Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
executable file 482 lines (430 sloc) 9.96 KB
#!/bin/sed -nf
# arkanoid.sed - http://aurelio.net/bin/sed/arkanoid/
# by Aurelio Marinho Jargas <verde (a) aurelio net>
#
# Arkanoid: a paddle that bounces a ball (pong!) to destroy blocks
#
# ACTORS:
# o ball -- paddle
# = block ~~ paddle (on hold mode)
# * block exploding . life (mini paddle)
# [come on, use your imagination :)]
# COMMANDS:
# z left move c hold mode ON/OFF
# x right move q quit
#
# HOW TO PLAY:
# You must press the ENTER key after *every* command. Start the
# program with "sed -f arkanoid.sed". Press ENTER. Choose the
# level. Press ENTER. Move the paddle with the keyboard arrows
# or with the Z and X keys. Press ENTER. Release the ball using
# the down arrow ou the C key. Press ENTER. Press ENTER. Press
# ENTER. Press ENTER...
#
# ANTI-FLAME DISCLAIMER:
# Well, just as sokoban.sed, this one is cool because it's sed.
# It's not funny to play or even exciting, because keep pressing
# ENTER to the ball move sucks. But hey, it's cute! &;)
#
# For the how-many-lines-it-has? fanatics:
# prompt$ sed '/^ *#/d' arkanoid.sed | sed '$=;d'
#
# Tip: Use hold mode and hit the paddle twice on the wall
# to escape cyclic ball movement
#
# TODO Get classic Arkanoid levels (somebody help me!)
#
# CHANGELOG:
# 2002-07-09 v1.0: Debut release
# 2005-05-13 v1.1: Now it's a sedcheck compliant script.
# It will run on most SED's, including oldies.
# 2013-02-12 v1.2: Removed ISO-8859-1 char, now we're plain ASCII.
b zero
:nocolor
### if you don't want colorful output, just uncomment next line
#s/K(\([0-9;]*\))//g
b showmap
:parsecmd
### arrow keys (1), numeric pad (2), i-case (3), wipe trash(4)
//{
s/\[A/h/g
s/\[B/h/g
s/\[C/x/g
s/\[D/z/g
}
y/4560/zhxq/
y/QZXHCc/qzxhhh/
s/[^qzxh#]//g
b execcmd
:welcome
i\
Welcome to the SED Arkanoid\
\
Please select a level to begin [1-2]:
d
:showhelp
### clear screen, show help
i\

x
s|.*|\
... Sed Arkanoid\
... \
... z,4,<left> left move\
... x,6,<right> right move\
... c,5,<down> hold on/off\
... q,0 quit game\
... <enter> go!\
\
|p
s/.*//
x
b end
:loadmap
### load map on HOLD space
/^1$/{ s/.*/\
_____________ \
| |\
| |\
|=============|\
|=============|\
|=============|\
| |\
| |\
| |\
| |\
| o |\
| ~~ |\
|...__________|\
/
b endmap
}
/^2$/{ s/.*/\
_____________ \
|= |\
|=== |\
|===== |\
|======= |\
|========= |\
|=========== |\
|=============|\
| |\
| |\
| o |\
| ~~ |\
|...__________|\
/
b endmap
}
### test levels
#
# free X test
/^t1$/{ s/.*/\
TEST 1 - f:X\
_____________ \
| = = = |\
| o |\
| = = = |\
| |\
|.____________|\
/
b endmap
}
# free Y test
/^t2$/{ s/.*/\
TEST 2 - f:Y\
_____________ \
| |\
| == = |\
| = == |\
| == |\
| =o= |\
| == |\
| |\
|____.________|\
/
b endmap
}
# tri-explosion test
/^t3$/{ s/.*/\
TEST 3 - 3\
_____________ \
| == |\
| == |\
| == = |\
| = == |\
| =o |\
| == |\
| |\
|.____________|\
/
b endmap
}
# round explosion test
/^t4$/{ s/.*/\
TEST 4 - >, <, b:>, b:<\
_____________ \
| = = |\
| == o == |\
| = = = = |\
| == == |\
| |\
|___________._|\
/
b endmap
}
/~~/!{
s/.*/there is no '&' level!/p
q
}
:endmap
s/^//
s/ $/ru /
h
b showhelp
#--------------------------------------------------------------------
#
### general hints about the code:
#
# - rlud are movements to perform on this turn
# - RLUD are movements already done
# - O is a ball already moved on this turn
# - @% are temporary ball states to indicate ball over a block
# - ! is a temporary explosion state after a free Y move
# - -- is plain paddle and ~~ is paddle on hold mode
# - ... are your 3 lives (mini-paddles)
# - # is the cheat mode identifier (jail!)
# - on hold, when releasing the ball, its X-direction will be same of
# the paddle side where the ball is
# - on hold, forcing paddle on the wall can move ball to the other side
# of the paddle
# - on hold mode, Y-direction is always down
# - explosions are showed, then reconverted to ball on the next move
# - ball on vertical and top borders do bounce
# - block explosion and paddle (of course) bounces
# - bounce: change X or Y direction
# - exploding a block may change Y-direction and/or X-direction, depending
# if there's another block on the way (see explosion comments)
# - diagonal moves are done as X then Y moves (that's why % is needed)
# - K() pattern is replaced by color escape chars <esc>[m
# - < and > are round explosion direction. stored at the end (.$) of the map
# - ball direction (rlud) is stored at the end (.. $) of the map also
# - user commands are case insensitive
# ballmiss routine: 1. reset direction and explosion status
# 2. put ball over paddle , 3. take one life, 4. put paddle on hold mode
#
:ballmiss
s/...$/ru /
s/\*/ /
s/ \(.\{20\}\)\([-~]\)/o\1\2/
s/\._/__/
s/--/~~/
b end
:zero
1 b welcome
# first map loading
2 b loadmap
b parsecmd
:execcmd
### execute user commands
### first, have you missed a ball?
x
/\*\(.\{20\}\)[_.]/{
/#/!b ballmiss
# cheat mode: never loses
y/d*/uo/
b execcmd
}
x
/q/q
# you cheater! (keep holding enter - hyper-speed)
/#/{
x
/#/!s/\(.*\)|/\1#/
}
# 1. move ball+paddle on hold, and goto end
# 2. move just paddle and continue
/z/{ x
/o.\{20\}~/{
s/ o/o /
s/ ~~/~~ /
b end
}
s/ --/-- /
s/ ~~/~~ /
}
/x/{ x
/o.\{20\}~/{
s/o / o/
s/~~ / ~~/
b end
}
s/-- / --/
s/~~ / ~~/
}
/h/{ x
### turn OFF hold mode routine
/~~/{
# depending which side of paddle, change X-direction
/o.\{20\}~~/y/Rr/LL/
/o.\{20\}~[^~]/y/Ll/RR/
# change Y-direction
/o.\{20\}~/y/Dd/UU/
}
# swap ON/OFF paddle shape
y/-~/~-/
}
/./!x
# current explosion turns back to ball
/o/s/\*/ /g
s/\*/o/
# reset movements
y/RLUD/rlud/
# hold ball, no move
/o.\{20\}~/b end
### LET'S MOVE IT!
# reached top: do bounce changing Y-direction
/_\(.\{20\}\)o/y/u/d/
### detect borders, change X-direction
/|o/y/l/r/
/o|/y/r/l/
# plain right-left ball move
/r/s/o / O/
/l/s/ o/O /
# tricky move over a block - part I
/r/{
s/o=/ @/
s/% /=o/
}
/l/{
s/=o/@ /
s/ %/o=/
}
# restore ball and mark X moves as done
y/O@rl/o%RL/
b boom
### detect block. if so, explode it!
#
# 0 1 RIGHT-UP example:
# +---+---+
# | = | * | 0. free X-way
# |o | o| 1. explode and change Y-direction (right-down)
# +-------+
# |== |** | 0. blocked X and Y way (tri-explosion)
# |o= |o* | 1. explode all and change X and Y direction (left-down)
# +-------+
# | |o |
# | = | * | 0. free Y-way
# |o= | = | 1. explode and change X-direction (left-up)
# +---+---+
#
### RIGHT-UP Smart clockwise full round explosion!
#
# +---+---+---+---+---+
# | = | * | | | | If two explosions on two turns,
# |o =| =| *| |o | we're on a round explosion.
# | = | = | = | * | | After the roll, we end as left-up.
# +---+---+---+---+---+
#
### explosion functions (wise is clockwise [>] or anti-clockwise [<])
# chkwise: if wise direction is empty, set it! - else dowise
# setwise: set wise direction, based on current ball direction
# dowise: set the next ball direction, based on wise direction
#
:chkwise
/ $/ b setwise
b dowise
# */! : ball came from X/Y free
:setwise
/\*/{
/Ld $/s/ $/>/
/Ru $/s/ $/>/
/Rd $/s/ $/</
/Lu $/s/ $/</
y/ud/du/
}
/!/{
/Ld $/s/ $/</
/Ru $/s/ $/</
/Rd $/s/ $/>/
/Lu $/s/ $/>/
y/RL/LR/
}
y/ud/UD/
b end
:dowise
/Rd<$/ y/d/U/
/Lu<$/ y/u/D/
/Ru<$/ y/R/L/
/Ld<$/ y/L/R/
/Ld>$/ y/d/U/
/Ru>$/ y/u/D/
/Rd>$/ y/R/L/
/Lu>$/ y/L/R/
b end
# UP & DOWN explosion code:
# 1. free X
# 2. blocked XY from left (tri-explosion)
# 3. blocked XY from right (tri-explosion)
# 4. free Y
#
:boom
/d/{
/o\(.\{20\}\)=/ s// \1*/
/% \(.\{19\}\)==\(.*L\)/s//*o\1**\2/
/ %\(.\{19\}\)==\(.*R\)/s//o*\1**\2/
/%\(.\{20\}\)=/ s//=\1!/
}
/u/{
/=\(.\{20\}\)o/ s//*\1 /
/==\(.\{19\}\)% \(.*L\)/s//**\1*o\2/
/==\(.\{19\}\) %\(.*R\)/s//**\1o*\2/
/=\(.\{20\}\)%/ s//!\1=/
}
# end tri-explosion: invert all directions (keep before "end free X" code)
/\*\*/{ y/udRL/DULR/
b end
}
# end free Y explosion
/! .*L/ b chkwise
/ !.*R/ b chkwise
# end free X explosion
/\*/ b chkwise
# detect paddle bounce, change Y-direction
/o\(.\{20\}\)-/y/d/u/
# plain up-down ball move (no explosion)
/u/s/ \(.\{20\}\)o/o\1 /
/d/s/o\(.\{20\}\) / \1o/
# tricky move over a block - part II
/u/s/ \(.\{20\}\)%/o\1=/
/d/s/%\(.\{20\}\) /=\1o/
# you missed the ball!
/o\(.\{20\}\)[_.]/y/o/*/
:end
# show move over a block explosion right
y/!/*/
# reset last explosion reminder for plain moves
/\*/!s/[<>]$/ /
### detect level finished or GAME OVER
/=/!s/\(\([^\n]*\n\)\{5\}[^|]*|\).........../\1K(33;1) VICTORY!!K()/
/\./!s/\(\([^\n]*\n\)\{5\}[^|]*|\).........../\1K(31;1) GAME OVERK()/
### save map
h
### hide direction (comment for debug)
s/...$//
### add colors
s/--/K(32;1)&K()/g
s/~~/K(32;1)&K()/g
s/o/K(33;1)&K()/g
s/ \{0,1\}_\{1,\} \{0,1\}/K(42;32)&K()/g
s/|/K(42;32)&K()/g
s/\./K(42;32;1)&K()/g
s/#/K(42;37;1)&K()/g
s/\*/K(31;1)&K()/g
b nocolor
:showmap
s/K(\([0-9;]*\))/[\1m/g
p
/VICT/q
/OVER/q
d