void mkzoo(int type) { struct mkroom *sroom; struct monst *mon; int sh, sx, sy, i; int goldlim = 500 * dlevel; int moct = 0; i = nroom; for (sroom = &rooms[rn2(nroom)];; sroom++) { if (sroom == &rooms[nroom]) sroom = &rooms[0]; if (!i-- || sroom->hx < 0) return; if (sroom->rtype) continue; if (type == MORGUE && sroom->rlit) continue; if (has_upstairs(sroom) || (has_dnstairs(sroom) && rn2(3))) continue; if (sroom->doorct == 1 || !rn2(5)) break; } sroom->rtype = type; sh = sroom->fdoor; for (sx = sroom->lx; sx <= sroom->hx; sx++) for (sy = sroom->ly; sy <= sroom->hy; sy++) { if ((sx == sroom->lx && doors[sh].x == sx - 1) || (sx == sroom->hx && doors[sh].x == sx + 1) || (sy == sroom->ly && doors[sh].y == sy - 1) || (sy == sroom->hy && doors[sh].y == sy + 1)) continue; mon = makemon((type == MORGUE) ? morguemon() : (type == BEEHIVE) ? PM_KILLER_BEE : (struct permonst *) 0, sx, sy); if (mon) mon->msleep = 1; switch (type) { case ZOO: i = sq(dist2(sx, sy, doors[sh].x, doors[sh].y)); if (i >= goldlim) i = 5 * dlevel; goldlim -= i; mkgold((long) (10 + rn2(i)), sx, sy); break; case MORGUE: // Usually there is one dead body in the morgue if (!moct && rn2(3)) { mksobj_at(CORPSE, sx, sy); moct++; } break; case BEEHIVE: if (!rn2(3)) mksobj_at(LUMP_OF_ROYAL_JELLY, sx, sy); break; } } }
/* drop a rock and remove monster */ static void monstone(struct monst *mdef) { if (strchr(mlarge, mdef->data->mlet)) mksobj_at(ENORMOUS_ROCK, mdef->mx, mdef->my); else mksobj_at(ROCK, mdef->mx, mdef->my); if (cansee(mdef->mx, mdef->my)) { unpmon(mdef); atl(mdef->mx, mdef->my, fobj->olet); } mondead(mdef); }
void makerogueghost(struct level *lev) { struct monst *ghost; struct obj *ghostobj; struct mkroom *croom; int x,y; if (!lev->nroom) return; /* Should never happen */ croom = &lev->rooms[rn2(lev->nroom)]; x = somex(croom); y = somey(croom); if (!(ghost = makemon(&mons[PM_GHOST], lev, x, y, NO_MM_FLAGS))) return; ghost->msleeping = 1; christen_monst(ghost, roguename()); if (rn2(4)) { ghostobj = mksobj_at(FOOD_RATION, lev, x, y, FALSE, FALSE); ghostobj->quan = (long) rnd(7); ghostobj->owt = weight(ghostobj); } if (rn2(2)) { ghostobj = mksobj_at(MACE, lev, x, y, FALSE, FALSE); ghostobj->spe = rnd(3); if (rn2(4)) curse(ghostobj); } else { ghostobj = mksobj_at(TWO_HANDED_SWORD, lev, x, y, FALSE, FALSE); ghostobj->spe = rnd(5) - 2; if (rn2(4)) curse(ghostobj); } ghostobj = mksobj_at(BOW, lev, x, y, FALSE, FALSE); ghostobj->spe = 1; if (rn2(4)) curse(ghostobj); ghostobj = mksobj_at(ARROW, lev, x, y, FALSE, FALSE); ghostobj->spe = 0; ghostobj->quan = (long) rn1(10,25); ghostobj->owt = weight(ghostobj); if (rn2(4)) curse(ghostobj); if (rn2(2)) { ghostobj = mksobj_at(RING_MAIL, lev, x, y, FALSE, FALSE); ghostobj->spe = rn2(3); if (!rn2(3)) ghostobj->oerodeproof = TRUE; if (rn2(4)) curse(ghostobj); } else { ghostobj = mksobj_at(PLATE_MAIL, lev, x, y, FALSE, FALSE); ghostobj->spe = rnd(5) - 2; if (!rn2(3)) ghostobj->oerodeproof = TRUE; if (rn2(4)) curse(ghostobj); } if (rn2(2)) { ghostobj = mksobj_at(FAKE_AMULET_OF_YENDOR, lev, x, y, TRUE, FALSE); ghostobj->known = TRUE; } }
void rnd_treesticks_at(int x, int y) { int num = rnd(3); while(num--) mksobj_at(rn2(2) ? QUARTERSTAFF : CLUB, x, y, TRUE, FALSE); }
/* make an object named after someone listed in the scoreboard file */ struct obj *mk_tt_object(struct level *lev, int objtype, /* CORPSE or STATUE */ int x, int y) { struct obj *otmp, *otmp2; boolean initialize_it; /* player statues never contain books */ initialize_it = (objtype != STATUE); if ((otmp = mksobj_at(objtype, lev, x, y, initialize_it, FALSE)) != 0) { /* tt_oname will return null if the scoreboard is empty */ if ((otmp2 = tt_oname(otmp)) != 0) otmp = otmp2; } return otmp; }
struct obj *mkgold(long amount, struct level *lev, int x, int y) { struct obj *gold = gold_at(lev, x, y); if (amount <= 0L) amount = (long)(1 + rnd(level_difficulty(&lev->z)+2) * rnd(30)); if (gold) { gold->quan += amount; } else { gold = mksobj_at(GOLD_PIECE, lev, x, y, TRUE, FALSE); gold->quan = amount; } gold->owt = weight(gold); return gold; }
struct obj * mkgold(long int amount, int x, int y) { register struct obj *gold = g_at(x,y); if (amount <= 0L) amount = (long)(1 + rnd(level_difficulty()+2) * rnd(30)); if (gold) { gold->quan += amount; } else { gold = mksobj_at(GOLD_PIECE, x, y, TRUE, FALSE); gold->quan = amount; } gold->owt = weight(gold); return (gold); }
static void makeniche(bool with_trap) { struct mkroom *aroom; struct rm *rm; int vct = 8; coord dd; int dy,xx,yy; struct trap *ttmp; if(doorindex < DOORMAX) while(vct--) { aroom = &rooms[rn2(nroom-1)]; if(aroom->rtype != 0) continue; /* not an ordinary room */ if(aroom->doorct == 1 && rn2(5)) continue; if(rn2(2)) { dy = 1; dd = finddpos(aroom->lx,aroom->hy+1,aroom->hx,aroom->hy+1); } else { dy = -1; dd = finddpos(aroom->lx,aroom->ly-1,aroom->hx,aroom->ly-1); } xx = dd.x; yy = dd.y; if((rm = &levl[xx][yy+dy])->typ) continue; if(with_trap || !rn2(4)) { rm->typ = SCORR; rm->scrsym = ' '; if(with_trap) { ttmp = maketrap(xx, yy+dy, TELEP_TRAP); ttmp->once = 1; make_engr_at(xx, yy-dy, "ad ae?ar um"); } dosdoor(xx, yy, aroom, SDOOR); } else { rm->typ = CORR; rm->scrsym = CORR_SYM; if(rn2(7)) dosdoor(xx, yy, aroom, rn2(5) ? SDOOR : DOOR); else { mksobj_at(SCR_TELEPORTATION, xx, yy+dy); if(!rn2(3)) mkobj_at(0, xx, yy+dy); } } return; } }
/* * OEXTRA note: Passing mtmp causes mtraits to be saved * even if ptr passed as well, but ptr is always used for * the corpse type (corpsenm). That allows the corpse type * to be different from the original monster, * i.e. vampire -> human corpse * yet still allow restoration of the original monster upon * resurrection. */ struct obj * mkcorpstat(int objtype, struct monst *mtmp, struct permonst *ptr, int x, int y, boolean init) /* CORPSE or STATUE */ { register struct obj *otmp; if (objtype != CORPSE && objtype != STATUE) warning("making corpstat type %d", objtype); if (x == 0 && y == 0) { /* special case - random placement */ otmp = mksobj(objtype, init, FALSE); if (otmp) rloco(otmp); } else otmp = mksobj_at(objtype, x, y, init, FALSE); if (otmp) { if (mtmp) { struct obj *otmp2; if (!ptr) ptr = mtmp->data; /* save_mtraits frees original data pointed to by otmp */ otmp2 = save_mtraits(otmp, mtmp); if (otmp2) otmp = otmp2; } /* use the corpse or statue produced by mksobj() as-is unless `ptr' is non-null */ if (ptr) { int old_corpsenm = otmp->corpsenm; otmp->corpsenm = monsndx(ptr); otmp->owt = weight(otmp); if (otmp->otyp == CORPSE && (special_corpse(old_corpsenm) || special_corpse(otmp->corpsenm))) { obj_stop_timers(otmp); start_corpse_timeout(otmp); } } } return(otmp); }
/* make an object of the appropriate type for a shop square */ static void mkshobj_at ( const struct shclass *shp, int sx, int sy) { struct monst *mtmp; int atype; struct permonst *ptr; if (rn2(100) < depth(&u.uz) && !MON_AT(sx, sy) && (ptr = mkclass(S_MIMIC,0)) && (mtmp = makemon(ptr,sx,sy,NO_MM_FLAGS)) != 0) { /* note: makemon will set the mimic symbol to a shop item */ if (rn2(10) >= depth(&u.uz)) { mtmp->m_ap_type = M_AP_OBJECT; mtmp->mappearance = STRANGE_OBJECT; } } else { atype = get_shop_item(shp - shtypes); if (atype < 0) (void) mksobj_at(-atype, sx, sy, true, true); else (void) mkobj_at(atype, sx, sy, true); } }
/* Make an object of the appropriate type for a shop square. Uses the level generation RNG. */ static void mkshobj_at(const struct shclass *shp, struct level *lev, int sx, int sy) { struct monst *mtmp; int atype; const struct permonst *ptr; enum rng rng = rng_for_level(&lev->z); if (rn2_on_rng(100, rng) < depth(&lev->z) && !MON_AT(lev, sx, sy) && (ptr = mkclass(&lev->z, S_MIMIC, 0, rng)) && (mtmp = makemon(ptr, lev, sx, sy, MM_ALLLEVRNG)) != 0) { /* note: makemon will set the mimic symbol to a shop item */ if (rn2_on_rng(10, rng) >= depth(&lev->z)) { mtmp->m_ap_type = M_AP_OBJECT; mtmp->mappearance = STRANGE_OBJECT; } } else { atype = get_shop_item(shp - shtypes, rng); if (atype < 0) mksobj_at(-atype, lev, sx, sy, TRUE, TRUE, rng); else mkobj_at(atype, lev, sx, sy, TRUE, rng); } }
void fill_zoo (struct mkroom *sroom) { struct monst *mon; int sx,sy,i; int sh, tx, ty, goldlim, type = sroom->rtype; int rmno = (sroom - rooms) + ROOMOFFSET; coord mm; sh = sroom->fdoor; switch(type) { case COURT: if(level.flags.is_maze_lev) { for(tx = sroom->lx; tx <= sroom->hx; tx++) for(ty = sroom->ly; ty <= sroom->hy; ty++) if(IS_THRONE(levl[tx][ty].typ)) goto throne_placed; } i = 100; do { /* don't place throne on top of stairs */ (void) somexy(sroom, &mm); tx = mm.x; ty = mm.y; } while (occupied((signed char)tx, (signed char)ty) && --i > 0); throne_placed: /* TODO: try to ensure the enthroned monster is an M2_PRINCE */ break; case BEEHIVE: tx = sroom->lx + (sroom->hx - sroom->lx + 1)/2; ty = sroom->ly + (sroom->hy - sroom->ly + 1)/2; if(sroom->irregular) { /* center might not be valid, so put queen elsewhere */ if ((int) levl[tx][ty].roomno != rmno || levl[tx][ty].edge) { (void) somexy(sroom, &mm); tx = mm.x; ty = mm.y; } } break; case ZOO: case LEPREHALL: goldlim = 500 * level_difficulty(); break; } for(sx = sroom->lx; sx <= sroom->hx; sx++) for(sy = sroom->ly; sy <= sroom->hy; sy++) { if(sroom->irregular) { if ((int) levl[sx][sy].roomno != rmno || levl[sx][sy].edge || (sroom->doorct && distmin(sx, sy, doors[sh].x, doors[sh].y) <= 1)) continue; } else if(!SPACE_POS(levl[sx][sy].typ) || (sroom->doorct && ((sx == sroom->lx && doors[sh].x == sx-1) || (sx == sroom->hx && doors[sh].x == sx+1) || (sy == sroom->ly && doors[sh].y == sy-1) || (sy == sroom->hy && doors[sh].y == sy+1)))) continue; /* don't place monster on explicitly placed throne */ if(type == COURT && IS_THRONE(levl[sx][sy].typ)) continue; mon = makemon( (type == COURT) ? courtmon() : (type == BARRACKS) ? squadmon() : (type == MORGUE) ? morguemon() : (type == BEEHIVE) ? (sx == tx && sy == ty ? &mons[PM_QUEEN_BEE] : &mons[PM_KILLER_BEE]) : (type == LEPREHALL) ? &mons[PM_LEPRECHAUN] : (type == COCKNEST) ? &mons[PM_COCKATRICE] : (type == ANTHOLE) ? antholemon() : (struct permonst *) 0, sx, sy, NO_MM_FLAGS); if(mon) { mon->msleeping = 1; if (type==COURT && mon->mpeaceful) { mon->mpeaceful = 0; set_malign(mon); } } switch(type) { case ZOO: case LEPREHALL: if(sroom->doorct) { int distval = dist2(sx,sy,doors[sh].x,doors[sh].y); i = sq(distval); } else i = goldlim; if(i >= goldlim) i = 5*level_difficulty(); goldlim -= i; (void) mkgold((long) rn1(i, 10), sx, sy); break; case MORGUE: if(!rn2(5)) (void) mk_tt_object(CORPSE, sx, sy); if(!rn2(10)) /* lots of treasure buried with dead */ (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST, sx, sy, true, false); if (!rn2(5)) make_grave(sx, sy, (char *)0); break; case BEEHIVE: if(!rn2(3)) (void) mksobj_at(LUMP_OF_ROYAL_JELLY, sx, sy, true, false); break; case BARRACKS: if(!rn2(20)) /* the payroll and some loot */ (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST, sx, sy, true, false); break; case COCKNEST: if(!rn2(3)) { struct obj *sobj = mk_tt_object(STATUE, sx, sy); if (sobj) { for (i = rn2(5); i; i--) (void) add_to_container(sobj, mkobj(RANDOM_CLASS, false)); sobj->owt = weight(sobj); } } break; case ANTHOLE: if(!rn2(3)) (void) mkobj_at(FOOD_CLASS, sx, sy, false); break; } } switch (type) { case COURT: { struct obj *chest; levl[tx][ty].typ = THRONE; (void) somexy(sroom, &mm); (void) mkgold((long) rn1(50 * level_difficulty(),10), mm.x, mm.y); /* the royal coffers */ chest = mksobj_at(CHEST, mm.x, mm.y, true, false); chest->spe = 2; /* so it can be found later */ level.flags.has_court = 1; break; } case BARRACKS: level.flags.has_barracks = 1; break; case ZOO: level.flags.has_zoo = 1; break; case MORGUE: level.flags.has_morgue = 1; break; case SWAMP: level.flags.has_swamp = 1; break; case BEEHIVE: level.flags.has_beehive = 1; break; } }
/* Record the breaking of a roleplay-conduct. */ void violated(int cdt) { switch (cdt) { case CONDUCT_PACIFISM: u.uconduct.killer++; if (u.roleplay.pacifist) { pline("你感到狂暴!"); if (yn("你确定要退出吗?") == 'y') { killer_format = NO_KILLER_PREFIX; killer = "在一阵狂暴之后退出"; done(QUIT); } if (u.uconduct.killer >= 10) u.roleplay.pacifist = FALSE; } break; case CONDUCT_NUDISM: u.uconduct.armoruses++; if (u.roleplay.nudist) { pline("你意识到你光着身子。"); makemon(&mons[PM_COBRA], level, u.ux, u.uy, NO_MM_FLAGS); mksobj_at(APPLE, level, u.ux, u.uy, FALSE, FALSE); u.roleplay.nudist = FALSE; } break; case CONDUCT_BLINDFOLDED: u.uconduct.unblinded++; if (u.roleplay.blindfolded) { pline("禅之精神,离开你的身体。"); makemon(mkclass(&level->z, S_ZOMBIE, 0), level, u.ux, u.uy, NO_MM_FLAGS); /* Z */ makemon(mkclass(&level->z, S_EYE, 0), level, u.ux, u.uy, NO_MM_FLAGS); /* e */ makemon(mkclass(&level->z, S_NYMPH, 0), level, u.ux, u.uy, NO_MM_FLAGS); /* n */ u.roleplay.blindfolded = FALSE; } break; case CONDUCT_VEGETARIAN: /* replaces violated_vegetarian() */ if (u.roleplay.vegetarian) pline("你感到内疚。"); if (Role_if(PM_MONK)) adjalign(-1); u.uconduct.unvegetarian++; u.uconduct.unvegan++; u.uconduct.food++; if (u.uconduct.unvegetarian >= 30) u.roleplay.vegetarian = FALSE; if (u.uconduct.unvegan >= 20) u.roleplay.vegan = FALSE; if (u.uconduct.food >= 10) u.roleplay.ascet = FALSE; break; case CONDUCT_VEGAN: if (u.roleplay.vegan) pline("你感到有点内疚。"); u.uconduct.unvegan++; u.uconduct.food++; if (u.uconduct.unvegan >= 20) u.roleplay.vegan = FALSE; if (u.uconduct.food >= 10) u.roleplay.ascet = FALSE; break; case CONDUCT_FOODLESS: if (u.roleplay.ascet) pline("你略微感到内疚。"); u.uconduct.food++; if (u.uconduct.food >= 10) u.roleplay.ascet = FALSE; break; case CONDUCT_ILLITERACY: u.uconduct.literate++; if (u.roleplay.illiterate) { /* should be impossible */ pline("Literatally literature for literate illiterates!"); exercise(A_WIS, TRUE); } break; case CONDUCT_THIEVERY: u.uconduct.robbed++; if (Role_if(PM_ROGUE)) pline("你感觉自己像一个强盗。"); break; default: impossible("violated: unknown conduct"); } }
void fill_zoo(struct level *lev, struct mkroom *sroom, enum rng rng) { struct monst *mon; int sx, sy, i; int sh, tx, ty, goldlim, type = sroom->rtype; int rmno = (sroom - lev->rooms) + ROOMOFFSET; coord mm; tx = ty = goldlim = 0; sh = sroom->fdoor; switch (type) { case COURT: if (lev->flags.is_maze_lev) { for (tx = sroom->lx; tx <= sroom->hx; tx++) for (ty = sroom->ly; ty <= sroom->hy; ty++) if (IS_THRONE(lev->locations[tx][ty].typ)) goto throne_placed; } i = 100; do { /* don't place throne on top of stairs */ somexy(lev, sroom, &mm, rng); tx = mm.x; ty = mm.y; } while (occupied(lev, tx, ty) && --i > 0); throne_placed: /* TODO: try to ensure the enthroned monster is an M2_PRINCE */ break; case BEEHIVE: tx = sroom->lx + (sroom->hx - sroom->lx + 1) / 2; ty = sroom->ly + (sroom->hy - sroom->ly + 1) / 2; if (sroom->irregular) { /* center might not be valid, so put queen elsewhere */ if ((int)lev->locations[tx][ty].roomno != rmno || lev->locations[tx][ty].edge) { somexy(lev, sroom, &mm, rng); tx = mm.x; ty = mm.y; } } break; case ZOO: case LEPREHALL: goldlim = 500 * level_difficulty(&lev->z); break; } for (sx = sroom->lx; sx <= sroom->hx; sx++) for (sy = sroom->ly; sy <= sroom->hy; sy++) { if (sroom->irregular) { if ((int)lev->locations[sx][sy].roomno != rmno || lev->locations[sx][sy].edge || (sroom->doorct && distmin(sx, sy, lev->doors[sh].x, lev->doors[sh].y) <= 1)) continue; } else if (!SPACE_POS(lev->locations[sx][sy].typ) || (sroom->doorct && ((sx == sroom->lx && lev->doors[sh].x == sx - 1) || (sx == sroom->hx && lev->doors[sh].x == sx + 1) || (sy == sroom->ly && lev->doors[sh].y == sy - 1) || (sy == sroom->hy && lev->doors[sh].y == sy + 1)))) continue; /* don't place monster on explicitly placed throne */ if (type == COURT && IS_THRONE(lev->locations[sx][sy].typ)) continue; mon = makemon((type == COURT) ? courtmon(&lev->z, rng) : (type == BARRACKS) ? squadmon(&lev->z) : (type == MORGUE) ? morguemon(&lev->z, rng) : (type == BEEHIVE) ? (sx == tx && sy == ty ? &mons[PM_QUEEN_BEE] : &mons[PM_KILLER_BEE]) : (type == LEPREHALL) ? &mons[PM_LEPRECHAUN] : (type == COCKNEST) ? &mons[PM_COCKATRICE] : (type == ANTHOLE) ? antholemon(&lev->z) : NULL, lev, sx, sy, rng == rng_main ? NO_MM_FLAGS : MM_ALLLEVRNG); if (mon) { mon->msleeping = 1; if (type == COURT && mon->mpeaceful) msethostility(mon, TRUE, TRUE); } switch (type) { case ZOO: case LEPREHALL: if (sroom->doorct) { int distval = dist2(sx, sy, lev->doors[sh].x, lev->doors[sh].y); i = sq(distval); } else i = goldlim; if (i >= goldlim) i = 5 * level_difficulty(&lev->z); goldlim -= i; mkgold(10 + rn2_on_rng(i, rng), lev, sx, sy, rng); break; case MORGUE: if (!rn2_on_rng(5, rng)) mk_tt_object(lev, CORPSE, sx, sy); if (!rn2_on_rng(10, rng)) /* lots of treasure */ mksobj_at(rn2_on_rng(3, rng) ? LARGE_BOX : CHEST, lev, sx, sy, TRUE, FALSE, rng); if (!rn2_on_rng(5, rng)) make_grave(lev, sx, sy, NULL); break; case BEEHIVE: if (!rn2_on_rng(3, rng)) mksobj_at(LUMP_OF_ROYAL_JELLY, lev, sx, sy, TRUE, FALSE, rng); break; case BARRACKS: if (!rn2_on_rng(20, rng)) /* the payroll and some loot */ mksobj_at((rn2(3)) ? LARGE_BOX : CHEST, lev, sx, sy, TRUE, FALSE, rng); break; case COCKNEST: if (!rn2_on_rng(3, rng)) { struct obj *sobj = mk_tt_object(lev, STATUE, sx, sy); if (sobj) { for (i = rn2_on_rng(5, rng); i; i--) add_to_container(sobj, mkobj(lev, RANDOM_CLASS, FALSE, rng)); sobj->owt = weight(sobj); } } break; case ANTHOLE: if (!rn2_on_rng(3, rng)) mkobj_at(FOOD_CLASS, lev, sx, sy, FALSE, rng); break; } } if (type == COURT) { struct obj *chest; lev->locations[tx][ty].typ = THRONE; somexy(lev, sroom, &mm, rng); mkgold(10 + rn2_on_rng(50 * level_difficulty(&lev->z), rng), lev, mm.x, mm.y, rng); /* the royal coffers */ chest = mksobj_at(CHEST, lev, mm.x, mm.y, TRUE, FALSE, rng); chest->spe = 2; /* so it can be found later */ } }
void makemaz() { int x,y; int zx,zy; coord mm; boolean al = (dlevel >= 30 && !flags.made_amulet); for(x = 2; x < COLNO-1; x++) for(y = 2; y < ROWNO-1; y++) levl[x][y].typ = (x%2 && y%2) ? 0 : HWALL; if(al) { struct monst *mtmp; zx = 2*(COLNO/4) - 1; zy = 2*(ROWNO/4) - 1; for(x = zx-2; x < zx+4; x++) for(y = zy-2; y <= zy+2; y++) { levl[x][y].typ = (y == zy-2 || y == zy+2 || x == zx-2 || x == zx+3) ? POOL : (y == zy-1 || y == zy+1 || x == zx-1 || x == zx+2) ? HWALL: ROOM; } (void) mkobj_at(AMULET_SYM, zx, zy); flags.made_amulet = 1; walkfrom(zx+4, zy); if ((mtmp = makemon(&hell_hound, zx, zy))) mtmp->msleep = 1; if ((mtmp = makemon(PM_WIZARD, zx+1, zy))) { mtmp->msleep = 1; flags.no_of_wizards = 1; } } else { mm = mazexy(); zx = mm.x; zy = mm.y; walkfrom(zx,zy); (void) mksobj_at(WAN_WISHING, zx, zy); (void) mkobj_at(ROCK_SYM, zx, zy); /* put a rock on top of it */ } for(x = 2; x < COLNO-1; x++) for(y = 2; y < ROWNO-1; y++) { switch(levl[x][y].typ) { case HWALL: levl[x][y].scrsym = '-'; break; case ROOM: levl[x][y].scrsym = '.'; break; } } for(x = rn1(8,11); x; x--) { mm = mazexy(); (void) mkobj_at(rn2(2) ? GEM_SYM : 0, mm.x, mm.y); } for(x = rn1(10,2); x; x--) { mm = mazexy(); (void) mkobj_at(ROCK_SYM, mm.x, mm.y); } mm = mazexy(); (void) makemon(PM_MINOTAUR, mm.x, mm.y); for(x = rn1(5,7); x; x--) { mm = mazexy(); (void) makemon((struct permonst *) 0, mm.x, mm.y); } for(x = rn1(6,7); x; x--) { mm = mazexy(); mkgold(0L,mm.x,mm.y); } for(x = rn1(6,7); x; x--) mktrap(0,1,(struct mkroom *) 0); mm = mazexy(); levl[(int)(xupstair = mm.x)][(int)(yupstair = mm.y)].scrsym = '<'; levl[(int)xupstair][(int)yupstair].typ = STAIRS; xdnstair = ydnstair = 0; }
struct obj * rnd_treefruit_at(int x, int y) { return mksobj_at(treefruits[rn2(SIZE(treefruits))], x, y, TRUE, FALSE); }
/* * 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); } }
int dozap(void) { struct obj *obj; xchar zx,zy; obj = getobj("/", "zap"); if(!obj) return(0); if(obj->spe < 0 || (obj->spe == 0 && rn2(121))) { pline("Nothing Happens."); return(1); } if(obj->spe == 0) pline("You wrest one more spell from the worn-out wand."); if(!(objects[obj->otyp].bits & NODIR) && !getdir(1)) return(1); /* make him pay for knowing !NODIR */ obj->spe--; if(objects[obj->otyp].bits & IMMEDIATE) { if(u.uswallow) bhitm(u.ustuck, obj); else if(u.dz) { if(u.dz > 0) { struct obj *otmp = o_at(u.ux, u.uy); if(otmp) bhito(otmp, obj); } } else bhit(u.dx,u.dy,rn1(8,6),0,bhitm,bhito,obj); } else { switch(obj->otyp){ case WAN_LIGHT: litroom(TRUE); break; case WAN_SECRET_DOOR_DETECTION: if(!findit()) return(1); break; case WAN_CREATE_MONSTER: { int cnt = 1; if(!rn2(23)) cnt += rn2(7) + 1; while(cnt--) makemon(NULL, u.ux, u.uy); } break; case WAN_WISHING: { char buf[BUFSZ]; struct obj *otmp; if(u.uluck + rn2(5) < 0) { pline("Unfortunately, nothing happens."); break; } pline("You may wish for an object. What do you want? "); getlin(buf); if(buf[0] == '\033') buf[0] = 0; otmp = readobjnam(buf); otmp = addinv(otmp); prinv(otmp); break; } case WAN_DIGGING: /* Original effect (approximately): * from CORR: dig until we pierce a wall * from ROOM: piece wall and dig until we reach * an ACCESSIBLE place. * Currently: dig for digdepth positions; * also down on request of Lennart Augustsson. */ { struct rm *room; int digdepth; if(u.uswallow) { struct monst *mtmp = u.ustuck; pline("You pierce %s's stomach wall!", monnam(mtmp)); mtmp->mhp = 1; /* almost dead */ unstuck(mtmp); mnexto(mtmp); break; } if(u.dz) { if(u.dz < 0) { pline("You loosen a rock from the ceiling."); pline("It falls on your head!"); losehp(1, "falling rock"); mksobj_at(ROCK, u.ux, u.uy); fobj->quan = 1; stackobj(fobj); if(Invisible) newsym(u.ux, u.uy); } else { dighole(); } break; } zx = u.ux+u.dx; zy = u.uy+u.dy; digdepth = 8 + rn2(18); Tmp_at(-1, '*'); /* open call */ while(--digdepth >= 0) { if(!isok(zx,zy)) break; room = &levl[zx][zy]; Tmp_at(zx,zy); if(!xdnstair){ if(zx < 3 || zx > COLNO-3 || zy < 3 || zy > ROWNO-3) break; if(room->typ == HWALL || room->typ == VWALL){ room->typ = ROOM; break; } } else if(room->typ == HWALL || room->typ == VWALL || room->typ == SDOOR || room->typ == LDOOR){ room->typ = DOOR; digdepth -= 2; } else if(room->typ == SCORR || !room->typ) { room->typ = CORR; digdepth--; } mnewsym(zx,zy); zx += u.dx; zy += u.dy; } mnewsym(zx,zy); /* not always necessary */ Tmp_at(-1,-1); /* closing call */ break; } default: buzz((int) obj->otyp - WAN_MAGIC_MISSILE, u.ux, u.uy, u.dx, u.dy); break; } } return(1); }
void nh_timeout() { register struct prop *upp; int sleeptime; int m_idx; int baseluck = (flags.moonphase == FULL_MOON) ? 1 : 0; if (flags.friday13) baseluck -= 1; if (u.uluck != baseluck && moves % (u.uhave.amulet || u.ugangr ? 300 : 600) == 0) { /* Cursed luckstones stop bad luck from timing out; blessed luckstones * stop good luck from timing out; normal luckstones stop both; * neither is stopped if you don't have a luckstone. * Luck is based at 0 usually, +1 if a full moon and -1 on Friday 13th */ register int time_luck = stone_luck(FALSE); boolean nostone = !carrying(LUCKSTONE) && !stone_luck(TRUE); if(u.uluck > baseluck && (nostone || time_luck < 0)) u.uluck--; else if(u.uluck < baseluck && (nostone || time_luck > 0)) u.uluck++; } if(u.uinvulnerable) return; /* things past this point could kill you */ if(Stoned) stoned_dialogue(); if(Slimed) slime_dialogue(); if(Vomiting) vomiting_dialogue(); if(Strangled) choke_dialogue(); if(u.mtimedone && !--u.mtimedone) { if (Unchanging) u.mtimedone = rnd(100*youmonst.data->mlevel + 1); else rehumanize(); } if(u.ucreamed) u.ucreamed--; /* Dissipate spell-based protection. */ if (u.usptime) { if (--u.usptime == 0 && u.uspellprot) { u.usptime = u.uspmtime; u.uspellprot--; find_ac(); if (!Blind) Norep("The %s haze around you %s.", hcolor(NH_GOLDEN), u.uspellprot ? "becomes less dense" : "disappears"); } } #ifdef STEED if (u.ugallop) { if (--u.ugallop == 0L && u.usteed) pline("%s stops galloping.", Monnam(u.usteed)); } #endif for(upp = u.uprops; upp < u.uprops+SIZE(u.uprops); upp++) if((upp->intrinsic & TIMEOUT) && !(--upp->intrinsic & TIMEOUT)) { switch(upp - u.uprops){ case STONED: if (delayed_killer && !killer) { killer = delayed_killer; delayed_killer = 0; } if (!killer) { /* leaving killer_format would make it "petrified by petrification" */ killer_format = NO_KILLER_PREFIX; killer = "killed by petrification"; } done(STONING); break; case SLIMED: if (delayed_killer && !killer) { killer = delayed_killer; delayed_killer = 0; } if (!killer) { killer_format = NO_KILLER_PREFIX; killer = "turned into green slime"; } done(TURNED_SLIME); break; case VOMITING: make_vomiting(0L, TRUE); break; case SICK: You("die from your illness."); killer_format = KILLED_BY_AN; killer = u.usick_cause; if ((m_idx = name_to_mon(killer)) >= LOW_PM) { if (type_is_pname(&mons[m_idx])) { killer_format = KILLED_BY; } else if (mons[m_idx].geno & G_UNIQ) { killer = the(killer); Strcpy(u.usick_cause, killer); killer_format = KILLED_BY; } } u.usick_type = 0; done(POISONING); break; case FAST: if (!Very_fast) You_feel("yourself slowing down%s.", Fast ? " a bit" : ""); break; case CONFUSION: HConfusion = 1; /* So make_confused works properly */ make_confused(0L, TRUE); stop_occupation(); break; case STUNNED: HStun = 1; make_stunned(0L, TRUE); stop_occupation(); break; case BLINDED: Blinded = 1; make_blinded(0L, TRUE); stop_occupation(); break; case INVIS: newsym(u.ux,u.uy); if (!Invis && !BInvis && !Blind) { You(!See_invisible ? "are no longer invisible." : "can no longer see through yourself."); stop_occupation(); } break; case SEE_INVIS: set_mimic_blocking(); /* do special mimic handling */ see_monsters(); /* make invis mons appear */ newsym(u.ux,u.uy); /* make self appear */ stop_occupation(); break; case WOUNDED_LEGS: heal_legs(); stop_occupation(); break; case HALLUC: HHallucination = 1; (void) make_hallucinated(0L, TRUE, 0L); stop_occupation(); break; case SLEEPING: if (unconscious() || Sleep_resistance) HSleeping += rnd(100); else if (Sleeping) { You("fall asleep."); sleeptime = rnd(20); fall_asleep(-sleeptime, TRUE); HSleeping += sleeptime + rnd(100); } break; case LEVITATION: (void) float_down(I_SPECIAL|TIMEOUT, 0L); break; case STRANGLED: killer_format = KILLED_BY; killer = (u.uburied) ? "suffocation" : "strangulation"; done(DIED); break; case FUMBLING: /* call this only when a move took place. */ /* otherwise handle fumbling msgs locally. */ if (u.umoved && !Levitation) { slip_or_trip(); nomul(-2, "fumbling"); nomovemsg = ""; /* The more you are carrying the more likely you * are to make noise when you fumble. Adjustments * to this number must be thoroughly play tested. */ if ((inv_weight() > -500)) { You("make a lot of noise!"); wake_nearby(); } } /* from outside means slippery ice; don't reset counter if that's the only fumble reason */ HFumbling &= ~FROMOUTSIDE; if (Fumbling) HFumbling += rnd(20); break; case DETECT_MONSTERS: see_monsters(); break; case PREGNANT: { char buf[BUFSZ]; if (!flags.female) { strcpy(buf, body_part(STOMACH)); if (!strcmp(buf, "stomach")) strcpy(buf, "belly"); pline("Something bursts out of your %s!"); killer_format = KILLED_BY; killer = "male childbirth"; done(DIED); } mksobj_at(PLACENTA, u.ux, u.uy, FALSE, FALSE); pline("BABIES!"); /* TODO */ stop_occupation(); break; } } } run_timers(); }
void killed(struct monst *mtmp) { #define NEW_SCORING int tmp; int tmp2; int nk; int x; int y; struct permonst *mdat = mtmp->data; if(mtmp->cham != 0) { mdat = PM_CHAM; } if(Blind != 0) { pline("You destroy it!"); } else { if(mtmp->mtame != 0) { pline("You destroy %s!", amonnam(mtmp, "poor")); } else { pline("You destroy %s!", monnam(mtmp)); } } if(u.umconf != 0) { if(Blind == 0) { pline("Your hands stop clowing blue."); u.umconf = 0; } } /* Count killed monsters */ #define MAXMONNO 100 /* In case we cannot find it in mons */ nk = 1; /* Index in mons array (if not 'd', '@', ...) */ tmp = mdat - mons; if((tmp >= 0) && (tmp < (CMNUM + 2))) { extern char fut_geno[]; ++u.nr_killed[tmp]; nk = u.nr_killed[tmp]; if((nk > MAXMONNO) && (index(fut_geno, mdat->mlet) == 0)) { charcat(fut_geno, mdat->mlet); } } /* Punish bad behaviour */ if(mdat->mlet == '@') { Telepat = 0; u.uluck -= 2; } if((mtmp->mpeaceful != 0) || (mtmp->mtame != 0)) { --u.uluck; } if(mdat->mlet == 'u') { u.uluck -= 5; } /* Give experience points */ tmp = 1 + (mdat->mlevel * mdat->mlevel); if(mdat->ac < 3) { tmp += (2 * (7 - mdat->ac)); } if(index("AcsSDXaeRTVWU&In:P", mdat->mlet) != 0) { tmp += (2 * mdat->mlevel); } if(index("DeV&P", mdat->mlet) != 0) { tmp += (7 * mdat->mlevel); } if(mdat->mlevel > 6) { tmp += 50; } #ifdef NEW_SCORING /* * ------- Recent addition: make number of points decrease * when this is not the first of this kind */ int ul = u.ulevel; int ml = mdat->mlevel; /* Points are given based on present and future level */ if(ul < 14) { for(tmp2 = 0; (tmp2 == 0) || ((ul + tmp2) <= ml); ++tmp2) { if(tmp <= 0) { if(((u.uexp + 1) + ((tmp + (0)) / nk)) >= (10 * pow(2, (unsigned)(ul - 1)))) { ++ul; if(ul == 14) { break; } } } else { if(((u.uexp + 1) + ((tmp + (4 << (tmp2 - 1))) / nk)) >= (10 * pow(2, (unsigned)(ul - 1)))) { ++ul; if(ul == 14) { break; } } } } } tmp2 = (ml - ul) - 1; if(tmp2 < 0) { tmp = (tmp + (0)) / nk; } else { tmp = (tmp + (4 << tmp2)) / nk; } if(tmp == 0) { tmp = 1; } /* * Note: ul is not necessarily the future value of u.ulevel * ------- End of recent valuation change ------- */ #endif u.uexp += tmp; u.urexp += (4 * tmp); flags.botl = 1; while((u.ulevel < 14) && (u.uexp >= (10 * pow(2, u.ulevel - 1)))) { ++u.ulevel; pline("Welcome to level %d.", u.ulevel); tmp = rnd(30); if(tmp < 3) { tmp = rnd(10); } u.uhpmax += tmp; u.uhp += tmp; flags.botl = 1; } /* Dispose of monster and make cadaver */ x = mtmp->mx; y = mtmp->my; mondead(mtmp); tmp = mdat->mlet; if(tmp == 'm') { /* He killed a minotaur, give him a wand of digging */ /* Note: The dead minotaur will be on top of it! */ mksobj_at(WAND_SYM, WAN_DIGGING, x, y); /* * if(cansee(x, y) != 0) { * atl(x, y, fobj->olet); * } */ stackobj(fobj); } #ifndef NOWORM else if(tmp == 'w') { mksobj_at(WEAPON_SYM, WORM_TOOTH, x, y); stackobj(fobj); } #endif else { if((letter(tmp) == 0) || (rn2(3) == 0)) { tmp = 0; } if(levl[x][y].typ >= DOOR) { /* Might be a mimic in wall */ if((x != u.ux) || (y != u.uy)) { /* Might be here after swallowed */ if((index("NTVm&", mdat->mlet) != NULL) || (rn2(5) != 0)) { mkobj_at(tmp, x, y); if(cansee(x, y) != 0) { atl(x, y, fobj->olet); } stackobj(fobj); } } } } }
void do_trap(trap_t *trap) // was dotrap { Short ttype = get_trap_type(trap->trap_info); nomul(0); if (get_trap_seen(trap->trap_info) && !rund(5) && ttype != PIT) { StrPrintF(ScratchBuffer, "You escape a%s.", traps[ttype]); message(ScratchBuffer); } else { trap->trap_info |= SEEN_TRAP; switch(ttype) { case SLP_GAS_TRAP: message("A cloud of gas puts you to sleep!"); nomul(-rnd(25)); break; case BEAR_TRAP: if (Levitation) { message("You float over a bear trap."); break; } you.utrap = 4 + rund(4); you.utraptype = TT_BEARTRAP; message("A bear trap closes on your foot!"); break; case PIERC: deltrap(trap); if (makemon(PM_PIERCER, you.ux, you.uy)) { message("A piercer suddenly drops from the ceiling!"); if (uarmh) message("Its blow glances off your helmet."); else thing_hit_you(3, dice(4,6), "falling piercer"); } break; case ARROW_TRAP: message("An arrow shoots out at you!"); if (!thing_hit_you(8, rnd(6), "arrow")){ mksobj_at(ARROW, you.ux, you.uy); fobj->quantity = 1; } break; case TRAPDOOR: if (!xdnstair) { message("A trap door in the ceiling opens and a rock falls on your head!"); if (uarmh) message("Fortunately, you are wearing a helmet!"); losehp((uarmh ? 2 : dice(2,10)), "falling rock"); mksobj_at(ROCK, you.ux, you.uy); fobj->quantity = 1; stackobj(fobj); if (Invisible) newsym(you.ux, you.uy); } else { Short newlevel = dlevel + 1; while (!rund(4) && newlevel < 29) newlevel++; message("A trap door opens up under you!"); if (Levitation || you.ustuck) { message("For some reason you don't fall in."); break; } goto_level(newlevel, false); } break; case DART_TRAP: message("A little dart shoots out at you!"); if (thing_hit_you(7, rnd(3), "little dart")) { if (!rund(6)) poisoned("dart", "poison dart"); } else { mksobj_at(DART, you.ux, you.uy); fobj->quantity = 1; } break; case TELEP_TRAP: map_mode_teleport = TELE_TRAP; if (get_trap_once(trap->trap_info)) { deltrap(trap); newsym(you.ux,you.uy); vtele(); } else { newsym(you.ux,you.uy); tele(); } break; case PIT: if (Levitation) { message("A pit opens up under you!"); message("You don't fall in!"); break; } message("You fall into a pit!"); you.utrap = rund(6) + 2; you.utraptype = TT_PIT; losehp(rnd(6),"fall into a pit"); selftouch("Falling, you"); break; default: StrPrintF(ScratchBuffer, "BUG: You hit a trap with info=%u", trap->trap_info); message(ScratchBuffer); } } }