@codincod/ornament 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/README.md +62 -2
- package/package.json +35 -3
- package/src/biome.ts +157 -0
- package/src/canvas/flat.ts +336 -0
- package/src/caustics.ts +81 -0
- package/src/census.ts +262 -0
- package/src/cephalopods.ts +1041 -0
- package/src/cloud.ts +308 -0
- package/src/crags.ts +974 -0
- package/src/drift.ts +435 -0
- package/src/eels.ts +667 -0
- package/src/fish_shape.ts +410 -0
- package/src/flora.ts +1955 -0
- package/src/flow_field.ts +491 -0
- package/src/jellies.ts +1794 -0
- package/src/nemos.ts +606 -0
- package/src/paint/bed.ts +231 -0
- package/src/paint/colour.ts +86 -0
- package/src/paint/frame.ts +204 -0
- package/src/paint/ink.ts +134 -0
- package/src/paint/life.ts +611 -0
- package/src/paint/light.ts +132 -0
- package/src/paint/pen.ts +225 -0
- package/src/paint/rock.ts +325 -0
- package/src/paint/sea.ts +809 -0
- package/src/paint/shade.ts +109 -0
- package/src/paint/sky.ts +377 -0
- package/src/paint/specimen.ts +300 -0
- package/src/paint/svg.ts +326 -0
- package/src/paint/trace.ts +164 -0
- package/src/passers.ts +730 -0
- package/src/perlin.ts +168 -0
- package/src/plenty.ts +65 -0
- package/src/puffers.ts +510 -0
- package/src/rays.ts +225 -0
- package/src/reef.ts +945 -0
- package/src/relics.ts +451 -0
- package/src/seabed.ts +525 -0
- package/src/shoal.ts +1658 -0
- package/src/sizes.ts +86 -0
- package/src/sun.ts +500 -0
- package/src/swarm.ts +587 -0
- package/src/visitors.ts +1936 -0
- package/src/walkers.ts +861 -0
package/src/census.ts
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How much of each animal a sea holds.
|
|
3
|
+
*
|
|
4
|
+
* The other half of `sizes.ts`, and it is here for the same fault. That file
|
|
5
|
+
* was written because every drawing had picked a size that looked right on its
|
|
6
|
+
* own and a boat had come out the size of a turtle. This one is the same story
|
|
7
|
+
* told about how many: every renderer picked a density that read well where it
|
|
8
|
+
* was written, and the water ended up with more crabs on the sand than fish in
|
|
9
|
+
* the column. A crab at eleven per thousand pixels of bed is defensible where
|
|
10
|
+
* it stands. A fish at one per sixty thousand square pixels is defensible where
|
|
11
|
+
* it stands. What lies between them is a sea nobody has ever swum in, and
|
|
12
|
+
* nothing catches it, because the two numbers are never read side by side.
|
|
13
|
+
*
|
|
14
|
+
* So every animal says how many of it a stretch of reef holds, in the unit a
|
|
15
|
+
* survey would report it in, and this turns that into how many to draw.
|
|
16
|
+
*
|
|
17
|
+
* ## Why the numbers are not used as they stand
|
|
18
|
+
*
|
|
19
|
+
* A reef carries upwards of a hundred fish over every hundred square metres of
|
|
20
|
+
* it, and most of them are small ones hanging above the coral. Drawn as
|
|
21
|
+
* counted, that is a screen of fish with a sea somewhere behind them, and
|
|
22
|
+
* everything else in the water is lost among them. Thin the whole table until
|
|
23
|
+
* the fish are countable and the crab, the octopus and the starfish all round
|
|
24
|
+
* to none, which leaves a bare floor under a busy column.
|
|
25
|
+
*
|
|
26
|
+
* The root is the compression that settles it, and it is the same bargain
|
|
27
|
+
* `sizes.ts` strikes over length. Something commoner is still drawn commoner,
|
|
28
|
+
* so the order is never wrong; the ends are pulled in far enough that the rare
|
|
29
|
+
* animal is still in the water somewhere. What is kept is which is commoner,
|
|
30
|
+
* rather than by how much.
|
|
31
|
+
*
|
|
32
|
+
* ## The mix comes out of the same table
|
|
33
|
+
*
|
|
34
|
+
* How common a moon jelly is against a comb jelly is the question of how common
|
|
35
|
+
* a jellyfish is against a fish, asked inside one family. A file that answered
|
|
36
|
+
* it in its own column would answer it a second way by the end of the year, so
|
|
37
|
+
* the shares a family draws its next animal from are these numbers normalised.
|
|
38
|
+
* A family after a count and a family after a mix read one statement.
|
|
39
|
+
*
|
|
40
|
+
* ## A day of its own
|
|
41
|
+
*
|
|
42
|
+
* `plenty.ts` decides how good a year the whole sea is having. This decides
|
|
43
|
+
* which animal is having it. Every kind swings from one day to the next on its
|
|
44
|
+
* own draw, and how far it swings is its own business: blooming is what a
|
|
45
|
+
* jellyfish does and a grouper does not. So `swings` is a column, and a week of
|
|
46
|
+
* water is a comb jelly week and then a moon jelly one.
|
|
47
|
+
*
|
|
48
|
+
* ## What it does not decide
|
|
49
|
+
*
|
|
50
|
+
* Where anything goes, when it turns up, or whether a renderer can afford it.
|
|
51
|
+
* A shark and a manta are in here for their share against each other and for
|
|
52
|
+
* nothing else, because what actually puts one in the water is a rest between
|
|
53
|
+
* crossings (`visitors.ts`); a bed with a thousand plants on it is capped by
|
|
54
|
+
* whoever has to draw them. This is what the sea holds, and the appetite is
|
|
55
|
+
* still `plenty.ts`.
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
import { stir } from "./perlin.ts"
|
|
59
|
+
import { thriving } from "./plenty.ts"
|
|
60
|
+
|
|
61
|
+
export type Kind =
|
|
62
|
+
| "barrel"
|
|
63
|
+
| "box"
|
|
64
|
+
| "comb"
|
|
65
|
+
| "crab"
|
|
66
|
+
| "crown"
|
|
67
|
+
| "cruiser"
|
|
68
|
+
| "darter"
|
|
69
|
+
| "dolphin"
|
|
70
|
+
| "drifter"
|
|
71
|
+
| "eel"
|
|
72
|
+
| "escort"
|
|
73
|
+
| "mane"
|
|
74
|
+
| "manowar"
|
|
75
|
+
| "manta"
|
|
76
|
+
| "mermaid"
|
|
77
|
+
| "moon"
|
|
78
|
+
| "octopus"
|
|
79
|
+
| "puffer"
|
|
80
|
+
| "shark"
|
|
81
|
+
| "squid"
|
|
82
|
+
| "starfish"
|
|
83
|
+
| "stinger"
|
|
84
|
+
| "swordfish"
|
|
85
|
+
| "turtle"
|
|
86
|
+
|
|
87
|
+
interface Held {
|
|
88
|
+
/**
|
|
89
|
+
* How many of it live over a hundred square metres of reef.
|
|
90
|
+
*
|
|
91
|
+
* The unit a transect is counted in, so a number here can be argued with by
|
|
92
|
+
* somebody who has swum one. It is what stands in the water at a given
|
|
93
|
+
* moment rather than what passes through in a season: a shark is scarce here
|
|
94
|
+
* because a shark is scarce at any one moment, and it is scarce in the
|
|
95
|
+
* picture for the same reason.
|
|
96
|
+
*/
|
|
97
|
+
readonly holds: number
|
|
98
|
+
/**
|
|
99
|
+
* How hard a day is allowed to swing it, as a power of the day's own draw.
|
|
100
|
+
*
|
|
101
|
+
* At 0 a kind is as common today as it was yesterday, which is what holding a
|
|
102
|
+
* territory looks like from outside. At 1 it rises and falls with the year
|
|
103
|
+
* `plenty.ts` decided. Past that it blooms: the draw is weighted low, so a
|
|
104
|
+
* high power leaves most weeks ordinary or thin and now and then fills the
|
|
105
|
+
* water with one animal, which is the only shape a bloom comes in.
|
|
106
|
+
*/
|
|
107
|
+
readonly swings: number
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* What a reef holds, animal by animal.
|
|
112
|
+
*
|
|
113
|
+
* Read down the `holds` column rather than across a row: the column is the
|
|
114
|
+
* whole point of the file, and every number in it was chosen against its
|
|
115
|
+
* neighbours rather than against how much of the picture the animal deserves.
|
|
116
|
+
* Where a figure is a range in the wild it is the ordinary end of that range,
|
|
117
|
+
* since `swings` is what carries the rest.
|
|
118
|
+
*/
|
|
119
|
+
const SEA: Readonly<Record<Kind, Held>> = {
|
|
120
|
+
/** A dustbin lid of a jelly, in on a season rather than resident. */
|
|
121
|
+
barrel: { holds: 0.09, swings: 1.8 },
|
|
122
|
+
/** Small, scarce, and inshore for part of the year. */
|
|
123
|
+
box: { holds: 0.025, swings: 1.6 },
|
|
124
|
+
/** Comb jellies outnumber everything else adrift in the water. */
|
|
125
|
+
comb: { holds: 0.66, swings: 2 },
|
|
126
|
+
/** Most crabs on a reef are under it. This is the few that are out. */
|
|
127
|
+
crab: { holds: 3, swings: 0.4 },
|
|
128
|
+
/** Deep water, and up here only where cold water is. */
|
|
129
|
+
crown: { holds: 0.03, swings: 1.4 },
|
|
130
|
+
/** Snapper, surgeon, parrot: the fish a reef reads as at a glance. */
|
|
131
|
+
cruiser: { holds: 24, swings: 0.35 },
|
|
132
|
+
/** Damsels and anthias over the coral, which is most of what a reef holds. */
|
|
133
|
+
darter: { holds: 90, swings: 0.5 },
|
|
134
|
+
/** They pass along a coast rather than live on one stretch of it. */
|
|
135
|
+
dolphin: { holds: 0.04, swings: 0.5 },
|
|
136
|
+
/** A grouper holds a hole and there are only so many holes. */
|
|
137
|
+
drifter: { holds: 1.1, swings: 0.15 },
|
|
138
|
+
/** Where there is a bed of them there are hundreds, and where there is not
|
|
139
|
+
* there are none. The colony's own arithmetic thins it to what fits. */
|
|
140
|
+
eel: { holds: 140, swings: 1.2 },
|
|
141
|
+
/** Butterflyfish, which go about in twos and are never far apart. */
|
|
142
|
+
escort: { holds: 6, swings: 0.35 },
|
|
143
|
+
/** A cold water animal, and in warm water a rarity worth the day. */
|
|
144
|
+
mane: { holds: 0.06, swings: 1.8 },
|
|
145
|
+
/** It goes where the wind puts it, so it arrives in a fleet or not at all. */
|
|
146
|
+
manowar: { holds: 0.015, swings: 2.6 },
|
|
147
|
+
/** Scarcest of the large ones, and tied to the few places they gather. */
|
|
148
|
+
manta: { holds: 0.012, swings: 0.7 },
|
|
149
|
+
/** Not an animal and not on a density; `visitors.ts` keeps her calendar. */
|
|
150
|
+
mermaid: { holds: 0, swings: 0 },
|
|
151
|
+
/** The jelly anybody can name, and it is common enough to earn that. */
|
|
152
|
+
moon: { holds: 0.45, swings: 2 },
|
|
153
|
+
/** One to a den, and a den is a find. */
|
|
154
|
+
octopus: { holds: 0.5, swings: 0.25 },
|
|
155
|
+
/** Solitary, territorial, and one to a stretch of reef this size. */
|
|
156
|
+
puffer: { holds: 0.4, swings: 0.4 },
|
|
157
|
+
/** A reef shark works a stretch of reef that is larger than this one. */
|
|
158
|
+
shark: { holds: 0.09, swings: 0.4 },
|
|
159
|
+
/** Reef squid keep company, so where there is one there are a few. */
|
|
160
|
+
squid: { holds: 0.6, swings: 0.8 },
|
|
161
|
+
/** Slow, obvious, and lying in the open, which is why they read as common. */
|
|
162
|
+
starfish: { holds: 4, swings: 0.5 },
|
|
163
|
+
/** The sea nettle, in on the season the way the barrel is. */
|
|
164
|
+
stinger: { holds: 0.18, swings: 1.8 },
|
|
165
|
+
/** A billfish over a reef is a visitor from the water beyond it. */
|
|
166
|
+
swordfish: { holds: 0.05, swings: 0.6 },
|
|
167
|
+
/** They graze a reef and sleep under its ledges, so one is about. */
|
|
168
|
+
turtle: { holds: 0.12, swings: 0.35 },
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* How hard the range is pulled in.
|
|
173
|
+
*
|
|
174
|
+
* The root `sizes.ts` takes of a length, taken here of a density, and picked
|
|
175
|
+
* the same way: at this it is the small fish that carry the water and the crab
|
|
176
|
+
* and the octopus are still in it. Nearer 1 and the darters bury everything
|
|
177
|
+
* else; nearer 0 and every animal in the sea is about as common as every other,
|
|
178
|
+
* which is the picture this file exists to prevent.
|
|
179
|
+
*/
|
|
180
|
+
const ROOT = 0.55
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* How wide a stretch of sea the box is a window on, in metres.
|
|
184
|
+
*
|
|
185
|
+
* It follows from `sizes.ts` rather than being chosen here. A fish of a third
|
|
186
|
+
* of a metre swimming at eight comes out at a fortieth of the box, and a window
|
|
187
|
+
* that fits forty of those across it is a window on about this much water. It
|
|
188
|
+
* is worth knowing that the answer is a room and not an ocean: everything in
|
|
189
|
+
* this scene is close enough to touch, which is why a shark crossing it is an
|
|
190
|
+
* event.
|
|
191
|
+
*/
|
|
192
|
+
const ACROSS = 13
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* How many the sea is drawn with, against how many it holds.
|
|
196
|
+
*
|
|
197
|
+
* The one number the file is tuned by, and it was fixed by the shoal: the
|
|
198
|
+
* desktop's water held about forty fish before any of this was written down, so
|
|
199
|
+
* it holds about forty now, and every other animal moved to meet them.
|
|
200
|
+
*/
|
|
201
|
+
const SCALE = 2.1
|
|
202
|
+
|
|
203
|
+
/** Square metres of reef in view, which a taller window sees more of. */
|
|
204
|
+
function seaIn(width: number, height: number): number {
|
|
205
|
+
return ACROSS * ACROSS * (height / Math.max(1, width))
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* A number of this kind's own, so no two kinds have the same day.
|
|
210
|
+
*
|
|
211
|
+
* Off the name rather than off a position in the table, because a position
|
|
212
|
+
* moves when something is added above it, and a sea that changed everywhere
|
|
213
|
+
* because a jellyfish was added is a sea nobody can reason about.
|
|
214
|
+
*/
|
|
215
|
+
function own(kind: Kind): number {
|
|
216
|
+
let run = 0
|
|
217
|
+
for (let at = 0; at < kind.length; at++) run = stir(run + kind.charCodeAt(at))
|
|
218
|
+
return run & 0xffff
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* How common this kind is drawn today: compressed, and then given its day.
|
|
223
|
+
*
|
|
224
|
+
* That order is the whole of it. Compressed first and swung afterwards, a bloom
|
|
225
|
+
* is a bloom; swung first and compressed afterwards, the root takes most of the
|
|
226
|
+
* day back off it again and a week of water is a week of the same water.
|
|
227
|
+
*/
|
|
228
|
+
function drawnHolds(kind: Kind, seed: number): number {
|
|
229
|
+
const held = SEA[kind]
|
|
230
|
+
if (held.holds <= 0) return 0
|
|
231
|
+
return held.holds ** ROOT * thriving(seed, own(kind)) ** held.swings
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* How many of these kinds to draw in a box this size, on this day.
|
|
236
|
+
*
|
|
237
|
+
* Comes back as it falls out rather than rounded, since a caller with a floor
|
|
238
|
+
* and a ceiling of its own wants the raw appetite to apply them to.
|
|
239
|
+
*/
|
|
240
|
+
export function manyIn(
|
|
241
|
+
kinds: readonly Kind[],
|
|
242
|
+
width: number,
|
|
243
|
+
height: number,
|
|
244
|
+
seed: number,
|
|
245
|
+
): number {
|
|
246
|
+
let sum = 0
|
|
247
|
+
for (const kind of kinds) sum += drawnHolds(kind, seed)
|
|
248
|
+
return (SCALE * sum * seaIn(width, height)) / 100
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* The shares to draw one of these kinds from, on this day.
|
|
253
|
+
*
|
|
254
|
+
* Weights against each other rather than chances, which is the shape every
|
|
255
|
+
* family in this ornament already wanted. They are not normalised, because
|
|
256
|
+
* nothing that draws from them needs them to be.
|
|
257
|
+
*/
|
|
258
|
+
export function mixOf<K extends Kind>(kinds: readonly K[], seed: number): Record<K, number> {
|
|
259
|
+
const mix = {} as Record<K, number>
|
|
260
|
+
for (const kind of kinds) mix[kind] = drawnHolds(kind, seed)
|
|
261
|
+
return mix
|
|
262
|
+
}
|