X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=src%2Fcmd2.c;h=1d24fc5eb2212515eb85fda79f6783067f41eb6f;hb=ca8e0d6d1d0fea1f6e09a899e016561b6bbd079e;hp=22b027c9ed5a87faa5714860eef1d8d389de6b8e;hpb=2dabd068522a6433630194cea47785e2d680c294;p=hengband%2Fhengband.git diff --git a/src/cmd2.c b/src/cmd2.c index 22b027c9e..1d24fc5eb 100644 --- a/src/cmd2.c +++ b/src/cmd2.c @@ -12,6 +12,34 @@ #include "angband.h" +bool confirm_leave_level(bool down_stair) +{ + quest_type *q_ptr = &quest[p_ptr->inside_quest]; + + /* Confirm leaving from once only quest */ + if (confirm_quest && p_ptr->inside_quest && + (q_ptr->type == QUEST_TYPE_RANDOM || + (q_ptr->flags & QUEST_FLAG_ONCE && + q_ptr->status != QUEST_STATUS_COMPLETED) || + (q_ptr->flags & QUEST_FLAG_TOWER && + ((q_ptr->status != QUEST_STATUS_STAGE_COMPLETED) || + (down_stair && (quest[QUEST_TOWER1].status != QUEST_STATUS_COMPLETED)))))) + { +#ifdef JP + msg_print("¤³¤Î³¬¤ò°ìÅÙµî¤ë¤ÈÆóÅÙ¤ÈÌá¤Ã¤ÆÍè¤é¤ì¤Þ¤»¤ó¡£"); + if (get_check("ËÜÅö¤Ë¤³¤Î³¬¤òµî¤ê¤Þ¤¹¤«¡©")) return TRUE; +#else + msg_print("You can't come back here once you leave this floor."); + if (get_check("Really leave this floor? ")) return TRUE; +#endif + } + else + { + return TRUE; + } + return FALSE; +} + /* * Go up one level @@ -46,6 +74,10 @@ void do_cmd_go_up(void) /* Quest up stairs */ if (have_flag(f_ptr->flags, FF_QUEST)) { + /* Cancel the command */ + if (!confirm_leave_level(FALSE)) return; + + /* Success */ #ifdef JP if ((p_ptr->pseikaku == SEIKAKU_COMBAT) || (inventory[INVEN_BOW].name1 == ART_CRIMSON)) @@ -63,6 +95,11 @@ void do_cmd_go_up(void) /* Activate the quest */ if (!quest[p_ptr->inside_quest].status) { + if (quest[p_ptr->inside_quest].type != QUEST_TYPE_RANDOM) + { + init_flags = INIT_ASSIGN; + process_dungeon_file("q_info.txt", 0, 0, 0, 0); + } quest[p_ptr->inside_quest].status = QUEST_STATUS_TAKEN; } @@ -77,6 +114,9 @@ void do_cmd_go_up(void) p_ptr->oldpx = 0; p_ptr->oldpy = 0; + + /* Hack -- take a turn */ + energy_use = 100; /* End the command */ return; @@ -88,26 +128,7 @@ void do_cmd_go_up(void) } else { - quest_type *q_ptr = &quest[p_ptr->inside_quest]; - - /* Confirm leaving from once only quest */ - if (confirm_quest && p_ptr->inside_quest && - (q_ptr->type == QUEST_TYPE_RANDOM || - (q_ptr->flags & QUEST_FLAG_ONCE && - q_ptr->status != QUEST_STATUS_COMPLETED))) - { -#ifdef JP - msg_print("¤³¤Î³¬¤ò°ìÅÙµî¤ë¤ÈÆóÅÙ¤ÈÌá¤Ã¤ÆÍè¤é¤ì¤Þ¤»¤ó¡£"); - if (get_check("ËÜÅö¤Ë¤³¤Î³¬¤òµî¤ê¤Þ¤¹¤«¡©")) go_up = TRUE; -#else - msg_print("You can't come back here once you leave this floor."); - if (get_check("Really leave this floor? ")) go_up = TRUE; -#endif - } - else - { - go_up = TRUE; - } + go_up = confirm_leave_level(FALSE); } /* Cancel the command */ @@ -228,6 +249,9 @@ void do_cmd_go_down(void) /* Quest down stairs */ else if (have_flag(f_ptr->flags, FF_QUEST)) { + /* Confirm Leaving */ + if(!confirm_leave_level(TRUE)) return; + #ifdef JP if ((p_ptr->pseikaku == SEIKAKU_COMBAT) || (inventory[INVEN_BOW].name1 == ART_CRIMSON)) msg_print("¤Ê¤ó¤À¤³¤Î³¬Ãʤϡª"); @@ -237,14 +261,19 @@ void do_cmd_go_down(void) msg_print("You enter the down staircase."); #endif - leave_quest_check(); + leave_tower_check(); p_ptr->inside_quest = c_ptr->special; /* Activate the quest */ if (!quest[p_ptr->inside_quest].status) { + if (quest[p_ptr->inside_quest].type != QUEST_TYPE_RANDOM) + { + init_flags = INIT_ASSIGN; + process_dungeon_file("q_info.txt", 0, 0, 0, 0); + } quest[p_ptr->inside_quest].status = QUEST_STATUS_TAKEN; } @@ -259,6 +288,10 @@ void do_cmd_go_down(void) p_ptr->oldpx = 0; p_ptr->oldpy = 0; + + + /* Hack -- take a turn */ + energy_use = 100; } else @@ -415,7 +448,7 @@ void do_cmd_search(void) /* * Determine if a grid contains a chest */ -static s16b chest_check(int y, int x) +static s16b chest_check(int y, int x, bool trapped) { cave_type *c_ptr = &cave[y][x]; @@ -436,8 +469,13 @@ static s16b chest_check(int y, int x) /* Skip unknown chests XXX XXX */ /* if (!(o_ptr->marked & OM_FOUND)) continue; */ - /* Check for chest */ - if (o_ptr->tval == TV_CHEST) return (this_o_idx); + /* Check for non empty chest */ + if ((o_ptr->tval == TV_CHEST) && + (((!trapped) && (o_ptr->pval)) || /* non empty */ + ((trapped) && (o_ptr->pval > 0)))) /* trapped only */ + { + return (this_o_idx); + } } /* No chest */ @@ -1009,7 +1047,7 @@ static int count_chests(int *y, int *x, bool trapped) int xx = px + ddx_ddd[d]; /* No (visible) chest is there */ - if ((o_idx = chest_check(yy, xx)) == 0) continue; + if ((o_idx = chest_check(yy, xx, FALSE)) == 0) continue; /* Grab the object */ o_ptr = &o_list[o_idx]; @@ -1238,7 +1276,7 @@ void do_cmd_open(void) feat = get_feat_mimic(c_ptr); /* Check for chest */ - o_idx = chest_check(y, x); + o_idx = chest_check(y, x, FALSE); /* Nothing useful */ if (!have_flag(f_info[feat].flags, FF_OPEN) && !o_idx) @@ -2175,7 +2213,7 @@ void do_cmd_disarm(void) feat = get_feat_mimic(c_ptr); /* Check for chests */ - o_idx = chest_check(y, x); + o_idx = chest_check(y, x, TRUE); /* Disarm a trap */ if (!is_trap(feat) && !o_idx) @@ -2834,6 +2872,9 @@ void do_cmd_rest(void) stop_singing(); } + /* Hex */ + if (hex_spelling_any()) stop_hex_spell_all(); + /* Prompt for time if needed */ if (command_arg <= 0) { @@ -2923,6 +2964,18 @@ static int breakage_chance(object_type *o_ptr) { int archer_bonus = (p_ptr->pclass == CLASS_ARCHER ? (p_ptr->lev-1)/7 + 4: 0); + /* Examine the snipe type */ + if (snipe_type) + { + if (snipe_type == SP_KILL_WALL) return (100); + if (snipe_type == SP_EXPLODE) return (100); + if (snipe_type == SP_PIERCE) return (100); + if (snipe_type == SP_FINAL) return (100); + if (snipe_type == SP_NEEDLE) return (100); + if (snipe_type == SP_EVILNESS) return (40); + if (snipe_type == SP_HOLYNESS) return (40); + } + /* Examine the item type */ switch (o_ptr->tval) { @@ -3316,6 +3369,9 @@ static s16b tot_dam_aux_shot(object_type *o_ptr, int tdam, monster_type *m_ptr) } } + /* Sniper */ + if (snipe_type) mult = tot_dam_aux_snipe(mult, m_ptr); + /* Return the total damage */ return (tdam * mult / 10); } @@ -3352,8 +3408,8 @@ static s16b tot_dam_aux_shot(object_type *o_ptr, int tdam, monster_type *m_ptr) void do_cmd_fire_aux(int item, object_type *j_ptr) { int dir; - int j, y, x, ny, nx, ty, tx, prev_y, prev_x; - int tdam, tdis, thits, tmul; + int i, j, y, x, ny, nx, ty, tx, prev_y, prev_x; + int tdam_base, tdis, thits, tmul; int bonus, chance; int cur_dis, visible; @@ -3366,6 +3422,8 @@ void do_cmd_fire_aux(int item, object_type *j_ptr) char o_name[MAX_NLEN]; + u16b path_g[512]; /* For calcuration of path length */ + int msec = delay_factor * delay_factor * delay_factor; /* STICK TO */ @@ -3381,10 +3439,12 @@ void do_cmd_fire_aux(int item, object_type *j_ptr) o_ptr = &o_list[0 - item]; } + /* Sniper - Cannot shot a single arrow twice */ + if ((snipe_type == SP_DOUBLE) && (o_ptr->number < 2)) snipe_type = SP_NONE; + /* Describe the object */ object_desc(o_name, o_ptr, OD_OMIT_PREFIX); - /* Use the proper number of shots */ thits = p_ptr->num_fire; @@ -3392,7 +3452,7 @@ void do_cmd_fire_aux(int item, object_type *j_ptr) tdis = 10; /* Base damage from thrown object plus launcher bonus */ - tdam = damroll(o_ptr->dd, o_ptr->ds) + o_ptr->to_d + j_ptr->to_d; + tdam_base = damroll(o_ptr->dd, o_ptr->ds) + o_ptr->to_d + j_ptr->to_d; /* Actually "fire" the object */ bonus = (p_ptr->to_h_b + o_ptr->to_h + j_ptr->to_h); @@ -3410,13 +3470,18 @@ void do_cmd_fire_aux(int item, object_type *j_ptr) tmul = tmul * (100 + (int)(adj_str_td[p_ptr->stat_ind[A_STR]]) - 128); /* Boost the damage */ - tdam *= tmul; - tdam /= 100; + tdam_base *= tmul; + tdam_base /= 100; /* Base range */ - tdis = 10 + tmul/40; + tdis = 13 + tmul/80; if ((j_ptr->sval == SV_LIGHT_XBOW) || (j_ptr->sval == SV_HEAVY_XBOW)) - tdis -= 5; + { + if (p_ptr->concent) + tdis -= (5 - (p_ptr->concent + 1) / 2); + else + tdis -= 5; + } project_length = tdis + 1; @@ -3425,15 +3490,13 @@ void do_cmd_fire_aux(int item, object_type *j_ptr) { energy_use = 0; + if (snipe_type == SP_AWAY) snipe_type = SP_NONE; + /* need not to reset project_length (already did)*/ return; } - /* Start at the player */ - y = py; - x = px; - /* Predict the "target" location */ tx = px + 99 * ddx[dir]; ty = py + 99 * ddy[dir]; @@ -3445,6 +3508,9 @@ void do_cmd_fire_aux(int item, object_type *j_ptr) ty = target_row; } + /* Get projection path length */ + tdis = project_path(path_g, project_length, py, px, ty, tx, PROJECT_PATH|PROJECT_THRU) - 1; + project_length = 0; /* reset to default */ /* Don't shoot at my feet */ @@ -3458,6 +3524,21 @@ void do_cmd_fire_aux(int item, object_type *j_ptr) } + /* Take a (partial) turn */ + energy_use = (energy_use / thits); + is_fired = TRUE; + + /* Sniper - Difficult to shot twice at 1 turn */ + if (snipe_type == SP_DOUBLE) p_ptr->concent = (p_ptr->concent + 1) / 2; + + /* Sniper - Repeat shooting when double shots */ + for (i = 0; i < ((snipe_type == SP_DOUBLE) ? 2 : 1); i++) + { + + /* Start at the player */ + y = py; + x = px; + /* Get local object */ q_ptr = &forge; @@ -3482,15 +3563,9 @@ void do_cmd_fire_aux(int item, object_type *j_ptr) floor_item_optimize(0 - item); } - /* Sound */ sound(SOUND_SHOOT); - - /* Take a (partial) turn */ - energy_use = (energy_use / thits); - - /* Hack -- Handle stuff */ handle_stuff(); @@ -3498,9 +3573,14 @@ void do_cmd_fire_aux(int item, object_type *j_ptr) prev_y = y; prev_x = x; + /* The shot does not hit yet */ + hit_body = FALSE; + /* Travel until stopped */ for (cur_dis = 0; cur_dis <= tdis; ) { + cave_type *c_ptr; + /* Hack -- Stop at the target */ if ((y == ty) && (x == tx)) break; @@ -3509,12 +3589,48 @@ void do_cmd_fire_aux(int item, object_type *j_ptr) nx = x; mmove2(&ny, &nx, py, px, ty, tx); + /* Shatter Arrow */ + if (snipe_type == SP_KILL_WALL) + { + c_ptr = &cave[ny][nx]; + + if (cave_have_flag_grid(c_ptr, FF_HURT_ROCK) && !c_ptr->m_idx) + { +#ifdef JP + if (c_ptr->info & (CAVE_MARK)) msg_print("´ä¤¬ºÕ¤±»¶¤Ã¤¿¡£"); +#else + if (c_ptr->info & (CAVE_MARK)) msg_print("Wall rocks were shattered."); +#endif + /* Forget the wall */ + c_ptr->info &= ~(CAVE_MARK); + + p_ptr->update |= (PU_VIEW | PU_LITE | PU_FLOW | PU_MON_LITE); + + /* Destroy the wall */ + cave_alter_feat(ny, nx, FF_HURT_ROCK); + + hit_body = TRUE; + break; + } + } + /* Stopped by walls/doors */ if (!cave_have_flag_bold(ny, nx, FF_PROJECT) && !cave[ny][nx].m_idx) break; /* Advance the distance */ cur_dis++; + /* Sniper */ + if (snipe_type == SP_LITE) + { + cave[ny][nx].info |= (CAVE_GLOW); + + /* Notice */ + note_spot(ny, nx); + + /* Redraw */ + lite_spot(ny, nx); + } /* The player can see the (on screen) missile */ if (panel_contains(ny, nx) && player_can_see_bold(ny, nx)) @@ -3538,6 +3654,25 @@ void do_cmd_fire_aux(int item, object_type *j_ptr) Term_xtra(TERM_XTRA_DELAY, msec); } + /* Sniper */ + if (snipe_type == SP_KILL_TRAP) + { + project(0, 0, ny, nx, 0, GF_KILL_TRAP, + (PROJECT_JUMP | PROJECT_HIDE | PROJECT_GRID | PROJECT_ITEM), -1); + } + + /* Sniper */ + if (snipe_type == SP_EVILNESS) + { + cave[ny][nx].info &= ~(CAVE_GLOW | CAVE_MARK); + + /* Notice */ + note_spot(ny, nx); + + /* Redraw */ + lite_spot(ny, nx); + } + /* Save the old location */ prev_y = y; prev_x = x; @@ -3550,6 +3685,7 @@ void do_cmd_fire_aux(int item, object_type *j_ptr) /* Monster here, Try to hit it */ if (cave[y][x].m_idx) { + int armour; cave_type *c_ptr = &cave[y][x]; monster_type *m_ptr = &m_list[c_ptr->m_idx]; @@ -3593,10 +3729,22 @@ void do_cmd_fire_aux(int item, object_type *j_ptr) } } + /* Some shots have hit bonus */ + armour = r_ptr->ac; + if (p_ptr->concent) + { + armour *= (10 - p_ptr->concent); + armour /= 10; + } + /* Did we hit it (penalize range) */ - if (test_hit_fire(chance - cur_dis, r_ptr->ac, m_ptr->ml)) + if (test_hit_fire(chance - cur_dis, armour, m_ptr->ml)) { bool fear = FALSE; + int tdam = tdam_base; + + /* Get extra damage from concentration */ + if (p_ptr->concent) tdam = boost_concentration_damage(tdam); /* Handle unseen monster */ if (!visible) @@ -3625,23 +3773,47 @@ void do_cmd_fire_aux(int item, object_type *j_ptr) msg_format("The %s hits %s.", o_name, m_name); #endif + if (m_ptr->ml) + { + /* Hack -- Track this monster race */ + if (!p_ptr->image) monster_race_track(m_ptr->ap_r_idx); - /* Hack -- Track this monster race */ - if (m_ptr->ml) monster_race_track(m_ptr->ap_r_idx); - - /* Hack -- Track this monster */ - if (m_ptr->ml) health_track(c_ptr->m_idx); + /* Hack -- Track this monster */ + health_track(c_ptr->m_idx); + } } - /* Apply special damage XXX XXX XXX */ - tdam = tot_dam_aux_shot(q_ptr, tdam, m_ptr); - tdam = critical_shot(q_ptr->weight, q_ptr->to_h, tdam); + if (snipe_type == SP_NEEDLE) + { + if ((randint1(randint1(r_ptr->level / (3 + p_ptr->concent)) + (8 - p_ptr->concent)) == 1) + && !(r_ptr->flags1 & RF1_UNIQUE) && !(r_ptr->flags7 & RF7_UNIQUE2)) + { + char m_name[80]; - /* No negative damage */ - if (tdam < 0) tdam = 0; + /* Get "the monster" or "it" */ + monster_desc(m_name, m_ptr, 0); - /* Modify the damage */ - tdam = mon_damage_mod(m_ptr, tdam, FALSE); + tdam = m_ptr->hp + 1; +#ifdef JP + msg_format("%s¤ÎµÞ½ê¤ËÆͤ­»É¤µ¤Ã¤¿¡ª", m_name); +#else + msg_format("Your shot sticked on a fatal spot of %s!", m_name); +#endif + } + else tdam = 1; + } + else + { + /* Apply special damage XXX XXX XXX */ + tdam = tot_dam_aux_shot(q_ptr, tdam, m_ptr); + tdam = critical_shot(q_ptr->weight, q_ptr->to_h, tdam); + + /* No negative damage */ + if (tdam < 0) tdam = 0; + + /* Modify the damage */ + tdam = mon_damage_mod(m_ptr, tdam, FALSE); + } /* Complex message */ if (p_ptr->wizard || cheat_xtra) @@ -3656,6 +3828,28 @@ void do_cmd_fire_aux(int item, object_type *j_ptr) } + /* Sniper */ + if (snipe_type == SP_EXPLODE) + { + u16b flg = (PROJECT_STOP | PROJECT_JUMP | PROJECT_KILL | PROJECT_GRID); + + sound(SOUND_EXPLODE); /* No explode sound - use breath fire instead */ + project(0, ((p_ptr->concent + 1) / 2 + 1), ny, nx, tdam, GF_MISSILE, flg, -1); + break; + } + + /* Sniper */ + if (snipe_type == SP_HOLYNESS) + { + cave[ny][nx].info |= (CAVE_GLOW); + + /* Notice */ + note_spot(ny, nx); + + /* Redraw */ + lite_spot(ny, nx); + } + /* Hit the monster, check for death */ if (mon_take_hit(c_ptr->m_idx, tdam, &fear, extract_note_dies(real_r_ptr(m_ptr)))) { @@ -3705,13 +3899,66 @@ void do_cmd_fire_aux(int item, object_type *j_ptr) #endif } - if (!projectable(m_ptr->fy, m_ptr->fx, py, px)) + + set_target(m_ptr, py, px); + + /* Sniper */ + if (snipe_type == SP_RUSH) { - set_target(m_ptr, py, px); + int n = randint1(5) + 3; + int m_idx = c_ptr->m_idx; + + for ( ; cur_dis <= tdis; ) + { + int ox = nx; + int oy = ny; + + if (!n) break; + + /* Calculate the new location (see "project()") */ + mmove2(&ny, &nx, py, px, ty, tx); + + /* Stopped by wilderness boundary */ + if (!in_bounds2(ny, nx)) break; + + /* Stopped by walls/doors */ + if (!player_can_enter(cave[ny][nx].feat, 0)) break; + + /* Stopped by monsters */ + if (!cave_empty_bold(ny, nx)) break; + + cave[ny][nx].m_idx = m_idx; + cave[oy][ox].m_idx = 0; + + m_ptr->fx = nx; + m_ptr->fy = ny; + + /* Update the monster (new location) */ + update_mon(c_ptr->m_idx, TRUE); + + lite_spot(ny, nx); + lite_spot(oy, ox); + + Term_fresh(); + Term_xtra(TERM_XTRA_DELAY, msec); + + x = nx; + y = ny; + cur_dis++; + n--; + } } } } + /* Sniper */ + if (snipe_type == SP_PIERCE) + { + if(p_ptr->concent < 1) break; + p_ptr->concent--; + continue; + } + /* Stop looking */ break; } @@ -3744,7 +3991,7 @@ void do_cmd_fire_aux(int item, object_type *j_ptr) object_copy(o_ptr, q_ptr); /* Forget mark */ - o_ptr->marked = 0; + o_ptr->marked &= OM_TOUCHED; /* Forget location */ o_ptr->iy = o_ptr->ix = 0; @@ -3768,6 +4015,12 @@ void do_cmd_fire_aux(int item, object_type *j_ptr) /* Drop (or break) near that location */ (void)drop_near(q_ptr, j, prev_y, prev_x); } + + /* Sniper - Repeat shooting when double shots */ + } + + /* Sniper - Loose his/her concentration after any shot */ + if (p_ptr->concent) reset_concentration(FALSE); } @@ -3777,6 +4030,8 @@ void do_cmd_fire(void) object_type *j_ptr; cptr q, s; + is_fired = FALSE; /* not fired yet */ + /* Get the "bow" (if any) */ j_ptr = &inventory[INVEN_BOW]; @@ -3829,6 +4084,24 @@ void do_cmd_fire(void) /* Fire the item */ do_cmd_fire_aux(item, j_ptr); + + if (!is_fired || p_ptr->pclass != CLASS_SNIPER) return; + + /* Sniper actions after some shootings */ + if (snipe_type == SP_AWAY) + { + teleport_player(10 + (p_ptr->concent * 2), 0L); + } + if (snipe_type == SP_FINAL) + { +#ifdef JP + msg_print("¼Í·â¤ÎÈ¿Æ°¤¬ÂΤò½±¤Ã¤¿¡£"); +#else + msg_print("A reactionary of shooting attacked you. "); +#endif + (void)set_slow(p_ptr->slow + randint0(7) + 7, FALSE); + (void)set_stun(p_ptr->stun + randint1(25)); + } } @@ -3856,7 +4129,7 @@ bool do_cmd_throw_aux(int mult, bool boomerang, int shuriken) int i, j, y, x, ty, tx, prev_y, prev_x; int ny[19], nx[19]; int chance, tdam, tdis; - int mul, div; + int mul, div, dd, ds; int cur_dis, visible; object_type forge; @@ -3884,7 +4157,7 @@ bool do_cmd_throw_aux(int mult, bool boomerang, int shuriken) set_action(ACTION_NONE); } - if (shuriken) + if (shuriken >= 0) { item = shuriken; } @@ -3977,6 +4250,7 @@ bool do_cmd_throw_aux(int mult, bool boomerang, int shuriken) /* Extract the thrown object's flags. */ object_flags(q_ptr, flgs); + torch_flags(q_ptr, flgs); /* Distribute the charges of rods/wands between the stacks */ distribute_charges(o_ptr, q_ptr, 1); @@ -4003,7 +4277,7 @@ bool do_cmd_throw_aux(int mult, bool boomerang, int shuriken) /* Max distance of 10-18 */ if (tdis > mul) tdis = mul; - if (shuriken) + if (shuriken >= 0) { ty = randint0(101)-50+py; tx = randint0(101)-50+px; @@ -4180,16 +4454,21 @@ bool do_cmd_throw_aux(int mult, bool boomerang, int shuriken) msg_format("The %s hits %s.", o_name, m_name); #endif + if (m_ptr->ml) + { + /* Hack -- Track this monster race */ + if (!p_ptr->image) monster_race_track(m_ptr->ap_r_idx); - /* Hack -- Track this monster race */ - if (m_ptr->ml) monster_race_track(m_ptr->ap_r_idx); - - /* Hack -- Track this monster */ - if (m_ptr->ml) health_track(c_ptr->m_idx); + /* Hack -- Track this monster */ + health_track(c_ptr->m_idx); + } } /* Hack -- Base damage from thrown object */ - tdam = damroll(q_ptr->dd, q_ptr->ds); + dd = q_ptr->dd; + ds = q_ptr->ds; + torch_dice(q_ptr, &dd, &ds); /* throwing a torch */ + tdam = damroll(dd, ds); /* Apply special damage XXX XXX XXX */ tdam = tot_dam_aux(q_ptr, tdam, m_ptr, 0, TRUE); tdam = critical_shot(q_ptr->weight, q_ptr->to_h, tdam); @@ -4279,6 +4558,9 @@ bool do_cmd_throw_aux(int mult, bool boomerang, int shuriken) } } + /* decrease toach's fuel */ + if (hit_body) torch_lost_fuel(q_ptr); + /* Chance of breakage (during attacks) */ j = (hit_body ? breakage_chance(q_ptr) : 0); @@ -4485,5 +4767,226 @@ msg_print(" */ void do_cmd_throw(void) { - do_cmd_throw_aux(1, FALSE, 0); + do_cmd_throw_aux(1, FALSE, -1); +} + + +#ifdef TRAVEL +/* + * Hack: travel command + */ +#define TRAVEL_UNABLE 9999 + +static int flow_head = 0; +static int flow_tail = 0; +static s16b temp2_x[MAX_SHORT]; +static s16b temp2_y[MAX_SHORT]; + +/* Hack: forget the "flow" information */ +void forget_travel_flow(void) +{ + int x, y; + + /* Check the entire dungeon */ + for (y = 0; y < cur_hgt; y++) + { + for (x = 0; x < cur_wid; x++) + { + /* Forget the old data */ + travel.cost[y][x] = MAX_SHORT; + } + } + + travel.y = travel.x = 0; +} + +static int travel_flow_cost(int y, int x) +{ + feature_type *f_ptr = &f_info[cave[y][x].feat]; + int cost = 1; + + /* Avoid obstacles (ex. trees) */ + if (have_flag(f_ptr->flags, FF_AVOID_RUN)) cost += 1; + + /* Water */ + if (have_flag(f_ptr->flags, FF_WATER)) + { + if (have_flag(f_ptr->flags, FF_DEEP) && !p_ptr->levitation) cost += 5; + } + + /* Lava */ + if (have_flag(f_ptr->flags, FF_LAVA)) + { + int lava = 2; + if (!p_ptr->resist_fire) lava *= 2; + if (!p_ptr->levitation) lava *= 2; + if (have_flag(f_ptr->flags, FF_DEEP)) lava *= 2; + + cost += lava; + } + + /* Detected traps and doors */ + if (cave[y][x].info & (CAVE_MARK)) + { + if (have_flag(f_ptr->flags, FF_DOOR)) cost += 1; + if (have_flag(f_ptr->flags, FF_TRAP)) cost += 10; + } + + return (cost); +} + +static void travel_flow_aux(int y, int x, int n, bool wall) +{ + cave_type *c_ptr = &cave[y][x]; + feature_type *f_ptr = &f_info[c_ptr->feat]; + int old_head = flow_head; + int add_cost = 1; + int base_cost = (n % TRAVEL_UNABLE); + int from_wall = (n / TRAVEL_UNABLE); + int cost; + + /* Ignore out of bounds */ + if (!in_bounds(y, x)) return; + + /* Ignore unknown grid except in wilderness */ + if (dun_level > 0 && !(c_ptr->info & CAVE_KNOWN)) return; + + /* Ignore "walls" and "rubble" (include "secret doors") */ + if (have_flag(f_ptr->flags, FF_WALL) || + have_flag(f_ptr->flags, FF_CAN_DIG) || + (have_flag(f_ptr->flags, FF_DOOR) && cave[y][x].mimic) || + (!have_flag(f_ptr->flags, FF_MOVE) && have_flag(f_ptr->flags, FF_CAN_FLY) && !p_ptr->levitation)) + { + if (!wall || !from_wall) return; + add_cost += TRAVEL_UNABLE; + } + else + { + add_cost = travel_flow_cost(y, x); + } + + cost = base_cost + add_cost; + + /* Ignore lower cost entries */ + if (travel.cost[y][x] <= cost) return; + + /* Save the flow cost */ + travel.cost[y][x] = cost; + + /* Enqueue that entry */ + temp2_y[flow_head] = y; + temp2_x[flow_head] = x; + + /* Advance the queue */ + if (++flow_head == MAX_SHORT) flow_head = 0; + + /* Hack -- notice overflow by forgetting new entry */ + if (flow_head == flow_tail) flow_head = old_head; + + return; +} + + +static void travel_flow(int ty, int tx) +{ + int x, y, d; + bool wall = FALSE; + feature_type *f_ptr = &f_info[cave[py][px].feat]; + + /* Reset the "queue" */ + flow_head = flow_tail = 0; + + /* is player in the wall? */ + if (!have_flag(f_ptr->flags, FF_MOVE)) wall = TRUE; + + /* Start at the target grid */ + travel_flow_aux(ty, tx, 0, wall); + + /* Now process the queue */ + while (flow_head != flow_tail) + { + /* Extract the next entry */ + y = temp2_y[flow_tail]; + x = temp2_x[flow_tail]; + + /* Forget that entry */ + if (++flow_tail == MAX_SHORT) flow_tail = 0; + + /* Ignore too far entries */ + //if (distance(ty, tx, y, x) > 100) continue; + + /* Add the "children" */ + for (d = 0; d < 8; d++) + { + /* Add that child if "legal" */ + travel_flow_aux(y + ddy_ddd[d], x + ddx_ddd[d], travel.cost[y][x], wall); + } + } + + /* Forget the flow info */ + flow_head = flow_tail = 0; +} + +void do_cmd_travel(void) +{ + int x, y, i; + int dx, dy, sx, sy; + feature_type *f_ptr; + + if (travel.x != 0 && travel.y != 0 && + get_check(_("¥È¥é¥Ù¥ë¤ò·Ñ³¤·¤Þ¤¹¤«¡©", "Do you continue to travel?"))) + { + y = travel.y; + x = travel.x; + } + else if (!tgt_pt(&x, &y)) return; + + if ((x == px) && (y == py)) + { +#ifdef JP + msg_print("¤¹¤Ç¤Ë¤½¤³¤Ë¤¤¤Þ¤¹¡ª"); +#else + msg_print("You are already there!!"); +#endif + return; + } + + f_ptr = &f_info[cave[y][x].feat]; + + if ((cave[y][x].info & CAVE_MARK) && + (have_flag(f_ptr->flags, FF_WALL) || + have_flag(f_ptr->flags, FF_CAN_DIG) || + (have_flag(f_ptr->flags, FF_DOOR) && cave[y][x].mimic))) + { +#ifdef JP + msg_print("¤½¤³¤Ë¤Ï¹Ô¤¯¤³¤È¤¬¤Ç¤­¤Þ¤»¤ó¡ª"); +#else + msg_print("You cannot travel there!"); +#endif + return; + } + + forget_travel_flow(); + travel_flow(y, x); + + travel.x = x; + travel.y = y; + + /* Travel till 255 steps */ + travel.run = 255; + + /* Paranoia */ + travel.dir = 0; + + /* Decides first direction */ + dx = abs(px - x); + dy = abs(py - y); + sx = ((x == px) || (dx < dy)) ? 0 : ((x > px) ? 1 : -1); + sy = ((y == py) || (dy < dx)) ? 0 : ((y > py) ? 1 : -1); + + for (i = 1; i <= 9; i++) + { + if ((sx == ddx[i]) && (sy == ddy[i])) travel.dir = i; + } } +#endif