1 /*        $NetBSD: command4.c,v 1.4 2021/05/02 12:50:43 rillig Exp $  */
2 
3 /*
4  * Copyright (c) 1983, 1993
5  *        The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 #ifndef lint
34 #if 0
35 static char sccsid[] = "@(#)com4.c      8.2 (Berkeley) 4/28/95";
36 #else
37 __RCSID("$NetBSD: command4.c,v 1.4 2021/05/02 12:50:43 rillig Exp $");
38 #endif
39 #endif                                  /* not lint */
40 
41 #include "extern.h"
42 
43 int
take(unsigned int from[])44 take(unsigned int from[])
45 {
46           int     firstnumber, heavy, bulky, value;
47 
48           firstnumber = wordnumber;
49           if (wordnumber < wordcount && wordvalue[wordnumber + 1] == OFF) {
50                     wordnumber++;
51                     wordvalue[wordnumber] = TAKEOFF;
52                     wordtype[wordnumber] = VERB;
53                     return (cypher());
54           } else {
55                     wordnumber++;
56                     while (wordnumber <= wordcount && wordtype[wordnumber] ==
57                         OBJECT) {
58                               value = wordvalue[wordnumber];
59                               printf("%s:\n", objsht[value]);
60                               heavy = (carrying + objwt[value]) <= WEIGHT;
61                               bulky = (encumber + objcumber[value]) <= CUMBER;
62                               if ((testbit(from, value) || wiz || tempwiz) &&
63                                   heavy && bulky && !testbit(inven, value)) {
64                                         setbit(inven, value);
65                                         carrying += objwt[value];
66                                         encumber += objcumber[value];
67                                         ourtime++;
68                                         if (testbit(from, value))
69                                                   printf("Taken.\n");
70                                         else
71                                                   printf("Zap! Taken from thin air.\n");
72                                         clearbit(from, value);
73                                         if (value == MEDALION)
74                                                   win--;
75                               } else if (testbit(inven, value))
76                                         printf("You're already holding %s%s.\n",
77                                             A_OR_AN_OR_BLANK(value),
78                                             objsht[value]);
79                               else if (!testbit(from, value))
80                                         printf("I don't see any %s around here.\n",
81                                             objsht[value]);
82                               else if (!heavy)
83                                         printf("The %s %stoo heavy.\n", objsht[value],
84                                             IS_OR_ARE(value));
85                               else
86                                         printf("The %s %stoo cumbersome to hold.\n",
87                                             objsht[value], IS_OR_ARE(value));
88                               if (wordnumber < wordcount - 1 &&
89                                   wordvalue[++wordnumber] == AND)
90                                         wordnumber++;
91                               else
92                                         return (firstnumber);
93                     }
94           }
95           /* special cases with their own return()'s */
96 
97           if (wordnumber <= wordcount && wordtype[wordnumber] == NOUNS)
98                     switch (wordvalue[wordnumber]) {
99 
100                     case SWORD:
101                               if (testbit(from, SWORD)) {
102                                         wordtype[wordnumber--] = OBJECT;
103                                         return (take(from));
104                               }
105                               if (testbit(from, TWO_HANDED)) {
106                                         wordvalue[wordnumber] = TWO_HANDED;
107                                         wordtype[wordnumber--] = OBJECT;
108                                         return (take(from));
109                               }
110                               wordvalue[wordnumber] = BROAD;
111                               wordtype[wordnumber--] = OBJECT;
112                               return (take(from));
113 
114                     case BODY:
115                               if (testbit(from, MAID)) {
116                                         wordvalue[wordnumber] = MAID;
117                                         wordtype[wordnumber--] = OBJECT;
118                                         return (take(from));
119                               } else if (testbit(from, DEADWOOD)) {
120                                         wordvalue[wordnumber] = DEADWOOD;
121                                         wordtype[wordnumber--] = OBJECT;
122                                         return (take(from));
123                               } else if (testbit(from, DEADNATIVE)) {
124                                         wordvalue[wordnumber] = DEADNATIVE;
125                                         wordtype[wordnumber--] = OBJECT;
126                                         return (take(from));
127                               } else {
128                                         if (testbit(from, DEADGOD)) {
129                                                   wordvalue[wordnumber] = DEADGOD;
130                                                   wordtype[wordnumber--] = OBJECT;
131                                                   return (take(from));
132                                         } else {
133                                                   wordvalue[wordnumber] = DEADTIME;
134                                                   wordtype[wordnumber--] = OBJECT;
135                                                   return (take(from));
136                                         }
137                               }
138                               break;
139 
140                     case AMULET:
141                               if (testbit(location[position].objects, AMULET)) {
142                                         printf("The amulet is warm to the touch, and ");
143                                         puts("its beauty catches your breath.");
144                                         printf("A mist falls over your eyes, but ");
145                                         puts("then it is gone.  Sounds seem clearer");
146                                         printf("and sharper but far away as if in a ");
147                                         puts("dream.  The sound of purling water");
148                                         printf("reaches you from afar.  The mist ");
149                                         printf("falls again, and your heart leaps in ");
150                                         puts("horror.");
151                                         printf("The gold freezes your hands and ");
152                                         puts("fathomless darkness engulfs your soul.");
153                               }
154                               wordtype[wordnumber--] = OBJECT;
155                               return (take(from));
156 
157                     case MEDALION:
158                               if (testbit(location[position].objects, MEDALION)) {
159                                         printf("The medallion is warm, and it ");
160                                         printf("rekindles your spirit with the ");
161                                         puts("warmth of life.");
162                                         printf("Your amulet begins to glow as the ");
163                                         printf("medallion is brought near to it, ");
164                                         printf("and together\nthey radiate.\n");
165                               }
166                               wordtype[wordnumber--] = OBJECT;
167                               return (take(from));
168 
169                     case TALISMAN:
170                               if (testbit(location[position].objects, TALISMAN)) {
171                                         printf("The talisman is cold to the touch, ");
172                                         puts("and it sends a chill down your spine.");
173                               }
174                               wordtype[wordnumber--] = OBJECT;
175                               return (take(from));
176 
177                     case NORMGOD:
178                               if (testbit(location[position].objects, BATHGOD) &&
179                                   (testbit(wear, AMULET) || testbit(inven, AMULET))) {
180                                         printf("She offers a delicate hand, and you ");
181                                         puts("help her out of the sparkling springs.");
182                                         printf("Water droplets like liquid silver ");
183                                         printf("bedew her golden skin, but when ");
184                                         puts("they part");
185                                         printf("from her, they fall as teardrops.  ");
186                                         puts("She wraps a single cloth around her and");
187                                         printf("ties it at the waist.  Around her ");
188                                         puts("neck hangs a golden amulet.");
189                                         printf("She bids you to follow her, and ");
190                                         puts("walks away.");
191                                         pleasure++;
192                                         followgod = ourtime;
193                                         clearbit(location[position].objects, BATHGOD);
194                               } else
195                                         if (!testbit(location[position].objects,
196                                             BATHGOD)) {
197                                                   printf("You're in no position to ");
198                                                   puts("take her.");
199                                         } else
200                                                   puts("She moves away from you.");
201                               break;
202 
203                     default:
204                               puts("It doesn't seem to work.");
205                     }
206           else
207                     puts("You've got to be kidding.");
208           return (firstnumber);
209 }
210 
211 int
throw(const char * name)212 throw(const char *name)
213 {
214           unsigned int     n;
215           int     deposit = 0;
216           int     first, value;
217 
218           first = wordnumber;
219           if (drop(name) != -1) {
220                     switch (wordvalue[wordnumber]) {
221 
222                     case AHEAD:
223                               deposit = ahead;
224                               break;
225 
226                     case BACK:
227                               deposit = back;
228                               break;
229 
230                     case LEFT:
231                               deposit = left;
232                               break;
233 
234                     case RIGHT:
235                               deposit = right;
236                               break;
237 
238                     case UP:
239                               deposit = location[position].up *
240                                   (location[position].access || position == FINAL);
241                               break;
242 
243                     case DOWN:
244                               deposit = location[position].down;
245                               break;
246                     }
247                     wordnumber = first + 1;
248                     while (wordnumber <= wordcount) {
249                               value = wordvalue[wordnumber];
250                               if (deposit &&
251                                   testbit(location[position].objects, value)) {
252                                         clearbit(location[position].objects, value);
253                                         if (value != GRENADE)
254                                                   setbit(location[deposit].objects,
255                                                       value);
256                                         else {
257                                                   printf("A thundering explosion ");
258                                                   printf("nearby sends up a cloud of ");
259                                                   puts("smoke and shrapnel.");
260                                                   for (n = 0; n < NUMOFWORDS; n++)
261                                                             location[deposit].objects[n] =
262                                                                 0;
263                                                   setbit(location[deposit].objects, CHAR);
264                                         }
265                                         if (value == ROPE && position == FINAL)
266                                                   location[position].access = 1;
267                                         switch (deposit) {
268                                         case 189:
269                                         case 231:
270                                                   puts("The stone door is unhinged.");
271                                                   location[189].north = 231;
272                                                   location[231].south = 189;
273                                                   break;
274                                         case 30:
275                                                   puts("The wooden door is blown open.");
276                                                   location[30].west = 25;
277                                                   break;
278                                         case 31:
279                                                   puts("The door is not damaged.");
280                                         }
281                               } else
282                                         if (value == GRENADE &&
283                                             testbit(location[position].objects,
284                                             value)) {
285                                                   printf("You are blown into shreds ");
286                                                   puts("when your grenade explodes.");
287                                                   die();
288                                         }
289                               if (wordnumber < wordcount - 1 &&
290                                   wordvalue[++wordnumber] == AND)
291                                         wordnumber++;
292                               else
293                                         return (first);
294                     }
295                     return (first);
296           }
297           return (first);
298 }
299 
300 int
drop(const char * name)301 drop(const char *name)
302 {
303 
304           int     firstnumber, value;
305 
306           firstnumber = wordnumber;
307           wordnumber++;
308           while (wordnumber <= wordcount &&
309               (wordtype[wordnumber] == OBJECT || wordtype[wordnumber] == NOUNS)) {
310                     value = wordvalue[wordnumber];
311                     if (value == BODY) {          /* special case */
312                               wordtype[wordnumber] = OBJECT;
313                               if (testbit(inven, MAID) ||
314                                   testbit(location[position].objects, MAID))
315                                         value = MAID;
316                               else if (testbit(inven, DEADWOOD) ||
317                                   testbit(location[position].objects, DEADWOOD))
318                                         value = DEADWOOD;
319                               else if (testbit(inven, DEADGOD) ||
320                                   testbit(location[position].objects, DEADGOD))
321                                         value = DEADGOD;
322                               else if (testbit(inven, DEADTIME) ||
323                                   testbit(location[position].objects, DEADTIME))
324                                         value = DEADTIME;
325                               else if (testbit(inven, DEADNATIVE) ||
326                                   testbit(location[position].objects, DEADNATIVE))
327                                         value = DEADNATIVE;
328                     }
329                     if (wordtype[wordnumber] == NOUNS && value == DOOR) {
330                               if (*name == 'K')
331                                         puts("You hurt your foot.");
332                               else
333                                         puts("You're not holding a door.");
334                     } else if (objsht[value] == NULL) {
335                               if (*name == 'K')
336                                         puts("That's not for kicking!");
337                               else
338                                         puts("You don't have that.");
339                     } else {
340                               printf("%s:\n", objsht[value]);
341                               if (testbit(inven, value)) {
342                                         clearbit(inven, value);
343                                         carrying -= objwt[value];
344                                         encumber -= objcumber[value];
345                                         if (value == BOMB) {
346                                                   printf("The bomb explodes.  A ");
347                                                   printf("blinding white light and ");
348                                                   printf("immense concussion ");
349                                                   puts("obliterate us.");
350                                                   die();
351                                         }
352                                         if (value != AMULET && value != MEDALION &&
353                                             value != TALISMAN)
354                                                   setbit(location[position].objects,
355                                                       value);
356                                         else
357                                                   tempwiz = 0;
358                                         ourtime++;
359                                         if (*name == 'K')
360                                                   puts("Drop kicked.");
361                                         else
362                                                   printf("%s.\n", name);
363                               } else {
364                                         if (*name != 'K') {
365                                                   printf("You aren't holding the %s.\n",
366                                                       objsht[value]);
367                                                   if (testbit(location[position].objects,
368                                                       value)) {
369                                                             if (*name == 'T')
370                                                                       puts("Kicked instead.");
371                                                             else if (*name == 'G')
372                                                                       puts("Given anyway.");
373                                                   }
374                                         } else if (testbit(location[position].objects,
375                                             value))
376                                                   puts("Kicked.");
377                                         else if (testbit(wear, value))
378                                                   puts("Not while it's being worn.");
379                                         else
380                                                   puts("Not found.");
381                               }
382                     }
383                     if (wordnumber < wordcount - 1 &&
384                         wordvalue[++wordnumber] == AND)
385                               wordnumber++;
386                     else
387                               return (firstnumber);
388           }
389           puts("Do what?");
390           return (-1);
391 }
392 
393 int
takeoff(void)394 takeoff(void)
395 {
396           wordnumber = take(wear);
397           return (drop("Dropped"));
398 }
399 
400 int
puton(void)401 puton(void)
402 {
403           wordnumber = take(location[position].objects);
404           return (wearit());
405 }
406 
407 int
eat(void)408 eat(void)
409 {
410           int     firstnumber, value;
411 
412           firstnumber = wordnumber;
413           wordnumber++;
414           while (wordnumber <= wordcount) {
415                     value = wordvalue[wordnumber];
416                     if (wordtype[wordnumber] != OBJECT || objsht[value] == NULL)
417                               value = -2;
418                     switch (value) {
419 
420                     case -2:
421                               puts("You can't eat that!");
422                               return (firstnumber);
423 
424                     case -1:
425                               puts("Eat what?");
426                               return (firstnumber);
427 
428                     default:
429                               printf("You can't eat %s%s!\n",
430                                   A_OR_AN_OR_BLANK(value), objsht[value]);
431                               return (firstnumber);
432 
433                     case PAPAYAS:
434                     case PINEAPPLE:
435                     case KIWI:
436                     case COCONUTS:      /* eatable things */
437                     case MANGO:
438 
439                               printf("%s:\n", objsht[value]);
440                               if (testbit(inven, value) &&
441                                   ourtime > ate - CYCLE &&
442                                   testbit(inven, KNIFE)) {
443                                         clearbit(inven, value);
444                                         carrying -= objwt[value];
445                                         encumber -= objcumber[value];
446                                         ate = max(ourtime, ate) + CYCLE / 3;
447                                         snooze += CYCLE / 10;
448                                         ourtime++;
449                                         printf("Eaten.  You can explore a little ");
450                                         puts("longer now.");
451                               } else if (!testbit(inven, value)) {
452                                         printf("You aren't holding the %s.\n",
453                                             objsht[value]);
454                               } else if (!testbit(inven, KNIFE))
455                                         puts("You need a knife.");
456                               else
457                                         puts("You're stuffed.");
458                               if (wordnumber < wordcount - 1 &&
459                                   wordvalue[++wordnumber] == AND)
460                                         wordnumber++;
461                               else
462                                         return (firstnumber);
463                     }                   /* end switch */
464           }                             /* end while */
465           return (firstnumber);
466 }
467