summaryrefslogtreecommitdiff
path: root/bin
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 /bin
parent912b6505f1335a1f9eabf55045b67e38738bdaf3 (diff)
Diffstat (limited to 'bin')
-rwxr-xr-xbin/fire173
1 files changed, 173 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