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