/// <summary> /// Gets the pip for the specified player. /// </summary> public int GetPip(BGPlayerID player) { if (Player != player || player == BGPlayerID.None) { return(0); } switch (ID) { case (BGPointID.HomeP1): case (BGPointID.HomeP2): { return(0); } case (BGPointID.JailP1): case (BGPointID.JailP2): { return(Count * 25); } default: { return(Count * ((Player == BGPlayerID.Player1) ? (1 + (int)ID) : (24 - (int)ID))); } } }
/// <summary> /// Gets the outer table for the specified player. /// </summary> public BGPoint[] GetOuterTable(BGPlayerID player) { switch (player) { case (BGPlayerID.Player1): { BGPoint[] outerTable = new BGPoint[18]; for (int i = 0; i < 18; i++) { outerTable[i] = this.m_Points[23 - i]; } return(outerTable); } case (BGPlayerID.Player2): { BGPoint[] outerTable = new BGPoint[18]; for (int i = 0; i < 18; i++) { outerTable[i] = this.m_Points[i]; } return(outerTable); } default: { return(null); } } }
/// <summary> /// Gets the inner table for the specified player. /// </summary> public BGPoint[] GetInnerTable(BGPlayerID player) { switch (player) { case (BGPlayerID.Player1): { BGPoint[] innerTable = new BGPoint[6]; for (int i = 0; i < 6; i++) { innerTable[i] = this.m_Points[i]; } return(innerTable); } case (BGPlayerID.Player2): { BGPoint[] innerTable = new BGPoint[6]; for (int i = 0; i < 6; i++) { innerTable[i] = this.m_Points[23 - i]; } return(innerTable); } default: { return(null); } } }
/// <summary> /// Gets whether the specified player can bear off. /// A player can bear off checkers if the player does not have any checkers in the outer table or in jail. /// </summary> /// <param name="player"></param> /// <returns></returns> public bool CanBearOff(BGPlayerID player) { if (player == BGPlayerID.None) { return(false); } return(!GetOuterTable(player).Any(point => point.IsOccupiedBy(player)) && !GetJail(player).IsOccupiedBy(player)); }
/// <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> /// Gets the inner table for the specified player ID. /// </summary> /// <param name="playerID"></param> /// <returns></returns> public Point[] GetInnerTable(BGPlayerID playerID) { switch (playerID) { case (BGPlayerID.Player1): return(InnerTableP1); case (BGPlayerID.Player2): return(InnerTableP2); default: return(null); } }
/// <summary> /// Gets the jail for the specified player. /// </summary> public BGPoint GetJail(BGPlayerID player) { switch (player) { case (BGPlayerID.Player1): return(m_JailP1); case (BGPlayerID.Player2): return(m_JailP2); default: return(null); } }
/// <summary> /// Gets the home for the specified player. /// </summary> public BGPoint GetHome(BGPlayerID player) { switch (player) { case (BGPlayerID.Player1): return(m_HomeP1); case (BGPlayerID.Player2): return(m_HomeP2); default: return(null); } }
/// <summary> /// Sets the number of checkers in the point as well as the player in control. /// Returns whether the operation was successful. /// </summary> public bool Set(BGPlayerID player, int count) { if ((player == BGPlayerID.None && count != 0) || (player != BGPlayerID.None && count == 0)) { return(false); } Player = player; Count = count; return(true); }
/// <summary> /// Gets the point the EXACT specified distance behind the given BOARD point with respect to the particular player. /// Returns null, if no such point exists. /// </summary> /// <param name="pointID"></param> /// <param name="player"></param> /// <param name="distance"></param> /// <returns></returns> public BGPoint GetPreviousPoint(BGPointID pointID, BGPlayerID player, int distance) { if (pointID <= BGPointID.Point1 || pointID >= BGPointID.Point24) { return(null); } if (player == BGPlayerID.Player1) { BGPoint previousPoint = null; int previousIndex = ((int)pointID + distance); if (previousIndex <= 23) { previousPoint = GetPoint((BGPointID)previousIndex); } else if (previousIndex == 24) { previousPoint = GetJail(BGPlayerID.Player2); } return(previousPoint); } else if (player == BGPlayerID.Player2) { BGPoint previousPoint = null; int previousIndex = ((int)pointID - distance); if (previousIndex >= 0) { previousPoint = GetPoint((BGPointID)previousIndex); } else if (previousIndex == -1) { previousPoint = GetJail(BGPlayerID.Player1); } return(previousPoint); } else { return(null); } }
/// <summary> /// Sets the point with the specified point Id with the specified player and checker count. /// Returns whether the operation was successful. /// </summary> /// <param name="id"></param> /// <param name="player"></param> /// <param name="count"></param> public bool SetPoint(BGPointID id, BGPlayerID player, int count) { return(GetPoint(id).Set(player, count)); }
/// <summary> /// Gets whether the point is occupied by at least 2 checkers from the specified player. /// </summary> public bool IsControlledBy(BGPlayerID player) { return((player != BGPlayerID.None) && (Count >= 2) && (Player == player)); }
/// <summary> /// Gets the chance that the specified point can be hit by an opposing player. /// </summary> /// <param name="pointID"></param> /// <returns></returns> public float GetVulnerability(BGPointID pointID) { BGPoint point = GetPoint(pointID); if (point.IsVulnerable()) { float vulnerability = 0f; bool[,] hitTable = new bool[6, 6]; BGPlayerID player = point.Player; BGPlayerID opponent = (player == BGPlayerID.Player1) ? BGPlayerID.Player2 : BGPlayerID.Player1; for (int roll1 = 1; roll1 <= 6; roll1++) { BGPoint point1 = GetPreviousPoint(pointID, opponent, roll1); if (point1 != null) { if (point1.IsOccupiedBy(opponent)) { //Debug.Log(string.Format("{0} is vulnerable to any roll with {1}", point.ID, roll1)); for (int i = 0; i < 6; i++) { hitTable[roll1 - 1, i] = hitTable[i, roll1 - 1] = true; } } else if (!point1.IsControlledBy(player)) { for (int roll2 = 1; roll2 <= 6; roll2++) { BGPoint point2 = GetPreviousPoint(point1.ID, opponent, roll2); if (point2 != null && point2.IsOccupiedBy(opponent)) { //Debug.Log(string.Format("{0} is vulnerable to roll ({1}, {2}) from {3}", point.ID, roll1, roll2, point2)); hitTable[roll1 - 1, roll2 - 1] = hitTable[roll2 - 1, roll1 - 1] = true; } } } } } for (int i = 0; i < 6; i++) { for (int j = 0; j < 6; j++) { if (hitTable[i, j]) { //Debug.Log(string.Format(">> {0},{1}", i + 1, j + 1)); vulnerability += 1f / 36f; } } } //Debug.Log(string.Format("Total vulnerability for {0} = {1}", point.ID, vulnerability)); return(vulnerability); } else { return(0f); } }
/// <summary> /// Gets the pip count for the specified player. /// </summary> public int GetPipCount(BGPlayerID player) { return(m_Points.Sum(point => point.GetPip(player))); }
/// <summary> /// Gets whether the point is occupied by the specified player. /// </summary> public bool IsOccupiedBy(BGPlayerID player) { return((player != BGPlayerID.None) && (Count >= 1) && (Player == player)); }
/// <summary> /// Initializes a new instance of the <see cref="BGPoint"/> class. /// </summary> /// <param name="id">Identifier.</param> public BGPoint(BGPointID id) { this.ID = id; this.Count = 0; this.Player = BGPlayerID.None; }
/// <summary> /// Gets whether the point blocks the specified player. /// </summary> public bool IsBlocking(BGPlayerID player) { return((player != BGPlayerID.None) && (Count >= 2) && (Player != player)); }
/// <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); }
/// <summary> /// Initializes a new instance of the <see cref="BGPoint"/> class. /// </summary> /// <param name="id">Identifier.</param> /// <param name="count">Count.</param> /// <param name="player">Player.</param> private BGPoint(BGPointID id, int count, BGPlayerID player) { this.ID = id; this.Count = count; this.Player = player; }