]> git.zerfleddert.de Git - micropolis/blob - src/sim/terrain/mapgener.c
Import Micropolis from http://www.donhopkins.com/home/micropolis/
[micropolis] / src / sim / terrain / mapgener.c
1 /* mapgener.c
2 *
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.
8 *
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.
13 *
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/>.
20 *
21 * ADDITIONAL TERMS per GNU GPL Section 7
22 *
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.
28 *
29 * Any propagation or conveyance of this program must include this
30 * copyright notice and these terms.
31 *
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.
36 *
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.
40 *
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
60 * NOT APPLY TO YOU.
61 */
62
63 /* Micropolis simulator code. Copyright 1988, 1989 Maxis, Will Wright */
64
65 #include "sim.h"
66
67 #define TRUE 1
68 #define FALSE 0
69 #define WORLD_X 120
70 #define WORLD_Y 100
71 #define RIVER 2
72 #define REDGE 3
73 #define CHANNEL 4
74 #define WOODS 37
75 #define BL 4096
76 #define BN 8192
77 #define BLN BL+BN
78
79 static int XStart, YStart;
80 static int Dir, LastDir;
81
82 /* trash values for GRand() */
83 static int GRanArray[5] = { 1018,4521,202,419,3 };
84
85 far GenerateMap()
86 {
87 GRanArray[0] = TickCount(); /* This is the only machine-specific call */
88 /* It inits GRand() w/ clockcount(long) */
89
90 if (!(GRand(10))) { /* 1 in 3 chance that island is generated */
91 MakeIsland();
92 return;
93 }
94 ClearMap(); /* else make river map */
95 GetRandStart();
96 DoRivers();
97 MakeLakes();
98 SmoothRiver();
99 DoTrees();
100 }
101
102 near ClearMap()
103 {
104 register int x, y;
105
106 for (x=0; x<WORLD_X; x++)
107 for (y=0; y<WORLD_Y; y++)
108 Map[x][y] = 0;
109 }
110
111 #define RADIUS 18
112
113 near MakeIsland()
114 {
115 register int x,y,z;
116
117 for (x=0; x<WORLD_X; x++)
118 for (y=0; y<WORLD_Y; y++)
119 Map[x][y] = RIVER;
120 for (x=5; x<WORLD_X-5; x++)
121 for (y=5; y<WORLD_Y-5; y++)
122 Map[x][y] = 0;
123 for (x=0; x<WORLD_X-5; x+=2) {
124 MapX= x ;
125 MapY= EGRand(RADIUS);
126 BRivPlop();
127 MapY= 90-EGRand(RADIUS);
128 BRivPlop();
129 MapY= 0;
130 SRivPlop();
131 MapY= 94;
132 SRivPlop();
133 }
134 for (y=0; y<WORLD_Y-5; y+=2) {
135 MapY= y ;
136 MapX= EGRand(RADIUS);
137 BRivPlop();
138 MapX= 110-EGRand(RADIUS);
139 BRivPlop();
140 MapX= 0;
141 SRivPlop();
142 MapX= 114;
143 SRivPlop();
144 }
145 SmoothRiver();
146 DoTrees();
147 }
148
149 near MakeLakes()
150 {
151 int Lim1, Lim2, t, z;
152 register int x, y;
153
154 Lim1 = GRand(10);
155 for (t = 0; t < Lim1; t++) {
156 x = GRand(99) + 10;
157 y = GRand(80) + 10;
158 Lim2 = GRand(12)+2;
159 for (z = 0; z < Lim2; z++) {
160 MapX = x - 6 + GRand(12);
161 MapY = y - 6 + GRand(12);
162 if (GRand(4)) SRivPlop();
163 else BRivPlop();
164 }
165 }
166 }
167
168 near GetRandStart()
169 {
170 XStart = 40 + GRand(40);
171 YStart = 33 + GRand(33);
172 MapX = XStart;
173 MapY = YStart;
174 }
175
176 near DoTrees()
177 {
178 int Amount,x,xloc,yloc;
179
180 Amount = GRand(100)+50;
181 for (x=0; x<Amount; x++) {
182 xloc = GRand(119);
183 yloc = GRand(99);
184 TreeSplash(xloc,yloc);
185 }
186 SmoothTrees();
187 SmoothTrees();
188 }
189
190 near TreeSplash(xloc,yloc)
191 int xloc,yloc;
192 {
193 int Dis, Dir;
194 register int xoff, yoff,z;
195
196 Dis = GRand(150)+50;
197 MapX = xloc;
198 MapY = yloc;
199 for (z=0; z<Dis; z++) {
200 Dir = GRand(7);
201 MoveMap(Dir);
202 if (!(TestBounds(MapX,MapY))) return;
203 if (Map[MapX][MapY] == 0) Map[MapX][MapY] = WOODS+ BLN;
204 }
205 }
206
207 far SmoothRiver()
208 {
209 static int DX[4] = {-1, 0, 1, 0};
210 static int DY[4] = { 0, 1, 0,-1};
211 static int REdTab[16] = { 13+BL,13+BL,17+BL,15+BL,5+BL,2,19+BL,
212 17+BL,9+BL,11+BL,2,13+BL,7+BL,9+BL,5+BL,2};
213 int bitindex, z,Xtem,Ytem;
214 register int temp,MapX,MapY;
215
216 for (MapX = 0; MapX < WORLD_X; MapX++)
217 for (MapY = 0; MapY < WORLD_Y; MapY++)
218 if (Map[MapX][MapY] == REDGE) {
219 bitindex = 0;
220 for (z=0; z<4; z++) {
221 bitindex = bitindex << 1;
222 Xtem = MapX + DX[z];
223 Ytem = MapY + DY[z];
224 if (TestBounds(Xtem, Ytem))
225 if ( Map[Xtem][Ytem]) bitindex++;
226 }
227 temp = REdTab[bitindex & 15];
228 if ((temp != 2) && (GRand(1))) temp++;
229 Map[MapX][MapY] = temp;
230 }
231 }
232
233 far SmoothTrees()
234 {
235 static int DX[4] = {-1, 0, 1, 0};
236 static int DY[4] = { 0, 1, 0,-1};
237 static int TEdTab[16] = {0,0,0,34,0,0,36,35,0,32,0,33,30,31,29,37};
238 int bitindex, z,Xtem,Ytem;
239 register int temp,MapX,MapY;
240
241 for (MapX = 0; MapX < WORLD_X; MapX++)
242 for (MapY = 0; MapY < WORLD_Y; MapY++)
243 if ((Map[MapX][MapY] & BLN) == BLN) {
244 bitindex = 0;
245 for (z=0; z<4; z++) {
246 bitindex = bitindex << 1;
247 Xtem = MapX + DX[z];
248 Ytem = MapY + DY[z];
249 if (TestBounds(Xtem, Ytem))
250 if (Map[Xtem][Ytem] & BN) bitindex++;
251
252 }
253 temp = TEdTab[bitindex & 15];
254 if (temp) {
255 if (temp != 37)
256 if ((MapX+MapY) & 1)
257 temp = temp-8;
258 Map[MapX][MapY] = temp+BLN;
259 }
260 else Map[MapX][MapY] = temp;
261 }
262 }
263
264 near DoRivers()
265 {
266
267 LastDir = GRand(3);
268 Dir = LastDir;
269 DoBRiv();
270 MapX = XStart;
271 MapY = YStart;
272 LastDir = LastDir ^ 4;
273 Dir = LastDir;
274 DoBRiv();
275 MapX = XStart;
276 MapY = YStart;
277 LastDir = GRand(3);
278 DoSRiv();
279 }
280
281 near DoBRiv()
282 {
283 int temp, count;
284
285 count = 0;
286 while (TestBounds (MapX+4, MapY+4)) {
287 BRivPlop();
288 if (GRand(10) > 4) Dir++;
289 if (GRand(10) > 4) Dir--;
290 if (!(GRand(10))) Dir = LastDir;
291 MoveMap (Dir);
292 }
293 }
294
295 near DoSRiv()
296 {
297 int temp;
298
299 while (TestBounds (MapX+3, MapY+3)) {
300 SRivPlop();
301 if (GRand(10) > 5) Dir++;
302 if (GRand(10) > 5) Dir--;
303 if (!(GRand(12))) Dir = LastDir;
304 MoveMap (Dir);
305 }
306 }
307
308 near MoveMap (dir)
309 int dir;
310 {
311 static int DirTab[2][8] ={ { 0, 1, 1, 1, 0, -1, -1, -1},
312 {-1,-1, 0, 1, 1, 1, 0, -1} };
313 dir = dir & 7;
314 MapX += DirTab[0][dir];
315 MapY += DirTab[1][dir];
316 }
317
318
319
320
321 near BRivPlop()
322 {
323 static int BRMatrix[9][9] ={
324 {0,0,0,3,3,3,0,0,0},
325 {0,0,3,2,2,2,3,0,0},
326 {0,3,2,2,2,2,2,3,0},
327 {3,2,2,2,2,2,2,2,3},
328 {3,2,2,2,4,2,2,2,3},
329 {3,2,2,2,2,2,2,2,3},
330 {0,3,2,2,2,2,2,3,0},
331 {0,0,3,2,2,2,3,0,0},
332 {0,0,0,3,3,3,0,0,0} };
333 int x, y;
334
335 for (x=0; x<9; x++)
336 for (y=0; y<9; y++)
337 PutOnMap (BRMatrix[y][x], x, y);
338 }
339
340 near SRivPlop()
341 {
342 static int SRMatrix[6][6] ={
343 {0,0,3,3,0,0},
344 {0,3,2,2,3,0},
345 {3,2,2,2,2,3},
346 {3,2,2,2,2,3},
347 {0,3,2,2,3,0},
348 {0,0,3,3,0,0} };
349 int x, y;
350
351 for (x=0; x<6; x++)
352 for (y=0; y<6; y++)
353 PutOnMap (SRMatrix[y][x], x, y);
354 }
355
356 near PutOnMap (Mchar, Xoff, Yoff)
357 int Mchar, Xoff, Yoff;
358 {
359 register int Xloc, Yloc, temp;
360
361 if (Mchar == 0) return;
362 Xloc = MapX + Xoff;
363 Yloc = MapY + Yoff;
364 if (TestBounds (Xloc, Yloc) == FALSE) return (FALSE);
365 if (temp = Map [Xloc][Yloc]) {
366 temp = temp & 1023;
367 if (temp == RIVER)
368 if (Mchar != CHANNEL)
369 return (FALSE);
370 if (temp == CHANNEL) return (FALSE);
371 }
372 Map [Xloc][Yloc] = Mchar;
373 }
374
375 far TestBounds(x, y)
376 register int x, y;
377 {
378 if ((( x >= 0) && (x < WORLD_X)) && (( y >= 0) && (y < WORLD_Y)))
379 return (TRUE);
380 return (FALSE);
381 }
382
383
384
385 near EGRand(limit)
386 int limit;
387 {
388 int x,z;
389
390 z= GRand(limit);
391 x= GRand(limit);
392 if (z < x) return(z);
393 return(x);
394 }
395
396 #define RANMASK 32767
397
398 near GRand(range) /* stupid but works */
399 int range;
400 {
401 register x, newv, divisor;
402
403 divisor = RANMASK/ (range+1);
404 newv = 0;
405 for (x=4; x!=0; x--)
406 newv += (GRanArray[x] = GRanArray[x-1]);
407 GRanArray[0] = newv;
408 x = (newv & RANMASK) / divisor;
409 if (x > range) return(range);
410 return(x);
411 }
Impressum, Datenschutz