/* terra.c: Terrain editor * * Micropolis, Unix Version. This game was released for the Unix platform * in or about 1990 and has been modified for inclusion in the One Laptop * Per Child program. Copyright (C) 1989 - 2007 Electronic Arts Inc. If * you need assistance with this program, you may contact: * http://wiki.laptop.org/go/Micropolis or email micropolis@laptop.org. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. You should have received a * copy of the GNU General Public License along with this program. If * not, see . * * ADDITIONAL TERMS per GNU GPL Section 7 * * No trademark or publicity rights are granted. This license does NOT * give you any right, title or interest in the trademark SimCity or any * other Electronic Arts trademark. You may not distribute any * modification of this program using the trademark SimCity or claim any * affliation or association with Electronic Arts Inc. or its employees. * * Any propagation or conveyance of this program must include this * copyright notice and these terms. * * If you convey this program (or any modifications of it) and assume * contractual liability for the program to recipients of it, you agree * to indemnify Electronic Arts for any liability that those contractual * assumptions impose on Electronic Arts. * * You may not misrepresent the origins of this program; modified * versions of the program must be marked as such and not identified as * the original program. * * This disclaimer supplements the one included in the General Public * License. TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, THIS * PROGRAM IS PROVIDED TO YOU "AS IS," WITH ALL FAULTS, WITHOUT WARRANTY * OF ANY KIND, AND YOUR USE IS AT YOUR SOLE RISK. THE ENTIRE RISK OF * SATISFACTORY QUALITY AND PERFORMANCE RESIDES WITH YOU. ELECTRONIC ARTS * DISCLAIMS ANY AND ALL EXPRESS, IMPLIED OR STATUTORY WARRANTIES, * INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY, SATISFACTORY QUALITY, * FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT OF THIRD PARTY * RIGHTS, AND WARRANTIES (IF ANY) ARISING FROM A COURSE OF DEALING, * USAGE, OR TRADE PRACTICE. ELECTRONIC ARTS DOES NOT WARRANT AGAINST * INTERFERENCE WITH YOUR ENJOYMENT OF THE PROGRAM; THAT THE PROGRAM WILL * MEET YOUR REQUIREMENTS; THAT OPERATION OF THE PROGRAM WILL BE * UNINTERRUPTED OR ERROR-FREE, OR THAT THE PROGRAM WILL BE COMPATIBLE * WITH THIRD PARTY SOFTWARE OR THAT ANY ERRORS IN THE PROGRAM WILL BE * CORRECTED. NO ORAL OR WRITTEN ADVICE PROVIDED BY ELECTRONIC ARTS OR * ANY AUTHORIZED REPRESENTATIVE SHALL CREATE A WARRANTY. SOME * JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF OR LIMITATIONS ON IMPLIED * WARRANTIES OR THE LIMITATIONS ON THE APPLICABLE STATUTORY RIGHTS OF A * CONSUMER, SO SOME OR ALL OF THE ABOVE EXCLUSIONS AND LIMITATIONS MAY * NOT APPLY TO YOU. */ /* terra.c - terrain editor for Sim City by Paul Schmidt, 1989 Raxsoft, Inc. 1194 Spring Valley Commons Livermore, CA 94550 (415) 449-9079 */ #include "..\sim\sim.h" #include "..\gr\menu.h" #include "..\gr\grdef.h" #include "..\terra\tmenu.h" #include "..\ed\eddef.h" #include "..\ed\edext.h" #include #include #include #include #include #include #include char *GSaveRect(); extern MOUSESTATE near mouse_state; extern FILE *demoFP; extern char realMouseFlag; extern long lastEvent, TickCount(); /* from ..\sim\main.c */ extern long policeFund, fireFund, transFund; char CreateWithIsland; #define UMaps 4 #define URecs 5000 int UndoMapBuffer1[WORLD_X*WORLD_Y]; int UndoMapBuffer2[WORLD_X*WORLD_Y]; int UndoMapBuffer3[WORLD_X*WORLD_Y]; int UndoMapBuffer4[WORLD_X*WORLD_Y]; int *UndoMap[UMaps]={UndoMapBuffer1,UndoMapBuffer2,UndoMapBuffer3,UndoMapBuffer4}; /* maps for fill undos */ int UndoMaps; /* number of occupied undo maps */ struct { char x,y; /* coordinate of undo */ int val; /* cell value */ } UndoRec[URecs]; /* putdown undos */ int UndoHead=0,UndoTail=0; char fillState=0; /* flag telling if fill mode is on or off */ int treeLevel=50; /* level for tree creation */ int lakeLevel=50; /* level for lake creation */ int curvLevel=50; /* level for river curviness */ /* ========================================================== */ void ClearUndo() /* clear all undo records */ { UndoMaps=UndoHead=UndoTail=0; /* kill undo pointers */ DrawAllEdIcons(UPDATE); /* update undo icon */ } void AddUndo(pos) /* add undo record */ Point pos; /* position to add to undo */ { if(pos.h != -1 || pos.v != -1) { /* if they're not setting to undo the entire map */ if(pos.h > WORLD_X || pos.v > WORLD_Y || pos.h < 0 || pos.v < 0) { /* if out of bounds */ return; /* do nothing */ } } if(pos.h == -1 && pos.v == -1) { /* if undo entire map */ register int tem; /* temporary counter */ register int x,y; /* temporary coordinates */ if(UndoMaps == UMaps) { /* if there are already five undo maps */ while(UndoRec[UndoTail].x != -1 || UndoRec[UndoTail].y != -1) { /* until we find the last map undo */ UndoTail=Bound(0,UndoTail+1,URecs-1); /* move tail */ } UndoTail=Bound(0,UndoTail+1,URecs-1); /* move tail to kill the last map */ UndoMaps--; for(tem=0;tem < UndoMaps;tem++) { /* for each map */ for(x=0;x < WORLD_X*WORLD_Y;x++) { *(UndoMap[tem]+x)=*(UndoMap[tem+1]+x); } } } for(x=0;x < WORLD_X*WORLD_Y;x++) { *(UndoMap[UndoMaps]+x)=*((int*)Map+x); /* save current map */ } UndoMaps++; /* one more map saved */ } UndoRec[UndoHead].x=pos.h; /* set x and y position */ UndoRec[UndoHead].y=pos.v; UndoRec[UndoHead].val=Map[pos.h][pos.v]; /* set map value */ UndoHead=Bound(0,UndoHead+1,URecs-1); /* move head */ if(UndoHead == UndoTail) { /* if we pushed the tail up */ UndoTail=Bound(0,UndoTail+1,URecs-1); /* move tail */ } } void Undo() /* undo one map operation */ { register int x,y; if(UndoHead == UndoTail) { /* if there's nothing to undo */ MakeSound(7); /* bad sound */ return; /* do nothing */ } UndoHead=Bound(0,UndoHead-1,URecs-1); /* set new head */ if(UndoRec[UndoHead].x == -1) { /* if the entire map changed */ register int tem; /* temporary counter */ register int x,y; /* temporary coordinates */ for(x=0;x < WORLD_X*WORLD_Y;x++) { *((int*)Map+x)=*(UndoMap[UndoMaps-1]+x); /* set undo map */ } UndoMaps--; /* one less map */ } else { Map[UndoRec[UndoHead].x][UndoRec[UndoHead].y]=UndoRec[UndoHead].val; /* set old value */ } UpdateOurMaps(); /* update big and small maps */ } /* ======================================================================== */ DoEvent() { int object; EVENT event; #if DEBUG && 0 PrintLock("DoEvent - get event "); #endif GetMouseEvent(&event); object=event.object; #if DEBUG && 0 PrintLock("DoEvent "); #endif switch(object&0xff00) { case 0: DoMenu(object); break; case 0x100: DoEdEvent(&event); break; case 0x200: DoKeyDown(object); break; case 0x300: MenuEvent(&event); break; case 0x400: DoMapEvent(&event); break; case 0x600: DoScreen(&event); break; } } UpdateOurSmallMap() /* update small map */ { register int tem; /* temporary counter */ MouseHide(); /* hide mouse */ DrawSmallMap(); /* updates small map */ for(tem=0;tem < WORLD_X*WORLD_Y;tem++) { *((int*)lastSmallMap+tem)=(*((int*)Map+tem))&LOMASK; /* copy map */ } MouseShow(); /* show mouse */ } UpdateOurMaps() /* update edit and map widnows */ { UpdateMapCursorOff(); /* turn off map cursor */ MouseHide(); /* hide mouse */ DrawBigMap(); /* updates large map */ MouseShow(); /* show mouse */ UpdateOurSmallMap(); DrawAllEdIcons(UPDATE); /* update icons */ UpdateMapCursorOn(); /* turn map cursor on */ } /* ======================================================================== */ DoMenu(itemNum) int itemNum; { static char far *popGameLevelStrs[]={"Easy","Medium","Hard",NULL}; int cur_windowActive; /* current active window */ register int x,y; /* temporary integers */ Rect msgBox; Rect msgRect; char *savePtr; /* pointer to saved rectangle */ int smoothFlag; long tmpFunds; int virginCity=YES; switch(itemNum) { /* case MNUSCNO: /* /* Load a scenario - if it fails we need to redraw the */ /* /* screen */ /* if (!LoadScenario()) { /* InitWindows(); /* } else { /* ClearUndo(); /* clear undo records */ /* } /* SelectNewWindow(EDWINDOW); /* enable edit window */ /* SelectNewWindow(MAPWINDOW); /* enable map window */ /* break; /**/ case MNUQUIT: if (Verify("EXIT")) Quit("Micropolis Terrain Editor"); break; case MNU_SoundToggle: /* sound on/off */ userSoundOn^=YES; sso: ShowSelectedOptions(); break; case MNUABOUT: DoAbout(); break; case MNULOAD: if (LoadGame(NULL,NO)) virginCity=NO; SelectNewWindow(EDWINDOW); /* enable edit window */ SelectNewWindow(MAPWINDOW); /* enable map window */ ClearUndo(); /* clear undo records */ break; case MNUSAVE: SaveGame(lastFileName); break; case MNUSVAS: SaveGame(NULL); break; case MNUNEW: /* Start new game */ if (Verify("NEW GAME")) { totalFunds=20000L; NewGame(NO); transFund=policeFund=fireFund=65535L; CityTax=7; virginCity=YES; ClearUndo(); /* clear undo records */ } SelectNewWindow(EDWINDOW); /* enable edit window */ SelectNewWindow(MAPWINDOW); /* enable map window */ break; case MNUPRINT: PrintCity(); break; case MNU_SmoothTrees: smoothFlag=1; goto dosmooth; case MNU_ClearMap: /* if map is to be cleared */ AddUndo(-1,-1); /* save map */ rax_ClearMap(); /* clear map (..\sim\mapgener.c) */ GameLevel=0; /* assume game is easy */ goto updateBoth; break; case MNU_ClearUnnatural: /* if unnatural objects are to be cleared */ AddUndo(-1,-1); /* save map */ for(x=0;x < WORLD_X;x++) { for(y=0;y < WORLD_Y;y++) { if((Map[x][y]&LOMASK) > 37) { /* get rid of everything unnatural */ Map[x][y]=0; /* turn it into dirt */ } } } updateBoth: UpdateOurMaps(); /* update both windows */ break; case MNU_GenerateRandom: /* if random map is to be generated */ if(SetTerrainParameters()) { /* allow user to set terrain generation parameters */ CenterRect(&msgBox, 20, 5); msgRect=*AdjRect(&msgBox); savePtr=GSaveRect(&msgRect); /* save rectangle */ GRectFill(&msgRect, WHITE|PWHITE); GSetAttrib(DGREEN, DGREEN, PBLACK); GRectOutline(&msgRect, 4); GSetAttrib(LGREEN, LGREEN, PMGREY); GRectOutline(&msgRect, 2); GSetAttrib(DBLUE, WHITE, PWHITE|PINV); CenterPrint(&msgBox, msgBox.top+2, "Now terraforming"); AddUndo(-1,-1); /* save map */ rax_ClearMap(); /* make river map */ rax_GetRandStart(); if(CreateWithIsland) { /* if we're creating an island */ rax_MakeIsland(); /* make an island */ } if(curvLevel) { /* if we're supposedly creating an island */ rax_DoRivers(); /* create river */ } if(lakeLevel) { /* if there are to be lakes */ rax_MakeLakes(); /* add lakes */ } rax_SmoothRiver(); /* smooth out river */ if(treeLevel) { /* if we're creating a woodsy terrain */ rax_DoTrees(); /* add trees */ } rax_SmoothTrees(); /* smooth trees */ rax_SmoothTrees(); /* smooth trees */ GRestoreRect(&msgRect,savePtr); /* restore rectangle */ MapX=MapY=0; goto updateBoth; } break; case MNU_SmoothRiver: /* if water is to be smoothed */ smoothFlag=2; goto dosmooth; case MNU_SmoothBoth: /* if both are to be smoothed */ smoothFlag=3; /* Both */ dosmooth: CenterRect(&msgBox, 16, 5); msgRect=*AdjRect(&msgBox); savePtr=GSaveRect(&msgRect); /* save rectangle */ GRectFill(&msgRect, WHITE|PWHITE); GSetAttrib(DGREEN, DGREEN, PBLACK); GRectOutline(&msgRect, 4); GSetAttrib(LGREEN, LGREEN, PMGREY); GRectOutline(&msgRect, 2); GSetAttrib(DBLUE, WHITE, PWHITE|PINV); CenterPrint(&msgBox, msgBox.top+2, "Smoothing..."); AddUndo(-1,-1); /* save map */ if (smoothFlag & 2) /* If water smooth flag set */ { rax_WaterEdges(); /* make sure water edges are ok */ rax_SmoothRiver(); } if (smoothFlag & 1) { rax_SmoothTrees(); rax_SmoothTrees(); } GRestoreRect(&msgRect,savePtr); /* restore rectangle */ goto updateBoth; case MNU_RandomIsland: /* if random Island toggle */ CreateWithIsland^=1; /* toggle state of flag */ ShowSelectedOptions(); /* update menu flag status */ break; case MNU_GameLevel: /* if game level */ /* GameLevel++; /* add one for PopUpMenuBox */ /* PopUpMenuBox(&GameLevel, popGameLevelStrs); /* GameLevel--; /**/ tmpFunds=totalFunds; /* Don't alter the amount of funds! */ ChooseGameLevel(); /* get city name & level from user */ if (!virginCity) totalFunds=tmpFunds; NewName(); /* set the name of the city */ break; case MNU_GameYear: /* if game year */ SetGameYear(); /* allow user to set the game year */ break; case MNU_EditWindow: /* if edit window */ SelectNewWindow(EDWINDOW); /* bring the edit window to the foreground */ break; case MNU_MapWindow: /* if map window */ SelectNewWindow(MAPWINDOW); /* bring the map window to the foreground */ break; default: /* unimplemented option */ break; } } long messageTime; DoEdEvent(ePtr) EVENT *ePtr; { int object; object=ePtr->object&0xff; if (object & 0xf0) { /* Must be an icon */ SetWandState(object&0xf, YES); } switch (object) { case 0: DoEdMapEvent(ePtr); break; case 2: DoMoveWindow(ePtr, edWinList); break; case 8: ResizeEdWindow(ePtr); break; } } /* ======================================================================== */ DoMapEvent(ePtr) EVENT *ePtr; { int object; object=ePtr->object&0xff; { switch (object) { case 0: DoMapWindowEvent(ePtr); /* move locus of edit window */ break; case 2: DoMoveMap(ePtr); /* move window */ break; } } } void EditTerra() /* main program entry point */ { int updateWait=0, updateWait2=0; CreateWithIsland=0; ShowSelectedOptions(); /* update menu flag status */ GameLevel=0; /* assume game is easy */ totalFunds=20000L; transFund=policeFund=fireFund=65535L; CityTax=7; EnableMenus(); /* make sure menus are enabled */ for (;;) { long lastMapCursor; /* time value for map window cursor flashing */ if (WaitedEnough(&lastMapCursor,2)) { /* if we should flash the map cursor */ UpdateMapCursor(); /* update the map cursor */ } if (!menuActive) /* if no menus are active */ { char moveFlag; if (CheckKeyState(CNTRLSCAN)) /* Is the control key hit? */ { int dx, dy; dx=joyMoveX; dy=joyMoveY; if (CheckKeyState(HOMESCAN)) /* Home arrow */ { dx--; dy--; } if (CheckKeyState(PGUPSCAN)) /* PgUp arrow */ { dx++; dy--; } if (CheckKeyState(ENDSCAN)) /* End arrow */ { dx--; dy++; } if (CheckKeyState(PGDNSCAN)) /* PgDn arrow */ { dx++; dy++; } if (CheckKeyState(RIGHTSCAN)) /* Right arrow */ dx++; if (CheckKeyState(LEFTSCAN)) /* Left arrow */ dx--; if (CheckKeyState(UPSCAN)) /* Up arrow */ dy--; if (CheckKeyState(DOWNSCAN)) /* Down arrow */ dy++; if (dx || dy) { DisableMenus(); freeze=YES; EdScroll(dx,dy); freeze=NO; } } if (!ScrollLock()) { moveagn: moveFlag=NO; if (mouse_state.x <= 1) { if (MapX > 0) { MapX--; moveFlag=YES; } } else if (mouse_state.x >= screenWidth-6) { if (MapX+edWinWid < WORLD_X) { MapX++; moveFlag=YES; } } if (mouse_state.y < 1 ) { if (MapY > 0) { MapY--; moveFlag=YES; } } else if (mouse_state.y >= screenHeight-6) { if (MapY+edWinLen < WORLD_Y) { MapY++; moveFlag=YES; } } if (moveFlag == YES) { DisableMenus(); /* locks to current process */ newMapFlags[CYMAP]=0; DrawBigMap(); #if 0 DrawObjects(); #endif EnableMenus(); goto moveagn; } } /* End of "if (!ScrollLock" */ } /* End if if (!menuActive) */ if (KBHit() || CheckMouseEvents()) /* if an event happened */ { DisableMenus(); while(KBHit()) { DoKey(); } while (CheckMouseEvents()) { DoEvent(); } lastEvent=TickCount(); } if (simSpeed == 0) { if (WaitedEnough(&updateWait, 18*3)) { DisableMenus(); UpdateEdWindow(); } } #if DEBUGINI OutStr("\nMAIN: re-enable"); #endif EnableMenus(); /* Make sure the menus are enabled */ copyOK=YES; #if DEBUGINI OutStr("\nMAIN: copyok, pass"); #endif Pass(); copyOK=NO; #if DEBUGINI OutStr("\nMAIN: copy not OK"); #endif } } SetGameYear() /* get game year */ { Rect verBox; static char *label="Enter Game Year:"; /* label for window */ char dateBuffer[10]; /* buffer for date */ EVENT event; char *savePtr; int len, x, y, i,c, optLens[8]; Rect tmpBox; Size strSize; const char **optPtr; int posIndex=(-1); long tmpTime; FlushKeys(); CenterRect(&verBox,18,5); tmpBox=*AdjRect(&verBox); savePtr=GSaveRect(&tmpBox); GRectFill(&tmpBox,BUDGFC+PMGREY); GSetAttrib(BUDGBC,BUDGBC,PWHITE); GRectOutline(&tmpBox, 4); /* Outline outline in BLACK */ GSetAttrib(BLACK,BLACK,PBLACK); GRectOutline(&tmpBox,1); GSetAttrib(BUDGBC,BUDGFC,PINV|PWHITE); PrintRectLines(&verBox,verBox.top,label); i=20; x=verBox.left+i; y=verBox.bottom-2; GSetAttrib(BUDGBC,BUDBOXC,PINV|PWHITE); /* GSetAttrib(BUDGBC,BUDBOXC,0); */ /* TempFullScreenCursor(); */ sprintf(dateBuffer,"%4d",(CityTime/48)+1900); /* set date */ GetStrSetNum(); /* Numbers only */ GetStrn(verBox.left+6,verBox.top+3,dateBuffer,5,1); /* allow user to edit the date and set eos */ GetStrSetAll(); /* allow any alphnum input */ if(strlen(dateBuffer) == 4) { /* if they entered a good date */ tmpTime=(atoi(dateBuffer)-1900)*48L; /* set new date */ if (tmpTime > 0) CityTime=tmpTime; } else { /* if not the correct length */ MakeSound(7); /* this should be CANTSND for bad date */ } for(i=0;i < 100;i++) { /* kill any and all events */ GetMouseEvent(&event); /* get event */ } /* RemoveTempCursor(); */ GRestoreRect(&tmpBox,savePtr); DoDate(); /* update the date in the edit window */ } int PSBound(a,n,b) /* return number between a and b */ { if(n < a) n=a; if(n > b) n=b; return n; } /* here is the concept for SetTerrainParameters(): ZDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD? 3 3 3 Terrain Creation Parameters 3 3 3 3 Number Number River 3 3 of Trees of Lakes Curviness 3 3 3 3  xxx%   xxx%   xxx%  3 3 3 3 ZDDDDDDDD? ZDDDDDDDD? 3 3 3 Go 3 3 Cancel 3 3 3 @DDDDDDDDY @DDDDDDDDY 3 @DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDY */ SetTerrainParameters() /* allow user to set up terrain grneration parameters */ { char *savePtr; /* pointer to saved screen data */ char temStr[20]; /* temporary string for percentages */ EVENT event; /* temporary event */ int atButton=0; /* current button we're at */ int buttonDown=0; /* flag telling if mouse button is down */ int goFlag=0; /* flag telling if terrain is to be generated */ long startTime; /* temporary timer value */ int tem; /* temporary counter */ int x,y; /* temporary positions */ Rect wRect; /* rectangle showing extents of window */ Rect tmpRect; /* temporary rectangle for adjusted window rectangle */ Point buttonPos[8]; /* positions of buttons */ FlushKeys(); /* do something...flush keyboard buffer? */ CenterRect(&wRect,36,10); /* center our window */ tmpRect=*AdjRect(&wRect); savePtr=GSaveRect(&tmpRect); GRectFill(&tmpRect,BUDGFC+PMGREY); GSetAttrib(BUDGBC,BUDGBC,PWHITE); GRectOutline(&tmpRect,4); /* Outline outline in BLACK */ GSetAttrib(BLACK,BLACK,PBLACK); GRectOutline(&tmpRect,1); GSetAttrib(BUDGBC,BUDGFC,PINV|PWHITE); PrintRectLines(&wRect,wRect.top,"Terrain Creation Parameters"); x=(wRect.left+2)*8; y=(wRect.top+2)*fontHeight; GPPrintf(x+(1*8),y+(1*fontHeight)-3," Number Number River "); GPPrintf(x+(1*8),y+(2*fontHeight)-3,"of Trees of Lakes Curviness"); buttonPos[0].h=wRect.left+3; /* positions of buttons */ buttonPos[1].h=wRect.left+10; buttonPos[2].h=wRect.left+14; buttonPos[3].h=wRect.left+21; buttonPos[4].h=wRect.left+25; buttonPos[5].h=wRect.left+32; for(tem=0;tem < 6;tem++) { buttonPos[tem].v=wRect.top+5; /* set vertical position */ } buttonPos[6].h=wRect.left+3; buttonPos[7].h=wRect.left+25; buttonPos[6].v=buttonPos[7].v=wRect.top+8; GSetAttrib(BUDGBC,BUDBOXC,PINV|PWHITE); for(tem=0;tem < 3;tem++) { /* for each set of value buttons */ AddTextButton(buttonPos[tem*2],"",0x800+tem*2); /* add button */ AddTextButton(buttonPos[tem*2+1],"",0x801+tem*2); /* add button */ } AddTextButton(buttonPos[6]," Go ",0x806); /* add 'go' button */ AddTextButton(buttonPos[7]," Cancel ",0x807); /* add 'cancel' button */ /* output initial values */ GSetAttrib(BUDGBC,BUDGFC,PINV|PWHITE); sprintf(temStr,"%3d%%%%",treeLevel); /* get string for tree level */ GPPrintf(x+(3*8),y+(3*fontHeight),temStr); /* output string */ sprintf(temStr,"%3d%%%%",lakeLevel); /* get string for lake level */ GPPrintf(x+(14*8),y+(3*fontHeight),temStr); /* output string */ sprintf(temStr,"%3d%%%%",curvLevel); /* get string for curviness level */ GPPrintf(x+(25*8),y+(3*fontHeight),temStr); /* output string */ /* GSetAttrib(BUDGBC,BUDBOXC,0); */ TempFullScreenCursor(); /* give us a cursor */ while(1) { /* until break */ if(0) { /* never unless below code calls it */ repos: SetMouseAtButton(atButton+0x800); } while (KBHit()) /* Clear any keys pressed */ { switch (GetECH()) { case 27: /* if escape */ case 'C': /* (or 'cancel') */ case 'c': goFlag=0; /* don't create random terrain */ goto xit; case 13: /* if carriage return */ case 'G': /* (or 'go') */ case 'g': goFlag=1; /* create random terrain */ goto xit; case '+': atButton=((atButton+1) % 8); /* for each button */ goto repos; case '-': atButton=(atButton)?(atButton-1):7; goto repos; } } if(CheckMouseEvents()) { /* if there's an activity */ GetMouseEvent(&event); /* get event */ downAgain: switch(event.object) { /* get event id */ case 0x800: /* if - trees */ treeLevel=PSBound(0,treeLevel-1,100); goto updateValues; /* update values */ case 0x801: /* if + trees */ treeLevel=PSBound(0,treeLevel+1,100); goto updateValues; /* update values */ case 0x802: /* if - lakes */ lakeLevel=PSBound(0,lakeLevel-1,100); goto updateValues; /* update values */ case 0x803: /* if + lakes */ lakeLevel=PSBound(0,lakeLevel+1,100); goto updateValues; /* update values */ case 0x804: /* if - curviness */ curvLevel=PSBound(0,curvLevel-1,100); goto updateValues; /* update values */ case 0x805: /* if + curviness */ curvLevel=PSBound(0,curvLevel+1,100); goto updateValues; /* update values */ case 0x806: /* if 'go' */ goFlag=1; /* return flag telling to create terrain */ break; case 0x807: /* if 'cancel' */ goFlag=0; /* return flag telling to create terrain */ break; } if(0) { /* only if above code calls us */ updateValues: RemoveTempCursor(); /* remove cursor from screen */ GSetAttrib(BUDGBC,BUDGFC,PINV|PWHITE); sprintf(temStr,"%3d%%%%",treeLevel); /* get string for tree level */ GPPrintf(x+(3*8),y+(3*fontHeight),temStr); /* output string */ sprintf(temStr,"%3d%%%%",lakeLevel); /* get string for lake level */ GPPrintf(x+(14*8),y+(3*fontHeight),temStr); /* output string */ sprintf(temStr,"%3d%%%%",curvLevel); /* get string for curviness level */ GPPrintf(x+(25*8),y+(3*fontHeight),temStr); /* output string */ TempFullScreenCursor(); /* put cursor back */ if(!buttonDown) { /* if button was not down */ buttonDown=1; /* set button down flag */ startTime=TickCount(); /* get current time */ while(StillDown()) { /* while a button is down */ if(TickCount()-startTime > 5) { /* if autorepeat is up */ goto downAgain; } } buttonDown=0; /* button is no longer down */ } else { /* if button is already down */ if(StillDown()) { /* if button is still down */ startTime=TickCount(); /* get current time */ while(startTime == TickCount()) ; /* wait for 1/18th of a second */ goto downAgain; } buttonDown=0; /* no button is down */ } } if(event.object == 0x806 || event.object == 0x807) { /* if one of the exit buttons */ xit: break; /* exit loop */ } } } for(tem=0x800;tem <= 0x809;tem++) { /* remove buttons from hot list */ DelButtonHot(tem); } RemoveTempCursor(); /* remove our cursor */ GRestoreRect(&tmpRect,savePtr); return goFlag; /* return flag telling if terrain is to be created */ }