]>
git.zerfleddert.de Git - micropolis/blob - src/sim/w_tool.c
1143b06f94d1be81ab342dc34c2229c6e69b005a
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 void DoSetWandState(SimView
*view
, short state
);
128 void DoPendTool(SimView
*view
, int tool
, int x
, int y
);
129 void EraserTo(SimView
*view
, int x
, int y
);
130 void EraserStart(SimView
*view
, int x
, int y
);
131 void DoShowZoneStatus(char *str
, char *s0
, char *s1
, char *s2
, char *s3
, char *s4
, int x
, int y
);
134 /*************************************************************************/
139 setWandState(SimView
*view
, short state
)
143 specialBase
= -state
;
144 state
= specialState
;
148 view
->tool_state
= state
;
150 DoSetWandState(view
, state
);
155 putDownPark(SimView
*view
, short mapH
, short mapV
)
159 if (TotalFunds
- CostOf
[parkState
] >= 0) {
163 tile
= FOUNTAIN
| BURNBIT
| BULLBIT
| ANIMBIT
;
165 tile
= (value
+ WOODS2
) | BURNBIT
| BULLBIT
;
167 if (Map
[mapH
][mapV
] == 0) {
168 Spend(CostOf
[parkState
]);
170 Map
[mapH
][mapV
] = tile
;
180 putDownNetwork(SimView
*view
, short mapH
, short mapV
)
182 int tile
= Map
[mapH
][mapV
] & LOMASK
;
184 if ((TotalFunds
> 0) && tally(tile
)) {
185 Map
[mapH
][mapV
] = tile
= 0;
190 if ((TotalFunds
- CostOf
[view
->tool_state
]) >= 0) {
191 Map
[mapH
][mapV
] = TELEBASE
| CONDBIT
| BURNBIT
| BULLBIT
| ANIMBIT
;
192 Spend(CostOf
[view
->tool_state
]);
204 checkBigZone(short id
, short *deltaHPtr
, short *deltaVPtr
)
207 case POWERPLANT
: /* check coal plant */
208 case PORT
: /* check sea port */
209 case NUCLEAR
: /* check nuc plant */
210 case STADIUM
: /* check stadium */
211 *deltaHPtr
= 0; *deltaVPtr
= 0; return (4);
213 case POWERPLANT
+ 1: /* check coal plant */
214 case COALSMOKE3
: /* check coal plant, smoke */
215 case COALSMOKE3
+ 1: /* check coal plant, smoke */
216 case COALSMOKE3
+ 2: /* check coal plant, smoke */
217 case PORT
+ 1: /* check sea port */
218 case NUCLEAR
+ 1: /* check nuc plant */
219 case STADIUM
+ 1: /* check stadium */
220 *deltaHPtr
= -1; *deltaVPtr
= 0; return (4);
222 case POWERPLANT
+ 4: /* check coal plant */
223 case PORT
+ 4: /* check sea port */
224 case NUCLEAR
+ 4: /* check nuc plant */
225 case STADIUM
+ 4: /* check stadium */
226 *deltaHPtr
= 0; *deltaVPtr
= -1; return (4);
228 case POWERPLANT
+ 5: /* check coal plant */
229 case PORT
+ 5: /* check sea port */
230 case NUCLEAR
+ 5: /* check nuc plant */
231 case STADIUM
+ 5: /* check stadium */
232 *deltaHPtr
= -1; *deltaVPtr
= -1; return (4);
237 *deltaHPtr
= 0; *deltaVPtr
= 0; return (6);
239 *deltaHPtr
= -1; *deltaVPtr
= 0; return (6);
241 *deltaHPtr
= -2; *deltaVPtr
= 0; return (6);
243 *deltaHPtr
= -3; *deltaVPtr
= 0; return (6);
247 *deltaHPtr
= 0; *deltaVPtr
= -1; return (6);
249 *deltaHPtr
= -1; *deltaVPtr
= -1; return (6);
251 *deltaHPtr
= -2; *deltaVPtr
= -1; return (6);
253 *deltaHPtr
= -3; *deltaVPtr
= -1; return (6);
257 *deltaHPtr
= 0; *deltaVPtr
= -2; return (6);
259 *deltaHPtr
= -1; *deltaVPtr
= -2; return (6);
261 *deltaHPtr
= -2; *deltaVPtr
= -2; return (6);
263 *deltaHPtr
= -3; *deltaVPtr
= -2; return (6);
267 *deltaHPtr
= 0; *deltaVPtr
= -3; return (6);
269 *deltaHPtr
= -1; *deltaVPtr
= -3; return (6);
271 *deltaHPtr
= -2; *deltaVPtr
= -3; return (6);
273 *deltaHPtr
= -3; *deltaVPtr
= -3; return (6);
276 *deltaHPtr
= 0; *deltaVPtr
= 0; return (0);
282 tally(short tileValue
)
284 /* can we autobulldoze this tile? */
285 if (((tileValue
>= FIRSTRIVEDGE
) &&
286 (tileValue
<= LASTRUBBLE
)) ||
287 ((tileValue
>= (POWERBASE
+ 2)) &&
288 (tileValue
<= (POWERBASE
+ 12))) ||
289 ((tileValue
>= TINYEXP
) &&
290 (tileValue
<= (LASTTINYEXP
+ 2)))) { /* ??? */
299 checkSize(short temp
)
301 /* check for the normal com, resl, ind 3x3 zones & the fireDept & PoliceDept */
302 if (((temp
>= (RESBASE
- 1)) && (temp
<= (PORTBASE
- 1))) ||
303 ((temp
>= (LASTPOWERPLANT
+ 1)) && (temp
<= (POLICESTATION
+ 4)))) {
305 } else if (((temp
>= PORTBASE
) && (temp
<= LASTPORT
)) ||
306 ((temp
>= COALBASE
) && (temp
<= LASTPOWERPLANT
)) ||
307 ((temp
>= STADIUMBASE
) && (temp
<= LASTZONE
))) {
318 check3x3border(short xMap
, short yMap
)
323 xPos
= xMap
; yPos
= yMap
- 1;
324 for (cnt
= 0; cnt
< 3; cnt
++) {
325 /*** this will do the upper bordering row ***/
326 ConnecTile(xPos
, yPos
, &Map
[xPos
][yPos
], 0);
330 xPos
= xMap
- 1; yPos
= yMap
;
331 for (cnt
= 0; cnt
< 3; cnt
++) {
332 /*** this will do the left bordering row ***/
333 ConnecTile(xPos
, yPos
, &Map
[xPos
][yPos
], 0);
337 xPos
= xMap
; yPos
= yMap
+ 3;
338 for (cnt
= 0; cnt
< 3; cnt
++) {
339 /*** this will do the bottom bordering row ***/
340 ConnecTile(xPos
, yPos
, &Map
[xPos
][yPos
], 0);
344 xPos
= xMap
+ 3; yPos
= yMap
;
345 for (cnt
= 0; cnt
< 3; cnt
++) {
346 /*** this will do the right bordering row ***/
347 ConnecTile(xPos
, yPos
, &Map
[xPos
][yPos
], 0);
354 check3x3(SimView
*view
, short mapH
, short mapV
, short base
, short tool
)
356 register short rowNum
, columnNum
;
357 register short holdMapH
, holdMapV
;
364 if ((mapH
< 0) || (mapH
> (WORLD_X
- 3)) ||
365 (mapV
< 0) || (mapV
> (WORLD_Y
- 3))) {
369 xPos
= holdMapH
= mapH
;
370 yPos
= holdMapV
= mapV
;
374 for (rowNum
= 0; rowNum
<= 2; rowNum
++) {
377 for (columnNum
= 0; columnNum
<= 2; columnNum
++) {
378 tileValue
= Map
[mapH
++][mapV
] & LOMASK
;
381 /* if autoDoze is enabled, add up the cost of bulldozed tiles */
382 if (tileValue
!= 0) {
383 if (tally(tileValue
)) {
390 /* check and see if the tile is clear or not */
391 if (tileValue
!= 0) {
403 cost
+= CostOf
[tool
];
405 if ((TotalFunds
- cost
) < 0) {
411 (cost
>= Expensive
) &&
413 (view
->super_user
== 0)) {
417 /* take care of the money situtation here */
423 for (rowNum
= 0; rowNum
<= 2; rowNum
++) {
426 for (columnNum
= 0; columnNum
<= 2; columnNum
++) {
427 if (columnNum
== 1 && rowNum
== 1) {
428 Map
[mapH
++][mapV
] = base
+ BNCNBIT
+ ZONEBIT
;
430 Map
[mapH
++][mapV
] = base
+ BNCNBIT
;
436 check3x3border(xPos
, yPos
);
445 check4x4border(short xMap
, short yMap
)
451 xPos
= xMap
; yPos
= yMap
- 1;
452 for (cnt
= 0; cnt
< 4; cnt
++) {
453 /* this will do the upper bordering row */
454 tilePtr
= &Map
[xPos
][yPos
];
455 ConnecTile(xPos
, yPos
, tilePtr
, 0);
459 xPos
= xMap
- 1; yPos
= yMap
;
460 for (cnt
= 0; cnt
< 4; cnt
++) {
461 /* this will do the left bordering row */
462 tilePtr
= &Map
[xPos
][yPos
];
463 ConnecTile(xPos
, yPos
, tilePtr
, 0);
467 xPos
= xMap
; yPos
= yMap
+ 4;
468 for (cnt
= 0; cnt
< 4;cnt
++) {
469 /* this will do the bottom bordering row */
470 tilePtr
= &Map
[xPos
][yPos
];
471 ConnecTile(xPos
, yPos
, tilePtr
, 0);
475 xPos
= xMap
+ 4; yPos
= yMap
;
476 for (cnt
= 0; cnt
< 4; cnt
++) {
477 /* this will do the right bordering row */
478 tilePtr
= &Map
[xPos
][yPos
];
479 ConnecTile(xPos
, yPos
, tilePtr
, 0);
486 check4x4(SimView
*view
, short mapH
, short mapV
,
487 short base
, short aniFlag
, short tool
)
489 register short rowNum
, columnNum
;
498 if ((mapH
< 0) || (mapH
> (WORLD_X
- 4)) ||
499 (mapV
< 0) || (mapV
> (WORLD_Y
- 4))) {
503 h
= xMap
= holdMapH
= mapH
;
508 for (rowNum
= 0; rowNum
<= 3; rowNum
++) {
511 for (columnNum
= 0; columnNum
<= 3; columnNum
++) {
512 tileValue
= Map
[mapH
++][mapV
] & LOMASK
;
515 /* if autoDoze is enabled, add up the cost of bulldozed tiles */
516 if (tileValue
!= 0) {
517 if (tally(tileValue
)) {
524 /* check and see if the tile is clear or not */
525 if (tileValue
!= 0) {
537 cost
+= CostOf
[tool
];
539 if ((TotalFunds
- cost
) < 0) {
545 (cost
>= Expensive
) &&
547 (view
->super_user
== 0)) {
551 /* take care of the money situtation here */
555 mapV
= v
; holdMapH
= h
;
557 for (rowNum
= 0; rowNum
<= 3; rowNum
++) {
560 for (columnNum
= 0; columnNum
<= 3; columnNum
++) {
561 if (columnNum
== 1 && rowNum
== 1)
562 Map
[mapH
++][mapV
] = base
+ BNCNBIT
+ ZONEBIT
;
563 else if (columnNum
== 1 && rowNum
== 2 && aniFlag
)
564 Map
[mapH
++][mapV
] = base
+ BNCNBIT
+ ANIMBIT
;
566 Map
[mapH
++][mapV
] = base
+ BNCNBIT
;
571 check4x4border(xMap
, yMap
);
580 check6x6border(short xMap
, short yMap
)
585 xPos
= xMap
; yPos
= yMap
- 1;
586 for (cnt
= 0; cnt
< 6; cnt
++) {
587 /* this will do the upper bordering row */
588 ConnecTile(xPos
, yPos
, &Map
[xPos
][yPos
], 0);
592 xPos
= xMap
- 1; yPos
= yMap
;
593 for (cnt
=0; cnt
< 6; cnt
++) {
594 /* this will do the left bordering row */
595 ConnecTile(xPos
, yPos
, &Map
[xPos
][yPos
], 0);
599 xPos
= xMap
; yPos
= yMap
+ 6;
600 for (cnt
= 0; cnt
< 6; cnt
++) {
601 /* this will do the bottom bordering row */
602 ConnecTile(xPos
, yPos
, &Map
[xPos
][yPos
], 0);
606 xPos
= xMap
+ 6; yPos
= yMap
;
607 for (cnt
= 0; cnt
< 6; cnt
++) {
608 /* this will do the right bordering row */
609 ConnecTile(xPos
, yPos
, &Map
[xPos
][yPos
], 0);
616 check6x6(SimView
*view
, short mapH
, short mapV
, short base
, short tool
)
618 register short rowNum
, columnNum
;
627 if ((mapH
< 0) || (mapH
> (WORLD_X
- 6)) ||
628 (mapV
< 0) || (mapV
> (WORLD_Y
- 6)))
631 h
= xMap
= holdMapH
= mapH
;
636 for (rowNum
= 0; rowNum
<= 5; rowNum
++) {
639 for (columnNum
= 0; columnNum
<= 5; columnNum
++) {
640 tileValue
= Map
[mapH
++][mapV
] & LOMASK
;
643 /* if autoDoze is enabled, add up the cost of bulldozed tiles */
644 if (tileValue
!= 0) {
645 if (tally(tileValue
)) {
652 /* check and see if the tile is clear or not */
653 if (tileValue
!= 0) {
665 cost
+= CostOf
[tool
];
667 if ((TotalFunds
- cost
) < 0) {
673 (cost
>= Expensive
) &&
675 (view
->super_user
== 0)) {
679 /* take care of the money situtation here */
683 mapV
= v
; holdMapH
= h
;
685 for (rowNum
= 0; rowNum
<= 5; rowNum
++) {
688 for (columnNum
= 0; columnNum
<= 5; columnNum
++) {
689 if (columnNum
== 1 && rowNum
== 1) {
690 Map
[mapH
++][mapV
] = base
+ BNCNBIT
+ ZONEBIT
;
692 Map
[mapH
++][mapV
] = base
+ BNCNBIT
;
698 check6x6border(xMap
, yMap
);
706 /* search table for zone status string match */
707 static short idArray
[28] = {
708 DIRT
, RIVER
, TREEBASE
, RUBBLE
,
709 FLOOD
, RADTILE
, FIRE
, ROADBASE
,
710 POWERBASE
, RAILBASE
, RESBASE
, COMBASE
,
711 INDBASE
, PORTBASE
, AIRPORTBASE
, COALBASE
,
712 FIRESTBASE
, POLICESTBASE
, STADIUMBASE
, NUCLEARBASE
,
713 827, 832, FOUNTAIN
, INDBASE2
,
714 FOOTBALLGAME1
, VBRDG0
, 952, 956
726 Clear, Water, Trees, Rubble,
727 Flood, Radioactive Waste, Fire, Road,
728 Power, Rail, Residential, Commercial,
729 Industrial, Port, AirPort, Coal Power,
730 Fire Department, Police Department, Stadium, Nuclear Power,
731 Draw Bridge, Radar Dish, Fountain, Industrial,
732 49er's 38 Bears 3, Draw Bridge, Ur 238
736 int getDensityStr(short catNo
, short mapH
, short mapV
)
742 z
= PopDensity
[mapH
>>1][mapV
>>1];
747 z
= LandValueMem
[mapH
>>1][mapV
>>1];
748 if (z
< 30) return (4);
749 if (z
< 80) return (5);
750 if (z
< 150) return (6);
753 z
= CrimeMem
[mapH
>>1][mapV
>>1];
758 z
= PollutionMem
[mapH
>>1][mapV
>>1];
759 if ((z
< 64) && (z
> 0)) return (13);
764 z
= RateOGMem
[mapH
>>3][mapV
>>3];
765 if (z
< 0) return (16);
766 if (z
== 0) return (17);
767 if (z
> 100) return (19);
775 doZoneStatus(short mapH
, short mapV
)
778 char statusStr
[5][256];
784 tileNum
= Map
[mapH
][mapV
] & LOMASK
;
786 if (tileNum
>= COALSMOKE1
&& tileNum
< FOOTBALLGAME1
)
790 for (x
= 1; x
< 29 && found
; x
++) {
791 if (tileNum
< idArray
[x
]) {
800 GetIndString(localStr
, 219, x
);
802 for (x
= 0; x
< 5; x
++) {
803 id
= getDensityStr(x
, mapH
, mapV
);
806 if (id
> 20) id
= 20;
807 GetIndString(statusStr
[x
], 202, id
);
810 DoShowZoneStatus(localStr
, statusStr
[0], statusStr
[1],
811 statusStr
[2], statusStr
[3], statusStr
[4], mapH
, mapV
);
816 DoShowZoneStatus(char *str
, char *s0
, char *s1
, char *s2
, char *s3
, char *s4
,
821 sprintf(buf
, "UIShowZoneStatus {%s} {%s} {%s} {%s} {%s} {%s} %d %d",
822 str
, s0
, s1
, s2
, s3
, s4
, x
, y
);
827 /* comefrom: processWand */
829 put3x3Rubble(short x
, short y
)
831 register int xx
, yy
, zz
;
833 for (xx
= x
- 1; xx
< x
+ 2; xx
++) {
834 for (yy
= y
- 1; yy
< y
+ 2; yy
++) {
835 if (TestBounds(xx
, yy
)) {
836 zz
= Map
[xx
][yy
] & LOMASK
;
837 if ((zz
!= RADTILE
) && (zz
!= 0)) {
840 ? (TINYEXP
+ Rand(2))
850 /* comefrom: processWand */
852 put4x4Rubble(short x
, short y
)
854 register int xx
, yy
, zz
;
856 for (xx
= x
- 1; xx
< x
+ 3; xx
++) {
857 for (yy
= y
- 1; yy
< y
+ 3; yy
++) {
858 if (TestBounds(xx
, yy
)) {
859 zz
= Map
[xx
][yy
] & LOMASK
;
860 if ((zz
!= RADTILE
) && (zz
!= 0)) {
863 ? (TINYEXP
+ Rand(2))
873 /* comefrom: processWand */
875 put6x6Rubble(short x
, short y
)
877 register int xx
, yy
, zz
;
879 for (xx
= x
- 1; xx
< x
+ 5; xx
++) {
880 for (yy
= y
- 1; yy
< y
+ 5; yy
++) {
881 if (TestBounds(xx
, yy
)) {
882 zz
= Map
[xx
][yy
] & LOMASK
;
883 if ((zz
!= RADTILE
) && (zz
!= 0)) {
886 ? (TINYEXP
+ Rand(2))
897 DidTool(SimView
*view
, char *name
, short x
, short y
)
902 sprintf(buf
, "UIDidTool%s %s %d %d",
903 name
, Tk_PathName(view
->tkwin
), x
, y
);
910 DoSetWandState(SimView
*view
, short state
)
914 sprintf(buf
, "UISetToolState %s %d", Tk_PathName(view
->tkwin
), state
);
919 /************************************************************************/
924 query_tool(SimView
*view
, short x
, short y
)
926 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
927 (y
< 0) || (y
> (WORLD_Y
- 1))) {
932 DidTool(view
, "Qry", x
, y
);
938 bulldozer_tool(SimView
*view
, short x
, short y
)
940 unsigned short currTile
, temp
;
941 short zoneSize
, deltaH
, deltaV
;
944 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
945 (y
< 0) || (y
> (WORLD_Y
- 1))) {
949 currTile
= Map
[x
][y
];
950 temp
= currTile
& LOMASK
;
952 if (currTile
& ZONEBIT
) { /* zone center bit is set */
953 if (TotalFunds
> 0) {
955 switch (checkSize(temp
)) {
957 MakeSound("city", "Explosion-High");
963 MakeSound("city", "Explosion-Low");
967 MakeSound("city", "Explosion-High");
968 MakeSound("city", "Explosion-Low");
976 } else if ((zoneSize
= checkBigZone(temp
, &deltaH
, &deltaV
))) {
977 if (TotalFunds
> 0) {
981 MakeSound("city", "Explosion-High");
985 MakeSound("city", "Explosion-Low");
986 put4x4Rubble(x
+ deltaH
, y
+ deltaV
);
990 MakeSound("city", "Explosion-High");
991 MakeSound("city", "Explosion-Low");
992 put6x6Rubble(x
+ deltaH
, y
+ deltaV
);
997 if (temp
== RIVER
|| temp
== REDGE
|| temp
== CHANNEL
) {
998 if (TotalFunds
>= 6) {
999 result
= ConnecTile(x
, y
, &Map
[x
][y
], 1);
1000 if (temp
!= (Map
[x
][y
] & LOMASK
)) {
1007 result
= ConnecTile(x
, y
, &Map
[x
][y
], 1);
1012 DidTool(view
, "Dozr", x
, y
);
1019 road_tool(SimView
*view
, short x
, short y
)
1023 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1024 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1028 result
= ConnecTile(x
, y
, &Map
[x
][y
], 2);
1031 DidTool(view
, "Road", x
, y
);
1038 rail_tool(SimView
*view
, short x
, short y
)
1042 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1043 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1047 result
= ConnecTile(x
, y
, &Map
[x
][y
], 3);
1050 DidTool(view
, "Rail", x
, y
);
1057 wire_tool(SimView
*view
, short x
, short y
)
1061 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1062 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1066 result
= ConnecTile(x
, y
, &Map
[x
][y
], 4);
1069 DidTool(view
, "Wire", x
, y
);
1076 park_tool(SimView
*view
, short x
, short y
)
1080 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1081 (y
< 0) || (y
> (WORLD_Y
- 1)))
1084 result
= putDownPark(view
, x
, y
);
1086 DidTool(view
, "Park", x
, y
);
1093 residential_tool(SimView
*view
, short x
, short y
)
1097 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1098 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1102 result
= check3x3(view
, x
, y
, RESBASE
, residentialState
);
1104 DidTool(view
, "Res", x
, y
);
1111 commercial_tool(SimView
*view
, short x
, short y
)
1115 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1116 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1120 result
= check3x3(view
, x
, y
, COMBASE
, commercialState
);
1122 DidTool(view
, "Com", x
, y
);
1129 industrial_tool(SimView
*view
, short x
, short y
)
1133 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1134 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1138 result
= check3x3(view
, x
, y
, INDBASE
, industrialState
);
1140 DidTool(view
, "Ind", x
, y
);
1147 police_dept_tool(SimView
*view
, short x
, short y
)
1151 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1152 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1156 result
= check3x3(view
, x
, y
, POLICESTBASE
, policeState
);
1158 DidTool(view
, "Pol", x
, y
);
1165 fire_dept_tool(SimView
*view
, short x
, short y
)
1169 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1170 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1174 result
= check3x3(view
, x
, y
, FIRESTBASE
, fireState
);
1176 DidTool(view
, "Fire", x
, y
);
1183 stadium_tool(SimView
*view
, short x
, short y
)
1187 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1188 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1192 result
= check4x4(view
, x
, y
, STADIUMBASE
, 0, stadiumState
);
1194 DidTool(view
, "Stad", x
, y
);
1201 coal_power_plant_tool(SimView
*view
, short x
, short y
)
1205 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1206 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1210 result
= check4x4(view
, x
, y
, COALBASE
, 1, powerState
);
1212 DidTool(view
, "Coal", x
, y
);
1219 nuclear_power_plant_tool(SimView
*view
, short x
, short y
)
1223 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1224 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1228 result
= check4x4(view
, x
, y
, NUCLEARBASE
, 1, nuclearState
);
1230 DidTool(view
, "Nuc", x
, y
);
1237 seaport_tool(SimView
*view
, short x
, short y
)
1241 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1242 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1246 result
= check4x4(view
, x
, y
, PORTBASE
, 0, seaportState
);
1248 DidTool(view
, "Seap", x
, y
);
1255 airport_tool(SimView
*view
, short x
, short y
)
1259 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1260 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1264 result
= check6x6(view
, x
, y
, AIRPORTBASE
, airportState
);
1266 DidTool(view
, "Airp", x
, y
);
1273 network_tool(SimView
*view
, short x
, short y
)
1277 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1278 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1282 result
= putDownNetwork(view
, x
, y
);
1284 DidTool(view
, "Net", x
, y
);
1292 special_tool(SimView
*view
, short x
, short y
)
1296 if ((x
< 0) || (x
> (WORLD_X
- 1)) ||
1297 (y
< 0) || (y
> (WORLD_Y
- 1))) {
1301 result
= check3x3(view
, x
, y
, specialBase
, specialState
);
1303 DidTool(view
, "Special", x
, y
);
1310 ChalkTool(SimView
*view
, short x
, short y
, short color
, short first
)
1313 ChalkStart(view
, x
, y
, color
);
1315 ChalkTo(view
, x
, y
);
1317 DidTool(view
, "Chlk", x
, y
);
1323 ChalkStart(SimView
*view
, int x
, int y
, int color
)
1328 for (ip
= &sim
->overlay
; *ip
!= NULL
; ip
= &((*ip
)->next
)) ;
1330 *ip
= ink
= NewInk();
1331 ink
->x
= x
; ink
->y
= y
;
1333 StartInk(ink
, x
, y
);
1334 view
->track_info
= (char *)ink
;
1337 view
->tool_event_time
= view
->tool_last_event_time
=
1338 ((TkWindow
*)view
->tkwin
)->dispPtr
->lastEventTime
;
1343 ChalkTo(SimView
*view
, int x
, int y
)
1348 Ink
*ink
= (Ink
*)view
->track_info
;
1351 if (view
->x
->dpy
->motion_buffer
) {
1352 XTimeCoord
*coords
= NULL
, *coord
;
1355 view
->tool_last_event_time
= view
->tool_event_time
;
1356 view
->tool_event_time
=
1357 ((TkWindow
*)view
->tkwin
)->dispPtr
->lastEventTime
;
1359 coords
= XGetMotionEvents(view
->x
->dpy
,
1360 Tk_WindowId(view
->tkwin
),
1361 view
->tool_last_event_time
,
1362 view
->tool_event_time
,
1365 printf("got %d events at %x from %d to %d (%d elapsed)\n",
1367 view
->tool_last_event_time
, view
->tool_event_time
,
1368 view
->tool_event_time
- view
->tool_last_event_time
);
1371 lx
= ink
->last_x
; ly
= ink
->last_y
;
1373 for (i
= 0, coord
= coords
; i
< n
; i
++, coord
++) {
1374 ViewToPixelCoords(view
, coord
->x
, coord
->y
, &x0
, &y0
);
1375 lx
= (lx
+ lx
+ lx
+ x0
) >>2;
1376 ly
= (ly
+ ly
+ ly
+ y0
) >>2;
1378 printf("adding %d %d => %d %d => %d %d\n",
1379 coord
->x
, coord
->y
, x0
, y0
, lx
, ly
);
1381 AddInk(ink
, lx
, ly
);
1386 XFree((char *)coords
);
1398 EraserTool(SimView
*view
, short x
, short y
, short first
)
1401 EraserStart(view
, x
, y
);
1403 EraserTo(view
, x
, y
);
1405 DidTool(view
, "Eraser", x
, y
);
1411 InkInBox(Ink
*ink
, int left
, int top
, int right
, int bottom
)
1413 if ((left
<= ink
->right
) &&
1414 (right
>= ink
->left
) &&
1415 (top
<= ink
->bottom
) &&
1416 (bottom
>= ink
->top
)) {
1417 int x
, y
, lx
, ly
, i
;
1419 if (ink
->length
== 1) {
1423 x
= ink
->x
; y
= ink
->y
;
1424 for (i
= 1; i
< ink
->length
; i
++) {
1425 int ileft
, iright
, itop
, ibottom
;
1428 x
+= ink
->points
[i
].x
; y
+= ink
->points
[i
].y
;
1429 if (x
< lx
) { ileft
= x
; iright
= lx
; }
1430 else { ileft
= lx
; iright
= x
; }
1431 if (y
< ly
) { itop
= y
; ibottom
= ly
; }
1432 else { itop
= ly
; ibottom
= y
; }
1433 if ((left
<= iright
) &&
1446 EraserStart(SimView
*view
, int x
, int y
)
1448 EraserTo(view
, x
, y
);
1453 EraserTo(SimView
*view
, int x
, int y
)
1457 for (ip
= &sim
->overlay
; *ip
!= NULL
;) {
1459 if (InkInBox(ink
, x
- 8, y
- 8, x
+ 8, y
+ 8)) {
1461 for (view
= sim
->editor
; view
!= NULL
; view
= view
->next
) {
1464 if ((ink
->right
>= (vleft
= (view
->pan_x
- (view
->w_width
/ 2)))) &&
1465 (ink
->left
<= (vleft
+ view
->w_width
)) &&
1466 (ink
->bottom
>= (vtop
= (view
->pan_y
- (view
->w_height
/ 2)))) &&
1467 (ink
->top
<= (vtop
+ view
->w_height
))) {
1468 view
->overlay_mode
= 0;
1469 EventuallyRedrawView(view
);
1477 ip
= &((*ip
)->next
);
1484 do_tool(SimView
*view
, short state
, short x
, short y
, short first
)
1489 case residentialState
:
1490 result
= residential_tool(view
, x
>>4, y
>>4);
1492 case commercialState
:
1493 result
= commercial_tool(view
, x
>>4, y
>>4);
1495 case industrialState
:
1496 result
= industrial_tool(view
, x
>>4, y
>>4);
1499 result
= fire_dept_tool(view
, x
>>4, y
>>4);
1502 result
= query_tool(view
, x
>>4, y
>>4);
1505 result
= police_dept_tool(view
, x
>>4, y
>>4);
1508 result
= wire_tool(view
, x
>>4, y
>>4);
1511 result
= bulldozer_tool(view
, x
>>4, y
>>4);
1514 result
= rail_tool(view
, x
>>4, y
>>4);
1517 result
= road_tool(view
, x
>>4, y
>>4);
1520 result
= ChalkTool(view
, x
- 5, y
+ 11, COLOR_WHITE
, first
);
1523 result
= EraserTool(view
, x
, y
, first
);
1526 result
= stadium_tool(view
, x
>>4, y
>>4);
1529 result
= park_tool(view
, x
>>4, y
>>4);
1532 result
= seaport_tool(view
, x
>>4, y
>>4);
1535 result
= coal_power_plant_tool(view
, x
>>4, y
>>4);
1538 result
= nuclear_power_plant_tool(view
, x
>>4, y
>>4);
1541 result
= airport_tool(view
, x
>>4, y
>>4);
1544 result
= network_tool(view
, x
>>4, y
>>4);
1557 current_tool(SimView
*view
, short x
, short y
, short first
)
1559 return do_tool(view
, view
->tool_state
, x
, y
, first
);
1564 DoTool(SimView
*view
, short tool
, short x
, short y
)
1568 result
= do_tool(view
, tool
, x
<<4, y
<<4, 1);
1573 MakeSoundOn(view
, "edit", "UhUh");
1574 } else if (result
== -2) {
1577 MakeSoundOn(view
, "edit", "Sorry");
1582 InvalidateEditors();
1587 ToolDown(SimView
*view
, int x
, int y
)
1591 ViewToPixelCoords(view
, x
, y
, &x
, &y
);
1595 result
= current_tool(view
, x
, y
, 1);
1600 MakeSoundOn(view
, "edit", "UhUh");
1601 } else if (result
== -2) {
1604 MakeSoundOn(view
, "edit", "Sorry");
1605 } else if (result
== -3) {
1606 DoPendTool(view
, view
->tool_state
, x
>>4, y
>>4);
1616 ToolUp(SimView
*view
, int x
, int y
)
1618 ToolDrag(view
, x
, y
);
1623 ToolDrag(SimView
*view
, int px
, int py
)
1625 int x
, y
, dx
, dy
, adx
, ady
, lx
, ly
, dist
;
1626 float i
, step
, tx
, ty
, dtx
, dty
, rx
, ry
;
1628 ViewToPixelCoords(view
, px
, py
, &x
, &y
);
1629 view
->tool_x
= x
; view
->tool_y
= y
;
1631 if ((view
->tool_state
== chalkState
) ||
1632 (view
->tool_state
== eraserState
)) {
1634 current_tool(view
, x
, y
, 0);
1635 view
->last_x
= x
; view
->last_y
= y
;
1639 dist
= toolSize
[view
->tool_state
];
1642 lx
= view
->last_x
>> 4;
1643 ly
= view
->last_y
>> 4;
1648 if (dx
== 0 && dy
== 0) {
1652 adx
= ABS(dx
); ady
= ABS(dy
);
1660 rx
= (dx
< 0 ? 1 : 0);
1661 ry
= (dy
< 0 ? 1 : 0);
1664 for (i
= 0.0; i
<= 1 + step
; i
+= step
) {
1665 tx
= (view
->last_x
>>4) + i
* dx
;
1666 ty
= (view
->last_y
>>4) + i
* dy
;
1669 if (dtx
>= 1 || dty
>= 1) {
1670 /* fill in corners */
1671 if ((dtx
>= 1) && (dty
>= 1)) {
1673 current_tool(view
, ((int)(tx
+ rx
)) <<4, ly
<<4, 0);
1675 current_tool(view
, lx
<<4, ((int)(ty
+ ry
)) <<4, 0);
1678 lx
= (int)(tx
+ rx
);
1679 ly
= (int)(ty
+ ry
);
1680 current_tool(view
, lx
<<4, ly
<<4, 0);
1684 for (i
= 0.0; i
<= 1 + step
; i
+= step
) {
1685 tx
= (view
->last_x
>>4) + i
* dx
;
1686 ty
= (view
->last_y
>>4) + i
* dy
;
1689 lx
= (int)(tx
+ rx
);
1690 ly
= (int)(ty
+ ry
);
1691 current_tool(view
, lx
<<4, ly
<<4, 0);
1695 view
->last_x
= (lx
<<4) + 8;
1696 view
->last_y
= (ly
<<4) + 8;
1698 sim_skip
= 0; /* update editors overlapping this one */
1705 DoPendTool(SimView
*view
, int tool
, int x
, int y
)
1709 sprintf(buf
, "DoPendTool %s %d %d %d",
1710 Tk_PathName(view
->tkwin
), tool
, x
, y
);