public void UpdateTankActionSituation(TankSituation tankSituation, TankAction tankAction, GameState newGameState) { TankAction[] tankActions = new TankAction[] { TankAction.NONE, TankAction.NONE, TankAction.NONE, TankAction.NONE }; tankActions[tankSituation.Tank.Index] = tankAction; List <Point> wallsRemoved = new List <Point>(); MutableGameStateEngine.ApplyAllActions(newGameState as MutableGameState, tankActions, wallsRemoved); bool isAdjacentWallRemoved = false; if (!tankSituation.TankState.IsActive) { IsValid = (TankAction == TankAction.NONE); return; } else { IsValid = true; } if (tankAction == TankAction.FIRE) { Direction movementDir = tankSituation.TankState.Dir; TankLocation tankLoc = Game.Current.Turns[newGameState.Tick].CalculationCache.TankLocationMatrix[tankSituation.TankState.Pos]; Point adjacentWallPoint = tankLoc.OutsideEdgesByDirection[(int)movementDir].CentreCell.Position; isAdjacentWallRemoved = wallsRemoved.Any( wallPoint => wallPoint == adjacentWallPoint ); } NewGameState = newGameState; WallsRemoved = wallsRemoved.ToArray(); IsAdjacentWallRemoved = isAdjacentWallRemoved; NewTankState = NewGameState.GetMobileState(TankSituation.Tank.Index); }
public override void ApplyActions(TankAction[] tankActions) { MutableGameStateEngine.ApplyAllActions(this, tankActions); }
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); } } } }
protected override void ChooseMoves() { GameState currGameState = Game.Current.CurrentTurn.GameState; TankAction[] tankActionsForLiveTank = new TankAction[] { TankAction.UP, TankAction.DOWN, TankAction.FIRE, TankAction.LEFT, TankAction.RIGHT, TankAction.NONE }; TankAction[] tankActionsForDeadTank = new TankAction[] { TankAction.NONE }; TankAction[][] tankActionsPerTank = new TankAction[Constants.TANK_COUNT][]; foreach (Tank tank in You.Tanks) { MobileState mobileState = currGameState.GetMobileState(tank.Index); if (mobileState.IsActive) { // Check if needing to avoid a bullet or shoot a bullet on the path to the base or the tank itself // If so, limit the actions to only those that allow avoiding the bullet tankActionsPerTank[tank.Number] = tankActionsForLiveTank; } else { tankActionsPerTank[tank.Number] = tankActionsForDeadTank; } } double[,] valueEstimates = new double[tankActionsPerTank[0].Length, tankActionsPerTank[1].Length]; GameStateValueEstimator valueEstimator = new GameStateValueEstimator(); valueEstimator.Player = You; Tank tank0 = You.Tanks[0]; Tank tank1 = You.Tanks[1]; double bestValue = double.NegativeInfinity; TankAction[] bestTankActions = null; for (int ta0 = 0; ta0 < tankActionsPerTank[0].Length; ta0++) { TankAction tankAction0 = tankActionsPerTank[0][ta0]; for (int ta1 = 0; ta1 < Constants.TANK_COUNT; ta1++) { TankAction tankAction1 = tankActionsPerTank[1][ta1]; GameState gameStateClone = currGameState.Clone(); gameStateClone.Tick++; TankAction[] tankActions = new TankAction[Constants.TANK_COUNT]; tankActions[tank0.Index] = tankAction0; tankActions[tank1.Index] = tankAction1; MutableGameStateEngine.ApplyAllActions(gameStateClone as MutableGameState, tankActions); valueEstimator.GameState = gameStateClone; double value = valueEstimator.Evaluate(); if (value > bestValue) { bestValue = value; bestTankActions = tankActions; } } } TankActionSet actionSet = new TankActionSet(YourPlayerIndex, currGameState.Tick); if (bestTankActions != null) { actionSet.Actions[tank0.Number] = bestTankActions[tank0.Number]; actionSet.Actions[tank1.Number] = bestTankActions[tank1.Number]; } Coordinator.SetBestMoveSoFar(actionSet); }