/
genbiome.go
871 lines (830 loc) · 56.9 KB
/
genbiome.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
// Package genbiome returns the biome for the given average precipitation and temperature.
package genbiome
import (
"image/color"
)
// Biomes definition
// See: http://www-cs-students.stanford.edu/~amitp/game-programming/polygon-map-generation/#biomes
//
//
// Elevation ||| Moisture Zone ->
// Zone V|| 6 (wet) | 5 | 4 | 3 | 2 | 1 (dry) |
// ==================================================================================
// 4 (high) || SNOW ---------------------------| TUNDRA --| BARE -----| SCORCHED -|
// ----------------------------------------------------------------------------------
// 3 || TAIGA ---------------| SHRUBLAND ----------| TEMPERATE DESERT ------|
// ----------------------------------------------------------------------------------
// 2 || TEMPERATE -| TEMPERATE ---------| GRASSLAND -----------| TEMPERATE -|
// || RAIN FOREST| SEASONAL FOREST ---| ---------------------| DESERT ----|
// ----------------------------------------------------------------------------------
// 1 (low) || TROPICAL RAIN FOREST | TROPICAL SEASONAL --| GRASSLAND | SUBTROPICAL|
// || ---------------------| FOREST -------------| ----------| DESERT ----|
// ----------------------------------------------------------------------------------
var RedblobLookupTable = [][]int{
{0x7, 0xA, 0x8, 0x8, 0x5, 0x5},
{0x9, 0xA, 0xA, 0x8, 0x8, 0x5},
{0x9, 0x9, 0x3, 0x3, 0x2, 0x2},
{0xD, 0xC, 0x1, 0xB, 0xB, 0xB},
}
// The RedBlobGames biomes.
const (
RedblobBiomeUnknown = 0x0
RedblobBiomeTundra = 0x1
RedblobBiomeTaiga = 0x2
RedblobBiomeShrubland = 0x3
RedblobBiomeTemperateRainForest = 0x4
RedblobBiomeTropicalRainForest = 0x5
RedblobBiomeTropicalSeasonalForest = 0x6
RedblobBiomeSubtropicalDesert = 0x7
RedblobBiomeTemperateSeasonalForest = 0x8
RedblobBiomeTemperateDesert = 0x9 // combined with BioGrassland in whittaker
RedblobBiomeGrassland = 0xA // combined with BioTemperateDesert in whittaker
RedblobBiomeSnow = 0xB // not in whittaker
RedblobBiomeBare = 0xC // not in whittaker
RedblobBiomeScorched = 0xD // not in whittaker
)
// GetWhittakerBiome returns the RedBlobGames biome for the given height and moisture zones.
func GetRedblobBiome(height, moisture int) int {
height = RedblobClampHeightToIndex(height)
moisture = RedblobClampMoistureToIndex(moisture)
return RedblobLookupTable[height][moisture]
}
// RedblobBiomeColor maps the (RedBlobGames) biome types to their color representation.
var RedblobBiomeColor = map[int]color.NRGBA{
RedblobBiomeSnow: ColorSnowIce,
RedblobBiomeTundra: {0xDD, 0xDD, 0xBB, 0xFF},
RedblobBiomeBare: {0xBB, 0xBB, 0xBB, 0xFF},
RedblobBiomeScorched: {0x99, 0x99, 0x99, 0xFF},
RedblobBiomeTaiga: {0xCC, 0xD4, 0xBB, 0xFF},
RedblobBiomeShrubland: {0xC4, 0xCC, 0xBB, 0xFF},
RedblobBiomeTemperateDesert: {0xE4, 0xE8, 0xCA, 0xFF},
RedblobBiomeTemperateRainForest: {0xA4, 0xC4, 0xA8, 0xFF},
RedblobBiomeTemperateSeasonalForest: {0xB4, 0xC9, 0xA9, 0xFF},
RedblobBiomeTropicalRainForest: {0x9C, 0xBB, 0xA9, 0xFF},
RedblobBiomeTropicalSeasonalForest: {0xA9, 0xCC, 0xA4, 0xFF},
RedblobBiomeGrassland: {0xC4, 0xD4, 0xAA, 0xFF},
RedblobBiomeSubtropicalDesert: {0xE9, 0xDD, 0xC7, 0xFF},
}
// GetRedblobBiomeColor returns a color representing the (RedBlobGames) biome
// with the given height and moisture zones.
//
// The intensity (ranging from 0.0-1.0) allows darkening / brightening for (for example)
// indicating elevation. ... lower might be darker (0.0), higher might be brighter (1.0).
func GetRedblobBiomeColor(height, moisture int, intensity float64) color.NRGBA {
c := RedblobBiomeColor[GetRedblobBiome(height, moisture)]
return color.NRGBA{
R: uint8(intensity * float64(c.R)),
G: uint8(intensity * float64(c.G)),
B: uint8(intensity * float64(c.B)),
A: 255,
}
}
func RedblobClampHeightToIndex(height int) int {
if height < 1 {
return 0
}
if height > 4 {
return 3
}
return height - 1
}
func RedblobClampMoistureToIndex(moisture int) int {
if moisture < 1 {
return 0
}
if moisture > 6 {
return 5
}
return moisture - 1
}
// Whittaker biomes based on:
// https://github.com/JoeyR/FastBiome
var WhittakerLookupTable = [][]int{
// <- +30°C | 0 °C |<- -15°C
{0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9}, // 0dm precipitation
{0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x6, 0x6, 0x6, 0x6, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9},
{0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x6, 0x6, 0x6, 0x6, 0x8, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9},
{0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x8, 0x8, 0x9, 0x9, 0x9, 0x9, 0x9, 0x0, 0x0, 0x0, 0x0},
{0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x7, 0x7, 0x7, 0x7, 0x7, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x8, 0x8, 0x8, 0x8, 0x9, 0x9, 0x9, 0x9, 0x9, 0x0, 0x0, 0x0, 0x0},
{0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x2, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x5, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x9, 0x9, 0x9, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x2, 0x2, 0x2, 0x2, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x5, 0x5, 0x5, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x9, 0x9, 0x9, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x5, 0x5, 0x5, 0x5, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x9, 0x9, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x3, 0x3, 0x3, 0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x9, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x3, 0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x6, 0x6, 0x6, 0x6, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x6, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x4, 0x8, 0x8, 0x8, 0x8, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x4, 0x4, 0x8, 0x8, 0x8, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x4, 0x8, 0x8, 0x8, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x4, 0x4, 0x8, 0x8, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x4, 0x4, 0x4, 0x8, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x5, 0x5, 0x5, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x4, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, // 45dm precipitation
}
// The Whittaker biomes.
const (
WhittakerBiomeUnknown = 0x0
WhittakerBiomeTropicalRainForest = 0x1
WhittakerBiomeTropicalSeasonalForestSavanna = 0x2
WhittakerBiomeSubtropicalDesert = 0x3
WhittakerBiomeTemperateRainForest = 0x4
WhittakerBiomeTemperateSeasonalForest = 0x5
WhittakerBiomeWoodlandShrubland = 0x6
WhittakerBiomeTemperateGrasslandDesert = 0x7
WhittakerBiomeBorealForestTaiga = 0x8
WhittakerBiomeTundra = 0x9
)
// GetWhittakerBiome returns the Whittaker biome for the given temperature and precipitation.
func GetWhittakerBiome(temperature, precipitation int) int {
temperature = WhittakerClampTemperatureToIndex(temperature)
precipitation = WhittakerClampPrecipitationToIndex(precipitation)
return WhittakerLookupTable[precipitation][temperature]
}
// WhittakerBiomeColor maps the (Whittaker) biome types to their color representation.
var WhittakerBiomeColor = map[int]color.NRGBA{
WhittakerBiomeTropicalRainForest: {0x9C, 0xBB, 0xA9, 0xFF},
WhittakerBiomeTropicalSeasonalForestSavanna: {0xA9, 0xCC, 0xA4, 0xFF},
WhittakerBiomeSubtropicalDesert: {0xE9, 0xDD, 0xC7, 0xFF},
WhittakerBiomeTemperateRainForest: {0xA4, 0xC4, 0xA8, 0xFF},
WhittakerBiomeTemperateSeasonalForest: {0xB4, 0xC9, 0xA9, 0xFF},
WhittakerBiomeWoodlandShrubland: {0xC4, 0xCC, 0xBB, 0xFF},
WhittakerBiomeTemperateGrasslandDesert: {0xE4, 0xE8, 0xCA, 0xFF},
WhittakerBiomeBorealForestTaiga: {0xCC, 0xD4, 0xBB, 0xFF},
WhittakerBiomeTundra: {0xDD, 0xDD, 0xBB, 0xFF},
}
// GetWhittakerModBiomeColor returns a color representing the (Whittaker) biome
// with the given temperature and precipitation.
//
// The intensity (ranging from 0.0-1.0) allows darkening / brightening for (for example)
// indicating elevation. ... lower might be darker (0.0), higher might be brighter (1.0).
func GetWhittakerBiomeColor(temperature, precipitation int, intensity float64) color.NRGBA {
c := WhittakerBiomeColor[GetWhittakerBiome(temperature, precipitation)]
return color.NRGBA{
R: uint8(intensity * float64(c.R)),
G: uint8(intensity * float64(c.G)),
B: uint8(intensity * float64(c.B)),
A: 255,
}
}
var WhittakerLookupTableModified = [][]int{
// <- +30°C | 0 °C |<- -15°C
{0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA}, // 0dm precipitation
{0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x6, 0x6, 0x6, 0x6, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0xB},
{0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x6, 0x6, 0x6, 0x6, 0x8, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0xB, 0xB},
{0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x8, 0x8, 0x9, 0x9, 0x9, 0x9, 0x9, 0xB, 0xB, 0xB, 0xB},
{0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x7, 0x7, 0x7, 0x7, 0x7, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x8, 0x8, 0x8, 0x8, 0x9, 0x9, 0x9, 0x9, 0x9, 0xB, 0xB, 0xB, 0xB},
{0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0xE, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x5, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x9, 0x9, 0x9, 0x9, 0xB, 0xB, 0xB, 0xB, 0xB},
{0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0xE, 0xE, 0xE, 0xE, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x5, 0x5, 0x5, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x9, 0x9, 0x9, 0x9, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0xE, 0xE, 0xE, 0xE, 0xE, 0xE, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x5, 0x5, 0x5, 0x5, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x9, 0x9, 0x9, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0x3, 0x3, 0x3, 0x3, 0xE, 0xE, 0xE, 0xE, 0xE, 0xE, 0xE, 0xE, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x9, 0x9, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0x3, 0x3, 0xE, 0xE, 0xE, 0xE, 0xE, 0xE, 0xE, 0xE, 0xE, 0xE, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x9, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0xE, 0xE, 0xE, 0xE, 0xE, 0xE, 0xE, 0xE, 0x2, 0x2, 0x2, 0x2, 0x6, 0x6, 0x6, 0x6, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0xE, 0xE, 0xE, 0xE, 0xE, 0xE, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x6, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0xE, 0xE, 0xE, 0xE, 0xE, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0xE, 0xE, 0xE, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0xE, 0xE, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0xE, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x4, 0x8, 0x8, 0x8, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x4, 0x4, 0x8, 0x8, 0x8, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x4, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x4, 0x4, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x4, 0x4, 0x4, 0x8, 0x8, 0xD, 0x8, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x4, 0x4, 0x4, 0x4, 0xD, 0xD, 0xD, 0xD, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0xD, 0xD, 0xD, 0xD, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x5, 0x5, 0x5, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x4, 0x4, 0x4, 0x4, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x4, 0x4, 0x4, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x4, 0x4, 0x4, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x4, 0x4, 0x4, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x4, 0x4, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0xC, 0xC, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0xC, 0xC, 0xC, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0xC, 0xC, 0xC, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0xC, 0xC, 0xC, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0x8, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0xC, 0xC, 0xC, 0xC, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0xC, 0xC, 0xC, 0xC, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0xC, 0xC, 0xC, 0xC, 0xC, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0xC, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0xC, 0xC, 0xC, 0xC, 0xC, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0xC, 0xC, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0xC, 0xC, 0xC, 0xC, 0xC, 0xC, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0xC, 0xC, 0x1, 0x1, 0x1, 0x1, 0x1, 0xC, 0xC, 0xC, 0xC, 0xC, 0xC, 0xC, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0xC, 0xC, 0xC, 0x1, 0x1, 0x1, 0x1, 0xC, 0xC, 0xC, 0xC, 0xC, 0xC, 0xC, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB},
{0xC, 0xC, 0xC, 0xC, 0x1, 0x1, 0xC, 0xC, 0xC, 0xC, 0xC, 0xC, 0xC, 0xC, 0xC, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0x8, 0x8, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB, 0xB}, // 45dm precipitation
}
// The modified Whittaker biomes.
const (
WhittakerModBiomeUnknown = 0x0
WhittakerModBiomeTropicalRainforest = 0x1
WhittakerModBiomeTropicalSeasonalForest = 0x2
WhittakerModBiomeSubtropicalDesert = 0x3
WhittakerModBiomeTemperateRainforest = 0x4
WhittakerModBiomeTemperateSeasonalForest = 0x5
WhittakerModBiomeWoodlandShrubland = 0x6
WhittakerModBiomeTemperateGrassland = 0x7
WhittakerModBiomeBorealForestTaiga = 0x8
WhittakerModBiomeTundra = 0x9
WhittakerModBiomeColdDesert = 0xA // Cold, dry winters, possibly warm, dry summers.
WhittakerModBiomeSavannah = 0xE // Hot, dry, grassland.
// Not covered by Whittaker:
WhittakerModBiomeSnow = 0xB // Precipitation (any), temperature below freezing (includes glaciers).
WhittakerModBiomeHotSwamp = 0xC // Hot, lots of precipitation, tropical swamps!
WhittakerModBiomeWetlands = 0xD // Temperate but lots of precipitation (marshes, cold swamps, etc.).
)
// WhittakerModBiomeToString returns a string representation of the given biome.
func WhittakerModBiomeToString(biome int) string {
switch biome {
case WhittakerModBiomeUnknown:
return "unknown"
case WhittakerModBiomeTropicalRainforest:
return "tropical rainforest"
case WhittakerModBiomeTropicalSeasonalForest:
return "tropical seasonal forest"
case WhittakerModBiomeSubtropicalDesert:
return "subtropical desert"
case WhittakerModBiomeTemperateRainforest:
return "temperate rainforest"
case WhittakerModBiomeTemperateSeasonalForest:
return "temperate seasonal forest"
case WhittakerModBiomeWoodlandShrubland:
return "woodland shrubland"
case WhittakerModBiomeTemperateGrassland:
return "temperate grassland"
case WhittakerModBiomeBorealForestTaiga:
return "boreal forest taiga"
case WhittakerModBiomeTundra:
return "tundra"
case WhittakerModBiomeColdDesert:
return "cold desert"
case WhittakerModBiomeSavannah:
return "savannah"
case WhittakerModBiomeSnow:
return "snow"
case WhittakerModBiomeHotSwamp:
return "hot swamp"
case WhittakerModBiomeWetlands:
return "wetlands"
default:
return "unknown"
}
}
// GetWhittakerModBiome returns the (modified) Whittaker biome for the given temperature and precipitation.
func GetWhittakerModBiome(temperature, precipitation int) int {
temperature = WhittakerClampTemperatureToIndex(temperature)
precipitation = WhittakerClampPrecipitationToIndex(precipitation)
return WhittakerLookupTableModified[precipitation][temperature]
}
var (
ColorRainforest = color.NRGBA{R: 0x1d, G: 0xBA, B: 0x37, A: 0xFF}
ColorSeasonalForest = color.NRGBA{R: 0x28, G: 0xAC, B: 0x2A, A: 0xFF}
ColorSnowIce = color.NRGBA{R: 0xFF, G: 0xFF, B: 0xFF, A: 0xFF}
)
// WhittakerModBiomeColor maps the (modified Whittaker) biome types to their color representation.
var WhittakerModBiomeColor = map[int]color.NRGBA{
WhittakerModBiomeUnknown: {0, 0, 0, 0xFF}, // {0xA9, 0, 0, 0xFF}, // TODO: Find better solution. It's wet and with relative cool temperature.
WhittakerModBiomeTropicalRainforest: ColorRainforest,
WhittakerModBiomeTropicalSeasonalForest: ColorSeasonalForest,
WhittakerModBiomeSubtropicalDesert: {0xfd, 0xe3, 0x8d, 0xFF}, // was 0xE9DDC7
WhittakerModBiomeTemperateRainforest: ColorRainforest,
WhittakerModBiomeTemperateSeasonalForest: ColorSeasonalForest,
WhittakerModBiomeWoodlandShrubland: {0x91, 0x90, 0x16, 0xFF},
WhittakerModBiomeTemperateGrassland: {0x97, 0xE9, 0x87, 0xFF},
WhittakerModBiomeBorealForestTaiga: {0x58, 0x9F, 0x5A, 0xFF},
WhittakerModBiomeTundra: {0x69, 0xB0, 0x0B, 0xFF},
WhittakerModBiomeColdDesert: {0xDD, 0xDD, 0xC0, 0xFF},
WhittakerModBiomeHotSwamp: {0x96, 0x4B, 0x00, 0xFF},
WhittakerModBiomeWetlands: {0x0B, 0xB0, 0x1B, 0xFF}, // TODO: Find a better color
WhittakerModBiomeSavannah: {0xff, 0xd1, 0x45, 0xFF},
WhittakerModBiomeSnow: ColorSnowIce,
}
// GetWhittakerModBiomeColor returns a color representing the (modified Whittaker) biome
// with the given temperature and precipitation.
//
// The intensity (ranging from 0.0-1.0) allows darkening / brightening for (for example)
// indicating elevation. ... lower might be darker (0.0), higher might be brighter (1.0).
func GetWhittakerModBiomeColor(temperature, precipitation int, intensity float64) color.NRGBA {
c := WhittakerModBiomeColor[GetWhittakerModBiome(temperature, precipitation)]
return color.NRGBA{
R: uint8(intensity * float64(c.R)),
G: uint8(intensity * float64(c.G)),
B: uint8(intensity * float64(c.B)),
A: 255,
}
}
// Whittaker constants.
const (
// Temperature range.
MinTemperatureC = -15
MaxTemperatureC = 30
// Precipitation range.
MinPrecipitationDM = 0
MaxPrecipitationDM = 45
)
// WhittakerClampTemperatureToIndex clamps the given temperature (yearly average) to the range of the lookup table.
func WhittakerClampTemperatureToIndex(temp int) int {
if temp <= MinTemperatureC {
return 44
}
if temp >= MaxTemperatureC {
return 0
}
return 44 - (temp + 15)
}
// WhittakerClampPrecipitationToIndex clamps the precipitation (in dm/year) to the range of the lookup table.
func WhittakerClampPrecipitationToIndex(prec int) int {
if prec >= MaxPrecipitationDM {
return 44
}
if prec <= MinPrecipitationDM {
return 0
}
return prec
}
// AzgaarLookupTable maps temperature and moisture to biome.
// See: https://github.com/Azgaar/Fantasy-Map-Generator/blob/master/main.js
var AzgaarLookupTable = [5][26]int{
// hot ↔ cold [>19°C; <-4°C]; dry ↕ wet
{1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10},
{3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 9, 9, 10, 10, 10},
{5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 9, 9, 9, 9, 9, 10, 10, 10},
{5, 6, 6, 6, 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10},
{7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10},
}
var azgaarBiomeName = [13]string{
"Marine",
"Hot desert",
"Cold desert",
"Savanna",
"Grassland", //4
"Tropical seasonal forest", //5
"Temperate deciduous forest", //6
"Tropical rainforest", //7
"Temperate rainforest", //8
"Taiga", //9
"Tundra", //10
"Glacier", //11
"Wetland", //12
}
// Biomes as per Azgaar's map generator.
const (
AzgaarBiomeMarine = iota
AzgaarBiomeHotDesert
AzgaarBiomeColdDesert
AzgaarBiomeSavanna
AzgaarBiomeGrassland
AzgaarBiomeTropicalSeasonalForest
AzgaarBiomeTemperateDeciduousForest
AzgaarBiomeTropicalRainforest
AzgaarBiomeTemperateRainforest
AzgaarBiomeTaiga
AzgaarBiomeTundra
AzgaarBiomeGlacier
AzgaarBiomeWetland
)
// AzgaarBiomeColor maps Azgaar's biome IDs to their color representation.
var AzgaarBiomeColor = [13]color.NRGBA{
{R: 0x46, G: 0x6e, B: 0xab, A: 0xFF},
{R: 0xfb, G: 0xe7, B: 0x9f, A: 0xFF},
{R: 0xb5, G: 0xb8, B: 0x87, A: 0xFF},
{R: 0xd2, G: 0xd0, B: 0x82, A: 0xFF},
{R: 0xc8, G: 0xd6, B: 0x8f, A: 0xFF},
{R: 0xb6, G: 0xd9, B: 0x5d, A: 0xFF},
{R: 0x29, G: 0xbc, B: 0x56, A: 0xFF},
{R: 0x7d, G: 0xcb, B: 0x35, A: 0xFF},
{R: 0x40, G: 0x9c, B: 0x43, A: 0xFF},
{R: 0x4b, G: 0x6b, B: 0x32, A: 0xFF},
{R: 0x96, G: 0x78, B: 0x4b, A: 0xFF},
{R: 0xd5, G: 0xe7, B: 0xeb, A: 0xFF},
{R: 0x0b, G: 0x91, B: 0x31, A: 0xFF},
}
// Habitability as per Azgaar's map generator.
var AzgaarBiomeHabitability = [13]int{0, 4, 10, 22, 30, 50, 100, 80, 90, 12, 4, 0, 12}
// Biome movement cost as per Azgaar's map generator.
var AzgaarBiomeMovementCost = [13]int{10, 200, 150, 60, 50, 70, 70, 80, 90, 200, 1000, 5000, 150}
// GetAzgaarBiome returns the biome for the given temperature, elevation, and precipitation.
//
// NOTE:
// - Elevation ranges from 0 to 100. (everything below 20 is considered water)
// - Temperature ranges from -5 to 20.
// - Moisture ranges from 0 to 20.
func GetAzgaarBiome(moisture, temperature, height int) int {
if height < 0 {
return 0 // marine biome: all water cells
}
if temperature < -5 {
return 11 // permafrost biome
}
if isAzgaarWetland(moisture, temperature, height) {
return 12 // wetland biome
}
moistureBand := min((moisture / 5), 4) // [0-4]
temperatureBand := min(max(20-temperature, 0), 25) // [0-25]
return AzgaarLookupTable[moistureBand][temperatureBand]
}
// GetAzgaarBiomeColor returns the biome color for the given temperature, elevation, and precipitation.
//
// NOTE:
// - Elevation ranges from 0 to 100. (everything below 20 is considered water)
// - Temperature ranges from -5 to 20.
// - Moisture ranges from 0 to 20.
func GetAzgaarBiomeColor(moisture, temperature, height int, intensity float64) color.NRGBA {
c := AzgaarBiomeColor[GetAzgaarBiome(moisture, temperature, height)]
return color.NRGBA{
R: uint8(intensity * float64(c.R)),
G: uint8(intensity * float64(c.G)),
B: uint8(intensity * float64(c.B)),
A: 255,
}
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
// isAzgaarWetland returns true if the region is considered a wetland.
func isAzgaarWetland(moisture, temperature, height int) bool {
if moisture > 40 && temperature > -2 && height < 25 {
return true //near coast
}
if moisture > 24 && temperature > -2 && height > 24 && height < 60 {
return true //off coast
}
return false
}
// KoppenGeigerClimate is a climate classification based on the Koppen-Geiger system.
//
// See: https://en.wikipedia.org/wiki/K%C3%B6ppen_climate_classification
// See: https://forhinhexes.blogspot.com/2019/12/koppen-geiger-climate-classification.html
//
// Köppen climate classification scheme symbols description table
// 1st ---------------- 2nd ------------------- 3rd
// A (Tropical) ------- f (Rainforest)
// -------------------- m (Monsoon)
// -------------------- w (Savanna, dry winter)
// -------------------- s (Savanna, dry summer)
// B (Dry) ------------ W (Arid Desert) ------- h (Hot)
// -------------------- S (Semi-Arid or steppe) k (Cold)
// C (Temperate) ------ w (Dry winter) -------- a (Hot summer)
// -------------------- f (No dry season) ----- b (Warm summer)
// -------------------- s (Dry summer) -------- c (Cold summer)
// D (Continental) w (Dry winter) -------- a (Hot summer)
// -------------------- f (No dry season) ----- b (Warm summer)
// -------------------- s (Dry summer) -------- c (Cold summer)
// -------------------------------------------- d (Very cold winter)
// E (Polar) ---------------------------------- T (Tundra)
// -------------------------------------------- F (Ice cap)
// type KoppenGeigerClimate int
/*
const (
KoppenGeigerClimateAf KoppenGeigerClimate = iota // Tropical rainforest
KoppenGeigerClimateAm // Tropical monsoon
KoppenGeigerClimateAw // Tropical savanna
KoppenGeigerClimateBWh // Hot desert
KoppenGeigerClimateBWk // Cold desert
KoppenGeigerClimateBSh // Hot steppe
KoppenGeigerClimateBSk // Cold steppe
KoppenGeigerClimateCsa // Dry summer, hot summer
KoppenGeigerClimateCsb // Dry summer, warm summer
KoppenGeigerClimateCsc // Dry summer, cold summer
KoppenGeigerClimateCwa // Dry winter, hot summer
KoppenGeigerClimateCwb // Dry winter, warm summer
KoppenGeigerClimateCwc // Dry winter, cold summer
KoppenGeigerClimateCfa // Humid subtropical
KoppenGeigerClimateCfb // Maritime temperate
KoppenGeigerClimateCfc // Maritime subarctic
KoppenGeigerClimateDsa // Dry summer, continental, hot summer
KoppenGeigerClimateDsb // Dry summer, continental, warm summer
KoppenGeigerClimateDsc // Dry summer, continental, cool summer
KoppenGeigerClimateDsd // Dry summer, continental, very cold winter
KoppenGeigerClimateDwa // Dry winter, continental, hot summer
KoppenGeigerClimateDwb // Dry winter, continental, warm summer
KoppenGeigerClimateDwc // Dry winter, continental, cool summer
KoppenGeigerClimateDwd // Dry winter, continental, very cold winter
KoppenGeigerClimateDfa // Humid continental, hot summer
KoppenGeigerClimateDfb // Humid continental, warm summer
KoppenGeigerClimateDfc // Humid continental, cool summer
KoppenGeigerClimateDfd // Humid continental, very cold winter
KoppenGeigerClimateET // Polar tundra
KoppenGeigerClimateEF // Polar ice cap
KoppenGeigerClimateUnknown // Unknown
)
// KoppenGeigerClimateColor maps Koppen-Geiger climate IDs to their color representation.
var KoppenGeigerClimateColor = map[KoppenGeigerClimate]color.NRGBA{
KoppenGeigerClimateAf: {R: 0x00, G: 0x00, B: 0xFF}, // Tropical rainforest
KoppenGeigerClimateAm: {R: 0x00, G: 0x78, B: 0xFF}, // Tropical monsoon
KoppenGeigerClimateAw: {R: 0x46, G: 0xAA, B: 0xFA}, // Tropical savanna
KoppenGeigerClimateBWh: {R: 0xFF, G: 0x00, B: 0x00}, // Hot desert
KoppenGeigerClimateBWk: {R: 0xFF, G: 0x96, B: 0x96}, // Cold desert
KoppenGeigerClimateBSh: {R: 0xF5, G: 0xA5, B: 0x00}, // Hot steppe
KoppenGeigerClimateBSk: {R: 0xFF, G: 0xDC, B: 0x64}, // Cold steppe
KoppenGeigerClimateCsa: {R: 0xFF, G: 0xFF, B: 0x00}, // Dry summer, subtropical
KoppenGeigerClimateCsb: {R: 0xC8, G: 0xC8, B: 0x00}, // Dry summer, cooler subtropical
KoppenGeigerClimateCsc: {R: 0x96, G: 0x96, B: 0x00}, // Dry summer, maritime temperate
KoppenGeigerClimateCwa: {R: 0x96, G: 0xFF, B: 0x96}, // Dry winter, humid subtropical
KoppenGeigerClimateCwb: {R: 0x64, G: 0xC8, B: 0x64}, // Dry winter, maritime temperate
KoppenGeigerClimateCwc: {R: 0x32, G: 0x96, B: 0x32}, // Dry winter, cooler maritime temperate
KoppenGeigerClimateCfa: {R: 0xC8, G: 0xFF, B: 0x50}, // Humid subtropical
KoppenGeigerClimateCfb: {R: 0x64, G: 0xFF, B: 0x50}, // Maritime temperate
KoppenGeigerClimateCfc: {R: 0x32, G: 0xC8, B: 0x00}, // Maritime subarctic
KoppenGeigerClimateDsa: {R: 0xFF, G: 0x00, B: 0xFF}, // Dry summer, continental, hot summer
KoppenGeigerClimateDsb: {R: 0xC8, G: 0x00, B: 0xC8}, // Dry summer, continental, warm summer
KoppenGeigerClimateDsc: {R: 0x96, G: 0x00, B: 0x96}, // Dry summer, continental, cool summer
KoppenGeigerClimateDsd: {R: 0x64, G: 0x00, B: 0x64}, // Dry summer, continental, very cold winter
KoppenGeigerClimateDwa: {R: 0xFF, G: 0x96, B: 0x00}, // Dry winter, continental, hot summer
KoppenGeigerClimateDwb: {R: 0xC8, G: 0x64, B: 0x00}, // Dry winter, continental, warm summer
KoppenGeigerClimateDwc: {R: 0x96, G: 0x32, B: 0x00}, // Dry winter, continental, cool summer
KoppenGeigerClimateDwd: {R: 0x64, G: 0x00, B: 0x00}, // Dry winter, continental, very cold winter
KoppenGeigerClimateDfa: {R: 0xFF, G: 0x64, B: 0x00}, // Humid continental, hot summer
KoppenGeigerClimateDfb: {R: 0xC8, G: 0x32, B: 0x00}, // Humid continental, warm summer
KoppenGeigerClimateDfc: {R: 0x96, G: 0x00, B: 0x00}, // Humid continental, cool summer
KoppenGeigerClimateDfd: {R: 0x64, G: 0x00, B: 0x00}, // Humid continental, very cold winter
KoppenGeigerClimateET: {R: 0xB2, G: 0xB2, B: 0xB2}, // Polar tundra
KoppenGeigerClimateEF: {R: 0xFF, G: 0xFF, B: 0xFF}, // Polar ice cap
KoppenGeigerClimateUnknown: {R: 0x00, G: 0x00, B: 0x00}, // Unknown
}
// KoppenGeigerClimateName maps Koppen-Geiger climate IDs to their name.
var KoppenGeigerClimateName = map[KoppenGeigerClimate]string{
KoppenGeigerClimateAf: "Tropical rainforest",
KoppenGeigerClimateAm: "Tropical monsoon",
KoppenGeigerClimateAw: "Tropical savanna",
KoppenGeigerClimateBWh: "Hot desert",
KoppenGeigerClimateBWk: "Cold desert",
KoppenGeigerClimateBSh: "Hot steppe",
KoppenGeigerClimateBSk: "Cold steppe",
KoppenGeigerClimateCsa: "Dry summer, subtropical",
KoppenGeigerClimateCsb: "Dry summer, cooler subtropical",
KoppenGeigerClimateCsc: "Dry summer, maritime temperate",
KoppenGeigerClimateCwa: "Dry winter, humid subtropical",
KoppenGeigerClimateCwb: "Dry winter, maritime temperate",
KoppenGeigerClimateCwc: "Dry winter, cooler maritime temperate",
KoppenGeigerClimateCfa: "Humid subtropical",
KoppenGeigerClimateCfb: "Maritime temperate",
KoppenGeigerClimateCfc: "Maritime subarctic",
KoppenGeigerClimateDsa: "Dry summer, continental, hot summer",
KoppenGeigerClimateDsb: "Dry summer, continental, warm summer",
KoppenGeigerClimateDsc: "Dry summer, continental, cool summer",
KoppenGeigerClimateDsd: "Dry summer, continental, very cold winter",
KoppenGeigerClimateDwa: "Dry winter, continental, hot summer",
KoppenGeigerClimateDwb: "Dry winter, continental, warm summer",
KoppenGeigerClimateDwc: "Dry winter, continental, cool summer",
KoppenGeigerClimateDwd: "Dry winter, continental, very cold winter",
KoppenGeigerClimateDfa: "Humid continental, hot summer",
KoppenGeigerClimateDfb: "Humid continental, warm summer",
KoppenGeigerClimateDfc: "Humid continental, cool summer",
KoppenGeigerClimateDfd: "Humid continental, very cold winter",
KoppenGeigerClimateET: "Polar tundra",
KoppenGeigerClimateEF: "Polar ice cap",
}
type KoppenGeigerMonthStats struct {
AvgTemp float64
MinTemp float64
MaxTemp float64
AvgPrec float64
MinPrec float64
MaxPrec float64
Summer bool
Winter bool
}
*/
// KoppenGeigerClimateID returns the Koppen-Geiger climate ID.
//
// 1. ==== Group A: Tropical climates
//
// This type of climate has every month of the year with an average temperature of 18 °C (64.4 °F) or higher, with significant precipitation.
//
// Af = Tropical rainforest climate;
// - average precipitation of at least 60 mm (2.4 in) in every month
//
// Am = Tropical monsoon climate;
// - driest month with precipitation less than 60 mm (2.4 in), but at least 100-(totalAnnualPrecipitation (mm) / 25) mm precipitation
//
// Aw or As = Tropical wet and dry or savanna climate;
// - driest month having precipitation less than 60 mm (2.4 in) and less than 100-(totalAnnualPrecipitation (mm) / 25) mm precipitation
//
// 2. ==== Group B: Arid climates
//
// This type of climate is defined by little precipitation that does not fit the polar (EF or ET) criteria of no month with an average
// temperature greater than 10 °C (50 °F).
//
// The threshold in millimeters is determined by multiplying the average annual temperature in Celsius by 20, then adding:
// (a) 280 if 70% or more of the total precipitation is in the spring and summer months (April–September in the Northern Hemisphere,
//
// or October–March in the Southern)
//
// (b) 140 if 30%–70% of the total precipitation is received during the spring and summer
// (c) 0 if less than 30% of the total precipitation is received during the spring and summer
//
// If the annual precipitation is less than 50% of this threshold, the classification is BW (arid: desert climate);
// if it is in the range of 50%–100% of the threshold, the classification is BS (semi-arid: steppe climate).
//
// A third letter can be included to indicate temperature.
//
// Originally:
// h signified low-latitude climate (average annual temperature above 18 °C (64.4 °F))
// k signified middle-latitude climate (average annual temperature below 18 °C)
//
// The more common practice today, especially in the United States:
// h to mean the coldest month has an average temperature above 0 °C (32 °F) (or −3 °C (27 °F))
// k denoting that at least one month's averages below 0 °C (or −3 °C (27 °F))
//
// In addition, n is used to denote a climate characterized by frequent fog and H for high altitudes.
//
// This defines the following climates:
// BWh = Hot desert climate
// BWk = Cold desert climate
// BSh = Hot semi-arid climate
// BSk = Cold semi-arid climate
//
// 3. ==== Group C: Temperate climates
//
// - coldest month averaging between 0 °C (32 °F) (or −3 °C (27 °F)) and 18 °C (64.4 °F)
// - at least one month averaging above 10 °C (50 °F).
//
// For the distribution of precipitation in locations that both satisfy a dry summer (Cs) and a dry winter (Cw),
// a location is considered to have a wet summer (Cw) when more precipitation falls within the summer months than
// the winter months while a location is considered to have a dry summer (Cs) when more precipitation falls within
// the winter months. This additional criterion applies to locations that satisfies both Ds and Dw as well.
//
// Cfa = Humid subtropical climate;
// - coldest month averaging above 0 °C (32 °F) (or −3 °C (27 °F))
// - at least one month's average temperature above 22 °C (71.6 °F)
// - at least four months averaging above 10 °C (50 °F).
// - no significant precipitation difference between seasons (neither the abovementioned set of conditions fulfilled)
// - no dry months in the summer.
//
// Cfb = Temperate oceanic climate or subtropical highland climate;
// - coldest month averaging above 0 °C (32 °F) (or −3 °C (27 °F))
// - all months with average temperatures below 22 °C (71.6 °F)
// - at least four months averaging above 10 °C (50 °F)
// - no significant precipitation difference between seasons (neither the abovementioned set of conditions fulfilled)
//
// Cfc = Subpolar oceanic climate;
// - coldest month averaging above 0 °C (32 °F) (or −3 °C (27 °F))
// - 1–3 months averaging above 10 °C (50 °F)
// - no significant precipitation difference between seasons (neither the abovementioned set of conditions fulfilled)
//
// Cwa = Monsoon-influenced humid subtropical climate;
// - coldest month averaging above 0 °C (32 °F) (or −3 °C (27 °F))
// - at least one month's average temperature above 22 °C (71.6 °F)
// - at least four months averaging above 10 °C (50 °F)
// - at least ten times as much rain in the wettest month of summer as in the driest month of winter
// (alternative definition is 70% or more of average annual precipitation is received in the warmest six months)
//
// Cwb = Subtropical highland climate or Monsoon-influenced temperate oceanic climate;
// - coldest month averaging above 0 °C (32 °F) (or −3 °C (27 °F))
// - all months with average temperatures below 22 °C (71.6 °F)
// - at least four months averaging above 10 °C (50 °F)
// - at least ten times as much rain in the wettest month of summer as in the driest month of winter
// (an alternative definition is 70% or more of average annual precipitation received in the warmest six months)
//
// Cwc = Cold subtropical highland climate or Monsoon-influenced subpolar oceanic climate;
// - coldest month averaging above 0 °C (32 °F) (or −3 °C (27 °F))
// - 1–3 months averaging above 10 °C (50 °F)
// - at least ten times as much rain in the wettest month of summer as in the driest month of winter
// (alternative definition is 70% or more of average annual precipitation is received in the warmest six months)
//
// Csa = Hot-summer Mediterranean climate;
// - coldest month averaging above 0 °C (32 °F) (or −3 °C (27 °F))
// - at least one month's average temperature above 22 °C (71.6 °F)
// - at least four months averaging above 10 °C (50 °F)
// - at least three times as much precipitation in the wettest month of winter as in the driest month of summer
// - the driest month of summer receives less than 40 mm (1.6 in) of precipitation
//
// Csb = Warm-summer Mediterranean climate;
// - coldest month averaging above 0 °C (32 °F) (or −3 °C (27 °F))
// - all months with average temperatures below 22 °C (71.6 °F)
// - at least four months averaging above 10 °C (50 °F)
// - at least three times as much precipitation in the wettest month of winter as in the driest month of summer
// - the driest month of summer receives less than 40 mm (1.6 in)
//
// Csc = Cold-summer Mediterranean climate;
// - coldest month averaging above 0 °C (32 °F) (or −3 °C (27 °F))
// - 1–3 months averaging above 10 °C (50 °F)
// - at least three times as much precipitation in the wettest month of winter as in the driest month of summer,
// - the driest month of summer receives less than 40 mm (1.6 in)
//
// 4. ==== Group D: Continental climates
//
// This type of climate has at least one month averaging below 0 °C (32 °F) (or −3 °C (27 °F)) and at least one month averaging above 10 °C (50 °F).
//
// Dfa = Hot-summer humid continental climate;
// - coldest month averaging below 0 °C (32 °F) (or −3 °C (27 °F))
// - at least one month's average temperature above 22 °C (71.6 °F)
// - at least four months averaging above 10 °C (50 °F)
// - no significant precipitation difference between seasons (neither the abovementioned set of conditions fulfilled)
//
// Dfb = Warm-summer humid continental climate;
// - coldest month averaging below 0 °C (32 °F) (or −3 °C (27 °F))
// - all months with average temperatures below 22 °C (71.6 °F)
// - at least four months averaging above 10 °C (50 °F)
// - no significant precipitation difference between seasons (neither the abovementioned set of conditions fulfilled)
//
// Dfc = Subarctic climate;
// - coldest month averaging below 0 °C (32 °F) (or −3 °C (27 °F))
// - 1–3 months averaging above 10 °C (50 °F)
// - no significant precipitation difference between seasons (neither the abovementioned set of conditions fulfilled)
//
// Dfd = Extremely cold subarctic climate;
// - coldest month averaging below −38 °C (−36.4 °F)
// - 1–3 months averaging above 10 °C (50 °F)
// - no significant precipitation difference between seasons (neither the abovementioned set of conditions fulfilled)
//
// Dwa = Monsoon-influenced hot-summer humid continental climate;
// - coldest month averaging below 0 °C (32 °F) (or −3 °C (27 °F))
// - at least one month's average temperature above 22 °C (71.6 °F)
// - at least four months averaging above 10 °C (50 °F)
// - at least ten times as much rain in the wettest month of summer as in the driest month of winter
// (alternative definition is 70% or more of average annual precipitation is received in the warmest six months)
//
// Dwb = Monsoon-influenced warm-summer humid continental climate;
// - coldest month averaging below 0 °C (32 °F) (or −3 °C (27 °F))
// - all months with average temperatures below 22 °C (71.6 °F)
// - at least four months averaging above 10 °C (50 °F)
// - at least ten times as much rain in the wettest month of summer as in the driest month of winter
// (alternative definition is 70% or more of average annual precipitation is received in the warmest six months)
//
// Dwc = Monsoon-influenced subarctic climate;
// - coldest month averaging below 0 °C (32 °F) (or −3 °C (27 °F))
// - 1–3 months averaging above 10 °C (50 °F)
// - at least ten times as much rain in the wettest month of summer as in the driest month of winter
// (alternative definition is 70% or more of average annual precipitation is received in the warmest six months)
//
// Dwd = Monsoon-influenced extremely cold subarctic climate;
// - coldest month averaging below −38 °C (−36.4 °F) and 1–3 months averaging above 10 °C (50 °F)
// - at least ten times as much rain in the wettest month of summer as in the driest month of winter
// (alternative definition is 70% or more of average annual precipitation is received in the warmest six months)
//
// Dsa = Mediterranean-influenced hot-summer humid continental climate;
// - coldest month averaging below 0 °C (32 °F) (or −3 °C (27 °F))
// - average temperature of the warmest month above 22 °C (71.6 °F)
// - at least four months averaging above 10 °C (50 °F)
// - at least three times as much precipitation in the wettest month of winter as in the driest month of summer
// - driest month of summer receives less than 30 mm (1.2 in)
//
// Dsb = Mediterranean-influenced warm-summer humid continental climate;
// - coldest month averaging below 0 °C (32 °F) (or −3 °C (27 °F))
// - average temperature of the warmest month below 22 °C (71.6 °F)
// - at least four months averaging above 10 °C (50 °F)
// - at least three times as much precipitation in the wettest month of winter as in the driest month of summer
// - driest month of summer receives less than 30 mm (1.2 in)
//
// Dsc = Mediterranean-influenced subarctic climate;
// - coldest month averaging below 0 °C (32 °F) (or −3 °C (27 °F))
// - 1–3 months averaging above 10 °C (50 °F)
// - at least three times as much precipitation in the wettest month of winter as in the driest month of summer
// - driest month of summer receives less than 30 mm (1.2 in)
//
// Dsd = Mediterranean-influenced extremely cold subarctic climate;
// - coldest month averaging below −38 °C (−36.4 °F)
// - 1–3 months averaging above 10 °C (50 °F)
// - at least three times as much precipitation in the wettest month of winter as in the driest month of summer
// - driest month of summer receives less than 30 mm (1.2 in)
//
// 5. ==== Group E: Polar and alpine climates
//
// This type of climate has every month of the year with an average temperature below 10 °C (50 °F)
//
// ET = Tundra climate;
// - average temperature of warmest month between 0 °C (32 °F) and 10 °C (50 °F)
//
// EF = Ice cap climate;
// - eternal winter
// - all 12 months of the year with average temperatures below 0 °C (32 °F)
// func KoppenGeigerClimateID(months [12]KoppenGeigerMonthStats, northernHemisphere bool) KoppenGeigerClimate {
// return KoppenGeigerClimateUnknown
// }