sourcegames/trek/StarTrek.xtl

1⍝# Star Trek's rules, a library: trek.xtl (scripted), play.xtl (at the 2⍝# terminal) and the web page all use these. The classic Star Trek game 3⍝# as the COR24 BASIC demo plays it: an 8 by 8 galaxy of quadrants, each 4⍝# an 8 by 8 grid of sectors; find and destroy every Klingon before the 5⍝# stardate runs out, with warp and impulse drive, phasers, photon 6⍝# torpedoes and shields. 7⍝# 8⍝# The game is one vector: 1 energy, 2 torpedoes, 3 shields, 4 stardate, 9⍝# 5 deadline, 6 and 7 the quadrant (row, column, 0 to 7), 8 and 9 the 10⍝# sector, 10 the status (0 playing, 1 won, 2 out of time, 3 ship lost, 11⍝# 4 resigned); then the galaxy as three planes of 64 (Klingons, bases, 12⍝# stars per quadrant) and the current quadrant's 64 sectors (0 empty, 13⍝# 1 the Enterprise, 2 a star, 3 a base, 4 and more a Klingon: its hit 14⍝# points plus 4). 15 16ᵇ⁼u̲se< "Board" 17ˢ⁼u̲se< "State" 18ˣ⁼u̲se< "Text" 19 20⍝## Reading the state 21⍝ Where each thing is in the state vector, by name. 22⍝ :: Int 23⍝# Where the energy is, in the state. 24ˡenergy ← 1 25⍝ :: Int 26⍝# Where the torpedoes left are, in the state. 27ˡtorpedoes ← 2 28⍝ :: Int 29⍝# Where the shields are, in the state. 30ˡshieldsAt ← 3 31⍝ :: Int 32⍝# Where the stardate is, in the state. 33ˡstardate ← 4 34⍝ :: Int 35⍝# Where the quadrant's row is, in the state. 36ˡquadRow ← 6 37⍝ :: Int 38⍝# Where the quadrant's column is, in the state. 39ˡquadCol ← 7 40⍝ :: Int 41⍝# Where the sector's row is, in the state. 42ˡsectRow ← 8 43⍝ :: Int 44⍝# Where the sector's column is, in the state. 45ˡsectCol ← 9 46⍝ :: Int 47⍝# Where the status is, in the state. 48ˡstatus ← 10 49 50⍝ :: a -> a 51⍝# The energy left. 52ˡe̲nergy ← { s → 1 s̲elect s } 53⍝ :: a -> a 54⍝# Torpedoes left. 55ˡt̲orps ← { s → 2 s̲elect s } 56⍝ :: a -> a 57⍝# The shields' energy. 58ˡs̲hields ← { s → 3 s̲elect s } 59⍝ :: a -> a 60⍝# The stardate. 61ˡd̲ate ← { s → 4 s̲elect s } 62⍝ :: a -> a 63⍝# The quadrant: row and column, 0 to 7. 64ˡq̲uad ← { s → 6 7 s̲elect s } 65⍝ :: a -> a 66⍝# The sector within the quadrant: row and column, 0 to 7. 67ˡs̲ector ← { s → 8 9 s̲elect s } 68⍝ :: a -> a 69⍝# 0 playing, 1 won, 2 time ran out, 3 the Enterprise lost, 4 resigned. 70ˡs̲tatus ← { s → 10 s̲elect s } 71⍝ :: a -> Int -> a 72⍝# Plane p of the galaxy (1 Klingons, 2 bases, 3 stars), an 8 by 8 matrix. 73ˡg̲alaxy ← { s p → 8 8 r̲eshape 64 t̲ake (10 + 64 × p − 1) d̲rop s } 74⍝ :: a -> a 75⍝# The quadrant shown: 8 by 8 sectors (0 empty, then the Enterprise, a star, a base, a Klingon's hit points). 76ˡg̲rid ← { s → 8 8 r̲eshape -64 t̲ake s } 77⍝ :: Num a => a -> a 78⍝# Klingons in the galaxy and in this quadrant. 79ˡk̲lingons ← { s → '+ r̲/ r̲avel s ˡg̲alaxy 1 } 80⍝ :: (Num a, Num b, Truthy b) => a -> b 81⍝# How many Klingons are in this quadrant. 82ˡh̲ere ← { s → '+ r̲/ r̲avel 4 ≤ ˡg̲rid s } 83 84⍝ :: Int -> Int -> Int 85⍝## Changing it 86⍝# Several items changed at once (lib/State): iv is index, value, ... 87ˡu̲pdate ← { s iv → s ˢu̲pdate iv } 88⍝ :: Int -> Int -> Int 89⍝# The items from position p on replaced by v (pv is p then v; lib/State). 90ˡp̲ut ← { s pv → s ˢp̲ut pv } 91⍝ :: Int -> Int -> Int 92⍝# The state with a new quadrant grid. 93ˡw̲ithGrid ← { s g → s ˡp̲ut ((t̲ally s) − 63) c̲at r̲avel g } 94⍝ :: Int -> Int -> Int 95⍝# The state with plane p of the galaxy replaced (pg is p then its 64 numbers). 96ˡw̲ithPlane ← { s pg → s ˡp̲ut (11 + 64 × (f̲irst pg) − 1) c̲at 1 d̲rop pg } 97⍝ :: Num a => a -> a 98⍝# The quadrant's square in a galaxy plane, 1 to 64. 99ˡh̲ome ← { s → 1 + (8 × 6 s̲elect s) + 7 s̲elect s } 100 101⍝ :: Int -> Char 102⍝## Where things are, said as the BASIC said it 103⍝# A row and column (0 to 7) as "C-5". 104ˡa̲t ← { rc → ((1 + f̲irst rc) s̲elect "ABCDEFGH") c̲at "-" c̲at f̲ormat 1 + 2 s̲elect rc } 105 106⍝ :: Num a => Unit -> a 107⍝# The eight courses of the compass, 1 north, clockwise: the step in rows 108⍝# and columns for each, as a 2 by 8 table. 109ˡc̲ourses ← { @ → 2 8 r̲eshape -1 -1 0 1 1 1 0 -1 0 1 1 1 0 -1 -1 -1 } 110 111⍝ :: Any a => a -> Int 112⍝## A new game and a new quadrant 113⍝# Every quadrant at once: Klingons in about 15 of each 100 (1 to 3 of 114⍝# them), a base in 2 of 10, 1 to 5 stars. A galaxy without Klingons is 115⍝# rolled again. 116ˡn̲ew ← { x → 117 kl ← (85 < r̲oll! 64 r̲eshape 100) × r̲oll! 64 r̲eshape 3 118 0 = '+ r̲/ kl ? ˡn̲ew x 119 bases ← 2 ≥ r̲oll! 64 r̲eshape 10 120 stars ← r̲oll! 64 r̲eshape 5 121 q ← (r̲oll! 8 8) − 1 122 ˡe̲nter (3000 10 0 2300 2330 c̲at q c̲at 0 0 0) c̲at kl c̲at bases c̲at stars c̲at 64 r̲eshape 0 123} 124⍝ :: Int -> Int 125⍝# Entering a quadrant: the Enterprise, its Klingons (5 hit points 126⍝# each), base and stars on different sectors at random, all placed at 127⍝# once: the codes in a row, put into the sectors of a random order (the 128⍝# order's own order is its inverse). 129ˡe̲nter ← { s → 130 c ← ˡh̲ome s 131 n ← c s̲elect r̲avel s ˡg̲alaxy 1 132 b ← c s̲elect r̲avel s ˡg̲alaxy 2 133 i ← c s̲elect r̲avel s ˡg̲alaxy 3 134 order ← g̲rade r̲oll! 64 r̲eshape 1000000 135 codes ← 1 c̲at (n r̲eshape 9) c̲at (b r̲eshape 3) c̲at (i r̲eshape 2) c̲at (63 − n + b + i) r̲eshape 0 136 e ← (f̲irst order) − 1 137 t ← (s ˡu̲pdate ˡsectRow c̲at (e d̲iv 8) c̲at ˡsectCol c̲at e m̲od 8) ˡw̲ithGrid (g̲rade order) s̲elect codes 138 0 = n ? t 139 said ← p̲rint! "" 140 said ← p̲rint! "*** RED ALERT *** RED ALERT *** RED ALERT ***" 141 said ← p̲rint! @ f̲ormat< "*** {n} KLINGON(S) IN QUADRANT {l:a_t l:q_uad s} ***"
f̲ormat< expands to
("*** " c̲at (f̲ormat (n)) c̲at " KLINGON(S) IN QUADRANT " c̲at (f̲ormat (ˡa̲t ˡq̲uad s)) c̲at " ***")
142 said ← p̲rint! "*** RED ALERT *** RED ALERT *** RED ALERT ***" 143 t 144} 145 146⍝ :: Int -> Int 147⍝## Scans 148⍝# The short-range scan: the sector grid as characters, every sector at 149⍝# once (a Klingon's code, 4 or more, is cut to 4 and read as K), spaced 150⍝# by lib/Board. 151ˡs̲rs ← { s → 152 said ← p̲rint! "" 153 said ← p̲rint! @ f̲ormat< "QUADRANT {l:a_t l:q_uad s} SECTOR {l:a_t l:s_ector s}"
f̲ormat< expands to
("QUADRANT " c̲at (f̲ormat (ˡa̲t ˡq̲uad s)) c̲at " SECTOR " c̲at (f̲ormat (ˡa̲t ˡs̲ector s)))
154 said ← p̲rint! " 1 2 3 4 5 6 7 8" 155 shown ← p̲rint! (8 2 r̲eshape "A B C D E F G H ") c̲at₂ ᵇs̲paced (1 + 4 m̲in ˡg̲rid s) s̲elect ".E*BK" 156 said ← p̲rint! @ f̲ormat< "STARDATE {l:d_ate s} ENERGY {l:e_nergy s} SHIELDS {l:s_hields s} TORP {l:t_orps s}"
f̲ormat< expands to
("STARDATE " c̲at (f̲ormat (ˡd̲ate s)) c̲at " ENERGY " c̲at (f̲ormat (ˡe̲nergy s)) c̲at " SHIELDS " c̲at (f̲ormat (ˡs̲hields s)) c̲at " TORP " c̲at (f̲ormat (ˡt̲orps s)))
157 said ← p̲rint! @ f̲ormat< "QUADRANT {l:a_t l:q_uad s} KLINGONS LEFT {l:k_lingons s}"
f̲ormat< expands to
("QUADRANT " c̲at (f̲ormat (ˡa̲t ˡq̲uad s)) c̲at " KLINGONS LEFT " c̲at (f̲ormat (ˡk̲lingons s)))
158 s 159} 160⍝ :: Int -> Int 161⍝# The long-range scan: the 5 by 5 quadrants around this one, each as its 162⍝# Klingons, bases and stars in three digits, "***" off the galaxy. The 163⍝# window's rows and columns are a table; the three planes' values for 164⍝# the 25 quadrants are one selection from a 3 by 64 matrix, and every 165⍝# cell's four characters are picked at once from " *0123456789". 166ˡl̲rs ← { s → 167 said ← p̲rint! "" 168 said ← p̲rint! @ f̲ormat< "LONG RANGE SCAN AT QUADRANT {l:a_t l:q_uad s}"
f̲ormat< expands to
("LONG RANGE SCAN AT QUADRANT " c̲at (f̲ormat (ˡa̲t ˡq̲uad s)))
169 said ← p̲rint! "LEGEND: K B S K=KLINGONS B=BASES S=STARS ***=VOID" 170 r ← (f̲irst ˡq̲uad s) + -2 -1 0 1 2 171 c ← (2 s̲elect ˡq̲uad s) + -2 -1 0 1 2 172 in ← r̲avel ((r ≥ 0) ∧ r ≤ 7) '∧ t̲able (c ≥ 0) ∧ c ≤ 7 173 cell ← r̲avel 1 + (8 × 0 m̲ax 7 m̲in r) '+ t̲able 0 m̲ax 7 m̲in c 174 planes ← cell s̲elect₂ 3 64 r̲eshape 192 t̲ake 10 d̲rop s 175 digits ← ((3 + planes) × 3 25 r̲eshape in) + 2 × 3 25 r̲eshape n̲ot in 176 shown ← p̲rint! (5 20 r̲eshape r̲avel₂ (25 r̲eshape 1) c̲at digits) s̲elect " *0123456789" 177 s 178} 179 180⍝## Small helpers 181 182⍝ :: (Any a, Any b) => a -> b -> a 183⍝# Say t and give s back. 184ˡs̲ay ← { s t → 185 said ← p̲rint! t 186 s 187} 188⍝ :: Any a => a -> a 189⍝# Refuse a command for want of energy. 190ˡi̲nsufficient ← { s → s ˡs̲ay "INSUFFICIENT ENERGY" } 191⍝ :: Num a => a -> a 192⍝# A sector's number, 1 to 64, from its row and column. 193ˡc̲ell ← { rc → 8 ᵇc̲ell rc } 194⍝ :: Int -> Int -> Int 195⍝# The Enterprise moved to sector rc: its old sector emptied, the new one 196⍝# marked, both in one expression over the 64 sectors. 197ˡm̲oveTo ← { s rc → 198 g ← r̲avel ˡg̲rid s 199 all ← r̲ange 64 200 g ← g × all ≠ ˡc̲ell ˡs̲ector s 201 g ← (g × all ≠ ˡc̲ell rc) + all = ˡc̲ell rc 202 (s ˡu̲pdate ˡsectRow c̲at (f̲irst rc) c̲at ˡsectCol c̲at 2 s̲elect rc) ˡw̲ithGrid g 203} 204⍝ :: Int -> Int -> Int 205⍝# A path from the Enterprise along course c for k steps: a 2 by k matrix 206⍝# of rows and columns, every step at once; and which steps are inside 207⍝# the quadrant, and their sectors (clamped, for looking them up). 208ˡp̲ath ← { s ck → 209 d ← (f̲irst ck) s̲elect₂ ˡc̲ourses @ 210 k ← r̲ange 2 s̲elect ck 211 ((ˡs̲ector s) 'l̲eft t̲able k) + d '× t̲able k 212} 213⍝ :: (Num a, Truthy b) => a -> b 214⍝# Whether every point of P (rows and columns) lies inside a quadrant. 215ˡi̲nside ← { P → '∧ r̲/ (P ≥ 0) ∧ P ≤ 7 } 216⍝ :: Num a => a -> a 217⍝# The sectors (1 to 64) of the points P, clamped to the quadrant. 218ˡc̲ells ← { P → 1 + (8 × 0 m̲ax 7 m̲in 1 s̲elect P) + 0 m̲ax 7 m̲in 2 s̲elect P } 219⍝ :: Num a => Int -> a 220⍝# Print each sector of a flat list of rows and columns, " C-5". 221ˡt̲rack ← { v → 222 0 = t̲ally v ? 0 223 said ← p̲rint! @ f̲ormat< " {l:a_t 2 t_ake v}"
f̲ormat< expands to
("  " c̲at (f̲ormat (ˡa̲t 2 t̲ake v)))
224 1 + ˡt̲rack 2 d̲rop v 225} 226 227⍝ :: Int -> Int 228⍝## The Klingons fire back 229⍝# 30 to 60 units: the shields take them first, the rest comes off the 230⍝# energy. 231ˡf̲ire ← { s → 232 0 = ˡh̲ere s ? s 233 u ← 29 + r̲oll! 31 234 h ← ˡs̲hields s 235 e ← (ˡe̲nergy s) − 0 m̲ax u − h 236 h ← 0 m̲ax h − u 237 said ← p̲rint! @ f̲ormat< "HIT - SHIELDS {h} ENERGY {e}"
f̲ormat< expands to
("HIT - SHIELDS " c̲at (f̲ormat (h)) c̲at " ENERGY " c̲at (f̲ormat (e)))
238 s ˡu̲pdate ˡenergy c̲at e c̲at ˡshieldsAt c̲at h 239} 240 241⍝ :: Int -> Int -> Int 242⍝## Moving 243⍝# Warp: course c, factor p (1 to 8) quadrants; 8 energy and one stardate 244⍝# a factor; clamped at the galaxy's edge; a new quadrant, then a scan. 245ˡw̲arp ← { s cp → 246 c ← f̲irst cp 247 p ← 2 s̲elect cp 248 (c < 1) ∨ (c > 8) ∨ (p < 1) ∨ p > 8 ? s 249 (ˡe̲nergy s) < 8 × p ? ˡi̲nsufficient s 250 q ← (ˡq̲uad s) + p × c s̲elect₂ ˡc̲ourses @ 251 said ← (q < 0) ∨ q > 7 252 told ← ˡc̲lamped '+ r̲/ said 253 q ← 0 m̲ax 7 m̲in q 254 ˡs̲rs ˡe̲nter s ˡu̲pdate ˡenergy c̲at ((ˡe̲nergy s) − 8 × p) c̲at ˡstardate c̲at ((ˡd̲ate s) + p) c̲at ˡquadRow c̲at (f̲irst q) c̲at ˡquadCol c̲at 2 s̲elect q 255} 256⍝ :: Num a => Int -> a 257⍝# Say n times that a move was clamped at the galaxy's edge. 258ˡc̲lamped ← { n → ˣl̲ines n r̲eshape e̲nclose "OUT OF GALAXY - CLAMPED" } 259⍝ :: Int -> Int -> Int 260⍝# Impulse: course c, p (1 to 8) sectors, a unit of energy each. The 261⍝# whole path at once; the first step that leaves the quadrant or meets 262⍝# something decides: through to the end, into the next quadrant, or 263⍝# halted just before the obstacle. 264ˡi̲mpulse ← { s cp → 265 c ← f̲irst cp 266 p ← 2 s̲elect cp 267 (c < 1) ∨ (c > 8) ∨ (p < 1) ∨ p > 8 ? s 268 (ˡe̲nergy s) < p ? ˡi̲nsufficient s 269 t ← s ˡu̲pdate ˡenergy c̲at (ˡe̲nergy s) − p 270 P ← s ˡp̲ath c c̲at p 271 in ← ˡi̲nside P 272 busy ← in ∧ 0 ≠ (ˡc̲ells P) s̲elect r̲avel ˡg̲rid s 273 j ← f̲irst (w̲here (n̲ot in) ∨ busy) c̲at p + 1 274 j > p ? ˡs̲rs t ˡm̲oveTo p s̲elect₂ P 275 0 = j s̲elect in ? ˡs̲rs t ˡc̲ross c 276 ˡs̲rs t ˡh̲alt j s̲elect₂ (ˡs̲ector s) c̲at₂ P 277} 278⍝ :: Int -> Int -> Int 279⍝# Leave the quadrant along course c: into the neighbor, clamped at the galaxy's edge. 280ˡc̲ross ← { s c → 281 q ← 0 m̲ax 7 m̲in (ˡq̲uad s) + c s̲elect₂ ˡc̲ourses @ 282 ˡe̲nter s ˡu̲pdate ˡquadRow c̲at (f̲irst q) c̲at ˡquadCol c̲at 2 s̲elect q 283} 284⍝ :: Int -> Int -> Int 285⍝# Stop at sector rc in front of an obstacle. 286ˡh̲alt ← { s rc → 287 said ← p̲rint! @ f̲ormat< "OBSTRUCTED - HALTED AT SECTOR {l:a_t rc}"
f̲ormat< expands to
("OBSTRUCTED - HALTED AT SECTOR " c̲at (f̲ormat (ˡa̲t rc)))
288 s ˡm̲oveTo rc 289} 290 291⍝ :: Int -> Int -> Int 292⍝## Fighting 293⍝# Phasers: p energy split over the Klingons here; every Klingon is hit 294⍝# at once (its code less the share); those below 4 are destroyed. One 295⍝# line per Klingon, in sector order; then they fire back. 296ˡp̲hasers ← { s p → 297 n ← ˡh̲ere s 298 0 = n ? s ˡs̲ay "NO KLINGONS HERE" 299 p ≤ 0 ? s 300 p > ˡe̲nergy s ? ˡi̲nsufficient s 301 g ← r̲avel ˡg̲rid s 302 hit ← g ≥ 4 303 v ← g − hit × p d̲iv n 304 dead ← hit ∧ v < 4 305 said ← ˡh̲its r̲avel₂ (2 c̲at '+ r̲/ hit) r̲eshape ((w̲here hit) c̲at hit r̲eplicate v) 306 kl ← (r̲avel s ˡg̲alaxy 1) − ('+ r̲/ dead) × (r̲ange 64) = ˡh̲ome s 307 ˡf̲ire ((s ˡu̲pdate ˡenergy c̲at (ˡe̲nergy s) − p) ˡw̲ithGrid v × n̲ot dead) ˡw̲ithPlane 1 c̲at kl 308} 309⍝ :: Num a => Int -> a 310⍝# The phaser report from pairs of a sector and what is left of its 311⍝# Klingon. 312ˡh̲its ← { v → 313 0 = t̲ally v ? 0 314 k ← (f̲irst v) − 1 315 rc ← (k d̲iv 8) c̲at k m̲od 8 316 hp ← (2 s̲elect v) − 4 317 said ← p̲rint! @ f̲ormat< "KLINGON AT {l:a_t rc}{l:p_hp hp}"
f̲ormat< expands to
("KLINGON AT " c̲at (f̲ormat (ˡa̲t rc)) c̲at (f̲ormat (ˡp̲hp hp)))
318 1 + ˡh̲its 2 d̲rop v 319} 320⍝ :: Int -> Char 321⍝# What a hit leaves of a Klingon: destroyed, or its hit points left. 322ˡp̲hp ← { hp → 323 hp < 0 ? " DESTROYED" 324 @ f̲ormat< " HIT - HP LEFT {hp}"
f̲ormat< expands to
" HIT - HP LEFT " c̲at (f̲ormat (hp))
325} 326⍝ :: Int -> Int -> Int 327⍝# A photon torpedo along course c: the whole track at once, to the first 328⍝# thing it meets or the quadrant's edge; a Klingon or a base there is 329⍝# destroyed, a star absorbs it. Then the Klingons fire back. 330ˡt̲orpedo ← { s c → 331 0 ≥ ˡt̲orps s ? s ˡs̲ay "NO TORPEDOES REMAINING" 332 (c < 1) ∨ c > 8 ? s 333 said ← p̲rint! "TORPEDO TRACK:" 334 t ← s ˡu̲pdate ˡtorpedoes c̲at (ˡt̲orps s) − 1 335 P ← s ˡp̲ath c c̲at 7 336 in ← ˡi̲nside P 337 what ← in × (ˡc̲ells P) s̲elect r̲avel ˡg̲rid s 338 j ← f̲irst (w̲here (n̲ot in) ∨ what ≠ 0) c̲at 8 339 hits ← j s̲elect in c̲at 0 340 shown ← ˡt̲rack r̲avel₂ ((j − 1) + hits) t̲ake₂ P 341 0 = hits ? ˡf̲ire t ˡs̲ay "TORPEDO MISSED - LEFT QUADRANT" 342 ˡf̲ire t ˡs̲trike (j s̲elect what) c̲at j s̲elect₂ P 343} 344⍝ :: Int -> Int -> Int 345⍝# What a torpedo did on sector rc (the thing's code first). 346ˡs̲trike ← { s wrc → 347 w ← f̲irst wrc 348 rc ← 1 d̲rop wrc 349 at ← ˡa̲t rc 350 k ← ˡc̲ell rc 351 w = 2 ? s ˡs̲ay @ f̲ormat< "TORPEDO ABSORBED BY STAR AT {at}"
f̲ormat< expands to
("TORPEDO ABSORBED BY STAR AT " c̲at (f̲ormat (at)))
352 g ← (r̲avel ˡg̲rid s) × k ≠ r̲ange 64 353 w = 3 ? (s ˡw̲ithGrid g) ˡw̲ithPlane 2 c̲at (r̲avel s ˡg̲alaxy 2) × (ˡh̲ome s) ≠ r̲ange 64 354 said ← p̲rint! @ f̲ormat< "*** KLINGON DESTROYED AT {at} ***"
f̲ormat< expands to
("*** KLINGON DESTROYED AT " c̲at (f̲ormat (at)) c̲at " ***")
355 (s ˡw̲ithGrid g) ˡw̲ithPlane 1 c̲at (r̲avel s ˡg̲alaxy 1) − (ˡh̲ome s) = r̲ange 64 356} 357⍝ :: Int -> Int -> Int 358⍝# Shields: p energy into the shields (negative drains them back). 359ˡs̲hieldsTo ← { s p → 360 0 > (ˡe̲nergy s) − p ? ˡi̲nsufficient s 361 s ˡu̲pdate ˡenergy c̲at ((ˡe̲nergy s) − p) c̲at ˡshieldsAt c̲at (ˡs̲hields s) + p 362} 363 364⍝## Reports 365 366⍝ :: Int -> Int 367⍝# The status report: the stardate, energy, shields, torpedoes and 368⍝# Klingons left, the quadrant and the sector. 369ˡr̲eport ← { s → 370 said ← p̲rint! "" 371 said ← p̲rint! @ f̲ormat< "STARDATE {l:d_ate s} / {5 s_elect s}"
f̲ormat< expands to
("STARDATE " c̲at (f̲ormat (ˡd̲ate s)) c̲at " / " c̲at (f̲ormat (5 s̲elect s)))
372 said ← p̲rint! @ f̲ormat< "ENERGY {l:e_nergy s}"
f̲ormat< expands to
("ENERGY   " c̲at (f̲ormat (ˡe̲nergy s)))
373 said ← p̲rint! @ f̲ormat< "SHIELDS {l:s_hields s}"
f̲ormat< expands to
("SHIELDS  " c̲at (f̲ormat (ˡs̲hields s)))
374 said ← p̲rint! @ f̲ormat< "TORP {l:t_orps s}"
f̲ormat< expands to
("TORP     " c̲at (f̲ormat (ˡt̲orps s)))
375 said ← p̲rint! @ f̲ormat< "KLINGONS {l:k_lingons s}"
f̲ormat< expands to
("KLINGONS " c̲at (f̲ormat (ˡk̲lingons s)))
376 said ← p̲rint! @ f̲ormat< "QUADRANT {l:a_t l:q_uad s}"
f̲ormat< expands to
("QUADRANT " c̲at (f̲ormat (ˡa̲t ˡq̲uad s)))
377 said ← p̲rint! @ f̲ormat< "SECTOR {l:a_t l:s_ector s}"
f̲ormat< expands to
("SECTOR   " c̲at (f̲ormat (ˡa̲t ˡs̲ector s)))
378 s 379} 380⍝ :: Any a => a -> a 381⍝# Print the commands. 382ˡh̲elp ← { s → 383 said ← p̲rint! "" 384 shown ← ˡl̲ines ( 385 "1 SRS SHORT RANGE SCAN" 386 "2 LRS LONG RANGE SCAN" 387 "3 WAR WARP DRIVE" 388 "4 IMP IMPULSE DRIVE" 389 "5 PHA PHASERS" 390 "6 TOR TORPEDOES" 391 "7 SHE SHIELD CONTROL" 392 "8 STA STATUS" 393 "9 HEL THIS HELP" 394 "0 QUI RESIGN" 395 "" 396 "COURSE COMPASS (FOR WARP/IMPULSE/TORPEDO):" 397 " 8 1 2 1=N 2=NE 3=E 4=SE" 398 " 7 + 3 5=S 6=SW 7=W 8=NW" 399 " 6 5 4" 400 "COORDS: ROWS A-H DOWN, COLS 1-8 ACROSS (E.G. C-5)") 401 s 402} 403⍝ :: Num a => Box Char -> a 404⍝# Print each string of a list of strings (lib/Text). 405ˡl̲ines ← { v → ˣl̲ines v } 406 407⍝ :: Int -> Int -> Int 408⍝## The game's course 409⍝# A command and its arguments: 1 SRS, 2 LRS, 3 warp (course, factor), 410⍝# 4 impulse (course, sectors), 5 phasers (energy), 6 torpedo (course), 411⍝# 7 shields (energy), 8 status, 9 help, 0 resign; then the verdict. 412ˡc̲ommand ← { s v → 413 ˡj̲udge s ˡd̲o v 414} 415⍝ :: Int -> Int -> Int 416⍝# Carry out command v (its number, then its arguments). 417ˡd̲o ← { s v → 418 c ← f̲irst v 419 a ← 1 d̲rop v 420 c = 1 ? ˡs̲rs s 421 c = 2 ? ˡl̲rs s 422 c = 3 ? s ˡw̲arp a 423 c = 4 ? s ˡi̲mpulse a 424 c = 5 ? s ˡp̲hasers f̲irst a 425 c = 6 ? s ˡt̲orpedo f̲irst a 426 c = 7 ? s ˡs̲hieldsTo f̲irst a 427 c = 8 ? ˡr̲eport s 428 c = 9 ? ˡh̲elp s 429 c = 0 ? s ˡu̲pdate ˡstatus c̲at 4 430 s ˡs̲ay "?WHAT" 431} 432⍝ :: Int -> Int 433⍝# The status: out of time first, then the ship lost, then the mission 434⍝# complete (as the BASIC checks them); a resignation stands. 435ˡj̲udge ← { s → 436 4 = ˡs̲tatus s ? s 437 over ← ((ˡd̲ate s) > 5 s̲elect s) c̲at (0 ≥ ˡe̲nergy s) c̲at 0 = ˡk̲lingons s 438 s ˡu̲pdate ˡstatus c̲at f̲irst (over r̲eplicate 2 3 1) c̲at 0 439} 440⍝ :: Int -> Char 441⍝# The game's ending, printed, and the Klingons left. 442ˡe̲nd ← { s → 443 st ← ˡs̲tatus s 444 said ← p̲rint! "" 445 st = 1 ? ˡm̲ission s 446 said ← p̲rint! d̲isclose (st − 1) s̲elect "*** STARDATE EXPIRED ***" "*** ENTERPRISE LOST ***" "*** COMMAND RESIGNED ***" 447 @ f̲ormat< "KLINGONS REMAINING {l:k_lingons s}"
f̲ormat< expands to
"KLINGONS REMAINING " c̲at (f̲ormat (ˡk̲lingons s))
448} 449⍝ :: Int -> Char 450⍝# The mission complete: the stardate and the energy left. 451ˡm̲ission ← { s → 452 said ← p̲rint! "*** MISSION COMPLETE ***" 453 said ← p̲rint! @ f̲ormat< "STARDATE {l:d_ate s}"
f̲ormat< expands to
("STARDATE " c̲at (f̲ormat (ˡd̲ate s)))
454 @ f̲ormat< "ENERGY {l:e_nergy s}"
f̲ormat< expands to
"ENERGY   " c̲at (f̲ormat (ˡe̲nergy s))
455}