bool CheckGameEndDelete(string channel) { UnoChannel uno = GetUnoChannel(channel); if (uno == null) { return(true); } if (uno.players.Count > 1) { return(false); } if (uno.is_active) { E.Say(channel, "[UNO] Game ended"); } m_settings.SyncFileContents(); // Save player data m_channels.Remove(channel); uno = null; // So that GC works GC.Collect(); return(true); }
void Cmd_Draw(string nick, string message) { Channel channel = p_manager.GetChannel(); UnoChannel uno = GetUnoChannel(channel.GetName()); UnoPlayer player = uno != null?uno.GetPlayer(nick) : null; if (player == null || !uno.is_active) { E.Notice(nick, "You are not part of an UNO game."); return; } if (uno.current_player != nick && !uno.CheckMode(UnoMode.LIGRETTO)) { E.Notice(nick, "It is not your turn (current: " + uno.current_player + ")."); return; } var drawn = player.DrawCards(Math.Max(1, uno.draw_count)); uno.draw_count = 0; E.Notice(nick, "You drew following cards: " + FormatCards(drawn)); uno.TurnNext(); TellGameStatus(channel); }
void TellGameStatus(Channel channel, UnoPlayer player = null) { UnoChannel uno = GetUnoChannel(channel.GetName()); if (uno == null) { return; } // No specific player. Take current one var current = uno.GetPlayer(); if (player == null) { player = current; } var sb = new System.Text.StringBuilder(); sb.Append("[UNO] " + uno.current_player); sb.Append(" (" + current.cards.Count + " cards) - "); sb.Append("Top card: " + FormatCards(new List <Card> { uno.top_card })); if (uno.draw_count > 0) { sb.Append("- draw count: " + uno.draw_count); } channel.Say(sb.ToString()); E.Notice(player.name, "Your cards: " + FormatCards(player.cards)); }
void Cmd_Deal(string nick, string message) { Channel channel = p_manager.GetChannel(); UnoChannel uno = GetUnoChannel(channel.GetName()); UnoPlayer nplayer = uno != null?uno.GetPlayer(nick) : null; if (nplayer == null || uno.is_active) { E.Notice(nick, "You are either not part of the game or " + " another is already ongoing."); return; } if (uno.players.Count < 2) { channel.Say("At least two player are required to start the game."); return; } foreach (UnoPlayer player in uno.players) { player.DrawCards(11, 2); } uno.top_card = nplayer.cards[0]; uno.is_active = true; TellGameStatus(channel); }
void Cmd_Leave(string nick, string message) { Channel channel = p_manager.GetChannel(); UnoChannel uno = GetUnoChannel(channel.GetName()); if (uno == null || uno.GetPlayer(nick) == null) { E.Notice(nick, "You are not part of an UNO game."); return; } OnUserLeave(nick); }
void Cmd_Top(string nick, string message) { Channel channel = p_manager.GetChannel(); UnoChannel uno = GetUnoChannel(channel.GetName()); UnoPlayer player = uno != null?uno.GetPlayer(nick) : null; if (player == null || !uno.is_active) { E.Notice(nick, "You are not part of an UNO game."); return; } TellGameStatus(channel, player); }
public override void OnUserLeave(string nick) { Channel channel = p_manager.GetChannel(); UnoChannel uno = GetUnoChannel(channel.GetName()); string old_player = uno == null ? null : uno.current_player; if (uno == null || !uno.RemovePlayer(channel, nick)) { return; } // Either close the game or echo the status if (!CheckGameEndDelete(channel.GetName())) { if (nick == old_player) { TellGameStatus(channel); } } }
void Cmd_Join(string nick, string message) { Channel channel = p_manager.GetChannel(); UnoChannel uno = GetUnoChannel(channel.GetName()); if (uno != null && uno.is_active) { channel.Say(nick + ": Please wait for " + uno.current_player + " to finish their game."); return; } if (uno != null && uno.GetPlayer(nick) != null) { E.Notice(nick, "You already joined the game."); return; } // Create a new UnoChannel if (uno == null) { string modes_s = Chatcommand.GetNext(ref message); byte modes = 0x03; try { modes = Convert.ToByte(modes_s, 16); } catch { } uno = new UnoChannel(modes); m_channels[channel.GetName()] = uno; } UserData user = channel.GetUserData(nick); user.cmd_scope = m_subcommand; uno.players.Add(new UnoPlayer(nick, user)); uno.current_player = nick; channel.Say("[UNO] " + uno.players.Count + " player(s) are waiting for a new UNO game. " + string.Format("Modes: 0x{0:X2}", uno.modes)); }
void Cmd_Put(string nick, string message) { Channel channel = p_manager.GetChannel(); UnoChannel uno = GetUnoChannel(channel.GetName()); UnoPlayer player = uno != null?uno.GetPlayer(nick) : null; if (player == null || !uno.is_active) { E.Notice(nick, "huh?? You don't have any cards."); return; } if (uno.current_player != nick && !uno.CheckMode(UnoMode.LIGRETTO)) { E.Notice(nick, "It is not your turn (current: " + uno.current_player + ")."); return; } uno.current_player = nick; // UnoMode.LIGRETTO string put_color_s = Chatcommand.GetNext(ref message).ToUpper(); CardColor put_color = CardColor.NONE; string put_face = Chatcommand.GetNext(ref message).ToUpper(); if (put_color_s.Length >= 2) { // The following format: "gwd4", "g4" put_face = put_color_s.Substring(1); put_color_s = put_color_s.Remove(1); } // Convert user input to internal format switch (put_color_s) { case "B": put_color = CardColor.BLUE; break; case "R": put_color = CardColor.RED; break; case "G": put_color = CardColor.GREEN; break; case "Y": put_color = CardColor.YELLOW; break; } bool change_face = false; if (put_face.Contains("W")) { // Convert/validate W and WD4 change_face = true; } if (put_color == CardColor.NONE || !card_faces.Contains(put_face)) { E.Notice(nick, "Invalid input. Syntax: $uno p <color> <face>, $p <color><face>."); return; } // Check whether color of face matches if (put_color != uno.top_card.Key && put_face != uno.top_card.Value && !change_face) { E.Notice(nick, "This card cannot be played. Please check color and face."); return; } int card_index = -1; if (change_face) { card_index = player.cards.FindIndex(item => item.Value == put_face); } else { card_index = player.cards.FindIndex( item => item.Key == put_color && item.Value == put_face); } if (card_index < 0) { E.Notice(nick, "You don't have this card."); return; } if (uno.draw_count > 0) { bool ok = false; if (put_face == "D2" && put_face == uno.top_card.Value && // No downgrade uno.CheckMode(UnoMode.STACK_D2)) { ok = true; } else if (put_face == "WD4" && put_face == uno.top_card.Value && uno.CheckMode(UnoMode.STACK_WD4)) { ok = true; } else if (put_face == "WD4" && uno.top_card.Value == "D2" && uno.CheckMode(UnoMode.UPGRADE)) { ok = true; } if (!ok) { E.Notice(nick, "You cannot play this card due to the top card."); return; } } // All OK. Put the card on top uno.top_card = new Card(put_color, put_face); player.cards.RemoveAt(card_index); bool pending_autodraw = false; switch (put_face) { case "D2": uno.draw_count += 2; pending_autodraw = !uno.CheckMode(UnoMode.STACK_D2); break; case "WD4": uno.draw_count += 4; pending_autodraw = !uno.CheckMode(UnoMode.STACK_WD4); break; case "R": if (uno.players.Count > 2) { uno.players.Reverse(); } else { uno.TurnNext(); // Acts as Skip for 2 players } break; case "S": uno.TurnNext(); break; } uno.TurnNext(); // Player won, except when it's again their turn (last card = skip) if (player.cards.Count == 0 && uno.current_player != player.name) { uno.RemovePlayer(channel, player.name); } if (CheckGameEndDelete(channel.GetName())) { return; // Game ended } if (pending_autodraw) { Cmd_Draw(uno.current_player, ""); } else { TellGameStatus(channel); } }
void Cmd_Join(string nick, string message) { Channel channel = p_manager.GetChannel(); UnoChannel uno = GetUnoChannel(channel.GetName()); if (uno != null && uno.is_active) { channel.Say(nick + ": Please wait for " + uno.current_player + " to finish their game."); return; } if (uno != null && uno.GetPlayer(nick) != null) { E.Notice(nick, "You already joined the game."); return; } // Create a new UnoChannel if (uno == null) { string modes_s = Chatcommand.GetNext(ref message); byte modes = 0x87; try { modes = Convert.ToByte(modes_s, 16); } catch { } uno = new UnoChannel(modes, m_settings); } if (uno.CheckMode(UnoMode.RANKED) && p_manager.GetUserStatus(nick) != 3) { E.Notice(nick, "You must be logged in to play ranked UNO."); return; } m_channels[channel.GetName()] = uno; // For new channels UserData user = channel.GetUserData(nick); user.cmd_scope = m_subcommand; var player = new UnoPlayer(nick, user); m_settings.Get(nick, ref player); uno.AddPlayer(player); // Human readable modes var modes_list = new List <string>(); for (int i = 1; i < byte.MaxValue; i <<= 1) { if ((uno.modes & i) > 0) { modes_list.Add(FormatMode((UnoMode)(uno.modes & i))); } } channel.Say("[UNO] " + uno.players.Count + " player(s) are waiting for a new UNO game. " + string.Format("Modes: [0x{0:X2}] ", uno.modes) + string.Join(", ", modes_list)); }