From: PatR Date: Mon, 10 Feb 2020 08:17:54 +0000 (-0800) Subject: redo achievement tracking X-Git-Tag: NetHack-3.7.0_WIP-2020-02-14~26 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d462bdffcab75c3583792179d8db4f278bbbc4cc;p=nethack redo achievement tracking Instead of an assortment of bits, assign numeric indices to the potential achievements and keep an array of those in the order they were attained. So disclosure might show the same subset occurring differently in different games depending on the player's actions. The encoded field in xlogfile doesn't care about that and remains the same. Modifies 'struct u', so EDITLEVEL has been incremented and existing save files are invalidated. --- diff --git a/include/extern.h b/include/extern.h index 4ad7d6a59..b5e8d46e5 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 extern.h $NHDT-Date: 1580633720 2020/02/02 08:55:20 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.787 $ */ +/* NetHack 3.6 extern.h $NHDT-Date: 1581322657 2020/02/10 08:17:37 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.795 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -994,7 +994,9 @@ E void FDECL(youhiding, (BOOLEAN_P, int)); E char *FDECL(trap_predicament, (char *, int, BOOLEAN_P)); E int NDECL(doconduct); E void FDECL(show_conduct, (int)); -E int NDECL(count_uachieve); +E void FDECL(record_achievement, (XCHAR_P)); +E boolean FDECL(remove_achievement, (XCHAR_P)); +E int NDECL(count_achievements); E int NDECL(dovanquished); E void FDECL(list_vanquished, (CHAR_P, BOOLEAN_P)); E int NDECL(num_genocides); diff --git a/include/patchlevel.h b/include/patchlevel.h index f0be24851..acc3b457e 100644 --- a/include/patchlevel.h +++ b/include/patchlevel.h @@ -1,4 +1,4 @@ -/* NetHack 3.7 patchlevel.h $NHDT-Date: 1580437691 2020/01/31 02:28:11 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.155 $ */ +/* NetHack 3.7 patchlevel.h $NHDT-Date: 1581322658 2020/02/10 08:17:38 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.156 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -14,7 +14,7 @@ * Incrementing EDITLEVEL can be used to force invalidation of old bones * and save files. */ -#define EDITLEVEL 13 +#define EDITLEVEL 14 #define COPYRIGHT_BANNER_A "NetHack, Copyright 1985-2020" #define COPYRIGHT_BANNER_B \ diff --git a/include/you.h b/include/you.h index 611fcf3b1..f017f0e0c 100644 --- a/include/you.h +++ b/include/you.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 you.h $NHDT-Date: 1574648937 2019/11/25 02:28:57 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.41 $ */ +/* NetHack 3.6 you.h $NHDT-Date: 1581322658 2020/02/10 08:17:38 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.42 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2016. */ /* NetHack may be freely redistributed. See license for details. */ @@ -54,17 +54,25 @@ struct u_event { Bitfield(ascended, 1); /* has offered the Amulet */ }; -struct u_achieve { - Bitfield(amulet, 1); /* touched Amulet */ - Bitfield(bell, 1); /* touched Bell */ - Bitfield(book, 1); /* touched Book */ - Bitfield(menorah, 1); /* touched Candelabrum */ - Bitfield(enter_gehennom,1); /* entered Gehennom (or Valley) by any means */ - Bitfield(ascended, 1); /* not quite the same as u.uevent.ascended */ - Bitfield(mines_luckstone, 1); /* got a luckstone at end of mines */ - Bitfield(finish_sokoban, 1); /* obtained the sokoban prize */ - - Bitfield(killed_medusa, 1); +/* numerical order of these matters because they've been encoded in a + bitmask in xlogfile; reordering would break decoding that; during play + the number doesn't matter--they're recorded in the order achieved */ +enum achivements { + ACH_BELL = 1, /* acquired Bell of Opening */ + ACH_HELL = 2, /* entered Gehennom */ + ACH_CNDL = 3, /* acquired Candelabrum of Invocation */ + ACH_BOOK = 4, /* acquired Book of the Dead */ + ACH_INVK = 5, /* performed invocation to gain access to Sanctum */ + ACH_AMUL = 6, /* acuired The Amulet */ + ACH_ENDG = 7, /* entered end game */ + ACH_ASTR = 8, /* entered Astral Plane */ + ACH_UWIN = 9, /* ascended */ + ACH_LUCK = 10, /* acquired Mines' End luckstone */ + ACH_SOKO = 11, /* acquired Sokoban bag of holding or amu of reflection */ + ACH_MEDU = 12, /* killed Medusa */ + ACH_BLND = 13, /* hero was always blond, no, blind */ + ACH_NUDE = 14, /* hero never wore armor */ + N_ACH }; struct u_realtime { @@ -346,7 +354,6 @@ struct you { /* 1 free bit! */ unsigned udg_cnt; /* how long you have been demigod */ - struct u_achieve uachieve; /* achievements */ struct u_event uevent; /* certain events have happened */ struct u_have uhave; /* you're carrying special objects */ struct u_conduct uconduct; /* KMH, conduct */ @@ -399,7 +406,7 @@ struct you { struct skills weapon_skills[P_NUM_SKILLS]; boolean twoweap; /* KMH -- Using two-weapon combat */ short mcham; /* vampire mndx if shapeshifted to bat/cloud */ - + xchar uachieved[N_ACH]; /* list of achievements in the order attained */ }; /* end of `struct you' */ #define Upolyd (u.umonnum != u.umonster) diff --git a/src/cmd.c b/src/cmd.c index 4264e1e28..94d5e245b 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 cmd.c $NHDT-Date: 1579914040 2020/01/25 01:00:40 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.394 $ */ +/* NetHack 3.6 cmd.c $NHDT-Date: 1581322659 2020/02/10 08:17:39 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.398 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */ /* NetHack may be freely redistributed. See license for details. */ @@ -792,16 +792,12 @@ boolean pre, wiztower; static const char Unachieve[] = "%s achievement revoked."; if (Is_mineend_level(&u.uz)) { - if (u.uachieve.mines_luckstone) { + if (remove_achievement(ACH_LUCK)) pline(Unachieve, "Mine's end"); - u.uachieve.mines_luckstone = 0; - } g.context.achieveo.mines_prize_oid = 0; } else if (Is_sokoend_level(&u.uz)) { - if (u.uachieve.finish_sokoban) { + if (remove_achievement(ACH_SOKO)) pline(Unachieve, "Sokoban end"); - u.uachieve.finish_sokoban = 0; - } g.context.achieveo.soko_prize_oid = 0; } } diff --git a/src/do.c b/src/do.c index 2a58939f2..70d51f8da 100644 --- a/src/do.c +++ b/src/do.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 do.c $NHDT-Date: 1580608377 2020/02/02 01:52:57 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.222 $ */ +/* NetHack 3.6 do.c $NHDT-Date: 1581322660 2020/02/10 08:17:40 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.224 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1039,8 +1039,7 @@ dodown() pline("Unspeakable cruelty and harm lurk down there."); if (yn("Are you sure you want to enter?") != 'y') return 0; - else - pline("So be it."); + pline("So be it."); u.uevent.gehennom_entered = 1; /* don't ask again */ } @@ -1642,7 +1641,8 @@ boolean at_stairs, falling, portal; You_hear("groans and moans everywhere."); } else pline("It is hot here. You smell smoke..."); - u.uachieve.enter_gehennom = 1; + + record_achievement(ACH_HELL); /* reached Gehennom */ } /* in case we've managed to bypass the Valley's stairway down */ if (Inhell && !Is_valley(&u.uz)) @@ -1677,10 +1677,14 @@ boolean at_stairs, falling, portal; /* special location arrival messages/events */ if (In_endgame(&u.uz)) { - if (new &&on_level(&u.uz, &astral_level)) + if (newdungeon) + record_achievement(ACH_ENDG); /* reached endgame */ + if (new && on_level(&u.uz, &astral_level)) { final_level(); /* guardian angel,&c */ - else if (newdungeon && u.uhave.amulet) + record_achievement(ACH_ASTR); /* reached Astral level */ + } else if (newdungeon && u.uhave.amulet) { resurrect(); /* force confrontation with Wizard */ + } } else if (In_quest(&u.uz)) { onquest(); /* might be reaching locate|goal level */ } else if (In_V_tower(&u.uz)) { diff --git a/src/end.c b/src/end.c index f10e0f424..cc328e6eb 100644 --- a/src/end.c +++ b/src/end.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 end.c $NHDT-Date: 1575245059 2019/12/02 00:04:19 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.181 $ */ +/* NetHack 3.6 end.c $NHDT-Date: 1581322661 2020/02/10 08:17:41 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.206 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -812,7 +812,7 @@ boolean taken; if (!done_stopprint) { if (should_query_disclose_option('c', &defquery)) { - int acnt = count_uachieve(); + int acnt = count_achievements(); Sprintf(qbuf, "Do you want to see your conduct%s%s?", (acnt > 0) ? " and achievement" : "", @@ -1222,6 +1222,17 @@ int how; iflags.at_night = night(); iflags.at_midnight = midnight(); + /* final achievement tracking; only show blind and nudist if some + tangible progress has been made; always show ascension last */ + if (u.uachieved[0] || !flags.beginner) { + if (u.uroleplay.blind) + record_achievement(ACH_BLND); /* blind the whole game */ + if (u.uroleplay.nudist) + record_achievement(ACH_NUDE); /* never wore armor */ + } + if (how == ASCENDED) + record_achievement(ACH_UWIN); + dump_open_log(endtime); /* Sometimes you die on the first move. Life's not fair. * On those rare occasions you get hosed immediately, go out @@ -1592,6 +1603,7 @@ int how; * score list?" */ if (have_windows && !iflags.toptenwin) exit_nhwindows((char *) 0), have_windows = FALSE; + /* update 'logfile' and 'xlogfile', if enabled, and maybe 'record' */ topten(how, endtime); if (have_windows) exit_nhwindows((char *) 0); diff --git a/src/insight.c b/src/insight.c index 62ee93607..153f4df07 100644 --- a/src/insight.c +++ b/src/insight.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 insight.c $NHDT-Date: 1580577249 2020/02/01 17:14:09 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.0 $ */ +/* NetHack 3.7 insight.c $NHDT-Date: 1581322662 2020/02/10 08:17:42 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1698,51 +1698,17 @@ int final; g.en_win = WIN_ERR; } -/* uses to decide whether there are any achievements to display */ -int -count_uachieve() -{ - int acnt = 0; - - /* these tests must be kept in sync with show_achievements() */ - if (u.uroleplay.blind) - ++acnt; - if (u.uroleplay.nudist) - ++acnt; - if (u.uachieve.mines_luckstone) - ++acnt; - if (u.uachieve.finish_sokoban) - ++acnt; - if (u.uachieve.killed_medusa) - ++acnt; - if (u.uachieve.bell) - ++acnt; - if (u.uachieve.enter_gehennom) - ++acnt; - if (u.uachieve.menorah) - ++acnt; - if (u.uachieve.book) - ++acnt; - if (u.uevent.invoked) - ++acnt; - if (u.uachieve.amulet) - ++acnt; - if (In_endgame(&u.uz)) - ++acnt; - if (Is_astralevel(&u.uz)) - ++acnt; - if (u.uachieve.ascended) - ++acnt; - - return acnt; -} +/* + * Achievements (see 'enum achievements' in you.h). + */ static void show_achievements(final) -int final; +int final; /* used "behind the curtain" by enl_foo() macros */ { - int acnt; + int i, achidx, acnt; char title[BUFSZ]; + boolean ach_amulet = FALSE; winid awin = WIN_ERR; /* unfortunately we can't show the achievements (at least not all of @@ -1754,7 +1720,7 @@ int final; /* first, figure whether any achievements have been accomplished so that we don't show the header for them if the resulting list below it would be empty */ - if ((acnt = count_uachieve()) == 0) + if ((acnt = count_achievements()) == 0) return; if (g.en_win != WIN_ERR) { @@ -1765,67 +1731,105 @@ int final; } Sprintf(title, "Achievement%s:", plur(acnt)); putstr(awin, 0, title); - /* after 'blind' and 'nudist', which are the easiest if you die but - the hardest if you ascend, they're arranged in approximate order - of difficulty */ - if (u.uroleplay.blind) - enl_msg(You_, "are exploring", "explored", - " without being able to see", ""); - if (u.uroleplay.nudist) - enl_msg(You_, "have gone", "went", " without any armor", ""); - - if (u.uachieve.mines_luckstone) - enl_msg(You_, "have ", "", "completed the Gnomish Mines", ""); - if (u.uachieve.finish_sokoban) - enl_msg(You_, "have ", "", "completed Sokoban", ""); - if (u.uachieve.killed_medusa) - enl_msg(You_, "have ", "", "defeated Medusa", ""); - if (u.uachieve.bell) { - /* alternate phrasing for present vs past and also for possessing - the item vs once held it */ - enl_msg(You_, - u.uhave.bell ? "have" : "have handled", - u.uhave.bell ? "had" : "handled", - " the Bell of Opening", ""); - } - /* wording is clumsy but the game is inconsistent about "entering - Gehennom"; the Valley is part of Gehennom but the message about - entering Gehennom is given when descending from the Valley to the - level below and that's also when the flag about entering gets set */ - if (u.uachieve.enter_gehennom) - enl_msg(You_, "have ", "", "passed the Valley of the Dead", ""); - if (u.uachieve.menorah) { - enl_msg(You_, - u.uhave.menorah ? "have" : "have handled", - u.uhave.menorah ? "had" : "handled", - " the Candelabrum of Invocation", ""); - } - if (u.uachieve.book) { - enl_msg(You_, - u.uhave.book ? "have" : "have handled", - u.uhave.book ? "had" : "handled", - " the Book of the Dead", ""); - } - if (u.uevent.invoked) - enl_msg(You_, "have ", "", "gained access to Moloch's Sanctum", ""); - if (u.uachieve.amulet) { - /* extra alternate wording for past tense because ascension - requires giving up the Amulet */ - enl_msg(You_, - u.uhave.amulet ? "have" : "have obtained", - u.uachieve.ascended ? "delivered" - : u.uhave.amulet ? "had" : "had obtained", - " the Amulet of Yendor", ""); - } - - /* reaching Astral makes feedback about reaching the Planes be redundant - and asceding makes both be redundant, but we display all that apply */ - if (In_endgame(&u.uz)) - enl_msg(You_, "have ", "", "reached the Elemental Planes", ""); - if (Is_astralevel(&u.uz)) - enl_msg(You_, "have ", "", "reached the Astral Plane", ""); - if (u.uachieve.ascended) - enlght_out(" You ascended!"); + + /* display achievements in the order in which they were recorded; + lone exception is to defer the Amulet (by taking it out of list) + if we just ascended; it warrants alternate wording when given + away during ascension, but the Amulet achievement is always + attained before entering endgame and the alternate wording looks + strange if shown before "reached endgame" and "reached Astral" */ + if (remove_achievement(ACH_UWIN)) { /* UWIN == Ascended! */ + ach_amulet = remove_achievement(ACH_AMUL); + record_achievement(ACH_UWIN); /* put back; always last when present */ + acnt = count_achievements(); + } + for (i = 0; i < acnt; ++i) { + achidx = u.uachieved[i]; + + switch (achidx) { + case ACH_BLND: + enl_msg(You_, "are exploring", "explored", + " without being able to see", ""); + break; + case ACH_NUDE: + enl_msg(You_, "have gone", "went", " without any armor", ""); + break; + case ACH_LUCK: + enl_msg(You_, "have ", "", "completed the Gnomish Mines", ""); + break; + case ACH_SOKO: + enl_msg(You_, "have ", "", "completed Sokoban", ""); + break; + case ACH_MEDU: + enl_msg(You_, "have ", "", "defeated Medusa", ""); + break; + case ACH_BELL: + /* alternate phrasing for present vs past and also for + possessing the item vs once held it */ + enl_msg(You_, + u.uhave.bell ? "have" : "have handled", + u.uhave.bell ? "had" : "handled", + " the Bell of Opening", ""); + break; + case ACH_HELL: + enl_msg(You_, "have ", "", "entered Gehennom", ""); + break; + case ACH_CNDL: + enl_msg(You_, + u.uhave.menorah ? "have" : "have handled", + u.uhave.menorah ? "had" : "handled", + " the Candelabrum of Invocation", ""); + break; + case ACH_BOOK: + enl_msg(You_, + u.uhave.book ? "have" : "have handled", + u.uhave.book ? "had" : "handled", + " the Book of the Dead", ""); + break; + case ACH_INVK: + enl_msg(You_, "have ", "", + "gained access to Moloch's Sanctum", ""); + break; + case ACH_AMUL: + /* note: we won't get here if ACH_UWIN is going to be shown */ + enl_msg(You_, + u.uhave.amulet ? "have" : "have obtained", + u.uhave.amulet ? "had" : "had obtained", + " the Amulet of Yendor", ""); + break; + + /* reaching Astral makes feedback about reaching the Planes + be redundant and ascending makes both be redundant, but + we display all that apply */ + case ACH_ENDG: + enl_msg(You_, "have ", "", "reached the Elemental Planes", ""); + break; + case ACH_ASTR: + enl_msg(You_, "have ", "", "reached the Astral Plane", ""); + break; + case ACH_UWIN: + /* if we took Amulet achievement out of the list, show it now; + always uses past tense here since game ends upon ascension */ + if (ach_amulet) + enl_msg(You_, "?", "delivered", " the Amulet of Yendor", ""); + /* the ultimate achievement... */ + enlght_out(" You ascended!"); + break; + default: + /* title[] has served its purpose, reuse it as a scratch buffer */ + Sprintf(title, " [Unexpected achievement #%d.]", achidx); + enlght_out(title); + break; + } /* switch */ + } /* for */ +#ifdef XLOGFILE + /* if we removed the Amulet achievement because of ascension, put it + back for encoding in the achievements field of xlogfile; it will + change position from the original ordering but that doesn't matter + to the bitmask which is going to be constructed and logged */ + if (ach_amulet) + record_achievement(ACH_AMUL); +#endif if (awin != g.en_win) { display_nhwindow(awin, TRUE); @@ -1833,6 +1837,65 @@ int final; } } +/* record an achievement (add at end of list unless already present) */ +void +record_achievement(achidx) +xchar achidx; +{ + int i; + + /* valid achievements range from 1 to N_ACH-1 */ + if (achidx < 1 || achidx >= N_ACH) { + impossible("Achievement #%d is out of range.", achidx); + return; + } + + /* the list has an extra slot so there is always at least one 0 at + its end (more than one unless all N_ACH-1 possible achievements + have been recorded); find first empty slot or achievement #achidx; + an attempt to duplicate an achievement can happen if any of Bell, + Candelabrum, Book, or Amulet is dropped then picked up again */ + for (i = 0; u.uachieved[i]; ++i) + if (u.uachieved[i] == achidx) + return; /* already recorded, don't duplicate it */ + u.uachieved[i] = achidx; + return; +} + +/* discard a recorded achievement; return True if removed, False otherwise */ +boolean +remove_achievement(achidx) +xchar achidx; +{ + int i; + + for (i = 0; u.uachieved[i]; ++i) + if (u.uachieved[i] == achidx) + break; /* stop when found */ + if (!u.uachieved[i]) /* not found */ + return FALSE; + /* list is 0 terminated so any beyond the removed one move up a slot */ + do { + u.uachieved[i] = u.uachieved[i + 1]; + } while (u.uachieved[++i]); + return TRUE; +} + +/* used to decide whether there are any achievements to display */ +int +count_achievements() +{ + int i, acnt = 0; + + for (i = 0; u.uachieved[i]; ++i) + ++acnt; + return acnt; +} + +/* + * Vanquished monsters. + */ + static const char *vanqorders[NUM_VANQ_ORDER_MODES] = { "traditional: by monster level, by internal monster index", "by monster toughness, by internal monster index", diff --git a/src/invent.c b/src/invent.c index 084cd472e..51568945e 100644 --- a/src/invent.c +++ b/src/invent.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 invent.c $NHDT-Date: 1580476196 2020/01/31 13:09:56 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.288 $ */ +/* NetHack 3.7 invent.c $NHDT-Date: 1581322662 2020/02/10 08:17:42 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.290 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -810,22 +810,22 @@ struct obj *obj; if (u.uhave.amulet) impossible("already have amulet?"); u.uhave.amulet = 1; - u.uachieve.amulet = 1; + record_achievement(ACH_AMUL); } else if (obj->otyp == CANDELABRUM_OF_INVOCATION) { if (u.uhave.menorah) impossible("already have candelabrum?"); u.uhave.menorah = 1; - u.uachieve.menorah = 1; + record_achievement(ACH_CNDL); } else if (obj->otyp == BELL_OF_OPENING) { if (u.uhave.bell) impossible("already have silver bell?"); u.uhave.bell = 1; - u.uachieve.bell = 1; + record_achievement(ACH_BELL); } else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) { if (u.uhave.book) impossible("already have the book?"); u.uhave.book = 1; - u.uachieve.book = 1; + record_achievement(ACH_BOOK); } else if (obj->oartifact) { if (is_quest_artifact(obj)) { if (u.uhave.questart) @@ -839,12 +839,12 @@ struct obj *obj; /* "special achievements"; revealed in end of game disclosure and dumplog, originally just recorded in XLOGFILE */ if (is_mines_prize(obj)) { - u.uachieve.mines_luckstone = 1; - g.context.achieveo.mines_prize_oid = 0; + record_achievement(ACH_LUCK); + g.context.achieveo.mines_prize_oid = 0; /* done with luckstone o_id */ obj->nomerge = 0; } else if (is_soko_prize(obj)) { - u.uachieve.finish_sokoban = 1; - g.context.achieveo.soko_prize_oid = 0; + record_achievement(ACH_SOKO); + g.context.achieveo.soko_prize_oid = 0; /* done with bag/amulet o_id */ obj->nomerge = 0; } } diff --git a/src/mon.c b/src/mon.c index e2d571f5e..d528a911c 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mon.c $NHDT-Date: 1580044343 2020/01/26 13:12:23 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.320 $ */ +/* NetHack 3.6 mon.c $NHDT-Date: 1581322664 2020/02/10 08:17:44 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.321 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2065,7 +2065,7 @@ register struct monst *mtmp; if (mtmp->data->msound == MS_NEMESIS) nemdead(); if (mtmp->data == &mons[PM_MEDUSA]) - u.uachieve.killed_medusa = 1; + record_achievement(ACH_MEDU); if (glyph_is_invisible(levl[mtmp->mx][mtmp->my].glyph)) unmap_object(mtmp->mx, mtmp->my); m_detach(mtmp, mptr); diff --git a/src/pray.c b/src/pray.c index 3d4045141..b098311d4 100644 --- a/src/pray.c +++ b/src/pray.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 pray.c $NHDT-Date: 1579401997 2020/01/19 02:46:37 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.139 $ */ +/* NetHack 3.6 pray.c $NHDT-Date: 1581322665 2020/02/10 08:17:45 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.140 $ */ /* Copyright (c) Benson I. Margulies, Mike Stephenson, Steve Linhart, 1989. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1516,7 +1516,6 @@ dosacrifice() /* The final Test. Did you win? */ if (uamul == otmp) Amulet_off(); - u.uevent.ascended = 1; if (carried(otmp)) useup(otmp); /* well, it's gone now */ else @@ -1552,8 +1551,8 @@ dosacrifice() pline(cloud_of_smoke, hcolor(NH_ORANGE)); done(ESCAPED); } else { /* super big win */ + u.uevent.ascended = 1; adjalign(10); - u.uachieve.ascended = 1; pline( "An invisible choir sings, and you are bathed in radiance..."); godvoice(altaralign, "Mortal, thou hast done well!"); @@ -1564,6 +1563,7 @@ dosacrifice() flags.female ? "dess" : ""); done(ASCENDED); } + /*NOTREACHED*/ } } /* real Amulet */ diff --git a/src/spell.c b/src/spell.c index 4b5e03594..11718e3c0 100644 --- a/src/spell.c +++ b/src/spell.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 spell.c $NHDT-Date: 1546565814 2019/01/04 01:36:54 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.88 $ */ +/* NetHack 3.6 spell.c $NHDT-Date: 1581322667 2020/02/10 08:17:47 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.102 $ */ /* Copyright (c) M. Stephenson 1988 */ /* NetHack may be freely redistributed. See license for details. */ @@ -259,6 +259,7 @@ struct obj *book2; /* successful invocation */ mkinvokearea(); u.uevent.invoked = 1; + record_achievement(ACH_INVK); /* in case you haven't killed the Wizard yet, behave as if you just did */ u.uevent.udemigod = 1; /* wizdead() */ diff --git a/src/topten.c b/src/topten.c index b2c163d69..1581cd4dc 100644 --- a/src/topten.c +++ b/src/topten.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 topten.c $NHDT-Date: 1579914041 2020/01/25 01:00:41 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.62 $ */ +/* NetHack 3.6 topten.c $NHDT-Date: 1581322668 2020/02/10 08:17:48 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.64 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -428,6 +428,7 @@ encodeconduct() static long encodeachieve() { + int i, ilimit; long r = 0L; /* @@ -469,34 +470,9 @@ encodeachieve() * the dungeon overview but both of those things go away as soon as * the program exits. */ - if (u.uachieve.bell) - r |= 1L << 0; - if (u.uachieve.enter_gehennom) - r |= 1L << 1; - if (u.uachieve.menorah) - r |= 1L << 2; - if (u.uachieve.book) - r |= 1L << 3; - if (u.uevent.invoked) - r |= 1L << 4; - if (u.uachieve.amulet) - r |= 1L << 5; - if (In_endgame(&u.uz)) - r |= 1L << 6; - if (Is_astralevel(&u.uz)) - r |= 1L << 7; - if (u.uachieve.ascended) - r |= 1L << 8; - if (u.uachieve.mines_luckstone) - r |= 1L << 9; - if (u.uachieve.finish_sokoban) - r |= 1L << 10; - if (u.uachieve.killed_medusa) - r |= 1L << 11; - if (u.uroleplay.blind) - r |= 1L << 12; - if (u.uroleplay.nudist) - r |= 1L << 13; + ilimit = min(N_ACH, 32 - 1); /* 32: portable limit for 'long' */ + for (i = 0; i < ilimit && u.uachieved[i]; ++i) + r |= 1L << (u.uachieved[i] - 1); return r; }