public GoTurn(GoMove move, int number) { Move = move; TurnNumber = number; PreviousTurn = null; NextTurns = new List<GoTurn>(); }
public List <GoPoint> WillCapture(GoMove move) { List <GoPoint> captured = new List <GoPoint>(); GoColor capturedColor = Helper.GetOppositeColor(move.Color); // check adjacents foreach (GoPoint potentialCaptured in getAdjacents(move.Point)) { if (Stones.ContainsKey(potentialCaptured)) { if (Stones[potentialCaptured] == capturedColor && !captured.Contains(potentialCaptured)) { // check liberties // note: this checking is done before the move is executed // means that actually if this adjacent group has only one liberty // we will play on it, so yes it will be captured List <GoPoint> group, liberties; CheckGroupLiberties(potentialCaptured, capturedColor, out group, out liberties); if (liberties.Count < 2) { // it is captured captured.AddRange(group); } } } } return(captured); }
public GoTurn(GoMove move, int number) { Move = move; TurnNumber = number; PreviousTurn = null; NextTurns = new List <GoTurn>(); }
public bool IsSuicide(GoMove move) { List <GoPoint> group, liberties; CheckGroupLiberties(move.Point, move.Color, out group, out liberties); return(liberties.Count == 0); }
private void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine) { Console.WriteLine(outLine.Data); // Collect the sort command output. if (!String.IsNullOrEmpty(outLine.Data)) { // Send event to notify response if (ResponsePushed != null) { ResponsePushed(this, new ResponseEventArgs(outLine.Data)); } if (!string.IsNullOrEmpty(m_expectedAnswer)) { if (m_expectedAnswer != outLine.Data) { throw new Exception("The program Pachi is not behaving as expected! The program needs to shutdown!"); } else { // we can clear that expected answer then m_expectedAnswer = null; } } // TODO proper parsing with regex to avoid errors // Analyse the response if (outLine.Data.StartsWith("=")) { m_waitingForAnswer = false; if (m_invalidateAnyMoves) { return; } if (outLine.Data == "= pass") { GoMove move = new GoMove(m_lastColorAsked, null, true); // Send the play if (HasPlayed != null && move != null) { HasPlayed(this, move); } } else { // parse the answer String coord = outLine.Data.Substring(2); if (coord.Length >= 2) { int x = (int)(coord[0] - 'A') + 1; // because I column doesn't exist if (coord[0] > 'I') { x = x - 1; } int y = int.Parse(coord.Substring(1)); GoPoint point = new GoPoint(x, y); GoMove move = new GoMove(m_lastColorAsked, point, false); // Send the play if (HasPlayed != null && move != null) { HasPlayed(this, move); } } } } } ExecuteNextCommand(); }
// 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
public List<GoPoint> WillCapture(GoMove move) { List<GoPoint> captured = new List<GoPoint>(); GoColor capturedColor = Helper.GetOppositeColor(move.Color); // check adjacents foreach (GoPoint potentialCaptured in getAdjacents(move.Point)) { if (Stones.ContainsKey(potentialCaptured)) { if (Stones[potentialCaptured] == capturedColor && !captured.Contains(potentialCaptured)) { // check liberties // note: this checking is done before the move is executed // means that actually if this adjacent group has only one liberty // we will play on it, so yes it will be captured List<GoPoint> group, liberties; CheckGroupLiberties(potentialCaptured, capturedColor, out group, out liberties); if (liberties.Count < 2) { // it is captured captured.AddRange(group); } } } } return captured; }
public bool IsSuicide(GoMove move) { List<GoPoint> group, liberties; CheckGroupLiberties(move.Point, move.Color, out group, out liberties); return liberties.Count == 0; }
// 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; }