ondras / rot.js

ROguelike Toolkit in JavaScript. Cool dungeon-related stuff, interactive manual, documentation, tests!
https://ondras.github.io/rot.js/hp/
BSD 3-Clause "New" or "Revised" License
2.33k stars 254 forks source link

Corridor doesn't always guard against room corners #123

Closed airstruck closed 7 years ago

airstruck commented 7 years ago

This probably shouldn't happen:

seed-7953

Generated with seed 7953 on the interactive manual.

As far as I can tell, there are actually two ways this can happen. Corners are marked as "expandable" walls, but are usually not eligible for expansion since they have no empty space around them.

E - wall that could expand now
X - wall that won't expand now

XEEEX
E...E
E...E
E...E
XEEEX

But if a wall is removed next to them, they can be expanded, and you can end up with this:

XEEEX
E...E
E...E
E....
XEEE.

Once doors are added, this ends up looking pretty awkward.

The other reason it can happen (it looks like it happened here) is because doors don't really exist in the regular map data, and corridors will happily tunnel into existing doors, thinking they are just normal floors. See also the other odd "double-door" just to the left of the highlighted area in the image.

It looks like both cases could be fixed by actually including the doors in the map data, and treating them as a separate type of cell from walls and floors.

One idea could be treating the cell value as a bitfield, so 2 would mean an open door and 3 would mean a closed door. You could just check the low bit when you don't care about doors and just want to know if the cell is "open" or "closed."

ondras commented 7 years ago

Well, IIRC, door placement has no relation to actual map (room/corridor/wall) generation. So this issue is more specific to the door placement algorithm. Adding a condition "do not place doors next to an existing door" sounds like a straightforward modification.

airstruck commented 7 years ago

Well, IIRC, door placement has no relation to actual map (room/corridor/wall) generation.

Right, it doesn't, they're just added after the fact. I guess what I'm suggesting is to add them to the _map data as part of the digging process, so you can check for them when determining whether a feature is valid.

Adding a condition "do not place doors next to an existing door" sounds like a straightforward modification.

That might work. Removing one of the doors in the highlighted example would result in one of these:

#####          #####          
#...#          #...#          
#...#####      #...#####      
#.......#      #...+...#      
####+##.#      ####.##.#      
   #.##.#         #.##.#      
   #....#         #....#      
   ######         ######      

The left-hand example sort of makes sense, but the right-hand example looks like a door missing a wall next to it. Choosing which door to remove might involve looking at neighboring cells.

If both of the offending doors are removed, it doesn't look too bad but it might break the "every room has at least one door" test.

ondras commented 7 years ago

I guess what I'm suggesting is to add them to the _map data as part of the digging process, so you can check for them when determining whether a feature is valid.

Makes sense. Also probably makes the whole algo a lot more complex. Perhaps this approach can be used as a basis for a completely new map generating algorithm?

My own aesthetic criteria are probably not that strict: in my view, these maps correspond to hundred-years-old dungeons with many crumpled walls, damaged interiors and so on. Two doors next to each other do not pose a real issue.

If both of the offending doors are removed, it doesn't look too bad but it might break the "every room has at least one door" test.

I am okay with this as well. Door-less rooms are nothing special. In fact, I am not sure why the algorithm does place doors at all; perhaps doors should have been completely omitted and moved upwards to application-level?

airstruck commented 7 years ago

Two doors next to each other do not pose a real issue.

Good point. DCSS does this occasionally and calls them "big doors." Opening a door opens all doors adjacent to it, and all doors adjacent to those, and so on, all at once. But I've never seen them in sequence in a tunnel; they usually appear like this:

#####
#...#####
#...+...#
#...+...#
#...#####
#####

It does seem reasonable to say that doors belong at application level, and just leave everything as-is, with the existing doors being more of a suggestion about where you might want to place doors if you feel like it. So I guess we can close this as "works as intended." :+1: