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

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

1.1       rubenllo    1: /*
                      2:     misc.c - all sorts of miscellaneous routines
                      3:
                      4:     UltraRogue: The Ultimate Adventure in the Dungeons of Doom
                      5:     Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
                      6:     All rights reserved.
                      7:
                      8:     Based on "Advanced Rogue"
                      9:     Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
                     10:     All rights reserved.
                     11:
                     12:     Based on "Rogue: Exploring the Dungeons of Doom"
                     13:     Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
                     14:     All rights reserved.
                     15:
                     16:     See the file LICENSE.TXT for full copyright and licensing information.
                     17: */
                     18:
                     19: #include <stdlib.h>
                     20: #include <string.h>
                     21: #include <ctype.h>
                     22: #include "rogue.h"
                     23:
                     24: /*
                     25:     tr_name()
                     26:         print the name of a trap
                     27: */
                     28:
                     29: char *
                     30: tr_name(char ch, char *trname)
                     31: {
                     32:     const char *s = NULL;
                     33:
                     34:     if (trname == NULL)
                     35:         return(" Your found an error in UltraRogue #100.");
                     36:
                     37:     switch(ch)
                     38:     {
                     39:         case TRAPDOOR:
                     40:             s = "trapdoor.";
                     41:             break;
                     42:         case BEARTRAP:
                     43:             s = "beartrap.";
                     44:             break;
                     45:         case SLEEPTRAP:
                     46:             s = "sleeping gas trap.";
                     47:             break;
                     48:         case ARROWTRAP:
                     49:             s = "arrow trap.";
                     50:             break;
                     51:         case TELTRAP:
                     52:             s = "teleport trap.";
                     53:             break;
                     54:         case DARTTRAP:
                     55:             s = "dart trap.";
                     56:             break;
                     57:         case POOL:
                     58:             s = "shimmering pool.";
                     59:             break;
                     60:         case MAZETRAP:
                     61:             s = "maze entrance.";
                     62:             break;
                     63:         case FIRETRAP:
                     64:             s = "fire trap.";
                     65:             break;
                     66:         case POISONTRAP:
                     67:             s = "poison pool trap.";
                     68:             break;
                     69:         case LAIR:
                     70:             s = "monster lair.";
                     71:             break;
                     72:         case RUSTTRAP:
                     73:             s = "rust trap.";
                     74:             break;
                     75:         default:
                     76:             ;
                     77:     }
                     78:
                     79:     sprintf(trname, "You found a %s.", s);
                     80:
                     81:     return(trname);
                     82: }
                     83:
                     84: /*
                     85:     look()
                     86:         A quick glance all around the player
                     87: */
                     88:
                     89: void
                     90: look(int wakeup)
                     91: {
                     92:     int     x, y;
                     93:     char   ch, och;
                     94:     int  oldx, oldy;
                     95:     int inpass, horizontal, vertical, do_light = FALSE, do_blank = FALSE;
                     96:     int passcount = 0;
                     97:     struct room *rp;
                     98:     int ey, ex;
                     99:
                    100:     /* Are we moving vertically or horizontally? */
                    101:
                    102:     if (runch == 'h' || runch == 'l')
                    103:         horizontal = TRUE;
                    104:     else
                    105:         horizontal = FALSE;
                    106:
                    107:     if (runch == 'j' || runch == 'k')
                    108:         vertical = TRUE;
                    109:     else
                    110:         vertical = FALSE;
                    111:
                    112:     getyx(cw, oldy, oldx);  /* Save current position */
                    113:
                    114:     /*
                    115:      * Blank out the floor around our last position and check for moving
                    116:      * out of a corridor in a maze.
                    117:     */
                    118:
                    119:     if (oldrp != NULL && (oldrp->r_flags & ISDARK) &&
                    120:         !(oldrp->r_flags & HASFIRE) && off(player, ISBLIND))
                    121:         do_blank = TRUE;
                    122:
                    123:     for (x = player.t_oldpos.x - 1; x <= player.t_oldpos.x + 1; x++)
                    124:         for (y = player.t_oldpos.y - 1; y <= player.t_oldpos.y + 1;
                    125:                 y++)
                    126:         {
                    127:             ch = show(y, x);
                    128:
                    129:             if (do_blank && (y != hero.y || x != hero.x) && ch == FLOOR)
                    130:                 mvwaddch(cw, y, x, ' ');
                    131:
                    132:             /* Moving out of a corridor? */
                    133:
                    134:             if (levtype == MAZELEV &&
                    135:                 (ch != '|' && ch != '-') && /* Not a wall */
                    136:                 ((vertical && x != player.t_oldpos.x &&
                    137:                 y == player.t_oldpos.y) ||
                    138:                  (horizontal && y != player.t_oldpos.y &&
                    139:                 x == player.t_oldpos.x)))
                    140:                 do_light = TRUE;    /* Just came to a turn */
                    141:         }
                    142:
                    143:     inpass = ((rp = roomin(hero)) == NULL);    /* Are we in a passage? */
                    144:
                    145:     /* Are we coming out of a wall into a corridor in a maze? */
                    146:     och = show(player.t_oldpos.y, player.t_oldpos.x);
                    147:     ch = show(hero.y, hero.x);
                    148:
                    149:     if (levtype == MAZELEV && (och == '|' || och == '-' ||
                    150:         och == SECRETDOOR) && (ch != '|' && ch != '-' && ch != SECRETDOOR))
                    151:     {
                    152:         do_light = off(player, ISBLIND);    /* Light it up if not blind */
                    153:     }
                    154:
                    155:     /* Look around the player */
                    156:
                    157:     ey = hero.y + 1;
                    158:     ex = hero.x + 1;
                    159:
                    160:     for (x = hero.x - 1; x <= ex; x++)
                    161:         if (x >= 0 && x < COLS)
                    162:             for (y = hero.y - 1; y <= ey; y++)
                    163:             {
                    164:                 if (y <= 0 || y >= LINES - 2)
                    165:                     continue;
                    166:
                    167:                 if (isalpha(mvwinch(mw, y, x)))
                    168:                 {
                    169:                     struct linked_list  *it;
                    170:                     struct thing    *tp;
                    171:
                    172:                     if (wakeup)
                    173:                         it = wake_monster(y, x);
                    174:                     else
                    175:                         it = find_mons(y, x);
                    176:
                    177:                     if (it == NULL)
                    178:                         continue;
                    179:
                    180:                     tp = THINGPTR(it);
                    181:                     tp->t_oldch = CCHAR( mvinch(y, x) );
                    182:
                    183:                     if (isatrap(tp->t_oldch))
                    184:                     {
                    185:                         struct trap *trp = trap_at(y, x);
                    186:
                    187:                         tp->t_oldch = (trp->tr_flags & ISFOUND) ? tp->t_oldch
                    188:                             : trp->tr_show;
                    189:                     }
                    190:
                    191:                     if (tp->t_oldch == FLOOR &&
                    192:                         (rp->r_flags & ISDARK)
                    193:                         && !(rp->r_flags & HASFIRE) &&
                    194:                         off(player, ISBLIND))
                    195:                         tp->t_oldch = ' ';
                    196:                 }
                    197:
                    198:                 /* Secret doors show as walls */
                    199:
                    200:                 if ((ch = show(y, x)) == SECRETDOOR)
                    201:                     ch = secretdoor(y, x);
                    202:
                    203:                 /*
                    204:                  * Don't show room walls if he is in a
                    205:                  * passage and check for maze turns
                    206:                 */
                    207:
                    208:                 if (off(player, ISBLIND))
                    209:                 {
                    210:                     if (y == hero.y && x == hero.x || (inpass && (ch == '-' ||
                    211:                         ch == '|')))
                    212:                         continue;
                    213:
                    214:                     /* Are we at a crossroads in a maze? */
                    215:
                    216:                     if (levtype == MAZELEV && (ch != '|' && ch != '-') &&
                    217:                         /* Not a wall */
                    218:                         ((vertical && x != hero.x && y == hero.y) ||
                    219:                          (horizontal && y != hero.y && x == hero.x)))
                    220:                         do_light = TRUE;
                    221:                         /* Just came to a turn */
                    222:                 }
                    223:                 else if (y != hero.y || x != hero.x)
                    224:                     continue;
                    225:
                    226:                 wmove(cw, y, x);
                    227:                 waddch(cw, ch);
                    228:
                    229:                 if (door_stop && !firstmove && running)
                    230:                 {
                    231:                     switch (runch)
                    232:                     {
                    233:                         case 'h':
                    234:                             if (x == ex)
                    235:                                 continue;
                    236:                             break;
                    237:                         case 'j':
                    238:                             if (y == hero.y - 1)
                    239:                                 continue;
                    240:                             break;
                    241:                         case 'k':
                    242:                             if (y == ey)
                    243:                                 continue;
                    244:                             break;
                    245:                         case 'l':
                    246:                             if (x == hero.x - 1)
                    247:                                 continue;
                    248:                             break;
                    249:                         case 'y':
                    250:                             if ((x + y) - (hero.x + hero.y) >= 1)
                    251:                                 continue;
                    252:                             break;
                    253:                         case 'u':
                    254:                             if ((y - x) - (hero.y - hero.x) >= 1)
                    255:                                 continue;
                    256:                             break;
                    257:                         case 'n':
                    258:                             if ((x + y) - (hero.x + hero.y) <= -1)
                    259:                                 continue;
                    260:                             break;
                    261:                         case 'b':
                    262:                             if ((y - x) - (hero.y - hero.x) <= -1)
                    263:                                 continue;
                    264:                             break;
                    265:                     }
                    266:
                    267:                     switch (ch)
                    268:                     {
                    269:                         case DOOR:
                    270:                             if (x == hero.x || y == hero.y)
                    271:                                 running = FALSE;
                    272:                             break;
                    273:                         case PASSAGE:
                    274:                             if (x == hero.x || y == hero.y)
                    275:                                 passcount++;
                    276:                             break;
                    277:                         case FLOOR:
                    278:
                    279:                         /*
                    280:                          * Stop by new passages in a
                    281:                          * maze (floor next to us)
                    282:                          */
                    283:                             if ((levtype == MAZELEV) &&
                    284:                                 ((horizontal && x == hero.x && y != hero.y) ||
                    285:                                 (vertical &&   y == hero.y && x != hero.x)))
                    286:                                 running = FALSE;
                    287:
                    288:                         case '|':
                    289:                         case '-':
                    290:                         case ' ':
                    291:                             break;
                    292:
                    293:                         default:
                    294:                             running = FALSE;
                    295:                             break;
                    296:                     }
                    297:                 }
                    298:             }
                    299:
                    300:     if (door_stop && !firstmove && passcount > 1)
                    301:         running = FALSE;
                    302:
                    303:     /*
                    304:      * Do we have to light up the area (just stepped into a new
                    305:      * corridor)?
                    306:      */
                    307:
                    308:     if (do_light && wakeup &&   /* wakeup will be true on a normal move */
                    309:         !(rp->r_flags & ISDARK) &&  /* We have some light */
                    310:         !ce(hero, player.t_oldpos)) /* Don't do anything if we didn't move */
                    311:         light(&hero);
                    312:
                    313:     mvwaddch(cw, hero.y, hero.x, PLAYER);
                    314:     wmove(cw, oldy, oldx);
                    315:
                    316:     if (wakeup)
                    317:     {
                    318:         player.t_oldpos = hero; /* Don't change if we didn't move */
                    319:         oldrp = rp;
                    320:     }
                    321: }
                    322:
                    323: /*
                    324:     secret_door()
                    325:         Figure out what a secret door looks like.
                    326: */
                    327:
                    328: char
                    329: secretdoor(int y, int x)
                    330: {
                    331:     struct room *rp;
                    332:     coord cp;
                    333:
                    334:     cp.x = x;
                    335:     cp.y = y;
                    336:
                    337:     if ((rp = roomin(cp)) != NULL)
                    338:     {
                    339:         if (y == rp->r_pos.y || y == rp->r_pos.y + rp->r_max.y - 1)
                    340:             return ('-');
                    341:         else
                    342:             return ('|');
                    343:     }
                    344:     return ('p');
                    345: }
                    346:
                    347: /*
                    348:     find_obj()
                    349:         find the unclaimed object at y, x
                    350: */
                    351:
                    352: struct linked_list  *
                    353: find_obj(int y, int x)
                    354: {
                    355:     struct linked_list  *obj, *sobj;
                    356:     struct object   *op;
                    357:
                    358:     sobj = lvl_obj;
                    359:
                    360:     for (obj = sobj; obj != NULL; obj = next(obj))
                    361:     {
                    362:         op = OBJPTR(obj);
                    363:
                    364:         if (op && op->o_pos.y == y && op->o_pos.x == x)
                    365:             return(obj);
                    366:     }
                    367:
                    368:     return(NULL);
                    369: }
                    370:
                    371: /*
                    372:     eat()
                    373:         He wants to eat something, so let him try
                    374: */
                    375:
                    376: void
                    377: eat(void)
                    378: {
                    379:     struct object   *obj;
                    380:     int amount;
                    381:     float scale = (float) (LINES * COLS) / (25.0F * 80.0F);
                    382:
                    383:     if ((obj = get_object(pack, "eat", FOOD, NULL)) == NULL)
                    384:         return;
                    385:
                    386:     switch (obj->o_which)
                    387:     {
                    388:         case FD_RATION:
                    389:             amount = (int)(scale * (HUNGERTIME + rnd(400) - 200));
                    390:
                    391:             if (rnd(100) > 70)
                    392:             {
                    393:                 msg("Yuk, this food tastes awful.");
                    394:                 pstats.s_exp++;
                    395:                 check_level();
                    396:             }
                    397:             else
                    398:                 msg("Yum, that tasted good.");
                    399:             break;
                    400:
                    401:         case FD_FRUIT:
                    402:             amount = (int)(scale * (200 + rnd(HUNGERTIME)));
                    403:             msg("My, that was a yummy %s.", fruit);
                    404:             break;
                    405:
                    406:         case FD_CRAM:
                    407:             amount = (int)(scale * (rnd(HUNGERTIME / 2) + 600));
                    408:             msg("The cram tastes dry in your mouth.");
                    409:             break;
                    410:
                    411:         case FD_CAKES:
                    412:             amount = (int)(scale * ((HUNGERTIME / 3) + rnd(600)));
                    413:             msg("Yum, the honey cakes tasted good.");
                    414:             break;
                    415:
                    416:         case FD_LEMBA:
                    417:             amount = (int)(scale * ((HUNGERTIME / 2) + rnd(900)));
                    418:             quaff(&player, P_HEALING, ISNORMAL);
                    419:             break;
                    420:
                    421:         case FD_MIRUVOR:
                    422:             amount = (int)(scale * ((HUNGERTIME / 3) + rnd(500)));
                    423:             quaff(&player, P_HEALING, ISNORMAL);
                    424:             quaff(&player, P_RESTORE, ISNORMAL);
                    425:             break;
                    426:
                    427:         default:
                    428:             msg("What a strange thing to eat!");
                    429:             amount = (int)(scale * HUNGERTIME);
                    430:     }
                    431:
                    432:     food_left += amount;
                    433:
                    434:     if (obj->o_flags & ISBLESSED)
                    435:     {
                    436:         food_left += 2 * amount;
                    437:         msg("You have a tingling feeling in your mouth.");
                    438:     }
                    439:     else if (food_left > scale * STOMACHSIZE)
                    440:     {
                    441:         food_left = (int)(scale * STOMACHSIZE);
                    442:         msg("You feel satiated and too full to move.");
                    443:         no_command = HOLDTIME;
                    444:     }
                    445:
                    446:     hungry_state = F_OK;
                    447:     updpack();
                    448:
                    449:     if (obj == cur_weapon)
                    450:         cur_weapon = NULL;
                    451:
                    452:     if (--obj->o_count <= 0) /* Remove this pack entry if last of food */
                    453:         discard_pack(obj);
                    454: }
                    455:
                    456: /*
                    457:  * Used to modify the player's strength it keeps track of the highest it has
                    458:  * been, just in case
                    459:  */
                    460:
                    461: void
                    462: chg_str(int amt, int both, int lost)
                    463: {
                    464:     int           ring_str; /* ring strengths */
                    465:     struct stats *ptr;      /* for speed */
                    466:
                    467:     ptr = &pstats;
                    468:
                    469:     ring_str = ring_value(R_ADDSTR) + (on(player, POWERSTR) ? 10 : 0) +
                    470:         (on(player, SUPERHERO) ? 10 : 0);
                    471:
                    472:     ptr->s_str -= ring_str;
                    473:     ptr->s_str += amt;
                    474:
                    475:     if (ptr->s_str < 3)
                    476:     {
                    477:         ptr->s_str = 3;
                    478:         lost = FALSE;
                    479:     }
                    480:     else if (ptr->s_str > 25)
                    481:         ptr->s_str = 25;
                    482:
                    483:     if (both)
                    484:         max_stats.s_str = ptr->s_str;
                    485:
                    486:     if (lost)
                    487:         lost_str -= amt;
                    488:
                    489:     ptr->s_str += ring_str;
                    490:
                    491:     if (ptr->s_str < 0)
                    492:         ptr->s_str = 0;
                    493:
                    494:     updpack();
                    495: }
                    496:
                    497: /*
                    498:  * Used to modify the player's dexterity it keeps track of the highest it has
                    499:  * been, just in case
                    500:  */
                    501:
                    502: void
                    503: chg_dext(int amt, int both, int lost)
                    504: {
                    505:     int ring_dext;      /* ring strengths   */
                    506:     struct stats *ptr;  /* for speed        */
                    507:
                    508:     ptr = &pstats;
                    509:
                    510:     ring_dext = ring_value(R_ADDHIT) + (on(player, POWERDEXT) ? 10 : 0) +
                    511:         (on(player, SUPERHERO) ? 5 : 0);
                    512:
                    513:     ptr->s_dext -= ring_dext;
                    514:     ptr->s_dext += amt;
                    515:
                    516:     if (ptr->s_dext < 3)
                    517:     {
                    518:         ptr->s_dext = 3;
                    519:         lost = FALSE;
                    520:     }
                    521:     else if (ptr->s_dext > 25)
                    522:         ptr->s_dext = 25;
                    523:
                    524:     if (both)
                    525:         max_stats.s_dext = ptr->s_dext;
                    526:
                    527:     if (lost)
                    528:         lost_dext -= amt;
                    529:
                    530:     ptr->s_dext += ring_dext;
                    531:
                    532:     if (ptr->s_dext < 0)
                    533:         ptr->s_dext = 0;
                    534: }
                    535:
                    536: /*
                    537:     add_haste()
                    538:         add a haste to the player
                    539: */
                    540:
                    541: void
                    542: add_haste(int blessed)
                    543: {
                    544:     short   hasttime;
                    545:
                    546:     if (blessed)
                    547:         hasttime = 10;
                    548:     else
                    549:         hasttime = 6;
                    550:
                    551:     if (on(player, ISSLOW))    /* Is person slow? */
                    552:     {
                    553:         extinguish_fuse(FUSE_NOSLOW);
                    554:         noslow(NULL);
                    555:
                    556:         if (blessed)
                    557:             hasttime = 4;
                    558:         else
                    559:             return;
                    560:     }
                    561:
                    562:     if (on(player, ISHASTE))
                    563:     {
                    564:         msg("You faint from exhaustion.");
                    565:         no_command += rnd(hasttime);
                    566:         lengthen_fuse(FUSE_NOHASTE, rnd(hasttime) + (roll(1, 4) * hasttime));
                    567:     }
                    568:     else
                    569:     {
                    570:         turn_on(player, ISHASTE);
                    571:         light_fuse(FUSE_NOHASTE, 0, roll(hasttime, hasttime), AFTER);
                    572:     }
                    573: }
                    574:
                    575: /*
                    576:     aggravate()
                    577:         aggravate all the monsters on this level
                    578: */
                    579:
                    580: void
                    581: aggravate(void)
                    582: {
                    583:     struct linked_list *mi;
                    584:     struct thing *tp;
                    585:
                    586:     for (mi = mlist; mi != NULL; mi = next(mi))
                    587:     {
                    588:         tp = THINGPTR(mi);
                    589:         chase_it(&tp->t_pos, &player);
                    590:     }
                    591: }
                    592:
                    593: /*
                    594:     vowelstr()
                    595:         for printfs: if string starts with a vowel, return "n" for an "an"
                    596: */
                    597:
                    598: char *
                    599: vowelstr(char *str)
                    600: {
                    601:     switch (*str)
                    602:     {
                    603:         case 'a':
                    604:         case 'A':
                    605:         case 'e':
                    606:         case 'E':
                    607:         case 'i':
                    608:         case 'I':
                    609:         case 'o':
                    610:         case 'O':
                    611:         case 'u':
                    612:         case 'U':
                    613:             return "n";
                    614:         default:
                    615:             return "";
                    616:     }
                    617: }
                    618:
                    619: /*
                    620:     is_object()
                    621:         see if the object is one of the currently used items
                    622: */
                    623:
                    624: int
                    625: is_current(struct object *obj)
                    626: {
                    627:     if (obj == NULL)
                    628:         return FALSE;
                    629:
                    630:     if (obj == cur_armor || obj == cur_weapon ||
                    631:         obj == cur_ring[LEFT_1] || obj == cur_ring[LEFT_2] ||
                    632:         obj == cur_ring[LEFT_3] || obj == cur_ring[LEFT_4] ||
                    633:         obj == cur_ring[LEFT_5] ||
                    634:         obj == cur_ring[RIGHT_1] || obj == cur_ring[RIGHT_2] ||
                    635:         obj == cur_ring[RIGHT_3] || obj == cur_ring[RIGHT_4] ||
                    636:         obj == cur_ring[RIGHT_5]) {
                    637:         msg("That's already in use.");
                    638:         return TRUE;
                    639:     }
                    640:
                    641:     return FALSE;
                    642: }
                    643:
                    644: /*
                    645:     get_dir()
                    646:         set up the direction co_ordinate for use in varios "prefix" commands
                    647: */
                    648:
                    649: int
                    650: get_dir(void)
                    651: {
                    652:     char *prompt;
                    653:     int   gotit;
                    654:
                    655:     prompt = "Which direction? ";
                    656:     msg(prompt);
                    657:
                    658:     do
                    659:     {
                    660:         gotit = TRUE;
                    661:
                    662:         switch (readchar())
                    663:         {
                    664:             case 'h':
                    665:             case 'H':
                    666:                 delta.y = 0;
                    667:                 delta.x = -1;
                    668:                 break;
                    669:
                    670:             case 'j':
                    671:             case 'J':
                    672:                 delta.y = 1;
                    673:                 delta.x = 0;
                    674:                 break;
                    675:
                    676:             case 'k':
                    677:             case 'K':
                    678:                 delta.y = -1;
                    679:                 delta.x = 0;
                    680:                 break;
                    681:
                    682:             case 'l':
                    683:             case 'L':
                    684:                 delta.y = 0;
                    685:                 delta.x = 1;
                    686:                 break;
                    687:
                    688:             case 'y':
                    689:             case 'Y':
                    690:                 delta.y = -1;
                    691:                 delta.x = -1;
                    692:                 break;
                    693:
                    694:             case 'u':
                    695:             case 'U':
                    696:                 delta.y = -1;
                    697:                 delta.x = 1;
                    698:                 break;
                    699:
                    700:             case 'b':
                    701:             case 'B':
                    702:                 delta.y = 1;
                    703:                 delta.x = -1;
                    704:                 break;
                    705:
                    706:             case 'n':
                    707:             case 'N':
                    708:                 delta.y = 1;
                    709:                 delta.x = 1;
                    710:                 break;
                    711:
                    712:             case  ESCAPE:
                    713:                 return FALSE;
                    714:
                    715:             default:
                    716:                 mpos = 0;
                    717:                 msg(prompt);
                    718:                 gotit = FALSE;
                    719:         }
                    720:     }
                    721:     while(!gotit);
                    722:
                    723:     if (on(player, ISHUH) && rnd(100) > 80)
                    724:         do
                    725:         {
                    726:             delta.y = rnd(3) - 1;
                    727:             delta.x = rnd(3) - 1;
                    728:         }
                    729:         while (delta.y == 0 && delta.x == 0);
                    730:
                    731:     mpos = 0;
                    732:
                    733:     return(TRUE);
                    734: }
                    735:
                    736: /*
                    737:     is_wearing()
                    738:         is the hero wearing a particular ring
                    739: */
                    740:
                    741: int
                    742: is_wearing(int type)
                    743: {
                    744: #define ISRING(h, r) (cur_ring[h] != NULL && cur_ring[h]->o_which == r)
                    745:
                    746:     return(
                    747:         ISRING(LEFT_1,  type) || ISRING(LEFT_2, type) ||
                    748:         ISRING(LEFT_3,  type) || ISRING(LEFT_4, type) ||
                    749:         ISRING(LEFT_5,  type) ||
                    750:         ISRING(RIGHT_1, type) || ISRING(RIGHT_2, type) ||
                    751:         ISRING(RIGHT_3, type) || ISRING(RIGHT_4, type) ||
                    752:         ISRING(RIGHT_5, type)  );
                    753: }
                    754:
                    755: /*
                    756:     maze_view()
                    757:         Returns true if the player can see the specified location
                    758:         within the confines of a maze (within one column or row)
                    759: */
                    760:
                    761: int
                    762: maze_view(int y, int x)
                    763: {
                    764:     int start, goal, delt, ycheck = 0, xcheck = 0, absy, absx;
                    765:     int row;
                    766:
                    767:     /* Get the absolute value of y and x differences */
                    768:
                    769:     absy = hero.y - y;
                    770:     absx = hero.x - x;
                    771:
                    772:     if (absy < 0)
                    773:         absy = -absy;
                    774:
                    775:     if (absx < 0)
                    776:         absx = -absx;
                    777:
                    778:     /* Must be within one row or column */
                    779:
                    780:     if (absy > 1 && absx > 1)
                    781:         return(FALSE);
                    782:
                    783:     if (absy <= 1)      /* Go along row */
                    784:     {
                    785:         start = hero.x;
                    786:         goal = x;
                    787:         row = TRUE;
                    788:         ycheck = hero.y;
                    789:     }
                    790:     else            /* Go along column */
                    791:     {
                    792:         start = hero.y;
                    793:         goal = y;
                    794:         row = FALSE;
                    795:         xcheck = hero.x;
                    796:     }
                    797:
                    798:     if (start <= goal)
                    799:         delt = 1;
                    800:     else
                    801:         delt = -1;
                    802:
                    803:     while (start != goal)
                    804:     {
                    805:         if (row)
                    806:             xcheck = start;
                    807:         else
                    808:             ycheck = start;
                    809:
                    810:         switch(CCHAR(winat(ycheck, xcheck)))
                    811:         {
                    812:             case '|':
                    813:             case '-':
                    814:             case WALL:
                    815:             case DOOR:
                    816:             case SECRETDOOR:
                    817:                 return(FALSE);
                    818:
                    819:             default:
                    820:                 break;
                    821:         }
                    822:         start += delt;
                    823:     }
                    824:
                    825:     return(TRUE);
                    826: }
                    827:
                    828: /*
                    829:     listen()
                    830:         listen for monsters less than 5 units away
                    831: */
                    832:
                    833: void
                    834: listen(void)
                    835: {
                    836:     struct linked_list  *item;
                    837:     struct thing    *tp;
                    838:     int thief_bonus = -50;
                    839:     int mcount = 0;
                    840:
                    841:     if (player.t_ctype == C_THIEF)
                    842:         thief_bonus = 10;
                    843:
                    844:     for (item = mlist; item != NULL; item = next(item))
                    845:     {
                    846:         tp = THINGPTR(item);
                    847:
                    848:         if (DISTANCE(hero, tp->t_pos) < 81
                    849:             && rnd(70) < (thief_bonus + 4 * pstats.s_dext +
                    850:             6 * pstats.s_lvl))
                    851:         {
                    852:             msg("You hear a%s %s nearby.",
                    853:                 vowelstr(monsters[tp->t_index].m_name),
                    854:                 monsters[tp->t_index].m_name);
                    855:             mcount++;
                    856:         }
                    857:     }
                    858:
                    859:     if (mcount == 0)
                    860:         msg("You hear nothing.");
                    861: }
                    862:
                    863: /*
                    864:  * nothing_message - print out "Nothing <adverb> happens."
                    865:  */
                    866:
                    867: static const char *nothings[] =
                    868: {
                    869:     "",
                    870:     "unusual ",
                    871:     "seems to ",
                    872:     "at all ",
                    873:     "really ",
                    874:     "noticeable ",
                    875:     "different ",
                    876:     "strange ",
                    877:     "wierd ",
                    878:     "bizzare ",
                    879:     "wonky ",
                    880:     ""
                    881: };
                    882:
                    883: void
                    884: nothing_message(int flags)
                    885: {
                    886:     int adverb = rnd(sizeof(nothings) / sizeof(char *));
                    887:
                    888:     NOOP(flags);
                    889:
                    890:     msg("Nothing %shappens.", nothings[adverb]);
                    891: }
                    892:
                    893: /*
                    894:     feel_message()
                    895:         print out "You feel <description>."
                    896: */
                    897:
                    898: void
                    899: feel_message(void)
                    900: {
                    901:     char *charp;
                    902:
                    903:     switch (rnd(25))
                    904:     {
                    905:         case 1:  charp = "bad";      break;
                    906:         case 2:  charp = "hurt";     break;
                    907:         case 3:  charp = "sick";     break;
                    908:         case 4:  charp = "faint";    break;
                    909:         case 5:  charp = "yucky";    break;
                    910:         case 6:  charp = "wonky";    break;
                    911:         case 7:  charp = "wierd";    break;
                    912:         case 8:  charp = "queasy";   break;
                    913:         case 9:  charp = "wounded";  break;
                    914:         case 11: charp = "unusual";  break;
                    915:         case 12: charp = "no pain";  break;
                    916:         case 13: charp = "strange";  break;
                    917:         case 14: charp = "noticable"; break;
                    918:         case 15: charp = "bizzare";   break;
                    919:         case 16: charp = "distressed";break;
                    920:         case 17: charp = "different"; break;
                    921:         case 18: charp = "a touch of ague"; break;
                    922:         case 19: charp = "a migrane coming on"; break;
                    923:         case 20: charp = "Excedrin headache #666"; break;
                    924:         case 21: charp = "a disturbance in the force"; break;
                    925:         case 22: charp = "like someone dropped a house on you"; break;
                    926:         case 23: charp = "as if every nerve in your body is on fire"; break;
                    927:         case 24: charp = "like thousands of red-hot army ants are crawling under your skin";
                    928:                     break;
                    929:
                    930:         default:
                    931:             charp = "ill";
                    932:             break;
                    933:     }
                    934:     msg("You feel %s.", charp);
                    935: }
                    936:
                    937: /*
                    938:     const_bonus()
                    939:         Hit point adjustment for changing levels
                    940: */
                    941:
                    942: int
                    943: const_bonus(void)
                    944: {
                    945:     int ret_val = -2;
                    946:
                    947:     if (pstats.s_const > 12)
                    948:         ret_val = pstats.s_const - 12;
                    949:     else if (pstats.s_const > 6)
                    950:         ret_val = 0;
                    951:     else if (pstats.s_const > 3)
                    952:         ret_val = -1;
                    953:
                    954:     return(ret_val);
                    955: }
                    956:
                    957: /*
                    958:     int_wis_bonus()
                    959:         Spell point adjustment for changing levels
                    960: */
                    961:
                    962: int
                    963: int_wis_bonus(void)
                    964: {
                    965:     int ret_val = -2;
                    966:     int casters_stat;
                    967:
                    968:     switch (player.t_ctype)
                    969:     {
                    970:         case C_PALADIN:
                    971:         case C_CLERIC:
                    972:             casters_stat = pstats.s_wisdom;
                    973:             break;
                    974:         case C_RANGER:
                    975:         case C_DRUID:
                    976:             casters_stat = pstats.s_wisdom;
                    977:             break;
                    978:         case  C_MAGICIAN:
                    979:             casters_stat = pstats.s_intel;
                    980:             break;
                    981:         case  C_ILLUSION:
                    982:             casters_stat = pstats.s_intel;
                    983:             break;
                    984:
                    985:         default:
                    986:             if (is_wearing(R_WIZARD))
                    987:                 casters_stat = pstats.s_intel;
                    988:             else if (is_wearing(R_PIETY))
                    989:                 casters_stat = pstats.s_wisdom;
                    990:             else
                    991:                 casters_stat = (rnd(2) ? pstats.s_wisdom :
                    992:                     pstats.s_intel);
                    993:     }
                    994:
                    995:     if (casters_stat > 12)
                    996:         ret_val = casters_stat - 12;
                    997:     else if (casters_stat > 6)
                    998:         ret_val = 0;
                    999:     else if (casters_stat > 3)
                   1000:         ret_val = -1;
                   1001:
                   1002:     return(ret_val);
                   1003: }
                   1004:
                   1005: void
                   1006: electrificate(void)
                   1007: {
                   1008:     int affect_dist = 4 + player.t_stats.s_lvl / 4;
                   1009:     struct linked_list  *item, *nitem;
                   1010:
                   1011:     for (item = mlist; item != NULL; item = nitem)
                   1012:     {
                   1013:         struct thing *tp = THINGPTR(item);
                   1014:         char *mname = monsters[tp->t_index].m_name;
                   1015:
                   1016:         nitem = next(item);
                   1017:
                   1018:         if (DISTANCE(tp->t_pos, hero) < affect_dist)
                   1019:         {
                   1020:             int damage = roll(2, player.t_stats.s_lvl);
                   1021:
                   1022:             debug("Charge does %d (%d)", damage, tp->t_stats.s_hpt - damage);
                   1023:
                   1024:             if (on(*tp, NOBOLT))
                   1025:                 continue;
                   1026:
                   1027:             if ((tp->t_stats.s_hpt -= damage) <= 0)
                   1028:             {
                   1029:                 msg("The %s is killed by an electric shock.", mname);
                   1030:                 killed(&player, item, NOMESSAGE, POINTS);
                   1031:                 continue;
                   1032:             }
                   1033:
                   1034:             if (rnd(tp->t_stats.s_intel / 5) == 0)
                   1035:             {
                   1036:                 turn_on(*tp, ISFLEE);
                   1037:                 msg("The %s is shocked by electricity.", mname);
                   1038:             }
                   1039:             else
                   1040:                 msg("The %s is zapped by your electricity.", mname);
                   1041:
                   1042:             summon_help(tp, NOFORCE);
                   1043:             turn_off(*tp, ISFRIENDLY);
                   1044:             turn_off(*tp, ISCHARMED);
                   1045:             turn_on(*tp, ISRUN);
                   1046:             turn_off(*tp, ISDISGUISE);
                   1047:             chase_it(&tp->t_pos, &player);
                   1048:             fighting = after = running = FALSE;
                   1049:         }
                   1050:     }
                   1051: }
                   1052:
                   1053: /*
                   1054:     feed_me -    Print out interesting messages about food consumption
                   1055: */
                   1056:
                   1057: static char *f_hungry[] =
                   1058: {
                   1059:     "want a cookie",
                   1060:     "feel like a snack",
                   1061:     "feel like some fruit",
                   1062:     "start having the munchies",
                   1063:     "are starting to get hungry"
                   1064: };
                   1065:
                   1066: static char *f_weak[] =
                   1067: {
                   1068:     "are really hungry",
                   1069:     "could eat a horse",
                   1070:     "want some food - now",
                   1071:     "are starting to feel weak",
                   1072:     "feel a gnawing in your stomach",
                   1073:     "are even willing to eat up cram",
                   1074:     "feel lightheaded from not eating"
                   1075: };
                   1076:
                   1077: static char *f_faint[] =
                   1078: {
                   1079:     "get dizzy from not eating",
                   1080:     "are starving for nutrients",
                   1081:     "feel too weak from lack of food",
                   1082:     "see a mirage of an incredible banquet",
                   1083:     "have incredible cramps in your stomach"
                   1084: };
                   1085:
                   1086: static char *f_plop[] =
                   1087: {
                   1088:     "faint",
                   1089:     "pass out",
                   1090:     "keel over",
                   1091:     "black out"
                   1092: };
                   1093:
                   1094: void
                   1095: feed_me(int hunger)
                   1096: {
                   1097:     char    *charp = NULL, *charp2 = NULL;
                   1098:
                   1099:     switch (hunger)
                   1100:     {
                   1101:         case F_OK:
                   1102:         default:
                   1103:             debug("feed_me(%d) called.", hunger);
                   1104:             break;
                   1105:
                   1106:         case  F_HUNGRY:
                   1107:             charp = f_hungry[rnd(sizeof(f_hungry) /
                   1108:                 sizeof(char *))];
                   1109:             break;
                   1110:
                   1111:         case  F_WEAK:
                   1112:             charp = f_weak[rnd(sizeof(f_weak) / sizeof(char *))];
                   1113:             break;
                   1114:
                   1115:         case F_FAINT:
                   1116:             charp = f_faint[rnd(sizeof(f_faint) / sizeof(char *))];
                   1117:             charp2 = f_plop[rnd(sizeof(f_plop) / sizeof(char *))];
                   1118:             break;
                   1119:     }
                   1120:
                   1121:     msg("You %s.", charp);
                   1122:
                   1123:     if (hunger == F_FAINT)
                   1124:         msg("You %s.", charp2);
                   1125: }
                   1126:
                   1127:
                   1128: /*
                   1129:     get_monster_number()
                   1130:         prompt player for a monster on list returns 0 if none selected
                   1131: */
                   1132:
                   1133: int
                   1134: get_monster_number(char *message)
                   1135: {
                   1136:     int  i;
                   1137:     int  pres_monst = 1;
                   1138:     int  ret_val = -1;
                   1139:     char buf[2 * LINELEN];
                   1140:     char monst_name[2 * LINELEN];
                   1141:
                   1142:     while (ret_val == -1)
                   1143:     {
                   1144:         msg("Which monster do you wish to %s? (* for list)", message);
                   1145:
                   1146:         if ((get_string(buf, cw)) != NORM)
                   1147:             return(0);
                   1148:
                   1149:         if ((i = atoi(buf)) != 0)
                   1150:             ret_val = i;
                   1151:         else if (buf[0] != '*')
                   1152:         {
                   1153:             for (i = 1; i < nummonst; i++)
                   1154:                 if ((strcmp(monsters[i].m_name, buf) == 0))
                   1155:                     ret_val = i;
                   1156:         }
                   1157:         /* The following hack should be redone by the windowing code */
                   1158:         else
                   1159:             while (pres_monst < nummonst)   /* Print out the monsters */
                   1160:             {
                   1161:                 int num_lines = LINES - 3;
                   1162:
                   1163:                 wclear(hw);
                   1164:                 touchwin(hw);
                   1165:
                   1166:                 wmove(hw, 2, 0);
                   1167:
                   1168:                 for (i = 0; i < num_lines && pres_monst < nummonst; i++)
                   1169:                 {
                   1170:                     sprintf(monst_name, "[%d] %s\n", pres_monst,
                   1171:                         monsters[pres_monst].m_name);
                   1172:                     waddstr(hw, monst_name);
                   1173:                     pres_monst++;
                   1174:                 }
                   1175:
                   1176:                 if (pres_monst < nummonst)
                   1177:                 {
                   1178:                     mvwaddstr(hw, LINES - 1, 0, morestr);
                   1179:                     wrefresh(hw);
                   1180:                     wait_for(' ');
                   1181:                 }
                   1182:                 else
                   1183:                 {
                   1184:                     mvwaddstr(hw, 0, 0, "Which monster");
                   1185:                     waddstr(hw, "? ");
                   1186:                     wrefresh(hw);
                   1187:                 }
                   1188:             }
                   1189:
                   1190: get_monst:
                   1191:         get_string(monst_name, hw);
                   1192:         ret_val = atoi(monst_name);
                   1193:
                   1194:         if ((ret_val < 1 || ret_val > nummonst - 1))
                   1195:         {
                   1196:             mvwaddstr(hw, 0, 0, "Please enter a number in the displayed range -- ");
                   1197:             wrefresh(hw);
                   1198:             goto get_monst;
                   1199:         }
                   1200:
                   1201:         /* Set up for redraw */
                   1202:
                   1203:         clearok(cw, TRUE);
                   1204:         touchwin(cw);
                   1205:     }
                   1206:
                   1207:     return(ret_val);
                   1208: }

CVSweb