Пример #1
0
        /// <summary>
        /// Starts the fuego engine and resets its game state to the given state.
        /// </summary>
        /// <param name="gameid"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        public async Task <GoGameStateResponse> StartAsync(Guid gameid, GoGameState state)
        {
            GoGameStateResponse rval;

            try
            {
                // Either we're starting a new game, or a game already exist and we're just
                // setting up fuego.
                Debug.Assert(state != null || _state != null, "state != null || _state != null");

                _fuego = new FuegoInstance();

                await Task.Factory.StartNew(() => StartProcess(state));

                rval = new GoGameStateResponse(GoResultCode.Success, state);
            }
            catch (GoEngineException gex)
            {
                rval = new GoGameStateResponse(gex.Code, null);
            }
            catch (Exception ex)
            {
                rval = new GoGameStateResponse(GoResultCode.ServerInternalError, null);
            }

            return(rval);
        }
Пример #2
0
        private void UpdateStateFromExeAndSaveToDatabase()
        {
            try
            {
                WriteCommand("showboard");
                ReadResponse();
                var msg = new StringBuilder();
                foreach (var l in _debugLines)
                {
                }

                GetStones(); // Gets the new _state.BlackPositions and _state.WhitePositions.

                if (State.GoMoveHistory == null)
                {
                    State.GoMoveHistory = new List <GoMoveHistoryItem>();
                }

                // Determine whose 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;
            }
        }
Пример #3
0
        public GoGameState GetGameState(Guid gameId)
        {
            using (var ctx = new GoGEntities())
            {
                var g = ctx.Games.FirstOrDefault(game => game.GameId == gameId);
                if (g == null)
                {
                    return(null);
                }

                var goMoveHistory = new List <GoMoveHistoryItem>();
                foreach (var h in g.Moves.OrderBy(h => h.Sequence))
                {
                    var newHistoryItem = new GoMoveHistoryItem();

                    newHistoryItem.Sequence = h.Sequence;

                    // Translate Move from db.
                    newHistoryItem.Move = new GoMove
                    {
                        Color    = h.IsBlack ? GoColor.Black : GoColor.White,
                        Position = h.Position,
                        MoveType = (MoveType)h.MoveType
                    };

                    // Translate Result from db.
                    newHistoryItem.Result = new GoMoveResult(h.Captured);

                    goMoveHistory.Add(newHistoryItem);
                }

                var p1 = new GoPlayer
                {
                    Level      = g.Player1Level,
                    Name       = g.Player1Name,
                    PlayerType = (PlayerType)g.Player1Type,
                    Score      = g.Player1Score,
                };
                var p2 = new GoPlayer
                {
                    Level      = g.Player2Level,
                    Name       = g.Player2Name,
                    PlayerType = (PlayerType)g.Player2Type,
                    Score      = g.Player2Score
                };
                var rval = new GoGameState(g.Size,
                                           p1, p2,
                                           (GoGameStatus)g.Status,
                                           g.BlacksTurn ? GoColor.Black : GoColor.White,
                                           g.BlackStones, g.WhiteStones,
                                           goMoveHistory,
                                           g.WinMargin);
                return(rval);
            }
        }
Пример #4
0
        //public GoMoveResult Undo()
        //{
        //    WriteCommand("undo");
        //    ReadResponse();
        //    SaveStones();
        //    var rval = new GoMoveResult();
        //    return rval;
        //}

//        public void Quit()
//        {
//            WriteCommand("quit");
//            ReadResponse();
//            if (Process != null)
//            {
//                try
//                {
//                    Process.Kill();
//                }
//// ReSharper disable EmptyGeneralCatchClause
//                catch
//// ReSharper restore EmptyGeneralCatchClause
//                {
//                }
//            }
//            Process = null;
//        }

        //public string Name()
        //{
        //    WriteCommand("name");
        //    string code, msg;
        //    ReadResponse(out code, out msg);
        //    return msg;
        //}

        //public string Version()
        //{
        //    WriteCommand("version");
        //    string code, msg;
        //    ReadResponse(out code, out msg);
        //    return msg;
        //}

        //public bool IsFunctioning
        //{
        //    get
        //    {
        //        try
        //        {
        //            if (Process == null)
        //                return false;
        //            if (!Process.Responding)
        //                return false;
        //            if (Process.HasExited)
        //                return false;
        //            if (Process.ExitTime > Process.StartTime)
        //                return true;
        //            Name(); // if this causes an exception, we're in a bad state
        //        }
        //        catch (Exception)
        //        {
        //            return false;
        //        }

        //        return true;
        //    }
        //}

        ///// <summary>
        ///// Engine must be running or this will throw an error.
        ///// </summary>
        //public bool CompareEngineState(GoGameState clientState)
        //{
        //    // Get black and white positions from exe.
        //    SaveStones();

        //    // This does a deep comparison.
        //    var rval = Equals(clientState, _state);
        //    return rval;
        //}

        #endregion Public Methods

        #region Private Helpers

        private void ReopenGame()
        {
            try
            {
                State.WinMargin = 0;
                State.Status    = GoGameStatus.Active;

                // Save to database.
                _goGRepository.SaveGameState(CurrentGameId, State);
            }
            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;
            }
        }
Пример #5
0
 public void LoadSGF(string sgf)
 {
     try
     {
         var tmpFilename = Path.GetTempFileName();
         File.WriteAllText(tmpFilename, sgf);
         WriteCommand("loadsgf", '"' + tmpFilename + '"');
         ReadResponse();
         UpdateStateFromExeAndSaveToDatabase();
     }
     catch (Exception)
     {
         // Setting State to null forces it to be loaded from database when the next user request
         // is made to the service.
         State = null;
         throw;
     }
 }
Пример #6
0
 public string SaveSGF()
 {
     try
     {
         var tmpFilename = Path.GetTempFileName();
         WriteCommand("savesgf", '"' + tmpFilename + '"');
         ReadResponse();
         var sgf = File.ReadAllText(tmpFilename, Encoding.UTF8);
         return(sgf);
     }
     catch (Exception)
     {
         // Setting State to null forces it to be loaded from database when the next user request
         // is made to the service.
         State = null;
         throw;
     }
 }
Пример #7
0
 /// <summary>
 /// Checks if fuego is running and if not restarts it.  If no state, starts the game and sets it up
 /// to match the database.
 /// </summary>
 public void EnsureRunning()
 {
     if (Process == null || Process.HasExited)
     {
         State = null;
         RestartProcess();
     }
     if (State == null)
     {
         // Try getting state from database.  If it doesn't exist in the database, then the user
         // never started the game (and we probably shouldn't have gotten to this point).  If it
         // does exist in the database, then we must initialize fuego.exe with the database state.
         var state = _goGRepository.GetGameState(this.CurrentGameId);
         if (state != null)
         {
             Start(state);
         }
     }
 }
Пример #8
0
        public void Start(Guid gameId, GoGameState state)
        {
            if (state == null)
            {
                throw new ArgumentNullException(nameof(state));
            }

            bool exists = _goGRepository.GetGameExists(gameId);

            if (exists)
            {
                throw new GoEngineException(GoResultCode.GameAlreadyExists, null);
            }

            // Get a Fuego instance and start it up.
            FuegoInstance inst = null;

            try
            {
                inst = GetFuegoInstance(gameId, GoOperation.Starting);
                inst.Start(state);

                // Save as the new game state.
                _goGRepository.SaveGameState(gameId, state);
            }
// ReSharper disable RedundantCatchClause
            catch (Exception)
            {
                throw;
            }
// ReSharper restore RedundantCatchClause
            finally
            {
                if (inst != null)
                {
                    inst.CurrentOperation = GoOperation.Idle;
                }
            }
        }
Пример #9
0
        public GoGameStateResponse Start(Guid gameid, GoGameState state)
        {
            GoGameStateResponse rval;

            try
            {
                // TODO: This code assumes only one player is AI, and uses its level setting.
                FuegoEngine.Instance.Start(gameid, state);
                rval = new GoGameStateResponse(GoResultCode.Success, state);
            }
            catch (GoEngineException gex)
            {
                _logger.LogEngineException(gameid, gex, state);
                rval = new GoGameStateResponse(gex.Code, null);
            }
            catch (Exception ex)
            {
                _logger.LogServerError(gameid, ex, state);
                rval = new GoGameStateResponse(GoResultCode.ServerInternalError, null);
            }
            return(rval);
        }
Пример #10
0
        private void LoadState()
        {
            // Note: this is temporary until can figure out why (de)serialization
            // fails with .Net Native compilation.
            return;

            try
            {
                if (_sessionStateService.SessionState.ContainsKey(GameStateKey))
                {
                    _state = (GoGameState)_sessionStateService.SessionState[GameStateKey];
                }

                //var storageFolder = ApplicationData.Current.LocalFolder;
                //var file = await storageFolder.GetFileAsync(StateFilename);
                //var str = await FileIO.ReadTextAsync(file);

                //_state = JsonConvert.DeserializeObject<GoGameState>(str);
            }
            catch (Exception ex)
            {
            }
        }
        private async void StartNewGame()
        {
            try
            {
                bool success             = false;
                GoGameStateResponse resp = null;

                for (int tries = 0; !AbortOperation && !success && tries < 5; tries++)
                {
                    BusyMessage = "Starting game...";
                    IsBusy      = true;

                    var tmpNewGame = Guid.NewGuid();

                    // Create game from user's selections.
                    var p1 = new GoPlayer();
                    var p2 = new GoPlayer();
                    if (Color == (int)GoColor.Black)
                    {
                        p1.Name       = Name;
                        p1.PlayerType = PlayerType.Human;

                        p2.Name       = "Fuego";
                        p2.PlayerType = PlayerType.AI;
                        p2.Level      = DifficultyLevel;
                    }
                    else
                    {
                        p2.Name       = Name;
                        p2.PlayerType = PlayerType.Human;

                        p1.Name       = "Fuego";
                        p1.PlayerType = PlayerType.AI;
                        p1.Level      = DifficultyLevel;
                    }
                    var tmpState = new GoGameState(
                        tmpNewGame,
                        (byte)BoardEdgeSize,
                        p1, p2,
                        GoGameStatus.Active,
                        GoColor.Black,
                        "",
                        "",
                        new List <GoMoveHistoryItem>(),
                        0);
                    resp = await DataRepository.StartAsync(tmpNewGame, tmpState);

                    BusyMessage = null;
                    IsBusy      = false;

                    ActiveGame = tmpNewGame;
                    success    = true;
                }

                if (AbortOperation)
                {
                    return;
                }

                if (success)
                {
                    NavService.Navigate("Game", ActiveGame);
                }
                else
                {
                    if (resp != null)
                    {
                        await DisplayErrorCode(resp.ResultCode);
                    }
                }
            }
            catch (Exception ex)
            {
            }
            finally
            {
                BusyMessage = null;
                IsBusy      = false;
            }
        }
Пример #12
0
 public GoGameStateResponse(GoResultCode resultCode, GoGameState gameState) : base(resultCode)
 {
     GameState = gameState;
 }
Пример #13
0
        async Task StartProcess(GoGameState state)
        {
            if (state != null)
            {
                _state = state;
            }

            _state.Operation = GoOperation.Starting;
            SaveState();

            _fuego.StartGame(_state.Size);

            var level = _state.Player1.PlayerType == PlayerType.AI
                ? _state.Player1.Level
                : _state.Player2.Level;

            // Set up parameters and clear board.
            //await WriteCommand("uct_max_memory", (1024 * 1024 * 250).ToString());

            if (level < 3)
            {
                ParseResponse(WriteCommand("uct_param_player max_games",
                                           ((level + 1) * 10).ToString(CultureInfo.InvariantCulture)));
            }
            else if (level < 6)
            {
                ParseResponse(WriteCommand("uct_param_player max_games",
                                           (level * 2000).ToString(CultureInfo.InvariantCulture)));
            }
            else if (level < 9)
            {
                ParseResponse(WriteCommand("uct_param_player max_games",
                                           (level * 10000).ToString(CultureInfo.InvariantCulture)));
            }
            else //if (level < 9)
            {
                ParseResponse(WriteCommand("uct_param_player max_games",
                                           int.MaxValue.ToString(CultureInfo.InvariantCulture)));
            }

            //WriteCommand("komi", state.Komi.ToString(CultureInfo.InvariantCulture));
            //ReadResponse();
            ParseResponse(WriteCommand("clear_board"));
            ParseResponse(WriteCommand("go_param_rules", "capture_dead 1"));

            // Set up board with some pre-existing moves.
            if (_state.GoMoveHistory.Count > 0)
            {
                // Must actually play every move back because otherwise undo operations
                // won't work.
                foreach (var m in _state.GoMoveHistory)
                {
                    string position;
                    switch (m.Move.MoveType)
                    {
                    case MoveType.Normal:
                        position = m.Move.Position;
                        break;

                    case MoveType.Pass:
                        position = "PASS";
                        break;

                    default:
                        throw new ArgumentException("Unrecognized move type: " + m.Move.MoveType);
                    }

                    ParseResponse(WriteCommand("play",
                                               (m.Move.Color == GoColor.Black ? "black" : "white") + ' ' + position));
                }
            }


            _state.Operation = GoOperation.Idle;
            SaveState();
        }
Пример #14
0
        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;
            }
        }
Пример #15
0
        private void ContinueGameFromState(GoGameState state)
        {
            // Player1 is always black, Player2 is always white.
            Player1 = new PlayerViewModel(state.Player1, GoColor.Black);
            Player2 = new PlayerViewModel(state.Player2, GoColor.White);

            _players = new[] { Player1, Player2 };

            WhoseTurn = state.WhoseTurn == GoColor.Black ? 0 : 1;
            OnPropertyChanged(nameof(WhoseTurn));
            CurrentTurnColor = _players[_whoseTurn].Color;

            SetState(state.Status, state.WinMargin);

            // Note that setting BoardEdgeSize triggers the board control to generate.
            BoardEdgeSize = state.Size;

            // Build a temporary dictionary with ALL the piece states in it, all set to
            // contain an empty PieceState initially.
            var tmpPieces = new Dictionary <string, PieceStateViewModel>();

            for (int x = 0; x < state.Size; x++)
            {
                for (int y = 0; y < state.Size; y++)
                {
                    var position = EngineHelpers.DecodePosition(x, y, state.Size);
                    tmpPieces.Add(position, new PieceStateViewModel(position, null, null, false, false, false));
                }
            }

            // This actually updates the UI.  Note that we can't add anything to Pieces after
            // this point because Pieces is a Dictionary, which can't be observed by the GameBoard
            // control.  From here forward, we simply update individual pieces inside Pieces; we
            // don't add or remove from it.
            Pieces = tmpPieces;

            int blackPrisoners = 0;
            int whitePrisoners = 0;

            // Save history.
            History = new ObservableCollection <GoMoveHistoryItem>();
            foreach (var h in state.GoMoveHistory)
            {
                History.Insert(0, h);
                if (h.Move.Color == GoColor.Black)
                {
                    blackPrisoners += h.Result.CapturedStones.Split(' ').Count(x => x != String.Empty);
                }
                else
                {
                    whitePrisoners += h.Result.CapturedStones.Split(' ').Count(x => x != String.Empty);
                }
            }

            Player1.Prisoners = Player1.Color == GoColor.Black ? blackPrisoners : whitePrisoners;
            Player2.Prisoners = Player2.Color == GoColor.Black ? blackPrisoners : whitePrisoners;

            // Set piece states for all the existing white and black pieces.
            SetPieces(state.BlackPositions, GoColor.Black);
            SetPieces(state.WhitePositions, GoColor.White);

            var latestNormalPiece = GetLatestNormalMovePieceFromHistory();

            if (latestNormalPiece != null)
            {
                latestNormalPiece.IsNewPiece = true;
            }

            // Correct Sequence value.
            //FixSequenceValuesForColor(state, GoColor.Black);
            //FixSequenceValuesForColor(state, GoColor.White);

            RaiseAllPiecesChanged();
            RaiseCommandsChanged();
        }
Пример #16
0
        /// <summary>
        /// Initialize game parameters and board to an given state.
        /// </summary>
        public void Start(GoGameState state)
        {
            try
            {
                if (state == null)
                {
                    throw new ArgumentNullException("state");
                }

                int level = state.Player1.PlayerType == PlayerType.AI ? state.Player1.Level : state.Player2.Level;
                State = state;

                // Set up parameters and clear board.
                WriteCommand("uct_max_memory", _memoryPerInstance.ToString(CultureInfo.InvariantCulture));
                ReadResponse();
                WriteCommand("boardsize", state.Size.ToString(CultureInfo.InvariantCulture));
                ReadResponse();
                if (level < 3)
                {
                    WriteCommand("uct_param_player max_games", ((level + 1) * 10).ToString(CultureInfo.InvariantCulture));
                    ReadResponse();
                }
                else if (level < 6)
                {
                    WriteCommand("uct_param_player max_games", (level * 2000).ToString(CultureInfo.InvariantCulture));
                    ReadResponse();
                }
                else if (level < 9)
                {
                    WriteCommand("uct_param_player max_games", (level * 10000).ToString(CultureInfo.InvariantCulture));
                    ReadResponse();
                }
                else //if (level < 9)
                {
                    WriteCommand("uct_param_player max_games", Int32.MaxValue.ToString(CultureInfo.InvariantCulture));
                    ReadResponse();
                }
                //WriteCommand("komi", state.Komi.ToString(CultureInfo.InvariantCulture));
                //ReadResponse();
                WriteCommand("clear_board");
                ReadResponse();

                WriteCommand("go_param_rules", "capture_dead 1");
                ReadResponse();

                //WriteCommand("showboard");
                //ReadResponse();


                // Set up board with some pre-existing moves.
                if (state.GoMoveHistory != null && state.GoMoveHistory.Count > 0)
                {
                    // Must actually play every move back because otherwise undo operations
                    // won't work.
                    foreach (var m in state.GoMoveHistory)
                    {
                        string position;
                        switch (m.Move.MoveType)
                        {
                        case MoveType.Normal:
                            position = m.Move.Position;
                            break;

                        case MoveType.Pass:
                            position = "PASS";
                            break;

                        default:
                            throw new ArgumentException("Unrecognized move type: " + m.Move.MoveType);
                        }

                        WriteCommand("play", (m.Move.Color == GoColor.Black ? "black" : "white") + ' ' + position);
                        ReadResponse();
                    }

                    //var param = new StringBuilder((19 * 19) * 9);
                    //if (state.BlackPositions != null)
                    //{
                    //    foreach (var p in state.BlackPositions.Trim().Split(' '))
                    //    {
                    //        if (!String.IsNullOrEmpty(p))
                    //        {
                    //            param.Append(" black ");
                    //            param.Append(p);
                    //        }
                    //    }
                    //}
                    //if (state.WhitePositions != null)
                    //{
                    //    foreach (var p in state.WhitePositions.Trim().Split(' '))
                    //    {
                    //        if (!String.IsNullOrEmpty(p))
                    //        {
                    //            param.Append(" white ");
                    //            param.Append(p);
                    //        }
                    //    }
                    //}
                    //WriteCommand("gogui-setup", param.ToString().Trim());
                    //ReadResponse();
                }
            }
            catch (Exception)
            {
                State = null; // Forces next attempt to reload state again.
                throw;
            }
        }
Пример #17
0
        public void SaveGameState(Guid gameId, GoGameState gameState)
        {
            var newMoveHistory = gameState.GoMoveHistory;

            using (var ctx = new GoGEntities())
            {
                // locate game by GameId
                var g = ctx.Games.FirstOrDefault(game => game.GameId == gameId);
                if (g == null)
                {
                    // add game
                    var newGame = new Game
                    {
                        BlackStones  = gameState.BlackPositions,
                        BlacksTurn   = gameState.WhoseTurn == GoColor.Black,
                        GameId       = gameId,
                        Size         = gameState.Size,
                        WhiteStones  = gameState.WhitePositions,
                        Started      = DateTimeOffset.Now,
                        LastMove     = DateTimeOffset.Now,
                        Player1Level = (byte)gameState.Player1.Level,
                        Player2Level = (byte)gameState.Player2.Level,
                        Player1Name  = gameState.Player1.Name,
                        Player2Name  = gameState.Player2.Name,
                        Player1Score = gameState.Player1.Score,
                        Player2Score = gameState.Player2.Score,
                        Player1Type  = (byte)gameState.Player1.PlayerType,
                        Player2Type  = (byte)gameState.Player2.PlayerType,
                        Status       = (byte)gameState.Status,
                        WinMargin    = gameState.WinMargin
                    };
                    UpdateMoves(ctx, newGame, newMoveHistory);

                    ctx.Games.Add(newGame);
                }
                else
                {
                    // update game
                    g.BlackStones  = gameState.BlackPositions;
                    g.BlacksTurn   = gameState.WhoseTurn == GoColor.Black;
                    g.GameId       = gameId;
                    g.Size         = gameState.Size;
                    g.WhiteStones  = gameState.WhitePositions;
                    g.LastMove     = DateTimeOffset.Now;
                    g.Player1Level = (byte)gameState.Player1.Level;
                    g.Player2Level = (byte)gameState.Player2.Level;
                    g.Player1Name  = gameState.Player1.Name;
                    g.Player2Name  = gameState.Player2.Name;
                    g.Player1Score = gameState.Player1.Score;
                    g.Player2Score = gameState.Player2.Score;
                    g.Player1Type  = (byte)gameState.Player1.PlayerType;
                    g.Player2Type  = (byte)gameState.Player2.PlayerType;
                    g.Status       = (byte)gameState.Status;
                    g.WinMargin    = gameState.WinMargin;

                    UpdateMoves(ctx, g, newMoveHistory);
                }

                ctx.SaveChanges();
            }
        }
Пример #18
0
        public void Undo()
        {
            try
            {
                // Note that resignation is stored as a single move, but fuego.exe doesn't know about resignations so
                // no need to send an undo command to the engine.

                int undo = 0;

                if (State.Status == GoGameStatus.BlackWonDueToResignation)
                {
                    var humanColor = State.Player1.PlayerType == PlayerType.Human ? GoColor.Black : GoColor.White;
                    undo = humanColor == GoColor.Black ? 2 : 1;

                    if (State.GoMoveHistory.Count > 1 && State.GoMoveHistory[State.GoMoveHistory.Count - 2].Move.Color == humanColor)
                    {
                        WriteCommand("gg-undo", "1");
                        ReadResponse();
                    }
                }
                else if (State.Status == GoGameStatus.WhiteWonDueToResignation)
                {
                    var humanColor = State.Player1.PlayerType == PlayerType.Human ? GoColor.Black : GoColor.White;
                    undo = humanColor == GoColor.White ? 2 : 1;

                    if (State.GoMoveHistory.Count > 1 && State.GoMoveHistory[State.GoMoveHistory.Count - 2].Move.Color == humanColor)
                    {
                        WriteCommand("gg-undo", "1");
                        ReadResponse();
                    }
                }
                else
                {
                    var his   = State.GoMoveHistory;
                    var count = his.Count;

                    var humanColor = State.Player1.PlayerType == PlayerType.Human ? GoColor.Black : GoColor.White;

                    // Reverse to before most recent human move.
                    for (int i = count - 1; i >= 0; i--)
                    {
                        if (his[i].Move.Color == humanColor)
                        {
                            undo = count - i;
                            break;
                        }
                    }

                    if (undo == 0)
                    {
                        throw new Exception("Can't undo because there are no human moves yet.");
                    }

                    WriteCommand("gg-undo", undo.ToString(CultureInfo.InvariantCulture));
                    ReadResponse();
                }

                UndoMovesInStateAndDatabase(undo);
            }
            catch (Exception)
            {
                // Setting State to null forces it to be loaded from database when the next user request
                // is made to the service.
                State = null;
                throw;
            }
        }