/** * Makes some {@link MZEdge}s within the dungeon require the dungeon's switch * to be in a particular state, and places the switch in a room in the * dungeon. * * @ if it fails */ protected void PlaceSwitches() { // Possible TODO: have multiple switches on separate circuits // At the moment, we only have one switch per dungeon. if (constraints.GetMaxSwitches() <= 0) { return; } List <MZRoom> solution = GetSolutionPath(); for (int attempt = 0; attempt < 10; ++attempt) { List <MZRoom> rooms = new List <MZRoom>(dungeon.GetRooms()); Shuffle(rooms); Shuffle(solution); // Pick a base room from the solution path so that the player // will have to encounter a switch-lock to solve the dungeon. MZRoom baseRoom = null; foreach (MZRoom room in solution) { if (room.GetChildren().Count > 1 && room.GetParent() != null) { baseRoom = room; break; } } if (baseRoom == null) { throw new RetryException(); } MZCondition baseRoomCond = baseRoom.GetPrecond(); RemoveDescendantsFromList(rooms, baseRoom); MZSymbol switchSym = new MZSymbol((int)MZSymbol.MZSymbolValue.Switch); MZRoom switchRoom = null; foreach (MZRoom room in rooms) { if (room.GetItem() == null && baseRoomCond.Implies(room.GetPrecond()) && constraints.RoomCanFitItem(room.id, switchSym)) { switchRoom = room; break; } } if (switchRoom == null) { continue; } if (SwitchLockChildRooms(baseRoom, MZCondition.SwitchState.Either)) { switchRoom.SetItem(switchSym); return; } } throw new RetryException(); }
/** * 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); } } }