sourceextensions/scene/demos/voxels-game.xtl
1⍝# Voxels, 15: Gem Hunt. Ten gems are buried around the start, a few
2⍝# blocks under the surface; dig them out in three minutes. The first
3⍝# lies four blocks straight down from where you start; the others are
4⍝# scattered within a dozen blocks, deeper. Gems glow a little (12 where
5⍝# a lamp is 15), so a tunnel near one is lit -- and the corner of the
6⍝# screen says how far the nearest gem you have not found is. Everything
7⍝# from the voxel demos works: dig, place, lamps, water, night. G gives
8⍝# up and shows the score. The game is X_eTaL: the gems are edits, a
9⍝# find is a dig whose cell is a gem's, the clock is the frames (60 a
10⍝# second), the labels are scene's.
11⍝# Run: just demo scene voxels-game
12⍝# click (or X) dig, right-click (or E) place, 1 to 8 choose the block
13⍝# (8 a lamp), N night or day, W A S D walk, Space jump, F fly, drag or
14⍝# the arrows to look, G give up, H back to the start, q quit
15
16ᵉⁿ⁼u̲se< "Endless"
17ᵛˣ⁼u̲se< "Voxels"
18ᵖˡ⁼u̲se< "Play"
19ˢᶜ⁼u̲se< "Scene"
20
21w ← "Voxels 15: Gem Hunt -- X_eTaL" ˢᶜo̲pen! 640 400
22g ← w ˢᶜf̲og! 22.0 44.0
23k ← w ˢᶜs̲ky! 0.55 0.72 0.92
24k ← w ˢᶜc̲urve! 160.0
25
26"Gem Hunt: ten gems are buried near you. Dig them out in three minutes."
27"The first is four blocks straight down. Gems glow; the top of the screen says how far the nearest is."
28ᵖˡhelpLit
29"G: give up"
30
31⍝## The gems
32
33s ← ᵉⁿl̲ighting ᵉⁿn̲ew w
34x0 ← f̲loor ᵉⁿs̲tart s
35
36⍝ the ground's top block at column x z: one below the height
37ᵘt̲op ← { xz → (f̲irst r̲avel ᵛˣh̲eightsAt xz c̲at 1) − 1 }
38
39⍝# u:m_ore gs: one more gem, at a random column within 12 blocks of the
40⍝# start (not the start's own), 2 to 6 blocks under the ground's top,
41⍝# never above the world's bottom
42ᵘm̲ore ← { gs →
43 o ← (r̲oll! 25 25) − 13
44 xz ← (1 3 s̲elect x0) + o
45 y ← 1 m̲ax (ᵘt̲op xz) − 1 + r̲oll! 5
46 gs c̲at 1 3 r̲eshape (1 s̲elect xz) c̲at y c̲at 2 s̲elect xz
47}
48
49⍝# the first gem four blocks down under the start (its fourth dig), then
50⍝# nine more
51first ← 1 3 r̲eshape (1 s̲elect x0) c̲at ((ᵘt̲op 1 3 s̲elect x0) − 3) c̲at 3 s̲elect x0
52gems ← 9 'ᵘm̲ore p̲ower first
53"the gems (x y z), the first under the start:"
54gems
55s ← (gems, 9) ᵉⁿs̲etAll s
56
57⍝## Playing
58
59⍝# The game is a tuple: (the gems not found yet, n by 3; how many found;
60⍝# the frames left; whether it is over; the edits seen so far). With the
61⍝# world and its player and the chosen block it makes the state.
62
63minutes ← 3
64total ← 1 s̲elect s̲hape gems
65
66⍝ a cell's key, for finding gems among dug cells
67ᵘk̲ey ← { q → (200000 × (64 × 100000 + 1 s̲elect₂ q) + 2 s̲elect₂ q) + 100000 + 3 s̲elect₂ q }
68
69⍝ the time left as m:ss
70ᵘc̲lock ← { frames →
71 secs ← frames d̲iv 60
72 (f̲ormat secs d̲iv 60) c̲at ":" c̲at -2 t̲ake "0" c̲at f̲ormat secs m̲od 60
73}
74
75⍝ the labels: gems found, the time, how far the nearest gem is
76ᵘs̲how ← { (s, game) →
77 (gs, found, left, over, _) ← game
78 p ← ᵉⁿp̲osition s
79 a ← ((f̲loat w) c̲at 1.0 16.0 14.0 14.0 1.0 1.0 1.0) ˢᶜl̲abel! "Gems " c̲at (f̲ormat found) c̲at " of " c̲at f̲ormat total
80 b ← ((f̲loat w) c̲at 2.0 200.0 14.0 14.0 1.0 1.0 0.6) ˢᶜl̲abel! "Time " c̲at ᵘc̲lock left
81 hint ← (0 < t̲ally gs) ᵘn̲ear (gs, p)
82 c ← ((f̲loat w) c̲at 3.0 340.0 14.0 14.0 0.6 1.0 1.0) ˢᶜl̲abel! hint
83 game
84}
85ᵘn̲ear ← { yes gp →
86 (gs, p) ← gp
87 0 = yes ? ""
88 d ← ((f̲loat gs) + 0.5) − ((t̲ally gs) c̲at 3) r̲eshape p
89 "Nearest gem " c̲at (f̲ormat f̲loor 0.5 + ('m̲in r̲/ '+ r̲/₂ d × d) ^ 0.5) c̲at " blocks"
90}
91
92⍝ the end: the score, big, across the middle
93ᵘe̲nd ← { game →
94 (gs, found, left, over, seen) ← game
95 over ? game
96 m ← (0 = t̲ally gs) ᵘv̲erdict (found, left)
97 said ← p̲rint! "game over: " c̲at m
98 z ← ((f̲loat w) c̲at 4.0 c̲at (320.0 − 1.5 × f̲loat (6 × t̲ally m) − 1) c̲at 170.0 21.0 1.0 0.85 0.3) ˢᶜl̲abel! m
99 (gs, found, left, 1, seen)
100}
101ᵘv̲erdict ← { all fl →
102 (found, left) ← fl
103 all ? "All " c̲at (f̲ormat total) c̲at " gems with " c̲at (ᵘc̲lock left) c̲at " to spare!"
104 left = 0 ? (f̲ormat found) c̲at " of " c̲at (f̲ormat total) c̲at " gems -- time is up"
105 (f̲ormat found) c̲at " of " c̲at (f̲ormat total) c̲at " gems -- stopped with " c̲at (ᵘc̲lock left) c̲at " left"
106}
107
108⍝ the gems found this frame: dug cells (the newest edits, block 0) that
109⍝ are gems' cells
110ᵘf̲inds ← { (s, game) →
111 (gs, found, left, over, seen) ← game
112 ed ← ᵉⁿe̲dits s
113 n ← t̲ally ed
114 new ← (n − seen) t̲ake ed
115 dug ← (0 = 4 s̲elect₂ new) r̲eplicate 1 2 3 s̲elect₂ new
116 hit ← (ᵘk̲ey gs) m̲ember? ᵘk̲ey dug
117 k ← '+ r̲/ hit
118 said ← (k > 0) ᵘt̲ell (hit r̲eplicate gs, found + k)
119 ((0 = hit) r̲eplicate gs, found + k, left, over, n)
120}
121ᵘt̲ell ← { yes cf →
122 (cells, found) ← cf
123 0 = yes ? ""
124 p̲rint! "found a gem at " c̲at (f̲ormat r̲avel cells) c̲at " (" c̲at (f̲ormat found) c̲at " of " c̲at (f̲ormat total) c̲at ")"
125}
126
127⍝# one frame: the world's frame (pl:f_rameV), then the game's turn and
128⍝# its labels
129ᵘf̲rame ← { (s, sel, game) →
130 ᵉⁿs̲topped s ? (s, sel, game)
131 (s, sel, v) ← ᵖˡf̲rameV (s, sel)
132 game ← ᵘt̲urn (s, v, game)
133 (s, sel, ᵘs̲how (s, game))
134}
135
136⍝# the game's turn: the gems found, the clock, and the end when the
137⍝# time is up, all are found or G is pressed (once over, it stays over)
138ᵘt̲urn ← { (s, v, game) →
139 (gs, found, left, over, seen) ← game
140 over ? game
141 game ← ᵘf̲inds (s, game)
142 (gs, found, left, over, seen) ← game
143 left ← 0 m̲ax left − 1
144 game ← (gs, found, left, over, seen)
145 done ← (0 = left) + (0 = t̲ally gs) + v m̲atch "key g"
146 0 < done ? ᵘe̲nd game
147 game
148}
149
150hud ← w ᵖˡh̲udLit 1
151s ← (4 × (1 + 2 × ᵉⁿreach) × 1 + 2 × ᵉⁿreach) 'ᵉⁿs̲tream p̲ower s
152game ← (gems, 0, minutes × 60 × 60, 0, t̲ally ᵉⁿe̲dits s)
153last ← 100000 'ᵘf̲rame p̲ower (s, 1, game)
154z ← ˢᶜc̲lose! w
155⍝ (accessors, not top-level tuple patterns: ask E10)
156ᵘg̲ameOf ← { (_, _, game) → game }
157ᵘf̲oundOf ← { (_, found, _, _, _) → found }
158"gems found:"
159ᵘf̲oundOf ᵘg̲ameOf last
160"bye"