void runners(void) { register struct linked_list *item; register struct thing *tp = NULL; for(item = mlist; item != NULL; item = next(item)) { tp = THINGPTR(item); turn_on(*tp, ISREADY); } for (;;) { for (item = mlist; item != NULL; item = next(item)) { tp = THINGPTR(item); if (on(*tp, ISREADY)) break; } if (item == NULL) break; turn_off(*tp, ISREADY); if (on(*tp, ISHELD) && rnd(tp->t_stats.s_lvl) > 11) { turn_off(*tp, ISHELD); turn_on(*tp, ISRUN); turn_off(*tp, ISDISGUISE); tp->t_dest = &hero; if (tp->t_stats.s_hpt < tp->maxstats.s_hpt) turn_on(*tp, ISFLEE); if (cansee(tp->t_pos.y, tp->t_pos.x)) msg("The %s breaks free from the hold spell!!!", monsters[tp->t_index].m_name); } if (off(*tp, ISHELD) && on(*tp, ISRUN)) { register int flee; /* Should monster run away? */ flee = (on(*tp, ISFLEE) || ((tp->t_dest == &hero) && on(player, ISINWALL) && off(*tp, CANINWALL))); if (off(*tp, ISSLOW) || tp->t_turn) { doctor(tp); do_chase(tp, flee); } if (off(*tp, ISDEAD) && on(*tp, ISHASTE)) { doctor(tp); do_chase(tp, flee); } if (off(*tp, ISDEAD)) { tp->t_turn ^= TRUE; tp->t_wasshot = FALSE; /* Not shot anymore */ } } } }
void chase_it(coord *runner, struct thing *th) { struct linked_list *item; struct thing *tp; /* If we couldn't find him, something is funny */ if ((item = find_mons(runner->y, runner->x)) == NULL) { debug("CHASER '%s'", unctrl(winat(runner->y, runner->x))); return; } tp = THINGPTR(item); /* Start the beastie running */ tp->t_ischasing = TRUE; tp->t_chasee = th; turn_on(*tp, ISRUN); turn_off(*tp, ISDISGUISE); return; }
void listen(void) { struct linked_list *item; struct thing *tp; int thief_bonus = -50; int mcount = 0; if (player.t_ctype == C_THIEF) thief_bonus = 10; for (item = mlist; item != NULL; item = next(item)) { tp = THINGPTR(item); if (DISTANCE(hero, tp->t_pos) < 81 && rnd(70) < (thief_bonus + 4 * pstats.s_dext + 6 * pstats.s_lvl)) { msg("You hear a%s %s nearby.", vowelstr(monsters[tp->t_index].m_name), monsters[tp->t_index].m_name); mcount++; } } if (mcount == 0) msg("You hear nothing."); }
aggravate() { register struct linked_list *mi; for (mi = mlist; mi != NULL; mi = next(mi)) runto(THINGPTR(mi), &hero); }
void aggravate(void) { struct linked_list *mi; struct thing *tp; for (mi = mlist; mi != NULL; mi = next(mi)) { tp = THINGPTR(mi); chase_it(&tp->t_pos, &player); } }
struct linked_list * find_mons(int y, int x) { struct linked_list *item; for (item = mlist; item != NULL; item = next(item)) { struct thing *th = THINGPTR(item); if (th->t_pos.y == y && th->t_pos.x == x) return item; } return NULL; }
void unsummon(fuse_arg *monny) { struct linked_list *monst = monny->ll; struct linked_list *sum_monst = (struct linked_list *) monst; struct thing *tp = THINGPTR(sum_monst); char *mname = monsters[tp->t_index].m_name; turn_off(*tp, WASSUMMONED); turn_off(player, HASSUMMONED); msg("Goodbye, master."); msg("The summoned %s phases out of existence", mname); killed(NULL, sum_monst, NOMESSAGE, NOPOINTS); mons_summoned--; }
void electrificate(void) { int affect_dist = 4 + player.t_stats.s_lvl / 4; struct linked_list *item, *nitem; for (item = mlist; item != NULL; item = nitem) { struct thing *tp = THINGPTR(item); char *mname = monsters[tp->t_index].m_name; nitem = next(item); if (DISTANCE(tp->t_pos, hero) < affect_dist) { int damage = roll(2, player.t_stats.s_lvl); debug("Charge does %d (%d)", damage, tp->t_stats.s_hpt - damage); if (on(*tp, NOBOLT)) continue; if ((tp->t_stats.s_hpt -= damage) <= 0) { msg("The %s is killed by an electric shock.", mname); killed(&player, item, NOMESSAGE, POINTS); continue; } if (rnd(tp->t_stats.s_intel / 5) == 0) { turn_on(*tp, ISFLEE); msg("The %s is shocked by electricity.", mname); } else msg("The %s is zapped by your electricity.", mname); summon_help(tp, NOFORCE); turn_off(*tp, ISFRIENDLY); turn_off(*tp, ISCHARMED); turn_on(*tp, ISRUN); turn_off(*tp, ISDISGUISE); chase_it(&tp->t_pos, &player); fighting = after = running = FALSE; } } }
coord * find_shoot(struct thing *tp, coord *dir) { struct room *rtp; int ulx, uly, xmx, ymx, xmon, ymon, tpx, tpy, row, col; struct linked_list *mon; struct thing *ick; rtp = roomin(tp->t_pos); /* Find room of chaser */ if (rtp == NULL) return NULL; ulx = rtp->r_pos.x; uly = rtp->r_pos.y; xmx = rtp->r_max.x; ymx = rtp->r_max.y; tpx = tp->t_pos.x; tpy = tp->t_pos.y; for (col = ulx; col < (ulx + xmx); col++) for (row = uly; row < (uly + ymx); row++) { if (row > 0 && col > 0 && isalpha(mvwinch(mw, row, col))) { mon = find_mons(row, col); if (mon) { ick = THINGPTR(mon); xmon = ick->t_pos.x; ymon = ick->t_pos.y; if (!(good_monster(*ick))) { if (straight_shot(tpy, tpx, ymon, xmon, dir)) return(dir); } } } } return(NULL); }
void genocide(int flags) { struct linked_list *ip; struct thing *mp; struct linked_list *nip; int which_monst; int blessed = flags & ISBLESSED; int cursed = flags & ISCURSED; while ((which_monst = get_monster_number("genocide")) == 0) ; if (cursed) /* oops... */ { new_level(THRONE, which_monst); msg("What's this I hear about you trying to wipe me out?"); fighting = running = after = FALSE; return; } /* Remove this monster from the present level */ for (ip = mlist; ip; ip = nip) { mp = THINGPTR(ip); nip = next(ip); if (mp->t_index == which_monst) { check_residue(mp); /* Check for special features before removing */ remove_monster(&mp->t_pos, ip); } } /* Remove from available monsters */ monsters[which_monst].m_normal = FALSE; monsters[which_monst].m_wander = FALSE; mpos = 0; msg("You have wiped out the %s.", monsters[which_monst].m_name); if (blessed) genocide(ISNORMAL); }
/* * runners: * Make all the running monsters move. */ runners() { reg struct thing *tp; reg struct linked_list *mon,*nextmon; for (mon = mlist; mon != NULL; mon = nextmon) { tp = THINGPTR(mon); nextmon = next(mon); if (off(*tp, ISHELD) && on(*tp, ISRUN)) { if (tp->t_nomove > 0) if (--tp->t_nomove > 0) continue; if (on(*tp, ISHASTE)) if (do_chase(mon) == -1) continue; if (off(*tp, ISSLOW) || tp->t_turn) if (do_chase(mon) == -1) continue; tp->t_turn ^= TRUE; } } }
struct linked_list * f_mons_a(int y, int x, int hit_bad) { int row, col; struct linked_list *item; struct thing *tp; for (row = x - 1; row <= x + 1; row++) for (col = y - 1; col <= y + 1; col++) if (row == x && col == y) continue; else if (col > 0 && row > 0 && isalpha(mvwinch(mw, col, row)) && ((item = find_mons(col, row)) != NULL)) { tp = THINGPTR(item); if ((good_monster(*tp) && !hit_bad) || (!good_monster(*tp) && hit_bad)) return (item); } return (NULL); }
do_rooms() { int i; struct room *rp; struct linked_list *item; struct thing *tp; int left_out; coord top; coord bsze; coord mp; /* * bsze is the maximum room size */ bsze.x = COLS / 3; bsze.y = (LINES - 2) / 3; /* * Clear things for a new level */ for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) rp->r_nexits = rp->r_flags = rp->r_fires = 0; /* * Put the gone rooms, if any, on the level */ left_out = rnd(4); for (i = 0; i < left_out; i++) rooms[rnd_room()].r_flags |= ISGONE; /* * dig and populate all the rooms on the level */ for (i = 0, rp = rooms; i < MAXROOMS; rp++, i++) { bool has_gold = FALSE; /* * Find upper left corner of box that this room goes in */ top.x = (i % 3) * bsze.x; top.y = i / 3 * bsze.y + 1; if (rp->r_flags & ISGONE) { /* * Place a gone room. Make certain that there is a * blank line for passage drawing. */ do { rp->r_pos.x = top.x + rnd(bsze.x - 2) + 1; rp->r_pos.y = top.y + rnd(bsze.y - 2) + 1; rp->r_max.x = -COLS; rp->r_max.x = -LINES; } while (rp->r_pos.y < 1 || rp->r_pos.y > LINES - 3); continue; } if (rnd(80) < level - 15) rp->r_flags |= ISDARK; /* * Find a place and size for a random room */ do { rp->r_max.x = rnd(bsze.x - 4) + 4; rp->r_max.y = rnd(bsze.y - 4) + 4; rp->r_pos.x = top.x + rnd(bsze.x - rp->r_max.x); rp->r_pos.y = top.y + rnd(bsze.y - rp->r_max.y); } while (rp->r_pos.y == 0); /* Draw the room */ draw_room(rp); /* * Put the gold in */ if (rnd(100) < 50 && (!has_artifact || level >= max_level)) { struct linked_list *item; struct object *cur; coord tp; has_gold = TRUE; /* This room has gold in it */ item = spec_item(GOLD, NULL, NULL, NULL); cur = OBJPTR(item); /* Put it somewhere */ rnd_pos(rp, &tp); cur->o_pos = tp; /* Put the gold into the level list of items */ add_obj(item, tp.y, tp.x); if (roomin(&tp) != rp) { endwin(); abort(); } } /* * Put the monster in */ if (rnd(100) < (has_gold ? 80 : 40)) { short which; int i, count; item = new_item(sizeof *tp); tp = THINGPTR(item); do { rnd_pos(rp, &mp); } while (mvwinch(stdscr, mp.y, mp.x) != FLOOR); which = randmonster(NOWANDER, NOGRAB); new_monster(item, which, &mp, NOMAXSTATS); /* * See if we want to give it a treasure to carry * around. */ if (rnd(100) < monsters[tp->t_index].m_carry) attach(tp->t_pack, new_thing()); /* * If it has a fire, mark it */ if (on(*tp, HASFIRE)) { rp->r_flags |= HASFIRE; rp->r_fires++; } /* * If it carries gold, give it some */ if (on(*tp, CARRYGOLD)) { struct object *cur; item = spec_item(GOLD, NULL, NULL, NULL); cur = OBJPTR(item); cur->o_count = GOLDCALC + GOLDCALC + GOLDCALC; cur->o_pos = tp->t_pos; attach(tp->t_pack, item); } i = rnd(7); if (on(*tp, ISSWARM) && i < 5) count = roll(2, 4); else if (on(*tp, ISFLOCK) && i < 5) count = roll(1, 4); else count = 0; for (i = 1; i <= count; i++) { coord *mpos; if ((mpos = place_mons(mp.y, mp.x)) != NULL) { struct linked_list *nitem; nitem = new_item(sizeof(struct thing)); new_monster(nitem, which, mpos, NOMAXSTATS); /* * If the monster is on a trap, trap * it */ if (isatrap(mvinch(mpos->y, mpos->x))) be_trapped(THINGPTR(nitem), mp); if (on(*tp, ISFRIENDLY)) turn_on(*(THINGPTR(nitem)), ISFRIENDLY); else turn_off(*(THINGPTR(nitem)), ISFRIENDLY); } } if (count > 0) { int boost = rnd(3) + 1; if (on(*tp, LOWCAST) || on(*tp, MEDCAST) || on(*tp, HIGHCAST)) turn_on(*tp, CANCAST); tp->t_stats.s_hpt += 3 * boost; tp->t_stats.s_arm -= 2 * boost; tp->t_stats.s_lvl += 2 * boost; tp->t_stats.s_str += 2 * boost; tp->t_stats.s_intel += 2 * boost; tp->t_stats.s_exp += 4 * boost * monsters[which].m_add_exp; } } } }
struct linked_list * wake_monster(int y, int x) { struct thing *tp; struct linked_list *it; struct room *trp; char *mname; if ((it = find_mons(y, x)) == NULL) { debug("Can't find monster in show."); return(NULL); } tp = THINGPTR(it); if ((good_monster(*tp)) || on(player, SUMMONING)) { chase_it(&tp->t_pos, &player); turn_off(*tp, ISINVIS); turn_off(*tp, CANSURPRISE); return(it); } trp = roomin(tp->t_pos); /* Current room for monster */ mname = monsters[tp->t_index].m_name; /* Let greedy ones guard gold */ if (on(*tp, ISGREED) && off(*tp, ISRUN)) if ((trp != NULL) && (lvl_obj != NULL)) { struct linked_list *item; struct object *cur; for (item = lvl_obj; item != NULL; item = next(item)) { cur = OBJPTR(item); if ((cur->o_type == GOLD) && (roomin(cur->o_pos) == trp)) { /* Run to the gold */ tp->t_horde = cur; turn_on(*tp, ISRUN); turn_off(*tp, ISDISGUISE); tp->t_ischasing = FALSE; /* Make it worth protecting */ cur->o_count += roll(2, 3) * GOLDCALC; break; } } } /* * Every time he sees mean monster, it might start chasing him unique * monsters always do */ if ( (on(*tp, ISUNIQUE)) || ( (rnd(100) > 33) && on(*tp, ISMEAN) && off(*tp, ISHELD) && off(*tp, ISRUN) && !is_stealth(&player) && (off(player, ISINVIS) || on(*tp, CANSEE)) ) ) { chase_it(&tp->t_pos, &player); } /* Handle gaze attacks */ if (on(*tp, ISRUN) && cansee(tp->t_pos.y, tp->t_pos.x) && off(player, ISINVIS)) { if (on(*tp, CANHUH)) /* Confusion */ { if (on(player, CANREFLECT)) { msg("You reflect the bewildering stare of the %s.", mname); if (save_throw(VS_MAGIC, tp)) { msg("The %s is confused!", mname); turn_on(*tp, ISHUH); } else msg("The %s staggers for a moment.", mname); } else if (save(VS_MAGIC)) { msg("You feel dizzy for a moment, but it quickly passes."); if (rnd(100) < 67) turn_off(*tp, CANHUH); } else if (off(player, ISCLEAR)) { if (off(player, ISHUH)) { light_fuse(FUSE_UNCONFUSE, 0, rnd(20) + HUHDURATION, AFTER); msg("The %s's gaze has confused you.", mname); turn_on(player, ISHUH); } else lengthen_fuse(FUSE_UNCONFUSE, rnd(20) + HUHDURATION); } } if (on(*tp, CANSNORE)) /* Sleep */ { if (on(player, CANREFLECT)) { msg("You reflect the lethargic glance of the %s", mname); if (save_throw(VS_PARALYZATION, tp)) { msg("The %s falls asleep!", mname); tp->t_no_move += SLEEPTIME; } } else if (no_command == 0 && !save(VS_PARALYZATION)) { if (is_wearing(R_ALERT)) msg("You feel slightly drowsy for a moment."); else { msg("The %s's gaze puts you to sleep.", mname); no_command = SLEEPTIME; if (rnd(100) < 50) turn_off(*tp, CANSNORE); } } } if (on(*tp, CANFRIGHTEN)) /* Fear */ { turn_off(*tp, CANFRIGHTEN); if (on(player, CANREFLECT)) { msg("The %s sees its reflection. ", mname); if (save_throw(VS_MAGIC,tp)) { msg("The %s is terrified by its reflection!", mname); turn_on(*tp, ISFLEE); } } else { if (!save(VS_WAND) && !(on(player, ISFLEE) && (player.t_chasee==tp))) { if ((player.t_ctype != C_PALADIN) && off(player, SUPERHERO)) { turn_on(player, ISFLEE); player.t_ischasing = FALSE; player.t_chasee = tp; msg("The sight of the %s terrifies you.", mname); } else msg("My, the %s looks ugly.", mname); } } } if (on(*tp, LOOKSLOW)) /* Slow */ { turn_off(*tp, LOOKSLOW); if (on(player, CANREFLECT)) { msg("You reflect the mournful glare of the %s.", mname); if (save_throw(VS_MAGIC,tp)) { msg("The %s is slowing down!", mname); turn_on(*tp, ISSLOW); } } else if (is_wearing(R_FREEDOM) || save(VS_MAGIC)) msg("You feel run-down for a moment."); else { if (on(player, ISHASTE)) /* Already sped up */ { extinguish_fuse(FUSE_NOHASTE); nohaste(NULL); } else { msg("You feel yourself moving %sslower.", on(player, ISSLOW) ? "even " : ""); if (on(player, ISSLOW)) lengthen_fuse(FUSE_NOSLOW, rnd(4) + 4); else { turn_on(player, ISSLOW); player.t_turn = TRUE; light_fuse(FUSE_NOSLOW, 0, rnd(4) + 4, AFTER); } } } } if (on(*tp, CANBLIND)) /* Blinding */ { turn_off(*tp, CANBLIND); if (on(player, CANREFLECT)) { msg("You reflect the blinding stare of the %s.", mname); if (save_throw(VS_WAND, tp)) { msg("The %s is blinded!", mname); turn_on(*tp, ISHUH); } } else if (off(player, ISBLIND)) if (save(VS_WAND) || is_wearing(R_TRUESEE) || is_wearing(R_SEEINVIS)) msg("Your eyes film over for a moment."); else { msg("The gaze of the %s blinds you.", mname); turn_on(player, ISBLIND); light_fuse(FUSE_SIGHT, 0, rnd(30) + 20, AFTER); look(FALSE); } } if (on(*tp, LOOKSTONE)) /* Stoning */ { turn_off(*tp, LOOKSTONE); if (on(player, CANREFLECT)) { msg("You reflect the flinty look of the %s.", mname); if (save_throw(VS_PETRIFICATION,tp)) { msg("The %s suddenly stiffens", mname); tp->t_no_move += STONETIME; } else { msg("The %s is turned to stone!", mname); killed(&player, it, NOMESSAGE, POINTS); } } else { if (on(player, CANINWALL)) msg("The %s cannot focus on you.", mname); else { msg("The gaze of the %s stiffens your limbs.", mname); if (save(VS_PETRIFICATION)) no_command = STONETIME; else if (rnd(100)) no_command = STONETIME * 3; else { msg("The gaze of the %s petrifies you.", mname); msg("You are turned to stone!!! --More--"); wait_for(' '); death(D_PETRIFY); return(it); } } } } } /* * True Sight sees all Never see ISINWALL or CANSURPRISE See ISSHADOW * 80% See ISINVIS with See Invisibilty */ if (off(player, CANTRUESEE) && on(*tp, ISINWALL) || on(*tp, CANSURPRISE) || (on(*tp, ISSHADOW) && rnd(100) < 80) || (on(*tp, ISINVIS) && off(player, CANSEE))) { /* TODO: incomplete - need to finish logic int ch = mvwinch(stdscr, y, x); */ } /* hero might be able to hear or smell monster if he can't see it */ if ((rnd(player.t_ctype == C_THIEF ? 40 : 200) == 0 || on(player, CANHEAR)) && !cansee(tp->t_pos.y, tp->t_pos.x)) msg("You hear a %s nearby.", mname); else if ((rnd(player.t_ctype == C_THIEF ? 40 : 200) == 0 || on(player, CANSCENT)) && !cansee(tp->t_pos.y, tp->t_pos.x)) msg("You smell a %s nearby.", mname); return(it); }
void wanderer(void) { int i, cnt = 0; struct room *hr = roomin(hero); struct linked_list *item; struct thing *tp; coord cp; char *loc; int which; /* Find a place for it -- avoid the player's room */ do { do { cnt++; i = rnd_room(); } while (!(hr != &rooms[i] || levtype == MAZELEV || levtype == THRONE || cnt > 5000)); rnd_pos(&rooms[i], &cp); } while(!step_ok(cp.y, cp.x, NOMONST, NULL)); /* Create a new wandering monster */ item = new_item(sizeof *tp); which = randmonster(TRUE, FALSE); new_monster(item, which, &cp, FALSE); tp = THINGPTR(item); tp->t_pos = cp; /* Assign the position to the monster */ chase_it(&tp->t_pos, &player); i = rnd(7); if (on(*tp, ISSWARM) && i < 5) cnt = roll(2, 4); else if (on(*tp, ISFLOCK) && i < 5) cnt = roll(1, 4); else cnt = 0; for (i = 1; i <= cnt; i++) { struct linked_list *ip = creat_mons(tp, which, NOMESSAGE); if (ip != NULL) { struct thing *mp = THINGPTR(ip); if (on(*tp, ISFRIENDLY)) turn_on(*mp, ISFRIENDLY); else turn_off(*mp, ISFRIENDLY); } } if (cnt > 0) { if (on(*tp, LOWCAST) || on(*tp, MEDCAST) || on(*tp, HIGHCAST)) turn_on(*tp, CANCAST); tp->t_stats.s_hpt += roll(2, 8); tp->t_stats.s_lvl += roll(2, 3); tp->t_stats.s_arm -= roll(1, 6); tp->t_stats.s_str += roll(2, 3); tp->t_stats.s_intel += roll(2, 3); tp->t_stats.s_exp += roll(2, 8) * monsters[which].m_add_exp; } i = DISTANCE(cp, hero); if (i < 20) loc = "very close to you"; else if (i < 400) loc = "nearby"; else loc = "in the distance"; if (wizard) msg("Started a wandering %s.", monsters[tp->t_index].m_name); else if (on(*tp, ISUNDEAD) && (player.t_ctype == C_CLERIC || player.t_ctype == C_PALADIN || is_wearing(R_PIETY))) msg("You sense a new ungodly monster %s.", loc); else if (on(player, CANHEAR) || (player.t_ctype == C_THIEF && rnd(20) == 0)) msg("You hear a new %s moving %s.", monsters[tp->t_index].m_name, loc); else if (on(player, CANSCENT) || (player.t_ctype == C_THIEF && rnd(20) == 0)) msg("You smell a new %s %s.", monsters[tp->t_index].m_name, loc); }
struct linked_list * summon_monster(int type, int familiar, int print_message) { struct linked_list *mp; struct thing *tp; int monster; if (familiar && !is_wearing(R_WIZARD) && off(player, CANSUMMON)) { msg("Only spellcasters can summon familiars!"); return(NULL); } if (type == 0) /* Random monster modified by level */ { int ndice = min(pstats.s_lvl, (nummonst - NUMSUMMON) / 8); monster = min(nummonst, roll(ndice, pstats.s_charisma)); /* * if a familiar exists, and it is higher in level, make it * again */ if (fam_ptr != NULL) { struct thing *fp = THINGPTR(fam_ptr); monster = max(fp->t_index, monster); } } else monster = type; turn_on(player, SUMMONING); mp = creat_mons(&player, monster, NOMESSAGE); if (!mp) { msg("Summon failed."); turn_off(player, SUMMONING); return(NULL); } if (print_message == MESSAGE) { msg("A %s appears out of nowhere!", monsters[monster].m_name); if (familiar) msg("I am here to serve %s.", whoami); else { msg("My goodness, are you Yendor?"); ++mons_summoned; debug("%d monsters now summoned.", mons_summoned); } } tp = THINGPTR(mp); turn_on(*tp, ISCHARMED); /* Summoned monsters are always charmed */ if (familiar) { int i; static const unsigned long fam_on[]= {ISREGEN,CANSHOOT,CANWIELD,HASARMOR,ISFAMILIAR,0}; static const unsigned long fam_off[]={ISMEAN, ISHUH, ISINVIS, CANSURPRISE, NOMOVE, ISSLOW, ISSHADOW, ISGREED, ISFAST, CANFLY, ISFLEE, 0}; for (i = 0; fam_on[i]; i++) turn_on(*tp, fam_on[i]); for (i = 0; fam_off[i]; i++) turn_off(*tp, fam_off[i]); if (fam_ptr != NULL) /* Get rid of old familiar */ { struct thing *fp = THINGPTR(fam_ptr); struct linked_list *fpack = fp->t_pack; struct linked_list *item; if (fpack != NULL) /* Transfer pack */ { if (tp->t_pack == NULL) tp->t_pack = fpack; else { for(item=tp->t_pack; item->l_next != NULL; item=next(item)) ; /* find last item in list */ item->l_next = fpack; fpack->l_prev = item; } } fpack = NULL; killed(NULL, fam_ptr, NOMESSAGE, NOPOINTS); } fam_ptr = mp; fam_type = monster; /* improve their abilities a bit */ tp->t_stats.s_hpt += roll(2, pstats.s_lvl); tp->t_stats.s_lvl += roll(2, (pstats.s_lvl / 4) + 1); tp->t_stats.s_arm -= roll(2, (pstats.s_lvl / 4) + 1); tp->t_stats.s_str += roll(2, (pstats.s_lvl / 4) + 1); tp->t_stats.s_intel += roll(2, (pstats.s_lvl / 4) + 1); tp->t_stats.s_wisdom += roll(2, (pstats.s_lvl / 4) + 1); tp->t_stats.s_dext += roll(2, (pstats.s_lvl / 4) + 1); tp->t_stats.s_const += roll(2, (pstats.s_lvl / 4) + 1); tp->t_stats.s_charisma += roll(2, (pstats.s_lvl / 4) + 1); /* some monsters do no damage by default */ if (strcmp(tp->t_stats.s_dmg, "0d0") == 0) tp->t_stats.s_dmg = "1d8"; tp->maxstats = tp->t_stats; /* structure assignment */ } turn_off(player, SUMMONING); return(mp); }
void new_monster(struct linked_list *item, int type, coord *cp, int max_monster) { struct thing *tp; struct monster *mp; char *ip, *hitp; int i, min_intel, max_intel; int num_dice, num_sides = 8, num_extra = 0; int eff_charisma = pstats.s_charisma; int eff_intel = pstats.s_intel; attach(mlist, item); tp = THINGPTR(item); tp->t_index = type; tp->t_wasshot = FALSE; tp->t_type = monsters[type].m_appear; tp->t_ctype = C_MONSTER; tp->t_no_move = 0; tp->t_doorgoal = -1; tp->t_pos = *cp; tp->t_oldpos = *cp; tp->t_oldch = CCHAR( mvwinch(cw, cp->y, cp->x) ); mvwaddch(mw, cp->y, cp->x, tp->t_type); mp = &monsters[tp->t_index]; /* Figure out monster's hit points */ hitp = mp->m_stats.s_hpt; num_dice = atoi(hitp); if ((hitp = strchr(hitp, 'd')) != NULL) { num_sides = atoi(++hitp); if ((hitp = strchr(hitp, '+')) != NULL) num_extra = atoi(++hitp); } if (max_monster == MAXSTATS) tp->t_stats.s_hpt = num_dice * num_sides + num_extra; else tp->t_stats.s_hpt = roll(num_dice, num_sides) + num_extra; tp->t_stats.s_lvl = mp->m_stats.s_lvl; tp->t_stats.s_arm = mp->m_stats.s_arm; tp->t_stats.s_dmg = mp->m_stats.s_dmg; tp->t_stats.s_exp = mp->m_stats.s_exp + mp->m_add_exp * tp->t_stats.s_hpt; tp->t_stats.s_str = mp->m_stats.s_str; if (max_level > 30) { tp->t_stats.s_hpt += roll(4, (max_level - 60) * 2); tp->t_stats.s_lvl += roll(4, (max_level - 60) / 8); tp->t_stats.s_arm -= roll(2, (max_level - 60) / 8); tp->t_stats.s_str += roll(2, (max_level - 60) / 12); tp->t_stats.s_exp += roll(4, (max_level - 60) * 2) * mp->m_add_exp; } /* * just initailize others values to something reasonable for now * maybe someday will *really* put these in monster table */ tp->t_stats.s_wisdom = 8 + rnd(4); tp->t_stats.s_dext = 8 + rnd(4); tp->t_stats.s_const = 8 + rnd(4); tp->t_stats.s_charisma = 8 + rnd(4); if (max_level > 45) tp->t_stats.s_dext += roll(2, (max_level - 50) / 8); /* Set the initial flags */ for (i = 0; i < 16; i++) tp->t_flags[i] = 0; for (i = 0; i < 16; i++) turn_on(*tp, mp->m_flags[i]); /* suprising monsters don't always surprise you */ if (!max_monster && on(*tp, CANSURPRISE) && rnd(100) < 20) turn_off(*tp, CANSURPRISE); /* If this monster is unique, genocide it */ if (on(*tp, ISUNIQUE)) mp->m_normal = FALSE; /* gods automatically get special abilities */ if (on(*tp, ISGOD)) { turn_on(*tp, CANFRIGHTEN); turn_on(*tp, CANCAST); turn_on(*tp, CANFLY); turn_on(*tp, CANBARGAIN); turn_on(*tp, ISLARGE); turn_on(*tp, CANTELEPORT); turn_on(*tp, CANSPEAK); turn_on(*tp, CANDARKEN); turn_on(*tp, CANSEE); turn_on(*tp, CANLIGHT); turn_on(*tp, BMAGICHIT); } tp->t_turn = TRUE; tp->t_pack = NULL; /* Figure intelligence */ min_intel = atoi(mp->m_intel); if ((ip = (char *) strchr(mp->m_intel, '-')) == NULL) tp->t_stats.s_intel = min_intel; else { max_intel = atoi(++ip); if (max_monster) tp->t_stats.s_intel = max_intel; else tp->t_stats.s_intel = min_intel + rnd(max_intel - min_intel); } tp->t_stats.s_power = (rnd(tp->t_stats.s_lvl / 5) + 1) * tp->t_stats.s_intel; tp->maxstats = tp->t_stats; /* structure assignment */ /* If the monster can shoot, it may have a weapon */ if (on(*tp, CANSHOOT) && (max_monster || rnd(9) < 6)) { struct linked_list *thrower_item, *missile_item; struct object *thrower, *a_missile; thrower_item = new_item(sizeof *thrower); thrower = OBJPTR(thrower_item); carried_weapon(tp, thrower); missile_item = new_item(sizeof *a_missile); a_missile = OBJPTR(missile_item); carried_weapon(tp, a_missile); /* The monster may use a crossbow, sling, footbow, or an arrow */ /* Take racial preferences into account */ if ((strcmp(mp->m_name, "elf") == 0) || (strcmp(mp->m_name, "noldor elf") == 0)) { thrower->o_which = BOW; if (rnd(5) == 0) a_missile->o_which = SILVERARROW; else a_missile->o_which = ARROW; } else if ((strcmp(mp->m_name, "dwarf") == 0) || (strcmp(mp->m_name, "kazad dwarf") == 0)) { thrower->o_which = CROSSBOW; a_missile->o_which = BOLT; } else if (on(*tp, ISSMALL)) { switch (rnd(3)) { case 0: thrower->o_which = SLING; a_missile->o_which = BULLET; break; default: thrower->o_which = SLING; a_missile->o_which = ROCK; } } else if (on(*tp, ISLARGE)) { switch (rnd(4)) { case 0: thrower->o_which = CROSSBOW; a_missile->o_which = BOLT; break; case 1: thrower->o_which = FOOTBOW; a_missile->o_which = FBBOLT; break; default: thrower->o_which = BOW; if (rnd(5) == 0) a_missile->o_which = FLAMEARROW; else a_missile->o_which = ARROW; break; } } else { switch (rnd(6)) { case 1: thrower->o_which = SLING; a_missile->o_which = ROCK; break; case 2: thrower->o_which = CROSSBOW; a_missile->o_which = BOLT; break; case 3: thrower->o_which = FOOTBOW; a_missile->o_which = FBBOLT; break; case 4: thrower->o_which = BOW; a_missile->o_which = ARROW; break; default: thrower->o_which = SLING; a_missile->o_which = BULLET; break; } } init_weapon(thrower, thrower->o_which); init_weapon(a_missile, a_missile->o_which); attach(tp->t_pack, thrower_item); attach(tp->t_pack, missile_item); } /* monsters that wield weapons */ if (on(*tp, CANWIELD)) { if (max_monster || rnd(3)) { struct linked_list *wield_item; struct object *wielded; wield_item = new_item(sizeof *wielded); wielded = OBJPTR(wield_item); carried_weapon(tp, wielded); i = rnd(CLAYMORE - CLUB) + rnd(2 * tp->t_stats.s_lvl); i = min(i, CLAYMORE); wielded->o_which = i; init_weapon(wielded, wielded->o_which); /* Is it too heavy? */ if (itemweight(wielded) > 8 * tp->t_stats.s_str) discard(wield_item); else attach(tp->t_pack, wield_item); } } if (is_wearing(R_AGGR)) chase_it(cp, &player); else { turn_off(*tp, ISRUN); if (on(*tp, ISFLEE) && (rnd(4) == 0)) turn_off(*tp, ISFLEE); if (rnd(luck) == 0) switch (player.t_ctype) { case C_MAGICIAN: case C_ILLUSION: eff_intel = 2 * pstats.s_intel; break; case C_DRUID: eff_intel = 2 * pstats.s_intel; case C_RANGER: eff_charisma = 2 * pstats.s_charisma; break; case C_ASSASIN: case C_THIEF: case C_NINJA: eff_charisma = pstats.s_charisma / 2; break; } /* LOWFRIENDLY monsters might be friendly */ i = roll(1,100); if (i == 0 || (on(*tp, LOWFRIENDLY) && i < eff_charisma) || (on(*tp, MEDFRIENDLY) && i < 3 * eff_charisma) || (on(*tp, HIGHFRIENDLY) && i < 5 * eff_charisma)) { turn_on(*tp, ISFRIENDLY); turn_off(*tp, ISMEAN); } i = roll(1,100); if (i == 0 || (on(*tp, LOWCAST) && i < eff_intel) || (on(*tp, MEDCAST) && i < 3 * eff_intel) || (on(*tp, HIGHCAST) && i < 5 * eff_intel)) { turn_on(*tp, CANCAST); } if (on(*tp, ISDISGUISE)) { char mch = 0; if (tp->t_pack != NULL) mch = (OBJPTR(tp->t_pack))->o_type; else switch (rnd(level > arts[0].ar_level ? 10 : 9)) { case 0: mch = GOLD; break; case 1: mch = POTION; break; case 2: mch = SCROLL; break; case 3: mch = FOOD; break; case 4: mch = WEAPON; break; case 5: mch = ARMOR; break; case 6: mch = RING; break; case 7: mch = STICK; break; case 8: mch = monsters[randmonster(NOWANDER, NOGRAB)].m_appear; break; case 9: mch = ARTIFACT; break; } tp->t_disguise = mch; } } }
/* * quaff: * Let the hero drink a potion */ int quaff() { struct object *obj; struct linked_list *item, *titem; struct thing *th; int wh; char buf[LINLEN]; bool bless, curse; /* * Make certain that it is somethings that we want to drink */ if ((item = get_item("quaff", POTION)) == NULL) return 0; obj = OBJPTR(item); if (obj->o_type != POTION) { msg("That's undrinkable!"); after = FALSE; return 0; } wh = obj->o_which; bless = o_on(obj, ISBLESS); curse = o_on(obj, ISCURSED); del_pack(item); /* get rid of it */ /* * Calculate the effect it has on the poor guy. */ switch(wh) { case P_CONFUSE: if (!bless) { if (pl_on(ISINVINC)) msg("You remain level-headed."); else { chg_abil(WIS,-1,TRUE); /* confuse his mind */ if (pl_off(ISHUH)) { msg("Wait, what's going on here. Huh? What? Who?"); if (pl_on(ISHUH)) lengthen(unconfuse,rnd(8)+HUHDURATION); else fuse(unconfuse,TRUE,rnd(8)+HUHDURATION); player.t_flags |= ISHUH; } } p_know[P_CONFUSE] = TRUE; } when P_POISON: if (!bless) { if (pl_off(ISINVINC) && !iswearing(R_SUSTSTR) && !iswearing(R_SUSAB)) { chg_abil(CON,-1,TRUE); chg_abil(STR,-(rnd(3)+1),TRUE); msg("You feel very sick now."); } else msg("You feel momentarily sick."); p_know[P_POISON] = TRUE; } when P_HEALING: if (!curse) { heal_self(4, TRUE); msg("You begin to feel better."); if (!iswearing(R_SLOW)) notslow(FALSE); sight(FALSE); p_know[P_HEALING] = TRUE; } when P_STRENGTH: if (!curse) { msg("You feel stronger, now. What bulging muscles!"); chg_abil(STR,1,TRUE); p_know[P_STRENGTH] = TRUE; } when P_MFIND: /* * Potion of monster detection - find all monsters */ if (mlist != NULL && !curse) { dispmons(); mpos = 0; msg("You begin to sense the presence of monsters--More--"); p_know[P_MFIND] = TRUE; wait_for(cw,' '); msg(""); /* clear line */ } else msg("You have a strange feeling for a moment, then it passes."); when P_TFIND: /* * Potion of magic detection. Show the potions and scrolls */ if (lvl_obj != NULL && !curse) { struct linked_list *mobj; struct object *tp; bool show; show = FALSE; wclear(hw); for (mobj = lvl_obj; mobj != NULL; mobj = next(mobj)) { tp = OBJPTR(mobj); if (is_magic(tp)) { show = TRUE; mvwaddch(hw, tp->o_pos.y, tp->o_pos.x, MAGIC); } } for(titem = mlist; titem != NULL; titem = next(titem)) { struct linked_list *pitem; th = THINGPTR(titem); for(pitem=th->t_pack;pitem!=NULL;pitem=next(pitem)) { if (is_magic(ldata(pitem))) { show = TRUE; mvwaddch(hw,th->t_pos.y, th->t_pos.x, MAGIC); } } } if (show) { msg("You begin to sense the presence of magic."); overlay(hw,cw); p_know[P_TFIND] = TRUE; break; } } msg("You have a strange feeling for a moment, then it passes."); when P_PARALYZE: if (!bless) { if (pl_on(ISINVINC)) msg("You feel numb for a moment."); else { msg("You can't move."); player.t_nocmd = HOLDTIME; } p_know[P_PARALYZE] = TRUE; } when P_SEEINVIS: if (!curse) { int invlen = roll(40,20); msg("This potion tastes like %s juice.", fruit); if (pl_off(CANSEE)) { player.t_flags |= CANSEE; fuse(unsee, TRUE, invlen); light(&hero); } else lengthen(unsee, invlen); sight(FALSE); } when P_RAISE: if (!curse) { msg("You suddenly feel much more skillful."); p_know[P_RAISE] = TRUE; chg_abil(DEX,1,TRUE); chg_abil(WIS,1,TRUE); chg_abil(CON,1,TRUE); raise_level(); } when P_XHEAL: if (!curse) { heal_self(8, TRUE); if (rnd(100) < 50) chg_abil(CON,1,TRUE); msg("You begin to feel much better."); p_know[P_XHEAL] = TRUE; if (!iswearing(R_SLOW)) notslow(FALSE); unconfuse(); extinguish(unconfuse); sight(FALSE); } when P_HASTE: if (!curse) { add_haste(TRUE); msg("You feel yourself moving much faster."); p_know[P_HASTE] = TRUE; } when P_INVINC: if (!curse) { int time = rnd(400) + 350; msg("You feel invincible."); if (player.t_flags & ISINVINC) lengthen(notinvinc,time); else fuse(notinvinc,TRUE,time); player.t_flags |= ISINVINC; p_know[P_INVINC] = TRUE; } when P_SMART: if (!curse) { msg("You feel more perceptive."); p_know[P_SMART] = TRUE; chg_abil(WIS,1,TRUE); } when P_RESTORE: if (!curse) { msg("Hey, this tastes great. You feel warm all over."); him->s_re = max_stats.s_re; him->s_ef = max_stats.s_re; ringabil(); /* add in rings */ updpack(); /* update weight */ p_know[P_RESTORE] = TRUE; extinguish(rchg_str); /* kill restore in from ulodyte */ } when P_BLIND: if (!bless) { if (pl_on(ISINVINC)) msg("The light dims for a moment."); else { chg_abil(WIS,-1,TRUE); msg("A cloak of darkness falls around you."); if (pl_off(ISBLIND)) { player.t_flags |= ISBLIND; fuse(sight, TRUE, rnd(400) + 450); light(&hero); } } p_know[P_BLIND] = TRUE; } when P_ETH: if (!curse) { int ethlen = roll(40,20); msg("You feel more vaporous."); if (pl_on(ISETHER)) lengthen(noteth,ethlen); else fuse(noteth,TRUE,ethlen); player.t_flags |= ISETHER; p_know[P_ETH] = TRUE; } when P_NOP: msg("This potion tastes extremely dull."); when P_DEX: if (!curse) { chg_abil(DEX,1,TRUE); /* increase dexterity */ p_know[P_DEX] = TRUE; msg("You feel much more agile."); } when P_REGEN: if (!curse) { int reglen = rnd(450) + 450; if (pl_on(ISREGEN)) lengthen(notregen, reglen); else fuse(notregen, TRUE, reglen); player.t_flags |= ISREGEN; msg("You feel yourself improved."); p_know[P_REGEN] = TRUE; } when P_DECREP: case P_SUPHERO: { int howmuch = rnd(3) + 1; if (wh == P_DECREP) { if (!bless) { if (iswearing(R_SUSAB) || pl_on(ISINVINC)) { msg("You feel momentarily woozy."); howmuch = 0; } else { msg("You feel crippled."); howmuch = -howmuch; if (!iswearing(R_SUSTSTR)) chg_abil(STR,howmuch,TRUE); } } else howmuch = 0; } else { /* potion of superhero */ if (curse) howmuch = 0; msg("You feel invigorated."); chg_abil(STR,howmuch,TRUE); } chg_abil(CON,howmuch,TRUE); chg_abil(DEX,howmuch,TRUE); chg_abil(WIS,howmuch,TRUE); /* change abilities */ p_know[wh] = TRUE; } otherwise: msg("What an odd tasting potion!"); return 0; } nochange = FALSE; if (p_know[wh] && p_guess[wh]) { free(p_guess[wh]); p_guess[wh] = NULL; } else if(!p_know[wh] && p_guess[wh] == NULL) { strcpy(buf, p_colors[wh]); msg(callit); if (get_str(buf, cw) == NORM) { p_guess[wh] = new(strlen(buf) + 1); strcpy(p_guess[wh], buf); }
void look(int wakeup) { int x, y; char ch, och; int oldx, oldy; int inpass, horizontal, vertical, do_light = FALSE, do_blank = FALSE; int passcount = 0; struct room *rp; int ey, ex; /* Are we moving vertically or horizontally? */ if (runch == 'h' || runch == 'l') horizontal = TRUE; else horizontal = FALSE; if (runch == 'j' || runch == 'k') vertical = TRUE; else vertical = FALSE; getyx(cw, oldy, oldx); /* Save current position */ /* * Blank out the floor around our last position and check for moving * out of a corridor in a maze. */ if (oldrp != NULL && (oldrp->r_flags & ISDARK) && !(oldrp->r_flags & HASFIRE) && off(player, ISBLIND)) do_blank = TRUE; for (x = player.t_oldpos.x - 1; x <= player.t_oldpos.x + 1; x++) for (y = player.t_oldpos.y - 1; y <= player.t_oldpos.y + 1; y++) { ch = show(y, x); if (do_blank && (y != hero.y || x != hero.x) && ch == FLOOR) mvwaddch(cw, y, x, ' '); /* Moving out of a corridor? */ if (levtype == MAZELEV && (ch != '|' && ch != '-') && /* Not a wall */ ((vertical && x != player.t_oldpos.x && y == player.t_oldpos.y) || (horizontal && y != player.t_oldpos.y && x == player.t_oldpos.x))) do_light = TRUE; /* Just came to a turn */ } inpass = ((rp = roomin(hero)) == NULL); /* Are we in a passage? */ /* Are we coming out of a wall into a corridor in a maze? */ och = show(player.t_oldpos.y, player.t_oldpos.x); ch = show(hero.y, hero.x); if (levtype == MAZELEV && (och == '|' || och == '-' || och == SECRETDOOR) && (ch != '|' && ch != '-' && ch != SECRETDOOR)) { do_light = off(player, ISBLIND); /* Light it up if not blind */ } /* Look around the player */ ey = hero.y + 1; ex = hero.x + 1; for (x = hero.x - 1; x <= ex; x++) if (x >= 0 && x < COLS) for (y = hero.y - 1; y <= ey; y++) { if (y <= 0 || y >= LINES - 2) continue; if (isalpha(mvwinch(mw, y, x))) { struct linked_list *it; struct thing *tp; if (wakeup) it = wake_monster(y, x); else it = find_mons(y, x); if (it == NULL) continue; tp = THINGPTR(it); tp->t_oldch = CCHAR( mvinch(y, x) ); if (isatrap(tp->t_oldch)) { struct trap *trp = trap_at(y, x); tp->t_oldch = (trp->tr_flags & ISFOUND) ? tp->t_oldch : trp->tr_show; } if (tp->t_oldch == FLOOR && (rp->r_flags & ISDARK) && !(rp->r_flags & HASFIRE) && off(player, ISBLIND)) tp->t_oldch = ' '; } /* Secret doors show as walls */ if ((ch = show(y, x)) == SECRETDOOR) ch = secretdoor(y, x); /* * Don't show room walls if he is in a * passage and check for maze turns */ if (off(player, ISBLIND)) { if (y == hero.y && x == hero.x || (inpass && (ch == '-' || ch == '|'))) continue; /* Are we at a crossroads in a maze? */ if (levtype == MAZELEV && (ch != '|' && ch != '-') && /* Not a wall */ ((vertical && x != hero.x && y == hero.y) || (horizontal && y != hero.y && x == hero.x))) do_light = TRUE; /* Just came to a turn */ } else if (y != hero.y || x != hero.x) continue; wmove(cw, y, x); waddch(cw, ch); if (door_stop && !firstmove && running) { switch (runch) { case 'h': if (x == ex) continue; break; case 'j': if (y == hero.y - 1) continue; break; case 'k': if (y == ey) continue; break; case 'l': if (x == hero.x - 1) continue; break; case 'y': if ((x + y) - (hero.x + hero.y) >= 1) continue; break; case 'u': if ((y - x) - (hero.y - hero.x) >= 1) continue; break; case 'n': if ((x + y) - (hero.x + hero.y) <= -1) continue; break; case 'b': if ((y - x) - (hero.y - hero.x) <= -1) continue; break; } switch (ch) { case DOOR: if (x == hero.x || y == hero.y) running = FALSE; break; case PASSAGE: if (x == hero.x || y == hero.y) passcount++; break; case FLOOR: /* * Stop by new passages in a * maze (floor next to us) */ if ((levtype == MAZELEV) && ((horizontal && x == hero.x && y != hero.y) || (vertical && y == hero.y && x != hero.x))) running = FALSE; case '|': case '-': case ' ': break; default: running = FALSE; break; } } } if (door_stop && !firstmove && passcount > 1) running = FALSE; /* * Do we have to light up the area (just stepped into a new * corridor)? */ if (do_light && wakeup && /* wakeup will be true on a normal move */ !(rp->r_flags & ISDARK) && /* We have some light */ !ce(hero, player.t_oldpos)) /* Don't do anything if we didn't move */ light(&hero); mvwaddch(cw, hero.y, hero.x, PLAYER); wmove(cw, oldy, oldx); if (wakeup) { player.t_oldpos = hero; /* Don't change if we didn't move */ oldrp = rp; } }
void teleport(void) { struct room *new_rp = NULL, *old_rp = roomin(hero); int rm, which; coord c; int is_lit = FALSE; /* For saving room light state */ int rand_position = TRUE; c = hero; mvwaddch(cw, hero.y, hero.x, mvwinch(stdscr, hero.y, hero.x)); if (is_wearing(R_TELCONTROL)) { msg("Where do you wish to teleport to? (* for help)"); wmove(cw, hero.y, hero.x); wrefresh(cw); which = (short) (readchar() & 0177); while (which != (short) ESCAPE && which != (short) LINEFEED && which != (short) CARRIAGE_RETURN) { switch(which) { case 'h': c.x--; break; case 'j': c.y++; break; case 'k': c.y--; break; case 'l': c.x++; break; case 'y': c.x--; c.y--; break; case 'u': c.x++; c.y--; break; case 'b': c.x--; c.y++; break; case 'n': c.x++; c.y++; break; case '*': msg("Use h,j,k,l,y,u,b,n to position cursor, then hit" "return."); } c.y = max(c.y, 1); c.y = min(c.y, LINES - 3); c.x = max(c.x, 1); c.x = min(c.x, COLS - 1); wmove(cw, c.y, c.x); wrefresh(cw); which = (short) (readchar() & 0177); } which = winat(c.y, c.x); if ((which == FLOOR || which == PASSAGE || which == DOOR) && ((ring_value(R_TELCONTROL) == 0 && rnd(10) < 6) || (ring_value(R_TELCONTROL) > 0 && rnd(10) < 9))) { rand_position = FALSE; msg("You attempt succeeds."); hero = c; new_rp = roomin(hero); } else msg("Your attempt fails."); } if (rand_position) { do { rm = rnd_room(); rnd_pos(&rooms[rm], &hero); } while (winat(hero.y, hero.x) != FLOOR); new_rp = &rooms[rm]; } /* If hero gets moved, darken old room */ if (old_rp && old_rp != new_rp) { if (!(old_rp->r_flags & ISDARK)) is_lit = TRUE; old_rp->r_flags |= ISDARK; /* Fake darkness */ light(&c); if (is_lit) old_rp->r_flags &= ~ISDARK; /* Restore light state */ } light(&hero); mvwaddch(cw, hero.y, hero.x, PLAYER); /* turn off ISHELD in case teleportation was done while fighting */ if (on(player, ISHELD)) { struct linked_list *ip, *nip; struct thing *mp; turn_off(player, ISHELD); hold_count = 0; for (ip = mlist; ip; ip = nip) { mp = THINGPTR(ip); nip = next(ip); if (on(*mp, DIDHOLD)) { turn_off(*mp, DIDHOLD); turn_on(*mp, CANHOLD); } turn_off(*mp, DIDSUFFOCATE); } } extinguish_fuse(FUSE_SUFFOCATE); player.t_no_move = 0; /* not trapped anymore */ count = 0; running = FALSE; return; }
/* * read_scroll: * Let the hero read a scroll */ int read_scroll() { struct object *obj; struct linked_list *item; int i, j, wh; unsigned long ch, nch; struct room *rp; struct linked_list *titem; char buf[LINLEN]; bool bless, curse; if ((item = get_item("read", SCROLL)) == NULL) return 0; obj = OBJPTR(item); if (obj->o_type != SCROLL) { msg("Nothing to read."); after = FALSE; return 0; } msg("As you read the scroll, it vanishes."); wh = obj->o_which; bless = o_on(obj, ISBLESS); curse = o_on(obj, ISCURSED); del_pack(item); /* Get rid of the thing */ /* * Calculate the effect it has on the hero */ switch(wh) { case S_KNOWALL: if (!curse) { idenpack(); /* identify all the pack */ msg("You feel more knowledgable."); chg_abil(WIS,1,TRUE); s_know[S_KNOWALL] = TRUE; } when S_CONFUSE: if (!curse) { /* * Scroll of monster confusion. Give him that power. */ msg("Your hands begin to glow red."); player.t_flags |= CANHUH; s_know[S_CONFUSE] = TRUE; } when S_LIGHT: rp = player.t_room; if (!curse) { if (rp == NULL) { s_know[S_LIGHT] = TRUE; msg("The corridor glows and then fades."); } else { if (rf_on(rp,ISDARK)) { s_know[S_LIGHT] = TRUE; msg("The room is lit."); rp->r_flags &= ~ISDARK; } light(&hero); mvwaddch(cw, hero.y, hero.x, PLAYER); } } when S_ARMOR: if (!curse) { if (cur_armor != NULL && o_off(cur_armor,ISPROT)) { s_know[S_ARMOR] = TRUE; msg("Your armor glows faintly for a moment."); if (o_on(cur_armor,ISCURSED)) cur_armor->o_ac = armors[cur_armor->o_which].a_class; else cur_armor->o_ac--; resoflg(cur_armor,ISCURSED); } } when S_HOLD: if (!curse) { /* * Hold monster scroll. Stop all monsters within 3 spaces * from chasing after the hero. */ int x,y; struct linked_list *mon; for (x = hero.x - 3; x <= hero.x + 3; x++) { for (y = hero.y - 3; y <= hero.y + 3; y++) { if (y > 0 && x > 0 && isalpha(mvwinch(mw, y, x))) { if ((mon = find_mons(y, x)) != NULL) { struct thing *th; th = THINGPTR(mon); th->t_flags &= ~ISRUN; th->t_flags |= ISHELD; th->t_flags |= ISSTUCK; } } } } } when S_SLEEP: /* * Scroll which makes you fall asleep */ if (!bless) { s_know[S_SLEEP] = TRUE; msg("You fall asleep."); player.t_nocmd += 4 + rnd(SLEEPTIME); } when S_CREATE: if (!bless) { if (makemons(mtlev[rnd(levcount)]->m_show)) s_know[S_CREATE] = TRUE; else msg("You hear a faint cry of anguish in the distance."); } when S_IDENT: if (!curse) { msg("This scroll is an identify scroll"); s_know[S_IDENT] = TRUE; whatis(NULL); } when S_MAP: if (curse) break; s_know[S_MAP] = TRUE; addmsg("Oh, now this scroll has a "); if (rnd(100) < 10 || bless) { addmsg("very detailed map on it."); endmsg(); displevl(); } else { addmsg("map on it."); endmsg(); overwrite(stdscr, hw); for (i = 1; i < LINES - 2; i++) { for (j = 0; j < COLS; j++) { switch (nch = ch = mvwinch(hw, i, j)) { case SECRETDOOR: nch = DOOR; mvaddch(i, j, nch); case '-': case '|': case DOOR: case PASSAGE: case ' ': case STAIRS: if (mvwinch(mw, i, j) != ' ') { struct thing *it; struct linked_list *blah; blah = find_mons(i, j); if (blah != NULL) { it = THINGPTR(blah); if (it->t_oldch == ' ') it->t_oldch = nch; } } break; default: nch = ' '; } if (nch != ch) waddch(hw, nch); } } overlay(cw, hw); overwrite(hw, cw); } when S_GFIND: if (!curse) { int gtotal = 0; struct room *rp; wclear(hw); for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) { gtotal += rp->r_goldval; if (rp->r_goldval != 0 && mvinch(rp->r_gold.y,rp->r_gold.x) == GOLD) mvwaddch(hw,rp->r_gold.y,rp->r_gold.x,GOLD); } if (gtotal) { s_know[S_GFIND] = TRUE; msg("You begin to feel greedy and sense gold."); overlay(hw,cw); } else msg("You begin to feel a pull downward."); } when S_TELEP: if (!curse) { int rm; struct room *cur_room; cur_room = player.t_room; rm = teleport(rndspot, &player); if (cur_room != &rooms[rm]) s_know[S_TELEP] = TRUE; } when S_ENCH: if (!curse) { if (cur_weapon == NULL || (cur_weapon != NULL && (o_on(cur_weapon,ISPROT) || cur_weapon->o_type != WEAPON))) msg("You feel a strange sense of loss."); else { s_know[S_ENCH] = TRUE; if (o_on(cur_weapon,ISCURSED)) { resoflg(cur_weapon,ISCURSED); cur_weapon->o_hplus = rnd(2); cur_weapon->o_dplus = rnd(2); } else { /* weapon was not cursed here */ if (rnd(100) < 50) cur_weapon->o_hplus += 1; else cur_weapon->o_dplus += 1; } setoflg(cur_weapon, ISKNOW); msg("Your %s glows blue for a moment.", w_magic[cur_weapon->o_which].mi_name); } } when S_SCARE: /* * A monster will refuse to step on a scare monster scroll * if it is dropped. Thus reading it is a mistake and produces * laughter at the poor rogue's boo boo. */ msg("You hear maniacal laughter in the distance."); when S_REMOVE: if (!curse) { if (cur_armor != NULL && o_off(cur_armor,ISPROT)) resoflg(cur_armor,ISCURSED); if (cur_weapon != NULL && o_off(cur_weapon,ISPROT)) resoflg(cur_weapon,ISCURSED); if (cur_ring[LEFT]!=NULL && o_off(cur_ring[LEFT],ISPROT)) resoflg(cur_ring[LEFT],ISCURSED); if (cur_ring[RIGHT]!=NULL && o_off(cur_ring[RIGHT],ISPROT)) resoflg(cur_ring[RIGHT],ISCURSED); msg("You feel as if somebody is watching over you."); s_know[S_REMOVE] = TRUE; } when S_AGGR: if (!bless) { if (mlist != NULL) { aggravate(); msg("You hear a high pitched humming noise."); s_know[S_AGGR] = TRUE; } } when S_NOP: msg("This scroll seems to be blank."); when S_GENOCIDE: if (!curse) { msg("You have been granted the boon of genocide."); genocide(); s_know[S_GENOCIDE] = TRUE; } when S_DCURSE: if (!bless) { struct linked_list *ll; struct object *lb; msg("Your pack shudders."); for (ll = pack ; ll != NULL ; ll = next(ll)) { lb = OBJPTR(ll); if (o_off(lb,ISPROT)) { resoflg(lb, ISBLESS); setoflg(lb, ISCURSED); } } } when S_DLEVEL: if (!bless) { int much = rnd(9) - 4; if (much != 0) { level += much; if (level < 1) level = 1; mpos = 0; new_level(NORMLEV); /* change levels */ msg("You are whisked away to another region."); s_know[S_DLEVEL] = TRUE; } } when S_PROTECT: if (!curse) { struct linked_list *ll; struct object *lb; msg("You are granted the power of protection."); if ((ll = get_item("protect",0)) != NULL) { lb = OBJPTR(ll); setoflg(lb,ISPROT); mpos = 0; msg("Protected %s.",inv_name(lb,TRUE)); } s_know[S_PROTECT] = TRUE; } when S_ALLENCH: if (!curse) { struct linked_list *ll; struct object *lb; int howmuch, ac, good; msg("You are granted the power of enchantment."); good = TRUE; if ((ll = get_item("enchant",0)) != NULL) { lb = OBJPTR(ll); resoflg(lb,ISCURSED); resoflg(lb,ISPROT); howmuch = rnd(3) + 1; switch(lb->o_type) { case RING: if (lb->o_ac < 0) lb->o_ac = 0; lb->o_ac += howmuch; when ARMOR: ac = armors[lb->o_which].a_class; if (lb->o_ac > ac) lb->o_ac = ac; lb->o_ac -= howmuch; when STICK: lb->o_charges += howmuch + 10; when WEAPON: if (lb->o_dplus < 0) lb->o_dplus = 0; if (lb->o_hplus < 0) lb->o_hplus = 0; lb->o_hplus += howmuch; lb->o_dplus += howmuch; otherwise: msg("You are injured as the scroll flashes & bursts into flames !!!"); chg_hpt(-roll(6,6),FALSE,K_SCROLL); good = FALSE; } if (good) { mpos = 0; msg("Enchanted %s.",inv_name(lb,TRUE)); } } s_know[S_ALLENCH] = TRUE; } when S_BLESS: if (!curse) { struct linked_list *ll; struct object *lb; msg("Your pack glistens brightly."); for (ll = pack ; ll != NULL ; ll = next(ll)) { whatis(ll); lb = OBJPTR(ll); resoflg(lb,ISCURSED); setoflg(lb,ISBLESS); } } when S_MAKEIT: if (!curse) { msg("You have been endowed with the power of creation."); s_know[S_MAKEIT] = TRUE; create_obj(TRUE); } when S_BAN: { int howdeep; char *ptr; if (bless) { if (level > 6) { howdeep = 1 + rnd(5); ptr = "elevated to the upper"; } else { howdeep = -1; bless = FALSE; } } else { howdeep = level + 10 + rnd(20) + (curse * 20); ptr = "banished to the lower"; } if ((!bless && level < howdeep) || bless) { level = howdeep; new_level(NORMLEV); mpos = 0; msg("You are %s regions.", ptr); s_know[S_BAN] = TRUE; } } when S_CWAND: if (!curse) { struct linked_list *ll; struct object *lb; bool wands = FALSE; for (ll = pack ; ll != NULL ; ll = next(ll)) { lb = OBJPTR(ll); if (lb->o_type == STICK) { whatis(ll); setoflg(lb, ISKNOW); resoflg(lb, ISCURSED); lb->o_charges += rnd(11) + 5; wands = TRUE; } } if (wands) { msg("Your sticks gleam."); s_know[wh] = TRUE; } } when S_LOCTRAP: { struct trap *trp; if (ntraps > 0) { for (trp = &traps[0]; trp < &traps[ntraps]; trp++) trp->tr_flags |= ISFOUND; look(FALSE); msg("You now recognize pitfalls."); s_know[S_LOCTRAP] = TRUE; } } otherwise: msg("What a puzzling scroll!"); return 0; }
int chase(struct thing *tp, coord *ee, int flee) { int x, y; int dist, thisdist, monst_dist = INT_MAX; struct linked_list *weapon; coord *er = &tp->t_pos; coord shoot; coord *shootit_dir = NULL; int ch; char mch; int next_player = FALSE; /* Take care of shooting directions */ if (on(*tp, CANBREATHE) || on(*tp, CANSHOOT) || on(*tp, CANCAST)) { if (good_monster(*tp)) { shootit_dir = find_shoot(tp, &shoot); /* find a mean monster */ if (wizard && shootit_dir) msg("Found monster to attack towards (%d,%d).", shootit_dir->x, shootit_dir->y); } else shootit_dir = can_shoot(er, ee, &shoot); /* shoot hero */ } /* * If the thing is confused, let it move randomly. Some monsters are * slightly confused all of the time. */ if ((on(*tp, ISHUH) && rnd(10) < 8) || ((on(*tp, ISINVIS) || on(*tp, ISSHADOW)) && rnd(100) < 20) || (on(player, ISINVIS) && off(*tp, CANSEE))) { /* Player is invisible */ /* get a valid random move */ tp->t_nxtpos = rndmove(tp); dist = DISTANCE(tp->t_nxtpos, *ee); if (on(*tp, ISHUH) && rnd(20) == 0) /* monster might lose confusion */ turn_off(*tp, ISHUH); /* * check to see if random move takes creature away from * player if it does then turn off ISHELD */ if (dist > 1 && on(*tp, DIDHOLD)) { turn_off(*tp, DIDHOLD); turn_on(*tp, CANHOLD); if (--hold_count == 0) turn_off(player, ISHELD); } } /* If we can breathe, we may do so */ else if (on(*tp, CANBREATHE) && (shootit_dir) && (rnd(100) < 67) && (off(player, ISDISGUISE) || (rnd(tp->t_stats.s_lvl) > 6)) && (DISTANCE(*er, *ee) < BOLT_LENGTH * BOLT_LENGTH)) { int chance; char *breath; /* Will it breathe at random */ if (on(*tp, CANBRANDOM)) { if (rnd(level / 20) == 0 && tp->t_index != nummonst + 1 && !(good_monster(*tp))) turn_off(*tp, CANBRANDOM); /* Select type of breath */ chance = rnd(100); if (chance < 11) breath = "acid"; else if (chance < 22) breath = "flame"; else if (chance < 33) breath = "lightning bolt"; else if (chance < 44) breath = "chlorine gas"; else if (chance < 55) breath = "ice"; else if (chance < 66) breath = "nerve gas"; else if (chance < 77) breath = "sleeping gas"; else if (chance < 88) breath = "slow gas"; else breath = "fear gas"; } /* Or can it breathe acid? */ else if (on(*tp, CANBACID)) { if (!good_monster(*tp) && rnd(level / 15) == 0) turn_off(*tp, CANBACID); breath = "acid"; } /* Or can it breathe fire */ else if (on(*tp, CANBFIRE)) { if (!good_monster(*tp) && rnd(level / 15) == 0) turn_off(*tp, CANBFIRE); breath = "flame"; } /* Or can it breathe electricity? */ else if (on(*tp, CANBBOLT)) { if (!good_monster(*tp) && rnd(level / 15) == 0) turn_off(*tp, CANBBOLT); breath = "lightning bolt"; } /* Or can it breathe gas? */ else if (on(*tp, CANBGAS)) { if (!good_monster(*tp) && rnd(level / 15) == 0) turn_off(*tp, CANBGAS); breath = "chlorine gas"; } /* Or can it breathe ice? */ else if (on(*tp, CANBICE)) { if (!good_monster(*tp) && rnd(level / 15) == 0) turn_off(*tp, CANBICE); breath = "ice"; } else if (on(*tp, CANBPGAS)) { if (!good_monster(*tp) && rnd(level / 15) == 0) turn_off(*tp, CANBPGAS); breath = "nerve gas"; } else if (on(*tp, CANBSGAS)) { if (!good_monster(*tp) && rnd(level / 15) == 0) turn_off(*tp, CANBSGAS); breath = "sleeping gas"; } else if (on(*tp, CANBSLGAS)) { if (!good_monster(*tp) && rnd(level / 15) == 0) turn_off(*tp, CANBSLGAS); breath = "slow gas"; } else { if (!good_monster(*tp) && rnd(level / 15) == 0) turn_off(*tp, CANBFGAS); breath = "fear gas"; } shoot_bolt(tp, *er, *shootit_dir, (tp == THINGPTR(fam_ptr)), tp->t_index, breath, roll(tp->t_stats.s_lvl, 6)); tp->t_nxtpos = *er; dist = DISTANCE(tp->t_nxtpos, *ee); if (!curr_mons) return (TRUE); } else if (shootit_dir && on(*tp, CANCAST) && (off(player, ISDISGUISE) || (rnd(tp->t_stats.s_lvl) > 6))) { /* If we can cast spells we might do so - even if adjacent fleeing monsters are restricted to certain spells */ incant(tp, *shootit_dir); tp->t_nxtpos = *er; dist = DISTANCE(tp->t_nxtpos, *ee); } else if (shootit_dir && on(*tp, CANSHOOT)) { weapon = get_hurl(tp); if (weapon && (off(*tp, ISFLEE) || rnd(DISTANCE(*er, *ee)) > 2) && (off(player, ISDISGUISE) || (rnd(tp->t_stats.s_lvl) > 6))) { /* Should we shoot or throw something? fleeing monsters may to shoot anyway if far enough away */ missile(shootit_dir->y, shootit_dir->x, weapon, tp); tp->t_nxtpos = *er; dist = DISTANCE(tp->t_nxtpos, *ee); } } else { /* Otherwise, find the empty spot next to the chaser that is closest to the chasee. */ int ey, ex; struct room *rer, *ree; int dist_to_old = INT_MIN; /* Dist from goal to old position */ /* Get rooms */ rer = roomin(*er); ree = roomin(*ee); /* * This will eventually hold where we move to get closer. If * we can't find an empty spot, we stay where we are. */ dist = flee ? 0 : INT_MAX; tp->t_nxtpos = *er; /* Are we at our goal already? */ if (!flee && ce(tp->t_nxtpos, *ee)) return (FALSE); ey = er->y + 1; ex = er->x + 1; for (x = er->x - 1; x <= ex; x++) for (y = er->y - 1; y <= ey; y++) { coord tryp; /* test position */ /* Don't try off the screen */ if ((x < 0) || (x >= COLS) || (y < 1) || (y >= LINES - 2)) continue; /* * Don't try the player if not going after * the player or he's disguised and monster is dumb */ if (((off(*tp, ISFLEE) && !ce(hero, *ee)) || (on(player, ISDISGUISE) && (rnd(tp->t_stats.s_lvl) < 6)) || good_monster(*tp)) && x == hero.x && y == hero.y) continue; tryp.x = x; tryp.y = y; /* * Is there a monster on this spot closer to * our goal? Don't look in our spot or where * we were. */ if (!ce(tryp, *er) && !ce(tryp, tp->t_oldpos) && isalpha( (mch = CCHAR(mvwinch(mw, y, x))) ) ) { int test_dist; test_dist = DISTANCE(tryp,*ee); if (test_dist <= 25 && /* Let's be fairly close */ test_dist < monst_dist) { /* Could we really move there? */ mvwaddch(mw, y, x, ' '); /* Temp blank monst */ if (diag_ok(er, &tryp, tp)) monst_dist = test_dist; mvwaddch(mw, y, x, mch); /* Restore monster */ } } if (!diag_ok(er, &tryp, tp)) continue; ch = mvwinch(cw, y, x); /* Screen character */ /* * Stepping on player is NOT okay if we are * fleeing */ if (on(*tp, ISFLEE) && (ch == PLAYER)) next_player = TRUE; if (step_ok(y, x, NOMONST, tp) && (off(*tp, ISFLEE) || ch != PLAYER)) { /* * If it is a trap, an intelligent * monster may not step on it (unless * our hero is on top!) */ if (isatrap(ch)) { if (!(ch == RUSTTRAP) && !(ch == FIRETRAP && on(*tp, NOFIRE)) && rnd(10) < tp->t_stats.s_intel && (y != hero.y || x != hero.x)) continue; } /* * OK -- this place counts */ thisdist = DISTANCE(tryp, *ee); /* * Adjust distance if we are being * shot at to moving out of line of sight. */ if (tp->t_wasshot && tp->t_stats.s_intel > 5 && ce(hero, *ee)) { /* Move out of line of sight */ if (straight_shot(tryp.y, tryp.x, ee->y, ee->x, NULL)) { if (flee) thisdist -= SHOTPENALTY; else thisdist += SHOTPENALTY; } /* * But do we want to leave * the room? */ else if (rer && rer == ree && ch == DOOR) thisdist += DOORPENALTY; } /* * Don't move to the last position if * we can help it */ if (ce(tryp, tp->t_oldpos)) dist_to_old = thisdist; else if ((flee && (thisdist > dist)) || (!flee && (thisdist < dist))) { tp->t_nxtpos = tryp; dist = thisdist; } } } /* * If we are running from the player and he is in our way, go * ahead and slug him. */ if (next_player && DISTANCE(*er,*ee) < dist && step_ok(tp->t_chasee->t_pos.y, tp->t_chasee->t_pos.x, NOMONST, tp)) { tp->t_nxtpos = tp->t_chasee->t_pos; /* Okay to hit player */ return(FALSE); } /* * If we can't get closer to the player (if that's our goal) * because other monsters are in the way, just stay put */ if (!flee && ce(hero, *ee) && monst_dist < INT_MAX && DISTANCE(*er, hero) < dist) tp->t_nxtpos = *er; /* Do we want to go back to the last position? */ else if (dist_to_old != INT_MIN && /* It is possible to move back */ ((flee && dist == 0) || /* No other possible moves */ (!flee && dist == INT_MAX))) { /* Do we move back or just stay put (default)? */ dist = DISTANCE(*er,*ee); /* Current distance */ if (!flee || (flee && (dist_to_old > dist))) tp->t_nxtpos = tp->t_oldpos; } } /* Make sure we have the real distance now */ dist = DISTANCE(tp->t_nxtpos, *ee); /* Mark monsters in a wall */ switch(mvinch(tp->t_nxtpos.y, tp->t_nxtpos.x)) { case WALL: case '-': case '|': turn_on(*tp, ISINWALL); break; default: turn_off(*tp, ISINWALL); } if (off(*tp, ISFLEE) && !(!SAME_POS((tp->t_chasee->t_pos),hero) || off(player, ISINWALL) || on(*tp, CANINWALL))) return(dist != 0); else /* May actually hit here from a confused move */ return(!ce(tp->t_nxtpos, hero)); }
int add_pack(struct linked_list *item, int print_message) { struct object *obj, *op; int from_floor; if (item == NULL) { from_floor = TRUE; if ((item = find_obj(hero.y, hero.x)) == NULL) { msg("Nothing to pick up."); return(FALSE); } } else from_floor = FALSE; if (from_floor) { item = get_stack(item); if (!item) return(FALSE); } obj = OBJPTR(item); /* If it is gold, just add its value to rogue's purse and get rid of */ if (obj->o_type == GOLD) { struct linked_list *mitem; struct thing *tp; if (print_message) { if (!terse) addmsg("You found "); msg("%d gold pieces.", obj->o_count); } /* * First make sure no greedy monster is after this gold. If * so, make the monster run after the rogue instead. */ for (mitem = mlist; mitem != NULL; mitem = next(mitem)) { tp = THINGPTR(mitem); if (tp->t_horde==obj) { tp->t_ischasing = TRUE; tp->t_chasee = &player; tp->t_horde = NULL; } } /* * This will cause problems if people are able to drop and * pick up gold, or when GOLDSTEAL monsters are killed. */ /* Thieves get EXP for gold they pick up */ if (player.t_ctype == C_THIEF) { pstats.s_exp += obj->o_count / 4; check_level(); } purse += obj->o_count; if (from_floor) rem_obj(item, TRUE); /* Remove object from the level */ return (TRUE); } /* see if he can carry any more weight */ if (itemweight(obj) + pstats.s_pack > pstats.s_carry) { msg("Too much for you to carry."); if (print_message) { msg("%s onto %s", terse ? "Moved" : "You moved", inv_name(obj, LOWERCASE)); } return(FALSE); } /* * Link it into the pack. If the item can be grouped, try to find its * neighbors and bump the count. A special case is food, which can't * be grouped, but an exact match allows the count to get * incremented. */ if ((op = apply_to_bag(pack, obj->o_type, bff_group, NULL, obj)) != NULL) { op->o_count += obj->o_count; /* add it to the rest */ if (from_floor) rem_obj(item, FALSE); pack_report(op, print_message, "You now have "); return(TRUE); } /* Check for and deal with scare monster scrolls */ if (obj->o_type == SCROLL && obj->o_which == S_SCARE) if (obj->o_flags & ISCURSED) { msg("The scroll turns to dust as you pick it up."); rem_obj(item, TRUE); return(TRUE); } /* Check if there is room */ if (count_bag(pack, obj->o_type, NULL) == max_print()) { msg("You have no room for more %s.", name_type(obj->o_type)); if (print_message) { obj = OBJPTR(item); msg("%s onto %s.", terse ? "Moved" : "You moved", inv_name(obj, LOWERCASE)); } return(FALSE); } /* * finally, add the new item to the bag, and free up the linked list * on top of it. */ if (from_floor) rem_obj(item, FALSE); push_bag(&pack, obj); pack_report(obj, print_message, "You now have "); ur_free(item); return(TRUE); /* signal success */ }
daemon runners(daemon_arg *arg) { struct linked_list *item; struct thing *tp; NOOP(arg); for (item = mlist; item != NULL; item = next_mons) { curr_mons = item; next_mons = next(curr_mons); tp = THINGPTR(item); if (on(*tp, ISHELD) && rnd(tp->t_stats.s_str + tp->t_stats.s_lvl) > 10 + rnd(50)) { turn_off(*tp, ISHELD); turn_off(*tp, ISDISGUISE); turn_on(*tp, ISRUN); tp->t_ischasing = TRUE; tp->t_chasee = &player; tp->t_horde = NULL; if (tp->t_stats.s_hpt < rnd(tp->maxstats.s_hpt)) turn_on(*tp, ISFLEE); if (cansee(tp->t_pos.y, tp->t_pos.x)) msg("The %s breaks free!", monsters[tp->t_index].m_name); } if (off(*tp, ISHELD) && on(*tp, ISRUN)) { int flee = FALSE; flee = on(*tp, ISFLEE) || ( (tp->t_chasee == &player) && on(player, ISINWALL) && off(*tp, CANINWALL) && off(*tp, ISFAMILIAR) ); if (off(*tp, ISSLOW) || tp->t_turn) { daemon_arg targ; targ.thingptr = tp; doctor(&targ); do_chase(tp, flee); } if (curr_mons && (on(*tp, ISHASTE) || ((on(*tp, CANFLY) || on(*tp, ISFAST)) && DISTANCE(hero, tp->t_pos) >= 4))) { daemon_arg targ; targ.thingptr = tp; doctor(&targ); do_chase(tp, flee); } if (curr_mons) { tp->t_turn ^= TRUE; tp->t_wasshot ^= FALSE; /* Not shot anymore */ } } } curr_mons = next_mons = NULL; return; }