]> git.zerfleddert.de Git - micropolis/blob - src/sim/w_con.c
0d20c9a55ffe23dbd5c988e724c14195d13d505e
[micropolis] / src / sim / w_con.c
1 /* w_con.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 #include "sim.h"
63
64
65 short _RoadTable[16] = {
66 66, 67, 66, 68,
67 67, 67, 69, 73,
68 66, 71, 66, 72,
69 70, 75, 74, 76
70 };
71
72 short _RailTable[16] = {
73 226, 227, 226, 228,
74 227, 227, 229, 233,
75 226, 231, 226, 232,
76 230, 235, 234, 236
77 };
78
79 short _WireTable[16] = {
80 210, 211, 210, 212,
81 211, 211, 213, 217,
82 210, 215, 210, 216,
83 214, 219, 218, 220
84 };
85
86
87 #define NeutralizeRoad(Tile) \
88 if (((Tile &= LOMASK) >= 64) && \
89 ((Tile & LOMASK) <= 207)) { \
90 Tile = (Tile & 0x000F) + 64; \
91 }
92
93
94 /* comefrom: check3Border check4Border check5Border processWand */
95 int
96 ConnecTile(short x, short y, short *TileAdrPtr, short Command)
97 {
98 short Tile;
99 int result = 1;
100
101 /* make sure the array subscripts are in bounds */
102 if (!TestBounds(x, y)) {
103 return (0);
104 }
105
106 /* AutoDoze */
107 if ((Command >= 2) && (Command <= 4)) {
108
109 if ((autoBulldoze != 0) &&
110 (TotalFunds > 0) &&
111 ((Tile = (*TileAdrPtr)) & BULLBIT)) {
112 NeutralizeRoad(Tile);
113 /* Maybe this should check BULLBIT instead of checking tile values? */
114 if (((Tile >= TINYEXP) && (Tile <= LASTTINYEXP)) ||
115 ((Tile < 64) && (Tile != 0))) {
116 Spend(1);
117 (*TileAdrPtr) = 0;
118 }
119 }
120 }
121
122 switch (Command) {
123
124 case 0: /* Fix zone */
125 _FixZone(x, y, TileAdrPtr);
126 break;
127
128 case 1: /* Doze zone */
129 result = _LayDoze(x, y, TileAdrPtr);
130 _FixZone(x, y, TileAdrPtr);
131 break;
132
133 case 2: /* Lay Road */
134 result = _LayRoad(x, y, TileAdrPtr);
135 _FixZone(x, y, TileAdrPtr);
136 break;
137
138 case 3: /* Lay Rail */
139 result = _LayRail(x, y, TileAdrPtr);
140 _FixZone(x, y, TileAdrPtr);
141 break;
142
143 case 4: /* Lay Wire */
144 result = _LayWire(x, y, TileAdrPtr);
145 _FixZone(x, y, TileAdrPtr);
146 break;
147
148 }
149
150 return result;
151 }
152
153 /* comefrom: ConnecTile */
154 int
155 _LayDoze(int x, int y, short *TileAdrPtr)
156 {
157 short Tile;
158
159 if (!(TotalFunds)) {
160 return -2; /* no mas dinero. */
161 }
162
163 Tile = (*TileAdrPtr);
164
165 if (!(Tile & BULLBIT)) {
166 return 0; /* Check dozeable bit. */
167 }
168
169 NeutralizeRoad(Tile);
170
171 switch (Tile) {
172 case HBRIDGE:
173 case VBRIDGE:
174 case BRWV:
175 case BRWH:
176 case HBRDG0:
177 case HBRDG1:
178 case HBRDG2:
179 case HBRDG3:
180 case VBRDG0:
181 case VBRDG1:
182 case VBRDG2:
183 case VBRDG3:
184 case HPOWER:
185 case VPOWER:
186 case HRAIL:
187 case VRAIL: /* Dozing over water, replace with water. */
188 (*TileAdrPtr) = RIVER;
189 break;
190
191 default: /* Dozing on land, replace with land. Simple, eh? */
192 (*TileAdrPtr) = DIRT;
193 break;
194 }
195
196 Spend(1); /* Costs $1.00....*/
197 return 1;
198 }
199
200
201 /* comefrom: ConnecTile */
202 int
203 _LayRoad(int x, int y, short *TileAdrPtr)
204 {
205 short Tile;
206 int cost = 10;
207
208 if (TotalFunds < 10) {
209 return -2;
210 }
211
212 Tile = (*TileAdrPtr) & LOMASK;
213
214 switch (Tile) {
215
216 case DIRT:
217 (*TileAdrPtr) = ROADS | BULLBIT | BURNBIT;
218 break;
219
220 case RIVER: /* Road on Water */
221 case REDGE:
222 case CHANNEL: /* Check how to build bridges, if possible. */
223 if (TotalFunds < 50) {
224 return -2;
225 }
226
227 cost = 50;
228
229 if (x < (WORLD_X - 1)) {
230 Tile = TileAdrPtr[WORLD_Y];
231 NeutralizeRoad(Tile);
232 if ((Tile == VRAILROAD) ||
233 (Tile == HBRIDGE) ||
234 ((Tile >= ROADS) &&
235 (Tile <= HROADPOWER))) {
236 (*TileAdrPtr) = HBRIDGE | BULLBIT;
237 break;
238 }
239 }
240
241 if (x > 0) {
242 Tile = TileAdrPtr[-WORLD_Y];
243 NeutralizeRoad(Tile);
244 if ((Tile == VRAILROAD) ||
245 (Tile == HBRIDGE) ||
246 ((Tile >= ROADS) &&
247 (Tile <= INTERSECTION))) {
248 (*TileAdrPtr) = HBRIDGE | BULLBIT;
249 break;
250 }
251 }
252
253 if (y < (WORLD_Y - 1)) {
254 Tile = TileAdrPtr[1];
255 NeutralizeRoad(Tile);
256 if ((Tile == HRAILROAD) ||
257 (Tile == VROADPOWER) ||
258 ((Tile >= VBRIDGE) &&
259 (Tile <= INTERSECTION))) {
260 (*TileAdrPtr) = VBRIDGE | BULLBIT;
261 break;
262 }
263 }
264
265 if (y > 0) {
266 Tile = TileAdrPtr[-1];
267 NeutralizeRoad(Tile);
268 if ((Tile == HRAILROAD) ||
269 (Tile == VROADPOWER) ||
270 ((Tile >= VBRIDGE) &&
271 (Tile <= INTERSECTION))) {
272 (*TileAdrPtr) = VBRIDGE | BULLBIT;
273 break;
274 }
275 }
276
277 /* Can't do road... */
278 return 0;
279
280 case LHPOWER: /* Road on power */
281 (*TileAdrPtr) = VROADPOWER | CONDBIT | BURNBIT | BULLBIT;
282 break;
283
284 case LVPOWER: /* Road on power #2 */
285 (*TileAdrPtr) = HROADPOWER | CONDBIT | BURNBIT | BULLBIT;
286 break;
287
288 case LHRAIL: /* Road on rail */
289 (*TileAdrPtr) = HRAILROAD | BURNBIT | BULLBIT;
290 break;
291
292 case LVRAIL: /* Road on rail #2 */
293 (*TileAdrPtr) = VRAILROAD | BURNBIT | BULLBIT;
294 break;
295
296 default: /* Can't do road */
297 return 0;
298
299 }
300
301 Spend(cost);
302
303 return 1;
304 }
305
306
307 /* comefrom: ConnecTile */
308 int
309 _LayRail(int x, int y, short *TileAdrPtr)
310 {
311 short Tile;
312 int cost = 20;
313
314 if (TotalFunds < 20) {
315 return -2;
316 }
317
318 Tile = (*TileAdrPtr) & LOMASK;
319 NeutralizeRoad(Tile);
320
321 switch (Tile) {
322 case 0: /* Rail on Dirt */
323 (*TileAdrPtr) = 226 | BULLBIT | BURNBIT;
324 break;
325
326 case 2: /* Rail on Water */
327 case 3:
328 case 4: /* Check how to build underwater tunnel, if possible. */
329 if (TotalFunds < 100) {
330 return -2;
331 }
332 cost = 100;
333
334 if (x < (WORLD_X - 1)) {
335 Tile = TileAdrPtr[WORLD_Y];
336 NeutralizeRoad(Tile);
337 if ((Tile == 221) || (Tile == 224) || ((Tile >= 226) && (Tile <= 237))) {
338 (*TileAdrPtr) = 224 | BULLBIT;
339 break;
340 }
341 }
342
343 if (x > 0) {
344 Tile = TileAdrPtr[-WORLD_Y];
345 NeutralizeRoad(Tile);
346 if ((Tile == 221) || (Tile == 224) || ((Tile > 225) && (Tile < 238))) {
347 (*TileAdrPtr) = 224 | BULLBIT;
348 break;
349 }
350 }
351
352 if (y < (WORLD_Y - 1)) {
353 Tile = TileAdrPtr[1];
354 NeutralizeRoad(Tile);
355 if ((Tile == 222) || (Tile == 238) || ((Tile > 224) && (Tile < 237))) {
356 (*TileAdrPtr) = 225 | BULLBIT;
357 break;
358 }
359 }
360
361 if (y > 0) {
362 Tile = TileAdrPtr[-1];
363 NeutralizeRoad(Tile);
364 if ((Tile == 222) || (Tile == 238) || ((Tile > 224) && (Tile < 237))) {
365 (*TileAdrPtr) = 225 | BULLBIT;
366 break;
367 }
368 }
369
370 /* Can't do rail... */
371 return 0;
372
373 case 210: /* Rail on power */
374 (*TileAdrPtr) = 222 | CONDBIT | BURNBIT | BULLBIT;
375 break;
376
377 case 211: /* Rail on power #2 */
378 (*TileAdrPtr) = 221 | CONDBIT | BURNBIT | BULLBIT;
379 break;
380
381 case 66: /* Rail on road */
382 (*TileAdrPtr) = 238 | BURNBIT | BULLBIT;
383 break;
384
385 case 67: /* Rail on road #2 */
386 (*TileAdrPtr) = 237 | BURNBIT | BULLBIT;
387 break;
388
389 default: /* Can't do rail */
390 return 0;
391 }
392
393 Spend(cost);
394 return 1;
395 }
396
397
398 /* comefrom: ConnecTile */
399 int
400 _LayWire(int x, int y, short *TileAdrPtr)
401 {
402 short Tile;
403 int cost = 5;
404
405 if (TotalFunds < 5) {
406 return -2;
407 }
408
409 Tile = (*TileAdrPtr) & LOMASK;
410 NeutralizeRoad(Tile);
411
412 switch (Tile) {
413 case 0: /* Wire on Dirt */
414 (*TileAdrPtr) = 210 | CONDBIT | BURNBIT | BULLBIT;
415 break;
416
417 case 2: /* Wire on Water */
418 case 3:
419 case 4: /* Check how to lay underwater wire, if possible. */
420 if (TotalFunds < 25)
421 return -2;
422 cost = 25;
423
424 if (x < (WORLD_X - 1)) {
425 Tile = TileAdrPtr[WORLD_Y];
426 if (Tile & CONDBIT) {
427 NeutralizeRoad(Tile);
428 if ((Tile != 77) && (Tile != 221) && (Tile != 208)) {
429 (*TileAdrPtr) = 209 | CONDBIT | BULLBIT;
430 break;
431 }
432 }
433 }
434
435 if (x > 0) {
436 Tile = TileAdrPtr[-WORLD_Y];
437 if (Tile & CONDBIT) {
438 NeutralizeRoad(Tile);
439 if ((Tile != 77) && (Tile != 221) && (Tile != 208)) {
440 (*TileAdrPtr) = 209 | CONDBIT | BULLBIT;
441 break;
442 }
443 }
444 }
445
446 if (y < (WORLD_Y - 1)) {
447 Tile = TileAdrPtr[1];
448 if (Tile & CONDBIT) {
449 NeutralizeRoad(Tile);
450 if ((Tile != 78) && (Tile != 222) && (Tile != 209)) {
451 (*TileAdrPtr) = 208 | CONDBIT | BULLBIT;
452 break;
453 }
454 }
455 }
456
457 if (y > 0) {
458 Tile = TileAdrPtr[-1];
459 if (Tile & CONDBIT) {
460 NeutralizeRoad(Tile);
461 if ((Tile != 78) && (Tile != 222) && (Tile != 209)) {
462 (*TileAdrPtr) = 208 | CONDBIT | BULLBIT;
463 break;
464 }
465 }
466 }
467
468 /* Can't do wire... */
469 return 0;
470
471 case 66: /* Wire on Road */
472 (*TileAdrPtr) = 77 | CONDBIT | BURNBIT | BULLBIT;
473 break;
474
475 case 67: /* Wire on Road #2 */
476 (*TileAdrPtr) = 78 | CONDBIT | BURNBIT | BULLBIT;
477 break;
478
479 case 226: /* Wire on rail */
480 (*TileAdrPtr) = 221 | CONDBIT | BURNBIT | BULLBIT;
481 break;
482
483 case 227: /* Wire on rail #2 */
484 (*TileAdrPtr) = 222 | CONDBIT | BURNBIT | BULLBIT;
485 break;
486
487 default: /* Can't do wire */
488 return 0;
489 }
490
491 Spend(cost);
492 return 1;
493 }
494
495
496 /* comefrom: ConnecTile */
497 _FixZone(int x, int y, short *TileAdrPtr)
498 {
499 _FixSingle(x,y, &TileAdrPtr[0]);
500
501 if (y > 0) {
502 _FixSingle(x, y-1, &TileAdrPtr[-1]);
503 }
504
505 if (x < (WORLD_X - 1)) {
506 _FixSingle(x+1, y, &TileAdrPtr[WORLD_Y]);
507 }
508
509 if (y < (WORLD_Y - 1)) {
510 _FixSingle(x, y+1, &TileAdrPtr[1]);
511 }
512
513 if (x > 0) {
514 _FixSingle(x-1, y, &TileAdrPtr[-WORLD_Y]);
515 }
516
517 }
518
519
520 /* comefrom: _FixZone */
521 _FixSingle(int x, int y, short *TileAdrPtr)
522 {
523 short Tile;
524 short adjTile = 0;
525
526 Tile = (*TileAdrPtr) & LOMASK;
527 NeutralizeRoad(Tile);
528 if ((Tile >= 66) && (Tile <= 76)) { /* Cleanup Road */
529
530 if (y > 0) {
531 Tile = TileAdrPtr[-1];
532 NeutralizeRoad(Tile);
533 if (((Tile == 237) || ((Tile >= 64) && (Tile <= 78))) &&
534 (Tile != 77) && (Tile != 238) && (Tile != 64))
535 adjTile |= 0x0001;
536 }
537
538 if (x < (WORLD_X - 1)) {
539 Tile = TileAdrPtr[WORLD_Y];
540 NeutralizeRoad(Tile);
541 if (((Tile == 238) || ((Tile >= 64) && (Tile <= 78))) &&
542 (Tile != 78) && (Tile != 237) && (Tile != 65))
543 adjTile |= 0x0002;
544 }
545
546 if (y < (WORLD_Y - 1)) {
547 Tile = TileAdrPtr[1];
548 NeutralizeRoad(Tile);
549 if (((Tile == 237) || ((Tile >= 64) && (Tile <= 78))) &&
550 (Tile != 77) && (Tile != 238) && (Tile != 64))
551 adjTile |= 0x0004;
552 }
553
554 if (x > 0) {
555 Tile = TileAdrPtr[-WORLD_Y];
556 NeutralizeRoad(Tile);
557 if (((Tile == 238) || ((Tile >= 64) && (Tile <= 78))) &&
558 (Tile != 78) && (Tile != 237) && (Tile != 65))
559 adjTile |= 0x0008;
560 }
561
562 (*TileAdrPtr) = _RoadTable[adjTile] | BULLBIT | BURNBIT;
563 return;
564 }
565
566 if ((Tile >= 226) && (Tile <= 236)) { /* Cleanup Rail */
567
568 if (y > 0) {
569 Tile = TileAdrPtr[-1];
570 NeutralizeRoad(Tile);
571 if ((Tile >= 221) && (Tile <= 238) &&
572 (Tile != 221) && (Tile != 237) && (Tile != 224))
573 adjTile |= 0x0001;
574 }
575
576 if (x < (WORLD_X - 1)) {
577 Tile = TileAdrPtr[WORLD_Y];
578 NeutralizeRoad(Tile);
579 if ((Tile >= 221) && (Tile <= 238) &&
580 (Tile != 222) && (Tile != 238) && (Tile != 225))
581 adjTile |= 0x0002;
582 }
583
584 if (y < (WORLD_Y - 1)) {
585 Tile = TileAdrPtr[1];
586 NeutralizeRoad(Tile);
587 if ((Tile >= 221) && (Tile <= 238) &&
588 (Tile != 221) && (Tile != 237) && (Tile != 224))
589 adjTile |= 0x0004;
590 }
591
592 if (x > 0) {
593 Tile = TileAdrPtr[-WORLD_Y];
594 NeutralizeRoad(Tile);
595 if ((Tile >= 221) && (Tile <= 238) &&
596 (Tile != 222) && (Tile != 238) && (Tile != 225))
597 adjTile |= 0x0008;
598 }
599
600 (*TileAdrPtr) = _RailTable[adjTile] | BULLBIT | BURNBIT;
601 return;
602 }
603
604 if ((Tile >= 210) && (Tile <= 220)) { /* Cleanup Wire */
605
606 if (y > 0) {
607 Tile = TileAdrPtr[-1];
608 if (Tile & CONDBIT) {
609 NeutralizeRoad(Tile);
610 if ((Tile != 209) && (Tile != 78) && (Tile != 222))
611 adjTile |= 0x0001;
612 }
613 }
614
615 if (x < (WORLD_X - 1)) {
616 Tile = TileAdrPtr[WORLD_Y];
617 if (Tile & CONDBIT) {
618 NeutralizeRoad(Tile);
619 if ((Tile != 208) && (Tile != 77) && (Tile != 221))
620 adjTile |= 0x0002;
621 }
622 }
623
624 if (y < (WORLD_Y - 1)) {
625 Tile = TileAdrPtr[1];
626 if (Tile & CONDBIT) {
627 NeutralizeRoad(Tile);
628 if ((Tile != 209) && (Tile != 78) && (Tile != 222))
629 adjTile |= 0x0004;
630 }
631 }
632
633 if (x > 0) {
634 Tile = TileAdrPtr[-WORLD_Y];
635 if (Tile & CONDBIT) {
636 NeutralizeRoad(Tile);
637 if ((Tile != 208) && (Tile != 77) && (Tile != 221))
638 adjTile |= 0x0008;
639 }
640 }
641
642 (*TileAdrPtr) = _WireTable[adjTile] | BULLBIT | BURNBIT | CONDBIT;
643 return;
644 }
645 }
646
Impressum, Datenschutz