summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Wührer <def@gmx.at>2026-04-26 15:47:41 +0200
committerDavid Wührer <def@gmx.at>2026-04-26 15:47:41 +0200
commit89312254e3eb1aa496dff15f2d503e97f3c985f2 (patch)
tree8877621b58aa0b2c26d87435abebb8a3f3d2ec34
parent912b6505f1335a1f9eabf55045b67e38738bdaf3 (diff)
-rwxr-xr-xbin/fire173
-rw-r--r--man/man1/fire.159
2 files changed, 232 insertions, 0 deletions
diff --git a/bin/fire b/bin/fire
new file mode 100755
index 0000000..b9c6c98
--- /dev/null
+++ b/bin/fire
@@ -0,0 +1,173 @@
+#!/bin/bash
+
+###
+# ASCII fire
+
+# TODO:
+# Better gradient for cooling flame.
+
+r=$'\e[31m'
+y=$'\e[33m'
+br=$'\e[1;31m'
+by=$'\e[1;33m'
+c=$'\e[0m'
+bs=$'\e[1;30m'
+#w=$'\e[37m'
+
+flame_gradient=(
+# "$w#$c"
+ "$by@$c"
+ "$by#$c"
+ "$y#$c"
+ "$y@$c"
+ "$br@$c"
+ "$br#$c"
+ "$r#$c"
+# "$bs($c"
+# "$bs($c"
+# "$bs)$c"
+# "$bs.$c"
+ " "
+)
+# TODO: Use 256 color palette.
+
+declare -ia cells=()
+
+##
+# init
+
+tput clear
+n_rows=$(tput lines)
+n_cols=$(tput cols)
+
+printf 'rows: %d\ncols: %d\n' "$n_rows" "$n_cols"
+
+#for cell in $(seq 0 $(((n_rows * n_cols) - 1)))
+for ((cell=0;cell<n_rows*n_cols;++cell))
+do cells[cell]=0
+done
+
+###
+# It is best if the bottom row is row #0.
+# Even if the terminal is resized,
+# there will always be a row #0.
+# Of course this means the rows will be drawn in reverse order.
+new_base_row(){
+ # TODO: If the terminal is resized, re-evaluate the number of columns.
+# for cell in $(seq 0 $((n_cols-1)))
+ declare -i delta=32 # ±16
+ for ((cell=0;cell<n_cols;++cell))
+ do cells[cell]=$(((cells[cell]+RANDOM%delta-(delta/2)+256)%256))
+ done
+ # TODO: Adjust delta to size of terminal? Not sure how.
+}
+
+# end init
+##
+
+num_to_cell(){
+ # Cells have a value between 0 and 255, inclusive.
+ # Arrays are 0-indexed.
+ echo -n "${flame_gradient[(255-$1)*${#flame_gradient[@]}/256]}"
+ # printf makes no apparent difference.
+}
+
+##
+# Compute the values of the indicated row
+# from the values of the row below.
+# Indicated row should not be the bottom row.
+# TODO: Does a lot of repeatedly computing the same numbers; could be avoided.
+burn_row(){
+ declare -i row_number=$1
+ declare -i cell
+ for ((cell=row_number*n_cols;cell<(row_number+1)*n_cols;++cell))
+ do
+ cell_l=${cells[$cell-$n_cols-1]}
+ cell_b=${cells[$cell-$n_cols]}
+ cell_r=${cells[$cell-$n_cols+1]}
+ # The flames cool between rows.
+ cells[cell]=$(((cell_l+cell_b+cell_r)/3-(256/n_rows)))
+ [[ ${cells[cell]} -lt 0 ]] && cells[cell]=0
+ done
+}
+# By burning iteratively, the entire array can be processed at once.
+# It is only a matter of direction.
+
+burn(){
+ declare -i cell cell_l cell_b cell_r
+ for ((cell=${#cells[@]}-1;cell>=n_cols;--cell))
+ do
+ cell_l=${cells[$cell-$n_cols-1]}
+ cell_b=${cells[$cell-$n_cols]} # cell_l from previous iteration.
+ cell_r=${cells[$cell-$n_cols+1]} # cell_b from previous iteration.
+ # The flames cool between rows.
+ cells[cell]=$(((cell_l+cell_b+cell_r)/3-(256/n_rows)))
+ [[ ${cells[cell]} -lt 0 ]] && cells[cell]=0
+ done
+}
+
+print_all(){
+# Wrong order. This burns downwards.
+ declare -i cell
+ for cell in "${cells[@]}"
+ do
+ num_to_cell $cell
+ done
+}
+
+print_rows(){
+ declare -i row
+ for ((row=n_rows-1;row>=0;--row))
+ do
+ # Print rows top to bottom:
+ tput cup $((n_rows-row)) 0
+ print_row $row
+ # Print rows bottom to top:
+ # tput cup $row 0
+ # print_row $((n_rows-1-row))
+ done
+ # TODO:
+ # It should be more efficient to print all at once.
+}
+
+print_row(){
+ declare -i row=$1
+ declare -i cell
+ for ((cell=row*n_cols;cell<(row+1)*n_cols;++cell))
+ do
+ num_to_cell "${cells[cell]}"
+ done
+}
+
+test_fire() {
+ # Saturate base row.
+ for ((cell=0;cell<n_cols;++cell))
+ do cells[cell]=255
+ done
+ # Print buffer.
+ tput cup 0 0
+ print_rows
+ # Burn.
+ for ((counter=0;counter<n_rows;++counter))
+ do
+ burn
+ print_rows
+ done
+}
+
+##
+# main
+
+#test_fire
+#exit
+
+new_base_row
+while :
+do
+ burn
+ print_rows
+ new_base_row
+ tput cup 0 0
+# sleep 0.2
+# sleep 1
+done
diff --git a/man/man1/fire.1 b/man/man1/fire.1
new file mode 100644
index 0000000..c3f214f
--- /dev/null
+++ b/man/man1/fire.1
@@ -0,0 +1,59 @@
+.TH fire 1 2026-04-17 utils
+
+.SH NAME
+fire \- exothermic oxygenation
+
+.SH SYNOPSIS
+.SY fire
+.YS
+
+.SH DESCRIPTION
+.B fire
+is a shell script that prints a burning fire into the terminal.
+.P
+If you are cold, you can make a
+.B fire
+to use your computer as an electric heater.
+(Disclaimer:
+While
+.B fire
+may increase the CPU temperature from frequent calculation and printing,
+it is not guaranteed to do so. Its main purpose is to look pretty.)
+.P
+On a printer or a mechanical teletype terminal, it will only waste your paper and ink.
+
+.SH OPTIONS
+.B fire
+has no options at this time.
+
+.SH EXIT STATUS
+No exit status is defined.
+
+.SH NOTES
+.B fire
+does not use an artificial delay, but prints as fast as it can,
+This may be too slow or too fast to have the desired effect,
+but slowing it down is trivial by commenting out and adjusting the
+.BR sleep (1)
+command in the script, near the botton.
+Making it faster is not as trivial; the bottleneck is almost certainly the terminal.
+
+.SH BUGS
+.B fire
+requires that the terminal supports certain capabilities, such as
+ANSI escape codes for colour.
+It does not check for those capabilities, but it does make use of
+.BR tput (1).
+.P
+.B fire
+currently only uses ASCII characters and the standard 16 colour palette.
+.BR termcap (5)
+permitting, it should support 256 colours
+(there are currently no terminals supporting 16 bit or 24 bit palettes),
+and maybe use glyphs that are better suited for rendering a convincing fire.
+
+.SH EXAMPLES
+.B fire
+
+.SH SEE ALSO
+.BR rain (1)