home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume6 / sun-tetris1 / suntetris_pw.c < prev    next >
C/C++ Source or Header  |  1989-07-06  |  16KB  |  507 lines

  1. #ifndef lint
  2. static char sccsid[] = "@(#)suntetris_pw.c    1.14 3/23/89";
  3. #endif
  4. /*
  5.  *  Copyright 1989, Rick Iwamoto iwamoto@sun.com
  6.  *  Permission is given to copy and distribute for non-profit purposes. 
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <suntool/sunview.h>
  11. #include <suntool/canvas.h>
  12. #include "suntetris.h"
  13. #include <pwd.h>
  14. #include <unistd.h>
  15.  
  16. extern Canvas canvas;
  17. static Pixwin *pw;
  18. static Pixfont *bigfont;
  19. static Pixrect *savepr;
  20. static int incolor;
  21. static int boardmap[BOARDWIDTH][BOARDHEIGHT];
  22.  
  23. typedef
  24. struct figure  {
  25.     int x[4], y[4];
  26. } Figure;
  27.  
  28. static Figure fig1a = { { 2, 1, 0, 0 }, { 2, 2, 2, 1 } };
  29. static Figure fig1b = { { 1, 1, 1, 0 }, { 0, 1, 2, 2 } };
  30. static Figure fig1c = { { 0, 1, 2, 2 }, { 1, 1, 1, 2 } };
  31. static Figure fig1d = { { 1, 1, 1, 2 }, { 2, 1, 0, 0 } };
  32. static Figure fig2a = { { 0, 1, 2, 2 }, { 2, 2, 2, 1 } };
  33. static Figure fig2b = { { 1, 1, 1, 0 }, { 2, 1, 0, 0 } };
  34. static Figure fig2c = { { 2, 1, 0, 0 }, { 1, 1, 1, 2 } };
  35. static Figure fig2d = { { 1, 1, 1, 2 }, { 0, 1, 2, 2 } };
  36. static Figure fig3a = { { 0, 1, 2, 1 }, { 2, 2, 2, 1 } };
  37. static Figure fig3b = { { 1, 1, 1, 0 }, { 2, 1, 0, 1 } };
  38. static Figure fig3c = { { 2, 1, 0, 1 }, { 1, 1, 1, 2 } };
  39. static Figure fig3d = { { 1, 1, 1, 2 }, { 0, 1, 2, 1 } };
  40. static Figure fig4a = { { 0, 1, 1, 2 }, { 1, 1, 2, 2 } };
  41. static Figure fig4b = { { 1, 1, 2, 2 }, { 2, 1, 1, 0 } };
  42. static Figure fig5a = { { 0, 1, 1, 2 }, { 2, 2, 1, 1 } };
  43. static Figure fig5b = { { 2, 2, 1, 1 }, { 2, 1, 1, 0 } };
  44. static Figure fig6a = { { 0, 1, 2, 3 }, { 1, 1, 1, 1 } };
  45. static Figure fig6b = { { 2, 2, 2, 2 }, { 3, 2, 1, 0 } };
  46. static Figure fig7 = { { 0, 1, 0, 1 }, { 1, 1, 2, 2 } };
  47.  
  48.  
  49. static Figure *figures[7][4] = {
  50.     { &fig1a, &fig1b, &fig1c, &fig1d },    /* backward L */
  51.     { &fig2a, &fig2b, &fig2c, &fig2d },    /* L */
  52.     { &fig3a, &fig3b, &fig3c, &fig3d },    /* T */
  53.     { &fig4a, &fig4b, &fig4a, &fig4b },    /* Z */
  54.     { &fig5a, &fig5b, &fig5a, &fig5b },    /* S */
  55.     { &fig6a, &fig6b, &fig6a, &fig6b },    /* I */
  56.     { &fig7, &fig7, &fig7, &fig7 }    /* Square block */
  57. };
  58.  
  59.  
  60. static bordercolor[8] =
  61.     { BLACK, GREEN, LTGREEN, VIOLET, RED, BLUE, YELLOW, CYAN };
  62. static fillcolor[8] =
  63.     { BLACK, RED, GREEN, RED, BLACK, VIOLET, RED, WHITE };
  64.  
  65. static short bwdata0[] = {    /* BLACK */
  66.     0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
  67.     0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF
  68. };
  69. mpr_static (bwblock0, BLOCKSIZE, BLOCKSIZE, 1, bwdata0);
  70. static short bwdata1[] = {    /* root middle */
  71.     0x0000,0x0000,0x2220,0x2220,0x0888,0x0888,0x2220,0x2220,
  72.     0x0888,0x0888,0x2220,0x2220,0x0888,0x0888,0x0000,0x0000
  73. };
  74. mpr_static (bwblock1, BLOCKSIZE, BLOCKSIZE, 1, bwdata1);
  75. static short bwdata2[] = {    /* 25 % middle */
  76.     0x0000,0x0000,0x0444,0x1110,0x0888,0x2220,0x0444,0x1110,
  77.     0x0888,0x2220,0x0444,0x1110,0x0888,0x2220,0x0000,0x0000
  78. };
  79. mpr_static (bwblock2, BLOCKSIZE, BLOCKSIZE, 1, bwdata2);
  80. static short bwdata3[] = {    /* 50 % middle */
  81.     0x0000,0x0000,0x2AA8,0x1554,0x2AA8,0x1554,0x2AA8,0x1554,
  82.     0x2AA8,0x1554,0x2AA8,0x1554,0x2AA8,0x1554,0x0000,0x0000
  83. };
  84. mpr_static (bwblock3, BLOCKSIZE, BLOCKSIZE, 1, bwdata3);
  85. static short bwdata4[] = {    /* 75 % middle */
  86.     0x0000,0x0000,0x3BB8,0x2EEC,0x3774,0x1DDC,0x3BB8,0x2EEC,
  87.     0x3774,0x1DDC,0x3BB8,0x2EEC,0x3774,0x1DDC,0x0000,0x0000
  88. };
  89. mpr_static (bwblock4, BLOCKSIZE, BLOCKSIZE, 1, bwdata4);
  90. static short bwdata5[] = {    /* horiz middle */
  91.     0x0000,0x0000,0x3FFC,0x0000,0x3FFC,0x0000,0x3FFC,0x0000,
  92.     0x3FFC,0x0000,0x3FFC,0x0000,0x3FFC,0x0000,0x0000,0x0000
  93. };
  94. mpr_static (bwblock5, BLOCKSIZE, BLOCKSIZE, 1, bwdata5);
  95. static short bwdata6[] = {    /* diag middle */
  96.     0x0000,0x0000,0x2490,0x1248,0x0924,0x2490,0x1248,0x0924,
  97.     0x2490,0x1248,0x0924,0x2490,0x1248,0x0924,0x0000,0x0000
  98. };
  99. mpr_static (bwblock6, BLOCKSIZE, BLOCKSIZE, 1, bwdata6);
  100. static short bwdata7[] = {    /* checker middle */
  101.     0x0000,0x0000,0x3330,0x3330,0x0CCC,0x0CCC,0x3330,0x3330,
  102.     0x0CCC,0x0CCC,0x3330,0x3330,0x0CCC,0x0CCC,0x0000,0x0000
  103. };
  104. mpr_static (bwblock7, BLOCKSIZE, BLOCKSIZE, 1, bwdata7);
  105. static Pixrect *bwblocks[8] = {
  106.     &bwblock0, &bwblock1, &bwblock2, &bwblock3, 
  107.     &bwblock4, &bwblock5, &bwblock6, &bwblock7
  108. };
  109.  
  110. #define BORDER 2
  111.  
  112. /* draw_block draws a single block according to color or black&white mode */
  113. #define draw_block(x,y,color) { \
  114.     if (incolor)  { \
  115.     pw_rop (pw, (x), (y), BLOCKSIZE, BLOCKSIZE, \
  116.         PIX_SRC | PIX_COLOR(bordercolor[color]), 0, 0, 0); \
  117.     pw_rop (pw, (x)+BORDER, (y)+BORDER, \
  118.         BLOCKSIZE-2*BORDER, BLOCKSIZE-2*BORDER, \
  119.         PIX_SRC | PIX_COLOR(fillcolor[color]), 0, 0, 0); \
  120.     } else \
  121.     pw_rop (pw, (x), (y), BLOCKSIZE, BLOCKSIZE, \
  122.         PIX_NOT(PIX_SRC), bwblocks[color], 0, 0); \
  123.     }
  124.     
  125.  
  126. /* draw_figure draws one of the 7 figures in the specified orientation
  127.    at the location on the canvas */
  128. void
  129. draw_figure (figno, orientation, pix_x, pix_y, color)
  130. int figno, orientation, pix_x, pix_y, color;
  131. {
  132.     int i;
  133.  
  134.     if (figno > 6 || orientation > 3)  exit (1);
  135.     pw_batch_on (pw);
  136.     for (i = 0; i < 4; i++)
  137.     draw_block (pix_x+(figures[figno][orientation]->x[i])*BLOCKSIZE,
  138.         pix_y+(figures[figno][orientation]->y[i])*BLOCKSIZE, color)
  139.     pw_batch_off (pw);
  140. }
  141.  
  142.  
  143. /* safe_move tells when the block will collide with another or when it
  144.    is at the border of the board */
  145. safe_move (figno, orientation, x, y)
  146. int figno, orientation, x, y;
  147. {
  148.     int i, xpos, ypos;
  149.  
  150.     for (i = 0; i < 4; i++)  {
  151.     xpos = x+figures[figno][orientation]->x[i];
  152.     ypos = y+figures[figno][orientation]->y[i];
  153.     if (xpos < 0 || xpos >= BOARDWIDTH || ypos < 0 || ypos >= BOARDHEIGHT
  154.         || boardmap[xpos][ypos] != 0)  return (0);
  155.     }
  156.     return (1);
  157. }
  158.  
  159.  
  160. /* mark_board logs the specified figure on the boardmap, which keeps track
  161.    of all pieces which have come to rest */
  162. void
  163. mark_board (figno, orientation, x, y)
  164. int figno, orientation, x, y;
  165. {
  166.     int i, xpos, ypos;
  167.  
  168.     for (i = 0; i < 4; i++)  {
  169.     xpos = x+figures[figno][orientation]->x[i];
  170.     ypos = y+figures[figno][orientation]->y[i];
  171.     boardmap[xpos][ypos] = 1;
  172.     }
  173. }
  174.  
  175.  
  176. static struct timeval delay_50ms = { 0, 50000 };
  177.  
  178. /* reduce_rows checks for solid blocks across rows on the board,
  179.    flashes the rows to be deleted, then deletes them from the board
  180.    as well as the boardmap */
  181. reduce_rows (y)
  182. int y;
  183. {
  184.     int i, j, skip = 0, reducing = 0;
  185.     static int reduce[BOARDHEIGHT] = {
  186.         0, 0, 0, 0, 0,
  187.         0, 0, 0, 0, 0,
  188.         0, 0, 0, 0, 0,
  189.         0, 0, 0, 0, 0 };
  190.  
  191.     /* check for solid rows */
  192.     /* log all of the rows which need to be deleted into reduce[] */
  193.     /* At most 4 rows can be deleted at one time */
  194.     for (j = y+3; j >= y; j--)  {
  195.     if (j >= BOARDHEIGHT)  continue;
  196.         /* for some blocks j can be past bottom */
  197.     reduce[j] = 1;
  198.     for (i = 0; i < BOARDWIDTH && reduce[j]; i++)
  199.         reduce[j] &= boardmap[i][j];
  200.     reducing |= reduce[j];
  201.     if (reduce[j])    /* save any rows-to-be-reduced for flashing */
  202.         pw_read (savepr, 0, (j-y)*BLOCKSIZE, BOARDWIDTH*BLOCKSIZE,
  203.         BLOCKSIZE, PIX_SRC, pw, BOARD_X, BOARD_Y+j*BLOCKSIZE);
  204.     }
  205.     if (!reducing)  return (0);
  206.     select (1, 0, 0, 0, &delay_50ms);
  207.     for (i = 0; i < 3; i++)  {    /* flash rows 3 times */
  208.     for (j = y+3; j >= y; j--)  {
  209.         if (j < BOARDHEIGHT && reduce[j])    /* erase rows */
  210.         pw_writebackground (pw, BOARD_X, BOARD_Y+j*BLOCKSIZE,
  211.             BOARDWIDTH*BLOCKSIZE, BLOCKSIZE, PIX_CLR);
  212.     }
  213.     select (1, 0, 0, 0, &delay_50ms);
  214.     for (j = y+3; j >= y; j--)  {
  215.         if (j < BOARDHEIGHT && reduce[j])    /* restore rows */
  216.         pw_rop (pw, BOARD_X, BOARD_Y+j*BLOCKSIZE, BOARDWIDTH*BLOCKSIZE,
  217.             BLOCKSIZE, PIX_SRC, savepr, 0, (j-y)*BLOCKSIZE);
  218.     }
  219.     select (1, 0, 0, 0, &delay_50ms);
  220.     }
  221.     pw_batch_on (pw);
  222.     /*  next, starting from the bottom of the board,
  223.     we do nothing if the row is to be deleted,
  224.     we copy the non-full row down by how many have been deleted
  225.     under it */
  226.     for (j = y+3; j >= 0; j--)  {    /* remove rows */
  227.     if (j >= BOARDHEIGHT)  continue;
  228.     if (reduce[j])  {
  229.         skip++;
  230.         reduce[j] = 0;
  231.     }
  232.     else if (skip > 0)  {
  233.         for (i = 0; i < BOARDWIDTH; i++)
  234.         boardmap[i][j+skip] = boardmap[i][j];
  235.         pw_copy (pw, BOARD_X, BOARD_Y+(j+skip)*BLOCKSIZE,
  236.         BLOCKSIZE*BOARDWIDTH, BLOCKSIZE,        /* one row */
  237.         PIX_SRC, pw, BOARD_X, BOARD_Y+j*BLOCKSIZE);
  238.     }
  239.     }
  240.     /* shift remaining blocks down by number of deleted rows */
  241.     pw_writebackground (pw, BOARD_X, BOARD_Y, BLOCKSIZE*BOARDWIDTH,
  242.     BLOCKSIZE*skip, PIX_CLR);
  243.     pw_batch_off (pw);
  244.     return (skip);
  245. }
  246.  
  247. #define BORDER_PIXOP (PIX_SRC | PIX_COLOR(RED))
  248. #define TEXT_PIXOP (PIX_SRC | PIX_COLOR(YELLOW))
  249.  
  250. /* close_board does the closing door effect when the game is over */
  251. void
  252. close_board ()
  253. {
  254.     int i, j;
  255.     static struct timeval delay_100ms = { 0, 100000 };
  256.  
  257.     for (i = 0; i < BOARDHEIGHT; i++)        /* clear boardmap */
  258.     for (j = 0; j < BOARDWIDTH; j++)  boardmap[j][i] = 0;
  259.     select (1, 0, 0, 0, &delay_100ms);
  260.     for (i = 0; i < BOARDHEIGHT/2; i++)  {
  261.     pw_batch_on (pw);
  262.     for (j = 0; j < BOARDWIDTH; j++)  {
  263.         draw_block (BOARD_X+j*BLOCKSIZE, BOARD_Y+i*BLOCKSIZE, 2)
  264.         draw_block (BOARD_X+j*BLOCKSIZE,
  265.         BOARD_Y+(BOARDHEIGHT-1-i)*BLOCKSIZE, 2);
  266.     }
  267.     pw_batch_off (pw);
  268.     select (1, 0, 0, 0, &delay_100ms);
  269.     }
  270.     pw_text (pw, BOARD_X+2*BLOCKSIZE, BOARD_Y+BLOCKSIZE*BOARDHEIGHT/2,
  271.     TEXT_PIXOP, bigfont, "GAME OVER");
  272.     select (1, 0, 0, 0, &delay_100ms);
  273. }
  274.  
  275.  
  276. void draw_score (lines, score, level)
  277. int lines, score, level;
  278. {
  279.     char s[10];
  280.  
  281.     pw_batch_on (pw);
  282.     sprintf (s, "%6d", lines);
  283.     pw_text (pw, 100, LINES_Y, TEXT_PIXOP, bigfont, s);
  284.     sprintf (s, "%6d", score);
  285.     pw_text (pw, 100, SCORE_Y, TEXT_PIXOP, bigfont, s);
  286.     sprintf (s, "%6d", level);
  287.     pw_text (pw, 100, LEVEL_Y, TEXT_PIXOP, bigfont, s);
  288.     pw_batch_off (pw);
  289. }
  290.  
  291.  
  292. void
  293. draw_board ()
  294. {
  295.     pw_batch_on (pw);
  296.     pw_writebackground (pw, 0, 0, pw->pw_pixrect->pr_width,
  297.     pw->pw_pixrect->pr_height, PIX_CLR);    /* clear screen */
  298.     pw_writebackground (pw, BOARD_X-4, BOARD_Y-4, 2, BOARDHEIGHT*BLOCKSIZE+8,
  299.     BORDER_PIXOP);
  300.     pw_writebackground (pw, BOARD_X-4, BOARD_Y-4, BOARDWIDTH*BLOCKSIZE+8, 2,
  301.     BORDER_PIXOP);
  302.     pw_writebackground (pw, BOARD_X+BOARDWIDTH*BLOCKSIZE+2, BOARD_Y-4,
  303.     2, BOARDHEIGHT*BLOCKSIZE+8, BORDER_PIXOP);
  304.     pw_writebackground (pw, BOARD_X-4, BOARD_Y+BOARDHEIGHT*BLOCKSIZE+2,
  305.     BOARDWIDTH*BLOCKSIZE+8, 2, BORDER_PIXOP);
  306.     pw_ttext (pw, 20, SCORE_Y, TEXT_PIXOP, bigfont, "SCORE");
  307.     pw_ttext (pw, 20, LINES_Y, TEXT_PIXOP, bigfont, "LINES");
  308.     pw_ttext (pw, 20, LEVEL_Y, TEXT_PIXOP, bigfont, "LEVEL");
  309.     pw_batch_off (pw);
  310. }
  311.  
  312.  
  313. /* init_pw gets the pixwin from the canvas and sets up the colormap */
  314. void
  315. init_pw (forcebw)
  316. int forcebw;
  317. {
  318.     u_char red[TETRISCMSSIZE], green[TETRISCMSSIZE], blue[TETRISCMSSIZE];
  319.  
  320.     bigfont = pf_open ("/usr/lib/fonts/fixedwidthfonts/gallant.r.19");
  321.     pw = (Pixwin *) window_get (canvas, WIN_PIXWIN);
  322.     incolor = (pw->pw_pixrect->pr_depth == 8);
  323.     if (forcebw)  incolor = 0;
  324.     tetris_cms(red, green, blue)
  325.     pw_setcmsname (pw, "suntetris");
  326.     pw_putcolormap (pw, 0, TETRISCMSSIZE, red, green, blue);
  327.     pw = canvas_pixwin (canvas);
  328.     pw_setcmsname (pw, "suntetris");
  329.     pw_putcolormap (pw, 0, TETRISCMSSIZE, red, green, blue);
  330.     savepr = mem_create (BOARDWIDTH*BLOCKSIZE, 4*BLOCKSIZE,
  331.          incolor?8:1);
  332. }
  333.  
  334.  
  335. /* rand_blocks draws a random assortment of blocks to the specified height
  336.    on the board and logs them into the boardmap */
  337. void
  338. rand_blocks (height)
  339. int height;
  340. {
  341.     int x, y, r;
  342.  
  343.     pw_batch_on (pw);
  344.     for (y = BOARDHEIGHT-height; y < BOARDHEIGHT; y++)  {
  345.     for (x = 0; x < BOARDWIDTH; x ++)  {
  346.         r = random ();
  347.         if (r % 4 == 0)  {
  348.         boardmap[x][y] = 1;
  349.         draw_block (BOARD_X+x*BLOCKSIZE,
  350.             BOARD_Y+y*BLOCKSIZE, (r/4) % 7 + 1)
  351.         }
  352.     }
  353.     }
  354.     pw_batch_off (pw);
  355. }
  356.  
  357.  
  358. #define BOXSIZE 32
  359. #define CHOICE_PIXOP PIX_NOT(PIX_SRC)
  360. #define CADJX 10
  361. #define CADJY BOXSIZE-8
  362. #define LVX 50
  363. #define HTX 260
  364. #define LVY BOARD_Y+10
  365. #define HTY BOARD_Y+10
  366.  
  367. /* display_choices draws the level selection and height selection boxes */
  368. void
  369. display_choices ()
  370. {
  371.     int i;
  372.  
  373.     pw_batch_on (pw);
  374.     pw_writebackground (pw, 0, 0, pw->pw_pixrect->pr_width,
  375.     pw->pw_pixrect->pr_height, PIX_CLR);    /* clear screen */
  376.     pw_text (pw, LVX, BOARD_Y, PIX_SRC, bigfont, "LEVEL");
  377.     pw_text (pw, HTX, BOARD_Y, PIX_SRC, bigfont, "HEIGHT");
  378.     for (i = 0; i < 6; i++)
  379.     pw_writebackground (pw, LVX+i*BOXSIZE, LVY, 2, 2*BOXSIZE, PIX_SET);
  380.     for (i = 0; i < 4; i++)
  381.     pw_writebackground (pw, HTX+i*BOXSIZE, HTY, 2, 2*BOXSIZE, PIX_SET);
  382.     for (i = 0; i < 3; i++)  {
  383.     pw_writebackground (pw, LVX, LVY+i*BOXSIZE, 5*BOXSIZE+2, 2,
  384.         PIX_SET);
  385.     pw_writebackground (pw, HTX, HTY+i*BOXSIZE, 3*BOXSIZE+2, 2,
  386.         PIX_SET);
  387.     }
  388.     for (i = 0; i <= 9; i++)
  389.     pw_char (pw, LVX+(i%5)*32+CADJX, LVY+(i/5)*32+CADJY, PIX_SRC,
  390.         bigfont, i+'0');
  391.     pw_char (pw, HTX+CADJX, HTY+CADJY, PIX_SRC, bigfont, '0');
  392.     pw_char (pw, HTX+BOXSIZE+CADJX, HTY+CADJY, PIX_SRC, bigfont, '4');
  393.     pw_char (pw, HTX+2*BOXSIZE+CADJX, HTY+CADJY, PIX_SRC, bigfont, '7');
  394.     pw_text (pw, HTX-6+CADJX, HTY+BOXSIZE+CADJY, PIX_SRC, bigfont, "10");
  395.     pw_text (pw, HTX-6+BOXSIZE+CADJX, HTY+BOXSIZE+CADJY, PIX_SRC, bigfont,
  396.     "13");
  397.     pw_text (pw, HTX-6+2*BOXSIZE+CADJX, HTY+BOXSIZE+CADJY, PIX_SRC, bigfont,
  398.     ">>");
  399.     pw_batch_off (pw);
  400. }
  401.  
  402.  
  403. /* select_level inverts the box corresponding to the specified level */
  404. void
  405. select_level (level)
  406. int level;
  407. {
  408.     pw_copy (pw, LVX+(level%5)*BOXSIZE+2, LVY+(level/5)*BOXSIZE+2,
  409.     BOXSIZE-2, BOXSIZE-2, PIX_NOT(PIX_SRC),
  410.     pw, LVX+(level%5)*BOXSIZE+2, LVY+(level/5)*BOXSIZE+2);
  411. }
  412.  
  413.  
  414. /* select_height inverts the box corresponding to the specified height
  415.    position onscreen (0-5) not the actual height (0,4,7,10,13,>>) */
  416. void
  417. select_height (height)
  418. int height;
  419. {
  420.     pw_copy (pw, HTX+(height%3)*BOXSIZE+2, HTY+(height/3)*BOXSIZE+2,
  421.     BOXSIZE-2, BOXSIZE-2, PIX_NOT(PIX_SRC),
  422.     pw, HTX+(height%3)*BOXSIZE+2, HTY+(height/3)*BOXSIZE+2);
  423. }
  424.  
  425.  
  426. static struct highscores  {
  427.     char name[16];
  428.     int level, score;
  429. } highs[10] =  {
  430.     "nobody", 0, 0,
  431.     "nobody", 0, 0,
  432.     "nobody", 0, 0,
  433.     "nobody", 0, 0,
  434.     "nobody", 0, 0,
  435.     "nobody", 0, 0,
  436.     "nobody", 0, 0,
  437.     "nobody", 0, 0,
  438.     "nobody", 0, 0,
  439.     "nobody", 0, 0,
  440. };
  441.  
  442. #define SPACING 32
  443. #define HIGHS_X 30
  444. #define HIGHS_Y 80
  445.  
  446. void
  447. display_hs ()
  448. {
  449.     int i;
  450.     char s[8];
  451.  
  452.     pw_batch_on (pw);
  453.     pw_writebackground (pw, 0, 0, pw->pw_pixrect->pr_width,
  454.     pw->pw_pixrect->pr_height, PIX_CLR);    /* clear screen */
  455.     pw_text (pw, HIGHS_X, HIGHS_Y-SPACING, PIX_SRC, bigfont, "NAME");
  456.     pw_text (pw, HIGHS_X+160, HIGHS_Y-SPACING, PIX_SRC, bigfont, "LEVEL");
  457.     pw_text (pw, HIGHS_X+270, HIGHS_Y-SPACING, PIX_SRC, bigfont, "SCORE");
  458.     for (i = 0; i < 10; i++)  {
  459.     pw_text (pw, HIGHS_X, HIGHS_Y+i*SPACING, PIX_SRC, bigfont,
  460.         highs[i].name);
  461.     pw_char (pw, HIGHS_X+180, HIGHS_Y+i*SPACING, PIX_SRC, bigfont,
  462.         highs[i].level+'0');
  463.     sprintf (s, "%5d", highs[i].score);
  464.     pw_text (pw, HIGHS_X+270, HIGHS_Y+i*SPACING, PIX_SRC, bigfont, s);
  465.     }
  466.     pw_batch_off (pw);
  467. }
  468.  
  469.  
  470. #ifndef HIGHSCOREFILE
  471. #define HIGHSCOREFILE suntetris.hs
  472. #endif HIGHSCOREFILE
  473.  
  474. /* The file locking here isn't foolproof */
  475. /* We have an unsecured highscore file */
  476. void
  477. update_hs (score, level)
  478. int score, level;
  479. {
  480.     FILE *fp;
  481.     int i, j;
  482.     struct passwd *passwd = getpwuid (getuid ());
  483.  
  484.     if ((fp = fopen (HIGHSCOREFILE, "r")) != NULL)  {    /* read old scores */
  485.     lockf (fileno (fp), F_LOCK, 0);
  486.     while (i < 10 && (fscanf(fp, "%s %d %d", highs[i].name,
  487.               &highs[i].level, &highs[i].score) != EOF))  i++;
  488.     fclose (fp);
  489.     }
  490.     for (i = 10; i > 0 && score > highs[i-1].score; i--) ;
  491.     if (i > 9)  return;
  492.     if ((fp = fopen (HIGHSCOREFILE, "w")) == NULL)  return;
  493.     lockf (fileno (fp), F_LOCK, 0);
  494.     for (j = 9; j > i; j--)  {
  495.     strcpy (highs[j].name, highs[j-1].name);
  496.     highs[j].level = highs[j-1].level;
  497.     highs[j].score = highs[j-1].score;
  498.     }
  499.     strcpy (highs[i].name, passwd->pw_name);
  500.     highs[i].level = level;
  501.     highs[i].score = score;
  502.     for (i = 0; i < 10; i++)
  503.     fprintf (fp, "%s %d %d\n", highs[i].name, highs[i].level,
  504.          highs[i].score);
  505.     fclose (fp);
  506. }
  507.