(linenum→info "unix/slp.c:2238")

bsd-games/2.17/hack/hack.objnam.c

    1: /*      $NetBSD: hack.objnam.c,v 1.6 2003/04/02 18:36:39 jsm Exp $   */
    2: 
    3: /*
    4:  * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
    5:  * Amsterdam
    6:  * All rights reserved.
    7:  *
    8:  * Redistribution and use in source and binary forms, with or without
    9:  * modification, are permitted provided that the following conditions are
   10:  * met:
   11:  *
   12:  * - Redistributions of source code must retain the above copyright notice,
   13:  * this list of conditions and the following disclaimer.
   14:  *
   15:  * - Redistributions in binary form must reproduce the above copyright
   16:  * notice, this list of conditions and the following disclaimer in the
   17:  * documentation and/or other materials provided with the distribution.
   18:  *
   19:  * - Neither the name of the Stichting Centrum voor Wiskunde en
   20:  * Informatica, nor the names of its contributors may be used to endorse or
   21:  * promote products derived from this software without specific prior
   22:  * written permission.
   23:  *
   24:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
   25:  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   26:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
   27:  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
   28:  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   29:  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   30:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   31:  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   32:  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   33:  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   34:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   35:  */
   36: 
   37: /*
   38:  * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
   39:  * All rights reserved.
   40:  *
   41:  * Redistribution and use in source and binary forms, with or without
   42:  * modification, are permitted provided that the following conditions
   43:  * are met:
   44:  * 1. Redistributions of source code must retain the above copyright
   45:  *    notice, this list of conditions and the following disclaimer.
   46:  * 2. Redistributions in binary form must reproduce the above copyright
   47:  *    notice, this list of conditions and the following disclaimer in the
   48:  *    documentation and/or other materials provided with the distribution.
   49:  * 3. The name of the author may not be used to endorse or promote products
   50:  *    derived from this software without specific prior written permission.
   51:  *
   52:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
   53:  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
   54:  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
   55:  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   56:  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   57:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   58:  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   59:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   60:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   61:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   62:  */
   63: 
   64: #include <sys/cdefs.h>
   65: #ifndef lint
   66: __RCSID("$NetBSD: hack.objnam.c,v 1.6 2003/04/02 18:36:39 jsm Exp $");
   67: #endif                          /* not lint */
   68: 
   69: #include <stdlib.h>
   70: #include "hack.h"
   71: #include "extern.h"
   72: #define Sprintf (void) sprintf
   73: #define Strcat  (void) strcat
   74: #define Strcpy  (void) strcpy
   75: #define PREFIX  15
   76: 
   77: char           *
   78: strprepend(s, pref)
   79:         char           *s, *pref;
   80: {
   81:         int             i = strlen(pref);
   82:         if (i > PREFIX) {
   83:                 pline("WARNING: prefix too short.");
   84:                 return (s);
   85:         }
   86:         s -= i;
   87:         (void) strncpy(s, pref, i);    /* do not copy trailing 0 */
   88:         return (s);
   89: }
   90: 
   91: char           *
   92: sitoa(a)
   93:         int             a;
   94: {
   95:         static char     buf[13];
   96:         Sprintf(buf, (a < 0) ? "%d" : "+%d", a);
   97:         return (buf);
   98: }
   99: 
  100: char           *
  101: typename(otyp)
  102:         int             otyp;
  103: {
  104:         static char     buf[BUFSZ];
  105:         struct objclass *ocl = &objects[otyp];
  106:         const char     *an = ocl->oc_name;
  107:         const char     *dn = ocl->oc_descr;
  108:         char           *un = ocl->oc_uname;
  109:         int             nn = ocl->oc_name_known;
  110:         switch (ocl->oc_olet) {
  111:         case POTION_SYM:
  112:                 Strcpy(buf, "potion");
  113:                 break;
  114:         case SCROLL_SYM:
  115:                 Strcpy(buf, "scroll");
  116:                 break;
  117:         case WAND_SYM:
  118:                 Strcpy(buf, "wand");
  119:                 break;
  120:         case RING_SYM:
  121:                 Strcpy(buf, "ring");
  122:                 break;
  123:         default:
  124:                 if (nn) {
  125:                         Strcpy(buf, an);
  126:                         if (otyp >= TURQUOISE && otyp <= JADE)
  127:                                 Strcat(buf, " stone");
  128:                         if (un)
  129:                                 Sprintf(eos(buf), " called %s", un);
  130:                         if (dn)
  131:                                 Sprintf(eos(buf), " (%s)", dn);
  132:                 } else {
  133:                         Strcpy(buf, dn ? dn : an);
  134:                         if (ocl->oc_olet == GEM_SYM)
  135:                                 Strcat(buf, " gem");
  136:                         if (un)
  137:                                 Sprintf(eos(buf), " called %s", un);
  138:                 }
  139:                 return (buf);
  140:         }
  141:         /* here for ring/scroll/potion/wand */
  142:         if (nn)
  143:                 Sprintf(eos(buf), " of %s", an);
  144:         if (un)
  145:                 Sprintf(eos(buf), " called %s", un);
  146:         if (dn)
  147:                 Sprintf(eos(buf), " (%s)", dn);
  148:         return (buf);
  149: }
  150: 
  151: char           *
  152: xname(obj)
  153:         struct obj     *obj;
  154: {
  155:         static char     bufr[BUFSZ];
  156:         char           *buf = &(bufr[PREFIX]); /* leave room for "17 -3 " */
  157:         int             nn = objects[obj->otyp].oc_name_known;
  158:         const char     *an = objects[obj->otyp].oc_name;
  159:         const char     *dn = objects[obj->otyp].oc_descr;
  160:         char           *un = objects[obj->otyp].oc_uname;
  161:         int             pl = (obj->quan != 1);
  162:         if (!obj->dknown && !Blind)
  163:                 obj->dknown = 1;/* %% doesnt belong here */
  164:         switch (obj->olet) {
  165:         case AMULET_SYM:
  166:                 Strcpy(buf, (obj->spe < 0 && obj->known)
  167:                        ? "cheap plastic imitation of the " : "");
  168:                 Strcat(buf, "Amulet of Yendor");
  169:                 break;
  170:         case TOOL_SYM:
  171:                 if (!nn) {
  172:                         Strcpy(buf, dn);
  173:                         break;
  174:                 }
  175:                 Strcpy(buf, an);
  176:                 break;
  177:         case FOOD_SYM:
  178:                 if (obj->otyp == DEAD_HOMUNCULUS && pl) {
  179:                         pl = 0;
  180:                         Strcpy(buf, "dead homunculi");
  181:                         break;
  182:                 }
  183:                 /* fungis ? */
  184:                 /* fall into next case */
  185:         case WEAPON_SYM:
  186:                 if (obj->otyp == WORM_TOOTH && pl) {
  187:                         pl = 0;
  188:                         Strcpy(buf, "worm teeth");
  189:                         break;
  190:                 }
  191:                 if (obj->otyp == CRYSKNIFE && pl) {
  192:                         pl = 0;
  193:                         Strcpy(buf, "crysknives");
  194:                         break;
  195:                 }
  196:                 /* fall into next case */
  197:         case ARMOR_SYM:
  198:         case CHAIN_SYM:
  199:         case ROCK_SYM:
  200:                 Strcpy(buf, an);
  201:                 break;
  202:         case BALL_SYM:
  203:                 Sprintf(buf, "%sheavy iron ball",
  204:                   (obj->owt > objects[obj->otyp].oc_weight) ? "very " : "");
  205:                 break;
  206:         case POTION_SYM:
  207:                 if (nn || un || !obj->dknown) {
  208:                         Strcpy(buf, "potion");
  209:                         if (pl) {
  210:                                 pl = 0;
  211:                                 Strcat(buf, "s");
  212:                         }
  213:                         if (!obj->dknown)
  214:                                 break;
  215:                         if (un) {
  216:                                 Strcat(buf, " called ");
  217:                                 Strcat(buf, un);
  218:                         } else {
  219:                                 Strcat(buf, " of ");
  220:                                 Strcat(buf, an);
  221:                         }
  222:                 } else {
  223:                         Strcpy(buf, dn);
  224:                         Strcat(buf, " potion");
  225:                 }
  226:                 break;
  227:         case SCROLL_SYM:
  228:                 Strcpy(buf, "scroll");
  229:                 if (pl) {
  230:                         pl = 0;
  231:                         Strcat(buf, "s");
  232:                 }
  233:                 if (!obj->dknown)
  234:                         break;
  235:                 if (nn) {
  236:                         Strcat(buf, " of ");
  237:                         Strcat(buf, an);
  238:                 } else if (un) {
  239:                         Strcat(buf, " called ");
  240:                         Strcat(buf, un);
  241:                 } else {
  242:                         Strcat(buf, " labeled ");
  243:                         Strcat(buf, dn);
  244:                 }
  245:                 break;
  246:         case WAND_SYM:
  247:                 if (!obj->dknown)
  248:                         Sprintf(buf, "wand");
  249:                 else if (nn)
  250:                         Sprintf(buf, "wand of %s", an);
  251:                 else if (un)
  252:                         Sprintf(buf, "wand called %s", un);
  253:                 else
  254:                         Sprintf(buf, "%s wand", dn);
  255:                 break;
  256:         case RING_SYM:
  257:                 if (!obj->dknown)
  258:                         Sprintf(buf, "ring");
  259:                 else if (nn)
  260:                         Sprintf(buf, "ring of %s", an);
  261:                 else if (un)
  262:                         Sprintf(buf, "ring called %s", un);
  263:                 else
  264:                         Sprintf(buf, "%s ring", dn);
  265:                 break;
  266:         case GEM_SYM:
  267:                 if (!obj->dknown) {
  268:                         Strcpy(buf, "gem");
  269:                         break;
  270:                 }
  271:                 if (!nn) {
  272:                         Sprintf(buf, "%s gem", dn);
  273:                         break;
  274:                 }
  275:                 Strcpy(buf, an);
  276:                 if (obj->otyp >= TURQUOISE && obj->otyp <= JADE)
  277:                         Strcat(buf, " stone");
  278:                 break;
  279:         default:
  280:                 Sprintf(buf, "glorkum %c (0%o) %u %d",
  281:                         obj->olet, obj->olet, obj->otyp, obj->spe);
  282:         }
  283:         if (pl) {
  284:                 char           *p;
  285: 
  286:                 for (p = buf; *p; p++) {
  287:                         if (!strncmp(" of ", p, 4)) {
  288:                                 /* pieces of, cloves of, lumps of */
  289:                                 int             c1, c2 = 's';
  290: 
  291:                                 do {
  292:                                         c1 = c2;
  293:                                         c2 = *p;
  294:                                         *p++ = c1;
  295:                                 } while (c1);
  296:                                 goto nopl;
  297:                         }
  298:                 }
  299:                 p = eos(buf) - 1;
  300:                 if (*p == 's' || *p == 'z' || *p == 'x' ||
  301:                     (*p == 'h' && p[-1] == 's'))
  302:                         Strcat(buf, "es");   /* boxes */
  303:                 else if (*p == 'y' && !strchr(vowels, p[-1]))
  304:                         Strcpy(p, "ies");    /* rubies, zruties */
  305:                 else
  306:                         Strcat(buf, "s");
  307:         }
  308: nopl:
  309:         if (obj->onamelth) {
  310:                 Strcat(buf, " named ");
  311:                 Strcat(buf, ONAME(obj));
  312:         }
  313:         return (buf);
  314: }
  315: 
  316: char           *
  317: doname(obj)
  318:         struct obj     *obj;
  319: {
  320:         char            prefix[PREFIX];
  321:         char           *bp = xname(obj);
  322:         if (obj->quan != 1)
  323:                 Sprintf(prefix, "%u ", obj->quan);
  324:         else
  325:                 Strcpy(prefix, "a ");
  326:         switch (obj->olet) {
  327:         case AMULET_SYM:
  328:                 if (strncmp(bp, "cheap ", 6))
  329:                         Strcpy(prefix, "the ");
  330:                 break;
  331:         case ARMOR_SYM:
  332:                 if (obj->owornmask & W_ARMOR)
  333:                         Strcat(bp, " (being worn)");
  334:                 /* fall into next case */
  335:         case WEAPON_SYM:
  336:                 if (obj->known) {
  337:                         Strcat(prefix, sitoa(obj->spe));
  338:                         Strcat(prefix, " ");
  339:                 }
  340:                 break;
  341:         case WAND_SYM:
  342:                 if (obj->known)
  343:                         Sprintf(eos(bp), " (%d)", obj->spe);
  344:                 break;
  345:         case RING_SYM:
  346:                 if (obj->owornmask & W_RINGR)
  347:                         Strcat(bp, " (on right hand)");
  348:                 if (obj->owornmask & W_RINGL)
  349:                         Strcat(bp, " (on left hand)");
  350:                 if (obj->known && (objects[obj->otyp].bits & SPEC)) {
  351:                         Strcat(prefix, sitoa(obj->spe));
  352:                         Strcat(prefix, " ");
  353:                 }
  354:                 break;
  355:         }
  356:         if (obj->owornmask & W_WEP)
  357:                 Strcat(bp, " (weapon in hand)");
  358:         if (obj->unpaid)
  359:                 Strcat(bp, " (unpaid)");
  360:         if (!strcmp(prefix, "a ") && strchr(vowels, *bp))
  361:                 Strcpy(prefix, "an ");
  362:         bp = strprepend(bp, prefix);
  363:         return (bp);
  364: }
  365: 
  366: /* used only in hack.fight.c (thitu) */
  367: void
  368: setan(const char *str, char *buf)
  369: {
  370:         if (strchr(vowels, *str))
  371:                 Sprintf(buf, "an %s", str);
  372:         else
  373:                 Sprintf(buf, "a %s", str);
  374: }
  375: 
  376: char           *
  377: aobjnam(otmp, verb)
  378:         struct obj     *otmp;
  379:         const char           *verb;
  380: {
  381:         char           *bp = xname(otmp);
  382:         char            prefix[PREFIX];
  383:         if (otmp->quan != 1) {
  384:                 Sprintf(prefix, "%u ", otmp->quan);
  385:                 bp = strprepend(bp, prefix);
  386:         }
  387:         if (verb) {
  388:                 /* verb is given in plural (i.e., without trailing s) */
  389:                 Strcat(bp, " ");
  390:                 if (otmp->quan != 1)
  391:                         Strcat(bp, verb);
  392:                 else if (!strcmp(verb, "are"))
  393:                         Strcat(bp, "is");
  394:                 else {
  395:                         Strcat(bp, verb);
  396:                         Strcat(bp, "s");
  397:                 }
  398:         }
  399:         return (bp);
  400: }
  401: 
  402: char           *
  403: Doname(obj)
  404:         struct obj     *obj;
  405: {
  406:         char           *s = doname(obj);
  407: 
  408:         if ('a' <= *s && *s <= 'z')
  409:                 *s -= ('a' - 'A');
  410:         return (s);
  411: }
  412: 
  413: const char *const wrp[] = {"wand", "ring", "potion", "scroll", "gem"};
  414: const char wrpsym[] = {WAND_SYM, RING_SYM, POTION_SYM, SCROLL_SYM, GEM_SYM};
  415: 
  416: struct obj     *
  417: readobjnam(bp)
  418:         char           *bp;
  419: {
  420:         char           *p;
  421:         int             i;
  422:         int             cnt, spe, spesgn, typ, heavy;
  423:         char            let;
  424:         char           *un, *dn, *an;
  425:         /* int the = 0; char *oname = 0; */
  426:         cnt = spe = spesgn = typ = heavy = 0;
  427:         let = 0;
  428:         an = dn = un = 0;
  429:         for (p = bp; *p; p++)
  430:                 if ('A' <= *p && *p <= 'Z')
  431:                         *p += 'a' - 'A';
  432:         if (!strncmp(bp, "the ", 4)) {
  433:                 /* the = 1; */
  434:                 bp += 4;
  435:         } else if (!strncmp(bp, "an ", 3)) {
  436:                 cnt = 1;
  437:                 bp += 3;
  438:         } else if (!strncmp(bp, "a ", 2)) {
  439:                 cnt = 1;
  440:                 bp += 2;
  441:         }
  442:         if (!cnt && digit(*bp)) {
  443:                 cnt = atoi(bp);
  444:                 while (digit(*bp))
  445:                         bp++;
  446:                 while (*bp == ' ')
  447:                         bp++;
  448:         }
  449:         if (!cnt)
  450:                 cnt = 1;      /* %% what with "gems" etc. ? */
  451: 
  452:         if (*bp == '+' || *bp == '-') {
  453:                 spesgn = (*bp++ == '+') ? 1 : -1;
  454:                 spe = atoi(bp);
  455:                 while (digit(*bp))
  456:                         bp++;
  457:                 while (*bp == ' ')
  458:                         bp++;
  459:         } else {
  460:                 p = strrchr(bp, '(');
  461:                 if (p) {
  462:                         if (p > bp && p[-1] == ' ')
  463:                                 p[-1] = 0;
  464:                         else
  465:                                 *p = 0;
  466:                         p++;
  467:                         spe = atoi(p);
  468:                         while (digit(*p))
  469:                                 p++;
  470:                         if (strcmp(p, ")"))
  471:                                 spe = 0;
  472:                         else
  473:                                 spesgn = 1;
  474:                 }
  475:         }
  476:         /*
  477:          * now we have the actual name, as delivered by xname, say green
  478:          * potions called whisky scrolls labeled "QWERTY" egg dead zruties
  479:          * fortune cookies very heavy iron ball named hoei wand of wishing
  480:          * elven cloak
  481:          */
  482:         for (p = bp; *p; p++)
  483:                 if (!strncmp(p, " named ", 7)) {
  484:                         *p = 0;
  485:                         /* oname = p+7; */
  486:                 }
  487:         for (p = bp; *p; p++)
  488:                 if (!strncmp(p, " called ", 8)) {
  489:                         *p = 0;
  490:                         un = p + 8;
  491:                 }
  492:         for (p = bp; *p; p++)
  493:                 if (!strncmp(p, " labeled ", 9)) {
  494:                         *p = 0;
  495:                         dn = p + 9;
  496:                 }
  497:         /* first change to singular if necessary */
  498:         if (cnt != 1) {
  499:                 /* find "cloves of garlic", "worthless pieces of blue glass" */
  500:                 for (p = bp; *p; p++)
  501:                         if (!strncmp(p, "s of ", 5)) {
  502:                                 while ((*p = p[1]) != '\0')
  503:                                         p++;
  504:                                 goto sing;
  505:                         }
  506:                 /* remove -s or -es (boxes) or -ies (rubies, zruties) */
  507:                 p = eos(bp);
  508:                 if (p[-1] == 's') {
  509:                         if (p[-2] == 'e') {
  510:                                 if (p[-3] == 'i') {
  511:                                         if (!strcmp(p - 7, "cookies"))
  512:                                                 goto mins;
  513:                                         Strcpy(p - 3, "y");
  514:                                         goto sing;
  515:                                 }
  516:                                 /* note: cloves / knives from clove / knife */
  517:                                 if (!strcmp(p - 6, "knives")) {
  518:                                         Strcpy(p - 3, "fe");
  519:                                         goto sing;
  520:                                 }
  521:                                 /* note: nurses, axes but boxes */
  522:                                 if (!strcmp(p - 5, "boxes")) {
  523:                                         p[-2] = 0;
  524:                                         goto sing;
  525:                                 }
  526:                         }
  527:         mins:
  528:                         p[-1] = 0;
  529:                 } else {
  530:                         if (!strcmp(p - 9, "homunculi")) {
  531:                                 Strcpy(p - 1, "us");        /* !! makes string
  532:                                                          * longer */
  533:                                 goto sing;
  534:                         }
  535:                         if (!strcmp(p - 5, "teeth")) {
  536:                                 Strcpy(p - 5, "tooth");
  537: