From: PatR Date: Tue, 25 Feb 2020 01:07:01 +0000 (-0800) Subject: flipping current level with #wizlevelflip X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=194b174bbc571dddd8f760934763ec3e9a860ce1;p=nethack flipping current level with #wizlevelflip Give wizard mode player control over how a level gets transposed by prompting for the desired outcome. Refreshing the screen showed that remembered, no longer in view wall corners and T walls were shown with their old orientation instead of being transposed along with the level. This fixes that, but does so by adding a chunk of code that will be irrelevant for normal play. --- diff --git a/include/extern.h b/include/extern.h index cae10391d..ec2910480 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 extern.h $NHDT-Date: 1582321542 2020/02/21 21:45:42 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.801 $ */ +/* NetHack 3.6 extern.h $NHDT-Date: 1582592780 2020/02/25 01:06:20 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.804 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2466,33 +2466,38 @@ E void FDECL(sysopt_seduce_set, (int)); /* ### sp_lev.c ### */ #if !defined(CROSSCOMPILE) || defined(CROSSCOMPILE_TARGET) +E void FDECL(flip_level, (int, BOOLEAN_P)); E void FDECL(flip_level_rnd, (int, BOOLEAN_P)); E boolean FDECL(check_room, (xchar *, xchar *, xchar *, xchar *, BOOLEAN_P)); E boolean FDECL(create_room, (XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P)); E void FDECL(create_secret_door, (struct mkroom *, XCHAR_P)); -E boolean -FDECL(dig_corridor, (coord *, coord *, BOOLEAN_P, SCHAR_P, SCHAR_P)); +E boolean FDECL(dig_corridor, (coord *, coord *, BOOLEAN_P, SCHAR_P, SCHAR_P)); E void FDECL(fill_room, (struct mkroom *, BOOLEAN_P)); E boolean FDECL(load_special, (const char *)); E xchar FDECL(selection_getpoint, (int, int, struct selectionvar *)); E struct selectionvar *NDECL(selection_new); E void FDECL(selection_free, (struct selectionvar *, BOOLEAN_P)); -#if !defined(IN_SP_LEV_C) E void FDECL(set_selection_floodfillchk, (int FDECL((*), (int,int)))); -#endif -E void FDECL(selection_floodfill, (struct selectionvar *, int, int, BOOLEAN_P)); -E void FDECL(get_location_coord, (schar *, schar *, int, struct mkroom *, long)); +E void FDECL(selection_floodfill, (struct selectionvar *, int, int, + BOOLEAN_P)); +E void FDECL(get_location_coord, (schar *, schar *, int, struct mkroom *, + long)); E void FDECL(selection_setpoint, (int, int, struct selectionvar *, XCHAR_P)); E struct selectionvar * FDECL(selection_not, (struct selectionvar *)); E void FDECL(selection_filter_percent, (struct selectionvar *, int)); -E int FDECL(selection_rndcoord, (struct selectionvar *, schar *, schar *, BOOLEAN_P)); +E int FDECL(selection_rndcoord, (struct selectionvar *, schar *, schar *, + BOOLEAN_P)); E void FDECL(selection_do_grow, (struct selectionvar *, int)); -E void FDECL(selection_do_line, (SCHAR_P, SCHAR_P, SCHAR_P, SCHAR_P, struct selectionvar *)); -E void FDECL(selection_do_randline, (SCHAR_P, SCHAR_P, SCHAR_P, SCHAR_P, SCHAR_P, SCHAR_P, struct selectionvar *)); -E struct selectionvar *FDECL(selection_filter_mapchar, (struct selectionvar *, XCHAR_P, int)); +E void FDECL(selection_do_line, (SCHAR_P, SCHAR_P, SCHAR_P, SCHAR_P, + struct selectionvar *)); +E void FDECL(selection_do_randline, (SCHAR_P, SCHAR_P, SCHAR_P, SCHAR_P, + SCHAR_P, SCHAR_P, struct selectionvar *)); +E struct selectionvar *FDECL(selection_filter_mapchar, (struct selectionvar *, + XCHAR_P, int)); E void FDECL(set_floodfillchk_match_under, (XCHAR_P)); -E void FDECL(selection_do_ellipse, (struct selectionvar *, int, int, int, int, int)); +E void FDECL(selection_do_ellipse, (struct selectionvar *, + int, int, int, int, int)); E void NDECL(update_croom); E const char *FDECL(get_trapname_bytype, (int)); E void FDECL(l_register_des, (lua_State *)); diff --git a/src/cmd.c b/src/cmd.c index 308429412..9f197bcbe 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 cmd.c $NHDT-Date: 1582321487 2020/02/21 21:44:47 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.403 $ */ +/* NetHack 3.6 cmd.c $NHDT-Date: 1582592803 2020/02/25 01:06:43 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.405 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1019,14 +1019,37 @@ wiz_level_tele(VOID_ARGS) return 0; } -/* #wizlevelflip - randomly flip the current level. - Does not handle vision, monst mtrack, levregions, - as flipping is normally done only during level creation. - */ +/* #wizlevelflip - flip the current level */ static int wiz_level_flip(VOID_ARGS) { - if (wizard) flip_level_rnd(3, TRUE); + static const char choices[] = "0123", + prmpt[] = "Flip 0=randomly, 1=vertically, 2=horizonally, 3=both:"; + + /* + * Does not handle + * levregions, + * monster mtrack, + * migrating monsters aimed at returning to specific coordinates + * on the this level + * as flipping is normally done only during level creation. + */ + if (wizard) { + char c = yn_function(prmpt, choices, '\0'); + + if (c && index(choices, c)) { + c -= '0'; + + if (!c) + flip_level_rnd(3, TRUE); + else + flip_level((int) c, TRUE); + + docrt(); + } else { + pline("%s", Never_mind); + } + } return 0; } diff --git a/src/sp_lev.c b/src/sp_lev.c index 9ef7ee1c2..828fa02af 100644 --- a/src/sp_lev.c +++ b/src/sp_lev.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 sp_lev.c $NHDT-Date: 1581562593 2020/02/13 02:56:33 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.157 $ */ +/* NetHack 3.6 sp_lev.c $NHDT-Date: 1582592810 2020/02/25 01:06:50 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.162 $ */ /* Copyright (c) 1989 by Jean-Christophe Collet */ /* NetHack may be freely redistributed. See license for details. */ @@ -30,7 +30,6 @@ static void FDECL(lvlfill_solid, (SCHAR_P, SCHAR_P)); static void FDECL(flip_drawbridge_horizontal, (struct rm *)); static void FDECL(flip_drawbridge_vertical, (struct rm *)); static int FDECL(flip_encoded_direction_bits, (int, int)); -static void FDECL(flip_level, (int, BOOLEAN_P)); static void FDECL(set_wall_property, (XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P, int)); static void NDECL(count_features); @@ -246,6 +245,49 @@ struct rm *lev; } } +/* for #wizlevelflip; not needed when flipping during level creation; + update seen vector for whole level and glyph for walls */ +static void +flip_visuals(flp) +int flp; +{ + struct rm *lev; + int x, y, seenv; + + for (y = 0; y < ROWNO; ++y) { + for (x = 1; x < COLNO; ++x) { + lev = &levl[x][y]; + seenv = lev->seenv & 0xff; + /* locations which haven't been seen can be skipped */ + if (seenv == 0) + continue; + /* flip 's seen vector; not necessary for locations seen + from all directions (the whole level after magic mapping) */ + if (seenv != SVALL) { + /* SV2 SV1 SV0 * + * SV3 -+- SV7 * + * SV4 SV5 SV6 */ + if (flp & 1) { /* swap top and bottom */ + seenv = swapbits(seenv, 2, 4); + seenv = swapbits(seenv, 1, 5); + seenv = swapbits(seenv, 0, 6); + } + if (flp & 2) { /* swap left and right */ + seenv = swapbits(seenv, 2, 0); + seenv = swapbits(seenv, 3, 7); + seenv = swapbits(seenv, 4, 6); + } + lev->seenv = (uchar) seenv; + } + /* if is displayed as a wall, reset its display glyph so + that remembered, out of view T's and corners get flipped */ + if ((IS_WALL(lev->typ) || lev->typ == SDOOR) + && glyph_is_cmap(lev->glyph)) + lev->glyph = back_to_glyph(x, y); + } + } +} + static int flip_encoded_direction_bits(int flp, int val) { @@ -267,12 +309,14 @@ flip_encoded_direction_bits(int flp, int val) #define FlipX(val) ((maxx - (val)) + minx) #define FlipY(val) ((maxy - (val)) + miny) -static void +/* transpose top with bottom or left with right or both; sometimes called + for new special levels, or for any level via the #wizlevelflip command */ +void flip_level(flp, extras) int flp; boolean extras; { - int x, y, i; + int x, y, i, itmp; int minx, miny, maxx, maxy; struct rm trm; struct trap *ttmp; @@ -283,10 +327,14 @@ boolean extras; get_level_extends(&minx, &miny, &maxx, &maxy); /* get_level_extends() returns -1,-1 to COLNO,ROWNO at max */ - if (miny < 0) miny = 0; - if (minx < 0) minx = 0; - if (maxx >= COLNO) maxx = (COLNO - 1); - if (maxy >= ROWNO) maxy = (ROWNO - 1); + if (miny < 0) + miny = 0; + if (minx < 0) + minx = 0; + if (maxx >= COLNO) + maxx = (COLNO - 1); + if (maxy >= ROWNO) + maxy = (ROWNO - 1); /* stairs and ladders */ if (flp & 1) { @@ -312,7 +360,8 @@ boolean extras; ttmp->launch.y = FlipY(ttmp->launch.y); ttmp->launch2.y = FlipY(ttmp->launch2.y); } else if (is_pit(ttmp->ttyp) && ttmp->conjoined) { - ttmp->conjoined = flip_encoded_direction_bits(flp, ttmp->conjoined); + ttmp->conjoined = flip_encoded_direction_bits(flp, + ttmp->conjoined); } } if (flp & 2) { @@ -321,7 +370,8 @@ boolean extras; ttmp->launch.x = FlipX(ttmp->launch.x); ttmp->launch2.x = FlipX(ttmp->launch2.x); } else if (is_pit(ttmp->ttyp) && ttmp->conjoined) { - ttmp->conjoined = flip_encoded_direction_bits(flp, ttmp->conjoined); + ttmp->conjoined = flip_encoded_direction_bits(flp, + ttmp->conjoined); } } } @@ -382,34 +432,34 @@ boolean extras; g.lregions[i].inarea.y1 = FlipY(g.lregions[i].inarea.y1); g.lregions[i].inarea.y2 = FlipY(g.lregions[i].inarea.y2); if (g.lregions[i].inarea.y1 > g.lregions[i].inarea.y2) { - int tmp = g.lregions[i].inarea.y1; + itmp = g.lregions[i].inarea.y1; g.lregions[i].inarea.y1 = g.lregions[i].inarea.y2; - g.lregions[i].inarea.y2 = tmp; + g.lregions[i].inarea.y2 = itmp; } g.lregions[i].delarea.y1 = FlipY(g.lregions[i].delarea.y1); g.lregions[i].delarea.y2 = FlipY(g.lregions[i].delarea.y2); if (g.lregions[i].delarea.y1 > g.lregions[i].delarea.y2) { - int tmp = g.lregions[i].delarea.y1; + itmp = g.lregions[i].delarea.y1; g.lregions[i].delarea.y1 = g.lregions[i].delarea.y2; - g.lregions[i].delarea.y2 = tmp; + g.lregions[i].delarea.y2 = itmp; } } if (flp & 2) { g.lregions[i].inarea.x1 = FlipX(g.lregions[i].inarea.x1); g.lregions[i].inarea.x2 = FlipX(g.lregions[i].inarea.x2); if (g.lregions[i].inarea.x1 > g.lregions[i].inarea.x2) { - int tmp = g.lregions[i].inarea.x1; + itmp = g.lregions[i].inarea.x1; g.lregions[i].inarea.x1 = g.lregions[i].inarea.x2; - g.lregions[i].inarea.x2 = tmp; + g.lregions[i].inarea.x2 = itmp; } g.lregions[i].delarea.x1 = FlipX(g.lregions[i].delarea.x1); g.lregions[i].delarea.x2 = FlipX(g.lregions[i].delarea.x2); if (g.lregions[i].delarea.x1 > g.lregions[i].delarea.x2) { - int tmp = g.lregions[i].delarea.x1; + itmp = g.lregions[i].delarea.x1; g.lregions[i].delarea.x1 = g.lregions[i].delarea.x2; - g.lregions[i].delarea.x2 = tmp; + g.lregions[i].delarea.x2 = itmp; } } } @@ -422,40 +472,41 @@ boolean extras; sroom->ly = FlipY(sroom->ly); sroom->hy = FlipY(sroom->hy); if (sroom->ly > sroom->hy) { - int tmp = sroom->ly; + itmp = sroom->ly; sroom->ly = sroom->hy; - sroom->hy = tmp; + sroom->hy = itmp; } } if (flp & 2) { sroom->lx = FlipX(sroom->lx); sroom->hx = FlipX(sroom->hx); if (sroom->lx > sroom->hx) { - int tmp = sroom->lx; + itmp = sroom->lx; sroom->lx = sroom->hx; - sroom->hx = tmp; + sroom->hx = itmp; } } if (sroom->nsubrooms) for (i = 0; i < sroom->nsubrooms; i++) { struct mkroom *rroom = sroom->sbrooms[i]; + if (flp & 1) { rroom->ly = FlipY(rroom->ly); rroom->hy = FlipY(rroom->hy); if (rroom->ly > rroom->hy) { - int tmp = rroom->ly; + itmp = rroom->ly; rroom->ly = rroom->hy; - rroom->hy = tmp; + rroom->hy = itmp; } } if (flp & 2) { rroom->lx = FlipX(rroom->lx); rroom->hx = FlipX(rroom->hx); if (rroom->lx > rroom->hx) { - int tmp = rroom->lx; + itmp = rroom->lx; rroom->lx = rroom->hx; - rroom->hx = tmp; + rroom->hx = itmp; } } } @@ -472,7 +523,7 @@ boolean extras; /* the map */ if (flp & 1) { for (x = minx; x <= maxx; x++) - for (y = miny; y < (miny + ((maxy-miny+1) / 2)); y++) { + for (y = miny; y < (miny + ((maxy - miny + 1) / 2)); y++) { int ny = FlipY(y); flip_drawbridge_vertical(&levl[x][y]); @@ -492,7 +543,7 @@ boolean extras; } } if (flp & 2) { - for (x = minx; x < (minx + ((maxx-minx+1) / 2)); x++) + for (x = minx; x < (minx + ((maxx - minx + 1) / 2)); x++) for (y = miny; y <= maxy; y++) { int nx = FlipX(x); @@ -514,28 +565,43 @@ boolean extras; } if (extras) { - if (flp & 1) u.uy = FlipY(u.uy); - if (flp & 2) u.ux = FlipX(u.ux); + if (flp & 1) + u.uy = FlipY(u.uy), u.uy0 = FlipY(u.uy0); + if (flp & 2) + u.ux = FlipX(u.ux), u.ux0 = FlipX(u.ux0); } - fix_wall_spines(1, 0, COLNO-1, ROWNO-1); - + fix_wall_spines(1, 0, COLNO - 1, ROWNO - 1); + if (extras && flp) { + set_wall_state(); + flip_visuals(flp); /* after wall_spines; flips seenv and wall joins */ + } vision_reset(); } #undef FlipX #undef FlipY +/* randomly transpose top with bottom or left with right or both; + caller controls which transpositions are allowed */ void flip_level_rnd(flp, extras) int flp; boolean extras; { int c = 0; - if ((flp & 1) && rn2(2)) c |= 1; - if ((flp & 2) && rn2(2)) c |= 2; - if (c) flip_level(c, extras); + /* TODO? + * Might change rn2(2) to !rn2(3) or (rn2(5) < 2) in order to bias + * the outcome towards the traditional orientation. + */ + if ((flp & 1) && rn2(2)) + c |= 1; + if ((flp & 2) && rn2(2)) + c |= 2; + + if (c) + flip_level(c, extras); }