Lua: remove dgn_comp, use lua instead

This commit is contained in:
Pasi Kallinen
2019-07-14 10:07:11 +03:00
parent fd55d9118e
commit 9cd9280276
19 changed files with 578 additions and 5139 deletions

View File

@@ -1,143 +0,0 @@
# NetHack 3.6 dungeon.def $NHDT-Date: 1462486876 2016/05/05 22:21:16 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.14 $
# Copyright (c) 1990-95 by M. Stephenson
# NetHack may be freely redistributed. See license for details.
#
# The dungeon description file for the "standard" 3.1 NetHack.
#
# Note: The order of the definition of dungeons in this file
# reflects in their order of creation in the real dungeon.
# The "Main" branch must *always* be first.
# Also note that the order of the dungeons in this file
# determines the order in which branch levels are assigned.
# If two dungeons have overlapping ranges for their entry
# points, then you should list the dungeon with the _least_
# number of choices for its branch level _first_.
#
DUNGEON: "The Dungeons of Doom" "D" (25, 5)
ALIGNMENT: unaligned
BRANCH: "The Gnomish Mines" @ (2, 3)
LEVEL: "rogue" "R" @ (15, 4)
LEVELDESC: roguelike
LEVEL: "oracle" "O" @ (5, 5)
LEVALIGN: neutral
CHAINBRANCH: "Sokoban" "oracle" + (1, 0) up
RNDLEVEL: "bigrm" "B" @ (10, 3) 40 10
CHAINBRANCH: "The Quest" "oracle" + (6, 2) portal
BRANCH: "Fort Ludios" @ (18, 4) portal
RNDLEVEL: "medusa" "none" @ (-5, 4) 4
LEVALIGN: chaotic
LEVEL: "castle" "none" @ (-1, 0)
CHAINBRANCH: "Gehennom" "castle" + (0, 0) no_down
BRANCH: "The Elemental Planes" @ (1, 0) no_down up
#
# Gehennom
#
# Now re-worked for 3.1, hell is hopefully going to be a little
# less boring. Also, in 3.1, the tower is not considered as a
# part of hell, but is set up as a separate dungeon.
#
# Gehennom is no longer considered "hellish" as a complete dungeon.
# That is, fire resistance is no longer a condition for survival in
# it. However, Gehennom, and the special levels in it in particular,
# is abundant with fire traps. As a result, fire resistance is still
# a prudent survival strategy in Gehennom.
#
# Note: Gehennom *must* be the second dungeon defined so that
# monsters can properly migrate here under certain
# circumstances.
#
DUNGEON: "Gehennom" "G" (20, 5)
DESCRIPTION: mazelike
DESCRIPTION: hellish
ALIGNMENT: noalign
BRANCH: "Vlad's Tower" @ (9, 5) up
LEVEL: "valley" "V" @ (1, 0)
LEVEL: "sanctum" "none" @ (-1, 0)
LEVEL: "juiblex" "J" @ (4, 4)
LEVEL: "baalz" "B" @ (6, 4)
LEVEL: "asmodeus" "A" @ (2, 6)
LEVEL: "wizard1" "none" @ (11, 6)
CHAINLEVEL: "wizard2" "X" "wizard1" + (1, 0)
CHAINLEVEL: "wizard3" "Y" "wizard1" + (2, 0)
LEVEL: "orcus" "O" @ (10, 6)
LEVEL: "fakewiz1" "F" @ (-6,4)
LEVEL: "fakewiz2" "G" @ (-6,4)
#
# The Mines of the Gnomes of Zurich.
#
DUNGEON: "The Gnomish Mines" "M" (8, 2)
ALIGNMENT: lawful
DESCRIPTION: mazelike
RNDLEVEL: "minetn" "T" @ (3, 2) 7
LEVELDESC: town
RNDLEVEL: "minend" "E" @ (-1, 0) 3
#
# The Questdungeon
#
# This is a proto-dungeon. The level file names will be prepended with
# three letter role abbreviation during initialization, replacing "x".
# A special "x-fill" level must be defined in the levels description
# file. It will be used for all levels not defined explicitly below.
#
DUNGEON: "The Quest" "Q" (5, 2)
LEVEL: "x-strt" "none" @ (1, 1)
LEVEL: "x-loca" "L" @ (3, 1)
LEVEL: "x-goal" "none" @ (-1, 0)
#
# Sokoban
#
DUNGEON: "Sokoban" "none" (4, 0)
DESCRIPTION: mazelike
ALIGNMENT: neutral
ENTRY: -1
RNDLEVEL: "soko1" "none" @ (1, 0) 2
RNDLEVEL: "soko2" "none" @ (2, 0) 2
RNDLEVEL: "soko3" "none" @ (3, 0) 2
RNDLEVEL: "soko4" "none" @ (4, 0) 2
#
# The Central Vault of Croesus.
#
DUNGEON: "Fort Ludios" "K" (1, 0)
DESCRIPTION: mazelike
ALIGNMENT: unaligned
LEVEL: "knox" "K" @ (-1, 0)
#
# Vlad's Tower
#
# It has been removed from Gehennom, and it is surrounded by stone.
# Must not allow bones files for its top level.
#
DUNGEON: "Vlad's Tower" "T" (3, 0)
PROTOFILE: "tower"
DESCRIPTION: mazelike
ALIGNMENT: chaotic
ENTRY: -1
LEVEL: "tower1" "none" @ (1, 0)
# it isn't necessary to list these last two, but doing so makes them
# show up in ^O output and in the level teleport menu
LEVEL: "tower2" "none" @ (2, 0)
LEVEL: "tower3" "none" @ (3, 0)
#
# The Endgame levels
#
# Enter on 2nd level from bottom; 1st (from bottom) is a
# placeholder for surface level, and should be unreachable.
# [Note: the name "dummy" is checked for in init_dungeons().]
#
DUNGEON: "The Elemental Planes" "E" (6, 0)
DESCRIPTION: mazelike
ALIGNMENT: unaligned
ENTRY: -2
LEVEL: "astral" "none" @ (1, 0)
LEVEL: "water" "none" @ (2, 0)
LEVEL: "fire" "none" @ (3, 0)
LEVEL: "air" "none" @ (4, 0)
LEVEL: "earth" "none" @ (5, 0)
LEVEL: "dummy" "none" @ (6, 0)

310
dat/dungeon.lua Normal file
View File

@@ -0,0 +1,310 @@
dungeon = {
{
name = "The Dungeons of Doom",
bonetag = "D",
base = 25,
range = 5,
alignment = "unaligned",
branches = {
{
name = "The Gnomish Mines",
base = 2,
range = 3
},
{
name = "Sokoban",
chainlevel = "oracle",
base = 1,
direction = "up"
},
{
name = "The Quest",
chainlevel = "oracle",
base = 6,
range = 2,
branchtype = "portal"
},
{
name = "Fort Ludios",
base = 18,
range = 4,
branchtype = "portal"
},
{
name = "Gehennom",
chainlevel = "castle",
base = 0,
branchtype = "no_down"
},
{
name = "The Elemental Planes",
base = 1,
branchtype = "no_down",
direction = "up"
}
},
levels = {
{
name = "rogue",
bonetag = "R",
base = 15,
range = 4,
flags = "roguelike",
},
{
name = "oracle",
bonetag = "O",
base = 5,
range = 5,
alignment = "neutral"
},
{
name = "bigrm",
bonetag = "B",
base = 10,
range = 3,
chance = 40,
nlevels = 10
},
{
name = "medusa",
base = -5,
range = 4,
nlevels = 4,
alignment = "chaotic"
},
{
name = "castle",
base = -1
}
}
},
{
name = "Gehennom",
bonetag = "G",
base = 20,
range = 5,
flags = { "mazelike", "hellish" },
alignment = "noalign",
branches = {
{
name = "Vlad's Tower",
base = 9,
range = 5,
direction = "up"
}
},
levels = {
{
name = "valley",
bonetag = "V",
base = 1
},
{
name = "sanctum",
base = -1
},
{
name = "juiblex",
bonetag = "J",
base = 4,
range = 4
},
{
name = "baalz",
bonetag = "B",
base = 6,
range = 4
},
{
name = "asmodeus",
bonetag = "A",
base = 2,
range = 6
},
{
name = "wizard1",
base = 11,
range = 6
},
{
name = "wizard2",
bonetag = "X",
chainlevel = "wizard1",
base = 1
},
{
name = "wizard3",
bonetag = "Y",
chainlevel = "wizard1",
base = 2
},
{
name = "orcus",
bonetag = "O",
base = 10,
range = 6
},
{
name = "fakewiz1",
bonetag = "F",
base = -6,
range = 4
},
{
name = "fakewiz2",
bonetag = "G",
base = -6,
range = 4
},
}
},
{
name = "The Gnomish Mines",
bonetag = "M",
base = 8,
range = 2,
alignment = "lawful",
flags = { "mazelike" },
levels = {
{
name = "minetn",
bonetag = "T",
base = 3,
range = 2,
nlevels = 7,
flags = "town"
},
{
name = "minend",
bonetag = "E",
base = -1,
nlevels = 3
},
}
},
{
name = "The Quest",
bonetag = "Q",
base = 5,
range = 2,
levels = {
{
name = "x-strt",
base = 1,
range = 1
},
{
name = "x-loca",
bonetag = "L",
base = 3,
range = 1
},
{
name = "x-goal",
base = -1
},
}
},
{
name = "Sokoban",
base = 4,
alignment = "neutral",
flags = { "mazelike" },
entry = -1,
levels = {
{
name = "soko1",
base = 1,
nlevels = 2
},
{
name = "soko2",
base = 2,
nlevels = 2
},
{
name = "soko3",
base = 3,
nlevels = 2
},
{
name = "soko4",
base = 4,
nlevels = 2
},
}
},
{
name = "Fort Ludios",
base = 1,
bonetag = "K",
flags = { "mazelike" },
alignment = "unaligned",
levels = {
{
name = "knox",
bonetag = "K",
base = -1
}
}
},
{
name = "Vlad's Tower",
base = 3,
bonetag = "T",
protofile = "tower",
alignment = "chaotic",
flags = { "mazelike" },
entry = -1,
levels = {
{
name = "tower1",
base = 1
},
{
name = "tower2",
base = 2
},
{
name = "tower3",
base = 3
},
}
},
{
name = "The Elemental Planes",
bonetag = "E",
base = 6,
alignment = "unaligned",
flags = { "mazelike" },
entry = -2,
levels = {
{
name = "astral",
base = 1
},
{
name = "water",
base = 2
},
{
name = "fire",
base = 3
},
{
name = "air",
base = 4
},
{
name = "earth",
base = 5
},
{
name = "dummy",
base = 6
},
}
},
}

View File

@@ -1,419 +0,0 @@
.TH DGN_COMP 6 "25 May 2015" NETHACK
.de ND
.ds Nd \\$3
..
.de NB
.ds Nb \\$2
..
.de NR
.ds Nr \\$2
..
.ND $NHDT-Date: 1524689548 2018/04/25 20:52:28 $
.NB $NHDT-Branch: NetHack-3.6.0 $
.NR $NHDT-Revision: 1.6 $
.ds Na Kenneth Lorber
.SH NAME
dgn_comp \- NetHack dungeon compiler
.SH SYNOPSIS
.B dgn_comp
[
.I file
]
.PP
If no arguments are given, it reads standard input.
.SH DESCRIPTION
.PP
.I Dgn_comp
is a dungeon compiler for NetHack version 3.2 and higher. It
takes a description file as an argument and produces a dungeon "script"
that is to be loaded by NetHack at runtime.
.PP
The purpose of this tool is to provide NetHack administrators and
implementors with a convenient way to create a custom dungeon for the
game, without having to recompile the entire world.
.SH GRAMMAR
.PP
DUNGEON:
.B name
.B bonesmarker
(
.B base
,
.B rand
) [
.B %age
]
.PP
where
.B name
is the dungeon name,
.B bonesmarker
is a letter for marking bones files, (
.B base
,
.B rand
) is the number of levels, and
.B %age
is its percentage chance of being generated (if absent, 100% chance).
DESCRIPTION:
.B tag
.PP
where
.B tag
is currently one of
.BR HELLISH ,
.BR MAZELIKE ,
or
.BR ROGUELIKE .
ALIGNMENT | LEVALIGN: [
.B lawful
|
.B neutral
|
.B chaotic
|
.B unaligned
]
.PP
gives the alignment of the dungeon/level (default is unaligned).
ENTRY:
.B level
.PP
the dungeon entry point. The dungeon connection attaches at this
level of the given dungeon.
If the value of
.B level
is negative, the entry level is calculated from the bottom of the
dungeon, with -1 being the last level.
If this line is not present in a dungeon description, the entry level
defaults to 1.
PROTOFILE:
.B name
.PP
the prototypical name for dungeon level files in this dungeon.
For example, the PROTOFILE name for the dungeon
.I Vlad's Tower
is
.IR tower .
LEVEL:
.B name
.B bonesmarker
@ (
.B base
,
.B rand
) [
.B %age
]
.PP
where
.B name
is the level name,
.B bonesmarker
is a letter for marking bones files, (
.B base
,
.B rand
) is the location and
.B %age
is the generation percentage, as above.
RNDLEVEL:
.B name
.B bonesmarker
@ (
.B base
,
.B rand
)
[
.B %age
]
.B rndlevs
.PP
where
.B name
is the level name,
.B bonesmarker
is a letter for marking bones files, (
.B base
,
.B rand
) is the location,
.B %age
is the generation percentage, as above, and
.B rndlevs
is the number of similar levels available to choose from.
CHAINLEVEL:
.B name
.B bonesmarker
.B prev_name
+ (
.B base
,
.B rand
) [
.B %age
]
.PP
where
.B name
is the level name,
.B bonesmarker
is a letter for marking bones files,
.B prev_name
is the name of a level defined previously, (
.B base
,
.B rand
) is the
.I offset
from the level being chained from, and
.B %age
is the generation percentage.
RNDCHAINLEVEL:
.B name
.B bonesmarker
.B prev_name
+ (
.B base
,
.B rand
) [
.B %age
]
.B rndlevs
.PP
where
.B name
is the level name,
.B bonesmarker
is a letter for marking bones files,
.B prev_name
is the name of a level defined previously, (
.B base
,
.B rand
) is the
.I offset
from the level being chained from,
.B %age
is the generation percentage, and
.B rndlevs
is the number of similar levels available to choose from.
LEVELDESC:
.B type
.PP
where
.B type
is the level type, (see DESCRIPTION, above). The
.B type
is used to override any pre-set value used to describe the entire dungeon,
for this level only.
BRANCH:
.B name
@ (
.B base
,
.B rand
) [
.B stair
|
.B no_up
|
.B no_down
|
.B portal
] [
.B up
|
.B down
]
.PP
where
.B name
is the name of the dungeon to branch to, and (
.B base
,
.B rand
) is the location of the branch.
The last two optional arguments are
the branch type and branch direction.
The type of a branch can be a two-way stair connection,
a one-way stair connection, or a magic portal.
A one-way stair is described by the types
.B no_up
and
.B no_down
which specify which stair direction is missing.
The default branch type is
.BR stair .
The direction for a stair can be either up or down; direction is not
applicable to portals. The default direction is
.BR down .
CHAINBRANCH:
.B name
.B prev_name
+ (
.B base
,
.B rand
) [
.B stair
|
.B no_up
|
.B no_down
|
.B portal
] [
.B up
|
.B down
]
.PP
where
.B name
is the name of the dungeon to branch to,
.B prev_name
is the name of a previously defined
.B level
and (
.B base
,
.B rand
) is the
.I offset
from the level being chained from.
The optional branch type and direction are the same as described above.
.SH GENERIC RULES
.PP
Each dungeon must have a unique
.B bonesmarker ,
and each special level must have a
.B bonesmarker
unique within its dungeon (letters may be reused in different dungeons).
If the
.B bonesmarker
has the special value "none", no bones files will be created for that
level or dungeon.
.PP
The value
.B base
may be in the range of 1 to
.B MAXLEVEL
(as defined in
.I global.h
).
.PP
The value
.B rand
may be in the range of -1 to
.BR MAXLEVEL .
.PP
If
.B rand
is -1 it will be replaced with the value (num_dunlevs(dungeon) - base)
during the load process (ie. from here to the end of the dungeon).
.PP
If
.B rand
is 0 the level is located absolutely at
.BR base .
.PP
Branches don't have a probability. Dungeons do. If a dungeon fails
to be generated during load, all its levels and branches are skipped.
.PP
No level or branch may be chained from a level with a percentage generation
probability. This is to prevent non-resolution during the load.
In addition, no branch may be made from a dungeon with a percentage
generation probability for the same reason.
.PP
As a general rule using the dungeon compiler:
.PP
If a dungeon has a
.B protofile
name associated with it
.RI ( eg.
.BR tower )
that file will be used.
.PP
If a special level is present, it will override the above rule and
the appropriate file will be loaded.
.PP
If neither of the above are present, the standard generator will
take over and make a "normal" level.
.PP
A level alignment, if present, will override
the alignment of the dungeon that it exists within.
.SH EXAMPLE
.PP
Here is the current syntax of the dungeon compiler's "language":
.LP
.nf
.ta +8n +8n +8n
#
# The dungeon description file for the "standard" original
# 3.0 NetHack.
#
DUNGEON: "The Dungeons of Doom" "D" (25, 5)
LEVEL: "rogue" "none" @ (15, 4)
LEVEL: "oracle" "none" @ (5, 7)
LEVEL: "bigroom" "B" @ (12, 3) 15
LEVEL: "medusa" "none" @ (20, 5)
CHAINLEVEL: "castle" "medusa" + (1, 4)
CHAINBRANCH: "Hell" "castle" + (0, 0) no_down
BRANCH: "The Astral Plane" @ (1, 0) no_down up
DUNGEON: "Hell" "H" (25, 5)
DESCRIPTION: mazelike
DESCRIPTION: hellish
BRANCH: "Vlad's Tower" @ (13, 5) up
LEVEL: "wizard" "none" @ (15, 10)
LEVEL: "fakewiz" "A" @ (5, 5)
LEVEL: "fakewiz" "B" @ (10, 5)
LEVEL: "fakewiz" "C" @ (15, 5)
LEVEL: "fakewiz" "D" @ (20, 5)
LEVEL: "fakewiz" "E" @ (25, 5)
DUNGEON: "Vlad's Tower" "T" (3, 0)
PROTOFILE: "tower"
DESCRIPTION: mazelike
ENTRY: -1
DUNGEON: "The Astral Plane" "A" (1, 0)
DESCRIPTION: mazelike
PROTOFILE: "endgame"
.fi
.PP
.I NOTES:
.br
Lines beginning with '#' are considered comments.
.br
A special level must be explicitly aligned. The alignment of the dungeon
it is in only applies to non-special levels within that dungeon.
.SH AUTHOR
.PP
M. Stephenson (from the level compiler by Jean-Christophe Collet).
.SH "SEE ALSO"
.PP
lev_comp(6), nethack(6)
.SH BUGS
.PP
Probably infinite.
.SH COPYRIGHT
This file is Copyright (C) \*(Na and was last modified \*(Nd (version
\*(Nb:\*(Nr).
NetHack may be freely redistributed. See license for details.

View File

@@ -1,330 +0,0 @@
DGN_COMP(6) 1995 DGN_COMP(6)
NAME
dgn_comp - NetHack dungeon compiler
SYNOPSIS
dgn_comp [ file ]
If no arguments are given, it reads standard input.
DESCRIPTION
Dgn_comp is a dungeon compiler for NetHack version 3.2 and
higher. It takes a description file as an argument and pro-
duces a dungeon "script" that is to be loaded by NetHack at
runtime.
The purpose of this tool is to provide NetHack administra-
tors and implementors with a convenient way to create a cus-
tom dungeon for the game, without having to recompile the
entire world.
GRAMMAR
DUNGEON: name bonesmarker ( base , rand ) [ %age ]
where name is the dungeon name, bonesmarker is a letter for
marking bones files, ( base , rand ) is the number of lev-
els, and %age is its percentage chance of being generated
(if absent, 100% chance).
DESCRIPTION: tag
where tag is currently one of HELLISH, MAZELIKE, or ROGUE-
LIKE.
ALIGNMENT | LEVALIGN: [ lawful | neutral | chaotic |
unaligned ]
gives the alignment of the dungeon/level (default is
unaligned).
ENTRY: level
the dungeon entry point. The dungeon connection attaches at
this level of the given dungeon. If the value of level is
negative, the entry level is calculated from the bottom of
the dungeon, with -1 being the last level. If this line is
not present in a dungeon description, the entry level
defaults to 1.
PROTOFILE: name
the prototypical name for dungeon level files in this
dungeon. For example, the PROTOFILE name for the dungeon
Vlad's Tower is tower.
Dec Last change: 12 1
DGN_COMP(6) 1995 DGN_COMP(6)
LEVEL: name bonesmarker @ ( base , rand ) [ %age ]
where name is the level name, bonesmarker is a letter for
marking bones files, ( base , rand ) is the location and
%age is the generation percentage, as above.
RNDLEVEL: name bonesmarker @ ( base , rand ) [ %age ]
rndlevs
where name is the level name, bonesmarker is a letter for
marking bones files, ( base , rand ) is the location, %age
is the generation percentage, as above, and rndlevs is the
number of similar levels available to choose from.
CHAINLEVEL: name bonesmarker prev_name + ( base , rand ) [
%age ]
where name is the level name, bonesmarker is a letter for
marking bones files, prev_name is the name of a level
defined previously, ( base , rand ) is the offset from the
level being chained from, and %age is the generation percen-
tage.
RNDCHAINLEVEL: name bonesmarker prev_name + ( base , rand )
[ %age ] rndlevs
where name is the level name, bonesmarker is a letter for
marking bones files, prev_name is the name of a level
defined previously, ( base , rand ) is the offset from the
level being chained from, %age is the generation percentage,
and rndlevs is the number of similar levels available to
choose from.
LEVELDESC: type
where type is the level type, (see DESCRIPTION, above). The
type is used to override any pre-set value used to describe
the entire dungeon, for this level only.
BRANCH: name @ ( base , rand ) [ stair | no_up | no_down |
portal ] [ up | down ]
where name is the name of the dungeon to branch to, and (
base , rand ) is the location of the branch. The last two
optional arguments are the branch type and branch direction.
The type of a branch can be a two-way stair connection, a
one-way stair connection, or a magic portal. A one-way
stair is described by the types no_up and no_down which
specify which stair direction is missing. The default
branch type is stair. The direction for a stair can be
either up or down; direction is not applicable to portals.
The default direction is down.
Dec Last change: 12 2
DGN_COMP(6) 1995 DGN_COMP(6)
CHAINBRANCH: name prev_name + ( base , rand ) [ stair |
no_up | no_down | portal ] [ up | down ]
where name is the name of the dungeon to branch to,
prev_name is the name of a previously defined level and (
base , rand ) is the offset from the level being chained
from. The optional branch type and direction are the same
as described above.
GENERIC RULES
Each dungeon must have a unique bonesmarker , and each spe-
cial level must have a bonesmarker unique within its dungeon
(letters may be reused in different dungeons). If the
bonesmarker has the special value "none", no bones files
will be created for that level or dungeon.
The value base may be in the range of 1 to MAXLEVEL (as
defined in global.h ).
The value rand may be in the range of -1 to MAXLEVEL.
If rand is -1 it will be replaced with the value
(num_dunlevs(dungeon) - base) during the load process (ie.
from here to the end of the dungeon).
If rand is 0 the level is located absolutely at base.
Branches don't have a probability. Dungeons do. If a
dungeon fails to be generated during load, all its levels
and branches are skipped.
No level or branch may be chained from a level with a per-
centage generation probability. This is to prevent non-
resolution during the load. In addition, no branch may be
made from a dungeon with a percentage generation probability
for the same reason.
As a general rule using the dungeon compiler:
If a dungeon has a protofile name associated with it (eg.
tower) that file will be used.
If a special level is present, it will override the above
rule and the appropriate file will be loaded.
If neither of the above are present, the standard generator
will take over and make a "normal" level.
A level alignment, if present, will override the alignment
of the dungeon that it exists within.
Dec Last change: 12 3
DGN_COMP(6) 1995 DGN_COMP(6)
EXAMPLE
Here is the current syntax of the dungeon compiler's
"language":
#
# The dungeon description file for the "standard" original
# 3.0 NetHack.
#
DUNGEON: "The Dungeons of Doom" "D" (25, 5)
LEVEL: "rogue" "none" @ (15, 4)
LEVEL: "oracle" "none" @ (5, 7)
LEVEL: "bigroom" "B" @ (12, 3) 15
LEVEL: "medusa" "none" @ (20, 5)
CHAINLEVEL: "castle" "medusa" + (1, 4)
CHAINBRANCH: "Hell" "castle" + (0, 0) no_down
BRANCH: "The Astral Plane" @ (1, 0) no_down up
DUNGEON: "Hell" "H" (25, 5)
DESCRIPTION: mazelike
DESCRIPTION: hellish
BRANCH: "Vlad's Tower" @ (13, 5) up
LEVEL: "wizard" "none" @ (15, 10)
LEVEL: "fakewiz" "A" @ (5, 5)
LEVEL: "fakewiz" "B" @ (10, 5)
LEVEL: "fakewiz" "C" @ (15, 5)
LEVEL: "fakewiz" "D" @ (20, 5)
LEVEL: "fakewiz" "E" @ (25, 5)
DUNGEON: "Vlad's Tower" "T" (3, 0)
PROTOFILE: "tower"
DESCRIPTION: mazelike
ENTRY: -1
DUNGEON: "The Astral Plane" "A" (1, 0)
DESCRIPTION: mazelike
PROTOFILE: "endgame"
NOTES:
Lines beginning with '#' are considered comments.
A special level must be explicitly aligned. The alignment
of the dungeon it is in only applies to non-special levels
within that dungeon.
AUTHOR
M. Stephenson (from the level compiler by Jean-Christophe
Collet).
SEE ALSO
lev_comp(6), nethack(6)
Dec Last change: 12 4
DGN_COMP(6) 1995 DGN_COMP(6)
BUGS
Probably infinite.
Dec Last change: 12 5

View File

@@ -18,22 +18,24 @@ struct couple {
};
struct tmpdungeon {
char name[24], protoname[24];
char *name, *protoname;
struct couple lev;
int flags, chance, levels, branches,
entry_lev; /* entry level for this dungeon */
char boneschar;
int align;
};
struct tmplevel {
char name[24];
char *name;
char *chainlvl;
struct couple lev;
int chance, rndlevs, chain, flags;
char boneschar;
};
struct tmpbranch {
char name[24]; /* destination dungeon name */
char *name; /* destination dungeon name */
struct couple lev;
int chain; /* index into tmplevel array (chained branch)*/
int type; /* branch type (see below) */

View File

@@ -1655,6 +1655,8 @@ E struct selectionvar *FDECL(l_selection_check, (lua_State *, int));
E int FDECL(l_selection_register, (lua_State *));
/* ### nhlua.c ### */
E lua_State * NDECL(nhl_init);
E boolean FDECL(nhl_loadlua, (lua_State *, const char *));
E boolean FDECL(load_lua, (const char *));
E void FDECL(nhl_error, (lua_State *, const char *));
E void FDECL(lcheck_param_table, (lua_State *));

View File

@@ -10,7 +10,7 @@
#include "sfproto.h"
#define DUNGEON_FILE "dungeon"
#define DUNGEON_FILE "dungeon.lua"
#define X_START "x-strt"
#define X_LOCATE "x-loca"
@@ -765,21 +765,56 @@ struct level_map {
{ X_GOAL, &nemesis_level },
{ "", (d_level *) 0 } };
int
get_dgn_flags(L)
lua_State *L;
{
int dgn_flags = 0;
const char *const flagstrs[] = { "town", "hellish", "mazelike", "roguelike", NULL};
const int flagstrs2i[] = { TOWN, HELLISH, MAZELIKE, ROGUELIKE, 0 };
lua_getfield(L, -1, "flags");
if (lua_type(L, -1) == LUA_TTABLE) {
int f, nflags;
lua_len(L, -1);
nflags = lua_tonumber(L, -1);
lua_pop(L, 1);
for (f = 0; f < nflags; f++) {
lua_pushinteger(L, f+1);
lua_gettable(L, -2);
if (lua_type(L, -1) == LUA_TSTRING) {
dgn_flags |= flagstrs2i[luaL_checkoption(L, -1, NULL, flagstrs)];
lua_pop(L, 1);
} else
impossible("flags[%i] is not a string", f);
}
} else if (lua_type(L, -1) == LUA_TSTRING) {
dgn_flags |= flagstrs2i[luaL_checkoption(L, -1, NULL, flagstrs)];
} else if (lua_type(L, -1) != LUA_TNIL)
impossible("flags is not an array or string");
lua_pop(L, 1);
return dgn_flags;
}
/* initialize the "dungeon" structs */
void
init_dungeons()
{
dlb *dgn_file;
const char *const dgnaligns[] = { "unaligned", "noalign", "lawful", "neutral", "chaotic", NULL};
const int dgnaligns2i[] = { D_ALIGN_NONE, D_ALIGN_NONE, D_ALIGN_LAWFUL, D_ALIGN_NEUTRAL, D_ALIGN_CHAOTIC, D_ALIGN_NONE };
lua_State *L;
register int i, cl = 0, cb = 0;
register s_level *x;
struct proto_dungeon pd;
struct level_map *lev_map;
struct version_info vers_info;
(void) memset(&pd, 0, sizeof(struct proto_dungeon));
pd.n_levs = pd.n_brs = 0;
dgn_file = dlb_fopen(DUNGEON_FILE, RDBMODE);
if (!dgn_file) {
L = nhl_init();
if (!nhl_loadlua(L, DUNGEON_FILE)) {
char tbuf[BUFSZ];
Sprintf(tbuf, "Cannot open dungeon description - \"%s", DUNGEON_FILE);
#ifdef DLBRSRC /* using a resource from the executable */
@@ -805,55 +840,186 @@ init_dungeons()
panic1(tbuf);
}
/* validate the data's version against the program's version */
Fread((genericptr_t) &vers_info, sizeof vers_info, 1, dgn_file);
/* we'd better clear the screen now, since when error messages come from
* check_version() they will be printed using pline(), which doesn't
* mix with the raw messages that might be already on the screen
*/
if (iflags.window_inited)
clear_nhwindow(WIN_MAP);
if (!check_version(&vers_info, DUNGEON_FILE, TRUE, UTD_CHECKSIZES))
panic("Dungeon description not valid.");
g.sp_levchn = (s_level *) 0;
lua_settop(L, 0);
lua_getglobal(L, "dungeon");
if (!lua_istable(L, -1))
panic("dungeon is not a lua table");
lua_len(L, -1);
g.n_dgns = lua_tonumber(L, -1);
lua_pop(L, 1);
pd.start = 0;
pd.n_levs = 0;
pd.n_brs = 0;
/*
* Read in each dungeon and transfer the results to the internal
* dungeon arrays.
*/
g.sp_levchn = (s_level *) 0;
Fread((genericptr_t) &g.n_dgns, sizeof(int), 1, dgn_file);
if (g.n_dgns >= MAXDUNGEON)
panic("init_dungeons: too many dungeons");
for (i = 0; i < g.n_dgns; i++) {
Fread((genericptr_t) &pd.tmpdungeon[i], sizeof(struct tmpdungeon), 1,
dgn_file);
if (!wizard && pd.tmpdungeon[i].chance
&& (pd.tmpdungeon[i].chance <= rn2(100))) {
int j;
int tidx = lua_gettop(L);
/* skip over any levels or branches */
for (j = 0; j < pd.tmpdungeon[i].levels; j++)
Fread((genericptr_t) &pd.tmplevel[cl],
sizeof(struct tmplevel), 1, dgn_file);
lua_pushnil(L); /* first key */
i = 0;
while (lua_next(L, tidx) != 0) {
if (!lua_istable(L, -1))
panic("dungeon[%i] is not a lua table", i);
for (j = 0; j < pd.tmpdungeon[i].branches; j++)
Fread((genericptr_t) &pd.tmpbranch[cb],
sizeof(struct tmpbranch), 1, dgn_file);
char *dgn_name = get_table_str(L, "name");
char *dgn_bonetag = get_table_str_opt(L, "bonetag", ""); /* TODO: single char or "none" */
char *dgn_protoname = get_table_str_opt(L, "protofile", "");
int dgn_base = get_table_int(L, "base");
int dgn_range = get_table_int_opt(L, "range", 0);
int dgn_align = dgnaligns2i[get_table_option(L, "alignment", "unaligned", dgnaligns)];
int dgn_entry = get_table_int_opt(L, "entry", 0);
int dgn_chance = get_table_int_opt(L, "chance", 0);
int dgn_flags = get_dgn_flags(L);
debugpline4("DUNGEON[%i]: %s, base=(%i,%i)", i, dgn_name, dgn_base, dgn_range);
if (!wizard && dgn_chance && (dgn_chance <= rn2(100))) {
debugpline1("IGNORING %s", dgn_name);
g.n_dgns--;
i--;
lua_pop(L, 1); /* pop the dungeon table */
continue;
}
Strcpy(g.dungeons[i].dname, pd.tmpdungeon[i].name);
Strcpy(g.dungeons[i].proto, pd.tmpdungeon[i].protoname);
g.dungeons[i].boneid = pd.tmpdungeon[i].boneschar;
/* levels begin */
lua_getfield(L, -1, "levels");
if (lua_type(L, -1) == LUA_TTABLE) {
int f, nlevels;
lua_len(L, -1);
nlevels = lua_tonumber(L, -1);
pd.tmpdungeon[i].levels = nlevels;
lua_pop(L, 1);
for (f = 0; f < nlevels; f++) {
lua_pushinteger(L, f+1);
lua_gettable(L, -2);
if (lua_type(L, -1) == LUA_TTABLE) {
int bi;
char *lvl_name = get_table_str(L, "name");
char *lvl_bonetag = get_table_str_opt(L, "bonetag", "");
int lvl_base = get_table_int(L, "base");
int lvl_range = get_table_int_opt(L, "range", 0);
int lvl_nlevels = get_table_int_opt(L, "nlevels", 0);
int lvl_chance = get_table_int_opt(L, "chance", 0);
char *lvl_chain = get_table_str_opt(L, "chainlevel", NULL);
int lvl_align = dgnaligns2i[get_table_option(L, "alignment", "unaligned", dgnaligns)];
int lvl_flags = get_dgn_flags(L);
struct tmplevel *tmpl = &pd.tmplevel[pd.n_levs + f];
debugpline4("LEVEL[%i]:%s,(%i,%i)", f, lvl_name, lvl_base, lvl_range);
tmpl->name = lvl_name;
tmpl->chainlvl = lvl_chain;
tmpl->lev.base = lvl_base;
tmpl->lev.rand = lvl_range;
tmpl->chance = lvl_chance;
tmpl->rndlevs = lvl_nlevels;
tmpl->flags = lvl_flags;
tmpl->chain = -1;
if (lvl_chain) {
debugpline1("CHAINLEVEL: %s", lvl_chain);
for (bi = 0; bi < pd.n_levs + f; bi++) {
debugpline2("checking(%i):%s", bi, pd.tmplevel[bi].name);
if (!strcmp(pd.tmplevel[bi].name, lvl_chain)) {
tmpl->chain = bi;
break;
}
}
if (tmpl->chain == -1)
panic("Could not chain level %s to %s", lvl_name, lvl_chain);
}
} else
panic("dungeon[%i].levels[%i] is not a hash", i, f);
lua_pop(L, 1);
}
pd.n_levs += nlevels;
if (pd.n_levs > LEV_LIMIT)
panic("init_dungeon: too many special levels");
} else if (lua_type(L, -1) != LUA_TNIL)
panic("dungeon[%i].levels is not an array of hashes", i);
lua_pop(L, 1);
/* levels end */
if (pd.tmpdungeon[i].lev.rand)
g.dungeons[i].num_dunlevs = (xchar) rn1(pd.tmpdungeon[i].lev.rand,
pd.tmpdungeon[i].lev.base);
/* branches begin */
lua_getfield(L, -1, "branches");
if (lua_type(L, -1) == LUA_TTABLE) {
int f, nbranches;
lua_len(L, -1);
nbranches = lua_tonumber(L, -1);
pd.tmpdungeon[i].branches = nbranches;
lua_pop(L, 1);
for (f = 0; f < nbranches; f++) {
lua_pushinteger(L, f+1);
lua_gettable(L, -2);
if (lua_type(L, -1) == LUA_TTABLE) {
int bi;
const char *const brdirstr[] = { "up", "down", NULL };
const int brdirstr2i[] = { TRUE, FALSE, FALSE };
const char *const brtypes[] = { "stair", "portal", "no_down", "no_up", NULL };
const int brtypes2i[] = { TBR_STAIR, TBR_PORTAL, TBR_NO_DOWN, TBR_NO_UP, TBR_STAIR };
char *br_name = get_table_str(L, "name");
int br_base = get_table_int(L, "base");
int br_range = get_table_int_opt(L, "range", 0);
int br_type = brtypes2i[get_table_option(L, "branchtype", "stair", brtypes)];
int br_up = brdirstr2i[get_table_option(L, "direction", "down", brdirstr)];
char *br_chain = get_table_str_opt(L, "chainlevel", NULL);
struct tmpbranch *tmpb = &pd.tmpbranch[pd.n_brs + f];
debugpline4("BRANCH[%i]:%s,(%i,%i)", f, br_name, br_base, br_range);
tmpb->name = br_name;
tmpb->lev.base = br_base;
tmpb->lev.rand = br_range;
tmpb->type = br_type;
tmpb->up = br_up;
tmpb->chain = -1;
if (br_chain) {
debugpline1("CHAINBRANCH:%s", br_chain);
for (bi = 0; bi < pd.n_levs + f - 1; bi++)
if (!strcmp(pd.tmplevel[bi].name, br_chain)) {
tmpb->chain = bi;
break;
}
}
} else
panic("dungeon[%i].branches[%i] is not a hash", i, f);
lua_pop(L, 1);
}
pd.n_brs += nbranches;
if (pd.n_brs > BRANCH_LIMIT)
panic("init_dungeon: too many branches");
} else if (lua_type(L, -1) != LUA_TNIL)
panic("dungeon[%i].branches is not an array of hashes", i);
lua_pop(L, 1);
/* branches end */
pd.tmpdungeon[i].name = dgn_name;
pd.tmpdungeon[i].protoname = dgn_protoname;
pd.tmpdungeon[i].boneschar = *dgn_bonetag ? *dgn_bonetag : 0;
pd.tmpdungeon[i].lev.base = dgn_base;
pd.tmpdungeon[i].lev.rand = dgn_range;
pd.tmpdungeon[i].flags = dgn_flags;
pd.tmpdungeon[i].align = dgn_align;
pd.tmpdungeon[i].chance = dgn_chance;
pd.tmpdungeon[i].entry_lev = dgn_entry;
Strcpy(g.dungeons[i].dname, dgn_name); /* FIXME: dname length */
Strcpy(g.dungeons[i].proto, dgn_protoname); /* FIXME: proto length */
g.dungeons[i].boneid = *dgn_bonetag ? *dgn_bonetag : 0;
if (dgn_range)
g.dungeons[i].num_dunlevs = (xchar) rn1(dgn_range, dgn_base);
else
g.dungeons[i].num_dunlevs = (xchar) pd.tmpdungeon[i].lev.base;
g.dungeons[i].num_dunlevs = (xchar) dgn_base;
if (!i) {
g.dungeons[i].ledger_start = 0;
@@ -865,14 +1031,13 @@ init_dungeons()
g.dungeons[i].dunlev_ureached = 0;
}
g.dungeons[i].flags.hellish = !!(pd.tmpdungeon[i].flags & HELLISH);
g.dungeons[i].flags.maze_like = !!(pd.tmpdungeon[i].flags & MAZELIKE);
g.dungeons[i].flags.rogue_like = !!(pd.tmpdungeon[i].flags & ROGUELIKE);
g.dungeons[i].flags.align =
((pd.tmpdungeon[i].flags & D_ALIGN_MASK) >> 4);
g.dungeons[i].flags.hellish = !!(dgn_flags & HELLISH);
g.dungeons[i].flags.maze_like = !!(dgn_flags & MAZELIKE);
g.dungeons[i].flags.rogue_like = !!(dgn_flags & ROGUELIKE);
g.dungeons[i].flags.align = dgn_align;
/*
* Set the entry level for this dungeon. The pd.tmpdungeon entry
* value means:
* Set the entry level for this dungeon. The entry value means:
* < 0 from bottom (-1 == bottom level)
* 0 default (top)
* > 0 actual level (1 = top)
@@ -880,13 +1045,13 @@ init_dungeons()
* Note that the entry_lev field in the dungeon structure is
* redundant. It is used only here and in print_dungeon().
*/
if (pd.tmpdungeon[i].entry_lev < 0) {
if (dgn_entry < 0) {
g.dungeons[i].entry_lev =
g.dungeons[i].num_dunlevs + pd.tmpdungeon[i].entry_lev + 1;
g.dungeons[i].num_dunlevs + dgn_entry + 1;
if (g.dungeons[i].entry_lev <= 0)
g.dungeons[i].entry_lev = 1;
} else if (pd.tmpdungeon[i].entry_lev > 0) {
g.dungeons[i].entry_lev = pd.tmpdungeon[i].entry_lev;
} else if (dgn_entry > 0) {
g.dungeons[i].entry_lev = dgn_entry;
if (g.dungeons[i].entry_lev > g.dungeons[i].num_dunlevs)
g.dungeons[i].entry_lev = g.dungeons[i].num_dunlevs;
} else { /* default */
@@ -928,23 +1093,14 @@ init_dungeons()
- (g.dungeons[i].entry_lev - 1);
}
/* this is redundant - it should have been flagged by dgn_comp */
if (g.dungeons[i].num_dunlevs > MAXLEVEL)
g.dungeons[i].num_dunlevs = MAXLEVEL;
pd.start = pd.n_levs; /* save starting point */
pd.n_levs += pd.tmpdungeon[i].levels;
if (pd.n_levs > LEV_LIMIT)
panic("init_dungeon: too many special levels");
/*
* Read in the prototype special levels. Don't add generated
* special levels until they are all placed.
*/
for (; cl < pd.n_levs; cl++) {
Fread((genericptr_t) &pd.tmplevel[cl], sizeof(struct tmplevel), 1,
dgn_file);
for (; cl < pd.n_levs; cl++) {
init_level(i, cl, &pd);
}
/*
* Recursively place the generated levels for this dungeon. This
* routine will attempt all possible combinations before giving
@@ -957,18 +1113,18 @@ init_dungeons()
fflush(stderr);
getchar();
#endif
for (; pd.start < pd.n_levs; pd.start++)
if (pd.final_lev[pd.start])
add_level(pd.final_lev[pd.start]);
/* levels handling end */
pd.n_brs += pd.tmpdungeon[i].branches;
if (pd.n_brs > BRANCH_LIMIT)
panic("init_dungeon: too many branches");
for (; cb < pd.n_brs; cb++)
Fread((genericptr_t) &pd.tmpbranch[cb], sizeof(struct tmpbranch),
1, dgn_file);
lua_pop(L, 1); /* pop the dungeon table */
i++;
}
(void) dlb_fclose(dgn_file);
lua_pop(L, 1); /* get rid of the dungeon global */
debugpline2("init_dungeon lua DONE (n_levs=%i, n_brs=%i)", pd.n_levs, pd.n_brs);
for (i = 0; i < 5; i++)
g.tune[i] = 'A' + rn2(7);
@@ -1028,6 +1184,8 @@ init_dungeons()
so that it's hidden from '#wizwhere' feedback. */
}
lua_close(L);
#ifdef DEBUG
dumpit();
#endif

View File

@@ -503,7 +503,7 @@ const char *name;
{
int ret;
lua_getfield(L, 1, name);
lua_getfield(L, -1, name);
ret = (int) luaL_checkinteger(L, -1);
lua_pop(L, 1);
return ret;
@@ -518,7 +518,7 @@ int defval;
{
int ret = defval;
lua_getfield(L, 1, name);
lua_getfield(L, -1, name);
if (!lua_isnil(L, -1)) {
ret = (int) luaL_checkinteger(L, -1);
}
@@ -533,7 +533,7 @@ const char *name;
{
char *ret;
lua_getfield(L, 1, name);
lua_getfield(L, -1, name);
ret = dupstr(luaL_checkstring(L, -1));
lua_pop(L, 1);
return ret;
@@ -549,10 +549,12 @@ char *defval;
{
const char *ret;
lua_getfield(L, 1, name);
lua_getfield(L, -1, name);
ret = luaL_optstring(L, -1, defval);
if (ret)
ret = dupstr(ret);
lua_pop(L, 1);
return ret ? dupstr(ret) : NULL;
return ret;
}
int
@@ -563,7 +565,7 @@ const char *name;
int ltyp;
int ret = -1;
lua_getfield(L, 1, name);
lua_getfield(L, -1, name);
ltyp = lua_type(L, -1);
if (ltyp == LUA_TSTRING) {
const char *const boolstr[] = { "true", "false", "yes", "no", NULL };
@@ -590,7 +592,7 @@ int defval;
{
int ret = defval;
lua_getfield(L, 1, name);
lua_getfield(L, -1, name);
if (lua_type(L, -1) != LUA_TNIL) {
lua_pop(L, 1);
return get_table_boolean(L, name);
@@ -608,7 +610,7 @@ const char *const opts[]; /* NULL-terminated list */
{
int ret;
lua_getfield(L, 1, name);
lua_getfield(L, -1, name);
ret = luaL_checkoption(L, -1, defval, opts);
lua_pop(L, 1);
return ret;
@@ -842,11 +844,9 @@ give_up:
return ret;
}
boolean
load_lua(name)
const char *name;
lua_State *
nhl_init()
{
boolean ret = TRUE;
lua_State *L = luaL_newstate();
luaL_openlibs(L);
@@ -867,6 +867,21 @@ const char *name;
l_register_des(L);
if (!nhl_loadlua(L, "nhlib.lua")) {
lua_close(L);
return (lua_State *) 0;
}
return L;
}
boolean
load_lua(name)
const char *name;
{
boolean ret = TRUE;
lua_State *L = nhl_init();
if (!L) {
ret = FALSE;
goto give_up;
}

View File

@@ -1,27 +0,0 @@
#define INTEGER 257
#define A_DUNGEON 258
#define BRANCH 259
#define CHBRANCH 260
#define LEVEL 261
#define RNDLEVEL 262
#define CHLEVEL 263
#define RNDCHLEVEL 264
#define UP_OR_DOWN 265
#define PROTOFILE 266
#define DESCRIPTION 267
#define DESCRIPTOR 268
#define LEVELDESC 269
#define ALIGNMENT 270
#define LEVALIGN 271
#define ENTRY 272
#define STAIR 273
#define NO_UP 274
#define NO_DOWN 275
#define PORTAL 276
#define STRING 277
typedef union
{
int i;
char* str;
} YYSTYPE;
extern YYSTYPE yylval;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -11,14 +11,11 @@ NHSROOT=..
VARDAT = bogusmon data engrave epitaph rumors quest.dat oracles options
all: $(VARDAT) spec_levs quest_levs dungeon
all: $(VARDAT) spec_levs quest_levs
../util/makedefs:
(cd ../util ; $(MAKE) makedefs)
../util/dgn_comp:
(cd ../util ; $(MAKE) dgn_comp)
../util/tile2x11:
(cd ../util ; $(MAKE) tile2x11)
@@ -129,12 +126,8 @@ spec_levs:
quest_levs:
touch quest_levs
dungeon: dungeon.def ../util/makedefs ../util/dgn_comp
../util/makedefs -e
../util/dgn_comp dungeon.pdf
spotless:
-rm -f spec_levs quest_levs *.lev $(VARDAT) dungeon dungeon.pdf
-rm -f spec_levs quest_levs *.lev $(VARDAT)
-rm -f nhdat x11tiles beostiles pet_mark.xbm pilemark.xbm rip.xpm mapbg.xpm
-rm -f rip.img GEM_RSC.RSC title.img nh16.img NetHack.ad
-rm -f nhsplash.xpm nhtiles.bmp

View File

@@ -67,26 +67,23 @@ MANEXT = 6
# manual installation for most BSD-style systems
GAMEMANCREATE = cat nethack.6 | $(NHGREP) >
DGNMANCREATE = cat dgn_comp.6 | $(NHGREP) >
RCVRMANCREATE = cat recover.6 | $(NHGREP) >
DLBMANCREATE = cat dlb.6 | $(NHGREP) >
MDMANCREATE = cat makedefs.6 | $(NHGREP) >
# manual installation for most SYSV-style systems
# GAMEMANCREATE = cat nethack.6 | $(NHGREP) | nroff -man - >
# DGNMANCREATE = cat dgn_comp.6 | $(NHGREP) | nroff -man - >
# RCVRMANCREATE = cat recover.6 | $(NHGREP) | nroff -man - >
# DLBMANCREATE = cat dlb.6 | $(NHGREP) | nroff -man - >
# MDMANCREATE = cat makedefs.6 | $(NHGREP) | nroff -man - >
manpages:
-$(GAMEMANCREATE) $(MANDIR)/$(GAME).$(MANEXT)
-$(DGNMANCREATE) $(MANDIR)/dgn_comp.$(MANEXT)
-$(RCVRMANCREATE) $(MANDIR)/recover.$(MANEXT)
-$(DLBMANCREATE) $(MANDIR)/dlb.$(MANEXT)
-$(MDMANCREATE) $(MANDIR)/makedefs.$(MANEXT)
# manual creation for distribution
DISTRIB = Guidebook.txt nethack.txt dgn_comp.txt recover.txt \
DISTRIB = Guidebook.txt nethack.txt recover.txt \
dlb.txt makedefs.txt
distrib: $(DISTRIB)
@@ -97,8 +94,6 @@ Guidebook.txt : Guidebook.mn tmac.n tmac.nh
MAN2TXT = $(NHGREP) | nroff -man - | $(COLCMD)
nethack.txt : nethack.6
cat nethack.6 | $(MAN2TXT) > nethack.txt
dgn_comp.txt : dgn_comp.6
cat dgn_comp.6 | $(MAN2TXT) > dgn_comp.txt
recover.txt : recover.6
cat recover.6 | $(MAN2TXT) > recover.txt
dlb.txt : dlb.6

View File

@@ -491,7 +491,7 @@ CSOURCES = $(HACKCSRC) $(SYSCSRC) $(WINCSRC) $(CHAINSRC) $(GENCSRC)
# all .h files except date.h, onames.h, pm.h, and vis_tab.h which would
# cause dependency loops if run through "make depend"
# and dgn_comp.h, dgn_file.h, special level & dungeon files.
# and dgn_file.h, special level & dungeon files.
#
HACKINCL = align.h amiconf.h artifact.h artilist.h attrib.h beconf.h botl.h \
color.h config.h config1.h context.h coord.h decl.h def_os2.h \
@@ -505,7 +505,7 @@ HACKINCL = align.h amiconf.h artifact.h artilist.h attrib.h beconf.h botl.h \
wincurs.h winX.h winprocs.h wintype.h you.h youprop.h
HSOURCES = $(HACKINCL) date.h onames.h pm.h vis_tab.h \
dgn_comp.h dgn_file.h
dgn_file.h
# the following .o's _must_ be made before any others (for makedefs)
FIRSTOBJ = monst.o objects.o

View File

@@ -88,14 +88,14 @@ SPEC_LEVS = asmodeus.lua baalz.lua bigrm-*.lua castle.lua fakewiz?.lua \
QUEST_LEVS = ???-goal.lua ???-fil?.lua ???-loca.lua ???-strt.lua
DATNODLB = $(VARDATND) license symbols
DATDLB = $(DATHELP) dungeon tribute $(SPEC_LEVS) $(QUEST_LEVS) $(VARDATD)
DATDLB = $(DATHELP) dungeon.lua tribute $(SPEC_LEVS) $(QUEST_LEVS) $(VARDATD)
DAT = $(DATNODLB) $(DATDLB)
$(GAME):
( cd lib/lua-5.3.5/src && make a && cp liblua.a ../../../src/ )
( cd src ; $(MAKE) )
all: $(GAME) recover Guidebook $(VARDAT) dungeon spec_levs check-dlb
all: $(GAME) recover Guidebook $(VARDAT) spec_levs check-dlb
true; $(MOREALL)
@echo "Done."
@@ -133,14 +133,10 @@ options: $(GAME)
quest.dat: $(GAME)
( cd dat ; $(MAKE) quest.dat )
spec_levs: dungeon
spec_levs:
( cd dat ; $(MAKE) spec_levs )
( cd dat ; $(MAKE) quest_levs )
dungeon: $(GAME)
( cd util ; $(MAKE) dgn_comp )
( cd dat ; $(MAKE) dungeon )
nhtiles.bmp: $(GAME)
( cd dat ; $(MAKE) nhtiles.bmp )
@@ -237,7 +233,7 @@ dofiles-nodlb:
$(CHGRP) $(GAMEGRP) $(DAT) ; \
chmod $(FILEPERM) $(DAT) )
update: $(GAME) recover $(VARDAT) dungeon spec_levs
update: $(GAME) recover $(VARDAT) spec_levs
# (don't yank the old version out from under people who're playing it)
-mv $(INSTDIR)/$(GAME) $(INSTDIR)/$(GAME).old
# quest.dat is also kept open and has the same problems over NFS
@@ -256,7 +252,7 @@ update: $(GAME) recover $(VARDAT) dungeon spec_levs
rootcheck:
@true; $(ROOTCHECK)
install: rootcheck $(GAME) recover $(VARDAT) dungeon spec_levs
install: rootcheck $(GAME) recover $(VARDAT) spec_levs
true; $(PREINSTALL)
# set up the directories
# not all mkdirs have -p; those that don't will create a -p directory

View File

@@ -186,7 +186,6 @@ HACK_H = ../src/hack.h-t
# utility .c files
MAKESRC = makedefs.c
DGNCOMPSRC = dgn_yacc.c dgn_lex.c dgn_main.c
RECOVSRC = recover.c
DLBSRC = dlb_main.c
UTILSRCS = $(MAKESRC) panic.c $(DGNCOMPSRC) $(RECOVSRC) $(DLBSRC)
@@ -205,9 +204,6 @@ OALLOC = $(OBJDIR)/alloc.o panic.o
# object files for makedefs
MAKEOBJS = makedefs.o $(OMONOBJ)
# object files for dungeon compiler
DGNCOMPOBJS = dgn_yacc.o dgn_lex.o dgn_main.o $(OALLOC)
# object files for recovery utility
RECOVOBJS = recover.o
@@ -267,35 +263,6 @@ lintdefs:
panic.o: panic.c $(CONFIG_H)
# dependencies for dgn_comp
#
dgn_comp: $(DGNCOMPOBJS)
$(CC) $(LFLAGS) -o dgn_comp $(DGNCOMPOBJS) $(LIBS)
dgn_yacc.o: dgn_yacc.c $(CONFIG_H) ../include/dgn_file.h ../include/date.h
dgn_main.o: dgn_main.c $(CONFIG_H) ../include/dlb.h
# see dgn_comp.l for WEIRD_LEX discussion
dgn_lex.o: dgn_lex.c $(CONFIG_H) ../include/dgn_comp.h ../include/dgn_file.h
$(CC) -c $(CFLAGS) -DWEIRD_LEX=`egrep -c _cplusplus dgn_lex.c` dgn_lex.c
# '$(YACC) -d' generates both $(YTABC) and $(YTABH) in one run
../include/dgn_comp.h: dgn_yacc.c
dgn_yacc.c: dgn_comp.y
$(YACC) $(YACCDIST) -d dgn_comp.y
sed -e 's#"$(YTABC)"#"$@"#' -e 's#$(YTABC):#$@:#' $(YTABC) > $@ \
&& rm $(YTABC)
sed -e 's#"$(YTABH)"#"dgn_comp.h"#' $(YTABH) > ../include/dgn_comp.h \
&& rm $(YTABH)
dgn_lex.c: dgn_comp.l
$(LEX) $(FLEXDIST) dgn_comp.l
sed -e 's#"$(LEXYYC)"#"$@"#' -e 's# *$$##' \
-e 's#static void yyunput#void yyunput#' $(LEXYYC) > $@ \
&& rm $(LEXYYC)
# note: <space><space><star> is basic RE substitute for <space><plus>
# with all of extern.h's functions to complain about, we drown in
# 'defined but not used' without -u
lintdgn:
@@ -501,17 +468,7 @@ $(HACK_H): $(CONFIG_H)
$(CONFIG_H): ../include/config.h
@( cd ../src ; $(MAKE) $(CONFIG_H) )
# 'make dist' => put generated lex and yacc sources into place for distribution
SYSSHARE=../sys/share/
$(SYSSHARE)dgn_lex.c: dgn_lex.c
cp dgn_lex.c $@
$(SYSSHARE)dgn_yacc.c: dgn_yacc.c
cp dgn_yacc.c $@
$(SYSSHARE)dgn_comp.h: ../include/dgn_comp.h
cp ../include/dgn_comp.h $@
dist: $(SYSSHARE)dgn_lex.c $(SYSSHARE)dgn_yacc.c $(SYSSHARE)dgn_comp.h
@echo 'pre-generated lex and yacc sources are in place in sys/share'
tags: $(UTILSRCS)
@ctags -tw $(UTILSRCS)
@@ -520,9 +477,7 @@ clean:
-rm -f *.o
spotless: clean
-rm -f dgn_lex.c dgn_yacc.c
-rm -f ../include/dgn_comp.h
-rm -f ../include/tile.h tiletxt.c
-rm -f makedefs dgn_comp recover dlb
-rm -f makedefs recover dlb
-rm -f gif2txt txt2ppm tile2x11 tile2img.ttp xpm2img.ttp \
tilemap tileedit tile2bmp

View File

@@ -1,144 +0,0 @@
%{
/* NetHack 3.6 dgn_comp.l $NHDT-Date: 1455415007 2016/02/14 01:56:47 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.13 $ */
/* Copyright (c) 1989 by Jean-Christophe Collet */
/* Copyright (c) 1990 by M. Stephenson */
/* NetHack may be freely redistributed. See license for details. */
#define DGN_COMP
#include "config.h"
#include "dgn_comp.h"
#include "dgn_file.h"
/*
* Most of these don't exist in flex, yywrap is macro and
* yyunput is properly declared in flex.skel.
*/
#if !defined(FLEX_SCANNER) && !defined(FLEXHACK_SCANNER)
int FDECL(yyback, (int *,int));
int NDECL(yylook);
int NDECL(yyinput);
int NDECL(yywrap);
int NDECL(yylex);
/* Traditional lexes let yyunput() and yyoutput() default to int;
* newer ones may declare them as void since they don't return
* values. For even more fun, the lex supplied as part of the
* newer unbundled compiler for SunOS 4.x adds the void declarations
* (under __STDC__ or _cplusplus ifdefs -- otherwise they remain
* int) while the bundled lex and the one with the older unbundled
* compiler do not. To detect this, we need help from outside --
* sys/unix/Makefile.utl.
*
* Digital UNIX is difficult and still has int in spite of all
* other signs.
*/
# if defined(NeXT) || defined(SVR4) || defined(_AIX32)
# define VOIDYYPUT
# endif
# if !defined(VOIDYYPUT) && defined(POSIX_TYPES)
# if !defined(BOS) && !defined(HISX) && !defined(_M_UNIX) && !defined(VMS)
# define VOIDYYPUT
# endif
# endif
# if !defined(VOIDYYPUT) && defined(WEIRD_LEX)
# if defined(SUNOS4) && defined(__STDC__) && (WEIRD_LEX > 1)
# define VOIDYYPUT
# endif
# endif
# if defined(VOIDYYPUT) && defined(__osf__)
# undef VOIDYYPUT
# endif
# ifdef VOIDYYPUT
void FDECL(yyunput, (int));
void FDECL(yyoutput, (int));
# else
int FDECL(yyunput, (int));
int FDECL(yyoutput, (int));
# endif
#else /* !FLEX_SCANNER && !FLEXHACK_SCANNER */
/* most recent flex allows suppressing yyunput() altogether when not needed */
#define YY_NO_UNPUT
#define YY_NO_INPUT
#endif
#if defined(FLEX_SCANNER) || defined(FLEXHACK_SCANNER)
/* older flex wants this */
#define YY_MALLOC_DECL genericptr_t FDECL(malloc, (size_t)); \
genericptr_t FDECL(realloc, (genericptr_t, size_t));
/* newer flex assumes <stdlib.h> so needs this in case it's been suppressed */
YY_MALLOC_DECL
#endif
void FDECL(init_yyin, (FILE *));
void FDECL(init_yyout, (FILE *));
/* this doesn't always get put in dgn_comp.h
* (esp. when using older versions of bison)
*/
extern YYSTYPE yylval;
int nh_line_number = 1;
%}
%%
DUNGEON return(A_DUNGEON);
up { yylval.i=1; return(UP_OR_DOWN); }
down { yylval.i=0; return(UP_OR_DOWN); }
ENTRY return(ENTRY);
stair return(STAIR);
no_up return(NO_UP);
no_down return(NO_DOWN);
portal return(PORTAL);
PROTOFILE return(PROTOFILE);
DESCRIPTION return(DESCRIPTION);
LEVELDESC return(LEVELDESC);
ALIGNMENT return(ALIGNMENT);
LEVALIGN return(LEVALIGN);
town { yylval.i=TOWN ; return(DESCRIPTOR); }
hellish { yylval.i=HELLISH ; return(DESCRIPTOR); }
mazelike { yylval.i=MAZELIKE ; return(DESCRIPTOR); }
roguelike { yylval.i=ROGUELIKE ; return(DESCRIPTOR); }
unaligned { yylval.i=D_ALIGN_NONE ; return(DESCRIPTOR); }
noalign { yylval.i=D_ALIGN_NONE ; return(DESCRIPTOR); }
lawful { yylval.i=D_ALIGN_LAWFUL ; return(DESCRIPTOR); }
neutral { yylval.i=D_ALIGN_NEUTRAL ; return(DESCRIPTOR); }
chaotic { yylval.i=D_ALIGN_CHAOTIC ; return(DESCRIPTOR); }
BRANCH return(BRANCH);
CHAINBRANCH return(CHBRANCH);
LEVEL return(LEVEL);
RNDLEVEL return(RNDLEVEL);
CHAINLEVEL return(CHLEVEL);
RNDCHLEVEL return(RNDCHLEVEL);
[-0-9]+ { yylval.i=atoi(yytext); return(INTEGER); }
\"[^"]*\" { yytext[yyleng - 1] = '\0'; /* discard the trailing \" */
yylval.str = dupstr(yytext + 1); /* skip the first \" */
return STRING; }
^#.*\n { nh_line_number++; }
\r?\n { nh_line_number++; }
[ \t]+ ; /* skip trailing tabs & spaces */
. { return yytext[0]; }
%%
/* routine to switch to another input file; needed for flex */
void
init_yyin( input_f )
FILE *input_f;
{
#if defined(FLEX_SCANNER) || defined(FLEXHACK_SCANNER)
if (yyin)
yyrestart(input_f);
else
#endif
yyin = input_f;
}
/* analogous routine (for completeness) */
void
init_yyout( output_f )
FILE *output_f;
{
yyout = output_f;
}
/*dgn_comp.l*/

View File

@@ -1,678 +0,0 @@
%{
/* NetHack 3.6 dgn_comp.y $NHDT-Date: 1432512785 2015/05/25 00:13:05 $ $NHDT-Branch: master $:$NHDT-Revision: 1.8 $ */
/* Copyright (c) 1989 by Jean-Christophe Collet */
/* Copyright (c) 1990 by M. Stephenson */
/* NetHack may be freely redistributed. See license for details. */
/*
* This file contains the Dungeon Compiler code
*/
/* In case we're using bison in AIX. This definition must be
* placed before any other C-language construct in the file
* excluding comments and preprocessor directives (thanks IBM
* for this wonderful feature...).
*
* Note: some cpps barf on this 'undefined control' (#pragma).
* Addition of the leading space seems to prevent barfage for now,
* and AIX will still see the directive in its non-standard locale.
*/
#ifdef _AIX
#pragma alloca /* keep leading space! */
#endif
#include "config.h"
#include "date.h"
#include "dgn_file.h"
void FDECL(yyerror, (const char *));
void FDECL(yywarning, (const char *));
int NDECL(yylex);
int NDECL(yyparse);
int FDECL(getchain, (char *));
int NDECL(check_dungeon);
int NDECL(check_branch);
int NDECL(check_level);
void NDECL(init_dungeon);
void NDECL(init_branch);
void NDECL(init_level);
void NDECL(output_dgn);
#define Free(ptr) free((genericptr_t)ptr)
#ifdef AMIGA
# undef printf
#ifndef LATTICE
# define memset(addr,val,len) setmem(addr,len,val)
#endif
#endif
#define ERR (-1)
static struct couple couple;
static struct tmpdungeon tmpdungeon[MAXDUNGEON];
static struct tmplevel tmplevel[LEV_LIMIT];
static struct tmpbranch tmpbranch[BRANCH_LIMIT];
static int in_dungeon = 0, n_dgns = -1, n_levs = -1, n_brs = -1;
extern int fatal_error;
extern const char *fname;
extern FILE *yyin, *yyout; /* from dgn_lex.c */
%}
%union
{
int i;
char* str;
}
%token <i> INTEGER
%token <i> A_DUNGEON BRANCH CHBRANCH LEVEL RNDLEVEL CHLEVEL RNDCHLEVEL
%token <i> UP_OR_DOWN PROTOFILE DESCRIPTION DESCRIPTOR LEVELDESC
%token <i> ALIGNMENT LEVALIGN ENTRY STAIR NO_UP NO_DOWN PORTAL
%token <str> STRING
%type <i> optional_int direction branch_type bones_tag
%start file
%%
file : /* nothing */
| dungeons
{
output_dgn();
}
;
dungeons : dungeon
| dungeons dungeon
;
dungeon : dungeonline
| dungeondesc
| branches
| levels
;
dungeonline : A_DUNGEON ':' STRING bones_tag rcouple optional_int
{
init_dungeon();
Strcpy(tmpdungeon[n_dgns].name, $3);
tmpdungeon[n_dgns].boneschar = (char)$4;
tmpdungeon[n_dgns].lev.base = couple.base;
tmpdungeon[n_dgns].lev.rand = couple.rand;
tmpdungeon[n_dgns].chance = $6;
Free($3);
}
;
optional_int : /* nothing */
{
$$ = 0;
}
| INTEGER
{
$$ = $1;
}
;
dungeondesc : entry
| descriptions
| prototype
;
entry : ENTRY ':' INTEGER
{
tmpdungeon[n_dgns].entry_lev = $3;
}
;
descriptions : desc
;
desc : DESCRIPTION ':' DESCRIPTOR
{
if($<i>3 <= TOWN || $<i>3 >= D_ALIGN_CHAOTIC)
yyerror("Illegal description - ignoring!");
else
tmpdungeon[n_dgns].flags |= $<i>3 ;
}
| ALIGNMENT ':' DESCRIPTOR
{
if($<i>3 && $<i>3 < D_ALIGN_CHAOTIC)
yyerror("Illegal alignment - ignoring!");
else
tmpdungeon[n_dgns].flags |= $<i>3 ;
}
;
prototype : PROTOFILE ':' STRING
{
Strcpy(tmpdungeon[n_dgns].protoname, $3);
Free($3);
}
;
levels : level1
| level2
| levdesc
| chlevel1
| chlevel2
;
level1 : LEVEL ':' STRING bones_tag '@' acouple
{
init_level();
Strcpy(tmplevel[n_levs].name, $3);
tmplevel[n_levs].boneschar = (char)$4;
tmplevel[n_levs].lev.base = couple.base;
tmplevel[n_levs].lev.rand = couple.rand;
tmpdungeon[n_dgns].levels++;
Free($3);
}
| RNDLEVEL ':' STRING bones_tag '@' acouple INTEGER
{
init_level();
Strcpy(tmplevel[n_levs].name, $3);
tmplevel[n_levs].boneschar = (char)$4;
tmplevel[n_levs].lev.base = couple.base;
tmplevel[n_levs].lev.rand = couple.rand;
tmplevel[n_levs].rndlevs = $7;
tmpdungeon[n_dgns].levels++;
Free($3);
}
;
level2 : LEVEL ':' STRING bones_tag '@' acouple INTEGER
{
init_level();
Strcpy(tmplevel[n_levs].name, $3);
tmplevel[n_levs].boneschar = (char)$4;
tmplevel[n_levs].lev.base = couple.base;
tmplevel[n_levs].lev.rand = couple.rand;
tmplevel[n_levs].chance = $7;
tmpdungeon[n_dgns].levels++;
Free($3);
}
| RNDLEVEL ':' STRING bones_tag '@' acouple INTEGER INTEGER
{
init_level();
Strcpy(tmplevel[n_levs].name, $3);
tmplevel[n_levs].boneschar = (char)$4;
tmplevel[n_levs].lev.base = couple.base;
tmplevel[n_levs].lev.rand = couple.rand;
tmplevel[n_levs].chance = $7;
tmplevel[n_levs].rndlevs = $8;
tmpdungeon[n_dgns].levels++;
Free($3);
}
;
levdesc : LEVELDESC ':' DESCRIPTOR
{
if($<i>3 >= D_ALIGN_CHAOTIC)
yyerror("Illegal description - ignoring!");
else
tmplevel[n_levs].flags |= $<i>3 ;
}
| LEVALIGN ':' DESCRIPTOR
{
if($<i>3 && $<i>3 < D_ALIGN_CHAOTIC)
yyerror("Illegal alignment - ignoring!");
else
tmplevel[n_levs].flags |= $<i>3 ;
}
;
chlevel1 : CHLEVEL ':' STRING bones_tag STRING '+' rcouple
{
init_level();
Strcpy(tmplevel[n_levs].name, $3);
tmplevel[n_levs].boneschar = (char)$4;
tmplevel[n_levs].chain = getchain($5);
tmplevel[n_levs].lev.base = couple.base;
tmplevel[n_levs].lev.rand = couple.rand;
if(!check_level()) n_levs--;
else tmpdungeon[n_dgns].levels++;
Free($3);
Free($5);
}
| RNDCHLEVEL ':' STRING bones_tag STRING '+' rcouple INTEGER
{
init_level();
Strcpy(tmplevel[n_levs].name, $3);
tmplevel[n_levs].boneschar = (char)$4;
tmplevel[n_levs].chain = getchain($5);
tmplevel[n_levs].lev.base = couple.base;
tmplevel[n_levs].lev.rand = couple.rand;
tmplevel[n_levs].rndlevs = $8;
if(!check_level()) n_levs--;
else tmpdungeon[n_dgns].levels++;
Free($3);
Free($5);
}
;
chlevel2 : CHLEVEL ':' STRING bones_tag STRING '+' rcouple INTEGER
{
init_level();
Strcpy(tmplevel[n_levs].name, $3);
tmplevel[n_levs].boneschar = (char)$4;
tmplevel[n_levs].chain = getchain($5);
tmplevel[n_levs].lev.base = couple.base;
tmplevel[n_levs].lev.rand = couple.rand;
tmplevel[n_levs].chance = $8;
if(!check_level()) n_levs--;
else tmpdungeon[n_dgns].levels++;
Free($3);
Free($5);
}
| RNDCHLEVEL ':' STRING bones_tag STRING '+' rcouple INTEGER INTEGER
{
init_level();
Strcpy(tmplevel[n_levs].name, $3);
tmplevel[n_levs].boneschar = (char)$4;
tmplevel[n_levs].chain = getchain($5);
tmplevel[n_levs].lev.base = couple.base;
tmplevel[n_levs].lev.rand = couple.rand;
tmplevel[n_levs].chance = $8;
tmplevel[n_levs].rndlevs = $9;
if(!check_level()) n_levs--;
else tmpdungeon[n_dgns].levels++;
Free($3);
Free($5);
}
;
branches : branch
| chbranch
;
branch : BRANCH ':' STRING '@' acouple branch_type direction
{
init_branch();
Strcpy(tmpbranch[n_brs].name, $3);
tmpbranch[n_brs].lev.base = couple.base;
tmpbranch[n_brs].lev.rand = couple.rand;
tmpbranch[n_brs].type = $6;
tmpbranch[n_brs].up = $7;
if(!check_branch()) n_brs--;
else tmpdungeon[n_dgns].branches++;
Free($3);
}
;
chbranch : CHBRANCH ':' STRING STRING '+' rcouple branch_type direction
{
init_branch();
Strcpy(tmpbranch[n_brs].name, $3);
tmpbranch[n_brs].chain = getchain($4);
tmpbranch[n_brs].lev.base = couple.base;
tmpbranch[n_brs].lev.rand = couple.rand;
tmpbranch[n_brs].type = $7;
tmpbranch[n_brs].up = $8;
if(!check_branch()) n_brs--;
else tmpdungeon[n_dgns].branches++;
Free($3);
Free($4);
}
;
branch_type : /* nothing */
{
$$ = TBR_STAIR; /* two way stair */
}
| STAIR
{
$$ = TBR_STAIR; /* two way stair */
}
| NO_UP
{
$$ = TBR_NO_UP; /* no up staircase */
}
| NO_DOWN
{
$$ = TBR_NO_DOWN; /* no down staircase */
}
| PORTAL
{
$$ = TBR_PORTAL; /* portal connection */
}
;
direction : /* nothing */
{
$$ = 0; /* defaults to down */
}
| UP_OR_DOWN
{
$$ = $1;
}
;
bones_tag : STRING
{
char *p = $1;
if (strlen(p) != 1) {
if (strcmp(p, "none") != 0)
yyerror("Bones marker must be a single char, or \"none\"!");
*p = '\0';
}
$$ = *p;
Free(p);
}
;
/*
* acouple rules:
*
* (base, range) where:
*
* base is either a positive or negative integer with a value
* less than or equal to MAXLEVEL.
* base > 0 indicates the base level.
* base < 0 indicates reverse index (-1 == lowest level)
*
* range is the random component.
* if range is zero, there is no random component.
* if range is -1 the dungeon loader will randomize between
* the base and the end of the dungeon.
* during dungeon load, range is always *added* to the base,
* therefore range + base(converted) must not exceed MAXLEVEL.
*/
acouple : '(' INTEGER ',' INTEGER ')'
{
if ($2 < -MAXLEVEL || $2 > MAXLEVEL) {
yyerror("Abs base out of dlevel range - zeroing!");
couple.base = couple.rand = 0;
} else if ($4 < -1 ||
(($2 < 0) ? (MAXLEVEL + $2 + $4 + 1) > MAXLEVEL :
($2 + $4) > MAXLEVEL)) {
yyerror("Abs range out of dlevel range - zeroing!");
couple.base = couple.rand = 0;
} else {
couple.base = $2;
couple.rand = $4;
}
}
;
/*
* rcouple rules:
*
* (base, range) where:
*
* base is either a positive or negative integer with a value
* less than or equal to MAXLEVEL.
* base > 0 indicates a forward index.
* base < 0 indicates a reverse index.
* base == 0 indicates on the parent level.
*
* range is the random component.
* if range is zero, there is no random component.
* during dungeon load, range is always *added* to the base,
* range + base(converted) may be very large. The dungeon
* loader will then correct to "between here and the top/bottom".
*
* There is no practical way of specifying "between here and the
* nth / nth last level".
*/
rcouple : '(' INTEGER ',' INTEGER ')'
{
if ($2 < -MAXLEVEL || $2 > MAXLEVEL) {
yyerror("Rel base out of dlevel range - zeroing!");
couple.base = couple.rand = 0;
} else {
couple.base = $2;
couple.rand = $4;
}
}
;
%%
void
init_dungeon()
{
if(++n_dgns > MAXDUNGEON) {
(void) fprintf(stderr, "FATAL - Too many dungeons (limit: %d).\n",
MAXDUNGEON);
(void) fprintf(stderr, "To increase the limit edit MAXDUNGEON in global.h\n");
exit(EXIT_FAILURE);
}
in_dungeon = 1;
tmpdungeon[n_dgns].lev.base = 0;
tmpdungeon[n_dgns].lev.rand = 0;
tmpdungeon[n_dgns].chance = 100;
Strcpy(tmpdungeon[n_dgns].name, "");
Strcpy(tmpdungeon[n_dgns].protoname, "");
tmpdungeon[n_dgns].flags = 0;
tmpdungeon[n_dgns].levels = 0;
tmpdungeon[n_dgns].branches = 0;
tmpdungeon[n_dgns].entry_lev = 0;
}
void
init_level()
{
if(++n_levs > LEV_LIMIT) {
yyerror("FATAL - Too many special levels defined.");
exit(EXIT_FAILURE);
}
tmplevel[n_levs].lev.base = 0;
tmplevel[n_levs].lev.rand = 0;
tmplevel[n_levs].chance = 100;
tmplevel[n_levs].rndlevs = 0;
tmplevel[n_levs].flags = 0;
Strcpy(tmplevel[n_levs].name, "");
tmplevel[n_levs].chain = -1;
}
void
init_branch()
{
if(++n_brs > BRANCH_LIMIT) {
yyerror("FATAL - Too many special levels defined.");
exit(EXIT_FAILURE);
}
tmpbranch[n_brs].lev.base = 0;
tmpbranch[n_brs].lev.rand = 0;
Strcpy(tmpbranch[n_brs].name, "");
tmpbranch[n_brs].chain = -1;
}
int
getchain(s)
char *s;
{
int i;
if(strlen(s)) {
for(i = n_levs - tmpdungeon[n_dgns].levels + 1; i <= n_levs; i++)
if(!strcmp(tmplevel[i].name, s)) return i;
yyerror("Can't locate the specified chain level.");
return(-2);
}
return(-1);
}
/*
* Consistancy checking routines:
*
* - A dungeon must have a unique name.
* - A dungeon must have a originating "branch" command
* (except, of course, for the first dungeon).
* - A dungeon must have a proper depth (at least (1, 0)).
*/
int
check_dungeon()
{
int i;
for(i = 0; i < n_dgns; i++)
if(!strcmp(tmpdungeon[i].name, tmpdungeon[n_dgns].name)) {
yyerror("Duplicate dungeon name.");
return(0);
}
if(n_dgns)
for(i = 0; i < n_brs - tmpdungeon[n_dgns].branches; i++) {
if(!strcmp(tmpbranch[i].name, tmpdungeon[n_dgns].name)) break;
if(i >= n_brs - tmpdungeon[n_dgns].branches) {
yyerror("Dungeon cannot be reached.");
return(0);
}
}
if(tmpdungeon[n_dgns].lev.base <= 0 ||
tmpdungeon[n_dgns].lev.rand < 0) {
yyerror("Invalid dungeon depth specified.");
return(0);
}
return(1); /* OK */
}
/*
* - A level must have a unique level name.
* - If chained, the level used as reference for the chain
* must be in this dungeon, must be previously defined, and
* the level chained from must be "non-probabilistic" (ie.
* have a 100% chance of existing).
*/
int
check_level()
{
int i;
if(!in_dungeon) {
yyerror("Level defined outside of dungeon.");
return(0);
}
for(i = 0; i < n_levs; i++)
if(!strcmp(tmplevel[i].name, tmplevel[n_levs].name)) {
yyerror("Duplicate level name.");
return(0);
}
if(tmplevel[i].chain == -2) {
yyerror("Invaild level chain reference.");
return(0);
} else if(tmplevel[i].chain != -1) { /* there is a chain */
/* KMH -- tmplevel[tmpbranch[i].chain].chance was in error */
if(tmplevel[tmplevel[i].chain].chance != 100) {
yyerror("Level cannot chain from a probabilistic level.");
return(0);
} else if(tmplevel[i].chain == n_levs) {
yyerror("A level cannot chain to itself!");
return(0);
}
}
return(1); /* OK */
}
/*
* - A branch may not branch backwards - to avoid branch loops.
* - A branch name must be unique.
* (ie. You can only have one entry point to each dungeon).
* - If chained, the level used as reference for the chain
* must be in this dungeon, must be previously defined, and
* the level chained from must be "non-probabilistic" (ie.
* have a 100% chance of existing).
*/
int
check_branch()
{
int i;
if(!in_dungeon) {
yyerror("Branch defined outside of dungeon.");
return(0);
}
for(i = 0; i < n_dgns; i++)
if(!strcmp(tmpdungeon[i].name, tmpbranch[n_brs].name)) {
yyerror("Reverse branching not allowed.");
return(0);
}
if(tmpbranch[i].chain == -2) {
yyerror("Invaild branch chain reference.");
return(0);
} else if(tmpbranch[i].chain != -1) { /* it is chained */
if(tmplevel[tmpbranch[i].chain].chance != 100) {
yyerror("Branch cannot chain from a probabilistic level.");
return(0);
}
}
return(1); /* OK */
}
/*
* Output the dungon definition into a file.
*
* The file will have the following format:
*
* [ nethack version ID ]
* [ number of dungeons ]
* [ first dungeon struct ]
* [ levels for the first dungeon ]
* ...
* [ branches for the first dungeon ]
* ...
* [ second dungeon struct ]
* ...
*/
void
output_dgn()
{
int nd, cl = 0, nl = 0,
cb = 0, nb = 0;
static struct version_info version_data = {
VERSION_NUMBER, VERSION_FEATURES,
VERSION_SANITY1, VERSION_SANITY2, VERSION_SANITY3
};
if(++n_dgns <= 0) {
yyerror("FATAL - no dungeons were defined.");
exit(EXIT_FAILURE);
}
if (fwrite((char *)&version_data, sizeof version_data, 1, yyout) != 1) {
yyerror("FATAL - output failure.");
exit(EXIT_FAILURE);
}
(void) fwrite((char *)&n_dgns, sizeof(int), 1, yyout);
for (nd = 0; nd < n_dgns; nd++) {
(void) fwrite((char *)&tmpdungeon[nd], sizeof(struct tmpdungeon),
1, yyout);
nl += tmpdungeon[nd].levels;
for(; cl < nl; cl++)
(void) fwrite((char *)&tmplevel[cl], sizeof(struct tmplevel),
1, yyout);
nb += tmpdungeon[nd].branches;
for(; cb < nb; cb++)
(void) fwrite((char *)&tmpbranch[cb], sizeof(struct tmpbranch),
1, yyout);
}
/* apparently necessary for Think C 5.x, otherwise harmless */
(void) fflush(yyout);
}
/*dgn_comp.y*/

View File

@@ -1,193 +0,0 @@
/* NetHack 3.6 dgn_main.c $NHDT-Date: 1432512785 2015/05/25 00:13:05 $ $NHDT-Branch: master $:$NHDT-Revision: 1.11 $ */
/* Copyright (c) 1989 by Jean-Christophe Collet */
/* Copyright (c) 1990 by M. Stephenson */
/* NetHack may be freely redistributed. See license for details. */
/*
* This file contains the main function for the parser
* and some useful functions needed by yacc
*/
#include "config.h"
#include "dlb.h"
/* Macintosh-specific code */
#if defined(__APPLE__) && defined(__MACH__)
/* MacOS X has Unix-style files and processes */
#undef MAC
#endif
#ifdef MAC
#if defined(__SC__) || defined(__MRC__)
#define MPWTOOL
#include <CursorCtl.h>
#else
/* put dungeon file in library location */
#define PREFIX ":lib:"
#endif
#endif
#ifndef MPWTOOL
#define SpinCursor(x)
#endif
#define MAX_ERRORS 25
extern int NDECL(yyparse);
extern int nh_line_number;
const char *fname = "(stdin)";
int fatal_error = 0;
int FDECL(main, (int, char **));
void FDECL(yyerror, (const char *));
void FDECL(yywarning, (const char *));
int NDECL(yywrap);
void FDECL(init_yyin, (FILE *));
void FDECL(init_yyout, (FILE *));
#ifdef AZTEC_36
FILE *FDECL(freopen, (char *, char *, FILE *));
#endif
#define Fprintf (void) fprintf
#if defined(__BORLANDC__) && !defined(_WIN32)
extern unsigned _stklen = STKSIZ;
#endif
int
main(argc, argv)
int argc;
char **argv;
{
char infile[64], outfile[64], basename[64];
FILE *fin, *fout;
int i, len;
boolean errors_encountered = FALSE;
#if defined(MAC) && (defined(THINK_C) || defined(__MWERKS__))
char *mark;
static char *mac_argv[] = { "dgn_comp", /* dummy argv[0] */
":dat:dungeon.pdf" };
argc = SIZE(mac_argv);
argv = mac_argv;
#endif
Strcpy(infile, "(stdin)");
fin = stdin;
Strcpy(outfile, "(stdout)");
fout = stdout;
if (argc == 1) { /* Read standard input */
init_yyin(fin);
init_yyout(fout);
(void) yyparse();
if (fatal_error > 0)
errors_encountered = TRUE;
} else { /* Otherwise every argument is a filename */
for (i = 1; i < argc; i++) {
fname = strcpy(infile, argv[i]);
/* the input file had better be a .pdf file */
len = strlen(fname) - 4; /* length excluding suffix */
if (len < 0 || strncmp(".pdf", fname + len, 4)) {
Fprintf(stderr, "Error - file name \"%s\" in wrong format.\n",
fname);
errors_encountered = TRUE;
continue;
}
/* build output file name */
#if defined(MAC) && (defined(THINK_C) || defined(__MWERKS__))
/* extract basename from path to infile */
mark = strrchr(infile, ':');
strcpy(basename, mark ? mark + 1 : infile);
mark = strchr(basename, '.');
if (mark)
*mark = '\0';
#else
/* Use the whole name - strip off the last 3 or 4 chars. */
#ifdef VMS /* avoid possible interaction with logical name */
len++; /* retain "." as trailing punctuation */
#endif
(void) strncpy(basename, infile, len);
basename[len] = '\0';
#endif
outfile[0] = '\0';
#ifdef PREFIX
(void) strcat(outfile, PREFIX);
#endif
(void) strcat(outfile, basename);
fin = freopen(infile, "r", stdin);
if (!fin) {
Fprintf(stderr, "Can't open %s for input.\n", infile);
perror(infile);
errors_encountered = TRUE;
continue;
}
fout = freopen(outfile, WRBMODE, stdout);
if (!fout) {
Fprintf(stderr, "Can't open %s for output.\n", outfile);
perror(outfile);
errors_encountered = TRUE;
continue;
}
init_yyin(fin);
init_yyout(fout);
(void) yyparse();
nh_line_number = 1;
if (fatal_error > 0) {
errors_encountered = TRUE;
fatal_error = 0;
}
}
}
if (fout && fclose(fout) < 0) {
Fprintf(stderr, "Can't finish output file.");
perror(outfile);
errors_encountered = TRUE;
}
exit(errors_encountered ? EXIT_FAILURE : EXIT_SUCCESS);
/*NOTREACHED*/
return 0;
}
/*
* Each time the parser detects an error, it uses this function.
* Here we take count of the errors. To continue farther than
* MAX_ERRORS wouldn't be reasonable.
*/
void
yyerror(s)
const char *s;
{
(void) fprintf(stderr, "%s : line %d : %s\n", fname, nh_line_number, s);
if (++fatal_error > MAX_ERRORS) {
(void) fprintf(stderr, "Too many errors, good bye!\n");
exit(EXIT_FAILURE);
}
}
/*
* Just display a warning (that is : a non fatal error)
*/
void
yywarning(s)
const char *s;
{
(void) fprintf(stderr, "%s : line %d : WARNING : %s\n", fname,
nh_line_number, s);
}
int
yywrap()
{
SpinCursor(3); /* Don't know if this is a good place to put it ?
Is it called for our grammar ?
Often enough ?
Too often ? -- h+ */
return 1;
}
/*dgn_main.c*/