コード例 #1
0
        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);
        }
コード例 #2
0
        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);
        }
コード例 #3
0
        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);
        }
コード例 #4
0
        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);
             */
        }
コード例 #5
0
        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;
             */
        }
コード例 #6
0
        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);
        }
コード例 #7
0
        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();
                }
            }
        }