-
Notifications
You must be signed in to change notification settings - Fork 0
/
uno_game.ml
228 lines (206 loc) · 7.55 KB
/
uno_game.ml
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
exception InvalidMove
(* INITIALIZATION FUNCTIONS *)
let rec cards_draw
(deck : Deck.t ref)
(num_cards : int)
(player_cards : Hand.t) =
if num_cards == 0 then player_cards
else
(* Use deck functions *)
let card, new_deck = Deck.draw_card !deck in
deck := new_deck;
cards_draw deck (num_cards - 1) (Hand.add_card player_cards card)
let starting_hands (num_players : int) (deck : Deck.t ref) =
let array_hands = Array.make num_players Hand.empty_hand in
let rec card_matcher num acc =
match num with
| 1 ->
let _ = acc.(0) <- cards_draw deck 7 Hand.empty_hand in
acc
| n ->
let _ = acc.(n - 1) <- cards_draw deck 7 Hand.empty_hand in
card_matcher (num - 1) acc
in
card_matcher num_players array_hands
let init_discard deck =
let temp_hand = cards_draw deck 1 Hand.empty_hand in
match Hand.list_of_hand temp_hand with
| [] -> raise Not_found
| h :: t -> [ h ]
(* DRAWING FUNCTIONS *)
let draw (deck : Deck.t ref) (hand : Hand.t) = cards_draw deck 1 hand
let special_draw
(card : Card.t)
(player_cards : Hand.t)
(deck : Deck.t ref) =
match Card.indicator_of_card card with
| PlusTwo -> cards_draw deck 2 player_cards
| PlusFour -> cards_draw deck 4 player_cards
| _ -> raise InvalidMove
(* CARD PLAY FUNCTIONS *)
let play_numbered_card card (hand : Hand.t) = Hand.remove_card hand card
let skip card hand = Hand.remove_card hand card
let color card hand = Hand.remove_card hand card
let reverse card hand = Hand.remove_card hand card
let is_numbered_card card =
match Card.int_of_indicator (Card.indicator_of_card card) with
| -1 -> false
| _ -> true
let easy_ai_play (hand : Hand.t) (card : Card.t) =
let card_color = Card.color_of_card card in
let card_indicator = Card.indicator_of_card card in
let hand_list = Hand.list_of_hand hand in
let rec ai_play_helper hand_list_help =
match hand_list_help with
| [] -> Command.Draw
| h :: t ->
if
Card.color_of_card h = card_color
|| Card.indicator_of_card h = card_indicator
|| Card.color_of_card h = Card.Wild
then
let return_card =
Card.create_card (Card.color_of_card h)
(Card.indicator_of_card h)
in
Command.Play return_card
else ai_play_helper t
in
ai_play_helper hand_list
let medium_ai_play (hand : Hand.t) (card : Card.t) =
let card_color = Card.color_of_card card in
let card_indicator = Card.indicator_of_card card in
let hand_list = Hand.list_of_hand hand in
let rec ai_play_helper_one hand_list_help untouched_hand_list =
match hand_list_help with
| [] ->
let rec ai_player_helper_two
hand_list_help_two
untouched_hand_list =
match hand_list_help_two with
| [] -> Command.Draw
| h :: t ->
if
Card.color_of_card h = card_color
|| Card.color_of_card h = Card.Wild
then
let return_card =
Card.create_card (Card.color_of_card h)
(Card.indicator_of_card h)
in
Command.Play return_card
else ai_player_helper_two t untouched_hand_list
in
ai_player_helper_two untouched_hand_list untouched_hand_list
| h :: t ->
if Card.indicator_of_card h = card_indicator then
let return_card =
Card.create_card (Card.color_of_card h)
(Card.indicator_of_card h)
in
Command.Play return_card
else ai_play_helper_one t untouched_hand_list
in
ai_play_helper_one hand_list hand_list
let hard_ai_play (hand : Hand.t) (card : Card.t) =
let card_color = Card.color_of_card card in
let card_indicator = Card.indicator_of_card card in
let hand_list = Hand.list_of_hand hand in
let rec ai_play_helper_one hand_list_help untouched_hand_list =
match hand_list_help with
| [] ->
let rec ai_player_helper_two
hand_list_help_two
untouched_hand_list =
match hand_list_help_two with
| [] ->
let rec ai_player_helper_three
hand_list_help_three
untouched_hand_list =
match untouched_hand_list with
| [] -> Command.Draw
| h :: t ->
if Card.color_of_card h = Card.Wild then
let return_card =
Card.create_card (Card.color_of_card h)
(Card.indicator_of_card h)
in
Command.Play return_card
else Command.Draw
in
ai_player_helper_three untouched_hand_list
untouched_hand_list
| h :: t ->
if Card.color_of_card h = card_color then
let return_card =
Card.create_card (Card.color_of_card h)
(Card.indicator_of_card h)
in
Command.Play return_card
else ai_player_helper_two t untouched_hand_list
in
ai_player_helper_two untouched_hand_list untouched_hand_list
| h :: t ->
if Card.indicator_of_card h = card_indicator then
let return_card =
Card.create_card (Card.color_of_card h)
(Card.indicator_of_card h)
in
Command.Play return_card
else ai_play_helper_one t untouched_hand_list
in
ai_play_helper_one hand_list hand_list
let easy_ai_choose_color =
Random.self_init ();
let random_num = Random.int 4 in
if random_num = 0 then Card.Red
else if random_num = 1 then Card.Blue
else if random_num = 2 then Card.Yellow
else Card.Green
let rec medium_ai_choose_color_helper hand =
match hand with
| [] -> Card.Red
| h :: t ->
if Card.color_of_card h != Card.Wild then Card.color_of_card h
else medium_ai_choose_color_helper t
let rec medium_ai_choose_color hand =
medium_ai_choose_color_helper (Hand.list_of_hand hand)
let rec hard_ai_choose_color_helper hand red blue yellow green =
match hand with
| [] ->
let max_value = ref red in
if !max_value > blue then max_value := !max_value
else max_value := blue;
if !max_value > yellow then max_value := !max_value
else max_value := yellow;
if !max_value > green then max_value := !max_value
else max_value := green;
let top_color = !max_value in
if top_color = red then Card.Red
else if top_color = blue then Card.Blue
else if top_color = yellow then Card.Yellow
else Card.Green
| h :: t ->
if Card.color_of_card h = Red then
hard_ai_choose_color_helper t (red + 1) blue yellow green
else if Card.color_of_card h = Blue then
hard_ai_choose_color_helper t red (blue + 1) yellow green
else if Card.color_of_card h = Yellow then
hard_ai_choose_color_helper t red blue (yellow + 1) green
else if Card.color_of_card h = Green then
hard_ai_choose_color_helper t red blue yellow (green + 1)
else hard_ai_choose_color_helper t red blue yellow green
let hard_ai_choose_color hand =
hard_ai_choose_color_helper (Hand.list_of_hand hand) 0 0 0 0
let ai_choose_color_all hand difficulty =
Command.(
match difficulty with
| Easy -> easy_ai_choose_color
| Medium -> medium_ai_choose_color hand
| Hard -> hard_ai_choose_color hand)
let ai_play_all hand card difficulty =
Command.(
match difficulty with
| Easy -> easy_ai_play hand card
| Medium -> medium_ai_play hand card
| Hard -> hard_ai_play hand card)