]> git.zerfleddert.de Git - micropolis/blame - src/sim/terrain/mapgener.c
resize editor when resizing window
[micropolis] / src / sim / terrain / mapgener.c
CommitLineData
6a5fa4e0
MG
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
79static int XStart, YStart;
80static int Dir, LastDir;
81
82 /* trash values for GRand() */
83static int GRanArray[5] = { 1018,4521,202,419,3 };
84
85far 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
102near ClearMap()
103{
104register 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
113near 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
149near 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
168near GetRandStart()
169{
170 XStart = 40 + GRand(40);
171 YStart = 33 + GRand(33);
172 MapX = XStart;
173 MapY = YStart;
174}
175
176near 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
190near TreeSplash(xloc,yloc)
191int 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
207far 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
233far 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
264near 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
281near DoBRiv()
282{
283int 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
295near DoSRiv()
296{
297int 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
308near MoveMap (dir)
309int dir;
310{
311static 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
321near BRivPlop()
322{
323static 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} };
333int 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
340near SRivPlop()
341{
342static 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} };
349int 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
356near PutOnMap (Mchar, Xoff, Yoff)
357int Mchar, Xoff, Yoff;
358{
359register 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
375far TestBounds(x, y)
376register 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
385near EGRand(limit)
386int 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
398near GRand(range) /* stupid but works */
399int 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