[comp.sources.games] v07i026: omega3 - rogue like dungeon exploration

billr@saab.CNA.TEK.COM (Bill Randle) (07/13/89)

Submitted-by: "Laurence R. Brothers"   <brothers@paul.rutgers.edu>
Posting-number: Volume 7, Issue 26
Archive-name: omega3/Part07
Supersedes: omega2: Volume 5, Issue 11-29,38-40



#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 7 (of 20)."
# Contents:  omon.c omspec.c otime.c
# Wrapped by billr@saab on Thu Jun 29 08:14:02 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'omon.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'omon.c'\"
else
echo shar: Extracting \"'omon.c'\" \(29973 characters\)
sed "s/^X//" >'omon.c' <<'END_OF_FILE'
X/* omega copyright (c) 1987,1988,1989 by Laurence Raphael Brothers */
X/* omon.c */
X/* various functions to do with monsters */
X
X#include "oglob.h"
X
X
X
X/* consider one monster's action */
Xvoid m_pulse(m)
Xstruct monster *m;
X{
X  int range = distance(m->x, m->y, Player.x,Player.y);
X
X  if (Time % 10 == 0) 
X    if (m->hp < Monsters[m->id].hp)
X      m->hp++;
X  
X  if ((! m_statusp(m,AWAKE)) && (range <= m->wakeup)) {
X    m_status_set(m,AWAKE);
X    resetgamestatus(FAST_MOVE);
X  }
X  
X  if (m_statusp(m,AWAKE)) {
X    if (m_statusp(m,WANDERING)) {
X      if (m_statusp(m,MOBILE)) m_random_move(m);
X      if (range <= m->sense) m_status_reset(m,WANDERING);
X    }
X    else /* not wandering */ {
X      if (m_statusp(m,HOSTILE)) {
X	if ((range > 2) && (range < m->sense) && (random_range(2) == 1))
X	  if (los_p(m->x,m->y,Player.x,Player.y) &&
X	      (Player.status[INVISIBLE] == 0)) monster_strike(m);
X      }
X      if ((m_statusp(m,HOSTILE) || m_statusp(m,NEEDY))
X	  && (range > 1)
X	  && m_statusp(m,MOBILE)) {
X	monster_move(m);
X	/* if monster is greedy, picks up treasure it finds */
X	if (m_statusp(m,GREEDY))
X	  while (Level->site[m->x][m->y].things != NULL) {
X	    m_pickup(m,Level->site[m->x][m->y].things->thing);
X	    Level->site[m->x][m->y].things =
X	      Level->site[m->x][m->y].things->next;
X	  }
X      }
X      if (m_statusp(m,HOSTILE) && (range ==1)) {
X	resetgamestatus(FAST_MOVE);
X	tacmonster(m);
X      }
X    }
X    /* prevents monsters from casting spells from other side of dungeon */
X    if (range < max(5,m->level)) 
X      monster_special(m);
X  }
X}
X    
X
X
X
X
X
X
X/* actually make a move */
Xvoid movemonster(m,newx,newy)
Xstruct monster *m;
Xint newx,newy;
X{
X  Level->site[m->x][m->y].creature = NULL;
X  m->x = newx;
X  m->y = newy;
X  Level->site[m->x][m->y].creature = m;
X  m_movefunction(m,Level->site[m->x][m->y].p_locf);
X}
X
X
X/* give object o to monster m */
Xvoid m_pickup(m,o)
Xstruct monster *m;
Xstruct object *o;
X{
X  pol tmp = ((pol) malloc(sizeof(oltype)));
X  tmp->thing = o;
X  tmp->next = m->possessions;
X  m->possessions = tmp;
X}
X
Xvoid m_dropstuff(m)
Xstruct monster *m;
X{
X  pol tmp = m->possessions;
X  if (tmp != NULL) {
X    while (tmp->next != NULL)
X      tmp = tmp->next;
X
X    tmp->next = Level->site[m->x][m->y].things;
X    Level->site[m->x][m->y].things = m->possessions;
X    m->possessions = NULL;
X  }
X}
X
X
X
Xvoid m_status_set(m,s)
Xstruct monster *m;
Xint s;
X{
X  m->status |= s;
X}
X
Xvoid m_status_reset(m,s)
Xstruct monster *m;
Xint s;
X{
X  m->status &= ~s;
X}
X
X
X
X/* monster status predicate */
Xint m_statusp(m,s)
Xstruct monster *m;
Xint s;
X{
X  return(m->status & s);
X}
X
X/* monster immunity predicate */
Xint m_immunityp(m,s)
Xstruct monster *m;
Xint s;
X{
X  return(m->immunity & pow2(s));
X}
X
X
X
Xvoid m_damage(m,dmg,dtype)
Xstruct monster *m;
Xint dmg,dtype;
X{
X  m_status_set(m,AWAKE);
X  m_status_set(m,HOSTILE);
X  if (m_immunityp(m,dtype)) {
X    if (los_p(Player.x,Player.y,m->x,m->y)) { 
X      if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
X      else {
X	strcpy(Str1,"The ");
X	strcat(Str1,m->monstring);
X      }
X      strcat(Str1," ignores the attack!");
X      mprint(Str1);
X    }
X  }
X  else if ((m->hp -= dmg) < 1) m_death(m);
X}
X
X
Xvoid m_death(m)
Xstruct monster *m;
X{
X  pob corpse;
X  pml ml;
X  int x,y,found=FALSE;
X  m->hp = -1;
X  if (los_p(Player.x,Player.y,m->x,m->y)) {
X    putspot(m->x,m->y,getspot(m->x,m->y,FALSE));
X    gain_experience(m->xpv);
X    calc_melee();
X    if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
X    else {
X      strcpy(Str1,"The ");
X      strcat(Str1,m->monstring);
X    }
X    strcat(Str1," is dead! ");
X    mprint(Str1);
X  }
X  m_dropstuff(m);
X  if (m->id == ML10+0) { /* death */
X    mprint("Death lies sprawled out on the ground......");
X    mprint("Death laughs ironically and gets back to his feet.");
X    mprint("He gestures and another scythe appears in his hands.");
X    switch(random_range(10)) {
X    case 0:
X      mprint("Death performs a little bow and goes back on guard."); 
X      break;
X    case 1:
X      mprint("'A hit! A palpable hit!' Death goes back on the attack."); 
X      break;
X    case 2:
X      mprint("'Ah, if only it could be so simple!' snickers Death.");
X      break;
X    case 3:
X      mprint("'This fool thinks he can slay death! What a jest!' says Death.");
X      break;
X    case 4:
X      mprint("'Your point is well taken.' says Death, attacking again.");
X      break;
X    case 5:
X      mprint("'Oh, come now, stop delaying the inevitable.' says Death.");
X      break;
X    case 6:
X      mprint("'Your destiny ends here with me.' says Death, scythe raised.");
X      break;
X    case 7:
X      mprint("'I almost felt that.' says Death, smiling.");
X      break;
X    case 8:
X      mprint("'Timeo Mortis?' asks Death quizzically, 'Not me!'");
X      break;
X    case 9:
X      mprint("Death sighs theatrically. 'They never learn.'");
X      break;
X    }
X    strengthen_death(m);
X  }
X  else {
X    Level->site[m->x][m->y].creature = NULL;
X    if (random_range(2) || (m->uniqueness != COMMON)) {
X      corpse=((pob) malloc(sizeof(objtype)));
X      make_corpse(corpse,m);
X      drop_at(m->x,m->y,corpse);
X    }
X    plotspot(m->x,m->y,FALSE);
X    switch(m->id) {
X    case ML0+8: /* hiscore npc */
X      switch(m->aux2) {
X      case 0:
X	mprint("You hear a faroff dirge. You feel a sense of triumph.");
X	break;
X      case 1:case 2: case 3:case 4:case 5:case 6:
X	mprint("You hear a faroff sound like angels crying....");
X	strcpy(Priest[1],nameprint());
X	Priestbehavior[1] = 2933;
X	break;
X      case 7:
X      mprint("A furtive figure dashes out of the shadows, takes a look at");
X	mprint("the corpse, and runs away!");
X	strcpy(Shadowlord,nameprint());
X	Shadowlordbehavior = 2912;
X	break;
X      case 8:
X	mprint("An aide-de-camp approaches, removes the corpse's insignia,");
X	mprint("and departs.");
X	strcpy(Commandant,nameprint());
X	Commandantbehavior = 2912;
X	break;
X      case 9:
X	mprint("An odd glow surrounds the corpse, and slowly fades.");
X	strcpy(Archmage,nameprint());
X	Archmagebehavior = 2933;
X	break;
X      case 10:
X	mprint("A demon materializes, takes a quick look at the corpse,");
X	mprint("and teleports away with a faint popping noise.");
X	strcpy(Prime,nameprint());
X	Primebehavior = 2932;
X	break;
X      case 11:
X	mprint("A sports columnist rushes forward and takes a quick photo");
X	mprint("of the corpse and rushes off muttering about a deadline.");
X	strcpy(Champion,nameprint());
X	Championbehavior = 2913;
X	break;
X      case 12:
X	mprint("You hear a fanfare in the distance, and feel dismayed.");
X	strcpy(Duke,nameprint());
X	Dukebehavior = 2911;
X	break;
X      case 13:
X	if (Player.alignment > 10) mprint("You feel smug.");
X	else if (Player.alignment < 10) mprint("You feel ashamed.");
X	strcpy(Chaoslord,nameprint());
X	Chaoslordbehavior = 2912;
X	break;
X      case 14:
X	if (Player.alignment < 10) mprint("You feel smug.");
X	else if (Player.alignment > 10) mprint("You feel ashamed.");
X	strcpy(Lawlord,nameprint());
X	Lawlordbehavior = 2911;
X	break;
X      case 15: 
X	/* just a tad complicated. Promote a new justiciar if any
X	   guards are left in the city, otherwise Destroy the Order! */
X	Player.alignment -= 100;
X	if (! gamestatusp(DESTROYED_ORDER)) {
X	  mprint("In the distance you hear a trumpet. A Servant of Law");
X	  mprint("materializes, sheds a tear, and leaves.");
X	  strcpy(Justiciar,nameprint());
X	  Justiciarbehavior = 2911;
X	  /* promote one of the city guards to be justiciar */
X	  ml = City->mlist;
X	  while ((! found) && (ml != NULL)) {
X	    found = ((ml->m->id == ML0+3) && (ml->m->hp > 0));
X	    if (! found) ml=ml->next;
X	  }
X	  if (ml != NULL) {
X	    mprint("A new justiciar has been promoted!");
X	    x = ml->m->x; y = ml->m->y;
X	    make_hiscore_npc(ml->m,15);
X	    ml->m->x = x;
X	    ml->m->y = y;
X	    ml->m->click = (Tick + 1) % 60;
X	    m_status_reset(ml->m,AWAKE);
X	    m_status_reset(ml->m,HOSTILE);
X	  }
X	  alert_guards(); 
X	  /* will cause order to be destroyed if no guards or justiciar*/
X	}
X	else {
X	  mprint("A Servant of Chaos materializes, grabs the corpse,");
X	  mprint("snickers a bit, and vanishes.");
X	}
X	break;
X      }
X      break;
X    case ML0+3: /* guard */
X      Player.alignment -= 10;
X      if ((Current_Environment == E_CITY) || 
X	  (Current_Environment == E_VILLAGE))
X	alert_guards();
X      break;
X    case ML3+5: 
X      if (! gamestatusp(ATTACKED_ORACLE)) {
X	mprint("You seem to hear a woman's voice from far off:");
X	mprint("'Well done! Come to me now....'");
X      }
X      setgamestatus(COMPLETED_CAVES); 
X      break; /* gob king */
X    case ML7+5: 
X      if (! gamestatusp(ATTACKED_ORACLE)) {
X	mprint("A female voice sounds from just behind your ear:");
X	mprint("'Well fought! I have some new advice for you....'");
X      }
X      setgamestatus(COMPLETED_SEWERS); 
X      break; /*grt worm */
X    case ML10+1:
X      setgamestatus(KILLED_EATER);
X      break;
X    case ML10+2:
X      setgamestatus(KILLED_LAWBRINGER);
X      break;
X    case ML10+3:
X      setgamestatus(KILLED_DRAGONLORD);
X      break;
X    case ML10+4:
X      setgamestatus(COMPLETED_VOLCANO);
X      if (! gamestatusp(ATTACKED_ORACLE)) {
X	mprint("You feel a soft touch on your shoulder...");
X	mprint("You turn around but there is no one there!");
X	mprint("You turn back and see a note: 'See me soon.'");
X	mprint("The note vanishes in a burst of blue fire!");
X      }
X      break;
X    case ML10+9: 
X      if (! gamestatusp(ATTACKED_ORACLE)) {
X	mprint("Words appear before you, traced in blue flame!");
X	mprint("'Return to the Prime Plane via the Circle of Sorcerors....'");
X      }
X      break; /* elem mast */
X    }
X  }
X  dodrawspot(m->x,m->y);
X}
X
X
X
X
X    
X    
X				   
Xvoid monster_move(m)
Xstruct monster *m;
X{
X  monster_action(m,m->movef);
X}
X
X
X
X
X
X
X
X
X
Xvoid monster_strike(m)
Xstruct monster *m;
X{
X  if (player_on_sanctuary())
X    print1("The aegis of your deity protects you!");
X  else {
X  /* It's lawful to wait to be attacked */
X    if (m->attacked==0) Player.alignment++;
X    m->attacked++;
X    monster_action(m,m->strikef);
X  }
X}
X
Xvoid monster_special(m)
Xstruct monster *m;
X{
X  /* since many special functions are really attacks, cancel them
X     all if on sanctuary */
X  if (! player_on_sanctuary())
X    monster_action(m,m->specialf);
X}  
X
X
Xvoid monster_talk(m)
Xstruct monster *m;
X{
X  monster_action(m,m->talkf);
X}
X
Xvoid monster_action(m,action)
Xstruct monster *m;
Xint action;
X{
X  int meleef;
X  if ((action >= M_MELEE_NORMAL) && (action < M_MOVE_NORMAL)) {
X    /* kluge allows multiple attack forms */
X    if (distance(m->x,m->y,Player.x,Player.y)<2) {
X      meleef = m->meleef;
X      m->meleef = action;
X      tacmonster(m);
X      m->meleef = meleef;
X    }
X  }
X  else switch(action) {
X
X  case M_NO_OP:m_no_op(m); break;
X    
X  case M_MOVE_NORMAL:m_normal_move(m); break;
X  case M_MOVE_FLUTTER:m_flutter_move(m); break;
X  case M_MOVE_FOLLOW:m_follow_move(m); break;
X  case M_MOVE_TELEPORT:m_teleport(m); break;
X  case M_MOVE_RANDOM:m_random_move(m); break;
X  case M_MOVE_SMART:m_smart_move(m); break;
X  case M_MOVE_SPIRIT:m_spirit_move(m); break;
X  case M_MOVE_CONFUSED:m_confused_move(m); break;
X  case M_MOVE_SCAREDY:m_scaredy_move(m); break;
X  case M_MOVE_ANIMAL:m_move_animal(m); break;
X
X  case M_STRIKE_MISSILE:m_nbolt(m); break;
X  case M_STRIKE_FBOLT:m_firebolt(m); break;
X  case M_STRIKE_LBALL:m_lball(m); break;
X  case M_STRIKE_FBALL:m_fireball(m); break;
X  case M_STRIKE_SNOWBALL:m_snowball(m); break;
X  case M_STRIKE_BLIND:m_blind_strike(m); break;
X  case M_STRIKE_SONIC:m_strike_sonic(m); break;
X    
X  case M_TALK_HORSE:m_talk_horse(m); break;
X  case M_TALK_THIEF:m_talk_thief(m);break;
X  case M_TALK_STUPID:m_talk_stupid(m); break;
X  case M_TALK_SILENT:m_talk_silent(m); break;
X  case M_TALK_HUNGRY:m_talk_hungry(m); break;
X  case M_TALK_GREEDY:m_talk_greedy(m); break;
X  case M_TALK_TITTER:m_talk_titter(m); break;
X  case M_TALK_MP:m_talk_mp(m); break;
X  case M_TALK_IM:m_talk_im(m); break;
X  case M_TALK_MAN:m_talk_man(m); break;
X  case M_TALK_ROBOT:m_talk_robot(m); break;
X  case M_TALK_EVIL:m_talk_evil(m); break;
X  case M_TALK_GUARD:m_talk_guard(m); break;
X  case M_TALK_MIMSY:m_talk_mimsy(m); break;
X  case M_TALK_SLITHY:m_talk_slithy(m); break;
X  case M_TALK_BURBLE:m_talk_burble(m); break;
X  case M_TALK_BEG:m_talk_beg(m); break;
X  case M_TALK_HINT:m_talk_hint(m); break;
X  case M_TALK_EF:m_talk_ef(m); break;
X  case M_TALK_GF:m_talk_gf(m); break;
X  case M_TALK_SEDUCTOR:m_talk_seductor(m); break;
X  case M_TALK_DEMONLOVER:m_talk_demonlover(m); break;
X  case M_TALK_NINJA:m_talk_ninja(m); break;
X  case M_TALK_ASSASSIN:m_talk_assassin(m); break;
X  case M_TALK_SERVANT: m_talk_servant(m); break;
X  case M_TALK_ANIMAL: m_talk_animal(m); break;
X  case M_TALK_SCREAM: m_talk_scream(m); break;
X  case M_TALK_PARROT: m_talk_parrot(m); break;
X  case M_TALK_HYENA: m_talk_hyena(m); break;
X  case M_TALK_DRUID: m_talk_druid(m); break;
X  case M_TALK_ARCHMAGE: m_talk_archmage(m); break;
X  case M_TALK_MERCHANT: m_talk_merchant(m); break;
X  case M_TALK_PRIME: m_talk_prime(m); break;
X
X  case M_SP_BOG:m_sp_bogthing(m); break;
X  case M_SP_LEASH:m_sp_leash(m); break;
X  case M_SP_WERE:m_sp_were(m); break;
X  case M_SP_WHISTLEBLOWER:m_sp_whistleblower(m); break;
X  case M_SP_MERCHANT:m_sp_merchant(m); break;
X  case M_SP_SURPRISE:m_sp_surprise(m); break;
X  case M_SP_MP:m_sp_mp(m); break;
X  case M_SP_THIEF:m_thief_f(m); break;
X  case M_SP_DEMONLOVER:m_sp_demonlover(m); break;
X  case M_SP_AGGRAVATE:m_aggravate(m); break;
X  case M_SP_POISON_CLOUD:m_sp_poison_cloud(m); break;
X  case M_SP_HUGE:m_huge_sounds(m); break;
X  case M_SP_SUMMON:m_summon(m); break;
X  case M_SP_ILLUSION:m_illusion(m); break;
X  case M_SP_ESCAPE:m_sp_escape(m); break;
X  case M_SP_FLUTTER:m_flutter_move(m); break;
X  case M_SP_EXPLODE:m_sp_explode(m); break;
X  case M_SP_DEMON:m_sp_demon(m); break;
X  case M_SP_ACID_CLOUD:m_sp_acid_cloud(m); break;
X  case M_SP_GHOST:m_sp_ghost(m); break;
X  case M_SP_SPELL:m_sp_spell(m); break;
X  case M_SP_SEDUCTOR:m_sp_seductor(m); break;
X  case M_SP_EATER:m_sp_eater(m); break;
X  case M_SP_DRAGONLORD:m_sp_dragonlord(m); break;
X  case M_SP_BLACKOUT:m_sp_blackout(m); break;
X  case M_SP_SWARM: m_sp_swarm(m); break;
X  case M_SP_ANGEL: m_sp_angel(m); break;
X  case M_SP_SERVANT: m_sp_servant(m); break;
X  case M_SP_AV: m_sp_av(m); break;
X  case M_SP_LW: m_sp_lw(m); break;
X  case M_SP_MB: m_sp_mb(m); break;
X  case M_SP_RAISE: m_sp_raise(m); break;
X  case M_SP_MIRROR: m_sp_mirror(m); break;
X  case M_SP_COURT: m_sp_court(m); break;
X  case M_SP_LAIR: m_sp_lair(m); break;
X  case M_SP_PRIME: m_sp_prime(m); break;
X  }
X}
X  
X/* makes one of the highscore npc's */    
Xvoid make_hiscore_npc(npc,npcid)
Xpmt npc;
Xint npcid;
X{
X  int behavior,level;
X  int st = -1;
X  pob ob;
X  *npc = Monsters[HISCORE_NPC];
X  npc->aux2 = npcid;
X  /* each of the high score npc's can be created here */
X  switch(npcid) {
X  case 0:
X    level = Hilevel;
X    behavior = Hibehavior;
X    strcpy(Str2,Hiscorer);
X    break;
X  case 1:
X    level = Priestlevel[1];
X    behavior = Priestbehavior[1];
X    strcpy(Str2,Priest[1]);
X    st = ARTIFACTID+14; /* hs of odin */
X    break;
X  case 2:
X    level = Priestlevel[2];
X    behavior = Priestbehavior[2];
X    strcpy(Str2,Priest[2]);
X    st = ARTIFACTID+17; /* hs of set */
X    break;
X  case 3:
X    level = Priestlevel[3];
X    behavior = Priestbehavior[3];
X    strcpy(Str2,Priest[3]);
X    st = ARTIFACTID+16; /* hs of athena */
X    break;
X  case 4:
X    level = Priestlevel[4];
X    behavior = Priestbehavior[4];
X    strcpy(Str2,Priest[4]);
X    st = ARTIFACTID+15; /* hs of hecate */
X    break;
X  case 5:
X    level = Priestlevel[5];
X    behavior = Priestbehavior[5];
X    strcpy(Str2,Priest[5]);
X    st = ARTIFACTID+18; /* hs of druid */
X    npc->talkf = M_TALK_DRUID;
X    break;
X  case 6:
X    level = Priestlevel[6];
X    behavior = Priestbehavior[6];
X    strcpy(Str2,Priest[6]);
X    st = ARTIFACTID+19; /* hs of destiny */
X    break;
X  case 7:
X    level = Shadowlordlevel;
X    behavior = Shadowlordbehavior;
X    strcpy(Str2,Shadowlord);
X    break;
X  case 8:
X    level = Commandantlevel;
X    behavior = Commandantbehavior;
X    strcpy(Str2,Commandant);
X    break;
X  case 9:
X    level = Archmagelevel;
X    behavior = Archmagebehavior;
X    strcpy(Str2,Archmage);
X    st = ARTIFACTID+9; /* kolwynia */
X    npc->talkf = M_TALK_ARCHMAGE;
X    break;
X  case 10:
X    level = Primelevel;
X    behavior = Primebehavior;
X    strcpy(Str2,Prime);
X    npc->talkf = M_TALK_PRIME;
X    npc->specialf = M_SP_PRIME;
X    break;
X  case 11:
X    level = Championlevel;
X    behavior = Championbehavior;
X    strcpy(Str2,Champion);
X    break;
X  case 12:
X    level = Dukelevel;
X    behavior = Dukebehavior;
X    strcpy(Str2,Duke);
X    break;
X  case 13:
X    level = Chaoslordlevel;
X    behavior = Chaoslordbehavior;
X    strcpy(Str2,Chaoslord);
X    break;
X  case 14:
X    level = Lawlordlevel;
X    behavior = Lawlordbehavior;
X    strcpy(Str2,Lawlord);
X    break;
X  case 15:
X    st = THINGID+16;
X    level = Justiciarlevel;
X    behavior = Justiciarbehavior;
X    strcpy(Str2,Justiciar);
X    npc->talkf = M_TALK_GUARD;
X    npc->specialf = M_SP_WHISTLEBLOWER;
X    break;
X  }
X  if (st > -1) {
X    ob = ((pob) malloc(sizeof(objtype)));
X    *ob = Objects[st];
X    m_pickup(npc,ob);
X  }
X  npc->monstring = salloc(Str2);
X  strcpy(Str1,"The body of ");
X  strcat(Str1,Str2);
X  npc->corpsestr = salloc(Str1);
X  determine_npc_behavior(npc,level,behavior);
X}
X
X
X
X
X/* sets npc behavior given level and behavior code */
Xvoid determine_npc_behavior(npc,level,behavior)
Xpmt npc;
Xint level,behavior;
X{
X  int combatype,competence,talktype;
X  npc->hp = (level+1)*20;
X  npc->status = AWAKE+MOBILE+WANDERING;
X  combatype = (behavior % 100) / 10;
X  competence = (behavior % 1000) / 100;
X  talktype = behavior / 1000;
X  npc->level = competence;
X  if (npc->level < 2*difficulty()) npc->status += HOSTILE;
X  npc->xpv = npc->level*20;
X  switch (combatype) {
X  case 1: /* melee */
X    npc->meleef = M_MELEE_NORMAL;
X    npc->dmg = competence*5;
X    npc->hit = competence*3;
X    npc->speed = 3;
X    break;
X  case 2: /*missile*/
X    npc->meleef = M_MELEE_NORMAL;
X    npc->strikef = M_STRIKE_MISSILE;
X    npc->dmg = competence*3;
X    npc->hit = competence*2;
X    npc->speed = 4;
X    break;
X  case 3: /* spellcasting */
X    npc->meleef = M_MELEE_NORMAL;
X    npc->dmg = competence;
X    npc->hit = competence;
X    npc->specialf = M_SP_SPELL;
X    npc->speed = 6;
X    break;
X  case 4: /* thievery */
X    npc->meleef = M_MELEE_NORMAL;
X    npc->dmg = competence;
X    npc->hit = competence;
X    npc->specialf=M_SP_THIEF;
X    npc->speed = 3;
X    break;
X  case 5: /* flee */
X    npc->dmg = competence;
X    npc->hit = competence;
X    npc->meleef = M_MELEE_NORMAL;
X    npc->specialf = M_MOVE_SCAREDY;
X    npc->speed = 3;
X    break;
X  }
X  if (npc->talkf == M_TALK_MAN)
X    switch (talktype) {
X    case 1: npc->talkf = M_TALK_EVIL; break;
X    case 2: npc->talkf = M_TALK_MAN; break;
X    case 3: npc->talkf = M_TALK_HINT; break;
X    case 4: npc->talkf = M_TALK_BEG; break;
X    case 5: npc->talkf = M_TALK_SILENT; break;
X    default: mprint("Say Whutt? (npc talk weirdness)"); break;
X    }
X  npc->uniqueness = UNIQUE_MADE;
X}
X
X
X/* makes an ordinary npc (maybe undead) */
Xvoid make_log_npc(npc)
Xstruct monster *npc;
X{
X  int b,s,l,i,j,n = -1;
X  int behavior,status,level;
X  FILE *fd;
X
X  /* in case the log file is null */
X  behavior = 2718;
X  level = 1;
X  status = 2;
X  strcpy(Str2,"Malaprop the Misnamed");
X  
X  strcpy(Str1,OMEGALIB);
X  strcat(Str1,"omega.log");
X  fd = fopen(Str1,"r");
X  i = getc(fd);
X  while(i!=EOF) {
X    fscanf(fd,"%d %d %d ",&s,&l,&b);
X    filescanstring(fd,Str2);
X    if ((j=random_range(10000))>n) {
X      status = s; 
X      level = l; 
X      behavior = b;
X      n = j;
X    }
X    i = fgetc(fd);
X  }
X  fclose(fd);
X  npc->hp = level*20;
X  if (status==1) {
X    if (level < 3) {
X      *npc = Monsters[GHOST];
X      strcpy(Str1,"ghost named ");
X    }
X    else if (level < 7) {
X      *npc = Monsters[HAUNT];
X      strcpy(Str1,"haunt named ");
X    }
X    else if (level < 12) {
X      *npc = Monsters[SPECTRE];
X      strcpy(Str1,"spectre named ");
X    }
X    else {
X      *npc = Monsters[LICHE];
X      strcpy(Str1,"lich named ");
X    }
X    strcat(Str1,Str2);
X    npc->monstring = salloc(Str1);
X    strcpy(Str3,"the mortal remains of ");
X    strcat(Str3,Str2);
X    npc->corpsestr = salloc(Str3);
X  }
X  else {
X    npc->monstring=salloc(Str2);
X    strcpy(Str3,"the corpse of ");
X    strcat(Str3,Str2);
X    npc->corpsestr = salloc(Str3);
X    determine_npc_behavior(npc,level,behavior);
X  }
X}
X
X
X
X
X
Xvoid m_trap_dart(m)
Xstruct monster *m;
X{
X  if (los_p(m->x,m->y,Player.x,Player.y)) {
X    if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
X    else {
X      strcpy(Str1,"The ");
X      strcat(Str1,m->monstring);
X    }
X    strcat(Str1," was hit by a dart!");
X    mprint(Str1);
X  Level->site[m->x][m->y].locchar = TRAP;
X  }
X  m_damage(m,difficulty()*2,NORMAL_DAMAGE);
X}
X
Xvoid m_trap_pit(m)
Xstruct monster *m;
X{
X  if (los_p(m->x,m->y,Player.x,Player.y)) {
X    if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
X    else {
X      strcpy(Str1,"The ");
X      strcat(Str1,m->monstring);
X    }
X    strcat(Str1," fell into a pit!");
X    mprint(Str1);
X  Level->site[m->x][m->y].locchar = TRAP;
X  }
X  if (! m_statusp(m,INTANGIBLE))
X    m_status_reset(m,MOBILE);
X  m_damage(m,difficulty()*5,NORMAL_DAMAGE);
X
X}
X
Xvoid m_trap_door(m)
Xstruct monster *m;
X{
X  if (los_p(m->x,m->y,Player.x,Player.y)) {
X    if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
X    else {
X      strcpy(Str1,"The ");
X      strcat(Str1,m->monstring);
X    }
X    strcat(Str1," fell into a trap door!");
X    mprint(Str1);
X  Level->site[m->x][m->y].locchar = TRAP;
X  }
X  m_vanish(m);
X}
X
Xvoid m_trap_abyss(m)
Xstruct monster *m;
X{
X  char Str1[80];
X  if (los_p(m->x,m->y,Player.x,Player.y)) {
X    if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
X    else {
X      strcpy(Str1,"The ");
X      strcat(Str1,m->monstring);
X    }
X    strcat(Str1," fell into the infinite abyss!");
X    mprint(Str1);
X  Level->site[m->x][m->y].locchar = ABYSS;
X  Level->site[m->x][m->y].p_locf = L_ABYSS;
X  }
X  m_vanish(m);
X}
X
Xvoid m_trap_snare(m)
Xstruct monster *m;
X{
X  char Str1[80];
X  Level->site[m->x][m->y].locchar = TRAP;
X  if (los_p(m->x,m->y,Player.x,Player.y)) {
X    if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
X    else {
X      strcpy(Str1,"The ");
X      strcat(Str1,m->monstring);
X    }
X    strcat(Str1," was caught in a snare!");
X    mprint(Str1);
X  }
X  if (! m_statusp(m,INTANGIBLE)) m_status_reset(m,MOBILE);
X}
X
Xvoid m_trap_blade(m)
Xstruct monster *m;
X{
X  char Str1[80];
X  Level->site[m->x][m->y].locchar = TRAP;
X  if (los_p(m->x,m->y,Player.x,Player.y)) { 
X    if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
X    else {
X      strcpy(Str1,"The ");
X      strcat(Str1,m->monstring);
X    }
X    strcat(Str1," was hit by a blade trap!");
X    mprint(Str1); } 
X  m_damage(m,(difficulty()+1)*7-Player.defense,NORMAL_DAMAGE);
X}
X
Xvoid m_trap_fire(m)
Xstruct monster *m;
X{
X  char Str1[80];
X  Level->site[m->x][m->y].locchar = TRAP;
X  if (los_p(m->x,m->y,Player.x,Player.y)) { 
X    if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
X    else {
X      strcpy(Str1,"The ");
X      strcat(Str1,m->monstring);
X    }
X    strcat(Str1," was hit by a fire trap!");
X    mprint(Str1); 
X  } 
X  m_damage(m,(difficulty()+1)*5,FLAME);
X}
X
X
Xvoid m_fire(m)
Xstruct monster *m;
X{
X  char Str1[80];
X  if (los_p(m->x,m->y,Player.x,Player.y)) { 
X    if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
X    else {
X      strcpy(Str1,"The ");
X      strcat(Str1,m->monstring);
X    }
X    strcat(Str1," was blasted by fire!");
X    mprint(Str1); 
X  } 
X  m_damage(m,random_range(100),FLAME);
X}
X
Xvoid m_trap_teleport(m)
Xstruct monster *m;
X{
X  char Str1[80];
X  Level->site[m->x][m->y].locchar = TRAP;
X  if (los_p(m->x,m->y,Player.x,Player.y)) { 
X    if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
X    else {
X      strcpy(Str1,"The ");
X      strcat(Str1,m->monstring);
X    }
X    strcat(Str1," walked into a teleport trap!");
X    mprint(Str1); 
X  } 
X  m_teleport(m);
X}
X
Xvoid m_trap_disintegrate(m)
Xstruct monster *m;
X{
X  char Str1[80];
X  if (los_p(m->x,m->y,Player.x,Player.y)) { 
X    if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
X    else {
X      strcpy(Str1,"The ");
X      strcat(Str1,m->monstring);
X    }
X    strcat(Str1," walked into a disintegration trap!");
X    mprint(Str1); 
X    Level->site[m->x][m->y].locchar = TRAP;
X  } 
X  disintegrate(m->x,m->y);
X}
X
Xvoid m_trap_sleepgas(m)
Xstruct monster *m;
X{
X  char Str1[80];
X  if (los_p(m->x,m->y,Player.x,Player.y)) { 
X    if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
X    else {
X      strcpy(Str1,"The ");
X      strcat(Str1,m->monstring);
X    }
X    strcat(Str1," walked into a sleepgas trap!");
X    mprint(Str1); 
X    Level->site[m->x][m->y].locchar = TRAP;
X  } 
X  if (! m_immunityp(m,SLEEP)) m_status_reset(m,AWAKE);
X}
X
Xvoid m_trap_acid(m)
Xstruct monster *m;
X{
X  char Str1[80];
X  if (los_p(m->x,m->y,Player.x,Player.y)) { 
X    if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
X    else {
X      strcpy(Str1,"The ");
X      strcat(Str1,m->monstring);
X    }
X    strcat(Str1," walked into an acid bath trap!");
X    mprint(Str1); 
X    Level->site[m->x][m->y].locchar = TRAP;
X  } 
X  m_damage(m,random_range(difficulty()*difficulty()),ACID);
X}
X
Xvoid m_trap_manadrain(m)
Xstruct monster *m;
X{
X  char Str1[80];
X  if (los_p(m->x,m->y,Player.x,Player.y)) { 
X    if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
X    else {
X      strcpy(Str1,"The ");
X      strcat(Str1,m->monstring);
X    }
X    strcat(Str1," walked into a manadrain trap!");
X    mprint(Str1); 
X    Level->site[m->x][m->y].locchar = TRAP;
X  } 
X  if (m->specialf == M_SP_SPELL) m->specialf = M_NO_OP;
X}
X
X
Xvoid m_water(m)
Xstruct monster *m;
X{
X  char Str1[80];
X  if ((! m_statusp(m,INTANGIBLE)) && 
X      (! m_statusp(m,SWIMMING)) &&
X      (! m_statusp(m,ONLYSWIM))) {
X    if (los_p(m->x,m->y,Player.x,Player.y)) { 
X    if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
X    else {
X      strcpy(Str1,"The ");
X      strcat(Str1,m->monstring);
X    }
X      strcat(Str1," drowned!");
X      mprint(Str1); 
X    }
X    m_death(m);
X  }
X}
X
X
Xvoid m_abyss(m)
Xstruct monster *m;
X{
X  char Str1[80];
X  if (los_p(m->x,m->y,Player.x,Player.y)) {
X    if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
X    else {
X      strcpy(Str1,"The ");
X      strcat(Str1,m->monstring);
X    }
X    strcat(Str1," fell into the infinite abyss!");
X    mprint(Str1);
X  }
X  m_vanish(m);
X}
X
X
X
Xvoid m_lava(m)
Xstruct monster *m;
X{
X  char Str1[80];
X  if ((! m_immunityp(m,FLAME)) ||
X      ((! m_statusp(m,SWIMMING))&& (! m_statusp(m,ONLYSWIM)))) {
X    if (los_p(m->x,m->y,Player.x,Player.y)) { 
X    if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
X    else {
X      strcpy(Str1,"The ");
X      strcat(Str1,m->monstring);
X    }
X      strcat(Str1," died in a pool of lava!");
X      mprint(Str1); 
X    }
X    m_death(m);
X  }
X}
X
Xvoid m_altar(m)
Xstruct monster *m;
X{
X  int visible = view_los_p(Player.x,Player.y,m->x,m->y);
X  if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
X  else {
X    strcpy(Str1,"The ");
X    strcat(Str1,m->monstring);
X  }
X  strcat(Str1," walks next to an altar...");
X  if (visible) mprint(Str1);
X  if (Level->site[m->x][m->y].aux==Player.patron) {
X    if (visible) {
X      mprint("Your deity is angry!");
X      mprint("A bolt of godsfire strikes the monster....");
X    }
X    disrupt(m->x,m->y,Player.rank[PRIESTHOOD]*50);
X  }
X  else if ((Player.patron == ODIN) || (Player.patron == ATHENA)) {
X    if ((Level->site[m->x][m->y].aux == SET) ||
X	(Level->site[m->x][m->y].aux == HECATE)) {
X      if (visible) {
X	mprint("The deity of the altar smiles on the monster....");
X	mprint("A shaft of light zaps the altar...");
X      }
X      m->hp = Monsters[m->id].hp*2;
X    }
X    else if (visible) mprint("but nothing much seems to happen");
X  }
X  else if ((Player.patron == SET) || (Player.patron == HECATE)) {
X    if ((Level->site[m->x][m->y].aux == ODIN) ||
X	(Level->site[m->x][m->y].aux == ATHENA)) {
X      if (visible) {
X	mprint("The deity of the altar smiles on the monster....");
X	mprint("A shaft of light zaps the altar...");
X      }
X      m->hp = Monsters[m->id].hp*2;
X    }
X    else if (visible) mprint("but nothing much seems to happen");
X  }
X  else if (visible) mprint("but nothing much seems to happen");
X}
X
X
X/* who knows what ml will point to when this is done... */
Xvoid free_mlist(ml)
Xpml ml;
X{
X  pml tml;
X   while (ml != NULL) {
X    tml = ml;
X    ml= ml->next;
X    free((char *) tml->m);
X    free((char *) tml);
X  }
X}
X
X
Xchar *mantype()
X{
X  switch(random_range(20)) {
X  case 0: strcpy(Str3,"janitor"); break;
X  case 1: strcpy(Str3,"beggar"); break;
X  case 2: strcpy(Str3,"barbarian"); break;
X  case 3: strcpy(Str3,"hairdresser"); break;
X  case 4: strcpy(Str3,"accountant"); break;
X  case 5: strcpy(Str3,"lawyer"); break;
X  case 6: strcpy(Str3,"indian chief"); break;
X  case 7: strcpy(Str3,"tinker"); break;
X  case 8: strcpy(Str3,"tailor"); break;
X  case 9: strcpy(Str3,"soldier"); break;
X  case 10: strcpy(Str3,"spy"); break;
X  case 11: strcpy(Str3,"doctor"); break;
X  case 12: strcpy(Str3,"miner"); break;
X  case 13: strcpy(Str3,"noble"); break;
X  case 14: strcpy(Str3,"serf"); break;
X  case 15: strcpy(Str3,"neer-do-well"); break;
X  case 16: strcpy(Str3,"vendor"); break;
X  case 17: strcpy(Str3,"dilettante"); break;
X  case 18: strcpy(Str3,"surveyor"); break;
X  case 19: strcpy(Str3,"jongleur"); break;
X  }
X  return(Str3);
X}
X
X
Xvoid strengthen_death(m)
Xstruct monster *m;
X{
X  pol ol = ((pol)malloc(sizeof(oltype)));
X  pob scythe = ((pob)malloc(sizeof(objtype)));
X#ifdef MSDOS
X  unsigned tmp;
X#endif
X  m->xpv += min(10000,m->xpv+1000);
X  m->hit += min(1000,m->hit+10);
X  m->dmg = min(10000,m->dmg*2);
X  m->ac += min(1000,m->ac+10);
X  m->speed = max(m->speed-1,1);
X#ifndef MSDOS
X  m->hp = min(100000,100+m->dmg*10);
X#else
X  /* In order not to have to make the hp's into longs or unsigned,
X     which would involve lots of changes, I'll make it max out at 30000. */
X  tmp = 100+m->dmg*10;
X  m->hp = (tmp > 30000) ? 30000 : tmp;
X#endif
X  *scythe = Objects[WEAPONID+39];
X  ol->thing = scythe;
X  ol->next = NULL;
X  m->possessions = ol;
X}
X
X
X
X
Xvoid m_no_op(m)
Xstruct monster *m;
X{
X}
END_OF_FILE
if test 29973 -ne `wc -c <'omon.c'`; then
    echo shar: \"'omon.c'\" unpacked with wrong size!
fi
# end of 'omon.c'
fi
if test -f 'omspec.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'omspec.c'\"
else
echo shar: Extracting \"'omspec.c'\" \(18439 characters\)
sed "s/^X//" >'omspec.c' <<'END_OF_FILE'
X/* omega copyright (c) 1987,1988,1989 by Laurence Raphael Brothers */
X/* omspec.c */
X/* monster special functions */
X
X#include "oglob.h"
X
X
Xvoid m_sp_mp(m)
Xstruct monster *m;
X{
X  if (m->attacked && (random_range(3) == 1)) {
X    mprint("You feel cursed!");
X    p_damage(10,UNSTOPPABLE,"a mendicant priest's curse");
X    m_vanish(m);
X  }
X  else if (! m_statusp(m,NEEDY)) {
X    mprint("The mendicant priest makes a mystical gesture....");
X    mprint("You feel impressed...");
X    Player.alignment += 5;
X    if (Player.alignment > 20)
X      Player.hp = max(Player.hp,Player.maxhp);
X    m_vanish(m);
X  }
X}
X
X
X
Xvoid m_sp_ng(m)
Xstruct monster *m;
X{
X  if (distance(m->x,m->y,Player.x,Player.y) < 2)
X    if ((random_range(5) == 1) || (Player.status[VULNERABLE]>0)) {
X      mprint("The night gaunt grabs you and carries you off!");
X      mprint("Its leathery wings flap and flap, and it giggles insanely.");
X      mprint("It tickles you cunningly to render you incapable of escape.");
X      mprint("Finally, it deposits you in a strange place.");
X      p_teleport(0);
X    }
X}
X
X
X
X
X
Xvoid m_sp_poison_cloud(m)
Xstruct monster *m;
X{
X  if (distance(m->x,m->y,Player.x,Player.y) < 3) {
X    mprint("A cloud of poison gas surrounds you!");
X    if (Player.status[BREATHING] > 0)
X      mprint("You can breathe freely, however.");
X    else p_poison(7);
X  }
X}
X
X
Xvoid m_sp_explode(m)
Xstruct monster *m;
X{
X  if ((distance(Player.x,Player.y,m->x,m->y)<2) &&
X      (m-> hp > 0) && 
X      (m->hp < Monsters[m->id].hp))
X    fball(m->x,m->y,m->x,m->y,m->hp);
X}
X
X
X
Xvoid m_sp_demon(m)
Xstruct monster *m;
X{
X  int mid;
X
X  if (random_range(2)) {
X    if ((m->id != ML4+6) && /*succubi don't give fear */
X	los_p(m->x,m->y,Player.x,Player.y) &&
X	(random_range(30) > Player.level+10) &&
X	(Player.status[AFRAID] == 0)) {
X      mprint("You are stricken with fear!");
X      if (! p_immune(FEAR)) Player.status[AFRAID] += m->level;
X      else mprint("You master your reptile brain and stand fast.");
X    }
X    else m_sp_spell(m);
X  }
X  if ((m->hp < (m->level * 5)) && (m->hp > 1)) {
X    mprint("The demon uses its waning lifeforce to summon help!");
X    m->hp = 1;
X    switch(m->level) {
X    case 3: mid = ML2+1; break; /* night gaunt */
X    case 4:
X    case 5: mid = ML3+2; break; /* lesser frost demon */
X    case 6: mid = ML5+4; break; /* frost demon */
X    case 7: mid = ML5+12; break; /* outer circle demon */
X    case 8: mid = ML6+10; break; /* demon serpent */
X    case 9: mid = ML7+14; break; /* inner circle demon */
X    }
X    summon(-1,mid);
X    summon(-1,mid);
X  }
X}
X
X
Xvoid m_sp_acid_cloud(m)
Xstruct monster *m;
X{
X  if (m_statusp(m,HOSTILE) &&
X      (distance(m->x,m->y,Player.x,Player.y) < 3))
X    acid_cloud();
X}
X
X	  
Xvoid m_sp_escape(m)
Xstruct monster *m;
X{
X  if (m_statusp(m,HOSTILE))
X    m_vanish(m);
X}
X
X
Xvoid m_sp_ghost(m)
Xstruct monster *m;
X{
X  if (m_statusp(m,HOSTILE)) {
X    mprint("The ghost moans horribly....");
X    p_damage(1,FEAR,"a ghost-inspired heart attack");
X    mprint("You've been terrorized!");
X    if (! p_immune(FEAR)) Player.status[AFRAID] += m->level;
X    else mprint("You master your reptile brain and stand fast.");
X  }
X}
X
X
X
X
X/* random spell cast by monster */
Xvoid m_sp_spell(m)
Xstruct monster *m;
X{
X  char action[80];
X  if (m_statusp(m,HOSTILE) && los_p(Player.x,Player.y,m->x,m->y)) {
X    if (m->uniqueness == COMMON) strcpy(action,"The ");
X    else strcpy(action,"");
X    strcat(action,m->monstring);
X    strcat(action," casts a spell...");
X    mprint(action);
X    if (! magic_resist(m->level)) switch (random_range(m->level+7)) {
X    case 0: 
X      nbolt(m->x,m->y,Player.x,Player.y,m->hit,10);
X      break;
X    case 1:
X      mprint("It seems stronger..."); 
X      m->hp += random_range(m->level*m->level);
X      break;
X    case 2:
X      haste(-1);
X      break;
X    case 3:
X      cure(-1);
X      break;
X    case 4:
X      lball(m->x,m->y,Player.x,Player.y,20);
X      break;
X    case 5:
X      enchant(-1);
X    case 6:
X      snowball(m->x,m->y,Player.x,Player.y,30);
X      break;
X    case 7:
X      bless(0-m->level);
X      break;
X    case 8:
X      p_poison(m->level);
X      break;
X    case 9:
X      sleep_player(m->level/2);
X      break;
X    case 10:
X      fbolt(m->x,m->y,Player.x,Player.y,m->hit*3,50);
X      break;
X    case 11:
X      acquire(0-m->level);
X      break;
X    case 12:
X      dispel(-1);
X      break;
X    case 13:
X      disrupt(Player.x,Player.y,50);
X      break;
X    case 14:
X      if (m->uniqueness == COMMON) {
X	strcpy(Str2,"a ");
X	strcat(Str2,m->monstring);
X      }
X      else strcpy(Str2,m->monstring);
X      level_drain(m->level,Str2);
X      break;
X    case 15:
X    case 16:
X      disintegrate(Player.x,Player.y);
X      break;
X    }
X  }
X}
X
X
X
X/* monsters with this have some way to hide, camouflage, etc until they 
X   attack */
Xvoid m_sp_surprise(m)
Xstruct monster *m;
X{
X  if (m->attacked) {
X    if (m_statusp(m,HOSTILE) && 
X	(! Player.status[TRUESIGHT]) &&
X	m_statusp(m,M_INVISIBLE)) {
X      m->monchar = Monsters[m->id].monchar;
X      if (! Player.status[ALERT]) {
X	switch(random_range(4)) {
X	case 0: 
X	  mprint("You are surprised by a sudden treacherous attack!");
X	  break;
X	case 1: 
X	  mprint("You are shocked out of your reverie by the scream of battle!");
X	  break;
X	case 2: 
X	  mprint("Suddenly, from out of the shadows, a surprise attack!");
X	  break;
X	case 3: 
X	  mprint("A shriek of hatred causes you to momentarily freeze up!");
X	  break;
X	}
X	morewait();
X	setgamestatus(SKIP_PLAYER);
X	m_status_reset(m,M_INVISIBLE);
X      }
X      else {
X	mprint("You alertly sense the presence of an attacker!");
X	m_status_reset(m,M_INVISIBLE);
X      }	
X    }
X  }
X}
X
Xvoid m_sp_whistleblower(m)
Xstruct monster *m;
X{
X  pml ml;
X  if (m_statusp(m,HOSTILE)) {
X    alert_guards();
X    m->specialf = M_MELEE_NORMAL;
X  }
X}
X
X
Xvoid m_sp_seductor(m)
Xstruct monster *m;
X{
X  if (m_statusp(m,HOSTILE)) {
X    if (m->uniqueness == COMMON) {
X      strcpy(Str2,"The ");
X      strcat(Str2,m->monstring);
X    }
X    else strcpy(Str2,m->monstring);
X    strcat(Str2," runs away screaming for help....");
X    mprint(Str2);
X    m_vanish(m);
X    summon(-1,-1);
X    summon(-1,-1);
X    summon(-1,-1);
X  }
X  else if (distance(Player.x,Player.y,m->x,m->y) < 2) 
X    m_talk_seductor(m);
X
X}
X
X
Xvoid m_sp_demonlover(m)
Xstruct monster *m;
X{
X  if (distance(Player.x,Player.y,m->x,m->y) < 2) 
X    m_talk_demonlover(m);
X}
X
Xvoid m_sp_eater(m)
Xstruct monster *m;
X{
X  int i;
X  if (Player.rank[COLLEGE]) m_status_set(m,HOSTILE);
X  if (m_statusp(m,HOSTILE))
X    if (los_p(m->x,m->y,Player.x,Player.y)) {
X      mprint("A strange numbing sensation comes over you...");
X      morewait();
X      Player.mana = Player.mana / 2;
X      if (random_range(4)) enchant(-1);
X      else dispel(-1);
X      Player.pow--;
X      if (--Player.pow < 1) p_death("The Eater of Magic");
X    }
X  if (m->hp < 10) {
X    mprint("The Eater explodes in a burst of mana!");
X    for(i=0;i<9;i++) 
X      manastorm(m->x+Dirs[0][i],m->y+Dirs[0][i],100);
X  }
X}
X
X
Xvoid m_sp_dragonlord(m)
Xstruct monster *m;
X{
X  if (m_statusp(m,HOSTILE)) {
X    if (distance(m->x,m->y,Player.x,Player.y)<2) {
X      if (! Player.status[IMMOBILE]) {
X	mprint("A gust of wind from the Dragonlord's wings knocks you down!");
X	p_damage(25,NORMAL_DAMAGE,"a gust of wind");
X	setgamestatus(SKIP_PLAYER);
X	Player.status[IMMOBILE]+=2;
X      }
X      else if (! Constriction) {
X	mprint("The Dragonlord grabs you with his tail!");
X	Constriction = 25;
X	Player.status[IMMOBILE]+=1;
X      }
X      else if (random_range(2)) {
X	mprint("The coils squeeze tighter and tighter...");
X	p_damage(Constriction,NORMAL_DAMAGE,"The Dragonlord");
X	Player.status[IMMOBILE]+=1;
X	Constriction *=2;
X      }
X      else {
X	mprint("The dragonlord hurls you to the ground!");
X	p_damage(2*Constriction,NORMAL_DAMAGE,"The Dragonlord");
X	Constriction = 0;
X      }
X      m_sp_spell(m);
X    }
X    else {
X      Constriction = 0;
X      if (view_los_p(m->x,m->y,Player.x,Player.y)) {
X	if ((! Player.immunity[FEAR]) && (! Player.status[AFRAID])) {
X	  mprint("You are awestruck at the sight of the Dragonlord.");
X	  Player.status[AFRAID]+=5;
X	}
X	if (random_range(3)) {
X	  m_sp_spell(m);
X	  m_sp_spell(m);
X	}
X      }
X    }
X  }
X  else if (distance(m->x,m->y,Player.x,Player.y)<2)
X    mprint("You are extremely impressed at the sight of the Dragonlord.");
X}
X
X
Xvoid m_sp_blackout(m)
Xstruct monster *m;
X{
X  if ((distance(m->x,m->y,Player.x,Player.y) < 4) &&
X      (Player.status[BLINDED] == 0)) {
X    mprint("The fungus emits a burst of black spores. You've been blinded!");
X    if (Player.status[TRUESIGHT] > 0) mprint("The blindness quickly passes.");
X    else Player.status[BLINDED]+=4;
X  }
X  if (loc_statusp(m->x,m->y,LIT)) {
X    mprint("The fungus chirps.... ");
X    mprint("The area is plunged into darkness.");
X    torch_check();torch_check();torch_check();
X    torch_check();torch_check();torch_check();
X    spreadroomdark(m->x,m->y,Level->site[m->x][m->y].roomnumber);
X    levelrefresh();
X  }
X}
X
X
Xvoid m_sp_bogthing(m)
Xstruct monster *m;
X{
X  if (Player.status[IMMOBILE] && 
X      (distance(Player.x,Player.y,m->x,m->y) < 2)) {
X    if (! Player.status[AFRAID]) {
X      mprint("As the bogthing touches you, you feel a frisson of terror....");
X      if (Player.immunity[FEAR]) mprint("which you shake off.");
X      else Player.status[AFRAID]+=2;
X    }
X    else {
X      mprint("The bogthing's touch causes you scream in agony!");
X      p_damage(50,UNSTOPPABLE,"fright");
X      mprint("Your struggles grow steadily weaker....");
X      Player.con--;
X      Player.str--;
X      if ((Player.con < 3) || (Player.str < 3))
X	p_death("congestive heart failure");
X    }
X  }
X}
X
X
Xvoid m_sp_were(m)
Xstruct monster *m;
X{
X  int mid;
X  if (m_statusp(m,HOSTILE) || (Phase == 6)) {
X    do mid = random_range(ML9-NML_0)+ML1;
X    while ((Monsters[mid].uniqueness != COMMON) ||
X	   (! m_statusp(&(Monsters[mid]),MOBILE)) ||
X	   (! m_statusp(&(Monsters[mid]),HOSTILE)));
X    m->id = Monsters[mid].id;
X    m->hp += Monsters[mid].hp;
X    m->status |= Monsters[mid].status;
X    m->ac = Monsters[mid].ac;
X    m->dmg = Monsters[mid].dmg;
X    m->speed = Monsters[mid].speed;
X    m->immunity |= Monsters[mid].immunity;
X    m->xpv += Monsters[mid].xpv;
X    m->corpseweight = Monsters[mid].corpseweight;
X    m->monchar = Monsters[mid].monchar;
X    m->talkf = Monsters[mid].talkf;
X    m->meleef = Monsters[mid].meleef;
X    m->strikef = Monsters[mid].strikef;
X    m->specialf = Monsters[mid].specialf;
X    strcpy(Str1,"were-");
X    strcat(Str1,Monsters[mid].monstring);
X    strcpy(Str2,"dead were-");
X    strcat(Str2,Monsters[mid].monstring);
X    m->monstring = salloc(Str1);
X    m->corpsestr = salloc(Str2);
X    m->immunity += pow2(NORMAL_DAMAGE);
X    if (los_p(m->x,m->y,Player.x,Player.y)) 
X      mprint("You witness a hideous transformation!");
X    else mprint("You hear a distant howl.");
X  }
X}    
X
X
Xvoid m_sp_leash(m)
Xstruct monster *m;
X{
X  if (m->aux1 < 0) {
X    m->aux1 = m->x;
X    m->aux2 = m->y;
X  }
X  else if (distance(m->x,m->y,m->aux1,m->aux2) > 5) {
X    Level->site[m->x][m->y].creature = NULL;
X    m->x = m->aux1;
X    m->y = m->aux2;
X    Level->site[m->x][m->y].creature = m;
X    if (los_p(Player.x,Player.y,m->x,m->y)) 
X      mprint("You see the dog jerked back by its chain!");
X    else mprint("You hear a strangled sort of yelp!");
X  }
X}
X
Xvoid m_sp_servant(m)
Xstruct monster *m;
X{
X  pml ml;
X  if ((m->id == ML4+12) && (Player.alignment < 0))
X    m_status_set(m,HOSTILE);
X  else if ((m->id == ML4+13) && (Player.alignment > 0))
X    m_status_set(m,HOSTILE);
X}
X
X
Xvoid m_sp_av(m)
Xstruct monster *m;
X{
X  if (Player.mana > 0) {
X    mprint("You feel a sudden loss of mana!");
X    Player.mana -= (max(0,10-distance(m->x,m->y,Player.x,Player.y)));
X    dataprint();
X  }
X}
X
Xvoid m_sp_lw(m)
Xstruct monster *m;
X{
X  if (random_range(2)) {
X    if (Level->site[m->x][m->y].locchar == FLOOR) {
X      Level->site[m->x][m->y].locchar = LAVA;
X      Level->site[m->x][m->y].p_locf = L_LAVA;
X    }
X    else if (Level->site[m->x][m->y].locchar == WATER) {
X      Level->site[m->x][m->y].locchar = FLOOR;
X      Level->site[m->x][m->y].p_locf = L_NO_OP;
X    }
X  }
X}
X
X
Xvoid m_sp_angel(m)
Xstruct monster *m;
X{
X  int mid,hostile = FALSE;
X  switch(m->aux1) {
X  case ATHENA:
X  case ODIN: 
X    hostile = ((Player.patron == HECATE) || (Player.patron == SET));
X    break;
X  case SET:
X  case HECATE: 
X    hostile = ((Player.patron == ODIN) || (Player.patron == ATHENA));
X    break;
X  case DESTINY:
X    hostile = (Player.patron != DESTINY);
X    break;
X  }
X  if (hostile)
X    m_status_set(m,HOSTILE);
X  if (m_statusp(m,HOSTILE)) {
X    mprint("The angel summons a heavenly host!");
X    switch(m->level) {
X    case 9: mid = ML8+11; break; /* high angel */
X    case 8: mid = ML6+11; break; /* angel */
X    default:
X    case 6: mid = ML3+4; break; /* phantom */
X    }
X    summon(-1,mid);
X    summon(-1,mid);
X    summon(-1,mid);
X    /* prevent angel from summoning infinitely */
X    m->specialf = M_NO_OP;
X  }
X}
X
X
X/* Could completely fill up level */
Xvoid m_sp_swarm(m)
Xstruct monster *m;
X{
X  if (random_range(5)==1) {
X    if (view_los_p(m->x,m->y,Player.x,Player.y))
X      mprint("The swarm expands!");
X    else mprint("You hear an aggravating humming noise.");
X    summon(-1,ML4+14);
X  }
X}
X
X
X
X
X/* raise nearby corpses from the dead.... */
Xvoid m_sp_raise(m)
Xstruct monster *m;
X{
X  int x,y;
X  pol t;
X  for(x=m->x-2;x<=m->x+2;x++)
X    for(y=m->y-2;y<=m->y+2;y++)
X      if (inbounds(x,y)) 
X	if (Level->site[x][y].things != NULL)
X	  if (Level->site[x][y].things->thing->id == CORPSEID) {
X	    mprint("The Zombie Overlord makes a mystical gesture...");
X	    summon(-1,Level->site[x][y].things->thing->charge);
X	    t = Level->site[x][y].things;
X	    Level->site[x][y].things = Level->site[x][y].things->next;
X	    free((char *) t);
X	  }
X}
X
X
X
X
Xvoid m_sp_mb(m)
Xstruct monster *m;
X{
X  if (distance(m->x,m->y,Player.x,Player.y)==1) {
X    mprint("The manaburst explodes!");
X    if (m_statusp(m,HOSTILE)) {
X      mprint("You get blasted!");
X      p_damage(random_range(100),UNSTOPPABLE,"a manaburst");
X      mprint("You feel cold all over!");
X      Player.pow-=3;
X      Player.iq--;
X      Player.con--;
X      Player.str-=2;
X      Player.dex--;
X      Player.agi--;
X      dispel(-1);
X    }
X    else {
X      mprint("You feel toasty warm inside!");
X      Player.pow++;
X      Player.mana = max(Player.mana,calcmana());
X      Player.hp = max(Player.hp,++Player.maxhp);
X    }
X    m->hp = 0;
X  }
X}
X
X
Xvoid m_sp_mirror(m)
Xstruct monster *m;
X{
X  int i,x,y;
X  if (view_los_p(m->x,m->y,Player.x,Player.y)) {
X    if (random_range(20)+6 < m->level) {
X      summon(-1,m->id);
X      mprint("You hear the sound of a mirror shattering!");
X    }
X    else for(i=0;i<5;i++) {
X      x = m->x + random_range(13)-6;
X      y = m->y + random_range(13)-6;
X      if (inbounds(x,y)) {
X	Level->site[x][y].showchar = m->monchar;
X	putspot(x,y,m->monchar);
X      }
X    }
X  }
X}
X
X
X
Xvoid m_illusion(m)
Xstruct monster *m;
X{
X  int i = random_range(NUMMONSTERS);
X  if (i==ML0+4) i = m->id; /* can't imitate NPC */
X  if (Player.status[TRUESIGHT]) {
X    m->monchar = Monsters[m->id].monchar;
X    m->monstring = Monsters[m->id].monstring;
X  }
X  else  if (random_range(5) == 1) {
X    m->monchar = Monsters[i].monchar;
X    m->monstring = Monsters[i].monstring;
X  }
X}
X
X
X
X
Xvoid m_huge_sounds(m)
Xstruct monster *m;
X{
X  if (m_statusp(m,AWAKE) &&
X      (! los_p(m->x,m->y,Player.x,Player.y)) &&
X      (random_range(10) == 1))
X    mprint("The dungeon shakes!");
X}
X
X
X
Xvoid m_thief_f(m)
Xstruct monster *m;
X{
X  int i = random_item();
X  if (random_range(3) == 1) {
X    if (distance(Player.x,Player.y,m->x,m->y) < 2) {
X      if (p_immune(THEFT) || (Player.level > (m->level*2)+random_range(20))) 
X	mprint("You feel secure.");
X      else {
X	if (i == ABORT)
X	  mprint("You feel fortunate.");
X	else if ((Player.possessions[i]->used) || 
X		 (Player.dex < m->level*random_range(10))) {
X	  mprint("You feel a sharp tug.... You hold on!");
X	}
X	else {
X	  mprint("You feel uneasy for a moment.");
X	  if (m->uniqueness == COMMON) {
X	    strcpy(Str2,"The ");
X	    strcat(Str2,m->monstring);
X	  }
X	  else strcpy(Str2,m->monstring);
X	  strcat(Str2,"suddenly runs away for some reason.");
X	  mprint(Str2);
X	  m_teleport(m);
X	  m->movef = M_MOVE_SCAREDY;
X	  m->specialf = M_MOVE_SCAREDY;
X	  m_pickup(m,Player.possessions[i]);
X	  conform_lost_object(Player.possessions[i]);
X	}
X      }
X    }
X  }
X}
X
X
Xvoid m_summon(m)
Xstruct monster *m;
X{
X  if ((distance(Player.x,Player.y,m->x,m->y) < 2) &&
X      (random_range(3) == 1)) {
X	summon(0,-1);
X	summon(0,-1);
X      }
X}	  
X
X
Xvoid m_aggravate(m)
Xstruct monster *m;
X{
X
X  if (m_statusp(m,HOSTILE)) {
X    if (m->uniqueness == COMMON) {
X      strcpy(Str2,"The ");
X      strcat(Str2,m->monstring);
X    }
X    else strcpy(Str2,m->monstring);
X    strcat(Str2," emits an irritating humming sound.");
X    mprint(Str2);
X    aggravate();
X    m_status_reset(m,HOSTILE);
X  }
X}
X
X
X
Xvoid m_sp_merchant(m)
Xstruct monster *m;
X{
X  pml ml;
X  if (m_statusp(m,HOSTILE))
X    if (Current_Environment == E_VILLAGE) {
X      mprint("The merchant screams: 'Help! Murder! Guards! Help!'");
X      mprint("You hear the sound of police whistles and running feet.");
X      for (ml=Level->mlist;ml!=NULL;ml=ml->next) {
X	m_status_set(ml->m,AWAKE);
X	m_status_set(ml->m,HOSTILE);
X      }
X      m->specialf = M_NO_OP;
X    }
X}
X
X/* The special function of the various people in the court of the archmage */
X/* and the sorcerors' circle */
Xvoid m_sp_court(m)
Xstruct monster *m;
X{
X  pml ml;
X  if (m_statusp(m,HOSTILE)) {
X    mprint("A storm of spells hits you!");
X    for(ml=Level->mlist;ml!=NULL;ml=ml->next) {
X      m_status_set(ml->m,HOSTILE);
X      m_sp_spell(ml->m);
X      if (ml->m->specialf == M_SP_COURT)
X	ml->m->specialf = M_SP_SPELL;
X    }
X  }
X}
X
X
X/* The special function of the dragons in the dragons' lair */
Xvoid m_sp_lair(m)
Xstruct monster *m;
X{
X  pml ml;
X  if (m_statusp(m,HOSTILE)) {
X    if (m->id == ML10+3) m->specialf = M_SP_DRAGONLORD;
X    mprint("You notice a number of dragons waking up....");
X    mprint("You are struck by a quantity of firebolts.");
X    for(ml=Level->mlist;ml!=NULL;ml=ml->next) {
X      m_status_set(ml->m,HOSTILE);
X      fbolt(ml->m->x,ml->m->y,Player.x,Player.y,100,100);
X      if (ml->m->specialf == M_SP_LAIR)
X	ml->m->specialf = M_STRIKE_FBOLT;
X    }
X  }
X}
X
X
Xvoid m_sp_prime(m)
Xstruct monster *m;
X{
X  if (m_statusp(m,HOSTILE)) {
X    mprint("The prime sorceror gestures and a pentacular gate opens!");
X    mprint("You are surrounded by demons!");
X    summon(-1,ML9+7);
X    summon(-1,ML9+7);
X    summon(-1,ML9+7);
X    summon(-1,ML9+7);
X  }
X  m->specialf = M_SP_SPELL;
X}
END_OF_FILE
if test 18439 -ne `wc -c <'omspec.c'`; then
    echo shar: \"'omspec.c'\" unpacked with wrong size!
fi
# end of 'omspec.c'
fi
if test -f 'otime.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'otime.c'\"
else
echo shar: Extracting \"'otime.c'\" \(2394 characters\)
sed "s/^X//" >'otime.c' <<'END_OF_FILE'
X/* omega copyright (c) 1987,1988,1989 by Laurence Raphael Brothers */
X/* otime.c */
X
X/* this file deals with the passage of time in omega */
X
X#include "oglob.h"
X
X/* This function coordinates monsters and player actions, as well as
Xrandom events. Each tick is a second. There are therefore 60 ticks to
Xthe minute and 60 minutes to the hour.
X*/
X
Xvoid time_clock(reset)
Xint reset;
X{
X  pml ml;
X
X  if (++Tick > 60) {
X    Tick = 0;
X    minute_status_check(); /* see about some player statuses each minute */
X    if (++Time % 10 == 0) tenminute_check();
X  }
X  
X  if (reset) Tick = (Player.click = 0);
X
X  while ((Tick == Player.click) && (Current_Environment != E_COUNTRYSIDE)) {
X    if (! gamestatusp(SKIP_PLAYER))
X      do {
X	resetgamestatus(SKIP_MONSTERS);
X	if ((! Player.status[SLEPT])  && 
X	    (Current_Environment != E_COUNTRYSIDE)) p_process(); 
X      } while (gamestatusp(SKIP_MONSTERS) && 
X	       (Current_Environment != E_COUNTRYSIDE));
X    else resetgamestatus(SKIP_PLAYER);
X    Player.click = (Player.click + Command_Duration) % 60;
X  }
X
X  /* klugy but what the heck. w/o this line, if the player caused
X  a change-environment to the country, the monsters on the old Level
X  will still act, causing all kinds of anomalies and core dumps,
X  intermittently. However, any other environment change will reset
X  Level appropriately, so only have to check for countryside */
X
X  if (Current_Environment != E_COUNTRYSIDE) {
X
X    /* no longer search for dead monsters every round -- waste of time.
X     Instead, just skip dead monsters. Eventually, the whole level
X     will be freed, getting rid of the dead 'uns */
X
X    for(ml=Level->mlist;ml!=NULL;ml=ml->next) 
X      if (ml->m->hp > 0) {
X
X	/* following is a hack until I discover source of phantom monsters */
X	if (Level->site[ml->m->x][ml->m->y].creature != ml->m)
X	  fix_phantom(ml->m); 
X
X	if (Tick == ml->m->click) {
X	  ml->m->click += ml->m->speed;
X	  while (ml->m->click > 60) ml->m->click -= 60;
X	  m_pulse(ml->m);
X	}
X      }
X  }
X}
X
X
X
X
X
X/* remedies occasional defective monsters */
Xvoid fix_phantom(m)
Xstruct monster *m;
X{
X  if (Level->site[m->x][m->y].creature == NULL) {
X    mprint("You hear a sound like a sigh of relief....");
X    Level->site[m->x][m->y].creature = m;
X  }
X  else {
X    mprint("You hear a puff of displaced air....");
X    findspace(&(m->x),&(m->y),-1);
X    Level->site[m->x][m->y].creature = m;
X    m_death(m);
X  }
X}
END_OF_FILE
if test 2394 -ne `wc -c <'otime.c'`; then
    echo shar: \"'otime.c'\" unpacked with wrong size!
fi
# end of 'otime.c'
fi
echo shar: End of archive 7 \(of 20\).
cp /dev/null ark7isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 20 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0