1 /* omega copyright (C) by Laurence Raphael Brothers, 1987,1988,1989 */
2 /* inv.c */
3 /* functions having to do with player item inventory */
4
5 #ifdef MSDOS_SUPPORTED_ANTIQUE
6 # include "curses.h"
7 #else
8 # ifdef AMIGA
9 # include <curses210.h>
10 # else
11 # ifdef __FreeBSD__
12 # include <ncurses.h>
13 # else
14 # include <curses.h>
15 # endif
16 # endif
17 #endif
18
19 #include "glob.h"
20
21 /* drops money, heh heh */
drop_money()22 void drop_money()
23 {
24 pob money;
25
26 /* WDT HACK! Let me guess -- this is yet another memory leak, right? */
27 money = detach_money();
28 if (money != NULL) {
29 if (Current_Environment == E_CITY) {
30 print1("As soon as the money leaves your hand,");
31 print2("a horde of scrofulous beggars snatch it up and are gone!");
32 }
33 else drop_at(Player.x,Player.y,money);
34 }
35 else setgamestatus(SKIP_MONSTERS);
36 }
37
38
39
40 /* returns some money from player back into "money" item.
41 for giving and dropping money */
detach_money()42 pob detach_money()
43 {
44 long c;
45 pob cash=NULL;
46 c = get_money(Player.cash);
47 if (c != ABORT) {
48 Player.cash -= c;
49 cash = ((pob) checkmalloc(sizeof(objtype)));
50 make_cash(cash,difficulty());
51 cash->basevalue = c;
52 }
53 return(cash);
54 }
55
56
57 /* gets a legal amount of money or ABORT */
get_money(limit)58 long get_money(limit)
59 long limit;
60 {
61 long c;
62 print1("How much? ");
63 c = parsenum();
64 if (c > limit) {
65 print3("Forget it, buddy.");
66 return(ABORT);
67 }
68 else return(c);
69 }
70
71
72
73 /* pick up from some location x,y */
74 /* Lift entire itemlist off ground, pass it to inventory control, which
75 may drop things back onto the now null ground */
pickup_at(x,y)76 void pickup_at(x,y)
77 int x,y;
78 {
79 int quit = FALSE;
80 char response;
81 pol ol = Level->site[x][y].things;
82 pol temp;
83
84 resetgamestatus(FAST_MOVE);
85
86 Level->site[x][y].things = NULL;
87
88 while (ol != NULL) {
89 if (! quit) {
90 clearmsg1();
91 print1("Pick up: ");
92 nprint1(itemid(ol->thing));
93 nprint1(" [ynq]: ");
94 response = ynq1();
95 quit = (response == 'q');
96 }
97 if (response == 'y') gain_item(ol->thing);
98 else drop_at(x,y,ol->thing);
99 temp = ol;
100 ol = ol->next;
101 temp->thing = NULL;
102 temp->next = NULL;
103 free((char *) temp);
104 }
105 }
106
107
108 /* WDT -- convert from a char (keypress) to an item index in
109 * player inventory */
110 /* Item identifiers, in this case the letters of the alphabet minus
111 * any letters already used for commands. Yes, there are more here
112 * than could be needed, but I don't want to short myself for later.
113 */
114 signed char inventory_keymap[] = "-abcfghimnoqruvwyz";
key_to_index(key)115 int key_to_index(key)
116 signed char key;
117 {
118 int i;
119 assert( MAXITEMS>0 ); /* must have room for an item, or this loop will
120 * die! */
121
122 for (i=0; i<MAXITEMS; i++) {
123 if (key == inventory_keymap[i])
124 return (signed char)i;
125 }
126 return O_UP_IN_AIR;
127 }
128
index_to_key(index)129 signed char index_to_key(index)
130 signed int index;
131 {
132 if ( index < MAXITEMS )
133 return inventory_keymap[index];
134 else return '-';
135 }
136
137
138 /* criteria for being able to put some item in some slot */
139 /* WDT -- why on earth does the 'slottable' function print stuff???? */
aux_slottable(o,slot)140 int aux_slottable(o,slot)
141 pob o;
142 int slot;
143 {
144 int ok = TRUE;
145 if (o == NULL) ok = FALSE;
146 else if (slot == O_ARMOR) {
147 if (o->objchar != ARMOR) {
148 ok = FALSE;
149 }
150 }
151 else if (slot == O_SHIELD) {
152 if (o->objchar != SHIELD) {
153 ok = FALSE;
154 }
155 }
156 else if (slot == O_BOOTS) {
157 if (o->objchar != BOOTS) {
158 ok = FALSE;
159 }
160 }
161 else if (slot == O_CLOAK) {
162 if (o->objchar != CLOAK) {
163 ok = FALSE;
164 }
165 }
166 else if (slot >= O_RING1) {
167 if (o->objchar != RING) {
168 ok = FALSE;
169 }
170 }
171 return(ok);
172 }
173
174 /* put all of o on objlist at x,y on Level->depth */
175 /* Not necessarily dropped by character; just dropped... */
drop_at(x,y,o)176 void drop_at(x,y,o)
177 int x,y;
178 pob o;
179 {
180 pol tmp;
181 pob cpy;
182
183 if (Current_Environment != E_COUNTRYSIDE) {
184 if ((Level->site[x][y].locchar != VOID_CHAR) &&
185 (Level->site[x][y].locchar != ABYSS)) {
186 cpy = ((pob) checkmalloc(sizeof(objtype)));
187 tmp = ((pol) checkmalloc(sizeof(oltype)));
188 *cpy = *o;
189 cpy->used = FALSE;
190 tmp->thing = cpy;
191 tmp->next = Level->site[x][y].things;
192 Level->site[x][y].things = tmp;
193 }
194 else if (Level->site[x][y].p_locf == L_VOID_STATION)
195 setgamestatus(PREPARED_VOID);
196 }
197 }
198
199 /* put n of o on objlist at x,y on Level->depth */
p_drop_at(x,y,n,o)200 void p_drop_at(x,y,n,o)
201 int x,y;
202 int n;
203 pob o;
204 {
205 pol tmp;
206 if (Current_Environment != E_COUNTRYSIDE)
207 if ((Level->site[x][y].locchar != VOID_CHAR) &&
208 (Level->site[x][y].locchar != ABYSS)) {
209 tmp = ((pol) checkmalloc(sizeof(oltype)));
210 tmp->thing = ((pob) checkmalloc(sizeof(objtype)));
211 *(tmp->thing) = *o;
212 tmp->thing->used = FALSE;
213 tmp->thing->number = n;
214 print2("Dropped ");
215 nprint2(itemid(tmp->thing));
216 morewait();
217 tmp->next = Level->site[x][y].things;
218 Level->site[x][y].things = tmp;
219 }
220 else if (Level->site[x][y].p_locf == L_VOID_STATION)
221 setgamestatus(PREPARED_VOID);
222 }
223
224
225 /* returns a string for identified items */
itemid(obj)226 char *itemid(obj)
227 pob obj;
228 {
229 char tstr[80];
230 if (obj->objchar==CASH){
231 strcpy(Str4,obj->truename);
232 return(Str4);
233 }
234 else {
235 if (Objects[obj->id].known > obj->known)
236 obj->known = Objects[obj->id].known;
237
238 setnumstr(obj,tstr);
239 strcpy(Str4,tstr);
240 if (obj->known == 0)
241 strcat(Str4,obj->objstr);
242 else if (obj->known == 1) {
243 if (obj->id == ARTIFACTID + 8 || obj->id == ARTIFACTID + 20 ||
244 obj->id == ARTIFACTID + 21)
245 strcat(Str4, "the ");
246 strcat(Str4,obj->truename);
247 }
248 else {
249 if (obj->id == ARTIFACTID + 8 || obj->id == ARTIFACTID + 20 ||
250 obj->id == ARTIFACTID + 21)
251 strcat(Str4, "the ");
252 if (obj->usef == I_NOTHING && Objects[obj->id].usef != I_NOTHING)
253 strcat(Str4, "disenchanted ");
254 if (obj->blessing < 0) {
255 strcat(Str4, "cursed ");
256 strcat(Str4, obj->cursestr);
257 }
258 else if (obj->blessing > 0) {
259 strcat(Str4, "blessed ");
260 strcat(Str4, obj->truename);
261 }
262 else strcat(Str4,obj->truename);
263 if (obj->number > 1) strcat(Str4,"s");
264 switch (obj->objchar) {
265 case STICK:
266 setchargestr(obj,tstr);
267 strcat(Str4,tstr);
268 break;
269 case MISSILEWEAPON:
270 case ARMOR:
271 case RING:
272 case SHIELD:
273 case WEAPON:
274 setplustr(obj,tstr);
275 strcat(Str4, tstr);
276 break;
277 default: strcat(Str4,""); break;
278 }
279 }
280 return(Str4);
281 }
282 }
283
cashstr()284 char *cashstr()
285 {
286 if (difficulty() < 3) return("copper pieces");
287 else if (difficulty() < 5) return("silver pieces");
288 else if (difficulty() < 7) return("gold pieces");
289 else if (difficulty() < 8) return("semiprecious gems");
290 else if (difficulty() < 9) return("mithril pieces");
291 else if (difficulty() < 10) return("precious gems");
292 else return("orichalc pieces");
293 }
294
295 /* return an object's plus as a string */
setplustr(obj,pstr)296 void setplustr(obj,pstr)
297 pob obj;
298 char *pstr;
299 {
300 pstr[0] = ' ';
301 pstr[1] = (obj->plus < 0 ? '-' : '+' );
302 if (abs(obj->plus) < 10) {
303 pstr[2] = '0' + abs(obj->plus);
304 pstr[3] = 0;
305 }
306 else {
307 pstr[2] = '0' + abs(obj->plus / 10);
308 pstr[3] = '0' + abs(obj->plus % 10);
309 pstr[4] = 0;
310 }
311 }
312
313 /* return an object's number as a string */
setnumstr(obj,nstr)314 void setnumstr(obj,nstr)
315 pob obj;
316 char *nstr;
317 {
318 if (obj->number < 2)
319 nstr[0] = 0;
320 else if (obj->number < 10) {
321 nstr[0] = '0' + obj->number;
322 nstr[1] = 'x';
323 nstr[2] = ' ';
324 nstr[3] = 0;
325 }
326 else if (obj->number < 41) {
327 nstr[0] = '0' + ((int)(obj->number / 10));
328 nstr[1] = '0' + (obj->number % 10);
329 nstr[2] = 'x';
330 nstr[3] = ' ';
331 nstr[4] = 0;
332 }
333 else strcpy(nstr,"lots of ");
334 }
335
336
337
338
339 /* return object with charges */
setchargestr(obj,cstr)340 void setchargestr(obj,cstr)
341 pob obj;
342 char *cstr;
343 {
344 cstr[0] = ' ';
345 cstr[1] = '[';
346 if (obj->charge < 0) {
347 cstr[2]='d';
348 cstr[3]='e';
349 cstr[4]='a';
350 cstr[5]='d';
351 cstr[6]=']';
352 cstr[7]=0;
353 }
354 else if (obj->charge < 10) {
355 cstr[2] = '0' + obj->charge;
356 cstr[3] = ']';
357 cstr[4] = 0;
358 }
359 else {
360 cstr[2] = '0' + ((int)(obj->charge / 10));
361 cstr[3] = '0' + (obj->charge % 10);
362 cstr[4] = ']';
363 cstr[5] = 0;
364 }
365 }
366
367
give_money(m)368 void give_money(m)
369 struct monster *m;
370 {
371 pob cash;
372
373 cash = detach_money();
374 if (cash == NULL)
375 setgamestatus(SKIP_MONSTERS);
376 else givemonster(m,cash);
377 }
378
379
380
givemonster(m,o)381 void givemonster(m,o)
382 struct monster *m;
383 struct object *o;
384 {
385 /* special case -- give gem to LawBringer */
386 if ((m->id == LAWBRINGER) && (o->id == ARTIFACTID+21)) {
387 clearmsg();
388 print1("The LawBringer accepts the gem reverently.");
389 print2("He raises it above his head, where it bursts into lambent flame!");
390 morewait();
391 print1("You are bathed in a shimmering golden light.");
392 print2("You feel embedded in an infinite matrix of ordered energy.");
393 morewait();
394 if (Imprisonment > 0)
395 Imprisonment = 0;
396 if (Player.rank[ORDER] == -1) {
397 print2("You have been forgiven. You feel like a Paladin....");
398 Player.rank[ORDER] = 1;
399 }
400 Player.alignment += 200;
401 Player.pow = Player.maxpow = Player.pow * 2;
402 gain_experience(2000);
403 setgamestatus(GAVE_STARGEM);
404 /* WDT HACK!!! Where else would this ever get freed?? */
405 free(o);
406 }
407 else {
408 if (m->uniqueness == COMMON) {
409 strcpy(Str3,"The ");
410 strcat(Str3,m->monstring);
411 }
412 else strcpy(Str3,m->monstring);
413
414 if (m_statusp(m,GREEDY) || m_statusp(m,NEEDY)) {
415 m_pickup(m,o);
416 strcat(Str3," takes your gift");
417 print1(Str3);
418 Player.alignment++;
419 if (m_statusp(m,GREEDY) && (true_item_value(o) < (long) m->level*100))
420 nprint1("...but does not appear satisfied.");
421 else if (m_statusp(m,NEEDY) &&
422 (true_item_value(o) < (long) Level->depth*Level->depth))
423 nprint1("...and looks chasteningly at you.");
424 else {
425 nprint1("...and seems happy with it.");
426 m_status_reset(m,HOSTILE);
427 m_status_reset(m,GREEDY);
428 m_status_reset(m,NEEDY);
429 }
430 }
431 else if (m_statusp(m,HUNGRY)) {
432
433 if (((m->id == HORSE) && (o->id == FOODID+15)) || /* grain */
434 ((m->id != HORSE) &&
435 ((o->usef == I_FOOD) || (o->usef == I_POISON_FOOD)))) {
436 strcat(Str3," wolfs down your food ... ");
437 print1(Str3);
438 m_status_reset(m,HUNGRY);
439 m_status_reset(m,HOSTILE);
440 if (o->usef == I_POISON_FOOD) {
441 Player.alignment -= 2;
442 nprint1("...and chokes on the poisoned ration!");
443 morewait();
444 m_status_set(m,HOSTILE);
445 m_damage(m,100,POISON);
446 }
447 else nprint1("...and now seems satiated.");
448 morewait();
449 free((char *)o);
450 }
451 else {
452 strcat(Str3," spurns your offering and leaves it on the ground.");
453 print1(Str3);
454 drop_at(m->x,m->y,o);
455 }
456 }
457 else {
458 strcat(Str3," doesn't care for your offering and drops it.");
459 print1(Str3);
460 drop_at(m->x,m->y,o);
461 }
462 }
463 }
464
465
466
467
468 /* will clear all, not just one of an object. */
conform_lost_object(obj)469 void conform_lost_object(obj)
470 pob obj;
471 {
472 if (obj != NULL) conform_lost_objects(obj->number,obj);
473 }
474
475
476
477 /* removes n of object from inventory; frees object if appropriate. */
478
dispose_lost_objects(n,obj)479 void dispose_lost_objects(n,obj)
480 int n;
481 pob obj;
482 {
483 int i,conformed=FALSE,subtracted=FALSE;
484
485 if (obj == NULL)
486 return;
487 for(i=0;i<MAXITEMS;i++)
488 if (Player.possessions[i] == obj) {
489 if (! subtracted) {
490 obj->number -= n;
491 subtracted = TRUE;
492 }
493 if (obj->number < 1) {
494 if (!conformed) {
495 conform_unused_object(obj);
496 conformed = TRUE;
497 }
498 Player.possessions[i] = NULL;
499 }
500 }
501 if (obj->number < 1)
502 free((char *) obj);
503 }
504
505
506
507
508 /* removes n of object from inventory without freeing object.
509 Removes all instances of pointer (might be 2 handed weapon, etc) */
conform_lost_objects(n,obj)510 void conform_lost_objects(n,obj)
511 int n;
512 pob obj;
513 {
514 int i,conformed=FALSE,subtracted=FALSE;
515 if (obj != NULL) for(i=0;i<MAXITEMS;i++)
516 if (Player.possessions[i] == obj) {
517 if (! subtracted) {
518 obj->number -= n;
519 subtracted = TRUE;
520 }
521 if (obj->number < 1) {
522 if (!conformed) {
523 conform_unused_object(obj);
524 conformed = TRUE;
525 }
526 Player.possessions[i] = NULL;
527 }
528 }
529 }
530
531
532 /* clears unused possession */
conform_unused_object(obj)533 void conform_unused_object(obj)
534 pob obj;
535 {
536 if (obj->used) {
537 obj->used = FALSE;
538 item_use(obj);
539 }
540 calc_melee();
541 }
542
543
544 /* select an item from inventory */
545 /* if itype is NULL_ITEM, any kind of item is acceptable.
546 if itype is CASH, any kind of item or '$' (cash) is acceptable.
547 if itype is FOOD, CORPSE or FOOD is acceptable, but only FOOD is
548 listed in the possibilities.
549 if itype is any other object type (eg SCROLL, POTION, etc.), only
550 that type of item is acceptable or is listed */
551
getitem(itype)552 int getitem(itype)
553 Symbol itype;
554 {
555 char invstr[64];
556 char key;
557 int i,k=0,ok=FALSE,drewmenu=FALSE,found=FALSE;
558
559 found = ((itype == NULL_ITEM) || ((itype == CASH) && (Player.cash > 0)));
560 invstr[0]=0;
561 for(i=1;i<MAXITEMS;i++)
562 if (Player.possessions[i] != NULL)
563 if ((itype == NULL_ITEM) ||
564 (itype == CASH) ||
565 (Player.possessions[i]->objchar == itype) ||
566 ((itype == FOOD) && (Player.possessions[i]->objchar == CORPSE))) {
567 found = TRUE;
568 invstr[k++] = index_to_key(i);
569 invstr[k] = 0;
570 }
571 if ((itype == CASH) && found) {
572 invstr[k++] = '$';
573 invstr[k] = 0;
574 }
575 if (! found) {
576 print3("Nothing appropriate.");
577 return(ABORT);
578 }
579 else {
580 print2("Select an item [");
581 nprint2(invstr);
582 nprint2(",?] ");
583 while (! ok) {
584 key = (char) mcigetc();
585 if (key == '?') {
586 drewmenu = TRUE;
587 for (i=1;i<MAXITEMS;i++)
588 if (Player.possessions[i] != NULL)
589 if ((itype == NULL_ITEM) ||
590 (itype == CASH) ||
591 (Player.possessions[i]->objchar == itype) ||
592 ((itype == FOOD) &&
593 (Player.possessions[i]->objchar == CORPSE)))
594 display_inventory_slot(i,FALSE);
595 }
596 else if (key == ESCAPE) ok = TRUE;
597 else if (key == (CASH&0xff)) {
598 if (itype == CASH) ok = TRUE;
599 else {
600 print3("You cannot select cash now.");
601 ok = FALSE;
602 }
603 }
604 else if ( !strmem(key,invstr) || key_to_index(key)==(signed char)-1 )
605 print3("Nope! Try again [? for inventory, ESCAPE to quit]:");
606 else ok = TRUE;
607 }
608 if (drewmenu) xredraw();
609 if (key == ESCAPE) return(ABORT);
610 else if (key == (CASH&0xff)) return(CASHVALUE);
611 else return key_to_index(key);
612 }
613 }
614
615
616 /* true if the numerical index based on 'a' == 1 turns out to be either
617 out of the range of the possessions array or a null item */
badobject(slotchar)618 int badobject(slotchar)
619 char slotchar;
620 {
621 int slot = slotchar + 1 - 'a';
622 if ((slot<1) || (slot >= MAXITEMS)) return(TRUE);
623 else return(Player.possessions[slot] == NULL);
624 }
625
626
627 #ifndef MSDOS_SUPPORTED_ANTIQUE
628 /* this takes the numerical index directly for the same effect as badobject*/
baditem(slotnum)629 int baditem(slotnum)
630 int slotnum;
631 {
632 if ((slotnum<1) || (slotnum >= MAXITEMS)) return(TRUE);
633 else return(Player.possessions[slotnum] == NULL);
634 }
635 #endif
636
637
638
639 /* formerly add_item_to_pack */
gain_item(o)640 void gain_item(o)
641 struct object *o;
642 {
643 if (o->uniqueness == UNIQUE_MADE)
644 Objects[o->id].uniqueness = UNIQUE_TAKEN;
645 if (o->objchar == CASH) {
646 print2("You gained some cash.");
647 Player.cash += o->basevalue;
648 free((char *)o);
649 dataprint();
650 }
651 else if (optionp(PACKADD)) {
652 if (! get_to_pack(o)) {
653 Player.possessions[O_UP_IN_AIR] = o;
654 do_inventory_control();
655 }
656 }
657 else {
658 Player.possessions[O_UP_IN_AIR] = o;
659 do_inventory_control();
660 }
661 }
662
663 /* inserts the item at the start of the pack array */
push_pack(o)664 void push_pack(o)
665 pob o;
666 {
667 int i;
668 for (i = Player.packptr; i > 0; i--)
669 Player.pack[i] = Player.pack[i-1];
670 Player.pack[0] = o;
671 Player.packptr++;
672 }
673
674 /* Adds item to pack list */
add_to_pack(o)675 void add_to_pack(o)
676 pob o;
677 {
678 if (Player.packptr >= MAXPACK) {
679 print3("Your pack is full. The item drops to the ground.");
680 drop_at(Player.x,Player.y,o);
681 }
682 else {
683 push_pack(o);
684 print3("Putting item in pack.");
685 }
686 }
687
688 /* Adds item to pack list, maybe going into inventory mode if pack is full */
get_to_pack(o)689 int get_to_pack(o)
690 pob o;
691 {
692 if (Player.packptr >= MAXPACK) {
693 print3("Your pack is full.");
694 morewait();
695 return(FALSE);
696 }
697 else {
698 push_pack(o);
699 print3("Putting item in pack.");
700 return(TRUE);
701 }
702 }
703
pack_item_cost(index)704 int pack_item_cost(index)
705 {
706 int cost;
707 if (index > 20) {
708 cost = 17;
709 }
710 else if (index > 15) {
711 cost = 7;
712 }
713 else cost = 2;
714 return cost;
715 }
716
717 /* WDT -- 'response' must be an index into the pack. */
use_pack_item(response,slot)718 int use_pack_item(response,slot)
719 int response,slot;
720 {
721 pob item; int i;
722 i = pack_item_cost(response);
723 if (i > 10) {
724 print1("You begin to rummage through your pack.");
725 morewait();
726 }
727 if (i > 5) {
728 print1("You search your pack for the item.");
729 morewait();
730 }
731 print1("You take the item from your pack.");
732 morewait();
733 Command_Duration += i;
734 item = Player.possessions[slot] = Player.pack[response];
735 for(i=response;i<Player.packptr-1;i++)
736 Player.pack[i] = Player.pack[i+1];
737 Player.pack[--Player.packptr] = NULL;
738
739 if ((slot == O_READY_HAND || slot == O_WEAPON_HAND) &&
740 twohandedp(item->id))
741 {
742 if (Player.possessions[O_READY_HAND] == NULL)
743 Player.possessions[O_READY_HAND] = item;
744 if (Player.possessions[O_WEAPON_HAND] == NULL)
745 Player.possessions[O_WEAPON_HAND] = item;
746 }
747 if (item_useable(item,slot)) {
748 item->used = TRUE;
749 item_use(item);
750 morewait();
751 if (item->number > 1) pack_extra_items(item);
752 }
753 }
754
755 /* WDT HACK! This ought to be in scr.c, along with its companion. However,
756 * right now it's only used in the function directly below. */
aux_display_pack(start_item,slot)757 int aux_display_pack(start_item,slot)
758 int start_item,slot;
759 {
760 int i=start_item, items;
761 char *depth_string;
762 if (Player.packptr < 1) print3("Pack is empty.");
763 else if (Player.packptr <= start_item) print3("You see the leather at the bottom of the pack.");
764 else {
765 menuclear();
766 items = 0;
767 for(i=start_item;i<Player.packptr && items<ScreenLength-5;i++) {
768 if ( aux_slottable(Player.pack[i],slot) ) {
769 if (pack_item_cost(i) > 10)
770 depth_string = "**";
771 else if (pack_item_cost(i) > 5)
772 depth_string = "* ";
773 else depth_string = " ";
774 sprintf(Str1, " %c: %s %s\n", i + 'a', depth_string,
775 itemid(Player.pack[i]));
776 if (items == 0)
777 menuprint("Items in Pack:\n");
778 menuprint(Str1);
779 items++;
780 }
781 }
782 if (items == 0)
783 menuprint("You see nothing useful for that slot in the pack.");
784 else {
785 menuprint("\n*: Takes some time to reach; **: buried very deeply.");
786 }
787 showmenu();
788 }
789 return i;
790 }
791
792 /* takes something from pack, puts to slot,
793 or to 'up-in-air', one of which at least must be empty */
aux_take_from_pack(slot)794 int aux_take_from_pack(slot)
795 int slot;
796 {
797 char response,pack_item, last_item;
798 int i,quit = FALSE,ok=TRUE;
799 if (Player.possessions[slot] != NULL)
800 slot = O_UP_IN_AIR;
801 if (Player.possessions[slot] != NULL)
802 print3("slot is not empty!");
803 else if (Player.packptr < 1)
804 print3("Pack is empty!");
805 else {
806 pack_item = 0;
807 do {
808 ok = TRUE;
809 last_item = aux_display_pack(pack_item,slot);
810 if (last_item == Player.packptr && pack_item == 0 )
811 print1("Enter pack slot letter or ESCAPE to quit.");
812 else if (last_item == Player.packptr)
813 print1("Enter pack slot letter, - to go back, or ESCAPE to quit.");
814 else if (pack_item == 0)
815 print1("Enter pack slot letter, + to see more, or ESCAPE to quit.");
816 else
817 print1("Enter pack slot letter, + or - to see more, or ESCAPE to quit.");
818 response = mcigetc();
819 if (response == '?') {
820 /* WDT HACK -- display some help instead. */
821 print1("Help not implemented (sorry).");
822 morewait();
823 ok = FALSE;
824 }
825 else if (response == ESCAPE) quit = TRUE;
826 else if (response == '+') {
827 if (last_item < Player.packptr)
828 pack_item = last_item;
829 ok = FALSE;
830 }
831 else if (response == '-') {
832 /* WDT HACK: this _should_ make us page up. Sadly,
833 * I have no way of calculating how much I'll be paging up.
834 * This is fixable, but I have no idea how much work... */
835 pack_item = 0;
836 ok = FALSE;
837 }
838 else{
839 ok = ((response >= 'a') && (response < 'a'+Player.packptr));
840 if (ok) ok = slottable(Player.pack[response-'a'],slot);
841 }
842 } while (! ok);
843 if (! quit) {
844 use_pack_item(response - 'a',slot);
845 }
846 }
847 display_possessions();
848 return slot;
849 }
850
851 /* takes something from pack, puts to slot,
852 or to 'up-in-air', one of which at least must be empty */
aux_top_take_from_pack(slot,display)853 int aux_top_take_from_pack(slot,display)
854 int slot,display;
855 {
856 char response;
857 int i,quit = FALSE,ok=TRUE,displayed=FALSE;
858 pob item;
859 if (Player.possessions[slot] != NULL)
860 slot = O_UP_IN_AIR;
861 if (Player.possessions[slot] != NULL)
862 print3("slot is not empty!");
863 else if (Player.packptr == 0)
864 print3("Pack is empty!");
865 else {
866 do {
867 ok = TRUE;
868 print1("Enter pack slot letter, or ? to show pack, or ESCAPE to quit.");
869 response = mcigetc();
870 if (response == '?') {
871 display_pack();
872 displayed = TRUE;
873 ok = FALSE;
874 }
875 else if (response == ESCAPE) quit = TRUE;
876 else{
877 ok = ((response >= 'a') && (response < 'a'+Player.packptr));
878 if (ok) ok = slottable(Player.pack[response-'a'],slot);
879 }
880 } while (! ok);
881 if (! quit) use_pack_item(response - 'a',slot);
882 }
883 if (displayed) {
884 if (display)
885 display_possessions();
886 else
887 xredraw();
888 }
889 return slot;
890 }
891
take_from_pack(slot,display)892 int take_from_pack(slot,display)
893 int slot,display;
894 {
895 if (optionp(TOPINV)) aux_top_take_from_pack(slot,display);
896 else aux_take_from_pack(slot);
897 }
898
899
900 #ifndef MSDOS_SUPPORTED_ANTIQUE
901 /* General interface to inventory */
item_inventory(topline)902 void item_inventory(topline)
903 int topline;
904 {
905 if (topline) {
906 display_possessions();
907 inventory_control();
908 }
909 else top_inventory_control();
910 }
911 #endif
912
913
do_inventory_control()914 void do_inventory_control()
915 {
916 if (optionp(TOPINV)) top_inventory_control();
917 else {
918 menuclear();
919 display_possessions();
920 inventory_control();
921 }
922 }
923
924 /* inventory_control assumes a few setup things have been done,
925 like displaying the slots, loading the O_UP_IN_AIR item, etc.
926
927 Each action uses up a little time. If only inspection actions
928 are taken, no time is used up. */
929
930
inventory_control()931 void inventory_control()
932 {
933 int slot = 0,done=FALSE;
934 int response;
935 char letter;
936 #ifdef MSDOS_SUPPORTED_ANTIQUE
937 int simple = 0;
938 #endif
939 clearmsg3();
940 checkclear();
941 print1("Action [d,e,l,p,s,t,x,>,<,?,ESCAPE]:");
942 show_inventory_slot(slot,FALSE);
943 display_inventory_slot(O_UP_IN_AIR,FALSE);
944 do {
945 move_slot(slot,slot,MAXITEMS);
946 response = mcigetc();
947
948 switch(response) {
949 case 12:
950 case 18: /* ^l, ^r */
951 display_possessions();
952 break;
953 case 'd':
954 if (Player.possessions[O_UP_IN_AIR] != NULL)
955 {
956 drop_from_slot(O_UP_IN_AIR);
957 display_inventory_slot(O_UP_IN_AIR, FALSE);
958 }
959 else if (Player.possessions[slot] != NULL)
960 {
961 drop_from_slot(slot);
962 show_inventory_slot(slot, FALSE);
963 }
964 else print3("Nothing in selected slot!");
965 Command_Duration++;
966 break;
967 case 'l':
968 Str1[0] = '\0';
969 if (Player.possessions[slot] != NULL) {
970 if (!strcmp(itemid(Player.possessions[slot]),
971 Player.possessions[slot]->objstr))
972 print3("You notice nothing new about it.");
973 else {
974 if (Player.possessions[slot]->uniqueness == COMMON)
975 strcat(Str1, "Your ");
976 strcat(Str1, itemid(Player.possessions[slot]));
977 if (Player.possessions[slot]->objchar == BOOTS)
978 strcat(Str1, " look like ");
979 else {
980 strcat(Str1, " looks like a");
981 letter = Player.possessions[slot]->objstr[0];
982 if (letter == 'a' || letter == 'A' || letter == 'e' ||
983 letter == 'E' || letter == 'i' || letter == 'I' ||
984 letter == 'o' || letter == 'O' || letter == 'u' || letter == 'U')
985 strcat(Str1, "n ");
986 else
987 strcat(Str1, " ");
988 }
989 strcat(Str1, Player.possessions[slot]->objstr);
990 print3(Str1);
991 }
992 }
993 else print3("Nothing in selected slot!");
994 break;
995 case 'p':
996 if (Player.possessions[slot] != NULL)
997 {
998 put_to_pack(slot);
999 show_inventory_slot(slot, FALSE);
1000 }
1001 Command_Duration+=5;
1002 break;
1003 case 's':
1004 display_pack();
1005 morewait();
1006 display_possessions();
1007 Command_Duration+=5;
1008 break;
1009 case 't':
1010 show_inventory_slot(take_from_pack(slot,TRUE), FALSE);
1011 Command_Duration+=5;
1012 break;
1013 case 'e':
1014 switch_to_slot(slot);
1015 show_inventory_slot(O_UP_IN_AIR,FALSE);
1016 show_inventory_slot(slot,FALSE);
1017 Command_Duration+=2;
1018 break;
1019 case '\n':
1020 case 'x':
1021 switch_to_slot(slot);
1022 show_inventory_slot(O_UP_IN_AIR,FALSE);
1023 show_inventory_slot(slot,FALSE);
1024 Command_Duration+=2;
1025 done = (Player.possessions[O_UP_IN_AIR] == NULL);
1026 break;
1027 case 'j':
1028 case '>':
1029 case '2':
1030 #if defined(KEY_DOWN)
1031 case KEY_DOWN:
1032 #endif
1033 slot = move_slot(slot,slot+1,MAXITEMS);
1034 break;
1035 case 'k':
1036 case '<':
1037 case '8':
1038 #if defined(KEY_UP)
1039 case KEY_UP:
1040 #endif
1041 slot = move_slot(slot,slot-1,MAXITEMS);
1042 break;
1043 #ifdef KEY_HOME
1044 case KEY_HOME:
1045 #endif
1046 case '-':
1047 slot = move_slot(slot,0,MAXITEMS);
1048 break;
1049 #ifdef KEY_LL
1050 case KEY_LL:
1051 #endif
1052 case '+':
1053 slot = move_slot(slot,MAXITEMS-1,MAXITEMS);
1054 break;
1055 case '?':
1056 menuclear();
1057 menuprint("d:\tDrop up-in-air or current item\n");
1058 menuprint("e:\tExchange current slot with up-in-air slot\n");
1059 menuprint("l:\tLook at current item\n");
1060 menuprint("p:\tPut up-in-air or current item in pack\n");
1061 menuprint("s:\tShow contents of pack\n");
1062 menuprint("t:\tTake something from pack into the\n\tcurrent or up-in-air slot\n");
1063 menuprint("x:\tAs 'e', but exit if up-in-air slot finishes empty\n");
1064 menuprint(">:\tMove down one slot/item\n");
1065 menuprint("<:\tMove up one slot/item\n");
1066 menuprint("?:\tDisplay help (this message + help file)\n");
1067 menuprint("ESCAPE:\texit\n");
1068 showmenu();
1069 clearmsg();
1070 print1("Display full help? (y/n)");
1071 if (ynq1() == 'y')
1072 inv_help();
1073 display_possessions();
1074 break;
1075 case ESCAPE:
1076 if (Player.possessions[O_UP_IN_AIR] != NULL) {
1077 drop_at(Player.x,Player.y,Player.possessions[O_UP_IN_AIR]);
1078 Player.possessions[O_UP_IN_AIR] = NULL;
1079 print3("Object 'up in air' dropped.");
1080 }
1081 done = TRUE;
1082 break;
1083 default:
1084 if (key_to_index(response) > 0) {
1085 slot = move_slot(slot,key_to_index(response),MAXITEMS);
1086 if (Player.possessions[slot] == NULL
1087 &&
1088 Player.possessions[O_UP_IN_AIR] == NULL) {
1089 show_inventory_slot(take_from_pack(slot,TRUE), FALSE);
1090 Command_Duration+=5;
1091 }
1092 else {
1093 switch_to_slot(slot);
1094 show_inventory_slot(slot,FALSE);
1095 slot = O_UP_IN_AIR;
1096 show_inventory_slot(slot,FALSE);
1097 Command_Duration+=2;
1098 }
1099 }
1100 }
1101 calc_melee();
1102 } while (! done);
1103 xredraw();
1104 }
1105
1106
1107
1108
1109
1110
1111
1112 /* same as inventory_control, but only uses msg window for i/o*/
1113
1114
top_inventory_control()1115 void top_inventory_control()
1116 {
1117 int slot = 0,done=FALSE,usedmenu=FALSE;
1118 char response, letter;
1119 clearmsg3();
1120 do {
1121 clearmsg1();
1122 print1("Action [d,e,l,p,s,t,x,~,?,ESCAPE]:");
1123 print2("'Up in air': ");
1124 if (Player.possessions[O_UP_IN_AIR] == NULL) nprint2("NOTHING");
1125 else nprint2(itemid(Player.possessions[O_UP_IN_AIR]));
1126 response = (char) mcigetc();
1127
1128 switch(response) {
1129 case 'd':
1130 if (Player.possessions[O_UP_IN_AIR] != NULL)
1131 drop_from_slot(O_UP_IN_AIR);
1132 else {
1133 slot = get_inventory_slot();
1134 if (Player.possessions[slot] != NULL)
1135 drop_from_slot(slot);
1136 else print3("Nothing in selected slot!");
1137 }
1138 Command_Duration++;
1139 break;
1140 case 'l':
1141 Str1[0] = '\0';
1142 slot = get_inventory_slot();
1143 if (Player.possessions[slot] != NULL) {
1144 if (!strcmp(itemid(Player.possessions[slot]),
1145 Player.possessions[slot]->objstr))
1146 print3("You notice nothing new about it.");
1147 else {
1148 if (Player.possessions[slot]->uniqueness == COMMON)
1149 strcat(Str1, "Your ");
1150 strcat(Str1, itemid(Player.possessions[slot]));
1151 if (Player.possessions[slot]->objchar == BOOTS)
1152 strcat(Str1, " look like ");
1153 else {
1154 strcat(Str1, " looks like a");
1155 letter = Player.possessions[slot]->objstr[0];
1156 if (letter == 'a' || letter == 'A' || letter == 'e' ||
1157 letter == 'E' || letter == 'i' || letter == 'I' ||
1158 letter == 'o' || letter == 'O' || letter == 'u' || letter == 'U')
1159 strcat(Str1, "n ");
1160 else
1161 strcat(Str1, " ");
1162 }
1163 strcat(Str1, Player.possessions[slot]->objstr);
1164 print3(Str1);
1165 }
1166 }
1167 else print3("Nothing in selected slot!");
1168 break;
1169 case 'p':
1170 if (Player.possessions[O_UP_IN_AIR] == NULL)
1171 slot = get_inventory_slot();
1172 else slot = O_UP_IN_AIR;
1173 put_to_pack(slot);
1174 Command_Duration+=5;
1175 break;
1176 case 's':
1177 display_pack();
1178 usedmenu = TRUE;
1179 Command_Duration+=5;
1180 break;
1181 case 't':
1182 slot = get_inventory_slot();
1183 (void) take_from_pack(slot,FALSE);
1184 Command_Duration+=5;
1185 break;
1186 case 'e':
1187 slot = get_inventory_slot();
1188 if ( slot == O_UP_IN_AIR ) break;
1189 switch_to_slot(slot);
1190 Command_Duration+=2;
1191 break;
1192 case 'x':
1193 slot = get_inventory_slot();
1194 if ( slot == O_UP_IN_AIR ) break;
1195 switch_to_slot(slot);
1196 Command_Duration+=2;
1197 done = (Player.possessions[O_UP_IN_AIR] == NULL);
1198 break;
1199 case '~':
1200 display_possessions();
1201 inventory_control();
1202 usedmenu = TRUE;
1203 done = TRUE;
1204 break;
1205 case '?':
1206 menuclear();
1207 menuprint("d:\tDrop an item\n");
1208 menuprint("e:\tExchange a slot with up-in-air slot\n");
1209 menuprint("l:\tLook at an item\n");
1210 menuprint("p:\tPut an item in pack\n");
1211 menuprint("s:\tShow contents of pack\n");
1212 menuprint("t:\tTake something from pack into a slot\n");
1213 menuprint("x:\tAs 'e', above, exit if up-in-air slot finishes empty\n");
1214 menuprint("~:\tEnter full-screen inventory mode\n");
1215 menuprint("?:\tDisplay help (this message + help file)\n");
1216 menuprint("ESCAPE:\texit\n");
1217 showmenu();
1218 clearmsg();
1219 print1("Display full help? (y/n)");
1220 if (ynq1() == 'y')
1221 inv_help();
1222 usedmenu=TRUE;
1223 break;
1224 case ESCAPE:
1225 if (Player.possessions[O_UP_IN_AIR] != NULL) {
1226 drop_at(Player.x,Player.y,Player.possessions[O_UP_IN_AIR]);
1227 Player.possessions[O_UP_IN_AIR] = NULL;
1228 print3("Object 'up in air' dropped.");
1229 }
1230 done = TRUE;
1231 break;
1232 }
1233 calc_melee();
1234 } while (! done);
1235 if (usedmenu)
1236 xredraw();
1237 }
1238
1239
1240
1241 /* Let the user select a slot. */
get_inventory_slot()1242 int get_inventory_slot()
1243 {
1244 signed char response;
1245 do {
1246 clearmsg1();
1247 print1("Which inventory slot ['-'='up-in-air' slot]?");
1248 response = (signed char)mcigetc();
1249 if ( response == ESCAPE || response == '-' )
1250 return O_UP_IN_AIR;
1251 else response = key_to_index(response);
1252 } while (response != O_UP_IN_AIR);
1253 return response;
1254 }
1255
1256
1257 /* returns some number between 0 and o->number */
get_item_number(o)1258 int get_item_number(o)
1259 pob o;
1260 {
1261 int n=0;
1262 if (o->number == 1)
1263 return 1;
1264 do {
1265 clearmsg();
1266 print1("How many? -- max ");
1267 mnumprint(o->number);
1268 nprint1(" :");
1269 n = (int) parsenum();
1270 if (n>o->number) print3("Too many!");
1271 else if (n<1) n = 0;
1272 } while (n > o->number);
1273 if (n < 1) n = 0;
1274 return(n);
1275 }
1276
drop_from_slot(slot)1277 void drop_from_slot(slot)
1278 int slot;
1279 {
1280 int n,waitflag;
1281 if (Player.possessions[slot] != NULL) {
1282 if(cursed(Player.possessions[slot]) == TRUE + TRUE)
1283 print3("It sticks to your fingers!");
1284 else {
1285 n = get_item_number(Player.possessions[slot]);
1286 if (n > 0) {
1287 p_drop_at(Player.x,Player.y,n,Player.possessions[slot]);
1288 waitflag = (Player.possessions[slot]->used &&
1289 (Player.possessions[slot]->number == n));
1290 conform_lost_objects(n,Player.possessions[slot]);
1291 if (waitflag) morewait();
1292 }
1293 else print3("Didn't drop anything.");
1294 }
1295 }
1296 else print3("Didn't drop anything.");
1297 }
1298
1299
put_to_pack(slot)1300 void put_to_pack(slot)
1301 int slot;
1302 {
1303 int waitflag,num = 1;
1304 pob temp,oslot = Player.possessions[slot];
1305 if (oslot == NULL)
1306 print3("Slot is empty!");
1307 else if (cursed(oslot) == TRUE+TRUE)
1308 print3("Item is cursed!");
1309 else {
1310 num = get_item_number(oslot);
1311 if (num > 0) {
1312 temp = split_item(num,oslot);
1313 waitflag = (oslot->used && (oslot->number == num));
1314 conform_lost_objects(num,oslot);
1315 if (waitflag) morewait();
1316 add_to_pack(temp);
1317 }
1318 }
1319 }
1320
1321
1322 /* splits num off of item to make newitem which is returned */
1323 /* something else (conform_lost_objects) has to reduce the actual
1324 number value of item and Player.itemweight */
split_item(num,item)1325 pob split_item(num,item)
1326 int num;
1327 pob item;
1328 {
1329 pob newitem=NULL;
1330 if (item != NULL) {
1331 newitem = ((pob) checkmalloc(sizeof(objtype)));
1332 *newitem = *item;
1333 if (num <= item->number)
1334 newitem->number = num;
1335 /* else num > item->number, so return newitem with number = item->number */
1336 newitem->used = FALSE; /* whether the original item was used or not */
1337 }
1338 return(newitem);
1339 }
1340
1341
1342
1343 /* Trades contents of "up in air" slot with selected slot. One or both
1344 may be null. If both slots are 'objequal' merges two groups into one
1345 in the selected slot. If one slot is null and the number of the other
1346 is greater than one, requests how many to move. */
1347
switch_to_slot(slot)1348 void switch_to_slot(slot)
1349 int slot;
1350 {
1351 pob oslot = Player.possessions[slot];
1352 pob oair = Player.possessions[O_UP_IN_AIR];
1353 pob otemp = NULL;
1354 int slotnull,airnull,num=1,trade=FALSE,put=FALSE,take=FALSE,merge=FALSE;
1355 int s2h=FALSE,a2h=FALSE;
1356
1357 /* ie, is cursed and in use */
1358 if (slot == O_UP_IN_AIR)
1359 print3("This action makes no sense!");
1360 else if (cursed(oslot)==TRUE+TRUE)
1361 print3("The object in that slot is cursed -- you can't get rid of it!");
1362 else {
1363
1364 slotnull = (oslot == NULL);
1365 airnull = (oair == NULL);
1366
1367 if (!slotnull)
1368 s2h = (Player.possessions[O_READY_HAND] ==
1369 Player.possessions[O_WEAPON_HAND]);
1370
1371 if (! airnull)
1372 a2h = (twohandedp(oair->id) &&
1373 ((slot == O_READY_HAND) || (slot == O_WEAPON_HAND)));
1374
1375
1376 /* figure out which action to take */
1377
1378 /* merge if both are same kind of object */
1379 merge = objequal(oslot,oair);
1380
1381 take = ((!merge) && (!slotnull) && airnull);
1382
1383 put = ((!merge) && slotnull && (!airnull) && slottable(oair,slot));
1384
1385 trade = ((!merge) && (!slotnull) && (!airnull) && slottable(oair,slot));
1386
1387 if (merge) merge_item(slot);
1388
1389 else if (put) {
1390
1391 /* deal with a 2-handed weapon */
1392 if (a2h) {
1393 if (Player.possessions[O_READY_HAND] == NULL)
1394 Player.possessions[O_READY_HAND] = oair;
1395 if (Player.possessions[O_WEAPON_HAND] == NULL)
1396 Player.possessions[O_WEAPON_HAND] = oair;
1397 }
1398 else Player.possessions[slot] = oair;
1399 Player.possessions[O_UP_IN_AIR] = NULL;
1400 if (item_useable(oair,slot)) {
1401 oair->used = TRUE;
1402 item_use(oair);
1403 morewait();
1404 if (oair->number > 1) pack_extra_items(oair);
1405 }
1406 Player.possessions[O_UP_IN_AIR] = NULL;
1407 }
1408
1409 else if (take) {
1410 num = get_item_number(oslot);
1411 if (num > 0) {
1412 otemp = split_item(num,oslot);
1413 dispose_lost_objects(num,oslot);
1414 Player.possessions[O_UP_IN_AIR] = otemp;
1415 }
1416 if (s2h) {
1417 if (Player.possessions[O_READY_HAND] == oslot)
1418 Player.possessions[O_READY_HAND] = NULL;
1419 if (Player.possessions[O_WEAPON_HAND] == oslot)
1420 Player.possessions[O_WEAPON_HAND] = NULL;
1421 }
1422 }
1423
1424 else if (trade) {
1425
1426 /* first remove item from slot */
1427 num = oslot->number;
1428 conform_lost_objects(oslot->number,oslot);
1429 oslot->number = num;
1430
1431 Player.possessions[O_UP_IN_AIR] = oslot;
1432
1433 Player.possessions[slot] = oair;
1434
1435 if (s2h) {
1436 if (Player.possessions[O_READY_HAND] == oslot)
1437 Player.possessions[O_READY_HAND] = NULL;
1438 if (Player.possessions[O_WEAPON_HAND] == oslot)
1439 Player.possessions[O_WEAPON_HAND] = NULL;
1440 }
1441
1442 if (a2h) {
1443 if (Player.possessions[O_READY_HAND] == NULL)
1444 Player.possessions[O_READY_HAND] = oair;
1445 if (Player.possessions[O_WEAPON_HAND] == NULL)
1446 Player.possessions[O_WEAPON_HAND] = oair;
1447 }
1448
1449 if (item_useable(oair,slot)) {
1450 oair->used = TRUE;
1451 item_use(oair);
1452 morewait();
1453 if (oair->number > 1) pack_extra_items(oair);
1454 }
1455 }
1456 }
1457 }
1458
1459
1460
1461
1462 /* merges the up-in-air items into the selected items */
1463
merge_item(slot)1464 void merge_item(slot)
1465 int slot;
1466 {
1467 Player.possessions[slot]->number +=
1468 Player.possessions[O_UP_IN_AIR]->number;
1469 Player.possessions[O_UP_IN_AIR] = NULL;
1470 }
1471
1472
1473 /* are two objects equal except for their number field? */
1474 /* returns false if either object is null */
objequal(o,p)1475 int objequal(o,p)
1476 struct object *o,*p;
1477 {
1478 if ((o == NULL) || (p == NULL)) return(FALSE);
1479 else return(
1480 (o->id == p->id) &&
1481 (o->plus == p->plus) &&
1482 (o->charge == 0) &&
1483 (p->charge == 0) &&
1484 (o->dmg == p->dmg) &&
1485 (o->hit == p->hit) &&
1486 (o->aux == p->aux) &&
1487 (o->known == p->known) &&
1488 (o->blessing == p->blessing) &&
1489 (o->usef == p->usef)
1490 );
1491
1492 }
1493
1494 /* criteria for being able to put some item in some slot */
slottable(o,slot)1495 int slottable(o,slot)
1496 pob o;
1497 int slot;
1498 {
1499 int ok = TRUE;
1500 if (o == NULL) ok = FALSE;
1501 else if (slot == O_ARMOR) {
1502 if (o->objchar != ARMOR) {
1503 print3("Only armor can go in the armor slot!");
1504 ok = FALSE;
1505 }
1506 }
1507 else if (slot == O_SHIELD) {
1508 if (o->objchar != SHIELD) {
1509 print3("Only a shield can go in the shield slot!");
1510 ok = FALSE;
1511 }
1512 }
1513 else if (slot == O_BOOTS) {
1514 if (o->objchar != BOOTS) {
1515 print3("Only boots can go in the boots slot!");
1516 ok = FALSE;
1517 }
1518 }
1519 else if (slot == O_CLOAK) {
1520 if (o->objchar != CLOAK) {
1521 print3("Only a cloak can go in the cloak slot!");
1522 ok = FALSE;
1523 }
1524 }
1525 else if (slot >= O_RING1) {
1526 if (o->objchar != RING) {
1527 print3("Only a ring can go in a ring slot!");
1528 ok = FALSE;
1529 }
1530 }
1531 return(ok);
1532 }
1533
1534
1535 /* ->;WDT HACK: this is bad factoring. I want to use this, but it's
1536 * printing SILLY stuff out. */
1537 /* whether or not an item o can be used in a slot. Assumes o can in
1538 fact be placed in the slot. */
item_useable(o,slot)1539 int item_useable(o,slot)
1540 pob o;
1541 int slot;
1542 {
1543 /* don't have to check the object in the first if since only armor
1544 can go in armor slot, cloak in cloak slot, etc */
1545
1546 if ((slot == O_ARMOR) ||
1547 (slot == O_CLOAK) ||
1548 (slot == O_SHIELD) ||
1549 (slot == O_BOOTS) ||
1550 (slot >= O_RING1))
1551 return(TRUE);
1552
1553 /* weapon is useable if it is put in weapon hand or if it is two-handed
1554 and put in either hand when the other also holds the weapon */
1555
1556 else if ((o->objchar == WEAPON) ||
1557 (o->objchar == MISSILEWEAPON)) {
1558 if (twohandedp(o->id) &&
1559 ((slot==O_READY_HAND)||(slot==O_WEAPON_HAND))) {
1560 if (Player.possessions[O_READY_HAND] ==
1561 Player.possessions[O_WEAPON_HAND]) {
1562 print1("You heft the weapon and find you must use both hands.");
1563 morewait();
1564 return(TRUE);
1565 }
1566 else {
1567 print1("This weapon is two-handed, so at the moment, ");
1568 print2("you are just lugging it around....");
1569 morewait();
1570 return(FALSE);
1571 }
1572 }
1573 else return(slot == O_WEAPON_HAND);
1574 }
1575 else return(FALSE);
1576 }
1577
1578
1579
1580
1581
1582
1583
1584
1585 /* returns FALSE if not cursed, TRUE if cursed but not used,
1586 TRUE + TRUE if cursed and used */
cursed(obj)1587 int cursed(obj)
1588 pob obj;
1589 {
1590 return((obj == NULL) ?
1591 FALSE :
1592 ((obj->blessing < 0) ?
1593 (obj->used == TRUE) + TRUE :
1594 FALSE));
1595 }
1596
1597
1598
1599
1600 /* returns true if item with id and charge is found in pack or in
1601 inventory slot. charge is used to differentiate
1602 corpses instead of aux, which is their food value. */
find_item(o,id,chargeval)1603 int find_item(o,id,chargeval)
1604 int id,chargeval;
1605 pob *o;
1606 {
1607 int i,found=FALSE;
1608 *o=NULL;
1609 for(i=1;((i<MAXITEMS)&&(! found));i++)
1610 if (Player.possessions[i] != NULL)
1611 if ((Player.possessions[i]->id == id) &&
1612 ((chargeval == -1) ||
1613 (Player.possessions[i]->charge == chargeval))) {
1614 *o = Player.possessions[i];
1615 found = TRUE;
1616 }
1617 if (! found)
1618 for(i=0;((i<Player.packptr)&&(! found));i++)
1619 if (Player.pack[i] != NULL)
1620 if ((Player.pack[i]->id == id) &&
1621 ((chargeval == -1) ||
1622 (Player.pack[i]->charge == chargeval))) {
1623 *o = Player.pack[i];
1624 found = TRUE;
1625 }
1626 return(found);
1627 }
1628
1629
1630
1631 /* returns true if item with id and charge is found in pack or in
1632 inventory slot. Destroys item. charge is used to differentiate
1633 corpses instead of aux, which is their food value. */
find_and_remove_item(id,chargeval)1634 int find_and_remove_item(id,chargeval)
1635 int id,chargeval;
1636 {
1637 int i,found=FALSE;
1638 pob o=NULL;
1639
1640 for(i=1;((i<MAXITEMS)&&(! found));i++)
1641 if (Player.possessions[i] != NULL)
1642 if ((Player.possessions[i]->id == id) &&
1643 ((chargeval == -1) ||
1644 (Player.possessions[i]->charge == chargeval))) {
1645 o = Player.possessions[i];
1646 conform_lost_objects(1, o);
1647 found = TRUE;
1648 }
1649 if (! found) for(i=0;((i<Player.packptr)&&(! found));i++)
1650 if (Player.pack[i] != NULL)
1651 if ((Player.pack[i]->id == id) &&
1652 ((chargeval == -1) ||
1653 (Player.pack[i]->charge == chargeval))) {
1654 Player.pack[i]->number--;
1655 if (Player.pack[i]->number == 0) {
1656 free((char *)Player.pack[i]);
1657 Player.pack[i] = NULL;
1658 }
1659 found = TRUE;
1660 }
1661 fixpack();
1662 return(found);
1663 }
1664
1665
1666
1667
lose_all_items()1668 void lose_all_items()
1669 {
1670 int i;
1671 print1("You notice that you are completely devoid of all possessions.");
1672 morewait();
1673 for(i=0;i<MAXITEMS;i++)
1674 if (Player.possessions[i] != NULL) {
1675 dispose_lost_objects(Player.possessions[i]->number,
1676 Player.possessions[i]);
1677 Player.possessions[i] = NULL;
1678 }
1679 for(i=0;i<MAXPACK;i++) {
1680 if (Player.pack[i] != NULL)
1681 free((char *) Player.pack[i]);
1682 Player.pack[i] = NULL;
1683 }
1684 Player.packptr = 0;
1685 calc_melee();
1686 morewait();
1687 }
1688
1689
1690 /* prevents people from wielding 3 short swords, etc. */
pack_extra_items(item)1691 void pack_extra_items(item)
1692 pob item;
1693 {
1694 pob extra=((pob) checkmalloc(sizeof(objtype)));
1695 *extra = *item;
1696 extra->number = item->number-1;
1697 extra->used = FALSE;
1698 item->number = 1;
1699 if (Player.packptr < MAXPACK) {
1700 print3("Putting extra items back in pack.");
1701 morewait();
1702 push_pack(extra);
1703 }
1704 else if (Player.possessions[O_UP_IN_AIR] == NULL) {
1705 print3("Extra copies of item are 'up in the air'");
1706 Player.possessions[O_UP_IN_AIR] = extra;
1707 }
1708 else {
1709 print3("No room for extra copies of item -- dropping them.");
1710 drop_at(Player.x,Player.y,extra);
1711 }
1712 calc_melee();
1713 }
1714
1715
1716 /* makes sure Player.pack is OK, (used after sale from pack) */
fixpack()1717 void fixpack()
1718 {
1719 pob tpack[MAXPACK];
1720 int i,tctr=0;
1721 for(i=0;i<MAXPACK;i++) tpack[i] = NULL;
1722 for(i=0;i<MAXPACK;i++)
1723 if (Player.pack[i]!=NULL)
1724 tpack[tctr++] = Player.pack[i];
1725 for(i=0;i<MAXPACK;i++)
1726 Player.pack[i]=tpack[i];
1727 Player.packptr = tctr;
1728 }
1729
1730
1731 /* show slots, with appropriate additional displays if two-handed weapons */
1732 /* are involved */
show_inventory_slot(slotnum,topline)1733 void show_inventory_slot(slotnum,topline)
1734 int slotnum;
1735 int topline;
1736 {
1737 if (!topline)
1738 if (Player.possessions[O_READY_HAND] == Player.possessions[O_WEAPON_HAND] &&
1739 (slotnum == O_READY_HAND || slotnum == O_WEAPON_HAND))
1740 {
1741 display_inventory_slot(O_READY_HAND, topline);
1742 display_inventory_slot(O_WEAPON_HAND, topline);
1743 }
1744 else if (slotnum == O_UP_IN_AIR && Player.possessions[O_UP_IN_AIR] &&
1745 twohandedp(Player.possessions[O_UP_IN_AIR]->id))
1746 {
1747 display_inventory_slot(O_READY_HAND, topline);
1748 display_inventory_slot(O_WEAPON_HAND, topline);
1749 display_inventory_slot(slotnum, topline);
1750 }
1751 else
1752 display_inventory_slot(slotnum, topline);
1753 else
1754 display_inventory_slot(slotnum, topline);
1755 }
1756