]> git.zerfleddert.de Git - micropolis/blob - src/sim/w_tool.c
show description (including time limit) when hovering over a scenario
[micropolis] / src / sim / w_tool.c
1 /* w_tool.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 specialBase = CHURCH;
66 int OverRide = 0;
67 int Expensive = 1000;
68 int Players = 1;
69 int Votes = 0;
70 int PendingTool = -1;
71 int PendingX;
72 int PendingY;
73
74
75 QUAD CostOf[] = {
76 100, 100, 100, 500,
77 0, 500, 5, 1,
78 20, 10, 0, 0,
79 5000, 10, 3000, 3000,
80 5000, 10000, 100, 0,
81 };
82
83
84 short toolSize[] = {
85 3, 3, 3, 3,
86 1, 3, 1, 1,
87 1, 1, 0, 0,
88 4, 1, 4, 4,
89 4, 6, 1, 0,
90 };
91
92
93 short toolOffset[] = {
94 1, 1, 1, 1,
95 0, 1, 0, 0,
96 0, 0, 0, 0,
97 1, 0, 1, 1,
98 1, 1, 0, 0,
99 };
100
101
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 */
122 };
123
124
125 Ink *NewInk();
126
127 short tally(short tileValue);
128 int DoSetWandState(SimView *view, short state);
129
130
131 /*************************************************************************/
132 /* UTILITIES */
133
134
135 setWandState(SimView *view, short state)
136 {
137 #if 0
138 if (state < 0) {
139 specialBase = -state;
140 state = specialState;
141 }
142 #endif
143
144 view->tool_state = state;
145 DoUpdateHeads();
146 DoSetWandState(view, state);
147 }
148
149
150 int
151 putDownPark(SimView *view, short mapH, short mapV)
152 {
153 short value, tile;
154
155 if (TotalFunds - CostOf[parkState] >= 0) {
156 value = Rand(4);
157
158 if (value == 4)
159 tile = FOUNTAIN | BURNBIT | BULLBIT | ANIMBIT;
160 else
161 tile = (value + WOODS2) | BURNBIT | BULLBIT;
162
163 if (Map[mapH][mapV] == 0) {
164 Spend(CostOf[parkState]);
165 UpdateFunds();
166 Map[mapH][mapV] = tile;
167 return 1;
168 }
169 return -1;
170 }
171 return -2;
172 }
173
174
175 int
176 putDownNetwork(SimView *view, short mapH, short mapV)
177 {
178 int tile = Map[mapH][mapV] & LOMASK;
179
180 if ((TotalFunds > 0) && tally(tile)) {
181 Map[mapH][mapV] = tile = 0;
182 Spend(1);
183 }
184
185 if (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]);
189 return 1;
190 } else {
191 return -2;
192 }
193 } else {
194 return -1;
195 }
196 }
197
198
199 short
200 checkBigZone(short id, short *deltaHPtr, short *deltaVPtr)
201 {
202 switch (id) {
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);
208
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);
217
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);
223
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);
229
230 /* check airport */
231 /*** first row ***/
232 case AIRPORT:
233 *deltaHPtr = 0; *deltaVPtr = 0; return (6);
234 case AIRPORT + 1:
235 *deltaHPtr = -1; *deltaVPtr = 0; return (6);
236 case AIRPORT + 2:
237 *deltaHPtr = -2; *deltaVPtr = 0; return (6);
238 case AIRPORT + 3:
239 *deltaHPtr = -3; *deltaVPtr = 0; return (6);
240
241 /*** second row ***/
242 case AIRPORT + 6:
243 *deltaHPtr = 0; *deltaVPtr = -1; return (6);
244 case AIRPORT + 7:
245 *deltaHPtr = -1; *deltaVPtr = -1; return (6);
246 case AIRPORT + 8:
247 *deltaHPtr = -2; *deltaVPtr = -1; return (6);
248 case AIRPORT + 9:
249 *deltaHPtr = -3; *deltaVPtr = -1; return (6);
250
251 /*** third row ***/
252 case AIRPORT + 12:
253 *deltaHPtr = 0; *deltaVPtr = -2; return (6);
254 case AIRPORT + 13:
255 *deltaHPtr = -1; *deltaVPtr = -2; return (6);
256 case AIRPORT + 14:
257 *deltaHPtr = -2; *deltaVPtr = -2; return (6);
258 case AIRPORT + 15:
259 *deltaHPtr = -3; *deltaVPtr = -2; return (6);
260
261 /*** fourth row ***/
262 case AIRPORT + 18:
263 *deltaHPtr = 0; *deltaVPtr = -3; return (6);
264 case AIRPORT + 19:
265 *deltaHPtr = -1; *deltaVPtr = -3; return (6);
266 case AIRPORT + 20:
267 *deltaHPtr = -2; *deltaVPtr = -3; return (6);
268 case AIRPORT + 21:
269 *deltaHPtr = -3; *deltaVPtr = -3; return (6);
270
271 default:
272 *deltaHPtr = 0; *deltaVPtr = 0; return (0);
273 }
274 }
275
276
277 short
278 tally(short tileValue)
279 {
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)))) { /* ??? */
287 return (1);
288 } else {
289 return (0);
290 }
291 }
292
293
294 short
295 checkSize(short temp)
296 {
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)))) {
300 return (3);
301 } else if (((temp >= PORTBASE) && (temp <= LASTPORT)) ||
302 ((temp >= COALBASE) && (temp <= LASTPOWERPLANT)) ||
303 ((temp >= STADIUMBASE) && (temp <= LASTZONE))) {
304 return (4);
305 }
306 return (0);
307 }
308
309
310 /* 3x3 */
311
312
313 void
314 check3x3border(short xMap, short yMap)
315 {
316 short xPos, yPos;
317 short cnt;
318
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);
323 xPos++;
324 }
325
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);
330 yPos++;
331 }
332
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);
337 xPos++;
338 }
339
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);
344 yPos++;
345 }
346 }
347
348
349 int
350 check3x3(SimView *view, short mapH, short mapV, short base, short tool)
351 {
352 register short rowNum, columnNum;
353 register short holdMapH, holdMapV;
354 short xPos, yPos;
355 short cost = 0;
356 short tileValue;
357 short flag;
358
359 mapH--; mapV--;
360 if ((mapH < 0) || (mapH > (WORLD_X - 3)) ||
361 (mapV < 0) || (mapV > (WORLD_Y - 3))) {
362 return -1;
363 }
364
365 xPos = holdMapH = mapH;
366 yPos = holdMapV = mapV;
367
368 flag = 1;
369
370 for (rowNum = 0; rowNum <= 2; rowNum++) {
371 mapH = holdMapH;
372
373 for (columnNum = 0; columnNum <= 2; columnNum++) {
374 tileValue = Map[mapH++][mapV] & LOMASK;
375
376 if (autoBulldoze) {
377 /* if autoDoze is enabled, add up the cost of bulldozed tiles */
378 if (tileValue != 0) {
379 if (tally(tileValue)) {
380 cost++;
381 } else {
382 flag = 0;
383 }
384 }
385 } else {
386 /* check and see if the tile is clear or not */
387 if (tileValue != 0) {
388 flag = 0;
389 }
390 }
391 }
392 mapV++;
393 }
394
395 if (flag == 0) {
396 return -1;
397 }
398
399 cost += CostOf[tool];
400
401 if ((TotalFunds - cost) < 0) {
402 return -2;
403 }
404
405 if ((Players > 1) &&
406 (OverRide == 0) &&
407 (cost >= Expensive) &&
408 (view != NULL) &&
409 (view->super_user == 0)) {
410 return -3;
411 }
412
413 /* take care of the money situtation here */
414 Spend(cost);
415 UpdateFunds();
416
417 mapV = holdMapV;
418
419 for (rowNum = 0; rowNum <= 2; rowNum++) {
420 mapH = holdMapH;
421
422 for (columnNum = 0; columnNum <= 2; columnNum++) {
423 if (columnNum == 1 && rowNum == 1) {
424 Map[mapH++][mapV] = base + BNCNBIT + ZONEBIT;
425 } else {
426 Map[mapH++][mapV] = base + BNCNBIT;
427 }
428 base++;
429 }
430 mapV++;
431 }
432 check3x3border(xPos, yPos);
433 return 1;
434 }
435
436
437 /* 4x4 */
438
439
440 void
441 check4x4border(short xMap, short yMap)
442 {
443 Ptr tilePtr;
444 short xPos, yPos;
445 short cnt;
446
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);
452 xPos++;
453 }
454
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);
460 yPos++;
461 }
462
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);
468 xPos++;
469 }
470
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);
476 yPos++;
477 }
478 }
479
480
481 short
482 check4x4(SimView *view, short mapH, short mapV,
483 short base, short aniFlag, short tool)
484 {
485 register short rowNum, columnNum;
486 short h, v;
487 short holdMapH;
488 short xMap, yMap;
489 short tileValue;
490 short flag;
491 short cost = 0;
492
493 mapH--; mapV--;
494 if ((mapH < 0) || (mapH > (WORLD_X - 4)) ||
495 (mapV < 0) || (mapV > (WORLD_Y - 4))) {
496 return -1;
497 }
498
499 h = xMap = holdMapH = mapH;
500 v = yMap = mapV;
501
502 flag = 1;
503
504 for (rowNum = 0; rowNum <= 3; rowNum++) {
505 mapH = holdMapH;
506
507 for (columnNum = 0; columnNum <= 3; columnNum++) {
508 tileValue = Map[mapH++][mapV] & LOMASK;
509
510 if (autoBulldoze) {
511 /* if autoDoze is enabled, add up the cost of bulldozed tiles */
512 if (tileValue != 0) {
513 if (tally(tileValue)) {
514 cost++;
515 } else {
516 flag = 0;
517 }
518 }
519 } else {
520 /* check and see if the tile is clear or not */
521 if (tileValue != 0) {
522 flag = 0;
523 }
524 }
525 }
526 mapV++;
527 }
528
529 if (flag == 0) {
530 return -1;
531 }
532
533 cost += CostOf[tool];
534
535 if ((TotalFunds - cost) < 0) {
536 return -2;
537 }
538
539 if ((Players > 1) &&
540 (OverRide == 0) &&
541 (cost >= Expensive) &&
542 (view != NULL) &&
543 (view->super_user == 0)) {
544 return -3;
545 }
546
547 /* take care of the money situtation here */
548 Spend(cost);
549 UpdateFunds();
550
551 mapV = v; holdMapH = h;
552
553 for (rowNum = 0; rowNum <= 3; rowNum++) {
554 mapH = holdMapH;
555
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;
561 else
562 Map[mapH++][mapV] = base + BNCNBIT;
563 base++;
564 }
565 mapV++;
566 }
567 check4x4border(xMap, yMap);
568 return 1;
569 }
570
571
572 /* 6x6 */
573
574
575 void
576 check6x6border(short xMap, short yMap)
577 {
578 short xPos, yPos;
579 short cnt;
580
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);
585 xPos++;
586 }
587
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);
592 yPos++;
593 }
594
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);
599 xPos++;
600 }
601
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);
606 yPos++;
607 }
608 }
609
610
611 short
612 check6x6(SimView *view, short mapH, short mapV, short base, short tool)
613 {
614 register short rowNum, columnNum;
615 short h, v;
616 short holdMapH;
617 short xMap, yMap;
618 short flag;
619 short tileValue;
620 short cost = 0;
621
622 mapH--; mapV--;
623 if ((mapH < 0) || (mapH > (WORLD_X - 6)) ||
624 (mapV < 0) || (mapV > (WORLD_Y - 6)))
625 return -1;
626
627 h = xMap = holdMapH = mapH;
628 v = yMap = mapV;
629
630 flag = 1;
631
632 for (rowNum = 0; rowNum <= 5; rowNum++) {
633 mapH = holdMapH;
634
635 for (columnNum = 0; columnNum <= 5; columnNum++) {
636 tileValue = Map[mapH++][mapV] & LOMASK;
637
638 if (autoBulldoze) {
639 /* if autoDoze is enabled, add up the cost of bulldozed tiles */
640 if (tileValue != 0)
641 if (tally(tileValue)) {
642 cost++;
643 } else {
644 flag = 0;
645 }
646 } else {
647 /* check and see if the tile is clear or not */
648 if (tileValue != 0) {
649 flag = 0;
650 }
651 }
652 }
653 mapV++;
654 }
655
656 if (flag == 0) {
657 return -1;
658 }
659
660 cost += CostOf[tool];
661
662 if ((TotalFunds - cost) < 0) {
663 return -2;
664 }
665
666 if ((Players > 1) &&
667 (OverRide == 0) &&
668 (cost >= Expensive) &&
669 (view != NULL) &&
670 (view->super_user == 0)) {
671 return -3;
672 }
673
674 /* take care of the money situtation here */
675 Spend(cost);
676 UpdateFunds();
677
678 mapV = v; holdMapH = h;
679
680 for (rowNum = 0; rowNum <= 5; rowNum++) {
681 mapH = holdMapH;
682
683 for (columnNum = 0; columnNum <= 5; columnNum++) {
684 if (columnNum == 1 && rowNum == 1) {
685 Map[mapH++][mapV] = base + BNCNBIT + ZONEBIT;
686 } else {
687 Map[mapH++][mapV] = base + BNCNBIT;
688 }
689 base++;
690 }
691 mapV++;
692 }
693 check6x6border(xMap, yMap);
694 return 1;
695 }
696
697
698 /* QUERY */
699
700
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
710 };
711
712 /*
713 0, 2, 21, 44,
714 48, 52, 53, 64,
715 208, 224, 240, 423,
716 612, 693, 709, 745,
717 761, 770, 779, 811,
718 827, 832, 840, 844,
719 932, 948, 952, 956
720
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
728 */
729
730
731 int getDensityStr(short catNo, short mapH, short mapV)
732 {
733 int z;
734
735 switch(catNo) {
736 case 0:
737 z = PopDensity[mapH >>1][mapV >>1];
738 z = z >> 6;
739 z = z & 3;
740 return (z);
741 case 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);
746 return (7);
747 case 2:
748 z = CrimeMem[mapH >>1][mapV >>1];
749 z = z >> 6;
750 z = z & 3;
751 return (z + 8);
752 case 3:
753 z = PollutionMem[mapH >>1][mapV >>1];
754 if ((z < 64) && (z > 0)) return (13);
755 z = z >> 6;
756 z = z & 3;
757 return (z + 12);
758 case 4:
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);
763 return (18);
764 }
765 }
766
767
768 doZoneStatus(short mapH, short mapV)
769 {
770 char localStr[256];
771 char statusStr[5][256];
772 short id;
773 short x;
774 short tileNum;
775 short found;
776
777 tileNum = Map[mapH][mapV] & LOMASK;
778
779 if (tileNum >= COALSMOKE1 && tileNum < FOOTBALLGAME1)
780 tileNum = COALBASE;
781
782 found = 1;
783 for (x = 1; x < 29 && found; x++) {
784 if (tileNum < idArray[x]) {
785 found = 0;
786 }
787 }
788 x--;
789
790 if (x < 1 || x > 28)
791 x = 28;
792
793 GetIndString(localStr, 219, x);
794
795 for (x = 0; x < 5; x++) {
796 id = getDensityStr(x, mapH, mapV);
797 id++;
798 if (id <= 0) id = 1;
799 if (id > 20) id = 20;
800 GetIndString(statusStr[x], 202, id);
801 }
802
803 DoShowZoneStatus(localStr, statusStr[0], statusStr[1],
804 statusStr[2], statusStr[3], statusStr[4], mapH, mapV);
805 }
806
807
808 DoShowZoneStatus(char *str, char *s0, char *s1, char *s2, char *s3, char *s4,
809 int x, int y)
810 {
811 char buf[1024];
812
813 sprintf(buf, "UIShowZoneStatus {%s} {%s} {%s} {%s} {%s} {%s} %d %d",
814 str, s0, s1, s2, s3, s4, x, y);
815 Eval(buf);
816 }
817
818
819 /* comefrom: processWand */
820 put3x3Rubble(short x, short y)
821 {
822 register xx, yy, zz;
823
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)) {
829 Map[xx][yy] =
830 (DoAnimation
831 ? (TINYEXP + Rand(2))
832 : SOMETINYEXP)
833 | ANIMBIT | BULLBIT;
834 }
835 }
836 }
837 }
838 }
839
840
841 /* comefrom: processWand */
842 put4x4Rubble(short x, short y)
843 {
844 register xx, yy, zz;
845
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)) {
851 Map[xx][yy] =
852 (DoAnimation
853 ? (TINYEXP + Rand(2))
854 : SOMETINYEXP)
855 | ANIMBIT | BULLBIT;
856 }
857 }
858 }
859 }
860 }
861
862
863 /* comefrom: processWand */
864 put6x6Rubble(short x, short y)
865 {
866 register xx, yy, zz;
867
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)) {
873 Map[xx][yy] =
874 (DoAnimation
875 ? (TINYEXP + Rand(2))
876 : SOMETINYEXP)
877 | ANIMBIT | BULLBIT;
878 }
879 }
880 }
881 }
882 }
883
884
885 DidTool(SimView *view, char *name, short x, short y)
886 {
887 char buf[256];
888
889 if (view != NULL) {
890 sprintf(buf, "UIDidTool%s %s %d %d",
891 name, Tk_PathName(view->tkwin), x, y);
892 Eval(buf);
893 }
894 }
895
896
897 DoSetWandState(SimView *view, short state)
898 {
899 char buf[256];
900
901 sprintf(buf, "UISetToolState %s %d", Tk_PathName(view->tkwin), state);
902 Eval(buf);
903 }
904
905
906 /************************************************************************/
907 /* TOOLS */
908
909
910 int
911 query_tool(SimView *view, short x, short y)
912 {
913 if ((x < 0) || (x > (WORLD_X - 1)) ||
914 (y < 0) || (y > (WORLD_Y - 1))) {
915 return -1;
916 }
917
918 doZoneStatus(x, y);
919 DidTool(view, "Qry", x, y);
920 return 1;
921 }
922
923
924 int
925 bulldozer_tool(SimView *view, short x, short y)
926 {
927 unsigned short currTile, temp;
928 short zoneSize, deltaH, deltaV;
929 int result = 1;
930
931 if ((x < 0) || (x > (WORLD_X - 1)) ||
932 (y < 0) || (y > (WORLD_Y - 1))) {
933 return -1;
934 }
935
936 currTile = Map[x][y];
937 temp = currTile & LOMASK;
938
939 if (currTile & ZONEBIT) { /* zone center bit is set */
940 if (TotalFunds > 0) {
941 Spend(1);
942 switch (checkSize(temp)) {
943 case 3:
944 MakeSound("city", "Explosion-High");
945 put3x3Rubble(x, y);
946 break;
947
948 case 4:
949 put4x4Rubble(x, y);
950 MakeSound("city", "Explosion-Low");
951 break;
952
953 case 6:
954 MakeSound("city", "Explosion-High");
955 MakeSound("city", "Explosion-Low");
956 put6x6Rubble(x, y);
957 break;
958
959 default:
960 break;
961 }
962 }
963 } else if ((zoneSize = checkBigZone(temp, &deltaH, &deltaV))) {
964 if (TotalFunds > 0) {
965 Spend(1);
966 switch (zoneSize) {
967 case 3:
968 MakeSound("city", "Explosion-High");
969 break;
970
971 case 4:
972 MakeSound("city", "Explosion-Low");
973 put4x4Rubble(x + deltaH, y + deltaV);
974 break;
975
976 case 6:
977 MakeSound("city", "Explosion-High");
978 MakeSound("city", "Explosion-Low");
979 put6x6Rubble(x + deltaH, y + deltaV);
980 break;
981 }
982 }
983 } else {
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)) {
988 Spend(5);
989 }
990 } else {
991 result = 0;
992 }
993 } else {
994 result = ConnecTile(x, y, &Map[x][y], 1);
995 }
996 }
997 UpdateFunds();
998 if (result == 1) {
999 DidTool(view, "Dozr", x, y);
1000 }
1001 return result;
1002 }
1003
1004
1005 int
1006 road_tool(SimView *view, short x, short y)
1007 {
1008 int result;
1009
1010 if ((x < 0) || (x > (WORLD_X - 1)) ||
1011 (y < 0) || (y > (WORLD_Y - 1))) {
1012 return -1;
1013 }
1014
1015 result = ConnecTile(x, y, &Map[x][y], 2);
1016 UpdateFunds();
1017 if (result == 1) {
1018 DidTool(view, "Road", x, y);
1019 }
1020 return result;
1021 }
1022
1023
1024 int
1025 rail_tool(SimView *view, short x, short y)
1026 {
1027 int result;
1028
1029 if ((x < 0) || (x > (WORLD_X - 1)) ||
1030 (y < 0) || (y > (WORLD_Y - 1))) {
1031 return -1;
1032 }
1033
1034 result = ConnecTile(x, y, &Map[x][y], 3);
1035 UpdateFunds();
1036 if (result == 1) {
1037 DidTool(view, "Rail", x, y);
1038 }
1039 return result;
1040 }
1041
1042
1043 int
1044 wire_tool(SimView *view, short x, short y)
1045 {
1046 int result;
1047
1048 if ((x < 0) || (x > (WORLD_X - 1)) ||
1049 (y < 0) || (y > (WORLD_Y - 1))) {
1050 return -1;
1051 }
1052
1053 result = ConnecTile(x, y, &Map[x][y], 4);
1054 UpdateFunds();
1055 if (result == 1) {
1056 DidTool(view, "Wire", x, y);
1057 }
1058 return result;
1059 }
1060
1061
1062 int
1063 park_tool(SimView *view, short x, short y)
1064 {
1065 int result;
1066
1067 if ((x < 0) || (x > (WORLD_X - 1)) ||
1068 (y < 0) || (y > (WORLD_Y - 1)))
1069 return -1;
1070
1071 result = putDownPark(view, x, y);
1072 if (result == 1) {
1073 DidTool(view, "Park", x, y);
1074 }
1075 return result;
1076 }
1077
1078
1079 int
1080 residential_tool(SimView *view, short x, short y)
1081 {
1082 int result;
1083
1084 if ((x < 0) || (x > (WORLD_X - 1)) ||
1085 (y < 0) || (y > (WORLD_Y - 1))) {
1086 return -1;
1087 }
1088
1089 result = check3x3(view, x, y, RESBASE, residentialState);
1090 if (result == 1) {
1091 DidTool(view, "Res", x, y);
1092 }
1093 return result;
1094 }
1095
1096
1097 int
1098 commercial_tool(SimView *view, short x, short y)
1099 {
1100 int result;
1101
1102 if ((x < 0) || (x > (WORLD_X - 1)) ||
1103 (y < 0) || (y > (WORLD_Y - 1))) {
1104 return -1;
1105 }
1106
1107 result = check3x3(view, x, y, COMBASE, commercialState);
1108 if (result == 1) {
1109 DidTool(view, "Com", x, y);
1110 }
1111 return result;
1112 }
1113
1114
1115 int
1116 industrial_tool(SimView *view, short x, short y)
1117 {
1118 int result;
1119
1120 if ((x < 0) || (x > (WORLD_X - 1)) ||
1121 (y < 0) || (y > (WORLD_Y - 1))) {
1122 return -1;
1123 }
1124
1125 result = check3x3(view, x, y, INDBASE, industrialState);
1126 if (result == 1) {
1127 DidTool(view, "Ind", x, y);
1128 }
1129 return result;
1130 }
1131
1132
1133 int
1134 police_dept_tool(SimView *view, short x, short y)
1135 {
1136 int result;
1137
1138 if ((x < 0) || (x > (WORLD_X - 1)) ||
1139 (y < 0) || (y > (WORLD_Y - 1))) {
1140 return -1;
1141 }
1142
1143 result = check3x3(view, x, y, POLICESTBASE, policeState);
1144 if (result == 1) {
1145 DidTool(view, "Pol", x, y);
1146 }
1147 return result;
1148 }
1149
1150
1151 int
1152 fire_dept_tool(SimView *view, short x, short y)
1153 {
1154 int result;
1155
1156 if ((x < 0) || (x > (WORLD_X - 1)) ||
1157 (y < 0) || (y > (WORLD_Y - 1))) {
1158 return -1;
1159 }
1160
1161 result = check3x3(view, x, y, FIRESTBASE, fireState);
1162 if (result == 1) {
1163 DidTool(view, "Fire", x, y);
1164 }
1165 return result;
1166 }
1167
1168
1169 int
1170 stadium_tool(SimView *view, short x, short y)
1171 {
1172 int result;
1173
1174 if ((x < 0) || (x > (WORLD_X - 1)) ||
1175 (y < 0) || (y > (WORLD_Y - 1))) {
1176 return -1;
1177 }
1178
1179 result = check4x4(view, x, y, STADIUMBASE, 0, stadiumState);
1180 if (result == 1) {
1181 DidTool(view, "Stad", x, y);
1182 }
1183 return result;
1184 }
1185
1186
1187 int
1188 coal_power_plant_tool(SimView *view, short x, short y)
1189 {
1190 int result;
1191
1192 if ((x < 0) || (x > (WORLD_X - 1)) ||
1193 (y < 0) || (y > (WORLD_Y - 1))) {
1194 return -1;
1195 }
1196
1197 result = check4x4(view, x, y, COALBASE, 1, powerState);
1198 if (result == 1) {
1199 DidTool(view, "Coal", x, y);
1200 }
1201 return result;
1202 }
1203
1204
1205 int
1206 nuclear_power_plant_tool(SimView *view, short x, short y)
1207 {
1208 int result;
1209
1210 if ((x < 0) || (x > (WORLD_X - 1)) ||
1211 (y < 0) || (y > (WORLD_Y - 1))) {
1212 return -1;
1213 }
1214
1215 result = check4x4(view, x, y, NUCLEARBASE, 1, nuclearState);
1216 if (result == 1) {
1217 DidTool(view, "Nuc", x, y);
1218 }
1219 return result;
1220 }
1221
1222
1223 int
1224 seaport_tool(SimView *view, short x, short y)
1225 {
1226 int result;
1227
1228 if ((x < 0) || (x > (WORLD_X - 1)) ||
1229 (y < 0) || (y > (WORLD_Y - 1))) {
1230 return -1;
1231 }
1232
1233 result = check4x4(view, x, y, PORTBASE, 0, seaportState);
1234 if (result == 1) {
1235 DidTool(view, "Seap", x, y);
1236 }
1237 return result;
1238 }
1239
1240
1241 int
1242 airport_tool(SimView *view, short x, short y)
1243 {
1244 int result;
1245
1246 if ((x < 0) || (x > (WORLD_X - 1)) ||
1247 (y < 0) || (y > (WORLD_Y - 1))) {
1248 return -1;
1249 }
1250
1251 result = check6x6(view, x, y, AIRPORTBASE, airportState);
1252 if (result == 1) {
1253 DidTool(view, "Airp", x, y);
1254 }
1255 return result;
1256 }
1257
1258
1259 int
1260 network_tool(SimView *view, short x, short y)
1261 {
1262 int result;
1263
1264 if ((x < 0) || (x > (WORLD_X - 1)) ||
1265 (y < 0) || (y > (WORLD_Y - 1))) {
1266 return -1;
1267 }
1268
1269 result = putDownNetwork(view, x, y);
1270 if (result == 1) {
1271 DidTool(view, "Net", x, y);
1272 }
1273 return result;
1274 }
1275
1276
1277 #if 0
1278 int
1279 special_tool(SimView *view, short x, short y)
1280 {
1281 int result;
1282
1283 if ((x < 0) || (x > (WORLD_X - 1)) ||
1284 (y < 0) || (y > (WORLD_Y - 1))) {
1285 return -1;
1286 }
1287
1288 result = check3x3(view, x, y, specialBase, specialState);
1289 if (result == 1) {
1290 DidTool(view, "Special", x, y);
1291 }
1292 return result;
1293 }
1294 #endif
1295
1296 int
1297 ChalkTool(SimView *view, short x, short y, short color, short first)
1298 {
1299 if (first) {
1300 ChalkStart(view, x, y, color);
1301 } else {
1302 ChalkTo(view, x, y);
1303 }
1304 DidTool(view, "Chlk", x, y);
1305 return 1;
1306 }
1307
1308
1309 ChalkStart(SimView *view, int x, int y, int color)
1310 {
1311 Ink *ink;
1312 Ink **ip;
1313
1314 for (ip = &sim->overlay; *ip != NULL; ip = &((*ip)->next)) ;
1315
1316 *ip = ink = NewInk();
1317 ink->x = x; ink->y = y;
1318 ink->color = color;
1319 StartInk(ink, x, y);
1320 view->track_info = (char *)ink;
1321 view->last_x = x;
1322 view->last_y = y;
1323 view->tool_event_time = view->tool_last_event_time =
1324 ((TkWindow *)view->tkwin)->dispPtr->lastEventTime;
1325 }
1326
1327
1328 ChalkTo(SimView *view, int x, int y)
1329 {
1330 int x0, y0, lx, ly;
1331 Ink *ink = (Ink *)view->track_info;
1332
1333 #ifdef MOTIONBUFFER
1334 if (view->x->dpy->motion_buffer) {
1335 XTimeCoord *coords = NULL, *coord;
1336 int n = 0, i;
1337
1338 view->tool_last_event_time = view->tool_event_time;
1339 view->tool_event_time =
1340 ((TkWindow *)view->tkwin)->dispPtr->lastEventTime;
1341
1342 coords = XGetMotionEvents(view->x->dpy,
1343 Tk_WindowId(view->tkwin),
1344 view->tool_last_event_time,
1345 view->tool_event_time,
1346 &n);
1347 #if 0
1348 printf("got %d events at %x from %d to %d (%d elapsed)\n",
1349 n, coords,
1350 view->tool_last_event_time, view->tool_event_time,
1351 view->tool_event_time - view->tool_last_event_time);
1352 #endif
1353 if (n) {
1354 lx = ink->last_x; ly = ink->last_y;
1355
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;
1360 #if 0
1361 printf("adding %d %d => %d %d => %d %d\n",
1362 coord->x, coord->y, x0, y0, lx, ly);
1363 #endif
1364 AddInk(ink, lx, ly);
1365 }
1366 }
1367
1368 if (coords) {
1369 XFree((char *)coords);
1370 }
1371 }
1372 #endif
1373
1374 AddInk(ink, x, y);
1375 view->last_x = x;
1376 view->last_y = y;
1377 }
1378
1379
1380 int
1381 EraserTool(SimView *view, short x, short y, short first)
1382 {
1383 if (first) {
1384 EraserStart(view, x, y);
1385 } else {
1386 EraserTo(view, x, y);
1387 }
1388 DidTool(view, "Eraser", x, y);
1389 return 1;
1390 }
1391
1392
1393 InkInBox(Ink *ink, int left, int top, int right, int bottom)
1394 {
1395 if ((left <= ink->right) &&
1396 (right >= ink->left) &&
1397 (top <= ink->bottom) &&
1398 (bottom >= ink->top)) {
1399 int x, y, lx, ly, i;
1400
1401 if (ink->length == 1) {
1402 return 1;
1403 }
1404
1405 x = ink->x; y = ink->y;
1406 for (i = 1; i < ink->length; i++) {
1407 int ileft, iright, itop, ibottom;
1408
1409 lx = x; ly = y;
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) &&
1416 (right >= ileft) &&
1417 (top <= ibottom) &&
1418 (bottom >= itop)) {
1419 return 1;
1420 }
1421 }
1422 }
1423 return 0;
1424 }
1425
1426
1427 EraserStart(SimView *view, int x, int y)
1428 {
1429 EraserTo(view, x, y);
1430 }
1431
1432
1433 EraserTo(SimView *view, int x, int y)
1434 {
1435 SimView *v;
1436 Ink **ip, *ink;
1437
1438 for (ip = &sim->overlay; *ip != NULL;) {
1439 ink = *ip;
1440 if (InkInBox(ink, x - 8, y - 8, x + 8, y + 8)) {
1441
1442 for (view = sim->editor; view != NULL; view = view->next) {
1443 int vleft, vtop;
1444
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);
1451 }
1452 }
1453
1454 *ip = ink->next;
1455
1456 FreeInk(ink);
1457 } else {
1458 ip = &((*ip)->next);
1459 }
1460 }
1461 }
1462
1463
1464 int
1465 do_tool(SimView *view, short state, short x, short y, short first)
1466 {
1467 int result = 0;
1468
1469 switch (state) {
1470 case residentialState:
1471 result = residential_tool(view, x >>4, y >>4);
1472 break;
1473 case commercialState:
1474 result = commercial_tool(view, x >>4, y >>4);
1475 break;
1476 case industrialState:
1477 result = industrial_tool(view, x >>4, y >>4);
1478 break;
1479 case fireState:
1480 result = fire_dept_tool(view, x >>4, y >>4);
1481 break;
1482 case queryState:
1483 result = query_tool(view, x >>4, y >>4);
1484 break;
1485 case policeState:
1486 result = police_dept_tool(view, x >>4, y >>4);
1487 break;
1488 case wireState:
1489 result = wire_tool(view, x >>4, y >>4);
1490 break;
1491 case dozeState:
1492 result = bulldozer_tool(view, x >>4, y >>4);
1493 break;
1494 case rrState:
1495 result = rail_tool(view, x >>4, y >>4);
1496 break;
1497 case roadState:
1498 result = road_tool(view, x >>4, y >>4);
1499 break;
1500 case chalkState:
1501 result = ChalkTool(view, x - 5, y + 11, COLOR_WHITE, first);
1502 break;
1503 case eraserState:
1504 result = EraserTool(view, x, y, first);
1505 break;
1506 case stadiumState:
1507 result = stadium_tool(view, x >>4, y >>4);
1508 break;
1509 case parkState:
1510 result = park_tool(view, x >>4, y >>4);
1511 break;
1512 case seaportState:
1513 result = seaport_tool(view, x >>4, y >>4);
1514 break;
1515 case powerState:
1516 result = coal_power_plant_tool(view, x >>4, y >>4);
1517 break;
1518 case nuclearState:
1519 result = nuclear_power_plant_tool(view, x >>4, y >>4);
1520 break;
1521 case airportState:
1522 result = airport_tool(view, x >>4, y >>4);
1523 break;
1524 case networkState:
1525 result = network_tool(view, x >>4, y >>4);
1526 break;
1527
1528 default:
1529 result = 0;
1530 break;
1531 }
1532
1533 return result;
1534 }
1535
1536
1537 int
1538 current_tool(SimView *view, short x, short y, short first)
1539 {
1540 return do_tool(view, view->tool_state, x, y, first);
1541 }
1542
1543
1544 DoTool(SimView *view, short tool, short x, short y)
1545 {
1546 int result;
1547
1548 result = do_tool(view, tool, x <<4, y <<4, 1);
1549
1550 if (result == -1) {
1551 ClearMes();
1552 SendMes(34);
1553 MakeSoundOn(view, "edit", "UhUh");
1554 } else if (result == -2) {
1555 ClearMes();
1556 SendMes(33);
1557 MakeSoundOn(view, "edit", "Sorry");
1558 }
1559
1560 sim_skip = 0;
1561 view->skip = 0;
1562 InvalidateEditors();
1563 }
1564
1565
1566 ToolDown(SimView *view, int x, int y)
1567 {
1568 int result;
1569
1570 ViewToPixelCoords(view, x, y, &x, &y);
1571 view->last_x = x;
1572 view->last_y = y;
1573
1574 result = current_tool(view, x, y, 1);
1575
1576 if (result == -1) {
1577 ClearMes();
1578 SendMes(34);
1579 MakeSoundOn(view, "edit", "UhUh");
1580 } else if (result == -2) {
1581 ClearMes();
1582 SendMes(33);
1583 MakeSoundOn(view, "edit", "Sorry");
1584 } else if (result == -3) {
1585 DoPendTool(view, view->tool_state, x >>4, y >>4);
1586 }
1587
1588 sim_skip = 0;
1589 view->skip = 0;
1590 view->invalid = 1;
1591 }
1592
1593
1594 ToolUp(SimView *view, int x, int y)
1595 {
1596 int result;
1597
1598 result = ToolDrag(view, x, y);
1599
1600 return (result);
1601 }
1602
1603
1604 ToolDrag(SimView *view, int px, int py)
1605 {
1606 int x, y, dx, dy, adx, ady, lx, ly, dist;
1607 float i, step, tx, ty, dtx, dty, rx, ry;
1608
1609 ViewToPixelCoords(view, px, py, &x, &y);
1610 view->tool_x = x; view->tool_y = y;
1611
1612 if ((view->tool_state == chalkState) ||
1613 (view->tool_state == eraserState)) {
1614
1615 current_tool(view, x, y, 0);
1616 view->last_x = x; view->last_y = y;
1617
1618 } else {
1619
1620 dist = toolSize[view->tool_state];
1621
1622 x >>= 4; y >>= 4;
1623 lx = view->last_x >> 4;
1624 ly = view->last_y >> 4;
1625
1626 reset:
1627
1628 dx = x - lx;
1629 dy = y - ly;
1630
1631 if (dx == 0 && dy == 0) {
1632 return;
1633 }
1634
1635 adx = ABS(dx); ady = ABS(dy);
1636
1637 if (adx > ady) {
1638 step = .3 / adx;
1639 } else {
1640 step = .3 / ady;
1641 }
1642
1643 rx = (dx < 0 ? 1 : 0);
1644 ry = (dy < 0 ? 1 : 0);
1645
1646 if (dist == 1) {
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;
1650 dtx = ABS(tx - lx);
1651 dty = ABS(ty - ly);
1652 if (dtx >= 1 || dty >= 1) {
1653 /* fill in corners */
1654 if ((dtx >= 1) && (dty >= 1)) {
1655 if (dtx > dty) {
1656 current_tool(view, ((int)(tx + rx)) <<4, ly <<4, 0);
1657 } else {
1658 current_tool(view, lx <<4, ((int)(ty + ry)) <<4, 0);
1659 }
1660 }
1661 lx = (int)(tx + rx);
1662 ly = (int)(ty + ry);
1663 current_tool(view, lx <<4, ly <<4, 0);
1664 }
1665 }
1666 } else {
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;
1670 dtx = ABS(tx - lx);
1671 dty = ABS(ty - ly);
1672 lx = (int)(tx + rx);
1673 ly = (int)(ty + ry);
1674 current_tool(view, lx <<4, ly <<4, 0);
1675 }
1676 }
1677
1678 view->last_x = (lx <<4) + 8;
1679 view->last_y = (ly <<4) + 8;
1680 }
1681 sim_skip = 0; /* update editors overlapping this one */
1682 view->skip = 0;
1683 view->invalid = 1;
1684 }
1685
1686
1687 DoPendTool(SimView *view, int tool, int x, int y)
1688 {
1689 char buf[256];
1690
1691 sprintf(buf, "DoPendTool %s %d %d %d",
1692 Tk_PathName(view->tkwin), tool, x, y);
1693 Eval(buf);
1694 }
Impressum, Datenschutz