source: trunk/minix/commands/advent/utility.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 13.5 KB
Line 
1/*
2 Utility Routines
3 the next logical funtions describe attributes of objects.
4 (ajar, hinged, opaque, printd, treasr, vessel, wearng)
5*/
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <ctype.h>
10#include <string.h>
11#include "advent.h"
12#include "advdec.h"
13
14/*
15 ajar .TRUE. if item is container and is open or unhinged
16*/
17boolean ajar(item)
18int item;
19{
20 return ((bitset(g.obj_state[item], OPENBT))
21 || (vessel(item) && !hinged(item)));
22}
23
24/*
25 at .TRUE. To tell if player is on either side of a two sided object.
26*/
27boolean at(item)
28int item;
29{
30 if (item < 1 || item > MAXOBJ)
31 return (FALSE);
32 else
33 return (g.place[item] == g.loc || g.fixed[item] == g.loc);
34}
35
36/*
37 athand .TRUE. if item readily reachable
38 it can be lying here, in hand or in open container.
39*/
40boolean athand(item)
41int item;
42{
43 int contnr;
44 boolean aaa;
45
46 contnr = -g.place[item];
47 aaa = enclosed(item) && ajar(contnr);
48
49 return ((g.place[item] == g.loc) || holding(item)
50 || (aaa && ((g.place[contnr] == g.loc)
51 || (toting(item) && holding(contnr)))));
52}
53
54/*
55 bitoff turns off (sets to 0) a bit in obj_state word
56*/
57void bitoff(obj, bit)
58int obj, bit;
59{
60 long val;
61
62 val = 1L << bit;
63 g.obj_state[obj] &= ~val;
64}
65
66/*
67 biton turns on (sets to 1) a bit in obj_state word
68*/
69void biton(obj, bit)
70int obj, bit;
71{
72 long val;
73
74 val = 1L << bit;
75 g.obj_state[obj] |= val;
76}
77
78/*
79 bitset .TRUE. if object_state has bit N set
80*/
81boolean bitset(state, bit)
82long state;
83int bit;
84{
85 return (((state >> bit) & 1) == 1);
86}
87
88/*
89 blind .TRUE. if you can't see at this loc, (darkness of glare)
90*/
91boolean blind()
92{
93 return (dark() || (g.loc == 200
94 && athand(LAMP) && (g.prop[LAMP] == 1)));
95}
96
97/*
98 burden .. returns weight of items being carried
99
100 if obj=0, burden calculates the total weight of the adventurer's burden
101 including everything in all containers (except the boat) that he is
102 carring.
103
104 if object is a container, calculate the weight of everything inside
105 the container (including the container itself). Since donkey FORTRAN
106 isn't recursive, we will only calculate weight of contained containers
107 one level down. The only serious contained container would be the sack
108 The only thing we'll miss will be filled VS empty bottle or cage.
109
110 If object isn't a container, return its weight.
111*/
112int burden(obj)
113int obj;
114{
115 int i, sum, temp;
116
117 sum = 0;
118 if (obj == 0) {
119 for (i = 1; i < MAXOBJ; i++) {
120 if (toting(i) && (g.place[i] != -BOAT))
121 sum += g.weight[i];
122 }
123 } else {
124 if (obj != BOAT) {
125 sum = g.weight[obj];
126 temp = g.holder[obj];
127 while (temp != 0) {
128 sum += g.weight[temp];
129 temp = g.hlink[temp];
130 }
131 }
132 }
133 return (sum);
134}
135
136/*
137 Routine to carry an object
138 start toting an object, removing it from the list of things
139 at its former location. If object > MAXOBJ ( moving "FIXED"
140 or second loc), then don't change place.
141*/
142void carry(obj, where)
143int obj, where;
144{
145 int temp;
146
147 if (obj < MAXOBJ) {
148 if (g.place[obj] == -1)
149 return;
150 g.place[obj] = -1;
151 }
152 if (g.atloc[where] == obj)
153 g.atloc[where] = g.link[obj];
154 else {
155 temp = g.atloc[where];
156 while (g.link[temp] != obj) {
157 temp = g.link[temp];
158 if (temp == 0)
159 bug(35);
160 }
161 g.link[temp] = g.link[obj];
162 }
163 return;
164}
165
166/*
167 confuz generates some variant of "Don't understand that" message.
168*/
169int confuz()
170{
171 int msg;
172
173 msg = 60;
174 if (pct(50))
175 msg = 61;
176 if (pct(33))
177 msg = 13;
178 if (pct(25))
179 msg = 347;
180 if (pct(20))
181 msg = 195;
182 return (msg);
183}
184
185/*
186 dark .TRUE. if there is no light here
187*/
188boolean dark()
189{
190 return (!(g.loc_attrib[g.loc] & LIGHT) &&
191 (!g.prop[LAMP] || !athand(LAMP)));
192}
193
194/*
195 Routine to check for presence
196 of dwarves..
197*/
198int dcheck()
199{
200 int i;
201
202 for (i = 1; i < (DWARFMAX); ++i)
203 if (g.dloc[i] == g.loc)
204 return (i);
205 return (0);
206}
207
208/*
209 dead .TRUE. if object is now dead
210*/
211boolean dead(obj)
212int obj;
213{
214 return (bitset(g.obj_state[obj], 10));
215}
216
217/*
218 drop Place an object at a given loc, prefixing it onto the atloc list.
219*/
220void drop(obj, where)
221int obj, where;
222{
223 if (obj > MAXOBJ)
224 g.fixed[obj - MAXOBJ] = where;
225 else
226 g.place[obj] = where;
227 if (where > 0) {
228 g.link[obj] = g.atloc[where];
229 g.atloc[where] = obj;
230 }
231 return;
232}
233
234/*
235 destroy Permanently eliminate "object" by moving it to
236 a non-existent location.
237*/
238void destroy(obj)
239int obj;
240{
241 move(obj, 0);
242 return;
243}
244
245/*
246 edible .TRUE. if obj can be eaten.
247*/
248boolean edible(obj)
249int obj;
250{
251 return (bitset(g.obj_state[obj], 7));
252}
253
254/*
255 enclosed .TRUE. If object is inside a container.
256*/
257boolean enclosed(item)
258int item;
259{
260 if (item < 1 || item > MAXOBJ)
261 return (FALSE);
262 else
263 return (g.place[item] < -1);
264}
265
266/*
267 extract remove "object" from a container.
268 origionally name "remove" but rename to avoid conflict with stdio.h
269*/
270void extract(obj)
271int obj;
272{
273 int contnr, temp;
274
275 contnr = -g.place[obj];
276 g.place[obj] = -1;
277 if (g.holder[contnr] == obj)
278 g.holder[contnr] = g.hlink[obj];
279 else {
280 temp = g.holder[contnr];
281 while (g.hlink[temp] != obj) {
282 temp = g.hlink[temp];
283 if (temp == 0)
284 bug(35);
285 }
286 g.hlink[temp] = g.hlink[obj];
287 }
288 return;
289}
290
291/*
292 forced To tell if a location will causes a forced move.
293 A forced location is one from which he is immediately bounced
294 to another. Normal use is for death (forced to location zero)
295 and for description of journey from on place to another.
296*/
297int forced(at_loc)
298int at_loc;
299{
300 return ((g.loc_attrib[at_loc] & 10) == 2);
301}
302
303/*
304 here .TRUE. If an item is at location or is being carried.
305*/
306boolean here(item)
307int item;
308{
309 return (g.place[item] == g.loc || toting(item));
310}
311
312/*
313 hinged .TRUE. If object can be opened or shut.
314*/
315boolean hinged(object)
316int object;
317{
318 return (bitset(g.obj_state[object], 1));
319}
320
321/*
322 holding .TRUE. If the object is being carried in hand.
323*/
324boolean holding(item)
325int item;
326{
327 if (item < 1 || item > MAXOBJ)
328 return (FALSE);
329 else
330 return (g.place[item] == -1);
331}
332
333/*
334 insert
335*/
336void insert(obj, contnr)
337int obj, contnr;
338{
339 int temp;
340
341 if (contnr == obj)
342 bug(32);
343 carry(obj, g.loc);
344
345 temp = g.holder[contnr];
346 g.holder[contnr] = obj;
347 g.hlink[obj] = temp;
348 g.place[obj] = -contnr;
349}
350
351/*
352 inside = .TRUE. If location is well within cave
353*/
354boolean inside(loc)
355int loc;
356{
357 return (!outside(loc) && !portal(loc));
358}
359
360/*
361 Juggle an object by picking it up and putting it down again,
362 The purpose being to get the object to the front of the chain
363 at its loc.
364*/
365void juggle(obj)
366int obj;
367{
368 int i, j;
369
370 i = g.place[obj];
371 j = g.fixed[obj];
372 move(obj, i);
373 move(obj + MAXOBJ, j);
374 return;
375}
376
377/*
378 Determine liquid in the vessel
379*/
380int liq(item)
381int item;
382{
383 int liquid;
384
385 if ((item == BOTTLE) || (item == CASK))
386 liquid = liq2(((int) g.prop[item] >> 1) & 7);
387 else
388 liquid = 0;
389
390 return (liquid);
391}
392
393/*
394 Determine type of liquid in vessel
395*/
396int liq2(liquid)
397int liquid;
398{
399 switch (liquid) {
400 case 4:
401 return (WATER);
402 case 5:
403 return (OIL);
404 case 6:
405 return (WINE);
406 default:
407 return (0); /* empty */
408 }
409}
410
411/*
412 Determine liquid at a location
413*/
414int liqloc(loc)
415int loc;
416{
417 return (liq2((int) ((g.loc_attrib[loc] >> 1) & 7)));
418}
419
420/*
421 living .TRUE. If object is living, bear for example
422*/
423boolean living(obj)
424int obj;
425{
426 return (bitset(g.obj_state[obj], 9));
427}
428
429/*
430 locked .TRUE. if lockable object is locked
431*/
432boolean locked(item)
433int item;
434{
435 return (bitset(g.obj_state[item], 4));
436}
437
438/*
439 locks .TRUE. if you can lock this object
440*/
441boolean locks(item)
442int item;
443{
444 return (bitset(g.obj_state[item], 3));
445}
446
447/*
448 LOOKIN list contents if obj is a container and is open or transparent.
449*/
450void lookin(contnr)
451int contnr;
452{
453 int temp;
454 boolean first_time;
455
456 if (vessel(contnr) && (ajar(contnr) || !opaque(contnr))) {
457 temp = g.holder[contnr];
458 first_time = TRUE;
459 while (temp != 0) {
460 if (first_time)
461 rspeak(360);
462 printf(" ");
463 pspeak(temp, -1);
464 temp = g.hlink[temp];
465 first_time = FALSE;
466 }
467 }
468 return;
469}
470
471/*
472 Routine to move an object
473*/
474void move(obj, where)
475int obj, where;
476{
477 int from;
478
479 if (obj > MAXOBJ)
480 from = g.fixed[obj - MAXOBJ];
481 else {
482 if (enclosed(obj))
483 extract(obj);
484 from = g.place[obj];
485 }
486 if ((from > 0) && (from < MAXOBJ * 2))
487 carry(obj, from);
488 drop(obj, where);
489 return;
490}
491
492/*
493 noway, generate's some variant of "can't do that" message.
494*/
495int noway()
496{
497 int msg;
498
499 msg = 14;
500 if (pct(50))
501 msg = 110;
502 if (pct(33))
503 msg = 147;
504 if (pct(25))
505 msg = 250;
506 if (pct(20))
507 msg = 262;
508 if (pct(17))
509 msg = 25;
510 if (pct(14))
511 msg = 345;
512 if (pct(12))
513 msg = 346;
514 return (msg);
515}
516
517/*
518 opaque .TRUE. If obj is non-transparent container
519*/
520boolean opaque(obj)
521int obj;
522{
523 return (bitset(g.obj_state[obj], 6));
524}
525
526/*
527 outsid .TRUE. If location is outside the cave
528*/
529boolean outside(loc)
530int loc;
531{
532 return (bitset(g.loc_attrib[loc], 6));
533}
534
535/*
536 Routine true x% of the time. (x an integer from 0 to 100)
537*/
538int pct(x)
539int x;
540{
541 return (ranz(100) < x);
542}
543
544/*
545 plural .TRUE. if object is multiple objects
546*/
547boolean plural(obj)
548int obj;
549{
550 return (bitset(g.obj_state[obj], 13));
551}
552
553/*
554 portal .TRUE. If location is a cave entrance
555*/
556boolean portal(loc)
557int loc;
558{
559 return (bitset(g.loc_attrib[loc], 5));
560}
561
562/*
563 printed .TRUE. If object can be read.
564*/
565boolean printed(obj)
566int obj;
567{
568 return (bitset(g.obj_state[obj], 8));
569}
570
571/*
572 put is the same as move, except it returns a
573 value used to set the negated prop values
574 for the repository objects.
575*/
576int put(obj, where, pval)
577int obj, where, pval;
578{
579 move(obj, where);
580 return ((-1) - pval);
581}
582
583/*
584 RANZ
585*/
586int ranz(range)
587int range;
588{
589 return (rand() % range);
590}
591
592/*
593 small .TRUE. If object fits in sack or small container
594*/
595boolean small(obj)
596int obj;
597{
598 return (bitset(g.obj_state[obj], 5));
599}
600
601/*
602 toting .TRUE. If an item is being caried.
603*/
604int toting(item)
605int item;
606{
607 boolean aaa, bbb, ccc;
608 int contnr, outer, outer2;
609
610 contnr = -g.place[item];
611 outer = -g.place[contnr];
612 outer2 = -g.place[outer];
613
614 aaa = holding(contnr);
615 bbb = enclosed(contnr) && holding(outer);
616 ccc = enclosed(outer) && holding(outer2);
617
618 return (holding(item) || (enclosed(item) && (aaa || bbb || ccc)));
619}
620
621/*
622 treasr .TRUE. If object is valuable for points
623*/
624boolean treasr(obj)
625int obj;
626{
627 return (bitset(g.obj_state[obj], 14));
628}
629
630/*
631 vessel .TRUE. if object can hold a liquid
632*/
633boolean vessel(obj)
634int obj;
635{
636 return (bitset(g.obj_state[obj], 15));
637}
638
639/*
640 wearng .TRUE. If wearing obj
641*/
642boolean wearng(item)
643int item;
644{
645 return (bitset(g.obj_state[item], WEARBT));
646}
647
648/*
649 worn .TRUE. if object is being worn
650*/
651boolean worn(obj)
652int obj;
653{
654 return (bitset(g.obj_state[obj], 11));
655}
656
657static char *e_msg[] = {
658 "message line > 70 characters", /* 00 */
659 "null line in message", /* 01 */
660 "too many words of messages", /* 02 */
661 "too many travel options", /* 03 */
662 "too many vocabulary words", /* 04 */
663 "required vocabulary word not found", /* 05 */
664 "too many rtext or mtext messages", /* 06 */
665 "too many hints", /* 07 */
666 "location has loc_attrib bit being set twice", /* 08 */
667 "invalid section number in database", /* 09 */
668 "out of order locs or rspeak entries.", /* 10 */
669 "illegal motion word in travel table", /* 11 */
670 "** unused **.",/* 12 */
671 "unknown or illegal word in adjective table.", /* 13 */
672 "illegal word in prep/obj table", /* 14 */
673 "too many entries in prep/obj table", /* 15 */
674 "object has condition bit set twice", /* 16 */
675 "object number too large", /* 17 */
676 "too many entries in adjective/noun table.", /* 18 */
677 "** unused **.",/* 19 */
678 "special travel (500>l>300) exceeds goto list", /* 20 */
679 "ran off end of vocabulary table", /* 21 */
680 "verb class (n/1000) not between 1 and 3", /* 22 */
681 "intransitive action verb exceeds goto list", /* 23 */
682 "transitive action verb exceeds goto list", /* 24 */
683 "conditional travel entry with no alternative", /* 25 */
684 "location has no travel entries", /* 26 */
685 "hint number exceeds goto list", /* 27 */
686 "invalid month returned by date function", /* 28 */
687 "action verb 'leave' has no object.", /* 29 */
688 "preposition found in unexpected table", /* 30 */
689 "received an unexpected word terminator from a1toa5", /* 31 */
690 "trying to put a container into itself (tricky!)", /* 32 */
691 "unknown word class in getwds", /* 33 */
692 "** unused **.",/* 34 */
693 "trying to carry a non-existent object"}; /* 35 */
694
695/*
696 Fatal error routine
697*/
698void bug(n)
699unsigned int n;
700{
701 if (n < 36 && *e_msg[n] != '*')
702 fprintf(stderr, "Fatal error, probable cause: %s\n", e_msg[n]);
703 else
704 fprintf(stderr, "Fatal error number %d - Unused error number!\n", n);
705 panic((char *) 0, TRUE);
706}
707
708/*
709 Prompt for input, strip leading and trailing spaces,
710 return &buf[first non-whitespace].
711 Does not return if end of input.
712*/
713char *
714 ask(prompt, buf, buflen)
715char *prompt, *buf;
716int buflen;
717{
718 fputs(prompt, stdout);
719 fflush(stdout);
720 if (!fgets(buf, buflen, stdin))
721 panic("end of input", FALSE);
722 if (*buf) {
723 int c;
724 char *end = buf + strlen(buf);
725 if (end[-1] != '\n')
726 /* Skip to end of line */
727 while ((c = getchar()) != '\n' && c != EOF);
728 while (*buf && isspace(*buf))
729 buf++;
730 while (buf <= --end && isspace(*end))
731 *end = '\0';
732 }
733 return buf;
734}
735
736/*
737 save and abort
738*/
739
740void panic(msg, save)
741char *msg;
742boolean save;
743{
744 fprintf(stderr, "\nPANIC: %s%s\n",
745 msg ? msg : "", save ? ". Save..." : msg ? "" : "aborting.");
746 if (save)
747 saveadv("advpanic.sav");
748 exit(EXIT_FAILURE);
749}
Note: See TracBrowser for help on using the repository browser.