# 2.11BSD#431 - /usr/src/games/hack/hack.shk.c

##### Functions

    addtobill         X
    bp_to_obj         X
    doinvbill         X
    dopay             X
    follower          X
    inshop            X
    obfree            X
    online            X
    paybill           X
    replshk           X
    shk_move          X
    shkcatch          X
    shkdead           X
    shkname           X
    shopdig           X
    splitbill         X
    subfrombill       X

##### Variables

    billobjs          X
    shtypes           X

##### Macros

    ANGRY             X
    ESHK              X
    GDIST             X
    NOTANGRY          X
    min               X

       1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
       2: /* hack.shk.c - version 1.0.3 */
       3:
       4: #include "hack.h"
       5: #ifdef QUEST
       6: int shlevel = 0;
       7: struct monst *shopkeeper = 0;
       8: struct obj *billobjs = 0;
       9: obfree(obj,merge) register struct obj *obj, *merge; {
      10:     free((char *) obj);
      11: }
      12: inshop(){ return(0); }
      13: addtobill(){}
      14: subfrombill(){}
      15: splitbill(){}
      16: dopay(){ return(0); }
      17: paybill(){}
      18: doinvbill(){ return(0); }
      19: shkdead(){}
      20: shkcatch(){ return(0); }
      21: shk_move(){ return(0); }
      22: replshk(mtmp,mtmp2) struct monst *mtmp, *mtmp2; {}
      23: char *shkname(){ return(""); }
      24:
      25: #else QUEST
      26: #include    "hack.mfndpos.h"
      27: #include    "def.mkroom.h"
      28: #include    "def.eshk.h"
      29:
      30: #define ESHK(mon)   ((struct eshk *)(&(mon->mextra[0])))
      31: #define NOTANGRY(mon)   mon->mpeaceful
      32: #define ANGRY(mon)  !NOTANGRY(mon)
      33:
      34: extern char plname[], *xname();
      35: extern struct obj *o_on(), *bp_to_obj();
      36:
      37: /* Descriptor of current shopkeeper. Note that the bill need not be
      38:    per-shopkeeper, since it is valid only when in a shop. */
      39: static struct monst *shopkeeper = 0;
      40: static struct bill_x *bill;
      41: static int shlevel = 0; /* level of this shopkeeper */
      42:        struct obj *billobjs;    /* objects on bill with bp->useup */
      43:                 /* only accessed here and by save & restore */
      44: static long int total;      /* filled by addupbill() */
      45: static long int followmsg;  /* last time of follow message */
      46:
      47: /*
      48: 	invariants: obj->unpaid iff onbill(obj) [unless bp->useup]
      49: 		obj->quan <= bp->bquan
      50:  */
      51:
      52:
      53: char shtypes[] = {  /* 8 shoptypes: 7 specialized, 1 mixed */
      54:     RING_SYM, WAND_SYM, WEAPON_SYM, FOOD_SYM, SCROLL_SYM,
      55:     POTION_SYM, ARMOR_SYM, 0
      56: };
      57:
      58: static char *shopnam[] = {
      59:     "engagement ring", "walking cane", "antique weapon",
      60:     "delicatessen", "second hand book", "liquor",
      61:     "used armor", "assorted antiques"
      62: };
      63:
      64: char *
      65: shkname(mtmp)               /* called in do_name.c */
      66: register struct monst *mtmp;
      67: {
      68:     return(ESHK(mtmp)->shknam);
      69: }
      70:
      71: shkdead(mtmp)               /* called in mon.c */
      72: register struct monst *mtmp;
      73: {
      74:     register struct eshk *eshk = ESHK(mtmp);
      75:
      76:     if(eshk->shoplevel == dlevel)
      77:         rooms[eshk->shoproom].rtype = 0;
      78:     if(mtmp == shopkeeper) {
      79:         setpaid();
      80:         shopkeeper = 0;
      81:         bill = (struct bill_x *) -1000; /* dump core when referenced */
      82:     }
      83: }
      84:
      85: replshk(mtmp,mtmp2)
      86: register struct monst *mtmp, *mtmp2;
      87: {
      88:     if(mtmp == shopkeeper) {
      89:         shopkeeper = mtmp2;
      90:         bill = &(ESHK(shopkeeper)->bill[0]);
      91:     }
      92: }
      93:
      94: static
      95: setpaid(){  /* caller has checked that shopkeeper exists */
      96:         /* either we paid or left the shop or he just died */
      97: register struct obj *obj;
      98: register struct monst *mtmp;
      99:     for(obj = invent; obj; obj = obj->nobj)
     100:         obj->unpaid = 0;
     101:     for(obj = fobj; obj; obj = obj->nobj)
     102:         obj->unpaid = 0;
     103:     for(obj = fcobj; obj; obj = obj->nobj)
     104:         obj->unpaid = 0;
     105:     for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
     106:         for(obj = mtmp->minvent; obj; obj = obj->nobj)
     107:             obj->unpaid = 0;
     108:     for(mtmp = fallen_down; mtmp; mtmp = mtmp->nmon)
     109:         for(obj = mtmp->minvent; obj; obj = obj->nobj)
     110:             obj->unpaid = 0;
     111:     while(obj = billobjs){
     112:         billobjs = obj->nobj;
     113:         free((char *) obj);
     114:     }
     115:     ESHK(shopkeeper)->billct = 0;
     116: }
     117:
     118: static
     119: addupbill(){    /* delivers result in total */
     120:         /* caller has checked that shopkeeper exists */
     121: register ct = ESHK(shopkeeper)->billct;
     122: register struct bill_x *bp = bill;
     123:     total = 0;
     124:     while(ct--){
     125:         total += bp->price * bp->bquan;
     126:         bp++;
     127:     }
     128: }
     129:
     130: inshop(){
     131: register roomno = inroom(u.ux,u.uy);
     132:
     133:     /* Did we just leave a shop? */
     134:     if(u.uinshop &&
     135:         (u.uinshop != roomno + 1 || shlevel != dlevel || !shopkeeper)) {
     136:         u.uinshop = 0;
     137:         if(shopkeeper) {
     138:             if(ESHK(shopkeeper)->billct) {
     139:             pline("Somehow you escaped the shop without paying!");
     140:             addupbill();
     141:             pline("You stole for a total worth of %ld zorkmids.",
     142:                 total);
     143:             ESHK(shopkeeper)->robbed += total;
     144:             setpaid();
     145:             if((rooms[ESHK(shopkeeper)->shoproom].rtype == GENERAL)
     146:                 == (rn2(3) == 0))
     147:                 ESHK(shopkeeper)->following = 1;
     148:             }
     149:             shopkeeper = 0;
     150:             shlevel = 0;
     151:         }
     152:     }
     153:
     154:     /* Did we just enter a zoo of some kind? */
     155:     if(roomno >= 0) {
     156:         register int rt = rooms[roomno].rtype;
     157:         register struct monst *mtmp;
     158:         if(rt == ZOO) {
     159:             pline("Welcome to David's treasure zoo!");
     160:         } else
     161:         if(rt == SWAMP) {
     162:             pline("It looks rather muddy down here.");
     163:         } else
     164:         if(rt == MORGUE) {
     165:             if(midnight())
     166:                 pline("Go away! Go away!");
     167:             else
     168:                 pline("You get an uncanny feeling ...");
     169:         } else
     170:             rt = 0;
     171:         if(rt != 0) {
     172:             rooms[roomno].rtype = 0;
     173:             for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
     174:                 if(rt != ZOO || !rn2(3))
     175:                     mtmp->msleep = 0;
     176:         }
     177:     }
     178:
     179:     /* Did we just enter a shop? */
     180:     if(roomno >= 0 && rooms[roomno].rtype >= 8) {
     181:         if(shlevel != dlevel || !shopkeeper
     182:                  || ESHK(shopkeeper)->shoproom != roomno)
     183:         findshk(roomno);
     184:         if(!shopkeeper) {
     185:         rooms[roomno].rtype = 0;
     186:         u.uinshop = 0;
     187:         } else if(inroom(shopkeeper->mx, shopkeeper->my) != roomno) {
     188:         u.uinshop = 0;
     189:         } else if(!u.uinshop){
     190:         if(!ESHK(shopkeeper)->visitct ||
     191:             strncmp(ESHK(shopkeeper)->customer, plname, PL_NSIZ)){
     192:
     193:             /* He seems to be new here */
     194:             ESHK(shopkeeper)->visitct = 0;
     195:             ESHK(shopkeeper)->following = 0;
     196:             (void) strncpy(ESHK(shopkeeper)->customer,plname,PL_NSIZ);
     197:             NOTANGRY(shopkeeper) = 1;
     198:         }
     199:         if(!ESHK(shopkeeper)->following) {
     200:             boolean box, pick;
     201:
     202:             pline("Hello %s! Welcome%s to %s's %s shop!",
     203:             plname,
     204:             ESHK(shopkeeper)->visitct++ ? " again" : "",
     205:             shkname(shopkeeper),
     206:             shopnam[rooms[ESHK(shopkeeper)->shoproom].rtype - 8] );
     207:             box = carrying(ICE_BOX);
     208:             pick = carrying(PICK_AXE);
     209:             if(box || pick) {
     210:             if(dochug(shopkeeper)) {
     211:                 u.uinshop = 0;  /* he died moving */
     212:                 return(0);
     213:             }
     214:             pline("Will you please leave your %s outside?",
     215:                 (box && pick) ? "box and pick-axe" :
     216:                 box ? "box" : "pick-axe");
     217:             }
     218:         }
     219:         u.uinshop = roomno + 1;
     220:         }
     221:     }
     222:     return(u.uinshop);
     223: }
     224:
     225: static
     226: findshk(roomno)
     227: register roomno;
     228: {
     229: register struct monst *mtmp;
     230:     for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
     231:         if(mtmp->isshk && ESHK(mtmp)->shoproom == roomno
     232:                && ESHK(mtmp)->shoplevel == dlevel) {
     233:         shopkeeper = mtmp;
     234:         bill = &(ESHK(shopkeeper)->bill[0]);
     235:         shlevel = dlevel;
     236:         if(ANGRY(shopkeeper) &&
     237:            strncmp(ESHK(shopkeeper)->customer,plname,PL_NSIZ))
     238:             NOTANGRY(shopkeeper) = 1;
     239:         /* billobjs = 0; -- this is wrong if we save in a shop */
     240:         /* (and it is harmless to have too many things in billobjs) */
     241:         return;
     242:     }
     243:     shopkeeper = 0;
     244:     shlevel = 0;
     245:     bill = (struct bill_x *) -1000; /* dump core when referenced */
     246: }
     247:
     248: static struct bill_x *
     249: onbill(obj) register struct obj *obj; {
     250: register struct bill_x *bp;
     251:     if(!shopkeeper) return(0);
     252:     for(bp = bill; bp < &bill[ESHK(shopkeeper)->billct]; bp++)
     253:         if(bp->bo_id == obj->o_id) {
     254:             if(!obj->unpaid) pline("onbill: paid obj on bill?");
     255:             return(bp);
     256:         }
     257:     if(obj->unpaid) pline("onbill: unpaid obj not on bill?");
     258:     return(0);
     259: }
     260:
     261: /* called with two args on merge */
     262: obfree(obj,merge) register struct obj *obj, *merge; {
     263: register struct bill_x *bp = onbill(obj);
     264: register struct bill_x *bpm;
     265:     if(bp) {
     266:         if(!merge){
     267:             bp->useup = 1;
     268:             obj->unpaid = 0;    /* only for doinvbill */
     269:             obj->nobj = billobjs;
     270:             billobjs = obj;
     271:             return;
     272:         }
     273:         bpm = onbill(merge);
     274:         if(!bpm){
     275:             /* this used to be a rename */
     276:             impossible("obfree: not on bill??");
     277:             return;
     278:         } else {
     279:             /* this was a merger */
     280:             bpm->bquan += bp->bquan;
     281:             ESHK(shopkeeper)->billct--;
     282:             *bp = bill[ESHK(shopkeeper)->billct];
     283:         }
     284:     }
     285:     free((char *) obj);
     286: }
     287:
     288: static
     289: pay(tmp,shkp)
     290: long tmp;
     291: register struct monst *shkp;
     292: {
     293:     long robbed = ESHK(shkp)->robbed;
     294:
     295:     u.ugold -= tmp;
     296:     shkp->mgold += tmp;
     297:     flags.botl = 1;
     298:     if(robbed) {
     299:         robbed -= tmp;
     300:         if(robbed < 0) robbed = 0;
     301:         ESHK(shkp)->robbed = robbed;
     302:     }
     303: }
     304:
     305: dopay(){
     306: long ltmp;
     307: register struct bill_x *bp;
     308: register struct monst *shkp;
     309: int pass, tmp;
     310:
     311:     multi = 0;
     312:     (void) inshop();
     313:     for(shkp = fmon; shkp; shkp = shkp->nmon)
     314:         if(shkp->isshk && dist(shkp->mx,shkp->my) < 3)
     315:             break;
     316:     if(!shkp && u.uinshop &&
     317:        inroom(shopkeeper->mx,shopkeeper->my) == ESHK(shopkeeper)->shoproom)
     318:         shkp = shopkeeper;
     319:
     320:     if(!shkp) {
     321:         pline("There is nobody here to receive your payment.");
     322:         return(0);
     323:     }
     324:     ltmp = ESHK(shkp)->robbed;
     325:     if(shkp != shopkeeper && NOTANGRY(shkp)) {
     326:         if(!ltmp) {
     327:             pline("You do not owe %s anything.", monnam(shkp));
     328:         } else
     329:         if(!u.ugold) {
     330:             pline("You have no money.");
     331:         } else {
     332:             long ugold = u.ugold;
     333:
     334:             if(u.ugold > ltmp) {
     335:             pline("You give %s the %ld gold pieces he asked for.",
     336:                 monnam(shkp), ltmp);
     337:             pay(ltmp, shkp);
     338:             } else {
     339:             pline("You give %s all your gold.", monnam(shkp));
     340:             pay(u.ugold, shkp);
     341:             }
     342:             if(ugold < ltmp/2) {
     343:             pline("Unfortunately, he doesn't look satisfied.");
     344:             } else {
     345:             ESHK(shkp)->robbed = 0;
     346:             ESHK(shkp)->following = 0;
     347:             if(ESHK(shkp)->shoplevel != dlevel) {
     348:             /* For convenience's sake, let him disappear */
     349:                 shkp->minvent = 0;      /* %% */
     350:                 shkp->mgold = 0;
     351:                 mondead(shkp);
     352:             }
     353:             }
     354:         }
     355:         return(1);
     356:     }
     357:
     358:     if(!ESHK(shkp)->billct){
     359:         pline("You do not owe %s anything.", monnam(shkp));
     360:         if(!u.ugold){
     361:             pline("Moreover, you have no money.");
     362:             return(1);
     363:         }
     364:         if(ESHK(shkp)->robbed){
     365: #define min(a,b)    ((a<b)?a:b)
     366:             pline("But since his shop has been robbed recently,");
     367:             pline("you %srepay %s's expenses.",
     368:               (u.ugold < ESHK(shkp)->robbed) ? "partially " : "",
     369:               monnam(shkp));
     370:             pay(min(u.ugold, ESHK(shkp)->robbed), shkp);
     371:             ESHK(shkp)->robbed = 0;
     372:             return(1);
     373:         }
     374:         if(ANGRY(shkp)){
     375:             pline("But in order to appease %s,",
     376:                 amonnam(shkp, "angry"));
     377:             if(u.ugold >= 1000){
     378:                 ltmp = 1000;
     379:                 pline(" you give him 1000 gold pieces.");
     380:             } else {
     381:                 ltmp = u.ugold;
     382:                 pline(" you give him all your money.");
     383:             }
     384:             pay(ltmp, shkp);
     385:             if(strncmp(ESHK(shkp)->customer, plname, PL_NSIZ)
     386:                || rn2(3)){
     387:                 pline("%s calms down.", Monnam(shkp));
     388:                 NOTANGRY(shkp) = 1;
     389:             } else  pline("%s is as angry as ever.",
     390:                     Monnam(shkp));
     391:         }
     392:         return(1);
     393:     }
     394:     if(shkp != shopkeeper) {
     395:         impossible("dopay: not to shopkeeper?");
     396:         if(shopkeeper) setpaid();
     397:         return(0);
     398:     }
     399:     for(pass = 0; pass <= 1; pass++) {
     400:         tmp = 0;
     401:         while(tmp < ESHK(shopkeeper)->billct) {
     402:             bp = &bill[tmp];
     403:             if(!pass && !bp->useup) {
     404:                 tmp++;
     405:                 continue;
     406:             }
     407:             if(!dopayobj(bp)) return(1);
     408:             bill[tmp] = bill[--ESHK(shopkeeper)->billct];
     409:         }
     410:     }
     411:     pline("Thank you for shopping in %s's %s store!",
     412:         shkname(shopkeeper),
     413:         shopnam[rooms[ESHK(shopkeeper)->shoproom].rtype - 8]);
     414:     NOTANGRY(shopkeeper) = 1;
     415:     return(1);
     416: }
     417:
     418: /* return 1 if paid successfully */
     419: /*        0 if not enough money */
     420: /*       -1 if object could not be found (but was paid) */
     421: static
     422: dopayobj(bp) register struct bill_x *bp; {
     423: register struct obj *obj;
     424: long ltmp;
     425:
     426:     /* find the object on one of the lists */
     427:     obj = bp_to_obj(bp);
     428:
     429:     if(!obj) {
     430:         impossible("Shopkeeper administration out of order.");
     431:         setpaid();  /* be nice to the player */
     432:         return(0);
     433:     }
     434:
     435:     if(!obj->unpaid && !bp->useup){
     436:         impossible("Paid object on bill??");
     437:         return(1);
     438:     }
     439:     obj->unpaid = 0;
     440:     ltmp = bp->price * bp->bquan;
     441:     if(ANGRY(shopkeeper)) ltmp += ltmp/3;
     442:     if(u.ugold < ltmp){
     443:         pline("You don't have gold enough to pay %s.",
     444:             doname(obj));
     445:         obj->unpaid = 1;
     446:         return(0);
     447:     }
     448:     pay(ltmp, shopkeeper);
     449:     pline("You bought %s for %ld gold piece%s.",
     450:         doname(obj), ltmp, plur(ltmp));
     451:     if(bp->useup) {
     452:         register struct obj *otmp = billobjs;
     453:         if(obj == billobjs)
     454:             billobjs = obj->nobj;
     455:         else {
     456:             while(otmp && otmp->nobj != obj) otmp = otmp->nobj;
     457:             if(otmp) otmp->nobj = obj->nobj;
     458:             else pline("Error in shopkeeper administration.");
     459:         }
     460:         free((char *) obj);
     461:     }
     462:     return(1);
     463: }
     464:
     465: /* routine called after dying (or quitting) with nonempty bill */
     466: paybill(){
     467:     if(shlevel == dlevel && shopkeeper && ESHK(shopkeeper)->billct){
     468:         addupbill();
     469:         if(total > u.ugold){
     470:             shopkeeper->mgold += u.ugold;
     471:             u.ugold = 0;
     472:         pline("%s comes and takes all your possessions.",
     473:             Monnam(shopkeeper));
     474:         } else {
     475:             u.ugold -= total;
     476:             shopkeeper->mgold += total;
     477:     pline("%s comes and takes the %ld zorkmids you owed him.",
     478:         Monnam(shopkeeper), total);
     479:         }
     480:         setpaid();  /* in case we create bones */
     481:     }
     482: }
     483:
     484: /* find obj on one of the lists */
     485: struct obj *
     486: bp_to_obj(bp)
     487: register struct bill_x *bp;
     488: {
     489:     register struct obj *obj;
     490:     register struct monst *mtmp;
     491:     register unsigned id = bp->bo_id;
     492:
     493:     if(bp->useup)
     494:         obj = o_on(id, billobjs);
     495:     else if(!(obj = o_on(id, invent)) &&
     496:         !(obj = o_on(id, fobj)) &&
     497:         !(obj = o_on(id, fcobj))) {
     498:             for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
     499:             if(obj = o_on(id, mtmp->minvent))
     500:                 break;
     501:             for(mtmp = fallen_down; mtmp; mtmp = mtmp->nmon)
     502:             if(obj = o_on(id, mtmp->minvent))
     503:                 break;
     504:         }
     505:     return(obj);
     506: }
     507:
     508: /* called in hack.c when we pickup an object */
     509: addtobill(obj) register struct obj *obj; {
     510: register struct bill_x *bp;
     511:     if(!inshop() ||
     512:     (u.ux == ESHK(shopkeeper)->shk.x && u.uy == ESHK(shopkeeper)->shk.y) ||
     513:     (u.ux == ESHK(shopkeeper)->shd.x && u.uy == ESHK(shopkeeper)->shd.y) ||
     514:         onbill(obj) /* perhaps we threw it away earlier */
     515:       ) return;
     516:     if(ESHK(shopkeeper)->billct == BILLSZ){
     517:         pline("You got that for free!");
     518:         return;
     519:     }
     520:     bp = &bill[ESHK(shopkeeper)->billct];
     521:     bp->bo_id = obj->o_id;
     522:     bp->bquan = obj->quan;
     523:     bp->useup = 0;
     524:     bp->price = getprice(obj);
     525:     ESHK(shopkeeper)->billct++;
     526:     obj->unpaid = 1;
     527: }
     528:
     529: splitbill(obj,otmp) register struct obj *obj, *otmp; {
     530:     /* otmp has been split off from obj */
     531: register struct bill_x *bp;
     532: register int tmp;
     533:     bp = onbill(obj);
     534:     if(!bp) {
     535:         impossible("splitbill: not on bill?");
     536:         return;
     537:     }
     538:     if(bp->bquan < otmp->quan) {
     539:         impossible("Negative quantity on bill??");
     540:     }
     541:     if(bp->bquan == otmp->quan) {
     542:         impossible("Zero quantity on bill??");
     543:     }
     544:     bp->bquan -= otmp->quan;
     545:
     546:     /* addtobill(otmp); */
     547:     if(ESHK(shopkeeper)->billct == BILLSZ) otmp->unpaid = 0;
     548:     else {
     549:         tmp = bp->price;
     550:         bp = &bill[ESHK(shopkeeper)->billct];
     551:         bp->bo_id = otmp->o_id;
     552:         bp->bquan = otmp->quan;
     553:         bp->useup = 0;
     554:         bp->price = tmp;
     555:         ESHK(shopkeeper)->billct++;
     556:     }
     557: }
     558:
     559: subfrombill(obj) register struct obj *obj; {
     560: long ltmp;
     561: register int tmp;
     562: register struct obj *otmp;
     563: register struct bill_x *bp;
     564:     if(!inshop() || (u.ux == ESHK(shopkeeper)->shk.x && u.uy == ESHK(shopkeeper)->shk.y) ||
     565:         (u.ux == ESHK(shopkeeper)->shd.x && u.uy == ESHK(shopkeeper)->shd.y))
     566:         return;
     567:     if((bp = onbill(obj)) != 0){
     568:         obj->unpaid = 0;
     569:         if(bp->bquan > obj->quan){
     570:             otmp = newobj(0);
     571:             *otmp = *obj;
     572:             bp->bo_id = otmp->o_id = flags.ident++;
     573:             otmp->quan = (bp->bquan -= obj->quan);
     574:             otmp->owt = 0;  /* superfluous */
     575:             otmp->onamelth = 0;
     576:             bp->useup = 1;
     577:             otmp->nobj = billobjs;
     578:             billobjs = otmp;
     579:             return;
     580:         }
     581:         ESHK(shopkeeper)->billct--;
     582:         *bp = bill[ESHK(shopkeeper)->billct];
     583:         return;
     584:     }
     585:     if(obj->unpaid){
     586:         pline("%s didn't notice.", Monnam(shopkeeper));
     587:         obj->unpaid = 0;
     588:         return;     /* %% */
     589:     }
     590:     /* he dropped something of his own - probably wants to sell it */
     591:     if(shopkeeper->msleep || shopkeeper->mfroz ||
     592:         inroom(shopkeeper->mx,shopkeeper->my) != ESHK(shopkeeper)->shoproom)
     593:         return;
     594:     if(ESHK(shopkeeper)->billct == BILLSZ ||
     595:       ((tmp = shtypes[rooms[ESHK(shopkeeper)->shoproom].rtype-8]) && tmp != obj->olet)
     596:       || index("_0", obj->olet)) {
     597:         pline("%s seems not interested.", Monnam(shopkeeper));
     598:         return;
     599:     }
     600:     ltmp = getprice(obj) * obj->quan;
     601:     if(ANGRY(shopkeeper)) {
     602:         ltmp /= 3;
     603:         NOTANGRY(shopkeeper) = 1;
     604:     } else  ltmp /= 2;
     605:     if(ESHK(shopkeeper)->robbed){
     606:         if((ESHK(shopkeeper)->robbed -= ltmp) < 0)
     607:             ESHK(shopkeeper)->robbed = 0;
     608: pline("Thank you for your contribution to restock this recently plundered shop.");
     609:         return;
     610:     }
     611:     if(ltmp > shopkeeper->mgold)
     612:         ltmp = shopkeeper->mgold;
     613:     pay(-ltmp, shopkeeper);
     614:     if(!ltmp)
     615:     pline("%s gladly accepts %s but cannot pay you at present.",
     616:         Monnam(shopkeeper), doname(obj));
     617:     else
     618:     pline("You sold %s and got %ld gold piece%s.", doname(obj), ltmp,
     619:         plur(ltmp));
     620: }
     621:
     622: doinvbill(mode)
     623: int mode;       /* 0: deliver count 1: paged */
     624: {
     625:     register struct bill_x *bp;
     626:     register struct obj *obj;
     627:     long totused, thisused;
     628:     char buf[BUFSZ];
     629:
     630:     if(mode == 0) {
     631:         register int cnt = 0;
     632:
     633:         if(shopkeeper)
     634:         for(bp = bill; bp - bill < ESHK(shopkeeper)->billct; bp++)
     635:             if(bp->useup ||
     636:               ((obj = bp_to_obj(bp)) && obj->quan < bp->bquan))
     637:             cnt++;
     638:         return(cnt);
     639:     }
     640:
     641:     if(!shopkeeper) {
     642:         impossible("doinvbill: no shopkeeper?");
     643:         return(0);
     644:     }
     645:
     646:     set_pager(0);
     647:     if(page_line("Unpaid articles already used up:") || page_line(""))
     648:         goto quit;
     649:
     650:     totused = 0;
     651:     for(bp = bill; bp - bill < ESHK(shopkeeper)->billct; bp++) {
     652:         obj = bp_to_obj(bp);
     653:         if(!obj) {
     654:         impossible("Bad shopkeeper administration.");
     655:         goto quit;
     656:         }
     657:         if(bp->useup || bp->bquan > obj->quan) {
     658:         register int cnt, oquan, uquan;
     659:
     660:         oquan = obj->quan;
     661:         /* KLUDGE -- reg overflow: simplify expression:
     662: 			uquan = (bp->useup ? bp->bquan : bp->bquan - oquan);
     663: 		*/
     664:         uquan = bp->bquan;
     665:         if(bp->useup)
     666:             uquan -= oquan;
     667:         thisused = bp->price * uquan;
     668:         totused += thisused;
     669:         obj->quan = uquan;      /* cheat doname */
     670:         (void) sprintf(buf, "x -  %s", doname(obj));
     671:         obj->quan = oquan;      /* restore value */
     672:         for(cnt = 0; buf[cnt]; cnt++);
     673:         while(cnt < 50)
     674:             buf[cnt++] = ' ';
     675:         (void) sprintf(&buf[cnt], " %5ld zorkmids", thisused);
     676:         if(page_line(buf))
     677:             goto quit;
     678:         }
     679:     }
     680:     (void) sprintf(buf, "Total:%50ld zorkmids", totused);
     681:     if(page_line("") || page_line(buf))
     682:         goto quit;
     683:     set_pager(1);
     684:     return(0);
     685: quit:
     686:     set_pager(2);
     687:     return(0);
     688: }
     689:
     690: static
     691: getprice(obj) register struct obj *obj; {
     692: register int tmp, ac;
     693:     switch(obj->olet){
     694:     case AMULET_SYM:
     695:         tmp = 10*rnd(500);
     696:         break;
     697:     case TOOL_SYM:
     698:         tmp = 10*rnd((obj->otyp == EXPENSIVE_CAMERA) ? 150 : 30);
     699:         break;
     700:     case RING_SYM:
     701:         tmp = 10*rnd(100);
     702:         break;
     703:     case WAND_SYM:
     704:         tmp = 10*rnd(100);
     705:         break;
     706:     case SCROLL_SYM:
     707:         tmp = 10*rnd(50);
     708: #ifdef MAIL
     709:         if(obj->otyp == SCR_MAIL)
     710:             tmp = rnd(5);
     711: #endif MAIL
     712:         break;
     713:     case POTION_SYM:
     714:         tmp = 10*rnd(50);
     715:         break;
     716:     case FOOD_SYM:
     717:         tmp = 10*rnd(5 + (2000/realhunger()));
     718:         break;
     719:     case GEM_SYM:
     720:         tmp = 10*rnd(20);
     721:         break;
     722:     case ARMOR_SYM:
     723:         ac = ARM_BONUS(obj);
     724:         if(ac <= -10)       /* probably impossible */
     725:             ac = -9;
     726:         tmp = 100 + ac*ac*rnd(10+ac);
     727:         break;
     728:     case WEAPON_SYM:
     729:         if(obj->otyp < BOOMERANG)
     730:             tmp = 5*rnd(10);
     731:         else if(obj->otyp == LONG_SWORD ||
     732:             obj->otyp == TWO_HANDED_SWORD)
     733:             tmp = 10*rnd(150);
     734:         else    tmp = 10*rnd(75);
     735:         break;
     736:     case CHAIN_SYM:
     737:         pline("Strange ..., carrying a chain?");
     738:     case BALL_SYM:
     739:         tmp = 10;
     740:         break;
     741:     default:
     742:         tmp = 10000;
     743:     }
     744:     return(tmp);
     745: }
     746:
     747: static
     748: realhunger(){   /* not completely foolproof */
     749: register tmp = u.uhunger;
     750: register struct obj *otmp = invent;
     751:     while(otmp){
     752:         if(otmp->olet == FOOD_SYM && !otmp->unpaid)
     753:             tmp += objects[otmp->otyp].nutrition;
     754:         otmp = otmp->nobj;
     755:     }
     756:     return((tmp <= 0) ? 1 : tmp);
     757: }
     758:
     759: shkcatch(obj)
     760: register struct obj *obj;
     761: {
     762:     register struct monst *shkp = shopkeeper;
     763:
     764:     if(u.uinshop && shkp && !shkp->mfroz && !shkp->msleep &&
     765:         u.dx && u.dy &&
     766:         inroom(u.ux+u.dx, u.uy+u.dy) + 1 == u.uinshop &&
     767:         shkp->mx == ESHK(shkp)->shk.x && shkp->my == ESHK(shkp)->shk.y &&
     768:         u.ux == ESHK(shkp)->shd.x && u.uy == ESHK(shkp)->shd.y) {
     769:         pline("%s nimbly catches the %s.", Monnam(shkp), xname(obj));
     770:         obj->nobj = shkp->minvent;
     771:         shkp->minvent = obj;
     772:         return(1);
     773:     }
     774:     return(0);
     775: }
     776:
     777: /*
     778:  * shk_move: return 1: he moved  0: he didnt  -1: let m_move do it
     779:  */
     780: shk_move(shkp)
     781: register struct monst *shkp;
     782: {
     783:     register struct monst *mtmp;
     784:     register struct permonst *mdat = shkp->data;
     785:     register xchar gx,gy,omx,omy,nx,ny,nix,niy;
     786:     register schar appr,i;
     787:     register int udist;
     788:     int z;
     789:     schar shkroom,chi,chcnt,cnt;
     790:     boolean uondoor, satdoor, avoid, badinv;
     791:     coord poss[9];
     792:     int info[9];
     793:     struct obj *ib = 0;
     794:
     795:     omx = shkp->mx;
     796:     omy = shkp->my;
     797:
     798:     if((udist = dist(omx,omy)) < 3) {
     799:         if(ANGRY(shkp)) {
     800:             (void) hitu(shkp, d(mdat->damn, mdat->damd)+1);
     801:             return(0);
     802:         }
     803:         if(ESHK(shkp)->following) {
     804:             if(strncmp(ESHK(shkp)->customer, plname, PL_NSIZ)){
     805:                 pline("Hello %s! I was looking for %s.",
     806:                     plname, ESHK(shkp)->customer);
     807:                 ESHK(shkp)->following = 0;
     808:                 return(0);
     809:             }
     810:             if(!ESHK(shkp)->robbed) {   /* impossible? */
     811:                 ESHK(shkp)->following = 0;
     812:                 return(0);
     813:             }
     814:             if(moves > followmsg+4) {
     815:                 pline("Hello %s! Didn't you forget to pay?",
     816:                     plname);
     817:                 followmsg = moves;
     818:             }
     819:             if(udist < 2)
     820:                 return(0);
     821:         }
     822:     }
     823:
     824:     shkroom = inroom(omx,omy);
     825:     appr = 1;
     826:     gx = ESHK(shkp)->shk.x;
     827:     gy = ESHK(shkp)->shk.y;
     828:     satdoor = (gx == omx && gy == omy);
     829:     if(ESHK(shkp)->following || ((z = holetime()) >= 0 && z*z <= udist)){
     830:         gx = u.ux;
     831:         gy = u.uy;
     832:         if(shkroom < 0 || shkroom != inroom(u.ux,u.uy))
     833:             if(udist > 4)
     834:             return(-1); /* leave it to m_move */
     835:     } else if(ANGRY(shkp)) {
     836:         long saveBlind = Blind;
     837:         Blind = 0;
     838:         if(shkp->mcansee && !Invis && cansee(omx,omy)) {
     839:             gx = u.ux;
     840:             gy = u.uy;
     841:         }
     842:         Blind = saveBlind;
     843:         avoid = FALSE;
     844:     } else {
     845: #define GDIST(x,y)  ((x-gx)*(x-gx)+(y-gy)*(y-gy))
     846:         if(Invis)
     847:           avoid = FALSE;
     848:         else {
     849:           uondoor = (u.ux == ESHK(shkp)->shd.x &&
     850:                 u.uy == ESHK(shkp)->shd.y);
     851:           if(uondoor) {
     852:             if(ESHK(shkp)->billct)
     853:             pline("Hello %s! Will you please pay before leaving?",
     854:                 plname);
     855:             badinv = (carrying(PICK_AXE) || carrying(ICE_BOX));
     856:             if(satdoor && badinv)
     857:             return(0);
     858:             avoid = !badinv;
     859:           } else {
     860:             avoid = (u.uinshop && dist(gx,gy) > 8);
     861:             badinv = FALSE;
     862:           }
     863:
     864:           if(((!ESHK(shkp)->robbed && !ESHK(shkp)->billct) || avoid)
     865:             && GDIST(omx,omy) < 3){
     866:             if(!badinv && !online(omx,omy))
     867:                 return(0);
     868:             if(satdoor)
     869:                 appr = gx = gy = 0;
     870:           }
     871:         }
     872:     }
     873:     if(omx == gx && omy == gy)
     874:         return(0);
     875:     if(shkp->mconf) {
     876:         avoid = FALSE;
     877:         appr = 0;
     878:     }
     879:     nix = omx;
     880:     niy = omy;
     881:     cnt = mfndpos(shkp,poss,info,ALLOW_SSM);
     882:     if(avoid && uondoor) {      /* perhaps we cannot avoid him */
     883:         for(i=0; i<cnt; i++)
     884:             if(!(info[i] & NOTONL)) goto notonl_ok;
     885:         avoid = FALSE;
     886:     notonl_ok:
     887:         ;
     888:     }
     889:     chi = -1;
     890:     chcnt = 0;
     891:     for(i=0; i<cnt; i++){
     892:         nx = poss[i].x;
     893:         ny = poss[i].y;
     894:         if(levl[nx][ny].typ == ROOM
     895:         || shkroom != ESHK(shkp)->shoproom
     896:         || ESHK(shkp)->following) {
     897: #ifdef STUPID
     898:             /* cater for stupid compilers */
     899:             register int zz;
     900: #endif STUPID
     901:             if(uondoor && (ib = sobj_at(ICE_BOX, nx, ny))) {
     902:             nix = nx; niy = ny; chi = i; break;
     903:             }
     904:             if(avoid && (info[i] & NOTONL))
     905:             continue;
     906:             if((!appr && !rn2(++chcnt)) ||
     907: #ifdef STUPID
     908:             (appr && (zz = GDIST(nix,niy)) && zz > GDIST(nx,ny))
     909: #else
     910:             (appr && GDIST(nx,ny) < GDIST(nix,niy))
     911: #endif STUPID
     912:             ) {
     913:                 nix = nx;
     914:                 niy = ny;
     915:                 chi = i;
     916:             }
     917:         }
     918:     }
     919:     if(nix != omx || niy != omy){
     920:         if(info[chi] & ALLOW_M){
     921:             mtmp = m_at(nix,niy);
     922:             if(hitmm(shkp,mtmp) == 1 && rn2(3) &&
     923:                hitmm(mtmp,shkp) == 2) return(2);
     924:             return(0);
     925:         } else if(info[chi] & ALLOW_U){
     926:             (void) hitu(shkp, d(mdat->damn, mdat->damd)+1);
     927:             return(0);
     928:         }
     929:         shkp->mx = nix;
     930:         shkp->my = niy;
     931:         pmon(shkp);
     932:         if(ib) {
     933:             freeobj(ib);
     934:             mpickobj(shkp, ib);
     935:         }
     936:         return(1);
     937:     }
     938:     return(0);
     939: }
     940: #endif QUEST
     941:
     942: online(x,y) {
     943:     return(x==u.ux || y==u.uy ||
     944:         (x-u.ux)*(x-u.ux) == (y-u.uy)*(y-u.uy));
     945: }
     946:
     947: /* Does this monster follow me downstairs? */
     948: follower(mtmp)
     949: register struct monst *mtmp;
     950: {
     951:     return( mtmp->mtame || index("1TVWZi&, ", mtmp->data->mlet) ||
     952:         (mtmp->isshk && ESHK(mtmp)->following) );
     953: }
     954:
     955: /* He is digging in the shop. */
     956: shopdig(fall)
     957: register int fall;
     958: {
     959:     if(!fall) {
     960:     if(u.utraptype == TT_PIT)
     961:         pline("\"Be careful, sir, or you might fall through the floor.\"");
     962:     else
     963:         pline("\"Please, do not damage the floor here.\"");
     964:     } else if(dist(shopkeeper->mx, shopkeeper->my) < 3) {
     965:     register struct obj *obj, *obj2;
     966:
     967:     pline("%s grabs your backpack!", shkname(shopkeeper));
     968:     for(obj = invent; obj; obj = obj2) {
     969:         obj2 = obj->nobj;
     970:         if(obj->owornmask) continue;
     971:         freeinv(obj);
     972:         obj->nobj = shopkeeper->minvent;
     973:         shopkeeper->minvent = obj;
     974:         if(obj->unpaid)
     975:             subfrombill(obj);
     976:     }
     977:     }
     978: }

#### Defined functions

addtobill defined in line 509; used 2 times

- in /usr/src/games/hack/hack.c line 449
- in /usr/src/games/hack/hack.eat.c line 108

addupbill defined in line 118; used 2 times

- in line 140, 468

bp_to_obj defined in line 485; used 4 times

- in line 35, 427, 636, 652

doinvbill defined in line 622; used 2 times

- in /usr/src/games/hack/hack.invent.c line 635, 671

dopay defined in line 305; used 2 times

- in /usr/src/games/hack/hack.cmd.c line 8, 44

dopayobj defined in line 421; used 1 times

- in line 407

findshk defined in line 225; used 1 times

- in line 183

follower defined in line 948; used 1 times

- in /usr/src/games/hack/hack.dog.c line 58

getprice defined in line 690; used 2 times

- in line 524, 600

inshop defined in line 130; used 12 times

- in line 312, 511, 564
- in /usr/src/games/hack/hack.apply.c line 340, 438
- in /usr/src/games/hack/hack.c line 305
- in /usr/src/games/hack/hack.do.c line 156, 227, 435
- in /usr/src/games/hack/hack.invent.c line 635
- in /usr/src/games/hack/hack.main.c line 266
- in /usr/src/games/hack/hack.trap.c line 323

obfree defined in line 262; used 11 times

- in /usr/src/games/hack/hack.do.c line 302-309(3), 356
- in /usr/src/games/hack/hack.dog.c line 404
- in /usr/src/games/hack/hack.fight.c line 163, 178
- in /usr/src/games/hack/hack.invent.c line 104, 126, 778
- in /usr/src/games/hack/hack.potion.c line 294

onbill defined in line 248; used 5 times

- in line 263, 273, 514, 533, 567

online defined in line 942; used 2 times

- in line 866
- in /usr/src/games/hack/hack.mon.c line 531

pay defined in line 288; used 6 times

- in line 337-340(2), 370, 384, 448, 613

paybill defined in line 466; used 1 times

- in /usr/src/games/hack/hack.end.c line 91

realhunger defined in line 747; used 1 times

- in line 717

replshk defined in line 85; used 1 times

- in /usr/src/games/hack/hack.mon.c line 611

setpaid defined in line 94; used 5 times

- in line 79, 144, 396, 431, 480

shk_move defined in line 780; used 1 times

- in /usr/src/games/hack/hack.mon.c line 276

shkcatch defined in line 759; used 1 times

- in /usr/src/games/hack/hack.do.c line 322

shkdead defined in line 71; used 1 times

- in /usr/src/games/hack/hack.mon.c line 594

shkname defined in line 64; used 5 times

- in line 205, 412, 967
- in /usr/src/games/hack/hack.do_name.c line 190, 208

shopdig defined in line 956; used 2 times

- in /usr/src/games/hack/hack.apply.c line 341, 439

splitbill defined in line 529; used 1 times

- in /usr/src/games/hack/hack.do.c line 455

subfrombill defined in line 559; used 2 times

- in line 975
- in /usr/src/games/hack/hack.do.c line 74

#### Defined variables

bill defined in line 40; used 20 times

- in line 81, 90(2), 122, 234(2), 245, 252(2), 282, 402, 408(2), 520, 550, 582, 634(2), 651(2)

billobjs defined in line 42; used 13 times

- in line 111-112(2), 269-270(2), 452-454(3), 494, 577-578(2)
- in /usr/src/games/hack/hack.lev.c line 49-50(2), 236

followmsg defined in line 45; used 2 times

- in line 814-817(2)

shlevel defined in line 41; used 6 times

- in line 135, 150, 181, 235, 244, 467

shopkeeper defined in line 39; used 104 times

- in line 78-80(2), 88-90(3), 115, 121, 135-149(7), 181-210(16), 233-243(6), 251-252(2), 281-282(2), 317-318(4), 325, 394-401(3), 408-414(4), 441, 448, 467-478(6), 512-525(7), 547-555(3), 564-565(4), 581-616(20), 633-634(2), 641, 651, 762, 964-973(5)

shopnam defined in line 58; used 2 times

- in line 206, 413

shtypes defined in line 53; used 5 times

- in line 595
- in /usr/src/games/hack/hack.mkshop.c line 43-44(2), 70-75(2)

total defined in line 44; used 8 times

- in line 123-125(2), 142-143(2), 469, 475-478(3)

#### Defined macros

ANGRY defined in line 32; used 6 times

- in line 236, 374, 441, 601, 799, 835

ESHK defined in line 30; used 87 times

- in line 68, 74, 90, 115, 121, 138-147(4), 182, 190-206(8), 231-237(4), 252, 281-282(2), 293, 301, 317, 324, 345-347(3), 358, 364-371(4), 385, 401, 408-413(2), 467, 512-525(7), 547-555(3), 564-565(4), 581-582(2), 592-595(3), 605-607(3), 634, 651, 767-768(4), 803-811(6), 826-829(3), 849-852(3), 864(2), 895-896(2), 952

GDIST defined in line 845; used 5 times

- in line 865, 908-910(4)

NOTANGRY defined in line 31; used 7 times

- in line 32, 197, 238, 325, 388, 414, 603

min defined in line 365; used 1 times

- in line 370

Last modified: 1985-10-04 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2796 |