/** * Fill the dungeon's space with rooms and doors (some locked). * Keys are not inserted at this point. * * @param levels the keyLevel -> room-set mapping to update * @ if it fails * @see KeyLevelRoomMapping */ protected void PlaceRooms(KeyLevelRoomMapping levels, int roomsPerLock) { // keyLevel: the number of keys required to Get to the new room int keyLevel = 0; MZSymbol latestKey = null; // condition that must hold true for the player to reach the new room // (the set of keys they must have). MZCondition cond = new MZCondition(); // Loop to place rooms and link them while (dungeon.RoomCount() < constraints.GetMaxRooms()) { bool doLock = false; // Decide whether we need to place a new lock // (Don't place the last lock, since that's reserved for the boss) if (ShouldAddNewLock(keyLevel, levels.GetRooms(keyLevel).Count, roomsPerLock)) { latestKey = new MZSymbol(keyLevel++); cond = cond.And(latestKey); doLock = true; } // Find an existing room with a free edge: MZRoom parentRoom = null; if (!doLock && UnityEngine.Random.Range(0, 10) > 0) { parentRoom = ChooseRoomWithFreeEdge(levels.GetRooms(keyLevel), keyLevel); } if (parentRoom == null) { parentRoom = ChooseRoomWithFreeEdge(new List <MZRoom>(dungeon.GetRooms()), keyLevel); doLock = true; } if (parentRoom == null) { throw new OutOfRoomsException(); } // Decide which direction to put the new room in relative to the // parent int nextId = ChooseFreeEdge(parentRoom, keyLevel); List <Vector2Int> coords = constraints.GetCoords(nextId); MZRoom room = new MZRoom(nextId, coords, parentRoom, null, cond); // Add the room to the dungeon dungeon.Add(room); parentRoom.AddChild(room); dungeon.Link(parentRoom, room, doLock ? latestKey : null); levels.AddRoom(keyLevel, room); } }
/** * Sets up the dungeon's entrance room. * * @param levels the keyLevel -> room-set mapping to update * @see KeyLevelRoomMapping */ protected void InitEntranceRoom(KeyLevelRoomMapping levels) { int id; List <int> possibleEntries = new List <int>(constraints.InitialRooms()); id = possibleEntries[UnityEngine.Random.Range(0, possibleEntries.Count)]; MZRoom entry = new MZRoom(id, constraints.GetCoords(id), null, new MZSymbol((int)MZSymbol.MZSymbolValue.Start), new MZCondition()); dungeon.Add(entry); levels.AddRoom(0, entry); }
/** * Places the BOSS and GOAL rooms within the dungeon, in existing rooms. * These rooms are moved into the next keyLevel. * * @param levels the keyLevel -> room-set mapping to update * @ if it fails * @see KeyLevelRoomMapping */ protected void PlaceBossGoalRooms(KeyLevelRoomMapping levels) { List <MZRoom> possibleGoalRooms = new List <MZRoom>(dungeon.RoomCount()); MZSymbol goalSym = new MZSymbol((int)MZSymbol.MZSymbolValue.Goal), bossSym = new MZSymbol((int)MZSymbol.MZSymbolValue.Boss); foreach (MZRoom room in dungeon.GetRooms()) { if (room.GetChildren().Count > 0 || room.GetItem() != null) { continue; } MZRoom parent = room.GetParent(); if (parent == null) { continue; } if (IsGenerateGoal() && (parent.GetChildren().Count != 1 || !parent.GetPrecond().Implies(room.GetPrecond()))) { continue; } if (IsGenerateGoal()) { if (!constraints.RoomCanFitItem(room.id, goalSym) || !constraints.RoomCanFitItem(parent.id, bossSym)) { continue; } } else { if (!constraints.RoomCanFitItem(room.id, bossSym)) { continue; } } possibleGoalRooms.Add(room); } if (possibleGoalRooms.Count == 0) { throw new RetryException(); } MZRoom goalRoom = possibleGoalRooms[UnityEngine.Random.Range(0, possibleGoalRooms.Count)], bossRoom = goalRoom.GetParent(); if (!IsGenerateGoal()) { bossRoom = goalRoom; goalRoom = null; } if (goalRoom != null) { goalRoom.SetItem(goalSym); } bossRoom.SetItem(bossSym); int oldKeyLevel = bossRoom.GetPrecond().GetKeyLevel(), newKeyLevel = Math.Min(levels.KeyCount(), constraints.GetMaxKeys()); if (oldKeyLevel != newKeyLevel) { List <MZRoom> oklRooms = levels.GetRooms(oldKeyLevel); if (goalRoom != null) { oklRooms.Remove(goalRoom); } oklRooms.Remove(bossRoom); if (goalRoom != null) { levels.AddRoom(newKeyLevel, goalRoom); } levels.AddRoom(newKeyLevel, bossRoom); MZSymbol bossKey = new MZSymbol(newKeyLevel - 1); MZCondition precond = bossRoom.GetPrecond().And(bossKey); bossRoom.SetPrecond(precond); if (goalRoom != null) { goalRoom.SetPrecond(precond); } if (newKeyLevel == 0) { dungeon.Link(bossRoom.GetParent(), bossRoom); } else { dungeon.Link(bossRoom.GetParent(), bossRoom, bossKey); } if (goalRoom != null) { dungeon.Link(bossRoom, goalRoom); } } }