예제 #1
0
        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));
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        void Cmd_EloTop(string nick, string message)
        {
            Channel channel = p_manager.GetChannel();

            var leaderboard = new Dictionary <string, int>();
            var dummy       = new UnoPlayer(null, null);

            foreach (string key in m_settings.IterateKeys())
            {
                if (!m_settings.Get(key, ref dummy))
                {
                    continue;
                }
                leaderboard.Add(key, dummy.GetElo());
            }
            int    n   = 0;
            string val = "";

            foreach (var record in leaderboard.OrderByDescending(i => i.Value))
            {
                if (n > 0)
                {
                    val += ", ";
                }

                val += record.Key + " (" + record.Value + ")";
                if (++n == 5)
                {
                    break;
                }
            }
            channel.Say("[UNO] Top 5 leaderboard: " + val);
        }
예제 #5
0
        public bool RemovePlayer(Channel channel, string nick)
        {
            UnoPlayer player = GetPlayer(nick);

            if (player == null)
            {
                return(false);
            }

            if (current_player == player.name)
            {
                TurnNext();
            }

            if (is_active && player.cards.Count == 0)
            {
                int score = 0;
                foreach (UnoPlayer up in players)
                {
                    if (up != player)
                    {
                        score += up.GetCardsValue();
                    }
                }

                string log = player.name + " finishes the game and gains "
                             + score + " points";
                if (CheckMode(UnoMode.RANKED))
                {
                    player.Win(players, initial_player_count);

                    foreach (UnoPlayer up in players)
                    {
                        m_settings.Set(up.name, up);
                    }

                    log += ". Elo: " + player.ShowElo(false);
                }
                channel.Say(log);
            }
            else
            {
                channel.Say(player.name + " left this UNO game.");
            }

            players.Remove(player);
            if (!is_active)
            {
                initial_player_count = players.Count;
            }
            return(true);
        }
예제 #6
0
        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);
        }
예제 #7
0
        public override void OnUserRename(string nick, string old_nick)
        {
            foreach (KeyValuePair <string, UnoChannel> chan in m_channels)
            {
                UnoPlayer player = chan.Value.players.Find(item => item.name == old_nick);
                if (player != null)
                {
                    player.name = nick;
                }

                if (chan.Value.current_player == old_nick)
                {
                    chan.Value.current_player = nick;
                }
            }
        }
예제 #8
0
        void Cmd_Elo(string nick, string message)
        {
            Channel channel = p_manager.GetChannel();
            string  who     = Chatcommand.GetNext(ref message);

            if (who.Length == 0)
            {
                who = nick;
            }

            var player = new UnoPlayer(who, null);

            if (!m_settings.Get(who, ref player))
            {
                channel.Say("[UNO] " + who + ": No information available");
            }
            else
            {
                channel.Say("[UNO] " + who + ": " + player.ShowElo(true));
            }
        }
예제 #9
0
        public bool RemovePlayer(Channel channel, string nick)
        {
            UnoPlayer player = GetPlayer(nick);

            if (player == null)
            {
                return(false);
            }

            if (current_player == player.name)
            {
                TurnNext();
            }

            if (is_active && player.cards.Count == 0)
            {
                int score = 0;
                foreach (UnoPlayer up in players)
                {
                    if (up != player)
                    {
                        score += up.GetCardsValue();
                    }
                }

                channel.Say(player.name + " finishes the game and gains " + score + " points");
            }
            else
            {
                channel.Say(player.name + " left this UNO game.");
            }

            players.Remove(player);
            player = null;             // So that GC works
            GC.Collect();
            return(true);
        }
예제 #10
0
        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);
            }
        }
예제 #11
0
        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));
        }
예제 #12
0
 public void AddPlayer(UnoPlayer player)
 {
     players.Add(player);
     current_player       = player.name;
     initial_player_count = players.Count;
 }