-
Notifications
You must be signed in to change notification settings - Fork 1
/
source.txt
172 lines (149 loc) · 9.45 KB
/
source.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
This is a documentation specifically explaining some of the more bizarre and
stupid features of the Crawl source code, and outlining some of my plans for
its future. This documentation is current for version 1.1 (14/10/97). Please
read Licence.txt for legal details.
I should start by describing the extent of my programming experience. I learnt
rudimentary Commodore 64 BASIC in year seven at primary school, which really
was of very little use, apart from teaching me how to use variables and how to
overuse goto (I love goto). Once or twice in high school I made really half-
hearted attempts to teach myself C++ from Borland's Turbo C++ manual, but I
didn't really get anywhere. I finally one day decided to write a game in C and
learn the language in the process. To this end, I resumed my reading of that
manual, and started to code. I had at this time played PCHack, nethack 3.1.3,
Larn, and Moria 4.83(?); I had never heard of Angband, Omega or ADOM, and
never seen Rogue. And I had certainly never seen their source code, or for
that matter any source code outside the examples in the manual. I eventually
got djgpp and rhide, which have helped enormously.
Why am I telling you this? To help explain some of what follows.
You see, I gave up on Borland's manual (which is very good, I'm just lazy)
when it started talking about pointers, because I just didn't (and still don't
really) understand what they're supposed to be so useful for. After pointers
came structs, enums, pragmas, classes, macros, and a whole lot of other stuff
which still means nothing to me. It also took me several months to realise
that putting every single function into one huge module was not going to work
if I wanted my game to have more that 64K of code, and even then I did weird
things like putting heaps of code into .h files and including them
directly... you can still see the legacy of this in the code. I even had the
dungeon generator in a separate file which was spawned, created the level,
saved it to disk, then passed control back to the main program which then read
the level from disk again. new_game still works on a similar principle.
Yes, there are many oddities in this code which may shock you, may even amuse
you, but almost certainly will make you feel proud of whatever programming
ability you have yourself. I won't even mention the disk accessing functions.
Okay, here's a list of some things which may be helpful in understanding the
code. If you can think of anything which should be added to this list, please
tell me.
Note: This list contains some Spoilers! Beware.
-int main() is in CRAWL99.CPP (the 99 is a version number, which started at 1
about 18 months ago). Other functions are scattered around the various files
and modules with very little logic, although a general guide is given below:
CRAWL99.CPP: input, item use, monster movement, spellcasting, miscellaneous
MONSPLS5.H: attack routines and monster placement, also some spells
NEWVIEW.H: the viewing window and line-of-sight functions;
NEWACCES.H: disk access (approach with caution)
GLOBVARS.H: the catalogue of global variables. Depressingly long.
The files which are actually in different modules are:
CRAWLFNC.CPP: heaps of miscellany, including new_game and monster names
BUILDER2.CPP: dungeon building and some monster stats, also spellbooks
MONSSTAT.CPP: rest of the monster stats
FN2.CPP: item names and more miscellany, also spell names and levels
FN3.CPP: some little things which I forget
FN4.CPP: stuff I couldn't put anywhere else
INVENT.CPP: the inventory function, also the 'X' mapping thing
NEWNAME.CPP: random name generator (for scrolls)
I may have forgotten some.
-To send a message to the player, you do this:
strcpy(info [info_lines], "[message]");
incrl(); in crawl99.cpp, or
incr(); in monspls5.cpp
As yet, you cannot send messages to the message windows from any of the other
modules, although there is a way of doing so from within the main module (eg
in NEWVIEW.H). To print a number, you must use itoa(number, stringvar, 10);
-The way that spellbooks work may be confusing. It's basically like this: Each
type of spellbook (book of minor magic, ice, etc) has a template consisting of
up to six spells. Each individual book has, stored in its item_plus variable,
an 8 bit number which, when converted to binary through itoa(n, str, 2); gives
which spells are present and which are not. Spell staves have the template,
but always have all appropriate spells.
-The general monster variable gmon_use works like this:
gmon_use = 0: monster can neither use items nor open doors;
gmon_use = 1: can open doors;
gmon_use = 3: can open doors and pick up weapons and missiles.
Monsters can be generated holding a weapon, some missiles, and a suit of
armour. They will never pick up armour, unique weapons, or anything other than
weapons and missiles. Special weapons, like flaming or draining, are
implemented so that monsters can use them too (even against each other). If
monsters are carrying a missile device (eg a bow) they won't use it to
attack, but will use it to shoot available missiles. Monsters cannot yet be
generated with special armours; this is still only partially implemented.
-The special tunnelling worm code (tunnelling worms are multi-segmented worms
which are like Hack's long worms, only with more mobility and the ability to
chew through rock) is very delicate, and I've left it alone ever since it
seemed to be working okay.
-As I mentioned earlier, the game and dungeon generator used to be in separate
files, so there are some strange inconsistencies between them. Most notable is
the way that BUILDER2 uses +70 for monsters, while the others use +50.
-the MLAVA and MWATER macros are for lava and water monsters, so I can change
their values easily.
-There was originally some logic to the monster spellcasting targetting code,
but that was mostly lost when I adapted that section to target other monsters
as well as you. I must look at it sometime.
-If you enchant a monster eg with a slow monster spell, the enchantment will
wear off after a while; this is contained in mons_ench. mons_ench_1 tells
whether a monster has any enchantments at all. Invisibility can only take up
mons_ench [2], and it does so sometimes even without enchantments (this is
how creatures disappear when submerged).
-The scroll labels are randomly generated from seeds in their item variables
item_plus and item_dam.
-Some of the variable names are rather esoteric. Here's a list of a few:
mons_class - the class of a monster
mons_sec - a secondary characteristic, eg: the class of a zombie, the
spell memory template used by a spellcaster, how many heads a hydra has, the
colour of a butterfly, etc.
mons_hp, mons_hp_max, mons_AC, mons_HD - all fairly self explanatory
mons_ev - monster evasion score
mons_ench - temporary enchantments
mons_ench_1 - is it enchanted at all?
mons_inv - what the monster's carrying - most slots currently unused. 0 is
weapon, 1 is missile, 2 is armour.
mons_beh - monster behaviour. Used mainly in monster() in CRAWL99.CPP
mons_hit - for mons_beh == 6, what monster the monster is attacking
gmon_use - see above
mcolour - obvious. Defined (along with gmon_use) in MONSSTAT.CPP
item_class - general class of item (eg weapon, armour, etc)
item_type - specific type of item - long sword, club, bow etc
item_plus - plusses on weapons, charges in wands, etc. Is unsigned char, so
for weapons, armour, missiles, and plussed rings, is +50, or +150 if cursed.
item_dam - was originally going to be how damaged the item is, but now used
for special weapons and armour, also for wands, potions etc ("steel wand").
item_x/y - I think these are only used in BUILDER2.CPP and NEWACCES.H.
* replace item with inv in most cases, and you have the inventory variable.
it_no, no_it, and no_mons used to mean something, but I don't think they do
anymore.
inv_no is the inventory item counter
i, j, k - these global loop variables are throwbacks to my BASIC past, and
have caused me no end of trouble.
icky, higgy, asdfg, nothing etc - minor local variables
There are vast numbers of other variables, but these should be enough to get
you started.
-The presence of a monster in a square is indicated by that square's grid [][]
value being incremented by 50. The presence of a cloud increments it by 100,
so the grid value is in the range 0-200, and grid [x] [y] % 50 gives you the
underlying terrain. The exception to this is, IIRC, monsters who spend part of
their time under water or lava; when they're submerged, they don't thus
increment the grid. Or maybe they do; it's a while since I wrote that bit. You
can find out where a certain monster is from its mons_x & y value, but given a
grid reference you must do a search loop to find the monster which is there.
Hopefully the above list is enough to give you a really basic understanding of
the abomination which is the Crawl source code. If you have any questions,
please feel free to ask me; I love getting email about Crawl!
Some of my plans for the near future:
Get rid of those bugs which I know are still lurking somewhere in there
(assistance in this task would be greatly appreciated);
Completely rewrite that silly system where the presence of a monster adds 50
to the grid square it's on, and a cloud adds 100 - this has got to go!;
Replace those mons_thing and item_thing variables with structs - if anyone
knows what a struct is and how to use it, please tell me;
Add shops like in Angband (only located between levels);
Keep on adding hordes of little features, so that one day Crawl can be a
bloated monster just like NetHack! (this has always been my dream)