Skip to content

Commit

Permalink
Hide plastic babies in slices of king cake
Browse files Browse the repository at this point in the history
Sometimes the hero will find a plastic baby inside a piece of king cake,
just like in real life.

In order to make this apply to 'real' king cake created during Mardi
Gras, and not to user-defined fruit with an identical name, change
holiday fruits to use a negative fruit ID as their spe. To enable this,
add a new macro, fruit_id() -- which provides the absolute value of
fruit->spe -- and use it in most cases the fruit ID needs to be
accessed.

Negative fruit IDs are already used when saving bones, to mark fruits
which don't exist on the current level and therefore don't need to be
included in the bones file, but those are negative fids in the g.ffruit
linked list, not negative spe on individual items.  These changes
shouldn't interfere with that process as long as the possible negative
spe is taken into consideration when saving and loading bones, which it
now should be.
  • Loading branch information
entrez committed May 12, 2022
1 parent 01b2d68 commit 0abcae9
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 8 deletions.
5 changes: 5 additions & 0 deletions include/obj.h
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,11 @@ struct obj {
#define thiefstone_ledger_valid(stone) \
((stone)->keyed_ledger > 0 && (stone)->keyed_ledger <= maxledgerno())

/* special holiday fruits are differentiated from user-defined fruits by
* negative spe */
#define is_holiday_fruit(obj) ((obj)->otyp == SLIME_MOLD && (obj)->spe < 0)
#define fruit_id(obj) (abs((obj)->spe))

/*
* Notes for adding new oextra structures:
*
Expand Down
4 changes: 2 additions & 2 deletions src/bones.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ resetobjs(struct obj *ochain, boolean restore)
}

if (otmp->otyp == SLIME_MOLD) {
goodfruit(otmp->spe);
goodfruit(fruit_id(otmp));
#ifdef MAIL_STRUCTURES
} else if (otmp->otyp == SCR_MAIL) {
/* 0: delivered in-game via external event;
Expand Down Expand Up @@ -321,7 +321,7 @@ drop_upon_death(struct monst *mtmp, /* monster if hero turned into one (other th
otmp->owt = weight(otmp);

if (otmp->otyp == SLIME_MOLD)
goodfruit(otmp->spe);
goodfruit(fruit_id(otmp));

if (rn2(5))
curse(otmp);
Expand Down
28 changes: 28 additions & 0 deletions src/eat.c
Original file line number Diff line number Diff line change
Expand Up @@ -2385,6 +2385,34 @@ fpostfx(struct obj *otmp)
if (!u.uconduct.literate++)
livelog_printf(LL_CONDUCT, "became literate by reading the fortune inside a cookie");
break;
case SLIME_MOLD:
if (is_holiday_fruit(otmp)) {
struct fruit *f = fruit_from_indx(fruit_id(otmp));
if (!rn2(15) && f && !strcmp("slice of king cake", f->fname)) {
static const int babies[] = {
PM_BABY_CROCODILE,
PM_BABY_LONG_WORM,
PM_BABY_PURPLE_WORM,
PM_BABY_GRAY_DRAGON,
PM_BABY_GOLD_DRAGON,
PM_BABY_SILVER_DRAGON,
PM_BABY_RED_DRAGON,
PM_BABY_WHITE_DRAGON,
PM_BABY_ORANGE_DRAGON,
PM_BABY_BLACK_DRAGON,
PM_BABY_BLUE_DRAGON,
PM_BABY_GREEN_DRAGON,
PM_BABY_YELLOW_DRAGON,
};
struct obj *feve = mksobj(FIGURINE, TRUE, FALSE);
set_corpsenm(feve, babies[rn2(SIZE(babies))]);
set_material(feve, PLASTIC);
There("is a plastic baby inside the slice of king cake!");
hold_another_object(feve, "It falls to the floor.",
(const char *) 0, (const char *) 0);
}
}
break;
case LUMP_OF_ROYAL_JELLY:
/* This stuff seems to be VERY healthy! */
gainstr(otmp, 1, TRUE); /* will -1 if cursed */
Expand Down
3 changes: 2 additions & 1 deletion src/mkobj.c
Original file line number Diff line number Diff line change
Expand Up @@ -990,7 +990,8 @@ mksobj(int otyp, boolean init, boolean artif)
/* fruitadd requires a modifiable string */
char foodbuf[BUFSZ];
Strcpy(foodbuf, foods[rn2(idx)]);
otmp->spe = fruitadd(foodbuf, NULL);
/* holiday fruits have negative spe */
otmp->spe = -fruitadd(foodbuf, NULL);
}
}
flags.made_fruit = TRUE;
Expand Down
2 changes: 1 addition & 1 deletion src/objnam.c
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,7 @@ xname_flags(
case FOOD_CLASS:
/* we could include partly-eaten-hack on fruit but don't need to */
if (typ == SLIME_MOLD) {
struct fruit *f = fruit_from_indx(obj->spe);
struct fruit *f = fruit_from_indx(fruit_id(obj));

if (!f) {
impossible("Bad fruit #%d?", obj->spe);
Expand Down
2 changes: 1 addition & 1 deletion src/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -7172,7 +7172,7 @@ fruitadd(char *str, struct fruit *replace_fruit)
char buf[PL_FSIZ], altname[PL_FSIZ];
boolean user_specified = (str == g.pl_fruit);
/* if not user-specified, then it's a fruit name for a fruit on
* a bones level or from orctown raider's loot...
* a bones level, a holiday food, or from orctown raider's loot...
*/

/* Note: every fruit has an id (kept in obj->spe) of at least 1;
Expand Down
11 changes: 8 additions & 3 deletions src/restore.c
Original file line number Diff line number Diff line change
Expand Up @@ -507,13 +507,18 @@ ghostfruit(register struct obj* otmp)
register struct fruit *oldf;

for (oldf = g.oldfruit; oldf; oldf = oldf->nextf)
if (oldf->fid == otmp->spe)
if (oldf->fid == fruit_id(otmp))
break;

if (!oldf)
if (!oldf) {
impossible("no old fruit?");
else
} else {
boolean holiday_food = is_holiday_fruit(otmp);
otmp->spe = fruitadd(oldf->fname, (struct fruit *) 0);
if (holiday_food) {
otmp->spe = -(otmp->spe);
}
}
}

#ifdef SYSCF
Expand Down

0 comments on commit 0abcae9

Please sign in to comment.