This is pickup.c in view mode; [Download] [Up]
/* SCCS Id: @(#)pickup.c 3.0 88/07/12 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ /* * Contains code for picking objects up, and container use. */ #include "hack.h" #ifndef OVERLAY static int FDECL(in_container,(struct obj *)); static int FDECL(ck_container,(struct obj *)); static int FDECL(ck_bag,(struct obj *)); static int FDECL(out_container,(struct obj *)); #else int FDECL(in_container,(struct obj *)); int FDECL(ck_container,(struct obj *)); int FDECL(ck_bag,(struct obj *)); int FDECL(out_container,(struct obj *)); #endif void FDECL(explode_bag,(struct obj *)); #ifdef OVLB static const char nearloadmsg[] = "have a little trouble lifting"; void pickup(all) int all; { register struct gold *gold = g_at(u.ux, u.uy); register struct obj *obj, *obj2; register int wt; char buf[BUFSZ]; register char *ip; register char sym; register int oletct = 0, iletct = 0; boolean all_of_a_type = FALSE, selective = FALSE; char olets[20], ilets[20]; struct obj dummygold; dummygold.ox = u.ux; dummygold.oy = u.uy; dummygold.olet = GOLD_SYM; dummygold.nobj = fobj; dummygold.nexthere = level.objects[u.ux][u.uy]; dummygold.cobj = 0; if(Levitation) { if ((multi && !flags.run) || (all && !flags.pickup)) read_engr_at(u.ux,u.uy); return; } /* multi && !flags.run means they are in the middle of some other * action, or possibly paralyzed, sleeping, etc.... and they just * teleported onto the object. They shouldn't pick it up. */ if ((multi && !flags.run) || (all && !flags.pickup)) { int ct = 0; for (obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere) if(!obj->cobj && obj != uchain) ct++; /* Stop on a zorkmid */ if (gold) ct++; /* If there are objects here, take a look. */ if (ct) { if (flags.run) nomul(0); nscr(); if (ct < 5) (void) dolook(); else { read_engr_at(u.ux,u.uy); pline("There are several objects here."); } } else read_engr_at(u.ux,u.uy); return; } /* check for more than one object */ if(!all) { register int ct = 0; if (gold) ct++; for(obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere) if(!obj->cobj) ct++; if(ct < 2) all++; else pline("There are several objects here."); } /* added by GAN 10/24/86 to allow selective picking up */ if(!all) { register struct obj *otmp = level.objects[u.ux][u.uy]; ilets[iletct] = 0; if(gold) { ilets[iletct++] = GOLD_SYM; ilets[iletct] = 0; } while(otmp) { if(!index(ilets, otmp->olet) && !otmp->cobj) { ilets[iletct++] = otmp->olet; ilets[iletct] = 0; } otmp = otmp->nexthere; } if(iletct == 1) Strcpy(buf,ilets); else { ilets[iletct++] = ' '; ilets[iletct++] = 'a'; ilets[iletct++] = 'A'; ilets[iletct] = 0; pline("What kinds of thing do you want to pick up? [%s] ", ilets); getlin(buf); if(buf[0] == '\033') { clrlin(); return; } else if(!buf[0]) selective = TRUE; } ip = buf; olets[0] = 0; while(sym = *ip++){ /* new A function (selective all) added by * GAN 01/09/87 */ if(sym == ' ') continue; if(sym == 'A') selective = TRUE; else if(sym == 'a') all_of_a_type = TRUE; else if(index(ilets, sym)){ if(!index(olets, sym)){ olets[oletct++] = sym; olets[oletct] = 0; } } else pline("There are no %c's here.", sym); } } if(all_of_a_type && !olets[0]) all = TRUE; for(obj = (gold ? &dummygold : level.objects[u.ux][u.uy]); obj; obj = obj2) { obj2 = obj->nexthere; /* perhaps obj will be picked up */ if(!obj->cobj) { if(flags.run) nomul(0); if(!all) { char c; if(!selective && !index(olets,obj->olet)) continue; if (!all_of_a_type) { if (obj == &dummygold) pline("Pick up %ld gold piece%s? ", gold->amount, plur(gold->amount)); else pline("Pick up %s? ", doname(obj)); if((c = ynaq()) == 'q') return; if(c == 'n') continue; if(c == 'a') { all_of_a_type = TRUE; if (selective) { selective = FALSE; olets[0] = obj->olet; olets[1] = 0; /* oletct = 1; */ } } } } if(obj == &dummygold) { int iw = inv_weight(); long gold_capacity; #ifndef lint /* long/int conversion */ iw -= (int)((u.ugold + 500)/1000); #endif gold_capacity = ((-iw) * 1000L) - 500 + 999 - u.ugold; if (gold_capacity <= 0L) { pline("There %s %ld gold piece%s here, but you cannot carry any more.", (gold->amount == 1) ? "is" : "are", gold->amount, plur(gold->amount)); continue; } if (gold_capacity >= gold->amount) { u.ugold += gold->amount; if (inv_weight() > -5) You(nearloadmsg); pline("%ld gold piece%s.", gold->amount, plur(gold->amount)); freegold(gold); if(Invisible) newsym(u.ux,u.uy); } else { You("can only carry %s of the %ld gold pieces lying here.", gold_capacity == 1L ? "one" : "some", gold->amount); You(nearloadmsg); pline("%ld gold piece%s.", gold_capacity, plur(gold_capacity)); u.ugold += gold_capacity; gold->amount -= gold_capacity; } flags.botl = 1; if(flags.run) nomul(0); continue; } if((obj->otyp == CORPSE && obj->corpsenm == PM_COCKATRICE) && !uarmg #ifdef POLYSELF && !resists_ston(uasmon) #endif ) { pline("Touching the dead cockatrice is a fatal mistake."); You("turn to stone."); You("die..."); killer_format = KILLED_BY_AN; killer = "cockatrice corpse"; done(STONING); } if(obj->otyp == SCR_SCARE_MONSTER){ if(obj->blessed) obj->blessed = 0; else if(!obj->spe && !obj->cursed) obj->spe = 1; else { pline("The scroll%s turn%s to dust as you pick %s up.", plur((long)obj->quan), (obj->quan==1) ? "s":"", (obj->quan==1) ? "it" : "them"); if(!(objects[SCR_SCARE_MONSTER].oc_name_known) && !(objects[SCR_SCARE_MONSTER].oc_uname)) docall(obj); useupf(obj); continue; } } /* do not pick up uchain */ if(obj == uchain) continue; wt = inv_weight() + (int)obj->owt; if (obj->otyp == LOADSTONE) goto lift_some; /* pick it up even if too heavy */ #ifdef POLYSELF if (obj->otyp == BOULDER && throws_rocks(uasmon)) { wt = inv_weight(); goto lift_some; } #endif if(wt > 0) { if(obj->quan > 1) { /* see how many we can lift */ int savequan = obj->quan; int iw = inv_weight(); int qq; for(qq = 1; qq < savequan; qq++){ obj->quan = qq; if(iw + weight(obj) > 0) break; } obj->quan = savequan; qq--; /* we can carry qq of them */ if(qq) { register struct obj *obj3; You("can only carry %s of the %s lying here.", (qq == 1) ? "one" : "some", doname(obj)); obj3 = splitobj(obj, qq); if(obj3->otyp == SCR_SCARE_MONSTER) if(obj3->spe) obj->spe = 0; goto lift_some; } } pline("There %s %s here, but %s.", (obj->quan == 1) ? "is" : "are", doname(obj), !invent ? "it is too heavy for you to lift" : "you cannot carry any more"); if(obj->otyp == SCR_SCARE_MONSTER) if(obj->spe) obj->spe = 0; break; } lift_some: if(inv_cnt() >= 52) { Your("knapsack cannot accommodate any more items."); if(obj->otyp == SCR_SCARE_MONSTER) if(obj->spe) obj->spe = 0; break; } { int pickquan = obj->quan; int mergquan; obj = pick_obj(obj); if(wt > -5) You(nearloadmsg); if(!Blind) obj->dknown = 1; mergquan = obj->quan; obj->quan = pickquan; /* to fool prinv() */ if(uwep && uwep == obj) mrg_to_wielded = TRUE; prinv(obj); mrg_to_wielded = FALSE; obj->quan = mergquan; } } } } struct obj * pick_obj(otmp) register struct obj *otmp; { if (otmp != uball) /* don't charge for this - kd, 1/17/90 */ addtobill(otmp, TRUE); /* sets obj->unpaid if necessary */ freeobj(otmp); if(Invisible) newsym(u.ux,u.uy); return(addinv(otmp)); /* might merge it with other objects */ } int doloot() { /* loot a container on the floor. */ register struct obj *cobj; register int c; if (Levitation) { You("cannot reach the floor."); return(0); } for(cobj = level.objects[u.ux][u.uy]; cobj; cobj = cobj->nexthere) { if(Is_container(cobj)) { pline("There is %s here, loot it? ", doname(cobj)); c = ynq(); if(c == 'q') return 0; if(c == 'n') continue; if(cobj->olocked) { pline("Hmmm, it seems to be locked."); continue; } if(cobj->otyp == BAG_OF_TRICKS) { You("carefully open the bag..."); pline("It develops a huge set of teeth and bites you!"); losehp(rnd(10), "carnivorous bag", KILLED_BY_AN); makeknown(BAG_OF_TRICKS); continue; } You("carefully open the %s...", xname(cobj)); if(cobj->otrapped) chest_trap(cobj, FINGER); if(multi < 0) return 0; /* a paralysis trap */ use_container(cobj, 0); } } return 0; } static struct obj *current_container; /* a local variable of use_container, to be used by its local procedures in/ck_container */ #define Icebox (current_container->otyp == ICE_BOX) int baggone; /* used in askchain so bag isn't used after explosion */ #endif /* OVLB */ #ifdef OVL0 void inc_cwt(cobj, obj) register struct obj *cobj, *obj; { if (cobj->otyp == BAG_OF_HOLDING) cobj->owt += (cobj->cursed?(obj->owt*2):(obj->owt/(cobj->blessed?4:2)) + 1); else cobj->owt += obj->owt; } #endif /* OVL0 */ #ifdef OVLB #ifndef OVERLAY static #endif int in_container(obj) register struct obj *obj; { char buf[BUFSZ]; if(obj == uball || obj == uchain) { You("must be kidding."); return(0); } if(obj == current_container) { pline("That would be an interesting topological exercise."); return(0); } if(obj->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)) { You("cannot %s something you are wearing.", Icebox ? "refrigerate" : "stash"); return(0); } if((obj->otyp == LOADSTONE) && obj->cursed) { obj->bknown = 1; pline("The stone%s won't leave your person.", plur((long)obj->quan)); return(0); } /* Prohibit Amulets in containers; if you allow it, monsters can't * steal them. It also becomes a pain to check to see if someone * has the Amulet. */ if(obj->otyp == AMULET_OF_YENDOR && !obj->spe) { pline("The Amulet of Yendor cannot be confined in such trappings."); return(0); } /* no nested containers - they do not save/restore properly. */ /* magic bag -> magic bag will self destruct later on. */ if(Is_container(obj) && Is_container(current_container) && (!Is_mbag(obj) || !Is_mbag(current_container))) { pline("The %s won't go in.", xname(obj)); return(1); /* be careful! */ } if(obj == uwep) { if(welded(obj)) { weldmsg(obj, FALSE); return(0); } setuwep((struct obj *) 0); if (uwep) return(0); /* unwielded, died, rewielded */ } #ifdef WALKIES if(obj->otyp == LEASH && obj->leashmon != 0) { pline("The %s is attached to your pet.", xname(obj)); return(0); } #endif inc_cwt(current_container, obj); freeinv(obj); obj->cobj = current_container; obj->nobj = fcobj; fcobj = obj; Strcpy(buf, xname(obj->cobj)); You("put %s into the %s.", doname(obj), buf); if(Icebox) obj->age = monstermoves - obj->age; /* actual age */ else if(Is_mbag(obj->cobj) && (Is_mbag(obj) || (obj->otyp == WAN_CANCELLATION && (obj->spe > 0)) )) { explode_bag(obj); You("are blasted by a magical explosion!"); losehp(d(6,6),"magical explosion", KILLED_BY_AN); baggone = 1; } return(1); } #ifndef OVERLAY static #endif int ck_container(obj) register struct obj *obj; { return(obj->cobj == current_container); } /* ck_bag() needs a formal argument to make the overlay/prototype mechanism * work right */ /*ARGSUSED*/ #ifndef OVERLAY static #endif int ck_bag(obj) struct obj *obj; { return(!baggone); } #ifndef OVERLAY static #endif int out_container(obj) register struct obj *obj; { register struct obj *otmp; register boolean near_capacity = (inv_weight() > -5); if(inv_cnt() >= 52) { pline("You have no room to hold anything else."); return(0); } if(obj->otyp != LOADSTONE && inv_weight() + (int)obj->owt > 0) { char buf[BUFSZ]; Strcpy(buf, doname(obj)); pline("There %s %s in the %s, but %s.", obj->quan==1 ? "is" : "are", buf, xname(current_container), invent ? "you cannot carry any more" : "it is too heavy for you to carry"); /* "too heavy for you to lift" is not right if you're carrying the container... */ return(0); } if(obj == fcobj) fcobj = fcobj->nobj; else { for(otmp = fcobj; otmp->nobj != obj; otmp = otmp->nobj) if(!otmp->nobj) panic("out_container"); otmp->nobj = obj->nobj; } dec_cwt(current_container, obj); obj->cobj = (struct obj *) 0; if (Icebox) obj->age = monstermoves - obj->age; /* simulated point of time */ (void) addinv(obj); if (near_capacity) You("have a little trouble removing"); prinv(obj); return 0; } void get_all_from_box() { register struct obj *otmp, *cobj, *ootmp, *nxobj; for(otmp = invent; otmp; otmp = otmp->nobj) { cobj = otmp; if(Is_container(otmp)) { current_container = otmp; for(ootmp=fcobj,nxobj=(fcobj ? fcobj->nobj : 0); ootmp; ootmp=nxobj,nxobj=(ootmp ? ootmp->nobj : 0) ) if(ootmp->cobj == cobj) (void)out_container(ootmp); } } return; } /* for getobj: 0: allow cnt; #: allow all types; %: expect food */ static const char frozen_food[] = { '0', '#', FOOD_SYM, 0 }; void use_container(obj, held) register struct obj *obj; register int held; { register int cnt = 0; register struct obj *otmp; register struct obj *backobj; current_container = obj; /* for use by in/out_container */ if(current_container->olocked) { pline("The %s seems to be locked.", xname(current_container)); return; } for(otmp = fcobj, backobj = (struct obj *) 0; otmp; backobj = otmp, otmp = otmp->nobj) if(otmp->cobj == obj) if(Is_mbag(obj) && obj->cursed && !rn2(13)) { if (otmp->known) pline("The %s to have vanished!", aobjnam(otmp,"seem")); else You("%s %s disappear.", Blind ? "notice" : "see", doname(otmp)); if(!backobj) { fcobj = otmp->nobj; dec_cwt(current_container, otmp); obfree(otmp, (struct obj *) 0); otmp = fcobj; } else { backobj->nobj = otmp->nobj; dec_cwt(current_container, otmp); obfree(otmp, (struct obj *) 0); otmp = backobj->nobj; } if (!otmp) break; if(otmp->cobj == obj) cnt++; } else cnt++; if(!cnt) pline("%s %s is empty.", (held) ? "Your" : "The", xname(obj)); else if (inv_cnt() < 52) { pline("Do you want to take something out of the %s? ", xname(obj)); if(yn() != 'n') if(askchain(fcobj, FALSE, NULL, 0, out_container, ck_container, 0, "nodot")) return; } if(!invent) return; pline("Do you wish to put something in? "); if(yn() != 'y') return; if (Icebox && current_container->dknown) { otmp = getobj(frozen_food, "put in"); if(!otmp || !in_container(otmp)) flags.move = multi = 0; } else { baggone = 0; /* might be set by in_container */ if(askchain(invent, TRUE, NULL, 0, in_container, ck_bag, 0, "nodot")) return; } return; } void delete_contents(obj) register struct obj *obj; { register struct obj *otmp, *notmp; while (fcobj && fcobj->cobj == obj) { otmp = fcobj; fcobj = fcobj->nobj; obfree(otmp,(struct obj *)0); } if (fcobj) { otmp = fcobj; while(otmp->nobj) if (otmp->nobj->cobj == obj) { notmp = otmp->nobj; otmp->nobj = notmp->nobj; obfree(notmp,(struct obj *)0); } else otmp = otmp->nobj; } } void explode_bag(obj) struct obj *obj; { struct obj *otmp, *cobj; cobj = obj->cobj; delete_contents(cobj); for (otmp = invent; otmp; otmp = otmp->nobj) if (otmp == cobj) break; if (otmp) { You("see your %s blow apart!", xname(otmp)); useup(otmp); /*return(0);*/ } else panic("explode_bag: bag not in invent."); } void dec_cwt(cobj, obj) register struct obj *cobj, *obj; { if (Is_mbag(cobj)) cobj->owt -= (cobj->cursed?(obj->owt*2):(obj->owt/(cobj->blessed?4:2)) + 1); else cobj->owt -= obj->owt; if(cobj->owt < objects[cobj->otyp].oc_weight) cobj->owt = objects[cobj->otyp].oc_weight; } #endif /* OVLB */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.