Exemplo n.º 1
0
 public Ship(int index, int id, int x, int y, int orientation, int speed, int rum, int owner) : base(id, EntityType.Ship, x, y)
 {
     this.index       = index;
     this.orientation = orientation;
     this.speed       = speed;
     this.rum         = rum;
     this.owner       = owner;
     bow       = coord.Neighbor(orientation);
     stern     = coord.Neighbor((orientation + 3) % 6);
     fposition = FastShipPosition.Create(x, y, orientation, speed);
     fbow      = FastShipPosition.Bow(fposition);
     fstern    = FastShipPosition.Stern(fposition);
 }
Exemplo n.º 2
0
 public void Bow_ReturnsValidCoord()
 {
     for (int x = 0; x < Constants.MAP_WIDTH; x++)
     {
         for (int y = 0; y < Constants.MAP_HEIGHT; y++)
         {
             for (int speed = 0; speed <= Constants.MAX_SHIP_SPEED; speed++)
             {
                 for (int orientation = 0; orientation < 6; orientation++)
                 {
                     var shipPosition     = new ShipPosition(new Coord(x, y), orientation, speed);
                     var fastShipPosition = FastShipPosition.Create(shipPosition);
                     FastCoord.ToCoord(FastShipPosition.Bow(fastShipPosition)).Should().Be(shipPosition.bow, shipPosition.ToString());
                 }
             }
         }
     }
 }
        private List <FireTarget> GetFireTargets(Ship ship, Ship enemyShip)
        {
            var result      = new List <FireTarget>();
            var enemyIndex  = enemyShip.index;
            var cannonCoord = FastShipPosition.Bow(ship.fposition);

            for (var turn = 0; turn < Settings.CANNONS_TRAVEL_TIME_LIMIT + 1; turn++)
            {
                var forecast      = gameState.forecaster.GetTurnForecast(turn);
                var enemyPosition = forecast.enemyShipsFinalPositions[enemyIndex];

                var coords      = new[] { FastShipPosition.Coord(enemyPosition), FastShipPosition.Bow(enemyPosition), FastShipPosition.Stern(enemyPosition) };
                var targetTypes = new[] { FireTargetType.ShipCenter, FireTargetType.ShipBow, FireTargetType.ShipStern };
                for (var i = 0; i < coords.Length; i++)
                {
                    var target = coords[i];
                    if (FastCoord.IsInsideMap(target))
                    {
                        if (forecast.myShipsPositions.Any(m => FastShipPosition.Collides(m, target)))
                        {
                            continue;
                        }
                        var distanceTo = FastCoord.Distance(cannonCoord, target);
                        if (distanceTo <= 10)
                        {
                            var travelTime = (int)(1 + Math.Round(distanceTo / 3.0));
                            if (travelTime == turn)
                            {
                                result.Add(new FireTarget(target, turn, i == 0 ? Constants.HIGH_DAMAGE : Constants.LOW_DAMAGE, targetTypes[i]));
                            }
                        }
                    }
                }
            }
            return(result);
        }
        public List <PathItem> FindPath(TurnState turnState, int ftarget, NavigationMethod navigationMethod)
        {
            var ship = turnState.FindMyShip(shipId);

            //if (FastShipPosition.Collides(ship.fposition, ftarget))
            //	return new List<PathItem>();

            var queue = new Queue <ShipPathChainItem>();

            queue.Enqueue(ShipPathChainItem.Start(ship.fposition, ftarget));

            var used = new Dictionary <ShipMovementState, ShipPathChainItem>();

            while (queue.Any())
            {
                var current = queue.Dequeue();
                if (current.depth != Settings.NAVIGATION_PATH_DEPTH)
                {
                    var turnForecast = gameState.forecaster.GetTurnForecast(current.depth);
                    foreach (var moveCommand in ShipMoveCommands.all)
                    {
                        var newShipMovement  = FastShipPosition.Move(current.fposition, moveCommand);
                        var newMovedPos      = FastShipPosition.GetMovedPosition(newShipMovement);
                        var newPos           = FastShipPosition.GetFinalPosition(newShipMovement);
                        var newMovementState = new ShipMovementState(newPos, current.depth + 1);
                        if (!used.ContainsKey(newMovementState))
                        {
                            var onMyShip = false;
                            foreach (var otherShip in turnState.myShips)
                            {
                                if (otherShip == ship)
                                {
                                    continue;
                                }
                                var  otherPosition = turnForecast.myShipsSourcePositions[otherShip.index];
                                uint myMovement;
                                uint otherMovement;
                                var  collisionType = CollisionChecker.Move(current.fposition, moveCommand, otherPosition, turnForecast.myShipsMoveCommands[otherShip.index], out myMovement, out otherMovement);
                                if ((collisionType & (CollisionType.MyMove | CollisionType.MyRotation)) != CollisionType.None)
                                {
                                    newShipMovement  = myMovement;
                                    newMovedPos      = FastShipPosition.GetMovedPosition(newShipMovement);
                                    newPos           = FastShipPosition.GetFinalPosition(newShipMovement);
                                    newMovementState = new ShipMovementState(newPos, current.depth + 1);
                                    onMyShip         = used.ContainsKey(newMovementState);
                                    break;
                                }
                            }

                            if (onMyShip)
                            {
                                continue;
                            }

                            var onEnemyShip = false;
                            if (current.depth == 0)
                            {
                                foreach (var enemyShip in turnState.enemyShips)
                                {
                                    var enemyPosition = enemyShip.fposition;
                                    foreach (var enemyMoveCommand in ShipMoveCommands.all)
                                    {
                                        uint myMovement;
                                        uint enemyMovement;
                                        var  collisionType = CollisionChecker.Move(current.fposition, moveCommand, enemyPosition, enemyMoveCommand, out myMovement, out enemyMovement);
                                        if ((collisionType & (CollisionType.MyMove | CollisionType.MyRotation)) != CollisionType.None)
                                        {
                                            newShipMovement  = myMovement;
                                            newMovedPos      = FastShipPosition.GetMovedPosition(newShipMovement);
                                            newPos           = FastShipPosition.GetFinalPosition(newShipMovement);
                                            newMovementState = new ShipMovementState(newPos, current.depth + 1);
                                            onEnemyShip      = used.ContainsKey(newMovementState);
                                            break;
                                        }
                                    }
                                }
                            }
                            else
                            {
                                var prevEnemyFinalPositions = gameState.forecaster.GetTurnForecast(Math.Min(current.depth - 1, Settings.NAVIGATOR_ENEMY_POSITION_DEPTH)).enemyShipsFinalPositions;
                                foreach (var enemyPosition in prevEnemyFinalPositions)
                                {
                                    uint myMovement;
                                    uint enemyMovement;
                                    var  collisionType = CollisionChecker.Move(current.fposition, moveCommand, enemyPosition, ShipMoveCommand.Wait, out myMovement, out enemyMovement);
                                    if ((collisionType & (CollisionType.MyMove | CollisionType.MyRotation)) != CollisionType.None)
                                    {
                                        newShipMovement  = myMovement;
                                        newMovedPos      = FastShipPosition.GetMovedPosition(newShipMovement);
                                        newPos           = FastShipPosition.GetFinalPosition(newShipMovement);
                                        newMovementState = new ShipMovementState(newPos, current.depth + 1);
                                        onEnemyShip      = used.ContainsKey(newMovementState);
                                        break;
                                    }
                                }

                                //onEnemyShip = gameState.forecaster.GetTurnForecast(Math.Min(current.depth, Settings.NAVIGATOR_ENEMY_POSITION_DEPTH)).enemyShipsFinalPositions
                                //	.Any(m => FastShipPosition.CollidesShip(newPos, m) || FastShipPosition.CollidesShip(newMovedPos, m));
                            }

                            if (onEnemyShip)
                            {
                                //used.Add(newMovementState, null);
                                continue;
                            }

                            var damage = turnForecast.mineDamageCoordMap[FastShipPosition.Coord(newPos)]
                                         + turnForecast.mineDamageCoordMap[FastShipPosition.Bow(newPos)]
                                         + turnForecast.mineDamageCoordMap[FastShipPosition.Stern(newPos)]
                                         + turnForecast.nearMineDamageCoordMap[FastShipPosition.Bow(newPos)]
                                         + turnForecast.nearMineDamageCoordMap[FastShipPosition.Stern(newPos)];

                            if (newMovedPos != newPos)
                            {
                                damage += turnForecast.mineDamageCoordMap[FastShipPosition.Bow(newMovedPos)]
                                          + turnForecast.mineDamageCoordMap[FastShipPosition.Stern(newMovedPos)]
                                          + turnForecast.nearMineDamageCoordMap[FastShipPosition.Bow(newMovedPos)]
                                          + turnForecast.nearMineDamageCoordMap[FastShipPosition.Stern(newMovedPos)];
                            }

                            var cannonedBowOrStern = turnForecast.cannonballCoordsMap[FastShipPosition.Bow(newPos)] || turnForecast.cannonballCoordsMap[FastShipPosition.Stern(newPos)];
                            if (cannonedBowOrStern)
                            {
                                damage += Constants.LOW_DAMAGE;
                            }

                            var cannonedCenter = turnForecast.cannonballCoordsMap[FastShipPosition.Coord(newPos)];
                            if (cannonedCenter)
                            {
                                damage += Constants.HIGH_DAMAGE;
                            }

                            if (Settings.NEAR_ENEMYSHIP_VIRTUAL_DAMAGE > 0)
                            {
                                var nearEnemyShip = turnState.enemyShips.Any(m => FastShipPosition.DistanceTo(newPos, m.fcoord) < Settings.NEAR_ENEMY_SHIP_MIN_DIST);
                                if (nearEnemyShip)
                                {
                                    damage += Settings.NEAR_ENEMYSHIP_VIRTUAL_DAMAGE;
                                }
                            }

                            var next = current.Next(newPos, moveCommand, ftarget, damage);
                            queue.Enqueue(next);
                            used.Add(newMovementState, next);
                        }
                    }
                }
            }

            ShipPathChainItem bestChainItem = null;

            foreach (var chainItem in used.Values.Where(v => v != null))
            {
                if (chainItem.prev != null)
                {
                    if (bestChainItem == null)
                    {
                        bestChainItem = chainItem;
                    }
                    else
                    {
                        switch (navigationMethod)
                        {
                        case NavigationMethod.Approach:
                            bestChainItem = SelectBestPath_Approach(chainItem, bestChainItem, ship);
                            break;

                        case NavigationMethod.Collect:
                            bestChainItem = SelectBestPath_Collect(chainItem, bestChainItem, ship);
                            break;

                        default:
                            bestChainItem = SelectBestPath(chainItem, bestChainItem, ship);
                            break;
                        }
                    }
                }
            }

            if (bestChainItem == null)
            {
                return(new List <PathItem>());
            }

            var chainDump = new List <ShipPathChainItem>();
            var chain     = new List <PathItem>();

            while (bestChainItem.prev != null)
            {
                chain.Add(new PathItem {
                    command = bestChainItem.command, targetPosition = bestChainItem.fposition, sourcePosition = bestChainItem.prev.fposition
                });
                chainDump.Add(bestChainItem);
                bestChainItem = bestChainItem.prev;
            }
            chainDump.Reverse();
            if (Settings.DUMP_BEST_PATH)
            {
                Console.Error.WriteLine($"Best path for ship {shipId}");
                foreach (var item in chainDump)
                {
                    Console.Error.WriteLine($"{item.command} - {FastShipPosition.ToShipPosition(item.fposition)} - dmg:{item.damage}");
                }
            }
            chain.Reverse();
            return(chain);
        }