{"id":9024,"date":"2024-12-24T03:00:00","date_gmt":"2024-12-24T08:00:00","guid":{"rendered":"https:\/\/www.both.org\/?p=9024"},"modified":"2024-12-20T14:23:17","modified_gmt":"2024-12-20T19:23:17","slug":"enjoy-the-holidays-with-this-ascii-fireplace","status":"publish","type":"post","link":"https:\/\/www.both.org\/?p=9024","title":{"rendered":"Enjoy the holidays with this ASCII fireplace"},"content":{"rendered":"<div class=\"pld-like-dislike-wrap pld-template-1\">\r\n    <div class=\"pld-like-wrap  pld-common-wrap\">\r\n    <a href=\"javascript:void(0)\" class=\"pld-like-trigger pld-like-dislike-trigger  \" title=\"\" data-post-id=\"9024\" data-trigger-type=\"like\" data-restriction=\"cookie\" data-already-liked=\"0\">\r\n                        <i class=\"fas fa-thumbs-up\"><\/i>\r\n                <\/a>\r\n    <span class=\"pld-like-count-wrap pld-count-wrap\">    <\/span>\r\n<\/div><\/div>\n<p>There\u2019s nothing quite like sitting in front of a warm fireplace over the holidays. And because it\u2019s the holidays, I wanted to share that experience with you.<\/p>\n\n\n\n<p>I like working on <a href=\"https:\/\/www.freedos.org\/\">FreeDOS<\/a>, an open source implementation of the classic DOS operating system. We can use OpenWatcom C on FreeDOS to make a passable \u201cfireplace\u201d animation, with the <em>extended ASCII<\/em> characters from DOS Code Page 437 and the <em>text window<\/em> feature of DOS console mode programming.<\/p>\n\n\n\n<p>The basics of writing this program are this: We\u2019ll animate our \u201cfire\u201d by defining a \u201cwindow\u201d that\u2019s one column wide, then print a string of several characters in it. With a narrow window, DOS will \u201cwrap\u201d the text at the window\u2014an easy way to quickly generate a column of characters to simulate \u201cfire.\u201d If we select random offsets for the fire, we can make the \u201cfire\u201d different heights, just like real flame. We\u2019ll define the \u201cfire\u201d using a series of shaded characters, from \u201clight\u201d to \u201cdark,\u201d in either orange or yellow.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"random-values-for-random-heights\">Random values for random heights<\/h2>\n\n\n\n<p>We\u2019ll need to generate a series of random numbers to simulate the different heights of the flames. In Linux, the best way to generate <a href=\"https:\/\/www.both.org\/?p=7448\">random numbers from the Linux kernel<\/a> is with the <code>getrandom<\/code> system call. But FreeDOS doesn\u2019t have a system call like this; instead, we need to use the <code>rand<\/code> pseudo-random function from the standard C library.<\/p>\n\n\n\n<p>To use <code>rand<\/code>, you need to <em>seed<\/em> the random number generator at a starting point. The best way to pick a seed is to use the system time, using the <code>time<\/code> function, which returns the current time as the <em>number of seconds<\/em> since the epoch. Having set the seed appropriately, every call to <code>rand<\/code> will generate a pseudo-random number between zero and some maximum value. Here\u2019s a demonstration:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;stdio.h&gt;\n#include &lt;stdlib.h&gt; \/* rand *\/\n#include &lt;time.h&gt;   \/* time *\/\n\nint main()\n{\n    int i;\n\n    srand(time(NULL));\n\n    for (i = 0; i &lt; 10; i++) {\n        printf(\"%d\\n\", rand());\n    }\n\n    return 0;\n}<\/code><\/pre>\n\n\n\n<p>If you compile this program as <code>random.c<\/code> and run it, you should see ten random numbers:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>C:\\SRC&gt; WCL -q random.c\nC:\\SRC&gt; RANDOM\n3966\n5350\n3368\n23404\n21324\n10824\n567\n16513\n5861\n20438<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"draw-a-window\">Draw a window<\/h2>\n\n\n\n<p>Using text windows in DOS is a common way to control the screen. Text windows are defined by video memory, and allow you to define an area of the screen to work in. You can clear just this area of the screen, and even set a new background color for it.<\/p>\n\n\n\n<p>Be careful when printing text in a window, however. If your text reaches the end of the window, it will \u201cwrap\u201d immediately to the next line. This is not what you usually want. Except our \u201cfire\u201d program is a special case, where we can use this feature to quickly draw a column of text:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;stdio.h&gt;\n\n#include &lt;conio.h&gt;\n#include &lt;graph.h&gt;\n\nint main()\n{\n    _setvideomode(_TEXTC80);\n\n    _settextwindow(5, 40, 20, 40);\n    _setbkcolor(1); \/* blue *\/\n    _clearscreen(_GWINDOW);\n\n    _outtext(\"Hello, world!\");\n\n    getch();\n    _setvideomode(_DEFAULTMODE);\n\n    return 0;\n}<\/code><\/pre>\n\n\n\n<p>This program uses functions specific to OpenWatcom C; you may need to use different functions if you prefer another C compiler on DOS. The functions to define a text window and set colors are defined in OpenWatcom\u2019s <code>graph.h<\/code> header file. The program also uses <code>getch<\/code> to wait for a keypress; this function is defined in OpenWatcom\u2019s <code>conio.h<\/code> header file.<\/p>\n\n\n\n<p>This program sets the video mode to <em>text mode<\/em> using color (instead of monochrome) with 80 columns and 25 rows. Then, the program creates a text window starting at row 5, column 40 in the upper-left to row 20, column 40 in the lower-right; this is a 1-column window with 16 rows. The program sets the background color to <code>1<\/code>, which is blue in the <a href=\"https:\/\/www.both.org\/?p=5546\">DOS color palette<\/a>, then clears the window, which sets the background color for the window.<\/p>\n\n\n\n<p>Using the <code>_outtext<\/code> function, the program then prints a string in the window, then waits for the user to press a key before resetting the video mode back to the defaults and exiting to DOS.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"533\" height=\"400\" src=\"https:\/\/www.both.org\/wp-content\/uploads\/2024\/12\/fire1.png\" alt=\"\" class=\"wp-image-9027\"\/><figcaption class=\"wp-element-caption\">A 1-column text window in DOS<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"random-flames\">Random flames<\/h2>\n\n\n\n<p>We can leverage the 1-column window to draw a string of characters to the screen. To simulate \u201cflames\u201d in text mode, we can use the extended ASCII characters in DOS Code Page 437: characters 0xb0, 0xb1, and 0xb2 are three different levels of shaded boxes, from light to dark, and 0xdb is a completely filled box. If we set the text color to either orange or yellow, these four characters can simulate a flame.<\/p>\n\n\n\n<p>We can use OpenWatcom\u2019s <code>_outmem<\/code> function to print out only a few characters from a string. This is like OpenWatcom\u2019s <code>_outtext<\/code> function, but <code>_outtext<\/code> prints an entire string, while <code>_outmem<\/code> lets us specify how many characters to print. Let\u2019s define a 7-character array that starts with three spaces (I\u2019ve used the characters 1, 2, and 3 so we can see them) then includes the four \u201cflame\u201d characters:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>char fire&#91;7] = { '1', '2', '3', 0xb0, 0xb1, 0xb2, 0xdb };<\/code><\/pre>\n\n\n\n<p>If we used <code>_outmem(fire, 4)<\/code>, we would always print the first four characters from the array. To print from some arbitrary starting point in the array, we need to use a pointer in the array. For example, if <code>char *f<\/code> is a character pointer, we can set the value of <code>f<\/code> to the <code>fire<\/code> array, then advance the pointer a certain number of positions. Moving ahead by three positions sets the <code>f<\/code> pointer to the fourth element in the <code>fire<\/code> array, which is <code>0xb0<\/code>. Printing four characters from <code>f<\/code> prints the flame characters:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>char fire&#91;7] = { '1', '2', '3', 0xb0, 0xb1, 0xb2, 0xdb };\nchar *f;\n\nf = fire;\nf += 3;\n\n_outmem(f, 4);<\/code><\/pre>\n\n\n\n<p>This array \u201ctrick\u201d makes it possible to simulate fire. To draw a \u201cflame,\u201d we set the array position in <code>f<\/code> ahead by up to three characters from the <code>flame<\/code> array, then print four characters from <code>f<\/code>. If the offset is zero, we print three spaces, then the first shaded box. If the offset is one, we print two spaces, then the first two shaded boxes. And so on for up to three positions.<\/p>\n\n\n\n<p>We can pick a random starting position using <code>rand()<\/code> and ensuring the value is in the range 0, 1, 2, or 3. One way to do this is with the <em>modulo<\/em> (<code>%<\/code>) operator, like <code>rand() % 4<\/code> to return a value from 0 to 3. But if you look at the binary representation of 3, it\u2019s binary <strong>0000 0011<\/strong>, so using a binary operation of <code>rand() &amp; 3<\/code> will \u201cmask\u201d the first two bits, giving a final value that\u2019s 0, 1, 2, or 3.<\/p>\n\n\n\n<p>Putting it all together, we can define a text window that\u2019s one column \u201cwide\u201d and five rows \u201ctall,\u201d and <code>_outmem<\/code> will print four characters from a random starting point. Because the window is one column wide, the text will \u201cwrap\u201d all the way down the text window. We need to set the text window to be one row \u201ctaller\u201d than the array so the text doesn\u2019t scroll out of the window.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;stdio.h&gt;\n#include &lt;stdlib.h&gt; \/* rand *\/\n#include &lt;time.h&gt;   \/* time *\/\n\n#include &lt;conio.h&gt;\n#include &lt;graph.h&gt;\n\nint main()\n{\n    int col, n;\n    char fire&#91;7] = { '1', '2', '3', 0xb0, 0xb1, 0xb2, 0xdb };\n    char *f;\n\n    srand(time(NULL));\n\n    _setvideomode(_TEXTC80);\n\n    for (col = 1; col &lt;= 80; col++) {\n        _settextwindow(5, col, 9, col);\n\n        n = rand() &amp; 3; \/* binary: 0, 1, 2, or 3 *\/\n        f = fire;\n        f += n; \/* advance ptr *\/\n\n        _outmem(f, 4); \/* print *\/\n    }\n\n    getch();\n    _setvideomode(_DEFAULTMODE);\n\n    return 0;\n}<\/code><\/pre>\n\n\n\n<p>If we save this program as <code>fire.c<\/code> and compile it with OpenWatcom, we\u2019ll see a random mix of characters across the screen, each displayed as four characters in 80 columns:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"533\" height=\"400\" src=\"https:\/\/www.both.org\/wp-content\/uploads\/2024\/12\/fire2.png\" alt=\"\" class=\"wp-image-9026\"\/><figcaption class=\"wp-element-caption\">ASCII text from the &#8216;fire&#8217; array<\/figcaption><\/figure>\n\n\n\n<p>The numbers are placeholders for spaces, and demonstrate that we\u2019re only printing up to four characters from random starting positions in the <code>fire<\/code> array.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"animating-a-fire\">Animating a fire<\/h2>\n\n\n\n<p>To animate a fire, we need to make a few small changes to the program: We\u2019ll randomly pick either orange (color 6) or bright yellow (color 14) to print each column of \u201cflames.\u201d One way to do this is with a simple <code>if<\/code> statement that tests if a random number is odd (in theory, half of the time):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>if (rand() &amp; 1) {\n    _settextcolor(6); \/* orange *\/\n}\nelse {\n    _settextcolor(14); \/* br yellow *\/\n}<\/code><\/pre>\n\n\n\n<p>Also, we\u2019ll continue to draw the flames until the user presses a key; we can use <code>kbhit<\/code> from <code>conio.h<\/code> to do that. The <code>delay()<\/code> function from <code>i86.h<\/code> can add a short delay after each loop, so the fire doesn\u2019t \u201cburn\u201d quite as quickly.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>do {\n    ...\n\n    delay(100);\n} while (kbhit() == 0);<\/code><\/pre>\n\n\n\n<p>We\u2019ll also change the \u201cnumbers\u201d in the <code>fire<\/code> array to spaces. This lets us skip the extra step of clearing the text window before we draw to it; the spaces will effectively erase whatever text was there before.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;stdio.h&gt;\n#include &lt;stdlib.h&gt; \/* rand *\/\n#include &lt;time.h&gt;   \/* time *\/\n\n#include &lt;conio.h&gt;\n#include &lt;graph.h&gt;\n#include &lt;i86.h&gt;    \/* delay *\/\n\nint main()\n{\n    int col, n;\n    char fire&#91;7] = { ' ', ' ', ' ', 0xb0, 0xb1, 0xb2, 0xdb };\n    char *f;\n\n    srand(time(NULL));\n\n    _setvideomode(_TEXTC80);\n    _displaycursor(_GCURSOROFF);\n\n    do {\n        for (col = 1; col &lt;= 80; col++) {\n            _settextwindow(5, col, 9, col);\n\n            if (rand() &amp; 1) {\n                _settextcolor(6); \/* orange *\/\n            }\n            else {\n                _settextcolor(14); \/* br yellow *\/\n            }\n\n            n = rand() &amp; 3; \/* binary: 0, 1, 2, or 3 *\/\n            f = fire;\n            f += n; \/* advance ptr *\/\n\n            _outmem(f, 4); \/* print *\/\n        }\n\n        delay(100);\n    } while (kbhit() == 0);\n\n    if (getch() == 0) { getch(); }\n    _setvideomode(_DEFAULTMODE);\n\n    return 0;\n}<\/code><\/pre>\n\n\n\n<p>This version of the program also hides the cursor with <code>_GCURSOROFF<\/code>.<\/p>\n\n\n\n<p>If you compile and run the new program, you can relax in front of an ASCII \u201cfire\u201d in FreeDOS:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"533\" height=\"400\" src=\"https:\/\/www.both.org\/wp-content\/uploads\/2024\/12\/fire3.png\" alt=\"\" class=\"wp-image-9025\"\/><figcaption class=\"wp-element-caption\">A warm, animated fireplace in ASCII text<\/figcaption><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>Enjoy the holidays by writing a &#8216;fire&#8217; program in ASCII text.<\/p>\n","protected":false},"author":33,"featured_media":5253,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_lmt_disableupdate":"","_lmt_disable":"","footnotes":""},"categories":[340,150],"tags":[267,147,152],"class_list":["post-9024","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-freedos","category-programming","tag-freedos","tag-fun","tag-programming"],"modified_by":"Jim Hall","_links":{"self":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/9024","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/users\/33"}],"replies":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=9024"}],"version-history":[{"count":4,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/9024\/revisions"}],"predecessor-version":[{"id":9032,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/9024\/revisions\/9032"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/media\/5253"}],"wp:attachment":[{"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=9024"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=9024"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=9024"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}