-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgame.c
468 lines (398 loc) · 11.1 KB
/
game.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
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
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
/**
* This game is provided as an example of good use of the C programming
* language for beginners. We assume you are familiar with simple
* programming constructs like for loops and pointers. Complicated
* functions are well documented. This game was originally written
* by Riccardo Mutschlechner <[email protected]> and Nik Ingrassia,
* but was rewritten from scratch.
*
* Author: John Detter <[email protected]>
*
*/
#include <string.h> /* Needed for memset */
#include <stdio.h> /* Needed for printf */
#include <unistd.h> /* Needed for read */
#include <stdlib.h> /* Needed for srand and rand (random)*/
#include <time.h> /* Needed for time (setting up random) */
#include "gofish.h"
/**
* The player for the game
*/
struct player game_players[PLAYERS_MAX];
/**
* How many players are actually playing in the game?
*/
int player_count;
/**
* The main deck for the game
*/
struct deck game_deck;
/**
* The names of the card ranks
*/
const char* rank_names[] =
{
NULL, NULL, /* No R0 or R1 */
"Two", "Three", "Four", "Five", "Six", "Seven", "Eight",
"Nine", "Ten", "Jack", "Queen", "King", "Ace"
};
/**
* Names for some computer players
*/
const char* computer_names[] =
{
"alice", "bob", "carl", "dana",
"evan", "frank", "gretta", "harry",
"ian", "jeanne", "kate"
};
int main(int argc, char** argv)
{
/* Setup the random seed for this game */
srand(time(NULL));
/* The input we will take from the user will go in here */
#define USER_INPUT_MAX 64
char user_input[USER_INPUT_MAX];
memset(user_input, 0, USER_INPUT_MAX); /* Zero the buffer */
/**
* Ask the user how many players they wish to play with.
*/
player_count = -1; /* The amount of computer players */
do
{
/* Prompt for player count */
printf("You must play against at least one computer player (max 11).\n");
printf("How many computers do you want to play with? ");
fflush(stdout); /* Flush output */
if(read(1, user_input, USER_INPUT_MAX - 1) < 0)
{
/* An error occurred in reading */
return -1;
}
/* Did we get a valid number? */
player_count = atoi(user_input);
if(player_count <= 0 || player_count >= PLAYERS_MAX)
{
sleep(DIALOG_SPEED); /* Sleep for 2 seconds */
printf("You entered an invalid player count. Exiting...\n");
return -1;
}
} while(player_count <= 0);
/* The user's name*/
char user_name[USER_INPUT_MAX];
memset(user_name, 0, USER_INPUT_MAX); /* Zero the buffer */
do
{
/* Prompt for player's name */
printf("What should we call you? ");
fflush(stdout); /* Flush output */
if(read(1, user_name, USER_INPUT_MAX - 1) < 0)
{
/* An error occurred getting the user's input */
return -1;
}
/* The last character is probably a new line, trim it. */
if(user_name[strlen(user_name) - 1] == '\n')
{
user_name[strlen(user_name) - 1] = 0;
}
if(strlen(user_name) < 2)
{
printf("Your name must be at least 2 characters.\n");
}
} while (strlen(user_name) < 2);
printf("Setting up game...");
/* Zero the players */
memset(game_players, 0, sizeof(struct player) * PLAYERS_MAX);
/* Add the one human player */
player_setup(game_players + 0, user_name, 1);
player_count++; /* increment player count for human player */
/* Add all other players */
int player_num;
for(player_num = 1;player_num < player_count;player_num++)
{
/* Add the player */
player_setup(game_players + player_num,
computer_names[player_num - 1], 0);
}
printf("done.\nInitilizing deck...");
memset(&game_deck, 0, sizeof(struct deck));
/* Add all of the cards to the deck */
deck_populate(&game_deck);
/* Shuffle the deck */
deck_shuffle(&game_deck);
printf("done.\nGiving out cards...");
/* Distribute cards to players */
int deal_cards = 5;
if(player_count == 2)
{
/* If there are only 2 players, 7 cards are used */
deal_cards = 7;
}
for(player_num = 0;player_num < player_count;player_num++)
{
struct player* p = game_players + player_num;
int card_count;
for(card_count = 0;card_count < deal_cards;card_count++)
{
/* Draw a card */
struct card* c = deck_draw(&game_deck);
/* Give the card to the player */
deck_put(&p->d, c);
/* Free the card pointer */
free(c);
}
}
printf("done.\n");
/* Check to see if anyone got any sets off of the start */
int player_index;
for(player_index = 0;player_index < player_count;player_index++)
{
struct player* curr_player = game_players + player_index;
rank_t set = -1;
do
{
set = deck_get_set(&curr_player->d);
if(set > 0)
{
printf("%s: I have all of the %s\'s.\n",
curr_player->name,
rank_names[set]);
curr_player->books++;
sleep(DIALOG_SPEED);
}
} while(set != -1);
}
/** We're ready to play! */
int playing = 1;
while(playing)
{
rank_t r;
struct player* p;
/* Let each player go */
int player_num;
for(player_num = 0;player_num < player_count;player_num++)
{
struct player* curr_player =
game_players + player_num;
printf("Top of player's deck: %d\n", curr_player->d.top);
/**
* Does this player have any cards in their hand?
*/
if(curr_player->d.top <= -1)
{
printf("game: %s has no cards.\n",
curr_player->name);
/* Sleep before draw */
sleep(DIALOG_SPEED);
/**
* Have the player draw a card
*/
struct card* c = deck_draw(&game_deck);
if(c != NULL)
{
/* We got a card */
printf("game: %s drew a card.\n", curr_player->name);
/* Add the card to the player's deck */
deck_put(&curr_player->d, c);
/* Did the player get the card they asked for? */
if(c->r == r)
{
sleep(DIALOG_SPEED);
/* Player goes again */
player_num--;
printf("game: %s drew the card they asked for.\n",
curr_player->name);
}
/* Free the card */
free(c);
} else {
/* We didn't get a card. */
printf("game: the deck is empty.\n");
}
/* Sleep before the next player goes */
sleep(DIALOG_SPEED);
continue;
}
/**
* Tell the player it is their turn
*/
if(curr_player->my_turn(curr_player, &r, &p) != 0)
{
printf("go fish: game error!\n");
exit(1);
}
/**
* The player must actually have this card.
*/
struct card* has_card =
deck_contains(&curr_player->d, r);
/* do a validity check */
if(r < R2 || r > RANK_MAX || !p
|| p == curr_player || !has_card)
{
printf("go fish: player entered an "
"invalid move.\n");
/* Try this again */
player_num--;
continue;
}
/**
* Put this card back into the player's deck
*/
deck_put(&curr_player->d, has_card);
free(has_card); /* Free the card */
printf("%s: %s, do you have any %s's?\n",
curr_player->name, p->name,
rank_names[r]);
/* Sleep */
sleep(DIALOG_SPEED);
/* How many cards did we find?*/
int count = 0;
struct card* taken[4];
memset(taken, 0, sizeof(struct card*) * 4);
/* Take the cards from the player: */
struct card* c;
while((c = deck_contains(&p->d, r)) != NULL)
{
taken[count] = c;
count++;
}
/**
* Did we get anything?
*/
if(count > 0)
{
printf("%s: I have %d %s%s\n", p->name,
count, rank_names[r],
count == 1 ? "" : "\'s");
/* Hand over all of the cards to the player */
int x;
for(x = 0;x < count;x++)
{
/* Hand over a card to the player */
deck_put(&curr_player->d, taken[x]);
/* Free the card */
free(taken[x]);
}
/* Sleep before the player goes again */
sleep(DIALOG_SPEED);
/**
* Do a quick check to see if the player
* acquired a book
*/
rank_t set = -1;
do
{
set = deck_get_set(&curr_player->d);
if(set > 0)
{
printf("%s: I have all of the %s\'s.\n",
curr_player->name,
rank_names[set]);
curr_player->books++;
sleep(DIALOG_SPEED);
}
} while(set != -1);
/* This player goes again */
player_num--;
continue;
} else {
/* didn't get anything */
printf("%s: Go fish.\n", p->name);
/* Sleep before draw */
sleep(DIALOG_SPEED);
struct card* c = deck_draw(&game_deck);
if(c != NULL)
{
/* We got a card */
printf("game: %s drew a card.\n", curr_player->name);
/* Add the card to the player's deck */
deck_put(&curr_player->d, c);
/* Did the player get the card they asked for? */
if(c->r == r)
{
sleep(DIALOG_SPEED);
/* Player goes again */
player_num--;
printf("game: %s drew the card they asked for.\n",
curr_player->name);
}
/* Free the card */
free(c);
} else {
/* We didn't get a card. */
printf("game: the deck is empty.\n");
}
/* Sleep before the next player goes */
sleep(DIALOG_SPEED);
/**
* Do a quick check to see if the player
* acquired a book
*/
rank_t set = -1;
do
{
set = deck_get_set(&curr_player->d);
if(set > 0)
{
printf("%s: I have all of the %s\'s.\n",
curr_player->name,
rank_names[set]);
curr_player->books++;
sleep(DIALOG_SPEED);
}
} while(set != -1);
}
}
playing = 0;
/* Check to see if the game is over */
int x;
for(x = 0;x < player_count;x++)
{
/* Are there cards in this player's hand? */
if(game_players[x].d.top >= 0)
{
/* Found a card in someone's hand. */
playing = 1;
}
}
}
/** Who has the most books? */
int max_books = -1;
int winner_count = 0;
struct player* winners[player_count];
int x;
for(x = 0;x < player_count;x++)
{
if(game_players[x].books > max_books)
{
/* New record */
max_books = game_players[x].books;
memset(winners, 0, sizeof(struct player*) *
player_count);
winners[0] = game_players + x;
winner_count = 1;
} else if(game_players[x].books == max_books)
{
/* Append a winner */
winners[winner_count] = game_players + x;
winner_count++;
}
}
/* Print out some new lines */
printf("\n\n");
const char* win_string = "won";
/* Is there a single winner? */
if(winner_count >= 1)
{
/* More than one winner */
printf("game: There was a tie between %d players.\n",
winner_count);
win_string = "tied";
}
for(x = 0;x < winner_count;x++)
{
printf("%s has %s the game!", winners[x]->name, win_string);
}
return 0;
}