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. */
10 if (TOTING(obj)) return(2011);
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;
24 if (game.fixed[obj] != 0)
26 if (obj == WATER || obj == OIL) {
27 if (!HERE(BOTTLE) || LIQ(0) != obj) {
28 if (TOTING(BOTTLE) && game.prop[BOTTLE] == 1)
30 if (game.prop[BOTTLE] != 1)SPK=105;
31 if (!TOTING(BOTTLE))SPK=104;
38 if (game.holdng >= INVLIMIT)
40 if (obj == BIRD && game.prop[BIRD] != 1 && -1-game.prop[BIRD] != 1) {
41 if (game.prop[BIRD] == 2) {
46 if (!TOTING(CAGE))SPK=27;
47 if (TOTING(ROD))SPK=26;
48 if (SPK/2 == 13) return(2011);
51 if ((obj==BIRD || obj==CAGE) && (game.prop[BIRD]==1 || -1-game.prop[BIRD]==1))
52 CARRY(BIRD+CAGE-obj,game.loc);
54 if (obj == BOTTLE && LIQ(0) != 0)
55 game.place[LIQ(0)] = -1;
56 if (!GSTONE(obj) || game.prop[obj] == 0)
63 /* Discard object. "Throw" also comes here for most objects. Special cases for
64 * bird (might attack snake or dragon) and cage (might contain bird) and vase.
65 * Drop coins at vending machine for extra batteries. */
67 int discard(long obj, bool just_do_it) {
69 if (TOTING(ROD2) && obj == ROD && !TOTING(ROD))obj=ROD2;
70 if (!TOTING(obj)) return(2011);
71 if (obj == BIRD && HERE(SNAKE)) {
73 if (game.closed) return(19000);
75 /* Set game.prop for use by travel options */
78 } else if ((GSTONE(obj) && AT(CAVITY) && game.prop[CAVITY] != 0)) {
82 if (HERE(RUG) && ((obj == EMRALD && game.prop[RUG] != 2) || (obj == RUBY &&
83 game.prop[RUG] == 2))) {
85 if (TOTING(RUG))SPK=220;
86 if (obj == RUBY)SPK=221;
91 if (K == 2)K=PLAC[SAPPH];
95 } else if (obj == COINS && HERE(VEND)) {
97 DROP(BATTER,game.loc);
100 } else if (obj == BIRD && AT(DRAGON) && game.prop[DRAGON] == 0) {
105 } else if (obj == BEAR && AT(TROLL)) {
108 MOVE(TROLL+NOBJECTS,0);
109 MOVE(TROLL2,PLAC[TROLL]);
110 MOVE(TROLL2+NOBJECTS,FIXD[TROLL]);
113 } else if (obj != VASE || game.loc == PLAC[PILLOW]) {
117 if (AT(PILLOW))game.prop[VASE]=0;
118 PSPEAK(VASE,game.prop[VASE]+1);
119 if (game.prop[VASE] != 0)game.fixed[VASE]= -1;
123 if (K == obj)obj=BOTTLE;
124 if (obj == BOTTLE && K != 0)game.place[K]=0;
125 if (obj == CAGE && game.prop[BIRD] == 1)DROP(BIRD,game.loc);
127 if (obj != BIRD) return(2012);
129 if (FOREST(game.loc))game.prop[BIRD]=2;
133 /* Attack. Assume target if unambiguous. "Throw" also links here. Attackable
134 * objects fall into two categories: enemies (snake, dwarf, etc.) and others
135 * (bird, clam, machine). Ambiguous if 2 enemies, or no enemies but 2 others. */
137 int attack(FILE *input, long obj, long verb) {
138 int i =ATDWRF(game.loc);
142 if (HERE(SNAKE))obj=obj*NOBJECTS+SNAKE;
143 if (AT(DRAGON) && game.prop[DRAGON] == 0)obj=obj*NOBJECTS+DRAGON;
144 if (AT(TROLL))obj=obj*NOBJECTS+TROLL;
145 if (AT(OGRE))obj=obj*NOBJECTS+OGRE;
146 if (HERE(BEAR) && game.prop[BEAR] == 0)obj=obj*NOBJECTS+BEAR;
147 if (obj > NOBJECTS) return(8000);
149 /* Can't attack bird or machine by throwing axe. */
150 if (HERE(BIRD) && verb != THROW)obj=BIRD;
151 if (HERE(VEND) && verb != THROW)obj=obj*NOBJECTS+VEND;
152 /* Clam and oyster both treated as clam for intransitive case;
154 if (HERE(CLAM) || HERE(OYSTER))obj=NOBJECTS*obj+CLAM;
155 if (obj > NOBJECTS) return(8000);
160 if (game.closed) return(2011);
166 PSPEAK(VEND,game.prop[VEND]+2);
167 game.prop[VEND]=3-game.prop[VEND];
172 if (obj == CLAM || obj == OYSTER)SPK=150;
173 if (obj == SNAKE)SPK=46;
174 if (obj == DWARF)SPK=49;
175 if (obj == DWARF && game.closed) return(19000);
176 if (obj == DRAGON)SPK=167;
177 if (obj == TROLL)SPK=157;
178 if (obj == OGRE)SPK=203;
179 if (obj == OGRE && i > 0) {
184 for (i=1; i < PIRATE; i++) {
185 if (game.dloc[i] == game.loc) {
194 if (obj == BEAR)SPK=165+(game.prop[BEAR]+1)/2;
195 if (obj != DRAGON || game.prop[DRAGON] != 0) return(2011);
196 /* Fun stuff for dragon. If he insists on attacking it, win!
197 * Set game.prop to dead, move dragon to central loc (still
198 * fixed), move rug there (not fixed), and move him there,
199 * too. Then do a null motion to get new description. */
201 GETIN(input,WD1,WD1X,WD2,WD2X);
202 if (WD1 != MAKEWD(25) && WD1 != MAKEWD(250519)) return(2607);
206 K=(PLAC[DRAGON]+FIXD[DRAGON])/2;
207 MOVE(DRAGON+NOBJECTS,-1);
208 MOVE(RUG+NOBJECTS,0);
212 for (obj=1; obj<=NOBJECTS; obj++) {
213 if (game.place[obj] == PLAC[DRAGON] || game.place[obj] == FIXD[DRAGON])MOVE(obj,K);
221 int throw_support(long spk)
229 int throw(FILE *cmdin, long obj, long verb)
230 /* Throw. Same as discard unless axe. Then same as attack except
231 * ignore bird, and if dwarf is present then one might be killed.
232 * (Only way to do so!) Axe also special for dragon, bear, and
233 * troll. Treasures special for troll. */
235 if (TOTING(ROD2) && obj == ROD && !TOTING(ROD))obj=ROD2;
238 if (obj >= 50 && obj <= MAXTRS && AT(TROLL)) {
240 /* Snarf a treasure for the troll. */
243 MOVE(TROLL+NOBJECTS,0);
244 DROP(TROLL2,PLAC[TROLL]);
245 DROP(TROLL2+NOBJECTS,FIXD[TROLL]);
249 if (obj == FOOD && HERE(BEAR)) {
250 /* But throwing food is another story. */
255 return(discard(obj, false));
258 if (AT(DRAGON) && game.prop[DRAGON] == 0) {
260 return throw_support(SPK);
264 return throw_support(SPK);
268 return throw_support(SPK);
270 if (HERE(BEAR) && game.prop[BEAR] == 0) {
271 /* This'll teach him to throw the axe at the bear! */
279 return(attack(cmdin, 0, verb));
282 if (randrange(NDWARVES+1) < game.dflag) {
284 return throw_support(SPK);
289 game.dkill=game.dkill+1;
290 if (game.dkill == 1)SPK=149;
292 return throw_support(SPK);
296 /* Feed. If bird, no seed. Snake, dragon, troll: quip. If dwarf, make him
297 * mad. Bear, special. */
304 if (!(obj != SNAKE && obj != DRAGON && obj != TROLL)) {
306 if (obj == DRAGON && game.prop[DRAGON] != 0)SPK=110;
307 if (obj == TROLL)SPK=182;
308 if (obj != SNAKE || game.closed || !HERE(BIRD))
320 game.dflag=game.dflag+2;
325 if (game.prop[BEAR] == 0)SPK=102;
326 if (game.prop[BEAR] == 3)SPK=110;
348 /* Fill. Bottle or urn must be empty, and liquid available. (Vase
354 if (LIQLOC(game.loc) == 0)SPK=144;
355 if (LIQLOC(game.loc) == 0 || !TOTING(VASE))
359 game.fixed[VASE]= -1;
360 return(discard(obj, true));
365 if (game.prop[URN] != 0) return(2011);
368 if (k == 0 || !HERE(BOTTLE)) return(2011);
371 if (k == OIL)game.prop[URN]=1;
372 SPK=211+game.prop[URN];
376 if (obj != 0 && obj != BOTTLE)
378 if (obj == 0 && !HERE(BOTTLE))
381 if (LIQLOC(game.loc) == 0)
383 if (HERE(URN) && game.prop[URN] != 0)
389 game.prop[BOTTLE]=MOD(COND[game.loc],4)/2*2;