honeytree 1.1.2 → 1.1.4

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.
@@ -17,9 +17,14 @@ export const GROUND_ELEMENT_TYPES = ["flower", "mushroom", "rock", "tall_grass"]
17
17
 
18
18
  function parseSprite(template, legend) {
19
19
  const lines = template
20
- .trim()
21
20
  .split("\n")
22
21
  .map((line) => line.replace(/\r/g, ""));
22
+ while (lines.length > 0 && lines[0].trim() === "") {
23
+ lines.shift();
24
+ }
25
+ while (lines.length > 0 && lines[lines.length - 1].trim() === "") {
26
+ lines.pop();
27
+ }
23
28
  const width = Math.max(...lines.map((line) => line.length));
24
29
  const rows = lines
25
30
  .map((line) => line.padEnd(width, " "))
@@ -82,11 +87,12 @@ export function getAnimalTypeForMinutes(totalMinutesCoded) {
82
87
  const TREE_SPRITES = {
83
88
  sapling: parseSprite(
84
89
  `
85
- l
86
- lLl
87
- l
88
- t
89
- t
90
+ L
91
+ lLl
92
+ llLll
93
+ lll
94
+ tT
95
+ tt
90
96
  `,
91
97
  {
92
98
  l: "leaf",
@@ -96,14 +102,15 @@ const TREE_SPRITES = {
96
102
  ),
97
103
  birch: parseSprite(
98
104
  `
99
- ll
100
- lLLl
101
- lLLLLl
102
- lLLl
103
- bb
104
- bB
105
- bb
106
- bB
105
+ lll
106
+ llLLLll
107
+ lLLlLllLl
108
+ llLLLLLll
109
+ lllLlll
110
+ bB
111
+ Bb
112
+ bBb
113
+ Bb
107
114
  `,
108
115
  {
109
116
  l: "leaf",
@@ -114,37 +121,38 @@ const TREE_SPRITES = {
114
121
  ),
115
122
  oak: parseSprite(
116
123
  `
117
- ddd
118
- ddlllld
119
- dlllLLllld
120
- dllLLLLlld
121
- dlllllld
122
- llllll
123
- tt
124
- tTTt
125
- tTTt
126
- tt
124
+ dddll
125
+ ddllLLlld
126
+ dllLLLLLLld
127
+ dllLLlLLlLLd
128
+ dllLLLlllld
129
+ ddllllld
130
+ llmll
131
+ tT
132
+ tTTt
133
+ tt t
127
134
  `,
128
135
  {
129
136
  d: "leafDark",
130
137
  l: "leaf",
131
138
  L: "leafLight",
139
+ m: "moss",
132
140
  t: "trunk",
133
141
  T: "trunkLight",
134
142
  },
135
143
  ),
136
144
  cherry: parseSprite(
137
145
  `
138
- ppp
139
- ppPPPPp
140
- pPPPpPPPp
141
- pPPPPPPPp
142
- pPPPPPp
143
- PPPPp
144
- tt
145
- tTTt
146
- tTTt
147
- tt
146
+ pPPp
147
+ ppPPPPpp
148
+ pPPPpPPPPp
149
+ pPPPPPPpPPp
150
+ ppPPPpPPp
151
+ pPPpp
152
+ tT
153
+ tTTt
154
+ tt t
155
+ tt
148
156
  `,
149
157
  {
150
158
  p: "petal",
@@ -155,16 +163,17 @@ const TREE_SPRITES = {
155
163
  ),
156
164
  pine: parseSprite(
157
165
  `
158
- p
159
- pPp
160
- pPPPp
161
- PPP
162
- pPPPp
163
- pPPPPPp
164
- PPPPP
165
- tTt
166
- tTt
167
- t
166
+ P
167
+ pPp
168
+ pPPPp
169
+ pPp
170
+ ppPPPpp
171
+ pPPPP
172
+ ppPPPPPp
173
+ pPPPp
174
+ tT
175
+ tt
176
+ tt
168
177
  `,
169
178
  {
170
179
  p: "pineDark",
@@ -175,18 +184,17 @@ const TREE_SPRITES = {
175
184
  ),
176
185
  willow: parseSprite(
177
186
  `
178
- llll
179
- llLLLLll
180
- llLLllLLll
181
- lLl lLl
182
- ll ll
183
- ll ll
184
- l l
185
- tTTt
186
- tTTt
187
- tT
188
- tT
189
- tt
187
+ llLLl
188
+ llLLLLLll
189
+ lLLLllLLLl
190
+ lLLl lLLl
191
+ lLl lLl
192
+ ll tT ll
193
+ l tT l
194
+ tT
195
+ tTTt
196
+ tt t
197
+ t t
190
198
  `,
191
199
  {
192
200
  l: "leaf",
@@ -197,20 +205,20 @@ const TREE_SPRITES = {
197
205
  ),
198
206
  ancient_oak: parseSprite(
199
207
  `
200
- ddd
201
- dddllllddd
202
- ddllLLLLlldd
203
- dddllLLLLllddd
204
- ddlllLLLllldd
205
- ddlllllllldd
206
- mllllllm
207
- mmmm
208
- tTTTTt
209
- tTTTTt
210
- ttTTTTtt
211
- tt tt
212
- t t
213
- t t
208
+ dddllld
209
+ dddllLLLlldd
210
+ ddllLLLLLLlldd
211
+ ddllLLlLLlLLld
212
+ dllLLLmLLLllld
213
+ ddlllmmmllld
214
+ ddllmllld
215
+ tTTTt
216
+ ttTTTtt
217
+ tTt tTt
218
+ ttT Ttt
219
+ tt tt
220
+ t t
221
+ t t
214
222
  `,
215
223
  {
216
224
  d: "leafDark",
@@ -223,18 +231,18 @@ const TREE_SPRITES = {
223
231
  ),
224
232
  crystal_tree: parseSprite(
225
233
  `
226
- cc
227
- ccCCCc
228
- cCCcCCCc
229
- cCCCCCCc
230
- cCCCCc
231
- CCCc
232
- tt
233
- tTTt
234
- tTTt
235
- tT
236
- tt
237
- tt
234
+ c
235
+ cCCC
236
+ cCCcCc
237
+ cCCCCCCc
238
+ CCcCCC
239
+ cCCC
240
+ cC
241
+ tT
242
+ tTTt
243
+ tT
244
+ tt
245
+ tt
238
246
  `,
239
247
  {
240
248
  c: "crystal1",
@@ -243,6 +251,488 @@ const TREE_SPRITES = {
243
251
  T: "trunk",
244
252
  },
245
253
  ),
254
+ // Frontend biome trees
255
+ sprout: parseSprite(
256
+ `
257
+ L
258
+ lLl
259
+ lll
260
+ t
261
+ `,
262
+ { l: "leaf", L: "leafLight", t: "trunk" },
263
+ ),
264
+ young_maple: parseSprite(
265
+ `
266
+ lLl
267
+ lLLLl
268
+ llLLLll
269
+ llLll
270
+ tT
271
+ tt
272
+ `,
273
+ { l: "leaf", L: "leafLight", t: "trunk", T: "trunkLight" },
274
+ ),
275
+ wide_oak: parseSprite(
276
+ `
277
+ ddlll
278
+ ddllLLLlld
279
+ dllLLLLLLLlld
280
+ dllLLlLLlLLlLd
281
+ dllLLLLLLllld
282
+ ddllllllldd
283
+ llmmlll
284
+ tTTt
285
+ tTTTTt
286
+ tt tt
287
+ `,
288
+ { d: "leafDark", l: "leaf", L: "leafLight", m: "moss", t: "trunk", T: "trunkLight" },
289
+ ),
290
+ magnolia: parseSprite(
291
+ `
292
+ PpP
293
+ pPPPPPp
294
+ pPPPpPPPPp
295
+ PPpPPPPPpPPP
296
+ pPPPPPPPPp
297
+ pPPpPPPp
298
+ pPPp
299
+ tT
300
+ tTTt
301
+ tt tt
302
+ `,
303
+ { p: "petal", P: "petalLight", t: "trunk", T: "trunkLight" },
304
+ ),
305
+ wisteria: parseSprite(
306
+ `
307
+ llLLll
308
+ llLLLLLLll
309
+ lLLLllLLLLl
310
+ lLLl lLLl
311
+ lLl T lLl
312
+ ll tT ll
313
+ l tT l
314
+ tT
315
+ tTTt
316
+ tt tt
317
+ t t
318
+ `,
319
+ { l: "leaf", L: "leafLight", t: "trunk", T: "trunkLight" },
320
+ ),
321
+ ancient_maple: parseSprite(
322
+ `
323
+ dddllld
324
+ dddllLLLlldd
325
+ ddllLLLLLLlldd
326
+ ddllLLlLLlLLldd
327
+ dllLLLmLLmLllld
328
+ ddlllmmmmlld
329
+ ddllmmlld
330
+ tTTTt
331
+ ttTTTtt
332
+ tTt tTt
333
+ ttT Ttt
334
+ tt tt
335
+ t t
336
+ `,
337
+ { d: "leafDark", l: "leaf", L: "leafLight", m: "moss", t: "trunkDark", T: "trunk" },
338
+ ),
339
+
340
+ // ── Backend biome trees (Deep Woods) ──────────────────────────
341
+ seedling: parseSprite(
342
+ `
343
+ d
344
+ dLd
345
+ d
346
+ t
347
+ `,
348
+ { d: "leafDark", L: "leaf", t: "trunk" },
349
+ ),
350
+ thin_birch: parseSprite(
351
+ `
352
+ dL
353
+ dLLd
354
+ dLLd
355
+ dLd
356
+ bB
357
+ Bb
358
+ bB
359
+ `,
360
+ { d: "leafDark", L: "leaf", b: "birchBark", B: "birchShadow" },
361
+ ),
362
+ tall_pine: parseSprite(
363
+ `
364
+ d
365
+ dLd
366
+ dLd
367
+ ddLdd
368
+ dLLLd
369
+ ddLLLdd
370
+ dLLLd
371
+ tT
372
+ tt
373
+ `,
374
+ { d: "leafDark", L: "leaf", t: "trunk", T: "trunkLight" },
375
+ ),
376
+ dark_oak: parseSprite(
377
+ `
378
+ ddddd
379
+ ddLLLdd
380
+ dddLLLddd
381
+ ddLLLLLdd
382
+ dddLLLddd
383
+ ddddddd
384
+ ddddd
385
+ tTt
386
+ ttt
387
+ `,
388
+ { d: "leafDark", L: "leaf", t: "trunk", T: "trunkLight" },
389
+ ),
390
+ dense_spruce: parseSprite(
391
+ `
392
+ dd
393
+ dLd
394
+ ddLdd
395
+ dLLLd
396
+ ddLLLdd
397
+ dLLLLLd
398
+ ddLLLLLdd
399
+ dLLLLLLLd
400
+ tTt
401
+ ttt
402
+ `,
403
+ { d: "leafDark", L: "leaf", t: "trunk", T: "trunkLight" },
404
+ ),
405
+ moss_oak: parseSprite(
406
+ `
407
+ ddddddd
408
+ dddLLLddd
409
+ dddLLLLLddd
410
+ dddLLmLLLddd
411
+ dddLmmLLddd
412
+ dddmmmdddd
413
+ dddmdddd
414
+ dtTTtd
415
+ tTTTTt
416
+ tt tt
417
+ t t
418
+ `,
419
+ { d: "leafDark", L: "leaf", m: "moss", t: "trunk", T: "trunkLight" },
420
+ ),
421
+ ancient_pine: parseSprite(
422
+ `
423
+ dd
424
+ dLd
425
+ ddLdd
426
+ dLLLd
427
+ ddLLLdd
428
+ dLLLLLd
429
+ ddLLLLLdd
430
+ dLLLLLLLd
431
+ ddLLLLLLLdd
432
+ dLLLLLLLLLd
433
+ ddLLLLLLLLLdd
434
+ tTTTt
435
+ ttttt
436
+ `,
437
+ { d: "leafDark", L: "leaf", t: "trunk", T: "trunkLight" },
438
+ ),
439
+
440
+ // ── AI/ML biome trees (Bioluminescent Grove) ──────────────────
441
+ spore: parseSprite(
442
+ `
443
+ lL
444
+ lLl
445
+ t
446
+ t
447
+ `,
448
+ { l: "leaf", L: "leafLight", t: "trunkDark" },
449
+ ),
450
+ glowstem: parseSprite(
451
+ `
452
+ LL
453
+ lLLl
454
+ lLl
455
+ tT
456
+ tT
457
+ tt
458
+ `,
459
+ { l: "leaf", L: "leafLight", t: "trunkDark", T: "trunk" },
460
+ ),
461
+ crystal_sapling: parseSprite(
462
+ `
463
+ cCc
464
+ cCCCc
465
+ CcCCc
466
+ cCCc
467
+ tTt
468
+ tTt
469
+ tt
470
+ `,
471
+ { c: "crystal1", C: "crystal2", t: "trunkDark", T: "trunk" },
472
+ ),
473
+ mycelium_tree: parseSprite(
474
+ `
475
+ lLLLl
476
+ llLLLll
477
+ lLlLLlLLl
478
+ llLLLLLll
479
+ lLLLLLl
480
+ lLLLl
481
+ tTTt
482
+ tTt
483
+ ttt
484
+ `,
485
+ { l: "leaf", L: "leafLight", t: "trunkDark", T: "trunk" },
486
+ ),
487
+ neural_oak: parseSprite(
488
+ `
489
+ LlLLlL
490
+ lLLlLLLLl
491
+ lLLlLLlLLLl
492
+ llLLLLLLLLl
493
+ lLLLlLLLl
494
+ lLLLLLl
495
+ lLLLl
496
+ tTTt
497
+ tTTt
498
+ tttt
499
+ `,
500
+ { l: "leaf", L: "leafLight", t: "trunkDark", T: "trunk" },
501
+ ),
502
+ void_willow: parseSprite(
503
+ `
504
+ lLLLLl
505
+ lLLLLLLl
506
+ lLLl lLLl
507
+ lLLl lLLl
508
+ lLl tT lLl
509
+ ll tT ll
510
+ l tT l
511
+ tT
512
+ tTTt
513
+ tt tt
514
+ t t
515
+ `,
516
+ { l: "leaf", L: "leafLight", t: "trunkDark", T: "trunk" },
517
+ ),
518
+ ancient_node: parseSprite(
519
+ `
520
+ lLLLLLl
521
+ lLLLlLLLl
522
+ lLLlLLlLLLl
523
+ lLLLLLLLLLLLl
524
+ lLLLlLLLLlLLLl
525
+ lLLLLlLLLLLl
526
+ lLLLLLLLLl
527
+ lLLLLLLl
528
+ ltTTTtl
529
+ tTTTTTt
530
+ tTt tTt
531
+ tt tt
532
+ t t
533
+ `,
534
+ { l: "leaf", L: "leafLight", t: "trunkDark", T: "trunk" },
535
+ ),
536
+
537
+ // ── Infra biome trees (Tundra) ────────────────────────────────
538
+ frozen_sprout: parseSprite(
539
+ `
540
+ lL
541
+ ll
542
+ ld
543
+ t
544
+ `,
545
+ { l: "leaf", L: "leafLight", d: "leafDark", t: "trunk" },
546
+ ),
547
+ bare_sapling: parseSprite(
548
+ `
549
+ l
550
+ lLl
551
+ ld
552
+ tT
553
+ Tt
554
+ tT
555
+ tt
556
+ `,
557
+ { l: "leaf", L: "leafLight", d: "leafDark", t: "trunk", T: "trunkLight" },
558
+ ),
559
+ hardy_pine: parseSprite(
560
+ `
561
+ d
562
+ dld
563
+ dld
564
+ ddldd
565
+ dlLld
566
+ ddlLldd
567
+ dlLld
568
+ tTt
569
+ `,
570
+ { d: "leafDark", l: "leaf", L: "leafLight", t: "trunk", T: "trunkLight" },
571
+ ),
572
+ frost_birch: parseSprite(
573
+ `
574
+ dll
575
+ dllLld
576
+ dllLLLld
577
+ dlLLLLld
578
+ dllLld
579
+ dllld
580
+ bBb
581
+ Bbb
582
+ bBb
583
+ `,
584
+ { d: "leafDark", l: "leaf", L: "leafLight", b: "birchBark", B: "birchShadow" },
585
+ ),
586
+ iron_pine: parseSprite(
587
+ `
588
+ d
589
+ dld
590
+ dld
591
+ ddldd
592
+ dlLld
593
+ ddlLldd
594
+ dlLLLld
595
+ ddlLLLldd
596
+ dtTtd
597
+ tttt
598
+ `,
599
+ { d: "leafDark", l: "leaf", L: "leafLight", t: "trunk", T: "trunkLight" },
600
+ ),
601
+ stone_oak: parseSprite(
602
+ `
603
+ ddddddd
604
+ dddllldddd
605
+ dddllLLlldd
606
+ ddllLLLLldd
607
+ dddllLLlddd
608
+ dddllldddd
609
+ ddddddddd
610
+ ddtTTtdd
611
+ tTTTTt
612
+ tt tt
613
+ t t
614
+ `,
615
+ { d: "leafDark", l: "leaf", L: "leafLight", t: "trunk", T: "trunkLight" },
616
+ ),
617
+ ancient_cedar: parseSprite(
618
+ `
619
+ dd
620
+ ddldd
621
+ dlLld
622
+ ddlLldd
623
+ dlLLLld
624
+ ddlLLLldd
625
+ dlLLLLLld
626
+ ddlLLLLLldd
627
+ dlLLLLLLLld
628
+ ddlLLLLLLLldd
629
+ dtTTTtd
630
+ tTTTt
631
+ ttttt
632
+ `,
633
+ { d: "leafDark", l: "leaf", L: "leafLight", t: "trunk", T: "trunkLight" },
634
+ ),
635
+
636
+ // ── Docs biome trees (Garden Path) ────────────────────────────
637
+ lamp_sprout: parseSprite(
638
+ `
639
+ lLl
640
+ lLl
641
+ lll
642
+ t
643
+ t
644
+ `,
645
+ { l: "leaf", L: "leafLight", t: "trunk" },
646
+ ),
647
+ garden_sapling: parseSprite(
648
+ `
649
+ lLl
650
+ lLLLl
651
+ lLLLl
652
+ lLl
653
+ tTt
654
+ ttt
655
+ `,
656
+ { l: "leaf", L: "leafLight", t: "trunk", T: "trunkLight" },
657
+ ),
658
+ lantern_oak: parseSprite(
659
+ `
660
+ llLll
661
+ lLLLLLl
662
+ lLLLLLLLl
663
+ lLLLLLLLl
664
+ lLLLLLl
665
+ lLLLl
666
+ tTt
667
+ tTt
668
+ ttt
669
+ `,
670
+ { l: "leaf", L: "leafLight", t: "trunk", T: "trunkLight" },
671
+ ),
672
+ path_willow: parseSprite(
673
+ `
674
+ lLLLl
675
+ lLLLLLl
676
+ lLLl lLLl
677
+ lLLl lLLl
678
+ lLl tTt lLl
679
+ l tTt l
680
+ tTt
681
+ tTTTt
682
+ tt tt
683
+ t t
684
+ `,
685
+ { l: "leaf", L: "leafLight", t: "trunk", T: "trunkLight" },
686
+ ),
687
+ library_tree: parseSprite(
688
+ `
689
+ llLLll
690
+ lLLLLLLl
691
+ lLLLLLLLLl
692
+ lLLLLLLLLl
693
+ lLLLLLLLLl
694
+ lLLLLLLl
695
+ lLLLLl
696
+ tTTt
697
+ tTTt
698
+ tttt
699
+ `,
700
+ { l: "leaf", L: "leafLight", t: "trunk", T: "trunkLight" },
701
+ ),
702
+ archive_oak: parseSprite(
703
+ `
704
+ lllLLllll
705
+ llLLLLLLLll
706
+ lllLLLLLLLlll
707
+ llLLLLLLLLLll
708
+ llLLLLLLLll
709
+ llLLLLLll
710
+ llLLLll
711
+ ltTtl
712
+ ttTTTtt
713
+ tt tt
714
+ t t
715
+ `,
716
+ { l: "leaf", L: "leafLight", t: "trunk", T: "trunkLight" },
717
+ ),
718
+ ancient_yew: parseSprite(
719
+ `
720
+ llLLLll
721
+ lLLLLLLLl
722
+ lLLLLLLLLLl
723
+ lLLLLLLLLLLLl
724
+ lLLLLLLLLLLLLLl
725
+ lLLLLLLLLLLLl
726
+ lLLLLLLLLLl
727
+ lLLLLLLLl
728
+ ltTTTtl
729
+ ttTTTTTtt
730
+ tTt tTt
731
+ tt tt
732
+ t t
733
+ `,
734
+ { l: "leaf", L: "leafLight", t: "trunk", T: "trunkLight" },
735
+ ),
246
736
  };
247
737
 
248
738
  const ANIMAL_SPRITES = {
@@ -312,6 +802,151 @@ OooooO
312
802
  t: "trunkDark",
313
803
  },
314
804
  ),
805
+
806
+ // ── Backend biome animals ─────────────────────────────────────
807
+ songbird: parseSprite(
808
+ `
809
+ ww
810
+ wWWw
811
+ Ww
812
+ t
813
+ `,
814
+ { w: "wing", W: "wingLight", t: "trunkDark" },
815
+ ),
816
+ beetle: parseSprite(
817
+ `
818
+ ss
819
+ sSSs
820
+ sSSs
821
+ ss
822
+ `,
823
+ { s: "shell", S: "shellLight" },
824
+ ),
825
+ frog: parseSprite(
826
+ `
827
+ eFFe
828
+ FFFF
829
+ FF F
830
+ `,
831
+ { F: "frog", e: "eye" },
832
+ ),
833
+ wolf: parseSprite(
834
+ `
835
+ ee
836
+ fFFF
837
+ fFFFF
838
+ fF F
839
+ F F
840
+ `,
841
+ { f: "fur", F: "furLight", e: "eye" },
842
+ ),
843
+
844
+ // ── AI/ML biome animals ───────────────────────────────────────
845
+ moth: parseSprite(
846
+ `
847
+ w w
848
+ wW Ww
849
+ WwW
850
+ w
851
+ `,
852
+ { w: "wing", W: "wingLight" },
853
+ ),
854
+ chameleon: parseSprite(
855
+ `
856
+ ecc
857
+ ccccc
858
+ cCCCc
859
+ c c
860
+ `,
861
+ { c: "chameleon", C: "chameleonLight", e: "eye" },
862
+ ),
863
+ spirit_owl: parseSprite(
864
+ `
865
+ eOOe
866
+ OoOoOO
867
+ OOoOOO
868
+ OOOO
869
+ tt
870
+ `,
871
+ { O: "owlLight", o: "owl", e: "eye", t: "trunkDark" },
872
+ ),
873
+
874
+ // ── Infra biome animals ───────────────────────────────────────
875
+ snowbird: parseSprite(
876
+ `
877
+ ww
878
+ wWWw
879
+ Ww
880
+ t
881
+ `,
882
+ { w: "wing", W: "wingLight", t: "trunkDark" },
883
+ ),
884
+ arctic_hare: parseSprite(
885
+ `
886
+ ee
887
+ rrre
888
+ rrrrr
889
+ rr r
890
+ `,
891
+ { r: "hare", e: "hareLight" },
892
+ ),
893
+ hawk: parseSprite(
894
+ `
895
+ eFF
896
+ FFFFF
897
+ FFF
898
+ F F
899
+ `,
900
+ { F: "hawk", e: "eye" },
901
+ ),
902
+ mountain_goat: parseSprite(
903
+ `
904
+ hh
905
+ GG
906
+ GGGG
907
+ G G
908
+ G G
909
+ `,
910
+ { G: "goat", h: "goatLight" },
911
+ ),
912
+ snowy_owl: parseSprite(
913
+ `
914
+ eOOe
915
+ OoOoOO
916
+ OOOOOO
917
+ OOOO
918
+ tt
919
+ `,
920
+ { O: "owlLight", o: "owl", e: "eye", t: "trunkDark" },
921
+ ),
922
+
923
+ // ── Docs biome animals ────────────────────────────────────────
924
+ robin: parseSprite(
925
+ `
926
+ ww
927
+ wRRw
928
+ Rw
929
+ t
930
+ `,
931
+ { w: "wing", R: "robin", t: "trunkDark" },
932
+ ),
933
+ hedgehog: parseSprite(
934
+ `
935
+ sss
936
+ sSSSs
937
+ sSeS
938
+ ss
939
+ `,
940
+ { s: "spine", S: "spineLight", e: "eye" },
941
+ ),
942
+ firefly: parseSprite(
943
+ `
944
+ g
945
+ wGw
946
+ w
947
+ `,
948
+ { g: "glow", G: "glowLight", w: "wing" },
949
+ ),
315
950
  };
316
951
 
317
952
 
@@ -357,8 +992,354 @@ ggg
357
992
  g: "grass",
358
993
  },
359
994
  ),
995
+
996
+ // ── Frontend biome ground elements ────────────────────────────
997
+ wildflower: parseSprite(
998
+ `
999
+ pP
1000
+ pPp
1001
+ g
1002
+ `,
1003
+ { p: "petal", P: "petalLight", g: "grassLight" },
1004
+ ),
1005
+ daisy: parseSprite(
1006
+ `
1007
+ P
1008
+ pPp
1009
+ g
1010
+ `,
1011
+ { p: "petal", P: "petalLight", g: "grassLight" },
1012
+ ),
1013
+ smooth_rock: parseSprite(
1014
+ `
1015
+ rr
1016
+ rrrr
1017
+ rrrr
1018
+ `,
1019
+ { r: "stone" },
1020
+ ),
1021
+ clover: parseSprite(
1022
+ `
1023
+ ll
1024
+ lLl
1025
+ g
1026
+ `,
1027
+ { l: "leaf", L: "leafLight", g: "grassLight" },
1028
+ ),
1029
+
1030
+ // ── Backend biome ground elements ─────────────────────────────
1031
+ fern: parseSprite(
1032
+ `
1033
+ l
1034
+ lLl
1035
+ lLLl
1036
+ lLl
1037
+ l
1038
+ `,
1039
+ { l: "leaf", L: "leafLight" },
1040
+ ),
1041
+ moss_patch: parseSprite(
1042
+ `
1043
+ mmm
1044
+ mMMMm
1045
+ mmm
1046
+ `,
1047
+ { m: "moss", M: "mossLight" },
1048
+ ),
1049
+ old_log: parseSprite(
1050
+ `
1051
+ ttttt
1052
+ TTTTT
1053
+ ttttt
1054
+ `,
1055
+ { t: "trunk", T: "trunkLight" },
1056
+ ),
1057
+ bracket_fungus: parseSprite(
1058
+ `
1059
+ MM
1060
+ MMM
1061
+ s
1062
+ `,
1063
+ { M: "mushroomCap", s: "mushroomStem" },
1064
+ ),
1065
+
1066
+ // ── AI/ML biome ground elements ───────────────────────────────
1067
+ glowing_mushroom: parseSprite(
1068
+ `
1069
+ cCc
1070
+ cCCCc
1071
+ s
1072
+ s
1073
+ `,
1074
+ { c: "crystal1", C: "crystal2", s: "mushroomStem" },
1075
+ ),
1076
+ crystal_shard: parseSprite(
1077
+ `
1078
+ c
1079
+ cCc
1080
+ cCc
1081
+ c
1082
+ `,
1083
+ { c: "crystal1", C: "crystal2" },
1084
+ ),
1085
+ spore_pod: parseSprite(
1086
+ `
1087
+ cc
1088
+ cCCc
1089
+ cCCc
1090
+ cc
1091
+ `,
1092
+ { c: "crystal1", C: "crystal2" },
1093
+ ),
1094
+ root_cluster: parseSprite(
1095
+ `
1096
+ tT
1097
+ tTTt
1098
+ tTt
1099
+ t
1100
+ `,
1101
+ { t: "trunkDark", T: "trunk" },
1102
+ ),
1103
+
1104
+ // ── Infra biome ground elements ───────────────────────────────
1105
+ lichen: parseSprite(
1106
+ `
1107
+ mm
1108
+ mmm
1109
+ `,
1110
+ { m: "moss" },
1111
+ ),
1112
+ frozen_rock: parseSprite(
1113
+ `
1114
+ rRr
1115
+ rrRrr
1116
+ rrrr
1117
+ `,
1118
+ { r: "stone", R: "stoneLight" },
1119
+ ),
1120
+ dead_branch: parseSprite(
1121
+ `
1122
+ t t
1123
+ tttt
1124
+ tt
1125
+ `,
1126
+ { t: "trunkDark" },
1127
+ ),
1128
+ ice_shard: parseSprite(
1129
+ `
1130
+ c
1131
+ cC
1132
+ cC
1133
+ c
1134
+ `,
1135
+ { c: "crystal1", C: "crystal2" },
1136
+ ),
1137
+
1138
+ // ── Docs biome ground elements ────────────────────────────────
1139
+ lantern: parseSprite(
1140
+ `
1141
+ y
1142
+ yYy
1143
+ yYy
1144
+ s
1145
+ s
1146
+ `,
1147
+ { y: "lantern", Y: "lanternLight", s: "trunk" },
1148
+ ),
1149
+ signpost: parseSprite(
1150
+ `
1151
+ sssss
1152
+ SSS
1153
+ t
1154
+ t
1155
+ t
1156
+ `,
1157
+ { s: "sign", S: "signLight", t: "trunk" },
1158
+ ),
1159
+ stepping_stone: parseSprite(
1160
+ `
1161
+ rr
1162
+ rrrr
1163
+ `,
1164
+ { r: "stone" },
1165
+ ),
1166
+ bookmark_flower: parseSprite(
1167
+ `
1168
+ pPp
1169
+ pPPp
1170
+ pg
1171
+ g
1172
+ `,
1173
+ { p: "petal", P: "petalLight", g: "grassLight" },
1174
+ ),
360
1175
  };
361
1176
 
1177
+ const BUSH_SPRITES = {
1178
+ tall_grass_bush: parseSprite(
1179
+ `
1180
+ gGg
1181
+ gGGGg
1182
+ gGGg
1183
+ `,
1184
+ { g: "grass", G: "grassLight" },
1185
+ ),
1186
+ fern_small: parseSprite(
1187
+ `
1188
+ lL
1189
+ lLLl
1190
+ lLl
1191
+ `,
1192
+ { l: "leaf", L: "leafLight" },
1193
+ ),
1194
+ shrub: parseSprite(
1195
+ `
1196
+ dd
1197
+ dLLd
1198
+ dLLLLd
1199
+ dLLd
1200
+ `,
1201
+ { d: "leafDark", L: "leaf" },
1202
+ ),
1203
+
1204
+ // ── Frontend biome bushes ─────────────────────────────────────
1205
+ meadow_shrub: parseSprite(
1206
+ `
1207
+ gGGg
1208
+ gGGGGg
1209
+ gGGg
1210
+ `,
1211
+ { g: "grass", G: "grassLight" },
1212
+ ),
1213
+ flower_bush: parseSprite(
1214
+ `
1215
+ pPPp
1216
+ pPPPPp
1217
+ pPPp
1218
+ `,
1219
+ { p: "petal", P: "petalLight" },
1220
+ ),
1221
+ clover_patch: parseSprite(
1222
+ `
1223
+ lLl
1224
+ lLLLl
1225
+ lLl
1226
+ `,
1227
+ { l: "leaf", L: "leafLight" },
1228
+ ),
1229
+
1230
+ // ── Backend biome bushes ──────────────────────────────────────
1231
+ fern_cluster: parseSprite(
1232
+ `
1233
+ lLLl
1234
+ lLLLLl
1235
+ lLLl
1236
+ `,
1237
+ { l: "leafDark", L: "leaf" },
1238
+ ),
1239
+ moss_mound: parseSprite(
1240
+ `
1241
+ mMm
1242
+ mMMMm
1243
+ mMMMm
1244
+ `,
1245
+ { m: "moss", M: "mossLight" },
1246
+ ),
1247
+ root_tangle: parseSprite(
1248
+ `
1249
+ tTt
1250
+ tTTTt
1251
+ tTt
1252
+ `,
1253
+ { t: "trunkDark", T: "trunk" },
1254
+ ),
1255
+
1256
+ // ── AI/ML biome bushes ────────────────────────────────────────
1257
+ spore_cluster: parseSprite(
1258
+ `
1259
+ cCc
1260
+ cCCCc
1261
+ cCc
1262
+ `,
1263
+ { c: "crystal1", C: "crystal2" },
1264
+ ),
1265
+ glow_moss: parseSprite(
1266
+ `
1267
+ lLl
1268
+ lLLLl
1269
+ lLl
1270
+ `,
1271
+ { l: "leaf", L: "leafLight" },
1272
+ ),
1273
+ mycelium_web: parseSprite(
1274
+ `
1275
+ t tTt
1276
+ tTTTt
1277
+ tTt
1278
+ `,
1279
+ { t: "trunkDark", T: "trunk" },
1280
+ ),
1281
+
1282
+ // ── Infra biome bushes ────────────────────────────────────────
1283
+ dried_shrub: parseSprite(
1284
+ `
1285
+ ddd
1286
+ ddDdd
1287
+ dDd
1288
+ `,
1289
+ { d: "leafDark", D: "leaf" },
1290
+ ),
1291
+ snow_mound: parseSprite(
1292
+ `
1293
+ sss
1294
+ sSSSs
1295
+ sSSs
1296
+ `,
1297
+ { s: "snow", S: "snowLight" },
1298
+ ),
1299
+ lichen_rock: parseSprite(
1300
+ `
1301
+ mrm
1302
+ rrrr
1303
+ rr
1304
+ `,
1305
+ { m: "moss", r: "stone" },
1306
+ ),
1307
+
1308
+ // ── Docs biome bushes ─────────────────────────────────────────
1309
+ garden_shrub: parseSprite(
1310
+ `
1311
+ lLLl
1312
+ lLLLLl
1313
+ lLLl
1314
+ `,
1315
+ { l: "leaf", L: "leafLight" },
1316
+ ),
1317
+ herb_patch: parseSprite(
1318
+ `
1319
+ gGg
1320
+ gGGGg
1321
+ gGg
1322
+ `,
1323
+ { g: "grass", G: "grassLight" },
1324
+ ),
1325
+ ivy_cluster: parseSprite(
1326
+ `
1327
+ dLLd
1328
+ dLLLLd
1329
+ dLLd
1330
+ `,
1331
+ { d: "leafDark", L: "leaf" },
1332
+ ),
1333
+ };
1334
+
1335
+ export function getBushSprite(type) {
1336
+ const sprite = BUSH_SPRITES[type];
1337
+ if (!sprite) {
1338
+ throw new Error(`Unknown bush type: ${type}`);
1339
+ }
1340
+ return sprite;
1341
+ }
1342
+
362
1343
  export function getTreeSprite(species) {
363
1344
  const sprite = TREE_SPRITES[species];
364
1345
  if (!sprite) {
@@ -397,4 +1378,3 @@ export function getSpriteWidth(kind, type) {
397
1378
  }
398
1379
  return getGroundElementSprite(type).width;
399
1380
  }
400
-