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 (obj == INTRANSITIVE) {
11 /* Carry, no object given yet. OK if only one object present. */
12 if(game.atloc[game.loc] == 0 ||
13 game.link[game.atloc[game.loc]] != 0 ||
16 obj=game.atloc[game.loc];
19 if (TOTING(obj)) return(2011);
21 if (obj == PLANT && game.prop[PLANT] <= 0)SPK=115;
22 if (obj == BEAR && game.prop[BEAR] == 1)SPK=169;
23 if (obj == CHAIN && game.prop[BEAR] != 0)SPK=170;
24 if (obj == URN)SPK=215;
25 if (obj == CAVITY)SPK=217;
26 if (obj == BLOOD)SPK=239;
27 if (obj == RUG && game.prop[RUG] == 2)SPK=222;
28 if (obj == SIGN)SPK=196;
33 if (game.fixed[obj] != 0)
35 if (obj == WATER || obj == OIL) {
36 if (!HERE(BOTTLE) || LIQ(0) != obj) {
37 if (TOTING(BOTTLE) && game.prop[BOTTLE] == 1)
39 if (game.prop[BOTTLE] != 1)SPK=105;
40 if (!TOTING(BOTTLE))SPK=104;
47 if (game.holdng >= INVLIMIT)
49 if (obj == BIRD && game.prop[BIRD] != 1 && -1-game.prop[BIRD] != 1) {
50 if (game.prop[BIRD] == 2) {
55 if (!TOTING(CAGE))SPK=27;
56 if (TOTING(ROD))SPK=26;
57 if (SPK/2 == 13) return(2011);
60 if ((obj==BIRD || obj==CAGE) && (game.prop[BIRD]==1 || -1-game.prop[BIRD]==1))
61 CARRY(BIRD+CAGE-obj,game.loc);
63 if (obj == BOTTLE && LIQ(0) != 0)
64 game.place[LIQ(0)] = -1;
65 if (!GSTONE(obj) || game.prop[obj] == 0)
72 /* Discard object. "Throw" also comes here for most objects. Special cases for
73 * bird (might attack snake or dragon) and cage (might contain bird) and vase.
74 * Drop coins at vending machine for extra batteries. */
76 int discard(long obj, bool just_do_it) {
78 if (TOTING(ROD2) && obj == ROD && !TOTING(ROD))obj=ROD2;
79 if (!TOTING(obj)) return(2011);
80 if (obj == BIRD && HERE(SNAKE)) {
82 if (game.closed) return(19000);
84 /* Set game.prop for use by travel options */
87 } else if ((GSTONE(obj) && AT(CAVITY) && game.prop[CAVITY] != 0)) {
91 if (HERE(RUG) && ((obj == EMRALD && game.prop[RUG] != 2) || (obj == RUBY &&
92 game.prop[RUG] == 2))) {
94 if (TOTING(RUG))SPK=220;
95 if (obj == RUBY)SPK=221;
100 if (K == 2)K=PLAC[SAPPH];
101 MOVE(RUG+NOBJECTS,K);
104 } else if (obj == COINS && HERE(VEND)) {
106 DROP(BATTER,game.loc);
109 } else if (obj == BIRD && AT(DRAGON) && game.prop[DRAGON] == 0) {
114 } else if (obj == BEAR && AT(TROLL)) {
117 MOVE(TROLL+NOBJECTS,0);
118 MOVE(TROLL2,PLAC[TROLL]);
119 MOVE(TROLL2+NOBJECTS,FIXD[TROLL]);
122 } else if (obj != VASE || game.loc == PLAC[PILLOW]) {
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;
132 if (K == obj)obj=BOTTLE;
133 if (obj == BOTTLE && K != 0)game.place[K]=0;
134 if (obj == CAGE && game.prop[BIRD] == 1)DROP(BIRD,game.loc);
136 if (obj != BIRD) return(2012);
138 if (FOREST(game.loc))game.prop[BIRD]=2;
142 /* Attack. Assume target if unambiguous. "Throw" also links here. Attackable
143 * objects fall into two categories: enemies (snake, dwarf, etc.) and others
144 * (bird, clam, machine). Ambiguous if 2 enemies, or no enemies but 2 others. */
146 int attack(FILE *input, long verb, long obj) {
147 int i =ATDWRF(game.loc);
151 if (HERE(SNAKE))obj=obj*NOBJECTS+SNAKE;
152 if (AT(DRAGON) && game.prop[DRAGON] == 0)obj=obj*NOBJECTS+DRAGON;
153 if (AT(TROLL))obj=obj*NOBJECTS+TROLL;
154 if (AT(OGRE))obj=obj*NOBJECTS+OGRE;
155 if (HERE(BEAR) && game.prop[BEAR] == 0)obj=obj*NOBJECTS+BEAR;
156 if (obj > NOBJECTS) return(8000);
158 /* Can't attack bird or machine by throwing axe. */
159 if (HERE(BIRD) && verb != THROW)obj=BIRD;
160 if (HERE(VEND) && verb != THROW)obj=obj*NOBJECTS+VEND;
161 /* Clam and oyster both treated as clam for intransitive case;
163 if (HERE(CLAM) || HERE(OYSTER))obj=NOBJECTS*obj+CLAM;
164 if (obj > NOBJECTS) return(8000);
169 if (game.closed) return(2011);
175 PSPEAK(VEND,game.prop[VEND]+2);
176 game.prop[VEND]=3-game.prop[VEND];
181 if (obj == CLAM || obj == OYSTER)SPK=150;
182 if (obj == SNAKE)SPK=46;
183 if (obj == DWARF)SPK=49;
184 if (obj == DWARF && game.closed) return(19000);
185 if (obj == DRAGON)SPK=167;
186 if (obj == TROLL)SPK=157;
187 if (obj == OGRE)SPK=203;
188 if (obj == OGRE && i > 0) {
193 for (i=1; i < PIRATE; i++) {
194 if (game.dloc[i] == game.loc) {
203 if (obj == BEAR)SPK=165+(game.prop[BEAR]+1)/2;
204 if (obj != DRAGON || game.prop[DRAGON] != 0) return(2011);
205 /* Fun stuff for dragon. If he insists on attacking it, win!
206 * Set game.prop to dead, move dragon to central loc (still
207 * fixed), move rug there (not fixed), and move him there,
208 * too. Then do a null motion to get new description. */
210 GETIN(input,WD1,WD1X,WD2,WD2X);
211 if (WD1 != MAKEWD(25) && WD1 != MAKEWD(250519)) return(2607);
215 K=(PLAC[DRAGON]+FIXD[DRAGON])/2;
216 MOVE(DRAGON+NOBJECTS,-1);
217 MOVE(RUG+NOBJECTS,0);
221 for (obj=1; obj<=NOBJECTS; obj++) {
222 if (game.place[obj] == PLAC[DRAGON] || game.place[obj] == FIXD[DRAGON])MOVE(obj,K);
230 int throw_support(long spk)
238 int throw(FILE *cmdin, long verb, long obj)
239 /* Throw. Same as discard unless axe. Then same as attack except
240 * ignore bird, and if dwarf is present then one might be killed.
241 * (Only way to do so!) Axe also special for dragon, bear, and
242 * troll. Treasures special for troll. */
244 if (TOTING(ROD2) && obj == ROD && !TOTING(ROD))obj=ROD2;
247 if (obj >= 50 && obj <= MAXTRS && AT(TROLL)) {
249 /* Snarf a treasure for the troll. */
252 MOVE(TROLL+NOBJECTS,0);
253 DROP(TROLL2,PLAC[TROLL]);
254 DROP(TROLL2+NOBJECTS,FIXD[TROLL]);
258 if (obj == FOOD && HERE(BEAR)) {
259 /* But throwing food is another story. */
264 return(discard(obj, false));
267 if (AT(DRAGON) && game.prop[DRAGON] == 0) {
269 return throw_support(SPK);
273 return throw_support(SPK);
277 return throw_support(SPK);
279 if (HERE(BEAR) && game.prop[BEAR] == 0) {
280 /* This'll teach him to throw the axe at the bear! */
288 return(attack(cmdin, verb, 0));
291 if (randrange(NDWARVES+1) < game.dflag) {
293 return throw_support(SPK);
298 game.dkill=game.dkill+1;
299 if (game.dkill == 1)SPK=149;
301 return throw_support(SPK);
305 /* Feed. If bird, no seed. Snake, dragon, troll: quip. If dwarf, make him
306 * mad. Bear, special. */
313 if (!(obj != SNAKE && obj != DRAGON && obj != TROLL)) {
315 if (obj == DRAGON && game.prop[DRAGON] != 0)SPK=110;
316 if (obj == TROLL)SPK=182;
317 if (obj != SNAKE || game.closed || !HERE(BIRD))
329 game.dflag=game.dflag+2;
334 if (game.prop[BEAR] == 0)SPK=102;
335 if (game.prop[BEAR] == 3)SPK=110;
357 /* Fill. Bottle or urn must be empty, and liquid available. (Vase
363 if (LIQLOC(game.loc) == 0)SPK=144;
364 if (LIQLOC(game.loc) == 0 || !TOTING(VASE))
368 game.fixed[VASE]= -1;
369 return(discard(obj, true));
374 if (game.prop[URN] != 0) return(2011);
377 if (k == 0 || !HERE(BOTTLE)) return(2011);
380 if (k == OIL)game.prop[URN]=1;
381 SPK=211+game.prop[URN];
385 if (obj != 0 && obj != BOTTLE)
387 if (obj == 0 && !HERE(BOTTLE))
390 if (LIQLOC(game.loc) == 0)
392 if (HERE(URN) && game.prop[URN] != 0)
398 game.prop[BOTTLE]=MOD(COND[game.loc],4)/2*2;