|
|
1.1 root 1: /* terra.c: Terrain editor
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:
63: /* terra.c - terrain editor for Sim City
64: by Paul Schmidt, 1989
65: Raxsoft, Inc.
66: 1194 Spring Valley Commons
67: Livermore, CA 94550
68: (415) 449-9079
69: */
70:
71: #include "..\sim\sim.h"
72: #include "..\gr\menu.h"
73: #include "..\gr\grdef.h"
74: #include "..\terra\tmenu.h"
75: #include "..\ed\eddef.h"
76: #include "..\ed\edext.h"
77: #include <setjmp.h>
78: #include <dos.h>
79: #include <stdio.h>
80: #include <fcntl.h>
81: #include <sys\types.h>
82: #include <sys\stat.h>
83: #include <direct.h>
84:
85: char *GSaveRect();
86:
87: extern MOUSESTATE near mouse_state;
88: extern FILE *demoFP;
89: extern char realMouseFlag;
90:
91: extern long lastEvent, TickCount(); /* from ..\sim\main.c */
92: extern long policeFund, fireFund, transFund;
93:
94: char CreateWithIsland;
95:
96: #define UMaps 4
97: #define URecs 5000
98: int UndoMapBuffer1[WORLD_X*WORLD_Y];
99: int UndoMapBuffer2[WORLD_X*WORLD_Y];
100: int UndoMapBuffer3[WORLD_X*WORLD_Y];
101: int UndoMapBuffer4[WORLD_X*WORLD_Y];
102: int *UndoMap[UMaps]={UndoMapBuffer1,UndoMapBuffer2,UndoMapBuffer3,UndoMapBuffer4}; /* maps for fill undos */
103: int UndoMaps; /* number of occupied undo maps */
104: struct {
105: char x,y; /* coordinate of undo */
106: int val; /* cell value */
107: } UndoRec[URecs]; /* putdown undos */
108: int UndoHead=0,UndoTail=0;
109:
110: char fillState=0; /* flag telling if fill mode is on or off */
111:
112: int treeLevel=50; /* level for tree creation */
113: int lakeLevel=50; /* level for lake creation */
114: int curvLevel=50; /* level for river curviness */
115:
116: /* ========================================================== */
117:
118: void ClearUndo() /* clear all undo records */
119: {
120: UndoMaps=UndoHead=UndoTail=0; /* kill undo pointers */
121: DrawAllEdIcons(UPDATE); /* update undo icon */
122: }
123:
124: void AddUndo(pos) /* add undo record */
125: Point pos; /* position to add to undo */
126: {
127:
128: if(pos.h != -1 || pos.v != -1) { /* if they're not setting to undo the entire map */
129: if(pos.h > WORLD_X || pos.v > WORLD_Y || pos.h < 0 || pos.v < 0) { /* if out of bounds */
130: return; /* do nothing */
131: }
132: }
133: if(pos.h == -1 && pos.v == -1) { /* if undo entire map */
134: register int tem; /* temporary counter */
135: register int x,y; /* temporary coordinates */
136:
137: if(UndoMaps == UMaps) { /* if there are already five undo maps */
138: while(UndoRec[UndoTail].x != -1 || UndoRec[UndoTail].y != -1) { /* until we find the last map undo */
139: UndoTail=Bound(0,UndoTail+1,URecs-1); /* move tail */
140: }
141: UndoTail=Bound(0,UndoTail+1,URecs-1); /* move tail to kill the last map */
142: UndoMaps--;
143: for(tem=0;tem < UndoMaps;tem++) { /* for each map */
144: for(x=0;x < WORLD_X*WORLD_Y;x++) {
145: *(UndoMap[tem]+x)=*(UndoMap[tem+1]+x);
146: }
147: }
148: }
149: for(x=0;x < WORLD_X*WORLD_Y;x++) {
150: *(UndoMap[UndoMaps]+x)=*((int*)Map+x); /* save current map */
151: }
152: UndoMaps++; /* one more map saved */
153: }
154: UndoRec[UndoHead].x=pos.h; /* set x and y position */
155: UndoRec[UndoHead].y=pos.v;
156: UndoRec[UndoHead].val=Map[pos.h][pos.v]; /* set map value */
157: UndoHead=Bound(0,UndoHead+1,URecs-1); /* move head */
158: if(UndoHead == UndoTail) { /* if we pushed the tail up */
159: UndoTail=Bound(0,UndoTail+1,URecs-1); /* move tail */
160: }
161: }
162:
163: void Undo() /* undo one map operation */
164: {
165: register int x,y;
166:
167: if(UndoHead == UndoTail) { /* if there's nothing to undo */
168: MakeSound(7); /* bad sound */
169: return; /* do nothing */
170: }
171: UndoHead=Bound(0,UndoHead-1,URecs-1); /* set new head */
172: if(UndoRec[UndoHead].x == -1) { /* if the entire map changed */
173: register int tem; /* temporary counter */
174: register int x,y; /* temporary coordinates */
175:
176: for(x=0;x < WORLD_X*WORLD_Y;x++) {
177: *((int*)Map+x)=*(UndoMap[UndoMaps-1]+x); /* set undo map */
178: }
179: UndoMaps--; /* one less map */
180: } else {
181: Map[UndoRec[UndoHead].x][UndoRec[UndoHead].y]=UndoRec[UndoHead].val; /* set old value */
182: }
183:
184: UpdateOurMaps(); /* update big and small maps */
185: }
186:
187: /* ======================================================================== */
188:
189: DoEvent()
190: {
191:
192: int object;
193: EVENT event;
194:
195: #if DEBUG && 0
196: PrintLock("DoEvent - get event ");
197: #endif
198: GetMouseEvent(&event);
199: object=event.object;
200: #if DEBUG && 0
201: PrintLock("DoEvent ");
202: #endif
203:
204: switch(object&0xff00)
205: {
206: case 0: DoMenu(object);
207: break;
208: case 0x100:
209: DoEdEvent(&event);
210: break;
211: case 0x200:
212: DoKeyDown(object);
213: break;
214: case 0x300:
215: MenuEvent(&event);
216: break;
217: case 0x400:
218: DoMapEvent(&event);
219: break;
220: case 0x600:
221: DoScreen(&event);
222: break;
223: }
224: }
225:
226: UpdateOurSmallMap() /* update small map */
227: {
228: register int tem; /* temporary counter */
229:
230: MouseHide(); /* hide mouse */
231: DrawSmallMap(); /* updates small map */
232: for(tem=0;tem < WORLD_X*WORLD_Y;tem++) {
233: *((int*)lastSmallMap+tem)=(*((int*)Map+tem))&LOMASK; /* copy map */
234: }
235: MouseShow(); /* show mouse */
236: }
237:
238: UpdateOurMaps() /* update edit and map widnows */
239: {
240: UpdateMapCursorOff(); /* turn off map cursor */
241: MouseHide(); /* hide mouse */
242: DrawBigMap(); /* updates large map */
243: MouseShow(); /* show mouse */
244: UpdateOurSmallMap();
245: DrawAllEdIcons(UPDATE); /* update icons */
246: UpdateMapCursorOn(); /* turn map cursor on */
247: }
248:
249: /* ======================================================================== */
250: DoMenu(itemNum)
251: int itemNum;
252: {
253: static char far *popGameLevelStrs[]={"Easy","Medium","Hard",NULL};
254: int cur_windowActive; /* current active window */
255: register int x,y; /* temporary integers */
256: Rect msgBox;
257: Rect msgRect;
258: char *savePtr; /* pointer to saved rectangle */
259: int smoothFlag;
260: long tmpFunds;
261: int virginCity=YES;
262:
263: switch(itemNum)
264: {
265: /* case MNUSCNO:
266: /* /* Load a scenario - if it fails we need to redraw the */
267: /* /* screen */
268: /* if (!LoadScenario()) {
269: /* InitWindows();
270: /* } else {
271: /* ClearUndo(); /* clear undo records */
272: /* }
273: /* SelectNewWindow(EDWINDOW); /* enable edit window */
274: /* SelectNewWindow(MAPWINDOW); /* enable map window */
275: /* break; /**/
276: case MNUQUIT:
277: if (Verify("EXIT"))
278: Quit("Micropolis Terrain Editor");
279: break;
280: case MNU_SoundToggle: /* sound on/off */
281: userSoundOn^=YES;
282: sso:
283: ShowSelectedOptions();
284: break;
285: case MNUABOUT:
286: DoAbout();
287: break;
288: case MNULOAD:
289: if (LoadGame(NULL,NO))
290: virginCity=NO;
291: SelectNewWindow(EDWINDOW); /* enable edit window */
292: SelectNewWindow(MAPWINDOW); /* enable map window */
293: ClearUndo(); /* clear undo records */
294: break;
295: case MNUSAVE:
296: SaveGame(lastFileName);
297: break;
298: case MNUSVAS:
299: SaveGame(NULL);
300: break;
301: case MNUNEW: /* Start new game */
302: if (Verify("NEW GAME")) {
303: totalFunds=20000L;
304: NewGame(NO);
305: transFund=policeFund=fireFund=65535L;
306: CityTax=7;
307: virginCity=YES;
308: ClearUndo(); /* clear undo records */
309: }
310: SelectNewWindow(EDWINDOW); /* enable edit window */
311: SelectNewWindow(MAPWINDOW); /* enable map window */
312: break;
313: case MNUPRINT:
314: PrintCity();
315: break;
316: case MNU_SmoothTrees:
317: smoothFlag=1;
318: goto dosmooth;
319: case MNU_ClearMap: /* if map is to be cleared */
320: AddUndo(-1,-1); /* save map */
321: rax_ClearMap(); /* clear map (..\sim\mapgener.c) */
322: GameLevel=0; /* assume game is easy */
323: goto updateBoth;
324: break;
325: case MNU_ClearUnnatural: /* if unnatural objects are to be cleared */
326: AddUndo(-1,-1); /* save map */
327: for(x=0;x < WORLD_X;x++) {
328: for(y=0;y < WORLD_Y;y++) {
329: if((Map[x][y]&LOMASK) > 37) { /* get rid of everything unnatural */
330: Map[x][y]=0; /* turn it into dirt */
331: }
332: }
333: }
334: updateBoth:
335: UpdateOurMaps(); /* update both windows */
336: break;
337: case MNU_GenerateRandom: /* if random map is to be generated */
338: if(SetTerrainParameters()) { /* allow user to set terrain generation parameters */
339: CenterRect(&msgBox, 20, 5);
340: msgRect=*AdjRect(&msgBox);
341: savePtr=GSaveRect(&msgRect); /* save rectangle */
342: GRectFill(&msgRect, WHITE|PWHITE);
343: GSetAttrib(DGREEN, DGREEN, PBLACK);
344: GRectOutline(&msgRect, 4);
345: GSetAttrib(LGREEN, LGREEN, PMGREY);
346: GRectOutline(&msgRect, 2);
347: GSetAttrib(DBLUE, WHITE, PWHITE|PINV);
348: CenterPrint(&msgBox, msgBox.top+2, "Now terraforming");
349:
350: AddUndo(-1,-1); /* save map */
351: rax_ClearMap(); /* make river map */
352: rax_GetRandStart();
353: if(CreateWithIsland) { /* if we're creating an island */
354: rax_MakeIsland(); /* make an island */
355: }
356: if(curvLevel) { /* if we're supposedly creating an island */
357: rax_DoRivers(); /* create river */
358: }
359: if(lakeLevel) { /* if there are to be lakes */
360: rax_MakeLakes(); /* add lakes */
361: }
362: rax_SmoothRiver(); /* smooth out river */
363: if(treeLevel) { /* if we're creating a woodsy terrain */
364: rax_DoTrees(); /* add trees */
365: }
366: rax_SmoothTrees(); /* smooth trees */
367: rax_SmoothTrees(); /* smooth trees */
368:
369: GRestoreRect(&msgRect,savePtr); /* restore rectangle */
370: MapX=MapY=0;
371: goto updateBoth;
372: }
373: break;
374: case MNU_SmoothRiver: /* if water is to be smoothed */
375: smoothFlag=2;
376: goto dosmooth;
377: case MNU_SmoothBoth: /* if both are to be smoothed */
378: smoothFlag=3; /* Both */
379: dosmooth:
380: CenterRect(&msgBox, 16, 5);
381: msgRect=*AdjRect(&msgBox);
382: savePtr=GSaveRect(&msgRect); /* save rectangle */
383: GRectFill(&msgRect, WHITE|PWHITE);
384: GSetAttrib(DGREEN, DGREEN, PBLACK);
385: GRectOutline(&msgRect, 4);
386: GSetAttrib(LGREEN, LGREEN, PMGREY);
387: GRectOutline(&msgRect, 2);
388: GSetAttrib(DBLUE, WHITE, PWHITE|PINV);
389: CenterPrint(&msgBox, msgBox.top+2, "Smoothing...");
390:
391: AddUndo(-1,-1); /* save map */
392: if (smoothFlag & 2) /* If water smooth flag set */
393: {
394: rax_WaterEdges(); /* make sure water edges are ok */
395: rax_SmoothRiver();
396: }
397: if (smoothFlag & 1)
398: {
399: rax_SmoothTrees();
400: rax_SmoothTrees();
401: }
402:
403: GRestoreRect(&msgRect,savePtr); /* restore rectangle */
404: goto updateBoth;
405:
406: case MNU_RandomIsland: /* if random Island toggle */
407: CreateWithIsland^=1; /* toggle state of flag */
408: ShowSelectedOptions(); /* update menu flag status */
409: break;
410:
411: case MNU_GameLevel: /* if game level */
412: /* GameLevel++; /* add one for PopUpMenuBox */
413: /* PopUpMenuBox(&GameLevel, popGameLevelStrs);
414: /* GameLevel--; /**/
415:
416: tmpFunds=totalFunds; /* Don't alter the amount of funds! */
417: ChooseGameLevel(); /* get city name & level from user */
418: if (!virginCity)
419: totalFunds=tmpFunds;
420: NewName(); /* set the name of the city */
421: break;
422: case MNU_GameYear: /* if game year */
423: SetGameYear(); /* allow user to set the game year */
424: break;
425:
426: case MNU_EditWindow: /* if edit window */
427: SelectNewWindow(EDWINDOW); /* bring the edit window to the foreground */
428: break;
429: case MNU_MapWindow: /* if map window */
430: SelectNewWindow(MAPWINDOW); /* bring the map window to the foreground */
431: break;
432:
433: default:
434: /* unimplemented option */
435: break;
436: }
437: }
438:
439: long messageTime;
440:
441: DoEdEvent(ePtr)
442: EVENT *ePtr;
443: {
444: int object;
445:
446: object=ePtr->object&0xff;
447:
448: if (object & 0xf0)
449: { /* Must be an icon */
450: SetWandState(object&0xf, YES);
451: }
452: switch (object)
453: {
454: case 0: DoEdMapEvent(ePtr);
455: break;
456: case 2: DoMoveWindow(ePtr, edWinList);
457: break;
458: case 8: ResizeEdWindow(ePtr);
459: break;
460: }
461: }
462:
463: /* ======================================================================== */
464: DoMapEvent(ePtr)
465: EVENT *ePtr;
466: {
467: int object;
468:
469: object=ePtr->object&0xff;
470:
471: {
472: switch (object)
473: { case 0: DoMapWindowEvent(ePtr); /* move locus of edit window */
474: break;
475: case 2: DoMoveMap(ePtr); /* move window */
476: break;
477: }
478: }
479: }
480:
481: void EditTerra() /* main program entry point */
482: {
483: int updateWait=0, updateWait2=0;
484:
485: CreateWithIsland=0;
486: ShowSelectedOptions(); /* update menu flag status */
487: GameLevel=0; /* assume game is easy */
488: totalFunds=20000L;
489: transFund=policeFund=fireFund=65535L;
490: CityTax=7;
491:
492: EnableMenus(); /* make sure menus are enabled */
493: for (;;)
494: {
495: long lastMapCursor; /* time value for map window cursor flashing */
496:
497: if (WaitedEnough(&lastMapCursor,2))
498: { /* if we should flash the map cursor */
499: UpdateMapCursor(); /* update the map cursor */
500: }
501:
502:
503: if (!menuActive) /* if no menus are active */
504: {
505: char moveFlag;
506: if (CheckKeyState(CNTRLSCAN)) /* Is the control key hit? */
507: {
508: int dx, dy;
509: dx=joyMoveX;
510: dy=joyMoveY;
511:
512: if (CheckKeyState(HOMESCAN)) /* Home arrow */
513: { dx--; dy--;
514: }
515: if (CheckKeyState(PGUPSCAN)) /* PgUp arrow */
516: { dx++; dy--;
517: }
518: if (CheckKeyState(ENDSCAN)) /* End arrow */
519: { dx--; dy++;
520: }
521: if (CheckKeyState(PGDNSCAN)) /* PgDn arrow */
522: { dx++; dy++;
523: }
524: if (CheckKeyState(RIGHTSCAN)) /* Right arrow */
525: dx++;
526: if (CheckKeyState(LEFTSCAN)) /* Left arrow */
527: dx--;
528: if (CheckKeyState(UPSCAN)) /* Up arrow */
529: dy--;
530: if (CheckKeyState(DOWNSCAN)) /* Down arrow */
531: dy++;
532: if (dx || dy)
533: {
534: DisableMenus();
535: freeze=YES;
536: EdScroll(dx,dy);
537: freeze=NO;
538: }
539: }
540: if (!ScrollLock())
541: {
542: moveagn:
543: moveFlag=NO;
544: if (mouse_state.x <= 1)
545: {
546: if (MapX > 0)
547: {
548: MapX--;
549: moveFlag=YES;
550: }
551: } else if (mouse_state.x >= screenWidth-6)
552: {
553: if (MapX+edWinWid < WORLD_X)
554: {
555: MapX++;
556: moveFlag=YES;
557: }
558: }
559: if (mouse_state.y < 1 )
560: {
561: if (MapY > 0)
562: {
563: MapY--;
564: moveFlag=YES;
565: }
566: }
567: else if (mouse_state.y >= screenHeight-6)
568: {
569: if (MapY+edWinLen < WORLD_Y)
570: {
571: MapY++;
572: moveFlag=YES;
573: }
574: }
575:
576: if (moveFlag == YES)
577: {
578: DisableMenus(); /* locks to current process */
579: newMapFlags[CYMAP]=0;
580: DrawBigMap();
581: #if 0
582: DrawObjects();
583: #endif
584: EnableMenus();
585: goto moveagn;
586: }
587:
588: } /* End of "if (!ScrollLock" */
589: } /* End if if (!menuActive) */
590: if (KBHit() || CheckMouseEvents()) /* if an event happened */
591: {
592: DisableMenus();
593: while(KBHit())
594: { DoKey();
595: }
596: while (CheckMouseEvents())
597: { DoEvent();
598: }
599: lastEvent=TickCount();
600: }
601: if (simSpeed == 0)
602: {
603: if (WaitedEnough(&updateWait, 18*3))
604: { DisableMenus();
605: UpdateEdWindow();
606: }
607: }
608: #if DEBUGINI
609: OutStr("\nMAIN: re-enable");
610: #endif
611:
612: EnableMenus(); /* Make sure the menus are enabled */
613: copyOK=YES;
614: #if DEBUGINI
615: OutStr("\nMAIN: copyok, pass");
616: #endif
617: Pass();
618: copyOK=NO;
619: #if DEBUGINI
620: OutStr("\nMAIN: copy not OK");
621: #endif
622: }
623: }
624:
625: SetGameYear() /* get game year */
626: {
627: Rect verBox;
628: static char *label="Enter Game Year:"; /* label for window */
629:
630: char dateBuffer[10]; /* buffer for date */
631: EVENT event;
632: char *savePtr;
633: int len, x, y, i,c, optLens[8];
634: Rect tmpBox;
635: Size strSize;
636: const char **optPtr;
637: int posIndex=(-1);
638: long tmpTime;
639:
640: FlushKeys();
641:
642: CenterRect(&verBox,18,5);
643:
644: tmpBox=*AdjRect(&verBox);
645: savePtr=GSaveRect(&tmpBox);
646:
647: GRectFill(&tmpBox,BUDGFC+PMGREY);
648: GSetAttrib(BUDGBC,BUDGBC,PWHITE);
649: GRectOutline(&tmpBox, 4);
650: /* Outline outline in BLACK */
651: GSetAttrib(BLACK,BLACK,PBLACK);
652: GRectOutline(&tmpBox,1);
653: GSetAttrib(BUDGBC,BUDGFC,PINV|PWHITE);
654: PrintRectLines(&verBox,verBox.top,label);
655: i=20;
656: x=verBox.left+i;
657: y=verBox.bottom-2;
658: GSetAttrib(BUDGBC,BUDBOXC,PINV|PWHITE);
659:
660: /* GSetAttrib(BUDGBC,BUDBOXC,0); */
661: /* TempFullScreenCursor(); */
662:
663: sprintf(dateBuffer,"%4d",(CityTime/48)+1900); /* set date */
664: GetStrSetNum(); /* Numbers only */
665: GetStrn(verBox.left+6,verBox.top+3,dateBuffer,5,1); /* allow user to edit the date and set eos */
666: GetStrSetAll(); /* allow any alphnum input */
667: if(strlen(dateBuffer) == 4) { /* if they entered a good date */
668: tmpTime=(atoi(dateBuffer)-1900)*48L; /* set new date */
669: if (tmpTime > 0)
670: CityTime=tmpTime;
671: } else { /* if not the correct length */
672: MakeSound(7); /* this should be CANTSND for bad date */
673: }
674: for(i=0;i < 100;i++) { /* kill any and all events */
675: GetMouseEvent(&event); /* get event */
676: }
677: /* RemoveTempCursor(); */
678: GRestoreRect(&tmpBox,savePtr);
679: DoDate(); /* update the date in the edit window */
680: }
681:
682: int PSBound(a,n,b) /* return number between a and b */
683: {
684: if(n < a) n=a;
685: if(n > b) n=b;
686: return n;
687: }
688:
689: /* here is the concept for SetTerrainParameters():
690: ZDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD?
691: 3 3
692: 3 Terrain Creation Parameters 3
693: 3 3
694: 3 Number Number River 3
695: 3 of Trees of Lakes Curviness 3
696: 3 3
697: 3 xxx% xxx% xxx% 3
698: 3 3
699: 3 ZDDDDDDDD? ZDDDDDDDD? 3
700: 3 3 Go 3 3 Cancel 3 3
701: 3 @DDDDDDDDY @DDDDDDDDY 3
702: @DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDY
703: */
704: SetTerrainParameters() /* allow user to set up terrain grneration parameters */
705: {
706: char *savePtr; /* pointer to saved screen data */
707: char temStr[20]; /* temporary string for percentages */
708: EVENT event; /* temporary event */
709: int atButton=0; /* current button we're at */
710: int buttonDown=0; /* flag telling if mouse button is down */
711: int goFlag=0; /* flag telling if terrain is to be generated */
712: long startTime; /* temporary timer value */
713: int tem; /* temporary counter */
714: int x,y; /* temporary positions */
715: Rect wRect; /* rectangle showing extents of window */
716: Rect tmpRect; /* temporary rectangle for adjusted window rectangle */
717: Point buttonPos[8]; /* positions of buttons */
718:
719: FlushKeys(); /* do something...flush keyboard buffer? */
720:
721: CenterRect(&wRect,36,10); /* center our window */
722:
723: tmpRect=*AdjRect(&wRect);
724: savePtr=GSaveRect(&tmpRect);
725:
726: GRectFill(&tmpRect,BUDGFC+PMGREY);
727: GSetAttrib(BUDGBC,BUDGBC,PWHITE);
728: GRectOutline(&tmpRect,4);
729: /* Outline outline in BLACK */
730: GSetAttrib(BLACK,BLACK,PBLACK);
731: GRectOutline(&tmpRect,1);
732: GSetAttrib(BUDGBC,BUDGFC,PINV|PWHITE);
733: PrintRectLines(&wRect,wRect.top,"Terrain Creation Parameters");
734: x=(wRect.left+2)*8;
735: y=(wRect.top+2)*fontHeight;
736: GPPrintf(x+(1*8),y+(1*fontHeight)-3," Number Number River ");
737: GPPrintf(x+(1*8),y+(2*fontHeight)-3,"of Trees of Lakes Curviness");
738:
739: buttonPos[0].h=wRect.left+3; /* positions of buttons */
740: buttonPos[1].h=wRect.left+10;
741: buttonPos[2].h=wRect.left+14;
742: buttonPos[3].h=wRect.left+21;
743: buttonPos[4].h=wRect.left+25;
744: buttonPos[5].h=wRect.left+32;
745: for(tem=0;tem < 6;tem++) {
746: buttonPos[tem].v=wRect.top+5; /* set vertical position */
747: }
748: buttonPos[6].h=wRect.left+3;
749: buttonPos[7].h=wRect.left+25;
750: buttonPos[6].v=buttonPos[7].v=wRect.top+8;
751:
752: GSetAttrib(BUDGBC,BUDBOXC,PINV|PWHITE);
753: for(tem=0;tem < 3;tem++) { /* for each set of value buttons */
754: AddTextButton(buttonPos[tem*2],"",0x800+tem*2); /* add button */
755: AddTextButton(buttonPos[tem*2+1],"",0x801+tem*2); /* add button */
756: }
757: AddTextButton(buttonPos[6]," Go ",0x806); /* add 'go' button */
758: AddTextButton(buttonPos[7]," Cancel ",0x807); /* add 'cancel' button */
759:
760: /* output initial values */
761: GSetAttrib(BUDGBC,BUDGFC,PINV|PWHITE);
762: sprintf(temStr,"%3d%%%%",treeLevel); /* get string for tree level */
763: GPPrintf(x+(3*8),y+(3*fontHeight),temStr); /* output string */
764: sprintf(temStr,"%3d%%%%",lakeLevel); /* get string for lake level */
765: GPPrintf(x+(14*8),y+(3*fontHeight),temStr); /* output string */
766: sprintf(temStr,"%3d%%%%",curvLevel); /* get string for curviness level */
767: GPPrintf(x+(25*8),y+(3*fontHeight),temStr); /* output string */
768:
769: /* GSetAttrib(BUDGBC,BUDBOXC,0); */
770: TempFullScreenCursor(); /* give us a cursor */
771:
772: while(1) { /* until break */
773: if(0) { /* never unless below code calls it */
774: repos:
775: SetMouseAtButton(atButton+0x800);
776: }
777: while (KBHit()) /* Clear any keys pressed */
778: {
779: switch (GetECH())
780: { case 27: /* if escape */
781: case 'C': /* (or 'cancel') */
782: case 'c':
783: goFlag=0; /* don't create random terrain */
784: goto xit;
785: case 13: /* if carriage return */
786: case 'G': /* (or 'go') */
787: case 'g':
788: goFlag=1; /* create random terrain */
789: goto xit;
790: case '+': atButton=((atButton+1) % 8); /* for each button */
791: goto repos;
792: case '-':
793: atButton=(atButton)?(atButton-1):7;
794: goto repos;
795: }
796: }
797: if(CheckMouseEvents()) { /* if there's an activity */
798: GetMouseEvent(&event); /* get event */
799: downAgain:
800: switch(event.object) { /* get event id */
801: case 0x800: /* if - trees */
802: treeLevel=PSBound(0,treeLevel-1,100);
803: goto updateValues; /* update values */
804: case 0x801: /* if + trees */
805: treeLevel=PSBound(0,treeLevel+1,100);
806: goto updateValues; /* update values */
807: case 0x802: /* if - lakes */
808: lakeLevel=PSBound(0,lakeLevel-1,100);
809: goto updateValues; /* update values */
810: case 0x803: /* if + lakes */
811: lakeLevel=PSBound(0,lakeLevel+1,100);
812: goto updateValues; /* update values */
813: case 0x804: /* if - curviness */
814: curvLevel=PSBound(0,curvLevel-1,100);
815: goto updateValues; /* update values */
816: case 0x805: /* if + curviness */
817: curvLevel=PSBound(0,curvLevel+1,100);
818: goto updateValues; /* update values */
819: case 0x806: /* if 'go' */
820: goFlag=1; /* return flag telling to create terrain */
821: break;
822: case 0x807: /* if 'cancel' */
823: goFlag=0; /* return flag telling to create terrain */
824: break;
825: }
826: if(0) { /* only if above code calls us */
827: updateValues:
828: RemoveTempCursor(); /* remove cursor from screen */
829: GSetAttrib(BUDGBC,BUDGFC,PINV|PWHITE);
830: sprintf(temStr,"%3d%%%%",treeLevel); /* get string for tree level */
831: GPPrintf(x+(3*8),y+(3*fontHeight),temStr); /* output string */
832: sprintf(temStr,"%3d%%%%",lakeLevel); /* get string for lake level */
833: GPPrintf(x+(14*8),y+(3*fontHeight),temStr); /* output string */
834: sprintf(temStr,"%3d%%%%",curvLevel); /* get string for curviness level */
835: GPPrintf(x+(25*8),y+(3*fontHeight),temStr); /* output string */
836: TempFullScreenCursor(); /* put cursor back */
837: if(!buttonDown) { /* if button was not down */
838: buttonDown=1; /* set button down flag */
839: startTime=TickCount(); /* get current time */
840: while(StillDown()) { /* while a button is down */
841: if(TickCount()-startTime > 5) { /* if autorepeat is up */
842: goto downAgain;
843: }
844: }
845: buttonDown=0; /* button is no longer down */
846: } else { /* if button is already down */
847: if(StillDown()) { /* if button is still down */
848: startTime=TickCount(); /* get current time */
849: while(startTime == TickCount()) ; /* wait for 1/18th of a second */
850: goto downAgain;
851: }
852: buttonDown=0; /* no button is down */
853: }
854: }
855: if(event.object == 0x806 || event.object == 0x807) { /* if one of the exit buttons */
856: xit:
857: break; /* exit loop */
858: }
859: }
860: }
861:
862: for(tem=0x800;tem <= 0x809;tem++) { /* remove buttons from hot list */
863: DelButtonHot(tem);
864: }
865: RemoveTempCursor(); /* remove our cursor */
866: GRestoreRect(&tmpRect,savePtr);
867: return goFlag; /* return flag telling if terrain is to be created */
868: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.