/* undead are not hostile unless disturbed.... */ void make_major_undead(int i, int j) { int mid; if (random_range(2)) mid = LICHE; /* lich */ else mid = VAMP_LORD; /*vampire lord*/ make_site_monster(i,j,mid); m_status_reset(Level->site[i][j].creature,AWAKE); m_status_reset(Level->site[i][j].creature,HOSTILE); }
/* undead are not hostile unless disturbed.... */ void make_minor_undead(int i, int j) { int mid; if (random_range(2)) mid = GHOST; else mid = HAUNT; make_site_monster(i,j,mid); m_status_reset(Level->site[i][j].creature,AWAKE); m_status_reset(Level->site[i][j].creature,HOSTILE); }
void pacify_guards(void) { pml ml; for(ml=Level->mlist; ml!=NULL; ml=ml->next) if ((ml->m->id == GUARD) || /*guard*/ ((ml->m->id == HISCORE_NPC) && (ml->m->aux2 == 15))) {/* justiciar */ m_status_reset(ml->m,HOSTILE); ml->m->specialf = M_NO_OP; if (ml->m->id == GUARD && ml->m->hp > 0 && ml->m->aux1 > 0) { if (Level->site[ml->m->x][ml->m->y].creature == ml->m) Level->site[ml->m->x][ml->m->y].creature = NULL; ml->m->x = ml->m->aux1; ml->m->y = ml->m->aux2; Level->site[ml->m->x][ml->m->y].creature = ml->m; } else if (ml->m->id == HISCORE_NPC && ml->m->hp > 0 && Current_Environment == E_CITY) { if (Level->site[ml->m->x][ml->m->y].creature == ml->m) Level->site[ml->m->x][ml->m->y].creature = NULL; ml->m->x = 40; ml->m->y = 62; Level->site[ml->m->x][ml->m->y].creature = ml->m; } } if (Current_Environment == E_CITY) Level->site[40][60].p_locf = L_ORDER; /* undoes action in alert_guards */ }
/* makes a log npc for houses and hovels */ void make_house_npc(int i, int j) { pml ml = ((pml) checkmalloc(sizeof(mltype))); pob ob; ml->m = ((pmt) checkmalloc(sizeof(montype))); *(ml->m) = Monsters[NPC]; make_log_npc(ml->m); if (ml->m->id == NPC) mprint("You detect signs of life in this house."); else mprint("An eerie shiver runs down your spine as you enter...."); /* if not == NPC, then we got a ghost off the npc list */ ml->m->x = i; ml->m->y = j; Level->site[i][j].creature = ml->m; ml->m->click = (Tick + 1) % 50; ml->next = Level->mlist; Level->mlist = ml; m_status_set(ml->m,HOSTILE); if (nighttime()) m_status_reset(ml->m,AWAKE); else m_status_set(ml->m,AWAKE); if (ml->m->startthing > -1) { ob = ((pob) checkmalloc(sizeof(objtype))); *ob = Objects[ml->m->startthing]; m_pickup(ml->m,ob); } }
void weapon_tangle(int dmgmod, pob o, pmt m) { if ((random_range(2) == 1) && (! m_immunityp(m,NORMAL_DAMAGE))) { mprint("You entangle the monster!"); m_status_reset(m,MOBILE); } p_hit(m,Player.dmg+dmgmod,NORMAL_DAMAGE); }
void weapon_acidwhip(int dmgmod, Object* o, Monster* m) { if ((random_range(2) == 1) && (! m_immunityp(m,NORMAL_DAMAGE))) { mprint("You entangle the monster!"); m_status_reset(m,MOBILE); } p_hit(m,Player.dmg+dmgmod,ACID); }
/* makes a hiscore npc for mansions */ void make_justiciar(int i, int j) { pml ml = ((pml) checkmalloc(sizeof(mltype))); ml->m = ((pmt) checkmalloc(sizeof(montype))); *(ml->m) = Monsters[NPC]; make_hiscore_npc(ml->m,15); ml->m->x = i; ml->m->y = j; Level->site[i][j].creature = ml->m; ml->m->click = (Tick + 1) % 60; ml->next = Level->mlist; Level->mlist = ml; m_status_reset(ml->m,AWAKE); }
/* makes a hiscore npc for mansions */ void make_mansion_npc(int i, int j) { pml ml = ((pml) checkmalloc(sizeof(mltype))); ml->m = ((pmt) checkmalloc(sizeof(montype))); *(ml->m) = Monsters[NPC]; make_hiscore_npc(ml->m,random_range(14) + 1); mprint("You detect signs of life in this house."); ml->m->x = i; ml->m->y = j; Level->site[i][j].creature = ml->m; ml->m->click = (Tick + 1) % 50; ml->next = Level->mlist; Level->mlist = ml; m_status_set(ml->m,HOSTILE); if (nighttime()) m_status_reset(ml->m,AWAKE); else m_status_set(ml->m,AWAKE); }
void m_trap_sleepgas(struct monster *m) { char Str1[80]; 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, " walked into a sleepgas trap!"); mprint(Str1); Level->site[m->x][m->y].locchar = TRAP; } if(!m_immunityp(m, SLEEP)) { m_status_reset(m, AWAKE); } }
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); }
/* Has all kinds of effects in different circumstances. Eventually will be more interesting */ void s_ritual(void) { pob symbol; int i,roomno; int x,y; mprint("You begin your ritual...."); mprint("You enter a deep trance. Time Passes..."); setgamestatus(SKIP_PLAYER); time_clock(FALSE); setgamestatus(SKIP_PLAYER); time_clock(FALSE); setgamestatus(SKIP_PLAYER); time_clock(FALSE); setgamestatus(SKIP_PLAYER); time_clock(FALSE); setgamestatus(SKIP_PLAYER); time_clock(FALSE); if (RitualHour == hour()) mprint("Your mental fatigue prevents from completing the ritual!"); else if (random_range(100) > Player.iq+Player.pow+Player.level) mprint("Your concentration was broken -- the ritual fails!"); else { mprint("You charge the ritual with magical energy and focus your will."); mprint("Time Passes..."); setgamestatus(SKIP_PLAYER); time_clock(FALSE); setgamestatus(SKIP_PLAYER); time_clock(FALSE); setgamestatus(SKIP_PLAYER); time_clock(FALSE); setgamestatus(SKIP_PLAYER); time_clock(FALSE); setgamestatus(SKIP_PLAYER); time_clock(FALSE); RitualHour = hour(); /* set of random conditions for different ritual effects */ if (Current_Environment == E_CITY) { mprint("Flowing waves of mystical light congeal all around you."); mprint("'Like wow, man! Colors!'"); mprint("Appreciative citizens throw you spare change."); Player.cash +=random_range(50); } else if ( (roomno=Level->site[Player.x][Player.y].roomnumber) >= ROOMBASE ) { if (RitualRoom == roomno) mprint("For some reason the ritual doesn't work this time..."); else { RitualRoom = roomno; switch (RitualRoom) { case RS_TREASURE: /* ransacked treasure chamber */ mprint("Your spell sets off frenetic growth all around you!"); for(i=0; i<8; i++) { Level->site[Player.x+Dirs[0][i]][Player.y+Dirs[1][i]].locchar = HEDGE; Level->site[Player.x+Dirs[0][i]][Player.y+Dirs[1][i]].p_locf = L_TRIFID; lset(Player.x+Dirs[0][i], Player.y+Dirs[1][i], CHANGED); } break; case RS_HAREM: /* harem */ case RS_BOUDOIR: /* boudoir */ mprint("A secret panel opens next to the bed...."); if (random_range(2)) summon(0,INCUBUS); /* succubus/incubus */ else summon(0,SATYR); /* satyr/nymph */ break; case RS_SHRINE: /*shrine to high magic */ mprint("A storm of mana coaelesces around you."); mprint("You are buffeted by bursts of random magic."); p_damage(random_range(Player.pow),UNSTOPPABLE,"high magic"); mprint("Continue ritual? Could be dangerous.... [yn] "); if (ynq()=='y') s_wish(); else mprint("The mana fades away to nothingness."); x = Player.x; y = Player.y; while (x >= 0 && Level->site[x - 1][y].roomnumber == RS_SHRINE) x--; while (y >= 0 && Level->site[x][y - 1].roomnumber == RS_SHRINE) y--; for (i = 0; Level->site[x][y].roomnumber == RS_SHRINE;) { Level->site[x][y].roomnumber = RS_ZORCH; lset(x, y, CHANGED); x++; i++; if (Level->site[x][y].roomnumber != RS_SHRINE) { x -= i; i = 0; y++; } } break; case RS_MAGIC_LAB: /* magician's lab */ mprint("Your magical activity sets off a latent spell in the lab!"); cast_spell(random_range(NUMSPELLS)); break; case RS_PENTAGRAM: /* pentagram room */ mprint("A smoky form begins to coalesce...."); summon(-1,-1); mprint("Fortunately, it seems confined to the pentagram."); m_status_reset(Level->mlist->m,MOBILE); break; case RS_OMEGA_DAIS: /* blue omega room */ mprint("The Lords of Destiny look upon you...."); if (Player.level > 10) { mprint("A curtain of blue flames leaps up from the omega."); morewait(); l_adept(); } else { if (Player.patron == DESTINY) { mprint("Your patrons take pity on you."); if ((Player.rank[PRIESTHOOD]<SPRIEST) && (! find_item(&symbol,OB_SYMBOL_DESTINY,-1))) { symbol = ((pob) checkmalloc(sizeof(objtype))); *symbol = Objects[OB_SYMBOL_DESTINY]; symbol->known = 2; symbol->charge = 17; gain_item(symbol); mprint("You feel uplifted."); } else gain_experience(min(1000,Player.xp)); } else if (random_range(3)==1) { mprint("You feel Fated."); gain_experience(Player.level*Player.level*10); Player.hp = max(Player.hp, Player.maxhp); } else if (random_range(2)) { mprint("You feel Doomed."); Player.hp = 1; Player.mana = 0; Player.xp = 0; } else mprint("The Lords of Destiny laugh at you!"); } break; default: mprint("Well, not much effect. Chalk it up to experience."); gain_experience(Player.level*5); break; } } } else { if (RitualRoom == Level->site[Player.x][Player.y].roomnumber) mprint("The ritual fails for some unexplainable reason."); else { mprint("The ritual seems to be generating some spell effect."); RitualRoom = Level->site[Player.x][Player.y].roomnumber; switch (RitualRoom) { case RS_WALLSPACE: shadowform(); break; case RS_CORRIDOR: haste(0); break; case RS_PONDS: breathe(0); break; case RS_ADEPT: hero(1); break; default: mprint("The ritual doesn't seem to produce any tangible results..."); gain_experience(Player.level*6); } } } } }
/* loads the city level */ void load_city(int populate) { int i,j; pml ml; char site; map *city; map *maze; initrand(E_CITY, 0); /* Get the hedge maze (which is in the city). */ maze = map_open(MAP_hedges); /* Choose a random level from it. */ map_setLevel(maze, random_range(map_getDepth(maze))); /* Get the city. */ city = map_open(MAP_city); map_setLevel(city,0); TempLevel = Level; if (ok_to_free(TempLevel)) { #ifndef SAVE_LEVELS free_level(TempLevel); #endif TempLevel = NULL; } #ifndef SAVE_LEVELS Level = ((plv) checkmalloc(sizeof(levtype))); #else msdos_changelevel(TempLevel,0,-1); Level = &TheLevel; #endif clear_level(Level); Level->depth = 0; Level->environment = E_CITY; /* WDT: Rampart, as a special case, has its width stored in a * global variable. */ WIDTH = Level->level_width = map_getWidth(city); LENGTH = Level->level_length = map_getLength(city); for(j=0; j<Level->level_length; j++) { for(i=0; i<Level->level_width; i++) { lset(i,j,SEEN); site = map_getSiteChar(city,i,j); switch(site) { /* case '@': Player.x = i; Player.y = j; Level->site[i][j].locchar = FLOOR; break; */ case 'g': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_GARDEN; break; case 'y': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_CEMETARY; break; case 'p': /* WDT: each of these places needs to be assigned * a function (or replaced with an 'x' in the map) */ case '!': case 'I': case 'E': case 'e': case 'x': assign_city_function(i,j); break; case 't': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_TEMPLE; CitySiteList[L_TEMPLE-CITYSITEBASE][0] = TRUE; CitySiteList[L_TEMPLE-CITYSITEBASE][1] = i; CitySiteList[L_TEMPLE-CITYSITEBASE][2] = j; break; #if 0 /* WDT: HACK! The new city doesn't use portcullis traps, but has other * uses for 'T'. Um... I'd rather have a use for them (that's what * the jail is supposed to be), so this will stay only for now; with * any luck we'll have things fixed up before the next release. */ case 'T': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_PORTCULLIS_TRAP; Level->site[i][j].aux = NOCITYMOVE; break; #endif /* end of hack */ case 'R': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_RAISE_PORTCULLIS; Level->site[i][j].aux = NOCITYMOVE; break; case '7': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_PORTCULLIS; Level->site[i][j].aux = NOCITYMOVE; break; case 'C': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_COLLEGE; CitySiteList[L_COLLEGE-CITYSITEBASE][0] = TRUE; CitySiteList[L_COLLEGE-CITYSITEBASE][1] = i; CitySiteList[L_COLLEGE-CITYSITEBASE][2] = j; break; case 's': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_SORCERORS; CitySiteList[L_SORCERORS-CITYSITEBASE][0] = TRUE; CitySiteList[L_SORCERORS-CITYSITEBASE][1] = i; CitySiteList[L_SORCERORS-CITYSITEBASE][2] = j; break; case 'M': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_MERC_GUILD; CitySiteList[L_MERC_GUILD-CITYSITEBASE][0] = TRUE; CitySiteList[L_MERC_GUILD-CITYSITEBASE][1] = i; CitySiteList[L_MERC_GUILD-CITYSITEBASE][2] = j; break; case 'K': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_MONASTERY; CitySiteList[L_MONASTERY-CITYSITEBASE][0] = TRUE; CitySiteList[L_MONASTERY-CITYSITEBASE][1] = i; CitySiteList[L_MONASTERY-CITYSITEBASE][2] = j; break; case 'c': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_CASTLE; CitySiteList[L_CASTLE-CITYSITEBASE][0] = TRUE; CitySiteList[L_CASTLE-CITYSITEBASE][1] = i; CitySiteList[L_CASTLE-CITYSITEBASE][2] = j; break; case '?': { static int myI = -1, myJ; char site; if ( myI == -1 ) { /* If this is the first time we've seen the hedge maze, * set this as its corner. */ myI = i; myJ = j; } site = map_getSiteChar(maze, i - myI, j - myJ); mazesite(site,i,j,populate); } break; case 'P': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_ORDER; CitySiteList[L_ORDER-CITYSITEBASE][0] = TRUE; CitySiteList[L_ORDER-CITYSITEBASE][1] = i; CitySiteList[L_ORDER-CITYSITEBASE][2] = j; break; case 'H': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_CHARITY; CitySiteList[L_CHARITY-CITYSITEBASE][0] = TRUE; CitySiteList[L_CHARITY-CITYSITEBASE][1] = i; CitySiteList[L_CHARITY-CITYSITEBASE][2] = j; break; case 'h': Level->site[i][j].locchar = FLOOR; if (populate) make_horse(i,j); /* from village.c */ break; case 'j': Level->site[i][j].locchar = FLOOR; if (populate) make_justiciar(i,j); break; case 'J': Level->site[i][j].locchar = CLOSED_DOOR; Level->site[i][j].p_locf = L_JAIL; break; case 'A': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_ARENA; CitySiteList[L_ARENA-CITYSITEBASE][0] = TRUE; CitySiteList[L_ARENA-CITYSITEBASE][1] = i; CitySiteList[L_ARENA-CITYSITEBASE][2] = j; break; case 'B': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_BANK; CitySiteList[L_BANK-CITYSITEBASE][0] = TRUE; CitySiteList[L_BANK-CITYSITEBASE][1] = i; CitySiteList[L_BANK-CITYSITEBASE][2] = j; lset(i,j,STOPS); lset(i,j+1,STOPS); lset(i+1,j,STOPS); lset(i-1,j,STOPS); lset(i,j-1,STOPS); break; case 'i': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_TOURIST; CitySiteList[L_TOURIST-CITYSITEBASE][1] = i; CitySiteList[L_TOURIST-CITYSITEBASE][2] = j; lset(i,j,STOPS); lset(i,j+1,STOPS); lset(i+1,j,STOPS); lset(i-1,j,STOPS); lset(i,j-1,STOPS); break; case 'X': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_COUNTRYSIDE; CitySiteList[L_COUNTRYSIDE-CITYSITEBASE][0] = TRUE; CitySiteList[L_COUNTRYSIDE-CITYSITEBASE][1] = i; CitySiteList[L_COUNTRYSIDE-CITYSITEBASE][2] = j; break; case 'v': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_VAULT; Level->site[i][j].aux = NOCITYMOVE; lset(i,j,SECRET); break; case 'S': Level->site[i][j].locchar = FLOOR; Level->site[i][j].aux = NOCITYMOVE; lset(i,j,SECRET); break; case 'G': Level->site[i][j].locchar = FLOOR; if (populate) { make_site_monster(i,j,GUARD); Level->site[i][j].creature->aux1 = i; Level->site[i][j].creature->aux2 = j; } break; case 'u': Level->site[i][j].locchar = FLOOR; if (populate) make_minor_undead(i,j); break; case 'U': Level->site[i][j].locchar = FLOOR; if (populate) make_major_undead(i,j); break; case 'V': Level->site[i][j].showchar = WALL; Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_VAULT; if (populate) make_site_treasure(i,j,5); Level->site[i][j].aux = NOCITYMOVE; lset(i,j,SECRET); break; case '%': Level->site[i][j].showchar = WALL; Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_TRAP_SIREN; if (populate) make_site_treasure(i,j,5); Level->site[i][j].aux = NOCITYMOVE; lset(i,j,SECRET); break; case '$': Level->site[i][j].locchar = FLOOR; if (populate) make_site_treasure(i,j,5); break; case '2': Level->site[i][j].locchar = ALTAR; Level->site[i][j].p_locf = L_ALTAR; Level->site[i][j].aux = ODIN; break; case '3': Level->site[i][j].locchar = ALTAR; Level->site[i][j].p_locf = L_ALTAR; Level->site[i][j].aux = SET; break; case '4': Level->site[i][j].locchar = ALTAR; Level->site[i][j].p_locf = L_ALTAR; Level->site[i][j].aux = ATHENA; break; case '5': Level->site[i][j].locchar = ALTAR; Level->site[i][j].p_locf = L_ALTAR; Level->site[i][j].aux = HECATE; break; case '6': Level->site[i][j].locchar = ALTAR; Level->site[i][j].p_locf = L_ALTAR; Level->site[i][j].aux = DESTINY; break; case '^': Level->site[i][j].showchar = WALL; Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = TRAP_BASE+random_range(NUMTRAPS); lset(i,j,SECRET); break; case '"': Level->site[i][j].locchar = HEDGE; break; case '~': Level->site[i][j].locchar = WATER; Level->site[i][j].p_locf = L_WATER; break; case '=': Level->site[i][j].locchar = WATER; Level->site[i][j].p_locf = L_MAGIC_POOL; break; case '*': Level->site[i][j].locchar = WALL; Level->site[i][j].aux = 10; break; case '#': Level->site[i][j].locchar = WALL; Level->site[i][j].aux = 500; break; case 'T':/* currently meaningless in large city map. */ case '>': /* currently meaningless outside of maze.*/ case '.': Level->site[i][j].locchar = FLOOR; break; case ',': Level->site[i][j].showchar = WALL; Level->site[i][j].locchar = FLOOR; Level->site[i][j].aux = NOCITYMOVE; lset(i,j,SECRET); break; case '-': case 'D': /* WDT: should all Ds be changed to -, or should D be given * special treatment? */ Level->site[i][j].locchar = CLOSED_DOOR; break; case '1': Level->site[i][j].locchar = STATUE; break; default: printf("\nOops... missed a case [%d,%d]: '%c' (%d)\n", i,j,site,site); morewait(); } if (loc_statusp(i,j,SEEN)) { if (loc_statusp(i,j,SECRET)) Level->site[i][j].showchar = WALL; else Level->site[i][j].showchar = Level->site[i][j].locchar; } } } map_close(maze); map_close(city); City = Level; /* make all city monsters asleep, and shorten their wakeup range to 2 */ /* to prevent players from being molested by vicious monsters on */ /* the streets */ for(ml=Level->mlist; ml!=NULL; ml=ml->next) { m_status_reset(ml->m,AWAKE); ml->m->wakeup = 2; } initrand(E_RESTORE, 0); }
/* 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 m_death(struct monster *m) { pob corpse; pml ml; int x; int y; int found = FALSE; m->hp = -1; if(los_p(Player.x, Player.y, m->x, m->y)) { putspot(m->x, m->y, getspot(m->x, m->y, FALSE)); gain_experience(m->xpv); calc_melee(); if(m->uniqueness != COMMON) { strcpy(Str1, m->monstring); } else { strcpy(Str1, "The "); strcat(Str1, m->monstring); } strcat(Str1, " is dead!"); mprint(Str1); } m_dropstuff(m); /* Death */ if(m->id == (ML10 + 0)) { mprint("Death lies sprawled out on the ground..."); mprint("Death laughs ironically and gets back to his feet."); mprint("He gestures and another scythe appears in his hands."); switch(random_range(10)) { case 0: mprint("Death performs a little bow and goes back on guard."); break; case 1: mprint("\'A hit! A palpable hit!\' Death goes back on the attack."); break; case 2: mprint("\'Ah, if only it could be so simple!\' snickers Death."); break; case 3: mprint("\'This fool things he can slay death! What a jest!\' says Death."); break; case 4: mprint("\'You point is well taken.\' says Death, attacking again."); break; case 5: mprint("\'Oh, come now, stop delaying the inevitable.\' says Death."); break; case 6: mprint("\'Your destiny ends here with me.\' says Death, scythe raised."); break; case 7: mprint("\'I almost felt that.\' says Death, smiling."); break; case 8: mprint("\'Timeo Mortis?\' asks Death quizzically, \'Not me!\'"); break; case 9: mprint("Death sighs theatrically. \'They never learn.\'"); break; } strengthen_death(m); } else { Level->site[m->x][m->y].creature = NULL; if(random_range(2) || (m->uniqueness != COMMON)) { corpse = (pob)malloc(sizeof(objtype)); make_corpse(corpse, m); drop_at(m->x, m->y, corpse); } plotspot(m->x, m->y, FALSE); switch(m->id) { case ML0 + 8: /* Hiscore NPC */ switch(m->aux2) { case 0: mprint("You hear a faroff dirge. You feel a sense of triumph."); break; case 1: case 2: case 3: case 4: case 5: case 6: mprint("You hear a faroff sound like angels crying..."); strcpy(Priest[1], nameprint()); Priestbehavior[1] = 2933; break; case 7: mprint("A furtive figure dashes out of the shadows, takes a look at"); mprint("the corpse, and runs away!"); strcpy(Shadowlord, nameprint()); Shadowlordbehavior = 2912; break; case 8: mprint("An aide-de-camp approaches, removes the corpse's insignia,"); mprint("and departs."); strcpy(Commandant, nameprint()); Commandantbehavior = 2912; break; case 9: mprint("An odd glow surrounds the corpse, and slowly fades."); strcpy(Archmage, nameprint()); Archmagebehavior = 2933; break; case 10: mprint("A demon materializes, takes a quick look at the corpse,"); mprint("and teleports away with a faint popping noise."); strcpy(Prime, nameprint()); Primebehavior = 2932; break; case 11: mprint("A sports columnist rushes forward and takes a quick photo"); mprint("of the corpse and rushes off muttering about a deadline."); strcpy(Champion, nameprint()); Championbehavior = 2913; break; case 12: mprint("You hear a fanfare in the distance, and feel dismayed."); strcpy(Duke, nameprint()); Dukebehavior = 2911; break; case 13: if(Player.alignment > 10) { mprint("You feel smug."); } else if(Player.alignment < 10) { mprint("You feel ashamed."); } strcpy(Chaoslord, nameprint()); Chaoslordbehavior = 2912; break; case 14: if(Player.alignment < 10) { mprint("You feel smug."); } else if(Player.alignment > 10) { mprint("You feel ashamed."); } strcpy(Lawlord, nameprint()); Lawlordbehavior = 2911; break; case 15: /* * Just a tad complicated. Promote a new justiciar if * an guards are left in the city, otherwise destroy * the Order! */ Player.alignment -= 100; if(!gamestatusp(DESTROYED_ORDER)) { mprint("In the distance you hear a trumpet. A Servent of Law"); mprint("materializes, sheds a tear, and leaves."); strcpy(Justiciar, nameprint()); Justiciarbehavior = 2911; /* Promote one of the city guards to be justiciar */ ml = City->mlist; while(!found && (ml != NULL)) { if((ml->m->id == (ML0 + 3)) && (ml->m->hp > 0)) { found = 1; } else { found = 0; } if(!found) { ml = ml->next; } } if(ml != NULL) { mprint("A new justiciar has been promoted!"); x = ml->m->x; y = ml->m->y; ml->m->x = x; ml->m->y = y; ml->m->click = (Tick + 1) % 60; m_status_reset(ml->m, AWAKE); m_status_reset(ml->m, HOSTILE); } /* * Will cause order to be destroyed if no guards or justiciar */ alert_guards(); } else { mprint("A Servant of Chaos materializes, grabs the corpse,"); mprint("snickers a bit, and vanishes."); } } break; case ML0 + 3: /* Guard */ Player.alignment -= 10; if((Current_Environment == E_CITY) || (Current_Environment == E_VILLAGE)) { alert_guards(); } break; case ML3 + 5: /* Goblin king */ if(!gamestatusp(ATTACKED_ORACLE)) { mprint("You seem to hear a woman's voice from far off:"); mprint("\'Well don! Come to me now...\'"); } setgamestatus(COMPLETED_CAVES); break; case ML7 + 5: /* Great worm */ if(!gamestatusp(ATTACKED_ORACLE)) { mprint("A female voice sounds from just behind your ear:"); mprint("\'Well fought! I have some new advice for you...\'"); } setgamestatus(COMPLETED_SEWERS); break; case ML10 + 1: setgamestatus(KILLED_EATER); break; case ML10 + 2: setgamestatus(KILLED_LAWBRINGER); break; case ML10 + 3: setgamestatus(KILLED_DRAGONLORD); break; case ML10 + 4: setgamestatus(COMPLETED_VOLCANO); if(!gamestatusp(ATTACKED_ORACLE)) { mprint("You feel a soft touch on your shoulder..."); mprint("You turn around but there is no one there!"); mprint("You turn back and see a not: \'See me soon.\'"); mprint("The note vanishes in a burst of blue fire!"); } break; case ML10 + 9: /* Elemental master */ if(!gamestatusp(ATTACKED_ORACLE)) { mprint("Words appear before you, traced in blue flame!"); mprint("\'Return to the Prime Plane via the Circle of Sorcerors..."); } break; } } dodrawspot(m->x, m->y); }
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 } }