]>
git.zerfleddert.de Git - micropolis/blob - src/sim/s_gen.c
3 * Micropolis, Unix Version. This game was released for the Unix platform
4 * in or about 1990 and has been modified for inclusion in the One Laptop
5 * Per Child program. Copyright (C) 1989 - 2007 Electronic Arts Inc. If
6 * you need assistance with this program, you may contact:
7 * http://wiki.laptop.org/go/Micropolis or email micropolis@laptop.org.
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or (at
12 * your option) any later version.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details. You should have received a
18 * copy of the GNU General Public License along with this program. If
19 * not, see <http://www.gnu.org/licenses/>.
21 * ADDITIONAL TERMS per GNU GPL Section 7
23 * No trademark or publicity rights are granted. This license does NOT
24 * give you any right, title or interest in the trademark SimCity or any
25 * other Electronic Arts trademark. You may not distribute any
26 * modification of this program using the trademark SimCity or claim any
27 * affliation or association with Electronic Arts Inc. or its employees.
29 * Any propagation or conveyance of this program must include this
30 * copyright notice and these terms.
32 * If you convey this program (or any modifications of it) and assume
33 * contractual liability for the program to recipients of it, you agree
34 * to indemnify Electronic Arts for any liability that those contractual
35 * assumptions impose on Electronic Arts.
37 * You may not misrepresent the origins of this program; modified
38 * versions of the program must be marked as such and not identified as
39 * the original program.
41 * This disclaimer supplements the one included in the General Public
42 * License. TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, THIS
43 * PROGRAM IS PROVIDED TO YOU "AS IS," WITH ALL FAULTS, WITHOUT WARRANTY
44 * OF ANY KIND, AND YOUR USE IS AT YOUR SOLE RISK. THE ENTIRE RISK OF
45 * SATISFACTORY QUALITY AND PERFORMANCE RESIDES WITH YOU. ELECTRONIC ARTS
46 * DISCLAIMS ANY AND ALL EXPRESS, IMPLIED OR STATUTORY WARRANTIES,
47 * INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY, SATISFACTORY QUALITY,
48 * FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT OF THIRD PARTY
49 * RIGHTS, AND WARRANTIES (IF ANY) ARISING FROM A COURSE OF DEALING,
50 * USAGE, OR TRADE PRACTICE. ELECTRONIC ARTS DOES NOT WARRANT AGAINST
51 * INTERFERENCE WITH YOUR ENJOYMENT OF THE PROGRAM; THAT THE PROGRAM WILL
52 * MEET YOUR REQUIREMENTS; THAT OPERATION OF THE PROGRAM WILL BE
53 * UNINTERRUPTED OR ERROR-FREE, OR THAT THE PROGRAM WILL BE COMPATIBLE
54 * WITH THIRD PARTY SOFTWARE OR THAT ANY ERRORS IN THE PROGRAM WILL BE
55 * CORRECTED. NO ORAL OR WRITTEN ADVICE PROVIDED BY ELECTRONIC ARTS OR
56 * ANY AUTHORIZED REPRESENTATIVE SHALL CREATE A WARRANTY. SOME
57 * JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF OR LIMITATIONS ON IMPLIED
58 * WARRANTIES OR THE LIMITATIONS ON THE APPLICABLE STATUTORY RIGHTS OF A
59 * CONSUMER, SO SOME OR ALL OF THE ABOVE EXCLUSIONS AND LIMITATIONS MAY
68 #define WATER_LOW RIVER /* 2 */
69 #define WATER_HIGH LASTRIVEDGE /* 20 */
70 #define WOODS_LOW TREEBASE /* 21 */
71 #define WOODS_HIGH UNUSED_TRASH2 /* 39 */
74 short XStart
, YStart
, MapX
, MapY
;
76 int TreeLevel
= -1; /* level for tree creation */
77 int LakeLevel
= -1; /* level for lake creation */
78 int CurveLevel
= -1; /* level for river curviness */
79 int CreateIsland
= -1; /* -1 => 10%, 0 => never, 1 => always */
87 void GetRandStart(void);
89 void MakeIsland(void);
90 void MakeNakedIsland(void);
91 void GenerateMap(int r
);
97 GenerateSomeCity(Rand16());
102 GenerateSomeCity(int r
)
104 if (CityFileName
!= NULL
) {
105 ckfree(CityFileName
);
109 gettimeofday(&start_time
, NULL
);
124 Eval("UIDidGenerateNewCity");
147 if (CreateIsland
< 0) {
148 if (Rand(100) < 10) { /* chance that island is generated */
153 if (CreateIsland
== 1) {
159 if (CurveLevel
!= 0) {
162 if (LakeLevel
!= 0) {
166 if (TreeLevel
!= 0) {
178 for (x
= 0; x
< WORLD_X
; x
++)
179 for (y
= 0; y
< WORLD_Y
; y
++)
189 for (x
= 0; x
< WORLD_X
; x
++) {
190 for (y
= 0; y
< WORLD_Y
; y
++) {
191 if (Map
[x
][y
] > WOODS
) {
202 MakeNakedIsland(void)
206 for (x
= 0; x
< WORLD_X
; x
++)
207 for (y
= 0; y
< WORLD_Y
; y
++)
209 for (x
= 5; x
< WORLD_X
- 5; x
++)
210 for (y
= 5; y
< WORLD_Y
- 5; y
++)
212 for (x
= 0; x
< WORLD_X
- 5; x
+= 2) {
214 MapY
= ERand(RADIUS
);
216 MapY
= (WORLD_Y
- 10) - ERand(RADIUS
);
220 MapY
= (WORLD_Y
- 6);
223 for (y
= 0; y
< WORLD_Y
- 5; y
+= 2) {
225 MapX
= ERand(RADIUS
);
227 MapX
= (WORLD_X
- 10) - ERand(RADIUS
);
231 MapX
= (WORLD_X
- 6);
249 short Lim1
, Lim2
, t
, z
;
255 Lim1
= LakeLevel
/ 2;
257 for (t
= 0; t
< Lim1
; t
++) {
258 x
= Rand(WORLD_X
- 21) + 10;
259 y
= Rand(WORLD_Y
- 20) + 10;
261 for (z
= 0; z
< Lim2
; z
++) {
262 MapX
= x
- 6 + Rand(12);
263 MapY
= y
- 6 + Rand(12);
276 XStart
= 40 + Rand(WORLD_X
- 80);
277 YStart
= 33 + Rand(WORLD_Y
- 67);
286 static short DirTab
[2][8] = { { 0, 1, 1, 1, 0, -1, -1, -1},
287 {-1,-1, 0, 1, 1, 1, 0, -1} };
289 MapX
+= DirTab
[0][dir
];
290 MapY
+= DirTab
[1][dir
];
295 TreeSplash(short xloc
, short yloc
)
301 dis
= Rand(150) + 50;
303 dis
= Rand(100 + (TreeLevel
* 2)) + 50;
307 for (z
= 0; z
< dis
; z
++) {
310 if (!(TestBounds(MapX
, MapY
)))
312 if ((Map
[MapX
][MapY
] & LOMASK
) == DIRT
)
313 Map
[MapX
][MapY
] = WOODS
+ BLBNBIT
;
321 short Amount
, x
, xloc
, yloc
;
324 Amount
= Rand(100) + 50;
326 Amount
= TreeLevel
+ 3;
328 for(x
= 0; x
< Amount
; x
++) {
329 xloc
= Rand(WORLD_X
- 1);
330 yloc
= Rand(WORLD_Y
- 1);
331 TreeSplash(xloc
, yloc
);
341 static short DX
[4] = {-1, 0, 1, 0};
342 static short DY
[4] = { 0, 1, 0,-1};
343 static short REdTab
[16] = {
344 13+BULLBIT
, 13+BULLBIT
, 17+BULLBIT
, 15+BULLBIT
,
345 5+BULLBIT
, 2, 19+BULLBIT
, 17+BULLBIT
,
346 9+BULLBIT
, 11+BULLBIT
, 2, 13+BULLBIT
,
347 7+BULLBIT
, 9+BULLBIT
, 5+BULLBIT
, 2 };
348 short bitindex
, z
, Xtem
, Ytem
;
349 register short temp
, MapX
, MapY
;
351 for (MapX
= 0; MapX
< WORLD_X
; MapX
++) {
352 for (MapY
= 0; MapY
< WORLD_Y
; MapY
++) {
353 if (Map
[MapX
][MapY
] == REDGE
) {
355 for (z
= 0; z
< 4; z
++) {
356 bitindex
= bitindex
<< 1;
359 if (TestBounds(Xtem
, Ytem
) &&
360 ((Map
[Xtem
][Ytem
] & LOMASK
) != DIRT
) &&
361 (((Map
[Xtem
][Ytem
]&LOMASK
) < WOODS_LOW
) ||
362 ((Map
[Xtem
][Ytem
]&LOMASK
) > WOODS_HIGH
)))
365 temp
= REdTab
[bitindex
& 15];
366 if ((temp
!= RIVER
) && (Rand(1)))
368 Map
[MapX
][MapY
] = temp
;
378 if (((cell
& LOMASK
) >= WOODS_LOW
) &&
379 ((cell
& LOMASK
) <= WOODS_HIGH
))
388 static short DX
[4] = {-1, 0, 1, 0};
389 static short DY
[4] = { 0, 1, 0,-1};
390 static short TEdTab
[16] = { 0, 0, 0, 34,
394 short bitindex
, z
, Xtem
, Ytem
;
395 register short temp
, MapX
, MapY
;
397 for (MapX
= 0; MapX
< WORLD_X
; MapX
++) {
398 for (MapY
= 0; MapY
< WORLD_Y
; MapY
++) {
399 if (IsTree(Map
[MapX
][MapY
])) {
401 for (z
= 0; z
< 4; z
++) {
402 bitindex
= bitindex
<< 1;
405 if (TestBounds(Xtem
, Ytem
) &&
406 IsTree(Map
[Xtem
][Ytem
])) {
410 temp
= TEdTab
[bitindex
& 15];
413 if ((MapX
+ MapY
) & 1)
415 Map
[MapX
][MapY
] = temp
+ BLBNBIT
;
417 else Map
[MapX
][MapY
] = temp
;
433 LastDir
= LastDir
^ 4;
448 if (CurveLevel
< 0) {
452 r1
= CurveLevel
+ 10;
453 r2
= CurveLevel
+ 100;
456 while (TestBounds (MapX
+ 4, MapY
+ 4)) {
461 if (Rand(r2
) > 90) Dir
++;
462 if (Rand(r2
) > 90) Dir
--;
474 if (CurveLevel
< 0) {
478 r1
= CurveLevel
+ 10;
479 r2
= CurveLevel
+ 100;
482 while (TestBounds (MapX
+ 3, MapY
+ 3)) {
487 if (Rand(r2
) > 90) Dir
++;
488 if (Rand(r2
) > 90) Dir
--;
496 PutOnMap(short Mchar
, short Xoff
, short Yoff
)
498 register short Xloc
, Yloc
, temp
;
504 if (TestBounds(Xloc
, Yloc
) == FALSE
)
506 if ((temp
= Map
[Xloc
][Yloc
])) {
507 temp
= temp
& LOMASK
;
509 if (Mchar
!= CHANNEL
)
514 Map
[Xloc
][Yloc
] = Mchar
;
521 static short BRMatrix
[9][9] = {
522 { 0, 0, 0, 3, 3, 3, 0, 0, 0 },
523 { 0, 0, 3, 2, 2, 2, 3, 0, 0 },
524 { 0, 3, 2, 2, 2, 2, 2, 3, 0 },
525 { 3, 2, 2, 2, 2, 2, 2, 2, 3 },
526 { 3, 2, 2, 2, 4, 2, 2, 2, 3 },
527 { 3, 2, 2, 2, 2, 2, 2, 2, 3 },
528 { 0, 3, 2, 2, 2, 2, 2, 3, 0 },
529 { 0, 0, 3, 2, 2, 2, 3, 0, 0 },
530 { 0, 0, 0, 3, 3, 3, 0, 0, 0 } };
533 for (x
= 0; x
< 9; x
++)
534 for (y
= 0; y
< 9; y
++)
535 PutOnMap(BRMatrix
[y
][x
], x
, y
);
542 static short SRMatrix
[6][6] = {
543 { 0, 0, 3, 3, 0, 0 },
544 { 0, 3, 2, 2, 3, 0 },
545 { 3, 2, 2, 2, 2, 3 },
546 { 3, 2, 2, 2, 2, 3 },
547 { 0, 3, 2, 2, 3, 0 },
548 { 0, 0, 3, 3, 0, 0 } };
551 for (x
= 0; x
< 6; x
++)
552 for (y
= 0; y
< 6; y
++)
553 PutOnMap(SRMatrix
[y
][x
], x
, y
);
562 for(x
= 0; x
< WORLD_X
; x
++) {
563 for(y
= 0; y
< WORLD_Y
; y
++) {
565 if (((Map
[x
][y
] & LOMASK
) >= WATER_LOW
) &&
566 ((Map
[x
][y
] & LOMASK
) <= WATER_HIGH
)) {
568 /* If nearest object is not water: */
569 if (((Map
[x
- 1][y
] & LOMASK
) < WATER_LOW
) ||
570 ((Map
[x
- 1][y
] & LOMASK
) > WATER_HIGH
)) {
574 if (x
< (WORLD_X
- 1)) {
575 /* If nearest object is not water: */
576 if (((Map
[x
+1][y
]&LOMASK
) < WATER_LOW
) ||
577 ((Map
[x
+1][y
]&LOMASK
) > WATER_HIGH
)) {
582 /* If nearest object is not water: */
583 if (((Map
[x
][y
- 1] & LOMASK
) < WATER_LOW
) ||
584 ((Map
[x
][y
-1]&LOMASK
) > WATER_HIGH
)) {
588 if (y
< (WORLD_Y
- 1)) {
589 /* If nearest object is not water: */
590 if (((Map
[x
][y
+ 1] & LOMASK
) < WATER_LOW
) ||
591 ((Map
[x
][y
+ 1] & LOMASK
) > WATER_HIGH
)) {
593 Map
[x
][y
]=REDGE
; /* set river edge */
600 for (x
= 0; x
< WORLD_X
; x
++) {
601 for (y
= 0; y
< WORLD_Y
; y
++) {
602 /* If water which is not a channel: */
603 if (((Map
[x
][y
] & LOMASK
) != CHANNEL
) &&
604 ((Map
[x
][y
] & LOMASK
) >= WATER_LOW
) &&
605 ((Map
[x
][y
] & LOMASK
) <= WATER_HIGH
)) {
607 /* If nearest object is not water; */
608 if (((Map
[x
- 1][y
] & LOMASK
) < WATER_LOW
) ||
609 ((Map
[x
- 1][y
] & LOMASK
) > WATER_HIGH
)) {
613 if (x
< (WORLD_X
- 1)) {
614 /* If nearest object is not water: */
615 if (((Map
[x
+ 1][y
] & LOMASK
) < WATER_LOW
) ||
616 ((Map
[x
+ 1][y
] & LOMASK
) > WATER_HIGH
)) {
621 /* If nearest object is not water: */
622 if (((Map
[x
][y
- 1] & LOMASK
) < WATER_LOW
) ||
623 ((Map
[x
][y
- 1] & LOMASK
) > WATER_HIGH
)) {
627 if (y
< (WORLD_Y
- 1)) {
628 /* If nearest object is not water: */
629 if (((Map
[x
][y
+ 1] & LOMASK
) < WATER_LOW
) ||
630 ((Map
[x
][y
+ 1] & LOMASK
) > WATER_HIGH
)) {
634 Map
[x
][y
] = RIVER
; /* make it a river */
638 for (x
= 0; x
< WORLD_X
; x
++) {
639 for (y
= 0; y
< WORLD_Y
; y
++) {
641 if (((Map
[x
][y
] & LOMASK
) >= WOODS_LOW
) &&
642 ((Map
[x
][y
] & LOMASK
) <= WOODS_HIGH
)) {
644 /* If nearest object is water: */
645 if ((Map
[x
- 1][y
] == RIVER
) ||
646 (Map
[x
- 1][y
] == CHANNEL
)) {
647 Map
[x
][y
] = REDGE
; /* make it water's edge */
651 if (x
< (WORLD_X
- 1)) {
652 /* If nearest object is water: */
653 if ((Map
[x
+ 1][y
] == RIVER
) ||
654 (Map
[x
+ 1][y
] == CHANNEL
)) {
655 Map
[x
][y
] = REDGE
; /* make it water's edge */
660 /* If nearest object is water: */
661 if ((Map
[x
][y
- 1] == RIVER
) ||
662 (Map
[x
][y
- 1] == CHANNEL
)) {
663 Map
[x
][y
] = REDGE
; /* make it water's edge */
667 if (y
< (WORLD_Y
- 1)) {
668 /* If nearest object is water; */
669 if ((Map
[x
][y
+ 1] == RIVER
) ||
670 (Map
[x
][y
+ 1] == CHANNEL
)) {
671 Map
[x
][y
] = REDGE
; /* make it water's edge */