home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format 115
/
af115sub.adf
/
yahzee.lzx
/
yahzee
/
game.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-06-03
|
9KB
|
309 lines
/*
* game.c
* ======
* Game functions.
*
* Copyright © 1994-1998 Håkan L. Younes (lorens@hem.passagen.se)
*/
#include <math.h>
#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include "rules.h"
#include "layout.h"
#include "draw.h"
#include "game.h"
#include "dice.h"
#include "highscores.h"
#include <clib/gadtools_protos.h>
#include <clib/intuition_protos.h>
extern struct Window *main_win;
extern struct NewGadget new_roll_gad;
extern struct Gadget die_gads[], *roll_gad, *disp_gad, *gt_gads;
extern struct rules *rules;
extern UBYTE num_players, chosen_num_players;
extern UBYTE chosen_gametype, chosen_scoring;
static UBYTE rolls_left;
static UBYTE rounds_left;
static UBYTE last_choice, prev_rolls_left;
static UBYTE current_player;
static UBYTE die_values[MAX_NUM_DICE];
static WORD scoreboard[MAX_PLAYERS][MAX_LABELS];
static UBYTE possible_score[MAX_LABELS];
static void
end_of_game (void)
{
register UBYTE n;
register BYTE m;
UBYTE order[MAX_PLAYERS];
BOOL new_high = FALSE;
order[0] = 0;
GT_SetGadgetAttrs (roll_gad, main_win, NULL,
GA_Disabled, TRUE, TAG_DONE);
for (n = 1; n < num_players; ++n)
{
order[n] = n;
for (m = n - 1; m >= 0; --m)
{
if (scoreboard[n][TOTAL] > scoreboard[order[m]][TOTAL] ||
(scoreboard[n][TOTAL] == scoreboard[order[m]][TOTAL] &&
!rules->labels[SAVED_ROLLS]) ||
(scoreboard[n][TOTAL] == scoreboard[order[m]][TOTAL] &&
rules->labels[SAVED_ROLLS] &&
scoreboard[n][SAVED_ROLLS] >= scoreboard[order[m]][SAVED_ROLLS]))
{
order[m + 1] = order[m];
order[m] = n;
}
}
}
draw_player_numbers (main_win->RPort, num_players, order[0]);
draw_chosen_score (main_win->RPort, rules,
order[0], scoreboard[order[0]], TRUE);
for (n = 0; n < num_players; ++n)
{
if (update_high_score (game_number (rules),
order[n], scoreboard[order[n]][TOTAL],
scoreboard[order[n]][SAVED_ROLLS]))
{
new_high = TRUE;
}
}
if (new_high)
display_high_scores (game_number (rules));
}
BOOL
new_game (void)
{
register UBYTE n, m;
rolls_left = 3;
current_player = 0;
if (num_players != chosen_num_players ||
rules != &game_definition[chosen_gametype][chosen_scoring])
{
rules = &game_definition[chosen_gametype][chosen_scoring];
num_players = chosen_num_players;
if (!layout_display (main_win->WScreen, &main_win, rules, num_players))
return FALSE;
}
else
{
for (n = 0; n < rules->num_dice; ++n)
OffGadget (&die_gads[n], main_win, NULL);
GT_SetGadgetAttrs (roll_gad, main_win, NULL,
GA_Disabled, FALSE, TAG_DONE);
GT_SetGadgetAttrs (disp_gad, main_win, NULL,
GTNM_Number, rolls_left, TAG_DONE);
}
rounds_left = 0;
for (n = 0; n < MAX_LABELS; ++n)
{
if (rules->labels[n] && n != UPPER_TOTAL && n != BONUS && n != TOTAL &&
n != SAVED_ROLLS)
{
++rounds_left;
}
}
for (n = 0; n < num_players; ++n)
{
for (m = 0; m < MAX_LABELS; ++m)
{
if (m == UPPER_TOTAL || m == BONUS || m == TOTAL || m == SAVED_ROLLS)
scoreboard[n][m] = 0;
else
scoreboard[n][m] = -1;
}
}
reset_scoreboard (main_win->RPort, rules, num_players);
draw_player_numbers (main_win->RPort, num_players, current_player);
return TRUE;
}
void
roll_dice (void)
{
register UBYTE n;
UWORD pos;
BOOL die_rolled = FALSE;
for (n = 0; n < rules->num_dice; ++n)
{
if (die_gads[n].Flags & (GFLG_DISABLED | GFLG_SELECTED))
{
die_values[n] = drand48() * 6 + 1;
pos = RemoveGadget (main_win, &die_gads[n]);
die_gads[n].GadgetRender = &die_images[die_values[n]];
die_gads[n].Flags &= ~(GFLG_SELECTED | GFLG_DISABLED);
AddGadget (main_win, &die_gads[n], pos);
RefreshGList (&die_gads[n], main_win, NULL, 1);
die_rolled = TRUE;
}
}
if (die_rolled)
{
if (rolls_left == 0)
{
if (--scoreboard[current_player][SAVED_ROLLS] == 0)
{
GT_SetGadgetAttrs (roll_gad, main_win, NULL,
GA_Disabled, TRUE, TAG_DONE);
}
}
else if (--rolls_left == 0)
{
if (!(rules->labels[SAVED_ROLLS] &&
scoreboard[current_player][SAVED_ROLLS] > 0))
{
GT_SetGadgetAttrs (roll_gad, main_win, NULL,
GA_Disabled, TRUE, TAG_DONE);
}
}
GT_SetGadgetAttrs (disp_gad, main_win, NULL,
GTNM_Number, rolls_left, TAG_DONE);
(rules->calc_score) (die_values, possible_score);
draw_possible_score (main_win->RPort, rules, current_player,
scoreboard[current_player], possible_score);
}
}
UBYTE
choose_score (
WORD x,
WORD y)
{
register UBYTE n;
BYTE score_no = -1;
if (die_gads[0].Flags & GFLG_DISABLED)
return 0;
for (n = 0; score_no < 0 && n < MAX_LABELS; ++n)
{
if (rules->labels[n] &&
x >= board_grid[current_player + 1][n].left &&
x < board_grid[current_player + 1][n].left +
board_grid[current_player + 1][n].width &&
y >= board_grid[current_player + 1][n].top &&
y < board_grid[current_player + 1][n].top +
board_grid[current_player + 1][n].height)
{
score_no = n;
}
}
if (scoreboard[current_player][score_no] == -1)
{
prev_rolls_left = rolls_left;
last_choice = score_no;
scoreboard[current_player][score_no] = possible_score[score_no];
scoreboard[current_player][TOTAL] += possible_score[score_no];
if (score_no < UPPER_TOTAL)
{
scoreboard[current_player][UPPER_TOTAL] +=
possible_score[score_no];
if (scoreboard[current_player][UPPER_TOTAL] >= rules->bonus_limit &&
scoreboard[current_player][BONUS] == 0)
{
scoreboard[current_player][BONUS] = rules->bonus;
scoreboard[current_player][TOTAL] += rules->bonus;
}
}
if (rules->labels[SAVED_ROLLS])
scoreboard[current_player][SAVED_ROLLS] += rolls_left;
draw_chosen_score (main_win->RPort, rules,
current_player, scoreboard[current_player], FALSE);
for (n = 0; n < rules->num_dice; ++n)
OffGadget (&die_gads[n], main_win, NULL);
rolls_left = 3;
++current_player;
if (current_player == num_players)
{
current_player = 0;
--rounds_left;
}
if (current_player == 0 && rounds_left == 0)
end_of_game ();
else
{
draw_player_numbers (main_win->RPort, num_players, current_player);
GT_SetGadgetAttrs (roll_gad, main_win, NULL,
GA_Disabled, FALSE, TAG_DONE);
GT_SetGadgetAttrs (disp_gad, main_win, NULL,
GTNM_Number, rolls_left);
}
}
return rounds_left;
}
void
undo_last_choice (void)
{
register UBYTE n;
if (current_player == 0)
{
++rounds_left;
current_player = num_players - 1;
}
else
--current_player;
rolls_left = prev_rolls_left;
if (rules->labels[SAVED_ROLLS])
scoreboard[current_player][SAVED_ROLLS] -= rolls_left;
scoreboard[current_player][last_choice] = -1;
scoreboard[current_player][TOTAL] -= possible_score[last_choice];
if (last_choice < UPPER_TOTAL)
{
scoreboard[current_player][UPPER_TOTAL] -= possible_score[last_choice];
if (scoreboard[current_player][UPPER_TOTAL] < rules->bonus_limit &&
scoreboard[current_player][BONUS] > 0)
{
scoreboard[current_player][TOTAL] -= rules->bonus;
scoreboard[current_player][BONUS] = 0;
}
}
draw_player_numbers (main_win->RPort, num_players, current_player);
draw_chosen_score (main_win->RPort, rules,
current_player, scoreboard[current_player], FALSE);
draw_possible_score (main_win->RPort, rules, current_player,
scoreboard[current_player], possible_score);
for (n = 0; n < rules->num_dice; ++n)
OnGadget (&die_gads[n], main_win, NULL);
if (!(rolls_left > 0 ||
(rules->labels[SAVED_ROLLS] &&
scoreboard[current_player][SAVED_ROLLS] > 0)))
{
GT_SetGadgetAttrs (roll_gad, main_win, NULL,
GA_Disabled, TRUE, TAG_DONE);
}
GT_SetGadgetAttrs (disp_gad, main_win, NULL,
GTNM_Number, rolls_left, TAG_DONE);
}