#include "stdafx.h"

#include "UI.h"

#include <stdio.h>

#include "Objects.h"
#include "Dispatch.h"
#include "CSB.h"
#include "Data.h"


#ifdef _DEBUG
i32 timertrace[1000];
i32 timertraceindex=0;
void settrace(i32 n)
{
  if (n==-1)
  {
    while (timertraceindex>0) timertrace[--timertraceindex]=0;
  }
  else if (n==-2)
  {
    if (TimerTraceActive)
    {
      i32 i;
      for (i=0; i<timertraceindex; i++)
      {
        fprintf (GETFILE(TraceFile), "%4d %08x\n",i, timertrace[i]);
      };
    };
  }
  else if (timertraceindex>999)
  {
    return;
  }
  else
  {
    timertrace[timertraceindex++] = n;
  };
}
#endif

#ifdef _DEBUG
#define TIMERTRACE(n) settrace(n);
#else
#define TIMERTRACE(n)
#endif



//*********************************************************
//
//*********************************************************
// TAG00b1f0
RN CreateMonster(i32  value,   //8
                 i32  hitPointMultiplier, //10
                 i32  numMonM1,//12 Number Monsters-1??
                 i32  facing,  //14 P4
                 i32  mapX,    //16
                 i32  mapY,
                 bool invisible,
                 bool drawAsSize4)    //18
{// (RN)
  dReg         D0, D3, D4, D5, D6;
  RN           objD7;
  MONSTERDESC *pmtDesc;
  DB4         *DB4A3;
  i16          w_12;
  i16          w_2;
  i32          monsterSize;
  MONSTERTYPE  mt;
  static bool  warningIssued = false;
  mt = (MONSTERTYPE)value;
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
//

  if (!MonsterAllowedOnLevel(RNnul, d.LoadedLevel, mt)) return(RNnul);





  if (   (d.ITEM16QueLen >= d.MaxITEM16-5)
      && (d.LoadedLevel == d.partyLevel)  )
  {
    if (d.MaxITEM16 < 240)
    {
      i32 i, newMax;
      newMax = d.MaxITEM16 + 50;
      d.Item16 = (ITEM16 *)UI_realloc(d.Item16, 16 * newMax,
                                      MALLOC087);
      for (i=d.MaxITEM16; i< newMax; i++)
      {
        d.Item16[i].word0 = -1;
      };
      d.MaxITEM16 = sw(newMax);
    }
  };






  if (   (d.ITEM16QueLen >= d.MaxITEM16-5)
      && (d.LoadedLevel == d.partyLevel)  ) return (RNnul);
  objD7=FindEmptyDB4Entry(false);
  if (objD7 == RNnul) return (RNnul);
  DB4A3 = GetRecordAddressDB4(objD7);
  DB4A3->monsterType(value); // Item26 index
  pmtDesc = &d.MonsterDescriptor[DB4A3->monsterType()];
  monsterSize = pmtDesc->horizontalSize();
  switch (monsterSize)
  {
  case 0: //Any number of monsters is OK.
    break;
  case 1: //size two.....worms perhaps?
    if (numMonM1 > 1)
    {
      if (!warningIssued && !PlayFile.IsOpen())
        UI_MessageBox("Too many monsters of size 2","Fixing...",MESSAGE_OK);
      warningIssued = true;
      numMonM1 = 1;
    };
    break;
  case 2:
    if (numMonM1 > 0)
    {
      if (!warningIssued && !PlayFile.IsOpen())
        UI_MessageBox("Too many monsters of size 4","Fixing...",MESSAGE_OK);
      warningIssued = true;
      numMonM1 = 0;
    };
    break;
  default:
    break;
  };
  DB4A3->possession(RNeof);
  D3W = 0;
  //30OCT02SETWBITS10_10(DB4A3->word14, uw(0));
  DB4A3->important(0);
  //30OCT02SETWBITS8_9(DB4A3->word14, P4);
  DB4A3->facing(facing);
  //30OCT02SETWBITS5_6(DB4A3->word14, numMonM1);
  DB4A3->numMonM1(numMonM1);
  DB4A3->invisible(invisible);
  DB4A3->drawAsSize4(drawAsSize4);
  w_2 = sw(numMonM1);
  if (w_2 != 0)
  {
    D4W = 0;// Added to avoid compiler warning. Not needed.
    D5W = STRandom0_3(); // Monster position????
  }
  else
  {
    D4W = 255;
    D5W = 0; //Added to avoid compiler warning. Not needed.
  };
  ASSERT(DB4A3->monsterType() < 27);
  D6W = pmtDesc->uByte8[1];
  do
  {
    w_12 = sw(STRandom() % (D6W/4 + 1));
    D0W = uw(D6W * hitPointMultiplier + w_12);
    DB4A3->hitPoints6[numMonM1] = D0W;
    if (w_2 != 0)
    {
      D4W = SetMonsterPositionBits(
                D4W,     //old positions byte
                numMonM1, //monster number
                D5W++);  //monster position
      if (pmtDesc->horizontalSize() == 1)
      {
        D5W++;
      };
      D5W &= 3;
    };
  } while ((numMonM1--) != 0);
  DB4A3->groupIndex(D4W);
  // The following function call fixes DB4A3->uByte5.
  D0W = MoveObject(objD7, -1, 0, mapX, mapY);
  ASSERT(D0W != 0xccc);
  if (D0W != 0)
  {
    return (RNnul);
  }
  else
  {
    QueueSound(soundTELEPORT, mapX, mapY, 1);
    return (objD7);
  };
}

//*********************************************************
//
//*********************************************************
//   TAG00bc12
void StealFromCharacter(DB4 *pDB4, i16 chIdx)
{//(void)
  dReg D0, D1, D5, D6, D7;
  RN objD4;
  CHARDESC *pcA2;
  i16      w_2;
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
//
  w_2 = 0;
  pcA2 = &d.CH16482[chIdx];
  D1W = sw(Quickness(pcA2));
  D7W = sw(100 - D1W);
  D5W = sw(STRandom(8));
  while ( (D7W>0) && (TAG016476(pcA2,D7W)==0) )
  {
    D6W = d.uByte13126[D5W];
    if (D6W == 13)
    {
      D6W = sw(D6W + STRandom(17));
    };
    objD4 = pcA2->possessions[D6W];
    if (objD4 != RNnul)
    {
      w_2 = 1;
      objD4 = RemovePossession(chIdx, D6W);
      if (pDB4->possession() == RNeof)
      {
        pDB4->possession(objD4);
      }
      else
      {
        AddObjectToRoom(objD4, pDB4->possession(), -1, 0);
      };
      DrawCharacterState(chIdx);
    };
    D5W = sw((D5W + 1) & 7);
    D7W -= 20;

  };
  D0W = sw(STRandom(8));
//
  if ( (STRandom(8)==0) || ((w_2!=0) && (STRandomBool()!=0)) )
  {
    D0W = sw(STRandom(64) + 20);
    ASSERT(pDB4->groupIndex() < d.MaxITEM16);
    d.Item16[pDB4->groupIndex()].uByte5 = D0B;
    //30OCT02SETWBITS0_3(pDB4->word14, 5);
    pDB4->fear(StateOfFear5);
  };
}

//*********************************************************
//
//*********************************************************
//   TAG00be5a
bool BlockedTypeA(i32 mapX, i32 mapY)
{ // return true if blocked to passage.
  // Certain monsters can go through certain doors.
  // Door types 3 & 4 are considered blocked as are
  // certain special doors on this level.
  dReg D0, D5;
  CELLFLAG cfD7;
  ROOMTYPE rtD6;
  DB0 *pDoor;
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  cfD7 = d.LevelCellFlags[mapX][mapY];
  rtD6 = (ROOMTYPE)(cfD7>>5);
  if (rtD6 == roomDOOR)
  {
    pDoor = FirstObjectRecordAddressDB0(mapX, mapY); //Door
    D5W = (I16)(cfD7 & 7); // door type
    SET(D0W, D5W==3);
    if (D0W == 0)
    {
      SET(D0W, D5W==4);
    };
    if (D0W != 0)
    {
      D0W = d.DoorTOC[pDoor->doorType()];//one of two types on level
      SET(D0W, (D0W & 0x100) == 0);// The high order byte
    };
    D0W = (I16)(D0W & 1);
  }
  else
  {
    SET(D0W, rtD6==roomSTONE);
    if (D0W == 0)
    {
      SET(D0W, rtD6 == roomFALSEWALL);
      if (D0W != 0)
      {
        SET(D0W, (cfD7 & 4) == 0);
      };
    };
  };
  return D0W != 0;
}

//*********************************************************
//
//*********************************************************
//  TAG00bf00
bool StoneOrClosedFalseWall(i32 mapX, i32 mapY)
{
  CELLFLAG cf;
  ROOMTYPE rt;
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  cf = d.LevelCellFlags[mapX][mapY];
  rt = (ROOMTYPE)(cf>>5);
  if (rt == roomSTONE)     return true;
  if (rt != roomFALSEWALL) return false;
  if (cf & 4) return false;
  return true;
}

//*********************************************************
//Generally, we try to follow a straight line between
// the party and the monster by keeping the slope
// of the line as constant as possible.  If we run into
// a wall (as determined by the provided function) we
// say it is impossible and return a zero.
// Else we return the distance to target. Orthogonal crow.
//*********************************************************
i16 TestDirectPathOpen(i32 mapX,    //8
                       i32 mapY,    //10
                       i32 partyX,  //12
                       i32 partyY,  //14
                       bool (*function)(i32,i32))
{
  dReg D0, D1, D4, D5, D6, D7;
  i16  w_12;
  bool DIAG_10;
  i16  w_8;
  i16  w_6;
  bool NS_4;
  i16  w_2;
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  D0W = sw(abs(mapX-partyX));
  D1W = sw(abs(mapY-partyY));
  if (D0W+D1W  <= 1) return 1;
  D5W = sw(abs(partyX - mapX));
  D4W = sw(abs(partyY - mapY));
  NS_4 = D5W < D4W; // Set if north/south
  DIAG_10 = D5W == D4W; // // set if perfect diagonal
  D5W = sw(partyX);
  D7W =(I16)((partyX <= mapX)  ? 1 : -1); // Y increment party to monster
  D4W = sw(partyY);
  D6W = (I16)(partyY <= mapY ? 1 : -1); // Increment party to monster
  if (NS_4) // If North/south
  {
    w_2 = sw(D4W - mapY); // partyY-mapY
    if (w_2 != 0)
    {
      D0W = sw(64 * (D5W - mapX) / w_2);
    }
    else
    {
      D0W = 128;
    };
  }
  else
  {
    w_2 = sw(D5W - mapX);
    if (w_2 != 0)
    {
      D0W = sw(64 * (D4W - mapY)/w_2); //partyY-mapY
    }
    else
    {
      D0W = 128;
    };
  };
  w_12 = D0W;
  do
  {
    if (DIAG_10) //perfect diagonal
    {


      if (    (    ((*function)(sw(D5W+D7W), D4W) != 0)
                && ((*function)(D5W, sw(D4W+D6W)) != 0))
           || ((*function)(D5W=sw(D5W+D7W), D4W=sw(D4W+D6W))!=0) )
      {
        return 0;
      };
    }
    else
    {
      if (NS_4) //North/south
      {
        w_2 = sw(D4W-mapY); //
        if (w_2 != 0)
        {
          D0W = sw(64 * (D5W + D7W - mapX)/w_2);
        }
        else
        {
          D0W = 128;
        };
      }
      else
      {
        w_2 = sw(D5W + D7W - mapX); // one step in x-direction vs mapX
        if (w_2 != 0) // if not in adjacent column
        {
          D0W = sw(64 * (D4W - mapY)/w_2); // new slope to monster
        }
        else
        {
          D0W = 128;
        };
      };
      w_2 = sw(D0W - w_12); // new slope minus original slope
      w_6 = sw(abs(w_2));
      if (NS_4)
      {
        w_2 = sw(D4W + D6W - mapY);
        if (w_2 != 0)
        {
          D1W = sw(64 * (D5W - mapX)/w_2);
        }
        else
        {
          D1W = 128;
        };
      }
      else
      {
        w_2 = sw(D5W - mapX); //#columns to monster
        if (w_2 != 0)
        {
          D1W = sw(64 * (D4W + D6W - mapY)/w_2); // new slope if we take y-step
        }
        else
        {
          D1W = 128;
        };
      };
      w_2 = sw(D1W - w_12);//y-step slope vs original slope
      w_8 = sw(abs(w_2));//difference in slope if we take y-step
      if (w_6 < w_8)
      {
        D5W = sw(D5W + D7W); // Assume party moves in x-direction
      }
      else
      {
        D4W = sw(D4W + D6W);//Assume party takes the y-step
      };
      D0W = (*function)(D5W, D4W);
      if (D0W != 0) // non-zero if blocked
      {
        if (w_6 != w_8) return 0;
        D0W = (*function)(D5W=sw(D5W+D7W), D4W=sw(D4W-D6W));
        if (D0W != 0) return 0;
      };
    };
    D0W = sw(abs(D5W - mapX));
    D1W = sw(abs(D4W - mapY));
  } while (D1W + D0W > 1);
  return DistanceBetweenPoints(mapX, mapY, partyX, partyY);
}

//*********************************************************
//
//*********************************************************
//  TAG00c202
i16 Blocked(DB4 *pDB4, i32 P2, i32 mapX, i32 mapY)
{
  dReg         D0, D4, D5, D6, D7;
  MONSTERDESC *pmtDesc;
  i16          w_18;
  i16          w_8[4];
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  pmtDesc = &d.MonsterDescriptor[pDB4->monsterType()];
  if (   (d.Invisible != 0)
      && !pmtDesc->seesInvisible() ) return 0;
  if (pmtDesc->word2Bit2()) goto tag00c2fe;
  //ASSERT(pDB4->uByte5 < d.MaxITEM16);
  if (pDB4->groupIndex() < d.MaxITEM16)
  {
    D4W = d.Item16[pDB4->groupIndex()].facings();
  }
  else
  {
    D4W = 0x7ccc; //designed to cause error!
  };

  if (P2 < 0)
  {
    D6W = 0;
    for (P2=pDB4->numMonM1(); //#monsters in group-1
         P2>=0;
         P2--)
    {
//      D7W = sw((D4W >> (2*P2)) & 3); //Direction this monster facing?
      D7W = sw(TwoBitNibble(D4W,P2)); //Direction this monster facing?
      D5W = D6W;
      while (D5W-- != 0)
      {
        D0W = w_8[D5W];
        if (D7W == D0W) break;
      };
      if (D5W == -1) // if we fell out bottom of loop.
      {
        w_8[D6W++] = D7W;
      };
      // for (P2) continue
//
    }; // while (P2 >= 0)
  }
  else
  {
//    w_8[0] = sw((D4W >> 2*P2) & 3);
    w_8[0] = sw(TwoBitNibble(D4W,P2));
    D6W = 1;
  };
  while (D6W-- != 0)
  {
    D0W = IsItInThisDirection(
                   w_8[D6W],
                   mapX,
                   mapY,
                   d.partyX,
                   d.partyY);
    if (D0W == 0) continue;
tag00c2fe: //***
    D5W = pmtDesc->sightDistance();
    if (!pmtDesc->canSeeInDark())
    {
      D5W = sw(D5W - d.CurrentPalette/2);
    };
    w_18 = sw(Larger(1, D5W));
    if (d.OrthogonalDistance2Party > w_18) return 0; //Cannot see the party then zero.
    D0W = TestDirectPathOpen(
              mapX, mapY, d.partyX, d.partyY, BlockedTypeA);
    return D0W;
    //continue here
  }; // while (D6-- != 0)
  return 0;
}

//*********************************************************
//
//*********************************************************
//  TAG00c36c
i16 GetBestMonsterFacingP1(MONSTERDESC *pmtDesc, i32 mapX, i32 mapY)
{
  dReg D0, D6, D7;
  i16  w_10;
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  D7W = pmtDesc->smellingDistance();
  if (D7W == 0) return 0;

  if (   ((D7W+1)/2 >= d.OrthogonalDistance2Party)
      && (TestDirectPathOpen(mapX,
                             mapY,
                             d.partyX,
                             d.partyY,
                             StoneOrClosedFalseWall) != 0) )
  {
    d.SecondaryDirection = d.SecondaryDirectionToParty;
    return sw(d.PrimaryDirectionToParty + 1);
  };
  D6W = SearchFootprints(mapX, mapY);
  if (D6W != 0)
  {
    w_10 = STRandom0_3();
    D0W = sw(w_10 + (UI8)(d.Byte13220[D6W-1]));
    if (D0W > 30 - 2*D7W)
    {
      return sw(GetPrimaryAndSecondaryDirection(
                     mapX,
                     mapY,
                     BITS0_4(d.PartyFootprints[D6W]),
                     BITS5_9(d.PartyFootprints[D6W]) ) + 1);
    };
  };
  return 0;
}

//*********************************************************
//
//*********************************************************
//   TAG00c442
bool PossibleMove(const MONSTERDESC *pmtDesc,   //8
                  i32 mapX,                     //12
                  i32 mapY,                     //14
                  i32 direction,                //16
                  i16 P5)                       //18
{ // This function expects d.Obj13020 to be the RN of
  // a monster.  After loading a new game, d.Obj13020 may
  // be zero.
  // And even during an extended game play, Obj13020 will
  // sometimes point to the wrong monster.
  // So what do we do about that?  To be compatible
  // with the initial Atari version, we should deal with the
  // zero.  To be correct, we should fix d.Obj13020 so that
  // it reflects the current monster.  So that is what I
  // have done.
  dReg           D0, D1, D4, D5, D6, D7;
  CELLFLAG      *pcfA0;
  DB0           *DB0A2;
  DB1           *DB1A2;
  DB15          *pDB15A2;
  RN             obj_2;
  D4L = 0xccccc;
  D5L = 0xccccc;
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  TIMERTRACE(0xc442);
  d.Byte13030[direction] = 1;
  d.Obj13040 = RNeof;
  d.Word13042 = 0;
  d.Word13044 = 0;
  if (pmtDesc->timePerMove() == 255) return 0;

  UpdateXY(direction, 1, 0, &mapX, &mapY);//One step forward
  D7W = sw(mapX);
  D6W = sw(mapY);
  D0W = 0;
  d.Word13038 = 1; // Assume move is impossible.
  if (D7W < 0)        return false;
  if (D7W >= d.width) return false;
  if (D6W < 0)        return false;
  if (D6W >= d.height)return false;
  pcfA0 = d.LevelCellFlags[D7W]; // column pointer
  D5W = pcfA0[D6W]; // Get this room's CELLFLAG
  //D5W = D0W
  D4W = sw(D5W >> 5); // The type of room.
  if (D4W == roomSTONE) return false;
  if (D4W == roomSTAIRS)return false;
  if (D4W == roomPIT)
  {
    if ((D5W & 8) != 0) // if (pit is open)
    {
      if ( !pmtDesc->levitating()) //Levitate over open pit is ok.
      {
        if (!((D5W&1)?P5:(D5W&1))) //Can monster walk on fake pit?
        {
          return false;
        };
      };
    };
  };
  if (D4W == roomFALSEWALL) 
  {
    if ((D5W&4) == 0)  // if (closed)
    {
      if (!((D5W&1)?P5:(D5W&1))) // Can monster walk through false wall?
      {
        return false;
      };
    };
  };
  d.Word13038 = 0;

  if (pmtDesc->invincible())
  {
    for (obj_2 =  FindFirstObject(D7W, D6W);
         obj_2 != RNeof;
         obj_2 =  GetDBRecordLink(obj_2))
    {

      if (obj_2.dbType() != dbCLOUD) continue;
      pDB15A2 = GetRecordAddressDB15(obj_2);
      if (pDB15A2->type() != 50) continue;
      d.Byte13034[direction] = 1;
      d.Word13036++;
      return 0;
//
//
    };
  };
  for (;;)
  {
    ASSERT(D4L != 0xccccc);
    ASSERT(D5L != 0xccccc);
    if (D4W != roomTELEPORTER) break;
    if ((D5W & 8)==0) break;//break if teleporter inactive
    if (pmtDesc->word16_12_15() < 10) break;
    DB1A2 = FirstObjectRecordAddressDB1(D7W, D6W);
    if (DB1A2->what() == 0) break;//if not monsters
	// See comment at top of this function about d.Obj13020.  It may
	// be zero and it may be wrong.  I have patched the Atari code
  // ProcessTimer29To41 to always put the current monster
  // in Obj13020.  This seemed the 'right' thing to do.
    if (MonsterAllowedOnLevel(d.LastMonsterMoved, DB1A2->destLevel()))
            break;
    d.Word13038 = 1;
    return 0;
  };
  d.Word13044 =    (d.LoadedLevel == d.partyLevel)
                && (D7W == d.partyX)
                && (D6W == d.partyY);
  if (d.Word13044) return 0;
  for (;;)
  {
    if (D4W != roomDOOR) break;//
    DB0A2 = FirstObjectRecordAddressDB0(D7W, D6W);
    D0W = (I16)(D5W & 7);
    D1W = BITS5_5(DB0A2->mode()); //Up-down or sideways
    if (D1W != 0)
    {
      D1W = pmtDesc->verticalSize();
    }
    else
    {
      D1W = 1;
    };
    if (D0W <= D1W) break;
    if ((D5W & 7) == 5) break;
    if (pmtDesc->nonMaterial()) break;
    d.Word13042 = 1;
    return 0;
  };
  d.Obj13040 = FindFirstMonster(D7W, D6W);
  return d.Obj13040 == RNeof;
  ;
}

//*********************************************************
//
//*********************************************************
i16 TAG00c70c(const MONSTERDESC *pmtDesc,i32 P2,i32 P3,i16 P4)
{
  dReg D0, D7;
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  for (D7W = 0; D7W < 4; D7W++)
  {
    if (d.Byte13030[D7W] != 0) continue;
    D0W = PossibleMove(pmtDesc, P2, P3, D7W, P4);
    if (D0W != 0) return sw(D7W + 1);
//
//
  };
  return 0;
}

//*********************************************************
//
//*********************************************************
i16 TAG00c756(const MONSTERDESC *pmtDesc,  //8
              i32 mapX,              //12
              i32 mapY,              //14
              i32 direction)         //16
{
  dReg D7;
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  D7W = sw(direction);
  ASSERT(D7W < 4);
  if (d.Byte13034[D7W] != 0)
  {
    return 0;
  };
  mapX = sw(mapX + d.DeltaX[D7W]);
  mapY = sw(mapY + d.DeltaY[D7W]);
  return PossibleMove(pmtDesc, mapX, mapY, D7W, 0);
}

//*********************************************************
//
//*********************************************************
//   TAG00c7bc
void TurnMonster(ITEM16 *pI16,
                 i32 preferredDirection,
                 i32 monsterIndex,  // within group
                 bool P4)
{ //P4 means to treat the monsters a pairs.  For example,
  //worms, which occupy two corners, must turn together.
  dReg D0, D5;
  i32 newDir;
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  //D7W = preferredDirection;
  //D6W = monsterIndex;
  D5W = P4;
  if (P4)
  {
    if (   (d.Time == d.Time13130)
        && (pI16 == d.pI1613134) ) return;
  };
  D5W = pI16->facings(); // Old facing byte
//  D0W = sw(D5W >> (2*monsterIndex)); // Current facing
  D0W = sw(TwoBitNibble(D5W,monsterIndex)); // Current facing
  D0W = (I16)((D0W - preferredDirection) & 3); // relative to preference
  if (D0W == 2) // if facing away from party
  {
    newDir = ((STRandom() & 2) + preferredDirection + 1) & 3;
    D5W = SetMonsterPositionBits(
             D5W,  //old facing byte
             monsterIndex,
             newDir); //
  }
  else
  {
    newDir = preferredDirection;
    D5W = SetMonsterPositionBits(
               D5W,  //old directions byte
               monsterIndex,
               newDir); //new direction
  };
  if (P4)
  {
    D5W = SetMonsterPositionBits(
                     D5W,             //old directions byte
                     monsterIndex ^ 1, //monster number
                     newDir);          //facing direction
    d.Time13130 = d.Time;
    d.pI1613134 = pI16;
  };
  pI16->facings() = D5B;
}

//*********************************************************
//
//*********************************************************
//   TAG00c86c
void TurnMonsterGroup(ITEM16 *pI16,
                      i32 PreferredDirection,
                      i32 numMonster,
                      i32 P4)
{ // P4 means monsters should be treated as pairs.
  // This particularly applies to worms that occupy
  // two corners of the room.  They must turn together.
  i32 monsterIndex;
  bool bD6;
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  monsterIndex = numMonster;
  bD6 = ( (monsterIndex!=0) && (P4!=0) );
  if (bD6) monsterIndex--;
  do
  {
//
    if ( (monsterIndex == 0) || (STRandomBool() != 0) )
    {

      TurnMonster(pI16,
                  PreferredDirection,
                  monsterIndex,
                  bD6);
    };
    monsterIndex--;
  } while (monsterIndex >= 0);
}

//*********************************************************
//
//*********************************************************
i16 TAG00c8c0(DB4 *pDB4, //8
              i32 mapX,  //12
              i32 mapY,  //14
              i16 P4)    //16 //MonsterIndex within group
{ //(i16)
  //Called to compute last parameter of call
  // to NextMonsterUpdateTime.
  //Return 0 if (no live character or ???).
  //      else 1;
  dReg         D4, D5, D6;
  RN           objD7;
  MONSTERTYPE  mtD7;
  ITEM16       item16_20;
  DB4         *DB4A3;
  MONSTERDESC *pmtDesc;
  CHARDESC    *pch_4;
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  DB4A3 = pDB4;
  d.Long12950 = d.Time;
  ASSERT(DB4A3->groupIndex() < d.MaxITEM16);
  memmove(&item16_20, &d.Item16[DB4A3->groupIndex()], 16);
  mtD7 = DB4A3->monsterType();
  pmtDesc = &d.MonsterDescriptor[mtD7];
  D6W = d.PrimaryDirectionToParty;
  D5W = item16_20.positions();
  if (D5W == 255)
  {
    D5W = STRandomBool();
  }
  else
  {
//    D5W = sw(((((D5W >> (2*P4)) & 3) + 5 - D6W) & 2) / 2);
    D5W = sw((((TwoBitNibble(D5W,P4)) + 5 - D6W) & 2) / 2);
    // 1 if CCW turn is good?????
  };
  D5W = (I16)((D5W + D6W) & 3);

  if (    (pmtDesc->word14_12_15() > 1) // ie: 3, 4, or 6
       && ((d.OrthogonalDistance2Party > 1) || (STRandomBool() != 0))   )
  {
    if ( (mtD7 == mon_Vexirk) || (mtD7 == mon_LordChaos) )
    {
      if (STRandomBool() != 0)
      {
        objD7 = RNFireball;
      }
      else
      {
        switch (STRandom0_3())
        {
        case 0: objD7 = RNDispellMissile; break;

        case 1: objD7 = RNLightning; break;

        case 2: objD7 = RNPoisonCloud; break;

        case 3: objD7 = RNZoSpell; break;
        }; //switch()
      };
    }
    else
    {
      switch (mtD7)
      {
      case mon_SlimeDevil:
          objD7 = RNPoison; break;
      case mon_FlyingEye:
          if (STRandom(8) != 0) objD7 = RNLightning;
          else objD7 = RNZoSpell;
          break;
      case mon_Zytaz:
          if (STRandomBool() != 0) objD7 = RNPoisonCloud;
          else objD7 = RNFireball;
          break;

      case mon_Demon:
      case mon_Dragon:
          objD7 = RNFireball;
          break;
      }; // switch
    };
    D4W = sw(pmtDesc->uByte8[4]/4 + 1);
    D4W = sw(D4W + STRandom(D4W));
    D4W = sw(D4W + STRandom(D4W));
    LaunchMissile(
                  objD7,       //parameter
                  mapX,
                  mapY,
                  D5W,        //position??
                  d.PrimaryDirectionToParty, //direction???
                  ApplyLimits(20, D4W, 255),
                  pmtDesc->uByte8[4],
                  8);
  }
  else
  {
    if (pmtDesc->word2Bit4())
    {
      D5W = STRandom0_3();
      for (D4W = 0;
           (D4W<4) && (d.CH16482[D5W].HP()==0);
           D4W++)
      { //look for live character.
//
      };
      if (D4W == 4) return 0;
    }
    else
    {
      D5W = GetCharacterToDamage(mapX, mapY, D5W);
      if (D5W < 0) return 0;
    };
    if (mtD7 == mon_Giggler)
    {
      StealFromCharacter(DB4A3, D5W);
    }
    else
    {
      D4W = sw(1 + TAG00f6ee(DB4A3, D5W));
      pch_4 = &d.CH16482[D5W];
      if (D4W > pch_4->uByte41)
      {
        pch_4->uByte41 = (UI8)(D4W);
        pch_4->facing3 = (UI8)((D6W+2) & 3);
      };
    };
  };
  D4W = pmtDesc->uByte1;
  if (D4W)
  {
    D4W--;
    QueueSound(d.uByte9672[D4W],mapX,mapY,1);
  };
  return (1);
}

//*********************************************************
//
//*********************************************************
void TAG00cb68(TIMER *pTimer,const ui32 time)
{
  TIMERTYPE tt;
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  if (time < (pTimer->timerTime & 0xffffff))
  {
    switch (pTimer->Function())
    {
    case TT_37:         tt = TT_32;         break;
    case TT_MONSTER_B0: tt = TT_MONSTER_A0; break;
    case TT_MONSTER_B1: tt = TT_MONSTER_A1; break;
    case TT_MONSTER_B2: tt = TT_MONSTER_A2; break;
    case TT_MONSTER_B3: tt = TT_MONSTER_A3; break;
    default: die(0xf5af, "Illegal Monster AI Timer");
             tt = TT_MONSTER_B0;
             break;
    };
    pTimer->Function(tt);
    pTimer->timerUByte8 = (UI8)((pTimer->timerTime & 0xffffff) - time);
    pTimer->timerTime = time | (pTimer->timerTime & 0xff000000);
  }
  else
  {
    pTimer->timerUByte8 = (UI8)(time - (pTimer->timerTime & 0xffffff));
  };
  SetTimer(pTimer);
}


//********************************************************//SMT
//  They are here to make duplicating pieces of code      //SMT
//  easier.  We are duplicating to get rid of gotos.      //SMT
//********************************************************//SMT
void Set_Monster_Timer(                                   //SMT
                   TIMER&    timer_70,                    //SMT
                   i32&      i_60,                        //SMT
             const i16       timeUntilNextUpdate,         //SMT
             const i16       w_40                         //SMT
                       )                                  //SMT
{                                                         //SMT
  /*tag00dcb8:*/                                          //SMT
  if (AITraceActive)                                      //SMT
  {                                                       //SMT
    fprintf(GETFILE(TraceFile),                           //SMT
            "      MAI Set_Monster_Timer(i_60=%d,"        //SMT
            "timeUntilNextUpdate=%d,w_40=%d)\n",          //SMT
             i_60, timeUntilNextUpdate, w_40);            //SMT
  };                                                      //SMT
  TIMERTRACE(0xdcb8);                                     //SMT
  if (w_40 != 0)                                          //SMT
  {                                                       //SMT
    TIMERTRACE(0xdcbe);                                   //SMT
    timer_70.timerTime += timeUntilNextUpdate & 0xffff;   //SMT
  }                                                       //SMT
  else                                                    //SMT
  {                                                       //SMT
    i_60 += timeUntilNextUpdate & 0xffff;                 //SMT
  };                                                      //SMT
  TAG00cb68(&timer_70, i_60);                             //SMT
}                                                         //SMT


//***************************************************
//  They are here to make duplicating pieces of code 
//  easier.  We are duplicating to get rid of gotos. 
//***************************************************
void EnsureI60NonZero(i32& i_60, ITEM16 *pI16A2)  //I60NZ
{                                                 //I60NZ
  if (i_60 == 0)                                  //I60NZ
  {                                               //I60NZ
    TIMERTRACE(0xdca6);                           //I60NZ
    i_60 = NextMonsterUpdateTime(pI16A2, -1, 0);  //I60NZ
  };                                              //I60NZ
}                                                 //I60NZ


//***************************************************         //I52R
//  They are here to make duplicating pieces of code          //I52R
//  easier.  We are duplicating to get rid of gotos.          //I52R
//***************************************************         //I52R
void Increment_Time_By_W52_Plus_Random(                       //I52R
                    TIMER&  timer_70,                         //I52R
              const i16&    w_52                              //I52R
              )                                               //I52R
{                                                             //I52R
  /*tag00dc7e:*/                                              //I52R
  TIMERTRACE(0xdc7e);                                         //I52R
  timer_70.timerTime += Larger(1, w_52 + STRandom0_3() - 1);  //I52R
}                                                             //I52R
                
//***************************************************         //DTMSF
//  They are here to make duplicating pieces of code          //DTMSF
//  easier.  We are duplicating to get rid of gotos.          //DTMSF
//***************************************************         //DTMSF
void Delete_Timers_Maybe_Set_Fear(                            //DTMSF
                      DB4    *DB4A3,                          //DTMSF
                      ITEM16 *pI16A2,                         //DTMSF
                const i32     mapX,                           //DTMSF
                const i32     mapY,                           //DTMSF
                const bool    fearFactorIs6                   //DTMSF
                                  )                           //DTMSF
{                                                             //DTMSF
  //ASSERT(fearFactorIs6 != 0x7ddd);                          //DTMSF
  if (fearFactorIs6)                                          //DTMSF
  {                                                           //DTMSF
    TIMERTRACE(0xd46c);                                       //DTMSF
    /*D3W = 7;*/                                              //DTMSF
    DB4A3->fear(StateOfFear7);                                //DTMSF
  };                                                          //DTMSF 
  ClearAllUByte12_80_DeleteMovementTimers(pI16A2, mapX, mapY);//DTMSF
}                                                             //DTMSF


//****************************************************************
// This was extracted from ProcessTimers29to41 so that the code   
// could be 'unwound' a bit.  This code is used in several places 
// and used to be reached via 'goto' instructions.                
//****************************************************************
void MaybeDelTimers_Fear6_TurnIndividuals(                    //MDF6TI
                      ITEM16         *pI16A2,                 //MDF6TI
                      DB4            *DB4A3,                  //MDF6TI
                      TIMER&          timer_70,               //MDF6TI
                const i16&            timeUntilNextUpdate,    //MDF6TI
                const TIMERTYPE&      timeFunc,               //MDF6TI
                const i32&            mapX,                   //MDF6TI
                const i32&            mapY,                   //MDF6TI
                const MONSTERDESC&    mtDescLocal,            //MDF6TI
                const i16&            w_50,                   //MDF6TI
                const i16&            w_48,                   //MDF6TI
                const i16&            w_40                    //MDF6TI
                )                                             //MDF6TI
{                                                             //MDF6TI
  dReg D1, D3, D5;                                            //MDF6TI
  i32 monIdx;                                                 //MDF6TI
  i32 monsterDirection;                                       //MDF6TI
  i32 w_80;                                                   //MDF6TI
  TIMERTYPE tt;                                               //MDF6TI
  TIMERTRACE(0xd0f0);                                         //MDF6TI
  if (timeFunc == -2)                                         //MDF6TI
  {                                                           //MDF6TI
    TIMERTRACE(0xd0f8);                                       //MDF6TI
    DeleteMonsterMovementTimers(mapX, mapY);                  //MDF6TI
  };                                                          //MDF6TI
  pI16A2->uByte6 = ub(d.partyX);                              //MDF6TI
  pI16A2->uByte7 = ub(d.partyY);                              //MDF6TI
  D3W = 6;                                                    //MDF6TI
  DB4A3->fear(StateOfFear6);                                  //MDF6TI
  D5W = d.PrimaryDirectionToParty;                            //MDF6TI
                                                              //MDF6TI
  for (monIdx = w_50; monIdx >= 0; monIdx--)                  //MDF6TI
  {                                                           //MDF6TI
    i32 coinflip=2;                                           //MDF6TI
                                                              //MDF6TI
    /* Always turn monster 0 to the preferred direction.*/    //MDF6TI
    /* Turn other monsters with probability of 50       */    //MDF6TI
    /* percent.                                         */    //MDF6TI
    /* You may well ask what is happening here.         */    //MDF6TI
    /* The compiler optimization had                    */    //MDF6TI
    /* an error and treated (2*monIdx) as a loop        */    //MDF6TI
    /* constant.  So I could                            */    //MDF6TI
    /* not shift by (2*monIdx).  So I shifted twice     */    //MDF6TI
    /* by monIdx instead.                               */    //MDF6TI
    /* What grief!                                      */    //MDF6TI
   /*    monsterDirection =                             */    //MDF6TI
   /*        (pI16A2->facings() >> (2*monIdx)) & 3;     */    //MDF6TI
    monsterDirection =                                        //MDF6TI
         TwoBitNibble(pI16A2->facings(),monIdx);              //MDF6TI
    if (   (D5W != monsterDirection)                          //MDF6TI
                                                              //MDF6TI
      && ((monIdx==0) || ((coinflip=STRandomBool())==0)) )    //MDF6TI
    {                                                         //MDF6TI
      TIMERTRACE(0xd154);                                     //MDF6TI
                                                              //MDF6TI
      TurnMonster(pI16A2,                                     //MDF6TI
                  D5W,  /*preferred direction*/               //MDF6TI
                  monIdx,  /*monster index*/                  //MDF6TI
                  (w_50 != 0) && (w_48 == 1));                //MDF6TI
      w_80 = STRandom0_3();                                   //MDF6TI
      D1L = d.Time;                                           //MDF6TI
      D3L = w_80 & 0xffff;                                    //MDF6TI
      D1L += D3L + 2;                                         //MDF6TI
      timer_70.timerTime =                                    //MDF6TI
             (timer_70.timerTime & 0xff000000) | D1L;         //MDF6TI
    }                                                         //MDF6TI
    else                                                      //MDF6TI
    {                                                         //MDF6TI
      TIMERTRACE(0xd1a8);                                     //MDF6TI
      timer_70.timerTime =                                    //MDF6TI
        (timer_70.timerTime & 0xff000000) | (d.Time + 1);     //MDF6TI
    };                                                        //MDF6TI
    if (w_40 != 0)                                            //MDF6TI
    {                                                         //MDF6TI
      TIMERTRACE(0xd1c4);                                     //MDF6TI
      timer_70.timerTime +=                                   //MDF6TI
        Smaller(STRandom0_3()+(UI8)(mtDescLocal.uByte7)/2,    //MDF6TI
                timeUntilNextUpdate);                         //MDF6TI
    };                                                        //MDF6TI
    switch (monIdx)                                           //MDF6TI
    {                                                         //MDF6TI
    case 0: tt = TT_MONSTER_B0; break;                        //MDF6TI
    case 1: tt = TT_MONSTER_B1; break;                        //MDF6TI
    case 2: tt = TT_MONSTER_B2; break;                        //MDF6TI
    case 3: tt = TT_MONSTER_B3; break;                        //MDF6TI
    default: die(0x3ffa, "Illegal Monster Index");            //MDF6TI
             tt = TT_MONSTER_B0;                              //MDF6TI
             break;                                           //MDF6TI
    };                                                        //MDF6TI
    timer_70.Function(tt);            //monIdx=0->3????       //MDF6TI
    TAG00cb68(&timer_70,                                      //MDF6TI
              NextMonsterUpdateTime(pI16A2,                   //MDF6TI
              (i16)monIdx, 0));                               //MDF6TI
    /*continue here*/                                         //MDF6TI
                                                              //MDF6TI
  }; /* for (monIdx) */                                       //MDF6TI
}                                                             //MDF6TI


//******************************************************************
// This was extracted from ProcessTimers29to41 so that the code     
// could be 'unwound' a bit.  This code is used in several places   
// and used to be reached via 'goto' instructions.                  
//******************************************************************
void Turn_Monsters_As_Group(                                  //TMAG
                    dReg&   D5,                               //TMAG
                    ITEM16 *pI16A2,                           //TMAG
              const i16&    w_54,                             //TMAG
              const i16&    w_50, //number of monsters        //TMAG
              const i16&    w_48, //Must turn as group flag   //TMAG
              const bool&   bool_36                           //TMAG
                            )                                 //TMAG
{                                                             //TMAG
  TIMERTRACE(0xd42e);                                         //TMAG
  if ( (bool_36 == false) && (w_54 >= 0) )                    //TMAG
  {                                                           //TMAG
    TIMERTRACE(0xd43a);                                       //TMAG
    D5W = STRandom0_3();                                      //TMAG
  };                                                          //TMAG
  TurnMonsterGroup(pI16A2,                                    //TMAG
                   D5W,    /*preferred direction     */       //TMAG
                   w_50,   /*number of monsters      */       //TMAG
                   w_48);  /*must-turn-as-group flag */       //TMAG
                           /* (worms, eg)            */       //TMAG
  TIMERTRACE(0xd454);                                         //TMAG
}                                                             //TMAG


//******************************************************************      //S37T
// This was extracted from ProcessTimers29to41 so that the code           //S37T
// could be 'unwound' a bit.  This code is used in several places         //S37T
// and used to be reached via 'goto' instructions.                        //S37T
//******************************************************************      //S37T
void Start37Timer(                                                        //S37T
            TIMER&             timer_70,                                  //S37T
            ITEM16             *pI16A2,                                   //S37T
            i32&               i_60,                                      //S37T
            const i16          timeUntilNextUpdate,                       //S37T
            const i16          w_40                                       //S37T
                  )                                                       //S37T
{                                                                         //S37T
  TIMERTRACE(0xdc9a);                                                     //S37T
  timer_70.Function(TT_37);                                    //S37T
  EnsureI60NonZero(i_60, pI16A2);                                         //S37T
  Set_Monster_Timer(                                                      //S37T
                   timer_70,                                              //S37T
                   i_60,                                                  //S37T
                   timeUntilNextUpdate, //const                           //S37T
                   w_40                 //const                           //S37T
                   );                                                     //S37T

}

//******************************************************************      //PIn
// This was extracted from ProcessTimers29to41 so that the code           //PIn
// could be 'unwound' a bit.  This code is used in several places         //PIn
// and used to be reached via 'goto' instructions.                        //PIn
//******************************************************************      //PIn
bool Process_Invincible(                                                  //PIn
            TIMER&             timer_70,                                  //PIn
            ITEM16             *pI16A2,                                   //PIn
            i32&               i_60,                                      //PIn
            i16&               w_54,                                      //PIn
            i16&               w_52,                                      //PIn
            bool&              bool_36, //Value ignored; Sometimes set.   //PIn
            i16&               w_32,                                      //PIn
            i16&               w_30,                                      //PIn
            dReg&              D5,                                        //PIn
            const MONSTERDESC& mtDescLocal,                               //PIn
            const RN&          monster,                                   //PIn
            const i16&         timeUntilNextUpdate,                       //PIn
            const i16&         w_50,                                      //PIn
            const i16&         w_48,                                      //PIn
            const i16&         w_40,                                      //PIn
            const i32&         mapX,                                      //PIn
            const i32&         mapY,                                      //PIn
            const i32&         PreferredDirection)                        //PIn
{                                                                         //PIn
  dReg D0, D4;                                                            //PIn
  TIMERTRACE(0xd63c);                                                     //PIn
  if (AITraceActive)
  {
    fprintf(GETFILE(TraceFile),
        "      MAI Entering Process_Invincible\n");
  };
  TAG00c70c(&mtDescLocal, mapX, mapY, 0);                                 //PIn
  D5W = sw(PreferredDirection);                                           //PIn
  D0W = TAG00c756(&mtDescLocal, mapX, mapY, D5W);                         //PIn
  if (D0W == 0)                                                           //PIn
  {                                                                       //PIn
    TIMERTRACE(0xd66a);                                                   //PIn
    D5W = sw((i32)d.SecondaryDirection);                                  //PIn
    D0W = TAG00c756(&mtDescLocal, mapX, mapY, D5W);                       //PIn
    if (D0W == 0)                                                         //PIn
    {                                                                     //PIn
      TIMERTRACE(0xd686);                                                 //PIn
      if (d.Word13036 != 0)                                               //PIn
      {                                                                   //PIn
        TIMERTRACE(0xd686);                                               //PIn
        D5W = (I16)((D5W + 2) & 3);                                       //PIn
        D0W = TAG00c756(&mtDescLocal, mapX, mapY, D5W);                   //PIn
      };                                                                  //PIn
      if (D0W == 0)                                                       //PIn
      {                                                                   //PIn
        TIMERTRACE(0xd6ac);                                               //PIn
        if (d.Word13036 < 2)                                              //PIn
        {                                                                 //PIn
          TIMERTRACE(0xd72c);                                             //PIn
          TurnMonsterGroup(pI16A2, PreferredDirection, w_50, w_48);       //PIn 
          Increment_Time_By_W52_Plus_Random(timer_70, w_52);              //PIn
          Start37Timer(                                                   //PIn
                 timer_70,                                                //PIn
                 pI16A2,                                                  //PIn
                 i_60,                                                    //PIn
                 timeUntilNextUpdate,  //const                            //PIn
                 w_40                  //const                            //PIn
                 );                                                       //PIn
          return true;                                                    //PIn
        };                                                                //PIn
        TIMERTRACE(0xd6b4);                                               //PIn
        D5W = sw((PreferredDirection + 2) & 3);                           //PIn
        D0W = TAG00c756(&mtDescLocal, mapX, mapY, D5W);                   //PIn
        if (D0W == 0)                                                     //PIn
        {                                                                 //PIn
          TIMERTRACE(0xd72c);                                             //PIn
          TurnMonsterGroup(pI16A2, PreferredDirection, w_50, w_48);       //PIn
          Increment_Time_By_W52_Plus_Random(timer_70, w_52);              //PIn
          Start37Timer(                                                   //PIn
                 timer_70,                                                //PIn
                 pI16A2,                                                  //PIn
                 i_60,                                                    //PIn
                 timeUntilNextUpdate,  //const                            //PIn
                 w_40                  //const                            //PIn
                 );                                                       //PIn
          return true;                                                    //PIn
        };                                                                //PIn
      };                                                                  //PIn
    };                                                                    //PIn
  };                                                                      //PIn
//tag00d6d6:                                                              //PIn
  TIMERTRACE(0xd6d6);                                                     //PIn
  // Try two steps in direction D5W???                                    //PIn
  w_30 = sw(mapX);                                                        //PIn
  w_32 = sw(mapY);                                                        //PIn
  w_30 = sw(w_30 + 2*d.DeltaX[D5W]);                                      //PIn
  w_32 = sw(w_32 + 2*d.DeltaY[D5W]);                                      //PIn
  QueueSound(17, w_30, w_32, 1);                                          //PIn
  TIMERTRACE(0xd302);                                                     //PIn
  D4W = sw(w_52/2 - w_54);                                                //PIn
  bool_36 = D4W <= 0;                                                     //PIn
  if (bool_36)                                                            //PIn
  {                                                                       //PIn
    TIMERTRACE(0xd31c);                                                   //PIn
    D0W = MoveObject(monster, mapX, mapY, w_30, w_32);                    //PIn
    ASSERT(D0W != 0xccc);                                                 //PIn
    if (D0W != 0)                                                         //PIn
    {                                                                     //PIn
      return true;                                                        //PIn
    };                                                                    //PIn
    timer_70.timerUByte6 = ub(d.NewX);                                    //PIn
    timer_70.timerUByte7 = ub(d.NewY);                                    //PIn
    pI16A2->ubPrevX = ub(mapX);                                            //PIn
    pI16A2->ubPrevY = ub(mapY);                                            //PIn
    pI16A2->uByte4 = (ui8)d.Time;                                         //PIn
  }                                                                       //PIn
  else                                                                    //PIn
  {                                                                       //PIn
    TIMERTRACE(0xd362);                                                   //PIn
    w_52 = D4W;                                                           //PIn
    w_54 = -1;                                                            //PIn
  };                                                                      //PIn
  return false;                                                           //PIn
}                                                                         //PIn
  

//******************************************************************//SF
// This was extracted from ProcessTimers29to41 so that the code     //SF
// could be 'unwound' a bit.  This code is used in several places   //SF
// and used to be reached via 'goto' instructions.                  //SF
//******************************************************************//SF
void Standard_Finish(                                               //SF
                           dReg&           D5,                      //SF
                           ITEM16         *pI16A2,                  //SF
                           TIMER&          timer_70,                //SF
                           i32&            i_60,                    //SF
                           DB4            *DB4A3,                   //SF
                     const i16             w_54,                    //SF
                     const i16             w_52,                    //SF
                     const i16             w_50,                    //SF
                     const i16             w_48,                    //SF
                     const bool            fearFactorIs6,           //SF
                     const i16             w_40,                    //SF
                     const bool            bool_36,                 //SF
                     const i16             w_34,                    //SF
                     const TIMERTYPE       timeFunc,                //SF
                     const MONSTERDESC&    mtDescLocal,             //SF
                     const i16             timeUntilNextUpdate,     //SF
                     const i32             mapX,                    //SF
                     const i32             mapY                     //SF
                     )                                              //SF
{                                                                   //SF
  if (AITraceActive)
  {
    fprintf(GETFILE(TraceFile),
        "      MAI Entering Standard_Finish\n");
  };
  if (bool_36 == false)                                             //SF
  {                                                                 //SF
    TIMERTRACE(0xd40c);                                             //SF
    if (STRandom0_3() != 0)                                         //SF
    {                                                               //SF
      TIMERTRACE(0xd414);                                           //SF
                                                                    //SF
      ASSERT( (timeFunc==-3) || (w_34 != 0x7ddd) );                 //SF
      //                                                            //SF
      // This happened once when                                    //SF
      // I was bashing an oitu with a door.                         //SF
      // Happened when I sent fireball at oitu. (timeFunc=-2)       //SF
      // Happened again when I bashed a demon with a door.          //SF
      // Notice that if (timeFunc==-3) then we unconditionally      //SF
      // make the same jump as we make conditionally here.          //SF
      //                                                            //SF
      // Therefore, the fact that w_34 is undefined will            //SF
      // never do any harm (if timeFunc==-3).                       //SF
      //                                                            //SF
      // If too far away then don't turn towards party.             //SF
      if (w_34 > mtDescLocal.smellingDistance())                    //SF
      {                                                             //SF
        TIMERTRACE(0xd454);                                         //SF
        if (timeFunc < -1)                                          //SF
        {                                                           //SF
          TIMERTRACE(0xd45c);                                       //SF
          if (bool_36 == false)                                     //SF
          {                                                         //SF
            return;                                                 //SF
          };                                                        //SF
          Delete_Timers_Maybe_Set_Fear(                             //SF
                                       DB4A3,                       //SF
                                       pI16A2,                      //SF
                                       mapX,                        //SF
                                       mapY,                        //SF
                                       fearFactorIs6                //SF
                                       );                           //SF
        };                                                          //SF
        Increment_Time_By_W52_Plus_Random(timer_70, w_52);          //SF
        Start37Timer(                                               //SF
               timer_70,                                            //SF
               pI16A2,                                              //SF
               i_60,                                                //SF
               timeUntilNextUpdate, //const                         //SF
               w_40                 //const                         //SF
               );                                                   //SF
        return;                                                     //SF
      };                                                            //SF
    };                                                              //SF
    if (timeFunc == -3)                                             //SF
    {                                                               //SF
      TIMERTRACE(0xd454);                                           //SF
      if (timeFunc < -1)                                            //SF
      {                                                             //SF
        TIMERTRACE(0xd45c);                                         //SF
        if (bool_36 == false)                                       //SF
        {                                                           //SF
          return;                                                   //SF
        };                                                          //SF
        Delete_Timers_Maybe_Set_Fear(                               //SF
                                     DB4A3,                         //SF
                                     pI16A2,                        //SF
                                     mapX,                          //SF
                                     mapY,                          //SF
                                     fearFactorIs6                  //SF
                                     );                             //SF
      };                                                            //SF
      Increment_Time_By_W52_Plus_Random(timer_70, w_52);            //SF
      Start37Timer(                                                 //SF
             timer_70,                                              //SF
             pI16A2,                                                //SF
             i_60,                                                  //SF
             timeUntilNextUpdate,  //const                          //SF
             w_40                  //const                          //SF
             );                                                     //SF
      return;                                                       //SF
    };                                                              //SF
  };                                                                //SF
  Turn_Monsters_As_Group(                                           //SF
                  D5,                                               //SF
                  pI16A2,                                           //SF
                  w_54,  //const                                    //SF
                  w_50,  //const//number of monsters                //SF
                  w_48,  //const//Must turn as group flag           //SF
                  bool_36//const                                    //SF
                  );                                                //SF
  if (timeFunc < -1)                                                //SF
  {                                                                 //SF
    TIMERTRACE(0xd45c);                                             //SF
    if (bool_36 == false)                                           //SF
    {                                                               //SF
      return;                                                       //SF
    };                                                              //SF
    Delete_Timers_Maybe_Set_Fear(                                   //SF
                                 DB4A3,                             //SF
                                 pI16A2,                            //SF
                                 mapX,                              //SF
                                 mapY,                              //SF
                                 fearFactorIs6                      //SF
                                 );                                 //SF
  };                                                                //SF
  Increment_Time_By_W52_Plus_Random(timer_70, w_52);                //SF
  Start37Timer(                                                     //SF
         timer_70,                                                  //SF
         pI16A2,                                                    //SF
         i_60,                                                      //SF
         timeUntilNextUpdate,  //const                              //SF
         w_40                  //const                              //SF
         );                                                         //SF
}                                                                   //SF


void Process_Invincible_And_Finish(                                 //PIAF
           dReg&          D5,                                       //PIAF
           DB4            *DB4A3,                                   //PIAF
           i32&           PreferredDirection,                       //PIAF
           ITEM16         *pI16A2,                                  //PIAF
           TIMER&         timer_70,                                 //PIAF
           i32&           i_60,                                     //PIAF
           i16&           w_54,                                     //PIAF
           i16&           w_52,                                     //PIAF
           bool&          bool_36,                                  //PIAF
           i16&           w_32,                                     //PIAF
           i16&           w_30,                                     //PIAF
     const i32&           mapX,                                     //PIAF
     const i32&           mapY,                                     //PIAF
     const TIMERTYPE      timeFunc,                                 //PIAF
     const RN&            monster,                                  //PIAF
     const i16&           timeUntilNextUpdate,                      //PIAF
     const MONSTERDESC&   mtDescLocal,                              //PIAF
     const bool&          invincible,                               //PIAF
     const i16&           w_50,                                     //PIAF
     const i16&           w_48,                                     //PIAF
     const bool&          fearFactorIs6,                            //PIAF
     const i16&           w_40,                                     //PIAF
     const i16&           w_34                                      //PIAF
                                   )                                //PIAF
{                                                                   //PIAF
  TIMERTRACE(0xd3cc);                                               //PIAF
  if (AITraceActive)
  {
    fprintf(GETFILE(TraceFile),
        "      MAI Entering Process_Invincible_And_Finish\n");
    if (bool_36)
    {
      fprintf(GETFILE(TraceFile),
        "      MAI bool_36 true..skiping 'while'\n");
    }
    else if (w_54 == -1)
    {
      fprintf(GETFILE(TraceFile),
        "      MAI w_54 = -1...skipping 'while'\n");
    }
    else if (!invincible)
    {
      fprintf(GETFILE(TraceFile),
        "      MAI Not invincible...skipping 'while'\n");
    };
  };
  while (   (bool_36 == false)                                      //PIAF
         && (w_54 != -1)                                            //PIAF
         && (invincible)                                            //PIAF
         && ((timeFunc == -3) || (STRandom0_3() == 0)))             //PIAF
  {                                                                 //PIAF
    TIMERTRACE(0xd3f0);                                             //PIAF
    PreferredDirection = STRandom0_3();                             //PIAF
    d.SecondaryDirection =                                          //PIAF
                 (DIRECTION)((PreferredDirection + 1) & 3);         //PIAF
//tag00d63c:                                                        //PIAF
    if (Process_Invincible(                                         //PIAF
           timer_70,  //Modified                                    //PIAF
           pI16A2,    //Modified                                    //PIAF
           i_60,      //Modified                                    //PIAF
           w_54,      //Modified                                    //PIAF
           w_52,      //Modified                                    //PIAF
           bool_36,   //Value ignored; Sometimes set.               //PIAF
           w_32,      //Modified                                    //PIAF
           w_30,      //Modified                                    //PIAF
           D5,        //Modified dir of movement                    //PIAF
           mtDescLocal,        //const                              //PIAF
           monster,            //const                              //PIAF
           timeUntilNextUpdate,//const                              //PIAF
           w_50,               //const                              //PIAF
           w_48,               //const                              //PIAF
           w_40,               //const                              //PIAF
           mapX,               //const                              //PIAF
           mapY,               //const                              //PIAF
           PreferredDirection  //const                              //PIAF
         )) return;                                                 //PIAF
    // goto tag00d3cc;  Not needed because of 'while' //            //PIAF
  };                                                                //PIAF
  Standard_Finish(                                                  //PIAF
                    D5,       //modified                            //PIAF
                    pI16A2,   //modified                            //PIAF
                    timer_70, //modified                            //PIAF
                    i_60,     //modified                            //PIAF
                    DB4A3,    //modified                            //PIAF
                    w_54,               //const                     //PIAF
                    w_52,               //const                     //PIAF
                    w_50,               //const                     //PIAF
                    w_48,               //const                     //PIAF
                    fearFactorIs6,      //const                     //PIAF
                    w_40,               //const                     //PIAF
                    bool_36,            //const                     //PIAF
                    w_34,               //const                     //PIAF
                    timeFunc,           //const                     //PIAF
                    mtDescLocal,        //const                     //PIAF
                    timeUntilNextUpdate,//const                     //PIAF
                    mapX,               //const                     //PIAF
                    mapY                //const                     //PIAF
                  );                                                //PIAF
}                                                                   //PIAF

//******************************************************************//TPTO
// This was extracted from ProcessTimers29to41 so that the code     //TPTO
// could be 'unwound' a bit.  This code is used in several places   //TPTO
// and used to be reached via 'goto' instructions.                  //TPTO
//******************************************************************//TPTO
void Try_Preferred_Direction_Then_Others(                           //TPTO
                       i32&            PreferredDirection,          //TPTO
                       ITEM16         *pI16A2,                      //TPTO
                       DB4            *DB4A3,                       //TPTO
                       TIMER&          timer_70,                    //TPTO
                       i32&            i_60,                        //TPTO
                       i16&            w_54,                        //TPTO
                       i16&            w_52,                        //TPTO
                       bool&           bool_36,                     //TPTO
                       i16&            w_32,                        //TPTO
                       i16&            w_30,                        //TPTO
                 const MONSTERDESC&    mtDescLocal,                 //TPTO
                 const i32&            mapX,                        //TPTO
                 const i32&            mapY,                        //TPTO
                 const bool&           invincible,                  //TPTO
                 const i16&            timeUntilNextUpdate,         //TPTO
                 const RN&             monster,                     //TPTO
                 const TIMERTYPE       timeFunc,                    //TPTO
                 const i16&            w_50,                        //TPTO
                 const i16&            w_48,                        //TPTO
                 const bool&           fearFactorIs6,               //TPTO
                 const i16&            w_42,                        //TPTO
                 const i16&            w_40,                        //TPTO
                 const i16&            w_34                         //TPTO
                 )                                                  //TPTO
{                                                                   //TPTO
  dReg D0, D4, D5;                                                  //TPTO
  TIMERTRACE(0xd55c + (PreferredDirection<<16));                    //TPTO
                                                                    //TPTO
  if (    (!PossibleMove(&mtDescLocal,                              //TPTO
                         mapX,                                      //TPTO
                         mapY,                                      //TPTO
                         D5W = sw(PreferredDirection),              //TPTO
                         w_42))                                     //TPTO
                                                                    //TPTO
       && (!PossibleMove(&mtDescLocal,                              //TPTO
                         mapX,                                      //TPTO
                         mapY,                                      //TPTO
                         D5W=sw((i32)d.SecondaryDirection),         //TPTO
                         (w_42 != 0) && (STRandomBool() !=0)))      //TPTO
                                                                    //TPTO
       && (!PossibleMove(&mtDescLocal,                              //TPTO
                         mapX,                                      //TPTO
                         mapY,                                      //TPTO
                         D5W=(I16)((D5W + 2) & 3),                  //TPTO
                         0))                                        //TPTO
       && (   (STRandom0_3() != 0)                                  //TPTO
           || (!PossibleMove(&mtDescLocal,                          //TPTO
                             mapX,                                  //TPTO
                             mapY,                                  //TPTO
                             D5W=sw((PreferredDirection + 2) & 3),  //TPTO
                             0))) )                                 //TPTO
  {                                                                 //TPTO
    //tag00d634:                                                    //TPTO
    TIMERTRACE(0xd634);                                             //TPTO
    if (!invincible)                                                //TPTO
    {                                                               //TPTO
      TIMERTRACE(0xd72c);                                           //TPTO
      TurnMonsterGroup(pI16A2, PreferredDirection, w_50, w_48);     //TPTO
      Increment_Time_By_W52_Plus_Random(timer_70, w_52);            //TPTO
      Start37Timer(                                                 //TPTO
             timer_70,                                              //TPTO
             pI16A2,                                                //TPTO
             i_60,                                                  //TPTO
             timeUntilNextUpdate, //const                           //TPTO
             w_40                 //const                           //TPTO
             );                                                     //TPTO
      return;                                                       //TPTO
    };                                                              //TPTO
    if (Process_Invincible(                                         //TPTO
          timer_70,  //Modified                                     //TPTO
          pI16A2,    //Modified                                     //TPTO
          i_60,      //Modified                                     //TPTO
          w_54,      //Modified                                     //TPTO
          w_52,      //Modified                                     //TPTO
          bool_36,   //VAlue ignored; Sometimes set.                //TPTO
          w_32,      //Modified                                     //TPTO
          w_30,      //Modified                                     //TPTO
          D5,        //Modified dir of movement                     //TPTO
          mtDescLocal,        //const                               //TPTO
          monster,            //const                               //TPTO
          timeUntilNextUpdate,//const                               //TPTO
          w_50,               //const                               //TPTO
          w_48,               //const                               //TPTO
          w_40,               //const                               //TPTO
          mapX,               //const                               //TPTO
          mapY,               //const                               //TPTO
          PreferredDirection  //const                               //TPTO
         )) return;                                                 //TPTO
  }                                                                 //TPTO
  else                                                              //TPTO
  {                                                                 //TPTO
    TIMERTRACE(0xd5fc);                                             //TPTO
    w_30 = sw(mapX);                                                //TPTO
    w_32 = sw(mapY);                                                //TPTO
    w_30 = sw(w_30 + d.DeltaX[D5W]);                                //TPTO
    w_32 = sw(w_32 + d.DeltaY[D5W]);                                //TPTO
    TIMERTRACE(0xd302);                                             //TPTO
    D4W = sw(w_52/2 - w_54);                                        //TPTO
    bool_36 = D4W <= 0;                                             //TPTO
    if (bool_36)                                                    //TPTO
    {                                                               //TPTO
      TIMERTRACE(0xd31c);                                           //TPTO
      D0W = MoveObject(monster, mapX, mapY, w_30, w_32);            //TPTO
      ASSERT(D0W != 0xccc);                                         //TPTO
      if (D0W != 0)                                                 //TPTO
      {                                                             //TPTO
        return;                                                     //TPTO
      };                                                            //TPTO
      timer_70.timerUByte6 = ub(d.NewX);                            //TPTO
      timer_70.timerUByte7 = ub(d.NewY);                            //TPTO
      pI16A2->ubPrevX = ub(mapX);                                    //TPTO
      pI16A2->ubPrevY = ub(mapY);                                    //TPTO
      pI16A2->uByte4 = (ui8)d.Time;                                 //TPTO
    }                                                               //TPTO
    else                                                            //TPTO
    {                                                               //TPTO
      TIMERTRACE(0xd362);                                           //TPTO
      w_52 = D4W;                                                   //TPTO
      w_54 = -1;                                                    //TPTO
    };                                                              //TPTO
  };                                                                //TPTO
  Process_Invincible_And_Finish(                                    //TPTO
                           D5,                 //modified           //TPTO
                           DB4A3,              //modified           //TPTO
                           PreferredDirection, //modified           //TPTO
                           pI16A2,             //modified           //TPTO
                           timer_70,           //modified           //TPTO
                           i_60,               //modified           //TPTO
                           w_54,               //modified           //TPTO
                           w_52,               //modified           //TPTO
                           bool_36,            //modified           //TPTO
                           w_32,               //modified           //TPTO
                           w_30,               //modified           //TPTO
                           mapX,                //const             //TPTO
                           mapY,                //const             //TPTO
                           timeFunc,            //const             //TPTO
                           monster,             //const             //TPTO
                           timeUntilNextUpdate, //const             //TPTO
                           mtDescLocal,         //const             //TPTO
                           invincible,          //const             //TPTO
                           w_50,                //const             //TPTO
                           w_48,                //const             //TPTO
                           fearFactorIs6,       //const             //TPTO
                           w_40,                //const             //TPTO
                           w_34                 //const             //TPTO
                       );                                           //TPTO
}                                                                   //TPTO


//******************************************************************//TTM
// This was extracted from ProcessTimers29to41 so that the code     //TTM
// could be 'unwound' a bit.  This code is used in several places   //TTM
// and used to be reached via 'goto' instructions.                  //TTM
//******************************************************************//TTM
void Try_To_Move(                                                   //TTM
          dReg                 D5,                                  //TTM
          DB4                 *DB4A3,                               //TTM
          ITEM16              *pI16A2,                              //TTM
          i32&                 PreferredDirection,                  //TTM
          TIMER&               timer_70,                            //TTM
          i32                  i_60,                                //TTM
          i16                  w_54,                                //TTM
          i16                  w_52,                                //TTM
          //i16&               w_42,                                //TTM
          bool&                bool_36,                             //TTM
          i16                  w_34,                                //TTM
          i16                  w_32,                                //TTM
          i16                  w_30,                                //TTM
          const TIMERTYPE      timeFunc,                            //TTM
          const RN             monster,                             //TTM
          const i16            timeUntilNextUpdate,                 //TTM
          const MONSTERDESC&   mtDescLocal,                         //TTM
          const bool           invincible,                          //TTM
          const i32            mapX,                                //TTM
          const i32            mapY,                                //TTM
          const i16            w_50,                                //TTM
          const i16            w_48,                                //TTM
          const bool           fearFactorIs6,                       //TTM
          const i16            w_40                                 //TTM
                 )                                                  //TTM
{                                                                   //TTM
  dReg D0, D1, D3;                                                  //TTM
  i16 w_42;                                                         //TTM
  TIMERTRACE(0xd74e);                                               //TTM
  w_42 = 1;                                                         //TTM
  w_34 = Blocked(DB4A3, -1, mapX, mapY);                            //TTM
  if (w_34 != 0)                                                    //TTM
  {                                                                 //TTM
    TIMERTRACE(0xd76c);                                             //TTM
    pI16A2->uByte6 = ub(d.partyX);                                  //TTM
    w_30 = d.partyX;                                                //TTM
    pI16A2->uByte7 = ub(d.partyY);                                  //TTM
    w_32 = d.partyY;                                                //TTM
    TIMERTRACE(0xd834);                                             //TTM
    D0W = (I16)(i32)GetPrimaryAndSecondaryDirection(                //TTM
                       mapX, mapY, w_30, w_32);                     //TTM
    PreferredDirection = (D0W + 2) & 3;                             //TTM
    d.SecondaryDirection =                                          //TTM
       (DIRECTION)((d.SecondaryDirection+2)&3);//180 degrees        //TTM
    w_52 = sw(w_52 - w_52/4);                                       //TTM
    Try_Preferred_Direction_Then_Others(                            //TTM
                         PreferredDirection,//modified              //TTM
                         pI16A2,            //modified              //TTM
                         DB4A3,             //modified              //TTM
                         timer_70,          //modified              //TTM
                         i_60,              //modified              //TTM
                         w_54,              //modified              //TTM
                         w_52,              //modified              //TTM
                         bool_36,           //modified              //TTM
                         w_32,              //modified              //TTM
                         w_30,              //modified              //TTM
                         mtDescLocal,         //const               //TTM
                         mapX,                //const               //TTM
                         mapY,                //const               //TTM
                         invincible,          //const               //TTM
                         timeUntilNextUpdate, //const               //TTM
                         monster,             //const               //TTM
                         timeFunc,            //const               //TTM
                         w_50,                //const               //TTM
                         w_48,                //const               //TTM
                         fearFactorIs6,       //const               //TTM
                         w_42,                //const               //TTM
                         w_40,                //const               //TTM
                         w_34                 //const               //TTM
                  );                                                //TTM
    return;                                                         //TTM
  };                                                                //TTM
  pI16A2->uByte5--;                                                 //TTM
  if (pI16A2->uByte5 != 0)                                          //TTM
  {                                                                 //TTM
//tag00d7ba:                                                        //TTM
    TIMERTRACE(0xd7ba);                                             //TTM
    if (STRandomBool() != 0)                                        //TTM
    {                                                               //TTM
      TIMERTRACE(0xd7c2);                                           //TTM
      D0W = TAG00c70c(&mtDescLocal, mapX, mapY, 0);                 //TTM
      if (D0W == 0)                                                 //TTM
      {                                                             //TTM
        TIMERTRACE(0xd7d8);                                         //TTM
        D0W = sw(abs(mapX - d.partyX));                             //TTM
        D1W = sw(abs(mapY - d.partyY));                             //TTM
        if (D1W + D0W <= 1)                                         //TTM
        {                                                           //TTM
          TIMERTRACE(0xd79e);                                       //TTM
          bool_36 = false;                                          //TTM
          D3W = 0;                                                  //TTM
          //30OCT02SETWBITS0_3(DB4A3->word14, D3W);                 //TTM
          DB4A3->fear(StateOfFear0);                                //TTM
          Turn_Monsters_As_Group(                                   //TTM
                          D5,                                       //TTM
                          pI16A2,                                   //TTM
                          w_54,  //const                            //TTM
                          w_50,  //const//number of monsters        //TTM
                          w_48,  //const//Must turn as group flag   //TTM
                          bool_36//const                            //TTM
                          );                                        //TTM
          if (timeFunc < -1)                                        //TTM
          {                                                         //TTM
            return;                                                 //TTM
          };                                                        //TTM
          Increment_Time_By_W52_Plus_Random(timer_70, w_52);        //TTM
          Start37Timer(                                             //TTM
                 timer_70,                                          //TTM
                 pI16A2,                                            //TTM
                 i_60,                                              //TTM
                 timeUntilNextUpdate, //const                       //TTM
                 w_40                 //const                       //TTM
                 );                                                 //TTM
          return;                                                   //TTM
        };                                                          //TTM
      };                                                            //TTM
      TIMERTRACE(0xd0808);                                          //TTM
      w_30 = pI16A2->uByte10;                                       //TTM
      w_32 = pI16A2->uByte11;                                       //TTM
      TIMERTRACE(0xd546);                                           //TTM
      PreferredDirection = GetPrimaryAndSecondaryDirection(         //TTM
                                  mapX,mapY,w_30,w_32);             //TTM
  // Direction to approach party.                                   //TTM
  //tag00d55c:                                                      //TTM
      Try_Preferred_Direction_Then_Others(                          //TTM
                        PreferredDirection,//modified               //TTM
                        pI16A2,            //modified               //TTM
                        DB4A3,             //modified               //TTM
                        timer_70,          //modified               //TTM
                        i_60,              //modified               //TTM
                        w_54,              //modified               //TTM
                        w_52,              //modified               //TTM
                        bool_36,           //modified               //TTM
                        w_32,              //modified               //TTM
                        w_30,              //modified               //TTM
                        mtDescLocal,         //const                //TTM
                        mapX,                //const                //TTM
                        mapY,                //const                //TTM
                        invincible,          //const                //TTM
                        timeUntilNextUpdate, //const                //TTM
                        monster,             //const                //TTM
                        timeFunc,            //const                //TTM
                        w_50,                //const                //TTM
                        w_48,                //const                //TTM
                        fearFactorIs6,       //const                //TTM
                        w_42,                //const                //TTM
                        w_40,                //const                //TTM
                        w_34                 //const                //TTM
                  );                                                //TTM
      return;                                                       //TTM
    };                                                              //TTM
    TIMERTRACE(0xd820);                                             //TTM
    w_30 = pI16A2->uByte6;                                          //TTM
    w_32 = pI16A2->uByte7;                                          //TTM
    TIMERTRACE(0xd834);                                             //TTM
    D0W = (I16)(i32)GetPrimaryAndSecondaryDirection(                //TTM
                                      mapX, mapY, w_30, w_32);      //TTM
    PreferredDirection = (D0W + 2) & 3;                             //TTM
    d.SecondaryDirection =                                          //TTM
       (DIRECTION)((d.SecondaryDirection+2)&3);//180 degrees        //TTM
    w_52 = sw(w_52 - w_52/4);                                       //TTM
    Try_Preferred_Direction_Then_Others(                            //TTM
                       PreferredDirection,//modified                //TTM
                       pI16A2,            //modified                //TTM
                       DB4A3,             //modified                //TTM
                       timer_70,          //modified                //TTM
                       i_60,              //modified                //TTM
                       w_54,              //modified                //TTM
                       w_52,              //modified                //TTM
                       bool_36,           //modified                //TTM
                       w_32,              //modified                //TTM
                       w_30,              //modified                //TTM
                       mtDescLocal,         //const                 //TTM
                       mapX,                //const                 //TTM
                       mapY,                //const                 //TTM
                       invincible,          //const                 //TTM
                       timeUntilNextUpdate, //const                 //TTM
                       monster,             //const                 //TTM
                       timeFunc,            //const                 //TTM
                       w_50,                //const                 //TTM
                       w_48,                //const                 //TTM
                       fearFactorIs6,       //const                 //TTM
                       w_42,                //const                 //TTM
                       w_40,                //const                 //TTM
                       w_34                 //const                 //TTM
                );                                                  //TTM
    return;                                                         //TTM
  };                                                                //TTM
                                                                    //TTM
//tag00d79e:                                                        //TTM
  TIMERTRACE(0xd79e);                                               //TTM
  bool_36 = false;                                                  //TTM
  D3W = 0;                                                          //TTM
  //30OCT02SETWBITS0_3(DB4A3->word14, D3W);                         //TTM
  DB4A3->fear(StateOfFear0);                                        //TTM
  Turn_Monsters_As_Group(                                           //TTM
                  D5,                                               //TTM
                  pI16A2,                                           //TTM
                  w_54,  //const                                    //TTM
                  w_50,  //const//number of monsters                //TTM
                  w_48,  //const//Must turn as group flag           //TTM
                  bool_36//const                                    //TTM
                  );                                                //TTM
  if (timeFunc < -1)                                                //TTM
  {                                                                 //TTM
    TIMERTRACE(0xd45c);                                             //TTM
    if (bool_36 == false)                                           //TTM
    {                                                               //TTM
      return;                                                       //TTM
    };                                                              //TTM
    Delete_Timers_Maybe_Set_Fear(                                   //TTM
                                 DB4A3,                             //TTM
                                 pI16A2,                            //TTM
                                 mapX,                              //TTM
                                 mapY,                              //TTM
                                 fearFactorIs6                      //TTM
                                 );                                 //TTM
  };                                                                //TTM
  Increment_Time_By_W52_Plus_Random(timer_70, w_52);                //TTM
  Start37Timer(                                                     //TTM
         timer_70,                                                  //TTM
         pI16A2,                                                    //TTM
         i_60,                                                      //TTM
         timeUntilNextUpdate,  //const                              //TTM
         w_40                  //const                              //TTM
         );                                                         //TTM
}                                                                   //TTM


//******************************************************************//T524
// This was extracted from ProcessTimers29to41 so that the code     //T524
// could be 'unwound' a bit.  This code is used in several places   //T524
// and used to be reached via 'goto' instructions.                  //T524
//******************************************************************//T524
void Try_Directions_D5_To_D4(                                       //T524
                 ITEM16        *pI16A2,                             //T524
                 dReg&          D4,                                 //T524
                 dReg&          D5,                                 //T524
                 i32&           PreferredDirection,                 //T524
                 DB4           *DB4A3,                              //T524
                 TIMER&         timer_70,                           //T524
                 i32            i_60,                               //T524
                 i16&           w_54,                               //T524
                 i16&           w_52,                               //T524
                 i16&           w_44,                               //T524
                 bool&          bool_36,                            //T524
                 i16&           w_32,                               //T524
                 i16&           w_30,                               //T524
           const TIMERTYPE&     timeFunc,                           //T524
           const bool&          invincible,                         //T524
           const i16            timeUntilNextUpdate,                //T524
           const RN             monster,                            //T524
           const MONSTERDESC&   mtDescLocal,                        //T524
           const i32&           mapX,                               //T524
           const i32&           mapY,                               //T524
           const i16&           w_50,                               //T524
           const i16&           w_48,                               //T524
           const bool&          fearFactorIs6,                      //T524
           const i16&           w_40,                               //T524
           const i16&           w_34                                //T524
           )                                                        //T524
{                                                                   //T524
  dReg D0;                                                          //T524
  //dReg D1, D3;                                                    //T524
  do                                                                //T524
  {                                                                 //T524
    TIMERTRACE(0xd28a);                                             //T524
//tag00d28a:                                                        //T524
    w_30 = sw(mapX);                                                //T524
    w_32 = sw(mapY);                                                //T524
    w_30 = sw(w_30 + d.DeltaX[D5W]);                                //T524
    w_32 = sw(w_32 + d.DeltaY[D5W]);                                //T524
    if (pI16A2->ubPrevX == w_30)                                     //T524
    {                                                               //T524
      TIMERTRACE(0xd2ca);                                           //T524
      if (pI16A2->ubPrevY == w_32)                                   //T524
      {                                                             //T524
        w_44 = STRandom0_3() == 0;                                  //T524
        TIMERTRACE(0xd2e2);                                         //T524
        if (w_44 == 0) goto tag00d36e;                              //T524
      };                                                            //T524
    };                                                              //T524
    D0W = PossibleMove(&mtDescLocal, mapX, mapY, D5W, 0);              //T524
    TIMERTRACE(0xd2fe);                                             //T524
    if (D0W != 0)                                                   //T524
    {                                                               //T524
      //while (from d728)                                           //T524
      //while (from d630)                                           //T524
                                                                    //T524
      TIMERTRACE(0xd302);                                           //T524
      D4W = sw(w_52/2 - w_54);                                      //T524
      bool_36 = D4W <= 0;                                           //T524
      if (bool_36)                                                  //T524
      {                                                             //T524
        TIMERTRACE(0xd31c);                                         //T524
        D0W = MoveObject(monster, mapX, mapY, w_30, w_32);          //T524
        ASSERT(D0W != 0xccc);                                       //T524
        if (D0W != 0)                                               //T524
        {                                                           //T524
          return;                                                   //T524
        };                                                          //T524
        timer_70.timerUByte6 = ub(d.NewX);                          //T524
        timer_70.timerUByte7 = ub(d.NewY);                          //T524
        pI16A2->ubPrevX = ub(mapX);                                  //T524
        pI16A2->ubPrevY = ub(mapY);                                  //T524
        pI16A2->uByte4 = (ui8)d.Time;                               //T524
      }                                                             //T524
      else                                                          //T524
      {                                                             //T524
        TIMERTRACE(0xd362);                                         //T524
        w_52 = D4W;                                                 //T524
        w_54 = -1;                                                  //T524
      };                                                            //T524
        Process_Invincible_And_Finish(                              //T524
                              D5,                 //modified        //T524
                              DB4A3,              //modified        //T524
                              PreferredDirection, //modified        //T524
                              pI16A2,             //modified        //T524
                              timer_70,           //modified        //T524
                              i_60,               //modified        //T524
                              w_54,               //modified        //T524
                              w_52,               //modified        //T524
                              bool_36,            //modified        //T524
                              w_32,               //modified        //T524
                              w_30,               //modified        //T524
                              mapX,                //const          //T524
                              mapY,                //const          //T524
                              timeFunc,            //const          //T524
                              monster,             //const          //T524
                              timeUntilNextUpdate, //const          //T524
                              mtDescLocal,         //const          //T524
                              invincible,          //const          //T524
                              w_50,                //const          //T524
                              w_48,                //const          //T524
                              fearFactorIs6,       //const          //T524
                              w_40,                //const          //T524
                              w_34                 //const          //T524
            );                                                      //T524
      return;                                                       //T524
    };                                                              //T524
    tag00d36e:                                                      //T524
    TIMERTRACE(0xd36e);                                             //T524
    if (d.Word13044 != 0)                                           //T524
    {                                                               //T524
      TIMERTRACE(0xd374);                                           //T524
      if (timeFunc != -3)                                           //T524
      {                                                             //T524
        TIMERTRACE(0xd37c);                                         //T524
        if (   ((timeUntilNextUpdate & 15)  != 5)                   //T524
            || (TAG00c70c(&mtDescLocal, mapX, mapY, 0)==0)          //T524
            || (STRandomBool() != 0) )                              //T524
        {                                                           //T524
          MaybeDelTimers_Fear6_TurnIndividuals(                     //T524
                      pI16A2,
                      DB4A3,
                      timer_70,
                      timeUntilNextUpdate,//const
                      timeFunc,           //const
                      mapX,               //const
                      mapY,               //const
                      mtDescLocal,        //const
                      w_50,               //const
                      w_48,               //const
                      w_40                //const
                      );
          return;                                                   //T524
        };                                                          //T524
        TIMERTRACE(0xd38a);                                         //T524
      };                                                            //T524
      pI16A2->uByte6 = ub(d.partyX);                                //T524
      pI16A2->uByte7 = ub(d.partyY);                                //T524
    };                                                              //T524
    D5W = (I16)((D5W + 1) & 3); // Next direction to try.           //T524
  } while (D4W != D5W);                                             //T524
                                                                    //T524                                                                    //T524
  Process_Invincible_And_Finish(                                    //T524
                           D5,                 //modified           //T524
                           DB4A3,              //modified           //T524
                           PreferredDirection, //modified           //T524
                           pI16A2,             //modified           //T524
                           timer_70,           //modified           //T524
                           i_60,               //modified           //T524
                           w_54,               //modified           //T524
                           w_52,               //modified           //T524
                           bool_36,            //modified           //T524
                           w_32,               //modified           //T524
                           w_30,               //modified           //T524
                           mapX,                //const             //T524
                           mapY,                //const             //T524
                           timeFunc,            //const             //T524
                           monster,             //const             //T524
                           timeUntilNextUpdate, //const             //T524
                           mtDescLocal,         //const             //T524
                           invincible,          //const             //T524
                           w_50,                //const             //T524
                           w_48,                //const             //T524
                           fearFactorIs6,       //const             //T524
                           w_40,                //const             //T524
                           w_34                 //const             //T524
    );                                                              //T524
  return;                                                           //T524
}                                                                   //T524


//*********************************************************         //D4D0
//                                                                  //D4D0
//*********************************************************         //D4D0
void D4D0Finish(                                                    //D4D0
                   i32&           PreferredDirection,               //D4D0
                   DB4           *DB4A3,                            //D4D0
                   TIMER&         timer_70,                         //D4D0
                   ITEM16        *pI16A2,                           //D4D0
                   i32            i_60,                             //D4D0
                   i16&           w_54,               //modified    //D4D0
                   i16&           w_52,                             //D4D0
                   i16&           w_42,                             //D4D0
                   bool&          bool_36,                          //D4D0
                   i16&           w_32,                             //D4D0
                   i16&           w_30,                             //D4D0
             const i32&           mapX,                             //D4D0
             const i32&           mapY,                             //D4D0
             const TIMERTYPE&     timeFunc,                         //D4D0
             const RN             monster,                          //D4D0
             const bool&          invincible,                       //D4D0
             const i16            timeUntilNextUpdate,              //D4D0
             const MONSTERDESC&   mtDescLocal,                      //D4D0
             const i16&           w_50,                             //D4D0
             const i16&           w_48,                             //D4D0
             const bool&          fearFactorIs6,                    //D4D0
             const i16&           w_40,                             //D4D0
             const i16&           w_34                              //D4D0
                )                                                   //D4D0
{                                                                   //D4D0
  TIMERTRACE(0xd4d0);                                               //D4D0
  w_52 = sw((w_52 + 1)/2);                                          //D4D0
  pI16A2->uByte6 = ub(d.partyX);                                    //D4D0
  w_30 = d.partyX;                                                  //D4D0
  pI16A2->uByte7 = ub(d.partyY);                                    //D4D0
  w_32 = d.partyY;                                                  //D4D0
  w_42 = 1;                                                         //D4D0
                                                                    //D4D0
//tag00d546:                                                        //D4D0
  TIMERTRACE(0xd546);                                               //D4D0
  PreferredDirection = GetPrimaryAndSecondaryDirection(             //D4D0
                                          mapX, mapY, w_30, w_32);  //D4D0
  // Direction to approach party.                                   //D4D0
//tag00d55c:                                                        //D4D0
  Try_Preferred_Direction_Then_Others(                              //D4D0
                      PreferredDirection,//modified                 //D4D0
                      pI16A2,            //modified                 //D4D0
                      DB4A3,             //modified                 //D4D0
                      timer_70,          //modified                 //D4D0
                      i_60,              //modified                 //D4D0
                      w_54,              //modified                 //D4D0
                      w_52,              //modified                 //D4D0
                      bool_36,           //modified                 //D4D0
                      w_32,              //modified                 //D4D0
                      w_30,              //modified                 //D4D0
                      mtDescLocal,         //const                  //D4D0
                      mapX,                //const                  //D4D0
                      mapY,                //const                  //D4D0
                      invincible,          //const                  //D4D0
                      timeUntilNextUpdate, //const                  //D4D0
                      monster,             //const                  //D4D0
                      timeFunc,            //const                  //D4D0
                      w_50,                //const                  //D4D0
                      w_48,                //const                  //D4D0
                      fearFactorIs6,       //const                  //D4D0
                      w_42,                //const                  //D4D0
                      w_40,                //const                  //D4D0
                      w_34                 //const                  //D4D0
                );                                                  //D4D0
}                                                                   //D4D0

//*********************************************************         //TU67
//                                                                  //TU67
//*********************************************************         //TU67
void TryUByte67(                                                    //TU67
                dReg&          D5,                                  //TU67
                i32&           PreferredDirection,                  //TU67
                ITEM16        *pI16A2,                              //TU67
                DB4           *DB4A3,                               //TU67
                TIMER&         timer_70,                            //TU67
                i32&           i_60,                                //TU67
                i16&           w_54,                                //TU67
                i16&           w_52,                                //TU67
                i16&           w_42,                                //TU67
                bool&          bool_36,                             //TU67
                i16&           w_32,                                //TU67
                i16&           w_30,                                //TU67
          const i32&           mapX,                                //TU67
          const i32&           mapY,                                //TU67
          const i16            timeUntilNextUpdate,                 //TU67
          const TIMERTYPE&     timeFunc,                            //TU67
          const RN             monster,                             //TU67
          const bool&          invincible,                          //TU67
          const MONSTERDESC&   mtDescLocal,                         //TU67
          const i16&           w_50,                                //TU67
          const i16&           w_48,                                //TU67
          const bool&          fearFactorIs6,                       //TU67
          const i16&           w_40,                                //TU67
          const i16&           w_34                                 //TU67
                )                                                   //TU67
{                                                                   //TU67
  dReg D3;                                                          //TU67
  TIMERTRACE(0xd500);                                               //TU67
  w_30 = pI16A2->uByte6;                                            //TU67
  w_32 = pI16A2->uByte7;                                            //TU67
  if (mapX == w_30)                                                 //TU67
  {                                                                 //TU67
    if (mapY == w_32)                                               //TU67
    {                                                               //TU67
      TIMERTRACE(0xd528);                                           //TU67
      bool_36 = false;                                              //TU67
      D3W = 0;                                                      //TU67
      //30OCT02SETWBITS0_3(DB4A3->word14,D3W);                      //TU67
      DB4A3->fear(StateOfFear0);                                    //TU67
      Turn_Monsters_As_Group(
                      D5,
                      pI16A2,
                      w_54,  //const
                      w_50,  //const//number of monsters
                      w_48,  //const//Must turn as group flag
                      bool_36//const
                      );
      if (timeFunc < -1)                                            //TU67
      {                                                             //TU67
        TIMERTRACE(0xd45c);                                         //TU67
        if (bool_36 == false)                                       //TU67
        {                                                           //TU67
          return;                                                   //TU67
        };                                                          //TU67
        Delete_Timers_Maybe_Set_Fear(                               //TU67
                                     DB4A3,                         //TU67
                                     pI16A2,                        //TU67
                                     mapX,                          //TU67
                                     mapY,                          //TU67
                                     fearFactorIs6                  //TU67
                                     );                             //TU67
      };                                                            //TU67
      Increment_Time_By_W52_Plus_Random(timer_70, w_52);            //TU67
      Start37Timer(                                                 //TU67
            timer_70,                                               //TU67
            pI16A2,                                                 //TU67
            i_60,                                                   //TU67
            timeUntilNextUpdate, //const                            //TU67
            w_40                 //const                            //TU67
            );                                                      //TU67
      return;                                                       //TU67
    };                                                              //TU67
  };                                                                //TU67
  w_42 = 1;                                                         //TU67
                                                                    //TU67
//tag00d546:                                                        //TU67
  TIMERTRACE(0xd546);                                               //TU67
  PreferredDirection = GetPrimaryAndSecondaryDirection(             //TU67
                                        mapX, mapY, w_30, w_32);    //TU67
  // Direction to approach party.                                   //TU67
//tag00d55c:                                                        //TU67
  Try_Preferred_Direction_Then_Others(                              //TU67
                      PreferredDirection,//modified                 //TU67
                      pI16A2,            //modified                 //TU67
                      DB4A3,             //modified                 //TU67
                      timer_70,          //modified                 //TU67
                      i_60,              //modified                 //TU67
                      w_54,              //modified                 //TU67
                      w_52,              //modified                 //TU67
                      bool_36,           //modified                 //TU67
                      w_32,              //modified                 //TU67
                      w_30,              //modified                 //TU67
                      mtDescLocal,         //const                  //TU67
                      mapX,                //const                  //TU67
                      mapY,                //const                  //TU67
                      invincible,          //const                  //TU67
                      timeUntilNextUpdate, //const                  //TU67
                      monster,             //const                  //TU67
                      timeFunc,            //const                  //TU67
                      w_50,                //const                  //TU67
                      w_48,                //const                  //TU67
                      fearFactorIs6,       //const                  //TU67
                      w_42,                //const                  //TU67
                      w_40,                //const                  //TU67
                      w_34                 //const                  //TU67
                      );                                            //TU67
}                                                                   //TU67


//*********************************************************         //IC
//                                                                  //IC
//*********************************************************         //IC
bool InitialChecks(                                                 //IC
                TIMER&         timer_70,                            //IC
                i16&           w_54,                                //IC
                i16&           w_52,                                //IC
                i16&           w_34,                                //IC
                i16&           w_32,                                //IC
                i16&           w_30,                                //IC
          const RN             monster,                             //IC
          const i16            timeUntilNextUpdate,                 //IC
          const TIMERTYPE&     timeFunc,                            //IC
          const i32            mapX,                                //IC
          const i32            mapY                                 //IC
                   )                                                //IC
{                                                                   //IC
  dReg D0, D3, D5;                                                  //IC
  DB4 *DB4A3;                                                       //IC
  bool invincible;                                                  //IC
  ITEM16      staticItem16;                                         //IC
  ITEM16      *pI16A2;                                              //IC
  MONSTERTYPE mtD0;                                                 //IC
  MONSTERDESC *pmtDesc;                                             //IC
  MONSTERDESC mtDescLocal;                                          //IC
  if (d.LoadedLevel != d.partyLevel)                                //IC
  {                                                                 //IC
    TIMERTRACE(0xcbe0);                                             //IC
    D5L = timeFunc;                                                 //IC
    if (timeFunc != TT_37)                                          //IC
    {                                                               //IC
      if (timeFunc != TT_32)                                        //IC
      {                                                             //IC
        if (timeFunc != TT_MONSTER_B0)                                      //IC
        {                                                           //IC
          if (timeFunc != TT_MONSTER_A0)                                    //IC
          {                                                         //IC
            if (AITraceActive)                                      //IC
            {                                                       //IC
              fprintf(GETFILE(TraceFile),                           //IC
                  "Skip monster AI because timeFunc "               //IC
                  "not 32, 33, 37, or 38\n");                       //IC
            };                                                      //IC
            return true;                                            //IC
          };                                                        //IC
        };                                                          //IC
      };                                                            //IC
    };                                                              //IC
  };                                                                //IC
  TIMERTRACE(0xcc02);                                               //IC
  //monster = FindFirstMonster(mapX, mapY);                         //IC
        //                                                          //IC
		// The following three words can be patched to put              //IC
		// monster at d.Obj13020 for TAG00c442.  See the                //IC
		// comments at TAG00c442.                                       //IC
		// As follows:                                                  //IC
		// 	00cc14  67e8	     beq     <cbfe>  // return via            //IC
    //                                     //nearby long-jump       //IC
		// 	00cc16  3940 cd24  move.w  D0,-13020(A4)                    //IC
		//                                                              //IC
  if (monster == RNeof)                                             //IC
  {                                                                 //IC
    return true;                                                    //IC
  };                                                                //IC
  d.LastMonsterMoved = monster;                                     //IC
  DB4A3 = GetRecordAddressDB4(monster);                             //IC
  //ASSERT(DB4A3->uByte5 != 0xff);                                  //IC
  TIMERTRACE(0xcc26);                                               //IC
  TIMERTRACE(DB4A3->monsterType());                                 //IC
  mtD0 = DB4A3->monsterType();                                      //IC
                                                                    //IC
  pmtDesc = &d.MonsterDescriptor[mtD0];                             //IC
  //A0 = (pnt)&Item26_26;                                           //IC
  memmove((pnt)&mtDescLocal, (pnt)pmtDesc, 26);                     //IC
  //                                                                //IC
  // The following three words can be patched to ensure             //IC
  // that w_34 is initialized.  Under rare circumstances,           //IC
  // w_34 does not get initialized.  This only causes               //IC
  // slightly erratic behaviour of the monster, but it makes        //IC
  // it nearly impossible to exactly match the PC code to           //IC
  // the Atari code.  So I have patched the Atari code              //IC
  // to set w_34 to a (relatively) large number.                    //IC
  // In general, the uninitialized value is part of an              //IC
  // address and is a large, positive number.  As follows:          //IC
  //                                                                //IC
  //    00cc4c  7618         moveq.l #24,D3     patch was 263c      //IC
  //    00cc4e  3d43 ffde    move.w  D3,-34(A6) patch was 0000 0018 //IC
  //                                                                //IC
  w_34 = 24;                                                        //IC
  timer_70.timerTime = d.Time | (d.LoadedLevel<<24);                //IC
  D3W = mtDescLocal.timePerMove();                                  //IC
  timer_70.timerUByte5 = ub(255 - D3W);                             //IC
  timer_70.timerUByte6 = ub(mapX);                                  //IC
  timer_70.timerUByte7 = ub(mapY);                                  //IC
  timer_70.timerUByte8 = 0;// This was also patched into the        //IC
                      // Atari binary code.  Sometimes a            //IC
                      // timer entry was created with garbage       //IC
                      // in uByte8.  It only caused an undefined    //IC
                      // delay but made it impossible to exactly    //IC
                      // match my code against the Atari code.      //IC
                      // Patch:  Paul Stevens                       //IC
                      //  cc6a  1d47 ffc0  move.b D7,-64(A6)        //IC
                      //                            patch was 3007  //IC
                      //  cc6e  1d46 ffc1  move.b D6,-63(A6)        //IC
                      //                            patch was ffc0  //IC
                      //  cc72  422e ffc2  clr.b  -62(A6)           //IC
                      //                            patch was ffc1  //IC
  if (d.LoadedLevel != d.partyLevel)                                //IC
  {                                                                 //IC
    TIMERTRACE(0xcc88);                                             //IC
    D5W = STRandom0_3();                                            //IC
    TIMERTRACE(0xcc94);                                             //IC
    D0W = PossibleMove(&mtDescLocal, mapX, mapY, D5W, 0);           //IC
    if (AITraceActive)                                              //IC
    {                                                               //IC
      fprintf(GETFILE(TraceFile),                                   //IC
        "      MAI Not on party level. PossibleMove(Random()=%s) "  //IC
        "returned %s.\n",d.DirectionNames[D5W], D0W?"true":"false");//IC
    };                                                              //IC
    if (D0W != 0)                                                   //IC
    {                                                               //IC
      TIMERTRACE(0xcca0);                                           //IC
      w_30 = sw(mapX);                                              //IC
      w_32 = sw(mapY);                                              //IC
      w_30 = sw(w_30 + d.DeltaX[D5W]);                              //IC
      w_32 = sw(w_32 + d.DeltaY[D5W]);                              //IC
      TIMERTRACE(0xccce);                                           //IC
      TIMERTRACE(monster.ConvertToInteger());                       //IC
      D0W = MoveObject(monster, mapX, mapY, w_30, w_32);            //IC
      if (AITraceActive)                                            //IC
      {                                                             //IC
        fprintf(GETFILE(TraceFile),                                 //IC
          "      MAI MoveObject to (%02d,%02d) returned %d\n",      //IC
          w_30,w_32,D0W);                                           //IC
      };                                                            //IC
      ASSERT(D0W != 0xccc);                                         //IC
      if (D0W != 0)                                                 //IC
      {                                                             //IC
        if (AITraceActive)                                          //IC
        {                                                           //IC
          fprintf(GETFILE(TraceFile),                               //IC
            "      MAI Skip monster AI because "                    //IC
            "MoveObject non-zero\n");                               //IC
        };                                                          //IC
        return true;                                                //IC
      };                                                            //IC
      timer_70.timerUByte6 = ub(d.NewX);                            //IC
      timer_70.timerUByte7 = ub(d.NewY);                            //IC
    }                                                               //IC
    else                                                            //IC
    {//IC                                                           //IC
      if (AITraceActive)                                            //IC
      {                                                             //IC
        fprintf(GETFILE(TraceFile),                                 //IC
          "      MAI  No attempt to move monster. "                 //IC                  
          "Que 37 timer\n");                                        //IC
      };                                                            //IC
    };                                                              //IC
//  tag00cd04:                                                      //IC
    TIMERTRACE(0xcd04);                                             //IC
    timer_70.Function(TT_37);                                       //IC
    D0W = sw(abs(d.LoadedLevel-d.partyLevel));                      //IC
    D5W = sw(Larger(D0W << 4, 2*(UI8)(mtDescLocal.timePerMove()))); //IC
    if (AITraceActive)                                              //IC
    {                                                               //IC
      fprintf(GETFILE(TraceFile),                                   //IC
        "      MAI Setting timer 37.  Time equals:\n");             //IC
      fprintf(GETFILE(TraceFile),                                   //IC
        "      MAI   16 * difference in levels = %d\n", 16*D0W);    //IC
      fprintf(GETFILE(TraceFile),                                   //IC
        "      MAI   2*MonsterType->timePerMove = %d\n",            //IC
               2*mtDescLocal.timePerMove());                        //IC
      fprintf(GETFILE(TraceFile),                                   //IC
        "      MAI   The larger number.....equals %d\n", D5W);      //IC
    };                                                              //IC
  //tag00cd30:                                                      //IC
    TIMERTRACE(0xcd30);                                             //IC
    timer_70.timerTime += D5W;                                      //IC
    SetTimer(&timer_70);                                            //IC
    return true;                                                    //IC
  };                                                                //IC
//tag00cd46:                                                        //IC
  TIMERTRACE(0xcd46);                                               //IC
  invincible = mtDescLocal.invincible(); //Impervious?              //IC
  if (invincible)                                                   //IC
  {                                                                 //IC
    if (d.Word11694 != 0) //Has the game been won?                  //IC
    {                                                               //IC
      return true;                                                  //IC
    };                                                              //IC
    d.Word13036 = 0;                                                //IC
    d.Byte13034[0] = 0;                                             //IC
    d.Byte13034[1] = 0;                                             //IC
    d.Byte13034[2] = 0;                                             //IC
    d.Byte13034[3] = 0;                                             //IC
  };                                                                //IC
  ASSERT(DB4A3->groupIndex() < d.MaxITEM16);                        //IC
  pI16A2 = &d.Item16[DB4A3->groupIndex()];                          //IC
  if (DB4A3->groupIndex() >= d.MaxITEM16)                           //IC
    pI16A2 = &staticItem16; // Just so we won't clobber something.  //IC
  D3W = pI16A2->uByte4;                                             //IC
  w_54 = sw((d.Time&255) - D3W );                                   //IC
  if (w_54 < 0)                                                     //IC
  {                                                                 //IC
    w_54 += 256;                                                    //IC
  };                                                                //IC
  w_52 = (UI8)(mtDescLocal.timePerMove());                          //IC
  if (w_52 == 255)                                                  //IC
  {                                                                 //IC
    w_52 = 100;                                                     //IC
  };                                                                //IC
  if ( (d.uByte13271 != 0) && (!invincible) )                       //IC
  {                                                                 //IC
    TIMERTRACE(0xcdc0);                                             //IC
    if (timeFunc < TT_EMPTY)                                        //IC
    {                                                               //IC
      return true;                                                  //IC
    };                                                              //IC
    timer_70.Function(timeFunc);                                    //IC
    timer_70.timerUByte8 = ub(timeUntilNextUpdate);                 //IC
    D5W = 4;                                                        //IC
    TIMERTRACE(0xcd30);                                             //IC
    timer_70.timerTime += D5W;                                      //IC
    SetTimer(&timer_70);                                            //IC
    return true;                                                    //IC
  };                                                                //IC
  TIMERTRACE(0xcde2);                                               //IC
  if (timeFunc < TT_EMPTY)                                          //IC
  {                                                                 //IC
    TIMERTRACE(0xcde8);                                             //IC
    switch (timeFunc)                                               //IC
    {                                                               //IC
    case TT_M3:           timer_70.Function(TT_29);                 //IC
                          break;                                    //IC
    case TT_M2:           timer_70.Function(TT_30);                 //IC
                          break;                                    //IC
    case TT_M1:           timer_70.Function(TT_31);                 //IC
                          break;                                    //IC
    default: SystemError((UI16)0xcdf0);                             //IC
    };                                                              //IC
    //timer_70.function = ub(timeFunc + 32);                        //IC
//                                                                  //IC
    if (   (timeFunc == TT_M1)                                      //IC
        || ((D5W = sw((w_52+2)/4 - w_54)) < 1) )                    //IC
    {                                                               //IC
      D5W = 1;                                                      //IC
    };                                                              //IC
    TIMERTRACE(0xcd30);                                             //IC
    timer_70.timerTime += D5W;                                      //IC
    SetTimer(&timer_70);                                            //IC
    return true;                                                    //IC
  };                                                                //IC
  return false;                                                     //IC
}                                                                   //IC


//*********************************************************
//
//*********************************************************
//   TAG00cbc6
void ProcessTimers29to41(const i32 mapX,
                         const i32 mapY,
                         TIMERTYPE timeFunc,
                         i16 timeUntilNextUpdate)
{//(void)
  ITEM16      staticItem16;
  dReg        D0, D1, D3, D4, D5;
  MONSTERTYPE mtD0;
  bool        boolD0;
  DB4         *DB4A3;
  ITEM16      *pI16A2;
  MONSTERDESC *pmtDesc;
  i16         w_110;
  i16         w_100;
  i16         w_90;
  //i16         w_80;
  TIMER       timer_70;
  i32         i_60;
  bool        invincible; //w_56
  i16         w_54;
  i16         w_52;
  i16         w_50;
  i16         w_48;
  bool        fearFactorIs6 = false;
  i16         w_44;
  i16         w_42;
  i16         w_40;
  i32         PreferredDirection;
  bool        bool_36;
  i16         w_34; // Blocked() = 0 or distance.
  i16         w_32;
  i16         w_30;
  const RN    monster = FindFirstMonster(mapX, mapY); //28
  MONSTERDESC mtDescLocal;
  i16         temp;
  STATE_OF_FEAR fearFactor;
  TIMERTYPE   tt;
  //i32         monIdx;
  //i32 monsterDirection;
  // A timer event with function code 37 is put on
  // the queue when a character dies from lack of
  // food in the prison.  We had to fake byte 5 of
  // the entry.  We put a 255 into it.
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  //D3L = 0xccccc; // Uninitialized value
  //D7W = mapX;
  //D6W = mapY;
  TIMERTRACE(-1);
  TIMERTRACE(d.RandomNumber);
  if (AITraceActive)
  {
    fprintf(GETFILE(TraceFile),"MonsterAI %02d(%02d,%02d)@%d Perform Initial Checks-timeFunc=%d, timeUntilNextUpdate=%d\n",d.LoadedLevel,mapX,mapY,d.Time,timeFunc,timeUntilNextUpdate);
  };
  if (InitialChecks(
                timer_70,
                w_54,
                w_52,
                w_34,
                w_32,
                w_30,
                monster,            //const
                timeUntilNextUpdate,//const
                timeFunc,           //const
                mapX,               //const
                mapY                //const
                )) return;
  DB4A3 = GetRecordAddressDB4(monster);
  mtD0 = DB4A3->monsterType();
  pmtDesc = &d.MonsterDescriptor[mtD0];
  memmove((pnt)&mtDescLocal, (pnt)pmtDesc, 26);
  pI16A2 = &d.Item16[DB4A3->groupIndex()];
  if (DB4A3->groupIndex() >= d.MaxITEM16)
    pI16A2 = &staticItem16; // Just so we won't clobber something.
  invincible = mtDescLocal.invincible(); //Impervious?
  TIMERTRACE(0xce18);
  fearFactor = DB4A3->fear();
  w_50 = (I16)(DB4A3->numMonM1());//Number of monsters-1
  w_48 = mtDescLocal.horizontalSize(); //Size of monster 1=two squares
  D5W = sw(mapX - d.partyX);
  w_30 = sw(abs(D5W));
  D5W = sw(mapY - d.partyY);
  w_32 = sw(abs(D5W));
  d.Word13016 = sw(mapX);
  d.Word13018 = sw(mapY);
  //d.Obj13020 = monster;
  d.Byte13030[0] = d.Byte13030[1] =d.Byte13030[2] =d.Byte13030[3] =0;
  d.OrthogonalDistance2Party = DistanceBetweenPoints(mapX, mapY, d.partyX, d.partyY);
  d.PrimaryDirectionToParty = (I16)GetPrimaryAndSecondaryDirection(mapX, mapY, d.partyX, d.partyY);
  d.SecondaryDirectionToParty = (I16)d.SecondaryDirection;
  i_60 = 0;
  w_40 = 1;
  if (AITraceActive)
  {
    fprintf(GETFILE(TraceFile),"      MAI Passed. Invincible=%d fearFactor=%d w_54=%d w_50=%d w_48=%d\n",invincible,fearFactor,w_54,w_50,w_48);
  };
  ASSERT(timeFunc >= TT_29);
  switch (timeFunc)
  {
    //timeFunc = sw(timeFunc-32);
  case TT_31:
      timeFunc = TT_M1;
      TIMERTRACE(0xcedc);
      if ( (fearFactor != StateOfFear6) && (fearFactor != StateOfFear5) )
      {
        if (AITraceActive)
        {
          fprintf(GETFILE(TraceFile),"      MAI timeFunc 31.  FearFactor not 5 or 6.\n");
        };
        DeleteMonsterMovementTimers(mapX, mapY);
        MaybeDelTimers_Fear6_TurnIndividuals(
                    pI16A2,
                    DB4A3,
                    timer_70,
                    timeUntilNextUpdate,//const
                    timeFunc,           //const
                    mapX,               //const
                    mapY,               //const
                    mtDescLocal,        //const
                    w_50,               //const
                    w_48,               //const
                    w_40                //const
                    );
        return;
      };
      if (AITraceActive)
      {
        fprintf(GETFILE(TraceFile),"      MAI timeFunc 31.  FearFactor is 5 or 6.\n");
      };
      TIMERTRACE(0xcef6);
      pI16A2->uByte6 = ub(d.partyX);
      pI16A2->uByte7 = ub(d.partyY);
      return;

  case TT_30:
      TIMERTRACE(0xcf14);
      timeFunc = TT_M2;
      if ( (fearFactor == StateOfFear6) || (fearFactor == StateOfFear5) )
      {
        if (AITraceActive)
        {
          fprintf(GETFILE(TraceFile),"      MAI timeFunc 30.  FearFactor is 5 or 6.\n");
        };
        return;
      };
      D5L = ((fearFactor==StateOfFear2)||(fearFactor==StateOfFear3))?1:0;
      if ( (D5W != 0) || (STRandom0_3() != 0) )
      {
        TIMERTRACE(0xcf50);
        D0W = Blocked(DB4A3, -1, mapX, mapY);
        if (AITraceActive)
        {
          fprintf(GETFILE(TraceFile),"      MAI timeFunc 31. FearFactor 2 or 3 or random. Block=%d\n", D0W);
        };
        if (D0W == 0)
        {
          TIMERTRACE(0xcd5c);
          bool_36 = false;
          fearFactorIs6 = false;
          Turn_Monsters_As_Group(
                          D5,
                          pI16A2,
                          w_54,  //const
                          w_50,  //const//number of monsters
                          w_48,  //const//Must turn as group flag
                          bool_36//const
                          );
          if (timeFunc < -1)
          {
            TIMERTRACE(0xd45c);
            if (bool_36 == false)
            {
              return;
            };
            Delete_Timers_Maybe_Set_Fear(
                                         DB4A3,
                                         pI16A2,
                                         mapX,
                                         mapY,
                                         fearFactorIs6
                                         );
          };
          Increment_Time_By_W52_Plus_Random(timer_70, w_52);
          Start37Timer(
                 timer_70,
                 pI16A2,
                 i_60,
                 timeUntilNextUpdate, //const
                 w_40                 //const
                 );
          return;
        };
        if (D5W != 0)
        {
          return;
        };
        if (STRandom0_3() != 0)
        {
          return;
        };
      };
      fearFactorIs6 = fearFactor == StateOfFear6;
      bool_36 = false;
      TIMERTRACE(0xd27e);
      D5W = STRandom0_3();
      D4W = D5W;
      w_44 = 0;
      Try_Directions_D5_To_D4(
                   pI16A2,
                   D4,
                   D5,  
                   PreferredDirection,
                   //monIdx,
                   //monsterDirection,
                   DB4A3,
                   //w_80,
                   timer_70,
                   i_60,
                   w_54,
                   w_52,
                   w_44,
                   bool_36,
                   w_32,
                   w_30,
                   timeFunc,
                   invincible,
                   timeUntilNextUpdate,
                   monster,
                   mtDescLocal,
                   mapX,
                   mapY,
                   w_50,
                   w_48,
                   fearFactorIs6,
                   w_40,
                   w_34
                   );
      return;
  case TT_29:
      TIMERTRACE(0xcf86);
      if (AITraceActive)
      {
        fprintf(GETFILE(TraceFile),"      MAI timeFunc 29.\n");
      };
      timeFunc = TT_M3;
      fearFactorIs6 = fearFactor == StateOfFear6;
      bool_36 = false;
      TIMERTRACE(0xd27e);
      D5W = STRandom0_3();
      D4W = D5W;
      w_44 = 0;
      Try_Directions_D5_To_D4(
                  pI16A2,
                  D4,
                  D5,
                  PreferredDirection,
                  //monIdx,
                  //monsterDirection,
                  DB4A3,
                  //w_80,
                  timer_70,
                  i_60,
                  w_54,
                  w_52,
                  w_44,
                  bool_36,
                  w_32,
                  w_30,
                  timeFunc,
                  invincible,
                  timeUntilNextUpdate,
                  monster,
                  mtDescLocal,
                  mapX,
                  mapY,
                  w_50,
                  w_48,
                  fearFactorIs6,
                  w_40,
                  w_34
                  );
      return;
  }; //switch
  if (timeFunc <= TT_MONSTER_A3)
  {
    TIMERTRACE(0xcfa6);
    switch(timeFunc)
    {
    case TT_32:         tt = TT_37;         break;
    case TT_MONSTER_A0: tt = TT_MONSTER_B0; break;
    case TT_MONSTER_A1: tt = TT_MONSTER_B1; break;
    case TT_MONSTER_A2: tt = TT_MONSTER_B2; break;
    case TT_MONSTER_A3: tt = TT_MONSTER_B3; break;
    default: die(0xd7d6,"Illegal Monster AI Timer");
             tt = TT_MONSTER_B0;
             break;
    };
    timer_70.Function(tt);
    if (AITraceActive)
    {
      fprintf(GETFILE(TraceFile),"      MAI timeFunc<37. Set New timerFunction to %d\n",timer_70.Function());
    };
    D0W = Blocked(DB4A3, -1, mapX, mapY);
    if (AITraceActive)
    {
      fprintf(GETFILE(TraceFile),"      MAI timeFunc<37.  Blocked=%d\n",D0W);
    };
    if (D0W != 0)
    {
      TIMERTRACE(0xcfc6);
      if ( (fearFactor != 6) && (fearFactor != 5) )
      {
        TIMERTRACE(0xcfd2);
        D0W = sw(abs(d.partyX - mapX));
        D1W = sw(abs(d.partyY - mapY));
        if (D0W + D1W <= 1) 
        {
          MaybeDelTimers_Fear6_TurnIndividuals(
                      pI16A2,
                      DB4A3,
                      timer_70,
                      timeUntilNextUpdate, //const
                      timeFunc,            //const
                      mapX,                //const
                      mapY,                //const
                      mtDescLocal,         //const
                      w_50,                //const
                      w_48,                //const
                      w_40                 //const
                      );
          return;
        };
        if ( ((fearFactor==0)||(fearFactor==3)) && (fearFactor!=7) ) 
        {
          TIMERTRACE(0xd21a);
          D3W = 7;
          //30OCT02SETWBITS0_3(DB4A3->word14, D3W);
          DB4A3->fear(StateOfFear7);
          pI16A2->uByte6 = ub(d.partyX);
          pI16A2->uByte7 = ub(d.partyY);
          timer_70.timerTime++;
          Start37Timer(
                 timer_70,
                 pI16A2,
                 i_60,
                 timeUntilNextUpdate, //const
                 w_40                 //const
                 );
          return;
        };
      };
      TIMERTRACE(0xd018);
      pI16A2->uByte6 = ub(d.partyX);
      pI16A2->uByte7 = ub(d.partyY);
    };
    if (fearFactor == 6)
    {
      TIMERTRACE(0xd036);
      if (AITraceActive)
      {
        fprintf(GETFILE(TraceFile),"      MAI fearFactor==6\n");
      };
      D5W = sw(timeFunc-33);
      //D0W = (I16)(pI16A2->ITEM16_uByte12[D5W] & 0x80);
      D0W = pI16A2->singleMonsterStatus[D5W].TestAttacking();
      i_60 = NextMonsterUpdateTime(pI16A2, D5W, D0W);
      Set_Monster_Timer(
                       timer_70,
                       i_60,
                       timeUntilNextUpdate, //const
                       w_40                 //const
                       );
      return;
    };
    TIMERTRACE(0xd0580);
    if ( (w_30 > 3) || (w_32 > 3) )
    {
      TIMERTRACE(0xd068);
      i_60 = d.Time + BITS4_7(mtDescLocal.word20);
      if (AITraceActive)
      {
        fprintf(GETFILE(TraceFile),
                  "      MAI fearFactor != 6.  Distance to party > 3.  mt->word20 = %d\n",
                  mtDescLocal.word20);
      };
      Set_Monster_Timer(
                       timer_70,
                       i_60,
                       timeUntilNextUpdate, //const
                       w_40                 //const
                       );
      return;
    };
    EnsureI60NonZero(i_60, pI16A2);
    Set_Monster_Timer(
                     timer_70,
                     i_60,
                     timeUntilNextUpdate, //const
                     w_40                 //const
                     );
    return;
  };

  TIMERTRACE(0xd08a);
  w_40 = 0;
  if (AITraceActive)
  {
    fprintf(GETFILE(TraceFile),"      MAI timeFunc>=37.\n");
  };
  if (timeUntilNextUpdate != 0)
  {
    TIMERTRACE(0xd094);
    i_60 = d.Time;
  };
  if (timeFunc != TT_37)
  {
  //tag00d870:
    TIMERTRACE(0xd870);
    if (fearFactor == StateOfFear5)
    {
      TIMERTRACE(0xd876);
      if (w_50 != 0)
      {
        TIMERTRACE(0xd87c);
        ClearAllUByte12_80_DeleteMovementTimers(pI16A2, mapX, mapY);
      }
      Try_To_Move(
              D5,
              DB4A3,
              pI16A2,
              PreferredDirection,
              timer_70,            
              i_60,
              w_54,
              w_52,
              //w_42,
              bool_36,
              w_34,
              w_32,
              w_30,
              timeFunc,           //const
              monster,            //const
              timeUntilNextUpdate,//const
              mtDescLocal,        //const
              invincible,         //const
              mapX,               //const
              mapY,               //const
              w_50,               //const
              w_48,               //const
              fearFactorIs6,    //const
              w_40                //const
            );
      return;
    };
    D4W = sw(timeFunc - 38);
    //D0W = pI16A2->ITEM16_uByte12[D4W];
    if (pI16A2->singleMonsterStatus[D4W].TestAttacking())
    {
      TIMERTRACE(0xd8a6);
      i_60 = NextMonsterUpdateTime(pI16A2, D4W, 0);
      w_90 = STRandom0_3();
      D4W = (UI8)(mtDescLocal.uByte7);
      timer_70.timerTime += uw(D4W + w_90 - 1);
      if (D4W > 15)
      {
        TIMERTRACE(0xd8dc);
        D0W = sw((STRandom() & 7) - 2);
        timer_70.timerTime += D0W;//D0 can be negative.
      };
    }
    else
    {
      if (D4W > w_50)
      {
        return;
      };
      PreferredDirection = d.PrimaryDirectionToParty;
      w_34 = Blocked(DB4A3, D4W, mapX, mapY);
      if (w_34 != 0)
      {
        TIMERTRACE(0xd91c);
        pI16A2->uByte6 = ub(d.partyX);
        pI16A2->uByte7 = ub(d.partyY);
      };
  //
  //
      if (   (w_50 == 0)
          && (w_48 != 2)
          && (((D5W=(I16)((i16)STRandom())) & 0xc0) == 0) )
      {
        TIMERTRACE(0xd94c);
        if (pI16A2->positions() != 255)
        {
          if (D5W & 0x38)
          {
            TIMERTRACE(0xd960);
            pI16A2->positions() = 0xff;
          }
          else
          {
            D0W = pI16A2->positions();
            if (D5W & 1)
            {
              TIMERTRACE(0xd97e);
              D1W = 1; // Turn right
            }
            else
            {
              TIMERTRACE(0xd980);
              D1W = -1; // Turn left
            };
            D5W = (I16)((D0W + D1W) & 3);
            // I think there is something wrong with D5 here.
          };
        };
  //tag00d98c:
        TIMERTRACE(0xd98c | (D5W<<16));
        if (   ((D5W & 0x38) == 0)
            && (w_34 != 1)
            && (w_48 == 0) )
        {
          TIMERTRACE(0xd9a2);
          D0W = TAG00e8ce(-1, mapX, mapY, pI16A2->positions());
          if (D0W != 0)
          {
            if (d.Word12958 == 2)
            {
              return;
            };
          };
          pI16A2->positions() = (UI8)(D5W & 3);
        };
      };
  //
      if (   (w_34 != 0)
          && (  (mtDescLocal.word2Bit2())
  //            ||(((pI16A2->facings() >> (2*D4W)) & 3) == PreferredDirection ) ))
              ||((TwoBitNibble(pI16A2->facings(),D4W)) == PreferredDirection ) ))
      {
        TIMERTRACE(0xd9fe);
        D5W = mtDescLocal.word14_12_15();
        if (   (w_34 <= D5W)
            && ((w_30 == 0)||(w_32 == 0))
            && (D5W <= (w_100=(I16)(STRandom(16) + 1))) )
        {
          TIMERTRACE(0xda38);
          if (D5W == 1)
          {
            TIMERTRACE(0xda40);
            //D5W = Item26_26.word2;
  //
  //
  //
  //
            if (  (   !mtDescLocal.word2Bit3()
                  || (STRandom0_3() == 0)
                  || !mtDescLocal.word2Bit4()
                  )
                && (w_48 == 0)
                && (pI16A2->positions() != 255))
            {
              TIMERTRACE(0xda74);
  //            D5W = (I16)((pI16A2->positions() >> (2*D4W)) & 3);
              D5W = (I16)(TwoBitNibble(pI16A2->positions(),D4W));
              if (PreferredDirection != D5W)
              {
                TIMERTRACE(0xda90);
                if (D5W != ((PreferredDirection + 1) & 3))
                {
                  TIMERTRACE(0xdaa2);
  //
                  if ( (w_50 == 0) && (STRandomBool() != 0) )
                  {
                    TIMERTRACE(0xdab0);
  //                  pI16A2->uByte3 = 0xff;
                  }
                  else
                  {
                    if ((PreferredDirection & 1) == (D5W & 1))
                    {
                      TIMERTRACE(0xdacc);
                      D5W--; // Turn left
                    }
                    else
                    {
                      TIMERTRACE(0xdaad0);
                      D5W++; //Turn right
                    };
                    D5W &= 3;
                    D0W = OrdinalOfMonsterAtPosition(DB4A3, D5W);
  
  //
  //
  //
                    if (   (D0W==0)
                        || (  (STRandomBool()!=0)
                            &&((OrdinalOfMonsterAtPosition(DB4A3,D5W=(I16)((D5W+2)&3))))==0) )
                    {
                      TIMERTRACE(0xdb08);
                      D0W = TAG00e8ce(-1, mapX, mapY, pI16A2->positions());
                      if ((D0W!=0) && (d.Word12958==2))
                      {
                        return;
                      };
                      if (d.Word12958 != 1)
                      {
                        TIMERTRACE(0xdb36);
                        D0W = SetMonsterPositionBits(
                                pI16A2->positions(), //old positions byte
                                D4W,           //monster number
                                D5W);          //position
                        pI16A2->positions() = D0UB;
                      };
                    };
                  };
                  D0W = sw(mtDescLocal.timePerMove()/2 + STRandomBool());
                  D0L = Larger(1, D0W);
                  timer_70.timerTime += D0L;
                  timer_70.Function(timeFunc);
                  EnsureI60NonZero(i_60, pI16A2);
                  Set_Monster_Timer(
                                    timer_70,
                                    i_60,
                                    timeUntilNextUpdate, //const
                                    w_40                 //const
                                    );
                  return;
                };
              };
            };
          };
          TIMERTRACE(0xdb7a);
          temp = TAG00c8c0(DB4A3,mapX,mapY,D4W);
          i_60 = NextMonsterUpdateTime(
                            pI16A2,
                            D4W,
                            temp);
          w_110 = STRandomBool();
          D0L = ((mtDescLocal.word20 & 15) + w_110) & 0xffff;
          timer_70.timerTime += D0L;
        }
        else
        {
          D3W = 7;
          //ASSERT(D3L != 0xccccc);
          //30OCT02SETWBITS0_3(DB4A3->word14, D3W) ;
          DB4A3->fear(StateOfFear7);
          if (w_50 != 0)
          {
            TIMERTRACE(0xdbd4);
            ClearAllUByte12_80_DeleteMovementTimers(pI16A2, mapX, mapY);
          };
          D4D0Finish(
                 PreferredDirection,
                 DB4A3,
                 timer_70,
                 pI16A2,
                 i_60,
                 w_54,               //modified
                 w_52,
                 w_42,
                 bool_36,
                 w_32,
                 w_30,
                 mapX,                 //const
                 mapY,                 //const
                 timeFunc,             //const
                 monster,              //const
                 invincible,           //const
                 timeUntilNextUpdate,  //const
                 mtDescLocal,          //const
                 w_50,                 //const
                 w_48,                 //const
                 fearFactorIs6,      //const
                 w_40,                 //const
                 w_34
                 );
          return;
        };
      }
      else
      {
        D0W = Blocked(DB4A3, -1, mapX, mapY);
        if (D0W != 0)
        {
          TIMERTRACE(0xdbfe);
          pI16A2->uByte6 = ub(d.partyX);
          pI16A2->uByte7 = ub(d.partyY);
          boolD0 = (w_50 != 0) & (w_48 == 1);
          TurnMonster(pI16A2,
                      PreferredDirection,
                      D4W,    //monster index
                      boolD0);
          timer_70.timerTime += 2;
          i_60 = timer_70.timerTime & 0xffffff;
        }
        else
        {
          TIMERTRACE(0xdc4a);
          D3W = 7;
          //30OCT02SETWBITS0_3(DB4A3->word14, D3W);
          DB4A3->fear(StateOfFear7);
          if (w_50 != 0)
          {
            ClearAllUByte12_80_DeleteMovementTimers(pI16A2, mapX, mapY);
          };
          TryUByte67(
                   D5,
                   PreferredDirection,
                   pI16A2,
                   DB4A3,
                   timer_70,
                   i_60,
                   w_54,
                   w_52,
                   w_42,
                   bool_36,
                   w_32,
                   w_30,
                   mapX,                //const
                   mapY,                //const  
                   timeUntilNextUpdate, //const
                   timeFunc,            //const
                   monster,             //const
                   invincible,          //const
                   mtDescLocal,         //const
                   w_50,                //const
                   w_48,                //const
                   fearFactorIs6,     //const
                   w_40,                //const
                   w_34                 //const
                   );
          return;
        };
      };
    };
    timer_70.Function(timeFunc);
    Set_Monster_Timer(
                     timer_70,
                     i_60,
                     timeUntilNextUpdate, //const
                     w_40                 //const
                     );
    return;
  };
  TIMERTRACE(0xd0b6);
  if (AITraceActive)
  {
    fprintf(GETFILE(TraceFile),"      MAI timeFunc=37.\n");
  };
  if (   (fearFactor != 0)
      && (fearFactor != 2)
      && (fearFactor != 3) )
  {
//tag00d490:
    TIMERTRACE(0xd490);
    if (AITraceActive)
    {
      fprintf(GETFILE(TraceFile),"      MAI fearFactor not 0, 2, or 3\n");
    };
    if (fearFactor != 7) 
    {
      TIMERTRACE(0xd746);
      if (fearFactor != 5)  
      {
        Increment_Time_By_W52_Plus_Random(timer_70, w_52);
        Start37Timer(
              timer_70,
              pI16A2,
              i_60,
              timeUntilNextUpdate, //const
              w_40                 //const
              );
        return;
      };
      Try_To_Move(
              D5,
              DB4A3,
              pI16A2,
              PreferredDirection,
              timer_70,            
              i_60,
              w_54,
              w_52,
              bool_36,
              w_34,
              w_32,
              w_30,
              timeFunc,           //const
              monster,            //const
              timeUntilNextUpdate,//const
              mtDescLocal,        //const
              invincible,         //const
              mapX,               //const
              mapY,               //const
              w_50,               //const
              w_48,               //const
              fearFactorIs6,      //const
              w_40                //const
            );
      return;
  
    };
    w_34 = Blocked(DB4A3, -1, mapX, mapY);
    if (w_34 != 0)
    {
      TIMERTRACE(0xd4b0);
      if (w_34 <= mtDescLocal.word14_12_15())
      {
        TIMERTRACE(0xd4c0);
        if (    (w_30 == 0)
            || (w_32 == 0) )
        {
          MaybeDelTimers_Fear6_TurnIndividuals(
                      pI16A2,
                      DB4A3,
                      timer_70,
                      timeUntilNextUpdate, //const
                      timeFunc,            //const
                      mapX,                //const
                      mapY,                //const
                      mtDescLocal,         //const
                      w_50,                //const
                      w_48,                //const
                      w_40                 //const
                      );
          return;
        };
      };
  //tag00d4d0:
      D4D0Finish(
                 PreferredDirection,
                 DB4A3,
                 timer_70,
                 pI16A2,
                 i_60,
                 w_54,               //modified
                 w_52,
                 w_42,
                 bool_36,
                 w_32,
                 w_30,
                 mapX,                 //const
                 mapY,                 //const
                 timeFunc,             //const
                 monster,              //const
                 invincible,           //const
                 timeUntilNextUpdate,  //const
                 mtDescLocal,          //const
                 w_50,                 //const
                 w_48,                 //const
                 fearFactorIs6,      //const
                 w_40,                 //const
                 w_34
                 );
      return;
    };
//  tag00d500:
    TryUByte67(
               D5,
               PreferredDirection,
               pI16A2,
               DB4A3,
               timer_70,
               i_60,
               w_54,
               w_52,
               w_42,
               bool_36,
               w_32,
               w_30,
               mapX,                //const
               mapY,                //const  
               timeUntilNextUpdate, //const
               timeFunc,            //const
               monster,             //const
               invincible,          //const
               mtDescLocal,         //const
               w_50,                //const
               w_48,                //const
               fearFactorIs6,     //const
               w_40,                //const
               w_34                 //const
               );
    return;

  };
  w_34 = Blocked(DB4A3, -1, mapX, mapY);
  if (AITraceActive)
  {
    fprintf(GETFILE(TraceFile),"      MAI fearFactor is 0, 2, or 3.  w_34=%d\n",w_34);
  };
  if (w_34 != 0)
  {
    TIMERTRACE(0xd0d0);
    if (w_34 <= mtDescLocal.word14_12_15())
    {
      TIMERTRACE(0xd0e2);
      if ( (w_30 == 0) || (w_32 == 0) )
      {  
        MaybeDelTimers_Fear6_TurnIndividuals(
                    pI16A2,
                    DB4A3,
                    timer_70,
                    timeUntilNextUpdate, //const
                    timeFunc,            //const
                    mapX,                //const
                    mapY,                //const
                    mtDescLocal,         //const
                    w_50,                //const
                    w_48,                //const
                    w_40                 //const
                    );
        return;
      };
    };

    TIMERTRACE(0xd214);
    if (fearFactor != 2)
    {
      TIMERTRACE(0xd21a);
      D3W = 7;
      //30OCT02SETWBITS0_3(DB4A3->word14, D3W);
      DB4A3->fear(StateOfFear7);
      pI16A2->uByte6 = ub(d.partyX);
      pI16A2->uByte7 = ub(d.partyY);
      timer_70.timerTime++;
      Start37Timer(
             timer_70,
             pI16A2,
             i_60,
             timeUntilNextUpdate, //const
             w_40                 //const
             );
      return;
    };  
    Increment_Time_By_W52_Plus_Random(timer_70, w_52);
    Start37Timer(
           timer_70,
           pI16A2,
           i_60,
           timeUntilNextUpdate,  //const
           w_40                  //const
           );
    return;
  };
  TIMERTRACE(0xd24a);
  if (fearFactor != 0)
  {
    Increment_Time_By_W52_Plus_Random(timer_70, w_52);
    Start37Timer(
           timer_70,
           pI16A2,
           i_60,
           timeUntilNextUpdate,  //const
           w_40                  //const
           );
    return;
  };

  TIMERTRACE(0xd250);
  PreferredDirection =
         GetBestMonsterFacingP1(&mtDescLocal, mapX, mapY);
  if (AITraceActive)
  {
    fprintf(GETFILE(TraceFile),"      MAI fearFactor is 0. Preferred Direction=%d\n",PreferredDirection);
  };
  if (PreferredDirection != 0)
  {
    TIMERTRACE(0xd264);
    PreferredDirection -= 1;
    w_42 = 0;
    Try_Preferred_Direction_Then_Others(
                        PreferredDirection,//modified
                        pI16A2,            //modified
                        DB4A3,             //modified
                        timer_70,          //modified
                        i_60,              //modified
                        w_54,              //modified
                        w_52,              //modified
                        bool_36,           //modified
                        w_32,              //modified
                        w_30,              //modified
                        mtDescLocal,         //const
                        mapX,                //const
                        mapY,                //const
                        invincible,          //const
                        timeUntilNextUpdate, //const
                        monster,             //const
                        timeFunc,            //const
                        w_50,                //const
                        w_48,                //const
                        fearFactorIs6,     //const
                        w_42,                //const
                        w_40,                //const
                        w_34                 //const
                  );
    return;
  };
  bool_36 = false;
  if (STRandomBool() == 0) 
  {
    if (AITraceActive)
    {
      fprintf(GETFILE(TraceFile),"      MAI No Preferrred Direction.  RandomBool()=0.\n");
    };
    Process_Invincible_And_Finish(
                           D5,                 //modified
                           DB4A3,              //modified
                           PreferredDirection, //modified
                           pI16A2,             //modified
                           timer_70,           //modified
                           i_60,               //modified
                           w_54,               //modified
                           w_52,               //modified
                           bool_36,            //modified
                           w_32,               //modified
                           w_30,               //modified
                           mapX,                //const
                           mapY,                //const
                           timeFunc,            //const
                           monster,             //const
                           timeUntilNextUpdate, //const
                           mtDescLocal,         //const
                           invincible,          //const
                           w_50,                //const
                           w_48,                //const
                           fearFactorIs6,       //const
                           w_40,                //const
                           w_34                 //const
          );
     return;
  };

//tag00d27e:
  TIMERTRACE(0xd27e);
  if (AITraceActive)
  {
    fprintf(GETFILE(TraceFile),"      MAI No Preferrred Direction.  RandomBool()=1.\n");
  };
  D5W = STRandom0_3();
  D4W = D5W;
  w_44 = 0;

  Try_Directions_D5_To_D4(
               pI16A2,
               D4,
               D5,
               PreferredDirection,
               //monIdx,
               //monsterDirection,
               DB4A3,
               //w_80,
               timer_70,
               i_60,
               w_54,
               w_52,
               w_44,
               bool_36,
               w_32,
               w_30,
               timeFunc,
               invincible,
               timeUntilNextUpdate,
               monster,
               mtDescLocal,
               mapX,
               mapY,
               w_50,
               w_48,
               fearFactorIs6,
               w_40,
               w_34
    );
  return;
//tag00d48c:
//  TIMERTRACE(0xd48c);
//  goto tag00d86c;



}

//*********************************************************
//
//*********************************************************
i16 TAG00e8ce(i16 P1, i32 mapX, i32 mapY, ui16 position)
{//(i16)
  dReg D0, D5;
  RN  objD6;
  i32 saveTimerIndex;
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  //D7W = position;
  D5W = 0;
  d.Word12958 = 0;
  do
  {
    for (objD6 = FindFirstObject(mapX, mapY);
         objD6 != RNeof;
         objD6 = GetDBRecordLink(objD6)  )
    {
      if (objD6.dbType() != dbMISSILE) continue;
      if (objD6.pos() != position) continue;
      saveTimerIndex = GetRecordAddressDB14(objD6)->timerIndex();
      D0W = CheckMissileEncounter(
                P1,    //party or monster
                mapX,
                mapY,
                position,
                objD6);//missile
      if (D0W == 0) continue;
      DeleteTimer(saveTimerIndex); //TAG00e156(objD6);
      D5W++;
      break;

//
    };
  } while ((objD6 != RNeof) && ((P1!=-1)||(d.Word12958!=2)));

//
  return (D5W);
}

//*********************************************************
// Distance as the (orthoganal) crow flies.
//*********************************************************
//  TAG00f4c8
i16 DistanceBetweenPoints(
              i32 X1,
              i32 Y1,
              i32 X2,
              i32 Y2)
{
  return sw(abs(X1-X2) + abs(Y1-Y2));
}
//*********************************************************
//
//*********************************************************
i16 TAG00f6ee(DB4 *pDB4,i16 chIdx)
{//(i16)
  dReg        D0, D1, D3, D4, D5, D6, D7;
  DB4        *DB4A3;
  CHARDESC   *chA2;
  MONSTERDESC mtDesc;
  i16         w_2;
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  DB4A3 = pDB4;
  chA2 = &d.CH16482[chIdx];
  if (chIdx >= d.NumCharacter) return 0;
  if (chA2->HP() == 0) return 0;

  if (d.PartySleeping != 0) WakeUp();
  w_2 = sw(2 * d.pCurLevelDesc->experienceMultiplier());
  memmove(&mtDesc, &d.MonsterDescriptor[DB4A3->monsterType()],26);
  // local copy of monster descriptor
  AdjustSkills(chIdx, 7, mtDesc.word16_8_11());
  if (d.PartySleeping == 0)
  {
    D0W = sw(Quickness(chA2));
    D1W = sw(STRandom(32));
    D3W = mtDesc.uByte8[4];
    D1W = sw(D1W + D3W + w_2 - 16);

    if ( (D0W >= D1W) && (STRandom0_3() != 0) ) return 0;
    // character is slower (or monster is lucky!)
    if (TAG016476(chA2, 60) != 0) return 0;
  };
  D6W = (i16)STRandom();
  if (D6W & 0x70)
  {
    D6W &= 15;
    D5W = mtDesc.word22();
    for (D4W=0; D6W > (D5W&15); D4W++) D5W >>= 4;
//

    D4W = d.uByte590[D4W];
  }
  else
  {
    D4W = (I16)(D6W & 1);
  };
  D3W = mtDesc.uByte8[2];
  D0W = sw(w_2 + STRandom(16) + D3W);
  D1W = sw(DetermineMastery(chIdx, 7));
  D7W = sw(D0W - 2*D1W);
  if (D7W <= 1)
  {
    if (STRandomBool() != 0) return 0;
    D7W = sw(STRandom0_3() + 2);
  };
  D7W /= 2;
  D0W = sw(STRandom(D7W));
  D1W = STRandom0_3();
  D7W = sw(D7W + D0W + D1W);
  D7W = sw(D7W + STRandom(D7W));
  D7W /= 4;
  D7W = sw(D7W + STRandom0_3() + 1);
  if (STRandomBool() != 0)
  {
    D7W = sw(D7W - (STRandom(D7W/2 + 1) - 1));
  };
  D7W = sw(DamageCharacter(chIdx, D7W, D4W, mtDesc.uByte22[2]));
  if (D7W != 0)
  {
    QueueSound(chIdx + 9, d.partyX, d.partyY, 2);
    D6W= mtDesc.uByte8[3];
    if (D6W != 0)
    {
      if (STRandomBool() != 0)
      {
        D6W = TAG016426(chA2, 4, D6W);
        // There was an impossible jump around the following function call.
        TAG017274(chIdx, D6W);
      };
    };
    return (D7W);
  };
  return (0);
}