Merge branch 'NetHack-3.6'

This commit is contained in:
nhmall
2019-05-18 16:30:43 -04:00
9 changed files with 220 additions and 96 deletions
+8 -1
View File
@@ -1,4 +1,4 @@
$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.3 $ $NHDT-Date: 1558045586 2019/05/16 22:26:26 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.5 $ $NHDT-Date: 1558171542 2019/05/18 09:25:42 $
This fixes36.3 file is here to capture information about updates in the 3.6.x This fixes36.3 file is here to capture information about updates in the 3.6.x
lineage following the release of 3.6.2 in May 2019. Please note, however, lineage following the release of 3.6.2 in May 2019. Please note, however,
@@ -19,6 +19,7 @@ glob pricing did not consider weight properly
Fixes to Post-3.6.2 Problems that Were Exposed Via git Repository Fixes to Post-3.6.2 Problems that Were Exposed Via git Repository
------------------------------------------------------------------ ------------------------------------------------------------------
glob shop interaction improved to handle more of the expected scenarios
Platform- and/or Interface-Specific Fixes or Features Platform- and/or Interface-Specific Fixes or Features
@@ -26,6 +27,12 @@ Platform- and/or Interface-Specific Fixes or Features
curses: very tall menus tried to use selector characters a-z, A-Z, and 0-9, curses: very tall menus tried to use selector characters a-z, A-Z, and 0-9,
but 0-9 should be reserved for counts and if the display was tall but 0-9 should be reserved for counts and if the display was tall
enough for more than 62 entries, arbitrary ASCII punctuation got used enough for more than 62 entries, arbitrary ASCII punctuation got used
curses: when all available lines in the message window are in use,
autodescribe feedback for 'pick a position with cursor' overwrote
the last line (usually the 'pick a position' prompt/hint), sometimes
leaving part of longer underlying line's text visible
curses: if message window is only one line, cancelling some prompts with ESC
left the prompts visible on the message line instead of erasing them
Windows: some startup error messages were not being delivered successfully Windows: some startup error messages were not being delivered successfully
+7 -5
View File
@@ -3569,11 +3569,7 @@ register struct obj *otmp, *obj;
if (obj->oclass == COIN_CLASS) if (obj->oclass == COIN_CLASS)
return TRUE; return TRUE;
if (obj->unpaid != otmp->unpaid || obj->spe != otmp->spe if (obj->bypass != otmp->bypass)
|| obj->cursed != otmp->cursed || obj->blessed != otmp->blessed
|| obj->no_charge != otmp->no_charge || obj->obroken != otmp->obroken
|| obj->otrapped != otmp->otrapped || obj->lamplit != otmp->lamplit
|| obj->bypass != otmp->bypass)
return FALSE; return FALSE;
if (obj->globby) if (obj->globby)
@@ -3582,6 +3578,12 @@ register struct obj *otmp, *obj;
* or don't inhibit their merger. * or don't inhibit their merger.
*/ */
if (obj->unpaid != otmp->unpaid || obj->spe != otmp->spe
|| obj->cursed != otmp->cursed || obj->blessed != otmp->blessed
|| obj->no_charge != otmp->no_charge || obj->obroken != otmp->obroken
|| obj->otrapped != otmp->otrapped || obj->lamplit != otmp->lamplit)
return FALSE;
if (obj->oclass == FOOD_CLASS if (obj->oclass == FOOD_CLASS
&& (obj->oeaten != otmp->oeaten || obj->orotten != otmp->orotten)) && (obj->oeaten != otmp->oeaten || obj->orotten != otmp->orotten))
return FALSE; return FALSE;
+44 -12
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 mkobj.c $NHDT-Date: 1557526914 2019/05/10 22:21:54 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.144 $ */ /* NetHack 3.6 mkobj.c $NHDT-Date: 1558124913 2019/05/17 20:28:33 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.147 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Derek S. Ray, 2015. */ /*-Copyright (c) Derek S. Ray, 2015. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -18,6 +18,7 @@ STATIC_DCL const char *FDECL(where_name, (struct obj *));
STATIC_DCL void FDECL(insane_object, (struct obj *, const char *, STATIC_DCL void FDECL(insane_object, (struct obj *, const char *,
const char *, struct monst *)); const char *, struct monst *));
STATIC_DCL void FDECL(check_contained, (struct obj *, const char *)); STATIC_DCL void FDECL(check_contained, (struct obj *, const char *));
STATIC_DCL void FDECL(check_glob, (struct obj *, const char *));
STATIC_DCL void FDECL(sanity_check_worn, (struct obj *)); STATIC_DCL void FDECL(sanity_check_worn, (struct obj *));
struct icp { struct icp {
@@ -2352,6 +2353,8 @@ const char *mesg;
} }
break; break;
} }
if (obj->globby)
check_glob(obj, mesg);
} }
} }
} }
@@ -2366,7 +2369,8 @@ const char *mesg;
struct obj *obj, *mwep; struct obj *obj, *mwep;
for (mon = monlist; mon; mon = mon->nmon) { for (mon = monlist; mon; mon = mon->nmon) {
if (DEADMONSTER(mon)) continue; if (DEADMONSTER(mon))
continue;
mwep = MON_WEP(mon); mwep = MON_WEP(mon);
if (mwep) { if (mwep) {
if (!mcarried(mwep)) if (!mcarried(mwep))
@@ -2379,6 +2383,8 @@ const char *mesg;
insane_object(obj, mfmt1, mesg, mon); insane_object(obj, mfmt1, mesg, mon);
if (obj->ocarry != mon) if (obj->ocarry != mon)
insane_object(obj, mfmt2, mesg, mon); insane_object(obj, mfmt2, mesg, mon);
if (obj->globby)
check_glob(obj, mesg);
check_contained(obj, mesg); check_contained(obj, mesg);
} }
} }
@@ -2429,7 +2435,8 @@ struct monst *mon;
impossible(altfmt, mesg, fmt_ptr((genericptr_t) obj), where_name(obj), impossible(altfmt, mesg, fmt_ptr((genericptr_t) obj), where_name(obj),
objnm, fmt_ptr((genericptr_t) mon), monnm); objnm, fmt_ptr((genericptr_t) mon), monnm);
} else { } else {
impossible(fmt, mesg, fmt_ptr((genericptr_t) obj), where_name(obj), objnm); impossible(fmt, mesg, fmt_ptr((genericptr_t) obj), where_name(obj),
objnm);
} }
} }
@@ -2461,6 +2468,8 @@ const char *mesg;
fmt_ptr((genericptr_t) obj), fmt_ptr((genericptr_t) obj),
fmt_ptr((genericptr_t) obj->ocontainer), fmt_ptr((genericptr_t) obj->ocontainer),
fmt_ptr((genericptr_t) container)); fmt_ptr((genericptr_t) container));
if (obj->globby)
check_glob(obj, mesg);
if (Has_contents(obj)) { if (Has_contents(obj)) {
/* catch most likely indirect cycle; we won't notice if /* catch most likely indirect cycle; we won't notice if
@@ -2472,14 +2481,36 @@ const char *mesg;
and "nested contained..." to "nested nested contained..." */ and "nested contained..." to "nested nested contained..." */
Strcpy(nestedmesg, "nested "); Strcpy(nestedmesg, "nested ");
copynchars(eos(nestedmesg), mesg, (int) sizeof nestedmesg copynchars(eos(nestedmesg), mesg, (int) sizeof nestedmesg
- (int) strlen(nestedmesg) - (int) strlen(nestedmesg) - 1);
- 1);
/* recursively check contents */ /* recursively check contents */
check_contained(obj, nestedmesg); check_contained(obj, nestedmesg);
} }
} }
} }
/* called when 'obj->globby' is set so we don't recheck it here */
STATIC_OVL void
check_glob(obj, mesg)
struct obj *obj;
const char *mesg;
{
#define LOWEST_GLOB GLOB_OF_GRAY_OOZE
#define HIGHEST_GLOB GLOB_OF_BLACK_PUDDING
if (obj->quan != 1L || obj->owt == 0
|| obj->otyp < LOWEST_GLOB || obj->otyp > HIGHEST_GLOB
/* a partially eaten glob could have any non-zero weight but an
intact one should weigh an exact multiple of base weight (20) */
|| ((obj->owt % objects[obj->otyp].oc_weight) != 0 && !obj->oeaten)) {
char mesgbuf[BUFSZ], globbuf[QBUFSZ];
Sprintf(globbuf, " glob %d,quan=%ld,owt=%u ",
obj->otyp, obj->quan, obj->owt);
mesg = strsubst(strcpy(mesgbuf, mesg), " obj ", globbuf);
insane_object(obj, ofmt0, mesg,
(obj->where == OBJ_MINVENT) ? obj->ocarry : 0);
}
}
/* check an object in hero's or monster's inventory which has worn mask set */ /* check an object in hero's or monster's inventory which has worn mask set */
STATIC_OVL void STATIC_OVL void
sanity_check_worn(obj) sanity_check_worn(obj)
@@ -2755,10 +2786,7 @@ struct obj **obj1, **obj2;
otmp1 = *obj1; otmp1 = *obj1;
otmp2 = *obj2; otmp2 = *obj2;
if (otmp1 && otmp2 && otmp1 != otmp2) { if (otmp1 && otmp2 && otmp1 != otmp2) {
if (otmp1->unpaid || otmp2->unpaid) globby_bill_fixup(otmp1, otmp2);
globby_bill_fixup(otmp1, otmp2);
else if (costly_spot(otmp1->ox, otmp1->oy))
globby_donation(otmp1, otmp2);
if (otmp1->bknown != otmp2->bknown) if (otmp1->bknown != otmp2->bknown)
otmp1->bknown = otmp2->bknown = 0; otmp1->bknown = otmp2->bknown = 0;
if (otmp1->rknown != otmp2->rknown) if (otmp1->rknown != otmp2->rknown)
@@ -2792,7 +2820,10 @@ struct obj **obj1, **obj2;
} }
/* /*
* Causes the heavier object to absorb the lighter object; * Causes the heavier object to absorb the lighter object in
* most cases, but if one object is OBJ_FREE and the other is
* on the floor, the floor object goes first.
*
* wrapper for obj_absorb so that floor_effects works more * wrapper for obj_absorb so that floor_effects works more
* cleanly (since we don't know which we want to stay around) * cleanly (since we don't know which we want to stay around)
*/ */
@@ -2806,8 +2837,9 @@ struct obj **obj1, **obj2;
otmp1 = *obj1; otmp1 = *obj1;
otmp2 = *obj2; otmp2 = *obj2;
if (otmp1 && otmp2 && otmp1 != otmp2) { if (otmp1 && otmp2 && otmp1 != otmp2) {
if (otmp1->owt > otmp2->owt if (!(otmp2->where == OBJ_FLOOR && otmp1->where == OBJ_FREE) &&
|| (otmp1->owt == otmp2->owt && rn2(2))) { (otmp1->owt > otmp2->owt
|| (otmp1->owt == otmp2->owt && rn2(2)))) {
return obj_absorb(obj1, obj2); return obj_absorb(obj1, obj2);
} }
return obj_absorb(obj2, obj1); return obj_absorb(obj2, obj1);
+14 -12
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 objnam.c $NHDT-Date: 1551138256 2019/02/25 23:44:16 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.235 $ */ /* NetHack 3.6 objnam.c $NHDT-Date: 1558125504 2019/05/17 20:38:24 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.239 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2011. */ /*-Copyright (c) Robert Patrick Rankin, 2011. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -905,7 +905,7 @@ unsigned doname_flags;
vague_quan = (doname_flags & DONAME_VAGUE_QUAN) != 0; vague_quan = (doname_flags & DONAME_VAGUE_QUAN) != 0;
boolean known, dknown, cknown, bknown, lknown; boolean known, dknown, cknown, bknown, lknown;
int omndx = obj->corpsenm; int omndx = obj->corpsenm;
char prefix[PREFIX]; char prefix[PREFIX], globbuf[QBUFSZ];
char tmpbuf[PREFIX + 1]; /* for when we have to add something at char tmpbuf[PREFIX + 1]; /* for when we have to add something at
the start of prefix instead of the the start of prefix instead of the
end (Strcat is used on the end) */ end (Strcat is used on the end) */
@@ -1203,26 +1203,27 @@ unsigned doname_flags;
} }
} }
/* treat 'restoring' like suppress_price because shopkeeper and /* treat 'restoring' like suppress_price because shopkeeper and
bill might not be available yet while restore is in progress */ bill might not be available yet while restore is in progress
(objects won't normally be formatted during that time, but if
'perm_invent' is enabled then they might be) */
if (iflags.suppress_price || g.restoring) { if (iflags.suppress_price || g.restoring) {
; /* don't attempt to obtain any stop pricing, even if 'with_price' */ ; /* don't attempt to obtain any stop pricing, even if 'with_price' */
} else if (is_unpaid(obj)) { /* in inventory or in container in invent */ } else if (is_unpaid(obj)) { /* in inventory or in container in invent */
long quotedprice = unpaid_cost(obj, TRUE); long quotedprice = unpaid_cost(obj, TRUE);
Sprintf(eos(bp), " (%s, %ld %s)", Sprintf(eos(bp), " (%s, %s%ld %s)",
obj->unpaid ? "unpaid" : "contents", obj->unpaid ? "unpaid" : "contents",
quotedprice, currency(quotedprice)); globwt(obj, globbuf), quotedprice, currency(quotedprice));
} else if (with_price) { /* on floor or in container on floor */ } else if (with_price) { /* on floor or in container on floor */
int nochrg = 0; int nochrg = 0;
long price = get_cost_of_shop_item(obj, &nochrg); long price = get_cost_of_shop_item(obj, &nochrg);
char globbuf[BUFSZ];
if (price > 0L) if (price > 0L)
Sprintf(eos(bp), " (%s, %s%ld %s)", Sprintf(eos(bp), " (%s, %s%ld %s)",
nochrg ? "contents" : "for sale", nochrg ? "contents" : "for sale",
globwt(obj, globbuf), price, currency(price)); globwt(obj, globbuf), price, currency(price));
else if (nochrg > 0) else if (nochrg > 0)
Strcat(bp, " (no charge)"); Sprintf(eos(bp), " (%sno charge)", globwt(obj, globbuf));
} }
if (!strncmp(prefix, "a ", 2)) { if (!strncmp(prefix, "a ", 2)) {
/* save current prefix, without "a "; might be empty */ /* save current prefix, without "a "; might be empty */
@@ -1236,7 +1237,8 @@ unsigned doname_flags;
/* show weight for items (debug tourist info) /* show weight for items (debug tourist info)
* aum is stolen from Crawl's "Arbitrary Unit of Measure" */ * aum is stolen from Crawl's "Arbitrary Unit of Measure" */
if (wizard && iflags.wizweight) { if (wizard && iflags.wizweight) {
Sprintf(eos(bp), " (%d aum)", obj->owt); if (!obj->globby) /* aum already apparent for globs */
Sprintf(eos(bp), " (%d aum)", obj->owt);
} }
bp = strprepend(bp, prefix); bp = strprepend(bp, prefix);
return bp; return bp;
@@ -4202,11 +4204,11 @@ globwt(otmp, buf)
struct obj *otmp; struct obj *otmp;
char *buf; char *buf;
{ {
if (otmp && buf && otmp->globby && otmp->quan == 1L) { *buf = '\0';
Sprintf(buf, "%d aum, ", (int) otmp->owt); if (otmp->globby) {
return buf; Sprintf(buf, "%u aum, ", otmp->owt);
} }
return ""; return buf;
} }
/*objnam.c*/ /*objnam.c*/
+98 -54
View File
@@ -4788,91 +4788,108 @@ sasc_bug(struct obj *op, unsigned x)
#endif #endif
/* /*
* When one glob is absorbed by another glob, the two become * The caller is about to make obj_absorbed go away.
* indistinguishable and the remaining glob grows in mass,
* the product of both.
* *
* The original billed item is lost to the absorption and the * There's no way for you (or a shopkeeper) to prevent globs
* original billed amount for the object being absorbed gets * from merging with each other on the floor due to the
* added to the cost owing for the absorber, and the separate * inherent nature of globs so it irretrievably becomes part
* cost for the absorbed object goes away. * of the floor glob mass. When one glob is absorbed by another
* glob, the two become indistinguishable and the remaining
* glob object grows in mass, the product of both.
*
* billing admin, player compensation, shopkeeper compensation
* all need to be considered.
*
* Any original billed item is lost to the absorption so the
* original billed amount for the object being absorbed must
* get added to the cost owing for the absorber, and the
* separate cost for the object being absorbed goes away.
*
* There are four scenarios to deal with:
* 1. shop_owned glob merging into shop_owned glob
* 2. player_owned glob merging into shop_owned glob
* 3. shop_owned glob merging into player_owned glob
* 4. player_owned glob merging into player_owned glob
*/ */
void void
globby_bill_fixup(obj_absorber, obj_absorbed) globby_bill_fixup(obj_absorber, obj_absorbed)
struct obj *obj_absorber, *obj_absorbed; struct obj *obj_absorber, *obj_absorbed;
{ {
int x, y;
struct bill_x *bp, *bp_absorber = (struct bill_x *) 0; struct bill_x *bp, *bp_absorber = (struct bill_x *) 0;
struct monst *shkp = 0; struct monst *shkp = 0;
struct eshk *eshkp;
long amount, per_unit_cost = set_cost(obj_absorbed, shkp);
boolean floor_absorber = (obj_absorber->where == OBJ_FLOOR);
if (!obj_absorber->globby) if (!obj_absorber->globby)
impossible("globby_bill_fixup called for non-globby object"); impossible("globby_bill_fixup called for non-globby object");
if (floor_absorber) {
x = obj_absorber->ox, y = obj_absorber->oy;
}
if (obj_absorber->unpaid) { if (obj_absorber->unpaid) {
/* look for a shopkeeper who owns this object */ /* look for a shopkeeper who owns this object */
for (shkp = next_shkp(fmon, TRUE); shkp; for (shkp = next_shkp(fmon, TRUE); shkp;
shkp = next_shkp(shkp->nmon, TRUE)) shkp = next_shkp(shkp->nmon, TRUE))
if (onbill(obj_absorber, shkp, TRUE)) if (onbill(obj_absorber, shkp, TRUE))
break; break;
} else if (obj_absorbed->unpaid) {
if (obj_absorbed->where == OBJ_FREE
&& floor_absorber && costly_spot(x, y)) {
shkp = shop_keeper(*in_rooms(x, y, SHOPBASE));
}
} }
/* sanity check, in case obj is on bill but not marked 'unpaid' */ /* sanity check, in case obj is on bill but not marked 'unpaid' */
if (!shkp) if (!shkp)
shkp = shop_keeper(*u.ushops); shkp = shop_keeper(*u.ushops);
if (!shkp)
return;
bp_absorber = onbill(obj_absorber, shkp, FALSE);
bp = onbill(obj_absorbed, shkp, FALSE);
eshkp = ESHK(shkp);
if ((bp_absorber = onbill(obj_absorber, shkp, FALSE)) != 0) { /**************************************************************
bp = onbill(obj_absorbed, shkp, FALSE); * Scenario 1. Shop-owned glob absorbing into shop-owned glob
if (bp) { **************************************************************/
bp_absorber->price += bp->price; if (bp && (!obj_absorber->no_charge
ESHK(shkp)->billct--; || billable(&shkp, obj_absorber, eshkp->shoproom, FALSE))) {
/* the glob being absorbed has a billing record */
amount = bp->price;
eshkp->billct--;
#ifdef DUMB #ifdef DUMB
{ {
/* DRS/NS 2.2.6 messes up -- Peter Kendell */ /* DRS/NS 2.2.6 messes up -- Peter Kendell */
int indx = ESHK(shkp)->billct; int indx = eshkp->billct;
*bp = ESHK(shkp)->bill_p[indx]; *bp = eshkp->bill_p[indx];
}
#else
*bp = ESHK(shkp)->bill_p[ESHK(shkp)->billct];
#endif
clear_unpaid_obj(shkp, obj_absorbed);
} else {
/* should never happen */
bp_absorber->price += get_cost(obj_absorbed, shkp)
* get_pricing_units(obj_absorbed);
} }
#else
*bp = eshkp->bill_p[eshkp->billct];
#endif
clear_unpaid_obj(shkp, obj_absorbed);
if (bp_absorber) {
/* the absorber has a billing record */
bp_absorber->price += amount;
} else {
/* the absorber has no billing record */
;
}
return;
} }
} /**************************************************************
* Scenario 2. Player-owned glob absorbing into shop-owned glob
/* **************************************************************/
* The caller is about to make obj_absorbed go away. if (!bp_absorber && !bp && !obj_absorber->no_charge) {
* /* there are no billing records */
* There's no way for you (or a shopkeeper) to prevent globs amount = get_pricing_units(obj_absorbed) * per_unit_cost;
* from merging with each other on the floor due to the
* inherent nature of globs so it irretrievably becomes part
* of the floor glob mass.
*
* globby_donation() needs to handle whether/how to
* compensate you for that.
*
* unpaid globs don't end up here.
*/
void
globby_donation(obj_absorber, obj_absorbed)
struct obj *obj_absorber, *obj_absorbed;
{
if (obj_absorber->where == OBJ_FLOOR
&& costly_spot(obj_absorber->ox, obj_absorber->oy)) {
int x = obj_absorber->ox, y = obj_absorber->oy;
struct monst *shkp = shop_keeper(*in_rooms(x, y, SHOPBASE));
struct eshk *eshkp = ESHK(shkp);
long amount, per_unit_cost = get_cost(obj_absorbed, shkp);
if (saleable(shkp, obj_absorbed)) { if (saleable(shkp, obj_absorbed)) {
amount = get_pricing_units(obj_absorbed) * per_unit_cost;
if (eshkp->debit >= amount) { if (eshkp->debit >= amount) {
if (eshkp->loan) { /* you carry shop's gold */ if (eshkp->loan) { /* you carry shop's gold */
if (eshkp->loan >= amount) if (eshkp->loan >= amount)
eshkp->loan -= amount; eshkp->loan -= amount;
else else
eshkp->loan = 0L; eshkp->loan = 0L;
} }
eshkp->debit -= amount; eshkp->debit -= amount;
@@ -4900,7 +4917,34 @@ struct obj *obj_absorber, *obj_absorbed;
eshkp->credit, currency(eshkp->credit)); eshkp->credit, currency(eshkp->credit));
} }
} }
return;
} else if (bp_absorber) {
/* absorber has a billing record */
bp_absorber->price += per_unit_cost * get_pricing_units(obj_absorbed);
return;
} }
/**************************************************************
* Scenario 3. shop_owned glob merging into player_owned glob
**************************************************************/
if (bp &&
(obj_absorber->no_charge
|| (floor_absorber && !costly_spot(x, y)))) {
amount = bp->price;
bill_dummy_object(obj_absorbed);
verbalize(
"You owe me %ld %s for my %s that %s with your%s",
amount, currency(amount), obj_typename(obj_absorbed->otyp),
ANGRY(shkp) ? "had the audacity to mix" :
"just mixed",
ANGRY(shkp) ? " stinking batch!" :
"s.");
return;
}
/**************************************************************
* Scenario 4. player_owned glob merging into player_owned glob
**************************************************************/
return;
} }
/*shk.c*/ /*shk.c*/
+3
View File
@@ -260,6 +260,9 @@ curses_create_main_windows()
if (curses_get_nhwin(STATUS_WIN)) { if (curses_get_nhwin(STATUS_WIN)) {
curses_del_nhwin(STATUS_WIN); curses_del_nhwin(STATUS_WIN);
/* 'count window' overlays last line of mesg win;
asking it to display a Null string removes it */
curses_count_window((char *) 0);
curses_del_nhwin(MESSAGE_WIN); curses_del_nhwin(MESSAGE_WIN);
curses_del_nhwin(MAP_WIN); curses_del_nhwin(MAP_WIN);
curses_del_nhwin(INV_WIN); curses_del_nhwin(INV_WIN);
+6
View File
@@ -301,6 +301,11 @@ curses_clear_nhwindow(winid wid)
{ {
if (wid != NHW_MESSAGE) { if (wid != NHW_MESSAGE) {
curses_clear_nhwin(wid); curses_clear_nhwin(wid);
} else {
/* scroll the message window one line if it's full */
curses_count_window("");
/* remove 'countwin', leaving last message line blank */
curses_count_window((char *) 0);
} }
} }
@@ -585,6 +590,7 @@ wait_synch() -- Wait until all pending output is complete (*flush*() for
void void
curses_wait_synch() curses_wait_synch()
{ {
/* [do we need 'if (counting) curses_count_window((char *)0);' here?] */
} }
/* /*
+34 -12
View File
@@ -164,7 +164,7 @@ curses_got_input(void)
/* misleadingly named; represents number of lines delivered since /* misleadingly named; represents number of lines delivered since
player was sure to have had a chance to read them; if player player was sure to have had a chance to read them; if player
has just given input then there aren't any such lines right; has just given input then there aren't any such lines right now;
that includes responding to More>> even though it stays same turn */ that includes responding to More>> even though it stays same turn */
turn_lines = 0; turn_lines = 0;
} }
@@ -375,8 +375,8 @@ void
curses_count_window(const char *count_text) curses_count_window(const char *count_text)
{ {
static WINDOW *countwin = NULL; static WINDOW *countwin = NULL;
int startx, starty, winx, winy; int winx, winy;
int messageh, messagew; int messageh, messagew, border;
if (!count_text) { if (!count_text) {
if (countwin) if (countwin)
@@ -384,18 +384,41 @@ curses_count_window(const char *count_text)
counting = FALSE; counting = FALSE;
return; return;
} }
counting = TRUE;
/* position of message window, not current position within message window
(so <0,0> for align_message:Top but will vary for other alignings) */
curses_get_window_xy(MESSAGE_WIN, &winx, &winy); curses_get_window_xy(MESSAGE_WIN, &winx, &winy);
/* size of message window, with space for borders already subtracted */
curses_get_window_size(MESSAGE_WIN, &messageh, &messagew); curses_get_window_size(MESSAGE_WIN, &messageh, &messagew);
if (curses_window_has_border(MESSAGE_WIN)) { /* decide where to put the one-line counting window */
winx++; border = curses_window_has_border(MESSAGE_WIN) ? 1 : 0;
winy++; winx += border; /* first writeable message column */
winy += border + (messageh - 1); /* last writable message line */
/* if most recent message (probably prompt leading to this instance of
counting window) is going to be covered up, scroll mesgs up a line */
if (!counting && my >= border + (messageh - 1)) {
scroll_window(MESSAGE_WIN);
if (messageh > 1) {
/* handling for next message will behave as if we're currently
positioned at the end of next to last line of message window */
my = border + (messageh - 1) - 1;
mx = border + (messagew - 1); /* (0 + 80 - 1) or (1 + 78 - 1) */
} else {
/* for a one-line window, use beginning of only line instead */
my = mx = border; /* 0 or 1 */
}
/* wmove(curses_get_nhwin(MESSAGE_WIN), my, mx); -- not needed */
} }
/* in case we're being called from clear_nhwindow(MESSAGE_WIN)
which gets called for every command keystroke; it sends an
empty string to get the scroll-up-one-line effect above and
we want to avoid the curses overhead for the operations below... */
if (!*count_text)
return;
winy += messageh - 1; counting = TRUE;
#ifdef PDCURSES #ifdef PDCURSES
if (countwin) if (countwin)
curses_destroy_win(countwin), countwin = NULL; curses_destroy_win(countwin), countwin = NULL;
@@ -404,10 +427,9 @@ curses_count_window(const char *count_text)
but not for dolook's autodescribe when it refers to a named monster */ but not for dolook's autodescribe when it refers to a named monster */
if (!countwin) if (!countwin)
countwin = newwin(1, messagew, winy, winx); countwin = newwin(1, messagew, winy, winx);
startx = 0; werase(countwin);
starty = 0;
mvwprintw(countwin, starty, startx, "%s", count_text); mvwprintw(countwin, 0, 0, "%s", count_text);
wrefresh(countwin); wrefresh(countwin);
} }
+6
View File
@@ -352,6 +352,8 @@ curses_del_wid(winid wid)
void void
curs_destroy_all_wins() curs_destroy_all_wins()
{ {
curses_count_window((char *) 0); /* clean up orphan */
while (nhwids) while (nhwids)
curses_del_wid(nhwids->nhwid); curses_del_wid(nhwids->nhwid);
} }
@@ -483,6 +485,10 @@ curses_puts(winid wid, int attr, const char *text)
} }
if (wid == MESSAGE_WIN) { if (wid == MESSAGE_WIN) {
/* if a no-history message is being shown, remove it */
if (counting)
curses_count_window((char *) 0);
curses_message_win_puts(text, FALSE); curses_message_win_puts(text, FALSE);
return; return;
} }