home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Games / ishido / ishido.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  23.1 KB  |  991 lines

  1. /*
  2.  * ishido.c - Ancient stone matching game.  
  3.  * 
  4.  * Authors:  John Sullivan, Amdahl Corporation (jjs40@cd.amdahl.com)
  5.  *           Sean Cummins, Amdahl Corporation (spc10@cd.amdahl.com)
  6.  * 
  7.  * "No matter how great your achievements or how stunning your defeats, over a
  8.  * billion Chinese couldn't care less."
  9.  * 
  10.  */
  11.  
  12. /****************************************************************************/
  13.  
  14. #include <stdio.h>
  15. #include <pwd.h>
  16. #include "gl.h"
  17.  
  18. /****************************************************************************/
  19.  
  20. #include "bitmap/hwood.bm"
  21. #include "bitmap/vwood.bm"
  22. #include "bitmap/atom.bm"
  23. #include "bitmap/dollar.bm"
  24. #include "bitmap/hammer.bm"
  25. #include "bitmap/maple.bm"
  26. #include "bitmap/smile.bm"
  27. #include "bitmap/star.bm"
  28.  
  29. /****************************************************************************/
  30.  
  31. #define TILE_WIDTH        50
  32. #define TILE_HEIGHT        50
  33. #define    BOARD_WIDTH        12
  34. #define BOARD_HEIGHT        8
  35. #define MARGIN_X        10
  36. #define MARGIN_Y        10
  37.  
  38. /****************************************************************************/
  39.  
  40. #define BOARD_X        MARGIN_X
  41. #define BOARD_Y        MARGIN_Y
  42. #define BOARD_W        (TILE_WIDTH*BOARD_WIDTH)
  43. #define BOARD_H        (TILE_HEIGHT*BOARD_HEIGHT)
  44. #define TILE_X(x)    (BOARD_X+TILE_WIDTH*(x))
  45. #define TILE_Y(y)    (BOARD_Y+TILE_HEIGHT*(y))
  46. #define SCORE_X        MARGIN_X*2+BOARD_W
  47. #define SCORE_Y        BOARD_Y
  48. #define    SCORE_W        20*GL_FONT_WIDTH
  49. #define SCREEN_W    MARGIN_X*3+BOARD_W+SCORE_W
  50. #define SCREEN_H    MARGIN_Y*2+BOARD_H
  51. #define QUITB_H        25
  52. #define QUITB_W        SCORE_W
  53. #define QUITB_X        SCORE_X
  54. #define QUITB_Y        SCREEN_H-MARGIN_Y-QUITB_H-1
  55.  
  56. #define RULEB_H        25
  57. #define RULEB_W        SCORE_W
  58. #define RULEB_X        SCORE_X
  59. #define RULEB_Y        QUITB_Y-MARGIN_Y-GAMEB_H
  60.  
  61. #define GAMEB_H        25
  62. #define GAMEB_W        SCORE_W
  63. #define GAMEB_X        SCORE_X
  64. #define GAMEB_Y        RULEB_Y-MARGIN_Y-GAMEB_H
  65. #define SCORE_H        GAMEB_Y-MARGIN_Y-SCORE_Y
  66.  
  67. /****************************************************************************/
  68.  
  69. #define IS_INTERIOR(x,y) ((x > 0) && (x < BOARD_WIDTH-1) && \
  70.               (y > 0) && (y < BOARD_HEIGHT-1))
  71.  
  72. /****************************************************************************/
  73.  
  74. #define TILE_SHAPES        6
  75. #define DECK_SIZE        TILE_SHAPES*TILE_SHAPES*2
  76.  
  77. #define TILE_EMPTY         -1
  78. typedef int     TILE;
  79.  
  80. #define TILE_COLOR(x)     ((x)%TILE_SHAPES)
  81. #define TILE_SHAPE(x)     ((x)/TILE_SHAPES)
  82.  
  83. /****************************************************************************/
  84.  
  85. #ifndef HIGH_SCORE_FILE
  86. #define HIGH_SCORE_FILE        "ishido_scores"
  87. #endif
  88.  
  89. #define NUM_HIGH_SCORES     20
  90.  
  91. typedef struct HIGH_SCORE_STRUCT {
  92.     char            name[12];
  93.     int             score;
  94.     int             fourways;
  95.     int             tiles;
  96. }               HIGH_SCORE;
  97.  
  98. /****************************************************************************/
  99.  
  100. extern void     quit_button();
  101. extern void     new_game_button();
  102. extern void     end_game_button();
  103. extern void     rule_button();
  104.  
  105. /****************************************************************************/
  106.  
  107. #define streq(a,b) (strcmp(a,b)==0)
  108.  
  109. /****************************************************************************/
  110.  
  111. GL_PIXEL        pix_bg;
  112. GL_PIXEL        pix_border;
  113. GL_PIXEL        pix_text;
  114. GL_PIXEL        pix_wood_fg[2];
  115. GL_PIXEL        pix_wood_bg[2];
  116. GL_PIXEL        pix_tile_bg[TILE_SHAPES];
  117. GL_PIXEL        pix_tile_fg;
  118. GL_PIXEL    pix_highlight;
  119.  
  120. GL_BITMAP       bitmap_wood[2];
  121. GL_BITMAP       bitmap_tile[TILE_SHAPES];
  122.  
  123. GB_BUTTON       button[3];
  124.  
  125. /****************************************************************************/
  126.  
  127. HIGH_SCORE      high_score[NUM_HIGH_SCORES];
  128.  
  129. int             game_over;
  130. int             rule_screen;
  131.  
  132. TILE            board[BOARD_WIDTH][BOARD_HEIGHT];
  133.  
  134. int             num_deck_tiles;
  135. TILE            deck[DECK_SIZE];
  136.  
  137. int             score;
  138. int             fourways;
  139. int        bonehead;
  140. int         silent;
  141.  
  142. int        num_possible;
  143. int        possible_x[BOARD_WIDTH*BOARD_HEIGHT];
  144. int        possible_y[BOARD_WIDTH*BOARD_HEIGHT];
  145.  
  146. /****************************************************************************/
  147.  
  148. int
  149. int_rand(m)
  150.     int             m;
  151. {
  152.     int             v;
  153.  
  154.     v = (lrand48() % m);
  155.     return (v);
  156. };
  157.  
  158. /****************************************************************************/
  159.  
  160. void
  161. seed_rand()
  162. {
  163.     srand48(time(NULL));
  164. };
  165.  
  166. /****************************************************************************/
  167.  
  168. char           *
  169. get_user_name()
  170. {
  171.     int             uid;
  172.     struct passwd  *passwd;
  173.  
  174.     uid = geteuid();
  175.     passwd = getpwuid(uid);
  176.     return (passwd->pw_name);
  177. };
  178.  
  179. /****************************************************************************/
  180.  
  181. void
  182. deck_init()
  183. {
  184.     int             i, j, n, c;
  185.     TILE            tile;
  186.  
  187.     num_deck_tiles = DECK_SIZE;
  188.     for (i = 0; i < DECK_SIZE; i++) {
  189.         deck[i] = i / 2;
  190.     };
  191.     for (i = 0; i < DECK_SIZE - 1; i++) {
  192.         n = int_rand(DECK_SIZE - i - 1);
  193.         tile = deck[i + n + 1];
  194.         deck[i + n + 1] = deck[i];
  195.         deck[i] = tile;
  196.     };
  197.     i = 0;
  198.     c = 0;
  199.     while (c < TILE_SHAPES) {
  200.         n = 0;
  201.         for (j = 0; j < c; j++) {
  202.             if (TILE_COLOR(deck[i]) == TILE_COLOR(deck[j])) {
  203.                 n++;
  204.             };
  205.             if (TILE_SHAPE(deck[i]) == TILE_SHAPE(deck[j])) {
  206.                 n++;
  207.             };
  208.         };
  209.         if (n == 0) {
  210.             tile = deck[c];
  211.             deck[c] = deck[i];
  212.             deck[i] = tile;
  213.             c++;
  214.         };
  215.         i++;
  216.     };
  217. };
  218.  
  219. /****************************************************************************/
  220.  
  221. void
  222. deck_print()
  223. {
  224.     int             i, c;
  225.  
  226.     printf("num_deck_tiles = %d:\n", num_deck_tiles);
  227.  
  228.     c = 0;
  229.     for (i = 0; i < num_deck_tiles; i++) {
  230.         printf("%4d ", deck[i]);
  231.         c++;
  232.         if (c == 14) {
  233.             printf("\n");
  234.             c = 0;
  235.         };
  236.     };
  237.     printf("\n");
  238. };
  239.  
  240. /****************************************************************************/
  241.  
  242. TILE
  243. deck_take_tile()
  244. {
  245.     int             i;
  246.     TILE            tile;
  247.  
  248.     tile = deck[0];
  249.  
  250.     for (i = 0; i < num_deck_tiles - 1; i++) {
  251.         deck[i] = deck[i + 1];
  252.     };
  253.     num_deck_tiles = num_deck_tiles - 1;
  254.     return (tile);
  255. };
  256.  
  257. /****************************************************************************/
  258.  
  259. void
  260. board_init()
  261. {
  262.     int             i, j;
  263.  
  264.     for (j = 0; j < BOARD_HEIGHT; j++) {
  265.         for (i = 0; i < BOARD_WIDTH; i++) {
  266.             board[i][j] = TILE_EMPTY;
  267.         };
  268.     };
  269.     board[0][0] = deck_take_tile();
  270.     board[0][7] = deck_take_tile();
  271.     board[11][0] = deck_take_tile();
  272.     board[11][7] = deck_take_tile();
  273.     board[5][3] = deck_take_tile();
  274.     board[6][4] = deck_take_tile();
  275. };
  276.  
  277. /****************************************************************************/
  278.  
  279. TILE
  280. board_get_tile(x, y)
  281.     int             x, y;
  282. {
  283.     if ((x < 0) || (x >= BOARD_WIDTH)) {
  284.         return (TILE_EMPTY);
  285.     };
  286.     if ((y < 0) || (y >= BOARD_HEIGHT)) {
  287.         return (TILE_EMPTY);
  288.     };
  289.     return (board[x][y]);
  290. };
  291.  
  292. /****************************************************************************/
  293.  
  294. int
  295. board_adjacent_tiles(tile, x, y, c, s)
  296.     TILE            tile;
  297.     int             x, y;
  298.     int            *c;
  299.     int            *s;
  300. {
  301.     int             i;
  302.     int             num;
  303.     TILE            adjtile[4];
  304.  
  305.     adjtile[0] = board_get_tile(x - 1, y);
  306.     adjtile[1] = board_get_tile(x + 1, y);
  307.     adjtile[2] = board_get_tile(x, y - 1);
  308.     adjtile[3] = board_get_tile(x, y + 1);
  309.     num = 0;
  310.     for (i = 0; i < 4; i++) {
  311.         if (adjtile[i] != TILE_EMPTY) {
  312.             c[num] = (TILE_COLOR(tile) == TILE_COLOR(adjtile[i]));
  313.             s[num] = (TILE_SHAPE(tile) == TILE_SHAPE(adjtile[i]));
  314.             num++;
  315.         };
  316.     };
  317.     return (num);
  318. };
  319.  
  320. /****************************************************************************/
  321.  
  322. int
  323. board_can_place_tile(x, y)
  324.     int             x, y;
  325. {
  326.     int             num;
  327.     TILE            tile;
  328.     int             c[4], s[4];
  329.  
  330.     if (board[x][y] != TILE_EMPTY) {
  331.         return (0);
  332.     };
  333.     tile = deck[0];
  334.     num = board_adjacent_tiles(tile, x, y, c, s);
  335.     if (num == 1) {
  336.         if (s[0] || c[0])
  337.             return (num);
  338.     };
  339.     if (num == 2) {
  340.         if (s[0] && c[1])
  341.             return (num);
  342.         if (s[1] && c[0])
  343.             return (num);
  344.     };
  345.     if (num == 3) {
  346.         if (s[0] && c[1] && c[2])
  347.             return (num);
  348.         if (s[1] && c[2] && c[0])
  349.             return (num);
  350.         if (s[2] && c[0] && c[1])
  351.             return (num);
  352.         if (c[0] && s[1] && s[2])
  353.             return (num);
  354.         if (c[1] && s[2] && s[0])
  355.             return (num);
  356.         if (c[2] && s[0] && s[1])
  357.             return (num);
  358.     };
  359.     if (num == 4) {
  360.         if (s[0] && s[1] && c[2] && c[3])
  361.             return (num);
  362.         if (s[0] && s[2] && c[1] && c[3])
  363.             return (num);
  364.         if (s[0] && s[3] && c[1] && c[2])
  365.             return (num);
  366.         if (s[1] && s[2] && c[0] && c[3])
  367.             return (num);
  368.         if (s[1] && s[3] && c[0] && c[2])
  369.             return (num);
  370.         if (s[2] && s[3] && c[0] && c[1])
  371.             return (num);
  372.     };
  373.     return (0);
  374. };
  375.  
  376. /****************************************************************************/
  377.  
  378. void board_update_possible_moves()
  379. {
  380.     int i,j;
  381.     int c;
  382.     
  383.     num_possible = 0;
  384.     if (num_deck_tiles == 0) {
  385.         return;
  386.     };
  387.     for (j = 0; j < BOARD_HEIGHT; j++) {
  388.             for (i = 0; i < BOARD_WIDTH; i++) {
  389.             if (board_can_place_tile(i,j)) {
  390.                 possible_x[num_possible] = i;
  391.                 possible_y[num_possible] = j;
  392.                 num_possible++;
  393.             };
  394.         };
  395.     };
  396. };
  397.  
  398. /****************************************************************************/
  399.  
  400. int             four_way_bonus[] = {
  401.     25, 50, 100, 200, 400, 600, 800, 1000, 5000, 10000, 25000, 50000
  402. };
  403.  
  404. /****************************************************************************/
  405.  
  406. int
  407. board_place_tile(x, y)
  408.     int             x, y;
  409. {
  410.     int             num;
  411.  
  412.     if (num_deck_tiles == 0) {
  413.         return (0);
  414.     };
  415.     num = board_can_place_tile(x, y);
  416.     if (num == 0) {
  417.         return (0);
  418.     };
  419.     board[x][y] = deck_take_tile();
  420.     if (IS_INTERIOR(x, y)) {
  421.         if (num == 1)
  422.             score = score + 1;
  423.         if (num == 2)
  424.             score = score + 2;
  425.         if (num == 3)
  426.             score = score + 4;
  427.         if (num == 4) {
  428.             score = score + 8;
  429.             if (fourways < 12) {
  430.                 score = score + four_way_bonus[fourways];
  431.             } else {
  432.                 score = score + four_way_bonus[11];
  433.             };
  434.             fourways++;
  435.         };
  436.     };
  437.     return (1);
  438. };
  439.  
  440. /****************************************************************************/
  441.  
  442. void
  443. high_score_load()
  444. {
  445.     FILE           *f;
  446.     int             i;
  447.  
  448.     f = fopen(HIGH_SCORE_FILE, "r");
  449.     if (f != NULL) {
  450.         fread(high_score, sizeof(HIGH_SCORE), NUM_HIGH_SCORES, f);
  451.     } else {
  452.         for (i = 0; i < NUM_HIGH_SCORES; i++) {
  453.             strcpy(high_score[i].name, "nobody");
  454.             high_score[i].score = 0;
  455.             high_score[i].fourways = 0;
  456.             high_score[i].tiles = 66;
  457.         };
  458.     };
  459.     fclose(f);
  460. };
  461.  
  462. /****************************************************************************/
  463.  
  464. void
  465. high_score_save()
  466. {
  467.     FILE           *f;
  468.  
  469.     f = fopen(HIGH_SCORE_FILE, "w");
  470.     if (f != NULL) {
  471.         fwrite(high_score, sizeof(HIGH_SCORE), NUM_HIGH_SCORES, f);
  472.     };
  473.     fclose(f);
  474. };
  475.  
  476. /****************************************************************************/
  477.  
  478. void
  479. high_score_add(name, sc, fw, ti)
  480.     char           *name;
  481.     int             sc;
  482.     int             fw;
  483.     int             ti;
  484. {
  485.     int             i;
  486.     int             pos;
  487.  
  488.     high_score_load();
  489.     pos = NUM_HIGH_SCORES;
  490.     for (i = NUM_HIGH_SCORES - 1; i >= 0; i--) {
  491.         if (sc >= high_score[i].score) {
  492.             pos = i;
  493.         };
  494.     };
  495.     if (pos < NUM_HIGH_SCORES) {
  496.         for (i = NUM_HIGH_SCORES - 1; i > pos; i--) {
  497.             strcpy(high_score[i].name, high_score[i - 1].name);
  498.             high_score[i].score = high_score[i - 1].score;
  499.             high_score[i].fourways = high_score[i - 1].fourways;
  500.             high_score[i].tiles = high_score[i - 1].tiles;
  501.         };
  502.         strcpy(high_score[pos].name, name);
  503.         high_score[pos].score = sc;
  504.         high_score[pos].fourways = fw;
  505.         high_score[pos].tiles = ti;
  506.         high_score_save();
  507.     };
  508. };
  509.  
  510. /****************************************************************************/
  511.  
  512. void
  513. init_game_play()
  514. {
  515.     strcpy(button[0].label, "End Game");
  516.     button[0].event_fn = end_game_button;
  517.  
  518.     game_over = 0;
  519.     rule_screen = 0;
  520.  
  521.     seed_rand();
  522.     deck_init();
  523.     board_init();
  524.     board_update_possible_moves();
  525.  
  526.     score = 0;
  527.     fourways = 0;
  528. };
  529.  
  530. /****************************************************************************/
  531.  
  532. void
  533. init_game_over()
  534. {
  535.     strcpy(button[0].label, "New Game");
  536.     button[0].event_fn = new_game_button;
  537.  
  538.     high_score_load();
  539.  
  540.     game_over = 1;
  541.     rule_screen = 0;
  542. };
  543.  
  544. /****************************************************************************/
  545.  
  546. void
  547. init_game_end()
  548. {
  549.     char           *name;
  550.  
  551.     if (num_deck_tiles == 0)
  552.         score = score + 1000;
  553.     if (num_deck_tiles == 1)
  554.         score = score + 500;
  555.     if (num_deck_tiles == 2)
  556.         score = score + 100;
  557.     name = get_user_name();
  558.     high_score_add(name, score, fourways, num_deck_tiles);
  559. };
  560.  
  561. /****************************************************************************/
  562.  
  563. void
  564. init_game(argc, argv)
  565.    int argc;
  566.    char **argv;
  567. {
  568.     int i;
  569.     int help;
  570.  
  571.     pix_bg = gl_alloc_color("black");
  572.     pix_border = gl_alloc_color("red");
  573.     pix_text = gl_alloc_color("white");
  574.     pix_wood_fg[0] = gl_alloc_color("tan4");
  575.     pix_wood_fg[1] = gl_alloc_color("tan3");
  576.     pix_wood_bg[0] = gl_alloc_color("sienna4");
  577.     pix_wood_bg[1] = gl_alloc_color("sienna3");
  578.     pix_tile_fg = gl_alloc_color("black");
  579.     pix_tile_bg[0] = gl_alloc_color("red");
  580.     pix_tile_bg[1] = gl_alloc_color("green");
  581.     pix_tile_bg[2] = gl_alloc_color("skyblue1");
  582.     pix_tile_bg[3] = gl_alloc_color("yellow");
  583.     pix_tile_bg[4] = gl_alloc_color("mediumpurple1");
  584.     pix_tile_bg[5] = gl_alloc_color("pink");
  585.     pix_highlight = gl_alloc_color("magenta");
  586.  
  587.     bitmap_wood[0] = gl_load_bitmap(hwood_bits, hwood_width, hwood_height);
  588.     bitmap_wood[1] = gl_load_bitmap(vwood_bits, vwood_width, vwood_height);
  589.  
  590.     bitmap_tile[0] = gl_load_bitmap(atom_bits, atom_width, atom_height);
  591.     bitmap_tile[1] = gl_load_bitmap(dollar_bits, dollar_width, dollar_height);
  592.     bitmap_tile[2] = gl_load_bitmap(hammer_bits, hammer_width, hammer_height);
  593.     bitmap_tile[3] = gl_load_bitmap(maple_bits, maple_width, maple_height);
  594.     bitmap_tile[4] = gl_load_bitmap(smile_bits, smile_width, smile_height);
  595.     bitmap_tile[5] = gl_load_bitmap(star_bits, star_width, star_height);
  596.  
  597.     button[0].x = GAMEB_X;
  598.     button[0].y = GAMEB_Y;
  599.     button[0].w = GAMEB_W;
  600.     button[0].h = GAMEB_H;
  601.     button[0].border = pix_border;
  602.     button[0].background = pix_bg;
  603.     button[0].text = pix_text;
  604.  
  605.     button[1].x = RULEB_X;
  606.     button[1].y = RULEB_Y;
  607.     button[1].w = RULEB_W;
  608.     button[1].h = RULEB_H;
  609.     button[1].border = pix_border;
  610.     button[1].background = pix_bg;
  611.     button[1].text = pix_text;
  612.     strcpy(button[1].label, "Rules");
  613.     button[1].event_fn = rule_button;
  614.  
  615.     button[2].x = QUITB_X;
  616.     button[2].y = QUITB_Y;
  617.     button[2].w = QUITB_W;
  618.     button[2].h = QUITB_H;
  619.     button[2].border = pix_border;
  620.     button[2].background = pix_bg;
  621.     button[2].text = pix_text;
  622.     strcpy(button[2].label, "Quit");
  623.     button[2].event_fn = quit_button;
  624.  
  625.     num_possible = 0;
  626.  
  627.     bonehead = 0;
  628.     silent = 0;
  629.     help = 0;
  630.  
  631.     for (i = 1; i < argc; i++) {
  632.         if (streq(argv[i],"-bonehead")) {
  633.             bonehead = 1;
  634.         } else if (streq(argv[i],"-silent")) {
  635.             silent = 1;
  636.         } else if (streq(argv[i],"-h")) {
  637.             help = 1;
  638.         } else {
  639.             help = 1;
  640.         };
  641.     };
  642.  
  643.     if (help) {
  644.         printf("usage: ishido [-bonehead] [-silent]\n");
  645.         printf("       -bonehead       Shows possible moves.\n");
  646.         printf("       -silent         Turns off bell.\n");
  647.         printf("       -h              This message.\n");
  648.         gl_exit();
  649.     };
  650.  
  651.     init_game_play();
  652.     init_game_over();
  653. };
  654.  
  655. /****************************************************************************/
  656.  
  657. void
  658. draw_tile(x, y, tile)
  659.     int             x, y;
  660.     TILE            tile;
  661. {
  662.  
  663.     gl_set_fg(pix_tile_fg);
  664.     gl_set_bg(pix_tile_bg[TILE_COLOR(tile)]);
  665.     gl_draw_bitmap(bitmap_tile[TILE_SHAPE(tile)], x, y,
  666.                TILE_WIDTH, TILE_HEIGHT);
  667. };
  668.  
  669. /****************************************************************************/
  670.  
  671. void
  672. draw_board_tile(x, y)
  673.     int             x, y;
  674. {
  675.     TILE            tile;
  676.  
  677.     tile = board[x][y];
  678.     if (tile == TILE_EMPTY) {
  679.         gl_set_fg_bg(pix_wood_fg[IS_INTERIOR(x, y)],
  680.                  pix_wood_bg[IS_INTERIOR(x, y)]);
  681.         gl_draw_bitmap(bitmap_wood[(x + y) % 2],
  682.                    TILE_X(x), TILE_Y(y),
  683.                    TILE_WIDTH, TILE_HEIGHT);
  684.     } else {
  685.         draw_tile(TILE_X(x), TILE_Y(y), tile);
  686.     };
  687. };
  688.  
  689. /****************************************************************************/
  690.  
  691. void
  692. draw_board_highlight_tile(x, y)
  693.     int             x, y;
  694. {
  695.     gl_set_fg_bg(pix_highlight,
  696.              pix_wood_bg[IS_INTERIOR(x, y)]);
  697.     gl_draw_bitmap(bitmap_wood[(x + y) % 2],
  698.                    TILE_X(x), TILE_Y(y),
  699.                    TILE_WIDTH, TILE_HEIGHT);
  700. };
  701.  
  702. /****************************************************************************/
  703.  
  704. void draw_board_show_possible_moves()
  705. {
  706.     int i;
  707.  
  708.         for (i = 0; i < num_possible; i++) {
  709.         draw_board_highlight_tile(possible_x[i],possible_y[i]);
  710.     };
  711. };
  712.  
  713.  
  714. /****************************************************************************/
  715.  
  716. void
  717. draw_board_hide_possible_moves()
  718. {
  719.     int i;
  720.     
  721.     for (i = 0; i < num_possible; i++) {
  722.         draw_board_tile(possible_x[i], possible_y[i]);
  723.     };
  724. };
  725.  
  726. /****************************************************************************/
  727.  
  728. void
  729. draw_board()
  730. {
  731.     int             i, j;
  732.  
  733.     for (j = 0; j < BOARD_HEIGHT; j++) {
  734.         for (i = 0; i < BOARD_WIDTH; i++) {
  735.             draw_board_tile(i, j);
  736.         };
  737.     };
  738.     if (bonehead) {
  739.         draw_board_show_possible_moves();
  740.     };
  741. };
  742.  
  743. /****************************************************************************/
  744.  
  745. void
  746. draw_score()
  747. {
  748.     char            buf[128];
  749.  
  750.     gl_set_fg_bg(pix_text, pix_bg);
  751.     gu_draw_centered_text(SCORE_X + SCORE_W / 2,
  752.                   SCORE_Y + GL_FONT_HEIGHT * 1, "Ishido v1.0");
  753.     gu_draw_centered_text(SCORE_X + SCORE_W / 2,
  754.                   SCORE_Y + GL_FONT_HEIGHT * 3, "Score");
  755.     sprintf(buf, "%06d", score);
  756.     gu_draw_centered_text(SCORE_X + SCORE_W / 2,
  757.                   SCORE_Y + GL_FONT_HEIGHT * 4, buf);
  758.     gu_draw_centered_text(SCORE_X + SCORE_W / 2,
  759.                   SCORE_Y + GL_FONT_HEIGHT * 5, "4-Way Matches");
  760.     sprintf(buf, "%d", fourways);
  761.     gu_draw_centered_text(SCORE_X + SCORE_W / 2,
  762.                   SCORE_Y + GL_FONT_HEIGHT * 6, buf);
  763.     gu_draw_centered_text(SCORE_X + SCORE_W / 2,
  764.               SCORE_Y + GL_FONT_HEIGHT * 7, "Tiles Remaining");
  765.     sprintf(buf, "%02d", num_deck_tiles);
  766.     gu_draw_centered_text(SCORE_X + SCORE_W / 2,
  767.                   SCORE_Y + GL_FONT_HEIGHT * 8, buf);
  768.     if ((game_over) || (num_deck_tiles == 0)) {
  769.         gu_draw_centered_text(SCORE_X + SCORE_W / 2,
  770.             SCORE_Y + GL_FONT_HEIGHT * 10, "              ");
  771.         gu_draw_centered_text(SCORE_X + SCORE_W / 2,
  772.                 SCORE_Y + GL_FONT_HEIGHT * 11, "    ");
  773.         gu_draw_centered_text(SCORE_X + SCORE_W / 2,
  774.                 SCORE_Y + GL_FONT_HEIGHT * 12, "         ");
  775.         gl_set_fg_bg(pix_bg, pix_bg);
  776.         gl_fill_rect(SCORE_X + SCORE_W / 2 - TILE_WIDTH / 2,
  777.             SCORE_Y + GL_FONT_HEIGHT * 13, TILE_WIDTH, TILE_HEIGHT);
  778.     } else {
  779.         gu_draw_centered_text(SCORE_X + SCORE_W / 2,
  780.             SCORE_Y + GL_FONT_HEIGHT * 10, "Possible Moves");
  781.         if (bonehead) {
  782.             sprintf(buf, "%02d", num_possible);
  783.         } else {
  784.             if (num_possible > 0) {
  785.                 sprintf(buf,"Yes");
  786.             } else {
  787.                 sprintf(buf,"None ");
  788.             };
  789.         };
  790.         gu_draw_centered_text(SCORE_X + SCORE_W / 2,
  791.                 SCORE_Y + GL_FONT_HEIGHT * 11, buf);
  792.         gu_draw_centered_text(SCORE_X + SCORE_W / 2,
  793.                 SCORE_Y + GL_FONT_HEIGHT * 12, "Next Tile");
  794.         draw_tile(SCORE_X + SCORE_W / 2 - TILE_WIDTH / 2,
  795.               SCORE_Y + GL_FONT_HEIGHT * 13, deck[0]);
  796.     };
  797. };
  798.  
  799. /****************************************************************************/
  800.  
  801. int             rule_lines = 21;
  802. char           *rule_text[] = {
  803.     "There are 72 tiles, two of each combination of six colors and six shapes.",
  804.     "At the start of the game, there are six tiles on the board representing",
  805.     "each shape and color.  To place an additional tile on the board, you",
  806.     "must match at least one adjacent tile according to the following rules:",
  807.     "   - To match a single tile, you must match either the color or shape.",
  808.     "   - To match two tiles, you must match one shape and one color.",
  809.     "   - To match three tiles, you must match two colors and one shape OR two",
  810.     "     shapes and one color.",
  811.     "   - To match four tiles, you must match two colors and two shapes.",
  812.     "",
  813.     "Tiles placed on the interior (lighter) squares score points when placed,",
  814.     "according to the number of adjacent tiles that they match.",
  815.     "   - Matching one tile:    1 point.    - Matching three tiles:  4 points.",
  816.     "   - Matching two tiles:   2 points.   - Matching four tiles:   8 points.",
  817.     "",
  818.     "In addition to the regular score there is an increasing bonus for each",
  819.     "four-way match starting with 25 points for the first and continuing with",
  820.     "50, 100, 200, 400, 600, 800, 1000, 5000, 10000, and 50000 points.",
  821.     "",
  822.     "A bonus of 1000 points is awarded at the end of the game placing for all",
  823.     "72 tiles.  500 and 100 points are awarded for one and two tiles remaining."
  824. };
  825.  
  826. /****************************************************************************/
  827.  
  828. void
  829. draw_rule_screen()
  830. {
  831.     int             i;
  832.  
  833.     gl_set_fg(pix_bg);
  834.     gl_fill_rect(BOARD_X, BOARD_Y, BOARD_W, BOARD_H);
  835.     gl_set_fg_bg(pix_text, pix_bg);
  836.     gu_draw_centered_text(BOARD_X + BOARD_W / 2, BOARD_Y + GL_FONT_HEIGHT,
  837.                   "Rules");
  838.     for (i = 0; i < rule_lines; i++) {
  839.         gl_draw_text(BOARD_X + GL_FONT_WIDTH,
  840.                  BOARD_Y + GL_FONT_HEIGHT * (i + 2),
  841.                  rule_text[i]);
  842.     };
  843. };
  844.  
  845. /****************************************************************************/
  846.  
  847. void
  848. draw_high_scores()
  849. {
  850.     int             i;
  851.     char            buf[200];
  852.  
  853.     gl_set_fg(pix_bg);
  854.     gl_fill_rect(BOARD_X, BOARD_Y, BOARD_W, BOARD_H);
  855.     gl_set_fg_bg(pix_text, pix_bg);
  856.     gu_draw_centered_text(BOARD_X + BOARD_W / 2, BOARD_Y + GL_FONT_HEIGHT * 1,
  857.                   "-- Game Over --");
  858.     gu_draw_centered_text(BOARD_X + BOARD_W / 2, BOARD_Y + GL_FONT_HEIGHT * 2,
  859.                   "##  Name          Score  4-Ways  Tiles");
  860.     gu_draw_centered_text(BOARD_X + BOARD_W / 2, BOARD_Y + GL_FONT_HEIGHT * 3,
  861.                   "--------------------------------------");
  862.     for (i = 0; i < NUM_HIGH_SCORES; i++) {
  863.         sprintf(buf, "%2d  %-12s  %5d    %2d      %2d ", i + 1,
  864.             high_score[i].name, high_score[i].score,
  865.             high_score[i].fourways, high_score[i].tiles);
  866.         gu_draw_centered_text(BOARD_X + BOARD_W / 2,
  867.                    BOARD_Y + GL_FONT_HEIGHT * (i + 4), buf);
  868.     };
  869. };
  870.  
  871. /****************************************************************************/
  872.  
  873. void
  874. redraw()
  875. {
  876.     gl_set_fg_bg(pix_border, pix_bg);
  877.     gu_draw_border(BOARD_X, BOARD_Y, BOARD_W, BOARD_H, 2);
  878.     gu_draw_border(SCORE_X, SCORE_Y, SCORE_W, SCORE_H, 2);
  879.  
  880.     gl_set_fg(pix_bg);
  881.     gl_fill_rect(SCORE_X, SCORE_Y, SCORE_W, SCORE_H);
  882.     draw_score();
  883.  
  884.     gb_draw_buttons(3, button);
  885.  
  886.     if (rule_screen) {
  887.         draw_rule_screen();
  888.     } else if (game_over) {
  889.         draw_high_scores();
  890.     } else {
  891.         draw_board();
  892.     };
  893. };
  894.  
  895. /****************************************************************************/
  896.  
  897. void
  898. quit_button()
  899. {
  900.     if (!game_over) {
  901.         init_game_end();
  902.     };
  903.     gl_exit_main();
  904. };
  905.  
  906. /****************************************************************************/
  907.  
  908. void
  909. new_game_button()
  910. {
  911.     init_game_play();
  912.     redraw();
  913. };
  914.  
  915. /****************************************************************************/
  916.  
  917. void
  918. end_game_button()
  919. {
  920.     init_game_end();
  921.     init_game_over();
  922.     redraw();
  923. };
  924.  
  925. /****************************************************************************/
  926.  
  927. void
  928. rule_button()
  929. {
  930.     rule_screen = 1 - rule_screen;
  931.     redraw();
  932. };
  933.  
  934. /****************************************************************************/
  935.  
  936. void
  937. board_button(event)
  938.     GL_EVENT       *event;
  939. {
  940.     int             x, y;
  941.  
  942.     x = (event->x - BOARD_X) / TILE_WIDTH;
  943.     y = (event->y - BOARD_Y) / TILE_WIDTH;
  944.     if (board_place_tile(x, y)) {
  945.         if (bonehead) {
  946.                 draw_board_hide_possible_moves();
  947.         };
  948.         board_update_possible_moves();
  949.         draw_board_tile(x, y);
  950.         if (bonehead) {
  951.             draw_board_show_possible_moves();
  952.         };
  953.         draw_score();
  954.     } else if (silent == 0) {
  955.         gl_ring_bell();
  956.     };
  957. };
  958.  
  959. /****************************************************************************/
  960.  
  961. void
  962. event(event)
  963.     GL_EVENT       *event;
  964. {
  965.     if ((gb_button_event(event, 3, button) == GL_FALSE) && (!game_over)) {
  966.         if (gu_event_in_rect(event, BOARD_X, BOARD_Y, BOARD_W, BOARD_H)) {
  967.             board_button(event);
  968.         }
  969.     };
  970. };
  971.  
  972. /****************************************************************************/
  973.  
  974. main(argc, argv)
  975.     int             argc;
  976.     char           **argv;
  977. {
  978.  
  979.  
  980.     gl_init(argc, argv, SCREEN_W, SCREEN_H);
  981.  
  982.     gl_redraw_func(redraw);
  983.     gl_event_func(event);
  984.  
  985.     init_game(argc, argv);
  986.  
  987.     gl_start();
  988.     gl_main_loop();
  989.     gl_exit();
  990. };
  991.