Dungeons - simple procedural map generator

Dungeons are a minimal ‘lego’ that can be used to build out adventures and games for the Loot ecosystem. Dungeons are designed to support 2D, 3D, and text-based worlds.

Examples


Principles

  1. This is a primitive. It is designed to play nicely with many other primitives.
  2. Let the game developers/dungeon masters make as many important decisions as possible, for example…
    a. Monsters
    b. Visual style
    c. Spawn points
  3. Expose everything via Solidity API (vs proprietary formats or focusing on the art)

What is a dungeon?
A Dungeon NFT is made up of three parts:

  1. ID (Number) - Each dungeon has a unique identifier (integer) numbered 1-1000.
  2. Image (png) - Each dungeon has a unique pixel art image representing it.
  3. Metadata (json) - Each dungeon has a json blob representing it which can be accessed from getters on the smart contract:
    a. id (int) - The ID of the dungeon
    b. img (???) - a reference to the Image of the dungeon
    c. layout (array) - A 2D array representing rooms, walls, and doors
    d. theme (int) - An integer depicting the color theme for the dungeon
    e. name (string) - The name of the dungeon

Why are they colored differently?
I thought it would be helpful to add some initial idea of a ‘location’ for each map. I tried to provide a set of different locations such as a forest area, an underwater area, etc. Game devs can choose to build on this or ignore it but I found it made dungeons that might appear somewhat similar feel quite unique and diverse.

These do not have to be tied to the specific colors I chose (the game dev just get an int for ‘theme’). This has the side effect of making the NFT artifact more interesting to look at / desirable to collect.

Where can I learn more?
We have an (inactive) Twitter account at @lootdungeons that we’ll start populating as we get closer to launch.

About the Team
threepwave is a generative artist and game designer with a background in virtual worlds.

13 Likes

This looks really cool. How are you thinking about representing them and letting people get/view them?

2 Likes

Representing
To make sure I understand your question on representing them, I’m planning to return a 2D array of text with a few characters to designate what lives in each tile (similar to how muds were defined back in the day). This feels like the lightest weight way for people to be able to injest them and build on top of them (vs more complex data structures).

This is the data structure I’m using currently to populate the art for dungeons:

const dungeon = [
  ['X', 'X', 'X', 'X', 'X'],
  ['X', ' ', ' ', 'X', ' '],
  ['X', ' ', 'X', 'd', ' '],
  ['X', 'd', ' ', ' ', 'X'],
  ['X', ' ', 'p', ' ', 'X'],
  ['X', 'X', ' ', 'X', 'X']
]

Each row of the array represents a row of dungeon tiles.
‘X’ represents a wall. ’ ’ represents an accessible tile. ‘d’ and ‘p’ are doors and points of interest but I will likely make these a bit more generic over time.

Claiming
My initial idea was to allocate ~1 per Loot owner and then offer extras for open mints so people who don’t have loot can participate. This would enable Loot owners to each have a unique dungeon (and follow patterns established thus far).

I haven’t thought through the dynamics of how these would be used (for example, I’m not sure what it means for someone to ‘own’ a dungeon). I don’t think that access should be gated to whoever owns the NFT so would love some thoughts here from others.

~10,000 unique dungeons feels about right as a starting point. This allows for a large amount of variety and different dungeons can be rotated, flipped, or linked together to provide lots of novel/new gameplay experiences. The number of combinatorics gets even better if users can add spawn points and additional metadata on top to generate even more permutations.

Any thoughts / feedback / ideas here would be appreciated as so far I’ve been focusing on delivering outputs with lots of variety and high quality.

3 Likes

One interesting idea was raised in Discord (thanks Hierux :crown:) was that the people who own dungeons could stake them with a realm, land, faction, etc. That would give anyone who visits that area a chance to see different dungeons and ‘land owners’ or similar groups that emerge more incentive to own/trade dungeons. I don’t think we need to do anything differently with the contract to enable this as the game logic and ‘staking’ (for lack of a better term) could be done separately and outside of this contract.

2 Likes

Hey threepwave, just wanted to take a second to congratulate you on what you’ve created so far with this project. This is one of the few derivative projects that I think actually aligns with the ethos of loot. It looks super interoperable, and offloading as many decisions to future devs is they way to go. These are the building blocks that are most important for this project long term. Thank you!

5 Likes

Cheers. Love the dungeon design overall and like Russell mentioned this will be a core building block moving forward. Looking forward to other devs getting their hands on it.

1 Like

@threepwave Been following this since you started in the Discord. This is an exciting direction for the Loot project. I also recall seeing a color palette shared there. Is it possible for you to bring that over here as well as part of the discussion?

1 Like

Thanks for the kind words and support folks. It helps a ton! I’m doing this during late nights and (soon to be) weekends, so the encouragement is rad!

@Bruedan here’s the palette you requested. I wanted to add a layer of differentiation on top of dungeons without being too opinionated. The names are just palette names, I likely will just include an int for the ‘environment’ vs a string representation. This will let developers take it in any direction they want. I think the colors also will make people who collect these dungeons more likely to print them out or put them on their walls :smiley:

3 Likes

This is one of the few derivative projects that I think actually aligns with the ethos of loot. It looks super interoperable, and offloading as many decisions to future devs is they way to go. These are the building blocks that are most important for this project long term. Thank you!

Big +1 to this. Been following along on Discord and love the principled approach. Keep up the great work.

I would also check if anyone in the artists or writes channels on Discord have feedback on the biomes and color schemes.

1 Like

Great project, I love how it looks. really looking forward to it and already thinking of things I could build on it.

I haven’t thought through the dynamics of how these would be used (for example, I’m not sure what it means for someone to ‘own’ a dungeon). I don’t think that access should be gated to whoever owns the NFT so would love some thoughts here from others.

I’m thinking that it could make a lot of sense for a dungeon owner to be the dungeon master in a literal way: they would have control over the dungeon setup.

For example:

  • Type, position, behavior of monsters and traps. They could pick these by spending a fixed amount of “dungeon master points” attached to the dungeon for example.
  • Adding welcome & congrats (for entering & leaving) messages for adventurers.
  • Maybe adding a way to add a long-form description of every object present? That way games could interpret e.g .a wooden box by its generic name, “wooden box”, or its dungeon description: “The wood of this box doesn’t seem to have seen any forest in a long, long time”.

Some inspiration links:

And a question: do you plan to have any way to make the entrance and exits of dungeons match with others? Or do you think this should be something let to the creators using it?

1 Like

All of your examples sound awesome! I think all of them would likely be best built as an additional layer on top of dungeons, after they’re already created.

My thought is that as we collectively build out the loot ecosystem, the goal should be creating “lego” pieces that are as easy to build upon as possible. By leaving the mechanisms you mentioned out (item descriptions, DM points, etc), Dungeons is more of a “minimum viable building block” that other devs can run with.

2 Likes

Yes I completely agree with keeping the base as minimal as possible (i.e. a dungeon map), and have additional ideas into separate layers − which may be L1 contracts or many other things!

2 Likes

Thanks for all the great feedback everyone!! I think we’re getting close to having final tuned dungeon code :slight_smile: I wanted to share some release notes today with folks. I have a family health emergency so progress has been slower than I’d like, but I was able to jump in and crank out some fixes today and this weekend is looking much better :slight_smile:

I’m doing a bunch of tuning with the dungeon sizes and probability of seeing points and doors (for example, doors only show up in hallways now). Would love if a few people have time to run through and give them a shot to share feedback.

note: there are going to be some rooms (especially smaller ones) with no points of interest or doors. I’m assuming this is ok as not every dungeon needs to have loot (and devs can choose to override this if they prefer). Would like feedback on this idea as well

dungeons v0.3 release notes

  • Supports 5x5 → 25x25 dungeons currently (increased from 5x5-10x10)
  • Doors only exist in hallways (vs randomly placed in rooms)
  • Points of interest only occur in rooms (vs randomly placed in hallways)
  • minimum room size reduced to 1 room (previously was 2)
  • maximum room size increased to room size / 1.5 (previously was 2)
  • The above two changes should result in more variety (more rooms per dungeon and less rooms per dungeon simultaneously)

Live Preview: https://lootdungeons.vercel.app/

Feedback Needed:

  • Are there enough doors and points of interest? Too many?
  • Is there variety in the different sizes and layouts of rooms? Does each piece feel unique?

Thank you for taking part in this journey!! Can’t wait to share this with the world.

@scatterbrained

I would also check if anyone in the artists or writes channels on Discord have feedback on the biomes and color schemes.

Thank you! I just shared some information about the project there: Discord

@bpierre

And a question: do you plan to have any way to make the entrance and exits of dungeons match with others? Or do you think this should be something let to the creators using it?

My current thinking is that this should be up to the game creators. For example, if we decide to go with a ‘staking’ mechanic described above, you could imagine that a game dev could build specifically for dungeons ‘held’ in the Divine Robes’ territory. They would then want to dynamically link between the specific dungeons they have access to (vs follow an arbitrary link). I’m also hoping that people build ‘campaigns’ on top of dungeons, stitching together spawn points, monsters, etc to make different experiences using the same dungeon.

1 Like

Based on how many times I refreshed https://lootdungeons.vercel.app/ , and how much I enjoyed checking them all out, I’d say they all feel unique and special! I think you’ve struck a good balance in terms of the amount of doors and POIs. Some felt right on the edge of too much (which was a good thing, right up to the line but not crossing it) and the rooms with no doors and no POIs felt like a little bare. Could definitely be up to the future devs, but personally if I minted an empty room, I’d feel a little disappointed. Having just one POI or door gives you so much more to imagine/room for creativity, and makes it feel like more than just a random 2D room shape.

Love what you’re doing with this project! If you need any help (especially with community management / documentation stuff), lmk!

3 Likes

Hm good point about the empty rooms… let me think about this. Perhaps each dungeon should have at least one ‘thing’ to it, even if it’s a tiny loot room:

I’m revisiting the API for dungoens and have been planning on amending the calls.

Here’s my current thinking.

Primary Audience:

  • Game Developers
  • Dungeon Masters
  • Artists or Writers who want to add metadata on top of the dungeon (e.g. environmental art, how to represent them as 3d, encounters and monsters, lore behind the dungeon)

Function Calls:
See updated post below with more detail and a consistent example.

  1. getDungeon() - Returns a 2D array representing all tiles in the dungeon as ascii characters. For example:
[
  ['X', 'X', 'X', 'X', 'X'],
  ['X', ' ', ' ', 'X', ' '],
  ['X', ' ', 'X', 'D', ' '],
  ['X', 'D', ' ', ' ', 'X'],
  ['X', ' ', 'i', ' ', 'X'],
  ['X', 'X', ' ', 'X', 'X']
] 
  1. numDoors(), numPoints(), numFloors(), numWalls(), numTiles() - Returns the number of individual spaces present (so you could say… query for dungeons with >3 doors)
  2. getRooms(), getHallways() - Returns an array of arrays of rooms and hallways (in case someone wants to place an encounter only in a room):
[ [3, 4], [2, 6], [1, 2], [0, 1], [3, 5], [6, 8] ]
  1. getDoors(), getPoints(), getFloors(), getWalls() - Returns a 1D array of each tile type. This will allow you to say, query for dungeons with >=2 doors or make every point a trap.
  2. getTile(x, y) - returns the value of a specific tile (so you could query from another product to see 'show me all dungeons with ___ at position x, y).
  3. getName(), getEnvironment - returns the name of the dungeon (string) or the environment (int) (so you could say 'get me all dungeons with environment=5 so i can build out fiery 3d land environments for all of them`

Would love to hear thoughts on this. Is this excessive? Am I missing anything? I tried to think through the ways I’d want to use and query these objects. @dom if you have a few minutes, would love your input here.

#3.1 – Sorry I’m a little confused. Is the array of arrays snippet meant to be an example output for the first #3.1 if run on the getDungeon call above it? The instance of [6,8] appearing out of bounds makes me think not but I might be daft. If not, maybe include a sample call to the example dungeon to be clear.

How are you defining a room? Is it a contiguous block of empty spaces? Is it the tile adjacent to the door? Does the definition of a room change when there are two entries into it? Is a hallway just a room of a specified width or smaller? A sample call for each function using the getDungeon call as sample data would help me here a ton.

#3.2 – 2. and the second 3. seem very similar. I’m terribly unfamiliar with Solidity though. Are you returning an array of pointers to their locations in the second 3?

I don’t think this is excessive. As an API user, I want to access all the raw dungeon data and one or two of the more high-use composite data components (like rooms, halls) as you defined.

#3.1 – Sorry I’m a little confused. Is the array of arrays snippet meant to be an example output for the first #3.1 if run on the getDungeon call above it? The instance of [6,8] appearing out of bounds makes me think not but I might be daft. If not, maybe include a sample call to the example dungeon to be clear.

Ah that is confusing. The examples are not related. I’ll edit so that they reference the same dungeon.

How are you defining a room? Is it a contiguous block of empty spaces? Is it the tile adjacent to the door? Does the definition of a room change when there are two entries into it? Is a hallway just a room of a specified width or smaller? A sample call for each function using the getDungeon call as sample data would help me here a ton.

Currently, rooms are large rectangular objects between 2x2->15x15 that are drawn initially and then hallways are placed. Rooms currently cannot intersect. Both rooms and hallways are ‘walkable’ tiles which is why they are both marked with ’ ’ in the dungeon but I’ve found it helpful (e.g. place a door only in hallways) to have a delineation in building the dungeons. I’ll write up sample API calls today for each of these using a consistent example so it’s clear.

#3.2 – 2. and the second 3. seem very similar. I’m terribly unfamiliar with Solidity though. Are you returning an array of pointers to their locations in the second 3?

Fixed numbering in original post so the ‘second number 3’ is now 4 :smiley:

The set of calls in #2 (e.g. numDoors) will return an integer that tells you how many discrete doors exist (e.g. 2). The set of calls in #4 will give you an array w/ the locations of all of the objects (e.g. if there is a door at (4, 6) and (9, 10) you will get [ [4, 6], [9, 10] ]. I could just provide the array of positions and a developer could infer the count from that (e.g. something like array.length) but I’m not sure if that’s an easy thing to do when querying the smart contract.