i wish to make an infinite maze of rooms that would essentially make this the backrooms.

I have stats for hunger, thirst, sanity that decrease every turn, I have a starter kit of tools for the player, a chest, equipment for cooking, water and everything for the player to choose to bring. I'm making a backrooms survival game, and the number one thing I need is, infinite rooms with random item spawns for objects "Almond Water" and "Brandless Potato Chips", butcherable animal corpses, and enemy creatures to fight or run away from.

I would like someone to please supply a short code to randomly generate rooms as that is the only feature I can't do alone with my knowledge.
If the script is too long for you to send here in the forums, please shove it in a .txt file on github as that is the only other site I can access at the moment.


also, anyone who helps will get to choose if they wish to show up as an NPC, a human corpse or an etched name on an object to be found via a magnifying glass.


There's a bunch of different ways to do a random dungeon. The one I would recommend as easiest is having a couple of rooms that the player can't reach, and cloning them to add to the map when you need them.

So that you don't have multiple rooms in the same place, you could use a dictionary to store a reference to the room at each location.

Exits leading "out" of the map (to a room that isn't built yet) would have a script that runs when the player tries to use them. It would do the following:

  • Pick a template room (if there's more than one option) and clone it here
  • foreach (room adjacent to the new location)
    • check if that room has an exit leading in this direction. If so:
      • make the exit point to this room
      • make the exit non-special
      • make a corresponding exit in the other direction
    • if there is no room there
      • if (random chance)
        • create a new exit leading off the map, which will do the same thing as this one
  • foreach (possible objects that could be in the new room):
    • if (random chance)
      • clone the object into the newly created room
  • the room is now created - move the player into it

Does that make sense?


I have a Basic program that will build a random map with only one path from start to end...
and you can select the size of the maze.
Unfortunately, it was written to create east and south walls, and you "draw" your way through it.
Also, unfortunately, I can't make head nor tails out of how it is written. :(
BUT, I do have a translation program to create the other 2 walls to create "rooms".
I know you want to create the maze "on the fly", but this would be an alternative option.
Then with a created map, a way to randomly populate it as needed.


Do you know how to work with clones?

It sounds like you're going to be dealing with a lot of cloned objects; and it's probably a good idea to make sure you have the basics of clones down before you start cloning whole rooms.


Here's one way I would consider making an infinite dungeon.

  • An inaccessible room named MAZE TEMPLATES which contains one or more "template" rooms. These are just so that you can give the room an alias and a description. If you have a few different types of rooms, you can make your maze feel less monotonous.
  • An inaccessible room named OBJECT TEMPLATES containing stuff like potions, collectibles, and monsters that you might want to put in the maze.
    • If you want these objects to do more randomisation (such as a chest with random contents), you can give them an initialisation script - but check that they aren't the original object before adding contents to them (the initialisation script will be run once for the original, then once for each clone)
  • Make a starting room, so that you can put the player in it and not need to think about all that stuff. Have an exit (or a few exits) leading out of it.
    • The exits leading into the maze should have a script on them: game.pov.parent = GenerateRoom(this)
  • Make a function GenerateRoom with a single parameter exit, and type "object". The script:
if (not HasAttribute (game, "mazerooms")) {
  game.mazerooms = NewObjectDictionary()
}
if (HasString (exit, "maze_coords")) {
  if (not HasInt (exit, "dest_x")) {
    dest_coords = Split (exit.maze_coords, "/")
    exit.dest_x = ToInt (ListItem (dest_coords, 0))
    exit.dest_y = ToInt (ListItem (dest_coords, 1))
  }
  dest_x = exit.dest_x
  dest_y = exit.dest_y
}
else {
  if (not HasInt (exit.parent, "maze_x")) {
    exit.parent.maze_x = 0
    exit.parent.maze_y = 0
  }
  dest_x = exit.parent.maze_x
  dest_y = exit.parent.maze_y
  if (DoesInherit (exit, "north")) dest_y = dest_y - 1
  if (DoesInherit (exit, "south")) dest_y = dest_y + 1
  if (DoesInherit (exit, "west")) dest_x = dest_x - 1
  if (DoesInherit (exit, "east")) dest_x = dest_x + 1
  exit.dest_x = dest_x
  exit.dest_y = dest_y
  exit.maze_coords = dest_x + "/" + dest_y
}
if (DictionaryContains (game.mazerooms, exit.maze_coords)) {
  return (ObjectDictionaryItem (game.mazerooms, exit.maze_coords))
}
newroom = CloneObject (PickOneObject (GetDirectChildren (MAZE TEMPLATES)))
newroom.maze_x = dest_x
newroom.maze_y = dest_y
newroom.parent = null

// Check if any other doors lead here - make doors going out
foreach (door_in, FilterByAttribute (AllExits(), "maze_coords", exit.maze_coords)) {
  door_out = GetUniqueElementName("exit")
  dir = ReverseDirection (door_in.alias)
  create exit (door_out, dir, newroom, door_in.parent, dir+"direction")
  door_in.to = newroom
  if (ToString (door_in.script) = "game.pov.parent = GenerateRoom(this)") {
    door_in.script = null
  }
}

// Make a random set of doors leading out into the void, for creation of new rooms
directions = NewStringDictionary()
dictionary add (directions, dest_x + "/" + (dest_y - 1), "north")
dictionary add (directions, dest_x + "/" + (dest_y - 1), "south")
dictionary add (directions, (dest_x - 1) + "/" + dest_y, "west")
dictionary add (directions, (dest_x + 1) + "/" + dest_y, "east")
foreach (possible, directions) {
  // Adjust the number 60 to change how many exits the maze has
  if (not DictionaryContains (game.mazerooms, possible) and RandomChance (60)) {
    dir = StringDictionaryItem (directions, possible)
    newexit = GetUniqueElementName("exit")
    create exit (newexit, dir, newroom, null, dir+"direction")
    newexit = GetObject (newexit)
    newexit.maze_coords = possible
    newexit.script => {
      game.pov.parent = GenerateRoom(this)
    }
  }
}

// now put objects in the room
objectscreated = NewObjectList()
// here we have a minimum and maximum number of objects to put in the room - change if desired
for (i, 1, GetRandomInt (0, 5)) {
  obj = PickOneObject (GetDirectChildren (OBJECT TEMPLATES))
  if (not ListContains (objectscreated, obj)) {
    list add (objectscreated, obj)
    newobj = CloneObjectAndMove (obj, NewRoom)
    if (HasScript (newobj, "_initialise_")) {
      do (newobj, "_initialise_")
    }
  }
}

return (newroom)

That's just a quick attempt off the top of my head, but I think it should work.


Here's a little more detail:
Maze supposed to be inescapable.
Small chance that room floodlight is smashed and room is dark

mrangel, it somewhat makes sense.

DarkLizerd, i'm listening..


My Dark Mystic Maze used the created mazes.
I tested an idea, a room's description included what you could see in the next rooms all the way to the far wall.
I never got too far with it, but it did have room pictures, and showed all the rooms to the end.
I never had a way to see the exit until you ran into it.

But why a maze with no exit?
You could include some one way doors to really mess people up, BUT, with a random map, you may trap the player in a small area.


i'm ok with trapped players, as I am planning on letting the player break a wall to continue if they're stuck.


A bit more randomness; this is the initialisation script I might use for a crate/chest in the object templates. When spawned, it selects a bunch of random objects to fill itself with.

if (HasObject (this, "prototype") and not this.prototype = this) {
  objects = FilterByAttribute (FilterByAttribute (GetDirectChildren (TEMPLATE OBJECTS), "take", true), "drop", true)
  for (i, GetRandomInt(-3,2), GetRandomInt(0,4)) {
    obj = CloneObjectAndMove (PickOneObject (objects), this)
    if (HasScript (obj, "_initialise_")) {
      do (obj, "_initialise_")
    }
  }
}

This only picks objects that can be taken and dropped, so you don't get monsters or more crates in the crate.


Of course... the chest COULD be a monster... I've played several games that had a mimic that would look like a chest just waiting for the unexpecting adventurer to come along.

Break walls... Maybe a "Harvey Wall Banger" potion???
Maybe a "Wreck-it Ralph" medallion?
Perhaps even a "portable hole"??? Just slap it on the wall and you have an instant hole.
Perhaps, the adventure finds a spray bottle of a cleaner labeled "Formula 410".
https://youtu.be/uRce2B8wOSk
But it only has 2 or 3 "shots" remaining.


Log in to post a reply.

Support

Forums