aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRobin Haberkorn <rhaberkorn@fmsbw.de>2026-04-03 00:32:20 +0200
committerRobin Haberkorn <rhaberkorn@fmsbw.de>2026-04-03 00:32:20 +0200
commitb286ad5334eaad82f85c759ee00a36678db7cb17 (patch)
tree3ef47aca83a365b5266efe7543f42e4cd4b93ff8
parentd456b21d604c7a252d630b132dfa5b4f6b67d4fc (diff)
* This is a gimmick pseudo-game for driving a tank around your buffer. * The tank is "animated" and crushes non-space characters it drives over. * When shooting, it deletes characters that get hit. * When escaping, the tank explodes and leaves a "crater" behind.
-rw-r--r--freebsd/pkg-plist1
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/tank.tes211
3 files changed, 213 insertions, 1 deletions
diff --git a/freebsd/pkg-plist b/freebsd/pkg-plist
index ab74145..dd3e7cb 100644
--- a/freebsd/pkg-plist
+++ b/freebsd/pkg-plist
@@ -13,6 +13,7 @@ share/man/man7/%%PROGRAM_PREFIX%%sciteco.7.gz
%%DATADIR%%/lib/getopt.tes
%%DATADIR%%/lib/lexer.tes
%%DATADIR%%/lib/repl.tes
+%%DATADIR%%/lib/tank.tes
%%DATADIR%%/lib/tecat.tes
%%LEXILLA%%%%DATADIR%%/lib/lexers/abaqus.tes
%%LEXILLA%%%%DATADIR%%/lib/lexers/ada.tes
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 0da616a..04e83ad 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -1,5 +1,5 @@
dist_scitecolib_DATA = color.tes lexer.tes session.tes opener.tes \
- fnkeys.tes string.tes getopt.tes
+ fnkeys.tes string.tes getopt.tes tank.tes
# Standalone scripts.
# These are not installed via _SCRIPTS as it would add the --program-prefix.
diff --git a/lib/tank.tes b/lib/tank.tes
new file mode 100644
index 0000000..8573e22
--- /dev/null
+++ b/lib/tank.tes
@@ -0,0 +1,211 @@
+!*
+ * TANK MODE
+ *
+ * Drive an ASCII tank around your buffer.
+ * Invoke via EIQ[$SCITECOPATH]/tank.tes
+ *!
+[tank.sprite.0] !* background *!
+
+!* FIXME: Perhaps encode the gun's top in the integer cell *!
+[tank.sprite.1]
+█▓█▓
+╠════○
+▓█▓█
+[tank.sprite.2]
+ █▓█▓
+○════╣
+ ▓█▓█
+[tank.sprite.3]
+ ┌┐
+▓││█
+█││▓
+▓┴┴█
+[tank.sprite.4]
+█┬┬▓
+▓││█
+█││▓
+ └┘
+
+!*
+ * f,tM[tank.rand] - LCG pseudo random number generator for values between f and t
+ * This is based on the version in the BSD libc.
+ *!
+::U[tank.rand]
+@[tank.rand]{
+ U.tU.f
+ (1103515245*Q[tank.rand]+12345) & (2^*31-1)U[tank.rand]
+ (Q[tank.rand]^/(Q.t-Q.f+1)+Q.f)
+}
+
+!* x,yM[tank.goto] -> success|failure *!
+@[tank.goto]{
+ U.yU.x
+ Q.x"< 0 ' Q.y"< 0 '
+ J Q.y:L"F 0 '
+ Q.x<0A"< I  F> ' 0A-10"= I  F> ' C>
+ -1
+}
+
+!* x,y,spriteM[tank.blit] *!
+@[tank.blit]{
+ U.sU.yU.x Q.xU.#x0
+ Q.s"N
+ 10[tank.sprite.0] !* background *!
+ %[tank.blit]
+ '
+ <
+ %.iQ[tank.sprite.\.s]U.c Q.c:;
+ Q[tank.blit]&1"=
+ !* toggle the chain character to simulate movements *!
+ Q.c-█"= ▓U.c | Q.c-▓"= █U.c ' '
+ '
+
+ Q.c-10"=
+ %.y Q.#x0U.x
+ Q.s"N 10:[tank.sprite.0] '
+ |
+ Q.x,Q.yM[tank.goto];
+ Q.s"N !* not background sprite *!
+ Q.c- "=
+ !* space is "transparent" - copy background unmodified *!
+ 0A"< I  | 0A-10"= I  | C ' '
+ -A:[tank.sprite.0]
+ %.x F<
+ '
+ !* "destroy" fields we have touched *!
+  U.d
+ 0A"F 0A-10"N 0A- "N 33,126M[tank.rand]U.d ' ' '
+ Q.d:[tank.sprite.0]
+ '
+ 0A"F 0A-10"N D ' ' Q.cI
+ %.x
+ '
+ >
+}
+
+@[tank.explode]{
+ !!.[explosion]*oO%. 
+ .[explosion]✹✸✶✧· 
+ :Q.[explosion]<
+ 0A"F 0A-10"N D ' '
+ %.i-1Q.[explosion]IR
+ >
+}
+
+0U[tank.score]
+
+@[tank.shoot]{
+ U.#dr U.yU.x
+
+ !* FIXME: Could also be encoded into a map *!
+ Q.#dr-1Oright,left,up,down
+ !right!
+ 6-1%.x %.y
+ 1U.#dx 0U.#dy
+ Oend
+ !left!
+ %.y
+ -U.#dx 0U.#dy
+ Oend
+ !up!
+ 2-1%.x
+ 0U.#dx -U.#dy
+ Oend
+ !down!
+ 2-1%.x 3%.y
+ 0U.#dx 1U.#dy
+ !* fall through *!
+ !end!
+ <
+ (Q.#dx%.x),(Q.#dy%.y)M[tank.goto]"F  '
+ 0A"<  ' Q.#dy"= 0A-10"=  ' '
+ 0A- "N 0A-10"N 1; ' '
+ 0A"F 0A-10"N D ' ' I●
+  -DI 
+ >
+ M[tank.explode]
+
+ %[tank.score] SCORE: \[tank.score]
+}
+
+@[tank.selfdestruct]{
+ U.yU.x Q.x+2U.#cx Q.y+2U.#cy
+ .[explosion]✹✹✸✸✶✶✧✧· 
+ 10<
+ Q.#cx-10U.x 20<
+ Q.x-1"< %.x F> '
+ Q.#cy-10U.y 20<
+ !* d = sqrt((x - cx)^2 + ((y - cy) * aspect)^2) *!
+ (Q.x-Q.#cx)^*2 + ((Q.y-Q.#cy)*2)^*2 U.#d2
+
+ Q.r^*2 - Q.#d2"<
+ Q.#d2 - (Q.r+2)^*2"<
+ !* on shock wave *!
+ Q.x,Q.yM[tank.goto]"F %.y F> '
+ -D Q.rQ.[explosion]I
+ '
+ |
+ !* within shock wave *!
+ Q.x,Q.yM[tank.goto]"F %.y F> '
+ -D I 
+ '
+ %.y>
+ %.x>
+ 1
+ %.r>
+ Q.#cx,Q.#cyM[tank.goto]
+}
+
+ESGETCOLUMNU.x :-1U.y
+Q.xU.#xo Q.yU.#yo
+
+!*
+ * Normalize identations to spaces -- assumed by M[goto]
+ * FIXME: Will not work well with character representations.
+ *!
+ESGETTABDRAWMODE-2"N
+ J <S^I;
+ ESGETCOLUMN-(-1ESGETCOLUMN)U.w
+ -D Q.w<I >
+ >
+'
+
+CONTROL: W A S D. SHOOT: SPACE. QUIT: ESCAPE. PRESS ANY KEY TO START. 
+
+ESGETCARETSTYLEU.[caretstyle]
+0ESSETCARETSTYLE
+
+1U.[sprite]
+<
+ Q.#xo,Q.#yo,0M[tank.blit] !* redraw background *!
+ Q.xU.#xo Q.yU.#yo
+
+ Q.x,Q.y,Q.[sprite]M[tank.blit]
+ 0 U.c
+ :Okey.U.c
+ F>
+ !key.w!
+ Q.y"> -%.y ' 3U.[sprite]
+ F>
+ !key.a!
+ Q.x,Q.y,0M[tank.blit] !* redraw background *!
+ Q.x"> -%.x ' 2U.[sprite]
+ F>
+ !key.s!
+ Q.x,Q.y,0M[tank.blit] !* redraw background *!
+ %.y 4U.[sprite]
+ F>
+ !key.d!
+ Q.x,Q.y,0M[tank.blit] !* redraw background *!
+ %.x 1U.[sprite]
+ F>
+ !key. !
+ !* FIXME: this also scrolls due to  *!
+ Q.x,Q.y,Q.[sprite]M[tank.shoot]
+ F>
+ !key.!
+ Q.x,Q.yM[tank.selfdestruct]
+ 1;
+>
+
+Q.[caretstyle]ESSETCARETSTYLE