1
0
Fork 0
mirror of https://codeberg.org/noisytoot/notnotdnethack.git synced 2025-07-31 18:02:26 +01:00
demogorgon22 2022-04-03 19:28:34 -04:00
commit 5c407fe9c0
24 changed files with 356 additions and 273 deletions

View file

@ -174,7 +174,7 @@ MONSTER:'@',"Cassilda the Iron Maiden",(34,09)
# Ladders
LADDER:(50,09),down
MONSTER:'@',"Stranger",(48,09)
MONSTER:'@',"Stranger",(48,09),hostile
OBJECT:'"',"amulet versus curses",(48,09),blessed,0,"The Star of Hypernotus"
MONSTER:'@',"priestess",(42,01), peaceful

View file

@ -1693,7 +1693,7 @@ A("The Sickle of Thunderblasts", SICKLE, (const char *)0,
A("The War-helm of the Dreaming", FACELESS_HELM, "bird-like bone faceless helm",
4500L, MT_DEFAULT, MZ_DEFAULT, WT_DEFAULT,
A_NEUTRAL, PM_MADMAN, NON_PM, TIER_A, (ARTG_NOGEN|ARTG_NOWISH|ARTG_MAJOR|ARTG_FXALGN),
A_CHAOTIC, PM_MADMAN, NON_PM, TIER_A, (ARTG_NOGEN|ARTG_NOWISH|ARTG_MAJOR|ARTG_FXALGN),
NO_MONS(),
NO_ATTK(), NOFLAG,
PROPS(MAGICAL_BREATHING, WALKING_NIGHTMARE), NOFLAG,
@ -1703,7 +1703,7 @@ A("The War-helm of the Dreaming", FACELESS_HELM, "bird-like bone faceless helm
A("The Spear of Peace", SPEAR, (const char *)0,
1500L, WOOD, MZ_DEFAULT, WT_DEFAULT,
A_CHAOTIC, PM_MADMAN, NON_PM, TIER_A, (ARTG_NOGEN|ARTG_NOWISH|ARTG_MAJOR|ARTG_FXALGN),
A_NEUTRAL, PM_MADMAN, NON_PM, TIER_A, (ARTG_NOGEN|ARTG_NOWISH|ARTG_MAJOR|ARTG_FXALGN),
NO_MONS(),
NO_ATTK(), NOFLAG,
PROPS(CLEAR_THOUGHTS, BLOCK_CONFUSION, HALLUC_RES, HALF_PHDAM, HALF_SPDAM), NOFLAG,

View file

@ -1522,6 +1522,7 @@ E boolean FDECL(is_flammable, (struct obj *));
E boolean FDECL(is_rottable, (struct obj *));
E void FDECL(place_object, (struct obj *,int,int));
E void FDECL(remove_object, (struct obj *));
E void FDECL(uncontain, (struct obj *));
E void FDECL(discard_minvent, (struct monst *));
E void FDECL(obj_extract_self, (struct obj *));
E void FDECL(obj_extract_and_unequip_self, (struct obj *));
@ -3363,6 +3364,7 @@ E int FDECL(unturn_dead, (struct monst *));
E void FDECL(cancel_item, (struct obj *));
E boolean FDECL(drain_item, (struct obj *));
E boolean FDECL(damage_item, (struct obj *));
E struct obj *FDECL(randpoly_obj, (struct obj *));
E struct obj *FDECL(poly_obj, (struct obj *, int));
E boolean FDECL(obj_resists, (struct obj *,int,int));
E boolean FDECL(obj_shudders, (struct obj *));

View file

@ -1110,7 +1110,6 @@ you_regen_san()
if (Role_if(PM_MONK)) reglevel += 8;
if (Role_if(PM_PRIEST)) reglevel += 7;
if (Role_if(PM_ANACHRONONAUT)) reglevel += 5;
if (Role_if(PM_TOURIST)) reglevel += 2;
if (Role_if(PM_EXILE)) reglevel += spiritDsize();
if (Role_if(PM_CONVICT)) reglevel -= 3;
if (Role_if(PM_NOBLEMAN)) reglevel -= 5;
@ -1170,7 +1169,7 @@ you_regen_san()
//Lots of stressful circumstances here!
else if(Race_if(PM_DROW)){
if(Role_if(PM_NOBLEMAN)){
if(Is_nemesis(&u.uz) && flags.initgend){
if(Is_nemesis(&u.uz)){
reglevel -= 30;
}
else if(Is_qstart(&u.uz) && Role_if(PM_NOBLEMAN) && !flags.initgend){
@ -1286,7 +1285,7 @@ moveloop()
didmove = flags.move;
if(didmove) {
/* actual time passed */
if(u.umoved){
if(u.umoved && !u.uattked){
int step_cost = NORMAL_SPEED;
#define COST(val) step_cost = min(val, step_cost);
if(uwep && uwep->oartifact == ART_TENSA_ZANGETSU){
@ -2056,7 +2055,7 @@ karemade:
)){
makemon(&mons[PM_ASPECT_OF_THE_SILENCE], 0, 0, NO_MM_FLAGS);
}
else if(!Infuture && !Is_nowhere(&u.uz) && !rn2(COA_PROB)){
else if(!Infuture && !mvitals[PM_CENTER_OF_ALL].died && !Is_nowhere(&u.uz) && !rn2(COA_PROB)){
coa_arrive();
}
else if(!(Is_illregrd(&u.uz) && u.ualign.type == A_LAWFUL && !u.uevent.uaxus_foe) && /*Turn off random generation on axus's level if lawful*/
@ -4869,6 +4868,8 @@ struct monst *mon;
else
mtmp0->nmon = mtmp->nmon;
mon_arrive(mtmp, FALSE);
mtmp->msleeping = mtmp->mtame = mtmp->mpeaceful = 0;
set_malign(mtmp);
break;
} else
mtmp0 = mtmp;

View file

@ -1677,10 +1677,7 @@ struct obj *obj;
else pline("This %s has no %s.", xname(obj), obj->otyp != GNOMISH_POINTY_HAT ? "oil" : "wax");
return;
}
if (is_lightsaber(obj) && !obj->cobj && !(
obj->oartifact == ART_INFINITY_S_MIRRORED_ARC ||
obj->oartifact == ART_ANNULUS
)) {
if (is_gemable_lightsaber(obj) && !obj->cobj) {
pline1(nothing_happens);
return;
}

View file

@ -11568,7 +11568,7 @@ arti_poly_contents(obj)
if (obj_shudders(otmp)) {
dobj = otmp;
}
else otmp = poly_obj(otmp, STRANGE_OBJECT);
else otmp = randpoly_obj(otmp);
}
}
if (dobj) {

View file

@ -4970,7 +4970,7 @@ boolean invoked;
//cast spell
doibite_cast(magr, wep);
}
else if(u.uinsight >= 40){
else if(u.uinsight >= 40 || invoked){
//hit targets
doibite_thrash(magr, wep);
}

View file

@ -1591,31 +1591,46 @@ void
udr_enlightenment()
{
int dr;
int cap = 11;
char mbuf[BUFSZ] = {'\0'};
en_win = create_nhwindow(NHW_MENU);
putstr(en_win, 0, "Current Damage Reduction:");
putstr(en_win, 0, "");
if(active_glyph(DEEP_SEA))
cap += 3;
if(!has_head_mon(&youmonst)){
Sprintf(mbuf, "You have no head; shots hit upper body");
putstr(en_win, 0, mbuf);
} else {
dr = slot_udr(HEAD_DR, (struct monst *)0, 0);
Sprintf(mbuf, "Head Armor: %s%d", (dr>11) ? "11-" : "", dr);
if(dr > cap)
Sprintf(mbuf, "Head Armor: %d-%d", cap, dr);
else
Sprintf(mbuf, "Head Armor: %d", dr);
putstr(en_win, 0, mbuf);
}
dr = slot_udr(UPPER_TORSO_DR, (struct monst *)0, 0);
Sprintf(mbuf, "Upper Body Armor: %s%d", (dr>11) ? "11-" : "", dr);
if(dr > cap)
Sprintf(mbuf, "Upper Body Armor: %d-%d", cap, dr);
else
Sprintf(mbuf, "Upper Body Armor: %d", dr);
dr = slot_udr(LOWER_TORSO_DR, (struct monst *)0, 0);
putstr(en_win, 0, mbuf);
Sprintf(mbuf, "Lower Body Armor: %s%d", (dr>11) ? "11-" : "", dr);
if(dr > cap)
Sprintf(mbuf, "Lower Body Armor: %d-%d", cap, dr);
else
Sprintf(mbuf, "Lower Body Armor: %d", dr);
putstr(en_win, 0, mbuf);
if(!can_wear_gloves(youracedata)){
Sprintf(mbuf, "You have no hands; shots hit upper body");
putstr(en_win, 0, mbuf);
} else {
dr = slot_udr(ARM_DR, (struct monst *)0, 0);
Sprintf(mbuf, "Hand Armor: %s%d", (dr>11) ? "11-" : "", dr);
if(dr > cap)
Sprintf(mbuf, "Hand Armor: %d-%d", cap, dr);
else
Sprintf(mbuf, "Hand Armor: %d", dr);
putstr(en_win, 0, mbuf);
}
if(!can_wear_boots(youracedata)){
@ -1623,7 +1638,10 @@ udr_enlightenment()
putstr(en_win, 0, mbuf);
} else {
dr = slot_udr(LEG_DR, (struct monst *)0, 0);
Sprintf(mbuf, "Foot Armor: %s%d", (dr>11) ? "11-" : "", dr);
if(dr > cap)
Sprintf(mbuf, "Foot Armor: %d-%d", cap, dr);
else
Sprintf(mbuf, "Foot Armor: %d", dr);
putstr(en_win, 0, mbuf);
}

View file

@ -551,7 +551,6 @@ register xchar x,y;
{
return (boolean)!((levl[x][y].wall_info & W_NONDIGGABLE)
&&((IS_STWALL(levl[x][y].typ) ||
IS_TREE(levl[x][y].typ) ||
IS_TREES(levl[x][y].typ)
)));
}
@ -562,7 +561,7 @@ register xchar x,y;
{
return (boolean)!((levl[x][y].wall_info & W_NONPASSWALL)
&&((IS_STWALL(levl[x][y].typ) ||
IS_TREE(levl[x][y].typ)
IS_TREES(levl[x][y].typ)
)));
}

View file

@ -4815,7 +4815,7 @@ boolean goodequip;
(void) mpickobj(mtmp, otmp);
} else if(mm == PM_DEEP_ONE || mm == PM_DEEPER_ONE) {
if(Infuture){
if(mm == PM_DEEP_ONE){
if(mm == PM_DEEPER_ONE){
switch (rn2(3)) {
case 0:
(void)mongets(mtmp, LEATHER_ARMOR, mkobjflags);
@ -5162,7 +5162,7 @@ boolean goodequip;
}
}
}
}else if((mm == PM_MIND_FLAYER || mm == PM_MASTER_MIND_FLAYER)){
} else if((mm == PM_MIND_FLAYER || mm == PM_MASTER_MIND_FLAYER)){
if(on_level(&rlyeh_level,&u.uz)){
otmp = mksobj(BULLWHIP, mkobjflags);
otmp->oerodeproof = 1;
@ -8958,6 +8958,7 @@ boolean goodequip;
} else if(Infuture){
otmp = mksobj(QUARTERSTAFF, mkobjflags);
otmp->spe = 9;
add_oprop(otmp, OPROP_PSIOW);
add_oprop(otmp, OPROP_PHSEW);
add_oprop(otmp, OPROP_WATRW);
otmp->objsize = MZ_GIGANTIC;

View file

@ -5173,8 +5173,10 @@ int tary;
else if(is_metallic(otmp)){
if(!obj_resists(otmp, 55, 95)){
if(!Blind)
Your("%s turns golden!", xname(otmp));
Your("%s turns golden yellow!", xname(otmp));
set_material(otmp, GOLD);
//Item may not naturally be yellow.
otmp->obj_color = CLR_YELLOW;
}
}
else {

View file

@ -2966,6 +2966,15 @@ register struct obj *otmp;
}
}
/* extra handling on extracting an object from a (non magic chest) container */
void
uncontain(obj)
struct obj * obj;
{
if (is_gemable_lightsaber(obj->ocontainer) && obj->ocontainer->lamplit)
end_burn(obj->ocontainer, TRUE);
}
/* throw away all of a monster's inventory */
void
discard_minvent(mtmp)
@ -3042,6 +3051,7 @@ obj_extract_self(obj)
remove_object(obj);
break;
case OBJ_CONTAINED:
uncontain(obj);
extract_nobj(obj, &obj->ocontainer->cobj);
container_weight(obj->ocontainer);
break;

View file

@ -3497,14 +3497,21 @@ dmonsfree()
int count = 0;
for (mtmp = &fmon; *mtmp;) {
if (DEADMONSTER(*mtmp)) {
struct monst *freetmp = *mtmp;
*mtmp = (*mtmp)->nmon;
rem_all_mx(freetmp);
dealloc_monst(freetmp);
count++;
} else
mtmp = &(*mtmp)->nmon;
if (DEADMONSTER(*mtmp)) {
struct monst *freetmp = *mtmp;
*mtmp = (*mtmp)->nmon;
rem_all_mx(freetmp);
dealloc_monst(freetmp);
count++;
}
else {
/* sanity check */
if ((*mtmp)->mhp < 1) {
impossible("monster (%s) has hp <1 (%d) but not marked dead", m_monnam(*mtmp), (*mtmp)->mhp);
mondead(*mtmp);
}
mtmp = &(*mtmp)->nmon;
}
}
if (count != iflags.purge_monsters)

View file

@ -10075,7 +10075,7 @@ is a red right hand
ATTK(AT_MAGC, AD_CLRC, 2, 8), ATTK(AT_MAGC, AD_CLRC, 2, 8)),
SIZ(WT_HUMAN, 400, MS_PRIEST, MZ_HUMAN),
MR_FIRE|MR_ELEC|MR_SLEEP|MR_POISON|MR_MAGIC|MR_STONE, 0,
MM_BREATHLESS /*MM*/, MT_OMNIVORE|MT_COLLECT|MT_MAGIC|MT_WANTSARTI|MT_WANTSAMUL /*MT*/, MF_MARTIAL_S /*MF*/,
MM_BREATHLESS /*MM*/, MT_HOSTILE|MT_OMNIVORE|MT_COLLECT|MT_MAGIC|MT_WANTSARTI|MT_WANTSAMUL /*MT*/, MF_MARTIAL_S /*MF*/,
MB_HUMANOID|MB_STRONG|MB_NEUTER|MB_NOEYES /*MB*/,
MG_NOSPELLCOOLDOWN|MG_NOWISH|MG_NOTAME|MG_NOPOLY|MG_PRINCE|MG_NASTY|MG_INFRAVISIBLE /*MG*/,
MA_G_O_O|MA_MINION|MA_ET /*MA*/, MV_EXTRAMISSION|MV_SEE_INVIS /*MV*/, CLR_YELLOW),

View file

@ -1494,6 +1494,9 @@ fix_object(otmp)
struct obj *otmp;
{
otmp->owt = weight(otmp);
if (obj_eternal_light(otmp) && !otmp->lamplit) {
begin_burn(otmp);
}
}
/*o_init.c*/

View file

@ -133,7 +133,7 @@ make_invulnerable(xtime,talk)
long xtime;
boolean talk;
{
long old = HStun;
long old = HSanctuary;
if (!xtime && old) {
if (talk){
@ -2806,7 +2806,7 @@ dodip()
else if (obj == uswapwep) was_swapwep = TRUE;
else if (obj == uquiver) was_quiver = TRUE;
obj = poly_obj(obj, STRANGE_OBJECT);
obj = randpoly_obj(obj);
if (was_wep) setuwep(obj);
else if (was_swapwep) setuswapwep(obj);

View file

@ -1052,10 +1052,19 @@ boolean ghostly;
} else if (monstermoves > omoves)
mon_catchup_elapsed_time(mtmp, monstermoves - omoves);
/* update shape-changers in case protection against
them is different now than when the level was saved */
restore_cham(mtmp);
/* update shape-changers in case protection against
them is different now than when the level was saved */
restore_cham(mtmp);
}
if(u.silver_flame_z.dnum == u.uz.dnum && u.silver_flame_z.dlevel == u.uz.dlevel
&& !(u.s_f_x) && !(u.s_f_y)
){
int limit = 1000;
do {
u.s_f_x = rnd(COLNO-1);
u.s_f_y = rn2(ROWNO);
} while((!isok(u.s_f_x, u.s_f_y) || !ZAP_POS(levl[u.s_f_x][u.s_f_y].typ)) && limit-- > 0);
}
}
if (ghostly)

View file

@ -1066,16 +1066,18 @@ register struct obj *obj, *merge;
}
}
if (donning(obj)) cancel_don();
if (obj == uwep) uwepgone();
else if (obj == uswapwep) uswapwepgone();
else if (obj == uquiver) uqwepgone();
else if (obj == uarm) setnotworn(obj);
else if (obj == uarmc) setnotworn(obj);
else if (obj == uarmh) setnotworn(obj);
else if (obj == uarms) setnotworn(obj);
else if (obj == uarmg) setnotworn(obj);
else if (obj == uarmu) setnotworn(obj);
else if (obj == uarmf) setnotworn(obj);
else if (obj == uarm) {Armor_off(); setnotworn(obj);}
else if (obj == uarmc) {Cloak_off(); setnotworn(obj);}
else if (obj == uarmh) {Helmet_off(); setnotworn(obj);}
else if (obj == uarms) {Shield_off(); setnotworn(obj);}
else if (obj == uarmg) {Gloves_off(); setnotworn(obj);}
else if (obj == uarmu) {Shirt_off(); setnotworn(obj);}
else if (obj == uarmf) {Boots_off(); setnotworn(obj);}
dealloc_obj(obj);
}

View file

@ -666,6 +666,10 @@ place_monster(mon, x, y)
struct monst *mon;
int x, y;
{
if( (mon->deadmonster&DEADMONSTER_PURGE) && !(mon->deadmonster&DEADMONSTER_DEAD)){
mon->deadmonster = 0;
pline("Bad deadmonster state detected (and fixed)");
}
if (mon == u.usteed ||
/* special case is for convoluted vault guard handling */
(DEADMONSTER(mon) && !(mon->isgd && x == 0 && y == 0))) {

View file

@ -2766,6 +2766,10 @@ u_init()
u.oonaenergy = !rn2(3) ? AD_FIRE : rn2(2) ? AD_COLD : AD_ELEC;
u.ring_wishes = -1;
dungeon_topology.alt_tower = !rn2(8);
u.silver_flame_z.dnum = u.uz.dnum;
u.silver_flame_z.dlevel = rn2(dunlevs_in_dungeon(&u.uz)) + dungeons[u.uz.dnum].depth_start;
int common_caste = 0;
switch(rn2(6)){
case 0:

View file

@ -371,6 +371,7 @@ register struct obj *obj;
}
update_inventory();
if ((obj == uwep || obj == uswapwep) && !test_twoweapon()) u.twoweap = 0;
}
void

View file

@ -4390,7 +4390,7 @@ boolean ranged;
/* assumes the player was polyed and not in natural form */
You("burn up!");
rehumanize();
break;
return (MM_HIT | MM_DEF_LSVD);
}
else {
if (vis)
@ -17714,6 +17714,7 @@ struct monst *mdef;
#define DID_MOVE u.uen -= 8;\
nomul(0, NULL);\
u.uattked = TRUE;\
return TRUE;
/* monk_moves()

471
src/zap.c
View file

@ -23,6 +23,7 @@ extern boolean notonhead; /* for long worms */
/* kludge to use mondied instead of killed */
extern boolean m_using;
STATIC_DCL void FDECL(polyuse, (struct obj*, int, int));
STATIC_DCL struct obj * FDECL(poly_obj_core, (struct obj *, int));
STATIC_DCL void FDECL(create_polymon, (struct obj *, int));
STATIC_DCL boolean FDECL(zap_updown, (struct obj *));
STATIC_DCL boolean FDECL(zap_reflect, (struct monst *, struct zapdata *));
@ -1575,143 +1576,95 @@ struct obj *obj;
delobj(obj);
}
/*
* Polymorph the object to the given object ID. If the ID is STRANGE_OBJECT
* then pick random object from the source's class (this is the standard
* "polymorph" case). If ID is set to a specific object, inhibit fusing
* n objects into 1. This could have been added as a flag, but currently
* it is tied to not being the standard polymorph case. The new polymorphed
* object replaces obj in its link chains. Return value is a pointer to
* the new object.
/*
* Polymorphs obj into a random object from the source's class.
*
* This should be safe to call for an object anywhere.
* May shrink stacks, has controls against various abuses,
* and is generally has behaviour befitting of polymorph magic.
*
* Replaces obj in chains, returing a pointer to the new object.
*/
struct obj *
poly_obj(obj, id)
struct obj *obj;
int id;
randpoly_obj(obj)
struct obj * obj;
{
struct obj *otmp;
xchar ox, oy;
boolean can_merge = (id == STRANGE_OBJECT);
int obj_location = obj->where;
int new_otyp = STRANGE_OBJECT; // default to random
struct obj * otmp; // new object
if (obj->otyp == BOULDER && In_sokoban(&u.uz))
change_luck(-1); /* Sokoban guilt, boulders only */
if (id == STRANGE_OBJECT) { /* preserve symbol */
if(obj->otyp == SPE_BLANK_PAPER || obj->otyp == SCR_BLANK_PAPER || obj->otyp == SCR_AMNESIA){
otmp = mksobj(rn2(2) ? SPE_BLANK_PAPER : SCR_BLANK_PAPER, MKOBJ_NOINIT);
} else if(obj->otyp == POT_BLOOD){
otmp = mksobj(POT_BLOOD, MKOBJ_NOINIT);
} else if(obj->otyp == POT_WATER || obj->otyp == POT_AMNESIA){
if(obj->otyp == POT_AMNESIA){
obj->otyp = POT_WATER;
set_object_color(obj);
}
if(!rn2(3)){
obj->blessed = 0;
obj->cursed = 1;
} else if(rn2(2)){
obj->cursed = 0;
obj->blessed = 1;
} else {
obj->blessed = 0;
obj->cursed = 0;
}
return obj;
} else if(obj->otyp == HYPOSPRAY_AMPULE){
int pick;
otmp = mksobj(HYPOSPRAY_AMPULE, MKOBJ_NOINIT);
do{
switch(rn2(14)){
case 0:
pick = POT_GAIN_ABILITY;
break;
case 1:
pick = POT_RESTORE_ABILITY;
break;
case 2:
pick = POT_BLINDNESS;
break;
case 3:
pick = POT_CONFUSION;
break;
case 4:
pick = POT_PARALYSIS;
break;
case 5:
pick = POT_SPEED;
break;
case 6:
pick = POT_HALLUCINATION;
break;
case 7:
pick = POT_HEALING;
break;
case 8:
pick = POT_EXTRA_HEALING;
break;
case 9:
pick = POT_GAIN_ENERGY;
break;
case 10:
pick = POT_SLEEPING;
break;
case 11:
pick = POT_FULL_HEALING;
break;
case 12:
pick = POT_POLYMORPH;
break;
case 13:
pick = POT_AMNESIA;
break;
}
} while(pick == (int)obj->ovar1);
otmp->ovar1 = (long)pick;
otmp->spe = obj->spe;
} else {
int try_limit = 3;
/* Try up to 3 times to make the magic-or-not status of
the new item be the same as it was for the old one. */
otmp = (struct obj *)0;
do {
if (otmp) delobj(otmp);
otmp = mkobj(obj->oclass, FALSE);
} while (--try_limit > 0 &&
objects[obj->otyp].oc_magic != objects[otmp->otyp].oc_magic);
}
} else {
/* literally replace obj with this new thing */
otmp = mksobj(id, MKOBJ_NOINIT);
/* Actually more things use corpsenm but they polymorph differently */
#define USES_CORPSENM(typ) ((typ)==CORPSE || (typ)==STATUE || (typ)==FIGURINE)
if (USES_CORPSENM(obj->otyp) && USES_CORPSENM(id))
otmp->corpsenm = obj->corpsenm;
#undef USES_CORPSENM
/* things that affect what otyp will be created by polymorph */
switch(obj->otyp) {
case SPE_BLANK_PAPER:
case SCR_BLANK_PAPER:
case SCR_AMNESIA:
new_otyp = rn2(2) ? SPE_BLANK_PAPER : SCR_BLANK_PAPER;
break;
#ifdef MAIL
case SCR_MAIL:
new_otyp = SCR_MAIL;
break;
#endif
case POT_WATER:
case POT_AMNESIA:
new_otyp = POT_WATER;
break;
case POT_BLOOD:
new_otyp = POT_BLOOD;
break;
case EGG:
if (obj->spe)
new_otyp = EGG;
break;
case HYPOSPRAY_AMPULE:
new_otyp = HYPOSPRAY_AMPULE;
break;
case SCR_GOLD_SCROLL_OF_LAW:
new_otyp = GOLD_PIECE;
break;
}
/* turn crocodile corpses into shoes */
if (obj->otyp == CORPSE && obj->corpsenm == PM_CROCODILE) {
new_otyp = LOW_BOOTS;
}
/* too-worn-out spellbooks turn blank */
if (obj->oclass == SPBOOK_CLASS && obj->spestudied > MAX_SPELL_STUDY) {
new_otyp = SPE_BLANK_PAPER;
}
/* preserve quantity */
otmp->quan = obj->quan;
/* preserve the shopkeepers (lack of) interest */
otmp->no_charge = obj->no_charge;
/* preserve inventory letter if in inventory */
if (obj_location == OBJ_INVENT)
otmp->invlet = obj->invlet;
/* create the new object, otmp, of the new type (or random type) */
otmp = poly_obj_core(obj, new_otyp);
/* after-creating-otmp special handling */
/* Sokoban guilt, boulder-like objects. Assumed to be the players fault. */
if (is_boulder(obj) && In_sokoban(&u.uz)) {
change_luck(-1);
}
/* 'n' merged objects may be fused into 1 object */
if (otmp->quan > 1L &&
(!objects[otmp->otyp].oc_merge || (otmp->quan > (long)rn2(1000)))) {
otmp->quan = 1L;
}
/* potions of water have their BUC randomized (and were guaranteed to turn into water) */
if (obj->otyp == POT_WATER) {
int state = rn2(3) - 1;
otmp->blessed = state > 0;
otmp->cursed = state < 0;
}
/* potions of blood get a random appropriate bloodtype (and were guaranteed to turn into blood) */
if (obj->otyp == POT_BLOOD) {
struct obj * dummy = mksobj(POT_BLOOD, NO_MKOBJ_FLAGS);
otmp->corpsenm = dummy->corpsenm;
delobj(dummy);
}
#ifdef MAIL
/* You can't send yourself 100 mail messages and then
* polymorph them into useful scrolls
*/
/* scrolls of mail have spe=1 (and were guaranteed to turn into mail) */
if (obj->otyp == SCR_MAIL) {
otmp->otyp = SCR_MAIL;
otmp->spe = 1;
}
#endif
/* avoid abusing eggs laid by you */
/* eggs laid by the player try to become other plausibly-player-laid eggs (and were guaranteed to turn into eggs) */
if (obj->otyp == EGG && obj->spe) {
int mtyp, tryct = 100;
/* first, turn into a generic egg */
if (otmp->otyp == EGG)
kill_egg(otmp);
@ -1733,6 +1686,145 @@ poly_obj(obj, id)
}
}
}
/* hypospray ampules randomize the contained potion (and were guaranteed to turn into ampules) */
if (obj->otyp == HYPOSPRAY_AMPULE) {
int hypospray_ampules[] = {POT_GAIN_ABILITY,POT_RESTORE_ABILITY,POT_BLINDNESS,POT_CONFUSION,POT_PARALYSIS,
POT_SPEED,POT_HALLUCINATION,POT_HEALING,POT_EXTRA_HEALING,POT_GAIN_ENERGY,
POT_SLEEPING,POT_FULL_HEALING,POT_POLYMORPH,POT_AMNESIA};
do {
otmp->ovar1 = (long)ROLL_FROM(hypospray_ampules);
} while(otmp->ovar1 == obj->ovar1);
otmp->spe = obj->spe;
}
/* gold scrolls of law turn a small randomize amount of gold (and were guaranteed to turn into gold pieces) */
if (obj->otyp == SCR_GOLD_SCROLL_OF_LAW) {
otmp->quan = rnd(50 * obj->quan) + 50 * obj->quan;
}
/* crocodile corpses were turned into shoes */
if (obj->otyp == CORPSE && obj->corpsenm == PM_CROCODILE) {
otmp->spe = 0;
otmp->oeroded = 0;
otmp->oerodeproof = TRUE;
otmp->cursed = FALSE;
}
/* general post-poly changes */
switch (otmp->oclass) {
case TOOL_CLASS:
if (otmp->otyp == CANDLE_OF_INVOCATION) {
otmp = poly_obj(otmp, WAX_CANDLE);
otmp->age = 400L;
}
else if (otmp->otyp == MAGIC_LAMP) {
otmp = poly_obj(otmp, OIL_LAMP);
otmp->age = 1500L; /* "best" oil lamp possible */
} else if (otmp->otyp == MAGIC_MARKER) {
otmp->recharged = 1; /* degraded quality */
}
/* don't care about the recharge count of other tools */
break;
case WAND_CLASS:
while (otmp->otyp == WAN_WISHING || otmp->otyp == WAN_POLYMORPH)
otmp = randpoly_obj(otmp);
/* altering the object tends to degrade its quality
(analogous to spellbook `read count' handling) */
if ((int)otmp->recharged < rn2(7)) /* recharge_limit */
otmp->recharged++;
break;
case POTION_CLASS:
while (otmp->otyp == POT_POLYMORPH)
otmp = randpoly_obj(otmp);
break;
case SPBOOK_CLASS:
while (otmp->otyp == SPE_POLYMORPH)
otmp = randpoly_obj(otmp);
/* reduce spellbook abuse */
if(otmp->otyp != SPE_BLANK_PAPER) {
otmp->spestudied = obj->spestudied + 1;
}
break;
case RING_CLASS:
while (otmp->otyp == RIN_WISHES)
otmp = randpoly_obj(otmp);
break;
case GEM_CLASS:
if (otmp->quan > (long)rnd(4) && obj->obj_material == MINERAL && otmp->obj_material != MINERAL) {
otmp = poly_obj(otmp, ROCK); /* transmutation backfired */
set_obj_quan(otmp, otmp->quan/2); /* some material has been lost */
}
break;
}
delobj(obj);
return otmp;
}
/*
* Polymorphs the object to the given object ID.
* If given STRANGE OBJECT, uses randpoly_obj().
*
* Returns a pointer to the new object.
*/
struct obj *
poly_obj(obj, id)
struct obj * obj;
int id;
{
struct obj * otmp;
if (id == STRANGE_OBJECT) {
impossible("poly_obj called with id=STRANGE_OBJECT?");
return randpoly_obj(obj);
}
otmp = poly_obj_core(obj, id);
delobj(obj);
return otmp;
}
/*
* the shared core of randpoly_obj and poly_obj
* does not destroy obj, caller must do so.
*/
struct obj *
poly_obj_core(obj, id)
struct obj *obj;
int id;
{
struct obj *otmp;
xchar ox, oy;
int obj_location = obj->where;
if (id == STRANGE_OBJECT) { /* preserve symbol */
int try_limit = 3;
/* Try up to 3 times to make the magic-or-not status of
the new item be the same as it was for the old one. */
otmp = (struct obj *)0;
do {
if (otmp) delobj(otmp);
otmp = mkobj(obj->oclass, FALSE);
} while (--try_limit > 0 &&
objects[obj->otyp].oc_magic != objects[otmp->otyp].oc_magic);
} else {
/* literally replace obj with this new thing */
otmp = mksobj(id, MKOBJ_NOINIT);
/* Actually more things use corpsenm but they polymorph differently */
#define USES_CORPSENM(typ) ((typ)==CORPSE || (typ)==STATUE || (typ)==FIGURINE)
if (USES_CORPSENM(obj->otyp) && USES_CORPSENM(id))
otmp->corpsenm = obj->corpsenm;
#undef USES_CORPSENM
}
/* preserve quantity, unless otmp cannot be stacked */
otmp->quan = (objects[otmp->otyp].oc_merge) ? obj->quan : 1;
/* preserve the shopkeepers (lack of) interest */
otmp->no_charge = obj->no_charge;
/* preserve inventory letter if in inventory */
if (obj_location == OBJ_INVENT)
otmp->invlet = obj->invlet;
/* keep special fields (including charges on wands) */
if (index(charged_objs, otmp->oclass)) otmp->spe = obj->spe;
@ -1757,92 +1849,9 @@ poly_obj(obj, id)
if (obj->opoisoned && is_poisonable(otmp))
otmp->opoisoned = obj->opoisoned;
if (id == STRANGE_OBJECT && obj->otyp == CORPSE) {
/* turn crocodile corpses into shoes */
if (obj->corpsenm == PM_CROCODILE) {
otmp->otyp = LOW_BOOTS;
otmp->oclass = ARMOR_CLASS;
otmp->spe = 0;
otmp->oeroded = 0;
otmp->oerodeproof = TRUE;
otmp->quan = 1L;
otmp->cursed = FALSE;
}
}
/* no box contents --KAA */
if (Has_contents(otmp)) delete_contents(otmp);
/* 'n' merged objects may be fused into 1 object */
if (otmp->quan > 1L && (!objects[otmp->otyp].oc_merge ||
(can_merge && otmp->quan > (long)rn2(1000))))
otmp->quan = 1L;
if (id == STRANGE_OBJECT && obj->otyp == SCR_GOLD_SCROLL_OF_LAW)
{
/* turn gold scrolls of law into a handful of gold pieces */
otmp->otyp = GOLD_PIECE;
otmp->oclass = COIN_CLASS;
set_material_gm(otmp, GOLD);
otmp->quan = rnd(50 * obj->quan) + 50 * obj->quan;
}
switch (otmp->oclass) {
case TOOL_CLASS:
if (otmp->otyp == CANDLE_OF_INVOCATION) {
otmp->otyp = WAX_CANDLE;
otmp->age = 400L;
}
else if (otmp->otyp == MAGIC_LAMP) {
otmp->otyp = OIL_LAMP;
otmp->age = 1500L; /* "best" oil lamp possible */
} else if (otmp->otyp == MAGIC_MARKER) {
otmp->recharged = 1; /* degraded quality */
}
/* don't care about the recharge count of other tools */
break;
case WAND_CLASS:
while (otmp->otyp == WAN_WISHING || otmp->otyp == WAN_POLYMORPH)
otmp->otyp = rnd_class(WAN_LIGHT, WAN_LIGHTNING);
/* altering the object tends to degrade its quality
(analogous to spellbook `read count' handling) */
if ((int)otmp->recharged < rn2(7)) /* recharge_limit */
otmp->recharged++;
break;
case POTION_CLASS:
while (otmp->otyp == POT_POLYMORPH)
otmp->otyp = rnd_class(POT_GAIN_ABILITY, POT_WATER);
break;
case SPBOOK_CLASS:
while (otmp->otyp == SPE_POLYMORPH)
otmp->otyp = rnd_class(SPE_DIG, SPE_BLANK_PAPER);
/* reduce spellbook abuse */
if(otmp->spestudied > MAX_SPELL_STUDY){
otmp->otyp = SPE_BLANK_PAPER;
otmp->obj_color = objects[SPE_BLANK_PAPER].oc_color;
}
else
otmp->spestudied = obj->spestudied + 1;
break;
case RING_CLASS:
while (otmp->otyp == RIN_WISHES)
otmp->otyp = rnd_class(RIN_WISHES, RIN_PROTECTION_FROM_SHAPE_CHAN);
break;
case GEM_CLASS:
if (otmp->quan > (long)rnd(4) && obj->obj_material == MINERAL && otmp->obj_material != MINERAL) {
otmp->otyp = ROCK; /* transmutation backfired */
set_material_gm(otmp, MINERAL);
otmp->quan /= 2L; /* some material has been lost */
}
break;
}
/* add focusing gems to lightsabers */
if (is_lightsaber(otmp)) {
struct obj *gem = mksobj(rn2(6) ? BLUE_FLUORITE : GREEN_FLUORITE, NO_MKOBJ_FLAGS);
@ -1859,27 +1868,27 @@ poly_obj(obj, id)
/* for now, take off worn items being polymorphed */
if (obj_location == OBJ_INVENT) {
if (id == STRANGE_OBJECT)
remove_worn_item(obj, TRUE);
remove_worn_item(obj, TRUE);
else {
/* This is called only for stone to flesh. It's a lot simpler
* than it otherwise might be. We don't need to check for
* special effects when putting them on (no meat objects have
* any) and only three worn masks are possible.
*/
otmp->owornmask = obj->owornmask;
remove_worn_item(obj, TRUE);
setworn(otmp, otmp->owornmask);
if (otmp->owornmask & LEFT_RING)
uleft = otmp;
if (otmp->owornmask & RIGHT_RING)
uright = otmp;
if (otmp->owornmask & W_WEP)
uwep = otmp;
if (otmp->owornmask & W_SWAPWEP)
uswapwep = otmp;
if (otmp->owornmask & W_QUIVER)
uquiver = otmp;
goto no_unwear;
/* This is called only for stone to flesh. It's a lot simpler
* than it otherwise might be. We don't need to check for
* special effects when putting them on (no meat objects have
* any) and only three worn masks are possible.
*/
otmp->owornmask = obj->owornmask;
remove_worn_item(obj, TRUE);
setworn(otmp, otmp->owornmask);
if (otmp->owornmask & LEFT_RING)
uleft = otmp;
if (otmp->owornmask & RIGHT_RING)
uright = otmp;
if (otmp->owornmask & W_WEP)
uwep = otmp;
if (otmp->owornmask & W_SWAPWEP)
uswapwep = otmp;
if (otmp->owornmask & W_QUIVER)
uquiver = otmp;
goto no_unwear;
}
}
else if (obj_location == OBJ_MINVENT) {
@ -1905,6 +1914,8 @@ no_unwear:
!is_boulder(otmp))
unblock_point(obj->ox, obj->oy);
/* copy OX structures */
mov_all_ox(obj, otmp);
/* ** we are now done adjusting the object ** */
@ -1944,7 +1955,6 @@ no_unwear:
} else Norep("%s is furious!", Monnam(shkp));
}
}
delobj(obj);
return otmp;
}
@ -2059,7 +2069,7 @@ struct obj *obj, *otmp;
do_osshock(obj);
break;
}
obj = poly_obj(obj, STRANGE_OBJECT);
obj = randpoly_obj(obj);;
newsym(obj->ox,obj->oy);
break;
case WAN_PROBING:
@ -2421,6 +2431,11 @@ register struct obj *obj;
incr_itimeout(&HFast, rn1(10, 100 + 60 * bcsign(obj)));
break;
default:
if(obj->otyp == SPE_FULL_HEALING){
objects[SPE_FULL_HEALING].oc_dir = IMMEDIATE;
pline("Bad full healing zap dir detected and fixed.");
break;
}
pline("Bad zapnodir item: %d", obj->otyp);
break;
}

View file

@ -861,6 +861,13 @@ monster_detail : MONSTER_ID chance ':' monster_c ',' m_name ',' coordinate '[' S
Free($6);
}
}
monster_infos
{
if (++nmons >= MAX_OF_TYPE) {
yyerror("Too many monsters in room or mazepart!");
nmons--;
}
}
| MONSTER_ID chance ':' monster_c ',' m_name ',' coordinate
{
tmpmonst[nmons] = New(monster);