Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System.Collections;
- using System.Collections.Generic;
- using System.Linq;
- using GameFramework.AI;
- using GameFramework.CardZones;
- using GameFramework.Data;
- using GameFramework.Utilities;
- using UnityEngine;
- namespace GameFramework.GamePhases
- {
- public class PlayHandsPhase : GamePhaseBase
- {
- private static readonly WaitForSeconds _pauseOpponentThink = new(0.9f);
- private static readonly WaitForSeconds _pauseShowGo = new(1.2f);
- private static readonly WaitForSeconds _pauseShowLastCard = new(1.5f);
- protected override IEnumerator RunPhaseLogic()
- {
- // Starts or Continues the Play Hands Phase --
- // This phase has two additional phases with two sub-phase event triggered functions
- // following the base phase, for selecting cards or clicking go button
- // This phase naturally transitions to/from CountHands phase when all cards have been played while peg score < 131
- // This phase may also transition to/from the MovingPegs phase (and its additional phase MovePeg)
- // When in a PlayerOut phase, only one player has cards and board had been reset - no go points, just play out
- TrySetActiveState(Context.TableScoreTotalPanel, true);
- // ---- PLAYER GO BUTTON ----
- if (Context.PlayPanelGoButton.activeSelf)
- {
- TrySetActiveState(Context.PlayPanelGoButton, false);
- }
- else
- {
- if (CurrentPhase == GamePhase.PlayHands)
- {
- SetPhase(GamePhase.PlayCard);
- }
- }
- // ---- PLAYER OUT PHASE ----
- if (CurrentPhase == GamePhase.PlayerOut)
- {
- yield return HandleOpponentPlayOut();
- yield break;
- }
- // ---- PLAYER CARD SELECTED ----
- if (SelectedCard != null)
- {
- yield return HandlePlayerMove(SelectedCard);
- yield return HandlePlayerPlayOut();
- yield break;
- }
- // ---- WHOSE TURN? ----
- var isNewRound = IsNewRound();
- var isPlayerCribOwner = IsPlayerCribOwner();
- var playerHand = Context.PlayerHandManager.GetCards();
- var opponentHand = Context.OpponentHandManager.GetCards();
- // Player or opponent leads?
- var isOpponentsMove = (LastPlayer == GamePlayer.Player1) || !HasPlayableCard(playerHand);
- var isPlayersMove = (isNewRound && !isPlayerCribOwner) || (!isNewRound && !isOpponentsMove);
- // ---- NEW ROUND SCENARIO: Need to ensure table score is zeroed ----
- if (isNewRound)
- {
- UpdateRunningScore(0);
- }
- // ---- GO SCENARIO: No one can play, but table <= 31 ----
- var tableScore = GetCurrentTableScore();
- if (!IsCountPhaseReady() && !HasPlayableCard(playerHand) && !HasPlayableCard(opponentHand))
- {
- if (tableScore != 31 && LastPlayer == GamePlayer.Player1)
- {
- SetPhase(GamePhase.PlayHands);
- yield return ShowGoMessage();
- }
- if (tableScore == 31)
- {
- if (LastPlayer != GamePlayer.Opponent)
- {
- SetPhase(GamePhase.PlayHands);
- }
- }
- yield return MovePlayedCardsToPlayedZone();
- ResetTableScore();
- if (!CheckAndEnterPlayOut())
- {
- if (LastPlayer == GamePlayer.Opponent)
- {
- SetPhase(GamePhase.PlayCard);
- }
- }
- yield break;
- }
- // ---- LAST CARD/COUNT PHASE ----
- if (IsCountPhaseReady())
- {
- if (tableScore < 31)
- {
- yield return ShowLastCardMessage();
- }
- yield break;
- }
- // ---- PLAYER MOVE CHECK ----
- if (isPlayersMove)
- {
- // Wait for player input (card select or Go button)
- // Defensive: if player can't play, show Go button
- if (!HasPlayableCard(playerHand) && HasPlayableCard(opponentHand))
- {
- TrySetActiveState(Context.PlayPanelGoButton, true);
- }
- if (!CheckAndEnterPlayOut())
- {
- SetPhase(GamePhase.PlayCard);
- }
- yield break;
- }
- // ---- OPPONENT MOVE CHECK ----
- if (HasPlayableCard(opponentHand))
- {
- yield return HandleOpponentMove();
- tableScore = GetCurrentTableScore();
- if (tableScore == 31)
- {
- // TODO: Opponent scores 2 points, implement scoring event later
- yield return MovePlayedCardsToPlayedZone();
- ResetTableScore();
- yield break;
- }
- // If EITHER player has cards in PlayHands/PlayCard phase, it is still not over and go button should be conditionally shown to player
- var isRoundStillGoing = CurrentPhase != GamePhase.PlayerOut && CurrentPhase != GamePhase.CountHands;
- var canStillPlay = playerHand.Count > 0 || Context.OpponentHandManager.GetCards().Count > 0;
- if (isRoundStillGoing && canStillPlay)
- {
- TrySetActiveState(Context.PlayPanelGoButton, !HasPlayableCard(playerHand));
- }
- if (!canStillPlay)
- {
- if (IsCountPhaseReady() && tableScore < 31)
- {
- yield return ShowLastCardMessage();
- }
- }
- yield break;
- }
- else
- {
- if (tableScore != 31 && LastPlayer == GamePlayer.Player1)
- {
- // TODO: Player scores a go point
- yield return ShowGoMessage();
- }
- }
- }
- // ------------------- HELPERS & HANDLERS -------------------
- private IEnumerator HandlePlayerMove(CardData card)
- {
- var playerHand = Context.PlayerHandManager.GetCards();
- if (!playerHand.Contains(card) || !CheckCanPlay(card))
- {
- yield break;
- }
- // Move card
- ZonesCardTransfer.TransferCard(
- Context.PlayerHandManager,
- Context.CardPlayPanelManager,
- card,
- Context.CardSprites,
- Context.CardSprites[card.SpriteName]);
- SetLastPlayer(GamePlayer.Player1);
- Context.PlayerLowestCardManager.AddCard(card, Context.CardSprites);
- UpdateRunningScore(card.Value);
- // Check for playout state (if PlayerOut phase, clear table if needed)
- if (CurrentPhase == GamePhase.OpponentOut && IsCountPhaseReady())
- {
- if (GetCurrentTableScore() == 31)
- {
- // TODO: 2 points to this player here, fire event when scoring system implemented
- }
- }
- // Normal flow: let opponent move else wait for next player action on playout
- if (CurrentPhase != GamePhase.OpponentOut)
- {
- SetPhase(GamePhase.PlayHands);
- }
- }
- private IEnumerator HandleOpponentMove()
- {
- yield return _pauseOpponentThink;
- var opponentHand = Context.OpponentHandManager.GetCards();
- var playZone = Context.CardPlayPanelManager.GetCards();
- var card = OpponentCardSelection.GetPlayCard(opponentHand, playZone, GetCurrentTableScore());
- if (card == null)
- {
- if (CurrentPhase != GamePhase.PlayerOut)
- {
- SetPhase(GamePhase.PlayHands);
- }
- yield break;
- }
- ZonesCardTransfer.TransferCard(
- Context.OpponentHandManager,
- Context.CardPlayPanelManager,
- card,
- Context.CardSprites,
- Context.CardSprites[card.SpriteName]);
- SetLastPlayer(GamePlayer.Opponent);
- Context.OpponentLowestCardManager.AddCard(card, Context.CardSprites);
- UpdateRunningScore(card.Value);
- if (CurrentPhase == GamePhase.PlayerOut && IsCountPhaseReady())
- {
- if (GetCurrentTableScore() == 31)
- {
- // TODO: 2 points to this player here, fire event when scoring system implemented
- }
- else
- {
- yield return ShowLastCardMessage();
- }
- }
- }
- private IEnumerator HandlePlayerPlayOut()
- {
- // ---- PHASE OUT LOGIC ----
- if (CurrentPhase != GamePhase.OpponentOut)
- {
- yield break;
- }
- var playerHand = Context.PlayerHandManager.GetCards();
- if (playerHand.Count == 0)
- {
- yield return MovePlayedCardsToPlayedZone();
- SetPhase(GamePhase.CountHands);
- yield break;
- }
- }
- private IEnumerator HandleOpponentPlayOut()
- {
- var opponentHand = Context.OpponentHandManager.GetCards();
- if (opponentHand.Count == 0)
- {
- yield return MovePlayedCardsToPlayedZone();
- SetPhase(GamePhase.CountHands);
- yield break;
- }
- yield return HandleOpponentMove();
- }
- private IEnumerator ShowGoMessage()
- {
- TrySetActiveState(Context.PlayPanelGoMessage, true);
- // TODO: Player1 earns 1 point for go, once scoring is implemented
- yield return _pauseShowGo;
- TrySetActiveState(Context.PlayPanelGoMessage, false);
- }
- private IEnumerator ShowLastCardMessage()
- {
- var isActiveSelf = Context.PlayerLastCardMessage.activeSelf || Context.OpponentLastCardMessage.activeSelf;
- if (isActiveSelf)
- {
- yield break; // Should not happen, but defensive check
- }
- var lastPlayerIsPlayer = (LastPlayer == GamePlayer.Player1);
- TrySetActiveState(Context.PlayerLastCardMessage, lastPlayerIsPlayer);
- TrySetActiveState(Context.OpponentLastCardMessage, !lastPlayerIsPlayer);
- yield return _pauseShowLastCard;
- TrySetActiveState(Context.PlayerLastCardMessage, false);
- TrySetActiveState(Context.OpponentLastCardMessage, false);
- }
- private IEnumerator MovePlayedCardsToPlayedZone()
- {
- var playZone = Context.CardPlayPanelManager;
- var playedZone = Context.CardsPlayedPanelManager;
- var currentCards = playZone.GetCards().ToList();
- foreach (var card in currentCards)
- {
- ZonesCardTransfer.TransferCard(playZone, playedZone, card, Context.CardSprites);
- yield return new WaitForSeconds(0.15f);
- }
- playZone.ClearZone();
- yield return new WaitForSeconds(0.4f);
- }
- private void ResetTableScore()
- {
- UpdateRunningScore(0);
- TrySetActiveState(Context.PlayPanelGoButton, false);
- TrySetActiveState(Context.PlayPanelGoMessage, false);
- }
- // --------------- Utility Logic ---------------
- private bool HasPlayableCard(IReadOnlyList<CardData> hand)
- {
- foreach (var card in hand)
- {
- if (CheckCanPlay(card))
- {
- return true;
- }
- }
- return false;
- }
- private bool IsNewRound()
- {
- var isPlayerHandFull = Context.PlayerHandManager.GetCards().Count == 4;
- var isOpponentHandFull = Context.OpponentHandManager.GetCards().Count == 4;
- return isPlayerHandFull && isOpponentHandFull;
- }
- private bool IsPlayerCribOwner()
- {
- return Context.PlayerCribPanelManager.GetCards().Count > 0;
- }
- private bool CheckAndEnterPlayOut()
- {
- var playerHand = Context.PlayerHandManager.GetCards();
- var opponentHand = Context.OpponentHandManager.GetCards();
- var playerOut = playerHand.Count == 0;
- var opponentOut = opponentHand.Count == 0;
- if (playerOut && !opponentOut)
- {
- SetPhase(GamePhase.PlayerOut);
- return true;
- }
- if (opponentOut && !playerOut)
- {
- SetPhase(GamePhase.OpponentOut);
- return true;
- }
- return false;
- }
- private int GetCurrentTableScore()
- {
- var text = Context.TableScoreValueTextMesh.text ?? "0";
- return int.TryParse(text, out int score) ? score : 0;
- }
- private void UpdateRunningScore(int value)
- {
- var current = GetCurrentTableScore();
- current = value == 0 ? 0 : current + GetNormalizedValue(value);
- Context.TableScoreValueTextMesh.text = current.ToString();
- // TODO: Check for 15-2 and 31 for 2 here when scoring events implemented (??)
- }
- private bool IsCountPhaseReady()
- {
- var playerCardsCount = Context.PlayerHandManager.GetCards().Count;
- var opponentCardsCount = Context.OpponentHandManager.GetCards().Count;
- if (playerCardsCount == 0 && opponentCardsCount == 0)
- {
- TrySetActiveState(Context.PlayPanelGoButton, false); // TEST: Commented out ResetTablescore, using this now
- TrySetActiveState(Context.PlayPanelGoMessage, false); // TEST: Commented out ResetTablescore, using this now
- SetPhase(GamePhase.CountHands);
- return true;
- }
- return false;
- }
- // NOTE: now repeated this method in AI class OpponentCardSelection - consider util later
- private int GetNormalizedValue(int value) => value > 10 ? 10 : value;
- private bool CheckCanPlay(CardData card)
- {
- var cardValue = GetNormalizedValue(card.Value);
- var currentScore = GetCurrentCardsCount();
- return currentScore + cardValue <= 31;
- }
- private int GetCurrentCardsCount()
- {
- var playZone = Context.CardPlayPanelManager;
- var currentCards = playZone.GetCards();
- return currentCards.Sum(card => GetNormalizedValue(card.Value));
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement