/// <summary> /// 交換カード受け取り時処理 /// </summary> /// <param name="playerId"></param> /// <param name="cards"></param> /// <returns></returns> private ResultOfPlaying ReceivedTradingCards(int playerId, List <Card> cards) { var result = ResultOfPlaying.Accepted; do { // カード枚数チェック if (players[playerId].tradingCardCount != cards.Count) { result = ResultOfPlaying.NotAccepted; break; } // 交換相手を特定 var player = players[playerId]; PrivateStatus opponent = null; switch (player.roleRank) { case RoleRank.Daifugo: opponent = players.FirstOrDefault(p => p.roleRank == RoleRank.Daihinmin); break; case RoleRank.Fugo: opponent = players.FirstOrDefault(p => p.roleRank == RoleRank.Hinmin); break; default: // logger(LogLevel.Error, "Player rank must be Daifugo or Fugo!"); break; } // 交換相手存在チェック if (opponent == null) { // logger( LogLevel.Error, "Not found opponent!"); result = ResultOfPlaying.NotAccepted; break; } // 交換処理 if (!DaifugoFunction.TradeCards(player.hand, cards, opponent.hand)) { // 不正なカードが指定されていた // logger( LogLevel.Error, "Received card is invalid!"); result = ResultOfPlaying.NotAccepted; break; } } while (false); players[playerId].tradingCardCount = 0; return(result); }
/// <summary> /// カード交換時処理 /// </summary> /// <returns></returns> private void UpdateTrading() { // ランクに応じたカード交換枚数を設定 foreach (var player in players) { player.tradingCardCount = player.roleRank switch { RoleRank.Daifugo => 2, RoleRank.Fugo => 1, _ => 0, }; } // デックをシャッフル deck.Shuffle(); // カードを各プレイヤーに配布 DaifugoFunction.DealCardsToPlayers(deck, players); // ゲーム状況を各プレイヤーに通知 var publicStatus = MakePublicStatus(); var tasks = new List <Task>(); foreach (var player in players) { string connection; playerIdToConnectionIdMap.TryGetValue(player.id, out connection); var task = messageTransceiver.SendStatusAsync(connection, publicStatus, player); tasks.Add(task); } foreach (var task in tasks) { task.Wait(); } // クライアントから交換カード受け取り待ち while (players.Any(p => p.tradingCardCount > 0)) { if (phase == Phase.End) { return; } } phase = Phase.BeforPlaying; }
/// <summary> /// プレイヤー参加受付時処理 /// </summary> /// <returns></returns> private void UpdateAcceptingPlayer() { while (players.Count < playerCount && !isStoppedAcceptingPlayer) { } if (isStoppedAcceptingPlayer) { // TODO: プレイヤー数を満たしていない場合はAIプレイヤーを参加させる } // プレイヤーの席順決定 DaifugoFunction.AssignPlayersToSeats(players, seats); // フェーズをカード交換に移行 phase = Phase.Trading; }
/// <summary> /// ターンのプレイヤーからカードを受け取り時の処理 /// </summary> /// <param name="playerId"></param> /// <param name="cards"></param> /// <returns></returns> private ResultOfPlaying ReceivedPlayingCards(int playerId, List <Card> cards) { ResultOfPlaying result = ResultOfPlaying.Accepted; do { if (playerId != Turn) { // logger( LogLevel.Error, "Not player turn. Player(" + playerId + ")"); result = ResultOfPlaying.NotAccepted; // フェーズを進めずリターン return(result); } var playerHand = players[playerId].hand; var field = fieldStack.FirstOrDefault(); if (DaifugoFunction.ArePlayedCardsValid(cards, playerHand, field)) { // フィールドスタックにカードを追加して fieldStack.Push(cards); // パスフラグをリセット players.ForEach(p => p.hasPassed = false); result = ResultOfPlaying.Accepted; } else { players[playerId].hasPassed = true; if (players.All(p => p.hasPassed || p.hand.Count == 0)) { // 全員パスなら、場を流してパスフラグをリセット while (fieldStack.Count > 0) { flowedCards.AddRange(fieldStack.Pop()); } players.ForEach(p => p.hasPassed = false); } result = ResultOfPlaying.NotAccepted; } } while (false); phase = Phase.AfterPlaying; return(result); }
/// <summary> /// フィールドに対して、有効なカードか判定 /// </summary> /// <param name="playedCards"></param> /// <param name="playerHand"></param> /// <param name="fieldCards"></param> /// <returns></returns> public static bool ArePlayedCardsValid(List <Card> playedCards, List <Card> playerHand, List <Card> fieldCards) { // 出されたカードが無いのであれば無効とする if (playedCards == null || playedCards.Count == 0) { return(false); } // フィールドカードと枚数が違うならば無効 if (fieldCards != null && fieldCards.Count > 0 && playedCards.Count != fieldCards.Count) { return(false); } // 出されたカードがプレイヤーの手札に無いものがあれば無効 if (playedCards.Any(c => !playerHand.Contains(c))) { return(false); } // 出されたカード内に同じカードが複数あれば無効 if (playedCards.GroupBy(c => c).Any(g => g.Count() >= 2)) { return(false); } if (fieldCards != null && fieldCards.Count == 1) { // フィールドカードが1枚ならば単純にランク比較 var playedRank = DaifugoFunction.NumberToRank(playedCards[0].number); var fieldRank = DaifugoFunction.NumberToRank(fieldCards[0].number); return(playedRank > fieldRank); } else if (AreCardsMultiple(fieldCards)) { // フィールドカードが複数枚だしならば if (!AreCardsMultiple(playedCards)) { // 出されたカードも複数枚でなければ無効 return(false); } // ランク比較 var playedRank = playedCards.Min(c => DaifugoFunction.NumberToRank(c.number)); var fieldRank = fieldCards.Min(c => DaifugoFunction.NumberToRank(c.number)); return(playedRank > fieldRank); } else if (AreCardsSequence(fieldCards)) { // フィールドカードが階段だしならば if (!AreCardsSequence(playedCards)) { // 出されたカードも階段出しでなければ無効 return(false); } // 階段出しランク比較 var playedRank = GetMinimumRankOfSequenceCards(playedCards); var fieldRank = GetMaximumRankOfSequenceCards(fieldCards); return(playedRank > fieldRank); } else { // フィールドカードが無ければ // 有効なカードか判定だけ if (playedCards.Count == 1 || AreCardsMultiple(playedCards) || AreCardsSequence(playedCards)) { return(true); } return(false); } }