-
Notifications
You must be signed in to change notification settings - Fork 0
/
actions4.c
253 lines (237 loc) · 7.83 KB
/
actions4.c
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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
/*
* Actions for the dungeon-running code.
*
* Zilog's C compiler is a bit . . . special, so this file is broken up into
* smaller units.
*
* Copyright (c) 1977, 2005 by Will Crowther and Don Woods
* Copyright (c) 2017 by Eric S. Raymond
* SPDX-License-Identifier: BSD-2-clause
*/
#include "actions.h"
phase_codes_t pour(verb_t verb, obj_t obj)
/* Pour. If no object, or object is bottle, assume contents of bottle.
* special tests for pouring water or oil on plant or rusty door. */
{
if (obj == BOTTLE ||
obj == INTRANSITIVE)
obj = liquid();
if (obj == NO_OBJECT)
return GO_UNKNOWN;
if (!TOTING(obj)) {
speak(get_action(verb)->message);
return GO_CLEAROBJ;
}
if (obj != OIL && obj != WATER) {
rspeak(CANT_POUR);
return GO_CLEAROBJ;
}
if (here(URN) && game.prop[URN] == URN_EMPTY)
return fill(verb, URN);
game.prop[BOTTLE] = EMPTY_BOTTLE;
game.place[obj] = LOC_NOWHERE;
if (!(at(PLANT) ||
at(DOOR))) {
rspeak(GROUND_WET);
return GO_CLEAROBJ;
}
if (!at(DOOR)) {
if (obj == WATER) {
/* cycle through the three plant states */
state_change(PLANT, MOD(game.prop[PLANT] + 1, 3));
game.prop[PLANT2] = game.prop[PLANT];
return GO_MOVE;
} else {
rspeak(SHAKING_LEAVES);
return GO_CLEAROBJ;
}
} else {
state_change(DOOR, (obj == OIL) ?
DOOR_UNRUSTED :
DOOR_RUSTED);
return GO_CLEAROBJ;
}
}
phase_codes_t quit(void)
/* Quit. Intransitive only. Verify intent and exit if that's what he wants. */
{
if (yes(get_arbitrary_message_index(REALLY_QUIT), get_arbitrary_message_index(OK_MAN), get_arbitrary_message_index(OK_MAN)))
terminate(quitgame);
return GO_CLEAROBJ;
}
phase_codes_t action_read(command_t* command)
/* Read. Print stuff based on objtxt. Oyster (?) is special case. */
{
int i;
if (command->obj == INTRANSITIVE) {
command->obj = NO_OBJECT;
for (i = 1; i <= NOBJECTS; i++) {
if (here(i) && get_object_text(i, 0) != NULL && game.prop[i] >= 0)
command->obj = command->obj * NOBJECTS + i;
}
if (command->obj > NOBJECTS ||
command->obj == NO_OBJECT ||
dark(game.loc))
return GO_UNKNOWN;
}
if (dark(game.loc)) {
sspeak(NO_SEE, command->word[0].raw);
} else if (command->obj == OYSTER && !game.clshnt && game.closed) {
game.clshnt = yes(get_arbitrary_message_index(CLUE_QUERY), get_arbitrary_message_index(WAYOUT_CLUE), get_arbitrary_message_index(OK_MAN));
} else if (get_object_text(command->obj, 0) == NULL ||
game.prop[command->obj] == STATE_NOTFOUND) {
speak(get_action(command->verb)->message);
} else
pspeak(command->obj, study, true, game.prop[command->obj]);
return GO_CLEAROBJ;
}
phase_codes_t reservoir(void)
/* Z'ZZZ (word gets recomputed at startup; different each game). */
{
if (!at(RESER) && game.loc != LOC_RESBOTTOM) {
rspeak(NOTHING_HAPPENS);
return GO_CLEAROBJ;
} else {
state_change(RESER,
game.prop[RESER] == WATERS_PARTED ? WATERS_UNPARTED : WATERS_PARTED);
if (at(RESER))
return GO_CLEAROBJ;
else {
game.oldlc2 = game.loc;
game.newloc = LOC_NOWHERE;
rspeak(NOT_BRIGHT);
return GO_TERMINATE;
}
}
}
phase_codes_t rub(verb_t verb, obj_t obj)
/* Rub. Yields various snide remarks except for lit urn. */
{
if (obj == URN && game.prop[URN] == URN_LIT) {
DESTROY(URN);
drop(AMBER, game.loc);
game.prop[AMBER] = AMBER_IN_ROCK;
--game.tally;
drop(CAVITY, game.loc);
rspeak(URN_GENIES);
} else if (obj != LAMP) {
rspeak(PECULIAR_NOTHING);
} else {
speak(get_action(verb)->message);
}
return GO_CLEAROBJ;
}
phase_codes_t say(command_t* command)
/* Say. Echo WD2. Magic words override. */
{
if (command->word[1].type == MOTION &&
(command->word[1].id == XYZZY ||
command->word[1].id == PLUGH ||
command->word[1].id == PLOVER)) {
return GO_WORD2;
}
if (command->word[1].type == ACTION && command->word[1].id == PART)
return reservoir();
if (command->word[1].type == ACTION &&
(command->word[1].id == FEE ||
command->word[1].id == FIE ||
command->word[1].id == FOE ||
command->word[1].id == FOO ||
command->word[1].id == FUM ||
command->word[1].id == PART)) {
return bigwords(command->word[1].id);
}
sspeak(OKEY_DOKEY, command->word[1].raw);
return GO_CLEAROBJ;
}
phase_codes_t throw_support(vocab_t spk)
{
rspeak(spk);
drop(AXE, game.loc);
return GO_MOVE;
}
phase_codes_t throw (command_t* command)
/* Throw. Same as discard unless axe. Then same as attack except
* ignore bird, and if dwarf is present then one might be killed.
* (Only way to do so!) Axe also special for dragon, bear, and
* troll. Treasures special for troll. */
{
int i;
if (!TOTING(command->obj)) {
speak(get_action(command->verb)->message);
return GO_CLEAROBJ;
}
if (get_object(command->obj)->is_treasure && at(TROLL)) {
/* Snarf a treasure for the troll. */
drop(command->obj, LOC_NOWHERE);
move(TROLL, LOC_NOWHERE);
move(TROLL + NOBJECTS, IS_FREE);
drop(TROLL2, get_object(TROLL)->plac);
drop(TROLL2 + NOBJECTS, get_object(TROLL)->fixd);
juggle(CHASM);
rspeak(TROLL_SATISFIED);
return GO_CLEAROBJ;
}
if (command->obj == FOOD && here(BEAR)) {
/* But throwing food is another story. */
command->obj = BEAR;
return (feed(command->verb, command->obj));
}
if (command->obj != AXE)
return (discard(command->verb, command->obj));
else {
if (atdwrf(game.loc) <= 0) {
if (at(DRAGON) && game.prop[DRAGON] == DRAGON_BARS)
return throw_support(DRAGON_SCALES);
if (at(TROLL))
return throw_support(TROLL_RETURNS);
if (at(OGRE))
return throw_support(OGRE_DODGE);
if (here(BEAR) && game.prop[BEAR] == UNTAMED_BEAR) {
/* This'll teach him to throw the axe at the bear! */
drop(AXE, game.loc);
game.fixed[AXE] = IS_FIXED;
juggle(BEAR);
state_change(AXE, AXE_LOST);
return GO_CLEAROBJ;
}
command->obj = INTRANSITIVE;
return (attack(command));
}
if (randrange(NDWARVES + 1) < game.dflag) {
return throw_support(DWARF_DODGES);
} else {
i = atdwrf(game.loc);
game.dseen[i] = false;
game.dloc[i] = LOC_NOWHERE;
return throw_support((++game.dkill == 1) ?
DWARF_SMOKE :
KILLED_DWARF);
}
}
}
phase_codes_t wake(verb_t verb, obj_t obj)
/* Wake. Only use is to disturb the dwarves. */
{
if (obj != DWARF ||
!game.closed) {
speak(get_action(verb)->message);
return GO_CLEAROBJ;
} else {
rspeak(PROD_DWARF);
return GO_DWARFWAKE;
}
}
#ifdef CALCULATOR
void print(char*);
#endif
phase_codes_t seed(verb_t verb, const char *arg)
/* Set seed */
{
int32_t seed;
seed = strtol(arg, NULL, 10);
speak(get_action(verb)->message, seed);
set_seed(seed);
--game.turns;
return GO_TOP;
}