Ejemplo n.º 1
0
        public WaitTurnInfo WaitNextTurn(int playerId, int refTurn, ClientCode clientCode, DateTime callTimestamp)
        {
            while (refTurn == 0)
            {
                // Entering the game
                GameInfo gameInfo = WaitGameStart(playerId, clientCode);
                if (gameInfo == null)
                {
                    // Not yet in a game
                    return(new WaitTurnInfo());
                }
                else if (gameInfo.State == GameState.Finish)
                {
                    // In a finished game
                    LeaveGame(playerId, clientCode);
                    continue;
                }
                // In a running game -- fall through
                break;
            }
            GameModel    game = accessLiveGame(playerId, clientCode);
            WaitTurnInfo wi   = game.CompletePlayerTurn(playerId, refTurn, callTimestamp);

            if (wi.TurnComplete == false)
            {
                game.WaitNextTurn(wi);
            }

            if (wi.GameFinished)
            {
                Thread.Sleep(Settings.LastWaitNextTurnSleepMillis);
            }

            return(wi);
        }
Ejemplo n.º 2
0
        private bool PlayerExitTest(WaitTurnInfo wi)
        {
            int p = wi.PlayerIndex;

            if (!_playerStates[p].IsActive)
            {
                wi.TurnComplete    = true;
                wi.GameFinished    = true;
                wi.FinishCondition = _playerStates[p].Condition;
                wi.FinishComment   = _playerStates[p].Comment;
                return(true);
            }
            return(false);
        }
Ejemplo n.º 3
0
        public WaitTurnInfo WaitNextTurn(int playerId, int refTurn, ClientCode clientCode)
        {
            Game         game = accessLiveGame(playerId, clientCode);
            WaitTurnInfo wi   = game.CompletePlayerTurn(playerId, refTurn);

            if (!wi.TurnComplete)
            {
                game.WaitNextTurn(wi);
            }
            if (wi.GameFinished)
            {
                Thread.Sleep(Settings.LastWaitNextTurnSleepMillis);
            }
            return(wi);
        }
Ejemplo n.º 4
0
        public void WaitNextTurn(WaitTurnInfo wi)
        {
            lock (_liveLock)
            {
                StartNextTurnMaybe();

                if (PlayerExitTest(wi))
                {
                    return;
                }
                if (_gameTurnStarted > wi.Turn)
                {
                    wi.TurnComplete = true;
                    return;
                }

                CheckRunState();
                DateTime dtNow = DateTime.Now;
                if (_turnEnd > dtNow)
                {
                    int waitMillis = (int)(_turnEnd - dtNow).TotalMilliseconds;
                    if (waitMillis > Settings.NextTurnPollTimeoutMillis)
                    {
                        waitMillis = Settings.NextTurnPollTimeoutMillis;
                    }
                    else if (waitMillis < Settings.MinimumSleepMillis)
                    {
                        waitMillis = Settings.MinimumSleepMillis;
                    }
                    Monitor.Wait(_liveLock, waitMillis);
                }
                else
                {
                    Monitor.Wait(_liveLock, Settings.NextTurnPollTimeoutMillis);
                }

                StartNextTurnMaybe();

                if (PlayerExitTest(wi))
                {
                    return;
                }
                if (_gameTurnStarted > wi.Turn)
                {
                    wi.TurnComplete = true;
                }
            }
        }
Ejemplo n.º 5
0
        public WaitTurnInfo CompletePlayerTurn(int playerId, int refTurn, DateTime callTimestamp)
        {
            lock (_liveLock)
            {
                WaitTurnInfo wi     = new WaitTurnInfo();
                int          player = FindPlayer(playerId);
                if (_playerStates[player].IsPresent == false)
                {
                    throw new ApplicationException("Player was dropped from the game");
                }
                wi.PlayerIndex = player;

                if (refTurn == 0)
                {
                    // Crash recovery logic
                    if (_playerStates[player].TurnCompleted < _gameTurnStarted)
                    {
                        wi.TurnComplete = true;
                        return(wi);
                    }
                    else
                    {
                        wi.Turn = _playerStates[player].TurnCompleted;
                        return(wi);
                    }
                }

                if (_playerStates[player].TurnCompleted == refTurn)
                {
                    wi.Turn = refTurn;
                    return(wi);
                }

                if (PlayerExitTest(wi))
                {
                    return(wi);
                }

                if (_playerStates[player].TurnCompleted != refTurn - 1)
                {
                    throw new ApplicationException($"Player is confusing turns: completed={_playerStates[player].TurnCompleted} refTurn={refTurn}");
                }
                if (refTurn > _gameTurnStarted)
                {
                    throw new ApplicationException($"Player skipping ahead of game progress: gameTurnStarted={_gameTurnStarted} refTurn={refTurn}");
                }

                _playerStates[player].TurnCompleted = _gameTurnStarted;
                _playerStates[player].TurnFinTime   = callTimestamp;

                #region Penalty logic
                int totalMsec = (int)(_playerStates[player].TurnFinTime - _turnStart).TotalMilliseconds;
                if (totalMsec > Settings.TurnResponseThresholdMillis)
                {
                    _playerStates[player].PenaltyPoints += (totalMsec - Settings.TurnResponseThresholdMillis) / 100;
                    // TODO OvertimeTurn stuff is of questionable value to us. Ditto Penalty Threshold, but the latter is at least understandable.
                    _playerStates[player].OvertimeTurnMsec = totalMsec;
                    _playerStates[player].OvertimeTurnTurn = _playerStates[player].TurnCompleted;
                    if (_playerStates[player].PenaltyPoints > Settings.PenaltyPointsThreshold && _playerStates[player].PenaltyThresholdReachedTurn < 0)
                    {
                        _playerStates[player].PenaltyThresholdReachedTurn = _playerStates[player].TurnCompleted;
                    }
                }
                else
                {
                    _playerStates[player].BonusPoints += (Settings.TurnResponseThresholdMillis - totalMsec) / 100;
                }
                #endregion

                _proto.LogPlayerTurnComplete(_playerStates[player], _turnStart);

                CompleteTurn();

                if (PlayerExitTest(wi))
                {
                    return(wi);
                }

                wi.Turn = refTurn;
                return(wi);
            }
        }
Ejemplo n.º 6
0
 public WaitTurnInfo CompletePlayerTurn(int playerId, int refTurn)
 {
     lock (_liveLock)
     {
         WaitTurnInfo wi = new WaitTurnInfo();
         int          p  = findPlayer(playerId);
         if (!_pstates[p].IsPresent)
         {
             throw new ApplicationException("Player was dropped from the game");
         }
         wi.PlayerIndex = p;
         if (refTurn == 0)
         {
             // Crash recovery logic
             if (_pstates[p].TurnCompleted < _gameTurnStarted)
             {
                 wi.TurnComplete = true;
                 return(wi);
             }
             else
             {
                 wi.Turn = _pstates[p].TurnCompleted;
                 return(wi);
             }
         }
         if (_pstates[p].TurnCompleted == refTurn)
         {
             wi.Turn = refTurn;
             return(wi);
         }
         if (playerExitTest(wi))
         {
             return(wi);
         }
         if (_pstates[p].TurnCompleted != refTurn - 1)
         {
             throw new ApplicationException(string.Format("Player is confusing turns: completed={0} refTurn={1}", _pstates[p].TurnCompleted, refTurn));
         }
         if (refTurn > _gameTurnStarted)
         {
             throw new ApplicationException(string.Format("Player skipping ahead of game progress: gameTurnStarted={0} refTurn={1}", _gameTurnStarted, refTurn));
         }
         _pstates[p].TurnCompleted = _gameTurnStarted;
         _pstates[p].TurnFinTime   = DateTime.Now;
         int totalMsec = (int)(_pstates[p].TurnFinTime - _turnStart).TotalMilliseconds;
         if (totalMsec > 1000)
         {
             _pstates[p].PenaltyPoints += (totalMsec - 1000) / 100;
         }
         else
         {
             _pstates[p].BonusPoints += (1000 - totalMsec) / 100;
         }
         if (totalMsec > Settings.TurnResponseThresholdMsec)
         {
             _pstates[p].OvertimeTurnMsec = totalMsec;
             _pstates[p].OvertimeTurnTurn = _pstates[p].TurnCompleted;
         }
         if (_pstates[p].PenaltyPoints > Settings.PenaltyPointsThreshold && _pstates[p].PenaltyThresholdReachedTurn < 0)
         {
             _pstates[p].PenaltyThresholdReachedTurn = _pstates[p].TurnCompleted;
         }
         _proto.LogPlayerTurnComplete(_pstates[p], _turnStart);
         completeTurn();
         if (playerExitTest(wi))
         {
             return(wi);
         }
         wi.Turn = refTurn;
         return(wi);
     }
 }