Esempio n. 1
0
    private static void singleValidation(DungeonLayout layout, int id)
    {
        TestLogger.log("validating layout - id: " + id);

        if (layout == null)
        {
            throw new DungeonLayoutNotAvailableException("DungeonDispatcher returned NULL for layout id: " + id);
        }
        if (layout.grid == null)
        {
            throw new WrongLayoutDeclarationException("layout.grid is NULL. layout id: " + id);
        }
        if (layout.rooms == null)
        {
            throw new WrongLayoutDeclarationException("layout.rooms is NULL. layout id: " + id);
        }
        if (layout.pathableAreas == null)
        {
            throw new WrongLayoutDeclarationException("layout.pathableAreas is NULL. layout id: " + id);
        }

        foreach (PseudoRoom room in layout.rooms)
        {
            checkRoom(layout, room);
        }
        foreach (PathableArea area in layout.pathableAreas)
        {
            checkArea(layout, area);
        }

        TestLogger.log("validated");
        TestLogger.log("");
    }
Esempio n. 2
0
    public Dungeon generateDungeon(Random rand, int seed)
    {
        //LATER_PATCH: pick dungeon type

        //scegli layout
        DungeonLayout layout = DungeonDispatcher.getDungeonLayoutById((rand.Next() % Constants.LAYOUTS_COUNT) + 1);

        //scegli stanze
        List <DungeonRoom> rooms = new List <DungeonRoom>();

        foreach (PseudoRoom room in layout.rooms)
        {
            DungeonRoom pickedRoom = DungeonDispatcher.getDungeonRoomByType(room.sizeX, room.sizeY, rand.Next(), rand);
            layout.grid.paste(pickedRoom.grid, room.position);
            rooms.Add(pickedRoom);
        }

        //crea percorsi
        PathLinkingStrategy pathLinker = new ClosestPathLinker();         //LATER_PATCH: decide which srtategy to use

        pathLinker.linkPaths(layout, rand);
        layout.grid.normalize();

        //inserisci tesori
        List <Treasure> treasures = new List <Treasure>();

        foreach (DungeonRoom room in rooms)
        {
            foreach (Treasure treasure in room.treasures)
            {
                treasures.Add(TreasureInitializer.initializeTreasure(treasure, rand));
            }
        }

        List <Coordinates> culDeSacs = layout.grid.getCulDeSacs();

        foreach (Coordinates culDeSac in culDeSacs)
        {
        }
        int antiChances = Constants.TREASURE_SPAWN_PERIOD;

        foreach (Coordinates point in culDeSacs)
        {
            if (rand.Next() % antiChances == 0)
            {
                layout.grid.put(point, Constants.TREASURE_MARKER);
                treasures.Add(TreasureInitializer.initializeTreasure(new Treasure(point), rand));
                antiChances = Constants.TREASURE_SPAWN_PERIOD + (treasures.Count * Constants.TREASURE_SPAWN_INCREMENTAL);
            }
            else
            {
                antiChances -= Constants.TREASURE_SPAWN_INCREMENTAL;
            }
        }

        //LATER_PATCH: add traps

        return(new Dungeon(layout.grid, rooms, treasures, seed /*LATER_PATCH: , traps*/));
    }
        private bool VerifyMobSpawners(
            DungeonLayout layout)
        {
            bool success = true;


            for (DungeonLayout.RoomIndexIterator iterator = new DungeonLayout.RoomIndexIterator(layout.RoomGrid);
                 iterator.Valid;
                 iterator.Next())
            {
                DungeonLayout.RoomIndex roomIndex = iterator.Current;
                Room         room         = layout.GetRoomByIndex(roomIndex);
                RoomTemplate roomTemplate =
                    layout.LayoutRoomTemplateSet.GetTemplateByName(room.static_room_data.room_template_name);

                // We don't add the mob spawner to the room if we create it
                // and it doesn't have any mobs left (spawner initially has 0 mobs.
                // TODO: Add this check back in when we support non-zero min spawn count
                //if (roomTemplate.MobSpawnerTemplates.Count() != room.mobSpawners.Count)
                //{
                //    _logger.WriteLine("DungeonValidator: FAILED: Mob spawner template count != mob spawner count");
                //    _logger.WriteLine(string.Format("  game_id: {0}", layout.GameID));
                //    _logger.WriteLine(string.Format("  room_key: {0},{1},{2}",
                //        room.room_key.x, room.room_key.y, room.room_key.z));
                //    success = false;
                //    break;
                //}

                foreach (MobSpawner spawner in room.mobSpawners)
                {
                    if (spawner.SpawnTable == null)
                    {
                        _logger.WriteLine("DungeonValidator: FAILED: Mob spawner missing spawn table!");
                        _logger.WriteLine(string.Format("  game_id: {0}", layout.GameID));
                        _logger.WriteLine(string.Format("  room_key: {0},{1},{2}",
                                                        room.room_key.x, room.room_key.y, room.room_key.z));
                        success = false;
                        break;
                    }

                    while (spawner.RemainingSpawnCount > 0)
                    {
                        Mob mob = spawner.SpawnRandomMob();

                        if (mob == null)
                        {
                            _logger.WriteLine("DungeonValidator: FAILED: Mob spawner failed to produce valid mob!");
                            _logger.WriteLine(string.Format("  game_id: {0}", layout.GameID));
                            _logger.WriteLine(string.Format("  room_key: {0},{1},{2}",
                                                            room.room_key.x, room.room_key.y, room.room_key.z));
                            success = false;
                            break;
                        }
                    }
                }
            }

            return(success);
        }
Esempio n. 4
0
        public DungeonLayout Generate(int width, int height)
        {
            DungeonLayout dungeonLayout = new DungeonLayout(width, height);

            dungeonLayout = GenerateMainPath(dungeonLayout);

            return(dungeonLayout);
        }
Esempio n. 5
0
 public override void linkPaths(DungeonLayout layout, Random rand)
 {
     foreach (PathableArea area in layout.pathableAreas)
     {
         shufflePaths(layout.grid, area, rand);
         recursiveMergePaths(layout.grid, area, rand);
     }
 }
Esempio n. 6
0
    // Start is called before the first frame update
    void Start()
    {
        layout = new DungeonLayout(10, 4);
        RoomIdentifier[] identifiers = layout.GetRoomTypes();

        foreach (RoomIdentifier i in identifiers)
        {
            createRoom(i);
        }
    }
    //Level Creation Methods

    //Picks an element for the Level, Creates the map, Creates a Dungeon Layout, and sets the initial game state for that level
    void CreateDungeonLevel()
    {
        currentLevelElement = GetNextElement();         //set the initial element for this dungeon level
        HUDCanvas.transform.FindChild("CurrentLevel").GetComponent <UnityEngine.UI.Text>().text = "Level " + round;
        DungeonLayoutGenerator.S.CreateLevelMap();
        DungeonLayout DL = DungeonLayoutGenerator.S.levelLayout.GetComponent <DungeonLayout> ();

        LoadingScreenCanvas.SetActive(false);

        created = true;
    }
Esempio n. 8
0
        private bool IsLeftRightAvailable(DungeonLayout roomLayout, RoomInfo previousRoom, int axis)
        {
            bool outOfBoundary = (previousRoom.x + axis >= roomLayout.width || previousRoom.x + axis < 0);

            if (!outOfBoundary)
            {
                return(roomLayout.layout[previousRoom.x + axis, previousRoom.y].roomState == RoomInfo.RoomState.Other);
            }

            return(false);
        }
Esempio n. 9
0
 private static void checkRoom(DungeonLayout layout, PseudoRoom room)
 {
     for (int x = room.position.x; x < room.sizeX + room.position.x; x++)
     {
         for (int y = room.position.y; y < room.sizeY + room.position.y; y++)
         {
             if (layout.grid.grid [x, y] != Constants.PSEUDO_ROOM_MARKER)
             {
                 throw new WrongLayoutDeclarationException("PseudoRoom declaration error. position: " + room.position.x + "," + room.position.y);
             }
         }
     }
 }
Esempio n. 10
0
 private static void checkArea(DungeonLayout layout, PathableArea area)
 {
     for (int x = area.position.x; x < area.sizeX + area.position.x; x++)
     {
         for (int y = area.position.y; y < area.sizeY + area.position.y; y++)
         {
             if (layout.grid.grid [x, y] != Constants.PATHABLE_MARKER)
             {
                 throw new WrongLayoutDeclarationException("PathableArea declaration error. position: " + area.position.x + "," + area.position.y);
             }
         }
     }
 }
Esempio n. 11
0
        private DungeonLayout GenerateMainPath(DungeonLayout dungeonLayout)
        {
            //Start from First Row
            int randX = (Random.Range(0, dungeonLayout.width));

            dungeonLayout.layout[randX, dungeonLayout.height - 1]           = new RoomInfo(randX, dungeonLayout.height - 1);
            dungeonLayout.layout[randX, dungeonLayout.height - 1].roomState = RoomInfo.RoomState.StartPoint;

            RoomInfo lastRoom = dungeonLayout.layout[randX, dungeonLayout.height - 1];

            while (true)
            {
                MoveDir nextMove = FindNextRoom(dungeonLayout, lastRoom);

                dungeonLayout.layout[lastRoom.x, lastRoom.y].previousIndex = new Vector2Int(lastRoom.x, lastRoom.y);

                if (nextMove == MoveDir.End)
                {
                    dungeonLayout.layout[lastRoom.x, lastRoom.y].roomState = RoomInfo.RoomState.EndPoint;
                    break;
                }

                int dirX = lastRoom.x, dirY = lastRoom.y;

                if (nextMove == MoveDir.Down)
                {
                    dirY -= 1;
                }

                if (nextMove == MoveDir.Left || nextMove == MoveDir.Right)
                {
                    dirX += ((nextMove == MoveDir.Left) ? -1 : 1);
                }

                dungeonLayout.layout[dirX, dirY]           = new RoomInfo(dirX, dirY);
                dungeonLayout.layout[dirX, dirY].roomState = RoomInfo.RoomState.MainPath;
                dungeonLayout.layout[dirX, dirY].roomStyle = RoomStyle.LeftRightOnly;

                if (nextMove == MoveDir.Down)
                {
                    RoomStyle randamType = (RoomStyle)Random.Range(2, 4);
                    dungeonLayout.layout[dirX, dirY].roomStyle             = randamType;
                    dungeonLayout.layout[lastRoom.x, lastRoom.y].roomStyle = RoomStyle.Bottom;
                }

                lastRoom = dungeonLayout.layout[dirX, dirY];
            }

            return(dungeonLayout);
        }
Esempio n. 12
0
        public bool BuildWorld(
            AsyncRPGDataContext db_context,
            int game_id, 
            out World world, 
            out string result)
        {
            bool success = true;
            WorldTemplate worldTemplate = null;
            DungeonLayout layout = null;

            world = null;
            result = SuccessMessages.GENERAL_SUCCESS;

            // Get the world generation parameters from the DB
            worldTemplate =
                WorldQueries.GetWorldGenerationParameters(
                    db_context,
                    game_id);

            // Create the initial set of rooms for the world
            if (success)
            {
                layout = new DungeonLayout(game_id, worldTemplate, m_roomTemplateSet, m_mobSpawnTableSet);

                if (!layout.BuildRoomLayout(out result))
                {
                    success = false;
                }
            }

            // Copy the rooms and portals from the layout into the world
            if (success)
            {
                world = new World(this, layout.LayoutWorldTemplate, game_id);
                world.ApplyLayout(layout);
            }

            // TODO: WorldBuilder: Generate the environment objects, etc

            // Save the cached world into the database
            if (success)
            {
                WorldQueries.InsertWorld(db_context, world);
            }

            return success;
        }
Esempio n. 13
0
        private void RenderRoom(DungeonLayout dungeonLayout)
        {
            string renderString = "";

            for (int y = dungeonLayout.height - 1; y >= 0; y--)
            {
                for (int x = 0; x < dungeonLayout.width; x++)
                {
                    Debug.Log("x:" + x + ", y:" + y + ", " + dungeonLayout.layout[x, y].roomState.ToString("g") + ", " + dungeonLayout.layout[x, y].roomStyle.ToString("g"));

                    if (x == dungeonLayout.width - 1)
                    {
                        renderString += "\n";
                    }
                }
            }
        }
Esempio n. 14
0
        public void ApplyLayout(
            DungeonLayout layout)
        {
            // Copy over all the rooms in the layout into the world
            for (DungeonLayout.RoomIndexIterator iterator = new DungeonLayout.RoomIndexIterator(layout.RoomGrid);
                iterator.Valid;
                iterator.Next())
            {
                DungeonLayout.RoomIndex roomIndex = iterator.Current;
                RoomLayout room = layout.GetRoomByIndex(roomIndex);
                RoomTemplate roomTemplate= layout.LayoutRoomTemplateSet.GetTemplateByName(room.static_room_data.room_template_name);

                room.runtime_nav_mesh = new NavMesh(room.room_key, roomTemplate.NavMeshTemplate);

                m_rooms.Add(room.room_key, room);
            }
        }
Esempio n. 15
0
    //function that actually creates the entire level layout
    private void LoadMapFile(TextAsset file)
    {
        try {
            string[] lines = file.text.Trim().Split('\n');             //split the file into lines
            for (int i = 0; i < lines.Length; ++i)
            {
                lines[i] = CleanLine(lines[i]);
            }

            int           numRooms = GetNumRooms(lines);   //number of rooms to init a DungeonLayout
            DungeonLayout DL       = levelLayout.AddComponent <DungeonLayout>();
            DL.Init(numRooms, lines);

            int height = lines.Length - 1;

            string line;
            for (int y = 0; y < height; ++y)
            {
                line = lines[y];
                int width = line.Length - 1;
                line = CleanLine(line);

                if (line != null)
                {
                    for (int x = 0; x < width; ++x)                             //for each char in the line
                    {
                        if (line[x] == '1' || line[x] == 'S' || line[x] == 'B') //Add all the room positions to the DL
                        {
                            Vector3 roomPos = MakeRoomPosition(y, x);           //row, col
                            if (line[x] == 'S')
                            {
                                DL.startRoomPosition = roomPos;
                            }
                            else if (line[x] == 'B')
                            {
                                DL.bossRoomPosition = roomPos;
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            Console.WriteLine("{0}\n", e.Message);
            print(e.Message);
        }
    }
    IEnumerator GenerateNewLevelAsync()
    {
        DungeonLayout layout = new DungeonLayout(mainPathLength, sidePathMaxLength);

        RoomIdentifier[] identifiers = layout.GetRoomIdentifiers();
        GameObject       newLevelObj = new GameObject("level_" + (curLevel + 1));

        newLevelObj.transform.position = Vector3.zero;
        newLevelObj.transform.parent   = transform;
        newLevelObj.SetActive(false);
        yield return(null);

        foreach (RoomIdentifier i in identifiers)
        {
            CreateRoom(i, newLevelObj.transform);
            yield return(null);
        }
        nextLevelObj = newLevelObj;
    }
Esempio n. 17
0
        private MoveDir FindNextRoom(DungeonLayout roomLayout, RoomInfo previousRoom)
        {
            //1,2 = Left, 3,4 = Right, 5 = Down
            int diceValue = Random.Range(1, 6);

            //Debug.Log(previousRoom.x +", " + previousRoom.y +", " + previousRoom.roomState.ToString("g"));

            if (diceValue == 1 || diceValue == 2)
            {
                if (!IsLeftRightAvailable(roomLayout, previousRoom, -1) &&
                    IsLeftRightAvailable(roomLayout, previousRoom, 1))
                {
                    return(MoveDir.Right);
                }
                else if (!IsLeftRightAvailable(roomLayout, previousRoom, -1) &&
                         !IsLeftRightAvailable(roomLayout, previousRoom, 1))
                {
                    return(CheckDownValidity(previousRoom));
                }

                return(MoveDir.Left);
            }

            if (diceValue == 3 || diceValue == 4)
            {
                if (!IsLeftRightAvailable(roomLayout, previousRoom, 1) &&
                    IsLeftRightAvailable(roomLayout, previousRoom, -1))
                {
                    return(MoveDir.Left);
                }
                else if (!IsLeftRightAvailable(roomLayout, previousRoom, 1) &&
                         !IsLeftRightAvailable(roomLayout, previousRoom, -1))
                {
                    return(CheckDownValidity(previousRoom));
                }

                return(MoveDir.Right);
            }

            return(CheckDownValidity(previousRoom));
        }
    private GameObject GenerateFirstLevel()
    {
        curLevel = 0;
        DungeonLayout layout = new DungeonLayout(mainPathLength, sidePathMaxLength);

        RoomIdentifier[] identifiers = layout.GetRoomIdentifiers();
        GameObject       newLevelObj = new GameObject("level_" + (curLevel + 1));

        newLevelObj.transform.position = Vector3.zero;
        newLevelObj.transform.parent   = transform;
        foreach (RoomIdentifier i in identifiers)
        {
            CreateRoom(i, newLevelObj.transform);
        }
        numEnemiesPerRoom += enemiesIncreasePerLevel;
        mainPathLength    += pathLengthIncreasePerLevel;
        sidePathMaxLength  = mainPathLength / 3;
        curLevel           = 1;
        StartCoroutine(GenerateNewLevelAsync());
        return(newLevelObj);
    }
        private Dictionary <int, Portal> BuildPortalIdMap(
            DungeonLayout layout)
        {
            Dictionary <int, Portal> portalIdToPortalMap = new Dictionary <int, Portal>();

            // Generate a mapping from portal id to portal
            for (DungeonLayout.RoomIndexIterator iterator = new DungeonLayout.RoomIndexIterator(layout.RoomGrid);
                 iterator.Valid;
                 iterator.Next())
            {
                DungeonLayout.RoomIndex roomIndex = iterator.Current;
                Room room = layout.GetRoomByIndex(roomIndex);

                // Add all of the portals to the map
                foreach (Portal portal in room.portals)
                {
                    portalIdToPortalMap.Add(portal.portal_id, portal);
                }
            }

            return(portalIdToPortalMap);
        }
Esempio n. 20
0
        private bool VerifyMobSpawners(
            DungeonLayout layout)
        {
            bool success = true;

            for (DungeonLayout.RoomIndexIterator iterator = new DungeonLayout.RoomIndexIterator(layout.RoomGrid);
                iterator.Valid;
                iterator.Next())
            {
                DungeonLayout.RoomIndex roomIndex = iterator.Current;
                Room room = layout.GetRoomByIndex(roomIndex);
                RoomTemplate roomTemplate=
                    layout.LayoutRoomTemplateSet.GetTemplateByName(room.static_room_data.room_template_name);

                // We don't add the mob spawner to the room if we create it
                // and it doesn't have any mobs left (spawner initially has 0 mobs.
                // TODO: Add this check back in when we support non-zero min spawn count
                //if (roomTemplate.MobSpawnerTemplates.Count() != room.mobSpawners.Count)
                //{
                //    _logger.WriteLine("DungeonValidator: FAILED: Mob spawner template count != mob spawner count");
                //    _logger.WriteLine(string.Format("  game_id: {0}", layout.GameID));
                //    _logger.WriteLine(string.Format("  room_key: {0},{1},{2}",
                //        room.room_key.x, room.room_key.y, room.room_key.z));
                //    success = false;
                //    break;
                //}

                foreach (MobSpawner spawner in room.mobSpawners)
                {
                    if (spawner.SpawnTable == null)
                    {
                        _logger.WriteLine("DungeonValidator: FAILED: Mob spawner missing spawn table!");
                        _logger.WriteLine(string.Format("  game_id: {0}", layout.GameID));
                        _logger.WriteLine(string.Format("  room_key: {0},{1},{2}",
                            room.room_key.x, room.room_key.y, room.room_key.z));
                        success = false;
                        break;
                    }

                    while (spawner.RemainingSpawnCount > 0)
                    {
                        Mob mob= spawner.SpawnRandomMob();

                        if (mob == null)
                        {
                            _logger.WriteLine("DungeonValidator: FAILED: Mob spawner failed to produce valid mob!");
                            _logger.WriteLine(string.Format("  game_id: {0}", layout.GameID));
                            _logger.WriteLine(string.Format("  room_key: {0},{1},{2}",
                                room.room_key.x, room.room_key.y, room.room_key.z));
                            success = false;
                            break;
                        }
                    }
                }
            }

            return success;
        }
Esempio n. 21
0
        private bool VerifyRoomAccessibility(
            DungeonLayout layout,
            Dictionary<int, Portal> portalIdToPortalMap)
        {
            UnionFind<RoomKey> roomUnion = new UnionFind<RoomKey>();
            RoomKey targetRoomKey = new RoomKey();
            bool success = true;

            // Do a first pass over the rooms to fill out the union and the portal map
            for (DungeonLayout.RoomIndexIterator iterator = new DungeonLayout.RoomIndexIterator(layout.RoomGrid);
                iterator.Valid;
                iterator.Next())
            {
                DungeonLayout.RoomIndex roomIndex = iterator.Current;
                Room room = layout.GetRoomByIndex(roomIndex);

                // Add the room to the union set
                roomUnion.AddElement(room.room_key);
            }

            // Union together all of the rooms connected by portals
            for (DungeonLayout.RoomIndexIterator iterator = new DungeonLayout.RoomIndexIterator(layout.RoomGrid);
                iterator.Valid;
                iterator.Next())
            {
                DungeonLayout.RoomIndex roomIndex = iterator.Current;
                Room room = layout.GetRoomByIndex(roomIndex);

                foreach (Portal portal in room.portals)
                {
                    Portal targetPortal= portalIdToPortalMap[portal.target_portal_id];

                    targetRoomKey.game_id= layout.GameID;
                    targetRoomKey.x= targetPortal.room_x;
                    targetRoomKey.y= targetPortal.room_y;
                    targetRoomKey.z= targetPortal.room_z;

                    roomUnion.Union(room.room_key, targetRoomKey);
                }
            }

            // Verify that all rooms share the same connectivity id
            int sharedConnectivityId = -1;
            for (DungeonLayout.RoomIndexIterator iterator = new DungeonLayout.RoomIndexIterator(layout.RoomGrid);
                iterator.Valid;
                iterator.Next())
            {
                DungeonLayout.RoomIndex roomIndex = iterator.Current;
                Room room = layout.GetRoomByIndex(roomIndex);

                int roomConnectivityId= roomUnion.FindRootIndex(room.room_key);

                if (sharedConnectivityId != -1)
                {
                    if (sharedConnectivityId != roomConnectivityId)
                    {
                        _logger.WriteLine("DungeonValidator: FAILED: Found room not connected to other rooms in dungeon!");
                        _logger.WriteLine(string.Format("  game_id: {0}", layout.GameID));
                        _logger.WriteLine(string.Format("  room_key: {0},{1},{2}",
                            room.room_key.x, room.room_key.y, room.room_key.z));
                        success= false;
                        break;
                    }
                }
                else
                {
                    sharedConnectivityId= roomConnectivityId;
                }
            }

            return success;
        }
Esempio n. 22
0
        private Dictionary<int, Portal> BuildPortalIdMap(
            DungeonLayout layout)
        {
            Dictionary<int, Portal> portalIdToPortalMap = new Dictionary<int, Portal>();

            // Generate a mapping from portal id to portal
            for (DungeonLayout.RoomIndexIterator iterator = new DungeonLayout.RoomIndexIterator(layout.RoomGrid);
                iterator.Valid;
                iterator.Next())
            {
                DungeonLayout.RoomIndex roomIndex = iterator.Current;
                Room room = layout.GetRoomByIndex(roomIndex);

                // Add all of the portals to the map
                foreach (Portal portal in room.portals)
                {
                    portalIdToPortalMap.Add(portal.portal_id, portal);
                }
            }

            return portalIdToPortalMap;
        }
Esempio n. 23
0
        private void DumpLayoutGeometry(
            string dumpGeometryPath, 
            DungeonLayout layout)
        {
            GeometryFileWriter fileWriter = new GeometryFileWriter();
            string filename= string.Format("DungeonLayout_Game{0}_Size{1}", layout.GameID, layout.LayoutWorldTemplate.dungeon_size);
            string header = string.Format("DungeonLayout for GameID:{0} DungeonSize: {1}", layout.GameID, layout.LayoutWorldTemplate.dungeon_size);
            string result = SuccessMessages.GENERAL_SUCCESS;
            Vector3d roomSize = new Vector3d(WorldConstants.ROOM_X_SIZE, WorldConstants.ROOM_Y_SIZE, WorldConstants.ROOM_Z_SIZE);

            for (DungeonLayout.RoomIndexIterator iterator = new DungeonLayout.RoomIndexIterator(layout.RoomGrid);
                iterator.Valid;
                iterator.Next())
            {
                DungeonLayout.RoomIndex roomIndex = iterator.Current;
                Room room = layout.GetRoomByIndex(roomIndex);
                AABB3d roomAABB = new AABB3d(room.world_position, room.world_position + roomSize);
                AABB3d shrunkRoomAABB = roomAABB.ScaleAboutCenter(0.5f);
                AABB3d centerAABB = roomAABB.ScaleAboutCenter(0.05f);

                // Add the AABB for this room
                fileWriter.AppendAABB(shrunkRoomAABB);

                // Create portal AABBs to all adjacent rooms
                for (MathConstants.eSignedDirection roomSide = MathConstants.eSignedDirection.first;
                    roomSide < MathConstants.eSignedDirection.count;
                    ++roomSide)
                {
                    if (room.RoomHasPortalOnSide(roomSide))
                    {
                        DungeonLayout.RoomIndex neighborRoomIndex = null;
                        switch (roomSide)
                        {
                            case MathConstants.eSignedDirection.positive_x:
                                neighborRoomIndex = roomIndex.Offset(1, 0, 0);
                                break;
                            case MathConstants.eSignedDirection.negative_x:
                                neighborRoomIndex = roomIndex.Offset(-1, 0, 0);
                                break;
                            case MathConstants.eSignedDirection.positive_y:
                                neighborRoomIndex = roomIndex.Offset(0, 1, 0);
                                break;
                            case MathConstants.eSignedDirection.negative_y:
                                neighborRoomIndex = roomIndex.Offset(0, -1, 0);
                                break;
                            case MathConstants.eSignedDirection.positive_z:
                                neighborRoomIndex = roomIndex.Offset(0, 0, 1);
                                break;
                            case MathConstants.eSignedDirection.negative_z:
                                neighborRoomIndex = roomIndex.Offset(0, 0, -1);
                                break;
                        }

                        Room neighborRoom = layout.GetRoomByIndex(neighborRoomIndex);
                        AABB3d neighborRoomAABB = new AABB3d(neighborRoom.world_position, neighborRoom.world_position + roomSize);
                        AABB3d neighborCenterAABB = neighborRoomAABB.ScaleAboutCenter(0.05f);
                        AABB3d portalAABB = centerAABB.EncloseAABB(neighborCenterAABB);

                        fileWriter.AppendAABB(portalAABB);
                    }
                }

                // TODO: DumpLayoutGeometry: Color the rooms by teleporter pair
            }

            if (!fileWriter.SaveFile(dumpGeometryPath, filename, header, out result))
            {
                _logger.WriteLine("DungeonValidator: WARNING: Failed to save layout geometry file");
                _logger.WriteLine(result);
            }
        }
Esempio n. 24
0
 public abstract void linkPaths(DungeonLayout layout, Random rand);
Esempio n. 25
0
        public bool ValidateDungeons(Command command)
        {
            bool success = true;
            string result= SuccessMessages.GENERAL_SUCCESS;

            RoomTemplateSet roomTemplateSet = new RoomTemplateSet();
            MobTypeSet mobTypeSet = new MobTypeSet();
            MobSpawnTableSet mobSpawnTableSet = new MobSpawnTableSet();
            int game_id_min = 0;
            int game_id_max = 100000; // Int32.MaxValue; This will take ~100 days to finish all 2 billion  dungeons
            string connection_string = "";

            string dumpGeometryPath = "";

            if (command.HasArgumentWithName("C"))
            {
                connection_string = command.GetTypedArgumentByName<CommandArgument_String>("C").ArgumentValue;
            }
            else
            {
                _logger.WriteLine("DungeonValidator: Missing expected connection string parameter");
                success = false;
            }

            if (command.HasArgumentWithName("G"))
            {
                game_id_min = command.GetTypedArgumentByName<CommandArgument_Int32>("G").ArgumentValue;
                game_id_max = game_id_min;
            }
            else
            {
                _logger.WriteLine("DungeonValidator: No game id given, evaluating all possible game ids");
            }

            if (game_id_min == game_id_max && command.HasArgumentWithName("D"))
            {
                dumpGeometryPath = command.GetTypedArgumentByName<CommandArgument_String>("D").ArgumentValue;
            }

            _logger.WriteLine("Validating layouts for game_ids {0} to {1}", game_id_min, game_id_max);

            // Get the room templates from the DB
            if (success && !roomTemplateSet.Initialize(connection_string, out result))
            {
                _logger.WriteLine(string.Format("DungeonValidator: Failed to load the room templates from the DB: {0}", result));
                success = false;
            }

            // Get the mob type set from the DB
            if (success && !mobTypeSet.Initialize(connection_string, out result))
            {
                _logger.WriteLine(string.Format("DungeonValidator: Failed to load the mob types from the DB: {0}", result));
                success = false;
            }

            // Get the mob spawn templates from the DB
            if (success && !mobSpawnTableSet.Initialize(connection_string, mobTypeSet, out result))
            {
                _logger.WriteLine(string.Format("DungeonValidator: Failed to load the mob spawn tables from the DB: {0}", result));
                success = false;
            }

            if (success)
            {
                DateTime startTime = DateTime.Now;

                // Test all possible world size configurations for each desired game id
                WorldTemplate[] worldTemplates = new WorldTemplate[] {
                    new WorldTemplate(GameConstants.eDungeonSize.small, GameConstants.eDungeonDifficulty.normal),
                    new WorldTemplate(GameConstants.eDungeonSize.medium, GameConstants.eDungeonDifficulty.normal),
                    new WorldTemplate(GameConstants.eDungeonSize.large, GameConstants.eDungeonDifficulty.normal),
                };

                for (int game_id = game_id_min; success && game_id <= game_id_max; ++game_id)
                {
                    foreach (WorldTemplate worldTemplate in worldTemplates)
                    {
                        DungeonLayout layout = new DungeonLayout(game_id, worldTemplate, roomTemplateSet, mobSpawnTableSet);

                        // Create the initial set of rooms for the world
                        if (!layout.BuildRoomLayout(out result))
                        {
                            _logger.WriteLine(
                                string.Format("DungeonValidator: Failed to generate dungeon layout, game_id:{0}, size:{1}",
                                game_id, worldTemplate.dungeon_size));
                            _logger.WriteLine(result);
                            success = false;
                        }

                        // Verify that this is a valid dungeon
                        if (success)
                        {
                            Dictionary<int, Portal> portalIdToPortalMap = BuildPortalIdMap(layout);

                            // Verify that all portals are connected correctly
                            success &= VerifyRoomPortals(layout, portalIdToPortalMap);

                            // Verify that every room is accessible to every other room
                            success &= VerifyRoomAccessibility(layout, portalIdToPortalMap);

                            // Verify monster spawners
                            success &= VerifyMobSpawners(layout);
                        }

                        // Dump the generated layout to a .obj file
                        if (dumpGeometryPath.Length > 0)
                        {
                            DumpLayoutGeometry(dumpGeometryPath, layout);
                        }
                    }

                    if (game_id_max > game_id_min)
                    {
                        if ((game_id % 1000) == 0)
                        {
                            TimeSpan elapsed = DateTime.Now.Subtract(startTime);

                            int percent_complete = 100 * (game_id - game_id_min) / (game_id_max - game_id_min);

                            _logger.Write("\r[{0:c}] {1}/{2} {3}%",
                                elapsed,
                                game_id-game_id_min,
                                game_id_max-game_id_min,
                                percent_complete);
                        }
                    }
                }

                // Write out a new line after the timing info
                _logger.WriteLine();
            }

            return success;
        }
        public bool ValidateDungeons(Command command)
        {
            bool   success = true;
            string result  = SuccessMessages.GENERAL_SUCCESS;

            RoomTemplateSet  roomTemplateSet  = new RoomTemplateSet();
            MobTypeSet       mobTypeSet       = new MobTypeSet();
            MobSpawnTableSet mobSpawnTableSet = new MobSpawnTableSet();
            int    game_id_min       = 0;
            int    game_id_max       = 100000; // Int32.MaxValue; This will take ~100 days to finish all 2 billion  dungeons
            string connection_string = "";

            string dumpGeometryPath = "";

            if (command.HasArgumentWithName("C"))
            {
                connection_string = command.GetTypedArgumentByName <CommandArgument_String>("C").ArgumentValue;
            }
            else
            {
                _logger.WriteLine("DungeonValidator: Missing expected connection string parameter");
                success = false;
            }

            if (command.HasArgumentWithName("G"))
            {
                game_id_min = command.GetTypedArgumentByName <CommandArgument_Int32>("G").ArgumentValue;
                game_id_max = game_id_min;
            }
            else
            {
                _logger.WriteLine("DungeonValidator: No game id given, evaluating all possible game ids");
            }

            if (game_id_min == game_id_max && command.HasArgumentWithName("D"))
            {
                dumpGeometryPath = command.GetTypedArgumentByName <CommandArgument_String>("D").ArgumentValue;
            }

            _logger.WriteLine("Validating layouts for game_ids {0} to {1}", game_id_min, game_id_max);

            // Get the room templates from the DB
            if (success && !roomTemplateSet.Initialize(connection_string, out result))
            {
                _logger.WriteLine(string.Format("DungeonValidator: Failed to load the room templates from the DB: {0}", result));
                success = false;
            }

            // Get the mob type set from the DB
            if (success && !mobTypeSet.Initialize(connection_string, out result))
            {
                _logger.WriteLine(string.Format("DungeonValidator: Failed to load the mob types from the DB: {0}", result));
                success = false;
            }

            // Get the mob spawn templates from the DB
            if (success && !mobSpawnTableSet.Initialize(connection_string, mobTypeSet, out result))
            {
                _logger.WriteLine(string.Format("DungeonValidator: Failed to load the mob spawn tables from the DB: {0}", result));
                success = false;
            }

            if (success)
            {
                DateTime startTime = DateTime.Now;

                // Test all possible world size configurations for each desired game id
                WorldTemplate[] worldTemplates = new WorldTemplate[] {
                    new WorldTemplate(GameConstants.eDungeonSize.small, GameConstants.eDungeonDifficulty.normal),
                    new WorldTemplate(GameConstants.eDungeonSize.medium, GameConstants.eDungeonDifficulty.normal),
                    new WorldTemplate(GameConstants.eDungeonSize.large, GameConstants.eDungeonDifficulty.normal),
                };

                for (int game_id = game_id_min; success && game_id <= game_id_max; ++game_id)
                {
                    foreach (WorldTemplate worldTemplate in worldTemplates)
                    {
                        DungeonLayout layout = new DungeonLayout(game_id, worldTemplate, roomTemplateSet, mobSpawnTableSet);

                        // Create the initial set of rooms for the world
                        if (!layout.BuildRoomLayout(out result))
                        {
                            _logger.WriteLine(
                                string.Format("DungeonValidator: Failed to generate dungeon layout, game_id:{0}, size:{1}",
                                              game_id, worldTemplate.dungeon_size));
                            _logger.WriteLine(result);
                            success = false;
                        }

                        // Verify that this is a valid dungeon
                        if (success)
                        {
                            Dictionary <int, Portal> portalIdToPortalMap = BuildPortalIdMap(layout);

                            // Verify that all portals are connected correctly
                            success &= VerifyRoomPortals(layout, portalIdToPortalMap);

                            // Verify that every room is accessible to every other room
                            success &= VerifyRoomAccessibility(layout, portalIdToPortalMap);

                            // Verify monster spawners
                            success &= VerifyMobSpawners(layout);
                        }

                        // Dump the generated layout to a .obj file
                        if (dumpGeometryPath.Length > 0)
                        {
                            DumpLayoutGeometry(dumpGeometryPath, layout);
                        }
                    }

                    if (game_id_max > game_id_min)
                    {
                        if ((game_id % 1000) == 0)
                        {
                            TimeSpan elapsed = DateTime.Now.Subtract(startTime);

                            int percent_complete = 100 * (game_id - game_id_min) / (game_id_max - game_id_min);

                            _logger.Write("\r[{0:c}] {1}/{2} {3}%",
                                          elapsed,
                                          game_id - game_id_min,
                                          game_id_max - game_id_min,
                                          percent_complete);
                        }
                    }
                }

                // Write out a new line after the timing info
                _logger.WriteLine();
            }

            return(success);
        }
        private bool VerifyRoomAccessibility(
            DungeonLayout layout,
            Dictionary <int, Portal> portalIdToPortalMap)
        {
            UnionFind <RoomKey> roomUnion     = new UnionFind <RoomKey>();
            RoomKey             targetRoomKey = new RoomKey();
            bool success = true;

            // Do a first pass over the rooms to fill out the union and the portal map
            for (DungeonLayout.RoomIndexIterator iterator = new DungeonLayout.RoomIndexIterator(layout.RoomGrid);
                 iterator.Valid;
                 iterator.Next())
            {
                DungeonLayout.RoomIndex roomIndex = iterator.Current;
                Room room = layout.GetRoomByIndex(roomIndex);

                // Add the room to the union set
                roomUnion.AddElement(room.room_key);
            }

            // Union together all of the rooms connected by portals
            for (DungeonLayout.RoomIndexIterator iterator = new DungeonLayout.RoomIndexIterator(layout.RoomGrid);
                 iterator.Valid;
                 iterator.Next())
            {
                DungeonLayout.RoomIndex roomIndex = iterator.Current;
                Room room = layout.GetRoomByIndex(roomIndex);

                foreach (Portal portal in room.portals)
                {
                    Portal targetPortal = portalIdToPortalMap[portal.target_portal_id];

                    targetRoomKey.game_id = layout.GameID;
                    targetRoomKey.x       = targetPortal.room_x;
                    targetRoomKey.y       = targetPortal.room_y;
                    targetRoomKey.z       = targetPortal.room_z;

                    roomUnion.Union(room.room_key, targetRoomKey);
                }
            }

            // Verify that all rooms share the same connectivity id
            int sharedConnectivityId = -1;

            for (DungeonLayout.RoomIndexIterator iterator = new DungeonLayout.RoomIndexIterator(layout.RoomGrid);
                 iterator.Valid;
                 iterator.Next())
            {
                DungeonLayout.RoomIndex roomIndex = iterator.Current;
                Room room = layout.GetRoomByIndex(roomIndex);

                int roomConnectivityId = roomUnion.FindRootIndex(room.room_key);

                if (sharedConnectivityId != -1)
                {
                    if (sharedConnectivityId != roomConnectivityId)
                    {
                        _logger.WriteLine("DungeonValidator: FAILED: Found room not connected to other rooms in dungeon!");
                        _logger.WriteLine(string.Format("  game_id: {0}", layout.GameID));
                        _logger.WriteLine(string.Format("  room_key: {0},{1},{2}",
                                                        room.room_key.x, room.room_key.y, room.room_key.z));
                        success = false;
                        break;
                    }
                }
                else
                {
                    sharedConnectivityId = roomConnectivityId;
                }
            }

            return(success);
        }
        private void DumpLayoutGeometry(
            string dumpGeometryPath,
            DungeonLayout layout)
        {
            GeometryFileWriter fileWriter = new GeometryFileWriter();
            string             filename   = string.Format("DungeonLayout_Game{0}_Size{1}", layout.GameID, layout.LayoutWorldTemplate.dungeon_size);
            string             header     = string.Format("DungeonLayout for GameID:{0} DungeonSize: {1}", layout.GameID, layout.LayoutWorldTemplate.dungeon_size);
            string             result     = SuccessMessages.GENERAL_SUCCESS;
            Vector3d           roomSize   = new Vector3d(WorldConstants.ROOM_X_SIZE, WorldConstants.ROOM_Y_SIZE, WorldConstants.ROOM_Z_SIZE);

            for (DungeonLayout.RoomIndexIterator iterator = new DungeonLayout.RoomIndexIterator(layout.RoomGrid);
                 iterator.Valid;
                 iterator.Next())
            {
                DungeonLayout.RoomIndex roomIndex = iterator.Current;
                Room   room           = layout.GetRoomByIndex(roomIndex);
                AABB3d roomAABB       = new AABB3d(room.world_position, room.world_position + roomSize);
                AABB3d shrunkRoomAABB = roomAABB.ScaleAboutCenter(0.5f);
                AABB3d centerAABB     = roomAABB.ScaleAboutCenter(0.05f);

                // Add the AABB for this room
                fileWriter.AppendAABB(shrunkRoomAABB);

                // Create portal AABBs to all adjacent rooms
                for (MathConstants.eSignedDirection roomSide = MathConstants.eSignedDirection.first;
                     roomSide < MathConstants.eSignedDirection.count;
                     ++roomSide)
                {
                    if (room.RoomHasPortalOnSide(roomSide))
                    {
                        DungeonLayout.RoomIndex neighborRoomIndex = null;
                        switch (roomSide)
                        {
                        case MathConstants.eSignedDirection.positive_x:
                            neighborRoomIndex = roomIndex.Offset(1, 0, 0);
                            break;

                        case MathConstants.eSignedDirection.negative_x:
                            neighborRoomIndex = roomIndex.Offset(-1, 0, 0);
                            break;

                        case MathConstants.eSignedDirection.positive_y:
                            neighborRoomIndex = roomIndex.Offset(0, 1, 0);
                            break;

                        case MathConstants.eSignedDirection.negative_y:
                            neighborRoomIndex = roomIndex.Offset(0, -1, 0);
                            break;

                        case MathConstants.eSignedDirection.positive_z:
                            neighborRoomIndex = roomIndex.Offset(0, 0, 1);
                            break;

                        case MathConstants.eSignedDirection.negative_z:
                            neighborRoomIndex = roomIndex.Offset(0, 0, -1);
                            break;
                        }

                        Room   neighborRoom       = layout.GetRoomByIndex(neighborRoomIndex);
                        AABB3d neighborRoomAABB   = new AABB3d(neighborRoom.world_position, neighborRoom.world_position + roomSize);
                        AABB3d neighborCenterAABB = neighborRoomAABB.ScaleAboutCenter(0.05f);
                        AABB3d portalAABB         = centerAABB.EncloseAABB(neighborCenterAABB);

                        fileWriter.AppendAABB(portalAABB);
                    }
                }

                // TODO: DumpLayoutGeometry: Color the rooms by teleporter pair
            }

            if (!fileWriter.SaveFile(dumpGeometryPath, filename, header, out result))
            {
                _logger.WriteLine("DungeonValidator: WARNING: Failed to save layout geometry file");
                _logger.WriteLine(result);
            }
        }
Esempio n. 29
0
        private bool VerifyRoomPortals(
            DungeonLayout layout,
            Dictionary<int, Portal> portalIdToPortalMap)
        {
            bool success = true;
            MathConstants.eSignedDirection[] roomSides = new MathConstants.eSignedDirection[] {
                MathConstants.eSignedDirection.positive_x,
                MathConstants.eSignedDirection.negative_x,
                MathConstants.eSignedDirection.positive_y,
                MathConstants.eSignedDirection.negative_y,
                MathConstants.eSignedDirection.positive_z,
                MathConstants.eSignedDirection.negative_z
            };

            for (DungeonLayout.RoomIndexIterator iterator = new DungeonLayout.RoomIndexIterator(layout.RoomGrid);
                iterator.Valid;
                iterator.Next())
            {
                DungeonLayout.RoomIndex roomIndex = iterator.Current;
                Room room = layout.GetRoomByIndex(roomIndex);

                // Verify the the portal bitmask matches the existing portals
                foreach (MathConstants.eSignedDirection roomSide in roomSides)
                {
                    if (room.RoomHasPortalOnSide(roomSide))
                    {
                        if (room.portals.Count(p => p.room_side == roomSide) == 0)
                        {
                            _logger.WriteLine("DungeonValidator: FAILED: Expected portal on room side {0} but found none!", roomSide);
                            _logger.WriteLine(string.Format("  game_id: {0}", layout.GameID));
                            _logger.WriteLine(string.Format("  room_key: {0},{1},{2}",
                                room.room_key.x, room.room_key.y, room.room_key.z));
                            success = false;
                            break;
                        }
                    }
                    else
                    {
                        if (room.portals.Count(p => p.room_side == roomSide) != 0)
                        {
                            _logger.WriteLine("DungeonValidator: FAILED: Expected no portal on room side {0} but found one!", roomSide);
                            _logger.WriteLine(string.Format("  game_id: {0}", layout.GameID));
                            _logger.WriteLine(string.Format("  room_key: {0},{1},{2}",
                                room.room_key.x, room.room_key.y, room.room_key.z));
                            success = false;
                            break;
                        }
                    }
                }

                // Verify that the portals are the right expected type
                foreach (Portal portal in room.portals)
                {
                    MathConstants.eSignedDirection roomSide = portal.room_side;

                    switch (portal.portal_type)
                    {
                        case ePortalType.door:
                            if (roomSide != MathConstants.eSignedDirection.positive_x && roomSide != MathConstants.eSignedDirection.negative_x &&
                                roomSide != MathConstants.eSignedDirection.positive_y && roomSide != MathConstants.eSignedDirection.negative_y)
                            {
                                _logger.WriteLine(
                                    string.Format(
                                    "DungeonValidator: FAILED: Door portal id={0} on unexpected side={1}",
                                    portal.portal_id, roomSide));
                                _logger.WriteLine(string.Format("  game_id: {0}", layout.GameID));
                                _logger.WriteLine(string.Format("  room_key: {0},{1},{2}",
                                    room.room_key.x, room.room_key.y, room.room_key.z));
                                success = false;
                            }
                            break;
                        case ePortalType.stairs:
                            if (roomSide != MathConstants.eSignedDirection.positive_z && roomSide != MathConstants.eSignedDirection.negative_z)
                            {
                                _logger.WriteLine(
                                    string.Format(
                                    "DungeonValidator: FAILED: Stairs portal id={0} on unexpected side={1}",
                                    portal.portal_id, roomSide));
                                _logger.WriteLine(string.Format("  game_id: {0}", layout.GameID));
                                _logger.WriteLine(string.Format("  room_key: {0},{1},{2}",
                                    room.room_key.x, room.room_key.y, room.room_key.z));
                                success = false;
                            }
                            break;
                        case ePortalType.teleporter:
                            if (roomSide != MathConstants.eSignedDirection.none)
                            {
                                _logger.WriteLine(
                                    string.Format(
                                    "DungeonValidator: FAILED: Teleporter portal id={0} on unexpected side={1}",
                                    portal.portal_id, roomSide));
                                _logger.WriteLine(string.Format("  game_id: {0}", layout.GameID));
                                _logger.WriteLine(string.Format("  room_key: {0},{1},{2}",
                                    room.room_key.x, room.room_key.y, room.room_key.z));
                                success = false;
                            }
                            break;
                    }
                }

                // Verify that the portals connect to a valid target portal
                foreach (Portal portal in room.portals)
                {
                    if (portalIdToPortalMap.ContainsKey(portal.target_portal_id))
                    {
                        Portal targetPortal = portalIdToPortalMap[portal.target_portal_id];

                        if (targetPortal.target_portal_id != portal.portal_id)
                        {
                            _logger.WriteLine("DungeonValidator: FAILED: Target Portal is not connected to a valid portal!");
                            _logger.WriteLine(string.Format("  game_id: {0}", layout.GameID));
                            _logger.WriteLine(string.Format("  room_key: {0},{1},{2}",
                                room.room_key.x, room.room_key.y, room.room_key.z));
                            success = false;
                            break;
                        }
                    }
                    else
                    {
                        _logger.WriteLine("DungeonValidator: FAILED: Portal is not connected to a valid target portal!");
                        _logger.WriteLine(string.Format("  game_id: {0}", layout.GameID));
                        _logger.WriteLine(string.Format("  room_key: {0},{1},{2}",
                            room.room_key.x, room.room_key.y, room.room_key.z));
                        success = false;
                        break;
                    }
                }
            }

            return success;
        }
        private bool VerifyRoomPortals(
            DungeonLayout layout,
            Dictionary <int, Portal> portalIdToPortalMap)
        {
            bool success = true;

            MathConstants.eSignedDirection[] roomSides = new MathConstants.eSignedDirection[] {
                MathConstants.eSignedDirection.positive_x,
                MathConstants.eSignedDirection.negative_x,
                MathConstants.eSignedDirection.positive_y,
                MathConstants.eSignedDirection.negative_y,
                MathConstants.eSignedDirection.positive_z,
                MathConstants.eSignedDirection.negative_z
            };

            for (DungeonLayout.RoomIndexIterator iterator = new DungeonLayout.RoomIndexIterator(layout.RoomGrid);
                 iterator.Valid;
                 iterator.Next())
            {
                DungeonLayout.RoomIndex roomIndex = iterator.Current;
                Room room = layout.GetRoomByIndex(roomIndex);

                // Verify the the portal bitmask matches the existing portals
                foreach (MathConstants.eSignedDirection roomSide in roomSides)
                {
                    if (room.RoomHasPortalOnSide(roomSide))
                    {
                        if (room.portals.Count(p => p.room_side == roomSide) == 0)
                        {
                            _logger.WriteLine("DungeonValidator: FAILED: Expected portal on room side {0} but found none!", roomSide);
                            _logger.WriteLine(string.Format("  game_id: {0}", layout.GameID));
                            _logger.WriteLine(string.Format("  room_key: {0},{1},{2}",
                                                            room.room_key.x, room.room_key.y, room.room_key.z));
                            success = false;
                            break;
                        }
                    }
                    else
                    {
                        if (room.portals.Count(p => p.room_side == roomSide) != 0)
                        {
                            _logger.WriteLine("DungeonValidator: FAILED: Expected no portal on room side {0} but found one!", roomSide);
                            _logger.WriteLine(string.Format("  game_id: {0}", layout.GameID));
                            _logger.WriteLine(string.Format("  room_key: {0},{1},{2}",
                                                            room.room_key.x, room.room_key.y, room.room_key.z));
                            success = false;
                            break;
                        }
                    }
                }

                // Verify that the portals are the right expected type
                foreach (Portal portal in room.portals)
                {
                    MathConstants.eSignedDirection roomSide = portal.room_side;

                    switch (portal.portal_type)
                    {
                    case ePortalType.door:
                        if (roomSide != MathConstants.eSignedDirection.positive_x && roomSide != MathConstants.eSignedDirection.negative_x &&
                            roomSide != MathConstants.eSignedDirection.positive_y && roomSide != MathConstants.eSignedDirection.negative_y)
                        {
                            _logger.WriteLine(
                                string.Format(
                                    "DungeonValidator: FAILED: Door portal id={0} on unexpected side={1}",
                                    portal.portal_id, roomSide));
                            _logger.WriteLine(string.Format("  game_id: {0}", layout.GameID));
                            _logger.WriteLine(string.Format("  room_key: {0},{1},{2}",
                                                            room.room_key.x, room.room_key.y, room.room_key.z));
                            success = false;
                        }
                        break;

                    case ePortalType.stairs:
                        if (roomSide != MathConstants.eSignedDirection.positive_z && roomSide != MathConstants.eSignedDirection.negative_z)
                        {
                            _logger.WriteLine(
                                string.Format(
                                    "DungeonValidator: FAILED: Stairs portal id={0} on unexpected side={1}",
                                    portal.portal_id, roomSide));
                            _logger.WriteLine(string.Format("  game_id: {0}", layout.GameID));
                            _logger.WriteLine(string.Format("  room_key: {0},{1},{2}",
                                                            room.room_key.x, room.room_key.y, room.room_key.z));
                            success = false;
                        }
                        break;

                    case ePortalType.teleporter:
                        if (roomSide != MathConstants.eSignedDirection.none)
                        {
                            _logger.WriteLine(
                                string.Format(
                                    "DungeonValidator: FAILED: Teleporter portal id={0} on unexpected side={1}",
                                    portal.portal_id, roomSide));
                            _logger.WriteLine(string.Format("  game_id: {0}", layout.GameID));
                            _logger.WriteLine(string.Format("  room_key: {0},{1},{2}",
                                                            room.room_key.x, room.room_key.y, room.room_key.z));
                            success = false;
                        }
                        break;
                    }
                }

                // Verify that the portals connect to a valid target portal
                foreach (Portal portal in room.portals)
                {
                    if (portalIdToPortalMap.ContainsKey(portal.target_portal_id))
                    {
                        Portal targetPortal = portalIdToPortalMap[portal.target_portal_id];

                        if (targetPortal.target_portal_id != portal.portal_id)
                        {
                            _logger.WriteLine("DungeonValidator: FAILED: Target Portal is not connected to a valid portal!");
                            _logger.WriteLine(string.Format("  game_id: {0}", layout.GameID));
                            _logger.WriteLine(string.Format("  room_key: {0},{1},{2}",
                                                            room.room_key.x, room.room_key.y, room.room_key.z));
                            success = false;
                            break;
                        }
                    }
                    else
                    {
                        _logger.WriteLine("DungeonValidator: FAILED: Portal is not connected to a valid target portal!");
                        _logger.WriteLine(string.Format("  game_id: {0}", layout.GameID));
                        _logger.WriteLine(string.Format("  room_key: {0},{1},{2}",
                                                        room.room_key.x, room.room_key.y, room.room_key.z));
                        success = false;
                        break;
                    }
                }
            }

            return(success);
        }