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; } }
struct obj * mksobj(int otyp, boolean init, boolean artif) { int mndx, tryct; struct obj *otmp; char let = objects[otyp].oc_class; otmp = newobj(0); *otmp = zeroobj; otmp->age = monstermoves; otmp->o_id = flags.ident++; if (!otmp->o_id) otmp->o_id = flags.ident++; /* ident overflowed */ otmp->quan = 1L; otmp->oclass = let; otmp->otyp = otyp; otmp->where = OBJ_FREE; otmp->dknown = index(dknowns, let) ? 0 : 1; if (otmp->otyp == AMULET_OF_YENDOR) otmp->orecursive = FALSE; if ((otmp->otyp >= ELVEN_SHIELD && otmp->otyp <= ORCISH_SHIELD) || otmp->otyp == SHIELD_OF_REFLECTION) otmp->dknown = 0; if (!objects[otmp->otyp].oc_uses_known) otmp->known = 1; if (is_rustprone(otmp) || is_corrodeable(otmp) || is_flammable(otmp)) otmp->rknown = 1; #ifdef INVISIBLE_OBJECTS otmp->oinvis = !rn2(1250); #endif if (init) switch (let) { case WEAPON_CLASS: otmp->quan = is_multigen(otmp) ? (long) rn1(6,6) : 1L; if(!rn2(11)) { otmp->spe = rne(3); otmp->blessed = rn2(2); } else if(!rn2(10)) { curse(otmp); otmp->spe = -rne(3); } else blessorcurse(otmp, 10); if (is_poisonable(otmp) && !rn2(100)) otmp->opoisoned = 1; if (artif && !rn2(20)) otmp = mk_artifact(otmp, (aligntyp)A_NONE); break; case FOOD_CLASS: otmp->odrained = 0; otmp->oeaten = 0; switch(otmp->otyp) { case CORPSE: /* possibly overridden by mkcorpstat() */ tryct = 50; do otmp->corpsenm = undead_to_corpse(rndmonnum()); while ((mvitals[otmp->corpsenm].mvflags & G_NOCORPSE) && (--tryct > 0)); if (tryct == 0) { /* perhaps rndmonnum() only wants to make G_NOCORPSE monsters on this level; let's create an adventurer's corpse instead, then */ otmp->corpsenm = PM_HUMAN; } /* timer set below */ break; case EGG: otmp->corpsenm = NON_PM; /* generic egg */ if (!rn2(3)) for (tryct = 200; tryct > 0; --tryct) { mndx = can_be_hatched(rndmonnum()); if (mndx != NON_PM && !dead_species(mndx, TRUE)) { otmp->corpsenm = mndx; /* typed egg */ attach_egg_hatch_timeout(otmp); break; } } break; case TIN: otmp->corpsenm = NON_PM; /* empty (so far) */ if (!rn2(6)) otmp->spe = 1; /* spinach */ else for (tryct = 200; tryct > 0; --tryct) { mndx = undead_to_corpse(rndmonnum()); if (mons[mndx].cnutrit && !(mvitals[mndx].mvflags & G_NOCORPSE)) { otmp->corpsenm = mndx; break; } } blessorcurse(otmp, 10); break; case SLIME_MOLD: otmp->spe = current_fruit; break; case KELP_FROND: otmp->quan = (long) rnd(2); break; } if (otmp->otyp == CORPSE || otmp->otyp == MEAT_RING || otmp->otyp == KELP_FROND) break; /* fall into next case */ case GEM_CLASS: if (otmp->otyp == LOADSTONE) curse(otmp); else if (otmp->otyp == ROCK) otmp->quan = (long) rn1(6,6); else if (otmp->otyp != LUCKSTONE && !rn2(6)) otmp->quan = 2L; else otmp->quan = 1L; break; case TOOL_CLASS: switch(otmp->otyp) { case TALLOW_CANDLE: case WAX_CANDLE: otmp->spe = 1; otmp->age = 20L * /* 400 or 200 */ (long)objects[otmp->otyp].oc_cost; otmp->lamplit = 0; otmp->quan = 1L + (long)(rn2(2) ? rn2(7) : 0); blessorcurse(otmp, 5); break; case BRASS_LANTERN: case OIL_LAMP: otmp->spe = 1; otmp->age = (long) rn1(500,1000); otmp->lamplit = 0; blessorcurse(otmp, 5); break; case MAGIC_LAMP: otmp->spe = 1; otmp->lamplit = 0; blessorcurse(otmp, 2); break; case IRON_SAFE: otmp->olocked = 1; case CHEST: case LARGE_BOX: if (otmp->otyp != IRON_SAFE) { otmp->olocked = !!(rn2(5)); /* clumsy tweak */ } otmp->otrapped = !(rn2(10)); case ICE_BOX: case SACK: case OILSKIN_SACK: case BAG_OF_HOLDING: mkbox_cnts(otmp); break; #ifdef TOURIST case EXPENSIVE_CAMERA: #endif case TINNING_KIT: case MAGIC_MARKER: otmp->spe = rn1(60,20); break; case CAN_OF_GREASE: otmp->spe = rnd(25); blessorcurse(otmp, 10); break; case CRYSTAL_BALL: otmp->spe = rnd(5); blessorcurse(otmp, 2); break; case HORN_OF_PLENTY: case BAG_OF_TRICKS: otmp->spe = rnd(20); break; case FIGURINE: { int tryct2 = 0; do otmp->corpsenm = rndmonnum(); while(is_human(&mons[otmp->corpsenm]) && tryct2++ < 30); blessorcurse(otmp, 4); break; } case BELL_OF_OPENING: otmp->spe = 3; break; case MAGIC_FLUTE: case MAGIC_HARP: case FROST_HORN: case FIRE_HORN: case DRUM_OF_EARTHQUAKE: otmp->spe = rn1(5,4); break; } break; case AMULET_CLASS: if (otmp->otyp == AMULET_OF_YENDOR) flags.made_amulet = TRUE; if(rn2(10) && (otmp->otyp == AMULET_OF_STRANGULATION || otmp->otyp == AMULET_OF_CHANGE || otmp->otyp == AMULET_OF_RESTFUL_SLEEP)) { curse(otmp); } else blessorcurse(otmp, 10); case VENOM_CLASS: case CHAIN_CLASS: case BALL_CLASS: break; case POTION_CLASS: if (otmp->otyp == POT_OIL) otmp->age = MAX_OIL_IN_FLASK; /* amount of oil */ /* fall through */ case SCROLL_CLASS: #ifdef MAIL if (otmp->otyp != SCR_MAIL) #endif blessorcurse(otmp, 4); break; case SPBOOK_CLASS: blessorcurse(otmp, 17); break; case ARMOR_CLASS: if(rn2(10) && (otmp->otyp == FUMBLE_BOOTS || otmp->otyp == LEVITATION_BOOTS || otmp->otyp == HELM_OF_OPPOSITE_ALIGNMENT || otmp->otyp == GAUNTLETS_OF_FUMBLING || otmp->otyp == TINFOIL_HAT || !rn2(11))) { curse(otmp); otmp->spe = -rne(3); } else if(!rn2(10)) { otmp->blessed = rn2(2); otmp->spe = rne(3); } else blessorcurse(otmp, 10); if (artif && !rn2(40)) otmp = mk_artifact(otmp, (aligntyp)A_NONE); /* simulate lacquered armor for samurai */ if (Role_if(PM_SAMURAI) && otmp->otyp == SPLINT_MAIL && (moves <= 1 || In_quest(&u.uz))) { #ifdef UNIXPC /* optimizer bitfield bug */ otmp->oerodeproof = 1; otmp->rknown = 1; #else otmp->oerodeproof = otmp->rknown = 1; #endif } break; case WAND_CLASS: if (otmp->otyp == WAN_WISHING) { otmp->spe = (rnf(2,3) ? 1 : rnf(1,2) ? 0 : 2); otmp->recharged = 1; } else { otmp->spe = rn1(5, (objects[otmp->otyp].oc_dir == NODIR) ? 11 : 4); otmp->recharged = 0; /* used to control recharging */ } blessorcurse(otmp, 17); break; case RING_CLASS: if(objects[otmp->otyp].oc_charged) { blessorcurse(otmp, 3); if(rn2(10)) { if(rn2(10) && bcsign(otmp)) otmp->spe = bcsign(otmp) * rne(3); else otmp->spe = rn2(2) ? rne(3) : -rne(3); } /* make useless +0 rings much less common */ if (otmp->spe == 0) otmp->spe = rn2(4) - rn2(3); /* negative rings are usually cursed */ if (otmp->spe < 0 && rn2(5)) curse(otmp); } else if(rn2(10) && (otmp->otyp == RIN_TELEPORTATION || otmp->otyp == RIN_POLYMORPH || otmp->otyp == RIN_AGGRAVATE_MONSTER || otmp->otyp == RIN_HUNGER || !rn2(9))) { curse(otmp); } break; case ROCK_CLASS: switch (otmp->otyp) { case STATUE: /* possibly overridden by mkcorpstat() */ otmp->corpsenm = rndmonnum(); if (!verysmall(&mons[otmp->corpsenm]) && rn2(level_difficulty()/2 + 10) > 10) (void) add_to_container(otmp, mkobj(SPBOOK_CLASS,FALSE)); } break; case COIN_CLASS: break; /* do nothing */ default: warning("impossible mkobj %d, sym '%c'.", otmp->otyp, objects[otmp->otyp].oc_class); return (struct obj *)0; } /* Some things must get done (timers) even if init = 0 */ switch (otmp->otyp) { case CORPSE: start_corpse_timeout(otmp); break; } /* unique objects may have an associated artifact entry */ if (objects[otyp].oc_unique && !otmp->oartifact) otmp = mk_artifact(otmp, (aligntyp)A_NONE); otmp->owt = weight(otmp); return(otmp); }
void _add_command_to_menu(QSP_ARG_DECL Menu *mp, Command *cp ) { if( add_to_container(MENU_CONTAINER(mp),(Item *)cp) < 0 ) warn("add_command_to_menu: error adding command!?"); }
STATIC_OVL void mkbox_cnts(struct obj *box) { register int n; register struct obj *otmp; box->cobj = (struct obj *) 0; switch (box->otyp) { case ICE_BOX: n = 20; break; case IRON_SAFE: n = 10; break; case CHEST: n = 5; break; case LARGE_BOX: n = 3; break; case SACK: case OILSKIN_SACK: /* initial inventory: sack starts out empty */ if (moves <= 1 && !in_mklev) { n = 0; break; } /*else FALLTHRU*/ case BAG_OF_HOLDING: n = 1; break; default: n = 0; break; } for (n = rn2(n+1); n > 0; n--) { if (box->otyp == ICE_BOX) { if (!(otmp = mksobj(CORPSE, TRUE, TRUE))) continue; /* Note: setting age to 0 is correct. Age has a different * from usual meaning for objects stored in ice boxes. -KAA */ otmp->age = 0L; if (otmp->timed) { (void) stop_timer(ROT_CORPSE, (genericptr_t)otmp); (void) stop_timer(REVIVE_MON, (genericptr_t)otmp); } } else { register int tprob; const struct icp *iprobs = boxiprobs; for (tprob = rnd(100); (tprob -= iprobs->iprob) > 0; iprobs++) ; if (!(otmp = mkobj(iprobs->iclass, TRUE))) continue; /* handle a couple of special cases */ if (otmp->oclass == COIN_CLASS) { /* 2.5 x level's usual amount; weight adjusted below */ otmp->quan = (long)(rnd(level_difficulty()+2) * rnd(75)); otmp->owt = weight(otmp); } else while (otmp->otyp == ROCK) { otmp->otyp = rnd_class(DILITHIUM_CRYSTAL, LOADSTONE); if (otmp->quan > 2L) otmp->quan = 1L; otmp->owt = weight(otmp); } if (box->otyp == BAG_OF_HOLDING) { if (Is_mbag(otmp)) { otmp->otyp = SACK; otmp->spe = 0; otmp->owt = weight(otmp); } else while (otmp->otyp == WAN_CANCELLATION) otmp->otyp = rnd_class(WAN_LIGHT, WAN_LIGHTNING); } } (void) add_to_container(box, otmp); } }
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 */ } }