/* * Choose the best direction for "flowing". * * Note that ghosts and rock-eaters generally don't flow because they can move * through obstacles. * * Monsters first try to use up-to-date distance information ('sound') as * saved in cave->squares[y][x].cost. Failing that, they'll try using scent * ('when') which is just old cost information. * * Tracking by 'scent' means that monsters end up near enough the player to * switch to 'sound' (cost), or they end up somewhere the player left via * teleport. Teleporting away from a location will cause the monsters who * were chasing the player to converge on that location as long as the player * is still near enough to "annoy" them without being close enough to chase * directly. */ static bool get_moves_flow(struct chunk *c, struct monster *m_ptr) { int i; int best_when = 0; int best_cost = 999; int best_direction = 0; int py = player->py, px = player->px; int my = m_ptr->fy, mx = m_ptr->fx; /* Only use this algorithm for passwall monsters if near permanent walls, * to avoid getting snagged */ if (flags_test(m_ptr->race->flags, RF_SIZE, RF_PASS_WALL, RF_KILL_WALL, FLAG_END) && !near_permwall(m_ptr, c)) return (FALSE); /* If the player has never been near this grid, abort */ if (c->squares[my][mx].when == 0) return FALSE; /* Monster is too far away to notice the player */ if (c->squares[my][mx].cost > z_info->max_flow_depth) return FALSE; if (c->squares[my][mx].cost > m_ptr->race->aaf) return FALSE; /* If the player can see monster, run towards them */ if (player_has_los_bold(my, mx)) return FALSE; /* Check nearby grids, diagonals first */ /* This gives preference to the cardinal directions */ for (i = 7; i >= 0; i--) { /* Get the location */ int y = my + ddy_ddd[i]; int x = mx + ddx_ddd[i]; /* Ignore unvisited/unpassable locations */ if (c->squares[y][x].when == 0) continue; /* Ignore locations whose data is more stale */ if (c->squares[y][x].when < best_when) continue; /* Ignore locations which are farther away */ if (c->squares[y][x].cost > best_cost) continue; /* Save the cost and time */ best_when = c->squares[y][x].when; best_cost = c->squares[y][x].cost; best_direction = i; } /* Save the location to flow toward */ /* We multiply by 16 to angle slightly toward the player's actual location */ if (best_direction) { m_ptr->ty = py + 16 * ddy_ddd[best_direction]; m_ptr->tx = px + 16 * ddx_ddd[best_direction]; return TRUE; } return FALSE; }
void _grasp_spell(int cmd, variant *res) { switch (cmd) { case SPELL_NAME: var_set_string(res, "Vampiric Grasp"); break; case SPELL_DESC: var_set_string(res, "Pulls a target creature to you."); break; case SPELL_CAST: { int m_idx; bool fear = FALSE; monster_type *m_ptr; monster_race *r_ptr; char m_name[MAX_NLEN]; var_set_bool(res, FALSE); if (!target_set(TARGET_KILL)) break; if (!cave[target_row][target_col].m_idx) break; if (!player_has_los_bold(target_row, target_col)) break; if (!projectable(py, px, target_row, target_col)) break; var_set_bool(res, TRUE); m_idx = cave[target_row][target_col].m_idx; m_ptr = &m_list[m_idx]; r_ptr = &r_info[m_ptr->r_idx]; monster_desc(m_name, m_ptr, 0); if (r_ptr->flagsr & RFR_RES_TELE) { if ((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flagsr & RFR_RES_ALL)) { if (is_original_ap_and_seen(m_ptr)) r_ptr->r_flagsr |= RFR_RES_TELE; msg_format("%s is unaffected!", m_name); break; } else if (r_ptr->level > randint1(100)) { if (is_original_ap_and_seen(m_ptr)) r_ptr->r_flagsr |= RFR_RES_TELE; msg_format("%s resists!", m_name); break; } } msg_format("You grasp %s.", m_name); teleport_monster_to(m_idx, py, px, 100, TELEPORT_PASSIVE); mon_take_hit(m_idx, damroll(10, 10), &fear, extract_note_dies(real_r_ptr(m_ptr))); break; } default: default_spell(cmd, res); break; } }
/* * do_cmd_cast calls this function if the player's class * is 'imitator'. */ static bool use_mane(int spell) { int dir; int plev = p_ptr->lev; u32b mode = (PM_ALLOW_GROUP | PM_FORCE_PET); u32b u_mode = 0L; if (randint1(50+plev) < plev/10) u_mode = PM_ALLOW_UNIQUE; /* spell code */ switch (spell) { case MS_SHRIEK: #ifdef JP msg_print("かん高い金切り声をあげた。"); #else msg_print("You make a high pitched shriek."); #endif aggravate_monsters(0); break; case MS_XXX1: break; case MS_DISPEL: { int m_idx; if (!target_set(TARGET_KILL)) return FALSE; m_idx = cave[target_row][target_col].m_idx; if (!m_idx) break; if (!player_has_los_bold(target_row, target_col)) break; if (!projectable(py, px, target_row, target_col)) break; dispel_monster_status(m_idx); break; } case MS_ROCKET: if (!get_aim_dir(&dir)) return FALSE; #ifdef JP else msg_print("ロケットを発射した。"); #else else msg_print("You fire a rocket."); #endif fire_rocket(GF_ROCKET, dir, damage, 2); break; case MS_SHOOT: if (!get_aim_dir(&dir)) return FALSE; #ifdef JP else msg_print("矢を放った。"); #else else msg_print("You fire an arrow.");
/** * Determine whether a monster is active or passive */ static bool monster_check_active(struct chunk *c, struct monster *mon) { /* Character is inside scanning range */ if (mon->cdis <= mon->race->aaf) mflag_on(mon->mflag, MFLAG_ACTIVE); /* Monster is hurt */ else if (mon->hp < mon->maxhp) mflag_on(mon->mflag, MFLAG_ACTIVE); /* Monster can "see" the player (checked backwards) */ else if (player_has_los_bold(mon->fy, mon->fx)) mflag_on(mon->mflag, MFLAG_ACTIVE); /* Monster can "smell" the player from far away (flow) */ else if (monster_can_flow(c, mon)) mflag_on(mon->mflag, MFLAG_ACTIVE); /* Otherwise go passive */ else mflag_off(mon->mflag, MFLAG_ACTIVE); return mflag_has(mon->mflag, MFLAG_ACTIVE) ? TRUE : FALSE; }
/* * Prepare the "temp" array for "target_interactive_set" * * Return the number of target_able monsters in the set. */ static void target_set_interactive_prepare(int mode) { int y, x; bool expand_look = (mode & (TARGET_LOOK)) ? TRUE : FALSE; /* Reset "temp" array */ clear_temp_array(); /* Scan the current panel */ for (y = Term->offset_y; y < Term->offset_y + SCREEN_HGT; y++) { for (x = Term->offset_x; x < Term->offset_x + SCREEN_WID; x++) { bool do_continue = FALSE; /* Check overflow */ if (temp_n >= TEMP_MAX) continue; /* Check bounds */ if (!in_bounds_fully(y, x)) continue; /* Require line of sight, unless "look" is "expanded" */ if (!player_has_los_bold(y, x) && (!expand_look)) continue; /* Require "interesting" contents */ if (!target_set_interactive_accept(y, x)) continue; /* Special mode */ if (mode & (TARGET_KILL)) { /* Must contain a monster */ if (!(cave_m_idx[y][x] > 0)) do_continue = TRUE; /* Must be a targettable monster */ if (!target_able(cave_m_idx[y][x])) do_continue = TRUE; } /* Don't continue on the trap exception, or if probing. */ if ((mode & (TARGET_TRAP)) && target_able_trap(y, x)) do_continue = FALSE; else if (mode & (TARGET_PROBE)) do_continue = FALSE; if (do_continue) continue; /* * Hack - don't go over redundant elemental terrain \ * (since we have large lakes and pools of the same terrain) */ if ((p_ptr->target_row > 0) || (p_ptr->target_col > 0)) { if (cave_feat[p_ptr->target_row][p_ptr->target_col] == cave_feat[y][x]) { if (cave_ff3_match(y, x, TERRAIN_MASK)) continue; } } /* Save the location */ temp_x[temp_n] = x; temp_y[temp_n] = y; temp_n++; } } /* Set the sort hooks */ ang_sort_comp = ang_sort_comp_distance; ang_sort_swap = ang_sort_swap_distance; /* Sort the positions */ ang_sort(temp_x, temp_y, temp_n); }
/* 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; }
/* * Choose a good hiding place near a monster for it to run toward. * * Pack monsters will use this to "ambush" the player and lure him out * of corridors into open space so they can swarm him. * * Return TRUE if a good location is available. */ static bool find_hiding(struct monster *m_ptr) { int fy = m_ptr->fy; int fx = m_ptr->fx; int py = player->py; int px = player->px; int i, y, x, dy, dx, d, dis; int gy = 0, gx = 0, gdis = 999, min; const int *y_offsets, *x_offsets; /* Closest distance to get */ min = distance(py, px, fy, fx) * 3 / 4 + 2; /* Start with adjacent locations, spread further */ for (d = 1; d < 10; d++) { /* Get the lists of points with a distance d from (fx, fy) */ y_offsets = dist_offsets_y[d]; x_offsets = dist_offsets_x[d]; /* Check the locations */ for (i = 0, dx = x_offsets[0], dy = y_offsets[0]; dx != 0 || dy != 0; i++, dx = x_offsets[i], dy = y_offsets[i]) { y = fy + dy; x = fx + dx; /* Skip illegal locations */ if (!square_in_bounds_fully(cave, y, x)) continue; /* Skip occupied locations */ if (!square_isempty(cave, y, x)) continue; /* Check for hidden, available grid */ if (!player_has_los_bold(y, x) && projectable(cave, fy, fx, y, x, PROJECT_STOP)) { /* Calculate distance from player */ dis = distance(y, x, py, px); /* Remember if closer than previous */ if (dis < gdis && dis >= min) { gy = y; gx = x; gdis = dis; } } } /* Check for success */ if (gdis < 999) { /* Good location */ m_ptr->ty = gy; m_ptr->tx = gx; /* Found good place */ return (TRUE); } } /* No good place */ return (FALSE); }
/* * Choose a "safe" location near a monster for it to run toward. * * A location is "safe" if it can be reached quickly and the player * is not able to fire into it (it isn't a "clean shot"). So, this will * cause monsters to "duck" behind walls. Hopefully, monsters will also * try to run towards corridor openings if they are in a room. * * This function may take lots of CPU time if lots of monsters are fleeing. * * Return TRUE if a safe location is available. */ static bool find_safety(struct chunk *c, struct monster *m_ptr) { int fy = m_ptr->fy; int fx = m_ptr->fx; int py = player->py; int px = player->px; int i, y, x, dy, dx, d, dis; int gy = 0, gx = 0, gdis = 0; const int *y_offsets; const int *x_offsets; /* Start with adjacent locations, spread further */ for (d = 1; d < 10; d++) { /* Get the lists of points with a distance d from (fx, fy) */ y_offsets = dist_offsets_y[d]; x_offsets = dist_offsets_x[d]; /* Check the locations */ for (i = 0, dx = x_offsets[0], dy = y_offsets[0]; dx != 0 || dy != 0; i++, dx = x_offsets[i], dy = y_offsets[i]) { y = fy + dy; x = fx + dx; /* Skip illegal locations */ if (!square_in_bounds_fully(cave, y, x)) continue; /* Skip locations in a wall */ if (!square_ispassable(cave, y, x)) continue; /* Ignore grids very far from the player */ if (c->squares[y][x].when < c->squares[py][px].when) continue; /* Ignore too-distant grids */ if (c->squares[y][x].cost > c->squares[fy][fx].cost + 2 * d) continue; /* Check for absence of shot (more or less) */ if (!player_has_los_bold(y,x)) { /* Calculate distance from player */ dis = distance(y, x, py, px); /* Remember if further than previous */ if (dis > gdis) { gy = y; gx = x; gdis = dis; } } } /* Check for success */ if (gdis > 0) { /* Good location */ m_ptr->ty = gy; m_ptr->tx = gx; /* Found safe place */ return (TRUE); } } /* No safe place */ return (FALSE); }
/** * Grab all objects from the grid. */ void process_monster_grab_objects(struct chunk *c, struct monster *m_ptr, const char *m_name, int nx, int ny) { monster_lore *l_ptr = get_lore(m_ptr->race); struct object *obj = square_object(c, ny, nx); bool is_item = obj ? TRUE : FALSE;; if (is_item && mflag_has(m_ptr->mflag, MFLAG_VISIBLE)) { rf_on(l_ptr->flags, RF_TAKE_ITEM); rf_on(l_ptr->flags, RF_KILL_ITEM); } /* Abort if can't pickup/kill */ if (!rf_has(m_ptr->race->flags, RF_TAKE_ITEM) && !rf_has(m_ptr->race->flags, RF_KILL_ITEM)) { return; } /* Take or kill objects on the floor */ while (obj) { char o_name[80]; bool safe = obj->artifact ? TRUE : FALSE; struct object *next = obj->next; /* Skip gold */ if (tval_is_money(obj)) { obj = next; continue; } /* Get the object name */ object_desc(o_name, sizeof(o_name), obj, ODESC_PREFIX | ODESC_FULL); /* React to objects that hurt the monster */ if (react_to_slay(obj, m_ptr)) safe = TRUE; /* The object cannot be picked up by the monster */ if (safe) { /* Only give a message for "take_item" */ if (rf_has(m_ptr->race->flags, RF_TAKE_ITEM) && mflag_has(m_ptr->mflag, MFLAG_VISIBLE) && player_has_los_bold(ny, nx) && !ignore_item_ok(obj)) { /* Dump a message */ msg("%s tries to pick up %s, but fails.", m_name, o_name); } /* Pick up the item */ } else if (rf_has(m_ptr->race->flags, RF_TAKE_ITEM)) { /* Describe observable situations */ if (player_has_los_bold(ny, nx) && !ignore_item_ok(obj)) msg("%s picks up %s.", m_name, o_name); /* Carry the object */ square_excise_object(c, ny, nx, obj); monster_carry(c, m_ptr, obj); /* Destroy the item */ } else { /* Describe observable situations */ if (player_has_los_bold(ny, nx) && !ignore_item_ok(obj)) msgt(MSG_DESTROY, "%s crushes %s.", m_name, o_name); /* Delete the object */ square_excise_object(c, ny, nx, obj); object_delete(obj); } /* Next object */ obj = next; } }
/** * Work out if a monster can move through the grid, if necessary bashing * down doors in the way. * * Returns TRUE if the monster is able to move through the grid. */ static bool process_monster_can_move(struct chunk *c, struct monster *m_ptr, const char *m_name, int nx, int ny, bool *did_something) { monster_lore *l_ptr = get_lore(m_ptr->race); /* Floor is open? */ if (square_ispassable(c, ny, nx)) return TRUE; /* Permanent wall in the way */ if (square_iswall(c, ny, nx) && square_isperm(c, ny, nx)) return FALSE; /* Normal wall, door, or secret door in the way */ /* There's some kind of feature in the way, so learn about * kill-wall and pass-wall now */ if (mflag_has(m_ptr->mflag, MFLAG_VISIBLE)) { rf_on(l_ptr->flags, RF_PASS_WALL); rf_on(l_ptr->flags, RF_KILL_WALL); } /* Monster moves through walls (and doors) */ if (rf_has(m_ptr->race->flags, RF_PASS_WALL)) return TRUE; /* Monster destroys walls (and doors) */ else if (rf_has(m_ptr->race->flags, RF_KILL_WALL)) { /* Forget the wall */ sqinfo_off(c->squares[ny][nx].info, SQUARE_MARK); /* Notice */ square_destroy_wall(c, ny, nx); /* Note changes to viewable region */ if (player_has_los_bold(ny, nx)) player->upkeep->update |= PU_UPDATE_VIEW; /* Update the flow, since walls affect flow */ player->upkeep->update |= PU_UPDATE_FLOW; return TRUE; } /* Handle doors and secret doors */ else if (square_iscloseddoor(c, ny, nx) || square_issecretdoor(c, ny, nx)) { bool may_bash = rf_has(m_ptr->race->flags, RF_BASH_DOOR) && one_in_(2); /* Take a turn */ *did_something = TRUE; /* Learn about door abilities */ if (mflag_has(m_ptr->mflag, MFLAG_VISIBLE)) { rf_on(l_ptr->flags, RF_OPEN_DOOR); rf_on(l_ptr->flags, RF_BASH_DOOR); } /* Creature can open or bash doors */ if (!rf_has(m_ptr->race->flags, RF_OPEN_DOOR) && !rf_has(m_ptr->race->flags, RF_BASH_DOOR)) return FALSE; /* Stuck door -- try to unlock it */ if (square_islockeddoor(c, ny, nx)) { int k = square_door_power(c, ny, nx); if (randint0(m_ptr->hp / 10) > k) { if (may_bash) msg("%s slams against the door.", m_name); else msg("%s fiddles with the lock.", m_name); /* Reduce the power of the door by one */ square_set_door_lock(c, ny, nx, k - 1); } } else { /* Handle viewable doors */ if (player_has_los_bold(ny, nx)) player->upkeep->update |= PU_UPDATE_VIEW; /* Closed or secret door -- open or bash if allowed */ if (may_bash) { square_smash_door(c, ny, nx); msg("You hear a door burst open!"); disturb(player, 0); /* Fall into doorway */ return TRUE; } else if (rf_has(m_ptr->race->flags, RF_OPEN_DOOR)) { square_open_door(c, ny, nx); } } } return FALSE; }
/*! * @brief フロア移動時のペット保存処理 / Preserve_pets * @return なし */ static void preserve_pet(void) { int num; MONSTER_IDX i; for (num = 0; num < MAX_PARTY_MON; num++) { party_mon[num].r_idx = 0; } if (p_ptr->riding) { monster_type *m_ptr = &m_list[p_ptr->riding]; /* Pet of other pet don't follow. */ if (m_ptr->parent_m_idx) { p_ptr->riding = 0; p_ptr->pet_extra_flags &= ~(PF_RYOUTE); p_ptr->riding_ryoute = p_ptr->old_riding_ryoute = FALSE; } else { /* Preserve the mount */ (void)COPY(&party_mon[0], m_ptr, monster_type); /* Delete from this floor */ delete_monster_idx(p_ptr->riding); } } /* * If player is in wild mode, no pets are preserved * except a monster whom player riding */ if (!p_ptr->wild_mode && !p_ptr->inside_arena && !p_ptr->inside_battle) { for (i = m_max - 1, num = 1; (i >= 1 && num < MAX_PARTY_MON); i--) { monster_type *m_ptr = &m_list[i]; if (!m_ptr->r_idx) continue; if (!is_pet(m_ptr)) continue; if (i == p_ptr->riding) continue; if (reinit_wilderness) { /* Don't lose sight of pets when getting a Quest */ } else { int dis = distance(p_ptr->y, p_ptr->x, m_ptr->fy, m_ptr->fx); /* Confused (etc.) monsters don't follow. */ if (MON_CONFUSED(m_ptr) || MON_STUNNED(m_ptr) || MON_CSLEEP(m_ptr)) continue; /* Pet of other pet don't follow. */ if (m_ptr->parent_m_idx) continue; /* * Pets with nickname will follow even from 3 blocks away * when you or the pet can see the other. */ if (m_ptr->nickname && ((player_has_los_bold(m_ptr->fy, m_ptr->fx) && projectable(p_ptr->y, p_ptr->x, m_ptr->fy, m_ptr->fx)) || (los(m_ptr->fy, m_ptr->fx, p_ptr->y, p_ptr->x) && projectable(m_ptr->fy, m_ptr->fx, p_ptr->y, p_ptr->x)))) { if (dis > 3) continue; } else { if (dis > 1) continue; } } (void)COPY(&party_mon[num], &m_list[i], monster_type); num++; /* Delete from this floor */ delete_monster_idx(i); } } if (record_named_pet) { for (i = m_max - 1; i >=1; i--) { monster_type *m_ptr = &m_list[i]; char m_name[80]; if (!m_ptr->r_idx) continue; if (!is_pet(m_ptr)) continue; if (!m_ptr->nickname) continue; if (p_ptr->riding == i) continue; monster_desc(m_name, m_ptr, MD_ASSUME_VISIBLE | MD_INDEF_VISIBLE); do_cmd_write_nikki(NIKKI_NAMED_PET, RECORD_NAMED_PET_MOVED, m_name); } } /* Pet of other pet may disappear. */ for (i = m_max - 1; i >=1; i--) { monster_type *m_ptr = &m_list[i]; /* Are there its parent? */ if (m_ptr->parent_m_idx && !m_list[m_ptr->parent_m_idx].r_idx) { /* Its parent have gone, it also goes away. */ if (is_seen(m_ptr)) { char m_name[80]; /* Acquire the monster name */ monster_desc(m_name, m_ptr, 0); #ifdef JP msg_format("%sは消え去った!", m_name); #else msg_format("%^s disappears!", m_name); #endif } /* Delete the monster */ delete_monster_idx(i); } } }
/* * Prepare the "temp" array for "target_interactive_set" * * Return the number of target_able monsters in the set. */ static void target_set_interactive_prepare(int mode) { int y, x; bool expand_look = (mode & (TARGET_LOOK)) ? TRUE : FALSE; /* Reset "temp" array */ target_grids.clear(); // Not needed. if (mode & (TARGET_GRID)) return; QRect vis = visible_dungeon(); /* Scan the current panel */ for (y = vis.y(); y <= vis.y() + vis.height(); y++) { for (x = vis.x(); x <= vis.x() + vis.width(); x++) { bool do_continue = FALSE; /* Check bounds */ if (!in_bounds_fully(y, x)) continue; /* Require line of sight, unless "look" is "expanded" */ if (!player_has_los_bold(y, x) && (!expand_look)) continue; /* Require "interesting" contents */ if (!target_set_interactive_accept(mode, y, x)) continue; /* Special mode */ if (mode & (TARGET_KILL)) { /* Must contain a monster */ if (!dungeon_info[y][x].has_monster()) do_continue = TRUE; /* Must be a targetable monster */ if (!target_able(dungeon_info[y][x].monster_idx, FALSE)) do_continue = TRUE; } /* Don't continue on the trap exception, or if probing. */ if ((mode & (TARGET_TRAP)) && target_able_trap(y, x)) do_continue = FALSE; else if (mode & (TARGET_PROBE)) do_continue = FALSE; if (do_continue) continue; /* * Hack - don't go over redundant elemental terrain \ * (since we have large lakes and pools of the same terrain) */ if ((p_ptr->target_row > 0) || (p_ptr->target_col > 0)) { if (dungeon_info[p_ptr->target_row][p_ptr->target_col].feature_idx == dungeon_info[y][x].feature_idx) { if (cave_ff3_match(y, x, TERRAIN_MASK)) continue; } } /* Save the location */ target_grids.append(make_coords(y, x)); } } // Sort by distance qSort(target_grids.begin(), target_grids.end(), coords_sort_distance); }
/*! * @brief 青魔法の発動 / * do_cmd_cast calls this function if the player's class is 'blue-mage'. * @param spell 発動するモンスター攻撃のID * @param success TRUEは成功時、FALSEは失敗時の処理を行う * @return 処理を実行したらTRUE、キャンセルした場合FALSEを返す。 */ static bool cast_learned_spell(int spell, bool success) { int dir; int plev = pseudo_plev(); int summon_lev = p_ptr->lev * 2 / 3 + randint1(p_ptr->lev/2); int damage = 0; bool pet = success; bool no_trump = FALSE; u32b p_mode, u_mode = 0L, g_mode; if (pet) { p_mode = PM_FORCE_PET; g_mode = 0; } else { p_mode = PM_NO_PET; g_mode = PM_ALLOW_GROUP; } if (!success || (randint1(50+plev) < plev/10)) u_mode = PM_ALLOW_UNIQUE; /* spell code */ switch (spell) { case MS_SHRIEK: msg_print(_("かん高い金切り声をあげた。", "You make a high pitched shriek.")); aggravate_monsters(0); break; case MS_XXX1: break; case MS_DISPEL: { int m_idx; if (!target_set(TARGET_KILL)) return FALSE; m_idx = cave[target_row][target_col].m_idx; if (!m_idx) break; if (!player_has_los_bold(target_row, target_col)) break; if (!projectable(p_ptr->y, p_ptr->x, target_row, target_col)) break; dispel_monster_status(m_idx); break; } case MS_ROCKET: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("ロケットを発射した。", "You fire a rocket.")); damage = monspell_bluemage_damage((MS_ROCKET), plev, DAM_ROLL); fire_rocket(GF_ROCKET, dir, damage, 2); break; case MS_SHOOT: { if (!get_aim_dir(&dir)) return FALSE; msg_print(_("矢を放った。", "You fire an arrow.")); damage = monspell_bluemage_damage((MS_SHOOT), plev, DAM_ROLL); fire_bolt(GF_ARROW, dir, damage); break; } case MS_XXX2: break; case MS_XXX3: break; case MS_XXX4: break; case MS_BR_ACID: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("酸のブレスを吐いた。", "You breathe acid.")); damage = monspell_bluemage_damage((MS_BR_ACID), plev, DAM_ROLL); fire_ball(GF_ACID, dir, damage, (plev > 40 ? -3 : -2)); break; case MS_BR_ELEC: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("稲妻のブレスを吐いた。", "You breathe lightning.")); damage = monspell_bluemage_damage((MS_BR_ELEC), plev, DAM_ROLL); fire_ball(GF_ELEC, dir, damage, (plev > 40 ? -3 : -2)); break; case MS_BR_FIRE: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("火炎のブレスを吐いた。", "You breathe fire.")); damage = monspell_bluemage_damage((MS_BR_FIRE), plev, DAM_ROLL); fire_ball(GF_FIRE, dir, damage, (plev > 40 ? -3 : -2)); break; case MS_BR_COLD: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("冷気のブレスを吐いた。", "You breathe frost.")); damage = monspell_bluemage_damage((MS_BR_COLD), plev, DAM_ROLL); fire_ball(GF_COLD, dir, damage, (plev > 40 ? -3 : -2)); break; case MS_BR_POIS: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("ガスのブレスを吐いた。", "You breathe gas.")); damage = monspell_bluemage_damage((MS_BR_POIS), plev, DAM_ROLL); fire_ball(GF_POIS, dir, damage, (plev > 40 ? -3 : -2)); break; case MS_BR_NETHER: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("地獄のブレスを吐いた。", "You breathe nether.")); damage = monspell_bluemage_damage((MS_BR_NETHER), plev, DAM_ROLL); fire_ball(GF_NETHER, dir, damage, (plev > 40 ? -3 : -2)); break; case MS_BR_LITE: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("閃光のブレスを吐いた。", "You breathe light.")); damage = monspell_bluemage_damage((MS_BR_LITE), plev, DAM_ROLL); fire_ball(GF_LITE, dir, damage, (plev > 40 ? -3 : -2)); break; case MS_BR_DARK: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("暗黒のブレスを吐いた。", "You breathe darkness.")); damage = monspell_bluemage_damage((MS_BR_DARK), plev, DAM_ROLL); fire_ball(GF_DARK, dir, damage, (plev > 40 ? -3 : -2)); break; case MS_BR_CONF: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("混乱のブレスを吐いた。", "You breathe confusion.")); damage = monspell_bluemage_damage((MS_BR_CONF), plev, DAM_ROLL); fire_ball(GF_CONFUSION, dir, damage, (plev > 40 ? -3 : -2)); break; case MS_BR_SOUND: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("轟音のブレスを吐いた。", "You breathe sound.")); damage = monspell_bluemage_damage((MS_BR_SOUND), plev, DAM_ROLL); fire_ball(GF_SOUND, dir, damage, (plev > 40 ? -3 : -2)); break; case MS_BR_CHAOS: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("カオスのブレスを吐いた。", "You breathe chaos.")); damage = monspell_bluemage_damage((MS_BR_CHAOS), plev, DAM_ROLL); fire_ball(GF_CHAOS, dir, damage, (plev > 40 ? -3 : -2)); break; case MS_BR_DISEN: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("劣化のブレスを吐いた。", "You breathe disenchantment.")); damage = monspell_bluemage_damage((MS_BR_DISEN), plev, DAM_ROLL); fire_ball(GF_DISENCHANT, dir, damage, (plev > 40 ? -3 : -2)); break; case MS_BR_NEXUS: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("因果混乱のブレスを吐いた。", "You breathe nexus.")); damage = monspell_bluemage_damage((MS_BR_NEXUS), plev, DAM_ROLL); fire_ball(GF_NEXUS, dir, damage, (plev > 40 ? -3 : -2)); break; case MS_BR_TIME: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("時間逆転のブレスを吐いた。", "You breathe time.")); damage = monspell_bluemage_damage((MS_BR_TIME), plev, DAM_ROLL); fire_ball(GF_TIME, dir, damage, (plev > 40 ? -3 : -2)); break; case MS_BR_INERTIA: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("遅鈍のブレスを吐いた。", "You breathe inertia.")); damage = monspell_bluemage_damage((MS_BR_INERTIA), plev, DAM_ROLL); fire_ball(GF_INERTIAL, dir, damage, (plev > 40 ? -3 : -2)); break; case MS_BR_GRAVITY: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("重力のブレスを吐いた。", "You breathe gravity.")); damage = monspell_bluemage_damage((MS_BR_GRAVITY), plev, DAM_ROLL); fire_ball(GF_GRAVITY, dir, damage, (plev > 40 ? -3 : -2)); break; case MS_BR_SHARDS: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("破片のブレスを吐いた。", "You breathe shards.")); damage = monspell_bluemage_damage((MS_BR_SHARDS), plev, DAM_ROLL); fire_ball(GF_SHARDS, dir, damage, (plev > 40 ? -3 : -2)); break; case MS_BR_PLASMA: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("プラズマのブレスを吐いた。", "You breathe plasma.")); damage = monspell_bluemage_damage((MS_BR_PLASMA), plev, DAM_ROLL); fire_ball(GF_PLASMA, dir, damage, (plev > 40 ? -3 : -2)); break; case MS_BR_FORCE: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("フォースのブレスを吐いた。", "You breathe force.")); damage = monspell_bluemage_damage((MS_BR_FORCE), plev, DAM_ROLL); fire_ball(GF_FORCE, dir, damage, (plev > 40 ? -3 : -2)); break; case MS_BR_MANA: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("魔力のブレスを吐いた。", "You breathe mana.")); damage = monspell_bluemage_damage((MS_BR_MANA), plev, DAM_ROLL); fire_ball(GF_MANA, dir, damage, (plev > 40 ? -3 : -2)); break; case MS_BALL_NUKE: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("放射能球を放った。", "You cast a ball of radiation.")); damage = monspell_bluemage_damage((MS_BALL_NUKE), plev, DAM_ROLL); fire_ball(GF_NUKE, dir, damage, 2); break; case MS_BR_NUKE: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("放射性廃棄物のブレスを吐いた。", "You breathe toxic waste.")); damage = monspell_bluemage_damage((MS_BR_NUKE), plev, DAM_ROLL); fire_ball(GF_NUKE, dir, damage, (plev > 40 ? -3 : -2)); break; case MS_BALL_CHAOS: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("純ログルスを放った。", "You invoke a raw Logrus.")); damage = monspell_bluemage_damage((MS_BALL_CHAOS), plev, DAM_ROLL); fire_ball(GF_CHAOS, dir, damage, 4); break; case MS_BR_DISI: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("分解のブレスを吐いた。", "You breathe disintegration.")); damage = monspell_bluemage_damage((MS_BR_DISI), plev, DAM_ROLL); fire_ball(GF_DISINTEGRATE, dir, damage, (plev > 40 ? -3 : -2)); break; case MS_BALL_ACID: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("アシッド・ボールの呪文を唱えた。", "You cast an acid ball.")); damage = monspell_bluemage_damage((MS_BALL_ACID), plev, DAM_ROLL); fire_ball(GF_ACID, dir, damage, 2); break; case MS_BALL_ELEC: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("サンダー・ボールの呪文を唱えた。", "You cast a lightning ball.")); damage = monspell_bluemage_damage((MS_BALL_ELEC), plev, DAM_ROLL); fire_ball(GF_ELEC, dir, damage, 2); break; case MS_BALL_FIRE: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("ファイア・ボールの呪文を唱えた。", "You cast a fire ball.")); damage = monspell_bluemage_damage((MS_BALL_FIRE), plev, DAM_ROLL); fire_ball(GF_FIRE, dir, damage, 2); break; case MS_BALL_COLD: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("アイス・ボールの呪文を唱えた。", "You cast a frost ball.")); damage = monspell_bluemage_damage((MS_BALL_COLD), plev, DAM_ROLL); fire_ball(GF_COLD, dir, damage, 2); break; case MS_BALL_POIS: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("悪臭雲の呪文を唱えた。", "You cast a stinking cloud.")); damage = monspell_bluemage_damage((MS_BALL_POIS), plev, DAM_ROLL); fire_ball(GF_POIS, dir, damage, 2); break; case MS_BALL_NETHER: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("地獄球の呪文を唱えた。", "You cast a nether ball.")); damage = monspell_bluemage_damage((MS_BALL_NETHER), plev, DAM_ROLL); fire_ball(GF_NETHER, dir, damage, 2); break; case MS_BALL_WATER: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("流れるような身振りをした。", "You gesture fluidly.")); damage = monspell_bluemage_damage((MS_BALL_WATER), plev, DAM_ROLL); fire_ball(GF_WATER, dir, damage, 4); break; case MS_BALL_MANA: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("魔力の嵐の呪文を念じた。", "You invoke a mana storm.")); damage = monspell_bluemage_damage((MS_BALL_MANA), plev, DAM_ROLL); fire_ball(GF_MANA, dir, damage, 4); break; case MS_BALL_DARK: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("暗黒の嵐の呪文を念じた。", "You invoke a darkness storm.")); damage = monspell_bluemage_damage((MS_BALL_DARK), plev, DAM_ROLL); fire_ball(GF_DARK, dir, damage, 4); break; case MS_DRAIN_MANA: if (!get_aim_dir(&dir)) return FALSE; damage = monspell_bluemage_damage((MS_DRAIN_MANA), plev, DAM_ROLL); fire_ball_hide(GF_DRAIN_MANA, dir, damage, 0); break; case MS_MIND_BLAST: if (!get_aim_dir(&dir)) return FALSE; damage = monspell_bluemage_damage((MS_MIND_BLAST), plev, DAM_ROLL); fire_ball_hide(GF_MIND_BLAST, dir, damage, 0); break; case MS_BRAIN_SMASH: if (!get_aim_dir(&dir)) return FALSE; damage = monspell_bluemage_damage((MS_BRAIN_SMASH), plev, DAM_ROLL); fire_ball_hide(GF_BRAIN_SMASH, dir, damage, 0); break; case MS_CAUSE_1: if (!get_aim_dir(&dir)) return FALSE; damage = monspell_bluemage_damage((MS_CAUSE_1), plev, DAM_ROLL); fire_ball_hide(GF_CAUSE_1, dir, damage, 0); break; case MS_CAUSE_2: if (!get_aim_dir(&dir)) return FALSE; damage = monspell_bluemage_damage((MS_CAUSE_2), plev, DAM_ROLL); fire_ball_hide(GF_CAUSE_2, dir, damage, 0); break; case MS_CAUSE_3: if (!get_aim_dir(&dir)) return FALSE; damage = monspell_bluemage_damage((MS_CAUSE_3), plev, DAM_ROLL); fire_ball_hide(GF_CAUSE_3, dir, damage, 0); break; case MS_CAUSE_4: if (!get_aim_dir(&dir)) return FALSE; damage = monspell_bluemage_damage((MS_CAUSE_4), plev, DAM_ROLL); fire_ball_hide(GF_CAUSE_4, dir, damage, 0); break; case MS_BOLT_ACID: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("アシッド・ボルトの呪文を唱えた。", "You cast an acid bolt.")); damage = monspell_bluemage_damage((MS_BOLT_ACID), plev, DAM_ROLL); fire_bolt(GF_ACID, dir, damage); break; case MS_BOLT_ELEC: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("サンダー・ボルトの呪文を唱えた。", "You cast a lightning bolt.")); damage = monspell_bluemage_damage((MS_BOLT_ELEC), plev, DAM_ROLL); fire_bolt(GF_ELEC, dir, damage); break; case MS_BOLT_FIRE: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("ファイア・ボルトの呪文を唱えた。", "You cast a fire bolt.")); damage = monspell_bluemage_damage((MS_BOLT_FIRE), plev, DAM_ROLL); fire_bolt(GF_FIRE, dir, damage); break; case MS_BOLT_COLD: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("アイス・ボルトの呪文を唱えた。", "You cast a frost bolt.")); damage = monspell_bluemage_damage((MS_BOLT_COLD), plev, DAM_ROLL); fire_bolt(GF_COLD, dir, damage); break; case MS_STARBURST: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("スターバーストの呪文を念じた。", "You invoke a starburst.")); damage = monspell_bluemage_damage((MS_STARBURST), plev, DAM_ROLL); fire_ball(GF_LITE, dir, damage, 4); break; case MS_BOLT_NETHER: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("地獄の矢の呪文を唱えた。", "You cast a nether bolt.")); damage = monspell_bluemage_damage((MS_BOLT_NETHER), plev, DAM_ROLL); fire_bolt(GF_NETHER, dir, damage); break; case MS_BOLT_WATER: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("ウォーター・ボルトの呪文を唱えた。", "You cast a water bolt.")); damage = monspell_bluemage_damage((MS_BOLT_WATER), plev, DAM_ROLL); fire_bolt(GF_WATER, dir, damage); break; case MS_BOLT_MANA: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("魔力の矢の呪文を唱えた。", "You cast a mana bolt.")); damage = monspell_bluemage_damage((MS_BOLT_MANA), plev, DAM_ROLL); fire_bolt(GF_MANA, dir, damage); break; case MS_BOLT_PLASMA: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("プラズマ・ボルトの呪文を唱えた。", "You cast a plasma bolt.")); damage = monspell_bluemage_damage((MS_BOLT_PLASMA), plev, DAM_ROLL); fire_bolt(GF_PLASMA, dir, damage); break; case MS_BOLT_ICE: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("極寒の矢の呪文を唱えた。", "You cast a ice bolt.")); damage = monspell_bluemage_damage((MS_BOLT_ICE), plev, DAM_ROLL); fire_bolt(GF_ICE, dir, damage); break; case MS_MAGIC_MISSILE: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("マジック・ミサイルの呪文を唱えた。", "You cast a magic missile.")); damage = monspell_bluemage_damage((MS_MAGIC_MISSILE), plev, DAM_ROLL); fire_bolt(GF_MISSILE, dir, damage); break; case MS_SCARE: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("恐ろしげな幻覚を作り出した。", "You cast a fearful illusion.")); fear_monster(dir, plev+10); break; case MS_BLIND: if (!get_aim_dir(&dir)) return FALSE; confuse_monster(dir, plev * 2); break; case MS_CONF: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("誘惑的な幻覚をつくり出した。", "You cast a mesmerizing illusion.")); confuse_monster(dir, plev * 2); break; case MS_SLOW: if (!get_aim_dir(&dir)) return FALSE; slow_monster(dir, plev); break; case MS_SLEEP: if (!get_aim_dir(&dir)) return FALSE; sleep_monster(dir, plev); break; case MS_SPEED: (void)set_fast(randint1(20 + plev) + plev, FALSE); break; case MS_HAND_DOOM: { if (!get_aim_dir(&dir)) return FALSE; msg_print(_("<破滅の手>を放った!", "You invoke the Hand of Doom!")); fire_ball_hide(GF_HAND_DOOM, dir, plev * 3, 0); break; } case MS_HEAL: msg_print(_("自分の傷に念を集中した。", "You concentrate on your wounds!")); (void)hp_player(plev*4); (void)set_stun(0); (void)set_cut(0); break; case MS_INVULNER: msg_print(_("無傷の球の呪文を唱えた。", "You cast a Globe of Invulnerability.")); (void)set_invuln(randint1(4) + 4, FALSE); break; case MS_BLINK: teleport_player(10, 0L); break; case MS_TELEPORT: teleport_player(plev * 5, 0L); break; case MS_WORLD: world_player = TRUE; msg_print(_("「時よ!」", "'Time!'")); msg_print(NULL); /* Hack */ p_ptr->energy_need -= 1000 + (100 + randint1(200)+200)*TURNS_PER_TICK/10; /* Redraw map */ p_ptr->redraw |= (PR_MAP); /* Update monsters */ p_ptr->update |= (PU_MONSTERS); /* Window stuff */ p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON); handle_stuff(); break; case MS_SPECIAL: break; case MS_TELE_TO: { monster_type *m_ptr; monster_race *r_ptr; char m_name[80]; if (!target_set(TARGET_KILL)) return FALSE; if (!cave[target_row][target_col].m_idx) break; if (!player_has_los_bold(target_row, target_col)) break; if (!projectable(p_ptr->y, p_ptr->x, target_row, target_col)) break; m_ptr = &m_list[cave[target_row][target_col].m_idx]; r_ptr = &r_info[m_ptr->r_idx]; monster_desc(m_name, m_ptr, 0); if (r_ptr->flagsr & RFR_RES_TELE) { if ((r_ptr->flags1 & (RF1_UNIQUE)) || (r_ptr->flagsr & RFR_RES_ALL)) { if (is_original_ap_and_seen(m_ptr)) r_ptr->r_flagsr |= RFR_RES_TELE; msg_format(_("%sには効果がなかった!", "%s is unaffected!"), m_name); break; } else if (r_ptr->level > randint1(100)) { if (is_original_ap_and_seen(m_ptr)) r_ptr->r_flagsr |= RFR_RES_TELE; msg_format(_("%sには耐性がある!", "%s resists!"), m_name); break; } } msg_format(_("%sを引き戻した。", "You command %s to return."), m_name); teleport_monster_to(cave[target_row][target_col].m_idx, p_ptr->y, p_ptr->x, 100, TELEPORT_PASSIVE); break; } case MS_TELE_AWAY: if (!get_aim_dir(&dir)) return FALSE; (void)fire_beam(GF_AWAY_ALL, dir, 100); break; case MS_TELE_LEVEL: { int target_m_idx; monster_type *m_ptr; monster_race *r_ptr; char m_name[80]; if (!target_set(TARGET_KILL)) return FALSE; target_m_idx = cave[target_row][target_col].m_idx; if (!target_m_idx) break; if (!player_has_los_bold(target_row, target_col)) break; if (!projectable(p_ptr->y, p_ptr->x, target_row, target_col)) break; m_ptr = &m_list[target_m_idx]; r_ptr = &r_info[m_ptr->r_idx]; monster_desc(m_name, m_ptr, 0); msg_format(_("%^sの足を指さした。", "You gesture at %^s's feet."), m_name); if ((r_ptr->flagsr & (RFR_EFF_RES_NEXU_MASK | RFR_RES_TELE)) || (r_ptr->flags1 & RF1_QUESTOR) || (r_ptr->level + randint1(50) > plev + randint1(60))) { msg_format(_("しかし効果がなかった!", "%^s is unaffected!"), m_name); } else teleport_level(target_m_idx); break; } case MS_PSY_SPEAR: if (!get_aim_dir(&dir)) return FALSE; msg_print(_("光の剣を放った。", "You throw a psycho-spear.")); damage = monspell_bluemage_damage((MS_PSY_SPEAR), plev, DAM_ROLL); (void)fire_beam(GF_PSY_SPEAR, dir, damage); break; case MS_DARKNESS: msg_print(_("暗闇の中で手を振った。", "You gesture in shadow.")); (void)unlite_area(10, 3); break; case MS_MAKE_TRAP: if (!target_set(TARGET_KILL)) return FALSE; msg_print(_("呪文を唱えて邪悪に微笑んだ。", "You cast a spell and cackle evilly.")); trap_creation(target_row, target_col); break; case MS_FORGET: msg_print(_("しかし何も起きなかった。", "Nothing happen.")); break; case MS_RAISE_DEAD: msg_print(_("死者復活の呪文を唱えた。", "You cast a animate dead.")); (void)animate_dead(0, p_ptr->y, p_ptr->x); break; case MS_S_KIN: { int k; msg_print(_("援軍を召喚した。", "You summon minions.")); for (k = 0;k < 1; k++) { if (summon_kin_player(summon_lev, p_ptr->y, p_ptr->x, (pet ? PM_FORCE_PET : 0L))) { if (!pet) msg_print(_("召喚された仲間は怒っている!", "Summoned fellows are angry!")); } else { no_trump = TRUE; } } break; } case MS_S_CYBER: { int k; msg_print(_("サイバーデーモンを召喚した!", "You summon a Cyberdemon!")); for (k = 0 ;k < 1 ; k++) if (summon_specific((pet ? -1 : 0), p_ptr->y, p_ptr->x, summon_lev, SUMMON_CYBER, p_mode)) { if (!pet) msg_print(_("召喚されたサイバーデーモンは怒っている!", "The summoned Cyberdemon are angry!")); } else { no_trump = TRUE; } break; } case MS_S_MONSTER: { int k; msg_print(_("仲間を召喚した。", "You summon help.")); for (k = 0;k < 1; k++) if (summon_specific((pet ? -1 : 0), p_ptr->y, p_ptr->x, summon_lev, 0, p_mode)) { if (!pet) msg_print(_("召喚されたモンスターは怒っている!", "The summoned monster is angry!")); } else { no_trump = TRUE; } break; } case MS_S_MONSTERS: { int k; msg_print(_("モンスターを召喚した!", "You summon monsters!")); for (k = 0;k < plev / 15 + 2; k++) if(summon_specific((pet ? -1 : 0), p_ptr->y, p_ptr->x, summon_lev, 0, (p_mode | u_mode))) { if (!pet) msg_print(_("召喚されたモンスターは怒っている!", "The summoned monsters are angry!")); } else { no_trump = TRUE; } break; } case MS_S_ANT: { int k; msg_print(_("アリを召喚した。", "You summon ants.")); for (k = 0;k < 1; k++) if (summon_specific((pet ? -1 : 0), p_ptr->y, p_ptr->x, summon_lev, SUMMON_ANT, (PM_ALLOW_GROUP | p_mode))) { if (!pet) msg_print(_("召喚されたアリは怒っている!", "The summoned ants are angry!")); } else { no_trump = TRUE; } break; } case MS_S_SPIDER: { int k; msg_print(_("蜘蛛を召喚した。", "You summon spiders.")); for (k = 0;k < 1; k++) if (summon_specific((pet ? -1 : 0), p_ptr->y, p_ptr->x, summon_lev, SUMMON_SPIDER, (PM_ALLOW_GROUP | p_mode))) { if (!pet) msg_print(_("召喚された蜘蛛は怒っている!", "Summoned spiders are angry!")); } else { no_trump = TRUE; } break; } case MS_S_HOUND: { int k; msg_print(_("ハウンドを召喚した。", "You summon hounds.")); for (k = 0;k < 1; k++) if (summon_specific((pet ? -1 : 0), p_ptr->y, p_ptr->x, summon_lev, SUMMON_HOUND, (PM_ALLOW_GROUP | p_mode))) { if (!pet) msg_print(_("召喚されたハウンドは怒っている!", "Summoned hounds are angry!")); } else { no_trump = TRUE; } break; } case MS_S_HYDRA: { int k; msg_print(_("ヒドラを召喚した。", "You summon a hydras.")); for (k = 0;k < 1; k++) if (summon_specific((pet ? -1 : 0), p_ptr->y, p_ptr->x, summon_lev, SUMMON_HYDRA, (g_mode | p_mode))) { if (!pet) msg_print(_("召喚されたヒドラは怒っている!", "Summoned hydras are angry!")); } else { no_trump = TRUE; } break; } case MS_S_ANGEL: { int k; msg_print(_("天使を召喚した!", "You summon an angel!")); for (k = 0;k < 1; k++) if (summon_specific((pet ? -1 : 0), p_ptr->y, p_ptr->x, summon_lev, SUMMON_ANGEL, (g_mode | p_mode))) { if (!pet) msg_print(_("召喚された天使は怒っている!", "Summoned angels are angry!")); } else { no_trump = TRUE; } break; } case MS_S_DEMON: { int k; msg_print(_("混沌の宮廷から悪魔を召喚した!", "You summon a demon from the Courts of Chaos!")); for (k = 0;k < 1; k++) if (summon_specific((pet ? -1 : 0), p_ptr->y, p_ptr->x, summon_lev, SUMMON_DEMON, (g_mode | p_mode))) { if (!pet) msg_print(_("召喚されたデーモンは怒っている!", "Summoned demons are angry!")); } else { no_trump = TRUE; } break; } case MS_S_UNDEAD: { int k; msg_print(_("アンデッドの強敵を召喚した!", "You summon an undead adversary!")); for (k = 0;k < 1; k++) if (summon_specific((pet ? -1 : 0), p_ptr->y, p_ptr->x, summon_lev, SUMMON_UNDEAD, (g_mode | p_mode))) { if (!pet) msg_print(_("召喚されたアンデッドは怒っている!", "Summoned undeads are angry!")); } else { no_trump = TRUE; } break; } case MS_S_DRAGON: { int k; msg_print(_("ドラゴンを召喚した!", "You summon a dragon!")); for (k = 0;k < 1; k++) if (summon_specific((pet ? -1 : 0), p_ptr->y, p_ptr->x, summon_lev, SUMMON_DRAGON, (g_mode | p_mode))) { if (!pet) msg_print(_("召喚されたドラゴンは怒っている!", "Summoned dragons are angry!")); } else { no_trump = TRUE; } break; } case MS_S_HI_UNDEAD: { int k; msg_print(_("強力なアンデッドを召喚した!", "You summon a greater undead!")); for (k = 0;k < 1; k++) if (summon_specific((pet ? -1 : 0), p_ptr->y, p_ptr->x, summon_lev, SUMMON_HI_UNDEAD, (g_mode | p_mode | u_mode))) { if (!pet) msg_print(_("召喚された上級アンデッドは怒っている!", "Summoned greater undeads are angry!")); } else { no_trump = TRUE; } break; } case MS_S_HI_DRAGON: { int k; msg_print(_("古代ドラゴンを召喚した!", "You summon an ancient dragon!")); for (k = 0;k < 1; k++) if (summon_specific((pet ? -1 : 0), p_ptr->y, p_ptr->x, summon_lev, SUMMON_HI_DRAGON, (g_mode | p_mode | u_mode))) { if (!pet) msg_print(_("召喚された古代ドラゴンは怒っている!", "Summoned ancient dragons are angry!")); } else { no_trump = TRUE; } break; } case MS_S_AMBERITE: { int k; msg_print(_("アンバーの王族を召喚した!", "You summon a Lord of Amber!")); for (k = 0;k < 1; k++) if (summon_specific((pet ? -1 : 0), p_ptr->y, p_ptr->x, summon_lev, SUMMON_AMBERITES, (g_mode | p_mode | u_mode))) { if (!pet) msg_print(_("召喚されたアンバーの王族は怒っている!", "Summoned Lords of Amber are angry!")); } else { no_trump = TRUE; } break; } case MS_S_UNIQUE: { int k, count = 0; msg_print(_("特別な強敵を召喚した!", "You summon a special opponent!")); for (k = 0;k < 1; k++) if (summon_specific((pet ? -1 : 0), p_ptr->y, p_ptr->x, summon_lev, SUMMON_UNIQUE, (g_mode | p_mode | PM_ALLOW_UNIQUE))) { count++; if (!pet) msg_print(_("召喚されたユニーク・モンスターは怒っている!", "Summoned special opponents are angry!")); } for (k = count;k < 1; k++) if (summon_specific((pet ? -1 : 0), p_ptr->y, p_ptr->x, summon_lev, SUMMON_HI_UNDEAD, (g_mode | p_mode | PM_ALLOW_UNIQUE))) { count++; if (!pet) msg_print(_("召喚された上級アンデッドは怒っている!", "Summoned greater undeads are angry!")); } if (!count) { no_trump = TRUE; } break; } default: msg_print("hoge?"); } if (no_trump) { msg_print(_("何も現れなかった。", "No one have appeared.")); } return TRUE; }
/* * do_cmd_cast calls this function if the player's class * is 'imitator'. */ static bool cast_learned_spell(int spell, bool success) { int dir; int plev = pseudo_plev(); int summon_lev = p_ptr->lev * 2 / 3 + randint1(p_ptr->lev/2); int hp = p_ptr->chp; int damage = 0; bool pet = success; bool no_trump = FALSE; u32b p_mode, u_mode = 0L, g_mode; if (pet) { p_mode = PM_FORCE_PET; g_mode = 0; } else { p_mode = PM_NO_PET; g_mode = PM_ALLOW_GROUP; } if (!success || (randint1(50+plev) < plev/10)) u_mode = PM_ALLOW_UNIQUE; /* spell code */ switch (spell) { case MS_SHRIEK: msg_print("You make a high pitched shriek."); aggravate_monsters(0); break; case MS_XXX1: break; case MS_DISPEL: { int m_idx; if (!target_set(TARGET_KILL)) return FALSE; m_idx = cave[target_row][target_col].m_idx; if (!m_idx) break; if (!player_has_los_bold(target_row, target_col)) break; if (!projectable(py, px, target_row, target_col)) break; dispel_monster_status(m_idx); break; } case MS_ROCKET: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You fire a rocket."); damage = hp / 4; fire_rocket(GF_ROCKET, dir, spell_power(damage), 2); break; case MS_SHOOT: { int slot; if (!get_aim_dir(&dir)) return FALSE; msg_print("You fire an arrow."); damage = 1; slot = equip_find_first(object_is_melee_weapon); if (slot) { object_type *o_ptr = equip_obj(slot); damage = damroll(o_ptr->dd, o_ptr->ds)+ o_ptr->to_d; if (damage < 1) damage = 1; } fire_bolt(GF_ARROW, dir, spell_power(damage)); break; } case MS_XXX2: break; case MS_XXX3: break; case MS_BR_STORM: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe storm."); damage = MIN(hp / 3, 300); fire_ball(GF_STORM, dir, spell_power(damage), (plev > 40 ? -3 : -2)); break; case MS_BR_ACID: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe acid."); damage = hp / 3; fire_ball(GF_ACID, dir, spell_power(damage), (plev > 40 ? -3 : -2)); break; case MS_BR_ELEC: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe lightning."); damage = hp / 3; fire_ball(GF_ELEC, dir, spell_power(damage), (plev > 40 ? -3 : -2)); break; case MS_BR_FIRE: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe fire."); damage = hp / 3; fire_ball(GF_FIRE, dir, spell_power(damage), (plev > 40 ? -3 : -2)); break; case MS_BR_COLD: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe frost."); damage = hp / 3; fire_ball(GF_COLD, dir, spell_power(damage), (plev > 40 ? -3 : -2)); break; case MS_BR_POIS: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe gas."); damage = hp / 3; fire_ball(GF_POIS, dir, spell_power(damage), (plev > 40 ? -3 : -2)); break; case MS_BR_NETHER: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe nether."); damage = hp / 6; fire_ball(GF_NETHER, dir, spell_power(damage), (plev > 40 ? -3 : -2)); break; case MS_BR_LITE: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe light."); damage = hp / 6; fire_ball(GF_LITE, dir, spell_power(damage), (plev > 40 ? -3 : -2)); break; case MS_BR_DARK: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe darkness."); damage = hp / 6; fire_ball(GF_DARK, dir, spell_power(damage), (plev > 40 ? -3 : -2)); break; case MS_BR_CONF: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe confusion."); damage = hp / 6; fire_ball(GF_CONFUSION, dir, spell_power(damage), (plev > 40 ? -3 : -2)); break; case MS_BR_SOUND: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe sound."); damage = hp / 6; fire_ball(GF_SOUND, dir, spell_power(damage), (plev > 40 ? -3 : -2)); break; case MS_BR_CHAOS: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe chaos."); damage = hp / 6; fire_ball(GF_CHAOS, dir, spell_power(damage), (plev > 40 ? -3 : -2)); break; case MS_BR_DISEN: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe disenchantment."); damage = hp / 6; fire_ball(GF_DISENCHANT, dir, spell_power(damage), (plev > 40 ? -3 : -2)); break; case MS_BR_NEXUS: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe nexus."); damage = MIN(hp / 3, 250); fire_ball(GF_NEXUS, dir, spell_power(damage), (plev > 40 ? -3 : -2)); break; case MS_BR_TIME: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe time."); damage = MIN(hp / 3, 150); fire_ball(GF_TIME, dir, spell_power(damage), (plev > 40 ? -3 : -2)); break; case MS_BR_INERTIA: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe inertia."); damage = MIN(hp / 6, 200); fire_ball(GF_INERT, dir, spell_power(damage), (plev > 40 ? -3 : -2)); break; case MS_BR_GRAVITY: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe gravity."); damage = MIN(hp / 3, 200); fire_ball(GF_GRAVITY, dir, spell_power(damage), (plev > 40 ? -3 : -2)); break; case MS_BR_SHARDS: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe shards."); damage = hp / 6; fire_ball(GF_SHARDS, dir, spell_power(damage), (plev > 40 ? -3 : -2)); break; case MS_BR_PLASMA: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe plasma."); damage = MIN(hp / 6, 150); fire_ball(GF_PLASMA, dir, spell_power(damage), (plev > 40 ? -3 : -2)); break; case MS_BR_FORCE: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe force."); damage = MIN(hp / 6, 200); fire_ball(GF_FORCE, dir, spell_power(damage), (plev > 40 ? -3 : -2)); break; case MS_BR_MANA: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe mana."); damage = MIN(hp / 3, 250); fire_ball(GF_MANA, dir, spell_power(damage), (plev > 40 ? -3 : -2)); break; case MS_BALL_NUKE: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a ball of radiation."); damage = plev * 2 + damroll(10, 6); fire_ball(GF_NUKE, dir, spell_power(damage), 2); break; case MS_BR_NUKE: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe toxic waste."); damage = hp / 3; fire_ball(GF_NUKE, dir, spell_power(damage), (plev > 40 ? -3 : -2)); break; case MS_BALL_CHAOS: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You invoke a raw Logrus."); damage = plev * 4 + damroll(10, 10); fire_ball(GF_CHAOS, dir, spell_power(damage), 4); break; case MS_BR_DISI: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe disintegration."); damage = MIN(hp / 6, 150); fire_ball(GF_DISINTEGRATE, dir, spell_power(damage), (plev > 40 ? -3 : -2)); break; case MS_BALL_ACID: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast an acid ball."); damage = randint1(plev * 6) + 15; fire_ball(GF_ACID, dir, spell_power(damage), 2); break; case MS_BALL_ELEC: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a lightning ball."); damage = randint1(plev * 3) + 8; fire_ball(GF_ELEC, dir, spell_power(damage), 2); break; case MS_BALL_FIRE: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a fire ball."); damage = randint1(plev * 7) + 10; fire_ball(GF_FIRE, dir, spell_power(damage), 2); break; case MS_BALL_COLD: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a frost ball."); damage = randint1(plev * 3) + 10; fire_ball(GF_COLD, dir, spell_power(damage), 2); break; case MS_BALL_POIS: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a stinking cloud."); damage = damroll(12,2); fire_ball(GF_POIS, dir, spell_power(damage), 2); break; case MS_BALL_NETHER: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a nether ball."); damage = plev * 2 + 50 + damroll(10, 10); fire_ball(GF_NETHER, dir, spell_power(damage), 2); break; case MS_BALL_WATER: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You gesture fluidly."); damage = randint1(plev * 4) + 50; fire_ball(GF_WATER, dir, spell_power(damage), 4); break; case MS_BALL_MANA: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You invoke a mana storm."); damage = plev * 8 + 50 + damroll(10, 10); fire_ball(GF_MANA, dir, spell_power(damage), 4); break; case MS_BALL_DARK: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You invoke a darkness storm."); damage = plev * 8 + 50 + damroll(10, 10); fire_ball(GF_DARK, dir, spell_power(damage), 4); break; case MS_DRAIN_MANA: if (!get_aim_dir(&dir)) return FALSE; fire_ball_hide(GF_DRAIN_MANA, dir, spell_power(randint1(plev)+plev), 0); break; case MS_MIND_BLAST: if (!get_aim_dir(&dir)) return FALSE; damage = damroll(7, 7); fire_ball_hide(GF_MIND_BLAST, dir, spell_power(damage), 0); break; case MS_BRAIN_SMASH: if (!get_aim_dir(&dir)) return FALSE; damage = damroll(12, 12); fire_ball_hide(GF_BRAIN_SMASH, dir, spell_power(damage), 0); break; case MS_CAUSE_1: if (!get_aim_dir(&dir)) return FALSE; damage = damroll(3, 8); fire_ball_hide(GF_CAUSE_1, dir, spell_power(damage), 0); break; case MS_CAUSE_2: if (!get_aim_dir(&dir)) return FALSE; damage = damroll(8, 8); fire_ball_hide(GF_CAUSE_2, dir, spell_power(damage), 0); break; case MS_CAUSE_3: if (!get_aim_dir(&dir)) return FALSE; damage = damroll(10, 15); fire_ball_hide(GF_CAUSE_3, dir, spell_power(damage), 0); break; case MS_CAUSE_4: if (!get_aim_dir(&dir)) return FALSE; damage = damroll(15, 15); fire_ball_hide(GF_CAUSE_4, dir, spell_power(damage), 0); break; case MS_BOLT_ACID: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast an acid bolt."); damage = damroll(7, 8) + plev * 2 / 3; fire_bolt(GF_ACID, dir, spell_power(damage)); break; case MS_BOLT_ELEC: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a lightning bolt."); damage = damroll(4, 8) + plev * 2 / 3; fire_bolt(GF_ELEC, dir, spell_power(damage)); break; case MS_BOLT_FIRE: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a fire bolt."); damage = damroll(9, 8) + plev * 2 / 3; fire_bolt(GF_FIRE, dir, spell_power(damage)); break; case MS_BOLT_COLD: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a frost bolt."); damage = damroll(6, 8) + plev * 2 / 3; fire_bolt(GF_COLD, dir, spell_power(damage)); break; case MS_STARBURST: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You invoke a starburst."); damage = plev * 8 + 50 + damroll(10, 10); fire_ball(GF_LITE, dir, spell_power(damage), 4); break; case MS_BOLT_NETHER: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a nether bolt."); damage = 30 + damroll(5, 5) + plev * 8 / 3; fire_bolt(GF_NETHER, dir, spell_power(damage)); break; case MS_BOLT_WATER: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a water bolt."); damage = damroll(10, 10) + plev * 2; fire_bolt(GF_WATER, dir, spell_power(damage)); break; case MS_BOLT_MANA: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a mana bolt."); damage = randint1(plev * 7) + 50; fire_bolt(GF_MANA, dir, spell_power(damage)); break; case MS_BOLT_PLASMA: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a plasma bolt."); damage = 10 + damroll(8, 7) + plev * 2; fire_bolt(GF_PLASMA, dir, spell_power(damage)); break; case MS_BOLT_ICE: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a ice bolt."); damage = damroll(6, 6) + plev * 2; fire_bolt(GF_ICE, dir, spell_power(damage)); break; case MS_MAGIC_MISSILE: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a magic missile."); damage = damroll(2, 6) + plev * 2 / 3; fire_bolt(GF_MISSILE, dir, spell_power(damage)); break; case MS_SCARE: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a fearful illusion."); fear_monster(dir, spell_power(plev+10)); break; case MS_BLIND: if (!get_aim_dir(&dir)) return FALSE; confuse_monster(dir, spell_power(plev * 2)); break; case MS_CONF: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a mesmerizing illusion."); confuse_monster(dir, spell_power(plev * 2)); break; case MS_SLOW: if (!get_aim_dir(&dir)) return FALSE; slow_monster(dir); break; case MS_SLEEP: if (!get_aim_dir(&dir)) return FALSE; sleep_monster(dir, plev*3); break; case MS_SPEED: (void)set_fast(randint1(20 + plev) + plev, FALSE); break; case MS_HAND_DOOM: { if (!get_aim_dir(&dir)) return FALSE; else msg_print("You invoke the Hand of Doom!"); fire_ball_hide(GF_HAND_DOOM, dir, spell_power(plev * 3), 0); break; } case MS_HEAL: msg_print("You concentrate on your wounds!"); (void)hp_player(spell_power(plev*4)); (void)set_stun(0, TRUE); (void)set_cut(0, TRUE); break; case MS_INVULNER: msg_print("You cast a Globe of Invulnerability."); (void)set_invuln(spell_power(randint1(4) + 4), FALSE); break; case MS_BLINK: teleport_player(10, 0L); break; case MS_TELEPORT: teleport_player(plev * 5, 0L); break; case MS_WORLD: world_player = TRUE; msg_print("'Time!'"); msg_print(NULL); /* Hack */ p_ptr->energy_need -= 1000 + (100 + randint1(200)+200)*TURNS_PER_TICK/10; /* Redraw map */ p_ptr->redraw |= (PR_MAP | PR_STATUS); /* Update monsters */ p_ptr->update |= (PU_MONSTERS); /* Window stuff */ p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON); handle_stuff(); break; case MS_SPECIAL: break; case MS_TELE_TO: { monster_type *m_ptr; monster_race *r_ptr; char m_name[80]; if (!target_set(TARGET_KILL)) return FALSE; if (!cave[target_row][target_col].m_idx) break; if (!player_has_los_bold(target_row, target_col)) break; if (!projectable(py, px, target_row, target_col)) break; m_ptr = &m_list[cave[target_row][target_col].m_idx]; r_ptr = &r_info[m_ptr->r_idx]; monster_desc(m_name, m_ptr, 0); if (r_ptr->flagsr & RFR_RES_TELE) { if ((r_ptr->flags1 & (RF1_UNIQUE)) || (r_ptr->flagsr & RFR_RES_ALL)) { if (is_original_ap_and_seen(m_ptr)) r_ptr->r_flagsr |= RFR_RES_TELE; msg_format("%s is unaffected!", m_name); break; } else if (r_ptr->level > randint1(100)) { if (is_original_ap_and_seen(m_ptr)) r_ptr->r_flagsr |= RFR_RES_TELE; msg_format("%s resists!", m_name); break; } } msg_format("You command %s to return.", m_name); teleport_monster_to(cave[target_row][target_col].m_idx, py, px, 100, TELEPORT_PASSIVE); break; } case MS_TELE_AWAY: if (!get_aim_dir(&dir)) return FALSE; (void)fire_beam(GF_AWAY_ALL, dir, spell_power(100)); break; case MS_TELE_LEVEL: { int target_m_idx; monster_type *m_ptr; monster_race *r_ptr; char m_name[80]; if (!target_set(TARGET_KILL)) return FALSE; target_m_idx = cave[target_row][target_col].m_idx; if (!target_m_idx) break; if (!player_has_los_bold(target_row, target_col)) break; if (!projectable(py, px, target_row, target_col)) break; m_ptr = &m_list[target_m_idx]; r_ptr = &r_info[m_ptr->r_idx]; monster_desc(m_name, m_ptr, 0); msg_format("You gesture at %^s's feet.", m_name); if ((r_ptr->flagsr & (RFR_EFF_RES_NEXU_MASK | RFR_RES_TELE)) || (r_ptr->flags1 & RF1_QUESTOR) || (r_ptr->level + randint1(50) > plev + randint1(60))) { msg_format("%^s is unaffected!", m_name); } else teleport_level(target_m_idx); break; } case MS_PSY_SPEAR: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You throw a psycho-spear."); damage = randint1(plev * 3) + 100; (void)fire_beam(GF_PSY_SPEAR, dir, spell_power(damage)); break; case MS_DARKNESS: msg_print("You gesture in shadow."); (void)unlite_area(10, 3); break; case MS_MAKE_TRAP: if (!target_set(TARGET_KILL)) return FALSE; msg_print("You cast a spell and cackle evilly."); trap_creation(target_row, target_col); break; case MS_FORGET: msg_print("Nothing happen."); break; case MS_RAISE_DEAD: msg_print("You cast a animate dead."); (void)animate_dead(0, py, px); break; case MS_S_KIN: { int k; msg_print("You summon minions."); for (k = 0;k < 1; k++) { if (summon_kin_player(summon_lev, py, px, (pet ? PM_FORCE_PET : 0L))) { if (!pet) msg_print("Summoned fellows are angry!"); } else { no_trump = TRUE; } } break; } case MS_S_CYBER: { int k; msg_print("You summon a Cyberdemon!"); for (k = 0 ;k < 1 ; k++) if (summon_specific((pet ? -1 : 0), py, px, summon_lev, SUMMON_CYBER, p_mode)) { if (!pet) msg_print("The summoned Cyberdemon are angry!"); } else { no_trump = TRUE; } break; } case MS_S_MONSTER: { int k; msg_print("You summon help."); for (k = 0;k < 1; k++) if (summon_specific((pet ? -1 : 0), py, px, summon_lev, 0, p_mode)) { if (!pet) msg_print("The summoned monster is angry!"); } else { no_trump = TRUE; } break; } case MS_S_MONSTERS: { int k; msg_print("You summon monsters!"); for (k = 0;k < plev / 15 + 2; k++) if(summon_specific((pet ? -1 : 0), py, px, summon_lev, 0, (p_mode | u_mode))) { if (!pet) msg_print("Summoned monsters are angry!"); } else { no_trump = TRUE; } break; } case MS_S_ANT: { int k; msg_print("You summon ants."); for (k = 0;k < 1; k++) if (summon_specific((pet ? -1 : 0), py, px, summon_lev, SUMMON_ANT, (PM_ALLOW_GROUP | p_mode))) { if (!pet) msg_print("Summoned ants are angry!"); } else { no_trump = TRUE; } break; } case MS_S_SPIDER: { int k; msg_print("You summon spiders."); for (k = 0;k < 1; k++) if (summon_specific((pet ? -1 : 0), py, px, summon_lev, SUMMON_SPIDER, (PM_ALLOW_GROUP | p_mode))) { if (!pet) msg_print("Summoned spiders are angry!"); } else { no_trump = TRUE; } break; } case MS_S_HOUND: { int k; msg_print("You summon hounds."); for (k = 0;k < 1; k++) if (summon_specific((pet ? -1 : 0), py, px, summon_lev, SUMMON_HOUND, (PM_ALLOW_GROUP | p_mode))) { if (!pet) msg_print("Summoned hounds are angry!"); } else { no_trump = TRUE; } break; } case MS_S_HYDRA: { int k; msg_print("You summon a hydras."); for (k = 0;k < 1; k++) if (summon_specific((pet ? -1 : 0), py, px, summon_lev, SUMMON_HYDRA, (g_mode | p_mode))) { if (!pet) msg_print("Summoned hydras are angry!"); } else { no_trump = TRUE; } break; } case MS_S_ANGEL: { int k; msg_print("You summon an angel!"); for (k = 0;k < 1; k++) if (summon_specific((pet ? -1 : 0), py, px, summon_lev, SUMMON_ANGEL, (g_mode | p_mode))) { if (!pet) msg_print("Summoned angels are angry!"); } else { no_trump = TRUE; } break; } case MS_S_DEMON: { int k; msg_print("You summon a demon from the Courts of Chaos!"); for (k = 0;k < 1; k++) if (summon_specific((pet ? -1 : 0), py, px, summon_lev, SUMMON_DEMON, (g_mode | p_mode))) { if (!pet) msg_print("Summoned demons are angry!"); } else { no_trump = TRUE; } break; } case MS_S_UNDEAD: { int k; msg_print("You summon an undead adversary!"); for (k = 0;k < 1; k++) if (summon_specific((pet ? -1 : 0), py, px, summon_lev, SUMMON_UNDEAD, (g_mode | p_mode))) { if (!pet) msg_print("Summoned undeads are angry!"); } else { no_trump = TRUE; } break; } case MS_S_DRAGON: { int k; msg_print("You summon a dragon!"); for (k = 0;k < 1; k++) if (summon_specific((pet ? -1 : 0), py, px, summon_lev, SUMMON_DRAGON, (g_mode | p_mode))) { if (!pet) msg_print("Summoned dragons are angry!"); } else { no_trump = TRUE; } break; } case MS_S_HI_UNDEAD: { int k; msg_print("You summon a greater undead!"); for (k = 0;k < 1; k++) if (summon_specific((pet ? -1 : 0), py, px, summon_lev, SUMMON_HI_UNDEAD, (g_mode | p_mode | u_mode))) { if (!pet) msg_print("Summoned greater undeads are angry!"); } else { no_trump = TRUE; } break; } case MS_S_HI_DRAGON: { int k; msg_print("You summon an ancient dragon!"); for (k = 0;k < 1; k++) if (summon_specific((pet ? -1 : 0), py, px, summon_lev, SUMMON_HI_DRAGON, (g_mode | p_mode | u_mode))) { if (!pet) msg_print("Summoned ancient dragons are angry!"); } else { no_trump = TRUE; } break; } case MS_S_AMBERITE: { int k; msg_print("You summon a Lord of Amber!"); for (k = 0;k < 1; k++) if (summon_specific((pet ? -1 : 0), py, px, summon_lev, SUMMON_AMBERITE, (g_mode | p_mode | u_mode))) { if (!pet) msg_print("Summoned Lords of Amber are angry!"); } else { no_trump = TRUE; } break; } case MS_S_UNIQUE: { int k, count = 0; msg_print("You summon a special opponent!"); for (k = 0;k < 1; k++) if (summon_specific((pet ? -1 : 0), py, px, summon_lev, SUMMON_UNIQUE, (g_mode | p_mode | PM_ALLOW_UNIQUE))) { count++; if (!pet) msg_print("Summoned special opponents are angry!"); } for (k = count;k < 1; k++) if (summon_specific((pet ? -1 : 0), py, px, summon_lev, SUMMON_HI_UNDEAD, (g_mode | p_mode | PM_ALLOW_UNIQUE))) { count++; if (!pet) msg_print("Summoned greater undeads are angry!"); } if (!count) { no_trump = TRUE; } break; } default: msg_print("hoge?"); } if (no_trump) { msg_print("No one have appeared."); } return TRUE; }
/* * do_cmd_cast calls this function if the player's class * is 'imitator'. */ static bool use_mane(int spell) { int dir; int plev = p_ptr->lev; u32b mode = (PM_ALLOW_GROUP | PM_FORCE_PET); u32b u_mode = 0L; if (randint1(50+plev) < plev/10) u_mode = PM_ALLOW_UNIQUE; /* spell code */ switch (spell) { case MS_SHRIEK: msg_print("You make a high pitched shriek."); aggravate_monsters(0); break; case MS_XXX1: break; case MS_DISPEL: { int m_idx; if (!target_set(TARGET_KILL)) return FALSE; m_idx = cave[target_row][target_col].m_idx; if (!m_idx) break; if (!player_has_los_bold(target_row, target_col)) break; if (!projectable(py, px, target_row, target_col)) break; dispel_monster_status(m_idx); break; } case MS_ROCKET: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You fire a rocket."); fire_rocket(GF_ROCKET, dir, damage, 2); break; case MS_SHOOT: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You fire an arrow."); fire_bolt(GF_ARROW, dir, damage); break; case MS_XXX2: break; case MS_XXX3: break; case MS_BR_STORM: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe storm."); fire_ball(GF_STORM, dir, damage, (plev > 35 ? -3 : -2)); break; case MS_BR_ACID: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe acid."); fire_ball(GF_ACID, dir, damage, (plev > 35 ? -3 : -2)); break; case MS_BR_ELEC: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe lightning."); fire_ball(GF_ELEC, dir, damage, (plev > 35 ? -3 : -2)); break; case MS_BR_FIRE: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe fire."); fire_ball(GF_FIRE, dir, damage, (plev > 35 ? -3 : -2)); break; case MS_BR_COLD: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe frost."); fire_ball(GF_COLD, dir, damage, (plev > 35 ? -3 : -2)); break; case MS_BR_POIS: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe gas."); fire_ball(GF_POIS, dir, damage, (plev > 35 ? -3 : -2)); break; case MS_BR_NETHER: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe nether."); fire_ball(GF_NETHER, dir, damage, (plev > 35 ? -3 : -2)); break; case MS_BR_LITE: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe light."); fire_ball(GF_LITE, dir, damage, (plev > 35 ? -3 : -2)); break; case MS_BR_DARK: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe darkness."); fire_ball(GF_DARK, dir, damage, (plev > 35 ? -3 : -2)); break; case MS_BR_CONF: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe confusion."); fire_ball(GF_CONFUSION, dir, damage, (plev > 35 ? -3 : -2)); break; case MS_BR_SOUND: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe sound."); fire_ball(GF_SOUND, dir, damage, (plev > 35 ? -3 : -2)); break; case MS_BR_CHAOS: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe chaos."); fire_ball(GF_CHAOS, dir, damage, (plev > 35 ? -3 : -2)); break; case MS_BR_DISEN: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe disenchantment."); fire_ball(GF_DISENCHANT, dir, damage, (plev > 35 ? -3 : -2)); break; case MS_BR_NEXUS: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe nexus."); fire_ball(GF_NEXUS, dir, damage, (plev > 35 ? -3 : -2)); break; case MS_BR_TIME: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe time."); fire_ball(GF_TIME, dir, damage, (plev > 35 ? -3 : -2)); break; case MS_BR_INERTIA: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe inertia."); fire_ball(GF_INERT, dir, damage, (plev > 35 ? -3 : -2)); break; case MS_BR_GRAVITY: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe gravity."); fire_ball(GF_GRAVITY, dir, damage, (plev > 35 ? -3 : -2)); break; case MS_BR_SHARDS: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe shards."); fire_ball(GF_SHARDS, dir, damage, (plev > 35 ? -3 : -2)); break; case MS_BR_PLASMA: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe plasma."); fire_ball(GF_PLASMA, dir, damage, (plev > 35 ? -3 : -2)); break; case MS_BR_FORCE: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe force."); fire_ball(GF_FORCE, dir, damage, (plev > 35 ? -3 : -2)); break; case MS_BR_MANA: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe mana."); fire_ball(GF_MANA, dir, damage, (plev > 35 ? -3 : -2)); break; case MS_BALL_NUKE: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a ball of radiation."); fire_ball(GF_NUKE, dir, damage, 2); break; case MS_BR_NUKE: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe toxic waste."); fire_ball(GF_NUKE, dir, damage, (plev > 35 ? -3 : -2)); break; case MS_BALL_CHAOS: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You invoke a raw Logrus."); fire_ball(GF_CHAOS, dir, damage, 4); break; case MS_BR_DISI: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You breathe disintegration."); fire_ball(GF_DISINTEGRATE, dir, damage, (plev > 35 ? -3 : -2)); break; case MS_BALL_ACID: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast an acid ball."); fire_ball(GF_ACID, dir, damage, 2); break; case MS_BALL_ELEC: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a lightning ball."); fire_ball(GF_ELEC, dir, damage, 2); break; case MS_BALL_FIRE: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a fire ball."); fire_ball(GF_FIRE, dir, damage, 2); break; case MS_BALL_COLD: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a frost ball."); fire_ball(GF_COLD, dir, damage, 2); break; case MS_BALL_POIS: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a stinking cloud."); fire_ball(GF_POIS, dir, damage, 2); break; case MS_BALL_NETHER: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a nether ball."); fire_ball(GF_NETHER, dir, damage, 2); break; case MS_BALL_WATER: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You gesture fluidly."); fire_ball(GF_WATER, dir, damage, 4); break; case MS_BALL_MANA: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You invoke a mana storm."); fire_ball(GF_MANA, dir, damage, 4); break; case MS_BALL_DARK: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You invoke a darkness storm."); fire_ball(GF_DARK, dir, damage, 4); break; case MS_DRAIN_MANA: if (!get_aim_dir(&dir)) return FALSE; fire_ball_hide(GF_DRAIN_MANA, dir, randint1(plev*3)+plev, 0); break; case MS_MIND_BLAST: if (!get_aim_dir(&dir)) return FALSE; fire_ball_hide(GF_MIND_BLAST, dir, damage, 0); break; case MS_BRAIN_SMASH: if (!get_aim_dir(&dir)) return FALSE; fire_ball_hide(GF_BRAIN_SMASH, dir, damage, 0); break; case MS_CAUSE_1: if (!get_aim_dir(&dir)) return FALSE; fire_ball_hide(GF_CAUSE_1, dir, damage, 0); break; case MS_CAUSE_2: if (!get_aim_dir(&dir)) return FALSE; fire_ball_hide(GF_CAUSE_2, dir, damage, 0); break; case MS_CAUSE_3: if (!get_aim_dir(&dir)) return FALSE; fire_ball_hide(GF_CAUSE_3, dir, damage, 0); break; case MS_CAUSE_4: if (!get_aim_dir(&dir)) return FALSE; fire_ball_hide(GF_CAUSE_4, dir, damage, 0); break; case MS_BOLT_ACID: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast an acid bolt."); fire_bolt(GF_ACID, dir, damage); break; case MS_BOLT_ELEC: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a lightning bolt."); fire_bolt(GF_ELEC, dir, damage); break; case MS_BOLT_FIRE: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a fire bolt."); fire_bolt(GF_FIRE, dir, damage); break; case MS_BOLT_COLD: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a frost bolt."); fire_bolt(GF_COLD, dir, damage); break; case MS_STARBURST: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You invoke a starburst."); fire_ball(GF_LITE, dir, damage, 4); break; case MS_BOLT_NETHER: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a nether bolt."); fire_bolt(GF_NETHER, dir, damage); break; case MS_BOLT_WATER: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a water bolt."); fire_bolt(GF_WATER, dir, damage); break; case MS_BOLT_MANA: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a mana bolt."); fire_bolt(GF_MANA, dir, damage); break; case MS_BOLT_PLASMA: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a plasma bolt."); fire_bolt(GF_PLASMA, dir, damage); break; case MS_BOLT_ICE: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a ice bolt."); fire_bolt(GF_ICE, dir, damage); break; case MS_MAGIC_MISSILE: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a magic missile."); fire_bolt(GF_MISSILE, dir, damage); break; case MS_SCARE: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a fearful illusion."); fear_monster(dir, plev+10); break; case MS_BLIND: if (!get_aim_dir(&dir)) return FALSE; confuse_monster(dir, plev * 2); break; case MS_CONF: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You cast a mesmerizing illusion."); confuse_monster(dir, plev * 2); break; case MS_SLOW: if (!get_aim_dir(&dir)) return FALSE; slow_monster(dir); break; case MS_SLEEP: if (!get_aim_dir(&dir)) return FALSE; sleep_monster(dir, plev*3); break; case MS_SPEED: (void)set_fast(randint1(20 + plev) + plev, FALSE); break; case MS_HAND_DOOM: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You invoke the Hand of Doom!"); fire_ball_hide(GF_HAND_DOOM, dir, 200, 0); break; case MS_HEAL: msg_print("You concentrate on your wounds!"); (void)hp_player(plev*6); (void)set_stun(0, TRUE); (void)set_cut(0, TRUE); break; case MS_INVULNER: msg_print("You cast a Globe of Invulnerability."); (void)set_invuln(randint1(7) + 7, FALSE); break; case MS_BLINK: if (mut_present(MUT_ASTRAL_GUIDE)) energy_use = 30; teleport_player(10, 0L); break; case MS_TELEPORT: if (mut_present(MUT_ASTRAL_GUIDE)) energy_use = 30; teleport_player(plev * 5, 0L); break; case MS_WORLD: world_player = TRUE; if (damage == 1 || damage == 2) msg_print("You yell 'The World! Time has stopped!'"); else if (damage == 3 || damage == 6) msg_print("You yell 'Time!'"); else msg_print("hek!"); msg_print(NULL); p_ptr->energy_need -= 1000 + (100 + randint1(200)+200)*TURNS_PER_TICK/10; p_ptr->redraw |= (PR_MAP); p_ptr->update |= (PU_MONSTERS); p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON); handle_stuff(); break; case MS_SPECIAL: break; case MS_TELE_TO: { monster_type *m_ptr; monster_race *r_ptr; char m_name[80]; if (!target_set(TARGET_KILL)) return FALSE; if (!cave[target_row][target_col].m_idx) break; if (!player_has_los_bold(target_row, target_col)) break; if (!projectable(py, px, target_row, target_col)) break; m_ptr = &m_list[cave[target_row][target_col].m_idx]; r_ptr = &r_info[m_ptr->r_idx]; monster_desc(m_name, m_ptr, 0); if (r_ptr->flagsr & RFR_RES_TELE) { if ((r_ptr->flags1 & (RF1_UNIQUE)) || (r_ptr->flagsr & RFR_RES_ALL)) { if (is_original_ap_and_seen(m_ptr)) r_ptr->r_flagsr |= RFR_RES_TELE; msg_format("%s is unaffected!", m_name); break; } else if (r_ptr->level > randint1(100)) { if (is_original_ap_and_seen(m_ptr)) r_ptr->r_flagsr |= RFR_RES_TELE; msg_format("%s resists!", m_name); break; } } msg_format("You command %s to return.", m_name); teleport_monster_to(cave[target_row][target_col].m_idx, py, px, 100, TELEPORT_PASSIVE); break; } case MS_TELE_AWAY: if (!get_aim_dir(&dir)) return FALSE; (void)fire_beam(GF_AWAY_ALL, dir, plev); break; case MS_TELE_LEVEL: { int target_m_idx; monster_type *m_ptr; monster_race *r_ptr; char m_name[80]; if (!target_set(TARGET_KILL)) return FALSE; target_m_idx = cave[target_row][target_col].m_idx; if (!target_m_idx) break; if (!player_has_los_bold(target_row, target_col)) break; if (!projectable(py, px, target_row, target_col)) break; m_ptr = &m_list[target_m_idx]; r_ptr = &r_info[m_ptr->r_idx]; monster_desc(m_name, m_ptr, 0); msg_format("You gesture at %^s's feet.", m_name); if ((r_ptr->flagsr & (RFR_EFF_RES_NEXU_MASK | RFR_RES_TELE)) || (r_ptr->flags1 & RF1_QUESTOR) || (r_ptr->level + randint1(50) > plev + randint1(60))) { msg_format("%^s is unaffected!", m_name); } else teleport_level(target_m_idx); break; } case MS_PSY_SPEAR: if (!get_aim_dir(&dir)) return FALSE; else msg_print("You throw a psycho-spear."); fire_beam(GF_PSY_SPEAR, dir, damage); break; case MS_DARKNESS: msg_print("You gesture in shadow."); unlite_area(10, 3); break; case MS_MAKE_TRAP: if (!target_set(TARGET_KILL)) return FALSE; msg_print("You cast a spell and cackle evilly."); trap_creation(target_row, target_col); break; case MS_FORGET: msg_print("Nothing happens."); /* TODO: forget_spell(m_idx) ... */ break; case MS_RAISE_DEAD: msg_print("You cast a animate dead."); animate_dead(0, py, px); break; case MS_S_KIN: { int k; if (!target_set(TARGET_KILL)) return FALSE; msg_print("You summon minions."); for (k = 0;k < 4; k++) { (void)summon_kin_player(plev, target_row, target_col, (PM_FORCE_PET | PM_ALLOW_GROUP)); } break; } case MS_S_CYBER: { int k; int max_cyber = (dun_level / 50) + randint1(3); if (!target_set(TARGET_KILL)) return FALSE; msg_print("You summon Cyberdemons!"); if (max_cyber > 4) max_cyber = 4; for (k = 0;k < max_cyber; k++) summon_specific(-1, target_row, target_col, plev, SUMMON_CYBER, mode); break; } case MS_S_MONSTER: { int k; if (!target_set(TARGET_KILL)) return FALSE; msg_print("You summon help."); for (k = 0;k < 1; k++) summon_specific(-1, target_row, target_col, plev, 0, (mode | u_mode)); break; } case MS_S_MONSTERS: { int k; if (!target_set(TARGET_KILL)) return FALSE; msg_print("You summon monsters!"); for (k = 0;k < 6; k++) summon_specific(-1, target_row, target_col, plev, 0, (mode | u_mode)); break; } case MS_S_ANT: { int k; if (!target_set(TARGET_KILL)) return FALSE; msg_print("You summon ants."); for (k = 0;k < 6; k++) summon_specific(-1, target_row, target_col, plev, SUMMON_ANT, mode); break; } case MS_S_SPIDER: { int k; if (!target_set(TARGET_KILL)) return FALSE; msg_print("You summon spiders."); for (k = 0;k < 6; k++) summon_specific(-1, target_row, target_col, plev, SUMMON_SPIDER, mode); break; } case MS_S_HOUND: { int k; if (!target_set(TARGET_KILL)) return FALSE; msg_print("You summon hounds."); for (k = 0;k < 4; k++) summon_specific(-1, target_row, target_col, plev, SUMMON_HOUND, mode); break; } case MS_S_HYDRA: { int k; if (!target_set(TARGET_KILL)) return FALSE; msg_print("You summon hydras."); for (k = 0;k < 4; k++) summon_specific(-1, target_row, target_col, plev, SUMMON_HYDRA, mode); break; } case MS_S_ANGEL: { int k; if (!target_set(TARGET_KILL)) return FALSE; msg_print("You summon angel!"); for (k = 0;k < 1; k++) summon_specific(-1, target_row, target_col, plev, SUMMON_ANGEL, mode); break; } case MS_S_DEMON: { int k; if (!target_set(TARGET_KILL)) return FALSE; msg_print("You summon a demon from the Courts of Chaos!"); for (k = 0;k < 1; k++) summon_specific(-1, target_row, target_col, plev, SUMMON_DEMON, (mode | u_mode)); break; } case MS_S_UNDEAD: { int k; if (!target_set(TARGET_KILL)) return FALSE; msg_print("You summon an undead adversary!"); for (k = 0;k < 1; k++) summon_specific(-1, target_row, target_col, plev, SUMMON_UNDEAD, (mode | u_mode)); break; } case MS_S_DRAGON: { int k; if (!target_set(TARGET_KILL)) return FALSE; msg_print("You summon dragon!"); for (k = 0;k < 1; k++) summon_specific(-1, target_row, target_col, plev, SUMMON_DRAGON, (mode | u_mode)); break; } case MS_S_HI_UNDEAD: { int k; if (!target_set(TARGET_KILL)) return FALSE; msg_print("You summon greater undead!"); for (k = 0;k < 6; k++) summon_specific(-1, target_row, target_col, plev, SUMMON_HI_UNDEAD, (mode | u_mode)); break; } case MS_S_HI_DRAGON: { int k; if (!target_set(TARGET_KILL)) return FALSE; msg_print("You summon ancient dragons!"); for (k = 0;k < 4; k++) summon_specific(-1, target_row, target_col, plev, SUMMON_HI_DRAGON, (mode | u_mode)); break; } case MS_S_AMBERITE: { int k; if (!target_set(TARGET_KILL)) return FALSE; msg_print("You summon Lords of Amber!"); for (k = 0;k < 4; k++) summon_specific(-1, target_row, target_col, plev, SUMMON_AMBERITE, (mode | PM_ALLOW_UNIQUE)); break; } case MS_S_UNIQUE: { int k, count = 0; if (!target_set(TARGET_KILL)) return FALSE; msg_print("You summon special opponents!"); for (k = 0;k < 4; k++) if (summon_specific(-1, target_row, target_col, plev, SUMMON_UNIQUE, (mode | PM_ALLOW_UNIQUE))) count++; for (k = count;k < 4; k++) summon_specific(-1, target_row, target_col, plev, SUMMON_HI_UNDEAD, (mode | u_mode)); break; } default: msg_print("hoge?"); } return TRUE; }
/*! * @brief モンスターが敵モンスターに特殊能力を使う処理のメインルーチン / * Monster tries to 'cast a spell' (or breath, etc) at another monster. * @param m_idx 術者のモンスターID * @return 実際に特殊能力を使った場合TRUEを返す * @details * The player is only disturbed if able to be affected by the spell. */ bool monst_spell_monst(int m_idx) { int y = 0, x = 0; int i, k, t_idx = 0; int thrown_spell; int dam = 0; int start; int plus = 1; byte spell[96], num = 0; char m_name[160]; char t_name[160]; #ifndef JP char m_poss[160]; #endif monster_type *m_ptr = &m_list[m_idx]; monster_type *t_ptr = NULL; monster_race *r_ptr = &r_info[m_ptr->r_idx]; monster_race *tr_ptr = NULL; u32b f4, f5, f6; bool see_m = is_seen(m_ptr); bool maneable = player_has_los_bold(m_ptr->fy, m_ptr->fx); bool see_t; bool see_either; bool pet = is_pet(m_ptr); bool in_no_magic_dungeon = (d_info[dungeon_type].flags1 & DF1_NO_MAGIC) && dun_level && (!p_ptr->inside_quest || is_fixed_quest_idx(p_ptr->inside_quest)); bool can_use_lite_area = FALSE; bool can_remember; /* Cannot cast spells when confused */ if (MON_CONFUSED(m_ptr)) return (FALSE); /* Extract the racial spell flags */ f4 = r_ptr->flags4; f5 = r_ptr->a_ability_flags1; f6 = r_ptr->a_ability_flags2; /* Target is given for pet? */ if (pet_t_m_idx && pet) { t_idx = pet_t_m_idx; t_ptr = &m_list[t_idx]; /* Cancel if not projectable (for now) */ if ((m_idx == t_idx) || !projectable(m_ptr->fy, m_ptr->fx, t_ptr->fy, t_ptr->fx)) { t_idx = 0; } } /* Is there counter attack target? */ if (!t_idx && m_ptr->target_y) { t_idx = cave[m_ptr->target_y][m_ptr->target_x].m_idx; if (t_idx) { t_ptr = &m_list[t_idx]; /* Cancel if neither enemy nor a given target */ if ((m_idx == t_idx) || ((t_idx != pet_t_m_idx) && !are_enemies(m_ptr, t_ptr))) { t_idx = 0; } /* Allow only summoning etc.. if not projectable */ else if (!projectable(m_ptr->fy, m_ptr->fx, t_ptr->fy, t_ptr->fx)) { f4 &= (RF4_INDIRECT_MASK); f5 &= (RF5_INDIRECT_MASK); f6 &= (RF6_INDIRECT_MASK); } } } /* Look for enemies normally */ if (!t_idx) { bool success = FALSE; if (p_ptr->inside_battle) { start = randint1(m_max-1) + m_max; if (randint0(2)) plus = -1; } else start = m_max + 1; /* Scan thru all monsters */ for (i = start; ((i < start + m_max) && (i > start - m_max)); i += plus) { int dummy = (i % m_max); if (!dummy) continue; t_idx = dummy; t_ptr = &m_list[t_idx]; /* Skip dead monsters */ if (!t_ptr->r_idx) continue; /* Monster must be 'an enemy' */ if ((m_idx == t_idx) || !are_enemies(m_ptr, t_ptr)) continue; /* Monster must be projectable */ if (!projectable(m_ptr->fy, m_ptr->fx, t_ptr->fy, t_ptr->fx)) continue; /* Get it */ success = TRUE; break; } /* No enemy found */ if (!success) return FALSE; } /* OK -- we've got a target */ y = t_ptr->fy; x = t_ptr->fx; tr_ptr = &r_info[t_ptr->r_idx]; /* Forget old counter attack target */ reset_target(m_ptr); /* Remove unimplemented spells */ f6 &= ~(RF6_WORLD | RF6_TRAPS | RF6_FORGET); if (f4 & RF4_BR_LITE) { if (!los(m_ptr->fy, m_ptr->fx, t_ptr->fy, t_ptr->fx)) f4 &= ~(RF4_BR_LITE); } /* Remove unimplemented special moves */ if (f6 & RF6_SPECIAL) { if ((m_ptr->r_idx != MON_ROLENTO) && (r_ptr->d_char != 'B')) f6 &= ~(RF6_SPECIAL); } if (f6 & RF6_DARKNESS) { bool vs_ninja = (p_ptr->pclass == CLASS_NINJA) && !is_hostile(t_ptr); if (vs_ninja && !(r_ptr->flags3 & (RF3_UNDEAD | RF3_HURT_LITE)) && !(r_ptr->flags7 & RF7_DARK_MASK)) can_use_lite_area = TRUE; if (!(r_ptr->flags2 & RF2_STUPID)) { if (d_info[dungeon_type].flags1 & DF1_DARKNESS) f6 &= ~(RF6_DARKNESS); else if (vs_ninja && !can_use_lite_area) f6 &= ~(RF6_DARKNESS); } } if (in_no_magic_dungeon && !(r_ptr->flags2 & RF2_STUPID)) { f4 &= (RF4_NOMAGIC_MASK); f5 &= (RF5_NOMAGIC_MASK); f6 &= (RF6_NOMAGIC_MASK); } if (p_ptr->inside_arena || p_ptr->inside_battle) { f4 &= ~(RF4_SUMMON_MASK); f5 &= ~(RF5_SUMMON_MASK); f6 &= ~(RF6_SUMMON_MASK | RF6_TELE_LEVEL); if (m_ptr->r_idx == MON_ROLENTO) f6 &= ~(RF6_SPECIAL); } if (p_ptr->inside_battle && !one_in_(3)) { f6 &= ~(RF6_HEAL); } if (m_idx == p_ptr->riding) { f4 &= ~(RF4_RIDING_MASK); f5 &= ~(RF5_RIDING_MASK); f6 &= ~(RF6_RIDING_MASK); } if (pet) { f4 &= ~(RF4_SHRIEK); f6 &= ~(RF6_DARKNESS | RF6_TRAPS); if (!(p_ptr->pet_extra_flags & PF_TELEPORT)) { f6 &= ~(RF6_BLINK | RF6_TPORT | RF6_TELE_TO | RF6_TELE_AWAY | RF6_TELE_LEVEL); } if (!(p_ptr->pet_extra_flags & PF_ATTACK_SPELL)) { f4 &= ~(RF4_ATTACK_MASK); f5 &= ~(RF5_ATTACK_MASK); f6 &= ~(RF6_ATTACK_MASK); } if (!(p_ptr->pet_extra_flags & PF_SUMMON_SPELL)) { f4 &= ~(RF4_SUMMON_MASK); f5 &= ~(RF5_SUMMON_MASK); f6 &= ~(RF6_SUMMON_MASK); } /* Prevent collateral damage */ if (!(p_ptr->pet_extra_flags & PF_BALL_SPELL) && (m_idx != p_ptr->riding)) { if ((f4 & (RF4_BALL_MASK & ~(RF4_ROCKET))) || (f5 & RF5_BALL_MASK) || (f6 & RF6_BALL_MASK)) { int real_y = y; int real_x = x; get_project_point(m_ptr->fy, m_ptr->fx, &real_y, &real_x, 0L); if (projectable(real_y, real_x, p_ptr->y, p_ptr->x)) { int dist = distance(real_y, real_x, p_ptr->y, p_ptr->x); if (dist <= 2) { f4 &= ~(RF4_BALL_MASK & ~(RF4_ROCKET)); f5 &= ~(RF5_BALL_MASK); f6 &= ~(RF6_BALL_MASK); } else if (dist <= 4) { f4 &= ~(RF4_BIG_BALL_MASK); f5 &= ~(RF5_BIG_BALL_MASK); f6 &= ~(RF6_BIG_BALL_MASK); } } else if (f5 & RF5_BA_LITE) { if ((distance(real_y, real_x, p_ptr->y, p_ptr->x) <= 4) && los(real_y, real_x, p_ptr->y, p_ptr->x)) f5 &= ~(RF5_BA_LITE); } } if (f4 & RF4_ROCKET) { int real_y = y; int real_x = x; get_project_point(m_ptr->fy, m_ptr->fx, &real_y, &real_x, PROJECT_STOP); if (projectable(real_y, real_x, p_ptr->y, p_ptr->x) && (distance(real_y, real_x, p_ptr->y, p_ptr->x) <= 2)) f4 &= ~(RF4_ROCKET); } if (((f4 & RF4_BEAM_MASK) || (f5 & RF5_BEAM_MASK) || (f6 & RF6_BEAM_MASK)) && !direct_beam(m_ptr->fy, m_ptr->fx, t_ptr->fy, t_ptr->fx, m_ptr)) { f4 &= ~(RF4_BEAM_MASK); f5 &= ~(RF5_BEAM_MASK); f6 &= ~(RF6_BEAM_MASK); } if ((f4 & RF4_BREATH_MASK) || (f5 & RF5_BREATH_MASK) || (f6 & RF6_BREATH_MASK)) { /* Expected breath radius */ int rad = (r_ptr->flags2 & RF2_POWERFUL) ? 3 : 2; if (!breath_direct(m_ptr->fy, m_ptr->fx, t_ptr->fy, t_ptr->fx, rad, 0, TRUE)) { f4 &= ~(RF4_BREATH_MASK); f5 &= ~(RF5_BREATH_MASK); f6 &= ~(RF6_BREATH_MASK); } else if ((f4 & RF4_BR_LITE) && !breath_direct(m_ptr->fy, m_ptr->fx, t_ptr->fy, t_ptr->fx, rad, GF_LITE, TRUE)) { f4 &= ~(RF4_BR_LITE); } else if ((f4 & RF4_BR_DISI) && !breath_direct(m_ptr->fy, m_ptr->fx, t_ptr->fy, t_ptr->fx, rad, GF_DISINTEGRATE, TRUE)) { f4 &= ~(RF4_BR_DISI); } } } /* Special moves restriction */ if (f6 & RF6_SPECIAL) { if (m_ptr->r_idx == MON_ROLENTO) { if ((p_ptr->pet_extra_flags & (PF_ATTACK_SPELL | PF_SUMMON_SPELL)) != (PF_ATTACK_SPELL | PF_SUMMON_SPELL)) f6 &= ~(RF6_SPECIAL); } else if (r_ptr->d_char == 'B') { if ((p_ptr->pet_extra_flags & (PF_ATTACK_SPELL | PF_TELEPORT)) != (PF_ATTACK_SPELL | PF_TELEPORT)) f6 &= ~(RF6_SPECIAL); } else f6 &= ~(RF6_SPECIAL); } } /* Remove some spells if necessary */ if (!(r_ptr->flags2 & RF2_STUPID)) { /* Check for a clean bolt shot */ if (((f4 & RF4_BOLT_MASK) || (f5 & RF5_BOLT_MASK) || (f6 & RF6_BOLT_MASK)) && !clean_shot(m_ptr->fy, m_ptr->fx, t_ptr->fy, t_ptr->fx, pet)) { f4 &= ~(RF4_BOLT_MASK); f5 &= ~(RF5_BOLT_MASK); f6 &= ~(RF6_BOLT_MASK); } /* Check for a possible summon */ if (((f4 & RF4_SUMMON_MASK) || (f5 & RF5_SUMMON_MASK) || (f6 & RF6_SUMMON_MASK)) && !(summon_possible(t_ptr->fy, t_ptr->fx))) { /* Remove summoning spells */ f4 &= ~(RF4_SUMMON_MASK); f5 &= ~(RF5_SUMMON_MASK); f6 &= ~(RF6_SUMMON_MASK); } /* Dispel magic */ if ((f4 & RF4_DISPEL) && !dispel_check_monster(m_idx, t_idx)) { /* Remove dispel spell */ f4 &= ~(RF4_DISPEL); } /* Check for a possible raise dead */ if ((f6 & RF6_RAISE_DEAD) && !raise_possible(m_ptr)) { /* Remove raise dead spell */ f6 &= ~(RF6_RAISE_DEAD); } /* Special moves restriction */ if (f6 & RF6_SPECIAL) { if ((m_ptr->r_idx == MON_ROLENTO) && !summon_possible(t_ptr->fy, t_ptr->fx)) { f6 &= ~(RF6_SPECIAL); } } } if (r_ptr->flags2 & RF2_SMART) { /* Hack -- allow "desperate" spells */ if ((m_ptr->hp < m_ptr->maxhp / 10) && (randint0(100) < 50)) { /* Require intelligent spells */ f4 &= (RF4_INT_MASK); f5 &= (RF5_INT_MASK); f6 &= (RF6_INT_MASK); } /* Hack -- decline "teleport level" in some case */ if ((f6 & RF6_TELE_LEVEL) && TELE_LEVEL_IS_INEFF((t_idx == p_ptr->riding) ? 0 : t_idx)) { f6 &= ~(RF6_TELE_LEVEL); } } /* No spells left */ if (!f4 && !f5 && !f6) return FALSE; /* Extract the "inate" spells */ for (k = 0; k < 32; k++) { if (f4 & (1L << k)) spell[num++] = k + RF4_SPELL_START; } /* Extract the "normal" spells */ for (k = 0; k < 32; k++) { if (f5 & (1L << k)) spell[num++] = k + RF5_SPELL_START; } /* Extract the "bizarre" spells */ for (k = 0; k < 32; k++) { if (f6 & (1L << k)) spell[num++] = k + RF6_SPELL_START; } /* No spells left */ if (!num) return (FALSE); /* Stop if player is dead or gone */ if (!p_ptr->playing || p_ptr->is_dead) return (FALSE); /* Handle "leaving" */ if (p_ptr->leaving) return (FALSE); /* Get the monster name (or "it") */ monster_desc(m_name, m_ptr, 0x00); #ifndef JP /* Get the monster possessive ("his"/"her"/"its") */ monster_desc(m_poss, m_ptr, MD_PRON_VISIBLE | MD_POSSESSIVE); #endif /* Get the target's name (or "it") */ monster_desc(t_name, t_ptr, 0x00); /* Choose a spell to cast */ thrown_spell = spell[randint0(num)]; see_t = is_seen(t_ptr); see_either = (see_m || see_t); if (p_ptr->riding && (m_idx == p_ptr->riding)) disturb(1, 1); /* Check for spell failure (inate attacks never fail) */ if (!spell_is_inate(thrown_spell) && (in_no_magic_dungeon || (MON_STUNNED(m_ptr) && one_in_(2)))) { disturb(1, 1); /* Message */ if (see_m) msg_format(_("%^sは呪文を唱えようとしたが失敗した。", "%^s tries to cast a spell, but fails."), m_name); return (TRUE); } /* Hex: Anti Magic Barrier */ if (!spell_is_inate(thrown_spell) && magic_barrier(m_idx)) { if (see_m) msg_format(_("反魔法バリアが%^sの呪文をかき消した。", "Anti magic barrier cancels the spell which %^s casts."), m_name); return (TRUE); } can_remember = is_original_ap_and_seen(m_ptr); dam = monspell_to_monster(thrown_spell, y, x, m_idx, t_idx); if (dam < 0)return FALSE; if (m_ptr->ml && maneable && !world_monster && !p_ptr->blind && (p_ptr->pclass == CLASS_IMITATOR)) { if (thrown_spell != 167) /* Not RF6_SPECIAL */ { if (p_ptr->mane_num == MAX_MANE) { p_ptr->mane_num--; for (i = 0; i < p_ptr->mane_num - 1; i++) { p_ptr->mane_spell[i] = p_ptr->mane_spell[i+1]; p_ptr->mane_dam[i] = p_ptr->mane_dam[i+1]; } } p_ptr->mane_spell[p_ptr->mane_num] = thrown_spell - RF4_SPELL_START; p_ptr->mane_dam[p_ptr->mane_num] = dam; p_ptr->mane_num++; new_mane = TRUE; p_ptr->redraw |= (PR_IMITATION); } } /* Remember what the monster did, if we saw it */ if (can_remember) { /* Inate spell */ if (thrown_spell < RF4_SPELL_START + RF4_SPELL_SIZE) { r_ptr->r_flags4 |= (1L << (thrown_spell - RF4_SPELL_START)); if (r_ptr->r_cast_spell < MAX_UCHAR) r_ptr->r_cast_spell++; } /* Bolt or Ball */ else if (thrown_spell < RF5_SPELL_START + RF5_SPELL_SIZE) { r_ptr->r_flags5 |= (1L << (thrown_spell - RF5_SPELL_START)); if (r_ptr->r_cast_spell < MAX_UCHAR) r_ptr->r_cast_spell++; } /* Special spell */ else if (thrown_spell < RF6_SPELL_START + RF6_SPELL_SIZE) { r_ptr->r_flags6 |= (1L << (thrown_spell - RF6_SPELL_START)); if (r_ptr->r_cast_spell < MAX_UCHAR) r_ptr->r_cast_spell++; } } /* Always take note of monsters that kill you */ if (p_ptr->is_dead && (r_ptr->r_deaths < MAX_SHORT) && !p_ptr->inside_arena) { r_ptr->r_deaths++; /* Ignore appearance difference */ } /* A spell was cast */ return TRUE; }