public DirectionalMatrix <DistanceCalculation> GetIncomingDistanceMatrixForBase(int playerIndex) { if (incomingDistanceMatricesByBase == null) { incomingDistanceMatricesByBase = new DirectionalMatrix <DistanceCalculation> [Constants.PLAYERS_PER_GAME]; } DirectionalMatrix <DistanceCalculation> incomingDistanceMatrix = incomingDistanceMatricesByBase[playerIndex]; if (incomingDistanceMatrix == null) { Base @base = Game.Current.Players[playerIndex].Base; Base @ownBase = Game.Current.Players[1 - playerIndex].Base; TurnCalculationCache turnCalcCache = TurnCalculationCache; Cell baseCell = turnCalcCache.CellMatrix[@base.Pos]; AttackTargetDistanceCalculator attackCalculator = new AttackTargetDistanceCalculator( ElementType.BASE, FiringLinesForPointsMatrix, this, turnCalcCache); // Don't move over your own base: TankLocation tankLoc = turnCalcCache.TankLocationMatrix[@ownBase.Pos]; attackCalculator.TabooAreas = new Rectangle[] { tankLoc.TankHalo }; incomingDistanceMatrix = attackCalculator.CalculateMatrixOfShortestDistancesToTargetCell(baseCell); incomingDistanceMatricesByBase[playerIndex] = incomingDistanceMatrix; } return(incomingDistanceMatrix); }
public DirectionalMatrix <DistanceCalculation> GetIncomingDistanceMatrixForBaseWithFinalDirectionOfMovement( int playerIndex, Direction finalDirectionOfMovement) { if (incomingDistanceMatricesByBaseAndFinalDirectionOfMovement == null) { incomingDistanceMatricesByBaseAndFinalDirectionOfMovement = new DirectionalMatrix <DistanceCalculation> [ Constants.PLAYERS_PER_GAME, Constants.RELEVANT_DIRECTION_COUNT]; } DirectionalMatrix <DistanceCalculation> incomingDistanceMatrix = incomingDistanceMatricesByBaseAndFinalDirectionOfMovement[playerIndex, (int)finalDirectionOfMovement]; if (incomingDistanceMatrix == null) { Base @base = Game.Current.Players[playerIndex].Base; TurnCalculationCache turnCalcCache = TurnCalculationCache; Cell baseCell = turnCalcCache.CellMatrix[@base.Pos]; AttackTargetDistanceCalculator attackCalculator = new AttackTargetDistanceCalculator( ElementType.BASE, FiringLinesForPointsMatrix, this, turnCalcCache); attackCalculator.MovementDirections = new Direction[] { finalDirectionOfMovement }; incomingDistanceMatrix = attackCalculator.CalculateMatrixOfShortestDistancesToTargetCell(baseCell); incomingDistanceMatricesByBaseAndFinalDirectionOfMovement[playerIndex, (int)finalDirectionOfMovement] = incomingDistanceMatrix; } return(incomingDistanceMatrix); }
public DirectionalMatrix <DistanceCalculation> GetIncomingAttackMatrixForTankByTankIndex(int tankIndex) { if (incomingAttackMatrixByTankIndex == null) { incomingAttackMatrixByTankIndex = new DirectionalMatrix <DistanceCalculation> [Constants.TANK_COUNT]; } DirectionalMatrix <DistanceCalculation> incomingAttackMatrix = incomingAttackMatrixByTankIndex[tankIndex]; if (incomingAttackMatrix == null) { MobileState tankState = GameState.GetMobileState(tankIndex); if (!tankState.IsActive) { return(null); } TurnCalculationCache turnCalcCache = TurnCalculationCache; Cell tankCell = turnCalcCache.CellMatrix[tankState.Pos]; AttackTargetDistanceCalculator attackCalculator = new AttackTargetDistanceCalculator( ElementType.TANK, FiringLinesForTanksMatrix, this, turnCalcCache); incomingAttackMatrix = attackCalculator.CalculateMatrixOfShortestDistancesToTargetCell(tankCell); incomingAttackMatrixByTankIndex[tankIndex] = incomingAttackMatrix; } return(incomingAttackMatrix); }
public TankAction[] GetTankActionsFromTankToAttackTankAtPointAlongDirectionOfMovement( int playerIndex, int tankNumber, Point targetPoint, Direction finalMovementDir, EdgeOffset[] edgeOffsets, bool keepMovingCloserOnFiringLastBullet) { Tank tank = Game.Current.Players[playerIndex].Tanks[tankNumber]; MobileState tankState = GameState.GetMobileState(tank.Index); TurnCalculationCache turnCalcCache = Game.Current.Turns[GameState.Tick].CalculationCache; Cell targetCell = turnCalcCache.CellMatrix[targetPoint]; FiringLineMatrix firingLinesForTanksMatrix = GameState.CalculationCache.FiringLinesForTanksMatrix; AttackTargetDistanceCalculator attackCalculator = new AttackTargetDistanceCalculator( ElementType.TANK, firingLinesForTanksMatrix, GameState.CalculationCache, turnCalcCache); attackCalculator.MovementDirections = new Direction[] { finalMovementDir }; attackCalculator.EdgeOffsets = edgeOffsets; CombinedMovementAndFiringDistanceCalculation combinedDistCalc = attackCalculator.GetShortestAttackDistanceFromCurrentTankPosition(tank.Index, targetCell); return(PathCalculator.GetTanksActionsOnOutgoingShortestAttackPathFromCurrentTankPosition( tank.Index, combinedDistCalc, GameState.CalculationCache, keepMovingCloserOnFiringLastBullet)); /* was: * DirectionalMatrix<DistanceCalculation> incomingDistanceMatrix * = attackCalculator.CalculateMatrixOfShortestDistancesToTargetCell(targetCell); * DistanceCalculation distanceCalc = incomingDistanceMatrix[tankState]; * return PathCalculator.GetTankActionsOnIncomingShortestPath(incomingDistanceMatrix, tankState.Dir, tankState.Pos.X, tankState.Pos.Y, * targetPoint.X, targetPoint.Y, firingLinesForTanksMatrix, keepMovingCloserOnFiringLastBullet); */ }
public int GetAttackDistanceFromTankToTankAtPointAlongDirectionOfMovement( int playerIndex, int tankNumber, Point targetPoint, Direction finalMovementDir, EdgeOffset[] edgeOffsets) { Tank tank = Game.Current.Players[playerIndex].Tanks[tankNumber]; MobileState tankState = GameState.GetMobileState(tank.Index); TurnCalculationCache turnCalcCache = Game.Current.Turns[GameState.Tick].CalculationCache; Cell targetCell = turnCalcCache.CellMatrix[targetPoint]; FiringLineMatrix firingLinesForTanksMatrix = GameState.CalculationCache.FiringLinesForTanksMatrix; AttackTargetDistanceCalculator attackCalculator = new AttackTargetDistanceCalculator( ElementType.TANK, firingLinesForTanksMatrix, GameState.CalculationCache, turnCalcCache); attackCalculator.MovementDirections = new Direction[] { finalMovementDir }; attackCalculator.EdgeOffsets = edgeOffsets; CombinedMovementAndFiringDistanceCalculation combinedDistCalc = attackCalculator.GetShortestAttackDistanceFromCurrentTankPosition(tank.Index, targetCell); if (combinedDistCalc == null) { return(Constants.UNREACHABLE_DISTANCE); } else { return(combinedDistCalc.TicksTillTargetShot); } /* was: * DirectionalMatrix<DistanceCalculation> incomingDistanceMatrix * = attackCalculator.CalculateMatrixOfShortestDistancesToTargetCell(targetCell); * DistanceCalculation distanceCalc = incomingDistanceMatrix[tankState]; * return distanceCalc.Distance; */ }
public int GetAttackDistanceFromTankToHypotheticalTankAtPoint( int playerIndex, int tankNumber, Point targetTankPoint, EdgeOffset[] edgeOffsets) { Tank tank = Game.Current.Players[playerIndex].Tanks[tankNumber]; MobileState tankState = GameState.GetMobileState(tank.Index); TurnCalculationCache turnCalcCache = Game.Current.Turns[GameState.Tick].CalculationCache; Cell targetCell = turnCalcCache.CellMatrix[targetTankPoint]; FiringLineMatrix firingLinesForTanksMatrix = GameState.CalculationCache.FiringLinesForTanksMatrix; AttackTargetDistanceCalculator attackCalculator = new AttackTargetDistanceCalculator( ElementType.TANK, firingLinesForTanksMatrix, GameState.CalculationCache, turnCalcCache); attackCalculator.MovementDirections = BoardHelper.AllRealDirections; attackCalculator.EdgeOffsets = edgeOffsets; CombinedMovementAndFiringDistanceCalculation combinedDistCalc = attackCalculator.GetShortestAttackDistanceFromCurrentTankPosition(tank.Index, targetCell); return(combinedDistCalc.TicksTillTargetShot); }
private static void CalculateBulletThreats(BulletCalculation bulletCalc, GameState gameState, Player you) { TurnCalculationCache turnCalcCache = Game.Current.Turns[gameState.Tick].CalculationCache; Tank[] tanks; if (you != null) { tanks = you.Tanks; } else { tanks = Game.Current.Tanks; } foreach (Tank tank in tanks) { MobileState tankState = gameState.GetMobileState(tank.Index); foreach (BulletPathCalculation bulletPathCalc in bulletCalc.BulletPaths) { List <BulletThreat> bulletThreats = new List <BulletThreat>(); foreach (BulletPathPoint bulletPathPoint in bulletPathCalc.BulletPathPoints) { if (bulletPathPoint.DangerArea.ContainsPoint(tankState.Pos)) { BulletThreat bulletThreat = new BulletThreat(bulletPathCalc) { FiringTank = bulletPathCalc.Bullet.Tank, TankThreatened = tank }; bulletThreats.Add(bulletThreat); // Take the bullet on: FiringLineMatrix firingLineMatrix = gameState.CalculationCache.FiringLinesForPointsMatrix; AttackTargetDistanceCalculator attackCalculator = new AttackTargetDistanceCalculator( ElementType.BULLET, firingLineMatrix, gameState.CalculationCache, turnCalcCache); attackCalculator.MovementDirections = new Direction[] { bulletPathCalc.BulletState.Dir.GetOpposite() }; Cell bulletCell = turnCalcCache.CellMatrix[bulletPathCalc.BulletState.Pos]; DirectionalMatrix <DistanceCalculation> distanceCalcs = attackCalculator.CalculateMatrixOfShortestDistancesToTargetCell(bulletCell); DistanceCalculation distanceCalc = distanceCalcs[tankState]; if (distanceCalc.Distance <= bulletPathPoint.TicksToEscape) { Node[] nodes = PathCalculator.GetIncomingNodesOnShortestPath( distanceCalcs, tankState.Dir, tankState.Pos.X, tankState.Pos.Y, bulletPathCalc.BulletState.Pos.X, bulletPathCalc.BulletState.Pos.Y, firingLineMatrix, keepMovingCloserOnFiringLastBullet: true); bulletThreat.NodePathToTakeOnBullet = nodes; TankAction[] tankActions = PathCalculator.GetTankActionsOnIncomingShortestPath(distanceCalcs, tankState.Dir, tankState.Pos.X, tankState.Pos.Y, bulletPathCalc.BulletState.Pos.X, bulletPathCalc.BulletState.Pos.Y, firingLineMatrix, keepMovingCloserOnFiringLastBullet: true); bulletThreat.TankActionsToTakeOnBullet = tankActions; } // Move off his path in one direction: Point tankOffset = tankState.Pos - bulletPathCalc.BulletState.Pos; Point bulletMovementOffset = bulletPathCalc.BulletState.Dir.GetOffset(); Point newTankPoint1; Point newTankPoint2; Direction newTankDir1; Direction newTankDir2; if (bulletPathCalc.BulletState.Dir.ToAxis() == Axis.Horizontal) { newTankPoint1 = new Point( (short)tankState.Pos.X, (short)(bulletPathCalc.BulletState.Pos.Y - Constants.TANK_OUTER_EDGE_OFFSET)); newTankDir1 = Direction.UP; newTankPoint2 = new Point( (short)tankState.Pos.X, (short)(bulletPathCalc.BulletState.Pos.Y + Constants.TANK_OUTER_EDGE_OFFSET)); newTankDir2 = Direction.DOWN; } else { newTankPoint1 = new Point( (short)(bulletPathCalc.BulletState.Pos.X - Constants.TANK_OUTER_EDGE_OFFSET), (short)tankState.Pos.Y); newTankDir1 = Direction.LEFT; newTankPoint2 = new Point( (short)(bulletPathCalc.BulletState.Pos.X + Constants.TANK_OUTER_EDGE_OFFSET), (short)tankState.Pos.Y); newTankDir2 = Direction.RIGHT; } DirectionalMatrix <DistanceCalculation> tankDistanceCalcs = gameState.CalculationCache.GetDistanceMatrixFromTankByTankIndex(tank.Index); distanceCalc = tankDistanceCalcs[newTankDir1, newTankPoint1.X, newTankPoint1.Y]; if (distanceCalc.Distance <= bulletPathPoint.TicksToEscape) { Node[] shortestPathsIn1Direction = PathCalculator.GetOutgoingNodesOnShortestPath(tankDistanceCalcs, newTankDir1, newTankPoint1.X, newTankPoint1.Y); bulletThreat.LateralMoveInOneDirection = shortestPathsIn1Direction; TankAction[] tankActionsIn1Direction = PathCalculator.GetTankActionsOnOutgoingShortestPath(tankDistanceCalcs, newTankDir1, newTankPoint1.X, newTankPoint1.Y); bulletThreat.TankActionsForLateralMoveInOneDirection = tankActionsIn1Direction; } distanceCalc = tankDistanceCalcs[newTankDir2, newTankPoint2.X, newTankPoint2.Y]; if (distanceCalc.Distance <= bulletPathPoint.TicksToEscape) { Node[] shortestPathsInOtherDirection = PathCalculator.GetOutgoingNodesOnShortestPath(tankDistanceCalcs, newTankDir2, newTankPoint2.X, newTankPoint2.Y); bulletThreat.LateralMoveInOtherDirection = shortestPathsInOtherDirection; TankAction[] tankActionsInOtherDirection = PathCalculator.GetTankActionsOnOutgoingShortestPath(tankDistanceCalcs, newTankDir2, newTankPoint2.X, newTankPoint2.Y); bulletThreat.TankActionsForLateralMoveInOtherDirection = tankActionsInOtherDirection; } } } bulletPathCalc.BulletThreats = bulletThreats.ToArray(); } } }