Table Based ASCII Map

I don’t even… What…

With some effort, including writing a whole program just to write out the code for every room, and their directions relative to each other, I’ve made a 16 by 16 grid of rooms.

In addition to this disturbing and utterly useless feat, I’ve also done something that I haven’t seen yet on this forum, and made some code to show you a map.

ASCII Map
An Interactive Fiction by ThisKobold
Release 1 / Serial number 250228 / Inform 7 v10.1.2 / D

A4

>show map
................
................
................
@...............
................
................
................
................
................
................
................
................
................
................
................
................

>east

B4

>east

C4

>east

D4

>show map
................
................
................
...@............
................
................
................
................
................
................
................
................
................
................
................
................

The map isn’t much to see right now- In fact, it’s all periods. But if you go to the table where each tile’s symbol is stored, you can change every tile. As long as you keep it in a certain list of unicode characters that are compatible with “[fixed letter spacing]”, the effect you get is one of an even grid of characters.

If you’ve played dwarf fortress, or NetHack, or Caves of Qud, or any roguelike game, really, you’ll recognize that the @ symbol shows where your character is on the grid.

Fun fact: There are 256 rooms. Once it gets to row 7 or 8, Inform begins to lag as it starts dealing with numbers in the triple digits. This is a 16 by 16 grid, and it is running code for every room to see whether or not the player is there.

If you are, it prints an @ symbol instead of the room’s map tile.

Onto the next topic. Making the table.

To create each room in the first place, I made code that prints “[room name] is a room.”, running through each variation necessary for the grid size you want. There is no way in hell I’m manually doing that for 256 individual rooms.

I also used this for the table. 256 rows in a table to make a 16 by 16 grid. However, a small hiccup arises when you try to do this- Inform 7 can’t print indentations, or tab.

All hope is not lost, however.

Instead of barking:
	Say fixed letter spacing;
	Let ID be 0;
	Repeat with Alpha running from 1 to 16:
		let Char be the letter corresponding to the number of alpha in the table of alphabet;
		Repeat with X running from 1 to 16:
			Now ID is ID plus 1;
			Say "[ID][apostrophe][quotation mark][char][X][quotation mark][apostrophe][quotation mark].[quotation mark][line break]";

Ignoring the necessity for a table listing the alphabet, this code creates properly formatted rows for each room in a table. Once you’ve copied and pasted the result into the source code, use the ‘Find And Replace’ function to replace every apostrophe with an indent, and the table is complete.

I don’t feel like showing the map code right now, because it’s horrible and probably not optimized, but I might show it later.

Using this table-making code, though, you can create a table with which to map an area in no time. With some clever room-naming schemes, or even just carefully altering the whole 256 row table to match the rooms you have, you can use it to map an area. The area doesn’t necessarily have to be a grid, either- You could hypothetically use this to show an ASCII map in whatever configuration you want, whether or not it matches the actual layout.

Is this code useless? Very likely. It lags the parser near the end of a particularly large grid. But it’s a very cool thing that I haven’t seen people do before.

Granted, I haven’t looked for it much.

I believe, however, that this is an accomplishment worth talking about, and a piece of code worth showing off here.

Let me know what you think, and if this is stupid.

Thank you.

7 Likes

I have had an idea for a way to both optimize it and make it work faster for traditional IF maps.

If you make the table of rooms much smaller, you can replace the “empty space” with raw, unchanging text that prints every time the map is called.

Now, the map only checks the rooms that you specify on the table, printing either their base tile or the @ symbol.

This both totally nullifies the need to make a table that is 256 rows long, and prevents the game from chugging at later rows.

It’s also much easier to do ASCII map art like this, and in fact you could probably make a function to make this even shorter.

I’ll have to try it later.

P.S. If you want to make one of these maps for your own game I’d be happy to help figure something out, either by looking at your code directly or describing in more detail what exactly I did, and adapting it to your map. I’m sure there are plenty of people here who could just reverse engineer the same effect, but I would love to help anyway.

1 Like

Nice! I’m a big fan of ASCII-art automaps for complicated structures in IF.

I did something similar in I7 a while back, though the map is significantly smaller (to deal with the slowness you mentioned). It places the rooms at runtime rather than compile-time, and then only lets you have a certain number of rooms on the map at once, so that the calculations don’t get impractically slow.

I’ve had a bit more success in Dialog, but that’s with an entirely static map that never changes during play—Dialog’s a lot worse than I7 at dynamically updating the map, so the majority of the layout has to be set at compile-time. That makes it less useful for a roguelike experience.

3 Likes

Following up on the idea I mentioned before, I have a slightly more conventional map that reveals areas you’ve explored, while still showing your current position.

Map 1 shows the areas you’ve explored, as well as your current position, while Map 2 simply reveals the whole map without your position.

ASCII Map 2
An Interactive Fiction by ThisKobold
Release 1 / Serial number 250228 / Inform 7 v10.1.2 / D

Z

>map 1
 --@--
 -----
 -----
 -----
 -----

>s

C

>map 1
 --O--
 --@--
 -@@@-
 -----
 -----

>map 2
 --O++
 --+-+
 0+++O
 ----+
 ----O

>map 1
 --O--
 --@--
 -@@@-
 -----
 -----

>e

Y

>s

F

>s

G

>map 1
 --O--
 --+--
 -+++O
 ----+
 ----@

>

This one doesn’t create a full 5 by 5 grid of rooms; Instead, the ‘empty space’ is a static, unchanging piece of text.

Here’s the code that prints the map, every time you ask for it:

Instead of map 1 when the location is in A1:
	repeat with X running through rooms in A1:
		if X is visited:
			now the real corresponding to the place of X in the table of map is the symbol corresponding to the place of X in the table of map;
		Else:
			now the real corresponding to the place of x in the table of map is "-";
	Now the real corresponding to the place of the location in the table of map is "@";
	Let Z be the real in row 1 of the table of map;
	Let B be the real in row 2 of the table of map;
	Let C be the real in row 3 of the table of map;
	Let D be the real in row 4 of the table of map;
	Let Y be the real in row 5 of the table of map;
	Let F be the real in row 6 of the table of map;
	Let G be the real in row 7 of the table of map;
	say fixed letter spacing;
	say " --[Z][B][B][line break]
	--[C]-[B][line break]
	[D][C][C][C][Y][line break]
	----[F][line break]
	----[G][paragraph break]";

The letters are the rooms. The ‘real’ is the symbol that represents a discovered room, and it starts out as a simple dash, to represent empty space. If you’re in a room, it shows up as an @ symbol, a-la nethack.

I had to dictate the “if it is unvisited” thing in order to… wait a minute… I just realized how stupid my code is. Nevermind that bit of unoptimized code; I’ll deal with it later.

Anyway, though, this is a little 7 room dungeon that comes with a map! How cute is that?

@Draconis Haha yeah… I don’t think I’m at a state right now to be able to even comprehend the kind of code that would go into representing a changing map. I can barely work through making this dinky little 5 by 5 grid.

I’m proud of my little dungeon though.

 --O++
 --+-+
 0+++O
 ----+
 ----O

My little dungeon…

3 Likes

I did something adjacent to this in Inform 6: The Wizard's Castle - Details

(The original Wizard’s Castle is text-only, but the z5 version linked on that page, and the Inform source, have a mode that shows an ASCII map using the z-machine status line.)

Here’s a similar project I put together for a “weekly challenge” on my Patreon. In addition to an auto-updating ASCII map, there’s a randomly-generated river and railroad (so that there’s something to display on the map?).

The way it works is, the rooms aren’t actually connected in the Informian sense. They’re assigned latitude and longitude values, and when you move in a direction, we modify your latitude and longitude and send you to the room with those coordinates. Looking at the source, one gets the sense that repeating through all 256 rooms over and over again should affect performance. But it seems to run fine on Borogove!

Map_Goof_Source.txt (15.7 KB)

2 Likes

This was a fun coding challenge.

For the ascii mapping, the most performant way to handle it that I’ve come up with so far was to organize my rooms into regions that represented rows on the map. Each region was given a list of map symbol texts, and each room was given a number that represented its index in the map region that it was in. Then I added an after going rule that edited the lists as needed. To display the map, I just looped through the regions and printed out the symbols in their mapping lists.

That worked really well for a simple map that just displayed the player’s position on the grid, but I wanted to do something a little more interesting than that. I also found it tedious to declare every individual room, so I decided to try creating an environment in a procedural way, similar to the example that @Afterward posted above.

I liked his idea of having a coordinate system, so I used that with some modifications. Unfortunately, having Inform position all of my rooms for me meant that it wasn’t going to allow me to do my region list trick, so I had to take a different mapping approach, and I didn’t want to follow Ryan Veeder’s lead there.

The Map Goof example uses a triple nested loop that iterates 65,536 times to draw a grid of 256 rooms. That’s a little excessive. I created a mapping loop that only does 256 iterations when given 256 rooms. I loaded both of them up in Quixe so I could check the command execution times, and it shows a significant improvement in performance over the huge triple loop approach. Not as lightning fast as my first map, but fast enough.

And generating the room layout works in a completely different way, but it’s pretty simple. Just imagine that you have a tunneling creature of some sort that you stick at a starting coordinate within some volume of space. It plants a room then looks around to see what directions it can travel in. It chooses a direction at random, plants another room there, and connects it to the room it’s currently in. Then it moves to the new coordinate and looks around again. Eventually, it gets to a coordinate where there are no open directions, at which point it starts backtracking along its previous path until it finds somewhere to go. It does this until it’s been everywhere and the map is complete.

This all results in a twisty little space that’s different on each playthrough. The downside is that it’s slow, but since this is code that only has to execute once when the game starts, that’s mostly okay. At least on my laptop. On my phone, the loading time was ungodly, so I’m deeming this one not mobile-friendly.

I’d also recommend not increasing the dimensions beyond what I’ve set them to here. It can handle a grid of 256 rooms, but once you push it up to 300 rooms it starts getting risky, and the compiler struggles. Anything beyond that and I found the most likely outcome to be Inform throwing a vicious, stack-overflowing bitch fit and telling me to go screw myself. It appears there’s a limit to the amount of recursion it can handle before it implodes.

Here’s a live example:
https://68bf7jgt.play.borogove.io/

And my source code:

Procgen Dungeon.txt (7.5 KB)

1 Like