|
|
1.1 root 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 [email protected].
8: *
9: * This program is free software: you can redistribute it and/or modify
10: * it under the terms of the GNU General Public License as published by
11: * the Free Software Foundation, either version 3 of the License, or (at
12: * your option) any later version.
13: *
14: * This program is distributed in the hope that it will be useful, but
15: * WITHOUT ANY WARRANTY; without even the implied warranty of
16: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17: * General Public License for more details. You should have received a
18: * copy of the GNU General Public License along with this program. If
19: * not, see <http://www.gnu.org/licenses/>.
20: *
21: * ADDITIONAL TERMS per GNU GPL Section 7
22: *
23: * No trademark or publicity rights are granted. This license does NOT
24: * give you any right, title or interest in the trademark SimCity or any
25: * other Electronic Arts trademark. You may not distribute any
26: * modification of this program using the trademark SimCity or claim any
27: * affliation or association with Electronic Arts Inc. or its employees.
28: *
29: * Any propagation or conveyance of this program must include this
30: * copyright notice and these terms.
31: *
32: * If you convey this program (or any modifications of it) and assume
33: * contractual liability for the program to recipients of it, you agree
34: * to indemnify Electronic Arts for any liability that those contractual
35: * assumptions impose on Electronic Arts.
36: *
37: * You may not misrepresent the origins of this program; modified
38: * versions of the program must be marked as such and not identified as
39: * the original program.
40: *
41: * This disclaimer supplements the one included in the General Public
42: * License. TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, THIS
43: * PROGRAM IS PROVIDED TO YOU "AS IS," WITH ALL FAULTS, WITHOUT WARRANTY
44: * OF ANY KIND, AND YOUR USE IS AT YOUR SOLE RISK. THE ENTIRE RISK OF
45: * SATISFACTORY QUALITY AND PERFORMANCE RESIDES WITH YOU. ELECTRONIC ARTS
46: * DISCLAIMS ANY AND ALL EXPRESS, IMPLIED OR STATUTORY WARRANTIES,
47: * INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY, SATISFACTORY QUALITY,
48: * FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT OF THIRD PARTY
49: * RIGHTS, AND WARRANTIES (IF ANY) ARISING FROM A COURSE OF DEALING,
50: * USAGE, OR TRADE PRACTICE. ELECTRONIC ARTS DOES NOT WARRANT AGAINST
51: * INTERFERENCE WITH YOUR ENJOYMENT OF THE PROGRAM; THAT THE PROGRAM WILL
52: * MEET YOUR REQUIREMENTS; THAT OPERATION OF THE PROGRAM WILL BE
53: * UNINTERRUPTED OR ERROR-FREE, OR THAT THE PROGRAM WILL BE COMPATIBLE
54: * WITH THIRD PARTY SOFTWARE OR THAT ANY ERRORS IN THE PROGRAM WILL BE
55: * CORRECTED. NO ORAL OR WRITTEN ADVICE PROVIDED BY ELECTRONIC ARTS OR
56: * ANY AUTHORIZED REPRESENTATIVE SHALL CREATE A WARRANTY. SOME
57: * JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF OR LIMITATIONS ON IMPLIED
58: * WARRANTIES OR THE LIMITATIONS ON THE APPLICABLE STATUTORY RIGHTS OF A
59: * CONSUMER, SO SOME OR ALL OF THE ABOVE EXCLUSIONS AND LIMITATIONS MAY
60: * NOT APPLY TO YOU.
61: */
62: #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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.