]> cvs.zerfleddert.de Git - micropolis/blob - src/sim/terrain/terra.c
do not include unused alloca.h (from Deanna Phillips' OpenBSD repository)
[micropolis] / src / sim / terrain / terra.c
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 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
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 \11 xxx% \10 \11 xxx% \10 \11 xxx% \10 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],"\11",0x800+tem*2); /* add button */
755 AddTextButton(buttonPos[tem*2+1],"\10",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 }
Impressum, Datenschutz