diff options
| -rwxr-xr-x | bin/fire | 173 | ||||
| -rw-r--r-- | man/man1/fire.1 | 59 |
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) |
