Attnam / ivan

Iter Vehemens ad Necem - a continuation of the graphical roguelike by members of http://attnam.com
GNU General Public License v2.0
301 stars 43 forks source link

Implement expansive GLTerrain for GTerrainMap #548

Closed jakwings closed 5 years ago

jakwings commented 5 years ago

Expansive floors can help prevent blocking important entrances.

Also detect more errors about the script format.

Fix #541

attnam-bot commented 5 years ago

This pull request introduces 4 alerts when merging d9cc3095113145bfc90f6446306ef9c47949f157 into b12dd0cc3e7506e95ebceeda0eb2fa95392fe515 - view on LGTM.com

new alerts:


Comment posted by LGTM.com

andrewtweber commented 5 years ago

Interesting solution to the TX problem. I like it.

Do you have to explicitly mark tiles as expansive ? I'm just wondering if this also fixes cases where you're simply trying to get from the up staircase to the down staircase in a level, and are blocked by a piece of furniture.

ryfactor commented 5 years ago

new alerts:

  • 4 for Wrong type of arguments to formatting function

The format specifier for Room.size() (which is unsigned long), needs to be %lu rather than %d.

EDIT: I like your solution too, by the way.

jakwings commented 5 years ago

Do you have to explicitly mark tiles as expansive ?

Yes, only awailable for GLTerrain in GTerrainMap for now. It was a good practice to familarize myself with the codebase but I don't think it is a good solution because the use case seems rare and it make the code more convoluted. A sophiscated rewrite of the whole dungeon generation algorithm would be better.

I'm just wondering if this also fixes cases where you're simply trying to get from the up staircase to the down staircase in a level, and are blocked by a piece of furniture.

I haven't added the flag to staircases, not checked the generation order of squares either. So no.

Shouldn't furniture normally generated in a room? And a staircase can only be blocked by an impassable room?

andrewtweber commented 5 years ago

Yes, somebody has had a situation where the only hallway connecting the 2 staircases had a room where one doorway was blocked by furniture.

I know that we changed most of the furniture so that it can be walked on, but it could happen in the future.

But yeah I guess just marking every staircase in each map (except the ones in hidden rooms) as Expansive would fix that.

jakwings commented 5 years ago

Only one square is marked at a time. After marking all expansive squares, other code simply checks if there is an expansive square next to the border (wall) or next to the unwalkable square (furniture), and then prevent placing a room or furniture.

If it is by design (GTerrainMap operated before OTerrainMap and special Square) that a water tile is next to the expansive, then it won't ABORT because maybe you demand the character swim or fly over the tile.

AquariusPower commented 5 years ago

I thought initially that the map size would be enlarged based on the necessity :)

prevent placing a room or furniture

does it means something like: on a room that usually have an anvil, a chair and the forge, such room could be spawned missing the anvil? not that would be a problem as we can build all the 3 of them.

jakwings commented 5 years ago

does it means something like: on a room that usually have an anvil, a chair and the forge, such room could be spawned missing the anvil?

It only checks the marks specified in Room->GTerrainMap. The marks can be outside the rooms (but still inside the level). If there is no enough space for placing the specified furniture, it will simply ABORT or infinitely loop. I haven't checked whether a random-size room will always has enough space.

If the the furniture is placed randomly inside a random-size room, there is no way to manually set the expansive tiles beforehand. I didn't add any thing to prevent blocking a tunnel by a random impassable room.

    /* not optional */
    Room
    {
      /* not optional */
      Square, Random HAS_NO_OTERRAIN;
      {
        /* not optinal */
        OTerrain = decoration(DOUBLE_BED);
      }

      Square, Random HAS_NO_OTERRAIN;
      {
        OTerrain = decoration(DOUBLE_BED);
      }
    }
############################
   random tunnel           #
#########################+##
                  #       X####################
          random->#       X+     random tunnel
           room   #############################

Another unresolved problem is — some random blockers (X) are placed this way:

     Really Poor Castle        #
###########...##################
         X.@@@.X
         X.....X
        ##########
        #        #
        # Random #
        #  Room  #
        ##########

So I just lowered the possibility of blocking the castle.


not that would be a problem as we can build all the 3 of them.

I think I will always die from starvation and enemies' strikes. :p

jakwings commented 5 years ago

EDITED: Ah, I reread my code. It will break the infinite loop when placing special squares. So a randomly put furniture may disappear only due to an expansive square. :p

AquariusPower commented 5 years ago

interesting, so it is more like safe squares (squares that shall be ignored when generating the random level, to prevent blocking the passage),

not sure but some usage example (with before and after results), could be added on the documentation to help ppl on understanding how to better prepare/fix/improve the maps :)

wouldnt this suffice ?

     Really Poor Castle        #
###########...##################
         @.@@@.X
         X.....@
        ##########
        #        #
        # Random #
        #  Room  #
        ##########