public GoTurn(GoMove move, int number) { Move = move; TurnNumber = number; PreviousTurn = null; NextTurns = new List <GoTurn>(); }
public GoTurn(GoMove move, int number) { Move = move; TurnNumber = number; PreviousTurn = null; NextTurns = new List<GoTurn>(); }
public void Execute(GoTurn turn) { if (!turn.Move.IsPass) { // add played stone Stones.Add(turn.Move.Point, turn.Move.Color); // remove captured if (turn.Killed != null) { foreach (GoPoint point in turn.Killed) { Stones.Remove(point); } } } }
// step can be negative public void GetBoardModifications(ref List <GoPoint> pointsToRemove, ref List <GoMove> moveToAdd, int step) { pointsToRemove.Clear(); moveToAdd.Clear(); // special case when m_currentNode is null but a move has been played if (m_currentNode == null && step > 0 && Turns.Count == 1) { moveToAdd.Add(new GoMove(Turns[0].Move.Color, Turns[0].Move.Point, false)); m_currentNode = Turns[0]; return; } // going forward if (step > 0 && m_currentNode != null) { for (int i = 0; i < step; ++i) { // take 1st variation as default if (m_currentNode.NextTurns.Count > 0) { m_currentNode = m_currentNode.NextTurns[0]; if (!m_currentNode.Move.IsPass) { // wanna add this move so if it was asked to be remove, cancel it pointsToRemove.Remove(m_currentNode.Move.Point); moveToAdd.Add(new GoMove(m_currentNode.Move.Color, m_currentNode.Move.Point, false)); if (m_currentNode != null && m_currentNode.Killed != null) { foreach (GoPoint point in m_currentNode.Killed) { // want to remove it? so if wanted to add it, cancel it List <int> indexToRemove = new List <int>(); for (int j = 0; j < moveToAdd.Count; ++j) { if (moveToAdd[j].Point == point) { indexToRemove.Add(j); } } foreach (int j in indexToRemove) { moveToAdd.RemoveAt(j); } pointsToRemove.Add(point); } } } } } } // going backward else if (step < 0 && m_currentNode != null) { for (int i = step; i < 0; ++i) { if (m_currentNode.PreviousTurn != null) { if (!m_currentNode.Move.IsPass) { // want to remove it? so if wanted to add it, cancel it List <int> indexToRemove = new List <int>(); for (int j = 0; j < moveToAdd.Count; ++j) { if (moveToAdd[j].Point == m_currentNode.Move.Point) { indexToRemove.Add(j); } } foreach (int j in indexToRemove) { moveToAdd.RemoveAt(j); } pointsToRemove.Add(m_currentNode.Move.Point); if (m_currentNode != null && m_currentNode.Killed != null) { foreach (GoPoint point in m_currentNode.Killed) { pointsToRemove.Remove(point); moveToAdd.Add(new GoMove(Helper.GetOppositeColor(m_currentNode.Move.Color), point, false)); } } } m_currentNode = m_currentNode.PreviousTurn; } } } }
// return true if the move is accepted, otherwise false // and message indicate why public bool PlayMove(GoMove move, ref GoMessageId message) { bool isValid = false; if (m_currentTurn != Turns.Count) { throw new Exception("You can't play if the state of the game is not the most recent, you might want to create a variation though but it is not implemented yet!"); } if (move.IsPass) { // this is a pass // is it the second one? if (Turns.Last().Move.Point == null) { // compute score float score = 0.0f; GoColor winner = GoColor.EMPTY; float whiteScore = 0.0f; float blackScore = 0.0f; StrasCouting(out whiteScore, out blackScore); if (whiteScore > blackScore) { winner = GoColor.WHITE; score = whiteScore - blackScore; } else { winner = GoColor.BLACK; score = blackScore - whiteScore; } // two pass the game is over switch (GameRule) { case RulesType.normal: OnGameIsOver(new GameResultEventArgs(winner, score, blackScore, whiteScore, false)); break; case RulesType.capture_N: int numberOfCapturesForWhite = GetNumberOfCapturedStonesFor(GoColor.WHITE); int numberOfCapturesForBlack = GetNumberOfCapturedStonesFor(GoColor.BLACK); GoColor moreCaptures = numberOfCapturesForWhite == numberOfCapturesForBlack ? GoColor.EMPTY : numberOfCapturesForWhite > numberOfCapturesForBlack ? GoColor.WHITE : GoColor.BLACK; OnGameIsOver(new GameResultEventArgs(moreCaptures , 0 , numberOfCapturesForBlack , numberOfCapturesForWhite , false)); break; default: throw new Exception("Error: unsupported rules type!"); } } GoTurn thisTurn = new GoTurn(move, m_currentTurn); thisTurn.OldKoPoint = KoPoint; // link the turns if (GetLastTurn() != null) { GetLastTurn().NextTurns.Add(thisTurn); thisTurn.PreviousTurn = GetLastTurn(); } // add to the list of turns Turns.Add(thisTurn); m_currentTurn++; isValid = true; } else if (move.Color == m_colorToMove) { // is it the ko point? if (KoPoint != null && move.Point == KoPoint) { message = GoMessageId.KO_THREAT_FIRST; isValid = false; } else { // is it on an empty space? if (Board.isPointFree(move.Point)) { // is it capturing something? List <GoPoint> captured = Board.WillCapture(move); if (captured.Count > 0) { GoTurn thisTurn = new GoTurn(move, m_currentTurn); thisTurn.Killed = captured; thisTurn.OldKoPoint = KoPoint; // link the turns if (GetLastTurn() != null) { GetLastTurn().NextTurns.Add(thisTurn); thisTurn.PreviousTurn = GetLastTurn(); } // add to the list of turns Turns.Add(thisTurn); m_currentTurn++; isValid = true; } else { // otherwise is it a suicide? if (Board.IsSuicide(move)) { message = GoMessageId.SUICIDE_MOVE; isValid = false; } else { // play the move increment turn counting GoTurn thisTurn = new GoTurn(move, m_currentTurn); thisTurn.OldKoPoint = KoPoint; // link the turns if (GetLastTurn() != null) { GetLastTurn().NextTurns.Add(thisTurn); thisTurn.PreviousTurn = GetLastTurn(); } // add to the list of turns Turns.Add(thisTurn); m_currentTurn++; isValid = true; } } } else { message = GoMessageId.ALREADY_A_STONE; isValid = false; } } } else { // WARNING your move will be ignored message = GoMessageId.NOT_COLOR_TURN; isValid = false; } if (isValid) { Board.Execute(Turns.Last()); KoPoint = null; // did it created a ko? if (GetLastTurn().Killed != null && GetLastTurn().Killed.Count == 1) { // test if the captured position would be a suicide for the other color GoMove suicideTest = new GoMove( Helper.GetOppositeColor(move.Color), GetLastTurn().Killed[0], false); if (Board.IsSuicide(suicideTest)) { // but if it capture exactly one stone back it is a ko List <GoPoint> koTest = Board.WillCapture(suicideTest); if (koTest.Count == 1) { KoPoint = suicideTest.Point; } } } else { // otherwise reinitialise the ko to null KoPoint = null; } // if it capture and we are playing the capture 5 stones rules // we need to check if the game is over if (GameRule == RulesType.capture_N && GetLastTurn().Killed != null && GetLastTurn().Killed.Count > 0) { if (GetNumberOfCapturedStonesFor(m_colorToMove) >= NumberOfStonesToCapture) { OnGameIsOver(new GameResultEventArgs(m_colorToMove , 0 , GetNumberOfCapturedStonesFor(GoColor.BLACK) , GetNumberOfCapturedStonesFor(GoColor.WHITE) , false)); } } Clock.NotifyMovePlayed(m_colorToMove); m_colorToMove = Helper.GetOppositeColor(m_colorToMove); } return(isValid); } // end of PlayMove
// step can be negative public void GetBoardModifications( ref List<GoPoint> pointsToRemove, ref List<GoMove> moveToAdd, int step ) { pointsToRemove.Clear(); moveToAdd.Clear(); // special case when m_currentNode is null but a move has been played if (m_currentNode == null && step > 0 && Turns.Count == 1) { moveToAdd.Add(new GoMove(Turns[0].Move.Color, Turns[0].Move.Point, false) ); m_currentNode = Turns[0]; return; } // going forward if (step > 0 && m_currentNode != null) { for (int i = 0; i < step; ++i) { // take 1st variation as default if (m_currentNode.NextTurns.Count > 0) { m_currentNode = m_currentNode.NextTurns[0]; if (!m_currentNode.Move.IsPass) { // wanna add this move so if it was asked to be remove, cancel it pointsToRemove.Remove(m_currentNode.Move.Point); moveToAdd.Add(new GoMove(m_currentNode.Move.Color, m_currentNode.Move.Point, false)); if (m_currentNode != null && m_currentNode.Killed != null) { foreach (GoPoint point in m_currentNode.Killed) { // want to remove it? so if wanted to add it, cancel it List<int> indexToRemove = new List<int>(); for (int j = 0; j < moveToAdd.Count; ++j) { if (moveToAdd[j].Point == point) { indexToRemove.Add(j); } } foreach (int j in indexToRemove) { moveToAdd.RemoveAt(j); } pointsToRemove.Add(point); } } } } } } // going backward else if (step < 0 && m_currentNode != null) { for (int i = step; i < 0; ++i) { if (m_currentNode.PreviousTurn != null) { if (!m_currentNode.Move.IsPass) { // want to remove it? so if wanted to add it, cancel it List<int> indexToRemove = new List<int>(); for (int j = 0; j < moveToAdd.Count; ++j) { if (moveToAdd[j].Point == m_currentNode.Move.Point) { indexToRemove.Add(j); } } foreach (int j in indexToRemove) { moveToAdd.RemoveAt(j); } pointsToRemove.Add(m_currentNode.Move.Point); if (m_currentNode != null && m_currentNode.Killed != null) { foreach (GoPoint point in m_currentNode.Killed) { pointsToRemove.Remove(point); moveToAdd.Add(new GoMove(Helper.GetOppositeColor(m_currentNode.Move.Color), point, false)); } } } m_currentNode = m_currentNode.PreviousTurn; } } } }
// return true if the move is accepted, otherwise false // and message indicate why public bool PlayMove(GoMove move, ref GoMessageId message) { bool isValid = false; if (m_currentTurn != Turns.Count) { throw new Exception("You can't play if the state of the game is not the most recent, you might want to create a variation though but it is not implemented yet!"); } if(move.IsPass) { // this is a pass // is it the second one? if (Turns.Last().Move.Point == null) { // compute score float score = 0.0f; GoColor winner = GoColor.EMPTY; float whiteScore = 0.0f; float blackScore = 0.0f; StrasCouting(out whiteScore, out blackScore); if (whiteScore > blackScore) { winner = GoColor.WHITE; score = whiteScore - blackScore; } else { winner = GoColor.BLACK; score = blackScore - whiteScore; } // two pass the game is over switch (GameRule) { case RulesType.normal: OnGameIsOver(new GameResultEventArgs(winner, score, blackScore, whiteScore, false)); break; case RulesType.capture_N: int numberOfCapturesForWhite = GetNumberOfCapturedStonesFor(GoColor.WHITE); int numberOfCapturesForBlack = GetNumberOfCapturedStonesFor(GoColor.BLACK); GoColor moreCaptures = numberOfCapturesForWhite == numberOfCapturesForBlack ? GoColor.EMPTY : numberOfCapturesForWhite > numberOfCapturesForBlack ? GoColor.WHITE : GoColor.BLACK; OnGameIsOver(new GameResultEventArgs(moreCaptures , 0 , numberOfCapturesForBlack , numberOfCapturesForWhite , false)); break; default: throw new Exception("Error: unsupported rules type!"); } } GoTurn thisTurn = new GoTurn(move, m_currentTurn); thisTurn.OldKoPoint = KoPoint; // link the turns if (GetLastTurn() != null) { GetLastTurn().NextTurns.Add(thisTurn); thisTurn.PreviousTurn = GetLastTurn(); } // add to the list of turns Turns.Add(thisTurn); m_currentTurn++; isValid = true; } else if(move.Color == m_colorToMove) { // is it the ko point? if (KoPoint != null && move.Point == KoPoint) { message = GoMessageId.KO_THREAT_FIRST; isValid = false; } else { // is it on an empty space? if (Board.isPointFree(move.Point)) { // is it capturing something? List<GoPoint> captured = Board.WillCapture(move); if (captured.Count > 0) { GoTurn thisTurn = new GoTurn(move, m_currentTurn); thisTurn.Killed = captured; thisTurn.OldKoPoint = KoPoint; // link the turns if (GetLastTurn() != null) { GetLastTurn().NextTurns.Add(thisTurn); thisTurn.PreviousTurn = GetLastTurn(); } // add to the list of turns Turns.Add(thisTurn); m_currentTurn++; isValid = true; } else { // otherwise is it a suicide? if (Board.IsSuicide(move)) { message = GoMessageId.SUICIDE_MOVE; isValid = false; } else { // play the move increment turn counting GoTurn thisTurn = new GoTurn(move, m_currentTurn); thisTurn.OldKoPoint = KoPoint; // link the turns if (GetLastTurn() != null ) { GetLastTurn().NextTurns.Add(thisTurn); thisTurn.PreviousTurn = GetLastTurn(); } // add to the list of turns Turns.Add(thisTurn); m_currentTurn++; isValid = true; } } } else { message = GoMessageId.ALREADY_A_STONE; isValid = false; } } } else { // WARNING your move will be ignored message = GoMessageId.NOT_COLOR_TURN; isValid = false; } if (isValid) { Board.Execute(Turns.Last()); KoPoint = null; // did it created a ko? if (GetLastTurn().Killed != null && GetLastTurn().Killed.Count == 1) { // test if the captured position would be a suicide for the other color GoMove suicideTest = new GoMove( Helper.GetOppositeColor(move.Color), GetLastTurn().Killed[0], false); if( Board.IsSuicide(suicideTest)) { // but if it capture exactly one stone back it is a ko List<GoPoint> koTest = Board.WillCapture(suicideTest); if (koTest.Count == 1) { KoPoint = suicideTest.Point; } } } else { // otherwise reinitialise the ko to null KoPoint = null; } // if it capture and we are playing the capture 5 stones rules // we need to check if the game is over if (GameRule == RulesType.capture_N && GetLastTurn().Killed != null && GetLastTurn().Killed.Count > 0) { if (GetNumberOfCapturedStonesFor(m_colorToMove) >= NumberOfStonesToCapture) { OnGameIsOver(new GameResultEventArgs(m_colorToMove , 0 , GetNumberOfCapturedStonesFor(GoColor.BLACK) , GetNumberOfCapturedStonesFor(GoColor.WHITE) , false)); } } Clock.NotifyMovePlayed(m_colorToMove); m_colorToMove = Helper.GetOppositeColor(m_colorToMove); } return isValid; }