Example #1
0
        public override void ProcessExternalInputWhileHeld(Vector3 inputPosition)
        {
            base.ProcessExternalInputWhileHeld(inputPosition);
            TorpedoAttack.Target target = new TorpedoAttack.Target();

            Board      board = Battle.main.defender.board;
            Vector3Int flatTileCoordinate = grid.GetFlatTileCoordinateAtPosition(inputPosition);

            if (!grid.GetTileAtPosition(inputPosition))
            {
                if (flatTileCoordinate.x >= 0 && flatTileCoordinate.x < board.tiles.GetLength(0))
                {
                    target.torpedoDropPoint = board.tiles[flatTileCoordinate.x, flatTileCoordinate.z > 0 ? board.tiles.GetLength(1) - 1 : 0];
                    target.torpedoHeading   = Vector2Int.up * (flatTileCoordinate.z > 0 ? -1 : 1);
                }
                else if (flatTileCoordinate.z >= 0 && flatTileCoordinate.z < board.tiles.GetLength(1))
                {
                    target.torpedoDropPoint = board.tiles[flatTileCoordinate.x > 0 ? board.tiles.GetLength(0) - 1 : 0, flatTileCoordinate.z];
                    target.torpedoHeading   = Vector2Int.right * (flatTileCoordinate.x > 0 ? -1 : 1);
                }
            }

            if (effect == null)
            {
                if (target.torpedoDropPoint != null && target.torpedoHeading != Vector2Int.zero)
                {
                    effect                = Effect.CreateEffect(typeof(TorpedoAttack));
                    effect.visibleTo      = Battle.main.attacker;
                    effect.targetedPlayer = Battle.main.defender;
                }
                else
                {
                    hookedPosition = Utilities.GetPositionOnElevationFromPerspective(inputPosition, Camera.main.transform.position, pickupPosition.y).projectedPosition;
                }
            }

            if (effect != null)
            {
                TorpedoAttack attack = effect as TorpedoAttack;
                if (target.torpedoDropPoint != null && target.torpedoHeading != Vector2Int.zero)
                {
                    if (target != attack.target)
                    {
                        attack.target = target;
                        RefreshEffectRepresentation();
                    }
                }
                else
                {
                    Destroy(attack.gameObject);
                    effect = null;
                }
            }
        }
Example #2
0
        static void FightFor(Player player)
        {
            Player attacked_player = Battle.main.attacker == player ? Battle.main.defender : Battle.main.attacker;
            Map    map             = new Map(attacked_player.board);

            float[,] priority_map = map.ratings.Normalize();

            float advantage             = player.board.ships.Sum(x => x.health) / (float)attacked_player.board.ships.Sum(x => x.health > 0 ? x.maxHealth : 0);
            int   prefered_torpedocount = Mathf.FloorToInt(Mathf.Clamp(player.arsenal.torpedoes, 0, player.arsenal.loadedTorpedoCap) * ((Mathf.Cos(advantage * Mathf.PI) + 1.0f) / 2.0f));

            int gun_targetcount      = player.arsenal.guns;
            int torpedo_targetcount  = player.arsenal.loadedTorpedoes >= prefered_torpedocount || player.arsenal.loadedTorpedoes == player.arsenal.torpedoes ? prefered_torpedocount : 0;
            int aircraft_targetcount = Mathf.CeilToInt(Mathf.Clamp(player.arsenal.aircraft - Battle.main.effects.Count(x => x is AircraftRecon && x.visibleTo == player), 0, int.MaxValue) * priority_map.Average());

            int cyclone_size = Battle.main.effects.Exists(x => x is Cyclone) ? (Battle.main.effects.Find(x => x is Cyclone) as Cyclone).maximumTileSpacingToTakeEffect * 2 : 0;

            for (int ti = 0; ti < gun_targetcount; ti++)
            {
                Vector2Int target = priority_map.Max();

                ArtilleryAttack attack = Effect.CreateEffect(typeof(ArtilleryAttack)) as ArtilleryAttack;
                attack.target = attacked_player.board.tiles[target.x, target.y];

                attack.visibleTo      = player;
                attack.targetedPlayer = attacked_player;

                Effect.AddToStack(attack);

                if (cyclone_size > 0)
                {
                    priority_map = priority_map.AddHeat(target, dist => dist <= cyclone_size ? 0.1f : 1.0f, (original, function) => original * function);
                }
                else
                {
                    priority_map = priority_map.AddHeat(target, dist => 1 - Mathf.Pow(0.5f, dist), (original, function) => original * function);
                }
            }

            for (int ti = 0; ti < torpedo_targetcount; ti++)
            {
                float best_lane_rating           = Mathf.NegativeInfinity;
                TorpedoAttack.Target best_target = new TorpedoAttack.Target();

                for (int i = 0; i < 4; i++)
                {
                    for (int a = 0; a < priority_map.GetLength(i % 2); a++)
                    {
                        float rating = 0;
                        for (int b = 0; b < priority_map.GetLength((i + 1) % 2) / 2; b++)
                        {
                            int x = i % 2 == 0 ? a : (i == 1 ? b : priority_map.GetLength(0) - b - 1);
                            int y = i % 2 == 1 ? a : (i == 0 ? b : priority_map.GetLength(1) - b - 1);

                            rating += priority_map[x, y];
                        }

                        if (rating > best_lane_rating)
                        {
                            best_lane_rating = rating;

                            best_target.torpedoDropPoint = attacked_player.board.tiles[i % 2 == 0 ? a : (i == 1 ? 0 : (priority_map.GetLength(0) - 1)), i % 2 == 1 ? a : (i == 0 ? 0 : (priority_map.GetLength(1) - 1))];
                            best_target.torpedoHeading   = new Vector2Int((2 - i) % 2, (1 - i) % 2);
                        }
                    }
                }

                TorpedoAttack attack = Effect.CreateEffect(typeof(TorpedoAttack)) as TorpedoAttack;
                attack.target = best_target;

                attack.visibleTo      = player;
                attack.targetedPlayer = attacked_player;

                Effect.AddToStack(attack);

                float average = priority_map.Average();
                priority_map = priority_map.AddHeat(best_target.torpedoDropPoint.coordinates, dist => 1 - Mathf.Pow(0.5f, dist), (original, function) => original * function);
            }

            for (int ti = 0; ti < aircraft_targetcount; ti++)
            {
                float best_line_rating = Mathf.NegativeInfinity;
                int   best_line        = 0;
                int   line_count       = attacked_player.board.tiles.GetLength(0) + attacked_player.board.tiles.GetLength(1) - 2;

                for (int line = 0; line < line_count; line++)
                {
                    int   line_position = line % (attacked_player.board.tiles.GetLength(0) - 1);
                    bool  lineVertical  = line_position == line;
                    float line_rating   = 0;

                    for (int a = 0; a < 2; a++)
                    {
                        for (int b = 0; b < attacked_player.board.tiles.GetLength(lineVertical ? 1 : 0); b++)
                        {
                            int x = lineVertical ? a + line_position : b;
                            int y = lineVertical ? b : a + line_position;
                            line_rating += priority_map[x, y];
                        }
                    }

                    if (line_rating > best_line_rating)
                    {
                        best_line        = line;
                        best_line_rating = line_rating;
                    }
                }

                AircraftRecon recon = Effect.CreateEffect(typeof(AircraftRecon)) as AircraftRecon;
                recon.target = best_line;

                recon.visibleTo      = player;
                recon.targetedPlayer = attacked_player;

                Effect.AddToStack(recon);

                bool line_vertical = best_line < attacked_player.board.tiles.GetLength(0);
                best_line %= attacked_player.board.tiles.GetLength(0) - 1;

                for (int a = 0; a < 2; a++)
                {
                    for (int b = 0; b < attacked_player.board.tiles.GetLength(line_vertical ? 1 : 0); b++)
                    {
                        int x = line_vertical ? a + best_line : b;
                        int y = line_vertical ? b : a + best_line;
                        priority_map[x, y] = 0;
                    }
                }
            }
        }