Infrastructure bits: Qt tombstone uses a short buffer; make sure that
the plname value fits instead of relying on snprintf() to truncate it.
A warning about gold, if any, was iffy but this should guarantee no
reason for future complaint. Year was safe but a compiler sensitive
to buffer overflows wouldn't know that.
Actual bugs: Qt used money in inventory for gold amount on tombstone;
that overlooks gold in containers and will be 0 by tombstone stage if
bones get saved. Year was recalculated from current date+time instead
of using the value that gets passed in--blindly flagging that variable
as UNUSED was a mistake.
Qt is capable of using an ascii map, and does so on the rogue level.
So failing to load tiles doesn't need to quit; it can continue in
text mode.
Not extensively tested. This disables the paper doll when the ascii
map is forced (either via options settings or due to tiles loading
failure, but not when simply on the rogue level) rather than trying
to display it with object class characters.
When items in the paper doll inventory subset (primary worn and
wielded items) have known BUC state, indicate what that is. It
now draws a one pixel wide white border around each doll tile,
and if BUC is known, that border gets its color changed (red for
known cursed, yellow for known uncursed, cyan for known blessed).
That isn't very visual so the first pixel inside the tile is
overwritten with the same color, and alternating pixels are also
overwritten for the second rectangle within. The 2..3 pixel wide
border is visible without cluttering the tile for 'normal' sized
paper doll. The tiles are allowed to be scrunched down to as
small as 6x6 so there won't be much left after 1 or 2 around the
edge are replaced.
Initially I was going to try to highlight welded items but the
more general BUC highlighting is simpler and usually more useful
to the player.
The qt_map.* bits are just reformatting. I was looking at pet
and pile annotations as a way to do BUC annotations but decided
not to attempt that.
During hallucination, actions which triggered update of persistent
inventory made Qt's display of map tiles for equipped objects have
those tiles switch randomly, but ordinary move-by-move fluctations
applied to floor objects left them alone.
Initially I took out hallucination of inventory items altogether,
but ended up putting that back and changing the floor hallucination
to affect Qt's paper doll too. The display.h change isn't needed
but I've left it in.
Enhance the "Qt Settings" dialog box to provide control over the
paper doll subset of inventory displayed between the message and
status windows (above the map). A ton of flailing about for a
fairly small but useful change in functionality.
Old dialog (no title):
| [ ] Zoomed -- check box
| "Width:" [ ] -- number entry spinner
| "Height:" [ ] -- ditto
| "Font:" [ ] -- Huge:18pt, Large:14, Medium:12, Small:10, Tiny:8
| [ Dismiss ] -- button
New dialog:
| "Qt NetHack Settings"
|
| "Map:" [ ] "Zoomed" -- check box
| "Tile Width" [ ] -- number entry spinner
| "Tile Height" [ ] -- ditto
| "Invent:" [ ] "Shown" -- check box
| "Doll Width" [ ] -- number entry spinner
| "Doll Height" [ ] -- ditto
| "Font:" [ ] -- Huge:18pt, Large:14, Medium:12, Small:10, Tiny:8
| [ Dismiss ] -- button
The inventory subset can now be suppressed. When shown (the default),
its size can be set independently of the map tiles' size. I've set
the default to be 32x32 tiles instead of 16x16 used for the map.
The settings are saved and restored automatically by Qt, and persist
not just across save/restore cycles but into new games. (That's not
a change, just a reminder.)
Move the nine #undef's common to all qt_*.cpp sources into qt_pre.h.
Make "hack.h" usage consistent; always enclose withing 'extern "C {'
and '}' even though only some of the sources care.
The core is mapping #annotate to ^N, which has no effect when
number_pad is Off. The Qt menu setup saw it as the way to run
that command, which will only work when number_pad is On. This
fixes the menu and didn't break the large subset of other menu
commands I've tried, but I haven't gotten through half of them yet.
An earlier tweak worked to prevent unnecessary line wrapping
for ^X output in a menu, but #enhance and '+' both had problems
with their last column. This seems to work better but is still
based on thrashing about rather than knowledge of how things are
supposed to operate.
In case you haven't seen it, the Qt screen layout is (a bigger
instance of):
+--------------------+------+--------------------------------+
| messages |invent| status |
| |subset| |
| | | |
| | | |
+------------------------------------------------------------+
| map |
| |
...
| |
+------------------------------------------------------------+
where some status fields include an icon and the inventory subset is
a miniature map showing a paper doll-style display of object tiles
for worn and wielded items. The two separating lines in the top half
can be dragged to resize the three windows there. The default message
window width to too small to see full text of some messages but can
be scrolled left and right. The window for the equipped subset of
inventory is unconditionally present; 'perm_invent' is a no-op.
Paper doll inventory layout (view with fixed-width font...):
Old New two-hand dual-wield
x H b x H b x H b . H b
S " w S " w W " W X " w
G C G G C q G C q G C q
= A = = A = = A = = A =
. U . l U L l U L l U L
. F . . F . . F . . F .
Legend:
'.' = blank, b = blindfold, '"' = amulet, '=' = left and right rings,
w/W = primary weapon, x/X = alternate/secondary weapon, q = quiver,
H = helmet, S = shield, G = gloves, C = cloak, A = suit, U = shirt,
F = boots, l = leash, L = active light source (lamp/candle/Sunsword).
Slots which don't have something equipped are shown blank.
'q' was missing; 'G' used to be shown on both sides. 'l' and 'L' are
new; for either, it picks the first one in inventory that's in active
use. The 'S' and 'x' slots vary depending upon weapon situation
since wearing a shield, wielding a two-handed weapon, and engaging in
two-weapon combat are all mutually exclusive.
The Qt menu entries which were executing nethack's help command
(the '?' menu) were doing so because their command keystroke was
a meta-character and such characters are being converted to '?'
to indicate an error in conversion to Latin1 character set. The
old Qt3 code didn't perform any such conversion.
This fix feels fragile because there are two different places
deciding how to disambiguate partial extended commands (the code
for Qt's '#' handling and a new routine in the core). Qt menus
now send '#' and enough letters to satisfy '#' handling for any
command which uses M-c or has no regular keystroke nor M-c one.
(If it were to send the full extended command name, the letters
after the unambiguous prefix would be left in the input queue to
be processed as subsequent commands.)
There is a fundamental problem that this doesn't address: if
the player uses BIND directives in the run-time config file, the
Qt menu bindings will break unless the BINDs are all done before
selecting windowtype. Qt's menu bindings translate a click on
a menu entry into the keystroke used to invoke the corresponding
command, so using BIND to change that after the menus are set up
will result in the wrong commands being executed.
Changes affecting everybody (using Qt): rename game->Save to
game->Save-and-exit and game->Quit to game->Quit-without-saving.
OSX-specific changes: add separate nethack->Quit and change
game->Quit-without-saving to game->_Quit-without-saving to prevent
that from being hijacked for the nethack menu. nethack->Quit menu
entry works. Command+Q is a keyboard shortcut for it. They bring
up a menu with choices of "Quit without saving" and "Cancel and
return to game". It's not the same as the handler for the window
Close button, which used to offer "Save" or "Cancel" (with the
latter triggering an infinite loop) but now offers "Save and exit"
or "Quit without saving". They don't share any code. The
game->_Quit-without-saving entry doesn't work; it runs nethack's '?'
command like a bunch of other broken menu entries. If it did work,
it would give nethack's "Really quit?" prompt and proceed from there.
The "Quit without saving" response for nethack->Quit confirmation
bypasses that and just quits.
Also OSX, add a second 'about' entry. The first one is hijacked and
added to the nethack menu, the second is help->_About_Qt_NetHack_
and avoids hijacking. Both nethack->About and help->_About_ bring
up the same dialog box showing version and assorted other info.
A lot of flailing about with for relatively small amount of progress.
In the Qt status panel the six characteristics and the older
status conditions all have icons (similar to map tiles) drawn
above their values. (The 3.6 era conditions that I added all
have blank icons and are in need of artwork. 3.7 conditions
aren't implemented.)
Int, Stun, and Conf all feature a brain oriented towards the
player's right shoulder. The intelligence one is just a bare
brain, the stunned one features a black cloud over it, and the
confusion one has something over it that is cloud-like but
shaped differently from Stun as well has being white rather
than black; I'm not sure what that depicts. This transposes
the Confusion icon so that it faces the player's left shoulder
instead of right. Not a very emphatic suggestion of confusion
but seems a useful difference without requiring any artistic
competence.
Menu hackery: change a couple of menu entry names on OSX to
control where they end up.
Move nethack's 'O' command from its hijacked position (due to name
"Options") of "nethack->Preferences..." to "Game->Run-time options".
Move persistent Qt settings on OSX from "Game->Qt settings" to
"nethack->Preferences...".
The Qt settings dialog (now accessed as Preferences...) desperately
needs a title and/or other explanatory text but I haven't figured
out how do to that. The values set with it are persistent, with
apparently quite a few choices for where to save them for future
runs. I used it to increase the size of text in the status window,
and found my settings stored in binary file
~/Library/Preferences/org.nethack.NetHack.plist
The subdirectories ~/Library and ~/Library/Preferences are
standard OSX per-user things. The file name is derived from values
set up in main routine: qt_main.cpp is setting OrganizationDomain
to "nethack.org" and ApplicationName to "NetHack". I've added a
value for ApplicationVersion but don't know whether anything cares
about it.
Add ^X (as "Attributes (extended status)") to the "Info" drop down
menu, also Overview, and Annotate.
Attributes and Overview work, Annotate results in running southeast.
Existing entries Conduct, Adjust, and Skills execute nethack's '?'
command so I didn't bother holding back on adding Annotate. Other
existing entries (Inventory, Discoveries, Spells, and Name) work.
If there's any sort of pattern involved, I'm not seeing it.
The Game menu has "Save", which shows up and works, but that's
supposed to be followed by "Quit" which doesn't show up when the
menu is used. This doesn't attempt to deal with that.
Command+q keystroke, which should close the application, behaves
the same as previously mentioned "quit nethack" in nethack menu:
runs nethack's '?' command and then resumes play.
Prevent an infinite loop that occurred if player clicked on the
close window button and then tried to cancel out of that in the
dialog it brings up.
I don't know whether Qt interface on platforms other than OSX
need this but they're getting it. The choices are changed from
"Save" or "Cancel" to "Save and exit" or "Quit without saving".
Since save allows subsequent restore, not being able to cancel
out of the application shutdown should only be an inconvenience.
Unresolved issues:
I don't know whether there's any other way to bring up that dialog,
where Cancel might be a viable choice. If so, handling that might
be tricky. Quit should definitely be available as an alterative
to Save, but that type of dialog doesn't seem to allow more than
two choices.
Picking "nethack" from application menu and then "quit nethack"
from the resulting pull down menu results in executing nethack's
help command (the '?' menu) and then just resumes play.
Add Michael's fix for control+x.
The enum name of the argument suggests that option+x should have
been sending control characters but that wasn't the case for me.
Before this fix, both control+x and option+x behaved like dead
keys, not transmitting anything for nethack to use. After this
fix, control+x sends ^X as desired but option+x is still dead.
The presence of longer lines has made the 'about' box become wider
so combine the first two short lines into one longer one.
Switching to the longer nethack version string resulted in "This
is NetHack MacOSX Nethack ..." so remove the initial "NetHack"
from the 'about' box's format string. That version string also
includes a final period; strip that off since "with Qt 5.x.y."
follows it to end the sentence.
Still some issues:
The application menu has first entry "nethack" which ought to be
capitalized but I haven't been able to figure out how to accomplish
that.
Some code in qt_main.cpp tries to add an extra instance of "about
NetHack" to the game window's "Help" menu but it doesn't show up.
Assuming you have the prerequisite packages, You can specify the
window ports to include on the make command line:
make WANT_WIN_QT=1 WANT_WIN_X11=1 WANT_WIN_CURSES=1 WANT_WIN_TTY=1 all
Prequisites for window ports beyond tty:
(some sample homebrew commands to obtain them shown but that is not the
only way):
xquartz for x11 support
brew install xquartz
Qt for Qt support
brew install Qt
The change to use fixed-width fonts for menus wasn't working
optimally because the font got changed after menu construction
had measured the necessary width and height amounts. ^X output,
which uses a menu instead of a text window for tty's benefit
(probably curses too; I don't remember), had a couple of lines
which were wrapping unnecessarily.
This fix avoids that, but the extra '+20' shouldn't be needed.
Unfortunately lines in menus are effectively double-spaced, which
looks bad, and I've no idea how to fix that.
Update the 'about' popup to reflect current information.
When I start Qt nethack on OSX 10.11, the horizontal application
menu for nethack that's rendered across the top of the desktop won't
respond to mouse clicks, not even if I click on nethack's title bar
or inside its game window first. But if I give another application
focus (which swaps top-edge menu to one for that other application)
and then click on nethack's title bar to give focus back to nethack
(which also swaps back to the top menu for it), clicking on that menu
begins working. I have no idea what's going on there.
Picking "nethack" in the application menu gives a pull down menu with
"about nethack" as the first entry. When choosing that, the revised
popup looks like
| Qt NetHack is a version of NetHack
| built using the Qt 5 GUI toolkit.
|
| This is NetHack 3.7.0-22 with Qt 5.11.3.
|
| NetHack's Qt interface originally developed by
| Warwick Allison.
|
| Qt:
| https://qt.io/
| NetHack:
| https://www.nethack.org/
The line with Warwick's name is wrapping and I don't know how to
make the popup wide enough to avoid that. The old edition had a
"Homepage" URL for him instead of that sentence but the URL was out
of date. It also had an obsolete URL for Qt and none at all for
NetHack itself.
The status lines are out of date. This brings status conditions
up to 3.6.0 level: adding Stoned, Slimed, Strangled, Deaf,
Levitating, Flying, Riding. It also reorders a few things:
put encumbrance after hunger, put Confused after Stunned, and
Blind after Hallucinating. Also renames Sick to FoodPois and
Ill to TermIll.
So, the portion of status devoted to conditions is now (left to
right on one line):
Satiated/[omitted]/Hungry/Weak/Fainting/Fainted,
[omitted]/Burdened/Stressed/Strained/Overtaxed/Overloaded,
Stone, Slime, Strngl, FoodPois, TermIll,
Stun, Conf, Hallu, Blind, Deaf,
Lev, Fly, Ride.
It's actually two lines. The upper line has a 40x40 or so icon
(aka tile, defined in qt_xpms.h rather than a data file) above
the corresponding text on the lower line. I created a blank icon
and used it for all the added conditions. At some point someone
with artistic talent will need to draw a bunch of things.
Qt menus have [ok][cancel][all][none][other stuff] buttons across
the top but it was disabling [cancel] for inventory viewing and
other pick-none menus. Enable that so that [cancel] is a viable
alternative to typing ESC or clicking on [ok] for dismissing the
menu without picking anything.
This greatly improves the '?' choice when using the '#' prefix
to select an extended command. It isn't perfect, because the
<text><spaces><more text> layout (using spaces to pad the first
column so that the second one lines up) produces at least one
line where <more text> is so long that it wraps, and instead of
| <text><spaces><start of more text>
| <blank><spaces><rest of more text>
that selectable menu entries have, the continuation is
| <text><spaces><start of more text>
|<rest of more text>
(made slightly worse by the fact that <text> is indented a little
and <rest...> isn't.
This affects the aesthetics of all NHW_MENU windows, not just the
one that desparately needed help. Maybe the core should send some
hint on a menu or text window by menu or text window basis about
whether or not fixed-width font is preferable to variable one.
Qt's implementation of '#' puts up a rectangular grid of buttons
containing command names from the alphabetized extcmdlist[]:
| # ? adjust annotate
| apply attributes autopickup call
| cast ...
When 3.6 put all commands into that list, the hardcoded 4 columns
resulted in so many rows that the grid wouldn't fit on the screen
(at least not on my smallish laptop screen). There's no scrollbar
so the commands beyond "takeoff" were inaccessible off the bottom.
Warning messages from within Qt were issued to stderr complaining
about trying to render something off the screen (once each time the
'#' command grid was generated).
It was also including wizard mode commands when not in wizard mode.
Suppress those when they're not applicable, and change the grid to
use 6 columns then and 8 for wizard mode. The appropriate amount
ought to be calculated on the fly but these values work ok with the
current command list. (On my screen; if something smaller is used,
the original problem could come back, just not as severe as before.)
Having an alphabetized list go across rows instead of down columns
feels counter-intuitive so transpose the grid.
| # autopickup ...
| ? call
| adjust cast
| annotate ...
| apply
[Having another button next to <cancel> that lets the user switch
back and forth between the two orientations could be worthwhile.
A full-fledged wc/wc2 option for that doesn't seem warranted.]
The commands can be selected by typing their names as an alternative
to mouse click. The input widget supports <backspace> but lacked
handling for <delete> so add that.
When typing a command by its name, a new grid showing only matching
candidates gets displayed so that you can switch back to mouse input.
It looks pretty bad but does work as intended. I didn't touch that;
however, it looks different now due to the columns-vs-rows change.
The menu after picking "?" looks worse. It assumes a fixed width
font and tries to align things in two columns with spaces, but the
result when using a variable width font is ugly. This makes no
attempt to address that.
tiles2x11 didn't complain about the tile definitions of the renamed
objects. It seems to me that all processors of win/share/*.txt
ought to be sharing the same code instead of apparently rolling
their own. (Maybe the issue was issuing diagnostic messages rather
than noticing the name mismatches? I haven't looked.)
For Qt, if unable to load either nhfiles.bmp or x11tiles, quit after
giving the can't-load-tiles feedback instead of continuing on and
eventually triggering a segfault.
In file included from ../win/Qt/qt_bind.cpp:20:
In file included from /usr/local/Cellar/qt/5.15.0/lib/QtGui.framework/Headers/QtGui:3:
In file included from /usr/local/Cellar/qt/5.15.0/lib/QtGui.framework/Headers/QtGuiDepends:3:
In file included from /usr/local/Cellar/qt/5.15.0/lib/QtCore.framework/Headers/QtCore:4:
In file included from /usr/local/Cellar/qt/5.15.0/lib/QtCore.framework/Headers/qglobal.h:1302:
/usr/local/Cellar/qt/5.15.0/lib/QtCore.framework/Headers/qflags.h:121:41: warning: declaration shadows a
variable in the global namespace [-Wshadow]
Q_DECL_CONSTEXPR inline QFlags(Enum flags) noexcept : i(Int(flags)) {}
^
[…]
../include/flag.h:390:29: note: previous declaration is here
extern NEARDATA struct flag flags;
^
In file included from ../win/Qt/qt_click.cpp:18:
In file included from /usr/local/Cellar/qt/5.15.0/lib/QtGui.framework/Headers/QtGui:3:
In file included from /usr/local/Cellar/qt/5.15.0/lib/QtGui.framework/Headers/QtGuiDepends:3:
In file included from /usr/local/Cellar/qt/5.15.0/lib/QtCore.framework/Headers/QtCore:36:
/usr/local/Cellar/qt/5.15.0/lib/QtCore.framework/Headers/qcache.h:191:15: warning: declaration shadows a
variable in the global namespace [-Wshadow]
Node *u = n;
^
../include/decl.h:219:23: note: previous declaration is here
E NEARDATA struct you u;
^
[…]
In file included from ../win/Qt/qt_click.cpp:18:
In file included from /usr/local/Cellar/qt/5.15.0/lib/QtGui.framework/Headers/QtGui:5:
In file included from /usr/local/Cellar/qt/5.15.0/lib/QtGui.framework/Headers/qabstracttextdocumentlayout.h:45:
In file included from /usr/local/Cellar/qt/5.15.0/lib/QtGui.framework/Headers/qtextlayout.h:47:
In file included from /usr/local/Cellar/qt/5.15.0/lib/QtGui.framework/Headers/qcolor.h:44:
/usr/local/Cellar/qt/5.15.0/lib/QtGui.framework/Headers/qrgb.h:66:46: warning: declaration shadows a
variable in the global namespace [-Wshadow]
inline Q_DECL_CONSTEXPR QRgb qRgb(int r, int g, int b)// set RGB value
^
../include/decl.h:1208:27: note: previous declaration is here
E struct instance_globals g;
^
[…]
In file included from ../win/Qt/qt_glyph.cpp:21:
In file included from /usr/local/Cellar/qt/5.15.0/lib/QtGui.framework/Headers/QtGui:5:
In file included from /usr/local/Cellar/qt/5.15.0/lib/QtGui.framework/Headers/qabstracttextdocumentlayout.h:48:
/usr/local/Cellar/qt/5.15.0/lib/QtGui.framework/Headers/qpalette.h:107:49: warning: declaration shadows a
variable in the global namespace [-Wshadow]
inline void setCurrentColorGroup(ColorGroup cg) { data.current_group = cg; }
^
../include/decl.h:1216:30: note: previous declaration is here
E const struct const_globals cg;
^