From 8dfe963652d69a82187ba1eaa3c8287f2753b033 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Wed, 23 Jun 2021 22:42:29 +0300 Subject: [PATCH] Allow spiders to spin webs Revisited this feature, and the chance of a spider spinning a web depends now on the number of webs already present on the level. For a giant spider to spin a web in the middle of a room with no supports, the limit of existing webs is 4, next to one support 9, next to two supports 14, and so on. Cave spider limits are much lower. --- doc/fixes37.0 | 1 + include/extern.h | 1 + src/monmove.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ src/trap.c | 16 ++++++++++++++ 4 files changed, 74 insertions(+) diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 233ef8426..c00799c40 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -1049,6 +1049,7 @@ monsters can see and remember hero resistances monsters can gain resistances by eating corpses menu for what-is command supports /^ and /" to view a list of nearby or whole level visible and remembered traps +spiders will occasionally spin webs when moving around Platform- and/or Interface-Specific New Features diff --git a/include/extern.h b/include/extern.h index 4c9e3138f..43ba4d2a1 100644 --- a/include/extern.h +++ b/include/extern.h @@ -2641,6 +2641,7 @@ extern boolean chest_trap(struct obj *, int, boolean); extern void deltrap(struct trap *); extern boolean delfloortrap(struct trap *); extern struct trap *t_at(int, int); +extern int count_traps(int); extern void b_trapped(const char *, int); extern boolean unconscious(void); extern void blow_up_landmine(struct trap *); diff --git a/src/monmove.c b/src/monmove.c index 7c9069820..f7cf941ad 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -12,6 +12,8 @@ static int disturb(struct monst *); static void release_hero(struct monst *); static void distfleeck(struct monst *, int *, int *, int *); static int m_arrival(struct monst *); +static boolean holds_up_web(xchar, xchar); +static int count_webbing_walls(xchar, xchar); static boolean m_balks_at_approaching(struct monst *); static boolean stuff_prevents_passage(struct monst *); static int vamp_shift(struct monst *, struct permonst *, boolean); @@ -857,6 +859,58 @@ m_balks_at_approaching(struct monst* mtmp) return FALSE; } +static boolean +holds_up_web(xchar x, xchar y) +{ + stairway *sway; + + if (!isok(x, y) + || IS_ROCK(levl[x][y].typ) + || ((levl[x][y].typ == STAIRS + || levl[x][y].typ == LADDER) + && (sway = stairway_at(x,y)) != 0 + && sway->up) + || levl[x][y].typ == IRONBARS) + return TRUE; + + return FALSE; +} + +/* returns the number of walls in the four cardinal directions that could + hold up a web */ +static int +count_webbing_walls(xchar x, xchar y) +{ + return (holds_up_web(x, y - 1) + holds_up_web(x + 1, y) + + holds_up_web(x, y + 1) + holds_up_web(x - 1, y)); +} + +/* monster might spin a web */ +static void +maybe_spin_web(struct monst *mtmp) +{ + if (webmaker(mtmp->data) && !mtmp->mspec_used + && !t_at(mtmp->mx, mtmp->my)) { + struct trap *trap; + int prob = (((mtmp->data == &mons[PM_GIANT_SPIDER]) ? 15 : 5) + * (count_webbing_walls(mtmp->mx, mtmp->my) + 1)) + - (3 * count_traps(WEB)); + + if (rn2(1000) < prob + && (trap = maketrap(mtmp->mx, mtmp->my, WEB)) != 0) { + mtmp->mspec_used = d(4, 4); /* 4..16 */ + if (cansee(mtmp->mx, mtmp->my)) { + char mbuf[BUFSZ]; + + Strcpy(mbuf, + canspotmon(mtmp) ? y_monnam(mtmp) : something); + pline("%s spins a web.", upstart(mbuf)); + trap->tseen = 1; + } + } + } +} + /* Return values: * 0: did not move, but can still attack and do other stuff. * 1: moved, possibly can attack. @@ -1553,6 +1607,8 @@ m_move(register struct monst* mtmp, register int after) } } + maybe_spin_web(mtmp); + if (hides_under(ptr) || ptr->mlet == S_EEL) { /* Always set--or reset--mundetected if it's already hidden (just in case the object it was hiding under went away); diff --git a/src/trap.c b/src/trap.c index c4e56225d..236092d2d 100644 --- a/src/trap.c +++ b/src/trap.c @@ -5399,6 +5399,22 @@ t_at(register int x, register int y) return (struct trap *) 0; } +/* return number of traps of type ttyp on this level */ +int +count_traps(int ttyp) +{ + int ret = 0; + struct trap *trap = g.ftrap; + + while (trap) { + if (trap->ttyp == ttyp) + ret++; + trap = trap->ntrap; + } + + return ret; +} + void deltrap(register struct trap* trap) {