# how to make ascii ui like in dwarf fortress

Only one text field, and inside it - different sections, menus, and popups, all in ascii. How to make that?

I mean something like this:

╔═════════════════╦══════╗
║                 ║      ║
║                 ║      ║
║                 ║      ║
║                 ║      ║
╚═════════════════╩══════╝


I see only the possibility to draw each line, calculating line length and somewhat manually. But maybe there is some kind of a simple way i am not aware of?

• There might be libraries or standard functions to place characters at arbitrary screen positions. What's your programming language and platform? Dwarf fortress in particular used to use ncurses but then faked it by using SDL with tiles and sprites which just happen to look like ASCII characters. – Philipp Jan 30 at 9:19
• i would like to do it in Java. – lxknvlk Jan 30 at 11:33
• It's largely the same for any language. Java console output can also use VT100 control codes (position, colours, etc. on Window's you need a tiny bit of platform specific code to set ENABLE_VIRTUAL_TERMINAL_PROCESSING) or you have libraries like sourceforge.net/projects/javacurses , or take you pick of 2D graphics choices. – Fire Lancer Jan 30 at 13:57
• Note: Dwarf Fortress doesn't use a text field. It draws a font texture using OpenGL. – user253751 Jan 30 at 16:35

I can't think of a pre-made library to do this all directly, and with such a low "resolution", you probably want precise control over how wide each column is etc.

You can basically treat your display like a very low resolution image, (e.g. a char screen[80][50]) then write that out each update, or you can just print the chars directly using something like ncurses or platform specific APIs to specify position. Or fake the whole thing displaying it like a tile-array with images that happen to look like ASCII/Extended-ASCII using one of many 2D graphics libraries/APIs.

Starting with some basic things like a single single column, row, etc. You can then build up from there, like you could for other graphics. The borders for a two column layout like that might be:

// make BUFFER_WIDTH, BUFFER_HEIGHT variable if want to support any sized console/terminal
int panel_height = BUFFER_HEIGHT - 2 /*pad*/ - 2 /*borders*/;
int border_bottom_y = panel_height + 2;
int right_width = 30;
int left_x = 2;
int left_width = BUFFER_WIDTH - right_width - 2 /*pad*/ - 3 /*outer and inner line*/;
int border_middle_x = left_x + left_width;
int right_x = border_middle_x + 1;
int border_right_x = right_x + right_width;

draw_cell(1, 1, 201); // (x, y, char)
draw_row(left_x, 1, left_width, 205); // (x, y, width, char)
draw_cell(border_middle_x, 1, 203);
draw_row(right_x, 1, right_width, 205);
draw_cell(border_right_x, 1, 187);

draw_col(1, 2, panel_height, 186); // (x, y, height, char)
draw_col(border_middle_x, 2, panel_height, 186);
draw_col(border_right_x, 2, panel_height, 186);

draw_cell(1, border_bottom_y, 200);
draw_row(left_x, border_bottom_y, left_width, 205);
draw_cell(border_middle_x, border_bottom_y, 202);
draw_row(right_x, border_bottom_y, right_width, 205);
draw_cell(border_right_x, border_bottom_y, 188);


Which you can then re-factor into a reusable left_right_panels function/class, along with functions/properties to get the coordinates and size of the left and right panel for further drawing within them.

As you build up these functions, there will be less individual values you are having to work out manually, potentially just the key ones (like "I want the right panel to be 30 columns, and the left to be everything else").

You can also of course extend the functions to accept colour codes etc. And probably use named constants for the ASCII "graphics" characters.

• might i ask why you don't suggest a TextArea with a fixed font applied? – Martin Frank Jan 31 at 7:14
• @MartinFrank Hmm, mentally I just didn't think of it separately from a console. No GUI library I can think of has much in the way of "text area drawing routines", so still looking at a 2D char/"image" buffer and then "textArea.setText(gameScreen)" or for colours/etc. processing it into one of the supported "rich text" formats. – Fire Lancer Jan 31 at 12:45
• There is a support for colors and fonts in Textarea... And the lines would be addressed over the [String]array of the textbuffer. But drawing directly would work as well ;) – Martin Frank Jan 31 at 15:41

There's lots of information in the article about Output libraries on RogueBasin wiki.

You're likely looking for curses or one of the derivatives, like ncurses, PDCurses, etc. Such a style of library lets you render UIs in a text-based console, supporting for example sub-windows, changing text at specific coordinates, and depending on the specific library sometimes even higher-level UI elements like text boxes, checkboxes, or scrollable areas. This is much more efficient than doing it yourself and redrawing the entire screen every frame.

Many such libraries exist with Java bindings.

One approach would be to make your UI regularily and then just run it through an ASCII-Art Library (I found this one with 5 secs googling for example: https://www.baeldung.com/ascii-art-in-java )

However that might not be possible performance-wise on an actual game.

Then you'd probably have to do it yourself. Using a monospace font in all UI elements would be valuable (ones where EVERY letter and symbol has the same pixel width) and from there on simply calculate the necessary values in width/height.

[Since you mentioned Java as well:] JavaFX also allows CSS styling afaik so id't be easy to style the chars in a cool manner. It also works pretty smoothly with bigger text boxes

you could use the ASCII Table library. it provides a basic acces to draw tables in java.

Here's an example of an grid layout

+--------------------------------------------------------------------------------------------+
|                                                                                            |
|                                      Top Frame Margin                                      |
|                                                                                            |
|        ╔════════════════════════╦════════════════════════╦════════════════════════╗        |
|        ║ row 1 col 1 / cell 1,1 ║ row 1 col 2 / cell 1,2 ║ row 1 col 3 / cell 1,3 ║        |
|  F  M  ╠════════════════════════╩════════════════════════╬════════════════════════╣  F  M  |
|  r  a  ║            row 2 col 1&2 / cell 1,1/2           ║ row 2 col 3 / cell 1,3 ║  r  a  |
|  a  r  ╠════════════════════════╦════════════════════════╩════════════════════════╣  a  r  |
|  m  g  ║ row 3 col 1 / cell 1,1 ║            row 2 col 2&3 / cell 1,2/3           ║  m  g  |
|  e  i  ╠════════════════════════╩═════════════════════════════════════════════════╣  e  i  |
|     n  ║                      row 4 col 1&2&3 / cell 1,1/2/3                      ║     n  |
|        ╚══════════════════════════════════════════════════════════════════════════╝        |
|                                                                                            |
|                                     Bottom Frame Margin                                    |
|                                                                                            |
+--------------------------------------------------------------------------------------------+


this would be an example of an single cell:

╔══════════════════════════════╗