public void DoBeforeUpdatingTheState( int currentTick, DateTime nextTickTimeOnServer, TimeSpan timeUntilNextTick, DateTime localTimeBeforeGetStatusCall, DateTime localTimeAfterGetStatusCall) { AllMobileStatesAccountedFor = new bool[Constants.MOBILE_ELEMENT_COUNT]; TankActionsTaken = new TankAction[Constants.TANK_COUNT]; for (int i = 0; i < TankActionsTaken.Length; i++) { TankActionsTaken[i] = TankAction.NONE; } PrevGameState = Game.Current.CurrentTurn.GameState; NewGameState = PrevGameState.Clone(); NewGameState.Tick = currentTick; NewGameState.Outcome = Outcome.InProgress; // TODO: Ideally the current turn should be updated as the very last step, // to prevent race conditions in scenarios where CurrentTurn is accessed // from another thread before the game state is fully updated: UpdateCurrentTurn(currentTick, nextTickTimeOnServer, timeUntilNextTick, localTimeBeforeGetStatusCall, localTimeAfterGetStatusCall); }
private void CheckGameState() { GameState calculatedGameState = PrevGameState.Clone(); calculatedGameState.Tick = Game.Current.CurrentTurn.Tick; if (calculatedGameState is MutableGameState) { MutableGameStateEngine.ApplyAllActions((MutableGameState)calculatedGameState, TankActionsTaken); } else if (calculatedGameState is ImmutableGameState) { ImmutableGameStateEngine.ApplyActions((ImmutableGameState)calculatedGameState, TankActionsTaken); } else { throw new InvalidOperationException( String.Format( "The calculated game state on turn {0} can't be cast to a known game state type", Game.Current.CurrentTurn.Tick ) ); } calculatedGameState.Outcome |= Outcome.InProgress; Game.Current.CurrentTurn.GameStateCalculatedByGameStateEngine = calculatedGameState; string reasonDifferent; if (!GameState.AreGameStatesEquivalent(NewGameState, calculatedGameState, out reasonDifferent)) { LogDebugMessage( "ERROR! The calculated game state does not match the new harness game state. \r\nReason: {0}", reasonDifferent); #if THROW_HARNESS_ERRORS throw new ApplicationException( String.Format( "The calculated game state does not match the new harness game state. \r\nReason: {0}", reasonDifferent ) ); #endif // Workaround for a bug in the Entelect test harness on tick 1. // Copy calculated game state into retrieved game state: if (NewGameState.Tick == 1) { BitMatrix destWalls = NewGameState.Walls; BitMatrix srcWalls = calculatedGameState.Walls; // Copy walls from calculated game state: for (int x = destWalls.TopLeft.X; x <= destWalls.BottomRight.X; x++) { for (int y = destWalls.TopLeft.Y; y <= destWalls.BottomRight.Y; y++) { destWalls[x, y] = srcWalls[x, y]; } } // Copy mobile states: for (int i = 0; i < Constants.MOBILE_ELEMENT_COUNT; i++) { MobileState calculatedMobileState = calculatedGameState.GetMobileState(i); NewGameState.SetMobileState(i, ref calculatedMobileState); } } } }