-
Notifications
You must be signed in to change notification settings - Fork 0
/
landscape.cp
3087 lines (2887 loc) · 115 KB
/
landscape.cp
1
/****************************************************************************************//* LANDSCAPE.CP *//****************************************************************************************//* (c) 1995 by Magnet Interactive Studios, inc. All rights reserved. *//****************************************************************************************//* Revision History: *//* 7/6/94 File first created. By Andrew Looney. *//* v1.0 8/3/94 First polished version. By Andrew Looney. *//* 8/8/94 Started making changes for next version. *//* v2.0 8/24/94 Seven level version burned onto CD-ROM. By Andrew Looney. *//* v2.1 8/29/94 Comments brought back up to date. By Andrew Looney. *//* v2.2 9/7/94 Sixteen level version. By Andrew Looney. *//* v2.3 9/23/94 Thirty level version burned onto CD-ROM. By Andrew Looney. *//* v2.4 10/19/94 Fifty level version. By Andrew Looney. *//* v2.5 10/31/94 Sixty level version burned onto CD-ROM. By Andrew Looney. *//* v3.0 10/31/94 Began switching over to real artwork. By Andrew Looney. *//* v3.1 11/11/94 COMDEX version. By Andrew Looney. *//* v3.2 12/2/94 Seventy-five level version. By Andrew Looney. *//* v3.3 12/14/94 Ack! Zombies! By Andrew Looney. *//* v3.4 12/23/94 Orange Meanies! By Andrew Looney. *//* v3.5 1/3/95 100 Levels! By Andrew Looney. *//* v3.6 1/5/95 101 Levels. By Andrew Looney. *//* v3.7 1/16/95 New, improved Brainy Seeker logic! By Andrew Looney. *//* v3.8 1/27/95 114 level version burned onto CD-ROM. By Andrew Looney. *//* v3.9 2/3/95 New CD-ROM burned for shipment to 3DO. By Andrew Looney. *//* v4.0 2/9/95 New CD-ROM featuring the big level grid. By Andrew Looney. *//* v4.1 2/22/95 New CD-ROM with rough draft of full interface. By Andrew Looney. *//* v4.2 3/17/95 The St. Patrick's Day Version. By Andrew Looney. *//* v4.3 3/20/95 The last version before the movies get added. By Andrew Looney. *//* v4.4 3/21/95 First version with movies integrated. By Andrew Looney. *//* v4.5 3/22/95 Second version with movies integrated. By Andrew Looney. *//* v4.6 3/27/95 Third version with movies integrated. By Andrew Looney. *//* v5.0 3/28/95 Newest version sent to QA. By Andrew Looney. *//* v5.1 3/28/95 Now, with Easter Eggs! By Andrew Looney. *//* v5.2 3/29/95 Could this be the final version? By Andrew Looney. *//* v5.3 3/30/95 OK, now maybe THIS is the final version! By Andrew Looney. *//* v5.4 4/3/95 Made a couple more minor changes. By Andrew Looney. *//****************************************************************************************//***************************** WHAT THIS SOFTWARE DOES ********************************** The functions in this class provide a way of creating a landscape as viewed from a 45 degree angle, which can be scrolled in any direction. The landscape is composed ofdiamond shaped tiles, each stored in a rectangular cel with transparent black bitsfiling out the four corners. The landscape will be of a fixed size, as determined bythe symbols ROWS_IN_LANDSCAPE and COLUMNS_IN_LANDSCAPE (defined in a header file), andwill be surrounded by an endless, nondescript "wasteland" area. The landscape is implemented with the use of a number of key data structures. Thefirst is a lookup table that contains a descriptor value for each tile in the landscape.These descriptors are selected from a list of art files to be used when displayingthe tiles. The second is an array of CCB structures, which each define an actual artelement that can be displayed on the screen. Although a CCB will exist for each tile in the landscape, the tiles will only be drawn to the screen if they are visible on the screen, thus to save CPU time. The next set of data structures implement the wasteland. Since we need a potentially infinite number of wasteland tiles to simulate a region that goes on forever, we instead create just enough CCB structures to exactly fill the screen. Then, if the player is out in the wasteland, and we need to scroll the landscape, we juggle our limited supply ofwasteland CCBs so that they always fill the screen, moving ones on the top of the screendown to the bottom of the screen when moving south, and so on. These wasteland CCBs areinitialized to the exact same locations as the set of real landscape tiles that start outfilling the screen, and they are scrolled and shuffled as needed whenever the reallandscape is scrolled; however, they are only displayed when there are holes in the reallandscape the need to be filled up. The next important data structure is a linked list containing pointers to all of theanimated tiles. An animated tile must be maintained during each pass, so that the next frame is loaded and set for display. But we don't want to waste time looking at each tilein the landscape just to find the animated ones, so instead we create a list of just theanimated tiles and use that when doing animated tile maintenance. We used to use the same approach for dealing with hazardous tiles, and if I haven'tmanaged to catch all the references to them in the comments, you may find mention ofthe hazards list, which was a linked list of all the dangerous tiles in the landscapewhich could more quickly be checked than checking all tiles in the landscape to find outif you are on any of them. As landscapes became very complex, with many many hazards,this seemed less effiecent that simply keeping track of the tile you are on and checkingagainst all adjacent tiles, and so I switched all hazard checking over to this method. Well, mostly. Checking for swamps is still done using a linked list of all swamp tiles.It didn't seem imperative to convert this, so I didn't bother. The swamp list is onlyever checked once by a seeker, unlike the hazards list, which could have been searchedas many as 6 times by a hazard avoiding seeker in each move, which became cumbersomewhen there were 40 hazard tiles and 12 hazard avoiding seekers on level. In addition to these structures, we also use a number of local, private variables. In particular, there are pointers to all of the different artwork elements that can beused during the game. The values of these pointers may or may not be valid; on startingup a level, the art that will be used on that level is loaded and art which won't be usedis deleted, in order to avoid running out of memory. Each tile has a unique code that identifies it. This is a 2 character code, defined asfollows. The first character defines the general nature of the tile, for example, L forlava and I for ice. The second character enumerates the tile, using numbers for animatedtiles and letters for static tiles. Thus, GB is a non-animating grass tile, the 2nd in thelist. Here's how you go about adding a new tile art to the landscape: 1.) Create a new symbol for the art element (for example, GB_TILE) in the big art elements list, and adjust the value of TOTAL_ART_ELEMENTS (in ICEBREAKER.H). 2.) Create a new symbol that defines the name of the art file (for example, GB_FILE) and a new variable (for example, gb_tile) that will be a pointer to this art element (in LANDSCAPE.H). 3.) Add initialization of the variable to BootLandscape (in this file). 4.) Add a case to the switch statement in LoadArtwork to handle the new tile. 5.) Add an if statement to ShutdownUnusedArtwork to handle the new tile. 6.) Add an if statement to ShutdownForExit to handle the new tile. 7.) If the tile can be used as a wasteland tile, add a case to the switch statement in CreateTiles to handle the tile. 8.) Add a case to the switch statement in ChangeArt to handle the tile. 9.) If the tile is an animated tile, add a call to CreateAnimatedTile in the function RepaintAndRegisterTiles to get the tile added to the animated tiles list. 10.) If the tile is hazardous, make sure that IsThisDangerous will say so. 11.) If the tile is an ice tile, set the variable check_for_ice to TRUE in 2 places: In CreateTiles and in RepaintAndRegisterTiles. 12.) If the tile is a transforming tile, (such as a pit creation), then add a call to the function TransformTile to initiate the transformation of the tile as needed (for example, in WEAPON.CP, when a purple pyramid is destroyed). 13.) If the tile is a transforming tile, (such as a pit creation), then add another call to TransformTile within the function MaintainAnimatedTiles, to switch the tile to the new type upon completion of the transformation animation. 14.) If the tile is hazardous to the dudemeyer, add handling for the tile to the functions ResultsHandler and PullIntoHazard (in ICEBREAKER.CP). 15.) If the tile is hazardous to seekers, add handling for the tile to the functions AnimateSeekers and CommenceHazardDeath (in SEEKER.CP). 16.) Add a case for the new tile to the switch statement in the function ArtworkMissing (in ICEBREAKER.CP). 17.) Add a case for the new tile to the function TranslateTileCode (in LEVELS.CP). 18.) If the tile can require related animations (for example, pit formations) then add code to the function LoadLevel that will set the art usage table entries for these related art elements to TRUE, so that for these animations will be loaded at level boot time (in LEVELS.CP). ... and that's all there is to it? Isn't that easy?*****************************************************************************************//***** regular includes *****/#include "graphics.h"#include "stdio.h"#include "stdlib.h"#include "mem.h"#include "types.h"#include "hardware.h"#include "event.h"#include "strings.h"#include "access.h"#include "UMemory.h"#include "Form3DO.h"#include "Init3DO.h"#include "Parse3DO.h"#include "Utils3DO.h"#include "audio.h"#include "music.h"/***** magnet includes *****/#include "icebreaker.h"#include "animation.h"#include "landscape.h"/***** special c++ include (this must be last) *****/#include "CPlusSwiHack.h"/***** global variables *****/extern ScreenContext g_screen;extern int32 level_lookup_table [ROWS_IN_LANDSCAPE] [COLUMNS_IN_LANDSCAPE];extern bool check_for_ice;extern bool g_art_usage[TOTAL_ART_ELEMENTS];/***************************** landscape::BootLandscape ******************************** This function simply sets all of the artwork element pointer values to NULL. This isimportant because artwork is only loaded if the pointer is set to NULL, and on bootup wecan't really be certain that these pointers will be pre-initialized to the value NULL.*****************************************************************************************/void landscape::BootLandscape(void){ ga_tile = (CCB *) NULL; gb_tile = (CCB *) NULL; gc_tile = (CCB *) NULL; gd_tile = (CCB *) NULL; ge_tile = (CCB *) NULL; gf_tile = (CCB *) NULL; he_tile = (CCB *) NULL; da_tile = (CCB *) NULL; db_tile = (CCB *) NULL; dc_tile = (CCB *) NULL; dd_tile = (CCB *) NULL; wa_tile = (CCB *) NULL; ha_tile = (CCB *) NULL; hb_tile = (CCB *) NULL; hc_tile = (CCB *) NULL; hd_tile = (CCB *) NULL; pa_tile = (CCB *) NULL; pb_tile = (CCB *) NULL; ia_tile = (CCB *) NULL; sa_tile = (CCB *) NULL; la_tile = (CCB *) NULL; lb_tile = (CCB *) NULL; sb_tile = (CCB *) NULL; hb_tile = (CCB *) NULL; hc_tile = (CCB *) NULL; hd_tile = (CCB *) NULL; ib_tile = (CCB *) NULL; pc_tile = (CCB *) NULL; s1_tile.anim_pointer = (ANIM *) NULL; l1_tile.anim_pointer = (ANIM *) NULL; p1_tile.anim_pointer = (ANIM *) NULL; gb2pa_tile.anim_pointer = (ANIM *) NULL; ia2pb_tile.anim_pointer = (ANIM *) NULL; hd2pc_tile.anim_pointer = (ANIM *) NULL; wa2pd_tile.anim_pointer = (ANIM *) NULL; ga2pe_tile.anim_pointer = (ANIM *) NULL; ha2pf_tile.anim_pointer = (ANIM *) NULL; ib2pg_tile.anim_pointer = (ANIM *) NULL; pg_tile = (CCB *) NULL; wb_tile = (CCB *) NULL; ic_tile = (CCB *) NULL; id_tile = (CCB *) NULL; pd_tile = (CCB *) NULL; pe_tile = (CCB *) NULL; pf_tile = (CCB *) NULL; va2pk_tile.anim_pointer = (ANIM *) NULL; da2pj_tile.anim_pointer = (ANIM *) NULL; db2pi_tile.anim_pointer = (ANIM *) NULL; dd2ph_tile.anim_pointer = (ANIM *) NULL; ud2p1_tile.anim_pointer = (ANIM *) NULL; ua_tile = (CCB *) NULL; ub_tile = (CCB *) NULL; uc_tile = (CCB *) NULL; ud_tile = (CCB *) NULL; ue_tile = (CCB *) NULL; va_tile = (CCB *) NULL; vb_tile = (CCB *) NULL; ph_tile = (CCB *) NULL; pi_tile = (CCB *) NULL; pj_tile = (CCB *) NULL; pk_tile = (CCB *) NULL; dc2pj_tile.anim_pointer = (ANIM *) NULL; ic2pb_tile.anim_pointer = (ANIM *) NULL; id2pb_tile.anim_pointer = (ANIM *) NULL; gc2pa_tile.anim_pointer = (ANIM *) NULL; gd2pa_tile.anim_pointer = (ANIM *) NULL; ge2pa_tile.anim_pointer = (ANIM *) NULL; gf2pa_tile.anim_pointer = (ANIM *) NULL; de2pj_tile.anim_pointer = (ANIM *) NULL; hb2pc_tile.anim_pointer = (ANIM *) NULL; hc2pl_tile.anim_pointer = (ANIM *) NULL; he2pc_tile.anim_pointer = (ANIM *) NULL; ua2p1_tile.anim_pointer = (ANIM *) NULL; ub2p1_tile.anim_pointer = (ANIM *) NULL; ue2pm_tile.anim_pointer = (ANIM *) NULL; uc2pm_tile.anim_pointer = (ANIM *) NULL; wb2pd_tile.anim_pointer = (ANIM *) NULL; wc2pd_tile.anim_pointer = (ANIM *) NULL; wd2pd_tile.anim_pointer = (ANIM *) NULL; de_tile = (CCB *) NULL; wc_tile = (CCB *) NULL; wd_tile = (CCB *) NULL; pl_tile = (CCB *) NULL; pm_tile = (CCB *) NULL;}/***************************** landscape::LoadArtwork ********************************* This function is called whenever the software determines that it needs a given artworkelement but that this element has not been loaded into memory (i.e. the pointer to thatelement is set to NULL.) This function takes as input the symbol which uniquely identifiesthis piece of artwork, and loads it into memory. If the file could not be found, thisfunction calls the routine ArtworkMissing, which will identify the missing art and abortthe program. (It is assumed that such problems will occur only during testing.)*****************************************************************************************/void landscape::LoadArtwork (int32 element_to_load){ switch(element_to_load) { case GA_TILE: ga_tile = LoadCel(GA_FILE,MEMTYPE_CEL); if (ga_tile == NULL) ArtworkMissing(GA_TILE); break; case GB_TILE: gb_tile = LoadCel(GB_FILE,MEMTYPE_CEL); if (gb_tile == NULL) ArtworkMissing(GB_TILE); break; case GC_TILE: gc_tile = LoadCel(GC_FILE,MEMTYPE_CEL); if (gc_tile == NULL) ArtworkMissing(GC_TILE); break; case GD_TILE: gd_tile = LoadCel(GD_FILE,MEMTYPE_CEL); if (gd_tile == NULL) ArtworkMissing(GD_TILE); break; case GE_TILE: ge_tile = LoadCel(GE_FILE,MEMTYPE_CEL); if (ge_tile == NULL) ArtworkMissing(GE_TILE); break; case GF_TILE: gf_tile = LoadCel(GF_FILE,MEMTYPE_CEL); if (gf_tile == NULL) ArtworkMissing(GF_TILE); break; case HE_TILE: he_tile = LoadCel(HE_FILE,MEMTYPE_CEL); if (he_tile == NULL) ArtworkMissing(HE_TILE); break; case DA_TILE: da_tile = LoadCel(DA_FILE,MEMTYPE_CEL); if (da_tile == NULL) ArtworkMissing(DA_TILE); break; case DB_TILE: db_tile = LoadCel(DB_FILE,MEMTYPE_CEL); if (db_tile == NULL) ArtworkMissing(DB_TILE); break; case DC_TILE: dc_tile = LoadCel(DC_FILE,MEMTYPE_CEL); if (dc_tile == NULL) ArtworkMissing(DC_TILE); break; case DD_TILE: dd_tile = LoadCel(DD_FILE,MEMTYPE_CEL); if (dd_tile == NULL) ArtworkMissing(DD_TILE); break; case WA_TILE: wa_tile = LoadCel(WA_FILE,MEMTYPE_CEL); if (wa_tile == NULL) ArtworkMissing(WA_TILE); break; case HA_TILE: ha_tile = LoadCel(HA_FILE,MEMTYPE_CEL); if (ha_tile == NULL) ArtworkMissing(HA_TILE); break; case HB_TILE: hb_tile = LoadCel(HB_FILE,MEMTYPE_CEL); if (hb_tile == NULL) ArtworkMissing(HB_TILE); break; case HC_TILE: hc_tile = LoadCel(HC_FILE,MEMTYPE_CEL); if (hc_tile == NULL) ArtworkMissing(HC_TILE); break; case HD_TILE: hd_tile = LoadCel(HD_FILE,MEMTYPE_CEL); if (hd_tile == NULL) ArtworkMissing(HD_TILE); break; case PA_TILE: pa_tile = LoadCel(PA_FILE,MEMTYPE_CEL); if (pa_tile == NULL) ArtworkMissing(PA_TILE); break; case PB_TILE: pb_tile = LoadCel(PB_FILE,MEMTYPE_CEL); if (pb_tile == NULL) ArtworkMissing(PB_TILE); break; case IA_TILE: ia_tile = LoadCel(IA_FILE,MEMTYPE_CEL); if (ia_tile == NULL) ArtworkMissing(IA_TILE); break; case SA_TILE: sa_tile = LoadCel(SA_FILE,MEMTYPE_CEL); if (sa_tile == NULL) ArtworkMissing(SA_TILE); break; case LA_TILE: la_tile = LoadCel(LA_FILE,MEMTYPE_CEL); if (la_tile == NULL) ArtworkMissing(LA_TILE); break; case LB_TILE: lb_tile = LoadCel(LB_FILE,MEMTYPE_CEL); if (lb_tile == NULL) ArtworkMissing(LB_TILE); break; case SB_TILE: sb_tile = LoadCel(SB_FILE,MEMTYPE_CEL); if (sb_tile == NULL) ArtworkMissing(SB_TILE); break; case IB_TILE: ib_tile = LoadCel(IB_FILE,MEMTYPE_CEL); if (ib_tile == NULL) ArtworkMissing(IB_TILE); break; case ID_TILE: id_tile = LoadCel(ID_FILE,MEMTYPE_CEL); if (id_tile == NULL) ArtworkMissing(ID_TILE); break; case PC_TILE: pc_tile = LoadCel(PC_FILE,MEMTYPE_CEL); if (pc_tile == NULL) ArtworkMissing(PC_TILE); break; case S1_TILE: if (!(s1_tile.LoadArtwork(S1_FILE))) ArtworkMissing(S1_TILE); break; case L1_TILE: if (!(l1_tile.LoadArtwork(L1_FILE))) ArtworkMissing(L1_TILE); break; case P1_TILE: if (!(p1_tile.LoadArtwork(P1_FILE))) ArtworkMissing(P1_TILE); break; case GB2PA_TILE: if (!(gb2pa_tile.LoadArtwork(GB2PA_FILE))) ArtworkMissing(GB2PA_TILE); break; case IA2PB_TILE: if (!(ia2pb_tile.LoadArtwork(IA2PB_FILE))) ArtworkMissing(IA2PB_TILE); break; case HD2PC_TILE: if (!(hd2pc_tile.LoadArtwork(HD2PC_FILE))) ArtworkMissing(HD2PC_TILE); break; case WA2PD_TILE: if (!(wa2pd_tile.LoadArtwork(WA2PD_FILE))) ArtworkMissing(WA2PD_TILE); break; case PG_TILE: pg_tile = LoadCel(PG_FILE,MEMTYPE_CEL); if (pg_tile == NULL) ArtworkMissing(PG_TILE); break; case WB_TILE: wb_tile = LoadCel(WB_FILE,MEMTYPE_CEL); if (wb_tile == NULL) ArtworkMissing(WB_TILE); break; case IC_TILE: ic_tile = LoadCel(IC_FILE,MEMTYPE_CEL); if (ic_tile == NULL) ArtworkMissing(IC_TILE); break; case PD_TILE: pd_tile = LoadCel(PD_FILE,MEMTYPE_CEL); if (pd_tile == NULL) ArtworkMissing(PD_TILE); break; case PE_TILE: pe_tile = LoadCel(PE_FILE,MEMTYPE_CEL); if (pe_tile == NULL) ArtworkMissing(PE_TILE); break; case PF_TILE: pf_tile = LoadCel(PF_FILE,MEMTYPE_CEL); if (pf_tile == NULL) ArtworkMissing(PF_TILE); break; case IB2PG_TILE: if (!(ib2pg_tile.LoadArtwork(IB2PG_FILE))) ArtworkMissing(IB2PG_TILE); break; case GA2PE_TILE: if (!(ga2pe_tile.LoadArtwork(GA2PE_FILE))) ArtworkMissing(GA2PE_TILE); break; case HA2PF_TILE: if (!(ha2pf_tile.LoadArtwork(HA2PF_FILE))) ArtworkMissing(HA2PF_TILE); break; case VA2PK_TILE: if (!(va2pk_tile.LoadArtwork(VA2PK_FILE))) ArtworkMissing(VA2PK_TILE); break; case UD2P1_TILE: if (!(ud2p1_tile.LoadArtwork(UD2P1_FILE))) ArtworkMissing(UD2P1_TILE); break; case DA2PJ_TILE: if (!(da2pj_tile.LoadArtwork(DA2PJ_FILE))) ArtworkMissing(DA2PJ_TILE); break; case DB2PI_TILE: if (!(db2pi_tile.LoadArtwork(DB2PI_FILE))) ArtworkMissing(DB2PI_TILE); break; case DD2PH_TILE: if (!(dd2ph_tile.LoadArtwork(DD2PH_FILE))) ArtworkMissing(DD2PH_TILE); break; case UA_TILE: ua_tile = LoadCel(UA_FILE,MEMTYPE_CEL); if (ua_tile == NULL) ArtworkMissing(UA_TILE); break; case UB_TILE: ub_tile = LoadCel(UB_FILE,MEMTYPE_CEL); if (ub_tile == NULL) ArtworkMissing(UB_TILE); break; case UC_TILE: uc_tile = LoadCel(UC_FILE,MEMTYPE_CEL); if (uc_tile == NULL) ArtworkMissing(UC_TILE); break; case UD_TILE: ud_tile = LoadCel(UD_FILE,MEMTYPE_CEL); if (ud_tile == NULL) ArtworkMissing(UD_TILE); break; case UE_TILE: ue_tile = LoadCel(UE_FILE,MEMTYPE_CEL); if (ue_tile == NULL) ArtworkMissing(UE_TILE); break; case VA_TILE: va_tile = LoadCel(VA_FILE,MEMTYPE_CEL); if (va_tile == NULL) ArtworkMissing(VA_TILE); break; case VB_TILE: vb_tile = LoadCel(VB_FILE,MEMTYPE_CEL); if (vb_tile == NULL) ArtworkMissing(VB_TILE); break; case PH_TILE: ph_tile = LoadCel(PH_FILE,MEMTYPE_CEL); if (ph_tile == NULL) ArtworkMissing(PH_TILE); break; case PI_TILE: pi_tile = LoadCel(PI_FILE,MEMTYPE_CEL); if (pi_tile == NULL) ArtworkMissing(PI_TILE); break; case PJ_TILE: pj_tile = LoadCel(PJ_FILE,MEMTYPE_CEL); if (pj_tile == NULL) ArtworkMissing(PJ_TILE); break; case PK_TILE: pk_tile = LoadCel(PK_FILE,MEMTYPE_CEL); if (pk_tile == NULL) ArtworkMissing(PK_TILE); break; case DC2PJ_TILE: if (!(dc2pj_tile.LoadArtwork(DC2PJ_FILE))) ArtworkMissing(DC2PJ_TILE); break; case IC2PB_TILE: if (!(ic2pb_tile.LoadArtwork(IC2PB_FILE))) ArtworkMissing(IC2PB_TILE); break; case ID2PB_TILE: if (!(id2pb_tile.LoadArtwork(ID2PB_FILE))) ArtworkMissing(ID2PB_TILE); break; case GC2PA_TILE: if (!(gc2pa_tile.LoadArtwork(GC2PA_FILE))) ArtworkMissing(GC2PA_TILE); break; case GD2PA_TILE: if (!(gd2pa_tile.LoadArtwork(GD2PA_FILE))) ArtworkMissing(GD2PA_TILE); break; case GE2PA_TILE: if (!(ge2pa_tile.LoadArtwork(GE2PA_FILE))) ArtworkMissing(GE2PA_TILE); break; case GF2PA_TILE: if (!(gf2pa_tile.LoadArtwork(GF2PA_FILE))) ArtworkMissing(GF2PA_TILE); break; case DE_TILE: de_tile = LoadCel(DE_FILE,MEMTYPE_CEL); if (de_tile == NULL) ArtworkMissing(DE_TILE); break; case WC_TILE: wc_tile = LoadCel(WC_FILE,MEMTYPE_CEL); if (wc_tile == NULL) ArtworkMissing(WC_TILE); break; case WD_TILE: wd_tile = LoadCel(WD_FILE,MEMTYPE_CEL); if (wd_tile == NULL) ArtworkMissing(WD_TILE); break; case PL_TILE: pl_tile = LoadCel(PL_FILE,MEMTYPE_CEL); if (pl_tile == NULL) ArtworkMissing(PL_TILE); break; case PM_TILE: pm_tile = LoadCel(PM_FILE,MEMTYPE_CEL); if (pm_tile == NULL) ArtworkMissing(PM_TILE); break; case DE2PJ_TILE: if (!(de2pj_tile.LoadArtwork(DE2PJ_FILE))) ArtworkMissing(DE2PJ_TILE); break; case HB2PC_TILE: if (!(hb2pc_tile.LoadArtwork(HB2PC_FILE))) ArtworkMissing(HB2PC_TILE); break; case HC2PL_TILE: if (!(hc2pl_tile.LoadArtwork(HC2PL_FILE))) ArtworkMissing(HC2PL_TILE); break; case HE2PC_TILE: if (!(he2pc_tile.LoadArtwork(HE2PC_FILE))) ArtworkMissing(HE2PC_TILE); break; case UA2P1_TILE: if (!(ua2p1_tile.LoadArtwork(UA2P1_FILE))) ArtworkMissing(UA2P1_TILE); break; case UB2P1_TILE: if (!(ub2p1_tile.LoadArtwork(UB2P1_FILE))) ArtworkMissing(UB2P1_TILE); break; case UC2PM_TILE: if (!(uc2pm_tile.LoadArtwork(UC2PM_FILE))) ArtworkMissing(UC2PM_TILE); break; case UE2PM_TILE: if (!(ue2pm_tile.LoadArtwork(UE2PM_FILE))) ArtworkMissing(UE2PM_TILE); break; case WB2PD_TILE: if (!(wb2pd_tile.LoadArtwork(WB2PD_FILE))) ArtworkMissing(WB2PD_TILE); break; case WC2PD_TILE: if (!(wc2pd_tile.LoadArtwork(WC2PD_FILE))) ArtworkMissing(WC2PD_TILE); break; case WD2PD_TILE: if (!(wd2pd_tile.LoadArtwork(WD2PD_FILE))) ArtworkMissing(WD2PD_TILE); break; }}/****************************** landscape::CreateTiles ******************************** This function creates a full set of empty tiles for the landscape (where a full set isROWS_IN_LANDSCAPE x COLUMNS_IN_LANDSCAPE tiles) and enough wasteland tiles to fill thescreen (which is defined to be ROWS_ON_SCREEN x COLUMNS_ON_SCREEN; be aware that if thesize of the tiles change, so too must these values). The CCBs are created using dynamicmemory allocation and the memory must be returned by making a call to ShutdownForRestartwhen the round is finished. The wasteland tiles are created based on the wastelanddescriptor loaded for the round and are thus ready for use, but the real landscape tiles will all be set to the same kind of tile as the wasteland tile. The function called RepaintAndRegisterTiles is then used to change the art in these tiles to that specifiedin the level_lookup_table.*****************************************************************************************/void landscape::CreateTiles (void){ int32 i,j; /***** create CCBs for all wasteland tiles *****/ wasteland_cels[0][0] = new(CCB); if (wasteland_cels[0][0] == (CCB *) NULL) { printf("CreateTiles couldn't get the wasteland memory it needed.\n"); exit(0); } switch (wasteland_descriptor) { case DA_TILE: if (da_tile == NULL) LoadArtwork(DA_TILE); memcpy(wasteland_cels[0][0],da_tile,sizeof(CCB)); break; case DB_TILE: if (db_tile == NULL) LoadArtwork(DB_TILE); memcpy(wasteland_cels[0][0],db_tile,sizeof(CCB)); break; case DC_TILE: if (dc_tile == NULL) LoadArtwork(DC_TILE); memcpy(wasteland_cels[0][0],dc_tile,sizeof(CCB)); break; case DD_TILE: if (dd_tile == NULL) LoadArtwork(DD_TILE); memcpy(wasteland_cels[0][0],dd_tile,sizeof(CCB)); break; case DE_TILE: if (de_tile == NULL) LoadArtwork(DE_TILE); memcpy(wasteland_cels[0][0],de_tile,sizeof(CCB)); break; case WA_TILE: if (wa_tile == NULL) LoadArtwork(WA_TILE); memcpy(wasteland_cels[0][0],wa_tile,sizeof(CCB)); break; case WB_TILE: if (wb_tile == NULL) LoadArtwork(WB_TILE); memcpy(wasteland_cels[0][0],wb_tile,sizeof(CCB)); break; case WC_TILE: if (wc_tile == NULL) LoadArtwork(WC_TILE); memcpy(wasteland_cels[0][0],wc_tile,sizeof(CCB)); break; case WD_TILE: if (wd_tile == NULL) LoadArtwork(WD_TILE); memcpy(wasteland_cels[0][0],wd_tile,sizeof(CCB)); break; case HA_TILE: if (ha_tile == NULL) LoadArtwork(HA_TILE); memcpy(wasteland_cels[0][0],ha_tile,sizeof(CCB)); break; case HB_TILE: if (hb_tile == NULL) LoadArtwork(HB_TILE); memcpy(wasteland_cels[0][0],hb_tile,sizeof(CCB)); break; case HC_TILE: if (hc_tile == NULL) LoadArtwork(HC_TILE); memcpy(wasteland_cels[0][0],hc_tile,sizeof(CCB)); break; case HD_TILE: if (hd_tile == NULL) LoadArtwork(HD_TILE); memcpy(wasteland_cels[0][0],hd_tile,sizeof(CCB)); break; case IA_TILE: if (ia_tile == NULL) LoadArtwork(IA_TILE); memcpy(wasteland_cels[0][0],ia_tile,sizeof(CCB)); check_for_ice = TRUE; break; case IB_TILE: if (ib_tile == NULL) LoadArtwork(IB_TILE); memcpy(wasteland_cels[0][0],ib_tile,sizeof(CCB)); check_for_ice = TRUE; break; case IC_TILE: if (ic_tile == NULL) LoadArtwork(IC_TILE); memcpy(wasteland_cels[0][0],ic_tile,sizeof(CCB)); check_for_ice = TRUE; break; case ID_TILE: if (id_tile == NULL) LoadArtwork(ID_TILE); memcpy(wasteland_cels[0][0],id_tile,sizeof(CCB)); check_for_ice = TRUE; break; case SA_TILE: if (sa_tile == NULL) LoadArtwork(SA_TILE); memcpy(wasteland_cels[0][0],sa_tile,sizeof(CCB)); break; case SB_TILE: if (sb_tile == NULL) LoadArtwork(SB_TILE); memcpy(wasteland_cels[0][0],sb_tile,sizeof(CCB)); break; case GA_TILE: if (ga_tile == NULL) LoadArtwork(GA_TILE); memcpy(wasteland_cels[0][0],ga_tile,sizeof(CCB)); break; case GB_TILE: if (gb_tile == NULL) LoadArtwork(GB_TILE); memcpy(wasteland_cels[0][0],gb_tile,sizeof(CCB)); break; case GC_TILE: if (gc_tile == NULL) LoadArtwork(GC_TILE); memcpy(wasteland_cels[0][0],gc_tile,sizeof(CCB)); break; case GD_TILE: if (gd_tile == NULL) LoadArtwork(GD_TILE); memcpy(wasteland_cels[0][0],gd_tile,sizeof(CCB)); break; case GE_TILE: if (ge_tile == NULL) LoadArtwork(GE_TILE); memcpy(wasteland_cels[0][0],ge_tile,sizeof(CCB)); break; case GF_TILE: if (gf_tile == NULL) LoadArtwork(GF_TILE); memcpy(wasteland_cels[0][0],gf_tile,sizeof(CCB)); break; case HE_TILE: if (he_tile == NULL) LoadArtwork(HE_TILE); memcpy(wasteland_cels[0][0],he_tile,sizeof(CCB)); break; case LA_TILE: if (la_tile == NULL) LoadArtwork(LA_TILE); memcpy(wasteland_cels[0][0],la_tile,sizeof(CCB)); break; case LB_TILE: if (lb_tile == NULL) LoadArtwork(LB_TILE); memcpy(wasteland_cels[0][0],lb_tile,sizeof(CCB)); break; case VA_TILE: if (va_tile == NULL) LoadArtwork(VA_TILE); memcpy(wasteland_cels[0][0],va_tile,sizeof(CCB)); break; case VB_TILE: if (vb_tile == NULL) LoadArtwork(VB_TILE); memcpy(wasteland_cels[0][0],vb_tile,sizeof(CCB)); break; case UA_TILE: if (ua_tile == NULL) LoadArtwork(UA_TILE); memcpy(wasteland_cels[0][0],ua_tile,sizeof(CCB)); break; case UB_TILE: if (ub_tile == NULL) LoadArtwork(UB_TILE); memcpy(wasteland_cels[0][0],ub_tile,sizeof(CCB)); break; case UC_TILE: if (uc_tile == NULL) LoadArtwork(UC_TILE); memcpy(wasteland_cels[0][0],uc_tile,sizeof(CCB)); break; case UD_TILE: if (ud_tile == NULL) LoadArtwork(UD_TILE); memcpy(wasteland_cels[0][0],ud_tile,sizeof(CCB)); break; case UE_TILE: if (ue_tile == NULL) LoadArtwork(UE_TILE); memcpy(wasteland_cels[0][0],ue_tile,sizeof(CCB)); break; default: printf("This level has an invalid wasteland type.\n"); if (da_tile == NULL) LoadArtwork(DA_TILE); memcpy(wasteland_cels[0][0],da_tile,sizeof(CCB)); break; } for (i = 1; i < ROWS_ON_SCREEN; i++) { wasteland_cels[i][0] = new(CCB); if (wasteland_cels[i][0] == (CCB *) NULL) { printf("CreateTiles couldn't get the wasteland memory it needed.\n"); exit(0); } memcpy(wasteland_cels[i][0],wasteland_cels[0][0],sizeof(CCB)); } for (i = 0; i < ROWS_ON_SCREEN; i++) { for (j = 1; j < COLUMNS_ON_SCREEN; j++) { wasteland_cels[i][j] = new(CCB); if (wasteland_cels[i][j] == (CCB *) NULL) { printf("CreateTiles couldn't get the wasteland memory it needed.\n"); exit(0); } memcpy(wasteland_cels[i][j],wasteland_cels[i][0],sizeof(CCB)); } } /***** create CCBs for all actual tiles *****/ landscape_cels[0][0] = new(CCB); if (landscape_cels[0][0] == (CCB *) NULL) { printf("CreateTiles couldn't get the memory it needed.\n"); exit(0); } memcpy(landscape_cels[0][0],wasteland_cels[0][0],sizeof(CCB)); for (i = 1; i < ROWS_IN_LANDSCAPE; i++) { landscape_cels[i][0] = new(CCB); if (landscape_cels[i][0] == (CCB *) NULL) { printf("CreateTiles couldn't get the memory it needed.\n"); exit(0); } memcpy(landscape_cels[i][0],landscape_cels[0][0],sizeof(CCB)); } for (i = 0; i < ROWS_IN_LANDSCAPE; i++) for (j = 1; j < COLUMNS_IN_LANDSCAPE; j++) { landscape_cels[i][j] = new(CCB); if (landscape_cels[i][j] == (CCB *) NULL) { printf("CreateTiles couldn't get the memory it needed.\n"); exit(0); } memcpy(landscape_cels[i][j],landscape_cels[i][0],sizeof(CCB)); }}/********************** landscape::PlaceTilesInStartingPositions ********************** The CreateTiles function does only what the name implies - it creates the tiles. This function should be called next, to position the tiles in the proper spots on the screen so that they all line up just right to create a cohesive landscape.*****************************************************************************************/void landscape::PlaceTilesInStartingPositions (void){ int32 i,j; /***** first, position all of the real tiles: *****/ /* position the first tile, from which all others derive */ landscape_cels[0][0]->ccb_XPos = INITIAL_UPPER_LEFT_X; landscape_cels[0][0]->ccb_YPos = INITIAL_UPPER_LEFT_Y; /* position the first ccb in each row */ for (i = 1; i < ROWS_IN_LANDSCAPE; i++) { landscape_cels[i][0]->ccb_XPos = landscape_cels[0][0]->ccb_XPos; landscape_cels[i][0]->ccb_YPos = landscape_cels[i-1][0]->ccb_YPos + (TILE_HEIGHT << 16); } /* Now position the other elements in each row */ for (i = 0; i < ROWS_IN_LANDSCAPE; i++) { for (j = 1; j < COLUMNS_IN_LANDSCAPE; j++) { landscape_cels[i][j]->ccb_XPos = landscape_cels[i][j-1]->ccb_XPos + (HALF_TILE_WIDTH << 16); if (j % 2) landscape_cels[i][j]->ccb_YPos = landscape_cels[i][j-1]->ccb_YPos - (HALF_TILE_HEIGHT << 16); else landscape_cels[i][j]->ccb_YPos = landscape_cels[i][j-1]->ccb_YPos + (HALF_TILE_HEIGHT << 16); } } /***** second, position all of the wasteland tiles: *****/ for (i = 0; i < ROWS_ON_SCREEN; i++) for (j = 0; j < COLUMNS_ON_SCREEN; j++) { wasteland_cels[i][j]->ccb_XPos = landscape_cels[i + 2][j]->ccb_XPos; wasteland_cels[i][j]->ccb_YPos = landscape_cels[i + 2][j]->ccb_YPos; } /***** Lastly, establish a pointer to the center of the playing field: *****/ center_tile = landscape_cels[7][7];}/************************* landscape::RepaintAndRegisterTiles ************************* Once the tiles are created, and positioned correctly on the screen, they then need to have the correct artwork inserted into them. That is the job of this function. It goes through the collection of landscape tiles and updates the artwork with the correct tile art as specified by the level_lookup_table. Furthermore, if the tile is an animated tile or a hazardous tile, it also performs whatever setup is required for those types of tiles and places them on the special linked lists appropriate for those tiles.*****************************************************************************************/void landscape::RepaintAndRegisterTiles(){ int32 i,j; for (i = 0; i < ROWS_IN_LANDSCAPE; i++) for (j = 0; j < COLUMNS_IN_LANDSCAPE; j++) { /* first, if the tile is to be an animated tile, place it on the anitile list */ if (level_lookup_table[i][j] == L1_TILE) { if (l1_tile.anim_pointer == NULL) LoadArtwork(L1_TILE); CreateAnimatedTile (&l1_tile, (STANDARD_FRAME_RATE >> 1),i,j,TRUE, level_lookup_table[i][j]); } if (level_lookup_table[i][j] == P1_TILE) { if (p1_tile.anim_pointer == NULL) LoadArtwork(P1_TILE); CreateAnimatedTile (&p1_tile, (STANDARD_FRAME_RATE >> 1),i,j,TRUE, level_lookup_table[i][j]); } if (level_lookup_table[i][j] == S1_TILE) { if (s1_tile.anim_pointer == NULL) LoadArtwork(S1_TILE); CreateAnimatedTile (&s1_tile,STANDARD_FRAME_RATE >> 2,i,j,TRUE, level_lookup_table[i][j]); } /* second, if the tile is a swamp tile, add it to the swamp list */ if ((level_lookup_table[i][j] == WA_TILE) || (level_lookup_table[i][j] == WB_TILE) || (level_lookup_table[i][j] == WC_TILE) || (level_lookup_table[i][j] == WD_TILE)) RegisterHazard(i,j); /* third, if the tile is an ice tile, set the check for ice flag */ if ((level_lookup_table[i][j] == IA_TILE) || (level_lookup_table[i][j] == IB_TILE) || (level_lookup_table[i][j] == IC_TILE) || (level_lookup_table[i][j] == ID_TILE)) check_for_ice = TRUE; /* lastly, no matter what kind of tile it is, the artwork must be installed */ ChangeArt(i,j); }}/************************** landscape::InitializeLandscape **************************** This function sets the global variables to their initial settings, and makes a seriesof calls to other functions that perform important initialization functions for thisclass. This function is meant to be called prior to each new round that uses a landscape.*****************************************************************************************/void landscape::InitializeLandscape (void) { int32 i,j; key_row = 0; key_column = 0; left_index = 0; right_index = COLUMNS_ON_SCREEN - 1; top_index = 0; bottom_index = ROWS_ON_SCREEN - 1; anitile_list = (anitile *) NULL; swamp_list = (hazard *) NULL; for (i = 0; i < ROWS_IN_LANDSCAPE; i++) for (j = 0; j < COLUMNS_IN_LANDSCAPE; j++) rock_lookup_table [i] [j] = FALSE; ShutdownUnusedArtwork(); CreateTiles(); PlaceTilesInStartingPositions(); RepaintAndRegisterTiles();}/**************************** landscape::DisplayLandscape ***************************** This function draws all of the visible landscape tiles into the screen bufferindicated by the external global variable g_screen. It also fills in any visible holesin the landscape by drawing wasteland tiles at any points where landscape tiles are notdrawn.*****************************************************************************************/void landscape::DisplayLandscape (bool only_maintain_endless_animations){ register int32 i,j; CCB *draw_me; register CCB *draw_me_next; MaintainAnimatedTiles(!(only_maintain_endless_animations)); draw_me = (CCB *) NULL; draw_me_next = draw_me; /* display all tiles on wasteland_visible_list that are really visible: */ for (i = 0; i < ROWS_ON_SCREEN; i++) { for (j = 0; j < COLUMNS_ON_SCREEN; j++) { wasteland_cels[i][j]->ccb_NextPtr = (CCB *) NULL; wasteland_cels[i][j]->ccb_Flags &= ~CCB_LAST; if ((wasteland_cels[i][j]->ccb_XPos < landscape_cels[0][0]->ccb_XPos) || (wasteland_cels[i][j]->ccb_XPos > landscape_cels[ROWS_IN_LANDSCAPE - 1] [COLUMNS_IN_LANDSCAPE - 1] ->ccb_XPos) || (wasteland_cels[i][j]->ccb_YPos < landscape_cels[0][1]->ccb_YPos) || (wasteland_cels[i][j]->ccb_YPos > landscape_cels[ROWS_IN_LANDSCAPE - 1] [COLUMNS_IN_LANDSCAPE - 2]->ccb_YPos)) { if (draw_me == (CCB *) NULL) { draw_me = wasteland_cels[i][j]; draw_me_next = draw_me; } else { draw_me_next->ccb_NextPtr = wasteland_cels[i][j]; draw_me_next = wasteland_cels[i][j]; } } } } /* now display all real tiles that are visible: */ for (i = 0; i < ROWS_IN_LANDSCAPE; i++) { for (j = 0; j < COLUMNS_IN_LANDSCAPE; j++) { landscape_cels[i][j]->ccb_NextPtr = (CCB *) NULL; landscape_cels[i][j]->ccb_Flags &= ~CCB_LAST; if ((landscape_cels[i][j]->ccb_XPos + (landscape_cels[i][j]->ccb_Width<<16) >= 0) && (landscape_cels[i][j]->ccb_XPos <= (SCREEN_WIDTH << 16)) && (landscape_cels[i][j]->ccb_YPos + (landscape_cels[i][j]->ccb_Height<<16) >=0) && (landscape_cels[i][j]->ccb_YPos <= (SCREEN_HEIGHT << 16))) { if (draw_me == (CCB *) NULL) { draw_me = landscape_cels[i][j]; draw_me_next = draw_me; } else { draw_me_next->ccb_NextPtr = landscape_cels[i][j]; draw_me_next = landscape_cels[i][j]; } } } } draw_me_next->ccb_Flags |= CCB_LAST; DrawScreenCels(g_screen.sc_Screens[g_screen.sc_curScreen],draw_me);}/***************************** landscape::MoveWorld *********************************** This function shifts the landscape a given distance in either or both directions as specified by the values of x_change and y_change. These parms can have either positiveor negative values depending on which direction you wish to move in. Note that this function moves only the real tiles; the application must subsequently call the function MaintainWasteland, which adjusts the set of wasteland tiles as needed to make them movein the same way that the main landscape did. These functions are kept separate becausethe application will usually wish to perform a move and then conduct collision detectionon the new scene before deciding that the move was legitimate. If it wasn't, it will wishto undo the move. Given this, we don't wish to waste any time moving the wasteland arounduntil the application commits to the new location position.*****************************************************************************************/void landscape::MoveWorld(int32 x_change, int32 y_change){ register int32 i,j; for (i = 0; i < ROWS_IN_LANDSCAPE; i++) for (j = 0; j < COLUMNS_IN_LANDSCAPE; j++) { landscape_cels[i][j]->ccb_XPos += x_change; landscape_cels[i][j]->ccb_YPos += y_change; }}/************************** landscape::MaintainWasteland ****************************** As described in the overall comments for this class of functions, the wasteland is displayed through the use of a small set of CCBs which are shuffled around when the landscape is scrolled so as to be kept on the screen at all times. This function therefore checks to see if such shuffling is needed and performs it if it is. If any of the CCBs have moved close enough to one edge of the screen to allow empty space behind the tiles to become visible, then this function peels the now-completely-invisible row (or column) of CCBs off of that side of the screen and glues it back onto the landscape on the opposite side of the screen.*****************************************************************************************/void landscape::MaintainWasteland(int32 x_change, int32 y_change){ register int32 i,j; /* start off by moving all cels as instructed */ for (i = 0; i < ROWS_ON_SCREEN; i++) for (j = 0; j < COLUMNS_ON_SCREEN; j++) { wasteland_cels[i][j]->ccb_XPos += x_change; wasteland_cels[i][j]->ccb_YPos += y_change; } /* Case 1: moving left (pull tiles off of right side and add them to left side) */ if (wasteland_cels[0][left_index]->ccb_XPos + (HALF_TILE_WIDTH << 16) >= 0) { key_column--; for (i = 0; i < ROWS_ON_SCREEN; i++) { wasteland_cels[i][right_index]->ccb_XPos = wasteland_cels[i][left_index]->ccb_XPos - (HALF_TILE_WIDTH << 16); } left_index = right_index; right_index--; if (right_index == -1) right_index = COLUMNS_ON_SCREEN - 1; } /* Case 2: moving right (pull tiles off of left side and add them to right side) */ else if (wasteland_cels[0][right_index]->ccb_XPos + (HALF_TILE_WIDTH << 16) <= (SCREEN_WIDTH << 16)) { key_column++; for (i = 0; i < ROWS_ON_SCREEN; i++) { wasteland_cels[i][left_index]->ccb_XPos = wasteland_cels[i][right_index]->ccb_XPos + (HALF_TILE_WIDTH << 16); } right_index = left_index; left_index++; if (left_index == COLUMNS_ON_SCREEN) left_index = 0; } /* Case 3: moving up (pull tiles off the bottom and add them to the top) */ if (wasteland_cels[top_index][1]->ccb_YPos + ((HALF_TILE_HEIGHT - 3) << 16) >= 0) { key_row--; for (i = 0; i < COLUMNS_ON_SCREEN; i++) { wasteland_cels[bottom_index][i]->ccb_YPos = wasteland_cels[top_index][i]->ccb_YPos - (TILE_HEIGHT << 16); } top_index = bottom_index; bottom_index--; if (bottom_index == -1) bottom_index = ROWS_ON_SCREEN - 1; return; } /* Case 4: moving down (pull tiles off the top and add them to the bottom) */ if (wasteland_cels[bottom_index][0]->ccb_YPos + ((HALF_TILE_HEIGHT + 3) << 16) <= (SCREEN_HEIGHT << 16)) { key_row++; for (i = 0; i < COLUMNS_ON_SCREEN; i++) { wasteland_cels[top_index][i]->ccb_YPos = wasteland_cels[bottom_index][i]->ccb_YPos + (TILE_HEIGHT << 16); } bottom_index = top_index; top_index++; if (top_index == ROWS_ON_SCREEN) top_index = 0; }}/****************************** landscape::ChangeArt ********************************** Changing the artwork a CCB considers its own is very easy: you just change the values of two pointers within its structure so that they reference a difference CCB's art information. However, which CCB should we go to in order to get our new art pointers?This routine figures that out, too. In addition, if the tile art that we need isn't resident in memory, we must also goout and get it.*****************************************************************************************/void landscape::ChangeArt(int32 row, int32 column){ CCB *source_cel; int32 x,y; source_cel = wasteland_cels[0][0]; switch (level_lookup_table[row][column]) { case GA_TILE: if (ga_tile == NULL) LoadArtwork(GA_TILE); source_cel = ga_tile; break; case GB_TILE: if (gb_tile == NULL) LoadArtwork(GB_TILE); source_cel = gb_tile; break; case GC_TILE: if (gc_tile == NULL) LoadArtwork(GC_TILE); source_cel = gc_tile; break; case GD_TILE: if (gd_tile == NULL) LoadArtwork(GD_TILE); source_cel = gd_tile; break; case GE_TILE: if (ge_tile == NULL) LoadArtwork(GE_TILE); source_cel = ge_tile; break; case GF_TILE: if (gf_tile == NULL) LoadArtwork(GF_TILE); source_cel = gf_tile; break; case HE_TILE: if (he_tile == NULL) LoadArtwork(HE_TILE); source_cel = he_tile; break; case DA_TILE: if (da_tile == NULL) LoadArtwork(DA_TILE); source_cel = da_tile; break; case DB_TILE: if (db_tile == NULL) LoadArtwork(DB_TILE); source_cel = db_tile; break; case DC_TILE: if (dc_tile == NULL) LoadArtwork(DC_TILE); source_cel = dc_tile; break; case DD_TILE: if (dd_tile == NULL) LoadArtwork(DD_TILE); source_cel = dd_tile; break; case WA_TILE: if (wa_tile == NULL) LoadArtwork(WA_TILE); source_cel = wa_tile; break; case HA_TILE: if (ha_tile == NULL) LoadArtwork(HA_TILE); source_cel = ha_tile; break; case HB_TILE: if (hb_tile == NULL) LoadArtwork(HB_TILE); source_cel = hb_tile; break; case HC_TILE: if (hc_tile == NULL) LoadArtwork(HC_TILE); source_cel = hc_tile; break; case HD_TILE: if (hd_tile == NULL) LoadArtwork(HD_TILE); source_cel = hd_tile; break; case LA_TILE: if (la_tile == NULL) LoadArtwork(LA_TILE); source_cel = la_tile; break; case LB_TILE: if (lb_tile == NULL) LoadArtwork(LB_TILE); source_cel = lb_tile; break; case SA_TILE: if (sa_tile == NULL) LoadArtwork(SA_TILE); source_cel = sa_tile; break; case SB_TILE: if (sb_tile == NULL) LoadArtwork(SB_TILE); source_cel = sb_tile; break; case PA_TILE: if (pa_tile == NULL) LoadArtwork(PA_TILE); source_cel = pa_tile; break; case PB_TILE: if (pb_tile == NULL) LoadArtwork(PB_TILE); source_cel = pb_tile; break; case PC_TILE: if (pc_tile == NULL) LoadArtwork(PC_TILE); source_cel = pc_tile; break; case IA_TILE: if (ia_tile == NULL) LoadArtwork(IA_TILE); source_cel = ia_tile; break; case IB_TILE: if (ib_tile == NULL) LoadArtwork(IB_TILE); source_cel = ib_tile; break; case ID_TILE: if (id_tile == NULL) LoadArtwork(ID_TILE); source_cel = id_tile; break; case DE_TILE: if (de_tile == NULL) LoadArtwork(DE_TILE); source_cel = de_tile; break; case WC_TILE: if (wc_tile == NULL) LoadArtwork(WC_TILE); source_cel = wc_tile; break; case WD_TILE: if (wd_tile == NULL) LoadArtwork(WD_TILE); source_cel = wd_tile; break; case PL_TILE: if (pl_tile == NULL) LoadArtwork(PL_TILE); source_cel = pl_tile; break; case PM_TILE: if (pm_tile == NULL) LoadArtwork(PM_TILE); source_cel = pm_tile; break; case PG_TILE: if (pg_tile == NULL) LoadArtwork(PG_TILE); source_cel = pg_tile; break; case WB_TILE: if (wb_tile == NULL) LoadArtwork(WB_TILE); source_cel = wb_tile; break; case IC_TILE: if (ic_tile == NULL) LoadArtwork(IC_TILE); source_cel = ic_tile; break; case PD_TILE: if (pd_tile == NULL) LoadArtwork(PD_TILE); source_cel = pd_tile; break; case PE_TILE: if (pe_tile == NULL) LoadArtwork(PE_TILE); source_cel = pe_tile; break; case PF_TILE: if (pf_tile == NULL) LoadArtwork(PF_TILE); source_cel = pf_tile; break; case PH_TILE: if (ph_tile == NULL) LoadArtwork(PH_TILE); source_cel = ph_tile; break; case PI_TILE: if (pi_tile == NULL) LoadArtwork(PI_TILE); source_cel = pi_tile; break; case PJ_TILE: if (pj_tile == NULL) LoadArtwork(PJ_TILE); source_cel = pj_tile; break; case PK_TILE: if (pk_tile == NULL) LoadArtwork(PK_TILE); source_cel = pk_tile; break; case VA_TILE: if (va_tile == NULL) LoadArtwork(VA_TILE); source_cel = va_tile; break; case VB_TILE: if (vb_tile == NULL) LoadArtwork(VB_TILE); source_cel = vb_tile; break; case UA_TILE: if (ua_tile == NULL) LoadArtwork(UA_TILE); source_cel = ua_tile; break; case UB_TILE: if (ub_tile == NULL) LoadArtwork(UB_TILE); source_cel = ub_tile; break; case UC_TILE: if (uc_tile == NULL) LoadArtwork(UC_TILE); source_cel = uc_tile; break; case UD_TILE: if (ud_tile == NULL) LoadArtwork(UD_TILE); source_cel = ud_tile; break; case UE_TILE: if (ue_tile == NULL) LoadArtwork(UE_TILE); source_cel = ue_tile; break; case DE2PJ_TILE: case HB2PC_TILE: case HC2PL_TILE: case HE2PC_TILE: case UA2P1_TILE: case UB2P1_TILE: case UC2PM_TILE: case UE2PM_TILE: case WB2PD_TILE: case WC2PD_TILE: case WD2PD_TILE: case DC2PJ_TILE: case IC2PB_TILE: case ID2PB_TILE: case GC2PA_TILE: case GD2PA_TILE: case GE2PA_TILE: case GF2PA_TILE: case GB2PA_TILE: case IA2PB_TILE: case HD2PC_TILE: case WA2PD_TILE: case GA2PE_TILE: case HA2PF_TILE: case IB2PG_TILE: case DD2PH_TILE: case DB2PI_TILE: case DA2PJ_TILE: case VA2PK_TILE: case UD2P1_TILE: case L1_TILE: case P1_TILE: case S1_TILE: source_cel = LocateAnimatedTile(row,column); break; } x = landscape_cels[row][column]->ccb_XPos; y = landscape_cels[row][column]->ccb_YPos; memcpy(landscape_cels[row][column],source_cel,sizeof(CCB)); landscape_cels[row][column]->ccb_XPos = x; landscape_cels[row][column]->ccb_YPos = y;}/*************************** landscape::RegisterHazard ******************************** When objects are moving around on the landscape, it is important to be able to check to see if any of those objects have walked onto a troublesome tile of some sort. In the interests of speed, we keep a list of tiles that are dangerous, so that we can compare an object's location to set of tiles that are meaningful instead of to all of the tiles in the universe. This function takes as input the row and column of a tile that is hazardous (or otherwise important) and adds it to this list.*****************************************************************************************/void landscape::RegisterHazard (int32 row, int32 column){ hazard *new_hazard; if ((level_lookup_table[row][column] == WA_TILE) || (level_lookup_table[row][column] == WB_TILE) || (level_lookup_table[row][column] == WC_TILE) || (level_lookup_table[row][column] == WD_TILE)) { new_hazard = new(hazard); new_hazard->row = row; new_hazard->column = column; new_hazard->next = swamp_list; swamp_list = new_hazard; return; }}/************************** landscape::RegisterRockyTile ****************************** This function takes as input the location of a rock and uses it to add an entry tothe rocky tiles list for the corresponding tile.*****************************************************************************************/void landscape::RegisterRockyTile (CCB *rock){ int32 i,j; for (i = 0; i < ROWS_IN_LANDSCAPE; i++) { for (j = 0; j < COLUMNS_IN_LANDSCAPE; j++) { if ((landscape_cels[i][j]->ccb_XPos == rock->ccb_XPos) && (landscape_cels[i][j]->ccb_YPos == rock->ccb_YPos)) { rock_lookup_table [i] [j] = TRUE; return; } } } printf("Hey! We've got a rock here that doesn't match up with a tile!\n");}/*************************** landscape::LoadPitFormation ******************************* This function takes as input the location of a purple or rainbow piece and uses it tomake sure that the pit formation animation for the corresponding tile is loaded.*****************************************************************************************/void landscape::LoadPitFormation (CCB *purple){ int32 i,j; for (i = 0; i < ROWS_IN_LANDSCAPE; i++) { for (j = 0; j < COLUMNS_IN_LANDSCAPE; j++) { if ((landscape_cels[i][j]->ccb_XPos == purple->ccb_XPos) && (landscape_cels[i][j]->ccb_YPos == purple->ccb_YPos)) { switch (level_lookup_table[i][j]) { case GB_TILE: if (gb2pa_tile.anim_pointer == NULL) LoadArtwork(GB2PA_TILE); g_art_usage[GB2PA_TILE] = TRUE; g_art_usage[PA_TILE] = TRUE; if (pa_tile == NULL) LoadArtwork(PA_TILE); break; case IA_TILE: if (ia2pb_tile.anim_pointer == NULL) LoadArtwork(IA2PB_TILE); g_art_usage[IA2PB_TILE] = TRUE; g_art_usage[PB_TILE] = TRUE; if (pb_tile == NULL) LoadArtwork(PB_TILE); break; case HD_TILE: if (hd2pc_tile.anim_pointer == NULL) LoadArtwork(HD2PC_TILE); g_art_usage[HD2PC_TILE] = TRUE; g_art_usage[PC_TILE] = TRUE; if (pc_tile == NULL) LoadArtwork(PC_TILE); break; case WA_TILE: if (wa2pd_tile.anim_pointer == NULL) LoadArtwork(WA2PD_TILE); g_art_usage[WA2PD_TILE] = TRUE; g_art_usage[PD_TILE] = TRUE; if (pd_tile == NULL) LoadArtwork(PD_TILE); break; case GA_TILE: if (ga2pe_tile.anim_pointer == NULL) LoadArtwork(GA2PE_TILE); g_art_usage[GA2PE_TILE] = TRUE; g_art_usage[PE_TILE] = TRUE; if (pe_tile == NULL) LoadArtwork(PE_TILE); break; case HA_TILE: if (ha2pf_tile.anim_pointer == NULL) LoadArtwork(HA2PF_TILE); g_art_usage[HA2PF_TILE] = TRUE; g_art_usage[PF_TILE] = TRUE; if (pf_tile == NULL) LoadArtwork(PF_TILE); break; case IB_TILE: if (ib2pg_tile.anim_pointer == NULL) LoadArtwork(IB2PG_TILE); g_art_usage[IB2PG_TILE] = TRUE; g_art_usage[PG_TILE] = TRUE; if (pg_tile == NULL) LoadArtwork(PG_TILE); break; case DD_TILE: if (dd2ph_tile.anim_pointer == NULL) LoadArtwork(DD2PH_TILE); g_art_usage[DD2PH_TILE] = TRUE; g_art_usage[PH_TILE] = TRUE; if (ph_tile == NULL) LoadArtwork(PH_TILE); break; case DB_TILE: if (db2pi_tile.anim_pointer == NULL) LoadArtwork(DB2PI_TILE); g_art_usage[DB2PI_TILE] = TRUE; g_art_usage[PI_TILE] = TRUE; if (pi_tile == NULL) LoadArtwork(PI_TILE); break; case DA_TILE: if (da2pj_tile.anim_pointer == NULL) LoadArtwork(DA2PJ_TILE); g_art_usage[DA2PJ_TILE] = TRUE; g_art_usage[PJ_TILE] = TRUE; if (pj_tile == NULL) LoadArtwork(PJ_TILE); break; case VA_TILE: if (va2pk_tile.anim_pointer == NULL) LoadArtwork(VA2PK_TILE); g_art_usage[VA2PK_TILE] = TRUE; g_art_usage[PK_TILE] = TRUE; if (pk_tile == NULL) LoadArtwork(PK_TILE); break; case UD_TILE: if (ud2p1_tile.anim_pointer == NULL) LoadArtwork(UD2P1_TILE); g_art_usage[UD2P1_TILE] = TRUE; g_art_usage[P1_TILE] = TRUE; if (p1_tile.anim_pointer == NULL) LoadArtwork(P1_TILE); break; case DC_TILE: if (dc2pj_tile.anim_pointer == NULL) LoadArtwork(DC2PJ_TILE); g_art_usage[DC2PJ_TILE] = TRUE; g_art_usage[PJ_TILE] = TRUE; if (pj_tile == NULL) LoadArtwork(PJ_TILE); break; case IC_TILE: if (ic2pb_tile.anim_pointer == NULL) LoadArtwork(IC2PB_TILE); g_art_usage[IC2PB_TILE] = TRUE; g_art_usage[PB_TILE] = TRUE; if (pb_tile == NULL) LoadArtwork(PB_TILE); break; case ID_TILE: if (id2pb_tile.anim_pointer == NULL) LoadArtwork(ID2PB_TILE); g_art_usage[ID2PB_TILE] = TRUE; g_art_usage[PB_TILE] = TRUE; if (pb_tile == NULL) LoadArtwork(PB_TILE); break; case GC_TILE: if (gc2pa_tile.anim_pointer == NULL) LoadArtwork(GC2PA_TILE); g_art_usage[GC2PA_TILE] = TRUE; g_art_usage[PA_TILE] = TRUE; if (pa_tile == NULL) LoadArtwork(PA_TILE); break; case GD_TILE: if (gd2pa_tile.anim_pointer == NULL) LoadArtwork(GD2PA_TILE); g_art_usage[GD2PA_TILE] = TRUE; g_art_usage[PA_TILE] = TRUE; if (pa_tile == NULL) LoadArtwork(PA_TILE); break; case GE_TILE: if (ge2pa_tile.anim_pointer == NULL) LoadArtwork(GE2PA_TILE); g_art_usage[GE2PA_TILE] = TRUE; g_art_usage[PA_TILE] = TRUE; if (pa_tile == NULL) LoadArtwork(PA_TILE); break; case GF_TILE: if (gf2pa_tile.anim_pointer == NULL) LoadArtwork(GF2PA_TILE); g_art_usage[GF2PA_TILE] = TRUE; g_art_usage[PA_TILE] = TRUE; if (pa_tile == NULL) LoadArtwork(PA_TILE); break; case DE_TILE: if (de2pj_tile.anim_pointer == NULL) LoadArtwork(DE2PJ_TILE); g_art_usage[DE2PJ_TILE] = TRUE; g_art_usage[PJ_TILE] = TRUE; if (pj_tile == NULL) LoadArtwork(PJ_TILE); break; case HB_TILE: if (hb2pc_tile.anim_pointer == NULL) LoadArtwork(HB2PC_TILE); g_art_usage[HB2PC_TILE] = TRUE; g_art_usage[PC_TILE] = TRUE; if (pc_tile == NULL) LoadArtwork(PC_TILE); break; case HC_TILE: if (hc2pl_tile.anim_pointer == NULL) LoadArtwork(HC2PL_TILE); g_art_usage[HC2PL_TILE] = TRUE; g_art_usage[PL_TILE] = TRUE; if (pl_tile == NULL) LoadArtwork(PL_TILE); break; case HE_TILE: if (he2pc_tile.anim_pointer == NULL) LoadArtwork(HE2PC_TILE); g_art_usage[HE2PC_TILE] = TRUE; g_art_usage[PC_TILE] = TRUE; if (pc_tile == NULL) LoadArtwork(PC_TILE); break; case UA_TILE: if (ua2p1_tile.anim_pointer == NULL) LoadArtwork(UA2P1_TILE); g_art_usage[UA2P1_TILE] = TRUE; g_art_usage[P1_TILE] = TRUE; if (p1_tile.anim_pointer == NULL) LoadArtwork(P1_TILE); break; case UB_TILE: if (ub2p1_tile.anim_pointer == NULL) LoadArtwork(UB2P1_TILE); g_art_usage[UB2P1_TILE] = TRUE; g_art_usage[P1_TILE] = TRUE; if (p1_tile.anim_pointer == NULL) LoadArtwork(P1_TILE); break; case UC_TILE: if (uc2pm_tile.anim_pointer == NULL) LoadArtwork(UC2PM_TILE); g_art_usage[UC2PM_TILE] = TRUE; g_art_usage[PM_TILE] = TRUE; if (pm_tile == NULL) LoadArtwork(PM_TILE); break; case UE_TILE: if (ue2pm_tile.anim_pointer == NULL) LoadArtwork(UE2PM_TILE); g_art_usage[UE2PM_TILE] = TRUE; g_art_usage[PM_TILE] = TRUE; if (pm_tile == NULL) LoadArtwork(PM_TILE); break; case WB_TILE: if (wb2pd_tile.anim_pointer == NULL) LoadArtwork(WB2PD_TILE); g_art_usage[WB2PD_TILE] = TRUE; g_art_usage[PD_TILE] = TRUE; if (pd_tile == NULL) LoadArtwork(PD_TILE); break; case WC_TILE: if (wc2pd_tile.anim_pointer == NULL) LoadArtwork(WC2PD_TILE); g_art_usage[WC2PD_TILE] = TRUE; g_art_usage[PD_TILE] = TRUE; if (pd_tile == NULL) LoadArtwork(PD_TILE); break; case WD_TILE: if (wd2pd_tile.anim_pointer == NULL) LoadArtwork(WD2PD_TILE); g_art_usage[WD2PD_TILE] = TRUE; g_art_usage[PD_TILE] = TRUE; if (pd_tile == NULL) LoadArtwork(PD_TILE); break; default: printf("Invalid placement of purple/rainbow piece.\n"); break; } return; } } } printf("Hey! We've got a purple/rainbow here that doesn't match up with a tile!\n");}/**************************** landscape::CheckTheWasteland ***************************** This function checks to see if an object is in the wasteland. In such as case, itreturns TRUE. If the object is on a tile right at the edge of the wasteland, this functionalso returns a pointer to the tile in question. We don't bother to do this if the objectis well into the wasteland, since the only time anyone will care about exactly which tilethe object is on is if the wasteland is deadly and a transition has been made.*****************************************************************************************/bool landscape::CheckTheWasteland(int32 center_x, int32 center_y, int32 cd_x, int32 cd_y, CCB* &which_tile){ register int32 i,j; /* Collision detection numbers need to be a tad smaller when dealing with hazards. */ cd_x -= HAZARD_X_COL_DETECT_ADJUSTMENT; cd_y -= HAZARD_Y_COL_DETECT_ADJUSTMENT; center_x = center_x << 16; center_y = center_y << 16; cd_x = cd_x << 16; cd_y = cd_y << 16; which_tile = (CCB *) NULL; /* First, check the inner perimeter and return FALSE if we are within it. */ if ((center_x > landscape_cels[ 0][ 1]->ccb_XPos - cd_x) && (center_x < landscape_cels[ 0][12]->ccb_XPos + cd_x + (TILE_WIDTH << 16)) && (center_y > landscape_cels[ 0][ 0]->ccb_YPos - cd_y) && (center_y < landscape_cels[13][ 1]->ccb_YPos + cd_y + (TILE_HEIGHT << 16))) return(FALSE); /* Second, check the outer perimeter and return TRUE if we are beyond it. */ if ((landscape_cels[ 1][ 1]->ccb_XPos - (TILE_WIDTH << 16) > center_x) || (landscape_cels[12][12]->ccb_XPos + ((TILE_WIDTH*2) << 16) < center_x) || (landscape_cels[ 0][ 0]->ccb_YPos - (TILE_HEIGHT << 16) > center_y) || (landscape_cels[13][ 1]->ccb_YPos + ((TILE_HEIGHT*2) << 16) < center_y)) return(TRUE); center_x = center_x >> 16; center_y = center_y >> 16; cd_x = cd_x >> 16; cd_y = cd_y >> 16; /* If we're still here, it means we are in the narrow strip between wasteland and */ /* playing area in which it is unclear which type of tile we are on. In this case, */ /* we must examine all of the wasteland tiles and see if we are sitting atop any */ /* of them. */ for (i = 0; i < ROWS_ON_SCREEN; i++) for (j = 0; j < COLUMNS_ON_SCREEN; j++) /* first make sure the wasteland tile is visible */ if ((wasteland_cels[i][j]->ccb_XPos < landscape_cels[0][0]->ccb_XPos) || (wasteland_cels[i][j]->ccb_XPos > landscape_cels[ROWS_IN_LANDSCAPE - 1] [COLUMNS_IN_LANDSCAPE - 1] ->ccb_XPos) || (wasteland_cels[i][j]->ccb_YPos < landscape_cels[0][1]->ccb_YPos) || (wasteland_cels[i][j]->ccb_YPos > landscape_cels[ROWS_IN_LANDSCAPE - 1] [COLUMNS_IN_LANDSCAPE - 2]->ccb_YPos)) { /* now see if we're on it */ if ((((wasteland_cels[i][j]->ccb_XPos>>16) < center_x - cd_x) && ((wasteland_cels[i][j]->ccb_XPos>>16)+TILE_WIDTH > center_x + cd_x) && ((wasteland_cels[i][j]->ccb_YPos>>16)+TILE_HEIGHT_25 < center_y - cd_y) && ((wasteland_cels[i][j]->ccb_YPos>>16)+TILE_HEIGHT_75 > center_y + cd_y)) || (((wasteland_cels[i][j]->ccb_YPos>>16) < center_y - cd_y) && ((wasteland_cels[i][j]->ccb_YPos>>16)+TILE_HEIGHT > center_y + cd_y) && ((wasteland_cels[i][j]->ccb_XPos>>16)+TILE_WIDTH_25 < center_x - cd_x) && ((wasteland_cels[i][j]->ccb_XPos>>16)+TILE_WIDTH_75 > center_x + cd_x))) { which_tile = wasteland_cels[i][j]; return(TRUE); } } /* if we still have not returned, then we aren't on a wasteland tile. */ return(FALSE);}/***************************** landscape::ExamineTile ********************************** This function is available for use in the case where the user wishes to know which tilean object is sitting on, regardless of whether the tile is hazardous or not. This function therefore goes through the entire list of objects and returns the correct tile. It returnsthe value AMBIGUOUS if the object is out in the wasteland, or it if is resting on the edge of a couple of tiles, leaving it unclear which tile it really is on.*****************************************************************************************/CCB* landscape::ExamineTile(int32 center_x, int32 center_y, int32 cd_x, int32 cd_y, int32 &tile_type){ int32 i,j; CCB *tile; /* First check to see if we're out in the wasteland */ if (CheckTheWasteland(center_x, center_y, cd_x, cd_y,tile)) { tile_type = wasteland_descriptor; return(tile); } /* Collision detection numbers need to be a tad smaller when dealing with hazards. */ cd_x -= HAZARD_X_COL_DETECT_ADJUSTMENT; cd_y -= HAZARD_Y_COL_DETECT_ADJUSTMENT; for (i = 0; i < ROWS_IN_LANDSCAPE; i++) for (j = 0; j < COLUMNS_IN_LANDSCAPE; j++) { if ((((landscape_cels[i][j]->ccb_XPos>>16) < center_x - cd_x) && ((landscape_cels[i][j]->ccb_XPos>>16) + TILE_WIDTH > center_x + cd_x) && ((landscape_cels[i][j]->ccb_YPos>>16) + TILE_HEIGHT_25 < center_y - cd_y) && ((landscape_cels[i][j]->ccb_YPos>>16) + TILE_HEIGHT_75 > center_y + cd_y)) || (((landscape_cels[i][j]->ccb_YPos>>16) < center_y - cd_y) && ((landscape_cels[i][j]->ccb_YPos>>16) + TILE_HEIGHT > center_y + cd_y) && ((landscape_cels[i][j]->ccb_XPos>>16) + TILE_WIDTH_25 < center_x - cd_x) && ((landscape_cels[i][j]->ccb_XPos>>16) + TILE_WIDTH_75 > center_x + cd_x))) { tile_type = level_lookup_table[i][j]; return (landscape_cels[i][j]); } } tile_type = AMBIGUOUS; return((CCB *) NULL);}/**************************** landscape::AmIOnThisTile ********************************* This function is available for use in the case where the user wishes to know if a givenobject is sitting on a given tile. It is not used in the functions that check for hazards,in general, because if a large number of tiles are to be checked, it is faster to do thechecks directly rather than make a lot of identical function calls. However, there arecases in which this function is useful.*****************************************************************************************/bool landscape::AmIOnThisTile (CCB *tile, int32 center_x, int32 center_y, int32 cd_x, int32 cd_y){ /* Collision detection numbers need to be a tad smaller when dealing with hazards. */ cd_x -= HAZARD_X_COL_DETECT_ADJUSTMENT; cd_y -= HAZARD_Y_COL_DETECT_ADJUSTMENT; if ((((tile->ccb_XPos>>16) < center_x - cd_x) && ((tile->ccb_XPos>>16) + TILE_WIDTH > center_x + cd_x) && ((tile->ccb_YPos>>16) + TILE_HEIGHT_25 < center_y - cd_y) && ((tile->ccb_YPos>>16) + TILE_HEIGHT_75 > center_y + cd_y)) || (((tile->ccb_YPos>>16) < center_y - cd_y) && ((tile->ccb_YPos>>16) + TILE_HEIGHT > center_y + cd_y) && ((tile->ccb_XPos>>16) + TILE_WIDTH_25 < center_x - cd_x) && ((tile->ccb_XPos>>16) + TILE_WIDTH_75 > center_x + cd_x))) return (TRUE); return(FALSE);}/***************************** landscape::CheckForSwamp ******************************** As the name implies, this function takes as input the size and position of an objectand then answers the question "Is this thing on a swamp tile?" The check is done firstby seeing if the object is in the wasteland, if the wasteland is swampy, and then bylooking at the tiles on the swamp list to see if there's a match.*****************************************************************************************/bool landscape::CheckForSwamp (int32 center_x, int32 center_y, int32 cd_x, int32 cd_y){ hazard *traversal_ptr; int32 i,j; CCB *dummy_tile; /* before looking through the whole list, find out if they are in a swamp wasteland */ if ((wasteland_descriptor == WA_TILE) || (wasteland_descriptor == WB_TILE) || (wasteland_descriptor == WC_TILE) || (wasteland_descriptor == WD_TILE)) { if (CheckTheWasteland(center_x, center_y, cd_x, cd_y, dummy_tile)) return(TRUE); } /* Collision detection numbers need to be a tad smaller when dealing with hazards. */ cd_x -= HAZARD_X_COL_DETECT_ADJUSTMENT; cd_y -= HAZARD_Y_COL_DETECT_ADJUSTMENT; traversal_ptr = swamp_list; while (traversal_ptr != (hazard *) NULL) { i = traversal_ptr->row; j = traversal_ptr->column; if ((((landscape_cels[i][j]->ccb_XPos>>16) < center_x - cd_x) && ((landscape_cels[i][j]->ccb_XPos>>16) + TILE_WIDTH > center_x + cd_x) && ((landscape_cels[i][j]->ccb_YPos>>16) + TILE_HEIGHT_25 < center_y - cd_y) && ((landscape_cels[i][j]->ccb_YPos>>16) + TILE_HEIGHT_75 > center_y + cd_y)) || (((landscape_cels[i][j]->ccb_YPos>>16) < center_y - cd_y) && ((landscape_cels[i][j]->ccb_YPos>>16) + TILE_HEIGHT > center_y + cd_y) && ((landscape_cels[i][j]->ccb_XPos>>16) + TILE_WIDTH_25 < center_x - cd_x) && ((landscape_cels[i][j]->ccb_XPos>>16) + TILE_WIDTH_75 > center_x + cd_x))) return (TRUE); traversal_ptr = traversal_ptr->next; } return(FALSE);}/************************** landscape::SelectSwampAtRandom ****************************** Because Zombies may be configured to rise out of a randomly selected swamp tile, weneed a way of picking a swamp tile at random. That's what this function does. It alsoreturns the total number of swamp tiles in the landscape (excluding the wasteland, ofcourse).*****************************************************************************************/int32 landscape::SelectSwampAtRandom (int32 &row, int32 &column){ hazard *traversal_ptr; int32 total_swamps; int32 where_we_are_now; int32 the_chosen_one; total_swamps = 0; traversal_ptr = swamp_list; while (traversal_ptr != (hazard *) NULL) { total_swamps++; traversal_ptr = traversal_ptr->next; } if (total_swamps == 0) { printf("There are no swamps, you Dunderhead!\n"); return(total_swamps); } the_chosen_one = RandomNumber(1,total_swamps); where_we_are_now = 1; traversal_ptr = swamp_list; while (where_we_are_now < the_chosen_one) { where_we_are_now++; traversal_ptr = traversal_ptr->next; } row = traversal_ptr->row; column = traversal_ptr->column; return(total_swamps);}/************************ landscape::CreateAnimatedTile ******************************* Since animated tiles (such as pools of water or pits filled with bubbling, oozing lava)require constant maintenance in order to give the illusion of activity, we maintain a list of the animated tiles in the landscape so as to avoid wasting time searching through the entire list of tiles just to find out which ones have animations. This function adds a new tile to the list of animated tiles and initializes the tile by linking the data structure to the master copy of the tile's animation, as provided in the parameters list. We also advance a random number of frames through the animation, so thatall of the tiles of this type won't be sychronized.*****************************************************************************************/void landscape::CreateAnimatedTile (anim_source *original, int32 frame_rate, int32 row, int32 column, bool endless_value, int32 new_type){ anitile *new_anitile; int32 i,j; new_anitile = new(anitile); new_anitile->tile_anim.InitializeAnim (original, frame_rate); new_anitile->endless = endless_value; new_anitile->row = row; new_anitile->column = column; new_anitile->tile_anim.Restart(); new_anitile->next = anitile_list; anitile_list = new_anitile; if ((new_type == L1_TILE) || (new_type == S1_TILE) || (new_type == P1_TILE)) { j = RandomNumber(1,10); for (i = 0; i <= j; i++) new_anitile->tile_anim.AdvanceFrame(); }}/*************************** landscape::LocateAnimatedTile **************************** During initialization, and when a tile is transformed (like when a new pit is created)it becomes necessary provide a pointer to the current frame's CCB of an animated tile, for use in displaying the animated tile artwork. This routine goes through the list of animated tiles searching for a match between the provided row and column and the row andcolumn values stored with the animated tile's entry on the list. (Yes, it's a clumsy wayof doing it, but it works and is excusable because the function is used only to get thingsset up.)*****************************************************************************************/CCB* landscape::LocateAnimatedTile(int32 row, int32 column){ anitile *traversal_ptr; traversal_ptr = anitile_list; while (traversal_ptr != (anitile *) NULL) { if ((traversal_ptr->row == row) && (traversal_ptr->column == column)) return(traversal_ptr->tile_anim.current_frame_ccb); traversal_ptr = traversal_ptr->next; } printf("Whoa! We didn't find any animated tiles that match!\n"); return((CCB *) NULL);}/************************* landscape::MaintainAnimatedTiles *************************** This function is called just prior to displaying the landscape, and it takes care ofadvancing the frame on all animated tiles in the landscape. In addition, if any of the animations are one-timers, such as transformation sequences that play once and end with the tile taking on a new appearance, then this function handles the cleanup needed when an animation of this type reaches the end. *****************************************************************************************/void landscape::MaintainAnimatedTiles(bool endless_only){ anitile *traversal_ptr,*lagging_ptr; int32 i,j; traversal_ptr = lagging_ptr = anitile_list; while (traversal_ptr != (anitile *) NULL) { if ((endless_only) && (!(traversal_ptr->endless))) traversal_ptr = traversal_ptr->next; else { i = traversal_ptr->row; j = traversal_ptr->column; if ((traversal_ptr->endless) || (!(traversal_ptr->tile_anim.AnimComplete()))) { /* if the scene goes on forever or it isn't over: advance frame and move on */ if ((level_lookup_table[i][j] == L1_TILE) || (level_lookup_table[i][j] == S1_TILE)) { if (traversal_ptr->tile_anim.AnimComplete()) { if (RandomNumber(1,20) == 1) traversal_ptr->tile_anim.AdvanceFrame(); } else traversal_ptr->tile_anim.AdvanceFrame(); } else traversal_ptr->tile_anim.AdvanceFrame(); landscape_cels[i][j]->ccb_SourcePtr = traversal_ptr->tile_anim.current_frame_ccb->ccb_SourcePtr; landscape_cels[i][j]->ccb_PLUTPtr = traversal_ptr->tile_anim.current_frame_ccb->ccb_PLUTPtr; lagging_ptr = traversal_ptr; traversal_ptr = traversal_ptr->next; } else { /* if the scene is done and it's a one-timer: get rid of it */ if (traversal_ptr == anitile_list) { anitile_list = anitile_list->next; traversal_ptr->tile_anim.ShutdownForRestart(); delete(traversal_ptr); traversal_ptr = lagging_ptr = anitile_list; } else { lagging_ptr->next = traversal_ptr->next; traversal_ptr->tile_anim.ShutdownForRestart(); delete(traversal_ptr); traversal_ptr = lagging_ptr->next; } /* then change the tile type value to the appropriate new tile type: */ switch (level_lookup_table[i][j]) { case GB2PA_TILE: TransformTile(i,j,PA_TILE); break; case IA2PB_TILE: TransformTile(i,j,PB_TILE); break; case HD2PC_TILE: TransformTile(i,j,PC_TILE); break; case WA2PD_TILE: TransformTile(i,j,PD_TILE); break; case GA2PE_TILE: TransformTile(i,j,PE_TILE); break; case HA2PF_TILE: TransformTile(i,j,PF_TILE); break; case IB2PG_TILE: TransformTile(i,j,PG_TILE); break; case DD2PH_TILE: TransformTile(i,j,PH_TILE); break; case DB2PI_TILE: TransformTile(i,j,PI_TILE); break; case DA2PJ_TILE: TransformTile(i,j,PJ_TILE); break; case VA2PK_TILE: TransformTile(i,j,PK_TILE); break; case UD2P1_TILE: TransformTile(i,j,P1_TILE); break; case DC2PJ_TILE: TransformTile(i,j,PJ_TILE); break; case IC2PB_TILE: TransformTile(i,j,PB_TILE); break; case ID2PB_TILE: TransformTile(i,j,PB_TILE); break; case GC2PA_TILE: TransformTile(i,j,PA_TILE); break; case GD2PA_TILE: TransformTile(i,j,PA_TILE); break; case GE2PA_TILE: TransformTile(i,j,PA_TILE); break; case GF2PA_TILE: TransformTile(i,j,PA_TILE); break; case DE2PJ_TILE: TransformTile(i,j,PJ_TILE); break; case HB2PC_TILE: TransformTile(i,j,PC_TILE); break; case HC2PL_TILE: TransformTile(i,j,PL_TILE); break; case HE2PC_TILE: TransformTile(i,j,PC_TILE); break; case UA2P1_TILE: TransformTile(i,j,P1_TILE); break; case UB2P1_TILE: TransformTile(i,j,P1_TILE); break; case UC2PM_TILE: TransformTile(i,j,PM_TILE); break; case UE2PM_TILE: TransformTile(i,j,PM_TILE); break; case WB2PD_TILE: TransformTile(i,j,PD_TILE); break; case WC2PD_TILE: TransformTile(i,j,PD_TILE); break; case WD2PD_TILE: TransformTile(i,j,PD_TILE); break; } } } }}/***************************** landscape::TransformTile ******************************* There are 2 versions of this function. The first (this one) does the actual transformation of a tile. The second (not this one) takes information about the location of the desired tile as input, finds the desired tile, and calls this version of the function. Transformation of a tile is usually a 2 stage process. First, the tile's type is changed to be an animated tile showing the transformation actually occurring (such as a crack appearing in the earth and widening to form a pit). Then, when the animation has run its course, the tile's type is again changed, to reflect its final form. Given this, and depending on the type of tile involved, this function may add elements to the animated tiles list and/or the hazardous tiles list.*****************************************************************************************/void landscape::TransformTile(int32 lookup_row, int32 lookup_column, int32 new_type){ level_lookup_table[lookup_row][lookup_column] = new_type; if (new_type == P1_TILE) CreateAnimatedTile (&p1_tile, (STANDARD_FRAME_RATE >> 1),lookup_row,lookup_column, TRUE, new_type); if (new_type == GB2PA_TILE) CreateAnimatedTile (&gb2pa_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == IA2PB_TILE) CreateAnimatedTile (&ia2pb_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == WA2PD_TILE) CreateAnimatedTile (&wa2pd_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == HD2PC_TILE) CreateAnimatedTile (&hd2pc_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == GA2PE_TILE) CreateAnimatedTile (&ga2pe_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == HA2PF_TILE) CreateAnimatedTile (&ha2pf_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == IB2PG_TILE) CreateAnimatedTile (&ib2pg_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == DD2PH_TILE) CreateAnimatedTile (&dd2ph_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == DB2PI_TILE) CreateAnimatedTile (&db2pi_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == DA2PJ_TILE) CreateAnimatedTile (&da2pj_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == VA2PK_TILE) CreateAnimatedTile (&va2pk_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == UD2P1_TILE) CreateAnimatedTile (&ud2p1_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == DC2PJ_TILE) CreateAnimatedTile (&dc2pj_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == IC2PB_TILE) CreateAnimatedTile (&ic2pb_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == ID2PB_TILE) CreateAnimatedTile (&id2pb_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == GC2PA_TILE) CreateAnimatedTile (&gc2pa_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == GD2PA_TILE) CreateAnimatedTile (&gd2pa_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == GE2PA_TILE) CreateAnimatedTile (&ge2pa_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == GF2PA_TILE) CreateAnimatedTile (&gf2pa_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == DE2PJ_TILE) CreateAnimatedTile (&de2pj_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == HB2PC_TILE) CreateAnimatedTile (&hb2pc_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == HC2PL_TILE) CreateAnimatedTile (&hc2pl_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == HE2PC_TILE) CreateAnimatedTile (&he2pc_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == UA2P1_TILE) CreateAnimatedTile (&ua2p1_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == UB2P1_TILE) CreateAnimatedTile (&ub2p1_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == UC2PM_TILE) CreateAnimatedTile (&uc2pm_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == UE2PM_TILE) CreateAnimatedTile (&ue2pm_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == WB2PD_TILE) CreateAnimatedTile (&wb2pd_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == WC2PD_TILE) CreateAnimatedTile (&wc2pd_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); if (new_type == WD2PD_TILE) CreateAnimatedTile (&wd2pd_tile,STANDARD_FRAME_RATE,lookup_row, lookup_column, FALSE, new_type); ChangeArt(lookup_row,lookup_column);}/***************************** landscape::TransformTile ******************************** There are 2 versions of this function. The first (not this one) does the actual transformation of a tile. The second (this one) takes information about the location of the desired tile as input, finds the desired tile, and calls the other version of this function. Please note that the caller of this routine will only know that it wants to form a pitwhere this tile is - it won't know the flavor of the tile in question, which in turn means that it doesn't know which pit transformation anim it should specify. Therefore, weassume that by specifying GB2PA_TILE, the caller means for us to use the appropriatepit formation animation.*****************************************************************************************/void landscape::TransformTile(int32 center_x, int32 center_y, int32 cd_x, int32 cd_y, int32 new_type){ int32 i,j; for (i = 0; i < ROWS_IN_LANDSCAPE; i++) for (j = 0; j < COLUMNS_IN_LANDSCAPE; j++) { if (((landscape_cels[i][j]->ccb_XPos >> 16) < center_x - cd_x) && ((landscape_cels[i][j]->ccb_XPos >> 16) + TILE_WIDTH > center_x + cd_x) && ((landscape_cels[i][j]->ccb_YPos >> 16) < center_y - cd_y) && ((landscape_cels[i][j]->ccb_YPos >> 16) + TILE_HEIGHT > center_y + cd_y)) { if (new_type == GB2PA_TILE) { switch (level_lookup_table[i][j]) { case IA_TILE: new_type = IA2PB_TILE; break; case HD_TILE: new_type = HD2PC_TILE; break; case WA_TILE: new_type = WA2PD_TILE; break; case GA_TILE: new_type = GA2PE_TILE; break; case HA_TILE: new_type = HA2PF_TILE; break; case IB_TILE: new_type = IB2PG_TILE; break; case DD_TILE: new_type = DD2PH_TILE; break; case DB_TILE: new_type = DB2PI_TILE; break; case DA_TILE: new_type = DA2PJ_TILE; break; case VA_TILE: new_type = VA2PK_TILE; break; case UD_TILE: new_type = UD2P1_TILE; break; case DC_TILE: new_type = DC2PJ_TILE; break; case IC_TILE: new_type = IC2PB_TILE; break; case ID_TILE: new_type = ID2PB_TILE; break; case GC_TILE: new_type = GC2PA_TILE; break; case GD_TILE: new_type = GD2PA_TILE; break; case GE_TILE: new_type = GE2PA_TILE; break; case GF_TILE: new_type = GF2PA_TILE; break; case DE_TILE: new_type = DE2PJ_TILE; break; case HB_TILE: new_type = HB2PC_TILE; break; case HC_TILE: new_type = HC2PL_TILE; break; case HE_TILE: new_type = HE2PC_TILE; break; case UA_TILE: new_type = UA2P1_TILE; break; case UB_TILE: new_type = UB2P1_TILE; break; case UC_TILE: new_type = UC2PM_TILE; break; case UE_TILE: new_type = UE2PM_TILE; break; case WB_TILE: new_type = WB2PD_TILE; break; case WC_TILE: new_type = WC2PD_TILE; break; case WD_TILE: new_type = WD2PD_TILE; break; } } TransformTile(i,j,new_type); return; } } printf("Uh-oh! Tried to transform a tile, but failed!\n");}/****************************** landscape::FetchTileCCB ******************************** In some cases, a user of the landscape class may know the row and column values of a tile in which they are interested, without having access to the actual CCB for that tile. This function supplies a pointer to the CCB of the tile at the supplied row and column position.*****************************************************************************************/CCB* landscape::FetchTileCCB(int32 lookup_row, int32 lookup_column){ return(landscape_cels[lookup_row][lookup_column]);}/************************* landscape::TotallyInTheWasteland ***************************** As the name suggests, this is a simple boolean function that takes a pair of coordinates and determines if that location is fully in the wasteland, or not.*****************************************************************************************/bool landscape::TotallyInTheWasteland(int32 center_x, int32 center_y){ if (((landscape_cels[ 1][ 1]->ccb_XPos >> 16) - TILE_WIDTH > center_x) || ((landscape_cels[12][12]->ccb_XPos >> 16) + (TILE_WIDTH * 2) < center_x) || ((landscape_cels[ 0][ 0]->ccb_YPos >> 16) - TILE_HEIGHT > center_y) || ((landscape_cels[13][ 1]->ccb_YPos >> 16) + (TILE_HEIGHT * 2) < center_y)) return(TRUE); return(FALSE);}/************************ landscape::TotallyInThePlayingArea **************************** As the name suggests, this is a simple boolean function that takes a pair of coordinates and determines if that location is fully in the playing area, or not.*****************************************************************************************/bool landscape::TotallyInThePlayingArea(int32 center_x, int32 center_y, int32 cd_x, int32 cd_y){ /* Collision detection numbers need to be a tad smaller when dealing with hazards. */ cd_x -= HAZARD_X_COL_DETECT_ADJUSTMENT; cd_y -= HAZARD_Y_COL_DETECT_ADJUSTMENT; center_x = center_x << 16; center_y = center_y << 16; cd_x = cd_x << 16; cd_y = cd_y << 16; if ((center_x > landscape_cels[ 0][ 1]->ccb_XPos - cd_x) && (center_x < landscape_cels[ 0][12]->ccb_XPos + cd_x + (TILE_WIDTH << 16)) && (center_y > landscape_cels[ 0][ 0]->ccb_YPos - cd_y) && (center_y < landscape_cels[13][ 1]->ccb_YPos + cd_y + (TILE_HEIGHT << 16))) return(TRUE); return(FALSE);}/************************ landscape::DetermineAdjacentTile **************************** Given the row index and column index into the landscape table of the tile someone iscurrently on, this function will return the row and column data for the tile adjacentto the known tile in whatever direction was requested. If there's no tile there, onlywasteland, then it returns -1, -1.****************************************************************************************/void landscape::DetermineAdjacentTile (int32 i, int32 j, int32 direction, int32 &adj_i, int32 &adj_j){ switch (direction) { case NORTH: adj_i = i - 1; adj_j = j; break; case SOUTH: adj_i = i + 1; adj_j = j; break; case WEST: adj_i = i; adj_j = j - 2; break; case EAST: adj_i = i; adj_j = j + 2; break; case NORTHEAST: if ((j % 2) == 1) adj_i = i - 1; else adj_i = i; adj_j = j + 1; break; case NORTHWEST: if ((j % 2) == 1) adj_i = i - 1; else adj_i = i; adj_j = j - 1; break; case SOUTHEAST: if ((j % 2) == 0) adj_i = i + 1; else adj_i = i; adj_j = j + 1; break; case SOUTHWEST: if ((j % 2) == 0) adj_i = i + 1; else adj_i = i; adj_j = j - 1; break; } /* if anything has fallen off of any edge anywhere, set both return values to -1. */ if ((adj_i < 0) || (adj_i >= ROWS_IN_LANDSCAPE) || (adj_j < 0) || (adj_j >= COLUMNS_IN_LANDSCAPE)) { adj_i = -1; adj_j = -1; }}/*************************** landscape::IsThisDangerous ********************************* This function takes as input the particulars of a given tile and returns TRUE if itsdangerous (with "danger" being defined by the special flags also provided to this routine)and FALSE if its harmless.*****************************************************************************************/bool landscape::IsThisDangerous(int32 row, int32 column, bool check_semi_hazards, bool view_rocks_as_hazards){ int32 check_me; if (row == -1) check_me = wasteland_descriptor; else check_me = level_lookup_table[row][column]; if ((check_me >= FIRST_PITFORMATION) && (check_me <= LAST_PITFORMATION)) return(TRUE); if ((check_me >= FIRST_PIT_TILE) && (check_me <= LAST_PIT_TILE)) return(TRUE); if (check_me == PK_TILE) return(TRUE); if ((check_me >= FIRST_LAVA_TILE) && (check_me <= LAST_LAVA_TILE)) return(TRUE); if (check_semi_hazards) { if ((check_me >= FIRST_SLIME_TILE) && (check_me <= LAST_SLIME_TILE)) return(TRUE); } if ((view_rocks_as_hazards) && (row != -1)) return(rock_lookup_table[row][column]); return(FALSE);}/*********************** landscape::DetermineWhatTileWeAreOn **************************** To check for hazards, we have to know where you are. This function tries to figurethis out, in terms of the row and column indexes of the landscape table. The only way tofigure this out is by comparing our location to the locations of each tile, in turn, inthe landscape until we get a match. However, this can be slow, particulary because seekersstart out in the wasteland and may spend a lot of time wandering around in the wastelandwithout ever being on a real tile. This is a drag. Therefore, we start by checking to see if we're completely out in the wasteland, andif we are, we return immediately instead of wasting time looking at other tiles. If we aren't in the wasteland, but yet we don't know where we are, then it's a goodbet that we're on one of the tiles at the border between wasteland and playing area.Therefore, the next thing we do is check against the tiles along the edge we are closestto. If we get a match, we return. At this point, having tried all the possible short cuts, we do the brute force search.*****************************************************************************************/int32 landscape::DetermineWhatTileWeAreOn(int32 center_x, int32 center_y, int32 cd_x, int32 cd_y, int32 &row, int32 &column, CCB* &tile_ccb){ int32 i,j; /* First check to see if we're indisputably out in the wasteland */ if (TotallyInTheWasteland(center_x, center_y)) { row = -1; column = -1; tile_ccb = (CCB *) NULL; return(wasteland_descriptor); } /* Then, if we aren't fully in the playing area, check only the edge tiles. */ if (!(TotallyInThePlayingArea(center_x, center_y, cd_x, cd_y))) { /* check the tiles along the left side. */ if ((ABS(center_x - FIND_CENTER_X(landscape_cels[0][1]))) <= TILE_WIDTH) { for (i = 0; i < ROWS_IN_LANDSCAPE; i++) for (j = 0; j < 2; j++) if (AmIOnThisTile(landscape_cels[i][j],center_x,center_y,cd_x,cd_y)) { row = i; column = j; return(level_lookup_table[i][j]); } } /* check the tiles along the right side. */ if ((ABS(center_x - FIND_CENTER_X(landscape_cels[13][12]))) <= TILE_WIDTH) { for (i = 0; i < ROWS_IN_LANDSCAPE; i++) for (j = 12; j < COLUMNS_IN_LANDSCAPE; j++) if (AmIOnThisTile(landscape_cels[i][j],center_x,center_y,cd_x,cd_y)) { row = i; column = j; return(level_lookup_table[i][j]); } } /* check the tiles along the top side. */ if ((ABS(center_y - FIND_CENTER_Y(landscape_cels[0][0]))) <= TILE_HEIGHT) { for (i = 0; i < 1; i++) for (j = 2; j < 12; j++) if (AmIOnThisTile(landscape_cels[i][j],center_x,center_y,cd_x,cd_y)) { row = i; column = j; return(level_lookup_table[i][j]); } } /* check the tiles along the bottom side. */ if ((ABS(center_y - FIND_CENTER_Y(landscape_cels[13][13]))) <= TILE_HEIGHT) { for (i = 13; i < ROWS_IN_LANDSCAPE; i++) for (j = 2; j < 12; j++) if (AmIOnThisTile(landscape_cels[i][j],center_x,center_y,cd_x,cd_y)) { row = i; column = j; return(level_lookup_table[i][j]); } } /* At this point, give up. We're in the wasteland... deal with it. */ row = -1; column = -1; return(AMBIGUOUS); } /* At this point, assume we're on a real tile. */ for (i = 0; i < ROWS_IN_LANDSCAPE; i++) for (j = 0; j < COLUMNS_IN_LANDSCAPE; j++) if (AmIOnThisTile(landscape_cels[i][j],center_x,center_y,cd_x,cd_y)) { row = i; column = j; return(level_lookup_table[i][j]); } /* If we're still here (which I doubt we ever will be) do a full check of the */ /* border before giving up and going home empty handed. */ if (CheckTheWasteland(center_x, center_y, cd_x, cd_y, tile_ccb)) { row = -1; column = -1; return(wasteland_descriptor); } row = -1; column = -1; return(AMBIGUOUS);}/***************************** landscape::CheckForDanger ******************************** This function takes all sorts of info about a seeker (or the dudemeyer) and returnstrue if that seeker is on top of a hazardous tile. The info it needs to figure this outis: a pair of coordinates, the object's size (measured as radius values for the x andy axes), the row and column of the tile we were most recently known to be on (thisfunction will update these values if they've changed; if the caller doesn't know them(typical at first) then -1,-1 should be provided so that we know to search all tilesuntil we find out just where we are), and 2 boolean values, check_semi_hazards, whichif true (and only if true) will cause us to consider slime tiles hazardous, andview_rocks_as_hazards, which if true (and only if true) will cause us to say that thetile is hazardous if there's a rock on it (this fact is used by smart seekers, whichavoid rocks by avoiding the entire tile as if it were dangerous).*****************************************************************************************/bool landscape::CheckForDanger(int32 center_x, int32 center_y, int32 cd_x, int32 cd_y, int32 &row, int32 &column, int32 &tile_type, CCB* &tile_ccb, bool check_semi_hazards, bool view_rocks_as_hazards){ int32 new_row; int32 new_column; int32 i; bool wasteland_checked; CCB *temp; /* if we don't know what tile we are on (usually 'cause we're in the wasteland, but */ /* not always) then we start by trying to find out. */ temp = (CCB *) NULL; if (row == -1) { i = DetermineWhatTileWeAreOn (center_x, center_y, cd_x, cd_y, row, column, temp); if (row == -1) { /* if we got -1 back from DetermineWhatTileWeAreOn, then either we are on the */ /* edge between 2 tiles or we're in the wasteland. In the first case, we */ /* return FALSE; in the second case, we check the wasteland tile for danger. */ if (i == AMBIGUOUS) return (FALSE); if (IsThisDangerous(row,column,check_semi_hazards,view_rocks_as_hazards)) { tile_ccb = temp; tile_type = wasteland_descriptor; return(TRUE); } return(FALSE); } } /* If we haven't returned yet, then we knew what tile we were on last time. Check */ /* to see if we're still on that tile. */ if (AmIOnThisTile (landscape_cels[row][column], center_x, center_y, cd_x, cd_y)) { if (IsThisDangerous(row,column,check_semi_hazards,view_rocks_as_hazards)) { tile_ccb = landscape_cels[row][column]; tile_type = level_lookup_table[row][column]; return(TRUE); } return (FALSE); } /* If we haven't returned yet, then we are no longer on the tile we were on last */ /* time. Check to see if we are on any of the adjacent tiles. */ wasteland_checked = FALSE; for (i = 0; i < 8; i++) { DetermineAdjacentTile (row,column,i,new_row,new_column); if ((new_row != -1) && (new_column != -1) && (AmIOnThisTile(landscape_cels[new_row][new_column],center_x,center_y,cd_x,cd_y))) { row = new_row; column = new_column; if (IsThisDangerous(row,column,check_semi_hazards,view_rocks_as_hazards)) { tile_type = level_lookup_table[row][column]; tile_ccb = landscape_cels[row][column]; return(TRUE); } return (FALSE); } if ((new_row == -1) && (wasteland_checked == FALSE)) { wasteland_checked = TRUE; if (CheckTheWasteland(center_x, center_y, cd_x, cd_y, temp)) { row = -1; column = -1; if (IsThisDangerous(row,column,check_semi_hazards,view_rocks_as_hazards)) { tile_ccb = temp; tile_type = wasteland_descriptor; return(TRUE); } return(FALSE); } } } /* If we haven't returned yet, then we aren't directly on top of any tile at all. */ /* Obviously in this case, we are not in danger. However, we need to make sure we */ /* haven't strayed too far from the tile we currently call home. */ if ((row != -1) && (column != -1)) { if (((ABS(center_x - FIND_CENTER_X(landscape_cels[row][column]))) > TILE_WIDTH_75) || ((ABS(center_y - FIND_CENTER_Y(landscape_cels[row][column]))) > TILE_HEIGHT_75)) { row = -1; column = -1; } } return(FALSE);}/************************* landscape::ShutdownForRestart ****************************** When a game ends, the player will either wish to quit or play again. In either case,this function should be called to surrender memory that was dynamically allocated duringthe game. Needless to say, it is particularly important that this function be calledwhenever a game is to be replayed; otherwise the memory that was allocated will be losttrack of and wasted.*****************************************************************************************/void landscape::ShutdownForRestart(void){ int32 i,j; anitile *anitile_traversal, *anitile_vanguard; hazard *hazards_traversal, *hazards_vanguard;printf("G"); /***** recover all memory used by animated tiles *****/ anitile_traversal = anitile_list; while (anitile_traversal != (anitile *) NULL) { anitile_vanguard = anitile_traversal->next; anitile_traversal->tile_anim.ShutdownForRestart(); delete(anitile_traversal); anitile_traversal = anitile_vanguard; }printf("a"); printf("m");printf("e"); /***** recover all memory used by swamp list *****/ hazards_traversal = swamp_list; while (hazards_traversal != (hazard *) NULL) { hazards_vanguard = hazards_traversal->next; delete(hazards_traversal); hazards_traversal = hazards_vanguard; }printf(" ");printf("o"); /***** recover all memory used by landscape tiles *****/ for (i = 0; i < ROWS_IN_LANDSCAPE; i++) for (j = 0; j < COLUMNS_IN_LANDSCAPE; j++) delete(landscape_cels[i][j]); printf("v"); /***** recover all memory used by wasteland tiles *****/ for (i = 0; i < ROWS_ON_SCREEN; i++) for (j = 0; j < COLUMNS_ON_SCREEN; j++) delete(wasteland_cels[i][j]);printf("e");}/*************************** landscape::ShutdownForExit ******************************* This function deallocates memory that was reserved for storage of artwork elementsthat are used repeatedly over a sequence of many games. This function should be calledonly when the program is about to be shutdown for good.*****************************************************************************************/void landscape::ShutdownForExit(void){ if (ga_tile != NULL) UnloadCel(ga_tile); if (gb_tile != NULL) UnloadCel(gb_tile); if (gc_tile != NULL) UnloadCel(gc_tile); if (gd_tile != NULL) UnloadCel(gd_tile); if (ge_tile != NULL) UnloadCel(ge_tile); if (gf_tile != NULL) UnloadCel(gf_tile); if (he_tile != NULL) UnloadCel(he_tile); if (da_tile != NULL) UnloadCel(da_tile); if (db_tile != NULL) UnloadCel(db_tile); if (dc_tile != NULL) UnloadCel(dc_tile); if (dd_tile != NULL) UnloadCel(dd_tile); if (wa_tile != NULL) UnloadCel(wa_tile); if (ha_tile != NULL) UnloadCel(ha_tile); if (hb_tile != NULL) UnloadCel(hb_tile); if (hc_tile != NULL) UnloadCel(hc_tile); if (hd_tile != NULL) UnloadCel(hd_tile); if (pa_tile != NULL) UnloadCel(pa_tile); if (pb_tile != NULL) UnloadCel(pb_tile); if (ia_tile != NULL) UnloadCel(ia_tile); if (sa_tile != NULL) UnloadCel(sa_tile); if (la_tile != NULL) UnloadCel(la_tile); if (lb_tile != NULL) UnloadCel(lb_tile); if (sb_tile != NULL) UnloadCel(sb_tile); if (ib_tile != NULL) UnloadCel(ib_tile); if (pc_tile != NULL) UnloadCel(pc_tile); s1_tile.ShutdownForExit(); l1_tile.ShutdownForExit(); p1_tile.ShutdownForExit(); gb2pa_tile.ShutdownForExit(); ia2pb_tile.ShutdownForExit(); hd2pc_tile.ShutdownForExit(); if (pg_tile != NULL) UnloadCel(pg_tile); if (wb_tile != NULL) UnloadCel(wb_tile); if (ic_tile != NULL) UnloadCel(ic_tile); if (pd_tile != NULL) UnloadCel(pd_tile); if (pe_tile != NULL) UnloadCel(pe_tile); if (pf_tile != NULL) UnloadCel(pf_tile); ud2p1_tile.ShutdownForExit(); va2pk_tile.ShutdownForExit(); da2pj_tile.ShutdownForExit(); db2pi_tile.ShutdownForExit(); dd2ph_tile.ShutdownForExit(); if (ua_tile != NULL) UnloadCel(ua_tile); if (ub_tile != NULL) UnloadCel(ub_tile); if (uc_tile != NULL) UnloadCel(uc_tile); if (ud_tile != NULL) UnloadCel(ud_tile); if (ue_tile != NULL) UnloadCel(ue_tile); if (va_tile != NULL) UnloadCel(va_tile); if (vb_tile != NULL) UnloadCel(vb_tile); if (pk_tile != NULL) UnloadCel(pk_tile); if (pj_tile != NULL) UnloadCel(pj_tile); if (pi_tile != NULL) UnloadCel(pi_tile); if (ph_tile != NULL) UnloadCel(ph_tile); if (id_tile != NULL) UnloadCel(id_tile); dc2pj_tile.ShutdownForExit(); ic2pb_tile.ShutdownForExit(); id2pb_tile.ShutdownForExit(); gc2pa_tile.ShutdownForExit(); gd2pa_tile.ShutdownForExit(); ge2pa_tile.ShutdownForExit(); gf2pa_tile.ShutdownForExit(); de2pj_tile.ShutdownForExit(); hb2pc_tile.ShutdownForExit(); hc2pl_tile.ShutdownForExit(); he2pc_tile.ShutdownForExit(); ua2p1_tile.ShutdownForExit(); ub2p1_tile.ShutdownForExit(); uc2pm_tile.ShutdownForExit(); ue2pm_tile.ShutdownForExit(); wb2pd_tile.ShutdownForExit(); wc2pd_tile.ShutdownForExit(); wd2pd_tile.ShutdownForExit(); if (de_tile != NULL) UnloadCel(de_tile); if (wc_tile != NULL) UnloadCel(wc_tile); if (wd_tile != NULL) UnloadCel(wd_tile); if (pl_tile != NULL) UnloadCel(pl_tile); if (pm_tile != NULL) UnloadCel(pm_tile);}/************************* landscape::ShutdownUnusedArtwork **************************** This function examines all of the art elements used by this class and gets rid of anythat are not currently needed, thus freeing up the memory this art was consuming for moreworthwhile causes. The way in which we know whether or not a piece of art is needed isby examining the values in the global art usage table (g_art_usage). This table is filledout by the function LoadLevel as the level parameters are parsed. Anything that isn'tset to TRUE in this table will not be needed during this level and can therefore safelybe discarded.*****************************************************************************************/void landscape::ShutdownUnusedArtwork(void){ if ((ga_tile != NULL) && (g_art_usage[GA_TILE] == FALSE)) { UnloadCel(ga_tile); ga_tile = (CCB *) NULL; } if ((gb_tile != NULL) && (g_art_usage[GB_TILE] == FALSE)) { UnloadCel(gb_tile); gb_tile = (CCB *) NULL; } if ((gc_tile != NULL) && (g_art_usage[GC_TILE] == FALSE)) { UnloadCel(gc_tile); gc_tile = (CCB *) NULL; } if ((gd_tile != NULL) && (g_art_usage[GD_TILE] == FALSE)) { UnloadCel(gd_tile); gd_tile = (CCB *) NULL; } if ((ge_tile != NULL) && (g_art_usage[GE_TILE] == FALSE)) { UnloadCel(ge_tile); ge_tile = (CCB *) NULL; } if ((gf_tile != NULL) && (g_art_usage[GF_TILE] == FALSE)) { UnloadCel(gf_tile); gf_tile = (CCB *) NULL; } if ((he_tile != NULL) && (g_art_usage[HE_TILE] == FALSE)) { UnloadCel(he_tile); he_tile = (CCB *) NULL; } if ((da_tile != NULL) && (g_art_usage[DA_TILE] == FALSE)) { UnloadCel(da_tile); da_tile = (CCB *) NULL; } if ((db_tile != NULL) && (g_art_usage[DB_TILE] == FALSE)) { UnloadCel(db_tile); db_tile = (CCB *) NULL; } if ((dc_tile != NULL) && (g_art_usage[DC_TILE] == FALSE)) { UnloadCel(dc_tile); dc_tile = (CCB *) NULL; } if ((dd_tile != NULL) && (g_art_usage[DD_TILE] == FALSE)) { UnloadCel(dd_tile); dd_tile = (CCB *) NULL; } if ((wa_tile != NULL) && (g_art_usage[WA_TILE] == FALSE)) { UnloadCel(wa_tile); wa_tile = (CCB *) NULL; } if ((ha_tile != NULL) && (g_art_usage[HA_TILE] == FALSE)) { UnloadCel(ha_tile); ha_tile = (CCB *) NULL; } if ((pa_tile != NULL) && (g_art_usage[PA_TILE] == FALSE)) { UnloadCel(pa_tile); pa_tile = (CCB *) NULL; } if ((pb_tile != NULL) && (g_art_usage[PB_TILE] == FALSE)) { UnloadCel(pb_tile); pb_tile = (CCB *) NULL; } if ((ia_tile != NULL) && (g_art_usage[IA_TILE] == FALSE)) { UnloadCel(ia_tile); ia_tile = (CCB *) NULL; } if ((sa_tile != NULL) && (g_art_usage[SA_TILE] == FALSE)) { UnloadCel(sa_tile); sa_tile = (CCB *) NULL; } if ((la_tile != NULL) && (g_art_usage[LA_TILE] == FALSE)) { UnloadCel(la_tile); la_tile = (CCB *) NULL; } if ((lb_tile != NULL) && (g_art_usage[LB_TILE] == FALSE)) { UnloadCel(lb_tile); lb_tile = (CCB *) NULL; } if ((sb_tile != NULL) && (g_art_usage[SB_TILE] == FALSE)) { UnloadCel(sb_tile); sb_tile = (CCB *) NULL; } if ((hb_tile != NULL) && (g_art_usage[HB_TILE] == FALSE)) { UnloadCel(hb_tile); hb_tile = (CCB *) NULL; } if ((hc_tile != NULL) && (g_art_usage[HC_TILE] == FALSE)) { UnloadCel(hc_tile); hc_tile = (CCB *) NULL; } if ((hd_tile != NULL) && (g_art_usage[HD_TILE] == FALSE)) { UnloadCel(hd_tile); hd_tile = (CCB *) NULL; } if ((ib_tile != NULL) && (g_art_usage[IB_TILE] == FALSE)) { UnloadCel(ib_tile); ib_tile = (CCB *) NULL; } if ((pc_tile != NULL) && (g_art_usage[PC_TILE] == FALSE)) { UnloadCel(pc_tile); pc_tile = (CCB *) NULL; } if ((pg_tile != NULL) && (g_art_usage[PG_TILE] == FALSE)) { UnloadCel(pg_tile); pg_tile = (CCB *) NULL; } if ((wb_tile != NULL) && (g_art_usage[WB_TILE] == FALSE)) { UnloadCel(wb_tile); wb_tile = (CCB *) NULL; } if ((ic_tile != NULL) && (g_art_usage[IC_TILE] == FALSE)) { UnloadCel(ic_tile); ic_tile = (CCB *) NULL; } if ((pd_tile != NULL) && (g_art_usage[PD_TILE] == FALSE)) { UnloadCel(pd_tile); pd_tile = (CCB *) NULL; } if ((pe_tile != NULL) && (g_art_usage[PE_TILE] == FALSE)) { UnloadCel(pe_tile); pe_tile = (CCB *) NULL; } if ((pf_tile != NULL) && (g_art_usage[PF_TILE] == FALSE)) { UnloadCel(pf_tile); pf_tile = (CCB *) NULL; } if ((id_tile != NULL) && (g_art_usage[ID_TILE] == FALSE)) { UnloadCel(id_tile); id_tile = (CCB *) NULL; } if ((ua_tile != NULL) && (g_art_usage[UA_TILE] == FALSE)) { UnloadCel(ua_tile); ua_tile = (CCB *) NULL; } if ((ub_tile != NULL) && (g_art_usage[UB_TILE] == FALSE)) { UnloadCel(ub_tile); ub_tile = (CCB *) NULL; } if ((uc_tile != NULL) && (g_art_usage[UC_TILE] == FALSE)) { UnloadCel(uc_tile); uc_tile = (CCB *) NULL; } if ((ud_tile != NULL) && (g_art_usage[UD_TILE] == FALSE)) { UnloadCel(ud_tile); ud_tile = (CCB *) NULL; } if ((ue_tile != NULL) && (g_art_usage[UE_TILE] == FALSE)) { UnloadCel(ue_tile); ue_tile = (CCB *) NULL; } if ((va_tile != NULL) && (g_art_usage[VA_TILE] == FALSE)) { UnloadCel(va_tile); va_tile = (CCB *) NULL; } if ((vb_tile != NULL) && (g_art_usage[VB_TILE] == FALSE)) { UnloadCel(vb_tile); vb_tile = (CCB *) NULL; } if ((pk_tile != NULL) && (g_art_usage[PK_TILE] == FALSE)) { UnloadCel(pk_tile); pk_tile = (CCB *) NULL; } if ((pj_tile != NULL) && (g_art_usage[PJ_TILE] == FALSE)) { UnloadCel(pj_tile); pj_tile = (CCB *) NULL; } if ((pi_tile != NULL) && (g_art_usage[PI_TILE] == FALSE)) { UnloadCel(pi_tile); pi_tile = (CCB *) NULL; } if ((ph_tile != NULL) && (g_art_usage[PH_TILE] == FALSE)) { UnloadCel(ph_tile); ph_tile = (CCB *) NULL; } if ((de_tile != NULL) && (g_art_usage[DE_TILE] == FALSE)) { UnloadCel(de_tile); de_tile = (CCB *) NULL; } if ((wc_tile != NULL) && (g_art_usage[WC_TILE] == FALSE)) { UnloadCel(wc_tile); wc_tile = (CCB *) NULL; } if ((wd_tile != NULL) && (g_art_usage[WD_TILE] == FALSE)) { UnloadCel(wd_tile); wd_tile = (CCB *) NULL; } if ((pl_tile != NULL) && (g_art_usage[PL_TILE] == FALSE)) { UnloadCel(pl_tile); pl_tile = (CCB *) NULL; } if ((pm_tile != NULL) && (g_art_usage[PM_TILE] == FALSE)) { UnloadCel(pm_tile); pm_tile = (CCB *) NULL; } if (g_art_usage[S1_TILE] == FALSE) s1_tile.ShutdownForExit(); if (g_art_usage[L1_TILE] == FALSE) l1_tile.ShutdownForExit(); if (g_art_usage[P1_TILE] == FALSE) p1_tile.ShutdownForExit(); if (g_art_usage[GB2PA_TILE] == FALSE) gb2pa_tile.ShutdownForExit(); if (g_art_usage[IA2PB_TILE] == FALSE) ia2pb_tile.ShutdownForExit(); if (g_art_usage[HD2PC_TILE] == FALSE) hd2pc_tile.ShutdownForExit(); if (g_art_usage[WA2PD_TILE] == FALSE) wa2pd_tile.ShutdownForExit(); if (g_art_usage[GA2PE_TILE] == FALSE) ga2pe_tile.ShutdownForExit(); if (g_art_usage[HA2PF_TILE] == FALSE) ha2pf_tile.ShutdownForExit(); if (g_art_usage[IB2PG_TILE] == FALSE) ib2pg_tile.ShutdownForExit(); if (g_art_usage[DC2PJ_TILE] == FALSE) dc2pj_tile.ShutdownForExit(); if (g_art_usage[IC2PB_TILE] == FALSE) ic2pb_tile.ShutdownForExit(); if (g_art_usage[ID2PB_TILE] == FALSE) id2pb_tile.ShutdownForExit(); if (g_art_usage[GC2PA_TILE] == FALSE) gc2pa_tile.ShutdownForExit(); if (g_art_usage[GD2PA_TILE] == FALSE) gd2pa_tile.ShutdownForExit(); if (g_art_usage[GE2PA_TILE] == FALSE) ge2pa_tile.ShutdownForExit(); if (g_art_usage[GF2PA_TILE] == FALSE) gf2pa_tile.ShutdownForExit(); if (g_art_usage[DE2PJ_TILE] == FALSE) de2pj_tile.ShutdownForExit(); if (g_art_usage[HB2PC_TILE] == FALSE) hb2pc_tile.ShutdownForExit(); if (g_art_usage[HC2PL_TILE] == FALSE) hc2pl_tile.ShutdownForExit(); if (g_art_usage[HE2PC_TILE] == FALSE) he2pc_tile.ShutdownForExit(); if (g_art_usage[UA2P1_TILE] == FALSE) ua2p1_tile.ShutdownForExit(); if (g_art_usage[UB2P1_TILE] == FALSE) ub2p1_tile.ShutdownForExit(); if (g_art_usage[UC2PM_TILE] == FALSE) uc2pm_tile.ShutdownForExit(); if (g_art_usage[UE2PM_TILE] == FALSE) ue2pm_tile.ShutdownForExit(); if (g_art_usage[WB2PD_TILE] == FALSE) wb2pd_tile.ShutdownForExit(); if (g_art_usage[WC2PD_TILE] == FALSE) wc2pd_tile.ShutdownForExit(); if (g_art_usage[WD2PD_TILE] == FALSE) wd2pd_tile.ShutdownForExit(); if (g_art_usage[UD2P1_TILE] == FALSE) ud2p1_tile.ShutdownForExit(); if (g_art_usage[VA2PK_TILE] == FALSE) va2pk_tile.ShutdownForExit(); if (g_art_usage[DA2PJ_TILE] == FALSE) da2pj_tile.ShutdownForExit(); if (g_art_usage[DB2PI_TILE] == FALSE) db2pi_tile.ShutdownForExit(); if (g_art_usage[DD2PH_TILE] == FALSE) dd2ph_tile.ShutdownForExit(); ScavengeMem();}/**************************************** EOF *******************************************/