/// <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); } } }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); } }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
protected MessagePackets GetStartMessages() { MessagePackets messages = new MessagePackets(); foreach (Player p in Players) { messages.Add(new StartMessage(p.Cards.ToArray()), p.Uid); } return(messages); }
/// <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); }
/// <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); }
/// <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); }
/// <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); } }
/// <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); }
/// <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); } }
/// <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); }
/// <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); }