A POSIX sh clone of the Nokia 6110 Snake game.
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
█ █
█ ╔═════╗ ╔═════╗ ╔═════╗ █
█ ║ ╔═╗ ║ ║ ╔═══╝ ║ ╔═╗ ║ █
█ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ █
█ ║ ╚═╝ ║ ║ ╚═══╗ ║ ║ ║ ║ █
█ ║ ╔═══╝ ╚═══╗ ║ ║ ║ ║ ║ █
█ ║ ║ ╔═══╝ ║ ║ ║ ║ ║ █
█ ╚═╝ o %═════╝ ╚═╝ ╚═╝ █
█ ╔═════╗ ╔═╗ ╔═╗ ╔═════╗ █
█ ║ ╔═╗ ║ ║ ║ ║ ║ ║ ╔═══╝ █
█ ║ ║ ║ ║ ║ ║╔╝╔╝ ║ ║ █
█ ║ ╚═╝ ║ ║ ╚╝╔╝ ║ ╚══╗ █
█ ║ ╔═╗ ║ ║ ╔╗╚╗ ║ ╔══╝ █
█ ║ ║ ║ ║ ║ ║╚╗╚╗ ║ ╚═══╗ █
█ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ █
█ █
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
psnake.sh [options...]
Options:
-H height set board height (default: 16)
-W width set board width (default: 28)
-a use ASCII characters (default: Unicode)
-d disable vertical speed correction
-m maximize board to terminal size
-q quiet mode (disable bells)
-s speed set game speed (tick rate, default: 6)
-h show help
-V show version
Controls:
arrow keys, change direction
WASD
q, C-c quit game
psnake is designed for POSIX-compatible shells and ANSI/VT-compatible
terminals.
The game relies on widely supported terminal escape sequences for cursor movement and screen updates. These sequences are not specified by POSIX, but are implemented by virtually all modern terminals.
When using ASCII-only characters to draw the snake, it is difficult to see where the tail is moving next. This becomes important when closely following the tail of a long snake.
Unicode box-drawing characters are used to clearly show turns and movement direction.
Terminal character cells are usually not square, which makes vertical movement appear faster than horizontal movement. This is corrected by slightly slowing down vertical movement to preserve visual consistency.
Sane option parsing powered by petopts.
The snake is stored as a space-separated list of cell indices. Using linear cell numbers instead of (x, y) coordinates simplifies collision detection while keeping the stored state compact.
Cursor positioning is derived from cell numbers. All cursor movement is performed relative to a saved position at the top-left corner of the playing area.
User input is read in a separate process using dd. Direction changes
are signaled to the main process via SIGUSR1 and SIGUSR2. From only
these two signals, the new direction is calculated relative to the
current direction. This has the side effect that pressing the same
direction the snake is already moving in still results in a direction
change. However, the original Nokia Snake game also allowed control
using only two buttons.
Subprocesses are avoided wherever possible. For example, parameter
expansion is used instead of external tools such as sed.
External commands used:
awk: floating-point arithmetic and random number generation when /dev/urandom is not availabledd: user inputod: reading random integers from/dev/urandomsleep: fixed game tick ratestty: terminal configuration and size detection