-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathzombie-maze-walker.sh
executable file
·149 lines (126 loc) · 2.84 KB
/
zombie-maze-walker.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#!/usr/bin/env bash
MAZEFILE=`dirname $0`/maze.txt
REPLAY=false
INVERTWALLS=
while getopts "f:ri" opt; do
case "$opt" in
r) REPLAY=true
LOG=$(tempfile) || exit;;
f) MAZEFILE="$OPTARG";;
i) INVERTWALLS='s/[^><^vuldr ]/[7m&[m/g';;
[?]) cat <<- EOF
Usage: $0 [OPTION] [-f mazefile]"
-f filename
use the custom maze file. Default: maze.txt
-r replay mode. Print the replay command at the end.
-i invert wall colors.
EOF
exit 1;;
esac
done
if [ ! -f "$MAZEFILE" ]; then
echo Maze file "$MAZEFILE" was not found.
exit 1
fi
IFS=''
while read line; do
new=$(wc -c <<< "$line")
if [[ -n "$prev" ]] && [[ ! "$new" = "$prev" ]]; then
echo "Lines of the maze must have equal length. Please fix."
exit 1
fi
prev=$new
done < "$MAZEFILE"
MAZE=$(sed 's#[/\\]#\\&#g;s#^#s/$/#;s#$#~/#;$s#~/$#/#' "$MAZEFILE")
if [[ ! $MAZE =~ ^([^><v^]*[><v^][^><v^]*)$ ]]; then
echo "The maze must have exactly one player represented by ^,>,<, or v"
exit 1
fi
GAMEFILE=$(tempfile) || exit
trap '{ $REPLAY && echo To rerun "\"sed -nf $GAMEFILE < $LOG\"" || rm -f $GAMEFILE; }' EXIT
WIDTH=$(read line < $MAZEFILE; echo -n "$line" | wc -c)
cat << EOF > $GAMEFILE
#!/bin/sed -nf
1{
s/.*//
$MAZE
h; b display
}
/^\(\[A\)\|w/{x; s/[><v]/^/; x; b next;}
/^\(\[B\)\|s/{x; s/[><^]/v/; x; b next;}
/^\(\[D\)\|a/{x; s/[>^v]/</; x; b next;}
/^\(\[C\)\|d/{x; s/[<v^]/>/; x; b next;}
:next
x
# Losing condition #1 - you walk into a zombie
/\([udlr]\(.\{$WIDTH\}\)\^\)\|\(v\(.\{$WIDTH\}\)[udlr]\)\|\(>[udlr]\|[udlr]<\)/{
s/$/&~ZOMBIE SAYS YUM!!!/
x
b display
}
# character movements
s/ \(.\{$WIDTH\}\)\^/^\1 /
s/v\(.\{$WIDTH\}\) / \1v/
s/> / >/
s/ </< /
# Losing condition #2 - a zombie walks into you
/\([><v^].\{$WIDTH\}u\)\|\(d.\{$WIDTH\}[><v^]\)\|\(r[><v^]\)\|\([><v^]l\)/{
s/$/&~YUM BRAINZZZ!!!/
x
b display
}
# nemesis movements
:nem
/[udlr]/{
# turning around
s/\(\([^ ].\{$WIDTH\}\)\|\(^.\{,$WIDTH\}\)\)u/\1D/
s/d\(\(.\{$WIDTH\}[^ ]\|\(.\{,$WIDTH\}\)$\)\)/U\1/
s/r\([^ ]\|~\|$\)/L\1/
s/\([^ ]\|~\|^\)l/\1R/
# moving
s/ \(.\{$WIDTH\}\)u/U\1 /
s/d\(.\{$WIDTH\}\) / \1D/
s/r / R/
s/ l/L /
b nem
}
y/UDLR/udlr/
# winning condition
/\(^[^~]*\^\)\|\(v[^~]*$\)\|\(>~\)\|\(~<\)\|\(^<\)\|\(>$\)/s/$/~YOU WON!!! HAVE A COOKIE/
x
:display
g
s/~/\\
/g
$INVERTWALLS
s/[><^v]/[1;36m&[m/g
s/[udlr]/[1;32mZ[m/g
i\\
[2J[H
p
/!/q
EOF
#-------------
# Play phase
mytime="`date +%s`"
export LC_ALL="C"
(while true; do
read -s -t 1 -n 1 TMP
RES=$?
CMD="$TMP"
if [ "$CMD" == '' ]; then
read -s -n 1 TMP; CMD="$CMD$TMP"
if [ "$CMD" == '[' ]; then
read -s -n 1 TMP; CMD="$CMD$TMP"
fi
fi
if [ $RES -eq 0 ]; then
echo "$CMD"
continue
fi
mytimenew="`date +%s`"
if [ "$mytimenew" != "$mytime" ]; then
echo
mytime=$mytimenew
fi
done) | ( $REPLAY && tee "$LOG" || cat ) | sed -nf $GAMEFILE