Narrow the scope of VERB.
[open-adventure.git] / actions2.c
1 #include "advent.h"
2 #include "funcs.h"
3
4 /*  Carry an object.  Special cases for bird and cage (if bird in cage, can't
5  *  take one without the other).  Liquids also special, since they depend on
6  *  status of bottle.  Also various side effects, etc. */
7
8 int carry(long obj) {
9         if(TOTING(obj)) return(2011);
10         SPK=25;
11         if(obj == PLANT && game.prop[PLANT] <= 0)SPK=115;
12         if(obj == BEAR && game.prop[BEAR] == 1)SPK=169;
13         if(obj == CHAIN && game.prop[BEAR] != 0)SPK=170;
14         if(obj == URN)SPK=215;
15         if(obj == CAVITY)SPK=217;
16         if(obj == BLOOD)SPK=239;
17         if(obj == RUG && game.prop[RUG] == 2)SPK=222;
18         if(obj == SIGN)SPK=196;
19         if(obj != MESSAG) goto L9011;
20         SPK=190;
21         DSTROY(MESSAG);
22 L9011:  if(game.fixed[obj] != 0) return(2011);
23         if(obj != WATER && obj != OIL) goto L9017;
24         K=obj;
25         obj=BOTTLE;
26         if(HERE(BOTTLE) && LIQ(0) == K) goto L9017;
27         if(TOTING(BOTTLE) && game.prop[BOTTLE] == 1) return(fill(obj));
28         if(game.prop[BOTTLE] != 1)SPK=105;
29         if(!TOTING(BOTTLE))SPK=104;
30          return(2011);
31 L9017:  SPK=92;
32         if(game.holdng >= 7) return(2011);
33         if(obj != BIRD || game.prop[BIRD] == 1 || -1-game.prop[BIRD] == 1) goto L9014;
34         if(game.prop[BIRD] == 2) goto L9015;
35         if(!TOTING(CAGE))SPK=27;
36         if(TOTING(ROD))SPK=26;
37         if(SPK/2 == 13) return(2011);
38         game.prop[BIRD]=1;
39 L9014:  if((obj == BIRD || obj == CAGE) && (game.prop[BIRD] == 1 || -1-game.prop[BIRD] ==
40                 1))CARRY(BIRD+CAGE-obj,game.loc);
41         CARRY(obj,game.loc);
42         K=LIQ(0);
43         if(obj == BOTTLE && K != 0)game.place[K]= -1;
44         if(!GSTONE(obj) || game.prop[obj] == 0) return(2009);
45         game.prop[obj]=0;
46         game.prop[CAVITY]=1;
47          return(2009);
48
49 L9015:  SPK=238;
50         DSTROY(BIRD);
51          return(2011);
52 }
53
54 /*  Discard object.  "Throw" also comes here for most objects.  Special cases for
55  *  bird (might attack snake or dragon) and cage (might contain bird) and vase.
56  *  Drop coins at vending machine for extra batteries. */
57
58 int discard(long obj, bool just_do_it) {
59         if(just_do_it) goto L9021;
60         if(TOTING(ROD2) && obj == ROD && !TOTING(ROD))obj=ROD2;
61         if(!TOTING(obj)) return(2011);
62         if(obj != BIRD || !HERE(SNAKE)) goto L9023;
63         RSPEAK(30);
64         if(game.closed) return(19000);
65         DSTROY(SNAKE);
66 /*  SET game.prop FOR USE BY TRAVEL OPTIONS */
67         game.prop[SNAKE]=1;
68 L9021:  K=LIQ(0);
69         if(K == obj)obj=BOTTLE;
70         if(obj == BOTTLE && K != 0)game.place[K]=0;
71         if(obj == CAGE && game.prop[BIRD] == 1)DROP(BIRD,game.loc);
72         DROP(obj,game.loc);
73         if(obj != BIRD) return(2012);
74         game.prop[BIRD]=0;
75         if(FOREST(game.loc))game.prop[BIRD]=2;
76          return(2012);
77
78 L9023:  if(!(GSTONE(obj) && AT(CAVITY) && game.prop[CAVITY] != 0)) goto L9024;
79         RSPEAK(218);
80         game.prop[obj]=1;
81         game.prop[CAVITY]=0;
82         if(!HERE(RUG) || !((obj == EMRALD && game.prop[RUG] != 2) || (obj == RUBY &&
83                 game.prop[RUG] == 2))) goto L9021;
84         SPK=219;
85         if(TOTING(RUG))SPK=220;
86         if(obj == RUBY)SPK=221;
87         RSPEAK(SPK);
88         if(SPK == 220) goto L9021;
89         K=2-game.prop[RUG];
90         game.prop[RUG]=K;
91         if(K == 2)K=PLAC[SAPPH];
92         MOVE(RUG+NOBJECTS,K);
93          goto L9021;
94
95 L9024:  if(obj != COINS || !HERE(VEND)) goto L9025;
96         DSTROY(COINS);
97         DROP(BATTER,game.loc);
98         PSPEAK(BATTER,0);
99          return(2012);
100
101 L9025:  if(obj != BIRD || !AT(DRAGON) || game.prop[DRAGON] != 0) goto L9026;
102         RSPEAK(154);
103         DSTROY(BIRD);
104         game.prop[BIRD]=0;
105          return(2012);
106
107 L9026:  if(obj != BEAR || !AT(TROLL)) goto L9027;
108         RSPEAK(163);
109         MOVE(TROLL,0);
110         MOVE(TROLL+NOBJECTS,0);
111         MOVE(TROLL2,PLAC[TROLL]);
112         MOVE(TROLL2+NOBJECTS,FIXD[TROLL]);
113         JUGGLE(CHASM);
114         game.prop[TROLL]=2;
115          goto L9021;
116
117 L9027:  if(obj == VASE && game.loc != PLAC[PILLOW]) goto L9028;
118         RSPEAK(54);
119          goto L9021;
120
121 L9028:  game.prop[VASE]=2;
122         if(AT(PILLOW))game.prop[VASE]=0;
123         PSPEAK(VASE,game.prop[VASE]+1);
124         if(game.prop[VASE] != 0)game.fixed[VASE]= -1;
125          goto L9021;
126 }
127
128 /*  Attack.  Assume target if unambiguous.  "Throw" also links here.  Attackable
129  *  objects fall into two categories: enemies (snake, dwarf, etc.)  and others
130  *  (bird, clam, machine).  Ambiguous if 2 enemies, or no enemies but 2 others. */
131
132 int attack(FILE *input, long obj, long verb) {
133         I=ATDWRF(game.loc);
134         if(obj != 0) goto L9124;
135         if(I > 0)obj=DWARF;
136         if(HERE(SNAKE))obj=obj*NOBJECTS+SNAKE;
137         if(AT(DRAGON) && game.prop[DRAGON] == 0)obj=obj*NOBJECTS+DRAGON;
138         if(AT(TROLL))obj=obj*NOBJECTS+TROLL;
139         if(AT(OGRE))obj=obj*NOBJECTS+OGRE;
140         if(HERE(BEAR) && game.prop[BEAR] == 0)obj=obj*NOBJECTS+BEAR;
141         if(obj > NOBJECTS) return(8000);
142         if(obj != 0) goto L9124;
143 /*  CAN'T ATTACK BIRD OR MACHINE BY THROWING AXE. */
144         if(HERE(BIRD) && verb != THROW)obj=BIRD;
145         if(HERE(VEND) && verb != THROW)obj=obj*NOBJECTS+VEND;
146 /*  CLAM AND OYSTER BOTH TREATED AS CLAM FOR INTRANSITIVE CASE; NO HARM DONE. */
147         if(HERE(CLAM) || HERE(OYSTER))obj=NOBJECTS*obj+CLAM;
148         if(obj > NOBJECTS) return(8000);
149 L9124:  if(obj == BIRD) {
150                 SPK=137;
151                 if(game.closed) return(2011);
152                 DSTROY(BIRD);
153                 game.prop[BIRD]=0;
154                 SPK=45;
155         }
156 L9125:  if(obj != VEND) goto L9126;
157         PSPEAK(VEND,game.prop[VEND]+2);
158         game.prop[VEND]=3-game.prop[VEND];
159          return(2012);
160
161 L9126:  if(obj == 0)SPK=44;
162         if(obj == CLAM || obj == OYSTER)SPK=150;
163         if(obj == SNAKE)SPK=46;
164         if(obj == DWARF)SPK=49;
165         if(obj == DWARF && game.closed) return(19000);
166         if(obj == DRAGON)SPK=167;
167         if(obj == TROLL)SPK=157;
168         if(obj == OGRE)SPK=203;
169         if(obj == OGRE && I > 0) goto L9128;
170         if(obj == BEAR)SPK=165+(game.prop[BEAR]+1)/2;
171         if(obj != DRAGON || game.prop[DRAGON] != 0) return(2011);
172 /*  Fun stuff for dragon.  If he insists on attacking it, win!  Set game.prop to dead,
173  *  move dragon to central loc (still fixed), move rug there (not fixed), and
174  *  move him there, too.  Then do a null motion to get new description. */
175         RSPEAK(49);
176         GETIN(input,WD1,WD1X,WD2,WD2X);
177         if(WD1 != MAKEWD(25) && WD1 != MAKEWD(250519)) return(2607);
178         PSPEAK(DRAGON,3);
179         game.prop[DRAGON]=1;
180         game.prop[RUG]=0;
181         K=(PLAC[DRAGON]+FIXD[DRAGON])/2;
182         MOVE(DRAGON+NOBJECTS,-1);
183         MOVE(RUG+NOBJECTS,0);
184         MOVE(DRAGON,K);
185         MOVE(RUG,K);
186         DROP(BLOOD,K);
187         for (obj=1; obj<=NOBJECTS; obj++) {
188         if(game.place[obj] == PLAC[DRAGON] || game.place[obj] == FIXD[DRAGON])MOVE(obj,K);
189         /*etc*/ ;
190         } /* end loop */
191         game.loc=K;
192         K=NUL;
193          return(8);
194
195 L9128:  RSPEAK(SPK);
196         RSPEAK(6);
197         DSTROY(OGRE);
198         K=0;
199         for (I=1; I < PIRATE; I++) {
200                 if(game.dloc[I] == game.loc) {
201                         K=K+1;
202                         game.dloc[I]=61;
203                         game.dseen[I]=false;
204                 }
205         }
206         SPK=SPK+1+1/K;
207         return(2011);
208 }
209
210 /*  Throw.  Same as discard unless axe.  Then same as attack except ignore bird,
211  *  and if dwarf is present then one might be killed.  (Only way to do so!)
212  *  Axe also special for dragon, bear, and troll.  Treasures special for troll. */
213
214 int throw(FILE *cmdin, long obj, long verb) {
215         if(TOTING(ROD2) && obj == ROD && !TOTING(ROD))obj=ROD2;
216         if(!TOTING(obj)) return(2011);
217         if(obj >= 50 && obj <= MAXTRS && AT(TROLL)) goto L9178;
218         if(obj == FOOD && HERE(BEAR)) goto L9177;
219         if(obj != AXE) return(discard(obj, false));
220         I=ATDWRF(game.loc);
221         if(I > 0) goto L9172;
222         SPK=152;
223         if(AT(DRAGON) && game.prop[DRAGON] == 0) goto L9175;
224         SPK=158;
225         if(AT(TROLL)) goto L9175;
226         SPK=203;
227         if(AT(OGRE)) goto L9175;
228         if(HERE(BEAR) && game.prop[BEAR] == 0) goto L9176;
229         obj=0;
230         return(attack(cmdin, obj, verb));
231
232 L9172:  SPK=48;
233         if(randrange(NDWARVES+1) < game.dflag) goto L9175;
234         game.dseen[I]=false;
235         game.dloc[I]=0;
236         SPK=47;
237         game.dkill=game.dkill+1;
238         if(game.dkill == 1)SPK=149;
239 L9175:  RSPEAK(SPK);
240         DROP(AXE,game.loc);
241         K=NUL;
242          return(8);
243
244 /*  This'll teach him to throw the axe at the bear! */
245 L9176:  SPK=164;
246         DROP(AXE,game.loc);
247         game.fixed[AXE]= -1;
248         game.prop[AXE]=1;
249         JUGGLE(BEAR);
250          return(2011);
251
252 /*  But throwing food is another story. */
253 L9177:  obj=BEAR;
254         return(feed(obj));
255
256 L9178:  SPK=159;
257 /*  Snarf a treasure for the troll. */
258         DROP(obj,0);
259         MOVE(TROLL,0);
260         MOVE(TROLL+NOBJECTS,0);
261         DROP(TROLL2,PLAC[TROLL]);
262         DROP(TROLL2+NOBJECTS,FIXD[TROLL]);
263         JUGGLE(CHASM);
264          return(2011);
265 }
266
267 /*  Feed.  If bird, no seed.  Snake, dragon, troll: quip.  If dwarf, make him
268  *  mad.  Bear, special. */
269
270 int feed(long obj) {
271         if(obj != BIRD) goto L9212;
272         SPK=100;
273          return(2011);
274
275 L9212:  if(obj != SNAKE && obj != DRAGON && obj != TROLL) goto L9213;
276         SPK=102;
277         if(obj == DRAGON && game.prop[DRAGON] != 0)SPK=110;
278         if(obj == TROLL)SPK=182;
279         if(obj != SNAKE || game.closed || !HERE(BIRD)) return(2011);
280         SPK=101;
281         DSTROY(BIRD);
282         game.prop[BIRD]=0;
283          return(2011);
284
285 L9213:  if(obj != DWARF) goto L9214;
286         if(!HERE(FOOD)) return(2011);
287         SPK=103;
288         game.dflag=game.dflag+2;
289          return(2011);
290
291 L9214:  if(obj != BEAR) goto L9215;
292         if(game.prop[BEAR] == 0)SPK=102;
293         if(game.prop[BEAR] == 3)SPK=110;
294         if(!HERE(FOOD)) return(2011);
295         DSTROY(FOOD);
296         game.prop[BEAR]=1;
297         game.fixed[AXE]=0;
298         game.prop[AXE]=0;
299         SPK=168;
300          return(2011);
301
302 L9215:  if(obj != OGRE) goto L9216;
303         if(HERE(FOOD))SPK=202;
304          return(2011);
305
306 L9216:  SPK=14;
307          return(2011);
308 }
309
310 /*  Fill.  Bottle or urn must be empty, and liquid available.  (Vase is nasty.) */
311
312 int fill(long obj) {
313         if(obj == VASE) goto L9222;
314         if(obj == URN) goto L9224;
315         if(obj != 0 && obj != BOTTLE) return(2011);
316         if(obj == 0 && !HERE(BOTTLE)) return(8000);
317         SPK=107;
318         if(LIQLOC(game.loc) == 0)SPK=106;
319         if(HERE(URN) && game.prop[URN] != 0)SPK=214;
320         if(LIQ(0) != 0)SPK=105;
321         if(SPK != 107) return(2011);
322         game.prop[BOTTLE]=MOD(COND[game.loc],4)/2*2;
323         K=LIQ(0);
324         if(TOTING(BOTTLE))game.place[K]= -1;
325         if(K == OIL)SPK=108;
326          return(2011);
327
328 L9222:  SPK=29;
329         if(LIQLOC(game.loc) == 0)SPK=144;
330         if(LIQLOC(game.loc) == 0 || !TOTING(VASE)) return(2011);
331         RSPEAK(145);
332         game.prop[VASE]=2;
333         game.fixed[VASE]= -1;
334         return(discard(obj, true));
335
336 L9224:  SPK=213;
337         if(game.prop[URN] != 0) return(2011);
338         SPK=144;
339         K=LIQ(0);
340         if(K == 0 || !HERE(BOTTLE)) return(2011);
341         game.place[K]=0;
342         game.prop[BOTTLE]=1;
343         if(K == OIL)game.prop[URN]=1;
344         SPK=211+game.prop[URN];
345          return(2011);
346 }