diff --git a/dat/opthelp b/dat/opthelp index 06fbf092d..eb9aeeb84 100644 --- a/dat/opthelp +++ b/dat/opthelp @@ -177,6 +177,12 @@ whatis_coord controls whether to include map coordinates when [n] map -- (map column x=0 is not used) screen -- [row,column] (row is offset to match tty usage) none -- no coordinates shown. +whatis_filter controls how to filter eligible map coordinates when [n] + getting a map location for eg. the travel command. + Value is the one of + n - no filtering + v - locations in view only + a - locations in same area (room, corridor, etc) Compound options which may be set only on startup are: diff --git a/dat/tribute b/dat/tribute index 05165e5e3..0b6f58fd6 100644 --- a/dat/tribute +++ b/dat/tribute @@ -5907,13 +5907,231 @@ betray 'em, quick as a wink. 'Cos that's villaining.' %e title # # +# _The_Amazing_Maurice_and_His_Educated_Rodents_ (sometimes spelled with +# "his" uncapitalized--the book itself uses all uppercase on both the +# cover and the title page so doesn't help resolve which is correct...) +# was the first of six Discworld books marketed for "Young Adults" (at +# least in the US), ages 12 to 16 give or take, so tended to be stocked +# on different shelves from the rest of Discworld in book stores and +# libraries. In the UK, _The_Amazing_Maurice..._ won the Carnegie Medal +# which is awarded for best children's book of the year. +# (The other Young Adult Discworld books are the five Tiffany Aching ones.) # -%title The Amazing Maurice and his Educated Rodents (1) +# _The_Amazing_Maurice..._ may well be the most serious Discworld book. +# (Don't worry, it has lots of humor/humour in it....) +# +%title The Amazing Maurice and His Educated Rodents (10) +# p. 68 (Harperteen edition; _Mr._Bunnsy_Has_an_Adventure_ is a book +# within the book, and a brief quote is shown at the beginning +# of each chapter. This one is from the start of chapter 4.) %passage 1 -The important thing about adventures, thought Mr Bunnsy, was that they +The important thing about adventures, thought Mr. Bunnsy, was that they shouldn't be so long as to make you miss mealtimes. - [The Amazing Maurice and his Educated Rodents, by Terry Pratchett] + [The Amazing Maurice and His Educated Rodents, by Terry Pratchett] +%e passage +# p. 9 (passage starts mid-paragraph) +%passage 2 +"Stealing from a thief isn't stealing, 'cos it cancels out." + + [The Amazing Maurice and His Educated Rodents, by Terry Pratchett] +%e passage +# pp. 11-12 (rats became intelligent from eating wizards' trash just outside +# one of the walls of Unseen University; Maurice insists that he +# never did that, implying that he'd eaten some of the rats instead +# [never explicitly stated] before he became intelligent himself) +%passage 3 +They said he was amazing. The Amazing Maurice, they said. He'd never +meant to be amazing. It just happened. + +He'd realized something was odd that day, just after lunch, when he'd +looked into a reflection in a puddle and thought, /that's me/. He'd never +been /aware/ of himself before. Of course it was hard to remember /how/ +he'd thought before becoming amazing. It seemed to him that his mind had +been just a kind of soup. + +And then there had been the rats, who lived under the rubbish heap in one +corner of his territory. He'd realized there was something educated +about the rats when he'd jumped on one and it'd said, "Can we talk about +this?" and part of his amazing new brain had told him you couldn't eat +someone who could talk. At least, not until you'd heard what it'd got +to say. + + [The Amazing Maurice and His Educated Rodents, by Terry Pratchett] +%e passage +# p. 32 (Maurice the cat, Keith the human boy, and the intelligent rat clan are +# in the town of Bad Blintz; people are queuing up for rationed food) +%passage 4 +"Shall we line up too?" asked the kid. + +"I shouldn't think so," said Maurice carefully. + +"Why not?" + +"See those men on the door? They look like the Watch. They've got big +truncheons. And everyone's showing them a bit of paper as they go past. +I don't like the look of that," said Maurice. "That looks like +/government/ to me." + +"We haven't done anything wrong," said the kid. "Not here, anyway." + +"You never know, with governments," said Maurice. "Just stay here kid. +I'll take a look." + + [The Amazing Maurice and His Educated Rodents, by Terry Pratchett] +%e passage +# p. 52 (speaker is Darktan, the traps expert; "Number One" platoon seems +# like an obvious joke here--missed deliberately or accidentally?) +%passage 5 +"All right, Number Three platoon, you're on widdling duty," he said. "Go +and have a good drink." + + [The Amazing Maurice and His Educated Rodents, by Terry Pratchett] +%e passage +# p. 110 (opening quote for chapter 6) +%passage 6 +There were big adventures and small adventures, Mr. Bunnsy knew. You +didn't get told what size they were going to be before you started. +Sometimes you could have a big adventure even when you were standing +still. + + [The Amazing Maurice and His Educated Rodents, by Terry Pratchett] +%e passage +# pp. 127-128 (searching for a secret door...) +%passage 7 +Malicia leaned against the wall with incredible nonchalance. + +There was not a click. A panel in the floor did not slide back. + +"Probably the wrong place," she said. "I'll just rest my arm innocently +on this coat hook." + +A sudden door in the wall completely failed to happen. + +"Of course, it'd help if there was an ornate candlestick," said Malicia. +"They're always a surefire secret-passage lever. Every adventurer knows +that." + +"There isn't a candlestick," said Maurice. + +"I know. Some people totally fail to have any /idea/ of how to design a +proper secret passage," said Malicia. She leaned against another piece +of wall, which had no affect whatsoever. + +"I don't think you'll find it that way," said Keith, who was carefully +examining a trap. + +"Oh? Won't I?" said Malicia. "Well at least I'm being /constructive/ +about things! Where would you look, if you're such an expert?" + +"Why is there a rat hole in a rat catcher's shed?" said Keith. "It smells +of dead rats and wet dogs and poison. I wouldn't come near this place, +if I was a rat." + +Malicia glared at him. Then her face wrapped itself in an expression of +acute concentration, as if she was trying out several ideas in her head. + +"Ye-es," she said. "That usually works, in stories. It's often the stupid +person who comes up with the good idea by accident." + +She crouched down and peered into the hole. + +"There's a sort of little lever," she said. "I'll just give it a little +push...." + +There was a /clonk/ under the floor, part of it swung back, and Keith +dropped out of sight. + +"Oh, yes," said Malicia. "I thought something like that would probably +happen." + + [The Amazing Maurice and His Educated Rodents, by Terry Pratchett] +%e passage +# p. 231 (passage ends mid-paragraph) +%passage 8 +He had to admit that he was cleverer at plans than at underground +navigation. He wasn't exactly lost, because cats never get lost. He +merely didn't know where everything else was. + + [The Amazing Maurice and His Educated Rodents, by Terry Pratchett] +%e passage +# pp. 298-300 (Keith has challanged the professional rat piper and offered +# to rid the town of rats for a much lower price; Sardines is +# one of the Educated Rodents, known for dancing all the time; +# "hwun/two/three/four/" is run-together "one /two/ three /four/"; +# quite a long passage primarily for the 'a bit more grimy' gag) +%passage 9 +[...] +"But first I shall need to borrow a pipe," Keith went on. + +"You haven't got one?" asked the mayor. + +"It got broken." + +Corporal Knopf nudged the mayor. "I've got a trombone from when I was in +the army," he said. "It won't take a moment to get it." + +The rat piper burst out laughing. + +"Doesn't that count?" asked the mayor, as Corporal Knopf hurried off. + +"What? A trombone for charming rats? No, no, let him try. Can't blame +a kid for trying. Good with a trombone, are you?" + +"I don't know," said Keith. + +"What do you mean, you don't know?" + +"I meant I've never played one. I'd be a lot happier with a flute, +trumpet, piccolo, cornet, or Lancre bagpipe, but I've seen people playing +the trombone, and it doesn't look too difficult. It's only an overgrown +trumpet, really." + +"Hah!" said the piper. "This I'd like to see--but not hear." + +The Watch came running back, rubbing a battered trombone with his sleave +and therefore making it just a bit more grimy. Keith took it, wiped the +mouthpiece, put it to his mouth, moved the slide a few times, and then +blew one long note. + +"Seems to work," he said. "I expect I can learn as I go along." He gave +the rat piper a brief smile. "Do you want to go first?" + +"You won't charm one rat with that mess, kid," said the piper, "but I'm +glad I'm here to see you try." + +Keith gave him a smile again, took a breath, and played. + +There was a tune there. The instrument squeaked and wheezed, because +Corporal Knopf had occasionally used the thing as a hammer, but there was +a tune, quite fast, almost jaunty. You could tap your feet to it. + +Someone tapped his feet to it. + +Sardines emerged from a crack in a nearby wall, going "hwun/two/three/four/" +under his breath. The crowd watched him dance ferociously across the +cobbles until he disappeared into a drain. Then they broke into applause. + +The piper looked at Keith. + +"Did that one have a /hat/ on?" he asked. + +"I didn't notice," said Keith. "Your go." + + [The Amazing Maurice and His Educated Rodents, by Terry Pratchett] +%e passage +# pp. 309-310 +%passage 10 +"You really /can/ talk? You can think?" asked the mayor. + +Darktan looked up at him. It had been a long night. He didn't want to +remember any of it. And now it was going to be a longer, harder day. +He took a deep breath. + +"Here's what I suggest," he said. "You pretend that rats can think, and +I'll promise to pretend that humans can think, too." + + [The Amazing Maurice and His Educated Rodents, by Terry Pratchett] %e passage %e title # diff --git a/doc/Guidebook.mn b/doc/Guidebook.mn index 32e71245f..9805e32c0 100644 --- a/doc/Guidebook.mn +++ b/doc/Guidebook.mn @@ -2927,14 +2927,32 @@ The option is also used with the `/m', `/M', `/o', and `/O' sub-commands of `/', where the `none' setting is overridden with `map'. -.lp whatis_inview +.lp whatis_filter When getting a location on the map, and using the keys to cycle through -next and previous targets, limit the possible targets to those in view. -(default off) +next and previous targets, allows filtering the possible targets. +.lp "" +.sd +.si +.CC n "no filtering [default]" +.CC v "in view only" +.CC a "in same area only" +.ei +.ed +.lp "" +The area-filter tries to be slightly predictive - if you're standing on a doorway, +it will consider the area on the side of the door you were last moving towards. +.lp "" +Filtering can also be changed when getting a location with the ``getpos.filter'' +key. .lp whatis_menu When getting a location on the map, and using a key to cycle through next and previous targets, use a menu instead to pick a target. (default off) +.lp whatis_moveskip +When getting a location on the map, and using shifted movement keys or +meta-digit keys to fast-move, instead of moving 8 units at a time, +move by skipping the same glyphs. +(default off) .lp windowtype Select which windowing system to use, such as ``tty'' or ``X11'' (default depends on version). @@ -3246,8 +3264,12 @@ When asked for a location, the key to go to next closest object. Default is 'o'. When asked for a location, the key to go to previous closest object. Default is 'O'. .lp getpos.menu When asked for a location, and using one of the next or previous keys to cycle through targets, toggle showing a menu instead. Default is '!'. -.lp getpos.inview -When asked for a location, and using one of the next or previous keys to cycle through targets, toggle limiting possible targets to those in view only. Default is '"'. +.lp getpos.moveskip +When asked for a location, and using the shifted movement keys or meta-digit keys to fast-move around, move by skipping the same glyphs instead of by 8 units. Default is '*'. +.lp getpos.filter +When asked for a location, change the filtering mode when using one of the next +or previous keys to cycle through targets. Toggles between no filtering, in view +only, and in the same area only. Default is '"'. .lp getpos.pick When asked for a location, the key to choose the location, and possibly ask for more info. Default is '.'. .lp getpos.pick.once @@ -3264,6 +3286,10 @@ When asked for a location, the key to go to next closest unexplored location. De When asked for a location, the key to go to previous closest unexplored location. Default is 'X'. .lp getpos.valid When asked for a location, the key to go to show valid target locations. Default is '$'. +.lp getpos.valid.next +When asked for a location, the key to go to next closest valid location. Default is 'z'. +.lp getpos.valid.prev +When asked for a location, the key to go to previous closest valid location. Default is 'Z'. .lp nopickup Prefix key to move without picking up items. Default is 'm'. .lp redraw @@ -3724,6 +3750,12 @@ was interrupted. .lp whatis_coord:compass When targeting with cursor, describe the cursor position with coordinates relative to your character. +.lp whatis_filter:area +When targeting with cursor, filter possible locations so only those in +the same area (eg. same room, or same corridor) are considered. +.lp whatis_moveskip +When targeting with cursor and using fast-move, skip the same glyphs instead +of moving 8 units at a time. .lp nostatus_updates Prevent updates to the status lines at the bottom of the screen, if your screen-reader reads those lines. The same information can be diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex index 07cc90964..c09cc7d1e 100644 --- a/doc/Guidebook.tex +++ b/doc/Guidebook.tex @@ -3561,15 +3561,38 @@ the `{\tt /m}', `{\tt /M}', `{\tt /o}', and `{\tt /O}' sub-commands of `{\tt /}', where the `{\it none\/}' setting is overridden with `{\it map}'. %.lp -\item[\ib{whatis\verb+_+inview}] +\item[\ib{whatis\verb+_+filter}] When getting a location on the map, and using the keys to cycle through -next and previous targets, limit the possible targets to those in view. -(default off) +next and previous targets, allows filtering the possible targets. +(default none) +%.lp "" +The possible settings are: + +%.sd +%.si +{\tt n} --- \verb#no filtering#;\\ +{\tt v} --- \verb#in view only#;\\ +{\tt a} --- \verb#in same area (room, corridor, etc)#. +%.ei +%.ed +%.lp "" +The area-filter tries to be slightly predictive - if you're standing on a doorway, +it will consider the area on the side of the door you were last moving towards. +%.lp "" +Filtering can also be changed when getting a location with the ``getpos.filter'' +key. +%.lp \item[\ib{whatis\verb+_+menu}] When getting a location on the map, and using a key to cycle through next and previous targets, use a menu instead to pick a target. (default off) %.lp +\item[\ib{whatis\verb+_+moveskip}] +When getting a location on the map, and using shifted movement keys or +meta-digit keys to fast-move, instead of moving 8 units at a time, +move by skipping the same glyphs. +(default off) +%.lp \item[\ib{windowtype}] Select which windowing system to use, such as ``{\tt tty}'' or ``{\tt X11}'' (default depends on version). @@ -3974,8 +3997,11 @@ When asked for a location, the key to go to previous closest object. Default is \item{\bb{getpos.menu}} When asked for a location, and using one of the next or previous keys to cycle through targets, toggle showing a menu instead. Default is '{\tt !}'. %.lp -\item{\bb{getpos.inview}} -When asked for a location, and using one of the next or previous keys to cycle through targets, toggle limiting possible targets to those in view only. Default is '{\tt "}'. +\item{\bb{getpos.moveskip}} +When asked for a location, and using the shifted movement keys or meta-digit keys to fast-move around, move by skipping the same glyphs instead of by 8 units. Default is ``{\tt *}''. +%.lp +\item{\bb{getpos.filter}} +When asked for a location, change the filtering mode when using one of the next or previous keys to cycle through targets. Toggles between no filtering, in view only, and in the same area only. Default is '{\tt "}'. %.lp \item{\bb{getpos.pick}} When asked for a location, the key to choose the location, and possibly ask for more info. Default is ``{\tt .}''. @@ -4001,6 +4027,12 @@ When asked for a location, the key to go to previous closest unexplored location \item{\bb{getpos.valid}} When asked for a location, the key to go to show valid target locations. Default is ``{\tt \$}''. %.lp +\item{\bb{getpos.valid.next}} +When asked for a location, the key to go to next closest valid location. Default is ``{\tt z}''. +%.lp +\item{\bb{getpos.valid.prev}} +When asked for a location, the key to go to previous closest valid location. Default is ``{\tt Z}''. +%.lp \item{\bb{nopickup}} Prefix key to move without picking up items. Default is ``{\tt m}''. %.lp @@ -4528,6 +4560,14 @@ was interrupted. When targeting with cursor, describe the cursor position with coordinates relative to your character. %.lp +\item[\ib{whatis\verb+_+filter:area}] +When targeting with cursor, filter possible locations so only those in +the same area (eg. same room, or same corridor) are considered. +%.lp +\item[\ib{whatis\verb+_+moveskip}] +When targeting with cursor and using fast-move, skip the same glyphs instead +of moving 8 units at a time. +%.lp \item[\ib{nostatus\verb+_+updates}] Prevent updates to the status lines at the bottom of the screen, if your screen-reader reads those lines. The same information can be diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 30ffed891..72b2d2d81 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -404,6 +404,11 @@ fix the 'A' command to have the 'D' command's fix for C331-1 (quirk for menustyle:Combination; if user included 'a' in "which object classes?" response, to operate on applicable all items, there would still be a followup menu asking to choose specific items) +eating 1 tin from stack of N (for N >= 2) on shop's floor forced hero to buy 2 +using a cursed whistle in a vault will summon the guard immediately +throne room's throne is occupied by a king +using a grappling hook and getting pulled toward the target into water would + drown hero without any chance to crawl out Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository @@ -453,6 +458,9 @@ attempting to name an item as an artifact and failing via hand slip violates illiterate conduct crashes for 'A' above were downgraded to impossible "cursed without otmp" wizhelp: ^O is #overview in wizard mode too; #wizwhere shows dungeon layout +wishing for tins sometimes yielded a tin wand +replace the fix for preventing putting on a helm of opposite alignment from + causing wielded Excalibur from blasting hero twice Platform- and/or Interface-Specific Fixes @@ -492,6 +500,9 @@ unix: Makefile.{src,utl} ignored CPPFLAGS which is expanded by the default .c win32gui: getversionstring() was overflowing the provided Help About buffer win32gui: guard against buffer overflow in in mswin_getlin() win32gui: handle menu_color attribute +win32gui: name-from-discoveries list menu selector characters were punctuation + instead of letters, repeated for each class; caused by the core bug + of erroneously specifying space as a selector for class header lines MacOSX: initial binary release was built from out of date source code that had 'BETA' and 'DEBUG' inappropriately enabled MacOSX: force TIMED_DELAY build option on so that 'runmode' run-time option @@ -585,6 +596,10 @@ random horses have a tiny chance of being generated saddled give feedback just before timed levitation runs out travel accepts 'm' (request menu) prefix pressing a or A when cursor positioning shows menu of "interesting" features +pressing z or Z when cursor positioning cycles through valid locations for + jumping, hitting with polearm, or casting a stinking cloud +when moving a cursor for a jump, polearm, or stinking cloud targeting, show + if the location is illegal, if "autodescribe" is on wizard-mode command #wizmakemap to recreate the current level 'goldX' boolean option to treat gold pieces as X (vs U) during BUCX filtering (should be persistent but is reset each save/restore cycle in order @@ -593,6 +608,8 @@ for menustyle:Traditional and Combination, support BUCX filtering for item pick-up and container put-in and take-out; also for object IDing for menustyle:Full and Traditional and Combination, support BUCX filtering for the 'A' command +option whatis_filter to set filtering for eligible map locations when cursor + positioning Platform- and/or Interface-Specific New Features diff --git a/include/decl.h b/include/decl.h index 18b37c295..a418d20de 100644 --- a/include/decl.h +++ b/include/decl.h @@ -389,6 +389,14 @@ E char *fqn_prefix_names[PREFIX_COUNT]; E NEARDATA struct savefile_info sfcap, sfrestinfo, sfsaveinfo; +struct opvar { + xchar spovartyp; /* one of SPOVAR_foo */ + union { + char *str; + long l; + } vardata; +}; + struct autopickup_exception { struct nhregex *regex; char *pattern; diff --git a/include/extern.h b/include/extern.h index dcbf8f003..e7a941889 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 extern.h $NHDT-Date: 1496959470 2017/06/08 22:04:30 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.591 $ */ +/* NetHack 3.6 extern.h $NHDT-Date: 1502753404 2017/08/14 23:30:04 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.600 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -384,9 +384,9 @@ E void NDECL(heal_legs); /* ### do_name.c ### */ E char *FDECL(coord_desc, (int, int, char *, CHAR_P)); -E boolean FDECL(getpos_menu, (coord *, BOOLEAN_P, int)); +E boolean FDECL(getpos_menu, (coord *, int)); E int FDECL(getpos, (coord *, BOOLEAN_P, const char *)); -E void FDECL(getpos_sethilite, (void (*f)(int))); +E void FDECL(getpos_sethilite, (void (*f)(int), boolean (*d)(int,int))); E void FDECL(new_mname, (struct monst *, int)); E void FDECL(free_mname, (struct monst *)); E void FDECL(new_oname, (struct obj *, int)); @@ -1312,6 +1312,7 @@ E struct obj *FDECL(obj_nexto, (struct obj *)); E struct obj *FDECL(obj_nexto_xy, (struct obj *, int, int, BOOLEAN_P)); E struct obj *FDECL(obj_absorb, (struct obj **, struct obj **)); E struct obj *FDECL(obj_meld, (struct obj **, struct obj **)); +E void FDECL(pudding_merge_message, (struct obj *, struct obj *)); /* ### mkroom.c ### */ @@ -1565,6 +1566,7 @@ E int FDECL(rnd_misc_item, (struct monst *)); E boolean FDECL(searches_for_item, (struct monst *, struct obj *)); E boolean FDECL(mon_reflects, (struct monst *, const char *)); E boolean FDECL(ureflects, (const char *, const char *)); +E void FDECL(mcureblindness, (struct monst *, BOOLEAN_P)); E boolean FDECL(munstone, (struct monst *, BOOLEAN_P)); E boolean FDECL(munslime, (struct monst *, BOOLEAN_P)); @@ -1624,6 +1626,9 @@ E char *FDECL(simple_typename, (int)); E boolean FDECL(obj_is_pname, (struct obj *)); E char *FDECL(distant_name, (struct obj *, char *(*)(OBJ_P))); E char *FDECL(fruitname, (BOOLEAN_P)); +E struct fruit *FDECL(fruit_from_indx, (int)); +E struct fruit *FDECL(fruit_from_name, (const char *, BOOLEAN_P, int *)); +E void FDECL(reorder_fruit, (BOOLEAN_P)); E char *FDECL(xname, (struct obj *)); E char *FDECL(mshot_xname, (struct obj *)); E boolean FDECL(the_unique_obj, (struct obj *)); @@ -1833,12 +1838,6 @@ E void VDECL(There, (const char *, ...)) PRINTF_F(1, 2); E void VDECL(verbalize, (const char *, ...)) PRINTF_F(1, 2); E void VDECL(raw_printf, (const char *, ...)) PRINTF_F(1, 2); E void VDECL(impossible, (const char *, ...)) PRINTF_F(1, 2); -E const char *FDECL(align_str, (ALIGNTYP_P)); -E void FDECL(mstatusline, (struct monst *)); -E void NDECL(ustatusline); -E void NDECL(self_invis_message); -E char *FDECL(piousness, (BOOLEAN_P, const char *)); -E void FDECL(pudding_merge_message, (struct obj *, struct obj *)); /* ### polyself.c ### */ @@ -1876,6 +1875,7 @@ E void FDECL(make_stoned, (long, const char *, int, const char *)); E void FDECL(make_vomiting, (long, BOOLEAN_P)); E boolean FDECL(make_hallucinated, (long, BOOLEAN_P, long)); E void FDECL(make_deaf, (long, BOOLEAN_P)); +E void NDECL(self_invis_message); E int NDECL(dodrink); E int FDECL(dopotion, (struct obj *)); E int FDECL(peffects, (struct obj *)); @@ -1932,6 +1932,10 @@ E void NDECL(clearpriests); E void FDECL(restpriest, (struct monst *, BOOLEAN_P)); E void FDECL(newepri, (struct monst *)); E void FDECL(free_epri, (struct monst *)); +E const char *FDECL(align_str, (ALIGNTYP_P)); +E char *FDECL(piousness, (BOOLEAN_P, const char *)); +E void FDECL(mstatusline, (struct monst *)); +E void NDECL(ustatusline); /* ### quest.c ### */ @@ -2250,6 +2254,11 @@ 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 opvar *)); +E struct opvar *FDECL(selection_opvar, (char *)); +E void FDECL(opvar_free_x, (struct opvar *)); +E void FDECL(set_selection_floodfillchk, (int FDECL((*), (int,int)))); +E void FDECL(selection_floodfill, (struct opvar *, int, int, BOOLEAN_P)); /* ### spell.c ### */ @@ -2505,6 +2514,7 @@ E int FDECL(hide_privileges, (BOOLEAN_P)); E void FDECL(newegd, (struct monst *)); E void FDECL(free_egd, (struct monst *)); E boolean FDECL(grddead, (struct monst *)); +E void NDECL(vault_summon_gd); E char FDECL(vault_occupied, (char *)); E void NDECL(invault); E int FDECL(gd_move, (struct monst *)); diff --git a/include/flag.h b/include/flag.h index 668f9cce7..ac3844fc3 100644 --- a/include/flag.h +++ b/include/flag.h @@ -176,6 +176,14 @@ struct sysflag { #define GPCOORDS_COMFULL 'f' #define GPCOORDS_SCREEN 's' +enum getloc_filters { + GFILTER_NONE = 0, + GFILTER_VIEW, + GFILTER_AREA, + + NUM_GFILTER +}; + struct instance_flags { /* stuff that really isn't option or platform related. They are * set and cleared during the game to control the internal @@ -194,8 +202,9 @@ struct instance_flags { #define TER_MON 0x08 #define TER_DETECT 0x10 /* detect_foo magic rather than #terrain */ boolean getloc_travelmode; - boolean getloc_limitview; + int getloc_filter; /* GFILTER_foo */ boolean getloc_usemenu; + boolean getloc_moveskip; coord travelcc; /* coordinates for travel_cache */ boolean window_inited; /* true if init_nhwindows() completed */ boolean vision_inited; /* true if vision is ready */ @@ -483,9 +492,12 @@ enum nh_keyfunc { NHKF_GETPOS_UNEX_PREV, NHKF_GETPOS_INTERESTING_NEXT, NHKF_GETPOS_INTERESTING_PREV, + NHKF_GETPOS_VALID_NEXT, + NHKF_GETPOS_VALID_PREV, NHKF_GETPOS_HELP, NHKF_GETPOS_MENU, NHKF_GETPOS_LIMITVIEW, + NHKF_GETPOS_MOVESKIP, NUM_NHKF }; @@ -496,6 +508,7 @@ enum gloctypes { GLOC_DOOR, GLOC_EXPLORE, GLOC_INTERESTING, + GLOC_VALID, NUM_GLOCS }; diff --git a/include/hack.h b/include/hack.h index dffb26c5c..c4691ae26 100644 --- a/include/hack.h +++ b/include/hack.h @@ -34,6 +34,9 @@ enum encumbrance_types { /* weight increment of heavy iron ball */ #define IRON_BALL_W_INCR 160 +/* number of turns it takes for vault guard to show up */ +#define VAULT_GUARD_TIME 30 + /* hunger states - see hu_stat in eat.c */ enum hunger_state_types { SATIATED = 0, diff --git a/include/permonst.h b/include/permonst.h index a5c4555c0..f70db03f0 100644 --- a/include/permonst.h +++ b/include/permonst.h @@ -70,7 +70,7 @@ extern NEARDATA struct permonst mons[]; /* the master list of monster types */ #define FAST_SPEED 15 #define VERY_FAST 24 -#define NON_PM PM_PLAYERMON /* "not a monster" */ +#define NON_PM (-1) /* "not a monster" */ #define LOW_PM (NON_PM + 1) /* first monster in mons[] */ #define SPECIAL_PM PM_LONG_WORM_TAIL /* [normal] < ~ < [special] */ /* mons[SPECIAL_PM] through mons[NUMMONS-1], inclusive, are diff --git a/include/prop.h b/include/prop.h index cb4cd3fde..3bbc7182f 100644 --- a/include/prop.h +++ b/include/prop.h @@ -7,7 +7,7 @@ /*** What the properties are *** * - * note: propertynames[] array in timeout.c must be kept in synch with these. + * note: propertynames[] array in timeout.c has string values for these. * Property #0 is not used. */ /* Resistances to troubles */ diff --git a/include/rm.h b/include/rm.h index 02b1947db..9283ee960 100644 --- a/include/rm.h +++ b/include/rm.h @@ -235,6 +235,12 @@ enum screen_symbols { #define is_cmap_drawbridge(i) ((i) >= S_vodbridge && (i) <= S_hcdbridge) #define is_cmap_door(i) ((i) >= S_vodoor && (i) <= S_hcdoor) #define is_cmap_wall(i) ((i) >= S_stone && (i) <= S_trwall) +#define is_cmap_room(i) ((i) >= S_room && (i) <= S_darkroom) +#define is_cmap_corr(i) ((i) >= S_corr && (i) <= S_litcorr) +#define is_cmap_furniture(i) ((i) >= S_upstair && (i) <= S_fountain) +#define is_cmap_water(i) ((i) == S_pool || (i) == S_water) +#define is_cmap_lava(i) ((i) == S_lava) + struct symdef { uchar sym; diff --git a/include/sp_lev.h b/include/sp_lev.h index 7a5054899..87fe076df 100644 --- a/include/sp_lev.h +++ b/include/sp_lev.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 sp_lev.h $NHDT-Date: 1470212260 2016/08/03 08:17:40 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.17 $ */ +/* NetHack 3.6 sp_lev.h $NHDT-Date: 1501803105 2017/08/03 23:31:45 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.21 $ */ /* Copyright (c) 1989 by Jean-Christophe Collet */ /* NetHack may be freely redistributed. See license for details. */ @@ -257,14 +257,6 @@ enum opcode_defs { #define SP_MAPCHAR_LIT(l) ((((l) >> 8) & 0xffff) - 10) #define SP_MAPCHAR_PACK(typ, lit) (((10 + (lit)) << 8) | ((typ) & 0xff)) -struct opvar { - xchar spovartyp; /* one of SPOVAR_foo */ - union { - char *str; - long l; - } vardata; -}; - struct splev_var { struct splev_var *next; char *name; @@ -493,61 +485,52 @@ struct lc_breakdef { #ifdef SPEC_LEV /* compiling lev_comp rather than nethack */ #ifdef USE_OLDARGS -#undef VA_ARGS -#undef VA_DECL -#undef VA_DECL2 -#undef VA_SHIFT +#ifndef VA_TYPE +typedef const char *vA; +#define VA_TYPE +#endif +#undef VA_ARGS /* redefine with the maximum number actually used */ +#undef VA_SHIFT /* ditto */ +#undef VA_PASS1 #define VA_ARGS \ arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, \ arg12, arg13, arg14 -#define VA_DECL(typ1, var1) \ - (var1, VA_ARGS) typ1 var1; \ - char *arg1, *arg2, *arg3, *arg4, *arg5, *arg6, *arg7, *arg8, *arg9, \ - *arg10, *arg11, *arg12, *arg13, *arg14; \ - { -#define VA_DECL2(typ1, var1, typ2, var2) \ - (var1, var2, VA_ARGS) typ1 var1; \ - typ2 var2; \ - char *arg1, *arg2, *arg3, *arg4, *arg5, *arg6, *arg7, *arg8, *arg9, \ - *arg10, *arg11, *arg12, *arg13, *arg14; \ - { -/* unlike in the core, lev_comp's VA_SHIFT is completely safe, - because callers always pass all these arguments */ +/* Unlike in the core, lev_comp's VA_SHIFT should be completely safe, + because callers always pass all these arguments. */ #define VA_SHIFT() \ (arg1 = arg2, arg2 = arg3, arg3 = arg4, arg4 = arg5, arg5 = arg6, \ arg6 = arg7, arg7 = arg8, arg8 = arg9, arg9 = arg10, arg10 = arg11, \ arg11 = arg12, arg12 = arg13, arg13 = arg14, arg14 = 0) /* standard NULL may be either (void *)0 or plain 0, both of which would need to be explicitly cast to (char *) here */ -typedef char *Va; #define VA_PASS1(a1) \ - (Va) a1, (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0, \ - (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0 + (vA) a1, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, \ + (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0 #define VA_PASS2(a1, a2) \ - (Va) a1, (Va) a2, (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0, \ - (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0 + (vA) a1, (vA) a2, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, \ + (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0 #define VA_PASS3(a1, a2, a3) \ - (Va) a1, (Va) a2, (Va) a3, (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0, \ - (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0 + (vA) a1, (vA) a2, (vA) a3, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, \ + (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0 #define VA_PASS4(a1, a2, a3, a4) \ - (Va) a1, (Va) a2, (Va) a3, (Va) a4, (Va) 0, (Va) 0, (Va) 0, (Va) 0, \ - (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0 + (vA) a1, (vA) a2, (vA) a3, (vA) a4, (vA) 0, (vA) 0, (vA) 0, (vA) 0, \ + (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0 #define VA_PASS5(a1, a2, a3, a4, a5) \ - (Va) a1, (Va) a2, (Va) a3, (Va) a4, (Va) a5, (Va) 0, (Va) 0, (Va) 0, \ - (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0 + (vA) a1, (vA) a2, (vA) a3, (vA) a4, (vA) a5, (vA) 0, (vA) 0, (vA) 0, \ + (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0 #define VA_PASS7(a1, a2, a3, a4, a5, a6, a7) \ - (Va) a1, (Va) a2, (Va) a3, (Va) a4, (Va) a5, (Va) a6, (Va) a7, (Va) 0, \ - (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0 + (vA) a1, (vA) a2, (vA) a3, (vA) a4, (vA) a5, (vA) a6, (vA) a7, (vA) 0, \ + (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0 #define VA_PASS8(a1, a2, a3, a4, a5, a6, a7, a8) \ - (Va) a1, (Va) a2, (Va) a3, (Va) a4, (Va) a5, (Va) a6, (Va) a7, (Va) a8, \ - (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0 + (vA) a1, (vA) a2, (vA) a3, (vA) a4, (vA) a5, (vA) a6, (vA) a7, (vA) a8, \ + (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0 #define VA_PASS9(a1, a2, a3, a4, a5, a6, a7, a8, a9) \ - (Va) a1, (Va) a2, (Va) a3, (Va) a4, (Va) a5, (Va) a6, (Va) a7, (Va) a8, \ - (Va) a9, (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0 + (vA) a1, (vA) a2, (vA) a3, (vA) a4, (vA) a5, (vA) a6, (vA) a7, (vA) a8, \ + (vA) a9, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0 #define VA_PASS14(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, \ a14) \ - (Va) a1, (Va) a2, (Va) a3, (Va) a4, (Va) a5, (Va) a6, (Va) a7, (Va) a8, \ - (Va) a9, (Va) a10, (Va) a11, (Va) a12, (Va) a13, (Va) a14 + (vA) a1, (vA) a2, (vA) a3, (vA) a4, (vA) a5, (vA) a6, (vA) a7, (vA) a8, \ + (vA) a9, (vA) a10, (vA) a11, (vA) a12, (vA) a13, (vA) a14 #else /*!USE_OLDARGS*/ /* USE_STDARG and USE_VARARGS don't need to pass dummy arguments or cast real ones */ diff --git a/include/system.h b/include/system.h index 21ccf8b72..f7a3d2606 100644 --- a/include/system.h +++ b/include/system.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 system.h $NHDT-Date: 1449269772 2015/12/04 22:56:12 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.12 $ */ +/* NetHack 3.6 system.h $NHDT-Date: 1501723401 2017/08/03 01:23:21 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.13 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -489,8 +489,17 @@ E int FDECL(vprintf, (const char *, va_list)); #endif #endif #else +#ifdef vprintf +#undef vprintf +#endif #define vprintf printf +#ifdef vfprintf +#undef vfprintf +#endif #define vfprintf fprintf +#ifdef vsprintf +#undef vsprintf +#endif #define vsprintf sprintf #endif #endif /* NEED_VARARGS */ diff --git a/include/tradstdc.h b/include/tradstdc.h index 26ce81ad5..8ab152b52 100644 --- a/include/tradstdc.h +++ b/include/tradstdc.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 tradstdc.h $NHDT-Date: 1448210011 2015/11/22 16:33:31 $ $NHDT-Branch: master $:$NHDT-Revision: 1.27 $ */ +/* NetHack 3.6 tradstdc.h $NHDT-Date: 1501803107 2017/08/03 23:31:47 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.29 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -100,6 +100,7 @@ #define VA_END() \ va_end(the_args); \ } +#define VA_PASS1(a1) a1 #if defined(ULTRIX_PROTO) && !defined(_VA_LIST_) #define _VA_LIST_ /* prevents multiple def in stdio.h */ #endif @@ -125,18 +126,27 @@ #define VA_END() \ va_end(the_args); \ } +#define VA_PASS1(a1) a1 #else /*USE_OLDARGS*/ +/* + * CAVEAT: passing double (including float promoted to double) will + * almost certainly break this, as would any integer type bigger than + * sizeof (char *). + * NetHack avoids floating point, and any configuration able to use + * 'long long int' or I64P32 or the like should be using USE_STDARG. + */ +#ifndef VA_TYPE +typedef const char *vA; +#define VA_TYPE +#endif #define VA_ARGS arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 #define VA_DECL(typ1, var1) \ - (var1, VA_ARGS) typ1 var1; \ - char *arg1, *arg2, *arg3, *arg4, *arg5, *arg6, *arg7, *arg8, *arg9; \ + (var1, VA_ARGS) typ1 var1; vA VA_ARGS; \ { #define VA_DECL2(typ1, var1, typ2, var2) \ - (var1, var2, VA_ARGS) typ1 var1; \ - typ2 var2; \ - char *arg1, *arg2, *arg3, *arg4, *arg5, *arg6, *arg7, *arg8, *arg9; \ + (var1, var2, VA_ARGS) typ1 var1; typ2 var2; vA VA_ARGS; \ { #define VA_START(x) #define VA_INIT(var1, typ1) @@ -151,9 +161,12 @@ */ #define VA_SHIFT() \ (arg1 = arg2, arg2 = arg3, arg3 = arg4, arg4 = arg5, arg5 = arg6, \ - arg6 = arg7, arg7 = arg8, arg8 = arg9) + arg6 = arg7, arg7 = arg8, arg8 = arg9, arg9 = 0) #define VA_NEXT(var1, typ1) ((var1 = (typ1) arg1), VA_SHIFT(), var1) #define VA_END() } +/* needed in pline.c, where full number of arguments is known and expected */ +#define VA_PASS1(a1) \ + (vA) a1, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0 #endif #endif @@ -380,7 +393,7 @@ typedef genericptr genericptr_t; /* (void *) or (char *) */ * append this to a prototype declaration (see pline() in extern.h). */ #ifdef __GNUC__ -#if __GNUC__ >= 2 +#if (__GNUC__ >= 2) && !defined(USE_OLDARGS) #define PRINTF_F(f, v) __attribute__((format(printf, f, v))) #endif #if __GNUC__ >= 3 diff --git a/include/winprocs.h b/include/winprocs.h index b76d9e1de..f3f4e870f 100644 --- a/include/winprocs.h +++ b/include/winprocs.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 winprocs.h $NHDT-Date: 1433806582 2015/06/08 23:36:22 $ $NHDT-Branch: master $:$NHDT-Revision: 1.36 $ */ +/* NetHack 3.6 winprocs.h $NHDT-Date: 1502141230 2017/08/07 21:27:10 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.38 $ */ /* Copyright (c) David Cohrs, 1992 */ /* NetHack may be freely redistributed. See license for details. */ @@ -13,8 +13,7 @@ struct window_procs { * not start with '-'. Names starting with * '+' are reserved for processors. */ unsigned long wincap; /* window port capability options supported */ - unsigned long - wincap2; /* additional window port capability options supported */ + unsigned long wincap2; /* additional window port capability options */ void FDECL((*win_init_nhwindows), (int *, char **)); void NDECL((*win_player_selection)); void NDECL((*win_askname)); @@ -177,91 +176,70 @@ extern * Window port preference capability bits. * Some day this might be better in its own wincap.h file. */ -#define WC_COLOR 0x01L /* 01 Port can display things in color */ -#define WC_HILITE_PET 0x02L /* 02 supports hilite pet */ -#define WC_ASCII_MAP 0x04L /* 03 supports an ascii map */ -#define WC_TILED_MAP 0x08L /* 04 supports a tiled map */ -#define WC_PRELOAD_TILES 0x10L /* 05 supports pre-loading tiles */ -#define WC_TILE_WIDTH 0x20L /* 06 prefer this width of tile */ -#define WC_TILE_HEIGHT 0x40L /* 07 prefer this height of tile */ -#define WC_TILE_FILE 0x80L /* 08 alternative tile file name */ -#define WC_INVERSE 0x100L /* 09 Port supports inverse video */ -#define WC_ALIGN_MESSAGE \ - 0x200L /* 10 supports message alignmt top|b|l|r */ -#define WC_ALIGN_STATUS 0x400L /* 11 supports status alignmt top|b|l|r */ -#define WC_VARY_MSGCOUNT \ - 0x800L /* 12 supports varying message window */ -#define WC_FONT_MAP 0x1000L /* 13 supports specification of map win font */ -#define WC_FONT_MESSAGE \ - 0x2000L /* 14 supports specification of msg win font */ -#define WC_FONT_STATUS 0x4000L /* 15 supports specification of sts win font \ - */ -#define WC_FONT_MENU 0x8000L /* 16 supports specification of mnu win font */ -#define WC_FONT_TEXT 0x10000L /* 17 supports specification of txt win font \ - */ -#define WC_FONTSIZ_MAP \ - 0x20000L /* 18 supports specification of map win font */ -#define WC_FONTSIZ_MESSAGE \ - 0x40000L /* 19 supports specification of msg win font */ -#define WC_FONTSIZ_STATUS \ - 0x80000L /* 20 supports specification of sts win font */ -#define WC_FONTSIZ_MENU \ - 0x100000L /* 21 supports specification of mnu win font */ -#define WC_FONTSIZ_TEXT \ - 0x200000L /* 22 supports specification of txt win font */ -#define WC_SCROLL_MARGIN \ - 0x400000L /* 23 supports setting scroll margin for map */ -#define WC_SPLASH_SCREEN \ - 0x800000L /* 24 supports display of splash screen */ -#define WC_POPUP_DIALOG \ - 0x1000000L /* 25 supports queries in pop dialogs */ -#define WC_SCROLL_AMOUNT \ - 0x2000000L /* 26 scroll this amount at scroll margin */ -#define WC_EIGHT_BIT_IN \ - 0x4000000L /* 27 8-bit character input */ -#define WC_PERM_INVENT \ - 0x8000000L /* 28 8-bit character input */ -#define WC_MAP_MODE \ - 0x10000000L /* 29 map_mode option */ -#define WC_WINDOWCOLORS \ - 0x20000000L /* 30 background color for message window */ -#define WC_PLAYER_SELECTION \ - 0x40000000L /* 31 background color for message window */ +/* clang-format off */ +#define WC_COLOR 0x00000001L /* 01 Port can display things in color */ +#define WC_HILITE_PET 0x00000002L /* 02 supports hilite pet */ +#define WC_ASCII_MAP 0x00000004L /* 03 supports an ascii map */ +#define WC_TILED_MAP 0x00000008L /* 04 supports a tiled map */ +#define WC_PRELOAD_TILES 0x00000010L /* 05 supports pre-loading tiles */ +#define WC_TILE_WIDTH 0x00000020L /* 06 prefer this width of tile */ +#define WC_TILE_HEIGHT 0x00000040L /* 07 prefer this height of tile */ +#define WC_TILE_FILE 0x00000080L /* 08 alternative tile file name */ +#define WC_INVERSE 0x00000100L /* 09 Port supports inverse video */ +#define WC_ALIGN_MESSAGE 0x00000200L /* 10 supports mesg alignment top|b|l|r */ +#define WC_ALIGN_STATUS 0x00000400L /* 11 supports status alignmt top|b|l|r */ +#define WC_VARY_MSGCOUNT 0x00000800L /* 12 supports varying message window */ +#define WC_FONT_MAP 0x00001000L /* 13 supports spec of map window font */ +#define WC_FONT_MESSAGE 0x00002000L /* 14 supports spec of message font */ +#define WC_FONT_STATUS 0x00004000L /* 15 supports spec of status font */ +#define WC_FONT_MENU 0x00008000L /* 16 supports spec of menu font */ +#define WC_FONT_TEXT 0x00010000L /* 17 supports spec of text window font */ +#define WC_FONTSIZ_MAP 0x00020000L /* 18 supports spec of map font size */ +#define WC_FONTSIZ_MESSAGE 0x040000L /* 19 supports spec of mesg font size */ +#define WC_FONTSIZ_STATUS 0x0080000L /* 20 supports spec of status font size */ +#define WC_FONTSIZ_MENU 0x00100000L /* 21 supports spec of menu font size */ +#define WC_FONTSIZ_TEXT 0x00200000L /* 22 supports spec of text font size */ +#define WC_SCROLL_MARGIN 0x00400000L /* 23 supports setting map scroll marg */ +#define WC_SPLASH_SCREEN 0x00800000L /* 24 supports display of splash screen */ +#define WC_POPUP_DIALOG 0x01000000L /* 25 supports queries in popup dialogs */ +#define WC_SCROLL_AMOUNT 0x02000000L /* 26 scroll this amount at scroll marg */ +#define WC_EIGHT_BIT_IN 0x04000000L /* 27 8-bit character input */ +#define WC_PERM_INVENT 0x08000000L /* 28 supports persistent inventory win */ +#define WC_MAP_MODE 0x10000000L /* 29 map_mode option */ +#define WC_WINDOWCOLORS 0x20000000L /* 30 background color for mesg window */ +#define WC_PLAYER_SELECTION 0x40000000L /* 31 supports player selection */ #ifdef NHSTDC -#define WC_MOUSE_SUPPORT \ - 0x80000000UL /* 32 mouse support */ +#define WC_MOUSE_SUPPORT 0x80000000UL /* 32 mouse support */ #else -#define WC_MOUSE_SUPPORT \ - 0x80000000L /* 32 mouse support */ +#define WC_MOUSE_SUPPORT 0x80000000L /* 32 mouse support */ #endif -/* no free bits */ + /* no free bits */ -#define WC2_FULLSCREEN 0x01L /* 01 display full screen */ -#define WC2_SOFTKEYBOARD 0x02L /* 02 software keyboard */ -#define WC2_WRAPTEXT 0x04L /* 03 wrap long lines of text */ -#define WC2_HILITE_STATUS \ - 0x08L /* 04 hilite fields in status */ -#define WC2_SELECTSAVED 0x10L /* 05 saved game selection menu */ -#define WC2_DARKGRAY 0x20L /* 06 use bold black for black glyphs */ - /* 26 free bits */ +#define WC2_FULLSCREEN 0x0001L /* 01 display full screen */ +#define WC2_SOFTKEYBOARD 0x0002L /* 02 software keyboard */ +#define WC2_WRAPTEXT 0x0004L /* 03 wrap long lines of text */ +#define WC2_HILITE_STATUS 0x0008L /* 04 hilite fields in status */ +#define WC2_SELECTSAVED 0x0010L /* 05 saved game selection menu */ +#define WC2_DARKGRAY 0x0020L /* 06 use bold black for black glyphs */ + /* 26 free bits */ -#define ALIGN_LEFT 1 -#define ALIGN_RIGHT 2 -#define ALIGN_TOP 3 +#define ALIGN_LEFT 1 +#define ALIGN_RIGHT 2 +#define ALIGN_TOP 3 #define ALIGN_BOTTOM 4 /* player_selection */ -#define VIA_DIALOG 0 +#define VIA_DIALOG 0 #define VIA_PROMPTS 1 /* map_mode settings - deprecated */ -#define MAP_MODE_TILES 0 -#define MAP_MODE_ASCII4x6 1 -#define MAP_MODE_ASCII6x8 2 -#define MAP_MODE_ASCII8x8 3 -#define MAP_MODE_ASCII16x8 4 -#define MAP_MODE_ASCII7x12 5 -#define MAP_MODE_ASCII8x12 6 +#define MAP_MODE_TILES 0 +#define MAP_MODE_ASCII4x6 1 +#define MAP_MODE_ASCII6x8 2 +#define MAP_MODE_ASCII8x8 3 +#define MAP_MODE_ASCII16x8 4 +#define MAP_MODE_ASCII7x12 5 +#define MAP_MODE_ASCII8x12 6 #define MAP_MODE_ASCII16x12 7 #define MAP_MODE_ASCII12x16 8 #define MAP_MODE_ASCII10x18 9 @@ -269,13 +247,13 @@ extern #define MAP_MODE_TILES_FIT_TO_SCREEN 11 #if 0 -#define WC_SND_SOUND 0x01L /* 01 Port has some sound capabilities */ -#define WC_SND_SPEAKER 0x02L /* 02 Sound supported via built-in speaker */ -#define WC_SND_STEREO 0x04L /* 03 Stereo sound supported */ -#define WC_SND_RAW 0x08L /* 04 Raw sound supported */ -#define WC_SND_WAVE 0x10L /* 05 Wave support */ -#define WC_SND_MIDI 0x20L /* 06 Midi support */ - /* 26 free bits */ +#define WC_SND_SOUND 0x0001L /* 01 Port has some sound capabilities */ +#define WC_SND_SPEAKER 0x0002L /* 02 Sound supported via built-in speaker */ +#define WC_SND_STEREO 0x0004L /* 03 Stereo sound supported */ +#define WC_SND_RAW 0x0008L /* 04 Raw sound supported */ +#define WC_SND_WAVE 0x0010L /* 05 Wave support */ +#define WC_SND_MIDI 0x0020L /* 06 Midi support */ + /* 26 free bits */ #endif struct wc_Opt { @@ -284,17 +262,17 @@ struct wc_Opt { }; /* role selection by player_selection(); this ought to be in the core... */ -#define RS_NAME 0 -#define RS_ROLE 1 -#define RS_RACE 2 -#define RS_GENDER 3 +#define RS_NAME 0 +#define RS_ROLE 1 +#define RS_RACE 2 +#define RS_GENDER 3 #define RS_ALGNMNT 4 -#define RS_filter 5 +#define RS_filter 5 #define RS_menu_arg(x) (ROLE_RANDOM - ((x) + 1)) /* 0..5 -> -3..-8 */ /* Choose_windows() may be called multiple times; these constants tell the * init function whether the window system is coming or going. */ -#define WININIT 0 +#define WININIT 0 #define WININIT_UNDO 1 #ifdef WINCHAIN @@ -310,7 +288,9 @@ struct wc_Opt { nextdata is the Xprivate* for the next link in the chain */ #define WINCHAIN_ALLOC 0 -#define WINCHAIN_INIT 1 +#define WINCHAIN_INIT 1 + +/* clang-format on */ #define CARGS void * @@ -321,8 +301,7 @@ struct chain_procs { * not start with '-'. Names starting with * '+' are reserved for processors. */ unsigned long wincap; /* window port capability options supported */ - unsigned long - wincap2; /* additional window port capability options supported */ + unsigned long wincap2; /* additional window port capability options */ void FDECL((*win_init_nhwindows), (CARGS, int *, char **)); void FDECL((*win_player_selection), (CARGS)); void FDECL((*win_askname), (CARGS)); diff --git a/src/allmain.c b/src/allmain.c index 3d3ba3414..b42a10604 100644 --- a/src/allmain.c +++ b/src/allmain.c @@ -13,6 +13,7 @@ #ifdef POSITIONBAR STATIC_DCL void NDECL(do_positionbar); #endif +STATIC_DCL void FDECL(regen_hp, (int)); STATIC_DCL void FDECL(interrupt_multi, (const char *)); void @@ -185,66 +186,20 @@ boolean resuming; /* One possible result of prayer is healing. Whether or * not you get healed depends on your current hit points. - * If you are allowed to regenerate during the prayer, the - * end-of-prayer calculation messes up on this. + * If you are allowed to regenerate during the prayer, + * the end-of-prayer calculation messes up on this. * Another possible result is rehumanization, which - * requires - * that encumbrance and movement rate be recalculated. + * requires that encumbrance and movement rate be + * recalculated. */ if (u.uinvulnerable) { /* for the moment at least, you're in tiptop shape */ wtcap = UNENCUMBERED; - } else if (Upolyd && youmonst.data->mlet == S_EEL - && !is_pool(u.ux, u.uy) - && !Is_waterlevel(&u.uz)) { - /* eel out of water loses hp, same as for monsters; - as hp gets lower, rate of further loss slows down - */ - if (u.mh > 1 && rn2(u.mh) > rn2(8) - && (!Half_physical_damage || !(moves % 2L))) { - u.mh--; - context.botl = 1; - } else if (u.mh < 1) - rehumanize(); - } else if (Upolyd && u.mh < u.mhmax) { - if (u.mh < 1) - rehumanize(); - else if (Regeneration - || (wtcap < MOD_ENCUMBER && !(moves % 20))) { - context.botl = 1; - u.mh++; - if (u.mh >= u.mhmax) - interrupt_multi("You are in full health."); - } - } else if (u.uhp < u.uhpmax - && (wtcap < MOD_ENCUMBER || !u.umoved - || Regeneration)) { - if (u.ulevel > 9 && !(moves % 3)) { - int heal, Con = (int) ACURR(A_CON); - - if (Con <= 12) { - heal = 1; - } else { - heal = rnd(Con); - if (heal > u.ulevel - 9) - heal = u.ulevel - 9; - } - context.botl = 1; - u.uhp += heal; - if (u.uhp > u.uhpmax) - u.uhp = u.uhpmax; - if (u.uhp >= u.uhpmax) - interrupt_multi("You are in full health."); - } else if (Regeneration - || (u.ulevel <= 9 - && !(moves - % ((MAXULEV + 12) / (u.ulevel + 2) - + 1)))) { - context.botl = 1; - u.uhp++; - if (u.uhp >= u.uhpmax) - interrupt_multi("You are in full health."); - } + } else if (!Upolyd ? (u.uhp < u.uhpmax) + : (u.mh < u.mhmax + || youmonst.data->mlet == S_EEL)) { + /* maybe heal */ + regen_hp(wtcap); } /* moving around while encumbered is hard work */ @@ -263,7 +218,7 @@ boolean resuming; } } - if ((u.uen < u.uenmax) + if (u.uen < u.uenmax && ((wtcap < MOD_ENCUMBER && (!(moves % ((MAXULEV + 8 - u.ulevel) * (Role_if(PM_WIZARD) ? 3 : 4) @@ -273,7 +228,7 @@ boolean resuming; if (u.uen > u.uenmax) u.uen = u.uenmax; context.botl = 1; - if (u.uen >= u.uenmax) + if (u.uen == u.uenmax) interrupt_multi("You feel full of energy."); } @@ -493,6 +448,76 @@ boolean resuming; } } +/* maybe recover some lost health (or lose some when an eel out of water) */ +STATIC_OVL void +regen_hp(wtcap) +int wtcap; +{ + int heal = 0; + boolean reached_full = FALSE, + encumbrance_ok = (wtcap < MOD_ENCUMBER || !u.umoved); + + if (Upolyd) { + if (u.mh < 1) { /* shouldn't happen... */ + rehumanize(); + } else if (youmonst.data->mlet == S_EEL + && !is_pool(u.ux, u.uy) && !Is_waterlevel(&u.uz)) { + /* eel out of water loses hp, similar to monster eels; + as hp gets lower, rate of further loss slows down */ + if (u.mh > 1 && !Regeneration && rn2(u.mh) > rn2(8) + && (!Half_physical_damage || !(moves % 2L))) + heal = -1; + } else if (u.mh < u.mhmax) { + if (Regeneration || (encumbrance_ok && !(moves % 20L))) + heal = 1; + } + if (heal) { + context.botl = 1; + u.mh += heal; + reached_full = (u.mh == u.mhmax); + } + + /* !Upolyd */ + } else { + /* [when this code was in-line within moveloop(), there was + no !Upolyd check here, so poly'd hero recovered lost u.uhp + once u.mh reached u.mhmax; that may have been convenient + for the player, but it didn't make sense for gameplay...] */ + if (u.uhp < u.uhpmax && (encumbrance_ok || Regeneration)) { + if (u.ulevel > 9) { + if (!(moves % 3L)) { + int Con = (int) ACURR(A_CON); + + if (Con <= 12) { + heal = 1; + } else { + heal = rnd(Con); + if (heal > u.ulevel - 9) + heal = u.ulevel - 9; + } + } + } else { /* u.ulevel <= 9 */ + if (!(moves % (long) ((MAXULEV + 12) / (u.ulevel + 2) + 1))) + heal = 1; + } + if (Regeneration && !heal) + heal = 1; + + if (heal) { + context.botl = 1; + u.uhp += heal; + if (u.uhp > u.uhpmax) + u.uhp = u.uhpmax; + /* stop voluntary multi-turn activity if now fully healed */ + reached_full = (u.uhp == u.uhpmax); + } + } + } + + if (reached_full) + interrupt_multi("You are in full health."); +} + void stop_occupation() { @@ -561,7 +586,7 @@ newgame() context.tribute.enabled = TRUE; /* turn on 3.6 tributes */ context.tribute.tributesz = sizeof(struct tribute_info); - for (i = 0; i < NUMMONS; i++) + for (i = LOW_PM; i < NUMMONS; i++) mvitals[i].mvflags = mons[i].geno & G_NOCORPSE; init_objects(); /* must be before u_init() */ diff --git a/src/apply.c b/src/apply.c index 546d2cefd..6337eb49d 100644 --- a/src/apply.c +++ b/src/apply.c @@ -445,6 +445,8 @@ struct obj *obj; } else { You(whistle_str, obj->cursed ? "shrill" : "high"); wake_nearby(); + if (obj->cursed) + vault_summon_gd(); } } @@ -1564,6 +1566,15 @@ boolean showmsg; static int jumping_is_magic; +boolean +get_valid_jump_position(x,y) +int x,y; +{ + return (isok(x, y) + && (ACCESSIBLE(levl[x][y].typ) || Passes_walls) + && is_valid_jump_pos(x, y, jumping_is_magic, FALSE)); +} + void display_jump_positions(state) int state; @@ -1577,9 +1588,7 @@ int state; for (dy = -4; dy <= 4; dy++) { x = dx + (int) u.ux; y = dy + (int) u.uy; - if (isok(x, y) - && (ACCESSIBLE(levl[x][y].typ) || Passes_walls) - && is_valid_jump_pos(x, y, jumping_is_magic, FALSE)) + if (get_valid_jump_position(x, y)) tmp_at(x, y); } } else { @@ -1678,7 +1687,7 @@ int magic; /* 0=Physical, otherwise skill level */ cc.x = u.ux; cc.y = u.uy; jumping_is_magic = magic; - getpos_sethilite(display_jump_positions); + getpos_sethilite(display_jump_positions, get_valid_jump_position); if (getpos(&cc, TRUE, "the desired position") < 0) return 0; /* user pressed ESC */ if (!is_valid_jump_pos(cc.x, cc.y, magic, TRUE)) { @@ -2851,6 +2860,15 @@ int min_range, max_range; static int polearm_range_min = -1; static int polearm_range_max = -1; +boolean +get_valid_polearm_position(x,y) +int x,y; +{ + return (isok(x, y) && ACCESSIBLE(levl[x][y].typ) + && distu(x, y) >= polearm_range_min + && distu(x, y) <= polearm_range_max); +} + void display_polearm_positions(state) int state; @@ -2864,9 +2882,7 @@ int state; for (dy = -4; dy <= 4; dy++) { x = dx + (int) u.ux; y = dy + (int) u.uy; - if (isok(x, y) && ACCESSIBLE(levl[x][y].typ) - && distu(x, y) >= polearm_range_min - && distu(x, y) <= polearm_range_max) { + if (get_valid_polearm_position(x, y)) { tmp_at(x, y); } } @@ -2936,7 +2952,7 @@ struct obj *obj; cc.x = hitm->mx; cc.y = hitm->my; } - getpos_sethilite(display_polearm_positions); + getpos_sethilite(display_polearm_positions, get_valid_polearm_position); if (getpos(&cc, TRUE, "the spot to hit") < 0) return res; /* ESC; uses turn iff polearm became wielded */ diff --git a/src/artifact.c b/src/artifact.c index 113843e78..13e8be981 100644 --- a/src/artifact.c +++ b/src/artifact.c @@ -498,7 +498,7 @@ long wp_mask; for (obj = invent; obj; obj = obj->nobj) { if (obj != otmp && obj->oartifact) { art = get_artifact(obj); - if (art->cary.adtyp == dtyp) { + if (art && art->cary.adtyp == dtyp) { mask = (long *) 0; break; } @@ -519,7 +519,8 @@ long wp_mask; for (obj = invent; obj; obj = obj->nobj) if (obj != otmp && obj->oartifact) { art = get_artifact(obj); - spfx &= ~art->cspfx; + if (art) + spfx &= ~art->cspfx; } } @@ -653,16 +654,17 @@ struct monst *mon; return 1; yours = (mon == &youmonst); - /* all quest artifacts are self-willed; it this ever changes, `badclass' + /* all quest artifacts are self-willed; if this ever changes, `badclass' will have to be extended to explicitly include quest artifacts */ self_willed = ((oart->spfx & SPFX_INTEL) != 0); if (yours) { badclass = self_willed && ((oart->role != NON_PM && !Role_if(oart->role)) || (oart->race != NON_PM && !Race_if(oart->race))); - badalign = - (oart->spfx & SPFX_RESTR) && oart->alignment != A_NONE - && (oart->alignment != u.ualign.type || u.ualign.record < 0); + badalign = ((oart->spfx & SPFX_RESTR) != 0 + && oart->alignment != A_NONE + && (oart->alignment != u.ualign.type + || u.ualign.record < 0)); } else if (!is_covetous(mon->data) && !is_mplayer(mon->data)) { badclass = self_willed && oart->role != NON_PM && oart != &artilist[ART_EXCALIBUR]; @@ -1493,8 +1495,8 @@ struct obj *obj; obj->age = 0; return 0; } - b_effect = - obj->blessed && (Role_switch == oart->role || !oart->role); + b_effect = (obj->blessed + && (Role_switch == oart->role || !oart->role)); recharge(otmp, b_effect ? 1 : obj->cursed ? -1 : 0); update_inventory(); break; @@ -1583,9 +1585,8 @@ struct obj *obj; } else otmp->quan += rnd(5); otmp->owt = weight(otmp); - otmp = - hold_another_object(otmp, "Suddenly %s out.", - aobjnam(otmp, "fall"), (const char *) 0); + otmp = hold_another_object(otmp, "Suddenly %s out.", + aobjnam(otmp, "fall"), (char *) 0); break; } } @@ -1883,12 +1884,11 @@ boolean loseit; /* whether to drop it if hero can longer touch it */ if (touch_artifact(obj, &youmonst)) { char buf[BUFSZ]; int dmg = 0, tmp; - boolean ag = - (objects[obj->otyp].oc_material == SILVER && Hate_silver), + boolean ag = (objects[obj->otyp].oc_material == SILVER && Hate_silver), bane = bane_applies(get_artifact(obj), &youmonst); /* nothing else to do if hero can successfully handle this object */ - if (!ag && !bane && !touch_blasted) + if (!ag && !bane) return 1; /* hero can't handle this object, but didn't get touch_artifact()'s @@ -2008,11 +2008,15 @@ int dropflag; /* 0==don't drop, 1==drop all, 2==drop weapon */ dropit = (dropflag > 0); /* drop all or drop weapon */ /* check secondary weapon first, before possibly unwielding primary */ - if (u.twoweap) + if (u.twoweap) { + bypass_obj(uswapwep); /* so loop below won't process it again */ (void) untouchable(uswapwep, dropit); + } /* check primary weapon next so that they're handled together */ - if (uwep) + if (uwep) { + bypass_obj(uwep); /* so loop below won't process it again */ (void) untouchable(uwep, dropit); + } /* in case someone is daft enough to add artifact or silver saddle */ if (u.usteed && (obj = which_armor(u.usteed, W_SADDLE)) != 0) { diff --git a/src/bones.c b/src/bones.c index a0ebc4d49..73fea3d2e 100644 --- a/src/bones.c +++ b/src/bones.c @@ -48,14 +48,10 @@ STATIC_OVL void goodfruit(id) int id; { - register struct fruit *f; + struct fruit *f = fruit_from_indx(-id); - for (f = ffruit; f; f = f->nextf) { - if (f->fid == -id) { - f->fid = id; - return; - } - } + if (f) + f->fid = id; } STATIC_OVL void diff --git a/src/botl.c b/src/botl.c index e6a771bdc..e28e8cc8b 100644 --- a/src/botl.c +++ b/src/botl.c @@ -13,6 +13,25 @@ const char *const enc_stat[] = { "", "Burdened", "Stressed", STATIC_OVL NEARDATA int mrank_sz = 0; /* loaded by max_rank_sz (from u_init) */ STATIC_DCL const char *NDECL(rank); +static char * +get_strength_str() +{ + static char buf[32]; + int st = ACURR(A_STR); + + if (st > 18) { + if (st > STR18(100)) + Sprintf(buf, "%2d", st - 100); + else if (st < STR18(100)) + Sprintf(buf, "18/%02d", st - 18); + else + Sprintf(buf, "18/**"); + } else + Sprintf(buf, "%-1d", st); + + return buf; +} + #if !defined(STATUS_VIA_WINDOWPORT) || defined(DUMPLOG) char * @@ -48,16 +67,9 @@ do_statusline1() j = (int) ((nb + 2) - newbot1); /* strlen(newbot1) but less computation */ if ((i - j) > 0) Sprintf(nb = eos(nb), "%*s", i - j, " "); /* pad with spaces */ - if (ACURR(A_STR) > 18) { - if (ACURR(A_STR) > STR18(100)) - Sprintf(nb = eos(nb), "St:%2d ", ACURR(A_STR) - 100); - else if (ACURR(A_STR) < STR18(100)) - Sprintf(nb = eos(nb), "St:18/%02d ", ACURR(A_STR) - 18); - else - Sprintf(nb = eos(nb), "St:18/** "); - } else - Sprintf(nb = eos(nb), "St:%-1d ", ACURR(A_STR)); - Sprintf(nb = eos(nb), "Dx:%-1d Co:%-1d In:%-1d Wi:%-1d Ch:%-1d", + + Sprintf(nb = eos(nb), "St:%s Dx:%-1d Co:%-1d In:%-1d Wi:%-1d Ch:%-1d", + get_strength_str(), ACURR(A_DEX), ACURR(A_CON), ACURR(A_INT), ACURR(A_WIS), ACURR(A_CHA)); Sprintf(nb = eos(nb), @@ -470,18 +482,8 @@ bot() valset[BL_TITLE] = TRUE; /* indicate val already set */ /* Strength */ - buf[0] = '\0'; blstats[idx][BL_STR].a.a_int = ACURR(A_STR); - if (ACURR(A_STR) > 18) { - if (ACURR(A_STR) > STR18(100)) - Sprintf(buf, "%2d", ACURR(A_STR) - 100); - else if (ACURR(A_STR) < STR18(100)) - Sprintf(buf, "18/%02d", ACURR(A_STR) - 18); - else - Sprintf(buf, "18/**"); - } else - Sprintf(buf, "%-1d", ACURR(A_STR)); - Strcpy(blstats[idx][BL_STR].val, buf); + Strcpy(blstats[idx][BL_STR].val, get_strength_str()); valset[BL_STR] = TRUE; /* indicate val already set */ /* Dexterity, constitution, intelligence, wisdom, charisma. */ diff --git a/src/cmd.c b/src/cmd.c index 2ec304a8a..cd7faedc8 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -135,6 +135,7 @@ STATIC_PTR int NDECL(wiz_level_change); STATIC_PTR int NDECL(wiz_show_seenv); STATIC_PTR int NDECL(wiz_show_vision); STATIC_PTR int NDECL(wiz_smell); +STATIC_PTR int NDECL(wiz_intrinsic); STATIC_PTR int NDECL(wiz_mon_polycontrol); STATIC_PTR int NDECL(wiz_show_wmodes); STATIC_DCL void NDECL(wiz_map_levltyp); @@ -1157,38 +1158,52 @@ STATIC_PTR int wiz_intrinsic(VOID_ARGS) { if (wizard) { - extern const char *const propertynames[]; /* timeout.c */ + extern const struct propname { + int prop_num; + const char *prop_name; + } propertynames[]; /* timeout.c */ static const char wizintrinsic[] = "#wizintrinsic"; static const char fmt[] = "You are%s %s."; winid win; anything any; char buf[BUFSZ]; - int i, n, p, amt, typ; + int i, j, n, p, amt, typ; long oldtimeout, newtimeout; const char *propname; menu_item *pick_list = (menu_item *) 0; + any = zeroany; win = create_nhwindow(NHW_MENU); start_menu(win); - - for (i = 1; (propname = propertynames[i]) != 0; ++i) { - if (i == HALLUC_RES) { + for (i = 0; (propname = propertynames[i].prop_name) != 0; ++i) { + p = propertynames[i].prop_num; + if (p == HALLUC_RES) { /* Grayswandir vs hallucination; ought to be redone to use u.uprops[HALLUC].blocked instead of being treated as a separate property; letting in be manually toggled even only in wizard mode would be asking for trouble... */ continue; } - any.a_int = i; - add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, propname, FALSE); + if (p == FIRE_RES) { + any.a_int = 0; + add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "--", FALSE); + } + any.a_int = i + 1; /* +1: avoid 0 */ + oldtimeout = u.uprops[p].intrinsic & TIMEOUT; + if (oldtimeout) + Sprintf(buf, "%-27s [%li]", propname, oldtimeout); + else + Sprintf(buf, "%s", propname); + add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE); } end_menu(win, "Which intrinsics?"); n = select_menu(win, PICK_ANY, &pick_list); destroy_nhwindow(win); amt = 30; /* TODO: prompt for duration */ - for (i = 0; i < n; ++i) { - p = pick_list[i].item.a_int; + for (j = 0; j < n; ++j) { + i = pick_list[j].item.a_int - 1; /* -1: reverse +1 above */ + p = propertynames[i].prop_num; oldtimeout = u.uprops[p].intrinsic & TIMEOUT; newtimeout = oldtimeout + (long) amt; switch (p) { @@ -1204,9 +1219,12 @@ wiz_intrinsic(VOID_ARGS) case BLINDED: make_blinded(newtimeout, TRUE); break; +#if 0 /* make_confused() only gives feedback when confusion is + * ending so use the 'default' case for it instead */ case CONFUSION: make_confused(newtimeout, TRUE); break; +#endif /*0*/ case DEAF: make_deaf(newtimeout, TRUE); break; @@ -1236,7 +1254,7 @@ wiz_intrinsic(VOID_ARGS) pline1(buf); break; default: - pline("Timeout for %s %s %d.", propertynames[p], + pline("Timeout for %s %s %d.", propertynames[i].prop_name, oldtimeout ? "increased by" : "set to", amt); incr_itimeout(&u.uprops[p].intrinsic, amt); break; @@ -2458,14 +2476,15 @@ int final; /* named fruit debugging (doesn't really belong here...); to enable, include 'fruit' in DEBUGFILES list (even though it isn't a file...) */ if (wizard && explicitdebug("fruit")) { - int fcount = 0; struct fruit *f; - char buf2[BUFSZ]; + reorder_fruit(TRUE); /* sort by fruit index, from low to high; + * this modifies the ffruit chain, so could + * possibly mask or even introduce a problem, + * but it does useful sanity checking */ for (f = ffruit; f; f = f->nextf) { - Sprintf(buf, "Fruit %d ", ++fcount); - Sprintf(buf2, "%s (id %d)", f->fname, f->fid); - enl_msg(buf, "is ", "was ", buf2, ""); + Sprintf(buf, "Fruit #%d ", f->fid); + enl_msg(buf, "is ", "was ", f->fname, ""); } enl_msg("The current fruit ", "is ", "was ", pl_fruit, ""); Sprintf(buf, "%d", flags.made_fruit); @@ -3724,10 +3743,13 @@ struct { { NHKF_GETPOS_DOOR_PREV, 'D', "getpos.door.prev" }, { NHKF_GETPOS_UNEX_NEXT, 'x', "getpos.unexplored.next" }, { NHKF_GETPOS_UNEX_PREV, 'X', "getpos.unexplored.prev" }, + { NHKF_GETPOS_VALID_NEXT, 'z', "getpos.valid.next" }, + { NHKF_GETPOS_VALID_PREV, 'Z', "getpos.valid.prev" }, { NHKF_GETPOS_INTERESTING_NEXT, 'a', "getpos.all.next" }, { NHKF_GETPOS_INTERESTING_PREV, 'A', "getpos.all.prev" }, { NHKF_GETPOS_HELP, '?', "getpos.help" }, - { NHKF_GETPOS_LIMITVIEW, '"', "getpos.inview" }, + { NHKF_GETPOS_LIMITVIEW, '"', "getpos.filter" }, + { NHKF_GETPOS_MOVESKIP, '*', "getpos.moveskip" }, { NHKF_GETPOS_MENU, '!', "getpos.menu" } }; @@ -5016,10 +5038,14 @@ dotravel(VOID_ARGS) } iflags.getloc_travelmode = TRUE; if (iflags.menu_requested) { - if (!getpos_menu(&cc, TRUE, GLOC_INTERESTING)) { + int gf = iflags.getloc_filter; + iflags.getloc_filter = GFILTER_VIEW; + if (!getpos_menu(&cc, GLOC_INTERESTING)) { + iflags.getloc_filter = gf; iflags.getloc_travelmode = FALSE; return 0; } + iflags.getloc_filter = gf; } else { pline("Where do you want to travel to?"); if (getpos(&cc, TRUE, "the desired destination") < 0) { diff --git a/src/do_name.c b/src/do_name.c index 452f6c555..7dec3fb7d 100644 --- a/src/do_name.c +++ b/src/do_name.c @@ -36,12 +36,15 @@ nextmbuf() * parameter value 0 = initialize, 1 = highlight, 2 = done */ static void FDECL((*getpos_hilitefunc), (int)) = (void FDECL((*), (int))) 0; +static boolean FDECL((*getpos_getvalid), (int,int)) = (boolean FDECL((*), (int,int))) 0; void -getpos_sethilite(f) +getpos_sethilite(f, d) void FDECL((*f), (int)); +boolean FDECL((*d), (int,int)); { getpos_hilitefunc = f; + getpos_getvalid = d; } const char *const gloc_descr[NUM_GLOCS][4] = { @@ -54,6 +57,11 @@ const char *const gloc_descr[NUM_GLOCS][4] = { "anything interesting" } }; +const char *const gloc_filtertxt[NUM_GFILTER] = { + "", + " in view", + " in this area" +}; void getpos_help_keyxhelp(tmpwin, k1, k2, gloc) @@ -69,7 +77,7 @@ int gloc; iflags.getloc_usemenu ? "get a menu of " : "move the cursor to ", gloc_descr[gloc][2 + iflags.getloc_usemenu], - iflags.getloc_limitview ? " in view" : ""); + gloc_filtertxt[iflags.getloc_filter]); putstr(tmpwin, 0, sbuf); } @@ -82,13 +90,17 @@ const char *goal; char sbuf[BUFSZ]; boolean doing_what_is; winid tmpwin = create_nhwindow(NHW_MENU); + const char *const fastmovemode[2] = { "8 units at a time", + "skipping same glyphs" }; Sprintf(sbuf, "Use '%c', '%c', '%c', '%c' to move the cursor to %s.", /* hjkl */ Cmd.move_W, Cmd.move_S, Cmd.move_N, Cmd.move_E, goal); putstr(tmpwin, 0, sbuf); - putstr(tmpwin, 0, - "Use 'H', 'J', 'K', 'L' to move the cursor 8 units at a time."); + Sprintf(sbuf, + "Use 'H', 'J', 'K', 'L' to fast-move the cursor, %s.", + fastmovemode[iflags.getloc_moveskip]); + putstr(tmpwin, 0, sbuf); putstr(tmpwin, 0, "Or enter a background symbol (ex. '<')."); Sprintf(sbuf, "Use '%s' to move the cursor on yourself.", visctrl(Cmd.spkeys[NHKF_GETPOS_SELF])); @@ -121,15 +133,26 @@ const char *goal; visctrl(Cmd.spkeys[NHKF_GETPOS_INTERESTING_PREV]), GLOC_INTERESTING); } + Sprintf(sbuf, "Use '%s' to change fast-move mode to %s.", + visctrl(Cmd.spkeys[NHKF_GETPOS_MOVESKIP]), + fastmovemode[!iflags.getloc_moveskip]); + putstr(tmpwin, 0, sbuf); + Sprintf(sbuf, "Use '%s' to toggle menu listing for possible targets.", visctrl(Cmd.spkeys[NHKF_GETPOS_MENU])); putstr(tmpwin, 0, sbuf); Sprintf(sbuf, - "Use '%s' to toggle limiting possible targets to in view only.", + "Use '%s' to change the mode of limiting possible targets.", visctrl(Cmd.spkeys[NHKF_GETPOS_LIMITVIEW])); putstr(tmpwin, 0, sbuf); if (!iflags.terrainmode) { char kbuf[BUFSZ]; + if (getpos_getvalid) { + Sprintf(sbuf, "Use '%s' or '%s' to move to valid locations.", + visctrl(Cmd.spkeys[NHKF_GETPOS_VALID_NEXT]), + visctrl(Cmd.spkeys[NHKF_GETPOS_VALID_PREV])); + putstr(tmpwin, 0, sbuf); + } if (getpos_hilitefunc) { Sprintf(sbuf, "Use '%s' to display valid locations.", visctrl(Cmd.spkeys[NHKF_GETPOS_SHOWVALID])); @@ -214,6 +237,99 @@ const void *b; && glyph_to_cmap(levl[(x)][(y)].glyph) == S_stone \ && !levl[(x)][(y)].seenv) +static struct opvar *gloc_filter_map = (struct opvar *) 0; + +#define GLOC_SAME_AREA(x,y) \ + (isok((x), (y)) \ + && (selection_getpoint((x),(y), gloc_filter_map))) + +static int gloc_filter_floodfill_match_glyph; + +int +gloc_filter_classify_glyph(glyph) +int glyph; +{ + int c; + + if (!glyph_is_cmap(glyph)) + return 0; + + c = glyph_to_cmap(glyph); + + if (is_cmap_room(c) || is_cmap_furniture(c)) + return 1; + else if (is_cmap_wall(c) || c == S_tree) + return 2; + else if (is_cmap_corr(c)) + return 3; + else if (is_cmap_water(c)) + return 4; + else if (is_cmap_lava(c)) + return 5; + return 0; +} + +STATIC_OVL int +gloc_filter_floodfill_matcharea(x,y) +int x,y; +{ + int glyph = back_to_glyph(x, y); + + if (!levl[x][y].seenv) + return FALSE; + + if (glyph == gloc_filter_floodfill_match_glyph) + return TRUE; + + if (gloc_filter_classify_glyph(glyph) == gloc_filter_classify_glyph(gloc_filter_floodfill_match_glyph)) + return TRUE; + + return FALSE; +} + +void +gloc_filter_floodfill(x,y) +int x,y; +{ + gloc_filter_floodfill_match_glyph = back_to_glyph(x,y); + + set_selection_floodfillchk(gloc_filter_floodfill_matcharea); + selection_floodfill(gloc_filter_map, x,y, FALSE); +} + +void +gloc_filter_init() +{ + if (iflags.getloc_filter == GFILTER_AREA) { + if (!gloc_filter_map) { + gloc_filter_map = selection_opvar(NULL); + } + /* special case: if we're in a doorway, try to figure out which + direction we're moving, and use that side of the doorway */ + if (IS_DOOR(levl[u.ux][u.uy].typ)) { + if (u.dx || u.dy) { + gloc_filter_floodfill(u.ux + u.dx, u.uy + u.dy); + } else { + /* TODO: maybe add both sides of the doorway? */ + } + } else { + gloc_filter_floodfill(u.ux, u.uy); + } + + + } +} + +void +gloc_filter_done() +{ + if (gloc_filter_map) { + opvar_free_x(gloc_filter_map); + gloc_filter_map = NULL; + } +} + + STATIC_OVL boolean gather_locs_interesting(x,y, gloc) int x,y, gloc; @@ -223,7 +339,13 @@ int x,y, gloc; */ int glyph = glyph_at(x, y); - if (iflags.getloc_limitview && !cansee(x,y)) + if (iflags.getloc_filter == GFILTER_VIEW && !cansee(x,y)) + return FALSE; + if (iflags.getloc_filter == GFILTER_AREA && !GLOC_SAME_AREA(x,y) + && !GLOC_SAME_AREA(x-1,y) + && !GLOC_SAME_AREA(x,y-1) + && !GLOC_SAME_AREA(x+1,y) + && !GLOC_SAME_AREA(x,y+1)) return FALSE; switch (gloc) { @@ -272,6 +394,8 @@ int x,y, gloc; || glyph_to_cmap(glyph) == S_darkroom || glyph_to_cmap(glyph) == S_corr || glyph_to_cmap(glyph) == S_litcorr)); + case GLOC_VALID: + return (getpos_getvalid && getpos_getvalid(x,y)); } /*NOTREACHED*/ return FALSE; @@ -297,6 +421,9 @@ int gloc; * Hero's spot will always sort to array[0] because it will always * be the shortest distance (namely, 0 units) away from . */ + + gloc_filter_init(); + *cnt_p = idx = 0; for (pass = 0; pass < 2; pass++) { for (x = 1; x < COLNO; x++) @@ -318,6 +445,8 @@ int gloc; else /* end of second pass */ qsort(*arr_p, *cnt_p, sizeof (coord), cmp_coord_distu); } /* pass */ + + gloc_filter_done(); } char * @@ -413,7 +542,9 @@ int cx, cy; if (do_screen_description(cc, TRUE, sym, tmpbuf, &firstmatch)) { (void) coord_desc(cx, cy, tmpbuf, iflags.getpos_coords); custompline(SUPPRESS_HISTORY, - "%s%s%s%s", firstmatch, *tmpbuf ? " " : "", tmpbuf, + "%s%s%s%s%s", firstmatch, *tmpbuf ? " " : "", tmpbuf, + (iflags.autodescribe && getpos_getvalid && !getpos_getvalid(cx,cy)) + ? " (illegal)" : "", (iflags.getloc_travelmode && !is_valid_travelpt(cx, cy)) ? " (no travel path)" : ""); curs(WIN_MAP, cx, cy); @@ -422,9 +553,8 @@ int cx, cy; } boolean -getpos_menu(ccp, fovonly, gloc) +getpos_menu(ccp, gloc) coord *ccp; -boolean fovonly; int gloc; { coord *garr = DUMMY; @@ -440,7 +570,8 @@ int gloc; if (gcount < 2) { /* gcount always includes the hero */ free((genericptr_t) garr); You("cannot %s %s.", - fovonly ? "see" : "detect", gloc_descr[gloc][0]); + iflags.getloc_filter == GFILTER_VIEW ? "see" : "detect", + gloc_descr[gloc][0]); return FALSE; } @@ -466,7 +597,8 @@ int gloc; } Sprintf(tmpbuf, "Pick a target %s%s%s", - gloc_descr[gloc][1], fovonly ? " in view" : "", + gloc_descr[gloc][1], + gloc_filtertxt[iflags.getloc_filter], iflags.getloc_travelmode ? " for travel" : ""); end_menu(tmpwin, tmpbuf); pick_cnt = select_menu(tmpwin, PICK_ONE, &picks); @@ -505,10 +637,12 @@ const char *goal; NHKF_GETPOS_UNEX_NEXT, NHKF_GETPOS_UNEX_PREV, NHKF_GETPOS_INTERESTING_NEXT, - NHKF_GETPOS_INTERESTING_PREV + NHKF_GETPOS_INTERESTING_PREV, + NHKF_GETPOS_VALID_NEXT, + NHKF_GETPOS_VALID_PREV }; char pick_chars[6]; - char mMoOdDxX[11]; + char mMoOdDxX[13]; int result = 0; int cx, cy, i, c; int sidx, tx, ty; @@ -595,8 +729,23 @@ const char *goal; } else if (Cmd.alphadirchars[i] == lowc((char) c) || (Cmd.num_pad && Cmd.dirchars[i] == (c & 0177))) { /* a shifted movement letter or Meta-digit */ - dx = 8 * xdir[i]; - dy = 8 * ydir[i]; + if (iflags.getloc_moveskip) { + /* skip same glyphs */ + int glyph = glyph_at(cx, cy); + + dx = xdir[i]; + dy = ydir[i]; + while (isok(cx + dx, cy + dy) + && glyph == glyph_at(cx + dx, cy + dy) + && isok(cx + dx+xdir[i], cy+dy+ydir[i]) + && glyph == glyph_at(cx + dx+xdir[i], cy + dy+ydir[i])) { + dx += xdir[i]; + dy += ydir[i]; + } + } else { + dx = 8 * xdir[i]; + dy = 8 * ydir[i]; + } } else continue; @@ -646,7 +795,12 @@ const char *goal; msg_given = TRUE; goto nxtc; } else if (c == Cmd.spkeys[NHKF_GETPOS_LIMITVIEW]) { - iflags.getloc_limitview = !iflags.getloc_limitview; + const char *const view_filters[NUM_GFILTER] = { + "Not limiting targets", + "Limiting targets to in sight", + "Limiting targets to in same area" + }; + iflags.getloc_filter = (iflags.getloc_filter + 1) % NUM_GFILTER; for (i = 0; i < NUM_GLOCS; i++) { if (garr[i]) { free((genericptr_t) garr[i]); @@ -654,8 +808,7 @@ const char *goal; } gidx[i] = gcount[i] = 0; } - pline("%s possible targets to those in sight only.", - iflags.getloc_limitview ? "Limiting" : "Not limiting"); + pline("%s.", view_filters[iflags.getloc_filter]); msg_given = TRUE; goto nxtc; } else if (c == Cmd.spkeys[NHKF_GETPOS_MENU]) { @@ -672,6 +825,10 @@ const char *goal; cx = u.ux; cy = u.uy; goto nxtc; + } else if (c == Cmd.spkeys[NHKF_GETPOS_MOVESKIP]) { + iflags.getloc_moveskip = !iflags.getloc_moveskip; + pline("%skipping over similar terrain when fastmoving the cursor.", + iflags.getloc_moveskip ? "S" : "Not s"); } else if ((cp = index(mMoOdDxX, c)) != 0) { /* 'm|M', 'o|O', &c */ /* nearest or farthest monster or object or door or unexplored */ int gtmp = (int) (cp - mMoOdDxX), /* 0..7 */ @@ -679,7 +836,7 @@ const char *goal; if (iflags.getloc_usemenu) { coord tmpcrd; - if (getpos_menu(&tmpcrd, iflags.getloc_limitview, gloc)) { + if (getpos_menu(&tmpcrd, gloc)) { cx = tmpcrd.x; cy = tmpcrd.y; } @@ -808,6 +965,7 @@ const char *goal; if (garr[i]) free((genericptr_t) garr[i]); getpos_hilitefunc = (void FDECL((*), (int))) 0; + getpos_getvalid = (boolean FDECL((*), (int,int))) 0; return result; } @@ -1880,7 +2038,7 @@ static const char *const sir_Terry_novels[] = { "Lords and Ladies", "Men at Arms", "Soul Music", "Interesting Times", "Maskerade", "Feet of Clay", "Hogfather", "Jingo", "The Last Continent", "Carpe Jugulum", "The Fifth Elephant", "The Truth", "Thief of Time", - "The Last Hero", "The Amazing Maurice and his Educated Rodents", + "The Last Hero", "The Amazing Maurice and His Educated Rodents", "Night Watch", "The Wee Free Men", "Monstrous Regiment", "A Hat Full of Sky", "Going Postal", "Thud!", "Wintersmith", "Making Money", "Unseen Academicals", "I Shall Wear Midnight", "Snuff", diff --git a/src/dog.c b/src/dog.c index 0b9d2ae9f..41a5e4f05 100644 --- a/src/dog.c +++ b/src/dog.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 dog.c $NHDT-Date: 1446808440 2015/11/06 11:14:00 $ $NHDT-Branch: master $:$NHDT-Revision: 1.52 $ */ +/* NetHack 3.6 dog.c $NHDT-Date: 1502753406 2017/08/14 23:30:06 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.60 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -736,7 +736,8 @@ struct monst *mon; register struct obj *obj; { struct permonst *mptr = mon->data, *fptr = 0; - boolean carni = carnivorous(mptr), herbi = herbivorous(mptr), starving; + boolean carni = carnivorous(mptr), herbi = herbivorous(mptr), + starving, mblind; if (is_quest_artifact(obj) || obj_resists(obj, 0, 95)) return obj->cursed ? TABU : APPORT; @@ -755,8 +756,10 @@ register struct obj *obj; return obj->cursed ? UNDEF : APPORT; /* a starving pet will eat almost anything */ - starving = - (mon->mtame && !mon->isminion && EDOG(mon)->mhpmax_penalty); + starving = (mon->mtame && !mon->isminion + && EDOG(mon)->mhpmax_penalty); + /* even carnivores will eat carrots if they're temporarily blind */ + mblind = (!mon->mcansee && haseyes(mon->data)); /* ghouls prefer old corpses and unhatchable eggs, yum! they'll eat fresh non-veggy corpses and hatchable eggs @@ -813,8 +816,9 @@ register struct obj *obj; case TIN: return metallivorous(mptr) ? ACCFOOD : MANFOOD; case APPLE: - case CARROT: return herbi ? DOGFOOD : starving ? ACCFOOD : MANFOOD; + case CARROT: + return (herbi || mblind) ? DOGFOOD : starving ? ACCFOOD : MANFOOD; case BANANA: return (mptr->mlet == S_YETI && herbi) ? DOGFOOD /* for monkey and ape (tameable), sasquatch */ diff --git a/src/dogmove.c b/src/dogmove.c index 321deb0af..5a385b6aa 100644 --- a/src/dogmove.c +++ b/src/dogmove.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 dogmove.c $NHDT-Date: 1463704424 2016/05/20 00:33:44 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.60 $ */ +/* NetHack 3.6 dogmove.c $NHDT-Date: 1502753407 2017/08/14 23:30:07 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.63 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -209,7 +209,7 @@ int x, y; /* dog's starting location, might be different from current */ boolean devour; { register struct edog *edog = EDOG(mtmp); - boolean poly, grow, heal, slimer, deadmimic; + boolean poly, grow, heal, eyes, slimer, deadmimic; int nutrit; long oprice; char objnambuf[BUFSZ]; @@ -226,6 +226,7 @@ boolean devour; poly = polyfodder(obj); grow = mlevelgain(obj); heal = mhealup(obj); + eyes = (obj->otyp == CARROT); if (devour) { if (mtmp->meating > 1) @@ -343,6 +344,8 @@ boolean devour; } if (heal) mtmp->mhp = mtmp->mhpmax; + if ((eyes || heal) && !mtmp->mcansee) + mcureblindness(mtmp, canseemon(mtmp)); if (deadmimic) quickmimic(mtmp); return 1; diff --git a/src/dothrow.c b/src/dothrow.c index 769be9370..a6825fcc9 100644 --- a/src/dothrow.c +++ b/src/dothrow.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 dothrow.c $NHDT-Date: 1455140444 2016/02/10 21:40:44 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.118 $ */ +/* NetHack 3.6 dothrow.c $NHDT-Date: 1502243899 2017/08/09 01:58:19 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.125 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -448,7 +448,22 @@ genericptr_t arg; int x, y, dx, dy, x_change, y_change, err, i, prev_x, prev_y; boolean keep_going = TRUE; - /* Use Bresenham's Line Algorithm to walk from src to dest */ + /* Use Bresenham's Line Algorithm to walk from src to dest. + * + * This should be replaced with a more versatile algorithm + * since it handles slanted moves in a suboptimal way. + * Going from 'x' to 'y' needs to pass through 'z', and will + * fail if there's an obstable there, but it could choose to + * pass through 'Z' instead if that way imposes no obstacle. + * ..y .Zy + * xz. vs x.. + * Perhaps we should check both paths and accept whichever + * one isn't blocked. But then multiple zigs and zags could + * potentially produce a meandering path rather than the best + * attempt at a straight line. And (*check_proc)() would + * need to work more like 'travel', distinguishing between + * testing a possible move and actually attempting that move. + */ dx = dest_cc->x - src_cc->x; dy = dest_cc->y - src_cc->y; prev_x = x = src_cc->x; @@ -640,9 +655,11 @@ int x, y; vision_recalc(1); /* update for new position */ flush_screen(1); - if (levl[x][y].typ == WATER && Is_waterlevel(&u.uz)) { - multi = 0; - drown(); + if (is_pool(x, y) && !u.uinwater + && ((Is_waterlevel(&u.uz) && levl[x][y].typ == WATER) + || !(Levitation || Flying || Wwalking))) { + multi = 0; /* can move, so drown() allows crawling out of water */ + (void) drown(); return FALSE; } @@ -768,8 +785,7 @@ boolean verbose; (void) walk_path(&uc, &cc, hurtle_step, (genericptr_t) &range); } -/* Move a monster through the air for a few squares. - */ +/* Move a monster through the air for a few squares. */ void mhurtle(mon, dx, dy, range) struct monst *mon; diff --git a/src/eat.c b/src/eat.c index 2c748ef06..552ae147b 100644 --- a/src/eat.c +++ b/src/eat.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 eat.c $NHDT-Date: 1470272344 2016/08/04 00:59:04 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.172 $ */ +/* NetHack 3.6 eat.c $NHDT-Date: 1502754159 2017/08/14 23:42:39 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.179 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -6,7 +6,7 @@ STATIC_PTR int NDECL(eatmdone); STATIC_PTR int NDECL(eatfood); -STATIC_PTR void FDECL(costly_tin, (int)); +STATIC_PTR struct obj *FDECL(costly_tin, (int)); STATIC_PTR int NDECL(opentin); STATIC_PTR int NDECL(unfaint); @@ -979,6 +979,7 @@ register int pm; u.mh = u.mhmax; else u.uhp = u.uhpmax; + make_blinded(0L, !u.ucreamed); context.botl = 1; break; case PM_STALKER: @@ -1152,7 +1153,7 @@ violated_vegetarian() /* common code to check and possibly charge for 1 context.tin.tin, * will split() context.tin.tin if necessary */ -STATIC_PTR void +STATIC_PTR struct obj * costly_tin(alter_type) int alter_type; /* COST_xxx */ { @@ -1166,6 +1167,7 @@ int alter_type; /* COST_xxx */ } costly_alteration(tin, alter_type); } + return tin; } int @@ -1293,7 +1295,7 @@ const char *mesg; r = tin_variety(tin, FALSE); if (tin->otrapped || (tin->cursed && r != HOMEMADE_TIN && !rn2(8))) { b_trapped("tin", 0); - costly_tin(COST_DSTROY); + tin = costly_tin(COST_DSTROY); goto use_up_tin; } @@ -1304,7 +1306,7 @@ const char *mesg; if (mnum == NON_PM) { pline("It turns out to be empty."); tin->dknown = tin->known = 1; - costly_tin(COST_OPEN); + tin = costly_tin(COST_OPEN); goto use_up_tin; } @@ -1333,7 +1335,7 @@ const char *mesg; You("discard the open tin."); if (!Hallucination) tin->dknown = tin->known = 1; - costly_tin(COST_OPEN); + tin = costly_tin(COST_OPEN); goto use_up_tin; } @@ -1352,7 +1354,7 @@ const char *mesg; cpostfx(mnum); /* charge for one at pre-eating cost */ - costly_tin(COST_OPEN); + tin = costly_tin(COST_OPEN); if (tintxts[r].nut < 0) /* rotten */ make_vomiting((long) rn1(15, 10), FALSE); @@ -1378,7 +1380,7 @@ const char *mesg; if (yn("Eat it?") == 'n') { if (flags.verbose) You("discard the open tin."); - costly_tin(COST_OPEN); + tin = costly_tin(COST_OPEN); goto use_up_tin; } @@ -1386,14 +1388,13 @@ const char *mesg; * Same order as with non-spinach above: * conduct update, side-effects, shop handling, and nutrition. */ - u.uconduct - .food++; /* don't need vegan/vegetarian checks for spinach */ + u.uconduct.food++; /* don't need vegetarian checks for spinach */ if (!tin->cursed) pline("This makes you feel like %s!", Hallucination ? "Swee'pea" : "Popeye"); gainstr(tin, 0, FALSE); - costly_tin(COST_OPEN); + tin = costly_tin(COST_OPEN); lesshungry(tin->blessed ? 600 /* blessed */ diff --git a/src/files.c b/src/files.c index ddba24d09..b25539954 100644 --- a/src/files.c +++ b/src/files.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 files.c $NHDT-Date: 1459987580 2016/04/07 00:06:20 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.205 $ */ +/* NetHack 3.6 files.c $NHDT-Date: 1502581476 2017/08/12 23:44:36 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.211 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -617,6 +617,7 @@ const char *name; int lev, oflag; { int reslt, fd; + if (!lftrack.init) { lftrack.init = 1; lftrack.fd = -1; @@ -671,7 +672,7 @@ int fd; } return close(fd); } -#else +#else /* !HOLD_LOCKFILE_OPEN */ int nhclose(fd) @@ -679,7 +680,7 @@ int fd; { return close(fd); } -#endif +#endif /* ?HOLD_LOCKFILE_OPEN */ /* ---------- END LEVEL FILE HANDLING ----------- */ @@ -3065,8 +3066,8 @@ const char *dir UNUSED_if_not_OS2_CODEVIEW; #ifdef VMS /* must be stream-lf to use UPDATE_RECORD_IN_PLACE */ if (!file_is_stmlf(fd)) { raw_printf( - "Warning: scoreboard file %s is not in stream_lf format", - fq_record); + "Warning: scoreboard file '%s' is not in stream_lf format", + fq_record); wait_synch(); } #endif @@ -3078,7 +3079,7 @@ const char *dir UNUSED_if_not_OS2_CODEVIEW; (void) chmod(fq_record, FCMASK | 007); #endif /* VMS && !SECURE */ } else { - raw_printf("Warning: cannot write scoreboard file %s", fq_record); + raw_printf("Warning: cannot write scoreboard file '%s'", fq_record); wait_synch(); } #endif /* !UNIX && !VMS */ @@ -3101,22 +3102,25 @@ const char *dir UNUSED_if_not_OS2_CODEVIEW; #endif if ((fd = open(fq_record, O_RDWR)) < 0) { -/* try to create empty record */ + /* try to create empty 'record' */ #if defined(AZTEC_C) || defined(_DCC) \ || (defined(__GNUC__) && defined(__AMIGA__)) /* Aztec doesn't use the third argument */ /* DICE doesn't like it */ - if ((fd = open(fq_record, O_CREAT | O_RDWR)) < 0) { + fd = open(fq_record, O_CREAT | O_RDWR); #else - if ((fd = open(fq_record, O_CREAT | O_RDWR, S_IREAD | S_IWRITE)) - < 0) { + fd = open(fq_record, O_CREAT | O_RDWR, S_IREAD | S_IWRITE); #endif - raw_printf("Warning: cannot write record %s", tmp); + if (fd = < 0) { + raw_printf("Warning: cannot write record '%s'", tmp); wait_synch(); - } else + } else { (void) nhclose(fd); - } else /* open succeeded */ + } + } else { + /* open succeeded => 'record' exists */ (void) nhclose(fd); + } #else /* MICRO || WIN32*/ #ifdef MAC @@ -3260,6 +3264,7 @@ recover_savefile() raw_printf("\nError writing %s; recovery failed.", SAVEF); (void) nhclose(gfd); (void) nhclose(sfd); + (void) nhclose(lfd); delete_savefile(); return FALSE; } @@ -3269,6 +3274,7 @@ recover_savefile() SAVEF); (void) nhclose(gfd); (void) nhclose(sfd); + (void) nhclose(lfd); delete_savefile(); return FALSE; } @@ -3279,6 +3285,7 @@ recover_savefile() SAVEF); (void) nhclose(gfd); (void) nhclose(sfd); + (void) nhclose(lfd); delete_savefile(); return FALSE; } @@ -3288,13 +3295,15 @@ recover_savefile() SAVEF); (void) nhclose(gfd); (void) nhclose(sfd); + (void) nhclose(lfd); delete_savefile(); return FALSE; } if (!copy_bytes(lfd, sfd)) { - (void) nhclose(lfd); + (void) nhclose(gfd); (void) nhclose(sfd); + (void) nhclose(lfd); delete_savefile(); return FALSE; } @@ -3302,7 +3311,7 @@ recover_savefile() processed[savelev] = 1; if (!copy_bytes(gfd, sfd)) { - (void) nhclose(lfd); + (void) nhclose(gfd); (void) nhclose(sfd); delete_savefile(); return FALSE; @@ -3343,6 +3352,7 @@ recover_savefile() for (lev = 0; lev < 256; lev++) { if (processed[lev]) { const char *fq_lock; + set_levelfile_name(lock, lev); fq_lock = fqname(lock, LEVELPREFIX, 3); (void) unlink(fq_lock); diff --git a/src/invent.c b/src/invent.c index cb1cfb2d0..b5ed81c6d 100644 --- a/src/invent.c +++ b/src/invent.c @@ -1747,7 +1747,8 @@ int FDECL((*fn), (OBJ_P)), FDECL((*ckfn), (OBJ_P)); nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") || ident || takeoff || take_out || put_in); ininv = (*objchn == invent); - bycat = (menu_class_present('B') || menu_class_present('U') + bycat = (menu_class_present('u') + || menu_class_present('B') || menu_class_present('U') || menu_class_present('C') || menu_class_present('X')); /* someday maybe we'll sort by 'olets' too (temporarily replace diff --git a/src/mkobj.c b/src/mkobj.c index aa1778a1d..78bb826f1 100644 --- a/src/mkobj.c +++ b/src/mkobj.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mkobj.c $NHDT-Date: 1462067745 2016/05/01 01:55:45 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.122 $ */ +/* NetHack 3.6 mkobj.c $NHDT-Date: 1501725405 2017/08/03 01:56:45 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.124 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2720,4 +2720,35 @@ struct obj **obj1, **obj2; return (struct obj *) 0; } +/* give a message if hero notices two globs merging [used to be in pline.c] */ +void +pudding_merge_message(otmp, otmp2) +struct obj *otmp; +struct obj *otmp2; +{ + boolean visible = (cansee(otmp->ox, otmp->oy) + || cansee(otmp2->ox, otmp2->oy)), + onfloor = (otmp->where == OBJ_FLOOR || otmp2->where == OBJ_FLOOR), + inpack = (carried(otmp) || carried(otmp2)); + + /* the player will know something happened inside his own inventory */ + if ((!Blind && visible) || inpack) { + if (Hallucination) { + if (onfloor) { + You_see("parts of the floor melting!"); + } else if (inpack) { + Your("pack reaches out and grabs something!"); + } + /* even though we can see where they should be, + * they'll be out of our view (minvent or container) + * so don't actually show anything */ + } else if (onfloor || inpack) { + pline("The %s coalesce%s.", makeplural(obj_typename(otmp->otyp)), + inpack ? " inside your pack" : ""); + } + } else { + You_hear("a faint sloshing sound."); + } +} + /*mkobj.c*/ diff --git a/src/mkroom.c b/src/mkroom.c index c76531b52..ff074cd5c 100644 --- a/src/mkroom.c +++ b/src/mkroom.c @@ -239,6 +239,26 @@ int type; } } +void +mk_zoo_thronemon(x,y) +int x,y; +{ + int i = rnd(level_difficulty()); + int pm = (i > 9) ? PM_OGRE_KING + : (i > 5) ? PM_ELVENKING + : (i > 2) ? PM_DWARF_KING + : PM_GNOME_KING; + struct monst *mon = makemon(&mons[pm], x, y, NO_MM_FLAGS); + + if (mon) { + mon->msleeping = 1; + mon->mpeaceful = 0; + set_malign(mon); + /* Give him a sceptre to pound in judgment */ + (void) mongets(mon, MACE); + } +} + void fill_zoo(sroom) struct mkroom *sroom; @@ -265,7 +285,7 @@ struct mkroom *sroom; ty = mm.y; } while (occupied((xchar) tx, (xchar) ty) && --i > 0); throne_placed: - /* TODO: try to ensure the enthroned monster is an M2_PRINCE */ + mk_zoo_thronemon(tx, ty); break; case BEEHIVE: tx = sroom->lx + (sroom->hx - sroom->lx + 1) / 2; diff --git a/src/mon.c b/src/mon.c index 69d64490b..466de5c31 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mon.c $NHDT-Date: 1496531114 2017/06/03 23:05:14 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.240 $ */ +/* NetHack 3.6 mon.c $NHDT-Date: 1502753408 2017/08/14 23:30:08 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.242 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -886,9 +886,9 @@ int meatobj(mtmp) /* for gelatinous cubes */ struct monst *mtmp; { - register struct obj *otmp, *otmp2; + struct obj *otmp, *otmp2; struct permonst *ptr, *original_ptr = mtmp->data; - int poly, grow, heal, count = 0, ecount = 0; + int poly, grow, heal, eyes, count = 0, ecount = 0; char buf[BUFSZ]; buf[0] = '\0'; @@ -986,6 +986,7 @@ struct monst *mtmp; poly = polyfodder(otmp); grow = mlevelgain(otmp); heal = mhealup(otmp); + eyes = (otmp->otyp == CARROT); delobj(otmp); /* munch */ ptr = mtmp->data; if (poly) { @@ -996,6 +997,8 @@ struct monst *mtmp; } else if (heal) { mtmp->mhp = mtmp->mhpmax; } + if ((eyes || heal) && !mtmp->mcansee) + mcureblindness(mtmp, canseemon(mtmp)); /* in case it polymorphed or died */ if (ptr != original_ptr) return !ptr ? 2 : 1; diff --git a/src/muse.c b/src/muse.c index 420c8564e..f91a88b23 100644 --- a/src/muse.c +++ b/src/muse.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 muse.c $NHDT-Date: 1469840918 2016/07/30 01:08:38 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.78 $ */ +/* NetHack 3.6 muse.c $NHDT-Date: 1502753408 2017/08/14 23:30:08 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.79 $ */ /* Copyright (C) 1990 by Ken Arromdee */ /* NetHack may be freely redistributed. See license for details. */ @@ -603,7 +603,7 @@ struct monst *mtmp; int i, fleetim, how = 0; struct obj *otmp = m.defensive; boolean vis, vismon, oseen; - const char *Mnam, *mcsa = "%s can see again."; + const char *Mnam; if ((i = precheck(mtmp, otmp)) != 0) return i; @@ -628,10 +628,7 @@ struct monst *mtmp; pline_The("tip of %s's horn glows!", mon_nam(mtmp)); } if (!mtmp->mcansee) { - mtmp->mcansee = 1; - mtmp->mblinded = 0; - if (vismon) - pline(mcsa, Monnam(mtmp)); + mcureblindness(mtmp, vismon); } else if (mtmp->mconf || mtmp->mstun) { mtmp->mconf = mtmp->mstun = 0; if (vismon) @@ -939,12 +936,8 @@ struct monst *mtmp; mtmp->mhp += i; if (mtmp->mhp > mtmp->mhpmax) mtmp->mhp = ++mtmp->mhpmax; - if (!otmp->cursed && !mtmp->mcansee) { - mtmp->mcansee = 1; - mtmp->mblinded = 0; - if (vismon) - pline(mcsa, Monnam(mtmp)); - } + if (!otmp->cursed && !mtmp->mcansee) + mcureblindness(mtmp, vismon); if (vismon) pline("%s looks better.", Monnam(mtmp)); if (oseen) @@ -957,12 +950,8 @@ struct monst *mtmp; mtmp->mhp += i; if (mtmp->mhp > mtmp->mhpmax) mtmp->mhp = (mtmp->mhpmax += (otmp->blessed ? 5 : 2)); - if (!mtmp->mcansee) { - mtmp->mcansee = 1; - mtmp->mblinded = 0; - if (vismon) - pline(mcsa, Monnam(mtmp)); - } + if (!mtmp->mcansee) + mcureblindness(mtmp, vismon); if (vismon) pline("%s looks much better.", Monnam(mtmp)); if (oseen) @@ -974,12 +963,8 @@ struct monst *mtmp; if (otmp->otyp == POT_SICKNESS) unbless(otmp); /* Pestilence */ mtmp->mhp = (mtmp->mhpmax += (otmp->blessed ? 8 : 4)); - if (!mtmp->mcansee && otmp->otyp != POT_SICKNESS) { - mtmp->mcansee = 1; - mtmp->mblinded = 0; - if (vismon) - pline(mcsa, Monnam(mtmp)); - } + if (!mtmp->mcansee && otmp->otyp != POT_SICKNESS) + mcureblindness(mtmp, vismon); if (vismon) pline("%s looks completely healed.", Monnam(mtmp)); if (oseen) @@ -2175,6 +2160,20 @@ const char *fmt, *str; return FALSE; } +/* cure mon's blindness (use_defensive, dog_eat, meatobj) */ +void +mcureblindness(mon, verbos) +struct monst *mon; +boolean verbos; +{ + if (!mon->mcansee) { + mon->mcansee = 1; + mon->mblinded = 0; + if (verbos && haseyes(mon->data)) + pline("%s can see again.", Monnam(mon)); + } +} + /* TRUE if the monster ate something */ boolean munstone(mon, by_you) diff --git a/src/objnam.c b/src/objnam.c index bb0c91a44..ec7c0e70e 100644 --- a/src/objnam.c +++ b/src/objnam.c @@ -90,8 +90,12 @@ releaseobuf(bufp) char *bufp; { /* caller may not know whether bufp is the most recently allocated - buffer; if it isn't, do nothing */ - if (bufp == obufs[obufidx]) + buffer; if it isn't, do nothing; note that because of the somewhat + obscure PREFIX handling for object name formatting by xname(), + the pointer our caller has and is passing to us might be into the + middle of an obuf rather than the address returned by nextobuf() */ + if (bufp >= obufs[obufidx] + && bufp < obufs[obufidx] + sizeof obufs[obufidx]) /* obufs[][BUFSZ] */ obufidx = (obufidx - 1 + NUMOBUF) % NUMOBUF; } @@ -100,11 +104,11 @@ obj_typename(otyp) register int otyp; { char *buf = nextobuf(); - register struct objclass *ocl = &objects[otyp]; - register const char *actualn = OBJ_NAME(*ocl); - register const char *dn = OBJ_DESCR(*ocl); - register const char *un = ocl->oc_uname; - register int nn = ocl->oc_name_known; + struct objclass *ocl = &objects[otyp]; + const char *actualn = OBJ_NAME(*ocl); + const char *dn = OBJ_DESCR(*ocl); + const char *un = ocl->oc_uname; + int nn = ocl->oc_name_known; if (Role_if(PM_SAMURAI) && Japanese_item_name(otyp)) actualn = Japanese_item_name(otyp); @@ -251,6 +255,135 @@ boolean juice; /* whether or not to append " juice" to the name */ return buf; } +/* look up a named fruit by index (1..127) */ +struct fruit * +fruit_from_indx(indx) +int indx; +{ + struct fruit *f; + + for (f = ffruit; f; f = f->nextf) + if (f->fid == indx) + break; + return f; +} + +/* look up a named fruit by name */ +struct fruit * +fruit_from_name(fname, exact, highest_fid) +const char *fname; +boolean exact; /* False => prefix or exact match, True = exact match only */ +int *highest_fid; /* optional output; only valid if 'fname' isn't found */ +{ + struct fruit *f, *tentativef; + char *altfname; + unsigned k; + /* + * note: named fruits are case-senstive... + */ + + if (highest_fid) + *highest_fid = 0; + /* first try for an exact match */ + for (f = ffruit; f; f = f->nextf) + if (!strcmp(f->fname, fname)) + return f; + else if (highest_fid && f->fid > *highest_fid) + *highest_fid = f->fid; + + /* didn't match as-is; if caller is willing to accept a prefix + match, try to find one; we want to find the longest prefix that + matches, not the first */ + if (!exact) { + tentativef = 0; + for (f = ffruit; f; f = f->nextf) { + k = strlen(f->fname); + if (!strncmp(f->fname, fname, k) + && (!fname[k] || fname[k] == ' ') + && (!tentativef || k > strlen(tentativef->fname))) + tentativef = f; + } + f = tentativef; + } + /* if we still don't have a match, try singularizing the target; + for exact match, that's trivial, but for prefix, it's hard */ + if (!f) { + altfname = makesingular(fname); + for (f = ffruit; f; f = f->nextf) { + if (!strcmp(f->fname, altfname)) + break; + } + releaseobuf(altfname); + } + if (!f && !exact) { + char fnamebuf[BUFSZ], *p; + unsigned fname_k = strlen(fname); /* length of assumed plural fname */ + + tentativef = 0; + for (f = ffruit; f; f = f->nextf) { + k = strlen(f->fname); + /* reload fnamebuf[] each iteration in case it gets modified; + there's no need to recalculate fname_k */ + Strcpy(fnamebuf, fname); + /* bug? if singular of fname is longer than plural, + failing the 'fname_k > k' test could skip a viable + candidate; unfortunately, we can't singularize until + after stripping off trailing stuff and we can't get + accurate fname_k until fname has been singularized; + compromise and use 'fname_k >= k' instead of '>', + accepting 1 char length discrepancy without risking + false match (I hope...) */ + if (fname_k >= k && (p = index(&fnamebuf[k], ' ')) != 0) { + *p = '\0'; /* truncate at 1st space past length of f->fname */ + altfname = makesingular(fnamebuf); + k = strlen(altfname); /* actually revised 'fname_k' */ + if (!strcmp(f->fname, altfname) + && (!tentativef || k > strlen(tentativef->fname))) + tentativef = f; + releaseobuf(altfname); /* avoid churning through all obufs */ + } + } + f = tentativef; + } + return f; +} + +/* sort the named-fruit linked list by fruit index number */ +void +reorder_fruit(forward) +boolean forward; +{ + struct fruit *f, *allfr[1 + 127]; + int i, j, k = SIZE(allfr); + + for (i = 0; i < k; ++i) + allfr[i] = (struct fruit *) 0; + for (f = ffruit; f; f = f->nextf) { + /* without sanity checking, this would reduce to 'allfr[f->fid]=f' */ + j = f->fid; + if (j < 1 || j >= k) { + impossible("reorder_fruit: fruit index (%d) out of range", j); + return; /* don't sort after all; should never happen... */ + } else if (allfr[j]) { + impossible("reorder_fruit: duplicate fruit index (%d)", j); + return; + } + allfr[j] = f; + } + ffruit = 0; /* reset linked list; we're rebuilding it from scratch */ + /* slot [0] will always be empty; must start 'i' at 1 to avoid + [k - i] being out of bounds during first iteration */ + for (i = 1; i < k; ++i) { + /* for forward ordering, go through indices from high to low; + for backward ordering, go from low to high */ + j = forward ? (k - i) : i; + if (allfr[j]) { + allfr[j]->nextf = ffruit; + ffruit = allfr[j]; + } + } +} + char * xname(obj) struct obj *obj; @@ -388,23 +521,20 @@ unsigned cxn_flags; /* bitmask of CXN_xxx values */ break; case FOOD_CLASS: if (typ == SLIME_MOLD) { - register struct fruit *f; + struct fruit *f = fruit_from_indx(obj->spe); - for (f = ffruit; f; f = f->nextf) { - if (f->fid == obj->spe) { - Strcpy(buf, f->fname); - break; - } - } if (!f) { impossible("Bad fruit #%d?", obj->spe); Strcpy(buf, "fruit"); - } else if (pluralize) { - /* ick; already pluralized fruit names - are allowed--we want to try to avoid - adding a redundant plural suffix */ - Strcpy(buf, makeplural(makesingular(buf))); - pluralize = FALSE; + } else { + Strcpy(buf, f->fname); + if (pluralize) { + /* ick; already pluralized fruit names + are allowed--we want to try to avoid + adding a redundant plural suffix */ + Strcpy(buf, makeplural(makesingular(buf))); + pluralize = FALSE; + } } break; } @@ -1493,7 +1623,10 @@ const char *str; buf[0] = lowc(*str); Strcpy(&buf[1], str + 1); return buf; - } else if (*str < 'A' || *str > 'Z') { + } else if (*str < 'A' || *str > 'Z' + /* treat named fruit as not a proper name, even if player + has assigned a capitalized proper name as his/her fruit */ + || fruit_from_name(str, TRUE, (int *) 0)) { /* not a proper name, needs an article */ insert_the = TRUE; } else { @@ -2010,10 +2143,14 @@ char *str; return 0; } -/* Plural routine; chiefly used for user-defined fruits. We have to try to - * account for everything reasonable the player has; something unreasonable - * can still break the code. However, it's still a lot more accurate than - * "just add an s at the end", which Rogue uses... +/* Plural routine; once upon a time it may have been chiefly used for + * user-defined fruits, but it is now used extensively throughout the + * program. + * + * For fruit, we have to try to account for everything reasonable the + * player has; something unreasonable can still break the code. + * However, it's still a lot more accurate than "just add an 's' at the + * end", which Rogue uses... * * Also used for plural monster names ("Wiped out all homunculi." or the * vanquished monsters list) and body parts. A lot of unique monsters have @@ -2847,9 +2984,14 @@ struct obj *no_wish; if (!strstri(bp, "wand ") && !strstri(bp, "spellbook ") && !strstri(bp, "finger ")) { if ((p = strstri(bp, "tin of ")) != 0) { - tmp = tin_variety_txt(p + 7, &tinv); - tvariety = tinv; - mntmp = name_to_mon(p + 7 + tmp); + if (!strcmpi(p + 7, "spinach")) { + contents = SPINACH; + mntmp = NON_PM; + } else { + tmp = tin_variety_txt(p + 7, &tinv); + tvariety = tinv; + mntmp = name_to_mon(p + 7 + tmp); + } typ = TIN; goto typfnd; } else if ((p = strstri(bp, " of ")) != 0 @@ -2858,35 +3000,32 @@ struct obj *no_wish; } } /* Find corpse type w/o "of" (red dragon scale mail, yeti corpse) */ - if (strncmpi(bp, "samurai sword", 13)) /* not the "samurai" monster! */ - if (strncmpi(bp, "wizard lock", 11)) /* not the "wizard" monster! */ - if (strncmpi(bp, "ninja-to", 8)) /* not the "ninja" rank */ - if (strncmpi(bp, "master key", - 10)) /* not the "master" rank */ - if (strncmpi(bp, "magenta", 7)) /* not the "mage" rank */ - if (mntmp < LOW_PM && strlen(bp) > 2 - && (mntmp = name_to_mon(bp)) >= LOW_PM) { - int mntmptoo, - mntmplen; /* double check for rank title */ - char *obp = bp; - mntmptoo = title_to_mon(bp, (int *) 0, &mntmplen); - bp += mntmp != mntmptoo - ? (int) strlen(mons[mntmp].mname) + if (strncmpi(bp, "samurai sword", 13) /* not the "samurai" monster! */ + && strncmpi(bp, "wizard lock", 11) /* not the "wizard" monster! */ + && strncmpi(bp, "ninja-to", 8) /* not the "ninja" rank */ + && strncmpi(bp, "master key", 10) /* not the "master" rank */ + && strncmpi(bp, "magenta", 7)) { /* not the "mage" rank */ + if (mntmp < LOW_PM && strlen(bp) > 2 + && (mntmp = name_to_mon(bp)) >= LOW_PM) { + int mntmptoo, mntmplen; /* double check for rank title */ + char *obp = bp; + + mntmptoo = title_to_mon(bp, (int *) 0, &mntmplen); + bp += (mntmp != mntmptoo) ? (int) strlen(mons[mntmp].mname) : mntmplen; - if (*bp == ' ') - bp++; - else if (!strncmpi(bp, "s ", 2)) - bp += 2; - else if (!strncmpi(bp, "es ", 3)) - bp += 3; - else if (!*bp && !actualn && !dn && !un - && !oclass) { - /* no referent; they don't really mean a - * monster type */ - bp = obp; - mntmp = NON_PM; - } - } + if (*bp == ' ') { + bp++; + } else if (!strncmpi(bp, "s ", 2)) { + bp += 2; + } else if (!strncmpi(bp, "es ", 3)) { + bp += 3; + } else if (!*bp && !actualn && !dn && !un && !oclass) { + /* no referent; they don't really mean a monster type */ + bp = obp; + mntmp = NON_PM; + } + } + } /* first change to singular if necessary */ if (*bp) { @@ -2952,7 +3091,8 @@ struct obj *no_wish; * gold/money concept. Maybe we want to add other monetary units as * well in the future. (TH) */ - if (!BSTRCMPI(bp, p - 10, "gold piece") || !BSTRCMPI(bp, p - 7, "zorkmid") + if (!BSTRCMPI(bp, p - 10, "gold piece") + || !BSTRCMPI(bp, p - 7, "zorkmid") || !strcmpi(bp, "gold") || !strcmpi(bp, "money") || !strcmpi(bp, "coin") || *bp == GOLD_SYM) { if (cnt > 5000 && !wizard) @@ -2975,15 +3115,19 @@ struct obj *no_wish; /* Search for class names: XXXXX potion, scroll of XXXXX. Avoid */ /* false hits on, e.g., rings for "ring mail". */ - if (strncmpi(bp, "enchant ", 8) && strncmpi(bp, "destroy ", 8) + if (strncmpi(bp, "enchant ", 8) + && strncmpi(bp, "destroy ", 8) && strncmpi(bp, "detect food", 11) - && strncmpi(bp, "food detection", 14) && strncmpi(bp, "ring mail", 9) + && strncmpi(bp, "food detection", 14) + && strncmpi(bp, "ring mail", 9) && strncmpi(bp, "studded leather armor", 21) && strncmpi(bp, "leather armor", 13) - && strncmpi(bp, "tooled horn", 11) && strncmpi(bp, "food ration", 11) + && strncmpi(bp, "tooled horn", 11) + && strncmpi(bp, "food ration", 11) && strncmpi(bp, "meat ring", 9)) for (i = 0; i < (int) (sizeof wrpsym); i++) { register int j = strlen(wrp[i]); + if (!strncmpi(bp, wrp[i], j)) { oclass = wrpsym[i]; if (oclass != AMULET_CLASS) { @@ -3099,11 +3243,17 @@ srch: for (i = bases[GEM_CLASS]; i <= LAST_GEM; i++) { register const char *zn; - if ((zn = OBJ_NAME(objects[i])) && !strcmpi(actualn, zn)) { + if ((zn = OBJ_NAME(objects[i])) != 0 && !strcmpi(actualn, zn)) { typ = i; goto typfnd; } } + /* "tin of foo" would be caught above, but plain "tin" has + a random chance of yielding "tin wand" unless we do this */ + if (!strcmpi(actualn, "tin")) { + typ = TIN; + goto typfnd; + } } if (((typ = rnd_otyp_by_namedesc(actualn, oclass)) != STRANGE_OBJECT) diff --git a/src/options.c b/src/options.c index b7ee5f0ba..0bfacc09d 100644 --- a/src/options.c +++ b/src/options.c @@ -233,7 +233,7 @@ static struct Bool_Opt { { "vt_tiledata", (boolean *) 0, FALSE, SET_IN_FILE }, #endif { "whatis_menu", &iflags.getloc_usemenu, FALSE, SET_IN_GAME }, - { "whatis_inview", &iflags.getloc_limitview, FALSE, SET_IN_GAME }, + { "whatis_moveskip", &iflags.getloc_moveskip, FALSE, SET_IN_GAME }, { "wizweight", &iflags.wizweight, FALSE, SET_IN_WIZGAME }, { "wraptext", &iflags.wc2_wraptext, FALSE, SET_IN_GAME }, #ifdef ZEROCOMP @@ -403,6 +403,8 @@ static struct Comp_Opt { #endif { "whatis_coord", "show coordinates when auto-describing cursor position", 1, SET_IN_GAME }, + { "whatis_filter", "filter coordinate locations when targeting next or previous", + 1, SET_IN_GAME }, { "windowcolors", "the foreground/background colors of windows", /*WC*/ 80, DISP_IN_GAME }, { "windowtype", "windowing system to use", WINTYPELEN, DISP_IN_GAME }, @@ -2341,32 +2343,32 @@ boolean tinitial, tfrom_file; return; if (!initial) { struct fruit *f; + int fnum = 0; - num = 0; - for (f = ffruit; f; f = f->nextf) { - if (!strcmp(op, f->fname)) - break; - num++; - } - if (!flags.made_fruit) { - for (forig = ffruit; forig; forig = forig->nextf) { - if (!strcmp(pl_fruit, forig->fname)) { - break; - } + /* count number of named fruits; if 'op' is found among them, + then the count doesn't matter because we won't be adding it */ + f = fruit_from_name(op, FALSE, &fnum); + if (!f) { + if (!flags.made_fruit) + forig = fruit_from_name(pl_fruit, FALSE, (int *) 0); + + if (!forig && fnum >= 100) { + pline("Doing that so many times isn't very fruitful."); + return; } } - if (!forig && num >= 100) { - pline("Doing that so many times isn't very fruitful."); - return; - } } goodfruit: nmcpy(pl_fruit, op, PL_FSIZ); sanitize_name(pl_fruit); - /* OBJ_NAME(objects[SLIME_MOLD]) won't work after initialization */ + /* OBJ_NAME(objects[SLIME_MOLD]) won't work for this after + initialization; it gets changed to generic "fruit" */ if (!*pl_fruit) nmcpy(pl_fruit, "slime mold", PL_FSIZ); if (!initial) { + /* if 'forig' is nonNull, we replace it rather than add + a new fruit; it can only be nonNull if no fruits have + been created since the previous name was put in place */ (void) fruitadd(pl_fruit, forig); pline("Fruit is now \"%s\".", pl_fruit); } @@ -2379,7 +2381,7 @@ boolean tinitial, tfrom_file; } fullname = "whatis_coord"; - if (match_optname(opts, fullname, 6, TRUE)) { + if (match_optname(opts, fullname, 8, TRUE)) { if (duplicate) complain_about_duplicate(opts, 1); if (negated) { @@ -2399,6 +2401,33 @@ boolean tinitial, tfrom_file; return; } + fullname = "whatis_filter"; + if (match_optname(opts, fullname, 8, TRUE)) { + if (duplicate) + complain_about_duplicate(opts, 1); + if (negated) { + iflags.getloc_filter = GFILTER_NONE; + return; + } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) { + char c = lowc(*op); + + switch (c) { + case 'n': + iflags.getloc_filter = GFILTER_NONE; + break; + case 'v': + iflags.getloc_filter = GFILTER_VIEW; + break; + case 'a': + iflags.getloc_filter = GFILTER_AREA; + break; + default: + badoption(opts); + } + } + return; + } + fullname = "warnings"; if (match_optname(opts, fullname, 5, TRUE)) { if (duplicate) @@ -4283,6 +4312,37 @@ boolean setinitial, setfromfile; free((genericptr_t) window_pick); } destroy_nhwindow(tmpwin); + } else if (!strcmp("whatis_filter", optname)) { + menu_item *window_pick = (menu_item *) 0; + int pick_cnt; + char gf = iflags.getloc_filter; + + tmpwin = create_nhwindow(NHW_MENU); + start_menu(tmpwin); + any = zeroany; + any.a_char = (GFILTER_NONE + 1); + add_menu(tmpwin, NO_GLYPH, &any, 'n', + 0, ATR_NONE, "no filtering", + (gf == GFILTER_NONE) ? MENU_SELECTED : MENU_UNSELECTED); + any.a_char = (GFILTER_VIEW + 1); + add_menu(tmpwin, NO_GLYPH, &any, 'v', + 0, ATR_NONE, "in view only", + (gf == GFILTER_VIEW) ? MENU_SELECTED : MENU_UNSELECTED); + any.a_char = (GFILTER_AREA + 1); + add_menu(tmpwin, NO_GLYPH, &any, 'a', + 0, ATR_NONE, "in same area", + (gf == GFILTER_AREA) ? MENU_SELECTED : MENU_UNSELECTED); + end_menu(tmpwin, + "Select location filtering when going for next/previous map position:"); + if ((pick_cnt = select_menu(tmpwin, PICK_ONE, &window_pick)) > 0) { + iflags.getloc_filter = (window_pick[0].item.a_char - 1); + /* PICK_ONE doesn't unselect preselected entry when + selecting another one */ + if (pick_cnt > 1 && iflags.getloc_filter == gf) + iflags.getloc_filter = (window_pick[1].item.a_char - 1); + free((genericptr_t) window_pick); + } + destroy_nhwindow(tmpwin); } else if (!strcmp("msg_window", optname)) { #ifdef TTY_GRAPHICS /* by Christian W. Cooper */ @@ -5057,6 +5117,11 @@ char *buf; : (iflags.getpos_coords == GPCOORDS_COMFULL) ? "full compass" : (iflags.getpos_coords == GPCOORDS_SCREEN) ? "screen" : "none"); + } else if (!strcmp(optname, "whatis_filter")) { + Sprintf(buf, "%s", + (iflags.getloc_filter == GFILTER_VIEW) ? "view" + : (iflags.getloc_filter == GFILTER_AREA) ? "area" + : "none"); } else if (!strcmp(optname, "scores")) { Sprintf(buf, "%d top/%d around%s", flags.end_top, flags.end_around, flags.end_own ? "/own" : ""); @@ -5574,7 +5639,6 @@ struct fruit *replace_fruit; /* disallow naming after other foods (since it'd be impossible * to tell the difference) */ - for (i = bases[FOOD_CLASS]; objects[i].oc_class == FOOD_CLASS; i++) { if (!strcmp(OBJ_NAME(objects[i]), pl_fruit)) { found = TRUE; @@ -5584,15 +5648,15 @@ struct fruit *replace_fruit; { char *c; - c = pl_fruit; - for (c = pl_fruit; *c >= '0' && *c <= '9'; c++) - ; + continue; if (isspace((uchar) *c) || *c == 0) numeric = TRUE; } - if (found || numeric || !strncmp(str, "cursed ", 7) - || !strncmp(str, "uncursed ", 9) || !strncmp(str, "blessed ", 8) + if (found || numeric + || !strncmp(str, "cursed ", 7) + || !strncmp(str, "uncursed ", 9) + || !strncmp(str, "blessed ", 8) || !strncmp(str, "partly eaten ", 13) || (!strncmp(str, "tin of ", 7) && (!strcmp(str + 7, "spinach") @@ -5615,42 +5679,39 @@ struct fruit *replace_fruit; */ flags.made_fruit = FALSE; if (replace_fruit) { - for (f = ffruit; f; f = f->nextf) { - if (f == replace_fruit) { - copynchars(f->fname, str, PL_FSIZ - 1); - goto nonew; - } - } + /* replace_fruit is already part of the fruit chain; + update it in place rather than looking it up again */ + f = replace_fruit; + copynchars(f->fname, str, PL_FSIZ - 1); + goto nonew; } } else { /* not user_supplied, so assumed to be from bones */ copynchars(altname, str, PL_FSIZ - 1); sanitize_name(altname); flags.made_fruit = TRUE; /* for safety. Any fruit name added from a - bones level should exist anyway. */ + * bones level should exist anyway. */ } - for (f = ffruit; f; f = f->nextf) { - if (f->fid > highest_fruit_id) - highest_fruit_id = f->fid; - if (!strncmp(str, f->fname, PL_FSIZ - 1) - || (*altname && !strcmp(altname, f->fname))) - goto nonew; - } - /* if adding another fruit would overflow spe, use a random - fruit instead... we've got a lot to choose from. + f = fruit_from_name(*altname ? altname : str, FALSE, &highest_fruit_id); + if (f) + goto nonew; + + /* Maximum number of named fruits is 127, even if obj->spe can + handle bigger values. If adding another fruit would overflow, + use a random fruit instead... we've got a lot to choose from. current_fruit remains as is. */ if (highest_fruit_id >= 127) return rnd(127); f = newfruit(); - (void) memset((genericptr_t)f, 0, sizeof(struct fruit)); + (void) memset((genericptr_t) f, 0, sizeof (struct fruit)); copynchars(f->fname, *altname ? altname : str, PL_FSIZ - 1); f->fid = ++highest_fruit_id; /* we used to go out of our way to add it at the end of the list, but the order is arbitrary so use simpler insertion at start */ f->nextf = ffruit; ffruit = f; -nonew: + nonew: if (user_specified) context.current_fruit = f->fid; return f->fid; diff --git a/src/pickup.c b/src/pickup.c index 2395c4110..0b91a4bb4 100644 --- a/src/pickup.c +++ b/src/pickup.c @@ -177,6 +177,8 @@ int *menu_on_demand; } if (itemcount && menu_on_demand) ilets[iletct++] = 'm'; + if (count_unpaid(objs)) + ilets[iletct++] = 'u'; tally_BUCX(objs, here, &bcnt, &ucnt, &ccnt, &xcnt, &ocnt); if (bcnt) @@ -222,8 +224,8 @@ int *menu_on_demand; goto ask_again; } else if (sym == 'm') { m_seen = TRUE; - } else if (index("BUCX", sym)) { - add_valid_menu_class(sym); /* 'B','U','C',or 'X' */ + } else if (index("uBUCX", sym)) { + add_valid_menu_class(sym); /* 'u' or 'B','U','C',or 'X' */ filtered = TRUE; } else { oc_of_sym = def_char_to_objclass(sym); @@ -2666,7 +2668,7 @@ boolean put_in; } else if (flags.menu_style == MENU_FULL) { all_categories = FALSE; Sprintf(buf, "%s what type of objects?", action); - mflags = (ALL_TYPES | BUCX_TYPES); + mflags = (ALL_TYPES | UNPAID_TYPES | BUCX_TYPES); if (put_in) mflags |= CHOOSE_ALL; n = query_category(buf, put_in ? invent : current_container->cobj, diff --git a/src/pline.c b/src/pline.c index 2c174e672..07e55e679 100644 --- a/src/pline.c +++ b/src/pline.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 pline.c $NHDT-Date: 1490908465 2017/03/30 21:14:25 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.58 $ */ +/* NetHack 3.6 pline.c $NHDT-Date: 1501803108 2017/08/03 23:31:48 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.61 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -435,276 +435,12 @@ VA_DECL(const char *, s) Vsprintf(pbuf, s, VA_ARGS); pbuf[BUFSZ - 1] = '\0'; /* sanity */ paniclog("impossible", pbuf); - pline("%s", pbuf); - pline("Program in disorder - perhaps you'd better #quit."); + pline("%s", VA_PASS1(pbuf)); + pline("%s", VA_PASS1("Program in disorder - perhaps you'd better #quit.")); program_state.in_impossible = 0; VA_END(); } -const char * -align_str(alignment) -aligntyp alignment; -{ - switch ((int) alignment) { - case A_CHAOTIC: - return "chaotic"; - case A_NEUTRAL: - return "neutral"; - case A_LAWFUL: - return "lawful"; - case A_NONE: - return "unaligned"; - } - return "unknown"; -} - -void -mstatusline(mtmp) -register struct monst *mtmp; -{ - aligntyp alignment = mon_aligntyp(mtmp); - char info[BUFSZ], monnambuf[BUFSZ]; - - info[0] = 0; - if (mtmp->mtame) { - Strcat(info, ", tame"); - if (wizard) { - Sprintf(eos(info), " (%d", mtmp->mtame); - if (!mtmp->isminion) - Sprintf(eos(info), "; hungry %ld; apport %d", - EDOG(mtmp)->hungrytime, EDOG(mtmp)->apport); - Strcat(info, ")"); - } - } else if (mtmp->mpeaceful) - Strcat(info, ", peaceful"); - - if (mtmp->data == &mons[PM_LONG_WORM]) { - int segndx, nsegs = count_wsegs(mtmp); - - /* the worm code internals don't consider the head of be one of - the worm's segments, but we count it as such when presenting - worm feedback to the player */ - if (!nsegs) { - Strcat(info, ", single segment"); - } else { - ++nsegs; /* include head in the segment count */ - segndx = wseg_at(mtmp, bhitpos.x, bhitpos.y); - Sprintf(eos(info), ", %d%s of %d segments", - segndx, ordin(segndx), nsegs); - } - } - if (mtmp->cham >= LOW_PM && mtmp->data != &mons[mtmp->cham]) - /* don't reveal the innate form (chameleon, vampire, &c), - just expose the fact that this current form isn't it */ - Strcat(info, ", shapechanger"); - /* pets eating mimic corpses mimic while eating, so this comes first */ - if (mtmp->meating) - Strcat(info, ", eating"); - /* a stethoscope exposes mimic before getting here so this - won't be relevant for it, but wand of probing doesn't */ - if (mtmp->mundetected || mtmp->m_ap_type) - mhidden_description(mtmp, TRUE, eos(info)); - if (mtmp->mcan) - Strcat(info, ", cancelled"); - if (mtmp->mconf) - Strcat(info, ", confused"); - if (mtmp->mblinded || !mtmp->mcansee) - Strcat(info, ", blind"); - if (mtmp->mstun) - Strcat(info, ", stunned"); - if (mtmp->msleeping) - Strcat(info, ", asleep"); -#if 0 /* unfortunately mfrozen covers temporary sleep and being busy \ - (donning armor, for instance) as well as paralysis */ - else if (mtmp->mfrozen) - Strcat(info, ", paralyzed"); -#else - else if (mtmp->mfrozen || !mtmp->mcanmove) - Strcat(info, ", can't move"); -#endif - /* [arbitrary reason why it isn't moving] */ - else if (mtmp->mstrategy & STRAT_WAITMASK) - Strcat(info, ", meditating"); - if (mtmp->mflee) - Strcat(info, ", scared"); - if (mtmp->mtrapped) - Strcat(info, ", trapped"); - if (mtmp->mspeed) - Strcat(info, mtmp->mspeed == MFAST ? ", fast" : mtmp->mspeed == MSLOW - ? ", slow" - : ", ???? speed"); - if (mtmp->minvis) - Strcat(info, ", invisible"); - if (mtmp == u.ustuck) - Strcat(info, sticks(youmonst.data) - ? ", held by you" - : !u.uswallow ? ", holding you" - : attacktype_fordmg(u.ustuck->data, - AT_ENGL, AD_DGST) - ? ", digesting you" - : is_animal(u.ustuck->data) - ? ", swallowing you" - : ", engulfing you"); - if (mtmp == u.usteed) - Strcat(info, ", carrying you"); - - /* avoid "Status of the invisible newt ..., invisible" */ - /* and unlike a normal mon_nam, use "saddled" even if it has a name */ - Strcpy(monnambuf, x_monnam(mtmp, ARTICLE_THE, (char *) 0, - (SUPPRESS_IT | SUPPRESS_INVISIBLE), FALSE)); - - pline("Status of %s (%s): Level %d HP %d(%d) AC %d%s.", monnambuf, - align_str(alignment), mtmp->m_lev, mtmp->mhp, mtmp->mhpmax, - find_mac(mtmp), info); -} - -void -ustatusline() -{ - char info[BUFSZ]; - - info[0] = '\0'; - if (Sick) { - Strcat(info, ", dying from"); - if (u.usick_type & SICK_VOMITABLE) - Strcat(info, " food poisoning"); - if (u.usick_type & SICK_NONVOMITABLE) { - if (u.usick_type & SICK_VOMITABLE) - Strcat(info, " and"); - Strcat(info, " illness"); - } - } - if (Stoned) - Strcat(info, ", solidifying"); - if (Slimed) - Strcat(info, ", becoming slimy"); - if (Strangled) - Strcat(info, ", being strangled"); - if (Vomiting) - Strcat(info, ", nauseated"); /* !"nauseous" */ - if (Confusion) - Strcat(info, ", confused"); - if (Blind) { - Strcat(info, ", blind"); - if (u.ucreamed) { - if ((long) u.ucreamed < Blinded || Blindfolded - || !haseyes(youmonst.data)) - Strcat(info, ", cover"); - Strcat(info, "ed by sticky goop"); - } /* note: "goop" == "glop"; variation is intentional */ - } - if (Stunned) - Strcat(info, ", stunned"); - if (!u.usteed && Wounded_legs) { - const char *what = body_part(LEG); - if ((Wounded_legs & BOTH_SIDES) == BOTH_SIDES) - what = makeplural(what); - Sprintf(eos(info), ", injured %s", what); - } - if (Glib) - Sprintf(eos(info), ", slippery %s", makeplural(body_part(HAND))); - if (u.utrap) - Strcat(info, ", trapped"); - if (Fast) - Strcat(info, Very_fast ? ", very fast" : ", fast"); - if (u.uundetected) - Strcat(info, ", concealed"); - if (Invis) - Strcat(info, ", invisible"); - if (u.ustuck) { - if (sticks(youmonst.data)) - Strcat(info, ", holding "); - else - Strcat(info, ", held by "); - Strcat(info, mon_nam(u.ustuck)); - } - - pline("Status of %s (%s): Level %d HP %d(%d) AC %d%s.", plname, - piousness(FALSE, align_str(u.ualign.type)), - Upolyd ? mons[u.umonnum].mlevel : u.ulevel, Upolyd ? u.mh : u.uhp, - Upolyd ? u.mhmax : u.uhpmax, u.uac, info); -} - -void -self_invis_message() -{ - pline("%s %s.", - Hallucination ? "Far out, man! You" : "Gee! All of a sudden, you", - See_invisible ? "can see right through yourself" - : "can't see yourself"); -} - -char * -piousness(showneg, suffix) -boolean showneg; -const char *suffix; -{ - static char buf[32]; /* bigger than "insufficiently neutral" */ - const char *pio; - - /* note: piousness 20 matches MIN_QUEST_ALIGN (quest.h) */ - if (u.ualign.record >= 20) - pio = "piously"; - else if (u.ualign.record > 13) - pio = "devoutly"; - else if (u.ualign.record > 8) - pio = "fervently"; - else if (u.ualign.record > 3) - pio = "stridently"; - else if (u.ualign.record == 3) - pio = ""; - else if (u.ualign.record > 0) - pio = "haltingly"; - else if (u.ualign.record == 0) - pio = "nominally"; - else if (!showneg) - pio = "insufficiently"; - else if (u.ualign.record >= -3) - pio = "strayed"; - else if (u.ualign.record >= -8) - pio = "sinned"; - else - pio = "transgressed"; - - Sprintf(buf, "%s", pio); - if (suffix && (!showneg || u.ualign.record >= 0)) { - if (u.ualign.record != 3) - Strcat(buf, " "); - Strcat(buf, suffix); - } - return buf; -} - -void -pudding_merge_message(otmp, otmp2) -struct obj *otmp; -struct obj *otmp2; -{ - boolean visible = - cansee(otmp->ox, otmp->oy) || cansee(otmp2->ox, otmp2->oy); - boolean onfloor = otmp->where == OBJ_FLOOR || otmp2->where == OBJ_FLOOR; - boolean inpack = carried(otmp) || carried(otmp2); - - /* the player will know something happened inside his own inventory */ - if ((!Blind && visible) || inpack) { - if (Hallucination) { - if (onfloor) { - You_see("parts of the floor melting!"); - } else if (inpack) { - Your("pack reaches out and grabs something!"); - } - /* even though we can see where they should be, - * they'll be out of our view (minvent or container) - * so don't actually show anything */ - } else if (onfloor || inpack) { - pline("The %s coalesce%s.", makeplural(obj_typename(otmp->otyp)), - inpack ? " inside your pack" : ""); - } - } else { - You_hear("a faint sloshing sound."); - } -} - #if defined(MSGHANDLER) && (defined(POSIX_TYPES) || defined(__GNUC__)) static boolean use_pline_handler = TRUE; static void @@ -732,16 +468,16 @@ const char *line; (void) setuid(getuid()); (void) execv(args[0], (char *const *) args); perror((char *) 0); - (void) fprintf(stderr, "Exec to message handler %s failed.\n", - env); + (void) fprintf(stderr, "Exec to message handler %s failed.\n", env); terminate(EXIT_FAILURE); } else if (f > 0) { int status; + waitpid(f, &status, 0); } else if (f == -1) { perror((char *) 0); use_pline_handler = FALSE; - pline("Fork to message handler failed."); + pline("%s", VA_PASS1("Fork to message handler failed.")); } } #endif /* defined(POSIX_TYPES) || defined(__GNUC__) */ diff --git a/src/potion.c b/src/potion.c index 38f5c6553..1a7e08ecc 100644 --- a/src/potion.c +++ b/src/potion.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 potion.c $NHDT-Date: 1455407631 2016/02/13 23:53:51 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.129 $ */ +/* NetHack 3.6 potion.c $NHDT-Date: 1502753790 2017/08/14 23:36:30 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.138 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -408,6 +408,16 @@ boolean talk; } } +void +self_invis_message() +{ + pline("%s %s.", + Hallucination ? "Far out, man! You" + : "Gee! All of a sudden, you", + See_invisible ? "can see right through yourself" + : "can't see yourself"); +} + STATIC_OVL void ghost_from_bottle() { @@ -1333,15 +1343,22 @@ boolean your_fault; if (useeit && !affected) pline("%s %s wet.", buf, aobjnam(saddle, "get")); } else { - boolean angermon = your_fault; + boolean angermon = your_fault, cureblind = FALSE; switch (obj->otyp) { - case POT_HEALING: - case POT_EXTRA_HEALING: case POT_FULL_HEALING: + cureblind = TRUE; + /*FALLTHRU*/ + case POT_EXTRA_HEALING: + if (!obj->cursed) + cureblind = TRUE; + /*FALLTHRU*/ + case POT_HEALING: + if (obj->blessed) + cureblind = TRUE; if (mon->data == &mons[PM_PESTILENCE]) goto do_illness; - /*FALLTHRU*/ + /*FALLTHRU*/ case POT_RESTORE_ABILITY: case POT_GAIN_ABILITY: do_healing: @@ -1351,6 +1368,8 @@ boolean your_fault; if (canseemon(mon)) pline("%s looks sound and hale again.", Monnam(mon)); } + if (cureblind) + mcureblindness(mon, canseemon(mon)); break; case POT_SICKNESS: if (mon->data == &mons[PM_PESTILENCE]) @@ -1409,7 +1428,7 @@ boolean your_fault; break; case POT_BLINDNESS: if (haseyes(mon->data)) { - register int btmp = 64 + rn2(32) + int btmp = 64 + rn2(32) + rn2(32) * !resist(mon, POTION_CLASS, 0, NOTELL); btmp += mon->mblinded; @@ -1524,7 +1543,8 @@ void potionbreathe(obj) register struct obj *obj; { - register int i, ii, isdone, kn = 0; + int i, ii, isdone, kn = 0; + boolean cureblind = FALSE; switch (obj->otyp) { case POT_RESTORE_ABILITY: @@ -1559,18 +1579,25 @@ register struct obj *obj; u.mh++, context.botl = 1; if (u.uhp < u.uhpmax) u.uhp++, context.botl = 1; + cureblind = TRUE; /*FALLTHRU*/ case POT_EXTRA_HEALING: if (Upolyd && u.mh < u.mhmax) u.mh++, context.botl = 1; if (u.uhp < u.uhpmax) u.uhp++, context.botl = 1; + if (!obj->cursed) + cureblind = TRUE; /*FALLTHRU*/ case POT_HEALING: if (Upolyd && u.mh < u.mhmax) u.mh++, context.botl = 1; if (u.uhp < u.uhpmax) u.uhp++, context.botl = 1; + if (obj->blessed) + cureblind = TRUE; + if (cureblind) + make_blinded(0L, !u.ucreamed); exercise(A_CON, TRUE); break; case POT_SICKNESS: diff --git a/src/priest.c b/src/priest.c index 0cce5cf36..4a3dd185d 100644 --- a/src/priest.c +++ b/src/priest.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 priest.c $NHDT-Date: 1446892452 2015/11/07 10:34:12 $ $NHDT-Branch: master $:$NHDT-Revision: 1.41 $ */ +/* NetHack 3.6 priest.c $NHDT-Date: 1501725407 2017/08/03 01:56:47 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.44 $ */ /* Copyright (c) Izchak Miller, Steve Linhart, 1989. */ /* NetHack may be freely redistributed. See license for details. */ @@ -852,4 +852,242 @@ boolean ghostly; } } +/* + * align_str(), piousness(), mstatusline() and ustatusline() used to be + * in pline.c, presumeably because the latter two generate one line of + * output. The USE_OLDARGS config gets warnings from 2016ish-vintage + * gcc (for -Wint-to-pointer-cast, activated by -Wall or -W) when they + * follow pline() itself. Fixing up the variadic calls like is done for + * lev_comp would be needlessly messy there. + * + * They don't belong here. If/when enlightenment ever gets split off + * from cmd.c (which definitely doesn't belong there), they should go + * with it. + */ + +const char * +align_str(alignment) +aligntyp alignment; +{ + switch ((int) alignment) { + case A_CHAOTIC: + return "chaotic"; + case A_NEUTRAL: + return "neutral"; + case A_LAWFUL: + return "lawful"; + case A_NONE: + return "unaligned"; + } + return "unknown"; +} + +/* used for self-probing */ +char * +piousness(showneg, suffix) +boolean showneg; +const char *suffix; +{ + static char buf[32]; /* bigger than "insufficiently neutral" */ + const char *pio; + + /* note: piousness 20 matches MIN_QUEST_ALIGN (quest.h) */ + if (u.ualign.record >= 20) + pio = "piously"; + else if (u.ualign.record > 13) + pio = "devoutly"; + else if (u.ualign.record > 8) + pio = "fervently"; + else if (u.ualign.record > 3) + pio = "stridently"; + else if (u.ualign.record == 3) + pio = ""; + else if (u.ualign.record > 0) + pio = "haltingly"; + else if (u.ualign.record == 0) + pio = "nominally"; + else if (!showneg) + pio = "insufficiently"; + else if (u.ualign.record >= -3) + pio = "strayed"; + else if (u.ualign.record >= -8) + pio = "sinned"; + else + pio = "transgressed"; + + Sprintf(buf, "%s", pio); + if (suffix && (!showneg || u.ualign.record >= 0)) { + if (u.ualign.record != 3) + Strcat(buf, " "); + Strcat(buf, suffix); + } + return buf; +} + +/* stethoscope or probing applied to monster -- one-line feedback */ +void +mstatusline(mtmp) +struct monst *mtmp; +{ + aligntyp alignment = mon_aligntyp(mtmp); + char info[BUFSZ], monnambuf[BUFSZ]; + + info[0] = 0; + if (mtmp->mtame) { + Strcat(info, ", tame"); + if (wizard) { + Sprintf(eos(info), " (%d", mtmp->mtame); + if (!mtmp->isminion) + Sprintf(eos(info), "; hungry %ld; apport %d", + EDOG(mtmp)->hungrytime, EDOG(mtmp)->apport); + Strcat(info, ")"); + } + } else if (mtmp->mpeaceful) + Strcat(info, ", peaceful"); + + if (mtmp->data == &mons[PM_LONG_WORM]) { + int segndx, nsegs = count_wsegs(mtmp); + + /* the worm code internals don't consider the head of be one of + the worm's segments, but we count it as such when presenting + worm feedback to the player */ + if (!nsegs) { + Strcat(info, ", single segment"); + } else { + ++nsegs; /* include head in the segment count */ + segndx = wseg_at(mtmp, bhitpos.x, bhitpos.y); + Sprintf(eos(info), ", %d%s of %d segments", + segndx, ordin(segndx), nsegs); + } + } + if (mtmp->cham >= LOW_PM && mtmp->data != &mons[mtmp->cham]) + /* don't reveal the innate form (chameleon, vampire, &c), + just expose the fact that this current form isn't it */ + Strcat(info, ", shapechanger"); + /* pets eating mimic corpses mimic while eating, so this comes first */ + if (mtmp->meating) + Strcat(info, ", eating"); + /* a stethoscope exposes mimic before getting here so this + won't be relevant for it, but wand of probing doesn't */ + if (mtmp->mundetected || mtmp->m_ap_type) + mhidden_description(mtmp, TRUE, eos(info)); + if (mtmp->mcan) + Strcat(info, ", cancelled"); + if (mtmp->mconf) + Strcat(info, ", confused"); + if (mtmp->mblinded || !mtmp->mcansee) + Strcat(info, ", blind"); + if (mtmp->mstun) + Strcat(info, ", stunned"); + if (mtmp->msleeping) + Strcat(info, ", asleep"); +#if 0 /* unfortunately mfrozen covers temporary sleep and being busy \ + (donning armor, for instance) as well as paralysis */ + else if (mtmp->mfrozen) + Strcat(info, ", paralyzed"); +#else + else if (mtmp->mfrozen || !mtmp->mcanmove) + Strcat(info, ", can't move"); +#endif + /* [arbitrary reason why it isn't moving] */ + else if (mtmp->mstrategy & STRAT_WAITMASK) + Strcat(info, ", meditating"); + if (mtmp->mflee) + Strcat(info, ", scared"); + if (mtmp->mtrapped) + Strcat(info, ", trapped"); + if (mtmp->mspeed) + Strcat(info, (mtmp->mspeed == MFAST) ? ", fast" + : (mtmp->mspeed == MSLOW) ? ", slow" + : ", [? speed]"); + if (mtmp->minvis) + Strcat(info, ", invisible"); + if (mtmp == u.ustuck) + Strcat(info, sticks(youmonst.data) ? ", held by you" + : !u.uswallow ? ", holding you" + : attacktype_fordmg(u.ustuck->data, AT_ENGL, AD_DGST) + ? ", digesting you" + : is_animal(u.ustuck->data) ? ", swallowing you" + : ", engulfing you"); + if (mtmp == u.usteed) + Strcat(info, ", carrying you"); + + /* avoid "Status of the invisible newt ..., invisible" */ + /* and unlike a normal mon_nam, use "saddled" even if it has a name */ + Strcpy(monnambuf, x_monnam(mtmp, ARTICLE_THE, (char *) 0, + (SUPPRESS_IT | SUPPRESS_INVISIBLE), FALSE)); + + pline("Status of %s (%s): Level %d HP %d(%d) AC %d%s.", monnambuf, + align_str(alignment), mtmp->m_lev, mtmp->mhp, mtmp->mhpmax, + find_mac(mtmp), info); +} + +/* stethoscope or probing applied to hero -- one-line feedback */ +void +ustatusline() +{ + char info[BUFSZ]; + + info[0] = '\0'; + if (Sick) { + Strcat(info, ", dying from"); + if (u.usick_type & SICK_VOMITABLE) + Strcat(info, " food poisoning"); + if (u.usick_type & SICK_NONVOMITABLE) { + if (u.usick_type & SICK_VOMITABLE) + Strcat(info, " and"); + Strcat(info, " illness"); + } + } + if (Stoned) + Strcat(info, ", solidifying"); + if (Slimed) + Strcat(info, ", becoming slimy"); + if (Strangled) + Strcat(info, ", being strangled"); + if (Vomiting) + Strcat(info, ", nauseated"); /* !"nauseous" */ + if (Confusion) + Strcat(info, ", confused"); + if (Blind) { + Strcat(info, ", blind"); + if (u.ucreamed) { + if ((long) u.ucreamed < Blinded || Blindfolded + || !haseyes(youmonst.data)) + Strcat(info, ", cover"); + Strcat(info, "ed by sticky goop"); + } /* note: "goop" == "glop"; variation is intentional */ + } + if (Stunned) + Strcat(info, ", stunned"); + if (!u.usteed && Wounded_legs) { + const char *what = body_part(LEG); + if ((Wounded_legs & BOTH_SIDES) == BOTH_SIDES) + what = makeplural(what); + Sprintf(eos(info), ", injured %s", what); + } + if (Glib) + Sprintf(eos(info), ", slippery %s", makeplural(body_part(HAND))); + if (u.utrap) + Strcat(info, ", trapped"); + if (Fast) + Strcat(info, Very_fast ? ", very fast" : ", fast"); + if (u.uundetected) + Strcat(info, ", concealed"); + if (Invis) + Strcat(info, ", invisible"); + if (u.ustuck) { + if (sticks(youmonst.data)) + Strcat(info, ", holding "); + else + Strcat(info, ", held by "); + Strcat(info, mon_nam(u.ustuck)); + } + + pline("Status of %s (%s): Level %d HP %d(%d) AC %d%s.", plname, + piousness(FALSE, align_str(u.ualign.type)), + Upolyd ? mons[u.umonnum].mlevel : u.ulevel, Upolyd ? u.mh : u.uhp, + Upolyd ? u.mhmax : u.uhpmax, u.uac, info); +} + /*priest.c*/ diff --git a/src/read.c b/src/read.c index efc36e3cb..46f838426 100644 --- a/src/read.c +++ b/src/read.c @@ -915,12 +915,21 @@ struct obj *sobj; return 0; } +boolean +get_valid_stinking_cloud_pos(x,y) +int x,y; +{ + return (!(!isok(x,y) || !cansee(x, y) + || !ACCESSIBLE(levl[x][y].typ) + || distu(x, y) >= 32)); +} + boolean is_valid_stinking_cloud_pos(x, y, showmsg) int x, y; boolean showmsg; { - if (!cansee(x, y) || !ACCESSIBLE(levl[x][y].typ) || distu(x, y) >= 32) { + if (get_valid_stinking_cloud_pos(x,y)) { if (showmsg) You("smell rotten eggs."); return FALSE; @@ -942,7 +951,7 @@ int state; for (dy = -dist; dy <= dist; dy++) { x = u.ux + dx; y = u.uy + dy; - if (isok(x, y) && is_valid_stinking_cloud_pos(x, y, FALSE)) + if (get_valid_stinking_cloud_pos(x,y)) tmp_at(x, y); } } else { @@ -1633,7 +1642,7 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */ already_known ? "stinking " : ""); cc.x = u.ux; cc.y = u.uy; - getpos_sethilite(display_stinking_cloud_positions); + getpos_sethilite(display_stinking_cloud_positions, get_valid_stinking_cloud_pos); if (getpos(&cc, TRUE, "the desired position") < 0) { pline1(Never_mind); break; diff --git a/src/sp_lev.c b/src/sp_lev.c index d8cde1f13..5323d4665 100644 --- a/src/sp_lev.c +++ b/src/sp_lev.c @@ -36,7 +36,6 @@ STATIC_DCL struct opvar *FDECL(opvar_new_coord, (int, int)); #if 0 STATIC_DCL struct opvar * FDECL(opvar_new_region, (int,int, int,int)); #endif /*0*/ -STATIC_DCL void FDECL(opvar_free_x, (struct opvar *)); STATIC_DCL struct opvar *FDECL(opvar_clone, (struct opvar *)); STATIC_DCL struct opvar *FDECL(opvar_var_conversion, (struct sp_coder *, struct opvar *)); @@ -114,8 +113,6 @@ STATIC_DCL void FDECL(spo_altar, (struct sp_coder *)); STATIC_DCL void FDECL(spo_trap, (struct sp_coder *)); STATIC_DCL void FDECL(spo_gold, (struct sp_coder *)); STATIC_DCL void FDECL(spo_corridor, (struct sp_coder *)); -STATIC_DCL struct opvar *FDECL(selection_opvar, (char *)); -STATIC_DCL xchar FDECL(selection_getpoint, (int, int, struct opvar *)); STATIC_DCL void FDECL(selection_setpoint, (int, int, struct opvar *, XCHAR_P)); STATIC_DCL struct opvar *FDECL(selection_not, (struct opvar *)); STATIC_DCL struct opvar *FDECL(selection_logical_oper, (struct opvar *, @@ -126,11 +123,8 @@ STATIC_DCL void FDECL(selection_filter_percent, (struct opvar *, int)); STATIC_DCL int FDECL(selection_rndcoord, (struct opvar *, schar *, schar *, BOOLEAN_P)); STATIC_DCL void FDECL(selection_do_grow, (struct opvar *, int)); -STATIC_DCL void FDECL(set_selection_floodfillchk, (int FDECL((*), (int,int)))); STATIC_DCL int FDECL(floodfillchk_match_under, (int, int)); STATIC_DCL int FDECL(floodfillchk_match_accessible, (int, int)); -STATIC_DCL void FDECL(selection_floodfill, (struct opvar *, int, int, - BOOLEAN_P)); STATIC_DCL void FDECL(selection_do_ellipse, (struct opvar *, int, int, int, int, int)); STATIC_DCL long FDECL(line_dist_coord, (long, long, long, long, long, long)); @@ -3052,6 +3046,7 @@ struct sp_coder *coder; while ((nparams++ < (SP_O_V_END + 1)) && (OV_typ(varparam) == SPOVAR_INT) && (OV_i(varparam) >= 0) && (OV_i(varparam) < SP_O_V_END)) { struct opvar *parm; + OV_pop(parm); switch (OV_i(varparam)) { case SP_O_V_NAME: @@ -3063,11 +3058,12 @@ struct sp_coder *coder; char monclass = SP_MONST_CLASS(OV_i(parm)); int monid = SP_MONST_PM(OV_i(parm)); - if (monid >= 0 && monid < NUMMONS) { + if (monid >= LOW_PM && monid < NUMMONS) { tmpobj.corpsenm = monid; break; /* we're done! */ } else { struct permonst *pm = (struct permonst *) 0; + if (def_char_to_monclass(monclass) != MAXMCLASSES) { pm = mkclass(def_char_to_monclass(monclass), G_NOGEN); } else { @@ -3780,7 +3776,7 @@ int dir; STATIC_VAR int FDECL((*selection_flood_check_func), (int, int)); STATIC_VAR schar floodfillchk_match_under_typ; -STATIC_OVL void +void set_selection_floodfillchk(f) int FDECL((*f), (int, int)); { @@ -3803,7 +3799,7 @@ int x, y; || levl[x][y].typ == SCORR); } -STATIC_OVL void +void selection_floodfill(ov, x, y, diagonals) struct opvar *ov; int x, y; diff --git a/src/timeout.c b/src/timeout.c index 66add4ec8..81285fc37 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -15,43 +15,83 @@ STATIC_DCL void FDECL(see_lamp_flicker, (struct obj *, const char *)); STATIC_DCL void FDECL(lantern_message, (struct obj *)); STATIC_DCL void FDECL(cleanup_burn, (ANY_P *, long)); -/* the order of these must match their numerical sequence in prop.h - because the property number is inferred from the array index; - used by wizard mode #timeout and #wizintrinsic */ -const char *const propertynames[] = { - "0: not used", -/* Resistances */ - /* 1..2 */ "fire resistance", "cold resistance", - /* 3..4 */ "sleep resistance", "disintegration resistance", - /* 5..6 */ "shock resistance", "poison resistance", - /* 7..8 */ "acid resistance", "stoning resistance", - /* 9..10 */ "drain resistance", "sickness resistance", - /* 11..12 */ "invulnerable", "magic resistance", -/* Troubles */ - /* 13..16 */ "stunned", "confused", "blinded", "deafness", - /* 17..20 */ "fatally sick", "petrifying", "strangling", "vomiting", - /* 21..22 */ "slippery fingers", "becoming slime", - /* 23..24 */ "hallucinating", "halluicination resistance", - /* 25..28 */ "fumbling", "wounded legs", "sleepy", "voracious hunger", -/* Vision and senses */ - /* 29..30 */ "see invisible", "telepathic", - /* 31..33 */ "warning", "warn:monster", "warn:undead", - /* 34..37 */ "searching", "clairvoyant", "infravision", "monster detection", -/* Appearance and behavior */ - /* 38..41 */ "adorned (+/-Cha)", "invisible", "displaced", "stealthy", - /* 42..43 */ "monster aggrevation", "conflict", -/* Transportation */ - /* 44..46 */ "jumping", "teleporting", "teleport control", - /* 47..49 */ "levitating", "flying", "water walking", - /* 50..52 */ "swimming", "magical breathing", "pass thru walls", -/* Physical attributes */ - /* 53..55 */ "slow digestion", "half spell damage", "half physical damage", - /* 56..58 */ "HP regeneration", "energy regeneration", "extra protection", - /* 59 */ "protection from shape changers", - /* 60..62 */ "polymorphing", "polymorph control", "unchanging", - /* 63..66 */ "fast", "reflecting", "free action", "fixed abilites", - /* 67 */ "life will be saved", - 0 /* sentinel */ +/* used by wizard mode #timeout and #wizintrinsic; order by 'interest' + for timeout countdown, where most won't occur in normal play */ +const struct propname { + int prop_num; + const char *prop_name; +} propertynames[] = { + { INVULNERABLE, "invulnerable" }, + { STONED, "petrifying" }, + { SLIMED, "becoming slime" }, + { STRANGLED, "strangling" }, + { SICK, "fatally sick" }, + { STUNNED, "stunned" }, + { CONFUSION, "confused" }, + { HALLUC, "hallucinating" }, + { BLINDED, "blinded" }, + { DEAF, "deafness" }, + { VOMITING, "vomiting" }, + { GLIB, "slippery fingers" }, + { WOUNDED_LEGS, "wounded legs" }, + { SLEEPY, "sleepy" }, + { TELEPORT, "teleporting" }, + { POLYMORPH, "polymorphing" }, + { LEVITATION, "levitating" }, + { FAST, "very fast" }, /* timed 'FAST' is very fast */ + { CLAIRVOYANT, "clairvoyant" }, + { DETECT_MONSTERS, "monster detection" }, + { SEE_INVIS, "see invisible" }, + { INVIS, "invisible" }, + /* properties beyond here don't have timed values during normal play, + so there's no much point in trying to order them sensibly; + they're either on or off based on equipment, role, actions, &c */ + { FIRE_RES, "fire resistance" }, + { COLD_RES, "cold resistance" }, + { SLEEP_RES, "sleep resistance" }, + { DISINT_RES, "disintegration resistance" }, + { SHOCK_RES, "shock resistance" }, + { POISON_RES, "poison resistance" }, + { ACID_RES, "acid resistance" }, + { STONE_RES, "stoning resistance" }, + { DRAIN_RES, "drain resistance" }, + { SICK_RES, "sickness resistance" }, + { ANTIMAGIC, "magic resistance" }, + { HALLUC_RES, "hallucination resistance" }, + { FUMBLING, "fumbling" }, + { HUNGER, "voracious hunger" }, + { TELEPAT, "telepathic" }, + { WARNING, "warning" }, + { WARN_OF_MON, "warn: monster type or class" }, + { WARN_UNDEAD, "warn: undead" }, + { SEARCHING, "searching" }, + { INFRAVISION, "infravision" }, + { ADORNED, "adorned (+/- Cha)" }, + { DISPLACED, "displaced" }, + { STEALTH, "stealthy" }, + { AGGRAVATE_MONSTER, "monster aggravation" }, + { CONFLICT, "conflict" }, + { JUMPING, "jumping" }, + { TELEPORT_CONTROL, "teleport control" }, + { FLYING, "flying" }, + { WWALKING, "water walking" }, + { SWIMMING, "swimming" }, + { MAGICAL_BREATHING, "magical breathing" }, + { PASSES_WALLS, "pass thru walls" }, + { SLOW_DIGESTION, "slow digestion" }, + { HALF_SPDAM, "half spell damage" }, + { HALF_PHDAM, "half physical damage" }, + { REGENERATION, "HP regeneration" }, + { ENERGY_REGENERATION, "energy regeneration" }, + { PROTECTION, "extra protection" }, + { PROT_FROM_SHAPE_CHANGERS, "protection from shape changers" }, + { POLYMORPH_CONTROL, "polymorph control" }, + { UNCHANGING, "unchanging" }, + { REFLECTING, "reflecting" }, + { FREE_ACTION, "free action" }, + { FIXED_ABIL, "fixed abilites" }, + { LIFESAVED, "life will be saved" }, + { 0, 0 }, }; /* He is being petrified - dialogue by inmet!tower */ @@ -1544,7 +1584,7 @@ wiz_timeout_queue() char buf[BUFSZ]; const char *propname; long intrinsic; - int i, count, longestlen, ln; + int i, p, count, longestlen, ln, specindx = 0; win = create_nhwindow(NHW_MENU); /* corner text window */ if (win == WIN_ERR) @@ -1562,13 +1602,16 @@ wiz_timeout_queue() * normal play but those can be forced via the #wizintrinsic command. */ count = longestlen = 0; - for (i = 1; (propname = propertynames[i]) != 0; ++i) { /* [0] not used */ - intrinsic = u.uprops[i].intrinsic; + for (i = 0; (propname = propertynames[i].prop_name) != 0; ++i) { + p = propertynames[i].prop_num; + intrinsic = u.uprops[p].intrinsic; if (intrinsic & TIMEOUT) { ++count; if ((ln = (int) strlen(propname)) > longestlen) longestlen = ln; } + if (specindx == 0 && p == FIRE_RES) + specindx = i; } putstr(win, 0, ""); if (!count) { @@ -1576,9 +1619,14 @@ wiz_timeout_queue() } else { putstr(win, 0, "Timed properties:"); putstr(win, 0, ""); - for (i = 1; (propname = propertynames[i]) != 0; ++i) { - intrinsic = u.uprops[i].intrinsic; + for (i = 0; (propname = propertynames[i].prop_name) != 0; ++i) { + p = propertynames[i].prop_num; + intrinsic = u.uprops[p].intrinsic; if (intrinsic & TIMEOUT) { + if (specindx > 0 && i >= specindx) { + putstr(win, 0, " -- settable via #wizinstrinc only --"); + specindx = 0; + } /* timeout value can be up to 16777215 (0x00ffffff) but width of 4 digits should result in values lining up almost all the time (if/when they don't, it won't diff --git a/src/vault.c b/src/vault.c index f076986f5..296116c53 100644 --- a/src/vault.c +++ b/src/vault.c @@ -191,6 +191,13 @@ findgd() return (struct monst *) 0; } +void +vault_summon_gd() +{ + if (vault_occupied(u.urooms) && !findgd()) + u.uinvault = (VAULT_GUARD_TIME - 1); +} + char vault_occupied(array) char *array; @@ -221,7 +228,8 @@ invault() vaultroom -= ROOMOFFSET; guard = findgd(); - if (++u.uinvault % 30 == 0 && !guard) { /* if time ok and no guard now. */ + if (++u.uinvault % VAULT_GUARD_TIME == 0 && !guard) { + /* if time ok and no guard now. */ char buf[BUFSZ]; register int x, y, dd, gx, gy; int lx = 0, ly = 0; diff --git a/sys/amiga/winami.c b/sys/amiga/winami.c index 5f32f7711..daabd859d 100644 --- a/sys/amiga/winami.c +++ b/sys/amiga/winami.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 winami.c $NHDT-Date: 1432512794 2015/05/25 00:13:14 $ $NHDT-Branch: master $:$NHDT-Revision: 1.19 $ */ +/* NetHack 3.6 winami.c $NHDT-Date: 1501981093 2017/08/06 00:58:13 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.20 $ */ /* Copyright (c) Gregg Wonderly, Naperville, Illinois, 1991,1992,1993,1996. */ /* NetHack may be freely redistributed. See license for details. */ @@ -807,8 +807,8 @@ amii_get_ext_cmd(void) } return (-1); - } else { -#else + } +#endif amii_clear_nhwindow(WIN_MESSAGE); /* Was NHW_MESSAGE */ if (scrollmsg) { @@ -932,58 +932,61 @@ amii_get_ext_cmd(void) DisplayBeep(NULL); } return (-1); -#endif - } +} - static int put_ext_cmd(obufp, colx, cw, bottom) char * obufp; - int colx, bottom; - struct amii_WinDesc *cw; - { - struct Window *w = cw->win; - char *t; +static int +put_ext_cmd(obufp, colx, cw, bottom) +char * obufp; +int colx, bottom; +struct amii_WinDesc *cw; +{ + struct Window *w = cw->win; + char *t; - t = (char *) alloc(strlen(obufp) + 7); - if (t != NULL) { - if (scrollmsg) { - sprintf(t, "xxx%s", obufp); - t[0] = 1; - t[1] = 1; - t[2] = '#'; - amii_curs(WIN_MESSAGE, 0, bottom); - SetAPen(w->RPort, C_WHITE); - Text(w->RPort, "># ", 3); - /* SetAPen( w->RPort, C_BLACK ); */ /* Black text on black - screen doesn't look too - well ... -jhsa */ - Text(w->RPort, t + 3, strlen(t) - 3); - } else { - sprintf(t, "# %s", obufp); - amii_curs(WIN_MESSAGE, 0, bottom); - SetAPen(w->RPort, C_WHITE); - Text(w->RPort, t, strlen(t)); - } - if (scrollmsg) - SetAPen(w->RPort, C_WHITE); - if (cw->data[cw->maxrow - 1]) - free(cw->data[cw->maxrow - 1]); - cw->data[cw->maxrow - 1] = t; - } else { + t = (char *) alloc(strlen(obufp) + 7); + if (t != NULL) { + if (scrollmsg) { + sprintf(t, "xxx%s", obufp); + t[0] = 1; + t[1] = 1; + t[2] = '#'; amii_curs(WIN_MESSAGE, 0, bottom); SetAPen(w->RPort, C_WHITE); - Text(w->RPort, "# ", 2); - /* SetAPen( w->RPort, C_BLACK ); */ /* Black on black ... -jhsa */ - Text(w->RPort, obufp, strlen(obufp)); + Text(w->RPort, "># ", 3); + /* SetAPen( w->RPort, C_BLACK ); */ /* Black text on black + * screen doesn't look + * too well ... -jhsa */ + Text(w->RPort, t + 3, strlen(t) - 3); + } else { + sprintf(t, "# %s", obufp); + amii_curs(WIN_MESSAGE, 0, bottom); SetAPen(w->RPort, C_WHITE); + Text(w->RPort, t, strlen(t)); } - amii_curs(WIN_MESSAGE, colx = strlen(obufp) + 3 + (scrollmsg != 0), - bottom); - return (colx); + if (scrollmsg) + SetAPen(w->RPort, C_WHITE); + if (cw->data[cw->maxrow - 1]) + free(cw->data[cw->maxrow - 1]); + cw->data[cw->maxrow - 1] = t; + } else { + amii_curs(WIN_MESSAGE, 0, bottom); + SetAPen(w->RPort, C_WHITE); + Text(w->RPort, "# ", 2); + /* SetAPen( w->RPort, C_BLACK ); */ /* Black on black ... -jhsa */ + Text(w->RPort, obufp, strlen(obufp)); + SetAPen(w->RPort, C_WHITE); } + amii_curs(WIN_MESSAGE, colx = strlen(obufp) + 3 + (scrollmsg != 0), + bottom); + return colx; +} - /* Ask a question and get a response */ - - char amii_yn_function(query, resp, def) const char * query, *resp; - char def; +/* Ask a question and get a response */ +char +amii_yn_function(query, resp, def) +const char * query, *resp; +char def; +{ /* * Generic yes/no function. 'def' is the default (returned by space or * return; 'esc' returns 'q', or 'n', or the default, depending on @@ -995,155 +998,158 @@ amii_get_ext_cmd(void) * are allowed); if it includes an , anything beyond that won't * be shown in the prompt to the user but will be acceptable as input. */ - { - register char q; - char rtmp[40]; - boolean digit_ok, allow_num; - char prompt[BUFSZ]; - register struct amii_WinDesc *cw; + register char q; + char rtmp[40]; + boolean digit_ok, allow_num; + char prompt[BUFSZ]; + register struct amii_WinDesc *cw; - if (cw = amii_wins[WIN_MESSAGE]) - cw->disprows = 0; - if (resp) { - char *rb, respbuf[QBUFSZ]; + if (cw = amii_wins[WIN_MESSAGE]) + cw->disprows = 0; + if (resp) { + char *rb, respbuf[QBUFSZ]; - allow_num = (index(resp, '#') != 0); - Strcpy(respbuf, resp); - /* any acceptable responses that follow aren't displayed */ - if ((rb = index(respbuf, '\033')) != 0) - *rb = '\0'; - (void) strncpy(prompt, query, QBUFSZ - 1); - prompt[QBUFSZ - 1] = '\0'; - Sprintf(eos(prompt), " [%s]", respbuf); - if (def) - Sprintf(eos(prompt), " (%c)", def); - Strcat(prompt, " "); - pline("%s", prompt); - } else { - amii_putstr(WIN_MESSAGE, 0, query); - cursor_on(WIN_MESSAGE); - q = WindowGetchar(); - cursor_off(WIN_MESSAGE); - *rtmp = q; - rtmp[1] = 0; - amii_addtopl(rtmp); - goto clean_up; - } - - do { /* loop until we get valid input */ - cursor_on(WIN_MESSAGE); - q = lowc(WindowGetchar()); - cursor_off(WIN_MESSAGE); -#if 0 -/* fix for PL2 */ - if (q == '\020') { /* ctrl-P */ - if(!doprev) (void) tty_doprev_message(); /* need two initially */ - (void) tty_doprev_message(); - q = (char)0; - doprev = 1; - continue; - } else if(doprev) { - tty_clear_nhwindow(WIN_MESSAGE); - cw->maxcol = cw->maxrow; - doprev = 0; - amii_addtopl(prompt); - continue; - } -#endif - digit_ok = allow_num && isdigit(q); - if (q == '\033') { - if (index(resp, 'q')) - q = 'q'; - else if (index(resp, 'n')) - q = 'n'; - else - q = def; - break; - } else if (index(quitchars, q)) { - q = def; - break; - } - if (!index(resp, q) && !digit_ok) { - amii_bell(); - q = (char) 0; - } else if (q == '#' || digit_ok) { - char z, digit_string[2]; - int n_len = 0; - long value = 0; - amii_addtopl("#"), n_len++; - digit_string[1] = '\0'; - if (q != '#') { - digit_string[0] = q; - amii_addtopl(digit_string), n_len++; - value = q - '0'; - q = '#'; - } - do { /* loop until we get a non-digit */ - cursor_on(WIN_MESSAGE); - z = lowc(WindowGetchar()); - cursor_off(WIN_MESSAGE); - if (isdigit(z)) { - value = (10 * value) + (z - '0'); - if (value < 0) - break; /* overflow: try again */ - digit_string[0] = z; - amii_addtopl(digit_string), n_len++; - } else if (z == 'y' || index(quitchars, z)) { - if (z == '\033') - value = -1; /* abort */ - z = '\n'; /* break */ - } else if (z == '\b') { - if (n_len <= 1) { - value = -1; - break; - } else { - value /= 10; - removetopl(1), n_len--; - } - } else { - value = -1; /* abort */ - amii_bell(); - break; - } - } while (z != '\n'); - if (value > 0) - yn_number = value; - else if (value == 0) - q = 'n'; /* 0 => "no" */ - else { /* remove number from top line, then try again */ - removetopl(n_len), n_len = 0; - q = '\0'; - } - } - } while (!q); - - if (q != '#' && q != '\033') { - Sprintf(rtmp, "%c", q); - amii_addtopl(rtmp); - } - clean_up: + allow_num = (index(resp, '#') != 0); + Strcpy(respbuf, resp); + /* any acceptable responses that follow aren't displayed */ + if ((rb = index(respbuf, '\033')) != 0) + *rb = '\0'; + (void) strncpy(prompt, query, QBUFSZ - 1); + prompt[QBUFSZ - 1] = '\0'; + Sprintf(eos(prompt), " [%s]", respbuf); + if (def) + Sprintf(eos(prompt), " (%c)", def); + Strcat(prompt, " "); + pline("%s", prompt); + } else { + amii_putstr(WIN_MESSAGE, 0, query); + cursor_on(WIN_MESSAGE); + q = WindowGetchar(); cursor_off(WIN_MESSAGE); - clear_nhwindow(WIN_MESSAGE); - return q; + *rtmp = q; + rtmp[1] = '\0'; + amii_addtopl(rtmp); + goto clean_up; } - void amii_display_file(fn, complain) const char * fn; - boolean complain; - { - register struct amii_WinDesc *cw; - register int win; - register dlb *fp; - register char *t; - register char buf[200]; + do { /* loop until we get valid input */ + cursor_on(WIN_MESSAGE); + q = lowc(WindowGetchar()); + cursor_off(WIN_MESSAGE); +#if 0 +/* fix for PL2 */ + if (q == '\020') { /* ctrl-P */ + if(!doprev) + (void) tty_doprev_message(); /* need two initially */ + (void) tty_doprev_message(); + q = (char)0; + doprev = 1; + continue; + } else if (doprev) { + tty_clear_nhwindow(WIN_MESSAGE); + cw->maxcol = cw->maxrow; + doprev = 0; + amii_addtopl(prompt); + continue; + } +#endif /*0*/ + digit_ok = allow_num && isdigit(q); + if (q == '\033') { + if (index(resp, 'q')) + q = 'q'; + else if (index(resp, 'n')) + q = 'n'; + else + q = def; + break; + } else if (index(quitchars, q)) { + q = def; + break; + } + if (!index(resp, q) && !digit_ok) { + amii_bell(); + q = (char) 0; + } else if (q == '#' || digit_ok) { + char z, digit_string[2]; + int n_len = 0; + long value = 0; - if (fn == NULL) - panic("NULL file name in display_file()"); + amii_addtopl("#"), n_len++; + digit_string[1] = '\0'; + if (q != '#') { + digit_string[0] = q; + amii_addtopl(digit_string), n_len++; + value = q - '0'; + q = '#'; + } + do { /* loop until we get a non-digit */ + cursor_on(WIN_MESSAGE); + z = lowc(WindowGetchar()); + cursor_off(WIN_MESSAGE); + if (isdigit(z)) { + value = (10 * value) + (z - '0'); + if (value < 0) + break; /* overflow: try again */ + digit_string[0] = z; + amii_addtopl(digit_string), n_len++; + } else if (z == 'y' || index(quitchars, z)) { + if (z == '\033') + value = -1; /* abort */ + z = '\n'; /* break */ + } else if (z == '\b') { + if (n_len <= 1) { + value = -1; + break; + } else { + value /= 10; + removetopl(1), n_len--; + } + } else { + value = -1; /* abort */ + amii_bell(); + break; + } + } while (z != '\n'); + if (value > 0) + yn_number = value; + else if (value == 0) + q = 'n'; /* 0 => "no" */ + else { /* remove number from top line, then try again */ + removetopl(n_len), n_len = 0; + q = '\0'; + } + } + } while (!q); - if ((fp = dlb_fopen(fn, RDTMODE)) == (dlb *) NULL) { - if (complain) { - sprintf(buf, "Can't display %s: %s", fn, + if (q != '#' && q != '\033') { + Sprintf(rtmp, "%c", q); + amii_addtopl(rtmp); + } + clean_up: + cursor_off(WIN_MESSAGE); + clear_nhwindow(WIN_MESSAGE); + return q; +} + +void +amii_display_file(fn, complain) +const char * fn; +boolean complain; +{ + register struct amii_WinDesc *cw; + register int win; + register dlb *fp; + register char *t; + register char buf[200]; + + if (fn == NULL) + panic("NULL file name in display_file()"); + + if ((fp = dlb_fopen(fn, RDTMODE)) == (dlb *) NULL) { + if (complain) { + sprintf(buf, "Can't display %s: %s", fn, #if defined(_DCC) || defined(__GNUC__) - strerror(errno) + strerror(errno) #else #ifdef __SASC_60 __sys_errlist[errno] @@ -1151,520 +1157,510 @@ amii_get_ext_cmd(void) sys_errlist[errno] #endif #endif - ); - amii_addtopl(buf); - } - return; + ); + amii_addtopl(buf); } - win = amii_create_nhwindow(NHW_TEXT); + return; + } + win = amii_create_nhwindow(NHW_TEXT); - /* Set window title to file name */ - if (cw = amii_wins[win]) - cw->morestr = (char *) fn; + /* Set window title to file name */ + if (cw = amii_wins[win]) + cw->morestr = (char *) fn; - while (dlb_fgets(buf, sizeof(buf), fp) != NULL) { - if (t = index(buf, '\n')) - *t = 0; - amii_putstr(win, 0, buf); + while (dlb_fgets(buf, sizeof(buf), fp) != NULL) { + if (t = index(buf, '\n')) + *t = 0; + amii_putstr(win, 0, buf); + } + dlb_fclose(fp); + + /* If there were lines in the file, display those lines */ + if (amii_wins[win]->cury > 0) + amii_display_nhwindow(win, TRUE); + + amii_wins[win]->morestr = NULL; /* don't free title string */ + amii_destroy_nhwindow(win); +} + +/* Put a 3-D motif border around the gadget. String gadgets or those + * which do not have highlighting are rendered down. Boolean gadgets + * are rendered in the up position by default. + */ +void +SetBorder(gd) +register struct Gadget * gd; +{ + register struct Border *bp; + register short *sp; + register int i, inc = -1, dec = -1; + int borders = 6; + int hipen = sysflags.amii_dripens[SHINEPEN], + shadowpen = sysflags.amii_dripens[SHADOWPEN]; +#ifdef INTUI_NEW_LOOK + struct DrawInfo *dip; +#endif + +#ifdef INTUI_NEW_LOOK + if (IntuitionBase->LibNode.lib_Version >= 37) { + if ((dip = GetScreenDrawInfo(HackScreen)) != 0) { + hipen = dip->dri_Pens[SHINEPEN]; + shadowpen = dip->dri_Pens[SHADOWPEN]; + FreeScreenDrawInfo(HackScreen, dip); } - dlb_fclose(fp); - - /* If there were lines in the file, display those lines */ - - if (amii_wins[win]->cury > 0) - amii_display_nhwindow(win, TRUE); - - amii_wins[win]->morestr = NULL; /* don't free title string */ - amii_destroy_nhwindow(win); + } +#endif + /* Allocate two border structures one for up image and one for down + * image, plus vector arrays for the border lines. + */ + if (gd->GadgetType == STRGADGET) + borders = 12; + if ((bp = (struct Border *) alloc(((sizeof (struct Border) * 2) + + (sizeof (short) * borders)) * 2)) + == NULL) { + return; } - /* Put a 3-D motif border around the gadget. String gadgets or those - * which do not have highlighting are rendered down. Boolean gadgets - * are rendered in the up position by default. + /* For a string gadget, we expand the border beyond the area where + * the text will be entered. */ - void SetBorder(gd) register struct Gadget * gd; - { - register struct Border *bp; - register short *sp; - register int i, inc = -1, dec = -1; - int borders = 6; - int hipen = sysflags.amii_dripens[SHINEPEN], - shadowpen = sysflags.amii_dripens[SHADOWPEN]; -#ifdef INTUI_NEW_LOOK - struct DrawInfo *dip; -#endif + /* Remove any special rendering flags to avoid confusing intuition */ + gd->Flags &= ~(GADGHIGHBITS | GADGIMAGE); -#ifdef INTUI_NEW_LOOK - if (IntuitionBase->LibNode.lib_Version >= 37) { - if (dip = GetScreenDrawInfo(HackScreen)) { - hipen = dip->dri_Pens[SHINEPEN]; - shadowpen = dip->dri_Pens[SHADOWPEN]; - FreeScreenDrawInfo(HackScreen, dip); - } + sp = (short *) (bp + 4); + if (gd->GadgetType == STRGADGET + || (gd->GadgetType == BOOLGADGET + && (gd->Flags & GADGHIGHBITS) == GADGHNONE)) { + sp[0] = -1; + sp[1] = gd->Height - 1; + sp[2] = -1; + sp[3] = -1; + sp[4] = gd->Width - 1; + sp[5] = -1; + + sp[6] = gd->Width + 1; + sp[7] = -2; + sp[8] = gd->Width + 1; + sp[9] = gd->Height + 1; + sp[10] = -2; + sp[11] = gd->Height + 1; + + sp[12] = -2; + sp[13] = gd->Height; + sp[14] = -2; + sp[15] = -2; + sp[16] = gd->Width; + sp[17] = -2; + sp[18] = gd->Width; + sp[19] = gd->Height; + sp[20] = -2; + sp[21] = gd->Height; + + for (i = 0; i < 3; ++i) { + bp[i].LeftEdge = bp[i].TopEdge = -1; + bp[i].FrontPen = (i == 0 || i == 1) ? shadowpen : hipen; + + /* Have to use JAM2 so that the old colors disappear. */ + bp[i].BackPen = C_BLACK; + bp[i].DrawMode = JAM2; + bp[i].Count = (i == 0 || i == 1) ? 3 : 5; + bp[i].XY = &sp[i * 6]; + bp[i].NextBorder = (i == 2) ? NULL : &bp[i + 1]; } -#endif - /* Allocate two border structures one for up image and one for down - * image, plus vector arrays for the border lines. + + /* bp[0] and bp[1] two pieces for the up image */ + gd->GadgetRender = (APTR) bp; + + /* No image change for select */ + gd->SelectRender = (APTR) bp; + + gd->LeftEdge++; + gd->TopEdge++; + gd->Flags |= GADGHCOMP; + } else { + /* Create the border vector values for up and left side, and + * also the lower and right side. */ + sp[0] = dec; + sp[1] = gd->Height + inc; + sp[2] = dec; + sp[3] = dec; + sp[4] = gd->Width + inc; + sp[5] = dec; - if (gd->GadgetType == STRGADGET) - borders = 12; + sp[6] = gd->Width + inc; + sp[7] = dec; + sp[8] = gd->Width + inc; + sp[9] = gd->Height + inc; + sp[10] = dec; + sp[11] = gd->Height + inc; - if ((bp = (struct Border *) alloc(((sizeof(struct Border) * 2) - + (sizeof(short) * borders)) * 2)) - == NULL) { + /* We are creating 4 sets of borders, the two sides of the + * rectangle share the border vectors with the opposite image, + * but specify different colors. + */ + for (i = 0; i < 4; ++i) { + bp[i].TopEdge = bp[i].LeftEdge = 0; + + /* A GADGHNONE is always down */ + if (gd->GadgetType == BOOLGADGET + && (gd->Flags & GADGHIGHBITS) != GADGHNONE) { + bp[i].FrontPen = (i == 1 || i == 2) ? shadowpen : hipen; + } else { + bp[i].FrontPen = (i == 1 || i == 3) ? hipen : shadowpen; + } + + /* Have to use JAM2 so that the old colors disappear. */ + bp[i].BackPen = C_BLACK; + bp[i].DrawMode = JAM2; + bp[i].Count = 3; + bp[i].XY = &sp[6 * ((i & 1) != 0)]; + bp[i].NextBorder = (i == 1 || i == 3) ? NULL : &bp[i + 1]; + } + + /* bp[0] and bp[1] two pieces for the up image */ + gd->GadgetRender = (APTR) bp; + + /* bp[2] and bp[3] two pieces for the down image */ + gd->SelectRender = (APTR)(bp + 2); + gd->Flags |= GADGHIMAGE; + } +} + +/* Following function copied from wintty.c; + Modified slightly to fit amiga needs */ +void +amii_player_selection() +{ + int i, k, n; + char pick4u = 'n', thisch, lastch = 0; + char pbuf[QBUFSZ], plbuf[QBUFSZ], rolenamebuf[QBUFSZ]; + winid win; + anything any; + menu_item *selected = 0; + + rigid_role_checks(); + + /* Should we randomly pick for the player? */ + if (flags.initrole == ROLE_NONE || flags.initrace == ROLE_NONE + || flags.initgend == ROLE_NONE || flags.initalign == ROLE_NONE) { + char *prompt; + + prompt = build_plselection_prompt(pbuf, QBUFSZ, + flags.initrole, flags.initrace, + flags.initgend, flags.initalign); + pline("%s", prompt); + do { /* loop until we get valid input */ + cursor_on(WIN_MESSAGE); + pick4u = lowc(WindowGetchar()); + cursor_off(WIN_MESSAGE); + if (index(quitchars, pick4u)) + pick4u = 'y'; + } while (!index(ynqchars, pick4u)); + pbuf[0] = pick4u; + pbuf[1] = 0; + amii_addtopl(pbuf); + + if (pick4u != 'y' && pick4u != 'n') { + give_up: /* Quit */ + if (selected) + free((genericptr_t) selected); + clearlocks(); + exit_nhwindows(NULL); + terminate(0); + /*NOTREACHED*/ return; } - - /* For a string gadget, we expand the border beyond the area where - * the text will be entered. - */ - - /* Remove any special rendering flags to avoid confusing intuition - */ - - gd->Flags &= ~(GADGHIGHBITS | GADGIMAGE); - - sp = (short *) (bp + 4); - if (gd->GadgetType == STRGADGET - || (gd->GadgetType == BOOLGADGET - && (gd->Flags & GADGHIGHBITS) == GADGHNONE)) { - sp[0] = -1; - sp[1] = gd->Height - 1; - sp[2] = -1; - sp[3] = -1; - sp[4] = gd->Width - 1; - sp[5] = -1; - - sp[6] = gd->Width + 1; - sp[7] = -2; - sp[8] = gd->Width + 1; - sp[9] = gd->Height + 1; - sp[10] = -2; - sp[11] = gd->Height + 1; - - sp[12] = -2; - sp[13] = gd->Height; - sp[14] = -2; - sp[15] = -2; - sp[16] = gd->Width; - sp[17] = -2; - sp[18] = gd->Width; - sp[19] = gd->Height; - sp[20] = -2; - sp[21] = gd->Height; - - for (i = 0; i < 3; ++i) { - bp[i].LeftEdge = bp[i].TopEdge = -1; - bp[i].FrontPen = (i == 0 || i == 1) ? shadowpen : hipen; - - /* Have to use JAM2 so that the old colors disappear. */ - bp[i].BackPen = C_BLACK; - bp[i].DrawMode = JAM2; - bp[i].Count = (i == 0 || i == 1) ? 3 : 5; - bp[i].XY = &sp[i * 6]; - bp[i].NextBorder = (i == 2) ? NULL : &bp[i + 1]; - } - - /* bp[0] and bp[1] two pieces for the up image */ - gd->GadgetRender = (APTR) bp; - - /* No image change for select */ - gd->SelectRender = (APTR) bp; - - gd->LeftEdge++; - gd->TopEdge++; - gd->Flags |= GADGHCOMP; - } else { - /* Create the border vector values for up and left side, and - * also the lower and right side. - */ - - sp[0] = dec; - sp[1] = gd->Height + inc; - sp[2] = dec; - sp[3] = dec; - sp[4] = gd->Width + inc; - sp[5] = dec; - - sp[6] = gd->Width + inc; - sp[7] = dec; - sp[8] = gd->Width + inc; - sp[9] = gd->Height + inc; - sp[10] = dec; - sp[11] = gd->Height + inc; - - /* We are creating 4 sets of borders, the two sides of the - * rectangle share the border vectors with the opposite image, - * but specify different colors. - */ - - for (i = 0; i < 4; ++i) { - bp[i].TopEdge = bp[i].LeftEdge = 0; - - /* A GADGHNONE is always down */ - - if (gd->GadgetType == BOOLGADGET - && (gd->Flags & GADGHIGHBITS) != GADGHNONE) { - bp[i].FrontPen = (i == 1 || i == 2) ? shadowpen : hipen; - } else { - bp[i].FrontPen = (i == 1 || i == 3) ? hipen : shadowpen; - } - - /* Have to use JAM2 so that the old colors disappear. */ - bp[i].BackPen = C_BLACK; - bp[i].DrawMode = JAM2; - bp[i].Count = 3; - bp[i].XY = &sp[6 * ((i & 1) != 0)]; - bp[i].NextBorder = (i == 1 || i == 3) ? NULL : &bp[i + 1]; - } - - /* bp[0] and bp[1] two pieces for the up image */ - gd->GadgetRender = (APTR) bp; - - /* bp[2] and bp[3] two pieces for the down image */ - gd->SelectRender = (APTR)(bp + 2); - gd->Flags |= GADGHIMAGE; - } } - /* Following function copied from wintty.c */ - /* Modified slightly to fit amiga needs */ + (void) root_plselection_prompt(plbuf, QBUFSZ - 1, + flags.initrole, flags.initrace, + flags.initgend, flags.initalign); - void amii_player_selection() - { - int i, k, n; - char pick4u = 'n', thisch, lastch = 0; - char pbuf[QBUFSZ], plbuf[QBUFSZ], rolenamebuf[QBUFSZ]; - winid win; - anything any; - menu_item *selected = 0; - - rigid_role_checks(); - - /* Should we randomly pick for the player? */ - if (flags.initrole == ROLE_NONE || flags.initrace == ROLE_NONE - || flags.initgend == ROLE_NONE || flags.initalign == ROLE_NONE) { - char *prompt = build_plselection_prompt( - pbuf, QBUFSZ, flags.initrole, flags.initrace, flags.initgend, - flags.initalign); - pline("%s", prompt); - do { /* loop until we get valid input */ - cursor_on(WIN_MESSAGE); - pick4u = lowc(WindowGetchar()); - cursor_off(WIN_MESSAGE); - if (index(quitchars, pick4u)) - pick4u = 'y'; - } while (!index(ynqchars, pick4u)); - pbuf[0] = pick4u; - pbuf[1] = 0; - amii_addtopl(pbuf); - - if (pick4u != 'y' && pick4u != 'n') { - give_up: /* Quit */ - if (selected) - free((genericptr_t) selected); - clearlocks(); - exit_nhwindows(NULL); - terminate(0); - /*NOTREACHED*/ - return; + /* Select a role, if necessary */ + /* we'll try to be compatible with pre-selected race/gender/alignment, + * but may not succeed */ + if (flags.initrole < 0) { + /* Process the choice */ + if (pick4u == 'y' || flags.initrole == ROLE_RANDOM + || flags.randomall) { + /* Pick a random role */ + flags.initrole = pick_role(flags.initrace, flags.initgend, + flags.initalign, PICK_RANDOM); + if (flags.initrole < 0) { + amii_putstr(WIN_MESSAGE, 0, "Incompatible role!"); + flags.initrole = randrole(); } - } - - (void) root_plselection_prompt(plbuf, QBUFSZ - 1, flags.initrole, - flags.initrace, flags.initgend, - flags.initalign); - - /* Select a role, if necessary */ - /* we'll try to be compatible with pre-selected race/gender/alignment, - * but may not succeed */ - if (flags.initrole < 0) { - /* Process the choice */ - if (pick4u == 'y' || flags.initrole == ROLE_RANDOM - || flags.randomall) { - /* Pick a random role */ - flags.initrole = pick_role(flags.initrace, flags.initgend, - flags.initalign, PICK_RANDOM); - if (flags.initrole < 0) { - amii_putstr(WIN_MESSAGE, 0, "Incompatible role!"); - flags.initrole = randrole(); + } else { + /* Prompt for a role */ + win = create_nhwindow(NHW_MENU); + start_menu(win); + any.a_void = 0; /* zero out all bits */ + for (i = 0; roles[i].name.m; i++) { + if (ok_role(i, flags.initrace, flags.initgend, + flags.initalign)) { + any.a_int = i + 1; /* must be non-zero */ + thisch = lowc(roles[i].name.m[0]); + if (thisch == lastch) + thisch = highc(thisch); + if (flags.initgend != ROLE_NONE + && flags.initgend != ROLE_RANDOM) { + if (flags.initgend == 1 && roles[i].name.f) + Strcpy(rolenamebuf, roles[i].name.f); + else + Strcpy(rolenamebuf, roles[i].name.m); + } else { + if (roles[i].name.f) { + Strcpy(rolenamebuf, roles[i].name.m); + Strcat(rolenamebuf, "/"); + Strcat(rolenamebuf, roles[i].name.f); + } else + Strcpy(rolenamebuf, roles[i].name.m); + } + add_menu(win, NO_GLYPH, &any, thisch, 0, ATR_NONE, + an(rolenamebuf), MENU_UNSELECTED); + lastch = thisch; } - } else { - /* Prompt for a role */ + } + any.a_int = pick_role(flags.initrace, flags.initgend, + flags.initalign, PICK_RANDOM) + 1; + if (any.a_int == 0) /* must be non-zero */ + any.a_int = randrole() + 1; + add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random", + MENU_UNSELECTED); + any.a_int = i + 1; /* must be non-zero */ + add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit", + MENU_UNSELECTED); + Sprintf(pbuf, "Pick a role for your %s", plbuf); + end_menu(win, pbuf); + n = select_menu(win, PICK_ONE, &selected); + destroy_nhwindow(win); + + /* Process the choice */ + if (n != 1 || selected[0].item.a_int == any.a_int) + goto give_up; /* Selected quit */ + + flags.initrole = selected[0].item.a_int - 1; + free((genericptr_t) selected), selected = 0; + } + (void) root_plselection_prompt(plbuf, QBUFSZ - 1, + flags.initrole, flags.initrace, + flags.initgend, flags.initalign); + } + + /* Select a race, if necessary */ + /* force compatibility with role, try for compatibility with + * pre-selected gender/alignment */ + if (flags.initrace < 0 + || !validrace(flags.initrole, flags.initrace)) { + /* pre-selected race not valid */ + if (pick4u == 'y' || flags.initrace == ROLE_RANDOM + || flags.randomall) { + flags.initrace = pick_race(flags.initrole, flags.initgend, + flags.initalign, PICK_RANDOM); + if (flags.initrace < 0) { + amii_putstr(WIN_MESSAGE, 0, "Incompatible race!"); + flags.initrace = randrace(flags.initrole); + } + } else { /* pick4u == 'n' */ + /* Count the number of valid races */ + n = 0; /* number valid */ + k = 0; /* valid race */ + for (i = 0; races[i].noun; i++) { + if (ok_race(flags.initrole, i, flags.initgend, + flags.initalign)) { + n++; + k = i; + } + } + if (n == 0) { + for (i = 0; races[i].noun; i++) { + if (validrace(flags.initrole, i)) { + n++; + k = i; + } + } + } + + /* Permit the user to pick, if there is more than one */ + if (n > 1) { win = create_nhwindow(NHW_MENU); start_menu(win); any.a_void = 0; /* zero out all bits */ - for (i = 0; roles[i].name.m; i++) { - if (ok_role(i, flags.initrace, flags.initgend, + for (i = 0; races[i].noun; i++) + if (ok_race(flags.initrole, i, flags.initgend, flags.initalign)) { any.a_int = i + 1; /* must be non-zero */ - thisch = lowc(roles[i].name.m[0]); - if (thisch == lastch) - thisch = highc(thisch); - if (flags.initgend != ROLE_NONE - && flags.initgend != ROLE_RANDOM) { - if (flags.initgend == 1 && roles[i].name.f) - Strcpy(rolenamebuf, roles[i].name.f); - else - Strcpy(rolenamebuf, roles[i].name.m); - } else { - if (roles[i].name.f) { - Strcpy(rolenamebuf, roles[i].name.m); - Strcat(rolenamebuf, "/"); - Strcat(rolenamebuf, roles[i].name.f); - } else - Strcpy(rolenamebuf, roles[i].name.m); - } - add_menu(win, NO_GLYPH, &any, thisch, 0, ATR_NONE, - an(rolenamebuf), MENU_UNSELECTED); - lastch = thisch; + add_menu(win, NO_GLYPH, &any, races[i].noun[0], 0, + ATR_NONE, races[i].noun, + MENU_UNSELECTED); } - } - any.a_int = pick_role(flags.initrace, flags.initgend, + any.a_int = pick_race(flags.initrole, flags.initgend, flags.initalign, PICK_RANDOM) + 1; if (any.a_int == 0) /* must be non-zero */ - any.a_int = randrole() + 1; + any.a_int = randrace(flags.initrole) + 1; add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random", MENU_UNSELECTED); any.a_int = i + 1; /* must be non-zero */ add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit", MENU_UNSELECTED); - Sprintf(pbuf, "Pick a role for your %s", plbuf); + Sprintf(pbuf, "Pick the race of your %s", plbuf); end_menu(win, pbuf); n = select_menu(win, PICK_ONE, &selected); destroy_nhwindow(win); - - /* Process the choice */ if (n != 1 || selected[0].item.a_int == any.a_int) goto give_up; /* Selected quit */ - flags.initrole = selected[0].item.a_int - 1; + k = selected[0].item.a_int - 1; free((genericptr_t) selected), selected = 0; } - (void) root_plselection_prompt(plbuf, QBUFSZ - 1, flags.initrole, - flags.initrace, flags.initgend, - flags.initalign); + flags.initrace = k; } + (void) root_plselection_prompt(plbuf, QBUFSZ - 1, + flags.initrole, flags.initrace, + flags.initgend, flags.initalign); + } - /* Select a race, if necessary */ - /* force compatibility with role, try for compatibility with - * pre-selected gender/alignment */ - if (flags.initrace < 0 - || !validrace(flags.initrole, flags.initrace)) { - /* pre-selected race not valid */ - if (pick4u == 'y' || flags.initrace == ROLE_RANDOM - || flags.randomall) { - flags.initrace = pick_race(flags.initrole, flags.initgend, - flags.initalign, PICK_RANDOM); - if (flags.initrace < 0) { - amii_putstr(WIN_MESSAGE, 0, "Incompatible race!"); - flags.initrace = randrace(flags.initrole); + /* Select a gender, if necessary */ + /* force compatibility with role/race, try for compatibility with + * pre-selected alignment */ + if (flags.initgend < 0 + || !validgend(flags.initrole, flags.initrace, flags.initgend)) { + /* pre-selected gender not valid */ + if (pick4u == 'y' || flags.initgend == ROLE_RANDOM + || flags.randomall) { + flags.initgend = pick_gend(flags.initrole, flags.initrace, + flags.initalign, PICK_RANDOM); + if (flags.initgend < 0) { + amii_putstr(WIN_MESSAGE, 0, "Incompatible gender!"); + flags.initgend = randgend(flags.initrole, flags.initrace); + } + } else { /* pick4u == 'n' */ + /* Count the number of valid genders */ + n = 0; /* number valid */ + k = 0; /* valid gender */ + for (i = 0; i < ROLE_GENDERS; i++) { + if (ok_gend(flags.initrole, flags.initrace, i, + flags.initalign)) { + n++; + k = i; } - } else { /* pick4u == 'n' */ - /* Count the number of valid races */ - n = 0; /* number valid */ - k = 0; /* valid race */ - for (i = 0; races[i].noun; i++) { - if (ok_race(flags.initrole, i, flags.initgend, - flags.initalign)) { + } + if (n == 0) { + for (i = 0; i < ROLE_GENDERS; i++) { + if (validgend(flags.initrole, flags.initrace, i)) { n++; k = i; } } - if (n == 0) { - for (i = 0; races[i].noun; i++) { - if (validrace(flags.initrole, i)) { - n++; - k = i; - } - } - } - - /* Permit the user to pick, if there is more than one */ - if (n > 1) { - win = create_nhwindow(NHW_MENU); - start_menu(win); - any.a_void = 0; /* zero out all bits */ - for (i = 0; races[i].noun; i++) - if (ok_race(flags.initrole, i, flags.initgend, - flags.initalign)) { - any.a_int = i + 1; /* must be non-zero */ - add_menu(win, NO_GLYPH, &any, races[i].noun[0], 0, - ATR_NONE, races[i].noun, - MENU_UNSELECTED); - } - any.a_int = pick_race(flags.initrole, flags.initgend, - flags.initalign, PICK_RANDOM) + 1; - if (any.a_int == 0) /* must be non-zero */ - any.a_int = randrace(flags.initrole) + 1; - add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random", - MENU_UNSELECTED); - any.a_int = i + 1; /* must be non-zero */ - add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit", - MENU_UNSELECTED); - Sprintf(pbuf, "Pick the race of your %s", plbuf); - end_menu(win, pbuf); - n = select_menu(win, PICK_ONE, &selected); - destroy_nhwindow(win); - if (n != 1 || selected[0].item.a_int == any.a_int) - goto give_up; /* Selected quit */ - - k = selected[0].item.a_int - 1; - free((genericptr_t) selected), selected = 0; - } - flags.initrace = k; } - (void) root_plselection_prompt(plbuf, QBUFSZ - 1, flags.initrole, - flags.initrace, flags.initgend, - flags.initalign); - } - /* Select a gender, if necessary */ - /* force compatibility with role/race, try for compatibility with - * pre-selected alignment */ - if (flags.initgend < 0 - || !validgend(flags.initrole, flags.initrace, flags.initgend)) { - /* pre-selected gender not valid */ - if (pick4u == 'y' || flags.initgend == ROLE_RANDOM - || flags.randomall) { - flags.initgend = pick_gend(flags.initrole, flags.initrace, - flags.initalign, PICK_RANDOM); - if (flags.initgend < 0) { - amii_putstr(WIN_MESSAGE, 0, "Incompatible gender!"); - flags.initgend = randgend(flags.initrole, flags.initrace); - } - } else { /* pick4u == 'n' */ - /* Count the number of valid genders */ - n = 0; /* number valid */ - k = 0; /* valid gender */ - for (i = 0; i < ROLE_GENDERS; i++) { + /* Permit the user to pick, if there is more than one */ + if (n > 1) { + win = create_nhwindow(NHW_MENU); + start_menu(win); + any.a_void = 0; /* zero out all bits */ + for (i = 0; i < ROLE_GENDERS; i++) if (ok_gend(flags.initrole, flags.initrace, i, flags.initalign)) { + any.a_int = i + 1; + add_menu(win, NO_GLYPH, &any, genders[i].adj[0], 0, + ATR_NONE, genders[i].adj, MENU_UNSELECTED); + } + any.a_int = pick_gend(flags.initrole, flags.initrace, + flags.initalign, PICK_RANDOM) + 1; + if (any.a_int == 0) /* must be non-zero */ + any.a_int = randgend(flags.initrole, flags.initrace) + 1; + add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random", + MENU_UNSELECTED); + any.a_int = i + 1; /* must be non-zero */ + add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit", + MENU_UNSELECTED); + Sprintf(pbuf, "Pick the gender of your %s", plbuf); + end_menu(win, pbuf); + n = select_menu(win, PICK_ONE, &selected); + destroy_nhwindow(win); + if (n != 1 || selected[0].item.a_int == any.a_int) + goto give_up; /* Selected quit */ + + k = selected[0].item.a_int - 1; + free((genericptr_t) selected), selected = 0; + } + flags.initgend = k; + } + (void) root_plselection_prompt(plbuf, QBUFSZ - 1, + flags.initrole, flags.initrace, + flags.initgend, flags.initalign); + } + + /* Select an alignment, if necessary */ + /* force compatibility with role/race/gender */ + if (flags.initalign < 0 + || !validalign(flags.initrole, flags.initrace, flags.initalign)) { + /* pre-selected alignment not valid */ + if (pick4u == 'y' || flags.initalign == ROLE_RANDOM + || flags.randomall) { + flags.initalign = pick_align(flags.initrole, flags.initrace, + flags.initgend, PICK_RANDOM); + if (flags.initalign < 0) { + amii_putstr(WIN_MESSAGE, 0, "Incompatible alignment!"); + flags.initalign = randalign(flags.initrole, flags.initrace); + } + } else { /* pick4u == 'n' */ + /* Count the number of valid alignments */ + n = 0; /* number valid */ + k = 0; /* valid alignment */ + for (i = 0; i < ROLE_ALIGNS; i++) { + if (ok_align(flags.initrole, flags.initrace, + flags.initgend, i)) { + n++; + k = i; + } + } + if (n == 0) { + for (i = 0; i < ROLE_ALIGNS; i++) { + if (validalign(flags.initrole, flags.initrace, i)) { n++; k = i; } } - if (n == 0) { - for (i = 0; i < ROLE_GENDERS; i++) { - if (validgend(flags.initrole, flags.initrace, i)) { - n++; - k = i; - } - } - } - - /* Permit the user to pick, if there is more than one */ - if (n > 1) { - win = create_nhwindow(NHW_MENU); - start_menu(win); - any.a_void = 0; /* zero out all bits */ - for (i = 0; i < ROLE_GENDERS; i++) - if (ok_gend(flags.initrole, flags.initrace, i, - flags.initalign)) { - any.a_int = i + 1; - add_menu(win, NO_GLYPH, &any, genders[i].adj[0], - 0, ATR_NONE, genders[i].adj, - MENU_UNSELECTED); - } - any.a_int = pick_gend(flags.initrole, flags.initrace, - flags.initalign, PICK_RANDOM) + 1; - if (any.a_int == 0) /* must be non-zero */ - any.a_int = - randgend(flags.initrole, flags.initrace) + 1; - add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random", - MENU_UNSELECTED); - any.a_int = i + 1; /* must be non-zero */ - add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit", - MENU_UNSELECTED); - Sprintf(pbuf, "Pick the gender of your %s", plbuf); - end_menu(win, pbuf); - n = select_menu(win, PICK_ONE, &selected); - destroy_nhwindow(win); - if (n != 1 || selected[0].item.a_int == any.a_int) - goto give_up; /* Selected quit */ - - k = selected[0].item.a_int - 1; - free((genericptr_t) selected), selected = 0; - } - flags.initgend = k; } - (void) root_plselection_prompt(plbuf, QBUFSZ - 1, flags.initrole, - flags.initrace, flags.initgend, - flags.initalign); - } - /* Select an alignment, if necessary */ - /* force compatibility with role/race/gender */ - if (flags.initalign < 0 - || !validalign(flags.initrole, flags.initrace, flags.initalign)) { - /* pre-selected alignment not valid */ - if (pick4u == 'y' || flags.initalign == ROLE_RANDOM - || flags.randomall) { - flags.initalign = pick_align(flags.initrole, flags.initrace, - flags.initgend, PICK_RANDOM); - if (flags.initalign < 0) { - amii_putstr(WIN_MESSAGE, 0, "Incompatible alignment!"); - flags.initalign = - randalign(flags.initrole, flags.initrace); - } - } else { /* pick4u == 'n' */ - /* Count the number of valid alignments */ - n = 0; /* number valid */ - k = 0; /* valid alignment */ - for (i = 0; i < ROLE_ALIGNS; i++) { + /* Permit the user to pick, if there is more than one */ + if (n > 1) { + win = create_nhwindow(NHW_MENU); + start_menu(win); + any.a_void = 0; /* zero out all bits */ + for (i = 0; i < ROLE_ALIGNS; i++) if (ok_align(flags.initrole, flags.initrace, flags.initgend, i)) { - n++; - k = i; + any.a_int = i + 1; + add_menu(win, NO_GLYPH, &any, aligns[i].adj[0], 0, + ATR_NONE, aligns[i].adj, MENU_UNSELECTED); } - } - if (n == 0) { - for (i = 0; i < ROLE_ALIGNS; i++) { - if (validalign(flags.initrole, flags.initrace, i)) { - n++; - k = i; - } - } - } + any.a_int = pick_align(flags.initrole, flags.initrace, + flags.initgend, PICK_RANDOM) + 1; + if (any.a_int == 0) /* must be non-zero */ + any.a_int = randalign(flags.initrole, flags.initrace) + 1; + add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random", + MENU_UNSELECTED); + any.a_int = i + 1; /* must be non-zero */ + add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit", + MENU_UNSELECTED); + Sprintf(pbuf, "Pick the alignment of your %s", plbuf); + end_menu(win, pbuf); + n = select_menu(win, PICK_ONE, &selected); + destroy_nhwindow(win); + if (n != 1 || selected[0].item.a_int == any.a_int) + goto give_up; /* Selected quit */ - /* Permit the user to pick, if there is more than one */ - if (n > 1) { - win = create_nhwindow(NHW_MENU); - start_menu(win); - any.a_void = 0; /* zero out all bits */ - for (i = 0; i < ROLE_ALIGNS; i++) - if (ok_align(flags.initrole, flags.initrace, - flags.initgend, i)) { - any.a_int = i + 1; - add_menu(win, NO_GLYPH, &any, aligns[i].adj[0], 0, - ATR_NONE, aligns[i].adj, - MENU_UNSELECTED); - } - any.a_int = pick_align(flags.initrole, flags.initrace, - flags.initgend, PICK_RANDOM) + 1; - if (any.a_int == 0) /* must be non-zero */ - any.a_int = - randalign(flags.initrole, flags.initrace) + 1; - add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random", - MENU_UNSELECTED); - any.a_int = i + 1; /* must be non-zero */ - add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit", - MENU_UNSELECTED); - Sprintf(pbuf, "Pick the alignment of your %s", plbuf); - end_menu(win, pbuf); - n = select_menu(win, PICK_ONE, &selected); - destroy_nhwindow(win); - if (n != 1 || selected[0].item.a_int == any.a_int) - goto give_up; /* Selected quit */ - - k = selected[0].item.a_int - 1; - free((genericptr_t) selected), selected = 0; - } - flags.initalign = k; + k = selected[0].item.a_int - 1; + free((genericptr_t) selected), selected = 0; } + flags.initalign = k; } - /* Success! */ } + /* Success! */ +} #endif /* AMIGA_INTUITION */ diff --git a/sys/atari/tos.c b/sys/atari/tos.c index eee7bd40f..9bf36a81b 100644 --- a/sys/atari/tos.c +++ b/sys/atari/tos.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 tos.c $NHDT-Date: 1432512796 2015/05/25 00:13:16 $ $NHDT-Branch: master $:$NHDT-Revision: 1.7 $ */ +/* NetHack 3.6 tos.c $NHDT-Date: 1501979358 2017/08/06 00:29:18 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.8 $ */ /* NetHack may be freely redistributed. See license for details. */ /* @@ -271,17 +271,20 @@ char *from, *to; int fromfd, tofd, r; char *buf; - if ((fromfd = open(from, O_RDONLY | O_BINARY, 0)) < 0) + fromfd = open(from, O_RDONLY | O_BINARY, 0); + if (fromfd < 0) return -1; - if ((tofd = open(to, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, FCMASK)) - < 0) + tofd = open(to, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, FCMASK); + if (tofd < 0) { + close(fromfd); return -1; - buf = (char *) alloc((size_t) BIGBUF); + } + buf = (char *) alloc((unsigned) BIGBUF); while ((r = read(fromfd, buf, BIGBUF)) > 0) write(tofd, buf, r); close(fromfd); close(tofd); - free(buf); + free((genericptr_t) buf); return 0; /* successful */ } diff --git a/sys/msdos/pckeys.c b/sys/msdos/pckeys.c index 352c916e8..ec59b999d 100644 --- a/sys/msdos/pckeys.c +++ b/sys/msdos/pckeys.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 pckeys.c $NHDT-Date: 1457207039 2016/03/05 19:43:59 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.11 $ */ +/* NetHack 3.6 pckeys.c $NHDT-Date: 1501465420 2017/07/31 01:43:40 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.12 $ */ /* Copyright (c) NetHack PC Development Team 1996 */ /* NetHack may be freely redistributed. See license for details. */ @@ -39,8 +39,8 @@ unsigned char shift; boolean opening_dialog; opening_dialog = pl_character[0] ? FALSE : TRUE; -#ifdef SIMULATE_CURSOR switch (scancode) { +#ifdef SIMULATE_CURSOR case 0x3d: /* F3 = toggle cursor type */ HideCursor(); cursor_type += 1; @@ -53,7 +53,6 @@ unsigned char shift; if ((shift & CTRL) && iflags.tile_view && !opening_dialog) userpan(1); break; - case 0x73: /* Control-left_arrow = scroll horizontal to left */ if ((shift & CTRL) && iflags.tile_view && !opening_dialog) userpan(0); diff --git a/util/lev_main.c b/util/lev_main.c index 3dce1a720..ecf7a444c 100644 --- a/util/lev_main.c +++ b/util/lev_main.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 lev_main.c $NHDT-Date: 1448074107 2015/11/21 02:48:27 $ $NHDT-Branch: master $:$NHDT-Revision: 1.43 $ */ +/* NetHack 3.6 lev_main.c $NHDT-Date: 1501723418 2017/08/03 01:23:38 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.47 $ */ /* Copyright (c) 1989 by Jean-Christophe Collet */ /* NetHack may be freely redistributed. See license for details. */ @@ -281,7 +281,7 @@ char **argv; } fin = freopen(fname, "r", stdin); if (!fin) { - lc_pline("Can't open \"%s\" for input.\n", fname); + lc_pline("Can't open \"%s\" for input.\n", VA_PASS1(fname)); perror(fname); errors_encountered = TRUE; } else { @@ -615,14 +615,14 @@ VA_DECL2(sp_lev *, sp, const char *, fmt) #ifdef USE_STDARG static void vadd_opvars(sp_lev *sp, const char *fmt, va_list the_args) -{ + #else static void vadd_opvars(sp, fmt, the_args) sp_lev *sp; const char *fmt; va_list the_args; -{ + #endif #else /* USE_STDARG | USE_VARARG */ @@ -632,7 +632,7 @@ va_list the_args; void add_opvars VA_DECL2(sp_lev *, sp, const char *, fmt) #endif /* USE_STDARG | USE_VARARG */ - +{ const char *p, *lp; long la; /* Do NOT use VA_START and VA_END in here... see above */ @@ -644,56 +644,56 @@ VA_DECL2(sp_lev *, sp, const char *, fmt) case 'i': /* integer */ { struct opvar *ov = New(struct opvar); - set_opvar_int(ov, VA_NEXT(la, long) ); + set_opvar_int(ov, VA_NEXT(la, long)); add_opcode(sp, SPO_PUSH, ov); break; } case 'c': /* coordinate */ { struct opvar *ov = New(struct opvar); - set_opvar_coord(ov, VA_NEXT(la, long) ); + set_opvar_coord(ov, VA_NEXT(la, long)); add_opcode(sp, SPO_PUSH, ov); break; } case 'r': /* region */ { struct opvar *ov = New(struct opvar); - set_opvar_region(ov, VA_NEXT(la, long) ); + set_opvar_region(ov, VA_NEXT(la, long)); add_opcode(sp, SPO_PUSH, ov); break; } case 'm': /* mapchar */ { struct opvar *ov = New(struct opvar); - set_opvar_mapchar(ov, VA_NEXT(la, long) ); + set_opvar_mapchar(ov, VA_NEXT(la, long)); add_opcode(sp, SPO_PUSH, ov); break; } case 'M': /* monster */ { struct opvar *ov = New(struct opvar); - set_opvar_monst(ov, VA_NEXT(la, long) ); + set_opvar_monst(ov, VA_NEXT(la, long)); add_opcode(sp, SPO_PUSH, ov); break; } case 'O': /* object */ { struct opvar *ov = New(struct opvar); - set_opvar_obj(ov, VA_NEXT(la, long) ); + set_opvar_obj(ov, VA_NEXT(la, long)); add_opcode(sp, SPO_PUSH, ov); break; } case 's': /* string */ { struct opvar *ov = New(struct opvar); - set_opvar_str(ov, VA_NEXT(lp, const char *) ); + set_opvar_str(ov, VA_NEXT(lp, const char *)); add_opcode(sp, SPO_PUSH, ov); break; } case 'v': /* variable */ { struct opvar *ov = New(struct opvar); - set_opvar_var(ov, VA_NEXT(lp, const char *) ); + set_opvar_var(ov, VA_NEXT(lp, const char *)); add_opcode(sp, SPO_PUSH, ov); break; } @@ -701,16 +701,21 @@ VA_DECL2(sp_lev *, sp, const char *, fmt) { long i = VA_NEXT(la, int); if (i < 0 || i >= MAX_SP_OPCODES) - lc_pline("add_opvars: unknown opcode '%ld'.", i); + lc_pline("add_opvars: unknown opcode '%ld'.", VA_PASS1(i)); add_opcode(sp, i, NULL); break; } default: - lc_pline("add_opvars: illegal format character '%c'.", *p); + lc_pline("add_opvars: illegal format character '%ld'.", + VA_PASS1((long) *p)); break; } } - return; + +#if !(defined(USE_STDARG) || defined(USE_VARARGS)) + /* provide closing brace for USE_OLDARGS nested block from VA_DECL2() */ + VA_END(); +#endif } void @@ -770,7 +775,8 @@ char *name; struct lc_funcdefs *f = New(struct lc_funcdefs); if (!f) { - lc_error("Could not alloc function definition for '%s'.", name); + lc_error("Could not alloc function definition for '%s'.", + VA_PASS1(name)); return NULL; } f->next = NULL; @@ -851,7 +857,8 @@ char *name; struct lc_vardefs *f = New(struct lc_vardefs); if (!f) { - lc_error("Could not alloc variable definition for '%s'.", name); + lc_error("Could not alloc variable definition for '%s'.", + VA_PASS1(name)); return NULL; } f->next = NULL; @@ -870,7 +877,7 @@ struct lc_vardefs *fchain; while (tmp) { if (be_verbose && (tmp->n_used == 0)) - lc_warning("Unused variable '%s'", tmp->name); + lc_warning("Unused variable '%s'", VA_PASS1(tmp->name)); nxt = tmp->next; Free(tmp->name); Free(tmp); @@ -909,7 +916,7 @@ long spovar; spovar &= ~SPOVAR_ARRAY; switch (spovar) { default: - lc_error("spovar2str(%ld)", spovar); + lc_error("spovar2str(%ld)", VA_PASS1(spovar)); break; case SPOVAR_INT: n = "integer"; @@ -965,9 +972,11 @@ long vartype; if ((tmp = vardef_defined(vd, varname, 1)) != 0) { if (tmp->var_type != vartype) lc_error("Trying to use variable '%s' as %s, when it is %s.", - varname, spovar2str(vartype), spovar2str(tmp->var_type)); + VA_PASS3(varname, + spovar2str(vartype), + spovar2str(tmp->var_type))); } else - lc_error("Variable '%s' not defined.", varname); + lc_error("Variable '%s' not defined.", VA_PASS1(varname)); } struct lc_vardefs * @@ -981,7 +990,9 @@ long vartype; if ((tmp = vardef_defined(vd, varname, 1)) != 0) { if (tmp->var_type != vartype) lc_error("Trying to redefine variable '%s' as %s, when it is %s.", - varname, spovar2str(vartype), spovar2str(tmp->var_type)); + VA_PASS3(varname, + spovar2str(vartype), + spovar2str(tmp->var_type))); } else { tmp = vardef_new(vartype, varname); tmp->next = vd; @@ -1008,7 +1019,8 @@ int opcode; case SPO_JGE: return SPO_JL; default: - lc_error("Cannot reverse comparison jmp opcode %d.", opcode); + lc_error("Cannot reverse comparison jmp opcode %ld.", + VA_PASS1((long) opcode)); return SPO_NULL; } } @@ -1050,7 +1062,8 @@ struct opvar *ov; tmpov->vardata.str[len] = '\0'; } break; default: { - lc_error("Unknown opvar_clone value type (%d)!", ov->spovartyp); + lc_error("Unknown opvar_clone value type (%ld)!", + VA_PASS1((long) ov->spovartyp)); } /* default */ } /* switch */ return tmpov; @@ -1079,9 +1092,10 @@ char *ldfname; struct lc_funcdefs *f; if (index(ldfname, '.')) - lc_error("Invalid dot ('.') in level name '%s'.", ldfname); + lc_error("Invalid dot ('.') in level name '%s'.", VA_PASS1(ldfname)); if ((int) strlen(ldfname) > 14) - lc_error("Level names limited to 14 characters ('%s').", ldfname); + lc_error("Level names limited to 14 characters ('%s').", + VA_PASS1(ldfname)); f = function_definitions; while (f) { f->n_called = 0; @@ -1169,8 +1183,8 @@ char c; if (!class || class == mons[i].mlet) if (!case_insensitive_comp(s, mons[i].mname)) { if (be_verbose) - lc_warning("Monster type \"%s\" matches \"%s\".", s, - mons[i].mname); + lc_warning("Monster type \"%s\" matches \"%s\".", + VA_PASS2(s, mons[i].mname)); return i; } return ERR; @@ -1205,7 +1219,8 @@ char c; /* class */ objname = obj_descr[i].oc_name; if (objname && !case_insensitive_comp(s, objname)) { if (be_verbose) - lc_warning("Object type \"%s\" matches \"%s\".", s, objname); + lc_warning("Object type \"%s\" matches \"%s\".", + VA_PASS2(s, objname)); return i; } } @@ -1314,14 +1329,14 @@ genericptr_t dat; _opcode *tmp; if ((opc < 0) || (opc >= MAX_SP_OPCODES)) - lc_error("Unknown opcode '%d'", opc); + lc_error("Unknown opcode '%ld'", VA_PASS1((long) opc)); tmp = (_opcode *) alloc(sizeof(_opcode) * (nop + 1)); if (!tmp) { /* lint suppression */ /*NOTREACHED*/ #if 0 /* not possible; alloc() never returns Null */ - lc_error("Could not alloc opcode space"); + lc_error("%s", VA_PASS1("Could not alloc opcode space")); #endif return; } @@ -1392,9 +1407,9 @@ sp_lev *sp; for (i = 0; i < len; i++) if ((tmpmap[max_hig][i] = what_map_char(map[i])) == INVALID_TYPE) { - lc_warning("Invalid character '%c' @ (%d, %d) - replacing " - "with stone", - map[i], max_hig, i); + lc_warning( + "Invalid character '%ld' @ (%ld, %ld) - replacing with stone", + VA_PASS3((long) map[i], (long) max_hig, (long) i)); tmpmap[max_hig][i] = STONE; } while (i < max_len) @@ -1409,8 +1424,9 @@ sp_lev *sp; max_y_map = max_hig - 1; if (max_len > MAP_X_LIM || max_hig > MAP_Y_LIM) { - lc_error("Map too large at (%d x %d), max is (%d x %d)", max_len, - max_hig, MAP_X_LIM, MAP_Y_LIM); + lc_error("Map too large at (%ld x %ld), max is (%ld x %ld)", + VA_PASS4((long) max_len, (long) max_hig, + (long) MAP_X_LIM, (long) MAP_Y_LIM)); } mbuf = (char *) alloc(((max_hig - 1) * max_len) + (max_len - 1) + 2); @@ -1420,7 +1436,8 @@ sp_lev *sp; mbuf[((max_hig - 1) * max_len) + (max_len - 1) + 1] = '\0'; - add_opvars(sp, "siio", VA_PASS4(mbuf, max_hig, max_len, SPO_MAP)); + add_opvars(sp, "siio", VA_PASS4(mbuf, (long) max_hig, (long) max_len, + SPO_MAP)); for (dy = 0; dy < max_hig; dy++) Free(tmpmap[dy]); diff --git a/util/makedefs.c b/util/makedefs.c index 55ea0367d..c2a046a94 100644 --- a/util/makedefs.c +++ b/util/makedefs.c @@ -2238,9 +2238,6 @@ do_permonst() Fprintf(ofp, "%s", Dont_Edit_Code); Fprintf(ofp, "#ifndef PM_H\n#define PM_H\n"); - if (strcmp(mons[0].mname, "playermon") != 0) - Fprintf(ofp, "\n#define\tPM_PLAYERMON\t(-1)"); - for (i = 0; mons[i].mlet; i++) { SpinCursor(3); diff --git a/util/recover.c b/util/recover.c index 5c1c27f1f..27c58e709 100644 --- a/util/recover.c +++ b/util/recover.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 recover.c $NHDT-Date: 1432512785 2015/05/25 00:13:05 $ $NHDT-Branch: master $:$NHDT-Revision: 1.15 $ */ +/* NetHack 3.6 recover.c $NHDT-Date: 1501461282 2017/07/31 00:34:42 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.16 $ */ /* Copyright (c) Janet Walz, 1992. */ /* NetHack may be freely redistributed. See license for details. */ @@ -245,7 +245,7 @@ char *basename; errno); #endif Fprintf(stderr, "Cannot open level 0 for %s.\n", basename); - return (-1); + return -1; } if (read(gfd, (genericptr_t) &hpid, sizeof hpid) != sizeof hpid) { Fprintf( @@ -253,7 +253,7 @@ char *basename; "Checkpoint data incompletely written or subsequently clobbered;", "recovery for \"", basename, "\" impossible."); Close(gfd); - return (-1); + return -1; } if (read(gfd, (genericptr_t) &savelev, sizeof(savelev)) != sizeof(savelev)) { @@ -261,7 +261,7 @@ char *basename; "impossible.\n", basename); Close(gfd); - return (-1); + return -1; } if ((read(gfd, (genericptr_t) savename, sizeof savename) != sizeof savename) @@ -273,7 +273,7 @@ char *basename; || (read(gfd, (genericptr_t) &plbuf, pltmpsiz) != pltmpsiz)) { Fprintf(stderr, "Error reading %s -- can't recover.\n", lock); Close(gfd); - return (-1); + return -1; } /* save file should contain: @@ -288,7 +288,7 @@ char *basename; if (sfd < 0) { Fprintf(stderr, "Cannot create savefile %s.\n", savename); Close(gfd); - return (-1); + return -1; } lfd = open_levelfile(savelev); @@ -296,7 +296,7 @@ char *basename; Fprintf(stderr, "Cannot open level of save for %s.\n", basename); Close(gfd); Close(sfd); - return (-1); + return -1; } if (write(sfd, (genericptr_t) &version_data, sizeof version_data) @@ -304,7 +304,8 @@ char *basename; Fprintf(stderr, "Error writing %s; recovery failed.\n", savename); Close(gfd); Close(sfd); - return (-1); + Close(lfd); + return -1; } if (write(sfd, (genericptr_t) &sfi, sizeof sfi) != sizeof sfi) { @@ -313,7 +314,8 @@ char *basename; savename); Close(gfd); Close(sfd); - return (-1); + Close(lfd); + return -1; } if (write(sfd, (genericptr_t) &pltmpsiz, sizeof pltmpsiz) @@ -323,7 +325,8 @@ char *basename; savename); Close(gfd); Close(sfd); - return (-1); + Close(lfd); + return -1; } if (write(sfd, (genericptr_t) &plbuf, pltmpsiz) != pltmpsiz) { @@ -331,7 +334,8 @@ char *basename; savename); Close(gfd); Close(sfd); - return (-1); + Close(lfd); + return -1; } copy_bytes(lfd, sfd); @@ -364,25 +368,27 @@ char *basename; #if 0 /* OBSOLETE, HackWB is no longer in use */ #ifdef AMIGA - /* we need to create an icon for the saved game - * or HackWB won't notice the file. - */ - { + { + /* we need to create an icon for the saved game + * or HackWB won't notice the file. + */ char iconfile[FILENAME]; int in, out; (void) sprintf(iconfile, "%s.info", savename); in = open("NetHack:default.icon", O_RDONLY); out = open(iconfile, O_WRONLY | O_TRUNC | O_CREAT); - if(in > -1 && out > -1){ - copy_bytes(in,out); - } - if(in > -1)close(in); - if(out > -1)close(out); + if (in > -1 && out > -1) { + copy_bytes(in, out); } + if (in > -1) + close(in); + if (out > -1) + close(out); + } +#endif /*AMIGA*/ #endif -#endif - return (0); + return 0; } #ifdef EXEPATH diff --git a/win/chain/wc_trace.c b/win/chain/wc_trace.c index 9073e062a..b3d21e7ea 100644 --- a/win/chain/wc_trace.c +++ b/win/chain/wc_trace.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 wc_trace.c $NHDT-Date: 1433806611 2015/06/08 23:36:51 $ $NHDT-Branch: master $:$NHDT-Revision: 1.7 $ */ +/* NetHack 3.6 wc_trace.c $NHDT-Date: 1501464799 2017/07/31 01:33:19 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.8 $ */ /* Copyright (c) Kenneth Lorber, 2012 */ /* NetHack may be freely redistributed. See license for details. */ @@ -10,7 +10,7 @@ #include FILE *wc_tracelogf; /* Should be static, but it's just too useful to have - * access to this logfile from arbitrary other files. */ + * access to this logfile from arbitrary other files. */ static unsigned int indent_level; /* Some winfuncs call other winfuncs, so * we need to support nesting. */ @@ -560,7 +560,7 @@ char *posbar; fprintf(wc_tracelogf, "%supdate_positionbar('%s'(%d))\n", INDENT, posbar, (int) strlen(posbar)); } else { - fprintf(wc_tracelogf, "%supdate_positionbar(NULL)\n"); + fprintf(wc_tracelogf, "%supdate_positionbar(NULL)\n", INDENT); } PRE; (*tdp->nprocs->win_update_positionbar)(tdp->ndata, posbar); @@ -901,7 +901,7 @@ void *vp; struct trace_data *tdp = vp; char *rv; - fprintf(wc_tracelogf, "%sget_color_string()\n"); + fprintf(wc_tracelogf, "%sget_color_string()\n", INDENT); PRE; rv = (*tdp->nprocs->win_get_color_string)(tdp->ndata); @@ -911,7 +911,7 @@ void *vp; fprintf(wc_tracelogf, "%s=> '%s'(%d)\n", INDENT, rv, (int) strlen(rv)); } else { - fprintf(wc_tracelogf, "%s=> NULL\n"); + fprintf(wc_tracelogf, "%s=> NULL\n", INDENT); } return rv; diff --git a/win/share/tileset.c b/win/share/tileset.c index 1b65c32b0..d37b91281 100644 --- a/win/share/tileset.c +++ b/win/share/tileset.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 tileset.c $NHDT-Date: 1457207053 2016/03/05 19:44:13 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.0 $ */ +/* NetHack 3.6 tileset.c $NHDT-Date: 1501463811 2017/07/31 01:16:51 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.0 $ */ /* Copyright (c) Ray Chason, 2016. */ /* NetHack may be freely redistributed. See license for details. */ @@ -25,7 +25,7 @@ boolean true_color; 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }; struct TileSetImage image; - FILE *fp = NULL; /* custodial */ + FILE *fp; char header[16]; boolean ok; @@ -40,10 +40,11 @@ boolean true_color; /* Identify the image type */ fp = fopen(filename, "rb"); - if (fp == NULL) goto error; + if (!fp) + goto error; memset(header, 0, sizeof(header)); fread(header, 1, sizeof(header), fp); - fclose(fp); + fclose(fp), fp = (FILE *) 0; /* Call the loader appropriate for the image */ if (memcmp(header, "BM", 2) == 0) { @@ -56,11 +57,13 @@ boolean true_color; } else { ok = FALSE; } - if (!ok) goto error; + if (!ok) + goto error; /* Reject if the interface cannot handle direct color and the image does not use a palette */ - if (!true_color && image.indexes == NULL) goto error; + if (!true_color && image.indexes == NULL) + goto error; /* Save the palette if present */ have_palette = image.indexes != NULL; @@ -87,12 +90,12 @@ boolean true_color; /* Split the image into tiles */ split_tiles(&image); - fclose(fp); free_image(&image); return TRUE; error: - if (fp) fclose(fp); + if (fp) + fclose(fp); free_image(&image); return FALSE; } @@ -108,6 +111,7 @@ static void get_tile_map(image_desc) const char *image_desc; { + return; } void @@ -115,43 +119,40 @@ free_tiles() { unsigned i; - if (tiles != NULL) { + if (tiles) { for (i = 0; i < num_tiles; ++i) { - free(tiles[i].pixels); - free(tiles[i].indexes); + free((genericptr_t) tiles[i].pixels); + free((genericptr_t) tiles[i].indexes); } + free((genericptr_t) tiles), tiles = NULL; } - free(tiles); - tiles = NULL; num_tiles = 0; - free(blank_tile.pixels); - blank_tile.pixels = NULL; - free(blank_tile.indexes); - blank_tile.indexes = NULL; + if (blank_tile.pixels) + free((genericptr_t) blank_tile.pixels), blank_tile.pixels = NULL; + if (blank_tile.indexes) + free((genericptr_t) blank_tile.indexes), blank_tile.indexes = NULL; } static void free_image(image) struct TileSetImage *image; { - free(image->pixels); - image->pixels = NULL; - free(image->indexes); - image->indexes = NULL; - free(image->image_desc); - image->image_desc = NULL; + if (image->pixels) + free((genericptr_t) image->pixels), image->pixels = NULL; + if (image->indexes) + free((genericptr_t) image->indexes), image->indexes = NULL; + if (image->image_desc) + free((genericptr_t) image->image_desc), image->image_desc = NULL; } const struct TileImage * get_tile(tile_index) unsigned tile_index; { - if (tile_index >= num_tiles) { + if (tile_index >= num_tiles) return &blank_tile; - } else { - return &tiles[tile_index]; - } + return &tiles[tile_index]; } static void @@ -176,10 +177,11 @@ const struct TileSetImage *image; for (y1 = 0; y1 < tile_rows; ++y1) { for (x1 = 0; x1 < tile_cols; ++x1) { struct TileImage *tile = &tiles[y1 * tile_cols + x1]; + tile->width = iflags.wc_tile_width; tile->height = iflags.wc_tile_height; tile->pixels = (struct Pixel *) - alloc(tile_size * sizeof(struct Pixel)); + alloc(tile_size * sizeof (struct Pixel)); if (image->indexes != NULL) { tile->indexes = (unsigned char *) alloc(tile_size); } @@ -187,6 +189,7 @@ const struct TileSetImage *image; for (x2 = 0; x2 < iflags.wc_tile_width; ++x2) { unsigned x = x1 * iflags.wc_tile_width + x2; unsigned y = y1 * iflags.wc_tile_height + y2; + i = y * image->width + x; j = y2 * tile->width + x2; tile->pixels[j] = image->pixels[i]; @@ -202,7 +205,7 @@ const struct TileSetImage *image; blank_tile.width = iflags.wc_tile_width; blank_tile.height = iflags.wc_tile_height; blank_tile.pixels = (struct Pixel *) - alloc(tile_size * sizeof(struct Pixel)); + alloc(tile_size * sizeof (struct Pixel)); for (i = 0; i < tile_size; ++i) { blank_tile.pixels[i].r = 0; blank_tile.pixels[i].g = 0;