/**
     * Creates a new MZCondition that requires this MZCondition to be satisfied and
     * requires another {@link MZSymbol} to be obtained as well.
     *
     * @param sym   the Added symbol the player must have for the new MZCondition
     *              to be satisfied
     * @return      the new MZCondition
     */
    public MZCondition And(MZSymbol sym)
    {
        MZCondition result = new MZCondition(this);

        result.Add(sym);
        return(result);
    }
 /**
  * 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);
     }
 }
 private void Add(MZCondition cond)
 {
     if (switchState == SwitchState.Either)
     {
         switchState = cond.switchState;
     }
     keyLevel = Math.Max(keyLevel, cond.keyLevel);
 }
    /**
     * 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);
        }
    }
    /**
     * Creates a new MZCondition that requires this MZCondition and another
     * MZCondition to both be satisfied.
     *
     * @param other the other MZCondition that must be satisfied.
     * @return      the new MZCondition
     */
    public MZCondition And(MZCondition other)
    {
        if (other == null)
        {
            return(this);
        }
        MZCondition result = new MZCondition(this);

        result.Add(other);
        return(result);
    }
 public override bool Equals(object other)
 {
     if (other.GetType() == typeof(MZCondition))
     {
         MZCondition o = (MZCondition)other;
         return(keyLevel == o.keyLevel && switchState == o.switchState);
     }
     else
     {
         return(base.Equals(other));
     }
 }
Exemple #7
0
    /**
     * Creates a MZRoom at the given coordinates, with the given parent,
     * containing a specific item, and having a certain pre-{@link MZCondition}.
     * <p>
     * The parent of a room is the parent node of this MZRoom in the initial
     * tree of the dungeon during
     * {@link generators.MZDungeonGenerator#Generate()}, and
     * before
     * {@link generators.MZDungeonGenerator#Graphify()}.
     *
     * @param coords    the coordinates of the new room
     * @param parent    the parent room or null if it is the root / entry room
     * @param item      the symbol to place in the room or null if no item
     * @param precond   the precondition of the room
     * @see MZCondition
     */
    public MZRoom(int id, List <Vector2Int> coords, MZRoom parent, MZSymbol item, MZCondition precond)
    {
        this.id        = id;
        this.coords    = coords;
        this.item      = item;
        this.edges     = new List <MZEdge>();
        this.precond   = precond;
        this.intensity = 0.0;
        this.parent    = parent;
        this.children  = new List <MZRoom>(3);
        // all edges initially null
        int x = 0, y = 0;

        foreach (Vector2Int xy in coords)
        {
            x += xy.x; y += xy.y;
        }
        center = new Vector2Int(x / coords.Count, y / coords.Count);
    }
    /**
     * Gets the single {@link MZSymbol} needed to make this MZCondition and another
     * MZCondition identical.
     * <p>
     * If {@link #and}ed to both MZConditions, the MZConditions would then imply
     * each other.
     *
     * @param other the other MZCondition
     * @return  the MZSymbol needed to make the MZConditions identical, or null if
     *          there is no single MZSymbol that would make them identical or if
     *          they are already identical.
     */
    public MZSymbol SingleSymbolDifference(MZCondition other)
    {
        // If the difference between this and other can be made up by obtaining
        // a single new symbol, this returns the symbol. If multiple or no
        // symbols are required, returns null.

        if (this.Equals(other))
        {
            return(null);
        }
        if (switchState == other.switchState)
        {
            return(new MZSymbol(Math.Max(keyLevel, other.keyLevel) - 1));
        }
        else
        {
            if (keyLevel != other.keyLevel)
            {
                return(null);
            }
            // Multiple symbols needed        ^^^

            if (switchState != SwitchState.Either &&
                other.switchState != SwitchState.Either)
            {
                return(null);
            }

            SwitchState nonEither = switchState != SwitchState.Either
                    ? switchState
                    : other.switchState;

            return(new MZSymbol(nonEither == SwitchState.On
                    ? (int)MZSymbol.MZSymbolValue.SwitchOn
                    : (int)MZSymbol.MZSymbolValue.SwitchOff));
        }
    }
    /**
     * 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);
            }
        }
    }
 /**
  * Creates a MZCondition from another MZCondition (copy it).
  *
  * @param other the other MZCondition
  */
 public MZCondition(MZCondition other)
 {
     keyLevel    = other.keyLevel;
     switchState = other.switchState;
 }
 /**
  * Determines whether another MZCondition is necessarily true if this one is.
  *
  * @param other the other MZCondition
  * @return  whether the other MZCondition is implied by this one
  */
 public bool Implies(MZCondition other)
 {
     return(keyLevel >= other.keyLevel &&
            (switchState == other.switchState ||
             other.switchState == SwitchState.Either));
 }
Exemple #13
0
 public MZRoom(int id, Vector2Int coords, MZRoom parent, MZSymbol item, MZCondition precond) :
     this(id, new List <Vector2Int> {
     coords
 }, parent, item, precond)
 {
 }
Exemple #14
0
 /**
  * @param precond   the precondition to set this MZRoom's to
  * @see MZCondition
  */
 public void SetPrecond(MZCondition precond)
 {
     this.precond = precond;
 }