home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format 115 / af115sub.adf / yahzee.lzx / yahzee / game.c < prev    next >
C/C++ Source or Header  |  1998-06-03  |  9KB  |  309 lines

  1. /*
  2.  * game.c
  3.  * ======
  4.  * Game functions.
  5.  *
  6.  * Copyright © 1994-1998 Håkan L. Younes (lorens@hem.passagen.se)
  7.  */
  8.  
  9. #include <math.h>
  10. #include <exec/types.h>
  11. #include <intuition/intuition.h>
  12. #include <intuition/gadgetclass.h>
  13. #include "rules.h"
  14. #include "layout.h"
  15. #include "draw.h"
  16. #include "game.h"
  17. #include "dice.h"
  18. #include "highscores.h"
  19.  
  20. #include <clib/gadtools_protos.h>
  21. #include <clib/intuition_protos.h>
  22.  
  23.  
  24. extern struct Window  *main_win;
  25. extern struct NewGadget   new_roll_gad;
  26. extern struct Gadget  die_gads[], *roll_gad, *disp_gad, *gt_gads;
  27. extern struct rules  *rules;
  28. extern UBYTE   num_players, chosen_num_players;
  29. extern UBYTE   chosen_gametype, chosen_scoring;
  30.  
  31. static UBYTE   rolls_left;
  32. static UBYTE   rounds_left;
  33. static UBYTE   last_choice, prev_rolls_left;
  34. static UBYTE   current_player;
  35. static UBYTE   die_values[MAX_NUM_DICE];
  36. static WORD    scoreboard[MAX_PLAYERS][MAX_LABELS];
  37. static UBYTE   possible_score[MAX_LABELS];
  38.  
  39.  
  40. static void
  41. end_of_game (void)
  42. {
  43.    register UBYTE   n;
  44.    register BYTE    m;
  45.    UBYTE   order[MAX_PLAYERS];
  46.    BOOL    new_high = FALSE;
  47.    
  48.    order[0] = 0;
  49.    
  50.    GT_SetGadgetAttrs (roll_gad, main_win, NULL,
  51.                       GA_Disabled, TRUE, TAG_DONE);
  52.    
  53.    for (n = 1; n < num_players; ++n)
  54.    {
  55.       order[n] = n;
  56.       for (m = n - 1; m >= 0; --m)
  57.       {
  58.          if (scoreboard[n][TOTAL] > scoreboard[order[m]][TOTAL] ||
  59.              (scoreboard[n][TOTAL] == scoreboard[order[m]][TOTAL] &&
  60.               !rules->labels[SAVED_ROLLS]) ||
  61.              (scoreboard[n][TOTAL] == scoreboard[order[m]][TOTAL] &&
  62.               rules->labels[SAVED_ROLLS] &&
  63.               scoreboard[n][SAVED_ROLLS] >= scoreboard[order[m]][SAVED_ROLLS]))
  64.          {
  65.             order[m + 1] = order[m];
  66.             order[m] = n;
  67.          }
  68.       }
  69.    }
  70.    draw_player_numbers (main_win->RPort, num_players, order[0]);
  71.    draw_chosen_score (main_win->RPort, rules,
  72.                       order[0], scoreboard[order[0]], TRUE);
  73.    
  74.    for (n = 0; n < num_players; ++n)
  75.    {
  76.       if (update_high_score (game_number (rules),
  77.                              order[n], scoreboard[order[n]][TOTAL],
  78.                              scoreboard[order[n]][SAVED_ROLLS]))
  79.       {
  80.          new_high = TRUE;
  81.       }
  82.    }
  83.    if (new_high)
  84.       display_high_scores (game_number (rules));
  85. }
  86.  
  87.  
  88. BOOL
  89. new_game (void)
  90. {
  91.    register UBYTE   n, m;
  92.    
  93.    rolls_left = 3;
  94.    current_player = 0;
  95.  
  96.    if (num_players != chosen_num_players ||
  97.        rules != &game_definition[chosen_gametype][chosen_scoring])
  98.    {
  99.       rules = &game_definition[chosen_gametype][chosen_scoring];
  100.       num_players = chosen_num_players;
  101.       if (!layout_display (main_win->WScreen, &main_win, rules, num_players))
  102.          return FALSE;
  103.    }
  104.    else
  105.    {
  106.       for (n = 0; n < rules->num_dice; ++n)
  107.          OffGadget (&die_gads[n], main_win, NULL);
  108.       GT_SetGadgetAttrs (roll_gad, main_win, NULL,
  109.                          GA_Disabled, FALSE, TAG_DONE);
  110.       GT_SetGadgetAttrs (disp_gad, main_win, NULL,
  111.                          GTNM_Number, rolls_left, TAG_DONE);
  112.    }
  113.    
  114.    rounds_left = 0;
  115.    for (n = 0; n < MAX_LABELS; ++n)
  116.    {
  117.       if (rules->labels[n] && n != UPPER_TOTAL && n != BONUS && n != TOTAL &&
  118.           n != SAVED_ROLLS)
  119.       {
  120.          ++rounds_left;
  121.       }
  122.    }
  123.    
  124.    for (n = 0; n < num_players; ++n)
  125.    {
  126.       for (m = 0; m < MAX_LABELS; ++m)
  127.       {
  128.          if (m == UPPER_TOTAL || m == BONUS || m == TOTAL || m == SAVED_ROLLS)
  129.             scoreboard[n][m] = 0;
  130.          else
  131.             scoreboard[n][m] = -1;
  132.       }
  133.    }
  134.    
  135.    reset_scoreboard (main_win->RPort, rules, num_players);
  136.    draw_player_numbers (main_win->RPort, num_players, current_player);
  137.    
  138.    return TRUE;
  139. }
  140.  
  141. void
  142. roll_dice (void)
  143. {
  144.    register UBYTE   n;
  145.    UWORD   pos;
  146.    BOOL   die_rolled = FALSE;
  147.    
  148.    for (n = 0; n < rules->num_dice; ++n)
  149.    {
  150.       if (die_gads[n].Flags & (GFLG_DISABLED | GFLG_SELECTED))
  151.       {
  152.          die_values[n] = drand48() * 6 + 1;
  153.          pos = RemoveGadget (main_win, &die_gads[n]);
  154.          die_gads[n].GadgetRender = &die_images[die_values[n]];
  155.          die_gads[n].Flags &= ~(GFLG_SELECTED | GFLG_DISABLED);
  156.          AddGadget (main_win, &die_gads[n], pos);
  157.          RefreshGList (&die_gads[n], main_win, NULL, 1);
  158.          die_rolled = TRUE;
  159.       }
  160.    }
  161.    
  162.    if (die_rolled)
  163.    {
  164.       if (rolls_left == 0)
  165.       {
  166.          if (--scoreboard[current_player][SAVED_ROLLS] == 0)
  167.          {
  168.             GT_SetGadgetAttrs (roll_gad, main_win, NULL,
  169.                                GA_Disabled, TRUE, TAG_DONE);
  170.          }
  171.       }
  172.       else if (--rolls_left == 0)
  173.       {
  174.          if (!(rules->labels[SAVED_ROLLS] &&
  175.              scoreboard[current_player][SAVED_ROLLS] > 0))
  176.          {
  177.             GT_SetGadgetAttrs (roll_gad, main_win, NULL,
  178.                                GA_Disabled, TRUE, TAG_DONE);
  179.          }
  180.       }
  181.       GT_SetGadgetAttrs (disp_gad, main_win, NULL,
  182.                          GTNM_Number, rolls_left, TAG_DONE);
  183.       (rules->calc_score) (die_values, possible_score);
  184.       draw_possible_score (main_win->RPort, rules, current_player,
  185.                            scoreboard[current_player], possible_score);
  186.    }
  187. }
  188.  
  189. UBYTE
  190. choose_score (
  191.    WORD   x,
  192.    WORD   y)
  193. {
  194.    register UBYTE   n;
  195.    BYTE   score_no = -1;
  196.    
  197.    if (die_gads[0].Flags & GFLG_DISABLED)
  198.       return 0;
  199.    
  200.    for (n = 0; score_no < 0 && n < MAX_LABELS; ++n)
  201.    {
  202.       if (rules->labels[n] &&
  203.           x >= board_grid[current_player + 1][n].left &&
  204.           x < board_grid[current_player + 1][n].left +
  205.               board_grid[current_player + 1][n].width &&
  206.           y >= board_grid[current_player + 1][n].top &&
  207.           y < board_grid[current_player + 1][n].top +
  208.               board_grid[current_player + 1][n].height)
  209.       {
  210.          score_no = n;
  211.       }
  212.    }
  213.    
  214.    if (scoreboard[current_player][score_no] == -1)
  215.    {
  216.       prev_rolls_left = rolls_left;
  217.       last_choice = score_no;
  218.       scoreboard[current_player][score_no] = possible_score[score_no];
  219.       scoreboard[current_player][TOTAL] += possible_score[score_no];
  220.       if (score_no < UPPER_TOTAL)
  221.       {
  222.          scoreboard[current_player][UPPER_TOTAL] +=
  223.                                                    possible_score[score_no];
  224.          if (scoreboard[current_player][UPPER_TOTAL] >= rules->bonus_limit &&
  225.              scoreboard[current_player][BONUS] == 0)
  226.          {
  227.             scoreboard[current_player][BONUS] = rules->bonus;
  228.             scoreboard[current_player][TOTAL] += rules->bonus;
  229.          }
  230.       }
  231.       if (rules->labels[SAVED_ROLLS])
  232.          scoreboard[current_player][SAVED_ROLLS] += rolls_left;
  233.       
  234.       draw_chosen_score (main_win->RPort, rules,
  235.                          current_player, scoreboard[current_player], FALSE);
  236.       for (n = 0; n < rules->num_dice; ++n)
  237.          OffGadget (&die_gads[n], main_win, NULL);
  238.       
  239.       rolls_left = 3;
  240.       ++current_player;
  241.       if (current_player == num_players)
  242.       {
  243.          current_player = 0;
  244.          --rounds_left;
  245.       }
  246.       if (current_player == 0 && rounds_left == 0)
  247.          end_of_game ();
  248.       else
  249.       {
  250.          draw_player_numbers (main_win->RPort, num_players, current_player);
  251.          GT_SetGadgetAttrs (roll_gad, main_win, NULL,
  252.                             GA_Disabled, FALSE, TAG_DONE);
  253.          GT_SetGadgetAttrs (disp_gad, main_win, NULL,
  254.                             GTNM_Number, rolls_left);
  255.       }
  256.    }
  257.    
  258.    return rounds_left;
  259. }
  260.  
  261. void
  262. undo_last_choice (void)
  263. {
  264.    register UBYTE   n;
  265.    
  266.    if (current_player == 0)
  267.    {
  268.       ++rounds_left;
  269.       current_player = num_players - 1;
  270.    }
  271.    else
  272.       --current_player;
  273.    
  274.    rolls_left = prev_rolls_left;
  275.    if (rules->labels[SAVED_ROLLS])
  276.       scoreboard[current_player][SAVED_ROLLS] -= rolls_left;
  277.    
  278.    scoreboard[current_player][last_choice] = -1;
  279.    scoreboard[current_player][TOTAL] -= possible_score[last_choice];
  280.    if (last_choice < UPPER_TOTAL)
  281.    {
  282.       scoreboard[current_player][UPPER_TOTAL] -= possible_score[last_choice];
  283.       if (scoreboard[current_player][UPPER_TOTAL] < rules->bonus_limit &&
  284.           scoreboard[current_player][BONUS] > 0)
  285.       {
  286.          scoreboard[current_player][TOTAL] -= rules->bonus;
  287.          scoreboard[current_player][BONUS] = 0;
  288.       }
  289.    }
  290.    
  291.    draw_player_numbers (main_win->RPort, num_players, current_player);
  292.    draw_chosen_score (main_win->RPort, rules,
  293.                       current_player, scoreboard[current_player], FALSE);
  294.    draw_possible_score (main_win->RPort, rules, current_player,
  295.                         scoreboard[current_player], possible_score);
  296.    
  297.    for (n = 0; n < rules->num_dice; ++n)
  298.       OnGadget (&die_gads[n], main_win, NULL);
  299.    if (!(rolls_left > 0 ||
  300.        (rules->labels[SAVED_ROLLS] &&
  301.         scoreboard[current_player][SAVED_ROLLS] > 0)))
  302.    {
  303.       GT_SetGadgetAttrs (roll_gad, main_win, NULL,
  304.                          GA_Disabled, TRUE, TAG_DONE);
  305.    }
  306.    GT_SetGadgetAttrs (disp_gad, main_win, NULL,
  307.                      GTNM_Number, rolls_left, TAG_DONE);
  308. }
  309.