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:
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.
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.OBJECT TEMPLATES
containing stuff like potions, collectibles, and monsters that you might want to put in the maze.
game.pov.parent = GenerateRoom(this)
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.