static bool _elemental_healing(int flag)
{
    int dir, ct = 0;

    if (!cave_have_flag_bold(py, px, flag))
    {
        msg_print("Failed! You are out of your element!");
        return FALSE;
    }

    for (dir = 0; dir < 8; dir++)
    {
        int x = px + ddx_ddd[dir];
        int y = py + ddy_ddd[dir];
        
        if (!in_bounds(y, x)) continue;
        if (cave_have_flag_bold(y, x, flag)) ct++;
    }

    if (ct < 4)
    {
        msg_print("Failed! You need to be surrounded by your element!");
        return FALSE;
    }

    msg_print("You bask in your element and slowly feel your life returning ... ");
    hp_player(100 + p_ptr->lev * 3);
    return TRUE;
}
예제 #2
0
static void _excavation_spell(int cmd, variant *res)
{
    switch (cmd)
    {
    case SPELL_NAME:
        var_set_string(res, "Excavation");
        break;
    case SPELL_DESC:
        var_set_string(res, "You break walls on your quest for treasure!  This takes a bit more time, though.");
        break;
    case SPELL_ENERGY:
        {
            int n = 200;
            
            if (equip_find_object(TV_DIGGING, SV_ANY))
                n -= 120 * p_ptr->lev / 50;
            else
                n -= 80 * p_ptr->lev / 50;

            var_set_int(res, n);
        }
        break;
    case SPELL_CAST:
        {
            int dir = 5;
            bool b = FALSE;

            if ( get_rep_dir2(&dir)
              && dir != 5 )
            {
                int x, y;
                y = py + ddy[dir];
                x = px + ddx[dir];

                if (!in_bounds(y, x))
                {
                    msg_print("You may excavate no further.");
                }
                else if ( cave_have_flag_bold(y, x, FF_WALL)
                       || cave_have_flag_bold(y, x, FF_TREE) 
                       || cave_have_flag_bold(y, x, FF_CAN_DIG) )
                {
                    msg_print("You dig your way to treasure!");
                    cave_alter_feat(y, x, FF_TUNNEL);
                    teleport_player_to(y, x, TELEPORT_NONMAGICAL); /*??*/
                    b = TRUE;
                }
                else
                {
                    msg_print("There is nothing to excavate.");
                }
            }
            var_set_bool(res, b);
        }
        break;
    default:
        default_spell(cmd, res);
        break;
    }
}
예제 #3
0
void _scatter_spell(int cmd, variant *res)
{
    switch (cmd)
    {
    case SPELL_NAME:
        var_set_string(res, "Scatter");
        break;
    case SPELL_DESC:
        var_set_string(res, "Attack all adjacent monsters with a single strike. If landed, your enemies will be scattered away from you.");
        break;
    case SPELL_CAST:
    {
        int              dir, x, y;
        cave_type       *c_ptr;
        monster_type    *m_ptr;

        for (dir = 0; dir < 8; dir++)
        {
            y = py + ddy_ddd[dir];
            x = px + ddx_ddd[dir];
            c_ptr = &cave[y][x];

            m_ptr = &m_list[c_ptr->m_idx];

            if (c_ptr->m_idx && (m_ptr->ml || cave_have_flag_bold(y, x, FF_PROJECT)))
                py_attack(y, x, MAULER_SCATTER);
        }
        var_set_bool(res, TRUE);
        break;
    }
    default:
        default_spell(cmd, res);
        break;
    }
}
static void _cavern_creation_spell(int cmd, variant *res)
{
    switch (cmd)
    {
    case SPELL_NAME:
        var_set_string(res, "Cavern Creation");
        break;
    case SPELL_DESC:
        var_set_string(res, "Stone to Mud all surrounding walls.");
        break;
    case SPELL_CAST:
    {
        int dir, x, y, ct = 0;
        for (dir = 0; dir < 8; dir++)
        {
            y = py + ddy_ddd[dir];
            x = px + ddx_ddd[dir];

            if (!in_bounds(y, x)) continue;
            if (!cave_have_flag_bold(y, x, FF_HURT_ROCK))  continue;
            cave_alter_feat(y, x, FF_HURT_ROCK);
            ct++;
        }
        if (ct)
            p_ptr->update |= (PU_FLOW | PU_BONUS);

        var_set_bool(res, TRUE);
        break;
    }
    default:
        default_spell(cmd, res);
        break;
    }
}
static bool _cave_is_open(int y, int x)
{
    if (cave_have_flag_bold(y, x, FF_HURT_ROCK)) return FALSE;
    if (cave[y][x].feat == feat_permanent) return FALSE;
    if (cave[y][x].feat == feat_permanent_glass_wall) return FALSE;
    if (cave[y][x].feat == feat_mountain) return FALSE;
    return TRUE;
}
예제 #6
0
static void _smash_wall_spell(int cmd, variant *res)
{
    switch (cmd)
    {
    case SPELL_NAME:
        var_set_string(res, "Smash");
        break;
    case SPELL_DESC:
        var_set_string(res, "Destroys adjacent targeted wall, door, tree, or trap.");
        break;
    case SPELL_CAST:
    {
        int y, x, dir;
        
        var_set_bool(res, FALSE);
        if (!get_rep_dir2(&dir)) return;
        if (dir == 5) return;

        y = py + ddy[dir];
        x = px + ddx[dir];
        
        if (!in_bounds(y, x)) return;

        if (cave_have_flag_bold(y, x, FF_HURT_ROCK))
        {
            cave_alter_feat(y, x, FF_HURT_ROCK);
            p_ptr->update |= PU_FLOW;
        }
        else if (cave_have_flag_bold(y, x, FF_TREE))
        {
            cave_set_feat(y, x, one_in_(3) ? feat_brake : feat_grass);
        }
        else
        {
            int flg = PROJECT_GRID | PROJECT_ITEM | PROJECT_HIDE;
            project(0, 0, y, x, 0, GF_KILL_DOOR, flg, -1);
        }
        var_set_bool(res, TRUE);
        break;
    }
    default:
        default_spell(cmd, res);
        break;
    }
}
/*
 * Determine if the given location is "between" two walls,
 * and "next to" two corridor spaces. XXX XXX XXX
 *
 * Assumes "in_bounds(y, x)"
 */
static bool possible_doorway(int y, int x)
{
    /* Count the adjacent corridors */
    if (next_to_corr(y, x) >= 2)
    {
        /* Check Vertical */
        if (cave_have_flag_bold(y - 1, x, FF_WALL) &&
            cave_have_flag_bold(y + 1, x, FF_WALL))
        {
            return (TRUE);
        }

        /* Check Horizontal */
        if (cave_have_flag_bold(y, x - 1, FF_WALL) &&
            cave_have_flag_bold(y, x + 1, FF_WALL))
        {
            return (TRUE);
        }
    }

    /* No doorway */
    return (FALSE);
}
/*
 * Places door at y, x position if at least 2 walls found
 */
static void try_door(int y, int x)
{
    /* Paranoia */
    if (!in_bounds(y, x)) return;

    /* Ignore walls */
    if (cave_have_flag_bold(y, x, FF_WALL)) return;

    /* Ignore room grids */
    if (cave[y][x].info & (CAVE_ROOM)) return;

    /* Occasional door (if allowed) */
    if ((randint0(100) < dun_tun_jct) && possible_doorway(y, x) && !(d_info[dungeon_type].flags1 & DF1_NO_DOORS))
    {
        /* Place a door */
        place_random_door(y, x, FALSE);
    }
}
static bool _elemental_travel(int flag)
{
    int  rng = p_ptr->lev / 2 + 10;
    int  x, y;

    if (!tgt_pt(&x, &y, rng)) return FALSE;
    if (!in_bounds(y, x)) return FALSE;

    if (!cave_have_flag_bold(y, x, flag))
    {
        msg_print("Failed! You are out of your element!");
        teleport_player((p_ptr->lev + 2) * 2, TELEPORT_PASSIVE);
    }
    else if (one_in_(7))
    {
        msg_print("You failed to travel correctly!");
        teleport_player((p_ptr->lev + 2) * 2, TELEPORT_PASSIVE);
    }
    else
        teleport_player_to(y, x, 0);

    return TRUE;
}
예제 #10
0
/*!
 * @brief モンスターが特殊能力の目標地点を決める処理 /
 * Get the actual center point of ball spells (rad > 1) (originally from TOband)
 * @param sy 始点のY座標
 * @param sx 始点のX座標
 * @param ty 目標Y座標を返す参照ポインタ
 * @param tx 目標X座標を返す参照ポインタ
 * @param flg 判定のフラグ配列
 * @return なし
 */
void get_project_point(int sy, int sx, int *ty, int *tx, int flg)
{
	u16b path_g[128];
	int  path_n, i;

	path_n = project_path(path_g, MAX_RANGE, sy, sx, *ty, *tx, flg);

	*ty = sy;
	*tx = sx;

	/* Project along the path */
	for (i = 0; i < path_n; i++)
	{
		sy = GRID_Y(path_g[i]);
		sx = GRID_X(path_g[i]);

		/* Hack -- Balls explode before reaching walls */
		if (!cave_have_flag_bold(sy, sx, FF_PROJECT)) break;

		*ty = sy;
		*tx = sx;
	}
}
예제 #11
0
static void _stone_smash_spell(int cmd, variant *res)
{
    switch (cmd)
    {
    case SPELL_NAME:
        var_set_string(res, "Stone Smash");
        break;
    case SPELL_DESC:
        var_set_string(res, "Destroys adjacent targeted wall.");
        break;
    case SPELL_CAST:
    {
        int y, x, dir;
        
        var_set_bool(res, FALSE);
        if (!get_rep_dir2(&dir)) return;
        if (dir == 5) return;

        y = py + ddy[dir];
        x = px + ddx[dir];
        
        if (!in_bounds(y, x)) return;

        if (cave_have_flag_bold(y, x, FF_HURT_ROCK))
        {
            cave_alter_feat(y, x, FF_HURT_ROCK);
            p_ptr->update |= PU_FLOW;
        }
        var_set_bool(res, TRUE);
        break;
    }
    default:
        default_spell(cmd, res);
        break;
    }
}
예제 #12
0
/* A special fetch(), that places item in player's inventory */
static bool _whip_fetch(int dir, int rng)
{
    int             ty, tx;
    cave_type      *c_ptr;
    object_type    *o_ptr;
    char            o_name[MAX_NLEN];

    /* Use a target */
    if (dir == 5 && target_okay())
    {
        tx = target_col;
        ty = target_row;

        if (distance(py, px, ty, tx) > rng)
        {
            msg_print("You can't fetch something that far away!");
            return FALSE;
        }

        c_ptr = &cave[ty][tx];

        /* We need an item to fetch */
        if (!c_ptr->o_idx)
        {
            msg_print("There is no object at this place.");
            return TRUE;  /* didn't work, but charge the player energy anyway */
        }

        /* Fetching from a vault is OK */

        /* Line of sight is required */
        if (!player_has_los_bold(ty, tx))
        {
            msg_print("You have no direct line of sight to that location.");
            return FALSE;
        }
        else if (!projectable(py, px, ty, tx))
        {
            msg_print("You have no direct line of sight to that location.");
            return FALSE;
        }
    }
    else
    {
        /* Use a direction */
        ty = py; /* Where to drop the item */
        tx = px;

        do
        {
            ty += ddy[dir];
            tx += ddx[dir];
            c_ptr = &cave[ty][tx];

            if ((distance(py, px, ty, tx) > MAX_RANGE) ||
                !in_bounds(ty, tx) ||
                !cave_have_flag_bold(ty, tx, FF_PROJECT))
            {
                return TRUE; /* didn't work, but charge the player energy anyway */
            }
        }
        while (!c_ptr->o_idx);
    }

    o_ptr = &o_list[c_ptr->o_idx];

    if (o_ptr->weight > p_ptr->lev * 15)
    {
        msg_print("The object is too heavy.");
        return TRUE; /* didn't work, but charge the player energy anyway */
    }

    object_desc(o_name, o_ptr, OD_NAME_ONLY);

    /* Get the object */
    if (!inven_carry_okay(o_ptr))
    {
        cmsg_format(TERM_VIOLET, "You fail to fetch %^s since your pack is full.", o_name);
        /* Leave the object where it is */
    }
    else
    {
        msg_format("You skillfully crack your whip and fetch %^s.", o_name);
        py_pickup_aux(c_ptr->o_idx);
    }

    return TRUE;
}
예제 #13
0
static void _double_crack_spell(int cmd, variant *res)
{
    switch (cmd)
    {
    case SPELL_NAME:
        var_set_string(res, "Double Crack");
        break;
    case SPELL_DESC:
        var_set_string(res, "Attack a monster normally with your whip, and then randomly attack an adjacent monster.");
        break;
    case SPELL_CAST:
        if (_whip_check())
        {
            int dir = 5;
            bool b = FALSE;

            if ( get_rep_dir2(&dir)
              && dir != 5 )
            {
                int x, y;
                int num = 1;
                int attempts = 0;

                /* First we attack where the player selected */
                y = py + ddy[dir];
                x = px + ddx[dir];
                if (in_bounds(y, x) && cave[y][x].m_idx)
                    py_attack(y, x, 0);
                else
                    msg_print("Your whip cracks in empty air.");

                /* Now the whip cracks randomly!
                   Note that we favor fighting in hallways, or
                   with ones back up against the wall. */
                while (num > 0)
                {
                    if (attempts > 3 * num)
                    {
                        while (num > 0)
                        {
                            msg_print("Your whip cracks in empty air.");
                            num--;
                        }
                        break;
                    }

                    /* random direction, but we don't penalize for choosing the player (5) */
                    dir = randint0(9);
                    if (dir == 5) continue;
                    
                    attempts++;
                    y = py + ddy[dir];
                    x = px + ddx[dir];

                    if ( !in_bounds(y, x) 
                      || cave_have_flag_bold(y, x, FF_WALL)
                      || cave_have_flag_bold(y, x, FF_TREE) 
                      || cave_have_flag_bold(y, x, FF_CAN_DIG) )
                    {
                        continue;
                    }

                    
                    if (cave[y][x].m_idx)
                        py_attack(y, x, 0);
                    else
                        msg_print("Your whip cracks in empty air.");

                    num--;
                }

                b = TRUE;
            }
            var_set_bool(res, b);
        }
        else
        {
            msg_print("Whip techniques can only be used if you are fighting with whips.");
            var_set_bool(res, FALSE);
        }
        break;
    default:
        default_spell(cmd, res);
        break;
    }
}
static void _greater_whirlwind_attack_spell(int cmd, variant *res)
{
    switch (cmd)
    {
    case SPELL_NAME:
        var_set_string(res, "Greater Ambush");
        break;
    case SPELL_DESC:
        var_set_string(res, "Perform a massive ambush on nearby monsters.");
        break;
    case SPELL_CAST:
    {
        int              i, x, y;
        cave_type       *c_ptr;
        monster_type    *m_ptr;

/*       cba
        d218l
        e3@7k
        f456j
         ghi  */

        typedef struct _offset_t { int dx; int dy; } _offset;
        static _offset offsets[] = {
            { 0, -1},
            {-1, -1},
            {-1,  0},
            {-1,  1},
            { 0,  1},
            { 1,  1},
            { 1,  0},
            { 1, -1},
            { 1, -2},
            { 0, -2},
            {-1, -2},
            {-2, -1},
            {-2,  0},
            {-2,  1},
            {-1,  2},
            { 0,  2},
            { 1,  2},
            { 2,  1},
            { 2,  0},
            { 2, -1},
            { 0,  0}, /* sentinel */
        };

        for (i = 0;; i++)
        {
            _offset offset = offsets[i];
            if (offset.dx == 0 && offset.dy == 0) break;

            y = py + offset.dy;
            x = px + offset.dx;

            if (!in_bounds(y, x)) continue;
            if (!projectable(py, px, y, x)) continue;

            c_ptr = &cave[y][x];

            if (!c_ptr->m_idx) continue;

            m_ptr = &m_list[c_ptr->m_idx];

            if (m_ptr->ml || cave_have_flag_bold(y, x, FF_PROJECT))
            {
                int msec = delay_factor * delay_factor * delay_factor;

                if (panel_contains(y, x) && player_can_see_bold(y, x))
                {
                    char c = 0x30;
                    byte a = TERM_WHITE;

                    print_rel(c, a, y, x);
                    move_cursor_relative(y, x);
                    Term_fresh();
                    Term_xtra(TERM_XTRA_DELAY, msec);
                    lite_spot(y, x);
                    Term_fresh();
                }
                else
                    Term_xtra(TERM_XTRA_DELAY, msec);

                py_attack(y, x, 0);
            }
        }
        var_set_bool(res, TRUE);
        break;
    }
    default:
        default_spell(cmd, res);
        break;
    }
}
예제 #15
0
/*!
 * @brief モンスターが敵対モンスターに直接ブレスを当てることが可能かを判定する /
 * Determine if a breath will hit the target.
 * @param y1 始点のY座標
 * @param x1 始点のX座標
 * @param y2 目標のY座標
 * @param x2 目標のX座標
 * @param rad 半径
 * @param typ 効果属性ID
 * @param is_friend TRUEならば、プレイヤーを巻き込む時にブレスの判定をFALSEにする。
 * @return ブレスを直接当てられるならばTRUEを返す
 */
static bool breath_direct(int y1, int x1, int y2, int x2, int rad, int typ, bool is_friend)
{
	/* Must be the same as projectable() */

	int i;

	/* Initial grid */
	int y = y1;
	int x = x1;

	int grid_n = 0;
	u16b grid_g[512];

	int grids = 0;
	byte gx[1024], gy[1024];
	byte gm[32];
	int gm_rad = rad;

	bool hit2 = FALSE;
	bool hityou = FALSE;

	int flg;

	switch (typ)
	{
	case GF_LITE:
	case GF_LITE_WEAK:
		flg = PROJECT_LOS;
		break;
	case GF_DISINTEGRATE:
		flg = PROJECT_DISI;
		break;
	default:
		flg = 0;
		break;
	}

	/* Check the projection path */
	grid_n = project_path(grid_g, MAX_RANGE, y1, x1, y2, x2, flg);

	/* Project along the path */
	for (i = 0; i < grid_n; ++i)
	{
		int ny = GRID_Y(grid_g[i]);
		int nx = GRID_X(grid_g[i]);

		if (flg & PROJECT_DISI)
		{
			/* Hack -- Balls explode before reaching walls */
			if (cave_stop_disintegration(ny, nx)) break;
		}
		else if (flg & PROJECT_LOS)
		{
			/* Hack -- Balls explode before reaching walls */
			if (!cave_los_bold(ny, nx)) break;
		}
		else
		{
			/* Hack -- Balls explode before reaching walls */
			if (!cave_have_flag_bold(ny, nx, FF_PROJECT)) break;
		}

		/* Save the "blast epicenter" */
		y = ny;
		x = nx;
	}

	grid_n = i;

	if (!grid_n)
	{
		if (flg & PROJECT_DISI)
		{
			if (in_disintegration_range(y1, x1, y2, x2) && (distance(y1, x1, y2, x2) <= rad)) hit2 = TRUE;
			if (in_disintegration_range(y1, x1, p_ptr->y, p_ptr->x) && (distance(y1, x1, p_ptr->y, p_ptr->x) <= rad)) hityou = TRUE;
		}
		else if (flg & PROJECT_LOS)
		{
			if (los(y1, x1, y2, x2) && (distance(y1, x1, y2, x2) <= rad)) hit2 = TRUE;
			if (los(y1, x1, p_ptr->y, p_ptr->x) && (distance(y1, x1, p_ptr->y, p_ptr->x) <= rad)) hityou = TRUE;
		}
		else
		{
			if (projectable(y1, x1, y2, x2) && (distance(y1, x1, y2, x2) <= rad)) hit2 = TRUE;
			if (projectable(y1, x1, p_ptr->y, p_ptr->x) && (distance(y1, x1, p_ptr->y, p_ptr->x) <= rad)) hityou = TRUE;
		}
	}
	else
	{
		breath_shape(grid_g, grid_n, &grids, gx, gy, gm, &gm_rad, rad, y1, x1, y, x, typ);

		for (i = 0; i < grids; i++)
		{
			/* Extract the location */
			y = gy[i];
			x = gx[i];

			if ((y == y2) && (x == x2)) hit2 = TRUE;
			if (player_bold(y, x)) hityou = TRUE;
		}
	}

	if (!hit2) return FALSE;
	if (is_friend && hityou) return FALSE;

	return TRUE;
}