/* * Open the drawbridge located at x,y */ void open_drawbridge(int x, int y) { struct rm *loc1, *loc2; struct trap *t; int x2, y2; loc1 = &level->locations[x][y]; if (loc1->typ != DRAWBRIDGE_UP) return; x2 = x; y2 = y; get_wall_for_db(&x2,&y2); if (cansee(x,y) || cansee(x2,y2)) pline("You see a drawbridge %s down!", (distu(x2,y2) < distu(x,y)) ? "going" : "coming"); loc1->typ = DRAWBRIDGE_DOWN; loc2 = &level->locations[x2][y2]; loc2->typ = DOOR; loc2->doormask = D_NODOOR; 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 tails */ do_entity(&(occupants[1])); revive_nasty(x,y,NULL); delallobj(x, y); 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); unblock_point(x2,y2); /* vision */ if (Is_stronghold(&u.uz)) u.uevent.uopened_dbridge = TRUE; }
/* * 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; }
/* * Close the drawbridge located at x,y */ void close_drawbridge(int x, int y) { struct rm *loc1, *loc2; struct trap *t; int x2, y2; loc1 = &level->locations[x][y]; if (loc1->typ != DRAWBRIDGE_DOWN) return; 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"); else if (canhear()) pline("You hear chains rattling and gears turning."); 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)) 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); del_engr_at(level, x, y); del_engr_at(level, x2, y2); newsym(x, y); newsym(x2, y2); block_point(x2, y2); /* vision */ }
static void mkswamp(struct level *lev) { struct mkroom *sroom; int sx, sy, i, eelct = 0; for (i = 0; i < 5; i++) { /* turn up to 5 rooms swampy */ sroom = &lev->rooms[rn2(lev->nroom)]; if (sroom->hx < 0 || sroom->rtype != OROOM || has_upstairs(lev, sroom) || has_dnstairs(lev, 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 (!OBJ_AT_LEV(lev, sx, sy) && !MON_AT(lev, sx, sy) && !t_at(lev, sx, sy) && !nexttodoor(lev, sx, sy)) { if ((sx + sy) % 2) { lev->locations[sx][sy].typ = POOL; if (!eelct || !rn2(4)) { /* mkclass() won't do, as we might get kraken */ makemon(rn2(5) ? &mons[PM_GIANT_EEL] : rn2(2) ? &mons[PM_PIRANHA] : &mons[PM_ELECTRIC_EEL], lev, sx, sy, NO_MM_FLAGS); eelct++; } } else if (!rn2(4)) /* swamps tend to be moldy */ makemon(mkclass(&lev->z, S_FUNGUS, 0), lev, sx, sy, NO_MM_FLAGS); } lev->flags.has_swamp = 1; } }
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++; } } } }
void dighole() { struct trap *ttmp = t_at(u.ux, u.uy); if(!xdnstair) { pline("The floor here seems too hard to dig in."); } else { if(ttmp) ttmp->ttyp = TRAPDOOR; else ttmp = maketrap(u.ux, u.uy, TRAPDOOR); ttmp->tseen = 1; pline("You've made a hole in the floor."); if(!u.ustuck) { if(inshop()) shopdig(1); pline("You fall through ..."); if(u.utraptype == TT_PIT) { u.utrap = 0; u.utraptype = 0; } goto_level(dlevel+1, FALSE); } } }
static boolean teleok(int x, int y, boolean trapok) { if (!trapok && t_at(level, x, y)) return FALSE; if (!goodpos(level, x, y, &youmonst, 0)) return FALSE; if (!tele_jump_ok(u.ux, u.uy, x, y)) return FALSE; if (!in_out_region(level, x, y)) return FALSE; return TRUE; }
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; }
/* * Try to find a dismount point adjacent to the steed's location. * If all else fails, try enexto(). Use enexto() as a last resort because * enexto() chooses its point randomly, possibly even outside the * room's walls, which is not what we want. * Adapted from mail daemon code. */ static boolean landing_spot(coord * spot, /* landing position (we fill it in) */ int reason, int forceit) { int i = 0, x, y, distance, min_distance = -1; boolean found = FALSE; struct trap *t; /* avoid known traps (i == 0) and boulders, but allow them as a backup */ if (reason != DISMOUNT_BYCHOICE || Stunned || Confusion || Fumbling) i = 1; for (; !found && i < 2; ++i) { for (x = u.ux - 1; x <= u.ux + 1; x++) for (y = u.uy - 1; y <= u.uy + 1; y++) { if (!isok(x, y) || (x == u.ux && y == u.uy)) continue; if (ACCESSIBLE(level->locations[x][y].typ) && !MON_AT(level, x, y) && !closed_door(level, x, y)) { distance = distu(x, y); if (min_distance < 0 || distance < min_distance || (distance == min_distance && rn2(2))) { if (i > 0 || (((t = t_at(level, x, y)) == 0 || !t->tseen) && (!sobj_at(BOULDER, level, x, y) || throws_rocks(youmonst.data)))) { spot->x = x; spot->y = y; min_distance = distance; found = TRUE; } } } } } /* If we didn't find a good spot and forceit is on, try enexto(). */ if (forceit && min_distance < 0 && !enexto(spot, level, u.ux, u.uy, youmonst.data)) return FALSE; return found; }
static void dowatersnakes() /* Fountain of snakes! */ { register int num = rn1(5,2); struct monst *mtmp; if (!(mons[PM_WATER_MOCCASIN].geno & (G_GENOD | G_EXTINCT))) { if (!Blind) pline("An endless stream of %s pours forth!", Hallucination ? makeplural(rndmonnam()) : "snakes"); else You("hear something hissing!"); while(num-- > 0) if((mtmp = makemon(&mons[PM_WATER_MOCCASIN],u.ux,u.uy)) && t_at(mtmp->mx, mtmp->my)) (void) mintrap(mtmp); } else pline("The fountain bubbles furiously for a moment, then calms."); }
static void dowaternymph() /* Water Nymph */ { register struct monst *mtmp; if(mons[PM_WATER_NYMPH].geno & (G_GENOD | G_EXTINCT)) return; if((mtmp = makemon(&mons[PM_WATER_NYMPH],u.ux,u.uy))) { if (!Blind) You("attract %s!", a_monnam(mtmp)); else You("hear a seductive voice."); mtmp->msleep = 0; if (t_at(mtmp->mx, mtmp->my)) (void) mintrap(mtmp); } else if (!Blind) pline("A large bubble rises to the surface and pops."); else You("hear a loud pop."); }
/* 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 void dowaterdemon() /* Water demon */ { register struct monst *mtmp; if(mons[PM_WATER_DEMON].geno & (G_GENOD | G_EXTINCT)) return; if((mtmp = makemon(&mons[PM_WATER_DEMON],u.ux,u.uy))) { if (!Blind) You("unleash %s!", a_monnam(mtmp)); else You("feel the presence of evil."); /* Give those on low levels a (slightly) better chance of survival */ if (rnd(100) > (80 + level_difficulty())) { pline("Grateful for %s release, %s grants you a wish!", his[pronoun_gender(mtmp)], he[pronoun_gender(mtmp)]); makewish(); mongone(mtmp); } else if (t_at(mtmp->mx, mtmp->my)) (void) mintrap(mtmp); } }
static void describe_mon(int x, int y, int monnum, char *buf) { char race[QBUFSZ]; const char *name; boolean accurate = !Hallucination; char steedbuf[BUFSZ]; struct monst *mtmp; char visionbuf[BUFSZ], temp_buf[BUFSZ]; static const int maximum_output_len = 78; if (monnum == -1) return; if (u.ux == x && u.uy == y && senseself()) { /* if not polymorphed, show both the role and the race */ race[0] = 0; if (!Upolyd) snprintf(race, SIZE(race), "%s ", urace.adj); sprintf(buf, "%s%s%s called %s", Invis ? "invisible " : "", race, mons[u.umonnum].mname, u.uplname); if (u.usteed) { snprintf(steedbuf, SIZE(steedbuf), ", mounted on %s", y_monnam(u.usteed)); /* assert((sizeof buf >= strlen(buf)+strlen(steedbuf)+1); */ strcat(buf, steedbuf); } /* When you see yourself normally, no explanation is appended (even if you could also see yourself via other means). Sensing self while blind or swallowed is treated as if it were by normal vision (cf canseeself()). */ if ((Invisible || u.uundetected) && !Blind && !Engulfed) { unsigned how = 0; if (Infravision) how |= 1; if (Unblind_telepat) how |= 2; if (Detect_monsters) how |= 4; if (how) sprintf(buf + strlen(buf), " [seen: %s%s%s%s%s]", (how & 1) ? "infravision" : "", /* add comma if telep and infrav */ ((how & 3) > 2) ? ", " : "", (how & 2) ? "telepathy" : "", /* add comma if detect and (infrav or telep or both) */ ((how & 7) > 4) ? ", " : "", (how & 4) ? "monster detection" : ""); } } else if (monnum >= NUMMONS) { monnum -= NUMMONS; if (monnum < WARNCOUNT) strcat(buf, warnexplain[monnum]); } else if ((mtmp = m_at(level, x, y))) { bhitpos.x = x; bhitpos.y = y; if (mtmp->data == &mons[PM_COYOTE] && accurate && !mtmp->mpeaceful) name = an(coyotename(mtmp)); else name = distant_monnam( mtmp, (mtmp->mtame && accurate) ? "tame" : (mtmp->mpeaceful && accurate) ? "peaceful" : NULL, ARTICLE_A); boolean spotted = canspotmon(mtmp); if (!spotted && (mtmp->mx != x || mtmp->my != y)) name = "an unseen long worm"; else if (!spotted) /* we can't safely impossible/panic from this point in the code; well, we /could/, but as it's called on every mouse movement, it'd quickly get very confusing and possibly lead to recursive panics; just put up an obvious message instead */ name = "a <BUG: monster both seen and unseen>"; snprintf(buf, BUFSZ-1, "%s%s", (mtmp->mx != x || mtmp->my != y) ? "tail of " : "", name); buf[BUFSZ-1] = '\0'; if (u.ustuck == mtmp) strcat(buf, (Upolyd && sticks(youmonst.data)) ? ", being held" : ", holding you"); if (mtmp->mleashed) strcat(buf, ", leashed to you"); if (mtmp->mtrapped && cansee(mtmp->mx, mtmp->my)) { struct trap *t = t_at(level, mtmp->mx, mtmp->my); int tt = t ? t->ttyp : NO_TRAP; /* newsym lets you know of the trap, so mention it here */ if (tt == BEAR_TRAP || tt == PIT || tt == SPIKED_PIT || tt == WEB) sprintf(buf + strlen(buf), ", trapped in %s", an(trapexplain[tt - 1])); } #ifdef DEBUG_STRATEGY if (wizard) { snprintf(temp_buf, SIZE(temp_buf), ", strategy %08lx, muxy %02x%02x", (unsigned long)mtmp->mstrategy, (int)mtmp->mux, (int)mtmp->muy); strncat(buf, temp_buf, maximum_output_len - strlen(buf) - 1); } #endif /* Don't mention how a long worm tail is seen; msensem() only works on monster heads. (Probably, the only unusual way to see a long worm tail is see invisible, anyway.) */ if (mtmp->mx == x && mtmp->my == y) { mon_vision_summary(mtmp, visionbuf); if (visionbuf[0]) { snprintf(temp_buf, SIZE(temp_buf), " [seen: %s]", visionbuf); strncat(buf, temp_buf, maximum_output_len - strlen(buf) - 1); } } } }
int dospinweb(void) { struct trap *ttmp = t_at(level, u.ux, u.uy); if (Levitation || Is_airlevel(&u.uz) || Underwater || Is_waterlevel(&u.uz)) { pline("You must be on the ground to spin a web."); return 0; } if (u.uswallow) { pline("You release web fluid inside %s.", mon_nam(u.ustuck)); if (is_animal(u.ustuck->data)) { expels(u.ustuck, u.ustuck->data, TRUE); return 0; } if (is_whirly(u.ustuck->data)) { int i; for (i = 0; i < NATTK; i++) if (u.ustuck->data->mattk[i].aatyp == AT_ENGL) break; if (i == NATTK) impossible("Swallower has no engulfing attack?"); else { char sweep[30]; sweep[0] = '\0'; switch(u.ustuck->data->mattk[i].adtyp) { case AD_FIRE: strcpy(sweep, "ignites and "); break; case AD_ELEC: strcpy(sweep, "fries and "); break; case AD_COLD: strcpy(sweep, "freezes, shatters and "); break; } pline("The web %sis swept away!", sweep); } return 0; } /* default: a nasty jelly-like creature */ pline("The web dissolves into %s.", mon_nam(u.ustuck)); return 0; } if (u.utrap) { pline("You cannot spin webs while stuck in a trap."); return 0; } exercise(A_DEX, TRUE); if (ttmp) switch (ttmp->ttyp) { case PIT: case SPIKED_PIT: pline("You spin a web, covering up the pit."); deltrap(ttmp); bury_objs(u.ux, u.uy); newsym(u.ux, u.uy); return 1; case SQKY_BOARD: pline("The squeaky board is muffled."); deltrap(ttmp); newsym(u.ux, u.uy); return 1; case TELEP_TRAP: case LEVEL_TELEP: case MAGIC_PORTAL: case VIBRATING_SQUARE: pline("Your webbing vanishes!"); return 0; case WEB: pline("You make the web thicker."); return 1; case HOLE: case TRAPDOOR: pline("You web over the %s.", (ttmp->ttyp == TRAPDOOR) ? "trap door" : "hole"); deltrap(ttmp); newsym(u.ux, u.uy); return 1; case ROLLING_BOULDER_TRAP: pline("You spin a web, jamming the trigger."); deltrap(ttmp); newsym(u.ux, u.uy); return 1; case ARROW_TRAP: case DART_TRAP: case BEAR_TRAP: case ROCKTRAP: case FIRE_TRAP: case LANDMINE: case SLP_GAS_TRAP: case RUST_TRAP: case MAGIC_TRAP: case ANTI_MAGIC: case POLY_TRAP: pline("You have triggered a trap!"); dotrap(ttmp, 0); return 1; default: impossible("Webbing over trap type %d?", ttmp->ttyp); return 0; } else if (On_stairs(u.ux, u.uy)) { /* cop out: don't let them hide the stairs */ pline("Your web fails to impede access to the %s.", (level->locations[u.ux][u.uy].typ == STAIRS) ? "stairs" : "ladder"); return 1; } ttmp = maketrap(level, u.ux, u.uy, WEB); if (ttmp) { ttmp->tseen = 1; ttmp->madeby_u = 1; } newsym(u.ux, u.uy); return 1; }
bool intersectAsLine(double minT1, double maxT1, double minT2, double maxT2, bool treat1AsLine, bool treat2AsLine) { _Line line1, line2; if (intersections.swapped()) { std::swap(treat1AsLine, treat2AsLine); std::swap(minT1, minT2); std::swap(maxT1, maxT2); } if (coinMinT1 >= 0) { bool earlyExit; if ((earlyExit = coinMaxT1 == minT1)) { coinMaxT1 = maxT1; } if (coinMaxT2 == minT2) { coinMaxT2 = maxT2; return true; } if (earlyExit) { return true; } coinMinT1 = -1; } // do line/quadratic or even line/line intersection instead if (treat1AsLine) { xy_at_t(quad1, minT1, line1[0].x, line1[0].y); xy_at_t(quad1, maxT1, line1[1].x, line1[1].y); } if (treat2AsLine) { xy_at_t(quad2, minT2, line2[0].x, line2[0].y); xy_at_t(quad2, maxT2, line2[1].x, line2[1].y); } int pts; double smallT1, largeT1, smallT2, largeT2; if (treat1AsLine & treat2AsLine) { double t1[2], t2[2]; pts = ::intersect(line1, line2, t1, t2); if (pts == 2) { smallT1 = interp(minT1, maxT1, t1[0]); largeT1 = interp(minT2, maxT2, t2[0]); smallT2 = interp(minT1, maxT1, t1[1]); largeT2 = interp(minT2, maxT2, t2[1]); intersections.addCoincident(smallT1, smallT2, largeT1, largeT2); } else { smallT1 = interp(minT1, maxT1, t1[0]); largeT1 = interp(minT2, maxT2, t2[0]); intersections.add(smallT1, largeT1); } } else { Intersections lq; pts = ::intersect(treat1AsLine ? quad2 : quad1, treat1AsLine ? line1 : line2, lq); if (pts == 2) { // if the line and edge are coincident treat differently _Point midQuad, midLine; double midQuadT = (lq.fT[0][0] + lq.fT[0][1]) / 2; xy_at_t(treat1AsLine ? quad2 : quad1, midQuadT, midQuad.x, midQuad.y); double lineT = t_at(treat1AsLine ? line1 : line2, midQuad); xy_at_t(treat1AsLine ? line1 : line2, lineT, midLine.x, midLine.y); if (AlmostEqualUlps(midQuad.x, midLine.x) && AlmostEqualUlps(midQuad.y, midLine.y)) { smallT1 = lq.fT[0][0]; largeT1 = lq.fT[1][0]; smallT2 = lq.fT[0][1]; largeT2 = lq.fT[1][1]; if (treat2AsLine) { smallT1 = interp(minT1, maxT1, smallT1); smallT2 = interp(minT1, maxT1, smallT2); } else { largeT1 = interp(minT2, maxT2, largeT1); largeT2 = interp(minT2, maxT2, largeT2); } intersections.addCoincident(smallT1, smallT2, largeT1, largeT2); goto setCoinMinMax; } } for (int index = 0; index < pts; ++index) { smallT1 = lq.fT[0][index]; largeT1 = lq.fT[1][index]; if (treat2AsLine) { smallT1 = interp(minT1, maxT1, smallT1); } else { largeT1 = interp(minT2, maxT2, largeT1); } intersections.add(smallT1, largeT1); } } if (pts > 0) { setCoinMinMax: coinMinT1 = minT1; coinMaxT1 = maxT1; coinMinT2 = minT2; coinMaxT2 = maxT2; } return pts > 0; }
/* * Let's destroy the drawbridge located at x,y */ void destroy_drawbridge(int x, int y) { struct rm *loc1, *loc2; struct trap *t; int x2, y2; int db_u; boolean e_inview; struct entity *etmp1 = &(occupants[0]), *etmp2 = &(occupants[1]); loc1 = &level->locations[x][y]; if (!IS_DRAWBRIDGE(loc1->typ)) return; x2 = x; y2 = y; get_wall_for_db(&x2,&y2); loc2 = &level->locations[x2][y2]; db_u = (loc1->drawbridgemask & DB_UNDER); if (db_u == DB_MOAT || db_u == DB_LAVA || db_u == DB_BOG) { struct obj *otmp; int where = (db_u == DB_LAVA) ? 0 : (db_u == DB_MOAT) ? 1 : 2; static char *wstr[3] = { "lava", "moat", "swamp" }; if (loc1->typ == DRAWBRIDGE_UP) { if (cansee(x2,y2)) pline("The portcullis of the drawbridge falls into the %s!", wstr[where]); else if (flags.soundok) You_hear("a loud *SPLASH*!"); } else { if (cansee(x,y)) pline("The drawbridge collapses into the %s!", wstr[where]); else if (flags.soundok) You_hear("a loud *SPLASH*!"); } loc1->typ = (where == 0) ? LAVAPOOL : (where == 1) ? MOAT : BOG; loc1->drawbridgemask = 0; if ((otmp = sobj_at(BOULDER, level, x,y)) != 0) { obj_extract_self(otmp); flooreffects(otmp,x,y,"fall"); } } else { if (cansee(x,y)) pline("The drawbridge disintegrates!"); else You_hear("a loud *CRASH*!"); loc1->typ = ((loc1->drawbridgemask & DB_ICE) ? ICE : ROOM); loc1->icedpool = ((loc1->drawbridgemask & DB_ICE) ? ICED_MOAT : 0); } wake_nearto(x, y, 500); loc2->typ = DOOR; loc2->doormask = D_NODOOR; 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); if (!does_block(level, x2, y2, NULL)) unblock_point(x2,y2); /* vision */ if (Is_stronghold(&u.uz)) u.uevent.uopened_dbridge = TRUE; set_entity(x2, y2, etmp2); /* currently only automissers can be here */ if (etmp2->edata) { e_inview = e_canseemon(level, etmp2); if (!automiss(etmp2)) { if (e_inview) pline("%s blown apart by flying debris.", E_phrase(etmp2, "are")); killer_format = KILLED_BY_AN; killer = "exploding drawbridge"; e_died(etmp2, e_inview? 3 : 2, CRUSHING); /*no corpse*/ } /* nothing which is vulnerable can survive this */ } set_entity(x, y, etmp1); if (etmp1->edata) { e_inview = e_canseemon(level, etmp1); if (!e_missed(etmp1, TRUE)) { if (e_inview) { if (!is_u(etmp1) && Hallucination) pline("%s into some heavy metal!", E_phrase(etmp1, "get")); else pline("%s hit by a huge chunk of metal!", E_phrase(etmp1, "are")); } else { if (flags.soundok && !is_u(etmp1) && !is_pool(level, x,y)) You_hear("a crushing sound."); } killer_format = KILLED_BY_AN; killer = "collapsing drawbridge"; e_died(etmp1, e_inview? 3 : 2, CRUSHING); /*no corpse*/ if (loc1->typ == MOAT) do_entity(etmp1); } } }
/* return TRUE if the caller needs to place the ball and chain down again * * Should not be called while swallowed. Should be called before movement, * because we might want to move the ball or chain to the hero's old position. * * It is called if we are moving. It is also called if we are teleporting * *if* the ball doesn't move and we thus must drag the chain. It is not * called for ordinary teleportation. * * allow_drag is only used in the ugly special case where teleporting must * drag the chain, while an identical-looking movement must drag both the ball * and chain. */ boolean drag_ball(xchar x, xchar y, int *bc_control, xchar * ballx, xchar * bally, xchar * chainx, xchar * chainy, boolean * cause_delay, boolean allow_drag) { struct trap *t = NULL; boolean already_in_rock; *ballx = uball->ox; *bally = uball->oy; *chainx = uchain->ox; *chainy = uchain->oy; *bc_control = 0; *cause_delay = FALSE; if (dist2(x, y, uchain->ox, uchain->oy) <= 2) { /* nothing moved */ move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy); return TRUE; } /* only need to move the chain? */ if (carried(uball) || distmin(x, y, uball->ox, uball->oy) <= 2) { xchar oldchainx = uchain->ox, oldchainy = uchain->oy; *bc_control = BC_CHAIN; move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy); if (carried(uball)) { /* move chain only if necessary */ if (distmin(x, y, uchain->ox, uchain->oy) > 1) { *chainx = u.ux; *chainy = u.uy; } return TRUE; } #define CHAIN_IN_MIDDLE(chx, chy) \ (distmin(x, y, chx, chy) <= 1 && \ distmin(chx, chy, uball->ox, uball->oy) <= 1) #define IS_CHAIN_ROCK(x,y) \ (IS_ROCK(level->locations[x][y].typ) || \ (IS_DOOR(level->locations[x][y].typ) && \ (level->locations[x][y].doormask & (D_CLOSED|D_LOCKED)))) /* Don't ever move the chain into solid rock. If we have to, then instead * undo the move_bc() and jump to the drag ball code. Note that this also * means the "cannot carry and drag" message will not appear, since unless we * moved at least two squares there is no possibility of the chain position * being in solid rock. */ #define SKIP_TO_DRAG { *chainx = oldchainx; *chainy = oldchainy; \ move_bc(0, *bc_control, *ballx, *bally, *chainx, *chainy); \ goto drag; } if (IS_CHAIN_ROCK(u.ux, u.uy) || IS_CHAIN_ROCK(*chainx, *chainy) || IS_CHAIN_ROCK(uball->ox, uball->oy)) already_in_rock = TRUE; else already_in_rock = FALSE; switch (dist2(x, y, uball->ox, uball->oy)) { /* two spaces diagonal from ball, move chain inbetween */ case 8: *chainx = (uball->ox + x) / 2; *chainy = (uball->oy + y) / 2; if (IS_CHAIN_ROCK(*chainx, *chainy) && !already_in_rock) SKIP_TO_DRAG; break; /* player is distance 2/1 from ball; move chain to one of the two spaces between @ __ 0 */ case 5:{ xchar tempx, tempy, tempx2, tempy2; /* find position closest to current position of chain */ /* no effect if current position is already OK */ if (abs(x - uball->ox) == 1) { tempx = x; tempx2 = uball->ox; tempy = tempy2 = (uball->oy + y) / 2; } else { tempx = tempx2 = (uball->ox + x) / 2; tempy = y; tempy2 = uball->oy; } if (IS_CHAIN_ROCK(tempx, tempy) && !IS_CHAIN_ROCK(tempx2, tempy2) && !already_in_rock) { if (allow_drag) { /* Avoid pathological case *if* not teleporting: 0 0_ _X move northeast -----> X@ @ */ if (dist2(u.ux, u.uy, uball->ox, uball->oy) == 5 && dist2(x, y, tempx, tempy) == 1) SKIP_TO_DRAG; /* Avoid pathological case *if* not teleporting: 0 0 _X move east -----> X_ @ @ */ if (dist2(u.ux, u.uy, uball->ox, uball->oy) == 4 && dist2(x, y, tempx, tempy) == 2) SKIP_TO_DRAG; } *chainx = tempx2; *chainy = tempy2; } else if (!IS_CHAIN_ROCK(tempx, tempy) && IS_CHAIN_ROCK(tempx2, tempy2) && !already_in_rock) { if (allow_drag) { if (dist2(u.ux, u.uy, uball->ox, uball->oy) == 5 && dist2(x, y, tempx2, tempy2) == 1) SKIP_TO_DRAG; if (dist2(u.ux, u.uy, uball->ox, uball->oy) == 4 && dist2(x, y, tempx2, tempy2) == 2) SKIP_TO_DRAG; } *chainx = tempx; *chainy = tempy; } else if (IS_CHAIN_ROCK(tempx, tempy) && IS_CHAIN_ROCK(tempx2, tempy2) && !already_in_rock) { SKIP_TO_DRAG; } else if (dist2(tempx, tempy, uchain->ox, uchain->oy) < dist2(tempx2, tempy2, uchain->ox, uchain->oy) || ((dist2(tempx, tempy, uchain->ox, uchain->oy) == dist2(tempx2, tempy2, uchain->ox, uchain->oy)) && rn2(2))) { *chainx = tempx; *chainy = tempy; } else { *chainx = tempx2; *chainy = tempy2; } break; } /* ball is two spaces horizontal or vertical from player; move */ /* chain inbetween *unless* current chain position is OK */ case 4: if (CHAIN_IN_MIDDLE(uchain->ox, uchain->oy)) break; *chainx = (x + uball->ox) / 2; *chainy = (y + uball->oy) / 2; if (IS_CHAIN_ROCK(*chainx, *chainy) && !already_in_rock) SKIP_TO_DRAG; break; /* ball is one space diagonal from player. Check for the following special case: @ _ moving southwest becomes @_ 0 0 (This will also catch teleporting that happens to resemble this case, but oh well.) Otherwise fall through. */ case 2: if (dist2(x, y, uball->ox, uball->oy) == 2 && dist2(x, y, uchain->ox, uchain->oy) == 4) { if (uchain->oy == y) *chainx = uball->ox; else *chainy = uball->oy; if (IS_CHAIN_ROCK(*chainx, *chainy) && !already_in_rock) SKIP_TO_DRAG; break; } /* fall through */ case 1: case 0: /* do nothing if possible */ if (CHAIN_IN_MIDDLE(uchain->ox, uchain->oy)) break; /* otherwise try to drag chain to player's old position */ if (CHAIN_IN_MIDDLE(u.ux, u.uy)) { *chainx = u.ux; *chainy = u.uy; break; } /* otherwise use player's new position (they must have teleported, for this to happen) */ *chainx = x; *chainy = y; break; default: impossible("bad chain movement"); break; } #undef SKIP_TO_DRAG #undef IS_CHAIN_ROCK #undef CHAIN_IN_MIDDLE return TRUE; } drag: if (near_capacity() > SLT_ENCUMBER && dist2(x, y, u.ux, u.uy) <= 2) { pline("You cannot %sdrag the heavy iron ball.", invent ? "carry all that and also " : ""); action_completed(); return FALSE; } if ((is_pool(level, uchain->ox, uchain->oy) && /* water not mere continuation of previous water */ (level->locations[uchain->ox][uchain->oy].typ == POOL || !is_pool(level, uball->ox, uball->oy) || level->locations[uball->ox][uball->oy].typ == POOL)) || ((t = t_at(level, uchain->ox, uchain->oy)) && (t->ttyp == PIT || t->ttyp == SPIKED_PIT || t->ttyp == HOLE || t->ttyp == TRAPDOOR))) { if (Levitation) { pline("You feel a tug from the iron ball."); if (t) t->tseen = 1; } else { struct monst *victim; pline("You are jerked back by the iron ball!"); if ((victim = m_at(level, uchain->ox, uchain->oy)) != 0) { int tmp; tmp = -2 + Luck + find_mac(victim); tmp += omon_adj(victim, uball, TRUE); if (tmp >= rnd(20)) hmon(victim, uball, 1); else miss(xname(uball), victim); } /* now check again in case mon died */ if (!m_at(level, uchain->ox, uchain->oy)) { u.ux = uchain->ox; u.uy = uchain->oy; newsym(u.ux0, u.uy0); } action_interrupted(); *bc_control = BC_BALL; move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy); *ballx = uchain->ox; *bally = uchain->oy; move_bc(0, *bc_control, *ballx, *bally, *chainx, *chainy); spoteffects(TRUE); return FALSE; } } *bc_control = BC_BALL | BC_CHAIN; move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy); if (dist2(x, y, u.ux, u.uy) > 2) { /* Awful case: we're still in range of the ball, so we thought we could only move the chain, but it turned out that the target square for the chain was rock, so we had to drag it instead. But we can't drag it either, because we teleported and are more than one square from our old position. Revert to the teleport behavior. */ *ballx = *chainx = x; *bally = *chainy = y; } else { *ballx = uchain->ox; *bally = uchain->oy; *chainx = u.ux; *chainy = u.uy; } *cause_delay = TRUE; return TRUE; }
/* TODO: Perhaps work out some way to let controlled teleport in on a CMD_ARG_POS, but there are too many codeflow possibilities involved to make that easy. For now, if dotele turns into the spell, we copy the argument on to the spell-handling function (which currently ignores it), but the other possible codepaths just lose it. */ int dotele(const struct nh_cmd_arg *arg) { struct trap *trap; trap = t_at(level, u.ux, u.uy); if (trap && (!trap->tseen || trap->ttyp != TELEP_TRAP)) trap = 0; if (trap) { if (trap->once) { pline("This is a vault teleport, usable once only."); if (yn("Jump in?") == 'n') trap = 0; else { deltrap(level, trap); newsym(u.ux, u.uy); } } if (trap) pline("You %s onto the teleportation trap.", locomotion(youmonst.data, "jump")); } if (!trap) { boolean castit = FALSE; int sp_no = 0, energy = 0; if (!supernatural_ability_available(SPID_RLOC)) { /* Try to use teleport away spell. */ if (objects[SPE_TELEPORT_AWAY].oc_name_known && !Confusion) for (sp_no = 0; sp_no < MAXSPELL; sp_no++) if (spl_book[sp_no].sp_id == SPE_TELEPORT_AWAY) { castit = TRUE; break; } if (!castit) { if (!Teleportation) pline("You don't know that spell."); else pline("You are not able to teleport at will."); return 0; } } if (u.uhunger <= 100 || ACURR(A_STR) < 6) { pline("You lack the strength %s.", castit ? "for a teleport spell" : "to teleport"); return 1; } energy = objects[SPE_TELEPORT_AWAY].oc_level * 7 / 2 - 2; if (u.uen <= energy) { pline("You lack the energy %s.", castit ? "for a teleport spell" : "to teleport"); return 1; } if (check_capacity("Your concentration falters from carrying so much.")) return 1; if (castit) { exercise(A_WIS, TRUE); if (spelleffects(sp_no, TRUE, arg)) return 1; else return 0; } else u.uen -= energy; } if (trap && trap->once) { if (next_to_u()) vault_tele(); else pline("You shudder for a moment."); } else if (!tele_impl(FALSE, TRUE)) return 0; next_to_u(); if (!trap) morehungry(100); return 1; }
/* return 0 (no move), 1 (move) or 2 (dead) */ int dog_move(struct monst *mtmp, int after) { int nx, ny, omx, omy, appr, nearer, j; int udist, chi, i, whappr; struct monst *mtmp2; struct permonst *mdat = mtmp->data; struct edog *edog = EDOG(mtmp); struct obj *obj; struct trap *trap; xchar cnt, chcnt, nix, niy; schar dogroom, uroom; xchar gx, gy, gtyp, otyp; /* current goal */ coord poss[9]; int info[9]; #define GDIST(x,y) ((x-gx)*(x-gx) + (y-gy)*(y-gy)) #define DDIST(x,y) ((x-omx)*(x-omx) + (y-omy)*(y-omy)) if(moves <= edog->eattime) return(0); /* dog is still eating */ omx = mtmp->mx; omy = mtmp->my; whappr = (moves - EDOG(mtmp)->whistletime < 5); if(moves > edog->hungrytime + 500 && !mtmp->mconf){ mtmp->mconf = 1; mtmp->mhpmax /= 3; if(mtmp->mhp > mtmp->mhpmax) mtmp->mhp = mtmp->mhpmax; if(cansee(omx,omy)) pline("%s is confused from hunger.", Monnam(mtmp)); else pline("You feel worried about %s.", monnam(mtmp)); } else if(moves > edog->hungrytime + 750 || mtmp->mhp < 1){ if(cansee(omx,omy)) pline("%s dies from hunger.", Monnam(mtmp)); else pline("You have a sad feeling for a moment, then it passes."); mondied(mtmp); return(2); } dogroom = inroom(omx,omy); uroom = inroom(u.ux,u.uy); udist = dist(omx,omy); /* maybe we tamed him while being swallowed --jgm */ if(!udist) return(0); /* if we are carrying sth then we drop it (perhaps near @) */ /* Note: if apport == 1 then our behaviour is independent of udist */ if(mtmp->minvent){ if(!rn2(udist) || !rn2((int) edog->apport)) if(rn2(10) < edog->apport){ relobj(mtmp, (int) mtmp->minvis); if(edog->apport > 1) edog->apport--; edog->dropdist = udist; /* hpscdi!jon */ edog->droptime = moves; } } else { if ((obj = o_at(omx,omy))) if(!strchr("0_", obj->olet)){ if((otyp = dogfood(obj)) <= CADAVER){ nix = omx; niy = omy; goto eatobj; } if (obj->owt < 10*mtmp->data->mlevel) if (rn2(20) < edog->apport+3) if (rn2(udist) || !rn2((int) edog->apport)){ freeobj(obj); unpobj(obj); /* if(levl[omx][omy].scrsym == obj->olet) newsym(omx,omy); */ mpickobj(mtmp,obj); } } } /* first we look for food */ gtyp = UNDEF; /* no goal as yet */ gx = gy = 0; for(obj = fobj; obj; obj = obj->nobj) { otyp = dogfood(obj); if(otyp > gtyp || otyp == UNDEF) continue; if(inroom(obj->ox,obj->oy) != dogroom) continue; if(otyp < MANFOOD && (dogroom >= 0 || DDIST(obj->ox,obj->oy) < 10)) { if(otyp < gtyp || (otyp == gtyp && DDIST(obj->ox,obj->oy) < DDIST(gx,gy))){ gx = obj->ox; gy = obj->oy; gtyp = otyp; } } else if(gtyp == UNDEF && dogroom >= 0 && uroom == dogroom && !mtmp->minvent && edog->apport > rn2(8)){ gx = obj->ox; gy = obj->oy; gtyp = APPORT; } } if(gtyp == UNDEF || (gtyp != DOGFOOD && gtyp != APPORT && moves < edog->hungrytime)){ if(dogroom < 0 || dogroom == uroom){ gx = u.ux; gy = u.uy; #ifndef QUEST } else { int tmp = rooms[(int)dogroom].fdoor; cnt = rooms[(int)dogroom].doorct; gx = gy = FAR; /* random, far away */ while(cnt--){ if(dist(gx,gy) > dist(doors[tmp].x, doors[tmp].y)){ gx = doors[tmp].x; gy = doors[tmp].y; } tmp++; } /* here gx == FAR e.g. when dog is in a vault */ if(gx == FAR || (gx == omx && gy == omy)){ gx = u.ux; gy = u.uy; } #endif /* QUEST */ } appr = (udist >= 9) ? 1 : (mtmp->mflee) ? -1 : 0; if(after && udist <= 4 && gx == u.ux && gy == u.uy) return(0); if(udist > 1){ if (!IS_ROOM(levl[(int)u.ux][(int)u.uy].typ) || !rn2(4) || whappr || (mtmp->minvent && rn2((int) edog->apport))) appr = 1; } /* if you have dog food he'll follow you more closely */ if (appr == 0) { obj = invent; while(obj){ if(obj->otyp == TRIPE_RATION){ appr = 1; break; } obj = obj->nobj; } } } else appr = 1; /* gtyp != UNDEF */ if(mtmp->mconf) appr = 0; if(gx == u.ux && gy == u.uy && (dogroom != uroom || dogroom < 0)){ coord *cp; cp = gettrack(omx,omy); if(cp){ gx = cp->x; gy = cp->y; } } nix = omx; niy = omy; cnt = mfndpos(mtmp,poss,info,ALLOW_M | ALLOW_TRAPS); chcnt = 0; chi = -1; for(i=0; i<cnt; i++){ nx = poss[i].x; ny = poss[i].y; if(info[i] & ALLOW_M){ mtmp2 = m_at(nx,ny); if(mtmp2->data->mlevel >= mdat->mlevel+2 || mtmp2->data->mlet == 'c') continue; if(after) return(0); /* hit only once each move */ if(hitmm(mtmp, mtmp2) == 1 && rn2(4) && mtmp2->mlstmv != moves && hitmm(mtmp2,mtmp) == 2) return(2); return(0); } /* dog avoids traps */ /* but perhaps we have to pass a trap in order to follow @ */ if((info[i] & ALLOW_TRAPS) && (trap = t_at(nx,ny))){ if(!trap->tseen && rn2(40)) continue; if(rn2(10)) continue; } /* dog eschewes cursed objects */ /* but likes dog food */ obj = fobj; while(obj){ if(obj->ox != nx || obj->oy != ny) goto nextobj; if(obj->cursed) goto nxti; if(obj->olet == FOOD_SYM && (otyp = dogfood(obj)) < MANFOOD && (otyp < ACCFOOD || edog->hungrytime <= moves)){ /* Note: our dog likes the food so much that he might eat it even when it conceals a cursed object */ nix = nx; niy = ny; chi = i; eatobj: edog->eattime = moves + obj->quan * objects[obj->otyp].oc_delay; if(edog->hungrytime < moves) edog->hungrytime = moves; edog->hungrytime += 5*obj->quan * objects[obj->otyp].nutrition; mtmp->mconf = 0; if(cansee(nix,niy)) pline("%s ate %s.", Monnam(mtmp), doname(obj)); /* perhaps this was a reward */ if(otyp != CADAVER) edog->apport += 200/(edog->dropdist+moves-edog->droptime); delobj(obj); goto newdogpos; } nextobj: obj = obj->nobj; } for(j=0; j<MTSZ && j<cnt-1; j++) if(nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y) if(rn2(4*(cnt-j))) goto nxti; /* Some stupid C compilers cannot compute the whole expression at once. */ nearer = GDIST(nx,ny); nearer -= GDIST(nix,niy); nearer *= appr; if((nearer == 0 && !rn2(++chcnt)) || nearer<0 || (nearer > 0 && !whappr && ((omx == nix && omy == niy && !rn2(3)) || !rn2(12)) )){ nix = nx; niy = ny; if(nearer < 0) chcnt = 0; chi = i; } nxti: ; } newdogpos: if(nix != omx || niy != omy){ if(info[chi] & ALLOW_U){ (void) hitu(mtmp, d(mdat->damn, mdat->damd)+1); return(0); } mtmp->mx = nix; mtmp->my = niy; for(j=MTSZ-1; j>0; j--) mtmp->mtrack[j] = mtmp->mtrack[j-1]; mtmp->mtrack[0].x = omx; mtmp->mtrack[0].y = omy; } if(mintrap(mtmp) == 2) /* he died */ return(2); pmon(mtmp); return(1); }
static void describe_mon(int x, int y, int monnum, char *buf) { char race[QBUFSZ]; char *name, monnambuf[BUFSZ]; boolean accurate = !Hallucination; char steedbuf[BUFSZ]; struct monst *mtmp; char visionbuf[BUFSZ], temp_buf[BUFSZ]; if (monnum == -1) return; if (u.ux == x && u.uy == y && senseself()) { /* if not polymorphed, show both the role and the race */ race[0] = 0; if (!Upolyd) sprintf(race, "%s ", urace.adj); sprintf(buf, "%s%s%s called %s", Invis ? "invisible " : "", race, mons[u.umonnum].mname, plname); if (u.usteed) { sprintf(steedbuf, ", mounted on %s", y_monnam(u.usteed)); /* assert((sizeof buf >= strlen(buf)+strlen(steedbuf)+1); */ strcat(buf, steedbuf); } /* When you see yourself normally, no explanation is appended (even if you could also see yourself via other means). Sensing self while blind or swallowed is treated as if it were by normal vision (cf canseeself()). */ if ((Invisible || u.uundetected) && !Blind && !u.uswallow) { unsigned how = 0; if (Infravision) how |= 1; if (Unblind_telepat) how |= 2; if (Detect_monsters) how |= 4; if (how) sprintf(eos(buf), " [seen: %s%s%s%s%s]", (how & 1) ? "infravision" : "", /* add comma if telep and infrav */ ((how & 3) > 2) ? ", " : "", (how & 2) ? "telepathy" : "", /* add comma if detect and (infrav or telep or both) */ ((how & 7) > 4) ? ", " : "", (how & 4) ? "monster detection" : ""); } } else if (monnum >= NUMMONS) { monnum -= NUMMONS; if (monnum < WARNCOUNT) strcat(buf, warnexplain[monnum]); } else if ( (mtmp = m_at(level, x,y)) ) { bhitpos.x = x; bhitpos.y = y; if (mtmp->data == &mons[PM_COYOTE] && accurate) name = coyotename(mtmp, monnambuf); else name = distant_monnam(mtmp, ARTICLE_NONE, monnambuf); sprintf(buf, "%s%s%s", (mtmp->mx != x || mtmp->my != y) ? ((mtmp->isshk && accurate) ? "tail of " : "tail of a ") : "", (mtmp->mtame && accurate) ? "tame " : (mtmp->mpeaceful && accurate) ? "peaceful " : "", name); if (u.ustuck == mtmp) strcat(buf, (Upolyd && sticks(youmonst.data)) ? ", being held" : ", holding you"); if (mtmp->mleashed) strcat(buf, ", leashed to you"); if (mtmp->mtrapped && cansee(mtmp->mx, mtmp->my)) { struct trap *t = t_at(level, mtmp->mx, mtmp->my); int tt = t ? t->ttyp : NO_TRAP; /* newsym lets you know of the trap, so mention it here */ if (tt == BEAR_TRAP || tt == PIT || tt == SPIKED_PIT || tt == WEB) sprintf(eos(buf), ", trapped in %s", an(trapexplain[tt])); } mon_vision_summary(mtmp, visionbuf); if (visionbuf[0]) { sprintf(temp_buf, " [seen: %s]", visionbuf); strncat(buf, temp_buf, BUFSZ-strlen(buf)-1); } } }
int dosit() { static const char sit_message[] = "VERB_SITZEN auf OBJECT KASUS_DATIV ARTIKEL_BESTIMMTER %s."; /* EN static const char sit_message[] = "sit on the %s."; */ register struct trap *trap; register int typ = levl[u.ux][u.uy].typ; #ifdef STEED if (u.usteed) { You("VERB_SITZEN bereits auf KASUS_DATIV %s.", mon_nam(u.usteed)); /* EN You("are already sitting on %s.", mon_nam(u.usteed)); */ return (0); } #endif if(!can_reach_floor()) { if (Levitation) You("VERB_SCHLAGEN Purzelbäume."); /* EN You("tumble in place."); */ else You("VERB_SITZEN auf Luft."); /* EN You("are sitting on air."); */ return 0; } else if (is_pool(u.ux, u.uy) && !Underwater) { /* water walking */ goto in_water; } if(OBJ_AT(u.ux, u.uy)) { register struct obj *obj; obj = level.objects[u.ux][u.uy]; You("VERB_SITZEN auf OBJECT KASUS_DATIV %s.", the(xname(obj))); /* EN You("sit on %s.", the(xname(obj))); */ if (!(Is_box(obj) || objects[obj->otyp].oc_material == CLOTH)) pline("Das ist nicht sehr bequem ..."); /* EN pline("It's not very comfortable..."); */ } else if ((trap = t_at(u.ux, u.uy)) != 0 || (u.utrap && (u.utraptype >= TT_LAVA))) { if (u.utrap) { exercise(A_WIS, FALSE); /* you're getting stuck longer */ if(u.utraptype == TT_BEARTRAP) { pline("Mit KASUS_DATIV PRONOMEN_POSSESSIV %s in KASUS_DATIV ARTIKEL_BESTIMMTER NOUN_BEARTRAP SUBJECT_IM_SATZ VERB_KOENNEN PRONOMEN_PERSONAL OBJECT PRONOMEN_PERSONAL nicht hinsetzen.", body_part(FOOT)); /* EN You_cant("sit down with your %s in the bear trap.", body_part(FOOT)); */ u.utrap++; } else if(u.utraptype == TT_PIT) { if(trap->ttyp == SPIKED_PIT) { You("VERB_SETZEN OBJECT PRONOMEN_PERSONAL auf einen Stachel. Aua!"); /* EN You("sit down on a spike. Ouch!"); */ losehp(1, "durch Sitzen auf einen Eisenstachel", KILLED_WITHOUT_PREPOSITION); /* EN losehp(1, "sitting on an iron spike", KILLED_BY); */ exercise(A_STR, FALSE); } else You("VERB_SETZEN OBJECT PRONOMEN_PERSONAL in die Grube."); /* EN You("sit down in the pit."); */ u.utrap += rn2(5); } else if(u.utraptype == TT_WEB) { You("VERB_SETZEN OBJECT PRONOMEN_PERSONAL ins Spinnenetz und VERB_VERHEDDERN OBJECT PRONOMEN_PERSONAL noch mehr!"); /* EN You("sit in the spider web and get entangled further!"); */ u.utrap += rn1(10, 5); } else if(u.utraptype == TT_LAVA) { /* Must have fire resistance or they'd be dead already */ You("VERB_SETZEN OBJECT PRONOMEN_PERSONAL in die Lava!"); /* EN You("sit in the lava!"); */ u.utrap += rnd(4); losehp(d(2,10), "durch Sitzen in Lava", KILLED_WITHOUT_PREPOSITION); /* EN losehp(d(2,10), "sitting in lava", KILLED_BY); */ } else if(u.utraptype == TT_INFLOOR) { You("VERB_CAN OBJECT PRONOMEN_PERSONAL nicht richtig hinsetzen!"); /* EN You_cant("maneuver to sit!"); */ u.utrap++; } } else { You("VERB_SETZEN OBJECT PRONOMEN_PERSONAL hin."); /* EN You("sit down."); */ dotrap(trap, 0); } } else if(Underwater || Is_waterlevel(&u.uz)) { if (Is_waterlevel(&u.uz)) pline("Hier gibt es keine Sitzkissen."); /* EN There("are no cushions floating nearby."); */ else You("VERB_SETZEN OBJECT PRONOMEN_PERSONAL auf den schlammigen Untergrund."); /* EN You("sit down on the muddy bottom."); */ } else if(is_pool(u.ux, u.uy)) { in_water: You("VERB_SITZEN im Wasser."); /* EN You("sit in the water."); */ if (!rn2(10) && uarm) (void) rust_dmg(uarm, "NOUN_ARMOR", 1, TRUE, &youmonst); /* EN (void) rust_dmg(uarm, "armor", 1, TRUE, &youmonst); */ if (!rn2(10) && uarmf && uarmf->otyp != WATER_WALKING_BOOTS) (void) rust_dmg(uarm, "NOUN_ARMOR", 1, TRUE, &youmonst); /* EN (void) rust_dmg(uarm, "armor", 1, TRUE, &youmonst); */ #ifdef SINKS } else if(IS_SINK(typ)) { You(sit_message, defsyms[S_sink].explanation); Your("%s VERB_WERDEN nass.", humanoid(youmonst.data) ? "NOUN_HINTERTEIL" : "NOUN_UNTERSEITE"); /* EN Your("%s gets wet.", humanoid(youmonst.data) ? "rump" : "underside"); */ #endif } else if(IS_ALTAR(typ)) { You(sit_message, defsyms[S_altar].explanation); altar_wrath(u.ux, u.uy); } else if(IS_GRAVE(typ)) { You(sit_message, defsyms[S_grave].explanation); } else if(typ == STAIRS) { You(sit_message, "NOUN_STUFEs"); /* EN You(sit_message, "stairs"); */ } else if(typ == LADDER) { You(sit_message, "NOUN_LADDER"); /* EN You(sit_message, "ladder"); */ } else if (is_lava(u.ux, u.uy)) { /* must be WWalking */ You(sit_message, "NOUN_LAVA"); /* EN You(sit_message, "lava"); */ burn_away_slime(); if (likes_lava(youmonst.data)) { pline_The("NOUN_LAVA fühlt sich warm an."); /* EN pline_The("lava feels warm."); */ return 1; } pline_The("NOUN_LAVA VERB_VERBRENNEN OBJECT PRONOMEN_PERSONAL!"); /* EN pline_The("lava burns you!"); */ losehp(d((Fire_resistance ? 2 : 10), 10), "durch Sitzen auf Lava", KILLED_WITHOUT_PREPOSITION); /* EN "sitting on lava", KILLED_BY); */ } else if (is_ice(u.ux, u.uy)) { You(sit_message, defsyms[S_ice].explanation); if (!Cold_resistance) pline_The("NOUN_ICE fühlt sich kalt an."); /* EN if (!Cold_resistance) pline_The("ice feels cold."); */ } else if (typ == DRAWBRIDGE_DOWN) { You(sit_message, "NOUN_DRAWBRIDGE"); /* EN You(sit_message, "drawbridge"); */ } else if(IS_THRONE(typ)) { You(sit_message, defsyms[S_throne].explanation); if (rnd(6) > 4) { switch (rnd(13)) { case 1: (void) adjattrib(rn2(A_MAX), -rn1(4,3), FALSE); losehp(rnd(10), "ADJEKTIV_CURSED NOUN_THRON", KILLED_BY_AN); /* EN losehp(rnd(10), "cursed throne", KILLED_BY_AN); */ break; case 2: (void) adjattrib(rn2(A_MAX), 1, FALSE); break; case 3: pline("SUBJECT ARTIKEL_UNBESTIMMTER%s elektrischer NOUN_SCHLAG VERB_SCHIESSEN OBJECT durch PRONOMEN_POSSESSIV NOUN_BODY!", /* EN pline("A%s electric shock shoots through your body!", */ (Shock_resistance) ? "" : " massiver"); /* EN (Shock_resistance) ? "n" : " massive"); */ losehp(Shock_resistance ? rnd(6) : rnd(30), "ADJEKTIV_ELEKTRISCH NOUN_STUHL", KILLED_BY_AN); /* EN "electric chair", KILLED_BY_AN); */ exercise(A_CON, FALSE); break; case 4: Du_fuehlst_dich("viel, viel besser!"); /* EN You_feel("much, much better!"); */ if (Upolyd) { if (u.mh >= (u.mhmax - 5)) u.mhmax += 4; u.mh = u.mhmax; } if(u.uhp >= (u.uhpmax - 5)) u.uhpmax += 4; u.uhp = u.uhpmax; make_blinded(0L,TRUE); make_sick(0L, (char *) 0, FALSE, SICK_ALL); heal_legs(); flags.botl = 1; break; case 5: take_gold(); break; case 6: if(u.uluck + rn2(5) < 0) { You("VERB_FUEHLEN, NEUER_SATZ SUBJECT_IM_SATZ wie PRONOMEN_POSSESSIV NOUN_LUCK sich ändert."); /* EN You_feel("your luck is changing."); */ change_luck(1); } else makewish(); break; case 7: { register int cnt = rnd(10); pline("Eine Stimme ertönt:"); /* EN pline("A voice echoes:"); */ verbalize("Euer Auditorium erwartet Euch bereits, %s!", /* EN verbalize("Thy audience hath been summoned, %s!", */ flags.female ? "Gebieterin" : "Gebieter"); /* EN flags.female ? "Dame" : "Sire"); */ while(cnt--) (void) makemon(courtmon(), u.ux, u.uy, NO_MM_FLAGS); break; } case 8: pline("Eine Stimme ertönt:"); /* EN pline("A voice echoes:"); */ verbalize("Wie es Euch beliebt, %s...", /* EN verbalize("By thy Imperious order, %s...", */ flags.female ? "Gebieterin" : "Gebieter"); /* EN flags.female ? "Dame" : "Sire"); */ do_genocide(5); /* REALLY|ONTHRONE, see do_genocide() */ break; case 9: pline("Eine Stimme ertönt:"); /* EN pline("A voice echoes:"); */ verbalize("SATZBEGINN MODIFIER_VERB_IMPERATIV VERB_SEIN verflucht dafür, NEUER_SATZ dass SUBJECT_IM_SATZ PRONOMEN_PERSONAL OBJECT PRONOMEN_PERSONAL auf diesem allerheiligsten Thron niedergelassen VERB_HABEN!"); /* EN verbalize("A curse upon thee for sitting upon this most holy throne!"); */ if (Luck > 0) { make_blinded(Blinded + rn1(100,250),TRUE); } else rndcurse(); break; case 10: if (Luck < 0 || (HSee_invisible & INTRINSIC)) { if (level.flags.nommap) { pline( "Ein schreckliches Dröhnen erfüllt KASUS_AKKUSATIV PRONOMEN_POSSESSIV NOUN_KOPF!"); /* EN "A terrible drone fills your head!"); */ make_confused(HConfusion + rnd(30), FALSE); } else { pline("Ein Bild formt sich in KASUS_DATIV PRONOMEN_POSSESSIV NOUN_GEDANKEs."); /* EN pline("An image forms in your mind."); */ do_mapping(); } } else { Your("NOUN_BLICK klärt sich."); /* EN Your("vision becomes clear."); */ HSee_invisible |= FROMOUTSIDE; newsym(u.ux, u.uy); } break; case 11: if (Luck < 0) { Du_fuehlst_dich("bedroht."); /* EN You_feel("threatened."); */ aggravate(); } else { Du_spuerst("einen reißenden Schmerz."); /* EN You_feel("a wrenching sensation."); */ tele(); /* teleport him */ } break; case 12: Dir_wird("eine Einsicht gewährt!"); /* EN You("are granted an insight!"); */ if (invent) { /* rn2(5) agrees w/seffects() */ identify_pack(rn2(5)); } break; case 13: Your("NOUN_VERSTAND verknotet sich zu einer Bretzel!"); /* EN Your("mind turns into a pretzel!"); */ make_confused(HConfusion + rn1(7,16),FALSE); break; default: impossible("throne effect"); break; } } else { if (is_prince(youmonst.data)) Du_fuehlst_dich("hier sehr wohl."); /* EN You_feel("very comfortable here."); */ else Du_fuehlst_dich("irgendwie fehl am Platz ..."); /* EN You_feel("somehow out of place..."); */ } if (!rn2(3) && IS_THRONE(levl[u.ux][u.uy].typ)) { /* may have teleported */ levl[u.ux][u.uy].typ = ROOM; pline_The("NOUN_THRON VERB_AUFLOESEN sich in ein Logikwölkchen SATZKLAMMER."); /* EN pline_The("throne vanishes in a puff of logic."); */ newsym(u.ux,u.uy); } } else if (lays_eggs(youmonst.data)) { struct obj *uegg; if (!flags.female) { pline("Männchen können keine Eier legen!"); /* EN pline("Males can't lay eggs!"); */ return 0; } if (u.uhunger < (int)objects[EGG].oc_nutrition) { You("VERB_HAVE nicht genug Energie um ein Ei zu legen."); /* EN You("don't have enough energy to lay an egg."); */ return 0; } uegg = mksobj(EGG, FALSE, FALSE); uegg->spe = 1; uegg->quan = 1; uegg->owt = weight(uegg); uegg->corpsenm = egg_type_from_parent(u.umonnum, FALSE); uegg->known = uegg->dknown = 1; attach_egg_hatch_timeout(uegg); You("VERB_LEGEN ein Ei."); /* EN You("lay an egg."); */ dropy(uegg); stackobj(uegg); morehungry((int)objects[EGG].oc_nutrition); } else if (u.uswallow) pline("Hier gibt es keine Sitzmöglichkeiten!"); /* EN There("are no seats in here!"); */ else pline("Spaß daran, %s zu sitzen?", auf_dem_Boden(u.ux,u.uy)); /* EN pline("Having fun sitting on the %s?", surface(u.ux,u.uy)); */ return(1); }
/* #sit command */ int dosit() { /*JP static const char sit_message[] = "sit on the %s."; */ static const char sit_message[] = "%sに座った."; register struct trap *trap = t_at(u.ux, u.uy); register int typ = levl[u.ux][u.uy].typ; if (u.usteed) { /*JP You("are already sitting on %s.", mon_nam(u.usteed)); */ You("もう%sに座っている.", mon_nam(u.usteed)); return 0; } if (u.uundetected && is_hider(youmonst.data) && u.umonnum != PM_TRAPPER) u.uundetected = 0; /* no longer on the ceiling */ if (!can_reach_floor(FALSE)) { if (u.uswallow) /*JP There("are no seats in here!"); */ pline("ここには椅子がない!"); else if (Levitation) /*JP You("tumble in place."); */ You("その場で宙返りした."); else /*JP You("are sitting on air."); */ You("空中に座った."); return 0; } else if (u.ustuck && !sticks(youmonst.data)) { /* holding monster is next to hero rather than beneath, but hero is in no condition to actually sit at has/her own spot */ if (humanoid(u.ustuck->data)) /*JP pline("%s won't offer %s lap.", Monnam(u.ustuck), mhis(u.ustuck)); */ pline("%sはひざを出さなかった.", Monnam(u.ustuck)); else /*JP pline("%s has no lap.", Monnam(u.ustuck)); */ pline("%sにはひざがない.", Monnam(u.ustuck)); return 0; } else if (is_pool(u.ux, u.uy) && !Underwater) { /* water walking */ goto in_water; } if (OBJ_AT(u.ux, u.uy) /* ensure we're not standing on the precipice */ && !uteetering_at_seen_pit(trap)) { register struct obj *obj; obj = level.objects[u.ux][u.uy]; if (youmonst.data->mlet == S_DRAGON && obj->oclass == COIN_CLASS) { #if 0 /*JP*/ You("coil up around your %shoard.", (obj->quan + money_cnt(invent) < u.ulevel * 1000) ? "meager " : ""); #else You("%sお宝のまわりでとぐろを巻いた.", (obj->quan + money_cnt(invent) < u.ulevel * 1000) ? "わずかな" : ""); #endif } else { /*JP You("sit on %s.", the(xname(obj))); */ You("%sに座った.", the(xname(obj))); if (!(Is_box(obj) || objects[obj->otyp].oc_material == CLOTH)) /*JP pline("It's not very comfortable..."); */ pline("あまり座りごこちがよくない..."); } } else if (trap != 0 || (u.utrap && (u.utraptype >= TT_LAVA))) { if (u.utrap) { exercise(A_WIS, FALSE); /* you're getting stuck longer */ if (u.utraptype == TT_BEARTRAP) { /*JP You_cant("sit down with your %s in the bear trap.", */ pline("%sが熊の罠にはさまっているので座れない.", body_part(FOOT)); u.utrap++; } else if (u.utraptype == TT_PIT) { if (trap && trap->ttyp == SPIKED_PIT) { /*JP You("sit down on a spike. Ouch!"); */ You("トゲの上に座った.いてっ!"); losehp(Half_physical_damage ? rn2(2) : 1, /*JP "sitting on an iron spike", KILLED_BY); */ "鉄のトゲの上に座って", KILLED_BY); exercise(A_STR, FALSE); } else /*JP You("sit down in the pit."); */ You("落し穴の中で座った."); u.utrap += rn2(5); } else if (u.utraptype == TT_WEB) { /*JP You("sit in the spider web and get entangled further!"); */ You("くもの巣の中で座ったら,ますます絡まった!"); u.utrap += rn1(10, 5); } else if (u.utraptype == TT_LAVA) { /* Must have fire resistance or they'd be dead already */ /*JP You("sit in the lava!"); */ You("溶岩の中に座った!"); if (Slimed) burn_away_slime(); u.utrap += rnd(4); /*JP losehp(d(2, 10), "sitting in lava", */ losehp(d(2, 10), "溶岩の中に座って", KILLED_BY); /* lava damage */ } else if (u.utraptype == TT_INFLOOR || u.utraptype == TT_BURIEDBALL) { /*JP You_cant("maneuver to sit!"); */ You("座るような動作ができない!"); u.utrap++; } } else { /*JP You("sit down."); */ You("座った."); dotrap(trap, 0); } } else if (Underwater || Is_waterlevel(&u.uz)) { if (Is_waterlevel(&u.uz)) /*JP There("are no cushions floating nearby."); */ pline("近くに浮いているクッションはない."); else /*JP You("sit down on the muddy bottom."); */ You("どろどろした底に座った."); } else if (is_pool(u.ux, u.uy)) { in_water: /*JP You("sit in the water."); */ You("水の中で座った."); if (!rn2(10) && uarm) /*JP (void) water_damage(uarm, "armor", TRUE); */ (void) water_damage(uarm, "鎧", TRUE); if (!rn2(10) && uarmf && uarmf->otyp != WATER_WALKING_BOOTS) /*JP (void) water_damage(uarm, "armor", TRUE); */ (void) water_damage(uarm, "鎧", TRUE); } else if (IS_SINK(typ)) { You(sit_message, defsyms[S_sink].explanation); /*JP Your("%s gets wet.", humanoid(youmonst.data) ? "rump" : "underside"); */ Your("%sは濡れた.", humanoid(youmonst.data) ? "尻" : "下部"); } else if (IS_ALTAR(typ)) { You(sit_message, defsyms[S_altar].explanation); altar_wrath(u.ux, u.uy); } else if (IS_GRAVE(typ)) { You(sit_message, defsyms[S_grave].explanation); } else if (typ == STAIRS) { /*JP You(sit_message, "stairs"); */ You(sit_message, "階段"); } else if (typ == LADDER) { /*JP You(sit_message, "ladder"); */ You(sit_message, "はしご"); } else if (is_lava(u.ux, u.uy)) { /* must be WWalking */ /*JP You(sit_message, "lava"); */ You(sit_message, "溶岩"); burn_away_slime(); if (likes_lava(youmonst.data)) { /*JP pline_The("lava feels warm."); */ pline("溶岩は暖かい."); return 1; } /*JP pline_The("lava burns you!"); */ You("溶岩で燃えた!"); losehp(d((Fire_resistance ? 2 : 10), 10), /* lava damage */ /*JP "sitting on lava", KILLED_BY); */ "溶岩に座って", KILLED_BY); } else if (is_ice(u.ux, u.uy)) { You(sit_message, defsyms[S_ice].explanation); if (!Cold_resistance) /*JP pline_The("ice feels cold."); */ pline("氷は冷たく感じた."); } else if (typ == DRAWBRIDGE_DOWN) { /*JP You(sit_message, "drawbridge"); */ You(sit_message, "跳ね橋"); } else if (IS_THRONE(typ)) { You(sit_message, defsyms[S_throne].explanation); if (rnd(6) > 4) { switch (rnd(13)) { case 1: (void) adjattrib(rn2(A_MAX), -rn1(4, 3), FALSE); /*JP losehp(rnd(10), "cursed throne", KILLED_BY_AN); */ losehp(rnd(10), "呪われた玉座で", KILLED_BY_AN); break; case 2: (void) adjattrib(rn2(A_MAX), 1, FALSE); break; case 3: #if 0 /*JP*/ pline("A%s electric shock shoots through your body!", (Shock_resistance) ? "n" : " massive"); #else pline("%s電気があなたの体を走り抜けた!", (Shock_resistance) ? "" : "激しい"); #endif /*JP losehp(Shock_resistance ? rnd(6) : rnd(30), "electric chair", */ losehp(Shock_resistance ? rnd(6) : rnd(30), "電気椅子で", KILLED_BY_AN); exercise(A_CON, FALSE); break; case 4: /*JP You_feel("much, much better!"); */ You_feel("とても,とても元気になったような気がした!"); if (Upolyd) { if (u.mh >= (u.mhmax - 5)) u.mhmax += 4; u.mh = u.mhmax; } if (u.uhp >= (u.uhpmax - 5)) u.uhpmax += 4; u.uhp = u.uhpmax; make_blinded(0L, TRUE); make_sick(0L, (char *) 0, FALSE, SICK_ALL); heal_legs(); context.botl = 1; break; case 5: take_gold(); break; case 6: if (u.uluck + rn2(5) < 0) { /*JP You_feel("your luck is changing."); */ pline("運が向いてきた気がする."); change_luck(1); } else makewish(); break; case 7: { int cnt = rnd(10); /* Magical voice not affected by deafness */ /*JP pline("A voice echoes:"); */ pline("声が響いた:"); #if 0 /*JP*/ verbalize("Thy audience hath been summoned, %s!", flags.female ? "Dame" : "Sire"); #else verbalize("%sよ!汝の聴衆召喚されし.", flags.female ? "女" : "男"); #endif while (cnt--) (void) makemon(courtmon(), u.ux, u.uy, NO_MM_FLAGS); break; } case 8: /* Magical voice not affected by deafness */ /*JP pline("A voice echoes:"); */ pline("声が響いた:"); #if 0 /*JP*/ verbalize("By thine Imperious order, %s...", flags.female ? "Dame" : "Sire"); #else verbalize("%sよ!汝の傲慢聞きいれようぞ.", flags.female ? "女" : "男"); #endif do_genocide(5); /* REALLY|ONTHRONE, see do_genocide() */ break; case 9: /* Magical voice not affected by deafness */ /*JP pline("A voice echoes:"); */ pline("声が響いた:"); verbalize( /*JP "A curse upon thee for sitting upon this most holy throne!"); */ "聖なる玉座に座りし汝に呪いあれ!"); if (Luck > 0) { make_blinded(Blinded + rn1(100, 250), TRUE); } else rndcurse(); break; case 10: if (Luck < 0 || (HSee_invisible & INTRINSIC)) { if (level.flags.nommap) { /*JP pline("A terrible drone fills your head!"); */ pline("恐しいブンブンという音が頭に響いた!"); make_confused((HConfusion & TIMEOUT) + (long) rnd(30), FALSE); } else { /*JP pline("An image forms in your mind."); */ pline("あるイメージが頭に浮んだ."); do_mapping(); } } else { /*JP Your("vision becomes clear."); */ Your("視界は冴え渡った."); HSee_invisible |= FROMOUTSIDE; newsym(u.ux, u.uy); } break; case 11: if (Luck < 0) { /*JP You_feel("threatened."); */ You("脅迫されているような気がした."); aggravate(); } else { /*JP You_feel("a wrenching sensation."); */ You("ねじられたような感覚を感じた."); tele(); /* teleport him */ } break; case 12: /*JP You("are granted an insight!"); */ You("洞察力を得た!"); if (invent) { /* rn2(5) agrees w/seffects() */ identify_pack(rn2(5), FALSE); } break; case 13: /*JP Your("mind turns into a pretzel!"); */ Your("心はクネクネになった!"); make_confused((HConfusion & TIMEOUT) + (long) rn1(7, 16), FALSE); break; default: impossible("throne effect"); break; } } else { if (is_prince(youmonst.data)) /*JP You_feel("very comfortable here."); */ You("ここはとても落ち着く."); else /*JP You_feel("somehow out of place..."); */ You("何か場違いの気がした..."); } if (!rn2(3) && IS_THRONE(levl[u.ux][u.uy].typ)) { /* may have teleported */ levl[u.ux][u.uy].typ = ROOM; /*JP pline_The("throne vanishes in a puff of logic."); */ pline("玉座はふっと消えた."); newsym(u.ux, u.uy); } } else if (lays_eggs(youmonst.data)) { struct obj *uegg; if (!flags.female) { #if 0 /*JP*/ pline("%s can't lay eggs!", Hallucination ? "You may think you are a platypus, but a male still" : "Males"); #else pline("%s雄は卵を産めない!", Hallucination ? "あなたは自分がカモノハシだと思っているかもしれないが,やっぱり" : ""); #endif return 0; } else if (u.uhunger < (int) objects[EGG].oc_nutrition) { /*JP You("don't have enough energy to lay an egg."); */ You("卵を産むだけのエネルギーがない."); return 0; } uegg = mksobj(EGG, FALSE, FALSE); uegg->spe = 1; uegg->quan = 1L; uegg->owt = weight(uegg); /* this sets hatch timers if appropriate */ set_corpsenm(uegg, egg_type_from_parent(u.umonnum, FALSE)); uegg->known = uegg->dknown = 1; /*JP You("lay an egg."); */ You("卵を産んだ."); dropy(uegg); stackobj(uegg); morehungry((int) objects[EGG].oc_nutrition); } else { /*JP pline("Having fun sitting on the %s?", surface(u.ux, u.uy)); */ pline("%sに座って楽しいかい?", surface(u.ux,u.uy)); } return 1; }
int dosit() { static const char sit_message[] = "sit on the %s."; register struct trap *trap; register int typ = levl[u.ux][u.uy].typ; #ifdef STEED if (u.usteed) { You("are already sitting on %s.", mon_nam(u.usteed)); return (0); } #endif if(!can_reach_floor()) { if (Levitation) You("tumble in place."); else You("are sitting on air."); return 0; } else if (is_pool(u.ux, u.uy) && !Underwater) { /* water walking */ goto in_water; } if(OBJ_AT(u.ux, u.uy)) { register struct obj *obj; obj = level.objects[u.ux][u.uy]; You("sit on %s.", the(xname(obj))); if (!(Is_box(obj) || objects[obj->otyp].oc_material == CLOTH)) pline("It's not very comfortable..."); } else if ((trap = t_at(u.ux, u.uy)) != 0 || (u.utrap && (u.utraptype >= TT_LAVA))) { if (u.utrap) { exercise(A_WIS, FALSE); /* you're getting stuck longer */ if(u.utraptype == TT_BEARTRAP) { You_cant("sit down with your %s in the bear trap.", body_part(FOOT)); u.utrap++; } else if(u.utraptype == TT_PIT) { if(trap->ttyp == SPIKED_PIT) { You("sit down on a spike. Ouch!"); losehp(1, "sitting on an iron spike", KILLED_BY); exercise(A_STR, FALSE); } else You("sit down in the pit."); u.utrap += rn2(5); } else if(u.utraptype == TT_WEB) { You("sit in the spider web and get entangled further!"); u.utrap += rn1(10, 5); } else if(u.utraptype == TT_LAVA) { /* Must have fire resistance or they'd be dead already */ You("sit in the lava!"); u.utrap += rnd(4); losehp(d(2,10), "sitting in lava", KILLED_BY); } else if(u.utraptype == TT_INFLOOR) { You_cant("maneuver to sit!"); u.utrap++; } } else { You("sit down."); dotrap(trap, 0); } } else if(Underwater || Is_waterlevel(&u.uz)) { if (Is_waterlevel(&u.uz)) There("are no cushions floating nearby."); else You("sit down on the muddy bottom."); } else if(is_pool(u.ux, u.uy)) { in_water: You("sit in the water."); if (!rn2(10) && uarm) (void) rust_dmg(uarm, "armor", 1, TRUE, &youmonst); if (!rn2(10) && uarmf && uarmf->otyp != WATER_WALKING_BOOTS) (void) rust_dmg(uarm, "armor", 1, TRUE, &youmonst); #ifdef SINKS } else if(IS_SINK(typ)) { You(sit_message, defsyms[S_sink].explanation); Your("%s gets wet.", humanoid(youmonst.data) ? "rump" : "underside"); #endif } else if(IS_ALTAR(typ)) { You(sit_message, defsyms[S_altar].explanation); altar_wrath(u.ux, u.uy); } else if(IS_GRAVE(typ)) { You(sit_message, defsyms[S_grave].explanation); } else if(typ == STAIRS) { You(sit_message, "stairs"); } else if(typ == LADDER) { You(sit_message, "ladder"); } else if (is_lava(u.ux, u.uy)) { /* must be WWalking */ You(sit_message, "lava"); burn_away_slime(); if (likes_lava(youmonst.data)) { pline_The("lava feels warm."); return 1; } pline_The("lava burns you!"); losehp(d((Fire_resistance ? 2 : 10), 10), "sitting on lava", KILLED_BY); } else if (is_ice(u.ux, u.uy)) { You(sit_message, defsyms[S_ice].explanation); if (!Cold_resistance) pline_The("ice feels cold."); } else if (typ == DRAWBRIDGE_DOWN) { You(sit_message, "drawbridge"); } else if(IS_THRONE(typ)) { You(sit_message, defsyms[S_throne].explanation); if (rnd(6) > 4) { switch (rnd(13)) { case 1: (void) adjattrib(rn2(A_MAX), -rn1(4,3), FALSE); losehp(rnd(10), "cursed throne", KILLED_BY_AN); break; case 2: (void) adjattrib(rn2(A_MAX), 1, FALSE); break; case 3: pline("A%s electric shock shoots through your body!", (Shock_resistance) ? "n" : " massive"); losehp(Shock_resistance ? rnd(6) : rnd(30), "electric chair", KILLED_BY_AN); exercise(A_CON, FALSE); break; case 4: You_feel("much, much better!"); if (Upolyd) { if (u.mh >= (u.mhmax - 5)) u.mhmax += 4; u.mh = u.mhmax; } if(u.uhp >= (u.uhpmax - 5)) u.uhpmax += 4; u.uhp = u.uhpmax; make_blinded(0L,TRUE); make_sick(0L, (char *) 0, FALSE, SICK_ALL); heal_legs(); flags.botl = 1; break; case 5: take_gold(); break; case 6: if(u.uluck + rn2(5) < 0) { You_feel("your luck is changing."); change_luck(1); } else makewish(); break; case 7: { register int cnt = rnd(10); pline("A voice echoes:"); verbalize("Thy audience hath been summoned, %s!", flags.female ? "Dame" : "Sire"); while(cnt--) (void) makemon(courtmon(), u.ux, u.uy, NO_MM_FLAGS); break; } case 8: pline("A voice echoes:"); verbalize("By thy Imperious order, %s...", flags.female ? "Dame" : "Sire"); do_genocide(5); /* REALLY|ONTHRONE, see do_genocide() */ break; case 9: pline("A voice echoes:"); verbalize("A curse upon thee for sitting upon this most holy throne!"); if (Luck > 0) { make_blinded(Blinded + rn1(100,250),TRUE); } else rndcurse(); break; case 10: if (Luck < 0 || (HSee_invisible & INTRINSIC)) { if (level.flags.nommap) { pline( "A terrible drone fills your head!"); make_confused(HConfusion + rnd(30), FALSE); } else { pline("An image forms in your mind."); do_mapping(); } } else { Your("vision becomes clear."); HSee_invisible |= FROMOUTSIDE; newsym(u.ux, u.uy); } break; case 11: if (Luck < 0) { You_feel("threatened."); aggravate(); } else { You_feel("a wrenching sensation."); tele(); /* teleport him */ } break; case 12: You("are granted an insight!"); if (invent) { /* rn2(5) agrees w/seffects() */ identify_pack(rn2(5)); } break; case 13: Your("mind turns into a pretzel!"); make_confused(HConfusion + rn1(7,16),FALSE); break; default: impossible("throne effect"); break; } } else { if (is_prince(youmonst.data)) You_feel("very comfortable here."); else You_feel("somehow out of place..."); } if (!rn2(3) && IS_THRONE(levl[u.ux][u.uy].typ)) { /* may have teleported */ levl[u.ux][u.uy].typ = ROOM; pline_The("throne vanishes in a puff of logic."); newsym(u.ux,u.uy); } } else if (lays_eggs(youmonst.data)) { struct obj *uegg; if (!flags.female) { pline("Males can't lay eggs!"); return 0; } if (u.uhunger < (int)objects[EGG].oc_nutrition) { You("don't have enough energy to lay an egg."); return 0; } uegg = mksobj(EGG, FALSE, FALSE); uegg->spe = 1; uegg->quan = 1; uegg->owt = weight(uegg); uegg->corpsenm = egg_type_from_parent(u.umonnum, FALSE); uegg->known = uegg->dknown = 1; attach_egg_hatch_timeout(uegg); You("lay an egg."); dropy(uegg); stackobj(uegg); morehungry((int)objects[EGG].oc_nutrition); } else if (u.uswallow) There("are no seats in here!"); else pline("Having fun sitting on the %s?", surface(u.ux,u.uy)); return(1); }
static int domonnoise(struct monst *mtmp) { const char *pline_msg = 0, /* Monnam(mtmp) will be prepended */ *verbl_msg = 0; /* verbalize() */ const struct permonst *ptr = mtmp->data; /* presumably nearness checks have already been made */ if (!canhear()) return 0; if (is_silent(ptr)) return 0; /* Make sure its your role's quest quardian; adjust if not */ if (ptr->msound == MS_GUARDIAN && ptr != &pm_guardian) { int mndx = monsndx(ptr); ptr = &mons[genus(mndx, 1)]; } /* be sure to do this before talking; the monster might teleport away, in which case we want to check its pre-teleport position */ if (!canspotmon(mtmp)) map_invisible(mtmp->mx, mtmp->my); switch (ptr->msound) { case MS_ORACLE: return doconsult(mtmp); case MS_PRIEST: priest_talk(mtmp); break; case MS_LEADER: case MS_NEMESIS: case MS_GUARDIAN: quest_chat(mtmp); break; case MS_SELL: /* pitch, pay, total */ shk_chat(mtmp); break; case MS_VAMPIRE: { /* vampire messages are varied by tameness, peacefulness, and time of night */ boolean isnight = night(); boolean kindred = (Upolyd && (u.umonnum == PM_VAMPIRE || u.umonnum == PM_VAMPIRE_LORD)); boolean nightchild = (Upolyd && (u.umonnum == PM_WOLF || u.umonnum == PM_WINTER_WOLF || u.umonnum == PM_WINTER_WOLF_CUB)); const char *racenoun = (u.ufemale && urace.individual.f) ? urace. individual.f : (urace.individual.m) ? urace.individual. m : urace.noun; if (mtmp->mtame) { if (kindred) verbl_msg = msgprintf("Good %s to you Master%s", isnight ? "evening" : "day", isnight ? "!" : ". Why do we not rest?"); else verbl_msg = msgcat( nightchild ? "Child of the night, " : "", midnight()? "I can stand this craving no longer!" : isnight ? "I beg you, help me satisfy this growing craving!" : "I find myself growing a little weary."); } else if (mtmp->mpeaceful) { if (kindred && isnight) verbl_msg = msgprintf("Good feeding %s!", u.ufemale ? "sister" : "brother"); else if (nightchild && isnight) verbl_msg = "How nice to hear you, child of the night!"; else verbl_msg = "I only drink... potions."; } else { int vampindex; static const char *const vampmsg[] = { /* These first two (0 and 1) are specially handled below */ "I vant to suck your %s!", "I vill come after %s without regret!", /* other famous vampire quotes can follow here if desired */ }; if (kindred) verbl_msg = "This is my hunting ground that you dare to prowl!"; else if (youmonst.data == &mons[PM_SILVER_DRAGON] || youmonst.data == &mons[PM_BABY_SILVER_DRAGON]) { /* Silver dragons are silver in color, not made of silver */ verbl_msg = msgprintf( "%s! Your silver sheen does not frighten me!", youmonst.data == &mons[PM_SILVER_DRAGON] ? "Fool" : "Young Fool"); } else { vampindex = rn2(SIZE(vampmsg)); if (vampindex == 0) { verbl_msg = msgprintf( vampmsg[vampindex], body_part(BLOOD)); } else if (vampindex == 1) { verbl_msg = msgprintf( vampmsg[vampindex], Upolyd ? an(mons[u.umonnum].mname) : an(racenoun)); } else verbl_msg = vampmsg[vampindex]; } } } break; case MS_WERE: if (flags.moonphase == FULL_MOON && (night() ^ !rn2(13))) { pline("%s throws back %s head and lets out a blood curdling %s!", Monnam(mtmp), mhis(mtmp), ptr == &mons[PM_HUMAN_WERERAT] ? "shriek" : "howl"); wake_nearto(mtmp->mx, mtmp->my, 11 * 11); } else pline_msg = "whispers inaudibly. All you can make out is \"moon\"."; break; case MS_BARK: if (flags.moonphase == FULL_MOON && night()) { pline_msg = "howls."; } else if (mtmp->mpeaceful) { if (mtmp->mtame && (mtmp->mconf || mtmp->mflee || mtmp->mtrapped || moves > EDOG(mtmp)->hungrytime || mtmp->mtame < 5)) pline_msg = "whines."; else if (mtmp->mtame && EDOG(mtmp)->hungrytime > moves + 1000) pline_msg = "yips."; else { if (mtmp->data == &mons[PM_FOX]) pline_msg = whatthefoxsays(); else if (mtmp->data != &mons[PM_DINGO]) /* dingos do not actually bark */ pline_msg = "barks."; } } else { if (mtmp->data == &mons[PM_FOX]) pline_msg = whatthefoxsays(); else pline_msg = "growls."; } break; case MS_MEW: if (mtmp->mtame) { if (mtmp->mconf || mtmp->mflee || mtmp->mtrapped || mtmp->mtame < 5) pline_msg = "yowls."; else if (moves > EDOG(mtmp)->hungrytime) pline_msg = "meows."; else if (EDOG(mtmp)->hungrytime > moves + 1000) pline_msg = "purrs."; else pline_msg = "mews."; break; } /* else FALLTHRU */ case MS_GROWL: pline_msg = mtmp->mpeaceful ? "snarls." : "growls!"; break; case MS_ROAR: pline_msg = mtmp->mpeaceful ? "snarls." : "roars!"; break; case MS_SQEEK: pline_msg = "squeaks."; break; case MS_SQAWK: if (ptr == &mons[PM_RAVEN] && !mtmp->mpeaceful) verbl_msg = "Nevermore!"; else pline_msg = "squawks."; break; case MS_HISS: if (!mtmp->mpeaceful) pline_msg = "hisses!"; else return 0; /* no sound */ break; case MS_BUZZ: pline_msg = mtmp->mpeaceful ? "drones." : "buzzes angrily."; break; case MS_GRUNT: pline_msg = "grunts."; break; case MS_NEIGH: if (mtmp->mtame < 5) pline_msg = "neighs."; else if (moves > EDOG(mtmp)->hungrytime) pline_msg = "whinnies."; else pline_msg = "whickers."; break; case MS_WAIL: pline_msg = "wails mournfully."; break; case MS_GURGLE: pline_msg = "gurgles."; break; case MS_BURBLE: pline_msg = "burbles."; break; case MS_SHRIEK: pline_msg = "shrieks."; aggravate(); break; case MS_IMITATE: pline_msg = "imitates you."; break; case MS_BONES: pline("%s rattles noisily.", Monnam(mtmp)); pline("You freeze for a moment."); helpless(2, hr_afraid, "scared by rattling", NULL); break; case MS_LAUGH: { static const char *const laugh_msg[4] = { "giggles.", "chuckles.", "snickers.", "laughs.", }; pline_msg = laugh_msg[rn2(4)]; } break; case MS_MUMBLE: pline_msg = "mumbles incomprehensibly."; break; case MS_WISHGIVER: if (mtmp->mtame) { verbl_msg = "Sorry, I'm all out of wishes."; } else if (mtmp->mpeaceful) { if (ptr == &mons[PM_WATER_DEMON]) pline_msg = "gurgles."; else verbl_msg = "I'm free!"; } else verbl_msg = "This will teach you not to disturb me!"; break; case MS_BOAST: /* giants */ if (!mtmp->mpeaceful) { switch (rn2(4)) { case 0: pline("%s boasts about %s gem collection.", Monnam(mtmp), mhis(mtmp)); break; case 1: pline_msg = "complains about a diet of mutton."; break; default: pline_msg = "shouts \"Fee Fie Foe Foo!\" and guffaws."; wake_nearto(mtmp->mx, mtmp->my, 7 * 7); break; } break; } /* else FALLTHRU */ case MS_HUMANOID: if (!mtmp->mpeaceful) { if (In_endgame(&u.uz) && is_mplayer(ptr)) { mplayer_talk(mtmp); break; } else return 0; /* no sound */ } /* Generic peaceful humanoid behaviour. */ if (mtmp->mflee) pline_msg = "wants nothing to do with you."; else if (mtmp->mhp < mtmp->mhpmax / 4) pline_msg = "moans."; else if (mtmp->mconf || mtmp->mstun) verbl_msg = !rn2(3) ? "Huh?" : rn2(2) ? "What?" : "Eh?"; else if (!mtmp->mcansee) verbl_msg = "I can't see!"; else if (mtmp->mtrapped) { struct trap *t = t_at(level, mtmp->mx, mtmp->my); if (t) t->tseen = 1; verbl_msg = "I'm trapped!"; } else if (mtmp->mhp < mtmp->mhpmax / 2) pline_msg = "asks for a potion of healing."; else if (mtmp->mtame && !mtmp->isminion && moves > EDOG(mtmp)->hungrytime) verbl_msg = "I'm hungry."; /* Specific monsters' interests */ else if (is_elf(ptr)) pline_msg = "curses orcs."; else if (is_dwarf(ptr)) pline_msg = "talks about mining."; else if (likes_magic(ptr)) pline_msg = "talks about spellcraft."; else if (ptr->mlet == S_CENTAUR) pline_msg = "discusses hunting."; else switch (monsndx(ptr)) { case PM_HOBBIT: pline_msg = (mtmp->mhpmax - mtmp->mhp >= 10) ? "complains about unpleasant dungeon conditions." : "asks you about the One Ring."; break; case PM_ARCHEOLOGIST: pline_msg = "describes a recent article in \"Spelunker Today\" " "magazine."; break; case PM_TOURIST: verbl_msg = "Aloha."; break; case PM_PRISONER: verbl_msg = "Thank you for freeing me!"; break; default: pline_msg = "discusses dungeon exploration."; break; } break; case MS_SEDUCE: if (ptr->mlet != S_NYMPH && flags.seduce_enabled && could_seduce(mtmp, &youmonst, NULL) == 1) { doseduce(mtmp); break; } switch ((poly_gender() != (int)mtmp->female) ? rn2(3) : 0) { case 2: verbl_msg = "Hello, sailor."; break; case 1: pline_msg = "comes on to you."; break; default: pline_msg = "cajoles you."; } break; case MS_ARREST: if (mtmp->mpeaceful) verbalize("Just the facts, %s.", u.ufemale ? "Ma'am" : "Sir"); else { static const char *const arrest_msg[3] = { "Anything you say can be used against you.", "You're under arrest!", "Stop in the name of the Law!", }; verbl_msg = arrest_msg[rn2(3)]; } break; case MS_BRIBE: if (mtmp->mpeaceful && !mtmp->mtame) { demon_talk(mtmp); break; } /* fall through */ case MS_CUSS: if (!mtmp->mpeaceful) cuss(mtmp); break; case MS_SPELL: /* deliberately vague, since it's not actually casting any spell */ pline_msg = "seems to mutter a cantrip."; break; case MS_NURSE: if (uwep && (uwep->oclass == WEAPON_CLASS || is_weptool(uwep))) verbl_msg = "Put that weapon away before you hurt someone!"; else if (uarmc || (uarm && !uskin()) || uarmh || uarms || uarmg || uarmf) verbl_msg = Role_if(PM_HEALER) ? "Doc, I can't help you unless you cooperate." : "Please undress so I can examine you."; else if (uarmu) verbl_msg = "Take off your shirt, please."; else verbl_msg = "Relax, this won't hurt a bit."; break; case MS_GUARD: if (money_cnt(invent)) verbl_msg = "Please drop that gold and follow me."; else verbl_msg = "Please follow me."; break; case MS_SOLDIER: { static const char *const soldier_foe_msg[3] = { "Resistance is useless!", "You're dog meat!", "Surrender!", }, *const soldier_pax_msg[3] = { "What lousy pay we're getting here!", "The food's not fit for Orcs!", "My feet hurt, I've been on them all day!", }; verbl_msg = mtmp->mpeaceful ? soldier_pax_msg[rn2(3)] : soldier_foe_msg[rn2(3)]; } break; case MS_RIDER: if (ptr == &mons[PM_DEATH] && !rn2(10)) pline_msg = "is busy reading a copy of Sandman #8."; else verbl_msg = "Who do you think you are, War?"; break; } if (pline_msg) pline("%s %s", Monnam(mtmp), pline_msg); else if (verbl_msg) verbalize("%s", verbl_msg); return 1; }
/* make a trap somewhere (in croom if mazeflag = 0) */ void mktrap(int num, int mazeflag, struct mkroom *croom) { struct trap *ttmp; int kind,nopierc,nomimic,fakedoor,fakegold,tryct = 0; xchar mx,my; if(!num || num >= TRAPNUM) { nopierc = (dlevel < 4) ? 1 : 0; nomimic = (dlevel < 9 || goldseen ) ? 1 : 0; if(index(fut_geno, 'M')) nomimic = 1; kind = rn2(TRAPNUM - nopierc - nomimic); /* note: PIERC = 7, MIMIC = 8, TRAPNUM = 9 */ } else kind = num; if(kind == MIMIC) { struct monst *mtmp; fakedoor = (!rn2(3) && !mazeflag); fakegold = (!fakedoor && !rn2(2)); if(fakegold) goldseen = TRUE; do { if(++tryct > 200) return; if(fakedoor) { /* note: fakedoor maybe on actual door */ if(rn2(2)){ if(rn2(2)) mx = croom->hx+1; else mx = croom->lx-1; my = somey(); } else { if(rn2(2)) my = croom->hy+1; else my = croom->ly-1; mx = somex(); } } else if(mazeflag) { coord mm; mm = mazexy(); mx = mm.x; my = mm.y; } else { mx = somex(); my = somey(); } } while(m_at(mx,my) || levl[mx][my].typ == STAIRS); if((mtmp = makemon(PM_MIMIC,mx,my))) { mtmp->mimic = 1; mtmp->mappearance = fakegold ? '$' : fakedoor ? '+' : (mazeflag && rn2(2)) ? AMULET_SYM : "=/)%?![<>" [ rn2(9) ]; } return; } do { if(++tryct > 200) return; if(mazeflag){ coord mm; mm = mazexy(); mx = mm.x; my = mm.y; } else { mx = somex(); my = somey(); } } while(t_at(mx, my) || levl[mx][my].typ == STAIRS); ttmp = maketrap(mx, my, kind); if(mazeflag && !rn2(10) && ttmp->ttyp < PIERC) ttmp->tseen = 1; }
/* * Let's destroy the drawbridge located at x,y */ void destroy_drawbridge(int x, int y) { struct rm *loc1, *loc2; struct trap *t; struct obj *chain; int x2, y2, i; boolean e_inview; struct entity *etmp1 = &(occupants[0]), *etmp2 = &(occupants[1]); loc1 = &level->locations[x][y]; if (!IS_DRAWBRIDGE(loc1->typ)) return; x2 = x; y2 = y; get_wall_for_db(&x2, &y2); loc2 = &level->locations[x2][y2]; if ((loc1->drawbridgemask & DB_UNDER) == DB_MOAT || (loc1->drawbridgemask & DB_UNDER) == DB_LAVA) { struct obj *otmp; boolean lava = (loc1->drawbridgemask & DB_UNDER) == DB_LAVA; if (loc1->typ == DRAWBRIDGE_UP) { if (cansee(x2, y2)) pline("The portcullis of the drawbridge falls into the %s!", lava ? "lava" : waterbody_name(x2, y2)); else You_hear("a loud *SPLASH*!"); } else { if (cansee(x, y)) pline("The drawbridge collapses into the %s!", lava ? "lava" : waterbody_name(x, y)); else You_hear("a loud *SPLASH*!"); } loc1->typ = lava ? LAVAPOOL : MOAT; loc1->drawbridgemask = 0; if ((otmp = sobj_at(BOULDER, level, x, y)) != 0) { obj_extract_self(otmp); flooreffects(otmp, x, y, "fall"); } } else { if (cansee(x, y)) pline("The drawbridge disintegrates!"); else You_hear("a loud *CRASH*!"); loc1->typ = ((loc1->drawbridgemask & DB_ICE) ? ICE : ROOM); loc1->icedpool = ((loc1->drawbridgemask & DB_ICE) ? ICED_MOAT : 0); } wake_nearto(x, y, 500); loc2->typ = DOOR; loc2->doormask = D_NODOOR; if ((t = t_at(level, x, y)) != 0) deltrap(level, t); if ((t = t_at(level, x2, y2)) != 0) deltrap(level, t); del_engr_at(level, x, y); del_engr_at(level, x2, y2); for (i = rn2(6); i > 0; --i) { /* scatter some debris */ /* doesn't matter if we happen to pick <x,y2> or <x2,y>; since drawbridges are never placed diagonally, those pairings will always match one of <x,y> or <x2,y2> */ chain = mksobj_at(IRON_CHAIN, level, rn2(2) ? x : x2, rn2(2) ? y : y2, TRUE, FALSE, rng_main); /* a force of 5 here would yield a radius of 2 for iron chain; anything less produces a radius of 1 */ (void) scatter(chain->ox, chain->oy, 1, MAY_HIT, chain); } newsym(x, y); newsym(x2, y2); if (!does_block(level, x2, y2)) unblock_point(x2, y2); /* vision */ if (Is_stronghold(&u.uz)) u.uevent.uopened_dbridge = TRUE; set_entity(x2, y2, etmp2); /* currently only automissers can be here */ if (etmp2->edata) { e_inview = e_canseemon(etmp2); if (!automiss(etmp2)) { if (e_inview) pline("%s blown apart by flying debris.", E_phrase(etmp2, "are")); e_died(etmp2, e_inview ? 3 : 2, CRUSHING, killer_msg(CRUSHING, "an exploding drawbridge")); } /* nothing which is vulnerable can survive this */ } set_entity(x, y, etmp1); if (etmp1->edata) { e_inview = e_canseemon(etmp1); if (!e_missed(etmp1, TRUE)) { if (e_inview) { if (!is_u(etmp1) && Hallucination) pline("%s into some heavy metal!", E_phrase(etmp1, "get")); else pline("%s hit by a huge chunk of metal!", E_phrase(etmp1, "are")); } else { if (!is_u(etmp1) && !is_pool(level, x, y)) You_hear("a crushing sound."); } e_died(etmp1, e_inview ? 3 : 2, CRUSHING, killer_msg(CRUSHING, "a collapsing drawbridge")); /* if (loc1->typ == MOAT) do_entity(etmp1); */ } if (is_u(etmp1)) spoteffects(FALSE); else if (!DEADMONSTER(etmp1->emon)) minliquid(etmp1->emon); } }
/* * drop_ball() * * The punished hero drops or throws her iron ball. If the hero is * blind, we must reset the order and glyph. Check for side effects. * This routine expects the ball to be already placed. * * Should not be called while swallowed. */ void drop_ball(xchar x, xchar y, schar dx, schar dy) { if (Blind) { u.bc_order = bc_order(); /* get the order */ /* pick up mem_obj */ u.bglyph = (u.bc_order) ? u.cglyph : level->locations[x][y].mem_obj; } if (x != u.ux || y != u.uy) { struct trap *t; const char *pullmsg = "The ball pulls you out of the %s!"; if (u.utrap && u.utraptype != TT_INFLOOR) { switch (u.utraptype) { case TT_PIT: pline(pullmsg, "pit"); break; case TT_WEB: pline(pullmsg, "web"); pline("The web is destroyed!"); deltrap(level, t_at(level, u.ux, u.uy)); break; case TT_LAVA: pline(pullmsg, "lava"); break; case TT_BEARTRAP:{ long side = rn2(3) ? LEFT_SIDE : RIGHT_SIDE; pline(pullmsg, "bear trap"); set_wounded_legs(side, rn1(1000, 500)); if (!u.usteed) { pline("Your %s %s is severely damaged.", (side == LEFT_SIDE) ? "left" : "right", body_part(LEG)); losehp(2, killer_msg(DIED, "leg damage from being " "pulled out of a bear trap")); } break; } } u.utrap = 0; fill_pit(level, u.ux, u.uy); } u.ux0 = u.ux; u.uy0 = u.uy; if (!Levitation && !MON_AT(level, x, y) && !u.utrap && (is_pool(level, x, y) || ((t = t_at(level, x, y)) && (t->ttyp == PIT || t->ttyp == SPIKED_PIT || t->ttyp == TRAPDOOR || t->ttyp == HOLE)))) { u.ux = x; u.uy = y; } else { u.ux = x - dx; u.uy = y - dy; } /* hero has moved, recalculate vision later */ turnstate.vision_full_recalc = TRUE; if (Blind) { /* drop glyph under the chain */ if (u.bc_felt & BC_CHAIN) level->locations[uchain->ox][uchain->oy].mem_obj = u.cglyph; u.bc_felt = 0; /* feel nothing */ /* pick up new glyph */ u.cglyph = (u.bc_order) ? u.bglyph : level->locations[u.ux][u.uy].mem_obj; } movobj(uchain, u.ux, u.uy); /* has a newsym */ if (Blind) { u.bc_order = bc_order(); } newsym(u.ux0, u.uy0); /* clean up old position */ if (u.ux0 != u.ux || u.uy0 != u.uy) { spoteffects(TRUE); if (In_sokoban(&u.uz)) change_luck(-1); /* Sokoban guilt */ } } }
int dosit() { static const char *sit_message = "sit on the %s."; register struct trap *trap; register int typ = levl[u.ux][u.uy].typ; if(Levitation) { pline("You're sitting on air."); return 0; } if(OBJ_AT(u.ux, u.uy)) { register struct obj *obj; obj = level.objects[u.ux][u.uy]; You("sit on %s.", the(xname(obj))); if(!Is_box(obj)) pline("It's not very comfortable..."); } else if ((trap = t_at(u.ux, u.uy)) != 0) { if (u.utrap) { exercise(A_WIS, FALSE); /* you're getting stuck longer */ if(u.utraptype == TT_BEARTRAP) { You("can't sit down with your %s in the bear trap.", body_part(FOOT)); u.utrap++; } else if(u.utraptype == TT_PIT) { if(trap->ttyp == SPIKED_PIT) { You("sit down on a spike. Ouch!"); losehp(1, "sitting on an iron spike", KILLED_BY); exercise(A_STR, FALSE); } else You("sit down in the pit."); u.utrap += rn2(5); } else if(u.utraptype == TT_WEB) { You("sit in the spider web and get entangled further!"); u.utrap += rn1(10, 5); } else if(u.utraptype == TT_LAVA) { /* Must have fire resistance or they'd be dead already */ You("sit in the lava!"); u.utrap += rnd(4); losehp(d(2,10), "sitting in lava", KILLED_BY); } else if(u.utraptype == TT_INFLOOR) { You("can't maneuver to sit!"); u.utrap++; } } else { You("sit down."); dotrap(trap); } } else if(Underwater || Is_waterlevel(&u.uz)) { if (Is_waterlevel(&u.uz)) pline("There are no cushions floating nearby."); else You("sit down in the muddy bottom."); } else if(is_pool(u.ux, u.uy)) { You("sit in the water."); if (!rn2(10) && uarm) (void) rust_dmg(uarm, "armor", 1, TRUE); #ifdef POLYSELF /* Note: without POLYSELF, this can't _happen_ without */ /* water walking boots.... */ if (!rn2(10) && uarmf && uarmf->otyp != WATER_WALKING_BOOTS) (void) rust_dmg(uarm, "armor", 1, TRUE); #endif #ifdef SINKS } else if(IS_SINK(typ)) { You(sit_message, defsyms[S_sink].explanation); Your("%s gets wet.", humanoid(uasmon) ? "rump" : "underside"); #endif } else if(IS_ALTAR(typ)) { You(sit_message, defsyms[S_altar].explanation); altar_wrath(u.ux, u.uy); } else if(typ == STAIRS) { You(sit_message, "stairs"); } else if(typ == LADDER) { You(sit_message, "ladder"); } else if (is_lava(u.ux, u.uy)) { /* must be WWalking */ You(sit_message, "lava"); pline("The lava burns you!"); losehp(d((Fire_resistance ? 2 : 10), 10), "sitting on lava", KILLED_BY); } else if (is_ice(u.ux, u.uy)) { You(sit_message, defsyms[S_ice].explanation); if (!Cold_resistance) pline("The ice feels cold."); } else if (typ == DRAWBRIDGE_DOWN) { You(sit_message, "drawbridge"); } else if(IS_THRONE(typ)) { You(sit_message, defsyms[S_throne].explanation); if (rnd(6) > 4) { switch (rnd(13)) { case 1: (void) adjattrib(rn2(A_MAX), -rn1(4,3), FALSE); losehp(rnd(10), "cursed throne", KILLED_BY_AN); break; case 2: (void) adjattrib(rn2(A_MAX), 1, FALSE); break; case 3: pline("A%s electric shock shoots through your body!", (Shock_resistance) ? "" : " massive"); losehp(Shock_resistance ? rnd(6) : rnd(30), "electric chair", KILLED_BY_AN); exercise(A_CON, FALSE); break; case 4: You("feel much, much better!"); if(u.uhp >= (u.uhpmax - 5)) u.uhpmax += 4; u.uhp = u.uhpmax; make_blinded(0L,TRUE); make_sick(0L,FALSE); heal_legs(); flags.botl = 1; break; case 5: take_gold(); break; case 6: if(u.uluck + rn2(5) < 0) { You("feel your luck is changing."); change_luck(1); } else makewish(); break; case 7: { register int cnt = rnd(10); pline("A voice echoes:"); verbalize("Thy audience hath been summoned, %s!", flags.female ? "Dame" : "Sire"); while(cnt--) (void) makemon(courtmon(), u.ux, u.uy); break; } case 8: pline("A voice echoes:"); verbalize("By thy Imperious order, %s...", flags.female ? "Dame" : "Sire"); do_genocide(1); break; case 9: pline("A voice echoes:"); verbalize("A curse upon thee for sitting upon this most holy throne!"); if (Luck > 0) { make_blinded(Blinded + rn1(100,250),TRUE); } else rndcurse(); break; case 10: if (Luck < 0 || (HSee_invisible & INTRINSIC)) { if (level.flags.nommap) { pline( "A terrible drone fills your head!"); make_confused(HConfusion + rnd(30), FALSE); } else { pline("An image forms in your mind."); do_mapping(); } } else { Your("vision becomes clear."); HSee_invisible |= FROMOUTSIDE; newsym(u.ux, u.uy); } break; case 11: if (Luck < 0) { You("feel threatened."); aggravate(); } else { You("feel a wrenching sensation."); tele(); /* teleport him */ } break; case 12: You("are granted an insight!"); if (invent) { int ret, cval = rn2(5); /* agrees w/seffects() */ /* use up `cval' "charges"; 0 is special case */ do { ret = ggetobj("identify", identify, cval); if (ret < 0) break; /* quit */ } while (ret == 0 || (cval -= ret) > 0); } break; case 13: Your("mind turns into a pretzel!"); make_confused(HConfusion + rn1(7,16),FALSE); break; default: impossible("throne effect"); break; } } else You("feel somehow out of place..."); if (!rn2(3) && IS_THRONE(levl[u.ux][u.uy].typ)) { /* may have teleported */ pline("The throne vanishes in a puff of logic."); levl[u.ux][u.uy].typ = ROOM; if(Invisible) newsym(u.ux,u.uy); } #ifdef POLYSELF } else if (lays_eggs(uasmon) || u.umonnum == PM_QUEEN_BEE) { struct obj *uegg; if (!flags.female) { pline("Males can't lay eggs!"); return 0; } if (u.uhunger < (int)objects[EGG].oc_nutrition) { You("don't have enough energy to lay an egg."); return 0; } uegg = mksobj(EGG, FALSE, FALSE); uegg->spe = 1; uegg->quan = 1; uegg->owt = weight(uegg); uegg->corpsenm = (u.umonnum==PM_QUEEN_BEE ? PM_KILLER_BEE : monsndx(uasmon)); uegg->known = uegg->dknown = 1; You("lay an egg."); dropy(uegg); stackobj(uegg); morehungry((int)objects[EGG].oc_nutrition); #endif } else if (u.uswallow) pline("There are no seats in here!"); else pline("Having fun sitting on the %s?", surface(u.ux,u.uy)); return(1); }
/* returns true if something happened */ boolean doorlock(struct obj * otmp, int x, int y) { struct rm *door = &level->locations[x][y]; boolean res = TRUE; int loudness = 0; int wandlevel = 0; if (otmp->oclass == WAND_CLASS) wandlevel = getwandlevel(&youmonst, otmp); /* Not completely right, but works since monsters wont use knock/wizlock */ const char *msg = NULL; const char *dustcloud = "A cloud of dust"; const char *quickly_dissipates = "quickly dissipates"; if (door->typ == SDOOR) { switch (otmp->otyp) { case WAN_OPENING: case SPE_KNOCK: case WAN_STRIKING: case SPE_FORCE_BOLT: door->typ = DOOR; door->doormask = D_CLOSED | (door->doormask & D_TRAPPED); newsym(x, y); if (cansee(x, y)) pline(msgc_youdiscover, "A door appears in the wall!"); if (otmp->otyp == WAN_OPENING || otmp->otyp == SPE_KNOCK) return TRUE; break; /* striking: continue door handling below */ case WAN_LOCKING: case SPE_WIZARD_LOCK: default: return FALSE; } } switch (otmp->otyp) { case WAN_LOCKING: case SPE_WIZARD_LOCK: if (Is_rogue_level(&u.uz)) { boolean vis = cansee(x, y); /* Can't have real locking in Rogue, so just hide doorway */ if (vis) pline(msgc_actionok, "%s springs up in the older, more primitive doorway.", dustcloud); else You_hear(msgc_actionok, "a swoosh."); if (obstructed(x, y, msgc_yafm)) { if (vis) pline(msgc_yafm, "The cloud %s.", quickly_dissipates); return FALSE; } block_point(x, y); door->typ = SDOOR; if (vis) pline(msgc_actionok, "The doorway vanishes!"); newsym(x, y); return TRUE; } if (obstructed(x, y, msgc_yafm)) return FALSE; /* Don't allow doors to close over traps. This is for pits */ /* & trap doors, but is it ever OK for anything else? */ if (t_at(level, x, y)) { /* maketrap() clears doormask, so it should be NODOOR */ pline(msgc_yafm, "%s springs up in the doorway, but %s.", dustcloud, quickly_dissipates); return FALSE; } if (wandlevel == P_MASTER) { pline(msgc_yafm, "%s springs up in the doorway and conceals it!", dustcloud); door->typ = SDOOR; newsym(x, y); return TRUE; } switch (door->doormask & ~D_TRAPPED) { case D_CLOSED: msg = "The door locks!"; break; case D_ISOPEN: msg = "The door swings shut, and locks!"; break; case D_BROKEN: msg = "The broken door reassembles and locks!"; break; case D_NODOOR: msg = "A cloud of dust springs up and assembles itself into a door!"; break; default: res = FALSE; break; } block_point(x, y); door->doormask = D_LOCKED | (door->doormask & D_TRAPPED); newsym(x, y); break; case WAN_OPENING: case SPE_KNOCK: if (door->doormask & D_LOCKED) { msg = "The door unlocks!"; door->doormask = D_CLOSED | (door->doormask & D_TRAPPED); } else res = FALSE; break; case WAN_STRIKING: case SPE_FORCE_BOLT: if (door->doormask & (D_LOCKED | D_CLOSED)) { if (door->doormask & D_TRAPPED) { if (MON_AT(level, x, y)) mb_trapped(m_at(level, x, y)); else { if (cansee(x, y)) pline(msgc_substitute, "KABOOM!! You see a door explode."); else You_hear(msgc_levelsound, "a distant explosion."); } door->doormask = D_NODOOR; unblock_point(x, y); newsym(x, y); loudness = 40; break; } door->doormask = D_BROKEN; if (cansee(x, y)) pline(msgc_actionok, "The door crashes open!"); else You_hear(msgc_levelsound, "a crashing sound."); unblock_point(x, y); newsym(x, y); /* force vision recalc before printing more messages */ if (turnstate.vision_full_recalc) vision_recalc(0); loudness = 20; } else res = FALSE; break; default: impossible("magic (%d) attempted on door.", otmp->otyp); break; } if (msg && cansee(x, y)) { pline(msgc_actionok, "%s", msg); /* we know whether it's locked now */ level->locations[x][y].mem_door_l = 1; map_background(x, y, TRUE); } if (loudness > 0) { /* door was destroyed */ wake_nearto(x, y, loudness); if (*in_rooms(level, x, y, SHOPBASE)) add_damage(x, y, 0L); } return res; }