コード例 #1
0
        public static void Main(string[] args)
        {
            MAP_SIZE = Math.Max(game.gameMap.width, game.gameMap.height);
            SHIP_RETURN_THRESHOLD     = 950;
            HIGH_HALITE_AREA_MAX      = MAP_SIZE / 4;
            HIGH_HALITE_AREA_DISTANCE = 10;
            MIN_HALITE_MOVE           = 50;

            game.Ready("zluhcsh3");

            Log.enabled = false;

            mission_control = new MissionControl(game);

            var combat = new Combat(game);

            while (true)
            {
                game.UpdateFrame();
                Log.StartTimeTrack();

                Player  me      = game.me;
                GameMap gameMap = game.gameMap;

                if (game.turnNumber == 1)
                {
                    gameMap.InitCombatAreas();
                }

                commandQueue.Clear();

                Log.StartSection("Clear enemy ships around shipyard/dropoffs");
                ClearEnemies(me.shipyard.position);
                foreach (var dropoff in me.dropoffs.Values)
                {
                    ClearEnemies(dropoff.position);
                }
                Log.EndSection();

                Log.StartSection("Update or Delete completed missions");
                var delete = new List <int>();
                foreach (var mission in mission_control.Missions.Values)
                {
                    if (me.ships.ContainsKey(mission.ShipId))
                    {
                        var ship = me.ships[mission.ShipId];
                        if (ship.position.Equals(mission.Target))
                        {
                            delete.Add(mission.ShipId);
                        }
                        mission.Distance = gameMap.CalculateDistance(ship.position, mission.Target);
                    }
                    else
                    {
                        // ship does not exist anymore
                        Log.LogMessage("remove mission: " + mission.ShipId);
                        delete.Add(mission.ShipId);
                    }
                }
                foreach (var shipid in delete)
                {
                    mission_control.Missions.Remove(shipid);
                }
                Log.EndSection();

                Log.StartSection("Send ships back before game ends.");
                if (game.turnNumber + MAP_SIZE >= Constants.MAX_TURNS)
                {
                    IsEndGamePhase = true;
                    Log.LogMessage("ENDGAME: turn#: " + game.turnNumber + " MAX_TURNS: " + Constants.MAX_TURNS + " MAP_SIZE: " + MAP_SIZE);
                    foreach (var ship in me.ships.Values)
                    {
                        if (mission_control.ShipIsReturning(ship))
                        {
                            continue;
                        }
                        var distance_shipyard = gameMap.CalculateDistance(gameMap.GetClosestDropoff(me, ship.position), ship.position);
                        var remaining_turns   = Constants.MAX_TURNS - game.turnNumber;
                        if (distance_shipyard < remaining_turns && distance_shipyard + 10 > remaining_turns)
                        {
                            Log.LogMessage("ENDGAME: return ship: " + ship + " DistYard: " + distance_shipyard + " Remaining Turns: " + remaining_turns);
                            mission_control.CancelMission(ship);
                            mission_control.AddReturnMission(ship);
                        }
                    }
                }
                Log.EndSection();

                Log.StartSection("Combat");
                combat.EvaluateCombatAreas();
                foreach (var ship in me.ships.Values)
                {
                    if (ship.make_combat_best_move == false)
                    {
                        continue;
                    }
                    MakeMove("Combat_Move", ship, ship.best_move, true);
                }
                Log.EndSection();

                Log.StartSection("Prepare new missions");
                var dropoff_candidates = new List <int>();
                int dropoff_distance   = MAP_SIZE / 4;

                var available_for_collection = new List <Ship>();

                foreach (var ship in me.ships.Values)
                {
                    if (ship.moved)
                    {
                        continue;
                    }
                    if (gameMap.CalculateDistance(gameMap.GetClosestDropoff(me, ship.position), ship.position) >= dropoff_distance)
                    {
                        dropoff_candidates.Add(ship.id.id);
                    }
                    if (mission_control.ShipIsReturning(ship))
                    {
                        continue;
                    }
                    if (ship.halite >= SHIP_RETURN_THRESHOLD)
                    {
                        mission_control.CancelMission(ship);
                        mission_control.AddReturnMission(ship);
                    }
                    else
                    {
                        // Ships available for halite collection, always re-assing collection mission.
                        mission_control.CancelMission(ship);
                        available_for_collection.Add(ship);
                    }
                }
                Log.EndSection();

                Log.StartSection("Create Dropoffs");
                // Create Dropoff
                int dropoff_ships = me.ships.Count / 8;
                if (MAP_SIZE >= 56)
                {
                    dropoff_ships = me.ships.Count / 10;
                }
                int dropoff_max = 1;
                if (MAP_SIZE == 48)
                {
                    dropoff_max = 2;
                }
                if (MAP_SIZE == 56)
                {
                    dropoff_max = 4;
                }
                if (MAP_SIZE == 64)
                {
                    dropoff_max = 5;
                }
                if (game.players.Count == 4)
                {
                    dropoff_max--;
                    if (MAP_SIZE == 64)
                    {
                        dropoff_max--;
                    }
                }
                if (me.halite >= (Constants.DROPOFF_COST + Constants.SHIP_COST) && me.dropoffs.Count < dropoff_max && dropoff_candidates.Count >= dropoff_ships)
                {
                    var  largest_halite = 0;
                    Ship dropoff_ship   = null;
                    foreach (var id in dropoff_candidates)
                    {
                        var ship = me.ships[id];
                        if (gameMap.CalculateDistance(ship.position, gameMap.GetClosestDropoff(me, ship.position)) < dropoff_distance + 2)
                        {
                            continue;
                        }
                        var halite = gameMap.CalculateHaliteForDropoff(ship.position, MAP_SIZE / 4);
                        if (halite > largest_halite)
                        {
                            largest_halite = halite;
                            dropoff_ship   = ship;
                        }
                    }
                    var create_dropoff = true;
                    if (MAP_SIZE == 32 && game.players.Count == 2 && largest_halite < 30000)
                    {
                        create_dropoff = false;
                    }
                    if (MAP_SIZE == 40 && game.players.Count == 2 && largest_halite < 32000)
                    {
                        create_dropoff = false;
                    }
                    if (MAP_SIZE == 48 && game.players.Count == 2 && largest_halite < 34000)
                    {
                        create_dropoff = false;
                    }
                    if (dropoff_ship != null && create_dropoff)
                    {
                        commandQueue.Add(dropoff_ship.MakeDropoff());
                        gameMap.UpdateDropoffCoverage(dropoff_ship.position, MAP_SIZE / 4);
                        me.ships.Remove(dropoff_ship.id.id);
                        mission_control.CancelMission(dropoff_ship);
                        if (available_for_collection.Contains(dropoff_ship))
                        {
                            available_for_collection.Remove(dropoff_ship);
                        }
                    }
                }
                Log.EndSection();

                Log.StartSection("Assign halite collection to ships");
                var high_value_positions = game.gameMap.GetHighValuePositions(me.shipyard, 10 + game.turnNumber / 10, available_for_collection.Count * 20);

                // Send availble ships to closest halite areas
                var ship_area_distance_list = new List <HighAreaDistance>();

                foreach (var high_area_position in high_value_positions)
                {
                    foreach (var ship in available_for_collection)
                    {
                        if (ship.moved)
                        {
                            continue;
                        }
                        if (IsEndGamePhase && gameMap.At(ship.position).HasStructure())
                        {
                            if (gameMap.At(ship.position).structure.owner.id == me.id.id)
                            {
                                continue;
                            }
                        }
                        int ship_halite_distance    = gameMap.CalculateDistance(ship.position, high_area_position);
                        int halite_dropoff_distance = gameMap.CalculateDistance(high_area_position, gameMap.GetClosestDropoff(me, high_area_position));

                        int halite_to_collect = Constants.MAX_HALITE - ship.halite;
                        int available_halite  = gameMap.At(high_area_position).halite;
                        int collected_halite  = 0;
                        int turns_to_collect  = 0;
                        var is_inspired       = gameMap.IsInpiredPosition(me, high_area_position);

                        while (halite_to_collect > 0 && collected_halite < halite_to_collect && available_halite > 0)
                        {
                            int collected_this_turn = (int)(available_halite / Constants.EXTRACT_RATIO);
                            if (collected_this_turn <= 0)
                            {
                                break;
                            }
                            available_halite -= collected_this_turn;
                            if (is_inspired)
                            {
                                collected_this_turn *= 3;
                            }
                            collected_halite += collected_this_turn;
                            turns_to_collect += 1;
                        }

                        double value = (double)collected_halite / (double)(turns_to_collect + ship_halite_distance + halite_dropoff_distance);
                        if (game.players.Count == 4 && is_inspired)
                        {
                            value *= 3;
                        }

                        ship_area_distance_list.Add(new HighAreaDistance(ship, high_area_position, value));
                    }
                }

                var closest_area_list = ship_area_distance_list.OrderByDescending(sad => sad.Value).ToList <HighAreaDistance>();

                var created_collect_mission_count = 0;
                foreach (var closest_distance in closest_area_list)
                {
                    var high_area_position = closest_distance.AreaPosition;
                    if (mission_control.ThereIsMissiontToTarget(high_area_position))
                    {
                        continue;
                    }
                    var closest_ship = gameMap.At(closest_distance.ShipPosition).ship;
                    if (mission_control.Missions.ContainsKey(closest_ship.id.id))
                    {
                        continue;
                    }
                    mission_control.AddCollectMission(closest_ship, high_area_position);
                    created_collect_mission_count++;
                }

                Log.EndSection();

                Log.StartSection("Move execution");
                var priority_missions = mission_control.Missions.Values.OrderBy(m => m.Distance);

                foreach (var mission in priority_missions)
                {
                    if (!me.ships.ContainsKey(mission.ShipId))
                    {
                        continue;
                    }

                    var ship   = me.ships[mission.ShipId];
                    var target = mission.Target;

                    if (ship.moved)
                    {
                        continue;
                    }

                    if (!gameMap.CanMove(ship))
                    {
                        commandQueue.Add(ship.StayStill());
                        continue;
                    }

                    if (mission.IsReturning())
                    {
                        path_finder.SearchPath(ship.owner.id, ship.position, target, 1);
                        var path = path_finder.GetPath(target);
                        if (!IsEndGamePhase)
                        {
                            if (path.Count() < 2 || gameMap.At(path[1]).IsOccupied(me.id.id))
                            {
                                commandQueue.Add(ship.StayStill());
                                continue;
                            }
                        }
                        if (path.Count > 1)
                        {
                            var return_direction = gameMap.GetDirection(ship.position, path[1]);
                            MakeMove("return_ship", ship, return_direction, false);
                        }
                        else
                        {
                            commandQueue.Add(ship.StayStill());
                        }
                        continue;
                    }
                    else
                    {
                        if (gameMap.At(ship.position).halite > Zluhcsh3.MIN_HALITE_MOVE)
                        {
                            commandQueue.Add(ship.StayStill());
                            continue;
                        }
                        if (detour_next_move.ContainsKey(ship.id.id))
                        {
                            var continuation_direction = detour_next_move[ship.id.id];
                            MakeMove("cont_detour", ship, continuation_direction, false);
                            detour_next_move.Remove(ship.id.id);
                            continue;
                        }
                        var direction = gameMap.GetClosestDirection(ship, target);
                        if (direction != Direction.STILL)
                        {
                            var position_to_move = gameMap.GetTargetPosition(ship.position, direction);
                            if (HasBlockingShip(ship.owner.id, position_to_move) || BlockReturningShips(ship, direction))
                            {
                                var detour_direction = SelectDetour(ship, direction, target);
                                MakeMove("detour", ship, detour_direction, false);
                                continue;
                            }
                            MakeMove("collect", ship, direction, false);
                            continue;
                        }
                        commandQueue.Add(ship.StayStill());
                        continue;
                    }
                }
                Log.EndSection();

                Log.StartSection("Resolve pending moves");
                foreach (var ship in me.ships.Values)
                {
                    if (ship.pending == Direction.STILL || ship.moved)
                    {
                        continue;
                    }

                    var target = gameMap.GetTargetPosition(ship.position, ship.pending);

                    var other_ship = gameMap.At(target).ship;
                    if (other_ship == null)
                    {
                        commandQueue.Add(ship.Move(ship.pending));
                        gameMap.At(ship.position).ship = null;
                        gameMap.At(target).MarkUnsafe(ship);
                        continue;
                    }

                    if (other_ship.moved || other_ship.pending == Direction.STILL)
                    {
                        commandQueue.Add(ship.StayStill());
                        continue;
                    }

                    var other_target = gameMap.GetTargetPosition(other_ship.position, other_ship.pending);
                    if (other_target.Equals(ship.position))
                    {
                        commandQueue.Add(ship.Move(ship.pending));
                        gameMap.At(target).MarkUnsafe(ship);
                        commandQueue.Add(other_ship.Move(other_ship.pending));
                        gameMap.At(other_target).MarkUnsafe(other_ship);
                        continue;
                    }

                    if (gameMap.At(other_target).ship == null)
                    {
                        commandQueue.Add(other_ship.Move(other_ship.pending));
                        gameMap.At(other_ship.position).ship = null;
                        gameMap.At(other_target).MarkUnsafe(other_ship);
                        commandQueue.Add(ship.Move(ship.pending));
                        gameMap.At(ship.position).ship = null;
                        gameMap.At(target).MarkUnsafe(ship);
                        continue;
                    }
                }
                Log.EndSection();

                if (Log.enabled)
                {
                    Log.StartSection("DEV: Verify ships with no mission");
                    foreach (var ship in me.ships.Values)
                    {
                        if (!mission_control.ShipHasMission(ship))
                        {
                            Log.LogMessage("ERROR: ship missing mission: " + ship);
                        }
                    }
                    Log.EndSection();
                }

                Log.StartSection("Spawn new ships");

                var completed_turns_percent = (double)game.turnNumber / (double)Constants.MAX_TURNS * 100.0;
                var my_ships_count          = Math.Max(1, me.ships.Count);


                // Spawn new ships if necessary. If there's an enemy blocking it will spawn and destroy it.
                if (completed_turns_percent < 60 && gameMap.GetTotalHalite() / game.players.Count / my_ships_count > 1500)
                {
                    if (me.halite >= Constants.SHIP_COST && (gameMap.At(me.shipyard).ship == null || gameMap.At(me.shipyard).ship.owner.id != me.id.id))
                    {
                        commandQueue.Add(me.shipyard.Spawn());
                    }
                }
                Log.EndSection();

                // Output commands.
                game.EndTurn(commandQueue);
            }
        }