forked from shichao-an/hacking
-
Notifications
You must be signed in to change notification settings - Fork 0
/
game_of_chance.c
428 lines (383 loc) · 14.9 KB
/
game_of_chance.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
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <time.h>
#include <stdlib.h>
#include "hacking.h"
#define DATAFILE "/var/chance.data" // File to store user data
// Custom user struct to store information about users
struct user {
int uid;
int credits;
int highscore;
char name[100];
int (*current_game) ();
};
// function prototypes
int get_player_data();
void register_new_player();
void update_player_data();
void show_highscore();
void jackpot();
void input_name();
void print_cards(char *, char *, int);
int take_wager(int, int);
void play_the_game();
int pick_a_number();
int dealer_no_match();
int find_the_ace();
void fatal(char *);
// Global variables
struct user player; // Player struct
int main() {
int choice, last_game;
srand(time(0)); // Seed the randomizer with the current time.
if(get_player_data() == -1) // Try to read player data from file.
register_new_player(); // If there is no data, register a new player.
while(choice != 7) {
printf("-=[ Game of Chance Menu ]=-\n");
printf("1 - Play the Pick a Number game\n");
printf("2 - Play the No Match Dealer game\n");
printf("3 - Play the Find the Ace game\n");
printf("4 - View current high score\n");
printf("5 - Change your user name\n");
printf("6 - Reset your account at 100 credits\n");
printf("7 - Quit\n");
printf("[Name: %s]\n", player.name);
printf("[You have %u credits] -> ", player.credits);
scanf("%d", &choice);
if((choice < 1) || (choice > 7))
printf("\n[!!] The number %d is an invalid selection.\n\n", choice);
else if (choice < 4) { // Othewise, choice was a game of some sort.
if(choice != last_game) { // If the function ptr isn't set
if(choice == 1) // then point it at the selected game
player.current_game = pick_a_number;
else if(choice == 2)
player.current_game = dealer_no_match;
else
player.current_game = find_the_ace;
last_game = choice; // and set last_game.
}
play_the_game(); // Play the game.
}
else if (choice == 4)
show_highscore();
else if (choice == 5) {
printf("\nChange user name\n");
printf("Enter your new name: ");
input_name();
printf("Your name has been changed.\n\n");
}
else if (choice == 6) {
printf("\nYour account has been reset with 100 credits.\n\n");
player.credits = 100;
}
}
update_player_data();
printf("\nThanks for playing! Bye.\n");
}
// This function reads the player data for the current uid
// from the file. It returns -1 if it is unable to find player
// data for the current uid.
int get_player_data() {
int fd, uid, read_bytes;
struct user entry;
uid = getuid();
fd = open(DATAFILE, O_RDONLY);
if(fd == -1) // Can't open the file, maybe it doesn't exist
return -1;
read_bytes = read(fd, &entry, sizeof(struct user)); // Read the first chunk.
while(entry.uid != uid && read_bytes > 0) { // Loop until proper uid is found.
read_bytes = read(fd, &entry, sizeof(struct user)); // Keep reading.
}
close(fd); // close the file
if(read_bytes < sizeof(struct user)) // This means that the end of file was reached.
return -1;
else
player = entry; // Copy the read entry into the player struct.
return 1; // Return a success.
}
// This is the new user registration function.
// It will create a new player account and append it to the file
void register_new_player() {
int fd;
printf("-=-={ New Player Registration }=-=-\n");
printf("Enter your name: ");
input_name();
player.uid = getuid();
player.highscore = player.credits = 100;
fd = open(DATAFILE, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR);
if(fd == -1)
fatal("in register_new_player() while opening file");
write(fd, &player, sizeof(struct user));
close(fd);
printf("\nWelcome to the Game of Chance %s.\n", player.name);
printf("You have been given %u credits.\n", player.credits);
}
// This function writes the current player data to the file.
// It is used primarily for updating the credits after games.
void update_player_data() {
int fd, i, read_uid;
char burned_byte;
fd = open(DATAFILE, O_RDWR);
if(fd == -1) // If open fails here, something is really wrong.
fatal("in update_player_data() while opening file");
read(fd, &read_uid, 4); // Read the uid from the first struct.
while(read_uid != player.uid) { // Loop until correct uid is found.
for(i=0; i < sizeof(struct user) - 4; i++) // Read through the
read(fd, &burned_byte, 1); // rest of that struct.
read(fd, &read_uid, 4); // Read the uid from the next struct.
}
write(fd, &(player.credits), 4); // Update credits.
write(fd, &(player.highscore), 4); // Update highscore.
write(fd, &(player.name), 100); // Update name.
close(fd);
}
// This function will display the current high score and
// the name of the person who set that high score.
void show_highscore() {
unsigned int top_score = 0;
char top_name[100];
struct user entry;
int fd;
printf("\n====================| HIGH SCORE |====================\n");
fd = open(DATAFILE, O_RDONLY);
if(fd == -1)
fatal("in show_highscore() while opening file");
while(read(fd, &entry, sizeof(struct user)) > 0) { // Loop until end of file.
if(entry.highscore > top_score) { // If there is a higher score,
top_score = entry.highscore; // set top_score to that score
strcpy(top_name, entry.name); // and top_name to that username.
}
}
close(fd);
if(top_score > player.highscore)
printf("%s has the high score of %u\n", top_name, top_score);
else
printf("You currently have the high score of %u credits!\n", player.highscore);
printf("======================================================\n\n");
}
// This function simply awards the jackpot for the Pick a Number game
void jackpot() {
printf("*+*+*+*+*+* JACKPOT *+*+*+*+*+*\n");
printf("You have won the jackpot of 100 credits!\n");
player.credits += 100;
}
// This function is used to input the player name, since
// scanf("%s", &whatever) will stop input at the first space.
void input_name() {
char *name_ptr, input_char='\n';
while(input_char == '\n') // Flush any leftover
scanf("%c", &input_char); // newline chars.
name_ptr = (char *) &(player.name); // name_ptr = player name's address
while(input_char != '\n') { // Loop until newline.
*name_ptr = input_char; // Put the input char into name field.
scanf("%c", &input_char); // Get the next char.
name_ptr++; // Increment the name pointer.
}
*name_ptr = 0; // Terminate the string.
}
// This function prints the 3 cards for the Find the Ace game.
// It expects a message to display, a pointer to the cards array,
// and the card the user has picked as input. If the user_pick is
// -1, then the selection numbers are displayed.
void print_cards(char *message, char *cards, int user_pick) {
int i;
printf("\n\t*** %s ***\n", message);
printf(" \t._.\t._.\t._.\n");
printf("Cards:\t|%c|\t|%c|\t|%c|\n\t", cards[0], cards[1], cards[2]);
if(user_pick == -1)
printf(" 1 \t 2 \t 3\n");
else {
for(i=0; i < user_pick; i++)
printf("\t");
printf(" ^-- your pick\n");
}
}
// This function inputs wagers for both the No Match Dealer and
// Find the Ace games. It expects the available credits and the
// previous wager as arguments. The previous_wager is only important
// for the second wager in the Find the Ace game. The function
// returns -1 if the wager is too big or too little, and it returns
// the wager amount otherwise.
int take_wager(int available_credits, int previous_wager) {
int wager, total_wager;
printf("How many of your %d credits would you like to wager? ", available_credits);
scanf("%d", &wager);
if(wager < 1) { // Make sure the wager is greater than 0.
printf("Nice try, but you must wager a positive number!\n");
return -1;
}
total_wager = previous_wager + wager;
if(total_wager > available_credits) { // Confirm available credits
printf("Your total wager of %d is more than you have!\n", total_wager);
printf("You only have %d available credits, try again.\n", available_credits);
return -1;
}
return wager;
}
// This function contains a loop to allow the current game to be
// played again. It also writes the new credit totals to file
// after each game is played.
void play_the_game() {
int play_again = 1;
int (*game) ();
char selection;
while(play_again) {
printf("\n[DEBUG] current_game pointer @ 0x%08x\n", player.current_game);
if(player.current_game() != -1) { // If the game plays without error and
if(player.credits > player.highscore) // a new high score is set,
player.highscore = player.credits; // update the highscore.
printf("\nYou now have %u credits\n", player.credits);
update_player_data(); // Write the new credit total to file.
printf("Would you like to play again? (y/n) ");
selection = '\n';
while(selection == '\n') // Flush any extra newlines.
scanf("%c", &selection);
if(selection == 'n')
play_again = 0;
}
else // This means the game returned an error,
play_again = 0; // so return to main menu.
}
}
// This function is the Pick a Number game.
// It returns -1 if the player doesn't have enough credits.
int pick_a_number() {
int pick, winning_number;
printf("\n####### Pick a Number ######\n");
printf("This game costs 10 credits to play. Simply pick a number\n");
printf("between 1 and 20, and if you pick the winning number, you\n");
printf("will win the jackpot of 100 credits!\n\n");
winning_number = (rand() % 20) + 1; // Pick a number between 1 and 20.
if(player.credits < 10) {
printf("You only have %d credits. That's not enough to play!\n\n", player.credits);
return -1; // Not enough credits to play
}
player.credits -= 10; // Deduct 10 credits
printf("10 credits have been deducted from your account.\n");
printf("Pick a number between 1 and 20: ");
scanf("%d", &pick);
printf("The winning number is %d\n", winning_number);
if(pick == winning_number)
jackpot();
else
printf("Sorry, you didn't win.\n");
return 0;
}
// This is the No Match Dealer game.
// It returns -1 if the player has 0 credits.
int dealer_no_match() {
int i, j, numbers[16], wager = -1, match = -1;
printf("\n::::::: No Match Dealer :::::::\n");
printf("In this game, you can wager up to all of your credits.\n");
printf("The dealer will deal out 16 random numbers between 0 and 99.\n");
printf("If there are no matches among them, you double your money!\n\n");
if(player.credits == 0) {
printf("You don't have any credits to wager!\n\n");
return -1;
}
while(wager == -1)
wager = take_wager(player.credits, 0);
printf("\t\t::: Dealing out 16 random numbers :::\n");
for(i=0; i < 16; i++) {
numbers[i] = rand() % 100; // pick a number 0 to 99
printf("%2d\t", numbers[i]);
if(i%8 == 7) // Print a line break every 8 numbers.
printf("\n");
}
for(i=0; i < 15; i++) { // Loop looking for matches
j = i + 1;
while(j < 16) {
if(numbers[i] == numbers[j])
match = numbers[i];
j++;
}
}
if(match != -1) {
printf("The dealer matched the number %d!\n", match);
printf("You lose %d credits.\n", wager);
player.credits -= wager;
} else {
printf("There were no matches! You win %d credits!\n", wager);
player.credits += wager;
}
return 0;
}
// This is the Find the Ace game.
// It returns -1 if the player has 0 credits.
int find_the_ace() {
int i, ace, total_wager;
int invalid_choice, pick = -1, wager_one = -1, wager_two = -1;
char choice_two, cards[3] = {'X', 'X', 'X'};
ace = rand()%3; // Place the ace randomly.
printf("******* Find the Ace *******\n");
printf("In this game, you can wager up to all of your credits.\n");
printf("Three cards will be dealt out, two queens and one ace.\n");
printf("If you find the ace, you will win your wager.\n");
printf("After choosing a card, one of the queens will be revealed.\n");
printf("At this point, you may either select a different card or\n");
printf("increase your wager.\n\n");
if(player.credits == 0) {
printf("You don't have any credits to wager!\n\n");
return -1;
}
while(wager_one == -1) // Loop until valid wager is made.
wager_one = take_wager(player.credits, 0);
print_cards("Dealing cards", cards, -1);
pick = -1;
while((pick < 1) || (pick > 3)) { // Loop until valid pick is made.
printf("Select a card: 1, 2, or 3 ");
scanf("%d", &pick);
}
pick--; // Adjust the pick since card numbering starts at 0.
i=0;
while(i == ace || i == pick) // Keep looping until
i++; // we find a valid queen to reveal.
cards[i] = 'Q';
print_cards("Revealing a queen", cards, pick);
invalid_choice = 1;
while(invalid_choice) { // Loop until valid choice is made.
printf("Would you like to:\n[c]hange your pick\tor\t[i]ncrease your wager?\n");
printf("Select c or i: ");
choice_two = '\n';
while(choice_two == '\n') // Flush extra newlines.
scanf("%c", &choice_two);
if(choice_two == 'i') { // Increase wager.
invalid_choice=0; // This is a valid choice.
while(wager_two == -1) // Loop until valid second wager is made.
wager_two = take_wager(player.credits, wager_one);
}
if(choice_two == 'c') { // Change pick.
i = invalid_choice = 0; // Valid choice
while(i == pick || cards[i] == 'Q') // Loop until the other card
i++;// is found,
pick = i;// and then swap pick.
printf("Your card pick has been changed to card %d\n", pick+1);
}
}
for(i=0; i < 3; i++) { // Reveal all of the cards.
if(ace == i)
cards[i] = 'A';
else
cards[i] = 'Q';
}
print_cards("End result", cards, pick);
if(pick == ace) { // handle win
printf("You have won %d credits from your first wager\n", wager_one);
player.credits += wager_one;
if(wager_two != -1) {
printf("and an additional %d credits from your second wager!\n", wager_two);
player.credits += wager_two;
}
} else { // handle loss
printf("You have lost %d credits from your first wager\n", wager_one);
player.credits -= wager_one;
if(wager_two != -1) {
printf("and an additional %d credits from your second wager!\n", wager_two);
player.credits -= wager_two;
}
}
return 0;
}