]>
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 */
84 GenerateSomeCity(Rand16());
88 GenerateSomeCity(int r
)
90 if (CityFileName
!= NULL
) {
95 gettimeofday(&start_time
, NULL
);
110 Eval("UIDidGenerateNewCity");
131 if (CreateIsland
< 0) {
132 if (Rand(100) < 10) { /* chance that island is generated */
137 if (CreateIsland
== 1) {
143 if (CurveLevel
!= 0) {
146 if (LakeLevel
!= 0) {
150 if (TreeLevel
!= 0) {
161 for (x
= 0; x
< WORLD_X
; x
++)
162 for (y
= 0; y
< WORLD_Y
; y
++)
171 for (x
= 0; x
< WORLD_X
; x
++) {
172 for (y
= 0; y
< WORLD_Y
; y
++) {
173 if (Map
[x
][y
] > WOODS
) {
187 for (x
= 0; x
< WORLD_X
; x
++)
188 for (y
= 0; y
< WORLD_Y
; y
++)
190 for (x
= 5; x
< WORLD_X
- 5; x
++)
191 for (y
= 5; y
< WORLD_Y
- 5; y
++)
193 for (x
= 0; x
< WORLD_X
- 5; x
+= 2) {
195 MapY
= ERand(RADIUS
);
197 MapY
= (WORLD_Y
- 10) - ERand(RADIUS
);
201 MapY
= (WORLD_Y
- 6);
204 for (y
= 0; y
< WORLD_Y
- 5; y
+= 2) {
206 MapX
= ERand(RADIUS
);
208 MapX
= (WORLD_X
- 10) - ERand(RADIUS
);
212 MapX
= (WORLD_X
- 6);
228 short Lim1
, Lim2
, t
, z
;
234 Lim1
= LakeLevel
/ 2;
236 for (t
= 0; t
< Lim1
; t
++) {
237 x
= Rand(WORLD_X
- 21) + 10;
238 y
= Rand(WORLD_Y
- 20) + 10;
240 for (z
= 0; z
< Lim2
; z
++) {
241 MapX
= x
- 6 + Rand(12);
242 MapY
= y
- 6 + Rand(12);
254 XStart
= 40 + Rand(WORLD_X
- 80);
255 YStart
= 33 + Rand(WORLD_Y
- 67);
263 static short DirTab
[2][8] = { { 0, 1, 1, 1, 0, -1, -1, -1},
264 {-1,-1, 0, 1, 1, 1, 0, -1} };
266 MapX
+= DirTab
[0][dir
];
267 MapY
+= DirTab
[1][dir
];
271 TreeSplash(short xloc
, short yloc
)
274 register short xoff
, yoff
, z
;
277 dis
= Rand(150) + 50;
279 dis
= Rand(100 + (TreeLevel
* 2)) + 50;
283 for (z
= 0; z
< dis
; z
++) {
286 if (!(TestBounds(MapX
, MapY
)))
288 if ((Map
[MapX
][MapY
] & LOMASK
) == DIRT
)
289 Map
[MapX
][MapY
] = WOODS
+ BLBNBIT
;
296 short Amount
, x
, xloc
, yloc
;
299 Amount
= Rand(100) + 50;
301 Amount
= TreeLevel
+ 3;
303 for(x
= 0; x
< Amount
; x
++) {
304 xloc
= Rand(WORLD_X
- 1);
305 yloc
= Rand(WORLD_Y
- 1);
306 TreeSplash(xloc
, yloc
);
315 static short DX
[4] = {-1, 0, 1, 0};
316 static short DY
[4] = { 0, 1, 0,-1};
317 static short REdTab
[16] = {
318 13+BULLBIT
, 13+BULLBIT
, 17+BULLBIT
, 15+BULLBIT
,
319 5+BULLBIT
, 2, 19+BULLBIT
, 17+BULLBIT
,
320 9+BULLBIT
, 11+BULLBIT
, 2, 13+BULLBIT
,
321 7+BULLBIT
, 9+BULLBIT
, 5+BULLBIT
, 2 };
322 short bitindex
, z
, Xtem
, Ytem
;
323 register short temp
, MapX
, MapY
;
325 for (MapX
= 0; MapX
< WORLD_X
; MapX
++) {
326 for (MapY
= 0; MapY
< WORLD_Y
; MapY
++) {
327 if (Map
[MapX
][MapY
] == REDGE
) {
329 for (z
= 0; z
< 4; z
++) {
330 bitindex
= bitindex
<< 1;
333 if (TestBounds(Xtem
, Ytem
) &&
334 ((Map
[Xtem
][Ytem
] & LOMASK
) != DIRT
) &&
335 (((Map
[Xtem
][Ytem
]&LOMASK
) < WOODS_LOW
) ||
336 ((Map
[Xtem
][Ytem
]&LOMASK
) > WOODS_HIGH
)))
339 temp
= REdTab
[bitindex
& 15];
340 if ((temp
!= RIVER
) && (Rand(1)))
342 Map
[MapX
][MapY
] = temp
;
351 if (((cell
& LOMASK
) >= WOODS_LOW
) &&
352 ((cell
& LOMASK
) <= WOODS_HIGH
))
360 static short DX
[4] = {-1, 0, 1, 0};
361 static short DY
[4] = { 0, 1, 0,-1};
362 static short TEdTab
[16] = { 0, 0, 0, 34,
366 short bitindex
, z
, Xtem
, Ytem
;
367 register short temp
, MapX
, MapY
;
369 for (MapX
= 0; MapX
< WORLD_X
; MapX
++) {
370 for (MapY
= 0; MapY
< WORLD_Y
; MapY
++) {
371 if (IsTree(Map
[MapX
][MapY
])) {
373 for (z
= 0; z
< 4; z
++) {
374 bitindex
= bitindex
<< 1;
377 if (TestBounds(Xtem
, Ytem
) &&
378 IsTree(Map
[Xtem
][Ytem
])) {
382 temp
= TEdTab
[bitindex
& 15];
385 if ((MapX
+ MapY
) & 1)
387 Map
[MapX
][MapY
] = temp
+ BLBNBIT
;
389 else Map
[MapX
][MapY
] = temp
;
404 LastDir
= LastDir
^ 4;
418 if (CurveLevel
< 0) {
422 r1
= CurveLevel
+ 10;
423 r2
= CurveLevel
+ 100;
426 while (TestBounds (MapX
+ 4, MapY
+ 4)) {
431 if (Rand(r2
) > 90) Dir
++;
432 if (Rand(r2
) > 90) Dir
--;
443 if (CurveLevel
< 0) {
447 r1
= CurveLevel
+ 10;
448 r2
= CurveLevel
+ 100;
451 while (TestBounds (MapX
+ 3, MapY
+ 3)) {
456 if (Rand(r2
) > 90) Dir
++;
457 if (Rand(r2
) > 90) Dir
--;
464 PutOnMap(short Mchar
, short Xoff
, short Yoff
)
466 register short Xloc
, Yloc
, temp
;
472 if (TestBounds(Xloc
, Yloc
) == FALSE
)
474 if (temp
= Map
[Xloc
][Yloc
]) {
475 temp
= temp
& LOMASK
;
477 if (Mchar
!= CHANNEL
)
482 Map
[Xloc
][Yloc
] = Mchar
;
488 static short BRMatrix
[9][9] = {
489 { 0, 0, 0, 3, 3, 3, 0, 0, 0 },
490 { 0, 0, 3, 2, 2, 2, 3, 0, 0 },
491 { 0, 3, 2, 2, 2, 2, 2, 3, 0 },
492 { 3, 2, 2, 2, 2, 2, 2, 2, 3 },
493 { 3, 2, 2, 2, 4, 2, 2, 2, 3 },
494 { 3, 2, 2, 2, 2, 2, 2, 2, 3 },
495 { 0, 3, 2, 2, 2, 2, 2, 3, 0 },
496 { 0, 0, 3, 2, 2, 2, 3, 0, 0 },
497 { 0, 0, 0, 3, 3, 3, 0, 0, 0 } };
500 for (x
= 0; x
< 9; x
++)
501 for (y
= 0; y
< 9; y
++)
502 PutOnMap(BRMatrix
[y
][x
], x
, y
);
508 static short SRMatrix
[6][6] = {
509 { 0, 0, 3, 3, 0, 0 },
510 { 0, 3, 2, 2, 3, 0 },
511 { 3, 2, 2, 2, 2, 3 },
512 { 3, 2, 2, 2, 2, 3 },
513 { 0, 3, 2, 2, 3, 0 },
514 { 0, 0, 3, 3, 0, 0 } };
517 for (x
= 0; x
< 6; x
++)
518 for (y
= 0; y
< 6; y
++)
519 PutOnMap(SRMatrix
[y
][x
], x
, y
);
527 for(x
= 0; x
< WORLD_X
; x
++) {
528 for(y
= 0; y
< WORLD_Y
; y
++) {
530 if (((Map
[x
][y
] & LOMASK
) >= WATER_LOW
) &&
531 ((Map
[x
][y
] & LOMASK
) <= WATER_HIGH
)) {
533 /* If nearest object is not water: */
534 if (((Map
[x
- 1][y
] & LOMASK
) < WATER_LOW
) ||
535 ((Map
[x
- 1][y
] & LOMASK
) > WATER_HIGH
)) {
539 if (x
< (WORLD_X
- 1)) {
540 /* If nearest object is not water: */
541 if (((Map
[x
+1][y
]&LOMASK
) < WATER_LOW
) ||
542 ((Map
[x
+1][y
]&LOMASK
) > WATER_HIGH
)) {
547 /* If nearest object is not water: */
548 if (((Map
[x
][y
- 1] & LOMASK
) < WATER_LOW
) ||
549 ((Map
[x
][y
-1]&LOMASK
) > WATER_HIGH
)) {
553 if (y
< (WORLD_Y
- 1)) {
554 /* If nearest object is not water: */
555 if (((Map
[x
][y
+ 1] & LOMASK
) < WATER_LOW
) ||
556 ((Map
[x
][y
+ 1] & LOMASK
) > WATER_HIGH
)) {
558 Map
[x
][y
]=REDGE
; /* set river edge */
565 for (x
= 0; x
< WORLD_X
; x
++) {
566 for (y
= 0; y
< WORLD_Y
; y
++) {
567 /* If water which is not a channel: */
568 if (((Map
[x
][y
] & LOMASK
) != CHANNEL
) &&
569 ((Map
[x
][y
] & LOMASK
) >= WATER_LOW
) &&
570 ((Map
[x
][y
] & LOMASK
) <= WATER_HIGH
)) {
572 /* If nearest object is not water; */
573 if (((Map
[x
- 1][y
] & LOMASK
) < WATER_LOW
) ||
574 ((Map
[x
- 1][y
] & LOMASK
) > WATER_HIGH
)) {
578 if (x
< (WORLD_X
- 1)) {
579 /* If nearest object is not water: */
580 if (((Map
[x
+ 1][y
] & LOMASK
) < WATER_LOW
) ||
581 ((Map
[x
+ 1][y
] & LOMASK
) > WATER_HIGH
)) {
586 /* If nearest object is not water: */
587 if (((Map
[x
][y
- 1] & LOMASK
) < WATER_LOW
) ||
588 ((Map
[x
][y
- 1] & LOMASK
) > WATER_HIGH
)) {
592 if (y
< (WORLD_Y
- 1)) {
593 /* If nearest object is not water: */
594 if (((Map
[x
][y
+ 1] & LOMASK
) < WATER_LOW
) ||
595 ((Map
[x
][y
+ 1] & LOMASK
) > WATER_HIGH
)) {
599 Map
[x
][y
] = RIVER
; /* make it a river */
603 for (x
= 0; x
< WORLD_X
; x
++) {
604 for (y
= 0; y
< WORLD_Y
; y
++) {
606 if (((Map
[x
][y
] & LOMASK
) >= WOODS_LOW
) &&
607 ((Map
[x
][y
] & LOMASK
) <= WOODS_HIGH
)) {
609 /* If nearest object is water: */
610 if ((Map
[x
- 1][y
] == RIVER
) ||
611 (Map
[x
- 1][y
] == CHANNEL
)) {
612 Map
[x
][y
] = REDGE
; /* make it water's edge */
616 if (x
< (WORLD_X
- 1)) {
617 /* If nearest object is water: */
618 if ((Map
[x
+ 1][y
] == RIVER
) ||
619 (Map
[x
+ 1][y
] == CHANNEL
)) {
620 Map
[x
][y
] = REDGE
; /* make it water's edge */
625 /* If nearest object is water: */
626 if ((Map
[x
][y
- 1] == RIVER
) ||
627 (Map
[x
][y
- 1] == CHANNEL
)) {
628 Map
[x
][y
] = REDGE
; /* make it water's edge */
632 if (y
< (WORLD_Y
- 1)) {
633 /* If nearest object is water; */
634 if ((Map
[x
][y
+ 1] == RIVER
) ||
635 (Map
[x
][y
+ 1] == CHANNEL
)) {
636 Map
[x
][y
] = REDGE
; /* make it water's edge */