/** * Standard "find me a location" function * * Obtains a legal location within the given distance of the initial * location, and with "los()" from the source to destination location. * * This function is often called from inside a loop which searches for * locations while increasing the "d" distance. * * need_los determines whether line of sight is needed */ void scatter(struct chunk *c, int *yp, int *xp, int y, int x, int d, bool need_los) { int nx, ny; /* Pick a location */ while (true) { /* Pick a new location */ ny = rand_spread(y, d); nx = rand_spread(x, d); /* Ignore annoying locations */ if (!square_in_bounds_fully(c, ny, nx)) continue; /* Ignore "excessively distant" locations */ if ((d > 1) && (distance(y, x, ny, nx) > d)) continue; /* Don't need los */ if (!need_los) break; /* Require "line of sight" if set */ if (need_los && (los(c, y, x, ny, nx))) break; } /* Save the location */ (*yp) = ny; (*xp) = nx; }
void move_enemy(ent *enemy, ent *player) { int *ey=&enemy->y; int *ex=&enemy->x; if (enemy->awake || (in_range(*ey,*ex,player->y,player->x,FOV_RADIUS) && los(*ey,*ex,player->y,player->x,WALL,NULL))) { enemy->awake=true; //sort the adjunct tiles by their distance to the player tile adj_tile[9]; int t=0; for (int y=*ey-1;y<=*ey+1;y++) for (int x=*ex-1;x<=*ex+1;x++) adj_tile[t++]=map[y][x]; qsort(adj_tile,9,sizeof(tile),compare_tiles); //move to the closest possible tile t=0; while (t<9 && !move_to(ey,ex,adj_tile[t].y-*ey,adj_tile[t].x-*ex)) { t++; } } else { //sleeping enemies move randomly move_to(ey,ex,-1+rand()%3,-1+rand()%3); } }
static void _necro_do_summon(int what, int num, bool fail) { int x = px; int y = py; if (fail) /* Failing spells should not be insta-death ... */ num = MAX(1, num/4); else num = spell_power(num); if (!fail && use_old_target && target_okay() && los(py, px, target_row, target_col) && !one_in_(3)) { y = target_row; x = target_col; } if (trump_summoning(num, !fail, y, x, 0, what, PM_ALLOW_UNIQUE)) { if (fail) { if (num == 1) msg_print("The summoned monster gets angry!"); else msg_print("The summoned monsters get angry!"); } } }
/** * Standard "find me a location" function, now with all legal outputs! * * Obtains a legal location within the given distance of the initial * location, and with "los()" from the source to destination location. * * This function is often called from inside a loop which searches for * locations while increasing the "d" distance. * * need_los determines whether line of sight is needed */ void scatter(struct chunk *c, int *yp, int *xp, int y, int x, int d, bool need_los) { int nx, ny; int tries = 0; /* Pick a location, try many times */ while (tries < 1000) { /* Pick a new location */ ny = rand_spread(y, d); nx = rand_spread(x, d); tries++; /* Ignore annoying locations */ if (!square_in_bounds_fully(c, ny, nx)) continue; /* Ignore "excessively distant" locations */ if ((d > 1) && (distance(y, x, ny, nx) > d)) continue; /* Require "line of sight" if set */ if (need_los && !los(c, y, x, ny, nx)) continue; /* Set the location and return */ (*yp) = ny; (*xp) = nx; return; } }
int main() { int n; int i; scanf("%d", &n); for (i = 1; i <= n; i++) { scanf("%d", &a[i]); } printf("%d\n", los(a, n)); return 0; }
void PositionCalculatorImpl::addMeasurementImpl( InputArray _tvec, InputArray _rvec, const Point2f _pt , double /*time*/, InputArray _cameraMatrix, InputArray _distortionMatrix ) { Mat tvec = _tvec.getMat(); Mat rvec = _rvec.getMat(); Mat camera_matrix = _cameraMatrix.getMat(); const Mat distortion_matrix = _distortionMatrix.getMat(); std::vector< Point2f > pts_in, pts_out; pts_in.push_back( _pt ); undistortPoints( pts_in, pts_out, camera_matrix, distortion_matrix, noArray(), camera_matrix ); Mat los( 3, 1,CV_64F ); los.at< double >( 0 ) = pts_out[0].x; los.at< double >( 1 ) = pts_out[0].y; los.at< double >( 2 ) = 1; if ( camera_matrix.type() != CV_64F ) camera_matrix.convertTo( camera_matrix, CV_64F ); if ( rvec.type() != CV_64F ) rvec.convertTo( rvec, CV_64F ); if ( tvec.type() != CV_64F ) tvec.convertTo( tvec, CV_64F ); los = camera_matrix.inv() * los; Mat camera_rotation; if ( rvec.rows == 3 && rvec.cols == 3 ) camera_rotation = rvec; else Rodrigues( rvec, camera_rotation ); if(tvec.rows == 1) tvec = tvec.t(); camera_rotation = camera_rotation.t(); const Mat camera_translation = ( -camera_rotation * tvec ); los = camera_rotation * los; positions.push_back( camera_translation ); Mat zero_pos( 3, 1, CV_64F ); zero_pos.setTo( 0 ); const Point2d azel = getAzEl( zero_pos, los ); angles.push_back( azel ); }
static void _jump_spell(int cmd, variant *res) { switch (cmd) { case SPELL_NAME: var_set_string(res, "Jump"); break; case SPELL_DESC: var_set_string(res, "Leap a short distance, clearing any intervening monsters or obstacles."); break; case SPELL_CAST: { int x, y; int len = 2 + p_ptr->lev/35; var_set_bool(res, FALSE); if (!tgt_pt(&x, &y, len)) return; if (distance(y, x, py, px) > len) { msg_print("You can't jump that far."); return; } if (!los(py, px, y, x)) { msg_print("You can't see that location."); return; } if (!cave_player_teleportable_bold(y, x, 0L)) { msg_print("You can't leap there!"); return; } teleport_player_to(y, x, 0L); var_set_bool(res, TRUE); break; } default: default_spell(cmd, res); break; } }
/** * Check to see if you can call the monster */ bool can_call_monster(int y, int x, monster_type *m_ptr) { int oy, ox; /* Skip dead monsters */ if (!m_ptr->race) return (FALSE); /* Only consider callable monsters */ if (!summon_specific_okay(m_ptr->race)) return (FALSE); /* Extract monster location */ oy = m_ptr->fy; ox = m_ptr->fx; /* Make sure the summoned monster is not in LOS of the summoner */ if (los(cave, y, x, oy, ox)) return (FALSE); return (TRUE); }
/** * Check to see if you can call the monster */ bool can_call_monster(int y, int x, struct monster *mon) { int oy, ox; /* Skip dead monsters */ if (!mon->race) return (false); /* Only consider callable monsters */ if (!summon_specific_okay(mon->race)) return (false); /* Extract monster location */ oy = mon->fy; ox = mon->fx; /* Make sure the summoned monster is not in LOS of the summoner */ if (los(cave, y, x, oy, ox)) return (false); return (true); }
unsigned int CMob::think() { int losx = x; int losy = y; if(los(losx, losy, PC->x, PC->y, get_fov_rad())) { last_seen_x = PC->x; last_seen_y = PC->y; chasing = true; } if (chasing) { if(tryattack(last_seen_x - x, last_seen_y - y)) return get_attack_time(); if(step_to(last_seen_x, last_seen_y)) return get_move_time(); } return get_move_time(); //idle }
void CLOSTexture::RecomputeTexture(int unit) { // If the map was resized, delete and regenerate the texture if (m_Texture) { CmpPtr<ICmpTerrain> cmpTerrain(m_Simulation, SYSTEM_ENTITY); if (cmpTerrain && m_MapSize != (ssize_t)cmpTerrain->GetVerticesPerSide()) DeleteTexture(); } bool recreated = false; if (!m_Texture) { ConstructTexture(unit); recreated = true; } PROFILE("recompute LOS texture"); std::vector<u8> losData; losData.resize(GetBitmapSize(m_MapSize, m_MapSize)); CmpPtr<ICmpRangeManager> cmpRangeManager(m_Simulation, SYSTEM_ENTITY); if (!cmpRangeManager) return; ICmpRangeManager::CLosQuerier los(cmpRangeManager->GetLosQuerier(g_Game->GetPlayerID())); GenerateBitmap(los, &losData[0], m_MapSize, m_MapSize); if (CRenderer::IsInitialised() && g_Renderer.m_Options.m_SmoothLOS && recreated) { g_Renderer.BindTexture(unit, m_TextureSmooth1); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_MapSize + g_BlurSize - 1, m_MapSize + g_BlurSize - 1, GL_ALPHA, GL_UNSIGNED_BYTE, &losData[0]); g_Renderer.BindTexture(unit, m_TextureSmooth2); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_MapSize + g_BlurSize - 1, m_MapSize + g_BlurSize - 1, GL_ALPHA, GL_UNSIGNED_BYTE, &losData[0]); } g_Renderer.BindTexture(unit, m_Texture); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_MapSize + g_BlurSize - 1, m_MapSize + g_BlurSize - 1, GL_ALPHA, GL_UNSIGNED_BYTE, &losData[0]); }
/* * Shatter the player's wielded weapon. */ void shatter_weapon(int silnum) { int i; object_type *w_ptr = &inventory[INVEN_WIELD]; char w_name[80]; p_ptr->crown_shatter = TRUE; /* Get the basic name of the object */ object_desc(w_name, sizeof(w_name), w_ptr, FALSE, 0); if (silnum == 2) msg_print("You strive to free a second Silmaril, but it is not fated to be."); else msg_print("You strive to free a third Silmaril, but it is not fated to be."); msg_format("As you strike the crown, your %s shatters into innumerable pieces.", w_name); // make more noise stealth_score -= 5; inven_item_increase(INVEN_WIELD, -1); inven_item_optimize(INVEN_WIELD); /* Process monsters */ for (i = 1; i < mon_max; i++) { monster_type *m_ptr = &mon_list[i]; /* If Morgoth, then anger him */ if (m_ptr->r_idx == R_IDX_MORGOTH) { if ((m_ptr->cdis <= 5) && los(p_ptr->py, p_ptr->px, m_ptr->fy, m_ptr->fx)) { msg_print("A shard strikes Morgoth upon his cheek."); set_alertness(m_ptr, ALERTNESS_VERY_ALERT); } } } }
/** * Determine if there is a space near the selected spot in which * a summoned creature can appear */ static bool summon_possible(int y1, int x1) { int y, x; /* Start at the location, and check 2 grids in each dir */ for (y = y1 - 2; y <= y1 + 2; y++) { for (x = x1 - 2; x <= x1 + 2; x++) { /* Ignore illegal locations */ if (!square_in_bounds(cave, y, x)) continue; /* Only check a circular area */ if (distance(y1, x1, y, x) > 2) continue; /* Hack: no summon on glyph of warding */ if (square_iswarded(cave, y, x)) continue; /* If it's empty floor grid in line of sight, we're good */ if (square_isempty(cave, y, x) && los(cave, y1, x1, y, x)) return (true); } } return false; }
/*! * @brief モンスターにとって死者復活を行うべき状態かどうかを返す / * Determine if there is a space near the player in which a summoned creature can appear * @param m_ptr 判定を行いたいモンスターの構造体参照ポインタ * @return 死者復活が有効な状態ならばTRUEを返す。 */ bool raise_possible(monster_type *m_ptr) { int xx, yy; int y = m_ptr->fy; int x = m_ptr->fx; s16b this_o_idx, next_o_idx = 0; cave_type *c_ptr; for (xx = x - 5; xx <= x + 5; xx++) { for (yy = y - 5; yy <= y + 5; yy++) { if (distance(y, x, yy, xx) > 5) continue; if (!los(y, x, yy, xx)) continue; if (!projectable(y, x, yy, xx)) continue; c_ptr = &cave[yy][xx]; /* Scan the pile of objects */ for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) { /* Acquire object */ object_type *o_ptr = &o_list[this_o_idx]; /* Acquire next object */ next_o_idx = o_ptr->next_o_idx; /* Known to be worthless? */ if (o_ptr->tval == TV_CORPSE) { if (!monster_has_hostile_align(m_ptr, 0, 0, &r_info[o_ptr->pval])) return TRUE; } } } } return FALSE; }
static void dig_path(int y0, int x0, int y1, int x1) { los(y0,x0,y1,x1,(chtype)NULL,&dig_tile); }
/** * Find a grid near the given one for an object to fall on * * We check several locations to see if we can find a location at which * the object can combine, stack, or be placed. Artifacts will try very * hard to be placed, including "teleporting" to a useful grid if needed. * * If no appropriate grid is found, the given grid is unchanged */ static void drop_find_grid(struct object *drop, int *y, int *x) { int best_score = -1; int best_y = *y; int best_x = *x; int i, dy, dx; struct object *obj; /* Scan local grids */ for (dy = -3; dy <= 3; dy++) { for (dx = -3; dx <= 3; dx++) { bool combine = false; int dist = (dy * dy) + (dx * dx); int ty = *y + dy; int tx = *x + dx; int num_shown = 0; int num_ignored = 0; int score; /* Lots of reasons to say no */ if ((dist > 10) || !square_in_bounds_fully(cave, ty, tx) || !los(cave, *y, *x, ty, tx) || !square_isfloor(cave, ty, tx) || square_isplayertrap(cave, ty, tx) || square_iswarded(cave, ty, tx)) continue; /* Analyse the grid for carrying the new object */ for (obj = square_object(cave, ty, tx); obj; obj = obj->next) { /* Check for possible combination */ if (object_similar(obj, drop, OSTACK_FLOOR)) combine = true; /* Count objects */ if (!ignore_item_ok(obj)) num_shown++; else num_ignored++; } if (!combine) num_shown++; /* Disallow if the stack size is too big */ if ((OPT(player, birth_stacking) && (num_shown > 1)) || ((num_shown + num_ignored) > z_info->floor_size && !floor_get_oldest_ignored(ty, tx))) continue; /* Score the location based on how close and how full the grid is */ score = 1000 - (dist + num_shown * 5); if ((score < best_score) || ((score == best_score) && one_in_(2))) continue; best_score = score; best_y = ty; best_x = tx; } } /* Return if we have a score, otherwise fail or try harder for artifacts */ if (best_score >= 0) { *y = best_y; *x = best_x; return; } else if (!drop->artifact) { return; } for (i = 0; i < 2000; i++) { /* Start bouncing from grid to grid, stopping if we find an empty one */ if (i < 1000) { best_y = rand_spread(best_y, 1); best_x = rand_spread(best_x, 1); } else { /* Now go to purely random locations */ best_y = randint0(cave->height); best_x = randint0(cave->width); } if (square_canputitem(cave, best_y, best_x)) { *y = best_y; *x = best_x; return; } } }
/** * Let an object fall to the ground at or near a location. * * The initial location is assumed to be "square_in_bounds_fully(cave, )". * * This function takes a parameter "chance". This is the percentage * chance that the item will "disappear" instead of drop. If the object * has been thrown, then this is the chance of disappearance on contact. * * This function will produce a description of a drop event under the player * when "verbose" is true. * * We check several locations to see if we can find a location at which * the object can combine, stack, or be placed. Artifacts will try very * hard to be placed, including "teleporting" to a useful grid if needed. * * Objects which fail to be carried by the floor are deleted. This function * attempts to add successfully dropped objects to, and to remove failures * from, the object list (as dropped items may or may not be already listed). */ void drop_near(struct chunk *c, struct object *dropped, int chance, int y, int x, bool verbose) { int i, k, n, d, s; int bs, bn; int by, bx; int dy, dx; int ty, tx; struct object *obj; char o_name[80]; bool flag = false; /* Only called in the current level */ assert(c == cave); /* Describe object */ object_desc(o_name, sizeof(o_name), dropped, ODESC_BASE); /* Handle normal "breakage" */ if (!dropped->artifact && (randint0(100) < chance)) { /* Message */ msg("The %s %s.", o_name, VERB_AGREEMENT(dropped->number, "breaks", "break")); /* Failure */ if (dropped->known) { delist_object(cave_k, dropped->known); object_delete(&dropped->known); } delist_object(c, dropped); object_delete(&dropped); return; } /* Score */ bs = -1; /* Picker */ bn = 0; /* Default */ by = y; bx = x; /* Scan local grids */ for (dy = -3; dy <= 3; dy++) { for (dx = -3; dx <= 3; dx++) { bool comb = false; /* Calculate actual distance */ d = (dy * dy) + (dx * dx); /* Ignore distant grids */ if (d > 10) continue; /* Location */ ty = y + dy; tx = x + dx; /* Skip illegal grids */ if (!square_in_bounds_fully(c, ty, tx)) continue; /* Require line of sight */ if (!los(c, y, x, ty, tx)) continue; /* Require floor space */ if (!square_isfloor(c, ty, tx)) continue; /* Require no trap or rune */ if (square_isplayertrap(c, ty, tx) || square_iswarded(c, ty, tx)) continue; /* No objects */ k = 0; n = 0; /* Scan objects in that grid */ for (obj = square_object(c, ty, tx); obj; obj = obj->next) { /* Check for possible combination */ if (object_similar(obj, dropped, OSTACK_FLOOR)) comb = true; /* Count objects */ if (!ignore_item_ok(obj)) k++; else n++; } /* Add new object */ if (!comb) k++; /* Option -- disallow stacking */ if (OPT(birth_no_stacking) && (k > 1)) continue; /* Paranoia? */ if ((k + n) > z_info->floor_size && !floor_get_oldest_ignored(ty, tx)) continue; /* Calculate score */ s = 1000 - (d + k * 5); /* Skip bad values */ if (s < bs) continue; /* New best value */ if (s > bs) bn = 0; /* Apply the randomizer to equivalent values */ if ((++bn >= 2) && (randint0(bn) != 0)) continue; /* Keep score */ bs = s; /* Track it */ by = ty; bx = tx; /* Okay */ flag = true; } } /* Handle lack of space */ if (!flag && !dropped->artifact) { /* Message */ msg("The %s %s.", o_name, VERB_AGREEMENT(dropped->number, "disappears", "disappear")); /* Debug */ if (player->wizard) msg("Breakage (no floor space)."); /* Failure */ if (dropped->known) { delist_object(cave_k, dropped->known); object_delete(&dropped->known); } delist_object(c, dropped); object_delete(&dropped); return; } /* Find a grid */ for (i = 0; !flag; i++) { /* Bounce around */ if (i < 1000) { ty = rand_spread(by, 1); tx = rand_spread(bx, 1); } else { /* Random locations */ ty = randint0(c->height); tx = randint0(c->width); } /* Require floor space */ if (!square_canputitem(c, ty, tx)) continue; /* Bounce to that location */ by = ty; bx = tx; /* Okay */ flag = true; } /* Give it to the floor */ if (!floor_carry(c, by, bx, dropped, false)) { /* Message */ msg("The %s %s.", o_name, VERB_AGREEMENT(dropped->number, "disappears", "disappear")); /* Debug */ if (player->wizard) msg("Breakage (too many objects)."); if (dropped->artifact) dropped->artifact->created = false; /* Failure */ if (dropped->known) { delist_object(cave_k, dropped->known); object_delete(&dropped->known); } delist_object(c, dropped); object_delete(&dropped); return; } /* Sound */ sound(MSG_DROP); /* Message when an object falls under the player */ if (verbose && (c->squares[by][bx].mon < 0)) /* Check the item still exists and isn't ignored */ if (c->objects[dropped->oidx] && !ignore_item_ok(dropped)) msg("You feel something roll beneath your feet."); }
void dig_path(int y0, int x0, int y1, int x1) { los(y0,x0,y1,x1,(char)NULL,&dig_tile); }
/*! * @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); } } }
//radial field of view void fov(int y, int x, int radius) { for (int yy=max(y-radius,0); yy<=min(y+radius,Y_-1); yy++) for (int xx=max(x-radius,0); xx<=min(x+radius,X_-1); xx++) if (in_range(y,x,yy,xx,radius) && los(y,x,yy,xx,WALL,NULL)) view_m[yy][xx]=IN_SIGHT; }
_rush_result _rush_attack(int rng, _rush_type type) { _rush_result result = _rush_cancelled; int tx, ty; int tm_idx = 0; u16b path_g[32]; int path_n, i; bool moved = FALSE; int flg = 0; int dis = 0; if (type == _rush_normal) flg = PROJECT_STOP | PROJECT_KILL; else if (type == _rush_acrobatic) flg = PROJECT_THRU | PROJECT_KILL; else flg = PROJECT_DISI | PROJECT_THRU; if (!p_ptr->duelist_target_idx) { msg_print("You need to select a foe first (Mark Target)."); return result; } tm_idx = p_ptr->duelist_target_idx; tx = m_list[tm_idx].fx; ty = m_list[tm_idx].fy; dis = distance(ty, tx, py, px); /* Foe must be visible. For all charges except the phase charge, the foe must also be in your line of sight */ if (!m_list[p_ptr->duelist_target_idx].ml || (type != _rush_phase && !los(ty, tx, py, px))) { msg_format("%^s is not in your line of sight.", duelist_current_challenge()); return result; } if (dis > rng) { msg_format("Your foe is out of range (%d vs %d).", dis, rng); if (!get_check("Charge anyway? ")) return result; } project_length = rng; path_n = project_path(path_g, project_length, py, px, ty, tx, flg); project_length = 0; if (!path_n) return result; result = _rush_failed; /* Use ty and tx as to-move point */ ty = py; tx = px; /* Scrolling the cave would invalidate our path! */ if (!dun_level && !p_ptr->wild_mode && !p_ptr->inside_arena && !p_ptr->inside_battle) wilderness_scroll_lock = TRUE; /* Project along the path */ for (i = 0; i < path_n; i++) { monster_type *m_ptr; cave_type *c_ptr; bool can_enter = FALSE; bool old_pass_wall = p_ptr->pass_wall; int ny = GRID_Y(path_g[i]); int nx = GRID_X(path_g[i]); c_ptr = &cave[ny][nx]; switch (type) { case _rush_normal: can_enter = cave_empty_bold(ny, nx) && player_can_enter(c_ptr->feat, 0); break; case _rush_acrobatic: can_enter = !c_ptr->m_idx && player_can_enter(c_ptr->feat, 0); break; case _rush_phase: p_ptr->pass_wall = TRUE; can_enter = !c_ptr->m_idx && player_can_enter(c_ptr->feat, 0); p_ptr->pass_wall = old_pass_wall; break; } if (can_enter) { ty = ny; tx = nx; continue; } if (!c_ptr->m_idx) { msg_print("Failed!"); break; } /* Move player before updating the monster */ if (!player_bold(ty, tx)) move_player_effect(ty, tx, MPE_FORGET_FLOW | MPE_HANDLE_STUFF | MPE_DONT_PICKUP); moved = TRUE; /* Update the monster */ update_mon(c_ptr->m_idx, TRUE); /* Found a monster */ m_ptr = &m_list[c_ptr->m_idx]; /* But it is not the monster we seek! */ if (tm_idx != c_ptr->m_idx) { /* Acrobatic Charge attempts to displace monsters on route */ if (type == _rush_acrobatic) { /* Swap position of player and monster */ set_monster_csleep(c_ptr->m_idx, 0); move_player_effect(ny, nx, MPE_FORGET_FLOW | MPE_HANDLE_STUFF | MPE_DONT_PICKUP); ty = ny; tx = nx; continue; } /* Normal Charge just attacks first monster on route */ else msg_format("There is %s in the way!", m_ptr->ml ? (tm_idx ? "another monster" : "a monster") : "someone"); } /* Attack the monster */ if (tm_idx == p_ptr->duelist_target_idx) result = _rush_succeeded; py_attack(ny, nx, 0); break; } if (!moved && !player_bold(ty, tx)) move_player_effect(ty, tx, MPE_FORGET_FLOW | MPE_HANDLE_STUFF | MPE_DONT_PICKUP); if (!dun_level && !p_ptr->wild_mode && !p_ptr->inside_arena && !p_ptr->inside_battle) { wilderness_scroll_lock = FALSE; wilderness_move_player(px, py); } return result; }
/*! * @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; }
/* * Let an object fall to the ground at or near a location. * * The initial location is assumed to be "in_bounds()". * * This function takes a parameter "chance". This is the percentage * chance that the item will "disappear" instead of drop. If the object * has been thrown, then this is the chance of disappearance on contact. * * Hack -- this function uses "chance" to determine if it should produce * some form of "description" of the drop event (under the player). * * We check several locations to see if we can find a location at which * the object can combine, stack, or be placed. Artifacts will try very * hard to be placed, including "teleporting" to a useful grid if needed. */ s16b drop_near(object_type *j_ptr, s32b chance, s32b y, s32b x) { s32b i, k, d, s; s32b bs, bn; s32b by, bx; s32b dy, dx; s32b ty, tx; s16b o_idx = 0; cave_type *c_ptr; char o_name[80]; bool flag = FALSE; bool plural = FALSE; /* Extract plural */ if (j_ptr->number != 1) plural = TRUE; /* Describe object */ object_desc(o_name, j_ptr, FALSE, 0); /* Handle normal "breakage" */ if (!(j_ptr->art_name || artifact_p(j_ptr)) && (rand_int(100) < chance)) { /* Message */ msg_format("The %s disappear%s.", o_name, (plural ? "" : "s")); /* Debug */ if (wizard) msg_print("(breakage)"); delete_object(j_ptr); /* Failure */ return (0); } /* Score */ bs = -1; /* Picker */ bn = 0; /* Default */ by = y; bx = x; /* Scan local grids */ for (dy = -3; dy <= 3; dy++) { /* Scan local grids */ for (dx = -3; dx <= 3; dx++) { bool comb = FALSE; /* Calculate actual distance */ d = (dy * dy) + (dx * dx); /* Ignore distant grids */ if (d > 10) continue; /* Location */ ty = y + dy; tx = x + dx; /* Skip illegal grids */ if (!in_bounds(ty, tx)) continue; /* Require line of sight */ if (!los(y, x, ty, tx)) continue; /* Obtain grid */ c_ptr = &cave[ty][tx]; /* Require floor space (or shallow terrain) -KMW- */ if (!has_flag(&f_info[c_ptr->feat], FLAG_FLOOR)) continue; /* No traps */ if (flag_used(&c_ptr->activations)) continue; /* No objects */ k = 0; /* Scan objects in that grid */ for_inventory_slot(&c_ptr->inventory, o_ptr); { /* Check for possible combination */ if (object_similar(o_ptr, j_ptr)) comb = TRUE; /* Count objects */ k++; } end_inventory_slot(); /* Add new object */ if (!comb) k++; /* Paranoia */ if (k >= inventory_limit_inven(&c_ptr->inventory)) continue; /* Calculate score */ s = 1000 - (d + k * 5); /* Skip bad values */ if (s < bs) continue; /* New best value */ if (s > bs) bn = 0; /* Apply the randomizer to equivalent values */ if ((++bn >= 2) && (rand_int(bn) != 0)) continue; /* Keep score */ bs = s; /* Track it */ by = ty; bx = tx; /* Okay */ flag = TRUE; } } /* Handle lack of space */ if (!flag && !(artifact_p(j_ptr) || j_ptr->art_name)) { /* Message */ msg_format("The %s disappear%s.", o_name, (plural ? "" : "s")); /* Debug */ if (wizard) msg_print("(no floor space)"); delete_object(j_ptr); /* Failure */ return (0); } /* Find a grid */ for (i = 0; !flag; i++) { /* Bounce around */ if (i < 1000) { ty = rand_spread(by, 1); tx = rand_spread(bx, 1); } /* Random locations */ else { ty = rand_int(cur_hgt); tx = rand_int(cur_wid); } /* Grid */ c_ptr = &cave[ty][tx]; /* Require floor space */ if (!has_flag(&f_info[c_ptr->feat], FLAG_FLOOR) || has_flag(&f_info[c_ptr->feat], FLAG_NO_WALK)) continue; /* Bounce to that location */ by = ty; bx = tx; /* Require floor space */ if (!cave_clean_bold(by, bx)) continue; /* Okay */ flag = TRUE; } j_ptr->iy = by; j_ptr->ix = bx; j_ptr->held_m_idx = 0; /* Grid */ c_ptr = &cave[by][bx]; /* Carry */ o_idx = inven_carry_inven(&c_ptr->inventory, j_ptr, FALSE); /* * j_ptr might have been merged into an existing object and then * deleted, so re-get the object. */ j_ptr = get_object(item_slot_to_item(o_idx)); /* Note the spot */ note_spot(by, bx); /* Draw the spot */ lite_spot(by, bx); /* Mega-Hack -- no message if "dropped" by player */ /* Message when an object falls under the player */ if (chance && (by == p_ptr->py) && (bx == p_ptr->px)) { msg_print("You feel something roll beneath your feet."); /* Sound */ sound(SOUND_DROP); } process_hooks(HOOK_DROPPED_NEAR, "(O,b,d,d,d,d)", j_ptr, chance, y, x, by, bx); /* XXX XXX XXX */ /* Result */ return (o_idx); }
int main() { printf("podaj liczbe z zakresu 1-1000: \n"); los(); return 0; }
/* * Apply a "project()" directly to all monsters in view of a certain spot. * * Note that affected monsters are NOT auto-tracked by this usage. * * We are able to check LOS from either the character (in which case we * use line of fire for speed and accuracy), or from any given grid. * * To avoid misbehavior when monster deaths have side-effects, * this is done in two passes. -- JDL */ bool project_los(int y0, int x0, int dam, int typ) { int i, d, x, y; u32b flg = PROJECT_JUMP | PROJECT_KILL | PROJECT_HIDE; bool obvious = FALSE; int who; /* Determine whether we are using LOF or LOS */ bool line_of_fire = FALSE; if ((y0 == p_ptr->py) && (x0 == p_ptr->px)) { line_of_fire = TRUE; who = SOURCE_PLAYER; } else if (cave_monster_trap_bold(y0, x0)) who = SOURCE_TRAP; else if (cave_player_trap_bold(y0, x0)) who = SOURCE_EFFECT; else who = SOURCE_OTHER; /* Mark monsters in LOS */ for (i = 1; i < mon_max; i++) { monster_type *m_ptr = &mon_list[i]; /* Paranoia -- Skip dead monsters */ if (!m_ptr->r_idx) continue; /* Location */ y = m_ptr->fy; x = m_ptr->fx; /* Apply character-centered test */ if (line_of_fire) { /* Require line of fire */ if (!player_can_fire_bold(y, x)) continue; } /* Apply generic grid test */ else { /* Get distance between source and monster */ d = distance(y0, x0, y, x); /* LOS extends only to max sight range */ if (d > MAX_RANGE) continue; /* Check LOS if not at grid or adjacent */ if (d > 1) { /* Ignore if not in LOS */ if (!los(y0, x0, y, x)) continue; } } /* Mark the monster */ m_ptr->mflag |= (MFLAG_TEMP); } /* Affect all (nearby) monsters */ for (i = 1; i < mon_max; i++) { monster_type *m_ptr = &mon_list[i]; /* Skip unmarked monsters */ if (!(m_ptr->mflag & (MFLAG_TEMP))) continue; /* Remove mark */ m_ptr->mflag &= ~(MFLAG_TEMP); /* Jump directly to the monster */ if (project_m(who, m_ptr->fy, m_ptr->fx, dam, typ, flg)) { obvious = TRUE; } } /* Result */ return (obvious); }
/*! * @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; }