Ejemplo n.º 1
0
        public StrategicDecision RunAway_FreeWay(TurnState turnState, Ship ship, StrategicDecision prevDecision)
        {
            var finalCoords = new List <int>();

            foreach (var enemyShip in turnState.enemyShips)
            {
                var move = FastShipPosition.Move(enemyShip.fposition, ShipMoveCommand.Faster);
                move = FastShipPosition.Move(FastShipPosition.GetFinalPosition(move), ShipMoveCommand.Faster);
                move = FastShipPosition.Move(FastShipPosition.GetFinalPosition(move), ShipMoveCommand.Faster);
                var finalCoord = FastShipPosition.Coord(FastShipPosition.GetFinalPosition(move));
                finalCoords.Add(finalCoord);
            }

            var candidates = runTargets.OrderByDescending(t => (int)finalCoords.Average(fc => FastCoord.Distance(t, fc) * FastCoord.Distance(t, fc))).Take(3).ToArray();

            var runTarget = candidates.OrderBy(
                t =>
            {
                var cost = 0;
                foreach (var enemyShip in turnState.enemyShips)
                {
                    cost += WayEvaluator.CalcCost(ship.fcoord, t, enemyShip.fcoord);
                }
                return(cost);
            }).First();

            return(new StrategicDecision {
                role = StrategicRole.RunAway, targetCoord = runTarget
            });
        }
Ejemplo n.º 2
0
 public void Coord_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.Coord(fastShipPosition)).Should().Be(shipPosition.coord, shipPosition.ToString());
                 }
             }
         }
     }
 }
        private static void Split(int position, ShipMoveCommand command, out int coord, out int bow, out int stern, out int orientation, out int speed, out int ncoord, out int nbow, out int nstern, out int norientation)
        {
            coord        = FastShipPosition.Coord(position);
            orientation  = FastShipPosition.Orientation(position);
            speed        = FastShipPosition.Speed(position);
            bow          = FastCoord.Neighbor(coord, orientation);
            stern        = FastCoord.Neighbor(coord, (orientation + 3) % 6);
            ncoord       = coord;
            nbow         = bow;
            nstern       = stern;
            norientation = orientation;
            switch (command)
            {
            case ShipMoveCommand.Faster:
                if (speed < Constants.MAX_SHIP_SPEED)
                {
                    speed++;
                }
                break;

            case ShipMoveCommand.Slower:
                if (speed > 0)
                {
                    speed--;
                }
                break;

            case ShipMoveCommand.Port:
                norientation = (orientation + 1) % 6;
                break;

            case ShipMoveCommand.Starboard:
                norientation = (orientation + 5) % 6;
                break;
            }
        }
        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);
        }
Ejemplo n.º 5
0
        private void RunOrSuicide(TurnState turnState)
        {
            if (turnState.myShips.Max(s => s.rum) > turnState.enemyShips.Max(s => s.rum) || turnState.myShips.Min(s => s.rum) > 50)
            {
                foreach (var ship in turnState.myShips)
                {
                    StrategicDecision prevDecision;
                    strateg.decisions.TryGetValue(ship.id, out prevDecision);
                    strateg.decisions[ship.id] = strateg.RunAway(turnState, ship, prevDecision);
                }
                return;
            }

            if (turnState.myShips.Count == 1)
            {
                var ship = turnState.myShips[0];
                StrategicDecision prevDecision;
                strateg.decisions.TryGetValue(ship.id, out prevDecision);
                strateg.decisions[ship.id] = strateg.RunAway(turnState, ship, prevDecision);
                return;
            }

            var ship1 = turnState.myShips[0];
            var ship2 = turnState.myShips[1];

            if (ship1.rum > ship2.rum)
            {
                var tmp = ship1;
                ship1 = ship2;
                ship2 = tmp;
            }
            if (FastCoord.Distance(ship1.fbow, ship2.fbow) <= 4)
            {
                StrategicDecision prevDecision;
                strateg.decisions.TryGetValue(ship1.id, out prevDecision);
                if (prevDecision?.role == StrategicRole.Fire || prevDecision?.role == StrategicRole.Explicit)
                {
                    strateg.decisions[ship1.id] = new StrategicDecision {
                        role = StrategicRole.Explicit, explicitCommand = ShipMoveCommand.Slower
                    };
                    strateg.decisions[ship2.id] = new StrategicDecision {
                        role = StrategicRole.Approach, targetCoord = prevDecision.fireToCoord
                    };
                }
                else
                {
                    var nextShip1Position = FastShipPosition.GetFinalPosition(FastShipPosition.Move(ship1.fposition, ShipMoveCommand.Wait));
                    nextShip1Position           = FastShipPosition.GetFinalPosition(FastShipPosition.Move(nextShip1Position, ShipMoveCommand.Slower));
                    strateg.decisions[ship1.id] = new StrategicDecision {
                        role = StrategicRole.Fire, fireToCoord = FastShipPosition.Coord(nextShip1Position)
                    };
                    strateg.decisions[ship2.id] = new StrategicDecision {
                        role = StrategicRole.Approach, targetCoord = FastShipPosition.Coord(nextShip1Position)
                    };
                }
            }
            else
            {
                var x = (FastCoord.GetX(ship1.fcoord) + FastCoord.GetX(ship2.fcoord)) / 2;
                var y = (FastCoord.GetY(ship1.fcoord) + FastCoord.GetY(ship2.fcoord)) / 2;
                if (x < 5)
                {
                    x = 5;
                }
                if (x > Constants.MAP_WIDTH - 6)
                {
                    x = Constants.MAP_WIDTH - 6;
                }
                if (y < 5)
                {
                    y = 5;
                }
                if (y > Constants.MAP_HEIGHT - 6)
                {
                    x = Constants.MAP_HEIGHT - 6;
                }

                strateg.decisions[ship1.id] = new StrategicDecision {
                    role = StrategicRole.Approach, targetCoord = FastCoord.Create(x, y)
                };
                strateg.decisions[ship2.id] = new StrategicDecision {
                    role = StrategicRole.Approach, targetCoord = FastCoord.Create(x, y)
                };
            }
        }
        public void MakeStrategicDecisions(TurnState turnState)
        {
            if (turnState.barrels.Any())
            {
                strateg.MakeStandardStrategicDecisions(turnState);
                return;
            }

            if (turnState.myShips.Max(s => s.rum) > turnState.enemyShips.Max(s => s.rum) || turnState.myShips.Min(s => s.rum) > 50)
            {
                foreach (var ship in turnState.myShips)
                {
                    StrategicDecision prevDecision;
                    strateg.decisions.TryGetValue(ship.id, out prevDecision);
                    strateg.decisions[ship.id] = strateg.RunAway(turnState, ship, prevDecision);
                }
                return;
            }

            if (turnState.myShips.Count == 1)
            {
                var ship = turnState.myShips[0];
                StrategicDecision prevDecision;
                strateg.decisions.TryGetValue(ship.id, out prevDecision);
                strateg.decisions[ship.id] = strateg.RunAway(turnState, ship, prevDecision);
                return;
            }

            var maxRum = turnState.myShips.Max(s => s.rum);
            var minRum = turnState.myShips.Min(s => s.rum);
            var ship1  = turnState.myShips.First(s => s.rum == minRum);
            var ship2  = turnState.myShips.Last(s => s.rum == maxRum);
            var last   = turnState.myShips.FirstOrDefault(s => s != ship1 && s != ship2);

            if (last != null)
            {
                StrategicDecision prevDecision;
                strateg.decisions.TryGetValue(last.id, out prevDecision);
                strateg.decisions[last.id] = strateg.RunAway(turnState, last, prevDecision);
            }

            if (FastCoord.Distance(ship1.fbow, ship2.fbow) <= 4)
            {
                StrategicDecision prevDecision;
                strateg.decisions.TryGetValue(ship1.id, out prevDecision);
                if (prevDecision?.role == StrategicRole.Fire || prevDecision?.role == StrategicRole.Explicit)
                {
                    strateg.decisions[ship1.id] = new StrategicDecision {
                        role = StrategicRole.Explicit, explicitCommand = ShipMoveCommand.Slower
                    };
                    strateg.decisions[ship2.id] = new StrategicDecision {
                        role = StrategicRole.Approach, targetCoord = prevDecision.fireToCoord
                    };
                }
                else
                {
                    var nextShip1Position = FastShipPosition.GetFinalPosition(FastShipPosition.Move(ship1.fposition, ShipMoveCommand.Wait));
                    nextShip1Position           = FastShipPosition.GetFinalPosition(FastShipPosition.Move(nextShip1Position, ShipMoveCommand.Slower));
                    strateg.decisions[ship1.id] = new StrategicDecision {
                        role = StrategicRole.Fire, fireToCoord = FastShipPosition.Coord(nextShip1Position)
                    };
                    strateg.decisions[ship2.id] = new StrategicDecision {
                        role = StrategicRole.Approach, targetCoord = FastShipPosition.Coord(nextShip1Position)
                    };
                }
            }
            else
            {
                var x = (FastCoord.GetX(ship1.fcoord) + FastCoord.GetX(ship2.fcoord)) / 2;
                var y = (FastCoord.GetY(ship1.fcoord) + FastCoord.GetY(ship2.fcoord)) / 2;
                if (x < 5)
                {
                    x = 5;
                }
                if (x > Constants.MAP_WIDTH - 6)
                {
                    x = Constants.MAP_WIDTH - 6;
                }
                if (y < 5)
                {
                    y = 5;
                }
                if (y > Constants.MAP_HEIGHT - 6)
                {
                    x = Constants.MAP_HEIGHT - 6;
                }

                strateg.decisions[ship1.id] = new StrategicDecision {
                    role = StrategicRole.Approach, targetCoord = FastCoord.Create(x, y)
                };
                strateg.decisions[ship2.id] = new StrategicDecision {
                    role = StrategicRole.Approach, targetCoord = FastCoord.Create(x, y)
                };
            }
        }
        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);
        }