diff --git a/doc/fixes36.1 b/doc/fixes36.1 index ff470d323..7be6ef2e3 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -521,6 +521,7 @@ hero poly'd into vampire could drain monster down to 0 HP without killing it, fix mention_walls reporting secret doors as solid stone jumping over water unintentionally moved hero through that water, causing drowning if not able to water walk or fly +try again to fix achievement recording bug with mines and sokoban prizes Platform- and/or Interface-Specific Fixes diff --git a/include/flag.h b/include/flag.h index 5b205e5b7..3bccbaa18 100644 --- a/include/flag.h +++ b/include/flag.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 flag.h $NHDT-Date: 1505214875 2017/09/12 11:14:35 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.123 $ */ +/* NetHack 3.6 flag.h $NHDT-Date: 1508827590 2017/10/24 06:46:30 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.129 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -349,25 +349,24 @@ struct instance_flags { int wc_fontsiz_menu; /* font size for the menu window */ int wc_fontsiz_text; /* font size for text windows */ int wc_scroll_amount; /* scroll this amount at scroll_margin */ - int wc_scroll_margin; /* scroll map when this far from - the edge */ + int wc_scroll_margin; /* scroll map when this far from the edge */ int wc_map_mode; /* specify map viewing options, mostly - for backward compatibility */ + * for backward compatibility */ int wc_player_selection; /* method of choosing character */ boolean wc_splash_screen; /* display an opening splash screen or not */ boolean wc_popup_dialog; /* put queries in pop up dialogs instead of - in the message window */ + * in the message window */ boolean wc_eight_bit_input; /* allow eight bit input */ boolean wc_mouse_support; /* allow mouse support */ boolean wc2_fullscreen; /* run fullscreen */ boolean wc2_softkeyboard; /* use software keyboard */ boolean wc2_wraptext; /* wrap text */ boolean wc2_selectsaved; /* display a menu of user's saved games */ - boolean wc2_darkgray; /* try to use dark-gray color for black glyphs */ - boolean wc2_hitpointbar; /* show graphical bar representing hit points */ - boolean cmdassist; /* provide detailed assistance for some commands */ - boolean clicklook; /* allow right-clicking for look */ - boolean obsolete; /* obsolete options can point at this, it isn't used */ + boolean wc2_darkgray; /* try to use dark-gray color for black glyphs */ + boolean wc2_hitpointbar; /* show graphical bar representing hit points */ + boolean cmdassist; /* provide detailed assistance for some commands */ + boolean clicklook; /* allow right-clicking for look */ + boolean obsolete; /* obsolete options can point at this, it isn't used */ struct autopickup_exception *autopickup_exceptions[2]; #define AP_LEAVE 0 #define AP_GRAB 1 @@ -381,6 +380,11 @@ struct instance_flags { Bitfield(save_uswallow, 1); Bitfield(save_uinwater, 1); Bitfield(save_uburied, 1); + /* item types used to acomplish "special achievements"; find the target + object and you'll be flagged as having achieved something... */ + short mines_prize_type; /* luckstone */ + short soko_prize_type1; /* bag of holding or */ + short soko_prize_type2; /* amulet of reflection */ }; /* diff --git a/include/obj.h b/include/obj.h index 75b35779d..f87caaa02 100644 --- a/include/obj.h +++ b/include/obj.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 obj.h $NHDT-Date: 1456618994 2016/02/28 00:23:14 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.53 $ */ +/* NetHack 3.6 obj.h $NHDT-Date: 1508827590 2017/10/24 06:46:30 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.60 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -343,13 +343,19 @@ struct obj { && !undiscovered_artifact(ART_EYES_OF_THE_OVERWORLD))) #define pair_of(o) ((o)->otyp == LENSES || is_gloves(o) || is_boots(o)) +/* 'PRIZE' values override obj->corpsenm so prizes mustn't be object types + which use that field for monster type (or other overloaded purpose) */ +#define MINES_PRIZE 1 +#define SOKO_PRIZE1 2 +#define SOKO_PRIZE2 3 #define is_mines_prize(o) \ - ((o)->otyp == LUCKSTONE && Is_mineend_level(&u.uz)) -#define is_soko_prize(o) \ - (((o)->otyp == AMULET_OF_REFLECTION \ - || (o)->otyp == BAG_OF_HOLDING) \ - && Is_sokoend_level(&u.uz)) - + ((o)->otyp == iflags.mines_prize_type \ + && (o)->record_achieve_special == MINES_PRIZE) +#define is_soko_prize(o) \ + (((o)->otyp == iflags.soko_prize_type1 \ + && (o)->record_achieve_special == SOKO_PRIZE1) \ + || ((o)->otyp == iflags.soko_prize_type2 \ + && (o)->record_achieve_special == SOKO_PRIZE2)) /* Flags for get_obj_location(). */ #define CONTAINED_TOO 0x1 diff --git a/src/bones.c b/src/bones.c index 4d3f67138..66efd480b 100644 --- a/src/bones.c +++ b/src/bones.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 bones.c $NHDT-Date: 1503309019 2017/08/21 09:50:19 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.70 $ */ +/* NetHack 3.6 bones.c $NHDT-Date: 1508827591 2017/10/24 06:46:31 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.71 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985,1993. */ /* NetHack may be freely redistributed. See license for details. */ @@ -124,7 +124,7 @@ boolean restore; otmp->spe = 1; #endif } else if (otmp->otyp == EGG) { - otmp->spe = 0; + otmp->spe = 0; /* not "laid by you" in next game */ } else if (otmp->otyp == TIN) { /* make tins of unique monster's meat be empty */ if (otmp->corpsenm >= LOW_PM @@ -133,24 +133,30 @@ boolean restore; } else if (otmp->otyp == CORPSE || otmp->otyp == STATUE) { int mnum = otmp->corpsenm; - /* Discard incarnation details of unique - monsters (by passing null instead of otmp - for object), shopkeepers (by passing false - for revival flag), temple priests, and - vault guards in order to prevent corpse - revival or statue reanimation. */ + /* Discard incarnation details of unique monsters + (by passing null instead of otmp for object), + shopkeepers (by passing false for revival flag), + temple priests, and vault guards in order to + prevent corpse revival or statue reanimation. */ if (has_omonst(otmp) && cant_revive(&mnum, FALSE, (struct obj *) 0)) { free_omonst(otmp); - /* mnum is now either human_zombie or - doppelganger; for corpses of uniques, - we need to force the transformation - now rather than wait until a revival - attempt, otherwise eating this corpse + /* mnum is now either human_zombie or doppelganger; + for corpses of uniques, we need to force the + transformation now rather than wait until a + revival attempt, otherwise eating this corpse would behave as if it remains unique */ if (mnum == PM_DOPPELGANGER && otmp->otyp == CORPSE) set_corpsenm(otmp, mnum); } + } else if ((otmp->otyp == iflags.mines_prize_type + && !Is_mineend_level(&u.uz)) + || ((otmp->otyp == iflags.soko_prize_type1 + || otmp->otyp == iflags.soko_prize_type2) + && !Is_sokoend_level(&u.uz))) { + /* "special prize" in this game becomes ordinary object + if loaded into another game */ + otmp->record_achieve_special = NON_PM; } else if (otmp->otyp == AMULET_OF_YENDOR) { /* no longer the real Amulet */ otmp->otyp = FAKE_AMULET_OF_YENDOR; @@ -183,8 +189,8 @@ sanitize_name(namebuf) char *namebuf; { int c; - boolean strip_8th_bit = - !strcmp(windowprocs.name, "tty") && !iflags.wc_eight_bit_input; + boolean strip_8th_bit = (!strcmp(windowprocs.name, "tty") + && !iflags.wc_eight_bit_input); /* it's tempting to skip this for single-user platforms, since only the current player could have left these bones--except diff --git a/src/invent.c b/src/invent.c index 0c61b3dee..429b5a9d5 100644 --- a/src/invent.c +++ b/src/invent.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 invent.c $NHDT-Date: 1498078873 2017/06/21 21:01:13 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.214 $ */ +/* NetHack 3.6 invent.c $NHDT-Date: 1508827592 2017/10/24 06:46:32 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.220 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -504,12 +504,21 @@ struct obj *obj; } set_artifact_intrinsic(obj, 1, W_ART); } - if (is_mines_prize(obj) && obj->record_achieve_special) { + + /* "special achievements" aren't discoverable during play, they + end up being recorded in XLOGFILE at end of game, nowhere else; + record_achieve_special overloads corpsenm which is ordinarily + initialized to NON_PM (-1) rather than to 0; any special prize + must never be a corpse, egg, tin, figurine, or statue because + their use of obj->corpsenm for monster type would conflict, + nor be a leash (corpsenm overloaded for m_id of leashed + monster) or a novel (corpsenm overloaded for novel index) */ + if (is_mines_prize(obj)) { u.uachieve.mines_luckstone = 1; - obj->record_achieve_special = 0; - } else if (is_soko_prize(obj) && obj->record_achieve_special) { + obj->record_achieve_special = NON_PM; + } else if (is_soko_prize(obj)) { u.uachieve.finish_sokoban = 1; - obj->record_achieve_special = 0; + obj->record_achieve_special = NON_PM; } } diff --git a/src/options.c b/src/options.c index b281ba695..d378d2200 100644 --- a/src/options.c +++ b/src/options.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 options.c $NHDT-Date: 1507846854 2017/10/12 22:20:54 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.315 $ */ +/* NetHack 3.6 options.c $NHDT-Date: 1508827592 2017/10/24 06:46:32 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.316 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -724,6 +724,12 @@ initoptions_init() iflags.travelcc.x = iflags.travelcc.y = -1; + /* for "special achievement" tracking (see obj.h, + create_object(sp_lev.c), addinv_core1(invent.c) */ + iflags.mines_prize_type = LUCKSTONE; + iflags.soko_prize_type1 = BAG_OF_HOLDING; + iflags.soko_prize_type2 = AMULET_OF_REFLECTION; + /* assert( sizeof flags.inv_order == sizeof def_inv_order ); */ (void) memcpy((genericptr_t) flags.inv_order, (genericptr_t) def_inv_order, sizeof flags.inv_order); diff --git a/src/sp_lev.c b/src/sp_lev.c index 448907f63..78dec8ebe 100644 --- a/src/sp_lev.c +++ b/src/sp_lev.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 sp_lev.c $NHDT-Date: 1449269920 2015/12/04 22:58:40 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.77 $ */ +/* NetHack 3.6 sp_lev.c $NHDT-Date: 1508827593 2017/10/24 06:46:33 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.89 $ */ /* Copyright (c) 1989 by Jean-Christophe Collet */ /* NetHack may be freely redistributed. See license for details. */ @@ -1881,6 +1881,7 @@ struct mkroom *croom; } } else { struct obj *cobj = container_obj[container_idx - 1]; + remove_object(otmp); if (cobj) { (void) add_to_container(cobj, otmp); @@ -1941,12 +1942,32 @@ struct mkroom *croom; } } - /* Nasty hack here: try to determine if this is the Mines or Sokoban - * "prize" and then set record_achieve_special (maps to corpsenm) - * for the object. That field will later be checked to find out if - * the player obtained the prize. */ - if (is_mines_prize(otmp) || is_soko_prize(otmp)) { - otmp->record_achieve_special = 1; + if (o->id != -1) { + static const char prize_warning[] = "multiple prizes on %s level"; + static int mcount = 0, scount = 0; + + /* if this is a specific item of the right type and it is being + created on the right level, flag it as the designated item + used to detect a special achievement (to whit, reaching and + exploring the target level, although the exploration part + might be short-circuited if a monster brings object to hero) */ + if (Is_mineend_level(&u.uz)) { + if (otmp->otyp == iflags.mines_prize_type) { + otmp->record_achieve_special = MINES_PRIZE; + if (++mcount > 1) + impossible(prize_warning, "mines end"); + } + } else if (Is_sokoend_level(&u.uz)) { + if (otmp->otyp == iflags.soko_prize_type1) { + otmp->record_achieve_special = SOKO_PRIZE1; + if (++scount > 1) + impossible(prize_warning, "sokoban end"); + } else if (otmp->otyp == iflags.soko_prize_type2) { + otmp->record_achieve_special = SOKO_PRIZE2; + if (++scount > 1) + impossible(prize_warning, "sokoban end"); + } + } } stackobj(otmp);