1 /* game_uno.c - NeonServ v5.6
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;
147 void uno_free_player(struct uno_player *player, struct uno_card_deck *deck) {
149 struct uno_card *card, *next_card;
150 for(card = player->cards; card; card = next_card) {
151 next_card = card->next;
153 card->next = deck->cards;
154 deck->cards->prev = card;
162 player->prev->next = player->next;
164 player->next->prev = player->prev;
168 void uno_free_topcard(struct uno_card *card) {
169 struct uno_card *next_card;
170 for(; card; card = next_card) {
171 next_card = card->prev;
176 void uno_free_game(struct uno_game *game) {
177 struct uno_player *player, *next_player;
178 for(player = game->player; player; player = next_player) {
179 next_player = player->next;
180 uno_free_player(player, NULL);
182 for(player = game->winner; player; player = next_player) {
183 next_player = player->next;
184 uno_free_player(player, NULL);
187 uno_free_deck(game->deck);
189 uno_free_topcard(game->top_card);
191 timeq_del(game->timer);
192 struct uno_game *cgame, *pgame = NULL;
193 for(cgame = uno_active_games; cgame; cgame = cgame->next) {
196 pgame->next = game->next;
198 uno_active_games = game->next;
206 struct uno_player *uno_get_next_player(struct uno_game *game) {
207 struct uno_player *player = game->active_player;
208 if(!game->reverse_direction) {
209 player = player->next;
211 player = game->player;
213 player = player->prev;
215 for(player = game->player; player->next; player = player->next) {
216 //loop to the last player
223 void uno_show_player_cards(struct uno_game *game, struct uno_player *player) {
224 struct uno_card *card;
225 char cards_buf[MAXLEN];
226 int cards_bufpos = 0;
227 for(card = player->cards; card; card = card->next) {
231 for(i = 0; i < UNO_COLOR_COUNT; i++) {
232 if(uno_colors[i] == card->color) {
233 cardcolor = uno_irc_colors[i];
234 cardchar = uno_color_chars[i];
239 while(uno_card_types[i].name) {
240 if(uno_card_types[i].type == card->card) {
241 cards_bufpos += sprintf(cards_buf + cards_bufpos, "%s[\003%d%s%s\003]", (cards_bufpos ? " " : ""), cardcolor, cardchar, uno_card_types[i].name);
247 reply(game->textbot, player->chanuser->user, "NF_UNO_YOUR_CARDS", cards_buf);
250 void uno_show_top_card(struct uno_game *game) {
251 struct uno_card *card = game->top_card;
256 for(i = 0; i < UNO_COLOR_COUNT; i++) {
257 if(uno_colors[i] == card->color) {
258 cardcolor = uno_irc_colors[i];
259 cardchar = uno_color_chars[i];
264 while(uno_card_types[i].name) {
265 if(uno_card_types[i].type == card->card) {
266 if(card->card == UNO_CARD_ADD_4 || card->card == UNO_CARD_COLOR)
268 sprintf(card_buf, "[\003%d%s%s\003]", cardcolor, cardchar, uno_card_types[i].name);
273 uno_reply(game, NULL, "NF_UNO_TOP_CARD", card_buf);
276 TIMEQ_CALLBACK(uno_game_wait_timeout) {
277 struct uno_game *game = data;
279 if(game->players == 1) {
280 uno_reply(game, NULL, "NF_UNO_LESS_PLAYERS");
284 game->deck = uno_shuffle_deck();
285 uno_reply(game, NULL, "NF_UNO_START");
286 struct uno_player *player;
287 for(player = game->player; player; player = player->next) {
290 for(i = 0; i < 7; i++) {
291 if(!game->deck->count)
292 game->deck = uno_shuffle_deck();
293 struct uno_card *card = uno_get_card(game->deck);
295 uno_reply(game, NULL, "NF_UNO_ERROR", 1);
299 card->next = player->cards;
301 player->cards->prev = card;
302 player->cards = card;
305 uno_show_player_cards(game, player);
306 if((player->chanuser->user->flags & USERFLAG_ISAUTHED)) {
308 int game_count = ((tmp = getSetting(player->chanuser->user, game->channel, "uno_games")) ? atoi(tmp) : 0);
309 int total_game_count = ((tmp = getSetting(player->chanuser->user, NULL, "uno_games")) ? atoi(tmp) : 0);
313 sprintf(buf, "%d", game_count);
314 setSetting(player->chanuser->user, game->channel, "uno_games", buf);
315 sprintf(buf, "%d", total_game_count);
316 setSetting(player->chanuser->user, NULL, "uno_games", buf);
319 if(!game->deck->count)
320 game->deck = uno_shuffle_deck();
321 struct uno_card *card = uno_get_card(game->deck);
323 uno_reply(game, NULL, "NF_UNO_ERROR", 1);
327 game->top_card = card;
328 game->state = UNO_STATE_RUNNING;
329 uno_show_top_card(game);
330 game->active_player = game->player; //active player
331 uno_reply(game, NULL, "NF_UNO_USER_HURRY_UP", game->active_player->chanuser->user->nick);
332 game->timer = timeq_add(30, module_id, uno_player_timeout, game);
335 TIMEQ_CALLBACK(uno_player_timeout) {
336 struct uno_game *game = data;
338 //player timeout (take another card)
339 struct uno_player *player = game->active_player, *next_player = uno_get_next_player(game);
340 //add a card to the players deck
341 if(!game->deck->count)
342 game->deck = uno_shuffle_deck();
343 struct uno_card *card = uno_get_card(game->deck);
345 uno_reply(game, NULL, "NF_UNO_ERROR", 2);
349 card->next = player->cards;
351 player->cards->prev = card;
352 player->cards = card;
355 game->active_player = next_player;
356 uno_reply(game, NULL, "NF_UNO_USER_TOOK_CARD", player->chanuser->user->nick);
357 struct uno_player *cplayer;
358 for(cplayer = game->player; cplayer; cplayer = cplayer->next) {
359 if(!cplayer->timeout)
363 uno_reply(game, NULL, "NF_UNO_TIMEOUT");
367 uno_show_player_cards(game, player);
368 uno_show_top_card(game);
369 uno_reply(game, NULL, "NF_UNO_USER_HURRY_UP", game->active_player->chanuser->user->nick);
370 uno_show_player_cards(game, game->active_player);
371 game->timer = timeq_add(30, module_id, uno_player_timeout, game);
374 void uno_action_take_card(struct uno_game *game, struct uno_player *player) {
375 timeq_del(game->timer);
377 struct uno_player *next_player = uno_get_next_player(game);
378 //add a card to the players deck
380 if(game->take_cards_pending) {
381 //count cards to take
382 struct uno_card *card;
384 for(card = game->top_card; card; card = card->prev) {
385 if(card->card == UNO_CARD_ADD_2)
387 else if(card->card == UNO_CARD_ADD_4)
393 for(i = 0; i < ccount; i++) {
394 if(!game->deck->count)
395 game->deck = uno_shuffle_deck(game->deck);
396 struct uno_card *card = uno_get_card(game->deck);
398 uno_reply(game, NULL, "NF_UNO_ERROR", 2);
402 card->next = player->cards;
404 player->cards->prev = card;
405 player->cards = card;
408 game->active_player = next_player;
409 if(game->take_cards_pending) {
410 game->take_cards_pending = 0;
411 uno_reply(game, NULL, "NF_UNO_USER_TOOK_CARDS", player->chanuser->user->nick, ccount);
413 uno_reply(game, NULL, "NF_UNO_USER_TOOK_CARD", player->chanuser->user->nick);
414 uno_show_player_cards(game, player);
415 uno_show_top_card(game);
416 uno_reply(game, NULL, "NF_UNO_USER_HURRY_UP", game->active_player->chanuser->user->nick);
417 uno_show_player_cards(game, game->active_player);
418 game->timer = timeq_add(30, module_id, uno_player_timeout, game);
423 struct uno_card *uno_parse_card(struct uno_game *game, struct uno_player *player, char *arg1) {
446 unsigned char ctype = 255, ccolor = 0;
449 while(uno_card_types[i].name) {
450 if(!stricmp(uno_card_types[i].name, arg1)) {
451 ctype = uno_card_types[i].type;
454 for(j = 0; j < UNO_COLOR_COUNT; j++) {
455 sprintf(tmpbuf, "%s%s", uno_color_chars[j], uno_card_types[i].name);
456 if(!stricmp(tmpbuf, arg1)) {
457 ccolor = uno_colors[j];
458 ctype = uno_card_types[i].type;
465 reply(game->textbot, player->chanuser->user, "NF_UNO_UNKNOWN_CARD", arg1);
468 struct uno_card *card;
469 for(card = player->cards; card; card = card->next) {
470 if(card->card == ctype && card->color == ccolor)
474 reply(game->textbot, player->chanuser->user, "NF_UNO_CARD_NOT_IN_DECK");
480 int uno_check_card_valid(struct uno_game *game, struct uno_card *card) {
481 if(game->take_cards_pending && card->card != game->top_card->card)
483 if(card->color == UNO_COLOR_BLACK || game->top_card->color == UNO_COLOR_BLACK)
485 if(card->color != game->top_card->color && card->card != game->top_card->card)
490 void uno_play_card(struct uno_game *game, struct uno_player *player, struct uno_card *card) {
491 timeq_del(game->timer);
494 card->prev->next = card->next;
496 player->cards = card->next;
498 card->next->prev = card->prev;
500 if(!game->take_cards_pending) {
501 uno_free_topcard(game->top_card);
504 card->prev = game->top_card;
506 game->top_card = card;
507 uno_show_top_card(game);
508 if(player->count == 1) {
509 uno_reply(game, NULL, "NF_UNO_ONE_CARD", game->active_player->chanuser->user->nick);
510 } else if(player->count == 0) {
511 uno_reply(game, NULL, "NF_UNO_USER_WIN", game->active_player->chanuser->user->nick);
513 player->prev->next = player->next;
515 game->player = player->next;
517 player->next->prev = player->prev;
520 struct uno_player *cplayer;
521 int winner_count = 0;
523 for(cplayer = game->winner; cplayer->next; cplayer = cplayer->next) {
529 cplayer->next = player;
531 game->winner = player;
532 if((player->chanuser->user->flags & USERFLAG_ISAUTHED)) {
534 int win_count = ((tmp = getSetting(player->chanuser->user, game->channel, "uno_win")) ? atoi(tmp) : 0);
535 int total_win_count = ((tmp = getSetting(player->chanuser->user, NULL, "uno_win")) ? atoi(tmp) : 0);
539 sprintf(buf, "%d", win_count);
540 setSetting(player->chanuser->user, game->channel, "uno_win", buf);
541 sprintf(buf, "%d", total_win_count);
542 setSetting(player->chanuser->user, NULL, "uno_win", buf);
545 player->prev = cplayer;
547 if(game->players <= 1) {
549 uno_reply(game, NULL, "NF_UNO_GAME_FINISHED");
551 table = table_init(4, winner_count + 3, 0);
553 content[0] = get_language_string(NULL, "NF_UNO_RANK");
554 content[1] = get_language_string(NULL, "NF_UNO_NAME");
555 content[2] = get_language_string(NULL, "NF_UNO_WON_GAMES");
556 content[3] = get_language_string(NULL, "NF_UNO_TOTAL_WON_GAMES");
557 table_add(table, content);
559 char rank_buf[20], won_buf[50], total_won_buf[50];
561 for(cplayer = game->winner; cplayer; cplayer = cplayer->next) {
562 sprintf(rank_buf, "%d", winner_count++);
563 content[0] = rank_buf;
564 content[1] = cplayer->chanuser->user->nick;
565 if((cplayer->chanuser->user->flags & USERFLAG_ISAUTHED)) {
566 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));
567 content[2] = won_buf;
568 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));
569 content[3] = total_won_buf;
574 table_add(table, content);
576 cplayer = game->player;
577 sprintf(rank_buf, "%d", winner_count++);
578 content[0] = rank_buf;
579 content[1] = cplayer->chanuser->user->nick;
580 if((cplayer->chanuser->user->flags & USERFLAG_ISAUTHED)) {
581 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));
582 content[2] = won_buf;
583 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));
584 content[3] = total_won_buf;
589 table_add(table, content);
590 char **table_lines = table_end(table);
592 for(i = 0; i < table->entrys; i++) {
593 uno_reply(game, NULL, table_lines[i]);
600 if(card->card == UNO_CARD_DIRECTION)
601 game->reverse_direction = (game->reverse_direction ? 0 : 1);
602 struct uno_player *next_player = uno_get_next_player(game);
603 game->active_player = next_player;
604 if(card->card == UNO_CARD_SKIP) {
605 uno_reply(game, NULL, "NF_UNO_USER_SKIP", game->active_player->chanuser->user->nick);
606 next_player = uno_get_next_player(game);
607 game->active_player = next_player;
609 if(card->card == UNO_CARD_ADD_2 || card->card == UNO_CARD_ADD_4) {
611 for(card = game->top_card; card; card = card->prev) {
612 if(card->card == UNO_CARD_ADD_2)
614 else if(card->card == UNO_CARD_ADD_4)
617 uno_reply(game, NULL, "NF_UNO_ADD_CARD", game->active_player->chanuser->user->nick, ccount);
618 game->take_cards_pending = 1;
620 uno_reply(game, NULL, "NF_UNO_USER_HURRY_UP", game->active_player->chanuser->user->nick);
621 uno_show_player_cards(game, game->active_player);
622 game->timer = timeq_add(30, module_id, uno_player_timeout, game);
625 void uno_event_part(struct ChanUser *chanuser) {
626 struct uno_game *game;
627 for(game = uno_active_games; game; game = game->next) {
628 if(chanuser->chan == game->channel) {
629 struct uno_player *player;
630 for(player = game->player; player; player = player->next) {
631 if(player->chanuser == chanuser) {
632 uno_free_player(player, game->deck);
640 void uno_event_freechan(struct ChanNode *chan) {
641 struct uno_game *game;
642 for(game = uno_active_games; game; game = game->next) {
643 if(game->channel == chan) {