Exemplo n.º 1
0
// This must be called when any of the following change:
// - effects
// - bionics
// - traits
// - underwater
// - clothes
// With the exception of clothes, all changes to these character attributes must
// occur through a function in this class which calls this function. Clothes are
// typically added/removed with wear() and takeoff(), but direct access to the
// 'wears' vector is still allowed due to refactor exhaustion.
void Character::recalc_sight_limits()
{
    sight_max = 9999;
    sight_boost = 0;
    sight_boost_cap = 0;

    // Set sight_max.
    if (has_effect("blind")) {
        sight_max = 0;
    } else if (has_effect("in_pit") ||
            (has_effect("boomered") && (!(has_trait("PER_SLIME_OK")))) ||
            (underwater && !has_bionic("bio_membrane") &&
                !has_trait("MEMBRANE") && !worn_with_flag("SWIM_GOGGLES") &&
                !has_trait("CEPH_EYES") && !has_trait("PER_SLIME_OK") ) ) {
        sight_max = 1;
    } else if (has_active_mutation("SHELL2")) {
        // You can kinda see out a bit.
        sight_max = 2;
    } else if ( (has_trait("MYOPIC") || has_trait("URSINE_EYE")) &&
            !is_wearing("glasses_eye") && !is_wearing("glasses_monocle") &&
            !is_wearing("glasses_bifocal") && !has_effect("contacts")) {
        sight_max = 4;
    } else if (has_trait("PER_SLIME")) {
        sight_max = 6;
    }

    // Set sight_boost and sight_boost_cap, based on night vision.
    // (A player will never have more than one night vision trait.)
    sight_boost_cap = 12;
    // Debug-only NV, by vache's request
    if (has_trait("DEBUG_NIGHTVISION")) {
        sight_boost = 59;
        sight_boost_cap = 59;
    } else if (has_nv() || is_wearing("rm13_armor_on") || has_active_mutation("NIGHTVISION3") ||
        has_active_mutation("ELFA_FNV") || (has_active_mutation("CEPH_VISION")) ) {
        // Yes, I'm breaking the cap. I doubt the reality bubble shrinks at night.
        // BIRD_EYE represents excellent fine-detail vision so I think it works.
        if (has_trait("BIRD_EYE")) {
            sight_boost_cap = 13;
        }
        sight_boost = sight_boost_cap;
    } else if (has_active_mutation("ELFA_NV")) {
        sight_boost = 6; // Elf-a and Bird eyes shouldn't coexist
    } else if (has_active_mutation("NIGHTVISION2") || has_active_mutation("FEL_NV") ||
        has_active_mutation("URSINE_EYE")) {
        if (has_trait("BIRD_EYE")) {
            sight_boost = 5;
        } else {
            sight_boost = 4;
         }
    } else if (has_active_mutation("NIGHTVISION")) {
        if (has_trait("BIRD_EYE")) {
            sight_boost = 2;
        } else {
            sight_boost = 1;
        }
    }
}
Exemplo n.º 2
0
fuse
unfly(fuse_arg *arg)
{
    NOOP(arg);

    turn_off(player, CANFLY);

    if (!is_wearing(R_LEVITATION))
        msg("You float gently to the ground.");
}
Exemplo n.º 3
0
fuse
unbreathe(fuse_arg *arg)
{
    NOOP(arg);

    turn_off(player, HASOXYGEN);

    if (!is_wearing(R_BREATHE))
        msg("You start huffing and puffing.");
}
Exemplo n.º 4
0
fuse
unhot(fuse_arg *arg)
{
    NOOP(arg);

    turn_off(player, NOFIRE);

    if (!is_wearing(R_FIRERESIST))
        msg("You feel a flush of warmth.");
}
Exemplo n.º 5
0
fuse
unregen(fuse_arg *arg)
{
    NOOP(arg);

    turn_off(player, ISREGEN);

    if (!is_wearing(R_REGEN))
        msg("Your metabolism slows down.");
}
Exemplo n.º 6
0
fuse
uncold(fuse_arg *arg)
{
    NOOP(arg);

    turn_off(player, NOCOLD);

    if (!is_wearing(R_COLDRESIST))
        msg("You feel a slight chill in the air.");
}
Exemplo n.º 7
0
int
int_wis_bonus(void)
{
    int ret_val = -2;
    int casters_stat;

    switch (player.t_ctype)
    {
    case C_PALADIN:
    case C_CLERIC:
        casters_stat = pstats.s_wisdom;
        break;
    case C_RANGER:
    case C_DRUID:
        casters_stat = pstats.s_wisdom;
        break;
    case  C_MAGICIAN:
        casters_stat = pstats.s_intel;
        break;
    case  C_ILLUSION:
        casters_stat = pstats.s_intel;
        break;

    default:
        if (is_wearing(R_WIZARD))
            casters_stat = pstats.s_intel;
        else if (is_wearing(R_PIETY))
            casters_stat = pstats.s_wisdom;
        else
            casters_stat = (rnd(2) ? pstats.s_wisdom :
                            pstats.s_intel);
    }

    if (casters_stat > 12)
        ret_val = casters_stat - 12;
    else if (casters_stat > 6)
        ret_val = 0;
    else if (casters_stat > 3)
        ret_val = -1;

    return(ret_val);
}
Exemplo n.º 8
0
void
untruesee(fuse_arg *arg)
{
    NOOP(arg);

    if (!is_wearing(R_TRUESEE))
    {
        turn_off(player, CANTRUESEE);
        msg("Your sensory perceptions return to normal.");
    }
}
Exemplo n.º 9
0
fuse
unsee(fuse_arg *arg)
{
    NOOP(arg);

    if (!is_wearing(R_SEEINVIS))
    {
        turn_off(player, CANSEE);
        msg("The tingling feeling leaves your eyes.");
    }
}
Exemplo n.º 10
0
struct linked_list *
summon_monster(int type, int familiar, int print_message)
{
    struct linked_list  *mp;
    struct thing    *tp;
    int   monster;

    if (familiar && !is_wearing(R_WIZARD) && off(player, CANSUMMON))
    {
        msg("Only spellcasters can summon familiars!");
        return(NULL);
    }

    if (type == 0)    /* Random monster modified by level */
    {
        int ndice = min(pstats.s_lvl, (nummonst - NUMSUMMON) / 8);

        monster = min(nummonst, roll(ndice, pstats.s_charisma));
        
		/*
         * if a familiar exists, and it is higher in level, make it
         * again 
         */

        if (fam_ptr != NULL) 
		{
            struct thing   *fp = THINGPTR(fam_ptr);

            monster = max(fp->t_index, monster);
        }
	}
    else
        monster = type;

    turn_on(player, SUMMONING);

    mp = creat_mons(&player, monster, NOMESSAGE);

    if (!mp)
    {
        msg("Summon failed.");
        turn_off(player, SUMMONING);
        return(NULL);
    }

    if (print_message == MESSAGE)
    {
        msg("A %s appears out of nowhere!", monsters[monster].m_name);

        if (familiar)
            msg("I am here to serve %s.", whoami);
        else
        {
            msg("My goodness, are you Yendor?");
            ++mons_summoned;
            debug("%d monsters now summoned.", mons_summoned);
        }
    }

    tp = THINGPTR(mp);
    turn_on(*tp, ISCHARMED);    /* Summoned monsters are always charmed */

    if (familiar)
    {
        int i;
        static const unsigned long fam_on[]= {ISREGEN,CANSHOOT,CANWIELD,HASARMOR,ISFAMILIAR,0};
        static const unsigned long fam_off[]={ISMEAN, ISHUH, ISINVIS,
                    CANSURPRISE, NOMOVE,
                    ISSLOW, ISSHADOW, ISGREED, ISFAST,
                    CANFLY, ISFLEE, 0};

        for (i = 0; fam_on[i]; i++)
            turn_on(*tp, fam_on[i]);

        for (i = 0; fam_off[i]; i++)
            turn_off(*tp, fam_off[i]);

        if (fam_ptr != NULL)    /* Get rid of old familiar */
        {
            struct thing    *fp = THINGPTR(fam_ptr);
            struct linked_list  *fpack = fp->t_pack;
            struct linked_list  *item;

            if (fpack != NULL)  /* Transfer pack */
            {
                if (tp->t_pack == NULL)
                    tp->t_pack = fpack;
                else
                {
                    for(item=tp->t_pack; item->l_next != NULL; item=next(item))
                        ;   /* find last item in list */

                    item->l_next = fpack;
                    fpack->l_prev = item;
                }
            }

            fpack = NULL;
            killed(NULL, fam_ptr, NOMESSAGE, NOPOINTS);
        }

        fam_ptr = mp;
        fam_type = monster;

        /* improve their abilities a bit */

        tp->t_stats.s_hpt += roll(2, pstats.s_lvl);
        tp->t_stats.s_lvl += roll(2, (pstats.s_lvl / 4) + 1);
        tp->t_stats.s_arm -= roll(2, (pstats.s_lvl / 4) + 1);
        tp->t_stats.s_str += roll(2, (pstats.s_lvl / 4) + 1);
        tp->t_stats.s_intel += roll(2, (pstats.s_lvl / 4) + 1);
        tp->t_stats.s_wisdom += roll(2, (pstats.s_lvl / 4) + 1);
        tp->t_stats.s_dext += roll(2, (pstats.s_lvl / 4) + 1);
        tp->t_stats.s_const += roll(2, (pstats.s_lvl / 4) + 1);
        tp->t_stats.s_charisma += roll(2, (pstats.s_lvl / 4) + 1);
		
		/* some monsters do no damage by default */
		
		if (strcmp(tp->t_stats.s_dmg, "0d0") == 0)
            tp->t_stats.s_dmg = "1d8";
			
        tp->maxstats = tp->t_stats; /* structure assignment */
    }

    turn_off(player, SUMMONING);

    return(mp);
}
Exemplo n.º 11
0
void
new_monster(struct linked_list *item, int type, coord *cp, int max_monster)
{
    struct thing    *tp;
    struct monster  *mp;
    char    *ip, *hitp;
    int   i, min_intel, max_intel;
    int   num_dice, num_sides = 8, num_extra = 0;
    int eff_charisma = pstats.s_charisma;
    int eff_intel = pstats.s_intel;

    attach(mlist, item);
    tp = THINGPTR(item);
    tp->t_index = type;
    tp->t_wasshot = FALSE;
    tp->t_type = monsters[type].m_appear;
    tp->t_ctype = C_MONSTER;
    tp->t_no_move = 0;
    tp->t_doorgoal = -1;
    tp->t_pos = *cp;
    tp->t_oldpos = *cp;
    tp->t_oldch = CCHAR( mvwinch(cw, cp->y, cp->x) );
    mvwaddch(mw, cp->y, cp->x, tp->t_type);
    mp = &monsters[tp->t_index];

    /* Figure out monster's hit points */

    hitp = mp->m_stats.s_hpt;
    num_dice = atoi(hitp);

    if ((hitp = strchr(hitp, 'd')) != NULL)
    {
        num_sides = atoi(++hitp);

        if ((hitp = strchr(hitp, '+')) != NULL)
            num_extra = atoi(++hitp);
    }

    if (max_monster == MAXSTATS)
        tp->t_stats.s_hpt = num_dice * num_sides + num_extra;
    else
        tp->t_stats.s_hpt = roll(num_dice, num_sides) + num_extra;

    tp->t_stats.s_lvl = mp->m_stats.s_lvl;
    tp->t_stats.s_arm = mp->m_stats.s_arm;
    tp->t_stats.s_dmg = mp->m_stats.s_dmg;
    tp->t_stats.s_exp = mp->m_stats.s_exp + mp->m_add_exp * tp->t_stats.s_hpt;
    tp->t_stats.s_str = mp->m_stats.s_str;

    if (max_level > 30)
    {
        tp->t_stats.s_hpt += roll(4, (max_level - 60) * 2);
        tp->t_stats.s_lvl += roll(4, (max_level - 60) / 8);
        tp->t_stats.s_arm -= roll(2, (max_level - 60) / 8);
        tp->t_stats.s_str += roll(2, (max_level - 60) / 12);
        tp->t_stats.s_exp += roll(4, (max_level - 60) * 2) * mp->m_add_exp;
    }

    /*
     * just initailize others values to something reasonable for now
     * maybe someday will *really* put these in monster table
     */

    tp->t_stats.s_wisdom = 8 + rnd(4);
    tp->t_stats.s_dext = 8 + rnd(4);
    tp->t_stats.s_const = 8 + rnd(4);
    tp->t_stats.s_charisma = 8 + rnd(4);

    if (max_level > 45)
        tp->t_stats.s_dext += roll(2, (max_level - 50) / 8);

    /* Set the initial flags */

    for (i = 0; i < 16; i++)
        tp->t_flags[i] = 0;

    for (i = 0; i < 16; i++)
        turn_on(*tp, mp->m_flags[i]);

    /* suprising monsters don't always surprise you */

    if (!max_monster && on(*tp, CANSURPRISE) && rnd(100) < 20)
        turn_off(*tp, CANSURPRISE);

    /* If this monster is unique, genocide it */

    if (on(*tp, ISUNIQUE))
        mp->m_normal = FALSE;

    /* gods automatically get special abilities */

    if (on(*tp, ISGOD))
    {
        turn_on(*tp, CANFRIGHTEN);
        turn_on(*tp, CANCAST);
        turn_on(*tp, CANFLY);
        turn_on(*tp, CANBARGAIN);
        turn_on(*tp, ISLARGE);
        turn_on(*tp, CANTELEPORT);
        turn_on(*tp, CANSPEAK);
        turn_on(*tp, CANDARKEN);
        turn_on(*tp, CANSEE);
        turn_on(*tp, CANLIGHT);
        turn_on(*tp, BMAGICHIT);
    }

    tp->t_turn = TRUE;
    tp->t_pack = NULL;

    /* Figure intelligence */

    min_intel = atoi(mp->m_intel);

    if ((ip = (char *) strchr(mp->m_intel, '-')) == NULL)
        tp->t_stats.s_intel = min_intel;
    else
    {
        max_intel = atoi(++ip);

        if (max_monster)
            tp->t_stats.s_intel = max_intel;
        else
            tp->t_stats.s_intel = min_intel + rnd(max_intel - min_intel);
    }

    tp->t_stats.s_power = (rnd(tp->t_stats.s_lvl / 5) + 1) * tp->t_stats.s_intel;

    tp->maxstats = tp->t_stats; /* structure assignment */

    /* If the monster can shoot, it may have a weapon */

    if (on(*tp, CANSHOOT) && (max_monster || rnd(9) < 6))
    {
        struct linked_list  *thrower_item, *missile_item;
        struct object *thrower, *a_missile;

        thrower_item = new_item(sizeof *thrower);
        thrower = OBJPTR(thrower_item);
        carried_weapon(tp, thrower);

        missile_item = new_item(sizeof *a_missile);
        a_missile = OBJPTR(missile_item);
        carried_weapon(tp, a_missile);

        /* The monster may use a crossbow, sling, footbow, or an arrow */
        /* Take racial preferences into account */

        if ((strcmp(mp->m_name, "elf") == 0) ||
            (strcmp(mp->m_name, "noldor elf") == 0))
        {
            thrower->o_which = BOW;

            if (rnd(5) == 0)
                a_missile->o_which = SILVERARROW;
            else
                a_missile->o_which = ARROW;
        }
        else if ((strcmp(mp->m_name, "dwarf") == 0) ||
                (strcmp(mp->m_name, "kazad dwarf") == 0))
        {
            thrower->o_which = CROSSBOW;
            a_missile->o_which = BOLT;
        }
        else if (on(*tp, ISSMALL))
        {
            switch (rnd(3))
            {
                case 0:
                    thrower->o_which = SLING;
                    a_missile->o_which = BULLET;
                    break;
                default:
                    thrower->o_which = SLING;
                    a_missile->o_which = ROCK;
            }
        }
        else if (on(*tp, ISLARGE))
        {
            switch (rnd(4))
            {
                case 0:
                    thrower->o_which = CROSSBOW;
                    a_missile->o_which = BOLT;
                    break;

                case 1:
                    thrower->o_which = FOOTBOW;
                    a_missile->o_which = FBBOLT;
                    break;

                default:
                    thrower->o_which = BOW;

                    if (rnd(5) == 0)
                        a_missile->o_which = FLAMEARROW;
                    else
                        a_missile->o_which = ARROW;

                    break;
            }
        }
        else
        {
            switch (rnd(6))
            {
                case 1:
                    thrower->o_which = SLING;
                    a_missile->o_which = ROCK;
                    break;

                case 2:
                    thrower->o_which = CROSSBOW;
                    a_missile->o_which = BOLT;
                    break;

                case 3:
                    thrower->o_which = FOOTBOW;
                    a_missile->o_which = FBBOLT;
                    break;

                case 4:
                    thrower->o_which = BOW;
                    a_missile->o_which = ARROW;
                    break;

                default:
                    thrower->o_which = SLING;
                    a_missile->o_which = BULLET;
                    break;
            }
        }

        init_weapon(thrower, thrower->o_which);
        init_weapon(a_missile, a_missile->o_which);

        attach(tp->t_pack, thrower_item);
        attach(tp->t_pack, missile_item);
    }

    /* monsters that wield weapons */

    if (on(*tp, CANWIELD))
    {
        if (max_monster || rnd(3))
        {
            struct linked_list  *wield_item;
            struct object   *wielded;

            wield_item = new_item(sizeof *wielded);
            wielded = OBJPTR(wield_item);
            carried_weapon(tp, wielded);

            i = rnd(CLAYMORE - CLUB) + rnd(2 * tp->t_stats.s_lvl);
            i = min(i, CLAYMORE);
            wielded->o_which = i;
            init_weapon(wielded, wielded->o_which);

            /* Is it too heavy? */

            if (itemweight(wielded) > 8 * tp->t_stats.s_str)
                discard(wield_item);
            else
                attach(tp->t_pack, wield_item);
        }
    }

    if (is_wearing(R_AGGR))
        chase_it(cp, &player);
    else
    {
        turn_off(*tp, ISRUN);

        if (on(*tp, ISFLEE) && (rnd(4) == 0))
            turn_off(*tp, ISFLEE);

        if (rnd(luck) == 0)
            switch (player.t_ctype)
            {
                case C_MAGICIAN:
                case C_ILLUSION:
                    eff_intel = 2 * pstats.s_intel;
                    break;
                case C_DRUID:
                    eff_intel = 2 * pstats.s_intel;
                case C_RANGER:
                    eff_charisma = 2 * pstats.s_charisma;
                    break;
                case C_ASSASIN:
                case C_THIEF:
                case C_NINJA:
                    eff_charisma = pstats.s_charisma / 2;
                    break;
            }

        /* LOWFRIENDLY monsters might be friendly */

        i = roll(1,100);

        if (i == 0 || (on(*tp, LOWFRIENDLY) && i < eff_charisma) ||
            (on(*tp, MEDFRIENDLY) && i < 3 * eff_charisma) ||
            (on(*tp, HIGHFRIENDLY) && i < 5 * eff_charisma))
        {
            turn_on(*tp, ISFRIENDLY);
            turn_off(*tp, ISMEAN);
        }

        i = roll(1,100);

        if (i == 0 || (on(*tp, LOWCAST) && i < eff_intel) ||
            (on(*tp, MEDCAST) && i < 3 * eff_intel) ||
            (on(*tp, HIGHCAST) && i < 5 * eff_intel))
        {
            turn_on(*tp, CANCAST);
        }

        if (on(*tp, ISDISGUISE))
        {
            char    mch = 0;

            if (tp->t_pack != NULL)
                mch = (OBJPTR(tp->t_pack))->o_type;
            else
                switch (rnd(level > arts[0].ar_level ? 10 : 9))
                {
                    case 0: mch = GOLD;     break;
                    case 1: mch = POTION;   break;
                    case 2: mch = SCROLL;   break;
                    case 3: mch = FOOD;     break;
                    case 4: mch = WEAPON;   break;
                    case 5: mch = ARMOR;    break;
                    case 6: mch = RING;     break;
                    case 7: mch = STICK;    break;
                    case 8: mch = monsters[randmonster(NOWANDER, NOGRAB)].m_appear;
                                break;
                    case 9: mch = ARTIFACT; break;
                }

            tp->t_disguise = mch;
        }
    }
}
Exemplo n.º 12
0
// This must be called when any of the following change:
// - effects
// - bionics
// - traits
// - underwater
// - clothes
// With the exception of clothes, all changes to these character attributes must
// occur through a function in this class which calls this function. Clothes are
// typically added/removed with wear() and takeoff(), but direct access to the
// 'wears' vector is still allowed due to refactor exhaustion.
void Character::recalc_sight_limits()
{
    sight_max = 9999;
    vision_mode_cache.reset();

    // Set sight_max.
    if (has_effect("blind") || worn_with_flag("BLIND") || has_active_bionic("bio_blindfold")) {
        sight_max = 0;
    } else if( has_effect("boomered") && (!(has_trait("PER_SLIME_OK"))) ) {
        sight_max = 1;
        vision_mode_cache.set( BOOMERED );
    } else if (has_effect("in_pit") ||
            (underwater && !has_bionic("bio_membrane") &&
                !has_trait("MEMBRANE") && !worn_with_flag("SWIM_GOGGLES") &&
                !has_trait("CEPH_EYES") && !has_trait("PER_SLIME_OK") ) ) {
        sight_max = 1;
    } else if (has_active_mutation("SHELL2")) {
        // You can kinda see out a bit.
        sight_max = 2;
    } else if ( (has_trait("MYOPIC") || has_trait("URSINE_EYE")) &&
            !is_wearing("glasses_eye") && !is_wearing("glasses_monocle") &&
            !is_wearing("glasses_bifocal") && !has_effect("contacts")) {
        sight_max = 4;
    } else if (has_trait("PER_SLIME")) {
        sight_max = 6;
    } else if( has_effect( "darkness" ) ) {
        vision_mode_cache.set( DARKNESS );
        sight_max = 10;
    }

    // Debug-only NV, by vache's request
    if( has_trait("DEBUG_NIGHTVISION") ) {
        vision_mode_cache.set( DEBUG_NIGHTVISION );
    }
    if( has_nv() ) {
        vision_mode_cache.set( NV_GOGGLES );
    }
    if( has_active_mutation("NIGHTVISION3") || is_wearing("rm13_armor_on") ) {
        vision_mode_cache.set( NIGHTVISION_3 );
    }
    if( has_active_mutation("ELFA_FNV") ) {
        vision_mode_cache.set( FULL_ELFA_VISION );
    }
    if( has_active_mutation("CEPH_VISION") ) {
        vision_mode_cache.set( CEPH_VISION );
    }
    if (has_active_mutation("ELFA_NV")) {
        vision_mode_cache.set( ELFA_VISION );
    }
    if( has_active_mutation("NIGHTVISION2") ) {
        vision_mode_cache.set( NIGHTVISION_2 );
    }
    if( has_active_mutation("FEL_NV") ) {
        vision_mode_cache.set( FELINE_VISION );
    }
    if( has_active_mutation("URSINE_EYE") ) {
        vision_mode_cache.set( URSINE_VISION );
    }
    if (has_active_mutation("NIGHTVISION")) {
        vision_mode_cache.set(NIGHTVISION_1);
    }
    if( has_trait("BIRD_EYE") ) {
        vision_mode_cache.set( BIRD_EYE);
    }
}
Exemplo n.º 13
0
void
death(int monst)
{
    char **dp = (char **) rip, *killer;
    struct tm   *lt;
    time_t  date;
    char    buf[80];
	int c;

    if (is_wearing(R_RESURRECT) || rnd(wizard ? 3 : 67) == 0)
    {
        int die = TRUE;

        if (resurrect-- == 0)
            msg("You've run out of lives.");
        else if (!save_resurrect(ring_value(R_RESURRECT)))
            msg("Your attempt to return from the grave fails.");
        else
        {
            struct linked_list  *item;
            struct linked_list  *next_item;
            struct object   *obj;
            int rm, flags;
            coord   pos;

            die = FALSE;
            msg("You feel a sudden warmth and then nothingness.");
            teleport();

            if (ring_value(R_RESURRECT) > 1 && rnd(10))
            {
                pstats.s_hpt = 2 * pstats.s_const;
                pstats.s_const = max(pstats.s_const - 1, 3);
            }
            else
            {
                for (item = pack; item != NULL; item = next_item)
                {
                    obj = OBJPTR(item);

                    if (obj->o_flags & ISOWNED || obj->o_flags & ISPROT)
                    {
                        next_item = next(item);
                        continue;
                    }

                    flags = obj->o_flags;
                    obj->o_flags &= ~ISCURSED;
                    dropcheck(obj);
                    obj->o_flags = flags;
                    next_item = next(item);
                    rem_pack(obj);

                    if (obj->o_type == ARTIFACT)
                        has_artifact &= ~(1 << obj->o_which);

                    do
                    {
                        rm = rnd_room();
                        rnd_pos(&rooms[rm], &pos);
                    }
                    while(winat(pos.y, pos.x) != FLOOR);

                    obj->o_pos = pos;
                    add_obj(item, obj->o_pos.y, obj->o_pos.x);
                }

                pstats.s_hpt = pstats.s_const;
                pstats.s_const = max(pstats.s_const - roll(2, 2), 3);
            }

            chg_str(roll(1, 4), TRUE, FALSE);
            pstats.s_lvl = max(pstats.s_lvl, 1);
            no_command += 2 + rnd(4);

            if (on(player, ISHUH))
                lengthen_fuse(FUSE_UNCONFUSE, rnd(8) + HUHDURATION);
            else
                light_fuse(FUSE_UNCONFUSE, 0, rnd(8) + HUHDURATION, AFTER);

            turn_on(player, ISHUH);
            light(&hero);
        }

        if (die)
        {
            wmove(cw, mpos, 0);
            waddstr(cw, morestr);
            wrefresh(cw);
            wait_for(' ');
        }
        else
            return;
    }

    time(&date);
    lt = localtime(&date);
    clear();
    wclear(cw);
    move(8, 0);

    while (*dp)
        printw("%s\n", *dp++);

    mvaddstr(14, 28 - ((int)(strlen(whoami) + 1) / 2), whoami);
    sprintf(buf, "%d+%ld Points", pstats.s_lvl, pstats.s_exp);
    mvaddstr(15, 28 - ((int)(strlen(buf) + 1) / 2), buf);
    killer = killname(monst,buf);
    mvaddstr(17, 28 - ((int)(strlen(killer) + 1) / 2), killer);
    mvaddstr(18, 28, (sprintf(prbuf, "%2d", lt->tm_year), prbuf));
    move(LINES - 1, 0);

    mvaddstr(LINES - 1, 0, retstr);

    while ((c = readcharw(stdscr)) != '\n' && c != '\r')
        continue;
    idenpack();
    wrefresh(cw);
    refresh();

    score(pstats.s_exp, pstats.s_lvl, KILLED, monst);
    byebye();
}
Exemplo n.º 14
0
int player::hit_roll()
{
 int stat = dex_cur;
// Some martial arts use something else to determine hits!
 if(weapon.typeId() == "style_tiger"){
   stat = (str_cur * 2 + dex_cur) / 3;
 } else if(weapon.typeId() == "style_leopard"){
   stat = (per_cur + int_cur + dex_cur * 2) / 4;
 } else if(weapon.typeId() == "style_snake"){
   stat = (per_cur + dex_cur) / 2;
 }
 int numdice = base_to_hit(stat) + weapon.type->m_to_hit +
               disease_intensity(DI_ATTACK_BOOST);
 int sides = 10 - encumb(bp_torso);
 int best_bonus = 0;
 if (sides < 2)
  sides = 2;

// Are we unarmed?
 if (unarmed_attack()) {
  best_bonus = skillLevel("unarmed");
  if (skillLevel("unarmed") > 4)
   best_bonus += skillLevel("unarmed") - 4; // Extra bonus for high levels
 }

// Using a bashing weapon?
 if (weapon.is_bashing_weapon()) {
  int bash_bonus = int(skillLevel("bashing") / 3);
  if (bash_bonus > best_bonus)
   best_bonus = bash_bonus;
 }

// Using a cutting weapon?
 if (weapon.is_cutting_weapon()) {
  int cut_bonus = int(skillLevel("cutting") / 2);
  if (cut_bonus > best_bonus)
   best_bonus = cut_bonus;
 }

// Using a spear?
 if (weapon.has_flag("SPEAR") || weapon.has_flag("STAB")) {
  int stab_bonus = int(skillLevel("stabbing") / 2);
  if (stab_bonus > best_bonus)
   best_bonus = stab_bonus;
 }

 numdice += best_bonus; // Use whichever bonus is best.

// Drunken master makes us hit better
 if (has_trait(PF_DRUNKEN)) {
  if (unarmed_attack())
   numdice += int(disease_level(DI_DRUNK) / 300);
  else
   numdice += int(disease_level(DI_DRUNK) / 400);
 }

// Farsightedness makes us hit worse
 if (has_trait(PF_HYPEROPIC) && !is_wearing("glasses_reading")) {
  numdice -= 2;
 }

 if (numdice < 1) {
  numdice = 1;
  sides = 8 - encumb(bp_torso);
 }

 return dice(numdice, sides);
}
Exemplo n.º 15
0
void
wanderer(void)
{
    int i, cnt = 0;
    struct room *hr = roomin(hero);
    struct linked_list  *item;
    struct thing    *tp;
    coord   cp;
    char    *loc;
    int which;

    /* Find a place for it -- avoid the player's room */

    do
    {
        do
        {
            cnt++;
            i = rnd_room();
        }
        while (!(hr != &rooms[i] || levtype == MAZELEV
               || levtype == THRONE || cnt > 5000));

        rnd_pos(&rooms[i], &cp);
    }
    while(!step_ok(cp.y, cp.x, NOMONST, NULL));

    /* Create a new wandering monster */

    item = new_item(sizeof *tp);
    which = randmonster(TRUE, FALSE);
    new_monster(item, which, &cp, FALSE);

    tp = THINGPTR(item);
    tp->t_pos = cp;     /* Assign the position to the monster */

    chase_it(&tp->t_pos, &player);

    i = rnd(7);

    if (on(*tp, ISSWARM) && i < 5)
        cnt = roll(2, 4);
    else if (on(*tp, ISFLOCK) && i < 5)
        cnt = roll(1, 4);
    else
        cnt = 0;

    for (i = 1; i <= cnt; i++)
    {
        struct linked_list  *ip = creat_mons(tp, which, NOMESSAGE);

        if (ip != NULL)
        {
            struct thing    *mp = THINGPTR(ip);

            if (on(*tp, ISFRIENDLY))
                turn_on(*mp, ISFRIENDLY);
            else
                turn_off(*mp, ISFRIENDLY);
        }
    }

    if (cnt > 0)
    {
        if (on(*tp, LOWCAST) || on(*tp, MEDCAST) || on(*tp, HIGHCAST))
            turn_on(*tp, CANCAST);

        tp->t_stats.s_hpt += roll(2, 8);
        tp->t_stats.s_lvl += roll(2, 3);
        tp->t_stats.s_arm -= roll(1, 6);
        tp->t_stats.s_str += roll(2, 3);
        tp->t_stats.s_intel += roll(2, 3);
        tp->t_stats.s_exp += roll(2, 8) * monsters[which].m_add_exp;
    }

    i = DISTANCE(cp, hero);

    if (i < 20)
        loc = "very close to you";
    else if (i < 400)
        loc = "nearby";
    else
        loc = "in the distance";

    if (wizard)
        msg("Started a wandering %s.", monsters[tp->t_index].m_name);
    else if (on(*tp, ISUNDEAD) && (player.t_ctype == C_CLERIC ||
            player.t_ctype == C_PALADIN || is_wearing(R_PIETY)))
        msg("You sense a new ungodly monster %s.", loc);
    else if (on(player, CANHEAR) || (player.t_ctype == C_THIEF &&
            rnd(20) == 0))
        msg("You hear a new %s moving %s.",
            monsters[tp->t_index].m_name, loc);
    else if (on(player, CANSCENT) || (player.t_ctype == C_THIEF &&
            rnd(20) == 0))
        msg("You smell a new %s %s.", monsters[tp->t_index].m_name,
            loc);
}
Exemplo n.º 16
0
void
doctor(daemon_arg *who)
{
    struct thing *tp = who->thingptr;
    long ohp;   /* turn off ISFLEE? */
    struct stats *curp;  /* current stats pointer */
    struct stats *maxp;  /* max stats pointer */
    int         turns_quiet, new_points;

    curp = &(tp->t_stats);
    maxp = &(tp->maxstats);

    if (on(*tp, ISINWALL))
    {
        tp->t_rest_hpt = 0;
        return;
    }

    /* Check for regenerating spell points first */

    doctor_spell_points(tp);

    if (curp->s_hpt == maxp->s_hpt)
    {
        tp->t_rest_hpt = 0;
        return;
    }

    tp->t_rest_hpt++;

    switch (tp->t_ctype)
    {
        case C_MAGICIAN:
        case C_ILLUSION:
            turns_quiet = 24 - curp->s_lvl;
            new_points = curp->s_lvl / 2 - 4;
            break;

        case C_THIEF:
        case C_ASSASIN:
        case C_NINJA:
            turns_quiet = 16 - curp->s_lvl;
            new_points = curp->s_lvl / 2 - 1;
            break;

        case C_CLERIC:
        case C_DRUID:
            turns_quiet = 16 - curp->s_lvl;
            new_points = curp->s_lvl / 2 - 2;
            break;

        case C_FIGHTER:
        case C_RANGER:
        case C_PALADIN:
            turns_quiet = 8 - curp->s_lvl / 2;
            new_points = curp->s_lvl / 2 - 1;
            break;

        case C_MONSTER:
            turns_quiet = 16 - curp->s_lvl;
            new_points = curp->s_lvl / 2 - 6;
            break;

        default:
            debug("What a strange character you are!");
            return;
    }

    ohp = curp->s_hpt;

    if (off(*tp, HASDISEASE))
    {
        if (curp->s_lvl < 8)
        {
            if (tp->t_rest_hpt > turns_quiet)
                curp->s_hpt++;
        }
        else if (tp->t_rest_hpt >= 15)
            curp->s_hpt += rnd(new_points) + 1;
    }

    if (tp == &player)
    {
        if (curp->s_lvl > 10)
            turns_quiet = 2;
        else
            turns_quiet = rnd(turns_quiet / 6) + 1;

        if (is_wearing(R_REGEN))
            curp->s_hpt += ring_value(R_REGEN);
    }

    if (on(*tp, ISREGEN))
        curp->s_hpt += curp->s_lvl / 5 + 1;

    if (ohp != curp->s_hpt)
    {
        if (curp->s_hpt >= maxp->s_hpt)
        {
            curp->s_hpt = maxp->s_hpt;

            if (off(*tp, WASTURNED) && on(*tp, ISFLEE)
                && tp != &player)
            {
                turn_off(*tp, ISFLEE);
                tp->t_oldpos = tp->t_pos;
                /* Start our trek over */
            }
        }
        tp->t_rest_hpt = 0;
    }

    return;
}
Exemplo n.º 17
0
void
doctor_spell_points(struct thing *tp)
{
    int        turns_quiet, new_points;
    struct stats *curp;   /* current stats pointer */
    struct stats *maxp;   /* max stats pointer */
    int         opower; /* current power */

    curp = &(tp->t_stats);
    maxp = &(tp->maxstats);
    opower = curp->s_power;

    /* The right ring will let you regenerate while wearing bad armor */

    if (off(*tp, CANCAST) ||
        ((tp == &player) &&
         (cur_armor && wear_ok(tp, cur_armor, NOMESSAGE) == FALSE) &&
         !(is_wearing(R_WIZARD) || is_wearing(R_PIETY))))
    {
        tp->t_rest_pow = 0;
        return;
    }

    tp->t_rest_pow++;

    switch (tp->t_ctype)
    {
        case C_MAGICIAN:
        case C_ILLUSION:
            turns_quiet = 18 - curp->s_lvl / 2;
            new_points = curp->s_lvl / 2;
            break;
        case C_CLERIC:
        case C_DRUID:
            turns_quiet = 24 - curp->s_lvl;
            new_points = curp->s_lvl / 2 - 2;
            break;
        case C_THIEF:
        case C_ASSASIN:
        case C_NINJA:
            turns_quiet = 32 - curp->s_lvl;
            new_points = curp->s_lvl / 3 - 3;
            break;
        case C_FIGHTER:
        case C_RANGER:
        case C_PALADIN:
            turns_quiet = 32 - curp->s_lvl;
            new_points = curp->s_lvl / 3 - 4;
            break;
        case C_MONSTER:
            turns_quiet = 24 - curp->s_lvl;
            new_points = curp->s_lvl - 6;
            break;
        default:
            return;
    }

    if (curp->s_lvl < 8)
    {
        if (tp->t_rest_pow > turns_quiet)
            curp->s_power++;
    }
    else if (tp->t_rest_pow >= 15)
        curp->s_power += rnd(new_points) + 1;

    if (tp == &player && (is_wearing(R_WIZARD) || is_wearing(R_PIETY)))
        curp->s_power += ring_value(R_WIZARD) + ring_value(R_PIETY);

    curp->s_power = min(max(0, curp->s_power), maxp->s_power);

    if (curp->s_power != opower)
        tp->t_rest_pow = 0;

    return;
}
Exemplo n.º 18
0
void player::complete_craft()
{
    const recipe *making = &recipe_dict[ activity.name ]; // Which recipe is it?
    int batch_size = activity.values.front();
    if( making == nullptr ) {
        debugmsg( "no recipe with id %s found", activity.name.c_str() );
        activity.set_to_null();
        return;
    }

    int secondary_dice = 0;
    int secondary_difficulty = 0;
    for( const auto &pr : making->required_skills ) {
        secondary_dice += get_skill_level( pr.first );
        secondary_difficulty += pr.second;
    }

    // # of dice is 75% primary skill, 25% secondary (unless secondary is null)
    int skill_dice;
    if( secondary_difficulty > 0 ) {
        skill_dice = get_skill_level( making->skill_used ) * 3 + secondary_dice;
    } else {
        skill_dice = get_skill_level( making->skill_used ) * 4;
    }

    auto helpers = g->u.get_crafting_helpers();
    for( const npc *np : helpers ) {
        if( np->get_skill_level( making->skill_used ) >=
            get_skill_level( making->skill_used ) ) {
            // NPC assistance is worth half a skill level
            skill_dice += 2;
            add_msg( m_info, _( "%s helps with crafting..." ), np->name.c_str() );
            break;
        }
    }

    // farsightedness can impose a penalty on electronics and tailoring success
    // it's equivalent to a 2-rank electronics penalty, 1-rank tailoring
    if( has_trait( trait_id( "HYPEROPIC" ) ) && !is_wearing( "glasses_reading" ) &&
        !is_wearing( "glasses_bifocal" ) && !has_effect( effect_contacts ) ) {
        int main_rank_penalty = 0;
        if( making->skill_used == skill_id( "electronics" ) ) {
            main_rank_penalty = 2;
        } else if( making->skill_used == skill_id( "tailor" ) ) {
            main_rank_penalty = 1;
        }
        skill_dice -= main_rank_penalty * 4;
    }

    // It's tough to craft with paws.  Fortunately it's just a matter of grip and fine-motor,
    // not inability to see what you're doing
    if( has_trait( trait_PAWS ) || has_trait( trait_PAWS_LARGE ) ) {
        int paws_rank_penalty = 0;
        if( has_trait( trait_PAWS_LARGE ) ) {
            paws_rank_penalty += 1;
        }
        if( making->skill_used == skill_id( "electronics" )
            || making->skill_used == skill_id( "tailor" )
            || making->skill_used == skill_id( "mechanics" ) ) {
            paws_rank_penalty += 1;
        }
        skill_dice -= paws_rank_penalty * 4;
    }

    // Sides on dice is 16 plus your current intelligence
    ///\EFFECT_INT increases crafting success chance
    int skill_sides = 16 + int_cur;

    int diff_dice;
    if( secondary_difficulty > 0 ) {
        diff_dice = making->difficulty * 3 + secondary_difficulty;
    } else {
        // Since skill level is * 4 also
        diff_dice = making->difficulty * 4;
    }

    int diff_sides = 24; // 16 + 8 (default intelligence)

    int skill_roll = dice( skill_dice, skill_sides );
    int diff_roll  = dice( diff_dice,  diff_sides );

    if( making->skill_used ) {
        const double batch_mult = 1 + time_to_craft( *making, batch_size ) / 30000.0;
        //normalize experience gain to crafting time, giving a bonus for longer crafting
        practice( making->skill_used, ( int )( ( making->difficulty * 15 + 10 ) * batch_mult ),
                  ( int )making->difficulty * 1.25 );

        //NPCs assisting or watching should gain experience...
        for( auto &elem : helpers ) {
            //If the NPC can understand what you are doing, they gain more exp
            if( elem->get_skill_level( making->skill_used ) >= making->difficulty ) {
                elem->practice( making->skill_used,
                                ( int )( ( making->difficulty * 15 + 10 ) * batch_mult *
                                         .50 ), ( int )making->difficulty * 1.25 );
                if( batch_size > 1 ) {
                    add_msg( m_info, _( "%s assists with crafting..." ), elem->name.c_str() );
                }
                if( batch_size == 1 ) {
                    add_msg( m_info, _( "%s could assist you with a batch..." ), elem->name.c_str() );
                }
                //NPCs around you understand the skill used better
            } else {
                elem->practice( making->skill_used,
                                ( int )( ( making->difficulty * 15 + 10 ) * batch_mult * .15 ),
                                ( int )making->difficulty * 1.25 );
                add_msg( m_info, _( "%s watches you craft..." ), elem->name.c_str() );
            }
        }

    }

    // Messed up badly; waste some components.
    if( making->difficulty != 0 && diff_roll > skill_roll * ( 1 + 0.1 * rng( 1, 5 ) ) ) {
        add_msg( m_bad, _( "You fail to make the %s, and waste some materials." ),
                 item::nname( making->result ).c_str() );
        if( last_craft->has_cached_selections() ) {
            last_craft->consume_components();
        } else {
            // @todo Guarantee that selections are cached
            const auto &req = making->requirements();
            for( const auto &it : req.get_components() ) {
                consume_items( it, batch_size );
            }
            for( const auto &it : req.get_tools() ) {
                consume_tools( it, batch_size );
            }
        }
        activity.set_to_null();
        return;
        // Messed up slightly; no components wasted.
    } else if( diff_roll > skill_roll ) {
        add_msg( m_neutral, _( "You fail to make the %s, but don't waste any materials." ),
                 item::nname( making->result ).c_str() );
        //this method would only have been called from a place that nulls activity.type,
        //so it appears that it's safe to NOT null that variable here.
        //rationale: this allows certain contexts (e.g. ACT_LONGCRAFT) to distinguish major and minor failures
        return;
    }

    // If we're here, the craft was a success!
    // Use up the components and tools
    std::list<item> used;
    if( !last_craft->has_cached_selections() ) {
        // This should fail and return, but currently crafting_command isn't saved
        // Meaning there are still cases where has_cached_selections will be false
        // @todo Allow saving last_craft and debugmsg+fail craft if selection isn't cached
        if( !has_trait( trait_id( "DEBUG_HS" ) ) ) {
            const auto &req = making->requirements();
            for( const auto &it : req.get_components() ) {
                std::list<item> tmp = consume_items( it, batch_size );
                used.splice( used.end(), tmp );
            }
            for( const auto &it : req.get_tools() ) {
                consume_tools( it, batch_size );
            }
        }
    } else if( !has_trait( trait_id( "DEBUG_HS" ) ) ) {
        used = last_craft->consume_components();
        if( used.empty() ) {
            return;
        }
    }

    // Set up the new item, and assign an inventory letter if available
    std::vector<item> newits = making->create_results( batch_size );
    bool first = true;
    float used_age_tally = 0;
    int used_age_count = 0;
    size_t newit_counter = 0;
    for( item &newit : newits ) {
        // messages, learning of recipe, food spoilage calc only once
        if( first ) {
            first = false;
            if( knows_recipe( making ) ) {
                add_msg( _( "You craft %s from memory." ), newit.type_name( 1 ).c_str() );
            } else {
                add_msg( _( "You craft %s using a book as a reference." ), newit.type_name( 1 ).c_str() );
                // If we made it, but we don't know it,
                // we're making it from a book and have a chance to learn it.
                // Base expected time to learn is 1000*(difficulty^4)/skill/int moves.
                // This means time to learn is greatly decreased with higher skill level,
                // but also keeps going up as difficulty goes up.
                // Worst case is lvl 10, which will typically take
                // 10^4/10 (1,000) minutes, or about 16 hours of crafting it to learn.
                int difficulty = has_recipe( making, crafting_inventory(), helpers );
                ///\EFFECT_INT increases chance to learn recipe when crafting from a book
                if( x_in_y( making->time, ( 1000 * 8 *
                                            ( difficulty * difficulty * difficulty * difficulty ) ) /
                            ( std::max( get_skill_level( making->skill_used ).level(), 1 ) * std::max( get_int(), 1 ) ) ) ) {
                    learn_recipe( ( recipe * )making );
                    add_msg( m_good, _( "You memorized the recipe for %s!" ),
                             newit.type_name( 1 ).c_str() );
                }
            }

            for( auto &elem : used ) {
                if( elem.goes_bad() ) {
                    used_age_tally += elem.get_relative_rot();
                    ++used_age_count;
                }
            }
        }

        // Don't store components for things made by charges,
        // don't store components for things that can't be uncrafted.
        if( recipe_dictionary::get_uncraft( making->result ) && !newit.count_by_charges() ) {
            // Setting this for items counted by charges gives only problems:
            // those items are automatically merged everywhere (map/vehicle/inventory),
            // which would either loose this information or merge it somehow.
            set_components( newit.components, used, batch_size, newit_counter );
            newit_counter++;
        }
        finalize_crafted_item( newit, used_age_tally, used_age_count );
        set_item_inventory( newit );
    }

    if( making->has_byproducts() ) {
        std::vector<item> bps = making->create_byproducts( batch_size );
        for( auto &bp : bps ) {
            finalize_crafted_item( bp, used_age_tally, used_age_count );
            set_item_inventory( bp );
        }
    }

    inv.restack( this );
}
Exemplo n.º 19
0
struct linked_list *
wake_monster(int y, int x)
{
    struct thing    *tp;
    struct linked_list  *it;
    struct room *trp;
    char    *mname;

    if ((it = find_mons(y, x)) == NULL)
    {
        debug("Can't find monster in show.");
        return(NULL);
    }

    tp = THINGPTR(it);

    if ((good_monster(*tp)) || on(player, SUMMONING))
    {
        chase_it(&tp->t_pos, &player);
        turn_off(*tp, ISINVIS);
        turn_off(*tp, CANSURPRISE);
        return(it);
    }

    trp = roomin(tp->t_pos);   /* Current room for monster */
    mname = monsters[tp->t_index].m_name;

    /* Let greedy ones guard gold */

    if (on(*tp, ISGREED) && off(*tp, ISRUN))
        if ((trp != NULL) && (lvl_obj != NULL))
        {
            struct linked_list  *item;
            struct object   *cur;

            for (item = lvl_obj; item != NULL; item = next(item))
            {
                cur = OBJPTR(item);

                if ((cur->o_type == GOLD) &&
                    (roomin(cur->o_pos) == trp))
                {
                    /* Run to the gold */
                    tp->t_horde = cur;
                    turn_on(*tp, ISRUN);
                    turn_off(*tp, ISDISGUISE);
                    tp->t_ischasing = FALSE;
                    /* Make it worth protecting */
                    cur->o_count += roll(2, 3) * GOLDCALC;
                    break;
                }
            }
        }

    /*
     * Every time he sees mean monster, it might start chasing him unique
     * monsters always do
     */

    if (  (on(*tp, ISUNIQUE)) ||
          ( (rnd(100) > 33) &&
            on(*tp, ISMEAN) &&
            off(*tp, ISHELD) &&
            off(*tp, ISRUN) &&
            !is_stealth(&player) &&
            (off(player, ISINVIS) || on(*tp, CANSEE))
          )
       )
    {
        chase_it(&tp->t_pos, &player);
    }

    /* Handle gaze attacks */

    if (on(*tp, ISRUN) && cansee(tp->t_pos.y, tp->t_pos.x) &&
            off(player, ISINVIS))
    {
        if (on(*tp, CANHUH))    /* Confusion */
        {
            if (on(player, CANREFLECT))
            {
                msg("You reflect the bewildering stare of the %s.", mname);

                if (save_throw(VS_MAGIC, tp))
                {
                    msg("The %s is confused!", mname);
                    turn_on(*tp, ISHUH);
                }
                else
                    msg("The %s staggers for a moment.", mname);
            }
            else if (save(VS_MAGIC))
            {
                msg("You feel dizzy for a moment, but it quickly passes.");

                if (rnd(100) < 67)
                    turn_off(*tp, CANHUH);
            }
            else if (off(player, ISCLEAR))
            {
                if (off(player, ISHUH))
                {
                    light_fuse(FUSE_UNCONFUSE, 0, rnd(20) + HUHDURATION, AFTER);
                    msg("The %s's gaze has confused you.", mname);
                    turn_on(player, ISHUH);
                }
                else
                    lengthen_fuse(FUSE_UNCONFUSE, rnd(20) + HUHDURATION);
            }
        }

        if (on(*tp, CANSNORE))      /* Sleep */
        {
            if (on(player, CANREFLECT))
            {
                msg("You reflect the lethargic glance of the %s", mname);

                if (save_throw(VS_PARALYZATION, tp))
                {
                    msg("The %s falls asleep!", mname);
                    tp->t_no_move += SLEEPTIME;
                }
            }
            else if (no_command == 0 && !save(VS_PARALYZATION))
            {
                if (is_wearing(R_ALERT))
                    msg("You feel slightly drowsy for a moment.");
                else
                {
                    msg("The %s's gaze puts you to sleep.", mname);
                    no_command = SLEEPTIME;

                    if (rnd(100) < 50)
                        turn_off(*tp, CANSNORE);
                }
            }
        }

        if (on(*tp, CANFRIGHTEN))   /* Fear */
        {
            turn_off(*tp, CANFRIGHTEN);

            if (on(player, CANREFLECT))
            {
                msg("The %s sees its reflection. ", mname);

                if (save_throw(VS_MAGIC,tp))
                {
                    msg("The %s is terrified by its reflection!", mname);
                    turn_on(*tp, ISFLEE);
                }
            }
            else
            {
                if (!save(VS_WAND) && !(on(player, ISFLEE) &&
                       (player.t_chasee==tp)))
                {
                    if ((player.t_ctype != C_PALADIN) &&
                        off(player, SUPERHERO))
                    {
                        turn_on(player, ISFLEE);
                        player.t_ischasing = FALSE;
                        player.t_chasee    = tp;
                        msg("The sight of the %s terrifies you.", mname);
                    }
                    else
                        msg("My, the %s looks ugly.", mname);
                }
            }
        }

        if (on(*tp, LOOKSLOW))     /* Slow */
        {
            turn_off(*tp, LOOKSLOW);

            if (on(player, CANREFLECT))
            {
                msg("You reflect the mournful glare of the %s.", mname);

                if (save_throw(VS_MAGIC,tp))
                {
                    msg("The %s is slowing down!", mname);
                    turn_on(*tp, ISSLOW);
                }
            }
            else if (is_wearing(R_FREEDOM) || save(VS_MAGIC))
                msg("You feel run-down for a moment.");
            else
            {
                if (on(player, ISHASTE))    /* Already sped up */
                {
                    extinguish_fuse(FUSE_NOHASTE);
                    nohaste(NULL);
                }
                else
                {
                    msg("You feel yourself moving %sslower.",
                     on(player, ISSLOW) ? "even " : "");

                    if (on(player, ISSLOW))
                        lengthen_fuse(FUSE_NOSLOW, rnd(4) + 4);
                    else
                    {
                        turn_on(player, ISSLOW);
                        player.t_turn = TRUE;
                        light_fuse(FUSE_NOSLOW, 0, rnd(4) + 4, AFTER);
                    }
                }
            }
        }

        if (on(*tp, CANBLIND))  /* Blinding */
        {
            turn_off(*tp, CANBLIND);

            if (on(player, CANREFLECT))
            {
                msg("You reflect the blinding stare of the %s.", mname);

                if (save_throw(VS_WAND, tp))
                {
                    msg("The %s is blinded!", mname);
                    turn_on(*tp, ISHUH);
                }
            }
            else if (off(player, ISBLIND))
                if (save(VS_WAND) || is_wearing(R_TRUESEE) || is_wearing(R_SEEINVIS))
                    msg("Your eyes film over for a moment.");
                else
                {
                    msg("The gaze of the %s blinds you.", mname);
                    turn_on(player, ISBLIND);
                    light_fuse(FUSE_SIGHT, 0, rnd(30) + 20, AFTER);
                    look(FALSE);
                }
        }

        if (on(*tp, LOOKSTONE))  /* Stoning */
        {
            turn_off(*tp, LOOKSTONE);

            if (on(player, CANREFLECT))
            {
                msg("You reflect the flinty look of the %s.", mname);

                if (save_throw(VS_PETRIFICATION,tp))
                {
                    msg("The %s suddenly stiffens", mname);
                    tp->t_no_move += STONETIME;
                }
                else
                {
                    msg("The %s is turned to stone!", mname);
                    killed(&player, it, NOMESSAGE, POINTS);
                }
            }
            else
            {
                if (on(player, CANINWALL))
                    msg("The %s cannot focus on you.", mname);
                else
                {
                    msg("The gaze of the %s stiffens your limbs.", mname);

                    if (save(VS_PETRIFICATION))
                        no_command = STONETIME;
                    else if (rnd(100))
                        no_command = STONETIME * 3;
                    else
                    {
                        msg("The gaze of the %s petrifies you.", mname);
                        msg("You are turned to stone!!! --More--");
                        wait_for(' ');
                        death(D_PETRIFY);
                        return(it);
                    }
                }
            }
        }
    }

    /*
     * True Sight sees all Never see ISINWALL or CANSURPRISE See ISSHADOW
     * 80% See ISINVIS with See Invisibilty
     */

    if (off(player, CANTRUESEE) &&
        on(*tp, ISINWALL) || on(*tp, CANSURPRISE) ||
        (on(*tp, ISSHADOW) && rnd(100) < 80) ||
        (on(*tp, ISINVIS) && off(player, CANSEE)))
	{
	    /* 
	    TODO: incomplete - need to finish logic
	    int ch = mvwinch(stdscr, y, x); 
	    */
	}
	

    /* hero might be able to hear or smell monster if he can't see it */

    if ((rnd(player.t_ctype == C_THIEF ? 40 : 200) == 0 ||
            on(player, CANHEAR)) && !cansee(tp->t_pos.y, tp->t_pos.x))
        msg("You hear a %s nearby.", mname);
    else if ((rnd(player.t_ctype == C_THIEF ? 40 : 200) == 0 ||
            on(player, CANSCENT)) && !cansee(tp->t_pos.y, tp->t_pos.x))
        msg("You smell a %s nearby.", mname);

    return(it);
}
Exemplo n.º 20
0
void
teleport(void)
{
    struct room *new_rp = NULL, *old_rp = roomin(hero);

    int rm, which;
    coord c;
    int is_lit = FALSE; /* For saving room light state */
    int rand_position = TRUE;

    c = hero;

    mvwaddch(cw, hero.y, hero.x, mvwinch(stdscr, hero.y, hero.x));

    if (is_wearing(R_TELCONTROL))
    {
        msg("Where do you wish to teleport to? (* for help)");
        wmove(cw, hero.y, hero.x);
        wrefresh(cw);

        which = (short) (readchar() & 0177);

        while (which != (short) ESCAPE && which != (short) LINEFEED
            && which != (short) CARRIAGE_RETURN)
        {
            switch(which)
            {
                case 'h':   c.x--; break;
                case 'j':   c.y++; break;
                case 'k':   c.y--; break;
                case 'l':   c.x++; break;
                case 'y':   c.x--;
                            c.y--; break;
                case 'u':   c.x++;
                            c.y--; break;
                case 'b':   c.x--;
                            c.y++; break;
                case 'n':   c.x++;
                            c.y++; break;
                case '*':
                    msg("Use h,j,k,l,y,u,b,n to position cursor, then hit"
                        "return.");
            }

            c.y = max(c.y, 1);
            c.y = min(c.y, LINES - 3);
            c.x = max(c.x, 1);
            c.x = min(c.x, COLS - 1);
            wmove(cw, c.y, c.x);
            wrefresh(cw);
            which = (short) (readchar() & 0177);
        }

        which = winat(c.y, c.x);

        if ((which == FLOOR || which == PASSAGE || which == DOOR) &&
            ((ring_value(R_TELCONTROL) == 0 && rnd(10) < 6)
             || (ring_value(R_TELCONTROL) > 0 && rnd(10) < 9)))
        {
            rand_position = FALSE;
            msg("You attempt succeeds.");
            hero = c;
            new_rp = roomin(hero);
        }
        else
            msg("Your attempt fails.");
    }

    if (rand_position)
    {
        do
        {
            rm = rnd_room();
            rnd_pos(&rooms[rm], &hero);
        }
        while (winat(hero.y, hero.x) != FLOOR);

        new_rp = &rooms[rm];
    }

    /* If hero gets moved, darken old room */

    if (old_rp && old_rp != new_rp)
    {
        if (!(old_rp->r_flags & ISDARK))
            is_lit = TRUE;

        old_rp->r_flags |= ISDARK;  /* Fake darkness */
        light(&c);

        if (is_lit)
            old_rp->r_flags &= ~ISDARK; /* Restore light state */
    }

    light(&hero);
    mvwaddch(cw, hero.y, hero.x, PLAYER);

    /* turn off ISHELD in case teleportation was done while fighting */

    if (on(player, ISHELD))
    {
        struct linked_list  *ip, *nip;
        struct thing    *mp;

        turn_off(player, ISHELD);
        hold_count = 0;

        for (ip = mlist; ip; ip = nip)
        {
            mp = THINGPTR(ip);
            nip = next(ip);

            if (on(*mp, DIDHOLD))
            {
                turn_off(*mp, DIDHOLD);
                turn_on(*mp, CANHOLD);
            }

            turn_off(*mp, DIDSUFFOCATE);
        }
    }

    extinguish_fuse(FUSE_SUFFOCATE);
    player.t_no_move = 0;   /* not trapped anymore */
    count = 0;
    running = FALSE;

    return;
}