-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathArabianTotestra.py
6719 lines (6182 loc) · 276 KB
/
ArabianTotestra.py
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
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
##############################################################################
## Arabian Totestra
## Version: 2022-01-01 (Happy New Year!)
## This is a fork of Totestra designed for Legends of Ancient Arabia.
## Hence, the map will use one of about 180 possible fixed seeds to
## generate the world. It's possible to select one of the seeds
## below randomly, or to specify one of three fixed seeds.
## The worlds have been selected because they generate maps which are
## suitable for an Arabian adventure (main land in middle latitudes, has no
## snow and little tundra)
"""
# About
ArabianTotestra.py is a map script for Civilization IV. It is derived
from Rich Marinaccio's map script Perfect World. While Rich Marinaccio
never provided a license for Perfect World, he has given me permission
to make derivatives of it and I believe he is OK with any and all
non-commercial use of the script.
In this variant of Perfect World, I have made a version of Perfect World
which generates the same maps Perfect World generates, but only (by default)
selects maps which are suitable for the Warlords Mod "Legends of Ancient
Arabia".
This is a map script: It is a Python2 program run by Civilization IV to
generate a map for that game.
This map script is designed to model a natural world like Earth: The
scipt simulates plate tectonics, rainfall, meteor hits, and other factors
which created the continents on Earth.
This script limits the number of worlds that can be generated. A script
was run for several weeks to find Perfect World random number generator
seeds which generate simulated planets suitable for creating an Arabian
adventure: The main continent needs to be near the equator, and there
needs to be very little cold areas in that continent. This script, by
default, will only randomly select one of the larger possible Arabian
adventures found by this script.
Unlike other Civilization IV map generators, all of the players will
start on the same continent, changing the map size won't change the
size of the generated map (all maps are 144 tiles wide and 96 tiles
tall), climate can not be selected (the climate is arid), and the
sea level can not be adjusted.
# Installation
Place this in one's PublicMaps folder, such as
"/Sid Meier's Civilization 4 Complete/Warlords/PublicMaps/". When
starting a game, select "Custom Game", and make sure "ArabianTotestra"
is visible when selecting "Map".
# Options
## Size
This should be set to Huge. While it can be set to a smaller size, the
map generator *always* generates an 144x96 map; smaller sizes reduce the
default number of players and make war weariness happen more quickly
while not affecting the actual map generated.
## Era
Set this to the desired era to start with. With the "Legends of Ancient
Arabia" mod, this should be "Ancient".
## Speed
How fast the game develops. For a quick game, choose "Quick" or "Normal",
and choose "Smaller start continents" for the seed below.
## Resources
Perfect World had its own unique resource placement code which better
simulates resources in the real world. For Civilization games, this is
less than ideal. "Full of resources" simply randomly places a large
number of resources everywhere on the map; "Resources evenly spread"
does not place resources on their own continents, but acts like "Full
of resources", except the resource count is lower. "Like Perfect World"
uses Perfect World's resource placement code.
## Map seed
This determines the seed given to the pseudo random number generator
to generate a map. Running a script on a Raspberry Pi server found a
large number of maps which appear to be suitable for Arabian adventures.
Selecting "larger start continents" will select one of those seeds which
generates a continent with a size of 1400 or higher. This is suitable
for a game at "epic" or "marathon" speeds.
"Smaller start continents" will select a seed which makes a continent
smaller than 1400 in size. This is for a game at "quick" or "normal"
speeds.
"Random" will select any known seed suitable for generating an Arabian
adventure.
"Free form (not Arabian)" will select a completely random Pefect World seed;
most maps will not be optimized for an Arabian adventure.
"Amira map" is a fixed seed I found in 2018 which looks to be a very
enjoyable Arabian adventure. Selecting this will always generate the
same map.
"Caulixtla map" is a fixed seed I found in 2012 which is my usual go
to Arabian adventure map. If nine players are selected, this is the
Hijazi start in the Arabian Caulixtla map included with my fork of
"Legends of Ancient Arabia". Note that this map will be upside down
compared to the map included with "Legends of Ancient Arabia"; the
LOAA version of the map was flipped over 180 degrees back in 2012.
"Fixed seed (Jungle start)" is a fixed seed making a larger continent
where the player starts in a jungle.
"Caulixtla map (Jungle start)" is the Caulixtla map again, but with
a start in a Jungle, as long as precisely nine players are selected (the
number of tribes in "Legends of Ancient Arabia"). If the map does not
have nine players, the player may not start in a jungle. This start
is the Omani start in the 2012 version of the Arabian Caulixtla map,
and the Hijazi start in the 2021 second revision of the Arabian Caulixtla
map.
"Fixed seed (Grassland start)" is a different map than the "Fixed seed
(Jungle start)" map above, and places the player on a medium sized map.
Like the Caulixtla map and other Fixed seed, this seed will always
generate the same map.
None of the fixed seed maps will be generated if selecting "Large start
continents", "Small start continents", "Random", or free form maps.
In addition, the free form maps will never generate a map from the "Large
start continents", "Small start continents", and "Random" list of maps.
## Player bonus resources
If playing at a harder difficulty, or if simply wanting to play an easier
game, it may be desirable to have more resources at one's starting
location. There are a large number of levels of bouns resources placed
in the player's start.
This allows one to have more starting resources without having to
regenerate the map until one has the desired quantity of starting
resources.
## Hut placement
This determines how goody huts are placed on the map. "Civ4 default"
just uses Civ4's default hut placement code; note that a given map seed
will have different hut placements every time a map is generated. In
other words, if using "Civ4 default" and one of the fixed seeds, the
huts will still vary their location every time the map is generated.
"No huts" simply does not put any goody huts on the map. This is the
behavior the original "Legends of Ancient Arabia" has with its default
map.
"Fixed huts per seed" places a reasonable number of huts on the map.
A given map seed will always have the same locations for goody huts.
"Huts are rare" makes huts very uncommon. A given map seed will always
have the same locations for huts.
"Many desert huts" places a large number of goody huts in deserts. A
given map seed will have the same hut locations.
"Many huts everywhere" has many goody huts all over the map. A given map
seed will have the same hut locations.
# Running stand alone
The script can also be run stand alone. This will not generate maps;
if map generation in standalone mode is desired, use old/TotestraRG32.py
instead. Instead, standalone mode tests the random number generator to
ensure it is generating correct RadioGatun[32] sums.
To run it standalone:
```
python2 ArabianTotestra.py --test foo
```
Replace foo above with the desired string to generate a RadioGatun[32]
sum of.
"""
# Here is a list of seeds for a possible Arabian adventure. Each seed is
# in (size, seed) format.
# Batch #1: 39000-52999
seedList = [(822, 52805),
(905, 51274),
(920, 49666),
(941, 39432),
(1009, 42645),
(1046, 49344),
(1047, 42527),
(1170, 46736),
(1185, 40509),
(1189, 47305),
(1214, 48855),
(1247, 41934),
(1291, 51302),
(1296, 48054),
(1305, 45083),
(1305, 51471),
(1315, 44103),
(1331, 52939),
(1366, 41848),
(1379, 46296),
(1382, 47419),
(1387, 47362),
(1410, 44380),
(1412, 47479),
(1460, 41126),
(1510, 44859),
(1519, 42362),
(1527, 41446),
(1554, 40780),
(1593, 50570),
(1605, 40170),
(1613, 48732),
(1746, 52226),
(1752, 43333),
(1823, 49499),
(1841, 47902),
(1851, 46824),
(1906, 46453),
(1912, 48126),
(2006, 50950),
(2173, 43216),
(2292, 42086),
(2323, 42609),
# Batch #2 70000+
(1544,70343),
(849,70810),
(1015,70843),
(1784,71015),
(1254,71467),
(1827,71484),
(1152,71499),
(1384,71566),
(2032,71855),
(709,71995),
(1161,72253),
(1035,72270),
(1640,72540),
(1271,72588),
(1959,72607),
(1534,72687),
(1644,72779),
(2013,73569),
(1034,73747),
(2113,73824),
(2022,73916),
(1674,74715),
(1164,75189),
(907,75214),
(2037,75280),
(1634,75374),
(1767,75409),
(795,75484),
(1710,75720),
(1812,75842),
(1916,76097),
(2348,76403),
(1393,76612),
(1612,77251),
(1412,77457),
(1021,77515),
(1409,77794),
(1923,77833),
(1822,78143),
(1167,78241),
(1781,78911),
(1053,79207),
(798,79391),
(1560,79494),
(2381,79534),
(1395,79661),
(1702,79861),
(1203,80387),
(989,80746),
(1454,80839),
(1208,81580),
(1431,81666),
(1839,82569),
(969,83077),
(912,83129),
(1804,83693),
(919,83897),
(1778,83960),
(1153,85024),
(1886,85846),
(1300,86356),
(1250,86631),
(1489,86846),
(1033,87400),
(1479,87402),
(1100,87512),
(1023,87925),
(1574,88522),
(1594,88823),
(1242,89101),
(946,89352),
(626,89650),
(1026,89777),
(1229,89816),
(1193,90116),
(868,90397),
(1105,90713),
(1177,90728),
(1481,90739),
(1032,90839),
(1794,91108),
(1543,91157),
(1294,91451),
(1315,91704),
(1417,92058),
(1070,92084),
(792,92102),
(1817,92156),
(1152,92794),
(1028,93379),
(1539,94166),
(1162,94324),
(1523,94751),
(2530,95000),
(1545,95113),
(1432,95305),
(1469,95600),
(1026,95813),
(1473,96034),
(1106,96942),
(1390,97173),
(1327,97610),
(1074,97755),
(791,97824),
(1612,98289),
(820,98419),
(1615,98603),
(1858,98677),
(1398,98881),
(1666,99421),
(2128,99613),
(1192,100109),
(1663,100321),
(1523,100799),
(1630,100870),
(2464,100891),
(1477,100980),
(1498,101145),
(1276,102074),
(1220,102806),
(1324,103244),
(984,103349),
(1503,103366),
(2256,103771),
(2103,104060),
(1112,104419),
(1453,104499),
(1349,104741),
(1805,104767),
(1189,104779),
(1614,104813),
(1356,105228),
(1068,105415),
(1338,105767),
(1503,105977),
(965,106312),
(1171,106559),
(1939,106617),
(989,107147),
(985,107856),
(1310,108193)
]
## Changes from PerfectWorld 2.06 (*not* 2.06f)
## 1) Ability to select climate
## 2) Ability to use fixed random seed
## 3) Remove mountains next to coast (fix coastside mountain ring bug)
## 4) Allow everyone to start on same landmass (biggest or 2nd biggest)
## 5) Have options for changing resource distribution
## 6) Note random seed on sign placed in the arctic
## 7) Ability to have bigger (192x128) or smaller (96x64) maps
## 8) Use RadioGatun[32] for random number generation
## File: PerfectWorld.py version 2.06
## Author: Rich Marinaccio
## Copyright 2007 Rich Marinaccio
##
## This map script for Civ4 generates a random, earth-like map, usually with a
## 'New World' with no starting locations that can only be reached with
## ocean going technology. Though great pains are taken to accurately simulate
## landforms and climate, the goal must be to make unpredictible, beautiful
## looking maps that are fun to play on.
##
## -- Summary of creation process: --
## First, a random heightfield is created using midpoint displacement. The
## resulting altitudes are then modified by a plate tectonics scheme that
## grows random plates and raises the altitudes near the plate borders to
## create mountain ranges and island chains.
##
## In generating the plot types from a heightmap, I had found that using
## peaks for high altitude and land for less altitude created large clusters
## of peaks, surrounded by a donut of hills, surrounded again by a donut of
## land. This looked absolutely terrible for Civ, so I made it such that
## peaks and hills are determined by altitude *differences* rather than by
## absolute altitude. This approach looks much better and more natural.
##
## The terrain generator gives the other needed visual cues to communicate
## altitude. Since air temperature gets colder with altitude, the peaks will
## be plots of ice and tundra, even near the equator, if the altitude
## is high enough. Prevailing winds, temperature and rainfall are all simulated
## in the terrain generator. You will notice that the deserts and rainforests
## are where they should be, as well as rain shadows behind mountain ranges.
##
## Rivers and lakes are also generated from the heightmap and follow accurate
## drainage paths, although with such a small heightmap some randomness needs
## to be thrown in to prevent rivers from being merely straight lines.
##
## Map bonuses are placed following the XML Rules but slightly differently than
## the default implimentation to better accomodate this map script.
##
## I've always felt that the most satisfying civ games are the ones that
## provide a use for those explorers and caravels. Though the map generator
## does not explicitly create a 'New World', it will take advantage of any
## continents that can serve that purpose. No starting locations will be placed
## on these continents. Therefore, the likelyhood of a significant new world
## is very high, but not guaranteed. It might also come in the form of multiple
## smaller 'New Worlds' rather than a large continent.
##
##############################################################################
## Version History
## 2.06 - Fixed a few bugs from my minimum hill/maximum bad feature function.
##
## 2.05 - Made maps of standard size and below a bit smaller. Changed the way I
## remove jungle to prevent excessive health problems. Tiles in FC on different
## continents have zero value. Tiles on different continents will not be boosted
## with resources or hills. Water tiles have zero value for non-coastal cities.
## Water tiles will not be boosted with resources for non-coastal cities, land
## tiles will be boosted instead. (lookout Sid's Sushi!)
##
## 2.04 - Changed many percent values to be a percent of land tiles rather than
## total map tiles for easier, more predictable adjustment. Ensured a minimum
## number of hills in a starting fat cross. Disabled the normalizeRemovePeaks
## function a replaced it with a maximum peaks in FC function. Added bonus
## resources to FC depending on player handicap. Added a value bonus for cities
## placed on river sides.
##
## 2.03 - Fixed an initialization problem related to Blue Marble. Added some
## enhanced error handling to help me track down some of the intermittant bugs
## that still remain.
##
## 2.02 - Fixed some problems with monsoons that were creating strange artifacts
## near the tropics. Added an exponential curve to heat loss due to altitude, so
## that jungles can appear more readily without crawling to inappropriate
## latitudes.
##
## 2.01 - Changed the way I handled a vanilla version difference. Added toroidal
## and flat map options. Made tree amount more easily adjustable. Added a variable to
## tune the level of resource bonuses. Changed the rules for fixing tundra/ice next
## to desert. Added altitude noise to the plate map to improve island chains. Added
## a variable to control heat loss due to high altitude. Implimented a new interleaved
## bonus placement scheme so that bonuses are placed individually in random order,
## rather than all of each bonus type at once. Brought back the meteor code from
## PerfectWorld 1 and eliminated the east/west continent divide.
##
## 2.0 - Rebuilt the landmass and climate model using the FaireWeather.py for
## Colonization map script engine. Improved the river system. Fixed some
## old bugs.
##
## 1.13 - Fixed a bug where starting on a goody hut would crash the game.
## Prevented start plots from being on mountain peaks. Changed an internal
## distance calculation from a straight line to a path distance, improving
## start locations somewhat. Created a new tuning variable called
## DesertLowTemp. Since deserts in civ are intended to be hot deserts, this
## variable will prevent deserts from appearing near the poles where the
## desert texture clashes horribly with the tundra texture.
##
## 1.12 - Found a small bug in the bonus placer that gave bonuses a minimum
## of zero, this is why duel size maps were having so much trouble.
##
## 1.11 - limited the features mixing with bonuses to forests only. This
## eliminates certain undesireable effects like floodplains being erased by
## or coinciding with oil or incense, or corn appearing in jungle.
##
## 1.10 - Wrapped all map constants into a class to avoid all those
## variables being loaded up when PW is not used. Also this makes it a
## little easier to change them programatically. Added two in-game options,
## New World Rules and Pangaea Rules. Added a tuning variable that allows
## bonuses with a tech requirement to co-exist with features, so that the
## absence of those features does not give away their location.
##
## 1.09 - Fixed a starting placement bug introduced in 1.07. Added a tuning
## variable to turn off 'New world' placement.
##
## 1.08 - Removed the hemispheres logic and replaced it with a simulated meteor
## shower to break up pangeas. Added a tuning variable to allow pangeas.
##
## 1.07 - Placing lakes and harbors after river placement was not updating river
## crossings. Resetting rivers after lake placement should solve this. Fixed a
## small discrepancy between Python randint and mapRand to make them behave the
## same way. Bonuses of the same bonus class, when forced to appear on the
## same continent, were sometimes crowding each other off the map. This was
## especially problematic on the smaller maps. I added some additional, less
## restrictive, passes to ensure that every resource has at least one placement
## unless the random factors decide that none should be placed. Starting plot
## normalization now will place food if a different bonus can not be used due
## to lack of food. Changed heightmap generation to more likely create a
## new world.
##
## 1.06 - Overhauled starting positions and resource placement to better
## suit the peculiarities of PerfectWorld
##
## 1.05 - Fixed the Mac bug and the multi-player bug.
##
## 1.04a - I had unfairly slandered getMapRand in my comments. I had stated
## that the period was shortened unnecessarily, which is not the case.
##
## 1.04 - Added and option to use the superior Python random number generator
## or the getMapRand that civ uses. Made the number of rivers generated tunable.
## Fixed a bug that prevented floodplains on river corners. Made floodplains
## in desert tunable.
##
## 1.03a - very minor change in hope of finding the source of a multi-player
## glitch.
##
## 1.03 - Improved lake generation. Added tuning variables to control some
## new features. Fixed some minor bugs involving the Areamap filler
## and fixed the issue with oasis appearing on lakes. Maps will now report
## the random seed value that was used to create them, so they can be easily
## re-created for debugging purposes.
##
## 1.02 - Fixed a bug that miscalculated the random placing of deserts. This
## also necessitated a readjustment of the default settings.
##
## 1.01 - Added global tuning variables for easier customization. Fixed a few
## bugs that caused deserts to get out of control.
##
# Class RadioGatun32 is under different copyright:
# Copyright (c) 2012-2017 Sam Trenholme
#
# TERMS
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# This software is provided 'as is' with no guarantees of correctness or
# fitness for purpose.
# This is a Python implementation of RadioGatun32. It takes about 10
# seconds to set up the RNG, then it can output approximately
# 30,000 16-bit random numbers per second on a Core i5-2430M
# There is another open-source Python RadioGatun implementation here:
# https://github.com/doegox/python-cryptoplus
# I would like to thank Lorenzo for his suggestion to use xrange to speed up
# the program
# Since range is too slow in Python2, we do this to make the code run in
# Python2 and Python3
try:
xrange
except:
xrange = range
class RadioGatun32:
def __init__(self, m):
self.wordsize = int(32)
self.millsize = int(19)
self.beltrows = 3
self.beltcol = 13
self.beltfeed = 12
self.mask = 0xffffffff # 32-bit
self.index = 0
(self.a, self.b) = self.seed(str(m))
def mill(self,a):
aa = []
for g in xrange(self.millsize):
aa.append(0)
x = 0
i = 0
y = 0
r = 0
z = 0
for i in xrange(self.millsize):
y = (i * 7) % self.millsize
r = int(((i * (i + 1)) / 2)) % self.wordsize
x = a[y] ^ (a[ ((y + 1) % self.millsize) ] |
(a[ ((y + 2) % self.millsize) ] ^ self.mask))
aa[i] = ((x >> r) | (x <<(self.wordsize - r))
& self.mask)
for i in xrange(self.millsize):
y = i
r = (i + 1) % self.millsize
z = (i + 4) % self.millsize
a[i] = aa[y] ^ aa[r] ^ aa[z]
a[0] ^= 1
return a
def belt(self,a,b):
q = []
for g in xrange(self.beltrows):
q.append(0)
s = 0
i = 0
v = 0
for s in xrange(self.beltrows):
q[s] = b[((s * self.beltcol) + self.beltcol - 1)]
i = self.beltcol - 1
while i > 0:
for s in xrange(self.beltrows):
v = i - 1
if v < 0:
v = self.beltcol - 1
b[((s * self.beltcol) + i)] = (
b[((s * self.beltcol) + v)])
i -= 1
for s in xrange(self.beltrows):
b[(s * self.beltcol)] = q[s]
for i in xrange(self.beltfeed):
s = (i + 1) + ((i % self.beltrows) * self.beltcol)
b[s] ^= a[(i + 1)]
a = self.mill(a)
for i in xrange(self.beltrows):
a[(i + self.beltcol)] ^= q[i]
return (a, b)
def seed(self,m):
p = []
for g in xrange(3):
p.append(0)
q = 0
c = 0
r = 0
done = 0
index = 0
counter = 0
a = []
b = []
for g in xrange(self.millsize):
a.append(0)
for g in xrange(self.beltrows * self.beltcol):
b.append(0)
for counter in xrange(16777218): # Infinite loop protection
p[0] = p[1] = p[2] = 0
for r in xrange(3):
q = 0
while q < self.wordsize:
x = 0
try:
x = ord(m[index])
except:
x = 1
index += 1
if(index > len(m)):
done = 1
x = 1
p[r] |= x << q
if done == 1:
for c in xrange(3):
b[c * 13] ^= p[c]
a[16 + c] ^= p[c]
(a,b) = self.belt(a,b)
for c in xrange(16):
(a,b) = self.belt(a,b)
return (a,b)
q += 8
for c in xrange(3):
b[c * 13] ^= p[c]
a[16 + c] ^= p[c]
(a,b) = self.belt(a,b)
return (a,b) # We should never get here
# Return 16-bit random integer (between 0 and 65535)
def rng16(self):
if (self.index % 4) == 0:
(self.a, self.b) = self.belt(self.a, self.b)
self.index += 1
return (((self.a[1] & 0xff) << 8) |
((self.a[1] & 0xff00) >> 8))
self.index += 1
if (self.index % 4) == 2:
return(((self.a[1] & 0xff0000) >> 8) |
((self.a[1] & 0xff000000) >> 24))
elif (self.index % 4) == 3:
return(((self.a[2] & 0xff) << 8) |
((self.a[2] & 0xff00) >> 8))
elif (self.index % 4) == 0:
return(((self.a[2] & 0xff0000) >> 8) |
((self.a[2] & 0xff000000) >> 24))
else: # Should never get here
return -1
# Return 32-bit random integer
def rng32(self):
if(self.index & 1):
self.index += 1
self.index &= 2
if(self.index):
self.index = 0
return (((self.a[2] & 0xff) << 24) |
((self.a[2] & 0xff000000) >> 24) |
((self.a[2] & 0xff00) << 8) |
((self.a[2] & 0xff0000) >> 8))
(self.a, self.b) = self.belt(self.a, self.b)
self.index = 2
return (((self.a[1] & 0xff) << 24) |
((self.a[1] & 0xff000000) >> 24) |
((self.a[1] & 0xff00) << 8) |
((self.a[1] & 0xff0000) >> 8))
# Return 64-bit random integer
def rng64(self):
left = self.rng32()
right = self.rng32()
return ((left << 32) | right)
# Return number between 0 (can be 0) and 1 (can be slightly smaller
# than 1 but never 1)
def random(self):
return float(self.rng64()) / 18446744073709551616
# Return a number between a and b
def randint(self, low, high):
if(low == high):
return low
if(high < low):
swap = low
low = high
high = swap
range = 1 + high - low
# For low ranges, we can use 16-bit ints to get number
if(range <= 10000):
max = 65536 - (65536 % range)
number = max
while number >= max:
number = self.rng16()
return low + (number % range)
# int() returns the floor, e.g. int(1.99999) returns 1
return int(low + (self.random() * range))
def do_rg32_test(testInput):
# 16 16-bit numbers
rg32test = RadioGatun32(testInput)
line = "16-bit: "
for a in range(16):
line += ("%04x" % (rg32test.rng16()))
print(line)
# 8 32-bit numbers
rg32test = RadioGatun32(testInput)
line = "32-bit: "
for a in range(8):
line += ("%08x" % (rg32test.rng32()))
print(line)
# 4 64-bit numbers
rg32test = RadioGatun32(testInput)
line = "64-bit: "
for a in range(4):
line += ("%016x" % (rg32test.rng64()))
print(line)
# 16-bit then 32-bit
rg32test = RadioGatun32(testInput)
line = "16/32 bit: "
for a in range(4):
line += ("%04x" % (rg32test.rng16()))
line += "----"
line += ("%08x" % (rg32test.rng32()))
print(line)
# 32-bit then 16-bit
rg32test = RadioGatun32(testInput)
line = "32/16 bit: "
for a in range(4):
line += ("%08x" % (rg32test.rng32()))
line += ("%04x" % (rg32test.rng16()))
line += "----"
print(line)
# Mix it up (16,16,32,64,64,32,16,16)
rg32test = RadioGatun32(testInput)
line = "Mix it up: "
line += ("%04x" % (rg32test.rng16()))
line += ("%04x" % (rg32test.rng16()))
line += ("%08x" % (rg32test.rng32()))
line += ("%016x" % (rg32test.rng64()))
line += ("%016x" % (rg32test.rng64()))
line += ("%08x" % (rg32test.rng32()))
line += ("%04x" % (rg32test.rng16()))
line += ("%04x" % (rg32test.rng16()))
print(line)
##### END BSD LICENSED CODE ##############################################
if __name__ != "__main__":
from CvPythonExtensions import *
import CvUtil
import CvMapGeneratorUtil
from array import array
from random import random,randint,seed
import math
import sys
import time
import os
class MapConstants :
def __init__(self):
return
def initialize(self):
print "Initializing map constants"
##############################################################################
## GLOBAL TUNING VARIABLES: Change these to customize the map results
gc = CyGlobalContext()
mmap = gc.getMap()
# Default seed
self.randomSeed = 0
#Percent of land vs. water
self.landPercent = 0.29
#If this variable is set to False, a shower of colossal meteors will attempt to
#break up any pangea-like continents. Setting this variable to True will allow
#pangeas to sometimes occur and should be greatly favored by any dinosaurs
#that might be living on this planet at the time.
self.AllowPangeas = False
#This variable can be used to turn off 'New world' logic and place starting
#positions anywhere in the world. For some mods, a new world doesn't make
#sense.
self.AllowNewWorld = True
self.ShareContinent = False
self.ShareContinentIndex = 1
#How many land squares will be above peak threshold and thus 'peaks'.
self.PeakPercent = 0.12
#How many land squares will be above hill threshold and thus 'hills' unless
#they are also above peak threshold in which case they will be 'peaks'.
self.HillPercent = 0.35
#In addition to the relative peak and hill generation, there is also a
#process that changes flats to hills or peaks based on altitude. This tends
#to randomize the high altitude areas somewhat and improve their appearance.
#These variables control the frequency of hills and peaks at the highest altitude.
self.HillChanceAtOne = .50
self.PeakChanceAtOne = .27
#How many land squares will be below desert rainfall threshold. In this case,
#rain levels close to zero are very likely to be desert, while rain levels close
#to the desert threshold will more likely be plains.
self.DesertPercent = 0.20
#How many land squares will be below plains rainfall threshold. Rain levels close
#to the desert threshold are likely to be plains, while those close to the plains
#threshold are likely to be grassland.
self.PlainsPercent = 0.42
#---The following variables are not based on percentages. Because temperature
#---is so strongly tied to latitude, using percentages for things like ice and
#---tundra leads to very strange results if most of the worlds land lies near
#---the equator
#What temperature will be considered cold enough to be ice. Temperatures range
#from coldest 0.0 to hottest 1.0.
self.SnowTemp = .30
#What temperature will be considered cold enough to be tundra. Temperatures range
#from coldest 0.0 to hottest 1.0.
self.TundraTemp = .35
#Hotter than this temperature will be considered deciduous forest, colder will
#be evergreen forest.Temperatures range from coldest 0.0 to hottest 1.0.
self.ForestTemp = .50
#What temperature will be considered hot enough to be jungle. Temperatures range
#from coldest 0.0 to hottest 1.0.
self.JungleTemp = .7
#Sets the threshold for jungle rainfall by modifying the plains threshold by this factor.
self.TreeFactor = 1.5
#This is the maximum chance for a tree to be placed when rainfall is above jungle level.
#use a value between 0.0 and 1.0
self.MaxTreeChance = 1.0
#This variable adjusts the amount of bonuses on the map. Values above 1.0 will add bonus
#bonuses. People often want lots of bonuses, and for those people, this variable is definately
#a bonus.
self.BonusBonus = 1.0
# This determines if we use Perfect World's way of spreading
# resources (False), or use a more normal resource distribution
self.spreadResources = False
#How many squares are added to a lake for each unit of drainage flowing
#into it.
self.LakeSizePerDrainage = 14.0
#This value modifies LakeSizePerRiverLength when a lake begins in desert
self.DesertLakeModifier = .60
#This value controls the amount of siltification in lakes
self.maxSiltPanSize = 200
#This value controls the number of mid-altitude lake depressions per
#map square. It will become a lake if enough water flows into the
#depression.
self.numberOfLakesPerPlot = 0.003
#This value sets the minimum altitude of lake depressions. They
#generally look better higher up.
self.minLakeAltitude = 0.45
#This value is used to decide if enough water has accumulated to form a river.
#A lower value creates more rivers over the entire map.
self.RiverThreshold = 4
#The percent chance that an oasis may appear in desert. A tile must be desert and
#surrounded on all sides by desert.
self.OasisChance = .08
#This sets the amount of heat lost at the highest altitude. 1.0 loses all heat
#0.0 loses no heat.
self.heatLostAtOne = 1.0
#This value is an exponent that controls the curve associated with
#temperature loss. Higher values create a steeper curve.
self.temperatureLossCurve = 1.3
#Degrees latitude for the top and bottom of the map. This allows
#for more specific climate zones
self.topLatitude = 90
self.bottomLatitude = -90
#Horse latitudes and polar fronts plus and minus in case you
#want some zones to be compressed or emphasized.
self.horseLatitude = 30
self.polarFrontLatitude = 60
#Tropics of Cancer and Capricorn plus and minus respectively
self.tropicsLatitude = 23
#Oceans are slow to gain and lose heat, so the max and min temps
#are reduced and raised by this much.
self.oceanTempClamp = .10
#Minimum amount of rain dropped by default before other factors
#add to the amount of rain dropped
self.minimumRainCost = 0.01
#Strength of geostrophic rainfall versus monsoon rainfall
self.geostrophicFactor = 6.0
#Monsoon uplift factor. This value is an ajustment so that monsoon uplift
#matches geostrophic uplift.
self.monsoonUplift = 500.0
#Height and Width of main climate and height maps. This does not
#reflect the resulting map size. Both dimensions( + 1 if wrapping in
#that dimension = False) must be evenly divisble by self.hmMaxGrain
# Note: The bigger map option may rewrite these values (see below)
self.hmWidth = 144
self.hmHeight = 97
#Controls wrapping (not sure if this makes sense yet)
self.WrapX = True
self.WrapY = False
#Size of largest map increment to begin midpoint displacement. Must
#be a power of 2.
self.hmMaxGrain = 16
#Option to divide map into two continents as far as the midpoint
#displacement is concerned. For guaranteed continent separation, further
#steps will be needed but this option will cause more ocean in the
#middle of the map. The possible choices are 0 = NO_SEPARATION,
#1 = NORTH_SOUTH_SEPARATION and 2 = EAST_WEST_SEPARATION.
self.hmSeparation = 0
#Creates a water margin around the map edges.
self.northMargin = False
self.southMargin = False
self.eastMargin = False
self.westMargin = False
#If you sink the margins all the way to 0.0, they become too obvious.
#This variable sets the maximum amount of sinking
self.hmMarginDepth = 0.60
#Margin of ocean around map edge when not wrapping and also through
#middle when using separation.
self.hmGrainMargin = 2
#These are not mountain peaks, but points on the height map initialized
#to 1.0 before the midpoint displacement process begins. This sets the
#percentage of 'peaks' for points that are not on the grain margin.
self.hmInitialPeakPercent = 0.30
#Scales the heuristic for random midpoint displacement. A higher number
#will create more noise(bumpy), a smaller number will make less
#noise(smooth).