public GoMove Hint(GoColor color) { WriteCommand("reg_genmove", color == GoColor.Black ? "black" : "white"); string code, msg; ReadResponse(out code, out msg); GoMove hint; switch (msg) { case "PASS": hint = new GoMove(MoveType.Pass, color, null); break; case "resign": hint = new GoMove(MoveType.Resign, color, null); break; default: hint = new GoMove(MoveType.Normal, color, msg); break; } return(hint); }
///// <summary> ///// Used to setup handicap or other initial board position. Fails if there are already pieces on the board. ///// </summary> //public void Place(GoMove[] moves) //{ // foreach (var m in moves) // { // WriteCommand("place_free_handicap", m.Color == GoColor.Black ? "black" : "white" + ' ' + m.Position); // ReadResponse(); // } //} /// <summary> /// Used to make a move. This returns immediately, since no real processing has to be done. /// </summary> public GoMoveResult Play(GoMove move) { if (move.MoveType == MoveType.Resign) { // Do nothing - fuego doesn't support the command to resign. } else { string position; switch (move.MoveType) { case MoveType.Normal: position = move.Position; break; case MoveType.Pass: position = "PASS"; break; default: throw new ArgumentException("Unrecognized move type: " + move.MoveType); } WriteCommand("play", (move.Color == GoColor.Black ? "black" : "white") + ' ' + position); ReadResponse(); } // Add to move history and record new game state in database so user can // see what happened. var rval = AddMoveAndUpdateStateAndSaveToDatabase(move); return(rval); }
public async void ExecuteResign() { MessageText = "Resigning..."; IsBusy = true; var move = new GoMove(MoveType.Resign, _players[WhoseTurn].Color, null); var resp = await DataRepository.PlayAsync(ActiveGame, move); IsBusy = false; MessageText = null; if (resp.ResultCode == GoResultCode.Success) { //AddMoveToHistory(resp.Move, resp.MoveResult); SwapTurns(); SetState(resp.MoveResult.Status, resp.MoveResult.WinMargin); } else if (resp.ResultCode == GoResultCode.CommunicationError) { await HandleCommunicationError("Resigning..."); } else { await DisplayErrorCode(resp.ResultCode); LoadGameFromRepoAsync("Syncronizing..."); } RaiseCommandsChanged(); }
public void GenMove(Guid gameId, GoColor color, out GoMove newMove, out GoMoveResult result) { // Get a Fuego instance and start it up. FuegoInstance inst = null; try { inst = GetFuegoInstance(gameId, GoOperation.GenMove); inst.EnsureRunning(); inst.GenMove(color, out newMove, out result); } // ReSharper disable RedundantCatchClause catch (Exception) { throw; } // ReSharper restore RedundantCatchClause finally { if (inst != null) { inst.CurrentOperation = GoOperation.Idle; } } }
private GoMoveResult AddMoveAndUpdateState(GoMove move) { GoMoveResult rval; try { var beforeBlack = _state.BlackPositions; var beforeWhite = _state.WhitePositions; GetStones(); // Gets the new _state.BlackPositions and _state.WhitePositions. if (move.Color == GoColor.Black) { rval = new GoMoveResult(beforeWhite, _state.WhitePositions); } else { rval = new GoMoveResult(beforeBlack, _state.BlackPositions); } _state.GoMoveHistory.Add(new GoMoveHistoryItem { Move = move, Result = rval }); // Change turn. _state.WhoseTurn = _state.WhoseTurn == GoColor.Black ? GoColor.White : GoColor.Black; switch (move.MoveType) { case MoveType.Resign: _state.Status = move.Color == GoColor.Black ? GoGameStatus.WhiteWonDueToResignation : GoGameStatus.BlackWonDueToResignation; break; case MoveType.Pass: // If previous move was a pass also, mark end game, but don't record // the game in the _fuego instance so that the end game // dead stone calculation will still work properly. var moveCount = _state.GoMoveHistory.Count; var previousMoveWasPass = moveCount >= 2 && _state.GoMoveHistory[moveCount - 2].Move.MoveType == MoveType.Pass; if (previousMoveWasPass) { _state.Status = GoGameStatus.Ended; ParseResponse(WriteCommand("gg-undo", "1")); } break; } rval.Status = _state.Status; } catch (Exception) { throw; } return(rval); }
private GoMoveResult AddMoveAndUpdateState(GoMove move) { GoMoveResult rval; try { var beforeBlack = _state.BlackPositions; var beforeWhite = _state.WhitePositions; GetStones(); // Gets the new _state.BlackPositions and _state.WhitePositions. if (move.Color == GoColor.Black) { rval = new GoMoveResult(beforeWhite, _state.WhitePositions); } else { rval = new GoMoveResult(beforeBlack, _state.BlackPositions); } _state.GoMoveHistory.Add(new GoMoveHistoryItem { Move = move, Result = rval }); // Change turn. _state.WhoseTurn = _state.WhoseTurn == GoColor.Black ? GoColor.White : GoColor.Black; switch (move.MoveType) { case MoveType.Resign: _state.Status = move.Color == GoColor.Black ? GoGameStatus.WhiteWonDueToResignation : GoGameStatus.BlackWonDueToResignation; break; case MoveType.Pass: // If previous move was a pass also, calculate winner. var moveCount = _state.GoMoveHistory.Count; bool previousMoveWasPass = moveCount >= 2 && _state.GoMoveHistory[moveCount - 2].Move.MoveType == MoveType.Pass; if (previousMoveWasPass) { var gameResult2 = CalculateGameResult(); _state.WinMargin = decimal.Parse(gameResult2.Substring(1)); _state.Status = gameResult2.StartsWith("B") ? GoGameStatus.BlackWon : GoGameStatus.WhiteWon; } break; } rval.Status = _state.Status; rval.WinMargin = _state.WinMargin; } catch (Exception ex) { throw; } return(rval); }
public async void ExecutePressedCommand(string position) { // Note: position is the Go position such as "A15" where the user pressed. if (!Pieces.ContainsKey(position)) { return; } _savedColor = Pieces[position].Color; Pieces[position].Color = _players[WhoseTurn].Color; Pieces[position].RaiseMultiplePropertiesChanged(); MessageText = "Moving..."; IsBusy = true; var move = new GoMove(MoveType.Normal, _players[WhoseTurn].Color, position); GoMoveResponse resp = await DataRepository.PlayAsync(ActiveGame, move); IsBusy = false; MessageText = null; if (resp.ResultCode == GoResultCode.Success) { AddMoveToHistory(resp.Move, resp.MoveResult); //Pieces[resp.Move.Position].IsNewPiece = true; RemoveCapturedPieces(resp); CurrentPlayer.Prisoners += resp.MoveResult.CapturedStones.Split(' ').Count(x => x != String.Empty); Pieces[position].RaiseMultiplePropertiesChanged(); SwapTurns(); SetState(resp.MoveResult.Status, resp.MoveResult.WinMargin); if (Status == GoGameStatus.Active) { PlayCurrentUser(); } } else if (resp.ResultCode == GoResultCode.CommunicationError) { await HandleCommunicationError("Moving..."); } else { Pieces[position].Color = _savedColor; Pieces[position].RaiseMultiplePropertiesChanged(); await DisplayErrorCode(resp.ResultCode); } RaiseCommandsChanged(); }
public async Task <GoHintResponse> HintAsync(Guid gameid, GoColor color) { GoHintResponse rval = null; try { await Task.Factory.StartNew( () => { EnsureFuegoStarted().Wait(); _state.Operation = GoOperation.Hint; SaveState(); var result = ParseResponse(WriteCommand("reg_genmove", color == GoColor.Black ? "black" : "white")); GoMove hint; switch (result.Msg) { case "PASS": hint = new GoMove(MoveType.Pass, color, null); break; case "resign": hint = new GoMove(MoveType.Resign, color, null); break; default: hint = new GoMove(MoveType.Normal, color, result.Msg); break; } rval = new GoHintResponse(GoResultCode.Success, hint); _state.Operation = GoOperation.Idle; SaveState(); }); } catch (GoEngineException gex) { rval = new GoHintResponse(gex.Code, null); } catch (Exception ex) { rval = new GoHintResponse(GoResultCode.ServerInternalError, null); } Debug.Assert(rval != null, "rval != null"); return(rval); }
public GoMoveResult Play(Guid gameId, GoMove move) { if (move == null) { throw new ArgumentNullException("move"); } // Get a Fuego instance and start it up. FuegoInstance inst = null; try { GoOperation op; switch (move.MoveType) { case MoveType.Normal: op = GoOperation.NormalMove; break; case MoveType.Pass: op = GoOperation.Pass; break; case MoveType.Resign: op = GoOperation.Resign; break; default: throw new Exception("Unrecognized move type: " + move.MoveType); } inst = GetFuegoInstance(gameId, op); inst.EnsureRunning(); var result = inst.Play(move); return(result); } // ReSharper disable RedundantCatchClause catch (Exception) { throw; } // ReSharper restore RedundantCatchClause finally { if (inst != null) { inst.CurrentOperation = GoOperation.Idle; } } }
public GoMoveResponse Play(Guid gameid, GoMove move) { GoMoveResponse rval; try { var result = FuegoEngine.Instance.Play(gameid, move); rval = new GoMoveResponse(GoResultCode.Success, move, result); } catch (GoEngineException gex) { _logger.LogEngineException(gameid, gex, move); rval = new GoMoveResponse(gex.Code, null, null); } catch (Exception ex) { _logger.LogServerError(gameid, ex, move); rval = new GoMoveResponse(GoResultCode.ServerInternalError, null, null); } return(rval); }
//public void Place(IEnumerable<string> positions, GoColor color) //{ // GoMove[] moves = positions.Select(m => new GoMove(MoveType.Normal, color, m)).ToArray(); // Place(moves); //} public void GenMove(GoColor color, out GoMove newMove, out GoMoveResult result) { // This debug code generates a resign from the AI randomly. //int x = r.Next(5); //if (x == 0) //{ // newMove = new GoMove(MoveType.Resign, color, null); // //WriteCommand("play", color == GoColor.Black ? "black resign" : "white resign"); // //ReadResponse(); // result = AddMoveAndUpdateStateAndSaveToDatabase(newMove); // return; //} WriteCommand("genmove", color == GoColor.Black ? "black" : "white"); string code, msg; ReadResponse(out code, out msg); switch (msg) { case "PASS": newMove = new GoMove(MoveType.Pass, color, null); break; case "resign": newMove = new GoMove(MoveType.Resign, color, null); break; default: newMove = new GoMove(MoveType.Normal, color, msg); break; } // Add to move history and record new game state in database so user can // see what happened. //Thread.Sleep(30000); result = AddMoveAndUpdateStateAndSaveToDatabase(newMove); }
private void AddMoveToHistory(GoMove move, GoMoveResult result) { try { if (move.MoveType == MoveType.Normal) { var latestPiece = GetLatestNormalMovePieceFromHistory(); if (latestPiece != null) { latestPiece.IsNewPiece = false; latestPiece.RaiseMultiplePropertiesChanged(); } } History.Insert(0, new GoMoveHistoryItem { Move = move, Result = result, }); if (move.MoveType == MoveType.Normal) { var latestPiece = GetLatestNormalMovePieceFromHistory(); if (latestPiece != null) { latestPiece.IsNewPiece = true; latestPiece.RaiseMultiplePropertiesChanged(); } } } catch (Exception) { // eat a winrt bug where the UI sees the inserted item and throws an exception if the user // already navigated away from the game page. throw; } }
public async Task <GoMoveResponse> GenMoveAsync(Guid id, GoColor color) { await LoadState(); GoMoveResponse rval = null; try { await Task.Run( async() => { await EnsureFuegoStartedAndMatchingGame(id); _state.Operation = GoOperation.GenMove; // This debug code generates a resign from the AI randomly. //int x = r.Next(5); //if (x == 0) //{ // newMove = new GoMove(MoveType.Resign, color, null); // //WriteCommand("play", color == GoColor.Black ? "black resign" : "white resign"); // //ReadResponse(); // result = AddMoveAndUpdateStateAndSaveToDatabase(newMove); // return; //} // Using kgs-genmove_cleanup for AI is important because // it will allow the final_status_list dead to be calculated // properly more often. // // This command captures the more obvious dead // stones before passing, though contrary to documentation // it does not capture ALL dead stones. // // Using just "genmove" will more often generate PASS prematurely // because it guesses too much about dead stones. Similarly, // "genmove" causes "final_status_list dead" to more often // generate strange results. var result = ParseResponse(WriteCommand("kgs-genmove_cleanup", color == GoColor.Black ? "black" : "white")); GoMove newMove; switch (result.Msg) { case "PASS": newMove = new GoMove(MoveType.Pass, color, null); break; case "resign": newMove = new GoMove(MoveType.Resign, color, null); break; default: newMove = new GoMove(MoveType.Normal, color, result.Msg); break; } // Add to move history and record new game state in database so user can // see what happened. var moveResult = AddMoveAndUpdateState(newMove); _state.Operation = GoOperation.Idle; await SaveState(); rval = new GoMoveResponse(GoResultCode.Success, newMove, moveResult); }); } catch (GoEngineException gex) { rval = new GoMoveResponse(gex.Code, null, null); } catch (Exception) { rval = new GoMoveResponse(GoResultCode.InternalError, null, null); } Debug.Assert(rval != null, "rval != null"); return(rval); }
public async Task <GoMoveResponse> GenMoveAsync(Guid gameid, GoColor color) { GoMoveResponse rval = null; try { await Task.Factory.StartNew( () => { EnsureFuegoStarted().Wait(); _state.Operation = GoOperation.GenMove; SaveState(); // This debug code generates a resign from the AI randomly. //int x = r.Next(5); //if (x == 0) //{ // newMove = new GoMove(MoveType.Resign, color, null); // //WriteCommand("play", color == GoColor.Black ? "black resign" : "white resign"); // //ReadResponse(); // result = AddMoveAndUpdateStateAndSaveToDatabase(newMove); // return; //} var result = ParseResponse(WriteCommand("genmove", color == GoColor.Black ? "black" : "white")); GoMove newMove; switch (result.Msg) { case "PASS": newMove = new GoMove(MoveType.Pass, color, null); break; case "resign": newMove = new GoMove(MoveType.Resign, color, null); break; default: newMove = new GoMove(MoveType.Normal, color, result.Msg); break; } // Add to move history and record new game state in database so user can // see what happened. var moveResult = AddMoveAndUpdateState(newMove); _state.Operation = GoOperation.Idle; SaveState(); rval = new GoMoveResponse(GoResultCode.Success, newMove, moveResult); }); } catch (GoEngineException gex) { rval = new GoMoveResponse(gex.Code, null, null); } catch (Exception ex) { rval = new GoMoveResponse(GoResultCode.ServerInternalError, null, null); } Debug.Assert(rval != null, "rval != null"); return(rval); }
public GoHintResponse(GoResultCode resultCode, GoMove move) : base(resultCode) { Move = move; }
public async Task <GoMoveResponse> PlayAsync(Guid id, GoMove move) { await LoadState(); GoMoveResponse rval = null; GoMoveResult moveResult; try { await Task.Run( async() => { await EnsureFuegoStartedAndMatchingGame(id); if (move.MoveType == MoveType.Resign) { // Fuego doesn't support the command to resign. _state.Operation = GoOperation.Resign; moveResult = AddMoveAndUpdateState(move); await SaveState(); } else { string position; switch (move.MoveType) { case MoveType.Normal: position = move.Position; _state.Operation = GoOperation.NormalMove; break; case MoveType.Pass: position = "PASS"; _state.Operation = GoOperation.Pass; break; default: throw new ArgumentException("Unrecognized move type: " + move.MoveType); } // This throws a GoEngineException on any failure. ParseResponse(WriteCommand("play", (move.Color == GoColor.Black ? "black" : "white") + ' ' + position)); // Add to move history and persist new game state so user can // see what happened. moveResult = AddMoveAndUpdateState(move); _state.Operation = GoOperation.Idle; await SaveState(); } Debug.Assert(moveResult != null, "moveResult != null"); rval = new GoMoveResponse(GoResultCode.Success, move, moveResult); }); } catch (GoEngineException gex) { rval = new GoMoveResponse(gex.Code, null, null); } catch (Exception) { rval = new GoMoveResponse(GoResultCode.InternalError, null, null); } Debug.Assert(rval != null, "rval != null"); return(rval); }
public GoMoveResponse(GoResultCode resultCode, GoMove move, GoMoveResult result) : base(resultCode) { Move = move; MoveResult = result; }
private GoMoveResult AddMoveAndUpdateStateAndSaveToDatabase(GoMove move) { try { var beforeBlack = State.BlackPositions; var beforeWhite = State.WhitePositions; GetStones(); // Gets the new _state.BlackPositions and _state.WhitePositions. GoMoveResult rval; if (move.Color == GoColor.Black) { rval = new GoMoveResult(beforeWhite, State.WhitePositions); } else { rval = new GoMoveResult(beforeBlack, State.BlackPositions); } if (State.GoMoveHistory == null) { State.GoMoveHistory = new List <GoMoveHistoryItem>(); } State.GoMoveHistory.Add(new GoMoveHistoryItem { Move = move, Result = rval }); // Change turn. State.WhoseTurn = State.WhoseTurn == GoColor.Black ? GoColor.White : GoColor.Black; switch (move.MoveType) { case MoveType.Resign: State.Status = move.Color == GoColor.Black ? GoGameStatus.WhiteWonDueToResignation : GoGameStatus.BlackWonDueToResignation; //var gameResult = CalculateGameResult(); //State.WinMargin = Decimal.Parse(gameResult.Substring(1)); break; case MoveType.Pass: // If previous move was a pass also, calculate winner. var moveCount = State.GoMoveHistory.Count; bool previousMoveWasPass = moveCount >= 2 && State.GoMoveHistory[moveCount - 2].Move.MoveType == MoveType.Pass; if (previousMoveWasPass) { var gameResult2 = CalculateGameResult(); State.WinMargin = Decimal.Parse(gameResult2.Substring(1)); State.Status = gameResult2.StartsWith("B") ? GoGameStatus.BlackWon : GoGameStatus.WhiteWon; } break; } rval.Status = State.Status; rval.WinMargin = State.WinMargin; // Save to database. _goGRepository.SaveGameState(CurrentGameId, State); return(rval); } catch (DbEntityValidationException) { // Setting State to null will cause it to be loaded from database the next time // a client initiates an operation. State = null; throw; } }
public async Task <GoHintResponse> HintAsync(Guid id, GoColor color) { await LoadState(); GoHintResponse rval = null; try { await Task.Run( async() => { await EnsureFuegoStartedAndMatchingGame(id); _state.Operation = GoOperation.Hint; // Remove limitation so we can get a good hint, even on lower // difficulty levels. SetDifficulty(true); var result = ParseResponse(WriteCommand("reg_genmove", color == GoColor.Black ? "black" : "white")); GoMove hint; switch (result.Msg) { case "PASS": hint = new GoMove(MoveType.Pass, color, null); break; case "resign": hint = new GoMove(MoveType.Resign, color, null); break; default: hint = new GoMove(MoveType.Normal, color, result.Msg); break; } rval = new GoHintResponse(GoResultCode.Success, hint); _state.Operation = GoOperation.Idle; await SaveState(); }); } catch (GoEngineException gex) { rval = new GoHintResponse(gex.Code, null); } catch (Exception) { rval = new GoHintResponse(GoResultCode.InternalError, null); } finally { try { // Reset to configured difficulty level. SetDifficulty(); } catch (Exception) { // ignored } } Debug.Assert(rval != null, "rval != null"); return(rval); }