/* find apt char to display at some location */ Symbol getspot(int x, int y, int showmonster) { #ifdef CENTER_ON_PLAYER /* funny scrolling may cause this. PGM */ if (!inbounds(x,y ) ) { return SPACE; } #endif if (loc_statusp(x,y,SECRET)) { if ( Level->site[x][y].roomnumber == RS_DRUID ) return(HEDGE); /* secret doors in druid temple are brambles -DAG */ else return(WALL); } else switch (Level->site[x][y].locchar) { case WATER: if (Level->site[x][y].creature == NULL) return(WATER); else if (m_statusp(Level->site[x][y].creature,SWIMMING)) return(WATER); else if (showmonster) return(Level->site[x][y].creature->monchar); else return(WATER); /* these sites never show anything but their location char's */ case CLOSED_DOOR: case LAVA: case FIRE: case ABYSS: return(Level->site[x][y].locchar); /* rubble and hedge don't show items on their location */ case RUBBLE: case HEDGE: if (showmonster && (Level->site[x][y].creature != NULL)) { if ((m_statusp(Level->site[x][y].creature,M_INVISIBLE)) && (! Player.status[TRUESIGHT])) return(getspot(x,y,FALSE)); else return (Level->site[x][y].creature->monchar); } else return(Level->site[x][y].locchar); /* everywhere else, first try to show monster, next show items, next show location char */ default: if (showmonster && (Level->site[x][y].creature != NULL)) { if ((m_statusp(Level->site[x][y].creature,M_INVISIBLE)) && (! Player.status[TRUESIGHT])) return(getspot(x,y,FALSE)); else return (Level->site[x][y].creature->monchar); } else if (Level->site[x][y].things != NULL) { if (Level->site[x][y].things->next != NULL) return(PILE); else return(Level->site[x][y].things->thing->objchar); } else return(Level->site[x][y].locchar); } }
void m_lava(struct monster *m) { char Str1[80]; if(!m_immunityp(m, FLAME) || (!m_statusp(m, SWIMMING) && !m_statusp(m, ONLYSWIM))) { if(los_p(m->x, m->y, Player.x, Player.y)) { if(m->uniqueness != COMMON) { strcpy(Str1, m->monstring); } else { strcpy(Str1, "The "); strcat(Str1, m->monstring); } strcat(Str1, " died in a pool of lava!"); mprint(Str1); } m_death(m); } }
void m_water(struct monster *m) { char Str1[80]; if(!m_statusp(m, INTANGIBLE) && !m_statusp(m, SWIMMING) && !m_statusp(m, ONLYSWIM)) { if(los_p(m->x, m->y, Player.x, Player.y)) { if(m->uniqueness != COMMON) { strcpy(Str1, m->monstring); } else { strcpy(Str1, "The "); strcat(Str1, m->monstring); } strcat(Str1, " drowned!"); mprint(Str1); } m_death(m); } }
/* if display, displays monsters, otherwise erases them */ void drawmonsters(int display) { pml ml; for (ml=Level->mlist;ml!=NULL;ml=ml->next) { if (ml->m->hp > 0) { if (display) { if (view_los_p(Player.x,Player.y,ml->m->x,ml->m->y)) { if (Player.status[TRUESIGHT] || (! m_statusp(ml->m,M_INVISIBLE))) { if (!optionp(SHOW_COLOUR) && (ml->m->level > 5) && ((ml->m->monchar&0xff) != '@') && ((ml->m->monchar&0xff) != '|')) wstandout(Levelw); putspot(ml->m->x,ml->m->y,ml->m->monchar); if (!optionp(SHOW_COLOUR)) wstandend(Levelw); } } } else erase_monster(ml->m); } } }
void m_trap_snare(struct monster *m) { char Str1[80]; Level->site[m->x][m->y].locchar = TRAP; if(los_p(m->x, m->y, Player.x, Player.y)) { if(m->uniqueness != COMMON) { strcpy(Str1, m->monstring); } else { strcpy(Str1, "The "); strcat(Str1, m->monstring); } strcat(Str1, " was caught in a snare!"); mprint(Str1); } if(!m_statusp(m, INTANGIBLE)) { m_status_reset(m, MOBILE); } }
void m_trap_pit(struct monster *m) { if(los_p(m->x, m->y, Player.x, Player.y)) { if(m->uniqueness != COMMON) { strcpy(Str1, m->monstring); } else { strcpy(Str1, "The "); strcat(Str1, m->monstring); } strcat(Str1, " fell into a pit!"); mprint(Str1); Level->site[m->x][m->y].locchar = TRAP; } if(!m_statusp(m, INTANGIBLE)) { m_status_reset(m, MOBILE); } m_damage(m, difficulty() * 5, NORMAL_DAMAGE); }
/* Consider one monster's action */ void m_pulse(struct monster *m) { int range = distance(m->x, m->y, Player.x, Player.y); if(Time % 10 == 0) { if(m->hp < Monsters[m->id].hp) { ++m->hp; } } if(!m_statusp(m, AWAKE) && (range <= m->wakeup)) { m_status_set(m, AWAKE); resetgamestatus(FAST_MOVE); } if(m_statusp(m, AWAKE)) { if(m_statusp(m, WANDERING)) { if(m_statusp(m, MOBILE)) { m_random_move(m); } if(range <= m->sense) { m_status_reset(m, WANDERING); } } else { /* Not wandering */ if(m_statusp(m, HOSTILE)) { if((range > 2) && (range < m->sense) && (random_range(2) == 1)) { if(los_p(m->x, m->y, Player.x, Player.y) && (Player.status[INVISIBLE] == 0)) { monster_strike(m); } } } if((m_statusp(m, HOSTILE) || m_statusp(m, NEEDY)) && (range > 1) && m_statusp(m, MOBILE)) { monster_move(m); /* If monster is greedy, picks up treasure it finds */ if(m_statusp(m, GREEDY)) { while(Level->site[m->x][m->y].things != NULL) { m_pickup(m, Level->site[m->x][m->y].things->thing); Level->site[m->x][m->y].things = Level->site[m->x][m->y].things->next; } } } if(m_statusp(m, HOSTILE) && (range == 1)) { resetgamestatus(FAST_MOVE); tacmonster(m); } } /* Prevents monsters form casting spells from other side of dungeon */ if(range < max(5, m->level)) { monster_special(m); } } }
void make_corpse(Object* newObject, Monster* m) { *newObject = Objects[CORPSEID]; newObject->charge = m->id; newObject->weight = m->corpseWeight; newObject->basevalue = m->corpseValue; newObject->known = 2; newObject->objstr = m->corpseString; newObject->truename = newObject->cursestr = newObject->objstr; if ( m_statusp(m, ALLOC ) ) { /* DAG we are keeping the corpseString here, can free name */ /* later, should track this in the object as well, as this */ /* is still a memory leak (though smaller than before) */ free ( (char *)m->name ); m->name = Monsters[m->id].name; m->corpseString = Monsters[m->id].corpseString; m_status_reset( m, ALLOC ); /* DAG level not otherwise used for corpses. Use to hold ALLOC info. */ newObject->level |= ALLOC; } /* DG I_CANNIBAL not implemented... fall through to code in I_CORPSE */ /* WDT HACK, of course -- we need to implement I_CANNIBAL. */ #if 0 if ((m->symbol&0xff) == '@') newObject->usef = I_CANNIBAL; else #endif if (m_statusp(m,EDIBLE)) { newObject->usef = I_FOOD; newObject->aux = 6; } else if (m_statusp(m,POISONOUS)) newObject->usef = I_POISON_FOOD; /* Special corpse-eating effects */ else switch(m->id) { case TSETSE: /*tse tse fly */ case TORPOR: /*torpor beast */ newObject->usef = I_SLEEP_SELF; break; case NASTY: newObject->usef = I_INVISIBLE; break; case BLIPPER: newObject->usef = I_TELEPORT; break; case EYE: /* floating eye -- it's traditional.... */ newObject->usef = I_CLAIRVOYANCE; break; case FUZZY: /*astral fuzzy */ newObject->usef = I_DISPLACE; break; case SERV_LAW: newObject->usef = I_CHAOS; break; case SERV_CHAOS: newObject->usef = I_LAW; break; case ASTRAL_VAMP: /* astral vampire */ newObject->usef = I_ENCHANT; break; case MANABURST: newObject->usef = I_SPELLS; break; case RAKSHASA: newObject->usef = I_TRUESIGHT; break; /* DG fall through to code in I_CORPSE and special case there */ #if 0 /* WDT HACK? */ case BEHEMOTH: newObject->usef = I_HEAL; break; case UNICORN: newObject->usef = I_NEUTRALIZE_POISON; break; #endif case COMA: /*coma beast */ newObject->usef = I_ALERT; break; /* DG I_INEDIBLE not implemented... fall through to code in I_CORPSE */ #if 0 /* WDT HACK: yawn. */ default: newObject->usef = I_INEDIBLE; break; #endif } }