# Dwarf Fortress and Claude's ASCII Art Blindness

Claude has trouble playing Pokemon partially [because it can't see the screen very well](https://www.lesswrong.com/posts/uhTN8zqXD9rJam3b7/llms-can-t-see-pixels-or-characters#Why_can_Claude_see_the_forest_but_not_the_cuttable_trees_). This made me wonder if Claude would be better at an ASCII game like Dwarf Fortress, where it doesn't need to rely on image recognition.

To check this, I built an MCP server to let Claude control an interactive terminal, and installed a text version of [Dwarf Fortress](https://www.bay12games.com/dwarves/).

![](https://39669.cdn.cke-cs.com/rQvD3VnunXZu34m86e5f/images/16a7121ee840d016c8a31ddd3e1957e0159374e4bdfcf36c.png)

Screenshot from [this video](https://youtu.be/FLmPN03ZQbM?si=2rIEGsi1NgtKJVtn&t=510)

Unfortunately this was a failure, since Claude has significant trouble interpreting the screen, and even when I switched to a much simpler roguelike game ([Angband](https://rephial.org/)) it had trouble interpreting the 2D ASCII grid. To make this work well, an LLM would likely need to be trained with 2D position information and/or use character-level tokenization instead of [BPE](https://huggingface.co/learn/llm-course/en/chapter6/5).

Terminal Game Tooling
---------------------

Claude usually runs terminal commands until they end and then reads the output. This doesn't work for games since they expect commands while the game is running. Luckily, the Unix gods gifted us with [tmux](https://www.redhat.com/en/blog/introduction-tmux-linux): A tool that runs a persistent terminal, with commands to send key presses and read the content of the screen.

I [wrote an MCP server that wraps tmux](https://github.com/brendanlong/claude-code-plays-text-games), so Claude can use tools like:

*   send_keys(\["h", "e", "l", "l", "o", "Return"\])
*   read_output

Claude is extremely good at using this when the terminal output is easy to read.

![](https://39669.cdn.cke-cs.com/rQvD3VnunXZu34m86e5f/images/23c34910bb2673499e3bcb6620773b71aba0de77a06869fc.png)

See [demo on asciinema](https://asciinema.org/a/732644?t=10)

Dwarf Fortress ASCII Mode
-------------------------

Dwarf Fortress was traditionally ASCII-based, but the newest version uses graphics, and [the old terminal mode was removed](https://www.reddit.com/r/dwarffortress/comments/1asobw3/text_mode/). Luckily, there are still old versions floating around. The [dwarffortress snap package](https://snapcraft.io/dwarffortress) uses an old enough version that ASCII mode still exists, although you'll need to install the latest/edge version to [pick up a necessary library for text mode](https://github.com/ultraviolet-1986/df/pull/4).

Then you can enable text mode by editing `~/snap/dwarffortress/current/data/init/init.txt` to change PRINT_MODE to TEXT. See [this recording](https://asciinema.org/a/723439) for an example.

Color is Important
------------------

At this point, I ran into trouble because [Claude could sort-of play the game](https://www.youtube.com/watch?v=Mxl8P7YGsh0), but was weirdly bad at it. It would say that it was selecting something in the menu that it clearly wasn't, or it would miss obvious rivers of blue on the map.

I eventually realized that Dwarf Fortress uses colors to indicate things like your current selection, and tmux doesn't show those by default.

![](https://39669.cdn.cke-cs.com/rQvD3VnunXZu34m86e5f/images/357732213f94fe5e8dfcb45beacc07c2743b109cef17264f.png)

Dwarf Fortress world creation screen showing that the History row is selected (note the bold) and that Medium is selected (the cyan highlight).

I added [a mode to view color](https://github.com/brendanlong/claude-code-plays-text-games/commit/efd30b474ec07310ad5af7e22649d5d3f01cf7f4), and Claude got better at reading *some* of these screens...

Claude Doesn't See in 2D
------------------------

And here's where the experiment starts to break down. With colorized output, Claude could see menu selections, but it became *extremely* hard for it to understand the 2D map output, which was a mix of meaningless symbols and color instructions.

LLMs like Claude are trained on 1D text. Where we see ASCII art like:

            (__)
    `\------(oo)
      ||    (__)
      ||w--||

Claude sees[^njegn8svew]:

            (__)\n`\------(oo)\n  ||    (__)\n  ||w--||        

2D text games use ASCII art for their maps, and it turns out a Dwarf Fortress map including color codes is *very* hard to read in this format[^j1nllnmgbms], and [Claude was extremely confused](https://youtu.be/FLmPN03ZQbM?si=0DMVe8QBTUuAFSMX&t=529).

![](https://39669.cdn.cke-cs.com/rQvD3VnunXZu34m86e5f/images/a1d220226f0ec8bd54c6bda25fd2388ec9a25b915c853926.png)

Behold: [A perfectly readable map](https://pastebin.com/A5rgt1HB)

Let's Try Something Simpler
---------------------------

So, I decided to try another game: [Angband](https://rephial.org/). This is a roguelike game where you explore a dungeon. The map is much simpler, and doesn't use colors for anything important, so we don't need to pollute the tmux output with them.

To make things go more smoothly, I started by [having Claude generate some documentation by reading the help menu](https://asciinema.org/a/732645)[^d1a30n1p7u] so I could [reference it](https://docs.anthropic.com/en/docs/claude-code/common-workflows#reference-files-and-directories) in future sessions.

Then I told it to try to get through the dungeon... and it didn't work very well[^y155g95q28m].

![](https://39669.cdn.cke-cs.com/rQvD3VnunXZu34m86e5f/images/4c1f66d762b61fd9ab3c74ec6ec2998ef9ead2af961f6617.png)

[Claude Sonnet 4 playing Angband](https://asciinema.org/a/732646?t=30)  
Later sections of this video get garbled because of asciinema's interaction with nested tmux sessions, but the raw tmux output was fine.  
I also [recorded Claude Opus 4.1 having similar trouble](https://youtu.be/gCj60LbMaks).

It certainly works better than Dwarf Fortress, but it's clear that Claude can't tell where it is on this map either, or where the different rows in the output line up. It walks the wrong direction, runs into a lot of walls and can't catch up with the cat it wants to eat[^rlcr56dnw3c]. I added some tools to help it, like [numbering the rows](https://github.com/brendanlong/claude-code-plays-text-games/commit/94f78970b1b8173de486e5f39f9a3d4884d77ded) and [giving it the coordinates of specific characters](https://github.com/brendanlong/claude-code-plays-text-games/commit/ddbdfb83872b47c0aac414e1200d2c859bb9941d), but even with that, it gets lost if it doesn't ask for coordinates after every move.

This is the point where I gave up. The goal was to see if Claude could play 2D text games without assistance, and I think at this point it's clear that it would need significant assistance to use this input effectively.

Conclusion
----------

In summary,

*   Claude is pretty good at using tmux when it can understand the output.
*   It has a lot of trouble understanding 2D ASCII-art output.
*   Sometimes color is important, but colorized ASCII-art is even harder to read.

Making every token the same width instead of using [BPE](https://huggingface.co/learn/llm-course/en/chapter6/5) might help, but I think it would be really interesting if someone trained a model with 2D positional information. It's irrelevant for most text, but I imagine ASCII art is common enough in the training data that LLMs could learn to use it. Or it would be really easy to come up with synthetic data from terminal programs and games.

[^njegn8svew]: If it's lucky and none of the characters are merged into larger tokens. 

[^j1nllnmgbms]: It doesn't help that a Dwarf Fortress map is hard for humans to read, and we can see 2D. 

[^d1a30n1p7u]: Honestly, I'm just including this detail to prove that the tmux MCP server is actually useful when you're not trying to get Claude to read ASCII art. 

[^y155g95q28m]: I did hit my Claude Opus limits, but last I checked, Opus wasn't any better at this. I might retry it tomorrow just in case. 

[^rlcr56dnw3c]: Problem unrelated to this post: Claude generated and then read docs says that f is a Feline (cat), but it still assumed that an f on the map was food.