public override bool Equals(Object obj) { // Check for null values and compare run-time types. if (obj == null || GetType() != obj.GetType()) { return(false); } GameBoardState other = obj as GameBoardState; //Check that both dictionaries have the same keys bool sameKeys = gameBoard.Keys.Except(other.gameBoard.Keys).Count() == 0 && other.gameBoard.Keys.Except(gameBoard.Keys).Count() == 0; if (!sameKeys) { return(false); } //Check that the values are equal as well foreach (var key in gameBoard.Keys) { if (gameBoard[key] != other.gameBoard[key]) { return(false); } } return(true); }
internal MoveState(GameBoardState state, CheckerColor color, int position, List <int> movesLeft, List <Change> changes) { this.state = state; this.color = color; this.position = position; this.movesLeft = movesLeft; this.changes = changes; }
//Given a state, an initial position and a target position, returns true if it is legal for the white player //to move a checker from the initial position to the target position, or false if not private static bool IsLegalMove(GameBoardState state, int from, int targetPosition) { bool result = IsLegalToMoveFromPosition(state, from) && IsLegalToMoveToPosition(state, from, targetPosition); if (from == 25) { Console.WriteLine("Mocing from white bar now.... Legal: " + result); } return(result); }
private void initialize(int[] gameBoard, Dice dice, int whiteCheckersOnBar, int whiteCheckersBoreOff, int blackCheckersOnBar, int blackCheckersBoreOff, CheckerColor playerToMove) { this.turnColor = playerToMove; this.dice = dice; recalculateMoves(); this.CurrentTurn = new Turn(turnColor, new List <Move>(), new List <int>(movesLeft)); this.currentGameBoardState = new GameBoardState(gameBoard, whiteCheckersOnBar, whiteCheckersBoreOff, blackCheckersOnBar, blackCheckersBoreOff); }
public void Move(CheckerColor color, int from, int targetPosition) { if (GameIsOver()) { Console.WriteLine("Game is over, so doing nothing"); return; } if (color != playerToMove()) { throw new InvalidOperationException(color + " can't move when it is " + color.OppositeColor() + "'s turn"); } //TODO REMOVE THIS SHIT numberOfMovesMade++; MovesCalculator mts = new MovesCalculator(currentGameBoardState, color, from, movesLeft); if (!mts.LegalToMoveToPosition(targetPosition)) { throw new InvalidOperationException("Illegal to move " + color + " form " + from + " to " + targetPosition); } MovesCalculator.MoveState resultingState = mts.MoveToPosition(targetPosition); currentGameBoardState = resultingState.state; movesLeft = resultingState.movesLeft; Changes.AddRange(resultingState.changes); NotifyAllViews(); foreach (Change change in resultingState.changes) { if (change is Move) { CurrentTurn.moves.Add(change as Move); } } if (GameIsOver()) { //Console.WriteLine("Game is over!! Terminating"); // Michaelius: The view notifies gameover. ML doesn't like printing. return; } if (movesLeft.Count() == 0) { changeTurns(); } else if (GetMoveableCheckers().Count() == 0) { changeTurns(); } }
//Given a state, an initial position and a target position, returns true if the white player //can move a checker from the initial position to the target position, or false if not. private static bool IsLegalToMoveToPosition(GameBoardState state, int fromPosition, int toPosition) { //If the target position is between -5 and 0, then the white player is trying to bear off a checker if (toPosition <= 0 && toPosition >= -5) { return(IsLegalToBearOff(state, fromPosition, toPosition)); } //If not, make sure the position is on the board and that there are less than two enemy checkers there if (toPosition < 1 || toPosition > 24) { return(false); } return(state.getMainBoard()[toPosition - 1] > -2); }
internal static IEnumerable <int> GetMoveableCheckers(GameBoardState state, CheckerColor color, List <int> moves) { HashSet <int> output = new HashSet <int>(); if (new MovesCalculator(state, color, color.GetBar(), moves).GetReachablePositions().Count() > 0) { output.Add(color.GetBar()); } for (int i = 1; i <= 24; i++) { if (new MovesCalculator(state, color, i, moves).GetReachablePositions().Count() > 0) { output.Add(i); } } return(output); }
//Given a state, an initial position and a target position, returns true if it is legal for white //to bear off a checker from the initial position to the target position private static bool IsLegalToBearOff(GameBoardState state, int from, int to) { //Check that the home board (including the position white bears off to) is filled with all whites checkers if (state.NumberOfCheckersInHomeBoard() != GameBoardState.NUMBER_OF_CHECKERS_PER_PLAYER) { return(false); } if (to == 0) { return(true); } //If the target position is less than 0, then white is for example trying to carry off a checker //from position 4 using a move of 5. For this to be legal, we must ensure that there are no checkers //in the home board positiond on a position greater than 4. return(state.NumberOfCheckersInHomeBoardFurtherAwayFromBar(from) == 0); }
internal static string CreateXmlForGameBoardState(GameBoardState state, string rootTag) { if (state == null) { throw new ArgumentNullException("state"); } if (rootTag == null) { throw new ArgumentNullException("rootTag"); } //Separating each element of the array with a space, and removes trailing spaces var board = state.getMainBoard().Select(i => i + " ").Aggregate((a, b) => a + b).Trim(); //Wrap the board with tags board = "<board>" + board + "</board>"; int whiteGoal = state.GetCheckersOnPosition(White.BearOffPositionID()); int whiteBar = state.GetCheckersOnPosition(White.GetBar()); //The agreed format is that black checkers on bar and target should be represented as negative int blackGoal = state.GetCheckersOnPosition(Black.BearOffPositionID()); blackGoal = Math.Min(blackGoal, blackGoal * -1); int blackBar = state.GetCheckersOnPosition(Black.GetBar()); blackBar = Math.Min(blackBar, blackBar * -1); //Wrap each of the above four values in their own tags var rest = String.Format("<whiteGoal>{0}</whiteGoal><whiteBar>{1}</whiteBar><blackGoal>{2}</blackGoal><blackBar>{3}</blackBar>", whiteBar, whiteGoal, blackBar, blackGoal); //Wrapping the entire message in the supplied root tags if (rootTag == "") { return(board + rest); } else { return(String.Format("<{0}>" + board + rest + "</{0}>", rootTag)); } }
internal MovesCalculator(GameBoardState state, CheckerColor color, int fromPosition, List <int> moves) { initialMoveState = new MoveState(state, color, fromPosition, moves, new List <Change>()); //Initialises the set of reachable states given the starting GameBoardState, position and moves IEnumerable <MoveState> tmp1 = initialMoveState.GenerateMoveStatesForPosition(); while (tmp1.Count() > 0) { reachableStates.AddRange(tmp1); //Adds all the states in tmp1 to the reachable states tmp1 = tmp1 //Maps every state 'a' in tmp1 to a list that contains the states that are reachable from 'a' .Select(s => s.GenerateMoveStatesForPosition()) //Concatenates all the lists, yielding a new set of reachable states .Aggregate((a, b) => a.Concat(b)); } }
//Given a state and a position, returns true if it is legal for the white player can move a checker from that position private static bool IsLegalToMoveFromPosition(GameBoardState state, int position) { //If the position is the bar, there has to be at least one checker on the bar if (position == WHITE.GetBar()) { return(state.getCheckersOnBar(WHITE) > 0); } //If not, there cannot be any checkers on the bar, the position has to be on the board, and there has to be at //least one checker on that position else { if (state.getCheckersOnBar(WHITE) > 0) { return(false); } if (position < 1 || position > 24) { return(false); } return(state.getMainBoard()[position - 1] > 0); } }
public static IEnumerable <ReachableState> GetReachableStatesThisTurn(GameBoardState state, CheckerColor color, List <int> movesLeft) { IEnumerable <int> moveableCheckers = GetMoveableCheckers(state, color, movesLeft); List <MoveState> moveStates = new List <MoveState>(); foreach (int pos in moveableCheckers) { var tmp = new MovesCalculator(state, color, pos, movesLeft).reachableStates; foreach (var moveState in tmp) { if (moveState.IsFinal) { moveStates.Add(moveState); } } } if (moveStates.Count() == 0) { return(new List <ReachableState>()); } return(moveStates.Select(moveState => new ReachableState(moveState.state, moveState.MovesMade()))); }
//Performs a move and returns the resulting state. If the move is illegal, null will be returned instead. internal static GameBoardState Move(GameBoardState state, CheckerColor color, int initialPosition, int distance) { //Since moving a checker from the black player is identical to moving a checker from the white player, if the white player's //situation was the same as the black player, the game board and input is inverted so this is the case, and the code for //moving a white checker is reused if (color == BLACK) { //Transforming the input state = state.InvertColor(); initialPosition = convertTo(WHITE, initialPosition); state = Move(state, WHITE, initialPosition, distance); //Returns null if the move is invalid, else transforms the move //back into the perspective of the black player and returns it. return(state == null ? null : state.InvertColor()); } //The position of the white bar relative to the board is 25, as 24 is the first position //for white when moving from the bar int initialPositionRelativeToBoard = initialPosition == WHITE.GetBar() ? 25 : initialPosition; int targetPosition = initialPositionRelativeToBoard - distance; if (IsLegalMove(state, initialPosition, targetPosition)) { //The previous definition of the target position is useful for determining whether or not //A move is legal. However, we risk getting negative values, for example when //the white player bears off a checker on position 4 using a die that shows 5 //Therefore the /actual/ target position is found using the below method call targetPosition = GetPositionAfterMove(color, initialPosition, distance); return(state.MoveChecker(initialPosition, targetPosition)); } else { return(null); } }
internal ReachableState(GameBoardState state, List <Move> movesMade) { this.state = state; this.movesMade = movesMade; }