!* * 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 > ' 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