]>
git.zerfleddert.de Git - micropolis/blob - src/sim/w_tool.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
65 short specialBase
= CHURCH
;
93 short toolOffset
[] = {
102 QUAD toolColors
[] = {
103 COLOR_LIGHTGREEN
| (COLOR_LIGHTGREEN
<< 8), /* residentialState */
104 COLOR_LIGHTBLUE
| (COLOR_LIGHTBLUE
<< 8), /* commercialState */
105 COLOR_YELLOW
| (COLOR_YELLOW
<< 8), /* industrialState */
106 COLOR_LIGHTGREEN
| (COLOR_RED
<< 8), /* fireState */
107 COLOR_ORANGE
| (COLOR_ORANGE
<< 8), /* queryState */
108 COLOR_LIGHTGREEN
| (COLOR_LIGHTBLUE
<< 8), /* policeState */
109 COLOR_DARKGRAY
| (COLOR_YELLOW
<< 8), /* wireState */
110 COLOR_LIGHTBROWN
| (COLOR_LIGHTBROWN
<< 8), /* dozeState */
111 COLOR_DARKGRAY
| (COLOR_OLIVE
<< 8), /* rrState */
112 COLOR_DARKGRAY
| (COLOR_WHITE
<< 8), /* roadState */
113 COLOR_LIGHTGRAY
| (COLOR_LIGHTGRAY
<< 8), /* chalkState */
114 COLOR_DARKGRAY
| (COLOR_DARKGRAY
<< 8), /* eraserState */
115 COLOR_LIGHTGRAY
| (COLOR_LIGHTGREEN
<< 8), /* stadiumState */
116 COLOR_LIGHTBROWN
| (COLOR_LIGHTGREEN
<< 8), /* parkState */
117 COLOR_LIGHTGRAY
| (COLOR_LIGHTBLUE
<< 8), /* seaportState */
118 COLOR_LIGHTGRAY
| (COLOR_YELLOW
<< 8), /* powerState */
119 COLOR_LIGHTGRAY
| (COLOR_YELLOW
<< 8), /* nuclearState */
120 COLOR_LIGHTGRAY
| (COLOR_LIGHTBROWN
<< 8), /* airportState */
121 COLOR_LIGHTGRAY
| (COLOR_RED
<< 8), /* networkState */
127 short tally(short tileValue
);
128 int DoSetWandState(SimView
*view
, short state
);
131 /*************************************************************************/
135 setWandState(SimView
*view
, short state
)
139 specialBase
= -state
;
140 state
= specialState
;
144 view
->tool_state
= state
;
146 DoSetWandState(view
, state
);
151 putDownPark(SimView
*view
, short mapH
, short mapV
)
155 if (TotalFunds
- CostOf
[parkState
] >= 0) {
159 tile
= FOUNTAIN
| BURNBIT
| BULLBIT
| ANIMBIT
;
161 tile
= (value
+ WOODS2
) | BURNBIT
| BULLBIT
;
163 if (Map
[mapH
][mapV
] == 0) {
164 Spend(CostOf
[parkState
]);
166 Map
[mapH
][mapV
] = tile
;
176 putDownNetwork(SimView
*view
, short mapH
, short mapV
)
178 int tile
= Map
[mapH
][mapV
] & LOMASK
;
180 if ((TotalFunds
> 0) && tally(tile
)) {
181 Map
[mapH
][mapV
] = tile
= 0;
186 if ((TotalFunds
- CostOf
[view
->tool_state
]) >= 0) {
187 Map
[mapH
][mapV
] = TELEBASE
| CONDBIT
| BURNBIT
| BULLBIT
| ANIMBIT
;
188 Spend(CostOf
[view
->tool_state
]);
200 checkBigZone(short id
, short *deltaHPtr
, short *deltaVPtr
)
203 case POWERPLANT
: /* check coal plant */
204 case PORT
: /* check sea port */
205 case NUCLEAR
: /* check nuc plant */
206 case STADIUM
: /* check stadium */
207 *deltaHPtr
= 0; *deltaVPtr
= 0; return (4);
209 case POWERPLANT
+ 1: /* check coal plant */
210 case COALSMOKE3
: /* check coal plant, smoke */
211 case COALSMOKE3
+ 1: /* check coal plant, smoke */
212 case COALSMOKE3
+ 2: /* check coal plant, smoke */
213 case PORT
+ 1: /* check sea port */
214 case NUCLEAR
+ 1: /* check nuc plant */
215 case STADIUM
+ 1: /* check stadium */
216 *deltaHPtr
= -1; *deltaVPtr
= 0; return (4);
218 case POWERPLANT
+ 4: /* check coal plant */
219 case PORT
+ 4: /* check sea port */
220 case NUCLEAR
+ 4: /* check nuc plant */
221 case STADIUM
+ 4: /* check stadium */
222 *deltaHPtr
= 0; *deltaVPtr
= -1; return (4);
224 case POWERPLANT
+ 5: /* check coal plant */
225 case PORT
+ 5: /* check sea port */
226 case NUCLEAR
+ 5: /* check nuc plant */
227 case STADIUM
+ 5: /* check stadium */
228 *deltaHPtr
= -1; *deltaVPtr
= -1; return (4);
233 *deltaHPtr
= 0; *deltaVPtr
= 0; return (6);
235 *deltaHPtr
= -1; *deltaVPtr
= 0; return (6);
237 *deltaHPtr
= -2; *deltaVPtr
= 0; return (6);
239 *deltaHPtr
= -3; *deltaVPtr
= 0; return (6);
243 *deltaHPtr
= 0; *deltaVPtr
= -1; return (6);
245 *deltaHPtr
= -1; *deltaVPtr
= -1; return (6);
247 *deltaHPtr
= -2; *deltaVPtr
= -1; return (6);
249 *deltaHPtr
= -3; *deltaVPtr
= -1; return (6);
253 *deltaHPtr
= 0; *deltaVPtr
= -2; return (6);
255 *deltaHPtr
= -1; *deltaVPtr
= -2; return (6);
257 *deltaHPtr
= -2; *deltaVPtr
= -2; return (6);
259 *deltaHPtr
= -3; *deltaVPtr
= -2; return (6);
263 *deltaHPtr
= 0; *deltaVPtr
= -3; return (6);
265 *deltaHPtr
= -1; *deltaVPtr
= -3; return (6);
267 *deltaHPtr
= -2; *deltaVPtr
= -3; return (6);
269 *deltaHPtr
= -3; *deltaVPtr
= -3; return (6);
272 *deltaHPtr
= 0; *deltaVPtr
= 0; return (0);
278 tally(short tileValue
)
280 /* can we autobulldoze this tile? */
281 if (((tileValue
>= FIRSTRIVEDGE
) &&
282 (tileValue
<= LASTRUBBLE
)) ||
283 ((tileValue
>= (POWERBASE
+ 2)) &&
284 (tileValue
<= (POWERBASE
+ 12))) ||
285 ((tileValue
>= TINYEXP
) &&
286 (tileValue
<= (LASTTINYEXP
+ 2)))) { /* ??? */
295 checkSize(short temp
)
297 /* check for the normal com, resl, ind 3x3 zones & the fireDept & PoliceDept */
298 if (((temp
>= (RESBASE
- 1)) && (temp
<= (PORTBASE
- 1))) ||
299 ((temp
>= (LASTPOWERPLANT
+ 1)) && (temp
<= (POLICESTATION
+ 4)))) {
301 } else if (((temp
>= PORTBASE
) && (temp
<= LASTPORT
)) ||
302 ((temp
>= COALBASE
) && (temp
<= LASTPOWERPLANT
)) ||
303 ((temp
>= STADIUMBASE
) && (temp
<= LASTZONE
))) {
314 check3x3border(short xMap
, short yMap
)
319 xPos
= xMap
; yPos
= yMap
- 1;
320 for (cnt
= 0; cnt
< 3; cnt
++) {
321 /*** this will do the upper bordering row ***/
322 ConnecTile(xPos
, yPos
, &Map
[xPos
][yPos
], 0);
326 xPos
= xMap
- 1; yPos
= yMap
;
327 for (cnt
= 0; cnt
< 3; cnt
++) {
328 /*** this will do the left bordering row ***/
329 ConnecTile(xPos
, yPos
, &Map
[xPos
][yPos
], 0);
333 xPos
= xMap
; yPos
= yMap
+ 3;
334 for (cnt
= 0; cnt
< 3; cnt
++) {
335 /*** this will do the bottom bordering row ***/
336 ConnecTile(xPos
, yPos
, &Map
[xPos
][yPos
], 0);
340 xPos
= xMap
+ 3; yPos
= yMap
;
341 for (cnt
= 0; cnt
< 3; cnt
++) {
342 /*** this will do the right bordering row ***/
343 ConnecTile(xPos
, yPos
, &Map
[xPos
][yPos
], 0);
350 check3x3(SimView
*view
, short mapH
, short mapV
, short base
, short tool
)
352 register short rowNum
, columnNum
;
353 register short holdMapH
, holdMapV
;
360 if ((mapH
< 0) || (mapH
> (WORLD_X
- 3)) ||
361 (mapV
< 0) || (mapV
> (WORLD_Y
- 3))) {
365 xPos
= holdMapH
= mapH
;
366 yPos
= holdMapV
= mapV
;
370 for (rowNum
= 0; rowNum
<= 2; rowNum
++) {
373 for (columnNum
= 0; columnNum
<= 2; columnNum
++) {
374 tileValue
= Map
[mapH
++][mapV
] & LOMASK
;
377 /* if autoDoze is enabled, add up the cost of bulldozed tiles */
378 if (tileValue
!= 0) {
379 if (tally(tileValue
)) {
386 /* check and see if the tile is clear or not */
387 if (tileValue
!= 0) {
399 cost
+= CostOf
[tool
];
401 if ((TotalFunds
- cost
) < 0) {
407 (cost
>= Expensive
) &&
409 (view
->super_user
== 0)) {
413 /* take care of the money situtation here */
419 for (rowNum
= 0; rowNum
<= 2; rowNum
++) {
422 for (columnNum
= 0; columnNum
<= 2; columnNum
++) {
423 if (columnNum
== 1 && rowNum
== 1) {
424 Map
[mapH
++][mapV
] = base
+ BNCNBIT
+ ZONEBIT
;
426 Map
[mapH
++][mapV
] = base
+ BNCNBIT
;
432 check3x3border(xPos
, yPos
);
441 check4x4border(short xMap
, short yMap
)
447 xPos
= xMap
; yPos
= yMap
- 1;
448 for (cnt
= 0; cnt
< 4; cnt
++) {
449 /* this will do the upper bordering row */
450 tilePtr
= (Ptr
) &Map
[xPos
][yPos
];
451 ConnecTile(xPos
, yPos
, tilePtr
, 0);
455 xPos
= xMap
- 1; yPos
= yMap
;
456 for (cnt
= 0; cnt
< 4; cnt
++) {
457 /* this will do the left bordering row */
458 tilePtr
= (Ptr
) &Map
[xPos
][yPos
];
459 ConnecTile(xPos
, yPos
, tilePtr
, 0);
463 xPos
= xMap
; yPos
= yMap
+ 4;
464 for (cnt
= 0; cnt
< 4;cnt
++) {
465 /* this will do the bottom bordering row */
466 tilePtr
= (Ptr
) &Map
[xPos
][yPos
];
467 ConnecTile(xPos
, yPos
, tilePtr
, 0);
471 xPos
= xMap
+ 4; yPos
= yMap
;
472 for (cnt
= 0; cnt
< 4; cnt
++) {
473 /* this will do the right bordering row */
474 tilePtr
= (Ptr
) &Map
[xPos
][yPos
];
475 ConnecTile(xPos
, yPos
, tilePtr
, 0);
482 check4x4(SimView
*view
, short mapH
, short mapV
,
483 short base
, short aniFlag
, short tool
)
485 register short rowNum
, columnNum
;
494 if ((mapH
< 0) || (mapH
> (WORLD_X
- 4)) ||
495 (mapV
< 0) || (mapV
> (WORLD_Y
- 4))) {
499 h
= xMap
= holdMapH
= mapH
;
504 for (rowNum
= 0; rowNum
<= 3; rowNum
++) {
507 for (columnNum
= 0; columnNum
<= 3; columnNum
++) {
508 tileValue
= Map
[mapH
++][mapV
] & LOMASK
;
511 /* if autoDoze is enabled, add up the cost of bulldozed tiles */
512 if (tileValue
!= 0) {
513 if (tally(tileValue
)) {
520 /* check and see if the tile is clear or not */
521 if (tileValue
!= 0) {
533 cost
+= CostOf
[tool
];
535 if ((TotalFunds
- cost
) < 0) {
541 (cost
>= Expensive
) &&
543 (view
->super_user
== 0)) {
547 /* take care of the money situtation here */
551 mapV
= v
; holdMapH
= h
;
553 for (rowNum
= 0; rowNum
<= 3; rowNum
++) {
556 for (columnNum
= 0; columnNum
<= 3; columnNum
++) {
557 if (columnNum
== 1 && rowNum
== 1)
558 Map
[mapH
++][mapV
] = base
+ BNCNBIT
+ ZONEBIT
;
559 else if (columnNum
== 1 && rowNum
== 2 && aniFlag
)
560 Map
[mapH
++][mapV
] = base
+ BNCNBIT
+ ANIMBIT
;
562 Map
[mapH
++][mapV
] = base
+ BNCNBIT
;
567 check4x4border(xMap
, yMap
);
576 check6x6border(short xMap
, short yMap
)
581 xPos
= xMap
; yPos
= yMap
- 1;
582 for (cnt
= 0; cnt
< 6; cnt
++) {
583 /* this will do the upper bordering row */
584 ConnecTile(xPos
, yPos
, &Map
[xPos
][yPos
], 0);
588 xPos
= xMap
- 1; yPos
= yMap
;
589 for (cnt
=0; cnt
< 6; cnt
++) {
590 /* this will do the left bordering row */
591 ConnecTile(xPos
, yPos
, &Map
[xPos
][yPos
], 0);
595 xPos
= xMap
; yPos
= yMap
+ 6;
596 for (cnt
= 0; cnt
< 6; cnt
++) {
597 /* this will do the bottom bordering row */
598 ConnecTile(xPos
, yPos
, &Map
[xPos
][yPos
], 0);
602 xPos
= xMap
+ 6; yPos
= yMap
;
603 for (cnt
= 0; cnt
< 6; cnt
++) {
604 /* this will do the right bordering row */
605 ConnecTile(xPos
, yPos
, &Map
[xPos
][yPos
], 0);
612 check6x6(SimView
*view
, short mapH
, short mapV
, short base
, short tool
)
614 register short rowNum
, columnNum
;
623 if ((mapH
< 0) || (mapH
> (WORLD_X
- 6)) ||
624 (mapV
< 0) || (mapV
> (WORLD_Y
- 6)))
627 h
= xMap
= holdMapH
= mapH
;
632 for (rowNum
= 0; rowNum
<= 5; rowNum
++) {
635 for (columnNum
= 0; columnNum
<= 5; columnNum
++) {
636 tileValue
= Map
[mapH
++][mapV
] & LOMASK
;
639 /* if autoDoze is enabled, add up the cost of bulldozed tiles */
641 if (tally(tileValue
)) {
647 /* check and see if the tile is clear or not */
648 if (tileValue
!= 0) {
660 cost
+= CostOf
[tool
];
662 if ((TotalFunds
- cost
) < 0) {
668 (cost
>= Expensive
) &&
670 (view
->super_user
== 0)) {
674 /* take care of the money situtation here */
678 mapV
= v
; holdMapH
= h
;
680 for (rowNum
= 0; rowNum
<= 5; rowNum
++) {
683 for (columnNum
= 0; columnNum
<= 5; columnNum
++) {
684 if (columnNum
== 1 && rowNum
== 1) {
685 Map
[mapH
++][mapV
] = base
+ BNCNBIT
+ ZONEBIT
;
687 Map
[mapH
++][mapV
] = base
+ BNCNBIT
;
693 check6x6border(xMap
, yMap
);
701 /* search table for zone status string match */
702 static short idArray
[28] = {
703 DIRT
, RIVER
, TREEBASE
, RUBBLE
,
704 FLOOD
, RADTILE
, FIRE
, ROADBASE
,
705 POWERBASE
, RAILBASE
, RESBASE
, COMBASE
,
706 INDBASE
, PORTBASE
, AIRPORTBASE
, COALBASE
,
707 FIRESTBASE
, POLICESTBASE
, STADIUMBASE
, NUCLEARBASE
,
708 827, 832, FOUNTAIN
, INDBASE2
,
709 FOOTBALLGAME1
, VBRDG0
, 952, 956
721 Clear, Water, Trees, Rubble,
722 Flood, Radioactive Waste, Fire, Road,
723 Power, Rail, Residential, Commercial,
724 Industrial, Port, AirPort, Coal Power,
725 Fire Department, Police Department, Stadium, Nuclear Power,
726 Draw Bridge, Radar Dish, Fountain, Industrial,
727 49er's 38 Bears 3, Draw Bridge, Ur 238
731 int getDensityStr(short catNo
, short mapH
, short mapV
)
737 z
= PopDensity
[mapH
>>1][mapV
>>1];
742 z
= LandValueMem
[mapH
>>1][mapV
>>1];
743 if (z
< 30) return (4);
744 if (z
< 80) return (5);
745 if (z
< 150) return (6);
748 z
= CrimeMem
[mapH
>>1][mapV
>>1];
753 z
= PollutionMem
[mapH
>>1][mapV
>>1];
754 if ((z
< 64) && (z
> 0)) return (13);
759 z
= RateOGMem
[mapH
>>3][mapV
>>3];
760 if (z
< 0) return (16);
761 if (z
== 0) return (17);
762 if (z
> 100) return (19);
768 doZoneStatus(short mapH
, short mapV
)
771 char statusStr
[5][256];
777 tileNum
= Map
[mapH
][mapV
] & LOMASK
;
779 if (tileNum
>= COALSMOKE1
&& tileNum
< FOOTBALLGAME1
)
783 for (x
= 1; x
< 29 && found
; x
++) {
784 if (tileNum
< idArray
[x
]) {
793 GetIndString(localStr
, 219, x
);
795 for (x
= 0; x
< 5; x
++) {
796 id
= getDensityStr(x
, mapH
, mapV
);
799 if (id
> 20) id
= 20;
800 GetIndString(statusStr
[x
], 202, id
);
803 DoShowZoneStatus(localStr
, statusStr
[0], statusStr
[1],
804 statusStr
[2], statusStr
[3], statusStr
[4], mapH
, mapV
);
808 DoShowZoneStatus(char *str
, char *s0
, char *s1
, char *s2
, char *s3
, char *s4
,
813 sprintf(buf
, "UIShowZoneStatus {%s} {%s} {%s} {%s} {%s} {%s} %d %d",
814 str
, s0
, s1
, s2
, s3
, s4
, x
, y
);
819 /* comefrom: processWand */
820 put3x3Rubble(short x
, short y
)
824 for (xx
= x
- 1; xx
< x
+ 2; xx
++) {
825 for (yy
= y
- 1; yy
< y
+ 2; yy
++) {
826 if (TestBounds(xx
, yy
)) {
827 zz
= Map
[xx
][yy
] & LOMASK
;
828 if ((zz
!= RADTILE
) && (zz
!= 0)) {
831 ? (TINYEXP
+ Rand(2))
841 /* comefrom: processWand */
842 put4x4Rubble(short x
, short y
)
846 for (xx
= x
- 1; xx
< x
+ 3; xx
++) {
847 for (yy
= y
- 1; yy
< y
+ 3; yy
++) {
848 if (TestBounds(xx
, yy
)) {
849 zz
= Map
[xx
][yy
] & LOMASK
;
850 if ((zz
!= RADTILE
) && (zz
!= 0)) {
853 ? (TINYEXP
+ Rand(2))
863 /* comefrom: processWand */
864 put6x6Rubble(short x
, short y
)
868 for (xx
= x
- 1; xx
< x
+ 5; xx
++) {
869 for (yy
= y
- 1; yy
< y
+ 5; yy
++) {
870 if (TestBounds(xx
, yy
)) {
871 zz
= Map
[xx
][yy
] & LOMASK
;
872 if ((zz
!= RADTILE
) && (zz
!= 0)) {
875 ? (TINYEXP
+ Rand(2))
885 DidTool(SimView
*view
, char *name
, short x
, short y
)
890 sprintf(buf
, "UIDidTool%s %s %d %d",
891 name
, Tk_PathName(view
->tkwin
), x
, y
);
897 DoSetWandState(SimView
*view
, short state
)
901 sprintf(buf
, "UISetToolState %s %d", Tk_PathName(view
->tkwin
), state
);
906 /************************************************************************/
911 query_tool(SimView
*view
, short x
, short y
)
913 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
914 (y
< 0) || (y
> (WORLD_Y
- 1))) {
919 DidTool(view
, "Qry", x
, y
);
925 bulldozer_tool(SimView
*view
, short x
, short y
)
927 unsigned short currTile
, temp
;
928 short zoneSize
, deltaH
, deltaV
;
931 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
932 (y
< 0) || (y
> (WORLD_Y
- 1))) {
936 currTile
= Map
[x
][y
];
937 temp
= currTile
& LOMASK
;
939 if (currTile
& ZONEBIT
) { /* zone center bit is set */
940 if (TotalFunds
> 0) {
942 switch (checkSize(temp
)) {
944 MakeSound("city", "Explosion-High");
950 MakeSound("city", "Explosion-Low");
954 MakeSound("city", "Explosion-High");
955 MakeSound("city", "Explosion-Low");
963 } else if ((zoneSize
= checkBigZone(temp
, &deltaH
, &deltaV
))) {
964 if (TotalFunds
> 0) {
968 MakeSound("city", "Explosion-High");
972 MakeSound("city", "Explosion-Low");
973 put4x4Rubble(x
+ deltaH
, y
+ deltaV
);
977 MakeSound("city", "Explosion-High");
978 MakeSound("city", "Explosion-Low");
979 put6x6Rubble(x
+ deltaH
, y
+ deltaV
);
984 if (temp
== RIVER
|| temp
== REDGE
|| temp
== CHANNEL
) {
985 if (TotalFunds
>= 6) {
986 result
= ConnecTile(x
, y
, &Map
[x
][y
], 1);
987 if (temp
!= (Map
[x
][y
] & LOMASK
)) {
994 result
= ConnecTile(x
, y
, &Map
[x
][y
], 1);
999 DidTool(view
, "Dozr", x
, y
);
1006 road_tool(SimView
*view
, short x
, short y
)
1010 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1011 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1015 result
= ConnecTile(x
, y
, &Map
[x
][y
], 2);
1018 DidTool(view
, "Road", x
, y
);
1025 rail_tool(SimView
*view
, short x
, short y
)
1029 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1030 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1034 result
= ConnecTile(x
, y
, &Map
[x
][y
], 3);
1037 DidTool(view
, "Rail", x
, y
);
1044 wire_tool(SimView
*view
, short x
, short y
)
1048 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1049 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1053 result
= ConnecTile(x
, y
, &Map
[x
][y
], 4);
1056 DidTool(view
, "Wire", x
, y
);
1063 park_tool(SimView
*view
, short x
, short y
)
1067 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1068 (y
< 0) || (y
> (WORLD_Y
- 1)))
1071 result
= putDownPark(view
, x
, y
);
1073 DidTool(view
, "Park", x
, y
);
1080 residential_tool(SimView
*view
, short x
, short y
)
1084 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1085 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1089 result
= check3x3(view
, x
, y
, RESBASE
, residentialState
);
1091 DidTool(view
, "Res", x
, y
);
1098 commercial_tool(SimView
*view
, short x
, short y
)
1102 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1103 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1107 result
= check3x3(view
, x
, y
, COMBASE
, commercialState
);
1109 DidTool(view
, "Com", x
, y
);
1116 industrial_tool(SimView
*view
, short x
, short y
)
1120 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1121 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1125 result
= check3x3(view
, x
, y
, INDBASE
, industrialState
);
1127 DidTool(view
, "Ind", x
, y
);
1134 police_dept_tool(SimView
*view
, short x
, short y
)
1138 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1139 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1143 result
= check3x3(view
, x
, y
, POLICESTBASE
, policeState
);
1145 DidTool(view
, "Pol", x
, y
);
1152 fire_dept_tool(SimView
*view
, short x
, short y
)
1156 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1157 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1161 result
= check3x3(view
, x
, y
, FIRESTBASE
, fireState
);
1163 DidTool(view
, "Fire", x
, y
);
1170 stadium_tool(SimView
*view
, short x
, short y
)
1174 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1175 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1179 result
= check4x4(view
, x
, y
, STADIUMBASE
, 0, stadiumState
);
1181 DidTool(view
, "Stad", x
, y
);
1188 coal_power_plant_tool(SimView
*view
, short x
, short y
)
1192 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1193 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1197 result
= check4x4(view
, x
, y
, COALBASE
, 1, powerState
);
1199 DidTool(view
, "Coal", x
, y
);
1206 nuclear_power_plant_tool(SimView
*view
, short x
, short y
)
1210 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1211 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1215 result
= check4x4(view
, x
, y
, NUCLEARBASE
, 1, nuclearState
);
1217 DidTool(view
, "Nuc", x
, y
);
1224 seaport_tool(SimView
*view
, short x
, short y
)
1228 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1229 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1233 result
= check4x4(view
, x
, y
, PORTBASE
, 0, seaportState
);
1235 DidTool(view
, "Seap", x
, y
);
1242 airport_tool(SimView
*view
, short x
, short y
)
1246 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1247 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1251 result
= check6x6(view
, x
, y
, AIRPORTBASE
, airportState
);
1253 DidTool(view
, "Airp", x
, y
);
1260 network_tool(SimView
*view
, short x
, short y
)
1264 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1265 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1269 result
= putDownNetwork(view
, x
, y
);
1271 DidTool(view
, "Net", x
, y
);
1279 special_tool(SimView
*view
, short x
, short y
)
1283 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1284 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1288 result
= check3x3(view
, x
, y
, specialBase
, specialState
);
1290 DidTool(view
, "Special", x
, y
);
1297 ChalkTool(SimView
*view
, short x
, short y
, short color
, short first
)
1300 ChalkStart(view
, x
, y
, color
);
1302 ChalkTo(view
, x
, y
);
1304 DidTool(view
, "Chlk", x
, y
);
1309 ChalkStart(SimView
*view
, int x
, int y
, int color
)
1314 for (ip
= &sim
->overlay
; *ip
!= NULL
; ip
= &((*ip
)->next
)) ;
1316 *ip
= ink
= NewInk();
1317 ink
->x
= x
; ink
->y
= y
;
1319 StartInk(ink
, x
, y
);
1320 view
->track_info
= (char *)ink
;
1323 view
->tool_event_time
= view
->tool_last_event_time
=
1324 ((TkWindow
*)view
->tkwin
)->dispPtr
->lastEventTime
;
1328 ChalkTo(SimView
*view
, int x
, int y
)
1331 Ink
*ink
= (Ink
*)view
->track_info
;
1334 if (view
->x
->dpy
->motion_buffer
) {
1335 XTimeCoord
*coords
= NULL
, *coord
;
1338 view
->tool_last_event_time
= view
->tool_event_time
;
1339 view
->tool_event_time
=
1340 ((TkWindow
*)view
->tkwin
)->dispPtr
->lastEventTime
;
1342 coords
= XGetMotionEvents(view
->x
->dpy
,
1343 Tk_WindowId(view
->tkwin
),
1344 view
->tool_last_event_time
,
1345 view
->tool_event_time
,
1348 printf("got %d events at %x from %d to %d (%d elapsed)\n",
1350 view
->tool_last_event_time
, view
->tool_event_time
,
1351 view
->tool_event_time
- view
->tool_last_event_time
);
1354 lx
= ink
->last_x
; ly
= ink
->last_y
;
1356 for (i
= 0, coord
= coords
; i
< n
; i
++, coord
++) {
1357 ViewToPixelCoords(view
, coord
->x
, coord
->y
, &x0
, &y0
);
1358 lx
= (lx
+ lx
+ lx
+ x0
) >>2;
1359 ly
= (ly
+ ly
+ ly
+ y0
) >>2;
1361 printf("adding %d %d => %d %d => %d %d\n",
1362 coord
->x
, coord
->y
, x0
, y0
, lx
, ly
);
1364 AddInk(ink
, lx
, ly
);
1369 XFree((char *)coords
);
1381 EraserTool(SimView
*view
, short x
, short y
, short first
)
1384 EraserStart(view
, x
, y
);
1386 EraserTo(view
, x
, y
);
1388 DidTool(view
, "Eraser", x
, y
);
1393 InkInBox(Ink
*ink
, int left
, int top
, int right
, int bottom
)
1395 if ((left
<= ink
->right
) &&
1396 (right
>= ink
->left
) &&
1397 (top
<= ink
->bottom
) &&
1398 (bottom
>= ink
->top
)) {
1399 int x
, y
, lx
, ly
, i
;
1401 if (ink
->length
== 1) {
1405 x
= ink
->x
; y
= ink
->y
;
1406 for (i
= 1; i
< ink
->length
; i
++) {
1407 int ileft
, iright
, itop
, ibottom
;
1410 x
+= ink
->points
[i
].x
; y
+= ink
->points
[i
].y
;
1411 if (x
< lx
) { ileft
= x
; iright
= lx
; }
1412 else { ileft
= lx
; iright
= x
; }
1413 if (y
< ly
) { itop
= y
; ibottom
= ly
; }
1414 else { itop
= ly
; ibottom
= y
; }
1415 if ((left
<= iright
) &&
1427 EraserStart(SimView
*view
, int x
, int y
)
1429 EraserTo(view
, x
, y
);
1433 EraserTo(SimView
*view
, int x
, int y
)
1438 for (ip
= &sim
->overlay
; *ip
!= NULL
;) {
1440 if (InkInBox(ink
, x
- 8, y
- 8, x
+ 8, y
+ 8)) {
1442 for (view
= sim
->editor
; view
!= NULL
; view
= view
->next
) {
1445 if ((ink
->right
>= (vleft
= (view
->pan_x
- (view
->w_width
/ 2)))) &&
1446 (ink
->left
<= (vleft
+ view
->w_width
)) &&
1447 (ink
->bottom
>= (vtop
= (view
->pan_y
- (view
->w_height
/ 2)))) &&
1448 (ink
->top
<= (vtop
+ view
->w_height
))) {
1449 view
->overlay_mode
= 0;
1450 EventuallyRedrawView(view
);
1458 ip
= &((*ip
)->next
);
1465 do_tool(SimView
*view
, short state
, short x
, short y
, short first
)
1470 case residentialState
:
1471 result
= residential_tool(view
, x
>>4, y
>>4);
1473 case commercialState
:
1474 result
= commercial_tool(view
, x
>>4, y
>>4);
1476 case industrialState
:
1477 result
= industrial_tool(view
, x
>>4, y
>>4);
1480 result
= fire_dept_tool(view
, x
>>4, y
>>4);
1483 result
= query_tool(view
, x
>>4, y
>>4);
1486 result
= police_dept_tool(view
, x
>>4, y
>>4);
1489 result
= wire_tool(view
, x
>>4, y
>>4);
1492 result
= bulldozer_tool(view
, x
>>4, y
>>4);
1495 result
= rail_tool(view
, x
>>4, y
>>4);
1498 result
= road_tool(view
, x
>>4, y
>>4);
1501 result
= ChalkTool(view
, x
- 5, y
+ 11, COLOR_WHITE
, first
);
1504 result
= EraserTool(view
, x
, y
, first
);
1507 result
= stadium_tool(view
, x
>>4, y
>>4);
1510 result
= park_tool(view
, x
>>4, y
>>4);
1513 result
= seaport_tool(view
, x
>>4, y
>>4);
1516 result
= coal_power_plant_tool(view
, x
>>4, y
>>4);
1519 result
= nuclear_power_plant_tool(view
, x
>>4, y
>>4);
1522 result
= airport_tool(view
, x
>>4, y
>>4);
1525 result
= network_tool(view
, x
>>4, y
>>4);
1538 current_tool(SimView
*view
, short x
, short y
, short first
)
1540 return do_tool(view
, view
->tool_state
, x
, y
, first
);
1544 DoTool(SimView
*view
, short tool
, short x
, short y
)
1548 result
= do_tool(view
, tool
, x
<<4, y
<<4, 1);
1553 MakeSoundOn(view
, "edit", "UhUh");
1554 } else if (result
== -2) {
1557 MakeSoundOn(view
, "edit", "Sorry");
1562 InvalidateEditors();
1566 ToolDown(SimView
*view
, int x
, int y
)
1570 ViewToPixelCoords(view
, x
, y
, &x
, &y
);
1574 result
= current_tool(view
, x
, y
, 1);
1579 MakeSoundOn(view
, "edit", "UhUh");
1580 } else if (result
== -2) {
1583 MakeSoundOn(view
, "edit", "Sorry");
1584 } else if (result
== -3) {
1585 DoPendTool(view
, view
->tool_state
, x
>>4, y
>>4);
1594 ToolUp(SimView
*view
, int x
, int y
)
1598 result
= ToolDrag(view
, x
, y
);
1604 ToolDrag(SimView
*view
, int px
, int py
)
1606 int x
, y
, dx
, dy
, adx
, ady
, lx
, ly
, dist
;
1607 float i
, step
, tx
, ty
, dtx
, dty
, rx
, ry
;
1609 ViewToPixelCoords(view
, px
, py
, &x
, &y
);
1610 view
->tool_x
= x
; view
->tool_y
= y
;
1612 if ((view
->tool_state
== chalkState
) ||
1613 (view
->tool_state
== eraserState
)) {
1615 current_tool(view
, x
, y
, 0);
1616 view
->last_x
= x
; view
->last_y
= y
;
1620 dist
= toolSize
[view
->tool_state
];
1623 lx
= view
->last_x
>> 4;
1624 ly
= view
->last_y
>> 4;
1631 if (dx
== 0 && dy
== 0) {
1635 adx
= ABS(dx
); ady
= ABS(dy
);
1643 rx
= (dx
< 0 ? 1 : 0);
1644 ry
= (dy
< 0 ? 1 : 0);
1647 for (i
= 0.0; i
<= 1 + step
; i
+= step
) {
1648 tx
= (view
->last_x
>>4) + i
* dx
;
1649 ty
= (view
->last_y
>>4) + i
* dy
;
1652 if (dtx
>= 1 || dty
>= 1) {
1653 /* fill in corners */
1654 if ((dtx
>= 1) && (dty
>= 1)) {
1656 current_tool(view
, ((int)(tx
+ rx
)) <<4, ly
<<4, 0);
1658 current_tool(view
, lx
<<4, ((int)(ty
+ ry
)) <<4, 0);
1661 lx
= (int)(tx
+ rx
);
1662 ly
= (int)(ty
+ ry
);
1663 current_tool(view
, lx
<<4, ly
<<4, 0);
1667 for (i
= 0.0; i
<= 1 + step
; i
+= step
) {
1668 tx
= (view
->last_x
>>4) + i
* dx
;
1669 ty
= (view
->last_y
>>4) + i
* dy
;
1672 lx
= (int)(tx
+ rx
);
1673 ly
= (int)(ty
+ ry
);
1674 current_tool(view
, lx
<<4, ly
<<4, 0);
1678 view
->last_x
= (lx
<<4) + 8;
1679 view
->last_y
= (ly
<<4) + 8;
1681 sim_skip
= 0; /* update editors overlapping this one */
1687 DoPendTool(SimView
*view
, int tool
, int x
, int y
)
1691 sprintf(buf
, "DoPendTool %s %d %d %d",
1692 Tk_PathName(view
->tkwin
), tool
, x
, y
);