Exemplo n.º 1
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);
             */
        }
Exemplo n.º 2
0
        public void AttackClosestEnemyTankToOwnBase(GameState currGameState, Tank killerTank, Tank targetTank,
                                                    TankActionSet actionSet, bool[] moveChosenByTankNumber)
        {
            MobileState killerTankState = currGameState.GetMobileState(killerTank.Index);

            if (killerTankState.IsActive)
            {
                MobileState enemyTankState = currGameState.GetMobileState(targetTank.Index);
                if (enemyTankState.IsActive)
                {
                    DirectionalMatrix <DistanceCalculation> attackMatrix
                        = currGameState.CalculationCache.GetIncomingAttackMatrixForTankByTankIndex(targetTank.Index);
                    if (attackMatrix != null)
                    {
                        DistanceCalculation attackCalculation = attackMatrix[killerTankState.Dir, killerTankState.Pos];
                        TankAction[]        tankActions
                            = PathCalculator.GetTankActionsOnIncomingShortestPath(attackMatrix, killerTankState, enemyTankState.Pos,
                                                                                  currGameState.CalculationCache.FiringLinesForTanksMatrix, keepMovingCloserOnFiringLastBullet: true);
                        if (tankActions.Length > 0)
                        {
                            actionSet.Actions[killerTank.Number]      = tankActions[0];
                            moveChosenByTankNumber[killerTank.Number] = true;
                        }
                    }
                }
            }
        }
Exemplo n.º 3
0
        public DirectionalMatrix <DistanceCalculation> GetCustomDistanceMatrixFromTank(
            int playerIndex, int tankNumber, int ticksWithoutFiring, Rectangle restrictedBoardArea)
        {
            Tank tank = Game.Current.Players[playerIndex].Tanks[tankNumber];
            TurnCalculationCache turnCalcCache = Game.Current.Turns[GameState.Tick].CalculationCache;

            // Don't ride over your own base!
            Base         @base   = tank.Player.Base;
            TankLocation tankLoc = turnCalcCache.TankLocationMatrix[@base.Pos];

            Rectangle[] tabooAreas = new Rectangle[] { tankLoc.TankBody };

            DistanceCalculator distanceCalculator = new DistanceCalculator();

            distanceCalculator.Walls = GameState.Walls;
            distanceCalculator.TankOuterEdgeMatrix    = GameState.CalculationCache.TankOuterEdgeMatrix;
            distanceCalculator.CellMatrix             = turnCalcCache.CellMatrix;
            distanceCalculator.TabooAreas             = tabooAreas;
            distanceCalculator.TicksWithoutFiring     = ticksWithoutFiring;
            distanceCalculator.RestrictedMovementArea = restrictedBoardArea;
            MobileState tankState = GameState.GetMobileState(tank.Index);
            DirectionalMatrix <DistanceCalculation> distanceMatrix
                = distanceCalculator.CalculateShortestDistancesFromTank(ref tankState);

            return(distanceMatrix);
        }
Exemplo n.º 4
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;
             */
        }
Exemplo n.º 5
0
        public TankAction[] GetActionsToReachLineOfFireDefencePointByIncomingAttackDirection(
            int playerIndex, int tankNumber, Direction finalIncomingDirectionOfAttack)
        {
            Player      player    = Game.Current.Players[playerIndex];
            Tank        tank      = player.Tanks[tankNumber];
            MobileState tankState = GetTankState(playerIndex, tankNumber);

            if (tankState.IsActive)  // TODO: Check if locked in a firefight also
            {
                DirectionalMatrix <DistanceCalculation> distanceMatrix
                    = GameState.CalculationCache.GetDistanceMatrixFromTankByTankIndex(tank.Index);
                Direction defenceDir = finalIncomingDirectionOfAttack.GetOpposite();
                if (defenceDir == Direction.NONE)
                {
                    defenceDir = Direction.RIGHT;
                }
                int startPosOffsetFromBase = Constants.TANK_OUTER_EDGE_OFFSET;
                int endPosOffsetFromBase   = startPosOffsetFromBase + MAX_POINTS_TO_TRY_FOR_DEFENCE_POS;
                for (int offsetSize = startPosOffsetFromBase; offsetSize < endPosOffsetFromBase; offsetSize++)
                {
                    Point defencePos = player.Base.Pos + defenceDir.GetOffset(offsetSize);
                    DistanceCalculation tankDefenceCalc = distanceMatrix[defenceDir, defencePos];
                    if (tankDefenceCalc.CodedDistance == 0)
                    {
                        // This defence point can't be reached, try further away
                        continue;
                    }
                    return(PathCalculator.GetTankActionsOnOutgoingShortestPath(distanceMatrix, defenceDir, defencePos));
                }
            }
            return(new TankAction[0]);
        }
        public DirectionalMatrix <DistanceCalculation> GetDistanceMatrixFromTankByTankIndex(int tankIndex)
        {
            if (distanceMatricesFromTankByTankIndex == null)
            {
                distanceMatricesFromTankByTankIndex = new DirectionalMatrix <DistanceCalculation> [Constants.TANK_COUNT];
            }
            if (distanceMatricesFromTankByTankIndex[tankIndex] == null)
            {
                TurnCalculationCache turnCalcCache = TurnCalculationCache;

                // Don't ride over your own base!
                Tank         tank       = Game.Current.Elements[tankIndex] as Tank;
                Base         @base      = tank.Player.Base;
                TankLocation tankLoc    = turnCalcCache.TankLocationMatrix[@base.Pos];
                Rectangle[]  tabooAreas = new Rectangle[] { tankLoc.TankBody };

                DistanceCalculator distanceCalculator = new DistanceCalculator();
                distanceCalculator.Walls = GameState.Walls;
                distanceCalculator.TankOuterEdgeMatrix = TankOuterEdgeMatrix;
                distanceCalculator.CellMatrix          = turnCalcCache.CellMatrix;
                distanceCalculator.TabooAreas          = tabooAreas;

                MobileState tankState = GameState.GetMobileState(tankIndex);

                distanceMatricesFromTankByTankIndex[tankIndex]
                    = distanceCalculator.CalculateShortestDistancesFromTank(ref tankState);
            }
            return(distanceMatricesFromTankByTankIndex[tankIndex]);
        }
Exemplo n.º 7
0
        public override MoveResult EvaluateLeafNodeMove(Move move)
        {
            MobileState tankState_i = GetTankState_i(move);
            MobileState tankState_j = GetTankState_j(move);

            // Both tanks must be alive:
            if (!(tankState_i.IsActive && tankState_j.IsActive))
            {
                return(new MoveResult(move)
                {
                    EvaluationOutcome = ScenarioEvaluationOutcome.Invalid
                });
            }

            TankSituation tankSit_i = GetTankSituation(move.p, move.i);
            TankSituation tankSit_j = GetTankSituation(move.pBar, move.j);
            int           ticksUntilFriendlyTankCanFireAgain = tankSit_i.ExpectedNextTickWhenTankCanFireAgain - GameState.Tick;
            int           ticksUntilEnemyTankCanFireAgain    = tankSit_j.ExpectedNextTickWhenTankCanFireAgain - GameState.Tick;

            if (ticksUntilEnemyTankCanFireAgain <= 0 || ticksUntilFriendlyTankCanFireAgain > 0)
            {
                return(new MoveResult(move)
                {
                    EvaluationOutcome = ScenarioEvaluationOutcome.Invalid
                });
            }

            int attackDistance = GetAttackDistanceFromTankToTank(move.p, move.i, move.j);

            if (attackDistance - ticksUntilEnemyTankCanFireAgain > 5)
            {
                return(new MoveResult(move)
                {
                    EvaluationOutcome = ScenarioEvaluationOutcome.Invalid
                });
            }

            foreach (TankActionSituation tankActSit in tankSit_i.TankActionSituationsPerTankAction)
            {
                int A_p_i = GetAttackDistanceFromHypotheticalTankStateToTank(
                    tankActSit.NewTankState, move.pBar, move.j, TankHelper.EdgeOffsets);
                int    slack       = A_p_i - ticksUntilEnemyTankCanFireAgain;
                double attackValue = ScenarioValueFunctions.AttackDisarmedEnemyTankSlackUntilRearmedFunction.Evaluate(slack);
                tankActSit.Value += attackValue;
            }

            // Convert a good attacking position into killing the enemy tank, by weighting the attacking action more highly:
            TankAction[] attackActions = GetTankActionsFromTankToAttackTank(move.p, move.i, move.j);
            if (attackActions.Length > 0)
            {
                TankAction attackAction      = attackActions[0];
                double     attackActionValue = ScenarioValueFunctions.AttackDisarmedEnemyTankAttackActionFunction.Evaluate(attackDistance);
                tankSit_i.TankActionSituationsPerTankAction[(int)attackAction].Value += attackActionValue;
            }

            return(new MoveResult(move)
            {
                EvaluationOutcome = ScenarioEvaluationOutcome.Possible
            });
        }
        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);
        }
Exemplo n.º 9
0
        public void DrawBullets(Graphics boardGraphics, GameState gameState)
        {
            int dirCount = Enum.GetValues(typeof(Direction)).Length;

            // Load bullets:
            Bitmap[] bulletImages = new Bitmap[dirCount];
            for (int d = 0; d < dirCount; d++)
            {
                Direction dir             = (Direction)d;
                string    bulletImageName = String.Format("Bullet_{0}.bmp", dir);
                bulletImages[d] = GetBitmapByName(bulletImageName);
            }

            for (int i = Constants.MIN_BULLET_INDEX; i <= Constants.MAX_BULLET_INDEX; i++)
            {
                MobileState bulletState = gameState.GetMobileState(i);
                if (bulletState.IsActive && bulletState.Dir != Direction.NONE)
                {
                    Image bulletImage = bulletImages[(byte)bulletState.Dir];
                    boardGraphics.DrawImage(
                        bulletImage,
                        MagnificationFactor * bulletState.Pos.X,
                        MagnificationFactor * bulletState.Pos.Y,
                        MagnificationFactor,
                        MagnificationFactor);
                }
            }
        }
        public static BulletSituation CreateBulletSituation(GameState gameState,
                                                            TankSituation tankSituation, int bulletIndex, int bulletId)
        {
            MobileState     bulletState = gameState.GetMobileState(bulletIndex);
            MobileState     tankState   = gameState.GetMobileState(bulletIndex - Constants.MIN_BULLET_INDEX);
            BulletSituation bulletSituation;

            if (!bulletState.IsActive)
            {
                bulletSituation = new BulletSituation(tankSituation, bulletIndex, bulletId)
                {
                    IsActive = false,
                    TickOffsetWhenTankCanFireAgain = 0,
                    TankStateAtTimeOfFiring        = tankState,
                    BulletStateAtTimeOfFiring      = bulletState,
                    BulletCalculationsByTick       = new BulletCalculationByTick[0]
                };
                return(bulletSituation);
            }

            // Assume the bullet has just been fired (not correct, but it shouldn't matter):
            bulletSituation = new BulletSituation(tankSituation, bulletIndex, bulletId)
            {
                TickFired = gameState.Tick,
                TankStateAtTimeOfFiring   = tankState,
                BulletStateAtTimeOfFiring = bulletState,
                IsActive = true
            };
            GenerateBulletTimeline(gameState, bulletSituation);
            return(bulletSituation);
        }
Exemplo n.º 11
0
        public int GetAttackDistanceFromTankToTank(int playerIndex, int tankNumber, int targetTankNumber)
        {
            Tank targetTank = Game.Current.Players[1 - playerIndex].Tanks[targetTankNumber];
            DirectionalMatrix <DistanceCalculation> distanceMatrix
                = GameState.CalculationCache.GetIncomingAttackMatrixForTankByTankIndex(targetTank.Index);
            MobileState tankState = GetTankState(playerIndex, tankNumber);

            return(distanceMatrix[tankState].Distance);
        }
Exemplo n.º 12
0
        public DirectionalMatrix <DistanceCalculation> CalculateDistancesForTank(MobileState tankState)
        {
            DistanceCalculator distanceCalculator = new DistanceCalculator();

            distanceCalculator.Walls = Board;
            distanceCalculator.TankOuterEdgeMatrix = TankEdgeMatrix;
            distanceCalculator.CellMatrix          = CellMatrix;
            return(distanceCalculator.CalculateShortestDistancesFromTank(ref tankState));
        }
Exemplo n.º 13
0
        private void AddBulletSurvivalTactic(Move move, int ticksUntil_p_i_CanFireAgain, int ticksToEscape,
                                             List <BulletSurvivalTactic> bulletTactics, Point survivalPoint, Direction dir,
                                             int tickOffsetWhenTankCanFireAgain, bool isConfrontingBullet)
        {
            MobileState survivalState = new MobileState(survivalPoint, dir, isActive: true);

            AddBulletSurvivalTactic(move, ticksUntil_p_i_CanFireAgain, ticksToEscape,
                                    bulletTactics, survivalState, tickOffsetWhenTankCanFireAgain, isConfrontingBullet);
        }
Exemplo n.º 14
0
 public int GetAttackDistanceToEnemyBaseFromTankState(int playerIndex, ref MobileState tankState)
 {
     if (tankState.IsActive)
     {
         DirectionalMatrix <DistanceCalculation> attackDistanceMatrix
             = GameState.CalculationCache.GetIncomingDistanceMatrixForBase(1 - playerIndex);
         return(attackDistanceMatrix[tankState].Distance);
     }
     return(Constants.UNREACHABLE_DISTANCE);
 }
Exemplo n.º 15
0
 public Mobile(string hostName, string deviceId, string deviceAccessKey, TransportType transportType)
     : base(hostName, deviceId, deviceAccessKey, transportType)
 {
     _state = new MobileState
     {
         Id = deviceId,
     };
     _consoleState     = null;
     _consoleTelemetry = null;
 }
 public static TankAction[] GetTankActionsOnIncomingShortestPath(
     DirectionalMatrix <DistanceCalculation> distances,
     MobileState attackingTankState, Point targetPos,
     FiringLineMatrix firingLineMatrix,
     bool keepMovingCloserOnFiringLastBullet = false)
 {
     return(GetTankActionsOnIncomingShortestPath(distances, attackingTankState.Dir,
                                                 attackingTankState.Pos.X, attackingTankState.Pos.Y, targetPos.X, targetPos.Y,
                                                 firingLineMatrix, keepMovingCloserOnFiringLastBullet));
 }
Exemplo n.º 17
0
 public T this[MobileState mobileState]
 {
     get
     {
         return(this[mobileState.Dir, mobileState.Pos]);
     }
     set
     {
         this[mobileState.Dir, mobileState.Pos] = value;
     }
 }
Exemplo n.º 18
0
        public bool TrySetTankActions(TankActionSet actionSet, int timeoutInMilliseconds)
        {
            if (actionSet == null)
            {
                return(true);
            }

            if (actionSet.Tick != Game.Current.CurrentTurn.Tick)
            {
                LogDebugMessage("Tank actions not submitted as tick {0} is in the past", actionSet.Tick);
                return(false);
            }

            int        playerIndex      = actionSet.PlayerIndex;
            GameState  currentGameState = Game.Current.CurrentTurn.GameState;
            int        numberAlive      = 0;
            int        tankId           = -1;
            TankAction tankAction       = TankAction.NONE;
            int        tankNumber       = -1;

            for (int t = 0; t < Constants.TANKS_PER_PLAYER; t++)
            {
                Tank        tank      = Game.Current.Players[actionSet.PlayerIndex].Tanks[t];
                MobileState tankState = currentGameState.GetMobileState(tank.Index);
                if (tankState.IsActive)
                {
                    numberAlive++;
                    tankId     = tank.Id;
                    tankAction = actionSet.Actions[t];
                    tankNumber = tank.Number;
                }
            }

            LogDebugMessage("Sending tank actions for player {0}", Solver.YourPlayerIndex);

            if (numberAlive == 1)
            {
                LogDebugMessage("    Tank {0} action {1} (tank id: {2})", tankNumber, tankAction, tankId);
                return(Communicator.TrySetAction(playerIndex, tankId, tankAction, CommunicatorCallback, timeoutInMilliseconds));
            }
            else
            if (numberAlive == 2)
            {
                TankAction tankAction1 = actionSet.Actions[0];
                TankAction tankAction2 = actionSet.Actions[1];
                LogDebugMessage("    Tank 0 action {0}", tankAction1);
                LogDebugMessage("    Tank 1 action {0}", tankAction2);
                return(Communicator.TrySetActions(playerIndex, tankAction1, tankAction2, CommunicatorCallback, timeoutInMilliseconds));
            }
            else
            {
                return(true);
            }
        }
Exemplo n.º 19
0
        public int GetAttackDistanceFromHypotheticalTankStateToTank(
            MobileState attackTankState, int targetPlayerIndex, int targetTankNumber,
            EdgeOffset[] edgeOffsets)
        {
            Tank targetTank = Game.Current.Players[targetPlayerIndex].Tanks[targetTankNumber];
            DirectionalMatrix <DistanceCalculation> distanceMatrix
                = GameState.CalculationCache.GetIncomingAttackMatrixForTankByTankIndex(targetTank.Index);
            DistanceCalculation distanceCalc = distanceMatrix[attackTankState];

            return(distanceCalc.Distance);
        }
Exemplo n.º 20
0
        protected override void ChooseMoves()
        {
            GameState     currGameState = Game.Current.CurrentTurn.GameState;
            TankActionSet actionSet     = new TankActionSet(YourPlayerIndex, currGameState.Tick);

            for (int tankNumber = 0; tankNumber < Constants.TANKS_PER_PLAYER; tankNumber++)
            {
                Tank        tank      = You.Tanks[tankNumber];
                MobileState tankState = currGameState.GetMobileState(tank.Index);
                if (!tankState.IsActive)
                {
                    continue;
                }

                int midX = currGameState.Walls.Width / 2;
                int midY = currGameState.Walls.Height / 2;

                int       targetX;
                int       targetY;
                Direction direction;

                if (tankState.Pos.X > midX)
                {
                    targetX = currGameState.Walls.Width - Constants.SEGMENT_SIZE;
                }
                else
                {
                    targetX = Constants.SEGMENT_SIZE;
                }

                if (tankState.Pos.Y > midY)
                {
                    targetY   = currGameState.Walls.Height - Constants.SEGMENT_SIZE;
                    direction = Direction.UP;
                }
                else
                {
                    targetY   = Constants.SEGMENT_SIZE;
                    direction = Direction.DOWN;
                }

                DirectionalMatrix <DistanceCalculation> distancesFromTank
                    = currGameState.CalculationCache.GetDistanceMatrixFromTankByTankIndex(tank.Index);
                TankAction[] tankActions = PathCalculator.GetTankActionsOnOutgoingShortestPath(
                    distancesFromTank, direction, targetX, targetY);
                if (tankActions.Length > 0)
                {
                    actionSet.Actions[tank.Number] = tankActions[0];
                }
            }

            Coordinator.SetBestMoveSoFar(actionSet);
        }
Exemplo n.º 21
0
        public TankAction[] GetTankActionsFromTankToAttackTank(int playerIndex, int tankNumber, int targetTankNumber)
        {
            Tank        targetTank      = Game.Current.Players[1 - playerIndex].Tanks[targetTankNumber];
            MobileState targetTankState = GetTankState(1 - playerIndex, targetTankNumber);
            DirectionalMatrix <DistanceCalculation> distanceMatrix
                = GameState.CalculationCache.GetIncomingAttackMatrixForTankByTankIndex(targetTank.Index);
            MobileState attackingTankState = GetTankState(playerIndex, tankNumber);

            return(PathCalculator.GetTankActionsOnIncomingShortestPath(distanceMatrix,
                                                                       attackingTankState, targetTankState.Pos, GameState.CalculationCache.FiringLinesForTanksMatrix,
                                                                       keepMovingCloserOnFiringLastBullet: false));
        }
Exemplo n.º 22
0
        private void FindShortestPathsWithRestrictionsOnFiring(MobileState tankState, DirectionalMatrix <DistanceCalculation> distanceMatrix)
        {
            TwoValuedCircularBuffer <Node> bfsQueue = new TwoValuedCircularBuffer <Node>(CircularBufferCapacityRequired);
            Node currNode       = new Node(ActionType.Moving, tankState.Dir, tankState.Pos);
            int  adjDistance    = 1;
            bool nodesToProcess = true;
            bool canFire        = TicksWithoutFiring < adjDistance;

            while (nodesToProcess)
            {
                // Get each node adjacent to the current node:
                Node[] adjacentNodes
                    = canFire
                    ? currNode.GetAdjacentOutgoingNodes(TankOuterEdgeMatrix[currNode.X, currNode.Y])
                    : currNode.GetAdjacentOutgoingNodesWithoutFiring(TankOuterEdgeMatrix[currNode.X, currNode.Y]);
                foreach (Node adj in adjacentNodes)
                {
                    if (adj.ActionType == ActionType.Moving)
                    {
                        // Check if the node already has a distance i.e. has it already been expanded?
                        if (distanceMatrix[adj.Dir, adj.X, adj.Y].CodedDistance == 0)
                        {
                            // Set the new shortest distance:
                            distanceMatrix[adj.Dir, adj.X, adj.Y] = new DistanceCalculation(adjDistance, currNode);

                            // Add to the queue to be expanded:
                            bfsQueue.Add(adj, adjDistance);
                        }
                    }
                    else
                    {
                        // A firing node can only be reached in one way (from the moving node on the same cell).
                        // So we don't need to check if it is the shortest path to the node (it must be).
                        // And we aren't interested in it, so no need to store it.
                        // Hence just add it to the queue (it is a "convenience" node to allow a BFS):
                        bfsQueue.Add(adj, adjDistance);
                    }
                }

                if (bfsQueue.Size == 0)
                {
                    nodesToProcess = false;
                }
                else
                {
                    CircularBufferItem <Node> nextItem = bfsQueue.Remove();
                    currNode    = nextItem.Item;
                    adjDistance = nextItem.Value + 1;
                    canFire     = adjDistance > TicksWithoutFiring;
                }
            }
        }
Exemplo n.º 23
0
        public int GetDistanceFromTankToTargetTank(
            int attackPlayerIndex, int attackTankNumber, int targetPlayerIndex, int targetTankNumber)
        {
            Tank attackTank = Game.Current.Players[attackPlayerIndex].Tanks[attackTankNumber];
            DirectionalMatrix <DistanceCalculation> distanceMatrix
                = GameState.CalculationCache.GetDistanceMatrixFromTankByTankIndex(attackTank.Index);

            Tank                defenceTank     = Game.Current.Players[targetPlayerIndex].Tanks[targetTankNumber];
            MobileState         targetTankState = GetTankState(targetPlayerIndex, targetTankNumber);
            DistanceCalculation distanceCalc    = distanceMatrix[targetTankState];

            return(distanceCalc.Distance);
        }
Exemplo n.º 24
0
        public int GetAttackDistanceOfTankToEnemyBaseFromDirection(int playerIndex, int tankNumber,
                                                                   Direction finalDirectionOfMovement)
        {
            MobileState tankState = GetTankState(playerIndex, tankNumber);

            if (tankState.IsActive)
            {
                DirectionalMatrix <DistanceCalculation> attackDistanceMatrix
                    = GameState.CalculationCache.GetIncomingDistanceMatrixForBaseWithFinalDirectionOfMovement(
                          1 - playerIndex, finalDirectionOfMovement);
                return(attackDistanceMatrix[tankState].Distance);
            }
            return(Constants.UNREACHABLE_DISTANCE);
        }
        // TODO: Use or remove...
        public static void UpdateBulletSituation(GameState gameState, BulletSituation bulletSituation)
        {
            MobileState bulletState = gameState.GetMobileState(bulletSituation.BulletIndex);

            if (!bulletState.IsActive)
            {
                bulletSituation.IsActive = false;
                bulletSituation.BulletCalculationsByTick = new BulletCalculationByTick[0];
            }
            else
            {
                // Re-generate the bullet timeline every turn, since the board may have changed:
                GenerateBulletTimeline(gameState, bulletSituation);
            }
        }
Exemplo n.º 26
0
        /* TODO: Allow easy comparison across actions...
         * public int[] GetAttackDistanceOfTankToEnemyBasePerTankAction(int playerIndex, int tankNumber)
         * {
         *  MobileState tankState = GetTankState(playerIndex, tankNumber);
         *  int[] attackDistancesByTankAction = new int[Constants.TANK_ACTION_COUNT];
         *  foreach (TankAction tankAction in TankHelper.TankActions)
         *  {
         *      if (tankState.IsActive)
         *      {
         *
         *
         *          DirectionalMatrix<DistanceCalculation> attackDistanceMatrix
         *              = GameState.CalculationCache.GetIncomingDistanceMatrixForBase(1 - playerIndex);
         *          return attackDistanceMatrix[tankState].Distance;
         *      }
         *      return Constants.UNREACHABLE_DISTANCE;
         *  }
         *  return attackDistancesByTankAction;
         * }
         */

        public TankAction[] GetActionsToAttackEnemyBase(int playerIndex, int tankNumber)
        {
            MobileState tankState = GetTankState(playerIndex, tankNumber);

            if (tankState.IsActive)
            {
                Base             enemyBase        = GetEnemyBase(playerIndex);
                FiringLineMatrix firingLineMatrix = GameState.CalculationCache.FiringLinesForPointsMatrix;
                DirectionalMatrix <DistanceCalculation> attackDistanceMatrix
                    = GameState.CalculationCache.GetIncomingDistanceMatrixForBase(1 - playerIndex);
                return(PathCalculator.GetTankActionsOnIncomingShortestPath(attackDistanceMatrix, tankState,
                                                                           enemyBase.Pos, firingLineMatrix, keepMovingCloserOnFiringLastBullet: true));
            }
            return(NoTankActions);
        }
Exemplo n.º 27
0
 private void LogActionsTaken()
 {
     for (int t = 0; t < Constants.TANK_COUNT; t++)
     {
         MobileState tankState = NewGameState.GetMobileState(t);
         if (tankState.IsActive)
         {
             Tank       tank        = Game.Current.Elements[t] as Tank;
             TankAction actionTaken = TankActionsTaken[t];
             LogDebugMessage("Player {0} tank {1} took action {2} and is now at {3}",
                             tank.PlayerNumber, tank.Number, actionTaken, tankState.Pos);
         }
     }
     DebugHelper.WriteLine();
 }
Exemplo n.º 28
0
        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 override MoveResult EvaluateLeafNodeMove(Move move)
        {
            MobileState   tankState_i = GetTankState_i(move);
            TankSituation tankSit_i   = GetTankSituation(move.p, move.i);

            if (tankSit_i.IsLockedDown || !tankState_i.IsActive)
            {
                return(new MoveResult(move)
                {
                    EvaluationOutcome = ScenarioEvaluationOutcome.Invalid
                });
            }

            foreach (TankActionSituation tankActSit in tankSit_i.TankActionSituationsPerTankAction)
            {
                MobileState newTankState          = tankActSit.NewTankState;
                int         attackDistToEnemyBase = GetAttackDistanceToEnemyBaseFromTankState(YourPlayerIndex, ref newTankState);
                if (tankActSit.TankAction == TankAction.FIRE && tankActSit.IsAdjacentWallRemoved)
                {
                    Point       adjacentPos            = tankActSit.NewTankState.Pos + tankActSit.NewTankState.Dir.GetOffset();
                    MobileState adjacentState          = new MobileState(adjacentPos, tankActSit.NewTankState.Dir, isActive: true);
                    int         attackDistToEnemyBase2 = GetAttackDistanceToEnemyBaseFromTankState(YourPlayerIndex, ref adjacentState) + 1;
                    if (attackDistToEnemyBase2 < attackDistToEnemyBase)
                    {
                        attackDistToEnemyBase = attackDistToEnemyBase2;
                    }
                }
                double value = ScenarioValueFunctions.AttackEnemyBaseFunction.Evaluate(attackDistToEnemyBase);
                tankActSit.Value += value;
            }

            // Convert a good position into killing the enemy base, by weighting the attacking action more highly:
            int attackDistance = GetAttackDistanceToEnemyBaseFromTankState(move.i, ref tankState_i);

            TankAction[] attackActions = GetActionsToAttackEnemyBase(move.p, move.i);
            if (attackActions.Length > 0)
            {
                TankAction attackAction      = attackActions[0];
                double     attackActionValue = ScenarioValueFunctions.AttackEnemyBaseAttackActionFunction.Evaluate(attackDistance);
                tankSit_i.TankActionSituationsPerTankAction[(int)attackAction].Value += attackActionValue;
            }

            return(new MoveResult(move)
            {
                EvaluationOutcome = ScenarioEvaluationOutcome.Possible
            });
        }
Exemplo n.º 30
0
        public void TestDistanceCalculator(string logFilePath, int repetitions, int smallRepetitions)
        {
            SegStateCalculator = new CacheBasedSegmentStateCalculator(HorizSegmentStateMatrix, VertSegmentStateMatrix);
            TankEdgeMatrix     = PerformanceTestHelper.TimeFunction(
                logFilePath, "Calculate tank edge matrix using TankEdgeCalculator", repetitions,
                CalculateTankOuterEdgeMatrix);

            MobileState tankState1 = new MobileState(new Point(20, 6), Direction.UP, isActive: true);

            DistancesFromTank1 = PerformanceTestHelper.TimeFunctionWithArgument(logFilePath, "Test Distance Calculator for tank 1",
                                                                                smallRepetitions, tankState1, CalculateDistancesForTank);

            MobileState tankState2 = new MobileState(new Point(56, 6), Direction.UP, isActive: true);

            DistancesFromTank2 = PerformanceTestHelper.TimeFunctionWithArgument(logFilePath, "Test Distance Calculator for tank 2",
                                                                                smallRepetitions, tankState2, CalculateDistancesForTank);
        }