/// <summary> /// Gets the results of moves. /// </summary> /// <param name="currentNode">Node of tree representing the previous move.</param> /// <returns>Map of move results.</returns> public MoveResult[,] GetMoveResult(GameTreeNode currentNode) { if (currentNode == null) { MoveResult[,] moveResults = new MoveResult[RulesetInfo.BoardSize.Width, RulesetInfo.BoardSize.Height]; for (int x = 0; x < RulesetInfo.BoardSize.Width; x++) { for (int y = 0; y < RulesetInfo.BoardSize.Height; y++) { moveResults[x, y] = MoveResult.Legal; } } return(moveResults); } lock (RulesetInfo) { MoveResult[,] moveResults = new MoveResult[RulesetInfo.BoardSize.Width, RulesetInfo.BoardSize.Height]; GameBoard[] history = currentNode.GetGameBoardHistory().ToArray(); GameBoard boardState = new GameBoard(currentNode.BoardState); GroupState groupState = new GroupState(currentNode.GroupState, RulesetInfo); StoneColor player; if (currentNode.Move.WhoMoves == StoneColor.None) { player = StoneColor.White; // TODO (future work) Petr: ensure this is actually appropriate in all such situations (probably isn't) } else { player = currentNode.Move.WhoMoves.GetOpponentColor(); } for (int x = 0; x < RulesetInfo.BoardSize.Width; x++) { for (int y = 0; y < RulesetInfo.BoardSize.Height; y++) { //set Ruleset state SetRulesetInfo(boardState, groupState); Position position = new Position(x, y); Move move = Move.PlaceStone(player, position); if (IsPositionOccupied(position) == MoveResult.OccupiedPosition) { moveResults[x, y] = MoveResult.OccupiedPosition; } else { //Find captures and remove prisoners List <int> capturedGroups = CheckPossiblyCapturedGroups(move); if (capturedGroups.Count != 0) { SetRulesetInfo(new GameBoard(currentNode.BoardState), new GroupState(currentNode.GroupState, RulesetInfo)); } //remove prisoners foreach (int groupID in capturedGroups) { RulesetInfo.GroupState.Groups[groupID].DeleteGroup(); } // add temporarily a stone to board RulesetInfo.GroupState.AddTempStoneToBoard(position, player); //check selfcapture, ko moveResults[x, y] = CheckSelfCaptureKo(move, history); // remove added stone RulesetInfo.GroupState.RemoveTempStoneFromPosition(position); } } } return(moveResults); } }
/// <summary> /// Verifies the legality of a move. Places the stone on the board. Finds prisoners and remove them. /// </summary> /// <param name="currentNode">Node of tree representing the previous move.</param> /// <param name="moveToMake">Move to check.</param> /// <returns>Object, which contains: the result of legality check, list of prisoners, the new state of game board, the new state of groups.</returns> public MoveProcessingResult ProcessMove(GameTreeNode currentNode, Move moveToMake) { lock (RulesetInfo) { StoneColor player = moveToMake.WhoMoves; Position position = moveToMake.Coordinates; GameBoard[] history = new GameBoard[0]; GroupState previousGroupState, currentGroupState; GameBoard previousBoard, currentBoard; if (currentNode == null) { previousGroupState = new GroupState(RulesetInfo); currentGroupState = new GroupState(RulesetInfo); previousBoard = new GameBoard(RulesetInfo.BoardSize); currentBoard = new GameBoard(RulesetInfo.BoardSize); } else { history = currentNode.GetGameBoardHistory().ToArray(); //set Ruleset state previousGroupState = new GroupState(currentNode.GroupState, RulesetInfo); currentGroupState = new GroupState(currentNode.GroupState, RulesetInfo); previousBoard = new GameBoard(currentNode.BoardState); currentBoard = new GameBoard(currentNode.BoardState); } SetRulesetInfo(currentBoard, currentGroupState); MoveProcessingResult processingResult = new MoveProcessingResult { Captures = new List <Position>(), NewBoard = previousBoard, NewGroupState = previousGroupState }; //1. step: check intersection if (moveToMake.Kind == MoveKind.Pass) { processingResult.Result = Pass(currentNode); return(processingResult); } else if (IsOutsideTheBoard(position) == MoveResult.OutsideTheBoard) { processingResult.Result = MoveResult.OutsideTheBoard; return(processingResult); } else if (IsPositionOccupied(position) == MoveResult.OccupiedPosition) { processingResult.Result = MoveResult.OccupiedPosition; return(processingResult); } else { //2. step: add stone RulesetInfo.GroupState.AddStoneToBoard(moveToMake.Coordinates, moveToMake.WhoMoves); //3. step: find captures and remove prisoners List <int> capturedGroups = CheckCapturedGroups(moveToMake); foreach (int groupID in capturedGroups) { processingResult.Captures.AddRange(RulesetInfo.GroupState.Groups[groupID].Members); RulesetInfo.GroupState.Groups[groupID].DeleteGroup(); } //4. step: check selfcapture, ko MoveResult r = CheckSelfCaptureKoSuperko(moveToMake, history); if (r == MoveResult.Legal) { RulesetInfo.GroupState.CountLiberties(); processingResult.NewBoard = currentBoard; processingResult.NewGroupState = currentGroupState; } else { SetRulesetInfo(previousBoard, previousGroupState); } processingResult.Result = r; return(processingResult); } } }