track eight more achievements
Record reaching experience level 3, 6, 10, 14, 18, 22, 26, and 30, the levels where the character gets a new rank title, and report those as achievements at end of game. These achievements persist even if enough levels to lose a rank are lost, and if lost ranks are regained the original achievement is the one that gets tracked and disclosed.
This commit is contained in:
25
src/botl.c
25
src/botl.c
@@ -270,18 +270,37 @@ int
|
||||
xlev_to_rank(xlev)
|
||||
int xlev;
|
||||
{
|
||||
/*
|
||||
* 1..2 => 0
|
||||
* 3..5 => 1
|
||||
* 6..9 => 2
|
||||
* 10..13 => 3
|
||||
* ...
|
||||
* 26..29 => 7
|
||||
* 30 => 8
|
||||
* Conversion is precise but only partially reversible.
|
||||
*/
|
||||
return (xlev <= 2) ? 0 : (xlev <= 30) ? ((xlev + 2) / 4) : 8;
|
||||
}
|
||||
|
||||
#if 0 /* not currently needed */
|
||||
/* convert rank index (0..8) to experience level (1..30) */
|
||||
int
|
||||
rank_to_xlev(rank)
|
||||
int rank;
|
||||
{
|
||||
return (rank <= 0) ? 1 : (rank <= 8) ? ((rank * 4) - 2) : 30;
|
||||
/*
|
||||
* 0 => 1..2
|
||||
* 1 => 3..5
|
||||
* 2 => 6..9
|
||||
* 3 => 10..13
|
||||
* ...
|
||||
* 7 => 26..29
|
||||
* 8 => 30
|
||||
* We return the low end of each range.
|
||||
*/
|
||||
return (rank < 1) ? 1 : (rank < 2) ? 3
|
||||
: (rank < 8) ? ((rank * 4) - 2) : 30;
|
||||
}
|
||||
#endif
|
||||
|
||||
const char *
|
||||
rank_of(lev, monnum, female)
|
||||
|
||||
@@ -299,9 +299,12 @@ boolean incr; /* true iff via incremental experience growth */
|
||||
|
||||
/* increase level (unless already maxxed) */
|
||||
if (u.ulevel < MAXULEV) {
|
||||
int newrank, oldrank = xlev_to_rank(u.ulevel);
|
||||
|
||||
/* increase experience points to reflect new level */
|
||||
if (incr) {
|
||||
long tmp = newuexp(u.ulevel + 1);
|
||||
|
||||
if (u.uexp >= tmp)
|
||||
u.uexp = tmp - 1;
|
||||
} else {
|
||||
@@ -314,6 +317,9 @@ boolean incr; /* true iff via incremental experience growth */
|
||||
if (u.ulevelmax < u.ulevel)
|
||||
u.ulevelmax = u.ulevel;
|
||||
adjabil(u.ulevel - 1, u.ulevel); /* give new intrinsics */
|
||||
newrank = xlev_to_rank(u.ulevel);
|
||||
if (newrank > oldrank)
|
||||
record_achievement(achieve_rank(newrank));
|
||||
}
|
||||
g.context.botl = TRUE;
|
||||
}
|
||||
|
||||
@@ -1882,8 +1882,8 @@ static void
|
||||
show_achievements(final)
|
||||
int final; /* used "behind the curtain" by enl_foo() macros */
|
||||
{
|
||||
int i, achidx, acnt;
|
||||
char title[BUFSZ];
|
||||
int i, achidx, absidx, acnt;
|
||||
char title[QBUFSZ], buf[QBUFSZ];
|
||||
winid awin = WIN_ERR;
|
||||
|
||||
/* unfortunately we can't show the achievements (at least not all of
|
||||
@@ -1922,8 +1922,9 @@ int final; /* used "behind the curtain" by enl_foo() macros */
|
||||
}
|
||||
for (i = 0; i < acnt; ++i) {
|
||||
achidx = u.uachieved[i];
|
||||
absidx = abs(achidx);
|
||||
|
||||
switch (achidx) {
|
||||
switch (absidx) {
|
||||
case ACH_BLND:
|
||||
enl_msg(You_, "are exploring", "explored",
|
||||
" without being able to see", "");
|
||||
@@ -2013,10 +2014,19 @@ int final; /* used "behind the curtain" by enl_foo() macros */
|
||||
/* the ultimate achievement... */
|
||||
enlght_out(" You ascended!");
|
||||
break;
|
||||
|
||||
/* rank 0 is the starting condition, not an achievement; 8 is Xp 30 */
|
||||
case ACH_RNK1: case ACH_RNK2: case ACH_RNK3: case ACH_RNK4:
|
||||
case ACH_RNK5: case ACH_RNK6: case ACH_RNK7: case ACH_RNK8:
|
||||
Sprintf(buf, "attained the rank of %s",
|
||||
rank_of(rank_to_xlev(absidx - (ACH_RNK1 - 1)),
|
||||
Role_switch, (achidx < 0) ? TRUE : FALSE));
|
||||
you_have_X(buf);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* title[] has served its purpose, reuse it as a scratch buffer */
|
||||
Sprintf(title, " [Unexpected achievement #%d.]", achidx);
|
||||
enlght_out(title);
|
||||
Sprintf(buf, " [Unexpected achievement #%d.]", achidx);
|
||||
enlght_out(buf);
|
||||
break;
|
||||
} /* switch */
|
||||
} /* for */
|
||||
@@ -2030,12 +2040,15 @@ int final; /* used "behind the curtain" by enl_foo() macros */
|
||||
/* record an achievement (add at end of list unless already present) */
|
||||
void
|
||||
record_achievement(achidx)
|
||||
xchar achidx;
|
||||
schar achidx;
|
||||
{
|
||||
int i;
|
||||
int i, absidx;
|
||||
|
||||
/* valid achievements range from 1 to N_ACH-1 */
|
||||
if (achidx < 1 || achidx >= N_ACH) {
|
||||
absidx = abs(achidx);
|
||||
/* valid achievements range from 1 to N_ACH-1; however, ranks can be
|
||||
stored as the complement (ie, negative) to track gender */
|
||||
if ((achidx < 1 && (absidx < ACH_RNK1 || absidx > ACH_RNK8))
|
||||
|| achidx >= N_ACH) {
|
||||
impossible("Achievement #%d is out of range.", achidx);
|
||||
return;
|
||||
}
|
||||
@@ -2046,7 +2059,7 @@ xchar 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)
|
||||
if (abs(u.uachieved[i]) == abs(achidx))
|
||||
return; /* already recorded, don't duplicate it */
|
||||
u.uachieved[i] = achidx;
|
||||
return;
|
||||
@@ -2055,12 +2068,12 @@ xchar achidx;
|
||||
/* discard a recorded achievement; return True if removed, False otherwise */
|
||||
boolean
|
||||
remove_achievement(achidx)
|
||||
xchar achidx;
|
||||
schar achidx;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; u.uachieved[i]; ++i)
|
||||
if (u.uachieved[i] == achidx)
|
||||
if (abs(u.uachieved[i]) == abs(achidx))
|
||||
break; /* stop when found */
|
||||
if (!u.uachieved[i]) /* not found */
|
||||
return FALSE;
|
||||
@@ -2082,6 +2095,19 @@ count_achievements()
|
||||
return acnt;
|
||||
}
|
||||
|
||||
/* convert a rank index to an achievement number; encode it when female
|
||||
in order to subsequently report gender-specific ranks accurately */
|
||||
schar
|
||||
achieve_rank(rank)
|
||||
int rank; /* 1..8 */
|
||||
{
|
||||
schar achidx = (schar) ((rank - 1) + ACH_RNK1);
|
||||
|
||||
if (flags.female)
|
||||
achidx = -achidx;
|
||||
return achidx;
|
||||
}
|
||||
|
||||
/*
|
||||
* Vanquished monsters.
|
||||
*/
|
||||
|
||||
19
src/topten.c
19
src/topten.c
@@ -474,13 +474,16 @@ boolean condition;
|
||||
static char *
|
||||
encode_extended_achievements()
|
||||
{
|
||||
static char buf[N_ACH*40];
|
||||
static char buf[N_ACH * 40];
|
||||
char rnkbuf[40];
|
||||
const char *achievement = NULL;
|
||||
int i;
|
||||
int i, achidx, absidx;
|
||||
|
||||
buf[0] = '\0';
|
||||
for (i = 0; u.uachieved[i]; i++) {
|
||||
switch (u.uachieved[i]) {
|
||||
achidx = u.uachieved[i];
|
||||
absidx = abs(achidx);
|
||||
switch (absidx) {
|
||||
case ACH_UWIN:
|
||||
achievement = "ascended";
|
||||
break;
|
||||
@@ -517,7 +520,6 @@ encode_extended_achievements()
|
||||
case ACH_SOKO_PRIZE:
|
||||
achievement = "obtained_the_sokoban_prize";
|
||||
break;
|
||||
|
||||
case ACH_ORCL:
|
||||
achievement = "consulted_the_oracle";
|
||||
break;
|
||||
@@ -542,6 +544,15 @@ encode_extended_achievements()
|
||||
case ACH_BGRM:
|
||||
achievement = "entered_bigroom";
|
||||
break;
|
||||
/* rank 0 is the starting condition, not an achievement; 8 is Xp 30 */
|
||||
case ACH_RNK1: case ACH_RNK2: case ACH_RNK3: case ACH_RNK4:
|
||||
case ACH_RNK5: case ACH_RNK6: case ACH_RNK7: case ACH_RNK8:
|
||||
Sprintf(rnkbuf, "attained_the_rank_of_%s",
|
||||
rank_of(rank_to_xlev(absidx - (ACH_RNK1 - 1)),
|
||||
Role_switch, (achidx < 0) ? TRUE : FALSE));
|
||||
strNsubst(rnkbuf, " ", "_", 0); /* replace every ' ' with '_' */
|
||||
achievement = lcase(rnkbuf);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user