1 /* game_uno.c - NeonServ v5.4
2 * Copyright (C) 2011-2012 Philipp Kreil (pk910)
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "../module.h"
19 #include "bot_NeonFun.h"
20 #include "../../IRCParser.h"
21 #include "../../bots.h"
22 #include "../../UserNode.h"
23 #include "../../ChanUser.h"
24 #include "../../tools.h"
27 struct uno_game *uno_active_games = NULL;
29 #define UNO_COLOR_COUNT 4
30 static int uno_colors[] = {UNO_COLOR_RED, UNO_COLOR_BLUE, UNO_COLOR_GREEN, UNO_COLOR_YELLOW};
31 static int uno_irc_colors[] = {4, 12, 3, 7};
32 static char *uno_color_chars[] = {"R", "B", "G", "Y"};
37 } uno_card_types[] = {
38 {"0", UNO_CARD_NUMBER_0},
39 {"1", UNO_CARD_NUMBER_1},
40 {"2", UNO_CARD_NUMBER_2},
41 {"3", UNO_CARD_NUMBER_3},
42 {"4", UNO_CARD_NUMBER_4},
43 {"5", UNO_CARD_NUMBER_5},
44 {"6", UNO_CARD_NUMBER_6},
45 {"7", UNO_CARD_NUMBER_7},
46 {"8", UNO_CARD_NUMBER_8},
47 {"9", UNO_CARD_NUMBER_9},
49 {"><", UNO_CARD_DIRECTION},
50 {"+2", UNO_CARD_ADD_2},
51 {"+4", UNO_CARD_ADD_4},
52 {"COLOR", UNO_CARD_COLOR},
56 struct uno_card_deck *uno_shuffle_deck() {
57 struct uno_card *card, *last_card = NULL;
59 #define ADD_CARD(ccolor,ctype) \
60 card = malloc(sizeof(*card)); \
61 card->color = ccolor; \
64 card->next = last_card; \
66 last_card->prev = card; \
69 int colorcount = UNO_COLOR_COUNT;
70 for(colorcount--; colorcount >= 0; colorcount--) {
71 ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_0);
72 ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_0);
73 ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_1);
74 ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_1);
75 ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_2);
76 ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_2);
77 ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_3);
78 ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_3);
79 ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_4);
80 ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_4);
81 ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_5);
82 ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_5);
83 ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_6);
84 ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_6);
85 ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_7);
86 ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_7);
87 ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_8);
88 ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_8);
89 ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_9);
90 ADD_CARD(uno_colors[colorcount], UNO_CARD_NUMBER_9);
91 ADD_CARD(uno_colors[colorcount], UNO_CARD_SKIP);
92 ADD_CARD(uno_colors[colorcount], UNO_CARD_SKIP);
93 ADD_CARD(uno_colors[colorcount], UNO_CARD_DIRECTION);
94 ADD_CARD(uno_colors[colorcount], UNO_CARD_DIRECTION);
95 ADD_CARD(uno_colors[colorcount], UNO_CARD_ADD_2);
96 ADD_CARD(uno_colors[colorcount], UNO_CARD_ADD_2);
98 ADD_CARD(UNO_COLOR_BLACK, UNO_CARD_ADD_4);
99 ADD_CARD(UNO_COLOR_BLACK, UNO_CARD_ADD_4);
100 ADD_CARD(UNO_COLOR_BLACK, UNO_CARD_ADD_4);
101 ADD_CARD(UNO_COLOR_BLACK, UNO_CARD_ADD_4);
102 ADD_CARD(UNO_COLOR_BLACK, UNO_CARD_COLOR);
103 ADD_CARD(UNO_COLOR_BLACK, UNO_CARD_COLOR);
104 ADD_CARD(UNO_COLOR_BLACK, UNO_CARD_COLOR);
105 ADD_CARD(UNO_COLOR_BLACK, UNO_CARD_COLOR);
107 struct uno_card_deck *deck = malloc(sizeof(*deck));
108 deck->cards = last_card;
109 deck->count = card_count;
113 struct uno_card *uno_get_card(struct uno_card_deck *deck) {
114 if(!deck->count) return NULL;
115 int card_id = (rand() % deck->count);
117 struct uno_card *card;
118 for(card = deck->cards; card; card = card->next) {
121 card->prev->next = card->next;
123 deck->cards = card->next;
125 card->next->prev = card->prev;
136 void uno_free_deck(struct uno_card_deck *deck) {
137 struct uno_card *card, *next_card;
139 for(card = deck->cards; card; card = next_card) {
140 next_card = card->next;
146 void uno_free_player(struct uno_player *player, struct uno_card_deck *deck) {
148 struct uno_card *card, *next_card;
149 for(card = player->cards; card; card = next_card) {
150 next_card = card->next;
152 card->next = deck->cards;
153 deck->cards->prev = card;
161 player->prev->next = player->next;
163 player->next->prev = player->prev;
167 void uno_free_topcard(struct uno_card *card) {
168 struct uno_card *next_card;
169 for(; card; card = next_card) {
170 next_card = card->prev;
175 void uno_free_game(struct uno_game *game) {
176 struct uno_player *player, *next_player;
177 for(player = game->player; player; player = next_player) {
178 next_player = player->next;
179 uno_free_player(player, NULL);
181 for(player = game->winner; player; player = next_player) {
182 next_player = player->next;
183 uno_free_player(player, NULL);
186 uno_free_deck(game->deck);
188 uno_free_topcard(game->top_card);
190 timeq_del(game->timer);
191 struct uno_game *cgame, *pgame = NULL;
192 for(cgame = uno_active_games; cgame; cgame = cgame->next) {
195 pgame->next = game->next;
197 uno_active_games = game->next;
205 struct uno_player *uno_get_next_player(struct uno_game *game) {
206 struct uno_player *player = game->active_player;
207 if(!game->reverse_direction) {
208 player = player->next;
210 player = game->player;
212 player = player->prev;
214 for(player = game->player; player->next; player = player->next) {
215 //loop to the last player
222 void uno_show_player_cards(struct uno_game *game, struct uno_player *player) {
223 struct uno_card *card;
224 char cards_buf[MAXLEN];
225 int cards_bufpos = 0;
226 for(card = player->cards; card; card = card->next) {
230 for(i = 0; i < UNO_COLOR_COUNT; i++) {
231 if(uno_colors[i] == card->color) {
232 cardcolor = uno_irc_colors[i];
233 cardchar = uno_color_chars[i];
238 while(uno_card_types[i].name) {
239 if(uno_card_types[i].type == card->card) {
240 cards_bufpos += sprintf(cards_buf + cards_bufpos, "%s[\003%d%s%s\003]", (cards_bufpos ? " " : ""), cardcolor, cardchar, uno_card_types[i].name);
246 reply(game->textbot, player->chanuser->user, "NF_UNO_YOUR_CARDS", cards_buf);
249 void uno_show_top_card(struct uno_game *game) {
250 struct uno_card *card = game->top_card;
255 for(i = 0; i < UNO_COLOR_COUNT; i++) {
256 if(uno_colors[i] == card->color) {
257 cardcolor = uno_irc_colors[i];
258 cardchar = uno_color_chars[i];
263 while(uno_card_types[i].name) {
264 if(uno_card_types[i].type == card->card) {
265 if(card->card == UNO_CARD_ADD_4 || card->card == UNO_CARD_COLOR)
267 sprintf(card_buf, "[\003%d%s%s\003]", cardcolor, cardchar, uno_card_types[i].name);
272 uno_reply(game, NULL, "NF_UNO_TOP_CARD", card_buf);
275 TIMEQ_CALLBACK(uno_game_wait_timeout) {
276 struct uno_game *game = data;
278 if(game->players == 1) {
279 uno_reply(game, NULL, "NF_UNO_LESS_PLAYERS");
283 game->deck = uno_shuffle_deck();
284 uno_reply(game, NULL, "NF_UNO_START");
285 struct uno_player *player;
286 for(player = game->player; player; player = player->next) {
289 for(i = 0; i < 7; i++) {
290 if(!game->deck->count)
291 game->deck = uno_shuffle_deck();
292 struct uno_card *card = uno_get_card(game->deck);
294 uno_reply(game, NULL, "NF_UNO_ERROR", 1);
298 card->next = player->cards;
300 player->cards->prev = card;
301 player->cards = card;
304 uno_show_player_cards(game, player);
305 if((player->chanuser->user->flags & USERFLAG_ISAUTHED)) {
307 int game_count = ((tmp = getSetting(player->chanuser->user, game->channel, "uno_games")) ? atoi(tmp) : 0);
308 int total_game_count = ((tmp = getSetting(player->chanuser->user, NULL, "uno_games")) ? atoi(tmp) : 0);
312 sprintf(buf, "%d", game_count);
313 setSetting(player->chanuser->user, game->channel, "uno_games", buf);
314 sprintf(buf, "%d", total_game_count);
315 setSetting(player->chanuser->user, NULL, "uno_games", buf);
318 if(!game->deck->count)
319 game->deck = uno_shuffle_deck();
320 struct uno_card *card = uno_get_card(game->deck);
322 uno_reply(game, NULL, "NF_UNO_ERROR", 1);
326 game->top_card = card;
327 game->state = UNO_STATE_RUNNING;
328 uno_show_top_card(game);
329 game->active_player = game->player; //active player
330 uno_reply(game, NULL, "NF_UNO_USER_HURRY_UP", game->active_player->chanuser->user->nick);
331 game->timer = timeq_add(30, module_id, uno_player_timeout, game);
334 TIMEQ_CALLBACK(uno_player_timeout) {
335 struct uno_game *game = data;
337 //player timeout (take another card)
338 struct uno_player *player = game->active_player, *next_player = uno_get_next_player(game);
339 //add a card to the players deck
340 if(!game->deck->count)
341 game->deck = uno_shuffle_deck();
342 struct uno_card *card = uno_get_card(game->deck);
344 uno_reply(game, NULL, "NF_UNO_ERROR", 2);
348 card->next = player->cards;
350 player->cards->prev = card;
351 player->cards = card;
354 game->active_player = next_player;
355 uno_reply(game, NULL, "NF_UNO_USER_TOOK_CARD", player->chanuser->user->nick);
356 struct uno_player *cplayer;
357 for(cplayer = game->player; cplayer; cplayer = cplayer->next) {
358 if(!cplayer->timeout)
362 uno_reply(game, NULL, "NF_UNO_TIMEOUT");
366 uno_show_player_cards(game, player);
367 uno_show_top_card(game);
368 uno_reply(game, NULL, "NF_UNO_USER_HURRY_UP", game->active_player->chanuser->user->nick);
369 uno_show_player_cards(game, game->active_player);
370 game->timer = timeq_add(30, module_id, uno_player_timeout, game);
373 void uno_action_take_card(struct uno_game *game, struct uno_player *player) {
374 timeq_del(game->timer);
376 struct uno_player *next_player = uno_get_next_player(game);
377 //add a card to the players deck
379 if(game->take_cards_pending) {
380 //count cards to take
381 struct uno_card *card;
383 for(card = game->top_card; card; card = card->prev) {
384 if(card->card == UNO_CARD_ADD_2)
386 else if(card->card == UNO_CARD_ADD_4)
392 for(i = 0; i < ccount; i++) {
393 if(!game->deck->count)
394 game->deck = uno_shuffle_deck(game->deck);
395 struct uno_card *card = uno_get_card(game->deck);
397 uno_reply(game, NULL, "NF_UNO_ERROR", 2);
401 card->next = player->cards;
403 player->cards->prev = card;
404 player->cards = card;
407 game->active_player = next_player;
408 if(game->take_cards_pending) {
409 game->take_cards_pending = 0;
410 uno_reply(game, NULL, "NF_UNO_USER_TOOK_CARDS", player->chanuser->user->nick, ccount);
412 uno_reply(game, NULL, "NF_UNO_USER_TOOK_CARD", player->chanuser->user->nick);
413 uno_show_player_cards(game, player);
414 uno_show_top_card(game);
415 uno_reply(game, NULL, "NF_UNO_USER_HURRY_UP", game->active_player->chanuser->user->nick);
416 uno_show_player_cards(game, game->active_player);
417 game->timer = timeq_add(30, module_id, uno_player_timeout, game);
422 struct uno_card *uno_parse_card(struct uno_game *game, struct uno_player *player, char *arg1) {
445 unsigned char ctype = 255, ccolor = 0;
448 while(uno_card_types[i].name) {
449 if(!stricmp(uno_card_types[i].name, arg1)) {
450 ctype = uno_card_types[i].type;
453 for(j = 0; j < UNO_COLOR_COUNT; j++) {
454 sprintf(tmpbuf, "%s%s", uno_color_chars[j], uno_card_types[i].name);
455 if(!stricmp(tmpbuf, arg1)) {
456 ccolor = uno_colors[j];
457 ctype = uno_card_types[i].type;
464 reply(game->textbot, player->chanuser->user, "NF_UNO_UNKNOWN_CARD", arg1);
467 struct uno_card *card;
468 for(card = player->cards; card; card = card->next) {
469 if(card->card == ctype && card->color == ccolor)
473 reply(game->textbot, player->chanuser->user, "NF_UNO_CARD_NOT_IN_DECK");
479 int uno_check_card_valid(struct uno_game *game, struct uno_card *card) {
480 if(game->take_cards_pending && card->card != game->top_card->card)
482 if(card->color == UNO_COLOR_BLACK || game->top_card->color == UNO_COLOR_BLACK)
484 if(card->color != game->top_card->color && card->card != game->top_card->card)
489 void uno_play_card(struct uno_game *game, struct uno_player *player, struct uno_card *card) {
490 timeq_del(game->timer);
493 card->prev->next = card->next;
495 player->cards = card->next;
497 card->next->prev = card->prev;
499 if(!game->take_cards_pending) {
500 uno_free_topcard(game->top_card);
503 card->prev = game->top_card;
505 game->top_card = card;
506 uno_show_top_card(game);
507 if(player->count == 1) {
508 uno_reply(game, NULL, "NF_UNO_ONE_CARD", game->active_player->chanuser->user->nick);
509 } else if(player->count == 0) {
510 uno_reply(game, NULL, "NF_UNO_USER_WIN", game->active_player->chanuser->user->nick);
512 player->prev->next = player->next;
514 game->player = player->next;
516 player->next->prev = player->prev;
519 struct uno_player *cplayer;
520 int winner_count = 0;
522 for(cplayer = game->winner; cplayer->next; cplayer = cplayer->next) {
528 cplayer->next = player;
530 game->winner = player;
531 if((player->chanuser->user->flags & USERFLAG_ISAUTHED)) {
533 int win_count = ((tmp = getSetting(player->chanuser->user, game->channel, "uno_win")) ? atoi(tmp) : 0);
534 int total_win_count = ((tmp = getSetting(player->chanuser->user, NULL, "uno_win")) ? atoi(tmp) : 0);
538 sprintf(buf, "%d", win_count);
539 setSetting(player->chanuser->user, game->channel, "uno_win", buf);
540 sprintf(buf, "%d", total_win_count);
541 setSetting(player->chanuser->user, NULL, "uno_win", buf);
544 player->prev = cplayer;
546 if(game->players <= 1) {
548 uno_reply(game, NULL, "NF_UNO_GAME_FINISHED");
550 table = table_init(4, winner_count + 3, 0);
552 content[0] = get_language_string(NULL, "NF_UNO_RANK");
553 content[1] = get_language_string(NULL, "NF_UNO_NAME");
554 content[2] = get_language_string(NULL, "NF_UNO_WON_GAMES");
555 content[3] = get_language_string(NULL, "NF_UNO_TOTAL_WON_GAMES");
556 table_add(table, content);
558 char rank_buf[20], won_buf[50], total_won_buf[50];
560 for(cplayer = game->winner; cplayer; cplayer = cplayer->next) {
561 sprintf(rank_buf, "%d", winner_count++);
562 content[0] = rank_buf;
563 content[1] = cplayer->chanuser->user->nick;
564 if((cplayer->chanuser->user->flags & USERFLAG_ISAUTHED)) {
565 sprintf(won_buf, "%d/%d", ((tmp = getSetting(cplayer->chanuser->user, game->channel, "uno_win")) ? atoi(tmp) : 0), ((tmp2 = getSetting(cplayer->chanuser->user, game->channel, "uno_games")) ? atoi(tmp2) : 0));
566 content[2] = won_buf;
567 sprintf(total_won_buf, "%d/%d", ((tmp = getSetting(cplayer->chanuser->user, NULL, "uno_win")) ? atoi(tmp) : 0), ((tmp2 = getSetting(cplayer->chanuser->user, NULL, "uno_games")) ? atoi(tmp2) : 0));
568 content[3] = total_won_buf;
573 table_add(table, content);
575 cplayer = game->player;
576 sprintf(rank_buf, "%d", winner_count++);
577 content[0] = rank_buf;
578 content[1] = cplayer->chanuser->user->nick;
579 if((cplayer->chanuser->user->flags & USERFLAG_ISAUTHED)) {
580 sprintf(won_buf, "%d/%d", ((tmp = getSetting(cplayer->chanuser->user, game->channel, "uno_win")) ? atoi(tmp) : 0), ((tmp2 = getSetting(cplayer->chanuser->user, game->channel, "uno_games")) ? atoi(tmp2) : 0));
581 content[2] = won_buf;
582 sprintf(total_won_buf, "%d/%d", ((tmp = getSetting(cplayer->chanuser->user, NULL, "uno_win")) ? atoi(tmp) : 0), ((tmp2 = getSetting(cplayer->chanuser->user, NULL, "uno_games")) ? atoi(tmp2) : 0));
583 content[3] = total_won_buf;
588 table_add(table, content);
589 char **table_lines = table_end(table);
591 for(i = 0; i < table->entrys; i++) {
592 uno_reply(game, NULL, table_lines[i]);
599 if(card->card == UNO_CARD_DIRECTION)
600 game->reverse_direction = (game->reverse_direction ? 0 : 1);
601 struct uno_player *next_player = uno_get_next_player(game);
602 game->active_player = next_player;
603 if(card->card == UNO_CARD_SKIP) {
604 uno_reply(game, NULL, "NF_UNO_USER_SKIP", game->active_player->chanuser->user->nick);
605 next_player = uno_get_next_player(game);
606 game->active_player = next_player;
608 if(card->card == UNO_CARD_ADD_2 || card->card == UNO_CARD_ADD_4) {
610 for(card = game->top_card; card; card = card->prev) {
611 if(card->card == UNO_CARD_ADD_2)
613 else if(card->card == UNO_CARD_ADD_4)
616 uno_reply(game, NULL, "NF_UNO_ADD_CARD", game->active_player->chanuser->user->nick, ccount);
617 game->take_cards_pending = 1;
619 uno_reply(game, NULL, "NF_UNO_USER_HURRY_UP", game->active_player->chanuser->user->nick);
620 uno_show_player_cards(game, game->active_player);
621 game->timer = timeq_add(30, module_id, uno_player_timeout, game);
624 void uno_event_part(struct ChanUser *chanuser) {
625 struct uno_game *game;
626 for(game = uno_active_games; game; game = game->next) {
627 if(chanuser->chan == game->channel) {
628 struct uno_player *player;
629 for(player = game->player; player; player = player->next) {
630 if(player->chanuser == chanuser) {
631 uno_free_player(player, game->deck);
639 void uno_event_quit(struct UserNode *user) {
640 struct uno_game *game;
641 for(game = uno_active_games; game; game = game->next) {
642 struct uno_player *player;
643 for(player = game->player; player; player = player->next) {
644 if(player->chanuser->user == user) {
645 uno_free_player(player, game->deck);
652 void uno_event_freechan(struct ChanNode *chan) {
653 struct uno_game *game;
654 for(game = uno_active_games; game; game = game->next) {
655 if(game->channel == chan) {