diff options
Diffstat (limited to 'Functions/Misc')
-rw-r--r-- | Functions/Misc/.distfiles | 1 | ||||
-rw-r--r-- | Functions/Misc/tetris | 243 |
2 files changed, 244 insertions, 0 deletions
diff --git a/Functions/Misc/.distfiles b/Functions/Misc/.distfiles index 5040576b5..9de53001a 100644 --- a/Functions/Misc/.distfiles +++ b/Functions/Misc/.distfiles @@ -4,4 +4,5 @@ allopt harden nslookup zkbd zstyle+ checkmail is-at-least run-help zmv colors mere zed zrecompile getjobs promptnl +tetris ' diff --git a/Functions/Misc/tetris b/Functions/Misc/tetris new file mode 100644 index 000000000..a9d367964 --- /dev/null +++ b/Functions/Misc/tetris @@ -0,0 +1,243 @@ +# Someone once accused zsh of not being as complete as Emacs, because it +# lacks Tetris and an adventure game. +# +# autoload -U tetris +# zle -N tetris +# bindkey '...' tetris + +emulate -L zsh + +tetris_hsz=11 +tetris_vsz=20 +typeset -ga tetris_shapes +tetris_shapes=( + 0x0f00 0x4444 0x0f00 0x4444 + 0x4e00 0x4c40 0x0e40 0x4640 + 0x6600 0x6600 0x6600 0x6600 + 0x4620 0x6c00 0x4620 0x6c00 + 0x2640 0x6300 0x2640 0x6300 + 0x6440 0x8e00 0x44c0 0x0e20 + 0xc440 0x0e80 0x4460 0x2e00 +) +typeset -gA tetris_rotations +tetris_rotations=( + 0x0f00 0x4444 0x4444 0x0f00 + 0x4e00 0x4c40 0x4c40 0x0e40 0x0e40 0x4640 0x4640 0x4e00 + 0x6600 0x6600 + 0x4620 0x6c00 0x6c00 0x4620 + 0x2640 0x6300 0x6300 0x2640 + 0x6440 0x8e00 0x8e00 0x44c0 0x44c0 0x0e20 0x0e20 0x6440 + 0xc440 0x0e80 0x0e80 0x4460 0x4460 0x2e00 0x2e00 0xc440 +) + +tetris_blankline= +for ((tetris_i=tetris_hsz; tetris_i--; )); do + tetris_blankline="$tetris_blankline " +done +tetris_blankboard= +for ((tetris_i=tetris_vsz; tetris_i--; )); do + tetris_blankboard="$tetris_blankboard$tetris_blankline" +done + +bindkey -N tetris +bindkey -R -M tetris '\000-\377' tetris-timeout +for ((tetris_i=256; tetris_i--; )); do + bindkey -M tetris 'T\'$(([##8]tetris_i)) tetris-timeout +done +bindkey -M tetris Ta tetris-left +bindkey -M tetris Tj tetris-left +bindkey -M tetris Ts tetris-rotate +bindkey -M tetris Tk tetris-rotate +bindkey -M tetris Td tetris-right +bindkey -M tetris Tl tetris-right +bindkey -M tetris 'T ' tetris-drop +bindkey -M tetris Tq tetris-quit + +unset tetris_board tetris_score + +zle -N tetris +function tetris { + emulate -L zsh + if ! zle; then + print -u2 "Use M-x tetris RET to play tetris." + return 2 + fi + tetris_saved_state="BUFFER=${BUFFER:q};CURSOR=${CURSOR:q};MARK=${MARK:q};zle -K ${KEYMAP:q}" + tetris_speed=$((100.0/KEYTIMEOUT)) + zle -K tetris + if [[ ${tetris_board+set} == set ]]; then + tetris-timeout + else + tetris_board=$tetris_blankboard + tetris_score=0 + tetris-new-block + fi +} + +function tetris-new-block { + emulate -L zsh + tetris_block=$tetris_shapes[1+RANDOM%$#tetris_shapes] + tetris_block_y=0 + tetris_block_x=4 + if ! tetris-block-fits; then + tetris-place-block "#" + tetris-render-screen + unset tetris_board tetris_score + tetris-quit + return + fi + tetris-place-block "*" + tetris-timed-move +} + +zle -N tetris-left +function tetris-left { + emulate -L zsh + tetris-place-block " " + (( tetris_block_x-- )) + tetris-block-fits || (( tetris_block_x++ )) + tetris-place-block "*" + tetris-timeout +} + +zle -N tetris-right +function tetris-right { + emulate -L zsh + tetris-place-block " " + (( tetris_block_x++ )) + tetris-block-fits || (( tetris_block_x-- )) + tetris-place-block "*" + tetris-timeout +} + +zle -N tetris-rotate +function tetris-rotate { + emulate -L zsh + tetris-place-block " " + local save_block=$tetris_block + tetris_block=$tetris_rotations[$tetris_block] + tetris-block-fits || tetris_block=$save_block + tetris-place-block "*" + tetris-timeout +} + +zle -N tetris-drop +function tetris-drop { + emulate -L zsh + tetris-place-block " " + ((tetris_block_y++)) + while tetris-block-fits; do + ((tetris_block_y++)) + done + ((tetris_block_y--)) + tetris-block-dropped +} + +zle -N tetris-timeout +function tetris-timeout { + emulate -L zsh + tetris-place-block " " + ((tetris_block_y++)) + if tetris-block-fits; then + tetris-place-block "*" + tetris-timed-move + return + fi + ((tetris_block_y--)) + tetris-block-dropped +} + +function tetris-block-dropped { + emulate -L zsh + tetris-place-block "O" + local fl=${tetris_blankline// /O} i=$((tetris_block_y*tetris_hsz)) y + for ((y=0; y!=4; y++)); do + if [[ $tetris_board[i+1,i+tetris_hsz] == $fl ]]; then + tetris_board[i+1,i+tetris_hsz]= + tetris_board=$tetris_blankline$tetris_board + ((tetris_score++)) + fi + ((i += tetris_hsz)) + done + tetris-new-block +} + +function tetris-block-fits { + emulate -L zsh + local y x i=$((1+tetris_block_y*tetris_hsz+tetris_block_x)) b=0x8000 + for ((y=0; y!=4; y++)); do + for ((x=0; x!=4; x++)); do + if ((tetris_block&b)); then + ((x+tetris_block_x >= 0)) || return 1 + ((x+tetris_block_x < tetris_hsz)) || return 1 + ((y+tetris_block_y >= 0)) || return 1 + ((y+tetris_block_y < tetris_vsz)) || return 1 + [[ $tetris_board[i] == " " ]] || return 1 + fi + ((b >>= 1)) + ((i++)) + done + ((i+=tetris_hsz-4)) + done + return 0 +} + +function tetris-place-block { + emulate -L zsh + local y x i=$((1+tetris_block_y*tetris_hsz+tetris_block_x)) b=0x8000 + for ((y=0; y!=4; y++)); do + for ((x=0; x!=4; x++)); do + ((tetris_block&b)) && tetris_board[i]=$1 + ((b >>= 1)) + ((i++)) + done + ((i+=tetris_hsz-4)) + done +} + +function tetris-timed-move { + emulate -L zsh + tetris-render-screen + LBUFFER= + RBUFFER=$'\n'$tetris_screen + zle -R + zle -U T +} + +function tetris-render-screen { + emulate -L zsh + setopt extendedglob + local s i extras + extras=( + "Score: $tetris_score" + "" + "Game parameters: ${tetris_hsz}x$tetris_vsz, ${tetris_speed}Hz" + "" + "Keys: left: a j" + " rotate: s k" + " right: d l" + " drop: space" + " quit: q" + ) + for ((i=0; i!=tetris_vsz; i++)); do + s="$s|${${${${${tetris_board[1+i*tetris_hsz,(i+1)*tetris_hsz]}//O/()}//\*/**}// / }//\#/##}|"${extras[1]+ $extras[1]}$'\n' + extras[1]=() + done + s="$s+${tetris_blankline// /--}+" + tetris_screen=$s +} + +zle -N tetris-quit +function tetris-quit { + emulate -L zsh + if [[ ! -o always_last_prompt ]]; then + BUFFER= + zle -M $tetris_screen + fi + eval $tetris_saved_state + if [[ -o always_last_prompt ]]; then + zle -M $tetris_screen + fi +} + +tetris "$@" |