fixed game_uno +2/+4 timeout handling
[NeonServV5.git] / src / modules / NeonFun.mod / game_uno.c
index 1500c243b44fdb0e091b26571f8c957733cb642f..2e67edaa2b871febaf38b52300f1cfc4c8cd137a 100644 (file)
@@ -1,4 +1,4 @@
-/* game_uno.c - NeonServ v5.4
+/* game_uno.c - NeonServ v5.6
  * Copyright (C) 2011-2012  Philipp Kreil (pk910)
  * 
  * This program is free software: you can redistribute it and/or modify
@@ -141,6 +141,7 @@ void uno_free_deck(struct uno_card_deck *deck) {
             free(card);
         }
     }
+    free(deck);
 }
 
 void uno_free_player(struct uno_player *player, struct uno_card_deck *deck) {
@@ -328,7 +329,7 @@ TIMEQ_CALLBACK(uno_game_wait_timeout) {
     uno_show_top_card(game);
     game->active_player = game->player; //active player
     uno_reply(game, NULL, "NF_UNO_USER_HURRY_UP", game->active_player->chanuser->user->nick);
-    game->timer = timeq_add(30, module_id, uno_player_timeout, game);
+    game->timer = timeq_add(40, module_id, uno_player_timeout, game);
 }
 
 TIMEQ_CALLBACK(uno_player_timeout) {
@@ -337,22 +338,42 @@ TIMEQ_CALLBACK(uno_player_timeout) {
     //player timeout (take another card)
     struct uno_player *player = game->active_player, *next_player = uno_get_next_player(game);
     //add a card to the players deck
-    if(!game->deck->count)
-        game->deck = uno_shuffle_deck();
-    struct uno_card *card = uno_get_card(game->deck);
-    if(!card) {
-        uno_reply(game, NULL, "NF_UNO_ERROR", 2);
-        uno_free_game(game);
-        return;
+    int ccount;
+    if(game->take_cards_pending) {
+        //count cards to take
+        struct uno_card *card;
+        ccount = 0;
+        for(card = game->top_card; card; card = card->prev) {
+            if(card->card == UNO_CARD_ADD_2)
+                ccount += 2;
+            else if(card->card == UNO_CARD_ADD_4)
+                ccount += 4;
+        }
+    } else
+        ccount = 1;
+    int i;
+    for(i = 0; i < ccount; i++) {
+        if(!game->deck->count)
+            game->deck = uno_shuffle_deck();
+        struct uno_card *card = uno_get_card(game->deck);
+        if(!card) {
+            uno_reply(game, NULL, "NF_UNO_ERROR", 2);
+            uno_free_game(game);
+            return;
+        }
+        card->next = player->cards;
+        if(player->cards)
+            player->cards->prev = card;
+        player->cards = card;
+        player->count++;
     }
-    card->next = player->cards;
-    if(player->cards)
-        player->cards->prev = card;
-    player->cards = card;
-    player->count++;
     player->timeout = 1;
     game->active_player = next_player;
-    uno_reply(game, NULL, "NF_UNO_USER_TOOK_CARD", player->chanuser->user->nick);
+    if(game->take_cards_pending) {
+        game->take_cards_pending = 0;
+        uno_reply(game, NULL, "NF_UNO_USER_TOOK_CARDS", player->chanuser->user->nick, ccount);
+    } else
+        uno_reply(game, NULL, "NF_UNO_USER_TOOK_CARD", player->chanuser->user->nick);
     struct uno_player *cplayer;
     for(cplayer = game->player; cplayer; cplayer = cplayer->next) {
         if(!cplayer->timeout)
@@ -367,7 +388,7 @@ TIMEQ_CALLBACK(uno_player_timeout) {
     uno_show_top_card(game);
     uno_reply(game, NULL, "NF_UNO_USER_HURRY_UP", game->active_player->chanuser->user->nick);
     uno_show_player_cards(game, game->active_player);
-    game->timer = timeq_add(30, module_id, uno_player_timeout, game);
+    game->timer = timeq_add(40, module_id, uno_player_timeout, game);
 }
 
 void uno_action_take_card(struct uno_game *game, struct uno_player *player) {
@@ -414,7 +435,7 @@ void uno_action_take_card(struct uno_game *game, struct uno_player *player) {
     uno_show_top_card(game);
     uno_reply(game, NULL, "NF_UNO_USER_HURRY_UP", game->active_player->chanuser->user->nick);
     uno_show_player_cards(game, game->active_player);
-    game->timer = timeq_add(30, module_id, uno_player_timeout, game);
+    game->timer = timeq_add(40, module_id, uno_player_timeout, game);
 }
 
 
@@ -479,7 +500,7 @@ struct uno_card *uno_parse_card(struct uno_game *game, struct uno_player *player
 int uno_check_card_valid(struct uno_game *game, struct uno_card *card) {
     if(game->take_cards_pending && card->card != game->top_card->card)
         return 1;
-    if(card->color == UNO_COLOR_BLACK)
+    if(card->color == UNO_COLOR_BLACK || game->top_card->color == UNO_COLOR_BLACK)
         return 0;
     if(card->color != game->top_card->color && card->card != game->top_card->card)
         return 1;
@@ -510,6 +531,8 @@ void uno_play_card(struct uno_game *game, struct uno_player *player, struct uno_
         uno_reply(game, NULL, "NF_UNO_USER_WIN", game->active_player->chanuser->user->nick);
         if(player->prev)
             player->prev->next = player->next;
+        else
+            game->player = player->next;
         if(player->next)
             player->next->prev = player->prev;
         player->next = NULL;
@@ -555,7 +578,7 @@ void uno_play_card(struct uno_game *game, struct uno_player *player, struct uno_
             winner_count = 1;
             char rank_buf[20], won_buf[50], total_won_buf[50];
             char *tmp, *tmp2;
-            for(cplayer = game->winner; cplayer->next; cplayer = cplayer->next) {
+            for(cplayer = game->winner; cplayer; cplayer = cplayer->next) {
                 sprintf(rank_buf, "%d", winner_count++);
                 content[0] = rank_buf;
                 content[1] = cplayer->chanuser->user->nick;
@@ -616,7 +639,7 @@ void uno_play_card(struct uno_game *game, struct uno_player *player, struct uno_
     }
     uno_reply(game, NULL, "NF_UNO_USER_HURRY_UP", game->active_player->chanuser->user->nick);
     uno_show_player_cards(game, game->active_player);
-    game->timer = timeq_add(30, module_id, uno_player_timeout, game);
+    game->timer = timeq_add(40, module_id, uno_player_timeout, game);
 }
 
 void uno_event_part(struct ChanUser *chanuser) {
@@ -634,19 +657,6 @@ void uno_event_part(struct ChanUser *chanuser) {
     }
 }
 
-void uno_event_quit(struct UserNode *user) {
-    struct uno_game *game;
-    for(game = uno_active_games; game; game = game->next) {
-        struct uno_player *player;
-        for(player = game->player; player; player = player->next) {
-            if(player->chanuser->user == user) {
-                uno_free_player(player, game->deck);
-                break;
-            }
-        }
-    }
-}
-
 void uno_event_freechan(struct ChanNode *chan) {
     struct uno_game *game;
     for(game = uno_active_games; game; game = game->next) {