/** * Removes the given {@link MZRoom} and all its descendants from the given * list. * * @param rooms the list of MZRooms to remove nodes from * @param room the MZRoom whose descendants to remove from the list */ protected void RemoveDescendantsFromList(List <MZRoom> rooms, MZRoom room) { rooms.Remove(room); foreach (MZRoom child in room.GetChildren()) { RemoveDescendantsFromList(rooms, child); } }
/** * Adds extra conditions to the given {@link MZRoom}'s preconditions and all * of its descendants. * * @param room the MZRoom to Add extra preconditions to * @param cond the extra preconditions to Add */ protected void AddPrecond(MZRoom room, MZCondition cond) { room.SetPrecond(room.GetPrecond().And(cond)); foreach (MZRoom child in room.GetChildren()) { AddPrecond(child, cond); } }
/** * Recursively applies the given intensity to the given {@link MZRoom}, and * higher intensities to each of its descendants that are within the same * keyLevel. * <p> * Intensities set by this method may (will) be outside of the normal range * from 0.0 to 1.0. See {@link #NormalizeIntensity} to correct this. * * @param room the room to set the intensity of * @param intensity the value to set intensity to (some randomn variance is * Added) * @see MZRoom */ protected double ApplyIntensity(MZRoom room, double intensity) { intensity *= 1.0 - intensityGrowthJitter / 2.0 + intensityGrowthJitter * UnityEngine.Random.value; room.SetIntensity(intensity); double maxIntensity = intensity; foreach (MZRoom child in room.GetChildren()) { if (room.GetPrecond().Implies(child.GetPrecond())) { maxIntensity = Math.Max(maxIntensity, ApplyIntensity(child, intensity + 1.0)); } } return(maxIntensity); }
/** * Randomly locks descendant rooms of the given {@link MZRoom} with * {@link MZEdge}s that require the switch to be in the given state. * <p> * If the given state is Either, the required states will be random. * * @param room the room whose child to lock * @param givenState the state to require the switch to be in for the * child rooms to be accessible * @return true if any locks were Added, false if none were * Added (which can happen due to the way the random * decisions are made) * @see MZCondition.SwitchState */ protected bool SwitchLockChildRooms(MZRoom room, MZCondition.SwitchState givenState) { bool anyLocks = false; MZCondition.SwitchState state = givenState != MZCondition.SwitchState.Either ? givenState : (UnityEngine.Random.Range(0, 2) == 0 ? MZCondition.SwitchState.On : MZCondition.SwitchState.Off); foreach (MZEdge edge in room.GetEdges()) { int neighborId = edge.GetTargetRoomId(); MZRoom nextRoom = dungeon.Get(neighborId); if (room.GetChildren().Contains(nextRoom)) { if (room.GetEdge(neighborId).GetSymbol() == null && UnityEngine.Random.Range(0, 4) != 0) { dungeon.Link(room, nextRoom, state.ToSymbol()); AddPrecond(nextRoom, new MZCondition(state.ToSymbol())); anyLocks = true; } else { anyLocks |= SwitchLockChildRooms(nextRoom, state); } if (givenState == MZCondition.SwitchState.Either) { state = state.Invert(); } } } return(anyLocks); }
/** * 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); } } }