[BACK]Return to misc.c CVS log [TXT][DIR] Up to [contributed] / early-roguelike / arogue5

Annotation of early-roguelike/arogue5/misc.c, Revision 1.1.1.1

1.1       rubenllo    1: /*
                      2:  * routines dealing specifically with miscellaneous magic
                      3:  *
                      4:  * Advanced Rogue
                      5:  * Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
                      6:  * All rights reserved.
                      7:  *
                      8:  * See the file LICENSE.TXT for full copyright and licensing information.
                      9:  */
                     10:
                     11: #include "curses.h"
                     12: #include <stdlib.h>
                     13: #include <ctype.h>
                     14: #include <string.h>
                     15: #include "rogue.h"
                     16:
                     17: /*
                     18:  * See if a monster has some magic it can use.  Use it and return TRUE if so.
                     19:  */
                     20: bool
                     21: m_use_item(struct thing *monster, coord *monst_pos, coord *defend_pos)
                     22: {
                     23:     register struct linked_list *pitem;
                     24:     register struct object *obj;
                     25:     register coord *shoot_dir = can_shoot(monst_pos, defend_pos);
                     26:     int dist=DISTANCE(monst_pos->y, monst_pos->x, defend_pos->y, defend_pos->x);
                     27:
                     28:     for (pitem=monster->t_pack; pitem; pitem=next(pitem)) {
                     29:        obj = OBJPTR(pitem);
                     30:        if (obj->o_type != RELIC) continue;     /* Only care about relics now */
                     31:        switch (obj->o_which) {
                     32:            case MING_STAFF: {
                     33:                static struct object missile = {
                     34:                  MISSILE, {0,0}, "", 0, "", "0d4 " , NULL, 0, WS_MISSILE, 100, 1
                     35:                };
                     36:
                     37:                if (shoot_dir != NULL) {
                     38:                    sprintf(missile.o_hurldmg, "%dd4", monster->t_stats.s_lvl);
                     39:                    do_motion(&missile, shoot_dir->y, shoot_dir->x, monster);
                     40:                    hit_monster(unc(missile.o_pos), &missile, monster);
                     41:                    return(TRUE);
                     42:                }
                     43:            }
                     44:            when ASMO_ROD:
                     45:                /* The bolt must be able to reach the defendant */
                     46:                if (shoot_dir != NULL && dist < BOLT_LENGTH * BOLT_LENGTH) {
                     47:                    char *name;
                     48:
                     49:                    switch (rnd(3)) { /* Select a function */
                     50:                        case 0:    name = "lightning bolt";
                     51:                        when 1:    name = "flame";
                     52:                        otherwise: name = "ice";
                     53:                    }
                     54:                    shoot_bolt( monster,
                     55:                                *monst_pos,
                     56:                                *shoot_dir,
                     57:                                FALSE,
                     58:                                monster->t_index,
                     59:                                name,
                     60:                                roll(monster->t_stats.s_lvl,6));
                     61:                    return(TRUE);
                     62:                }
                     63:            when BRIAN_MANDOLIN:
                     64:                /* The defendant must be the player and within 2 spaces */
                     65:                if (ce(*defend_pos, hero) && dist < 9 && no_command == 0 &&
                     66:                    rnd(100) < 33) {
                     67:                    if (!save(VS_MAGIC, &player, -4) &&
                     68:                        !ISWEARING(R_ALERT)) {
                     69:                        msg("Some beautiful music enthralls you.");
                     70:                        no_command += FREEZETIME;
                     71:                    }
                     72:                    else msg("You wince at a sour note.");
                     73:                    return(TRUE);
                     74:                }
                     75:            when GERYON_HORN:
                     76:                /* The defendant must be the player and within 2 spaces */
                     77:                if (ce(*defend_pos, hero) && dist < 9 &&
                     78:                    (off(player, ISFLEE) || player.t_dest != &monster->t_pos)
                     79:                    && rnd(100) < 33) {
                     80:                    if (!ISWEARING(R_HEROISM) &&
                     81:                        !save(VS_MAGIC, &player, -4)) {
                     82:                            turn_on(player, ISFLEE);
                     83:                            player.t_dest = &monster->t_pos;
                     84:                            msg("A shrill blast terrifies you.");
                     85:                    }
                     86:                    else msg("A shrill blast sends chills up your spine.");
                     87:                    return(TRUE);
                     88:                }
                     89:        }
                     90:     }
                     91:     return(FALSE);
                     92: }
                     93:  
                     94: /*
                     95:  * add something to the contents of something else
                     96:  * bag: the holder of the items
                     97:  * item: the item to put inside
                     98:  */
                     99: void
                    100: put_contents(struct object *bag, struct linked_list *item)
                    101: {
                    102:     register struct linked_list *titem;
                    103:     register struct object *tobj;
                    104:
                    105:     bag->o_ac++;
                    106:     tobj = OBJPTR(item);
                    107:     for (titem = bag->contents; titem != NULL; titem = next(titem)) {
                    108:        if ((OBJPTR(titem))->o_which == tobj->o_which)
                    109:            break;
                    110:     }
                    111:     if (titem == NULL) {       /* if not a duplicate put at beginning */
                    112:        attach(bag->contents, item);
                    113:     }
                    114:     else {
                    115:        item->l_prev = titem;
                    116:        item->l_next = titem->l_next;
                    117:        if (next(titem) != NULL)
                    118:            (titem->l_next)->l_prev = item;
                    119:        titem->l_next = item;
                    120:     }
                    121: }
                    122: 
                    123: /*
                    124:  * remove something from something else
                    125:  * bag: the holder of the items
                    126:  */
                    127: void
                    128: take_contents(struct object *bag, struct linked_list *item)
                    129: {
                    130:
                    131:     if (bag->o_ac <= 0) {
                    132:        msg("Nothing to take out");
                    133:        return;
                    134:     }
                    135:     bag->o_ac--;
                    136:     detach(bag->contents, item);
                    137:     if (!add_pack(item, FALSE, NULL))
                    138:        put_contents(bag, item);
                    139: }
                    140:
                    141: 
                    142: void
                    143: do_bag(struct linked_list *item)
                    144: {
                    145:
                    146:     register struct linked_list *titem = NULL;
                    147:     register struct object *obj;
                    148:     bool doit = TRUE;
                    149:
                    150:     obj = OBJPTR(item);
                    151:     while (doit) {
                    152:        msg("What do you want to do? (* for a list): ");
                    153:        mpos = 0;
                    154:        switch (readchar()) {
                    155:            case EOF:
                    156:            case ESCAPE:
                    157:                msg ("");
                    158:                doit = FALSE;
                    159:            when '1':
                    160:                inventory(obj->contents, ALL);
                    161:
                    162:            when '2':
                    163:                if (obj->o_ac >= MAXCONTENTS) {
                    164:                    msg("the %s is full", m_magic[obj->o_which].mi_name);
                    165:                    break;
                    166:                }
                    167:                switch (obj->o_which) {
                    168:                case MM_BEAKER: titem = get_item(pack, "put in", POTION);
                    169:                when MM_BOOK:   titem = get_item(pack, "put in", SCROLL);
                    170:                }
                    171:                if (titem == NULL)
                    172:                    break;
                    173:                detach(pack, titem);
                    174:                inpack--;
                    175:                put_contents(obj, titem);
                    176:
                    177:            when '3':
                    178:                titem = get_item(obj->contents,"take out",ALL);
                    179:                if (titem == NULL)
                    180:                    break;
                    181:                take_contents(obj, titem);
                    182:
                    183:            when '4':
                    184:                switch (obj->o_which) {
                    185:                case MM_BEAKER:
                    186:                    titem = get_item(obj->contents,"quaff",ALL);
                    187:                    if (titem == NULL)
                    188:                        break;
                    189:                    obj->o_ac--;
                    190:                    detach(obj->contents, titem);
                    191:                    quaff((OBJPTR(titem))->o_which,
                    192:                          (OBJPTR(titem))->o_flags & (ISCURSED | ISBLESSED),
                    193:                          TRUE);
                    194:                    o_discard(titem);
                    195:                when MM_BOOK:
                    196:                    if (on(player, ISBLIND)) {
                    197:                        msg("You can't see to read anything");
                    198:                        break;
                    199:                    }
                    200:                    titem = get_item(obj->contents,"read",ALL);
                    201:                    if (titem == NULL)
                    202:                        break;
                    203:                    obj->o_ac--;
                    204:                    detach(obj->contents, titem);
                    205:                    read_scroll((OBJPTR(titem))->o_which,
                    206:                                (OBJPTR(titem))->o_flags & (ISCURSED|ISBLESSED),
                    207:                                TRUE);
                    208:                    o_discard(titem);
                    209:                }
                    210:                doit = FALSE;
                    211:
                    212:            otherwise:
                    213:                wclear(hw);
                    214:                touchwin(hw);
                    215:                mvwaddstr(hw,0,0,"The following operations are available:");
                    216:                mvwaddstr(hw,2,0,"[1]\tInventory\n");
                    217:                wprintw(hw,"[2]\tPut something in the %s\n",
                    218:                        m_magic[obj->o_which].mi_name);
                    219:                wprintw(hw,"[3]\tTake something out of the %s\n",
                    220:                        m_magic[obj->o_which].mi_name);
                    221:                switch(obj->o_which) {
                    222:                    case MM_BEAKER: waddstr(hw,"[4]\tQuaff a potion\n");
                    223:                    when MM_BOOK:   waddstr(hw,"[4]\tRead a scroll\n");
                    224:                }
                    225:                waddstr(hw,"[ESC]\tLeave this menu\n");
                    226:                mvwaddstr(hw, LINES-1, 0, spacemsg);
                    227:                draw(hw);
                    228:                wait_for (hw,' ');
                    229:                clearok(cw, TRUE);
                    230:                touchwin(cw);
                    231:        }
                    232:     }
                    233: }
                    234: 
                    235: void
                    236: do_panic(void)
                    237: {
                    238:     register int x,y;
                    239:     register struct linked_list *mon;
                    240:     register struct thing *th;
                    241:
                    242:     for (x = hero.x-2; x <= hero.x+2; x++) {
                    243:        for (y = hero.y-2; y <= hero.y+2; y++) {
                    244:            if (y < 1 || x < 0 || y > LINES - 3  || x > COLS - 1)
                    245:                continue;
                    246:            if (isalpha(mvwinch(mw, y, x))) {
                    247:                if ((mon = find_mons(y, x)) != NULL) {
                    248:                    th = THINGPTR(mon);
                    249:                    if (!on(*th, ISUNDEAD) && !save(VS_MAGIC, th, 0)) {
                    250:                        turn_on(*th, ISFLEE);
                    251:                        turn_on(*th, WASTURNED);
                    252:
                    253:                        /* If monster was suffocating, stop it */
                    254:                        if (on(*th, DIDSUFFOCATE)) {
                    255:                            turn_off(*th, DIDSUFFOCATE);
                    256:                            extinguish(suffocate);
                    257:                        }
                    258:
                    259:                        /* If monster held us, stop it */
                    260:                        if (on(*th, DIDHOLD) && (--hold_count == 0))
                    261:                                turn_off(player, ISHELD);
                    262:                        turn_off(*th, DIDHOLD);
                    263:                    }
                    264:                    runto(th, &hero);
                    265:                }
                    266:            }
                    267:        }
                    268:     }
                    269: }
                    270: 
                    271: /*
                    272:  * print miscellaneous magic bonuses
                    273:  */
                    274: char *
                    275: misc_name(struct object *obj)
                    276: {
                    277:     static char buf[LINELEN];
                    278:     char buf1[LINELEN];
                    279:
                    280:     buf[0] = '\0';
                    281:     buf1[0] = '\0';
                    282:     if (!(obj->o_flags & ISKNOW))
                    283:        return (m_magic[obj->o_which].mi_name);
                    284:     switch (obj->o_which) {
                    285:        case MM_BRACERS:
                    286:        case MM_PROTECT:
                    287:            strcat(buf, num(obj->o_ac, 0));
                    288:            strcat(buf, " ");
                    289:     }
                    290:     switch (obj->o_which) {
                    291:        case MM_G_OGRE:
                    292:        case MM_G_DEXTERITY:
                    293:        case MM_JEWEL:
                    294:        case MM_STRANGLE:
                    295:        case MM_R_POWERLESS:
                    296:        case MM_DANCE:
                    297:            if (obj->o_flags & ISCURSED)
                    298:                strcat(buf, "cursed ");
                    299:     }
                    300:     strcat(buf, m_magic[obj->o_which].mi_name);
                    301:     switch (obj->o_which) {
                    302:        case MM_JUG:
                    303:            if (obj->o_ac == JUG_EMPTY)
                    304:                strcat(buf1, " [empty]");
                    305:            else if (p_know[obj->o_ac])
                    306:                sprintf(buf1, " [containing a potion of %s (%s)]",
                    307:                        p_magic[obj->o_ac].mi_name,
                    308:                        p_colors[obj->o_ac]);
                    309:            else sprintf(buf1, " [containing a%s %s liquid]",
                    310:                        vowelstr(p_colors[obj->o_ac]),
                    311:                        p_colors[obj->o_ac]);
                    312:        when MM_BEAKER:
                    313:        case MM_BOOK: {
                    314:            sprintf(buf1, " [containing %d]", obj->o_ac);
                    315:        }
                    316:        when MM_OPEN:
                    317:        case MM_HUNGER:
                    318:            sprintf(buf1, " [%d ring%s]", obj->o_charges,
                    319:                          obj->o_charges == 1 ? "" : "s");
                    320:        when MM_DRUMS:
                    321:            sprintf(buf1, " [%d beat%s]", obj->o_charges,
                    322:                          obj->o_charges == 1 ? "" : "s");
                    323:        when MM_DISAPPEAR:
                    324:        case MM_CHOKE:
                    325:            sprintf(buf1, " [%d pinch%s]", obj->o_charges,
                    326:                          obj->o_charges == 1 ? "" : "es");
                    327:        when MM_KEOGHTOM:
                    328:            sprintf(buf1, " [%d application%s]", obj->o_charges,
                    329:                          obj->o_charges == 1 ? "" : "s");
                    330:        when MM_SKILLS:
                    331:            switch (obj->o_ac) {
                    332:            case C_MAGICIAN:    strcpy(buf1, " [magic user]");
                    333:            when C_FIGHTER:     strcpy(buf1, " [fighter]");
                    334:            when C_CLERIC:      strcpy(buf1, " [cleric]");
                    335:            when C_THIEF:       strcpy(buf1, " [thief]");
                    336:            }
                    337:     }
                    338:     strcat (buf, buf1);
                    339:     return buf;
                    340: }
                    341: 
                    342: void
                    343: use_emori(void)
                    344: {
                    345:     char selection;    /* Cloak function */
                    346:     int state = 0;     /* Menu state */
                    347:
                    348:     msg("What do you want to do? (* for a list): ");
                    349:     do {
                    350:        selection = tolower(readchar());
                    351:        switch (selection) {
                    352:            case '*':
                    353:              if (state != 1) {
                    354:                wclear(hw);
                    355:                touchwin(hw);
                    356:                mvwaddstr(hw, 2, 0,  "[1] Fly\n[2] Stop flying\n");
                    357:                waddstr(hw,          "[3] Turn invisible\n[4] Turn Visible\n");
                    358:                mvwaddstr(hw, 0, 0, "What do you want to do? ");
                    359:                draw(hw);
                    360:                state = 1;      /* Now in prompt window */
                    361:              }
                    362:              break;
                    363:
                    364:            case ESCAPE:
                    365:                if (state == 1) {
                    366:                    clearok(cw, TRUE); /* Set up for redraw */
                    367:                    touchwin(cw);
                    368:                }
                    369:                msg("");
                    370:
                    371:                after = FALSE;
                    372:                return;
                    373:
                    374:            when '1':
                    375:            case '2':
                    376:            case '3':
                    377:            case '4':
                    378:                if (state == 1) {       /* In prompt window */
                    379:                    clearok(cw, TRUE); /* Set up for redraw */
                    380:                    touchwin(cw);
                    381:                }
                    382:
                    383:                msg("");
                    384:
                    385:                state = 2;      /* Finished */
                    386:                break;
                    387:
                    388:            default:
                    389:                if (state == 1) {       /* In the prompt window */
                    390:                    mvwaddstr(hw, 0, 0,
                    391:                                "Please enter a selection between 1 and 4:  ");
                    392:                    draw(hw);
                    393:                }
                    394:                else {  /* Normal window */
                    395:                    mpos = 0;
                    396:                    msg("Please enter a selection between 1 and 4:  ");
                    397:                }
                    398:        }
                    399:     } while (state != 2);
                    400:
                    401:     /* We now must have a selection between 1 and 4 */
                    402:     switch (selection) {
                    403:        case '1':       /* Fly */
                    404:            if (on(player, ISFLY)) {
                    405:                extinguish(land);       /* Extinguish in case of potion */
                    406:                msg("%slready flying.", terse ? "A" : "You are a");
                    407:            }
                    408:            else {
                    409:                msg("You feel lighter than air!");
                    410:                turn_on(player, ISFLY);
                    411:            }
                    412:        when '2':       /* Stop flying */
                    413:            if (off(player, ISFLY))
                    414:                msg("%sot flying.", terse ? "N" : "You are n");
                    415:            else {
                    416:                if (find_slot(land))
                    417:                    msg("%sot flying by the cloak.",
                    418:                        terse ? "N" : "You are n");
                    419:                else land();
                    420:            }
                    421:        when '3':       /* Turn invisible */
                    422:            if (off(player, ISINVIS)) {
                    423:                turn_on(player, ISINVIS);
                    424:                msg("You have a tingling feeling all over your body");
                    425:                PLAYER = IPLAYER;
                    426:                light(&hero);
                    427:            }
                    428:            else {
                    429:                extinguish(appear);     /* Extinguish in case of potion */
                    430:                extinguish(dust_appear);/* dust of disappearance        */
                    431:                msg("%slready invisible.", terse ? "A" : "You are a");
                    432:            }
                    433:        when '4':       /* Turn visible */
                    434:            if (off(player, ISINVIS))
                    435:                msg("%sot invisible.", terse ? "N" : "You are n");
                    436:            else {
                    437:                if (find_slot(appear) || find_slot(dust_appear))
                    438:                    msg("%sot invisible by the cloak.",
                    439:                        terse ? "N" : "You are n");
                    440:                else appear();
                    441:            }
                    442:     }
                    443: }
                    444: 
                    445: void
                    446: use_mm(int which)
                    447: {
                    448:     register struct object *obj = NULL;
                    449:     register struct linked_list *item = NULL;
                    450:     bool cursed, blessed, is_mm;
                    451:     char buf[LINELEN];
                    452:
                    453:     cursed = FALSE;
                    454:     is_mm = FALSE;
                    455:
                    456:     if (which < 0) {   /* A real miscellaneous magic item  */
                    457:        is_mm = TRUE;
                    458:        item = get_item(pack, "use", USEABLE);
                    459:        /*
                    460:         * Make certain that it is a micellaneous magic item
                    461:         */
                    462:        if (item == NULL)
                    463:            return;
                    464:
                    465:        obj = OBJPTR(item);
                    466:        cursed = (obj->o_flags & ISCURSED) != 0;
                    467:        blessed = (obj->o_flags & ISBLESSED) != 0;
                    468:        which = obj->o_which;
                    469:     }
                    470:
                    471:     if (obj->o_type == RELIC) {                /* An artifact */
                    472:        is_mm = FALSE;
                    473:        switch (obj->o_which) {
                    474:            case EMORI_CLOAK:
                    475:                use_emori();
                    476:            when BRIAN_MANDOLIN:
                    477:                /* Put monsters around us to sleep */
                    478:                read_scroll(S_HOLD, 0, FALSE);
                    479:            when GERYON_HORN:
                    480:                /* Chase close monsters away */
                    481:                msg("The horn blasts a shrill tone.");
                    482:                do_panic();
                    483:            when HEIL_ANKH:
                    484:            case YENDOR_AMULET:
                    485:                /* Nothing happens by this mode */
                    486:                msg("Nothing happens.");
                    487:        }
                    488:     }
                    489:     else switch (which) {              /* Miscellaneous Magic */
                    490:        /*
                    491:         * the jug of alchemy manufactures potions when you drink
                    492:         * the potion it will make another after a while
                    493:         */
                    494:        case MM_JUG:
                    495:            if (obj->o_ac == JUG_EMPTY) {
                    496:                msg("The jug is empty");
                    497:                break;
                    498:            }
                    499:            quaff (obj->o_ac, 0, FALSE);
                    500:            obj->o_ac = JUG_EMPTY;
                    501:            fuse (alchemy, obj, ALCHEMYTIME, AFTER);
                    502:            if (!(obj->o_flags & ISKNOW))
                    503:                whatis(item);
                    504:
                    505:        /*
                    506:         * the beaker of plentiful potions is used to hold potions
                    507:         * the book of infinite spells is used to hold scrolls
                    508:         */
                    509:        when MM_BEAKER:
                    510:        case MM_BOOK:
                    511:            do_bag(item);
                    512:
                    513:        /*
                    514:         * the chime of opening opens up secret doors
                    515:         */
                    516:        when MM_OPEN:
                    517:        {
                    518:            register struct linked_list *exit;
                    519:            register struct room *rp;
                    520:            register coord *cp;
                    521:
                    522:            if (obj->o_charges <= 0) {
                    523:                msg("The chime is cracked!");
                    524:                break;
                    525:            }
                    526:            obj->o_charges--;
                    527:            msg("chime... chime... hime... ime... me... e...");
                    528:            if ((rp = roomin(&hero)) == NULL) {
                    529:                search(FALSE, TRUE); /* Non-failing search for door */
                    530:                break;
                    531:            }
                    532:            for (exit = rp->r_exit; exit != NULL; exit = next(exit)) {
                    533:                cp = DOORPTR(exit);
                    534:                if (winat(cp->y, cp->x) == SECRETDOOR) {
                    535:                    mvaddch (cp->y, cp->x, DOOR);
                    536:                    if (cansee (cp->y, cp->x))
                    537:                        mvwaddch(cw, cp->y, cp->x, DOOR);
                    538:                }
                    539:            }
                    540:        }
                    541:
                    542:        /*
                    543:         * the chime of hunger just makes the hero hungry
                    544:         */
                    545:        when MM_HUNGER:
                    546:            if (obj->o_charges <= 0) {
                    547:                msg("The chime is cracked!");
                    548:                break;
                    549:            }
                    550:            obj->o_charges--;
                    551:            food_left = MORETIME + 5;
                    552:            msg(terse ? "Getting hungry" : "You are starting to get hungry");
                    553:            hungry_state = F_HUNGRY;
                    554:            aggravate();
                    555:
                    556:        /*
                    557:         * the drums of panic make all creatures within two squares run
                    558:         * from the hero in panic unless they save or they are mindless
                    559:         * undead
                    560:         */
                    561:        when MM_DRUMS:
                    562:            if (obj->o_charges <= 0) {
                    563:                msg("The drum is broken!");
                    564:                break;
                    565:            }
                    566:            obj->o_charges--;
                    567:        /*
                    568:         * dust of disappearance makes the player invisible for a while
                    569:         */
                    570:        when MM_DISAPPEAR:
                    571:            m_know[MM_DISAPPEAR] = TRUE;
                    572:            if (obj->o_charges <= 0) {
                    573:                msg("No more dust!");
                    574:                break;
                    575:            }
                    576:            obj->o_charges--;
                    577:            msg("aaAAACHOOOooo. Cough. Cough. Sneeze. Sneeze.");
                    578:            if (!find_slot(dust_appear)) {
                    579:                turn_on(player, ISINVIS);
                    580:                fuse(dust_appear, 0, DUSTTIME, AFTER);
                    581:                PLAYER = IPLAYER;
                    582:                light(&hero);
                    583:            }
                    584:            else lengthen(dust_appear, DUSTTIME);
                    585:
                    586:        /*
                    587:         * dust of choking and sneezing can kill the hero if he misses
                    588:         * the save
                    589:         */
                    590:        when MM_CHOKE:
                    591:            m_know[MM_CHOKE] = TRUE;
                    592:            if (obj->o_charges <= 0) {
                    593:                msg("No more dust!");
                    594:                break;
                    595:            }
                    596:            obj->o_charges--;
                    597:            msg("aaAAACHOOOooo. Cough. Cough. Sneeze. Sneeze.");
                    598:            if (!save(VS_POISON, &player, 0)) {
                    599:                msg ("You choke to death!!! --More--");
                    600:                pstats.s_hpt = -1; /* in case he hangs up the phone */
                    601:                wait_for(cw,' ');
                    602:                death(D_CHOKE);
                    603:            }
                    604:            else {
                    605:                msg("You begin to cough and choke uncontrollably");
                    606:                if (find_slot(unchoke))
                    607:                    lengthen(unchoke, DUSTTIME);
                    608:                else
                    609:                    fuse(unchoke, 0, DUSTTIME, AFTER);
                    610:                turn_on(player, ISHUH);
                    611:                turn_on(player, ISBLIND);
                    612:                light(&hero);
                    613:            }
                    614:
                    615:        when MM_KEOGHTOM:
                    616:            /*
                    617:             * this is a very powerful healing ointment
                    618:             * but it takes a while to put on...
                    619:             */
                    620:            if (obj->o_charges <= 0) {
                    621:                msg("The jar is empty!");
                    622:                break;
                    623:            }
                    624:            obj->o_charges--;
                    625:            waste_time();
                    626:            if (on(player, HASDISEASE)) {
                    627:                extinguish(cure_disease);
                    628:                cure_disease();
                    629:                msg(terse ? "You feel yourself improving."
                    630:                          : "You begin to feel yourself improving again.");
                    631:            }
                    632:            if (on(player, HASINFEST)) {
                    633:                turn_off(player, HASINFEST);
                    634:                infest_dam = 0;
                    635:                msg(terse ? "You feel yourself improving."
                    636:                          : "You begin to feel yourself improving again.");
                    637:            }
                    638:            if (on(player, DOROT)) {
                    639:                msg("You feel your skin returning to normal.");
                    640:                turn_off(player, DOROT);
                    641:            }
                    642:            pstats.s_hpt += roll(pstats.s_lvl, 6);
                    643:            if (pstats.s_hpt > max_stats.s_hpt)
                    644:                pstats.s_hpt = max_stats.s_hpt;
                    645:            sight();
                    646:            msg("You begin to feel much better.");
                    647:
                    648:        /*
                    649:         * The book has a character class associated with it.
                    650:         * if your class matches that of the book, it will raise your
                    651:         * level by one. If your class does not match the one of the book,
                    652:         * it change your class to that of book.
                    653:         * Note that it takes a while to read.
                    654:         */
                    655:        when MM_SKILLS:
                    656:            detach (pack, item);
                    657:            inpack--;
                    658:            waste_time();
                    659:            waste_time();
                    660:            waste_time();
                    661:            waste_time();
                    662:            waste_time();
                    663:            if (obj->o_ac == player.t_ctype) {
                    664:                msg("You feel more skillful");
                    665:                raise_level(TRUE);
                    666:            }
                    667:            else {
                    668:                /*
                    669:                 * reset his class and then use check_level to reset hit
                    670:                 * points and the right level for his exp pts
                    671:                 * drop exp pts by 10%
                    672:                 */
                    673:                long save;
                    674:
                    675:                msg("You feel like a whole new person!");
                    676:                /*
                    677:                 * if he becomes a thief he has to have leather armor
                    678:                 */
                    679:                if (obj->o_ac == C_THIEF                        &&
                    680:                    cur_armor != NULL                           &&
                    681:                    cur_armor->o_which != LEATHER               &&
                    682:                    cur_armor->o_which != STUDDED_LEATHER )
                    683:                        cur_armor->o_which = STUDDED_LEATHER;
                    684:                /*
                    685:                 * if he's changing from a fighter then may have to change
                    686:                 * his sword since only fighter can use two-handed
                    687:                 * and bastard swords
                    688:                 */
                    689:                if (player.t_ctype == C_FIGHTER                 &&
                    690:                    cur_weapon != NULL                          &&
                    691:                    cur_weapon->o_type == WEAPON                &&
                    692:                   (cur_weapon->o_which== BASWORD               ||
                    693:                    cur_weapon->o_which== TWOSWORD ))
                    694:                        cur_weapon->o_which = SWORD;
                    695:
                    696:                /*
                    697:                 * if he was a thief then take out the trap_look() daemon
                    698:                 */
                    699:                if (player.t_ctype == C_THIEF)
                    700:                    kill_daemon(trap_look);
                    701:                /*
                    702:                 * if he becomes a thief then add the trap_look() daemon
                    703:                 */
                    704:                if (obj->o_ac == C_THIEF)
                    705:                    start_daemon(trap_look, 0, AFTER);
                    706:                char_type = player.t_ctype = obj->o_ac;
                    707:                save = pstats.s_hpt;
                    708:                max_stats.s_hpt = pstats.s_hpt = 0;
                    709:                max_stats.s_lvl = pstats.s_lvl = 0;
                    710:                max_stats.s_exp = pstats.s_exp -= pstats.s_exp/10;
                    711:                check_level(TRUE);
                    712:                if (pstats.s_hpt > save) /* don't add to current hits */
                    713:                    pstats.s_hpt = save;
                    714:            }
                    715:
                    716:        otherwise:
                    717:            msg("What a strange magic item you have!");
                    718:     }
                    719:     status(FALSE);
                    720:     if (is_mm && m_know[which] && m_guess[which]) {
                    721:        free(m_guess[which]);
                    722:        m_guess[which] = NULL;
                    723:     }
                    724:     else if (is_mm &&
                    725:             !m_know[which] &&
                    726:             askme &&
                    727:             (obj->o_flags & ISKNOW) == 0 &&
                    728:             m_guess[which] == NULL) {
                    729:        msg(terse ? "Call it: " : "What do you want to call it? ");
                    730:        if (get_str(buf, msgw) == NORM) {
                    731:            m_guess[which] = new((unsigned int) strlen(buf) + 1);
                    732:            strcpy(m_guess[which], buf);
                    733:        }
                    734:     }
                    735:     if (item != NULL && which == MM_SKILLS)
                    736:        o_discard(item);
                    737:     updpack(TRUE);
                    738: }

CVSweb