예제 #1
0
        /// <summary>
        /// Get messages to send in response to a JoinMessage
        /// </summary>
        /// <param name="uid"> The uid of the player </param>
        /// <param name="joinMessage"></param>
        /// <returns> List of messages to be sent </returns>
        public MessagePackets HandleJoin(string uid, JoinMessage joinMessage)
        {
            lock (this)
            {
                if (PlayerGameTypeMap.ContainsKey(uid))
                {
                    PlayerGameNameMap.Add(uid, joinMessage.GameName);

                    string gameType = PlayerGameTypeMap[uid];
                    if (GameNameMap[gameType].ContainsKey(joinMessage.GameName))
                    {
                        // The game exists, so join it
                        return(GameNameMap[gameType][joinMessage.GameName].HandleJoin(uid, joinMessage));
                    }
                    else
                    {
                        MessagePackets messages = new MessagePackets();

                        // The game doesn't exist, so make a new one and join it
                        GameManager gm = (GameManager)Activator.CreateInstance(GameManagerMap[gameType]);
                        GameNameMap[gameType].Add(joinMessage.GameName, gm);
                        messages.Add(gm.HandleJoin(uid, joinMessage));

                        // Push available games update
                        messages.Add(GetAvailableGamesMessage(gameType));

                        return(messages);
                    }
                }
                else
                {
                    throw new Exception("Game type not known for player " + uid);
                }
            }
        }
예제 #2
0
        /// <summary>
        /// By default, when the round is started just start the first trick with the current player.
        /// Called when enough players have joined the game, or when the game is restarted.
        /// Subclasses should override to enable different behaviors.
        /// </summary>
        /// <returns> List of messages to be sent </returns>
        protected virtual MessagePackets DoStartRound()
        {
            MessagePackets messages = new MessagePackets();

            messages.Add(GetStartMessages());
            messages.Add(StartTrick(CurPlayer, true));
            return(messages);
        }
예제 #3
0
        /// <summary>
        /// Start a round by starting passing.
        /// </summary>
        /// <returns> List of messages to be sent </returns>
        protected override MessagePackets DoStartRound()
        {
            MessagePackets messages = new MessagePackets();

            messages.Add(GetStartMessages());
            messages.Add(StartPass());
            return(messages);
        }
예제 #4
0
        /// <summary>
        /// Starts a round by starting the bid and sending out meld points
        /// </summary>
        /// <returns> List of messages to be sent </returns>
        protected override MessagePackets DoStartRound()
        {
            MessagePackets messages = new MessagePackets();

            messages.Add(GetStartMessages());
            messages.Add(StartBid(GetCurrentPlayer(), GetDealerIndex()));
            messages.Add(GetMeldPointsMessages());
            return(messages);
        }
예제 #5
0
        /// <summary>
        /// Start the round with dealing first 5 cards and deciding trump
        /// </summary>
        /// <returns> List of messages to be sent </returns>
        protected override MessagePackets DoStartRound()
        {
            MessagePackets messages = new MessagePackets();
            Player         p        = GetPlayer(GetDealerIndex());

            messages.Add(new StartMessage(p.Cards.Take(5).ToArray()), p.Uid);
            messages.Add(GetBroadcastMessage(new TrumpMessage(p.Name, unavailableOptions: p.TrumpUsed.ToArray(), extraOptions: ExtraTrumpOptions)));
            return(messages);
        }
예제 #6
0
        /// <summary>
        /// Get messages to send in response to a player disconnecting
        /// </summary>
        /// <param name="playerId"> The uid of the player </param>
        /// <returns> List of messages to be sent </returns>
        public MessagePackets HandlePlayerDisconnect(string playerId)
        {
            lock (this)
            {
                MessagePackets messages = new MessagePackets();

                GameManager gm = GetGameManager(playerId);
                messages.Add(Do(gm, () => gm.HandleDisconnect(playerId)));
                messages.Add(RemovePlayer(playerId));

                return(messages);
            }
        }
예제 #7
0
        /// <summary>
        /// Handle a TrumpMessage.
        /// </summary>
        /// <param name="trumpMessage"></param>
        /// <returns> List of messages to be sent </returns>
        public override MessagePackets HandleTrump(TrumpMessage trumpMessage)
        {
            MessagePackets messages = new MessagePackets();

            // Broadcast to all players
            messages.Add(GetBroadcastMessage(trumpMessage));

            // Set trump suit
            ((PinochleTrickDecider)GetDecider()).Trump = trumpMessage.TrumpSuit;

            // Initiate meld round
            messages.Add(StartMeld(trumpMessage.TrumpSuit));

            return(messages);
        }
예제 #8
0
        /// <summary>
        /// Start passing round.
        /// </summary>
        /// <returns> List of messages to be sent </returns>
        private MessagePackets StartPass()
        {
            MessagePackets messages = new MessagePackets();

            List <Player> players = GetPlayersMutable();

            for (int i = 0; i < players.Count; i++)
            {
                // Get player to pass to
                int idx = (i + PASS_DIRS[CurPass]) % players.Count;
                if (idx < 0)
                {
                    idx = players.Count() + idx;
                }
                string passingTo = players[idx].Name;

                // Update and send pass message
                PassMessage passMessage = new PassMessage(players[i].Name, NUM_TO_PASS, passingTo);
                PassMessages.Add(passMessage);
                messages.Add(passMessage, players[i].Uid);
            }

            // Update pass direction
            CurPass = (CurPass + 1) % PASS_DIRS.Length;

            return(messages);
        }
예제 #9
0
        /// <summary>
        /// Start meld round.
        /// </summary>
        /// <param name="trump"> Trump suit </param>
        /// <returns> List of messages to be sent </returns>
        private MessagePackets StartMeld(string trump)
        {
            MessagePackets messages = new MessagePackets();

            foreach (Player p in GetPlayersMutable())
            {
                MeldCounter counter = new MeldCounter(p.Cards, trump, Suits.Count, Ranks.Count);
                p.MeldScore = counter.TotalMeld();
                MeldMessage message = new MeldMessage(p.Name, trump, p.MeldScore)
                {
                    AcesAround       = counter.AcesAround(),
                    KingsAround      = counter.KingsAround(),
                    QueensAround     = counter.QueensAround(),
                    JacksAround      = counter.JacksAround(),
                    TrumpNine        = counter.Nines(),
                    Run              = counter.Runs(),
                    ClubsMarriage    = counter.ClubsMarriage(),
                    DiamondsMarriage = counter.DiamondsMarriage(),
                    SpadesMarriage   = counter.SpadesMarriage(),
                    HeartsMarriage   = counter.HeartsMarriage(),
                    Pinochle         = counter.Pinochle()
                };
                messages.Add(message, p.Uid);
            }

            return(messages);
        }
예제 #10
0
        /// <summary>
        /// Handle a MeldMessage
        /// </summary>
        /// <param name="meldMessage"></param>
        /// <returns> List of messages to be sent </returns>
        public override MessagePackets HandleMeld(MeldMessage meldMessage)
        {
            MessagePackets messages = new MessagePackets();

            // Broadcast to all players
            messages.Add(GetBroadcastMessage(meldMessage));

            // Start first trick if all meld is in
            NumMeld++;
            if (NumMeld == GetNumPlayers())
            {
                NumMeld = 0;
                messages.Add(StartTrick(LastBidder));
            }

            return(messages);
        }
예제 #11
0
        /// <summary>
        /// Update all player scores and broadcast them to all players
        /// </summary>
        /// <returns> List of messages to be sent </returns>
        private MessagePackets GetScoreMessages()
        {
            MessagePackets messages = new MessagePackets();

            foreach (Player p in Players)
            {
                messages.Add(GetBroadcastMessage(new ScoreMessage(p.Name, p.Score, p.Score - p.OldScore, p.MissedBidBy)));
            }
            return(messages);
        }
예제 #12
0
        protected MessagePackets GetStartMessages()
        {
            MessagePackets messages = new MessagePackets();

            foreach (Player p in Players)
            {
                messages.Add(new StartMessage(p.Cards.ToArray()), p.Uid);
            }
            return(messages);
        }
예제 #13
0
        /// <summary>
        /// Handle a BidMessage.
        /// </summary>
        /// <param name="bidMessage"></param>
        /// <returns> List of messages to be sent </returns>
        public override MessagePackets HandleBid(BidMessage bidMessage)
        {
            MessagePackets messages = new MessagePackets();

            // Broadcast bid to all players
            messages.Add(GetBroadcastMessage(bidMessage));

            // Parse bid
            CurBid = bidMessage.Bid;
            if (bidMessage.Bid != 0)
            {
                LastBidder = GetCurrentPlayerIndex();
            }
            else
            {
                CurBid = bidMessage.CurBid;
                PassedPlayers.Add(GetCurrentPlayerIndex());
            }

            // Get next non-passed player
            NextPlayer();
            while (PassedPlayers.Contains(GetCurrentPlayerIndex()) && GetCurrentPlayerIndex() != LastBidder)
            {
                NextPlayer();
            }

            // Handle last bid
            if (GetCurrentPlayerIndex() == LastBidder)
            {
                messages.Add(GetBroadcastMessage(new BidMessage(GetCurrentPlayer().Name, CurBid, CurBid)));
                PassedPlayers = new List <int>();
                messages.Add(StartKitty(GetCurrentPlayerIndex()));
            }

            // Initiate next bid
            else
            {
                Player player = GetCurrentPlayer();
                messages.Add(GetBroadcastMessage(new BidMessage(player.Name, CurBid)));
            }

            return(messages);
        }
예제 #14
0
        /// <summary>
        /// Handle a TrumpMessage.
        /// </summary>
        /// <param name="trumpMessage"></param>
        /// <returns> List of messages to be sent </returns>
        public override MessagePackets HandleTrump(TrumpMessage trumpMessage)
        {
            MessagePackets messages = new MessagePackets();

            // Broadcast to all players
            messages.Add(GetBroadcastMessage(trumpMessage));

            // Save trump and update player model
            ((TrumpDecider)GetDecider()).Trump = trumpMessage.TrumpSuit;
            Player choosingPlayer = GetPlayersMutable().Where(p => p.Name == trumpMessage.ChoosingPlayer).Single();

            choosingPlayer.TrumpUsed.Add(trumpMessage.TrumpSuit);

            // Send out cards and start first trick
            messages.Add(GetStartMessages());
            messages.Add(GetTrickInfoMessage());
            messages.Add(StartTrick(GetDealerIndex()));
            return(messages);
        }
예제 #15
0
        /// <summary>
        /// Handle a JoinMessage.
        /// </summary>
        /// <param name="message"> The received join message </param>
        /// <param name="playerId"> The uid of the player joining </param>
        /// <returns> List of messages to be sent </returns>
        public MessagePackets HandleJoin(string playerId, JoinMessage message)
        {
            // Verify game state
            VerifyNotOver();
            VerifyNotStarted();

            MessagePackets messages = new MessagePackets();

            if (Players.Any(p => p.Name == message.UserName))
            {
                // Handle user name already exists in game
                messages.Add(new JoinResponse(false, errorMessage: string.Format("The name '{0}' already exists in the game '{1}'", message.UserName, message.GameName)), playerId);
            }
            else
            {
                // Send success response
                messages.Add(new JoinResponse(true, message.UserName), playerId);

                // Inform new player of all existing players
                foreach (Player p in Players)
                {
                    messages.Add(new JoinMessage(p.Name, message.GameName, p.Order), playerId);
                }

                // Create new player model
                Player player = new Player(message.UserName, playerId, Players.Count);
                Players.Add(player);

                // Broadcast new player to all players with correct order
                message.Order = player.Order;
                messages.Add(GetBroadcastMessage(message));

                // There are enough players, so start the game
                if (Players.Count == DoGetMinPlayers())
                {
                    messages.Add(StartRound());
                }
            }

            return(messages);
        }
예제 #16
0
        /// <summary>
        /// Handle a RestartMessage.
        /// </summary>
        /// <param name="restartMessage"></param>
        /// <returns> List of messages to be sent </returns>
        public MessagePackets HandleRestart(RestartMessage restartMessage)
        {
            if (!restartMessage.NewGame)
            {
                // Restart the same game
                VerifyStarted();
                Reset();
                return(StartRound());
            }
            else
            {
                MessagePackets messages = new MessagePackets();

                // Confirm restart request
                Player player = Players.Where(p => p.Name == restartMessage.PlayerName).Single();
                messages.Add(restartMessage, player.Uid);

                // Inform other players the player left the old game
                messages.Add(DisconnectPlayer(player));

                return(messages);
            }
        }
예제 #17
0
        /// <summary>
        /// Handle a PassMessage.
        /// </summary>
        /// <param name="passMessage"></param>
        /// <returns> List of messages to be sent </returns>
        public override MessagePackets HandlePass(PassMessage passMessage)
        {
            MessagePackets messages = new MessagePackets();

            // Add pass message
            PassMessages.Where(pm => pm.PassingPlayer == passMessage.PassingPlayer).Single().PassedCards = passMessage.PassedCards;

            // Continue once all passes have been completed
            if (PassMessages.Where(pm => pm.PassedCards != null).Count() == GetNumPlayers())
            {
                foreach (PassMessage pm in PassMessages)
                {
                    if (pm.PassingPlayer != pm.PassingTo)
                    {
                        // Update players' cards
                        Player passingToPlayer = GetPlayersMutable().Where(p => p.Name == pm.PassingTo).Single();
                        Player passingPlayer   = GetPlayersMutable().Where(p => p.Name == pm.PassingPlayer).Single();
                        passingToPlayer.Cards.AddRange(pm.PassedCards);
                        passingPlayer.Cards.RemoveAll(c => pm.PassedCards.Any(h => h.Equals(c)));

                        // Send new cards to player
                        messages.Add(pm, passingToPlayer.Uid);
                    }
                }

                // Initiate first trick
                List <Player> players        = GetPlayersMutable();
                int           startingPlayer = players.IndexOf(players.Where(p => p.Cards.Any(c => c.Suit == "C" && c.Rank == "2")).Single());
                messages.Add(StartTrick(startingPlayer, true));

                // Reset pass messages
                PassMessages = new List <PassMessage>();
            }

            return(messages);
        }
예제 #18
0
        /// <summary>
        /// Get messages to send in response to a RestartMessage
        /// </summary>
        /// <param name="playerId"> The uid of the player </param>
        /// <param name="restartMessage"></param>
        /// <returns> List of messages to be sent </returns>
        public MessagePackets HandleRestart(string playerId, RestartMessage restartMessage)
        {
            lock (this)
            {
                MessagePackets messages = new MessagePackets();

                GameManager gm = GetGameManager(playerId);
                messages.Add(Do(gm, () => gm.HandleRestart(restartMessage)));

                if (restartMessage.NewGame)
                {
                    RemovePlayer(playerId);
                }

                return(messages);
            }
        }
예제 #19
0
        /// <summary>
        /// Handle a DisconnectMessage.
        /// </summary>
        /// <param name="playerId"> The uid of the disconnected player </param>
        /// <returns> List of messages to be sent </returns>
        public MessagePackets HandleDisconnect(string playerId)
        {
            MessagePackets messages = new MessagePackets();

            Player player = Players.Where(p => p.Uid == playerId).SingleOrDefault();

            if (player != null)
            {
                messages.Add(DisconnectPlayer(player));
            }
            else
            {
                throw new Exception("Player " + playerId + " does not exist");
            }

            return(messages);
        }
예제 #20
0
        /// <summary>
        /// Handle a TurnMessage.
        /// </summary>
        /// <param name="message"> The received turn message </param>
        /// <returns> List of messages to be sent </returns>
        public MessagePackets HandleTurn(TurnMessage message)
        {
            // Verify game state
            VerifyGameRunning();
            VerifyPlayer(message.PlayerName);

            // Broadcast turn to all players
            MessagePackets messages = new MessagePackets();

            messages.Add(GetBroadcastMessage(message));

            // Add card to current trick, and remove from player's hand
            CurTrick.Add(message.Card);
            Players[CurPlayer].Cards.Remove(message.Card);

            // Update CurPlayer
            NextPlayer();

            // Handle all players have played
            if (CurPlayer == Leader)
            {
                // Decide and score trick
                int winningPlayer = DecideTrick();
                messages.Add(ScoreTrick(winningPlayer));

                // Broadcast trick to all players
                messages.Add(GetBroadcastMessage(new TrickMessage(Players[winningPlayer].Name)));

                // Handle last trick
                if (Players.All(p => p.Cards.Count == 0))
                {
                    DoLastTrick(winningPlayer);

                    // Update, send, and clear scores
                    UpdateScores();
                    messages.Add(GetScoreMessages());
                    ClearPerHandScores();

                    // Handle game over
                    if (DoShouldGameEnd())
                    {
                        messages.Add(EndGame());
                    }
                    // Initiate next hand
                    else
                    {
                        NextDealer();
                        messages.Add(StartRound());
                    }
                }
                // Initiate next trick
                else
                {
                    messages.Add(StartTrick(winningPlayer));
                }
            }
            // Handle next turn
            else
            {
                messages.Add(NextTurn());
            }

            return(messages);
        }