/* Check whether the location has an outdated object displayed on it. */ static boolean check_map_spot(int x, int y, char oclass, unsigned material) { int memobj; struct obj *otmp; struct monst *mtmp; memobj = level->locations[x][y].mem_obj; if (memobj) { /* there's some object shown here */ if (oclass == ALL_CLASSES) { return (!(level->objects[x][y] || /* stale if nothing here */ ((mtmp = m_at(level, x, y)) != 0 && mtmp->minvent))); } else { if (material && objects[memobj - 1].oc_material == material) { /* the object shown here is of interest because material matches */ for (otmp = level->objects[x][y]; otmp; otmp = otmp->nexthere) if (o_material(otmp, GOLD)) return FALSE; /* didn't find it; perhaps a monster is carrying it */ if ((mtmp = m_at(level, x, y)) != 0) { for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) if (o_material(otmp, GOLD)) return FALSE; } /* detection indicates removal of this object from the map */ return TRUE; } if (oclass && objects[memobj - 1].oc_class == oclass) { /* the object shown here is of interest because its class matches */ for (otmp = level->objects[x][y]; otmp; otmp = otmp->nexthere) if (o_in(otmp, oclass)) return FALSE; /* didn't find it; perhaps a monster is carrying it */ if ((mtmp = m_at(level, x, y)) != 0) { for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) if (o_in(otmp, oclass)) return FALSE; } /* detection indicates removal of this object from the map */ return TRUE; } } } return FALSE; }
int goodpos(int x, int y) { // used only in mnexto and rloc return !(x < 1 || x > COLNO - 2 || y < 1 || y > ROWNO - 2 || m_at(x, y) || !ACCESSIBLE(_level->l[x][y].typ) || (x == _u.ux && y == _u.uy) || sobj_at(ENORMOUS_ROCK, x, y) ); }
struct monst * mk_roamer(const struct permonst *ptr, aligntyp alignment, struct level *lev, xchar x, xchar y, boolean peaceful, int mm_flags) { struct monst *roamer; boolean coaligned = (u.ualign.type == alignment); if (ptr != &mons[PM_ALIGNED_PRIEST] && ptr != &mons[PM_ANGEL]) return NULL; if (MON_AT(lev, x, y)) rloc(m_at(lev, x, y), FALSE); /* insurance */ if (!(roamer = makemon(ptr, lev, x, y, mm_flags))) return NULL; EPRI(roamer)->shralign = alignment; if (coaligned && !peaceful) EPRI(roamer)->renegade = TRUE; /* roamer->ispriest == FALSE naturally */ roamer->isminion = TRUE; /* borrowing this bit */ roamer->mtrapseen = ~0; /* traps are known */ msethostility(roamer, !peaceful, TRUE); /* TODO: handle in_mklev */ roamer->msleeping = 0; /* MORE TO COME */ return roamer; }
void mkswamp(void) { // Michiel Huisjes & Fred de Wilde struct mkroom *sroom; int sx, sy, i, eelct = 0; for (i = 0; i < 5; i++) { // 5 tries sroom = &rooms[rn2(nroom)]; if (sroom->hx < 0 || sroom->rtype || has_upstairs(sroom) || has_dnstairs(sroom)) continue; // satisfied; make a swamp sroom->rtype = SWAMP; for (sx = sroom->lx; sx <= sroom->hx; sx++) for (sy = sroom->ly; sy <= sroom->hy; sy++) if ((sx + sy) % 2 && !o_at(sx, sy) && !t_at(sx, sy) && !m_at(sx, sy) && !nexttodoor(sx, sy)) { levl[sx][sy].typ = POOL; levl[sx][sy].scrsym = POOL_SYM; if (!eelct || !rn2(4)) { (void) makemon(PM_EEL, sx, sy); eelct++; } } } }
static struct monst * bchit(int ddx, int ddy, int range, char sym) { struct monst *mtmp = (struct monst *) 0; int bchx = u.ux, bchy = u.uy; if(sym) Tmp_at(-1, sym); /* open call */ while(range--) { bchx += ddx; bchy += ddy; if ((mtmp = m_at(bchx,bchy))) break; if(!ZAP_POS(levl[bchx][bchy].typ)) { bchx -= ddx; bchy -= ddy; break; } if(sym) Tmp_at(bchx, bchy); } if(sym) Tmp_at(-1, -1); return(mtmp); }
/* * Is (x,y) a good position of mtmp? If mtmp is NULL, then is (x,y) good * for an object? * * This function will only look at mtmp->mdat, so makemon, mplayer, etc can * call it to generate new monster positions with fake monster structures. */ boolean goodpos(struct level *lev, int x, int y, struct monst *mtmp, unsigned gpflags) { const struct permonst *mdat = NULL; boolean ignorewater = ((gpflags & MM_IGNOREWATER) != 0); if (!isok(x, y)) return FALSE; /* in many cases, we're trying to create a new monster, which * can't go on top of the player or any existing monster. * however, occasionally we are relocating engravings or objects, * which could be co-located and thus get restricted a bit too much. * oh well. */ if (mtmp != &youmonst && x == u.ux && y == u.uy && (!u.usteed || mtmp != u.usteed)) return FALSE; if (mtmp) { struct monst *mtmp2 = m_at(lev, x,y); /* Be careful with long worms. A monster may be placed back in * its own location. Normally, if m_at() returns the same monster * that we're trying to place, the monster is being placed in its * own location. However, that is not correct for worm segments, * because all the segments of the worm return the same m_at(). * Actually we overdo the check a little bit--a worm can't be placed * in its own location, period. If we just checked for mtmp->mx * != x || mtmp->my != y, we'd miss the case where we're called * to place the worm segment and the worm's head is at x,y. */ if (mtmp2 && (mtmp2 != mtmp || mtmp->wormno)) return FALSE; mdat = mtmp->data; if (is_pool(lev, x,y) && !ignorewater) { if (mtmp == &youmonst) return !!(HLevitation || Flying || Wwalking || Swimming || Amphibious); else return (is_flyer(mdat) || is_swimmer(mdat) || is_clinger(mdat)); } else if (mdat->mlet == S_EEL && rn2(13) && !ignorewater) { return FALSE; } else if (is_lava(lev, x,y)) { if (mtmp == &youmonst) return !!HLevitation; else return is_flyer(mdat) || likes_lava(mdat); } if (passes_walls(mdat) && may_passwall(lev, x,y)) return TRUE; } if (!ACCESSIBLE(lev->locations[x][y].typ)) { if (!(is_pool(lev, x,y) && ignorewater)) return FALSE; } if (closed_door(lev, x, y) && (!mdat || !amorphous(mdat))) return FALSE; if (sobj_at(BOULDER, lev, x, y) && (!mdat || !throws_rocks(mdat))) return FALSE; return TRUE; }
/* create a new shopkeeper in the given room */ static int shkinit ( const struct shclass *shp, struct mkroom *sroom) { int sh, sx, sy; struct monst *shk; /* place the shopkeeper in the given room */ sh = sroom->fdoor; sx = doors[sh].x; sy = doors[sh].y; /* check that the shopkeeper placement is sane */ if(sroom->irregular) { int rmno = (sroom - rooms) + ROOMOFFSET; if (isok(sx-1,sy) && !levl[sx-1][sy].edge && (int) levl[sx-1][sy].roomno == rmno) sx--; else if (isok(sx+1,sy) && !levl[sx+1][sy].edge && (int) levl[sx+1][sy].roomno == rmno) sx++; else if (isok(sx,sy-1) && !levl[sx][sy-1].edge && (int) levl[sx][sy-1].roomno == rmno) sy--; else if (isok(sx,sy+1) && !levl[sx][sy+1].edge && (int) levl[sx][sy+1].roomno == rmno) sx++; else goto shk_failed; } else if(sx == sroom->lx-1) sx++; else if(sx == sroom->hx+1) sx--; else if(sy == sroom->ly-1) sy++; else if(sy == sroom->hy+1) sy--; else { shk_failed: return(-1); } if(MON_AT(sx, sy)) (void) rloc(m_at(sx, sy), false); /* insurance */ /* now initialize the shopkeeper monster structure */ if(!(shk = makemon(&mons[PM_SHOPKEEPER], sx, sy, NO_MM_FLAGS))) return(-1); shk->isshk = shk->mpeaceful = 1; set_malign(shk); shk->msleeping = 0; shk->mtrapseen = ~0; /* we know all the traps already */ ESHK(shk)->shoproom = (sroom - rooms) + ROOMOFFSET; sroom->resident = shk; ESHK(shk)->shoptype = sroom->rtype; assign_level(&(ESHK(shk)->shoplevel), &u.uz); ESHK(shk)->shd = doors[sh]; ESHK(shk)->shk.x = sx; ESHK(shk)->shk.y = sy; ESHK(shk)->robbed = 0L; ESHK(shk)->credit = 0L; ESHK(shk)->debit = 0L; ESHK(shk)->loan = 0L; ESHK(shk)->visitct = 0; ESHK(shk)->following = 0; ESHK(shk)->billct = 0; shk->mgold = 1000L + 30L*(long)rnd(100); /* initial capital */ if (shp->shknms == shkrings) (void) mongets(shk, TOUCHSTONE); nameshk(shk, shp->shknms); return(sh); }
/* * Close the drawbridge located at x,y. * Returns TRUE if the drawbridge was closed, FALSE otherwise. */ boolean close_drawbridge(int x, int y) { struct rm *loc1, *loc2; struct monst *m; struct trap *t; int x2, y2; loc1 = &level->locations[x][y]; if (loc1->typ != DRAWBRIDGE_DOWN) return FALSE; /* A huge monster will block the drawbridge. */ if ((m = m_at(level, x, y)) && hugemonst(m->data)) { pline("%s blocks the drawbridge with %s weight!", canseemon(level, m) ? Amonnam(m) : "Something", canseemon(level, m) ? mhis(level, m) : "its"); return FALSE; } if (rn2(5) == 0) { pline("The mechanism seems to have something stuck in it and won't close."); return FALSE; } x2 = x; y2 = y; get_wall_for_db(&x2,&y2); if (cansee(x,y) || cansee(x2,y2)) pline("You see a drawbridge %s up!", (((u.ux == x || u.uy == y) && !Underwater) || distu(x2,y2) < distu(x,y)) ? "coming" : "going"); loc1->typ = DRAWBRIDGE_UP; loc2 = &level->locations[x2][y2]; loc2->typ = DBWALL; switch (loc1->drawbridgemask & DB_DIR) { case DB_NORTH: case DB_SOUTH: loc2->horizontal = TRUE; break; case DB_WEST: case DB_EAST: loc2->horizontal = FALSE; break; } loc2->wall_info = W_NONDIGGABLE; set_entity(x, y, &(occupants[0])); set_entity(x2, y2, &(occupants[1])); do_entity(&(occupants[0])); /* Do set_entity after first */ set_entity(x2, y2, &(occupants[1])); /* do_entity for worm tail */ do_entity(&(occupants[1])); if (OBJ_AT(x, y) && flags.soundok) You_hear("smashing and crushing."); revive_nasty(x,y,NULL); revive_nasty(x2,y2,NULL); delallobj(x, y); delallobj(x2, y2); if ((t = t_at(level, x, y)) != 0) deltrap(level, t); if ((t = t_at(level, x2, y2)) != 0) deltrap(level, t); newsym(x, y); newsym(x2, y2); block_point(x2,y2); /* vision */ return TRUE; }
int do_mname(void) { char buf[BUFSZ]; coord cc; int cx,cy; struct monst *mtmp; char qbuf[QBUFSZ]; if (Hallucination) { pline("You would never recognize it anyway."); return 0; } cc.x = u.ux; cc.y = u.uy; if (getpos(&cc, FALSE, "the monster you want to name") < 0 || (cx = cc.x) < 0) return 0; cy = cc.y; if (cx == u.ux && cy == u.uy) { if (u.usteed && canspotmon(u.usteed)) mtmp = u.usteed; else { pline("This %s creature is called %s and cannot be renamed.", ACURR(A_CHA) > 14 ? (flags.female ? "beautiful" : "handsome") : "ugly", plname); return 0; } } else mtmp = m_at(level, cx, cy); if (!mtmp || (!sensemon(mtmp) && (!(cansee(cx,cy) || see_with_infrared(mtmp)) || mtmp->mundetected || mtmp->m_ap_type == M_AP_FURNITURE || mtmp->m_ap_type == M_AP_OBJECT || (mtmp->minvis && !See_invisible)))) { pline("I see no monster there."); return 0; } /* special case similar to the one in lookat() */ distant_monnam(mtmp, ARTICLE_THE, buf); sprintf(qbuf, "What do you want to call %s?", buf); getlin(qbuf,buf); if (!*buf || *buf == '\033') return 0; /* strip leading and trailing spaces; unnames monster if all spaces */ mungspaces(buf); if (mtmp->data->geno & G_UNIQ) { distant_monnam(mtmp, ARTICLE_THE, buf); *buf = highc(*buf); pline("%s doesn't like being called names!", buf); } else christen_monst(mtmp, buf); return 0; }
static void set_entity(int x, int y, struct entity *etmp) { if ((x == u.ux) && (y == u.uy)) u_to_e(etmp); else if (MON_AT(level, x, y)) m_to_e(m_at(level, x, y), x, y, etmp); else etmp->edata = NULL; }
int do_mname(const struct nh_cmd_arg *arg) { coord cc; int cx, cy; struct monst *mtmp; const char *qbuf, *buf; if (Hallucination) { pline("You would never recognize it anyway."); return 0; } cc.x = u.ux; cc.y = u.uy; if (getargpos(arg, &cc, FALSE, "the monster you want to name") == NHCR_CLIENT_CANCEL || (cx = cc.x) < 0) return 0; cy = cc.y; if (cx == u.ux && cy == u.uy) { if (u.usteed && canspotmon(u.usteed)) mtmp = u.usteed; else { pline("This %s creature is called %s and cannot be renamed.", beautiful(), u.uplname); return 0; } } else mtmp = m_at(level, cx, cy); unsigned msense_status = mtmp ? msensem(&youmonst, mtmp) : 0; if (!(msense_status & ~MSENSE_ITEMMIMIC)) { pline("I see no monster there."); return 0; } else if (!(msense_status & (MSENSE_ANYDETECT | MSENSE_ANYVISION))) { pline("You can't see it well enough to recognise it in the future."); return 0; } /* special case similar to the one in lookat() */ qbuf = distant_monnam(mtmp, NULL, ARTICLE_THE); qbuf = msgprintf("What do you want to call %s?", qbuf); buf = getarglin(arg, qbuf); if (!*buf || *buf == '\033') return 0; /* strip leading and trailing spaces; unnames monster if all spaces */ buf = msgmungspaces(buf); if (mtmp->data->geno & G_UNIQ) { qbuf = msgupcasefirst(distant_monnam(mtmp, NULL, ARTICLE_THE)); pline("%s doesn't like being called names!", qbuf); } else christen_monst(mtmp, buf); return 0; }
STATIC_OVL void set_entity(int x, int y, struct entity *etmp) { if ((x == u.ux) && (y == u.uy)) u_to_e(etmp); else if (MON_AT(x, y)) m_to_e(m_at(x, y), x, y, etmp); else etmp->edata = (struct permonst *)0; }
bool goodpos(int x, int y) /* used only in mnexto and rloc */ { return ( !(x < 1 || x > COLNO - 2 || y < 1 || y > ROWNO - 2 || m_at(x, y) || !ACCESSIBLE(levl[x][y].typ) || (x == u.ux && y == u.uy) || sobj_at(ENORMOUS_ROCK, x, y) )); }
/* used only in mnexto and rloc */ int goodpos(int x, int y) { return( ! (x < 1 || x > COLNO-2 || y < 1 || y > ROWNO-2 || m_at(x,y) || !ACCESSIBLE(levl[x][y].typ) || (x == u.ux && y == u.uy) || sobj_at(ENORMOUS_ROCK, x, y) )); }
int dosearch(void) { xchar x, y; struct trap *trap; struct monst *mtmp; if (u.uswallow) pline("What are you looking for? The exit?"); else for (x = u.ux - 1; x < u.ux + 2; x++) for (y = u.uy - 1; y < u.uy + 2; y++) if (x != u.ux || y != u.uy) { if (levl[x][y].typ == SDOOR) { if (rn2(7)) continue; levl[x][y].typ = DOOR; levl[x][y].seen = 0; // force prl prl(x, y); nomul(0); } else if (levl[x][y].typ == SCORR) { if (rn2(7)) continue; levl[x][y].typ = CORR; levl[x][y].seen = 0; // force prl prl(x, y); nomul(0); } else { // Be careful not to find anything in an SCORR or SDOOR if ((mtmp = m_at(x, y)) != NULL) { if (mtmp->mimic) { seemimic(mtmp); pline("You find a mimic."); return 1; } } for (trap = ftrap; trap; trap = trap->ntrap) { if (trap->tx == x && trap->ty == y && !trap->tseen && !rn2(8)) { nomul(0); pline("You find a%s.", traps[trap->ttyp]); if (trap->ttyp == PIERC) { deltrap(trap); (void) makemon(PM_PIERCER, x, y); return 1; } trap->tseen = 1; if (!vism_at(x, y)) atl(x, y, '^'); } } } } return 1; }
struct monst * boomhit(int dx, int dy) { int i, ct; struct monst *mtmp; char sym = ')'; bhitpos.x = u.ux; bhitpos.y = u.uy; for (i = 0; i < 8; i++) if (xdir[i] == dx && ydir[i] == dy) break; tmp_at(-1, sym); /* open call */ for (ct = 0; ct < 10; ct++) { if (i == 8) i = 0; sym = ')' + '(' - sym; tmp_at(-2, sym); /* change let call */ dx = xdir[i]; dy = ydir[i]; bhitpos.x += dx; bhitpos.y += dy; if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != NULL) { tmp_at(-1, -1); return (mtmp); } if (!ZAP_POS(levl[bhitpos.x][bhitpos.y].typ)) { bhitpos.x -= dx; bhitpos.y -= dy; break; } if (bhitpos.x == u.ux && bhitpos.y == u.uy) { /* ct == 9 */ if (rn2(20) >= 10 + u.ulevel) { /* we hit ourselves */ thitu(10, rnd(10), "boomerang"); break; } else { /* we catch it */ tmp_at(-1, -1); pline("Skillfully, you catch the boomerang."); return (&youmonst); } } tmp_at(bhitpos.x, bhitpos.y); if (ct % 5 != 0) i++; } tmp_at(-1, -1); /* do not leave last symbol */ return (0); }
void newgame() { fobj = invent = level.buriedobjlist = migrating_objs = (struct obj *)0; fmon = migrating_mons = (struct monst *)0; ftrap = 0; flags.ident = 1; if(wiz1_level.dlevel == 0) init_dungeons(); init_objects(); /* must be before u_init() */ u_init(); init_artifacts(); /* must be after u_init() */ #ifndef NO_SIGNAL (void) signal(SIGINT, (SIG_RET_TYPE) done1); #endif #ifdef NEWS if(flags.news) display_file(NEWS, FALSE); #endif #ifdef MULDGN load_qtlist(); /* load up the quest text info */ quest_init(); if(flags.legacy && moves == 1) com_pager(1); #endif mklev(); u_on_upstairs(); check_special_room(FALSE); vision_reset(); /* set up internals for level (after mklev) */ flags.botlx = 1; /* Move the monster from under you or else * makedog() will fail when it calls makemon(). * - ucsfcgl!kneller */ if(MON_AT(u.ux, u.uy)) mnexto(m_at(u.ux, u.uy)); #ifdef CLIPPING cliparound(u.ux, u.uy); #endif (void) makedog(); docrt(); #ifdef INSURANCE save_currentstate(); #endif return; }
int doride(const struct nh_cmd_arg *arg) { boolean forcemount = FALSE; schar dx, dy, dz; if (u.usteed) dismount_steed(DISMOUNT_BYCHOICE); else if (getargdir(arg, NULL, &dx, &dy, &dz) && isok(u.ux + dx, u.uy + dy)) { if (wizard && yn("Force the mount to succeed?") == 'y') forcemount = TRUE; return mount_steed(m_at(level, u.ux + dx, u.uy + dy), forcemount); } else return 0; return 1; }
int breamq(struct monst *mtmp, int xdef, int ydef, const struct attack *mattk) { /* if new breath types are added, change AD_ACID to max type */ int typ = (mattk->adtyp == AD_RBRE) ? rnd(AD_ACID) : mattk->adtyp; boolean youdef = u.ux == xdef && u.uy == ydef; if (!youdef && distmin(mtmp->mx, mtmp->my, xdef, ydef) < 3) return 0; boolean linedup = qlined_up(mtmp, xdef, ydef, TRUE, FALSE); if (linedup) { if (mtmp->mcan) { if (canhear()) { if (mon_visible(mtmp)) pline("%s coughs.", Monnam(mtmp)); else You_hear("a cough."); } return 0; } if (!mtmp->mspec_used && rn2(3)) { if ((typ >= AD_MAGM) && (typ <= AD_ACID)) { if (mon_visible(mtmp)) { pline("%s breathes %s!", Monnam(mtmp), breathwep[typ - 1]); action_interrupted(); } buzz((int)(-20 - (typ - 1)), (int)mattk->damn, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), 0); /* breath runs out sometimes. Also, give monster some cunning; don't breath if the target fell asleep. */ if (!rn2(3)) mtmp->mspec_used = 10 + rn2(20); boolean sleeping = youdef ? u_helpless(hm_asleep) : MON_AT(level, xdef, ydef) ? m_at(level, xdef, ydef)->msleeping : FALSE; if (typ == AD_SLEE && sleeping) mtmp->mspec_used += rnd(20); } else impossible("Breath weapon %d used", typ - 1); } } return 1; }
int wiz_hit(struct monst *mtmp) { /* if we have stolen or found the amulet, we disappear */ if(mtmp->minvent && mtmp->minvent->olet == AMULET_SYM && mtmp->minvent->spe == 0) { /* vanish -- very primitive */ fall_down(mtmp); return(1); } /* if it is lying around someplace, we teleport to it */ if(!carrying(AMULET_OF_YENDOR)) { struct obj *otmp; for(otmp = fobj; otmp; otmp = otmp->nobj) if(otmp->olet == AMULET_SYM && !otmp->spe) { if((u.ux != otmp->ox || u.uy != otmp->oy) && !m_at(otmp->ox, otmp->oy)) { /* teleport to it and pick it up */ mtmp->mx = otmp->ox; mtmp->my = otmp->oy; freeobj(otmp); mpickobj(mtmp, otmp); pmon(mtmp); return(0); } goto hithim; } return(0); /* we don't know where it is */ } hithim: if(rn2(2)) { /* hit - perhaps steal */ /* if hit 1/20 chance of stealing amulet & vanish - amulet is on level 26 again. */ if(hitu(mtmp, d(mtmp->data->damn,mtmp->data->damd)) && !rn2(20) && stealamulet(mtmp)) ; } else inrange(mtmp); /* try magic */ return(0); }
int findit(void) { // returns number of things found int num; xchar zx, zy; struct trap *ttmp; struct monst *mtmp; xchar lx, hx, ly, hy; if (u.uswallow) return 0; for (lx = u.ux; (num = levl[lx - 1][u.uy].typ) && num != CORR; lx--); for (hx = u.ux; (num = levl[hx + 1][u.uy].typ) && num != CORR; hx++); for (ly = u.uy; (num = levl[u.ux][ly - 1].typ) && num != CORR; ly--); for (hy = u.uy; (num = levl[u.ux][hy + 1].typ) && num != CORR; hy++); num = 0; for (zy = ly; zy <= hy; zy++) for (zx = lx; zx <= hx; zx++) { if (levl[zx][zy].typ == SDOOR) { levl[zx][zy].typ = DOOR; atl(zx, zy, '+'); num++; } else if (levl[zx][zy].typ == SCORR) { levl[zx][zy].typ = CORR; atl(zx, zy, CORR_SYM); num++; } else if ((ttmp = t_at(zx, zy)) != NULL) { if (ttmp->ttyp == PIERC) { (void) makemon(PM_PIERCER, zx, zy); num++; deltrap(ttmp); } else if (!ttmp->tseen) { ttmp->tseen = 1; if (!vism_at(zx, zy)) atl(zx, zy, '^'); num++; } } else if ((mtmp = m_at(zx, zy)) != NULL) if (mtmp->mimic) { seemimic(mtmp); num++; } } return num; }
/* ddx, ddy, range: direction and range * sym: symbol displayed on path * fhitm, fhito: fns called when mon/obj hit * obj: 2nd arg to fhitm/fhito */ struct monst * bhit(int ddx, int ddy, int range, char sym, void (*fhitm)(struct monst *, struct obj *), bool (*fhito)(struct obj *, struct obj *), struct obj *obj) { struct monst *mtmp; struct obj *otmp; int typ; bhitpos.x = u.ux; bhitpos.y = u.uy; if (sym) /* open call */ tmp_at(-1, sym); while (range-- > 0) { bhitpos.x += ddx; bhitpos.y += ddy; typ = levl[bhitpos.x][bhitpos.y].typ; if ((mtmp = m_at(bhitpos.x, bhitpos.y))) { if (sym) { tmp_at(-1, -1); /* close call */ return (mtmp); } (*fhitm)(mtmp, obj); range -= 3; } if (fhito && (otmp = o_at(bhitpos.x, bhitpos.y))) { if ((*fhito)(otmp, obj)) range--; } if (!ZAP_POS(typ)) { bhitpos.x -= ddx; bhitpos.y -= ddy; break; } if (sym) tmp_at(bhitpos.x, bhitpos.y); } /* leave last symbol unless in a pool */ if (sym) tmp_at(-1, (levl[bhitpos.x][bhitpos.y].typ == POOL) ? -1 : 0); return (0); }
static boolean obstructed(int x, int y, enum msg_channel msgc) { struct monst *mtmp = m_at(level, x, y); if (mtmp && mtmp->m_ap_type != M_AP_FURNITURE) { if (mtmp->m_ap_type == M_AP_OBJECT) goto objhere; reveal_monster_at(x, y, TRUE); pline(msgc, "%s stands in the way!", !canspotmon(mtmp) ? "Some creature" : Monnam(mtmp)); return TRUE; } if (OBJ_AT(x, y)) { objhere: pline(msgc, "Something's in the way."); return TRUE; } return FALSE; }
/* Choose location where spell takes effect. */ static int throwspell(schar *dx, schar *dy, const struct nh_cmd_arg *arg) { coord cc; if (u.uinwater) { pline("You're joking! In this weather?"); return 0; } else if (Is_waterlevel(&u.uz)) { pline("You had better wait for the sun to come out."); return 0; } pline("Where do you want to cast the spell?"); cc.x = u.ux; cc.y = u.uy; if (getargpos(arg, &cc, FALSE, "the desired position") == NHCR_CLIENT_CANCEL) return 0; /* user pressed ESC */ /* The number of moves from hero to where the spell drops. */ if (distmin(u.ux, u.uy, cc.x, cc.y) > 10) { pline("The spell dissipates over the distance!"); return 0; } else if (Engulfed) { pline("The spell is cut short!"); exercise(A_WIS, FALSE); /* What were you THINKING! */ *dx = 0; *dy = 0; return 1; } else if ((!cansee(cc.x, cc.y) && (!MON_AT(level, cc.x, cc.y) || !canspotmon(m_at(level, cc.x, cc.y)))) || IS_STWALL(level->locations[cc.x][cc.y].typ)) { pline("Your mind fails to lock onto that location!"); return 0; } else { *dx = cc.x; *dy = cc.y; return 1; } }
static void restfakecorr() { int fcx,fcy,fcbeg; struct rm *crm; while((fcbeg = EGD->fcbeg) < EGD->fcend) { fcx = EGD->fakecorr[fcbeg].fx; fcy = EGD->fakecorr[fcbeg].fy; if((u.ux == fcx && u.uy == fcy) || cansee(fcx,fcy) || m_at(fcx,fcy)) return; crm = &levl[fcx][fcy]; crm->typ = EGD->fakecorr[fcbeg].ftyp; if(!crm->typ) crm->seen = 0; newsym(fcx,fcy); EGD->fcbeg++; } /* it seems he left the corridor - let the guard disappear */ mondead(guard); guard = 0; }
/* Be sure this corresponds with what happens to player-thrown objects in * dothrow.c (for consistency). --KAA * Returns 0 if object still exists (not destroyed). */ static int drop_throw(struct obj *obj, boolean ohit, int x, int y) { int retvalu = 1; int create; struct monst *mtmp; struct trap *t; if (breaks(obj, x, y)) return 1; if (ohit && (is_multigen(obj) || obj->otyp == ROCK)) create = !rn2(3); else create = 1; if (create && !((mtmp = m_at(level, x, y)) && (mtmp->mtrapped) && (t = t_at(level, x, y)) && (is_pit_trap(t->ttyp)))) { int objgone = 0; if (down_gate(x, y) != -1) objgone = ship_object(obj, x, y, FALSE); if (!objgone) { if (!flooreffects(obj, x, y, "fall")) { /* don't double-dip on damage */ place_object(obj, level, x, y); if (!mtmp && x == u.ux && y == u.uy) mtmp = &youmonst; if (mtmp && ohit) passive_obj(mtmp, obj, NULL); stackobj(obj); retvalu = 0; } } } else obfree(obj, NULL); return retvalu; }
static bool clear_fcorr(struct monst *grd, bool forceshow) { int fcx, fcy, fcbeg; struct monst *mtmp; if (!on_level(&(EGD(grd)->gdlevel), &u.uz)) return true; while ((fcbeg = EGD(grd)->fcbeg) < EGD(grd)->fcend) { fcx = EGD(grd)->fakecorr[fcbeg].fx; fcy = EGD(grd)->fakecorr[fcbeg].fy; if ((grd->mhp <= 0 || !in_fcorridor(grd, u.ux, u.uy)) && EGD(grd)->gddone) forceshow = true; if ((u.ux == fcx && u.uy == fcy && grd->mhp > 0) || (!forceshow && couldsee(fcx, fcy)) || (Punished && !carried(uball) && uball->ox == fcx && uball->oy == fcy)) return false; if ((mtmp = m_at(fcx, fcy)) != 0) { if (mtmp->isgd) return (false); else if (!in_fcorridor(grd, u.ux, u.uy)) { if (mtmp->mtame) yelp(mtmp); (void)rloc(mtmp, false); } } levl[fcx][fcy].typ = EGD(grd)->fakecorr[fcbeg].ftyp; map_location(fcx, fcy, 1); /* bypass vision */ if (!ACCESSIBLE(levl[fcx][fcy].typ)) block_point(fcx, fcy); EGD(grd)->fcbeg++; } if (grd->mhp <= 0) { pline_The("corridor disappears."); if (IS_ROCK(levl[u.ux][u.uy].typ)) You("are encased in rock."); } return (true); }
/* * called with [x,y] = coordinates; * [0,0] means anyplace * [u.ux,u.uy] means: call mnexto (if !in_mklev) * * In case we make an Orc or killer bee, we make an entire horde (swarm); * note that in this case we return only one of them (the one at [x,y]). */ struct monst * makemon(struct permonst *ptr, int x, int y) { struct monst *mtmp; int tmp, ct; boolean anything = (!ptr); extern boolean in_mklev; if(x != 0 || y != 0) if(m_at(x,y)) return((struct monst *) 0); if(ptr){ if(strchr(fut_geno, ptr->mlet)) return((struct monst *) 0); } else { ct = CMNUM - strlen(fut_geno); if(strchr(fut_geno, 'm')) ct++; /* make only 1 minotaur */ if(strchr(fut_geno, '@')) ct++; if(ct <= 0) return(0); /* no more monsters! */ tmp = rn2(ct*dlevel/24 + 7); if(tmp < dlevel - 4) tmp = rn2(ct*dlevel/24 + 12); if(tmp >= ct) tmp = rn1(ct - ct/2, ct/2); for(ct = 0; ct < CMNUM; ct++){ ptr = &mons[ct]; if(strchr(fut_geno, ptr->mlet)) continue; if(!tmp--) goto gotmon; } panic("makemon?"); } gotmon: mtmp = newmonst(ptr->pxlth); *mtmp = zeromonst; /* clear all entries in structure */ for(ct = 0; ct < ptr->pxlth; ct++) ((char *) &(mtmp->mextra[0]))[ct] = 0; mtmp->nmon = fmon; fmon = mtmp; mtmp->m_id = flags.ident++; mtmp->data = ptr; mtmp->mxlth = ptr->pxlth; if(ptr->mlet == 'D') mtmp->mhpmax = mtmp->mhp = 80; else if(!ptr->mlevel) mtmp->mhpmax = mtmp->mhp = rnd(4); else mtmp->mhpmax = mtmp->mhp = d(ptr->mlevel, 8); mtmp->mx = x; mtmp->my = y; mtmp->mcansee = 1; if(ptr->mlet == 'M'){ mtmp->mimic = 1; mtmp->mappearance = ']'; } if(!in_mklev) { if(x == u.ux && y == u.uy && ptr->mlet != ' ') mnexto(mtmp); if(x == 0 && y == 0) rloc(mtmp); } if(ptr->mlet == 's' || ptr->mlet == 'S') { mtmp->mhide = mtmp->mundetected = 1; if(in_mklev) if(mtmp->mx && mtmp->my) (void) mkobj_at(0, mtmp->mx, mtmp->my); } if(ptr->mlet == ':') { mtmp->cham = 1; (void) newcham(mtmp, &mons[dlevel+14+rn2(CMNUM-14-dlevel)]); } if(ptr->mlet == 'I' || ptr->mlet == ';') mtmp->minvis = 1; if(ptr->mlet == 'L' || ptr->mlet == 'N' || (in_mklev && strchr("&w;", ptr->mlet) && rn2(5)) ) mtmp->msleep = 1; #ifndef NOWORM if(ptr->mlet == 'w' && getwn(mtmp)) initworm(mtmp); #endif /* NOWORM */ if(anything) if(ptr->mlet == 'O' || ptr->mlet == 'k') { coord mm; int cnt = rnd(10); mm.x = x; mm.y = y; while(cnt--) { mm = enexto(mm.x, mm.y); (void) makemon(ptr, mm.x, mm.y); } } return(mtmp); }
int dotalk(const struct nh_cmd_arg *arg) { struct monst *mtmp; int tx, ty; struct obj *otmp; schar dx; schar dy; schar dz; if (!getargdir(arg, NULL, &dx, &dy, &dz)) { /* decided not to chat */ return 0; } if (is_silent(youmonst.data)) { pline("As %s, you cannot speak.", an(youmonst.data->mname)); return 0; } if (Strangled) { pline("You can't speak. You're choking!"); return 0; } if (Engulfed) { pline("They won't hear you out there."); return 0; } if (Underwater) { pline("Your speech is unintelligible underwater."); return 0; } if (!Blind && (otmp = shop_object(u.ux, u.uy)) != NULL) { /* standing on something in a shop and chatting causes the shopkeeper to describe the price(s). This can inhibit other chatting inside a shop, but that shouldn't matter much. shop_object() returns an object iff inside a shop and the shopkeeper is present and willing (not angry) and able (not asleep) to speak and the position contains any objects other than just gold. */ price_quote(otmp); return 1; } if (u.usteed && dz > 0) { if (!u.usteed->mcanmove || u.usteed->msleeping) { pline("Your steed remains silent..."); return 0; } return domonnoise(u.usteed); } if (dz) { pline("They won't hear you %s there.", dz < 0 ? "up" : "down"); return 0; } if (dx == 0 && dy == 0) { if (u.umonnum == PM_ETTIN) { pline("You discover that your other head makes boring conversation."); return 0; } pline("Talking to yourself is a bad habit for a dungeoneer."); return 0; } tx = u.ux + dx; ty = u.uy + dy; if (!isok(tx, ty)) { pline("You call out into the abyss, but nobody hears you."); return 0; } mtmp = m_at(level, tx, ty); /* Do we try to close a door on the square? We do if a) the square is known by the player to be a doorway, b) there's no invisible-I marker there, c) there's no monster in a chattable state there. */ if (!mtmp || mtmp->mundetected || mtmp->m_ap_type == M_AP_FURNITURE || mtmp->m_ap_type == M_AP_OBJECT) { int membg = level->locations[tx][ty].mem_bg; if (membg == S_vodoor || membg == S_vcdoor || membg == S_ndoor || membg == S_hodoor || membg == S_hcdoor) { if (!level->locations[tx][ty].mem_invis) { struct nh_cmd_arg newarg; arg_from_delta(dx, dy, dz, &newarg); return doclose(&newarg); } } pline("You start talking, but nobody seems to hear you."); return 0; } /* sleeping monsters won't talk, except priests (who wake up) */ if ((!mtmp->mcanmove || mtmp->msleeping) && !mtmp->ispriest) { /* If it is unseen, the player can't tell the difference between not noticing him and just not existing, so skip the message. */ if (canspotmon(mtmp)) pline("%s seems not to notice you.", Monnam(mtmp)); else pline("You start talking, but nobody seems to hear you."); return 0; } /* if this monster is waiting for something, prod it into action */ mtmp->mstrategy &= ~STRAT_WAITMASK; if (mtmp->mtame && mtmp->meating) { if (!canspotmon(mtmp)) map_invisible(mtmp->mx, mtmp->my); pline("%s is eating noisily.", Monnam(mtmp)); return 0; } return domonnoise(mtmp); }
/* create a new shopkeeper in the given room; uses level creation RNG */ static int shkinit(const struct shclass *shp, struct level *lev, struct mkroom *sroom) { int sh, sx, sy; struct monst *shk; /* place the shopkeeper in the given room */ sh = sroom->fdoor; sx = lev->doors[sh].x; sy = lev->doors[sh].y; /* check that the shopkeeper placement is sane */ if (sroom->irregular) { int rmno = (sroom - lev->rooms) + ROOMOFFSET; if (isok(sx - 1, sy) && !lev->locations[sx - 1][sy].edge && (int)lev->locations[sx - 1][sy].roomno == rmno) sx--; else if (isok(sx + 1, sy) && !lev->locations[sx + 1][sy].edge && (int)lev->locations[sx + 1][sy].roomno == rmno) sx++; else if (isok(sx, sy - 1) && !lev->locations[sx][sy - 1].edge && (int)lev->locations[sx][sy - 1].roomno == rmno) sy--; else if (isok(sx, sy + 1) && !lev->locations[sx][sy + 1].edge && (int)lev->locations[sx][sy + 1].roomno == rmno) sx++; else goto shk_failed; } else if (sx == sroom->lx - 1) sx++; else if (sx == sroom->hx + 1) sx--; else if (sy == sroom->ly - 1) sy++; else if (sy == sroom->hy + 1) sy--; else { shk_failed: return -1; } if (MON_AT(lev, sx, sy)) rloc(m_at(lev, sx, sy), FALSE); /* insurance */ /* now initialize the shopkeeper monster structure */ if (!(shk = makemon(&mons[PM_SHOPKEEPER], lev, sx, sy, MM_ALLLEVRNG))) return -1; shk->isshk = 1; msethostility(shk, FALSE, TRUE); shk->msleeping = 0; shk->mtrapseen = ~0; /* we know all the traps already */ ESHK(shk)->shoproom = (sroom - lev->rooms) + ROOMOFFSET; sroom->resident = shk; ESHK(shk)->shoptype = sroom->rtype; assign_level(&(ESHK(shk)->shoplevel), &lev->z); ESHK(shk)->shd = lev->doors[sh]; ESHK(shk)->shk.x = sx; ESHK(shk)->shk.y = sy; ESHK(shk)->robbed = 0L; ESHK(shk)->credit = 0L; ESHK(shk)->debit = 0L; ESHK(shk)->loan = 0L; ESHK(shk)->visitct = 0; ESHK(shk)->following = 0; ESHK(shk)->billct = 0; ESHK(shk)->bill_inactive = FALSE; /* initial capital */ mkmonmoney(shk, 1030L + 30L * mklev_rn2(100, lev), rng_for_level(&lev->z)); if (shp->shknms == shkrings) mongets(shk, TOUCHSTONE, rng_for_level(&lev->z)); nameshk(shk, shp->shknms, lev); return sh; }