Merge branch 'dopush' of https://github.com/argrath/NetHack into NetHack-3.7
This commit is contained in:
162
src/hack.c
162
src/hack.c
@@ -9,6 +9,8 @@
|
|||||||
/* #define DEBUG */ /* uncomment for debugging */
|
/* #define DEBUG */ /* uncomment for debugging */
|
||||||
|
|
||||||
staticfn boolean could_move_onto_boulder(coordxy, coordxy);
|
staticfn boolean could_move_onto_boulder(coordxy, coordxy);
|
||||||
|
staticfn void dopush(coordxy, coordxy, coordxy, coordxy, struct obj *,
|
||||||
|
boolean);
|
||||||
staticfn void cannot_push_msg(struct obj *, coordxy, coordxy);
|
staticfn void cannot_push_msg(struct obj *, coordxy, coordxy);
|
||||||
staticfn int cannot_push(struct obj *, coordxy, coordxy);
|
staticfn int cannot_push(struct obj *, coordxy, coordxy);
|
||||||
staticfn void moverock_done(coordxy, coordxy);
|
staticfn void moverock_done(coordxy, coordxy);
|
||||||
@@ -157,6 +159,87 @@ could_move_onto_boulder(coordxy sx, coordxy sy)
|
|||||||
return squeezeablylightinvent();
|
return squeezeablylightinvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
staticfn void
|
||||||
|
dopush(
|
||||||
|
coordxy sx,
|
||||||
|
coordxy sy,
|
||||||
|
coordxy rx,
|
||||||
|
coordxy ry,
|
||||||
|
struct obj *otmp,
|
||||||
|
boolean costly)
|
||||||
|
{
|
||||||
|
struct monst *shkp;
|
||||||
|
|
||||||
|
{
|
||||||
|
const char *what;
|
||||||
|
boolean givemesg, easypush;
|
||||||
|
/* give boulder pushing feedback if this is a different
|
||||||
|
boulder than the last one pushed or if it's been at
|
||||||
|
least 2 turns since we last pushed this boulder;
|
||||||
|
unlike with Norep(), intervening messages don't cause
|
||||||
|
it to repeat, only doing something else in the meantime */
|
||||||
|
if (otmp->o_id != gb.bldrpush_oid) {
|
||||||
|
gb.bldrpushtime = svm.moves + 1L;
|
||||||
|
gb.bldrpush_oid = otmp->o_id;
|
||||||
|
}
|
||||||
|
givemesg = (svm.moves > gb.bldrpushtime + 2L
|
||||||
|
|| svm.moves < gb.bldrpushtime);
|
||||||
|
what = givemesg ? the(xname(otmp)) : 0;
|
||||||
|
if (!u.usteed) {
|
||||||
|
easypush = throws_rocks(gy.youmonst.data);
|
||||||
|
if (givemesg)
|
||||||
|
pline("With %s effort you move %s.",
|
||||||
|
easypush ? "little" : "great", what);
|
||||||
|
if (!easypush)
|
||||||
|
exercise(A_STR, TRUE);
|
||||||
|
} else {
|
||||||
|
if (givemesg)
|
||||||
|
pline("%s moves %s.", YMonnam(u.usteed), what);
|
||||||
|
}
|
||||||
|
gb.bldrpushtime = svm.moves;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move the boulder *after* the message. */
|
||||||
|
if (glyph_is_invisible(levl[rx][ry].glyph))
|
||||||
|
unmap_object(rx, ry);
|
||||||
|
otmp->next_boulder = 0;
|
||||||
|
movobj(otmp, rx, ry); /* does newsym(rx,ry) */
|
||||||
|
if (Blind) {
|
||||||
|
feel_location(rx, ry);
|
||||||
|
feel_location(sx, sy);
|
||||||
|
} else {
|
||||||
|
newsym(sx, sy);
|
||||||
|
}
|
||||||
|
/* maybe adjust bill if boulder was pushed across shop boundary;
|
||||||
|
normally otmp->unpaid would not apply because otmp isn't in
|
||||||
|
hero's inventory, but addtobill() sets it and subfrombill()
|
||||||
|
clears it */
|
||||||
|
if (costly && !costly_spot(rx, ry)) {
|
||||||
|
/* pushing from inside shop to its boundary (or free spot) */
|
||||||
|
addtobill(otmp, FALSE, FALSE, FALSE);
|
||||||
|
} else if (!costly && costly_spot(rx, ry) && otmp->unpaid
|
||||||
|
&& ((shkp = shop_keeper(*in_rooms(rx, ry, SHOPBASE)))
|
||||||
|
!= 0)
|
||||||
|
&& onshopbill(otmp, shkp, TRUE)) {
|
||||||
|
/* this can happen if hero pushes boulder from farther inside
|
||||||
|
shop into shop's free spot (which will add it to the bill),
|
||||||
|
then teleports or Passes_walls to doorway (without exiting
|
||||||
|
the shop), and then pushes the boulder from the free spot
|
||||||
|
back into the shop; it's contingent upon the shopkeeper not
|
||||||
|
"muttering an incantation" to fracture the boulder while it
|
||||||
|
is unpaid at the free spot */
|
||||||
|
subfrombill(otmp, shkp);
|
||||||
|
} else if (otmp->unpaid
|
||||||
|
&& (shkp = find_objowner(otmp, sx, sy)) != 0
|
||||||
|
&& !strchr(in_rooms(rx, ry, SHOPBASE),
|
||||||
|
ESHK(shkp)->shoproom)) {
|
||||||
|
/* once the boulder is fully out of the shop, so that it's
|
||||||
|
* impossible to change your mind and push it back in without
|
||||||
|
* leaving and triggering Kops, switch it to stolen_value */
|
||||||
|
stolen_value(otmp, sx, sy, TRUE, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
staticfn void
|
staticfn void
|
||||||
cannot_push_msg(struct obj *otmp, coordxy sx, coordxy sy)
|
cannot_push_msg(struct obj *otmp, coordxy sx, coordxy sy)
|
||||||
{
|
{
|
||||||
@@ -252,8 +335,7 @@ moverock_core(coordxy sx, coordxy sy)
|
|||||||
coordxy rx, ry;
|
coordxy rx, ry;
|
||||||
struct obj *otmp;
|
struct obj *otmp;
|
||||||
struct trap *ttmp;
|
struct trap *ttmp;
|
||||||
struct monst *mtmp, *shkp;
|
struct monst *mtmp;
|
||||||
const char *what;
|
|
||||||
boolean costly, firstboulder = TRUE;
|
boolean costly, firstboulder = TRUE;
|
||||||
|
|
||||||
while ((otmp = sobj_at(BOULDER, sx, sy)) != 0) {
|
while ((otmp = sobj_at(BOULDER, sx, sy)) != 0) {
|
||||||
@@ -472,8 +554,10 @@ moverock_core(coordxy sx, coordxy sy)
|
|||||||
that if in single-level branch (Knox) or in endgame */
|
that if in single-level branch (Knox) or in endgame */
|
||||||
newlev = random_teleport_level();
|
newlev = random_teleport_level();
|
||||||
/* if trap doesn't work, skip "disappears" message */
|
/* if trap doesn't work, skip "disappears" message */
|
||||||
if (newlev == depth(&u.uz))
|
if (newlev == depth(&u.uz)) {
|
||||||
goto dopush;
|
dopush(sx, sy, rx, ry, otmp, costly);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
/*FALLTHRU*/
|
/*FALLTHRU*/
|
||||||
case TELEP_TRAP:
|
case TELEP_TRAP:
|
||||||
if (u.usteed)
|
if (u.usteed)
|
||||||
@@ -513,75 +597,7 @@ moverock_core(coordxy sx, coordxy sy)
|
|||||||
remove_object(otmp);
|
remove_object(otmp);
|
||||||
place_object(otmp, otmp->ox, otmp->oy);
|
place_object(otmp, otmp->ox, otmp->oy);
|
||||||
}
|
}
|
||||||
|
dopush(sx, sy, rx, ry, otmp, costly);
|
||||||
{
|
|
||||||
boolean givemesg, easypush;
|
|
||||||
dopush:
|
|
||||||
/* give boulder pushing feedback if this is a different
|
|
||||||
boulder than the last one pushed or if it's been at
|
|
||||||
least 2 turns since we last pushed this boulder;
|
|
||||||
unlike with Norep(), intervening messages don't cause
|
|
||||||
it to repeat, only doing something else in the meantime */
|
|
||||||
if (otmp->o_id != gb.bldrpush_oid) {
|
|
||||||
gb.bldrpushtime = svm.moves + 1L;
|
|
||||||
gb.bldrpush_oid = otmp->o_id;
|
|
||||||
}
|
|
||||||
givemesg = (svm.moves > gb.bldrpushtime + 2L
|
|
||||||
|| svm.moves < gb.bldrpushtime);
|
|
||||||
what = givemesg ? the(xname(otmp)) : 0;
|
|
||||||
if (!u.usteed) {
|
|
||||||
easypush = throws_rocks(gy.youmonst.data);
|
|
||||||
if (givemesg)
|
|
||||||
pline("With %s effort you move %s.",
|
|
||||||
easypush ? "little" : "great", what);
|
|
||||||
if (!easypush)
|
|
||||||
exercise(A_STR, TRUE);
|
|
||||||
} else {
|
|
||||||
if (givemesg)
|
|
||||||
pline("%s moves %s.", YMonnam(u.usteed), what);
|
|
||||||
}
|
|
||||||
gb.bldrpushtime = svm.moves;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Move the boulder *after* the message. */
|
|
||||||
if (glyph_is_invisible(levl[rx][ry].glyph))
|
|
||||||
unmap_object(rx, ry);
|
|
||||||
otmp->next_boulder = 0;
|
|
||||||
movobj(otmp, rx, ry); /* does newsym(rx,ry) */
|
|
||||||
if (Blind) {
|
|
||||||
feel_location(rx, ry);
|
|
||||||
feel_location(sx, sy);
|
|
||||||
} else {
|
|
||||||
newsym(sx, sy);
|
|
||||||
}
|
|
||||||
/* maybe adjust bill if boulder was pushed across shop boundary;
|
|
||||||
normally otmp->unpaid would not apply because otmp isn't in
|
|
||||||
hero's inventory, but addtobill() sets it and subfrombill()
|
|
||||||
clears it */
|
|
||||||
if (costly && !costly_spot(rx, ry)) {
|
|
||||||
/* pushing from inside shop to its boundary (or free spot) */
|
|
||||||
addtobill(otmp, FALSE, FALSE, FALSE);
|
|
||||||
} else if (!costly && costly_spot(rx, ry) && otmp->unpaid
|
|
||||||
&& ((shkp = shop_keeper(*in_rooms(rx, ry, SHOPBASE)))
|
|
||||||
!= 0)
|
|
||||||
&& onshopbill(otmp, shkp, TRUE)) {
|
|
||||||
/* this can happen if hero pushes boulder from farther inside
|
|
||||||
shop into shop's free spot (which will add it to the bill),
|
|
||||||
then teleports or Passes_walls to doorway (without exiting
|
|
||||||
the shop), and then pushes the boulder from the free spot
|
|
||||||
back into the shop; it's contingent upon the shopkeeper not
|
|
||||||
"muttering an incantation" to fracture the boulder while it
|
|
||||||
is unpaid at the free spot */
|
|
||||||
subfrombill(otmp, shkp);
|
|
||||||
} else if (otmp->unpaid
|
|
||||||
&& (shkp = find_objowner(otmp, sx, sy)) != 0
|
|
||||||
&& !strchr(in_rooms(rx, ry, SHOPBASE),
|
|
||||||
ESHK(shkp)->shoproom)) {
|
|
||||||
/* once the boulder is fully out of the shop, so that it's
|
|
||||||
* impossible to change your mind and push it back in without
|
|
||||||
* leaving and triggering Kops, switch it to stolen_value */
|
|
||||||
stolen_value(otmp, sx, sy, TRUE, FALSE);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
cannot_push_msg(otmp, sx, sy);
|
cannot_push_msg(otmp, sx, sy);
|
||||||
return cannot_push(otmp, sx, sy);
|
return cannot_push(otmp, sx, sy);
|
||||||
|
|||||||
Reference in New Issue
Block a user