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