|
|
1.1 root 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 [email protected].
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.