public void DoAfterUpdatingTheState(bool stateUpdateCompletedSuccessfully) { // Find any mobile states unaccounted for, and remove them: for (int i = 0; i < AllMobileStatesAccountedFor.Length; i++) { // Ignore if accounted for: if (AllMobileStatesAccountedFor[i]) { continue; } // Ignore if not active: MobileState mobiState = NewGameState.GetMobileState(i); if (!mobiState.IsActive) { continue; } Element element = Game.Current.Elements[i]; mobiState = mobiState.Kill(); NewGameState.SetMobileState(i, ref mobiState); LogDebugMessage("Deactivating {0} {1} @{2}, which was not accounted for", element.ElementType, i, mobiState.Pos); } // Record the actual actions taken by the players: Turn prevTurn = Game.Current.CurrentTurn.PreviousTurn; if (prevTurn != null) { prevTurn.TankActionsTakenAfterPreviousTurn = TankActionsTaken; } Game.Current.CurrentTurn.GameState = NewGameState; LogActionsTaken(); LogDebugMessage("New game state: {0}", NewGameState); DebugHelper.WriteLine(); CheckGameState(); // Clear the variables, so the callback can be used again without risk of debris from the previous time: TankActionsTaken = null; PrevGameState = null; NewGameState = null; }
public void UpdateTankState(int unitId, TankAction tankAction, Point newPos, Direction newDir, bool isActive) { bool tankFound = false; for (int t = 0; t < Constants.TANK_COUNT; t++) { Tank tank = Game.Current.Elements[t] as Tank; if (tank.Id == unitId) { MobileState newMobileState = new MobileState(newPos, newDir, isActive); NewGameState.SetMobileState(t, ref newMobileState); TankActionsTaken[tank.Index] = tankAction; tankFound = true; AllMobileStatesAccountedFor[tank.Index] = true; break; } } /* TODO: Else find a likely matching tank in the previous game state based on position and direction: */ #if DEBUG if (!tankFound) { LogDebugMessage("ERROR! No existing tank could be found with id {0} at position ({1}, {2})", unitId, newPos.X, newPos.Y); #if THROW_HARNESS_ERRORS throw new InvalidOperationException( String.Format( "No existing tank could be found with id {0} at position ({1}, {2})", unitId, newPos.X, newPos.Y) ); #endif } #endif }
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); } } } }
public void UpdateBulletState(int bulletId, Point bulletPos, Direction bulletDir, bool isActive) { MobileState newMobileState = new MobileState(bulletPos, bulletDir, isActive); // Look for the bullet: int i = 0; bool bulletFound = false; for (int b = Constants.MIN_BULLET_INDEX; b <= Constants.MAX_BULLET_INDEX; b++) { if (Game.Current.CurrentTurn.BulletIds[i] == bulletId) { NewGameState.SetMobileState(b, ref newMobileState); bulletFound = true; AllMobileStatesAccountedFor[b] = true; break; } i++; } if (!bulletFound) { /* Find a tank which has the same direction as the bullet, * and where the bullet is in the correct position for a newly fired bullet: */ for (int t = 0; t < Constants.TANK_COUNT; t++) { MobileState tankState = NewGameState.GetMobileState(t); if (tankState.Dir == bulletDir) { Point tankFiringPoint = tankState.GetTankFiringPoint(); if (tankFiringPoint == bulletPos) { Tank tank = Game.Current.Elements[t] as Tank; int bulletIndex = tank.Bullet.Index; NewGameState.SetMobileState(bulletIndex, ref newMobileState); Game.Current.CurrentTurn.BulletIds[t] = bulletId; AllMobileStatesAccountedFor[bulletIndex] = true; bulletFound = true; break; } } } /* TODO: Find a likely matching bullet in the previous game state based on position and direction: * if (!bulletFound) * { * // Find a bullet which has the same direction and is two spaces before this bullet: * * } */ #if DEBUG if (!bulletFound) { LogDebugMessage("ERROR! The {0}bullet with id {1} at {2} could not be matched to a tank", isActive ? String.Empty : "dead ", bulletId, bulletPos); #if THROW_HARNESS_ERRORS throw new InvalidOperationException( string.Format( "The {0}bullet with id {1} at {2} could not be matched to a tank", isActive ? String.Empty : "dead ", bulletId, bulletPos ) ); #endif } #endif } }