]> 4ch.mooo.com Git - 16.git/blobdiff - src/lib/hp/play/c6_play.c
not done making demohp.c. i gotta get the files to the other lappy4
[16.git] / src / lib / hp / play / c6_play.c
diff --git a/src/lib/hp/play/c6_play.c b/src/lib/hp/play/c6_play.c
new file mode 100755 (executable)
index 0000000..995e6c7
--- /dev/null
@@ -0,0 +1,1429 @@
+/* Catacomb Apocalypse Source Code\r
+ * Copyright (C) 1993-2014 Flat Rock Software\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License along\r
+ * with this program; if not, write to the Free Software Foundation, Inc.,\r
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+ */\r
+\r
+// C3_PLAY.C\r
+\r
+#include "DEF.H"\r
+#include "gelib.h"\r
+#pragma hdrstop\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                LOCAL CONSTANTS\r
+\r
+=============================================================================\r
+*/\r
+\r
+#define POINTTICS      6\r
+#define PAUSE 300\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                GLOBAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+byte bcolor;\r
+short skytimer=-1,skytimer_reset;\r
+short groundtimer=-1,groundtimer_reset;\r
+\r
+unsigned scolor,gcolor;\r
+unsigned *skycolor,*groundcolor,debug_sky,debug_gnd;\r
+\r
+unsigned nocolorchange=0xFFFF;\r
+byte BGFLAGS,                          // global that holds all current flags\r
+         bgflag;                               // used by BG changer, this flag is set when done\r
+\r
+\r
+unsigned sky_daytonight[]={0x0909,0x0101,0x0808,0x0000,0xFFFF};\r
+//unsigned gnd_daytonight[]={0x0202,0xFFFF};\r
+\r
+unsigned sky_lightning[]={0x0101,0x0909,0x0f0f,0x0808,0x0000,0xFFFF};\r
+\r
+unsigned sky_colors[NUMLEVELS]={0x0000,0x0000,0x0000,0x0000,0x0808,\r
+                                                                                 0x0404,0x0000,0x0000,0x0000,0x0000,\r
+                                                                                 0x0000,0x0000,0x0000,0x0000,0x0606,\r
+                                                                                 0x0000,0x0000,0x0000,0x0000,0x0000,\r
+                                                                                 0x0000};\r
+unsigned gnd_colors[NUMLEVELS]={0x0202,0x0202,0x0606,0x0202,0x0707,\r
+                                                                                 0x0505,0x0808,0x0606,0x0101,0x0808,\r
+                                                                                 0x0606,0x0404,0x0808,0x0c0c,0x0e0e,\r
+                                                                                 0x0808,0x0808,0x0c0c,0x0000,0x0707,\r
+                                                                                 0x0808};\r
+\r
+\r
+ControlInfo    control;\r
+boolean                running=false; //,slowturn;\r
+\r
+int                    bordertime;\r
+objtype objlist[MAXACTORS],*new,*obj,*player,*lastobj,*objfreelist;\r
+\r
+#if USE_INERT_LIST\r
+inertobjtype inertobjlist[MAXINERTOBJ],*inert;\r
+#endif\r
+\r
+unsigned       farmapylookup[MAPSIZE];\r
+byte           *nearmapylookup[MAPSIZE];\r
+\r
+boolean                singlestep,godmode;\r
+int                    extravbls;\r
+status_flags    status_flag;\r
+int             status_delay;\r
+\r
+//\r
+// replacing refresh manager\r
+//\r
+unsigned       mapwidth,mapheight,tics,realtics;\r
+boolean                compatability;\r
+byte           *updateptr;\r
+unsigned       mapwidthtable[64];\r
+unsigned       uwidthtable[UPDATEHIGH];\r
+unsigned       blockstarts[UPDATEWIDE*UPDATEHIGH];\r
+#define        UPDATESCREENSIZE        (UPDATEWIDE*PORTTILESHIGH+2)\r
+#define        UPDATESPARESIZE         (UPDATEWIDE*2+4)\r
+#define UPDATESIZE                     (UPDATESCREENSIZE+2*UPDATESPARESIZE)\r
+byte           update[UPDATESIZE];\r
+\r
+int            mousexmove,mouseymove;\r
+int            pointcount,pointsleft;\r
+\r
+short BeepTime = 0;\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                LOCAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+void CalcBounds (objtype *ob);\r
+void DrawPlayScreen (void);\r
+void PreFullDisplay(void);\r
+void PostFullDisplay(boolean draw_view);\r
+\r
+\r
+//\r
+// near data map array (wall values only, get text number from far data)\r
+//\r
+byte           tilemap[MAPSIZE][MAPSIZE];\r
+byte           spotvis[MAPSIZE][MAPSIZE];\r
+objtype                *actorat[MAPSIZE][MAPSIZE];\r
+\r
+objtype dummyobj;\r
+\r
+int bordertime;\r
+int    objectcount;\r
+\r
+void StopMusic(void);\r
+void StartMusic(void);\r
+\r
+void CalibrateJoystick(short joynum);\r
+\r
+//==========================================================================\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+//     CenterWindow() - Generates a window of a given width & height in the\r
+//             middle of the screen\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+\r
+#define MAXX   320\r
+#define MAXY   120\r
+\r
+void   CenterWindow(word w,word h)\r
+{\r
+       US_DrawWindow(((MAXX / 8) - w) / 2,((MAXY / 8) - h) / 2,w,h);\r
+}\r
+\r
+//===========================================================================\r
+\r
+\r
+/*\r
+=====================\r
+=\r
+= CheckKeys\r
+=\r
+=====================\r
+*/\r
+\r
+void CheckKeys (void)\r
+{\r
+       extern boolean autofire;\r
+\r
+       if (screenfaded)                        // don't do anything with a faded screen\r
+               return;\r
+\r
+#if 0\r
+//\r
+// pause key wierdness can't be checked as a scan code\r
+//\r
+       if (Paused)\r
+       {\r
+               CenterWindow (8,3);\r
+               US_PrintCentered ("PAUSED");\r
+               VW_UpdateScreen ();\r
+//             SD_MusicOff();\r
+               IN_Ack();\r
+//             SD_MusicOn();\r
+               Paused = false;\r
+               if (MousePresent) Mouse(MDelta);        // Clear accumulated mouse movement\r
+       }\r
+       else\r
+       if (Keyboard[sc_Enter])                 // P = pause with no screen disruptioon\r
+       {\r
+//             SD_MusicOff();\r
+               DisplaySMsg("PAUSED",NULL);\r
+               IN_Ack();\r
+//             SD_MusicOn();\r
+               if (MousePresent) Mouse(MDelta);        // Clear accumulated mouse movement\r
+       }\r
+       else\r
+       if (Keyboard[sc_S])\r
+       {\r
+               char *Text[] = {{"Slow Mode ON"},{"Slow Mode OFF"}};\r
+\r
+               SlowMode ^= 1;\r
+               extravbls = SlowMode << 3;\r
+               CenterWindow (8,3);\r
+               US_PrintCentered (Text[SlowMode]);\r
+               VW_UpdateScreen ();\r
+//             SD_MusicOff();\r
+               IN_Ack();\r
+//             SD_MusicOn();\r
+               if (MousePresent) Mouse(MDelta);        // Clear accumulated mouse movement\r
+       }\r
+#endif\r
+\r
+\r
+// F2 - SOUND OPTIONS\r
+//\r
+       if (Keyboard[sc_F2])\r
+       {\r
+               int height=7;\r
+               boolean ChoiceMade = false;\r
+\r
+               if (AdLibPresent)\r
+                       height++;\r
+\r
+               VW_FixRefreshBuffer();\r
+               CenterWindow(22,height);\r
+               US_Print( "\n        1 )  NO SOUND \n");\r
+               US_Print(   "        2 )  PC  AUDIO \n");\r
+\r
+               if (AdLibPresent)\r
+                       US_Print("        3 ) ADLIB AUDIO\n");\r
+\r
+               US_Print( "\n       ESC)    EXIT    ");\r
+               VW_UpdateScreen();\r
+\r
+               // Switch audio device ON/OFF & load sounds if there\r
+               // was a change in the device.\r
+\r
+               do {\r
+\r
+                       if (Keyboard[1])                                                                // ESC - Exit\r
+                               ChoiceMade = true;\r
+                       else\r
+                       if (Keyboard[2])                                                                // 1 - No Sound\r
+                       {\r
+                               SD_SetSoundMode(sdm_Off);\r
+                               ChoiceMade = true;\r
+                       }\r
+                       else\r
+                       if (Keyboard[3])                                                        // 2 - PC Audio\r
+                       {\r
+                               SD_SetSoundMode(sdm_PC);\r
+//                             if (oldsoundmode != sdm_PC)\r
+                                       CA_LoadAllSounds();\r
+                               ChoiceMade = true;\r
+                       }\r
+                       else\r
+                       if ((Keyboard[4]) &&    AdLibPresent)           // 3 - AdLib Audio\r
+                       {\r
+                               SD_SetSoundMode(sdm_AdLib);\r
+//                             if (oldsoundmode != sdm_AdLib)\r
+                                       CA_LoadAllSounds();\r
+                               ChoiceMade = true;\r
+                       }\r
+\r
+               } while (!ChoiceMade);\r
+               tics = realtics = 1;\r
+               IN_ClearKeysDown();\r
+       }\r
+\r
+// F5 - CALIBRATE JOYSTICK\r
+//\r
+       if (Keyboard[sc_F5])\r
+       {\r
+               CalibrateJoystick(0);\r
+               tics = realtics = 1;\r
+               IN_ClearKeysDown();\r
+       }\r
+\r
+deadloop:;\r
+// ESCAPE - quits game\r
+//\r
+       if ((Keyboard[sc_Escape]) || (Flags & FL_DEAD))\r
+       {\r
+               char ch;\r
+\r
+               DisplaySMsg("Options", NULL);\r
+               status_flag = S_NONE;\r
+\r
+\r
+               if (Flags & FL_DEAD)\r
+               {\r
+                       char choices[] = {sc_Escape,sc_R,sc_N,sc_Q,0};\r
+                       ch = DisplayMsg("Restore          New          Quit",choices);\r
+                       DisplayMsg("                                      ", NULL);\r
+               }\r
+               else\r
+               {\r
+                       char choices[] = {sc_Escape,sc_S,sc_R,sc_N,sc_Q,0};\r
+                       ch = DisplayMsg("Save       Restore       New       Quit",choices);\r
+               }\r
+               DrawText(true);\r
+\r
+               switch (ch)\r
+               {\r
+                       case sc_S:\r
+                               if (!(Flags & FL_DEAD))\r
+                                       Keyboard[sc_F3] = true;\r
+                       break;\r
+\r
+                       case sc_R:\r
+                               Keyboard[sc_F4] = true;\r
+                       break;\r
+\r
+                       case sc_N:\r
+                               DisplaySMsg("Starting anew", NULL);\r
+                               VW_WaitVBL(60);\r
+                               playstate = ex_resetgame;\r
+                               Flags &= ~FL_DEAD;\r
+                       break;\r
+\r
+                       case sc_Q:\r
+                               DisplaySMsg("FARE THEE WELL!", NULL);\r
+                               VW_WaitVBL(120);\r
+                               if (!Flags & FL_QUICK)\r
+                                       VW_FadeOut();\r
+                               NormalScreen();\r
+                               FreeUpMemory();\r
+                               Quit(NULL);\r
+                       break;\r
+               }\r
+               tics = realtics = 1;\r
+       }\r
+\r
+// F1 - DISPLAY HELP\r
+//\r
+       if (Keyboard[sc_F1])\r
+       {\r
+               PrintHelp();\r
+\r
+#ifdef TEXT_PRESENTER\r
+\r
+               extern PresenterInfo MainHelpText;\r
+\r
+               VW_FadeOut();\r
+\r
+               FreeUpMemory();\r
+               if (!LoadPresenterScript("HELP.TXT",&MainHelpText))\r
+               {\r
+                       VW_FadeIn();\r
+                       CenterWindow(30,5);\r
+                       US_CPrint("\nError loading HELP file.\n");\r
+                       US_CPrint("Press any key.");\r
+                       IN_Ack();\r
+                       VW_FadeOut();\r
+               }\r
+               else\r
+               {\r
+                       VW_SetSplitScreen(200);\r
+                       bufferofs = displayofs = screenloc[0];\r
+                       VW_Bar(0,0,320,200,0);\r
+\r
+                       Display640();\r
+                       Presenter(&MainHelpText);\r
+                       Display320();\r
+               }\r
+               FreePresenterScript(&MainHelpText);\r
+#endif\r
+               VW_SetSplitScreen(120);\r
+               VW_SetScreen(screenloc[0],0);\r
+               screenpage = 0;\r
+               CacheScaleds();\r
+\r
+               bufferofs = 0;\r
+               RedrawStatusWindow();\r
+               ThreeDRefresh();\r
+               VW_FadeIn();\r
+               Keyboard[sc_F1] = false;\r
+               tics = realtics = 1;\r
+               IN_ClearKeysDown();\r
+       }\r
+\r
+// F3 - SAVE GAME\r
+//\r
+       if ((Keyboard[sc_F3]) && (!(Flags & FL_DEAD)))\r
+       {\r
+               PreFullDisplay();\r
+               GE_SaveGame();\r
+               PostFullDisplay(true);\r
+               tics = realtics = 1;\r
+               IN_ClearKeysDown();\r
+       }\r
+\r
+// F4 - LOAD GAME\r
+//\r
+       if (Keyboard[sc_F4])\r
+       {\r
+               PreFullDisplay();\r
+               if (GE_LoadGame())\r
+               {\r
+                       loadedgame = true;\r
+                       playstate = ex_loadedgame;\r
+                       Flags &= ~FL_DEAD;\r
+                       lasttext = -1;\r
+                       PostFullDisplay(false);\r
+               }\r
+               else\r
+               if (playstate == ex_victorious)\r
+               {\r
+                       PostFullDisplay(false);\r
+                       Victory(false);\r
+                       IN_Ack();\r
+                       Quit(NULL);\r
+               }\r
+               else\r
+                       PostFullDisplay(true);\r
+               Keyboard[sc_F5] = false;\r
+               tics = realtics = 1;\r
+               IN_ClearKeysDown();\r
+       }\r
+\r
+       if (Flags & FL_DEAD)\r
+               goto deadloop;\r
+\r
+//\r
+// F10-? debug keys\r
+//\r
+       if (Keyboard[sc_BackSpace])\r
+       {\r
+               DebugKeys();\r
+               if (MousePresent) Mouse(MDelta);        // Clear accumulated mouse movement\r
+               lasttimecount = TimeCount;\r
+       }\r
+}\r
+\r
+//-------------------------------------------------------------------------\r
+// PreFullDisplay()\r
+//-------------------------------------------------------------------------\r
+void PreFullDisplay()\r
+{\r
+       VW_FadeOut();\r
+       VW_SetSplitScreen(200);\r
+       bufferofs = displayofs = screenloc[0];\r
+       VW_Bar(0,0,320,200,0);\r
+}\r
+\r
+//-------------------------------------------------------------------------\r
+// PostFullDisplay()\r
+//-------------------------------------------------------------------------\r
+void PostFullDisplay(boolean draw_view)\r
+{\r
+       VW_SetSplitScreen(120);\r
+       bufferofs = 0;\r
+       RedrawStatusWindow();\r
+       if (draw_view)\r
+       {\r
+               ThreeDRefresh();\r
+               VW_FadeIn();\r
+       }\r
+}\r
+\r
+\r
+//===========================================================================\r
+\r
+/*\r
+#############################################################################\r
+\r
+                                 The objlist data structure\r
+\r
+#############################################################################\r
+\r
+objlist containt structures for every actor currently playing.  The structure\r
+is accessed as a linked list starting at *player, ending when ob->next ==\r
+NULL.  GetNewObj inserts a new object at the end of the list, meaning that\r
+if an actor spawn another actor, the new one WILL get to think and react the\r
+same frame.  RemoveObj unlinks the given object and returns it to the free\r
+list, but does not damage the objects ->next pointer, so if the current object\r
+removes itself, a linked list following loop can still safely get to the\r
+next element.\r
+\r
+<backwardly linked free list>\r
+\r
+#############################################################################\r
+*/\r
+\r
+\r
+/*\r
+=========================\r
+=\r
+= InitObjList\r
+=\r
+= Call to clear out the entire object list, returning them all to the free\r
+= list.  Allocates a special spot for the player.\r
+=\r
+=========================\r
+*/\r
+\r
+void InitObjList (void)\r
+{\r
+       int     i;\r
+\r
+       for (i=0;i<MAXACTORS;i++)\r
+       {\r
+               objlist[i].prev = &objlist[i+1];\r
+               objlist[i].next = NULL;\r
+       }\r
+\r
+       objlist[MAXACTORS-1].prev = NULL;\r
+\r
+       objfreelist = &objlist[0];\r
+       lastobj = NULL;\r
+\r
+       objectcount = 0;\r
+\r
+//\r
+// give the player and score the first free spots\r
+//\r
+       GetNewObj (false);\r
+       player = new;\r
+\r
+#if USE_INERT_LIST\r
+       inert = inertobjlist;\r
+#endif\r
+\r
+}\r
+\r
+//===========================================================================\r
+\r
+/*\r
+=========================\r
+=\r
+= GetNewObj\r
+=\r
+= Sets the global variable new to point to a free spot in objlist.\r
+= The free spot is inserted at the end of the liked list\r
+=\r
+= When the object list is full, the caller can either have it bomb out ot\r
+= return a dummy object pointer that will never get used\r
+=\r
+=========================\r
+*/\r
+\r
+void GetNewObj (boolean usedummy)\r
+{\r
+       if (!objfreelist)\r
+       {\r
+               if (usedummy)\r
+               {\r
+                       new = &dummyobj;\r
+                       return;\r
+               }\r
+               Quit ("GetNewObj: No free spots in objlist!");\r
+       }\r
+\r
+       new = objfreelist;\r
+       objfreelist = new->prev;\r
+       memset (new,0,sizeof(*new));\r
+\r
+       if (lastobj)\r
+               lastobj->next = new;\r
+       new->prev = lastobj;    // new->next is allready NULL from memset\r
+\r
+       new->active = false;\r
+       lastobj = new;\r
+\r
+       objectcount++;\r
+}\r
+\r
+//===========================================================================\r
+\r
+/*\r
+=========================\r
+=\r
+= RemoveObj\r
+=\r
+= Add the given object back into the free list, and unlink it from it's\r
+= neighbors\r
+=\r
+=========================\r
+*/\r
+\r
+void RemoveObj (objtype *gone)\r
+{\r
+       objtype **spotat;\r
+\r
+       if (gone == player)\r
+               Quit ("RemoveObj: Tried to remove the player!");\r
+\r
+//\r
+// fix the next object's back link\r
+//\r
+       if (gone == lastobj)\r
+               lastobj = (objtype *)gone->prev;\r
+       else\r
+               gone->next->prev = gone->prev;\r
+\r
+//\r
+// fix the previous object's forward link\r
+//\r
+       gone->prev->next = gone->next;\r
+\r
+//\r
+// add it back in to the free list\r
+//\r
+       gone->prev = objfreelist;\r
+       objfreelist = gone;\r
+\r
+       objectcount--;\r
+}\r
+\r
+#if USE_INERT_LIST\r
+\r
+//--------------------------------------------------------------------------\r
+// MoveObjToInert()\r
+//--------------------------------------------------------------------------\r
+void MoveObjToInert(objtype *obj)\r
+{\r
+\r
+       if (inert == &inertobjlist[MAXINERTOBJ])\r
+               return;\r
+\r
+// Transfer info needed by inert objtype\r
+//\r
+       inert->x = obj->x;\r
+       inert->y = obj->y;\r
+       inert->size = obj->size;\r
+       inert->viewx = obj->viewx;\r
+       inert->tilex = obj->tilex;\r
+       inert->tiley = obj->tiley;\r
+       inert->state = obj->state;\r
+       inert->ticcount = obj->ticcount;\r
+\r
+// Setup links between inert objects\r
+//\r
+       if (inert != inertobjlist)\r
+               (inert-1)->next = inert;\r
+       inert->next = NULL;\r
+       inert++;\r
+\r
+// Free 'real' object from list.\r
+//\r
+       RemoveObj(obj);\r
+}\r
+\r
+#endif\r
+\r
+//==========================================================================\r
+\r
+/*\r
+===================\r
+=\r
+= PollControls\r
+=\r
+===================\r
+*/\r
+\r
+void PollControls (void)\r
+{\r
+       unsigned buttons;\r
+\r
+       IN_ReadControl(0,&control);\r
+\r
+       if (MousePresent)\r
+       {\r
+               Mouse(MButtons);\r
+               buttons = _BX;\r
+               Mouse(MDelta);\r
+               mousexmove = _CX;\r
+               mouseymove = _DX;\r
+\r
+               if (buttons&1)\r
+                       control.button0 = 1;\r
+               if (buttons&2)\r
+                       control.button1 = 1;\r
+\r
+       }\r
+\r
+       if (Keyboard[sc_V] || Keyboard[sc_Tab])\r
+               running = true;\r
+       else\r
+               running = false;\r
+}\r
+\r
+//==========================================================================\r
+\r
+#if 0\r
+/*\r
+=================\r
+=\r
+= StopMusic\r
+=\r
+=================\r
+*/\r
+\r
+void StopMusic(void)\r
+{\r
+       int     i;\r
+\r
+       SD_MusicOff();\r
+       for (i = 0;i < LASTMUSIC;i++)\r
+               if (audiosegs[STARTMUSIC + i])\r
+               {\r
+                       MM_SetPurge(&((memptr)audiosegs[STARTMUSIC + i]),3);\r
+                       MM_SetLock(&((memptr)audiosegs[STARTMUSIC + i]),false);\r
+               }\r
+}\r
+\r
+//==========================================================================\r
+\r
+\r
+/*\r
+=================\r
+=\r
+= StartMusic\r
+=\r
+=================\r
+*/\r
+\r
+// JAB - Cache & start the appropriate music for this level\r
+void StartMusic(void)\r
+{\r
+       musicnames      chunk;\r
+\r
+       SD_MusicOff();\r
+       chunk = TOOHOT_MUS;\r
+//     if ((chunk == -1) || (MusicMode != smm_AdLib))\r
+//DEBUG control panel          return;\r
+\r
+       MM_BombOnError (false);\r
+       CA_CacheAudioChunk(STARTMUSIC + chunk);\r
+       MM_BombOnError (true);\r
+       if (mmerror)\r
+               mmerror = false;\r
+       else\r
+       {\r
+               MM_SetLock(&((memptr)audiosegs[STARTMUSIC + chunk]),true);\r
+               SD_StartMusic((MusicGroup far *)audiosegs[STARTMUSIC + chunk]);\r
+       }\r
+}\r
+#endif\r
+\r
+//==========================================================================\r
+\r
+\r
+/*\r
+===================\r
+=\r
+= PlayLoop\r
+=\r
+===================\r
+*/\r
+\r
+void PlayLoop (void)\r
+{\r
+       char shot_color[3] = {4,9,14};\r
+\r
+       int allgems[5]={GEM_DELAY_TIME,         // used for Q & D comparison\r
+                                                GEM_DELAY_TIME,                // for having all gems...\r
+                                                GEM_DELAY_TIME,                // the "allgems" declaration MUST\r
+                                                GEM_DELAY_TIME,                // match the "gems" declaration in\r
+                                                GEM_DELAY_TIME         // the gametype structure!\r
+                                               };\r
+\r
+//     int originx=0;\r
+//     int i=100;\r
+       signed long dx,dy,radius,psin,pcos,newx,newy;\r
+       int             give;\r
+       short objnum;\r
+       signed long ox,oy,xl,xh,yl,yh,px,py,norm_dx,norm_dy;\r
+       short o_radius;\r
+\r
+       void (*think)();\r
+\r
+       ingame = true;\r
+       playstate = TimeCount = 0;\r
+       gamestate.shotpower = handheight = 0;\r
+       pointcount = pointsleft = 0;\r
+\r
+       status_flag = S_NONE;\r
+\r
+#if 0\r
+       // setup sky/ground colors and effects (based on level)\r
+       //\r
+       switch (gamestate.mapon)\r
+       {\r
+               case 255:\r
+                       if (!(BGFLAGS & BGF_NIGHT))\r
+                       {\r
+                               InitBgChange(3*60,sky_daytonight,-1,NULL,BGF_NIGHT);\r
+                               groundcolor = &gnd_colors[0];\r
+                       }\r
+                       else\r
+                       {\r
+                               skycolor = &sky_colors[0];\r
+                               groundcolor = &gnd_colors[0];\r
+                       }\r
+               break;\r
+\r
+               default:\r
+                       skycolor = &sky_colors[gamestate.mapon];\r
+                       groundcolor = &gnd_colors[gamestate.mapon];\r
+                       skytimer = groundtimer = -1;\r
+               break;\r
+       }\r
+#endif\r
+\r
+       BGFLAGS |= BGF_NOT_LIGHTNING;\r
+       skytimer = groundtimer = -1;\r
+\r
+       debug_gnd = *groundcolor;\r
+       debug_sky = *skycolor;\r
+       RedrawStatusWindow();\r
+       ThreeDRefresh();\r
+       if (screenfaded)\r
+               VW_FadeIn();\r
+\r
+#ifndef PROFILE\r
+       fizzlein = true;                                // fizzle fade in the first refresh\r
+#endif\r
+       TimeCount = lasttimecount = lastnuke = 0;\r
+\r
+       PollControls ();                                // center mouse\r
+//     StartMusic ();\r
+       do\r
+       {\r
+#ifndef PROFILE\r
+               PollControls();\r
+#else\r
+               control.xaxis = 1;\r
+               if (++TimeCount == 300)\r
+                       return;\r
+#endif\r
+               DisplayStatus(&status_flag);\r
+\r
+               objnum=0;\r
+               for (obj = player;obj;obj = obj->next)\r
+               {\r
+                       if ((obj->active >= yes) && (!(FreezeTime && (obj!=player))))\r
+                       {\r
+                               if (obj->ticcount)\r
+                               {\r
+                                       obj->ticcount-=realtics;\r
+                                       while ( obj->ticcount <= 0)\r
+                                       {\r
+                                               think = obj->state->think;\r
+                                               if (think)\r
+                                               {\r
+                                                       statetype *oldstate=obj->state;\r
+\r
+                                                       think (obj);\r
+                                                       if (!obj->state)\r
+                                                       {\r
+                                                               RemoveObj (obj);\r
+                                                               goto nextactor;\r
+                                                       }\r
+                                                       if (obj->state != oldstate)\r
+                                                               break;\r
+                                               }\r
+\r
+                                               obj->state = obj->state->next;\r
+                                               if (!obj->state)\r
+                                               {\r
+                                                       RemoveObj (obj);\r
+                                                       goto nextactor;\r
+                                               }\r
+                                               if (!obj->state->tictime)\r
+                                               {\r
+                                                       obj->ticcount = 0;\r
+                                                       goto nextactor;\r
+                                               }\r
+                                               if (obj->state->tictime>0)\r
+                                                       obj->ticcount += obj->state->tictime;\r
+                                       }\r
+                               }\r
+\r
+                               think = obj->state->think;\r
+                               if (think)\r
+                               {\r
+                                       think (obj);\r
+                                       if (!obj->state)\r
+                                               RemoveObj (obj);\r
+                               }\r
+nextactor:;\r
+                       }\r
+\r
+                       // keep a list of objects around the player for radar updates\r
+                       //\r
+                               if (obj == player)\r
+                               {\r
+                                       px = player->x;\r
+                                       py = player->y;\r
+                                       psin = sintable[player->angle];\r
+                                       pcos = costable[player->angle];\r
+                                       xl = px-((long)RADAR_WIDTH<<TILESHIFT)/2;\r
+                                       xh = px+((long)RADAR_WIDTH<<TILESHIFT)/2-1;\r
+                                       yl = py-((long)RADAR_HEIGHT<<TILESHIFT)/2;\r
+                                       yh = py+((long)RADAR_HEIGHT<<TILESHIFT)/2;\r
+                               }\r
+\r
+                               if (objnum > MAX_RADAR_BLIPS-2)\r
+                                       objnum = MAX_RADAR_BLIPS-2;\r
+\r
+                               ox = obj->x;\r
+                               oy = obj->y;\r
+\r
+\r
+                               if ((ox >= xl) && (ox <= xh) && (oy >= yl) && (oy <= yh))\r
+                               {\r
+                                       norm_dx = (dx = px-ox)>>TILESHIFT;\r
+                                       norm_dy = (dy = oy-py)>>TILESHIFT;\r
+\r
+                                       o_radius = IntSqrt((norm_dx * norm_dx) + (norm_dy * norm_dy));\r
+\r
+                                       if (o_radius < RADAR_RADIUS)\r
+                                       {\r
+                                               newx = FixedByFrac(dy,pcos)-FixedByFrac(dx,psin);\r
+                                               newy = FixedByFrac(dy,psin)+FixedByFrac(dx,pcos);\r
+\r
+                                               RadarXY[objnum][0]=newx>>TILESHIFT;\r
+                                               RadarXY[objnum][1]=newy>>TILESHIFT;\r
+\r
+                                               // Define color to use for this object...\r
+                                               //\r
+\r
+                                               switch (obj->obclass)\r
+                                               {\r
+                       // NO GEM NEEDED\r
+                       //\r
+                                       // THE WIZARD! (YOU)\r
+                                       //\r
+                                                       case playerobj:\r
+                                                               RadarXY[objnum++][2]=15;\r
+                                                       break;\r
+\r
+                                       // WIZARD'S SHOTS\r
+                                       //\r
+                                                       case bounceobj:\r
+                                                       case pshotobj:\r
+                                                       case bigpshotobj:\r
+                                                               RadarXY[objnum++][2]=shot_color[screenpage];\r
+                                                       break;\r
+\r
+                       // RED GEM\r
+                       //\r
+                                       // STOMPY                                                                               (DK RED)\r
+                                       //\r
+                                                       case invisdudeobj:\r
+                                                       case stompyobj:\r
+                                                               if (gamestate.gems[B_RGEM-B_RGEM])\r
+                                                                       if (obj->active == always)\r
+                                                                               RadarXY[objnum++][2]=4;\r
+                                                       break;\r
+\r
+                                       // BLOB                                                                                 (LT RED)\r
+                                       //\r
+                                                       case blobobj:\r
+                                                               if (gamestate.gems[B_RGEM-B_RGEM])\r
+                                                                       if (obj->active == always)\r
+                                                                               RadarXY[objnum++][2]=12;\r
+                                                       break;\r
+\r
+                       // BLUE GEM\r
+                       //\r
+                                       // ROBOTANK                                                                             (LT BLUE)\r
+                                       //\r
+                                                       case robotankobj:\r
+                                                       case fmageobj:\r
+                                                               if (gamestate.gems[B_BGEM-B_RGEM])\r
+                                                                       if (obj->active == always)\r
+                                                                               RadarXY[objnum++][2]=9;\r
+                                                       break;\r
+\r
+#if 1\r
+                                       // BLUE DEMON                                                                   (DK BLUE)\r
+                                       //\r
+                                                       case demonobj:\r
+                                                               if (gamestate.gems[B_GGEM-B_RGEM])\r
+                                                                       if (obj->active == always)\r
+                                                                               RadarXY[objnum++][2]=1;\r
+                                                       break;\r
+#endif\r
+\r
+                       // GREEN GEM\r
+                       //\r
+                                       // WIZARD                                                                               (LT GREEN)\r
+                                       //\r
+                                                       case wizardobj:\r
+                                                               if (gamestate.gems[B_GGEM-B_RGEM])\r
+                                                                       if (obj->active == always)\r
+                                                                               RadarXY[objnum++][2]=10;\r
+                                                       break;\r
+\r
+                                       // AQUA MAN                                                                             (DK GREEN)\r
+                                       //\r
+                                                       case aquamanobj:\r
+                                                               if (gamestate.gems[B_GGEM-B_RGEM])\r
+                                                                       if (obj->active == always)\r
+                                                                               RadarXY[objnum++][2]=2;\r
+                                                       break;\r
+\r
+                       // YELLOW GEM\r
+                       //\r
+                                       // EQYPTIAN HEAD                                                                (BROWN)\r
+                                       //\r
+                                                       case headobj:\r
+                                                               if (gamestate.gems[B_YGEM-B_RGEM])\r
+                                                                       if (obj->active == always)\r
+                                                                               RadarXY[objnum++][2]=6;\r
+                                                       break;\r
+\r
+                                       //      RAMBONE                                                                         (YELLOW)\r
+                                       //      TROLL\r
+                                                       case ramboneobj:\r
+                                                       case trollobj:\r
+                                                               if (gamestate.gems[B_YGEM-B_RGEM])\r
+                                                                       if (obj->active == always)\r
+                                                                               RadarXY[objnum++][2]=14;\r
+                                                       break;\r
+\r
+                                       //      BUG                                                                                     (LIGHT GRAY)\r
+                                                       case bugobj:\r
+                                                               if (gamestate.gems[B_YGEM-B_RGEM])\r
+                                                                       if (obj->active == always)\r
+                                                                               RadarXY[objnum++][2]=7;\r
+                                                       break;\r
+\r
+                                       //      RAY                                                                                     (DARK GRAY)\r
+                                                       case rayobj:\r
+                                                               if (gamestate.gems[B_YGEM-B_RGEM])\r
+                                                                       if (obj->active == always)\r
+                                                                               RadarXY[objnum++][2]=8;\r
+                                                       break;\r
+\r
+                       // PURPLE GEM\r
+                       //\r
+                                       // MEC DEMON                                                                    (PURPLE)\r
+                                       //\r
+                                                       case cyborgdemonobj:\r
+                                                               if (gamestate.gems[B_PGEM-B_RGEM])\r
+                                                                       if (obj->active == always)\r
+                                                                               RadarXY[objnum++][2]=5;\r
+                                                       break;\r
+\r
+                                       // EYE                                                                                  (LT PURPLE)\r
+                                       //\r
+                                                       case eyeobj:\r
+                                                       case reyeobj:\r
+                                                               if (gamestate.gems[B_PGEM-B_RGEM])\r
+                                                                       if (obj->active == always)\r
+                                                                               RadarXY[objnum++][2]=13;\r
+                                                       break;\r
+\r
+                       // ALL GEMS NEEDED\r
+                       //\r
+                                       // NEMESIS\r
+                                       //\r
+                                                       case grelmobj:\r
+                                                               if (!memcmp(gamestate.gems,allgems,sizeof(gamestate.gems)))\r
+                                                                       if (obj->active == always)\r
+                                                                               RadarXY[objnum++][2]=15;\r
+                                                       break;\r
+                                               }\r
+                                       }\r
+                               }\r
+               }\r
+               RadarXY[objnum][2]=-1;          // Signals end of RadarXY list...\r
+\r
+#if USE_INERT_LIST\r
+               if (inert != inertobjlist)\r
+                       for (obj=(objtype *)inertobjlist;obj;obj=obj->next)\r
+                               if (obj->ticcount)\r
+                               {\r
+                                       obj->ticcount-=realtics;\r
+                                       while ( obj->ticcount <= 0)\r
+                                       {\r
+                                               obj->state = obj->state->next;\r
+                                               if (!obj->state)\r
+                                                       Quit("Removable object in INERT list.");\r
+\r
+                                               if (!obj->state->tictime)\r
+                                               {\r
+                                                       obj->ticcount = 0;\r
+                                                       goto nextactor;\r
+                                               }\r
+\r
+                                               if (obj->state->tictime>0)\r
+                                                       obj->ticcount += obj->state->tictime;\r
+                                       }\r
+                               }\r
+#endif\r
+\r
+               if (bordertime)\r
+               {\r
+                       bordertime -= realtics;\r
+                       if (bordertime<=0)\r
+                       {\r
+                               bordertime = 0;\r
+                               VW_ColorBorder(0);\r
+                       }\r
+               }\r
+\r
+#if 1\r
+// random lightning?\r
+//\r
+       if (BGFLAGS & (BGF_NOT_LIGHTNING))\r
+       {\r
+               if ((scolor & 0xe0) && (!(random(20-realtics))))\r
+               {\r
+                       BGFLAGS &= ~BGF_NOT_LIGHTNING;\r
+                       InitBgChange(1,sky_lightning,-1,NULL,BGF_NOT_LIGHTNING);\r
+               }\r
+       }\r
+\r
+// handle sky/ground color changes\r
+//\r
+               if (skytimer != -1)\r
+               {\r
+                       skytimer -= realtics;\r
+                       if (skytimer < 0)\r
+                       {\r
+                               skycolor++;\r
+                               if (*skycolor == 0xffff)\r
+                               {\r
+                                       skytimer = -1;\r
+//                                     skycolor--;\r
+                                       skycolor = &scolor;\r
+                                       if (groundtimer == -1)\r
+                                               BGFLAGS |= bgflag;\r
+                               }\r
+                               else\r
+                                       skytimer = skytimer_reset;\r
+                       }\r
+               }\r
+\r
+               if (groundtimer != -1)\r
+               {\r
+                       groundtimer -= realtics;\r
+                       if (groundtimer < 0)\r
+                       {\r
+                               groundcolor++;\r
+                               if (*groundcolor == 0xffff)\r
+                               {\r
+                                       groundtimer = -1;\r
+//                                     groundcolor--;\r
+                                       groundcolor = &gcolor;\r
+                                       if (skytimer == -1)\r
+                                               BGFLAGS |= bgflag;\r
+                               }\r
+                               else\r
+                                       groundtimer = groundtimer_reset;\r
+                       }\r
+               }\r
+#endif\r
+\r
+\r
+//\r
+//             Handle FreezeTime counter..\r
+//\r
+               if (FreezeTime)\r
+               {\r
+                       if (FreezeTime<20*30)\r
+                               if ((BeepTime+=realtics)>=60)\r
+                               {\r
+                                       BeepTime -= 60;\r
+                                       SD_PlaySound(TICKSND);\r
+                               }\r
+\r
+                       if ((FreezeTime-=realtics)<=0)\r
+                       {\r
+                               FreezeTime=0;\r
+                               SD_PlaySound(TIMERETURNSND);\r
+                               DisplaySMsg(NULL,NULL);\r
+                               status_flag = S_NONE;\r
+                       }\r
+               }\r
+\r
+\r
+// refresh all\r
+//\r
+               ThreeDRefresh ();\r
+\r
+               if (Flags & FL_DEAD)\r
+               {\r
+                       SD_PlaySound (GAMEOVERSND);\r
+                       DisplaySMsg("DEAD",NULL);\r
+                       DrawHealth();\r
+               }\r
+\r
+// check for win\r
+//\r
+               if (playstate == ex_victorious)\r
+               {\r
+                       Victory(true);\r
+                       IN_Ack();\r
+                       Quit(NULL);\r
+               }\r
+\r
+               CheckKeys();\r
+\r
+       }while (!playstate);\r
+//     StopMusic ();\r
+\r
+       ingame = false;\r
+       if (bordertime)\r
+       {\r
+               bordertime = 0;\r
+               VW_ColorBorder(0);\r
+       }\r
+\r
+       if (abortgame)\r
+               abortgame = false;\r
+}\r
+\r
+//--------------------------------------------------------------------------\r
+// IntSqrt() - by Master Programmer, George Leritte!\r
+//--------------------------------------------------------------------------\r
+int IntSqrt(long va)\r
+{\r
+asm     mov     AX, word ptr va\r
+asm     mov     DX, word ptr va+2\r
+asm     mov     bx,dx           // {bx = integer square root of dx:ax}\r
+asm     or      bx,ax           // {if dx:ax=0 then return}\r
+asm     jz      isq01\r
+asm     mov     bx,dx\r
+asm     shl     bx,1\r
+asm     or      bl,ah\r
+asm     or      bl,al\r
+asm     dec     bx\r
+asm     add     bx,dx           // { initial guess}\r
+asm     jg      isq10\r
+asm     inc     bx              // { don't return zero}\r
+asm     jg      isq10\r
+asm     mov     bx,7fffh\r
+isq01:;\r
+                 goto    exitrout;\r
+\r
+isq10:;\r
+asm     push    ax\r
+asm     push    dx\r
+asm     div     bx\r
+asm     sub     ax,bx\r
+asm     cmp     ax,1\r
+asm     jbe     isq90\r
+asm     cmp     ax,-1\r
+asm     jae     isq90\r
+asm     sar     ax,1\r
+asm     add     bx,ax\r
+asm     pop     dx\r
+asm     pop     ax\r
+asm     jmp     isq10\r
+isq90:;\r
+asm     pop     dx\r
+asm     pop     ax\r
+exitrout:;\r
+asm     mov     ax,bx\r
+}\r
+\r
+//-------------------------------------------------------------------------\r
+// InitBgChange()\r
+//-------------------------------------------------------------------------\r
+void InitBgChange(short stimer, unsigned *scolors, short gtimer, unsigned *gcolors, byte flag)\r
+{\r
+       skytimer_reset = skytimer = stimer;\r
+       if (scolors)\r
+               skycolor = scolors;\r
+\r
+       groundtimer_reset = groundtimer = gtimer;\r
+       if (gcolors)\r
+               groundcolor = gcolors;\r
+\r
+       bgflag = flag;\r
+}\r
+\r
+////////////////////////////////////////////////////////\r
+//\r
+// DisplayStatus\r
+//\r
+//  Stat_Flag -  contains the type of status displayed\r
+//  -- also uses status_delay (global variable) will not\r
+//     change display until this variable is zero.\r
+//  -- heirarchy is determined by the series of if statements,\r
+//        to change it, rearrange th if statements.\r
+//\r
+////////////////////////////////////////////////////////\r
+\r
+#define MESSAGEDELAY  25\r
+void DisplayStatus (status_flags *stat_flag)\r
+{\r
+       status_flags temp_status;\r
+\r
+\r
+       if (*stat_flag == S_TIMESTOP)\r
+         return;\r
+\r
+       if (status_delay > 0)\r
+       {\r
+               status_delay -= realtics;\r
+               return;\r
+       }\r
+       else\r
+               status_delay = 0;\r
+\r
+       // check for a change in status from previous call\r
+\r
+       temp_status = S_VIEWING;                             //precaution\r
+\r
+       if (Keyboard[sc_Control] || control.button0)\r
+               temp_status = S_MISSLE;\r
+\r
+       if (Keyboard[sc_Z] && !Keyboard[sc_F10])\r
+               temp_status = S_ZAPPER;\r
+\r
+       if ((Keyboard[sc_X] && !Keyboard[sc_F10]) || Keyboard[sc_Enter])\r
+               temp_status = S_XTER;\r
+\r
+       if (control.x)\r
+               temp_status = S_TURN;\r
+\r
+       if ((Keyboard[sc_V] || Keyboard[sc_Tab]) && control.x)\r
+               temp_status = S_QTURN;\r
+\r
+       if (Keyboard[sc_Alt] && control.x)\r
+               temp_status = S_SIDESTEP;\r
+\r
+       if (control.y < 0)\r
+               temp_status = S_ADVANCE;\r
+\r
+       if (control.y > 0)\r
+               temp_status = S_RETREAT;\r
+\r
+       if (Keyboard[sc_F5])\r
+               temp_status = S_JOYSTICK;\r
+\r
+       if (Keyboard[sc_F4])\r
+               temp_status = S_RESTORING;\r
+\r
+       if (Keyboard[sc_F3])\r
+               temp_status = S_SAVING;\r
+\r
+       if (Keyboard[sc_F2])\r
+               temp_status = S_SND;\r
+\r
+       if (Keyboard[sc_F1])\r
+               temp_status = S_HELP;\r
+\r
+       if (temp_status != *stat_flag)\r
+       {\r
+               *stat_flag = temp_status;\r
+\r
+\r
+               switch (*stat_flag)\r
+               {\r
+                       case S_MISSLE:\r
+                               DisplaySMsg("Magick Missile", NULL);\r
+                               status_delay = MESSAGEDELAY;\r
+                       break;\r
+\r
+                       case S_ZAPPER:\r
+                               if (gamestate.bolts)\r
+                               {\r
+                                       DisplaySMsg("Zapper", NULL);\r
+                                       status_delay = MESSAGEDELAY+10;\r
+                               }\r
+                       break;\r
+\r
+                       case S_XTER:\r
+                               if (gamestate.nukes)\r
+                               {\r
+                                       DisplaySMsg("Xterminator", NULL);\r
+                                       status_delay = MESSAGEDELAY+5;\r
+                               }\r
+                       break;\r
+\r
+                       case S_TURN:\r
+                               DisplaySMsg("Turning", NULL);\r
+                               status_delay = MESSAGEDELAY;\r
+                       break;\r
+\r
+                       case S_QTURN:\r
+                               DisplaySMsg("Quick Turning", NULL);\r
+                               status_delay = MESSAGEDELAY;\r
+                       break;\r
+\r
+                       case S_SIDESTEP:\r
+                               DisplaySMsg("Sidestepping", NULL);\r
+                               status_delay = MESSAGEDELAY;\r
+                       break;\r
+\r
+                       case S_ADVANCE:\r
+                               DisplaySMsg("Advancing", NULL);\r
+                               status_delay = MESSAGEDELAY;\r
+                       break;\r
+\r
+                       case S_RETREAT:\r
+                               DisplaySMsg("Retreating", NULL);\r
+                               status_delay = MESSAGEDELAY;\r
+                       break;\r
+\r
+                       case S_JOYSTICK:\r
+                               DisplaySMsg("Adjusting Joystick", NULL);\r
+                       break;\r
+\r
+                       case S_RESTORING:\r
+                               DisplaySMsg("Restoring", NULL);\r
+                       break;\r
+\r
+                       case S_SAVING:\r
+                               DisplaySMsg("Saving", NULL);\r
+                       break;\r
+\r
+                       case S_SND:\r
+                               DisplaySMsg("Select Sound", NULL);\r
+                       break;\r
+\r
+                       case S_HELP:\r
+                               DisplaySMsg("Getting Help", NULL);\r
+                       break;\r
+\r
+                       case S_VIEWING:\r
+                               DisplaySMsg("Viewing", NULL);\r
+                       break;\r
+               }\r
+               bufferofs = displayofs = screenloc[screenpage];\r
+\r
+       }\r
+}\r