예제 #1
0
파일: AI.cs 프로젝트: PistaMista/Polyships
        public static float[,] GetPreferredMap(this Ship ship)
        {
            float[,] map = new float[ship.parentBoard.tiles.GetLength(0), ship.parentBoard.tiles.GetLength(1)];

            for (int i = 0; i < 2; i++)
            {
                map = map.AddHeat
                          (new Vector2Int(UnityEngine.Random.Range(0, map.GetLength(0)), UnityEngine.Random.Range(0, map.GetLength(1))),
                          dist => Mathf.Pow(0.85f, dist));
            }

            return(map);
        }
예제 #2
0
파일: AI.cs 프로젝트: PistaMista/Polyships
            public Map(Board board)
            {
                ratings = new float[board.tiles.GetLength(0), board.tiles.GetLength(1)];

                tiles = new Tile[board.tiles.GetLength(0), board.tiles.GetLength(1)];

                float[,] gaussian_map  = new float[board.tiles.GetLength(0), board.tiles.GetLength(1)];
                bool[,] permablock_map = new bool[tiles.GetLength(0), tiles.GetLength(1)];

                for (int x = 0; x < tiles.GetLength(0); x++)
                {
                    for (int y = 0; y < tiles.GetLength(1); y++)
                    {
                        Gameplay.Tile tile = board.tiles[x, y];
                        if (tile.hit)
                        {
                            if (tile.containedShip != null)
                            {
                                bool shipInTileDestroyed = tile.containedShip.health <= 0;
                                permablock_map[x, y] = shipInTileDestroyed;
                                for (int i = 0; i < 8; i += shipInTileDestroyed ? 1 : 2)
                                {
                                    int x_toblock = x + Math.Sign((i - 1) * (5 - i));
                                    int y_toblock = y + Math.Sign((3 - i) * (7 - i));
                                    if (x_toblock >= 0 && x_toblock < permablock_map.GetLength(0) && y_toblock >= 0 && y_toblock < permablock_map.GetLength(1))
                                    {
                                        permablock_map[x_toblock, y_toblock] = true;
                                    }
                                }

                                gaussian_map = gaussian_map.AddHeat(tile.coordinates, dist => Mathf.Pow(0.4f, dist) * 3.0f);

                                Gameplay.Tile[] neighbours = new Gameplay.Tile[4];
                                for (int i = 0; i < 4; i++)
                                {
                                    int nx = x + (1 - i) % 2;
                                    int ny = y + (2 - i) % 2;
                                    if (nx >= 0 && nx < tiles.GetLength(0) && ny >= 0 && ny < tiles.GetLength(1))
                                    {
                                        neighbours[i] = board.tiles[nx, ny];
                                    }
                                }

                                int hit_neighbours = neighbours.Count(c => c != null && c.hit && c.containedShip != null);

                                if (hit_neighbours == 0)
                                {
                                    for (int i = 0; i < 4; i++)
                                    {
                                        Gameplay.Tile neighbour = neighbours[i];
                                        if (neighbour != null)
                                        {
                                            tiles[neighbour.coordinates.x, neighbour.coordinates.y].importance = 2.0f;
                                        }
                                    }
                                }
                                else if (hit_neighbours == 1)
                                {
                                    for (int i = 0; i < 4; i++)
                                    {
                                        Gameplay.Tile neighbour = neighbours[i];
                                        if (neighbour != null && neighbour.hit && neighbour.containedShip != null)
                                        {
                                            Gameplay.Tile opposite = neighbours[(i + 2) % 4];
                                            if (opposite != null)
                                            {
                                                tiles[opposite.coordinates.x, opposite.coordinates.y].importance = 3.5f;
                                            }
                                            break;
                                        }
                                    }
                                }
                            }
                            else
                            {
                                gaussian_map         = gaussian_map.AddHeat(tile.coordinates, dist => Mathf.Pow(0.3f, dist) * UnityEngine.Random.Range(-3.0f, 0.5f));
                                permablock_map[x, y] = true;
                            }
                        }
                    }
                }

                AircraftRecon[] recon = Array.ConvertAll(Battle.main.effects.Where(x => x is AircraftRecon && x.targetedPlayer == board.owner).ToArray(), x => x as AircraftRecon);

                for (int i = 0; i < recon.Length; i++)
                {
                    int  result        = recon[i].result;
                    int  line          = recon[i].target;
                    int  line_position = line % (board.tiles.GetLength(0) - 1);
                    bool line_vertical = line == line_position;

                    int start = result > 0 ? line_position + 1 : 0;
                    int end   = result > 0 ? board.tiles.GetLength(line_vertical ? 0 : 1) : line_position + 1;

                    for (int a = start; a < end; a++)
                    {
                        for (int b = 0; b < board.tiles.GetLength(line_vertical ? 1 : 0); b++)
                        {
                            int x = line_vertical ? a : b;
                            int y = line_vertical ? b : a;
                            gaussian_map[x, y] *= 1.5f;
                        }
                    }
                }

                gaussian_map = gaussian_map.Normalize();
                tiles.InjectArray(gaussian_map, (ref Tile a, float b) => a.gauss = b);

                int[,] space_map = new int[board.tiles.GetLength(0), board.tiles.GetLength(1)];

                for (int i = 0; i < 2; i++)
                {
                    for (int a = 0; a < tiles.GetLength(i); a++)
                    {
                        int sequence_start = 0;
                        int sequence       = 0;
                        for (int b = 0; b < tiles.GetLength(1 - i); b++)
                        {
                            int  x            = i == 0 ? a : b;
                            int  y            = i == 0 ? b : a;
                            bool permablocked = permablock_map[x, y];

                            if (!permablocked)
                            {
                                if (sequence == 0)
                                {
                                    sequence_start = b;
                                }
                                sequence++;
                            }

                            if (b == tiles.GetLength(1 - i) - 1 || permablocked)
                            {
                                for (int depth = 0; depth < sequence; depth++)
                                {
                                    Vector2Int pos = new Vector2Int(i == 0 ? a : sequence_start + depth, i == 0 ? sequence_start + depth : a);
                                    if (sequence > space_map[pos.x, pos.y] && !board.tiles[pos.x, pos.y].hit)
                                    {
                                        space_map[pos.x, pos.y] = sequence;
                                    }
                                }
                                sequence = 0;
                            }
                        }
                    }
                }

                tiles.InjectArray(space_map, (ref Tile x, int y) => x.possibleShips = board.ships.Where(ship => ship.health > 0 && ship.maxHealth <= y).ToArray());

                int combined_ship_health = board.ships.Sum(ship => ship.health > 0 ? ship.maxHealth : 0);

                for (int x = 0; x < ratings.GetLength(0); x++)
                {
                    for (int y = 0; y < ratings.GetLength(1); y++)
                    {
                        Tile tile = tiles[x, y];
                        ratings[x, y] = (tile.importance + tile.gauss) * (tile.possibleShips.Sum(ship => ship.maxHealth) / (float)combined_ship_health);
                    }
                }
            }