Merge branch 'NetHack-3.7' into twitch-interact

This commit is contained in:
2025-08-30 11:09:34 -07:00
396 changed files with 31854 additions and 14952 deletions

1
.gitignore vendored
View File

@@ -56,6 +56,7 @@ Makefile.gcc-orig
*.lastcodeanalysissucceeded
# VS 2017 caches data into the hidden directory .vs
.vs
win/win32/vs/obj/*
# Win32-specific ignores end
.DS_Store
# ms-dos

View File

@@ -361,41 +361,44 @@ Using the cross-compiler, build the following targets:
cross-compile and link with these compiler switches:
-DCROSSCOMPILE and -DCROSSCOMPILE_TARGET
core sources (2019): src/allmain.c, src/alloc.c, src/apply.c,
core sources (2024): src/allmain.c, src/alloc.c, src/apply.c,
src/artifact.c, src/attrib.c, src/ball.c,
src/bones.c, src/botl.c, src/cmd.c, src/dbridge.c,
src/bones.c, src/botl.c, src/calendar.c,
src/coloratt.c, src/cmd.c, src/dbridge.c,
src/decl.c, src/detect.c, src/dig.c, src/display.c,
src/dlb.c, src/do.c, src/do_name.c, src/do_wear.c,
src/dog.c, src/dogmove.c, src/dokick.c,
src/dothrow.c, src/drawing.c, src/dungeon.c,
src/eat.c, src/end.c, src/engrave.c, src/exper.c,
src/explode.c, src/extralev.c, src/files.c,
src/fountain.c, src/hack.c, src/hacklib.c,
src/insight.c, src/invent.c, src/isaac64.c,
src/light.c, src/lock.c, src/mail.c,
src/makemon.c, src/mcastu.c,
src/fountain.c, src/getpos.c, src/glyphs.c,
src/hack.c, src/hacklib.c, src/insight.c,
src/invent.c, src/isaac64.c, src/light.c,
src/lock.c, src/mail.c, src/makemon.c, src/mcastu.c,
src/mdlib.c, src/mhitm.c, src/mhitu.c, src/minion.c,
src/mklev.c, src/mkmap.c, src/mkmaze.c, src/mkobj.c,
src/mkroom.c, src/mon.c, src/mondata.c,
src/monmove.c, src/monst.c, src/mplayer.c,
src/mthrowu.c, src/muse.c, src/music.c,
src/nhlsel.c, src/nhlua.c, src/nhlobj.c,
src/o_init.c, src/objects.c, src/objnam.c,
src/options.c, src/pager.c, src/pickup.c,
src/pline.c, src/polyself.c, src/potion.c,
src/pray.c, src/priest.c, src/quest.c,
src/nhlua.c, src/nhlsel.c, src/nhlobj.c,
src/nhmd4.c, src/objects.c, src/o_init.c,
src/objnam.c, src/options.c, src/pager.c,
src/pickup.c, src/pline.c, src/polyself.c,
src/potion.c, src/pray.c, src/priest.c, src/quest.c,
src/questpgr.c, src/read.c, src/rect.c,
src/region.c, src/restore.c, src/rip.c, src/rnd.c,
src/role.c, src/rumors.c, src/save.c, src/sfstruct.c,
src/shk.c, src/shknam.c, src/sit.c, src/sounds.c,
src/sp_lev.c, src/spell.c, src/steal.c, src/steed.c,
src/region.c, src/report.c, src/restore.c,src/rip.c,
src/rnd.c, src/role.c, src/rumors.c, src/save.c,
src/selvar.c, src/sfstruct.c, src/shk.c,
src/shknam.c, src/sit.c, src/sounds.c, src/sp_lev.c,
src/spell.c, src/stairs.c, src/steal.c, src/steed.c,
src/symbols.c, src/sys.c, src/teleport.c,
src/timeout.c, src/topten.c, src/track.c,
src/trap.c, src/u_init.c, src/uhitm.c, src/vault.c,
src/version.c, src/vision.c,
src/weapon.c, src/were.c, src/wield.c, src/windows.c,
src/wizard.c, src/worm.c, src/worn.c, src/write.c,
src/zap.c, sys/share/cppregex.cpp
src/trap.c, src/u_init.c, src/uhitm.c,
src/utf8map.c, src/vault.c, src/version.c,
src/vision.c, src/weapon.c, src/were.c, src/wield.c,
src/windows.c, src/wizard.c, src/wizcmds.c,
src/worm.c, src/worn.c, src/write.c, src/zap.c,
sys/share/cppregex.cpp
tty sources: win/tty/getline.c, win/tty/termcap.c,
win/tty/topl.c, win/tty/wintty.c
@@ -469,10 +472,10 @@ Cross-compiler pre-built binary downloads:
or pdcursesmod from:
https://github.com/Bill-Gray/PDCursesMod.git
- A shell script to download that djgpp cross-compiler and associated
- A bash script to download that djgpp cross-compiler and associated
pieces for either linux or macOS is available:
sh sys/msdos/fetch-cross-compiler.sh
bash sys/msdos/fetch-cross-compiler.sh
That script won't install anything, it just does file fetches and stores
them in subfolders of lib. The linux.370 and macOS.370 hints files are
@@ -480,7 +483,7 @@ Cross-compiler pre-built binary downloads:
CROSS_TO_MSDOS=1
on your make command line.
Note: Both the fetch-cross-compiler.sh script and the msdos
Note: Both the fetch-cross-compiler.sh bash script and the msdos
cross-compile and package procedures require unzip and zip to be available
on your host build system.
@@ -695,7 +698,7 @@ Cross-compiler url: https://emscripten.org/docs/getting_started/downloads.html
+--------------------------------+
| B7. Case sample: mips |
| B7. Case sample: mips |
+--------------------------------+
Cross-compiler used: gcc-mipsel-linux-gnu, g++-mipsel-linux-gnu

View File

@@ -58,6 +58,11 @@ NOTE: These instructions assume you are on the default branch; this _is_
NOTE: The following instructions require perl. If you do not have perl on
your system, please install it before proceeding.
NOTE: More information on nhgitset.pl is available before installation via:
perldoc DEVEL/nhgitset.pl
After installation, the same information is available with:
git nhhelp nhgitset
A. If you have never set up git on this machine before:
(This assumes you will only be using git for NetHack. If you are going to
use it for other projects as well, think before you type.)
@@ -92,10 +97,11 @@ B. Specify the prefix for variable substitution:
tree you cloned from git. I use ~/nethack/GITADDDIR; for that base,
create the needed directories and edit the file:
~/nethack/GITADDDIR/DOTGIT/PRE
Put this in it (if your OS is not Unix-like you may need to change
the first line):
Put this in it, adapting it to your variant (if your OS is not Unix-like
you may need to change the first line):
#!/bin/sh
git config nethack.substprefix MINE
git config nethack.projectname MineHack
Now make it executable:
chmod +x ~/nethack/GITADDDIR/DOTGIT/PRE
C. Configure the repository:
@@ -169,8 +175,8 @@ A. Introduction
The PREFIX is the value in the git config variable nethack.substprefix.
VARNAME is one of:
Date
Branch (experimental)
Revision (experimental)
Branch
Revision
other names will give a warning.
B. Enabling variable expansion

4
DEVEL/VERSION Normal file
View File

@@ -0,0 +1,4 @@
5
Please see "git log DEVEL" for previous changes.
Make documentation of nhgitset.pl easier to find and
find out about.

View File

@@ -12,11 +12,32 @@ die "Bad subcommand '$ARGV[0]'" unless $ok{$ARGV[0]};
# we won't fail on a failure, so just system()
$rv = system('.git/hooks/nhsub',"--$ARGV[0]",@ARGV[1..$#ARGV]);
if($rv){
print "warning: nhsub failed: $rv $!\n";
print "warning: nhsub failed: $rv $!\n";
}
if(length $ENV{GIT_PREFIX}){
chdir($ENV{GIT_PREFIX}) or die "Can't chdir $ENV{GIT_PREFIX}: $!";
chdir($ENV{GIT_PREFIX}) or die "Can't chdir $ENV{GIT_PREFIX}: $!";
}
exec "git", @ARGV or die "Can't exec git: $!";
__END__
=for nhgitset nhadd Add file contents to the index with NetHack additions
=for nhgitset nhcommit Record changes to the repository with NetHack additions
=head1 NAME
C<NHadd> - NetHack internal common code for nhadd and nhcommit
=head1 SYNOPSIS
C<git nhadd E<lt>git add optionsE<gt>>
C<git nhcommit E<lt>git add optionsE<gt>>
=head1 DESCRIPTION
Run nhsub with the given arguments, then run C<git add> or C<git commit>
with the given arguments. Note that only basic arguments for those commands
are understood; more complex situations may be handled by running C<git nhsub>
manually before running C<git add> or C<git commit>.

View File

@@ -16,9 +16,11 @@ my $tracefile = "/tmp/nhgitt.$$";
# OS hackery
my $DS = quotemeta('/');
my $PDS = '/';
if ($^O eq "MSWin32")
{
$DS = quotemeta('\\');
$PDS = '\\';
}
our %saved_env;
@@ -26,25 +28,23 @@ our @saved_argv;
our $saved_input;
sub saveSTDIN {
@saved_input = <STDIN>;
@saved_input = <STDIN>;
if($trace){
print TRACE "STDIN:\n";
print TRACE $saved_input;
print TRACE "ENDSTDIN\n";
}
if($trace){
print TRACE "STDIN:\n";
print TRACE $saved_input;
print TRACE "ENDSTDIN\n";
}
tie *STDIN, 'NHIO::STDIN', @saved_input;
tie *STDIN, 'NHIO::STDIN', @saved_input;
}
# XXX this needs a re-write (don't tie and untie, just set NEXT=0)
# (the sensitive thing is @foo = <STDIN> )
sub resetSTDIN{
my $x = tied(*STDIN);
my %x = %$x;
my $data = @$x{DATA};
untie *STDIN;
tie *STDIN, 'NHIO::STDIN', $data;
my $x = tied(*STDIN);
my %x = %$x;
my $data = @$x{DATA};
untie *STDIN;
tie *STDIN, 'NHIO::STDIN', $data;
}
# don't need this now
@@ -55,21 +55,142 @@ sub resetSTDIN{
#}
sub PRE {
&do_hook("PRE");
&do_hook("PRE");
}
sub POST {
&do_hook("POST");
&do_hook("POST");
}
###
### versioning for nhgitset and friends
###
# values of nethack.setupversion and DEVEL/VERSION:
# 1 is reserved for repos checked out before versioning was added
# 2 used clean/smudge filter, poorly
# 3 was first production version
# 4 added the version file and version checking; nhhelp, NH_DATESUB support, etc.
sub version_in_devel {
# (1) check for a non-null nethack.setuppath - this handles
# any repo that has already been set up (but NOT checking
# out <v4 over >=v4 since nethack.setuppath will exist but
# DEVEL/VERSION will not).
# XXX if the source repo has been removed, we'll fall back to
# the third case - hopefully that's ok.
# XXX there's no way to recover from a missing source repo
# without editing .git/config.
my $path = `git config --local nethack.setuppath`;
chomp $path;
$path =~ s/DEVEL$//; # NOP if config not set
# (2) else check the local directory; that will be correct for NHsource.
if(0 == length $path){
$path = `git rev-parse --show-toplevel`;
chomp $path;
$path = '' unless(-d "$path${PDS}DEVEL");
}
# (3) If that doesn't exist, check using the invocation path; that will be
# correct for other repos during nhgitset (but will also fail for
# checking out 3 over 4).
if(0 == length $path){
# strip out "DEVEL"
$path = ($0 =~ m!^(.*)${PDS}DEVEL${PDS}.*?(*nla:DEVEL)!)[0];
}
# Uh oh?
if(0==length($path) or (! -d "$path${PDS}DEVEL")){
die "Can't locate DEVEL directory in '$path'.";
}
# Handle checking out version <4 over version >=4. If
# this seems to be the situation, don't revert the code.
return 0 if(! -f "$path${PDS}DEVEL${PDS}VERSION");
my $version;
my $verfile = "$path${PDS}DEVEL${PDS}VERSION";
open VERFH,"<",$verfile or die "xCan't open $verfile: $!";
$version = 0+<VERFH>;
my $message = join('',<VERFH>);
close VERFH;
die "Valid version not found in $verfile" unless($version >= 4);
return ($version,$message) if($version > 0);
return 0;
}
sub version_in_git {
my $vtemp = `git config --local --get nethack.setupversion`;
chomp($vtemp);
return $vtemp if($vtemp > 0);
return 0;
}
sub version_set_git {
my $version_new = $_[0];
system("git config nethack.setupversion $version_new");
if($?){
die "Can't set nethack.setupversion $version_new: $?,$!\n";
}
}
###
### store githash and gitbranch in dat/gitinfo.txt
###
# CAUTION! This is run not just from git hooks, but also from
# sys/unix/gitinfo.sh
sub nhversioning {
use strict;
use warnings;
# See if we're (probably) in a "git pull", in which case we need to
# check for upgrades.
my $check_upgrade = 1 if($_[0]);
# Check for pre-v4 source repo.
my $is_sourcerepo;
{
chomp($is_sourcerepo = `git config --int --get nethack.is-sourcerepo`);
if(0 == length $is_sourcerepo){ # not set - assume old repo
$is_sourcerepo = 1;
}elsif($is_sourcerepo==1){
;
}elsif($is_sourcerepo==0){
;
}
}
# Skip the skipping tests if we're being called directly.
# NB: post-commit has no args, but that will be caught by
# the next test for non-source repos.
if($#ARGV != -1){
# Skip this if we didn't change branches, but see if we need to warn.
if(defined($ARGV[2]) and ($ARGV[2] == 0)){
# Because we can create an out of sync state, possibly warn.
my $ref = $ARGV[1];
if($is_sourcerepo and (0 != 0+`git diff --name-only $ref $ref^ |grep ^DEVEL|wc -l`)){
warn "WARNING: DEVEL directory changed. Versioning may be inconsistent\n";
}
return
}
}
if($check_upgrade){
my $current_version = version_in_git();
my($new_version,$message) = version_in_devel();
if($new_version > $current_version){
warn "nhgitset.pl and/or related programs have changed.\n";
warn "Please re-run nhgitset.pl to update from version $current_version to $new_version.\n";
if(length $message){
warn "Additional information\n$message\n";
}
}
}
# Skip versioning if we aren't in a source repo.
return if(0==$is_sourcerepo);
my $git_sha = `git rev-parse HEAD`;
$git_sha =~ s/\s+//g;
my $git_branch = `git rev-parse --abbrev-ref HEAD`;
@@ -77,7 +198,14 @@ sub nhversioning {
die "git rev-parse failed" unless(length $git_sha and length $git_branch);
my $exists = 0;
if (open my $fh, '<', 'dat/gitinfo.txt') {
no strict 'refs';
no strict 'subs';
my $file_gitinfo = "dat${PDS}gitinfo.txt";
my $file_gittemp = "dat${PDS}TMPgitinfo.txt";
use strict 'subs';
use strict 'refs';
if (open my $fh, '<', $file_gitinfo) {
$exists = 1;
my $hashok = 0;
my $branchok = 0;
@@ -91,61 +219,71 @@ sub nhversioning {
}
close $fh;
if ($hashok && $branchok) {
print "dat/gitinfo.txt unchanged, githash=".$git_sha."\n";
print "$file_gitinfo unchanged, githash=".$git_sha."\n";
return;
}
} else {
print "WARNING: Can't find dat directory\n" unless(-d "dat");
warn "WARNING: Can't find dat directory\n" unless(-d "dat");
return;
}
if (open my $fh, '>', 'dat/gitinfo.txt') {
if (open my $fh, '>', $file_gittemp) {
my $how = ($exists ? "updated" : "created");
print $fh 'githash='.$git_sha."\n";
print $fh 'gitbranch='.$git_branch."\n";
print "dat/gitinfo.txt ".$how.", githash=".$git_sha."\n";
print "$file_gitinfo ".$how.", githash=".$git_sha."\n";
if(close($fh)){
if(rename($file_gittemp, $file_gitinfo)){
; # all ok
} else {
warn "WARNING: Can't rename $file_gittemp -> $file_gitinfo";
}
} else {
warn "WARNING: Can't close temp file: $!";
}
} else {
print "WARNING: Unable to open dat/gitinfo.txt: $!\n";
warn "WARNING: Unable to open $file_gitinfo: $!\n";
}
}
# PRIVATE
sub do_hook {
my($p) = @_;
my $hname = $0;
$hname =~ s!^((.*$DS)|())(.*)!$1$p-$4!;
if(-x $hname){
print TRACE "START $p: $hname\n" if($trace);
my($p) = @_;
my $hname = $0;
$hname =~ s!^((.*$DS)|())(.*)!$1$p-$4!;
if(-x $hname){
print TRACE "START $p: $hname\n" if($trace);
open TOHOOK, "|-", $hname or die "open $hname: $!";
print TOHOOK <STDIN>;
close TOHOOK or die "close $hname: $! $?";
open TOHOOK, "|-", $hname or die "open $hname: $!";
print TOHOOK <STDIN>;
close TOHOOK or die "close $hname: $! $?";
print TRACE "END $p\n" if($trace);
}
print TRACE "END $p\n" if($trace);
}
}
sub trace_start {
return unless($trace);
my $self = shift;
open TRACE, ">>", $tracefile;
print TRACE "START CLIENT PID:$$ ARGV:\n";
print TRACE "CWD: " . cwd() . "\n";
print TRACE "[0] $0\n";
my $x1;
for(my $x=0;$x<scalar @ARGV;$x++){
$x1 = $x+1;
print TRACE "[$x1] $ARGV[$x]\n";
}
print TRACE "ENV:\n";
foreach my $k (sort keys %ENV){
next unless ($k =~ m/(^GIT_)|(^NH)/);
print TRACE " $k => $ENV{$k}\n";
}
return unless($trace);
my $self = shift;
open TRACE, ">>", $tracefile;
print TRACE "START CLIENT PID:$$ ARGV:\n";
print TRACE "CWD: " . cwd() . "\n";
print TRACE "[0] $0\n";
my $x1;
for(my $x=0;$x<scalar @ARGV;$x++){
$x1 = $x+1;
print TRACE "[$x1] $ARGV[$x]\n";
}
print TRACE "ENV:\n";
foreach my $k (sort keys %ENV){
next unless ($k =~ m/(^GIT_)|(^NH)/);
print TRACE " $k => $ENV{$k}\n";
}
}
BEGIN {
%saved_env = %ENV;
@saved_argv = @ARGV;
&trace_start;
%saved_env = %ENV;
@saved_argv = @ARGV;
&trace_start;
}
###
@@ -153,42 +291,41 @@ BEGIN {
###
package NHIO::STDIN;
sub TIEHANDLE {
my $class = shift;
my %fh;
# XXX yuck
if(ref @_[0]){
$fh{DATA} = @_[0];
} else {
$fh{DATA} = \@_;
}
$fh{NEXT} = 0;
return bless \%fh, $class;
my $class = shift;
my %fh;
if(ref @_[0]){
$fh{DATA} = @_[0];
} else {
$fh{DATA} = \@_;
}
$fh{NEXT} = 0;
return bless \%fh, $class;
}
sub READLINE {
my $self = shift;
return undef if($self->{EOF});
if(wantarray){
my $lim = $#{$self->{DATA}};
my @ary = @{$self->{DATA}}[$self->{NEXT}..$lim];
my @rv = @ary[$self->{NEXT}..$#ary];
$self->{EOF} = 1;
return @rv;
} else{
my $rv = $self->{DATA}[$self->{NEXT}];
if(length $rv){
$self->{NEXT}++;
return $rv;
} else {
$self->{EOF} = 1;
return undef;
}
}
my $self = shift;
return undef if($self->{EOF});
if(wantarray){
my $lim = $#{$self->{DATA}};
my @ary = @{$self->{DATA}}[$self->{NEXT}..$lim];
my @rv = @ary[$self->{NEXT}..$#ary];
$self->{EOF} = 1;
return @rv;
} else{
my $rv = $self->{DATA}[$self->{NEXT}];
if(length $rv){
$self->{NEXT}++;
return $rv;
} else {
$self->{EOF} = 1;
return undef;
}
}
}
sub EOF {
$self = shift;
return $self->{EOF};
$self = shift;
return $self->{EOF};
}
1;
@@ -223,11 +360,20 @@ NHgithook - common code for NetHack git hooks (and other git bits)
(core hook code)
&NHgithook::POST;
__END__
=for nhgitset NHgithook Infrastructure for NetHack git hooks.
=head1 DESCRIPTION
Perl module for infrastructure of NetHack Git hooks.
Buffers call information so multiple independent actions may be coded for
Git hooks and similar Git callouts.
Maintains C<dat/gitinfo.txt>.
Common routines for dealing with nethack.setupversion git config variable.
=head1 SETUP
Changing the C<$trace> and C<$tracefile> variables requires editing the
@@ -247,6 +393,9 @@ may be useful since multiple processes may be live at the same time.
Some features not well tested, especially under Windows.
Not well documented, but almost no one needs to change (or even call)
this code.
=head1 AUTHOR
Kenneth Lorber (keni@his.com)

View File

@@ -17,24 +17,24 @@ my $dbgfile = ($^O eq "MSWin32") ? "$ENV{TEMP}.$$" : "/tmp/trace.$$";
open TRACE, ">>", $rawin?"/dev/tty":(($debug==0)? $sink : $dbgfile);
print TRACE "TEST TRACE\n";
if($debug){
print TRACE "START CLIENT ARGV:\n";
print TRACE "[0] $0\n";
my $x1;
for(my $x=0;$x<scalar @ARGV;$x++){
$x1 = $x+1;
print TRACE "[$x1] $ARGV[$x]\n";
}
print TRACE "ENV:\n";
foreach my $k (sort keys %ENV){
next unless ($k =~ m/^GIT_/);
print TRACE " $k => $ENV{$k}\n";
}
print TRACE "CWD: " . `pwd`;
&dumpfile($ARGV[0], "[0O]");
&dumpfile($ARGV[1], "[1A]");
&dumpfile($ARGV[2], "[2B]");
print TRACE "L=$ARGV[3]\n";
print TRACE "END\n";
print TRACE "START CLIENT ARGV:\n";
print TRACE "[0] $0\n";
my $x1;
for(my $x=0;$x<scalar @ARGV;$x++){
$x1 = $x+1;
print TRACE "[$x1] $ARGV[$x]\n";
}
print TRACE "ENV:\n";
foreach my $k (sort keys %ENV){
next unless ($k =~ m/^GIT_/);
print TRACE " $k => $ENV{$k}\n";
}
print TRACE "CWD: " . `pwd`;
&dumpfile($ARGV[0], "[0O]");
&dumpfile($ARGV[1], "[1A]");
&dumpfile($ARGV[2], "[2B]");
print TRACE "L=$ARGV[3]\n";
print TRACE "END\n";
}
my $mark_len = $ARGV[3];
@@ -47,37 +47,37 @@ my $mark_end = '>' x $mark_len;
my $PREFIX;
# pick up the prefix for substitutions in this repo
if($rawin){
$PREFIX = "TEST";
$PREFIX = "TEST";
} else {
$PREFIX = `git config --local --get nethack.substprefix`;
chomp($PREFIX);
$PREFIX = `git config --local --get nethack.substprefix`;
chomp($PREFIX);
}
my @out;
my $cntout;
if($rawin){
@out = <STDIN>;
@out = <STDIN>;
} else {
#system "git merge-file -p .... > temp
my $tags = "-L CURRENT -L ANCESTOR -L OTHER"; # XXX should "CURRENT" be "MINE"?
@out = `git merge-file -p $tags $ARGV[1] $ARGV[0] $ARGV[2]`;
#system "git merge-file -p .... > temp
my $tags = "-L CURRENT -L ANCESTOR -L OTHER"; # XXX should "CURRENT" be "MINE"?
@out = `git merge-file -p $tags $ARGV[1] $ARGV[0] $ARGV[2]`;
#NB: we don't check the exit value because it's useless
print TRACE "MERGE-FILE START\n".join("",@out)."MERGE-FILE END\n";
print TRACE "MERGE-FILE START\n".join("",@out)."MERGE-FILE END\n";
}
($cntout,@out) = &edit_merge(@out);
if($rawin){
print "COUNT: $cntout\n";
print @out;
print "COUNT: $cntout\n";
print @out;
} else {
# spit @out to $ARGV[1] (careful: what about EOL character?)
open OUT, ">$ARGV[1]" or die "Can't open $ARGV[1]";
print OUT @out;
close OUT;
# spit @out to $ARGV[1] (careful: what about EOL character?)
open OUT, ">$ARGV[1]" or die "Can't open $ARGV[1]";
print OUT @out;
close OUT;
print TRACE "WRITING START ($ARGV[1])\n".join("",@out)."WRITING END\n";
&dumpfile($ARGV[1], "READBACK");
print TRACE "WRITING START ($ARGV[1])\n".join("",@out)."WRITING END\n";
&dumpfile($ARGV[1], "READBACK");
}
print TRACE "COUNT: $cntout\n";
@@ -95,37 +95,37 @@ exit( ($cntout>0) ? 1 : 0);
# keep failing so we don't need to keep changing the setup while building this script
sub dumpfile {
my($file, $tag) = @_;
print TRACE "FILE $tag START\n";
print TRACE `hexdump -C $file`;
print TRACE "FILE END\n";
my($file, $tag) = @_;
print TRACE "FILE $tag START\n";
print TRACE `hexdump -C $file`;
print TRACE "FILE END\n";
}
sub edit_merge {
my(@input) = @_;
# $::count is a bit ugly XXX
local $::count = 0; # we need the number of conflicts for exit()
my @out;
my(@input) = @_;
# $::count is a bit ugly XXX
local $::count = 0; # we need the number of conflicts for exit()
my @out;
local $_;
while($_ = shift @input){
if(m/^$mark_start /){
print TRACE "FOUND A CONFLICT\n";
my @conflict;
push(@conflict, $_);
while($_ = shift @input){
push(@conflict, $_);
if(m/^$mark_end /){
last;
}
}
push(@out, &edit_conflict(@conflict));
} else {
push(@out, $_);
local $_;
while($_ = shift @input){
if(m/^$mark_start /){
print TRACE "FOUND A CONFLICT\n";
my @conflict;
push(@conflict, $_);
while($_ = shift @input){
push(@conflict, $_);
if(m/^$mark_end /){
last;
}
}
push(@out, &edit_conflict(@conflict));
} else {
push(@out, $_);
}
print TRACE "RETURN count=$::count\n";
return($::count, @out);
}
print TRACE "RETURN count=$::count\n";
return($::count, @out);
}
sub edit_conflict {
@@ -305,41 +305,41 @@ print TRACE "MVM: -$varname-$oursval-$theirval-\n";
package PREFIX;
# Resolve the conflict of a single var's 2 values. Return undef to leave the conflict.
sub Date {
my($PREFIX, $varname, $mine, $theirs) = @_;
my $m = ($mine =~ m/(\d+)/)[0];
my $t = ($theirs =~ m/(\d+)/)[0];
return undef unless ($m>0) && ($t>0);
my($PREFIX, $varname, $mine, $theirs) = @_;
my $m = ($mine =~ m/(\d+)/)[0];
my $t = ($theirs =~ m/(\d+)/)[0];
return undef unless ($m>0) && ($t>0);
return "\$$PREFIX-$varname: " . (($m>$t)?$mine:$theirs) .' $';
return "\$$PREFIX-$varname: " . (($m>$t)?$mine:$theirs) .' $';
}
#sub Header {
#sub Author {
sub Branch {
my($PREFIX, $varname, $mine, $theirs) = @_;
$mine =~ s/^\s+//; $mine =~ s/\s+$//;
$theirs =~ s/^\s+//; $theirs =~ s/\s+$//;
return "\$$PREFIX-$varname: $mine \$" if(length $mine);
return "\$$PREFIX-$varname: $theirs \$" if(length $theirs);
return "\$$PREFIX-$varname\$" if(length $theirs);
my($PREFIX, $varname, $mine, $theirs) = @_;
$mine =~ s/^\s+//; $mine =~ s/\s+$//;
$theirs =~ s/^\s+//; $theirs =~ s/\s+$//;
return "\$$PREFIX-$varname: $mine \$" if(length $mine);
return "\$$PREFIX-$varname: $theirs \$" if(length $theirs);
return "\$$PREFIX-$varname\$" if(length $theirs);
}
sub Revision {
my($PREFIX, $varname, $mine, $theirs) = @_;
my($m) = ($mine =~ m/1.(\d+)/);
my($t) = ($theirs =~ m/1.(\d+)/);
if($m > 0 && $t > 0){
my $q = ($m > $t) ? $m : $t;
return "\$$PREFIX-$varname: 1.$q \$";
}
if($m > 0){
return "\$$PREFIX-$varname: 1.$m \$";
}
if($t > 0){
return "\$$PREFIX-$varname: 1.$t \$";
}
return "\$$PREFIX-$varname\$";
my($PREFIX, $varname, $mine, $theirs) = @_;
my($m) = ($mine =~ m/1.(\d+)/);
my($t) = ($theirs =~ m/1.(\d+)/);
if($m > 0 && $t > 0){
my $q = ($m > $t) ? $m : $t;
return "\$$PREFIX-$varname: 1.$q \$";
}
if($m > 0){
return "\$$PREFIX-$varname: 1.$m \$";
}
if($t > 0){
return "\$$PREFIX-$varname: 1.$t \$";
}
return "\$$PREFIX-$varname\$";
}
__END__
@@ -396,3 +396,17 @@ TEST 8:
===
/* NetHack 3.7 objnam.c $TEST-Date: 1426977394 2015/03/21 22:36:34 $ $TEST-Branch: master $:$TEST-Revision: 1.108 $ */
>>> d3
=for nhgitset NHsubst NetHack merge driver
=head1 NAME
C<NHsubst> - NetHack merge driver
=head1 SYNOPSIS
(called from C<git>, do not invoke directly)
=head1 DESCRIPTION
This is invoked by git through .git/config.

View File

@@ -3,6 +3,8 @@
# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
# NetHack may be freely redistributed. See license for details.
# Not in use as of v3, but could come back in the future.
# clean/smudge filter for handling substitutions
use strict;
@@ -54,9 +56,9 @@ if($ARGV[0] eq "--clean"){
exit 1;
}
# XXX for now, there isn't any - if we get called, we subst. No options for now.
# XX for now, there isn't any - if we get called, we subst. No options for now.
# get relevant config info
#XXX
#XX
#git check-attr -a $ARGV[1]
# Process stdin to stdout.
@@ -109,7 +111,7 @@ sub Date {
my($val, $mode, $submode) = @_;
if($mode eq "c"){
if($submode==0){
# we add this to make merge easier for now XXX
# we add this to make merge easier for now XX
my $now = time; # not %s below - may not be portable
# YYYY/MM/DD HH:MM:SS
$val = "$now " . strftime("%Y/%m/%d %H:%M:%S", gmtime($now));

79
DEVEL/hooksdir/nhhelp Normal file
View File

@@ -0,0 +1,79 @@
#!/usr/bin/perl
# $NHDT-Date: 1730238507 2024/10/29 21:48:27 $ $NHDT-Brev: keni-gitset:1.0 $
# Copyright (c) 2024 by Kenneth Lorber, Kensington, Maryland
# NetHack may be freely redistributed. See license for details.
# This deals with a git problem: there is no way to do:
# git help alias-name
# (yes, that will show the definition of the alias, but not show an actual
# help document).
#
# So we implement this:
# nhhelp
# With no arguments, run perldoc on this file.
# nhhelp FOO
# Run perldoc on .git/hooks/FOO (if it exists).
if($#ARGV == -1){
system("perldoc $0")==0 or die "perldoc error: $!\n";
exit 0;
}
if($#ARGV == 0){
if($ARGV[0] eq "-a"){
&listhelp;
exit 0;
}
chomp(my $target = `git config nethack.aliashelp.$ARGV[0]`);
my $file = ".git/hooks/$target";
if(-f $file){
system("perldoc $file")==0 or die "perldoc error: $!\n";
} else {
print "Unknown name '$ARGV[0]'\n";
&usage;
}
exit 0;
}
&usage;
exit 0;
sub usage {
print <<E_O_M;
usage: git nhhelp [<nhcmd>|-a]
E_O_M
}
sub listhelp {
print "nhhelp is available for:\n";
my @namelist = `git config --name-only --get-regexp 'nethack.aliashelp.*'`;
print "NAMELIST $?\n" if($?);
@namelist = map {
if(m/^nethack.aliashelp.(.*)/){
chomp(my $x = `git config 'nethack.aliasdesc.$1'`);
sprintf("%-12s %s",$1,$x);
}
} sort @namelist;
print " " . join("\n ", @namelist)."\n";
exit 0;
}
__END__
=for nhgitset nhhelp Help on NetHack git commands
=head1 NAME
C<nhhelp> - NetHack git command for help on NetHack git commands
=head1 SYNOPSIS
C<git nhhelp [nhcmd|-a]>
=head1 DESCRIPTION
With no arguments, print this message.
With one argument matching a NetHack git command, print the
documentation for that command.
With the argument C<-a>, show all available nhhelp topics with one line
summaries.

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
#!/usr/bin/perl
# $NHDT-Date: 1524689631 2018/04/25 20:53:51 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.1 $
# NetHack 3.7 post-applypatch $NHDT-Date: 1524689631 2018/04/25 20:53:51 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1 $
# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
# NetHack may be freely redistributed. See license for details.
@@ -24,7 +24,11 @@ BEGIN {
chomp $gitdir;
push(@INC, $gitdir.$PDS."hooks");
}
use NHgithook;
eval {use NHgithook;};
if($@){
warn "loading NHgithook failed: $@";
$nogithook = 1;
}
#STARTUP-END
&NHgithook::PRE;

View File

@@ -24,10 +24,15 @@ BEGIN {
chomp $gitdir;
push(@INC, $gitdir.$PDS."hooks");
}
use NHgithook;
eval {use NHgithook;};
if($@){
warn "loading NHgithook failed: $@";
$nogithook = 1;
}
#STARTUP-END
&NHgithook::PRE;
&NHgithook::nhversioning;
eval { &NHgithook::nhversioning unless($nogithook) };
warn "nhversioning failed: $@" if($@);
&NHgithook::POST;
exit 0;

View File

@@ -24,10 +24,17 @@ BEGIN {
chomp $gitdir;
push(@INC, $gitdir.$PDS."hooks");
}
use NHgithook;
eval {use NHgithook;};
if($@){
warn "loading NHgithook failed: $@";
$nogithook = 1;
}
#STARTUP-END
&NHgithook::PRE;
&NHgithook::nhversioning;
eval { &NHgithook::nhversioning unless($nogithook) };
warn "nhversioning failed: $@" if($@);
&NHgithook::POST;
exit 0;

View File

@@ -25,10 +25,15 @@ BEGIN {
push(@INC, $gitdir.$PDS."hooks");
}
use NHgithook;
eval {use NHgithook;};
if($@){
warn "loading NHgithook failed: $@";
$nogithook = 1;
}
#STARTUP-END
&NHgithook::PRE;
&NHgithook::nhversioning;
eval { &NHgithook::nhversioning(1) unless($nogithook) };
warn "nhversioning failed: $@" if($@);
&NHgithook::POST;
exit 0;

View File

@@ -24,7 +24,11 @@ BEGIN {
chomp $gitdir;
push(@INC, $gitdir.$PDS."hooks");
}
use NHgithook;
eval {use NHgithook;};
if($@){
warn "loading NHgithook failed: $@";
$nogithook = 1;
}
#STARTUP-END
&NHgithook::saveSTDIN;

View File

@@ -24,7 +24,11 @@ BEGIN {
chomp $gitdir;
push(@INC, $gitdir.$PDS."hooks");
}
use NHgithook;
eval {use NHgithook;};
if($@){
warn "loading NHgithook failed: $@";
$nogithook = 1;
}
#STARTUP-END
&NHgithook::PRE;

View File

@@ -24,7 +24,11 @@ BEGIN {
chomp $gitdir;
push(@INC, $gitdir.$PDS."hooks");
}
use NHgithook;
eval {use NHgithook;};
if($@){
warn "loading NHgithook failed: $@";
$nogithook = 1;
}
#STARTUP-END
&NHgithook::PRE;

View File

@@ -24,7 +24,11 @@ BEGIN {
chomp $gitdir;
push(@INC, $gitdir.$PDS."hooks");
}
use NHgithook;
eval {use NHgithook;};
if($@){
warn "loading NHgithook failed: $@";
$nogithook = 1;
}
#STARTUP-END
&NHgithook::PRE;

View File

@@ -24,7 +24,11 @@ BEGIN {
chomp $gitdir;
push(@INC, $gitdir.$PDS."hooks");
}
use NHgithook;
eval {use NHgithook;};
if($@){
warn "loading NHgithook failed: $@";
$nogithook = 1;
}
#STARTUP-END
&NHgithook::saveSTDIN;

View File

@@ -24,7 +24,11 @@ BEGIN {
chomp $gitdir;
push(@INC, $gitdir.$PDS."hooks");
}
use NHgithook;
eval {use NHgithook;};
if($@){
warn "loading NHgithook failed: $@";
$nogithook = 1;
}
#STARTUP-END
&NHgithook::PRE;

View File

@@ -1,5 +1,5 @@
#!/usr/bin/perl
# $NHDT-Date: 1524689633 2018/04/25 20:53:53 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.1 $
# NetHack 3.7 prepare-commit-msg $NHDT-Date: 1524689633 2018/04/25 20:53:53 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1 $
# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
# NetHack may be freely redistributed. See license for details.
@@ -24,7 +24,11 @@ BEGIN {
chomp $gitdir;
push(@INC, $gitdir.$PDS."hooks");
}
use NHgithook;
eval {use NHgithook;};
if($@){
warn "loading NHgithook failed: $@";
$nogithook = 1;
}
#STARTUP-END
&NHgithook::PRE;

View File

@@ -3,32 +3,29 @@
# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
# NetHack may be freely redistributed. See license for details.
# value of nethack.setupversion we will end up with when this is done
# version 1 is reserved for repos checked out before versioning was added
my $version_new = 3;
my $version_old = 0; # current version, if any (0 is no entry ergo new repo)
use Cwd;
use Getopt::Std;
# Activestate Perl doesn't include File::Spec. Grr.
BEGIN {
eval "require File::Spec::Functions";
if($@){
die <<E_O_M;
eval "require File::Spec::Functions";
if($@){
die <<E_O_M;
File::Spec not found. (If you are running ActiveState Perl please run:
cpan File::Spec
and re-run this program.
cpan File::Spec
then re-run this program.
E_O_M
}
File::Spec::Functions->import;
}
File::Spec::Functions->import;
}
exit 1 unless(getopts('nvf')); # TODO: this can probably have better output
# OS hackery
my $DS = quotemeta('/'); # Directory Separator (for regex)
my $DSP = '/'; # ... for printing
BEGIN {
# OS hackery
$DS = quotemeta('/'); # Directory Separator (for regex)
$PDS = '/'; # ... for printing
# Temporarily disabled; there's something weird about msys
# msys: POSIXish over a Windows filesystem (so / not \ but \r\n not \n).
#if($^O eq "msys"){
@@ -37,78 +34,130 @@ my $DSP = '/'; # ... for printing
# # NB: We don't need to do anything about File::Spec. It doesn't know
# # about msys but it defaults to Unix, so we'll be ok.
#}
if($^O eq "MSWin32"){
if($^O eq "MSWin32"){
$DS = quotemeta('\\');
$DSP = '\\';
$PDS = '\\';
}
# Fix @INC so we can 'use NHgithook' before it's installed.
# Set $is_sourcerepo while we're at it - same logic.
{
# Special case for running nhgitset against a different repo.
# Must preceed the normal case!
# NB: we use $DEVhooksdir later in the program
$DEVhooksdir = ($0 =~ m!^(.*)$DS!)[0];
chomp($DEVhooksdir);
$DEVhooksdir .= $PDS."hooksdir";
push(@INC, $DEVhooksdir) if(-d $DEVhooksdir);
# This one is for the normal case (in NHsource)
my $topdir = `git rev-parse --show-toplevel`;
chomp $topdir;
$topdir .= "${PDS}DEVEL${PDS}hooksdir";
push(@INC, $topdir) if(-d $topdir);
$is_sourcerepo = 0;
$is_sourcerepo = 1 if(-d $topdir);
}
}
use NHgithook;
# current (installed) version, if any (0 is no entry ergo new repo)
my $version_old = NHgithook::version_in_git;
# version this program will install
my($version_new,$message_new) = NHgithook::version_in_devel;
if(0==$version_new and !opt_f){
# Edge case: this repo has been set up using version >= 4, but now we're running
# nhgitset after checking out DEVEL supporting version <4.
# Use -f to recover from broken DEVEL code.
print STDERR "DEVEL has version <4 code but version >=4 code already installed. Stopping.\n";
print STDERR "(If you need to reinstall the old code, rerun with -f\n";
exit 0;
}
die "Valid version not found in DEVEL/VERSION" unless(0==$version_new or $version_new >= 4);
# make sure we're at the top level of a repo
if(! -d ".git"){
die "This is not the top level of a git repository.\n";
die "This is not the top level of a git repository.\n";
}
my $vtemp = `git config --local --get nethack.setupversion`;
chomp($vtemp);
if($vtemp > 0){
$version_old = 0+$vtemp;
if($version_old != $version_new){
print STDERR "Migrating from setup version $version_old to $version_new\n" if($opt_v);
}
if($version_old >= $version_new and !opt_f){
print STDERR "Nothing to do.\n";
exit 0;
}
# legacy check:
if(length $vtemp == 0){
if(`git config --get merge.NHsubst.name` =~ m/^Net/){
$version_old = 1;
print STDERR "Migrating to setup version 1\n" if($opt_v);
if($version_old > 0){
if($version_old != $version_new){
print STDERR "Migrating from setup version $version_old to $version_new\n";
if(length $message_new){
print STDERR "Additional information:\n$message_new\n";
}
}
}
# legacy check:
if(length $version_old == 0){
if(`git config --get merge.NHsubst.name` =~ m/^Net/){
$version_old = 1;
print STDERR "Migrating to setup version 1\n" if($opt_v);
}
}
my $gitadddir = `git config --get nethack.gitadddir`;
chomp($gitadddir);
if(length $gitadddir){
if(! -d $gitadddir){
die "nethack.gitadddir has invalid value '$gitadddir'\n";
}
if(! -d $gitadddir){
die "nethack.gitadddir has invalid value '$gitadddir'\n";
}
}
print STDERR "nethack.gitadddir=$gitadddir\n" if($opt_v);
# This is (relatively) safe because we know we're at R in R/DEVEL/nhgitset.pl
my $srcdir = ($0 =~ m!^(.*)$DS!)[0];
#XXX do I really want a full path for srcdir? how badly?
if(! -f catfile($srcdir, 'nhgitset.pl')){
die "I can't find myself in '$srcdir'\n";
die "I can't find myself in '$srcdir'\n";
}
print STDERR "Copying from: $srcdir\n" if($opt_v);
if($opt_f || $version_old==0){
print STDERR "Configuring line endings\n" if($opt_v);
unlink catfile('.git','index') unless($opt_n);
system("git reset") unless($opt_n);
system("git config --local core.safecrlf true") unless($opt_n);
system("git config --local core.autocrlf false") unless($opt_n);
print STDERR "Configuring line endings\n" if($opt_v);
system("git reset") unless($opt_n);
&add_config('core.safecrlf', 'true') unless($opt_n);
&add_config('core.autocrlf', 'false') unless($opt_n);
} elsif($version_old <2){
my $xx = `git config --get --local core.safecrlf`;
if($xx !~ m/true/){
print STDERR "\nNeed to 'rm .git${DSP}index;git reset'.\n";
print STDERR " When ready to proceed, re-run with -f flag.\n";
exit 2;
}
my $xx = `git config --get --local core.safecrlf`;
if($xx !~ m/true/){
print STDERR "\nNeed to 'rm .git${PDS}index;git reset'.\n";
print STDERR " When ready to proceed, re-run with -f flag.\n";
exit 2;
}
}
print STDERR "Installing aliases\n" if($opt_v);
$addpath = catfile(curdir(),'.git','hooks','NHadd');
&add_alias('nhadd', "!$addpath add");
&add_help('nhadd', 'NHadd');
&add_alias('nhcommit', "!$addpath commit");
&add_help('nhcommit', 'NHadd');
my $nhsub = catfile(curdir(),'.git','hooks','nhsub');
&add_alias('nhsub', "!$nhsub");
&add_help('nhsub', 'nhsub');
&add_alias('nhhelp', '!'.catfile(curdir(),'.git','hooks','nhhelp'));
&add_help('nhhelp', 'nhhelp');
&add_help('NHsubst', 'NHsubst');
&add_help('NHgithook', 'NHgithook.pm');
&add_help('nhgitset', 'gitsetdocs', '../../DEVEL/nhgitset.pl');
print STDERR "Installing filter/merge\n" if($opt_v);
# XXXX need it in NHadd to find nhsub???
# removed at version 3
#print STDERR "Installing filter/merge\n" if($opt_v);
#if($^O eq "MSWin32"){
# $cmd = '.git\\\\hooks\\\\NHtext';
#} else {
@@ -117,179 +166,211 @@ print STDERR "Installing filter/merge\n" if($opt_v);
#&add_config('filter.NHtext.clean', "$cmd --clean %f");
#&add_config('filter.NHtext.smudge', "$cmd --smudge %f");
if($version_old == 1 or $version_old == 2){
print STDERR "Removing filter.NHtext\n" if($opt_v);
system('git','config','--unset','filter.NHtext.clean') unless($opt_n);
system('git','config','--unset','filter.NHtext.smudge') unless($opt_n);
system('git','config','--remove-section','filter.NHtext') unless($opt_n);
print STDERR "Removing filter.NHtext\n" if($opt_v);
system('git','config','--unset','filter.NHtext.clean') unless($opt_n);
system('git','config','--unset','filter.NHtext.smudge') unless($opt_n);
system('git','config','--remove-section','filter.NHtext') unless($opt_n);
print STDERR "Removing NHtext\n" if($opt_v);
unlink catfile(curdir(),'.git','hooks','NHtext') unless($opt_n);
print STDERR "Removing NHtext\n" if($opt_v);
unlink catfile(curdir(),'.git','hooks','NHtext') unless($opt_n);
}
&add_config('nethack.setuppath',$srcdir);
&add_config('nethack.is-sourcerepo',0+$is_sourcerepo);
$cmd = catfile(curdir(),'.git','hooks','NHsubst');
&add_config('merge.NHsubst.name', 'NetHack Keyword Substitution');
&add_config('merge.NHsubst.driver', "$cmd %O %A %B %L");
print STDERR "Running directories\n" if($opt_v);
foreach my $dir ( glob("$srcdir$DS*") ){
next unless(-d $dir);
# copy directories into .git (right now that's just hooks and nhgitset.pl)
my @gitadd = length($gitadddir)?glob("$gitadddir$DS*"):undef;
foreach my $dir ( (glob("$srcdir$DS*"), @gitadd) ){
next unless(-d $dir);
my $target = catfile($dir, 'TARGET');
next unless(-f $target);
my $target = catfile($dir, 'TARGET');
next unless(-f $target);
open TARGET, '<', $target or die "$target: $!";
my $targetpath = <TARGET>;
# still have to eat all these line endings under msys, so instead of chomp use this:
$targetpath =~ s![\r\n]!!g;
close TARGET;
print STDERR "Directory $dir -> $targetpath\n" if($opt_v);
open TARGET, '<', $target or die "$target: $!";
my $targetpath = <TARGET>;
# still have to eat all these line endings under msys, so instead of chomp use this:
$targetpath =~ s![\r\n]!!g;
close TARGET;
print STDERR "Directory $dir -> $targetpath\n" if($opt_v);
my $enddir = $dir;
$enddir =~ s!.*$DS!!;
if(! &process_override($enddir, "INSTEAD")){
&process_override($enddir, "PRE");
my $fnname = "do_dir_$enddir";
if(defined &$fnname){
&$fnname($dir, $targetpath);
}
&process_override($enddir, "POST");
my $enddir = $dir;
$enddir =~ s!.*$DS!!;
if(! &process_override($enddir, "INSTEAD")){
&process_override($enddir, "PRE");
my $fnname = "do_dir_$enddir";
if(defined &$fnname){
&$fnname($dir, $targetpath);
}
&process_override($enddir, "POST");
}
}
&do_file_nhgitset();
&check_prefix; # for variable substitution
&check_gitvars; # for variable substitution
if($version_old != $version_new){
print STDERR "Setting version to $version_new\n" if($opt_v);
if(! $opt_n){
system("git config nethack.setupversion $version_new");
if($?){
die "Can't set nethack.setupversion $version_new: $?,$!\n";
}
}
if($version_old != $version_new or $opt_f){
print STDERR "Setting version to $version_new\n" if($opt_v);
NHgithook::version_set_git($version_new) if(! $opt_n);
}
exit 0;
sub process_override {
my($srcdir, $plname) = @_;
return 0 unless(length $gitadddir);
# @files: [0] is the name under .git/hooks; others are places to
# check during configuration
sub add_help {
my($cmd, @files) = @_;
my $plpath = catfile($gitadddir, $srcdir, $plname);
#print STDERR " ",catfile($srcdir, $plname),"\n"; # save this for updating docs - list of overrides
return 0 unless(-x $plpath);
print STDERR "Running $plpath\n" if($opt_v);
# current directory is top of target repo
unless($opt_n){
system("$plpath $opt_v") and die "Callout $plpath failed: $?\n";
&add_config("nethack.aliashelp.$cmd", $files[0]);
# pull out =for nhgitset CMD description...
my $desc;
foreach my $file (@files){
open my $fh, "<", "$DEVhooksdir/$file";
if($fh){
while(<$fh>){
m/^=for\s+nhgitset\s+\Q$cmd\E\s+(.*)/ && do {
$desc = $1;
goto found;
}
}
close $fh;
} else {
warn "Can't open: '$DEVhooksdir/$file' ($!)\n";
}
return 1;
}
found:
if($desc){
&add_config("nethack.aliasdesc.$cmd", $desc);
} else {
&add_config("nethack.aliasdesc.$cmd", "(no description available)");
}
}
sub process_override {
my($srcdir, $plname) = @_;
return 0 unless(length $gitadddir);
my $plpath = catfile($gitadddir, $srcdir, $plname);
return 0 unless(-x $plpath);
print STDERR "RunningOverride $plpath\n" if($opt_v);
# current directory is top of target repo
unless($opt_n){
system("$plpath $opt_v") and die "Callout $plpath failed: $?\n";
}
return 1;
}
sub add_alias {
my($name, $def) = @_;
&add_config("alias.$name",$def);
my($name, $def) = @_;
&add_config("alias.$name",$def);
}
sub add_config {
my($name, $val) = @_;
system('git', 'config', '--local', $name, $val) unless($opt_n);
my($name, $val) = @_;
system('git', 'config', '--local', $name, $val) unless($opt_n);
}
sub check_gitvars {
&check_prefix("substprefix");
&check_prefix("projectname");
}
sub check_prefix {
my $lcl = `git config --local --get nethack.substprefix`;
chomp($lcl);
if(0==length $lcl){
my $other = `git config --get nethack.substprefix`;
chomp($other);
if(0==length $other){
print STDERR "ERROR: nethack.substprefix is not set anywhere. Set it and re-run.\n";
exit 2;
} else {
&add_config('nethack.substprefix', $other);
print STDERR "Copying prefix '$other' to local repository.\n" if($opt_v);
}
$lcl = $other; # for display below
my $which = $_[0];
my $lcl = `git config --local --get nethack.$which`;
chomp($lcl);
if(0==length $lcl){
my $other = `git config --get nethack.$which`;
chomp($other);
if(0==length $other){
print STDERR "ERROR: nethack.$which is not set anywhere. Set it and re-run.\n";
exit 2;
} else {
&add_config('nethack.$which', $other);
print STDERR "Copying prefix '$other' to local repository.\n" if($opt_v);
}
print "\n\nUsing prefix '$lcl' - PLEASE MAKE SURE THIS IS CORRECT\n\n";
$lcl = $other; # for display below
}
print "Using $which '$lcl' - PLEASE MAKE SURE THIS IS CORRECT\n";
}
sub do_dir_DOTGIT {
if(1){
# We are NOT going to mess with config now.
return;
} else {
my($srcdir, $targetdir) = @_;
#warn "do_dir_DOTGIT($srcdir, $targetdir)\n";
my $cname = "$srcdir/config";
if(-e $cname){
print STDERR "Appending to .git/config\n" if($opt_v);
open CONFIG, ">>.git/config" or die "open .git/config: $!";
open IN, "<", $cname or die "open $cname: $!";
my @data = <IN>;
print CONFIG @data;
close IN;
close CONFIG;
} else {
print STDERR " Nothing to add to .git/config\n" if($opt_v);
}
# XXX are there other files in .git that we might want to handle?
# So just in case:
for my $file ( glob("$srcdir/*") ){
next if( $file =~ m!.*/TARGET$! );
next if( $file =~ m!.*/config$! );
die "ERROR: no handler for $file\n";
}
}
my($srcdir, $targetdir) = @_;
# not currently in use so just bail
return;
# are there other files in .git that we might want to handle?
# So just in case:
for my $file ( glob("$srcdir/*") ){
next if( $file =~ m!.*/TARGET$! );
next if( $file =~ m!.*/config$! );
die "ERROR: no handler for $file\n";
}
}
sub do_dir_hooksdir {
my($srcdir, $targetdir) = @_;
my($srcdir, $targetdir) = @_;
unless (-d $targetdir){
unless (-d $targetdir){
# Older versions of git, when cloning a repo and
# the expected source templates directory does not
# exist, does not create .git/hooks. So do it here.
mkdir $targetdir;
print STDERR "WARNING: .git/hooks had to be created.\n";
print STDERR " You may want to update git.\n";
mkdir $targetdir;
print STDERR "WARNING: .git/hooks had to be created.\n";
print STDERR " You may want to update git.\n";
}
for my $path ( glob("$srcdir$DS*") ){
next if( $path =~ m!.*${DS}TARGET$! );
my $file = $path;
$file =~ s!.*$DS!!;
$file = catfile($targetdir, $file);
next if($opt_n);
open IN, "<", $path or die "Can't open $path: $!";
open OUT, ">", "$file" or die "Can't open $file: $!";
while(<IN>){
print OUT;
}
close OUT;
close IN;
for my $path ( glob("$srcdir$DS*") ){
next if( $path =~ m!.*${DS}TARGET$! );
my $file = $path;
$file =~ s!.*$DS!!;
$file = catfile($targetdir, $file);
next if($opt_n);
open IN, "<", $path or die "Can't open $path: $!";
open OUT, ">", "$file" or die "Can't open $file: $!";
while(<IN>){
print OUT;
}
close OUT;
close IN;
if(! -x $file){
chmod 0755 ,$file;
}
if(! -x $file){
chmod 0755 ,$file;
}
}
}
sub do_file_nhgitset {
my $infile = "DEVEL/nhgitset.pl";
$infile = "$DEVhooksdir/../nhgitset.pl" unless(-f $infile);
my $outfile = ".git/hooks/gitsetdocs";
open IN, "<", $infile or die "Can't open $infile:$!";
open OUT, ">", $outfile or die "Can't open $outfile:$!";
my $started;
print IN "die \"DO NOT RUN THIS FILE\n\"";
while(<IN>){
m/^__END__/ && do {$started =1; next};
print OUT if($started);
}
close OUT;
close IN;
}
#(can we change the .gitattributes syntax to include a comment character?)
#maybe [comment] attr.c:parse_attr_line
#grr - looks like # is the comment character
__END__
(can we change the .gitattributes syntax to include a comment character?)
maybe [comment] attr.c:parse_attr_line
grr - looks like # is the comment character
=head1 NAME
nhgitset.pl - Setup program for NetHack git repositories
@@ -302,17 +383,36 @@ nhgitset.pl - Setup program for NetHack git repositories
=head1 DESCRIPTION
nhgitset.pl installs NetHack-specific setup after a C<git clone> (or after
changes to the desired configuration, which are installed by re-running
nhgitset.pl).
nhgitset.pl installs NetHack-specific setup after a C<git clone> or after
changes to the setup, which are installed by re-running nhgitset.pl. If
an upgrade is needed, you will be informed during a C<git pull> or similar
operation.
The following options are available:
B<-f> Force. Do not use this unless the program requests it.
=over
B<-n> Make no changes.
=item B<-f>
B<-v> Verbose output.
Force. Do not use this unless the program requests it or the hooks are broken.
=back
=over
=item B<-n>
Dry-run - make no changes.
=back
=over
=item B<-v>
Verbose output.
=back
=head1 CONFIG
@@ -329,8 +429,35 @@ nethack.gitadddir
nethack.setupversion
The version for nhgitset.pl and friends; has no relationship
to NetHack version numbers.
nethack.substprefix
The prefix this repo uses for variable substitution.
nethack.projectname
The name of the game being built - see C<Project()>.
nethack.is-sourcerepo
Does this repo contain NetHack source code? (1 = yes, 0 = no)
nethack.setuppath
Path to (and including) the DEVEL directory used including the
copy of nhgitset.pl used to set up this repo.
nethack.aliashelp.*
The last element of the variable is the name used with C<git nhhelp>
and the value is the name of a file to display with C<perldoc>.
nethack.aliasdesc.*
The last element of the variable is the name used with C<git nhhelp>
and the value is short help displayed with C<git nhhelp -a>.
=head1 EXIT STATUS
@@ -339,3 +466,5 @@ nethack.substprefix
1 Fail.
2 Intervention required.
=for nhgitset nhgitset NetHack git helper installer

140
Files
View File

@@ -12,8 +12,8 @@ Porting README azure-pipelines.yml
DEVEL:
(files for people developing changes to NetHack)
Developer.txt code_features.txt code_style.txt git_recipes.txt
gitinfo.pl nhgitset.pl
Developer.txt VERSION code_features.txt code_style.txt
git_recipes.txt gitinfo.pl nhgitset.pl
DEVEL/DOTGIT:
(file for people developing changes to NetHack)
@@ -23,11 +23,11 @@ DEVEL/hooksdir:
(files for people developing changes to NetHack)
NHadd NHgithook.pm NHsubst
NHtext TARGET applypatch-msg
commit-msg nhsub post-applypatch
post-checkout post-commit post-merge
post-rewrite pre-applypatch pre-auto-gc
pre-commit pre-push pre-rebase
prepare-commit-msg
commit-msg nhhelp nhsub
post-applypatch post-checkout post-commit
post-merge post-rewrite pre-applypatch
pre-auto-gc pre-commit pre-push
pre-rebase prepare-commit-msg
dat:
(files for all versions)
@@ -47,20 +47,21 @@ Val-strt.lua Wiz-fila.lua Wiz-filb.lua Wiz-goal.lua Wiz-loca.lua
Wiz-strt.lua air.lua asmodeus.lua astral.lua baalz.lua
bigrm-1.lua bigrm-2.lua bigrm-3.lua bigrm-4.lua bigrm-5.lua
bigrm-6.lua bigrm-7.lua bigrm-8.lua bigrm-9.lua bigrm-10.lua
bigrm-11.lua bogusmon.txt castle.lua cmdhelp data.base
dungeon.lua earth.lua engrave.txt epitaph.txt fakewiz1.lua
fakewiz2.lua fire.lua hellfill.lua help hh
history juiblex.lua keyhelp knox.lua license
medusa-1.lua medusa-2.lua medusa-3.lua medusa-4.lua minefill.lua
minend-1.lua minend-2.lua minend-3.lua minetn-1.lua minetn-2.lua
minetn-3.lua minetn-4.lua minetn-5.lua minetn-6.lua minetn-7.lua
nhcore.lua nhlib.lua opthelp optmenu oracle.lua
oracles.txt orcus.lua quest.lua rumors.fal rumors.tru
sanctum.lua soko1-1.lua soko1-2.lua soko2-1.lua soko2-2.lua
soko3-1.lua soko3-2.lua soko4-1.lua soko4-2.lua symbols
themerms.lua tower1.lua tower2.lua tower3.lua tribute
tut-1.lua tut-2.lua usagehlp valley.lua water.lua
wizard1.lua wizard2.lua wizard3.lua wizhelp
bigrm-11.lua bigrm-12.lua bogusmon.txt castle.lua cmdhelp
data.base dungeon.lua earth.lua engrave.txt epitaph.txt
fakewiz1.lua fakewiz2.lua fire.lua hellfill.lua help
hh history juiblex.lua keyhelp knox.lua
license luahelper medusa-1.lua medusa-2.lua medusa-3.lua
medusa-4.lua minefill.lua minend-1.lua minend-2.lua minend-3.lua
minetn-1.lua minetn-2.lua minetn-3.lua minetn-4.lua minetn-5.lua
minetn-6.lua minetn-7.lua nhcore.lua nhlib.lua opthelp
optmenu oracle.lua oracles.txt orcus.lua quest.lua
rumors.fal rumors.tru sanctum.lua soko1-1.lua soko1-2.lua
soko2-1.lua soko2-2.lua soko3-1.lua soko3-2.lua soko4-1.lua
soko4-2.lua symbols themerms.lua tower1.lua tower2.lua
tower3.lua tribute tut-1.lua tut-2.lua usagehlp
valley.lua water.lua wizard1.lua wizard2.lua wizard3.lua
wizhelp
doc:
(files for all versions)
@@ -93,13 +94,14 @@ dlb.h dungeon.h engrave.h extern.h flag.h
fnamesiz.h func_tab.h global.h hack.h hacklib.h
integer.h isaac64.h lint.h mail.h mextra.h
mfndpos.h micro.h mkroom.h monattk.h mondata.h
monflag.h monst.h monsters.h nhmd4.h obj.h
objclass.h objects.h optlist.h patchlevel.h pcconf.h
permonst.h prop.h quest.h rect.h region.h
rm.h seffects.h selvar.h skills.h sndprocs.h
sp_lev.h spell.h stairs.h sym.h sys.h
tcap.h tileset.h timeout.h tradstdc.h trap.h
unixconf.h vision.h vmsconf.h warnings.h winami.h
monflag.h monst.h monsters.h nhmd4.h nhregex.h
obj.h objclass.h objects.h optlist.h patchlevel.h
pcconf.h permonst.h prop.h quest.h rect.h
region.h rm.h savefile.h seffects.h selvar.h
sfmacros.h sfprocs.h skills.h sndprocs.h sp_lev.h
spell.h stairs.h sym.h sys.h tcap.h
tileset.h timeout.h tradstdc.h trap.h unixconf.h
vision.h vmsconf.h warnings.h weight.h winami.h
wincurs.h windconf.h winprocs.h wintype.h you.h
youprop.h
@@ -291,26 +293,27 @@ windsound.c
src:
(files for all versions)
allmain.c alloc.c apply.c artifact.c attrib.c ball.c
bones.c botl.c calendar.c cmd.c coloratt.c date.c
dbridge.c decl.c detect.c dig.c display.c dlb.c
do.c do_name.c do_wear.c dog.c dogmove.c dokick.c
dothrow.c drawing.c dungeon.c eat.c end.c engrave.c
exper.c explode.c extralev.c files.c fountain.c getpos.c
glyphs.c hack.c hacklib.c insight.c invent.c isaac64.c
light.c lock.c mail.c makemon.c mcastu.c mdlib.c
mhitm.c mhitu.c minion.c mklev.c mkmap.c mkmaze.c
mkobj.c mkroom.c mon.c mondata.c monmove.c monst.c
mplayer.c mthrowu.c muse.c music.c nhlobj.c nhlsel.c
nhlua.c nhmd4.c o_init.c objects.c objnam.c options.c
pager.c pickup.c pline.c polyself.c potion.c pray.c
priest.c quest.c questpgr.c read.c rect.c region.c
report.c restore.c rip.c rnd.c role.c rumors.c
save.c selvar.c sfstruct.c shk.c shknam.c sit.c
sounds.c sp_lev.c spell.c stairs.c steal.c steed.c
strutil.c symbols.c sys.c teleport.c timeout.c topten.c
track.c trap.c u_init.c uhitm.c utf8map.c vault.c
version.c vision.c weapon.c were.c wield.c windows.c
wizard.c wizcmds.c worm.c worn.c write.c zap.c
bones.c botl.c calendar.c cfgfiles.c cmd.c coloratt.c
date.c dbridge.c decl.c detect.c dig.c display.c
dlb.c do.c do_name.c do_wear.c dog.c dogmove.c
dokick.c dothrow.c drawing.c dungeon.c eat.c end.c
engrave.c exper.c explode.c extralev.c files.c fountain.c
getpos.c glyphs.c hack.c hacklib.c insight.c invent.c
isaac64.c light.c lock.c mail.c makemon.c mcastu.c
mdlib.c mhitm.c mhitu.c minion.c mklev.c mkmap.c
mkmaze.c mkobj.c mkroom.c mon.c mondata.c monmove.c
monst.c mplayer.c mthrowu.c muse.c music.c nhlobj.c
nhlsel.c nhlua.c nhmd4.c o_init.c objects.c objnam.c
options.c pager.c pickup.c pline.c polyself.c potion.c
pray.c priest.c quest.c questpgr.c read.c rect.c
region.c report.c restore.c rip.c rnd.c role.c
rumors.c save.c selvar.c sfbase.c sfstruct.c shk.c
shknam.c sit.c sounds.c sp_lev.c spell.c stairs.c
steal.c steed.c strutil.c symbols.c sys.c teleport.c
timeout.c topten.c track.c trap.c u_init.c uhitm.c
utf8map.c vault.c version.c vision.c weapon.c were.c
wield.c windows.c wizard.c wizcmds.c worm.c worn.c
write.c zap.c
submodules:
(files in top directory)
@@ -428,14 +431,14 @@ vmsunix.c
sys/windows:
(files for Windows 7/8.x/10/11 version)
Install.windows Makefile.mingw32 Makefile.mingw32.depend
Makefile.nmake build-msys2.txt build-nmake.txt
build-vs.txt console.rc consoletty.c
fetch.cmd guitty.c nethack.def
nethackrc.template nhico.uu nhsetup.bat
porthelp sysconf.template win10.c
win10.h win32api.h windmain.c
windsys.c winos.h
GNUmakefile GNUmakefile.depend Install.windows
Makefile.nmake build-msys2.txt build-nmake.txt
build-vs.txt console.rc consoletty.c
fetch.cmd fetch.sh guitty.c
nethack.def nethackrc.template nhico.uu
nhsetup.bat porthelp sysconf.template
win10.c win10.h win32api.h
windmain.c windsys.c winos.h
sys/windows/vs:
(files for Visual Studio 2019 or 2022 Community Edition builds)
@@ -447,7 +450,7 @@ config.props console.props
cpp.hint default.props
default_dll.props default_lib.props
dirs.props dll.props
files.props
files.props sfctool.sln
sys/windows/vs/FetchPrereq:
(files for Visual Studio 2019 or 2022 Community Edition builds)
@@ -528,10 +531,18 @@ sys/windows/vs/dlb:
(files for Visual Studio 2019 or 2022 Community Edition builds)
afterdlb.proj dlb.vcxproj
sys/windows/vs/fetchctags:
(files for Visual Studio 2019 or 2022 Community Edition builds)
fetchctags.nmake fetchctags.vcxproj
sys/windows/vs/hacklib:
(file for Visual Studio 2019 or 2022 Community Edition builds)
hacklib.vcxproj
sys/windows/vs/lualib:
(file for Visual Studio 2019 or 2022 Community Edition builds)
lualib.vcxproj
sys/windows/vs/makedefs:
(files for Visual Studio 2019 or 2022 Community Edition builds)
aftermakedefs.proj makedefs.vcxproj
@@ -544,6 +555,14 @@ sys/windows/vs/recover:
(files for Visual Studio 2019 or 2022 Community Edition builds)
afterrecover.proj recover.vcxproj
sys/windows/vs/sfctool:
(file for Visual Studio 2019 or 2022 Community Edition builds)
sfctool.vcxproj
sys/windows/vs/sftags:
(files for Visual Studio 2019 or 2022 Community Edition builds)
aftersftags.proj sftags.vcxproj
sys/windows/vs/tile2bmp:
(files for Visual Studio 2019 or 2022 Community Edition builds)
aftertile2bmp.proj tile2bmp.vcxproj
@@ -562,12 +581,13 @@ afteruudecode.proj uudecode.vcxproj
test:
(files for testing)
test_cnf.lua test_des.lua test_lev.lua test_obj.lua test_sel.lua
test_shk.lua test_src.lua testmove.lua testwish.lua
README.md test_cnf.lua test_des.lua test_lev.lua test_obj.lua
test_sel.lua test_shk.lua test_src.lua testmove.lua testwish.lua
util:
(files for all versions)
dlb_main.c makedefs.c mdgrep.h mdgrep.pl panic.c recover.c
sfctool.c sfexpasc.c sftags.c stripbs.c
win/Qt:
(files for the Qt 4 or 5 widget library - X11, Windows, Mac OS X)
@@ -664,7 +684,7 @@ pet_mark.xbm rip.xpm x11tiles
src:
(files for win32 that are moved into src at compile time)
Makefile Makefile.mingw32
GNUmakefile Makefile
(files generated by 'moc' for Qt interface at compile time)
qt_kde0.moc qt_main.moc qt_map.moc qt_menu.moc qt_msg.moc

9
README
View File

@@ -57,10 +57,11 @@ considered spoilers:
level once that square's location becomes known (found or magic
mapped); goes away once sanctum temple is found (entered or high altar
mapped)
- savefile: add support to deconstruct internal data structures down into
their individual fields and save those fields instead of the entire
struct
- savefile: use little-endian format for fields where that makes a difference
- savefile: add support for a tool to deconstruct data structures,
that get stored in a savefile, down into their individual fields and
save those individual fields instead of the entire struct. The
intention is to provide a way to export and transport savefiles
between platforms, architectures and data models.
- - - - - - - - - - -

View File

@@ -1,27 +1,27 @@
strategy:
matrix:
linux_latest_gcc9_minimal:
linux_latest_gcc14_minimal:
imageName: 'ubuntu-latest'
toolchainName: gcc9
toolchainName: gcc14
buildTargetName: minimal
linux_jammy_clang_all:
imageName: 'ubuntu-22.04'
linux_noble_clang_all:
imageName: 'ubuntu-24.04'
toolchainName: clang
buildTargetName: all
linux_jammy_gcc9_all:
imageName: 'ubuntu-22.04'
toolchainName: gcc9
buildTargetName: all
linux_jammy_gcc12_all:
imageName: 'ubuntu-22.04'
toolchainName: gcc12
linux_noble_gcc13_all:
imageName: 'ubuntu-24.04'
toolchainName: gcc13
buildTargetName: all
macOS_latest_clang_all:
imageName: 'macOS-latest'
toolchainName: clang
buildTargetName: all
macOS_Ventura_clang13_all:
imageName: 'macOS-13'
macOS_Sequoia_clang15_all:
imageName: 'macOS-15'
toolchainName: clang
buildTargetName: all
windows-visualstudio:
@@ -29,15 +29,15 @@ strategy:
toolchainName: vs
buildTargetName: all
windows-mingw:
imageName: 'windows-2019'
imageName: 'windows-2025'
toolchainName: mingw
buildTargetName: all
linux_focal_cross_msdos:
imageName: 'ubuntu-20.04'
linux_noble_cross_msdos:
imageName: 'ubuntu-24.04'
toolchainName: cross
buildTargetName: msdos
linux_jammy_docs:
imageName: 'ubuntu-22.04'
linux_noble_docs:
imageName: 'ubuntu-24.04'
toolchainName: docs
buildTargetName: all
continueOnError: true
@@ -60,30 +60,20 @@ variables:
steps:
- bash: |
if [ "$(toolchain)" == "gcc7" ]
then
echo "##vso[task.setvariable variable=CC]gcc-7"
echo "##vso[task.setvariable variable=CXX]g++-7"
fi
if [ "$(toolchain)" == "gcc9" ]
then
echo "##vso[task.setvariable variable=CC]gcc-9"
echo "##vso[task.setvariable variable=CXX]g++-9"
fi
if [ "$(toolchain)" == "gcc10" ]
if [ "$(toolchain)" == "gcc13" ]
then
echo "##vso[task.setvariable variable=CC]gcc-10"
echo "##vso[task.setvariable variable=CXX]g++-10"
echo "##vso[task.setvariable variable=CC]gcc-13"
echo "##vso[task.setvariable variable=CXX]g++-13"
fi
if [ "$(toolchain)" == "gcc11" ]
if [ "$(toolchain)" == "gcc14" ]
then
echo "##vso[task.setvariable variable=CC]gcc-11"
echo "##vso[task.setvariable variable=CXX]g++-11"
fi
if [ "$(toolchain)" == "gcc12" ]
then
echo "##vso[task.setvariable variable=CC]gcc-12"
echo "##vso[task.setvariable variable=CXX]g++-12"
echo "##vso[task.setvariable variable=CC]gcc-14"
echo "##vso[task.setvariable variable=CXX]g++-14"
fi
if [ "$(toolchain)" == "clang" ]
then
@@ -92,8 +82,8 @@ steps:
fi
if [ "$(toolchain)" == "cross" ]
then
echo "##vso[task.setvariable variable=CC]gcc-9"
echo "##vso[task.setvariable variable=CXX]g++-9"
echo "##vso[task.setvariable variable=CC]gcc-13"
echo "##vso[task.setvariable variable=CXX]g++-13"
fi
displayName: 'Setting variables'
@@ -124,7 +114,7 @@ steps:
condition: eq( variables.toolchain, 'vs' )
displayName: 'Copying store key'
- task: MSBuild@1
- task: VSBuild@1
inputs:
solution: $(Agent.BuildDirectory)/$(netHackPath)/sys/windows/vs/NetHack.sln
platform: Win32
@@ -142,13 +132,15 @@ steps:
export LUA_VERSION=5.4.6
#
# 64-bit
#export CURLSRC=https://github.com/brechtsanders/winlibs_mingw/releases/download/11.2.0-9.0.0-ucrt-r5/winlibs-x86_64-posix-seh-gcc-11.2.0-mingw-w64ucrt-9.0.0-r5.zip
#export CURLSRC=https://github.com/brechtsanders/winlibs_mingw/releases/download/14.2.0posix-19.1.1-12.0.0-ucrt-r2/winlibs-x86_64-posix-seh-gcc-14.2.0-llvm-19.1.1-mingw-w64ucrt-12.0.0-r2.zip
#export CURLSRC=https://github.com/brechtsanders/winlibs_mingw/releases/download/15.1.0posix-12.0.0-ucrt-r1/winlibs-x86_64-posix-seh-gcc-15.1.0-mingw-w64ucrt-12.0.0-r1.zip
#export CURLDST=mingw-x64.zip
#export MINGWBIN=mingw64
#export MSYSTEM=MINGW64
#
# 32-bit
export CURLSRC=https://github.com/brechtsanders/winlibs_mingw/releases/download/11.2.0-9.0.0-ucrt-r5/winlibs-i686-posix-dwarf-gcc-11.2.0-mingw-w64ucrt-9.0.0-r5.zip
#export CURLSRC=https://github.com/brechtsanders/winlibs_mingw/releases/download/14.2.0posix-19.1.1-12.0.0-ucrt-r2/winlibs-i686-posix-dwarf-gcc-14.2.0-llvm-19.1.1-mingw-w64ucrt-12.0.0-r2.zip
export CURLSRC=https://github.com/brechtsanders/winlibs_mingw/releases/download/15.1.0posix-12.0.0-ucrt-r1/winlibs-i686-posix-dwarf-gcc-15.1.0-mingw-w64ucrt-12.0.0-r1.zip
export CURLDST=mingw-x86.zip
export MINGWBIN=mingw32
export MSYSTEM=MINGW32
@@ -164,10 +156,10 @@ steps:
export
cd ../src
pwd
cp ../sys/windows/Makefile.mingw32* .
mingw32-make -f Makefile.mingw32 CI_COMPILER=1 GIT=1 MSYSTEM=$MSYSTEM LUA_VERSION=$LUA_VERSION clean
mingw32-make -f Makefile.mingw32 CI_COMPILER=1 GIT=1 MSYSTEM=$MSYSTEM LUA_VERSION=$LUA_VERSION depend
mingw32-make -f Makefile.mingw32 CI_COMPILER=1 GIT=1 MSYSTEM=$MSYSTEM LUA_VERSION=$LUA_VERSION
cp ../sys/windows/GNUmakefile* .
mingw32-make -f GNUmakefile CI_COMPILER=1 GIT=1 MSYSTEM=$MSYSTEM LUA_VERSION=$LUA_VERSION clean
mingw32-make -f GNUmakefile CI_COMPILER=1 GIT=1 MSYSTEM=$MSYSTEM LUA_VERSION=$LUA_VERSION depend
mingw32-make -f GNUmakefile CI_COMPILER=1 GIT=1 MSYSTEM=$MSYSTEM LUA_VERSION=$LUA_VERSION
condition: eq( variables.toolchain, 'mingw' )
workingDirectory: $(Agent.BuildDirectory)/$(netHackPath)/src
displayName: 'MinGW Build'
@@ -222,6 +214,7 @@ steps:
workingDirectory: $(Agent.BuildDirectory)/$(netHackPath)
- bash: |
brew install groff
cd sys/unix
sh setup.sh hints/macos.370
cd ../..
@@ -232,12 +225,13 @@ steps:
displayName: 'Building mac full build'
- bash: |
sudo apt -qq -y install libfl2
export GCCVER=gcc1220
cd sys/unix
sh setup.sh hints/linux.370
cd ../..
make fetch-lua
sh sys/msdos/fetch-cross-compiler.sh
sys/msdos/fetch-cross-compiler.sh
retVal=$?
if [ $retVal -eq 0 ]; then
make LUA_VERSION=5.4.6 WANT_WIN_TTY=1 WANT_WIN_CURSES=1 CROSS_TO_MSDOS=1 package

85
dat/bigrm-12.lua Normal file
View File

@@ -0,0 +1,85 @@
-- NetHack bigroom bigrm-12.lua $NHDT-Date: $ $NHDT-Branch: NetHack-3.7 $
-- Copyright (c) 2024 by Pasi Kallinen
-- NetHack may be freely redistributed. See license for details.
--
-- Two hexagons
des.level_flags("mazelevel", "noflipy");
des.level_init({ style = "solidfill", fg = " " });
des.map([[
....................... .......................
......................... .........................
........................... ...........................
............................. .............................
........PPPPPPPPPPPPPPP........ ........LLLLLLLLLLLLLLL........
........PPPPPPPPPPPPPPPPP........ ........LLLLLLLLLLLLLLLLL........
........PPPWWWWWWWWWWWWWPPP...............LLLZZZZZZZZZZZZZLLL........
........PPPWWWWWWWWWWWWWWWPPP.............LLLZZZZZZZZZZZZZZZLLL........
........PPPWWWWWWWWWWWWWWWWWPPP...........LLLZZZZZZZZZZZZZZZZZLLL........
........PPPWWWWWWWWWWWWWWWPPP.............LLLZZZZZZZZZZZZZZZLLL........
........PPPWWWWWWWWWWWWWPPP...............LLLZZZZZZZZZZZZZLLL........
........PPPPPPPPPPPPPPPPP........ ........LLLLLLLLLLLLLLLLL........
........PPPPPPPPPPPPPPP........ ........LLLLLLLLLLLLLLL........
............................. .............................
........................... ...........................
......................... .........................
....................... .......................
]]);
-- maybe replace lavawalls/waterwalls with stone walls
if percent(20) then
if percent(50) then
des.replace_terrain({ fromterrain = "W", toterrain = "-" });
end
if percent(50) then
des.replace_terrain({ fromterrain = "Z", toterrain = "-" });
end
end
-- maybe replace pools with floor and then possibly walls with pools
if percent(25) then
des.replace_terrain({ fromterrain = "P", toterrain = "." });
if percent(75) then
des.replace_terrain({ fromterrain = "W", toterrain = "P" });
end
end
if percent(25) then
des.replace_terrain({ fromterrain = "L", toterrain = "." });
if percent(75) then
des.replace_terrain({ fromterrain = "Z", toterrain = "L" });
end
end
-- maybe make both sides have the same terrain
if percent(20) then
if percent(50) then
-- both are lava
des.replace_terrain({ fromterrain = "P", toterrain = "L" });
des.replace_terrain({ fromterrain = "W", toterrain = "Z" });
else
-- both are water
des.replace_terrain({ fromterrain = "L", toterrain = "P" });
des.replace_terrain({ fromterrain = "Z", toterrain = "W" });
end
end
des.region(selection.area(00,00,75,19), "lit")
des.non_diggable();
des.wallify();
des.stair("up");
des.stair("down");
for i = 1,15 do
des.object();
end
for i = 1,6 do
des.trap();
end
for i = 1,28 do
des.monster();
end

View File

@@ -9,20 +9,20 @@ des.level_flags("mazelevel", "noflip");
des.map([[
----------- -----------
|.........| |.........|
|.........|-----------| |-----------|.........|
|-|...................|----------| |----------|...................|-|
-|.............................|-------|.............................|-
-|.................................................................|-
-|...............................................................|-
-|......LLLLL.......................................LLLLL......|-
-|.....LLLLL.......................................LLLLL.....|-
-|.....LLLLL.......................................LLLLL.....|-
-|......LLLLL.......................................LLLLL......|-
-|...............................................................|-
-|.................................................................|-
-|.............................|-------|.............................|-
|-|...................|----------| |----------|...................|-|
|.........|-----------| |-----------|.........|
|.........------------- -------------.........|
---...................------------ ------------...................---
--.............................---------.............................--
--.................................................................--
--...............................................................--
--......LLLLL.......................................LLLLL......--
--.....LLLLL.......................................LLLLL.....--
--.....LLLLL.......................................LLLLL.....--
--......LLLLL.......................................LLLLL......--
--...............................................................--
--.................................................................--
--.............................---------.............................--
---...................------------ ------------...................---
|.........------------- -------------.........|
|.........| |.........|
----------- -----------
]]);

View File

@@ -12,7 +12,7 @@ des.map([[
--...........-- --...........-- --...........-- --...........--
--.............-- --.............-- --.............-- --.............--
-...............- -...............- -...............- -...............-
|-...............---...............---...............---...............--
--...............---...............---...............---...............--
|.................-.................-.................-.................|
|........T.................T.................T.................T........|
|.......................................................................|

View File

@@ -14,11 +14,11 @@ des.map([[
---------.................................---
---------...........................................---
---------.....................................................---
|--------...............................................................--|
---------...............................................................---
|.........................................................................|
|.L.....................................................................L.|
|.........................................................................|
|--...............................................................--------|
---...............................................................---------
---.....................................................---------
---...........................................---------
---.................................---------

View File

@@ -144,6 +144,7 @@ local loc = place:rndcoord(1);
des.object({ id = "chest", trapped = 0, locked = 1, coord = loc ,
contents = function()
des.object("wishing");
des.object("potion of gain level");
end
});
-- Prevent monsters from eating it. (@'s never eat objects)

View File

@@ -1,5 +1,5 @@
# NetHack 3.7 data.base
# $NHDT-Date: 1684001509 2023/05/13 18:11:49 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.106 $
# $NHDT-Date: 1737609388 2025/01/22 21:16:28 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.141 $
# Copyright (c) 1994, 1995, 1996 by the NetHack Development Team
# Copyright (c) 1994 by Boudewijn Wayers
# NetHack may be freely redistributed. See license for details.
@@ -2056,6 +2056,16 @@ genetic engineer
immediate mutations in the subject. Far from needing an
elaborate laboratory to accomplish such abominations, a mere
touch seems to be all that is necessary.
[]
"I thought the whole point of genetic engineering was to avoid
the random waste of natural evolution, and replace it with
the efficiency of reason," Miles piped up. All three haut-
women turned to stare at him in astonishment, as if a potted
plant had suddenly offered a critique of its fertilization
routine. "Or ... so it seems to me," Miles trailed off in
a much smaller voice.
[ Cetaganda, Lois McMaster Bujold ]
geryon
Forthwith that image vile of fraud appear'd,
His head and upper part expos'd on land,
@@ -2395,7 +2405,6 @@ hell hound*
~helm of *
~crystal helmet
helm*
dented pot
* helmet
A piece of armor designed to protect the head.
(What were you expecting?)
@@ -5230,6 +5239,7 @@ squeaky board
additionally gives the wielder the power of regeneration.
When invoked it performs healing magic.
stair*
branch stair*
Up he went -- very quickly at first -- then more slowly -- then
in a little while even more slowly than that -- and finally,
after many minutes of climbing up the endless stairway, one

View File

@@ -70,7 +70,7 @@ dungeon = {
base = 10,
range = 3,
chance = 40,
nlevels = 11
nlevels = 12
},
{
name = "medusa",

View File

@@ -279,6 +279,8 @@ I died laughing
I disbelieved in reincarnation in my last life, too.
I hacked myself to death
I have all the time in the world
#"reached Mine's End": not necessarily true; sounds like "reached my end"
I have reached Mine's End
I knew I'd find a use for this gravestone!
I know my mind. And it's around here someplace.
I lied! I'll never be alright!

View File

@@ -410,6 +410,20 @@ hells = {
end
des.terrain(outside_walls, " "); -- return the outside back to solid wall
end,
-- 7: open cavern, "mines" with more space
function ()
des.level_init({ style = "solidfill", fg = " ", lit = 0 });
des.level_flags("mazelevel", "noflip");
des.level_init({ style="mines", fg=".", smoothed=true ,joined=true, lit=0 });
local sel = selection.match("."):grow();
des.terrain({ selection = sel, typ = "." });
local border = selection.rect(0,0, 78, 20);
des.terrain({ selection = border, typ = " " });
des.wallify();
end,
};
local hellno = math.random(1, #hells);

102
dat/luahelper Normal file
View File

@@ -0,0 +1,102 @@
# NetHack 3.7 luahelper $NHDT-Date: $ $NHDT-Branch: NetHack-3.7 $
#
# Makefile to assist developers in adding lines to various build
# Makefiles, or project files, as lua files are added or removed.
# NetHack may be freely redistributed. See license for details.
#
# Must be run while your current directory is the top of the
# NetHack source tree.
#
# make -f dat/luahelper [target]
#
# Target examples:
#
# Visual Studio nmake : make -f dat/luahelper devhelp-nmake >file.txt
#
# Visual Studio project: make -f dat/luahelper devhelp-vstudio >file.txt
#
# MSYS2 GNUmakefile : make -f dat/luahelper devhelp-msys2 >file.txt
#
# Xcode project.pbxproj: make -f dat/luahelper devhelp-xcode >file.txt
#
#
MAKEFLAGS += --no-print-directory
AWK=awk
luanames = asmodeus baalz bigrm-* castle fakewiz? juiblex knox medusa-? \
minend-? minefill minetn-? oracle orcus sanctum soko?-? tower? \
valley wizard? nhcore nhlib themerms astral air earth fire water \
hellfill tut-? ???-goal ???-fil? ???-loca ???-strt \
dungeon quest
alllua = $(wildcard $(addsuffix .lua,$(addprefix dat/, $(luanames))))
#
# generates lines to insert into
# sys/windows/Makefile.nmake
#
devhelp-nmake:
@echo "$(notdir $(alllua))" | \
$(AWK) '{for (i=1; i<=NF; ++i)printf "%s%s%s%s", \
i == 1? "LUA_FILES = " : "", \
"$$(DAT)", \
$$i, \
i % 3? " ": ((i == NF)? "\n" : " \\\n\t")} \
i % 3{print ""}'
@echo ""
#
# generates lines to insert into
# sys/windows/GNUmakefile
#
devhelp-msys2:
@echo "$(basename $(notdir $(alllua)))" | \
$(AWK) '{for (i=1; i<=NF; ++i)printf "%s%s%s", \
i == 1? "LUALIST = " : "", \
$$i, \
i % 5? " ": ((i == NF)? "\n" : " \\\n\t")} \
i % 5{print ""}'
@echo ""
xcodeextra = bogusmon cmdhelp data engrave epitaph help hh \
history keyhelp opthelp optmenu options oracles \
rumors tribute wizhelp
#
# generates lines to insert into
# sys/unix/NetHack.xcodeproj/project.pbxproj
#
devhelp-xcode:
@echo "\t\t\tinputPaths = ("
@echo "$(xcodeextra) $(notdir $(alllua))" | \
$(AWK) '{for (i=1; i<=NF; ++i)printf "%s%s%s%s%s", \
i == 1? "\t" : "", \
"\t\t\t\042$$(NH_DAT_DIR)/", \
$$i, \
"\042", \
i % 1? " ": ((i == NF)? "\n" : ",\n\t")} \
i % 1{print ""}'
@echo "\t\t\t);"
#
# generates lines to insert into
# sys/windows/vs/files.props
#
devhelp-vstudio:
@echo " <ItemGroup>"
@echo "$(notdir $(alllua))" | \
$(AWK) '{for (i=1; i<=NF; ++i)printf "%s%s%s%s%s", \
i == 1? " " : "", \
"<Luafiles Include = \042", \
$$i, \
"\042/>", \
i % 1? " ": ((i == NF)? "\n" : "\n ")} \
i % 1{print ""}'
@echo " </ItemGroup>"
all:
make -f dat/luahelper devhelp-nmake >./luahelp-nmake.txt
make -f dat/luahelper devhelp-msys2 >./luahelp-msys2.txt
make -f dat/luahelper devhelp-xcode >./luahelp-xcode.txt
make -f dat/luahelper devhelp-vstudio >./luahelp-vstudio.txt
# end

View File

@@ -132,7 +132,7 @@ des.monster("water nymph")
des.monster("water nymph")
for i=1,30 do
des.monster({ id = "raven", hostile = 1 })
des.monster({ id = "raven", peaceful = 0 })
end
--#medusa-3.lua

View File

@@ -40,7 +40,6 @@ mail enable the mail daemon [True]
mention_decor give feedback when walking across stairs, altars, [False]
fountains, and such even when not obscured by objects
mention_walls give feedback when walking against a wall [False]
menu_objsyms show object symbols in menus if it is selectable [False]
menu_overlay overlay menus on the screen and align to right [True]
menucolors enable MENUCOLOR pattern matching to highlight [False]
lines in object menus like inventory; might highlight with
@@ -190,6 +189,16 @@ menustyle user interface for selection of multiple objects: [Full]
only the first letter ('T','C','F','P') matters
(With Traditional, many actions allow pseudo-class 'm' to
request a menu for choosing items: one-shot Combination.)
menu_objsyms whether to include object class symbols in menus: [4]
0 - none -- don't add object symbols to menus;
1 - headers -- append object class symbol to menu header lines;
2 - entries -- show object glyphs (same as class symbol
for ASCII interfaces) on each menu entry line;
3 - both -- 1 and 2 combined;
4 - conditional -- as 2 but only if no headers are present;
5 - one-or-other -- 1 and 4 combined;
choices 0 and 1 should work with any interface; 2 through 5
are supported by tty and curses
msg_window behavior of ^P message recall for tty interface: [s]
single -- one message at a time
full -- full window with all saved top line messages

View File

@@ -102,6 +102,13 @@ local orcus1 = des.map({ halign = "right", valign = "center", map = [[
des.object()
des.object()
des.object()
-- An object that's worth most of a wish
-- (this is part of the compensation for the reduced wishes at the Castle)
if math.random(0, 1) == 1 then
des.object("magic marker")
else
des.object("magic lamp")
end
-- The resident nasty
des.monster("Orcus",33,15)
-- And its preferred companions

View File

@@ -28,6 +28,7 @@ All monsters are created evil, but some are more evil than others.
Always attack a floating eye from behind!
An elven cloak is always the height of fashion.
Any small object that is accidentally dropped will hide under a larger object.
Archeologists are very squishy, often found under boulders.
Archeologists find more bones piles.
Austin Powers says: My Mojo is back! Yeah, baby!
Balrogs do not appear above level 20.

View File

@@ -59,6 +59,8 @@ des.object("boulder", 09, 12);
--
des.object("boulder", 03, 14);
-- prevent monster generation over the (filled) holes
des.exclusion({ type = "monster-generation", region = { 08,01, 23,01 } });
-- Traps
des.trap("hole", 08, 01);
des.trap("hole", 09, 01);

View File

@@ -60,6 +60,8 @@ des.object("boulder",10,08);
des.object("boulder",12,09);
des.object("boulder",11,10);
-- prevent monster generation over the (filled) holes
des.exclusion({ type = "monster-generation", region = { 05,01, 22,01 } });
-- Traps
des.trap("hole",05,01)
des.trap("hole",06,01)

View File

@@ -46,6 +46,8 @@ des.object("boulder",03,09)
des.object("boulder",05,07)
des.object("boulder",06,06)
-- prevent monster generation over the (filled) holes
des.exclusion({ type = "monster-generation", region = { 07,09, 18,09 } });
-- Traps
des.trap("hole",08,09)
des.trap("hole",09,09)

View File

@@ -46,6 +46,8 @@ des.object("boulder",06,09)
des.object("boulder",05,10)
des.object("boulder",05,11)
-- prevent monster generation over the (filled) holes
des.exclusion({ type = "monster-generation", region = { 06,11, 18,11 } });
-- Traps
des.trap("hole",07,11)
des.trap("hole",08,11)

View File

@@ -52,6 +52,8 @@ des.object("boulder",09,09)
des.object("boulder",10,07)
des.object("boulder",10,10)
-- prevent monster generation over the (filled) holes
des.exclusion({ type = "monster-generation", region = { 11,10, 27,10 } });
-- Traps
des.trap("hole",12,10)
des.trap("hole",13,10)

View File

@@ -47,6 +47,8 @@ des.object("boulder",07,10)
des.object("boulder",10,10)
des.object("boulder",03,11)
-- prevent monster generation over the (filled) holes
des.exclusion({ type = "monster-generation", region = { 12,10, 24,10 } });
-- Traps
des.trap("hole",12,10)
des.trap("hole",13,10)

View File

@@ -72,6 +72,8 @@ des.object("boulder",09,09)
des.object("boulder",08,10)
des.object("boulder",10,10)
-- prevent monster generation over the (filled) pits
des.exclusion({ type = "monster-generation", region = { 01,06, 07,11 } });
-- Traps
des.trap("pit",03,06)
des.trap("pit",04,06)

View File

@@ -41,6 +41,9 @@ des.object("boulder",08,08)
des.object("boulder",09,08)
des.object("boulder",10,08)
-- prevent monster generation over the (filled) pits
des.exclusion({ type = "monster-generation", region = { 01,01, 01,09 } });
des.exclusion({ type = "monster-generation", region = { 01,08, 07,09 } });
-- Traps
des.trap("pit",01,02)
des.trap("pit",01,03)

File diff suppressed because it is too large Load Diff

View File

@@ -37,9 +37,14 @@ des.monster("V",niches[3])
-- gave them titles rather than (or perhaps in addition to) specific names
-- and we use those titles here. Marking them as 'waiting' forces them to
-- start in vampire form instead of vampshifted into bat/fog/wolf form.
des.monster({ id="Vampire Lady", niches[4], name="Madame", waiting=1 })
des.monster({ id="Vampire Lady", niches[5], name="Marquise", waiting=1 })
des.monster({ id="Vampire Lady", niches[6], name="Countess", waiting=1 })
local Vgenod = nh.is_genocided("vampire");
local Vnames = { nil, nil, nil };
if (not Vgenod) then
Vnames = { "Madame", "Marquise", "Countess" };
end
des.monster({ id="vampire lady", coord=niches[4], name=Vnames[1], waiting=1 })
des.monster({ id="vampire lady", coord=niches[5], name=Vnames[2], waiting=1 })
des.monster({ id="vampire lady", coord=niches[6], name=Vnames[3], waiting=1 })
-- The doors
des.door("closed",08,03)
des.door("closed",10,03)

View File

@@ -3665,7 +3665,7 @@ and needs to see in the dark. Strange but true.
%e passage
# p. 218
%passage 9
"He's bound to have done /something/," Noddy repeated.
"He's bound to have done /something/," Nobby repeated.
In this he was echoing the Patrician's view of crime and punishment. If
there was a crime, there should be punishment. If the specific criminal
@@ -6031,7 +6031,7 @@ was mostly unexplored, too.(1)
%e passage
# p. 219 (passage begins mid-sentence)
%passage 12
[...] Sam Vines had learned a lot from watching Lady Sybil. She didn't
[...] Sam Vimes had learned a lot from watching Lady Sybil. She didn't
mean to act like that, but she'd been born to it, into a class which had
always behaved this way: You went through the world as if there was
/no possibility/ that anyone would stop you or question you, and most of

View File

@@ -1,26 +1,53 @@
local tut_ctrl_key = nil;
local tut_alt_key = nil;
function tut_key(command)
local s = nh.eckey(command);
local m = s:match("^^([A-Z])$"); -- ^X is Ctrl-X
if (m ~= nil) then
tut_ctrl_key = m;
return "Ctrl-" .. m;
end
m = s:match("^M%-([A-Z])$"); -- M-X is Alt-X
if (m ~= nil) then
tut_alt_key = m;
return "Alt-" .. m;
end
return s;
end
function tut_key_help(x, y)
if (tut_ctrl_key ~= nil) then
des.engraving({ coord = { x,y }, type = "engrave", text = "Note: Outside the tutorial, Ctrl-key combinations are shown prefixed with a caret, like '^" .. tut_ctrl_key .. "'", degrade = false });
tut_ctrl_key = nil;
end
end
des.level_init({ style = "solidfill", fg = " " });
des.level_flags("mazelevel", "noflip",
"nomongen", "nodeathdrops", "noautosearch");
des.map([[
---------------------------------------------------------------------------
|-.--|.......|......|..S....|.F.......|.............|.....................|
|-.--|.......|......|..S....|.F.......|.............|.......|.............|
|.-..........|......|--|....|.F.....|.|S-------.....|.....................|
||.--|.......|..T......|....|.F.....|.|.......|.....|.....................|
||.|.|.......|......|-.|....|.F.....|.|.......|.....|.....................|
||.--|.......|..T......|....|.F.....|.|.......|.....|.......|.............|
||.|.|.......|......|-.|....|.F.....|.|.......|.....|--------.............|
||.|.|.......|......||.|-.-----------.-.......|-S----.....................|
|-+-S---------..---.||........................|...|.......................|
|......| |.-------------------.......|...|....--S----............|
|......| ###### |.........| |..S.......|...|....|.....|............|
|----.-| -+- # |.....---.|######+..|.......S...|....|.....|............|
|----+----.----+---.|.--|.|.|# ------------...|....|.....|............|
|----+----.----+---.|.--|.|.|# ------------...|....|.....F............|
|........|.|......|.|...F...|# ........|.....+...|....|.....|............|
|.P......-S|......|------.---# .........|.....|...|....-------............|
|..........|......+.|...|.|.S# ..--S-----.....|LLL|.......................|
|.W......---......|.|.|.|.|.|# ..|......|.....|LLL|.......................|
|....Z.L.S.F......|.|.|.|.---# |......+.....|...|.......................|
|........|--......|...|.....|####+......|.....|...+.......................|
|.P......-S|......|------.---# .........|.....|...|....-------........----|
|..........|......+.|...|.|.S# ..--S-----.....|LLL|..................|..| |
|.W......---......|.|.|.|.|.|# ..|......|.....|LLL|..................|..--|
|....Z.L.S.F......|.|.|.|.---# |......+.....|...|..................|..|.|
|........|--......|...|.....|####+......|.....|...+..................||...|
---------------------------------------------------------------------------
]]);
@@ -40,26 +67,30 @@ nh.parse_config("OPTIONS=mention_walls");
nh.parse_config("OPTIONS=mention_decor");
nh.parse_config("OPTIONS=lit_corridor");
local movekeys = nh.eckey("movewest") .. " " ..
nh.eckey("movesouth") .. " " ..
nh.eckey("movenorth") .. " " ..
nh.eckey("moveeast");
local movekeys = tut_key("movewest") .. " " ..
tut_key("movesouth") .. " " ..
tut_key("movenorth") .. " " ..
tut_key("moveeast");
local diagmovekeys = nh.eckey("movesouthwest") .. " " ..
nh.eckey("movenortheast") .. " " ..
nh.eckey("movesoutheast") .. " " ..
nh.eckey("movenorthwest");
local diagmovekeys = tut_key("movesouthwest") .. " " ..
tut_key("movenortheast") .. " " ..
tut_key("movesoutheast") .. " " ..
tut_key("movenorthwest");
des.engraving({ coord = { 9,3 }, type = "engrave", text = "Move around with " .. movekeys, degrade = false });
des.engraving({ coord = { 5,2 }, type = "engrave", text = "Move diagonally with " .. diagmovekeys, degrade = false });
if (u.role == "Knight") then
des.engraving({ coord = { 12,1 }, type = "engrave", text = "Knights can jump with '" .. tut_key("jump") .. "'", degrade = false });
end
--
des.engraving({ coord = { 2,4 }, type = "engrave", text = "Some actions may require multiple tries before succeeding", degrade = false });
des.engraving({ coord = { 2,5 }, type = "engrave", text = "Open the door by moving into it", degrade = false });
des.door({ coord = { 2,6 }, state = "closed" });
des.engraving({ coord = { 2,7 }, type = "engrave", text = "Close the door with '" .. nh.eckey("close") .. "'", degrade = false });
des.engraving({ coord = { 2,7 }, type = "engrave", text = "Close the door with '" .. tut_key("close") .. "'", degrade = false });
--
@@ -69,14 +100,20 @@ des.trap({ type = "magic portal", coord = { 4,4 }, seen = true });
--
des.engraving({ coord = { 5,9 }, type = "engrave", text = "This door is locked. Kick it with '" .. nh.eckey("kick") .. "'", degrade = false });
des.engraving({ coord = { 5,9 }, type = "engrave", text = "This door is locked. Kick it with '" .. tut_key("kick") .. "'", degrade = false });
des.door({ coord = { 5,10 }, state = "locked" });
des.engraving({ coord = { 5,12 }, type = "engrave", text = "Look around the map with '" .. nh.eckey("glance") .. "'", degrade = false });
-- by default, kick is the first command that can be a ctrl-key combo
tut_key_help(6, 8);
des.engraving({ coord = { 5,12 }, type = "engrave", text = "Look around the map with '" .. tut_key("glance") .. "', press ESC when you're done", degrade = false });
--
des.engraving({ coord = { 10,13 }, type = "engrave", text = "Use '" .. nh.eckey("search") .. "' to search for secret doors", degrade = false });
des.engraving({ coord = { 10,13 }, type = "engrave", text = "Use '" .. tut_key("search") .. "' to search for secret doors", degrade = false });
des.engraving({ coord = { 10,15 }, type = "engrave", text = "Wrong secret", degrade = false });
--
@@ -96,21 +133,24 @@ for i = 1, 4 do
coord = locs[i], victim = false });
end
des.engraving({ coord = { 15,15 }, type = "engrave", text = "Some traps can be disabled with '" .. tut_key("untrap") .. "'", degrade = false });
des.trap({ coord = { 15,16 }, type = "web", spider_on_web = false });
--
des.door({ coord = { 18,13 }, state = "closed" });
des.engraving({ coord = { 19,13 }, type = "engrave", text = "Pick up items with '" .. nh.eckey("pickup") .. "'", degrade = false });
des.engraving({ coord = { 19,13 }, type = "engrave", text = "Pick up items with '" .. tut_key("pickup") .. "'", degrade = false });
local armor = (u.role == "Monk") and "leather gloves" or "leather armor";
des.object({ id = armor, spe = 0, buc = "cursed", coord = { 19,14} });
des.engraving({ coord = { 19,15 }, type = "engrave", text = "Wear armor with '" .. nh.eckey("wear") .. "'", degrade = false });
des.engraving({ coord = { 19,15 }, type = "engrave", text = "Wear armor with '" .. tut_key("wear") .. "'", degrade = false });
des.object({ id = "dagger", spe = 0, buc = "not-cursed", coord = { 21,15} });
des.engraving({ coord = { 21,14 }, type = "engrave", text = "Wield weapons with '" .. nh.eckey("wield") .. "'", degrade = false });
des.engraving({ coord = { 21,14 }, type = "engrave", text = "Wield weapons with '" .. tut_key("wield") .. "'", degrade = false });
des.engraving({ coord = { 22,13 }, type = "engrave", text = "Hit monsters by walking into them.", degrade = false });
@@ -131,13 +171,13 @@ des.object({ id = "boulder", coord = {25,12} });
--
des.engraving({ coord = { 27,9 }, type = "engrave", text = "Take off armor with '" .. nh.eckey("takeoff") .. "'", degrade = false });
des.engraving({ coord = { 27,9 }, type = "engrave", text = "Take off armor with '" .. tut_key("takeoff") .. "'", degrade = false });
--
des.object({ class = "?", id = "remove curse", buc = "blessed", coord = {23,11} })
des.engraving({ coord = { 22,11 }, type = "engrave", text = "Some items have shuffled descriptions, different each game", degrade = false });
des.engraving({ coord = { 23,11 }, type = "engrave", text = "Pick up this scroll, read it with '" .. nh.eckey("read") .. "', and try to remove the armor again", degrade = false });
des.engraving({ coord = { 23,11 }, type = "engrave", text = "Pick up this scroll, read it with '" .. tut_key("read") .. "', and try to remove the armor again", degrade = false });
--
@@ -157,14 +197,14 @@ des.object({ coord = {14, 6}, id = "boulder" });
des.door({ coord = { 20,3 }, state = percent(50) and "open" or "closed" });
des.engraving({ coord = { 21,3 }, type = "engrave", text = "Avoid being burdened, it slows you down", degrade = false });
des.engraving({ coord = { 22,3 }, type = "engrave", text = "Drop items with '" .. nh.eckey("drop") .. "'", degrade = false });
des.engraving({ coord = { 22,3 }, type = "engrave", text = "Drop items with '" .. tut_key("drop") .. "'", degrade = false });
des.engraving({ coord = { 22,4 }, type = "engrave", text = "You can drop partial stacks by prefixing the item slot letter with a number", degrade = false });
--
des.monster({ id = "yellow mold", coord = { 26,2 }, waiting = true, countbirth = false });
des.engraving({ coord = { 25,5 }, type = "engrave", text = "Throw items with '" .. nh.eckey("throw") .. "'", degrade = false });
des.engraving({ coord = { 25,5 }, type = "engrave", text = "Throw items with '" .. tut_key("throw") .. "'", degrade = false });
des.trap({ type = "magic portal", coord = { 21,1 }, seen = true });
@@ -176,35 +216,36 @@ des.engraving({ coord = { 37,4 }, type = "engrave", text = "Missiles, such as ro
des.object({ coord = { 37,3 }, id = "sling", buc = "not-cursed", spe = 9 });
des.engraving({ coord = { 37,3 }, type = "engrave", text = "Wield the sling", degrade = false });
des.engraving({ coord = { 36,1 }, type = "engrave", text = "Use '" .. nh.eckey("fire") .. "' to fire missiles with the wielded launcher", degrade = false });
des.engraving({ coord = { 36,1 }, type = "engrave", text = "Use '" .. tut_key("fire") .. "' to fire missiles with the wielded launcher", degrade = false });
des.engraving({ coord = { 35,4 }, type = "engrave", text = "Firing launches items from your quiver; Use '" .. nh.eckey("quiver") .. "' to put items in it", degrade = false });
des.engraving({ coord = { 35,4 }, type = "engrave", text = "Firing launches items from your quiver; Use '" .. tut_key("quiver") .. "' to put items in it", degrade = false });
des.engraving({ coord = { 33,4 }, type = "engrave", text = "You can wait a turn with '" .. nh.eckey("wait") .. "'", degrade = false });
des.engraving({ coord = { 33,4 }, type = "engrave", text = "You can wait a turn with '" .. tut_key("wait") .. "'", degrade = false });
--
des.door({ coord = { 38,6 }, state = "closed" });
des.engraving({ coord = { 39,6 }, type = "engrave", text = "You loot containers with '" .. nh.eckey("loot") .. "'", degrade = false });
des.engraving({ coord = { 39,6 }, type = "engrave", text = "You loot containers with '" .. tut_key("loot") .. "'", degrade = false });
des.object({ coord = { 42,6 }, id = "large box", broken = true,
des.object({ coord = { 41,6 }, id = "large box", broken = true, trapped = false,
contents = function(obj)
des.object({ id = "secret door detection", class = "/", spe = 30 }); end
});
des.engraving({ coord = { 42,6 }, type = "engrave", text = "Containers can also be emptied with '" .. tut_key("tip") .. "'", degrade = false });
des.engraving({ coord = { 45,6 }, type = "engrave", text = "Magic wands are used with '" .. nh.eckey("zap") .. "'", degrade = false });
des.engraving({ coord = { 45,6 }, type = "engrave", text = "Magic wands are used with '" .. tut_key("zap") .. "'", degrade = false });
--
des.door({ coord = { 35,9 }, state = "nodoor" });
des.engraving({ coord = { 34,9 }, type = "engrave", text = "You can run by prefixing a movement key with '" .. nh.eckey("run") .. "'", degrade = false });
des.engraving({ coord = { 34,9 }, type = "engrave", text = "You can run by prefixing a movement key with '" .. tut_key("run") .. "'", degrade = false });
--
des.door({ coord = { 33,16 }, state = "nodoor" });
des.engraving({ coord = { 35,15 }, type = "engrave", text = "Travel across the level with '" .. nh.eckey("travel") .. "'", degrade = false });
des.engraving({ coord = { 35,15 }, type = "engrave", text = "Travel across the level with '" .. tut_key("travel") .. "'", degrade = false });
--
@@ -212,23 +253,22 @@ des.trap({ type = "magic portal", coord = { 27,14 }, seen = true });
--
des.engraving({ coord = { 48,1 }, type = "burn", text = "Use '" .. nh.eckey("eat") .. "' to eat edible things", degrade = false });
des.engraving({ coord = { 48,1 }, type = "burn", text = "Use '" .. tut_key("eat") .. "' to eat edible things", degrade = false });
des.object({ coord = { 50,3 }, id = "apple", buc = "not-cursed" });
des.object({ coord = { 50,3 }, id = "candy bar", buc = "not-cursed" });
local otmp = des.object({ coord = { 50,3 }, id = "corpse", montype = "newt", buc = "not-cursed" });
otmp:stop_timer("rot-corpse");
des.object({ coord = { 50,3 }, id = "corpse", montype = "lichen", buc = "not-cursed" });
--
des.door({ coord = { 46,11 }, state = "closed" });
des.engraving({ coord = { 43,11 }, type = "burn", text = "Use '" .. nh.eckey("twoweapon") .. "' to use two weapons at once", degrade = false });
des.engraving({ coord = { 43,11 }, type = "burn", text = "Use '" .. tut_key("twoweapon") .. "' to use two weapons at once", degrade = false });
des.object({ coord = { 43,13 }, id = "knife", buc = "uncursed" });
des.object({ coord = { 43,14 }, id = "dagger", buc = "blessed" });
des.engraving({ coord = { 43,16 }, type = "burn", text = "Swap weapons quickly with '" .. nh.eckey("swap") .. "'", degrade = false });
des.engraving({ coord = { 43,16 }, type = "burn", text = "Swap weapons quickly with '" .. tut_key("swap") .. "'", degrade = false });
des.door({ coord = { 40,15 }, state = "random" });
@@ -236,24 +276,60 @@ des.door({ coord = { 40,15 }, state = "random" });
des.object({ coord = { 48,7 }, id = "ring of levitation", buc = "not-cursed" });
des.engraving({ coord = { 48,10 }, type = "burn", text = "Put on accessories with '" .. nh.eckey("puton") .. "'", degrade = false });
des.engraving({ coord = { 48,10 }, type = "burn", text = "Put on accessories with '" .. tut_key("puton") .. "'", degrade = false });
des.engraving({ coord = { 48,16 }, type = "burn", text = "Remove accessories with '" .. nh.eckey("remove") .. "'", degrade = false });
des.engraving({ coord = { 48,16 }, type = "burn", text = "Remove accessories with '" .. tut_key("remove") .. "'", degrade = false });
des.door({ coord = { 50,16 }, state = "closed" });
--
des.engraving({ coord = { 58,9 }, type = "burn", text = "Use '" .. nh.eckey("down") .. "' to go down the stairs", degrade = false });
des.engraving({ coord = { 58,9 }, type = "burn", text = "Use '" .. tut_key("down") .. "' to go down the stairs", degrade = false });
des.stair({ dir = "down", coord = { 58,10 } });
--
-- one more ctrl-key help, if needed
tut_key_help(64, 4);
des.engraving({ coord = { 65,3 }, type = "burn", text = "UNDER CONSTRUCTION", degrade = false });
des.trap({ type = "magic portal", coord = { 66,2 }, seen = true });
--
-- squeezing through small gaps
des.engraving({ coord = { 69,12 }, type = "burn", text = "Can't get through? You're carrying too much.", degrade = false });
-- try to squeeze over boulders, find a trap door
des.object({ id = "boulder", coord = {71,16} });
des.object({ id = "boulder", coord = {72,16} });
des.object({ id = "boulder", coord = {73,16} });
des.trap({ type = "trap door", coord = { 73,15 } });
--
des.engraving({ coord = { 60,2 }, type = "engrave", text = "Spellcasting", degrade = false });
if (u.uenmax < 5) then
-- TODO: make sure hero has enough Pw to cast the spell (5 pw) instead?
-- TODO: ensure the first cast of this spell succeeds?
des.engraving({ coord = { 59,2 }, type = "engrave", text = "Unfortunately you don't have enough energy to cast spells.", degrade = false });
end
des.engraving({ coord = { 57,2 }, type = "engrave", text = "Pick up the spellbook with '" .. tut_key("pickup") .. "'", degrade = false });
des.object({ coord = { 57,2 }, id = "spellbook of light", buc = "blessed" });
des.engraving({ coord = { 55,2 }, type = "engrave", text = "Read the spellbook with '" .. tut_key("read") .. "'", degrade = false });
des.engraving({ coord = { 53,2 }, type = "engrave", text = "Use '" .. tut_key("cast") .. "' to cast a spell", degrade = false });
des.region(selection.area(53,01, 59, 3), "unlit");
--
des.engraving({ coord = { 72,2 }, type = "engrave", text = "You \"quaff\" potions with '" .. tut_key("quaff") .. "'", degrade = false });
des.object({ coord = { 72,2 }, id = "potion of object detection", buc = "blessed" });
----------------
-- entering and leaving tutorial _branch_ now handled by core

7
doc/.gitattributes vendored
View File

@@ -3,7 +3,6 @@
*.6 NHSUBST
*.7 NHSUBST
fixes* NHSUBST
*.txt NHSUBST
config.nh NHSUBST
Guidebook.txt NH_header=no
tmac.n NH_header=no
@@ -12,5 +11,7 @@ fixes* NH_header=no
*.txt NH_header=no
* NH_filestag=(file%s_for_all_versions)
Guidebook.tex NH_DATESUB
Guidebook.mn NH_DATESUB
*.6 NH_DATESUB
Guidebook.mn NH_DATESUB NHAUTODOCS
*.6 NH_DATESUB NHAUTODOCS
*.7 NH_DATESUB NHAUTODOCS
fixes* -NHAUTODOCS

8
doc/.gitignore vendored
View File

@@ -14,4 +14,10 @@ Guidebook.pdf
Guidebook.ps
Guidebook.dated.*
*.synctex.*
# files that might appear from "make fetch-docs"
dlb.pdf
makedefs.pdf
mn.pdf
mnh.pdf
nethack.pdf
recover.pdf

View File

@@ -1,4 +1,4 @@
.\" $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.574 $ $NHDT-Date: 1711040379 2024/03/21 16:59:39 $
.\" $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.598 $ $NHDT-Date: 1745139202 2025/04/20 00:53:22 $
.\"
.\" This is an excerpt from the 'roff' man page from the 'groff' package.
.\"+--
@@ -46,8 +46,8 @@
.ds vr NetHack 3.7.0
.ds f0 \*(vr
.ds f1 \" empty
.\"DO NOT REMOVE NH_DATESUB .ds f2 DATE(%B %-d, %Y)
.ds f2 September 13, 2024
.\"DO NOT REMOVE NH_DATESUB .ds f2 Date(%B %-d, %Y)
.ds f2 May 1, 2025
.
.\" A note on some special characters:
.\" \(lq = left double quote
@@ -2920,8 +2920,16 @@ magic spells on them).
.pg
One of the most useful of these is the \fIscroll of identify\fP, which
can be used to determine what another object is, whether it is cursed or
blessed, and how many uses it has left. Some objects of subtle
enchantment are difficult to identify without these.
blessed, and how many uses it has left.
Some objects of subtle enchantment are difficult to identify without these.
.pg
A scroll whose label is known can be read even when the hero is blind.
If a scroll has been discovered, it will be listed in inventory by type
rather than by label, but the label is known in that situtaion even though
it isn't shown.
.pg
Many scrolls produce a different effect from usual if they are blessed or
cursed, or read while the hero is confused.
.pg
A mail daemon may run up and deliver mail to you as a
\fIscroll of mail\fP (on versions compiled with this feature).
@@ -3780,7 +3788,8 @@ See
.op role
for a description of how to use negation to exclude choices.
.lp ""
Default is random.
If \f(CRalign\fP is not specified, there is no default value;
player will be prompted unless role and/or race forces a choice for alignment.
Cannot be set with the \(oq\f(CRO\fP\(cq command.
Persistent.
.lp autodescribe
@@ -4006,7 +4015,8 @@ See
.op role
for a description of how to use negation to exclude choices.
.lp ""
Default is random.
If \f(CRgender\fP is not specified, there is no default value;
player will be prompted unless role and/or race forces a choice for gender.
Cannot be set with the \(oq\f(CRO\fP\(cq command.
Persistent.
.lp "goldX "
@@ -4161,8 +4171,38 @@ Default \(oq|\(cq.
Key to go to the next menu page.
Default \(oq>\(cq.
.lp menu_objsyms
Show object symbols in menu headings in menus where
the object symbols act as menu accelerators (default off).
." [originally menu_objsyms was a boolean]
." Show object symbols in menu headings in menus where
." the object symbols act as menu accelerators (default off).
Inventory and other object menus are normally separated by object class
(weapons, armor, and so forth), with a menu header line at the beginning
of each group.
You can have menus add the display symbol for the class of objects for
each header line.
You can also add the display symbol for the individual item in each menu
entry.
For a tiles map, that would be a small rendition of an object's tile.
For a text map, it is the same character as is used for the object's
class, which would be most useful when there are no headers separating
objects among classes.
Possible values are
.PS "5\ -\ One-or-other"
.PL "0\ -\ None"
no symbols for either header lines or menu entries;
.PL "1\ -\ Headers"
show symbols on header lines but not entries;
.PL "2\ -\ Entries"
show symbols on menu entry lines but not headers;
.PL "3\ -\ Both"
show symbols on headers and entries;
.PL "4\ -\ Conditional"
only show symbols for entries if there are no headers;
.PL "5\ -\ One-or-other"
show symbols on headers, or on entries if no headers.
.PE
Supported by tty and curses.
When setting the value, it can be specified by digit or keyword.
The default value is \f(CRConditional\fP (4).
.lp menu_overlay
Do not clear the screen before drawing menus, and align
menus to the right edge of the screen. Only for the tty port.
@@ -4246,6 +4286,11 @@ the role (that is, by suffixing one of
If
.op "\-@"
is used for the role, then a random one will be automatically chosen.
.lp ""
On some systems, the default is the player's user name;
on others, there is no default and the player will be prompted.
The former can made to behave like the latter by specifying a generic name
such as ``player''.
Cannot be set with the \(oq\f(CRO\fP\(cq command.
.lp "news "
Read the NetHack news file, if present (default on).
@@ -4506,7 +4551,8 @@ See
.op role
for a description of how to use negation to exclude choices.
.lp ""
Default is random.
If \f(CRrace\fP is not specified, there is no default value;
player will be prompted unless role forces a choice for race.
Cannot be set with the \(oq\f(CRO\fP\(cq command.
Persistent.
.lp rest_on_space
@@ -4542,7 +4588,8 @@ option if they're all negations.
.\" Only one positive value is allowed, and if present, it overrides any
.\" negations.
.lp ""
Default is \f(CRrandom\fP.
If \f(CRrole\fP is not specified, there is no default value;
player will be prompted.
Cannot be set with the \(oq\f(CRO\fP\(cq command.
Persistent.
.lp roguesymset
@@ -6064,23 +6111,13 @@ escape command (!). The syntax is the same as WIZARDS.
EXPLORERS\ =\ A list of users who are allowed to use the explore mode.
The syntax is the same as WIZARDS.
.lp
MSGHANDLER\ =\ A path and filename of executable. Whenever a message-window
message is shown, NetHack runs this program. The program will get
the message as the only parameter.
.lp
MAXPLAYERS\ =\ Limit the maximum number of games that can be running
at the same time.
.lp
SAVEFORMAT\ =\ A list of up to two save file formats separated by space.
The first format in the list will written as well as read. The second format
will be read only if no save file in the first format exists.
Valid choices are \(lqhistorical\(rq for binary writing of entire structs,
\(lqlendian\(rq for binary writing of each field in little-endian order,
\(lqascii\(rq for writing the save file content in ascii text.
.lp
BONESFORMAT\ =\ A list of up to two bones file formats separated by space.
The first format in the list will written as well as read. The second format
will be read only if no bones files in the first format exist.
Valid choices are \(lqhistorical\(rq for binary writing of entire structs,
\(lqlendian\(rq for binary writing of each field in little-endian order,
\(lqascii\(rq for writing the bones file content in ascii text.
.lp
SUPPORT\ =\ A string explaining how to get local support (no default value).
.lp
RECOVER\ =\ A string explaining how to recover a game on this system

View File

@@ -1,5 +1,5 @@
\documentstyle[titlepage,longtable]{article}
% NetHack 3.7 Guidebook.tex $NHDT-Date: 1711040379 2024/03/21 16:59:39 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.562 $ */
% NetHack 3.7 Guidebook.tex $NHDT-Date: 1745139202 2025/04/20 00:53:22 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.579 $ */
%+% we're still limping along in LaTeX 2.09 compatibility mode
%-%\documentclass{article}
%-%\usepackage{hyperref} % before longtable
@@ -47,8 +47,8 @@
%.au
\author{Original version - Eric S. Raymond\\
(Edited and expanded for 3.7.0 by Mike Stephenson and others)}
%DO NOT REMOVE NH_DATESUB \date{DATE(%B %-d, %Y)}
\date{September 13, 2024}
%DO NOT REMOVE NH_DATESUB \date{Date(%B %-d, %Y)}
\date{May 1, 2025}
\maketitle
@@ -3158,8 +3158,18 @@ magic spells on them).
One of the most useful of these is the %
{\it scroll of identify}, which
can be used to determine what another object is, whether it is cursed or
blessed, and how many uses it has left. Some objects of subtle
enchantment are difficult to identify without these.
blessed, and how many uses it has left.
Some objects of subtle enchantment are difficult to identify without these.
%.pg
A scroll whose label is known can be read even when the hero is blind.
If a scroll has been discovered, it will be listed in inventory by type
rather than by label, but the label is known in that situtaion even though
it isn't shown.
%.pg
Many scrolls produce a different effect from usual if they are blessed or
cursed, or read while the hero is confused.
%.pg
A mail daemon may run up and deliver mail to you as a %
@@ -4135,7 +4145,8 @@ See {\it role\/}
for a description of how to use negation to exclude choices.
%.lp ""
\\
Default is random.
If {\tt align} is not specified, there is no default value;
player will be prompted unless role and/or race forces a choice for alignment.
Cannot be set with the `{\tt O}' command. Persistent.
%.lp
\item[\ib{autodescribe}]
@@ -4390,7 +4401,8 @@ See {\it role\/}
for a description of how to use negation to exclude choices.
%.lp ""
\\
Default is random.
If {\tt gender} is not specified, there is no default value;
player will be prompted unless role and/or race forces a choice for gender.
Cannot be set with the `{\tt O}' command. Persistent.
%.lp
\item[\ib{goldX}]
@@ -4566,8 +4578,40 @@ Key to go to the next menu page.
Implemented by the Amiga, Gem and tty ports.
Default `\verb+>+'.
\item[\ib{menu\verb+_+objsyms}]
Show object symbols in menu headings in menus where
the object symbols act as menu accelerators (default off).
% [originally menu_objsyms was a boolean]
% Show object symbols in menu headings in menus where
% the object symbols act as menu accelerators (default off).
Inventory and other object menus are normally separated by object class
(weapons, armor, and so forth), with a menu header line at the beginning
of each group.
You can have menus add the display symbol for the class of objects for
each header line.
You can also add the display symbol for the individual item in each menu
entry.
For a tiles map, that would be a small rendition of an object's tile.
For a text map, it is the same character as is used for the object's
class, which would be most useful when there are no headers separating
objects among classes.
% FIXME! -- three column table may be simpler than mashing first two together
% Possible values are
% .PS "5\ -\ One-or-other"
% .PL "0\ -\ None"
% no symbols for either header lines or menu entries;
% .PL "1\ -\ Headers"
% show symbols on header lines but not entries;
% .PL "2\ -\ Entries"
% show symbols on menu entry lines but not headers;
% .PL "3\ -\ Both"
% show symbols on headers and entries;
% .PL "4\ -\ Conditional"
% only show symbols for entries if there are no headers;
% .PL "5\ -\ One-or-other"
% show symbols on headers, or on entries if no headers.
% .PE
Supported by tty and curses.
When setting the value, it can be specified by digit or keyword.
The default value is {\tt Conditional} (4).
\item[\ib{menu\verb+_+overlay}]
Do not clear the screen before drawing menus, and align
menus to the right edge of the screen. Only for the tty port.
@@ -4666,6 +4710,12 @@ the role (that is, by suffixing one of
``{\tt -A -B -C -H -K -M -P -Ra -Ro -S -T -V -W}'').
If ``{\tt -@}'' is used for the role, then a random one will be
automatically chosen.
%.lp
\\
On some systems, the default is the player's user name;
on others, there is no default and the player will be prompted.
The former can made to behave like the latter by specifying a generic name
such as ``player''.
Cannot be set with the `{\tt O}' command.
%.lp
\item[\ib{news}]
@@ -4948,7 +4998,9 @@ See {\it role\/}
for a description of how to use negation to exclude choices.
%.lp ""
\\
Default is random.
If {\tt race} is not specified, there is no default value;
player will be prompted unless role forces a choice for race.
unless role forces a choice for race.
Cannot be set with the `{\tt O}' command. Persistent.
%.lp
\item[\ib{rest\verb+_+on\verb+_+space}]
@@ -4983,7 +5035,8 @@ option if they're all negations.
%.\" negations.
%.lp ""
\\
Default is random.
If {\tt role} is not specified, there is no default value;
player will be prompted.
Cannot be set with the `{\tt O}' command. Persistent.
%.lp
\item[\ib{roguesymset}]
@@ -5503,6 +5556,10 @@ Use bold black instead of blue for black glyphs (TTY only).
\item[\ib{use\verb+_+inverse}]
If {\it NetHack\/} can, it should display inverse when the game specifies it.
%.lp
\item[\ib{use\verb+_+menu\verb+_+glyphs}]
If {\it NetHack\/} can, it should display glyphs next to objects in the
inventory.
%.lp
\item[\ib{vary\verb+_+msgcount}]
If {\it NetHack\/} can, it should display this number of messages at a time
in the message window.
@@ -6703,25 +6760,14 @@ The syntax is the same as WIZARDS.
A list of users who are allowed to use the explore mode.
The syntax is the same as WIZARDS.
%.lp
\item[\ib{MSGHANDLER}]
A path and filename of executable. Whenever a message-window
message is shown, NetHack runs this program. The program will get
the message as the only parameter.
%.lp
\item[\ib{MAXPLAYERS}]
Limit the maximum number of games that can be running at the same time.
%.lp
\item[\ib{SAVEFORMAT}]
A list of up to two save file formats separated by space.
The first format in the list will written as well as read. The second format
will be read only if no save file in the first format exists.
Valid choices are ``{\tt historical}'' for binary writing of entire structs,
``{\tt lendian}'' for binary writing of each field in little-endian order,
``{\tt ascii}'' for writing the save file content in ascii text.
%.lp
\item[\ib{BONESFORMAT}]
A list of up to two bones file formats separated by space.
The first format in the list will written as well as read. The second
format will be read only if no bones files in the first format exist.
Valid choices are ``{\tt historical}'' for binary writing of entire structs,
``{\tt lendian}'' for binary writing of each field in little-endian order,
``{\tt ascii}'' for writing the bones file content in ascii text.
%.lp
\item[\ib{SUPPORT}]
A string explaining how to get local support (no default value).
%.lp

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,10 @@
# NetHack 3.7 config.nh $NHDT-Date: 1596498144 2020/08/03 23:42:24 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.4 $
# NetHack 3.7 config.nh $NHDT-Date: 1745978702 2025/04/29 18:05:02 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.10 $
# Copyright (c) 2016 by Pasi Kallinen
# NetHack may be freely redistributed. See license for details.
# Sample config file for NetHack 3.7.0
#
# Sample run-time configuration file for NetHack 3.7.0
# usually named ".nethackrc" (note leading dot; location
# depends upon the type of system nethack is running on).
#
# A '#' at the beginning of a line means the rest of the line is a comment.
#
@@ -177,9 +180,17 @@
# Default is 'inverse'
#OPTIONS=menu_headings:inverse
# Show object symbols in menus in the item class lines where that object symbol
# acts as an accelerator key to select items of that class.
#OPTIONS=menu_objsyms
# Control of displaying object symbols in menus for picking objects:
# show symbols in individual menu entries only if there are no class separators
#OPTIONS=menu_objsyms:4
# show symbols on object class separator lines and also in individual entries
#OPTIONS=menu_objsyms:3
# show symbols in individual entries but not on class separators
#OPTIONS=menu_objsyms:2
# show object symbols on class separators but not in individual entries
#OPTIONS=menu_objsyms:1
# don't show symbols on class separators or in individual menu entries
#OPTIONS=menu_objsyms:0
# Do not clear the screen before drawing menus, and align menus to right
#OPTIONS=menu_overlay
@@ -487,7 +498,7 @@
# Show all unholy water in red
#MENUCOLOR=" unholy " = red
# Show all cursed worn items in orange and underlined
#MENUCOLOR=" cursed .* (being worn)" = orange&underline
#MENUCOLOR=" cursed .* \(being worn\)" = orange&underline
# Use the IBM character set rather than just plain ascii characters

180
doc/dlb.6
View File

@@ -1,40 +1,73 @@
.\" $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.12 $ $NHDT-Date: 1693253316 2023/08/28 20:08:36 $
.\"DO NOT REMOVE NH_DATESUB .TH DLB 6 "DATE(%-d %B %Y)" NETHACK
.TH DLB 6 "8 February 2022" NETHACK
.\"DO NOT REMOVE NH_DATESUB .ds Nd DATE(%Y)
.ds Nd 2022
.\" $NHDT-Branch: master $:$NHDT-Revision: 1.14 $ $NHDT-Date: 1735103831 2024/12/25 00:17:11 $
.\"DO NOT REMOVE NH_DATESUB .TH DLB 6 "Date(%-d %B %Y)" Project(uc)
.TH DLB 6 "25 December 2024" NETHACK
.\"DO NOT REMOVE NH_DATESUB .ds Nd Date(%Y)
.ds Nd 2024
.de NB
.ds Nb \\$2
..
.de NR
.ds Nr \\$2
..
.NB $NHDT-Branch: NetHack-3.7 $
.NR $NHDT-Revision: 1.12 $
.NB $NHDT-Branch: keni-gitset $
.NR $NHDT-Revision: 1.13 $
.\" groff and AT&T-descended troffs use different hyphenation patterns.
.\" Don't hyphenate the last word on a page or column, or
.\" before/after last/first 2 characters of a word.
.ie \n(.g .hy 12
.el .hy 14
.ds Na Kenneth Lorber
.SH NAME
dlb \- NetHack data librarian
.SH SYNOPSIS
.B dlb
{
.B xct
}
[
.B vfIC
]
arguments...
[
.B files...
]
.SH DESCRIPTION
.\" We'd use `RB` with 7 arguments, but Unix troff man(7) has a limit of
.\" 6 arguments to its macros.
{\c
.BR c | t | x\c
}\c
.RB [ v ]\c
.RB [ C
.IR directory ]
.RI [ file ]
\&.\|.\|.
.PP
.B dlb
{\c
.BR c | t | x\c
}\c
.RB [ v ]\c
.B I
.IR list-file
.PP
.B dlb
{\c
.BR c | t | x\c
}\c
.RB [ v ]\c
.RB [ f
.IR archive-file-name ]
.RI [ file ]
\&.\|.\|.
.SH DESCRIPTION
.I Dlb
is a file archiving tool in the spirit (and tradition) of tar for
NetHack version 3.1 and higher. It is used to maintain the
archive files from which NetHack reads special level files and other
read-only information. Note that like tar the command and option
specifiers are specified as a continuous string and are followed
by any arguments required in the same order as the option specifiers.
is a file archiving tool in the spirit (and tradition) of
.IR tar (1)
for
.IR nethack (6)
version 3.1 and higher.
It is used to maintain the
archive files from which the game reads special level files and other
read-only information.
Note that like
.IR tar ,
the letters specifying the operation and options
are expressed as a continuous string.
Unlike
.IR tar ,
.I dlb
is configured with a default set of file names to process.
.ig
.PP
^?ALLDOCS
This facility is optional and may be excluded during NetHack
@@ -48,61 +81,76 @@ This facility is optional and was excluded from this NetHack
configuration.
^.
^.
.SH COMMANDS
The
.B x
command causes
.I dlb
to extract the contents of the archive into the current directory.
.PP
The
..
.SS Operations
.B c
command causes
causes
.I dlb
to create a new archive from files in the current directory.
.PP
The
.B t
command lists the files in the archive.
.SH OPTIONS AND ARGUMENTS
.DT
.ta \w'f archive\ \ \ 'u
v verbose output
.br
.sp 1
f archive specify the archive. Default if f not specified is
LIBFILE (usually the nhdat file in the playground).
.br
.sp 1
I lfile specify the file containing the list of files to
put in to or extract from the archive if no files are listed
on the command line. Default for archive creation if no files
are listed is LIBLISTFILE.
.br
.sp 1
C dir change directory. Changes directory before trying to
read any files (including the archive and the lfile).
.br
lists the files in the archive.
.PP
.B x
causes
.I dlb
to extract the contents of the archive into the current directory.
.SH OPTIONS
.TP 13n \" "I list-file" + 2n
.BI "C " dir
Change directory to
.I dir
before trying to
read any files.
.TP
.BI "f " archive
Read from or write to
.I archive
instead of LIBFILE
(usually the
.I nhdat
file in the playground).
.TP
.BI "I " list-file
Read from
.I list-file
the names of files to emplace within or extract from the archive.
The default for archive creation is LIBLISTFILE.
.TP
.B v
Operate verbosely.
.SH EXAMPLES
Create the default archive from the default file list:
.br
dlb c
.sp 1
List the contents of the archive 'foo':
.br
dlb tf foo
.SH AUTHOR
.RS
.EX
dlb c
.EE
.RE
.PP
List the contents of the archive
.IR foo :
.RS
.EX
dlb tf foo
.EE
.RE
.SH AUTHOR
Kenneth Lorber
.SH "SEE ALSO"
.PP
nethack(6), tar(1)
.IR nethack (6),
.IR tar (1)
.SH BUGS
.PP
Not a good tar emulation; - does not mean stdin or stdout.
.IP \(bu 2n
Not a good
.I tar
emulation;
.B -
does not mean stdin or stdout.
.IP \(bu
Should include an optional compression facility.
.IP \(bu
Not all read-only files for NetHack can be read out of an archive;
examining the source is the only way to know which files can be.
examining the source is the only way to know which files can be.
.SH COPYRIGHT
This file is Copyright (C) \*(Na, \*(Nd for version \*(Nb:\*(Nr.
NetHack may be freely redistributed. See license for details.

View File

@@ -1,4 +1,4 @@
DLB(6) DLB(6)
DLB(6) Games Manual DLB(6)
@@ -61,10 +61,10 @@ BUGS
way to know which files can be.
COPYRIGHT
This file is Copyright (C) Kenneth Lorber, 2022 for version
NetHack-3.7:1.12. NetHack may be freely redistributed. See license
for details.
This file is Copyright (C) Kenneth Lorber, 2024 for version keni-git-
set:1.13. NetHack may be freely redistributed. See license for
details.
NETHACK 8 February 2022 DLB(6)
NETHACK 25 December 2024 DLB(6)

View File

@@ -1,4 +1,4 @@
NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1484 $ $NHDT-Date: 1726862062 2024/09/20 19:54:22 $
NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1535 $ $NHDT-Date: 1740629713 2025/02/26 20:15:13 $
General Fixes and Modified Features
-----------------------------------
@@ -121,7 +121,8 @@ tribute (Discworld snippets) typos, in book order rather than fix order:
quote, passage #6 first footnote, insert omitted "be", passage #7
last paragraph, "to" -> "be"
Men at Arms passage #1, italicize /for/, passage #2, insert omitted
word "had": 'it was /fate/ that _had_ let Edward'
word "had": 'it was /fate/ that _had_ let Edward', #9, fix name typo
"Noddy" -> "Nobby"
Interesting Times passage #1, italicize several words
Feet of Clay passage #1, second "does not need" -> "doesn't even need"
Hogfather passage #7 missing initial double quote for "Oh, just ...",
@@ -131,7 +132,8 @@ tribute (Discworld snippets) typos, in book order rather than fix order:
missing opening single quote on second sentence of Lord Downey's
line, passage #11 both in footnote: "genious" -> "genius",
"was, oddly enough, was one [...]" -> "was, oddly enough, one [...]"
The Fifth Elephant #1, italicize /always/, #9, "dublet" -> "doublet"
The Fifth Elephant #1, italicize /always/, #9, "dublet" -> "doublet",
#12, fix name typo, "Vines" -> "Vimes"
The Truth #1, italicize several words
Thief of Time #2, "gold starts" -> "gold stars"
A Hat Full of Sky passage #9 "though" -> "thought"
@@ -959,9 +961,11 @@ a hero on the quest home level who runs or travels past the quest leader and
gets tossed out of the quest for some reason would keep running on the
far side of the quest portal
allow rush/run over water if wearing discovered water walking boots
putting on water walking boots while underwater (maybe via magical breathing)
and rising to surface wasn't causing the boots to become discovered
flying pets wouldn't target underwater food but if they happened to fly over
such food they could and would eat it
praying on an altar with pet corpse on it can revive the pet
praying on an altar with pet corpse or statue on it can revive the pet
applying a cursed oil lamp can make your hands slippery
valkyries start with a spear instead of a long sword
grid bugs don't have hands
@@ -987,7 +991,7 @@ bigroom variant 3 may have some walls replaced with other terrain
bigroom variant 4 may have two large squares of terrain in the middle
bigroom variant 5 may have patches of ice or clouds
some large monsters can knock back smaller monsters with a hit
change Demonbane to a mace, make it the first sac gift for priests,
change Demonbane to a silver mace, make it the first sac gift for priests,
and give it an invoke ability to banish demons
wielding Giantslayer prevents knockback from larger monsters; likewise for
carried loadstone(s)
@@ -1237,7 +1241,7 @@ when a werecreature in human form attacked hero, it could transform to critter
status highlighting for hit points didn't work as intended for up or down HP
changes; 'up' rule was used for both, 'down' rule was ignored
unhide an unseen water monster using a polymorph trap on land
allow defining random-teleport exclusion zones in lua
allow defining random-teleport or monster-generation exclusion zones in lua
if Magicbane cancelled a shapeshifter, forcing it to 'unshift', subsequent
messages continued to refer to the shifted form
a pet that was poison resistant but not stoning resistant would eat Medusa's
@@ -1473,6 +1477,57 @@ interactively setting a status highlight for hunger with 'O' and choosing
use C++ regex processing but not for tty+posixregex
a pet with the hides-under attribute could "move reluctantly over" a cursed
object and then hide under it
prevent monster generation in the sokoban trap hallway
change MSGHANDLER from compile-time to sysconf option
allow changing extended command autocompletions via #optionsfull
if eating a tin's contents caused the hero to choke to death or turn to stone,
resulting bones would contain the tin still intact
when hero who is poly'd into metallivore form eats a tin, bypass "smells like
<monster>" feedback and the "Eat it?" prompt; just eat the contents
along with the tin without asking
digging in ice was handled inconsistently, particularly if done at the span
spot in front of closed drawbridge
angry god may remove an intrinsic
gelatinous cubes eat organic objects inside them
pets with reflection were unwilling to attack floating eyes
artifact gifts are rebalanced (easier to obtain; higher-value sacrifices are
needed for higher-value artifacts; lower-value artifacts are usually
gifted enchanted; unaligned artifacts are possible but rare even on
the first gift; artifacts you can't use well are less likely)
luck gains from sacrificing are limited by the value of the sacrifice
failed #untrap could move hero diagonally into or out of an open doorway
remember box is trapped after finding the trap
when you hear a monster incant a scroll, ensure that the 'I' invisible
monster indicator doesn't trump telepathy briefly
proceed with showpaths option even if the sysconf file is missing
angry shopkeeper was not charging for thrown items
avoid "You fall down a deep shaft!" if deliberately flying down
since introduction in 3.1.0, the definition for Mitre of Holiness has specified
that carrying it provides fire resistance, but that had never been
implemented; wearing it didn't confer fire resistance either--there is
no 'defends' capability for it since carrying should encompass that
if a tree and a boulder or statue were at the same location, applying an axe
would break the boulder or statue rather than chop the tree
avoid premapping outside Sokoban map to prevent showing stone glyphs
Grimtooth is permanently poisoned, protects from poison, and can fling poison
cursed magic whistle can teleport you to your pet
Fire and Frost Brand can be invoked for expert level fireball or cone of cold
wielding Trollsbane grants hungerless regeneration
hitting with Ogresmasher gives a higher chance of knockback
Snickersnee can hit at a distance once per turn for free
the engraving pristine text field was not being appropriately populated during
level creation
worn alchemy smock reduces chances of dipped potions exploding
dwarves can sense buried items under their feet
monsters trapped in pits cannot kick
create familiar spell can create harder creatures
a vampire lord could choose to take on wolf form while flying over water or
lava, then revert to vampire lord form and teleport unnecessarily
a gas spore that was killed when an engulfer swallowed it produced an explosion
on the map rather than inside the engulfer
hallucination can display objects on the map that have a description (for
shuffling into play at game start) but no name; examining those might
trigger a crash
Fixes to 3.7.0-x General Problems Exposed Via git Repository
@@ -2051,6 +2106,28 @@ non-fireproof water walking boots wouldn't be burnt up if fire resistant hero
at wall locations
if a pile of objects had plain arrow(s) on top, map location classification
got confused and reported 'unexplored area'
when the 'fireassist' option was on, 'f' would choose uquiver over wielded
throw-and-return uwep
knockback could move hero diagonally into or out of an open doorway
farlook of /e or /E stopped reporting engraving and headstone text after a fix
for the situation where // or ; reported such text when there was an
object or monster in the way
message was garbled when lightning or acid breath hit iron bars
shop bug: buying a container with unpaid items in it could produce impossible
"unpaid_cost: object not on any bill" warnings
when walking into/against a locked closed door, 'autounlock'==kick didn't
execute kick when player answered yes to "Door is locked. Kick it?"
having a 1% chance of creating rideable monsters with worn saddle gave knights
a 1% chance of creating an extra saddle for starting pony; it wasn't
tracked with other objects so produced a trivial memory leak
when attacking a displacer beast, using the 'F' forcefight prefix prevented it
from swapping places with the hero
successfully disarming a chest trap was clearing the chest's 'tknown' bit
instead of setting it; likewise when failing to disarm triggered and
used up the trap
when game ended with 'force_invmenu' On, final disclosure of inventory would
contain spurious menu entry "? - (list likely candidates)"
avoid reporting "a gold pieces appears next to you" for mimic
Fixes to 3.7.0-x Platform and/or Interface Problems Exposed Via git Repository
@@ -2108,6 +2185,7 @@ Qt: with a pick-one menu containing a pre-selected entry, clicking on that
instead of typing the selector letter toggled off preselected entry
but failed to toggle on the explicitly selected one; clicking again
after nothing was pre-selected anymore refused to toggle anything on
Qt: don't show main window and tombstone window maximized by default
tty: redraw unexplored locations as S_unexplored rather than <space> after
map has been partially overwritten by popup menu or text display
tty: previous change resulted in remnants of previous level being shown on
@@ -2161,6 +2239,9 @@ X11: when trying to lookup scrollbars in order to handle scrolling via keys,
X11: enable horizontal scrollbar for persistent inventory window
X11: if a group accelerator matched a menu command ('^' in menu for '/')
it wouldn't work to select, just to manipulate the menu
X11: ascii_map could try to use a color value, with some added flag bits set,
as an index into the color_gcs[] and inv_color_gcs[] arrays leading
to a segfault; clear the flag bits before using the color as an index
X11+macOS: after the "bad Atom" fix (below), the persistent inventory window
crept downward every time it got updated
@@ -2204,7 +2285,7 @@ curses: if user's terminal was set to 'application keypad mode' (DEC VTxxx
"ESC SPC G"), nethack wasn't recognizing number pad keys
curses: change petattr attributes, dropping support for curses-only ones
curses: swap the grey and no-color color initialization
curses: allow changing default colors with the 'palette' config option
curses+Qt: allow changing default colors with the 'palette' config option
(only if compiled with CHANGE_COLOR)
curses: if messages have been issued during start-up (for instance, warnings
about issues in run-time config file), prompt user to press <return>
@@ -2375,7 +2456,12 @@ tty: add support for petattr
tty: if a ^C interrupt occurred while DECgraphics characters were being drawn
on the map, the "Really quit?" prompt would be illegible due to being
rendered with VT line drawing characters
tty: hide cursor unless waiting for user input
tty: hide cursor unless waiting for user input; now extended to include tty
platforms that define NO_TERMS, rather than just on those using
termcap/terminfo, namely Windows console and msdos (text-mode
implemented; vga and vesa just have stubs currently)
tty+curses: if terminal goes away while in the wishing prompt, return to the
wish prompt when game is restored
Unix: when user name is used as default character name, keep hyphenated value
intact instead stripping off dash and whatever follows as if that
specified role/race/&c (worked once upon a time; broken since 3.3.0)
@@ -2387,6 +2473,8 @@ Unix: re-do command line parsing
Unix: add ../include/nhlua.h to the alloc.o dependencies in Makefile.utl to
match Makefile.src
Unix: implement SELF_RECOVER compile-time option, on by default on linux
Unix: allow build to succeed with musl (instead of glibc), by specifying
musl=1 on the make command line
user_sounds: move the message hook from inside individual window display ports
to the core where it allows MSGTYP_NOSHOW msgtyp's to still trigger
sounds to correct a reported github issue; also fixes a past reported
@@ -2490,6 +2578,8 @@ item-using monsters will zap wand of undead turning at corpse-wielding hero
when the corpse is harmful
boiling a pool or fountain now creates a temporary cloud of steam
random themed rooms in the dungeons of doom
environment variables THEMERM and THEMERMFILL can be used in wizard mode to
provide some control over theme room generation
extended achievement and conduct fields for xlogfile
record amount of gold in hero's possession in xlogfile
new objects: amulets of flying and guarding, helm of caution,
@@ -2566,7 +2656,7 @@ menu for what-is command supports /^ and /" to view a list of nearby or whole
level visible and remembered traps
spiders will occasionally spin webs when moving around
drinking a burning potion of oil will cure being turned into slime
new bigroom variant, a boulder maze
new bigroom variants, a boulder maze and hexagons
vomiting on an altar provokes the deities wrath
branch stairs have a different glyph, show up in yellow color in tty
duration of confusion when drinking booze depends upon hunger state
@@ -2710,6 +2800,20 @@ livelog/#chronicle for saving-grace: if saving-grace prevents hero's death,
enlightenment/attribute disclosure for saving-grace: include a line for have
or haven't been saved (game in progress) or did or didn't get saved
(game over) via saving-grace
'selectsaved' lists "name-role-race-gend-algn" instead of just "name" in the
menu of save files available to be restored
'selectsaved' prefixes "name-role-race-gend-algn" with "- " for normal play,
"X " for explore mode, or "D " for debug mode if any of the games
shown in its menu weren't saved during normal play; if they're all
normal play, the prefix is suppressed
tourists gain experience by "taking photos" of new creatures, and
going to new dungeon levels
healers gain experience by healing pets
blessed scroll of destroy armor asks which armor to destroy
archeologists' fedora is lucky
telepathic hero can discern which particular monster just read a scroll
add "make fetch-docs" to download pre-formatted documentation
monsters will use throw-and-return weapons such as an aklys
Platform- and/or Interface-Specific New Features
@@ -2806,7 +2910,7 @@ always print a message when the hero teleports (pr #265 by copperwater)
always print a message when the hero level teleports (pr #265 by copperwater)
remove Sokoban luck penalties for actions you can't cheat with (pr #260 by
copperwater)
sounds for minotaurs (pr #298 by NullCGT)
sounds for minotaurs (pr #298 by Kestrel Gregorich-Trevor)
correct the Guidebook descriptions for msdos video_width and video_height to
state that they work with video:vesa; the video:vga setting that was
described there forces the 640x480x16 mode where video_width and
@@ -2820,7 +2924,7 @@ allow themed rooms constrained by level difficulty (pr #344 by copperwater)
add a varied form of LIBNH nethack library contribution (pr #385, #403
by apowers313)
add cross-compile to WASM (pr #385, #403, #412 by apowers313)
differentiating gendered monster tiles (pr #430 by NullCGT)
differentiating gendered monster tiles (pr #430 by Kestrel Gregorich-Trevor)
check bones data directly for deja vu messages (pr #374 by entrez)
unify code for extracting an object from a monster's inventory (pr #455 by
copperwater)
@@ -2847,9 +2951,8 @@ use %lu, not %d, in format string in timer_sanity_check() (pr #617 by argrath)
bad cast making sp_lev chameleon light source (pr #625 by entrez)
add Ray Chason's adaptation of nethack's Qt5 interface to work with Qt6 (issue
#525 followup comment by chasonr)
mingw32 build updates and replacement of sys/windows/Makefile.gcc with new
sys/windows/Makefile.mingw32 and sys/windows/Makefile.mingw32.depend
(pr #661 by feiyunw)
mingw32 build updates to replace contents of sys/windows/GNUmakefile and new
sys/windows/GNUmakefile.depend (pr #661 by feiyunw)
mark various pointers to const char as const pointers (pr #624 by argrath)
function fill_special_room() in sp_lev.c was dereferencing a pointer
argument prior to a subsequent check for a NULL pointer that
@@ -2906,6 +3009,9 @@ split "cannot_push" on moverock_done() into a separate function (pr #1282
by argrath)
split making pits on do_earthquake() into a separate function and
eliminate some gotos on do_earthquake() (pr #1287 by argrath)
update the WASM cross-compile to work with the current
code (pr #1331 by guillaumebrunerie)
add silver maces (pr #1405 by disperse)
Code Cleanup and Reorganization

View File

@@ -14,7 +14,6 @@ Platform- and/or Interface-Specific Fixes
General New Features
--------------------
Conway's Life bigroom variant
Platform- and/or Interface-Specific New Features

View File

@@ -201,6 +201,7 @@ Returns a table with the following elements:
| ttyp_name | text | name of trap type
| tseen | boolean | trap seen by you?
| madeby_u | boolean | trap made by you?
| once | boolean | trap is deleted once triggered
| tnote | integer | note of a squeaky board trap
| launchx, launchy, launch2x, launch2y | integer | coordinates of a boulder for a rolling boulder trap
| conjoined | integer | encoded directions for a [spiked] pit.
@@ -249,6 +250,15 @@ Example:
local str = nh.ing_suffix("foo");
=== is_genocided
Is specific monster type genocided? Returns a boolean value.
Example:
local x = nh.is_genocided("vampire");
=== level_difficulty
Returns an integer value describing the level difficulty.
@@ -531,9 +541,10 @@ Example:
=== exclusion
Exclude an area of the map from being randomly chosen target when
falling or teleporting into the level. Multiple exclusions per level are allowed.
falling or teleporting into the level, or creating a monster.
Multiple exclusions per level are allowed.
* type is one of "teleport", "teleport-up", or "teleport-down".
* type is one of "teleport", "teleport-up", "teleport-down", or "monster-generation".
Example:
@@ -783,8 +794,9 @@ The hash parameter accepts the following keys:
| adjacentok | boolean | is adjacent location ok, if given one is not suitable?
| ignorewater | boolean | ignore water when choosing location for the monster
| countbirth | boolean | do we count this monster as generated
| appear_as | string | monster can appear as object, monster, or terrain. Add "obj:", "mon:", or "ter:" prefix to the value. |
| inventory | function | objects generated in the function are given to the monster
| appear_as | string | monster can appear as object, monster, or terrain. Add "obj:", "mon:", or "ter:" prefix to the value.
| inventory | function | objects generated in the function are given to the monster (any random inventory it gets is discarded unless keep_default_invent is true)
| keep_default_invent | boolean | if inventory is specified and this is true, those items are in addition to random inventory for this species; if inventory is not specified and this is false, monster gets no starting inventory
|===
Example:
@@ -839,6 +851,7 @@ The table parameter accepts the following:
| eroded | int | Object erosion
| locked | boolean | Is the object locked?
| trapped | boolean | Is the object trapped?
| trap_known | boolean | If container is trapped, is it obvious?
| recharged | boolean | Is the object recharged?
| greased | boolean | Is the object greased?
| broken | boolean | Is the object broken?
@@ -1307,6 +1320,8 @@ Example:
=== room
Create a selection of locations inside the (current) room.
Does not include the edges of the room, such as its walls.
Does not do any check on terrain type, so if there are non-ROOM locations inside the room, they remain part of the selection.
Example:

View File

@@ -1,7 +1,7 @@
.\"DO NOT REMOVE NH_DATESUB .TH MAKEDEFS 6 "DATE(%-d %B %Y)" NETHACK
.TH MAKEDEFS 6 "8 February 2022" NETHACK
.\"DO NOT REMOVE NH_DATESUB .ds Nd DATE(%Y)
.ds Nd 2022
.\"DO NOT REMOVE NH_DATESUB .TH MAKEDEFS 6 "Date(%-d %B %Y)" Project(uc)
.TH MAKEDEFS 6 "25 December 2024" NETHACK
.\"DO NOT REMOVE NH_DATESUB .ds Nd Date(%Y)
.ds Nd 2024
.de NB
.ds Nb \\$2
..
@@ -10,6 +10,11 @@
..
.NB $NHDT-Branch: NetHack-3.7 $
.NR $NHDT-Revision: 1.22 $
.\" groff and AT&T-descended troffs use different hyphenation patterns.
.\" Don't hyphenate the last word on a page or column, or
.\" before/after last/first 2 characters of a word.
.ie \n(.g .hy 12
.el .hy 14
.ds Na Kenneth Lorber
.SH NAME
makedefs \- NetHack miscellaneous build-time functions

View File

@@ -1,4 +1,4 @@
MAKEDEFS(6) MAKEDEFS(6)
MAKEDEFS(6) Games Manual MAKEDEFS(6)
@@ -32,13 +32,13 @@ SHORT COMMANDS
-m Generate date.h and options file. It will read dat/gitinfo.txt,
only if it is present, to obtain githash= and gitbranch=
info and include related preprocessor #defines in date.h file.
info and include related preprocessor #defines in date.h file.
-p Generate pm.h
-q Generate the rumors file.
-s Generate the bogusmon , engrave and epitaph files.
-s Generate the bogusmon, engrave, and epitaph files.
-1 Generate the epitaph file.
@@ -53,7 +53,7 @@ LONG COMMANDS
Show debugging output.
--make [command]
Execute a short command. Command is given without preceding
Execute a short command. Command is given without preceding
dash.
--input file
@@ -61,66 +61,66 @@ LONG COMMANDS
is - standard input is read.
--output file
Specify the output file for the command (if needed). If the
Specify the output file for the command (if needed). If the
file is - standard output is written.
--svs [delimiter]
Generate a version string to standard output without a trailing
newline. If specified, the delimiter is used between each part
Generate a version string to standard output without a trailing
newline. If specified, the delimiter is used between each part
of the version string.
--grep Filter the input file to the output file. See the MDGREP FUNC-
--grep Filter the input file to the output file. See the MDGREP FUNC-
TIONS section below for information on controlling the filtering
operation.
--grep-showvars
Show the name and value for each variable known to the grep
Show the name and value for each variable known to the grep
option.
--grep-trace
Turn on debug tracing for the grep function ( --grep must be
Turn on debug tracing for the grep function ( --grep must be
specified as well).
--grep-defined symbol
Exit shell true (0) if symbol is known and defined, otherwise
Exit shell true (0) if symbol is known and defined, otherwise
exit shell false (1).
--grep-define symbol
Force the value of symbol to be "defined." Symbol must already
Force the value of symbol to be "defined." Symbol must already
be known to makedefs.
--grep-undef symbol
Force the definition of symbol to be "undefined." Symbol must
Force the definition of symbol to be "undefined." Symbol must
already be known to makedefs.
MDGREP FUNCTIONS
The --grep command (and certain other commands) filter their input, on
a line-by-line basis, according to control lines embedded in the input
and on information gleaned from the NetHack(6) configuration. This
allows certain changes such as embedding platform-specific documenta-
The --grep command (and certain other commands) filter their input, on
a line-by-line basis, according to control lines embedded in the input
and on information gleaned from the NetHack(6) configuration. This
allows certain changes such as embedding platform-specific documenta-
tion into the master documentation files.
Rules:
- The default conditional state is printing enabled.
- Any line NOT starting with a caret (^) is either suppressed
or passed through unchanged depending on the current condi-
- Any line NOT starting with a caret (^) is either suppressed
or passed through unchanged depending on the current condi-
tional state.
- Any line starting with a caret is a control line; as in C,
zero or more spaces may be embedded in the line almost any-
where (except immediately after the caret); however the
- Any line starting with a caret is a control line; as in C,
zero or more spaces may be embedded in the line almost any-
where (except immediately after the caret); however the
caret must be in column 1.
- Conditionals may be nested.
- Makedefs will exit with an error code if any errors are
detected; processing will continue (if it can) to allow as
- Makedefs will exit with an error code if any errors are
detected; processing will continue (if it can) to allow as
many errors as possible to be detected.
- Unknown identifiers are treated as both TRUE and as an
error. Note that --undef or #undef in the NetHack(6) con-
- Unknown identifiers are treated as both TRUE and as an
error. Note that --undef or #undef in the NetHack(6) con-
figuration are different from unknown.
Control lines:
@@ -143,10 +143,10 @@ AUTHOR
The NetHack Development Team
COPYRIGHT
This file is Copyright (C) Kenneth Lorber, 2022 for version keni-crash-
web2:1.21. NetHack may be freely redistributed. See license for
details.
This file is Copyright (C) Kenneth Lorber, 2024 for version
NetHack-3.7:1.22. NetHack may be freely redistributed. See license
for details.
NETHACK 8 February 2022 MAKEDEFS(6)
NETHACK 25 December 2024 MAKEDEFS(6)

View File

@@ -17,8 +17,8 @@ DESCRIPTION
All -mn macros, diversions, string registers, and number registers are
defined below. Many nroff and troff requests are unsafe in conjunction
with this package. However, the requests below may be used with
impunity:
with this package. However, the requests below may be used with im-
punity:
.bp begin new page
.br break output line
@@ -29,8 +29,8 @@ DESCRIPTION
Font and point size changes with \f and \s are also allowed; for exam-
ple, ``\f2word\fR'' will italicize word. Output of the tbl(1), eqn(1),
and refer(1) preprocessors for equations, tables, and references is
acceptable as input.
and refer(1) preprocessors for equations, tables, and references is ac-
ceptable as input.
FILES
/usr/lib/tmac/tmac.n
@@ -47,12 +47,12 @@ WARNINGS
This package is not now intended for uses other than with the news doc-
umentation.
Bug reports are always welcome; please send them to the author.
(Include a sample of the input; this helps track down the bug.)
Bug reports are always welcome; please send them to the author. (In-
clude a sample of the input; this helps track down the bug.)
AUTHOR
Matt Bishop (mab@riacs.arpa, ihnp4!ames!riacs!mab, dec-
vax!decwrl!riacs!mab)
Matt Bishop (mab@riacs.arpa, ihnp4!ames!riacs!mab, decvax!decwrl!ri-
acs!mab)
Updated for versions 1.4-1.6 by The NetHack Development Team
REQUESTS
@@ -82,7 +82,7 @@ bt num .5i+1v - bottom of footer to bottom of page
cm num 0 - 0 if no cut marks, nonzero if cut marks
.cn x y z mac - - print computer/site name; same as .i
.dd div - i text of display
dg str *,- - footnote mark
dg str *,<*> - footnote mark
dw str current - name of current day of week
dy str current - full date
.ed mac - b end display

View File

@@ -76,6 +76,7 @@ and the second for
Macro What Initial Note \0 Explanation
Name It Is Value
.sp .3
nH num 0 \- avoid processing multiple times
_BR mac \- \- hard line break with vertical padding inserted
bR num \- i
_CC \*Y mac \- \- aligned one char key \*x with \fIshort\fP definition \*y
@@ -92,4 +93,5 @@ PX num \- i
PY num \- i
_SD \*X mac \- \- .sd with options c-center i-indent n-no indent
SF num \- i
UR mac \- \- URL passthrough for HTML generator
_UX mac \- \- .ux with updated trademark owner

View File

@@ -1,7 +1,7 @@
.\"DO NOT REMOVE NH_DATESUB .TH NETHACK 6 "DATE(%-d %B %Y)" NETHACK
.TH NETHACK 6 "21 February 2022" NETHACK
.\"DO NOT REMOVE NH_DATESUB .ds Nd DATE(%Y)
.ds Nd 2022
.\"DO NOT REMOVE NH_DATESUB .TH NETHACK 6 "Date(%-d %B %Y)" Project(uc)
.TH NETHACK 6 "25 December 2024" NETHACK
.\"DO NOT REMOVE NH_DATESUB .ds Nd Date(%Y)
.ds Nd 2024
.de NB
.ds Nb \\$2
..
@@ -10,6 +10,11 @@
..
.NB $NHDT-Branch: NetHack-3.7 $
.NR $NHDT-Revision: 1.31 $
.\" groff and AT&T-descended troffs use different hyphenation patterns.
.\" Don't hyphenate the last word on a page or column, or
.\" before/after last/first 2 characters of a word.
.ie \n(.g .hy 12
.el .hy 14
.ds Na Robert Patrick Rankin
.SH NAME
nethack \- Exploring The Mazes of Menace

View File

@@ -286,4 +286,4 @@ COPYRIGHT
NETHACK 28 February 2024 NETHACK(6)
NETHACK 25 December 2024 NETHACK(6)

View File

@@ -1,7 +1,7 @@
.\"DO NOT REMOVE NH_DATESUB .TH RECOVER 6 "DATE(%-d %B %Y)" NETHACK
.TH RECOVER 6 "8 February 2022" NETHACK
.\"DO NOT REMOVE NH_DATESUB .ds Nd DATE(%Y)
.ds Nd 2022
.\"DO NOT REMOVE NH_DATESUB .TH RECOVER 6 "Date(%-d %B %Y)" Project(uc)
.TH RECOVER 6 "25 December 2024" NETHACK
.\"DO NOT REMOVE NH_DATESUB .ds Nd Date(%Y)
.ds Nd 2024
.de NB
.ds Nb \\$2
..
@@ -10,6 +10,11 @@
..
.NB $NHDT-Branch: NetHack-3.7 $
.NR $NHDT-Revision: 1.12 $
.\" groff and AT&T-descended troffs use different hyphenation patterns.
.\" Don't hyphenate the last word on a page or column, or
.\" before/after last/first 2 characters of a word.
.ie \n(.g .hy 12
.el .hy 14
.ds Na Kenneth Lorber
.SH NAME
recover \- recover a NetHack game interrupted by disaster
@@ -43,6 +48,7 @@ supplies a directory which is the NetHack playground.
It overrides the value from NETHACKDIR, HACKDIR, or the directory
specified by the game administrator during compilation
(usually /usr/games/lib/nethackdir).
.ig
.PP
^?ALLDOCS
For recovery to be possible,
@@ -64,6 +70,7 @@ This configuration of
was created without support for recovery.
^.
^.
..
NetHack normally writes out files for levels as the player leaves them,
so they will be ready for return visits.
When checkpointing, NetHack also writes out the level entered and

View File

@@ -1,4 +1,4 @@
RECOVER(6) RECOVER(6)
RECOVER(6) Games Manual RECOVER(6)
@@ -22,15 +22,11 @@ DESCRIPTION
The -d option, which must be the first argument if it appears, supplies
a directory which is the NetHack playground. It overrides the value
from NETHACKDIR, HACKDIR, or the directory specified by the game admin-
istrator during compilation (usually /usr/games/lib/nethackdir).
For recovery to be possible, nethack must have been compiled with the
INSURANCE option, and the run-time option checkpoint must also have
been on. NetHack normally writes out files for levels as the player
leaves them, so they will be ready for return visits. When checkpoint-
ing, NetHack also writes out the level entered and the current game
state on every level change. This naturally slows level changes down
somewhat.
istrator during compilation (usually /usr/games/lib/nethackdir).
NetHack normally writes out files for levels as the player leaves them,
so they will be ready for return visits. When checkpointing, NetHack
also writes out the level entered and the current game state on every
level change. This naturally slows level changes down somewhat.
The level file names are of the form base.nn, where nn is an internal
bookkeeping number for the level. The file base.0 is used for game
@@ -77,10 +73,10 @@ BUGS
nism to avoid conflicts.
COPYRIGHT
This file is Copyright (C) Kenneth Lorber, 2022 for version
This file is Copyright (C) Kenneth Lorber, 2024 for version
NetHack-3.7:1.12. NetHack may be freely redistributed. See license
for details.
NETHACK 8 February 2022 RECOVER(6)
NETHACK 25 December 2024 RECOVER(6)

View File

@@ -508,8 +508,8 @@ use the following guidelines:
Windows with Visual studio nmake at the command
line.
sys/windows/Makefile.mingw32
sys/windows/Makefile.mingw32.depend
sys/windows/GNUmakefile
sys/windows/GNUmakefile.depend
Will require updates in order to build on
Windows with mingw32 or MSYS2 using GNU make at

View File

@@ -134,8 +134,9 @@
\\$1\\$2
..
.
.\" Don't hyphenate the last word on a page or column. groff and AT&T-
.\" descended troffs use different hyphenation patterns.
.ie \n(.g .hy 6
.el .hy 2
.\" groff and AT&T-descended troffs use different hyphenation patterns.
.\" Don't hyphenate the last word on a page or column, or
.\" before/after last/first 2 characters of a word.
.ie \n(.g .hy 12
.el .hy 14
.\"tmac.nh/"

View File

@@ -649,14 +649,6 @@ can_suspend() -- Tell the core if the window system will allow the game
to be suspended now. If unconditionally yes or no, use
genl_can_suspend_yes() or genl_can_suspend_no().
start_screen() -- Only used on Unix tty ports, but must be declared for
completeness. Sets up the tty to work in full-screen
graphics mode. Look at win/tty/termcap.c for an
example. If your window-port does not need this function
just declare an empty function.
end_screen() -- Only used on Unix tty ports, but must be declared for
completeness. The complement of start_screen().
outrip(winid, int, time_t)
-- The tombstone code. If you want the traditional code use
genl_outrip for the value and check the #if in rip.c.

2
include/.gitignore vendored
View File

@@ -15,3 +15,5 @@ tile.h
win32api.h
# really obsolete...
.cvsignore
sfproto.h

View File

@@ -5,6 +5,10 @@
#ifndef ARTIFACT_H
#define ARTIFACT_H
#include "permonst.h"
#include "prop.h"
/* clang-format off */
#define SPFX_NONE 0x00000000L /* no special effects, just a bonus */
@@ -49,6 +53,8 @@ struct artifact {
aligntyp alignment; /* alignment of bequeathing gods */
short role; /* character role associated with */
short race; /* character race associated with */
schar gen_spe; /* bias to spe when gifted or randomly generated */
uchar gift_value; /* minimum sacrifice value to be gifted this */
long cost; /* price when sold to hero (default 100 x base cost) */
char acolor; /* color to use if artifact 'glows' */
};
@@ -65,8 +71,25 @@ enum invoke_prop_types {
ENLIGHTENING,
CREATE_AMMO,
BANISH,
FLING_POISON,
FIRESTORM,
SNOWSTORM,
BLINDING_RAY
};
/* artifact tracking; gift and wish imply found; it also gets set for items
seen on the floor, in containers, and wielded or dropped by monsters */
struct arti_info {
Bitfield(exists, 1); /* 1 if corresponding artifact has been created */
Bitfield(found, 1); /* 1 if artifact is known by hero to exist */
Bitfield(gift, 1); /* 1 iff artifact was created as a prayer reward */
Bitfield(wish, 1); /* 1 iff artifact was created via wish */
Bitfield(named, 1); /* 1 iff artifact was made by naming an item */
Bitfield(viadip, 1); /* 1 iff dipped long sword became Excalibur */
Bitfield(lvldef, 1); /* 1 iff created by special level definition */
Bitfield(bones, 1); /* 1 iff came from bones file */
Bitfield(rndm, 1); /* 1 iff randomly generated */
};
/* clang-format on */
#endif /* ARTIFACT_H */

View File

@@ -7,28 +7,28 @@
/* in makedefs.c, all we care about is the list of names */
#define A(nam, typ, s1, s2, mt, atk, dfn, cry, inv, al, cl, rac, \
cost, clr, bn) nam
gs, gv, cost, clr, bn) nam
static const char *const artifact_names[] = {
#elif defined(ARTI_ENUM)
#define A(nam, typ, s1, s2, mt, atk, dfn, cry, inv, al, cl, rac, \
cost, clr, bn) \
gs, gv, cost, clr, bn) \
ART_##bn
#elif defined(DUMP_ARTI_ENUM)
#define A(nam, typ, s1, s2, mt, atk, dfn, cry, inv, al, cl, rac, \
cost, clr, bn) \
gs, gv, cost, clr, bn) \
{ ART_##bn, "ART_" #bn }
#else
/* in artifact.c, set up the actual artifact list structure;
color field is for an artifact when it glows, not for the item itself */
#define A(nam, typ, s1, s2, mt, atk, dfn, cry, inv, al, cl, rac, \
cost, clr, bn) \
gs, gv, cost, clr, bn) \
{ \
typ, nam, s1, s2, mt, atk, dfn, cry, inv, al, cl, rac, \
cost, clr \
gs, gv, cost, clr \
}
/* clang-format off */
@@ -43,6 +43,7 @@ static const char *const artifact_names[] = {
#define FIRE(a,b) {0,AD_FIRE,a,b}
#define ELEC(a,b) {0,AD_ELEC,a,b} /* electrical shock */
#define STUN(a,b) {0,AD_STUN,a,b} /* magical attack */
#define POIS(a,b) {0,AD_DRST,a,b} /* poison */
/* clang-format on */
static NEARDATA struct artifact artilist[] = {
@@ -52,24 +53,47 @@ static NEARDATA struct artifact artilist[] = {
* 1. The more useful the artifact, the better its cost.
* 2. Quest artifacts are highly valued.
* 3. Chaotic artifacts are inflated due to scarcity (and balance).
*
* Artifact gen_spe rationale:
* 1. If the artifact is useful against most enemies, +0.
* 2. If the artifact is useful against only a few enemies, usually +2.
* This gives the artifact use to early-game characters who receive
* it as a gift or find it on the ground.
* 3. Role gift gen_spe is chosen to balance against the role's
* default starting weapon (it should be better, but need not be
* much better).
* 4. This can be modified as required for special cases.
* (In some cases, like Excalibur, the value is irrelevant.)
* 5. Nonweapon spe may have a special meaning, so gen_spe for
* nonweapons must always be 0.
*
* Artifact gift_value is chosen so that "endgame-quality" artifacts are
* not gifted in the early game (so that characters don't grind on an
* altar early-game until they have their endgame weapon, then use it to
* carry them through the game). Those artifacts have values ranging from
* around 8 to 10, based on how good the artifact is. Less powerful
* artifacts have values in the 1 to 5 range. Values in between are used
* for conditionally good artifacts. (Note that the value of a gift is
* normally 1 higher than the difficulty of the monster.)
*/
/* dummy element #0, so that all interesting indices are non-zero */
A("", STRANGE_OBJECT, 0, 0, 0, NO_ATTK, NO_DFNS, NO_CARY, 0, A_NONE,
NON_PM, NON_PM, 0L, NO_COLOR, NONARTIFACT),
NON_PM, NON_PM,
0, 0, 0L, NO_COLOR, NONARTIFACT),
A("Excalibur", LONG_SWORD, (SPFX_NOGEN | SPFX_RESTR | SPFX_SEEK
| SPFX_DEFN | SPFX_INTEL | SPFX_SEARCH),
0, 0, PHYS(5, 10), DRLI(0, 0), NO_CARY, 0, A_LAWFUL, PM_KNIGHT, NON_PM,
4000L, NO_COLOR, EXCALIBUR),
0, 10, 4000L, NO_COLOR, EXCALIBUR),
/*
* Stormbringer only has a 2 because it can drain a level,
* providing 8 more.
*/
A("Stormbringer", RUNESWORD,
(SPFX_RESTR | SPFX_ATTK | SPFX_DEFN | SPFX_INTEL | SPFX_DRLI), 0, 0,
DRLI(5, 2), DRLI(0, 0), NO_CARY, 0, A_CHAOTIC, NON_PM, NON_PM, 8000L,
NO_COLOR, STORMBRINGER),
DRLI(5, 2), DRLI(0, 0), NO_CARY, 0, A_CHAOTIC, NON_PM, NON_PM,
0, 9, 8000L, NO_COLOR, STORMBRINGER),
/*
* Mjollnir can be thrown when wielded if hero has 25 Strength
* (usually via gauntlets of power but possible with rings of
@@ -84,10 +108,12 @@ static NEARDATA struct artifact artilist[] = {
*/
A("Mjollnir", WAR_HAMMER, /* Mjo:llnir */
(SPFX_RESTR | SPFX_ATTK), 0, 0, ELEC(5, 24), NO_DFNS, NO_CARY, 0,
A_NEUTRAL, PM_VALKYRIE, NON_PM, 4000L, NO_COLOR, MJOLLNIR),
A_NEUTRAL, PM_VALKYRIE, NON_PM,
0, 8, 4000L, NO_COLOR, MJOLLNIR),
A("Cleaver", BATTLE_AXE, SPFX_RESTR, 0, 0, PHYS(3, 6), NO_DFNS, NO_CARY,
0, A_NEUTRAL, PM_BARBARIAN, NON_PM, 1500L, NO_COLOR, CLEAVER),
0, A_NEUTRAL, PM_BARBARIAN, NON_PM,
0, 8, 1500L, NO_COLOR, CLEAVER),
/*
* Grimtooth glows in warning when elves are present, but its
@@ -95,8 +121,9 @@ static NEARDATA struct artifact artilist[] = {
* (handled as special case in spec_dbon()).
*/
A("Grimtooth", ORCISH_DAGGER, (SPFX_RESTR | SPFX_WARN | SPFX_DFLAG2),
0, M2_ELF, PHYS(2, 6), NO_DFNS,
NO_CARY, 0, A_CHAOTIC, NON_PM, PM_ORC, 300L, CLR_RED, GRIMTOOTH),
0, M2_ELF, PHYS(2, 6), POIS(0,0),
NO_CARY, FLING_POISON, A_CHAOTIC, NON_PM, PM_ORC,
0, 5, 1200L, CLR_RED, GRIMTOOTH),
/*
* Orcrist and Sting have same alignment as elves.
*
@@ -105,56 +132,56 @@ static NEARDATA struct artifact artilist[] = {
* Sting and Orcrist will warn of M2_ORC monsters.
*/
A("Orcrist", ELVEN_BROADSWORD, (SPFX_WARN | SPFX_DFLAG2), 0, M2_ORC,
PHYS(5, 0), NO_DFNS, NO_CARY, 0, A_CHAOTIC, NON_PM, PM_ELF, 2000L,
CLR_BRIGHT_BLUE, ORCRIST), /* bright blue is actually light blue */
PHYS(5, 0), NO_DFNS, NO_CARY, 0, A_CHAOTIC, NON_PM, PM_ELF,
3, 4, 2000L, CLR_BRIGHT_BLUE, ORCRIST), /* actually light blue */
A("Sting", ELVEN_DAGGER, (SPFX_WARN | SPFX_DFLAG2), 0, M2_ORC,
PHYS(5, 0), NO_DFNS, NO_CARY, 0, A_CHAOTIC, NON_PM, PM_ELF, 800L,
CLR_BRIGHT_BLUE, STING),
PHYS(5, 0), NO_DFNS, NO_CARY, 0, A_CHAOTIC, NON_PM, PM_ELF,
3, 1, 800L, CLR_BRIGHT_BLUE, STING),
/*
* Magicbane is a bit different! Its magic fanfare
* unbalances victims in addition to doing some damage.
*/
A("Magicbane", ATHAME, (SPFX_RESTR | SPFX_ATTK | SPFX_DEFN), 0, 0,
STUN(3, 4), DFNS(AD_MAGM), NO_CARY, 0, A_NEUTRAL, PM_WIZARD, NON_PM,
3500L, NO_COLOR, MAGICBANE),
0, 7, 3500L, NO_COLOR, MAGICBANE),
A("Frost Brand", LONG_SWORD, (SPFX_RESTR | SPFX_ATTK | SPFX_DEFN), 0, 0,
COLD(5, 0), COLD(0, 0), NO_CARY, 0, A_NONE, NON_PM, NON_PM, 3000L,
NO_COLOR, FROST_BRAND),
COLD(5, 0), COLD(0, 0), NO_CARY, SNOWSTORM, A_NONE, NON_PM, NON_PM,
0, 9, 3000L, NO_COLOR, FROST_BRAND),
A("Fire Brand", LONG_SWORD, (SPFX_RESTR | SPFX_ATTK | SPFX_DEFN), 0, 0,
FIRE(5, 0), FIRE(0, 0), NO_CARY, 0, A_NONE, NON_PM, NON_PM, 3000L,
NO_COLOR, FIRE_BRAND),
FIRE(5, 0), FIRE(0, 0), NO_CARY, FIRESTORM, A_NONE, NON_PM, NON_PM,
0, 5, 3000L, NO_COLOR, FIRE_BRAND),
A("Dragonbane", BROADSWORD,
(SPFX_RESTR | SPFX_DCLAS | SPFX_REFLECT), 0, S_DRAGON,
PHYS(5, 0), NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM, 500L,
NO_COLOR, DRAGONBANE),
PHYS(5, 0), NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM,
2, 5, 500L, NO_COLOR, DRAGONBANE),
A("Demonbane", MACE, (SPFX_RESTR | SPFX_DFLAG2), 0, M2_DEMON,
A("Demonbane", SILVER_MACE, (SPFX_RESTR | SPFX_DFLAG2), 0, M2_DEMON,
PHYS(5, 0), NO_DFNS, NO_CARY, BANISH, A_LAWFUL, PM_CLERIC, NON_PM,
2500L, NO_COLOR, DEMONBANE),
1, 3, 2500L, NO_COLOR, DEMONBANE),
A("Werebane", SILVER_SABER, (SPFX_RESTR | SPFX_DFLAG2), 0, M2_WERE,
PHYS(5, 0), DFNS(AD_WERE), NO_CARY, 0, A_NONE, NON_PM, NON_PM, 1500L,
NO_COLOR, WEREBANE),
PHYS(5, 0), DFNS(AD_WERE), NO_CARY, 0, A_NONE, NON_PM, NON_PM,
1, 4, 1500L, NO_COLOR, WEREBANE),
A("Grayswandir", SILVER_SABER, (SPFX_RESTR | SPFX_HALRES), 0, 0,
PHYS(5, 0), NO_DFNS, NO_CARY, 0, A_LAWFUL, NON_PM, NON_PM, 8000L,
NO_COLOR, GRAYSWANDIR),
PHYS(5, 0), NO_DFNS, NO_CARY, 0, A_LAWFUL, NON_PM, NON_PM,
0, 10, 8000L, NO_COLOR, GRAYSWANDIR),
A("Giantslayer", LONG_SWORD, (SPFX_RESTR | SPFX_DFLAG2), 0, M2_GIANT,
PHYS(5, 0), NO_DFNS, NO_CARY, 0, A_NEUTRAL, NON_PM, NON_PM, 200L,
NO_COLOR, GIANTSLAYER),
PHYS(5, 0), NO_DFNS, NO_CARY, 0, A_NEUTRAL, NON_PM, NON_PM,
2, 4, 200L, NO_COLOR, GIANTSLAYER),
A("Ogresmasher", WAR_HAMMER, (SPFX_RESTR | SPFX_DCLAS), 0, S_OGRE,
PHYS(5, 0), NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM, 200L,
NO_COLOR, OGRESMASHER),
PHYS(5, 0), NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM,
2, 1, 200L, NO_COLOR, OGRESMASHER),
A("Trollsbane", MORNING_STAR, (SPFX_RESTR | SPFX_DCLAS), 0, S_TROLL,
PHYS(5, 0), NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM, 200L,
NO_COLOR, TROLLSBANE),
A("Trollsbane", MORNING_STAR, (SPFX_RESTR | SPFX_DCLAS | SPFX_REGEN), 0,
S_TROLL, PHYS(5, 0), NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM,
2, 1, 200L, NO_COLOR, TROLLSBANE),
/*
* Two problems: 1) doesn't let trolls regenerate heads,
@@ -162,8 +189,8 @@ static NEARDATA struct artifact artilist[] = {
* allowing those at all causes more problems than worth the effort).
*/
A("Vorpal Blade", LONG_SWORD, (SPFX_RESTR | SPFX_BEHEAD), 0, 0,
PHYS(5, 1), NO_DFNS, NO_CARY, 0, A_NEUTRAL, NON_PM, NON_PM, 4000L,
NO_COLOR, VORPAL_BLADE),
PHYS(5, 1), NO_DFNS, NO_CARY, 0, A_NEUTRAL, NON_PM, NON_PM,
1, 5, 4000L, NO_COLOR, VORPAL_BLADE),
/*
* Ah, never shall I forget the cry,
@@ -174,33 +201,38 @@ static NEARDATA struct artifact artilist[] = {
* (From Sir W.S. Gilbert's "The Mikado")
*/
A("Snickersnee", KATANA, SPFX_RESTR, 0, 0, PHYS(0, 8), NO_DFNS, NO_CARY,
0, A_LAWFUL, PM_SAMURAI, NON_PM, 1200L, NO_COLOR, SNICKERSNEE),
0, A_LAWFUL, PM_SAMURAI, NON_PM,
0, 8, 1200L, NO_COLOR, SNICKERSNEE),
/* Sunsword emits light when wielded (handled in the core rather than
via artifact fields), but that light has no particular color */
A("Sunsword", LONG_SWORD, (SPFX_RESTR | SPFX_DFLAG2), 0, M2_UNDEAD,
PHYS(5, 0), DFNS(AD_BLND), NO_CARY, BLINDING_RAY, A_LAWFUL, NON_PM,
NON_PM, 1500L, NO_COLOR, SUNSWORD),
NON_PM,
0, 6, 1500L, NO_COLOR, SUNSWORD),
/*
* The artifacts for the quest dungeon, all self-willed.
* gen_spe should be 0; gift_value irrelevant and set to 12.
*/
A("The Orb of Detection", CRYSTAL_BALL,
(SPFX_NOGEN | SPFX_RESTR | SPFX_INTEL), (SPFX_ESP | SPFX_HSPDAM), 0,
NO_ATTK, NO_DFNS, CARY(AD_MAGM), INVIS, A_LAWFUL, PM_ARCHEOLOGIST,
NON_PM, 2500L, NO_COLOR, ORB_OF_DETECTION),
NON_PM,
0, 12, 2500L, NO_COLOR, ORB_OF_DETECTION),
A("The Heart of Ahriman", LUCKSTONE,
(SPFX_NOGEN | SPFX_RESTR | SPFX_INTEL), SPFX_STLTH, 0,
/* this stone does double damage if used as a projectile weapon */
PHYS(5, 0), NO_DFNS, NO_CARY, LEVITATION, A_NEUTRAL, PM_BARBARIAN,
NON_PM, 2500L, NO_COLOR, HEART_OF_AHRIMAN),
NON_PM,
0, 12, 2500L, NO_COLOR, HEART_OF_AHRIMAN),
A("The Sceptre of Might", MACE,
(SPFX_NOGEN | SPFX_RESTR | SPFX_INTEL | SPFX_DALIGN), 0, 0, PHYS(5, 0),
DFNS(AD_MAGM), NO_CARY, CONFLICT, A_LAWFUL, PM_CAVE_DWELLER, NON_PM,
2500L, NO_COLOR, SCEPTRE_OF_MIGHT),
0, 12, 2500L, NO_COLOR, SCEPTRE_OF_MIGHT),
#if 0 /* OBSOLETE -- from 3.1.0 to 3.2.x, this was quest artifact for the
* Elf role; in 3.3.0 elf became a race available to several roles
@@ -209,35 +241,37 @@ static NEARDATA struct artifact artilist[] = {
A("The Palantir of Westernesse", CRYSTAL_BALL,
(SPFX_NOGEN | SPFX_RESTR | SPFX_INTEL),
(SPFX_ESP | SPFX_REGEN | SPFX_HSPDAM), 0,
NO_ATTK, NO_DFNS, NO_CARY, TAMING, A_CHAOTIC, NON_PM, PM_ELF, 8000L,
NO_COLOR, PALANTIR_OF_WESTERNESSE),
NO_ATTK, NO_DFNS, NO_CARY, TAMING, A_CHAOTIC, NON_PM, PM_ELF,
0, 12, 8000L, NO_COLOR, PALANTIR_OF_WESTERNESSE),
#endif
A("The Staff of Aesculapius", QUARTERSTAFF,
(SPFX_NOGEN | SPFX_RESTR | SPFX_ATTK | SPFX_INTEL | SPFX_DRLI
| SPFX_REGEN),
0, 0, DRLI(0, 0), DRLI(0, 0), NO_CARY, HEALING, A_NEUTRAL, PM_HEALER,
NON_PM, 5000L, NO_COLOR, STAFF_OF_AESCULAPIUS),
NON_PM,
0, 12, 5000L, NO_COLOR, STAFF_OF_AESCULAPIUS),
A("The Magic Mirror of Merlin", MIRROR,
(SPFX_NOGEN | SPFX_RESTR | SPFX_INTEL | SPFX_SPEAK), SPFX_ESP, 0,
NO_ATTK, NO_DFNS, CARY(AD_MAGM), 0, A_LAWFUL, PM_KNIGHT, NON_PM, 1500L,
NO_COLOR, MAGIC_MIRROR_OF_MERLIN),
NO_ATTK, NO_DFNS, CARY(AD_MAGM), 0, A_LAWFUL, PM_KNIGHT, NON_PM,
0, 12, 1500L, NO_COLOR, MAGIC_MIRROR_OF_MERLIN),
A("The Eyes of the Overworld", LENSES,
(SPFX_NOGEN | SPFX_RESTR | SPFX_INTEL | SPFX_XRAY), 0, 0, NO_ATTK,
DFNS(AD_MAGM), NO_CARY, ENLIGHTENING, A_NEUTRAL, PM_MONK, NON_PM,
2500L, NO_COLOR, EYES_OF_THE_OVERWORLD),
0, 12, 2500L, NO_COLOR, EYES_OF_THE_OVERWORLD),
A("The Mitre of Holiness", HELM_OF_BRILLIANCE,
(SPFX_NOGEN | SPFX_RESTR | SPFX_DFLAG2 | SPFX_INTEL | SPFX_PROTECT), 0,
M2_UNDEAD, NO_ATTK, NO_DFNS, CARY(AD_FIRE), ENERGY_BOOST, A_LAWFUL,
PM_CLERIC, NON_PM, 2000L, NO_COLOR, MITRE_OF_HOLINESS),
PM_CLERIC, NON_PM,
0, 12, 2000L, NO_COLOR, MITRE_OF_HOLINESS),
A("The Longbow of Diana", BOW,
(SPFX_NOGEN | SPFX_RESTR | SPFX_INTEL | SPFX_REFLECT), SPFX_ESP, 0,
PHYS(5, 0), NO_DFNS, NO_CARY, CREATE_AMMO, A_CHAOTIC, PM_RANGER, NON_PM,
4000L, NO_COLOR, LONGBOW_OF_DIANA),
0, 12, 4000L, NO_COLOR, LONGBOW_OF_DIANA),
/* MKoT has an additional carry property if the Key is not cursed (for
rogues) or blessed (for non-rogues): #untrap of doors and chests
@@ -245,38 +279,39 @@ static NEARDATA struct artifact artilist[] = {
A("The Master Key of Thievery", SKELETON_KEY,
(SPFX_NOGEN | SPFX_RESTR | SPFX_INTEL | SPFX_SPEAK),
(SPFX_WARN | SPFX_TCTRL | SPFX_HPHDAM), 0, NO_ATTK, NO_DFNS, NO_CARY,
UNTRAP, A_CHAOTIC, PM_ROGUE, NON_PM, 3500L, NO_COLOR,
MASTER_KEY_OF_THIEVERY),
UNTRAP, A_CHAOTIC, PM_ROGUE, NON_PM,
0, 12, 3500L, NO_COLOR, MASTER_KEY_OF_THIEVERY),
A("The Tsurugi of Muramasa", TSURUGI,
(SPFX_NOGEN | SPFX_RESTR | SPFX_INTEL | SPFX_BEHEAD | SPFX_LUCK
| SPFX_PROTECT),
0, 0, PHYS(0, 8), NO_DFNS, NO_CARY, 0, A_LAWFUL, PM_SAMURAI, NON_PM,
4500L, NO_COLOR, TSURUGI_OF_MURAMASA),
0, 12, 4500L, NO_COLOR, TSURUGI_OF_MURAMASA),
A("The Platinum Yendorian Express Card", CREDIT_CARD,
(SPFX_NOGEN | SPFX_RESTR | SPFX_INTEL | SPFX_DEFN),
(SPFX_ESP | SPFX_HSPDAM), 0, NO_ATTK, NO_DFNS, CARY(AD_MAGM),
CHARGE_OBJ, A_NEUTRAL, PM_TOURIST, NON_PM, 7000L, NO_COLOR,
YENDORIAN_EXPRESS_CARD),
CHARGE_OBJ, A_NEUTRAL, PM_TOURIST, NON_PM,
0, 12, 7000L, NO_COLOR, YENDORIAN_EXPRESS_CARD),
A("The Orb of Fate", CRYSTAL_BALL,
(SPFX_NOGEN | SPFX_RESTR | SPFX_INTEL | SPFX_LUCK),
(SPFX_WARN | SPFX_HSPDAM | SPFX_HPHDAM), 0, NO_ATTK, NO_DFNS, NO_CARY,
LEV_TELE, A_NEUTRAL, PM_VALKYRIE, NON_PM, 3500L, NO_COLOR,
ORB_OF_FATE),
LEV_TELE, A_NEUTRAL, PM_VALKYRIE, NON_PM,
0, 12, 3500L, NO_COLOR, ORB_OF_FATE),
A("The Eye of the Aethiopica", AMULET_OF_ESP,
(SPFX_NOGEN | SPFX_RESTR | SPFX_INTEL), (SPFX_EREGEN | SPFX_HSPDAM), 0,
NO_ATTK, DFNS(AD_MAGM), NO_CARY, CREATE_PORTAL, A_NEUTRAL, PM_WIZARD,
NON_PM, 4000L, NO_COLOR, EYE_OF_THE_AETHIOPICA),
NON_PM,
0, 12, 4000L, NO_COLOR, EYE_OF_THE_AETHIOPICA),
#if !defined(ARTI_ENUM) && !defined(DUMP_ARTI_ENUM)
/*
* terminator; otyp must be zero
*/
A(0, 0, 0, 0, 0, NO_ATTK, NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM, 0L,
NO_COLOR, TERMINATOR)
A(0, 0, 0, 0, 0, NO_ATTK, NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM,
0, 0, 0L, NO_COLOR, TERMINATOR)
}; /* artilist[] (or artifact_names[]) */
#endif

View File

@@ -249,7 +249,7 @@ enum hlattribs {
struct hilite_s {
enum statusfields fld;
boolean set;
unsigned anytype;
enum any_types anytype;
anything value;
int behavior;
char textmatch[MAXVALWIDTH];
@@ -271,7 +271,7 @@ struct istat_s {
boolean chg; /* need to recalc time? */
boolean percent_matters;
short percent_value;
unsigned anytype;
enum any_types anytype;
anything a, rawval;
char *val;
int valwidth;

View File

@@ -259,21 +259,23 @@
# ifdef CRASHREPORT
# undef CRASHREPORT
# endif
# ifdef MSDOS
# if defined(MSDOS) || defined(NOPANICTRACE)
# undef PANICTRACE
# endif
#endif
#ifdef CRASHREPORT
# ifndef DUMPLOG_CORE
# define DUMPLOG_CORE // required to get ^P info
# define DUMPLOG_CORE // required to get ^P info
# endif
# ifdef MACOS
# define PANICTRACE
# endif
# ifdef __linux__
# define PANICTRACE
# define NOSTATICFN
# ifndef NOSTATICFN // may be defined on command line
# define NOSTATICFN
# endif
# endif
// This test isn't quite right: CNG is only available from Windows 2000 on.
// But we'll check that at runtime.
@@ -395,38 +397,6 @@
/* # define ZLIB_COMP */ /* ZLIB for compression */
#endif
/*
* Internal Compression Options
*
* Internal compression options RLECOMP and ZEROCOMP alter the data
* that gets written to the save file by NetHack, in contrast
* to COMPRESS or ZLIB_COMP which compress the entire file after
* the NetHack data is written out.
*
* Defining RLECOMP builds in support for internal run-length
* compression of level structures. If RLECOMP support is included
* it can be toggled on/off at runtime via the config file option
* rlecomp.
*
* Defining ZEROCOMP builds in support for internal zero-comp
* compression of data. If ZEROCOMP support is included it can still
* be toggled on/off at runtime via the config file option zerocomp.
*
* RLECOMP and ZEROCOMP support can be included even if
* COMPRESS or ZLIB_COMP support is included. One reason for doing
* so would be to provide savefile read compatibility with a savefile
* where those options were in effect. With RLECOMP and/or ZEROCOMP
* defined, NetHack can read an rlecomp or zerocomp savefile in, yet
* re-save without them.
*
* Using any compression option will create smaller bones/level/save
* files at the cost of additional code and time.
*/
/* # define INTERNAL_COMP */ /* defines both ZEROCOMP and RLECOMP */
/* # define ZEROCOMP */ /* Support ZEROCOMP compression */
/* # define RLECOMP */ /* Support RLECOMP compression */
/*
* Data librarian. Defining DLB places most of the support files into
* a tar-like file, thus making a neater installation. See *conf.h
@@ -463,7 +433,7 @@
*/
#define INSURANCE /* allow crashed game recovery */
#ifndef MAC
#if !defined(MAC) && !defined(SHIM_GRAPHICS)
#define CHDIR /* delete if no chdir() available */
#endif
@@ -629,11 +599,10 @@ typedef unsigned char uchar;
* glyph" code, then the escape codes for color and the glyph character
* itself, and then the "end glyph" code.
*
* To compile NetHack with this, add tile.c to WINSRC and tile.o to WINOBJ
* in the hints file or Makefile.
* Set boolean option vt_tiledata and/or vt_sounddata in your config file
* to turn either of these on.
* Note that gnome-terminal at least doesn't work with this. */
* To compile NetHack with this, add tile.c to WINSRC and tile.o to WINOBJ in
* the hints file or Makefile. Set boolean option vt_tiledata and/or
* vt_sounddata in your config file to turn either of these on. Note that some
* terminals (e.g. old versions of gnome-terminal) don't work with this. */
/* #define TTY_TILES_ESCCODES */
/* #define TTY_SOUND_ESCCODES */
@@ -641,12 +610,6 @@ typedef unsigned char uchar;
* at least 28 additional rows beneath the status window on your terminal */
/* #define TTY_PERM_INVENT */
/* NetHack will execute an external program whenever a new message-window
* message is shown. The program to execute is given in environment variable
* NETHACK_MSGHANDLER. It will get the message as the only parameter.
* Only available with POSIX_TYPES, GNU C, or WIN32 */
/* #define MSGHANDLER */
/* enable status highlighting via STATUS_HILITE directives in run-time
config file and the 'statushilites' option */
#define STATUS_HILITES /* support hilites of status fields */

View File

@@ -31,6 +31,10 @@
#ifndef CROSSCOMPILE
#define SHORT_FILENAMES
#endif
/* this is not fully-implemented yet for msdos */
#ifdef ENHANCED_SYMBOLS
#undef ENHANCED_SYMBOLS
#endif
#endif
/*

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 context.h $NHDT-Date: 1646428003 2022/03/04 21:06:43 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.45 $ */
/* NetHack 3.7 context.h $NHDT-Date: 1753856387 2025/07/29 22:19:47 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.58 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Michael Allison, 2006. */
/* NetHack may be freely redistributed. See license for details. */
@@ -135,6 +135,11 @@ struct achievement_tracking {
boolean minetn_reached; /* avoid redundant checking for town entry */
};
struct lifelists {
long total_seen_upclose; /* count of critters seen up close */
long total_photographed; /* count of critters photographed (tourists) */
};
struct context_info {
unsigned ident; /* social security number for each monster */
unsigned no_of_wizards; /* 0, 1 or 2 (wizard and his shadow) */
@@ -145,9 +150,11 @@ struct context_info {
int current_fruit; /* fruit->fid corresponding to svp.pl_fruit[] */
int mysteryforce; /* adjusts how often "mysterious force" kicks in */
int rndencode; /* randomized escape sequence introducer */
int startingpet_typ; /* monster type for initial pet */
int warnlevel; /* threshold (digit) to warn about unseen mons */
long next_attrib_check; /* next attribute check */
long seer_turn; /* when random clairvoyance will next kick in */
long snickersnee_turn; /* Snickersnee last used to distance attack */
long stethoscope_seq; /* when a stethoscope was last used; first use
* during a move takes no time, second uses move */
boolean travel; /* find way automatically to u.tx,u.ty */
@@ -160,6 +167,7 @@ struct context_info {
boolean mv;
boolean bypasses; /* bypass flag is set on at least one fobj */
boolean door_opened; /* set to true if door was opened during test_move */
boolean resume_wish; /* game was exited while in wish prompt */
boolean tips[NUM_TIPS];
struct dig_info digging;
struct victual_info victual;
@@ -173,6 +181,7 @@ struct context_info {
struct tribute_info tribute;
struct novel_tracking novel;
struct achievement_tracking achieveo;
struct lifelists lifelist;
char jingle[5 + 1];
};

View File

@@ -27,9 +27,9 @@
* <stddef.h> Common macro definitions
* <stdint.h> (C99) Fixed-width integer types
* <stdio.h> Input/output program utilities
*
* General utilities: memory management, program utilities, string
* conversions, random numbers, algorithms
* <stdlib.h> General utilities: memory management,
* program utilities, string conversions,
* random numbers, algorithms
* <string.h> String handling
* <tgmath.h> (C99) Type-generic math (macros wrapping math.h and
* complex.h)
@@ -51,13 +51,17 @@
*
*/
#if !defined(__cplusplus)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <assert.h>
#include <stdarg.h>
#include <ctype.h>
#include <time.h>
#else /* !__cplusplus */
/* for FILE */
#include <stdio.h>
#endif /* !__cplusplus */
#endif /* CSTD_H */

View File

@@ -181,7 +181,6 @@ struct instance_globals_a {
struct h2o_ctx acid_ctx;
boolean havestate;
unsigned long magic; /* validate that structure layout is preserved */
};
struct instance_globals_b {
@@ -219,7 +218,6 @@ struct instance_globals_b {
boolean bot_disabled;
boolean havestate;
unsigned long magic; /* validate that structure layout is preserved */
};
struct instance_globals_c {
@@ -260,7 +258,7 @@ struct instance_globals_c {
/* symbols.c */
int currentgraphics;
/* files.c */
/* files.c, cfgfiles.c */
char *cmdline_rcfile; /* set in unixmain.c, used in options.c */
char *config_section_chosen;
char *config_section_current;
@@ -298,8 +296,10 @@ struct instance_globals_c {
short corpsenm_digested; /* monster type being digested, set by gulpum */
/* zap.c */
/* new */
boolean converted_savefile_loaded;
boolean havestate;
unsigned long magic; /* validate that structure layout is preserved */
};
struct instance_globals_d {
@@ -340,8 +340,11 @@ struct instance_globals_d {
boolean decor_fumble_override;
boolean decor_levitate_override;
/* new */
boolean deferred_showpaths;
char *deferred_showpaths_dir;
boolean havestate;
unsigned long magic; /* validate that structure layout is preserved */
};
struct instance_globals_e {
@@ -362,7 +365,6 @@ struct instance_globals_e {
to gb.beyond_savefile_load */
boolean havestate;
unsigned long magic; /* validate that structure layout is preserved */
};
struct instance_globals_f {
@@ -387,7 +389,6 @@ struct instance_globals_f {
long int followmsg; /* last time of follow message */
boolean havestate;
unsigned long magic; /* validate that structure layout is preserved */
};
struct instance_globals_g {
@@ -422,6 +423,7 @@ struct instance_globals_g {
long gmst_moves;
struct obj *gmst_invent;
genericptr_t *gmst_ubak, *gmst_disco, *gmst_mvitals;
struct spell gmst_spl_book[MAXSPELL + 1];
/* pline.c */
struct gamelog_line *gamelog;
@@ -435,7 +437,6 @@ struct instance_globals_g {
long glyphmap_perlevel_flags;
boolean havestate;
unsigned long magic; /* validate that structure layout is preserved */
};
struct instance_globals_h {
@@ -456,7 +457,6 @@ struct instance_globals_h {
struct attack *hitmsg_prev;
boolean havestate;
unsigned long magic; /* validate that structure layout is preserved */
};
struct instance_globals_i {
@@ -490,7 +490,6 @@ struct instance_globals_i {
/* new */
boolean havestate;
unsigned long magic; /* validate that structure layout is preserved */
};
struct instance_globals_j {
@@ -499,7 +498,6 @@ struct instance_globals_j {
int jumping_is_magic; /* current jump result of magic */
boolean havestate;
unsigned long magic; /* validate that structure layout is preserved */
};
struct instance_globals_k {
@@ -513,7 +511,6 @@ struct instance_globals_k {
boolean known;
boolean havestate;
unsigned long magic; /* validate that structure layout is preserved */
};
struct instance_globals_l {
@@ -579,7 +576,6 @@ struct instance_globals_l {
char lua_copyright[LUA_COPYRIGHT_BUFSIZ];
boolean havestate;
unsigned long magic; /* validate that structure layout is preserved */
};
struct instance_globals_m {
@@ -608,6 +604,9 @@ struct instance_globals_m {
/* dokick.c */
struct rm *maploc;
/* mhitm.c */
struct monst *mswallower; /* for gas spore explosion when it's swallowed*/
/* mhitu.c */
int mhitu_dieroll;
@@ -615,10 +614,10 @@ struct instance_globals_m {
boolean made_branch; /* used only during level creation */
/* mkmap.c */
int min_rx; /* rectangle bounds for regions */
int max_rx;
int min_ry;
int max_ry;
coordxy min_rx; /* rectangle bounds for regions */
coordxy max_rx;
coordxy min_ry;
coordxy max_ry;
/* mkobj.c */
boolean mkcorpstat_norevive; /* for trolls */
@@ -646,7 +645,6 @@ struct instance_globals_m {
* POT_WATER should become discovered */
boolean havestate;
unsigned long magic; /* validate that structure layout is preserved */
};
struct instance_globals_n {
@@ -696,7 +694,6 @@ struct instance_globals_n {
short nocreate4;
boolean havestate;
unsigned long magic; /* validate that structure layout is preserved */
};
struct instance_globals_o {
@@ -742,11 +739,9 @@ struct instance_globals_o {
/* restore.c */
struct fruit *oldfruit;
long omoves;
/* rumors.c */
int oracle_flg; /* -1=>don't use, 0=>need init, 1=>init done */
unsigned long *oracle_loc;
/* uhitm.c */
boolean override_confirmation; /* Used to flag attacks caused by
@@ -755,7 +750,6 @@ struct instance_globals_o {
boolean obj_zapped;
boolean havestate;
unsigned long magic; /* validate that structure layout is preserved */
};
struct instance_globals_p {
@@ -806,13 +800,11 @@ struct instance_globals_p {
/* new stuff */
boolean havestate;
unsigned long magic; /* validate that structure layout is preserved */
};
struct instance_globals_q {
boolean havestate;
unsigned long magic; /* validate that structure layout is preserved */
};
struct instance_globals_r {
@@ -841,7 +833,6 @@ struct instance_globals_r {
struct repo repo;
boolean havestate;
unsigned long magic; /* validate that structure layout is preserved */
};
struct instance_globals_s {
@@ -923,7 +914,6 @@ struct instance_globals_s {
int seethru; /* 'bubble' debugging: clouds and water don't block light */
boolean havestate;
unsigned long magic; /* validate that structure layout is preserved */
};
struct instance_globals_t {
@@ -949,8 +939,8 @@ struct instance_globals_t {
const char *this_title; /* title for inventory list of specific type */
/* muse.c */
int trapx;
int trapy;
coordxy trapx;
coordxy trapy;
/* rumors.c */
long true_rumor_size; /* rumor size variables are signed so that value -1
@@ -974,7 +964,6 @@ struct instance_globals_t {
int twohits; /* 0: single hit; 1: first of 2; 2: second of 2 */
boolean havestate;
unsigned long magic; /* validate that structure layout is preserved */
};
struct instance_globals_u {
@@ -994,7 +983,6 @@ struct instance_globals_u {
/* new stuff */
boolean havestate;
unsigned long magic; /* validate that structure layout is preserved */
};
struct instance_globals_v {
@@ -1031,7 +1019,6 @@ struct instance_globals_v {
struct sound_voice voice;
boolean havestate;
unsigned long magic; /* validate that structure layout is preserved */
};
struct instance_globals_w {
@@ -1040,6 +1027,9 @@ struct instance_globals_w {
int warn_obj_cnt; /* count of monsters meeting criteria */
long wailmsg;
/* do_wear.c */
uint8 wasinwater;
/* symbols.c */
nhsym warnsyms[WARNCOUNT]; /* the current warning display symbols */
@@ -1054,9 +1044,9 @@ struct instance_globals_w {
/* new */
struct win_settings wsettings; /* wintype.h */
long were_changes; /* were.c, allmain.c */
boolean havestate;
unsigned long magic; /* validate that structure layout is preserved */
};
struct instance_globals_x {
@@ -1077,7 +1067,6 @@ struct instance_globals_x {
coordxy xstart, xsize;
boolean havestate;
unsigned long magic; /* validate that structure layout is preserved */
};
struct instance_globals_y {
@@ -1095,7 +1084,6 @@ struct instance_globals_y {
coordxy ystart, ysize;
boolean havestate;
unsigned long magic; /* validate that structure layout is preserved */
};
struct instance_globals_z {
@@ -1112,7 +1100,6 @@ struct instance_globals_z {
* remember who zapped the wand. */
boolean havestate;
unsigned long magic; /* validate that structure layout is preserved */
};
struct instance_globals_saved_b {
@@ -1188,6 +1175,10 @@ struct instance_globals_saved_n {
struct instance_globals_saved_o {
/* rumors.c */
unsigned oracle_cnt; /* oracles are handled differently from rumors... */
unsigned long *oracle_loc;
/* other */
long omoves; /* level timestamp */
};
struct instance_globals_saved_p {

View File

@@ -728,7 +728,7 @@ enum glyph_offsets {
#define glyph_to_explosion(glyph) \
(glyph_is_explosion(glyph) ? (((glyph) - GLYPH_EXPLODE_OFF) % (S_expl_br - S_expl_tl + 1)) : 0)
#define glyph_to_warning(glyph) \
(glyph_is_warning(glyph) ? ((glyph) - GLYPH_WARNING_OFF) : NO_GLYPH)
(glyph_is_warning(glyph) ? ((glyph) - GLYPH_WARNING_OFF) : 0)
/*
* Return true if the given glyph is what we want. Note that bodies are

View File

@@ -39,7 +39,8 @@ enum level_region_types {
LR_BRANCH,
LR_TELE,
LR_UPTELE,
LR_DOWNTELE
LR_DOWNTELE,
LR_MONGEN,
};
typedef struct dest_area { /* non-stairway level change identifier */
@@ -187,66 +188,71 @@ struct linfo {
/* what the player knows about a single dungeon level */
/* initialized in mklev() */
struct mapseen_feat {
/* feature knowledge that must be calculated from levl array */
Bitfield(nfount, 2);
Bitfield(nsink, 2);
Bitfield(naltar, 2);
Bitfield(nthrone, 2);
Bitfield(ngrave, 2);
Bitfield(ntree, 2);
Bitfield(water, 2);
Bitfield(lava, 2);
Bitfield(ice, 2);
/* calculated from rooms array */
Bitfield(nshop, 2);
Bitfield(ntemple, 2);
/* altar alignment; MSA_NONE if there is more than one and
they aren't all the same */
Bitfield(msalign, 2);
Bitfield(shoptype, 5);
};
struct mapseen_flags {
Bitfield(notreachable, 1); /* can't get back to this level */
Bitfield(forgot, 1); /* player has forgotten about this level */
Bitfield(knownbones, 1); /* player aware of bones */
Bitfield(oracle, 1);
Bitfield(sokosolved, 1);
Bitfield(bigroom, 1);
Bitfield(castle, 1);
Bitfield(castletune, 1); /* add tune hint to castle annotation */
Bitfield(valley, 1);
Bitfield(msanctum, 1);
Bitfield(ludios, 1);
Bitfield(roguelevel, 1);
/* quest annotations: quest_summons is for main dungeon level
with entry portal and is reset once quest has been finished;
questing is for quest home (level 1) */
Bitfield(quest_summons, 1); /* heard summons from leader */
Bitfield(questing, 1); /* quest leader has unlocked quest stairs */
/* "gateway to sanctum" */
Bitfield(vibrating_square, 1); /* found vibrating square 'trap';
* flag cleared once the msanctum
* annotation has been added (on
* the next dungeon level; temple
* entered or high altar mapped) */
Bitfield(spare1, 1); /* not used */
};
struct mapseen_rooms {
Bitfield(seen, 1);
Bitfield(untended, 1); /* flag for shop without shk */
};
typedef struct mapseen {
struct mapseen *next; /* next map in the chain */
branch *br; /* knows about branch via taking it in goto_level */
d_level lev; /* corresponding dungeon level */
struct mapseen_feat {
/* feature knowledge that must be calculated from levl array */
Bitfield(nfount, 2);
Bitfield(nsink, 2);
Bitfield(naltar, 2);
Bitfield(nthrone, 2);
Bitfield(ngrave, 2);
Bitfield(ntree, 2);
Bitfield(water, 2);
Bitfield(lava, 2);
Bitfield(ice, 2);
/* calculated from rooms array */
Bitfield(nshop, 2);
Bitfield(ntemple, 2);
/* altar alignment; MSA_NONE if there is more than one and
they aren't all the same */
Bitfield(msalign, 2);
Bitfield(shoptype, 5);
} feat;
struct mapseen_flags {
Bitfield(notreachable, 1); /* can't get back to this level */
Bitfield(forgot, 1); /* player has forgotten about this level */
Bitfield(knownbones, 1); /* player aware of bones */
Bitfield(oracle, 1);
Bitfield(sokosolved, 1);
Bitfield(bigroom, 1);
Bitfield(castle, 1);
Bitfield(castletune, 1); /* add tune hint to castle annotation */
Bitfield(valley, 1);
Bitfield(msanctum, 1);
Bitfield(ludios, 1);
Bitfield(roguelevel, 1);
/* quest annotations: quest_summons is for main dungeon level
with entry portal and is reset once quest has been finished;
questing is for quest home (level 1) */
Bitfield(quest_summons, 1); /* heard summons from leader */
Bitfield(questing, 1); /* quest leader has unlocked quest stairs */
/* "gateway to sanctum" */
Bitfield(vibrating_square, 1); /* found vibrating square 'trap';
* flag cleared once the msanctum
* annotation has been added (on
* the next dungeon level; temple
* entered or high altar mapped) */
Bitfield(spare1, 1); /* not used */
} flags;
struct mapseen_feat feat;
struct mapseen_flags flags;
/* custom naming */
char *custom;
unsigned custom_lth;
struct mapseen_rooms {
Bitfield(seen, 1);
Bitfield(untended, 1); /* flag for shop without shk */
} msrooms[(MAXNROFROOMS + 1) * 2]; /* same size as svr.rooms[] */
struct mapseen_rooms msrooms[(MAXNROFROOMS + 1) * 2]; /* same size as svr.rooms[] */
/* dead heroes; might not have graves or ghosts */
struct cemetery *final_resting_place; /* same as level.bonesinfo */
} mapseen;

View File

@@ -33,8 +33,9 @@ struct engr {
* even when hero isn't (so behaves similarly
* to how Elbereth did in 3.4.3) */
Bitfield(nowipeout, 1); /* this engraving will not degrade */
Bitfield(eread, 1); /* the engraving text has been read or felt */
/* 5 free bits */
Bitfield(eread, 1); /* refers to the engaving text: read or felt */
Bitfield(erevealed, 1); /* refers to engraving map symbol: revealed */
/* 4 free bits */
};
#define newengr(lth) \
@@ -46,8 +47,7 @@ struct engr {
#define spot_shows_engravings(x,y) \
(levl[(x)][(y)].typ == CORR \
|| levl[(x)][(y)].typ == SCORR \
|| levl[(x)][(y)].typ == ICE \
|| levl[(x)][(y)].typ == ROOM )
|| levl[(x)][(y)].typ == ROOM)
#endif /* ENGRAVE_H */

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 extern.h $NHDT-Date: 1723580890 2024/08/13 20:28:10 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1435 $ */
/* NetHack 3.7 extern.h $NHDT-Date: 1738638877 2025/02/03 19:14:37 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1476 $ */
/* Copyright (c) Steve Creps, 1988. */
/* NetHack may be freely redistributed. See license for details. */
@@ -67,6 +67,10 @@
*
*/
#ifndef ARTIFACT_H
#include "artifact.h"
#endif
/* ### alloc.c ### */
#if 0
@@ -126,7 +130,9 @@ extern void use_unicorn_horn(struct obj **);
extern boolean tinnable(struct obj *) NONNULLPTRS;
extern void reset_trapset(void);
extern int use_whip(struct obj *) NONNULLPTRS;
extern boolean could_pole_mon(void);
extern int use_pole(struct obj *, boolean) NONNULLPTRS;
extern void maybe_dunk_boulders(coordxy, coordxy);
extern void fig_transform(union any *, long) NONNULLARG1;
extern int unfixable_trouble_count(boolean);
@@ -136,7 +142,7 @@ extern void init_artifacts(void);
extern void save_artifacts(NHFILE *);
extern void restore_artifacts(NHFILE *);
extern const char *artiname(int);
extern struct obj *mk_artifact(struct obj *, aligntyp);
extern struct obj *mk_artifact(struct obj *, aligntyp, uchar, boolean);
extern const char *artifact_name(const char *, short *, boolean) NONNULLARG1;
extern boolean exist_artifact(int, const char *) NONNULLPTRS;
extern void artifact_exists(struct obj *, const char *, boolean, unsigned) ;
@@ -181,6 +187,7 @@ extern void mkot_trap_warn(void);
extern boolean is_magic_key(struct monst *, struct obj *);
extern struct obj *has_magic_key(struct monst *);
extern boolean is_art(struct obj *, int);
extern boolean permapoisoned(struct obj *);
/* ### attrib.c ### */
@@ -246,6 +253,8 @@ extern void savebones(int, time_t, struct obj *);
extern int getbones(void);
extern boolean bones_include_name(const char *) NONNULLARG1;
extern void fix_ghostly_obj(struct obj *) NONNULLARG1;
extern void newebones(struct monst *) NONNULLARG1;
extern void free_ebones(struct monst *) NONNULLARG1;
/* ### botl.c ### */
@@ -301,6 +310,28 @@ extern boolean friday_13th(void);
extern int night(void);
extern int midnight(void);
/* ### cfgfiles.c ### */
#if !defined(CROSSCOMPILE) || defined(CROSSCOMPILE_TARGET)
extern int l_get_config_errors(lua_State *) NONNULLARG1;
#endif
extern int do_write_config_file(void);
extern boolean parse_config_line(char *) NONNULLARG1;
#ifdef USER_SOUNDS
extern boolean can_read_file(const char *) NONNULLARG1;
#endif
extern void config_error_init(boolean, const char *, boolean);
extern void config_erradd(const char *);
extern int config_error_done(void);
/* arg1 of read_config_file can be NULL to pass through
* to fopen_config_file() to mean 'use the default config file name' */
extern boolean read_config_file(const char *, int);
extern boolean parse_conf_str(const char *str, boolean (*proc)(char *));
extern boolean parse_conf_file(FILE *fp, boolean (*proc)(char *arg));
extern void set_configfile_name(const char *);
extern char *get_configfile(void);
extern const char *get_default_configfile(void);
/* ### coloratt.c ### */
extern char *color_attr_to_str(color_attr *);
@@ -394,8 +425,10 @@ extern char extcmd_initiator(void);
extern int doextcmd(void);
extern struct ext_func_tab *extcmds_getentry(int);
extern int count_bind_keys(void);
extern int count_autocompletions(void);
extern void get_changed_key_binds(strbuf_t *);
extern void handler_rebind_keys(void);
extern void handler_change_autocompletions(void);
extern int extcmds_match(const char *, int, int **);
extern const char *key2extcmddesc(uchar);
extern boolean bind_specialkey(uchar, const char *);
@@ -411,7 +444,7 @@ extern int enter_explore_mode(void);
extern boolean bind_mousebtn(int, const char *);
extern boolean bind_key(uchar, const char *);
extern void dokeylist(void);
extern coordxy xytod(coordxy, coordxy);
extern int xytod(coordxy, coordxy);
extern void dtoxy(coord *, int);
extern int movecmd(char, int);
extern int dxdy_moveok(void);
@@ -730,12 +763,14 @@ extern int remarm_swapwep(void);
extern int destroy_arm(struct obj *);
extern void adj_abon(struct obj *, schar) NONNULLARG1;
extern boolean inaccessible_equipment(struct obj *, const char *, boolean);
extern int any_worn_armor_ok(struct obj *);
extern int count_worn_armor(void);
/* ### dog.c ### */
extern void newedog(struct monst *) NONNULLARG1;
extern void free_edog(struct monst *) NONNULLARG1;
extern void initedog(struct monst *) NONNULLARG1;
extern void initedog(struct monst *, boolean) NONNULLARG1;
extern struct monst *make_familiar(struct obj *, coordxy, coordxy, boolean);
extern struct monst *makedog(void);
extern void update_mlstmv(void);
@@ -757,7 +792,7 @@ extern struct obj *droppables(struct monst *) NONNULLARG1;
extern int dog_nutrition(struct monst *, struct obj *) NONNULLPTRS;
extern int dog_eat(struct monst *, struct obj *,
coordxy, coordxy, boolean) NONNULLPTRS;
extern int pet_ranged_attk(struct monst *) NONNULLARG1;
extern int pet_ranged_attk(struct monst *, boolean) NONNULLARG1;
extern int dog_move(struct monst *, int) NONNULLARG1;
extern boolean could_reach_item(struct monst *, coordxy, coordxy) NONNULLARG1;
extern void finish_meating(struct monst *) NONNULLARG1;
@@ -940,20 +975,21 @@ extern char *build_english_list(char *) NONNULLARG1;
/* ### engrave.c ### */
extern char *random_engraving(char *) NONNULLARG1;
extern char *random_engraving(char *, char *) NONNULLARG12;
extern void wipeout_text(char *, int, unsigned) NONNULLARG1;
extern boolean can_reach_floor(boolean);
extern void cant_reach_floor(coordxy, coordxy, boolean, boolean);
extern void cant_reach_floor(coordxy, coordxy, boolean, boolean, boolean);
extern struct engr *engr_at(coordxy, coordxy);
extern struct engr *sengr_at(const char *, coordxy, coordxy, boolean) NONNULLARG1;
extern void u_wipe_engr(int);
extern void wipe_engr_at(coordxy, coordxy, xint16, boolean);
extern void read_engr_at(coordxy, coordxy);
extern void make_engr_at(coordxy, coordxy, const char *, long, int) NONNULLARG3;
extern void make_engr_at(coordxy, coordxy, const char *, const char *, long, int) NONNULLARG3;
extern void del_engr_at(coordxy, coordxy);
extern int freehand(void);
extern int doengrave(void);
extern void sanitize_engravings(void);
extern void forget_engravings(void);
extern void engraving_sanity_check(void);
extern void save_engravings(NHFILE *) NONNULLARG1;
extern void rest_engravings(NHFILE *) NONNULLARG1;
@@ -964,6 +1000,7 @@ extern void make_grave(coordxy, coordxy, const char *);
extern void disturb_grave(coordxy, coordxy);
extern void see_engraving(struct engr *) NONNULLARG1;
extern void feel_engraving(struct engr *) NONNULLARG1;
extern boolean engr_can_be_felt(struct engr *) NONNULLARG1;
/* ### exper.c ### */
@@ -994,15 +1031,12 @@ extern void makerogueghost(void);
/* ### files.c ### */
extern const char *nh_basename(const char *, boolean) NONNULLARG1;
#if !defined(CROSSCOMPILE) || defined(CROSSCOMPILE_TARGET)
extern int l_get_config_errors(lua_State *) NONNULLARG1;
#endif
extern char *fname_encode(const char *, char,
char *, char *, int) NONNULLPTRS;
extern char *fname_decode(char, char *, char *, int) NONNULLPTRS;
extern const char *fqname(const char *, int, int);
extern FILE *fopen_datafile(const char *, const char *, int) NONNULLPTRS;
extern void zero_nhfile(NHFILE *) NONNULLARG1;
extern void init_nhfile(NHFILE *) NONNULLARG1;
extern void close_nhfile(NHFILE *) NONNULLARG1;
extern void rewind_nhfile(NHFILE *) NONNULLARG1;
extern void set_levelfile_name(char *, int) NONNULLARG1;
@@ -1025,6 +1059,7 @@ extern void set_error_savefile(void);
extern NHFILE *create_savefile(void);
extern NHFILE *open_savefile(void);
extern int delete_savefile(void);
extern NHFILE *get_freeing_nhfile(void);
extern NHFILE *restore_saved_game(void);
extern int check_panic_save(void);
#ifdef SELECTSAVED
@@ -1034,22 +1069,14 @@ extern char **get_saved_games(void);
extern void free_saved_games(char **);
extern void nh_compress(const char *);
extern void nh_uncompress(const char *);
extern void nh_sfconvert(const char *);
extern void nh_sfunconvert(const char *);
extern int delete_convertedfile(const char *);
extern void free_convert_filenames(void);
extern boolean lock_file(const char *, int, int) NONNULLARG1;
extern void unlock_file(const char *) NONNULLARG1;
extern int do_write_config_file(void);
extern boolean parse_config_line(char *) NONNULLARG1;
#ifdef USER_SOUNDS
extern boolean can_read_file(const char *) NONNULLARG1;
#endif
extern void config_error_init(boolean, const char *, boolean);
extern void config_erradd(const char *);
extern int config_error_done(void);
/* arg1 of read_config_file can be NULL to pass through
* to fopen_config_file() to mean 'use the default config file name' */
extern boolean read_config_file(const char *, int);
extern void check_recordfile(const char *);
extern void read_wizkit(void);
extern boolean parse_conf_str(const char *str, boolean (*proc)(char *));
extern int read_sym_file(int);
extern void paniclog(const char *, const char *) NONNULLPTRS;
extern void testinglog(const char *, const char *, const char *);
@@ -1065,11 +1092,13 @@ extern int nhclose(int);
#ifdef DEBUG
extern boolean debugcore(const char *, boolean);
#endif
extern void reveal_paths(void);
extern void reveal_paths(int);
extern boolean read_tribute(const char *, const char *, int, char *, int,
unsigned);
extern boolean Death_quote(char *, int) NONNULLARG1;
extern void livelog_add(long ll_type, const char *) NONNULLARG2;
ATTRNORETURN extern void do_deferred_showpaths(int) NORETURN;
extern boolean contains_directory(const char *);
/* ### fountain.c ### */
@@ -1168,6 +1197,7 @@ extern boolean in_town(coordxy, coordxy);
extern void check_special_room(boolean);
extern int dopickup(void);
extern void lookaround(void);
extern boolean doorless_door(coordxy, coordxy);
extern boolean crawl_destination(coordxy, coordxy);
extern int monster_nearby(void);
extern void end_running(boolean);
@@ -1182,6 +1212,7 @@ extern int near_capacity(void);
extern int calc_capacity(int);
extern int max_capacity(void);
extern boolean check_capacity(const char *);
extern void dump_weights(void);
extern int inv_cnt(boolean);
/* sometimes money_cnt(gi.invent) which can be null */
extern long money_cnt(struct obj *) NO_NNARGS;
@@ -1324,6 +1355,7 @@ extern void silly_thing(const char *, struct obj *) NONNULLARG1;
extern void sync_perminvent(void);
extern void perm_invent_toggled(boolean negated);
extern void prepare_perminvent(winid window);
extern struct obj *carrying_stoning_corpse(void);
/* ### ioctl.c ### */
@@ -1431,6 +1463,7 @@ extern void mkmonmoney(struct monst *, long) NONNULLARG1;
extern int bagotricks(struct obj *, boolean, int *);
extern boolean propagate(int, boolean, boolean);
extern void summon_furies(int);
extern void dump_mongen(void);
/* ### mcastu.c ### */
@@ -1474,6 +1507,7 @@ extern struct monst *cloneu(void);
extern void expels(struct monst *, struct permonst *, boolean) NONNULLARG12;
extern struct attack *getmattk(struct monst *, struct monst *, int, int *,
struct attack *) NONNULLARG12;
extern boolean mtrapped_in_pit(struct monst *) NONNULLARG1;
extern int mattacku(struct monst *) NONNULLARG1;
boolean diseasemu(struct permonst *) NONNULLARG1;
boolean u_slip_free(struct monst *, struct attack *) NONNULLARG12;
@@ -1483,6 +1517,11 @@ extern int gazemu(struct monst *, struct attack *) NONNULLARG12;
extern void mdamageu(struct monst *, int) NONNULLARG1;
extern int could_seduce(struct monst *, struct monst *, struct attack *) NONNULLARG12;
extern int doseduce(struct monst *) NONNULLARG1;
extern boolean mon_avoiding_this_attack(struct monst *, int) NONNULLARG1;
/* extern boolean ranged_attk_assessed(struct monst *mtmp,
boolean (*assessfunct)(struct monst *, int)) NONNULLARG1;
*/
extern boolean ranged_attk_available(struct monst *mtmp) NONNULLARG1;
/* ### minion.c ### */
@@ -1504,9 +1543,11 @@ extern void gain_guardian_angel(void);
/* ### mklev.c ### */
extern void sort_rooms(void);
extern void add_room(int, int, int, int, boolean, schar, boolean);
extern void add_subroom(struct mkroom *, int, int, int, int, boolean, schar,
boolean) NONNULLARG1;
extern void add_room(coordxy, coordxy, coordxy, coordxy,
boolean, schar, boolean);
extern void add_subroom(struct mkroom *,
coordxy, coordxy, coordxy, coordxy,
boolean, schar, boolean) NONNULLARG1;
extern void free_luathemes(enum lua_theme_group);
extern void makecorridors(void);
extern void add_door(coordxy, coordxy, struct mkroom *) NONNULLARG3;
@@ -1532,8 +1573,8 @@ extern void mineralize(int, int, int, int, boolean);
/* ### mkmap.c ### */
extern void flood_fill_rm(int, int, int, boolean, boolean);
extern void remove_rooms(int, int, int, int);
extern void flood_fill_rm(coordxy, coordxy, int, boolean, boolean);
extern void remove_rooms(coordxy, coordxy, coordxy, coordxy);
extern boolean litstate_rnd(int);
/* ### mkmaze.c ### */
@@ -1552,6 +1593,7 @@ extern void bound_digging(void);
extern void mkportal(coordxy, coordxy, xint16, xint16);
extern boolean bad_location(coordxy, coordxy, coordxy, coordxy, coordxy,
coordxy);
extern boolean is_exclusion_zone(xint16, coordxy, coordxy);
/* dungeon.c u_on_rndspot() passes NULL final arg to place_lregion() */
extern void place_lregion(coordxy, coordxy, coordxy, coordxy, coordxy,
coordxy, coordxy, coordxy, xint16, d_level *) NO_NNARGS;
@@ -1596,6 +1638,8 @@ extern void costly_alteration(struct obj *, int) NONNULLARG1;
extern void clear_dknown(struct obj *);
extern void unknow_object(struct obj *);
extern struct obj *mksobj(int, boolean, boolean) NONNULL;
extern boolean stone_object_type(unsigned);
extern boolean stone_furniture_type(unsigned);
extern int bcsign(struct obj *) NONNULLARG1;
extern int weight(struct obj *) NONNULLARG1;
extern struct obj *mkgold(long, coordxy, coordxy);
@@ -1740,6 +1784,7 @@ extern struct monst *get_iter_mons(boolean (*)(struct monst *));
extern struct monst *get_iter_mons_xy(boolean (*)(struct monst *,
coordxy, coordxy),
coordxy, coordxy);
extern int healmon(struct monst *, int, int) NONNULLARG1;
extern void rescham(void);
extern void restartcham(void);
extern void restore_cham(struct monst *) NONNULLARG1;
@@ -1767,6 +1812,10 @@ extern void dealloc_mextra(struct monst *);
extern boolean usmellmon(struct permonst *);
extern void mimic_hit_msg(struct monst *, short);
extern void adj_erinys(unsigned);
extern void see_monster_closeup(struct monst *, boolean) NONNULLARG1;
extern void see_nearby_monsters(void);
extern void shieldeff_mon(struct monst *) NONNULLARG1;
extern void flash_mon(struct monst *) NONNULLARG1;
/* ### mondata.c ### */
@@ -1776,6 +1825,7 @@ extern boolean attacktype(struct permonst *, int) NONNULLARG1;
extern boolean noattacks(struct permonst *) NONNULLARG1;
extern boolean poly_when_stoned(struct permonst *) NONNULLARG1;
extern boolean defended(struct monst *, int) NONNULLARG1;
extern boolean Resists_Elem(struct monst *, int) NONNULLARG1;
extern boolean resists_drli(struct monst *) NONNULLARG1;
extern boolean resists_magm(struct monst *) NONNULLARG1;
extern boolean resists_blnd(struct monst *) NONNULLARG1;
@@ -1926,6 +1976,7 @@ extern int dosuspend(void);
extern void nt_regularize(char *);
extern int(*nt_kbhit)(void);
extern void Delay(int);
boolean get_user_home_folder(char *, size_t);
# ifdef CRASHREPORT
struct CRctxt;
extern struct CRctxt *ctxp;
@@ -2065,12 +2116,7 @@ extern void tutorial(boolean);
#endif /* MAKEDEFS_C MDLIB_C CPPREGEX_C */
/* ### {cpp,pmatch,posix}regex.c ### */
extern struct nhregex *regex_init(void);
extern boolean regex_compile(const char *, struct nhregex *) NONNULLARG1;
extern char *regex_error_desc(struct nhregex *, char *) NONNULLARG2;
extern boolean regex_match(const char *, struct nhregex *) NO_NNARGS;
extern void regex_free(struct nhregex *) NONNULLARG1;
#include "nhregex.h"
#if !defined(MAKEDEFS_C) && !defined(MDLIB_C) && !defined(CPPREGEX_C)
@@ -2083,6 +2129,7 @@ extern void consoletty_open(int);
extern void consoletty_rubout(void);
extern int tgetch(void);
extern int console_poskey(coordxy *, coordxy *, int *);
void console_g_putch(int in_ch);
extern void set_output_mode(int);
extern void synch_cursor(void);
extern void nethack_enter_consoletty(void);
@@ -2246,6 +2293,10 @@ extern boolean msgtype_parse_add(char *) NONNULLARG1;
extern int msgtype_type(const char *, boolean) NONNULLARG1;
extern void hide_unhide_msgtypes(boolean, int);
extern void msgtype_free(void);
extern void options_free_window_colors(void);
#ifdef TTY_PERM_INVENT
extern void check_perm_invent_again(void);
#endif
/* ### pager.c ### */
@@ -2283,7 +2334,14 @@ extern int getlock(void);
extern const char *get_portable_device(void);
#endif
/* ### pcsys.c ### */
/* ### pcsys.c, windsys.c ### */
#if defined(MICRO) || defined(WIN32)
ATTRNORETURN extern void nethack_exit(int) NORETURN;
#else
#define nethack_exit exit
#endif
/* ### pcsys.c ### */
#if defined(MICRO) || defined(WIN32)
extern void flushout(void);
@@ -2355,6 +2413,7 @@ extern int loot_mon(struct monst *, int *, boolean *) NO_NNARGS;
extern int dotip(void);
extern struct autopickup_exception *check_autopickup_exceptions(struct obj *) NONNULLARG1;
extern boolean autopick_testobj(struct obj *, boolean) NONNULLARG1;
extern boolean u_safe_from_fatal_corpse(struct obj *obj, int) NONNULLARG1;
/* ### pline.c ### */
@@ -2621,16 +2680,20 @@ extern int dorecover(NHFILE *) NONNULLARG1;
extern void restcemetery(NHFILE *, struct cemetery **) NONNULLARG12;
extern void trickery(char *) NO_NNARGS;
extern void getlev(NHFILE *, int, xint8) NONNULLARG1;
extern void get_plname_from_file(NHFILE *, char *) NONNULLARG12;
extern void get_plname_from_file(NHFILE *, char *, boolean) NONNULLARG12;
#ifdef SELECTSAVED
extern int restore_menu(winid);
#endif
extern void minit(void);
extern boolean lookup_id_mapping(unsigned, unsigned *) NONNULLARG2;
extern int validate(NHFILE *, const char *, boolean) NONNULLARG1;
/* extern void reset_restpref(void); */
/* extern void set_restpref(const char *); */
/* extern void set_savepref(const char *); */
#ifdef SFCTOOL
void rest_bubbles(NHFILE *);
void restore_gamelog(NHFILE *);
boolean restgamestate(NHFILE *);
void restore_msghistory(NHFILE *);
#endif
/* ### rip.c ### */
@@ -2776,11 +2839,7 @@ extern void bufoff(int);
extern void bflush(int);
extern void bwrite(int, const genericptr_t, unsigned) NONNULLARG2;
extern void mread(int, genericptr_t, unsigned) NONNULLARG2;
extern void minit(void);
extern void bclose(int);
#if defined(ZEROCOMP)
extern void zerocomp_bclose(int);
#endif
/* ### shk.c ### */
@@ -2894,6 +2953,7 @@ extern void whimper(struct monst *) NONNULLARG1;
extern void beg(struct monst *) NONNULLARG1;
extern const char *maybe_gasp(struct monst *) NONNULLARG1;
extern const char *cry_sound(struct monst *) NONNULLARG1;
extern int domonnoise(struct monst *) NONNULLARG1;
extern int dotalk(void);
extern int tiphat(void);
#ifdef USER_SOUNDS
@@ -2918,6 +2978,7 @@ extern char *get_sound_effect_filename(int32_t seidint,
extern char *base_soundname_to_filename(char *, char *, size_t, int32_t) NONNULLARG1;
extern void set_voice(struct monst *, int32_t, int32_t, int32_t) NO_NNARGS;
extern void sound_speak(const char *) NO_NNARGS;
extern enum soundlib_ids soundlib_id_from_opt(char *);
/* ### sp_lev.c ### */
@@ -2936,7 +2997,7 @@ extern void flip_level_rnd(int, boolean);
extern boolean check_room(coordxy *, coordxy *, coordxy *, coordxy *, boolean) NONNULLPTRS;
extern boolean create_room(coordxy, coordxy, coordxy, coordxy,
coordxy, coordxy, xint16, xint16);
extern boolean dig_corridor(coord *, coord *, boolean, schar, schar) NONNULLARG12;
extern boolean dig_corridor(coord *, coord *, int *, boolean, schar, schar) NONNULLARG12;
extern void fill_special_room(struct mkroom *) NO_NNARGS;
extern void wallify_map(coordxy, coordxy, coordxy, coordxy);
extern boolean load_special(const char *) NONNULLARG1;
@@ -3025,7 +3086,7 @@ extern struct obj *findgold(struct obj *) NO_NNARGS;
extern void rider_cant_reach(void);
extern boolean can_saddle(struct monst *) NONNULLARG1;
extern int use_saddle(struct obj *) NONNULLARG1;
extern void put_saddle_on_mon(struct obj *, struct monst *) NONNULLARG12;
extern void put_saddle_on_mon(struct obj *, struct monst *) NONNULLARG2;
extern boolean can_ride(struct monst *) NONNULLARG1;
extern int doride(void);
extern boolean mount_steed(struct monst *, boolean) NO_NNARGS;
@@ -3078,6 +3139,8 @@ extern boolean goodpos(coordxy, coordxy, struct monst *,
mmflags_nht) NO_NNARGS;
extern boolean enexto(coord *, coordxy, coordxy,
struct permonst *) NONNULLARG1;
extern boolean enexto_gpflags(coord *, coordxy, coordxy, struct permonst *,
mmflags_nht) NONNULLARG1;
extern boolean enexto_core(coord *, coordxy, coordxy, struct permonst *,
mmflags_nht) NONNULLARG1;
extern void teleds(coordxy, coordxy, int);
@@ -3085,6 +3148,7 @@ extern int collect_coords(coord *, coordxy, coordxy, int, unsigned,
boolean (*)(coordxy, coordxy)) NONNULLARG1;
extern boolean safe_teleds(int);
extern boolean teleport_pet(struct monst *, boolean) NONNULLARG1;
extern void tele_to_rnd_pet(void);
extern void tele(void);
extern void scrolltele(struct obj *) NO_NNARGS;
extern int dotelecmd(void);
@@ -3208,6 +3272,7 @@ extern void drain_en(int, boolean);
extern int dountrap(void);
extern int could_untrap(boolean, boolean);
extern void cnv_trap_obj(int, int, struct trap *, boolean) NONNULLARG3;
extern boolean into_vs_onto(int);
extern int untrap(boolean, coordxy, coordxy, struct obj *) NO_NNARGS;
extern boolean openholdingtrap(struct monst *, boolean *) NO_NNARGS;
extern boolean closeholdingtrap(struct monst *, boolean *) NO_NNARGS;
@@ -3350,6 +3415,7 @@ extern boolean mhitm_knockback(struct monst *, struct monst *,struct attack *,
extern int passive(struct monst *, struct obj *, boolean, boolean, uchar,
boolean) NONNULLARG1;
extern void passive_obj(struct monst *, struct obj *, struct attack *) NONNULLARG1;
extern void that_is_a_mimic(struct monst *, unsigned) NONNULLARG1;
extern void stumble_onto_mimic(struct monst *) NONNULLARG1;
extern int flash_hits_mon(struct monst *, struct obj *) NONNULLARG12;
extern void light_hits_gremlin(struct monst *, int) NONNULLARG1;
@@ -3367,6 +3433,7 @@ extern void append_slash(char *) NONNULLARG1;
extern boolean check_user_string(const char *) NONNULLARG1;
extern char *get_login_name(void);
extern unsigned long sys_random_seed(void);
ATTRNORETURN extern void after_opt_showpaths(const char *) NORETURN;
#endif /* UNIX */
/* ### unixtty.c ### */
@@ -3448,15 +3515,18 @@ extern int doextversion(void);
extern boolean comp_times(long);
#endif
extern boolean check_version(struct version_info *, const char *, boolean,
unsigned long) NONNULLARG12;
extern boolean uptodate(NHFILE *, const char *, unsigned long) NONNULLARG1;
extern void store_formatindicator(NHFILE *) NONNULLARG1;
unsigned long) NONNULLARG1;
extern int uptodate(NHFILE *, const char *, unsigned long) NONNULLARG1;
extern void store_version(NHFILE *) NONNULLARG1;
extern unsigned long get_feature_notice_ver(char *) NO_NNARGS;
extern unsigned long get_current_feature_ver(void);
extern const char *copyright_banner_line(int) NONNULL;
extern void early_version_info(boolean);
extern void dump_version_info(void);
extern void store_critical_bytes(NHFILE *) NONNULLARG1;
extern int compare_critical_bytes(NHFILE *, int *, unsigned long) NONNULLARG1;
extern int get_critical_size_count(void);
extern int validate(NHFILE *, const char *, boolean) NONNULLARG1;
/* ### video.c ### */
@@ -3475,12 +3545,14 @@ extern int assign_videocolors(char *) NONNULLARG1;
/* ### vision.c ### */
extern boolean get_viz_clear(int, int);
extern void vision_init(void);
extern int does_block(int, int, struct rm *) NONNULLARG3;
extern void vision_reset(void);
extern void vision_recalc(int);
extern void block_point(int, int);
extern void unblock_point(int, int);
extern void recalc_block_point(coordxy, coordxy);
extern boolean clear_path(int, int, int, int);
extern void do_clear_area(coordxy, coordxy, int,
void(*)(coordxy, coordxy, void *), genericptr_t);
@@ -3610,6 +3682,8 @@ extern int weapon_hit_bonus(struct obj *) NO_NNARGS;
extern int weapon_dam_bonus(struct obj *) NO_NNARGS;
extern void skill_init(const struct def_skill *) NONNULLARG1;
extern void setmnotwielded(struct monst *, struct obj *) NONNULLARG1;
extern const struct throw_and_return_weapon *autoreturn_weapon(struct obj *)
NONNULLARG1;
/* ### were.c ### */
@@ -3786,6 +3860,7 @@ extern boolean worm_cross(int, int, int, int);
extern int wseg_at(struct monst *, int, int) NO_NNARGS;
extern void flip_worm_segs_vertical(struct monst *, int, int) NONNULLARG1;
extern void flip_worm_segs_horizontal(struct monst *, int, int) NONNULLARG1;
extern void redraw_worm(struct monst *);
/* ### worn.c ### */

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 flag.h $NHDT-Date: 1715979826 2024/05/17 21:03:46 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.246 $ */
/* NetHack 3.7 flag.h $NHDT-Date: 1744860497 2025/04/16 19:28:17 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.251 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Michael Allison, 2006. */
/* NetHack may be freely redistributed. See license for details. */
@@ -224,6 +224,12 @@ struct accessibility_data {
a11y.mon_notices_blocked = 0; \
} } while(0)
enum debug_fuzzer_states {
fuzzer_off,
fuzzer_impossible_panic,
fuzzer_impossible_continue
};
/*
* Stuff that really isn't option or platform related and does not
* get saved and restored. They are set and cleared during the game
@@ -231,18 +237,23 @@ struct accessibility_data {
* and probably warrant a structure of their own elsewhere some day.
*/
struct instance_flags {
boolean query_menu; /* use a menu for yes/no queries */
boolean showdamage;
boolean defer_plname; /* X11 hack: askname() might not set svp.plname */
boolean fuzzerpending; /* fuzzing requested on command line but not active
* yet (to allow interactive initialization prior
* to input becoming taken over);
* True => enable fuzzer when entering moveloop */
boolean herecmd_menu; /* use menu when mouseclick on yourself */
boolean invis_goldsym; /* gold symbol is ' '? */
boolean in_lua; /* executing a lua script */
boolean lua_testing; /* doing lua tests */
boolean term_gone; /* terminal is gone, abort abort abort */
boolean nofollowers; /* level change ignores pets (for tutorial) */
boolean partly_eaten_hack; /* extra flag for xname() used when it's called
* indirectly so we can't use xname_flags() */
boolean query_menu; /* use a menu for yes/no queries */
boolean remember_getpos; /* save getpos() positioning in do-again queue */
boolean sad_feeling; /* unseen pet is dying */
boolean showdamage; /* extra message reporting damage hero has taken */
xint8 debug_fuzzer; /* fuzz testing */
int at_midnight; /* only valid during end of game disclosure */
int at_night; /* also only valid during end of game disclosure */
@@ -254,6 +265,8 @@ struct instance_flags {
int getloc_filter; /* GFILTER_foo */
int in_lava_effects; /* hack for Boots_off() */
int last_msg; /* indicator of last message player saw */
int menuobjsyms; /* value of 'menu_objsyms' option;
* ought to be in flags rather than iflags */
int override_ID; /* true to force full identification of objects */
int parse_config_file_src; /* hack for parse_config_line() */
int purge_monsters; /* # of dead monsters still on fmon list */
@@ -290,13 +303,13 @@ struct instance_flags {
*/
unsigned msg_history; /* hint: # of top lines to save */
int getpos_coords; /* show coordinates when getting cursor position */
int menuinvertmode; /* 0 = invert toggles every item;
1 = invert skips 'all items' item */
int menuinvertmode; /* 0 = invert toggles every item;
* 1 = invert skips 'all items' item */
color_attr menu_headings; /* CLR_ and ATR_ for menu headings */
uint32_t colorcount; /* store how many colors terminal is capable of */
boolean use_truecolor; /* force use of truecolor */
#ifdef ALTMETA
boolean altmeta; /* Alt-c sends ESC c rather than M-c */
boolean altmeta; /* Alt+c sends ESC c rather than M-c */
#endif
boolean autodescribe; /* autodescribe mode in getpos() */
boolean cbreak; /* in cbreak mode, rogue format */
@@ -305,7 +318,8 @@ struct instance_flags {
boolean echo; /* 1 to echo characters */
boolean force_invmenu; /* always menu when handling inventory */
boolean hilite_pile; /* mark piles of objects with a hilite */
boolean menu_head_objsym; /* Show obj symbol in menu headings */
boolean menu_head_objsym; /* Show obj symbol in menu headings; controlled
* by 'menuobjsyms' */
boolean menu_overlay; /* Draw menus over the map */
boolean menu_requested; /* Flag for overloaded use of 'm' prefix
* on some non-move commands */
@@ -313,6 +327,7 @@ struct instance_flags {
boolean news; /* print news */
boolean num_pad; /* use numbers for movement commands */
boolean perm_invent; /* display persistent inventory window */
boolean perm_invent_pending; /* need to try again */
boolean renameallowed; /* can change hero name during role selection */
boolean renameinprogress; /* we are changing hero name */
boolean sounds; /* master on/off switch for using soundlib */
@@ -323,6 +338,8 @@ struct instance_flags {
boolean tux_penalty; /* True iff hero is a monk and wearing a suit */
boolean use_background_glyph; /* use background glyph when appropriate */
boolean use_menu_color; /* use color in menus; only if wc_color */
boolean use_menu_glyphs; /* use object glyphs in menus, if the port
* supports it; controlled by 'menuobjsyms' */
#ifdef STATUS_HILITES
long hilite_delta; /* number of moves to leave a temp hilite lit */
long unhilite_deadline; /* time when oldest temp hilite should be unlit */

View File

@@ -6,8 +6,6 @@
#ifndef GLOBAL_H
#define GLOBAL_H
#include <stdio.h>
/*
* Files expected to exist in the playground directory (possibly inside
* a dlb container file).
@@ -117,16 +115,6 @@ typedef uchar nhsym;
#endif
#endif
#if 0
/* comment out to test effects of each #define -- these will probably
* disappear eventually
*/
#ifdef INTERNAL_COMP
#define RLECOMP /* run-length compression of levl array - JLee */
#define ZEROCOMP /* zero-run compression of everything - Olaf Seibert */
#endif
#endif
/* #define SPECIALIZATION */ /* do "specialized" version of new topology */
#ifdef BITFIELDS
@@ -359,25 +347,8 @@ struct version_info {
unsigned long incarnation; /* actual version number */
unsigned long feature_set; /* bitmask of config settings */
unsigned long entity_count; /* # of monsters and objects */
unsigned long struct_sizes1; /* size of key structs */
unsigned long struct_sizes2; /* size of more key structs */
};
struct savefile_info {
unsigned long sfi1; /* compression etc. */
unsigned long sfi2; /* miscellaneous */
unsigned long sfi3; /* thirdparty */
};
#ifdef NHSTDC
#define SFI1_EXTERNALCOMP (1UL)
#define SFI1_RLECOMP (1UL << 1)
#define SFI1_ZEROCOMP (1UL << 2)
#else
#define SFI1_EXTERNALCOMP (1L)
#define SFI1_RLECOMP (1L << 1)
#define SFI1_ZEROCOMP (1L << 2)
#endif
/* This is used to store some build-info data that used
to be present in makedefs-generated header file date.h */
@@ -393,8 +364,6 @@ struct nomakedefs_s {
unsigned long version_features;
unsigned long ignored_features;
unsigned long version_sanity1;
unsigned long version_sanity2;
unsigned long version_sanity3;
unsigned long build_time;
};
extern struct nomakedefs_s nomakedefs;
@@ -431,6 +400,8 @@ extern struct nomakedefs_s nomakedefs;
#define PL_CSIZ 32 /* sizeof pl_character */
#define PL_FSIZ 32 /* fruit name */
#define PL_PSIZ 63 /* player-given names for pets, other monsters, objects */
/* room for "name-role-race-gend-algn" plus 1 character playmode code */
#define PL_NSIZ_PLUS (PL_NSIZ + 4 * (1 + 3) + 1) /* 49 */
#define MAXDUNGEON 16 /* current maximum number of dungeons */
#define MAXLEVEL 32 /* max number of levels in one dungeon */
@@ -458,6 +429,7 @@ extern struct nomakedefs_s nomakedefs;
/* PANICTRACE: Always defined for NH_DEVEL_STATUS != NH_STATUS_RELEASED
but only for supported platforms. */
#ifndef NOPANICTRACE
#ifdef UNIX
#if (NH_DEVEL_STATUS != NH_STATUS_RELEASED)
/* see end.c */
@@ -468,6 +440,7 @@ extern struct nomakedefs_s nomakedefs;
#endif /* CROSS_TO_WASM | CROSS_TO_MSDOS */
#endif /* NH_DEVEL_STATUS != NH_STATUS_RELEASED */
#endif /* UNIX */
#endif /* !NOPANICTRACE */
/* The following are meaningless if PANICTRACE is not defined: */
#if defined(__linux__) && defined(__GLIBC__) && (__GLIBC__ >= 2)
@@ -480,6 +453,9 @@ extern struct nomakedefs_s nomakedefs;
#if !defined(CROSS_TO_WASM) /* no popen in WASM */
#define PANICTRACE_GDB
#endif
#ifdef CROSS_TO_WASM
#undef COMPRESS
#endif
#endif
/* Supply nethack_enter macro if not supplied by port */
@@ -509,7 +485,6 @@ extern struct nomakedefs_s nomakedefs;
#define C(c) (0x1f & (c))
#endif
#define unctrl(c) ((c) <= C('z') ? (0x60 | (c)) : (c))
#define unmeta(c) (0x7f & (c))
/* Game log message type flags */
@@ -596,4 +571,6 @@ typedef enum NHL_pcall_action {
NHLpa_impossible
} NHL_pcall_action;
#define SFCTOOL_BIT (1UL << 30)
#endif /* GLOBAL_H */

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 hack.h $NHDT-Date: 1725653009 2024/09/06 20:03:29 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.262 $ */
/* NetHack 3.7 hack.h $NHDT-Date: 1736530208 2025/01/10 09:30:08 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.266 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Pasi Kallinen, 2017. */
/* NetHack may be freely redistributed. See license for details. */
@@ -12,6 +12,7 @@
#include "lint.h"
#include "align.h"
#include "weight.h"
#include "dungeon.h"
#include "stairs.h"
#include "objclass.h"
@@ -29,13 +30,11 @@
#include "mkroom.h"
#include "obj.h"
#include "quest.h"
#include "rect.h"
#include "region.h"
#include "rm.h"
#include "selvar.h"
#include "sndprocs.h"
#include "spell.h"
#include "sym.h"
#include "sys.h"
#include "timeout.h"
#include "winprocs.h"
@@ -48,7 +47,6 @@
#define ON 1
#define OFF 0
#define BOLT_LIM 8 /* from this distance ranged attacks will be made */
#define MAX_CARR_CAP 1000 /* so that boulders can be heavier */
#define DUMMY { 0 } /* array initializer, letting [1..N-1] default */
#define DEF_NOTHING ' ' /* default symbol for NOTHING and UNEXPLORED */
@@ -67,9 +65,6 @@
#define CXN_ARTICLE 8 /* include a/an/the prefix */
#define CXN_NOCORPSE 16 /* suppress " corpse" suffix */
/* 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
@@ -347,7 +342,6 @@ enum digcheck_result {
DIGCHECK_FAIL_OBJ_POOL_OR_TRAP
};
/* Dismount: causes for why you are no longer riding */
enum dismount_types {
@@ -442,6 +436,8 @@ enum earlyarg {
, ARG_DUMPENUMS
#endif
, ARG_DUMPGLYPHIDS
, ARG_DUMPMONGEN
, ARG_DUMPWEIGHTS
#ifdef WIN32
, ARG_WINDOWS
#endif
@@ -673,6 +669,8 @@ struct mvitals {
uchar born;
uchar died;
uchar mvflags;
Bitfield(seen_close, 1);
Bitfield(photographed, 1);
};
@@ -767,13 +765,7 @@ struct role_filter {
boolean roles[NUM_ROLES + 1];
short mask;
};
enum saveformats {
invalid = 0,
historical = 1, /* entire struct, binary, as-is */
lendian = 2, /* each field, binary, little-endian */
ascii = 3 /* each field, ascii text (just proof of concept) */
};
#define NUM_RACES (5)
struct selectionvar {
int wid, hei;
@@ -796,6 +788,7 @@ struct sinfo {
int exiting; /* an exit handler is executing */
int saving; /* creating a save file */
int restoring; /* reloading a save file */
int freeingdata; /* in saveobjchn(), mode FREEING */
int in_getlev; /* in getlev() */
int in_moveloop; /* normal gameplay in progress */
int in_impossible; /* reporting a warning */
@@ -808,6 +801,7 @@ struct sinfo {
int in_sanity_check; /* for impossible() during sanity checking */
int config_error_ready; /* config_error_add is ready, available */
int beyond_savefile_load; /* set when past savefile loading */
int savefile_completed; /* savefile has completed writing */
#ifdef PANICLOG
int in_paniclog; /* writing a panicloc entry */
#endif
@@ -859,6 +853,20 @@ typedef struct strbuf {
char buf[256];
} strbuf_t;
enum stoning_checks {
st_gloves = 0x1, /* wearing gloves? */
st_corpse = 0x2, /* is it a corpse obj? */
st_petrifies = 0x4, /* does the corpse petrify on touch? */
st_resists = 0x8, /* do you have stoning resistance? */
st_all = (st_gloves | st_corpse | st_petrifies | st_resists)
};
struct throw_and_return_weapon {
short otyp;
int range;
Bitfield(tethered, 1);
};
struct trapinfo {
struct obj *tobj;
coordxy tx, ty;
@@ -886,6 +894,19 @@ typedef struct {
#define UTD_SKIP_SANITY1 0x04
#define UTD_SKIP_SAVEFILEINFO 0x08
#define UTD_WITHOUT_WAITSYNCH_PERFILE 0x10
#define UTD_QUIETLY 0x20
/* Values for savefile status */
#define SF_UPTODATE 0
#define SF_OUTDATED 1
#define SF_CRITICAL_BYTE_COUNT_MISMATCH 2
#define SF_DM_IL32LLP64_ON_ILP32LL64 3 /* Wind x64 savefile on x86 */
#define SF_DM_I32LP64_ON_ILP32LL64 4 /* Unix 64 savefile on x86 */
#define SF_DM_ILP32LL64_ON_I32LP64 5 /* x86 savefile on Unix 64 */
#define SF_DM_ILP32LL64_ON_IL32LLP64 6 /* x86 savefile on Wind x64 */
#define SF_DM_I32LP64_ON_IL32LLP64 7 /* Unix 64 savefile on Wind x64 */
#define SF_DM_IL32LLP64_ON_I32LP64 8 /* Wind x64 savefile on Unix 64 */
#define SF_DM_MISMATCH 9 /* generic savefile byte mismatch */
#define ENTITIES 2
struct valuable_data {
@@ -927,34 +948,49 @@ struct xlock_s {
boolean magic_key;
};
#define MAX_BMASK 4
/* NetHack ftypes */
#define NHF_LEVELFILE 1
#define NHF_SAVEFILE 2
#define NHF_BONESFILE 3
/* modes */
#define READING 0x0
#define COUNTING 0x1
#define WRITING 0x2
#define FREEING 0x4
#define MAX_BMASK 4
#define READING 0x0
#define COUNTING 0x01
#define WRITING 0x02
#define FREEING 0x04
#define CONVERTING 0x08
#define UNCONVERTING 0x10
#if 0
/* operations of the various saveXXXchn & co. routines */
#define perform_bwrite(nhfp) ((nhfp)->mode & (COUNTING | WRITING))
#define release_data(nhfp) ((nhfp)->mode & FREEING)
#endif
/* operations of the various saveXXXchn & co. routines */
#define update_file(nhfp) ((nhfp)->mode & (COUNTING | WRITING))
#define release_data(nhfp) ((nhfp)->mode & FREEING)
enum saveformats {
invalid = 0,
historical = 1, /* entire struct, binary, as-is */
exportascii = 2, /* each field written out as ascii text */
NUM_SAVEFORMATS
};
/* Content types for fieldlevel files */
struct fieldlevel_content {
boolean deflt; /* individual fields */
boolean binary; /* binary rather than text */
boolean json; /* JSON */
};
typedef struct {
struct nh_file {
int fd; /* for traditional structlevel binary writes */
int mode; /* holds READING, WRITING, or FREEING modes */
int mode; /* holds READING, WRITING, FREEING, CONVERTING modes */
int ftype; /* NHF_LEVELFILE, NHF_SAVEFILE, or NHF_BONESFILE */
int fnidx; /* index of procs for fieldlevel saves */
long count; /* holds current line count for default style file,
field count for binary style */
long rcount, /* read count since opening */
wcount; /* write count since opening */
boolean structlevel; /* traditional structure binary saves */
boolean fieldlevel; /* fieldlevel saves each field individually */
boolean addinfo; /* if set, some additional context info from core */
@@ -965,7 +1001,10 @@ typedef struct {
FILE *fplog; /* file pointer logfile */
FILE *fpdebug; /* file pointer debug info */
struct fieldlevel_content style;
} NHFILE;
struct nh_file *nhfpconvert;
};
typedef struct nh_file NHFILE;
/* Monster name articles */
#define ARTICLE_NONE 0
@@ -1142,6 +1181,10 @@ typedef uint32_t mmflags_nht; /* makemon MM_ flags */
#define MHID_ALTMON 4 /* if mimicking a monster, include that */
#define MHID_REGION 8 /* include region when mon is in one */
/* flags for that_is_a_mimic() */
#define MIM_REVEAL 1 /* seemimic() */
#define MIM_OMIT_WAIT 2 /* strip beginning from "Wait! That is a <foo>" */
/* flags for make_corpse() and mkcorpstat(); 0..7 are recorded in obj->spe */
#define CORPSTAT_NONE 0x00
#define CORPSTAT_GENDER 0x03 /* 0x01 | 0x02 */
@@ -1247,11 +1290,12 @@ typedef uint32_t mmflags_nht; /* makemon MM_ flags */
/* flag for suppressing perm_invent update when name gets assigned */
#define ONAME_SKIP_INVUPD 0x0200U /* don't call update_inventory() */
/* Flags to control find_mid() */
/* Flags to control find_mid() and whereis_mon() */
#define FM_FMON 0x01 /* search the fmon chain */
#define FM_MIGRATE 0x02 /* search the migrating monster chain */
#define FM_MYDOGS 0x04 /* search gm.mydogs */
#define FM_EVERYWHERE (FM_FMON | FM_MIGRATE | FM_MYDOGS)
#define FM_YOU 0x08 /* check for gy.youmonst */
#define FM_EVERYWHERE (FM_YOU | FM_FMON | FM_MIGRATE | FM_MYDOGS)
/* Flags to control pick_[race,role,gend,align] routines in role.c */
#define PICK_RANDOM 0
@@ -1498,17 +1542,16 @@ typedef uint32_t mmflags_nht; /* makemon MM_ flags */
#define getlogin() ((char *) 0)
#endif /* MICRO */
/* The function argument to qsort() requires a particular
* calling convention under WINCE which is not the default
* in that environment.
*/
#if defined(WIN_CE)
#define QSORTCALLBACK __cdecl
#else
/* These may have been defined to platform-specific values in *conf.h
* or on the compiler command line from a hints file or Makefile */
#ifndef QSORTCALLBACK
#define QSORTCALLBACK
#endif
#ifndef SIG_RET_TYPE
#define SIG_RET_TYPE void (*)(int)
#endif
#define DEVTEAM_EMAIL "devteam@nethack.org"
#define DEVTEAM_URL "https://www.nethack.org/"
@@ -1517,8 +1560,13 @@ typedef uint32_t mmflags_nht; /* makemon MM_ flags */
#include "nhlua.h"
#endif
#if !defined(RECOVER_C)
#include "extern.h"
#include "savefile.h"
#include "decl.h"
#endif /* RECOVER_C */
#endif /* HACK_H */

View File

@@ -78,7 +78,9 @@ extern void nh_snprintf_w_impossible(const char *func, int line, char *str,
extern unsigned Strlen_(const char *, const char *, int) NONNULLPTRS;
#endif
extern int unicodeval_to_utf8str(int, uint8 *, size_t);
extern boolean copy_bytes(int, int);
extern const char *datamodel(int);
extern const char *what_datamodel_is_this(int, int, int, int, int, int);
#endif /* HACKLIB_H */

View File

@@ -39,26 +39,29 @@
#define HAS_INTTYPES_H
#else /*!__DECC*/
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) \
&& !defined(HAS_STDINT_H)
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)
#if !defined(HAS_STDINT_H)
/* The compiler claims to conform to C99. Use stdint.h */
#define HAS_STDINT_H
#endif
#endif /* !HAS_STDINT_H */
#if !defined(HAS_INTTYPES_H)
/* The compiler claims to conform to C99. Use inttypes.h */
#define HAS_INTTYPES_H
#endif /* !HAS_INTTYPES_H */
#if defined(__GNUC__) && defined(__INT64_MAX__) && !defined(HAS_STDINT_H)
#define HAS_STDINT_H
#endif
#endif
#endif /* claims to be C99 */
#endif /*?__DECC*/
#ifdef HAS_STDINT_H
#include <stdint.h>
#define SKIP_STDINT_WORKAROUND
#else /*!stdint*/
#endif
#ifdef HAS_INTTYPES_H
#include <inttypes.h>
#define SKIP_STDINT_WORKAROUND
#endif
#endif /*?stdint*/
#endif /* HAS_INTTYPES_H */
#ifndef SKIP_STDINT_WORKAROUND /* !C99 */
/*
@@ -86,8 +89,13 @@ typedef unsigned int uint32_t;
64-bit integers, you should comment out USE_ISAAC64 in config.h so
that the previous RNG gets used instead. Then this file will be
inhibited and it won't matter what the int64_t and uint64_t lines are. */
#if defined(__cplusplus)
#include <stdint.h>
#else
typedef long long int int64_t;
typedef unsigned long long int uint64_t;
#endif
#endif /* !C99 */
@@ -101,6 +109,11 @@ typedef uint32_t uint32;
typedef int64_t int64;
typedef uint64_t uint64;
/* Also provide ushort, uint, ulong */
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
/* for non-negative L, calculate L * 10 + D, avoiding signed overflow;
yields -1 if overflow would have happened;
assumes compiler will optimize the constants */

View File

@@ -50,7 +50,7 @@
* src/makemon.c: if (mmflags & MM_XX) newXX(mtmp);
* your new code: mon = makemon(&mons[mnum], x, y, MM_XX);
*
* 7. Adjust size_monst() in src/cmd.c appropriately.
* 7. Adjust size_monst() in src/wizcmds.c appropriately.
* 8. Adjust dealloc_mextra() in src/mon.c to clean up
* properly during monst deallocation.
* 9. Adjust copy_mextra() in src/mon.c to make duplicate
@@ -75,6 +75,7 @@ struct fakecorridor {
};
struct egd {
unsigned parentmid; /* make clobber-detection possible */
int fcbeg, fcend; /* fcend: first unused pos */
int vroom; /* room number of the vault */
coordxy gdx, gdy; /* goal of guard's walk */
@@ -92,6 +93,7 @@ struct egd {
** formerly epri.h -- temple priest extension
*/
struct epri {
unsigned parentmid; /* make clobber-detection possible */
aligntyp shralign; /* alignment of priest's shrine */
schar shroom; /* index in rooms */
coord shrpos; /* position of shrine */
@@ -118,6 +120,7 @@ struct bill_x {
};
struct eshk {
unsigned parentmid; /* make clobber-detection possible */
long robbed; /* amount stolen by most recent customer */
long credit; /* amount credited to customer */
long debit; /* amount of debt for using unpaid items */
@@ -145,6 +148,7 @@ struct eshk {
** formerly emin.h -- minion extension
*/
struct emin {
unsigned parentmid; /* make clobber-detection possible */
aligntyp min_align; /* alignment of minion */
boolean renegade; /* hostile co-aligned priest or Angel */
};
@@ -165,6 +169,7 @@ enum dogfood_types {
};
struct edog {
unsigned parentmid; /* make clobber-detection possible */
long droptime; /* moment dog dropped object */
unsigned dropdist; /* dist of dropped obj from @ */
int apport; /* amount of training */
@@ -177,6 +182,22 @@ struct edog {
Bitfield(killed_by_u, 1); /* you attempted to kill him */
};
/***
** extension tracking a player's remnant monster (ghost, mummy etc.)
*/
struct ebones {
unsigned parentmid; /* make clobber-detection possible */
uchar role; /* index into roles[] */
uchar race; /* index into races[] */
align oldalign; /* character alignment */
uchar deathlevel; /* level when dying (m_lev may differ) */
schar luck; /* luck when dying */
short mnum; /* monster type */
Bitfield(female, 1); /* was female */
Bitfield(demigod, 1); /* had killed wiz or invoked */
Bitfield(crowned, 1); /* had been crowned */
};
/***
** mextra.h -- collection of all monster extensions
*/
@@ -187,6 +208,7 @@ struct mextra {
struct eshk *eshk;
struct emin *emin;
struct edog *edog;
struct ebones *ebones;
int mcorpsenm; /* obj->corpsenm for mimic posing as statue or corpse,
* obj->spe (fruit index) for one posing as a slime mold,
* or an alignment mask for one posing as an altar */
@@ -198,6 +220,7 @@ struct mextra {
#define ESHK(mon) ((mon)->mextra->eshk)
#define EMIN(mon) ((mon)->mextra->emin)
#define EDOG(mon) ((mon)->mextra->edog)
#define EBONES(mon) ((mon)->mextra->ebones)
#define MCORPSENM(mon) ((mon)->mextra->mcorpsenm)
#define has_mgivenname(mon) ((mon)->mextra && MGIVENNAME(mon))
@@ -206,6 +229,7 @@ struct mextra {
#define has_eshk(mon) ((mon)->mextra && ESHK(mon))
#define has_emin(mon) ((mon)->mextra && EMIN(mon))
#define has_edog(mon) ((mon)->mextra && EDOG(mon))
#define has_ebones(mon) ((mon)->mextra && EBONES(mon))
#define has_mcorpsenm(mon) ((mon)->mextra && MCORPSENM(mon) != NON_PM)
#endif /* MEXTRA_H */

View File

@@ -6,26 +6,28 @@
#ifndef MFNDPOS_H
#define MFNDPOS_H
#define ALLOW_MDISP 0x00001000L /* can displace a monster out of its way */
#define ALLOW_TRAPS 0x00020000L /* can enter traps */
#define ALLOW_U 0x00040000L /* can attack you */
#define ALLOW_M 0x00080000L /* can attack other monsters */
#define ALLOW_TM 0x00100000L /* can attack tame monsters */
/* clang-format off */
#define ALLOW_MDISP 0x00001000L /* can displace a monster out of its way */
#define ALLOW_TRAPS 0x00020000L /* can enter traps */
#define ALLOW_U 0x00040000L /* can attack you */
#define ALLOW_M 0x00080000L /* can attack other monsters */
#define ALLOW_TM 0x00100000L /* can attack tame monsters */
#define ALLOW_ALL (ALLOW_U | ALLOW_M | ALLOW_TM | ALLOW_TRAPS)
#define NOTONL 0x00200000L /* avoids direct line to player */
#define OPENDOOR 0x00400000L /* opens closed doors */
#define UNLOCKDOOR 0x00800000L /* unlocks locked doors */
#define BUSTDOOR 0x01000000L /* breaks any doors */
#define ALLOW_ROCK 0x02000000L /* pushes rocks */
#define ALLOW_WALL 0x04000000L /* walks thru walls */
#define ALLOW_DIG 0x08000000L /* digs */
#define ALLOW_BARS 0x10000000L /* may pass thru iron bars */
#define ALLOW_SANCT 0x20000000L /* enters temples */
#define ALLOW_SSM 0x40000000L /* ignores scare monster */
#define NOTONL 0x00200000L /* avoids direct line to player */
#define OPENDOOR 0x00400000L /* opens closed doors */
#define UNLOCKDOOR 0x00800000L /* unlocks locked doors */
#define BUSTDOOR 0x01000000L /* breaks any doors */
#define ALLOW_ROCK 0x02000000L /* pushes rocks */
#define ALLOW_WALL 0x04000000L /* walks thru walls */
#define ALLOW_DIG 0x08000000L /* digs */
#define ALLOW_BARS 0x10000000L /* may pass thru iron bars */
#define ALLOW_SANCT 0x20000000L /* enters temples */
#define ALLOW_SSM 0x40000000L /* ignores scare monster */
#ifdef NHSTDC
#define NOGARLIC 0x80000000UL /* hates garlic */
#define NOGARLIC 0x80000000UL /* hates garlic */
#else
#define NOGARLIC 0x80000000L /* hates garlic */
#define NOGARLIC 0x80000000L /* hates garlic */
#endif
/* clang-format on */
#endif /* MFNDPOS_H */

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 monst.h $NHDT-Date: 1678560511 2023/03/11 18:48:31 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.54 $ */
/* NetHack 3.7 monst.h $NHDT-Date: 1738640524 2025/02/03 19:42:04 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.67 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2016. */
/* NetHack may be freely redistributed. See license for details. */
@@ -99,12 +99,12 @@ struct monst {
short mnum; /* permanent monster index number */
short cham; /* if shapeshifter, orig mons[] idx goes here */
short movement; /* movement points (derived from permonst definition
and added effects */
* and added effects */
uchar m_lev; /* adjusted difficulty level of monster */
aligntyp malign; /* alignment of this monster, relative to the
player (positive = good to kill) */
* player (positive = good to kill) */
coordxy mx, my;
coordxy mux, muy; /* where the monster thinks you are */
coordxy mux, muy; /* where the monster thinks you are */
#define MTSZ 4
/* mtrack[0..2] is used to keep extra data when migrating the monster */
coord mtrack[MTSZ]; /* monster track */
@@ -112,11 +112,11 @@ struct monst {
unsigned mappearance; /* for undetected mimics and the wiz */
uchar m_ap_type; /* what mappearance is describing, m_ap_types */
schar mtame; /* level of tameness, implies peaceful */
schar mtame; /* level of tameness, implies peaceful */
unsigned short mintrinsics; /* low 8 correspond to mresists */
unsigned short mextrinsics; /* low 8 correspond to mresists */
unsigned long seen_resistance; /* M_SEEN_x; saw you resist an effect */
int mspec_used; /* monster's special ability attack timeout */
int mspec_used; /* monster's special ability attack timeout */
Bitfield(female, 1); /* is female */
Bitfield(minvis, 1); /* currently invisible */
@@ -156,14 +156,13 @@ struct monst {
Bitfield(ispriest, 1); /* is an aligned priest or high priest */
Bitfield(iswiz, 1); /* is the Wizard of Yendor */
#define MAX_NUM_WORMS 32 /* should be 2^(wormno bitfield size) */
Bitfield(wormno, 5); /* at most 31 worms on any level */
Bitfield(mtemplit, 1); /* temporarily seen; only valid during bhit() */
Bitfield(meverseen, 1); /* mon has been seen at some point */
Bitfield(mspotted, 1); /* mon is currently seen by hero */
#define MAX_NUM_WORMS 32 /* should be 2^(wormno bitfield size) */
unsigned long mstrategy; /* for monsters with mflag3: current strategy */
#ifdef NHSTDC
#define STRAT_APPEARMSG 0x80000000UL
@@ -180,12 +179,10 @@ struct monst {
#define STRAT_PLAYER 0x01000000L
#define STRAT_NONE 0x00000000L
#define STRAT_STRATMASK 0x0f000000L
#define STRAT_XMASK 0x00ff0000L
#define STRAT_YMASK 0x0000ff00L
/* mstrategy unused 0x00ffff00L */
#define STRAT_GOAL 0x000000ffL
#define STRAT_GOALX(s) ((coordxy) ((s & STRAT_XMASK) >> 16))
#define STRAT_GOALY(s) ((coordxy) ((s & STRAT_YMASK) >> 8))
coord mgoal; /* monster strategy, target location */
long mtrapseen; /* bitmap of traps we've been trapped in */
long mlstmv; /* for catching up with lost time */
long mstate; /* debugging info on monsters stored here */
@@ -268,22 +265,15 @@ struct monst {
#endif
#define mon_resistancebits(mon) \
((mon)->data->mresists | (mon)->mextrinsics | (mon)->mintrinsics)
#define resists_fire(mon) \
((mon_resistancebits(mon) & MR_FIRE) != 0)
#define resists_cold(mon) \
((mon_resistancebits(mon) & MR_COLD) != 0)
#define resists_sleep(mon) \
((mon_resistancebits(mon) & MR_SLEEP) != 0)
#define resists_disint(mon) \
((mon_resistancebits(mon) & MR_DISINT) != 0)
#define resists_elec(mon) \
((mon_resistancebits(mon) & MR_ELEC) != 0)
#define resists_poison(mon) \
((mon_resistancebits(mon) & MR_POISON) != 0)
#define resists_acid(mon) \
((mon_resistancebits(mon) & MR_ACID) != 0)
#define resists_ston(mon) \
((mon_resistancebits(mon) & MR_STONE) != 0)
#define resists_fire(mon) Resists_Elem(mon, FIRE_RES)
#define resists_cold(mon) Resists_Elem(mon, COLD_RES)
#define resists_sleep(mon) Resists_Elem(mon, SLEEP_RES)
#define resists_disint(mon) Resists_Elem(mon, DISINT_RES)
#define resists_elec(mon) Resists_Elem(mon, SHOCK_RES)
#define resists_poison(mon) Resists_Elem(mon, POISON_RES)
#define resists_acid(mon) Resists_Elem(mon, ACID_RES)
#define resists_ston(mon) Resists_Elem(mon, STONE_RES)
#define is_lminion(mon) \
(is_minion((mon)->data) && mon_aligntyp(mon) == A_LAWFUL)

View File

@@ -47,8 +47,10 @@
* Rule #1: monsters of a given class are contiguous in the
* mons[] array.
*
* Rule #2: monsters of a given class are presented in ascending
* order of strength.
* Rule #2: monsters of a given class are generally kept in
* the same order as in previous versions of NetHack
* (they used to be presented in ascending order of
* strength, but this rule no longer applies).
*
* Rule #3: monster frequency is included in the geno mask;
* the frequency can be from 0 to 7. 0's will also
@@ -97,7 +99,7 @@
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(1, 5, MS_BUZZ, MZ_TINY), MR_POISON, MR_POISON,
M1_ANIMAL | M1_FLY | M1_NOHANDS | M1_POIS, M2_HOSTILE | M2_FEMALE, 0,
5, CLR_YELLOW, KILLER_BEE),
6, CLR_YELLOW, KILLER_BEE),
MON(NAM("soldier ant"), S_ANT,
LVL(3, 18, 3, 0, 0), (G_GENO | G_SGROUP | 2),
A(ATTK(AT_BITE, AD_PHYS, 2, 4), ATTK(AT_STNG, AD_DRST, 3, 4),
@@ -105,7 +107,7 @@
SIZ(20, 5, MS_SILENT, MZ_TINY), MR_POISON, MR_POISON,
M1_ANIMAL | M1_NOHANDS | M1_OVIPAROUS | M1_POIS | M1_CARNIVORE,
M2_HOSTILE, 0,
6, CLR_BLUE, SOLDIER_ANT),
7, CLR_BLUE, SOLDIER_ANT),
MON(NAM("fire ant"), S_ANT,
LVL(3, 18, 3, 10, 0), (G_GENO | G_SGROUP | 1),
A(ATTK(AT_BITE, AD_PHYS, 2, 4), ATTK(AT_BITE, AD_FIRE, 2, 4),
@@ -215,8 +217,8 @@
SIZ(300, 250, MS_BARK, MZ_SMALL), 0, 0,
M1_ANIMAL | M1_NOHANDS | M1_CARNIVORE, M2_HOSTILE, M3_INFRAVISIBLE,
2, CLR_BROWN, COYOTE),
MON(NAM("werejackal"),
S_DOG, LVL(2, 12, 7, 10, -7), (G_NOGEN | G_NOCORPSE),
MON(NAM("werejackal"), S_DOG,
LVL(2, 12, 7, 10, -7), (G_NOGEN | G_NOCORPSE),
A(ATTK(AT_BITE, AD_WERE, 1, 4),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(300, 250, MS_BARK, MZ_SMALL), MR_POISON, 0,
@@ -271,7 +273,7 @@
M2_NOPOLY | M2_WERE | M2_HOSTILE, M3_INFRAVISIBLE,
7, CLR_GRAY, WEREWOLF),
MON(NAM("winter wolf cub"), S_DOG,
LVL(5, 12, 4, 0, -5),
LVL(5, 12, 4, 0, 0),
(G_NOHELL | G_GENO | G_SGROUP | 2),
A(ATTK(AT_BITE, AD_PHYS, 1, 8), ATTK(AT_BREA, AD_COLD, 1, 6),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
@@ -286,21 +288,21 @@
M1_ANIMAL | M1_NOHANDS | M1_CARNIVORE, M2_HOSTILE, M3_INFRAVISIBLE,
8, CLR_BLACK, WARG),
MON(NAM("winter wolf"), S_DOG,
LVL(7, 12, 4, 20, 0), (G_NOHELL | G_GENO | 1),
LVL(7, 12, 4, 20, -5), (G_NOHELL | G_GENO | 1),
A(ATTK(AT_BITE, AD_PHYS, 2, 6), ATTK(AT_BREA, AD_COLD, 2, 6),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(700, 300, MS_BARK, MZ_LARGE), MR_COLD, MR_COLD,
M1_ANIMAL | M1_NOHANDS | M1_CARNIVORE, M2_HOSTILE | M2_STRONG, 0,
9, CLR_CYAN, WINTER_WOLF),
MON(NAM("hell hound pup"), S_DOG,
LVL(7, 12, 4, 20, -5), (G_HELL | G_GENO | G_SGROUP | 1),
LVL(7, 12, 4, 20, 0), (G_HELL | G_GENO | G_SGROUP | 1),
A(ATTK(AT_BITE, AD_PHYS, 2, 6), ATTK(AT_BREA, AD_FIRE, 2, 6),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(200, 200, MS_BARK, MZ_SMALL), MR_FIRE, MR_FIRE,
M1_ANIMAL | M1_NOHANDS | M1_CARNIVORE, M2_HOSTILE, M3_INFRAVISIBLE,
9, CLR_RED, HELL_HOUND_PUP),
MON(NAM("hell hound"), S_DOG,
LVL(12, 14, 2, 20, 0), (G_HELL | G_GENO | 1),
LVL(12, 14, 2, 20, -5), (G_HELL | G_GENO | 1),
A(ATTK(AT_BITE, AD_PHYS, 3, 6), ATTK(AT_BREA, AD_FIRE, 3, 6),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(600, 300, MS_BARK, MZ_MEDIUM), MR_FIRE, MR_FIRE,
@@ -590,7 +592,7 @@
LVL(4, 0, 8, 10, 0), (G_GENO | 2),
A(ATTK(AT_NONE, AD_COLD, 0, 6),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(50, 20, MS_SILENT, MZ_MEDIUM), MR_COLD | MR_POISON,
SIZ(WT_JELLY, 20, MS_SILENT, MZ_MEDIUM), MR_COLD | MR_POISON,
MR_COLD | MR_POISON,
M1_BREATHLESS | M1_AMORPHOUS | M1_NOEYES | M1_NOLIMBS | M1_NOHEAD
| M1_MINDLESS | M1_NOTAKE,
@@ -600,7 +602,7 @@
LVL(5, 0, 8, 10, 0), (G_GENO | 1),
A(ATTK(AT_NONE, AD_ACID, 0, 6),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(50, 20, MS_SILENT, MZ_MEDIUM),
SIZ(WT_JELLY, 20, MS_SILENT, MZ_MEDIUM),
MR_ACID | MR_STONE, MR_ACID | MR_STONE,
M1_BREATHLESS | M1_AMORPHOUS | M1_NOEYES | M1_NOLIMBS | M1_NOHEAD
| M1_MINDLESS | M1_ACID | M1_NOTAKE,
@@ -610,7 +612,7 @@
LVL(6, 3, 8, 20, 0), (G_GENO | 2),
A(ATTK(AT_ENGL, AD_ACID, 3, 6), ATTK(AT_NONE, AD_ACID, 3, 6),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(50, 20, MS_SILENT, MZ_MEDIUM),
SIZ(WT_JELLY, 20, MS_SILENT, MZ_MEDIUM),
MR_ACID | MR_STONE, MR_ACID | MR_STONE,
M1_BREATHLESS | M1_AMORPHOUS | M1_NOEYES | M1_NOLIMBS | M1_NOHEAD
| M1_MINDLESS | M1_ACID | M1_NOTAKE,
@@ -701,14 +703,14 @@
LVL(3, 12, 9, 20, 0), (G_GENO | 2),
A(ATTK(AT_CLAW, AD_SITM, 0, 0), ATTK(AT_CLAW, AD_SEDU, 0, 0),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(600, 300, MS_SEDUCE, MZ_HUMAN), 0, 0, M1_HUMANOID | M1_TPORT,
SIZ(WT_NYMPH, 300, MS_SEDUCE, MZ_HUMAN), 0, 0, M1_HUMANOID | M1_TPORT,
M2_HOSTILE | M2_FEMALE | M2_COLLECT, M3_INFRAVISIBLE,
5, CLR_GREEN, WOOD_NYMPH),
MON(NAM("water nymph"), S_NYMPH,
LVL(3, 12, 9, 20, 0), (G_GENO | 2),
A(ATTK(AT_CLAW, AD_SITM, 0, 0), ATTK(AT_CLAW, AD_SEDU, 0, 0),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(600, 300, MS_SEDUCE, MZ_HUMAN), 0, 0,
SIZ(WT_NYMPH, 300, MS_SEDUCE, MZ_HUMAN), 0, 0,
M1_HUMANOID | M1_TPORT | M1_SWIM, M2_HOSTILE | M2_FEMALE | M2_COLLECT,
M3_INFRAVISIBLE,
5, CLR_BLUE, WATER_NYMPH),
@@ -716,7 +718,7 @@
LVL(3, 12, 9, 20, 0), (G_GENO | 2),
A(ATTK(AT_CLAW, AD_SITM, 0, 0), ATTK(AT_CLAW, AD_SEDU, 0, 0),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(600, 300, MS_SEDUCE, MZ_HUMAN), 0, 0, M1_HUMANOID | M1_TPORT,
SIZ(WT_NYMPH, 300, MS_SEDUCE, MZ_HUMAN), 0, 0, M1_HUMANOID | M1_TPORT,
M2_HOSTILE | M2_FEMALE | M2_COLLECT, M3_INFRAVISIBLE,
5, CLR_BROWN, MOUNTAIN_NYMPH),
/*
@@ -1052,7 +1054,7 @@
LVL(3, 1, 0, 0, 0), (G_GENO | G_NOCORPSE | 2),
A(ATTK(AT_ENGL, AD_PHYS, 1, 6),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(0, 0, MS_SILENT, MZ_HUGE), MR_SLEEP | MR_POISON | MR_STONE, 0,
SIZ(WT_ETHEREAL, 0, MS_SILENT, MZ_HUGE), MR_SLEEP | MR_POISON | MR_STONE, 0,
M1_FLY | M1_BREATHLESS | M1_NOEYES | M1_NOLIMBS | M1_NOHEAD
| M1_MINDLESS | M1_AMORPHOUS | M1_UNSOLID,
M2_HOSTILE | M2_NEUTER, 0,
@@ -1061,7 +1063,7 @@
LVL(4, 20, 2, 30, 0), (G_GENO | G_NOCORPSE | 2),
A(ATTK(AT_ENGL, AD_BLND, 2, 8),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(0, 0, MS_SILENT, MZ_HUGE), MR_SLEEP | MR_POISON | MR_STONE, 0,
SIZ(WT_ETHEREAL, 0, MS_SILENT, MZ_HUGE), MR_SLEEP | MR_POISON | MR_STONE, 0,
M1_FLY | M1_BREATHLESS | M1_NOEYES | M1_NOLIMBS | M1_NOHEAD
| M1_MINDLESS,
M2_HOSTILE | M2_NEUTER, 0,
@@ -1070,7 +1072,7 @@
LVL(5, 20, 2, 30, 0), (G_NOHELL | G_GENO | G_NOCORPSE | 1),
A(ATTK(AT_ENGL, AD_COLD, 1, 6),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(0, 0, MS_SILENT, MZ_HUGE),
SIZ(WT_ETHEREAL, 0, MS_SILENT, MZ_HUGE),
MR_COLD | MR_SLEEP | MR_POISON | MR_STONE, 0,
M1_FLY | M1_BREATHLESS | M1_NOEYES | M1_NOLIMBS | M1_NOHEAD
| M1_MINDLESS,
@@ -1080,7 +1082,7 @@
LVL(6, 20, 2, 30, 0), (G_GENO | G_NOCORPSE | 1),
A(ATTK(AT_ENGL, AD_ELEC, 1, 6), ATTK(AT_ENGL, AD_DREN, 2, 6),
ATTK(AT_NONE, AD_ELEC, 0, 4), NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(0, 0, MS_SILENT, MZ_HUGE),
SIZ(WT_ETHEREAL, 0, MS_SILENT, MZ_HUGE),
MR_ELEC | MR_SLEEP | MR_DISINT | MR_POISON | MR_STONE, 0,
M1_FLY | M1_BREATHLESS | M1_NOEYES | M1_NOLIMBS | M1_NOHEAD
| M1_MINDLESS | M1_UNSOLID,
@@ -1090,7 +1092,7 @@
LVL(7, 22, 2, 30, 0), (G_HELL | G_GENO | G_NOCORPSE | 2),
A(ATTK(AT_ENGL, AD_FIRE, 1, 8),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(0, 0, MS_SILENT, MZ_HUGE),
SIZ(WT_ETHEREAL, 0, MS_SILENT, MZ_HUGE),
MR_FIRE | MR_SLEEP | MR_POISON | MR_STONE, 0,
M1_FLY | M1_BREATHLESS | M1_NOEYES | M1_NOLIMBS | M1_NOHEAD
| M1_MINDLESS | M1_UNSOLID,
@@ -1100,7 +1102,7 @@
LVL(8, 22, 2, 30, 0), (G_HELL | G_GENO | G_NOCORPSE | 1),
A(ATTK(AT_ENGL, AD_FIRE, 1, 10), ATTK(AT_NONE, AD_FIRE, 0, 4),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(0, 0, MS_SILENT, MZ_HUGE),
SIZ(WT_ETHEREAL, 0, MS_SILENT, MZ_HUGE),
MR_FIRE | MR_SLEEP | MR_POISON | MR_STONE, 0,
M1_FLY | M1_BREATHLESS | M1_NOEYES | M1_NOLIMBS | M1_NOHEAD
| M1_MINDLESS | M1_UNSOLID,
@@ -1168,7 +1170,7 @@
LVL(3, 15, 0, 0, 0), (G_NOCORPSE | G_GENO | 4),
A(ATTK(AT_EXPL, AD_BLND, 10, 20),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(0, 0, MS_SILENT, MZ_SMALL),
SIZ(WT_ETHEREAL, 0, MS_SILENT, MZ_SMALL),
MR_FIRE | MR_COLD | MR_ELEC | MR_DISINT | MR_SLEEP | MR_POISON
| MR_ACID | MR_STONE, 0,
M1_FLY | M1_BREATHLESS | M1_AMORPHOUS | M1_NOEYES | M1_NOLIMBS
@@ -1180,7 +1182,7 @@
LVL(5, 15, 0, 0, 0), (G_NOCORPSE | G_GENO | 2),
A(ATTK(AT_EXPL, AD_HALU, 10, 12),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(0, 0, MS_SILENT, MZ_SMALL),
SIZ(WT_ETHEREAL, 0, MS_SILENT, MZ_SMALL),
MR_FIRE | MR_COLD | MR_ELEC | MR_DISINT | MR_SLEEP | MR_POISON
| MR_ACID | MR_STONE, 0,
M1_FLY | M1_BREATHLESS | M1_AMORPHOUS | M1_NOEYES | M1_NOLIMBS
@@ -1340,7 +1342,7 @@
LVL(12, 9, 2, 10, 0), G_GENO,
A(ATTK(AT_BITE, AD_PHYS, 2, 6),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(1500, 500, MS_ROAR, MZ_HUGE), 0, 0,
SIZ(WT_BABY_DRAGON, 500, MS_ROAR, MZ_HUGE), 0, 0,
M1_FLY | M1_THICK_HIDE | M1_NOHANDS | M1_CARNIVORE,
M2_HOSTILE | M2_STRONG | M2_GREEDY | M2_JEWELS, 0,
13, CLR_GRAY, BABY_GRAY_DRAGON),
@@ -1348,7 +1350,7 @@
LVL(12, 9, 2, 10, 0), G_GENO,
A(ATTK(AT_BITE, AD_PHYS, 2, 6),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(1500, 500, MS_ROAR, MZ_HUGE), 0, 0,
SIZ(WT_BABY_DRAGON, 500, MS_ROAR, MZ_HUGE), 0, 0,
M1_FLY | M1_THICK_HIDE | M1_NOHANDS | M1_CARNIVORE,
M2_HOSTILE | M2_STRONG | M2_GREEDY | M2_JEWELS, M3_INFRAVISIBLE,
13, HI_GOLD, BABY_GOLD_DRAGON),
@@ -1356,7 +1358,7 @@
LVL(12, 9, 2, 10, 0), G_GENO,
A(ATTK(AT_BITE, AD_PHYS, 2, 6),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(1500, 500, MS_ROAR, MZ_HUGE), 0, 0,
SIZ(WT_BABY_DRAGON, 500, MS_ROAR, MZ_HUGE), 0, 0,
M1_FLY | M1_THICK_HIDE | M1_NOHANDS | M1_CARNIVORE,
M2_HOSTILE | M2_STRONG | M2_GREEDY | M2_JEWELS, 0,
13, DRAGON_SILVER, BABY_SILVER_DRAGON),
@@ -1366,7 +1368,7 @@
LVL(12, 9, 2, 10, 0), G_GENO,
A(ATTK(AT_BITE, AD_PHYS, 2, 6),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(1500, 500, MS_ROAR, MZ_HUGE), 0, 0,
SIZ(WT_BABY_DRAGON, 500, MS_ROAR, MZ_HUGE), 0, 0,
M1_FLY | M1_THICK_HIDE | M1_NOHANDS | M1_CARNIVORE,
M2_HOSTILE | M2_STRONG | M2_GREEDY | M2_JEWELS, 0,
13, CLR_CYAN, BABY_SHIMMERING_DRAGON),
@@ -1375,7 +1377,7 @@
LVL(12, 9, 2, 10, 0), G_GENO,
A(ATTK(AT_BITE, AD_PHYS, 2, 6),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(1500, 500, MS_ROAR, MZ_HUGE), MR_FIRE, 0,
SIZ(WT_BABY_DRAGON, 500, MS_ROAR, MZ_HUGE), MR_FIRE, 0,
M1_FLY | M1_THICK_HIDE | M1_NOHANDS | M1_CARNIVORE,
M2_HOSTILE | M2_STRONG | M2_GREEDY | M2_JEWELS, M3_INFRAVISIBLE,
13, CLR_RED, BABY_RED_DRAGON),
@@ -1383,7 +1385,7 @@
LVL(12, 9, 2, 10, 0), G_GENO,
A(ATTK(AT_BITE, AD_PHYS, 2, 6),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(1500, 500, MS_ROAR, MZ_HUGE), MR_COLD, 0,
SIZ(WT_BABY_DRAGON, 500, MS_ROAR, MZ_HUGE), MR_COLD, 0,
M1_FLY | M1_THICK_HIDE | M1_NOHANDS | M1_CARNIVORE,
M2_HOSTILE | M2_STRONG | M2_GREEDY | M2_JEWELS, 0,
13, CLR_WHITE, BABY_WHITE_DRAGON),
@@ -1391,7 +1393,7 @@
LVL(12, 9, 2, 10, 0), G_GENO,
A(ATTK(AT_BITE, AD_PHYS, 2, 6),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(1500, 500, MS_ROAR, MZ_HUGE), MR_SLEEP, 0,
SIZ(WT_BABY_DRAGON, 500, MS_ROAR, MZ_HUGE), MR_SLEEP, 0,
M1_FLY | M1_THICK_HIDE | M1_NOHANDS | M1_CARNIVORE,
M2_HOSTILE | M2_STRONG | M2_GREEDY | M2_JEWELS, 0,
13, CLR_ORANGE, BABY_ORANGE_DRAGON),
@@ -1399,7 +1401,7 @@
LVL(12, 9, 2, 10, 0), G_GENO,
A(ATTK(AT_BITE, AD_PHYS, 2, 6),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(1500, 500, MS_ROAR, MZ_HUGE), MR_DISINT, 0,
SIZ(WT_BABY_DRAGON, 500, MS_ROAR, MZ_HUGE), MR_DISINT, 0,
M1_FLY | M1_THICK_HIDE | M1_NOHANDS | M1_CARNIVORE,
M2_HOSTILE | M2_STRONG | M2_GREEDY | M2_JEWELS, 0,
13, CLR_BLACK, BABY_BLACK_DRAGON),
@@ -1407,7 +1409,7 @@
LVL(12, 9, 2, 10, 0), G_GENO,
A(ATTK(AT_BITE, AD_PHYS, 2, 6),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(1500, 500, MS_ROAR, MZ_HUGE), MR_ELEC, 0,
SIZ(WT_BABY_DRAGON, 500, MS_ROAR, MZ_HUGE), MR_ELEC, 0,
M1_FLY | M1_THICK_HIDE | M1_NOHANDS | M1_CARNIVORE,
M2_HOSTILE | M2_STRONG | M2_GREEDY | M2_JEWELS, 0,
13, CLR_BLUE, BABY_BLUE_DRAGON),
@@ -1415,7 +1417,7 @@
LVL(12, 9, 2, 10, 0), G_GENO,
A(ATTK(AT_BITE, AD_PHYS, 2, 6),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(1500, 500, MS_ROAR, MZ_HUGE), MR_POISON, 0,
SIZ(WT_BABY_DRAGON, 500, MS_ROAR, MZ_HUGE), MR_POISON, 0,
M1_FLY | M1_THICK_HIDE | M1_NOHANDS | M1_CARNIVORE | M1_POIS,
M2_HOSTILE | M2_STRONG | M2_GREEDY | M2_JEWELS, 0,
13, CLR_GREEN, BABY_GREEN_DRAGON),
@@ -1423,7 +1425,7 @@
LVL(12, 9, 2, 10, 0), G_GENO,
A(ATTK(AT_BITE, AD_PHYS, 2, 6),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(1500, 500, MS_ROAR, MZ_HUGE), MR_ACID | MR_STONE, 0,
SIZ(WT_BABY_DRAGON, 500, MS_ROAR, MZ_HUGE), MR_ACID | MR_STONE, 0,
M1_FLY | M1_THICK_HIDE | M1_NOHANDS | M1_CARNIVORE | M1_ACID,
M2_HOSTILE | M2_STRONG | M2_GREEDY | M2_JEWELS, 0,
13, CLR_YELLOW, BABY_YELLOW_DRAGON),
@@ -1573,7 +1575,7 @@
LVL(8, 36, 2, 30, 0), (G_NOCORPSE | 1),
A(ATTK(AT_ENGL, AD_PHYS, 1, 10),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(0, 0, MS_SILENT, MZ_HUGE), MR_POISON | MR_STONE, 0,
SIZ(WT_ETHEREAL, 0, MS_SILENT, MZ_HUGE), MR_POISON | MR_STONE, 0,
M1_NOEYES | M1_NOLIMBS | M1_NOHEAD | M1_MINDLESS | M1_BREATHLESS
| M1_UNSOLID | M1_FLY,
M2_STRONG | M2_NEUTER, 0,
@@ -1582,7 +1584,7 @@
LVL(8, 12, 2, 30, 0), (G_NOCORPSE | 1),
A(ATTK(AT_CLAW, AD_FIRE, 3, 6), ATTK(AT_NONE, AD_FIRE, 0, 4),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(0, 0, MS_SILENT, MZ_HUGE), MR_FIRE | MR_POISON | MR_STONE, 0,
SIZ(WT_ETHEREAL, 0, MS_SILENT, MZ_HUGE), MR_FIRE | MR_POISON | MR_STONE, 0,
M1_NOEYES | M1_NOLIMBS | M1_NOHEAD | M1_MINDLESS | M1_BREATHLESS
| M1_UNSOLID | M1_FLY | M1_NOTAKE,
M2_STRONG | M2_NEUTER, M3_INFRAVISIBLE,
@@ -2335,7 +2337,7 @@
LVL(6, 12, 4, 15, -6), (G_GENO | 2),
A(ATTK(AT_TUCH, AD_DRLI, 1, 6),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(0, 0, MS_SILENT, MZ_HUMAN),
SIZ(WT_ETHEREAL, 0, MS_SILENT, MZ_HUMAN),
MR_COLD | MR_SLEEP | MR_POISON | MR_STONE, 0,
M1_BREATHLESS | M1_FLY | M1_HUMANOID | M1_UNSOLID,
M2_UNDEAD | M2_STALK | M2_HOSTILE, 0,

17
include/nhregex.h Normal file
View File

@@ -0,0 +1,17 @@
/* NetHack 3.7 nhregex.h $NHDT-Date: $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: $ */
/* NetHack may be freely redistributed. See license for details. */
#ifndef NHREGEX_H
#define NHREGEX_H
/* ### {cpp,pmatch,posix}regex.c ### */
extern struct nhregex *regex_init(void);
extern boolean regex_compile(const char *, struct nhregex *) NONNULLARG1;
extern char *regex_error_desc(struct nhregex *, char *) NONNULLARG2;
extern boolean regex_match(const char *, struct nhregex *) NO_NNARGS;
extern void regex_free(struct nhregex *) NONNULLARG1;
#endif /* NHREGEX_H */
/*extern.h*/

View File

@@ -87,6 +87,7 @@ struct obj {
#define NOBJ_STATES 10
xint16 timed; /* # of fuses (timers) attached to this obj */
/* Bitfields currently require 5 bytes minimum */
Bitfield(cursed, 1); /* uncursed when neither cursed nor blessed */
Bitfield(blessed, 1);
Bitfield(unpaid, 1); /* owned by shop; valid for objects in hero's
@@ -98,6 +99,10 @@ struct obj {
* items on shop floor or in containers there;
* implicit for items at any other location
* unless carried and explicitly flagged unpaid */
Bitfield(recharged, 3); /* number of times it's been recharged */
#define on_ice recharged /* corpse on ice */
Bitfield(lamplit, 1); /* a light-source -- can be lit */
Bitfield(known, 1); /* exact nature known (for instance, charge count
* or enchantment); many items have this preset if
* they lack anything interesting to discover */
@@ -105,6 +110,14 @@ struct obj {
* some types of items always have dknown set */
Bitfield(bknown, 1); /* BUC (blessed/uncursed/cursed) known */
Bitfield(rknown, 1); /* rustproofing status known */
Bitfield(cknown, 1); /* for containers (including statues): the contents
* are known; also applicable to tins; also applies
* to horn of plenty but only for empty/non-empty */
Bitfield(lknown, 1); /* locked/unlocked status is known; assigned for bags
* and for horn of plenty (when tipping) even though
* they have no locks */
Bitfield(tknown, 1); /* trap status known for chests */
Bitfield(nomerge, 1); /* set temporarily to prevent merging */
Bitfield(oeroded, 2); /* rusted/burnt weapon/armor */
Bitfield(oeroded2, 2); /* corroded/rotted weapon/armor */
@@ -123,33 +136,23 @@ struct obj {
/* or accidental tripped rolling boulder trap */
#define opoisoned otrapped /* object (weapon) is coated with poison */
Bitfield(recharged, 3); /* number of times it's been recharged */
#define on_ice recharged /* corpse on ice */
Bitfield(lamplit, 1); /* a light-source -- can be lit */
Bitfield(globby, 1); /* combines with like types on adjacent squares */
Bitfield(greased, 1); /* covered with grease */
Bitfield(nomerge, 1); /* set temporarily to prevent merging */
Bitfield(how_lost, 2); /* stolen by mon or thrown, dropped by hero */
Bitfield(in_use, 1); /* for magic items before useup items */
Bitfield(bypass, 1); /* mark this as an object to be skipped by bhito() */
Bitfield(cknown, 1); /* for containers (including statues): the contents
* are known; also applicable to tins; also applies
* to horn of plenty but only for empty/non-empty */
Bitfield(lknown, 1); /* locked/unlocked status is known; assigned for bags
* and for horn of plenty (when tipping) even though
* they have no locks */
Bitfield(pickup_prev, 1); /* was picked up previously */
Bitfield(ghostly, 1); /* it just got placed into a bones file */
Bitfield(how_lost, 3); /* stolen by mon or thrown, dropped by hero, etc */
Bitfield(named_how, 1); /* source of name per TODO in resetobjs() */
#if 0
/* not implemented */
Bitfield(tknown, 1); /* trap status known for chests */
Bitfield(eknown, 1); /* effect known for wands zapped or rings worn when
* not seen yet after being picked up while blind
* [maybe for remaining stack of used potion too] */
/* 7 free bits */
/* 5 free bits */
#else
/* 1 free bit */
/* 6 free bits */
#endif
int corpsenm; /* type of corpse is mons[corpsenm] */
@@ -162,6 +165,7 @@ struct obj {
* 1 for others (format as "next boulder") */
int usecount; /* overloaded for various things that tally */
#define spestudied usecount /* # of times a spellbook has been studied */
#define wishedfor usecount /* flag for hold_another_object() if from wish */
unsigned oeaten; /* nutrition left in food, if partly eaten */
long age; /* creation date */
long owornmask; /* bit mask indicating which equipment slot(s) an
@@ -218,10 +222,12 @@ struct obj {
(otmp->oclass == WEAPON_CLASS \
&& objects[otmp->otyp].oc_skill >= P_SHORT_SWORD \
&& objects[otmp->otyp].oc_skill <= P_SABER)
/* Snickersnee is not a polearm, but can hit from distance */
#define is_pole(otmp) \
((otmp->oclass == WEAPON_CLASS || otmp->oclass == TOOL_CLASS) \
&& (objects[otmp->otyp].oc_skill == P_POLEARMS \
|| objects[otmp->otyp].oc_skill == P_LANCE))
|| objects[otmp->otyp].oc_skill == P_LANCE \
|| is_art(otmp, ART_SNICKERSNEE)))
#define is_spear(otmp) \
(otmp->oclass == WEAPON_CLASS && objects[otmp->otyp].oc_skill == P_SPEAR)
#define is_launcher(otmp) \
@@ -242,6 +248,9 @@ struct obj {
((o)->oclass == TOOL_CLASS && objects[(o)->otyp].oc_skill != P_NONE)
/* towel is not a weptool: spe isn't an enchantment, cursed towel
doesn't weld to hand, and twoweapon won't work with one */
#define is_blunt_weapon(o) \
(((o)->oclass == WEAPON_CLASS || is_weptool(o)) \
&& ((objects[(o)->otyp].oc_dir & WHACK) != 0))
#define is_wet_towel(o) ((o)->otyp == TOWEL && (o)->spe > 0)
#define bimanual(otmp) \
((otmp->oclass == WEAPON_CLASS || otmp->oclass == TOOL_CLASS) \
@@ -250,10 +259,11 @@ struct obj {
(otmp->oclass == WEAPON_CLASS \
&& objects[otmp->otyp].oc_skill >= -P_SHURIKEN \
&& objects[otmp->otyp].oc_skill <= -P_BOW)
#define is_poisonable(otmp) \
(otmp->oclass == WEAPON_CLASS \
&& objects[otmp->otyp].oc_skill >= -P_SHURIKEN \
&& objects[otmp->otyp].oc_skill <= -P_BOW)
#define is_poisonable(otmp) \
((otmp->oclass == WEAPON_CLASS \
&& objects[otmp->otyp].oc_skill >= -P_SHURIKEN \
&& objects[otmp->otyp].oc_skill <= -P_BOW) \
|| permapoisoned(otmp))
#define uslinging() (uwep && objects[uwep->otyp].oc_skill == P_SLING)
/* 'is_quest_artifact()' only applies to the current role's artifact */
#define any_quest_artifact(o) ((o)->oartifact >= ART_ORB_OF_DETECTION)
@@ -464,11 +474,17 @@ struct obj {
#define POTHIT_MONST_THROW 2 /* thrown by a monster */
#define POTHIT_OTHER_THROW 3 /* propelled by some other means [scatter()] */
/* tracking how an item left your inventory */
#define LOST_NONE 0 /* still in inventory, or method not covered below */
#define LOST_THROWN 1 /* thrown or fired by the hero */
#define LOST_DROPPED 2 /* dropped or tipped out of a container by the hero */
#define LOST_STOLEN 3 /* stolen from hero's inventory by a monster */
/* tracking how an item left your inventory via how_lost field */
#define LOST_NONE 0 /* still in inventory, or method not covered below */
#define LOST_THROWN 1 /* thrown or fired by the hero */
#define LOST_DROPPED 2 /* dropped or tipped out of a container by the hero */
#define LOST_STOLEN 3 /* stolen from hero's inventory by a monster */
#define LOSTOVERRIDEMASK 0x3
#define LOST_EXPLODING 4 /* the object is exploding (i.e. POT_OIL) */
/* tracking how a name got acquired by an object in named_how field */
#define NAMED_PLAIN 0 /* nothing special, typical naming */
#define NAMED_KEEP 1 /* historic statue, or stoned/killed monster */
/*
* Notes for adding new oextra structures:

View File

@@ -10,6 +10,7 @@
(liquid potion inside glass bottle, metal arrowhead on wooden shaft)
and object definitions only specify one type on a best-fit basis */
enum obj_material_types {
NO_MATERIAL = 0,
LIQUID = 1, /* currently only for venom */
WAX = 2,
VEGGY = 3, /* foodstuffs */

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 objects.h $NHDT-Date: 1725653011 2024/09/06 20:03:31 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.26 $ */
/* NetHack 3.7 objects.h $NHDT-Date: 1749097644 2025/06/04 20:27:24 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.30 $ */
/* Copyright (c) Mike Threepoint, 1989. */
/* NetHack may be freely redistributed. See license for details. */
@@ -352,6 +352,10 @@ WEAPON("mace", NoDes,
1, 0, 0, 40, 30, 5, 6, 6, 0, B, P_MACE, IRON, HI_METAL,
MACE),
/* +1 small */
WEAPON("silver mace", NoDes,
1, 0, 0, 2, 36, 60, 6, 6, 0, B, P_MACE, SILVER, HI_SILVER,
SILVER_MACE),
/* +1 small */
WEAPON("morning star", NoDes,
1, 0, 0, 12, 120, 10, 4, 6, 0, B, P_MORNING_STAR, IRON, HI_METAL,
MORNING_STAR),
@@ -931,7 +935,7 @@ EYEWEAR("lenses", NoDes, 1, 0, 5, 3, 80, GLASS, HI_GLASS,
LENSES),
EYEWEAR("blindfold", NoDes, 1, BLINDED, 50, 2, 20, CLOTH, CLR_BLACK,
BLINDFOLD),
EYEWEAR("towel", NoDes, 1, BLINDED, 50, 2, 50, CLOTH, CLR_MAGENTA,
EYEWEAR("towel", NoDes, 1, BLINDED, 50, 5, 50, CLOTH, CLR_MAGENTA,
TOWEL),
#undef EYEWEAR
@@ -1501,7 +1505,7 @@ COIN("gold piece", 1000, GOLD, 1, GOLD_PIECE),
OBJECT(OBJ(name, desc), \
BITS(0, 1, 0, 0, 0, 0, 0, 0, 0, \
HARDGEM(mohs), 0, -P_SLING, glass), \
0, GEM_CLASS, prob, 0, 1, gval, 3, 3, 0, 0, nutr, color, sn)
0, GEM_CLASS, prob, 0, wt, gval, 3, 3, 0, 0, nutr, color, sn)
#define ROCK(name,desc,kn,prob,wt,gval,sdam,ldam,mgc,nutr,mohs,glass,colr,sn) \
OBJECT(OBJ(name, desc), \
BITS(kn, 1, 0, 0, mgc, 0, 0, 0, 0, \

View File

@@ -167,6 +167,8 @@ static int optfn_##a(int, int, boolean, char *, char *);
NHOPTB(ascii_map, Advanced, 0, opt_in, set_in_game,
ascii_map_Def, Yes, No, No, NoAlias, &iflags.wc_ascii_map,
Term_False, "show map as text")
NHOPTO("autocompletions", Advanced, o_autocomplete, BUFSZ, opt_in, set_in_game,
No, Yes, No, NoAlias, "edit autocompletions")
NHOPTB(autodescribe, Advanced, 0, opt_out, set_in_game,
On, Yes, No, No, NoAlias, &iflags.autodescribe, Term_False,
"describe terrain under cursor")
@@ -440,9 +442,9 @@ static int optfn_##a(int, int, boolean, char *, char *);
No, Yes, No, No, NoAlias, "jump to the last page in a menu")
NHOPTC(menu_next_page, Advanced, 4, opt_in, set_in_config,
No, Yes, No, No, NoAlias, "go to the next menu page")
NHOPTB(menu_objsyms, Advanced, 0, opt_in, set_in_game,
Off, Yes, No, No, NoAlias, &iflags.menu_head_objsym,
Term_False, "show object symbols in menus")
NHOPTC(menu_objsyms, Advanced, 12, opt_in, set_in_game,
Yes, Yes, No, Yes, "use_menu_glyphs",
"show object symbols in menus")
#ifdef TTY_GRAPHICS
NHOPTB(menu_overlay, Advanced, 0, opt_in, set_in_game,
On, Yes, No, No, NoAlias, &iflags.menu_overlay, Term_False,

Some files were not shown because too many files have changed in this diff Show More