home *** CD-ROM | disk | FTP | other *** search
/ 100 af Verdens Bedste Spil / 100Spil.iso / dos / wolf3d / source / wolfsrc.1 / WL_GAME.C < prev    next >
C/C++ Source or Header  |  1993-03-16  |  28KB  |  1,485 lines

  1. // WL_GAME.C
  2.  
  3. #include "WL_DEF.H"
  4. #pragma hdrstop
  5.  
  6. #ifdef MYPROFILE
  7. #include <TIME.H>
  8. #endif
  9.  
  10.  
  11. /*
  12. =============================================================================
  13.  
  14.                          LOCAL CONSTANTS
  15.  
  16. =============================================================================
  17. */
  18.  
  19.  
  20. /*
  21. =============================================================================
  22.  
  23.                          GLOBAL VARIABLES
  24.  
  25. =============================================================================
  26. */
  27.  
  28. boolean        ingame,fizzlein;
  29. unsigned    latchpics[NUMLATCHPICS];
  30. gametype    gamestate;
  31.  
  32. long        spearx,speary;
  33. unsigned    spearangle;
  34. boolean        spearflag;
  35.  
  36. //
  37. // ELEVATOR BACK MAPS - REMEMBER (-1)!!
  38. //
  39. int ElevatorBackTo[]={1,1,7,3,5,3};
  40.  
  41. void ScanInfoPlane (void);
  42. void SetupGameLevel (void);
  43. void DrawPlayScreen (void);
  44. void LoadLatchMem (void);
  45. void GameLoop (void);
  46.  
  47. /*
  48. =============================================================================
  49.  
  50.                          LOCAL VARIABLES
  51.  
  52. =============================================================================
  53. */
  54.  
  55.  
  56.  
  57. //===========================================================================
  58. //===========================================================================
  59.  
  60.  
  61. /*
  62. ==========================
  63. =
  64. = SetSoundLoc - Given the location of an object (in terms of global
  65. =    coordinates, held in globalsoundx and globalsoundy), munges the values
  66. =    for an approximate distance from the left and right ear, and puts
  67. =    those values into leftchannel and rightchannel.
  68. =
  69. = JAB
  70. =
  71. ==========================
  72. */
  73.  
  74.     fixed    globalsoundx,globalsoundy;
  75.     int        leftchannel,rightchannel;
  76. #define ATABLEMAX 15
  77. byte righttable[ATABLEMAX][ATABLEMAX * 2] = {
  78. { 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 6, 0, 0, 0, 0, 0, 1, 3, 5, 8, 8, 8, 8, 8, 8, 8, 8},
  79. { 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 6, 4, 0, 0, 0, 0, 0, 2, 4, 6, 8, 8, 8, 8, 8, 8, 8, 8},
  80. { 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 4, 1, 0, 0, 0, 1, 2, 4, 6, 8, 8, 8, 8, 8, 8, 8, 8},
  81. { 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 6, 5, 4, 2, 1, 0, 1, 2, 3, 5, 7, 8, 8, 8, 8, 8, 8, 8, 8},
  82. { 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 6, 5, 4, 3, 2, 2, 3, 3, 5, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  83. { 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 6, 6, 5, 4, 4, 4, 4, 5, 6, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  84. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 6, 6, 5, 5, 5, 6, 6, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  85. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  86. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  87. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  88. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  89. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  90. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  91. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  92. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}
  93. };
  94. byte lefttable[ATABLEMAX][ATABLEMAX * 2] = {
  95. { 8, 8, 8, 8, 8, 8, 8, 8, 5, 3, 1, 0, 0, 0, 0, 0, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8},
  96. { 8, 8, 8, 8, 8, 8, 8, 8, 6, 4, 2, 0, 0, 0, 0, 0, 4, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8},
  97. { 8, 8, 8, 8, 8, 8, 8, 8, 6, 4, 2, 1, 0, 0, 0, 1, 4, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8},
  98. { 8, 8, 8, 8, 8, 8, 8, 8, 7, 5, 3, 2, 1, 0, 1, 2, 4, 5, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8},
  99. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 6, 5, 3, 3, 2, 2, 3, 4, 5, 6, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8},
  100. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 6, 5, 4, 4, 4, 4, 5, 6, 6, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8},
  101. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 6, 6, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  102. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 6, 6, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  103. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  104. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  105. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  106. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  107. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  108. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  109. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}
  110. };
  111.  
  112. void
  113. SetSoundLoc(fixed gx,fixed gy)
  114. {
  115.     fixed    xt,yt;
  116.     int        x,y;
  117.  
  118. //
  119. // translate point to view centered coordinates
  120. //
  121.     gx -= viewx;
  122.     gy -= viewy;
  123.  
  124. //
  125. // calculate newx
  126. //
  127.     xt = FixedByFrac(gx,viewcos);
  128.     yt = FixedByFrac(gy,viewsin);
  129.     x = (xt - yt) >> TILESHIFT;
  130.  
  131. //
  132. // calculate newy
  133. //
  134.     xt = FixedByFrac(gx,viewsin);
  135.     yt = FixedByFrac(gy,viewcos);
  136.     y = (yt + xt) >> TILESHIFT;
  137.  
  138.     if (y >= ATABLEMAX)
  139.         y = ATABLEMAX - 1;
  140.     else if (y <= -ATABLEMAX)
  141.         y = -ATABLEMAX;
  142.     if (x < 0)
  143.         x = -x;
  144.     if (x >= ATABLEMAX)
  145.         x = ATABLEMAX - 1;
  146.     leftchannel  =  lefttable[x][y + ATABLEMAX];
  147.     rightchannel = righttable[x][y + ATABLEMAX];
  148.  
  149. #if 0
  150.     CenterWindow(8,1);
  151.     US_PrintSigned(leftchannel);
  152.     US_Print(",");
  153.     US_PrintSigned(rightchannel);
  154.     VW_UpdateScreen();
  155. #endif
  156. }
  157.  
  158. /*
  159. ==========================
  160. =
  161. = SetSoundLocGlobal - Sets up globalsoundx & globalsoundy and then calls
  162. =    UpdateSoundLoc() to transform that into relative channel volumes. Those
  163. =    values are then passed to the Sound Manager so that they'll be used for
  164. =    the next sound played (if possible).
  165. =
  166. = JAB
  167. =
  168. ==========================
  169. */
  170. void PlaySoundLocGlobal(word s,fixed gx,fixed gy)
  171. {
  172.     SetSoundLoc(gx,gy);
  173.     SD_PositionSound(leftchannel,rightchannel);
  174.     if (SD_PlaySound(s))
  175.     {
  176.         globalsoundx = gx;
  177.         globalsoundy = gy;
  178.     }
  179. }
  180.  
  181. void UpdateSoundLoc(void)
  182. {
  183.     if (SoundPositioned)
  184.     {
  185.         SetSoundLoc(globalsoundx,globalsoundy);
  186.         SD_SetPosition(leftchannel,rightchannel);
  187.     }
  188. }
  189.  
  190. /*
  191. **    JAB End
  192. */
  193.  
  194.  
  195. /*
  196. ==========================
  197. =
  198. = ClearMemory
  199. =
  200. ==========================
  201. */
  202.  
  203. void ClearMemory (void)
  204. {
  205.     PM_UnlockMainMem();
  206.     SD_StopDigitized();
  207.     MM_SortMem ();
  208. }
  209.  
  210.  
  211. /*
  212. ==========================
  213. =
  214. = ScanInfoPlane
  215. =
  216. = Spawn all actors and mark down special places
  217. =
  218. ==========================
  219. */
  220.  
  221. void ScanInfoPlane (void)
  222. {
  223.     unsigned    x,y,i,j;
  224.     int            tile;
  225.     unsigned    far    *start;
  226.  
  227.     start = mapsegs[1];
  228.     for (y=0;y<mapheight;y++)
  229.         for (x=0;x<mapwidth;x++)
  230.         {
  231.             tile = *start++;
  232.             if (!tile)
  233.                 continue;
  234.  
  235.             switch (tile)
  236.             {
  237.             case 19:
  238.             case 20:
  239.             case 21:
  240.             case 22:
  241.                 SpawnPlayer(x,y,NORTH+tile-19);
  242.                 break;
  243.  
  244.             case 23:
  245.             case 24:
  246.             case 25:
  247.             case 26:
  248.             case 27:
  249.             case 28:
  250.             case 29:
  251.             case 30:
  252.  
  253.             case 31:
  254.             case 32:
  255.             case 33:
  256.             case 34:
  257.             case 35:
  258.             case 36:
  259.             case 37:
  260.             case 38:
  261.  
  262.             case 39:
  263.             case 40:
  264.             case 41:
  265.             case 42:
  266.             case 43:
  267.             case 44:
  268.             case 45:
  269.             case 46:
  270.  
  271.             case 47:
  272.             case 48:
  273.             case 49:
  274.             case 50:
  275.             case 51:
  276.             case 52:
  277.             case 53:
  278.             case 54:
  279.  
  280.             case 55:
  281.             case 56:
  282.             case 57:
  283.             case 58:
  284.             case 59:
  285.             case 60:
  286.             case 61:
  287.             case 62:
  288.  
  289.             case 63:
  290.             case 64:
  291.             case 65:
  292.             case 66:
  293.             case 67:
  294.             case 68:
  295.             case 69:
  296.             case 70:
  297.             case 71:
  298.             case 72:
  299.             case 73:                        // TRUCK AND SPEAR!
  300.             case 74:
  301.  
  302.                 SpawnStatic(x,y,tile-23);
  303.                 break;
  304.  
  305. //
  306. // P wall
  307. //
  308.             case 98:
  309.                 if (!loadedgame)
  310.                   gamestate.secrettotal++;
  311.                 break;
  312.  
  313. //
  314. // guard
  315. //
  316.             case 180:
  317.             case 181:
  318.             case 182:
  319.             case 183:
  320.                 if (gamestate.difficulty<gd_hard)
  321.                     break;
  322.                 tile -= 36;
  323.             case 144:
  324.             case 145:
  325.             case 146:
  326.             case 147:
  327.                 if (gamestate.difficulty<gd_medium)
  328.                     break;
  329.                 tile -= 36;
  330.             case 108:
  331.             case 109:
  332.             case 110:
  333.             case 111:
  334.                 SpawnStand(en_guard,x,y,tile-108);
  335.                 break;
  336.  
  337.  
  338.             case 184:
  339.             case 185:
  340.             case 186:
  341.             case 187:
  342.                 if (gamestate.difficulty<gd_hard)
  343.                     break;
  344.                 tile -= 36;
  345.             case 148:
  346.             case 149:
  347.             case 150:
  348.             case 151:
  349.                 if (gamestate.difficulty<gd_medium)
  350.                     break;
  351.                 tile -= 36;
  352.             case 112:
  353.             case 113:
  354.             case 114:
  355.             case 115:
  356.                 SpawnPatrol(en_guard,x,y,tile-112);
  357.                 break;
  358.  
  359.             case 124:
  360.                 SpawnDeadGuard (x,y);
  361.                 break;
  362. //
  363. // officer
  364. //
  365.             case 188:
  366.             case 189:
  367.             case 190:
  368.             case 191:
  369.                 if (gamestate.difficulty<gd_hard)
  370.                     break;
  371.                 tile -= 36;
  372.             case 152:
  373.             case 153:
  374.             case 154:
  375.             case 155:
  376.                 if (gamestate.difficulty<gd_medium)
  377.                     break;
  378.                 tile -= 36;
  379.             case 116:
  380.             case 117:
  381.             case 118:
  382.             case 119:
  383.                 SpawnStand(en_officer,x,y,tile-116);
  384.                 break;
  385.  
  386.  
  387.             case 192:
  388.             case 193:
  389.             case 194:
  390.             case 195:
  391.                 if (gamestate.difficulty<gd_hard)
  392.                     break;
  393.                 tile -= 36;
  394.             case 156:
  395.             case 157:
  396.             case 158:
  397.             case 159:
  398.                 if (gamestate.difficulty<gd_medium)
  399.                     break;
  400.                 tile -= 36;
  401.             case 120:
  402.             case 121:
  403.             case 122:
  404.             case 123:
  405.                 SpawnPatrol(en_officer,x,y,tile-120);
  406.                 break;
  407.  
  408.  
  409. //
  410. // ss
  411. //
  412.             case 198:
  413.             case 199:
  414.             case 200:
  415.             case 201:
  416.                 if (gamestate.difficulty<gd_hard)
  417.                     break;
  418.                 tile -= 36;
  419.             case 162:
  420.             case 163:
  421.             case 164:
  422.             case 165:
  423.                 if (gamestate.difficulty<gd_medium)
  424.                     break;
  425.                 tile -= 36;
  426.             case 126:
  427.             case 127:
  428.             case 128:
  429.             case 129:
  430.                 SpawnStand(en_ss,x,y,tile-126);
  431.                 break;
  432.  
  433.  
  434.             case 202:
  435.             case 203:
  436.             case 204:
  437.             case 205:
  438.                 if (gamestate.difficulty<gd_hard)
  439.                     break;
  440.                 tile -= 36;
  441.             case 166:
  442.             case 167:
  443.             case 168:
  444.             case 169:
  445.                 if (gamestate.difficulty<gd_medium)
  446.                     break;
  447.                 tile -= 36;
  448.             case 130:
  449.             case 131:
  450.             case 132:
  451.             case 133:
  452.                 SpawnPatrol(en_ss,x,y,tile-130);
  453.                 break;
  454.  
  455. //
  456. // dogs
  457. //
  458.             case 206:
  459.             case 207:
  460.             case 208:
  461.             case 209:
  462.                 if (gamestate.difficulty<gd_hard)
  463.                     break;
  464.                 tile -= 36;
  465.             case 170:
  466.             case 171:
  467.             case 172:
  468.             case 173:
  469.                 if (gamestate.difficulty<gd_medium)
  470.                     break;
  471.                 tile -= 36;
  472.             case 134:
  473.             case 135:
  474.             case 136:
  475.             case 137:
  476.                 SpawnStand(en_dog,x,y,tile-134);
  477.                 break;
  478.  
  479.  
  480.             case 210:
  481.             case 211:
  482.             case 212:
  483.             case 213:
  484.                 if (gamestate.difficulty<gd_hard)
  485.                     break;
  486.                 tile -= 36;
  487.             case 174:
  488.             case 175:
  489.             case 176:
  490.             case 177:
  491.                 if (gamestate.difficulty<gd_medium)
  492.                     break;
  493.                 tile -= 36;
  494.             case 138:
  495.             case 139:
  496.             case 140:
  497.             case 141:
  498.                 SpawnPatrol(en_dog,x,y,tile-138);
  499.                 break;
  500.  
  501. //
  502. // boss
  503. //
  504. #ifndef SPEAR
  505.             case 214:
  506.                 SpawnBoss (x,y);
  507.                 break;
  508.             case 197:
  509.                 SpawnGretel (x,y);
  510.                 break;
  511.             case 215:
  512.                 SpawnGift (x,y);
  513.                 break;
  514.             case 179:
  515.                 SpawnFat (x,y);
  516.                 break;
  517.             case 196:
  518.                 SpawnSchabbs (x,y);
  519.                 break;
  520.             case 160:
  521.                 SpawnFakeHitler (x,y);
  522.                 break;
  523.             case 178:
  524.                 SpawnHitler (x,y);
  525.                 break;
  526. #else
  527.             case 106:
  528.                 SpawnSpectre (x,y);
  529.                 break;
  530.             case 107:
  531.                 SpawnAngel (x,y);
  532.                 break;
  533.             case 125:
  534.                 SpawnTrans (x,y);
  535.                 break;
  536.             case 142:
  537.                 SpawnUber (x,y);
  538.                 break;
  539.             case 143:
  540.                 SpawnWill (x,y);
  541.                 break;
  542.             case 161:
  543.                 SpawnDeath (x,y);
  544.                 break;
  545.  
  546. #endif
  547.  
  548. //
  549. // mutants
  550. //
  551.             case 252:
  552.             case 253:
  553.             case 254:
  554.             case 255:
  555.                 if (gamestate.difficulty<gd_hard)
  556.                     break;
  557.                 tile -= 18;
  558.             case 234:
  559.             case 235:
  560.             case 236:
  561.             case 237:
  562.                 if (gamestate.difficulty<gd_medium)
  563.                     break;
  564.                 tile -= 18;
  565.             case 216:
  566.             case 217:
  567.             case 218:
  568.             case 219:
  569.                 SpawnStand(en_mutant,x,y,tile-216);
  570.                 break;
  571.  
  572.             case 256:
  573.             case 257:
  574.             case 258:
  575.             case 259:
  576.                 if (gamestate.difficulty<gd_hard)
  577.                     break;
  578.                 tile -= 18;
  579.             case 238:
  580.             case 239:
  581.             case 240:
  582.             case 241:
  583.                 if (gamestate.difficulty<gd_medium)
  584.                     break;
  585.                 tile -= 18;
  586.             case 220:
  587.             case 221:
  588.             case 222:
  589.             case 223:
  590.                 SpawnPatrol(en_mutant,x,y,tile-220);
  591.                 break;
  592.  
  593. //
  594. // ghosts
  595. //
  596. #ifndef SPEAR
  597.             case 224:
  598.                 SpawnGhosts (en_blinky,x,y);
  599.                 break;
  600.             case 225:
  601.                 SpawnGhosts (en_clyde,x,y);
  602.                 break;
  603.             case 226:
  604.                 SpawnGhosts (en_pinky,x,y);
  605.                 break;
  606.             case 227:
  607.                 SpawnGhosts (en_inky,x,y);
  608.                 break;
  609. #endif
  610.             }
  611.  
  612.         }
  613. }
  614.  
  615. //==========================================================================
  616.  
  617. /*
  618. ==================
  619. =
  620. = SetupGameLevel
  621. =
  622. ==================
  623. */
  624.  
  625. void SetupGameLevel (void)
  626. {
  627.     int    x,y,i;
  628.     unsigned    far *map,tile,spot;
  629.  
  630.  
  631.     if (!loadedgame)
  632.     {
  633.      gamestate.TimeCount=
  634.      gamestate.secrettotal=
  635.      gamestate.killtotal=
  636.      gamestate.treasuretotal=
  637.      gamestate.secretcount=
  638.      gamestate.killcount=
  639.      gamestate.treasurecount=0;
  640.     }
  641.  
  642.     if (demoplayback || demorecord)
  643.         US_InitRndT (false);
  644.     else
  645.         US_InitRndT (true);
  646.  
  647. //
  648. // load the level
  649. //
  650.     CA_CacheMap (gamestate.mapon+10*gamestate.episode);
  651.     mapon-=gamestate.episode*10;
  652.  
  653.     mapwidth = mapheaderseg[mapon]->width;
  654.     mapheight = mapheaderseg[mapon]->height;
  655.  
  656.     if (mapwidth != 64 || mapheight != 64)
  657.         Quit ("Map not 64*64!");
  658.  
  659.  
  660. //
  661. // copy the wall data to a data segment array
  662. //
  663.     memset (tilemap,0,sizeof(tilemap));
  664.     memset (actorat,0,sizeof(actorat));
  665.     map = mapsegs[0];
  666.     for (y=0;y<mapheight;y++)
  667.         for (x=0;x<mapwidth;x++)
  668.         {
  669.             tile = *map++;
  670.             if (tile<AREATILE)
  671.             {
  672.             // solid wall
  673.                 tilemap[x][y] = tile;
  674.                 (unsigned)actorat[x][y] = tile;
  675.             }
  676.             else
  677.             {
  678.             // area floor
  679.                 tilemap[x][y] = 0;
  680.                 (unsigned)actorat[x][y] = 0;
  681.             }
  682.         }
  683.  
  684. //
  685. // spawn doors
  686. //
  687.     InitActorList ();            // start spawning things with a clean slate
  688.     InitDoorList ();
  689.     InitStaticList ();
  690.  
  691.     map = mapsegs[0];
  692.     for (y=0;y<mapheight;y++)
  693.         for (x=0;x<mapwidth;x++)
  694.         {
  695.             tile = *map++;
  696.             if (tile >= 90 && tile <= 101)
  697.             {
  698.             // door
  699.                 switch (tile)
  700.                 {
  701.                 case 90:
  702.                 case 92:
  703.                 case 94:
  704.                 case 96:
  705.                 case 98:
  706.                 case 100:
  707.                     SpawnDoor (x,y,1,(tile-90)/2);
  708.                     break;
  709.                 case 91:
  710.                 case 93:
  711.                 case 95:
  712.                 case 97:
  713.                 case 99:
  714.                 case 101:
  715.                     SpawnDoor (x,y,0,(tile-91)/2);
  716.                     break;
  717.                 }
  718.             }
  719.         }
  720.  
  721. //
  722. // spawn actors
  723. //
  724.     ScanInfoPlane ();
  725.  
  726. //
  727. // take out the ambush markers
  728. //
  729.     map = mapsegs[0];
  730.     for (y=0;y<mapheight;y++)
  731.         for (x=0;x<mapwidth;x++)
  732.         {
  733.             tile = *map++;
  734.             if (tile == AMBUSHTILE)
  735.             {
  736.                 tilemap[x][y] = 0;
  737.                 if ( (unsigned)actorat[x][y] == AMBUSHTILE)
  738.                     actorat[x][y] = NULL;
  739.  
  740.                 if (*map >= AREATILE)
  741.                     tile = *map;
  742.                 if (*(map-1-mapwidth) >= AREATILE)
  743.                     tile = *(map-1-mapwidth);
  744.                 if (*(map-1+mapwidth) >= AREATILE)
  745.                     tile = *(map-1+mapwidth);
  746.                 if ( *(map-2) >= AREATILE)
  747.                     tile = *(map-2);
  748.  
  749.                 *(map-1) = tile;
  750.             }
  751.         }
  752.  
  753.  
  754.  
  755. //
  756. // have the caching manager load and purge stuff to make sure all marks
  757. // are in memory
  758. //
  759.     CA_LoadAllSounds ();
  760.  
  761. }
  762.  
  763.  
  764. //==========================================================================
  765.  
  766.  
  767. /*
  768. ===================
  769. =
  770. = DrawPlayBorderSides
  771. =
  772. = To fix window overwrites
  773. =
  774. ===================
  775. */
  776.  
  777. void DrawPlayBorderSides (void)
  778. {
  779.     int    xl,yl;
  780.  
  781.     xl = 160-viewwidth/2;
  782.     yl = (200-STATUSLINES-viewheight)/2;
  783.  
  784.     VWB_Bar (0,0,xl-1,200-STATUSLINES,127);
  785.     VWB_Bar (xl+viewwidth+1,0,xl-2,200-STATUSLINES,127);
  786.  
  787.     VWB_Vlin (yl-1,yl+viewheight,xl-1,0);
  788.     VWB_Vlin (yl-1,yl+viewheight,xl+viewwidth,125);
  789. }
  790.  
  791.  
  792. /*
  793. ===================
  794. =
  795. = DrawAllPlayBorderSides
  796. =
  797. ===================
  798. */
  799.  
  800. void DrawAllPlayBorderSides (void)
  801. {
  802.     unsigned    i,temp;
  803.  
  804.     temp = bufferofs;
  805.     for (i=0;i<3;i++)
  806.     {
  807.         bufferofs = screenloc[i];
  808.         DrawPlayBorderSides ();
  809.     }
  810.     bufferofs = temp;
  811. }
  812.  
  813. /*
  814. ===================
  815. =
  816. = DrawPlayBorder
  817. =
  818. ===================
  819. */
  820. void DrawAllPlayBorder (void)
  821. {
  822.     unsigned    i,temp;
  823.  
  824.     temp = bufferofs;
  825.     for (i=0;i<3;i++)
  826.     {
  827.         bufferofs = screenloc[i];
  828.         DrawPlayBorder ();
  829.     }
  830.     bufferofs = temp;
  831. }
  832.  
  833. /*
  834. ===================
  835. =
  836. = DrawPlayBorder
  837. =
  838. ===================
  839. */
  840.  
  841. void DrawPlayBorder (void)
  842. {
  843.     int    xl,yl;
  844.  
  845.     VWB_Bar (0,0,320,200-STATUSLINES,127);
  846.  
  847.     xl = 160-viewwidth/2;
  848.     yl = (200-STATUSLINES-viewheight)/2;
  849.     VWB_Bar (xl,yl,viewwidth,viewheight,0);
  850.  
  851.     VWB_Hlin (xl-1,xl+viewwidth,yl-1,0);
  852.     VWB_Hlin (xl-1,xl+viewwidth,yl+viewheight,125);
  853.     VWB_Vlin (yl-1,yl+viewheight,xl-1,0);
  854.     VWB_Vlin (yl-1,yl+viewheight,xl+viewwidth,125);
  855.     VWB_Plot (xl-1,yl+viewheight,124);
  856. }
  857.  
  858.  
  859.  
  860. /*
  861. ===================
  862. =
  863. = DrawPlayScreen
  864. =
  865. ===================
  866. */
  867.  
  868. void DrawPlayScreen (void)
  869. {
  870.     int    i,j,p,m;
  871.     unsigned    temp;
  872.  
  873.     VW_FadeOut ();
  874.  
  875.     temp = bufferofs;
  876.  
  877.     CA_CacheGrChunk (STATUSBARPIC);
  878.  
  879.     for (i=0;i<3;i++)
  880.     {
  881.         bufferofs = screenloc[i];
  882.         DrawPlayBorder ();
  883.         VWB_DrawPic (0,200-STATUSLINES,STATUSBARPIC);
  884.     }
  885.  
  886.     bufferofs = temp;
  887.  
  888.     UNCACHEGRCHUNK (STATUSBARPIC);
  889.  
  890.     DrawFace ();
  891.     DrawHealth ();
  892.     DrawLives ();
  893.     DrawLevel ();
  894.     DrawAmmo ();
  895.     DrawKeys ();
  896.     DrawWeapon ();
  897.     DrawScore ();
  898. }
  899.  
  900.  
  901.  
  902. //==========================================================================
  903.  
  904. /*
  905. ==================
  906. =
  907. = StartDemoRecord
  908. =
  909. ==================
  910. */
  911.  
  912. #define MAXDEMOSIZE    8192
  913.  
  914. void StartDemoRecord (int levelnumber)
  915. {
  916.     MM_GetPtr (&demobuffer,MAXDEMOSIZE);
  917.     MM_SetLock (&demobuffer,true);
  918.     demoptr = (char far *)demobuffer;
  919.     lastdemoptr = demoptr+MAXDEMOSIZE;
  920.  
  921.     *demoptr = levelnumber;
  922.     demoptr += 4;                // leave space for length
  923.     demorecord = true;
  924. }
  925.  
  926.  
  927. /*
  928. ==================
  929. =
  930. = FinishDemoRecord
  931. =
  932. ==================
  933. */
  934.  
  935. char    demoname[13] = "DEMO?.";
  936.  
  937. void FinishDemoRecord (void)
  938. {
  939.     long    length,level;
  940.  
  941.     demorecord = false;
  942.  
  943.     length = demoptr - (char far *)demobuffer;
  944.  
  945.     demoptr = ((char far *)demobuffer)+1;
  946.     *(unsigned far *)demoptr = length;
  947.  
  948.     CenterWindow(24,3);
  949.     PrintY+=6;
  950.     US_Print(" Demo number (0-9):");
  951.     VW_UpdateScreen();
  952.  
  953.     if (US_LineInput (px,py,str,NULL,true,2,0))
  954.     {
  955.         level = atoi (str);
  956.         if (level>=0 && level<=9)
  957.         {
  958.             demoname[4] = '0'+level;
  959.             CA_WriteFile (demoname,(void far *)demobuffer,length);
  960.         }
  961.     }
  962.  
  963.  
  964.     MM_FreePtr (&demobuffer);
  965. }
  966.  
  967. //==========================================================================
  968.  
  969. /*
  970. ==================
  971. =
  972. = RecordDemo
  973. =
  974. = Fades the screen out, then starts a demo.  Exits with the screen faded
  975. =
  976. ==================
  977. */
  978.  
  979. void RecordDemo (void)
  980. {
  981.     int level,esc;
  982.  
  983.     CenterWindow(26,3);
  984.     PrintY+=6;
  985.     CA_CacheGrChunk(STARTFONT);
  986.     fontnumber=0;
  987.     US_Print("  Demo which level(1-10):");
  988.     VW_UpdateScreen();
  989.     VW_FadeIn ();
  990.     esc = !US_LineInput (px,py,str,NULL,true,2,0);
  991.     if (esc)
  992.         return;
  993.  
  994.     level = atoi (str);
  995.     level--;
  996.  
  997.     SETFONTCOLOR(0,15);
  998.     VW_FadeOut ();
  999.  
  1000. #ifndef SPEAR
  1001.     NewGame (gd_hard,level/10);
  1002.     gamestate.mapon = level%10;
  1003. #else
  1004.     NewGame (gd_hard,0);
  1005.     gamestate.mapon = level;
  1006. #endif
  1007.  
  1008.     StartDemoRecord (level);
  1009.  
  1010.     DrawPlayScreen ();
  1011.     VW_FadeIn ();
  1012.  
  1013.     startgame = false;
  1014.     demorecord = true;
  1015.  
  1016.     SetupGameLevel ();
  1017.     StartMusic ();
  1018.     PM_CheckMainMem ();
  1019.     fizzlein = true;
  1020.  
  1021.     PlayLoop ();
  1022.  
  1023.     demoplayback = false;
  1024.  
  1025.     StopMusic ();
  1026.     VW_FadeOut ();
  1027.     ClearMemory ();
  1028.  
  1029.     FinishDemoRecord ();
  1030. }
  1031.  
  1032. //==========================================================================
  1033.  
  1034. /*
  1035. ==================
  1036. =
  1037. = PlayDemo
  1038. =
  1039. = Fades the screen out, then starts a demo.  Exits with the screen faded
  1040. =
  1041. ==================
  1042. */
  1043.  
  1044. void PlayDemo (int demonumber)
  1045. {
  1046.     int length;
  1047.  
  1048. #ifdef DEMOSEXTERN
  1049. // debug: load chunk
  1050. #ifndef SPEARDEMO
  1051.     int dems[4]={T_DEMO0,T_DEMO1,T_DEMO2,T_DEMO3};
  1052. #else
  1053.     int dems[1]={T_DEMO0};
  1054. #endif
  1055.  
  1056.     CA_CacheGrChunk(dems[demonumber]);
  1057.     demoptr = grsegs[dems[demonumber]];
  1058.     MM_SetLock (&grsegs[dems[demonumber]],true);
  1059. #else
  1060.     demoname[4] = '0'+demonumber;
  1061.     CA_LoadFile (demoname,&demobuffer);
  1062.     MM_SetLock (&demobuffer,true);
  1063.     demoptr = (char far *)demobuffer;
  1064. #endif
  1065.  
  1066.     NewGame (1,0);
  1067.     gamestate.mapon = *demoptr++;
  1068.     gamestate.difficulty = gd_hard;
  1069.     length = *((unsigned far *)demoptr)++;
  1070.     demoptr++;
  1071.     lastdemoptr = demoptr-4+length;
  1072.  
  1073.     VW_FadeOut ();
  1074.  
  1075.     SETFONTCOLOR(0,15);
  1076.     DrawPlayScreen ();
  1077.     VW_FadeIn ();
  1078.  
  1079.     startgame = false;
  1080.     demoplayback = true;
  1081.  
  1082.     SetupGameLevel ();
  1083.     StartMusic ();
  1084.     PM_CheckMainMem ();
  1085.     fizzlein = true;
  1086.  
  1087.     PlayLoop ();
  1088.  
  1089. #ifdef DEMOSEXTERN
  1090.     UNCACHEGRCHUNK(dems[demonumber]);
  1091. #else
  1092.     MM_FreePtr (&demobuffer);
  1093. #endif
  1094.  
  1095.     demoplayback = false;
  1096.  
  1097.     StopMusic ();
  1098.     VW_FadeOut ();
  1099.     ClearMemory ();
  1100. }
  1101.  
  1102. //==========================================================================
  1103.  
  1104. /*
  1105. ==================
  1106. =
  1107. = Died
  1108. =
  1109. ==================
  1110. */
  1111.  
  1112. #define DEATHROTATE 2
  1113.  
  1114. void Died (void)
  1115. {
  1116.     float    fangle;
  1117.     long    dx,dy;
  1118.     int        iangle,curangle,clockwise,counter,change;
  1119.  
  1120.     gamestate.weapon = -1;            // take away weapon
  1121.     SD_PlaySound (PLAYERDEATHSND);
  1122. //
  1123. // swing around to face attacker
  1124. //
  1125.     dx = killerobj->x - player->x;
  1126.     dy = player->y - killerobj->y;
  1127.  
  1128.     fangle = atan2(dy,dx);            // returns -pi to pi
  1129.     if (fangle<0)
  1130.         fangle = M_PI*2+fangle;
  1131.  
  1132.     iangle = fangle/(M_PI*2)*ANGLES;
  1133.  
  1134.     if (player->angle > iangle)
  1135.     {
  1136.         counter = player->angle - iangle;
  1137.         clockwise = ANGLES-player->angle + iangle;
  1138.     }
  1139.     else
  1140.     {
  1141.         clockwise = iangle - player->angle;
  1142.         counter = player->angle + ANGLES-iangle;
  1143.     }
  1144.  
  1145.     curangle = player->angle;
  1146.  
  1147.     if (clockwise<counter)
  1148.     {
  1149.     //
  1150.     // rotate clockwise
  1151.     //
  1152.         if (curangle>iangle)
  1153.             curangle -= ANGLES;
  1154.         do
  1155.         {
  1156.             change = tics*DEATHROTATE;
  1157.             if (curangle + change > iangle)
  1158.                 change = iangle-curangle;
  1159.  
  1160.             curangle += change;
  1161.             player->angle += change;
  1162.             if (player->angle >= ANGLES)
  1163.                 player->angle -= ANGLES;
  1164.  
  1165.             ThreeDRefresh ();
  1166.             CalcTics ();
  1167.         } while (curangle != iangle);
  1168.     }
  1169.     else
  1170.     {
  1171.     //
  1172.     // rotate counterclockwise
  1173.     //
  1174.         if (curangle<iangle)
  1175.             curangle += ANGLES;
  1176.         do
  1177.         {
  1178.             change = -tics*DEATHROTATE;
  1179.             if (curangle + change < iangle)
  1180.                 change = iangle-curangle;
  1181.  
  1182.             curangle += change;
  1183.             player->angle += change;
  1184.             if (player->angle < 0)
  1185.                 player->angle += ANGLES;
  1186.  
  1187.             ThreeDRefresh ();
  1188.             CalcTics ();
  1189.         } while (curangle != iangle);
  1190.     }
  1191.  
  1192. //
  1193. // fade to red
  1194. //
  1195.     FinishPaletteShifts ();
  1196.  
  1197.     bufferofs += screenofs;
  1198.     VW_Bar (0,0,viewwidth,viewheight,4);
  1199.     IN_ClearKeysDown ();
  1200.     FizzleFade(bufferofs,displayofs+screenofs,viewwidth,viewheight,70,false);
  1201.     bufferofs -= screenofs;
  1202.     IN_UserInput(100);
  1203.     SD_WaitSoundDone ();
  1204.  
  1205.     if (tedlevel == false)    // SO'S YA DON'T GET KILLED WHILE LAUNCHING!
  1206.       gamestate.lives--;
  1207.  
  1208.     if (gamestate.lives > -1)
  1209.     {
  1210.         gamestate.health = 100;
  1211.         gamestate.weapon = gamestate.bestweapon
  1212.             = gamestate.chosenweapon = wp_pistol;
  1213.         gamestate.ammo = STARTAMMO;
  1214.         gamestate.keys = 0;
  1215.         gamestate.attackframe = gamestate.attackcount =
  1216.         gamestate.weaponframe = 0;
  1217.  
  1218.         DrawKeys ();
  1219.         DrawWeapon ();
  1220.         DrawAmmo ();
  1221.         DrawHealth ();
  1222.         DrawFace ();
  1223.         DrawLives ();
  1224.     }
  1225.  
  1226. }
  1227.  
  1228. //==========================================================================
  1229.  
  1230. /*
  1231. ===================
  1232. =
  1233. = GameLoop
  1234. =
  1235. ===================
  1236. */
  1237.  
  1238. void GameLoop (void)
  1239. {
  1240.     int i,xl,yl,xh,yh;
  1241.     char num[20];
  1242.     boolean    died;
  1243. #ifdef MYPROFILE
  1244.     clock_t start,end;
  1245. #endif
  1246.  
  1247. restartgame:
  1248.     ClearMemory ();
  1249.     SETFONTCOLOR(0,15);
  1250.     DrawPlayScreen ();
  1251.     died = false;
  1252. restart:
  1253.     do
  1254.     {
  1255.         if (!loadedgame)
  1256.           gamestate.score = gamestate.oldscore;
  1257.         DrawScore();
  1258.  
  1259.         startgame = false;
  1260.         if (loadedgame)
  1261.             loadedgame = false;
  1262.         else
  1263.             SetupGameLevel ();
  1264.  
  1265. #ifdef SPEAR
  1266.         if (gamestate.mapon == 20)    // give them the key allways
  1267.         {
  1268.             gamestate.keys |= 1;
  1269.             DrawKeys ();
  1270.         }
  1271. #endif
  1272.  
  1273.         ingame = true;
  1274.         StartMusic ();
  1275.         PM_CheckMainMem ();
  1276.         if (!died)
  1277.             PreloadGraphics ();
  1278.         else
  1279.             died = false;
  1280.  
  1281.         fizzlein = true;
  1282.         DrawLevel ();
  1283.  
  1284. startplayloop:
  1285.         PlayLoop ();
  1286.  
  1287. #ifdef SPEAR
  1288.         if (spearflag)
  1289.         {
  1290.             SD_StopSound();
  1291.             SD_PlaySound(GETSPEARSND);
  1292.             if (DigiMode != sds_Off)
  1293.             {
  1294.                 long lasttimecount = TimeCount;
  1295.  
  1296.                 while(TimeCount < lasttimecount+150)
  1297.                 //while(DigiPlaying!=false)
  1298.                     SD_Poll();
  1299.             }
  1300.             else
  1301.                 SD_WaitSoundDone();
  1302.  
  1303.             ClearMemory ();
  1304.             gamestate.oldscore = gamestate.score;
  1305.             gamestate.mapon = 20;
  1306.             SetupGameLevel ();
  1307.             StartMusic ();
  1308.             PM_CheckMainMem ();
  1309.             player->x = spearx;
  1310.             player->y = speary;
  1311.             player->angle = spearangle;
  1312.             spearflag = false;
  1313.             Thrust (0,0);
  1314.             goto startplayloop;
  1315.         }
  1316. #endif
  1317.  
  1318.         StopMusic ();
  1319.         ingame = false;
  1320.  
  1321.         if (demorecord && playstate != ex_warped)
  1322.             FinishDemoRecord ();
  1323.  
  1324.         if (startgame || loadedgame)
  1325.             goto restartgame;
  1326.  
  1327.         switch (playstate)
  1328.         {
  1329.         case ex_completed:
  1330.         case ex_secretlevel:
  1331.             gamestate.keys = 0;
  1332.             DrawKeys ();
  1333.             VW_FadeOut ();
  1334.  
  1335.             ClearMemory ();
  1336.  
  1337.             LevelCompleted ();        // do the intermission
  1338. #ifdef SPEARDEMO
  1339.             if (gamestate.mapon == 1)
  1340.             {
  1341.                 died = true;            // don't "get psyched!"
  1342.  
  1343.                 VW_FadeOut ();
  1344.  
  1345.                 ClearMemory ();
  1346.  
  1347.                 CheckHighScore (gamestate.score,gamestate.mapon+1);
  1348.  
  1349.                 #pragma warn -sus
  1350.                 #ifndef JAPAN
  1351.                 _fstrcpy(MainMenu[viewscores].string,STR_VS);
  1352.                 #endif
  1353.                 MainMenu[viewscores].routine = CP_ViewScores;
  1354.                 #pragma warn +sus
  1355.  
  1356.                 return;
  1357.             }
  1358. #endif
  1359.  
  1360. #ifdef JAPDEMO
  1361.             if (gamestate.mapon == 3)
  1362.             {
  1363.                 died = true;            // don't "get psyched!"
  1364.  
  1365.                 VW_FadeOut ();
  1366.  
  1367.                 ClearMemory ();
  1368.  
  1369.                 CheckHighScore (gamestate.score,gamestate.mapon+1);
  1370.  
  1371.                 #pragma warn -sus
  1372.                 #ifndef JAPAN
  1373.                 _fstrcpy(MainMenu[viewscores].string,STR_VS);
  1374.                 #endif
  1375.                 MainMenu[viewscores].routine = CP_ViewScores;
  1376.                 #pragma warn +sus
  1377.  
  1378.                 return;
  1379.             }
  1380. #endif
  1381.  
  1382.             gamestate.oldscore = gamestate.score;
  1383.  
  1384. #ifndef SPEAR
  1385.             //
  1386.             // COMING BACK FROM SECRET LEVEL
  1387.             //
  1388.             if (gamestate.mapon == 9)
  1389.                 gamestate.mapon = ElevatorBackTo[gamestate.episode];    // back from secret
  1390.             else
  1391.             //
  1392.             // GOING TO SECRET LEVEL
  1393.             //
  1394.             if (playstate == ex_secretlevel)
  1395.                 gamestate.mapon = 9;
  1396. #else
  1397.  
  1398. #define FROMSECRET1        3
  1399. #define FROMSECRET2        11
  1400.  
  1401.             //
  1402.             // GOING TO SECRET LEVEL
  1403.             //
  1404.             if (playstate == ex_secretlevel)
  1405.                 switch(gamestate.mapon)
  1406.                 {
  1407.                  case FROMSECRET1: gamestate.mapon = 18; break;
  1408.                  case FROMSECRET2: gamestate.mapon = 19; break;
  1409.                 }
  1410.             else
  1411.             //
  1412.             // COMING BACK FROM SECRET LEVEL
  1413.             //
  1414.             if (gamestate.mapon == 18 || gamestate.mapon == 19)
  1415.                 switch(gamestate.mapon)
  1416.                 {
  1417.                  case 18: gamestate.mapon = FROMSECRET1+1; break;
  1418.                  case 19: gamestate.mapon = FROMSECRET2+1; break;
  1419.                 }
  1420. #endif
  1421.             else
  1422.             //
  1423.             // GOING TO NEXT LEVEL
  1424.             //
  1425.                 gamestate.mapon++;
  1426.  
  1427.  
  1428.             break;
  1429.  
  1430.         case ex_died:
  1431.             Died ();
  1432.             died = true;            // don't "get psyched!"
  1433.  
  1434.             if (gamestate.lives > -1)
  1435.                 break;                // more lives left
  1436.  
  1437.             VW_FadeOut ();
  1438.  
  1439.             ClearMemory ();
  1440.  
  1441.             CheckHighScore (gamestate.score,gamestate.mapon+1);
  1442.  
  1443.             #pragma warn -sus
  1444.             #ifndef JAPAN
  1445.             _fstrcpy(MainMenu[viewscores].string,STR_VS);
  1446.             #endif
  1447.             MainMenu[viewscores].routine = CP_ViewScores;
  1448.             #pragma warn +sus
  1449.  
  1450.             return;
  1451.  
  1452.         case ex_victorious:
  1453.  
  1454. #ifndef SPEAR
  1455.             VW_FadeOut ();
  1456. #else
  1457.             VL_FadeOut (0,255,0,17,17,300);
  1458. #endif
  1459.             ClearMemory ();
  1460.  
  1461.             Victory ();
  1462.  
  1463.             ClearMemory ();
  1464.  
  1465.             CheckHighScore (gamestate.score,gamestate.mapon+1);
  1466.  
  1467.             #pragma warn -sus
  1468.             #ifndef JAPAN
  1469.             _fstrcpy(MainMenu[viewscores].string,STR_VS);
  1470.             #endif
  1471.             MainMenu[viewscores].routine = CP_ViewScores;
  1472.             #pragma warn +sus
  1473.  
  1474.             return;
  1475.  
  1476.         default:
  1477.             ClearMemory ();
  1478.             break;
  1479.         }
  1480.  
  1481.     } while (1);
  1482.  
  1483. }
  1484.  
  1485.