/// <summary> /// Updates the indicators with the current move options and dice roll from BoardManager. /// </summary> private void UpdateMoveIndicators() { BGMoveOptions moveOptions = BackgammonGame.Instance.MoveOptions; BGDiceRoll diceRoll = BackgammonGame.Instance.DiceRoll; UpdateMoveIndicators(moveOptions, diceRoll); }
/// <summary> /// Initializes a new instance of the <see cref="BGMoveOptions"/> class. /// </summary> /// <param name="player"></param> /// <param name="boardMap"></param> /// <param name="diceRoll"></param> public BGMoveOptions(BGPlayerID player, BGBoardMap boardMap, BGDiceRoll diceRoll) { Moves = null; Moves = GetMoves(player, boardMap, diceRoll); // A player must use both numbers of a roll if possible. // If either number can be played but not both, the player must play the larger one. if (diceRoll.Roll1 != diceRoll.Roll2 && diceRoll.CanUse(diceRoll.Roll1) && diceRoll.CanUse(diceRoll.Roll2)) { List <BGMove> roll1OnlyMoves = new List <BGMove>(); List <BGMove> roll2OnlyMoves = new List <BGMove>(); List <BGMove> bothRollMoves = new List <BGMove>(); foreach (BGMove move in Moves) { BGBoardMap newBoardMap = boardMap.Copy(); newBoardMap.Use(move); BGDiceRoll newDiceRoll = diceRoll.Copy(); newDiceRoll.Use(move); BGMoveOptions newMoveOptions = new BGMoveOptions(player, newBoardMap, newDiceRoll); if (move.DiceRoll == diceRoll.Roll1 && newMoveOptions.CanMoveWith(diceRoll.Roll2) || move.DiceRoll == diceRoll.Roll2 && newMoveOptions.CanMoveWith(diceRoll.Roll1)) { bothRollMoves.Add(move); } else if (move.DiceRoll == diceRoll.Roll1 && !newMoveOptions.CanMoveWith(diceRoll.Roll2)) { roll1OnlyMoves.Add(move); } else if (move.DiceRoll == diceRoll.Roll2 && !newMoveOptions.CanMoveWith(diceRoll.Roll1)) { roll2OnlyMoves.Add(move); } } if (bothRollMoves.Count > 0) { Moves = bothRollMoves; } else if (diceRoll.Roll1 > diceRoll.Roll2 && roll1OnlyMoves.Count > 0) { Moves = roll1OnlyMoves; } else if (diceRoll.Roll2 > diceRoll.Roll1 && roll2OnlyMoves.Count > 0) { Moves = roll2OnlyMoves; } } }
/// <summary> /// Updates the indicators with the specified move options and dice roll. /// </summary> private void UpdateMoveIndicators(BGMoveOptions moveOptions, BGDiceRoll diceRoll) { int index = 0; SimpleDie[] dice = GetCurrentMoveIndicators(); for (int roll = 1; roll <= 6; roll++) { int total = diceRoll.GetTotalRolls(roll); int left = diceRoll.GetRollsLeft(roll); for (int current = 0; current < total; current++) { if (!dice[index].gameObject.activeSelf) { dice[index].gameObject.SetActive(true); dice[index].GetComponent <FloatingObject>().CurrentAngle = 0; } dice[index].Number = roll; if (current < total - left) { dice[index].GetComponent <Animator>().SetInteger("State", (int)States.Used); } else if (!moveOptions.CanMoveWith(roll)) { dice[index].GetComponent <Animator>().SetInteger("State", (int)States.Unavailable); } else { dice[index].GetComponent <Animator>().SetInteger("State", (int)States.Available); } if (++index >= 4) { break; } } } for (int i = index; i < 4; i++) { dice[i].gameObject.SetActive(false); } }
/// <summary> /// Initializes a new instance of the <see cref="BGState"/> class. /// </summary> /// <param name="boardMap">Board map.</param> /// <param name="moveOptions">Move options.</param> /// <param name="diceRoll">Dice roll.</param> public BGState(BGBoardMap boardMap, BGMoveOptions moveOptions, BGDiceRoll diceRoll) { BoardMap = boardMap; Moves = new List <BGMove>(); NextStates = new Dictionary <BGMove, BGState>(); foreach (BGMove move in moveOptions.Moves) { BGBoardMap newBoardMap = boardMap.Copy(); newBoardMap.Use(move); BGDiceRoll newDiceRoll = diceRoll.Copy(); newDiceRoll.Use(move); BGMoveOptions newMoveOptions = new BGMoveOptions(BGPlayerID.Player2, newBoardMap, newDiceRoll); Moves.Add(move); NextStates[move] = new BGState(newBoardMap, newMoveOptions, newDiceRoll); } }
/// <summary> /// Determines which move to use given the current board map, move options and available dice rolls. /// </summary> /// <param name="boardMap"></param> /// <param name="moveOptions"></param> /// <returns></returns> public List <BGMove> GetMove(BGBoardMap boardMap, BGMoveOptions moveOptions, BGDiceRoll diceRoll) { Evaluate(new BGState(boardMap, moveOptions, diceRoll)); return(m_BestMoves); }
/// <summary> /// Wait the specified number of seconds for the dice to settle. /// </summary> /// <param name="seconds"></param> /// <returns></returns> private IEnumerator WaitDice(float seconds) { IsLocked = true; yield return(new WaitForSeconds(seconds)); int roll1; int roll2; if (IsFirstTurn) { roll1 = Player1.Dice.Die1.Number; roll2 = Player2.Dice.Die1.Number; } else { roll1 = CurrentPlayer.Dice.Die1.Number; roll2 = CurrentPlayer.Dice.Die2.Number; } if (IsFirstTurn && roll1 == roll2) { if (IsMurphyRuleEnabled) { Stakes *= 2; } ShowAlert("Rerolling dice."); RollDice(); } else { if (IsFirstTurn) { CurrentPlayer = (roll1 > roll2) ? Player1 : Player2; ShowAlert(string.Format("{0} moves first.", CurrentPlayer.Name)); } IsDiceRolled = true; DiceRoll = new BGDiceRoll(roll1, roll2); MoveOptions = new BGMoveOptions(CurrentPlayer.ID, Board.GetBoardMap(), DiceRoll); EventHelper.Raise(this, MoveOptionsUpdated); if (!MoveOptions.CanMove()) { ShowAlert(string.Format("{0} can not move and must yield this turn.", CurrentPlayer.Name)); yield return(Wait(3f)); EndTurn(); } else if (CurrentPlayer.IsAIControlled) { List <BGMove> moves = new AIPlayerDefault().GetMove(Board.GetBoardMap(), MoveOptions, DiceRoll); foreach (BGMove move in moves) { yield return(new WaitForSeconds(1f)); MoveChecker(move); } yield return(new WaitForSeconds(3f)); EndTurn(); } } IsLocked = false; }
/// <summary> /// Gets a list of all moves that can be made for the specified player with the specified board and dice roll. /// </summary> private List <BGMove> GetMoves(BGPlayerID player, BGBoardMap board, BGDiceRoll diceRoll) { List <BGMove> moves = new List <BGMove>(); if (player == BGPlayerID.None) { return(moves); } BGPoint home = board.GetHome(player); BGPoint jail = board.GetJail(player); BGPoint[] innerTable = board.GetInnerTable(player); BGPoint[] outerTable = board.GetOuterTable(player); // Find available moves. if (jail.Count > 0) { for (int roll = 1; roll <= 6; roll++) { if (diceRoll.CanUse(roll) && !outerTable[roll - 1].IsBlocking(player)) { moves.Add(new BGMove(jail, outerTable[roll - 1], roll)); } } } else { for (int roll = 1; roll <= 6; roll++) { if (diceRoll.CanUse(roll)) { for (BGPointID point = BGPointID.Point1; point <= BGPointID.Point24; point++) { BGPoint from = board.GetPoint(point); if (from.IsOccupiedBy(player)) { BGPoint to = null; if (player == BGPlayerID.Player1 && ((point - roll) >= BGPointID.Point1)) { to = board.GetPoint(point - roll); } else if (player == BGPlayerID.Player2 && ((point + roll) <= BGPointID.Point24)) { to = board.GetPoint(point + roll); } if (to != null && !to.IsBlocking(player)) { moves.Add(new BGMove(from, to, roll)); } } } } } if (!outerTable.Any(point => point.IsOccupiedBy(player))) { // Get max distance from home. int maxDistance = 0; for (int i = 0; i < innerTable.Length; i++) { if (innerTable[i].IsOccupiedBy(player)) { maxDistance = i + 1; } } // Find moves that can be used to bear off. for (int roll = 1; roll <= 6; roll++) { if (diceRoll.CanUse(roll)) { if (innerTable[roll - 1].IsOccupiedBy(player)) { moves.Add(new BGMove(innerTable[roll - 1], home, roll)); } else if (maxDistance > 0 && innerTable[maxDistance - 1].IsOccupiedBy(player) && roll >= maxDistance) { moves.Add(new BGMove(innerTable[maxDistance - 1], home, roll)); } } } } } return(moves); }