home *** CD-ROM | disk | FTP | other *** search
/ Assassins - Ultimate CD Games Collection 4 / Assassins 4 (1999)(Weird Science).iso / misc / omega / source / mon.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-02  |  30.2 KB  |  1,165 lines

  1. /* omega copyright (c) 1987,1988,1989 by Laurence Raphael Brothers */
  2. /* mon.c */
  3. /* various functions to do with monsters */
  4.  
  5. #include "glob.h"
  6.  
  7.  
  8.  
  9. /* consider one monster's action */
  10. void m_pulse(m)
  11. struct monster *m;
  12. {
  13.   int range = distance(m->x, m->y, Player.x,Player.y);
  14.   pol prev;
  15.  
  16.   if (Time % 10 == 0) 
  17.     if (m->hp < Monsters[m->id].hp)
  18.       m->hp++;
  19.   
  20.   if ((! m_statusp(m,AWAKE)) && (range <= m->wakeup)) {
  21.     m_status_set(m,AWAKE);
  22.     resetgamestatus(FAST_MOVE);
  23.   }
  24.   
  25.   if (m_statusp(m,AWAKE)) {
  26.     if (m_statusp(m,WANDERING)) {
  27.       if (m_statusp(m,MOBILE)) m_random_move(m);
  28.       if (range <= m->sense && (m_statusp(m, HOSTILE) || m_statusp(m, NEEDY)))
  29.     m_status_reset(m,WANDERING);
  30.     }
  31.     else /* not wandering */ {
  32.       if (m_statusp(m,HOSTILE)) {
  33.     if ((range > 2) && (range < m->sense) && (random_range(2) == 1))
  34.       if (los_p(m->x,m->y,Player.x,Player.y) &&
  35.           (Player.status[INVISIBLE] == 0)) monster_strike(m);
  36.       }
  37.       if ((m_statusp(m,HOSTILE) || m_statusp(m,NEEDY))
  38.       && (range > 1)
  39.       && m_statusp(m,MOBILE)) {
  40.     monster_move(m);
  41.  
  42.       }
  43.       if (m_statusp(m,HOSTILE) && (range ==1)) {
  44.     resetgamestatus(FAST_MOVE);
  45.     tacmonster(m);
  46.       }
  47.     }
  48.     /* if monster is greedy, picks up treasure it finds */
  49.     if (m_statusp(m,GREEDY))
  50.       while (Level->site[m->x][m->y].things != NULL) {
  51.     m_pickup(m,Level->site[m->x][m->y].things->thing);
  52.     prev = Level->site[m->x][m->y].things;
  53.     Level->site[m->x][m->y].things =
  54.       Level->site[m->x][m->y].things->next;
  55.     free((char *) prev);
  56.       }
  57.     /* prevents monsters from casting spells from other side of dungeon */
  58.     if (range < max(5,m->level)) 
  59.       monster_special(m);
  60.   }
  61. }
  62.     
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69. /* actually make a move */
  70. void movemonster(m,newx,newy)
  71. struct monster *m;
  72. int newx,newy;
  73. {
  74.   if (Level->site[newx][newy].creature != NULL)
  75.     return;
  76.   if (Level->site[m->x][m->y].creature == m)
  77.     Level->site[m->x][m->y].creature = NULL;
  78.   m->x = newx;
  79.   m->y = newy;
  80.   Level->site[m->x][m->y].creature = m;
  81.   m_movefunction(m,Level->site[m->x][m->y].p_locf);
  82. }
  83.  
  84.  
  85. /* give object o to monster m */
  86. void m_pickup(m,o)
  87. struct monster *m;
  88. struct object *o;
  89. {
  90.   pol tmp = ((pol) checkmalloc(sizeof(oltype)));
  91.   tmp->thing = o;
  92.   tmp->next = m->possessions;
  93.   m->possessions = tmp;
  94. }
  95.  
  96. void m_dropstuff(m)
  97. struct monster *m;
  98. {
  99.   pol tmp = m->possessions;
  100.   if (tmp != NULL) {
  101.     while (tmp->next != NULL)
  102.       tmp = tmp->next;
  103.  
  104.     tmp->next = Level->site[m->x][m->y].things;
  105.     Level->site[m->x][m->y].things = m->possessions;
  106.     m->possessions = NULL;
  107.   }
  108. }
  109.  
  110.  
  111.  
  112. void m_damage(m,dmg,dtype)
  113. struct monster *m;
  114. int dmg,dtype;
  115. {
  116.   m_status_set(m,AWAKE);
  117.   m_status_set(m,HOSTILE);
  118.   if (m_immunityp(m,dtype)) {
  119.     if (los_p(Player.x,Player.y,m->x,m->y)) { 
  120.       if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
  121.       else {
  122.     strcpy(Str1,"The ");
  123.     strcat(Str1,m->monstring);
  124.       }
  125.       strcat(Str1," ignores the attack!");
  126.       mprint(Str1);
  127.     }
  128.   }
  129.   else if ((m->hp -= dmg) < 1) m_death(m);
  130. }
  131.  
  132.  
  133. void m_death(m)
  134. struct monster *m;
  135. {
  136.   pob corpse;
  137.   pml ml;
  138.   int x,y,found=FALSE;
  139.   pol curr, prev = NULL;
  140.  
  141.   m->hp = -1;
  142.   if (los_p(Player.x,Player.y,m->x,m->y)) {
  143.     gain_experience(m->xpv);
  144.     calc_melee();
  145.     if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
  146.     else {
  147.       strcpy(Str1,"The ");
  148.       strcat(Str1,m->monstring);
  149.     }
  150.     strcat(Str1," is dead! ");
  151.     mprint(Str1);
  152.   }
  153.   m_dropstuff(m);
  154.   if (m->id == ML10+0) { /* Death */
  155.     mprint("Death lies sprawled out on the ground......");
  156.     mprint("Death laughs ironically and gets back to its feet.");
  157.     mprint("It gestures and another scythe appears in its hands.");
  158.     switch(random_range(10)) {
  159.     case 0:
  160.       mprint("Death performs a little bow and goes back on guard."); 
  161.       break;
  162.     case 1:
  163.       mprint("'A hit! A palpable hit!' Death goes back on the attack."); 
  164.       break;
  165.     case 2:
  166.       mprint("'Ah, if only it could be so simple!' snickers Death.");
  167.       break;
  168.     case 3:
  169.       mprint("'You think Death can be slain?  What a jest!' says Death.");
  170.       break;
  171.     case 4:
  172.       mprint("'Your point is well taken.' says Death, attacking again.");
  173.       break;
  174.     case 5:
  175.       mprint("'Oh, come now, stop delaying the inevitable.' says Death.");
  176.       break;
  177.     case 6:
  178.       mprint("'Your destiny ends here with me.' says Death, scythe raised.");
  179.       break;
  180.     case 7:
  181.       mprint("'I almost felt that.' says Death, smiling.");
  182.       break;
  183.     case 8:
  184.       mprint("'Timeo Mortis?' asks Death quizzically, 'Not me!'");
  185.       break;
  186.     case 9:
  187.       mprint("Death sighs theatrically. 'They never learn.'");
  188.       break;
  189.     }
  190.     strengthen_death(m);
  191.   }
  192.   else {
  193.     Level->site[m->x][m->y].creature = NULL;
  194.     if (m == Arena_Monster)
  195.       Arena_Victory = TRUE;    /* won this round of arena combat */
  196.     if (random_range(2) || (m->uniqueness != COMMON)) {
  197.       corpse=((pob) checkmalloc(sizeof(objtype)));
  198.       make_corpse(corpse,m);
  199.       drop_at(m->x,m->y,corpse);
  200.     }
  201.     plotspot(m->x,m->y,FALSE);
  202.     switch(m->id) {
  203.     case ML0+8: /* hiscore npc */
  204.       switch(m->aux2) {
  205.       case 0:
  206.     mprint("You hear a faroff dirge. You feel a sense of triumph.");
  207.     break;
  208.       case 1:case 2: case 3:case 4:case 5:case 6:
  209.     mprint("You hear a faroff sound like angels crying....");
  210.     strcpy(Priest[m->aux2],nameprint());
  211.     Priestbehavior[m->aux2] = 2933;
  212.     break;
  213.       case 7:
  214.       mprint("A furtive figure dashes out of the shadows, takes a look at");
  215.     mprint("the corpse, and runs away!");
  216.     strcpy(Shadowlord,nameprint());
  217.     Shadowlordbehavior = 2912;
  218.     break;
  219.       case 8:
  220.     mprint("An aide-de-camp approaches, removes the corpse's insignia,");
  221.     mprint("and departs.");
  222.     strcpy(Commandant,nameprint());
  223.     Commandantbehavior = 2912;
  224.     break;
  225.       case 9:
  226.     mprint("An odd glow surrounds the corpse, and slowly fades.");
  227.     strcpy(Archmage,nameprint());
  228.     Archmagebehavior = 2933;
  229.     break;
  230.       case 10:
  231.     mprint("A demon materializes, takes a quick look at the corpse,");
  232.     mprint("and teleports away with a faint popping noise.");
  233.     strcpy(Prime,nameprint());
  234.     Primebehavior = 2932;
  235.     break;
  236.       case 11:
  237.     mprint("A sports columnist rushes forward and takes a quick photo");
  238.     mprint("of the corpse and rushes off muttering about a deadline.");
  239.     strcpy(Champion,nameprint());
  240.     Championbehavior = 2913;
  241.     break;
  242.       case 12:
  243.     mprint("You hear a fanfare in the distance, and feel dismayed.");
  244.     strcpy(Duke,nameprint());
  245.     Dukebehavior = 2911;
  246.     break;
  247.       case 13:
  248.     if (Player.alignment > 10) mprint("You feel smug.");
  249.     else if (Player.alignment < 10) mprint("You feel ashamed.");
  250.     strcpy(Chaoslord,nameprint());
  251.     Chaoslordbehavior = 2912;
  252.     break;
  253.       case 14:
  254.     if (Player.alignment < 10) mprint("You feel smug.");
  255.     else if (Player.alignment > 10) mprint("You feel ashamed.");
  256.     strcpy(Lawlord,nameprint());
  257.     Lawlordbehavior = 2911;
  258.     break;
  259.       case 15: 
  260.     /* just a tad complicated. Promote a new justiciar if any
  261.        guards are left in the city, otherwise Destroy the Order! */
  262.     Player.alignment -= 100;
  263.     if (! gamestatusp(DESTROYED_ORDER)) {
  264.       curr = Level->site[m->x][m->y].things;
  265.       while (curr && curr->thing->id != THINGID + 16) {
  266.         prev = curr;
  267.         curr = curr->next;
  268.       }
  269.       strcpy(Justiciar,nameprint());
  270.       Justiciarbehavior = 2911;
  271.       mprint("In the distance you hear a trumpet. A Servant of Law");
  272.       /* promote one of the city guards to be justiciar */
  273.       ml = City->mlist;
  274.       while ((! found) && (ml != NULL)) {
  275.         found = ((ml->m->id == ML0+3) && (ml->m->hp > 0));
  276.         if (! found) ml=ml->next;
  277.       }
  278.       if (ml != NULL) {
  279.         if (curr) {
  280.           mprint("materializes, sheds a tear, picks up the badge, and leaves.");
  281.           m_pickup(ml->m, curr->thing);
  282.           if (prev)
  283.         prev->next = curr->next;
  284.           else
  285.         Level->site[m->x][m->y].things = curr->next;
  286.           free(curr);
  287.         }
  288.         else
  289.           mprint("materializes, sheds a tear, and leaves.");
  290.         mprint("A new justiciar has been promoted!");
  291.         x = ml->m->x; y = ml->m->y;
  292.         make_hiscore_npc(ml->m,15);
  293.         ml->m->x = x;
  294.         ml->m->y = y;
  295.         ml->m->click = (Tick + 1) % 60;
  296.         m_status_reset(ml->m,AWAKE);
  297.         m_status_reset(ml->m,HOSTILE);
  298.       }
  299.       else {
  300.         mprint("materializes, sheds a tear, and leaves.");
  301.         morewait();
  302.       }
  303.       alert_guards(); 
  304.       /* will cause order to be destroyed if no guards or justiciar*/
  305.     }
  306.     else {
  307.       mprint("A Servant of Chaos materializes, grabs the corpse,");
  308.       mprint("snickers a bit, and vanishes.");
  309.     }
  310.     break;
  311.       }
  312.       save_hiscore_npc(m->aux2);
  313.       break;
  314.     case ML0+3: /* guard */
  315.       Player.alignment -= 10;
  316.       if ((Current_Environment == E_CITY) || 
  317.       (Current_Environment == E_VILLAGE))
  318.     alert_guards();
  319.       break;
  320.     case ML3+5: 
  321.       if (! gamestatusp(ATTACKED_ORACLE)) {
  322.     mprint("You seem to hear a woman's voice from far off:");
  323.     mprint("'Well done! Come to me now....'");
  324.       }
  325.       setgamestatus(COMPLETED_CAVES); 
  326.       break; /* gob king */
  327.     case ML7+5: 
  328.       if (! gamestatusp(ATTACKED_ORACLE)) {
  329.     mprint("A female voice sounds from just behind your ear:");
  330.     mprint("'Well fought! I have some new advice for you....'");
  331.       }
  332.       setgamestatus(COMPLETED_SEWERS); 
  333.       break; /*grt worm */
  334.     case ML10+1:
  335.       setgamestatus(KILLED_EATER);
  336.       break;
  337.     case ML10+2:
  338.       setgamestatus(KILLED_LAWBRINGER);
  339.       break;
  340.     case ML10+3:
  341.       setgamestatus(KILLED_DRAGONLORD);
  342.       break;
  343.     case ML10+4:
  344.       setgamestatus(COMPLETED_VOLCANO);
  345.       if (! gamestatusp(ATTACKED_ORACLE)) {
  346.     mprint("You feel a soft touch on your shoulder...");
  347.     mprint("You turn around but there is no one there!");
  348.     mprint("You turn back and see a note: 'See me soon.'");
  349.     mprint("The note vanishes in a burst of blue fire!");
  350.       }
  351.       break;
  352.     case ML10+9: 
  353.       if (! gamestatusp(ATTACKED_ORACLE)) {
  354.     mprint("Words appear before you, traced in blue flame!");
  355.     mprint("'Return to the Prime Plane via the Circle of Sorcerors....'");
  356.       }
  357.       break; /* elem mast */
  358.     }
  359.     switch (m->specialf) {
  360.       case M_SP_COURT:
  361.       case M_SP_LAIR:
  362.     m_status_set(m,HOSTILE);
  363.     monster_action(m, m->specialf);
  364.     }
  365.   }
  366. }
  367.  
  368.  
  369.  
  370.  
  371.     
  372.     
  373.                    
  374. void monster_move(m)
  375. struct monster *m;
  376. {
  377.   monster_action(m,m->movef);
  378. }
  379.  
  380.  
  381.  
  382.  
  383.  
  384.  
  385.  
  386.  
  387.  
  388. void monster_strike(m)
  389. struct monster *m;
  390. {
  391.   if (player_on_sanctuary())
  392.     print1("The aegis of your deity protects you!");
  393.   else {
  394.   /* It's lawful to wait to be attacked */
  395.     if (m->attacked==0) Player.alignment++;
  396.     m->attacked++;
  397.     monster_action(m,m->strikef);
  398.   }
  399. }
  400.  
  401. void monster_special(m)
  402. struct monster *m;
  403. {
  404.   /* since many special functions are really attacks, cancel them
  405.      all if on sanctuary */
  406.   if (! player_on_sanctuary())
  407.     monster_action(m,m->specialf);
  408. }  
  409.  
  410.  
  411. void monster_talk(m)
  412. struct monster *m;
  413. {
  414.   monster_action(m,m->talkf);
  415. }
  416.  
  417. void monster_action(m,action)
  418. struct monster *m;
  419. int action;
  420. {
  421.   int meleef;
  422.   if ((action >= M_MELEE_NORMAL) && (action < M_MOVE_NORMAL)) {
  423.     /* kluge allows multiple attack forms */
  424.     if (distance(m->x,m->y,Player.x,Player.y)<2) {
  425.       meleef = m->meleef;
  426.       m->meleef = action;
  427.       tacmonster(m);
  428.       m->meleef = meleef;
  429.     }
  430.   }
  431.   else switch(action) {
  432.  
  433.   case M_NO_OP:m_no_op(m); break;
  434.     
  435.   case M_MOVE_NORMAL:m_normal_move(m); break;
  436.   case M_MOVE_FLUTTER:m_flutter_move(m); break;
  437.   case M_MOVE_FOLLOW:m_follow_move(m); break;
  438.   case M_MOVE_TELEPORT:m_teleport(m); break;
  439.   case M_MOVE_RANDOM:m_random_move(m); break;
  440.   case M_MOVE_SMART:m_smart_move(m); break;
  441.   case M_MOVE_SPIRIT:m_spirit_move(m); break;
  442.   case M_MOVE_CONFUSED:m_confused_move(m); break;
  443.   case M_MOVE_SCAREDY:m_scaredy_move(m); break;
  444.   case M_MOVE_ANIMAL:m_move_animal(m); break;
  445.   case M_MOVE_LEASH:m_move_leash(m); break;
  446.  
  447.   case M_STRIKE_MISSILE:m_nbolt(m); break;
  448.   case M_STRIKE_FBOLT:m_firebolt(m); break;
  449.   case M_STRIKE_LBALL:m_lball(m); break;
  450.   case M_STRIKE_FBALL:m_fireball(m); break;
  451.   case M_STRIKE_SNOWBALL:m_snowball(m); break;
  452.   case M_STRIKE_BLIND:m_blind_strike(m); break;
  453.   case M_STRIKE_SONIC:m_strike_sonic(m); break;
  454.     
  455.   case M_TALK_HORSE:m_talk_horse(m); break;
  456.   case M_TALK_THIEF:m_talk_thief(m);break;
  457.   case M_TALK_STUPID:m_talk_stupid(m); break;
  458.   case M_TALK_SILENT:m_talk_silent(m); break;
  459.   case M_TALK_HUNGRY:m_talk_hungry(m); break;
  460.   case M_TALK_GREEDY:m_talk_greedy(m); break;
  461.   case M_TALK_TITTER:m_talk_titter(m); break;
  462.   case M_TALK_MP:m_talk_mp(m); break;
  463.   case M_TALK_IM:m_talk_im(m); break;
  464.   case M_TALK_MAN:m_talk_man(m); break;
  465.   case M_TALK_ROBOT:m_talk_robot(m); break;
  466.   case M_TALK_EVIL:m_talk_evil(m); break;
  467.   case M_TALK_GUARD:m_talk_guard(m); break;
  468.   case M_TALK_MIMSY:m_talk_mimsy(m); break;
  469.   case M_TALK_SLITHY:m_talk_slithy(m); break;
  470.   case M_TALK_BURBLE:m_talk_burble(m); break;
  471.   case M_TALK_BEG:m_talk_beg(m); break;
  472.   case M_TALK_HINT:m_talk_hint(m); break;
  473.   case M_TALK_EF:m_talk_ef(m); break;
  474.   case M_TALK_GF:m_talk_gf(m); break;
  475.   case M_TALK_SEDUCTOR:m_talk_seductor(m); break;
  476.   case M_TALK_DEMONLOVER:m_talk_demonlover(m); break;
  477.   case M_TALK_NINJA:m_talk_ninja(m); break;
  478.   case M_TALK_ASSASSIN:m_talk_assassin(m); break;
  479.   case M_TALK_SERVANT: m_talk_servant(m); break;
  480.   case M_TALK_ANIMAL: m_talk_animal(m); break;
  481.   case M_TALK_SCREAM: m_talk_scream(m); break;
  482.   case M_TALK_PARROT: m_talk_parrot(m); break;
  483.   case M_TALK_HYENA: m_talk_hyena(m); break;
  484.   case M_TALK_DRUID: m_talk_druid(m); break;
  485.   case M_TALK_ARCHMAGE: m_talk_archmage(m); break;
  486.   case M_TALK_MERCHANT: m_talk_merchant(m); break;
  487.   case M_TALK_PRIME: m_talk_prime(m); break;
  488.  
  489.   case M_SP_BOG:m_sp_bogthing(m); break;
  490.   case M_SP_WERE:m_sp_were(m); break;
  491.   case M_SP_WHISTLEBLOWER:m_sp_whistleblower(m); break;
  492.   case M_SP_MERCHANT:m_sp_merchant(m); break;
  493.   case M_SP_SURPRISE:m_sp_surprise(m); break;
  494.   case M_SP_MP:m_sp_mp(m); break;
  495.   case M_SP_THIEF:m_thief_f(m); break;
  496.   case M_SP_DEMONLOVER:m_sp_demonlover(m); break;
  497.   case M_SP_AGGRAVATE:m_aggravate(m); break;
  498.   case M_SP_POISON_CLOUD:m_sp_poison_cloud(m); break;
  499.   case M_SP_HUGE:m_huge_sounds(m); break;
  500.   case M_SP_SUMMON:m_summon(m); break;
  501.   case M_SP_ILLUSION:m_illusion(m); break;
  502.   case M_SP_ESCAPE:m_sp_escape(m); break;
  503.   case M_SP_FLUTTER:m_flutter_move(m); break;
  504.   case M_SP_EXPLODE:m_sp_explode(m); break;
  505.   case M_SP_DEMON:m_sp_demon(m); break;
  506.   case M_SP_ACID_CLOUD:m_sp_acid_cloud(m); break;
  507.   case M_SP_GHOST:m_sp_ghost(m); break;
  508.   case M_SP_SPELL:m_sp_spell(m); break;
  509.   case M_SP_SEDUCTOR:m_sp_seductor(m); break;
  510.   case M_SP_EATER:m_sp_eater(m); break;
  511.   case M_SP_DRAGONLORD:m_sp_dragonlord(m); break;
  512.   case M_SP_BLACKOUT:m_sp_blackout(m); break;
  513.   case M_SP_SWARM: m_sp_swarm(m); break;
  514.   case M_SP_ANGEL: m_sp_angel(m); break;
  515.   case M_SP_SERVANT: m_sp_servant(m); break;
  516.   case M_SP_AV: m_sp_av(m); break;
  517.   case M_SP_LW: m_sp_lw(m); break;
  518.   case M_SP_MB: m_sp_mb(m); break;
  519.   case M_SP_RAISE: m_sp_raise(m); break;
  520.   case M_SP_MIRROR: m_sp_mirror(m); break;
  521.   case M_SP_COURT: m_sp_court(m); break;
  522.   case M_SP_LAIR: m_sp_lair(m); break;
  523.   case M_SP_PRIME: m_sp_prime(m); break;
  524.   }
  525. }
  526.   
  527. /* makes one of the highscore npcs */    
  528. void make_hiscore_npc(npc,npcid)
  529. pmt npc;
  530. int npcid;
  531. {
  532.   int st = -1;
  533.   pob ob;
  534.   *npc = Monsters[HISCORE_NPC];
  535.   npc->aux2 = npcid;
  536.   /* each of the high score npcs can be created here */
  537.   switch(npcid) {
  538.   case 0:
  539.     strcpy(Str2,Hiscorer);
  540.     determine_npc_behavior(npc,Hilevel,Hibehavior);
  541.     break;
  542.   case 1: case 2: case 3: case 4: case 5: case 6:
  543.     strcpy(Str2,Priest[npcid]);
  544.     determine_npc_behavior(npc,Priestlevel[npcid],Priestbehavior[npcid]);
  545.     st = ARTIFACTID+13+npcid;    /* appropriate holy symbol... */
  546.     Objects[st].uniqueness = UNIQUE_MADE;
  547.     if (npcid == DRUID)
  548.       npc->talkf = M_TALK_DRUID;
  549.     if (Player.patron == npcid)
  550.       m_status_reset(npc, HOSTILE);
  551.     break;
  552.   case 7:
  553.     strcpy(Str2,Shadowlord);
  554.     determine_npc_behavior(npc,Shadowlordlevel,Shadowlordbehavior);
  555.     break;
  556.   case 8:
  557.     strcpy(Str2,Commandant);
  558.     determine_npc_behavior(npc,Commandantlevel,Commandantbehavior);
  559.     if (Player.rank[LEGION])
  560.       m_status_reset(npc, HOSTILE);
  561.     break;
  562.   case 9:
  563.     strcpy(Str2,Archmage);
  564.     determine_npc_behavior(npc,Archmagelevel,Archmagebehavior);
  565.     st = ARTIFACTID+9; /* kolwynia */
  566.     npc->talkf = M_TALK_ARCHMAGE;
  567.     m_status_reset(npc, WANDERING);
  568.     m_status_reset(npc, HOSTILE);
  569.     break;
  570.   case 10:
  571.     strcpy(Str2,Prime);
  572.     determine_npc_behavior(npc,Primelevel,Primebehavior);
  573.     npc->talkf = M_TALK_PRIME;
  574.     npc->specialf = M_SP_PRIME;
  575.     if (Player.alignment < 0)
  576.       m_status_reset(npc, HOSTILE);
  577.     break;
  578.   case 11:
  579.     strcpy(Str2,Champion);
  580.     determine_npc_behavior(npc,Championlevel,Championbehavior);
  581.     if (Player.rank[ARENA])
  582.       m_status_reset(npc, HOSTILE);
  583.     break;
  584.   case 12:
  585.     strcpy(Str2,Duke);
  586.     determine_npc_behavior(npc,Dukelevel,Dukebehavior);
  587.     break;
  588.   case 13:
  589.     strcpy(Str2,Chaoslord);
  590.     determine_npc_behavior(npc,Chaoslordlevel,Chaoslordbehavior);
  591.     if (Player.alignment < 0 && random_range(2))
  592.       m_status_reset(npc, HOSTILE);
  593.     break;
  594.   case 14:
  595.     strcpy(Str2,Lawlord);
  596.     determine_npc_behavior(npc,Lawlordlevel,Lawlordbehavior);
  597.     if (Player.alignment > 0)
  598.       m_status_reset(npc, HOSTILE);
  599.     break;
  600.   case 15:
  601.     strcpy(Str2,Justiciar);
  602.     determine_npc_behavior(npc,Justiciarlevel,Justiciarbehavior);
  603.     st = THINGID+16;    /* badge */
  604.     npc->talkf = M_TALK_GUARD;
  605.     npc->specialf = M_SP_WHISTLEBLOWER;
  606.     m_status_reset(npc, WANDERING);
  607.     m_status_reset(npc, HOSTILE);
  608.     break;
  609.   }
  610.   if (st > -1 && Objects[st].uniqueness == UNIQUE_MADE) {
  611.     ob = ((pob) checkmalloc(sizeof(objtype)));
  612.     *ob = Objects[st];
  613.     m_pickup(npc,ob);
  614.   }
  615.   npc->monstring = salloc(Str2);
  616.   strcpy(Str1,"The body of ");
  617.   strcat(Str1,Str2);
  618.   npc->corpsestr = salloc(Str1);
  619. }
  620.  
  621.  
  622.  
  623.  
  624. /* sets npc behavior given level and behavior code */
  625. void determine_npc_behavior(npc,level,behavior)
  626. pmt npc;
  627. int level,behavior;
  628. {
  629.   int combatype,competence,talktype;
  630.   npc->hp = (level+1)*20;
  631.   npc->status = AWAKE+MOBILE+WANDERING;
  632.   combatype = (behavior % 100) / 10;
  633.   competence = (behavior % 1000) / 100;
  634.   talktype = behavior / 1000;
  635.   npc->level = competence;
  636.   if (npc->level < 2*difficulty()) npc->status += HOSTILE;
  637.   npc->xpv = npc->level*20;
  638.   switch (combatype) {
  639.   case 1: /* melee */
  640.     npc->meleef = M_MELEE_NORMAL;
  641.     npc->dmg = competence*5;
  642.     npc->hit = competence*3;
  643.     npc->speed = 3;
  644.     break;
  645.   case 2: /*missile*/
  646.     npc->meleef = M_MELEE_NORMAL;
  647.     npc->strikef = M_STRIKE_MISSILE;
  648.     npc->dmg = competence*3;
  649.     npc->hit = competence*2;
  650.     npc->speed = 4;
  651.     break;
  652.   case 3: /* spellcasting */
  653.     npc->meleef = M_MELEE_NORMAL;
  654.     npc->dmg = competence;
  655.     npc->hit = competence;
  656.     npc->specialf = M_SP_SPELL;
  657.     npc->speed = 6;
  658.     break;
  659.   case 4: /* thievery */
  660.     npc->meleef = M_MELEE_NORMAL;
  661.     npc->dmg = competence;
  662.     npc->hit = competence;
  663.     npc->specialf=M_SP_THIEF;
  664.     npc->speed = 3;
  665.     break;
  666.   case 5: /* flee */
  667.     npc->dmg = competence;
  668.     npc->hit = competence;
  669.     npc->meleef = M_MELEE_NORMAL;
  670.     npc->specialf = M_MOVE_SCAREDY;
  671.     npc->speed = 3;
  672.     break;
  673.   }
  674.   if (npc->talkf == M_TALK_MAN)
  675.     switch (talktype) {
  676.     case 1: npc->talkf = M_TALK_EVIL; break;
  677.     case 2: npc->talkf = M_TALK_MAN; break;
  678.     case 3: npc->talkf = M_TALK_HINT; break;
  679.     case 4: npc->talkf = M_TALK_BEG; break;
  680.     case 5: npc->talkf = M_TALK_SILENT; break;
  681.     default: mprint("Say Whutt? (npc talk weirdness)"); break;
  682.     }
  683.   npc->uniqueness = UNIQUE_MADE;
  684. }
  685.  
  686.  
  687. /* makes an ordinary npc (maybe undead) */
  688. void make_log_npc(npc)
  689. struct monster *npc;
  690. {
  691.   int i,n;
  692.   int behavior,status,level;
  693.   FILE *fd;
  694.  
  695.   /* in case the log file is null */
  696.   behavior = 2718;
  697.   level = 1;
  698.   status = 2;
  699.   strcpy(Str2,"Malaprop the Misnamed");
  700.   
  701.   strcpy(Str1,Omegalib);
  702.   strcat(Str1,"omega.log");
  703.   fd = checkfopen(Str1,"r");
  704.   n = 1;
  705.   while(fgets(Str1,STRING_LEN, fd)) {
  706.     if (random_range(n) == 0) {    /* this algo. from Knuth 2 - cute, eh? */
  707.       sscanf(Str1,"%d %d %d",&status,&level,&behavior);
  708.       for (i = 0; (Str1[i] < 'a' || Str1[i] > 'z') &&
  709.     (Str1[i] < 'A' || Str1[i] > 'Z'); i++)
  710.     ;
  711.       strcpy(Str2, Str1 + i);
  712.       Str2[strlen(Str2) - 1] = '\0';    /* 'cos fgets reads in the \n */
  713.     }
  714.     n++;
  715.   }
  716.   fclose(fd);
  717.   npc->hp = level*20;
  718.   if (status==1) {
  719.     if (level < 3) {
  720.       *npc = Monsters[GHOST];
  721.       strcpy(Str1,"ghost named ");
  722.     }
  723.     else if (level < 7) {
  724.       *npc = Monsters[HAUNT];
  725.       strcpy(Str1,"haunt named ");
  726.     }
  727.     else if (level < 12) {
  728.       *npc = Monsters[SPECTRE];
  729.       strcpy(Str1,"spectre named ");
  730.     }
  731.     else {
  732.       *npc = Monsters[LICHE];
  733.       strcpy(Str1,"lich named ");
  734.     }
  735.     strcat(Str1,Str2);
  736.     npc->monstring = salloc(Str1);
  737.     strcpy(Str3,"the mortal remains of ");
  738.     strcat(Str3,Str2);
  739.     npc->corpsestr = salloc(Str3);
  740.   }
  741.   else {
  742.     npc->monstring=salloc(Str2);
  743.     strcpy(Str3,"the corpse of ");
  744.     strcat(Str3,Str2);
  745.     npc->corpsestr = salloc(Str3);
  746.   }
  747.   determine_npc_behavior(npc,level,behavior);
  748. }
  749.  
  750.  
  751.  
  752.  
  753.  
  754. void m_trap_dart(m)
  755. struct monster *m;
  756. {
  757.   if (los_p(m->x,m->y,Player.x,Player.y)) {
  758.     if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
  759.     else {
  760.       strcpy(Str1,"The ");
  761.       strcat(Str1,m->monstring);
  762.     }
  763.     strcat(Str1," was hit by a dart!");
  764.     mprint(Str1);
  765.     Level->site[m->x][m->y].locchar = TRAP;
  766.     lset(m->x, m->y, CHANGED);
  767.   }
  768.   m_damage(m,difficulty()*2,NORMAL_DAMAGE);
  769. }
  770.  
  771. void m_trap_pit(m)
  772. struct monster *m;
  773. {
  774.   if (los_p(m->x,m->y,Player.x,Player.y)) {
  775.     if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
  776.     else {
  777.       strcpy(Str1,"The ");
  778.       strcat(Str1,m->monstring);
  779.     }
  780.     strcat(Str1," fell into a pit!");
  781.     mprint(Str1);
  782.     Level->site[m->x][m->y].locchar = TRAP;
  783.     lset(m->x, m->y, CHANGED);
  784.   }
  785.   if (! m_statusp(m,INTANGIBLE))
  786.     m_status_reset(m,MOBILE);
  787.   m_damage(m,difficulty()*5,NORMAL_DAMAGE);
  788.  
  789. }
  790.  
  791. void m_trap_door(m)
  792. struct monster *m;
  793. {
  794.   if (los_p(m->x,m->y,Player.x,Player.y)) {
  795.     if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
  796.     else {
  797.       strcpy(Str1,"The ");
  798.       strcat(Str1,m->monstring);
  799.     }
  800.     strcat(Str1," fell into a trap door!");
  801.     mprint(Str1);
  802.     Level->site[m->x][m->y].locchar = TRAP;
  803.     lset(m->x, m->y, CHANGED);
  804.   }
  805.   m_vanish(m);
  806. }
  807.  
  808. void m_trap_abyss(m)
  809. struct monster *m;
  810. {
  811.   char Str1[80];
  812.   if (los_p(m->x,m->y,Player.x,Player.y)) {
  813.     if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
  814.     else {
  815.       strcpy(Str1,"The ");
  816.       strcat(Str1,m->monstring);
  817.     }
  818.     strcat(Str1," fell into the infinite abyss!");
  819.     mprint(Str1);
  820.     Level->site[m->x][m->y].locchar = ABYSS;
  821.     lset(m->x, m->y, CHANGED);
  822.     Level->site[m->x][m->y].p_locf = L_ABYSS;
  823.     lset(m->x, m->y, CHANGED);
  824.   }
  825.   setgamestatus(SUPPRESS_PRINTING);
  826.   m_vanish(m);
  827.   resetgamestatus(SUPPRESS_PRINTING);
  828. }
  829.  
  830. void m_trap_snare(m)
  831. struct monster *m;
  832. {
  833.   char Str1[80];
  834.   Level->site[m->x][m->y].locchar = TRAP;
  835.   lset(m->x, m->y, CHANGED);
  836.   if (los_p(m->x,m->y,Player.x,Player.y)) {
  837.     if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
  838.     else {
  839.       strcpy(Str1,"The ");
  840.       strcat(Str1,m->monstring);
  841.     }
  842.     strcat(Str1," was caught in a snare!");
  843.     mprint(Str1);
  844.   }
  845.   if (! m_statusp(m,INTANGIBLE)) m_status_reset(m,MOBILE);
  846. }
  847.  
  848. void m_trap_blade(m)
  849. struct monster *m;
  850. {
  851.   char Str1[80];
  852.   Level->site[m->x][m->y].locchar = TRAP;
  853.   lset(m->x, m->y, CHANGED);
  854.   if (los_p(m->x,m->y,Player.x,Player.y)) { 
  855.     if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
  856.     else {
  857.       strcpy(Str1,"The ");
  858.       strcat(Str1,m->monstring);
  859.     }
  860.     strcat(Str1," was hit by a blade trap!");
  861.     mprint(Str1); } 
  862.   m_damage(m,(difficulty()+1)*7-Player.defense,NORMAL_DAMAGE);
  863. }
  864.  
  865. void m_trap_fire(m)
  866. struct monster *m;
  867. {
  868.   char Str1[80];
  869.   Level->site[m->x][m->y].locchar = TRAP;
  870.   lset(m->x, m->y, CHANGED);
  871.   if (los_p(m->x,m->y,Player.x,Player.y)) { 
  872.     if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
  873.     else {
  874.       strcpy(Str1,"The ");
  875.       strcat(Str1,m->monstring);
  876.     }
  877.     strcat(Str1," was hit by a fire trap!");
  878.     mprint(Str1); 
  879.   } 
  880.   m_damage(m,(difficulty()+1)*5,FLAME);
  881. }
  882.  
  883.  
  884. void m_fire(m)
  885. struct monster *m;
  886. {
  887.   char Str1[80];
  888.   if (los_p(m->x,m->y,Player.x,Player.y)) { 
  889.     if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
  890.     else {
  891.       strcpy(Str1,"The ");
  892.       strcat(Str1,m->monstring);
  893.     }
  894.     strcat(Str1," was blasted by fire!");
  895.     mprint(Str1); 
  896.   } 
  897.   m_damage(m,random_range(100),FLAME);
  898. }
  899.  
  900. void m_trap_teleport(m)
  901. struct monster *m;
  902. {
  903.   char Str1[80];
  904.   Level->site[m->x][m->y].locchar = TRAP;
  905.   lset(m->x, m->y, CHANGED);
  906.   if (los_p(m->x,m->y,Player.x,Player.y)) { 
  907.     if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
  908.     else {
  909.       strcpy(Str1,"The ");
  910.       strcat(Str1,m->monstring);
  911.     }
  912.     strcat(Str1," walked into a teleport trap!");
  913.     mprint(Str1); 
  914.   } 
  915.   m_teleport(m);
  916. }
  917.  
  918. void m_trap_disintegrate(m)
  919. struct monster *m;
  920. {
  921.   char Str1[80];
  922.   if (los_p(m->x,m->y,Player.x,Player.y)) { 
  923.     if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
  924.     else {
  925.       strcpy(Str1,"The ");
  926.       strcat(Str1,m->monstring);
  927.     }
  928.     strcat(Str1," walked into a disintegration trap!");
  929.     mprint(Str1); 
  930.     Level->site[m->x][m->y].locchar = TRAP;
  931.     lset(m->x, m->y, CHANGED);
  932.   } 
  933.   disintegrate(m->x,m->y);
  934. }
  935.  
  936. void m_trap_sleepgas(m)
  937. struct monster *m;
  938. {
  939.   char Str1[80];
  940.   if (los_p(m->x,m->y,Player.x,Player.y)) { 
  941.     if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
  942.     else {
  943.       strcpy(Str1,"The ");
  944.       strcat(Str1,m->monstring);
  945.     }
  946.     strcat(Str1," walked into a sleepgas trap!");
  947.     mprint(Str1); 
  948.     Level->site[m->x][m->y].locchar = TRAP;
  949.     lset(m->x, m->y, CHANGED);
  950.   } 
  951.   if (! m_immunityp(m,SLEEP)) m_status_reset(m,AWAKE);
  952. }
  953.  
  954. void m_trap_acid(m)
  955. struct monster *m;
  956. {
  957.   char Str1[80];
  958.   if (los_p(m->x,m->y,Player.x,Player.y)) { 
  959.     if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
  960.     else {
  961.       strcpy(Str1,"The ");
  962.       strcat(Str1,m->monstring);
  963.     }
  964.     strcat(Str1," walked into an acid bath trap!");
  965.     mprint(Str1); 
  966.     Level->site[m->x][m->y].locchar = TRAP;
  967.     lset(m->x, m->y, CHANGED);
  968.   } 
  969.   m_damage(m,random_range(difficulty()*difficulty()),ACID);
  970. }
  971.  
  972. void m_trap_manadrain(m)
  973. struct monster *m;
  974. {
  975.   char Str1[80];
  976.   if (los_p(m->x,m->y,Player.x,Player.y)) { 
  977.     if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
  978.     else {
  979.       strcpy(Str1,"The ");
  980.       strcat(Str1,m->monstring);
  981.     }
  982.     strcat(Str1," walked into a manadrain trap!");
  983.     mprint(Str1); 
  984.     Level->site[m->x][m->y].locchar = TRAP;
  985.     lset(m->x, m->y, CHANGED);
  986.   } 
  987.   if (m->specialf == M_SP_SPELL) m->specialf = M_NO_OP;
  988. }
  989.  
  990.  
  991. void m_water(m)
  992. struct monster *m;
  993. {
  994.   char Str1[80];
  995.   if ((! m_statusp(m,INTANGIBLE)) && 
  996.       (! m_statusp(m,SWIMMING)) &&
  997.       (! m_statusp(m,ONLYSWIM))) {
  998.     if (los_p(m->x,m->y,Player.x,Player.y)) { 
  999.     if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
  1000.     else {
  1001.       strcpy(Str1,"The ");
  1002.       strcat(Str1,m->monstring);
  1003.     }
  1004.       strcat(Str1," drowned!");
  1005.       mprint(Str1); 
  1006.     }
  1007.     m_death(m);
  1008.   }
  1009. }
  1010.  
  1011.  
  1012. void m_abyss(m)
  1013. struct monster *m;
  1014. {
  1015.   char Str1[80];
  1016.   if (los_p(m->x,m->y,Player.x,Player.y)) {
  1017.     if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
  1018.     else {
  1019.       strcpy(Str1,"The ");
  1020.       strcat(Str1,m->monstring);
  1021.     }
  1022.     strcat(Str1," fell into the infinite abyss!");
  1023.     mprint(Str1);
  1024.   }
  1025.   m_vanish(m);
  1026. }
  1027.  
  1028.  
  1029.  
  1030. void m_lava(m)
  1031. struct monster *m;
  1032. {
  1033.   char Str1[80];
  1034.   if ((! m_immunityp(m,FLAME)) ||
  1035.       ((! m_statusp(m,SWIMMING))&& (! m_statusp(m,ONLYSWIM)))) {
  1036.     if (los_p(m->x,m->y,Player.x,Player.y)) { 
  1037.     if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
  1038.     else {
  1039.       strcpy(Str1,"The ");
  1040.       strcat(Str1,m->monstring);
  1041.     }
  1042.       strcat(Str1," died in a pool of lava!");
  1043.       mprint(Str1); 
  1044.     }
  1045.     m_death(m);
  1046.   }
  1047. }
  1048.  
  1049. void m_altar(m)
  1050. struct monster *m;
  1051. {
  1052.   int visible = view_los_p(Player.x,Player.y,m->x,m->y);
  1053.   int reaction = 0;
  1054.   int altar = Level->site[m->x][m->y].aux;
  1055.  
  1056.   if (visible) {
  1057.     if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
  1058.     else {
  1059.       strcpy(Str1,"The ");
  1060.       strcat(Str1,m->monstring);
  1061.     }
  1062.     strcat(Str1," walks next to an altar...");
  1063.     mprint(Str1);
  1064.   }
  1065.   if (!m_statusp(m, HOSTILE))
  1066.     reaction = 0;
  1067.   else if (m->id == HISCORE_NPC && m->aux2 == altar)
  1068.     reaction = 1;    /* high priest of same deity */
  1069.   else if ((m->id == ML6+11 || m->id == ML8+11 || m->id == ML9+6) &&
  1070.       m->aux1 == altar)
  1071.     reaction = 1;    /* angel of same deity */
  1072.   else if (altar == Player.patron)
  1073.     reaction = -1;    /* friendly deity will zap hostile monster */
  1074.   else if (((Player.patron == ODIN || Player.patron == ATHENA) &&
  1075.       (altar == SET || altar == HECATE)) ||
  1076.       ((Player.patron == SET || Player.patron == HECATE) &&
  1077.       (altar == ODIN || altar == ATHENA)))
  1078.     reaction = 1;    /* hostile deity will help hostile monster */
  1079.   switch (reaction) {
  1080.     case -1:
  1081.       if (visible) {
  1082.     mprint("Your deity is angry!");
  1083.     mprint("A bolt of godsfire strikes the monster....");
  1084.       }
  1085.       disrupt(m->x,m->y,Player.rank[PRIESTHOOD]*50);
  1086.       break;
  1087.     case 1:
  1088.       if (visible) {
  1089.     mprint("The deity of the altar smiles on the monster....");
  1090.     mprint("A shaft of light zaps the altar...");
  1091.       }
  1092.       m->hp = Monsters[m->id].hp*2;
  1093.       break;
  1094.     default:
  1095.       if (visible)
  1096.     mprint("but nothing much seems to happen");
  1097.       break;
  1098.   }
  1099. }
  1100.  
  1101.  
  1102. char *mantype()
  1103. {
  1104.   switch(random_range(20)) {
  1105.     case 0: return "janitor";
  1106.     case 1: return "beggar";
  1107.     case 2: return "barbarian";
  1108.     case 3: return "hairdresser";
  1109.     case 4: return "accountant";
  1110.     case 5: return "lawyer";
  1111.     case 6: return "indian chief";
  1112.     case 7: return "tinker";
  1113.     case 8: return "tailor";
  1114.     case 9: return "soldier";
  1115.     case 10: return "spy";
  1116.     case 11: return "doctor";
  1117.     case 12: return "miner";
  1118.     case 13: return "noble";
  1119.     case 14: return "serf";
  1120.     case 15: return "neer-do-well";
  1121.     case 16: return "vendor";
  1122.     case 17: return "dilettante";
  1123.     case 18: return "surveyor";
  1124.     default:
  1125.     case 19: return "jongleur";
  1126.   }
  1127. }
  1128.  
  1129.  
  1130. void strengthen_death(m)
  1131. struct monster *m;
  1132. {
  1133.   pol ol = ((pol)checkmalloc(sizeof(oltype)));
  1134.   pob scythe = ((pob)checkmalloc(sizeof(objtype)));
  1135. #ifdef MSDOS
  1136.   unsigned tmp;
  1137. #endif
  1138.   m->xpv += min(10000,m->xpv+1000);
  1139.   m->hit += min(1000,m->hit+10);
  1140.   m->dmg = min(10000,m->dmg*2);
  1141.   m->ac += min(1000,m->ac+10);
  1142.   m->speed = max(m->speed-1,1);
  1143.   m->movef = M_MOVE_SMART;
  1144. #ifndef MSDOS
  1145.   m->hp = min(100000,100+m->dmg*10);
  1146. #else
  1147.   /* In order not to have to make the hp's into longs or unsigned,
  1148.      which would involve lots of changes, I'll make it max out at 30000. */
  1149.   tmp = 100+m->dmg*10;
  1150.   m->hp = (tmp > 30000) ? 30000 : tmp;
  1151. #endif
  1152.   *scythe = Objects[WEAPONID+39];
  1153.   ol->thing = scythe;
  1154.   ol->next = NULL;
  1155.   m->possessions = ol;
  1156. }
  1157.  
  1158.  
  1159.  
  1160.  
  1161. void m_no_op(m)
  1162. struct monster *m;
  1163. {
  1164. }
  1165.