コード例 #1
0
 /**
  * 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);
     }
 }
コード例 #2
0
    /**
     * 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);
    }
コード例 #3
0
    /**
     * Randomly links up some adjacent rooms to make the dungeon graph less of
     * a tree.
     *
     * @ if it fails
     */
    protected void Graphify()
    {
        foreach (MZRoom room in dungeon.GetRooms())
        {
            if (room.IsGoal() || room.IsBoss())
            {
                continue;
            }

            foreach (KeyValuePair <Double, int> next in
                     // Doesn't matter what the keyLevel is; later checks about
                     // preconds ensure linkage doesn't trivialize the puzzle.
                     constraints.GetAdjacentRooms(room.id, Int32.MaxValue))
            {
                int nextId = next.Value;

                if (room.GetEdge(nextId) != null)
                {
                    continue;
                }

                MZRoom nextRoom = dungeon.Get(nextId);
                if (nextRoom == null || nextRoom.IsGoal() || nextRoom.IsBoss())
                {
                    continue;
                }

                if (room.GetCoords()[0].x == -1 && room.GetCoords()[0].y == -3)
                {
                    //Debug.Log(nextRoom.GetCoords()[0].x + " " + nextRoom.GetCoords()[0].y);
                    Debug.Log(room.GetEdges().Count);
                }

                bool forwardImplies  = room.GetPrecond().Implies(nextRoom.GetPrecond()),
                     backwardImplies = nextRoom.GetPrecond().Implies(room.GetPrecond());
                if (forwardImplies && backwardImplies)
                {
                    // both rooms are at the same keyLevel.
                    if (UnityEngine.Random.value >=
                        constraints.EdgeGraphifyProbability(room.id, nextRoom.id))
                    {
                        continue;
                    }

                    dungeon.Link(room, nextRoom);
                }
                else
                {
                    MZSymbol difference = room.GetPrecond().SingleSymbolDifference(
                        nextRoom.GetPrecond());
                    if (difference == null || (!difference.IsSwitchState() &&
                                               UnityEngine.Random.value >=
                                               constraints.EdgeGraphifyProbability(room.id, nextRoom.id)))
                    {
                        continue;
                    }

                    dungeon.Link(room, nextRoom, difference);
                }
            }
        }
    }
コード例 #4
0
    /**
     * 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();
    }
コード例 #5
0
    /**
     * 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);
            }
        }
    }