X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=src%2Fxtra2.c;h=a39394da04da53a797c59b35c854cd7a4115ad4a;hb=dd94a4b734413305e38e0f140b567bfc3d632e47;hp=8b4119e2c2e4f2bf0123a0972cb9b14977871ef4;hpb=a9696bd23c1859316bfc6bffdeedab530ac1c720;p=hengband%2Fhengband.git diff --git a/src/xtra2.c b/src/xtra2.c index 8b4119e2c..a39394da0 100644 --- a/src/xtra2.c +++ b/src/xtra2.c @@ -24,23 +24,24 @@ void check_experience(void) bool level_mutation = FALSE; bool level_inc_stat = FALSE; bool android = (p_ptr->prace == RACE_ANDROID ? TRUE : FALSE); - + int old_lev = p_ptr->lev; /* Hack -- lower limit */ if (p_ptr->exp < 0) p_ptr->exp = 0; - - /* Hack -- lower limit */ if (p_ptr->max_exp < 0) p_ptr->max_exp = 0; + if (p_ptr->max_max_exp < 0) p_ptr->max_max_exp = 0; /* Hack -- upper limit */ if (p_ptr->exp > PY_MAX_EXP) p_ptr->exp = PY_MAX_EXP; - - /* Hack -- upper limit */ if (p_ptr->max_exp > PY_MAX_EXP) p_ptr->max_exp = PY_MAX_EXP; + if (p_ptr->max_max_exp > PY_MAX_EXP) p_ptr->max_max_exp = PY_MAX_EXP; /* Hack -- maintain "max" experience */ if (p_ptr->exp > p_ptr->max_exp) p_ptr->max_exp = p_ptr->exp; + /* Hack -- maintain "max max" experience */ + if (p_ptr->max_exp > p_ptr->max_max_exp) p_ptr->max_max_exp = p_ptr->max_exp; + /* Redraw experience */ p_ptr->redraw |= (PR_EXP); @@ -103,16 +104,17 @@ void check_experience(void) msg_format("¥ì¥Ù¥ë %d ¤Ë¤è¤¦¤³¤½¡£", p_ptr->lev); #else msg_format("Welcome to level %d.", p_ptr->lev); + #endif /* Update some stuff */ p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS); /* Redraw some stuff */ - p_ptr->redraw |= (PR_LEV | PR_TITLE); + p_ptr->redraw |= (PR_LEV | PR_TITLE | PR_EXP); /* Window stuff */ - p_ptr->window |= (PW_PLAYER | PW_SPELL); + p_ptr->window |= (PW_PLAYER | PW_SPELL | PW_INVEN); /* HP¤ÈMP¤Î¾å¾ºÎ̤òɽ¼¨ */ level_up = 1; @@ -219,6 +221,9 @@ msg_print(" /* Handle stuff */ handle_stuff(); } + + /* Load an autopick preference file */ + if (old_lev != p_ptr->lev) autopick_load_pref(FALSE); } @@ -230,24 +235,19 @@ msg_print(" */ static int get_coin_type(int r_idx) { - monster_race *r_ptr = &r_info[r_idx]; - - /* Analyze "coin" monsters */ - if (r_ptr->d_char == '$') + /* Analyze monsters */ + switch (r_idx) { - /* Look for textual clues */ - switch (r_idx) - { - case MON_COPPER_COINS: return (2); - case MON_SILVER_COINS: return (5); - case MON_GOLD_COINS: return (10); - case MON_MITHRIL_COINS: return (16); - case MON_ADAMANT_COINS: return (17); - } + case MON_COPPER_COINS: return 2; + case MON_SILVER_COINS: return 5; + case MON_GOLD_COINS: return 10; + case MON_MITHRIL_COINS: + case MON_MITHRIL_GOLEM: return 16; + case MON_ADAMANT_COINS: return 17; } /* Assume nothing */ - return (0); + return 0; } @@ -360,11 +360,72 @@ static bool kind_is_armor(int k_idx) /* + * Hack -- determine if a template is hafted weapon + */ +static bool kind_is_hafted(int k_idx) +{ + object_kind *k_ptr = &k_info[k_idx]; + + /* Analyze the item type */ + if (k_ptr->tval == TV_HAFTED) + { + return (TRUE); + } + + /* Assume not good */ + return (FALSE); +} + + +void complete_quest(int quest_num) +{ + switch (quest[quest_num].type) + { + case QUEST_TYPE_RANDOM: + if (record_rand_quest) do_cmd_write_nikki(NIKKI_RAND_QUEST_C, quest_num, NULL); + break; + default: + if (record_fix_quest) do_cmd_write_nikki(NIKKI_FIX_QUEST_C, quest_num, NULL); + break; + } + + quest[quest_num].status = QUEST_STATUS_COMPLETED; + quest[quest_num].complev = (byte)p_ptr->lev; + + if (!(quest[quest_num].flags & QUEST_FLAG_SILENT)) + { + msg_print(_("¥¯¥¨¥¹¥È¤òãÀ®¤·¤¿¡ª", "You just completed your quest!")); + msg_print(NULL); + } +} + +static int count_all_hostile_monsters(void) +{ + int x, y; + int number_mon = 0; + + for (x = 0; x < cur_wid; ++ x) + { + for (y = 0; y < cur_hgt; ++ y) + { + int m_idx = cave[y][x].m_idx; + + if (m_idx > 0 && is_hostile(&m_list[m_idx])) + { + ++ number_mon; + } + } + } + + return number_mon; +} + +/* * Check for "Quest" completion when a quest monster is killed or charmed. */ void check_quest_completion(monster_type *m_ptr) { - int i, j, y, x, ny, nx, i2, j2; + int i, j, y, x, ny, nx; int quest_num; @@ -406,6 +467,7 @@ void check_quest_completion(monster_type *m_ptr) /* Interesting quest */ if ((quest[i].type == QUEST_TYPE_KILL_NUMBER) || + (quest[i].type == QUEST_TYPE_TOWER) || (quest[i].type == QUEST_TYPE_KILL_ALL)) break; @@ -434,21 +496,7 @@ void check_quest_completion(monster_type *m_ptr) if (quest[i].cur_num >= quest[i].num_mon) { - if (record_fix_quest) do_cmd_write_nikki(NIKKI_FIX_QUEST_C, i, NULL); - /* completed quest */ - quest[i].status = QUEST_STATUS_COMPLETED; - quest[i].complev = (byte)p_ptr->lev; - - if (!(quest[i].flags & QUEST_FLAG_SILENT)) - { -#ifdef JP -msg_print("¥¯¥¨¥¹¥È¤òãÀ®¤·¤¿¡ª"); -#else - msg_print("You just completed your quest!"); -#endif - - msg_print(NULL); - } + complete_quest(i); quest[i].cur_num = 0; } @@ -456,36 +504,17 @@ msg_print(" } case QUEST_TYPE_KILL_ALL: { - int number_mon = 0; - if (!is_hostile(m_ptr)) break; - /* Count all hostile monsters */ - for (i2 = 0; i2 < cur_wid; ++i2) - for (j2 = 0; j2 < cur_hgt; j2++) - if (cave[j2][i2].m_idx > 0) - if (is_hostile(&m_list[cave[j2][i2].m_idx])) - number_mon++; - - if ((number_mon - 1) == 0) + if (count_all_hostile_monsters() == 1) { - if (record_fix_quest) do_cmd_write_nikki(NIKKI_FIX_QUEST_C, i, NULL); - /* completed */ if (quest[i].flags & QUEST_FLAG_SILENT) { quest[i].status = QUEST_STATUS_FINISHED; } else { - quest[i].status = QUEST_STATUS_COMPLETED; - quest[i].complev = (byte)p_ptr->lev; -#ifdef JP -msg_print("¥¯¥¨¥¹¥È¤òãÀ®¤·¤¿¡ª"); -#else - msg_print("You just completed your quest!"); -#endif - - msg_print(NULL); + complete_quest(i); } } break; @@ -501,28 +530,14 @@ msg_print(" if (quest[i].cur_num >= quest[i].max_num) { - if (record_fix_quest && (quest[i].type == QUEST_TYPE_KILL_LEVEL)) do_cmd_write_nikki(NIKKI_FIX_QUEST_C, i, NULL); - if (record_rand_quest && (quest[i].type == QUEST_TYPE_RANDOM)) do_cmd_write_nikki(NIKKI_RAND_QUEST_C, i, NULL); - /* completed quest */ - quest[i].status = QUEST_STATUS_COMPLETED; - quest[i].complev = (byte)p_ptr->lev; + complete_quest(i); + if (!(quest[i].flags & QUEST_FLAG_PRESET)) { create_stairs = TRUE; p_ptr->inside_quest = 0; } - if (!(quest[i].flags & QUEST_FLAG_SILENT)) - { -#ifdef JP -msg_print("¥¯¥¨¥¹¥È¤òãÀ®¤·¤¿¡ª"); -#else - msg_print("You just completed your quest!"); -#endif - - msg_print(NULL); - } - /* Finish the two main quests without rewarding */ if ((i == QUEST_OBERON) || (i == QUEST_SERPENT)) { @@ -542,22 +557,26 @@ msg_print(" quest[i].cur_num++; if (quest[i].cur_num >= quest[i].max_num) { - if (record_fix_quest) do_cmd_write_nikki(NIKKI_FIX_QUEST_C, i, NULL); - /* completed quest */ - quest[i].status = QUEST_STATUS_COMPLETED; - quest[i].complev = (byte)p_ptr->lev; + complete_quest(i); + quest[i].cur_num = 0; + } + break; + } + case QUEST_TYPE_TOWER: + { + if (!is_hostile(m_ptr)) break; + + if (count_all_hostile_monsters() == 1) + { + quest[i].status = QUEST_STATUS_STAGE_COMPLETED; - if (!(quest[i].flags & QUEST_FLAG_SILENT)) + if((quest[QUEST_TOWER1].status == QUEST_STATUS_STAGE_COMPLETED) && + (quest[QUEST_TOWER2].status == QUEST_STATUS_STAGE_COMPLETED) && + (quest[QUEST_TOWER3].status == QUEST_STATUS_STAGE_COMPLETED)) { -#ifdef JP -msg_print("¥¯¥¨¥¹¥È¤òãÀ®¤·¤¿¡ª"); -#else - msg_print("You just completed your quest!"); -#endif - msg_print(NULL); + complete_quest(QUEST_TOWER1); } - quest[i].cur_num = 0; } break; } @@ -586,10 +605,10 @@ msg_print(" /* Create stairs down */ - cave_set_feat(y, x, FEAT_MORE); + cave_set_feat(y, x, feat_down_stair); /* Remember to update everything */ - p_ptr->update |= (PU_VIEW | PU_LITE | PU_FLOW | PU_MONSTERS | PU_MON_LITE); + p_ptr->update |= (PU_FLOW); } /* @@ -615,6 +634,21 @@ msg_print(" } +void check_find_art_quest_completion(object_type *o_ptr) +{ + int i; + /* Check if completed a quest */ + for (i = 0; i < max_quests; i++) + { + if ((quest[i].type == QUEST_TYPE_FIND_ARTIFACT) && + (quest[i].status == QUEST_STATUS_TAKEN) && + (quest[i].k_idx == o_ptr->name1)) + { + complete_quest(i); + } + } +} + /* * Return monster death string */ @@ -680,13 +714,13 @@ void monster_death(int m_idx, bool drop_item) monster_race *r_ptr = &r_info[m_ptr->r_idx]; - bool visible = (m_ptr->ml || (r_ptr->flags1 & RF1_UNIQUE)); + bool visible = ((m_ptr->ml && !p_ptr->image) || (r_ptr->flags1 & RF1_UNIQUE)); u32b mo_mode = 0L; bool do_gold = (!(r_ptr->flags1 & RF1_ONLY_ITEM)); bool do_item = (!(r_ptr->flags1 & RF1_ONLY_GOLD)); - bool cloned = FALSE; + bool cloned = (m_ptr->smart & SM_CLONED) ? TRUE : FALSE; int force_coin = get_coin_type(m_ptr->r_idx); object_type forge; @@ -695,8 +729,8 @@ void monster_death(int m_idx, bool drop_item) bool drop_chosen_item = drop_item && !cloned && !p_ptr->inside_arena && !p_ptr->inside_battle && !is_pet(m_ptr); - - if (world_monster) world_monster = FALSE; + /* The caster is dead? */ + if (world_monster && world_monster == m_idx) world_monster = 0; /* Notice changes in view */ if (r_ptr->flags7 & (RF7_LITE_MASK | RF7_DARK_MASK)) @@ -709,9 +743,6 @@ void monster_death(int m_idx, bool drop_item) y = m_ptr->fy; x = m_ptr->fx; - if (m_ptr->smart & SM_CLONED) - cloned = TRUE; - if (record_named_pet && is_pet(m_ptr) && m_ptr->nickname) { char m_name[80]; @@ -808,9 +839,8 @@ msg_print(" /* Drop a dead corpse? */ if (one_in_(r_ptr->flags1 & RF1_UNIQUE ? 1 : 4) && - ((r_ptr->flags9 & RF9_DROP_CORPSE) || - (r_ptr->flags9 & RF9_DROP_SKELETON)) && - !(p_ptr->inside_arena || p_ptr->inside_battle || (m_ptr->smart & SM_CLONED) || ((m_ptr->r_idx == today_mon) && is_pet(m_ptr)))) + (r_ptr->flags9 & (RF9_DROP_CORPSE | RF9_DROP_SKELETON)) && + !(p_ptr->inside_arena || p_ptr->inside_battle || cloned || ((m_ptr->r_idx == today_mon) && is_pet(m_ptr)))) { /* Assume skeleton */ bool corpse = FALSE; @@ -821,7 +851,7 @@ msg_print(" */ if (!(r_ptr->flags9 & RF9_DROP_SKELETON)) corpse = TRUE; - else if ((r_ptr->flags9 & RF9_DROP_CORPSE) && (r_ptr->flags1 && RF1_UNIQUE)) + else if ((r_ptr->flags9 & RF9_DROP_CORPSE) && (r_ptr->flags1 & RF1_UNIQUE)) corpse = TRUE; /* Else, a corpse is more likely unless we did a "lot" of damage */ @@ -922,9 +952,6 @@ msg_print(" else get_obj_num_hook = kind_is_book; - /* Prepare allocation table */ - get_obj_num_prep(); - /* Make a book */ make_object(q_ptr, mo_mode); @@ -942,15 +969,15 @@ msg_print(" { if (!one_in_(7)) { - int wy = py, wx = px; + int wy = y, wx = x; int attempts = 100; bool pet = is_pet(m_ptr); do { - scatter(&wy, &wx, py, px, 20, 0); + scatter(&wy, &wx, y, x, 20, 0); } - while (!(in_bounds(wy, wx) && cave_floor_bold(wy, wx)) && --attempts); + while (!(in_bounds(wy, wx) && cave_empty_bold2(wy, wx)) && --attempts); if (attempts > 0) { @@ -987,6 +1014,7 @@ msg_print(" if (p_ptr->pseikaku == SEIKAKU_NAMAKE) { int a_idx = 0; + artifact_type *a_ptr = NULL; if (!drop_chosen_item) break; @@ -1004,15 +1032,20 @@ msg_print(" a_idx = ART_NAMAKE_ARMOR; break; } + + a_ptr = &a_info[a_idx]; } - while (a_info[a_idx].cur_num); + while (a_ptr->cur_num); - if (a_info[a_idx].cur_num == 0) + /* Create the artifact */ + if (create_named_art(a_idx, y, x)) { - /* Create the artifact */ - create_named_art(a_idx, y, x); - a_info[a_idx].cur_num = 1; + a_ptr->cur_num = 1; + + /* Hack -- Memorize location of artifact in saved floors */ + if (character_dungeon) a_ptr->floor_id = p_ptr->floor_id; } + else if (!preserve_mode) a_ptr->cur_num = 1; } break; @@ -1067,7 +1100,7 @@ msg_print(" case MON_A_GOLD: case MON_A_SILVER: if (drop_chosen_item && ((m_ptr->r_idx == MON_A_GOLD) || - ((m_ptr->r_idx == MON_A_SILVER) && !((r_ptr->r_pkills + 1) % 5)))) + ((m_ptr->r_idx == MON_A_SILVER) && (r_ptr->r_akills % 5 == 0)))) { /* Get local object */ q_ptr = &forge; @@ -1106,9 +1139,6 @@ msg_print(" /* Activate restriction */ get_obj_num_hook = kind_is_cloak; - /* Prepare allocation table */ - get_obj_num_prep(); - /* Make a cloak */ make_object(q_ptr, mo_mode); @@ -1129,9 +1159,6 @@ msg_print(" /* Activate restriction */ get_obj_num_hook = kind_is_polearm; - /* Prepare allocation table */ - get_obj_num_prep(); - /* Make a poleweapon */ make_object(q_ptr, mo_mode); @@ -1152,9 +1179,6 @@ msg_print(" /* Activate restriction */ get_obj_num_hook = kind_is_armor; - /* Prepare allocation table */ - get_obj_num_prep(); - /* Make a hard armor */ make_object(q_ptr, mo_mode); @@ -1163,6 +1187,26 @@ msg_print(" } break; + case '\\': + if (dun_level > 4) + { + /* Get local object */ + q_ptr = &forge; + + /* Wipe the object */ + object_wipe(q_ptr); + + /* Activate restriction */ + get_obj_num_hook = kind_is_hafted; + + /* Make a hafted weapon */ + make_object(q_ptr, mo_mode); + + /* Drop it in the dungeon */ + (void)drop_near(q_ptr, -1, y, x); + } + break; + case '|': if (m_ptr->r_idx != MON_STORMBRINGER) { @@ -1175,9 +1219,6 @@ msg_print(" /* Activate restriction */ get_obj_num_hook = kind_is_sword; - /* Prepare allocation table */ - get_obj_num_prep(); - /* Make a sword */ make_object(q_ptr, mo_mode); @@ -1363,15 +1404,28 @@ msg_print(" a_idx = ART_FUNDIN; chance = 5; break; + + case MON_ROBIN_HOOD: + a_idx = ART_ROBIN_HOOD; + chance = 5; + break; } if ((a_idx > 0) && ((randint0(100) < chance) || p_ptr->wizard)) { - if (a_info[a_idx].cur_num == 0) + artifact_type *a_ptr = &a_info[a_idx]; + + if (!a_ptr->cur_num) { /* Create the artifact */ - create_named_art(a_idx, y, x); - a_info[a_idx].cur_num = 1; + if (create_named_art(a_idx, y, x)) + { + a_ptr->cur_num = 1; + + /* Hack -- Memorize location of artifact in saved floors */ + if (character_dungeon) a_ptr->floor_id = p_ptr->floor_id; + } + else if (!preserve_mode) a_ptr->cur_num = 1; } } @@ -1383,11 +1437,19 @@ msg_print(" if (d_info[dungeon_type].final_artifact) { int a_idx = d_info[dungeon_type].final_artifact; - if (!a_info[a_idx].cur_num) + artifact_type *a_ptr = &a_info[a_idx]; + + if (!a_ptr->cur_num) { /* Create the artifact */ - create_named_art(a_idx, y, x); - a_info[a_idx].cur_num = 1; + if (create_named_art(a_idx, y, x)) + { + a_ptr->cur_num = 1; + + /* Hack -- Memorize location of artifact in saved floors */ + if (character_dungeon) a_ptr->floor_id = p_ptr->floor_id; + } + else if (!preserve_mode) a_ptr->cur_num = 1; /* Prevent rewarding both artifact and "default" object */ if (!d_info[dungeon_type].final_object) k_idx = 0; @@ -1429,6 +1491,9 @@ msg_print(" if (is_pet(m_ptr) || p_ptr->inside_battle || p_ptr->inside_arena) number = 0; /* Pets drop no stuff */ if (!drop_item && (r_ptr->d_char != '$')) number = 0; + + if((r_ptr->flags2 & (RF2_MULTIPLY)) && (r_ptr->r_akills > 1024)) + number = 0; /* Limit of Multiply monster drop */ /* Hack -- handle creeping coins */ coin_type = force_coin; @@ -1550,17 +1615,17 @@ int mon_damage_mod(monster_type *m_ptr, int dam, bool is_psy_spear) if ((r_ptr->flagsr & RFR_RES_ALL) && dam > 0) { dam /= 100; - if((dam == 0) && one_in_(3)) dam = 1; + if ((dam == 0) && one_in_(3)) dam = 1; } - if (m_ptr->invulner) + if (MON_INVULNER(m_ptr)) { if (is_psy_spear) { - if(!p_ptr->blind && m_ptr->ml) + if (!p_ptr->blind && is_seen(m_ptr)) { #ifdef JP -msg_print("¥Ð¥ê¥¢¤òÀÚ¤êÎö¤¤¤¿¡ª"); + msg_print("¥Ð¥ê¥¢¤òÀÚ¤êÎö¤¤¤¿¡ª"); #else msg_print("The barrier is penetrated!"); #endif @@ -1574,115 +1639,84 @@ msg_print(" return (dam); } + +/* + * Calculate experience point to be get + * + * Even the 64 bit operation is not big enough to avoid overflaw + * unless we carefully choose orders of multiplication and division. + * + * Get the coefficient first, and multiply (potentially huge) base + * experience point of a monster later. + */ static void get_exp_from_mon(int dam, monster_type *m_ptr) { - s32b div, new_exp, new_exp_frac; monster_race *r_ptr = &r_info[m_ptr->r_idx]; - int monnum_penarty = 0; + + s32b new_exp; + u32b new_exp_frac; + s32b div_h; + u32b div_l; if (!m_ptr->r_idx) return; if (is_pet(m_ptr) || p_ptr->inside_battle) return; + + /* + * - Ratio of monster's level to player's level effects + * - Varying speed effects + * - Get a fraction in proportion of damage point + */ + new_exp = r_ptr->level * SPEED_TO_ENERGY(m_ptr->mspeed) * dam; + new_exp_frac = 0; + div_h = 0L; + div_l = (p_ptr->max_plv+2) * SPEED_TO_ENERGY(r_ptr->speed); + + /* Use (average maxhp * 2) as a denominator */ + if (!(r_ptr->flags1 & RF1_FORCE_MAXHP)) + s64b_mul(&div_h, &div_l, 0, r_ptr->hdice * (ironman_nightmare ? 2 : 1) * (r_ptr->hside + 1)); else + s64b_mul(&div_h, &div_l, 0, r_ptr->hdice * (ironman_nightmare ? 2 : 1) * r_ptr->hside * 2); + + /* Special penalty in the wilderness */ + if (!dun_level && (!(r_ptr->flags8 & RF8_WILD_ONLY) || !(r_ptr->flags1 & RF1_UNIQUE))) + s64b_mul(&div_h, &div_l, 0, 5); + + /* Do division first to prevent overflaw */ + s64b_div(&new_exp, &new_exp_frac, div_h, div_l); + + /* Special penalty for mutiply-monster */ + if ((r_ptr->flags2 & RF2_MULTIPLY) || (m_ptr->r_idx == MON_DAWN)) { - u32b m_exp; - u32b m_exp_h, m_exp_l; - u32b div_h, div_l; - if ((r_ptr->flags2 & RF2_MULTIPLY) || (m_ptr->r_idx == MON_DAWN)) - { - monnum_penarty = r_ptr->r_pkills / 400; - if (monnum_penarty > 8) monnum_penarty = 8; - } - if (r_ptr->flags1 & RF1_UNIQUE) - { - m_exp = (long)r_ptr->mexp * r_ptr->level; - div = (p_ptr->max_plv+2); - } - else - { - m_exp = (long)r_ptr->mexp * r_ptr->level * SPEED_TO_ENERGY(m_ptr->mspeed); - div = (p_ptr->max_plv+2) * SPEED_TO_ENERGY(r_ptr->speed); - } - m_exp_h = m_exp/0x10000L; - m_exp_l = m_exp%0x10000L; - m_exp_h *= dam; - m_exp_l *= dam; - m_exp_h += m_exp_l / 0x10000L; - m_exp_l %= 0x10000L; - - /* real monster maxhp have effect on EXP */ - if(!(r_ptr->flags1 & RF1_FORCE_MAXHP)) - { - u32b maxhp = m_ptr->max_maxhp*2; - m_exp_h *= maxhp; - m_exp_l *= maxhp; - m_exp_h += m_exp_l / 0x10000L; - m_exp_l %= 0x10000L; + int monnum_penarty = r_ptr->r_akills / 400; + if (monnum_penarty > 8) monnum_penarty = 8; - div *= r_ptr->hdice * (r_ptr->hside + 1); - } - if (!dun_level && (!(r_ptr->flags8 & RF8_WILD_ONLY) || !(r_ptr->flags1 & RF1_UNIQUE))) div *= 5; - div_h = div/0x10000L; - div_l = div%0x10000L; - div_h *= (m_ptr->max_maxhp*2); - div_l *= (m_ptr->max_maxhp*2); - div_h += div_l / 0x10000L; - div_l %= 0x10000L; - - while (monnum_penarty) + while (monnum_penarty--) { - div_h *= 4; - div_l *= 4; - div_h += div_l / 0x10000L; - div_l %= 0x10000L; - monnum_penarty--; + /* Divide by 4 */ + s64b_RSHIFT(new_exp, new_exp_frac, 2); } + } + + /* Special penalty for rest_and_shoot exp scum */ + if ((m_ptr->dealt_damage > m_ptr->max_maxhp) && (m_ptr->hp >= 0)) + { + int over_damage = m_ptr->dealt_damage / m_ptr->max_maxhp; + if (over_damage > 32) over_damage = 32; - m_exp_l = (0x7fffffff & (m_exp_h << 16)) | m_exp_l; - m_exp_h = m_exp_h >> 15; - div_l = (0x7fffffff & (div_h << 16)) | div_l; - div_h = div_h >> 15; - -#define M_INT_GREATER63(h1,l1,h2,l2) ( (h1>h2)||( (h1==h2)&&(l1>=l2))) -#define M_INT_SUB63(h1,l1, h2,l2) {h1-=h2;if(l1>30);l1=(l1<<1)&0x7fffffff;} -#define M_INT_RSHIFT63(h1,l1) {l1=(l1>>1)|(h1<<30);h1>>=1;} -#define M_INT_DIV63(h1,l1,h2,l2,result) \ - do{ \ - int bit=1; \ - result = 0; \ - while( M_INT_GREATER63(h1,l1, h2, l2) ){M_INT_LSHIFT63(h2, l2); bit<<=1;} \ - for(bit>>=1; bit>=1; bit>>=1){ \ - M_INT_RSHIFT63(h2, l2); \ - if(M_INT_GREATER63(h1, l1, h2, l2)) \ - {result|=bit;M_INT_SUB63(h1, l1, h2, l2);} \ - } \ - } while(0) - - /* Give some experience for the kill */ - M_INT_DIV63(m_exp_h, m_exp_l, div_h, div_l, new_exp); - - /* Handle fractional experience */ - /* multiply 0x10000L to remainder */ - m_exp_h = (m_exp_h<<16) | (m_exp_l>>15); - m_exp_l <<= 16; - M_INT_DIV63(m_exp_h, m_exp_l, div_h, div_l, new_exp_frac); - new_exp_frac += p_ptr->exp_frac; - /* Keep track of experience */ - if (new_exp_frac >= 0x10000L) - { - new_exp++; - p_ptr->exp_frac = (u16b)(new_exp_frac - 0x10000L); - } - else + while (over_damage--) { - p_ptr->exp_frac = (u16b)new_exp_frac; + /* 9/10 for once */ + s64b_mul(&new_exp, &new_exp_frac, 0, 9); + s64b_div(&new_exp, &new_exp_frac, 0, 10); } - - /* Gain experience */ - gain_exp(new_exp); } -} + /* Finally multiply base experience point of the monster */ + s64b_mul(&new_exp, &new_exp_frac, 0, r_ptr->mexp); + + /* Gain experience */ + gain_exp_64(new_exp, new_exp_frac); +} /* @@ -1725,14 +1759,17 @@ bool mon_take_hit(int m_idx, int dam, bool *fear, cptr note) bool innocent = TRUE, thief = FALSE; int i; int expdam; + int dealt_damage; - COPY(&exp_mon, m_ptr, monster_type); + (void)COPY(&exp_mon, m_ptr, monster_type); if (!(r_ptr->flags7 & RF7_KILL_EXP)) { expdam = (m_ptr->hp > dam) ? dam : m_ptr->hp; - if (r_ptr->flags6 & RF6_HEAL) expdam = (expdam+1) * 2 / 3; get_exp_from_mon(expdam, &exp_mon); + + /* Genocided by chaos patron */ + if (!m_ptr->r_idx) m_idx = 0; } /* Redraw (later) if needed */ @@ -1740,9 +1777,7 @@ bool mon_take_hit(int m_idx, int dam, bool *fear, cptr note) if (p_ptr->riding == m_idx) p_ptr->redraw |= (PR_UHEALTH); /* Wake it up */ - m_ptr->csleep = 0; - - if (r_ptr->flags7 & RF7_HAS_LD_MASK) p_ptr->update |= (PU_MON_LITE); + (void)set_monster_csleep(m_idx, 0); /* Hack - Cancel any special player stealth magics. -LM- */ if (p_ptr->special_defense & NINJA_S_STEALTH) @@ -1750,8 +1785,22 @@ bool mon_take_hit(int m_idx, int dam, bool *fear, cptr note) set_superstealth(FALSE); } + /* Genocided by chaos patron */ + if (!m_idx) return TRUE; + + /* Remember dealt_damage before this attack*/ + dealt_damage = m_ptr->dealt_damage; + /* Hurt it */ m_ptr->hp -= dam; + + m_ptr->dealt_damage += dam; + if(m_ptr->dealt_damage > m_ptr->max_maxhp * 100) m_ptr->dealt_damage = m_ptr->max_maxhp * 100; + if (p_ptr->wizard) + { + msg_format( _("¹ç·×%d/%d¤Î¥À¥á¡¼¥¸¤òÍ¿¤¨¤¿¡£","You do %d (out of %d) damage."), + m_ptr->dealt_damage, m_ptr->maxhp); + } /* It is dead now */ if (m_ptr->hp < 0) @@ -1773,15 +1822,43 @@ bool mon_take_hit(int m_idx, int dam, bool *fear, cptr note) if (r_ptr->r_sights < MAX_SHORT) r_ptr->r_sights++; } - /* When the player kills a Unique, it stays dead */ - if (r_ptr->flags1 & RF1_UNIQUE && !(m_ptr->smart & SM_CLONED)) - r_ptr->max_num = 0; + if (!(m_ptr->smart & SM_CLONED)) + { + /* When the player kills a Unique, it stays dead */ + if (r_ptr->flags1 & RF1_UNIQUE) + { + r_ptr->max_num = 0; + + /* Mega-Hack -- Banor & Lupart */ + if ((m_ptr->r_idx == MON_BANOR) || (m_ptr->r_idx == MON_LUPART)) + { + r_info[MON_BANORLUPART].max_num = 0; + r_info[MON_BANORLUPART].r_pkills++; + r_info[MON_BANORLUPART].r_akills++; + if (r_info[MON_BANORLUPART].r_tkills < MAX_SHORT) r_info[MON_BANORLUPART].r_tkills++; + } + else if (m_ptr->r_idx == MON_BANORLUPART) + { + r_info[MON_BANOR].max_num = 0; + r_info[MON_BANOR].r_pkills++; + r_info[MON_BANOR].r_akills++; + if (r_info[MON_BANOR].r_tkills < MAX_SHORT) r_info[MON_BANOR].r_tkills++; + r_info[MON_LUPART].max_num = 0; + r_info[MON_LUPART].r_pkills++; + r_info[MON_LUPART].r_akills++; + if (r_info[MON_LUPART].r_tkills < MAX_SHORT) r_info[MON_LUPART].r_tkills++; + } + } - /* When the player kills a Nazgul, it stays dead */ - if (r_ptr->flags7 & RF7_UNIQUE_7) r_ptr->max_num--; + /* When the player kills a Nazgul, it stays dead */ + else if (r_ptr->flags7 & RF7_NAZGUL) r_ptr->max_num--; + } + + /* Count all monsters killed */ + if (r_ptr->r_akills < MAX_SHORT) r_ptr->r_akills++; /* Recall even invisible uniques or winners */ - if (m_ptr->ml || (r_ptr->flags1 & RF1_UNIQUE)) + if ((m_ptr->ml && !p_ptr->image) || (r_ptr->flags1 & RF1_UNIQUE)) { /* Count kills this life */ if ((m_ptr->mflag2 & MFLAG2_KAGE) && (r_info[MON_KAGE].r_pkills < MAX_SHORT)) r_info[MON_KAGE].r_pkills++; @@ -1861,19 +1938,18 @@ msg_format("%^s chg_virtue(V_VALOUR, 2); } - if ((r_ptr->flags1 & RF1_UNIQUE) && ((r_ptr->flags3 & RF3_EVIL) || - (r_ptr->flags3 & RF3_GOOD))) - - chg_virtue(V_HARMONY, 2); - - if ((r_ptr->flags1 & RF1_UNIQUE) && (r_ptr->flags3 & RF3_GOOD)) + if (r_ptr->flags1 & RF1_UNIQUE) { - chg_virtue(V_UNLIFE, 2); - chg_virtue(V_VITALITY, -2); - } + if (r_ptr->flags3 & (RF3_EVIL | RF3_GOOD)) chg_virtue(V_HARMONY, 2); - if ((r_ptr->flags1 & RF1_UNIQUE) && one_in_(3)) - chg_virtue(V_INDIVIDUALISM, -1); + if (r_ptr->flags3 & RF3_GOOD) + { + chg_virtue(V_UNLIFE, 2); + chg_virtue(V_VITALITY, -2); + } + + if (one_in_(3)) chg_virtue(V_INDIVIDUALISM, -1); + } if (m_ptr->r_idx == MON_BEGGAR || m_ptr->r_idx == MON_LEPER) { @@ -1882,7 +1958,6 @@ msg_format("%^s if ((r_ptr->flags3 & RF3_GOOD) && ((r_ptr->level) / 10 + (3 * dun_level) >= randint1(100))) - chg_virtue(V_UNLIFE, 1); if (r_ptr->d_char == 'A') @@ -1917,18 +1992,18 @@ msg_format("%^s chg_virtue(V_HONOUR, 1); } } - if ((r_ptr->flags2 & RF2_MULTIPLY) && (r_ptr->r_pkills > 1000) && one_in_(10)) + if ((r_ptr->flags2 & RF2_MULTIPLY) && (r_ptr->r_akills > 1000) && one_in_(10)) { chg_virtue(V_VALOUR, -1); } - + for (i = 0; i < 4; i++) { - if(r_ptr->blow[i].d_dice != 0) innocent = FALSE; /* Murderer! */ - + if (r_ptr->blow[i].d_dice != 0) innocent = FALSE; /* Murderer! */ + if ((r_ptr->blow[i].effect == RBE_EAT_ITEM) || (r_ptr->blow[i].effect == RBE_EAT_GOLD)) - + thief = TRUE; /* Thief! */ } @@ -1941,7 +2016,6 @@ msg_format("%^s chg_virtue(V_JUSTICE, 3); else if (1+((r_ptr->level) / 10 + (2 * dun_level)) >= randint1(100)) - chg_virtue(V_JUSTICE, 1); } else if (innocent) @@ -1956,13 +2030,13 @@ msg_format("%^s if ((r_ptr->flags1 & RF1_UNIQUE) && record_destroy_uniq) { - char m_name[160]; + char note_buf[160]; #ifdef JP - sprintf(m_name, "%s%s", r_name + r_ptr->name, (m_ptr->smart & SM_CLONED) ? "(¥¯¥í¡¼¥ó)" : ""); + sprintf(note_buf, "%s%s", r_name + r_ptr->name, (m_ptr->smart & SM_CLONED) ? "(¥¯¥í¡¼¥ó)" : ""); #else - sprintf(m_name, "%s%s", r_name + r_ptr->name, (m_ptr->smart & SM_CLONED) ? "(Clone)" : ""); + sprintf(note_buf, "%s%s", r_name + r_ptr->name, (m_ptr->smart & SM_CLONED) ? "(Clone)" : ""); #endif - do_cmd_write_nikki(NIKKI_UNIQUE, 0, m_name); + do_cmd_write_nikki(NIKKI_UNIQUE, 0, note_buf); } /* Make a sound */ @@ -2002,9 +2076,9 @@ msg_format("%s /* Special note at death */ if (explode) #ifdef JP -msg_format("%s¤ÏÇúȯ¤·¤ÆÊ´¡¹¤Ë¤Ê¤Ã¤¿¡£", m_name); + msg_format("%s¤ÏÇúȯ¤·¤ÆÊ´¡¹¤Ë¤Ê¤Ã¤¿¡£", m_name); #else - msg_format("%s explodes into tiny shreds.", m_name); + msg_format("%^s explodes into tiny shreds.", m_name); #endif else { @@ -2032,7 +2106,7 @@ msg_format("%s #endif } - if (r_ptr->flags1 & RF1_UNIQUE && !(m_ptr->smart & SM_CLONED)) + if ((r_ptr->flags1 & RF1_UNIQUE) && !(m_ptr->smart & SM_CLONED) && !vanilla_town) { for (i = 0; i < MAX_KUBI; i++) { @@ -2050,22 +2124,6 @@ msg_format("%s /* Generate treasure */ monster_death(m_idx, TRUE); - if ((m_ptr->r_idx == MON_BANOR) || (m_ptr->r_idx == MON_LUPART)) - { - r_info[MON_BANORLUPART].max_num = 0; - r_info[MON_BANORLUPART].r_pkills++; - if (r_info[MON_BANORLUPART].r_tkills < MAX_SHORT) r_info[MON_BANORLUPART].r_tkills++; - } - - if (m_ptr->r_idx == MON_BANORLUPART) - { - r_info[MON_BANOR].max_num = 0; - r_info[MON_BANOR].r_pkills++; - if (r_info[MON_BANOR].r_tkills < MAX_SHORT) r_info[MON_BANOR].r_tkills++; - r_info[MON_LUPART].max_num = 0; - r_info[MON_LUPART].r_pkills++; - if (r_info[MON_LUPART].r_tkills < MAX_SHORT) r_info[MON_LUPART].r_tkills++; - } /* Mega hack : replace IKETA to BIKETAL */ if ((m_ptr->r_idx == MON_IKETA) && @@ -2097,9 +2155,17 @@ msg_format("%s /* Prevent bug of chaos patron's reward */ if (r_ptr->flags7 & RF7_KILL_EXP) + { get_exp_from_mon((long)exp_mon.max_maxhp*2, &exp_mon); + } else - get_exp_from_mon(((long)exp_mon.max_maxhp+1L) * 9L / 10L, &exp_mon); + { + u32b destroy_exp = exp_mon.max_maxhp + 1; + /* Add remained exp*/ + if(dealt_damage < m_ptr->maxhp) + destroy_exp += m_ptr->maxhp - dealt_damage; + get_exp_from_mon(destroy_exp, &exp_mon); + } /* Not afraid */ (*fear) = FALSE; @@ -2112,35 +2178,21 @@ msg_format("%s #ifdef ALLOW_FEAR /* Mega-Hack -- Pain cancels fear */ - if (m_ptr->monfear && (dam > 0)) + if (MON_MONFEAR(m_ptr) && (dam > 0)) { - int tmp = randint1(dam); - - /* Cure a little fear */ - if (tmp < m_ptr->monfear) - { - /* Reduce fear */ - m_ptr->monfear -= tmp; - } - - /* Cure all the fear */ - else + /* Cure fear */ + if (set_monster_monfear(m_idx, MON_MONFEAR(m_ptr) - randint1(dam))) { - /* Cure fear */ - m_ptr->monfear = 0; - /* No more fear */ (*fear) = FALSE; } } /* Sometimes a monster gets scared by damage */ - if (!m_ptr->monfear && !(r_ptr->flags3 & (RF3_NO_FEAR))) + if (!MON_MONFEAR(m_ptr) && !(r_ptr->flags3 & (RF3_NO_FEAR))) { - int percentage; - /* Percentage of fully healthy */ - percentage = (100L * m_ptr->hp) / m_ptr->maxhp; + int percentage = (100L * m_ptr->hp) / m_ptr->maxhp; /* * Run (sometimes) if at 10% or less of max hit points, @@ -2153,9 +2205,9 @@ msg_format("%s (*fear) = TRUE; /* XXX XXX XXX Hack -- Add some timed fear */ - m_ptr->monfear = (randint1(10) + + (void)set_monster_monfear(m_idx, (randint1(10) + (((dam >= m_ptr->hp) && (percentage > 7)) ? - 20 : ((11 - percentage) * 5))); + 20 : ((11 - percentage) * 5)))); } } @@ -2272,12 +2324,6 @@ void redraw_window(void) { /* Only if the dungeon exists */ if (!character_dungeon) return; - - /* Hack - Activate term zero for the redraw */ - Term_activate(&term_screen[0]); - - /* Hack -- react to changes */ - Term_xtra(TERM_XTRA_REACT, 0); /* Window stuff */ p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_SPELL | PW_PLAYER); @@ -2290,9 +2336,6 @@ void redraw_window(void) /* Redraw */ Term_redraw(); - - /* Refresh */ - Term_fresh(); } @@ -2350,6 +2393,24 @@ bool change_panel(int dy, int dx) return (FALSE); } +bool change_panel_xy(int y, int x) +{ + int dy = 0, dx = 0; + int wid, hgt; + + /* Get size */ + get_screen_size(&wid, &hgt); + + if (y < panel_row_min) dy = -1; + if (y > panel_row_max) dy = 1; + if (x < panel_col_min) dx = -1; + if (x > panel_col_max) dx = 1; + + if (!dy && !dx) return (FALSE); + + return change_panel(dy, dx); +} + /* * Given an row (y) and col (x), this routine detects when a move @@ -2738,7 +2799,6 @@ bool target_okay(void) } - /* * Sorting hook -- comp function -- by "distance to player" * @@ -2772,6 +2832,75 @@ static bool ang_sort_comp_distance(vptr u, vptr v, int a, int b) /* + * Sorting hook -- comp function -- by importance level of grids + * + * We use "u" and "v" to point to arrays of "x" and "y" positions, + * and sort the arrays by level of monster + */ +static bool ang_sort_comp_importance(vptr u, vptr v, int a, int b) +{ + byte *x = (byte*)(u); + byte *y = (byte*)(v); + cave_type *ca_ptr = &cave[y[a]][x[a]]; + cave_type *cb_ptr = &cave[y[b]][x[b]]; + monster_type *ma_ptr = &m_list[ca_ptr->m_idx]; + monster_type *mb_ptr = &m_list[cb_ptr->m_idx]; + monster_race *ap_ra_ptr, *ap_rb_ptr; + + /* The player grid */ + if (y[a] == py && x[a] == px) return TRUE; + if (y[b] == py && x[b] == px) return FALSE; + + /* Extract monster race */ + if (ca_ptr->m_idx && ma_ptr->ml) ap_ra_ptr = &r_info[ma_ptr->ap_r_idx]; + else ap_ra_ptr = NULL; + if (cb_ptr->m_idx && mb_ptr->ml) ap_rb_ptr = &r_info[mb_ptr->ap_r_idx]; + else ap_rb_ptr = NULL; + + if (ap_ra_ptr && !ap_rb_ptr) return TRUE; + if (!ap_ra_ptr && ap_rb_ptr) return FALSE; + + /* Compare two monsters */ + if (ap_ra_ptr && ap_rb_ptr) + { + /* Unique monsters first */ + if ((ap_ra_ptr->flags1 & RF1_UNIQUE) && !(ap_rb_ptr->flags1 & RF1_UNIQUE)) return TRUE; + if (!(ap_ra_ptr->flags1 & RF1_UNIQUE) && (ap_rb_ptr->flags1 & RF1_UNIQUE)) return FALSE; + + /* Shadowers first (¤¢¤ä¤·¤¤±Æ) */ + if ((ma_ptr->mflag2 & MFLAG2_KAGE) && !(mb_ptr->mflag2 & MFLAG2_KAGE)) return TRUE; + if (!(ma_ptr->mflag2 & MFLAG2_KAGE) && (mb_ptr->mflag2 & MFLAG2_KAGE)) return FALSE; + + /* Unknown monsters first */ + if (!ap_ra_ptr->r_tkills && ap_rb_ptr->r_tkills) return TRUE; + if (ap_ra_ptr->r_tkills && !ap_rb_ptr->r_tkills) return FALSE; + + /* Higher level monsters first (if known) */ + if (ap_ra_ptr->r_tkills && ap_rb_ptr->r_tkills) + { + if (ap_ra_ptr->level > ap_rb_ptr->level) return TRUE; + if (ap_ra_ptr->level < ap_rb_ptr->level) return FALSE; + } + + /* Sort by index if all conditions are same */ + if (ma_ptr->ap_r_idx > mb_ptr->ap_r_idx) return TRUE; + if (ma_ptr->ap_r_idx < mb_ptr->ap_r_idx) return FALSE; + } + + /* An object get higher priority */ + if (cave[y[a]][x[a]].o_idx && !cave[y[b]][x[b]].o_idx) return TRUE; + if (!cave[y[a]][x[a]].o_idx && cave[y[b]][x[b]].o_idx) return FALSE; + + /* Priority from the terrain */ + if (f_info[ca_ptr->feat].priority > f_info[cb_ptr->feat].priority) return TRUE; + if (f_info[ca_ptr->feat].priority < f_info[cb_ptr->feat].priority) return FALSE; + + /* If all conditions are same, compare distance */ + return ang_sort_comp_distance(u, v, a, b); +} + + +/* * Sorting hook -- swap function -- by "distance to player" * * We use "u" and "v" to point to arrays of "x" and "y" positions, @@ -2893,70 +3022,17 @@ static bool target_set_accept(int y, int x) next_o_idx = o_ptr->next_o_idx; /* Memorized object */ - if (o_ptr->marked) return (TRUE); + if (o_ptr->marked & OM_FOUND) return (TRUE); } /* Interesting memorized features */ if (c_ptr->info & (CAVE_MARK)) { - byte feat; - - /* Feature code (applying "mimic" field) */ - feat = c_ptr->mimic ? c_ptr->mimic : f_info[c_ptr->feat].mimic; - - /* Notice glyphs */ + /* Notice object features */ if (c_ptr->info & CAVE_OBJECT) return (TRUE); - /* Notice the Pattern */ - if ((feat <= FEAT_PATTERN_XTRA2) && - (feat >= FEAT_PATTERN_START)) - return (TRUE); - - /* Notice doors */ - if (feat == FEAT_OPEN) return (TRUE); - if (feat == FEAT_BROKEN) return (TRUE); - - /* Notice stairs */ - if (feat == FEAT_LESS) return (TRUE); - if (feat == FEAT_MORE) return (TRUE); - if (feat == FEAT_LESS_LESS) return (TRUE); - if (feat == FEAT_MORE_MORE) return (TRUE); - - /* Notice shops */ - if ((feat >= FEAT_SHOP_HEAD) && - (feat <= FEAT_SHOP_TAIL)) return (TRUE); - - if (feat == FEAT_MUSEUM) return (TRUE); - - /* Notice buildings -KMW- */ - if ((feat >= FEAT_BLDG_HEAD) && - (feat <= FEAT_BLDG_TAIL)) return (TRUE); - - /* Notice traps */ - if (is_trap(feat)) return (TRUE); - - /* Notice doors */ - if ((feat >= FEAT_DOOR_HEAD) && - (feat <= FEAT_DOOR_TAIL)) return (TRUE); - -#if 0 - /* Notice rubble */ - /* I think FEAT_RUBBLEs should not be "interesting" */ - if (feat == FEAT_RUBBLE) return (TRUE); - - /* Notice veins with treasure */ - /* Now veins with treasure are too many */ - if (feat == FEAT_MAGMA_K) return (TRUE); - if (feat == FEAT_QUARTZ_K) return (TRUE); -#endif - - /* Notice quest features */ - if (feat == FEAT_QUEST_ENTER) return (TRUE); - if (feat == FEAT_QUEST_EXIT) return (TRUE); - if (feat == FEAT_QUEST_DOWN) return (TRUE); - if (feat == FEAT_QUEST_UP) return (TRUE); - if (feat == FEAT_TOWN) return (TRUE); - if (feat == FEAT_ENTRANCE) return (TRUE); + /* Feature code (applying "mimic" field) */ + if (have_flag(f_info[get_feat_mimic(c_ptr)].flags, FF_NOTICE)) return TRUE; } /* Nope */ @@ -2972,20 +3048,35 @@ static bool target_set_accept(int y, int x) static void target_set_prepare(int mode) { int y, x; + int min_hgt, max_hgt, min_wid, max_wid; + + if (mode & TARGET_KILL) + { + /* Inner range */ + min_hgt = MAX((py - MAX_RANGE), 0); + max_hgt = MIN((py + MAX_RANGE), cur_hgt - 1); + min_wid = MAX((px - MAX_RANGE), 0); + max_wid = MIN((px + MAX_RANGE), cur_wid - 1); + } + else /* not targetting */ + { + /* Inner panel */ + min_hgt = panel_row_min; + max_hgt = panel_row_max; + min_wid = panel_col_min; + max_wid = panel_col_max; + } /* Reset "temp" array */ temp_n = 0; /* Scan the current panel */ - for (y = panel_row_min; y <= panel_row_max; y++) + for (y = min_hgt; y <= max_hgt; y++) { - for (x = panel_col_min; x <= panel_col_max; x++) + for (x = min_wid; x <= max_wid; x++) { cave_type *c_ptr; - /* Require line of sight, unless "look" is "expanded" */ - if (!expand_look && !player_has_los_bold(y, x)) continue; - /* Require "interesting" contents */ if (!target_set_accept(y, x)) continue; @@ -3004,8 +3095,18 @@ static void target_set_prepare(int mode) } /* Set the sort hooks */ - ang_sort_comp = ang_sort_comp_distance; - ang_sort_swap = ang_sort_swap_distance; + if (mode & (TARGET_KILL)) + { + /* Target the nearest monster for shooting */ + ang_sort_comp = ang_sort_comp_distance; + ang_sort_swap = ang_sort_swap_distance; + } + else + { + /* Look important grids first in Look command */ + ang_sort_comp = ang_sort_comp_importance; + ang_sort_swap = ang_sort_swap_distance; + } /* Sort the positions */ ang_sort(temp_x, temp_y, temp_n); @@ -3022,6 +3123,9 @@ static void target_set_prepare(int mode) temp_x[1] = tmp; } } +void target_set_prepare_look(){ + target_set_prepare(TARGET_LOOK); +} /* @@ -3029,62 +3133,58 @@ static void target_set_prepare(int mode) */ static void evaluate_monster_exp(char *buf, monster_type *m_ptr) { -#define M_INT_GREATER(h1,l1,h2,l2) ( (h1>h2)||( (h1==h2)&&(l1>=l2))) -#define M_INT_SUB(h1,l1, h2,l2) {h1-=h2;if(l1=0x10000L){l1&=0xFFFF;h1++;}} -#define M_INT_LSHIFT(h1,l1) {h1=(h1<<1)|(l1>>15);l1=(l1<<1)&0xffff;} -#define M_INT_RSHIFT(h1,l1) {l1=(l1>>1)|((h1&1)<<15);h1>>=1;} -#define M_INT_MULT(h1,l1,mul,h2,l2) {l2=(l1*mul)&0xffff;h2=((l1*mul)>>16)+h1*mul;} - monster_race *ap_r_ptr = &r_info[m_ptr->ap_r_idx]; + u32b num; + s32b exp_mon, exp_adv; + u32b exp_mon_frac, exp_adv_frac; - u32b tmp_h,tmp_l; - int bit,result; - u32b exp_mon= (ap_r_ptr->mexp)*(ap_r_ptr->level); - u32b exp_mon_h= exp_mon / (p_ptr->max_plv+2); - u32b exp_mon_l= ((exp_mon % (p_ptr->max_plv+2))*0x10000/(p_ptr->max_plv+2))&0xFFFF; - - u32b exp_adv_h = player_exp[p_ptr->lev -1] * p_ptr->expfact /100; - u32b exp_adv_l = ((player_exp[p_ptr->lev -1]%100) * p_ptr->expfact *0x10000/100)&0xFFFF; - - M_INT_SUB(exp_adv_h, exp_adv_l, p_ptr->exp, p_ptr->exp_frac); - if ((p_ptr->lev>=PY_MAX_LEVEL) || (p_ptr->prace == RACE_ANDROID)) + if ((p_ptr->lev >= PY_MAX_LEVEL) || (p_ptr->prace == RACE_ANDROID)) + { sprintf(buf,"**"); + return; + } else if (!ap_r_ptr->r_tkills || (m_ptr->mflag2 & MFLAG2_KAGE)) - sprintf(buf,"??"); - else if (M_INT_GREATER(exp_mon_h, exp_mon_l, exp_adv_h, exp_adv_l)) - sprintf(buf,"001"); - else { - M_INT_MULT(exp_mon_h, exp_mon_l, 1000,tmp_h, tmp_l); - if( M_INT_GREATER(exp_adv_h, exp_adv_l, tmp_h, tmp_l) ) - sprintf(buf,"999"); - else + if (!p_ptr->wizard) { - bit=1; result=0; - M_INT_ADD(exp_adv_h, exp_adv_l, exp_mon_h, exp_mon_l); - M_INT_SUB(exp_adv_h, exp_adv_l, 0, 1); - while(M_INT_GREATER(exp_adv_h, exp_adv_l, exp_mon_h,exp_mon_l)) - { - M_INT_LSHIFT(exp_mon_h,exp_mon_l); - bit <<= 1; - } - M_INT_RSHIFT(exp_mon_h,exp_mon_l);bit>>=1; - for(;bit>=1;bit>>=1) - { - if(M_INT_GREATER(exp_adv_h,exp_adv_l,exp_mon_h,exp_mon_l)) - { - result |= bit; - M_INT_SUB(exp_adv_h,exp_adv_l,exp_mon_h,exp_mon_l); - } - M_INT_RSHIFT(exp_mon_h,exp_mon_l); - } - sprintf(buf,"%03d",result); + sprintf(buf,"??"); + return; } } + + + /* The monster's experience point (assuming average monster speed) */ + exp_mon = ap_r_ptr->mexp * ap_r_ptr->level; + exp_mon_frac = 0; + s64b_div(&exp_mon, &exp_mon_frac, 0, (p_ptr->max_plv + 2)); + + + /* Total experience value for next level */ + exp_adv = player_exp[p_ptr->lev -1] * p_ptr->expfact; + exp_adv_frac = 0; + s64b_div(&exp_adv, &exp_adv_frac, 0, 100); + + /* Experience value need to get */ + s64b_sub(&exp_adv, &exp_adv_frac, p_ptr->exp, p_ptr->exp_frac); + + + /* You need to kill at least one monster to get any experience */ + s64b_add(&exp_adv, &exp_adv_frac, exp_mon, exp_mon_frac); + s64b_sub(&exp_adv, &exp_adv_frac, 0, 1); + + /* Extract number of monsters needed */ + s64b_div(&exp_adv, &exp_adv_frac, exp_mon, exp_mon_frac); + + /* If 999 or more monsters needed, only display "999". */ + num = MIN(999, exp_adv_frac); + + /* Display the number */ + sprintf(buf,"%03ld", (long int)num); } +bool show_gold_on_floor = FALSE; + /* * Examine a grid, return a keypress. * @@ -3112,7 +3212,8 @@ static int target_set_aux(int y, int x, int mode, cptr info) s16b this_o_idx, next_o_idx = 0; cptr s1 = "", s2 = "", s3 = "", x_info = ""; bool boring = TRUE; - byte feat; + s16b feat; + feature_type *f_ptr; int query = '\001'; char out_val[MAX_NLEN+80]; @@ -3326,7 +3427,7 @@ static int target_set_aux(int y, int x, int mode, cptr info) next_o_idx = o_ptr->next_o_idx; /* Obtain an object description */ - object_desc(o_name, o_ptr, TRUE, 3); + object_desc(o_name, o_ptr, 0); /* Describe the object */ #ifdef JP @@ -3380,7 +3481,7 @@ static int target_set_aux(int y, int x, int mode, cptr info) o_ptr = &o_list[floor_list[0]]; /* Describe the object */ - object_desc(o_name, o_ptr, TRUE, 3); + object_desc(o_name, o_ptr, 0); /* Message */ #ifdef JP @@ -3435,7 +3536,9 @@ static int target_set_aux(int y, int x, int mode, cptr info) screen_save(); /* Display */ + show_gold_on_floor = TRUE; (void)show_floor(0, y, x, &min_width); + show_gold_on_floor = FALSE; /* Prompt */ #ifdef JP @@ -3498,7 +3601,7 @@ static int target_set_aux(int y, int x, int mode, cptr info) next_o_idx = o_ptr->next_o_idx; /* Describe it */ - if (o_ptr->marked) + if (o_ptr->marked & OM_FOUND) { char o_name[MAX_NLEN]; @@ -3506,7 +3609,7 @@ static int target_set_aux(int y, int x, int mode, cptr info) boring = FALSE; /* Obtain an object description */ - object_desc(o_name, o_ptr, TRUE, 3); + object_desc(o_name, o_ptr, 0); /* Describe the object */ #ifdef JP @@ -3554,26 +3657,56 @@ static int target_set_aux(int y, int x, int mode, cptr info) /* Feature code (applying "mimic" field) */ - feat = c_ptr->mimic ? c_ptr->mimic : f_info[c_ptr->feat].mimic; + feat = get_feat_mimic(c_ptr); /* Require knowledge about grid, or ability to see grid */ if (!(c_ptr->info & CAVE_MARK) && !player_can_see_bold(y, x)) { /* Forget feature */ - feat = FEAT_NONE; + feat = feat_none; } + f_ptr = &f_info[feat]; + /* Terrain feature if needed */ - if (boring || (feat > FEAT_INVIS)) + if (boring || have_flag(f_ptr->flags, FF_REMEMBER)) { cptr name; + /* Hack -- special handling for quest entrances */ + if (have_flag(f_ptr->flags, FF_QUEST_ENTER)) + { + /* Set the quest number temporary */ + int old_quest = p_ptr->inside_quest; + int j; + + /* Clear the text */ + for (j = 0; j < 10; j++) quest_text[j][0] = '\0'; + quest_text_line = 0; + + p_ptr->inside_quest = c_ptr->special; + + /* Get the quest text */ + init_flags = INIT_NAME_ONLY; + + process_dungeon_file("q_info.txt", 0, 0, 0, 0); + +#ifdef JP + name = format("¥¯¥¨¥¹¥È¡Ö%s¡×(%d³¬ÁêÅö)", quest[c_ptr->special].name, quest[c_ptr->special].level); +#else + name = format("the entrance to the quest '%s'(level %d)", quest[c_ptr->special].name, quest[c_ptr->special].level); +#endif + + /* Reset the old quest number */ + p_ptr->inside_quest = old_quest; + } + /* Hack -- special handling for building doors */ - if ((feat >= FEAT_BLDG_HEAD) && (feat <= FEAT_BLDG_TAIL)) + else if (have_flag(f_ptr->flags, FF_BLDG) && !p_ptr->inside_arena) { - name = building[feat - FEAT_BLDG_HEAD].name; + name = building[f_ptr->subtype].name; } - else if (feat == FEAT_ENTRANCE) + else if (have_flag(f_ptr->flags, FF_ENTRANCE)) { #ifdef JP name = format("%s(%d³¬ÁêÅö)", d_text + d_info[c_ptr->special].text, d_info[c_ptr->special].mindepth); @@ -3581,11 +3714,11 @@ static int target_set_aux(int y, int x, int mode, cptr info) name = format("%s(level %d)", d_text + d_info[c_ptr->special].text, d_info[c_ptr->special].mindepth); #endif } - else if (feat == FEAT_TOWN) + else if (have_flag(f_ptr->flags, FF_TOWN)) { name = town[c_ptr->special].name; } - else if (p_ptr->wild_mode && (feat == FEAT_FLOOR)) + else if (p_ptr->wild_mode && (feat == feat_floor)) { #ifdef JP name = "Æ»"; @@ -3595,80 +3728,67 @@ static int target_set_aux(int y, int x, int mode, cptr info) } else { - name = f_name + f_info[feat].name; + name = f_name + f_ptr->name; } /* Pick a prefix */ - if (*s2 && ((feat >= FEAT_MINOR_GLYPH) && - (feat <= FEAT_PATTERN_XTRA2))) - { -#ifdef JP - s2 = "¤Î¾å"; -#else - s2 = "on "; -#endif - - } - else if (*s2 && ((feat >= FEAT_DOOR_HEAD) && - (feat <= FEAT_PERM_SOLID))) - { -#ifdef JP - s2 = "¤ÎÃæ"; -#else - s2 = "in "; -#endif - - } - else if (*s2 && (feat == FEAT_TOWN)) + if (*s2 && + ((!have_flag(f_ptr->flags, FF_MOVE) && !have_flag(f_ptr->flags, FF_CAN_FLY)) || + (!have_flag(f_ptr->flags, FF_LOS) && !have_flag(f_ptr->flags, FF_TREE)) || + have_flag(f_ptr->flags, FF_TOWN))) { #ifdef JP s2 = "¤ÎÃæ"; #else s2 = "in "; #endif - } /* Hack -- special introduction for store & building doors -KMW- */ - if (((feat >= FEAT_SHOP_HEAD) && (feat <= FEAT_SHOP_TAIL)) || - ((feat >= FEAT_BLDG_HEAD) && (feat <= FEAT_BLDG_TAIL)) || - (feat == FEAT_MUSEUM) || - (feat == FEAT_ENTRANCE)) + if (have_flag(f_ptr->flags, FF_STORE) || + have_flag(f_ptr->flags, FF_QUEST_ENTER) || + (have_flag(f_ptr->flags, FF_BLDG) && !p_ptr->inside_arena) || + have_flag(f_ptr->flags, FF_ENTRANCE)) { #ifdef JP s2 = "¤ÎÆþ¸ý"; #else s3 = ""; #endif - } - else if ((feat == FEAT_TOWN) || (feat == FEAT_FLOOR) || (feat == FEAT_DIRT) || (feat == FEAT_FLOWER)) - { #ifndef JP + else if (have_flag(f_ptr->flags, FF_FLOOR) || + have_flag(f_ptr->flags, FF_TOWN) || + have_flag(f_ptr->flags, FF_SHALLOW) || + have_flag(f_ptr->flags, FF_DEEP)) + { s3 =""; -#endif } else { /* Pick proper indefinite article */ -#ifndef JP s3 = (is_a_vowel(name[0])) ? "an " : "a "; -#endif } +#endif /* Display a message */ if (p_ptr->wizard) + { + char f_idx_str[32]; + if (c_ptr->mimic) sprintf(f_idx_str, "%d/%d", c_ptr->feat, c_ptr->mimic); + else sprintf(f_idx_str, "%d", c_ptr->feat); #ifdef JP - sprintf(out_val, "%s%s%s%s[%s] %x %d %d %d %d (%d,%d)", s1, name, s2, s3, info, c_ptr->info, c_ptr->feat, c_ptr->dist, c_ptr->cost, c_ptr->when, x, y); + sprintf(out_val, "%s%s%s%s[%s] %x %s %d %d %d (%d,%d) %d", s1, name, s2, s3, info, c_ptr->info, f_idx_str, c_ptr->dist, c_ptr->cost, c_ptr->when, y, x, travel.cost[y][x]); #else - sprintf(out_val, "%s%s%s%s [%s] %x %d %d %d %d (%d,%d)", s1, s2, s3, name, info, c_ptr->info, c_ptr->feat, c_ptr->dist, c_ptr->cost, c_ptr->when, x, y); + sprintf(out_val, "%s%s%s%s [%s] %x %s %d %d %d (%d,%d)", s1, s2, s3, name, info, c_ptr->info, f_idx_str, c_ptr->dist, c_ptr->cost, c_ptr->when, y, x); #endif + } else #ifdef JP sprintf(out_val, "%s%s%s%s[%s]", s1, name, s2, s3, info); #else - sprintf(out_val, "%s%s%s%s [%s]", s1, s2, s3, name, info); + sprintf(out_val, "%s%s%s%s [%s]", s1, s2, s3, name, info); #endif prt(out_val, 0, 0); @@ -3745,8 +3865,7 @@ bool target_set(int mode) cave_type *c_ptr; int wid, hgt; - - + /* Get size */ get_screen_size(&wid, &hgt); @@ -3773,6 +3892,9 @@ bool target_set(int mode) y = temp_y[m]; x = temp_x[m]; + /* Set forcus */ + change_panel_xy(y, x); + if (!(mode & TARGET_LOOK)) prt_path(y, x); /* Access */ @@ -3799,9 +3921,12 @@ strcpy(info, "q #endif } - + /* Describe and Prompt */ - while (!(query = target_set_aux(y, x, mode, info))); + while (TRUE){ + query = target_set_aux(y, x, mode, info); + if(query)break; + } /* Cancel tracking */ /* health_track(0); */ @@ -4397,6 +4522,7 @@ msg_print(" bool get_rep_dir(int *dp, bool under) { int dir; + cptr prompt; /* Initialize */ (*dp) = 0; @@ -4414,24 +4540,36 @@ bool get_rep_dir(int *dp, bool under) #endif /* ALLOW_REPEAT -- TNB */ + if (under) + { + prompt = _("Êý¸þ ('.'­¸µ, ESC¤ÇÃæÃÇ)? ", "Direction ('.' at feet, Escape to cancel)? "); + } + else + { + prompt = _("Êý¸þ (ESC¤ÇÃæÃÇ)? ", "Direction (Escape to cancel)? "); + } + /* Get a direction */ while (!dir) { char ch; /* Get a command (or Cancel) */ -#ifdef JP -if (!get_com("Êý¸þ (ESC¤ÇÃæÃÇ)? ", &ch, TRUE)) break; -#else - if (!get_com("Direction (Escape to cancel)? ", &ch, TRUE)) break; -#endif + if (!get_com(prompt, &ch, TRUE)) break; + /* Look down */ + if ((under) && ((ch == '5') || (ch == '-') || (ch == '.'))) + { + dir = 5; + } + else + { + /* Look up the direction */ + dir = get_keymap_dir(ch); - /* Look up the direction */ - dir = get_keymap_dir(ch); - - /* Oops */ - if (!dir) bell(); + /* Oops */ + if (!dir) bell(); + } } /* Prevent weirdness */ @@ -4458,7 +4596,7 @@ if (!get_com(" monster_type *m_ptr = &m_list[p_ptr->riding]; monster_race *r_ptr = &r_info[m_ptr->r_idx]; - if (m_ptr->confused) + if (MON_CONFUSED(m_ptr)) { /* Standard confusion */ if (randint0(100) < 75) @@ -4497,7 +4635,7 @@ msg_print(" monster_type *m_ptr = &m_list[p_ptr->riding]; monster_desc(m_name, m_ptr, 0); - if (m_ptr->confused) + if (MON_CONFUSED(m_ptr)) { #ifdef JP msg_format("%s¤Ïº®Í𤷤Ƥ¤¤ë¡£", m_name); @@ -4618,13 +4756,6 @@ msg_print(" return (TRUE); } - -int get_chaos_patron(void) -{ - return ((p_ptr->age + p_ptr->sc) % MAX_PATRON); -} - - void gain_level_reward(int chosen_reward) { object_type *q_ptr; @@ -5259,7 +5390,7 @@ msg_print(" #endif break; case REW_CURSE_WP: - if (!buki_motteruka(INVEN_RARM)) break; + if (!buki_motteruka(INVEN_RARM) && !buki_motteruka(INVEN_LARM)) break; #ifdef JP msg_format("%s¤ÎÀ¼¤¬¶Á¤­ÅϤä¿:", chaos_patrons[p_ptr->chaos_patron]); @@ -5274,8 +5405,14 @@ msg_print(" msg_print("'Thou reliest too much on thy weapon.'"); #endif - object_desc(o_name, &inventory[INVEN_RARM], TRUE, 0); - (void)curse_weapon(FALSE, INVEN_RARM); + dummy = INVEN_RARM; + if (buki_motteruka(INVEN_LARM)) + { + dummy = INVEN_LARM; + if (buki_motteruka(INVEN_RARM) && one_in_(2)) dummy = INVEN_RARM; + } + object_desc(o_name, &inventory[dummy], OD_NAME_ONLY); + (void)curse_weapon(FALSE, dummy); #ifdef JP reward = format("%s¤¬Ç˲õ¤µ¤ì¤¿¡£", o_name); #else @@ -5298,7 +5435,7 @@ msg_print(" msg_print("'Thou reliest too much on thine equipment.'"); #endif - object_desc(o_name, &inventory[INVEN_BODY], TRUE, 0); + object_desc(o_name, &inventory[INVEN_BODY], OD_NAME_ONLY); (void)curse_armor(); #ifdef JP reward = format("%s¤¬Ç˲õ¤µ¤ì¤¿¡£", o_name); @@ -5342,9 +5479,15 @@ msg_print(" case 3: if (one_in_(2)) { - if (!buki_motteruka(INVEN_RARM)) break; - object_desc(o_name, &inventory[INVEN_RARM], TRUE, 0); - (void)curse_weapon(FALSE, INVEN_RARM); + if (!buki_motteruka(INVEN_RARM) && !buki_motteruka(INVEN_LARM)) break; + dummy = INVEN_RARM; + if (buki_motteruka(INVEN_LARM)) + { + dummy = INVEN_LARM; + if (buki_motteruka(INVEN_RARM) && one_in_(2)) dummy = INVEN_RARM; + } + object_desc(o_name, &inventory[dummy], OD_NAME_ONLY); + (void)curse_weapon(FALSE, dummy); #ifdef JP reward = format("%s¤¬Ç˲õ¤µ¤ì¤¿¡£", o_name); #else @@ -5354,7 +5497,7 @@ msg_print(" else { if (!inventory[INVEN_BODY].k_idx) break; - object_desc(o_name, &inventory[INVEN_BODY], TRUE, 0); + object_desc(o_name, &inventory[INVEN_BODY], OD_NAME_ONLY); (void)curse_armor(); #ifdef JP reward = format("%s¤¬Ç˲õ¤µ¤ì¤¿¡£", o_name); @@ -5397,7 +5540,19 @@ msg_print(" } activate_hi_summon(py, px, FALSE); (void)activate_ty_curse(FALSE, &count); - if (one_in_(2)) (void)curse_weapon(FALSE, INVEN_RARM); + if (one_in_(2)) + { + dummy = 0; + + if (buki_motteruka(INVEN_RARM)) + { + dummy = INVEN_RARM; + if (buki_motteruka(INVEN_LARM) && one_in_(2)) dummy = INVEN_LARM; + } + else if (buki_motteruka(INVEN_LARM)) dummy = INVEN_LARM; + + if (dummy) (void)curse_weapon(FALSE, dummy); + } if (one_in_(2)) (void)curse_armor(); break; case REW_DESTRUCT: @@ -5578,12 +5733,85 @@ msg_format(" /* + * XAngband: determine if a given location is "interesting" + * based on target_set_accept function. + */ +static bool tgt_pt_accept(int y, int x) +{ + cave_type *c_ptr; + + /* Bounds */ + if (!(in_bounds(y, x))) return (FALSE); + + /* Player grid is always interesting */ + if ((y == py) && (x == px)) return (TRUE); + + /* Handle hallucination */ + if (p_ptr->image) return (FALSE); + + /* Examine the grid */ + c_ptr = &cave[y][x]; + + /* Interesting memorized features */ + if (c_ptr->info & (CAVE_MARK)) + { + /* Notice stairs */ + if (cave_have_flag_grid(c_ptr, FF_LESS)) return (TRUE); + if (cave_have_flag_grid(c_ptr, FF_MORE)) return (TRUE); + + /* Notice quest features */ + if (cave_have_flag_grid(c_ptr, FF_QUEST_ENTER)) return (TRUE); + if (cave_have_flag_grid(c_ptr, FF_QUEST_EXIT)) return (TRUE); + } + + /* Nope */ + return (FALSE); +} + + +/* + * XAngband: Prepare the "temp" array for "tget_pt" + * based on target_set_prepare funciton. + */ +static void tgt_pt_prepare(void) +{ + int y, x; + + /* Reset "temp" array */ + temp_n = 0; + + if (!expand_list) return; + + /* Scan the current panel */ + for (y = 1; y < cur_hgt; y++) + { + for (x = 1; x < cur_wid; x++) + { + /* Require "interesting" contents */ + if (!tgt_pt_accept(y, x)) continue; + + /* Save the location */ + temp_x[temp_n] = x; + temp_y[temp_n] = y; + temp_n++; + } + } + + /* Target the nearest monster for shooting */ + 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); +} + +/* * old -- from PsiAngband. */ bool tgt_pt(int *x_ptr, int *y_ptr) { char ch = 0; - int d, x, y; + int d, x, y, n; bool success = FALSE; int wid, hgt; @@ -5594,8 +5822,14 @@ bool tgt_pt(int *x_ptr, int *y_ptr) x = px; y = py; + if (expand_list) + { + tgt_pt_prepare(); + n = 0; + } + #ifdef JP -msg_print("¾ì½ê¤òÁª¤ó¤Ç¥¹¥Ú¡¼¥¹¥­¡¼¤ò²¡¤·¤Æ²¼¤µ¤¤¡£"); + msg_print("¾ì½ê¤òÁª¤ó¤Ç¥¹¥Ú¡¼¥¹¥­¡¼¤ò²¡¤·¤Æ²¼¤µ¤¤¡£"); #else msg_print("Select a point and press space."); #endif @@ -5623,6 +5857,62 @@ msg_print(" else success = TRUE; break; + + /* XAngband: Move cursor to stairs */ + case '>': + case '<': + if (expand_list && temp_n) + { + int dx, dy; + int cx = (panel_col_min + panel_col_max) / 2; + int cy = (panel_row_min + panel_row_max) / 2; + + n++; + + /* Skip stairs which have defferent distance */ + for (; n < temp_n; ++ n) + { + cave_type *c_ptr = &cave[temp_y[n]][temp_x[n]]; + + if (cave_have_flag_grid(c_ptr, FF_STAIRS) && + cave_have_flag_grid(c_ptr, ch == '>' ? FF_MORE : FF_LESS)) + { + /* Found */ + break; + } + } + + if (n == temp_n) /* Loop out taget list */ + { + n = 0; + y = py; + x = px; + verify_panel(); /* Move cursor to player */ + + /* Update stuff */ + p_ptr->update |= (PU_MONSTERS); + + /* Redraw map */ + p_ptr->redraw |= (PR_MAP); + + /* Window stuff */ + p_ptr->window |= (PW_OVERHEAD); + + /* Handle stuff */ + handle_stuff(); + } + else /* move cursor to next stair and change panel */ + { + y = temp_y[n]; + x = temp_x[n]; + + dy = 2 * (y - cy) / hgt; + dx = 2 * (x - cx) / wid; + if (dy || dx) change_panel(dy, dx); + } + } + break; + default: /* Look up the direction */ d = get_keymap_dir(ch); @@ -6025,3 +6315,166 @@ int spell_exp_level(int spell_exp) else if (spell_exp < SPELL_EXP_MASTER) return EXP_LEVEL_EXPERT; else return EXP_LEVEL_MASTER; } + + +/* + * Display a rumor and apply its effects + */ + +int rumor_num(char *zz, int max_idx) +{ + if (strcmp(zz, "*") == 0) return randint1(max_idx - 1); + return atoi(zz); +} + +cptr rumor_bind_name(char *base, cptr fullname) +{ + char *s, *v; + + s = strstr(base, "{Name}"); + if (s) + { + s[0] = '\0'; + v = format("%s%s%s", base, fullname, (s + 6)); + } + else + { + v = base; + } + + return v; +} + +void display_rumor(bool ex) +{ + bool err; + int section = 0; + char Rumor[1024]; + + if (ex) + { + if (randint0(3) == 0) section = 1; + } + +#ifdef JP + err = get_rnd_line_jonly("rumors_j.txt", section, Rumor, 10); + if (err) strcpy(Rumor, "±³¤Î±½¤â¤¢¤ë¡£"); +#else + err = get_rnd_line("rumors.txt", section, Rumor); + if (err) strcpy(Rumor, "Some rumors are wrong."); +#endif + + err = TRUE; + + if (strncmp(Rumor, "R:", 2) == 0) + { + char *zz[4]; + cptr rumor_msg = NULL; + cptr rumor_eff_format = NULL; + char fullname[1024] = ""; + + if (tokenize(Rumor + 2, 3, zz, TOKENIZE_CHECKQUOTE) == 3) + { + if (strcmp(zz[0], "ARTIFACT") == 0) + { + int a_idx, k_idx; + object_type forge; + object_type *q_ptr = &forge; + artifact_type *a_ptr; + + while (1) + { + a_idx = rumor_num(zz[1], max_a_idx); + + a_ptr = &a_info[a_idx]; + if (a_ptr->name) break; + } + + k_idx = lookup_kind(a_ptr->tval, a_ptr->sval); + object_prep(q_ptr, k_idx); + q_ptr->name1 = a_idx; + q_ptr->ident = IDENT_STORE; + object_desc(fullname, q_ptr, OD_NAME_ONLY); + } + else if (strcmp(zz[0], "MONSTER") == 0) + { + int r_idx; + monster_race *r_ptr; + + while(1) + { + r_idx = rumor_num(zz[1], max_r_idx); + r_ptr = &r_info[r_idx]; + if (r_ptr->name) break; + } + + strcpy(fullname, r_name + r_ptr->name); + + /* Remember this monster */ + if (!r_ptr->r_sights) + { + r_ptr->r_sights++; + } + } + else if (strcmp(zz[0], "DUNGEON") == 0) + { + int d_idx; + dungeon_info_type *d_ptr; + + while (1) + { + d_idx = rumor_num(zz[1], max_d_idx); + d_ptr = &d_info[d_idx]; + if (d_ptr->name) break; + } + + strcpy(fullname, d_name + d_ptr->name); + + if (!max_dlv[d_idx]) + { + max_dlv[d_idx] = d_ptr->mindepth; + rumor_eff_format = _("%s¤Ëµ¢´Ô¤Ç¤­¤ë¤è¤¦¤Ë¤Ê¤Ã¤¿¡£", "You can recall to %s."); + } + } + else if (strcmp(zz[0], "TOWN") == 0) + { + int t_idx; + s32b visit; + + while(1) + { + t_idx = rumor_num(zz[1], NO_TOWN); + if (town[t_idx].name) break; + } + + strcpy(fullname, town[t_idx].name); + + visit = (1L << (t_idx - 1)); + if ((t_idx != SECRET_TOWN) && !(p_ptr->visit & visit)) + { + p_ptr->visit |= visit; + rumor_eff_format = _("%s¤Ë¹Ô¤Ã¤¿¤³¤È¤¬¤¢¤ëµ¤¤¬¤¹¤ë¡£", "You feel you have been to %s."); + } + } + + rumor_msg = rumor_bind_name(zz[2], fullname); + msg_print(rumor_msg); + if (rumor_eff_format) + { + msg_print(NULL); + msg_format(rumor_eff_format, fullname); + } + err = FALSE; + } + /* error */ +#ifdef JP + if (err) msg_print("¤³¤Î¾ðÊó¤Ï´Ö°ã¤Ã¤Æ¤¤¤ë¡£"); +#else + if (err) msg_print("This information is wrong."); +#endif + } + else + { + msg_format("%s", Rumor); + } +}