Survival Royale 1.0.0
A very simple yet funny card game.
Loading...
Searching...
No Matches
main.c
Go to the documentation of this file.
1// Copyright (C) 2025 Giulio Salvi, Jacopo Paradisi
2//
3// This program is free software: you can redistribute it and/or modify
4// it under the terms of the GNU General Public License as published by
5// the Free Software Foundation, either version 3 of the License, or
6// (at your option) any later version.
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11// GNU General Public License for more details.
12//
13// You should have received a copy of the GNU General Public License
14// along with this program. If not, see <https://www.gnu.org/licenses/>.
15
20
21#include "tui.h"
22#include "ansi.h"
23#include "main.h"
24#include "logs.h"
25#include "ansi_const.h"
26
27int main(int argc, char** argv) {
28 //
29 // return 0;
30
31 srand(time(NULL));
33 const LogsConfiguration logsCfg = gameCfg.beVerbose ? prepareLogs() : (LogsConfiguration){.fileName = "", .useConsole = true};
34
35 if(gameCfg.useTui) {
38 }
39
41
42 if(gameCfg.beVerbose)
43 printGameConfiguration(gameCfg, logsCfg, true);
44
45 Card* deck = prepareCardDeck();
46 const int playersCounter = askPlayerNumber();
48
49 Game game = prepareGame(playersCounter, deck, gameCfg, logsCfg);
50 if(gameCfg.beVerbose)
51 printPlayers(game, false);
52
53 while(!handleGamePhase(&game) && game.playersCounter) {
54 removeDeadPlayers(&game);
55 withdrawCards(&game);
56 shuffleDeck(deck);
57 giveCards(&game, deck);
58
59 if(gameCfg.beVerbose)
60 printPlayers(game, false);
61 }
62
63 withdrawCards(&game);
64 removeDeadPlayers(&game);
65
66 if(game.playersCounter)
67 announceWinner(*game.players[0]);
68 else
69 printfgr("#b##%d#No player has won.#r#\n", FgBrightRed);
70
71 freeDeck(deck);
72 freeGame(&game);
73
74 return 0;
75}
76
78 if(!checkTerminalSize()) {
79 printfgr("#b##%d#The terminal is too small for the game to be played.#r#\n", FgBrightRed);
81 }
82 if(!checkTerminalHost()) {
83 printf("The terminal's host is not supported. Please, use Windows Terminal App.\n");
85 }
86}
87
89 #ifdef _WIN32
90 SetConsoleOutputCP(CP_UTF8);
91 #endif
92}
93
95 int maxRows = 0, maxColumns = 0;
96 screenSize(&maxColumns, &maxRows);
97
98 return isTerminalSizeValid(maxRows, maxColumns);
99}
100
102 #ifdef _WIN32
103 HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
104 if (hSnapshot == INVALID_HANDLE_VALUE)
105 return false;
106
107 DWORD processId = GetCurrentProcessId();
108 while (processId != 0) {
109 PROCESSENTRY32 pe32;
110 pe32.dwSize = sizeof(PROCESSENTRY32);
111
112 int found = 0;
113 if (Process32First(hSnapshot, &pe32)) {
114 do {
115 if (pe32.th32ProcessID == processId) {
116 if(strcmp(pe32.szExeFile, "WindowsTerminal.exe") == 0)
117 return true;
118
119 processId = pe32.th32ParentProcessID;
120 found = 1;
121 break;
122 }
123 } while (Process32Next(hSnapshot, &pe32));
124 }
125
126 if (!found) {
127 CloseHandle(hSnapshot);
128 return false;
129 }
130
131 if (processId == 0) {
132 CloseHandle(hSnapshot);
133 return false;
134 }
135 }
136
137 CloseHandle(hSnapshot);
138 return false;
139 #else
140 return true;
141 #endif
142}
143
144int randomInt(const int min, const int max) {
145 return rand()%(max - min + 1) + min;
146}
147
150 int n = -1;
151 char opt = '\0';
152
153 do {
154 if(opt != '\0') {
155 clearScreen();
156 printfgr("#b##%d#The valid options are y, Y, n and N.\n#r#", (int)FgBrightRed);
157 }
158
159 printgr("#b#Can the players have the cards with the same rank? (y,Y,n,N) #r#");
160 fflush(stdin);
161 int _ = scanf("%c", &opt);
162 } while(opt != 'y' && opt != 'Y' && opt != 'n' && opt != 'N');
163 cfg.allowSameRank = opt == 'y' || opt == 'Y';
164
165 opt = '\0';
166 do {
167 if(opt != '\0') {
168 clearScreen();
169 printfgr("#b##%d#The valid options are y, Y, n, N.\n#r#", (int)FgBrightRed);
170 }
171
172 printgr("#b#Can the players have the cards with the same suit? (y, Y, n, N) #r#");
173 fflush(stdin);
174 int _ = scanf("%c", &opt);
175 } while(opt != 'y' && opt != 'Y' && opt != 'n' && opt != 'N');
176 cfg.allowSameSuit = opt == 'y' || opt == 'Y';
177
178 do {
179 if(n < 0 && n != -1) {
180 clearScreen();
181 printfgr("#b##%d#The value must be positive.\n#r#", (int)FgBrightRed);
182 }
183
184 printgr("#b#How many LPs on the field should there be by default? #r#");
185 fflush(stdin);
186 const int a = scanf("%d", &n);
187 if(a == 0)
188 n = -2;
189 } while(n < 0);
190 cfg.defaultLPsOnField = n;
191
192 n = -1;
193 do {
194 if(n <= 0 && n != -1) {
195 clearScreen();
196 printfgr("#b##%d#The value must be positive and not zero.\n#r#", (int)FgBrightRed);
197 }
198
199 printgr("#b#How many LPs should the players have by default? #r#");
200 fflush(stdin);
201 const int a = scanf("%d", &n);
202 if(a == 0)
203 n = -2;
204 } while(n < 1);
205 cfg.defaultPlayersLPs = n;
206
207 cfg.beVerbose = false;
208
209 return cfg;
210}
211
213 int playersCounter = 2;
214
215 do {
216 if(playersCounter < 2 || playersCounter > 20) {
217 playersCounter = 0;
218 clearScreen();
219
220 printfgr("#b##%d#The players number must be between 2 and 20.\n#r#", (int)FgBrightRed);
221 }
222
223 printgr("#b#Please, insert the players number: #r#");
224 int _ = scanf("%d", &playersCounter);
225 } while(playersCounter < 2 || playersCounter > 20);
226
227 return playersCounter;
228}
229
231 Card card;
232
233 card.suit = -1;
234 card.rank = -1;
235
236 return card;
237}
238
240 Card* deck = malloc(sizeof(Card)*40);
241 if(!deck)
242 exit(EXIT_ALLOC_FAILURE);
243
244 for(int i = 0; i < 40; i++)
245 deck[i] = buildCard();
246
247 return deck;
248}
249
251 Player* player = malloc(sizeof(Player));
252 if(!player)
253 exit(EXIT_ALLOC_FAILURE);
254
255 player->id = -1;
256 player->facedUpCard = buildCard();
257 player->facedDownCard = buildCard();
258 player->revealedFacedDownCard = false;
259
260 return player;
261}
262
263Game buildGame(int playersCounter) {
264 Game game;
265
266 game.playersCounter = playersCounter;
267 game.players = malloc(sizeof(Player*)*game.playersCounter);
268 if(!game.players)
269 exit(EXIT_ALLOC_FAILURE);
270
271 for(int i = 0; i < game.playersCounter; i++)
272 game.players[i] = buildPlayer();
273
274 return game;
275}
276
277void freeDeck(Card* deck) {
278 free(deck);
279}
280
281void freePlayer(Player* player) {
282 free(player);
283}
284
285void freePlayers(Player** players, int playersCounter) {
286 for(int i = 0; i < playersCounter; i++)
287 freePlayer(players[i]);
288 free(players);
289}
290
291void freeGame(Game* game) {
292 freePlayers(game->players, game->playersCounter);
293}
294
296 Card* deck = buildDeck();
297
298 for(int i = 0; i < 40; i++) {
299 Card card = buildCard();
300
301 do {
302 card.suit = randomInt(Clubs, Hearts);
303 card.rank = randomInt(Ace, King);
304 } while(deckHasCard(deck, card));
305
306 deck[i] = card;
307 }
308
309 return deck;
310}
311
312Game prepareGame(int playersCounter, Card* deck, GameConfiguration gameConfiguration, LogsConfiguration logsConfiguration) {
313 Game game = buildGame(playersCounter);
314 game.lifePointsOnTheField = gameConfiguration.defaultLPsOnField;
315
316 for(int i = 0; i < game.playersCounter; i++) {
317 Player* player = malloc(sizeof(Player));
318 if(!player)
319 exit(EXIT_ALLOC_FAILURE);
320
321 do
322 player = preparePlayer(i + 1, deck, gameConfiguration);
323 while(
324 cardsWereGiven(game.players, game.playersCounter, *player) ||
325 cardAreEqual(player->facedUpCard, player->facedDownCard) || (
326 !gameConfiguration.allowSameRank ?
327 player->facedUpCard.rank == player->facedDownCard.rank : false
328 ) || (
329 !gameConfiguration.allowSameSuit ?
330 player->facedUpCard.suit == player->facedDownCard.suit : false
331 )
332 );
333
334 game.players[i] = player;
335 }
336
337 game.gameConfiguration = gameConfiguration;
338 game.logsConfiguration = logsConfiguration;
339
340 return game;
341}
342
343Player* preparePlayer(int id, Card* deck, GameConfiguration configuration) {
344 Player* player = buildPlayer();
345
346 player->id = id;
347 player->lifePoints = configuration.defaultPlayersLPs;
348 player->facedUpCard = deck[randomInt(0, 39)];
349 player->facedDownCard = deck[randomInt(0, 39)];
350
351 return player;
352}
353
354void shuffleDeck(Card* deck) {
355 for(int i = 39; i > 0; i--) {
356 int j = randomInt(0, i);
357
358 Card tmp = deck[i];
359 deck[i] = deck[j];
360 deck[j] = tmp;
361 }
362}
363
365 PageData* pages;
366 int starterPlayerPosition = randomInt(0, game->playersCounter - 1);
367 int maxRows = 0, maxColumns = 0, totalPages = 0, bestStartColumn = 0;
368
369 if(game->gameConfiguration.useTui) {
370 screenSize(&maxColumns, &maxRows);
371 pages = getPageData(maxRows, maxColumns, game->players, game->playersCounter, &totalPages, &bestStartColumn);
372
373 drawPageFrame(maxRows, maxColumns);
374 cursorPosition(maxRows - (LOG_SECTION_HEIGHT + 1) + 1, 3);
375
377 printPageData(pages, game->logsConfiguration, totalPages, true);
378 }
379
380 printfgr("The current phase starts from #b#player %d#r#.", game->players[starterPlayerPosition]->id);
381 Pause(false);
382
383 for(int i = 0; i < game->playersCounter; i++) {
384 int position = (i + starterPlayerPosition)%game->playersCounter, id = game->players[position]->id;
385
386 if(game->gameConfiguration.useTui)
387 navigatePages(pages, totalPages, maxRows, maxColumns, bestStartColumn, position, game);
388 else {
389 Player* player = game->players[position];
390 printfgr("%s#b#It's your turn, player %d!!#r# You have #b##%d#%d LPs#r#.\n", i == 0 ? "\n\n" : "", id, FgBrightCyan, player->lifePoints);
391
392 revealCard(player->facedUpCard, id, true, true);
393 applyEffect(game, position, true);
394 printgr("\n");
395
396 if(!player->revealedFacedDownCard) {
397 revealCard(player->facedDownCard, id, false, false);
398
400 applyEffect(game, position, false);
401 else
402 printgr("#b#The card has not been revealed#r#.\n");
403 } else
404 printfgr("#b#Player %d#r#, your #b#faced down card#r# has been #b##%d#already revealed#r#!\n", id, FgBrightRed);
405
406 Pause(true);
407 }
408 }
409
411 if(game->gameConfiguration.useTui)
412 freePageData(pages, totalPages);
413
414 return isGameEnded(game);
415}
416
417bool isGameEnded(Game* game) {
418 int c = 0;
419
420 for(int i = 0; i < game->playersCounter; i++)
421 if(game->players[i]->lifePoints > 0)
422 c++;
423
424 return c <= 1;
425}
426
427bool applyEffect(Game* game, int playerPosition, bool facedUpCard) {
428 Player* player = game->players[playerPosition];
429
430 if(!facedUpCard) {
431 if(game->players[playerPosition]->revealedFacedDownCard) {
432 printfgr("#b#Player %d's faced down card#r# has been #b##%d#already revealed#r#! #b#No effect by the last card has been applied#r#.", player->id, FgBrightRed);
433 return game->gameConfiguration.useTui;
434 }
435
436 player->revealedFacedDownCard = true;
437 }
438
439 if((facedUpCard ? player->facedUpCard.rank : player->facedDownCard.rank) == Ace) {
440 if(player->lifePoints > 0) {
441 game->lifePointsOnTheField++;
442 player->lifePoints--;
443 }
444
445 if(game->gameConfiguration.useTui) {
446 printfgr("By the effect of the #b#player %d's faced %s card#r# now on the #b#playing field#r# there are #b##%d#%d LPs#r#.", player->id, facedUpCard ? "up" : "down", FgGreen, game->lifePointsOnTheField);
447
448 return true;
449 } else {
450 printfgr("Now #b#player %d#r# has #b##%d#%d LPs#r#. ", player->id, FgBrightRed, player->lifePoints);
451 printfgr("Now on the #b#playing field#r# there are #b##%d#%d LPs#r#.\n", FgGreen, game->lifePointsOnTheField);
452
453 return false;
454 }
455 } else if((facedUpCard ? player->facedUpCard.rank : player->facedDownCard.rank) == Seven) {
456 if(game->gameConfiguration.useTui) {
457 tellFacedDownCard(game->players[(playerPosition + 1)%game->playersCounter]->facedDownCard, game->players[(playerPosition + 1)%game->playersCounter]->id);
458
459 Pause(false);
461 for(int i = 0; i < 137; i++)
462 printgr(" ");
464 } else
465 revealCard(game->players[(playerPosition + 1)%game->playersCounter]->facedDownCard, game->players[(playerPosition + 1)%game->playersCounter]->id, false, true);
466
467 return applyEffect(game, (playerPosition + 1)%game->playersCounter, false);
468 } else if((facedUpCard ? player->facedUpCard.rank : player->facedDownCard.rank) == Jack) {
469 if(player->lifePoints > 0) {
470 player->lifePoints--;
471 game->players[(playerPosition == 0 ? game->playersCounter : playerPosition) - 1]->lifePoints++;
472 }
473
474 if(!game->gameConfiguration.useTui) {
475 printfgr("Now #b#player %d#r# has #b##%d#%d LPs#r#. ", player->id, FgBrightRed, player->lifePoints);
476 printfgr("Now #b#player %d#r# has #b##%d#%d LPs#r#.\n", game->players[(playerPosition == 0 ? game->playersCounter : playerPosition) - 1]->id, FgGreen, game->players[(playerPosition == 0 ? game->playersCounter : playerPosition) - 1]->lifePoints);
477 }
478
479 return false;
480 } else if((facedUpCard ? player->facedUpCard.rank : player->facedDownCard.rank) == Queen) {
481 if(player->lifePoints > 0) {
482 player->lifePoints--;
483 game->players[(playerPosition + 2)%game->playersCounter]->lifePoints++;
484 }
485
486 if(!game->gameConfiguration.useTui) {
487 printfgr("Now #b#player %d#r# has #b##%d#%d LPs#r#. ", player->id, FgBrightRed, player->lifePoints);
488 printfgr("Now #b#player %d#r# has #b##%d#%d LPs#r#.\n", game->players[(playerPosition + 2)%game->playersCounter]->id, FgGreen, game->players[(playerPosition + 2)%game->playersCounter]->lifePoints);
489 }
490
491 return false;
492 } else if((facedUpCard ? player->facedUpCard.rank : player->facedDownCard.rank) == King) {
493 player->lifePoints += game->lifePointsOnTheField;
494 game->lifePointsOnTheField = 0;
495
496 if(game->gameConfiguration.useTui) {
497 printfgr("By the effect of the #b#player %d's faced %s card#r# now on the #b#playing field#r# there are #b##%d#0 LPs#r#.", player->id, facedUpCard ? "up" : "down", FgBrightYellow);
498
499 return true;
500 } else {
501 printfgr("Now #b#player %d#r# has #b##%d#%d LPs#r#. ", player->id, FgGreen, player->lifePoints);
502 printfgr("Now on the #b#playing field#r# there are #b##%d#0 LPs#r#.\n", FgBrightYellow);
503
504 return false;
505 }
506 } else {
507 printfgr("#b#No effect by the player %d's faced %s card has been applied#r#.", player->id, facedUpCard ? "up" : "down");
508 return game->gameConfiguration.useTui;
509 }
510}
511
513 char ans = '\0';
514 fflush(stdin);
515
516 do {
517 if(ans != '\0') {
518 scrollUp(1);
521 }
522
523 printgr("Do you want to #b#reveal#r# your #b#faced down#r# card and #b#apply its effect#r#?? (y,Y,n,N) ");
524 int _ = scanf("%c", &ans);
525 } while(ans != 'Y' && ans != 'N' && ans != 'y' && ans != 'n');
526
527 printgr("\n");
528
529 return ans == 'Y' || ans == 'y';
530}
531
532void giveCards(Game* game, Card* deck) {
533 for(int i = 0; i < game->playersCounter; i++)
534 if(game->players[i]->lifePoints > 0) {
535 Player* player = buildPlayer();
536 player->id = game->players[i]->id;
537 player->lifePoints = game->players[i]->lifePoints;
538
539 do {
540 player->facedUpCard = deck[randomInt(0, 39)];
541 player->facedDownCard = deck[randomInt(0, 39)];
542 } while(cardsWereGiven(game->players, game->playersCounter, *player) ||
543 cardAreEqual(player->facedUpCard, player->facedDownCard) ||
544 (!game->gameConfiguration.allowSameRank ? player->facedUpCard.rank == player->facedDownCard.rank : false) || (!game->gameConfiguration.allowSameSuit ? player->facedUpCard.suit == player->facedDownCard.suit : false)
545 );
546
547 freePlayer(game->players[i]);
548 game->players[i] = player;
549 }
550}
551
553 for(int i = 0; i < game->playersCounter; i++)
554 if(game->players[i]->lifePoints == 0)
555 printfgr("#%d##b#Player %d, you are dead.#r#\n", FgBrightRed, game->players[i]->id);
556}
557
559 int c = 0;
560
561 for(int i = 0; i < game->playersCounter; i++)
562 if(game->players[i]->lifePoints == 0)
563 c++;
564
565 return c;
566}
567
569 int newPlayersCounter = game->playersCounter - countDeadPlayers(game);
570 if(game->playersCounter == newPlayersCounter)
571 return;
572
573 Player** players = (Player**)malloc(newPlayersCounter*sizeof(Player*));
574 if(!players)
575 exit(EXIT_ALLOC_FAILURE);
576
577 for(int i = 0, p = 0; i < game->playersCounter; i++) {
578 if(game->players[i]->lifePoints > 0)
579 players[p++] = game->players[i];
580 else
581 freePlayer(game->players[i]);
582 }
583 free(game->players);
584
585 game->players = players;
586 game->playersCounter = newPlayersCounter;
587}
588
589void withdrawCards(Game* game) {
590 for(int i = 0; i < game->playersCounter; i++) {
591 game->players[i]->facedUpCard = buildCard();
592 game->players[i]->facedDownCard = buildCard();
593 }
594}
595
596void announceWinner(Player player) {
597 printfgr("\n#b##%d#Congratulations player %d, you have won!!#r#\n", FgBrightGreen, player.id);
598}
599
600bool deckHasCard(Card* deck, Card card) {
601 for(int i = 0; i < 40; i++)
602 if(cardAreEqual(deck[i], card))
603 return true;
604
605 return false;
606}
607
608bool cardAreEqual(Card card1, Card card2) {
609 return card1.rank == card2.rank && card1.suit == card2.suit;
610}
611
612bool cardsWereGiven(Player** players, int playersCounter, Player player) {
613 for(int i = 0; i < playersCounter; i++)
614 if(players[i]->lifePoints > 0)
615 if(cardAreEqual(player.facedDownCard, players[i]->facedDownCard) || cardAreEqual(player.facedUpCard, players[i]->facedUpCard))
616 return true;
617
618 return false;
619}
620
621void printCardEffect(Card card, bool newLine) {
622 if(card.rank == Ace)
623 printgr("you drop #b#1 LP#r# to the #b#playing field#r#.");
624 else if(card.rank >= Two && card.rank <= Six)
625 printgr("#b#none#r#.");
626 else if(card.rank == Seven)
627 printgr("you force the #b#next player#r# to reveal #b#his faced down card#r# and #b#apply its effect#r#.");
628 else if(card.rank == Jack)
629 printgr("you give #b#1 LP#r# to the #b#previous player#r#.");
630 else if(card.rank == Queen)
631 printgr("you give #b#1 LP#r# to the #b#second following player#r#.");
632 else if(card.rank == King)
633 printgr("you claim #b#all#r# the #b#LPs#r# on the playing field.");
634
635 if(newLine)
636 printgr("\n");
637}
638
639void revealCard(Card card, int playerId, bool facedUp, bool newLine) {
640 printfgr("Player %d #b#faced %s#r# card is a #b#", playerId, facedUp ? "up" : "down");
641 printCard(card, (LogsConfiguration){.fileName = "", .useConsole = true}, false);
642 printgr("#r#, the effect is: ");
643 printCardEffect(card, true);
644
645 if(newLine)
646 printgr("\n");
647}
648
649void tellFacedDownCard(Card card, int playerId) {
650 LogsConfiguration logsConfiguration = {.fileName = "", .useConsole = true};
651
652 if(playerId == 0)
653 printgr("Your");
654 else
655 printfgr("Player %d's", playerId);
656 printgr(" #b#faced down#r# card is a #b#");
657 printCard(card, logsConfiguration, false);
658
659 printgr("#r#. The effect is: ");
660 printCardEffect(card, false);
661}
Implemented following https://en.wikipedia.org/wiki/ANSI_escape_code.
void Pause(bool clear)
Waits for the user to press a key without waiting for 'Enter' to be pressed.
Definition ansi.c:305
void printgr(const char *text)
Prints a text with the graphic rendition specified with custom graphic rendition format specifiers.
Definition ansi.c:127
void eraseInDisplay(int n)
Clears part of the screen.
Definition ansi.c:398
void cursorHorizontalAbsolute(int n)
Moves the cursor to column n.
Definition ansi.c:382
void cursorPosition(int n, int m)
Moves the cursor at n-th row and at the m-th column.
Definition ansi.c:389
void screenSize(int *width, int *height)
It returns the width and the height of the screen. On unix-like platforms, in case of errors,...
Definition ansi.c:312
void clearScreen()
Clears the entire terminal's window's content.
Definition ansi.c:85
void scrollUp(int n)
Scrolls the whole page up by n rows.
Definition ansi.c:412
void printfgr(char *text,...)
Prints text as printgr but handles standard C format specifiers %, d, i, u, x, X, f,...
Definition ansi.c:222
Declaration of constant values for ANSI module.
#define FgBrightYellow
ANSI standard bright yellow foreground color.
Definition ansi_const.h:46
#define FgBrightCyan
ANSI standard bright cyan foreground color.
Definition ansi_const.h:52
#define FgBrightRed
ANSI standard bright red foreground color.
Definition ansi_const.h:42
#define FgGreen
ANSI standard green foreground color.
Definition ansi_const.h:28
#define FgBrightGreen
ANSI standard bright green foreground color.
Definition ansi_const.h:44
GameConfiguration getConfigurationFromArguments(char **argv, const int argc)
Generates a game configuration from the given options. If some options are not specified,...
Definition cli.c:135
int handleCLIArguments(char **argv, const int argc)
It validates and intreprets the CLI options.
Definition cli.c:72
GameConfiguration getGameConfiguration(const int code, const GameConfiguration cliGameConfiguration)
Gets the game configuration based on the action code. If action code is ACTION_HELP,...
Definition config.c:46
#define EXIT_WINDOWS_TERMINAL_HOST_NOT_SUPPORTED
Exit code when the terminal's host process, on Windows, is not supported.
Definition consts.h:32
#define EXIT_TERMINAL_TOO_SMALL
Exit code when the terminal is too small for the TUI.
Definition consts.h:30
#define EXIT_ALLOC_FAILURE
Exit code when dynamic memory allocation fails.
Definition consts.h:22
Definition of logger functions.
void printPlayers(Game game, bool newLine)
Prints user-friendly the players' infos.
Definition logs.c:76
void printPageData(PageData pages[], LogsConfiguration logsConfiguration, int totalPages, bool newLine)
Prints user-friendly the pages' infos.
Definition logs.c:177
void printGameConfiguration(GameConfiguration gameConfiguration, LogsConfiguration logsConfiguration, bool newLine)
Prints user-friendly game configuration settings.
Definition logs.c:53
void printCard(Card card, LogsConfiguration logsConfiguration, bool newLine)
Prints user-friendly the card rank and suit.
Definition logs.c:112
LogsConfiguration prepareLogs()
Generates the logger configuration for the current session. Tries to generate the log file.
Definition logs.c:26
void giveCards(Game *game, Card *deck)
Assigns new cards to the player. It is not guaranteed that the old cards might be reassigned to the s...
Definition main.c:532
Card * prepareCardDeck()
Generates a deck with cards ordered randomly. It is guaranteed that no duplicated cards occurs in the...
Definition main.c:295
bool cardAreEqual(Card card1, Card card2)
Checks if two cards are equal.
Definition main.c:608
bool isGameEnded(Game *game)
Determines whether the game is ended.
Definition main.c:417
void shuffleDeck(Card *deck)
Shuffles the deck using Fisher - Yates algorithm.
Definition main.c:354
Card * buildDeck()
Generates a deck.
Definition main.c:239
void printCardEffect(Card card, bool newLine)
Prints user-friendly the card's effect.
Definition main.c:621
bool handleGamePhase(Game *game)
Handles the current game phase.
Definition main.c:364
int main(int argc, char **argv)
Definition main.c:27
Player * buildPlayer()
Generates a player.
Definition main.c:250
bool cardsWereGiven(Player **players, int playersCounter, Player player)
Checks if the cards of a given player have been already given to other players.
Definition main.c:612
void freeGame(Game *game)
Frees a game structure.
Definition main.c:291
Card buildCard()
Generates a card.
Definition main.c:230
bool revealFacedDownCard(Card card)
Asks to the player if he wants to reveal the faced down card.
Definition main.c:512
Game prepareGame(int playersCounter, Card *deck, GameConfiguration gameConfiguration, LogsConfiguration logsConfiguration)
Generates a game structure with the given players number and with the given data gave by the game con...
Definition main.c:312
void freePlayer(Player *player)
Frees a player.
Definition main.c:281
bool checkTerminalSize()
Checks if the terminal size is suitable for the TUI (Terminal User Interface).
Definition main.c:94
void setupTerminal()
On Windows, configures that the terminal such that it supports UTF-8 encoded chars.
Definition main.c:88
void revealCard(Card card, int playerId, bool facedUp, bool newLine)
Prints user-friendly the card revealed from a player.
Definition main.c:639
Game buildGame(int playersCounter)
Generates a game with the given number of players.
Definition main.c:263
int randomInt(const int min, const int max)
Generates a random number in the range (inclusive).
Definition main.c:144
void announceWinner(Player player)
Announces the winner.
Definition main.c:596
bool applyEffect(Game *game, int playerPosition, bool facedUpCard)
Applies the effect of the player at the given index in the players vector.
Definition main.c:427
bool checkTerminalHost()
On Windows, it checks if the terminal's host process is supported.
Definition main.c:101
void freePlayers(Player **players, int playersCounter)
Free all the players in the vector.
Definition main.c:285
void checkTerminal()
Checks if the terminal size is suitable for the TUI (Terminal User Interface); if the terminal it is ...
Definition main.c:77
int askPlayerNumber()
Asks the number of players to the user.
Definition main.c:212
void removeDeadPlayers(Game *game)
Removes the dead players from the players vector.
Definition main.c:568
void withdrawCards(Game *game)
Generates via the function buildCard new cards that are given to the players.
Definition main.c:589
void tellFacedDownCard(Card card, int playerId)
Prints user-friendly the faced down card revealed of the player.
Definition main.c:649
GameConfiguration askConfigurationOptionsViaTerminal()
Asks to the user via terminal the game configuration.
Definition main.c:148
bool deckHasCard(Card *deck, Card card)
Checks if a card is present in a deck.
Definition main.c:600
void announceDeadPlayers(Game *game)
Announces the dead players.
Definition main.c:552
int countDeadPlayers(Game *game)
Counts how many dead players there are in the players vector.
Definition main.c:558
void freeDeck(Card *deck)
Frees the cards deck.
Definition main.c:277
Player * preparePlayer(int id, Card *deck, GameConfiguration configuration)
Generates a player structure with the given player id and with the given data gave by the game config...
Definition main.c:343
Declaration of game-related constants, definition of game-related structures and functions.
bool cardAreEqual(Card card1, Card card2)
Checks if two cards are equal.
Definition main.c:608
#define Seven
Integer const to represent rank seven.
Definition main.h:38
Player * buildPlayer()
Generates a player.
Definition main.c:250
#define Jack
Integer const to represent rank jack.
Definition main.h:40
#define Ace
Integer const to represent rank ace.
Definition main.h:26
#define Clubs
Integer const to represent suit clubs.
Definition main.h:47
#define Hearts
Integer const to represent suit hearts.
Definition main.h:53
#define Six
Integer const to represent rank six.
Definition main.h:36
#define Queen
Integer const to represent rank queen.
Definition main.h:42
#define King
Integer const to represent rank king.
Definition main.h:44
#define Two
Integer const to represent rank two.
Definition main.h:28
Defines a structure for the cards.
Definition main.h:58
unsigned int rank
The rank of the card.
Definition main.h:62
unsigned int suit
The suit of the card.
Definition main.h:60
The game configuration structure.
bool allowSameRank
Determines if a player can have cards with the same rank. It increases randomness if set to false.
bool useTui
Determines if the gama has to use the terminal user interface (TUI).
int defaultLPsOnField
The default amount of LPs on the playing field at the beginning of a match.
bool beVerbose
Determines if the program has to have a verbose logging behaviour.
int defaultPlayersLPs
The default amount of LPs that every player have at the beginning of a match.
bool allowSameSuit
Determines if a player can have cards with the same suit It increases randomness if set to false.
Defines a structure for the game.
Definition main.h:80
unsigned int lifePointsOnTheField
The amount of LPs currently on the playing field.
Definition main.h:88
GameConfiguration gameConfiguration
The configuration for the game.
Definition main.h:82
unsigned int playersCounter
The amount of players currently alive.
Definition main.h:86
Player ** players
The currently alive players vector.
Definition main.h:90
LogsConfiguration logsConfiguration
The configuration for the logs, if the game has to be verbose.
Definition main.h:84
The configuration for the logger.
Struct to represent the layout and data of a page containing player information.
Definition tui.h:45
Defines a structure for the player's info.
Definition main.h:66
Card facedDownCard
The faced down card.
Definition main.h:76
bool revealedFacedDownCard
Flag for recording if the faced down card has been revealed; it can be toggled even if the faced down...
Definition main.h:72
unsigned int lifePoints
The current player LPs.
Definition main.h:70
unsigned int id
The player ID.
Definition main.h:68
Card facedUpCard
The faced up card.
Definition main.h:74
Terminal User Interface (TUI) implementation for card game display.
void drawPageFrame(int maxRows, int maxColumns)
Draws the frame for a page, including borders and separators.
Definition tui.c:114
PageData * getPageData(int maxRows, int maxColumns, Player **players, int totalPlayers, int *totalPages, int *bestStartColumn)
Computes the page layout for players and allocates memory for the page data.
Definition tui.c:223
void freePageData(PageData *pages, int totalPages)
Frees the memory allocated for page data.
Definition tui.c:276
bool isTerminalSizeValid(int maxRows, int maxColumns)
Checks if the terminal size meets the minimum requirements.
Definition tui.c:283
#define LOG_SECTION_HEIGHT
Integer const to represent the height of the logs section.
Definition tui.h:38
void navigatePages(PageData *pagesData, int totalPages, int maxRows, int maxColumns, int bestStartColumn, int playerIndex, Game *game)
Navigates between pages and handles player actions during their turn.
Definition tui.c:32