├── .github
└── FUNDING.yml
├── CustomElements.js
├── LICENSE
├── Libraries
├── eatlegacy.js
├── habitat.js
└── spacetode.js
├── Media
├── Fonts
│ ├── Inconsolata.otf
│ ├── Rosario-Bold.ttf
│ ├── Rosario-BoldItalic.ttf
│ ├── Rosario-Italic.ttf
│ ├── Rosario-Regular.ttf
│ ├── UbuntuMono-B.ttf
│ ├── UbuntuMono-BI.ttf
│ ├── UbuntuMono-R.ttf
│ └── UbuntuMono-RI.ttf
└── Images
│ ├── RedTode.png
│ └── favicon.png
├── README.md
├── Source
├── Elements
│ ├── Clear.js
│ ├── Explosive.js
│ ├── Food.js
│ ├── Globals.js
│ ├── Life.js
│ ├── Old
│ │ ├── TodeSplat2
│ │ │ ├── Bondo.js
│ │ │ ├── Clear.js
│ │ │ ├── EdgeClear.js
│ │ │ ├── FatFly.js
│ │ │ ├── Pheromone.js
│ │ │ ├── Platformer.js
│ │ │ ├── PlayerSnake.js
│ │ │ ├── Rope.js
│ │ │ ├── SleepyFly.js
│ │ │ ├── Snake.js
│ │ │ └── SpaceShip.js
│ │ └── TodeSplat3
│ │ │ ├── Explosive.js
│ │ │ ├── Globals.js
│ │ │ ├── Life.js
│ │ │ ├── People.js
│ │ │ ├── Presets.js
│ │ │ ├── Sandbox.js
│ │ │ ├── T2Tile.js
│ │ │ ├── Tutorial.js
│ │ │ └── Weather.js
│ ├── Sandbox.js
│ ├── Smell.js
│ ├── State.js
│ ├── T2Tile.js
│ ├── Temperature.js
│ ├── Testing.js
│ ├── TwoTwoTwoTwo.js
│ └── Weird.js
└── Engine
│ ├── Dropper.js
│ ├── Floor.js
│ ├── Lighting.js
│ ├── Random.js
│ ├── ShuffleWorker.js
│ ├── Site.js
│ ├── Space.js
│ └── World.js
├── config.js
├── index.html
├── main.js
└── ui.js
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: TodePond
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
13 |
--------------------------------------------------------------------------------
/CustomElements.js:
--------------------------------------------------------------------------------
1 | SpaceTode`
2 |
3 |
4 | `
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 l2wilson94
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/Libraries/eatlegacy.js:
--------------------------------------------------------------------------------
1 |
2 | // This is an older version of the Eat library.
3 | // I kept it because SpaceTode still uses it.
4 |
5 | //
6 | // Every result has three properties...
7 | //
8 | // 'success'
9 | // true if the desired thing was found
10 | //
11 | // 'snippet'
12 | // the desired thing
13 | //
14 | // 'code'
15 | // the rest of the code (with the desired thing removed)
16 | //
17 |
18 | EAT = {}
19 | HABITAT.EAT_LEGACY = true
20 |
21 | {
22 |
23 | //====================//
24 | // Control Structures //
25 | //====================//
26 | EAT.many = (func) => (source, ...args) => {
27 |
28 | // Buffers
29 | let success = undefined
30 | let code = source
31 |
32 | // Head
33 | let headResult = undefined
34 | headResult = {success, code} = func(code, ...args)
35 | if (!success) return {...headResult, code: source}
36 |
37 | // Tail
38 | let tailResult = undefined
39 | tailResult = {success, code} = EAT.many(func)(code, ...args)
40 | if (!success) return headResult
41 | tailResult.snippet = headResult.snippet + tailResult.snippet
42 | return tailResult
43 |
44 | }
45 |
46 | EAT.maybe = (func) => (source, ...args) => {
47 |
48 | let result = undefined
49 | let success = undefined
50 | let code = source
51 |
52 | result = {success, code} = func(code, ...args)
53 | if (!success) {
54 | result.success = true
55 | result.snippet = ""
56 | }
57 |
58 | return result
59 | }
60 |
61 | EAT.list = (...funcs) => (source, ...args) => {
62 |
63 | // Buffers
64 | let success = undefined
65 | let code = source
66 |
67 | // Head
68 | let headResult = undefined
69 | const headFunc = funcs[0]
70 | headResult = {success, code} = headFunc(code, ...args)
71 | if (!success) return {...headResult, code: source}
72 |
73 | // Tail
74 | let tailResult = undefined
75 | const tailFuncs = funcs.slice(1)
76 | if (tailFuncs.length == 0) return headResult
77 | tailResult = {success, code} = EAT.list(...tailFuncs)(code, ...args)
78 | tailResult.snippet = headResult.snippet + tailResult.snippet
79 | return tailResult
80 |
81 | }
82 |
83 | EAT.or = (...funcs) => (source, ...args) => {
84 |
85 | for (const func of funcs) {
86 |
87 | let result = undefined
88 | let success = undefined
89 | let code = source
90 |
91 | result = {success, code} = func(code, ...args)
92 | if (success) return result
93 | }
94 |
95 | const success = false
96 | const code = source
97 | const snippet = undefined
98 | return {success, snippet, code}
99 | }
100 |
101 | EAT.fail = (source) => ({success: false, snippet: undefined, code: source})
102 |
103 | //====================//
104 | // In-Built Functions //
105 | //====================//
106 | EAT.string = (string) => (source) => {
107 | const success = source.slice(0, string.length) == string
108 | const snippet = success? string : undefined
109 | const code = success? source.slice(string.length) : source
110 | return {success, snippet, code}
111 | }
112 |
113 | EAT.regexp = EAT.regExp = EAT.regex = EAT.regEx = (regex) => (source) => {
114 | const fullRegex = new RegExp("^" + regex.source + "$")
115 |
116 | let i = 0
117 | while (i <= source.length) {
118 | const snippet = source.slice(0, i)
119 | const success = fullRegex.test(snippet)
120 | if (success) {
121 | const code = source.slice(snippet.length)
122 | return {success, snippet, code}
123 | }
124 | i++
125 | }
126 |
127 | const success = false
128 | const snippet = undefined
129 | const code = source
130 | return {success, snippet, code}
131 |
132 | }
133 |
134 | EAT.space = EAT.string(" ")
135 | EAT.tab = EAT.string(" ")
136 | EAT.newline = EAT.newLine = EAT.string("\n")
137 |
138 | EAT.gap = EAT.many (
139 | EAT.or (
140 | EAT.space,
141 | EAT.tab,
142 | )
143 | )
144 |
145 | EAT.whitespace = EAT.whiteSpace = EAT.many (
146 | EAT.or (
147 | EAT.space,
148 | EAT.tab,
149 | EAT.newline,
150 | )
151 | )
152 |
153 | EAT.emptyLine = EAT.list (
154 | EAT.maybe(EAT.gap),
155 | EAT.newline,
156 | )
157 |
158 | EAT.emptyLines = EAT.many(EAT.emptyLine)
159 |
160 | EAT.name = EAT.list (
161 | EAT.regexp(/[a-zA-Z_$]/),
162 | EAT.many(EAT.regex(/[a-zA-Z0-9_$]/))
163 | )
164 |
165 | EAT.margin = EAT.or (
166 | EAT.many(EAT.tab),
167 | EAT.many(EAT.space),
168 | )
169 |
170 | EAT.line = EAT.many(EAT.regex(/[^\n]/))
171 | }
--------------------------------------------------------------------------------
/Media/Fonts/Inconsolata.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TodePond/SandPond/6015bd3e4692ce7398408bdf7388f15cb8b50c09/Media/Fonts/Inconsolata.otf
--------------------------------------------------------------------------------
/Media/Fonts/Rosario-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TodePond/SandPond/6015bd3e4692ce7398408bdf7388f15cb8b50c09/Media/Fonts/Rosario-Bold.ttf
--------------------------------------------------------------------------------
/Media/Fonts/Rosario-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TodePond/SandPond/6015bd3e4692ce7398408bdf7388f15cb8b50c09/Media/Fonts/Rosario-BoldItalic.ttf
--------------------------------------------------------------------------------
/Media/Fonts/Rosario-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TodePond/SandPond/6015bd3e4692ce7398408bdf7388f15cb8b50c09/Media/Fonts/Rosario-Italic.ttf
--------------------------------------------------------------------------------
/Media/Fonts/Rosario-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TodePond/SandPond/6015bd3e4692ce7398408bdf7388f15cb8b50c09/Media/Fonts/Rosario-Regular.ttf
--------------------------------------------------------------------------------
/Media/Fonts/UbuntuMono-B.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TodePond/SandPond/6015bd3e4692ce7398408bdf7388f15cb8b50c09/Media/Fonts/UbuntuMono-B.ttf
--------------------------------------------------------------------------------
/Media/Fonts/UbuntuMono-BI.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TodePond/SandPond/6015bd3e4692ce7398408bdf7388f15cb8b50c09/Media/Fonts/UbuntuMono-BI.ttf
--------------------------------------------------------------------------------
/Media/Fonts/UbuntuMono-R.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TodePond/SandPond/6015bd3e4692ce7398408bdf7388f15cb8b50c09/Media/Fonts/UbuntuMono-R.ttf
--------------------------------------------------------------------------------
/Media/Fonts/UbuntuMono-RI.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TodePond/SandPond/6015bd3e4692ce7398408bdf7388f15cb8b50c09/Media/Fonts/UbuntuMono-RI.ttf
--------------------------------------------------------------------------------
/Media/Images/RedTode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TodePond/SandPond/6015bd3e4692ce7398408bdf7388f15cb8b50c09/Media/Images/RedTode.png
--------------------------------------------------------------------------------
/Media/Images/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TodePond/SandPond/6015bd3e4692ce7398408bdf7388f15cb8b50c09/Media/Images/favicon.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # SandPond
4 | SandPond is an engine for cells that follow spatial rules.
5 | It's heavily inspired by Dave Ackley's [T2 Tile Project](https://t2tile.com/).
6 |
7 | **For more info, check out the [SandPond Saga](https://youtube.com/c/TodePond) video series.**
8 |
9 | ## Rules
10 | Atoms follow simple rules, like this one:
11 | ```
12 | @ => _
13 | _ @
14 | ```
15 | The `@` represents the atom.
16 | The `_` represents an empty space.
17 | So... the rule makes the atom fall down if there's an empty space below it.
18 |
19 | ## Try it out
20 | Try it out at [www.sandpond.cool](http://www.sandpond.cool).
21 | Or [download](https://github.com/l2wilson94/SandPond/archive/main.zip) it and open `index.html` in a browser.
22 |
23 | ## Make your own element
24 | Elements are written in the [SpaceTode](https://github.com/l2wilson94/SpaceTode) language.
25 | To learn SpaceTode, check out the [documentation](https://l2wilson94.gitbook.io/spacetode).
26 | Or look at the examples in the [Elements](https://github.com/l2wilson94/SandPond/tree/main/Source/Elements) folder.
27 |
--------------------------------------------------------------------------------
/Source/Elements/Clear.js:
--------------------------------------------------------------------------------
1 | SpaceTode`
2 |
3 | element Eater {
4 | colour "brown"
5 | category "Clear"
6 | arg energy 10
7 |
8 | change D (self) => new Eater.Done(self.energy)
9 | change B (self) => new Eater.Bomb(self.energy)
10 | change E (self) => new Eater(self.energy)
11 | change Y (self) => new Eater(self.energy + 1)
12 | change N (self) => new Eater()
13 |
14 | given O (element) => element !== Empty && element !== Void && element !== Eater && element !== Eater.Done && element !== Eater.Bomb
15 |
16 | given e (self) => self.energy-- < 0
17 | e => D
18 |
19 | for(xyz.directions) {
20 | @O => YY
21 | }
22 |
23 | any(xyz.directions) {
24 | @_ => EE
25 | }
26 |
27 | element Done {
28 | colour "grey"
29 | emissive "black"
30 | arg energy 0
31 | @ => B
32 | }
33 |
34 | element Bomb {
35 | colour "lightgreen"
36 | emissive "green"
37 | arg energy 0
38 | all(xyz.others) {
39 | action @O => .N
40 | }
41 |
42 | @ => _
43 | }
44 | }
45 |
46 | element Clear {
47 | colour "brown"
48 | category "Clear"
49 | arg timer 0
50 |
51 | given C (element) => element === Clear
52 | change C (self) => new Clear(self.timer)
53 | change c (self) => {
54 | //self.timer++
55 | return new Clear(self.timer + 0.1)
56 | }
57 |
58 | given B (element) => element === Clear.Bomb
59 | change B (self) => new Clear.Bomb(self.timer)
60 | change b (atom) => new Clear.Bomb(atom.timer)
61 |
62 | keep T (self, atom) => self.timer = atom.timer + 20
63 |
64 | given D (element) => element === Clear.Done
65 | change D (self) => new Clear.Done(self.timer)
66 |
67 | // Other element
68 | given O (element) => element !== Void && element !== Clear && element !== Clear.Done && element !== Clear.Bomb
69 |
70 | all(xyz.directions) {
71 | //@B => .T
72 | @O => .c
73 | }
74 | any(xyz.directions) {
75 | @x => D.
76 | @D => D.
77 | }
78 |
79 | element Done {
80 | colour "grey"
81 | emissive "black"
82 | arg timer 0
83 | all(xyz.directions) @C => ..
84 | @ => B
85 | }
86 |
87 | element Bomb {
88 | colour "lightgreen"
89 | emissive "green"
90 | arg timer 0
91 | all(xyz.directions) action @C => @B
92 | all(xyz.others) {
93 | action @O => ._
94 | }
95 |
96 | given t (self) => self.timer-- < 0
97 | t => _
98 | }
99 |
100 | }
101 |
102 | element Clear2D {
103 | colour "brown"
104 | category "Clear"
105 | arg timer 0
106 |
107 | given C (element) => element === Clear2D
108 | change C (self) => new Clear2D(self.timer)
109 | change c (self) => {
110 | //self.timer++
111 | return new Clear2D(self.timer + 0.2)
112 | }
113 |
114 | given B (element) => element === Clear2D.Bomb
115 | change B (self) => new Clear2D.Bomb(self.timer)
116 | change b (atom) => new Clear2D.Bomb(atom.timer)
117 |
118 | keep T (self, atom) => self.timer = atom.timer + 20
119 |
120 | given D (element) => element === Clear2D.Done
121 | change D (self) => new Clear2D.Done(self.timer)
122 |
123 | // Other element
124 | given O (element) => element !== Void && element !== Clear2D && element !== Clear2D.Done && element !== Clear2D.Bomb
125 |
126 | all(xy.rotations) {
127 | //@B => .T
128 | @O => .c
129 | }
130 | any(xy.rotations) {
131 | @x => D.
132 | @D => D.
133 | }
134 |
135 | element Done {
136 | colour "grey"
137 | emissive "black"
138 | arg timer 0
139 | all(xyz.directions) @C => ..
140 | @ => B
141 | }
142 |
143 | element Bomb {
144 | colour "lightgreen"
145 | emissive "green"
146 | arg timer 0
147 | all(xy.rotations) action @C => @B
148 | all(xy.others) {
149 | action @O => ._
150 | }
151 |
152 | given t (self) => self.timer-- < 0
153 | t => _
154 | }
155 |
156 | }
157 |
158 | element Wipe {
159 | colour "brown"
160 | category "Clear"
161 | arg timer 4
162 |
163 | given W (element) => element === Wipe
164 | change W (self) => new Wipe(self.timer)
165 |
166 | given E (element) => element === Wipe.Edge
167 | change E (self) => new Wipe.Edge(self.timer)
168 | change e (self) => new Wipe.Edge(self.timer + 0.1)
169 |
170 | given D (element) => element === Wipe.Done
171 | change D (self) => new Wipe.Done(self.timer)
172 |
173 | given B (element) => element === Wipe.Bomb
174 | change B (self) => new Wipe.Bomb(self.timer)
175 |
176 | // Other element
177 | given O (element) => element !== Void && element !== Wipe && element !== Wipe.Done && element !== Wipe.Edge && element !== Wipe.Bomb
178 |
179 | @O => @W
180 | @x => E.
181 |
182 | element Edge {
183 | arg timer 0
184 | colour "brown"
185 |
186 | all(yz.rotations) {
187 | O => e
188 | @ .
189 | }
190 |
191 | all(yz.rotations) {
192 | x => .
193 | @ D
194 | }
195 |
196 | all(yz.rotations) {
197 | @ => D
198 | D .
199 | }
200 | }
201 |
202 | element Done {
203 | colour "grey"
204 | emissive "black"
205 | arg timer 0
206 |
207 | all(yz.rotations) {
208 | @ => .
209 | E .
210 |
211 | @ => .
212 | E .
213 |
214 | @ => .
215 | D .
216 | }
217 |
218 | .@ => @B
219 |
220 | x@ => .B
221 |
222 | }
223 |
224 | element Bomb {
225 | colour "lightgreen"
226 | emissive "green"
227 | arg timer 0
228 |
229 | all(xyz.directions) action @E => @B
230 | all(xyz.others) {
231 | action @O => ._
232 | }
233 |
234 | given t (self) => self.timer-- < 0
235 | t => _
236 | }
237 | }
238 |
239 | element Wipe2D {
240 | colour "brown"
241 | category "Clear"
242 | //default true
243 |
244 | symbol W Wipe2D
245 | symbol E Wipe2D.Edge
246 | symbol D Wipe2D.Done
247 | symbol B Wipe2D.Bomb
248 |
249 | // Other element
250 | given O (element) => element !== Void && element !== Wipe2D && element !== Wipe2D.Done && element !== Wipe2D.Edge && element !== Wipe2D.Bomb
251 |
252 | @O => @W
253 | @x => E.
254 |
255 | element Edge {
256 | colour "brown"
257 |
258 | all(y) {
259 | O => E
260 | @ .
261 | }
262 |
263 | all(y) {
264 | x => .
265 | @ D
266 | }
267 |
268 | all(y) {
269 | @ => D
270 | D .
271 | }
272 | }
273 |
274 | element Done {
275 | colour "grey"
276 | emissive "black"
277 |
278 | all(y) {
279 | @ => .
280 | E .
281 |
282 | @ => .
283 | E .
284 |
285 | @ => .
286 | D .
287 | }
288 |
289 | .@ => @B
290 |
291 | x@ => .B
292 |
293 | }
294 |
295 | element Bomb {
296 | colour "lightgreen"
297 | emissive "green"
298 | arg timer 4
299 |
300 | all(xy.others) {
301 | action @O => ._
302 | }
303 |
304 | given t (self) => self.timer-- < 0
305 | t => _
306 | }
307 | }
308 |
309 | `
--------------------------------------------------------------------------------
/Source/Elements/Explosive.js:
--------------------------------------------------------------------------------
1 |
2 | SpaceTode`
3 |
4 |
5 |
6 | element Explosion any(xyz.directions) {
7 | colour "darkorange"
8 | emissive "red"
9 | opacity 0.3
10 | category "Explosive"
11 | prop temperature HOT
12 | prop state EFFECT
13 | arg timer 20
14 | arg explosionColour "orange"
15 |
16 | given i (self) => self.init !== true
17 | keep c (self, space) => {
18 | if (self.explosionColour === "blue") {
19 | self.colour = {r:0, g:0, b:255}
20 | self.emissive = {r:0, g:0, b:128}
21 | SPACE.updateAppearance(space)
22 | }
23 | else if (self.explosionColour === "red") {
24 | self.colour = {r:255, g:0, b:0}
25 | self.emissive = {r:128, g:0, b:0}
26 | SPACE.updateAppearance(space)
27 | }
28 | else if (self.explosionColour === "green") {
29 | self.colour = {r:0, g:255, b:0}
30 | self.emissive = {r:0, g:128, b:0}
31 | SPACE.updateAppearance(space)
32 | }
33 | else if (self.explosionColour === "yellow") {
34 | self.colour = {r:255, g:200, b:0}
35 | self.emissive = {r:128, g:100, b:0}
36 | SPACE.updateAppearance(space)
37 | }
38 | self.init = true
39 | }
40 | action i => c
41 |
42 | keep t (self) => self.timer--
43 | action @ => t
44 |
45 | given t (self) => self.timer <= 0
46 | t => _
47 |
48 | change E (self, selfElement) => {
49 | const e = new selfElement(self.timer, self.explosionColour)
50 | e.colour = self.colour
51 | e.emissive = self.emissive
52 | return e
53 | }
54 | @. => .E
55 |
56 | }
57 |
58 | element GunPowder {
59 | category "Explosive"
60 | colour "grey"
61 | emissive "brown"
62 | prop state SOLID
63 | prop temperature ROOM
64 | prop states () => ({
65 | [HOT]: Explosion,
66 | })
67 |
68 | mimic(Temperature)
69 | mimic(Powder)
70 |
71 | }
72 |
73 | element Firework {
74 | colour "grey"
75 | emissive "black"
76 | category "Explosive"
77 | prop state SOLID
78 | prop temperature WARM
79 | arg fuel 25
80 |
81 | change E () => {
82 | const rando = Math.floor(Math.random() * 5)
83 | if (rando < 1) return new Explosion(20, "orange")
84 | if (rando < 2) return new Explosion(20, "blue")
85 | if (rando < 3) return new Explosion(20, "red")
86 | if (rando < 4) return new Explosion(20, "yellow")
87 | if (rando < 5) return new Explosion(20, "green")
88 | }
89 |
90 | given t (self) => self.fuel <= 0
91 | t => E
92 |
93 | change F (self) => {
94 | self.fuel--
95 | return new Fire()
96 | }
97 |
98 | _ => @
99 | @ F
100 |
101 | @ => E
102 | }
103 |
104 | // TODO: implement direction and make it an arg
105 | // needs quite a lot of work - need firstclass directions in the SpaceTode language, similar to symmetries
106 | element Meteor {
107 | colour "#781a00"
108 | emissive "black"
109 | category "Explosive"
110 | prop state SOLID
111 | prop temperature WARM
112 | data stuck false
113 | prop states () => ({
114 | [COLD]: Rock,
115 | [CHILLY]: Rock,
116 | [COOL]: [Rock, 0.4],
117 | })
118 |
119 | mimic(Temperature)
120 |
121 | change F () => new Fire()
122 | action {
123 | _ => F
124 | @ .
125 | }
126 |
127 | given F (element) => element === Fire
128 | @ => _
129 | F @
130 |
131 | given E (element) => element === Explosion
132 | @ => _
133 | E .
134 |
135 | given D (element) => element.state > SOLID
136 | select D (atom) => atom
137 | change D (selected) => selected
138 | @ => D
139 | D @
140 |
141 | given M (element, selfElement, atom) => element === selfElement || atom.stuck === false
142 | @ => .
143 | M .
144 |
145 | change E () => new Explosion(35)
146 | @ => E
147 |
148 | mimic(Sticky)
149 | }
150 |
151 | `
152 |
--------------------------------------------------------------------------------
/Source/Elements/Food.js:
--------------------------------------------------------------------------------
1 | // Food Flags
2 | const PLANT = Flag(1)
3 | const MEAT = Flag(2)
4 | const WATER = Flag(3)
5 | const BUG = Flag(4)
6 | const DAIRY = Flag(5)
7 |
8 | SpaceTode`
9 |
10 | element Carrot {
11 | colour "rgb(200, 80, 0)"
12 | category "Life"
13 | prop state SOLID
14 | prop temperature ROOM
15 | prop food PLANT
16 |
17 | change i () => new Carrot.Leaf(Math.random(), false)
18 | @ => i
19 |
20 | given L (self, element, atom) => element === Carrot.Leaf && atom.id === self.id
21 | change L (self) => new Carrot.Leaf(self.id)
22 |
23 | given P (self, element, atom) => element === Carrot.Part && atom.id === self.id
24 | change P (self) => new Carrot.Part(self.id)
25 |
26 | given 1 (element) => element.state > SOLID
27 | select 1 (atom) => atom
28 | change 1 (selected) => selected
29 |
30 | given 2 (element) => element.state > SOLID
31 | select 2 (atom) => atom
32 | change 2 (selected) => selected
33 |
34 | given 3 (element) => element.state > SOLID
35 | select 3 (atom) => atom
36 | change 3 (selected) => selected
37 |
38 | given n (element) => element.state === undefined || element.state <= SOLID
39 |
40 | element Leaf {
41 | colour "green"
42 | arg id
43 | arg grown true
44 | prop state SOLID
45 | prop temperature ROOM
46 | prop food PLANT
47 |
48 | any(xz.rotations) {
49 | origin g
50 | given g (self) => !self.grown
51 | keep g (self) => self.grown = true
52 | g => g
53 | _ P
54 | _ P
55 |
56 | g => _
57 |
58 | P 1
59 | P => P
60 | @ P
61 | 1 @
62 |
63 | P 2
64 | P => 1
65 | @12 @PP
66 | n .
67 |
68 | @PP => 123
69 | 123 @PP
70 |
71 | @PP => 1P2
72 | 1n P.
73 | 2 @
74 |
75 | PP@ => 1@2
76 | 1n P.
77 | 2 P
78 |
79 | @PP => P12
80 | 1 n P .
81 | 2 @
82 |
83 | PP@ => @12
84 | 1 n P .
85 | 2 P
86 | }
87 |
88 | all(xyz.directions) @PP => ...
89 | mimic(Powder)
90 |
91 | }
92 |
93 | element Part {
94 | colour "rgb(200, 80, 0)"
95 | arg id
96 | prop state SOLID
97 | prop temperature ROOM
98 | prop food PLANT
99 |
100 | any(xz.rotations) {
101 | L 1
102 | @ => L
103 | P @
104 | 1 P
105 |
106 | L 1
107 | @ => 2
108 | P12 P@L
109 |
110 | L 1
111 | P => 2
112 | @12 @PL
113 | n .
114 |
115 | L@P => 123
116 | 123 L@P
117 |
118 | LP@ => 123
119 | 123 LP@
120 | }
121 |
122 | all(xyz.directions) {
123 | P@L => ...
124 | @PL => ...
125 | }
126 | mimic(Powder)
127 | }
128 | }
129 |
130 | element Plant {
131 | colour "green"
132 | emissive "green"
133 | category "Life"
134 | prop state SOLID
135 | prop temperature ROOM
136 | prop food PLANT
137 | prop states () => ({
138 | [HOT]: [Charcoal, 0.12]
139 | })
140 |
141 | mimic(Powder)
142 | mimic(Temperature)
143 |
144 | maybe(1/50) {
145 |
146 | any(xyz.directions) {
147 | @ => @
148 | _ $
149 | }
150 | }
151 |
152 | }
153 |
154 | element Cheese {
155 | colour "#fcc203"
156 | emissive "#fc4e03"
157 | category "Life"
158 | prop state SOLID
159 | prop temperature ROOM
160 | prop food DAIRY
161 | prop stickiness 0.5
162 | prop states () => ({
163 | [WARM]: Fondue,
164 | [HOT]: Fondue,
165 | })
166 |
167 | // Make holes
168 | given i (self) => self.init !== true
169 | keep i (self, origin) => {
170 | if (Math.random() < 0.3) return SPACE.setAtom(origin, new Empty(), Empty)
171 | self.init = true
172 | }
173 | action i => i
174 |
175 | symbol S Cheese.Smell
176 |
177 | data age 0
178 | data smelly false
179 | given E (self, element) => {
180 | if (self.smelly) return element === Empty
181 | self.age++
182 | if (self.age < 20) return false
183 | self.smelly = true
184 | return false
185 | }
186 | maybe(0.2) any(xyz.directions) action @E => @S
187 |
188 | mimic(Temperature)
189 | mimic(Sticky)
190 | mimic(Solid)
191 |
192 | element Smell {
193 | colour "#fcc203"
194 | emissive "#fc4e03"
195 | opacity 0.1
196 | prop state GAS
197 | prop temperature ROOM
198 | prop smell STINK
199 | mimic(Smell)
200 | }
201 | }
202 |
203 | element Fondue {
204 | colour "#fcc203"
205 | emissive "#fc4e03"
206 | category "Life"
207 | opacity 0.3
208 | prop state SOLID
209 | prop temperature BODY
210 | prop food DAIRY
211 | prop states () => ({
212 | [COLD]: Cheese,
213 | [CHILLY]: Cheese,
214 | [COOL]: Cheese,
215 | })
216 |
217 | symbol S Fondue.Smell
218 | maybe(0.003) any(xyz.directions) action @_ => @S
219 | mimic(Temperature)
220 | mimic(Goo)
221 |
222 | element Smell {
223 | colour "#fcc203"
224 | emissive "#fc4e03"
225 | opacity 0.1
226 | prop state GAS
227 | prop temperature ROOM
228 | prop smell STINK
229 | mimic(Smell)
230 | }
231 | }
232 |
233 | `
234 |
--------------------------------------------------------------------------------
/Source/Elements/Globals.js:
--------------------------------------------------------------------------------
1 | SpaceTode`
2 |
3 | origin @
4 | change @ (self) => self
5 |
6 | given ! (origin, self) => origin.atom !== self
7 |
8 | symbol _ Empty
9 | symbol x Void
10 | symbol * Void
11 |
12 | given . (element) => element !== Void
13 | keep .
14 |
15 | given # (element) => element !== Empty && element !== Void
16 | keep #
17 |
18 | given $ (element, Self) => element === Self
19 | change $ (Self) => new Self()
20 |
21 | given ? (element) => element !== Void
22 | select ? (atom) => atom
23 | change ? (selected) => selected
24 |
25 | check < (self) => self.continue === false
26 | check > (self) => self.continue === true
27 | keep < (self) => self.continue = false
28 | keep > (self) => self.continue = true
29 |
30 | `
31 |
--------------------------------------------------------------------------------
/Source/Elements/Life.js:
--------------------------------------------------------------------------------
1 | SpaceTode`
2 |
3 | element Fish {
4 | prop state SOLID
5 | prop temperature BODY
6 | prop food MEAT
7 | prop diet PLANT
8 | data stuck false
9 | colour "rgb(255, 100, 0)"
10 | arg id
11 | category "Life"
12 |
13 | {
14 | given i (self) => self.id === undefined
15 | keep i (self) => self.id = Math.random()
16 | action i => i
17 | }
18 |
19 | {
20 | change T (self) => new Fish.Tail(self.id)
21 | @ => T
22 | _ @
23 |
24 | any(xyz.rotations) {
25 |
26 | change t (self, Self) => new Self.Tail(self.id, true)
27 | symbol W Water
28 | @W => t@
29 |
30 | given s (element, self, atom) => element === Fish.Tail && atom.id === self.id
31 | select s (atom) => atom
32 | change s (selected) => selected
33 | @s => s@
34 |
35 | s _
36 | @_ => .s
37 |
38 | }
39 | }
40 |
41 | element Tail {
42 | colour "rgb(255, 100, 0)"
43 | arg id
44 | arg holdsWater false
45 |
46 | given H (element, self, atom) => element === Fish && self.id === atom.id
47 | all(xyz.directions) @H => ..
48 |
49 | change w (self) => self.holdsWater? new Water() : new Empty()
50 | @ => w
51 | }
52 | }
53 |
54 | element Smeller {
55 | prop state SOLID
56 | prop temperature BODY
57 | data target undefined
58 | data interest 0
59 |
60 | given i (self) => self.target === undefined
61 | keep i (self) => {
62 | self.target = [0, 0, 0]
63 | }
64 | i => i
65 |
66 |
67 | given D (element) => element.state > SOLID
68 | select D (atom) => atom
69 | change D (selected) => selected
70 | @ => D
71 | D @
72 |
73 | given P (element) => element === Pheromone
74 | select P (atom) => atom.target
75 | keep P (self, selected) => {
76 | if (selected === undefined) return
77 | self.target = [...selected]
78 | self.interest = 1.0
79 | }
80 | action for(xz.directions) @P => P.
81 |
82 | given I (self) => self.interest > 0
83 | keep I (self) => self.interest -= 0.01
84 | action I => I
85 |
86 | given M (element, x, z, self) => {
87 | if (self.interest <= 0) return false
88 | if (element.state <= SOLID) return false
89 | if (x > 0 && self.target[0] < 0) return true
90 | if (x < 0 && self.target[0] > 0) return true
91 | if (z > 0 && self.target[2] < 0) return true
92 | if (z < 0 && self.target[2] > 0) return true
93 | return false
94 | }
95 | select M (atom, x, z) => [atom, x, z]
96 | change M (selected) => {
97 | const [atom, x, z] = selected
98 | if (atom.target !== undefined) {
99 | atom.target[0] -= x
100 | atom.target[2] -= z
101 | }
102 | return atom
103 | }
104 | change m (x, z, self) => {
105 | self.target[0] += x
106 | self.target[2] += z
107 | return self
108 | }
109 | for(xz.directions) {
110 | @M => Mm
111 |
112 | M => m
113 | @ M
114 | }
115 |
116 | maybe(0.15) any(xz.directions) @D => D@
117 |
118 | }
119 |
120 | element Mouse {
121 | category "Life"
122 | colour "white"
123 | emissive "grey"
124 | prop state SOLID
125 | prop temperature BODY
126 | prop food MEAT
127 | prop diet PLANT | DAIRY
128 | prop pheromone LOVE | STINK
129 | data stuck false
130 | data target undefined
131 | data interest 0.0
132 | arg energy 0.85
133 | arg id
134 |
135 | given T (self, element, atom, Self) => element === Self.Tail && atom.id == self.id
136 | change T (self, Self) => new Self.Tail(self.id)
137 |
138 | change M (self, Self) => new Self(self.id)
139 |
140 | //======//
141 | // Init //
142 | //======//
143 | given i (self) => self.id === undefined
144 | change i (self) => {
145 | self.id = Math.random()
146 | self.target = [0, 0, 0]
147 | return self
148 | }
149 | i => i
150 |
151 | //=======//
152 | // Scent //
153 | //=======//
154 | origin p
155 | given p (self) => self.energy > 0.9
156 | change p (self) => new Pheromone(0.94, self)
157 | given ~ (element) => element === Empty || false
158 |
159 | //=======//
160 | // Breed //
161 | //=======//
162 | given B (element, atom, self, Self) => (element === Self || element === Self.Tail) && (atom.id !== self.id) && self.energy > 0.9
163 | keep B (atom) => atom.energy -= 0.0
164 | change b (self, Self) => {
165 | self.energy -= 0.6
166 | return new Self(0.6)
167 | }
168 | given , (element) => element === Empty || element.state === GAS
169 | for(xyz.directions) {
170 | action p~ => .p
171 | @B, => BBb
172 | @,B => BbB
173 | }
174 |
175 | //=====//
176 | // Eat //
177 | //=====//
178 | given F (Self, element) => Flag.has(element.food, Self.diet)
179 | change e (self) => {
180 | self.energy += 0.05
181 | if (self.energy > 1) self.energy = 1
182 | return new Empty()
183 | }
184 |
185 | for(xyz.directions) {
186 | T@F => eT@
187 | }
188 |
189 | for(xyz.rotations) {
190 | F => @
191 | T@ eT
192 | }
193 |
194 | //=======//
195 | // Sniff //
196 | //=======//
197 | mimic(Sniffer)
198 |
199 | //======//
200 | // Fall //
201 | //======//
202 | given D (element) => element.state > SOLID
203 | select D (atom) => atom
204 | change D (selected) => selected
205 |
206 | given d (element) => element.state > SOLID
207 | select d (atom) => atom
208 | change d (selected) => selected
209 | T => D
210 | @ T
211 | D @
212 |
213 | @ => T
214 | T @
215 |
216 | for(xz.directions) {
217 | @T => Dd
218 | Dd @T
219 |
220 | @T => Dd
221 | Dd @T
222 | }
223 |
224 | for(xz.directions) {
225 | T => D
226 | @D .T
227 | }
228 |
229 | //==============//
230 | // Follow Smell //
231 | //==============//
232 | given s (self) => Math.random() > self.energy + 0.1
233 | given f (element, x, z, self) => {
234 | if (self.interest <= 0) return false
235 | if (element.state <= SOLID) return false
236 | if (x > 0 && self.target[0] < 0) return true
237 | if (x < 0 && self.target[0] > 0) return true
238 | if (z > 0 && self.target[2] < 0) return true
239 | if (z < 0 && self.target[2] > 0) return true
240 | return false
241 | }
242 | select f (atom, x, z) => [atom, x, z]
243 | change f (selected, self) => {
244 | const [atom, x, z] = selected
245 | if (atom.target !== undefined) {
246 | atom.target[0] -= x
247 | atom.target[2] -= z
248 | }
249 | return atom
250 | }
251 |
252 | change F (self, x, z) => {
253 | self.target[0] += x
254 | self.target[2] += z
255 | return self
256 | }
257 |
258 | //======//
259 | // Move //
260 | //======//
261 | given h (self) => self.energy > 0.9
262 | maybe(0.75) h => .
263 |
264 | given m (element) => element.state > SOLID
265 | select m (atom) => atom
266 | change m (selected, self) => {
267 | self.energy -= 0.0005
268 | if (self.energy < 0) self.energy = 0
269 | return selected
270 | }
271 |
272 | for(xz.directions) {
273 | T@f => fTF
274 |
275 | df => TF
276 | T@ df
277 | }
278 |
279 | for(xz) pov(top) {
280 | f F
281 | T@ => .f
282 | }
283 |
284 | action {
285 |
286 | s => .
287 |
288 | for(xz.directions) {
289 | T@m => mT@
290 |
291 | dm => T@
292 | T@ dm
293 | }
294 |
295 | for(xz) pov(top) {
296 | m @
297 | T@ => .m
298 | }
299 | }
300 |
301 | ! => .
302 |
303 | //===========//
304 | // Grow Tail //
305 | //===========//
306 | given g (element, self) => element === Empty && self.energy > 0.5
307 | change g (self, Self) => {
308 | self.energy -= 0.5
309 | return new Self.Tail(self.id)
310 | }
311 | for(xyz.directions) @T => ..
312 | any(xyz.directions) @g => .g
313 |
314 | //==================//
315 | // Act Without Tail //
316 | //==================//
317 | @ => D
318 | D @
319 |
320 | action {
321 | s => .
322 | for(xz.directions) @m => m@
323 | }
324 |
325 | // TODO: more behaviours here? eg: smell following
326 |
327 | ! => .
328 |
329 | element Tail {
330 | prop state SOLID
331 | prop temperature BODY
332 | prop food MEAT
333 | prop diet PLANT | DAIRY
334 | data stuck false
335 | colour "pink"
336 | emissive "rgb(255, 64, 128)"
337 | arg id
338 |
339 | given ^ (element, atom, self) => element === SpaceTode.global.elements.Mouse
340 | for(xyz.directions) @^ => ..
341 | mimic(Powder)
342 | }
343 | }
344 |
345 | element Rabbit {
346 | category "Life"
347 | colour "white"
348 | emissive "grey"
349 | prop state SOLID
350 | prop temperature BODY
351 | prop food MEAT
352 | prop diet PLANT
353 | prop pheromone LOVE
354 | data stuck false
355 | data target undefined
356 | data interest 0.0
357 | data energy 0.6
358 |
359 | //================//
360 | // Global Symbols //
361 | //================//
362 | // Rabbit
363 | given R (element, atom, self) => element === Rabbit && atom.id === self.id
364 | change R (self) => new Rabbit(self.id)
365 |
366 | // Rabbit Ears
367 | given E (element, atom, self) => element === Rabbit.Ear && atom.id === self.id
368 | change E (self) => new Rabbit.Ear(self.id)
369 |
370 | // Stretch
371 | given r (element, atom, self) => element === Rabbit.Stretch && atom.id === self.id
372 | change r (self) => new Rabbit.Stretch(self.id)
373 |
374 | // Stretch Ears
375 | given e (element, atom, self) => element === Rabbit.Stretch.Ear && atom.id === self.id
376 | change e (self) => new Rabbit.Stretch.Ear(self.id)
377 |
378 | //======//
379 | // Init //
380 | //======//
381 | {
382 | arg id
383 | given i (self) => self.id === undefined
384 | change i (self) => {
385 | self.id = Math.random()
386 | self.target = [0, 0, 0]
387 | return self
388 | }
389 | i => i
390 | }
391 |
392 | //===========//
393 | // Grow Ears //
394 | //===========//
395 | {
396 | data grown false
397 | origin g
398 | given g (self) => !self.grown
399 | keep g (self) => self.grown = true
400 | for(xz.swaps) {
401 | _ _ E E
402 | _g_ => EgE
403 | }
404 | }
405 |
406 | //======//
407 | // Land //
408 | //======//
409 | {
410 |
411 | given L (element) => element.state <= SOLID
412 | keep l (self) => {
413 | self.jumpRemaining = 5
414 | self.jumpDirection = undefined
415 | }
416 |
417 | maybe(1/25) {
418 | action {
419 | @ => l
420 | L .
421 | }
422 |
423 | for(xz.directions) action {
424 | E@ => .l
425 | L .
426 | }
427 |
428 | for(xz.directions) action {
429 | @E => l.
430 | L .
431 | }
432 | }
433 | }
434 |
435 | //======//
436 | // Move //
437 | //======//
438 | {
439 | // If I'm currently stretching, catch up with (or wait for) the stretch
440 | given g (element, atom, self) => element === Rabbit.Stretch && atom.id === self.id && atom.grown
441 | for(xz.rotations) {
442 | g => @
443 | @ _
444 |
445 | r .
446 | @ => >
447 | }
448 | }
449 |
450 | action @ => <
451 | action {
452 |
453 | // Check I have all my body parts (:
454 | all(xz.rotations) action {
455 | E E . .
456 | E@E => .>.
457 | }
458 | < => >
459 |
460 | // Start a new stretch
461 | given n (element, self, transformationNumber) => {
462 | if (self.jumpDirection === undefined) {
463 | self.jumpDirection = transformationNumber
464 | }
465 | else if (transformationNumber == self.jumpDirection) {
466 |
467 | }
468 | else return false
469 | self.jumpRemaining--
470 | if (element === Empty && self.jumpRemaining >= 0) {
471 | return true
472 | }
473 | return false
474 | }
475 | change n (self, transformationNumber) => {
476 | let t = transformationNumber + 1
477 | if (t > 3) t -= 4
478 | //self.jumpRemaining--
479 | //self.jumpRemaining = 5
480 | return new Rabbit.Stretch(self.id, t)
481 | }
482 | for(xz.rotations) {
483 | n n
484 | @ => <
485 | }
486 | }
487 | < => .
488 |
489 | //======//
490 | // Fall //
491 | //======//
492 | data jumpRemaining 0
493 | data jumpDirection
494 | {
495 | given 1 (element) => element.state > SOLID
496 | select 1 (atom) => atom
497 | change 1 (selected) => selected
498 |
499 | given 2 (element) => element.state > SOLID
500 | select 2 (atom) => atom
501 | change 2 (selected) => selected
502 |
503 | given 3 (element) => element.state > SOLID
504 | select 3 (atom) => atom
505 | change 3 (selected) => selected
506 |
507 | origin f
508 | given f (self) => self.jumpRemaining <= 0
509 |
510 | for(xz.rotations) {
511 | E E => 1 3
512 | EfE E2E
513 | 123 E@E
514 | }
515 | }
516 |
517 | //=========//
518 | // Injured //
519 | //=========//
520 | {
521 | given m (element, atom, self) => (element === Rabbit.Stretch.Ear || element === Rabbit.Ear) && atom.id === self.id
522 | for(xz.rotations) {
523 | m m . .
524 | m@m => ...
525 |
526 | r .
527 | @ => .
528 |
529 | @e => ..
530 | }
531 |
532 | // Fall
533 | given I (element) => element.state > SOLID
534 | select I (atom) => atom
535 | change I (selected) => selected
536 | @ => I
537 | I @
538 |
539 | // Move
540 | any(xz.rotations) {
541 | @I => I@
542 | }
543 | }
544 |
545 | //==============//
546 | // Sub-Elements //
547 | //==============//
548 | element Ear {
549 | //category "Life"
550 | colour "white"
551 | emissive "grey"
552 | prop state SOLID
553 | prop temperature BODY
554 | data stuck false
555 | arg id
556 | arg part
557 |
558 | // Catch up with my stretch
559 | given g (element, atom, self) => element === Rabbit.Stretch.Ear && atom.id === self.id
560 | for(xz.rotations) {
561 | g @
562 | @ => _
563 | }
564 | }
565 |
566 | element Stretch {
567 | colour "white"
568 | emissive "grey"
569 | //colour "pink"
570 | //emissive "purple"
571 | //opacity 0.5
572 | prop state SOLID
573 | prop temperature BODY
574 | prop food MEAT
575 | data stuck false
576 | arg id
577 | arg transformationNumber
578 |
579 | {
580 | data grown false
581 | origin g
582 | given g (self, transformationNumber) => !self.grown && self.transformationNumber === transformationNumber
583 | keep g (self) => self.grown = true
584 | for(xz.rotations) {
585 | _ _ e e
586 | _g_ => ege
587 | }
588 |
589 | origin G
590 | given G (self) => self.grown
591 | given m (element, atom, self) => (element === Rabbit.Stretch.Ear || element === Rabbit.Ear) && atom.id === self.id
592 | for(xz.rotations) {
593 | m m . .
594 | mGm => ...
595 | }
596 |
597 | @ => _
598 | }
599 |
600 | element Ear {
601 | colour "white"
602 | emissive "grey"
603 | //colour "pink"
604 | //emissive "purple"
605 | //opacity 0.5
606 | prop state SOLID
607 | prop temperature BODY
608 | data stuck false
609 | arg id
610 | arg part
611 |
612 | }
613 |
614 | }
615 |
616 | }
617 |
618 | element Ant {
619 | colour "grey"
620 | emissive "black"
621 | category "Life"
622 | prop state SOLID
623 | prop temperature BODY
624 | prop food Flag.and(BUG, MEAT)
625 |
626 | given M (element) => element.state > LIQUID && element.state !== EFFECT
627 | select M (atom) => atom
628 | change M (selected) => selected
629 | given m (element) => element.state > LIQUID && element.state !== EFFECT
630 |
631 | given S (element, selfElement) => element.state <= SOLID && element !== selfElement
632 | any(xyz.rotations) {
633 | @M => M@
634 | S .
635 |
636 | mM => .@
637 | @S M.
638 | }
639 |
640 | all(xyz.directions) {
641 | @S => ..
642 | }
643 |
644 | given A (element, selfElement) => element === selfElement
645 | any(xz.rotations) {
646 | @M => M@
647 | A .
648 | }
649 |
650 | given F (element) => element.state > LIQUID
651 | select F (atom) => atom
652 | change F (selected) => selected
653 | @ => F
654 | F @
655 |
656 | }
657 |
658 | element OldRabbit {
659 | colour "white"
660 | emissive "grey"
661 | //category "Life"
662 | prop state SOLID
663 | prop temperature BODY
664 | prop food MEAT
665 |
666 | data id
667 |
668 | element Part {
669 | colour "white"
670 | emissive "grey"
671 | arg id
672 | prop state SOLID
673 | prop temperature BODY
674 | prop food MEAT
675 |
676 | given R (element, atom, self) => element === OldRabbit && atom.id === self.id
677 | @R => ..
678 | R@ => ..
679 |
680 | @ => .
681 | R .
682 |
683 | @ => .
684 | R .
685 |
686 | @ => _
687 | }
688 |
689 | // Init ID
690 | given i (self) => self.id === undefined
691 | keep i (self) => self.id = Math.random()
692 | i => i
693 |
694 | // Grow body
695 | change P (self, atom) => {
696 | const part = new OldRabbit.Part(self.id)
697 | part.colour = self.colour
698 | part.emissive = self.emissive
699 | return part
700 | }
701 | @_ => .P
702 | _@ => P.
703 |
704 | _ => P
705 | @ .
706 |
707 | _ => P
708 | @ .
709 |
710 | // Die because can't grow
711 | given n (element, atom, self) => element !== OldRabbit.Part || atom.id !== self.id
712 | n => .
713 | @ _
714 | _ .
715 |
716 | n => .
717 | @ _
718 | _ .
719 |
720 | @n => _.
721 | _ .
722 |
723 | n@ => ._
724 | _ .
725 |
726 | // Fall down
727 | given P (element, atom, self) => element === OldRabbit.Part && atom.id === self.id
728 | P P _ _
729 | P@P => P_P
730 | ___ P@P
731 |
732 | any(xyz.directions) {
733 |
734 | // Eat
735 | given C (element) => element === Carrot.Leaf || element === Carrot.Part
736 | keep C (atom) => atom.eaten = true
737 | @.C => ..C
738 | @C => .C
739 |
740 | // Breed
741 | given R (element, atom, self) => (element === OldRabbit || element === OldRabbit.Part) && self.id !== atom.id
742 | change B () => new OldRabbit()
743 | maybe(1/15) {
744 | @_R => .B.
745 | @R_ => ..B
746 | _@R => B..
747 | _@.R => B...
748 | }
749 | }
750 |
751 | // Move
752 | maybe(1/2) pov(right) any(z) {
753 | @_ => _@
754 | }
755 |
756 | any(x) {
757 | P_P_ _P_P
758 | P@P_ => _P@P
759 | }
760 |
761 | }
762 |
763 | `
--------------------------------------------------------------------------------
/Source/Elements/Old/TodeSplat2/Bondo.js:
--------------------------------------------------------------------------------
1 | TodeSplat`
2 |
3 | element BigSandSeed {
4 | colour "pink"
5 | emissive "purple"
6 | //precise true
7 | //pour false
8 | category "sandbox"
9 | //default true
10 |
11 | data id -1
12 |
13 | input i extends _ ({self}) => self.id = Math.random()
14 | output P ({space, self}) => {
15 | const atom = ATOM.make(BigSandPart)
16 | atom.id = self.id
17 | SPACE.setAtom(space, atom)
18 | }
19 |
20 | rule {
21 | @ => P
22 | i P
23 | }
24 |
25 | }
26 |
27 | element BigSandPart {
28 | colour "pink"
29 | emissive "purple"
30 | hidden true
31 |
32 | data id -1
33 |
34 | input P extends # ({space, self}) => space.atom.element == BigSandPart && self.id == space.atom.id
35 | input T extends # ({space, self}) => space.atom.element == BigSandTrail && self.id == space.atom.id
36 | input t ({space, args, self}) => {
37 | if (space && space.atom && space.atom.element == BigSandTrail && self.id == space.atom.id) {
38 | args.success = true
39 | args.trailSpace = space
40 | }
41 | return true
42 | }
43 |
44 | output m ({self, space, trailSpace}) => {
45 | if (space == trailSpace) {
46 | SPACE.setAtom(space, self)
47 | }
48 | }
49 |
50 | output T ({self, space}) => {
51 | const atom = ATOM.make(BigSandTrail)
52 | atom.id = self.id
53 | SPACE.setAtom(space, atom)
54 | }
55 |
56 | input S extends # ({space, self}) => {
57 | if (space.atom.element == BigSandPart && space.atom.id == self.id) return false
58 | if (space.atom.element == BigSandTrail && space.atom.id == self.id) return false
59 | return true
60 | }
61 |
62 | rule XZ { @t => ?? => _m }
63 | rule {
64 | @ => _
65 | T @
66 | }
67 |
68 | rule {
69 | @ => T
70 | _ @
71 | }
72 |
73 | rule xz {
74 | @_ => __
75 | P_ P@
76 | }
77 |
78 | rule xz {
79 | @_ => TT
80 | S_ S@
81 | }
82 |
83 | }
84 |
85 | element BigSandTrail {
86 | colour "lightblue"
87 | emissive "blue"
88 | hidden true
89 |
90 | data id -1
91 |
92 | }
93 |
94 | element TallSand {
95 |
96 | colour "pink"
97 | emissive "purple"
98 | //precise true
99 | //pour false
100 | category "sandbox"
101 |
102 | input e extends _ ({args}) => args.id = Math.random()
103 |
104 | output p ({space, id}) => {
105 | const atom = ATOM.make(FloaterBondoPart)
106 | atom.id = id
107 | atom.subid = Math.random()
108 | SPACE.setAtom(space, atom)
109 | }
110 |
111 | rule xyz { @e => pp }
112 |
113 | }
114 |
115 | element FloaterBondoPart {
116 | colour "pink"
117 | emissive "purple"
118 | hidden true
119 |
120 | input F extends # ({space}) => space.atom.element == FloaterBondoPart
121 | input B extends F ({space, self, args}) => {
122 | if (space.atom.id == self.id) {
123 | args.buddy = space.atom
124 | return true
125 | }
126 | }
127 |
128 | input T extends # ({space, self}) => {
129 | return space.atom.element == FloaterBondoTrail && space.atom.id == self.id && space.atom.subid != self.subid
130 | }
131 |
132 | input t ({space, args, self}) => {
133 | if (space && space.atom && space.atom.element == FloaterBondoTrail && space.atom.id == self.id && space.atom.subid != self.subid) {
134 | args.success = true
135 | args.trailSpace = space
136 | }
137 | return true
138 | }
139 |
140 | output s ({space, trailSpace, self}) => {
141 | if (space == trailSpace) {
142 | SPACE.setAtom(trailSpace, self)
143 | }
144 | }
145 |
146 | output T ({space, self}) => {
147 | const atom = ATOM.make(FloaterBondoTrail)
148 | atom.id = self.id
149 | atom.subid = self.subid
150 | SPACE.setAtom(space, atom)
151 | }
152 |
153 | output B ({space, buddy}) => SPACE.setAtom(space, buddy)
154 |
155 | rule XZ {
156 | @t => ?? => Ts
157 | }
158 |
159 | rule {
160 | @ ? T
161 | t => ? => s
162 | }
163 |
164 | rule xz {
165 | B@ BT
166 | _ => @
167 | }
168 |
169 | rule {
170 | B B
171 | @ => T
172 | _ @
173 | }
174 |
175 | rule xz {
176 | B B
177 | @_ => T@
178 | #_ #_
179 | }
180 |
181 | }
182 |
183 | element FloaterBondoTrail {
184 | colour "lightblue"
185 | emissive "blue"
186 | hidden true
187 |
188 | input t ({space, args, self}) => {
189 | if (space && space.atom && space.atom.element == FloaterBondoPart && space.atom.id == self.id && space.atom.subid == self.subid) {
190 | args.success = true
191 | }
192 | return true
193 | }
194 |
195 |
196 | rule XYZ {
197 | @B => !! => _.
198 | }
199 |
200 | }
201 |
202 |
203 |
204 | `
--------------------------------------------------------------------------------
/Source/Elements/Old/TodeSplat2/Clear.js:
--------------------------------------------------------------------------------
1 | TodeSplat`
2 |
3 | element Clear {
4 |
5 | colour "brown"
6 | emissive "brown"
7 | precise true
8 | category "clear"
9 |
10 | input t ({space, args}) => {
11 | if (space && space.atom && space.atom.element == ClearDone) {
12 | args.success = true
13 | }
14 | return true
15 | }
16 |
17 | input e ({space, args}) => {
18 | if (!space) {
19 | args.success = true
20 | }
21 | return true
22 | }
23 |
24 | input D extends # ({space}) => space.atom.element == ClearDone
25 | output D ({space}) => SPACE.setAtom(space, ATOM.make(ClearDone))
26 | output c ({space}) => { if (space) SPACE.setAtom(space, ATOM.make(Clear)) }
27 |
28 | rule XYZ { @t => ?? => D. }
29 | rule XY { @e => ?? => D. }
30 | rule XYZ { @- => .c }
31 |
32 | }
33 |
34 | element ClearDone {
35 |
36 | colour "blue"
37 | emissive "blue"
38 | hidden true
39 |
40 | input c ({space, args}) => {
41 | if (space && space.atom && space.atom.element == Clear) {
42 | args.success = false
43 | }
44 | return true
45 | }
46 |
47 | output B ({space}) => SPACE.setAtom(space, ATOM.make(ClearBomb))
48 |
49 | rule XYZ { @c => !! => B. }
50 |
51 | }
52 |
53 | element ClearBomb {
54 | colour "black"
55 | emissive "black"
56 | hidden true
57 |
58 | output e ({space}) => {
59 | if (space) SPACE.setAtom(space, undefined)
60 | }
61 |
62 | rule XYZ { @- => ee }
63 | }
64 |
65 | `
--------------------------------------------------------------------------------
/Source/Elements/Old/TodeSplat2/EdgeClear.js:
--------------------------------------------------------------------------------
1 | TodeSplat`
2 |
3 | element EdgeClear {
4 |
5 | colour "brown"
6 | emissive "brown"
7 | precise true
8 | family "EdgeClear"
9 | category "clear"
10 |
11 | output E ({space}) => SPACE.setAtom(space, ATOM.make(EdgeClearEdge))
12 | input N extends . ({space}) => {
13 | if (!space.atom) return true
14 | if (space.atom.element.family != "EdgeClear") return true
15 | }
16 |
17 | rule { @NN => @@@ }
18 | rule { @N => @@ }
19 | rule { @x => Ex }
20 | }
21 |
22 | element EdgeClearEdge {
23 | colour "blue"
24 | emissive "darkblue"
25 | hidden true
26 | family "EdgeClear"
27 |
28 | input E ({space}) => {
29 | if (!space) return true
30 | if (space.atom && space.atom.element.family == "EdgeClear") return true
31 | }
32 |
33 | output B ({space}) => SPACE.setAtom(space, ATOM.make(EdgeClearBomb))
34 |
35 | rule Y {
36 | @ => B
37 | E .
38 | }
39 |
40 | rule Y {
41 | @ => @
42 | . @
43 | }
44 |
45 | }
46 |
47 | element EdgeClearBomb {
48 | colour "grey"
49 | emissive "black"
50 | hidden true
51 | family "EdgeClear"
52 |
53 | input N extends . ({space}) => {
54 | if (!space.atom) return true
55 | if (space.atom.element == EdgeClear) return true
56 | if (space.atom.element.family != "EdgeClear") return true
57 | }
58 |
59 | input B ({space}) => space && space.atom && space.atom.element == EdgeClearBomb
60 | input D ({space}) => space && space.atom && space.atom.element == EdgeClearDone
61 | output D ({space}) => SPACE.setAtom(space, ATOM.make(EdgeClearDone))
62 |
63 |
64 | rule { NN@ => @@@ }
65 | rule { N@ => @@ }
66 |
67 | rule xy { D@ => DD }
68 | rule XY { B@ => BD }
69 |
70 |
71 | }
72 |
73 | element EdgeClearDone {
74 | colour "lightgreen"
75 | emissive "green"
76 | hidden true
77 | family "EdgeClear"
78 |
79 | input b ({space, args}) => {
80 | if (!space) return true
81 | if (!space.atom) return true
82 | if (space.atom.element == EdgeClearBomb) args.success = false
83 | return true
84 | }
85 |
86 | rule XY { b@ => !! => b_ }
87 | }
88 | `
--------------------------------------------------------------------------------
/Source/Elements/Old/TodeSplat2/FatFly.js:
--------------------------------------------------------------------------------
1 | TodeSplat`
2 |
3 |
4 | element FatFly {
5 |
6 | colour "royalblue"
7 | emissive "darkblue"
8 | precise true
9 | pour false
10 | category "life"
11 |
12 | input e ({space, args}) => {
13 | if (space && !space.atom) args.success = true
14 | return true
15 | }
16 |
17 | input L extends # ({space, args}) => {
18 | if (space.atom.element == FatFlyLimb) return true
19 | }
20 |
21 | output L ({space, args}) => {
22 | SPACE.setAtom(space, ATOM.make(FatFlyLimb))
23 | }
24 |
25 | output l ({space}) => {
26 | if (space && !space.atom) {
27 | SPACE.setAtom(space, ATOM.make(FatFlyLimb))
28 | }
29 | }
30 |
31 | // Grow (or regrow) limbs
32 | rule XYZ {
33 | @e => ?? => @l
34 | e ? l
35 | }
36 |
37 | rule xyz { @L_ => L@_ }
38 |
39 | }
40 |
41 | element FatFlyLimb {
42 | hidden true
43 | colour "royalblue"
44 | emissive "darkblue"
45 |
46 | input f ({space, args}) => {
47 | if (!space || !space.atom) return true
48 | if (space.atom.element == FatFly) args.success = true
49 | return true
50 | }
51 |
52 | rule XYZ {
53 | @f => ?? => ..
54 | f ? .
55 | }
56 |
57 | rule { @ => _ }
58 |
59 | }
60 |
61 |
62 |
63 |
64 | `
--------------------------------------------------------------------------------
/Source/Elements/Old/TodeSplat2/Pheromone.js:
--------------------------------------------------------------------------------
1 | TodeSplat`
2 |
3 |
4 | element Pheromone {
5 |
6 | colour "pink"
7 | emissive "purple"
8 | opacity 0.3
9 |
10 | hidden true
11 | data distance 0
12 |
13 | output m ({space, self}) => {
14 | SPACE.setAtom(space, undefined)
15 | self.distance++
16 | }
17 |
18 | rule 0.001 { @ => _ }
19 | rule xyz { @_ => m@ }
20 |
21 | }
22 |
23 |
24 |
25 |
26 | `
--------------------------------------------------------------------------------
/Source/Elements/Old/TodeSplat2/Platformer.js:
--------------------------------------------------------------------------------
1 | TodeSplat`
2 |
3 | element Platformer {
4 |
5 | colour "red"
6 | emissive "darkred"
7 | precise true
8 | pour false
9 | category "player"
10 |
11 | input r () => Keyboard.ArrowRight
12 | input l () => Keyboard.ArrowLeft
13 | input f () => Keyboard.ArrowUp
14 | input b () => Keyboard.ArrowDown
15 |
16 | rule {
17 | @ => _
18 | _ @
19 | }
20 |
21 | rule { @_ => rr => _@ }
22 | rule { _@ => ll => @_ }
23 |
24 | rule side { @_ => bb => _@ }
25 | rule side { _@ => ff => @_ }
26 |
27 | rule {
28 | _ => r => @
29 | @# rr _#
30 | }
31 |
32 | rule {
33 | _ => l => @
34 | #@ ll #_
35 | }
36 |
37 | rule side {
38 | _ => b => @
39 | @# bb _#
40 | }
41 |
42 | rule side {
43 | _ => f => @
44 | #@ ff #_
45 | }
46 |
47 | }
48 |
49 |
50 | `
--------------------------------------------------------------------------------
/Source/Elements/Old/TodeSplat2/PlayerSnake.js:
--------------------------------------------------------------------------------
1 | let snakerDirection = "right"
2 |
3 | on.keydown(e => {
4 | if (snakerDirection == "right") {
5 | //if (e.key == "ArrowLeft") return snakerDirection = "forward"
6 | //if (e.key == "ArrowRight") return snakerDirection = "back"
7 | if (e.key == "ArrowUp") return snakerDirection = "up"
8 | if (e.key == "ArrowDown") return snakerDirection = "down"
9 | }
10 | if (snakerDirection == "left") {
11 | //if (e.key == "ArrowLeft") return snakerDirection = "back"
12 | //if (e.key == "ArrowRight") return snakerDirection = "forward"
13 | if (e.key == "ArrowUp") return snakerDirection = "up"
14 | if (e.key == "ArrowDown") return snakerDirection = "down"
15 | }
16 | /*if (snakerDirection == "forward") {
17 | if (e.key == "ArrowLeft") return snakerDirection = "left"
18 | if (e.key == "ArrowRight") return snakerDirection = "right"
19 | if (e.key == "ArrowUp") return snakerDirection = "up"
20 | if (e.key == "ArrowDown") return snakerDirection = "down"
21 | }*/
22 | /*if (snakerDirection == "back") {
23 | if (e.key == "ArrowLeft") return snakerDirection = "right"
24 | if (e.key == "ArrowRight") return snakerDirection = "left"
25 | if (e.key == "ArrowUp") return snakerDirection = "up"
26 | if (e.key == "ArrowDown") return snakerDirection = "down"
27 | }*/
28 | if (snakerDirection == "up") {
29 | if (e.key == "ArrowLeft") return snakerDirection = "left"
30 | if (e.key == "ArrowRight") return snakerDirection = "right"
31 | //if (e.key == "ArrowUp") return snakerDirection = "back"
32 | //if (e.key == "ArrowDown") return snakerDirection = "forward"
33 | }
34 | if (snakerDirection == "down") {
35 | if (e.key == "ArrowLeft") return snakerDirection = "left"
36 | if (e.key == "ArrowRight") return snakerDirection = "right"
37 | //if (e.key == "ArrowUp") return snakerDirection = "forward"
38 | //if (e.key == "ArrowDown") return snakerDirection = "back"
39 | }
40 | })
41 |
42 | TodeSplat`
43 |
44 | element Snaker {
45 |
46 | colour "green"
47 | emissive "darkgreen"
48 | precise true
49 | pour false
50 | category "player"
51 |
52 | data score 0
53 |
54 | //===========//
55 | // FUNCTIONS //
56 | //===========//
57 | // Is it the next trail?
58 | input t ({space, args, self, tests}) => {
59 | if (tests.length == 0) tests[0] = ({isTrail}) => isTrail
60 |
61 | if (!space || !space.atom) return true
62 | if (space.atom.element != PlayerSnakeTrail) return true
63 |
64 | const trail = space.atom
65 | if (trail.score == self.score + 1) {
66 | args.isTrail = true
67 | args.trail = space.atom
68 | args.trailSpace = space
69 | }
70 | return true
71 | }
72 |
73 | // Place the trail that I ate
74 | output t ({space, self, trail}) => {
75 | SPACE.setAtom(space, trail)
76 | trail.score = self.score
77 | }
78 |
79 | // Place me in the place the trail was
80 | output o ({space, self, trailSpace}) => {
81 | if (space != trailSpace) return
82 | SPACE.setAtom(space, self)
83 | }
84 |
85 | // Create new trail
86 | output T ({space, self}) => {
87 | const trail = ATOM.make(PlayerSnakeTrail, {score: self.score})
88 | SPACE.setAtom(space, trail)
89 | }
90 |
91 | // Am I waiting for my trail to be caught up on?
92 | input * ({space, args, self, tests}) => {
93 | if (tests.length == 0) tests[0] = ({isWaiting}) => isWaiting
94 |
95 | if (!space || !space.atom) return true
96 | if (space.atom.element != PlayerSnakeTrail) return true
97 | const trail = space.atom
98 |
99 | if (trail.score == self.score) {
100 | args.isWaiting = true
101 | }
102 |
103 | return true
104 | }
105 |
106 | // Are there higher scoring snakes around me?
107 | input ^ ({space, self, tests, args}) => {
108 |
109 | if (tests.length == 0) tests[0] = ({isObeying}) => isObeying
110 |
111 | if (!space || !space.atom) return true
112 | if (space.atom.element != Snaker && space.atom.element != PlayerSnakeTrail) return true
113 |
114 | if (space.atom.score == self.score + 1) {
115 | args.isObeying = true
116 | }
117 | return true
118 | }
119 |
120 | // Is it Res?
121 | input F extends # ({space}) => space.atom.element.isFood
122 |
123 | // Make a new leader
124 | output l ({space, self}) => {
125 | const leader = ATOM.make(Snaker, {score: self.score + 1})
126 | self.leader = false
127 | SPACE.setAtom(space, leader)
128 | }
129 |
130 | //=======//
131 | // RULES //
132 | //=======//
133 | // Wait for snakes to catch up
134 | rule XYZ { @* => .. }
135 |
136 | // Move up trail
137 | rule XYZ { @t => to }
138 |
139 | // If there is a higher score snake/trail nearby, do nothing
140 | rule XYZ { @^ => .. }
141 |
142 | // Otherwise, assume I am the leader:
143 | input r () => snakerDirection == "right"
144 | rule { @F => rr => @l }
145 | rule { @_ => rr => T@ }
146 |
147 | input l () => snakerDirection == "left"
148 | rule { F@ => ll => l@ }
149 | rule { _@ => ll => @T }
150 |
151 | input f () => snakerDirection == "forward"
152 | rule side { F@ => ff => l@ }
153 | rule side { _@ => ff => @T }
154 |
155 | input b () => snakerDirection == "back"
156 | rule side { @F => bb => @l }
157 | rule side { @_ => bb => T@ }
158 |
159 | input u () => snakerDirection == "up"
160 | rule {
161 | F => u => l
162 | @ u @
163 | }
164 | rule {
165 | _ => u => @
166 | @ u T
167 | }
168 |
169 | input d () => snakerDirection == "down"
170 | rule {
171 | @ => d => @
172 | F d l
173 | }
174 | rule {
175 | @ => d => T
176 | _ d @
177 | }
178 |
179 | }
180 |
181 | element PlayerSnakeTrail {
182 |
183 | colour "blue"
184 | emissive "darkblue"
185 |
186 | // Can I die?
187 | input * ({space, self}) => {
188 | if (!space || !space.atom) return true
189 | if (space.atom.element != Snaker && space.atom.element != PlayerSnakeTrail) return true
190 | if (space.atom.score != self.score - 1) return true
191 | return false
192 | }
193 | rule XYZ { @* => _. }
194 |
195 | }
196 |
197 | `
--------------------------------------------------------------------------------
/Source/Elements/Old/TodeSplat2/Rope.js:
--------------------------------------------------------------------------------
1 | TodeSplat`
2 |
3 | element Rope {
4 |
5 | colour "brown"
6 | precise true
7 | category "sandbox"
8 | pour false
9 |
10 | data remaining 50
11 |
12 | input r ({self}) => {
13 | if (!self.id) self.id = Math.random()
14 | return self.remaining > 0
15 | }
16 | input f ({self}) => self.remaining <= 0
17 |
18 | output P ({space, self}) => {
19 | self.remaining--
20 | const atom = ATOM.make(RopePart)
21 | atom.id = self.id
22 | SPACE.setAtom(space, atom)
23 | }
24 |
25 | rule { @f => _* }
26 | rule { @_ => P@ }
27 | rule { @x => Px }
28 | }
29 |
30 | element RopePart {
31 | colour "#3D1600"
32 | hidden true
33 |
34 | input P extends # ({space, self}) => space.atom.element == RopePart && space.atom.id == self.id
35 |
36 | input N ({space, self}) => {
37 | if (!space) return true
38 | if (!space.atom) return true
39 | if (space.atom.element == RopePart) {
40 | if (self.id != space.atom.id) return true
41 | }
42 | }
43 |
44 | input h ({space, args}) => {
45 | if (space && space.atom && (space.atom.element == Fire || space.atom.element == Lava)) args.success = true
46 | return true
47 | }
48 |
49 | output F ({space}) => {
50 | SPACE.setAtom(space, ATOM.make(Fire))
51 | }
52 |
53 | rule XYZ {
54 | h => ? => .
55 | @h ?? F.
56 | }
57 |
58 | rule {
59 | NNN NNN
60 | @ => _
61 | _ @
62 | }
63 |
64 | rule x {
65 | PNN => PNN
66 | _@N @_N
67 | N N
68 | }
69 |
70 | rule x {
71 | _@ => @_
72 | _PP _PP
73 | }
74 |
75 | rule x {
76 | PP_ => PP_
77 | @_ _@
78 | }
79 |
80 | rule x {
81 | P => P
82 | P@P P_P
83 | _ @
84 | }
85 |
86 | /*rule x {
87 | @ => @
88 | PP P_
89 | _ P
90 | }*/
91 |
92 | /*rule {
93 | NN NN
94 | @N => _N
95 | _PN @PN
96 | }*/
97 |
98 | /*rule {
99 | P P
100 | @ => T
101 | _ @
102 | }*/
103 |
104 | }
105 |
106 | element RopeTrail {
107 | hidden true
108 | colour "black"
109 |
110 | }
111 |
112 | element Plank {
113 | colour "brown"
114 |
115 | precise true
116 | category "sandbox"
117 | pour false
118 |
119 | output p ({space, id}) => {
120 | if (!space) return
121 | const atom = ATOM.make(BrickPart, {id})
122 | SPACE.setAtom(space, atom)
123 | }
124 |
125 | input i ({args, id}) => {
126 | if (!id) {
127 | args.id = Math.random()
128 | }
129 | else args.id = id
130 | return true
131 | }
132 |
133 | rule XZ top {
134 | @i* => ppp
135 | *** ppp
136 | }
137 |
138 | }
139 |
140 | element BrickPart {
141 | colour "saddlebrown"
142 | hidden true
143 |
144 | data id -1
145 |
146 | input p ({space, args, self}) => {
147 | if (space && space.atom && space.atom.element == BrickPart) {
148 | if (space.atom.id == self.id) args.success = true
149 | }
150 | return true
151 | }
152 |
153 | input n ({space, self}) => {
154 | if (!space) return true
155 | if (!space.atom) return true
156 | if (space.atom.element == BrickPart) {
157 | if (self.id != space.atom.id) return true
158 | }
159 | }
160 |
161 | rule XZ {
162 | n n n n
163 | @ => _
164 | _ @
165 | }
166 |
167 | }
168 |
169 | element Stretch {
170 | colour "blue"
171 | hidden true
172 | }
173 |
174 | `
--------------------------------------------------------------------------------
/Source/Elements/Old/TodeSplat2/SleepyFly.js:
--------------------------------------------------------------------------------
1 | TodeSplat`
2 |
3 |
4 | element SleepyFly {
5 |
6 | colour "royalblue"
7 | emissive "darkblue"
8 | precise true
9 | //hidden true
10 | pour false
11 | category "life"
12 |
13 | data sleeping false
14 |
15 | input s ({self}) => self.sleeping
16 | input a ({self}) => !self.sleeping
17 |
18 | output s ({self}) => self.sleeping = true
19 | output a ({self}) => self.sleeping = false
20 |
21 | // Go to sleep
22 | rule 0.001 { @a => @s }
23 |
24 | // Wake up
25 | rule 0.01 { @s => @a }
26 |
27 | // Move if awake
28 | rule xyz { @_ => aa => _@ }
29 |
30 | // Sleep if asleep
31 | rule {
32 | @ => s => _
33 | _ s @
34 | }
35 |
36 | }
37 |
38 |
39 |
40 |
41 | `
--------------------------------------------------------------------------------
/Source/Elements/Old/TodeSplat2/Snake.js:
--------------------------------------------------------------------------------
1 | TodeSplat`
2 |
3 |
4 | // NOT WORKING AT THE MOMENT BECause I removed "tests"
5 |
6 | element Snake {
7 |
8 | colour "green"
9 | emissive "darkgreen"
10 | precise true
11 | pour false
12 | category "life"
13 | hidden true
14 |
15 | data score 0
16 |
17 | //===========//
18 | // FUNCTIONS //
19 | //===========//
20 | // Is it the next trail?
21 | input t ({space, args, self, tests}) => {
22 | if (tests.length == 0) tests[0] = ({isTrail}) => isTrail
23 |
24 | if (!space || !space.atom) return true
25 | if (space.atom.element != SnakeTrail) return true
26 |
27 | const trail = space.atom
28 | if (trail.score == self.score + 1) {
29 | args.isTrail = true
30 | args.trail = space.atom
31 | args.trailSpace = space
32 | }
33 | return true
34 | }
35 |
36 | // Place the trail that I ate
37 | output t ({space, self, trail}) => {
38 | SPACE.setAtom(space, trail)
39 | trail.score = self.score
40 | }
41 |
42 | // Place me in the place the trail was
43 | output o ({space, self, trailSpace}) => {
44 | if (space != trailSpace) return
45 | SPACE.setAtom(space, self)
46 | }
47 |
48 | // Create new trail
49 | output T ({space, self}) => {
50 | const trail = ATOM.make(SnakeTrail, {score: self.score})
51 | SPACE.setAtom(space, trail)
52 | }
53 |
54 | // Am I waiting for my trail to be caught up on?
55 | input * ({space, args, self, tests}) => {
56 | if (tests.length == 0) tests[0] = ({isWaiting}) => isWaiting
57 |
58 | if (!space || !space.atom) return true
59 | if (space.atom.element != SnakeTrail) return true
60 | const trail = space.atom
61 |
62 | if (trail.score == self.score) {
63 | args.isWaiting = true
64 | }
65 |
66 | return true
67 | }
68 |
69 | // Are there higher scoring snakes around me?
70 | input ^ ({space, self, tests, args}) => {
71 |
72 | if (tests.length == 0) tests[0] = ({isObeying}) => isObeying
73 |
74 | if (!space || !space.atom) return true
75 | if (space.atom.element != Snake && space.atom.element != SnakeTrail) return true
76 |
77 | if (space.atom.score == self.score + 1) {
78 | args.isObeying = true
79 | }
80 | return true
81 | }
82 |
83 | // Is it Food?
84 | input R extends # ({space}) => space.atom.element.isFood
85 |
86 | // Make a new leader
87 | output l ({space, self}) => {
88 | const leader = ATOM.make(Snake, {score: self.score + 1})
89 | self.leader = false
90 | SPACE.setAtom(space, leader)
91 | }
92 |
93 | //=======//
94 | // RULES //
95 | //=======//
96 | // Wait for snakes to catch up
97 | rule XYZ { @* => .. }
98 |
99 | // Move up trail
100 | rule XYZ { @t => to }
101 |
102 | // If there is a higher score snake/trail nearby, do nothing
103 | rule XYZ { @^ => .. }
104 |
105 | // Otherwise, assume I am the leader:
106 | // Eat Res
107 | rule xyz { @R => @l }
108 |
109 | // Move into empty space
110 | rule xyz { @_ => T@ }
111 |
112 | }
113 |
114 | element SnakeTrail {
115 |
116 | colour "blue"
117 | emissive "darkblue"
118 |
119 | // Can I die?
120 | input * ({space, self}) => {
121 | if (!space || !space.atom) return true
122 | if (space.atom.element != Snake && space.atom.element != SnakeTrail) return true
123 | if (space.atom.score != self.score - 1) return true
124 | }
125 | rule XYZ { @* => _. }
126 |
127 | }
128 |
129 | `
--------------------------------------------------------------------------------
/Source/Elements/Old/TodeSplat2/SpaceShip.js:
--------------------------------------------------------------------------------
1 | TodeSplat`
2 |
3 | element SpaceShip {
4 |
5 | colour "pink"
6 | emissive "purple"
7 | precise true
8 | pour false
9 | category "player"
10 |
11 | input r () => Keyboard.ArrowRight
12 | input l () => Keyboard.ArrowLeft
13 | input f () => Keyboard.ArrowUp
14 | input b () => Keyboard.ArrowDown
15 | input d () => Keyboard[" "]
16 |
17 | output S ({space}) => SPACE.setAtom(space, ATOM.make(Sand))
18 |
19 | action {
20 | @ => @ => @
21 | d _ S
22 | }
23 |
24 | rule { @r => @_ => _@ }
25 | rule { l@ => _@ => @_ }
26 |
27 | rule top {
28 | b => _ => @
29 | @ @ _
30 | }
31 |
32 | rule top {
33 | @ => @ => _
34 | f _ @
35 | }
36 |
37 | }
38 |
39 |
40 |
41 |
42 | `
--------------------------------------------------------------------------------
/Source/Elements/Old/TodeSplat3/Explosive.js:
--------------------------------------------------------------------------------
1 | let fireworkColour = 0
2 |
3 | TodeSplat`
4 |
5 | element Spark {
6 |
7 | colour "lightyellow"
8 | emissive "orange"
9 | category "Explosive"
10 | state "effect"
11 | ignites true
12 | floor true
13 | given s (element, self) => element == self.element
14 | keep s
15 |
16 | rule 0.2 { @ => _}
17 | rule xyz { @s => _s }
18 | rule xyz 0.4 { @_ => @@ }
19 |
20 |
21 | }
22 |
23 | element BlueSpark {
24 |
25 | floor true
26 | colour "lightblue"
27 | emissive "lightblue"
28 | category "Explosive"
29 | state "effect"
30 | ignites true
31 | ruleset Spark
32 |
33 | }
34 |
35 | element Explosion {
36 |
37 | floor true
38 | colour "lightyellow"
39 | emissive "orange"
40 | category "Explosive"
41 | state "effect"
42 | ignites true
43 | data timer 20
44 | isHot true
45 |
46 | keep t (self, space) => self.timer--
47 | given d (self) => self.timer <= 0
48 | change E (self) => new self.element({timer: self.timer})
49 |
50 | action { @ => t }
51 | rule { @d => _. }
52 |
53 | rule xyz { @. => @E }
54 |
55 | }
56 |
57 | element RedExplosion {
58 |
59 | floor true
60 | colour "red"
61 | emissive "darkred"
62 | category "Explosive"
63 | state "effect"
64 | ignites true
65 | data timer 20
66 | isHot true
67 |
68 | ruleset Explosion
69 |
70 | }
71 |
72 | element BlueExplosion {
73 |
74 | floor true
75 | colour "blue"
76 | emissive "darkblue"
77 | category "Explosive"
78 | state "effect"
79 | ignites true
80 | data timer 20
81 | isHot true
82 |
83 | ruleset Explosion
84 |
85 | }
86 |
87 | element GunPowder {
88 |
89 | colour "grey"
90 | emissive "brown"
91 | category "Explosive"
92 | state "solid"
93 |
94 | given H (element) => element && element.ignites
95 | change E (self) => new Explosion()
96 |
97 | rule xyz { @H => EE }
98 | ruleset Powder
99 |
100 | }
101 |
102 | element Lightning {
103 | colour "yellow"
104 | emissive "orange"
105 | category "Explosive"
106 | state "effect"
107 | ignites true
108 | precise true
109 | pour false
110 |
111 | change S () => new Spark()
112 | action xz 0.3 { @_ => @S }
113 |
114 | rule {
115 | @ => @
116 | _ @
117 | }
118 |
119 | given N (space, element) => !space || element != Lightning
120 | keep N
121 | change F () => new LightningFlash()
122 | rule {
123 | @ => F
124 | N N
125 | }
126 |
127 | }
128 |
129 | element LightningFlash {
130 | colour "lightblue"
131 | emissive "lightblue"
132 | hidden true
133 | state "effect"
134 | ignites true
135 |
136 | change S () => new BlueSpark()
137 | action xz 0.5 { @_ => @S }
138 |
139 | change B () => new LightningBang
140 | rule {
141 | _ => _
142 | @ B
143 | }
144 | }
145 |
146 | element LightningBang {
147 | colour "white"
148 | emissive "white"
149 | hidden true
150 | state "effect"
151 | ignites true
152 |
153 | given F (element) => element == LightningFlash
154 |
155 | rule {
156 | @ => _
157 | F @
158 | }
159 |
160 | rule {
161 | @ => _
162 | }
163 |
164 | }
165 |
166 | element Firework {
167 |
168 | colour "grey"
169 | emissive "black"
170 | precise true
171 | pour false
172 | floor true
173 | category "Explosive"
174 | state "solid"
175 |
176 | data timer 25
177 |
178 | change E (self) => {
179 | if (self.timer > 0) return self
180 | fireworkColour++
181 | if (fireworkColour >= 3) fireworkColour = 0
182 | if (fireworkColour == 0) return new Explosion()
183 | else if (fireworkColour == 1) return new RedExplosion()
184 | else if (fireworkColour == 2) return new BlueExplosion()
185 | }
186 |
187 | change F (self) => {
188 | self.timer--
189 | return new Fire()
190 | }
191 |
192 | rule {
193 | _ => E
194 | @ F
195 | }
196 |
197 | }
198 |
199 | element Rocket {
200 |
201 | colour "grey"
202 | emissive "black"
203 | precise true
204 | pour false
205 | category "Explosive"
206 | state "solid"
207 |
208 | ruleset Solid
209 |
210 | given I (element) => element && element.ignites
211 | change F () => new Firework()
212 | rule xyz { @I => F. }
213 |
214 | }
215 |
216 | `
217 |
--------------------------------------------------------------------------------
/Source/Elements/Old/TodeSplat3/Globals.js:
--------------------------------------------------------------------------------
1 | TodeSplat`
2 |
3 | given . (space) => space
4 | keep .
5 |
6 | given @ (self, atom) => self == atom
7 | change @ (self) => self
8 |
9 | given # (atom) => atom
10 | keep #
11 |
12 | given _ (space, atom) => space && !atom
13 | change _ () => undefined
14 |
15 | given x (space) => !space
16 | keep x
17 |
18 |
19 |
20 | `
--------------------------------------------------------------------------------
/Source/Elements/Old/TodeSplat3/Life.js:
--------------------------------------------------------------------------------
1 | TodeSplat`
2 |
3 | element Food {
4 |
5 | colour "brown"
6 | emissive "brown"
7 | category "Life"
8 | isFood true
9 | state "solid"
10 |
11 | ruleset Powder
12 |
13 | }
14 |
15 | element FloatyFood {
16 |
17 | colour "brown"
18 | emissive "brown"
19 | category "Life"
20 | isFood true
21 |
22 | state "solid"
23 |
24 | rule xyz { @_ => _@ }
25 |
26 | }
27 |
28 | element Fly {
29 |
30 | colour "royalblue"
31 | emissive "darkblue"
32 | precise true
33 | pour false
34 | category "Life"
35 | state "solid"
36 |
37 | given F (element) => element && element.isFood
38 | rule 0.0005 { @ => _ }
39 | rule xyz 0.05 { @F => @@ }
40 | rule xyz { @F => @_ }
41 | rule xyz { @_ => _@ }
42 |
43 | }
44 |
45 | element Ant {
46 |
47 | colour "grey"
48 | emissive "black"
49 | precise true
50 | pour false
51 | category "Life"
52 | state "solid"
53 |
54 | given F (element) => element && element.isFood
55 |
56 | rule 0.0005 { @ => _ }
57 |
58 | ruleset Solid
59 |
60 | rule xyz 0.05 { @F => @@ }
61 | rule xyz { @F => _@ }
62 |
63 | rule xz {
64 | _ => @
65 | @. _.
66 | }
67 |
68 | }
69 |
70 | element MountainMaker {
71 |
72 | colour "lightblue"
73 | emissive "red"
74 | category "Life"
75 | state "effect"
76 |
77 | change S () => new Sand()
78 |
79 | rule 0.4 {
80 | @ => S
81 | }
82 |
83 | rule xyz {
84 | @._ => ..@
85 | }
86 |
87 | }
88 |
89 | element SandLeaver {
90 |
91 | colour "brown"
92 | emissive "brown"
93 | category "Life"
94 | state "solid"
95 | precise true
96 | pour false
97 |
98 | change F () => new Sand()
99 | rule xyz 0.45 { @_ => @F }
100 |
101 | rule {
102 | @ => _
103 | _ @
104 | }
105 |
106 | rule xz {
107 | _ => @
108 | @ _
109 | }
110 |
111 | }
112 |
113 | element FoodLeaver {
114 |
115 | colour "yellow"
116 | emissive "orange"
117 | category "Life"
118 | state "solid"
119 | precise true
120 | pour false
121 |
122 | change F () => new Food()
123 | rule xyz 0.45 { @_ => @F }
124 |
125 | rule {
126 | @ => _
127 | _ @
128 | }
129 |
130 | rule xz {
131 | _ => @
132 | @ _
133 | }
134 |
135 | }
136 | element Cycler {
137 |
138 | colour "grey"
139 | emissive "black"
140 | category "Life"
141 | state "solid"
142 |
143 | rule {
144 | x => x
145 | _@ @_
146 | }
147 |
148 | rule {
149 | _ @
150 | @x => _x
151 | }
152 |
153 | rule {
154 | @_ => _@
155 | x x
156 | }
157 |
158 | rule {
159 | @ => _
160 | _ @
161 | }
162 |
163 | }
164 |
165 | element Plant {
166 | colour "green"
167 | category "Life"
168 | state "solid"
169 |
170 | // Burn
171 | given H (element) => element && element.ignites
172 | keep H
173 | change F () => new BurningPlant()
174 | rule xyz { @H => FH }
175 |
176 | // Gravity
177 | ruleset Powder
178 |
179 | // Grow
180 | rule xz 0.05 { @_ => @@ }
181 |
182 | }
183 |
184 | element BurningPlant {
185 | colour "green"
186 | category "Life"
187 | state "solid"
188 | hidden true
189 | ignites true
190 |
191 | rule 0.03 { @ => _ }
192 |
193 | change F () => new Fire()
194 | rule {
195 | _ => F
196 | @ @
197 | }
198 | ruleset Plant
199 |
200 | }
201 |
202 | element Herbivore {
203 | colour "blue"
204 | emissive "darkblue"
205 | category "Life"
206 | state "solid"
207 | precise true
208 | pour false
209 |
210 | // Die
211 | rule 0.002 { @ => _ }
212 |
213 | // Gravity
214 | ruleset Powder
215 |
216 | // Reproduce
217 | given P (element) => element == Plant || (element && element.isFood)
218 | rule xyz 0.05 { @P => @@ }
219 |
220 | // Eat
221 | rule xyz { @P => @_ }
222 |
223 | // Move
224 | rule xz 0.5 { @_ => _@ }
225 | }
226 |
227 | element Fish {
228 | colour "rgb(255, 100, 0)"
229 | category "Life"
230 | precise true
231 | pour false
232 | state "solid"
233 |
234 | given W (element) => element == Water
235 | select W (atom) => atom
236 | change W (selected) => selected
237 | rule xyz { @W => W@ }
238 |
239 | rule {
240 | @ => .
241 | W .
242 | }
243 | ruleset Solid
244 |
245 | rule 0.05 xz {
246 | _ => @
247 |
248 | @ _
249 | }
250 |
251 | }
252 |
253 | element Giraffe {
254 | colour "rgb(128, 128, 0)"
255 | emissive "rgb(255, 128, 0)"
256 | state "solid"
257 | precise true
258 | pour false
259 | category "Life"
260 |
261 | data level 0
262 |
263 | given d (self) => self.level > 0
264 | given d (atom, element, self) => element != Giraffe || !atom || atom.level != self.level - 1
265 | rule {
266 | @ => _
267 | d .
268 | }
269 |
270 | ruleset Solid
271 |
272 | given e (space, atom) => space && !atom
273 | given e (self) => self.level < 10
274 | change G (self) => new Giraffe({level: self.level + 1})
275 | action {
276 | e => G
277 | @ .
278 | }
279 | rule xz 0.05 { @_ => _@ }
280 |
281 |
282 | }
283 |
284 | element StretchyGiraffe {
285 | colour "rgb(128, 128, 0)"
286 | emissive "rgb(255, 128, 0)"
287 | state "solid"
288 | precise true
289 | pour false
290 | category "Life"
291 |
292 | data level 0
293 |
294 | given d (self) => self.level == 0
295 | given d (element) => !element || element.state != "solid"
296 | given d (space) => space
297 | select d (atom) => atom
298 | change d (selected) => selected
299 | rule {
300 | @ => d
301 | d @
302 | }
303 |
304 | given e (space, atom) => space && !atom
305 | given e (self) => self.level < 7
306 | change G (self) => new StretchyGiraffe({level: self.level + 1})
307 | action {
308 | e => G
309 | @ .
310 | }
311 |
312 | given G (element) => element == StretchyGiraffe
313 | change T (self) => new GiraffeTrail({level: self.level + 1})
314 | rule xz {
315 | G_ .T
316 | @d => d@
317 | }
318 |
319 | given T (element, atom, self) => element && element == GiraffeTrail && atom.level == self.level
320 | rule xz {
321 | G_ .T
322 | @T => _@
323 | }
324 |
325 | rule xz {
326 | _ .
327 | @T => _@
328 | }
329 |
330 | }
331 |
332 | element GiraffeTrail {
333 | colour "grey"
334 | emissive "black"
335 | hidden true
336 | }
337 |
338 | `
--------------------------------------------------------------------------------
/Source/Elements/Old/TodeSplat3/People.js:
--------------------------------------------------------------------------------
1 | TodeSplat`
2 |
3 | element LukeWilson {
4 |
5 | colour "red"
6 | emissive "darkred"
7 | category "People"
8 | //default true
9 | precise true
10 | pour false
11 |
12 | state "solid"
13 | data id -1
14 |
15 | given i (self) => self.id == -1
16 | keep i (self) => self.id = Math.random()
17 | action { i => i}
18 |
19 | // Hatch when fallen
20 | change B (self) => new LukeBody({id: self.id})
21 | change L (self) => new LukeLeg({id: self.id})
22 | change H (self) => new LukeHair({id: self.id})
23 | change A (self) => new LukeArm({id: self.id})
24 | change F (self) => new LukeFace({id: self.id})
25 |
26 |
27 | given H (element, atom, self) => atom && element == LukeHair && atom.id == self.id
28 | given F (element, atom, self) => atom && element == LukeFace && atom.id == self.id
29 | given A (element, atom, self) => atom && element == LukeArm && atom.id == self.id
30 | given L (element, atom, self) => atom && element == LukeLeg && atom.id == self.id
31 | given B (element, atom, self) => atom && element == LukeBody && atom.id == self.id
32 | action {
33 | ___ HHH
34 | ___ => HFH
35 | __@__ AB@BA
36 | _ _ L L
37 | }
38 |
39 | // Unsquish :)
40 | action {
41 | HHH ...
42 | HFH ...
43 | AB@B_ => ....A
44 | L L . .
45 | }
46 |
47 | given l (element, atom, self) => atom && (element != LukeLeg || atom.id != self.id)
48 | rule {
49 | HHH HHH
50 | _HFH_ AB@BA
51 | AB@B => _L_L
52 | L l _ .
53 | }
54 |
55 | rule {
56 | ___ HHH
57 | HHH => .F.
58 | AB@BA .....
59 | L L . .
60 | }
61 |
62 | // Fall
63 | rule {
64 | HHH ___
65 | HFH HHH
66 | AB@BA => _HFH_
67 | _L_L_ AB@BA
68 | _ _ L L
69 | }
70 |
71 | // Walk Right
72 | rule {
73 | HHH_ _HHH
74 | HFH_ _HFH
75 | AB@BA => _AB@B
76 | L_L_ _L_L
77 | }
78 |
79 | // Walk Right up slope
80 | rule {
81 | HHH_ _HHH
82 | HFH_ _HFH
83 | AB@BA => _AB@B
84 | L_L _L_.
85 | }
86 |
87 |
88 |
89 | }
90 |
91 | element LukeArm {
92 | colour "#F2BB4F"
93 | hidden true
94 | state "solid"
95 | }
96 |
97 | element LukeFace {
98 | colour "#F2BB4F"
99 | hidden true
100 | state "solid"
101 | }
102 |
103 | element LukeHair {
104 | colour "#562c2c"
105 | hidden true
106 | state "solid"
107 | }
108 |
109 | element LukeLeg {
110 | colour "grey"
111 | emissive "black"
112 | hidden true
113 | state "solid"
114 |
115 | /*given H (element) => element == LukeHair
116 | given B (element) => element == LukeBody
117 | change B () => new LukeBody()
118 | rule {
119 | H .
120 | B .
121 | @ => B
122 | _ @
123 | }*/
124 | }
125 |
126 | element LukeBody {
127 | colour "red"
128 | emissive "darkred"
129 | hidden true
130 | state "solid"
131 |
132 | given B (element) => element == LukeBody
133 | change B () => new LukeBody()
134 | change H () => new LukeHair()
135 |
136 | /*action { @_B => .B. }
137 | action { B_@ => .B. }*/
138 |
139 | }
140 |
141 |
142 |
143 | `
--------------------------------------------------------------------------------
/Source/Elements/Old/TodeSplat3/Presets.js:
--------------------------------------------------------------------------------
1 | TodeSplat`
2 |
3 | element Static {
4 | colour "grey"
5 | emissive "black"
6 | category "Rulesets"
7 | state "solid"
8 | }
9 |
10 | element Powder {
11 |
12 | colour "grey"
13 | category "Rulesets"
14 | //hidden true
15 |
16 | state "solid"
17 |
18 | given D (space, element) => space && (!element || element.state == "liquid" || element.state == "gloop" || element.state == "gas" || element.state == "effect")
19 | select D (atom) => atom
20 | change D (selected) => selected
21 |
22 | given T (space, element) => space && (!element || element.state == "liquid" || element.state == "gloop" || element.state == "gas" || element.state == "effect")
23 | select T (atom) => atom
24 | change T (selected) => selected
25 |
26 | rule {
27 | @ => D
28 | D @
29 | }
30 |
31 | rule xz {
32 | @T => TD
33 | #D #@
34 | }
35 |
36 | }
37 |
38 | element Solid {
39 | colour "grey"
40 | category "Rulesets"
41 | //hidden true
42 |
43 | state "solid"
44 |
45 | given D (space, element) => space && (!element || element.state == "liquid" || element.state == "gloop" || element.state == "gas" || element.state == "effect")
46 | select D (atom) => atom
47 | change D (selected) => selected
48 |
49 | rule {
50 | @ => D
51 | D @
52 | }
53 | }
54 |
55 | element Liquid {
56 |
57 | colour "grey"
58 | category "Rulesets"
59 | //hidden true
60 |
61 | state "liquid"
62 |
63 | given D (space, element) => space && (!element || element.state == "gas" || element.state == "effect")
64 | select D (atom) => atom
65 | change D (selected) => selected
66 |
67 | given T (space, element) => space && (!element || element.state == "gas" || element.state == "effect")
68 | select T (atom) => atom
69 | change T (selected) => selected
70 |
71 | rule {
72 | @ => D
73 | D @
74 | }
75 |
76 | rule xz {
77 | @T => TD
78 | #D #@
79 | }
80 |
81 | rule xz {
82 | @D D@
83 | # => #
84 | }
85 |
86 | }
87 |
88 | element Gloop {
89 |
90 | colour "grey"
91 | category "Rulesets"
92 | //hidden true
93 |
94 | state "gloop"
95 |
96 | given D (space, element) => space && (!element || element.state == "liquid" || element.state == "gas" || element.state == "effect")
97 | select D (atom) => atom
98 | change D (selected) => selected
99 |
100 | given T (space, element) => space && (!element || element.state == "liquid" || element.state == "gas" || element.state == "effect")
101 | select T (atom) => atom
102 | change T (selected) => selected
103 |
104 | rule {
105 | @ => D
106 | D @
107 | }
108 |
109 | rule xz 0.1 {
110 | @T => TD
111 | #D #@
112 | }
113 |
114 | rule xz 0.05 {
115 | @D D@
116 | # => #
117 | }
118 |
119 | }
120 |
121 | `
--------------------------------------------------------------------------------
/Source/Elements/Old/TodeSplat3/Sandbox.js:
--------------------------------------------------------------------------------
1 | TodeSplat`
2 |
3 | element Sand {
4 | default true
5 | colour "#ffcc00"
6 | emissive "#ffa34d"
7 | category "Sandbox"
8 |
9 | ruleset Powder
10 |
11 | }
12 |
13 | element Water {
14 |
15 | colour "lightblue"
16 | emissive "blue"
17 | opacity 0.5
18 | category "Sandbox"
19 | state "liquid"
20 |
21 | given H (element) => element && element.isHot
22 | keep H
23 |
24 | change S () => new Steam()
25 |
26 | rule xyz { @H => SH }
27 | ruleset Liquid
28 |
29 | }
30 |
31 | element Fire {
32 | colour "orange"
33 | emissive "red"
34 | category "Sandbox"
35 | floor true
36 | ignites true
37 | isHot true
38 |
39 | state "effect"
40 |
41 | rule 0.3 { @ => _ }
42 | rule {
43 | _ => @
44 | @ _
45 | }
46 |
47 | rule {
48 | x => x
49 | @ _
50 | }
51 |
52 | }
53 |
54 | /*element Flame {
55 | colour "orange"
56 | emissive "red"
57 | category "Sandbox"
58 | floor true
59 | ignites true
60 | isHot true
61 | precise true
62 |
63 | state "effect"
64 |
65 | rule 0.03 { @ => _ }
66 |
67 | change F () => new Fire()
68 | rule {
69 | _ => F
70 | @ @
71 | }
72 | rule xyz { @_ => @F }
73 |
74 | }*/
75 |
76 | element Lava {
77 | colour "red"
78 | emissive "darkred"
79 | category "Sandbox"
80 | opacity 0.7
81 | ignites true
82 | isHot true
83 |
84 | state "gloop"
85 |
86 | change F () => new Fire()
87 |
88 | action 0.25 {
89 | _ => F
90 | @ @
91 | }
92 |
93 | ruleset Gloop
94 |
95 | }
96 |
97 | element Slime {
98 | colour "lightgreen"
99 | emissive "green"
100 | category "Sandbox"
101 | opacity 0.7
102 | state "gloop"
103 | ruleset Gloop
104 | }
105 |
106 | element Snow {
107 | colour "white"
108 | emissive "grey"
109 |
110 | category "Sandbox"
111 | state "solid"
112 |
113 | given H (element) => element && element.isHot
114 | keep H
115 | change W () => new Water()
116 |
117 | rule 0.0005 { @ => W }
118 | rule xyz { @H => WH }
119 |
120 | ruleset Powder
121 |
122 | }
123 |
124 | element Steam {
125 | colour "lightgrey"
126 | emissive "darkgrey"
127 | category "Sandbox"
128 | opacity 0.3
129 | floor true
130 | state "gas"
131 |
132 | change W () => new Water()
133 |
134 | rule 0.0002 { @ => W }
135 |
136 | rule {
137 | _ => @
138 | @ _
139 | }
140 |
141 | rule xz { @_ => _@ }
142 |
143 | }
144 |
145 | element WallSeed {
146 | colour "rgb(128, 128, 128)"
147 | emissive "rgb(2, 128, 200)"
148 | category "Sandbox"
149 | state "solid"
150 |
151 | data fuel 10
152 |
153 | ruleset Solid
154 |
155 | given W (element) => element == Solid || element == WallSeed
156 | given W (self) => self.fuel == 10
157 | rule {
158 | @ => _
159 | W .
160 | }
161 |
162 | change W () => new Solid()
163 | change S (self) => {
164 | self.fuel--
165 | if (self.fuel > 0) return self
166 | }
167 |
168 | rule {
169 | _ => S
170 | @ W
171 | }
172 |
173 | }
174 |
175 | element Platform {
176 | colour "rgb(128, 128, 128)"
177 | emissive "rgb(2, 128, 200)"
178 | category "Sandbox"
179 | state "solid"
180 | data fuel 100
181 | //default true
182 | precise true
183 | pour false
184 |
185 | given f (self) => self.fuel <= 0
186 | rule { f => _ }
187 |
188 | change S () => new Static()
189 | change P (self) => new Platform({fuel: (self.fuel-1)/2})
190 | rule { _@_ => PSP}
191 |
192 | change B (self) => new Platform({fuel: self.fuel-1})
193 | rule x { @_ => SB }
194 |
195 | /*rule { #@# => ._. }*/
196 |
197 | rule x { @x => _. }
198 | }
199 |
200 | element Ball {
201 | colour "grey"
202 | emissive "black"
203 | state "solid"
204 | category "Sandbox"
205 |
206 | data fallSpeed 0
207 |
208 | keep f (self) => {
209 | self.fallSpeed += 0.015
210 | if (self.fallSpeed > 2) self.fallSpeed = 2
211 | }
212 | action {
213 | @ => f
214 | _ .
215 | }
216 |
217 | given s (atom) => atom
218 | select s (atom) => atom
219 | keep s (self, selected) => {
220 | self.fallSpeed += 0.015
221 | if (selected.fallSpeed != undefined) {
222 | if (selected.fallSpeed < self.fallSpeed) {
223 | selected.fallSpeed = self.fallSpeed
224 | }
225 | }
226 | if (self.fallSpeed < 0) self.fallSpeed = 0
227 | }
228 | action {
229 | @ => s
230 | s .
231 | }
232 |
233 | keep c (self) => self.fallSpeed = 0
234 | action {
235 | @ => c
236 | x .
237 | }
238 |
239 | given q (space, atom) => space && !atom
240 | given q (self) => Math.random() < self.fallSpeed / 2
241 | rule {
242 | @ => _
243 | _ _
244 | q @
245 | }
246 |
247 | given e (space, atom) => space && !atom
248 | given e (self) => Math.random() < self.fallSpeed
249 | rule {
250 | @ => _
251 | e @
252 | }
253 |
254 | }
255 |
256 | `
257 |
--------------------------------------------------------------------------------
/Source/Elements/Old/TodeSplat3/T2Tile.js:
--------------------------------------------------------------------------------
1 | TodeSplat`
2 |
3 | element ForkBomb {
4 |
5 | colour "grey"
6 | emissive "black"
7 | category "T2Tile"
8 |
9 | rule xyz { @_ => @@ }
10 |
11 | }
12 |
13 | element Res {
14 |
15 | colour "slategrey"
16 | emissive "grey"
17 | opacity 0.3
18 | category "T2Tile"
19 | isFood true
20 |
21 | rule xyz { @_ => _@ }
22 |
23 | }
24 |
25 | element DReg {
26 |
27 | colour "brown"
28 | emissive "brown"
29 | opacity 0.3
30 | category "T2Tile"
31 |
32 | given D (element) => element == DReg
33 | given n (atom, element) => atom && element != DReg
34 |
35 | change R () => new Res()
36 | change D () => new DReg()
37 |
38 | rule xyz 0.001 { @_ => D@ }
39 | rule xyz 0.005 { @_ => R@ }
40 | rule xyz 0.1 { @D => _@ }
41 | rule xyz 0.01 { @n => _@ }
42 | rule xyz { @_ => _@ }
43 |
44 | }
45 |
46 | `;
47 |
--------------------------------------------------------------------------------
/Source/Elements/Old/TodeSplat3/Tutorial.js:
--------------------------------------------------------------------------------
1 | TodeSplat`
2 |
3 | element SandDemo {
4 |
5 | colour "#ffcc00"
6 | emissive "#ffa34d"
7 | category "Tutorial"
8 |
9 | given D (space) => space
10 | given D (element) => element == WaterDemo || element == SlimeDemo || element == undefined
11 | select D (atom) => atom
12 |
13 | change D (selected) => selected
14 |
15 | rule {
16 | @ => D
17 | D @
18 | }
19 |
20 | rule xz {
21 | @ => D
22 | #D #@
23 | }
24 |
25 | }
26 |
27 | element WaterDemo {
28 |
29 | colour "lightblue"
30 | emissive "blue"
31 | opacity 0.5
32 | category "Tutorial"
33 |
34 | rule {
35 | @ => _
36 | _ @
37 | }
38 |
39 | rule xz {
40 | @_ => _@
41 | # #
42 | }
43 |
44 | }
45 |
46 | element SlimeDemo {
47 |
48 | colour "lightgreen"
49 | emissive "green"
50 | opacity 0.7
51 | category "Tutorial"
52 |
53 | rule {
54 | @ => _
55 | _ @
56 | }
57 |
58 | rule xz 0.1 {
59 | @_ => _@
60 | # #
61 | }
62 |
63 | }
64 |
65 | element SnowDemo {
66 |
67 | colour "white"
68 | emissive "grey"
69 | category "Tutorial"
70 |
71 | change W () => new WaterDemo()
72 | rule 0.0001 { @ => W }
73 | ruleset SandDemo
74 |
75 | }
76 |
77 | element PlantDemo {
78 | colour "green"
79 | category "Tutorial"
80 |
81 | // Gravity
82 | ruleset SandDemo
83 |
84 | // Grow
85 | rule xz 0.05 { @_ => @@ }
86 |
87 | }
88 |
89 | element HerbivoreDemo {
90 | colour "blue"
91 | emissive "darkblue"
92 | category "Tutorial"
93 |
94 | // Die
95 | rule 0.002 { @ => _ }
96 |
97 | // Gravity
98 | ruleset SandDemo
99 |
100 | // Reproduce
101 | given P (element) => element == PlantDemo
102 | rule xyz 0.05 { @P => @@ }
103 |
104 | // Eat
105 | rule xyz { @P => @_ }
106 |
107 | // Move
108 | rule xz 0.5 { @_ => _@ }
109 | }
110 |
111 | element LavaDemo {
112 | colour "red"
113 | emissive "darkred"
114 | category "Tutorial"
115 | opacity 0.7
116 |
117 | change F () => new FireDemo()
118 | action {
119 | _ => F
120 | @ @
121 | }
122 |
123 | ruleset SlimeDemo
124 | }
125 |
126 | element FireDemo {
127 | colour "orange"
128 | emissive "red"
129 | category "Tutorial"
130 | opacity 0.5
131 | floor true
132 |
133 | rule 0.3 { @ => _ }
134 |
135 | rule {
136 | _ => @
137 | @ _
138 | }
139 |
140 | rule { @ => _ }
141 |
142 | }
143 |
144 | element EggDemo {
145 | colour "pink"
146 | emissive "grey"
147 | category "Tutorial"
148 | precise true
149 | pour false
150 |
151 | data timer 100
152 |
153 | // Countdown
154 | keep t (self) => self.timer--
155 | action { @ => t }
156 |
157 | // Hatch
158 | given h (self) => self.timer < 0
159 | change H () => new HerbivoreDemo()
160 | rule { h => H }
161 |
162 | // Fall
163 | rule {
164 | @ => _
165 | _ @
166 | }
167 | }
168 |
169 | element WindySandDemo {
170 | colour SandDemo.colour
171 | emissive SandDemo.emissive
172 | category "Tutorial"
173 |
174 | rule 0.3 { _@ => @_ }
175 | rule 0.2 {
176 | _ => @
177 | #@ #_
178 | }
179 |
180 | ruleset SandDemo
181 | }
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 | `
--------------------------------------------------------------------------------
/Source/Elements/Old/TodeSplat3/Weather.js:
--------------------------------------------------------------------------------
1 | TodeSplat`
2 |
3 | element WeatherBoy {
4 | colour "blue"
5 | emissive "darkblue"
6 |
7 | state "effect"
8 |
9 | isWeatherBoy true
10 | chance 0.01
11 |
12 | // init
13 | given i (self) => !self.initialised
14 | change I (self) => {
15 | self.birthday = new Date().getTime()
16 | self.initialised = true
17 | return self
18 | }
19 | rule { @i => I. }
20 |
21 | given d (space, atom) => space && !atom
22 | given d (self) => Math.random() < self.element.chance
23 | change D (self) => self.element.drop? new self.element.drop() : undefined
24 | rule {
25 | @ => @
26 | d D
27 | }
28 |
29 | rule {
30 | _ => @
31 | @ _
32 | }
33 |
34 | given W (atom) => atom && atom.initialised
35 | given W (element) => element && element.isWeatherBoy
36 | given W (self, atom) => atom && self.birthday >= atom.birthday
37 | change W (self) => {
38 | const atom = new self.element()
39 | atom.birthday = self.birthday
40 | atom.initialised = true
41 | return atom
42 | }
43 | rule xz 0.2 { @_ => W@ }
44 | rule xz { @W => _@ }
45 | rule xz { @_ => _@ }
46 | }
47 |
48 | element Rainy {
49 | colour "lightblue"
50 | emissive "darkblue"
51 | opacity 0.0
52 | category "Weather"
53 | state "effect"
54 |
55 | isWeatherBoy true
56 | chance 0.01
57 | drop Water
58 |
59 | ruleset WeatherBoy
60 | }
61 |
62 | element Sandstorm {
63 | colour "#ffcc00"
64 | emissive "darkblue"
65 | opacity 0.0
66 | category "Weather"
67 | state "effect"
68 |
69 | isWeatherBoy true
70 | chance 0.01
71 | drop Sand
72 |
73 | ruleset WeatherBoy
74 | }
75 |
76 | element Snowstorm {
77 | colour "white"
78 | emissive "darkblue"
79 | opacity 0.0
80 | category "Weather"
81 | state "effect"
82 |
83 | isWeatherBoy true
84 | chance 0.01
85 | drop Snow
86 |
87 | ruleset WeatherBoy
88 | }
89 |
90 | element Sunny {
91 | colour "orange"
92 | emissive "darkblue"
93 | category "Weather"
94 | opacity 0.0
95 | state "effect"
96 |
97 | isWeatherBoy true
98 | chance 0.01
99 | drop undefined
100 |
101 | ruleset WeatherBoy
102 | }
103 |
104 | `
--------------------------------------------------------------------------------
/Source/Elements/Sandbox.js:
--------------------------------------------------------------------------------
1 | SpaceTode`
2 |
3 | element Sand {
4 | colour "#ffcc00"
5 | emissive "#ffa34d"
6 | category "Sandbox"
7 | prop state SOLID
8 | prop temperature ROOM
9 | prop states () => ({
10 | [HOT]: Glass,
11 | })
12 |
13 | mimic(Temperature)
14 | mimic(Powder)
15 | }
16 |
17 | /*element Salt {
18 | default true
19 | colour "white"
20 | emissive "grey"
21 | category "Sandbox"
22 | prop state SOLID
23 | prop temperature ROOM
24 | prop states () => ({
25 | [HOT]: Glass,
26 | })
27 |
28 | mimic(Temperature)
29 | mimic(Powder)
30 | }*/
31 |
32 | element Water {
33 | colour "lightblue"
34 | emissive "blue"
35 | opacity 0.35
36 | category "Sandbox"
37 | prop state LIQUID
38 | prop temperature COOL
39 | prop states () => ({
40 | [COLD]: [Ice, 0.05],
41 | [CHILLY]: [Snow, 0.05],
42 | [WARM]: [Steam, 0.4],
43 | [HOT]: Steam,
44 | })
45 |
46 | mimic(Temperature)
47 | mimic(Liquid)
48 | }
49 |
50 | element Ice {
51 | colour "lightblue"
52 | emissive "#87c5c7"
53 | category "Sandbox"
54 | opacity 0.4
55 | prop state SOLID
56 | prop temperature COLD
57 | prop states () => ({
58 | [COOL]: [Water, 0.0001],
59 | [ROOM]: [Water, 0.0001],
60 | [BODY]: [Water, 0.01],
61 | [WARM]: Water,
62 | [HOT]: Water,
63 | })
64 |
65 | mimic(Temperature)
66 | mimic(Sticky)
67 | mimic(Powder)
68 | }
69 |
70 | element Snow {
71 | colour "white"
72 | emissive "grey"
73 | category "Sandbox"
74 | prop state SOLID
75 | prop temperature CHILLY
76 | prop states () => ({
77 | [COOL]: [Water, 0.04],
78 | [ROOM]: [Water, 0.00005],
79 | [BODY]: [Water, 0.01],
80 | [WARM]: Water,
81 | [HOT]: Water,
82 | })
83 |
84 | mimic(Temperature)
85 | mimic(Powder)
86 | }
87 |
88 | element Steam {
89 | colour "lightgrey"
90 | emissive "darkgrey"
91 | category "Sandbox"
92 | opacity 0.2
93 | prop state GAS
94 | prop temperature WARM
95 | prop states () => ({
96 | [COLD]: Water,
97 | [CHILLY]: Water,
98 | [COOL]: [Water, 0.1],
99 | [ROOM]: [Empty, 0.1],
100 | })
101 |
102 | mimic(Temperature)
103 |
104 | given D (element, selfElement) => element !== selfElement && element.state >= GAS
105 | select D (atom) => atom
106 | change D (selected) => selected
107 | D => @
108 | @ D
109 |
110 | mimic(Gas)
111 | }
112 |
113 | element Stone {
114 | category "Sandbox"
115 | prop state SOLID
116 | prop temperature ROOM
117 | prop states () => ({
118 | [HOT]: Magma,
119 | })
120 | mimic(Temperature)
121 | mimic(Solid)
122 | }
123 |
124 | element Rock {
125 | colour "grey"
126 | emissive "black"
127 | prop state SOLID
128 | prop temperature ROOM
129 | prop stickiness 1.0
130 | data stuck false
131 | category "Sandbox"
132 | mimic(Sticky)
133 | mimic(Solid)
134 | }
135 |
136 | element Fire {
137 | colour "darkorange"
138 | emissive "red"
139 | category "Sandbox"
140 | opacity 0.25
141 | prop state EFFECT
142 | prop temperature HOT
143 | prop states () => ({
144 | [COLD]: Empty,
145 | [CHILLY]: Empty,
146 | [COOL]: Empty,
147 | [ROOM]: [Empty, 0.3],
148 | [BODY]: [Empty, 0.1],
149 | })
150 |
151 | mimic(Temperature)
152 |
153 | given D (element, selfElement) => element !== selfElement && element.state >= GAS
154 | select D (atom) => atom
155 | change D (selected) => selected
156 | D => @
157 | @ D
158 |
159 | given n (element, selfElement) => element !== selfElement
160 | n .
161 | @ => _
162 |
163 | }
164 |
165 | element Magma {
166 | colour "orange"
167 | emissive "brown"
168 | category "Sandbox"
169 | prop state SOLID
170 | prop temperature HOT
171 | prop states () => ({
172 | [COLD]: Rock,
173 | [CHILLY]: Rock,
174 | [COOL]: Rock,
175 | [ROOM]: [Rock, 0.075],
176 | [BODY]: [Rock, 0.065],
177 | [WARM]: [Rock, 0.05],
178 | })
179 |
180 | mimic(Temperature)
181 | mimic(Goo)
182 | }
183 |
184 | element Lava {
185 | colour "red"
186 | emissive "darkred"
187 | category "Sandbox"
188 | opacity 0.5
189 | prop state SOLID
190 | prop temperature HOT
191 | prop states () => ({
192 | [COOL]: [Rock, 0.05],
193 | [COLD]: [Rock, 0.1],
194 | })
195 |
196 | mimic(Temperature)
197 |
198 | change F () => new Fire()
199 | action {
200 | _ => F
201 | @ .
202 | }
203 |
204 | mimic(Goo)
205 |
206 | }
207 |
208 | element Laser {
209 | colour "red"
210 | opacity 0.2
211 | prop state EFFECT
212 | prop temperature HOT
213 | category "Sandbox"
214 |
215 | symbol L Laser
216 | symbol G Glass
217 | given n (element, selfElement) => (element.state === undefined || element.state < GAS) && element !== Glass && element !== Void
218 | @ => _
219 | n @
220 | n L
221 |
222 | @ => _
223 | n @
224 |
225 | @ => _
226 | _ @
227 |
228 | @ => _
229 | G .
230 | . L
231 |
232 | @ => _
233 | }
234 |
235 | element Slime {
236 | colour "lightgreen"
237 | emissive "green"
238 | category "Sandbox"
239 | opacity 0.65
240 | prop state SOLID
241 | prop temperature BODY
242 | prop states () => ({
243 | [HOT]: Acid,
244 | })
245 |
246 | mimic(Temperature)
247 | mimic(Goo)
248 | }
249 |
250 | element Acid {
251 | colour "lightgreen"
252 | emissive "green"
253 | opacity 0.35
254 | category "Sandbox"
255 | prop state LIQUID
256 | prop temperature ROOM
257 | prop states () => ({
258 | [COLD]: Slime,
259 | [CHILLY]: Slime,
260 | })
261 |
262 | mimic(Temperature)
263 |
264 | symbol S Steam
265 | given n (element, selfElement) => (element.state === undefined || element.state < GAS) && element !== Void && element !== Empty && element !== selfElement && element !== Slime && element !== Glass
266 | n => S
267 | @ _
268 |
269 | @ => S
270 | n _
271 |
272 | @ => _
273 | _ @
274 |
275 | any(xz.rotations) {
276 | @n => _S
277 |
278 | @ => .
279 | x .
280 |
281 | @_ => _@
282 | }
283 | }
284 |
285 | element Cloud any(xz.rotations) {
286 |
287 | category "Structure"
288 | arg rain Water
289 | arg chance 1/100
290 | arg birthday
291 | opacity 0.35
292 | prop state GAS
293 | prop temperature ROOM
294 |
295 | given i (self) => self.birthday === undefined
296 | keep i (self, time) => self.birthday = time
297 | i => i
298 |
299 | given r (element, self) => element === Empty && (Math.random() < self.chance)
300 | change R (self) => new self.rain()
301 | @ => .
302 | r R
303 |
304 | _ => @
305 | @ _
306 |
307 | change W (selfElement, self) => new selfElement(self.rain, self.chance, self.birthday)
308 | maybe(1/5) @_ => W@
309 |
310 | given W (element, selfElement, atom, self) => element === selfElement && self.birthday >= atom.birthday
311 | @W => _@
312 | @_ => _@
313 |
314 | }
315 |
316 | element Static {
317 | prop state SOLID
318 | prop temperature ROOM
319 | category "Structure"
320 | }
321 |
322 | element Wall {
323 | colour "rgb(128, 128, 128)"
324 | emissive "rgb(2, 128, 200)"
325 | category "Structure"
326 | prop state SOLID
327 | prop temperature ROOM
328 | arg fuel 10
329 |
330 | mimic(Solid)
331 |
332 | given W (element, selfElement) => element === selfElement
333 | @ => _
334 | W .
335 |
336 | symbol S Stone
337 | @ => _
338 | S .
339 |
340 | given B (element) => element === Wall.Builder
341 | change B (self, element) => new Wall.Builder(self.fuel)
342 | @ => _
343 | B .
344 |
345 | @ => B
346 |
347 | @ => _
348 |
349 | element Builder {
350 | colour "pink"
351 | emissive "red"
352 | prop state SOLID
353 | prop temperature ROOM
354 | arg fuel 10
355 |
356 | change G (self) => {
357 | self.fuel--
358 | if (self.fuel < 0) return new Empty()
359 | return self
360 | }
361 | _ => G
362 | @ S
363 |
364 | x => .
365 | @ _
366 | }
367 |
368 | }
369 |
370 | element Cardboard {
371 | colour "brown"
372 | //default true
373 | category "Structure"
374 | prop state SOLID
375 | prop temperature ROOM
376 | arg id
377 | arg ready false
378 |
379 | given S (element) => element.state > SOLID
380 | select S (atom) => atom
381 | change S (selected) => selected
382 |
383 | given i (self) => self.id === undefined
384 | keep i (self) => self.id = Cardboard.id
385 | action i => i
386 |
387 | given R (self) => !self.ready && !Mouse.down
388 | keep R (self) => self.ready = true
389 | action R => R
390 |
391 |
392 | given r (self) => !self.ready
393 | r => .
394 |
395 | for(xz.rotations) {
396 | $ .
397 | @ => .
398 | }
399 |
400 | any(xz.rotations) {
401 | @ => S
402 | S @
403 | }
404 | }
405 |
406 | element Glass {
407 | opacity 0.1
408 | prop state SOLID
409 | prop temperature ROOM
410 | prop stickiness 1.0
411 | data stuck false
412 | category "Sandbox"
413 | mimic(Sticky)
414 | mimic(Solid)
415 |
416 | symbol G new Glass
417 |
418 | @ => @
419 | _ G
420 | G G
421 |
422 | }
423 |
424 | element Charcoal {
425 | colour "#2e362d"
426 | emissive "#2e362d"
427 | category "Sandbox"
428 | prop state SOLID
429 | prop temperature ROOM
430 | prop states () => ({
431 | [HOT]: [FlamingCharcoal, 0.05],
432 | })
433 |
434 | mimic(Temperature)
435 | mimic(Solid)
436 | }
437 |
438 | element FlamingCharcoal {
439 | colour "#2e362d"
440 | emissive "#2e362d"
441 | //category "Sandbox"
442 | prop state SOLID
443 | prop temperature HOT
444 | prop states () => ({
445 | [ROOM]: [Ash, 0.003],
446 | [COOL]: [Ash, 0.005],
447 | [COLD]: [Ash, 0.01],
448 | })
449 |
450 | mimic(Temperature)
451 |
452 | change F () => new Fire()
453 | action {
454 | _ => F
455 | @ .
456 | }
457 |
458 | mimic(Solid)
459 | }
460 |
461 | element Ash {
462 | colour "black"
463 | emissive "black"
464 | category "Sandbox"
465 | prop state SOLID
466 | prop temperature WARM
467 |
468 | mimic(Temperature)
469 | mimic(Powder)
470 | }
471 |
472 | element Crystal {
473 | colour "pink"
474 | emissive "purple"
475 | //category "Sandbox"
476 | opacity 0.3
477 |
478 | data fuel
479 |
480 | given n (element, Self) => element !== Self
481 |
482 | given D (element) => element.state > SOLID && element.state !== EFFECT
483 | select D (atom) => atom
484 | change D (selected) => selected
485 |
486 |
487 | given g (element) => element.state <= SOLID
488 |
489 |
490 |
491 | $ => .
492 | @ .
493 | g .
494 |
495 | all(xz.directions) {
496 | $ => .
497 | @ .
498 | g .
499 | }
500 |
501 | maybe(0.3) any(xz.directions) {
502 | _@_ => $.$
503 | }
504 |
505 | maybe(1/20) {
506 | _ => $
507 | @ .
508 | }
509 |
510 | /*all(xz.directions) {
511 | @ => .
512 | $ .
513 |
514 | @$ => ..
515 | $ .
516 | }*/
517 |
518 | /*@ => ?
519 | ? @*/
520 |
521 | }
522 |
523 |
524 |
525 | `
526 |
527 | on.mousedown(e => {
528 | if (UI.selectedElement === Cardboard) {
529 | if (e.buttons !== 1) return
530 | Cardboard.id = Math.random()
531 | }
532 | })
533 |
--------------------------------------------------------------------------------
/Source/Elements/Smell.js:
--------------------------------------------------------------------------------
1 | // Smell Flags
2 | const LOVE = Flag(1)
3 | const STINK = Flag(2)
4 |
5 | SpaceTode`
6 |
7 | element Sniffer {
8 | given P (element, self, atom, Self) => Flag.has(element.smell, Self.pheromone) && (atom.owner !== self)
9 | select P (atom) => atom.target
10 | keep P (self, selected) => {
11 | if (selected === undefined) return
12 | self.target = [...selected]
13 | self.interest = 1.0
14 | }
15 | action for(xz.directions) @P => P.
16 |
17 | given I (self) => self.interest > 0
18 | keep I (self) => self.interest -= 0.1
19 | action I => I
20 | }
21 |
22 | element Smell {
23 | prop state GAS
24 | prop temperature ROOM
25 | opacity 0.3
26 |
27 | given i (self) => self.target === undefined
28 | keep i (self) => {
29 | self.target = [0, 0, 0]
30 | if (self.strength === undefined) self.strength = 0.99
31 | }
32 | i => i
33 |
34 | given S (self) => Math.random() > self.strength
35 | S => _
36 |
37 | given F (element, Self) => element.state >= GAS && element !== Self
38 | select F (atom) => atom
39 | change F (selected, self) => {
40 | self.target[1] -= 1
41 | return selected
42 | }
43 | @ => F
44 | F @
45 |
46 | change M (self, x, y, z) => {
47 | self.target[0] += x
48 | self.target[1] += y
49 | self.target[2] += z
50 | return self
51 | }
52 |
53 | given D (element, Self) => element.state >= GAS && element !== Self
54 | select D (atom) => atom
55 | change D (selected) => selected
56 | for(xyz.directions) @D => DM
57 |
58 | }
59 |
60 | element Pheromone {
61 | category "Life"
62 | prop state GAS
63 | prop temperature ROOM
64 | prop smell LOVE
65 | arg strength 0.99
66 | arg owner undefined
67 | colour "pink"
68 | emissive "rgb(255, 64, 128)"
69 | opacity 0.3
70 | mimic(Smell)
71 | }
72 |
73 | `
74 |
--------------------------------------------------------------------------------
/Source/Elements/State.js:
--------------------------------------------------------------------------------
1 |
2 | const EFFECT = 0
3 | const VOID = 1
4 | const SOLID = 2
5 | const LIQUID = 3
6 | const GAS = 4
7 |
8 | Empty.state = GAS
9 | Void.state = VOID
10 |
11 | SpaceTode`
12 |
13 | element Solid {
14 | prop state SOLID
15 | //category "Rulesets"
16 |
17 | given D (element) => element.state > SOLID && element.state !== EFFECT
18 | select D (atom) => atom
19 | change D (selected) => selected
20 | @ => D
21 | D @
22 | }
23 |
24 | element Powder {
25 | prop state SOLID
26 | //category "Rulesets"
27 |
28 | given D (element) => element.state > SOLID && element.state !== EFFECT
29 | select D (atom) => atom
30 | change D (selected) => selected
31 | @ => D
32 | D @
33 |
34 | given S (element) => element.state > SOLID && element.state !== EFFECT
35 | select S (atom) => atom
36 | change S (selected) => selected
37 | given F (element) => element.state > SOLID
38 | any(xz.rotations) {
39 | @S => S@
40 | F .
41 | }
42 | }
43 |
44 | element Liquid {
45 | prop state LIQUID
46 | //category "Rulesets"
47 |
48 | given D (element) => element.state > LIQUID && element.state !== EFFECT
49 | select D (atom) => atom
50 | change D (selected) => selected
51 | @ => D
52 | D @
53 |
54 | @ => .
55 | x .
56 |
57 | given S (element) => element.state > SOLID && element.state !== EFFECT
58 | select S (atom) => atom
59 | change S (selected) => selected
60 | for(xz.rotations) @S => S@
61 | }
62 |
63 | element Goo {
64 | prop state SOLID
65 | //category "Rulesets"
66 |
67 | given D (element) => element.state > SOLID
68 | select D (atom) => atom
69 | change D (selected) => selected
70 |
71 | given F (element) => element.state > SOLID
72 |
73 | @ => D
74 | D @
75 |
76 | @ => .
77 | x .
78 |
79 | any(xz.rotations) {
80 |
81 | maybe(1/20) {
82 | @D => D@
83 | F .
84 | }
85 |
86 | maybe(1/30) @D => D@
87 | }
88 | }
89 |
90 | element Gas {
91 | prop state GAS
92 | //category "Rulesets"
93 |
94 | given D (element) => element.state >= GAS && element.state !== EFFECT
95 | select D (atom) => atom
96 | change D (selected) => selected
97 | any(xyz.directions) @D => D@
98 | }
99 |
100 | element Sticky {
101 | prop state SOLID
102 | //category "Rulesets"
103 |
104 | // Init atom properties
105 | given i (self) => self.stickyInit === undefined
106 | keep i (self, time, Self) => {
107 | self.stickyInit = true
108 | self.stuckTime = -Infinity
109 | self.stuck = false
110 | if (Self.stickiness === undefined) Self.stickiness = 1.0
111 | if (Self.stickinessNormalised === undefined) Self.stickinessNormalised = Math.floor(Self.stickiness * 30)
112 | }
113 | action i => i
114 |
115 | // Debug colour
116 | /*keep c (self, time, origin, Self) => {
117 | let timeDiff = Math.round((time - self.stuckTime) * 255 / Self.stickinessNormalised)
118 | if (timeDiff > 255) timeDiff = 255
119 | self.colour.r = timeDiff
120 | self.colour.b = 255 - timeDiff
121 | self.colour.g = 255 - timeDiff
122 | SPACE.updateAppearance(origin)
123 | }
124 | action @ => c*/
125 |
126 | // Contact with ground
127 | given n (element, selfElement, atom) => element !== selfElement && element.state <= SOLID && atom.stuck !== false
128 | keep t (self, time) => self.stuckTime = time
129 | action {
130 | @ => t
131 | n .
132 | }
133 |
134 | // Spread + Receive signal
135 | given s (selfElement, element, self, atom) => element === selfElement && self.stuckTime > atom.stuckTime
136 | keep s (self, atom) => atom.stuckTime = self.stuckTime
137 | given r (selfElement, element, self, atom) => element === selfElement && self.stuckTime < atom.stuckTime
138 | keep r (self, atom) => self.stuckTime = atom.stuckTime
139 | all(xyz.directions) {
140 | action @s => .s
141 | action @r => .r
142 | }
143 |
144 | /*all(xyz.shifts) {
145 | action {
146 | s => s
147 | @ .
148 | }
149 | action {
150 | r => r
151 | @ .
152 | }
153 | }*/
154 |
155 | // Stuck!
156 | given S (self, time, Self) => {
157 | const stuck = time - self.stuckTime < Self.stickinessNormalised
158 | self.stuck = stuck
159 | return stuck
160 | }
161 | S => .
162 |
163 | /*given D (element) => element.state > SOLID
164 | select D (atom) => atom
165 | change D (selected) => selected
166 | // Fall
167 | @ => D
168 | D @*/
169 |
170 | }
171 |
172 | `
--------------------------------------------------------------------------------
/Source/Elements/T2Tile.js:
--------------------------------------------------------------------------------
1 | SpaceTode`
2 |
3 | element Forkbomb any(xyz.directions) {
4 | colour "grey"
5 | emissive "black"
6 | category "T2Tile"
7 | keep F (space) => SPACE.setAtom(space, new Forkbomb(), Forkbomb)
8 |
9 | @_ => .F
10 | }
11 |
12 | element Res any(xyz.directions) {
13 | category "T2Tile"
14 | colour "slategrey"
15 | emissive "grey"
16 | opacity 0.2
17 | @_ => _@
18 | }
19 |
20 | element DReg any(xyz.directions) {
21 |
22 | colour "brown"
23 | emissive "brown"
24 | opacity 0.2
25 | category "T2Tile"
26 |
27 | symbol D DReg
28 | symbol R Res
29 | given n (element) => element !== DReg && element !== Void
30 |
31 | maybe(1/1000) @_ => D@
32 | maybe(1/200) @_ => R@
33 | maybe(1/10) @D => _@
34 | maybe(1/100) @n => _@
35 | @_ => _@
36 |
37 | }
38 |
39 | element SwapLine {
40 | colour "brown"
41 | category "T2Tile"
42 |
43 | symbol L SwapLine
44 | symbol D SwapLine.Done
45 |
46 | for(y) {
47 | _ => L
48 | @ .
49 |
50 | x => .
51 | @ D
52 |
53 | D => .
54 | @ D
55 | }
56 |
57 | given O (element) => element !== SwapLine
58 | for(y) {
59 | O => .
60 | @ D
61 | }
62 |
63 | element Done {
64 | colour "grey"
65 | emissive "black"
66 |
67 |
68 | for(y) {
69 | D .
70 | @ => .
71 |
72 | L .
73 | @ => .
74 |
75 | L .
76 | @ => .
77 | }
78 |
79 | @D => _@
80 | @L => _@
81 | @x => _.
82 | @? => ?@
83 | }
84 |
85 | }
86 |
87 | element ThickSwapLine {
88 | colour "brown"
89 | category "T2Tile"
90 |
91 | symbol L ThickSwapLine
92 | symbol F ThickSwapLine.Front
93 | symbol B ThickSwapLine.Back
94 |
95 | given l (element) => element !== ThickSwapLine
96 | given f (element) => element !== ThickSwapLine.Front
97 | given b (element) => element !== ThickSwapLine.Back
98 |
99 | given N (element) => element === ThickSwapLine || element === ThickSwapLine.Front || element === ThickSwapLine.Back
100 | given n (element) => element !== ThickSwapLine && element !== ThickSwapLine.Front && element !== ThickSwapLine.Back
101 |
102 | ln ..
103 | @_n => .F.
104 | ln ..
105 |
106 | for(y) {
107 | nnnn ....
108 | __n => $F.
109 | @F ..
110 | }
111 |
112 |
113 | for(y) {
114 |
115 | xxf => ...
116 | @Ff B..
117 | f .
118 |
119 | BFf => ...
120 | @Ff B..
121 | f .
122 |
123 | N .
124 | nnf => ...
125 | @Ff B..
126 | f .
127 | }
128 |
129 |
130 | element Back {
131 | colour "green"
132 | emissive "lightgreen"
133 |
134 | @f => _.
135 |
136 | for(y) {
137 | @ => _
138 | F .
139 | }
140 |
141 | }
142 |
143 | element Front {
144 | colour "grey"
145 | emissive "black"
146 |
147 | for(y) {
148 | L => .
149 | @ _
150 | }
151 |
152 | n@ => ._
153 |
154 | B@x => __.
155 |
156 | @B => _.
157 |
158 | for(y) {
159 | B => .
160 | @ _
161 | }
162 |
163 | for(y) {
164 |
165 | BF => ..
166 | @ .
167 |
168 | LF ..
169 | @ => .
170 | }
171 |
172 | n .
173 | B@_n => _B@.
174 | n .
175 |
176 |
177 | }
178 |
179 | }
180 |
181 | element SwapWall {
182 | colour "brown"
183 | category "T2Tile"
184 | arg timer 0
185 |
186 | given W (element) => element === SwapWall
187 | change W (self) => new SwapWall(self.timer)
188 | change w (self) => new SwapWall(self.timer + 1)
189 |
190 | given D (element) => element === SwapWall.Done
191 | change D (self) => new SwapWall.Done(self.timer)
192 |
193 | given E (element) => element === SwapWall.Egg
194 | change E (self) => new SwapWall.Egg(self.timer)
195 |
196 | for(yz.directions) {
197 | _ => w
198 | @ .
199 | }
200 |
201 | for(yz.directions) {
202 | x => .
203 | @ E
204 |
205 | E => .
206 | @ E
207 |
208 | D => .
209 | @ E
210 | }
211 |
212 | given O (element) => element !== SwapWall
213 | for(yz.directions) {
214 | O => .
215 | @ D
216 | }
217 |
218 | element Egg {
219 | colour "lightgreen"
220 | emissive "green"
221 | arg timer 0
222 |
223 | given t (self) => self.timer-- > 0
224 | t => .
225 |
226 | for(yz.directions) {
227 | W .
228 | @ => .
229 | }
230 |
231 | @ => D
232 | }
233 |
234 | element Done {
235 | colour "grey"
236 | emissive "black"
237 | arg timer 0
238 |
239 | for(yz) {
240 | D .
241 | @ => .
242 |
243 | W .
244 | @ => .
245 |
246 | E .
247 | @ => .
248 |
249 | W .
250 | @ => .
251 |
252 | E .
253 | @ => .
254 | }
255 |
256 | @D => _@
257 | @W => _@
258 | @x => _.
259 | @? => ?@
260 | }
261 |
262 | }
263 |
264 | element SwapWallUp {
265 | colour "brown"
266 | category "T2Tile"
267 | arg timer 0
268 |
269 | given W (element) => element === SwapWallUp
270 | change W (self) => new SwapWallUp(self.timer)
271 | change w (self) => new SwapWallUp(self.timer + 1)
272 |
273 | given D (element) => element === SwapWallUp.Done
274 | change D (self) => new SwapWallUp.Done(self.timer)
275 |
276 | given E (element) => element === SwapWallUp.Egg
277 | change E (self) => new SwapWallUp.Egg(self.timer)
278 |
279 | pov(top) {
280 |
281 | for(xz.directions) {
282 | _ => w
283 | @ .
284 | }
285 |
286 | for(xz.directions) {
287 | x => .
288 | @ E
289 |
290 | E => .
291 | @ E
292 |
293 | D => .
294 | @ E
295 | }
296 |
297 | given O (element) => element !== SwapWallUp
298 | for(xz.directions) {
299 | O => .
300 | @ D
301 | }
302 | }
303 |
304 | element Egg pov(top) {
305 | colour "lightgreen"
306 | emissive "green"
307 | arg timer 0
308 |
309 | given t (self) => self.timer-- > 0
310 | t => .
311 |
312 | for(xz.directions) {
313 | W .
314 | @ => .
315 | }
316 |
317 | @ => D
318 | }
319 |
320 | element Done {
321 | colour "grey"
322 | emissive "black"
323 | arg timer 0
324 |
325 | for(xz) {
326 | @ => .
327 | D .
328 |
329 | @ => .
330 | W .
331 |
332 | E .
333 | @ => .
334 |
335 | W@ => ..
336 |
337 | E@ => ..
338 | }
339 |
340 | D @
341 | @ => _
342 |
343 | W @
344 | @ => _
345 |
346 | x .
347 | @ => _
348 |
349 | ? @
350 | @ => ?
351 | }
352 |
353 | }
354 |
355 | element Gravifloor {
356 | colour "brown"
357 | //category "T2Tile"
358 | //default true
359 |
360 | symbol G Gravifloor.Grower
361 | symbol B Gravifloor.Builder
362 | symbol W Gravifloor.Worker
363 | symbol b Gravifloor.Bullet
364 |
365 | @ => _
366 | _ @
367 |
368 | @ => _
369 | $ @
370 |
371 | @ => _
372 | G .
373 |
374 | @ => _
375 | B B
376 |
377 | @ => G
378 | * .
379 |
380 | @ => _
381 |
382 | element Grower {
383 | colour "brown"
384 | for(xz.directions) @_ => @$
385 | @ => B
386 | }
387 |
388 | element Builder {
389 | colour "brown"
390 | arg timer 1.0
391 | keep t (atom, space) => {
392 | if (atom.timer > 0) {
393 | atom.timer -= 0.05
394 | if (atom.timer < 0) atom.timer = 0
395 | atom.opacity = Math.floor(255 * atom.timer)
396 | SPACE.update(space)
397 | }
398 | }
399 | action @ => t
400 |
401 | given t (self) => self.timer <= 0
402 | t => W
403 | }
404 |
405 | element Worker {
406 | visible false
407 |
408 | maybe(0.001) {
409 | _ => b
410 | @ .
411 | }
412 |
413 | }
414 |
415 | element Bullet {
416 | colour "brown"
417 |
418 | arg timer 1.0
419 | keep t (atom, origin) => {
420 | if (atom.timer > 0) {
421 | atom.timer -= 0.025
422 | if (atom.timer < 0) atom.timer = 0
423 | atom.opacity = Math.floor(255 * atom.timer)
424 | SPACE.update(atom)
425 | }
426 | }
427 | action @ => t
428 |
429 | * => .
430 | @ _
431 |
432 | _ => @
433 | @ _
434 |
435 |
436 | }
437 | }
438 |
439 | element RainbowRabbit {
440 | colour "white"
441 | emissive "grey"
442 | //category "Rainbow"
443 | data id
444 | arg hue
445 |
446 | element Part {
447 | colour "white"
448 | emissive "grey"
449 | arg id
450 |
451 | given R (element, atom, self) => element === RainbowRabbit && atom.id === self.id
452 | @R => ..
453 | R@ => ..
454 |
455 | @ => .
456 | R .
457 |
458 | @ => .
459 | R .
460 |
461 | @ => _
462 | }
463 |
464 | // Init ID
465 | given i (self) => {
466 | return self.id === undefined
467 | }
468 | keep i (self) => {
469 | self.id = Math.random()
470 | if (self.hue === undefined) self.hue = Math.floor(Math.random() * 300)
471 | const colour = new THREE.Color("hsl(" + self.hue + ", 100%, 40%)")
472 | self.colour = {
473 | r: Math.floor(colour.r * 255),
474 | g: Math.floor(colour.g * 255),
475 | b: Math.floor(colour.b * 255),
476 | }
477 | self.emissive = self.colour
478 | }
479 | i => i
480 |
481 | // Grow body
482 | change P (self, atom) => {
483 | const part = new RainbowRabbit.Part(self.id)
484 | part.colour = self.colour
485 | part.emissive = self.emissive
486 | return part
487 | }
488 | @_ => .P
489 | _@ => P.
490 |
491 | _ => P
492 | @ .
493 |
494 | _ => P
495 | @ .
496 |
497 | // Die because can't grow
498 | given n (element, atom, self) => element !== RainbowRabbit.Part || atom.id !== self.id
499 | n => .
500 | @ _
501 | _ .
502 |
503 | n => .
504 | @ _
505 | _ .
506 |
507 | @n => _.
508 | _ .
509 |
510 | n@ => ._
511 | _ .
512 |
513 | // Fall down
514 | given P (element, atom, self) => element === RainbowRabbit.Part && atom.id === self.id
515 | P P _ _
516 | P@P => P_P
517 | ___ P@P
518 |
519 | // Move
520 | pov(right) {
521 |
522 | given H (self, atom, element) => {
523 | if (element !== RainbowRabbit) return false
524 | if ((self.hue < atom.hue)) {
525 | self.tempOtherHue = atom.hue
526 | return true
527 | }
528 | }
529 |
530 | change H (self) => new RainbowRabbit(self.tempOtherHue)
531 |
532 | @H => H@
533 | @.H => H.@
534 | maybe(1/2) any(z) @_ => _@
535 | }
536 |
537 | given R (element) => element === RainbowRabbit
538 | @ _
539 | R => .
540 |
541 | any(x) {
542 | P_P_ _P_P
543 | P@P_ => _P@P
544 | }
545 | }
546 |
547 | element Pulse {
548 | //category "T2Tile"
549 | //default true
550 | colour "brown"
551 |
552 | symbol H Pulse.Head
553 | symbol T Pulse.Tail
554 |
555 | ___ HHH
556 | _@_ => HTH
557 | ___ HHH
558 |
559 | @ => _
560 |
561 | element Head {
562 | colour "brown"
563 |
564 | any(xy.directions) {
565 | H .
566 | @_ => T@
567 | H .
568 | }
569 | }
570 |
571 | element Tail {
572 | colour "grey"
573 | emissive "black"
574 |
575 | given n (element) => element !== Pulse.Head && element !== Pulse.Tail && element !== Pulse
576 |
577 | all(xy.directions) {
578 | @n => _.
579 | }
580 | }
581 | }
582 |
583 | element Gravifull {
584 | //category "T2Tile"
585 | colour "pink"
586 | emissive "red"
587 | //default true
588 |
589 | symbol W Gravifull.Worker
590 | symbol B Gravifull.Builder
591 |
592 | // The "No Cheating" Method
593 | for(xyz.directions) @_ => .$
594 | @ => B
595 |
596 | // The "Cheating" Method
597 | /*behave () => {
598 | for (const space of spaces) {
599 | SPACE.set(space, new Gravifull.Worker(), Gravifull.Worker)
600 | }
601 | }*/
602 |
603 | element Builder {
604 | colour "pink"
605 | emissive "red"
606 | arg timer 1.0
607 |
608 | keep t (atom, space) => {
609 | if (atom.timer > 0) {
610 | atom.timer -= 0.5
611 | if (atom.timer < 0) atom.timer = 0
612 | atom.opacity = Math.floor(255 * atom.timer)
613 | SPACE.update(space)
614 | }
615 | }
616 | action @ => t
617 | //action any(xyz.directions) @$ => tt
618 |
619 | given t (self) => self.timer <= 0
620 | t => W
621 | }
622 |
623 | element Worker {
624 | visible false
625 |
626 | behave (sites, origin, Self) => {
627 | //print(sites)
628 | for (const site of sites) {
629 | const element = site.element
630 | if (element === Sandee) {
631 | const sandSites = site.sites
632 | const spaceBelow = sandSites[17]
633 | const elBelow = spaceBelow.element
634 | if (elBelow === Gravifull.Worker || elBelow === Wateree) {
635 | const atomBelow = spaceBelow.atom
636 | SPACE.set(spaceBelow, site.atom, Sandee)
637 | SPACE.set(site, atomBelow, elBelow)
638 | }
639 | else {
640 | const rando = Math.floor(Math.random() * 4)
641 | const slidesn = [18, 16, 55, 54][rando]
642 | const spaceSlide = sandSites[slidesn]
643 | const elSlide = spaceSlide.element
644 | if (elSlide === Gravifull.Worker || elSlide === Wateree) {
645 | const atomSlide = spaceSlide.atom
646 | SPACE.set(spaceSlide, site.atom, Sandee)
647 | SPACE.set(site, atomSlide, elSlide)
648 | }
649 | }
650 | }
651 | else if (element === Wateree) {
652 | const sandSites = site.sites
653 | const spaceBelow = sandSites[17]
654 | const elBelow = spaceBelow.element
655 | if (elBelow === Void) continue
656 | if (elBelow === Gravifull.Worker) {
657 | const atomBelow = spaceBelow.atom
658 | SPACE.set(spaceBelow, site.atom, Wateree)
659 | SPACE.set(site, atomBelow, Gravifull.Worker)
660 | }
661 | else {
662 | const rando = Math.floor(Math.random() * 4)
663 | const slidesn = [13, 11, 32, 37][rando]
664 | const spaceSlide = sandSites[slidesn]
665 | const elSlide = spaceSlide.element
666 | if (elSlide === Gravifull.Worker) {
667 | const atomSlide = spaceSlide.atom
668 | SPACE.set(spaceSlide, site.atom, Wateree)
669 | SPACE.set(site, atomSlide, Gravifull.Worker)
670 | }
671 | }
672 | }
673 | }
674 | }
675 | }
676 |
677 | }
678 |
679 | element Sandee {
680 | colour "#ffcc00"
681 | emissive "#ffa34d"
682 | //category "T2Tile"
683 | prop state SOLID
684 | prop temperature ROOM
685 |
686 | mimic(Gravifull.Worker)
687 | }
688 |
689 | element Wateree {
690 | colour "lightblue"
691 | emissive "blue"
692 | opacity 0.35
693 | //category "T2Tile"
694 | prop state LIQUID
695 | prop temperature COOL
696 |
697 | mimic(Gravifull.Worker)
698 | }
699 |
700 | element Huegene {
701 | colour "white"
702 | arg hue
703 | data coloured false
704 | opacity 0.1
705 | category "T2Tile"
706 | //default true
707 |
708 | // Cache hue RGB values
709 | given i () => !hueStepsInit
710 | keep i () => initHueStuff()
711 | action i => i
712 |
713 | // Pick the default hue if I haven't got one
714 | given h (self) => self.hue === undefined
715 | keep h (self) => self.hue = Math.round(HUE_DEFAULT)
716 | action h => h
717 |
718 | // Colour myself in with the correct RGB values
719 | given c (self) => !self.coloured
720 | keep c (origin, self) => {
721 | const offset = self.hue*3
722 | self.colour.r = HUE_RGBS[offset]
723 | self.colour.g = HUE_RGBS[offset+1]
724 | self.colour.b = HUE_RGBS[offset+2]
725 | self.emissive.r = self.colour.r
726 | self.emissive.g = self.colour.g
727 | self.emissive.b = self.colour.b
728 | SPACE.update(origin)
729 | self.coloured = true
730 | }
731 | action c => c
732 |
733 | // Mutate
734 | arg energy 1.0
735 | given e (self) => self.energy >= 1.0
736 | origin e
737 | change + (self) => {
738 | const mutation = Math.random() < 0.5? 1 : -1
739 | self.energy = 0.5
740 | return new Huegene(hueWrap(self.hue + mutation), 0.5)
741 | }
742 | any(xyz.rotations) {
743 | e_ => .+
744 | }
745 |
746 | // Photosynethesise
747 | keep e (self) => {
748 | self.energy += 0.1
749 | if (self.energy > 1.0) self.energy = 1.0
750 | }
751 | @ => e
752 |
753 | }
754 |
755 |
756 | element HuegeneEater {
757 | colour "white"
758 | arg hue
759 | arg energy 1.0
760 | data coloured false
761 | //opacity 0.05
762 | category "T2Tile"
763 |
764 | // Cache hue RGB values
765 | given i () => !hueStepsInit
766 | keep i () => initHueStuff()
767 | action i => i
768 |
769 | // Pick the default hue if I haven't got one
770 | given h (self) => self.hue === undefined
771 | keep h (self) => self.hue = Math.round(HUE_DEFAULT)
772 | action h => h
773 |
774 | // Colour myself in with the correct RGB values
775 | given c (self) => !self.coloured
776 | keep c (origin, self) => {
777 | const offset = self.hue*3
778 | self.colour.r = HUE_RGBS[offset]
779 | self.colour.g = HUE_RGBS[offset+1]
780 | self.colour.b = HUE_RGBS[offset+2]
781 | self.emissive.r = self.colour.r
782 | self.emissive.g = self.colour.g
783 | self.emissive.b = self.colour.b
784 | SPACE.update(origin)
785 | self.coloured = false
786 | }
787 | action c => c
788 | //default true
789 | // Eat / Move / Reproduce
790 | given H (element, atom, self) => {
791 | if (element !== Huegene) return false
792 | const diff = Math.min( Math.abs((self.hue - atom.hue)/ HUE_STEPS), Math.abs((self.hue-HUE_STEPS - atom.hue)/ HUE_STEPS) )
793 | return Math.random() > diff*3
794 | }
795 | given R (element, atom, self) => {
796 | if (element !== Empty) return false
797 | if (self.energy < 1.0) return false
798 | return true
799 | }
800 | given M (element, atom, self) => {
801 | self.energy -= 0.1
802 | if (element !== Empty) return false
803 | if (self.energy <= 0.0) return false
804 | return true
805 | }
806 | change E (atom, self) => {
807 | self.energy += atom.energy * 0.5
808 | if (self.energy > 1.0) self.energy = 1.0
809 | return self
810 | }
811 | change R (atom, self) => {
812 | const mutation = Math.random() < 0.5? 1 : -1
813 | self.energy = 0.5
814 | return new HuegeneEater(hueWrap(self.hue + mutation), 0.5)
815 | }
816 | change M (self) => {
817 | return self
818 | }
819 | any(xyz.directions) {
820 | @H => _E
821 | @R => .R
822 | @M => _M
823 | }
824 |
825 | given D (self) => self.energy <= 0.0
826 | D => _
827 |
828 | //@ => _
829 |
830 |
831 | }
832 |
833 | `
834 |
835 | let hueStepsInit = false
836 | let HUE_STEPS = 50
837 | let HUE_DEFAULT = Math.round(3 * HUE_STEPS / 4)
838 | let HUE_RGBS = new Uint8Array(HUE_STEPS * 3)
839 | const initHueStuff = () => {
840 | for (let i = 0; i < HUE_STEPS; i++) {
841 | const colour = new THREE.Color()
842 | colour.setHSL(i / HUE_STEPS, 0.9, 0.4)
843 | HUE_RGBS[i*3] = Math.floor(colour.r * 255)
844 | HUE_RGBS[i*3 + 1] = Math.floor(colour.g * 255)
845 | HUE_RGBS[i*3 + 2] = Math.floor(colour.b * 255)
846 | }
847 | hueStepsInit = true
848 | }
849 |
850 | const hueWrap = (n) => {
851 | if (n >= HUE_STEPS) return hueWrap(n - HUE_STEPS)
852 | if (n < 0) return hueWrap(n + HUE_STEPS)
853 | return n
854 | }
855 |
856 |
857 |
858 | //DROPPER_OVERRIDE = true
--------------------------------------------------------------------------------
/Source/Elements/Temperature.js:
--------------------------------------------------------------------------------
1 |
2 | const COLD = 0 // ... -10C
3 | const CHILLY = 1 // -10C to 0C
4 | const COOL = 2 // 0C to 15C
5 | const ROOM = 3 // 15C to 30C
6 | const BODY = 4 // 30C to 40C
7 | const WARM = 5 // 40C to 100C
8 | const HOT = 6 // 100C ...
9 |
10 | SpaceTode`
11 |
12 | element Temperature {
13 |
14 | //============//
15 | // Init Cache //
16 | //============//
17 | given i (selfElement) => selfElement.statesCache === undefined
18 | keep i (selfElement) => {
19 | const cache = {...(selfElement.states? selfElement.states() : {})}
20 | const chancesCache = {}
21 | for (const tempKey in cache) {
22 | const temp = cache[tempKey]
23 | if (temp.is(Array)) {
24 | cache[tempKey] = temp[0]
25 | chancesCache[tempKey] = temp[1]
26 | }
27 | }
28 | selfElement.statesChancesCache = chancesCache
29 | selfElement.statesCache = cache
30 | }
31 | i => i
32 |
33 | //==============//
34 | // Change State //
35 | //==============//
36 | select s (element) => element
37 | keep s (space, selfElement, selected) => {
38 | const selfTargets = selfElement.statesCache
39 | if (selfTargets === undefined) return
40 |
41 | let otherTemp = selected.temperature
42 | if (otherTemp === undefined) otherTemp = ROOM
43 |
44 | const selfTarget = selfTargets[otherTemp]
45 | if (selfTarget === undefined) return
46 |
47 | const selfChances = selfElement.statesChancesCache
48 | const selfChance = selfChances[otherTemp]
49 | if (selfChance !== undefined && Math.random() > selfChance) return
50 |
51 | SPACE.setAtom(space, new selfTarget(), selfTarget)
52 | }
53 |
54 | action any(xyz.directions) @s => s.
55 |
56 | given N (self, atom) => self !== atom
57 | N => .
58 | }
59 |
60 | `
--------------------------------------------------------------------------------
/Source/Elements/Testing.js:
--------------------------------------------------------------------------------
1 | SpaceTode`
2 |
3 | element SquishSand {
4 |
5 | colour "#ffcc00"
6 | emissive "#ffa34d"
7 | category "Weird"
8 | symbol D SquishSand.Double
9 | symbol S SquishSand.Single
10 | @ => D
11 |
12 | element Double any(xz) {
13 | //default true
14 | //category "Structure"
15 | colour "#ffa34d"
16 | emissive "#ffa34d"
17 |
18 | @ => _
19 | _ @
20 |
21 | @ => _
22 | _ _ S S
23 |
24 | @ => _
25 | _ @
26 |
27 | @ => _
28 | _ @
29 |
30 | _ => S
31 | @ S
32 |
33 | }
34 |
35 | element Single any(xz) {
36 | colour "#ffcc00"
37 | emissive "#ffa34d"
38 |
39 | @ => _
40 | _ @
41 |
42 | _ .
43 | @ => _
44 | $ D
45 |
46 | @ => D
47 | D @
48 |
49 | @ => .
50 | _ _ . .
51 |
52 | @ => .
53 | $ $ . .
54 |
55 | @ => D
56 | D @
57 |
58 | @ => D
59 | D @
60 |
61 | @ => _
62 | _ @
63 |
64 | @ => _
65 | _ @
66 |
67 | }
68 |
69 | }
70 |
71 | element Rainblock {
72 |
73 | category "Weird"
74 |
75 | // Setup
76 | {
77 | data init false
78 | given i (self) => !self.init
79 | keep i (self, origin) => {
80 | self.init = true
81 | const hue = Math.floor(Math.random() * 360)
82 | const colour = new THREE.Color("hsl("+hue+", 100%, 50%)")
83 | self.colour.r = Math.round(colour.r * 255)
84 | self.colour.g = Math.round(colour.g * 255)
85 | self.colour.b = Math.round(colour.b * 255)
86 | self.emissive.r = Math.round(colour.r * 255)
87 | self.emissive.g = Math.round(colour.g * 255)
88 | self.emissive.b = Math.round(colour.b * 255)
89 | SPACE.update(origin)
90 | }
91 | i => i
92 | }
93 |
94 | // Move
95 | {
96 | given R (self, element, atom) => element === Rainblock && atom.colour.r > self.colour.r
97 | select R (atom) => atom
98 | change R (selected) => selected
99 | @R => R@
100 |
101 |
102 | /*given r (self, element, atom) => element === Rainblock && atom.colour.r < self.colour.r
103 | select r (atom) => atom
104 | change r (selected) => selected
105 | r@ => @r*/
106 |
107 | pov(right) {
108 | given G (self, element, atom) => element === Rainblock && atom.colour.g > self.colour.g
109 | select G (atom) => atom
110 | change G (selected) => selected
111 | @G => G@
112 |
113 |
114 | /*given g (self, element, atom) => element === Rainblock && atom.colour.g < self.colour.g
115 | select g (atom) => atom
116 | change g (selected) => selected
117 | g@ => @g*/
118 | }
119 |
120 | given B (self, element, atom) => element === Rainblock && atom.colour.b > self.colour.b
121 | select B (atom) => atom
122 | change B (selected) => selected
123 | B => @
124 | @ B
125 |
126 |
127 | /*given b (self, element, atom) => element === Rainblock && atom.colour.b < self.colour.b
128 | select b (atom) => atom
129 | change b (selected) => selected
130 | @ => b
131 | b @*/
132 |
133 | /*@ => _
134 | _ @*/
135 |
136 | any(xyz.directions) {
137 | @_ => _@
138 | }
139 | }
140 |
141 | }
142 |
143 | element CrystalOld {
144 |
145 | category "Weird"
146 | colour "lightblue"
147 | emissive "blue"
148 |
149 | maybe(1/100) any(xz.directions) {
150 | ..... $...$
151 | ..@.. => ..$..
152 | ..... $...$
153 | }
154 |
155 |
156 |
157 | }
158 |
159 | element Brancher {
160 | category "Weird"
161 |
162 | @ => _
163 | _ @
164 |
165 | symbol G Brancher.Grower
166 | symbol S Sand
167 |
168 | @ => G
169 | * .
170 |
171 | @ => _
172 |
173 | element Grower {
174 |
175 | colour "rgb(70, 255, 128)"
176 | colour "rgb(35, 200, 100)"
177 |
178 | G => .
179 | @ .
180 |
181 | all(xz.directions) {
182 | G => .
183 | @ .
184 | }
185 |
186 | maybe(0.3) any(xz.directions) {
187 | _@_ => $.$
188 | }
189 |
190 | /*maybe(0.3) any(xz.directions) {
191 | _ _ => $ $
192 | @ .
193 | }*/
194 |
195 | /*any(xz.directions) {
196 | _ => $
197 | @ .
198 | }*/
199 |
200 | maybe(1/20) {
201 | _ => $
202 | @ .
203 | }
204 |
205 | }
206 |
207 | }
208 |
209 | element Labyrinth {
210 | category "Weird"
211 |
212 | data countBuffer 0
213 |
214 | // Reset buffer
215 | keep r (self) => self.countBuffer = 0
216 | action @ => r
217 |
218 | // Count neighbours
219 | given c (element, Self, self) => {
220 | if (element === Self) self.countBuffer++
221 | return true
222 | }
223 |
224 | action {
225 | ccc ...
226 | c@c => ...
227 | ccc ...
228 | }
229 |
230 | pov(right) action {
231 | ccc ...
232 | c@c => ...
233 | ccc ...
234 | }
235 |
236 | pov(top) action {
237 | ccc ...
238 | c@c => ...
239 | ccc ...
240 | }
241 |
242 | // Die
243 | given d (self) => self.countBuffer > 4
244 | d => _
245 |
246 | // Grow
247 | origin g
248 | given g (self) => self.countBuffer === 2
249 | for(xyz.directions) g_ => .$
250 |
251 | }
252 |
253 | element SparkLife {
254 | category "Weird"
255 | colour "rgb(255, 255, 70)"
256 | data countBuffer 0
257 |
258 | // Reset buffer
259 | keep r (self) => self.countBuffer = 0
260 | action @ => r
261 |
262 | // Count neighbours
263 | given c (element, Self, self) => {
264 | if (element === Self) self.countBuffer++
265 | return false
266 | }
267 |
268 | all(xyz.others) @c => ..
269 |
270 | // Die
271 | given d (self) => self.countBuffer >= 5 || self.countBuffer <= 2
272 | d => _
273 |
274 | // Grow
275 | origin g
276 | given g (self) => self.countBuffer >= 0 && self.countBuffer <= Infinity
277 | for(xyz.directions) g_ => .$
278 |
279 | }
280 |
281 | element GameOfLife {
282 | category "Weird"
283 | //category "Video"
284 | colour "brown"
285 |
286 | // Globals
287 | symbol D GameOfLife.Dead
288 | symbol A GameOfLife.Alive
289 |
290 | // Setup: Fill up the universe
291 | all(xy.directions) @_ => @$
292 |
293 | // Then become a dead or alive space
294 | maybe(0.9) @ => D
295 | @ => A
296 |
297 | element Dead {
298 | opacity 1
299 | //visible false
300 | colour "white"
301 | emissive "grey"
302 | data tally 0
303 | //category "Video"
304 |
305 | // Reset tally
306 | keep r (self) => self.tally = 0
307 | action @ => r
308 |
309 | // Count alive neighbours
310 | given a (self, element) => {
311 | if (element === GameOfLife.Alive) {
312 | self.tally++
313 | }
314 | return false
315 | }
316 | action {
317 | aaa ...
318 | a@a => ...
319 | aaa ...
320 | }
321 |
322 | // Live!
323 | given l (self) => self.tally === 3
324 | l => A
325 | }
326 |
327 | element Alive {
328 | //category "Video"
329 | prop override true
330 | data tally 0
331 | colour "grey"
332 | emissive "black"
333 |
334 | // Reset tally
335 | keep r (self) => self.tally = 0
336 | action @ => r
337 |
338 | // Count alive neighbours
339 | given a (self, element) => {
340 | if (element === GameOfLife.Alive) {
341 | self.tally++
342 | }
343 | return false
344 | }
345 | action {
346 | aaa ...
347 | a@a => ...
348 | aaa ...
349 | }
350 |
351 | // Survive
352 | given s (self) => self.tally >= 2 && self.tally <= 3
353 | s => .
354 |
355 | // Die
356 | @ => D
357 |
358 | }
359 |
360 | }
361 |
362 |
363 | element SpreadWater {
364 | category "Weird"
365 | //category "Video"
366 | data direction 0
367 | colour "lightblue"
368 | emissive "blue"
369 | opacity 1
370 |
371 | prop state LIQUID
372 | prop temperature COOL
373 | @ => _
374 | _ @
375 |
376 | for(xz.directions) {
377 | @ => _
378 | _ @
379 | }
380 |
381 | given D (self, transformationNumber, element) => element === Empty && self.direction === transformationNumber
382 | all(xz.directions) {
383 | @D => _@
384 | }
385 |
386 | keep N (self) => self.direction = Math.floor(Math.random() * 4)
387 | @ => N
388 | }
389 |
390 |
391 |
392 | element MomentumSand {
393 | category "Weird"
394 | //category "Video"
395 | emissive "#ffa34d"
396 | colour "#fc0"
397 | data movement 0
398 |
399 | keep g (self) => {
400 | self.movement += 0.05
401 | if (self.movement > 1) self.movement = 1
402 | }
403 | action {
404 | @ => g
405 | _ .
406 | }
407 |
408 | given F (element, self) => {
409 | if (element !== Empty && element !== SpreadWater) return false
410 | return self.movement > 2/3
411 | }
412 | select F (atom) => atom
413 | change F (selected) => selected
414 |
415 | given f (element, self) => {
416 | if (element !== Empty && element !== SpreadWater) return false
417 | return self.movement > 1/3
418 | }
419 | select f (atom) => atom
420 | change f (selected) => selected
421 | @ => _
422 | _ F
423 | F @
424 |
425 | @ => f
426 | f @
427 |
428 | given b (Self, element) => element === Self
429 | keep b (atom, self) => {
430 | if (atom.movement < self.movement) {
431 | atom.movement = self.movement
432 | }
433 | }
434 | action {
435 | @ => .
436 | b b
437 | }
438 |
439 | given s (element, self) => {
440 | if (element !== Empty && element !== SpreadWater) return false
441 | return self.movement > 0.3
442 | }
443 | select s (atom) => atom
444 | change s (selected) => selected
445 |
446 | change m (self) => {
447 | self.movement -= 0.2
448 | if (self.movement < 0) self.movement = 0
449 | return self
450 | }
451 |
452 |
453 | any(xz.directions) {
454 | @ => s
455 | s m
456 | }
457 |
458 | }
459 |
460 | `;
461 |
--------------------------------------------------------------------------------
/Source/Elements/TwoTwoTwoTwo.js:
--------------------------------------------------------------------------------
1 | SpaceTode`
2 |
3 | element TwoTwoTwoTwoOne {
4 | emissive "rgb(255, 0,0)"
5 | colour "rgb(255, 100, 100)"
6 | category "Stream"
7 | symbol 2 TwoTwoTwoTwoTwo
8 |
9 | keep W () => {
10 | const currentTime = performance.now()
11 | if (!window.lastTime) {
12 | window.lastTime = currentTime
13 | return
14 | }
15 | const deltaTime = currentTime - window.lastTime
16 | if (deltaTime < 200) {
17 | return
18 | }
19 | window.lastTime = currentTime
20 | const wordIndex = window.wordIndex || 0
21 | const word = words[wordIndex]
22 | window.wordIndex = (wordIndex + 1) % words.length
23 | for (let i = 0; i < 4; i++) {
24 | const letter = word[i]
25 | const coordinates = convertLetterIntoCoordinates(letter)
26 | for (const coordinate of coordinates) {
27 | const [x, y] = coordinate
28 | const space = WORLD.selectSpace(world, -10 + x + i*7, 10 - y, 18)
29 | SPACE.setAtom(space, new Pixel())
30 | }
31 | }
32 | }
33 |
34 | maybe(0.5) {
35 | @ => _
36 | _ @
37 |
38 | @ => _
39 | 2 @
40 |
41 | action @ => W
42 |
43 | @ => 2
44 | }
45 |
46 | }
47 |
48 | element Pixel {
49 | colour "black"
50 |
51 | keep C (space, self) => {
52 | const FADE_AMOUNT = 2
53 | self.colour.r = Math.min(255, self.colour.r + FADE_AMOUNT)
54 | self.colour.g = Math.min(255, self.colour.g + FADE_AMOUNT)
55 | self.colour.b = Math.min(255, self.colour.b + FADE_AMOUNT)
56 | self.emissive.r = Math.min(255, self.emissive.r + FADE_AMOUNT)
57 | self.emissive.g = Math.min(255, self.emissive.g + FADE_AMOUNT)
58 | self.emissive.b = Math.min(255, self.emissive.b + FADE_AMOUNT)
59 | SPACE.update(space)
60 | }
61 |
62 | action @ => C
63 |
64 | pov(right) {
65 | @_ => _@
66 | }
67 |
68 | maybe(0.01) {
69 | @ => _
70 | }
71 | }
72 |
73 | element TwoTwoTwoTwoTwo {
74 | emissive "rgb(0, 0, 255)"
75 | colour "rgb(100, 100, 255)"
76 |
77 | symbol 1 TwoTwoTwoTwoOne
78 |
79 | maybe(0.5) {
80 | _ @
81 | @ => _
82 |
83 | @ _
84 | 1 => @
85 |
86 | @ => 1
87 | }
88 | }
89 | `;
90 |
91 | const alphabet = {
92 | A: [
93 | // @prettier-ignore
94 | "..#..",
95 | ".#.#.",
96 | "#####",
97 | "#...#",
98 | "#...#",
99 | ],
100 | B: [
101 | // @prettier-ignore
102 | "####.",
103 | "#...#",
104 | "####.",
105 | "#...#",
106 | "####.",
107 | ],
108 | C: [
109 | // @prettier-ignore
110 | ".###.",
111 | "#....",
112 | "#....",
113 | "#....",
114 | ".###.",
115 | ],
116 | D: [
117 | // @prettier-ignore
118 | "####.",
119 | "#...#",
120 | "#...#",
121 | "#...#",
122 | "####.",
123 | ],
124 | E: [
125 | // @prettier-ignore
126 | "#####",
127 | "#....",
128 | "####.",
129 | "#....",
130 | "#####",
131 | ],
132 | F: [
133 | // @prettier-ignore
134 | "#####",
135 | "#....",
136 | "####.",
137 | "#....",
138 | "#....",
139 | ],
140 | G: [
141 | // @prettier-ignore
142 | ".###.",
143 | "#....",
144 | "#.###",
145 | "#...#",
146 | ".###.",
147 | ],
148 | H: [
149 | // @prettier-ignore
150 | "#...#",
151 | "#...#",
152 | "#####",
153 | "#...#",
154 | "#...#",
155 | ],
156 | I: [
157 | // @prettier-ignore
158 | "#####",
159 | "..#..",
160 | "..#..",
161 | "..#..",
162 | "#####",
163 | ],
164 | J: [
165 | // @prettier-ignore
166 | "..###",
167 | "...#.",
168 | "...#.",
169 | "#..#.",
170 | ".##..",
171 | ],
172 | K: [
173 | // @prettier-ignore
174 | "#..#.",
175 | "#.#..",
176 | "##...",
177 | "#.#..",
178 | "#..#.",
179 | ],
180 | L: [
181 | // @prettier-ignore
182 | "#....",
183 | "#....",
184 | "#....",
185 | "#....",
186 | "#####",
187 | ],
188 | M: [
189 | // @prettier-ignore
190 | "#...#",
191 | "##.##",
192 | "#.#.#",
193 | "#...#",
194 | "#...#",
195 | ],
196 | N: [
197 | // @prettier-ignore
198 | "#...#",
199 | "##..#",
200 | "#.#.#",
201 | "#..##",
202 | "#...#",
203 | ],
204 | O: [
205 | // @prettier-ignore
206 | ".###.",
207 | "#...#",
208 | "#...#",
209 | "#...#",
210 | ".###.",
211 | ],
212 | P: [
213 | // @prettier-ignore
214 | "####.",
215 | "#...#",
216 | "####.",
217 | "#....",
218 | "#....",
219 | ],
220 | Q: [
221 | // @prettier-ignore
222 | ".###.",
223 | "#...#",
224 | "#...#",
225 | "#.##.",
226 | ".##.#",
227 | ],
228 | R: [
229 | // @prettier-ignore
230 | "####.",
231 | "#...#",
232 | "####.",
233 | "#.#..",
234 | "#..#.",
235 | ],
236 | S: [
237 | // @prettier-ignore
238 | ".###.",
239 | "#....",
240 | ".###.",
241 | "...#.",
242 | "###..",
243 | ],
244 | T: [
245 | // @prettier-ignore
246 | "#####",
247 | "..#..",
248 | "..#..",
249 | "..#..",
250 | "..#..",
251 | ],
252 | U: [
253 | // @prettier-ignore
254 | "#...#",
255 | "#...#",
256 | "#...#",
257 | "#...#",
258 | ".###.",
259 | ],
260 | V: [
261 | // @prettier-ignore
262 | "#...#",
263 | "#...#",
264 | "#...#",
265 | ".#.#.",
266 | "..#..",
267 | ],
268 | W: [
269 | // @prettier-ignore
270 | "#...#",
271 | "#...#",
272 | "#.#.#",
273 | "##.##",
274 | "#...#",
275 | ],
276 | X: [
277 | // @prettier-ignore
278 | "#...#",
279 | ".#.#.",
280 | "..#..",
281 | ".#.#.",
282 | "#...#",
283 | ],
284 | Y: [
285 | // @prettier-ignore
286 | "#...#",
287 | "#...#",
288 | ".###.",
289 | "..#..",
290 | "..#..",
291 | ],
292 | Z: [
293 | // @prettier-ignore
294 | "#####",
295 | "...#.",
296 | "..#..",
297 | ".#...",
298 | "#####",
299 | ],
300 | };
301 |
302 | // console.log(Object.values(alphabet).length);
303 |
304 | function convertLetterIntoCoordinates(letter) {
305 | const letterArray = alphabet[letter];
306 | const coordinates = [];
307 | for (let y = 0; y < letterArray.length; y++) {
308 | for (let x = 0; x < letterArray[y].length; x++) {
309 | if (letterArray[y][x] === "#") {
310 | coordinates.push([x, y]);
311 | }
312 | }
313 | }
314 | return coordinates;
315 | }
316 |
317 | // console.log(convertLetterIntoCoordinates("Z"));
318 |
319 | const wordsString = `ABET
320 | ABLE
321 | ABLY
322 | ABUT
323 | ACAI
324 | ACED
325 | ACES
326 | ACHE
327 | ACHY
328 | ACID
329 | ACME
330 | ACNE
331 | ACRE
332 | ACTS
333 | ADDS
334 | AEON
335 | AFAR
336 | AFRO
337 | AGED
338 | AGES
339 | AGOG
340 | AHEM
341 | AIDE
342 | AILS
343 | AIMS
344 | AIRS
345 | AIRY
346 | AJAR
347 | AKIN
348 | ALAS
349 | ALLY
350 | ALMS
351 | ALOE
352 | ALSO
353 | ALTO
354 | ALUM
355 | AMEN
356 | AMID
357 | AMMO
358 | AMOK
359 | AMPS
360 | ANDS
361 | ANEW
362 | ANKH
363 | ANON
364 | ANTI
365 | ANTS
366 | APES
367 | APEX
368 | APPS
369 | AQUA
370 | ARCH
371 | ARCS
372 | AREA
373 | ARIA
374 | ARID
375 | ARKS
376 | ARMS
377 | ARMY
378 | ARSE
379 | ARTS
380 | ARTY
381 | ASHY
382 | ASKS
383 | ATOM
384 | ATOP
385 | AUNT
386 | AURA
387 | AUTO
388 | AVID
389 | AVOW
390 | AWAY
391 | AWED
392 | AWES
393 | AWLS
394 | AWRY
395 | AXED
396 | AXES
397 | AXIS
398 | AXLE
399 | BABA
400 | BABE
401 | BABY
402 | BACH
403 | BACK
404 | BADS
405 | BAGS
406 | BAIL
407 | BAIT
408 | BAKE
409 | BALD
410 | BALE
411 | BALK
412 | BALL
413 | BALM
414 | BAND
415 | BANE
416 | BANG
417 | BANK
418 | BANS
419 | BARB
420 | BARD
421 | BARE
422 | BARF
423 | BARK
424 | BARN
425 | BARS
426 | BASE
427 | BASH
428 | BASK
429 | BASS
430 | BAST
431 | BATH
432 | BATS
433 | BAUD
434 | BAWL
435 | BAYS
436 | BEAD
437 | BEAK
438 | BEAM
439 | BEAN
440 | BEAR
441 | BEAT
442 | BEAU
443 | BECK
444 | BEDS
445 | BEEF
446 | BEEN
447 | BEEP
448 | BEER
449 | BEES
450 | BEET
451 | BEGS
452 | BELL
453 | BELT
454 | BEND
455 | BENT
456 | BERG
457 | BERM
458 | BEST
459 | BETA
460 | BETS
461 | BEVY
462 | BEYS
463 | BIAS
464 | BIBS
465 | BIDE
466 | BIDS
467 | BIFF
468 | BIKE
469 | BILE
470 | BILK
471 | BILL
472 | BIND
473 | BIOS
474 | BIRD
475 | BITE
476 | BITS
477 | BLAB
478 | BLAH
479 | BLEB
480 | BLED
481 | BLEW
482 | BLIP
483 | BLOB
484 | BLOC
485 | BLOG
486 | BLOT
487 | BLOW
488 | BLUE
489 | BLUR
490 | BOAR
491 | BOAS
492 | BOAT
493 | BOBS
494 | BODE
495 | BODS
496 | BODY
497 | BOGS
498 | BOGY
499 | BOIL
500 | BOLA
501 | BOLD
502 | BOLO
503 | BOLT
504 | BOMB
505 | BOND
506 | BONE
507 | BONG
508 | BONK
509 | BONY
510 | BOOK
511 | BOOM
512 | BOON
513 | BOOR
514 | BOOS
515 | BOOT
516 | BORE
517 | BORN
518 | BOSS
519 | BOTH
520 | BOTS
521 | BOUT
522 | BOWL
523 | BOWS
524 | BOXY
525 | BOYO
526 | BOYS
527 | BOZO
528 | BRAG
529 | BRAN
530 | BRAS
531 | BRAT
532 | BRAY
533 | BRED
534 | BREW
535 | BRIE
536 | BRIG
537 | BRIM
538 | BRIS
539 | BRIT
540 | BROS
541 | BROW
542 | BUCK
543 | BUDS
544 | BUFF
545 | BUGS
546 | BULB
547 | BULK
548 | BULL
549 | BUMP
550 | BUMS
551 | BUND
552 | BUNG
553 | BUNK
554 | BUNS
555 | BUNT
556 | BUOY
557 | BURB
558 | BURG
559 | BURL
560 | BURN
561 | BURP
562 | BURR
563 | BURY
564 | BUSH
565 | BUSK
566 | BUST
567 | BUSY
568 | BUTT
569 | BUYS
570 | BUZZ
571 | BYES
572 | BYTE
573 | CABS
574 | CAFE
575 | CAFF
576 | CAGE
577 | CAKE
578 | CALF
579 | CALL
580 | CALM
581 | CAME
582 | CAMO
583 | CAMP
584 | CANE
585 | CANS
586 | CAPE
587 | CAPO
588 | CAPS
589 | CARB
590 | CARD
591 | CARE
592 | CARP
593 | CARS
594 | CART
595 | CASE
596 | CASH
597 | CASK
598 | CAST
599 | CATS
600 | CAVE
601 | CAWS
602 | CAYS
603 | CEDE
604 | CELL
605 | CELS
606 | CELT
607 | CENT
608 | CESS
609 | CHAD
610 | CHAI
611 | CHAP
612 | CHAR
613 | CHAT
614 | CHEF
615 | CHEW
616 | CHIC
617 | CHIN
618 | CHIP
619 | CHIT
620 | CHOP
621 | CHOW
622 | CHUB
623 | CHUG
624 | CHUM
625 | CIAO
626 | CITE
627 | CITY
628 | CLAD
629 | CLAM
630 | CLAN
631 | CLAP
632 | CLAW
633 | CLAY
634 | CLEF
635 | CLIP
636 | CLOD
637 | CLOG
638 | CLOP
639 | CLOT
640 | CLUB
641 | CLUE
642 | COAL
643 | COAT
644 | COAX
645 | COBS
646 | COCA
647 | COCO
648 | CODA
649 | CODE
650 | CODS
651 | COED
652 | COGS
653 | COIL
654 | COIN
655 | COKE
656 | COLA
657 | COLD
658 | COLE
659 | COLT
660 | COMA
661 | COMB
662 | COME
663 | COMP
664 | CONE
665 | CONS
666 | COOK
667 | COOL
668 | COOP
669 | COOS
670 | COPE
671 | COPS
672 | COPY
673 | CORD
674 | CORE
675 | CORK
676 | CORN
677 | COST
678 | COSY
679 | COTS
680 | COUP
681 | COVE
682 | COWL
683 | COWS
684 | COZY
685 | CRAB
686 | CRAG
687 | CRAM
688 | CRAP
689 | CRAW
690 | CREW
691 | CRIB
692 | CRIT
693 | CROC
694 | CROP
695 | CROW
696 | CRUD
697 | CRUX
698 | CUBE
699 | CUBS
700 | CUDS
701 | CUED
702 | CUES
703 | CUFF
704 | CULL
705 | CULT
706 | CUPS
707 | CURB
708 | CURD
709 | CURE
710 | CURL
711 | CURT
712 | CUSP
713 | CUSS
714 | CUTE
715 | CUTS
716 | CYAN
717 | CYST
718 | CZAR
719 | DABS
720 | DADA
721 | DADS
722 | DAFT
723 | DAME
724 | DAMN
725 | DAMP
726 | DAMS
727 | DANK
728 | DARE
729 | DARK
730 | DARN
731 | DART
732 | DASH
733 | DATA
734 | DATE
735 | DAWN
736 | DAYS
737 | DAZE
738 | DEAD
739 | DEAF
740 | DEAL
741 | DEAN
742 | DEAR
743 | DEBT
744 | DECK
745 | DEED
746 | DEEM
747 | DEEP
748 | DEER
749 | DEFT
750 | DEFY
751 | DELI
752 | DELL
753 | DELT
754 | DEMO
755 | DENS
756 | DENT
757 | DERM
758 | DESK
759 | DEWS
760 | DEWY
761 | DIAL
762 | DICE
763 | DIED
764 | DIES
765 | DIET
766 | DIGS
767 | DILL
768 | DIME
769 | DIMS
770 | DINE
771 | DING
772 | DINK
773 | DINO
774 | DINT
775 | DIPS
776 | DIRE
777 | DIRT
778 | DISC
779 | DISH
780 | DISK
781 | DISS
782 | DIVA
783 | DIVE
784 | DOCK
785 | DOCS
786 | DODO
787 | DOER
788 | DOES
789 | DOFF
790 | DOGS
791 | DOJO
792 | DOLE
793 | DOLL
794 | DOLT
795 | DOME
796 | DONE
797 | DONG
798 | DOOM
799 | DOOR
800 | DOPE
801 | DORK
802 | DORM
803 | DORY
804 | DOSE
805 | DOTE
806 | DOTH
807 | DOTS
808 | DOUR
809 | DOVE
810 | DOWN
811 | DOXY
812 | DOZE
813 | DOZY
814 | DRAB
815 | DRAG
816 | DRAM
817 | DRAW
818 | DRAY
819 | DREW
820 | DRIP
821 | DROP
822 | DRUG
823 | DRUM
824 | DRYS
825 | DUAL
826 | DUBS
827 | DUCK
828 | DUCT
829 | DUDE
830 | DUDS
831 | DUEL
832 | DUES
833 | DUET
834 | DUFF
835 | DUKE
836 | DULL
837 | DULY
838 | DUMB
839 | DUMP
840 | DUNE
841 | DUNG
842 | DUNK
843 | DUNS
844 | DUOS
845 | DUPE
846 | DUSK
847 | DUST
848 | DUTY
849 | DYAD
850 | DYED
851 | DYER
852 | DYES
853 | EACH
854 | EARL
855 | EARN
856 | EARS
857 | EASE
858 | EAST
859 | EASY
860 | EATS
861 | EAVE
862 | EBBS
863 | ECHO
864 | EDDY
865 | EDGE
866 | EDGY
867 | EDIT
868 | EELS
869 | EGGS
870 | EGGY
871 | EGOS
872 | ELKS
873 | ELMS
874 | ELSE
875 | EMIT
876 | EMMY
877 | EMUS
878 | ENDS
879 | ENVY
880 | EONS
881 | EPEE
882 | EPIC
883 | ERAS
884 | ERRS
885 | ETCH
886 | EURO
887 | EVEN
888 | EVER
889 | EVES
890 | EVIL
891 | EWES
892 | EXAM
893 | EXEC
894 | EXIT
895 | EXON
896 | EXPO
897 | EYED
898 | EYES
899 | FABS
900 | FACE
901 | FACT
902 | FADE
903 | FADS
904 | FAIL
905 | FAIR
906 | FAKE
907 | FALL
908 | FAME
909 | FANG
910 | FANS
911 | FARE
912 | FARM
913 | FART
914 | FAST
915 | FATE
916 | FATS
917 | FAUN
918 | FAVA
919 | FAVE
920 | FAWN
921 | FAZE
922 | FEAR
923 | FEAT
924 | FEED
925 | FEEL
926 | FEES
927 | FEET
928 | FELL
929 | FELT
930 | FEND
931 | FENS
932 | FERN
933 | FESS
934 | FEST
935 | FETA
936 | FETE
937 | FEUD
938 | FIAT
939 | FIBS
940 | FIFE
941 | FIGS
942 | FILE
943 | FILL
944 | FILM
945 | FILO
946 | FIND
947 | FINE
948 | FINK
949 | FINS
950 | FIRE
951 | FIRM
952 | FIRS
953 | FISH
954 | FIST
955 | FITS
956 | FIVE
957 | FIZZ
958 | FLAB
959 | FLAG
960 | FLAK
961 | FLAM
962 | FLAN
963 | FLAP
964 | FLAT
965 | FLAW
966 | FLAX
967 | FLAY
968 | FLEA
969 | FLED
970 | FLEE
971 | FLEW
972 | FLEX
973 | FLIP
974 | FLIT
975 | FLOC
976 | FLOE
977 | FLOG
978 | FLOP
979 | FLOW
980 | FLUB
981 | FLUE
982 | FLUS
983 | FLUX
984 | FOAL
985 | FOAM
986 | FOBS
987 | FOCI
988 | FOES
989 | FOGS
990 | FOGY
991 | FOIL
992 | FOLD
993 | FOLK
994 | FOND
995 | FONT
996 | FOOD
997 | FOOL
998 | FOOT
999 | FOPS
1000 | FORD
1001 | FORE
1002 | FORK
1003 | FORM
1004 | FORT
1005 | FOUL
1006 | FOUR
1007 | FOWL
1008 | FOXY
1009 | FRAG
1010 | FRAT
1011 | FRAY
1012 | FREE
1013 | FRET
1014 | FRIG
1015 | FROG
1016 | FROM
1017 | FUEL
1018 | FUCK
1019 | FUGU
1020 | FULL
1021 | FUME
1022 | FUND
1023 | FUNK
1024 | FURL
1025 | FURS
1026 | FURY
1027 | FUSE
1028 | FUSS
1029 | FUTZ
1030 | FUZZ
1031 | GAFF
1032 | GAGS
1033 | GAIN
1034 | GAIT
1035 | GALA
1036 | GALE
1037 | GALL
1038 | GALS
1039 | GAME
1040 | GANG
1041 | GAPE
1042 | GAPS
1043 | GARB
1044 | GASH
1045 | GASP
1046 | GATE
1047 | GAVE
1048 | GAWK
1049 | GAYS
1050 | GAZE
1051 | GEAR
1052 | GEEK
1053 | GEES
1054 | GELS
1055 | GEMS
1056 | GENE
1057 | GENS
1058 | GENT
1059 | GERM
1060 | GETS
1061 | GHAT
1062 | GHEE
1063 | GIFT
1064 | GIGS
1065 | GILD
1066 | GILL
1067 | GILT
1068 | GINS
1069 | GIRD
1070 | GIRL
1071 | GIST
1072 | GITS
1073 | GIVE
1074 | GLAD
1075 | GLAM
1076 | GLEE
1077 | GLEN
1078 | GLIB
1079 | GLOB
1080 | GLOM
1081 | GLOP
1082 | GLOW
1083 | GLUE
1084 | GLUG
1085 | GLUM
1086 | GLUT
1087 | GNAR
1088 | GNAT
1089 | GNAW
1090 | GOAD
1091 | GOAL
1092 | GOAT
1093 | GOBS
1094 | GOBY
1095 | GODS
1096 | GOER
1097 | GOES
1098 | GOLD
1099 | GOLF
1100 | GONE
1101 | GONG
1102 | GOOD
1103 | GOOF
1104 | GOON
1105 | GOOP
1106 | GOOS
1107 | GORE
1108 | GORY
1109 | GOSH
1110 | GOTH
1111 | GOUT
1112 | GOWN
1113 | GRAB
1114 | GRAD
1115 | GRAM
1116 | GRAN
1117 | GRAY
1118 | GREW
1119 | GREY
1120 | GRID
1121 | GRIM
1122 | GRIN
1123 | GRIP
1124 | GRIT
1125 | GROG
1126 | GROW
1127 | GRUB
1128 | GUFF
1129 | GULF
1130 | GULL
1131 | GULP
1132 | GUMS
1133 | GUNK
1134 | GUNS
1135 | GURU
1136 | GUSH
1137 | GUST
1138 | GUTS
1139 | GUYS
1140 | GYMS
1141 | GYRE
1142 | GYRO
1143 | HACK
1144 | HAGS
1145 | HAIL
1146 | HAIR
1147 | HALF
1148 | HALL
1149 | HALO
1150 | HALT
1151 | HAMS
1152 | HAND
1153 | HANG
1154 | HANK
1155 | HAPS
1156 | HARD
1157 | HARE
1158 | HARK
1159 | HARM
1160 | HARP
1161 | HART
1162 | HASH
1163 | HATE
1164 | HATH
1165 | HATS
1166 | HAUL
1167 | HAVE
1168 | HAWK
1169 | HAWS
1170 | HAYS
1171 | HAZE
1172 | HAZY
1173 | HEAD
1174 | HEAL
1175 | HEAP
1176 | HEAR
1177 | HEAT
1178 | HECK
1179 | HEED
1180 | HEEL
1181 | HEFT
1182 | HEIR
1183 | HELD
1184 | HELL
1185 | HELM
1186 | HELP
1187 | HEMP
1188 | HEMS
1189 | HENS
1190 | HERB
1191 | HERD
1192 | HERE
1193 | HERO
1194 | HERS
1195 | HEST
1196 | HEWN
1197 | HEWS
1198 | HICK
1199 | HIDE
1200 | HIGH
1201 | HIKE
1202 | HILL
1203 | HILT
1204 | HIND
1205 | HINT
1206 | HIPS
1207 | HIRE
1208 | HISS
1209 | HITS
1210 | HIVE
1211 | HIYA
1212 | HOAR
1213 | HOAX
1214 | HOBO
1215 | HOCK
1216 | HOED
1217 | HOES
1218 | HOGS
1219 | HOLD
1220 | HOLE
1221 | HOLO
1222 | HOLT
1223 | HOLY
1224 | HOME
1225 | HONE
1226 | HONK
1227 | HOOD
1228 | HOOF
1229 | HOOK
1230 | HOOP
1231 | HOOT
1232 | HOPE
1233 | HOPS
1234 | HORN
1235 | HOSE
1236 | HOST
1237 | HOUR
1238 | HOVE
1239 | HOWL
1240 | HUBS
1241 | HUCK
1242 | HUED
1243 | HUES
1244 | HUFF
1245 | HUGE
1246 | HUGS
1247 | HULA
1248 | HULK
1249 | HULL
1250 | HUMP
1251 | HUMS
1252 | HUNG
1253 | HUNK
1254 | HUNT
1255 | HURL
1256 | HURT
1257 | HUSH
1258 | HUSK
1259 | HUTS
1260 | HYMN
1261 | HYPE
1262 | HYPO
1263 | ICED
1264 | ICES
1265 | ICKY
1266 | ICON
1267 | IDEA
1268 | IDLE
1269 | IDLY
1270 | IDOL
1271 | IFFY
1272 | ILLS
1273 | IMPS
1274 | INCH
1275 | INFO
1276 | INKS
1277 | INKY
1278 | INNS
1279 | INTO
1280 | IONS
1281 | IOTA
1282 | IRIS
1283 | IRKS
1284 | IRON
1285 | ISLE
1286 | ISMS
1287 | ITCH
1288 | ITEM
1289 | JABS
1290 | JACK
1291 | JADE
1292 | JAIL
1293 | JAKE
1294 | JAMB
1295 | JAMS
1296 | JAPE
1297 | JARS
1298 | JAVA
1299 | JAWA
1300 | JAWS
1301 | JAYS
1302 | JAZZ
1303 | JEAN
1304 | JEEP
1305 | JEER
1306 | JEEZ
1307 | JELL
1308 | JERK
1309 | JEST
1310 | JETS
1311 | JIBE
1312 | JIBS
1313 | JIGS
1314 | JILT
1315 | JINK
1316 | JINX
1317 | JIVE
1318 | JOBS
1319 | JOCK
1320 | JOGS
1321 | JOIN
1322 | JOKE
1323 | JOLT
1324 | JOTS
1325 | JOWL
1326 | JOYS
1327 | JUDO
1328 | JUGS
1329 | JUJU
1330 | JUKE
1331 | JUMP
1332 | JUNK
1333 | JURY
1334 | JUST
1335 | JUTE
1336 | JUTS
1337 | KALE
1338 | KEEL
1339 | KEEN
1340 | KEEP
1341 | KEGS
1342 | KELP
1343 | KEPT
1344 | KETO
1345 | KEYS
1346 | KHAN
1347 | KHAT
1348 | KICK
1349 | KIDS
1350 | KILL
1351 | KILN
1352 | KILO
1353 | KILT
1354 | KIND
1355 | KING
1356 | KIPS
1357 | KISS
1358 | KITE
1359 | KITS
1360 | KIWI
1361 | KNEE
1362 | KNEW
1363 | KNIT
1364 | KNOB
1365 | KNOT
1366 | KNOW
1367 | KOAN
1368 | KOOK
1369 | KOTO
1370 | LABS
1371 | LACE
1372 | LACK
1373 | LACY
1374 | LADS
1375 | LADY
1376 | LAGS
1377 | LAID
1378 | LAIN
1379 | LAIR
1380 | LAKE
1381 | LAMA
1382 | LAMB
1383 | LAME
1384 | LAMP
1385 | LAND
1386 | LANE
1387 | LAPS
1388 | LARD
1389 | LARK
1390 | LASH
1391 | LASS
1392 | LAST
1393 | LATE
1394 | LAUD
1395 | LAVA
1396 | LAWN
1397 | LAWS
1398 | LAYS
1399 | LAZE
1400 | LAZY
1401 | LEAD
1402 | LEAF
1403 | LEAK
1404 | LEAN
1405 | LEAP
1406 | LEAS
1407 | LEEK
1408 | LEER
1409 | LEET
1410 | LEFT
1411 | LEGS
1412 | LEND
1413 | LENS
1414 | LENT
1415 | LESS
1416 | LEST
1417 | LEWD
1418 | LIAR
1419 | LIBS
1420 | LICE
1421 | LICK
1422 | LIDS
1423 | LIED
1424 | LIEN
1425 | LIER
1426 | LIES
1427 | LIEU
1428 | LIFE
1429 | LIFT
1430 | LIKE
1431 | LILT
1432 | LILY
1433 | LIMA
1434 | LIMB
1435 | LIME
1436 | LIMO
1437 | LIMP
1438 | LINE
1439 | LING
1440 | LINK
1441 | LINT
1442 | LION
1443 | LIPS
1444 | LISP
1445 | LIST
1446 | LITE
1447 | LIVE
1448 | LOAD
1449 | LOAF
1450 | LOAM
1451 | LOAN
1452 | LOBE
1453 | LOBS
1454 | LOCH
1455 | LOCK
1456 | LOCO
1457 | LODE
1458 | LOFT
1459 | LOGE
1460 | LOGO
1461 | LOGS
1462 | LOIN
1463 | LONE
1464 | LONG
1465 | LOOK
1466 | LOOM
1467 | LOON
1468 | LOOP
1469 | LOOS
1470 | LOOT
1471 | LOPS
1472 | LORD
1473 | LORE
1474 | LOSE
1475 | LOSS
1476 | LOST
1477 | LOTH
1478 | LOTS
1479 | LOUD
1480 | LOUT
1481 | LOVE
1482 | LOWS
1483 | LUBE
1484 | LUCK
1485 | LUFF
1486 | LUGS
1487 | LULL
1488 | LUMP
1489 | LUNE
1490 | LUNG
1491 | LURE
1492 | LURK
1493 | LUSH
1494 | LUST
1495 | LUTE
1496 | LUVS
1497 | LYNX
1498 | LYRE
1499 | MACE
1500 | MACH
1501 | MACK
1502 | MACS
1503 | MADE
1504 | MAGE
1505 | MAGI
1506 | MAGS
1507 | MAID
1508 | MAIL
1509 | MAIM
1510 | MAIN
1511 | MAKE
1512 | MAKI
1513 | MALE
1514 | MALL
1515 | MALT
1516 | MAMA
1517 | MANE
1518 | MANS
1519 | MANY
1520 | MAPS
1521 | MARE
1522 | MARK
1523 | MARS
1524 | MART
1525 | MASH
1526 | MASK
1527 | MASS
1528 | MAST
1529 | MATE
1530 | MATH
1531 | MATS
1532 | MAUL
1533 | MAWS
1534 | MAXI
1535 | MAYO
1536 | MAZE
1537 | MAZY
1538 | MEAD
1539 | MEAL
1540 | MEAN
1541 | MEAT
1542 | MEEK
1543 | MEET
1544 | MEGA
1545 | MELD
1546 | MELT
1547 | MEMO
1548 | MEND
1549 | MENU
1550 | MEOW
1551 | MERE
1552 | MESA
1553 | MESH
1554 | MESS
1555 | META
1556 | METE
1557 | MEWL
1558 | MEWS
1559 | MICA
1560 | MICE
1561 | MICS
1562 | MIDS
1563 | MILD
1564 | MILE
1565 | MILK
1566 | MILL
1567 | MIME
1568 | MIND
1569 | MINE
1570 | MINI
1571 | MINK
1572 | MINT
1573 | MINX
1574 | MIRE
1575 | MISO
1576 | MISS
1577 | MIST
1578 | MITE
1579 | MOAN
1580 | MOAT
1581 | MOBS
1582 | MOCK
1583 | MODE
1584 | MODS
1585 | MOJO
1586 | MOLD
1587 | MOLE
1588 | MOLT
1589 | MOMS
1590 | MONK
1591 | MONO
1592 | MOOD
1593 | MOON
1594 | MOOR
1595 | MOOS
1596 | MOOT
1597 | MOPE
1598 | MOPS
1599 | MORE
1600 | MORN
1601 | MOSH
1602 | MOSS
1603 | MOST
1604 | MOTE
1605 | MOTH
1606 | MOVE
1607 | MOWS
1608 | MUCH
1609 | MUCK
1610 | MUDS
1611 | MUFF
1612 | MUGS
1613 | MULE
1614 | MULL
1615 | MUMS
1616 | MUON
1617 | MURK
1618 | MUSE
1619 | MUSH
1620 | MUSK
1621 | MUST
1622 | MUTE
1623 | MUTT
1624 | MYTH
1625 | NAAN
1626 | NABS
1627 | NAGS
1628 | NAIL
1629 | NAME
1630 | NANA
1631 | NANS
1632 | NAPE
1633 | NAPS
1634 | NARC
1635 | NARD
1636 | NARY
1637 | NAVY
1638 | NAYS
1639 | NEAR
1640 | NEAT
1641 | NECK
1642 | NEED
1643 | NEEM
1644 | NEON
1645 | NERD
1646 | NESS
1647 | NEST
1648 | NETS
1649 | NEWS
1650 | NEWT
1651 | NEXT
1652 | NIBS
1653 | NICE
1654 | NICK
1655 | NIGH
1656 | NINE
1657 | NITE
1658 | NOBS
1659 | NODE
1660 | NODS
1661 | NOEL
1662 | NOIR
1663 | NONE
1664 | NOOK
1665 | NOON
1666 | NOPE
1667 | NORI
1668 | NORM
1669 | NOSE
1670 | NOSH
1671 | NOSY
1672 | NOTE
1673 | NOUN
1674 | NOVA
1675 | NUBS
1676 | NUDE
1677 | NUKE
1678 | NULL
1679 | NUMB
1680 | NUNS
1681 | NUTS
1682 | OAFS
1683 | OAKS
1684 | OAKY
1685 | OARS
1686 | OATH
1687 | OATS
1688 | OBEY
1689 | OBIT
1690 | OBOE
1691 | ODDS
1692 | ODES
1693 | ODOR
1694 | OGLE
1695 | OGRE
1696 | OILS
1697 | OILY
1698 | OINK
1699 | OKAY
1700 | OKRA
1701 | OLDS
1702 | OMEN
1703 | OMIT
1704 | ONCE
1705 | ONES
1706 | ONLY
1707 | ONTO
1708 | ONUS
1709 | ONYX
1710 | OOPS
1711 | OOZE
1712 | OOZY
1713 | OPAL
1714 | OPEN
1715 | OPTS
1716 | OPUS
1717 | ORAL
1718 | ORBS
1719 | ORCA
1720 | ORES
1721 | ORGY
1722 | ORZO
1723 | OUCH
1724 | OURS
1725 | OUST
1726 | OUTS
1727 | OVAL
1728 | OVEN
1729 | OVER
1730 | OVUM
1731 | OWED
1732 | OWES
1733 | OWLS
1734 | OWNS
1735 | PACE
1736 | PACK
1737 | PACT
1738 | PADS
1739 | PAGE
1740 | PAID
1741 | PAIL
1742 | PAIN
1743 | PAIR
1744 | PALE
1745 | PALL
1746 | PALM
1747 | PALP
1748 | PALS
1749 | PANE
1750 | PANG
1751 | PANS
1752 | PANT
1753 | PAPA
1754 | PAPS
1755 | PARA
1756 | PARE
1757 | PARK
1758 | PARS
1759 | PART
1760 | PASS
1761 | PAST
1762 | PATE
1763 | PATH
1764 | PATS
1765 | PAVE
1766 | PAWN
1767 | PAWS
1768 | PAYS
1769 | PEAK
1770 | PEAL
1771 | PEAR
1772 | PEAS
1773 | PEAT
1774 | PECK
1775 | PECS
1776 | PEED
1777 | PEEK
1778 | PEEL
1779 | PEEP
1780 | PEER
1781 | PEES
1782 | PEGS
1783 | PELT
1784 | PENS
1785 | PENT
1786 | PEON
1787 | PERK
1788 | PERM
1789 | PERP
1790 | PESO
1791 | PEST
1792 | PETS
1793 | PEWS
1794 | PHEW
1795 | PICK
1796 | PICS
1797 | PIED
1798 | PIER
1799 | PIES
1800 | PIGS
1801 | PIKA
1802 | PIKE
1803 | PILE
1804 | PILL
1805 | PINE
1806 | PING
1807 | PINK
1808 | PINS
1809 | PINT
1810 | PIPE
1811 | PISS
1812 | PITA
1813 | PITH
1814 | PITS
1815 | PITY
1816 | PLAN
1817 | PLAT
1818 | PLAY
1819 | PLEA
1820 | PLEB
1821 | PLED
1822 | PLEX
1823 | PLOD
1824 | PLOP
1825 | PLOT
1826 | PLOW
1827 | PLOY
1828 | PLUG
1829 | PLUM
1830 | PLUS
1831 | POCK
1832 | PODS
1833 | POEM
1834 | POET
1835 | POKE
1836 | POKY
1837 | POLE
1838 | POLL
1839 | POLO
1840 | POLY
1841 | POMP
1842 | POND
1843 | PONG
1844 | PONY
1845 | POOF
1846 | POOL
1847 | POOP
1848 | POOR
1849 | POPE
1850 | POPS
1851 | PORE
1852 | PORK
1853 | PORT
1854 | POSE
1855 | POSH
1856 | POSY
1857 | POTS
1858 | POUF
1859 | POUR
1860 | POUT
1861 | PRAM
1862 | PRAY
1863 | PREP
1864 | PREY
1865 | PREZ
1866 | PRIG
1867 | PRIM
1868 | PROB
1869 | PROD
1870 | PROF
1871 | PROG
1872 | PROM
1873 | PROP
1874 | PROS
1875 | PROW
1876 | PUBS
1877 | PUCK
1878 | PUDS
1879 | PUFF
1880 | PUGS
1881 | PUKE
1882 | PULL
1883 | PULP
1884 | PUMA
1885 | PUMP
1886 | PUNK
1887 | PUNS
1888 | PUNT
1889 | PUNY
1890 | PUPA
1891 | PUPS
1892 | PURE
1893 | PURL
1894 | PURR
1895 | PUSH
1896 | PUSS
1897 | PUTS
1898 | PUTT
1899 | PUTZ
1900 | PYRE
1901 | PYRO
1902 | QUAD
1903 | QUID
1904 | QUIP
1905 | QUIT
1906 | QUIZ
1907 | RACE
1908 | RACK
1909 | RACY
1910 | RADS
1911 | RAFT
1912 | RAGA
1913 | RAGE
1914 | RAGS
1915 | RAID
1916 | RAIL
1917 | RAIN
1918 | RAJA
1919 | RAKE
1920 | RAKU
1921 | RALE
1922 | RAMP
1923 | RAMS
1924 | RANG
1925 | RANK
1926 | RANT
1927 | RAPS
1928 | RAPT
1929 | RARE
1930 | RASH
1931 | RASP
1932 | RATE
1933 | RATH
1934 | RATS
1935 | RAVE
1936 | RAYS
1937 | RAZE
1938 | RAZZ
1939 | READ
1940 | REAL
1941 | REAM
1942 | REAP
1943 | REAR
1944 | REDO
1945 | REED
1946 | REEF
1947 | REEK
1948 | REEL
1949 | REFS
1950 | REIN
1951 | RELY
1952 | REMS
1953 | REND
1954 | RENT
1955 | REPO
1956 | REPP
1957 | REPS
1958 | REST
1959 | RIBS
1960 | RICE
1961 | RICH
1962 | RIDE
1963 | RIDS
1964 | RIFE
1965 | RIFF
1966 | RIFT
1967 | RIGS
1968 | RILE
1969 | RILL
1970 | RIME
1971 | RIMS
1972 | RIND
1973 | RING
1974 | RINK
1975 | RIOT
1976 | RIPE
1977 | RIPS
1978 | RISE
1979 | RISK
1980 | RITE
1981 | RITZ
1982 | ROAD
1983 | ROAM
1984 | ROAN
1985 | ROAR
1986 | ROBE
1987 | ROBS
1988 | ROCK
1989 | RODE
1990 | RODS
1991 | ROES
1992 | ROIL
1993 | ROLE
1994 | ROLL
1995 | ROMP
1996 | ROMS
1997 | ROOF
1998 | ROOK
1999 | ROOM
2000 | ROOS
2001 | ROOT
2002 | ROPE
2003 | ROPY
2004 | ROSE
2005 | ROSY
2006 | ROTE
2007 | ROTI
2008 | ROTO
2009 | ROTS
2010 | ROUT
2011 | ROUX
2012 | ROVE
2013 | ROWS
2014 | RUBE
2015 | RUBS
2016 | RUBY
2017 | RUCK
2018 | RUDE
2019 | RUED
2020 | RUES
2021 | RUFF
2022 | RUGS
2023 | RUIN
2024 | RULE
2025 | RUMP
2026 | RUMS
2027 | RUNE
2028 | RUNG
2029 | RUNS
2030 | RUNT
2031 | RUSE
2032 | RUSH
2033 | RUST
2034 | RUTS
2035 | SACK
2036 | SACS
2037 | SAFE
2038 | SAGA
2039 | SAGE
2040 | SAGO
2041 | SAGS
2042 | SAID
2043 | SAIL
2044 | SAKE
2045 | SAKI
2046 | SALE
2047 | SALT
2048 | SAME
2049 | SAND
2050 | SANE
2051 | SANG
2052 | SANK
2053 | SAPS
2054 | SARI
2055 | SASH
2056 | SASS
2057 | SATE
2058 | SAVE
2059 | SAWN
2060 | SAWS
2061 | SAYS
2062 | SCAB
2063 | SCAD
2064 | SCAM
2065 | SCAN
2066 | SCAR
2067 | SCAT
2068 | SCOT
2069 | SCUD
2070 | SCUM
2071 | SEAL
2072 | SEAM
2073 | SEAR
2074 | SEAS
2075 | SEAT
2076 | SECT
2077 | SEED
2078 | SEEK
2079 | SEEM
2080 | SEEN
2081 | SEEP
2082 | SEER
2083 | SEES
2084 | SELF
2085 | SELL
2086 | SEMI
2087 | SEND
2088 | SENT
2089 | SEPT
2090 | SETS
2091 | SEWN
2092 | SEWS
2093 | SHAM
2094 | SHED
2095 | SHEW
2096 | SHIM
2097 | SHIN
2098 | SHIP
2099 | SHIT
2100 | SHIV
2101 | SHOD
2102 | SHOE
2103 | SHOO
2104 | SHOP
2105 | SHOT
2106 | SHOW
2107 | SHUN
2108 | SHUT
2109 | SIBS
2110 | SICK
2111 | SIDE
2112 | SIFT
2113 | SIGH
2114 | SIGN
2115 | SILK
2116 | SILL
2117 | SILO
2118 | SILT
2119 | SINE
2120 | SING
2121 | SINK
2122 | SINS
2123 | SIPS
2124 | SIRE
2125 | SIRS
2126 | SITE
2127 | SITS
2128 | SIZE
2129 | SKEW
2130 | SKID
2131 | SKIM
2132 | SKIN
2133 | SKIP
2134 | SKIS
2135 | SKIT
2136 | SLAB
2137 | SLAG
2138 | SLAM
2139 | SLAP
2140 | SLAT
2141 | SLAW
2142 | SLAY
2143 | SLED
2144 | SLEW
2145 | SLID
2146 | SLIM
2147 | SLIP
2148 | SLIT
2149 | SLOB
2150 | SLOE
2151 | SLOG
2152 | SLOP
2153 | SLOT
2154 | SLOW
2155 | SLUG
2156 | SLUM
2157 | SMOG
2158 | SMUG
2159 | SNAG
2160 | SNAP
2161 | SNIP
2162 | SNIT
2163 | SNOB
2164 | SNOT
2165 | SNOW
2166 | SNUB
2167 | SNUG
2168 | SOAK
2169 | SOAP
2170 | SOAR
2171 | SOBA
2172 | SOBS
2173 | SOCK
2174 | SODA
2175 | SODS
2176 | SOFA
2177 | SOFT
2178 | SOIL
2179 | SOLD
2180 | SOLE
2181 | SOLO
2182 | SOME
2183 | SONG
2184 | SONS
2185 | SOON
2186 | SOOT
2187 | SOPS
2188 | SORE
2189 | SORT
2190 | SOUL
2191 | SOUP
2192 | SOUR
2193 | SOWN
2194 | SOWS
2195 | SOYA
2196 | SPAM
2197 | SPAN
2198 | SPAR
2199 | SPAS
2200 | SPAT
2201 | SPAY
2202 | SPEC
2203 | SPED
2204 | SPEW
2205 | SPIN
2206 | SPIT
2207 | SPOT
2208 | SPRY
2209 | SPUD
2210 | SPUN
2211 | SPUR
2212 | STAB
2213 | STAG
2214 | STAR
2215 | STAT
2216 | STAY
2217 | STEM
2218 | STEP
2219 | STEW
2220 | STIR
2221 | STOP
2222 | STOW
2223 | STUB
2224 | STUD
2225 | STUN
2226 | STYE
2227 | SUBS
2228 | SUCH
2229 | SUCK
2230 | SUED
2231 | SUES
2232 | SUET
2233 | SUIT
2234 | SULK
2235 | SUMO
2236 | SUMP
2237 | SUMS
2238 | SUNG
2239 | SUNK
2240 | SUNS
2241 | SUPS
2242 | SURE
2243 | SURF
2244 | SUSS
2245 | SWAB
2246 | SWAG
2247 | SWAM
2248 | SWAN
2249 | SWAP
2250 | SWAT
2251 | SWAY
2252 | SWIG
2253 | SWIM
2254 | SWUM
2255 | SYNC
2256 | TABS
2257 | TACH
2258 | TACK
2259 | TACO
2260 | TACT
2261 | TAGS
2262 | TAIL
2263 | TAKE
2264 | TALC
2265 | TALE
2266 | TALK
2267 | TALL
2268 | TAME
2269 | TAMP
2270 | TANG
2271 | TANK
2272 | TANS
2273 | TAPE
2274 | TAPS
2275 | TARE
2276 | TARN
2277 | TARO
2278 | TARP
2279 | TARS
2280 | TART
2281 | TASK
2282 | TAUT
2283 | TAXI
2284 | TEAK
2285 | TEAL
2286 | TEAM
2287 | TEAR
2288 | TEAS
2289 | TEAT
2290 | TECH
2291 | TEEM
2292 | TEEN
2293 | TEES
2294 | TEFF
2295 | TELE
2296 | TELL
2297 | TEMP
2298 | TEND
2299 | TENT
2300 | TERM
2301 | TERN
2302 | TEST
2303 | TEXT
2304 | THAN
2305 | THAT
2306 | THAW
2307 | THEE
2308 | THEM
2309 | THEN
2310 | THEY
2311 | THIN
2312 | THIS
2313 | THOU
2314 | THRU
2315 | THUD
2316 | THUG
2317 | THUS
2318 | TICK
2319 | TIDE
2320 | TIDY
2321 | TIED
2322 | TIER
2323 | TIES
2324 | TIFF
2325 | TIKI
2326 | TILE
2327 | TILL
2328 | TILT
2329 | TIME
2330 | TINE
2331 | TING
2332 | TINS
2333 | TINT
2334 | TINY
2335 | TIPS
2336 | TIRE
2337 | TITS
2338 | TOAD
2339 | TODE
2340 | TOED
2341 | TOES
2342 | TOFU
2343 | TOGA
2344 | TOIL
2345 | TOKE
2346 | TOLD
2347 | TOLE
2348 | TOLL
2349 | TOMB
2350 | TOME
2351 | TONE
2352 | TONG
2353 | TOOK
2354 | TOOL
2355 | TOON
2356 | TOOT
2357 | TOPS
2358 | TORE
2359 | TORN
2360 | TORT
2361 | TORY
2362 | TOSS
2363 | TOTE
2364 | TOTS
2365 | TOUR
2366 | TOUT
2367 | TOWN
2368 | TOWS
2369 | TOYS
2370 | TRAM
2371 | TRAP
2372 | TRAY
2373 | TREE
2374 | TREK
2375 | TREY
2376 | TRIG
2377 | TRIM
2378 | TRIO
2379 | TRIP
2380 | TROD
2381 | TROT
2382 | TSAR
2383 | TUBA
2384 | TUBE
2385 | TUBS
2386 | TUCK
2387 | TUFF
2388 | TUFT
2389 | TUGS
2390 | TUMS
2391 | TUNA
2392 | TUNE
2393 | TURD
2394 | TURF
2395 | TURK
2396 | TURN
2397 | TUSH
2398 | TUSK
2399 | TUTS
2400 | TUTU
2401 | TWEE
2402 | TWIG
2403 | TWIN
2404 | TWIT
2405 | TWOS
2406 | TYKE
2407 | TYPE
2408 | TYPO
2409 | UDON
2410 | UGLY
2411 | UMPS
2412 | UNDO
2413 | UNIT
2414 | UNTO
2415 | UPON
2416 | URGE
2417 | URNS
2418 | USED
2419 | USER
2420 | USES
2421 | VAIL
2422 | VAIN
2423 | VAMP
2424 | VANE
2425 | VANS
2426 | VARY
2427 | VASE
2428 | VAST
2429 | VATS
2430 | VEAL
2431 | VEER
2432 | VEIL
2433 | VEIN
2434 | VEND
2435 | VENT
2436 | VERB
2437 | VERT
2438 | VERY
2439 | VEST
2440 | VETO
2441 | VETS
2442 | VIAL
2443 | VIBE
2444 | VICE
2445 | VIDS
2446 | VIED
2447 | VIES
2448 | VIEW
2449 | VILE
2450 | VIMS
2451 | VINE
2452 | VINO
2453 | VISA
2454 | VISE
2455 | VITA
2456 | VIVA
2457 | VOID
2458 | VOLE
2459 | VOLT
2460 | VOTE
2461 | VOWS
2462 | WACK
2463 | WADE
2464 | WADS
2465 | WAFT
2466 | WAGE
2467 | WAGS
2468 | WAIF
2469 | WAIL
2470 | WAIT
2471 | WAKE
2472 | WALK
2473 | WALL
2474 | WAND
2475 | WANE
2476 | WANT
2477 | WARD
2478 | WARE
2479 | WARM
2480 | WARN
2481 | WARP
2482 | WARS
2483 | WART
2484 | WARY
2485 | WASH
2486 | WASP
2487 | WATT
2488 | WAVE
2489 | WAVY
2490 | WAXY
2491 | WAYS
2492 | WEAK
2493 | WEAN
2494 | WEAR
2495 | WEBS
2496 | WEDS
2497 | WEED
2498 | WEEK
2499 | WEEN
2500 | WEEP
2501 | WELL
2502 | WENT
2503 | WERE
2504 | WEST
2505 | WHAT
2506 | WHEN
2507 | WHOM
2508 | WIDE
2509 | WIFE
2510 | WILD
2511 | WILL
2512 | WILT
2513 | WIND
2514 | WINE
2515 | WING
2516 | WINS
2517 | WIPE
2518 | WIRE
2519 | WISE
2520 | WISH
2521 | WITH
2522 | WOLF
2523 | WOOD
2524 | WOOL
2525 | WORD
2526 | WORE
2527 | WORK
2528 | WORM
2529 | WORN
2530 | WRAP
2531 | YARD
2532 | YARN
2533 | YEAH
2534 | YEAR
2535 | YOGA
2536 | YOUR
2537 | ZERO
2538 | ZINC
2539 | ZONE
2540 | ZOOM`;
2541 |
2542 | const words = wordsString.split("\n");
2543 | // console.log(words);
2544 |
--------------------------------------------------------------------------------
/Source/Elements/Weird.js:
--------------------------------------------------------------------------------
1 | SpaceTode`
2 |
3 | element RainbowSand {
4 | category "Weird"
5 |
6 | data ready false
7 | given i (self) => !self.ready
8 | keep i (space, self, time) => {
9 | const colour = new THREE.Color("hsl(" + time + ", 100%, 50%)")
10 | self.colour.r = colour.r * 255
11 | self.colour.g = colour.g * 255
12 | self.colour.b = colour.b * 255
13 | self.emissive.r = colour.r * 255
14 | self.emissive.g = colour.g * 255
15 | self.emissive.b = colour.b * 255
16 | self.ready = true
17 | SPACE.update(space)
18 | }
19 | action i => i
20 |
21 | any(xz.directions) {
22 | @ => _
23 | _ @
24 |
25 | @ => _
26 | _ @
27 | }
28 | }
29 |
30 | element RainglowSand {
31 | category "Weird"
32 |
33 | prop colours {
34 | const arr = []
35 | for (let i = 0; i < 360; i++) {
36 | const colour = new THREE.Color("hsl(" + i + ", 100%, 50%)")
37 | const cs = [colour.r, colour.g, colour.b].map(c => Math.floor(c * 255))
38 | arr.push(cs)
39 |
40 | }
41 | return arr
42 | }
43 | data ready false
44 | data offset 0
45 | keep i (space, self, time, Self) => {
46 | if (!self.ready) {
47 | self.offset = time
48 | self.ready = true
49 | }
50 | const [r, g, b] = Self.colours[(time + self.offset) % 360]
51 | self.colour.r = r
52 | self.colour.g = g
53 | self.colour.b = b
54 | self.emissive.r = r
55 | self.emissive.g = g
56 | self.emissive.b = b
57 | SPACE.update(space)
58 | }
59 | action @ => i
60 |
61 | any(xz.directions) {
62 | @ => _
63 | _ @
64 |
65 | @ => _
66 | _ @
67 |
68 | @ => @
69 | }
70 | }
71 |
72 | element Glooper {
73 |
74 | colour "rgb(110, 120, 200)"
75 | category "Weird"
76 |
77 | arg direction "down"
78 | arg directionTime 0
79 |
80 | keep c (self) => {
81 | if (self.direction == "down") {
82 | self.colour.r = 110
83 | self.colour.g = 120
84 | self.colour.b = 200
85 | }
86 | else {
87 | self.colour.r = 110
88 | self.colour.g = 200
89 | self.colour.b = 1
90 | }
91 | }
92 | action @ => c
93 |
94 | keep u (self, time) => {
95 | self.direction = "up"
96 | self.directionTime = time
97 | }
98 | action {
99 | @ => u
100 | x .
101 | }
102 |
103 | keep d (self, time) => {
104 | self.direction = "down"
105 | self.directionTime = time
106 | }
107 | action {
108 | x .
109 | @ => d
110 | }
111 |
112 | given D (Self, element, self, atom) => {
113 | return Self === element && self.directionTime < atom.directionTime
114 | }
115 | keep D (self, atom) => {
116 | self.direction = atom.direction
117 | self.directionTime = atom.directionTime
118 | }
119 | for(xyz.directions) {
120 | @D => .D
121 | }
122 |
123 | for(xyz.directions) {
124 | @_$ => _@.
125 | }
126 |
127 | for(xyz.rotations) {
128 | @ => _
129 | _$ @.
130 | }
131 |
132 | action @ => <
133 | for(xyz.directions) {
134 | action @$ => >.
135 | }
136 | < => _
137 |
138 | given d (self, element) => element === Empty && self.direction == "down"
139 | // set to 0.2 to make it move down
140 | maybe(0.2) {
141 | @ => _
142 | d @
143 | }
144 |
145 | given u (self, element) => element === Empty && self.direction == "up"
146 | // set to 0.2 to make it move up
147 | maybe(0.2) {
148 | u => @
149 | @ _
150 | }
151 |
152 | any(xz.directions) {
153 | @ => _
154 | $d .@
155 |
156 | $u .@
157 | @ => _
158 | }
159 |
160 | }
161 |
162 | element AntiGlooper {
163 |
164 | colour "rgb(200, 120, 110)"
165 | category "Weird"
166 |
167 | arg direction "down"
168 | arg directionTime 0
169 |
170 | symbol G Glooper
171 | symbol E Eater
172 |
173 | for(xyz.directions) {
174 | @G => EE
175 | }
176 |
177 | mimic(Glooper)
178 |
179 | }
180 |
181 | element GloopGridder {
182 |
183 | colour "rgb(50, 150, 50)"
184 | category "Weird"
185 |
186 | arg timer 300
187 | symbol S Glooper
188 |
189 | given t (self) => self.timer-- <= 0
190 | t => S
191 |
192 | change G (self, Self) => new Self(self.timer)
193 |
194 | any(xyz.directions) {
195 | maybe(0.1) @_ => @G
196 | @$ => _@
197 | @_ => _@
198 | }
199 |
200 | }
201 |
202 | element UpSignal {
203 |
204 | symbol G Glooper
205 | keep u (atom, time) => {
206 | atom.direction = "up"
207 | atom.directionTime = time
208 | }
209 | //category "T2Tile"
210 |
211 | @ => _
212 | _ @
213 |
214 | @ => _
215 | G u
216 |
217 | @ => _
218 | }
219 |
220 |
221 | element DownSignal {
222 |
223 | symbol G Glooper
224 | keep d (atom, time) => {
225 | atom.direction = "down"
226 | atom.directionTime = time
227 | }
228 | //category "T2Tile"
229 |
230 | @ => _
231 | _ @
232 |
233 |
234 | @ => _
235 | G d
236 |
237 | @ => _
238 | }
239 |
240 |
241 |
242 | `;
243 |
--------------------------------------------------------------------------------
/Source/Engine/Dropper.js:
--------------------------------------------------------------------------------
1 | //======//
2 | // Drop //
3 | //======//
4 | const DROPPER = {};
5 | let UIstarted = false;
6 | let DROPPER_LOCATION = "default";
7 | let DROPPER_SHADOW = true;
8 | let MAX_DROPPER = 2;
9 | let MAX_SHADOW = 21;
10 |
11 | let DROPPER_POUR = "default";
12 | let DROPPER_HEIGHT = 5;
13 |
14 | let DROPPER_ARGS_NEEDS_EVAL = false;
15 | let DROPPER_ARGS_SOURCE = "";
16 | let DROPPER_ARGS = [];
17 |
18 | let DROPPER_OVERRIDE = false;
19 |
20 | {
21 | //===========//
22 | // Constants //
23 | //===========//
24 | const SPREAD_CHANCE = 1;
25 |
26 | //=========//
27 | // Globals //
28 | //=========//
29 | let previousPosition;
30 | let down;
31 |
32 | const dropperShadowMaterial = new THREE.MeshLambertMaterial({
33 | transparent: false,
34 | opacity: 0.5,
35 | //flatShading: true,
36 | side: THREE.DoubleSide,
37 | });
38 | const dropperShadowGeometry = new THREE.BoxBufferGeometry(
39 | 1 * ATOM_SIZE * ATOM_SCALE,
40 | 1 * ATOM_SIZE * ATOM_SCALE,
41 | 1 * ATOM_SIZE * ATOM_SCALE
42 | );
43 | const dropperShadow = [];
44 |
45 | for (let i = 0; i < MAX_SHADOW * MAX_SHADOW; i++) {
46 | dropperShadow[i] = new THREE.Mesh(
47 | dropperShadowGeometry,
48 | dropperShadowMaterial
49 | );
50 | }
51 |
52 | DROPPER.refreshShadows = () => {
53 | const cutoff = MAX_DROPPER * 2 + 1;
54 | for (let i = cutoff; i < MAX_SHADOW * MAX_SHADOW; i++) {
55 | dropperShadow[i].visible = false;
56 | }
57 | };
58 |
59 | //========//
60 | // Public //
61 | //========//
62 | DROPPER.tryDrop = (position) => {
63 | if (!UIstarted && !Mouse.down && Touches.length == 0) return;
64 | if (UI.selectedElement === undefined) return false;
65 | if (UI.clicking) return;
66 |
67 | if (position == undefined) {
68 | previousPosition = undefined;
69 | for (const shadow of dropperShadow) {
70 | shadow.visible = false;
71 | }
72 | return;
73 | }
74 |
75 | position.x /= ATOM_SIZE;
76 | position.y /= ATOM_SIZE;
77 | position.z /= ATOM_SIZE;
78 |
79 | if (position.y < 0) position.y = 0;
80 |
81 | if (DROPPER_SHADOW) {
82 | const x = Math.round(position.x);
83 | const y = Math.round(position.y);
84 | const z = Math.round(position.z);
85 |
86 | dropAtom(x, y, z, 0, true, 0);
87 | if (
88 | true ||
89 | (DROPPER_POUR == "default" && UI.selectedElement.pour) ||
90 | DROPPER_POUR == "pour"
91 | ) {
92 | let id = 1;
93 | for (let i = -MAX_DROPPER; i <= MAX_DROPPER; i++) {
94 | for (let j = -MAX_DROPPER; j <= MAX_DROPPER; j++) {
95 | if (i == 0 && j == 0) continue;
96 | dropAtom(x + i, y, z + j, 0, true, id);
97 | id++;
98 | }
99 | }
100 | /*dropAtom(x + 1, y, z, 0, true, 1)
101 | dropAtom(x - 1, y, z, 0, true, 2)
102 | dropAtom(x, y, z + 1, 0, true, 3)
103 | dropAtom(x, y, z - 1, 0, true, 4)
104 |
105 | dropAtom(x + 1, y, z + 1, 0, true, 5)
106 | dropAtom(x + 1, y, z - 1, 0, true, 6)
107 | dropAtom(x - 1, y, z + 1, 0, true, 7)
108 | dropAtom(x - 1, y, z - 1, 0, true, 8)*/
109 | }
110 | }
111 |
112 | const previousDown = down;
113 | down = Mouse.down;
114 | if (Touches.length == 1) {
115 | down = true;
116 | }
117 |
118 | if (
119 | !(DROPPER_POUR == "default" && UI.selectedElement.pour) ||
120 | DROPPER_POUR == "pour"
121 | ) {
122 | if (!position) return;
123 | if (down && !previousDown) {
124 | const x = Math.round(position.x);
125 | const y = Math.round(position.y);
126 | const z = Math.round(position.z);
127 | dropAtom(x, y, z);
128 | //if (!UI.selectedElement.pour) return
129 | let id = 1;
130 | for (let i = -MAX_DROPPER; i <= MAX_DROPPER; i++) {
131 | for (let j = -MAX_DROPPER; j <= MAX_DROPPER; j++) {
132 | if (i == 0 && j == 0) continue;
133 | dropAtom(x + i, y, z + j);
134 | id++;
135 | }
136 | }
137 | /*if (Math.random() < SPREAD_CHANCE) dropAtom(x + 1, y, z)
138 | if (Math.random() < SPREAD_CHANCE) dropAtom(x - 1, y, z)
139 | if (Math.random() < SPREAD_CHANCE) dropAtom(x, y, z + 1)
140 | if (Math.random() < SPREAD_CHANCE) dropAtom(x, y, z - 1)
141 |
142 | if (Math.random() < SPREAD_CHANCE) dropAtom(x + 1, y, z + 1)
143 | if (Math.random() < SPREAD_CHANCE) dropAtom(x + 1, y, z - 1)
144 | if (Math.random() < SPREAD_CHANCE) dropAtom(x - 1, y, z + 1)
145 | if (Math.random() < SPREAD_CHANCE) dropAtom(x - 1, y, z - 1)*/
146 | //if (Math.random() < SPREAD_CHANCE) dropAtom(x, y + 1, z)
147 | //if (Math.random() < SPREAD_CHANCE) dropAtom(x, y - 1, z)
148 | }
149 | return;
150 | }
151 |
152 | if (!down || !position) {
153 | previousPosition = undefined;
154 | return;
155 | }
156 |
157 | //if (position.y < 0) position.y = 0
158 | if (previousPosition == undefined) {
159 | previousPosition = position;
160 | return;
161 | }
162 |
163 | const xDiff = position.x - previousPosition.x;
164 | const zDiff = position.z - previousPosition.z;
165 | const yDiff = position.y - previousPosition.y;
166 |
167 | /*if (xDiff == 0 && zDiff == 0 && yDiff == 0) {
168 |
169 | const xNew = Math.round(position.x)
170 | const yNew = Math.round(position.y)
171 | const zNew = Math.round(position.z)
172 |
173 | dropAtom(xNew, yNew, zNew)
174 | previousPosition = position
175 | return
176 | }*/
177 |
178 | const xAbs = Math.abs(xDiff);
179 | const zAbs = Math.abs(zDiff);
180 | const yAbs = Math.abs(yDiff);
181 |
182 | let largest = Math.max(xAbs, zAbs, yAbs);
183 | if (largest == 0) largest = 0.00001;
184 |
185 | const xRatio = xAbs / largest;
186 | const zRatio = zAbs / largest;
187 | const yRatio = yAbs / largest;
188 |
189 | const xWay = Math.sign(xDiff);
190 | const zWay = Math.sign(zDiff);
191 | const yWay = Math.sign(yDiff);
192 |
193 | const xInc = xWay * xRatio;
194 | const zInc = zWay * zRatio;
195 | const yInc = yWay * yRatio;
196 |
197 | for (const i of largest) {
198 | const xNew = Math.round(position.x - xInc * i);
199 | const zNew = Math.round(position.z - zInc * i);
200 | const yNew = Math.round(position.y - yInc * i);
201 |
202 | if (Math.random() < 1) dropAtom(xNew, yNew, zNew);
203 | if (
204 | !(
205 | (DROPPER_POUR == "default" && UI.selectedElement.pour) ||
206 | DROPPER_POUR == "pour"
207 | )
208 | )
209 | continue;
210 | for (let i = -MAX_DROPPER; i <= MAX_DROPPER; i++) {
211 | for (let j = -MAX_DROPPER; j <= MAX_DROPPER; j++) {
212 | if (i == 0 && j == 0) continue;
213 | dropAtom(xNew + i, yNew, zNew + j);
214 | }
215 | }
216 | /*if (Math.random() < SPREAD_CHANCE) dropAtom(xNew + 1, yNew, zNew)
217 | if (Math.random() < SPREAD_CHANCE) dropAtom(xNew - 1, yNew, zNew)
218 | if (Math.random() < SPREAD_CHANCE) dropAtom(xNew, yNew, zNew + 1)
219 | if (Math.random() < SPREAD_CHANCE) dropAtom(xNew, yNew, zNew - 1)
220 |
221 | if (Math.random() < SPREAD_CHANCE) dropAtom(xNew + 1, yNew, zNew + 1)
222 | if (Math.random() < SPREAD_CHANCE) dropAtom(xNew + 1, yNew, zNew - 1)
223 | if (Math.random() < SPREAD_CHANCE) dropAtom(xNew - 1, yNew, zNew + 1)
224 | if (Math.random() < SPREAD_CHANCE) dropAtom(xNew - 1, yNew, zNew - 1)*/
225 | //if (Math.random() < SPREAD_CHANCE) dropAtom(xNew, yNew + 1, zNew)
226 | //if (Math.random() < SPREAD_CHANCE) dropAtom(xNew, yNew - 1, zNew)
227 | }
228 |
229 | previousPosition = position;
230 | };
231 |
232 | //=========//
233 | // Private //
234 | //=========//
235 | // This function is the messy result of adding one line of code every two weeks without much thought
236 | let dropperShadowReady = [false].repeated(9);
237 | const dropAtom = (
238 | x,
239 | y,
240 | z,
241 | yOffset = 0,
242 | justShow = false,
243 | shadowNumber = 0,
244 | yOverride = Math.floor(DROPPER_HEIGHT)
245 | ) => {
246 | if (!UI) return;
247 | if (UI.selectedElement === undefined) return;
248 | const atomType = UI.selectedElement;
249 | const dropStart = MAX_Y - yOverride;
250 | let alteredY = dropStart + yOffset;
251 | let alteredZ = z;
252 | if (D2_MODE) alteredY = y;
253 | if (D2_MODE) alteredZ = 0;
254 | if (D1_MODE) alteredY = 0;
255 | const space = WORLD.selectSpace(world, x, alteredY, alteredZ);
256 | if (space.atom.element == Void) {
257 | if (justShow) dropperShadow[shadowNumber].visible = false;
258 | return;
259 | }
260 | if (
261 | !D2_MODE &&
262 | !D1_MODE &&
263 | !DROPPER_OVERRIDE &&
264 | space.atom.element != Empty
265 | ) {
266 | if (atomType != space.atom.element)
267 | return dropAtom(x, y, z, yOffset + 1, justShow, shadowNumber);
268 | }
269 | if (!justShow) {
270 | if (atomType === space.atom.element) return;
271 | if (DROPPER_ARGS_NEEDS_EVAL) {
272 | DROPPER_ARGS = JS("[" + DROPPER_ARGS_SOURCE + "]");
273 | DROPPER_ARGS_NEEDS_EVAL = false;
274 | }
275 | const atom = new atomType(...DROPPER_ARGS);
276 | SPACE.setAtom(space, atom, atomType);
277 | } else {
278 | if (!dropperShadowReady[shadowNumber]) {
279 | scene.add(dropperShadow[shadowNumber]);
280 | dropperShadowReady[shadowNumber] = true;
281 | }
282 |
283 | dropperShadow[shadowNumber].visible = true;
284 | dropperShadow[shadowNumber].position.set(
285 | x * ATOM_SIZE,
286 | alteredY * ATOM_SIZE,
287 | alteredZ * ATOM_SIZE
288 | );
289 | dropperShadow[shadowNumber].material.emissive.set(atomType.emissive);
290 | dropperShadow[shadowNumber].material.color.set(atomType.colour);
291 | dropperShadow[shadowNumber].material.opacity = 0.35;
292 | }
293 | };
294 | }
295 |
--------------------------------------------------------------------------------
/Source/Engine/Floor.js:
--------------------------------------------------------------------------------
1 | //=======//
2 | // Floor //
3 | //=======//
4 | {
5 |
6 | const floorMaterial = DARK_MODE? new THREE.MeshLambertMaterial({color: "rgb(45, 45, 61)", emissive: "rgb(45, 45, 61)"}) : new THREE.MeshLambertMaterial({color: "white", emissive: "grey"})
7 | const floorMaterials = [
8 | floorMaterial,
9 | floorMaterial,
10 | floorMaterial,
11 | floorMaterial,
12 | floorMaterial,
13 | floorMaterial,
14 | ]
15 |
16 | const noFloorMaterial = new THREE.MeshLambertMaterial({color: "white", emissive: "grey", opacity: 0.0, transparent: true})
17 | const noFloorMaterials = [
18 | noFloorMaterial,
19 | noFloorMaterial,
20 | noFloorMaterial,
21 | noFloorMaterial,
22 | noFloorMaterial,
23 | noFloorMaterial,
24 | ]
25 |
26 | makeFloor = (FLOOR_TYPE, width, depth) => {
27 | const floorGeometry = new THREE.BoxGeometry(width, ATOM_SIZE, depth)
28 | const floor = new THREE.Mesh(floorGeometry, FLOOR_TYPE == "floor"? floorMaterials : noFloorMaterials)
29 | floor.position.set(0, -1 * ATOM_SIZE, 0)
30 | floor.castShadow = false
31 | floor.receiveShadow = SHADOW_MODE
32 | return floor
33 | }
34 |
35 | make2DFloor = (FLOOR_TYPE, width, height) => {
36 | const floorGeometry = new THREE.BoxGeometry(width, height, ATOM_SIZE)
37 | const floor = new THREE.Mesh(floorGeometry, floorMaterials)
38 | floor.position.set(0, height / 2, -1 * ATOM_SIZE)
39 | return floor
40 | }
41 |
42 | }
--------------------------------------------------------------------------------
/Source/Engine/Lighting.js:
--------------------------------------------------------------------------------
1 | //==========//
2 | // Lighting //
3 | //==========//
4 | function makeSun(is2D = false) {
5 | const sun = new THREE.DirectionalLight()
6 | sun.position.set(-200, 400, 100)
7 |
8 | if (SHADOW_MODE) {
9 | sun.castShadow = true
10 | sun.shadow.mapSize.width = 1024
11 | sun.shadow.mapSize.height = 1024
12 | sun.shadow.camera.near = 450
13 | sun.shadow.camera.far = 475
14 | sun.shadow.bias = -0.0004
15 | }
16 |
17 | //const helper = new THREE.CameraHelper(sun.shadow.camera)
18 | //scene.add(helper)
19 |
20 | if (is2D) sun.position.set(-200, 100, 400)
21 | return sun
22 | }
23 |
24 | /*function makeBackground() {
25 | const background = new THREE.Color()
26 | background.setHSL(Math.random(), 1, 0.92)
27 | return background
28 | }*/
29 |
30 | const bgColour = new THREE.Color()
31 | if (!DARK_MODE) bgColour.setHSL(Math.random(), 1, 0.85)
32 | else bgColour.setRGB(13 / 255, 16 / 255, 23 / 255)
33 | //else bgColour.setRGB(45 / 255, 45 / 255, 61 / 255)
34 | const bgColourString = `rgb(${Math.floor(bgColour.r * 255)}, ${Math.floor(bgColour.g * 255)}, ${Math.floor(bgColour.b * 255)})`
35 |
36 | function makeBackground() {
37 | return bgColour
38 | }
39 |
40 | function createScreen() {
41 | //const geo = new THREE.PlaneGeometry(WORLD_WIDTH * ATOM_SIZE, WORLD_HEIGHT * ATOM_SIZE
42 | const geo = new THREE.PlaneGeometry(WORLD_WIDTH, WORLD_HEIGHT)
43 | const mat = new THREE.MeshBasicMaterial({
44 | color: bgColour,
45 | side: THREE.FrontSide,
46 | })
47 |
48 | const mesh0 = new THREE.Mesh(geo, mat)
49 | mesh0.frustrumCulled = false
50 | mesh0.position.set (
51 | mesh0.position.x,
52 | mesh0.position.y + ((WORLD_HEIGHT-1) * ATOM_SIZE) / 2,
53 | mesh0.position.z - ((WORLD_DEPTH) * ATOM_SIZE) / 2,
54 | )
55 | if (D2_MODE) mesh0.position.z -= ATOM_SIZE
56 | scene.add(mesh0)
57 |
58 | const mesh1 = new THREE.Mesh(geo, mat)
59 | mesh1.frustrumCulled = false
60 | mesh1.position.set (
61 | mesh1.position.x,
62 | mesh1.position.y + ((WORLD_HEIGHT-1) * ATOM_SIZE) / 2,
63 | mesh1.position.z + ((WORLD_DEPTH) * ATOM_SIZE) / 2,
64 | )
65 | mesh1.rotateY(Math.PI)
66 | scene.add(mesh1)
67 |
68 | const mesh2 = new THREE.Mesh(geo, mat)
69 | mesh2.frustrumCulled = false
70 | mesh2.position.set (
71 | mesh2.position.x - ((WORLD_WIDTH) * ATOM_SIZE) / 2,
72 | mesh2.position.y + ((WORLD_HEIGHT-1) * ATOM_SIZE) / 2,
73 | mesh2.position.z,
74 | )
75 | mesh2.rotateY(Math.PI / 2)
76 | scene.add(mesh2)
77 |
78 | const mesh3 = new THREE.Mesh(geo, mat)
79 | mesh3.frustrumCulled = false
80 | mesh3.position.set (
81 | mesh3.position.x + ((WORLD_WIDTH) * ATOM_SIZE) / 2,
82 | mesh3.position.y + ((WORLD_HEIGHT-1) * ATOM_SIZE) / 2,
83 | mesh3.position.z,
84 | )
85 | mesh3.rotateY(-Math.PI / 2)
86 | scene.add(mesh3)
87 |
88 | }
--------------------------------------------------------------------------------
/Source/Engine/Random.js:
--------------------------------------------------------------------------------
1 |
2 | const createRandomSpaceIds = (spaceCount, buffer) => {
3 | crypto.getRandomValues(buffer)
4 | }
5 |
6 |
--------------------------------------------------------------------------------
/Source/Engine/ShuffleWorker.js:
--------------------------------------------------------------------------------
1 | shuffle = (array) => {
2 | postMessage(array.sort(() => Math.random() - 0.5));
3 | requestAnimationFrame(() => shuffle(array));
4 | };
5 |
--------------------------------------------------------------------------------
/Source/Engine/Site.js:
--------------------------------------------------------------------------------
1 | //======//
2 | // Site //
3 | //======//
4 | const SITE = {}
5 |
6 | {
7 |
8 | // Site Job Description
9 | //=====================
10 | // "I keep my SPACE."
11 | // "I keep my RELATIVE POSITION."
12 |
13 | //========//
14 | // Public //
15 | //========//
16 | SITE.make = (space, x, y, z) => {
17 | return space
18 | /*const site = {
19 | space,
20 | x,
21 | y,
22 | z,
23 | }
24 | return space*/
25 | }
26 |
27 |
28 | }
--------------------------------------------------------------------------------
/Source/Engine/Space.js:
--------------------------------------------------------------------------------
1 | //=======//
2 | // Space //
3 | //=======//
4 | const SPACE = {}
5 |
6 | {
7 |
8 | // Space Job Description
9 | //======================
10 | // "I am responsible for my ATOM."
11 | // "I keep a CACHE of stuff to speed up rendering."
12 |
13 | //========//
14 | // Public //
15 | //========//
16 | SPACE.make = (world, id) => {
17 | return {
18 |
19 | // Real Data
20 | atom: new Empty(),
21 | element: Empty,
22 |
23 | // Cached Data
24 | id,
25 | sites: [], //EVENTWINDOW makes this
26 | colourOffset0: id*3 + 0, //not really my job to make this... WORLD should make this
27 | colourOffset1: id*3 + 1,
28 | colourOffset2: id*3 + 2,
29 |
30 | }
31 | }
32 |
33 | const updateAppearanceShadow = (space, _world = world) => {
34 | const atom = space.atom
35 | if (atom == undefined || !atom.visible) {
36 | //WORLD.setSpaceVisible(world, space, false)
37 | WORLD.hideSpace(_world, space)
38 | //WORLD.setSpaceColour(world, space, atom.colour, atom.emissive)
39 | //WORLD.setSpaceOpacity(world, space, 255)
40 | return
41 | }
42 | //WORLD.setSpaceVisible(world, space, true)
43 | WORLD.showSpace(_world, space)
44 | WORLD.setSpaceOpacity(_world, space, atom.opacity)
45 | WORLD.setSpaceColour(_world, space, atom.colour, atom.emissive)
46 | }
47 |
48 |
49 | const updateAppearanceNoShadow = (space, _world = world) => {
50 | const atom = space.atom
51 | if (atom == undefined || !atom.visible) {
52 | WORLD.setSpaceVisible(_world, space, false)
53 | //WORLD.hideSpace(world, space)
54 | //WORLD.setSpaceColour(world, space, atom.colour, atom.emissive)
55 | //WORLD.setSpaceOpacity(world, space, 255)
56 | return
57 | }
58 | WORLD.setSpaceVisible(_world, space, true)
59 | //WORLD.showSpace(world, space)
60 | WORLD.setSpaceOpacity(_world, space, atom.opacity)
61 | WORLD.setSpaceColour(_world, space, atom.colour, atom.emissive)
62 | }
63 |
64 | SPACE.updateAppearance = SHADOW_MODE? updateAppearanceShadow : updateAppearanceNoShadow
65 | SPACE.update = SPACE.updateAppearance
66 |
67 | SPACE.setAtom = (space, atom, element = atom.element) => {
68 | space.atom = atom
69 | space.element = element
70 | SPACE.updateAppearance(space)
71 | }
72 |
73 | SPACE.set = SPACE.setAtom
74 |
75 | }
--------------------------------------------------------------------------------
/config.js:
--------------------------------------------------------------------------------
1 | //===========//
2 | // Constants //
3 | //===========//
4 | const urlParams = new URLSearchParams(window.location.search)
5 |
6 | const DOF_MODE = urlParams.has("dof")
7 | const SHADOW_MODE = urlParams.has("shadow")
8 | const SMALL_MODE = urlParams.has("small") || !urlParams.has("big")
9 | const MASSIVE_MODE = urlParams.has("massive")
10 | const D2_MODE = urlParams.has("2d")
11 | const D1_MODE = urlParams.has("1d")
12 | const VR_MODE = urlParams.has("vr")
13 | const TINY_MODE = urlParams.has("tiny")/* | true*/
14 | const LONG_MODE = urlParams.has("long")
15 | const PURE_RANDOM_MODE = urlParams.has("pure")
16 | const SHUFFLE_MODE = urlParams.has("shuffle")
17 | const FIRING_MODE = urlParams.has("firing")
18 | const MEDIUM_MODE = urlParams.has("medium")
19 | const RIDICULOUS_MODE = urlParams.has("ridiculous")
20 | const NO_SECRET_MODE = urlParams.has("nosecret")
21 |
22 | const DARK_MODE = urlParams.has("dark")
23 |
24 | const DEFAULT_RANDOMNESS_MODE = "track"
25 | const RANDOM = SHUFFLE_MODE? "shuffle" : (PURE_RANDOM_MODE? "pure" : (FIRING_MODE? "firing" : DEFAULT_RANDOMNESS_MODE))
26 |
27 | const FLOOR_TYPE = urlParams.has("nofloor")? "nofloor" : "floor"
28 |
29 | let MAX_X = (SMALL_MODE? 30 : 50) * (D1_MODE? 2 : 1) * (D2_MODE? 5 : 1)
30 | let MAX_Z = D1_MODE? 0 : (D2_MODE? 0 : MAX_X)
31 | let MAX_Y = D1_MODE? 0 : (SMALL_MODE? 30 : 40) * (D2_MODE? 8 : 1)
32 |
33 | if (TINY_MODE) {
34 | MAX_X = Math.floor(MAX_X * 0.6)
35 | MAX_Z = Math.floor(MAX_Z * 0.6)
36 | MAX_Y = Math.floor(MAX_Y * 0.7)
37 | }
38 |
39 | if (MASSIVE_MODE) {
40 | MAX_X = Math.floor(MAX_X * 2.5)
41 | MAX_Z = Math.floor(MAX_Z * 2.5)
42 | MAX_Y = Math.floor(MAX_Y * 1.5)
43 | }
44 |
45 | if (RIDICULOUS_MODE) {
46 | MAX_X = Math.floor(MAX_X * 3.0)
47 | MAX_Z = Math.floor(MAX_Z * 3.0)
48 | MAX_Y = Math.floor(MAX_Y * 1.5)
49 | }
50 |
51 | if (LONG_MODE) {
52 | MAX_X = Math.floor(MAX_X * 1.3)
53 | MAX_Z = Math.floor(MAX_Z * 1)
54 | MAX_Y = Math.floor(MAX_Y * 0.75)
55 | }
56 |
57 | if (MEDIUM_MODE) {
58 | MAX_X = 40 * (D1_MODE? 2 : 1) * (D2_MODE? 5 : 1)
59 | MAX_Y = 35 * (D2_MODE? 8 : 1)
60 | MAX_Z = D1_MODE? 0 : (D2_MODE? 0 : MAX_X)
61 | }
62 |
63 | let SIZE = SMALL_MODE? "small" : "big"
64 | if (TINY_MODE) SIZE = "tiny"
65 | else if (MASSIVE_MODE) SIZE = "massive"
66 | else if (MEDIUM_MODE) SIZE = "medium"
67 |
68 |
69 | const SHAPE = LONG_MODE? "long" : "cube"
70 |
71 | const MIN_X = -MAX_X
72 | const MIN_Z = -MAX_Z
73 | const MIN_Y = 0
74 |
75 | const WORLD_WIDTH = MAX_X * 2 + 1
76 | const WORLD_DEPTH = MAX_Z * 2 + 1
77 | const WORLD_HEIGHT = MAX_Y
78 |
79 | const WORLD_AREA = {
80 | x: [MIN_X, MAX_X],
81 | y: [MIN_Y, MAX_Y],
82 | z: [MIN_Z, MAX_Z],
83 | }
84 |
85 |
86 | const ATOM_SIZE = 0.01
87 | const ATOM_SCALE = 1.0
88 |
89 | const CAMERA_START_X = 0
90 | let CAMERA_START_Y = (D2_MODE? WORLD_HEIGHT/2 : (SMALL_MODE? 85 : 140)) * ATOM_SIZE
91 | let CAMERA_START_Z = (SMALL_MODE? 125 : 200) * (D2_MODE? 2 : 1) * ATOM_SIZE
92 |
93 | if (MEDIUM_MODE) {
94 | CAMERA_START_Y = CAMERA_START_Y * 1.25
95 | CAMERA_START_Z = CAMERA_START_Z * 1.25
96 | }
97 |
98 | if (MASSIVE_MODE) {
99 | CAMERA_START_Y = CAMERA_START_Y * 2.25
100 | CAMERA_START_Z = CAMERA_START_Z * 2.25
101 | }
102 |
103 | if (TINY_MODE) {
104 | CAMERA_START_Y = CAMERA_START_Y * 0.65
105 | CAMERA_START_Z = CAMERA_START_Z * 0.7
106 | }
107 |
108 | if (D2_MODE) {
109 | //CAMERA_START_Y = CAMERA_START_Y * 2.8
110 | CAMERA_START_Z = CAMERA_START_Z * 2.25
111 | }
112 |
113 | const CAMERA_SPEED = 2
114 |
115 | //window.history.replaceState({}, "", window.location.pathname)
116 |
117 | let SPEED_MOD = urlParams.get("speed")
118 | if (SPEED_MOD === null) SPEED_MOD = "1"
119 | SPEED_MOD = parseFloat(SPEED_MOD)
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
Loading...
49 |