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); }
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); }
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); }
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; } } }
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); } }
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); } }