Merge branch 'NetHack-3.6.2'

This commit is contained in:
nhmall
2018-11-21 18:58:04 -05:00
14 changed files with 261 additions and 100 deletions

View File

@@ -205,6 +205,8 @@ successfully paying for shop damage with shop credit would be followed by
if a migrating monster was killed off because there was no room on the
destination level, it would leave a corpse even if it was a type
which should never leave one (demon, golem, blob, &c)
end of game while carrying Schroedinger's Box would reveal cat-or-corpse
for inventory disclosure or put that info into dumplog, but not both
Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 extern.h $NHDT-Date: 1541719965 2018/11/08 23:32:45 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.647 $ */
/* NetHack 3.6 extern.h $NHDT-Date: 1542798602 2018/11/21 11:10:02 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.650 $ */
/* Copyright (c) Steve Creps, 1988. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1851,6 +1851,7 @@ E struct obj *FDECL(pick_obj, (struct obj *));
E int NDECL(encumber_msg);
E int FDECL(container_at, (int, int, BOOLEAN_P));
E int NDECL(doloot);
E void FDECL(observe_quantum_cat, (struct obj *, BOOLEAN_P, BOOLEAN_P));
E boolean FDECL(container_gone, (int (*)(OBJ_P)));
E boolean NDECL(u_handsy);
E int FDECL(use_container, (struct obj **, int, BOOLEAN_P));

View File

@@ -484,7 +484,7 @@ fail_mon_placement:
&& !LEVEL_SPECIFIC_NOCORPSE(mtmp->data))
(void) mkcorpstat(CORPSE, mtmp, mtmp->data,
xlocale, ylocale, CORPSTAT_NONE);
mtmp->mx = mtmp->my = -1; /* for mongone, mon is not anywhere */
mtmp->mx = mtmp->my = 0; /* for mongone, mon is not anywhere */
mongone(mtmp);
}
}

122
src/end.c
View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 end.c $NHDT-Date: 1541902951 2018/11/11 02:22:31 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.150 $ */
/* NetHack 3.6 end.c $NHDT-Date: 1542798619 2018/11/21 11:10:19 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.152 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */
@@ -49,7 +49,6 @@ STATIC_DCL void FDECL(get_valuables, (struct obj *));
STATIC_DCL void FDECL(sort_valuables, (struct valuable_data *, int));
STATIC_DCL void FDECL(artifact_score, (struct obj *, BOOLEAN_P, winid));
STATIC_DCL void FDECL(really_done, (int)) NORETURN;
STATIC_DCL boolean FDECL(odds_and_ends, (struct obj *, int));
STATIC_DCL void FDECL(savelife, (int));
STATIC_PTR int FDECL(CFDECLSPEC vanqsort_cmp, (const genericptr,
const genericptr));
@@ -954,6 +953,13 @@ int size; /* max value is less than 20 */
return;
}
#if 0
/*
* odds_and_ends() was used for 3.6.0 and 3.6.1.
* Schroedinger's Cat is handled differently starting with 3.6.2.
*/
STATIC_DCL boolean FDECL(odds_and_ends, (struct obj *, int));
#define CAT_CHECK 2
STATIC_OVL boolean
@@ -962,6 +968,7 @@ struct obj *list;
int what;
{
struct obj *otmp;
for (otmp = list; otmp; otmp = otmp->nobj) {
switch (what) {
case CAT_CHECK: /* Schroedinger's Cat */
@@ -975,6 +982,7 @@ int what;
}
return FALSE;
}
#endif
/* called twice; first to calculate total, then to list relevant items */
STATIC_OVL void
@@ -1218,6 +1226,20 @@ int how;
obj->known = obj->bknown = obj->dknown = obj->rknown = 1;
if (Is_container(obj) || obj->otyp == STATUE)
obj->cknown = obj->lknown = 1;
/* we resolve Schroedinger's cat now in case of both
disclosure and dumplog, where the 50:50 chance for
live cat has to be the same both times */
if (SchroedingersBox(obj)) {
if (!Schroedingers_cat) {
/* tell observe_quantum_cat() not to create a cat; if it
chooses live cat in this situation, it will leave the
SchroedingersBox flag set (for container_contents()) */
observe_quantum_cat(obj, FALSE, FALSE);
if (SchroedingersBox(obj))
Schroedingers_cat = TRUE;
} else
obj->spe = 0; /* ordinary box with cat corpse in it */
}
}
if (strcmp(flags.end_disclose, "none"))
@@ -1228,7 +1250,7 @@ int how;
/* if pets will contribute to score, populate mydogs list now
(bones creation isn't a factor, but pline() messaging is; used to
be done ever sooner, but we need it to come after dump_everything()
be done even sooner, but we need it to come after dump_everything()
so that any accompanying pets are still on the map during dump) */
if (how == ESCAPED || how == ASCENDED)
keepdogs(TRUE);
@@ -1389,22 +1411,22 @@ int how;
viz_array[0][0] |= IN_SIGHT; /* need visibility for naming */
mtmp = mydogs;
Strcpy(pbuf, "You");
if (!Schroedingers_cat) /* check here in case disclosure was off */
Schroedingers_cat = odds_and_ends(invent, CAT_CHECK);
if (Schroedingers_cat) {
int mhp, m_lev = adj_lev(&mons[PM_HOUSECAT]);
mhp = d(m_lev, 8);
nowrap_add(u.urexp, mhp);
Strcat(eos(pbuf), " and Schroedinger's cat");
}
if (mtmp) {
if (mtmp || Schroedingers_cat) {
while (mtmp) {
Sprintf(eos(pbuf), " and %s", mon_nam(mtmp));
if (mtmp->mtame)
nowrap_add(u.urexp, mtmp->mhp);
mtmp = mtmp->nmon;
}
/* [it might be more robust to create a housecat and add it to
mydogs; it doesn't have to be placed on the map for that] */
if (Schroedingers_cat) {
int mhp, m_lev = adj_lev(&mons[PM_HOUSECAT]);
mhp = d(m_lev, 8);
nowrap_add(u.urexp, mhp);
Strcat(eos(pbuf), " and Schroedinger's cat");
}
dump_forward_putstr(endwin, 0, pbuf, done_stopprint);
pbuf[0] = '\0';
} else {
@@ -1513,23 +1535,18 @@ boolean identified, all_containers, reportempty;
{
register struct obj *box, *obj;
char buf[BUFSZ];
boolean cat, deadcat;
boolean cat,
dumping =
#ifdef DUMPLOG
iflags.in_dumplog ? TRUE :
#endif
FALSE;
for (box = list; box; box = box->nobj) {
if (Is_container(box) || box->otyp == STATUE) {
box->cknown = 1; /* we're looking at the contents now */
if (identified)
box->lknown = 1;
cat = deadcat = FALSE;
if (SchroedingersBox(box) && !Schroedingers_cat) {
/* Schroedinger's Cat? */
cat = odds_and_ends(box, CAT_CHECK);
if (cat)
Schroedingers_cat = TRUE;
else
deadcat = TRUE;
box->spe = 0;
}
if (box->otyp == BAG_OF_TRICKS) {
continue; /* wrong type of container */
} else if (box->cobj) {
@@ -1537,38 +1554,49 @@ boolean identified, all_containers, reportempty;
Loot *sortedcobj, *srtc;
unsigned sortflags;
/* at this stage, the SchroedingerBox() flag is only set
if the cat inside the box is alive; the box actually
contains a cat corpse that we'll pretend is not there;
for dead cat, the flag will be clear and there'll be
a cat corpse inside the box; either way, inventory
reports the box as containing "1 item" */
cat = SchroedingersBox(box);
Sprintf(buf, "Contents of %s:", the(xname(box)));
putstr(tmpwin, 0, buf);
putstr(tmpwin, 0, "");
sortflags = (((flags.sortloot == 'l' || flags.sortloot == 'f')
? SORTLOOT_LOOT : 0)
| (flags.sortpack ? SORTLOOT_PACK : 0));
sortedcobj = sortloot(&box->cobj, sortflags, FALSE,
(boolean FDECL((*), (OBJ_P))) 0);
for (srtc = sortedcobj; ((obj = srtc->obj) != 0); ++srtc) {
if (identified) {
discover_object(obj->otyp, TRUE, FALSE);
obj->known = obj->bknown = obj->dknown
= obj->rknown = 1;
if (Is_container(obj) || obj->otyp == STATUE)
obj->cknown = obj->lknown = 1;
if (!dumping)
putstr(tmpwin, 0, "");
buf[0] = buf[1] = ' '; /* two leading spaces */
if (box->cobj && !cat) {
sortflags = (((flags.sortloot == 'l'
|| flags.sortloot == 'f')
? SORTLOOT_LOOT : 0)
| (flags.sortpack ? SORTLOOT_PACK : 0));
sortedcobj = sortloot(&box->cobj, sortflags, FALSE,
(boolean FDECL((*), (OBJ_P))) 0);
for (srtc = sortedcobj; ((obj = srtc->obj) != 0); ++srtc) {
if (identified) {
discover_object(obj->otyp, TRUE, FALSE);
obj->known = obj->bknown = obj->dknown
= obj->rknown = 1;
if (Is_container(obj) || obj->otyp == STATUE)
obj->cknown = obj->lknown = 1;
}
Strcpy(&buf[2], doname(obj));
putstr(tmpwin, 0, buf);
}
putstr(tmpwin, 0, doname(obj));
unsortloot(&sortedcobj);
} else if (cat) {
Strcpy(&buf[2], "Schroedinger's cat!");
putstr(tmpwin, 0, buf);
}
unsortloot(&sortedcobj);
if (cat)
putstr(tmpwin, 0, "Schroedinger's cat");
else if (deadcat)
putstr(tmpwin, 0, "Schroedinger's dead cat");
if (dumping)
putstr(0, 0, "");
display_nhwindow(tmpwin, TRUE);
destroy_nhwindow(tmpwin);
if (all_containers)
container_contents(box->cobj, identified, TRUE,
reportempty);
} else if (cat || deadcat) {
pline("%s Schroedinger's %scat!", Tobjnam(box, "contain"),
deadcat ? "dead " : "");
display_nhwindow(WIN_MESSAGE, FALSE);
} else if (reportempty) {
pline("%s is empty.", upstart(thesimpleoname(box)));
display_nhwindow(WIN_MESSAGE, FALSE);

View File

@@ -423,7 +423,7 @@ struct mail_info *info;
/* zip back to starting location */
go_back:
if (!md_rush(md, start.x, start.y))
md->mx = md->my = -1; /* for mongone, md is not on map */
md->mx = md->my = 0; /* for mongone, md is not on map */
mongone(md);
/* deliver some classes of messages even if no daemon ever shows up */
give_up:

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 makemon.c $NHDT-Date: 1539804904 2018/10/17 19:35:04 $ $NHDT-Branch: keni-makedefsm $:$NHDT-Revision: 1.127 $ */
/* NetHack 3.6 makemon.c $NHDT-Date: 1542798623 2018/11/21 11:10:23 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.128 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */
@@ -280,7 +280,8 @@ register struct monst *mtmp;
if (rn2(2))
(void) mongets(mtmp, rn2(3) ? DAGGER : KNIFE);
if (rn2(5))
(void) mongets(mtmp, rn2(3) ? LEATHER_JACKET : LEATHER_CLOAK);
(void) mongets(mtmp, rn2(3) ? LEATHER_JACKET
: LEATHER_CLOAK);
if (rn2(3))
(void) mongets(mtmp, rn2(3) ? LOW_BOOTS : HIGH_BOOTS);
if (rn2(3))
@@ -304,7 +305,8 @@ register struct monst *mtmp;
case PM_HUNTER:
(void) mongets(mtmp, rn2(3) ? SHORT_SWORD : DAGGER);
if (rn2(2))
(void) mongets(mtmp, rn2(2) ? LEATHER_JACKET : LEATHER_ARMOR);
(void) mongets(mtmp, rn2(2) ? LEATHER_JACKET
: LEATHER_ARMOR);
(void) mongets(mtmp, BOW);
m_initthrow(mtmp, ARROW, 12);
break;
@@ -744,9 +746,21 @@ register struct monst *mtmp;
break;
case S_QUANTMECH:
if (!rn2(20)) {
struct obj *catcorpse;
otmp = mksobj(LARGE_BOX, FALSE, FALSE);
otmp->spe = 1; /* flag for special box */
otmp->owt = weight(otmp);
/* we used to just set the flag, which resulted in weight()
treating the box as being heavier by the weight of a cat;
now we include a cat corpse that won't rot; when opening or
disclosing the box's contents, the corpse might be revived,
otherwise it's given a rot timer; weight is now ordinary */
if ((catcorpse = mksobj(CORPSE, TRUE, FALSE)) != 0) {
otmp->spe = 1; /* flag for special SchroedingersBox */
set_corpsenm(catcorpse, PM_HOUSECAT);
(void) stop_timer(ROT_CORPSE, obj_to_any(catcorpse));
add_to_container(otmp, catcorpse);
otmp->owt = weight(otmp);
}
(void) mpickobj(mtmp, otmp);
}
break;

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 mkobj.c $NHDT-Date: 1518053380 2018/02/08 01:29:40 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.130 $ */
/* NetHack 3.6 mkobj.c $NHDT-Date: 1542798624 2018/11/21 11:10:24 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.136 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Derek S. Ray, 2015. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1388,8 +1388,6 @@ register struct obj *obj;
when we assume this is a brand new glob so use objects[].oc_weight */
if (obj->globby && obj->owt > 0)
wt = obj->owt;
if (SchroedingersBox(obj))
wt += mons[PM_HOUSECAT].cwt;
if (Is_container(obj) || obj->otyp == STATUE) {
struct obj *contents;
register int cwt = 0;

View File

@@ -105,7 +105,7 @@ mon_sanity_check()
}
}
for (x = 0; x < COLNO; x++)
for (x = 1; x < COLNO; x++)
for (y = 0; y < ROWNO; y++)
if ((mtmp = level.monsters[x][y]) != 0) {
for (m = fmon; m; m = m->nmon)
@@ -1747,7 +1747,7 @@ m_detach(mtmp, mptr)
struct monst *mtmp;
struct permonst *mptr; /* reflects mtmp->data _prior_ to mtmp's death */
{
boolean onmap = (mtmp->mx > -1);
boolean onmap = (mtmp->mx > 0);
if (mtmp == context.polearm.hitmon)
context.polearm.hitmon = 0;

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 pickup.c $NHDT-Date: 1541312259 2018/11/04 06:17:39 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.201 $ */
/* NetHack 3.6 pickup.c $NHDT-Date: 1542798625 2018/11/21 11:10:25 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.202 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */
@@ -34,7 +34,6 @@ STATIC_PTR int FDECL(in_container, (struct obj *));
STATIC_PTR int FDECL(out_container, (struct obj *));
STATIC_DCL void FDECL(removed_from_icebox, (struct obj *));
STATIC_DCL long FDECL(mbag_item_gone, (int, struct obj *));
STATIC_DCL void FDECL(observe_quantum_cat, (struct obj *));
STATIC_DCL void FDECL(explain_container_prompt, (BOOLEAN_P));
STATIC_DCL int FDECL(traditional_loot, (BOOLEAN_P));
STATIC_DCL int FDECL(menu_loot, (int, BOOLEAN_P));
@@ -2321,45 +2320,66 @@ struct obj *item;
return loss;
}
STATIC_OVL void
observe_quantum_cat(box)
/* used for #loot/apply, #tip, and final disclosure */
void
observe_quantum_cat(box, makecat, givemsg)
struct obj *box;
boolean makecat, givemsg;
{
static NEARDATA const char sc[] = "Schroedinger's Cat";
struct obj *deadcat;
struct monst *livecat;
struct monst *livecat = 0;
xchar ox, oy;
boolean itsalive = !rn2(2);
box->spe = 0; /* box->owt will be updated below */
if (get_obj_location(box, &ox, &oy, 0))
box->ox = ox, box->oy = oy; /* in case it's being carried */
/* this isn't really right, since any form of observation
(telepathic or monster/object/food detection) ought to
force the determination of alive vs dead state; but basing
it just on opening the box is much simpler to cope with */
livecat = rn2(2)
? makemon(&mons[PM_HOUSECAT], box->ox, box->oy, NO_MINVENT)
: 0;
if (livecat) {
livecat->mpeaceful = 1;
set_malign(livecat);
if (!canspotmon(livecat))
You("think %s brushed your %s.", something, body_part(FOOT));
else
pline("%s inside the box is still alive!", Monnam(livecat));
(void) christen_monst(livecat, sc);
} else {
deadcat = mk_named_object(CORPSE, &mons[PM_HOUSECAT],
box->ox, box->oy, sc);
if (deadcat) {
obj_extract_self(deadcat);
(void) add_to_container(box, deadcat);
force the determination of alive vs dead state; but basing it
just on opening or disclosing the box is much simpler to cope with */
/* SchroedingersBox already has a cat corpse in it */
deadcat = box->cobj;
if (itsalive) {
if (makecat)
livecat = makemon(&mons[PM_HOUSECAT], box->ox, box->oy,
NO_MINVENT | MM_ADJACENTOK);
if (livecat) {
livecat->mpeaceful = 1;
set_malign(livecat);
if (givemsg) {
if (!canspotmon(livecat))
You("think %s brushed your %s.", something,
body_part(FOOT));
else
pline("%s inside the box is still alive!",
Monnam(livecat));
}
(void) christen_monst(livecat, sc);
if (deadcat) {
obj_extract_self(deadcat);
obfree(deadcat, (struct obj *) 0), deadcat = 0;
}
box->owt = weight(box);
box->spe = 0;
}
pline_The("%s inside the box is dead!",
Hallucination ? rndmonnam((char *) 0) : "housecat");
} else {
box->spe = 0; /* now an ordinary box (with a cat corpse inside) */
if (deadcat) {
/* set_corpsenm() will start the rot timer that was removed
when makemon() created SchroedingersBox; start it from
now rather than from when this special corpse got created */
deadcat->age = monstermoves;
set_corpsenm(deadcat, PM_HOUSECAT);
deadcat = oname(deadcat, sc);
}
if (givemsg)
pline_The("%s inside the box is dead!",
Hallucination ? rndmonnam((char *) 0) : "housecat");
}
box->owt = weight(box);
nhUse(deadcat);
return;
}
@@ -2472,7 +2492,7 @@ boolean more_containers; /* True iff #loot multiple and this isn't last one */
/* check for Schroedinger's Cat */
quantum_cat = SchroedingersBox(current_container);
if (quantum_cat) {
observe_quantum_cat(current_container);
observe_quantum_cat(current_container, TRUE, TRUE);
used = 1;
}
@@ -3096,7 +3116,7 @@ struct obj *box; /* or bag */
} else if (SchroedingersBox(box)) {
char yourbuf[BUFSZ];
observe_quantum_cat(box);
observe_quantum_cat(box, TRUE, TRUE);
if (!Has_contents(box)) /* evidently a live cat came out */
/* container type of "large box" is inferred */
pline("%sbox is now empty.", Shk_Your(yourbuf, box));

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 restore.c $NHDT-Date: 1451082255 2015/12/25 22:24:15 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.103 $ */
/* NetHack 3.6 restore.c $NHDT-Date: 1542798626 2018/11/21 11:10:26 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.109 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Michael Allison, 2009. */
/* NetHack may be freely redistributed. See license for details. */
@@ -298,10 +298,32 @@ boolean ghostly, frozen;
/* get contents of a container or statue */
if (Has_contents(otmp)) {
struct obj *otmp3;
otmp->cobj = restobjchn(fd, ghostly, Is_IceBox(otmp));
/* restore container back pointers */
for (otmp3 = otmp->cobj; otmp3; otmp3 = otmp3->nobj)
otmp3->ocontainer = otmp;
} else if (SchroedingersBox(otmp)) {
struct obj *catcorpse;
/*
* TODO: Remove this after 3.6.x save compatibility is dropped.
*
* For 3.6.2, SchroedingersBox() always has a cat corpse in it.
* For 3.6.[01], it was empty and its weight was falsified
* to have the value it would have had if there was one inside.
* Put a non-rotting cat corpse in this box to convert to 3.6.2.
*
* [Note: after this fix up, future save/restore of this object
* will take the Has_contents() code path above.]
*/
if ((catcorpse = mksobj(CORPSE, TRUE, FALSE)) != 0) {
otmp->spe = 1; /* flag for special SchroedingersBox */
set_corpsenm(catcorpse, PM_HOUSECAT);
(void) stop_timer(ROT_CORPSE, obj_to_any(catcorpse));
add_to_container(otmp, catcorpse);
otmp->owt = weight(otmp);
}
}
if (otmp->bypass)
otmp->bypass = 0;

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 zap.c $NHDT-Date: 1537234123 2018/09/18 01:28:43 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.287 $ */
/* NetHack 3.6 zap.c $NHDT-Date: 1542798627 2018/11/21 11:10:27 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.289 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2013. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1916,14 +1916,17 @@ struct obj *obj, *otmp;
if (Is_container(obj) || obj->otyp == STATUE) {
obj->cknown = obj->lknown = 1;
if (!obj->cobj) {
boolean catbox = SchroedingersBox(obj);
pline("%s empty.", Tobjnam(obj, "are"));
} else if (SchroedingersBox(obj)) {
/* we don't want to force alive vs dead
determination for Schroedinger's Cat here,
so just make probing be inconclusive for it */
if (catbox)
obj->cknown = 0;
pline("%s empty.", Tobjnam(obj, catbox ? "seem" : "are"));
You("aren't sure whether %s has %s or its corpse inside.",
the(xname(obj)),
/* unfortunately, we can't tell whether rndmonnam()
picks a form which can't leave a corpse */
an(Hallucination ? rndmonnam((char *) 0) : "cat"));
obj->cknown = 0;
} else {
struct obj *o;
/* view contents (not recursively) */

View File

@@ -688,11 +688,11 @@ tty_delay_output()
clock_t goal;
int k;
goal = 50 + clock();
back_buffer_flip();
if (iflags.debug_fuzzer)
return;
goal = 50 + clock();
back_buffer_flip();
while (goal > clock()) {
k = junk; /* Do nothing */
}

View File

@@ -185,6 +185,8 @@ static const char scanmap[] = {
'b', 'n', 'm', ',', '.', '?' /* ... */
};
#define IDT_FUZZ_TIMER 100
/*
// FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
@@ -727,6 +729,62 @@ mswin_layout_main_window(HWND changed_child)
SetForegroundWindow(changed_child);
}
VOID CALLBACK FuzzTimerProc(
_In_ HWND hwnd,
_In_ UINT uMsg,
_In_ UINT_PTR idEvent,
_In_ DWORD dwTime
)
{
INPUT input[16];
int i_pos = 0;
int c = randomkey();
SHORT k = VkKeyScanA(c);
BOOL gen_alt = (rn2(50) == 0) && isalpha(c);
if (!iflags.debug_fuzzer) {
KillTimer(hwnd, IDT_FUZZ_TIMER);
return;
}
if (!GetFocus())
return;
ZeroMemory(input, sizeof(input));
if (gen_alt) {
input[i_pos].type = INPUT_KEYBOARD;
input[i_pos].ki.dwFlags = KEYEVENTF_SCANCODE;
input[i_pos].ki.wScan = MapVirtualKey(VK_MENU, 0);
i_pos++;
}
if (HIBYTE(k) & 1) {
input[i_pos].type = INPUT_KEYBOARD;
input[i_pos].ki.dwFlags = KEYEVENTF_SCANCODE;
input[i_pos].ki.wScan = MapVirtualKey(VK_LSHIFT, 0);
i_pos++;
}
input[i_pos].type = INPUT_KEYBOARD;
input[i_pos].ki.dwFlags = KEYEVENTF_SCANCODE;
input[i_pos].ki.wScan = MapVirtualKey(LOBYTE(k), 0);
i_pos++;
if (HIBYTE(k) & 1) {
input[i_pos].type = INPUT_KEYBOARD;
input[i_pos].ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
input[i_pos].ki.wScan = MapVirtualKey(VK_LSHIFT, 0);
i_pos++;
}
if (gen_alt) {
input[i_pos].type = INPUT_KEYBOARD;
input[i_pos].ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
input[i_pos].ki.wScan = MapVirtualKey(VK_MENU, 0);
i_pos++;
}
SendInput(i_pos, input, sizeof(input[0]));
}
LRESULT
onWMCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
@@ -745,11 +803,22 @@ onWMCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
mswin_display_splash_window(TRUE);
break;
case IDM_FUZZ:
if (iflags.debug_fuzzer)
KillTimer(hWnd, IDT_FUZZ_TIMER);
else
SetTimer(hWnd, IDT_FUZZ_TIMER, 10, FuzzTimerProc);
iflags.debug_fuzzer = !iflags.debug_fuzzer;
break;
case IDM_EXIT:
if (iflags.debug_fuzzer)
break;
done2();
break;
case IDM_SAVE:
if (iflags.debug_fuzzer)
break;
if (!program_state.gameover && !program_state.done_hup)
dosave();
else
@@ -829,6 +898,9 @@ onWMCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
wchar_t *wtext;
int tlen = 0;
if (iflags.debug_fuzzer)
break;
ZeroMemory(filename, sizeof(filename));
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(OPENFILENAME);

View File

@@ -142,6 +142,7 @@
#define IDM_SETTING_LOCKWINDOWS 32797
#define IDM_SETTING_SCREEN_TO_CLIPBOARD 32798
#define IDM_SETTING_SCREEN_TO_FILE 32799
#define IDM_FUZZ 32800
#define IDC_STATIC -1
// Next default values for new objects
@@ -149,7 +150,7 @@
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 146
#define _APS_NEXT_COMMAND_VALUE 32800
#define _APS_NEXT_COMMAND_VALUE 32801
#define _APS_NEXT_CONTROL_VALUE 1341
#define _APS_NEXT_SYMED_VALUE 110
#endif