Move more globals into the game state block.
[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(void) {
9         if(TOTING(OBJ)) return(2011);
10         SPK=25;
11         if(OBJ == PLANT && PROP[PLANT] <= 0)SPK=115;
12         if(OBJ == BEAR && PROP[BEAR] == 1)SPK=169;
13         if(OBJ == CHAIN && 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 && 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(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) && PROP[BOTTLE] == 1) return(fill());
28         if(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 || PROP[BIRD] == 1 || -1-PROP[BIRD] == 1) goto L9014;
34         if(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         PROP[BIRD]=1;
39 L9014:  if((OBJ == BIRD || OBJ == CAGE) && (PROP[BIRD] == 1 || -1-PROP[BIRD] ==
40                 1))CARRY(BIRD+CAGE-OBJ,LOC);
41         CARRY(OBJ,LOC);
42         K=LIQ(0);
43         if(OBJ == BOTTLE && K != 0)PLACE[K]= -1;
44         if(!GSTONE(OBJ) || PROP[OBJ] == 0) return(2009);
45         PROP[OBJ]=0;
46         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(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 PROP FOR USE BY TRAVEL OPTIONS */
67         PROP[SNAKE]=1;
68 L9021:  K=LIQ(0);
69         if(K == OBJ)OBJ=BOTTLE;
70         if(OBJ == BOTTLE && K != 0)PLACE[K]=0;
71         if(OBJ == CAGE && PROP[BIRD] == 1)DROP(BIRD,LOC);
72         DROP(OBJ,LOC);
73         if(OBJ != BIRD) return(2012);
74         PROP[BIRD]=0;
75         if(FOREST(LOC))PROP[BIRD]=2;
76          return(2012);
77
78 L9023:  if(!(GSTONE(OBJ) && AT(CAVITY) && PROP[CAVITY] != 0)) goto L9024;
79         RSPEAK(218);
80         PROP[OBJ]=1;
81         PROP[CAVITY]=0;
82         if(!HERE(RUG) || !((OBJ == EMRALD && PROP[RUG] != 2) || (OBJ == RUBY &&
83                 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-PROP[RUG];
90         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,LOC);
98         PSPEAK(BATTER,0);
99          return(2012);
100
101 L9025:  if(OBJ != BIRD || !AT(DRAGON) || PROP[DRAGON] != 0) goto L9026;
102         RSPEAK(154);
103         DSTROY(BIRD);
104         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         PROP[TROLL]=2;
115          goto L9021;
116
117 L9027:  if(OBJ == VASE && LOC != PLAC[PILLOW]) goto L9028;
118         RSPEAK(54);
119          goto L9021;
120
121 L9028:  PROP[VASE]=2;
122         if(AT(PILLOW))PROP[VASE]=0;
123         PSPEAK(VASE,PROP[VASE]+1);
124         if(PROP[VASE] != 0)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) {
133         I=ATDWRF(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) && 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) && 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                 PROP[BIRD]=0;
154                 SPK=45;
155         }
156 L9125:  if(OBJ != VEND) goto L9126;
157         PSPEAK(VEND,PROP[VEND]+2);
158         PROP[VEND]=3-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+(PROP[BEAR]+1)/2;
171         if(OBJ != DRAGON || PROP[DRAGON] != 0) return(2011);
172 /*  Fun stuff for dragon.  If he insists on attacking it, win!  Set 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         VERB=0;
177         OBJ=0;
178         GETIN(input,WD1,WD1X,WD2,WD2X);
179         if(WD1 != MAKEWD(25) && WD1 != MAKEWD(250519)) return(2607);
180         PSPEAK(DRAGON,3);
181         PROP[DRAGON]=1;
182         PROP[RUG]=0;
183         K=(PLAC[DRAGON]+FIXD[DRAGON])/2;
184         MOVE(DRAGON+NOBJECTS,-1);
185         MOVE(RUG+NOBJECTS,0);
186         MOVE(DRAGON,K);
187         MOVE(RUG,K);
188         DROP(BLOOD,K);
189         for (OBJ=1; OBJ<=NOBJECTS; OBJ++) {
190         if(PLACE[OBJ] == PLAC[DRAGON] || PLACE[OBJ] == FIXD[DRAGON])MOVE(OBJ,K);
191         /*etc*/ ;
192         } /* end loop */
193         LOC=K;
194         K=NUL;
195          return(8);
196
197 L9128:  RSPEAK(SPK);
198         RSPEAK(6);
199         DSTROY(OGRE);
200         K=0;
201         for (I=1; I < PIRATE; I++) {
202                 if(game.dloc[I] == LOC) {
203                         K=K+1;
204                         game.dloc[I]=61;
205                         game.dseen[I]=false;
206                 }
207         }
208         SPK=SPK+1+1/K;
209         return(2011);
210 }
211
212 /*  Throw.  Same as discard unless axe.  Then same as attack except ignore bird,
213  *  and if dwarf is present then one might be killed.  (Only way to do so!)
214  *  Axe also special for dragon, bear, and troll.  Treasures special for troll. */
215
216 int throw(FILE *cmdin) {
217         if(TOTING(ROD2) && OBJ == ROD && !TOTING(ROD))OBJ=ROD2;
218         if(!TOTING(OBJ)) return(2011);
219         if(OBJ >= 50 && OBJ <= MAXTRS && AT(TROLL)) goto L9178;
220         if(OBJ == FOOD && HERE(BEAR)) goto L9177;
221         if(OBJ != AXE) return(discard(false));
222         I=ATDWRF(LOC);
223         if(I > 0) goto L9172;
224         SPK=152;
225         if(AT(DRAGON) && PROP[DRAGON] == 0) goto L9175;
226         SPK=158;
227         if(AT(TROLL)) goto L9175;
228         SPK=203;
229         if(AT(OGRE)) goto L9175;
230         if(HERE(BEAR) && PROP[BEAR] == 0) goto L9176;
231         OBJ=0;
232         return(attack(cmdin));
233
234 L9172:  SPK=48;
235         if(randrange(NDWARVES+1) < game.dflag) goto L9175;
236         game.dseen[I]=false;
237         game.dloc[I]=0;
238         SPK=47;
239         game.dkill=game.dkill+1;
240         if(game.dkill == 1)SPK=149;
241 L9175:  RSPEAK(SPK);
242         DROP(AXE,LOC);
243         K=NUL;
244          return(8);
245
246 /*  This'll teach him to throw the axe at the bear! */
247 L9176:  SPK=164;
248         DROP(AXE,LOC);
249         FIXED[AXE]= -1;
250         PROP[AXE]=1;
251         JUGGLE(BEAR);
252          return(2011);
253
254 /*  But throwing food is another story. */
255 L9177:  OBJ=BEAR;
256         return(feed());
257
258 L9178:  SPK=159;
259 /*  Snarf a treasure for the troll. */
260         DROP(OBJ,0);
261         MOVE(TROLL,0);
262         MOVE(TROLL+NOBJECTS,0);
263         DROP(TROLL2,PLAC[TROLL]);
264         DROP(TROLL2+NOBJECTS,FIXD[TROLL]);
265         JUGGLE(CHASM);
266          return(2011);
267 }
268
269 /*  Feed.  If bird, no seed.  Snake, dragon, troll: quip.  If dwarf, make him
270  *  mad.  Bear, special. */
271
272 int feed() {
273         if(OBJ != BIRD) goto L9212;
274         SPK=100;
275          return(2011);
276
277 L9212:  if(OBJ != SNAKE && OBJ != DRAGON && OBJ != TROLL) goto L9213;
278         SPK=102;
279         if(OBJ == DRAGON && PROP[DRAGON] != 0)SPK=110;
280         if(OBJ == TROLL)SPK=182;
281         if(OBJ != SNAKE || game.closed || !HERE(BIRD)) return(2011);
282         SPK=101;
283         DSTROY(BIRD);
284         PROP[BIRD]=0;
285          return(2011);
286
287 L9213:  if(OBJ != DWARF) goto L9214;
288         if(!HERE(FOOD)) return(2011);
289         SPK=103;
290         game.dflag=game.dflag+2;
291          return(2011);
292
293 L9214:  if(OBJ != BEAR) goto L9215;
294         if(PROP[BEAR] == 0)SPK=102;
295         if(PROP[BEAR] == 3)SPK=110;
296         if(!HERE(FOOD)) return(2011);
297         DSTROY(FOOD);
298         PROP[BEAR]=1;
299         FIXED[AXE]=0;
300         PROP[AXE]=0;
301         SPK=168;
302          return(2011);
303
304 L9215:  if(OBJ != OGRE) goto L9216;
305         if(HERE(FOOD))SPK=202;
306          return(2011);
307
308 L9216:  SPK=14;
309          return(2011);
310 }
311
312 /*  Fill.  Bottle or urn must be empty, and liquid available.  (Vase is nasty.) */
313
314 int fill() {
315         if(OBJ == VASE) goto L9222;
316         if(OBJ == URN) goto L9224;
317         if(OBJ != 0 && OBJ != BOTTLE) return(2011);
318         if(OBJ == 0 && !HERE(BOTTLE)) return(8000);
319         SPK=107;
320         if(LIQLOC(LOC) == 0)SPK=106;
321         if(HERE(URN) && PROP[URN] != 0)SPK=214;
322         if(LIQ(0) != 0)SPK=105;
323         if(SPK != 107) return(2011);
324         PROP[BOTTLE]=MOD(COND[LOC],4)/2*2;
325         K=LIQ(0);
326         if(TOTING(BOTTLE))PLACE[K]= -1;
327         if(K == OIL)SPK=108;
328          return(2011);
329
330 L9222:  SPK=29;
331         if(LIQLOC(LOC) == 0)SPK=144;
332         if(LIQLOC(LOC) == 0 || !TOTING(VASE)) return(2011);
333         RSPEAK(145);
334         PROP[VASE]=2;
335         FIXED[VASE]= -1;
336          return(discard(true));
337
338 L9224:  SPK=213;
339         if(PROP[URN] != 0) return(2011);
340         SPK=144;
341         K=LIQ(0);
342         if(K == 0 || !HERE(BOTTLE)) return(2011);
343         PLACE[K]=0;
344         PROP[BOTTLE]=1;
345         if(K == OIL)PROP[URN]=1;
346         SPK=211+PROP[URN];
347          return(2011);
348 }