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

Annotation of early-roguelike/arogue7/move.c, Revision 1.1.1.1

1.1       rubenllo    1: /*
                      2:  * move.c  -  Hero movement commands
                      3:  *
                      4:  * Advanced Rogue
                      5:  * Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
                      6:  * All rights reserved.
                      7:  *
                      8:  * Based on "Rogue: Exploring the Dungeons of Doom"
                      9:  * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
                     10:  * All rights reserved.
                     11:  *
                     12:  * See the file LICENSE.TXT for full copyright and licensing information.
                     13:  */
                     14:
                     15: /*
                     16:  * Hero movement commands
                     17:  *
                     18:  */
                     19:
                     20: #include "curses.h"
                     21: #include <ctype.h>
                     22: #include <string.h>
                     23: #include "rogue.h"
                     24: #ifdef PC7300
                     25: #include "menu.h"
                     26: #endif
                     27:
                     28: /*
                     29:  * Used to hold the new hero position
                     30:  */
                     31:
                     32: static coord nh;
                     33:
                     34: static char Moves[3][3] = {
                     35:     { 'y', 'k', 'u' },
                     36:     { 'h', '.', 'l' },
                     37:     { 'b', 'j', 'n' }
                     38: };
                     39: 
                     40: /*
                     41:  * be_trapped:
                     42:  *     The guy stepped on a trap.... Make him pay.
                     43:  */
                     44:
                     45: char
                     46: be_trapped(struct thing *th, coord *tc)
                     47: {
                     48:     register struct trap *tp;
                     49:     register char ch, *mname = "";
                     50:     register bool is_player = (th == &player),
                     51:                  can_see;
                     52:     register struct linked_list *mitem = NULL;
                     53:     register struct thing *mp;
                     54:
                     55:
                     56:     /* Can the player see the creature? */
                     57:     can_see = (cansee(tc->y, tc->x) && (is_player || !invisible(th)));
                     58:
                     59:     tp = trap_at(tc->y, tc->x);
                     60:     /*
                     61:      * if he's wearing boots of elvenkind, he won't set off the trap
                     62:      * unless its a magic pool (they're not really traps)
                     63:      */
                     64:     if (is_player                                      &&
                     65:        cur_misc[WEAR_BOOTS] != NULL                    &&
                     66:        cur_misc[WEAR_BOOTS]->o_which == MM_ELF_BOOTS   &&
                     67:        tp->tr_type != POOL)
                     68:            return '\0';
                     69:
                     70:     /*
                     71:      * if the creature is flying then it won't set off the trap
                     72:      */
                     73:      if (on(*th, ISFLY))
                     74:        return '\0';
                     75:
                     76:     tp->tr_flags |= ISFOUND;
                     77:
                     78:     if (!is_player) {
                     79:        mitem = find_mons(th->t_pos.y, th->t_pos.x);
                     80:        mname = monster_name(th);
                     81:     }
                     82:     else {
                     83:        count = running = FALSE;
                     84:        mvwaddch(cw, tp->tr_pos.y, tp->tr_pos.x, tp->tr_type);
                     85:     }
                     86:     switch (ch = tp->tr_type) {
                     87:        case TRAPDOOR:
                     88:            if (is_player) {
                     89:                level++;
                     90:                pstats.s_hpt -= roll(1, 10);
                     91:                if (pstats.s_hpt <= 0) death(D_FALL);
                     92:                new_level(NORMLEV);
                     93:                msg("You fell into a trap!");
                     94:            }
                     95:            else {
                     96:                if (can_see) msg("%s fell into a trap!", prname(mname, TRUE));
                     97:
                     98:                /*
                     99:                 * See if the fall killed the monster
                    100:                 * don't let a UNIQUE die since it might have an artifact
                    101:                 * that we need
                    102:                 */
                    103:                if (off(*th,ISUNIQUE) && (th->t_stats.s_hpt-=roll(1,10)) <= 0){
                    104:                    killed(mitem, FALSE, FALSE, FALSE);
                    105:                }
                    106:                else {  /* Just move monster to next level */
                    107:                    check_residue(th);
                    108:
                    109:                    /* Erase the monster from the old position */
                    110:                    if (isalpha(mvwinch(cw, th->t_pos.y, th->t_pos.x)))
                    111:                        mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch);
                    112:                    mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
                    113:
                    114:                    /* let him summon on next lvl */
                    115:                    if (on (*th, HASSUMMONED)) {
                    116:                            turn_off(*th, HASSUMMONED);
                    117:                            turn_on(*th, CANSUMMON);
                    118:                    }
                    119:                    turn_on(*th,ISELSEWHERE);
                    120:                    detach(mlist, mitem);
                    121:                    attach(tlist, mitem);       /* remember him next level */
                    122:
                    123:                    /* Make sure that no one is still chasing us */
                    124:                    for (mitem = mlist; mitem != NULL; mitem = next(mitem)) {
                    125:                        mp = THINGPTR(mitem);
                    126:                        if (mp->t_dest == &th->t_pos) {
                    127:                            mp->t_dest = &hero;
                    128:                            mp->t_wasshot = FALSE;
                    129:                            turn_off(*mp, ISFLEE);      /* Don't run away! */
                    130:                        }
                    131:                    }
                    132:
                    133:                    /* Make sure we were not chasing a monster here */
                    134:                    th->t_dest = &hero;
                    135:                    if (on(*th, ISFRIENDLY), turn_off(*th, ISFLEE));
                    136:                }
                    137:            }
                    138:        when BEARTRAP:
                    139:            if (is_stealth(th)) {
                    140:                if (is_player) msg("You pass a bear trap.");
                    141:                else if (can_see) msg("%s passes a bear trap.",
                    142:                                      prname(mname, TRUE));
                    143:            }
                    144:            else {
                    145:                th->t_no_move += movement(&player) * BEARTIME;
                    146:                th->t_action = A_FREEZE;
                    147:                if (is_player) msg("You are caught in a bear trap.");
                    148:                else if (can_see) msg("%s is caught in a bear trap.",
                    149:                                        prname(mname, TRUE));
                    150:            }
                    151:        when SLEEPTRAP:
                    152:            if (is_player) {
                    153:                msg("A strange white mist envelops you.");
                    154:                if (!ISWEARING(R_ALERT)) {
                    155:                    msg("You fall asleep.");
                    156:                    player.t_no_move += movement(&player) * SLEEPTIME;
                    157:                    player.t_action = A_FREEZE;
                    158:                }
                    159:            }
                    160:            else {
                    161:                if (can_see)
                    162:                    msg("A strange white mist envelops %s.",
                    163:                        prname(mname, FALSE));
                    164:                if (on(*th, ISUNDEAD)) {
                    165:                    if (can_see)
                    166:                        msg("The mist doesn't seem to affect %s.",
                    167:                           prname(mname, FALSE));
                    168:                }
                    169:                else {
                    170:                    th->t_no_move += movement(th) * SLEEPTIME;
                    171:                    th->t_action = A_FREEZE;
                    172:                }
                    173:            }
                    174:        when ARROWTRAP:
                    175:            if (swing(th->t_ctype, th->t_stats.s_lvl-1, th->t_stats.s_arm, 1))
                    176:            {
                    177:                if (is_player) {
                    178:                    msg("Oh no! An arrow shot you.");
                    179:                    if ((pstats.s_hpt -= roll(1, 6)) <= 0) {
                    180:                        msg("The arrow killed you.");
                    181:                        death(D_ARROW);
                    182:                    }
                    183:                }
                    184:                else {
                    185:                    if (can_see)
                    186:                        msg("An arrow shot %s.", prname(mname, FALSE));
                    187:                    if ((th->t_stats.s_hpt -= roll(1, 6)) <= 0) {
                    188:                        if (can_see)
                    189:                            msg("The arrow killed %s.", prname(mname, FALSE));
                    190:                        killed(mitem, FALSE, FALSE, TRUE);
                    191:                    }
                    192:                }
                    193:            }
                    194:            else
                    195:            {
                    196:                register struct linked_list *item;
                    197:                register struct object *arrow;
                    198:
                    199:                if (is_player) msg("An arrow shoots past you.");
                    200:                else if (can_see)
                    201:                          msg("An arrow shoots by %s.", prname(mname, FALSE));
                    202:                item = new_item(sizeof *arrow);
                    203:                arrow = OBJPTR(item);
                    204:                arrow->o_type = WEAPON;
                    205:                arrow->contents = NULL;
                    206:                arrow->o_which = ARROW;
                    207:                arrow->o_hplus = rnd(3) - 1;
                    208:                arrow->o_dplus = rnd(3) - 1;
                    209:                init_weapon(arrow, ARROW);
                    210:                arrow->o_count = 1;
                    211:                arrow->o_pos = *tc;
                    212:                arrow->o_mark[0] = '\0';
                    213:                fall(item, FALSE);
                    214:            }
                    215:        when TELTRAP:
                    216:            if (is_player) teleport();
                    217:            else {
                    218:                register int rm;
                    219:                struct room *old_room;  /* old room of monster */
                    220:
                    221:                /*
                    222:                 * Erase the monster from the old position
                    223:                 */
                    224:                if (isalpha(mvwinch(cw, th->t_pos.y, th->t_pos.x)))
                    225:                    mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch);
                    226:                mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
                    227:                /*
                    228:                 * check to see if room should go dark
                    229:                 */
                    230:                if (on(*th, HASFIRE)) {
                    231:                    old_room=roomin(&th->t_pos);
                    232:                    if (old_room != NULL) {
                    233:                        register struct linked_list *fire_item;
                    234:
                    235:                        for (fire_item = old_room->r_fires; fire_item != NULL;
                    236:                             fire_item = next(fire_item)) {
                    237:                            if (THINGPTR(fire_item) == th) {
                    238:                                detach(old_room->r_fires, fire_item);
                    239:                                destroy_item(fire_item);
                    240:
                    241:                                if (old_room->r_fires == NULL) {
                    242:                                    old_room->r_flags &= ~HASFIRE;
                    243:                                    if (can_see) light(&hero);
                    244:                                }
                    245:                            }
                    246:                        }
                    247:                    }
                    248:                }
                    249:
                    250:                /* Get a new position */
                    251:                do {
                    252:                    rm = rnd_room();
                    253:                    rnd_pos(&rooms[rm], &th->t_pos);
                    254:                } until(winat(th->t_pos.y, th->t_pos.x) == FLOOR);
                    255:
                    256:                /* Put it there */
                    257:                mvwaddch(mw, th->t_pos.y, th->t_pos.x, th->t_type);
                    258:                th->t_oldch = CCHAR( mvwinch(cw, th->t_pos.y, th->t_pos.x) );
                    259:                /*
                    260:                 * check to see if room that creature appears in should
                    261:                 * light up
                    262:                 */
                    263:                if (on(*th, HASFIRE)) {
                    264:                    register struct linked_list *fire_item;
                    265:
                    266:                    fire_item = creat_item();
                    267:                    ldata(fire_item) = (char *) th;
                    268:                    attach(rooms[rm].r_fires, fire_item);
                    269:
                    270:                    rooms[rm].r_flags |= HASFIRE;
                    271:                    if(cansee(th->t_pos.y, th->t_pos.x) &&
                    272:                       next(rooms[rm].r_fires) == NULL)
                    273:                        light(&hero);
                    274:                }
                    275:                if (can_see)
                    276:                    msg("%s seems to have disappeared!", prname(mname, TRUE));
                    277:            }
                    278:        when DARTTRAP:
                    279:            if (swing(th->t_ctype, th->t_stats.s_lvl+1, th->t_stats.s_arm, 1)) {
                    280:                if (is_player) {
                    281:                    msg("A small dart just hit you in the shoulder.");
                    282:                    if ((pstats.s_hpt -= roll(1, 4)) <= 0) {
                    283:                        msg("The dart killed you.");
                    284:                        death(D_DART);
                    285:                    }
                    286:
                    287:                    /* Now the poison */
                    288:                    if (!save(VS_POISON, &player, 0)) {
                    289:                        /* 75% chance it will do point damage - else strength */
                    290:                        if (rnd(100) < 75) {
                    291:                            pstats.s_hpt /= 2;
                    292:                            if (pstats.s_hpt == 0) death(D_POISON);
                    293:                        }
                    294:                        else if (!ISWEARING(R_SUSABILITY))
                    295:                                chg_str(-1);
                    296:                    }
                    297:                }
                    298:                else {
                    299:                    if (can_see)
                    300:                        msg("A small dart just hit %s in the shoulder.",
                    301:                                prname(mname, FALSE));
                    302:                    if ((th->t_stats.s_hpt -= roll(1,4)) <= 0) {
                    303:                        if (can_see)
                    304:                            msg("The dart killed %s.", prname(mname, FALSE));
                    305:                        killed(mitem, FALSE, FALSE, TRUE);
                    306:                    }
                    307:                    if (!save(VS_POISON, th, 0)) {
                    308:                        th->t_stats.s_hpt /= 2;
                    309:                        if (th->t_stats.s_hpt <= 0) {
                    310:                            if (can_see)
                    311:                                msg("The dart killed %s.", prname(mname,FALSE));
                    312:                            killed(mitem, FALSE, FALSE, TRUE);
                    313:                        }
                    314:                    }
                    315:                }
                    316:            }
                    317:            else {
                    318:                if (is_player)
                    319:                    msg("A small dart whizzes by your ear and vanishes.");
                    320:                else if (can_see)
                    321:                    msg("A small dart whizzes by %s's ear and vanishes.",
                    322:                        prname(mname, FALSE));
                    323:            }
                    324:         when POOL: {
                    325:            register int i;
                    326:
                    327:            i = rnd(100);
                    328:            if (is_player) {
                    329:                if ((tp->tr_flags & ISGONE)) {
                    330:                    if (i < 30) {
                    331:                        teleport();        /* teleport away */
                    332:                        pool_teleport = TRUE;
                    333:                    }
                    334:                    else if((i < 45) && level > 2) {
                    335:                        level -= rnd(2) + 1;
                    336:                        cur_max = level;
                    337:                        new_level(NORMLEV);
                    338:                        pool_teleport = TRUE;
                    339:                        msg("You here a faint groan from below.");
                    340:                    }
                    341:                    else if(i < 70) {
                    342:                        level += rnd(4) + 1;
                    343:                        new_level(NORMLEV);
                    344:                        pool_teleport = TRUE;
                    345:                        msg("You find yourself in strange surroundings.");
                    346:                    }
                    347:                    else if(i > 95) {
                    348:                        msg("Oh no!!! You drown in the pool!!! --More--");
                    349:                        wait_for(' ');
                    350:                        death(D_DROWN);
                    351:                    }
                    352:                }
                    353:            }
                    354:            else {
                    355:                if (i < 60) {
                    356:                    if (can_see) {
                    357:                        /* Drowns */
                    358:                        if (i < 30)
                    359:                            msg("%s drowned in the pool!", prname(mname, TRUE));
                    360:
                    361:                        /* Teleported to another level */
                    362:                        else msg("%s disappeared!", prname(mname, TRUE));
                    363:                    }
                    364:                    killed(mitem, FALSE, FALSE, TRUE);
                    365:                }
                    366:            }
                    367:        }
                    368:     when MAZETRAP:
                    369:        if (is_player) {
                    370:            pstats.s_hpt -= roll(1, 10);
                    371:            level++;
                    372:            msg("You fell through a trap door!");
                    373:            if (pstats.s_hpt <= 0) death(D_FALL);
                    374:            new_level(MAZELEV);
                    375:            msg("You are surrounded by twisty passages!");
                    376:        }
                    377:        else {
                    378:            if (can_see) msg("%s fell into a trap!", prname(mname, TRUE));
                    379:
                    380:            if (on(*th, ISUNIQUE)) {
                    381:                    check_residue(th);
                    382:
                    383:                    /* Erase the monster from the old position */
                    384:                    if (isalpha(mvwinch(cw, th->t_pos.y, th->t_pos.x)))
                    385:                        mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch);
                    386:                    mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
                    387:
                    388:                    /* let him summon on next lvl */
                    389:                    if (on (*th, HASSUMMONED)) {
                    390:                            turn_off(*th, HASSUMMONED);
                    391:                            turn_on(*th, CANSUMMON);
                    392:                    }
                    393:                    turn_on(*th,ISELSEWHERE);
                    394:                    detach(mlist, mitem);
                    395:                    attach(tlist, mitem);       /* remember him next level */
                    396:
                    397:                    /* Make sure that no one is still chasing us */
                    398:                    for (mitem = mlist; mitem != NULL; mitem = next(mitem)) {
                    399:                        mp = THINGPTR(mitem);
                    400:                        if (mp->t_dest == &th->t_pos) {
                    401:                            mp->t_dest = &hero;
                    402:                            mp->t_wasshot = FALSE;
                    403:                            turn_off(*mp, ISFLEE);      /* Don't run away! */
                    404:                        }
                    405:                    }
                    406:
                    407:                    /* Make sure we were not chasing a monster here */
                    408:                    th->t_dest = &hero;
                    409:                    if (on(*th, ISFRIENDLY), turn_off(*th, ISFLEE));
                    410:            }
                    411:            else
                    412:                    killed(mitem, FALSE, FALSE, FALSE);
                    413:        }
                    414:     }
                    415:
                    416:     /* Move the cursor back onto the hero */
                    417:     wmove(cw, hero.y, hero.x);
                    418:
                    419:     md_flushinp();
                    420:     return(ch);
                    421: }
                    422: 
                    423: /*
                    424:  * blue_light:
                    425:  *     magically light up a room (or level or make it dark)
                    426:  */
                    427:
                    428: bool
                    429: blue_light(bool blessed, bool cursed)
                    430: {
                    431:     register struct room *rp;
                    432:     bool ret_val=FALSE;        /* Whether or not affect is known */
                    433:
                    434:     rp = roomin(&hero);        /* What room is hero in? */
                    435:
                    436:     /* Darken the room if the magic is cursed */
                    437:     if (cursed) {
                    438:        if ((rp == NULL) || !lit_room(rp)) msg(nothing);
                    439:        else {
                    440:            rp->r_flags |= ISDARK;
                    441:            if (!lit_room(rp) && (levtype != OUTSIDE || !daytime))
                    442:                msg("The %s suddenly goes dark.",
                    443:                        levtype == OUTSIDE ? "area" : "room");
                    444:            else msg(nothing);
                    445:            ret_val = TRUE;
                    446:        }
                    447:     }
                    448:     else {
                    449:        ret_val = TRUE;
                    450:        if (rp && !lit_room(rp) &&
                    451:            (levtype != OUTSIDE || !daytime)) {
                    452:            addmsg("The %s is lit", levtype == OUTSIDE ? "area" : "room");
                    453:            if (!terse)
                    454:                addmsg(" by a %s blue light.",
                    455:                    blessed ? "bright" : "shimmering");
                    456:            endmsg();
                    457:        }
                    458:        else if (winat(hero.y, hero.x) == PASSAGE)
                    459:            msg("The corridor glows %sand then fades",
                    460:                    blessed ? "brightly " : "");
                    461:        else {
                    462:            ret_val = FALSE;
                    463:            msg(nothing);
                    464:        }
                    465:        if (blessed) {
                    466:            register int i;     /* Index through rooms */
                    467:
                    468:            for (i=0; i<MAXROOMS; i++)
                    469:                rooms[i].r_flags &= ~ISDARK;
                    470:        }
                    471:        else if (rp) rp->r_flags &= ~ISDARK;
                    472:     }
                    473:
                    474:     /*
                    475:      * Light the room and put the player back up
                    476:      */
                    477:     light(&hero);
                    478:     mvwaddch(cw, hero.y, hero.x, PLAYER);
                    479:     return(ret_val);
                    480: }
                    481: 
                    482: /*
                    483:  * corr_move:
                    484:  *     Check to see that a move is legal.  If so, return correct character.
                    485:  *     If not, if player came from a legal place, then try to turn him.
                    486:  */
                    487:
                    488: void
                    489: corr_move(int dy, int dx)
                    490: {
                    491:     int legal=0;               /* Number of legal alternatives */
                    492:     register int y, x,         /* Indexes though possible positions */
                    493:                 locy, locx;    /* Hold delta of chosen location */
                    494:
                    495:     /* New position */
                    496:     nh.y = hero.y + dy;
                    497:     nh.x = hero.x + dx;
                    498:
                    499:     /* If it is a legal move, just return */
                    500:     if (nh.x >= 0 && nh.x < cols && nh.y > 0 && nh.y < lines - 2) {
                    501:
                    502:        switch (winat(nh.y, nh.x)) {
                    503:            case WALL:
                    504:            case '|':
                    505:            case '-':
                    506:                break;
                    507:            default:
                    508:                if (diag_ok(&hero, &nh, &player))
                    509:                        return;
                    510:        }
                    511:     }
                    512:
                    513:     /* Check legal places surrounding the player -- ignore previous position */
                    514:     for (y = hero.y - 1; y <= hero.y + 1; y++) {
                    515:        if (y < 1 || y > lines - 3)
                    516:            continue;
                    517:        for (x = hero.x - 1; x <= hero.x + 1; x++) {
                    518:            /* Ignore borders of the screen */
                    519:            if (x < 0 || x > cols - 1)
                    520:                continue;
                    521:
                    522:            /*
                    523:             * Ignore where we came from, where we are, and where we couldn't go
                    524:             */
                    525:            if ((x == hero.x - dx && y == hero.y - dy) ||
                    526:                (x == hero.x + dx && y == hero.y + dy) ||
                    527:                (x == hero.x && y == hero.y))
                    528:                continue;
                    529:
                    530:            switch (winat(y, x)) {
                    531:                case WALL:
                    532:                case '|':
                    533:                case '-':
                    534:                    break;
                    535:                default:
                    536:                    nh.y = y;
                    537:                    nh.x = x;
                    538:                    if (diag_ok(&hero, &nh, &player)) {
                    539:                        legal++;
                    540:                        locy = y - (hero.y - 1);
                    541:                        locx = x - (hero.x - 1);
                    542:                    }
                    543:            }
                    544:        }
                    545:     }
                    546:
                    547:     /* If we have 2 or more legal moves, make no change */
                    548:     if (legal != 1) {
                    549:        return;
                    550:     }
                    551:
                    552:     runch = Moves[locy][locx];
                    553:
                    554:     /*
                    555:      * For mazes, pretend like it is the beginning of a new run at each turn
                    556:      * in order to get the lighting correct.
                    557:      */
                    558:     if (levtype == MAZELEV) firstmove = TRUE;
                    559:     return;
                    560: }
                    561: 
                    562: /*
                    563:  * dip_it:
                    564:  *     Dip an object into a magic pool
                    565:  */
                    566: void
                    567: dip_it(void)
                    568: {
                    569:        reg struct linked_list *what;
                    570:        reg struct object *ob;
                    571:        reg struct trap *tp;
                    572:        reg int wh, i;
                    573:
                    574:        tp = trap_at(hero.y,hero.x);
                    575:        if (tp == NULL || tp->tr_type != POOL) {
                    576:            msg("I see no shimmering pool here");
                    577:            return;
                    578:        }
                    579:        if (tp->tr_flags & ISGONE) {
                    580:            msg("This shimmering pool appears to have been used once already.");
                    581:            return;
                    582:        }
                    583:
                    584:        /* It takes 3 movement periods to dip something */
                    585:        if (player.t_action != C_DIP) {
                    586:            if ((what = get_item(pack, "dip", ALL, FALSE, FALSE)) == NULL) {
                    587:                msg("");
                    588:                after = FALSE;
                    589:                return;
                    590:            }
                    591:
                    592:            ob = OBJPTR(what);
                    593:            if (ob == cur_armor          ||
                    594:                ob == cur_misc[WEAR_BOOTS]       || ob == cur_misc[WEAR_JEWEL]   ||
                    595:                ob == cur_misc[WEAR_GAUNTLET] ||
                    596:                ob == cur_misc[WEAR_CLOAK]       ||
                    597:                ob == cur_misc[WEAR_BRACERS] ||
                    598:                ob == cur_misc[WEAR_NECKLACE]||
                    599:                ob == cur_ring[LEFT_1]   || ob == cur_ring[LEFT_2]       ||
                    600:                ob == cur_ring[LEFT_3]   || ob == cur_ring[LEFT_4]       ||
                    601:                ob == cur_ring[RIGHT_1]  || ob == cur_ring[RIGHT_2]      ||
                    602:                ob == cur_ring[RIGHT_3]  || ob == cur_ring[RIGHT_4]) {
                    603:                mpos = 0;
                    604:                msg("You'll have to take it off first.");
                    605:                return;
                    606:            }
                    607:
                    608:            player.t_using = what;      /* Remember what it is */
                    609:            player.t_action = C_DIP;    /* We are dipping */
                    610:            player.t_no_move = 3 * movement(&player);
                    611:            return;
                    612:        }
                    613:
                    614:        /* We have waited our time, let's dip it */
                    615:        what = player.t_using;
                    616:        player.t_using = NULL;
                    617:        player.t_action = A_NIL;
                    618:
                    619:        ob = OBJPTR(what);
                    620:
                    621:        tp->tr_flags |= ISGONE;
                    622:        if (ob != NULL) {
                    623:            wh = ob->o_which;
                    624:            ob->o_flags |= ISKNOW;
                    625:            i = rnd(100);
                    626:            switch(ob->o_type) {
                    627:                case WEAPON:
                    628:                    if(i < 50) {                /* enchant weapon here */
                    629:                        if ((ob->o_flags & ISCURSED) == 0) {
                    630:                                ob->o_hplus += 1;
                    631:                                ob->o_dplus += 1;
                    632:                        }
                    633:                        else {          /* weapon was prev cursed here */
                    634:                                ob->o_hplus = rnd(2);
                    635:                                ob->o_dplus = rnd(2);
                    636:                        }
                    637:                        ob->o_flags &= ~ISCURSED;
                    638:                        msg("The %s glows blue for a moment.",weaps[wh].w_name);
                    639:                    }
                    640:                    else if(i < 70) {   /* curse weapon here */
                    641:                        if ((ob->o_flags & ISCURSED) == 0) {
                    642:                                ob->o_hplus = -(rnd(2)+1);
                    643:                                ob->o_dplus = -(rnd(2)+1);
                    644:                        }
                    645:                        else {                  /* if already cursed */
                    646:                                ob->o_hplus--;
                    647:                                ob->o_dplus--;
                    648:                        }
                    649:                        ob->o_flags |= ISCURSED;
                    650:                        msg("The %s glows red for a moment.",weaps[wh].w_name);
                    651:                    }
                    652:                    else
                    653:                        msg(nothing);
                    654:                when ARMOR:
                    655:                    if (i < 50) {       /* enchant armor */
                    656:                        if((ob->o_flags & ISCURSED) == 0)
                    657:                            ob->o_ac -= rnd(2) + 1;
                    658:                        else
                    659:                            ob->o_ac = -rnd(3)+ armors[wh].a_class;
                    660:                        ob->o_flags &= ~ISCURSED;
                    661:                        msg("The %s glows blue for a moment",armors[wh].a_name);
                    662:                    }
                    663:                    else if(i < 75){    /* curse armor */
                    664:                        if ((ob->o_flags & ISCURSED) == 0)
                    665:                            ob->o_ac = rnd(3)+ armors[wh].a_class;
                    666:                        else
                    667:                            ob->o_ac += rnd(2) + 1;
                    668:                        ob->o_flags |= ISCURSED;
                    669:                        msg("The %s glows red for a moment.",armors[wh].a_name);
                    670:                    }
                    671:                    else
                    672:                        msg(nothing);
                    673:                when STICK: {
                    674:                    int j;
                    675:                    j = rnd(8) + 1;
                    676:                    if(i < 50) {                /* add charges */
                    677:                        ob->o_charges += j;
                    678:                        ws_know[wh] = TRUE;
                    679:                        if (ob->o_flags & ISCURSED)
                    680:                            ob->o_flags &= ~ISCURSED;
                    681:                        msg("The %s %s glows blue for a moment.",
                    682:                            ws_made[wh],ws_type[wh]);
                    683:                    }
                    684:                    else if(i < 65) {   /* remove charges */
                    685:                        if ((ob->o_charges -= i) < 0)
                    686:                            ob->o_charges = 0;
                    687:                        ws_know[wh] = TRUE;
                    688:                        if (ob->o_flags & ISBLESSED)
                    689:                            ob->o_flags &= ~ISBLESSED;
                    690:                        else
                    691:                            ob->o_flags |= ISCURSED;
                    692:                        msg("The %s %s glows red for a moment.",
                    693:                            ws_made[wh],ws_type[wh]);
                    694:                    }
                    695:                    else
                    696:                        msg(nothing);
                    697:                }
                    698:                when SCROLL:
                    699:                    s_know[wh] = TRUE;
                    700:                    msg("The '%s' scroll unfurls.",s_names[wh]);
                    701:                when POTION:
                    702:                    p_know[wh] = TRUE;
                    703:                    msg("The %s potion bubbles for a moment.",p_colors[wh]);
                    704:                when RING:
                    705:                    if(i < 50) {         /* enchant ring */
                    706:                        if ((ob->o_flags & ISCURSED) == 0)
                    707:                            ob->o_ac += rnd(2) + 1;
                    708:                        else
                    709:                            ob->o_ac = rnd(2) + 1;
                    710:                        ob->o_flags &= ~ISCURSED;
                    711:                    }
                    712:                    else if(i < 80) { /* curse ring */
                    713:                        if ((ob->o_flags & ISCURSED) == 0)
                    714:                            ob->o_ac = -(rnd(2) + 1);
                    715:                        else
                    716:                            ob->o_ac -= (rnd(2) + 1);
                    717:                        ob->o_flags |= ISCURSED;
                    718:                    }
                    719:                    r_know[wh] = TRUE;
                    720:                    msg("The %s ring vibrates for a moment.",r_stones[wh]);
                    721:                when MM:
                    722:                    m_know[wh] = TRUE;
                    723:                    switch (ob->o_which) {
                    724:                    case MM_BRACERS:
                    725:                    case MM_PROTECT:
                    726:                        if(i < 50) {     /* enchant item */
                    727:                            if ((ob->o_flags & ISCURSED) == 0)
                    728:                                ob->o_ac += rnd(2) + 1;
                    729:                            else
                    730:                                ob->o_ac = rnd(2) + 1;
                    731:                            ob->o_flags &= ~ISCURSED;
                    732:                        }
                    733:                        else if(i < 80) { /* curse item */
                    734:                            if ((ob->o_flags & ISCURSED) == 0)
                    735:                                ob->o_ac = -(rnd(2) + 1);
                    736:                            else
                    737:                                ob->o_ac -= (rnd(2) + 1);
                    738:                            ob->o_flags |= ISCURSED;
                    739:                        }
                    740:                        msg("The item vibrates for a moment.");
                    741:                    when MM_CHOKE:
                    742:                    case MM_DISAPPEAR:
                    743:                        ob->o_ac = 0;
                    744:                        msg ("The dust dissolves in the pool!");
                    745:                    }
                    746:                otherwise:
                    747:                msg("The pool bubbles for a moment.");
                    748:            }
                    749:            updpack(FALSE, &player);
                    750:        }
                    751:        else
                    752:            msg(nothing);
                    753: }
                    754: 
                    755: /*
                    756:  * do_move:
                    757:  *     Check to see that a move is legal.  If it is handle the
                    758:  * consequences (fighting, picking up, etc.)
                    759:  */
                    760:
                    761: void
                    762: do_move(int dy, int dx)
                    763: {
                    764:     register struct room *rp, *orp;
                    765:     register char ch;
                    766:     struct linked_list *item;
                    767:     register struct thing *tp = NULL;
                    768:     coord old_hero;
                    769:     register int wasfirstmove, moved, num_hits;
                    770:     bool changed=FALSE;        /* Did we switch places with a friendly monster? */
                    771:
                    772:     wasfirstmove = firstmove;
                    773:     firstmove = FALSE;
                    774:     curprice = -1;             /* if in trading post, we've moved off obj */
                    775:
                    776:     /*
                    777:      * Do a confused move (maybe)
                    778:      */
                    779:     if (player.t_action == A_NIL &&
                    780:        ((on(player, ISHUH) && rnd(100) < 80) ||
                    781:         (on(player, ISDANCE) && rnd(100) < 80) ||
                    782:         (ISWEARING(R_DELUSION) && rnd(100) < 25)))
                    783:        /* Get a random move */
                    784:        nh = *rndmove(&player);
                    785:     else {
                    786:        nh.y = hero.y + dy;
                    787:        nh.x = hero.x + dx;
                    788:     }
                    789:
                    790:     /*
                    791:      * Check if he tried to move off the screen or make an illegal
                    792:      * diagonal move, and stop him if he did.
                    793:      */
                    794:     if (nh.x < 0 || nh.x > cols-1 || nh.y < 1 || nh.y >= lines - 2
                    795:        || !diag_ok(&hero, &nh, &player))
                    796:     {
                    797:        after = running = FALSE;
                    798:        player.t_action = A_NIL;
                    799:        return;
                    800:     }
                    801:     if (running && ce(hero, nh))
                    802:        after = running = FALSE;
                    803:     ch = CCHAR( winat(nh.y, nh.x) );
                    804:
                    805:     /* Take care of hero trying to move close to something frightening */
                    806:     if (on(player, ISFLEE)) {
                    807:        if (rnd(100) < 10) {
                    808:            turn_off(player, ISFLEE);
                    809:            msg("You regain your composure.");
                    810:        }
                    811:        else if (DISTANCE(nh.y, nh.x, player.t_dest->y, player.t_dest->x) <
                    812:                 DISTANCE(hero.y, hero.x, player.t_dest->y, player.t_dest->x)) {
                    813:                        running = FALSE;
                    814:                        msg("You are too terrified to move that way");
                    815:                        player.t_action = A_NIL;
                    816:                        player.t_no_move = movement(&player);
                    817:                        return;
                    818:        }
                    819:     }
                    820:
                    821:     /* If we want to move to a monster, see what it is */
                    822:     if (isalpha(ch)) {
                    823:        item = find_mons(nh.y, nh.x);
                    824:        if (item == NULL) {
                    825:            debug("Cannot find monster in move.");
                    826:            player.t_action = A_NIL;
                    827:            return;
                    828:        }
                    829:        tp = THINGPTR(item);
                    830:     }
                    831:
                    832:     /*
                    833:      * Take care of hero being held.  If the player is being held, he
                    834:      * can't move unless he is either attacking a non-friendly monster
                    835:      * or attacking a friendly monster that can't move.
                    836:      */
                    837:     if (on(player, ISHELD) &&
                    838:        (!isalpha(ch) || (on(*tp, ISFRIENDLY) && off(*tp, ISHELD)))) {
                    839:        msg("You are being held.");
                    840:        player.t_action = A_NIL;
                    841:        return;
                    842:     }
                    843:
                    844:     /* See if we have to wait for our movement rate */
                    845:     if (player.t_action == A_NIL) {
                    846:        after = FALSE;
                    847:        firstmove = wasfirstmove;       /* Remember if this is first move */
                    848:        player.t_no_move = movement(&player);
                    849:        if (player.t_ctype == C_MONK)
                    850:            player.t_no_move -= pstats.s_lvl/6;
                    851:        if (on(player, ISFLY))
                    852:            player.t_no_move /= 2; /* If flying, speed him up */
                    853:
                    854:        if (player.t_no_move < 1) player.t_no_move = 1;
                    855:
                    856:        /* Remember our action */
                    857:        player.t_action = Moves[dy+1][dx+1];
                    858:        return;
                    859:     }
                    860:
                    861:     /* Now let's forget the old move and just do it */
                    862:     player.t_action = A_NIL;
                    863:
                    864:     /* If we're moving onto a friendly monster, let's change places. */
                    865:     if (isalpha(ch) && on(*tp, ISFRIENDLY) && off(*tp, ISHELD)) {
                    866:        coord tpos,     /* Where monster may have been going */
                    867:              current;  /* Current hero position */
                    868:        int action;     /* The monster's action */
                    869:
                    870:        current = hero;
                    871:        tpos = tp->t_newpos;
                    872:        action = tp->t_action;
                    873:
                    874:        /* Disrupt whatever our friend was doing */
                    875:        tp->t_action = A_NIL;
                    876:
                    877:        /* Tentatively move us to where he is */
                    878:        hero = tp->t_pos;
                    879:
                    880:        /* See if we can move him to where we were */
                    881:        tp->t_newpos = current;
                    882:        do_chase(tp);
                    883:
                    884:        /* Did we succeed? */
                    885:        if (ce(tp->t_pos, current)) {
                    886:            /* Reset our idea of what ch is */
                    887:            ch = CCHAR( winat(nh.y, nh.x) );
                    888:
                    889:            /* Let it be known that we made the switch */
                    890:            changed = TRUE;
                    891:            old_hero = current;
                    892:
                    893:            /* Make the monster think it didn't move */
                    894:            tp->t_oldpos = current;
                    895:            tp->t_doorgoal = NULL;
                    896:
                    897:            /* Let the player know something funny happened. */
                    898:            msg("What a sidestep!");
                    899:        }
                    900:        else {
                    901:            /* Restore things -- we couldn't move */
                    902:            hero = current;
                    903:            tp->t_newpos = tpos;
                    904:            tp->t_action = action;
                    905:        }
                    906:     }
                    907:
                    908:     /* assume he's not in a wall */
                    909:     if (!isalpha(ch)) turn_off(player, ISINWALL);
                    910:
                    911:     switch (ch) {
                    912:        case '|':
                    913:        case '-':
                    914:            if (levtype == OUTSIDE) {
                    915:                hero = nh;
                    916:                new_level(OUTSIDE);
                    917:                return;
                    918:            }
                    919:        case WALL:
                    920:        case SECRETDOOR:
                    921:            if (off(player, CANINWALL) || running) {
                    922:                after = running = FALSE;
                    923:
                    924:                /* Light if finishing run */
                    925:                if (levtype == MAZELEV && lit_room(&rooms[0]))
                    926:                    look(FALSE, TRUE);
                    927:
                    928:                after = running = FALSE;
                    929:
                    930:                return;
                    931:            }
                    932:            turn_on(player, ISINWALL);
                    933:            break;
                    934:        case POOL:
                    935:            if (levtype == OUTSIDE) {
                    936:                lake_check(&nh);
                    937:                running = FALSE;
                    938:                break;
                    939:            }
                    940:        case MAZETRAP:
                    941:            if (levtype == OUTSIDE) {
                    942:            running = FALSE;
                    943:            break;
                    944:        }
                    945:        case TRAPDOOR:
                    946:        case TELTRAP:
                    947:        case BEARTRAP:
                    948:        case SLEEPTRAP:
                    949:        case ARROWTRAP:
                    950:        case DARTTRAP:
                    951:            ch = be_trapped(&player, &nh);
                    952:            if (ch == TRAPDOOR || ch == TELTRAP ||
                    953:                pool_teleport  || ch == MAZETRAP) {
                    954:                pool_teleport = FALSE;
                    955:                return;
                    956:            }
                    957:            break;
                    958:        case GOLD:
                    959:        case POTION:
                    960:        case SCROLL:
                    961:        case FOOD:
                    962:        case WEAPON:
                    963:        case ARMOR:
                    964:        case RING:
                    965:        case MM:
                    966:        case RELIC:
                    967:        case STICK:
                    968:            running = FALSE;
                    969:            take = ch;
                    970:            break;
                    971:        case DOOR:
                    972:        case STAIRS:
                    973:        case POST:
                    974:            running = FALSE;
                    975:            break;
                    976:        default:
                    977:            break;
                    978:     }
                    979:
                    980:     if (isalpha(ch)) { /* if its a monster then fight it */
                    981:        /*
                    982:         * If we were running down a corridor and didn't start right
                    983:         * next to the critter, don't do anything.
                    984:         */
                    985:        if (running && wasfirstmove == FALSE && roomin(&hero) == NULL) {
                    986:            struct linked_list *item;
                    987:
                    988:            item = find_mons(nh.y, nh.x);
                    989:            if (item != NULL && !invisible(THINGPTR(item))) {
                    990:                after = running = FALSE;
                    991:                return;
                    992:            }
                    993:        }
                    994:
                    995:        /* We have to add time because we're attacking */
                    996:        player.t_no_move = FIGHTBASE;
                    997:        player.t_no_move += weap_move(&player, cur_weapon);
                    998:        if (on(player, ISHASTE))
                    999:                player.t_no_move /= 2;
                   1000:        else if (on(player, ISSLOW))
                   1001:                player.t_no_move *= 2;
                   1002:
                   1003:        /* We may attack faster if we're high enough level
                   1004:         * and the right class
                   1005:         */
                   1006:        switch(player.t_ctype) {
                   1007:            case C_FIGHTER: num_hits = player.t_stats.s_lvl/9  + 1;
                   1008:            when C_PALADIN: num_hits = player.t_stats.s_lvl/12 + 1;
                   1009:            when C_RANGER:  num_hits = player.t_stats.s_lvl/13 + 1;
                   1010:            when C_MONK:    if(cur_weapon) num_hits= 1;
                   1011:                            else           num_hits= player.t_stats.s_lvl/5 + 1;
                   1012:            otherwise:      num_hits = 1;
                   1013:        }
                   1014:
                   1015:        /*
                   1016:         * The player has already moved the initial movement period.
                   1017:         * Let's add that in, do our division, and then subtract it
                   1018:         * out so that the total time is divided, not just the
                   1019:         * additional attack time.
                   1020:         */
                   1021:        moved = movement(&player),
                   1022:        player.t_no_move += moved;
                   1023:        player.t_no_move /= num_hits;
                   1024:        player.t_no_move -= moved;
                   1025:        running = FALSE;
                   1026:
                   1027:        /* Mark that we are attacking and save the attack coordinate */
                   1028:        player.t_action = A_ATTACK;
                   1029:        player.t_newpos = nh;
                   1030:        runch = Moves[dy+1][dx+1];      /* Remember the direction */
                   1031:
                   1032:        if (player.t_no_move <= 0) after = FALSE;
                   1033:        return;
                   1034:     }
                   1035:
                   1036:     /*
                   1037:      * if not fighting then move the hero
                   1038:      */
                   1039:     if (changed == FALSE) {
                   1040:        old_hero = hero;        /* Save hero's old position */
                   1041:        hero = nh;              /* Move the hero */
                   1042:     }
                   1043:     rp = roomin(&hero);
                   1044:     orp = roomin(&old_hero);
                   1045:
                   1046:     /* Unlight any possible cross-corridor */
                   1047:     if (levtype == MAZELEV) {
                   1048:        register bool call_light = FALSE;
                   1049:        register char wall_check;
                   1050:
                   1051:        if (wasfirstmove && lit_room(&rooms[0])) {
                   1052:            /* Are we moving out of a corridor? */
                   1053:            switch (runch) {
                   1054:                case 'h':
                   1055:                case 'l':
                   1056:                    if (old_hero.y + 1 < lines - 2) {
                   1057:                        wall_check = CCHAR( winat(old_hero.y + 1, old_hero.x) );
                   1058:                        if (!isrock(wall_check)) call_light = TRUE;
                   1059:                    }
                   1060:                    if (old_hero.y - 1 > 0) {
                   1061:                        wall_check = CCHAR( winat(old_hero.y - 1, old_hero.x) );
                   1062:                        if (!isrock(wall_check)) call_light = TRUE;
                   1063:                    }
                   1064:                    break;
                   1065:                case 'j':
                   1066:                case 'k':
                   1067:                    if (old_hero.x + 1 < cols) {
                   1068:                        wall_check = CCHAR( winat(old_hero.y, old_hero.x + 1) );
                   1069:                        if (!isrock(wall_check)) call_light = TRUE;
                   1070:                    }
                   1071:                    if (old_hero.x - 1 >= 0) {
                   1072:                        wall_check = CCHAR( winat(old_hero.y, old_hero.x - 1) );
                   1073:                        if (!isrock(wall_check)) call_light = TRUE;
                   1074:                    }
                   1075:                    break;
                   1076:                default:
                   1077:                    call_light = TRUE;
                   1078:            }
                   1079:            player.t_oldpos = old_hero;
                   1080:            if (call_light) light(&old_hero);
                   1081:        }
                   1082:     }
                   1083:
                   1084:     else if (orp != NULL && rp == NULL) {    /* Leaving a room -- darken it */
                   1085:        orp->r_flags |= FORCEDARK;      /* Fake darkness */
                   1086:        light(&old_hero);
                   1087:        orp->r_flags &= ~FORCEDARK;     /* Restore light state */
                   1088:     }
                   1089:     else if (rp != NULL && orp == NULL){/* Entering a room */
                   1090:        light(&hero);
                   1091:        if (rp->r_flags & ISTREAS)
                   1092:            wake_room(rp);
                   1093:     }
                   1094:     ch = CCHAR( winat(old_hero.y, old_hero.x) );
                   1095:     wmove(cw, unc(old_hero));
                   1096:     waddch(cw, ch);
                   1097:     wmove(cw, unc(hero));
                   1098:     waddch(cw, PLAYER);
                   1099: }
                   1100: 
                   1101: /*
                   1102:  * do_run:
                   1103:  *     Start the hero running
                   1104:  */
                   1105:
                   1106: void
                   1107: do_run(char ch)
                   1108: {
                   1109:     firstmove = TRUE;
                   1110:     running = TRUE;
                   1111:     after = FALSE;
                   1112:     runch = ch;
                   1113: }
                   1114: 
                   1115: /*
                   1116:  * getdelta:
                   1117:  *     Takes a movement character (eg. h, j, k, l) and returns the
                   1118:  *     y and x delta corresponding to it in the remaining arguments.
                   1119:  *     Returns TRUE if it could find it, FALSE otherwise.
                   1120:  */
                   1121: bool
                   1122: getdelta(char match, int *dy, int *dx)
                   1123: {
                   1124:     int y, x;
                   1125:
                   1126:     for (y = 0; y < 3; y++)
                   1127:        for (x = 0; x < 3; x++)
                   1128:            if (Moves[y][x] == match) {
                   1129:                *dy = y - 1;
                   1130:                *dx = x - 1;
                   1131:                return(TRUE);
                   1132:            }
                   1133:
                   1134:     return(FALSE);
                   1135: }
                   1136: 
                   1137: /*
                   1138:  * isatrap:
                   1139:  *     Returns TRUE if this character is some kind of trap
                   1140:  */
                   1141: bool
                   1142: isatrap(char ch)
                   1143: {
                   1144:        switch(ch) {
                   1145:                case DARTTRAP:
                   1146:                case TELTRAP:
                   1147:                case TRAPDOOR:
                   1148:                case ARROWTRAP:
                   1149:                case SLEEPTRAP:
                   1150:                case BEARTRAP:  return(TRUE);
                   1151:                case MAZETRAP:
                   1152:                case POOL:      return(levtype != OUTSIDE);
                   1153:                default:        return(FALSE);
                   1154:        }
                   1155: }
                   1156: 
                   1157: /*
                   1158:  * Called to illuminate a room.
                   1159:  * If it is dark, remove anything that might move.
                   1160:  */
                   1161:
                   1162: void
                   1163: light(coord *cp)
                   1164: {
                   1165:     register struct room *rp;
                   1166:     register int j, k, x, y;
                   1167:     register char ch, rch, sch;
                   1168:     register struct linked_list *item;
                   1169:     int jlow, jhigh, klow, khigh;      /* Boundaries of lit area */
                   1170:
                   1171:     if ((rp = roomin(cp)) != NULL) {
                   1172:        /*
                   1173:         * is he wearing ring of illumination?
                   1174:         */
                   1175:        if (&hero == cp && ISWEARING(R_LIGHT)) /* Must be hero's room */
                   1176:            rp->r_flags &= ~ISDARK;
                   1177:
                   1178:        /* If we are in a maze, don't look at the whole room (level) */
                   1179:        if (levtype == MAZELEV) {
                   1180:            int see_radius;
                   1181:
                   1182:            see_radius = 1;
                   1183:
                   1184:            /* If we are looking at the hero in a rock, broaden our sights */
                   1185:            if (&hero == cp || &player.t_oldpos == cp) {
                   1186:                ch = CCHAR( winat(hero.y, hero.x) );
                   1187:                if (isrock(ch)) see_radius = 2;
                   1188:                ch = CCHAR( winat(player.t_oldpos.y, player.t_oldpos.x) );
                   1189:                if (isrock(ch)) see_radius = 2;
                   1190:            }
                   1191:
                   1192:            jlow = max(0, cp->y - see_radius - rp->r_pos.y);
                   1193:            jhigh = min(rp->r_max.y, cp->y + see_radius + 1 - rp->r_pos.y);
                   1194:            klow = max(0, cp->x - see_radius - rp->r_pos.x);
                   1195:            khigh = min(rp->r_max.x, cp->x + see_radius + 1 - rp->r_pos.x);
                   1196:        }
                   1197:        else {
                   1198:            jlow = klow = 0;
                   1199:            jhigh = rp->r_max.y;
                   1200:            khigh = rp->r_max.x;
                   1201:        }
                   1202:        for (j = 0; j < rp->r_max.y; j++)
                   1203:        {
                   1204:            for (k = 0; k < rp->r_max.x; k++)
                   1205:            {
                   1206:                bool see_here, see_before;
                   1207:
                   1208:                /* Is this in the give area -- needed for maze */
                   1209:                if ((j < jlow || j >= jhigh) && (k < klow || k >= khigh))
                   1210:                    continue;
                   1211:
                   1212:                y = rp->r_pos.y + j;
                   1213:                x = rp->r_pos.x + k;
                   1214:
                   1215:                /*
                   1216:                 * If we are in a maze do not look at this area unless
                   1217:                 * we can see it from where we are or where we last were
                   1218:                 * (for erasing purposes).
                   1219:                 */
                   1220:                if (levtype == MAZELEV) {
                   1221:                    /* If we can't see it from here, could we see it before? */
                   1222:                    if ((see_here = maze_view(y, x)) == FALSE) {
                   1223:                        coord savhero;
                   1224:
                   1225:                        /* Could we see it from where we were? */
                   1226:                        savhero = hero;
                   1227:                        hero = player.t_oldpos;
                   1228:                        see_before = maze_view(y, x);
                   1229:                        hero = savhero;
                   1230:
                   1231:                        if (!see_before) continue;
                   1232:                    }
                   1233:                }
                   1234:
                   1235:                ch = show(y, x);
                   1236:                wmove(cw, y, x);
                   1237:                /*
                   1238:                 * Figure out how to display a secret door
                   1239:                 */
                   1240:                if (ch == SECRETDOOR) {
                   1241:                    if (j == 0 || j == rp->r_max.y - 1)
                   1242:                        ch = '-';
                   1243:                    else
                   1244:                        ch = '|';
                   1245:                }
                   1246:                /* For monsters, if they were previously not seen and
                   1247:                 * now can be seen, or vice-versa, make sure that will
                   1248:                 * happen.  This is for dark rooms as opposed to invisibility.
                   1249:                 *
                   1250:                 * Call winat() in the test because ch will not reveal
                   1251:                 * invisible monsters.
                   1252:                 */
                   1253:                if (isalpha(winat(y, x))) {
                   1254:                    struct thing *tp;   /* The monster */
                   1255:
                   1256:                    item = wake_monster(y, x);
                   1257:                    tp = THINGPTR(item);
                   1258:
                   1259:                    /* Previously not seen -- now can see it */
                   1260:                    if (tp->t_oldch == ' ' && cansee(tp->t_pos.y, tp->t_pos.x))
                   1261:                        tp->t_oldch = CCHAR( mvinch(y, x) );
                   1262:
                   1263:                    /* Previously seen -- now can't see it */
                   1264:                    else if (!cansee(tp->t_pos.y, tp->t_pos.x) &&
                   1265:                             roomin(&tp->t_pos) != NULL)
                   1266:                        switch (tp->t_oldch) {
                   1267:                            /*
                   1268:                             * Only blank it out if it is in a room and not
                   1269:                             * the border (or other wall) of the room.
                   1270:                             */
                   1271:                             case DOOR:
                   1272:                             case SECRETDOOR:
                   1273:                             case '-':
                   1274:                             case '|':
                   1275:                                break;
                   1276:
                   1277:                             otherwise:
                   1278:                                tp->t_oldch = ' ';
                   1279:                        }
                   1280:                }
                   1281:
                   1282:                /*
                   1283:                 * If the room is a dark room, we might want to remove
                   1284:                 * monsters and the like from it (since they might
                   1285:                 * move).
                   1286:                 * A dark room.
                   1287:                 */
                   1288:                if ((!lit_room(rp) && (levtype != OUTSIDE)) ||
                   1289:                    (levtype == OUTSIDE && !daytime) ||
                   1290:                    on(player, ISBLIND)         ||
                   1291:                    (rp->r_flags & FORCEDARK)   ||
                   1292:                    (levtype == MAZELEV && !see_here && see_before)) {
                   1293:                    sch = CCHAR( mvwinch(cw, y, x) );   /* What's seen */
                   1294:                    rch = CCHAR( mvinch(y, x) );        /* What's really there */
                   1295:                    switch (rch) {
                   1296:                        case DOOR:
                   1297:                        case SECRETDOOR:
                   1298:                        case STAIRS:
                   1299:                        case TRAPDOOR:
                   1300:                        case TELTRAP:
                   1301:                        case BEARTRAP:
                   1302:                        case SLEEPTRAP:
                   1303:                        case ARROWTRAP:
                   1304:                        case DARTTRAP:
                   1305:                        case MAZETRAP:
                   1306:                        case POOL:
                   1307:                        case POST:
                   1308:                        case '|':
                   1309:                        case '-':
                   1310:                        case WALL:
                   1311:                            if (isalpha(sch)) ch = rch;
                   1312:                            else if (sch != FLOOR) ch = sch;
                   1313:                            else ch = ' '; /* Hide undiscoverd things */
                   1314:                        when FLOOR:
                   1315:                            ch = ' ';
                   1316:                        otherwise:
                   1317:                            ch = ' ';
                   1318:                    }
                   1319:                    /* Take care of our magic bookkeeping. */
                   1320:                    switch (sch) {
                   1321:                        case MAGIC:
                   1322:                        case BMAGIC:
                   1323:                        case CMAGIC:
                   1324:                            ch = sch;
                   1325:                    }
                   1326:                }
                   1327:                mvwaddch(cw, y, x, ch);
                   1328:            }
                   1329:        }
                   1330:     }
                   1331: }
                   1332: 
                   1333: /*
                   1334:  * lit_room:
                   1335:  *     Called to see if the specified room is lit up or not.
                   1336:  */
                   1337:
                   1338: bool
                   1339: lit_room(struct room *rp)
                   1340: {
                   1341:     register struct linked_list *fire_item;
                   1342:     register struct thing *fire_creature;
                   1343:
                   1344:     if (!(rp->r_flags & ISDARK)) return(TRUE); /* A definitely lit room */
                   1345:
                   1346:     /* Is it lit by fire light? */
                   1347:     if (rp->r_flags & HASFIRE) {
                   1348:        switch ((int)levtype) {
                   1349:            case MAZELEV:
                   1350:                /* See if a fire creature is in line of sight */
                   1351:                for (fire_item = rp->r_fires; fire_item != NULL;
                   1352:                     fire_item = next(fire_item)) {
                   1353:                    fire_creature = THINGPTR(fire_item);
                   1354:                    if (maze_view(fire_creature->t_pos.y,
                   1355:                                  fire_creature->t_pos.x)) return(TRUE);
                   1356:                }
                   1357:
                   1358:                /* Couldn't find any in line-of-sight */
                   1359:                return(FALSE);
                   1360:
                   1361:            /* We should probably do something special for the outside */
                   1362:            otherwise:
                   1363:                return TRUE;
                   1364:        }
                   1365:     }
                   1366:     return(FALSE);
                   1367: }
                   1368: 
                   1369: /*
                   1370:  * movement:
                   1371:  *     Given a pointer to a player/monster structure, calculate the
                   1372:  *     movement rate for that character.
                   1373:  */
                   1374:
                   1375: short
                   1376: movement(struct thing *tp)
                   1377: {
                   1378:     register int result;
                   1379:     register int carry;                /* Percentage carried */
                   1380:
                   1381:     result = 0;
                   1382:
                   1383:     /* Adjust for armor (player only) */
                   1384:     if (tp == &player && cur_armor) {
                   1385:        int diff; /* Now armor class differs from normal one of same type */
                   1386:
                   1387:        /* Blessed armor adds less */
                   1388:        diff = cur_armor->o_ac - armors[cur_armor->o_which].a_class;
                   1389:        switch (cur_armor->o_which) {
                   1390:            case LEATHER:
                   1391:            case RING_MAIL:
                   1392:            case STUDDED_LEATHER:
                   1393:            case SCALE_MAIL:
                   1394:            case PADDED_ARMOR:
                   1395:                diff += 1;
                   1396:            when CHAIN_MAIL:
                   1397:            case SPLINT_MAIL:
                   1398:            case BANDED_MAIL:
                   1399:            case PLATE_MAIL:
                   1400:                diff += 2;
                   1401:            when PLATE_ARMOR:
                   1402:                diff += 3;
                   1403:            otherwise:
                   1404:                debug("forgot an armor in movement()");
                   1405:        }
                   1406:        if (diff < 0) diff = 0;
                   1407:        result += diff;
                   1408:
                   1409:     }
                   1410:
                   1411:     /* Adjust for the pack */
                   1412:     carry = 100 * tp->t_stats.s_pack / tp->t_stats.s_carry;
                   1413:     if (carry > 75) result++;
                   1414:
                   1415:     /* Get a bonus for dexterity */
                   1416:     result -= dext_plus(tp == &player ? dex_compute() : tp->t_stats.s_dext);
                   1417:
                   1418:     /* only allow adjust for the minus's */
                   1419:     if (result < 0) result = 0;
                   1420:     result += tp->t_movement; /* now add in movement rate */
                   1421:
                   1422:     /* Is the character slowed? */
                   1423:     if (on(*tp, ISSLOW) || on(*tp, ISDANCE)) result *= 2;
                   1424:
                   1425:     /* Is the character hasted? */
                   1426:     if (on(*tp, ISHASTE)) result /= 2;
                   1427:
                   1428:     /* We have a minimum of 1 */
                   1429:     if (result < 1) result = 1;
                   1430:
                   1431:     return(result);
                   1432: }
                   1433: 
                   1434: /*
                   1435:  * rndmove:
                   1436:  *     move in a random direction if the monster/person is confused
                   1437:  */
                   1438:
                   1439: coord *
                   1440: rndmove(struct thing *who)
                   1441: {
                   1442:     register int x, y;
                   1443:     register int ex, ey, nopen = 0;
                   1444:     static coord ret;  /* what we will be returning */
                   1445:     static coord dest;
                   1446:
                   1447:     ret = who->t_pos;
                   1448:     /*
                   1449:      * Now go through the spaces surrounding the player and
                   1450:      * set that place in the array to true if the space can be
                   1451:      * moved into
                   1452:      */
                   1453:     ey = ret.y + 1;
                   1454:     ex = ret.x + 1;
                   1455:     for (y = who->t_pos.y - 1; y <= ey; y++)
                   1456:        if (y > 0 && y < lines - 2)
                   1457:            for (x = who->t_pos.x - 1; x <= ex; x++)
                   1458:            {
                   1459:                if (x < 0 || x >= cols)
                   1460:                    continue;
                   1461:                if (step_ok(y, x, NOMONST, who) == TRUE)
                   1462:                {
                   1463:                    dest.y = y;
                   1464:                    dest.x = x;
                   1465:                    if (!diag_ok(&who->t_pos, &dest, who))
                   1466:                        continue;
                   1467:                    if (rnd(++nopen) == 0)
                   1468:                        ret = dest;
                   1469:                }
                   1470:            }
                   1471:     return &ret;
                   1472: }
                   1473:
                   1474:
                   1475: 
                   1476: #define TRAPTYPES 9            /* 9 total trap types that can be set */
                   1477: #define WIZARDTRAPS 3          /* Only wizards can set 3 of these */
                   1478:
                   1479: static char *trap_types[TRAPTYPES] = {
                   1480:     "Trap Door",
                   1481:     "Bear Trap",
                   1482:     "Sleep Trap",
                   1483:     "Arrow Trap",
                   1484:     "Teleport Trap",
                   1485:     "Dart Trap",
                   1486:     "Magic pool",
                   1487:     "Maze Trap",
                   1488:     "Trading Post"
                   1489: };
                   1490:
                   1491: #ifdef PC7300
                   1492: #define TRAPWIDTH 13   /* Length of longest named trap from above list */
                   1493: #define        TRAPPREFIX 4    /* Length of prefix (eg. "[9] ") */
                   1494: static menu_t Display;                         /* The menu structure */
                   1495: static mitem_t Dispitems[TRAPTYPES+1];         /* Info for each line */
                   1496: static char Displines[TRAPTYPES+1][TRAPWIDTH+TRAPPREFIX+1];
                   1497: #endif
                   1498:
                   1499: /*
                   1500:  * set_trap:
                   1501:  *     set a trap at (y, x) on screen.
                   1502:  */
                   1503:
                   1504: void
                   1505: set_trap(struct thing *tp, int y, int x)
                   1506: {
                   1507:     register bool is_player = (tp == &player);
                   1508:     register int selection = rnd(TRAPTYPES-WIZARDTRAPS) + '1';
                   1509:     register int i, num_traps;
                   1510:     register char ch, och;
                   1511:     int thief_bonus = 0;
                   1512:     int s_dext;
                   1513:
                   1514:     if (is_player && player.t_ctype != C_THIEF && player.t_ctype != C_ASSASIN) {
                   1515:        msg("Only thieves and assassins can set traps.");
                   1516:        return;
                   1517:     }
                   1518:     switch (och = CCHAR( mvinch(y, x) )) {
                   1519:        case WALL:
                   1520:        case FLOOR:
                   1521:        case PASSAGE:
                   1522:            break;
                   1523:        default:
                   1524:            if (is_player) msg("The trap failed!");
                   1525:            return;
                   1526:     }
                   1527:
                   1528:     if (is_player) {
                   1529:        int state = 0, /* 0 -> current screen, 1 -> prompt screen, 2 -> done */
                   1530:            units;     /* Number of movement units for the given trap */
                   1531:
                   1532:        if (player.t_action == C_SETTRAP) {
                   1533:            selection = player.t_selection;
                   1534:            player.t_selection = 0;
                   1535:            player.t_using = NULL;
                   1536:            player.t_action = A_NIL;
                   1537:        }
                   1538:        else {
                   1539:            msg("Which kind of trap do you wish to set? (* for a list): ");
                   1540:            num_traps = TRAPTYPES - (wizard ? 0 : WIZARDTRAPS);
                   1541:            do {
                   1542:                selection = tolower(readchar());
                   1543:                switch (selection) {
                   1544:                    case '*':
                   1545:                      if (state != 1) {
                   1546: #ifdef PC7300
                   1547:                        for (i=0; i<TRAPTYPES; i++) {
                   1548:                            /*
                   1549:                             * Add numbers so the player can use a
                   1550:                             * number later, if he knows it.  Let's
                   1551:                             * put the number on here instead of in
                   1552:                             * trap_types in case we want to drop it
                   1553:                             * later.
                   1554:                             */
                   1555:                            sprintf(Displines[i], "[%d] %s",
                   1556:                                        i+1, trap_types[i]);
                   1557:                            Dispitems[i].mi_name = Displines[i];
                   1558:                            Dispitems[i].mi_flags = 0;
                   1559:                            Dispitems[i].mi_val = i+'1';
                   1560:                        }
                   1561:
                   1562:                        /* Place an end marker for the items */
                   1563:                        Dispitems[num_traps].mi_name = 0;
                   1564:
                   1565:                        /* Set up the main menu structure */
                   1566:                        Display.m_label = "Trap Creation";
                   1567:                        Display.m_title = "Trap Types";
                   1568:                        Display.m_prompt = "Select a trap type or press Cancl.";
                   1569:                        Display.m_curptr = '\0';
                   1570:                        Display.m_markptr = '\0';
                   1571:                        Display.m_flags = 0;
                   1572:                        Display.m_selcnt = 1;
                   1573:                        Display.m_items = Dispitems;
                   1574:                        Display.m_curi = 0;
                   1575:
                   1576:                        /*
                   1577:                         * Try to display the menu.  If we don't have a local
                   1578:                         * terminal, the call will fail and we will just
                   1579:                         * continue with the normal mode.
                   1580:                         */
                   1581:                        if (menu(&Display) >= 0) {
                   1582:                            if (Display.m_selcnt == 0) {
                   1583:                                /* Cancelled menu */
                   1584:                                msg("");
                   1585:
                   1586:                                trap_tries--;   /* Don't count this one */
                   1587:                                after = FALSE;
                   1588:                                return;
                   1589:                            }
                   1590:                            selection = Display.m_curi->mi_val;
                   1591:                            state = 2;
                   1592:                            break;
                   1593:                        }
                   1594: #endif
                   1595:
                   1596:                        wclear(hw);
                   1597:                        touchwin(hw);
                   1598:                        for (i=0; i<num_traps; i++) {
                   1599:                            wmove(hw, i+2, 0);
                   1600:                            wprintw(hw, "[%d] %s", i+1, trap_types[i]);
                   1601:                        }
                   1602:                        mvwaddstr(hw, 0, 0,
                   1603:                                "Which kind of trap do you wish to set? ");
                   1604:
                   1605:                        if (menu_overlay)
                   1606:                            /*
                   1607:                             * Put out the selection.  The longest line is
                   1608:                             * the prompt line (39 characters long).
                   1609:                             */
                   1610:                            over_win(cw, hw, num_traps + 3, 41, 0, 39, '\0');
                   1611:                        else
                   1612:                            draw(hw);
                   1613:                        state = 1;      /* Now in prompt window */
                   1614:                      }
                   1615:                      break;
                   1616:
                   1617:                    case ESCAPE:
                   1618:                        if (state == 1) {
                   1619:                            clearok(cw, FALSE); /* Set up for redraw */
                   1620:                            touchwin(cw);
                   1621:                        }
                   1622:                        msg("");
                   1623:
                   1624:                        trap_tries--;   /* Don't count this one */
                   1625:                        after = FALSE;
                   1626:                        return;
                   1627:
                   1628:                    case '1':
                   1629:                    case '2':
                   1630:                    case '3':
                   1631:                    case '4':
                   1632:                    case '5':
                   1633:                    case '6':
                   1634:                    case '7':
                   1635:                    case '8':
                   1636:                    case '9':
                   1637:                        if (selection < '7' || wizard) {
                   1638:                            if (state == 1) {   /* In prompt window */
                   1639:                                clearok(cw, FALSE); /* Set up for redraw */
                   1640:                                touchwin(cw);
                   1641:                            }
                   1642:
                   1643:                            msg("");
                   1644:
                   1645:                            /*
                   1646:                             * Make sure there is a floor below us for trap
                   1647:                             * doors.
                   1648:                             */
                   1649:                            if (selection == '1' && level >= nfloors) {
                   1650:                                if (state == 1) draw(cw);
                   1651:                                msg("There is no level below this one.");
                   1652:                                return;
                   1653:                            }
                   1654:                            state = 2;  /* Finished */
                   1655:                            break;
                   1656:                        }
                   1657:
                   1658:                        /* Fall through for non-wizard, unusual trap case */
                   1659:                    default:
                   1660:                        if (state == 1) {       /* In the prompt window */
                   1661:                            wmove(hw, 0, 0);
                   1662:                            wprintw(hw,
                   1663:                                "Please enter a selection between 1 and %d:  ",
                   1664:                                num_traps);
                   1665:                            if (menu_overlay)
                   1666:                                /*
                   1667:                                 * Put out the selection.  The longest line is
                   1668:                                 * the prompt line (43 characters long).
                   1669:                                 */
                   1670:                                over_win(cw, hw, num_traps+3, 45, 0, 43, '\0');
                   1671:                            else
                   1672:                                draw(hw);
                   1673:                        }
                   1674:                        else {  /* Normal window */
                   1675:                            mpos = 0;
                   1676:                            msg("Please enter a selection between 1 and %d:  ",
                   1677:                                num_traps);
                   1678:                        }
                   1679:                }
                   1680:            } while (state != 2);
                   1681:
                   1682:            switch ((player.t_selection = selection)) {
                   1683:                case '1': units = 20;   /* Trap door */
                   1684:                when '2': units = 5;    /* Bear trap */
                   1685:                when '3': units = 6;    /* Sleeping gas trap */
                   1686:                when '4': units = 5;    /* Arrow trap */
                   1687:                when '5': units = 8;    /* Teleport trap */
                   1688:                when '6': units = 5;    /* Dart trap */
                   1689:                otherwise: units = 10;  /* Unknown trap */
                   1690:            }
                   1691:            player.t_no_move = units * movement(&player);
                   1692:            player.t_action = C_SETTRAP;
                   1693:            player.t_using = NULL;
                   1694:            return;
                   1695:        }
                   1696:     }
                   1697:
                   1698:     if (is_player && player.t_ctype == C_THIEF)   thief_bonus = 30;
                   1699:     if (is_player && player.t_ctype == C_ASSASIN) thief_bonus = 20;
                   1700:
                   1701:     s_dext = (tp == &player) ? dex_compute() : tp->t_stats.s_dext;
                   1702:
                   1703:     if (ntraps >= MAXTRAPS || ++trap_tries >= MAXTRPTRY || levtype == POSTLEV ||
                   1704:        rnd(80) >= (s_dext + tp->t_stats.s_lvl/2 + thief_bonus)) {
                   1705:        if (is_player) msg("The trap failed!");
                   1706:        return;
                   1707:     }
                   1708:
                   1709:     switch (selection) {
                   1710:        case '1': ch = TRAPDOOR;
                   1711:        when '2': ch = BEARTRAP;
                   1712:        when '3': ch = SLEEPTRAP;
                   1713:        when '4': ch = ARROWTRAP;
                   1714:        when '5': ch = TELTRAP;
                   1715:        when '6': ch = DARTTRAP;
                   1716:        when '7': ch = POOL;
                   1717:        when '8': ch = MAZETRAP;
                   1718:        when '9': ch = POST;
                   1719:     }
                   1720:
                   1721:     mvaddch(y, x, ch);
                   1722:     traps[ntraps].tr_show = och;
                   1723:     traps[ntraps].tr_type = ch;
                   1724:     traps[ntraps].tr_pos.y = y;
                   1725:     traps[ntraps].tr_pos.x = x;
                   1726:     if (is_player)
                   1727:        traps[ntraps].tr_flags = ISTHIEFSET;
                   1728:     if (ch == POOL || ch == POST) {
                   1729:        traps[ntraps].tr_flags |= ISFOUND;
                   1730:     }
                   1731:
                   1732:     ntraps++;
                   1733: }
                   1734: 
                   1735: /*
                   1736:  * show:
                   1737:  *     returns what a certain thing will display as to the un-initiated
                   1738:  */
                   1739:
                   1740: char
                   1741: show(int y, int x)
                   1742: {
                   1743:     register char ch = CCHAR( winat(y, x) );
                   1744:     register struct linked_list *it;
                   1745:     register struct thing *tp;
                   1746:
                   1747:     if (isatrap(ch)) {
                   1748:        register struct trap *trp = trap_at(y, x);
                   1749:
                   1750:        return (trp->tr_flags & ISFOUND) ? ch : trp->tr_show;
                   1751:     }
                   1752:     else if (isalpha(ch)) {
                   1753:        if ((it = find_mons(y, x)) == NULL) {
                   1754:            msg("Show:  Can't find monster in show (%d, %d)", y, x);
                   1755:            return(mvwinch(stdscr, y, x));
                   1756:        }
                   1757:        tp = THINGPTR(it);
                   1758:
                   1759:        if (on(*tp, ISDISGUISE)) ch = tp->t_disguise; /* As a mimic */
                   1760:
                   1761:        /* Hide invisible creatures */
                   1762:        else if (invisible(tp)) {
                   1763:            /* We can't see surprise-type creatures through "see invisible" */
                   1764:            if (off(player,CANSEE) || on(*tp,CANSURPRISE))
                   1765:                ch = CCHAR( mvwinch(stdscr, y, x) ); /* Invisible */
                   1766:        }
                   1767:        else if (on(*tp, CANINWALL)) {
                   1768:            if (isrock(mvwinch(stdscr, y, x))) ch = CCHAR( winch(stdscr) ); /* As Xorn */
                   1769:        }
                   1770:     }
                   1771:     return ch;
                   1772: }
                   1773:
                   1774: 
                   1775: /*
                   1776:  * trap_at:
                   1777:  *     find the trap at (y,x) on screen.
                   1778:  */
                   1779:
                   1780: struct trap *
                   1781: trap_at(int y, int x)
                   1782: {
                   1783:     register struct trap *tp, *ep;
                   1784:
                   1785:     ep = &traps[ntraps];
                   1786:     for (tp = traps; tp < ep; tp++)
                   1787:        if (tp->tr_pos.y == y && tp->tr_pos.x == x)
                   1788:            break;
                   1789:     if (tp == ep)
                   1790:        debug((sprintf(prbuf, "Trap at %d,%d not in array", y, x), prbuf));
                   1791:     return tp;
                   1792: }
                   1793: 
                   1794: /*
                   1795:  * weap_move:
                   1796:  *     Calculate how many segments it will take to swing the given
                   1797:  *     weapon (note that the weapon may actually be a stick or
                   1798:  *     even something else).
                   1799:  *     wielder: Who's wielding the weapon
                   1800:  *     weap: The weapon
                   1801:  */
                   1802:
                   1803: int
                   1804: weap_move(struct thing *wielder, struct object *weap)
                   1805: {
                   1806:     register int weap_rate;
                   1807:     int                 dexterity;
                   1808:     int                 strength;
                   1809:
                   1810:     if (weap == NULL) return(1); /* hand, claw, bite attacks are quick */
                   1811:
                   1812:     switch (weap->o_type) {
                   1813:        case STICK:
                   1814:            if (EQUAL(ws_type[weap->o_which], "staff"))
                   1815:                weap_rate = 2;
                   1816:            else weap_rate = 1; /* A wand */
                   1817:
                   1818:        when WEAPON:
                   1819:            weap_rate = weaps[weap->o_which].w_rate;
                   1820:
                   1821:            /* Adjust for blessed or cursed weapon */
                   1822:            if (weap->o_hplus < 0)      /* Cursed */
                   1823:                weap_rate -= (weap->o_hplus - 2) / 3;
                   1824:            else if (weap_rate > 0)     /* Blessed */
                   1825:                weap_rate -= (2*weap->o_hplus + weap_rate - 1) / weap_rate;
                   1826:
                   1827:        when RELIC:
                   1828:            switch (weap->o_which) {
                   1829:                case MUSTY_DAGGER:
                   1830:                case HRUGGEK_MSTAR:
                   1831:                case AXE_AKLAD:
                   1832:                case YEENOGHU_FLAIL:
                   1833:                case MING_STAFF:
                   1834:                case ORCUS_WAND:
                   1835:                case ASMO_ROD:
                   1836:                    /* These operate in the blink of an eye */
                   1837:                    weap_rate = 1;
                   1838:                otherwise:
                   1839:                    /* What is it? */
                   1840:                    weap_rate = 10;
                   1841:                    debug("unknown weapon in weap_move()");
                   1842:            }
                   1843:        otherwise:
                   1844:            /* What is it? */
                   1845:            weap_rate = 10;
                   1846:            debug("unknown weapon in weap_move()");
                   1847:     }
                   1848:
                   1849:     /* Put in a dexterity bonus */
                   1850:     if (wielder == &player) dexterity = dex_compute();
                   1851:     else dexterity = wielder->t_stats.s_dext;
                   1852:     weap_rate -= dext_plus(dexterity) / 2;
                   1853:
                   1854:     /* Put in a strength bonus */
                   1855:     if (wielder == &player) strength = str_compute();
                   1856:     else strength = wielder->t_stats.s_str;
                   1857:     weap_rate -= str_plus(strength) / 2;
                   1858:
                   1859:     /* It can't speed you up and it must take SOME time */
                   1860:     if (weap_rate <= 0) weap_rate = 1;
                   1861:
                   1862:     /* Do we need to adjust for fast/slow movement? */
                   1863:     if (on(*wielder, ISSLOW) || on(*wielder, ISDANCE)) weap_rate *= 2;
                   1864:     if (on(*wielder, ISHASTE)) weap_rate /= 2;
                   1865:
                   1866:     /* Return the result */
                   1867:     return(weap_rate);
                   1868: }

CVSweb