-
Notifications
You must be signed in to change notification settings - Fork 0
/
game_rules.c
134 lines (109 loc) · 3.74 KB
/
game_rules.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include "game_rules.h"
#include "card.h"
#include "player.h"
#include "config.h"
#include "game.h"
static int choice_not_in_cards(const int num_choices, const int card_choices[],
const int cards_size)
{
int i;
for (i = 0 ; i < num_choices ; i++)
if (card_choices[i] >= cards_size)
return TRUE;
return FALSE;
}
static int cannot_lay_first_card(const struct card_t *cards,
const int card_choices[], const struct game_t *game)
{
return (!can_lay(&cards[card_choices[0]], game->pile, game->pile_size));
}
static int valid_move_with_given_hand(const struct game_t *game,
const int card_choices[], const int num_choices, const struct card_t *cards,
const int cards_size)
{
struct card_t to_lay[50];
int num_to_lay = 0;
int i = 0;
if ((num_choices > cards_size) ||
(choice_not_in_cards(num_choices, card_choices, cards_size)))
return FALSE;
for (i = 0 ; i < num_choices ; i++)
to_lay[num_to_lay++] = cards[card_choices[i]];
if ((!all_ranks_equal(to_lay, num_to_lay)) ||
(cannot_lay_first_card(cards, card_choices, game)))
return FALSE;
return TRUE;
}
static int empty_pile(const int pile_size)
{
return (pile_size == 0);
}
static int two_on_pile(const struct card_t *pile, const int pile_size)
{
return (pile[pile_size-1].rank == TWO);
}
static int card_higher_than_pile(const struct card_t *card,
const struct card_t *pile, const int pile_size)
{
return (card_cmp(card, &pile[pile_size-1]) == GT);
}
static int seven_on_pile(const struct card_t *pile, const int pile_size)
{
return (pile[pile_size-1].rank == SEVEN);
}
static int can_move_with_hand(const struct player_t *player, const struct card_t *pile,
const int pile_size)
{
int i;
for (i = 0 ; i < player->hand_size ; i++)
if (can_lay(&player->hand[i], pile, pile_size))
return TRUE;
return FALSE;
}
static int can_move_with_face_up(const struct player_t *player, const struct card_t *pile,
const int pile_size)
{
int i;
for (i = 0 ; i < player->face_up_size ; i++)
if (can_lay(&player->face_up[i], pile, pile_size))
return TRUE;
return FALSE;
}
int can_lay(const struct card_t *card, const struct card_t *pile, const int pile_size)
{
if ((empty_pile(pile_size)) || (special_card(card)) ||
(two_on_pile(pile, pile_size)) || (ranks_equal(card, &pile[pile_size-1])) ||
(card_higher_than_pile(card, pile, pile_size)))
return TRUE;
else if (seven_on_pile(pile, pile_size))
return can_lay(card, pile, pile_size-1);
else
return FALSE;
}
int valid_move(const struct game_t *game, const int card_choices[], const int num_choices)
{
const struct player_t *player = &game->players[game->current_player];
if (player->hand_size > 0)
return valid_move_with_given_hand(game, card_choices, num_choices,
player->hand, player->hand_size);
else if (player->face_up_size > 0)
return valid_move_with_given_hand(game, card_choices, num_choices,
player->face_up, player->face_up_size);
else
return FALSE;
}
int can_move(const struct game_t *game)
{
const struct player_t *player = &game->players[game->current_player];
if (player->hand_size > 0)
return can_move_with_hand(player, game->pile, game->pile_size);
else if (player->face_up_size > 0)
return can_move_with_face_up(player, game->pile, game->pile_size);
else
return FALSE;
}
int can_lay_from_face_down(const struct game_t *game, const int choice)
{
const struct player_t *player = &game->players[game->current_player];
return can_lay(&player->face_down[choice], game->pile, game->pile_size);
}