Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. // WL_STATE.C
  2.  
  3. #include "wl_def.h"
  4. #pragma hdrstop
  5.  
  6. /*
  7. =============================================================================
  8.  
  9.                             LOCAL CONSTANTS
  10.  
  11. =============================================================================
  12. */
  13.  
  14.  
  15. /*
  16. =============================================================================
  17.  
  18.                             GLOBAL VARIABLES
  19.  
  20. =============================================================================
  21. */
  22.  
  23.  
  24. static const dirtype opposite[9] =
  25.     {west,southwest,south,southeast,east,northeast,north,northwest,nodir};
  26.  
  27. static const dirtype diagonal[9][9] =
  28. {
  29.     /* east */  {nodir,nodir,northeast,nodir,nodir,nodir,southeast,nodir,nodir},
  30.                 {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},
  31.     /* north */ {northeast,nodir,nodir,nodir,northwest,nodir,nodir,nodir,nodir},
  32.                 {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},
  33.     /* west */  {nodir,nodir,northwest,nodir,nodir,nodir,southwest,nodir,nodir},
  34.                 {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},
  35.     /* south */ {southeast,nodir,nodir,nodir,southwest,nodir,nodir,nodir,nodir},
  36.                 {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},
  37.                 {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir}
  38. };
  39.  
  40.  
  41.  
  42. void    SpawnNewObj (unsigned tilex, unsigned tiley, statetype *state);
  43. void    NewState (objtype *ob, statetype *state);
  44.  
  45. boolean TryWalk (objtype *ob);
  46. void    MoveObj (objtype *ob, int32_t move);
  47.  
  48. void    KillActor (objtype *ob);
  49. void    DamageActor (objtype *ob, unsigned damage);
  50.  
  51. boolean CheckLine (objtype *ob);
  52. void    FirstSighting (objtype *ob);
  53. boolean CheckSight (objtype *ob);
  54.  
  55. /*
  56. =============================================================================
  57.  
  58.                                 LOCAL VARIABLES
  59.  
  60. =============================================================================
  61. */
  62.  
  63.  
  64.  
  65. //===========================================================================
  66.  
  67.  
  68. /*
  69. ===================
  70. =
  71. = SpawnNewObj
  72. =
  73. = Spaws a new actor at the given TILE coordinates, with the given state, and
  74. = the given size in GLOBAL units.
  75. =
  76. = newobj = a pointer to an initialized new actor
  77. =
  78. ===================
  79. */
  80.  
  81. void SpawnNewObj (unsigned tilex, unsigned tiley, statetype *state)
  82. {
  83.     GetNewActor ();
  84.     newobj->state = state;
  85.     if (state->tictime)
  86.         newobj->ticcount = DEMOCHOOSE_ORIG_SDL(
  87.                 US_RndT () % state->tictime,
  88.                 US_RndT () % state->tictime + 1);     // Chris' moonwalk bugfix ;D
  89.     else
  90.         newobj->ticcount = 0;
  91.  
  92.     newobj->tilex = (short) tilex;
  93.     newobj->tiley = (short) tiley;
  94.     newobj->x = ((int32_t)tilex<<TILESHIFT)+TILEGLOBAL/2;
  95.     newobj->y = ((int32_t)tiley<<TILESHIFT)+TILEGLOBAL/2;
  96.     newobj->dir = nodir;
  97.  
  98.     actorat[tilex][tiley] = newobj;
  99.     newobj->areanumber =
  100.         *(mapsegs[0] + (newobj->tiley<<mapshift)+newobj->tilex) - AREATILE;
  101. }
  102.  
  103.  
  104.  
  105. /*
  106. ===================
  107. =
  108. = NewState
  109. =
  110. = Changes ob to a new state, setting ticcount to the max for that state
  111. =
  112. ===================
  113. */
  114.  
  115. void NewState (objtype *ob, statetype *state)
  116. {
  117.     ob->state = state;
  118.     ob->ticcount = state->tictime;
  119. }
  120.  
  121.  
  122.  
  123. /*
  124. =============================================================================
  125.  
  126.                         ENEMY TILE WORLD MOVEMENT CODE
  127.  
  128. =============================================================================
  129. */
  130.  
  131.  
  132. /*
  133. ==================================
  134. =
  135. = TryWalk
  136. =
  137. = Attempts to move ob in its current (ob->dir) direction.
  138. =
  139. = If blocked by either a wall or an actor returns FALSE
  140. =
  141. = If move is either clear or blocked only by a door, returns TRUE and sets
  142. =
  143. = ob->tilex         = new destination
  144. = ob->tiley
  145. = ob->areanumber    = the floor tile number (0-(NUMAREAS-1)) of destination
  146. = ob->distance      = TILEGLOBAl, or -doornumber if a door is blocking the way
  147. =
  148. = If a door is in the way, an OpenDoor call is made to start it opening.
  149. = The actor code should wait until
  150. =       doorobjlist[-ob->distance].action = dr_open, meaning the door has been
  151. =       fully opened
  152. =
  153. ==================================
  154. */
  155.  
  156. #define CHECKDIAG(x,y)                              \
  157. {                                                   \
  158.     temp=(uintptr_t)actorat[x][y];                  \
  159.     if (temp)                                       \
  160.     {                                               \
  161.         if (temp<256)                               \
  162.             return false;                           \
  163.         if (((objtype *)temp)->flags&FL_SHOOTABLE)  \
  164.             return false;                           \
  165.     }                                               \
  166. }
  167.  
  168. #ifdef PLAYDEMOLIKEORIGINAL
  169.     #define DOORCHECK                                   \
  170.             if(DEMOCOND_ORIG)                           \
  171.                 doornum = temp&63;                      \
  172.             else                                        \
  173.             {                                           \
  174.                 doornum = (int) temp & 127;             \
  175.                 OpenDoor(doornum);                      \
  176.                 ob->distance = -doornum - 1;            \
  177.                 return true;                            \
  178.             }
  179. #else
  180.     #define DOORCHECK                                   \
  181.             doornum = (int) temp & 127;                 \
  182.             OpenDoor(doornum);                          \
  183.             ob->distance = -doornum - 1;                \
  184.             return true;
  185. #endif
  186.  
  187. #define CHECKSIDE(x,y)                                  \
  188. {                                                       \
  189.     temp=(uintptr_t)actorat[x][y];                      \
  190.     if (temp)                                           \
  191.     {                                                   \
  192.         if (temp<128)                                   \
  193.             return false;                               \
  194.         if (temp<256)                                   \
  195.         {                                               \
  196.             DOORCHECK                                   \
  197.         }                                               \
  198.         else if (((objtype *)temp)->flags&FL_SHOOTABLE) \
  199.             return false;                               \
  200.     }                                                   \
  201. }
  202.  
  203.  
  204. boolean TryWalk (objtype *ob)
  205. {
  206.     int       doornum = -1;
  207.     uintptr_t temp;
  208.  
  209.     if (ob->obclass == inertobj)
  210.     {
  211.         switch (ob->dir)
  212.         {
  213.             case north:
  214.                 ob->tiley--;
  215.                 break;
  216.  
  217.             case northeast:
  218.                 ob->tilex++;
  219.                 ob->tiley--;
  220.                 break;
  221.  
  222.             case east:
  223.                 ob->tilex++;
  224.                 break;
  225.  
  226.             case southeast:
  227.                 ob->tilex++;
  228.                 ob->tiley++;
  229.                 break;
  230.  
  231.             case south:
  232.                 ob->tiley++;
  233.                 break;
  234.  
  235.             case southwest:
  236.                 ob->tilex--;
  237.                 ob->tiley++;
  238.                 break;
  239.  
  240.             case west:
  241.                 ob->tilex--;
  242.                 break;
  243.  
  244.             case northwest:
  245.                 ob->tilex--;
  246.                 ob->tiley--;
  247.                 break;
  248.         }
  249.     }
  250.     else
  251.     {
  252.         switch (ob->dir)
  253.         {
  254.             case north:
  255.                 if (ob->obclass == dogobj || ob->obclass == fakeobj
  256.                     || ob->obclass == ghostobj || ob->obclass == spectreobj)
  257.                 {
  258.                     CHECKDIAG(ob->tilex,ob->tiley-1);
  259.                 }
  260.                 else
  261.                 {
  262.                     CHECKSIDE(ob->tilex,ob->tiley-1);
  263.                 }
  264.                 ob->tiley--;
  265.                 break;
  266.  
  267.             case northeast:
  268.                 CHECKDIAG(ob->tilex+1,ob->tiley-1);
  269.                 CHECKDIAG(ob->tilex+1,ob->tiley);
  270.                 CHECKDIAG(ob->tilex,ob->tiley-1);
  271.                 ob->tilex++;
  272.                 ob->tiley--;
  273.                 break;
  274.  
  275.             case east:
  276.                 if (ob->obclass == dogobj || ob->obclass == fakeobj
  277.                     || ob->obclass == ghostobj || ob->obclass == spectreobj)
  278.                 {
  279.                     CHECKDIAG(ob->tilex+1,ob->tiley);
  280.                 }
  281.                 else
  282.                 {
  283.                     CHECKSIDE(ob->tilex+1,ob->tiley);
  284.                 }
  285.                 ob->tilex++;
  286.                 break;
  287.  
  288.             case southeast:
  289.                 CHECKDIAG(ob->tilex+1,ob->tiley+1);
  290.                 CHECKDIAG(ob->tilex+1,ob->tiley);
  291.                 CHECKDIAG(ob->tilex,ob->tiley+1);
  292.                 ob->tilex++;
  293.                 ob->tiley++;
  294.                 break;
  295.  
  296.             case south:
  297.                 if (ob->obclass == dogobj || ob->obclass == fakeobj
  298.                     || ob->obclass == ghostobj || ob->obclass == spectreobj)
  299.                 {
  300.                     CHECKDIAG(ob->tilex,ob->tiley+1);
  301.                 }
  302.                 else
  303.                 {
  304.                     CHECKSIDE(ob->tilex,ob->tiley+1);
  305.                 }
  306.                 ob->tiley++;
  307.                 break;
  308.  
  309.             case southwest:
  310.                 CHECKDIAG(ob->tilex-1,ob->tiley+1);
  311.                 CHECKDIAG(ob->tilex-1,ob->tiley);
  312.                 CHECKDIAG(ob->tilex,ob->tiley+1);
  313.                 ob->tilex--;
  314.                 ob->tiley++;
  315.                 break;
  316.  
  317.             case west:
  318.                 if (ob->obclass == dogobj || ob->obclass == fakeobj
  319.                     || ob->obclass == ghostobj || ob->obclass == spectreobj)
  320.                 {
  321.                     CHECKDIAG(ob->tilex-1,ob->tiley);
  322.                 }
  323.                 else
  324.                 {
  325.                     CHECKSIDE(ob->tilex-1,ob->tiley);
  326.                 }
  327.                 ob->tilex--;
  328.                 break;
  329.  
  330.             case northwest:
  331.                 CHECKDIAG(ob->tilex-1,ob->tiley-1);
  332.                 CHECKDIAG(ob->tilex-1,ob->tiley);
  333.                 CHECKDIAG(ob->tilex,ob->tiley-1);
  334.                 ob->tilex--;
  335.                 ob->tiley--;
  336.                 break;
  337.  
  338.             case nodir:
  339.                 return false;
  340.  
  341.             default:
  342.                 Quit ("Walk: Bad dir");
  343.         }
  344.     }
  345.  
  346. #ifdef PLAYDEMOLIKEORIGINAL
  347.     if (DEMOCOND_ORIG && doornum != -1)
  348.     {
  349.         OpenDoor(doornum);
  350.         ob->distance = -doornum-1;
  351.         return true;
  352.     }
  353. #endif
  354.  
  355.     ob->areanumber =
  356.         *(mapsegs[0] + (ob->tiley<<mapshift)+ob->tilex) - AREATILE;
  357.  
  358.     ob->distance = TILEGLOBAL;
  359.     return true;
  360. }
  361.  
  362.  
  363. /*
  364. ==================================
  365. =
  366. = SelectDodgeDir
  367. =
  368. = Attempts to choose and initiate a movement for ob that sends it towards
  369. = the player while dodging
  370. =
  371. = If there is no possible move (ob is totally surrounded)
  372. =
  373. = ob->dir           =       nodir
  374. =
  375. = Otherwise
  376. =
  377. = ob->dir           = new direction to follow
  378. = ob->distance      = TILEGLOBAL or -doornumber
  379. = ob->tilex         = new destination
  380. = ob->tiley
  381. = ob->areanumber    = the floor tile number (0-(NUMAREAS-1)) of destination
  382. =
  383. ==================================
  384. */
  385.  
  386. void SelectDodgeDir (objtype *ob)
  387. {
  388.     int         deltax,deltay,i;
  389.     unsigned    absdx,absdy;
  390.     dirtype     dirtry[5];
  391.     dirtype     turnaround,tdir;
  392.  
  393.     if (ob->flags & FL_FIRSTATTACK)
  394.     {
  395.         //
  396.         // turning around is only ok the very first time after noticing the
  397.         // player
  398.         //
  399.         turnaround = nodir;
  400.         ob->flags &= ~FL_FIRSTATTACK;
  401.     }
  402.     else
  403.         turnaround=opposite[ob->dir];
  404.  
  405.     deltax = player->tilex - ob->tilex;
  406.     deltay = player->tiley - ob->tiley;
  407.  
  408.     //
  409.     // arange 5 direction choices in order of preference
  410.     // the four cardinal directions plus the diagonal straight towards
  411.     // the player
  412.     //
  413.  
  414.     if (deltax>0)
  415.     {
  416.         dirtry[1]= east;
  417.         dirtry[3]= west;
  418.     }
  419.     else
  420.     {
  421.         dirtry[1]= west;
  422.         dirtry[3]= east;
  423.     }
  424.  
  425.     if (deltay>0)
  426.     {
  427.         dirtry[2]= south;
  428.         dirtry[4]= north;
  429.     }
  430.     else
  431.     {
  432.         dirtry[2]= north;
  433.         dirtry[4]= south;
  434.     }
  435.  
  436.     //
  437.     // randomize a bit for dodging
  438.     //
  439.     absdx = abs(deltax);
  440.     absdy = abs(deltay);
  441.  
  442.     if (absdx > absdy)
  443.     {
  444.         tdir = dirtry[1];
  445.         dirtry[1] = dirtry[2];
  446.         dirtry[2] = tdir;
  447.         tdir = dirtry[3];
  448.         dirtry[3] = dirtry[4];
  449.         dirtry[4] = tdir;
  450.     }
  451.  
  452.     if (US_RndT() < 128)
  453.     {
  454.         tdir = dirtry[1];
  455.         dirtry[1] = dirtry[2];
  456.         dirtry[2] = tdir;
  457.         tdir = dirtry[3];
  458.         dirtry[3] = dirtry[4];
  459.         dirtry[4] = tdir;
  460.     }
  461.  
  462.     dirtry[0] = diagonal [ dirtry[1] ] [ dirtry[2] ];
  463.  
  464.     //
  465.     // try the directions util one works
  466.     //
  467.     for (i=0;i<5;i++)
  468.     {
  469.         if ( dirtry[i] == nodir || dirtry[i] == turnaround)
  470.             continue;
  471.  
  472.         ob->dir = dirtry[i];
  473.         if (TryWalk(ob))
  474.             return;
  475.     }
  476.  
  477.     //
  478.     // turn around only as a last resort
  479.     //
  480.     if (turnaround != nodir)
  481.     {
  482.         ob->dir = turnaround;
  483.  
  484.         if (TryWalk(ob))
  485.             return;
  486.     }
  487.  
  488.     ob->dir = nodir;
  489. }
  490.  
  491.  
  492. /*
  493. ============================
  494. =
  495. = SelectChaseDir
  496. =
  497. = As SelectDodgeDir, but doesn't try to dodge
  498. =
  499. ============================
  500. */
  501.  
  502. void SelectChaseDir (objtype *ob)
  503. {
  504.     int     deltax,deltay;
  505.     dirtype d[3];
  506.     dirtype tdir, olddir, turnaround;
  507.  
  508.  
  509.     olddir=ob->dir;
  510.     turnaround=opposite[olddir];
  511.  
  512.     deltax=player->tilex - ob->tilex;
  513.     deltay=player->tiley - ob->tiley;
  514.  
  515.     d[1]=nodir;
  516.     d[2]=nodir;
  517.  
  518.     if (deltax>0)
  519.         d[1]= east;
  520.     else if (deltax<0)
  521.         d[1]= west;
  522.     if (deltay>0)
  523.         d[2]=south;
  524.     else if (deltay<0)
  525.         d[2]=north;
  526.  
  527.     if (abs(deltay)>abs(deltax))
  528.     {
  529.         tdir=d[1];
  530.         d[1]=d[2];
  531.         d[2]=tdir;
  532.     }
  533.  
  534.     if (d[1]==turnaround)
  535.         d[1]=nodir;
  536.     if (d[2]==turnaround)
  537.         d[2]=nodir;
  538.  
  539.  
  540.     if (d[1]!=nodir)
  541.     {
  542.         ob->dir=d[1];
  543.         if (TryWalk(ob))
  544.             return;     /*either moved forward or attacked*/
  545.     }
  546.  
  547.     if (d[2]!=nodir)
  548.     {
  549.         ob->dir=d[2];
  550.         if (TryWalk(ob))
  551.             return;
  552.     }
  553.  
  554.     /* there is no direct path to the player, so pick another direction */
  555.  
  556.     if (olddir!=nodir)
  557.     {
  558.         ob->dir=olddir;
  559.         if (TryWalk(ob))
  560.             return;
  561.     }
  562.  
  563.     if (US_RndT()>128)      /*randomly determine direction of search*/
  564.     {
  565.         for (tdir=north; tdir<=west; tdir=(dirtype)(tdir+1))
  566.         {
  567.             if (tdir!=turnaround)
  568.             {
  569.                 ob->dir=tdir;
  570.                 if ( TryWalk(ob) )
  571.                     return;
  572.             }
  573.         }
  574.     }
  575.     else
  576.     {
  577.         for (tdir=west; tdir>=north; tdir=(dirtype)(tdir-1))
  578.         {
  579.             if (tdir!=turnaround)
  580.             {
  581.                 ob->dir=tdir;
  582.                 if ( TryWalk(ob) )
  583.                     return;
  584.             }
  585.         }
  586.     }
  587.  
  588.     if (turnaround !=  nodir)
  589.     {
  590.         ob->dir=turnaround;
  591.         if (ob->dir != nodir)
  592.         {
  593.             if ( TryWalk(ob) )
  594.                 return;
  595.         }
  596.     }
  597.  
  598.     ob->dir = nodir;                // can't move
  599. }
  600.  
  601.  
  602. /*
  603. ============================
  604. =
  605. = SelectRunDir
  606. =
  607. = Run Away from player
  608. =
  609. ============================
  610. */
  611.  
  612. void SelectRunDir (objtype *ob)
  613. {
  614.     int deltax,deltay;
  615.     dirtype d[3];
  616.     dirtype tdir;
  617.  
  618.  
  619.     deltax=player->tilex - ob->tilex;
  620.     deltay=player->tiley - ob->tiley;
  621.  
  622.     if (deltax<0)
  623.         d[1]= east;
  624.     else
  625.         d[1]= west;
  626.     if (deltay<0)
  627.         d[2]=south;
  628.     else
  629.         d[2]=north;
  630.  
  631.     if (abs(deltay)>abs(deltax))
  632.     {
  633.         tdir=d[1];
  634.         d[1]=d[2];
  635.         d[2]=tdir;
  636.     }
  637.  
  638.     ob->dir=d[1];
  639.     if (TryWalk(ob))
  640.         return;     /*either moved forward or attacked*/
  641.  
  642.     ob->dir=d[2];
  643.     if (TryWalk(ob))
  644.         return;
  645.  
  646.     /* there is no direct path to the player, so pick another direction */
  647.  
  648.     if (US_RndT()>128)      /*randomly determine direction of search*/
  649.     {
  650.         for (tdir=north; tdir<=west; tdir=(dirtype)(tdir+1))
  651.         {
  652.             ob->dir=tdir;
  653.             if ( TryWalk(ob) )
  654.                 return;
  655.         }
  656.     }
  657.     else
  658.     {
  659.         for (tdir=west; tdir>=north; tdir=(dirtype)(tdir-1))
  660.         {
  661.             ob->dir=tdir;
  662.             if ( TryWalk(ob) )
  663.                 return;
  664.         }
  665.     }
  666.  
  667.     ob->dir = nodir;                // can't move
  668. }
  669.  
  670.  
  671. /*
  672. =================
  673. =
  674. = MoveObj
  675. =
  676. = Moves ob be move global units in ob->dir direction
  677. = Actors are not allowed to move inside the player
  678. = Does NOT check to see if the move is tile map valid
  679. =
  680. = ob->x                 = adjusted for new position
  681. = ob->y
  682. =
  683. =================
  684. */
  685.  
  686. void MoveObj (objtype *ob, int32_t move)
  687. {
  688.     int32_t    deltax,deltay;
  689.  
  690.     switch (ob->dir)
  691.     {
  692.         case north:
  693.             ob->y -= move;
  694.             break;
  695.         case northeast:
  696.             ob->x += move;
  697.             ob->y -= move;
  698.             break;
  699.         case east:
  700.             ob->x += move;
  701.             break;
  702.         case southeast:
  703.             ob->x += move;
  704.             ob->y += move;
  705.             break;
  706.         case south:
  707.             ob->y += move;
  708.             break;
  709.         case southwest:
  710.             ob->x -= move;
  711.             ob->y += move;
  712.             break;
  713.         case west:
  714.             ob->x -= move;
  715.             break;
  716.         case northwest:
  717.             ob->x -= move;
  718.             ob->y -= move;
  719.             break;
  720.  
  721.         case nodir:
  722.             return;
  723.  
  724.         default:
  725.             Quit ("MoveObj: bad dir!");
  726.     }
  727.  
  728.     //
  729.     // check to make sure it's not on top of player
  730.     //
  731.     if (areabyplayer[ob->areanumber])
  732.     {
  733.         deltax = ob->x - player->x;
  734.         if (deltax < -MINACTORDIST || deltax > MINACTORDIST)
  735.             goto moveok;
  736.         deltay = ob->y - player->y;
  737.         if (deltay < -MINACTORDIST || deltay > MINACTORDIST)
  738.             goto moveok;
  739.  
  740.         if (ob->hidden)          // move closer until he meets CheckLine
  741.             goto moveok;
  742.  
  743.         if (ob->obclass == ghostobj || ob->obclass == spectreobj)
  744.             TakeDamage (tics*2,ob);
  745.  
  746.         //
  747.         // back up
  748.         //
  749.         switch (ob->dir)
  750.         {
  751.             case north:
  752.                 ob->y += move;
  753.                 break;
  754.             case northeast:
  755.                 ob->x -= move;
  756.                 ob->y += move;
  757.                 break;
  758.             case east:
  759.                 ob->x -= move;
  760.                 break;
  761.             case southeast:
  762.                 ob->x -= move;
  763.                 ob->y -= move;
  764.                 break;
  765.             case south:
  766.                 ob->y -= move;
  767.                 break;
  768.             case southwest:
  769.                 ob->x += move;
  770.                 ob->y -= move;
  771.                 break;
  772.             case west:
  773.                 ob->x += move;
  774.                 break;
  775.             case northwest:
  776.                 ob->x += move;
  777.                 ob->y += move;
  778.                 break;
  779.  
  780.             case nodir:
  781.                 return;
  782.         }
  783.         return;
  784.     }
  785. moveok:
  786.     ob->distance -=move;
  787. }
  788.  
  789. /*
  790. =============================================================================
  791.  
  792.                                 STUFF
  793.  
  794. =============================================================================
  795. */
  796.  
  797. /*
  798. ===============
  799. =
  800. = DropItem
  801. =
  802. = Tries to drop a bonus item somewhere in the tiles surrounding the
  803. = given tilex/tiley
  804. =
  805. ===============
  806. */
  807.  
  808. void DropItem (wl_stat_t itemtype, int tilex, int tiley)
  809. {
  810.     int     x,y,xl,xh,yl,yh;
  811.  
  812.     //
  813.     // find a free spot to put it in
  814.     //
  815.     if (!actorat[tilex][tiley])
  816.     {
  817.         PlaceItemType (itemtype, tilex,tiley);
  818.         return;
  819.     }
  820.  
  821.     xl = tilex-1;
  822.     xh = tilex+1;
  823.     yl = tiley-1;
  824.     yh = tiley+1;
  825.  
  826.     for (x=xl ; x<= xh ; x++)
  827.     {
  828.         for (y=yl ; y<= yh ; y++)
  829.         {
  830.             if (!actorat[x][y])
  831.             {
  832.                 PlaceItemType (itemtype, x,y);
  833.                 return;
  834.             }
  835.         }
  836.     }
  837. }
  838.  
  839.  
  840.  
  841. /*
  842. ===============
  843. =
  844. = KillActor
  845. =
  846. ===============
  847. */
  848.  
  849. void KillActor (objtype *ob)
  850. {
  851.     int     tilex,tiley;
  852.  
  853.     tilex = ob->tilex = (word)(ob->x >> TILESHIFT);         // drop item on center
  854.     tiley = ob->tiley = (word)(ob->y >> TILESHIFT);
  855.  
  856.     switch (ob->obclass)
  857.     {
  858.         case guardobj:
  859.             GivePoints (100);
  860.             NewState (ob,&s_grddie1);
  861.             PlaceItemType (bo_clip2,tilex,tiley);
  862.             break;
  863.  
  864.         case officerobj:
  865.             GivePoints (400);
  866.             NewState (ob,&s_ofcdie1);
  867.             PlaceItemType (bo_clip2,tilex,tiley);
  868.             break;
  869.  
  870.         case mutantobj:
  871.             GivePoints (700);
  872.             NewState (ob,&s_mutdie1);
  873.             PlaceItemType (bo_clip2,tilex,tiley);
  874.             break;
  875.  
  876.         case ssobj:
  877.             GivePoints (500);
  878.             NewState (ob,&s_ssdie1);
  879.             if (gamestate.bestweapon < wp_machinegun)
  880.                 PlaceItemType (bo_machinegun,tilex,tiley);
  881.             else
  882.                 PlaceItemType (bo_clip2,tilex,tiley);
  883.             break;
  884.  
  885.         case dogobj:
  886.             GivePoints (200);
  887.             NewState (ob,&s_dogdie1);
  888.             break;
  889.  
  890. #ifndef SPEAR
  891.         case bossobj:
  892.             GivePoints (5000);
  893.             NewState (ob,&s_bossdie1);
  894.             PlaceItemType (bo_key1,tilex,tiley);
  895.             break;
  896.  
  897.         case gretelobj:
  898.             GivePoints (5000);
  899.             NewState (ob,&s_greteldie1);
  900.             PlaceItemType (bo_key1,tilex,tiley);
  901.             break;
  902.  
  903.         case giftobj:
  904.             GivePoints (5000);
  905.             gamestate.killx = player->x;
  906.             gamestate.killy = player->y;
  907.             NewState (ob,&s_giftdie1);
  908.             break;
  909.  
  910.         case fatobj:
  911.             GivePoints (5000);
  912.             gamestate.killx = player->x;
  913.             gamestate.killy = player->y;
  914.             NewState (ob,&s_fatdie1);
  915.             break;
  916.  
  917.         case schabbobj:
  918.             GivePoints (5000);
  919.             gamestate.killx = player->x;
  920.             gamestate.killy = player->y;
  921.             NewState (ob,&s_schabbdie1);
  922.             break;
  923.         case fakeobj:
  924.             GivePoints (2000);
  925.             NewState (ob,&s_fakedie1);
  926.             break;
  927.  
  928.         case mechahitlerobj:
  929.             GivePoints (5000);
  930.             NewState (ob,&s_mechadie1);
  931.             break;
  932.         case realhitlerobj:
  933.             GivePoints (5000);
  934.             gamestate.killx = player->x;
  935.             gamestate.killy = player->y;
  936.             NewState (ob,&s_hitlerdie1);
  937.             break;
  938. #else
  939.         case spectreobj:
  940.             if (ob->flags&FL_BONUS)
  941.             {
  942.                 GivePoints (200);       // Get points once for each
  943.                 ob->flags &= ~FL_BONUS;
  944.             }
  945.             NewState (ob,&s_spectredie1);
  946.             break;
  947.  
  948.         case angelobj:
  949.             GivePoints (5000);
  950.             NewState (ob,&s_angeldie1);
  951.             break;
  952.  
  953.         case transobj:
  954.             GivePoints (5000);
  955.             NewState (ob,&s_transdie0);
  956.             PlaceItemType (bo_key1,tilex,tiley);
  957.             break;
  958.  
  959.         case uberobj:
  960.             GivePoints (5000);
  961.             NewState (ob,&s_uberdie0);
  962.             PlaceItemType (bo_key1,tilex,tiley);
  963.             break;
  964.  
  965.         case willobj:
  966.             GivePoints (5000);
  967.             NewState (ob,&s_willdie1);
  968.             PlaceItemType (bo_key1,tilex,tiley);
  969.             break;
  970.  
  971.         case deathobj:
  972.             GivePoints (5000);
  973.             NewState (ob,&s_deathdie1);
  974.             PlaceItemType (bo_key1,tilex,tiley);
  975.             break;
  976. #endif
  977.     }
  978.  
  979.     gamestate.killcount++;
  980.     ob->flags &= ~FL_SHOOTABLE;
  981.     actorat[ob->tilex][ob->tiley] = NULL;
  982.     ob->flags |= FL_NONMARK;
  983. }
  984.  
  985.  
  986.  
  987. /*
  988. ===================
  989. =
  990. = DamageActor
  991. =
  992. = Called when the player succesfully hits an enemy.
  993. =
  994. = Does damage points to enemy ob, either putting it into a stun frame or
  995. = killing it.
  996. =
  997. ===================
  998. */
  999.  
  1000. void DamageActor (objtype *ob, unsigned damage)
  1001. {
  1002.     madenoise = true;
  1003.  
  1004.     //
  1005.     // do double damage if shooting a non attack mode actor
  1006.     //
  1007.     if ( !(ob->flags & FL_ATTACKMODE) )
  1008.         damage <<= 1;
  1009.  
  1010.     ob->hitpoints -= (short)damage;
  1011.  
  1012.     if (ob->hitpoints<=0)
  1013.         KillActor (ob);
  1014.     else
  1015.     {
  1016.         if (! (ob->flags & FL_ATTACKMODE) )
  1017.             FirstSighting (ob);             // put into combat mode
  1018.  
  1019.         switch (ob->obclass)                // dogs only have one hit point
  1020.         {
  1021.             case guardobj:
  1022.                 if (ob->hitpoints&1)
  1023.                     NewState (ob,&s_grdpain);
  1024.                 else
  1025.                     NewState (ob,&s_grdpain1);
  1026.                 break;
  1027.  
  1028.             case officerobj:
  1029.                 if (ob->hitpoints&1)
  1030.                     NewState (ob,&s_ofcpain);
  1031.                 else
  1032.                     NewState (ob,&s_ofcpain1);
  1033.                 break;
  1034.  
  1035.             case mutantobj:
  1036.                 if (ob->hitpoints&1)
  1037.                     NewState (ob,&s_mutpain);
  1038.                 else
  1039.                     NewState (ob,&s_mutpain1);
  1040.                 break;
  1041.  
  1042.             case ssobj:
  1043.                 if (ob->hitpoints&1)
  1044.                     NewState (ob,&s_sspain);
  1045.                 else
  1046.                     NewState (ob,&s_sspain1);
  1047.  
  1048.                 break;
  1049.         }
  1050.     }
  1051. }
  1052.  
  1053. /*
  1054. =============================================================================
  1055.  
  1056.                                 CHECKSIGHT
  1057.  
  1058. =============================================================================
  1059. */
  1060.  
  1061.  
  1062. /*
  1063. =====================
  1064. =
  1065. = CheckLine
  1066. =
  1067. = Returns true if a straight line between the player and ob is unobstructed
  1068. =
  1069. =====================
  1070. */
  1071.  
  1072. boolean CheckLine (objtype *ob)
  1073. {
  1074.     int         x1,y1,xt1,yt1,x2,y2,xt2,yt2;
  1075.     int         x,y;
  1076.     int         xdist,ydist,xstep,ystep;
  1077.     int         partial,delta;
  1078.     int32_t     ltemp;
  1079.     int         xfrac,yfrac,deltafrac;
  1080.     unsigned    value,intercept;
  1081.  
  1082.     x1 = ob->x >> UNSIGNEDSHIFT;            // 1/256 tile precision
  1083.     y1 = ob->y >> UNSIGNEDSHIFT;
  1084.     xt1 = x1 >> 8;
  1085.     yt1 = y1 >> 8;
  1086.  
  1087.     x2 = plux;
  1088.     y2 = pluy;
  1089.     xt2 = player->tilex;
  1090.     yt2 = player->tiley;
  1091.  
  1092.     xdist = abs(xt2-xt1);
  1093.  
  1094.     if (xdist > 0)
  1095.     {
  1096.         if (xt2 > xt1)
  1097.         {
  1098.             partial = 256-(x1&0xff);
  1099.             xstep = 1;
  1100.         }
  1101.         else
  1102.         {
  1103.             partial = x1&0xff;
  1104.             xstep = -1;
  1105.         }
  1106.  
  1107.         deltafrac = abs(x2-x1);
  1108.         delta = y2-y1;
  1109.         ltemp = ((int32_t)delta<<8)/deltafrac;
  1110.         if (ltemp > 0x7fffl)
  1111.             ystep = 0x7fff;
  1112.         else if (ltemp < -0x7fffl)
  1113.             ystep = -0x7fff;
  1114.         else
  1115.             ystep = ltemp;
  1116.         yfrac = y1 + (((int32_t)ystep*partial) >>8);
  1117.  
  1118.         x = xt1+xstep;
  1119.         xt2 += xstep;
  1120.         do
  1121.         {
  1122.             y = yfrac>>8;
  1123.             yfrac += ystep;
  1124.  
  1125.             value = (unsigned)tilemap[x][y];
  1126.             x += xstep;
  1127.  
  1128.             if (!value)
  1129.                 continue;
  1130.  
  1131.             if (value<128 || value>256)
  1132.                 return false;
  1133.  
  1134.             //
  1135.             // see if the door is open enough
  1136.             //
  1137.             value &= ~0x80;
  1138.             intercept = yfrac-ystep/2;
  1139.  
  1140.             if (intercept>doorposition[value])
  1141.                 return false;
  1142.  
  1143.         } while (x != xt2);
  1144.     }
  1145.  
  1146.     ydist = abs(yt2-yt1);
  1147.  
  1148.     if (ydist > 0)
  1149.     {
  1150.         if (yt2 > yt1)
  1151.         {
  1152.             partial = 256-(y1&0xff);
  1153.             ystep = 1;
  1154.         }
  1155.         else
  1156.         {
  1157.             partial = y1&0xff;
  1158.             ystep = -1;
  1159.         }
  1160.  
  1161.         deltafrac = abs(y2-y1);
  1162.         delta = x2-x1;
  1163.         ltemp = ((int32_t)delta<<8)/deltafrac;
  1164.         if (ltemp > 0x7fffl)
  1165.             xstep = 0x7fff;
  1166.         else if (ltemp < -0x7fffl)
  1167.             xstep = -0x7fff;
  1168.         else
  1169.             xstep = ltemp;
  1170.         xfrac = x1 + (((int32_t)xstep*partial) >>8);
  1171.  
  1172.         y = yt1 + ystep;
  1173.         yt2 += ystep;
  1174.         do
  1175.         {
  1176.             x = xfrac>>8;
  1177.             xfrac += xstep;
  1178.  
  1179.             value = (unsigned)tilemap[x][y];
  1180.             y += ystep;
  1181.  
  1182.             if (!value)
  1183.                 continue;
  1184.  
  1185.             if (value<128 || value>256)
  1186.                 return false;
  1187.  
  1188.             //
  1189.             // see if the door is open enough
  1190.             //
  1191.             value &= ~0x80;
  1192.             intercept = xfrac-xstep/2;
  1193.  
  1194.             if (intercept>doorposition[value])
  1195.                 return false;
  1196.         } while (y != yt2);
  1197.     }
  1198.  
  1199.     return true;
  1200. }
  1201.  
  1202.  
  1203. /*
  1204. ================
  1205. =
  1206. = CheckSight
  1207. =
  1208. = Checks a straight line between player and current object
  1209. =
  1210. = If the sight is ok, check alertness and angle to see if they notice
  1211. =
  1212. = returns true if the player has been spoted
  1213. =
  1214. ================
  1215. */
  1216.  
  1217. #define MINSIGHT        0x18000l
  1218.  
  1219. boolean CheckSight (objtype *ob)
  1220. {
  1221.     int32_t deltax,deltay;
  1222.  
  1223.     //
  1224.     // don't bother tracing a line if the area isn't connected to the player's
  1225.     //
  1226.     if (!areabyplayer[ob->areanumber])
  1227.         return false;
  1228.  
  1229.     //
  1230.     // if the player is real close, sight is automatic
  1231.     //
  1232.     deltax = player->x - ob->x;
  1233.     deltay = player->y - ob->y;
  1234.  
  1235.     if (deltax > -MINSIGHT && deltax < MINSIGHT
  1236.         && deltay > -MINSIGHT && deltay < MINSIGHT)
  1237.         return true;
  1238.  
  1239.     //
  1240.     // see if they are looking in the right direction
  1241.     //
  1242.     switch (ob->dir)
  1243.     {
  1244.         case north:
  1245.             if (deltay > 0)
  1246.                 return false;
  1247.             break;
  1248.  
  1249.         case east:
  1250.             if (deltax < 0)
  1251.                 return false;
  1252.             break;
  1253.  
  1254.         case south:
  1255.             if (deltay < 0)
  1256.                 return false;
  1257.             break;
  1258.  
  1259.         case west:
  1260.             if (deltax > 0)
  1261.                 return false;
  1262.             break;
  1263.  
  1264.         // check diagonal moving guards fix
  1265.  
  1266.         case northwest:
  1267.             if (DEMOCOND_SDL && deltay > -deltax)
  1268.                 return false;
  1269.             break;
  1270.  
  1271.         case northeast:
  1272.             if (DEMOCOND_SDL && deltay > deltax)
  1273.                 return false;
  1274.             break;
  1275.  
  1276.         case southwest:
  1277.             if (DEMOCOND_SDL && deltax > deltay)
  1278.                 return false;
  1279.             break;
  1280.  
  1281.         case southeast:
  1282.             if (DEMOCOND_SDL && -deltax > deltay)
  1283.                 return false;
  1284.             break;
  1285.     }
  1286.  
  1287.     //
  1288.     // trace a line to check for blocking tiles (corners)
  1289.     //
  1290.     return CheckLine (ob);
  1291. }
  1292.  
  1293.  
  1294. /*
  1295. ===============
  1296. =
  1297. = FirstSighting
  1298. =
  1299. = Puts an actor into attack mode and possibly reverses the direction
  1300. = if the player is behind it
  1301. =
  1302. ===============
  1303. */
  1304.  
  1305. void FirstSighting (objtype *ob)
  1306. {
  1307.     //
  1308.     // react to the player
  1309.     //
  1310.     switch (ob->obclass)
  1311.     {
  1312.         case guardobj:
  1313.             PlaySoundLocActor(HALTSND,ob);
  1314.             NewState (ob,&s_grdchase1);
  1315.             ob->speed *= 3;                 // go faster when chasing player
  1316.             break;
  1317.  
  1318.         case officerobj:
  1319.             PlaySoundLocActor(SPIONSND,ob);
  1320.             NewState (ob,&s_ofcchase1);
  1321.             ob->speed *= 5;                 // go faster when chasing player
  1322.             break;
  1323.  
  1324.         case mutantobj:
  1325.             NewState (ob,&s_mutchase1);
  1326.             ob->speed *= 3;                 // go faster when chasing player
  1327.             break;
  1328.  
  1329.         case ssobj:
  1330.             PlaySoundLocActor(SCHUTZADSND,ob);
  1331.             NewState (ob,&s_sschase1);
  1332.             ob->speed *= 4;                 // go faster when chasing player
  1333.             break;
  1334.  
  1335.         case dogobj:
  1336.             PlaySoundLocActor(DOGBARKSND,ob);
  1337.             NewState (ob,&s_dogchase1);
  1338.             ob->speed *= 2;                 // go faster when chasing player
  1339.             break;
  1340.  
  1341. #ifndef SPEAR
  1342.         case bossobj:
  1343.             SD_PlaySound(GUTENTAGSND);
  1344.             NewState (ob,&s_bosschase1);
  1345.             ob->speed = SPDPATROL*3;        // go faster when chasing player
  1346.             break;
  1347.  
  1348. #ifndef APOGEE_1_0
  1349.         case gretelobj:
  1350.             SD_PlaySound(KEINSND);
  1351.             NewState (ob,&s_gretelchase1);
  1352.             ob->speed *= 3;                 // go faster when chasing player
  1353.             break;
  1354.  
  1355.         case giftobj:
  1356.             SD_PlaySound(EINESND);
  1357.             NewState (ob,&s_giftchase1);
  1358.             ob->speed *= 3;                 // go faster when chasing player
  1359.             break;
  1360.  
  1361.         case fatobj:
  1362.             SD_PlaySound(ERLAUBENSND);
  1363.             NewState (ob,&s_fatchase1);
  1364.             ob->speed *= 3;                 // go faster when chasing player
  1365.             break;
  1366. #endif
  1367.  
  1368.         case schabbobj:
  1369.             SD_PlaySound(SCHABBSHASND);
  1370.             NewState (ob,&s_schabbchase1);
  1371.             ob->speed *= 3;                 // go faster when chasing player
  1372.             break;
  1373.  
  1374.         case fakeobj:
  1375.             SD_PlaySound(TOT_HUNDSND);
  1376.             NewState (ob,&s_fakechase1);
  1377.             ob->speed *= 3;                 // go faster when chasing player
  1378.             break;
  1379.  
  1380.         case mechahitlerobj:
  1381.             SD_PlaySound(DIESND);
  1382.             NewState (ob,&s_mechachase1);
  1383.             ob->speed *= 3;                 // go faster when chasing player
  1384.             break;
  1385.  
  1386.         case realhitlerobj:
  1387.             SD_PlaySound(DIESND);
  1388.             NewState (ob,&s_hitlerchase1);
  1389.             ob->speed *= 5;                 // go faster when chasing player
  1390.             break;
  1391.  
  1392.         case ghostobj:
  1393.             NewState (ob,&s_blinkychase1);
  1394.             ob->speed *= 2;                 // go faster when chasing player
  1395.             break;
  1396. #else
  1397.         case spectreobj:
  1398.             SD_PlaySound(GHOSTSIGHTSND);
  1399.             NewState (ob,&s_spectrechase1);
  1400.             ob->speed = 800;                        // go faster when chasing player
  1401.             break;
  1402.  
  1403.         case angelobj:
  1404.             SD_PlaySound(ANGELSIGHTSND);
  1405.             NewState (ob,&s_angelchase1);
  1406.             ob->speed = 1536;                       // go faster when chasing player
  1407.             break;
  1408.  
  1409.         case transobj:
  1410.             SD_PlaySound(TRANSSIGHTSND);
  1411.             NewState (ob,&s_transchase1);
  1412.             ob->speed = 1536;                       // go faster when chasing player
  1413.             break;
  1414.  
  1415.         case uberobj:
  1416.             NewState (ob,&s_uberchase1);
  1417.             ob->speed = 3000;                       // go faster when chasing player
  1418.             break;
  1419.  
  1420.         case willobj:
  1421.             SD_PlaySound(WILHELMSIGHTSND);
  1422.             NewState (ob,&s_willchase1);
  1423.             ob->speed = 2048;                       // go faster when chasing player
  1424.             break;
  1425.  
  1426.         case deathobj:
  1427.             SD_PlaySound(KNIGHTSIGHTSND);
  1428.             NewState (ob,&s_deathchase1);
  1429.             ob->speed = 2048;                       // go faster when chasing player
  1430.             break;
  1431. #endif
  1432.     }
  1433.  
  1434.     if (ob->distance < 0)
  1435.         ob->distance = 0;       // ignore the door opening command
  1436.  
  1437.     ob->flags |= FL_ATTACKMODE|FL_FIRSTATTACK;
  1438. }
  1439.  
  1440.  
  1441.  
  1442. /*
  1443. ===============
  1444. =
  1445. = SightPlayer
  1446. =
  1447. = Called by actors that ARE NOT chasing the player.  If the player
  1448. = is detected (by sight, noise, or proximity), the actor is put into
  1449. = it's combat frame and true is returned.
  1450. =
  1451. = Incorporates a random reaction delay
  1452. =
  1453. ===============
  1454. */
  1455.  
  1456. boolean SightPlayer (objtype *ob)
  1457. {
  1458.     if (ob->flags & FL_ATTACKMODE)
  1459.         Quit ("An actor in ATTACKMODE called SightPlayer!");
  1460.  
  1461.     if (ob->temp2)
  1462.     {
  1463.         //
  1464.         // count down reaction time
  1465.         //
  1466.         ob->temp2 -= (short) tics;
  1467.         if (ob->temp2 > 0)
  1468.             return false;
  1469.         ob->temp2 = 0;                                  // time to react
  1470.     }
  1471.     else
  1472.     {
  1473.         if (!areabyplayer[ob->areanumber])
  1474.             return false;
  1475.  
  1476.         if (ob->flags & FL_AMBUSH)
  1477.         {
  1478.             if (!CheckSight (ob))
  1479.                 return false;
  1480.             ob->flags &= ~FL_AMBUSH;
  1481.         }
  1482.         else
  1483.         {
  1484.             if (!madenoise && !CheckSight (ob))
  1485.                 return false;
  1486.         }
  1487.  
  1488.  
  1489.         switch (ob->obclass)
  1490.         {
  1491.             case guardobj:
  1492.                 ob->temp2 = 1+US_RndT()/4;
  1493.                 break;
  1494.             case officerobj:
  1495.                 ob->temp2 = 2;
  1496.                 break;
  1497.             case mutantobj:
  1498.                 ob->temp2 = 1+US_RndT()/6;
  1499.                 break;
  1500.             case ssobj:
  1501.                 ob->temp2 = 1+US_RndT()/6;
  1502.                 break;
  1503.             case dogobj:
  1504.                 ob->temp2 = 1+US_RndT()/8;
  1505.                 break;
  1506.  
  1507.             case bossobj:
  1508.             case schabbobj:
  1509.             case fakeobj:
  1510.             case mechahitlerobj:
  1511.             case realhitlerobj:
  1512.             case gretelobj:
  1513.             case giftobj:
  1514.             case fatobj:
  1515.             case spectreobj:
  1516.             case angelobj:
  1517.             case transobj:
  1518.             case uberobj:
  1519.             case willobj:
  1520.             case deathobj:
  1521.                 ob->temp2 = 1;
  1522.                 break;
  1523.         }
  1524.         return false;
  1525.     }
  1526.  
  1527.     FirstSighting (ob);
  1528.  
  1529.     return true;
  1530. }
  1531.