-\r
-extern void chest_death(bool scatter, POSITION y, POSITION x, OBJECT_IDX o_idx);\r
-extern void chest_trap(POSITION y, POSITION x, OBJECT_IDX o_idx);\r
-\r
+
+extern void chest_death(bool scatter, POSITION y, POSITION x, OBJECT_IDX o_idx);
+extern void chest_trap(POSITION y, POSITION x, OBJECT_IDX o_idx);
+
-/*!\r
- * @file cmd-eat.c\r
- * @brief プレイヤーの食べるコマンド実装\r
- * @date 2018/09/07\r
- * @details\r
- * cmd6.cより分離。\r
- */\r
-\r
-\r
-#include "angband.h"\r
-#include "object-hook.h"\r
-#include "avatar.h"\r
-#include "spells-status.h"\r
-#include "realm-hex.h"\r
-#include "player-status.h"\r
-\r
-/*!\r
- * @brief 食料を食べるコマンドのサブルーチン\r
- * @param item 食べるオブジェクトの所持品ID\r
- * @return なし\r
- */\r
-void do_cmd_eat_food_aux(INVENTORY_IDX item)\r
-{\r
- int ident, lev;\r
- object_type *o_ptr;\r
-\r
- if (music_singing_any()) stop_singing();\r
- if (hex_spelling_any()) stop_hex_spell_all();\r
-\r
- /* Get the item (in the pack) */\r
- if (item >= 0)\r
- {\r
- o_ptr = &inventory[item];\r
- }\r
-\r
- /* Get the item (on the floor) */\r
- else\r
- {\r
- o_ptr = &o_list[0 - item];\r
- }\r
-\r
- sound(SOUND_EAT);\r
-\r
- take_turn(p_ptr, 100);;\r
-\r
- /* Identity not known yet */\r
- ident = FALSE;\r
-\r
- /* Object level */\r
- lev = k_info[o_ptr->k_idx].level;\r
-\r
- if (o_ptr->tval == TV_FOOD)\r
- {\r
- /* Analyze the food */\r
- switch (o_ptr->sval)\r
- {\r
- case SV_FOOD_POISON:\r
- {\r
- if (!(p_ptr->resist_pois || IS_OPPOSE_POIS()))\r
- {\r
- if (set_poisoned(p_ptr->poisoned + randint0(10) + 10))\r
- {\r
- ident = TRUE;\r
- }\r
- }\r
- break;\r
- }\r
-\r
- case SV_FOOD_BLINDNESS:\r
- {\r
- if (!p_ptr->resist_blind)\r
- {\r
- if (set_blind(p_ptr->blind + randint0(200) + 200))\r
- {\r
- ident = TRUE;\r
- }\r
- }\r
- break;\r
- }\r
-\r
- case SV_FOOD_PARANOIA:\r
- {\r
- if (!p_ptr->resist_fear)\r
- {\r
- if (set_afraid(p_ptr->afraid + randint0(10) + 10))\r
- {\r
- ident = TRUE;\r
- }\r
- }\r
- break;\r
- }\r
-\r
- case SV_FOOD_CONFUSION:\r
- {\r
- if (!p_ptr->resist_conf)\r
- {\r
- if (set_confused(p_ptr->confused + randint0(10) + 10))\r
- {\r
- ident = TRUE;\r
- }\r
- }\r
- break;\r
- }\r
-\r
- case SV_FOOD_HALLUCINATION:\r
- {\r
- if (!p_ptr->resist_chaos)\r
- {\r
- if (set_image(p_ptr->image + randint0(250) + 250))\r
- {\r
- ident = TRUE;\r
- }\r
- }\r
- break;\r
- }\r
-\r
- case SV_FOOD_PARALYSIS:\r
- {\r
- if (!p_ptr->free_act)\r
- {\r
- if (set_paralyzed(p_ptr->paralyzed + randint0(10) + 10))\r
- {\r
- ident = TRUE;\r
- }\r
- }\r
- break;\r
- }\r
-\r
- case SV_FOOD_WEAKNESS:\r
- {\r
- take_hit(DAMAGE_NOESCAPE, damroll(6, 6), _("毒入り食料", "poisonous food"), -1);\r
- (void)do_dec_stat(A_STR);\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_FOOD_SICKNESS:\r
- {\r
- take_hit(DAMAGE_NOESCAPE, damroll(6, 6), _("毒入り食料", "poisonous food"), -1);\r
- (void)do_dec_stat(A_CON);\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_FOOD_STUPIDITY:\r
- {\r
- take_hit(DAMAGE_NOESCAPE, damroll(8, 8), _("毒入り食料", "poisonous food"), -1);\r
- (void)do_dec_stat(A_INT);\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_FOOD_NAIVETY:\r
- {\r
- take_hit(DAMAGE_NOESCAPE, damroll(8, 8), _("毒入り食料", "poisonous food"), -1);\r
- (void)do_dec_stat(A_WIS);\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_FOOD_UNHEALTH:\r
- {\r
- take_hit(DAMAGE_NOESCAPE, damroll(10, 10), _("毒入り食料", "poisonous food"), -1);\r
- (void)do_dec_stat(A_CON);\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_FOOD_DISEASE:\r
- {\r
- take_hit(DAMAGE_NOESCAPE, damroll(10, 10), _("毒入り食料", "poisonous food"), -1);\r
- (void)do_dec_stat(A_STR);\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_FOOD_CURE_POISON:\r
- {\r
- if (set_poisoned(0)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_FOOD_CURE_BLINDNESS:\r
- {\r
- if (set_blind(0)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_FOOD_CURE_PARANOIA:\r
- {\r
- if (set_afraid(0)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_FOOD_CURE_CONFUSION:\r
- {\r
- if (set_confused(0)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_FOOD_CURE_SERIOUS:\r
- {\r
- ident = cure_serious_wounds(4, 8);\r
- break;\r
- }\r
-\r
- case SV_FOOD_RESTORE_STR:\r
- {\r
- if (do_res_stat(A_STR)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_FOOD_RESTORE_CON:\r
- {\r
- if (do_res_stat(A_CON)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_FOOD_RESTORING:\r
- {\r
- ident = restore_all_status();\r
- break;\r
- }\r
-\r
-\r
-#ifdef JP\r
- /* それぞれの食べ物の感想をオリジナルより細かく表現 */\r
- case SV_FOOD_BISCUIT:\r
- {\r
- msg_print("甘くてサクサクしてとてもおいしい。");\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_FOOD_JERKY:\r
- {\r
- msg_print("歯ごたえがあっておいしい。");\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_FOOD_SLIME_MOLD:\r
- {\r
- msg_print("これはなんとも形容しがたい味だ。");\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_FOOD_RATION:\r
- {\r
- msg_print("これはおいしい。");\r
- ident = TRUE;\r
- break;\r
- }\r
-#else\r
- case SV_FOOD_RATION:\r
- case SV_FOOD_BISCUIT:\r
- case SV_FOOD_JERKY:\r
- case SV_FOOD_SLIME_MOLD:\r
- {\r
- msg_print("That tastes good.");\r
- ident = TRUE;\r
- break;\r
- }\r
-#endif\r
-\r
-\r
- case SV_FOOD_WAYBREAD:\r
- {\r
- msg_print(_("これはひじょうに美味だ。", "That tastes good."));\r
- (void)set_poisoned(0);\r
- (void)hp_player(damroll(4, 8));\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
-#ifdef JP\r
- case SV_FOOD_PINT_OF_ALE:\r
- {\r
- msg_print("のどごし爽やかだ。");\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_FOOD_PINT_OF_WINE:\r
- {\r
- msg_print("That tastes good.");\r
- ident = TRUE;\r
- break;\r
- }\r
-#else\r
- case SV_FOOD_PINT_OF_ALE:\r
- case SV_FOOD_PINT_OF_WINE:\r
- {\r
- msg_print("That tastes good.");\r
- ident = TRUE;\r
- break;\r
- }\r
-#endif\r
-\r
- }\r
- }\r
- p_ptr->update |= (PU_COMBINE | PU_REORDER);\r
-\r
- if (!(object_is_aware(o_ptr)))\r
- {\r
- chg_virtue(V_KNOWLEDGE, -1);\r
- chg_virtue(V_PATIENCE, -1);\r
- chg_virtue(V_CHANCE, 1);\r
- }\r
-\r
- /* We have tried it */\r
- if (o_ptr->tval == TV_FOOD) object_tried(o_ptr);\r
-\r
- /* The player is now aware of the object */\r
- if (ident && !object_is_aware(o_ptr))\r
- {\r
- object_aware(o_ptr);\r
- gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev);\r
- }\r
-\r
- p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);\r
-\r
-\r
- /* Food can feed the player */\r
- if (prace_is_(RACE_VAMPIRE) || (p_ptr->mimic_form == MIMIC_VAMPIRE))\r
- {\r
- /* Reduced nutritional benefit */\r
- (void)set_food(p_ptr->food + (o_ptr->pval / 10));\r
- msg_print(_("あなたのような者にとって食糧など僅かな栄養にしかならない。",\r
- "Mere victuals hold scant sustenance for a being such as yourself."));\r
-\r
- if (p_ptr->food < PY_FOOD_ALERT) /* Hungry */\r
- msg_print(_("あなたの飢えは新鮮な血によってのみ満たされる!",\r
- "Your hunger can only be satisfied with fresh blood!"));\r
- }\r
- else if ((prace_is_(RACE_SKELETON) ||\r
- prace_is_(RACE_GOLEM) ||\r
- prace_is_(RACE_ZOMBIE) ||\r
- prace_is_(RACE_SPECTRE)) &&\r
- (o_ptr->tval == TV_STAFF || o_ptr->tval == TV_WAND))\r
- {\r
- concptr staff;\r
-\r
- if (o_ptr->tval == TV_STAFF &&\r
- (item < 0) && (o_ptr->number > 1))\r
- {\r
- msg_print(_("まずは杖を拾わなければ。", "You must first pick up the staffs."));\r
- return;\r
- }\r
- staff = (o_ptr->tval == TV_STAFF) ? _("杖", "staff") : _("魔法棒", "wand");\r
-\r
- /* "Eat" charges */\r
- if (o_ptr->pval == 0)\r
- {\r
- msg_format(_("この%sにはもう魔力が残っていない。", "The %s has no charges left."), staff);\r
- o_ptr->ident |= (IDENT_EMPTY);\r
- p_ptr->update |= (PU_COMBINE | PU_REORDER);\r
- p_ptr->window |= (PW_INVEN);\r
-\r
- return;\r
- }\r
- msg_format(_("あなたは%sの魔力をエネルギー源として吸収した。", "You absorb mana of the %s as your energy."), staff);\r
-\r
- /* Use a single charge */\r
- o_ptr->pval--;\r
-\r
- /* Eat a charge */\r
- set_food(p_ptr->food + 5000);\r
-\r
- /* XXX Hack -- unstack if necessary */\r
- if (o_ptr->tval == TV_STAFF &&\r
- (item >= 0) && (o_ptr->number > 1))\r
- {\r
- object_type forge;\r
- object_type *q_ptr;\r
- q_ptr = &forge;\r
-\r
- /* Obtain a local object */\r
- object_copy(q_ptr, o_ptr);\r
-\r
- /* Modify quantity */\r
- q_ptr->number = 1;\r
-\r
- /* Restore the charges */\r
- o_ptr->pval++;\r
-\r
- /* Unstack the used item */\r
- o_ptr->number--;\r
- p_ptr->total_weight -= q_ptr->weight;\r
- item = inven_carry(q_ptr);\r
-\r
- msg_format(_("杖をまとめなおした。", "You unstack your staff."));\r
- }\r
-\r
- /* Describe charges in the pack */\r
- if (item >= 0)\r
- {\r
- inven_item_charges(item);\r
- }\r
-\r
- /* Describe charges on the floor */\r
- else\r
- {\r
- floor_item_charges(0 - item);\r
- }\r
-\r
- p_ptr->window |= (PW_INVEN | PW_EQUIP);\r
-\r
- /* Don't eat a staff/wand itself */\r
- return;\r
- }\r
- else if ((prace_is_(RACE_DEMON) ||\r
- (mimic_info[p_ptr->mimic_form].MIMIC_FLAGS & MIMIC_IS_DEMON)) &&\r
- (o_ptr->tval == TV_CORPSE && o_ptr->sval == SV_CORPSE &&\r
- my_strchr("pht", r_info[o_ptr->pval].d_char)))\r
- {\r
- /* Drain vitality of humanoids */\r
- GAME_TEXT o_name[MAX_NLEN];\r
- object_desc(o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));\r
- msg_format(_("%sは燃え上り灰になった。精力を吸収した気がする。", "%^s is burnt to ashes. You absorb its vitality!"), o_name);\r
- (void)set_food(PY_FOOD_MAX - 1);\r
- }\r
- else if (prace_is_(RACE_SKELETON))\r
- {\r
-#if 0\r
- if (o_ptr->tval == TV_SKELETON ||\r
- (o_ptr->tval == TV_CORPSE && o_ptr->sval == SV_SKELETON))\r
- {\r
- msg_print(_("あなたは骨で自分の体を補った。", "Your body absorbs the bone."));\r
- set_food(p_ptr->food + 5000);\r
- }\r
- else\r
-#endif\r
-\r
- if (!((o_ptr->sval == SV_FOOD_WAYBREAD) ||\r
- (o_ptr->sval < SV_FOOD_BISCUIT)))\r
- {\r
- object_type forge;\r
- object_type *q_ptr = &forge;\r
-\r
- msg_print(_("食べ物がアゴを素通りして落ちた!", "The food falls through your jaws!"));\r
- object_prep(q_ptr, lookup_kind(o_ptr->tval, o_ptr->sval));\r
-\r
- /* Drop the object from heaven */\r
- (void)drop_near(q_ptr, -1, p_ptr->y, p_ptr->x);\r
- }\r
- else\r
- {\r
- msg_print(_("食べ物がアゴを素通りして落ち、消えた!", "The food falls through your jaws and vanishes!"));\r
- }\r
- }\r
- else if (prace_is_(RACE_GOLEM) ||\r
- prace_is_(RACE_ZOMBIE) ||\r
- prace_is_(RACE_ENT) ||\r
- prace_is_(RACE_DEMON) ||\r
- prace_is_(RACE_ANDROID) ||\r
- prace_is_(RACE_SPECTRE) ||\r
- (mimic_info[p_ptr->mimic_form].MIMIC_FLAGS & MIMIC_IS_NONLIVING))\r
- {\r
- msg_print(_("生者の食物はあなたにとってほとんど栄養にならない。", "The food of mortals is poor sustenance for you."));\r
- set_food(p_ptr->food + ((o_ptr->pval) / 20));\r
- }\r
- else if (o_ptr->tval == TV_FOOD && o_ptr->sval == SV_FOOD_WAYBREAD)\r
- {\r
- /* Waybread is always fully satisfying. */\r
- set_food(MAX(p_ptr->food, PY_FOOD_MAX - 1));\r
- }\r
- else\r
- {\r
- /* Food can feed the player */\r
- (void)set_food(p_ptr->food + o_ptr->pval);\r
- }\r
-\r
- /* Destroy a food in the pack */\r
- if (item >= 0)\r
- {\r
- inven_item_increase(item, -1);\r
- inven_item_describe(item);\r
- inven_item_optimize(item);\r
- }\r
-\r
- /* Destroy a food on the floor */\r
- else\r
- {\r
- floor_item_increase(0 - item, -1);\r
- floor_item_describe(0 - item);\r
- floor_item_optimize(0 - item);\r
- }\r
-}\r
-\r
-\r
-/*!\r
- * @brief 食料を食べるコマンドのメインルーチン /\r
- * Eat some food (from the pack or floor)\r
- * @return なし\r
- */\r
-void do_cmd_eat_food(void)\r
-{\r
- OBJECT_IDX item;\r
- concptr q, s;\r
-\r
- if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN))\r
- {\r
- set_action(ACTION_NONE);\r
- }\r
-\r
- /* Restrict choices to food */\r
- item_tester_hook = item_tester_hook_eatable;\r
-\r
- q = _("どれを食べますか? ", "Eat which item? ");\r
- s = _("食べ物がない。", "You have nothing to eat.");\r
-\r
- if (!choose_object(&item, q, s, (USE_INVEN | USE_FLOOR))) return;\r
-\r
- /* Eat the object */\r
- do_cmd_eat_food_aux(item);\r
-}\r
-\r
+/*!
+ * @file cmd-eat.c
+ * @brief プレイヤーの食べるコマンド実装
+ * @date 2018/09/07
+ * @details
+ * cmd6.cより分離。
+ */
+
+
+#include "angband.h"
+#include "object-hook.h"
+#include "avatar.h"
+#include "spells-status.h"
+#include "realm-hex.h"
+#include "player-status.h"
+
+/*!
+ * @brief 食料を食べるコマンドのサブルーチン
+ * @param item 食べるオブジェクトの所持品ID
+ * @return なし
+ */
+void do_cmd_eat_food_aux(INVENTORY_IDX item)
+{
+ int ident, lev;
+ object_type *o_ptr;
+
+ if (music_singing_any()) stop_singing();
+ if (hex_spelling_any()) stop_hex_spell_all();
+
+ /* Get the item (in the pack) */
+ if (item >= 0)
+ {
+ o_ptr = &inventory[item];
+ }
+
+ /* Get the item (on the floor) */
+ else
+ {
+ o_ptr = &o_list[0 - item];
+ }
+
+ sound(SOUND_EAT);
+
+ take_turn(p_ptr, 100);;
+
+ /* Identity not known yet */
+ ident = FALSE;
+
+ /* Object level */
+ lev = k_info[o_ptr->k_idx].level;
+
+ if (o_ptr->tval == TV_FOOD)
+ {
+ /* Analyze the food */
+ switch (o_ptr->sval)
+ {
+ case SV_FOOD_POISON:
+ {
+ if (!(p_ptr->resist_pois || IS_OPPOSE_POIS()))
+ {
+ if (set_poisoned(p_ptr->poisoned + randint0(10) + 10))
+ {
+ ident = TRUE;
+ }
+ }
+ break;
+ }
+
+ case SV_FOOD_BLINDNESS:
+ {
+ if (!p_ptr->resist_blind)
+ {
+ if (set_blind(p_ptr->blind + randint0(200) + 200))
+ {
+ ident = TRUE;
+ }
+ }
+ break;
+ }
+
+ case SV_FOOD_PARANOIA:
+ {
+ if (!p_ptr->resist_fear)
+ {
+ if (set_afraid(p_ptr->afraid + randint0(10) + 10))
+ {
+ ident = TRUE;
+ }
+ }
+ break;
+ }
+
+ case SV_FOOD_CONFUSION:
+ {
+ if (!p_ptr->resist_conf)
+ {
+ if (set_confused(p_ptr->confused + randint0(10) + 10))
+ {
+ ident = TRUE;
+ }
+ }
+ break;
+ }
+
+ case SV_FOOD_HALLUCINATION:
+ {
+ if (!p_ptr->resist_chaos)
+ {
+ if (set_image(p_ptr->image + randint0(250) + 250))
+ {
+ ident = TRUE;
+ }
+ }
+ break;
+ }
+
+ case SV_FOOD_PARALYSIS:
+ {
+ if (!p_ptr->free_act)
+ {
+ if (set_paralyzed(p_ptr->paralyzed + randint0(10) + 10))
+ {
+ ident = TRUE;
+ }
+ }
+ break;
+ }
+
+ case SV_FOOD_WEAKNESS:
+ {
+ take_hit(DAMAGE_NOESCAPE, damroll(6, 6), _("毒入り食料", "poisonous food"), -1);
+ (void)do_dec_stat(A_STR);
+ ident = TRUE;
+ break;
+ }
+
+ case SV_FOOD_SICKNESS:
+ {
+ take_hit(DAMAGE_NOESCAPE, damroll(6, 6), _("毒入り食料", "poisonous food"), -1);
+ (void)do_dec_stat(A_CON);
+ ident = TRUE;
+ break;
+ }
+
+ case SV_FOOD_STUPIDITY:
+ {
+ take_hit(DAMAGE_NOESCAPE, damroll(8, 8), _("毒入り食料", "poisonous food"), -1);
+ (void)do_dec_stat(A_INT);
+ ident = TRUE;
+ break;
+ }
+
+ case SV_FOOD_NAIVETY:
+ {
+ take_hit(DAMAGE_NOESCAPE, damroll(8, 8), _("毒入り食料", "poisonous food"), -1);
+ (void)do_dec_stat(A_WIS);
+ ident = TRUE;
+ break;
+ }
+
+ case SV_FOOD_UNHEALTH:
+ {
+ take_hit(DAMAGE_NOESCAPE, damroll(10, 10), _("毒入り食料", "poisonous food"), -1);
+ (void)do_dec_stat(A_CON);
+ ident = TRUE;
+ break;
+ }
+
+ case SV_FOOD_DISEASE:
+ {
+ take_hit(DAMAGE_NOESCAPE, damroll(10, 10), _("毒入り食料", "poisonous food"), -1);
+ (void)do_dec_stat(A_STR);
+ ident = TRUE;
+ break;
+ }
+
+ case SV_FOOD_CURE_POISON:
+ {
+ if (set_poisoned(0)) ident = TRUE;
+ break;
+ }
+
+ case SV_FOOD_CURE_BLINDNESS:
+ {
+ if (set_blind(0)) ident = TRUE;
+ break;
+ }
+
+ case SV_FOOD_CURE_PARANOIA:
+ {
+ if (set_afraid(0)) ident = TRUE;
+ break;
+ }
+
+ case SV_FOOD_CURE_CONFUSION:
+ {
+ if (set_confused(0)) ident = TRUE;
+ break;
+ }
+
+ case SV_FOOD_CURE_SERIOUS:
+ {
+ ident = cure_serious_wounds(4, 8);
+ break;
+ }
+
+ case SV_FOOD_RESTORE_STR:
+ {
+ if (do_res_stat(A_STR)) ident = TRUE;
+ break;
+ }
+
+ case SV_FOOD_RESTORE_CON:
+ {
+ if (do_res_stat(A_CON)) ident = TRUE;
+ break;
+ }
+
+ case SV_FOOD_RESTORING:
+ {
+ ident = restore_all_status();
+ break;
+ }
+
+
+#ifdef JP
+ /* それぞれの食べ物の感想をオリジナルより細かく表現 */
+ case SV_FOOD_BISCUIT:
+ {
+ msg_print("甘くてサクサクしてとてもおいしい。");
+ ident = TRUE;
+ break;
+ }
+
+ case SV_FOOD_JERKY:
+ {
+ msg_print("歯ごたえがあっておいしい。");
+ ident = TRUE;
+ break;
+ }
+
+ case SV_FOOD_SLIME_MOLD:
+ {
+ msg_print("これはなんとも形容しがたい味だ。");
+ ident = TRUE;
+ break;
+ }
+
+ case SV_FOOD_RATION:
+ {
+ msg_print("これはおいしい。");
+ ident = TRUE;
+ break;
+ }
+#else
+ case SV_FOOD_RATION:
+ case SV_FOOD_BISCUIT:
+ case SV_FOOD_JERKY:
+ case SV_FOOD_SLIME_MOLD:
+ {
+ msg_print("That tastes good.");
+ ident = TRUE;
+ break;
+ }
+#endif
+
+
+ case SV_FOOD_WAYBREAD:
+ {
+ msg_print(_("これはひじょうに美味だ。", "That tastes good."));
+ (void)set_poisoned(0);
+ (void)hp_player(damroll(4, 8));
+ ident = TRUE;
+ break;
+ }
+
+#ifdef JP
+ case SV_FOOD_PINT_OF_ALE:
+ {
+ msg_print("のどごし爽やかだ。");
+ ident = TRUE;
+ break;
+ }
+
+ case SV_FOOD_PINT_OF_WINE:
+ {
+ msg_print("That tastes good.");
+ ident = TRUE;
+ break;
+ }
+#else
+ case SV_FOOD_PINT_OF_ALE:
+ case SV_FOOD_PINT_OF_WINE:
+ {
+ msg_print("That tastes good.");
+ ident = TRUE;
+ break;
+ }
+#endif
+
+ }
+ }
+ p_ptr->update |= (PU_COMBINE | PU_REORDER);
+
+ if (!(object_is_aware(o_ptr)))
+ {
+ chg_virtue(V_KNOWLEDGE, -1);
+ chg_virtue(V_PATIENCE, -1);
+ chg_virtue(V_CHANCE, 1);
+ }
+
+ /* We have tried it */
+ if (o_ptr->tval == TV_FOOD) object_tried(o_ptr);
+
+ /* The player is now aware of the object */
+ if (ident && !object_is_aware(o_ptr))
+ {
+ object_aware(o_ptr);
+ gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev);
+ }
+
+ p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
+
+
+ /* Food can feed the player */
+ if (prace_is_(RACE_VAMPIRE) || (p_ptr->mimic_form == MIMIC_VAMPIRE))
+ {
+ /* Reduced nutritional benefit */
+ (void)set_food(p_ptr->food + (o_ptr->pval / 10));
+ msg_print(_("あなたのような者にとって食糧など僅かな栄養にしかならない。",
+ "Mere victuals hold scant sustenance for a being such as yourself."));
+
+ if (p_ptr->food < PY_FOOD_ALERT) /* Hungry */
+ msg_print(_("あなたの飢えは新鮮な血によってのみ満たされる!",
+ "Your hunger can only be satisfied with fresh blood!"));
+ }
+ else if ((prace_is_(RACE_SKELETON) ||
+ prace_is_(RACE_GOLEM) ||
+ prace_is_(RACE_ZOMBIE) ||
+ prace_is_(RACE_SPECTRE)) &&
+ (o_ptr->tval == TV_STAFF || o_ptr->tval == TV_WAND))
+ {
+ concptr staff;
+
+ if (o_ptr->tval == TV_STAFF &&
+ (item < 0) && (o_ptr->number > 1))
+ {
+ msg_print(_("まずは杖を拾わなければ。", "You must first pick up the staffs."));
+ return;
+ }
+ staff = (o_ptr->tval == TV_STAFF) ? _("杖", "staff") : _("魔法棒", "wand");
+
+ /* "Eat" charges */
+ if (o_ptr->pval == 0)
+ {
+ msg_format(_("この%sにはもう魔力が残っていない。", "The %s has no charges left."), staff);
+ o_ptr->ident |= (IDENT_EMPTY);
+ p_ptr->update |= (PU_COMBINE | PU_REORDER);
+ p_ptr->window |= (PW_INVEN);
+
+ return;
+ }
+ msg_format(_("あなたは%sの魔力をエネルギー源として吸収した。", "You absorb mana of the %s as your energy."), staff);
+
+ /* Use a single charge */
+ o_ptr->pval--;
+
+ /* Eat a charge */
+ set_food(p_ptr->food + 5000);
+
+ /* XXX Hack -- unstack if necessary */
+ if (o_ptr->tval == TV_STAFF &&
+ (item >= 0) && (o_ptr->number > 1))
+ {
+ object_type forge;
+ object_type *q_ptr;
+ q_ptr = &forge;
+
+ /* Obtain a local object */
+ object_copy(q_ptr, o_ptr);
+
+ /* Modify quantity */
+ q_ptr->number = 1;
+
+ /* Restore the charges */
+ o_ptr->pval++;
+
+ /* Unstack the used item */
+ o_ptr->number--;
+ p_ptr->total_weight -= q_ptr->weight;
+ item = inven_carry(q_ptr);
+
+ msg_format(_("杖をまとめなおした。", "You unstack your staff."));
+ }
+
+ /* Describe charges in the pack */
+ if (item >= 0)
+ {
+ inven_item_charges(item);
+ }
+
+ /* Describe charges on the floor */
+ else
+ {
+ floor_item_charges(0 - item);
+ }
+
+ p_ptr->window |= (PW_INVEN | PW_EQUIP);
+
+ /* Don't eat a staff/wand itself */
+ return;
+ }
+ else if ((prace_is_(RACE_DEMON) ||
+ (mimic_info[p_ptr->mimic_form].MIMIC_FLAGS & MIMIC_IS_DEMON)) &&
+ (o_ptr->tval == TV_CORPSE && o_ptr->sval == SV_CORPSE &&
+ my_strchr("pht", r_info[o_ptr->pval].d_char)))
+ {
+ /* Drain vitality of humanoids */
+ GAME_TEXT o_name[MAX_NLEN];
+ object_desc(o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
+ msg_format(_("%sは燃え上り灰になった。精力を吸収した気がする。", "%^s is burnt to ashes. You absorb its vitality!"), o_name);
+ (void)set_food(PY_FOOD_MAX - 1);
+ }
+ else if (prace_is_(RACE_SKELETON))
+ {
+#if 0
+ if (o_ptr->tval == TV_SKELETON ||
+ (o_ptr->tval == TV_CORPSE && o_ptr->sval == SV_SKELETON))
+ {
+ msg_print(_("あなたは骨で自分の体を補った。", "Your body absorbs the bone."));
+ set_food(p_ptr->food + 5000);
+ }
+ else
+#endif
+
+ if (!((o_ptr->sval == SV_FOOD_WAYBREAD) ||
+ (o_ptr->sval < SV_FOOD_BISCUIT)))
+ {
+ object_type forge;
+ object_type *q_ptr = &forge;
+
+ msg_print(_("食べ物がアゴを素通りして落ちた!", "The food falls through your jaws!"));
+ object_prep(q_ptr, lookup_kind(o_ptr->tval, o_ptr->sval));
+
+ /* Drop the object from heaven */
+ (void)drop_near(q_ptr, -1, p_ptr->y, p_ptr->x);
+ }
+ else
+ {
+ msg_print(_("食べ物がアゴを素通りして落ち、消えた!", "The food falls through your jaws and vanishes!"));
+ }
+ }
+ else if (prace_is_(RACE_GOLEM) ||
+ prace_is_(RACE_ZOMBIE) ||
+ prace_is_(RACE_ENT) ||
+ prace_is_(RACE_DEMON) ||
+ prace_is_(RACE_ANDROID) ||
+ prace_is_(RACE_SPECTRE) ||
+ (mimic_info[p_ptr->mimic_form].MIMIC_FLAGS & MIMIC_IS_NONLIVING))
+ {
+ msg_print(_("生者の食物はあなたにとってほとんど栄養にならない。", "The food of mortals is poor sustenance for you."));
+ set_food(p_ptr->food + ((o_ptr->pval) / 20));
+ }
+ else if (o_ptr->tval == TV_FOOD && o_ptr->sval == SV_FOOD_WAYBREAD)
+ {
+ /* Waybread is always fully satisfying. */
+ set_food(MAX(p_ptr->food, PY_FOOD_MAX - 1));
+ }
+ else
+ {
+ /* Food can feed the player */
+ (void)set_food(p_ptr->food + o_ptr->pval);
+ }
+
+ /* Destroy a food in the pack */
+ if (item >= 0)
+ {
+ inven_item_increase(item, -1);
+ inven_item_describe(item);
+ inven_item_optimize(item);
+ }
+
+ /* Destroy a food on the floor */
+ else
+ {
+ floor_item_increase(0 - item, -1);
+ floor_item_describe(0 - item);
+ floor_item_optimize(0 - item);
+ }
+}
+
+
+/*!
+ * @brief 食料を食べるコマンドのメインルーチン /
+ * Eat some food (from the pack or floor)
+ * @return なし
+ */
+void do_cmd_eat_food(void)
+{
+ OBJECT_IDX item;
+ concptr q, s;
+
+ if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN))
+ {
+ set_action(ACTION_NONE);
+ }
+
+ /* Restrict choices to food */
+ item_tester_hook = item_tester_hook_eatable;
+
+ q = _("どれを食べますか? ", "Eat which item? ");
+ s = _("食べ物がない。", "You have nothing to eat.");
+
+ if (!choose_object(&item, q, s, (USE_INVEN | USE_FLOOR))) return;
+
+ /* Eat the object */
+ do_cmd_eat_food_aux(item);
+}
+
-\r
-extern void do_cmd_eat_food(void);\r
-extern void do_cmd_eat_food_aux(INVENTORY_IDX item);\r
+
+extern void do_cmd_eat_food(void);
+extern void do_cmd_eat_food_aux(INVENTORY_IDX item);
-/* cmd3-item.h */\r
-\r
-extern void do_cmd_inven(void);\r
-extern void do_cmd_equip(void);\r
-extern void do_cmd_wield(void);\r
-extern void do_cmd_takeoff(void);\r
-extern void do_cmd_drop(void);\r
-extern void do_cmd_destroy(void);\r
-extern void do_cmd_observe(void);\r
-extern void do_cmd_uninscribe(void);\r
-extern void do_cmd_inscribe(void);\r
-extern void do_cmd_refill(void);\r
-extern void do_cmd_target(void);\r
-extern void do_cmd_look(void);\r
-extern void do_cmd_locate(void);\r
-extern void do_cmd_query_symbol(void);\r
+/* cmd3-item.h */
+
+extern void do_cmd_inven(void);
+extern void do_cmd_equip(void);
+extern void do_cmd_wield(void);
+extern void do_cmd_takeoff(void);
+extern void do_cmd_drop(void);
+extern void do_cmd_destroy(void);
+extern void do_cmd_observe(void);
+extern void do_cmd_uninscribe(void);
+extern void do_cmd_inscribe(void);
+extern void do_cmd_refill(void);
+extern void do_cmd_target(void);
+extern void do_cmd_look(void);
+extern void do_cmd_locate(void);
+extern void do_cmd_query_symbol(void);
extern void do_cmd_use(void);
\ No newline at end of file
-extern bool do_riding(bool force);\r
-extern void check_pets_num_and_align(monster_type *m_ptr, bool inc);\r
-extern int calculate_upkeep(void);\r
-extern void do_cmd_pet_dismiss(void);\r
-extern void do_cmd_pet(void);\r
-extern bool player_can_ride_aux(cave_type *c_ptr, bool now_riding);\r
-extern bool rakuba(HIT_POINT dam, bool force);\r
-\r
-\r
+extern bool do_riding(bool force);
+extern void check_pets_num_and_align(monster_type *m_ptr, bool inc);
+extern int calculate_upkeep(void);
+extern void do_cmd_pet_dismiss(void);
+extern void do_cmd_pet(void);
+extern bool player_can_ride_aux(cave_type *c_ptr, bool now_riding);
+extern bool rakuba(HIT_POINT dam, bool force);
+
+
-/*!\r
- * @file cmd-quaff.c\r
- * @brief プレイヤーの飲むコマンド実装\r
- * @date 2018/09/07\r
- * @details\r
- * cmd6.cより分離。\r
- */\r
-\r
-#include "angband.h"\r
-#include "selfinfo.h"\r
-#include "object-hook.h"\r
-#include "mutation.h"\r
-#include "avatar.h"\r
-#include "spells-status.h"\r
-#include "realm-hex.h"\r
-\r
-/*!\r
- * @brief 薬を飲むコマンドのサブルーチン /\r
- * Quaff a potion (from the pack or the floor)\r
- * @param item 飲む薬オブジェクトの所持品ID\r
- * @return なし\r
- */\r
-void do_cmd_quaff_potion_aux(INVENTORY_IDX item)\r
-{\r
- bool ident;\r
- DEPTH lev;\r
- object_type *o_ptr;\r
- object_type forge;\r
- object_type *q_ptr;\r
-\r
-\r
- if (p_ptr->timewalk)\r
- {\r
- if (flush_failure) flush();\r
- msg_print(_("瓶から水が流れ出てこない!", "The potion doesn't flow out from a bottle."));\r
-\r
- sound(SOUND_FAIL);\r
- return;\r
- }\r
-\r
- if (music_singing_any()) stop_singing();\r
- if (hex_spelling_any())\r
- {\r
- if (!hex_spelling(HEX_INHAIL)) stop_hex_spell_all();\r
- }\r
-\r
- /* Get the item (in the pack) */\r
- if (item >= 0)\r
- {\r
- o_ptr = &inventory[item];\r
- }\r
-\r
- /* Get the item (on the floor) */\r
- else\r
- {\r
- o_ptr = &o_list[0 - item];\r
- }\r
- q_ptr = &forge;\r
-\r
- /* Obtain a local object */\r
- object_copy(q_ptr, o_ptr);\r
-\r
- /* Single object */\r
- q_ptr->number = 1;\r
-\r
- /* Reduce and describe inventory */\r
- if (item >= 0)\r
- {\r
- inven_item_increase(item, -1);\r
- inven_item_describe(item);\r
- inven_item_optimize(item);\r
- }\r
-\r
- /* Reduce and describe floor item */\r
- else\r
- {\r
- floor_item_increase(0 - item, -1);\r
- floor_item_describe(0 - item);\r
- floor_item_optimize(0 - item);\r
- }\r
-\r
- sound(SOUND_QUAFF);\r
-\r
-\r
- /* Not identified yet */\r
- ident = FALSE;\r
-\r
- /* Object level */\r
- lev = k_info[q_ptr->k_idx].level;\r
-\r
- /* Analyze the potion */\r
- if (q_ptr->tval == TV_POTION)\r
- {\r
- switch (q_ptr->sval)\r
- {\r
- /* 飲みごたえをオリジナルより細かく表現 */\r
- case SV_POTION_WATER:\r
- msg_print(_("口の中がさっぱりした。", ""));\r
- msg_print(_("のどの渇きが少しおさまった。", "You feel less thirsty."));\r
- ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_APPLE_JUICE:\r
- msg_print(_("甘くてサッパリとしていて、とてもおいしい。", ""));\r
- msg_print(_("のどの渇きが少しおさまった。", "You feel less thirsty."));\r
- ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_SLIME_MOLD:\r
- msg_print(_("なんとも不気味な味だ。", ""));\r
- msg_print(_("のどの渇きが少しおさまった。", "You feel less thirsty."));\r
- ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_SLOWNESS:\r
- if (set_slow(randint1(25) + 15, FALSE)) ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_SALT_WATER:\r
- msg_print(_("うぇ!思わず吐いてしまった。", "The potion makes you vomit!"));\r
-\r
- if (!(prace_is_(RACE_GOLEM) ||\r
- prace_is_(RACE_ZOMBIE) ||\r
- prace_is_(RACE_DEMON) ||\r
- prace_is_(RACE_ANDROID) ||\r
- prace_is_(RACE_SPECTRE) ||\r
- (mimic_info[p_ptr->mimic_form].MIMIC_FLAGS & MIMIC_IS_NONLIVING)))\r
- {\r
- /* Only living creatures get thirsty */\r
- (void)set_food(PY_FOOD_STARVE - 1);\r
- }\r
-\r
- (void)set_poisoned(0);\r
- (void)set_paralyzed(p_ptr->paralyzed + 4);\r
- ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_POISON:\r
- if (!(p_ptr->resist_pois || IS_OPPOSE_POIS()))\r
- {\r
- if (set_poisoned(p_ptr->poisoned + randint0(15) + 10))\r
- {\r
- ident = TRUE;\r
- }\r
- }\r
- break;\r
-\r
- case SV_POTION_BLINDNESS:\r
- if (!p_ptr->resist_blind)\r
- {\r
- if (set_blind(p_ptr->blind + randint0(100) + 100))\r
- {\r
- ident = TRUE;\r
- }\r
- }\r
- break;\r
-\r
- case SV_POTION_BOOZE:\r
- ident = booze(p_ptr);\r
- break;\r
-\r
- case SV_POTION_SLEEP:\r
- if (!p_ptr->free_act)\r
- {\r
- msg_print(_("あなたは眠ってしまった。", "You fall asleep."));\r
-\r
- if (ironman_nightmare)\r
- {\r
- msg_print(_("恐ろしい光景が頭に浮かんできた。", "A horrible vision enters your mind."));\r
-\r
- /* Have some nightmares */\r
- sanity_blast(NULL, FALSE);\r
- }\r
- if (set_paralyzed(p_ptr->paralyzed + randint0(4) + 4))\r
- {\r
- ident = TRUE;\r
- }\r
- }\r
- break;\r
-\r
- case SV_POTION_LOSE_MEMORIES:\r
- if (!p_ptr->hold_exp && (p_ptr->exp > 0))\r
- {\r
- msg_print(_("過去の記憶が薄れていく気がする。", "You feel your memories fade."));\r
- chg_virtue(V_KNOWLEDGE, -5);\r
-\r
- lose_exp(p_ptr->exp / 4);\r
- ident = TRUE;\r
- }\r
- break;\r
-\r
- case SV_POTION_RUINATION:\r
- msg_print(_("身も心も弱ってきて、精気が抜けていくようだ。", "Your nerves and muscles feel weak and lifeless!"));\r
- take_hit(DAMAGE_LOSELIFE, damroll(10, 10), _("破滅の薬", "a potion of Ruination"), -1);\r
-\r
- (void)dec_stat(A_DEX, 25, TRUE);\r
- (void)dec_stat(A_WIS, 25, TRUE);\r
- (void)dec_stat(A_CON, 25, TRUE);\r
- (void)dec_stat(A_STR, 25, TRUE);\r
- (void)dec_stat(A_CHR, 25, TRUE);\r
- (void)dec_stat(A_INT, 25, TRUE);\r
- ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_DEC_STR:\r
- if (do_dec_stat(A_STR)) ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_DEC_INT:\r
- if (do_dec_stat(A_INT)) ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_DEC_WIS:\r
- if (do_dec_stat(A_WIS)) ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_DEC_DEX:\r
- if (do_dec_stat(A_DEX)) ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_DEC_CON:\r
- if (do_dec_stat(A_CON)) ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_DEC_CHR:\r
- if (do_dec_stat(A_CHR)) ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_DETONATIONS:\r
- ident = detonation(p_ptr);\r
- break;\r
-\r
- case SV_POTION_DEATH:\r
- chg_virtue(V_VITALITY, -1);\r
- chg_virtue(V_UNLIFE, 5);\r
- msg_print(_("死の予感が体中を駆けめぐった。", "A feeling of Death flows through your body."));\r
- take_hit(DAMAGE_LOSELIFE, 5000, _("死の薬", "a potion of Death"), -1);\r
- ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_INFRAVISION:\r
- if (set_tim_infra(p_ptr->tim_infra + 100 + randint1(100), FALSE))\r
- {\r
- ident = TRUE;\r
- }\r
- break;\r
-\r
- case SV_POTION_DETECT_INVIS:\r
- if (set_tim_invis(p_ptr->tim_invis + 12 + randint1(12), FALSE))\r
- {\r
- ident = TRUE;\r
- }\r
- break;\r
-\r
- case SV_POTION_SLOW_POISON:\r
- if (set_poisoned(p_ptr->poisoned / 2)) ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_CURE_POISON:\r
- if (set_poisoned(0)) ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_BOLDNESS:\r
- if (set_afraid(0)) ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_SPEED:\r
- if (!p_ptr->fast)\r
- {\r
- if (set_fast(randint1(25) + 15, FALSE)) ident = TRUE;\r
- }\r
- else\r
- {\r
- (void)set_fast(p_ptr->fast + 5, FALSE);\r
- }\r
- break;\r
-\r
- case SV_POTION_RESIST_HEAT:\r
- if (set_oppose_fire(p_ptr->oppose_fire + randint1(10) + 10, FALSE))\r
- {\r
- ident = TRUE;\r
- }\r
- break;\r
-\r
- case SV_POTION_RESIST_COLD:\r
- if (set_oppose_cold(p_ptr->oppose_cold + randint1(10) + 10, FALSE))\r
- {\r
- ident = TRUE;\r
- }\r
- break;\r
-\r
- case SV_POTION_HEROISM:\r
- ident = heroism(25);\r
- break;\r
-\r
- case SV_POTION_BESERK_STRENGTH:\r
- ident = berserk(randint1(25) + 25);\r
- break;\r
-\r
- case SV_POTION_CURE_LIGHT:\r
- ident = cure_light_wounds(2, 8);\r
- break;\r
-\r
- case SV_POTION_CURE_SERIOUS:\r
- ident = cure_serious_wounds(4, 8);\r
- break;\r
-\r
- case SV_POTION_CURE_CRITICAL:\r
- ident = cure_critical_wounds(damroll(6, 8));\r
- break;\r
-\r
- case SV_POTION_HEALING:\r
- ident = cure_critical_wounds(300);\r
- break;\r
-\r
- case SV_POTION_STAR_HEALING:\r
- ident = cure_critical_wounds(1200);\r
- break;\r
-\r
- case SV_POTION_LIFE:\r
- ident = life_stream(TRUE, TRUE);\r
- break;\r
-\r
- case SV_POTION_RESTORE_MANA:\r
- ident = restore_mana(TRUE);\r
- break;\r
-\r
- case SV_POTION_RESTORE_EXP:\r
- if (restore_level()) ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_RES_STR:\r
- if (do_res_stat(A_STR)) ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_RES_INT:\r
- if (do_res_stat(A_INT)) ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_RES_WIS:\r
- if (do_res_stat(A_WIS)) ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_RES_DEX:\r
- if (do_res_stat(A_DEX)) ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_RES_CON:\r
- if (do_res_stat(A_CON)) ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_RES_CHR:\r
- if (do_res_stat(A_CHR)) ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_INC_STR:\r
- if (do_inc_stat(A_STR)) ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_INC_INT:\r
- if (do_inc_stat(A_INT)) ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_INC_WIS:\r
- if (do_inc_stat(A_WIS)) ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_INC_DEX:\r
- if (do_inc_stat(A_DEX)) ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_INC_CON:\r
- if (do_inc_stat(A_CON)) ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_INC_CHR:\r
- if (do_inc_stat(A_CHR)) ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_AUGMENTATION:\r
- if (do_inc_stat(A_STR)) ident = TRUE;\r
- if (do_inc_stat(A_INT)) ident = TRUE;\r
- if (do_inc_stat(A_WIS)) ident = TRUE;\r
- if (do_inc_stat(A_DEX)) ident = TRUE;\r
- if (do_inc_stat(A_CON)) ident = TRUE;\r
- if (do_inc_stat(A_CHR)) ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_ENLIGHTENMENT:\r
- msg_print(_("自分の置かれている状況が脳裏に浮かんできた...", "An image of your surroundings forms in your mind..."));\r
- chg_virtue(V_KNOWLEDGE, 1);\r
- chg_virtue(V_ENLIGHTEN, 1);\r
- wiz_lite(FALSE);\r
- ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_STAR_ENLIGHTENMENT:\r
- msg_print(_("更なる啓蒙を感じた...", "You begin to feel more enlightened..."));\r
- chg_virtue(V_KNOWLEDGE, 1);\r
- chg_virtue(V_ENLIGHTEN, 2);\r
- msg_print(NULL);\r
- wiz_lite(FALSE);\r
- (void)do_inc_stat(A_INT);\r
- (void)do_inc_stat(A_WIS);\r
- (void)detect_traps(DETECT_RAD_DEFAULT, TRUE);\r
- (void)detect_doors(DETECT_RAD_DEFAULT);\r
- (void)detect_stairs(DETECT_RAD_DEFAULT);\r
- (void)detect_treasure(DETECT_RAD_DEFAULT);\r
- (void)detect_objects_gold(DETECT_RAD_DEFAULT);\r
- (void)detect_objects_normal(DETECT_RAD_DEFAULT);\r
- identify_pack();\r
- self_knowledge();\r
- ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_SELF_KNOWLEDGE:\r
- msg_print(_("自分自身のことが少しは分かった気がする...", "You begin to know yourself a little better..."));\r
- msg_print(NULL);\r
- self_knowledge();\r
- ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_EXPERIENCE:\r
- if (p_ptr->prace == RACE_ANDROID) break;\r
- chg_virtue(V_ENLIGHTEN, 1);\r
- if (p_ptr->exp < PY_MAX_EXP)\r
- {\r
- s32b ee = (p_ptr->exp / 2) + 10;\r
- if (ee > 100000L) ee = 100000L;\r
- msg_print(_("更に経験を積んだような気がする。", "You feel more experienced."));\r
- gain_exp(ee);\r
- ident = TRUE;\r
- }\r
- break;\r
-\r
- case SV_POTION_RESISTANCE:\r
- (void)set_oppose_acid(p_ptr->oppose_acid + randint1(20) + 20, FALSE);\r
- (void)set_oppose_elec(p_ptr->oppose_elec + randint1(20) + 20, FALSE);\r
- (void)set_oppose_fire(p_ptr->oppose_fire + randint1(20) + 20, FALSE);\r
- (void)set_oppose_cold(p_ptr->oppose_cold + randint1(20) + 20, FALSE);\r
- (void)set_oppose_pois(p_ptr->oppose_pois + randint1(20) + 20, FALSE);\r
- ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_CURING:\r
- if (true_healing(50)) ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_INVULNERABILITY:\r
- (void)set_invuln(p_ptr->invuln + randint1(4) + 4, FALSE);\r
- ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_NEW_LIFE:\r
- roll_hitdice(0L);\r
- get_max_stats();\r
- p_ptr->update |= PU_BONUS;\r
- lose_all_mutations();\r
- ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_NEO_TSUYOSHI:\r
- (void)set_image(0);\r
- (void)set_tsuyoshi(p_ptr->tsuyoshi + randint1(100) + 100, FALSE);\r
- ident = TRUE;\r
- break;\r
-\r
- case SV_POTION_TSUYOSHI:\r
- msg_print(_("「オクレ兄さん!」", "Brother OKURE!"));\r
- msg_print(NULL);\r
- p_ptr->tsuyoshi = 1;\r
- (void)set_tsuyoshi(0, TRUE);\r
- if (!p_ptr->resist_chaos)\r
- {\r
- (void)set_image(50 + randint1(50));\r
- }\r
- ident = TRUE;\r
- break;\r
- \r
- case SV_POTION_POLYMORPH:\r
- if ((p_ptr->muta1 || p_ptr->muta2 || p_ptr->muta3) && one_in_(23))\r
- {\r
- lose_all_mutations();\r
- }\r
- else\r
- {\r
- do\r
- {\r
- if (one_in_(2))\r
- {\r
- if(gain_random_mutation(0)) ident = TRUE;\r
- }\r
- else if (lose_mutation(0)) ident = TRUE;\r
- } while(!ident || one_in_(2));\r
- }\r
- break;\r
- }\r
- }\r
-\r
- if (prace_is_(RACE_SKELETON))\r
- {\r
- msg_print(_("液体の一部はあなたのアゴを素通りして落ちた!", "Some of the fluid falls through your jaws!"));\r
- (void)potion_smash_effect(0, p_ptr->y, p_ptr->x, q_ptr->k_idx);\r
- }\r
- p_ptr->update |= (PU_COMBINE | PU_REORDER);\r
-\r
- if (!(object_is_aware(q_ptr)))\r
- {\r
- chg_virtue(V_PATIENCE, -1);\r
- chg_virtue(V_CHANCE, 1);\r
- chg_virtue(V_KNOWLEDGE, -1);\r
- }\r
-\r
- /* The item has been tried */\r
- object_tried(q_ptr);\r
-\r
- /* An identification was made */\r
- if (ident && !object_is_aware(q_ptr))\r
- {\r
- object_aware(q_ptr);\r
- gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev);\r
- }\r
-\r
- p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);\r
-\r
- /* Potions can feed the player */\r
- switch (p_ptr->mimic_form)\r
- {\r
- case MIMIC_NONE:\r
- switch (p_ptr->prace)\r
- {\r
- case RACE_VAMPIRE:\r
- (void)set_food(p_ptr->food + (q_ptr->pval / 10));\r
- break;\r
- case RACE_SKELETON:\r
- /* Do nothing */\r
- break;\r
- case RACE_GOLEM:\r
- case RACE_ZOMBIE:\r
- case RACE_DEMON:\r
- case RACE_SPECTRE:\r
- set_food(p_ptr->food + ((q_ptr->pval) / 20));\r
- break;\r
- case RACE_ANDROID:\r
- if (q_ptr->tval == TV_FLASK)\r
- {\r
- msg_print(_("オイルを補給した。", "You replenish yourself with the oil."));\r
- set_food(p_ptr->food + 5000);\r
- }\r
- else\r
- {\r
- set_food(p_ptr->food + ((q_ptr->pval) / 20));\r
- }\r
- break;\r
- case RACE_ENT:\r
- msg_print(_("水分を取り込んだ。", "You are moistened."));\r
- set_food(MIN(p_ptr->food + q_ptr->pval + MAX(0, q_ptr->pval * 10) + 2000, PY_FOOD_MAX - 1));\r
- break;\r
- default:\r
- (void)set_food(p_ptr->food + q_ptr->pval);\r
- break;\r
- }\r
- break;\r
- case MIMIC_DEMON:\r
- case MIMIC_DEMON_LORD:\r
- set_food(p_ptr->food + ((q_ptr->pval) / 20));\r
- break;\r
- case MIMIC_VAMPIRE:\r
- (void)set_food(p_ptr->food + (q_ptr->pval / 10));\r
- break;\r
- default:\r
- (void)set_food(p_ptr->food + q_ptr->pval);\r
- break;\r
- }\r
-}\r
-\r
-\r
-\r
-/*!\r
- * @brief 薬を飲むコマンドのメインルーチン /\r
- * Quaff some potion (from the pack or floor)\r
- * @return なし\r
- */\r
-void do_cmd_quaff_potion(void)\r
-{\r
- OBJECT_IDX item;\r
- concptr q, s;\r
-\r
- if (p_ptr->wild_mode)\r
- {\r
- return;\r
- }\r
-\r
- if (cmd_limit_arena(p_ptr)) return;\r
-\r
- if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN))\r
- {\r
- set_action(ACTION_NONE);\r
- }\r
-\r
- /* Restrict choices to potions */\r
- item_tester_hook = item_tester_hook_quaff;\r
-\r
- q = _("どの薬を飲みますか? ", "Quaff which potion? ");\r
- s = _("飲める薬がない。", "You have no potions to quaff.");\r
-\r
- if (!choose_object(&item, q, s, (USE_INVEN | USE_FLOOR))) return;\r
-\r
- /* Quaff the potion */\r
- do_cmd_quaff_potion_aux(item);\r
-}\r
+/*!
+ * @file cmd-quaff.c
+ * @brief プレイヤーの飲むコマンド実装
+ * @date 2018/09/07
+ * @details
+ * cmd6.cより分離。
+ */
+
+#include "angband.h"
+#include "selfinfo.h"
+#include "object-hook.h"
+#include "mutation.h"
+#include "avatar.h"
+#include "spells-status.h"
+#include "realm-hex.h"
+
+/*!
+ * @brief 薬を飲むコマンドのサブルーチン /
+ * Quaff a potion (from the pack or the floor)
+ * @param item 飲む薬オブジェクトの所持品ID
+ * @return なし
+ */
+void do_cmd_quaff_potion_aux(INVENTORY_IDX item)
+{
+ bool ident;
+ DEPTH lev;
+ object_type *o_ptr;
+ object_type forge;
+ object_type *q_ptr;
+
+
+ if (p_ptr->timewalk)
+ {
+ if (flush_failure) flush();
+ msg_print(_("瓶から水が流れ出てこない!", "The potion doesn't flow out from a bottle."));
+
+ sound(SOUND_FAIL);
+ return;
+ }
+
+ if (music_singing_any()) stop_singing();
+ if (hex_spelling_any())
+ {
+ if (!hex_spelling(HEX_INHAIL)) stop_hex_spell_all();
+ }
+
+ /* Get the item (in the pack) */
+ if (item >= 0)
+ {
+ o_ptr = &inventory[item];
+ }
+
+ /* Get the item (on the floor) */
+ else
+ {
+ o_ptr = &o_list[0 - item];
+ }
+ q_ptr = &forge;
+
+ /* Obtain a local object */
+ object_copy(q_ptr, o_ptr);
+
+ /* Single object */
+ q_ptr->number = 1;
+
+ /* Reduce and describe inventory */
+ if (item >= 0)
+ {
+ inven_item_increase(item, -1);
+ inven_item_describe(item);
+ inven_item_optimize(item);
+ }
+
+ /* Reduce and describe floor item */
+ else
+ {
+ floor_item_increase(0 - item, -1);
+ floor_item_describe(0 - item);
+ floor_item_optimize(0 - item);
+ }
+
+ sound(SOUND_QUAFF);
+
+
+ /* Not identified yet */
+ ident = FALSE;
+
+ /* Object level */
+ lev = k_info[q_ptr->k_idx].level;
+
+ /* Analyze the potion */
+ if (q_ptr->tval == TV_POTION)
+ {
+ switch (q_ptr->sval)
+ {
+ /* 飲みごたえをオリジナルより細かく表現 */
+ case SV_POTION_WATER:
+ msg_print(_("口の中がさっぱりした。", ""));
+ msg_print(_("のどの渇きが少しおさまった。", "You feel less thirsty."));
+ ident = TRUE;
+ break;
+
+ case SV_POTION_APPLE_JUICE:
+ msg_print(_("甘くてサッパリとしていて、とてもおいしい。", ""));
+ msg_print(_("のどの渇きが少しおさまった。", "You feel less thirsty."));
+ ident = TRUE;
+ break;
+
+ case SV_POTION_SLIME_MOLD:
+ msg_print(_("なんとも不気味な味だ。", ""));
+ msg_print(_("のどの渇きが少しおさまった。", "You feel less thirsty."));
+ ident = TRUE;
+ break;
+
+ case SV_POTION_SLOWNESS:
+ if (set_slow(randint1(25) + 15, FALSE)) ident = TRUE;
+ break;
+
+ case SV_POTION_SALT_WATER:
+ msg_print(_("うぇ!思わず吐いてしまった。", "The potion makes you vomit!"));
+
+ if (!(prace_is_(RACE_GOLEM) ||
+ prace_is_(RACE_ZOMBIE) ||
+ prace_is_(RACE_DEMON) ||
+ prace_is_(RACE_ANDROID) ||
+ prace_is_(RACE_SPECTRE) ||
+ (mimic_info[p_ptr->mimic_form].MIMIC_FLAGS & MIMIC_IS_NONLIVING)))
+ {
+ /* Only living creatures get thirsty */
+ (void)set_food(PY_FOOD_STARVE - 1);
+ }
+
+ (void)set_poisoned(0);
+ (void)set_paralyzed(p_ptr->paralyzed + 4);
+ ident = TRUE;
+ break;
+
+ case SV_POTION_POISON:
+ if (!(p_ptr->resist_pois || IS_OPPOSE_POIS()))
+ {
+ if (set_poisoned(p_ptr->poisoned + randint0(15) + 10))
+ {
+ ident = TRUE;
+ }
+ }
+ break;
+
+ case SV_POTION_BLINDNESS:
+ if (!p_ptr->resist_blind)
+ {
+ if (set_blind(p_ptr->blind + randint0(100) + 100))
+ {
+ ident = TRUE;
+ }
+ }
+ break;
+
+ case SV_POTION_BOOZE:
+ ident = booze(p_ptr);
+ break;
+
+ case SV_POTION_SLEEP:
+ if (!p_ptr->free_act)
+ {
+ msg_print(_("あなたは眠ってしまった。", "You fall asleep."));
+
+ if (ironman_nightmare)
+ {
+ msg_print(_("恐ろしい光景が頭に浮かんできた。", "A horrible vision enters your mind."));
+
+ /* Have some nightmares */
+ sanity_blast(NULL, FALSE);
+ }
+ if (set_paralyzed(p_ptr->paralyzed + randint0(4) + 4))
+ {
+ ident = TRUE;
+ }
+ }
+ break;
+
+ case SV_POTION_LOSE_MEMORIES:
+ if (!p_ptr->hold_exp && (p_ptr->exp > 0))
+ {
+ msg_print(_("過去の記憶が薄れていく気がする。", "You feel your memories fade."));
+ chg_virtue(V_KNOWLEDGE, -5);
+
+ lose_exp(p_ptr->exp / 4);
+ ident = TRUE;
+ }
+ break;
+
+ case SV_POTION_RUINATION:
+ msg_print(_("身も心も弱ってきて、精気が抜けていくようだ。", "Your nerves and muscles feel weak and lifeless!"));
+ take_hit(DAMAGE_LOSELIFE, damroll(10, 10), _("破滅の薬", "a potion of Ruination"), -1);
+
+ (void)dec_stat(A_DEX, 25, TRUE);
+ (void)dec_stat(A_WIS, 25, TRUE);
+ (void)dec_stat(A_CON, 25, TRUE);
+ (void)dec_stat(A_STR, 25, TRUE);
+ (void)dec_stat(A_CHR, 25, TRUE);
+ (void)dec_stat(A_INT, 25, TRUE);
+ ident = TRUE;
+ break;
+
+ case SV_POTION_DEC_STR:
+ if (do_dec_stat(A_STR)) ident = TRUE;
+ break;
+
+ case SV_POTION_DEC_INT:
+ if (do_dec_stat(A_INT)) ident = TRUE;
+ break;
+
+ case SV_POTION_DEC_WIS:
+ if (do_dec_stat(A_WIS)) ident = TRUE;
+ break;
+
+ case SV_POTION_DEC_DEX:
+ if (do_dec_stat(A_DEX)) ident = TRUE;
+ break;
+
+ case SV_POTION_DEC_CON:
+ if (do_dec_stat(A_CON)) ident = TRUE;
+ break;
+
+ case SV_POTION_DEC_CHR:
+ if (do_dec_stat(A_CHR)) ident = TRUE;
+ break;
+
+ case SV_POTION_DETONATIONS:
+ ident = detonation(p_ptr);
+ break;
+
+ case SV_POTION_DEATH:
+ chg_virtue(V_VITALITY, -1);
+ chg_virtue(V_UNLIFE, 5);
+ msg_print(_("死の予感が体中を駆けめぐった。", "A feeling of Death flows through your body."));
+ take_hit(DAMAGE_LOSELIFE, 5000, _("死の薬", "a potion of Death"), -1);
+ ident = TRUE;
+ break;
+
+ case SV_POTION_INFRAVISION:
+ if (set_tim_infra(p_ptr->tim_infra + 100 + randint1(100), FALSE))
+ {
+ ident = TRUE;
+ }
+ break;
+
+ case SV_POTION_DETECT_INVIS:
+ if (set_tim_invis(p_ptr->tim_invis + 12 + randint1(12), FALSE))
+ {
+ ident = TRUE;
+ }
+ break;
+
+ case SV_POTION_SLOW_POISON:
+ if (set_poisoned(p_ptr->poisoned / 2)) ident = TRUE;
+ break;
+
+ case SV_POTION_CURE_POISON:
+ if (set_poisoned(0)) ident = TRUE;
+ break;
+
+ case SV_POTION_BOLDNESS:
+ if (set_afraid(0)) ident = TRUE;
+ break;
+
+ case SV_POTION_SPEED:
+ if (!p_ptr->fast)
+ {
+ if (set_fast(randint1(25) + 15, FALSE)) ident = TRUE;
+ }
+ else
+ {
+ (void)set_fast(p_ptr->fast + 5, FALSE);
+ }
+ break;
+
+ case SV_POTION_RESIST_HEAT:
+ if (set_oppose_fire(p_ptr->oppose_fire + randint1(10) + 10, FALSE))
+ {
+ ident = TRUE;
+ }
+ break;
+
+ case SV_POTION_RESIST_COLD:
+ if (set_oppose_cold(p_ptr->oppose_cold + randint1(10) + 10, FALSE))
+ {
+ ident = TRUE;
+ }
+ break;
+
+ case SV_POTION_HEROISM:
+ ident = heroism(25);
+ break;
+
+ case SV_POTION_BESERK_STRENGTH:
+ ident = berserk(randint1(25) + 25);
+ break;
+
+ case SV_POTION_CURE_LIGHT:
+ ident = cure_light_wounds(2, 8);
+ break;
+
+ case SV_POTION_CURE_SERIOUS:
+ ident = cure_serious_wounds(4, 8);
+ break;
+
+ case SV_POTION_CURE_CRITICAL:
+ ident = cure_critical_wounds(damroll(6, 8));
+ break;
+
+ case SV_POTION_HEALING:
+ ident = cure_critical_wounds(300);
+ break;
+
+ case SV_POTION_STAR_HEALING:
+ ident = cure_critical_wounds(1200);
+ break;
+
+ case SV_POTION_LIFE:
+ ident = life_stream(TRUE, TRUE);
+ break;
+
+ case SV_POTION_RESTORE_MANA:
+ ident = restore_mana(TRUE);
+ break;
+
+ case SV_POTION_RESTORE_EXP:
+ if (restore_level()) ident = TRUE;
+ break;
+
+ case SV_POTION_RES_STR:
+ if (do_res_stat(A_STR)) ident = TRUE;
+ break;
+
+ case SV_POTION_RES_INT:
+ if (do_res_stat(A_INT)) ident = TRUE;
+ break;
+
+ case SV_POTION_RES_WIS:
+ if (do_res_stat(A_WIS)) ident = TRUE;
+ break;
+
+ case SV_POTION_RES_DEX:
+ if (do_res_stat(A_DEX)) ident = TRUE;
+ break;
+
+ case SV_POTION_RES_CON:
+ if (do_res_stat(A_CON)) ident = TRUE;
+ break;
+
+ case SV_POTION_RES_CHR:
+ if (do_res_stat(A_CHR)) ident = TRUE;
+ break;
+
+ case SV_POTION_INC_STR:
+ if (do_inc_stat(A_STR)) ident = TRUE;
+ break;
+
+ case SV_POTION_INC_INT:
+ if (do_inc_stat(A_INT)) ident = TRUE;
+ break;
+
+ case SV_POTION_INC_WIS:
+ if (do_inc_stat(A_WIS)) ident = TRUE;
+ break;
+
+ case SV_POTION_INC_DEX:
+ if (do_inc_stat(A_DEX)) ident = TRUE;
+ break;
+
+ case SV_POTION_INC_CON:
+ if (do_inc_stat(A_CON)) ident = TRUE;
+ break;
+
+ case SV_POTION_INC_CHR:
+ if (do_inc_stat(A_CHR)) ident = TRUE;
+ break;
+
+ case SV_POTION_AUGMENTATION:
+ if (do_inc_stat(A_STR)) ident = TRUE;
+ if (do_inc_stat(A_INT)) ident = TRUE;
+ if (do_inc_stat(A_WIS)) ident = TRUE;
+ if (do_inc_stat(A_DEX)) ident = TRUE;
+ if (do_inc_stat(A_CON)) ident = TRUE;
+ if (do_inc_stat(A_CHR)) ident = TRUE;
+ break;
+
+ case SV_POTION_ENLIGHTENMENT:
+ msg_print(_("自分の置かれている状況が脳裏に浮かんできた...", "An image of your surroundings forms in your mind..."));
+ chg_virtue(V_KNOWLEDGE, 1);
+ chg_virtue(V_ENLIGHTEN, 1);
+ wiz_lite(FALSE);
+ ident = TRUE;
+ break;
+
+ case SV_POTION_STAR_ENLIGHTENMENT:
+ msg_print(_("更なる啓蒙を感じた...", "You begin to feel more enlightened..."));
+ chg_virtue(V_KNOWLEDGE, 1);
+ chg_virtue(V_ENLIGHTEN, 2);
+ msg_print(NULL);
+ wiz_lite(FALSE);
+ (void)do_inc_stat(A_INT);
+ (void)do_inc_stat(A_WIS);
+ (void)detect_traps(DETECT_RAD_DEFAULT, TRUE);
+ (void)detect_doors(DETECT_RAD_DEFAULT);
+ (void)detect_stairs(DETECT_RAD_DEFAULT);
+ (void)detect_treasure(DETECT_RAD_DEFAULT);
+ (void)detect_objects_gold(DETECT_RAD_DEFAULT);
+ (void)detect_objects_normal(DETECT_RAD_DEFAULT);
+ identify_pack();
+ self_knowledge();
+ ident = TRUE;
+ break;
+
+ case SV_POTION_SELF_KNOWLEDGE:
+ msg_print(_("自分自身のことが少しは分かった気がする...", "You begin to know yourself a little better..."));
+ msg_print(NULL);
+ self_knowledge();
+ ident = TRUE;
+ break;
+
+ case SV_POTION_EXPERIENCE:
+ if (p_ptr->prace == RACE_ANDROID) break;
+ chg_virtue(V_ENLIGHTEN, 1);
+ if (p_ptr->exp < PY_MAX_EXP)
+ {
+ s32b ee = (p_ptr->exp / 2) + 10;
+ if (ee > 100000L) ee = 100000L;
+ msg_print(_("更に経験を積んだような気がする。", "You feel more experienced."));
+ gain_exp(ee);
+ ident = TRUE;
+ }
+ break;
+
+ case SV_POTION_RESISTANCE:
+ (void)set_oppose_acid(p_ptr->oppose_acid + randint1(20) + 20, FALSE);
+ (void)set_oppose_elec(p_ptr->oppose_elec + randint1(20) + 20, FALSE);
+ (void)set_oppose_fire(p_ptr->oppose_fire + randint1(20) + 20, FALSE);
+ (void)set_oppose_cold(p_ptr->oppose_cold + randint1(20) + 20, FALSE);
+ (void)set_oppose_pois(p_ptr->oppose_pois + randint1(20) + 20, FALSE);
+ ident = TRUE;
+ break;
+
+ case SV_POTION_CURING:
+ if (true_healing(50)) ident = TRUE;
+ break;
+
+ case SV_POTION_INVULNERABILITY:
+ (void)set_invuln(p_ptr->invuln + randint1(4) + 4, FALSE);
+ ident = TRUE;
+ break;
+
+ case SV_POTION_NEW_LIFE:
+ roll_hitdice(0L);
+ get_max_stats();
+ p_ptr->update |= PU_BONUS;
+ lose_all_mutations();
+ ident = TRUE;
+ break;
+
+ case SV_POTION_NEO_TSUYOSHI:
+ (void)set_image(0);
+ (void)set_tsuyoshi(p_ptr->tsuyoshi + randint1(100) + 100, FALSE);
+ ident = TRUE;
+ break;
+
+ case SV_POTION_TSUYOSHI:
+ msg_print(_("「オクレ兄さん!」", "Brother OKURE!"));
+ msg_print(NULL);
+ p_ptr->tsuyoshi = 1;
+ (void)set_tsuyoshi(0, TRUE);
+ if (!p_ptr->resist_chaos)
+ {
+ (void)set_image(50 + randint1(50));
+ }
+ ident = TRUE;
+ break;
+
+ case SV_POTION_POLYMORPH:
+ if ((p_ptr->muta1 || p_ptr->muta2 || p_ptr->muta3) && one_in_(23))
+ {
+ lose_all_mutations();
+ }
+ else
+ {
+ do
+ {
+ if (one_in_(2))
+ {
+ if(gain_random_mutation(0)) ident = TRUE;
+ }
+ else if (lose_mutation(0)) ident = TRUE;
+ } while(!ident || one_in_(2));
+ }
+ break;
+ }
+ }
+
+ if (prace_is_(RACE_SKELETON))
+ {
+ msg_print(_("液体の一部はあなたのアゴを素通りして落ちた!", "Some of the fluid falls through your jaws!"));
+ (void)potion_smash_effect(0, p_ptr->y, p_ptr->x, q_ptr->k_idx);
+ }
+ p_ptr->update |= (PU_COMBINE | PU_REORDER);
+
+ if (!(object_is_aware(q_ptr)))
+ {
+ chg_virtue(V_PATIENCE, -1);
+ chg_virtue(V_CHANCE, 1);
+ chg_virtue(V_KNOWLEDGE, -1);
+ }
+
+ /* The item has been tried */
+ object_tried(q_ptr);
+
+ /* An identification was made */
+ if (ident && !object_is_aware(q_ptr))
+ {
+ object_aware(q_ptr);
+ gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev);
+ }
+
+ p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
+
+ /* Potions can feed the player */
+ switch (p_ptr->mimic_form)
+ {
+ case MIMIC_NONE:
+ switch (p_ptr->prace)
+ {
+ case RACE_VAMPIRE:
+ (void)set_food(p_ptr->food + (q_ptr->pval / 10));
+ break;
+ case RACE_SKELETON:
+ /* Do nothing */
+ break;
+ case RACE_GOLEM:
+ case RACE_ZOMBIE:
+ case RACE_DEMON:
+ case RACE_SPECTRE:
+ set_food(p_ptr->food + ((q_ptr->pval) / 20));
+ break;
+ case RACE_ANDROID:
+ if (q_ptr->tval == TV_FLASK)
+ {
+ msg_print(_("オイルを補給した。", "You replenish yourself with the oil."));
+ set_food(p_ptr->food + 5000);
+ }
+ else
+ {
+ set_food(p_ptr->food + ((q_ptr->pval) / 20));
+ }
+ break;
+ case RACE_ENT:
+ msg_print(_("水分を取り込んだ。", "You are moistened."));
+ set_food(MIN(p_ptr->food + q_ptr->pval + MAX(0, q_ptr->pval * 10) + 2000, PY_FOOD_MAX - 1));
+ break;
+ default:
+ (void)set_food(p_ptr->food + q_ptr->pval);
+ break;
+ }
+ break;
+ case MIMIC_DEMON:
+ case MIMIC_DEMON_LORD:
+ set_food(p_ptr->food + ((q_ptr->pval) / 20));
+ break;
+ case MIMIC_VAMPIRE:
+ (void)set_food(p_ptr->food + (q_ptr->pval / 10));
+ break;
+ default:
+ (void)set_food(p_ptr->food + q_ptr->pval);
+ break;
+ }
+}
+
+
+
+/*!
+ * @brief 薬を飲むコマンドのメインルーチン /
+ * Quaff some potion (from the pack or floor)
+ * @return なし
+ */
+void do_cmd_quaff_potion(void)
+{
+ OBJECT_IDX item;
+ concptr q, s;
+
+ if (p_ptr->wild_mode)
+ {
+ return;
+ }
+
+ if (cmd_limit_arena(p_ptr)) return;
+
+ if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN))
+ {
+ set_action(ACTION_NONE);
+ }
+
+ /* Restrict choices to potions */
+ item_tester_hook = item_tester_hook_quaff;
+
+ q = _("どの薬を飲みますか? ", "Quaff which potion? ");
+ s = _("飲める薬がない。", "You have no potions to quaff.");
+
+ if (!choose_object(&item, q, s, (USE_INVEN | USE_FLOOR))) return;
+
+ /* Quaff the potion */
+ do_cmd_quaff_potion_aux(item);
+}
-\r
-extern void do_cmd_quaff_potion(void);\r
-extern void do_cmd_quaff_potion_aux(INVENTORY_IDX item);\r
-\r
+
+extern void do_cmd_quaff_potion(void);
+extern void do_cmd_quaff_potion_aux(INVENTORY_IDX item);
+
-/*!\r
- * @file cmd-read.c\r
- * @brief プレイヤーの読むコマンド実装\r
- * @date 2018/09/07\r
- * @details\r
- * cmd6.cより分離。\r
- */\r
-\r
-#include "angband.h"\r
-#include "object-hook.h"\r
-#include "artifact.h"\r
-#include "avatar.h"\r
-#include "player-status.h"\r
-#include "rumor.h"\r
-#include "realm-hex.h"\r
-\r
-#include "spells-object.h"\r
-#include "spells-summon.h"\r
-#include "spells-status.h"\r
-\r
-/*!\r
- * @brief 巻物を読むコマンドのサブルーチン\r
- * Read a scroll (from the pack or floor).\r
- * @param item 読むオブジェクトの所持品ID\r
- * @param known 判明済ならばTRUE\r
- * @return なし\r
- * @details\r
- * <pre>\r
- * Certain scrolls can be "aborted" without losing the scroll. These\r
- * include scrolls with no effects but recharge or identify, which are\r
- * cancelled before use. XXX Reading them still takes a turn, though.\r
- * </pre>\r
- */\r
-void do_cmd_read_scroll_aux(INVENTORY_IDX item, bool known)\r
-{\r
- int k, used_up, ident, lev;\r
- object_type *o_ptr;\r
-\r
-\r
- /* Get the item (in the pack) */\r
- if (item >= 0)\r
- {\r
- o_ptr = &inventory[item];\r
- }\r
-\r
- /* Get the item (on the floor) */\r
- else\r
- {\r
- o_ptr = &o_list[0 - item];\r
- }\r
-\r
- take_turn(p_ptr, 100);;\r
- if (cmd_limit_time_walk(p_ptr)) return;\r
-\r
- if (p_ptr->pclass == CLASS_BERSERKER)\r
- {\r
- msg_print(_("巻物なんて読めない。", "You cannot read."));\r
- return;\r
- }\r
-\r
- if (music_singing_any()) stop_singing();\r
-\r
- /* Hex */\r
- if (hex_spelling_any() && ((p_ptr->lev < 35) || hex_spell_fully())) stop_hex_spell_all();\r
-\r
- /* Not identified yet */\r
- ident = FALSE;\r
-\r
- /* Object level */\r
- lev = k_info[o_ptr->k_idx].level;\r
-\r
- /* Assume the scroll will get used up */\r
- used_up = TRUE;\r
-\r
- if (o_ptr->tval == TV_SCROLL)\r
- {\r
- /* Analyze the scroll */\r
- switch (o_ptr->sval)\r
- {\r
- case SV_SCROLL_DARKNESS:\r
- {\r
- if (!(p_ptr->resist_blind) && !(p_ptr->resist_dark))\r
- {\r
- (void)set_blind(p_ptr->blind + 3 + randint1(5));\r
- }\r
- if (unlite_area(10, 3)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_AGGRAVATE_MONSTER:\r
- {\r
- msg_print(_("カン高くうなる様な音が辺りを覆った。", "There is a high pitched humming noise."));\r
- aggravate_monsters(0);\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_CURSE_ARMOR:\r
- {\r
- if (curse_armor()) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_CURSE_WEAPON:\r
- {\r
- k = 0;\r
- if (has_melee_weapon(INVEN_RARM))\r
- {\r
- k = INVEN_RARM;\r
- if (has_melee_weapon(INVEN_LARM) && one_in_(2)) k = INVEN_LARM;\r
- }\r
- else if (has_melee_weapon(INVEN_LARM)) k = INVEN_LARM;\r
- if (k && curse_weapon(FALSE, k)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_SUMMON_MONSTER:\r
- {\r
- for (k = 0; k < randint1(3); k++)\r
- {\r
- if (summon_specific(0, p_ptr->y, p_ptr->x, dun_level, 0, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0'))\r
- {\r
- ident = TRUE;\r
- }\r
- }\r
- break;\r
- }\r
-\r
- case SV_SCROLL_SUMMON_UNDEAD:\r
- {\r
- for (k = 0; k < randint1(3); k++)\r
- {\r
- if (summon_specific(0, p_ptr->y, p_ptr->x, dun_level, SUMMON_UNDEAD, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0'))\r
- {\r
- ident = TRUE;\r
- }\r
- }\r
- break;\r
- }\r
-\r
- case SV_SCROLL_SUMMON_PET:\r
- {\r
- if (summon_specific(-1, p_ptr->y, p_ptr->x, dun_level, 0, (PM_ALLOW_GROUP | PM_FORCE_PET), '\0'))\r
- {\r
- ident = TRUE;\r
- }\r
- break;\r
- }\r
-\r
- case SV_SCROLL_SUMMON_KIN:\r
- {\r
- if (summon_kin_player(p_ptr->lev, p_ptr->y, p_ptr->x, (PM_FORCE_PET | PM_ALLOW_GROUP)))\r
- {\r
- ident = TRUE;\r
- }\r
- break;\r
- }\r
-\r
- case SV_SCROLL_TRAP_CREATION:\r
- {\r
- if (trap_creation(p_ptr->y, p_ptr->x)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_PHASE_DOOR:\r
- {\r
- teleport_player(10, 0L);\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_TELEPORT:\r
- {\r
- teleport_player(100, 0L);\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_TELEPORT_LEVEL:\r
- {\r
- (void)teleport_level(0);\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_WORD_OF_RECALL:\r
- {\r
- if (!recall_player(p_ptr, randint0(21) + 15)) used_up = FALSE;\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_IDENTIFY:\r
- {\r
- if (!ident_spell(FALSE)) used_up = FALSE;\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_STAR_IDENTIFY:\r
- {\r
- if (!identify_fully(FALSE)) used_up = FALSE;\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_REMOVE_CURSE:\r
- {\r
- if (remove_curse())\r
- {\r
- ident = TRUE;\r
- }\r
- break;\r
- }\r
-\r
- case SV_SCROLL_STAR_REMOVE_CURSE:\r
- {\r
- if (remove_all_curse())\r
- {\r
- ident = TRUE;\r
- }\r
- break;\r
- }\r
-\r
- case SV_SCROLL_ENCHANT_ARMOR:\r
- {\r
- ident = TRUE;\r
- if (!enchant_spell(0, 0, 1)) used_up = FALSE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_ENCHANT_WEAPON_TO_HIT:\r
- {\r
- if (!enchant_spell(1, 0, 0)) used_up = FALSE;\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_ENCHANT_WEAPON_TO_DAM:\r
- {\r
- if (!enchant_spell(0, 1, 0)) used_up = FALSE;\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_STAR_ENCHANT_ARMOR:\r
- {\r
- if (!enchant_spell(0, 0, randint1(3) + 2)) used_up = FALSE;\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_STAR_ENCHANT_WEAPON:\r
- {\r
- if (!enchant_spell(randint1(3), randint1(3), 0)) used_up = FALSE;\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_RECHARGING:\r
- {\r
- if (!recharge(130)) used_up = FALSE;\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_MUNDANITY:\r
- {\r
- ident = TRUE;\r
- if (!mundane_spell(FALSE)) used_up = FALSE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_LIGHT:\r
- {\r
- if (lite_area(damroll(2, 8), 2)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_MAPPING:\r
- {\r
- map_area(DETECT_RAD_MAP);\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_DETECT_GOLD:\r
- {\r
- if (detect_treasure(DETECT_RAD_DEFAULT)) ident = TRUE;\r
- if (detect_objects_gold(DETECT_RAD_DEFAULT)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_DETECT_ITEM:\r
- {\r
- if (detect_objects_normal(DETECT_RAD_DEFAULT)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_DETECT_TRAP:\r
- {\r
- if (detect_traps(DETECT_RAD_DEFAULT, known)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_DETECT_DOOR:\r
- {\r
- if (detect_doors(DETECT_RAD_DEFAULT)) ident = TRUE;\r
- if (detect_stairs(DETECT_RAD_DEFAULT)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_DETECT_INVIS:\r
- {\r
- if (detect_monsters_invis(DETECT_RAD_DEFAULT)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_SATISFY_HUNGER:\r
- {\r
- if (set_food(PY_FOOD_MAX - 1)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_BLESSING:\r
- {\r
- if (set_blessed(p_ptr->blessed + randint1(12) + 6, FALSE)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_HOLY_CHANT:\r
- {\r
- if (set_blessed(p_ptr->blessed + randint1(24) + 12, FALSE)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_HOLY_PRAYER:\r
- {\r
- if (set_blessed(p_ptr->blessed + randint1(48) + 24, FALSE)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_MONSTER_CONFUSION:\r
- {\r
- if (!(p_ptr->special_attack & ATTACK_CONFUSE))\r
- {\r
- msg_print(_("手が輝き始めた。", "Your hands begin to glow."));\r
- p_ptr->special_attack |= ATTACK_CONFUSE;\r
- p_ptr->redraw |= (PR_STATUS);\r
- ident = TRUE;\r
- }\r
- break;\r
- }\r
-\r
- case SV_SCROLL_PROTECTION_FROM_EVIL:\r
- {\r
- k = 3 * p_ptr->lev;\r
- if (set_protevil(p_ptr->protevil + randint1(25) + k, FALSE)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_RUNE_OF_PROTECTION:\r
- {\r
- warding_glyph();\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_TRAP_DOOR_DESTRUCTION:\r
- {\r
- if (destroy_doors_touch()) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_STAR_DESTRUCTION:\r
- {\r
- if (destroy_area(p_ptr->y, p_ptr->x, 13 + randint0(5), FALSE))\r
- ident = TRUE;\r
- else\r
- msg_print(_("ダンジョンが揺れた...", "The dungeon trembles..."));\r
-\r
- break;\r
- }\r
-\r
- case SV_SCROLL_DISPEL_UNDEAD:\r
- {\r
- if (dispel_undead(80)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_SPELL:\r
- {\r
- if ((p_ptr->pclass == CLASS_WARRIOR) ||\r
- (p_ptr->pclass == CLASS_IMITATOR) ||\r
- (p_ptr->pclass == CLASS_MINDCRAFTER) ||\r
- (p_ptr->pclass == CLASS_SORCERER) ||\r
- (p_ptr->pclass == CLASS_ARCHER) ||\r
- (p_ptr->pclass == CLASS_MAGIC_EATER) ||\r
- (p_ptr->pclass == CLASS_RED_MAGE) ||\r
- (p_ptr->pclass == CLASS_SAMURAI) ||\r
- (p_ptr->pclass == CLASS_BLUE_MAGE) ||\r
- (p_ptr->pclass == CLASS_CAVALRY) ||\r
- (p_ptr->pclass == CLASS_BERSERKER) ||\r
- (p_ptr->pclass == CLASS_SMITH) ||\r
- (p_ptr->pclass == CLASS_MIRROR_MASTER) ||\r
- (p_ptr->pclass == CLASS_NINJA) ||\r
- (p_ptr->pclass == CLASS_SNIPER)) break;\r
- p_ptr->add_spells++;\r
- p_ptr->update |= (PU_SPELLS);\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_GENOCIDE:\r
- {\r
- (void)symbol_genocide(300, TRUE);\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_MASS_GENOCIDE:\r
- {\r
- (void)mass_genocide(300, TRUE);\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_ACQUIREMENT:\r
- {\r
- acquirement(p_ptr->y, p_ptr->x, 1, TRUE, FALSE, FALSE);\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_STAR_ACQUIREMENT:\r
- {\r
- acquirement(p_ptr->y, p_ptr->x, randint1(2) + 1, TRUE, FALSE, FALSE);\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- /* New Hengband scrolls */\r
- case SV_SCROLL_FIRE:\r
- {\r
- fire_ball(GF_FIRE, 0, 666, 4);\r
- /* Note: "Double" damage since it is centered on the player ... */\r
- if (!(IS_OPPOSE_FIRE() || p_ptr->resist_fire || p_ptr->immune_fire))\r
- take_hit(DAMAGE_NOESCAPE, 50+randint1(50), _("炎の巻物", "a Scroll of Fire"), -1);\r
-\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
-\r
- case SV_SCROLL_ICE:\r
- {\r
- fire_ball(GF_ICE, 0, 777, 4);\r
- if (!(IS_OPPOSE_COLD() || p_ptr->resist_cold || p_ptr->immune_cold))\r
- take_hit(DAMAGE_NOESCAPE, 100+randint1(100), _("氷の巻物", "a Scroll of Ice"), -1);\r
-\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_CHAOS:\r
- {\r
- fire_ball(GF_CHAOS, 0, 1000, 4);\r
- if (!p_ptr->resist_chaos)\r
- take_hit(DAMAGE_NOESCAPE, 111+randint1(111), _("ログルスの巻物", "a Scroll of Logrus"), -1);\r
-\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_RUMOR:\r
- {\r
- msg_print(_("巻物にはメッセージが書かれている:", "There is message on the scroll. It says:"));\r
- msg_print(NULL);\r
- display_rumor(TRUE);\r
- msg_print(NULL);\r
- msg_print(_("巻物は煙を立てて消え去った!", "The scroll disappears in a puff of smoke!"));\r
-\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_ARTIFACT:\r
- {\r
- ident = TRUE;\r
- if (!artifact_scroll()) used_up = FALSE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_RESET_RECALL:\r
- {\r
- ident = TRUE;\r
- if (!reset_recall()) used_up = FALSE;\r
- break;\r
- }\r
-\r
- case SV_SCROLL_AMUSEMENT:\r
- {\r
- ident = TRUE;\r
- amusement(p_ptr->y, p_ptr->x, 1, FALSE);\r
- break;\r
- }\r
-\r
- case SV_SCROLL_STAR_AMUSEMENT:\r
- {\r
- ident = TRUE;\r
- amusement(p_ptr->y, p_ptr->x, randint1(2) + 1, FALSE);\r
- break;\r
- }\r
- }\r
- }\r
- else if (o_ptr->name1 == ART_GHB)\r
- {\r
- msg_print(_("私は苦労して『グレーター・ヘル=ビースト』を倒した。", "I had a very hard time to kill the Greater hell-beast, "));\r
- msg_print(_("しかし手に入ったのはこのきたないTシャツだけだった。", "but all I got was this lousy t-shirt!"));\r
- used_up = FALSE;\r
- }\r
- else if (o_ptr->name1 == ART_POWER)\r
- {\r
- msg_print(_("「一つの指輪は全てを統べ、", "'One Ring to rule them all, "));\r
- msg_print(NULL);\r
- msg_print(_("一つの指輪は全てを見つけ、", "One Ring to find them, "));\r
- msg_print(NULL);\r
- msg_print(_("一つの指輪は全てを捕らえて", "One Ring to bring them all "));\r
- msg_print(NULL);\r
- msg_print(_("暗闇の中に繋ぎとめる。」", "and in the darkness bind them.'"));\r
- used_up = FALSE;\r
- }\r
- else if (o_ptr->tval==TV_PARCHMENT)\r
- {\r
- concptr q;\r
- GAME_TEXT o_name[MAX_NLEN];\r
- char buf[1024];\r
- screen_save();\r
-\r
- q=format("book-%d_jp.txt",o_ptr->sval);\r
-\r
- /* Display object description */\r
- object_desc(o_name, o_ptr, OD_NAME_ONLY);\r
-\r
- /* Build the filename */\r
- path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, q);\r
-\r
- /* Peruse the help file */\r
- (void)show_file(TRUE, buf, o_name, 0, 0);\r
- screen_load();\r
-\r
- used_up=FALSE;\r
- }\r
-\r
- p_ptr->update |= (PU_COMBINE | PU_REORDER);\r
-\r
- if (!(object_is_aware(o_ptr)))\r
- {\r
- chg_virtue(V_PATIENCE, -1);\r
- chg_virtue(V_CHANCE, 1);\r
- chg_virtue(V_KNOWLEDGE, -1);\r
- }\r
-\r
- /* The item was tried */\r
- object_tried(o_ptr);\r
-\r
- /* An identification was made */\r
- if (ident && !object_is_aware(o_ptr))\r
- {\r
- object_aware(o_ptr);\r
- gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev);\r
- }\r
-\r
- p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);\r
-\r
-\r
- /* Hack -- allow certain scrolls to be "preserved" */\r
- if (!used_up)\r
- {\r
- return;\r
- }\r
-\r
- sound(SOUND_SCROLL);\r
-\r
- /* Destroy a scroll in the pack */\r
- if (item >= 0)\r
- {\r
- inven_item_increase(item, -1);\r
- inven_item_describe(item);\r
- inven_item_optimize(item);\r
- }\r
-\r
- /* Destroy a scroll on the floor */\r
- else\r
- {\r
- floor_item_increase(0 - item, -1);\r
- floor_item_describe(0 - item);\r
- floor_item_optimize(0 - item);\r
- }\r
-}\r
-\r
-/*!\r
- * @brief 読むコマンドのメインルーチン /\r
- * Eat some food (from the pack or floor)\r
- * @return なし\r
- */\r
-void do_cmd_read_scroll(void)\r
-{\r
- object_type *o_ptr;\r
- OBJECT_IDX item;\r
- concptr q, s;\r
-\r
- if (p_ptr->wild_mode)\r
- {\r
- return;\r
- }\r
-\r
- if (cmd_limit_arena(p_ptr)) return;\r
-\r
- if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN))\r
- {\r
- set_action(ACTION_NONE);\r
- }\r
-\r
- if (cmd_limit_blind(p_ptr)) return;\r
- if (cmd_limit_confused(p_ptr)) return;\r
-\r
- /* Restrict choices to scrolls */\r
- item_tester_hook = item_tester_hook_readable;\r
-\r
- q = _("どの巻物を読みますか? ", "Read which scroll? ");\r
- s = _("読める巻物がない。", "You have no scrolls to read.");\r
-\r
- o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR));\r
- if (!o_ptr) return;\r
-\r
- /* Read the scroll */\r
- do_cmd_read_scroll_aux(item, object_is_aware(o_ptr));\r
-}\r
+/*!
+ * @file cmd-read.c
+ * @brief プレイヤーの読むコマンド実装
+ * @date 2018/09/07
+ * @details
+ * cmd6.cより分離。
+ */
+
+#include "angband.h"
+#include "object-hook.h"
+#include "artifact.h"
+#include "avatar.h"
+#include "player-status.h"
+#include "rumor.h"
+#include "realm-hex.h"
+
+#include "spells-object.h"
+#include "spells-summon.h"
+#include "spells-status.h"
+
+/*!
+ * @brief 巻物を読むコマンドのサブルーチン
+ * Read a scroll (from the pack or floor).
+ * @param item 読むオブジェクトの所持品ID
+ * @param known 判明済ならばTRUE
+ * @return なし
+ * @details
+ * <pre>
+ * Certain scrolls can be "aborted" without losing the scroll. These
+ * include scrolls with no effects but recharge or identify, which are
+ * cancelled before use. XXX Reading them still takes a turn, though.
+ * </pre>
+ */
+void do_cmd_read_scroll_aux(INVENTORY_IDX item, bool known)
+{
+ int k, used_up, ident, lev;
+ object_type *o_ptr;
+
+
+ /* Get the item (in the pack) */
+ if (item >= 0)
+ {
+ o_ptr = &inventory[item];
+ }
+
+ /* Get the item (on the floor) */
+ else
+ {
+ o_ptr = &o_list[0 - item];
+ }
+
+ take_turn(p_ptr, 100);;
+ if (cmd_limit_time_walk(p_ptr)) return;
+
+ if (p_ptr->pclass == CLASS_BERSERKER)
+ {
+ msg_print(_("巻物なんて読めない。", "You cannot read."));
+ return;
+ }
+
+ if (music_singing_any()) stop_singing();
+
+ /* Hex */
+ if (hex_spelling_any() && ((p_ptr->lev < 35) || hex_spell_fully())) stop_hex_spell_all();
+
+ /* Not identified yet */
+ ident = FALSE;
+
+ /* Object level */
+ lev = k_info[o_ptr->k_idx].level;
+
+ /* Assume the scroll will get used up */
+ used_up = TRUE;
+
+ if (o_ptr->tval == TV_SCROLL)
+ {
+ /* Analyze the scroll */
+ switch (o_ptr->sval)
+ {
+ case SV_SCROLL_DARKNESS:
+ {
+ if (!(p_ptr->resist_blind) && !(p_ptr->resist_dark))
+ {
+ (void)set_blind(p_ptr->blind + 3 + randint1(5));
+ }
+ if (unlite_area(10, 3)) ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_AGGRAVATE_MONSTER:
+ {
+ msg_print(_("カン高くうなる様な音が辺りを覆った。", "There is a high pitched humming noise."));
+ aggravate_monsters(0);
+ ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_CURSE_ARMOR:
+ {
+ if (curse_armor()) ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_CURSE_WEAPON:
+ {
+ k = 0;
+ if (has_melee_weapon(INVEN_RARM))
+ {
+ k = INVEN_RARM;
+ if (has_melee_weapon(INVEN_LARM) && one_in_(2)) k = INVEN_LARM;
+ }
+ else if (has_melee_weapon(INVEN_LARM)) k = INVEN_LARM;
+ if (k && curse_weapon(FALSE, k)) ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_SUMMON_MONSTER:
+ {
+ for (k = 0; k < randint1(3); k++)
+ {
+ if (summon_specific(0, p_ptr->y, p_ptr->x, dun_level, 0, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0'))
+ {
+ ident = TRUE;
+ }
+ }
+ break;
+ }
+
+ case SV_SCROLL_SUMMON_UNDEAD:
+ {
+ for (k = 0; k < randint1(3); k++)
+ {
+ if (summon_specific(0, p_ptr->y, p_ptr->x, dun_level, SUMMON_UNDEAD, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0'))
+ {
+ ident = TRUE;
+ }
+ }
+ break;
+ }
+
+ case SV_SCROLL_SUMMON_PET:
+ {
+ if (summon_specific(-1, p_ptr->y, p_ptr->x, dun_level, 0, (PM_ALLOW_GROUP | PM_FORCE_PET), '\0'))
+ {
+ ident = TRUE;
+ }
+ break;
+ }
+
+ case SV_SCROLL_SUMMON_KIN:
+ {
+ if (summon_kin_player(p_ptr->lev, p_ptr->y, p_ptr->x, (PM_FORCE_PET | PM_ALLOW_GROUP)))
+ {
+ ident = TRUE;
+ }
+ break;
+ }
+
+ case SV_SCROLL_TRAP_CREATION:
+ {
+ if (trap_creation(p_ptr->y, p_ptr->x)) ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_PHASE_DOOR:
+ {
+ teleport_player(10, 0L);
+ ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_TELEPORT:
+ {
+ teleport_player(100, 0L);
+ ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_TELEPORT_LEVEL:
+ {
+ (void)teleport_level(0);
+ ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_WORD_OF_RECALL:
+ {
+ if (!recall_player(p_ptr, randint0(21) + 15)) used_up = FALSE;
+ ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_IDENTIFY:
+ {
+ if (!ident_spell(FALSE)) used_up = FALSE;
+ ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_STAR_IDENTIFY:
+ {
+ if (!identify_fully(FALSE)) used_up = FALSE;
+ ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_REMOVE_CURSE:
+ {
+ if (remove_curse())
+ {
+ ident = TRUE;
+ }
+ break;
+ }
+
+ case SV_SCROLL_STAR_REMOVE_CURSE:
+ {
+ if (remove_all_curse())
+ {
+ ident = TRUE;
+ }
+ break;
+ }
+
+ case SV_SCROLL_ENCHANT_ARMOR:
+ {
+ ident = TRUE;
+ if (!enchant_spell(0, 0, 1)) used_up = FALSE;
+ break;
+ }
+
+ case SV_SCROLL_ENCHANT_WEAPON_TO_HIT:
+ {
+ if (!enchant_spell(1, 0, 0)) used_up = FALSE;
+ ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_ENCHANT_WEAPON_TO_DAM:
+ {
+ if (!enchant_spell(0, 1, 0)) used_up = FALSE;
+ ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_STAR_ENCHANT_ARMOR:
+ {
+ if (!enchant_spell(0, 0, randint1(3) + 2)) used_up = FALSE;
+ ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_STAR_ENCHANT_WEAPON:
+ {
+ if (!enchant_spell(randint1(3), randint1(3), 0)) used_up = FALSE;
+ ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_RECHARGING:
+ {
+ if (!recharge(130)) used_up = FALSE;
+ ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_MUNDANITY:
+ {
+ ident = TRUE;
+ if (!mundane_spell(FALSE)) used_up = FALSE;
+ break;
+ }
+
+ case SV_SCROLL_LIGHT:
+ {
+ if (lite_area(damroll(2, 8), 2)) ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_MAPPING:
+ {
+ map_area(DETECT_RAD_MAP);
+ ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_DETECT_GOLD:
+ {
+ if (detect_treasure(DETECT_RAD_DEFAULT)) ident = TRUE;
+ if (detect_objects_gold(DETECT_RAD_DEFAULT)) ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_DETECT_ITEM:
+ {
+ if (detect_objects_normal(DETECT_RAD_DEFAULT)) ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_DETECT_TRAP:
+ {
+ if (detect_traps(DETECT_RAD_DEFAULT, known)) ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_DETECT_DOOR:
+ {
+ if (detect_doors(DETECT_RAD_DEFAULT)) ident = TRUE;
+ if (detect_stairs(DETECT_RAD_DEFAULT)) ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_DETECT_INVIS:
+ {
+ if (detect_monsters_invis(DETECT_RAD_DEFAULT)) ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_SATISFY_HUNGER:
+ {
+ if (set_food(PY_FOOD_MAX - 1)) ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_BLESSING:
+ {
+ if (set_blessed(p_ptr->blessed + randint1(12) + 6, FALSE)) ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_HOLY_CHANT:
+ {
+ if (set_blessed(p_ptr->blessed + randint1(24) + 12, FALSE)) ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_HOLY_PRAYER:
+ {
+ if (set_blessed(p_ptr->blessed + randint1(48) + 24, FALSE)) ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_MONSTER_CONFUSION:
+ {
+ if (!(p_ptr->special_attack & ATTACK_CONFUSE))
+ {
+ msg_print(_("手が輝き始めた。", "Your hands begin to glow."));
+ p_ptr->special_attack |= ATTACK_CONFUSE;
+ p_ptr->redraw |= (PR_STATUS);
+ ident = TRUE;
+ }
+ break;
+ }
+
+ case SV_SCROLL_PROTECTION_FROM_EVIL:
+ {
+ k = 3 * p_ptr->lev;
+ if (set_protevil(p_ptr->protevil + randint1(25) + k, FALSE)) ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_RUNE_OF_PROTECTION:
+ {
+ warding_glyph();
+ ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_TRAP_DOOR_DESTRUCTION:
+ {
+ if (destroy_doors_touch()) ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_STAR_DESTRUCTION:
+ {
+ if (destroy_area(p_ptr->y, p_ptr->x, 13 + randint0(5), FALSE))
+ ident = TRUE;
+ else
+ msg_print(_("ダンジョンが揺れた...", "The dungeon trembles..."));
+
+ break;
+ }
+
+ case SV_SCROLL_DISPEL_UNDEAD:
+ {
+ if (dispel_undead(80)) ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_SPELL:
+ {
+ if ((p_ptr->pclass == CLASS_WARRIOR) ||
+ (p_ptr->pclass == CLASS_IMITATOR) ||
+ (p_ptr->pclass == CLASS_MINDCRAFTER) ||
+ (p_ptr->pclass == CLASS_SORCERER) ||
+ (p_ptr->pclass == CLASS_ARCHER) ||
+ (p_ptr->pclass == CLASS_MAGIC_EATER) ||
+ (p_ptr->pclass == CLASS_RED_MAGE) ||
+ (p_ptr->pclass == CLASS_SAMURAI) ||
+ (p_ptr->pclass == CLASS_BLUE_MAGE) ||
+ (p_ptr->pclass == CLASS_CAVALRY) ||
+ (p_ptr->pclass == CLASS_BERSERKER) ||
+ (p_ptr->pclass == CLASS_SMITH) ||
+ (p_ptr->pclass == CLASS_MIRROR_MASTER) ||
+ (p_ptr->pclass == CLASS_NINJA) ||
+ (p_ptr->pclass == CLASS_SNIPER)) break;
+ p_ptr->add_spells++;
+ p_ptr->update |= (PU_SPELLS);
+ ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_GENOCIDE:
+ {
+ (void)symbol_genocide(300, TRUE);
+ ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_MASS_GENOCIDE:
+ {
+ (void)mass_genocide(300, TRUE);
+ ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_ACQUIREMENT:
+ {
+ acquirement(p_ptr->y, p_ptr->x, 1, TRUE, FALSE, FALSE);
+ ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_STAR_ACQUIREMENT:
+ {
+ acquirement(p_ptr->y, p_ptr->x, randint1(2) + 1, TRUE, FALSE, FALSE);
+ ident = TRUE;
+ break;
+ }
+
+ /* New Hengband scrolls */
+ case SV_SCROLL_FIRE:
+ {
+ fire_ball(GF_FIRE, 0, 666, 4);
+ /* Note: "Double" damage since it is centered on the player ... */
+ if (!(IS_OPPOSE_FIRE() || p_ptr->resist_fire || p_ptr->immune_fire))
+ take_hit(DAMAGE_NOESCAPE, 50+randint1(50), _("炎の巻物", "a Scroll of Fire"), -1);
+
+ ident = TRUE;
+ break;
+ }
+
+
+ case SV_SCROLL_ICE:
+ {
+ fire_ball(GF_ICE, 0, 777, 4);
+ if (!(IS_OPPOSE_COLD() || p_ptr->resist_cold || p_ptr->immune_cold))
+ take_hit(DAMAGE_NOESCAPE, 100+randint1(100), _("氷の巻物", "a Scroll of Ice"), -1);
+
+ ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_CHAOS:
+ {
+ fire_ball(GF_CHAOS, 0, 1000, 4);
+ if (!p_ptr->resist_chaos)
+ take_hit(DAMAGE_NOESCAPE, 111+randint1(111), _("ログルスの巻物", "a Scroll of Logrus"), -1);
+
+ ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_RUMOR:
+ {
+ msg_print(_("巻物にはメッセージが書かれている:", "There is message on the scroll. It says:"));
+ msg_print(NULL);
+ display_rumor(TRUE);
+ msg_print(NULL);
+ msg_print(_("巻物は煙を立てて消え去った!", "The scroll disappears in a puff of smoke!"));
+
+ ident = TRUE;
+ break;
+ }
+
+ case SV_SCROLL_ARTIFACT:
+ {
+ ident = TRUE;
+ if (!artifact_scroll()) used_up = FALSE;
+ break;
+ }
+
+ case SV_SCROLL_RESET_RECALL:
+ {
+ ident = TRUE;
+ if (!reset_recall()) used_up = FALSE;
+ break;
+ }
+
+ case SV_SCROLL_AMUSEMENT:
+ {
+ ident = TRUE;
+ amusement(p_ptr->y, p_ptr->x, 1, FALSE);
+ break;
+ }
+
+ case SV_SCROLL_STAR_AMUSEMENT:
+ {
+ ident = TRUE;
+ amusement(p_ptr->y, p_ptr->x, randint1(2) + 1, FALSE);
+ break;
+ }
+ }
+ }
+ else if (o_ptr->name1 == ART_GHB)
+ {
+ msg_print(_("私は苦労して『グレーター・ヘル=ビースト』を倒した。", "I had a very hard time to kill the Greater hell-beast, "));
+ msg_print(_("しかし手に入ったのはこのきたないTシャツだけだった。", "but all I got was this lousy t-shirt!"));
+ used_up = FALSE;
+ }
+ else if (o_ptr->name1 == ART_POWER)
+ {
+ msg_print(_("「一つの指輪は全てを統べ、", "'One Ring to rule them all, "));
+ msg_print(NULL);
+ msg_print(_("一つの指輪は全てを見つけ、", "One Ring to find them, "));
+ msg_print(NULL);
+ msg_print(_("一つの指輪は全てを捕らえて", "One Ring to bring them all "));
+ msg_print(NULL);
+ msg_print(_("暗闇の中に繋ぎとめる。」", "and in the darkness bind them.'"));
+ used_up = FALSE;
+ }
+ else if (o_ptr->tval==TV_PARCHMENT)
+ {
+ concptr q;
+ GAME_TEXT o_name[MAX_NLEN];
+ char buf[1024];
+ screen_save();
+
+ q=format("book-%d_jp.txt",o_ptr->sval);
+
+ /* Display object description */
+ object_desc(o_name, o_ptr, OD_NAME_ONLY);
+
+ /* Build the filename */
+ path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, q);
+
+ /* Peruse the help file */
+ (void)show_file(TRUE, buf, o_name, 0, 0);
+ screen_load();
+
+ used_up=FALSE;
+ }
+
+ p_ptr->update |= (PU_COMBINE | PU_REORDER);
+
+ if (!(object_is_aware(o_ptr)))
+ {
+ chg_virtue(V_PATIENCE, -1);
+ chg_virtue(V_CHANCE, 1);
+ chg_virtue(V_KNOWLEDGE, -1);
+ }
+
+ /* The item was tried */
+ object_tried(o_ptr);
+
+ /* An identification was made */
+ if (ident && !object_is_aware(o_ptr))
+ {
+ object_aware(o_ptr);
+ gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev);
+ }
+
+ p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
+
+
+ /* Hack -- allow certain scrolls to be "preserved" */
+ if (!used_up)
+ {
+ return;
+ }
+
+ sound(SOUND_SCROLL);
+
+ /* Destroy a scroll in the pack */
+ if (item >= 0)
+ {
+ inven_item_increase(item, -1);
+ inven_item_describe(item);
+ inven_item_optimize(item);
+ }
+
+ /* Destroy a scroll on the floor */
+ else
+ {
+ floor_item_increase(0 - item, -1);
+ floor_item_describe(0 - item);
+ floor_item_optimize(0 - item);
+ }
+}
+
+/*!
+ * @brief 読むコマンドのメインルーチン /
+ * Eat some food (from the pack or floor)
+ * @return なし
+ */
+void do_cmd_read_scroll(void)
+{
+ object_type *o_ptr;
+ OBJECT_IDX item;
+ concptr q, s;
+
+ if (p_ptr->wild_mode)
+ {
+ return;
+ }
+
+ if (cmd_limit_arena(p_ptr)) return;
+
+ if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN))
+ {
+ set_action(ACTION_NONE);
+ }
+
+ if (cmd_limit_blind(p_ptr)) return;
+ if (cmd_limit_confused(p_ptr)) return;
+
+ /* Restrict choices to scrolls */
+ item_tester_hook = item_tester_hook_readable;
+
+ q = _("どの巻物を読みますか? ", "Read which scroll? ");
+ s = _("読める巻物がない。", "You have no scrolls to read.");
+
+ o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR));
+ if (!o_ptr) return;
+
+ /* Read the scroll */
+ do_cmd_read_scroll_aux(item, object_is_aware(o_ptr));
+}
-\r
-\r
-extern void do_cmd_read_scroll_aux(INVENTORY_IDX item, bool known);\r
-extern void do_cmd_read_scroll(void);\r
+
+
+extern void do_cmd_read_scroll_aux(INVENTORY_IDX item, bool known);
+extern void do_cmd_read_scroll(void);
-/*!\r
- @file cmd-spell.c\r
- @brief 魔法のインターフェイスと発動 / Purpose: Do everything for each spell\r
- @date 2013/12/31\r
- @author\r
- 2013 Deskull rearranged comment for Doxygen.\r
- */\r
-\r
-#include "angband.h"\r
-#include "selfinfo.h"\r
-#include "spells-summon.h"\r
-#include "realm-arcane.h"\r
-#include "realm-chaos.h"\r
-#include "realm-craft.h"\r
-#include "realm-crusade.h"\r
-#include "realm-daemon.h"\r
-#include "realm-death.h"\r
-#include "realm-hex.h"\r
-#include "realm-hissatsu.h"\r
-#include "realm-life.h"\r
-#include "realm-nature.h"\r
-#include "realm-song.h"\r
-#include "realm-sorcery.h"\r
-#include "realm-trump.h"\r
-#include "angband.h"\r
-#include "avatar.h"\r
-#include "player-status.h"\r
-#include "object-hook.h"\r
-\r
-/*!\r
- * @brief\r
- * 魔法の効果を「キャプション:ダイス+定数値」のフォーマットで出力する / Generate dice info string such as "foo 2d10"\r
- * @param str キャプション\r
- * @param dice ダイス数\r
- * @param sides ダイス目\r
- * @param base 固定値\r
- * @return フォーマットに従い整形された文字列\r
- */\r
-concptr info_string_dice(concptr str, DICE_NUMBER dice, DICE_SID sides, int base)\r
-{\r
- /* Fix value */\r
- if (!dice)\r
- return format("%s%d", str, base);\r
-\r
- /* Dice only */\r
- else if (!base)\r
- return format("%s%dd%d", str, dice, sides);\r
-\r
- /* Dice plus base value */\r
- else\r
- return format("%s%dd%d%+d", str, dice, sides, base);\r
-}\r
-\r
-\r
-/*!\r
- * @brief 魔法によるダメージを出力する / Generate damage-dice info string such as "dam 2d10"\r
- * @param dice ダイス数\r
- * @param sides ダイス目\r
- * @param base 固定値\r
- * @return フォーマットに従い整形された文字列\r
- */\r
-concptr info_damage(DICE_NUMBER dice, DICE_SID sides, int base)\r
-{\r
- return info_string_dice(_("損傷:", "dam "), dice, sides, base);\r
-}\r
-\r
-/*!\r
- * @brief 魔法の効果時間を出力する / Generate duration info string such as "dur 20+1d20"\r
- * @param base 固定値\r
- * @param sides ダイス目\r
- * @return フォーマットに従い整形された文字列\r
- */\r
-concptr info_duration(int base, DICE_SID sides)\r
-{\r
- return format(_("期間:%d+1d%d", "dur %d+1d%d"), base, sides);\r
-}\r
-\r
-/*!\r
- * @brief 魔法の効果範囲を出力する / Generate range info string such as "range 5"\r
- * @param range 効果範囲\r
- * @return フォーマットに従い整形された文字列\r
- */\r
-concptr info_range(POSITION range)\r
-{\r
- return format(_("範囲:%d", "range %d"), range);\r
-}\r
-\r
-/*!\r
- * @brief 魔法による回復量を出力する / Generate heal info string such as "heal 2d8"\r
- * @param dice ダイス数\r
- * @param sides ダイス目\r
- * @param base 固定値\r
- * @return フォーマットに従い整形された文字列\r
- */\r
-concptr info_heal(DICE_NUMBER dice, DICE_SID sides, int base)\r
-{\r
- return info_string_dice(_("回復:", "heal "), dice, sides, base);\r
-}\r
-\r
-/*!\r
- * @brief 魔法効果発動までの遅延ターンを出力する / Generate delay info string such as "delay 15+1d15"\r
- * @param base 固定値\r
- * @param sides ダイス目\r
- * @return フォーマットに従い整形された文字列\r
- */\r
-concptr info_delay(int base, DICE_SID sides)\r
-{\r
- return format(_("遅延:%d+1d%d", "delay %d+1d%d"), base, sides);\r
-}\r
-\r
-\r
-/*!\r
- * @brief 魔法によるダメージを出力する(固定値&複数回処理) / Generate multiple-damage info string such as "dam 25 each"\r
- * @param dam 固定値\r
- * @return フォーマットに従い整形された文字列\r
- */\r
-concptr info_multi_damage(HIT_POINT dam)\r
-{\r
- return format(_("損傷:各%d", "dam %d each"), dam);\r
-}\r
-\r
-\r
-/*!\r
- * @brief 魔法によるダメージを出力する(ダイスのみ&複数回処理) / Generate multiple-damage-dice info string such as "dam 5d2 each"\r
- * @param dice ダイス数\r
- * @param sides ダイス目\r
- * @return フォーマットに従い整形された文字列\r
- */\r
-concptr info_multi_damage_dice(DICE_NUMBER dice, DICE_SID sides)\r
-{\r
- return format(_("損傷:各%dd%d", "dam %dd%d each"), dice, sides);\r
-}\r
-\r
-/*!\r
- * @brief 魔法による一般的な効力値を出力する(固定値) / Generate power info string such as "power 100"\r
- * @param power 固定値\r
- * @return フォーマットに従い整形された文字列\r
- */\r
-concptr info_power(int power)\r
-{\r
- return format(_("効力:%d", "power %d"), power);\r
-}\r
-\r
-\r
-/*!\r
- * @brief 魔法による一般的な効力値を出力する(ダイス値) / Generate power info string such as "power 100"\r
- * @param dice ダイス数\r
- * @param sides ダイス目\r
- * @return フォーマットに従い整形された文字列\r
- */\r
-/*\r
- * Generate power info string such as "power 1d100"\r
- */\r
-concptr info_power_dice(DICE_NUMBER dice, DICE_SID sides)\r
-{\r
- return format(_("効力:%dd%d", "power %dd%d"), dice, sides);\r
-}\r
-\r
-\r
-/*!\r
- * @brief 魔法の効果半径を出力する / Generate radius info string such as "rad 100"\r
- * @param rad 効果半径\r
- * @return フォーマットに従い整形された文字列\r
- */\r
-concptr info_radius(POSITION rad)\r
-{\r
- return format(_("半径:%d", "rad %d"), rad);\r
-}\r
-\r
-\r
-/*!\r
- * @brief 魔法効果の限界重量を出力する / Generate weight info string such as "max wgt 15"\r
- * @param weight 最大重量\r
- * @return フォーマットに従い整形された文字列\r
- */\r
-concptr info_weight(WEIGHT weight)\r
-{\r
-#ifdef JP\r
- return format("最大重量:%d.%dkg", lbtokg1(weight), lbtokg2(weight));\r
-#else\r
- return format("max wgt %d", weight/10);\r
-#endif\r
-}\r
-\r
-/*!\r
- * @brief 魔法処理のメインルーチン\r
- * @param realm 魔法領域のID\r
- * @param spell 各領域の魔法ID\r
- * @param mode 求める処理\r
- * @return 各領域魔法に各種テキストを求めた場合は文字列参照ポインタ、そうでない場合はNULLポインタを返す。\r
- */\r
-concptr do_spell(REALM_IDX realm, SPELL_IDX spell, BIT_FLAGS mode)\r
-{\r
- switch (realm)\r
- {\r
- case REALM_LIFE: return do_life_spell(spell, mode);\r
- case REALM_SORCERY: return do_sorcery_spell(spell, mode);\r
- case REALM_NATURE: return do_nature_spell(spell, mode);\r
- case REALM_CHAOS: return do_chaos_spell(spell, mode);\r
- case REALM_DEATH: return do_death_spell(spell, mode);\r
- case REALM_TRUMP: return do_trump_spell(spell, mode);\r
- case REALM_ARCANE: return do_arcane_spell(spell, mode);\r
- case REALM_CRAFT: return do_craft_spell(spell, mode);\r
- case REALM_DAEMON: return do_daemon_spell(spell, mode);\r
- case REALM_CRUSADE: return do_crusade_spell(spell, mode);\r
- case REALM_MUSIC: return do_music_spell(spell, mode);\r
- case REALM_HISSATSU: return do_hissatsu_spell(spell, mode);\r
- case REALM_HEX: return do_hex_spell(spell, mode);\r
- }\r
-\r
- return NULL;\r
-}\r
-\r
-\r
-/*!\r
- * @brief 領域魔法の閲覧、学習、使用選択するインターフェイス処理\r
- * Allow user to choose a spell/prayer from the given book.\r
- * @param sn 選択した魔法IDを返す参照ポインタ\r
- * @param prompt 魔法を利用する際の動詞表記\r
- * @param sval 魔道書のsval\r
- * @param learned 閲覧/使用選択ならばTRUE、学習処理ならFALSE\r
- * @param use_realm 魔法領域ID\r
- * @return\r
- * <pre>\r
- * If a valid spell is chosen, saves it in '*sn' and returns TRUE\r
- * If the user hits escape, returns FALSE, and set '*sn' to -1\r
- * If there are no legal choices, returns FALSE, and sets '*sn' to -2\r
- * The "prompt" should be "cast", "recite", or "study"\r
- * The "known" should be TRUE for cast/pray, FALSE for study\r
- * </pre>\r
- */\r
-static int get_spell(SPELL_IDX *sn, concptr prompt, OBJECT_SUBTYPE_VALUE sval, bool learned, REALM_IDX use_realm)\r
-{\r
- int i;\r
- SPELL_IDX spell = -1;\r
- int num = 0;\r
- int ask = TRUE;\r
- MANA_POINT need_mana;\r
- SPELL_IDX spells[64];\r
- bool flag, redraw, okay;\r
- char choice;\r
- const magic_type *s_ptr;\r
- char out_val[160];\r
- concptr p;\r
- COMMAND_CODE code;\r
-#ifdef JP\r
- char jverb_buf[128];\r
-#endif\r
- int menu_line = (use_menu ? 1 : 0);\r
-\r
- /* Get the spell, if available */\r
- if (repeat_pull(&code))\r
- {\r
- *sn = (SPELL_IDX)code;\r
- /* Verify the spell */\r
- if (spell_okay(*sn, learned, FALSE, use_realm))\r
- {\r
- /* Success */\r
- return (TRUE);\r
- }\r
- }\r
-\r
- p = spell_category_name(mp_ptr->spell_book);\r
-\r
- /* Extract spells */\r
- for (spell = 0; spell < 32; spell++)\r
- {\r
- /* Check for this spell */\r
- if ((fake_spell_flags[sval] & (1L << spell)))\r
- {\r
- /* Collect this spell */\r
- spells[num++] = spell;\r
- }\r
- }\r
-\r
- /* Assume no usable spells */\r
- okay = FALSE;\r
-\r
- /* Assume no spells available */\r
- (*sn) = -2;\r
-\r
- /* Check for "okay" spells */\r
- for (i = 0; i < num; i++)\r
- {\r
- /* Look for "okay" spells */\r
- if (spell_okay(spells[i], learned, FALSE, use_realm)) okay = TRUE;\r
- }\r
-\r
- /* No "okay" spells */\r
- if (!okay) return (FALSE);\r
- if (((use_realm) != p_ptr->realm1) && ((use_realm) != p_ptr->realm2) && (p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE)) return FALSE;\r
- if (((p_ptr->pclass == CLASS_SORCERER) || (p_ptr->pclass == CLASS_RED_MAGE)) && !is_magic(use_realm)) return FALSE;\r
- if ((p_ptr->pclass == CLASS_RED_MAGE) && ((use_realm) != REALM_ARCANE) && (sval > 1)) return FALSE;\r
-\r
- /* Assume cancelled */\r
- *sn = (-1);\r
-\r
- /* Nothing chosen yet */\r
- flag = FALSE;\r
-\r
- /* No redraw yet */\r
- redraw = FALSE;\r
-\r
- p_ptr->window |= (PW_SPELL);\r
- handle_stuff();\r
-\r
- /* Build a prompt (accept all spells) */\r
-#ifdef JP\r
- jverb(prompt, jverb_buf, JVERB_AND);\r
- (void)strnfmt(out_val, 78, "(%^s:%c-%c, '*'で一覧, ESCで中断) どの%sを%^sますか? ",\r
- p, I2A(0), I2A(num - 1), p, jverb_buf);\r
-#else\r
- (void)strnfmt(out_val, 78, "(%^ss %c-%c, *=List, ESC=exit) %^s which %s? ",\r
- p, I2A(0), I2A(num - 1), prompt, p);\r
-#endif\r
-\r
- /* Get a spell from the user */\r
-\r
- choice = (always_show_list || use_menu) ? ESCAPE : 1;\r
- while (!flag)\r
- {\r
- if (choice == ESCAPE) choice = ' ';\r
- else if (!get_com(out_val, &choice, TRUE))break;\r
-\r
- if (use_menu && choice != ' ')\r
- {\r
- switch (choice)\r
- {\r
- case '0':\r
- {\r
- screen_load();\r
- return FALSE;\r
- }\r
-\r
- case '8':\r
- case 'k':\r
- case 'K':\r
- {\r
- menu_line += (num - 1);\r
- break;\r
- }\r
-\r
- case '2':\r
- case 'j':\r
- case 'J':\r
- {\r
- menu_line++;\r
- break;\r
- }\r
-\r
- case 'x':\r
- case 'X':\r
- case '\r':\r
- case '\n':\r
- {\r
- i = menu_line - 1;\r
- ask = FALSE;\r
- break;\r
- }\r
- }\r
- if (menu_line > num) menu_line -= num;\r
- /* Display a list of spells */\r
- print_spells(menu_line, spells, num, 1, 15, use_realm);\r
- if (ask) continue;\r
- }\r
- else\r
- {\r
- /* Request redraw */\r
- if ((choice == ' ') || (choice == '*') || (choice == '?'))\r
- {\r
- /* Show the list */\r
- if (!redraw)\r
- {\r
- /* Show list */\r
- redraw = TRUE;\r
- screen_save();\r
-\r
- /* Display a list of spells */\r
- print_spells(menu_line, spells, num, 1, 15, use_realm);\r
- }\r
-\r
- /* Hide the list */\r
- else\r
- {\r
- if (use_menu) continue;\r
-\r
- /* Hide list */\r
- redraw = FALSE;\r
- screen_load();\r
- }\r
-\r
- /* Redo asking */\r
- continue;\r
- }\r
-\r
-\r
- /* Note verify */\r
- ask = (isupper(choice));\r
-\r
- /* Lowercase */\r
- if (ask) choice = (char)tolower(choice);\r
-\r
- /* Extract request */\r
- i = (islower(choice) ? A2I(choice) : -1);\r
- }\r
-\r
- /* Totally Illegal */\r
- if ((i < 0) || (i >= num))\r
- {\r
- bell();\r
- continue;\r
- }\r
-\r
- /* Save the spell index */\r
- spell = spells[i];\r
-\r
- /* Require "okay" spells */\r
- if (!spell_okay(spell, learned, FALSE, use_realm))\r
- {\r
- bell();\r
-#ifdef JP\r
- msg_format("その%sを%sことはできません。", p, prompt);\r
-#else\r
- msg_format("You may not %s that %s.", prompt, p);\r
-#endif\r
-\r
- continue;\r
- }\r
-\r
- /* Verify it */\r
- if (ask)\r
- {\r
- char tmp_val[160];\r
-\r
- /* Access the spell */\r
- if (!is_magic(use_realm))\r
- {\r
- s_ptr = &technic_info[use_realm - MIN_TECHNIC][spell];\r
- }\r
- else\r
- {\r
- s_ptr = &mp_ptr->info[use_realm - 1][spell];\r
- }\r
-\r
- /* Extract mana consumption rate */\r
- if (use_realm == REALM_HISSATSU)\r
- {\r
- need_mana = s_ptr->smana;\r
- }\r
- else\r
- {\r
- need_mana = mod_need_mana(s_ptr->smana, spell, use_realm);\r
- }\r
-\r
- /* Prompt */\r
-#ifdef JP\r
- jverb(prompt, jverb_buf, JVERB_AND);\r
- /* 英日切り替え機能に対応 */\r
- (void)strnfmt(tmp_val, 78, "%s(MP%d, 失敗率%d%%)を%sますか? ",\r
- do_spell(use_realm, spell, SPELL_NAME), need_mana,\r
- spell_chance(spell, use_realm), jverb_buf);\r
-#else\r
- (void)strnfmt(tmp_val, 78, "%^s %s (%d mana, %d%% fail)? ",\r
- prompt, do_spell(use_realm, spell, SPELL_NAME), need_mana,\r
- spell_chance(spell, use_realm));\r
-#endif\r
-\r
-\r
- /* Belay that order */\r
- if (!get_check(tmp_val)) continue;\r
- }\r
-\r
- /* Stop the loop */\r
- flag = TRUE;\r
- }\r
-\r
- if (redraw) screen_load();\r
-\r
- p_ptr->window |= (PW_SPELL);\r
- handle_stuff();\r
-\r
- /* Abort if needed */\r
- if (!flag) return FALSE;\r
-\r
- /* Save the choice */\r
- (*sn) = spell;\r
-\r
- repeat_push((COMMAND_CODE)spell);\r
-\r
- /* Success */\r
- return TRUE;\r
-}\r
-\r
-/*!\r
- * @brief プレイヤーの職業が練気術師の時、領域魔法と練気術を切り換える処理のインターフェイス\r
- * @param browse_only 魔法と技能の閲覧を行うならばTRUE\r
- * @return 魔道書を一冊も持っていないならTRUEを返す\r
- */\r
-static void confirm_use_force(bool browse_only)\r
-{\r
- char which;\r
- COMMAND_CODE code;\r
-\r
- /* Get the item index */\r
- if (repeat_pull(&code) && (code == INVEN_FORCE))\r
- {\r
- browse_only ? do_cmd_mind_browse() : do_cmd_mind();\r
- return;\r
- }\r
-\r
- /* Show the prompt */\r
- prt(_("('w'練気術, ESC) 'w'かESCを押してください。 ", "(w for the Force, ESC) Hit 'w' or ESC. "), 0, 0);\r
-\r
- while (1)\r
- {\r
- /* Get a key */\r
- which = inkey();\r
-\r
- if (which == ESCAPE) break;\r
- else if (which == 'w')\r
- {\r
- repeat_push(INVEN_FORCE);\r
- break;\r
- }\r
- }\r
-\r
- /* Clear the prompt line */\r
- prt("", 0, 0);\r
-\r
- if (which == 'w')\r
- {\r
- browse_only ? do_cmd_mind_browse() : do_cmd_mind();\r
- }\r
-}\r
-\r
-\r
-/*!\r
- * @brief プレイヤーの魔法と技能を閲覧するコマンドのメインルーチン /\r
- * Peruse the spells/prayers in a book\r
- * @return なし\r
- * @details\r
- * <pre>\r
- * Note that *all* spells in the book are listed\r
- *\r
- * Note that browsing is allowed while confused or blind,\r
- * and in the dark, primarily to allow browsing in stores.\r
- * </pre>\r
- */\r
-void do_cmd_browse(void)\r
-{\r
- OBJECT_IDX item;\r
- OBJECT_SUBTYPE_VALUE sval;\r
- REALM_IDX use_realm = 0;\r
- int j, line;\r
- SPELL_IDX spell = -1;\r
- int num = 0;\r
-\r
- SPELL_IDX spells[64];\r
- char temp[62 * 4];\r
-\r
- object_type *o_ptr;\r
-\r
- concptr q, s;\r
-\r
- /* Warriors are illiterate */\r
- if (!(p_ptr->realm1 || p_ptr->realm2) && (p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE))\r
- {\r
- msg_print(_("本を読むことができない!", "You cannot read books!"));\r
- return;\r
- }\r
-\r
- if (p_ptr->special_defense & KATA_MUSOU)\r
- {\r
- set_action(ACTION_NONE);\r
- }\r
-\r
- if (p_ptr->pclass == CLASS_FORCETRAINER)\r
- {\r
- if (player_has_no_spellbooks())\r
- {\r
- confirm_use_force(TRUE);\r
- return;\r
- }\r
- }\r
-\r
- /* Restrict choices to "useful" books */\r
- if (p_ptr->realm2 == REALM_NONE) item_tester_tval = mp_ptr->spell_book;\r
- else item_tester_hook = item_tester_learn_spell;\r
-\r
- q = _("どの本を読みますか? ", "Browse which book? ");\r
- s = _("読める本がない。", "You have no books that you can read.");\r
-\r
- o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR | (p_ptr->pclass == CLASS_FORCETRAINER ? USE_FORCE : 0)));\r
- if (!o_ptr)\r
- {\r
- if (item == INVEN_FORCE) /* the_force */\r
- {\r
- do_cmd_mind_browse();\r
- return;\r
- }\r
- return;\r
- }\r
-\r
- /* Access the item's sval */\r
- sval = o_ptr->sval;\r
-\r
- use_realm = tval2realm(o_ptr->tval);\r
-\r
- /* Track the object kind */\r
- object_kind_track(o_ptr->k_idx);\r
- handle_stuff();\r
-\r
- /* Extract spells */\r
- for (spell = 0; spell < 32; spell++)\r
- {\r
- /* Check for this spell */\r
- if ((fake_spell_flags[sval] & (1L << spell)))\r
- {\r
- /* Collect this spell */\r
- spells[num++] = spell;\r
- }\r
- }\r
-\r
- screen_save();\r
- prt("", 0, 0);\r
-\r
- /* Keep browsing spells. Exit browsing on cancel. */\r
- while (TRUE)\r
- {\r
- /* Ask for a spell, allow cancel */\r
- if (!get_spell(&spell, _("読む", "browse"), o_ptr->sval, TRUE, use_realm))\r
- {\r
- /* If cancelled, leave immediately. */\r
- if (spell == -1) break;\r
-\r
- /* Display a list of spells */\r
- print_spells(0, spells, num, 1, 15, use_realm);\r
-\r
- /* Notify that there's nothing to see, and wait. */\r
- if (use_realm == REALM_HISSATSU)\r
- prt(_("読める技がない。", "No techniques to browse."), 0, 0);\r
- else\r
- prt(_("読める呪文がない。", "No spells to browse."), 0, 0);\r
- (void)inkey();\r
-\r
- screen_load();\r
-\r
- return;\r
- }\r
-\r
- /* Clear lines, position cursor (really should use strlen here) */\r
- Term_erase(14, 14, 255);\r
- Term_erase(14, 13, 255);\r
- Term_erase(14, 12, 255);\r
- Term_erase(14, 11, 255);\r
-\r
- roff_to_buf(do_spell(use_realm, spell, SPELL_DESC), 62, temp, sizeof(temp));\r
-\r
- for (j = 0, line = 11; temp[j]; j += 1 + strlen(&temp[j]))\r
- {\r
- prt(&temp[j], line, 15);\r
- line++;\r
- }\r
- }\r
- screen_load();\r
-}\r
-\r
-/*!\r
- * @brief プレイヤーの第二魔法領域を変更する /\r
- * @param next_realm 変更先の魔法領域ID\r
- * @return なし\r
- */\r
-static void change_realm2(CHARACTER_IDX next_realm)\r
-{\r
- int i, j = 0;\r
- char tmp[80];\r
-\r
- for (i = 0; i < 64; i++)\r
- {\r
- p_ptr->spell_order[j] = p_ptr->spell_order[i];\r
- if (p_ptr->spell_order[i] < 32) j++;\r
- }\r
- for (; j < 64; j++)\r
- p_ptr->spell_order[j] = 99;\r
-\r
- for (i = 32; i < 64; i++)\r
- {\r
- p_ptr->spell_exp[i] = SPELL_EXP_UNSKILLED;\r
- }\r
- p_ptr->spell_learned2 = 0L;\r
- p_ptr->spell_worked2 = 0L;\r
- p_ptr->spell_forgotten2 = 0L;\r
-\r
- sprintf(tmp, _("魔法の領域を%sから%sに変更した。", "change magic realm from %s to %s."), realm_names[p_ptr->realm2], realm_names[next_realm]);\r
- do_cmd_write_nikki(NIKKI_BUNSHOU, 0, tmp);\r
- p_ptr->old_realm |= 1 << (p_ptr->realm2 - 1);\r
- p_ptr->realm2 = next_realm;\r
-\r
- p_ptr->update |= (PU_REORDER);\r
- p_ptr->update |= (PU_SPELLS);\r
- handle_stuff();\r
-\r
- /* Load an autopick preference file */\r
- autopick_load_pref(FALSE);\r
-}\r
-\r
-\r
-/*!\r
- * @brief 魔法を学習するコマンドのメインルーチン /\r
- * Study a book to gain a new spell/prayer\r
- * @return なし\r
- */\r
-void do_cmd_study(void)\r
-{\r
- int i;\r
- OBJECT_IDX item;\r
- OBJECT_SUBTYPE_VALUE sval;\r
- int increment = 0;\r
- bool learned = FALSE;\r
-\r
- /* Spells of realm2 will have an increment of +32 */\r
- SPELL_IDX spell = -1;\r
-\r
- concptr p = spell_category_name(mp_ptr->spell_book);\r
-\r
- object_type *o_ptr;\r
-\r
- concptr q, s;\r
-\r
- if (!p_ptr->realm1)\r
- {\r
- msg_print(_("本を読むことができない!", "You cannot read books!"));\r
- return;\r
- }\r
-\r
- if (p_ptr->blind || no_lite())\r
- {\r
- msg_print(_("目が見えない!", "You cannot see!"));\r
- return;\r
- }\r
-\r
- if (cmd_limit_confused(p_ptr)) return;\r
-\r
- if (!(p_ptr->new_spells))\r
- {\r
- msg_format(_("新しい%sを覚えることはできない!", "You cannot learn any new %ss!"), p);\r
- return;\r
- }\r
-\r
- if (p_ptr->special_defense & KATA_MUSOU)\r
- {\r
- set_action(ACTION_NONE);\r
- }\r
-\r
-#ifdef JP\r
- if (p_ptr->new_spells < 10) {\r
- msg_format("あと %d つの%sを学べる。", p_ptr->new_spells, p);\r
- }\r
- else {\r
- msg_format("あと %d 個の%sを学べる。", p_ptr->new_spells, p);\r
- }\r
-#else\r
- msg_format("You can learn %d new %s%s.", p_ptr->new_spells, p,\r
- (p_ptr->new_spells == 1 ? "" : "s"));\r
-#endif\r
-\r
- msg_print(NULL);\r
-\r
-\r
- /* Restrict choices to "useful" books */\r
- if (p_ptr->realm2 == REALM_NONE) item_tester_tval = mp_ptr->spell_book;\r
- else item_tester_hook = item_tester_learn_spell;\r
-\r
- q = _("どの本から学びますか? ", "Study which book? ");\r
- s = _("読める本がない。", "You have no books that you can read.");\r
-\r
- o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR));\r
- if (!o_ptr) return;\r
-\r
- /* Access the item's sval */\r
- sval = o_ptr->sval;\r
-\r
- if (o_ptr->tval == REALM2_BOOK) increment = 32;\r
- else if (o_ptr->tval != REALM1_BOOK)\r
- {\r
- if (!get_check(_("本当に魔法の領域を変更しますか?", "Really, change magic realm? "))) return;\r
- change_realm2(tval2realm(o_ptr->tval));\r
- increment = 32;\r
- }\r
-\r
- /* Track the object kind */\r
- object_kind_track(o_ptr->k_idx);\r
- handle_stuff();\r
-\r
- /* Mage -- Learn a selected spell */\r
- if (mp_ptr->spell_book != TV_LIFE_BOOK)\r
- {\r
- /* Ask for a spell, allow cancel */\r
- if (!get_spell(&spell, _("学ぶ", "study"), sval, FALSE, o_ptr->tval - TV_LIFE_BOOK + 1) && (spell == -1)) return;\r
- }\r
-\r
- /* Priest -- Learn a random prayer */\r
- else\r
- {\r
- int k = 0;\r
- int gift = -1;\r
-\r
- /* Extract spells */\r
- for (spell = 0; spell < 32; spell++)\r
- {\r
- /* Check spells in the book */\r
- if ((fake_spell_flags[sval] & (1L << spell)))\r
- {\r
- /* Skip non "okay" prayers */\r
- if (!spell_okay(spell, FALSE, TRUE,\r
- (increment ? p_ptr->realm2 : p_ptr->realm1))) continue;\r
-\r
- /* Hack -- Prepare the randomizer */\r
- k++;\r
-\r
- /* Hack -- Apply the randomizer */\r
- if (one_in_(k)) gift = spell;\r
- }\r
- }\r
-\r
- /* Accept gift */\r
- spell = gift;\r
- }\r
-\r
- /* Nothing to study */\r
- if (spell < 0)\r
- {\r
- msg_format(_("その本には学ぶべき%sがない。", "You cannot learn any %ss in that book."), p);\r
-\r
- /* Abort */\r
- return;\r
- }\r
-\r
- if (increment) spell += increment;\r
-\r
- /* Learn the spell */\r
- if (spell < 32)\r
- {\r
- if (p_ptr->spell_learned1 & (1L << spell)) learned = TRUE;\r
- else p_ptr->spell_learned1 |= (1L << spell);\r
- }\r
- else\r
- {\r
- if (p_ptr->spell_learned2 & (1L << (spell - 32))) learned = TRUE;\r
- else p_ptr->spell_learned2 |= (1L << (spell - 32));\r
- }\r
-\r
- if (learned)\r
- {\r
- int max_exp = (spell < 32) ? SPELL_EXP_MASTER : SPELL_EXP_EXPERT;\r
- int old_exp = p_ptr->spell_exp[spell];\r
- int new_rank = EXP_LEVEL_UNSKILLED;\r
- concptr name = do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME);\r
-\r
- if (old_exp >= max_exp)\r
- {\r
- msg_format(_("その%sは完全に使いこなせるので学ぶ必要はない。", "You don't need to study this %s anymore."), p);\r
- return;\r
- }\r
-#ifdef JP\r
- if (!get_check(format("%sの%sをさらに学びます。よろしいですか?", name, p)))\r
-#else\r
- if (!get_check(format("You will study a %s of %s again. Are you sure? ", p, name)))\r
-#endif\r
- {\r
- return;\r
- }\r
- else if (old_exp >= SPELL_EXP_EXPERT)\r
- {\r
- p_ptr->spell_exp[spell] = SPELL_EXP_MASTER;\r
- new_rank = EXP_LEVEL_MASTER;\r
- }\r
- else if (old_exp >= SPELL_EXP_SKILLED)\r
- {\r
- if (spell >= 32) p_ptr->spell_exp[spell] = SPELL_EXP_EXPERT;\r
- else p_ptr->spell_exp[spell] += SPELL_EXP_EXPERT - SPELL_EXP_SKILLED;\r
- new_rank = EXP_LEVEL_EXPERT;\r
- }\r
- else if (old_exp >= SPELL_EXP_BEGINNER)\r
- {\r
- p_ptr->spell_exp[spell] = SPELL_EXP_SKILLED + (old_exp - SPELL_EXP_BEGINNER) * 2 / 3;\r
- new_rank = EXP_LEVEL_SKILLED;\r
- }\r
- else\r
- {\r
- p_ptr->spell_exp[spell] = SPELL_EXP_BEGINNER + old_exp / 3;\r
- new_rank = EXP_LEVEL_BEGINNER;\r
- }\r
- msg_format(_("%sの熟練度が%sに上がった。", "Your proficiency of %s is now %s rank."), name, exp_level_str[new_rank]);\r
- }\r
- else\r
- {\r
- /* Find the next open entry in "p_ptr->spell_order[]" */\r
- for (i = 0; i < 64; i++)\r
- {\r
- /* Stop at the first empty space */\r
- if (p_ptr->spell_order[i] == 99) break;\r
- }\r
-\r
- /* Add the spell to the known list */\r
- p_ptr->spell_order[i++] = spell;\r
-\r
- /* Mention the result */\r
-#ifdef JP\r
- /* 英日切り替え機能に対応 */\r
- if (mp_ptr->spell_book == TV_MUSIC_BOOK)\r
- {\r
- msg_format("%sを学んだ。",\r
- do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME));\r
- }\r
- else\r
- {\r
- msg_format("%sの%sを学んだ。",\r
- do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME), p);\r
- }\r
-#else\r
- msg_format("You have learned the %s of %s.",\r
- p, do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME));\r
-#endif\r
- }\r
-\r
- take_turn(p_ptr, 100);;\r
-\r
- switch (mp_ptr->spell_book)\r
- {\r
- case TV_LIFE_BOOK:\r
- chg_virtue(V_FAITH, 1);\r
- break;\r
- case TV_DEATH_BOOK:\r
- chg_virtue(V_UNLIFE, 1);\r
- break;\r
- case TV_NATURE_BOOK:\r
- chg_virtue(V_NATURE, 1);\r
- break;\r
- default:\r
- chg_virtue(V_KNOWLEDGE, 1);\r
- break;\r
- }\r
-\r
- sound(SOUND_STUDY);\r
-\r
- /* One less spell available */\r
- p_ptr->learned_spells++;\r
-\r
- /* Update Study */\r
- p_ptr->update |= (PU_SPELLS);\r
- update_creature(p_ptr);\r
-\r
- /* Redraw object recall */\r
- p_ptr->window |= (PW_OBJECT);\r
-}\r
-\r
-\r
-/*!\r
- * @brief 魔法を詠唱するコマンドのメインルーチン /\r
- * Cast a spell\r
- * @return なし\r
- */\r
-void do_cmd_cast(void)\r
-{\r
- OBJECT_IDX item;\r
- OBJECT_SUBTYPE_VALUE sval;\r
- SPELL_IDX spell;\r
- REALM_IDX realm;\r
- int chance;\r
- int increment = 0;\r
- REALM_IDX use_realm;\r
- MANA_POINT need_mana;\r
-\r
- concptr prayer;\r
- object_type *o_ptr;\r
- const magic_type *s_ptr;\r
- concptr q, s;\r
-\r
- bool over_exerted = FALSE;\r
-\r
- /* Require spell ability */\r
- if (!p_ptr->realm1 && (p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE))\r
- {\r
- msg_print(_("呪文を唱えられない!", "You cannot cast spells!"));\r
- return;\r
- }\r
-\r
- /* Require lite */\r
- if (p_ptr->blind || no_lite())\r
- {\r
- if (p_ptr->pclass == CLASS_FORCETRAINER) confirm_use_force(FALSE);\r
- else\r
- {\r
- msg_print(_("目が見えない!", "You cannot see!"));\r
- flush();\r
- }\r
- return;\r
- }\r
-\r
- if (cmd_limit_confused(p_ptr)) return;\r
-\r
- /* Hex */\r
- if (p_ptr->realm1 == REALM_HEX)\r
- {\r
- if (hex_spell_fully())\r
- {\r
- bool flag = FALSE;\r
- msg_print(_("これ以上新しい呪文を詠唱することはできない。", "Can not spell new spells more."));\r
- flush();\r
- if (p_ptr->lev >= 35) flag = stop_hex_spell();\r
- if (!flag) return;\r
- }\r
- }\r
-\r
- if (p_ptr->pclass == CLASS_FORCETRAINER)\r
- {\r
- if (player_has_no_spellbooks())\r
- {\r
- confirm_use_force(FALSE);\r
- return;\r
- }\r
- }\r
-\r
- prayer = spell_category_name(mp_ptr->spell_book);\r
-\r
- /* Restrict choices to spell books */\r
- item_tester_tval = mp_ptr->spell_book;\r
-\r
- q = _("どの呪文書を使いますか? ", "Use which book? ");\r
- s = _("呪文書がない!", "You have no spell books!");\r
-\r
- o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR | (p_ptr->pclass == CLASS_FORCETRAINER ? USE_FORCE : 0)));\r
- if (!o_ptr)\r
- {\r
- if (item == INVEN_FORCE) /* the_force */\r
- {\r
- do_cmd_mind();\r
- return;\r
- }\r
- return;\r
- }\r
-\r
- /* Access the item's sval */\r
- sval = o_ptr->sval;\r
-\r
- if ((p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE) && (o_ptr->tval == REALM2_BOOK)) increment = 32;\r
-\r
- /* Track the object kind */\r
- object_kind_track(o_ptr->k_idx);\r
- handle_stuff();\r
-\r
- if ((p_ptr->pclass == CLASS_SORCERER) || (p_ptr->pclass == CLASS_RED_MAGE))\r
- realm = o_ptr->tval - TV_LIFE_BOOK + 1;\r
- else if (increment) realm = p_ptr->realm2;\r
- else realm = p_ptr->realm1;\r
-\r
- /* Ask for a spell */\r
-#ifdef JP\r
- if (!get_spell(&spell, ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "詠唱する" : (mp_ptr->spell_book == TV_MUSIC_BOOK) ? "歌う" : "唱える"),\r
- sval, TRUE, realm))\r
- {\r
- if (spell == -2) msg_format("その本には知っている%sがない。", prayer);\r
- return;\r
- }\r
-#else\r
- if (!get_spell(&spell, ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "recite" : "cast"),\r
- sval, TRUE, realm))\r
- {\r
- if (spell == -2)\r
- msg_format("You don't know any %ss in that book.", prayer);\r
- return;\r
- }\r
-#endif\r
-\r
-\r
- use_realm = tval2realm(o_ptr->tval);\r
-\r
- /* Hex */\r
- if (use_realm == REALM_HEX)\r
- {\r
- if (hex_spelling(spell))\r
- {\r
- msg_print(_("その呪文はすでに詠唱中だ。", "You are already casting it."));\r
- return;\r
- }\r
- }\r
-\r
- if (!is_magic(use_realm))\r
- {\r
- s_ptr = &technic_info[use_realm - MIN_TECHNIC][spell];\r
- }\r
- else\r
- {\r
- s_ptr = &mp_ptr->info[realm - 1][spell];\r
- }\r
-\r
- /* Extract mana consumption rate */\r
- need_mana = mod_need_mana(s_ptr->smana, spell, realm);\r
-\r
- /* Verify "dangerous" spells */\r
- if (need_mana > p_ptr->csp)\r
- {\r
- if (flush_failure) flush();\r
-\r
- /* Warning */\r
-#ifdef JP\r
- msg_format("その%sを%sのに十分なマジックポイントがない。", prayer,\r
- ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "詠唱する" : (mp_ptr->spell_book == TV_LIFE_BOOK) ? "歌う" : "唱える"));\r
-#else\r
- msg_format("You do not have enough mana to %s this %s.",\r
- ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "recite" : "cast"),\r
- prayer);\r
-#endif\r
-\r
-\r
- if (!over_exert) return;\r
-\r
- /* Verify */\r
- if (!get_check_strict(_("それでも挑戦しますか? ", "Attempt it anyway? "), CHECK_OKAY_CANCEL)) return;\r
- }\r
-\r
- /* Spell failure chance */\r
- chance = spell_chance(spell, use_realm);\r
-\r
- /* Sufficient mana */\r
- if (need_mana <= p_ptr->csp)\r
- {\r
- /* Use some mana */\r
- p_ptr->csp -= need_mana;\r
- }\r
- else over_exerted = TRUE;\r
- p_ptr->redraw |= (PR_MANA);\r
-\r
- /* Failed spell */\r
- if (randint0(100) < chance)\r
- {\r
- if (flush_failure) flush();\r
-\r
- msg_format(_("%sをうまく唱えられなかった!", "You failed to get the %s off!"), prayer);\r
- sound(SOUND_FAIL);\r
-\r
- switch (realm)\r
- {\r
- case REALM_LIFE:\r
- if (randint1(100) < chance) chg_virtue(V_VITALITY, -1);\r
- break;\r
- case REALM_DEATH:\r
- if (randint1(100) < chance) chg_virtue(V_UNLIFE, -1);\r
- break;\r
- case REALM_NATURE:\r
- if (randint1(100) < chance) chg_virtue(V_NATURE, -1);\r
- break;\r
- case REALM_DAEMON:\r
- if (randint1(100) < chance) chg_virtue(V_JUSTICE, 1);\r
- break;\r
- case REALM_CRUSADE:\r
- if (randint1(100) < chance) chg_virtue(V_JUSTICE, -1);\r
- break;\r
- case REALM_HEX:\r
- if (randint1(100) < chance) chg_virtue(V_COMPASSION, -1);\r
- break;\r
- default:\r
- if (randint1(100) < chance) chg_virtue(V_KNOWLEDGE, -1);\r
- break;\r
- }\r
-\r
- /* Failure casting may activate some side effect */\r
- do_spell(realm, spell, SPELL_FAIL);\r
-\r
-\r
- if ((o_ptr->tval == TV_CHAOS_BOOK) && (randint1(100) < spell))\r
- {\r
- msg_print(_("カオス的な効果を発生した!", "You produce a chaotic effect!"));\r
- wild_magic(spell);\r
- }\r
- else if ((o_ptr->tval == TV_DEATH_BOOK) && (randint1(100) < spell))\r
- {\r
- if ((sval == 3) && one_in_(2))\r
- {\r
- sanity_blast(0, TRUE);\r
- }\r
- else\r
- {\r
- msg_print(_("痛い!", "It hurts!"));\r
- take_hit(DAMAGE_LOSELIFE, damroll(o_ptr->sval + 1, 6), _("暗黒魔法の逆流", "a miscast Death spell"), -1);\r
-\r
- if ((spell > 15) && one_in_(6) && !p_ptr->hold_exp)\r
- lose_exp(spell * 250);\r
- }\r
- }\r
- else if ((o_ptr->tval == TV_MUSIC_BOOK) && (randint1(200) < spell))\r
- {\r
- msg_print(_("いやな音が響いた", "An infernal sound echoed."));\r
- aggravate_monsters(0);\r
- }\r
- if (randint1(100) >= chance)\r
- chg_virtue(V_CHANCE, -1);\r
- }\r
-\r
- /* Process spell */\r
- else\r
- {\r
- /* Canceled spells cost neither a turn nor mana */\r
- if (!do_spell(realm, spell, SPELL_CAST)) return;\r
-\r
- if (randint1(100) < chance)\r
- chg_virtue(V_CHANCE, 1);\r
-\r
- /* A spell was cast */\r
- if (!(increment ?\r
- (p_ptr->spell_worked2 & (1L << spell)) :\r
- (p_ptr->spell_worked1 & (1L << spell)))\r
- && (p_ptr->pclass != CLASS_SORCERER)\r
- && (p_ptr->pclass != CLASS_RED_MAGE))\r
- {\r
- int e = s_ptr->sexp;\r
-\r
- /* The spell worked */\r
- if (realm == p_ptr->realm1)\r
- {\r
- p_ptr->spell_worked1 |= (1L << spell);\r
- }\r
- else\r
- {\r
- p_ptr->spell_worked2 |= (1L << spell);\r
- }\r
-\r
- /* Gain experience */\r
- gain_exp(e * s_ptr->slevel);\r
-\r
- /* Redraw object recall */\r
- p_ptr->window |= (PW_OBJECT);\r
-\r
- switch (realm)\r
- {\r
- case REALM_LIFE:\r
- chg_virtue(V_TEMPERANCE, 1);\r
- chg_virtue(V_COMPASSION, 1);\r
- chg_virtue(V_VITALITY, 1);\r
- chg_virtue(V_DILIGENCE, 1);\r
- break;\r
- case REALM_DEATH:\r
- chg_virtue(V_UNLIFE, 1);\r
- chg_virtue(V_JUSTICE, -1);\r
- chg_virtue(V_FAITH, -1);\r
- chg_virtue(V_VITALITY, -1);\r
- break;\r
- case REALM_DAEMON:\r
- chg_virtue(V_JUSTICE, -1);\r
- chg_virtue(V_FAITH, -1);\r
- chg_virtue(V_HONOUR, -1);\r
- chg_virtue(V_TEMPERANCE, -1);\r
- break;\r
- case REALM_CRUSADE:\r
- chg_virtue(V_FAITH, 1);\r
- chg_virtue(V_JUSTICE, 1);\r
- chg_virtue(V_SACRIFICE, 1);\r
- chg_virtue(V_HONOUR, 1);\r
- break;\r
- case REALM_NATURE:\r
- chg_virtue(V_NATURE, 1);\r
- chg_virtue(V_HARMONY, 1);\r
- break;\r
- case REALM_HEX:\r
- chg_virtue(V_JUSTICE, -1);\r
- chg_virtue(V_FAITH, -1);\r
- chg_virtue(V_HONOUR, -1);\r
- chg_virtue(V_COMPASSION, -1);\r
- break;\r
- default:\r
- chg_virtue(V_KNOWLEDGE, 1);\r
- break;\r
- }\r
- }\r
- switch (realm)\r
- {\r
- case REALM_LIFE:\r
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_TEMPERANCE, 1);\r
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_COMPASSION, 1);\r
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_VITALITY, 1);\r
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_DILIGENCE, 1);\r
- break;\r
- case REALM_DEATH:\r
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_UNLIFE, 1);\r
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, -1);\r
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, -1);\r
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_VITALITY, -1);\r
- break;\r
- case REALM_DAEMON:\r
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, -1);\r
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, -1);\r
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HONOUR, -1);\r
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_TEMPERANCE, -1);\r
- break;\r
- case REALM_CRUSADE:\r
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, 1);\r
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, 1);\r
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_SACRIFICE, 1);\r
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HONOUR, 1);\r
- break;\r
- case REALM_NATURE:\r
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_NATURE, 1);\r
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HARMONY, 1);\r
- break;\r
- case REALM_HEX:\r
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, -1);\r
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, -1);\r
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HONOUR, -1);\r
- if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_COMPASSION, -1);\r
- break;\r
- }\r
- if (mp_ptr->spell_xtra & MAGIC_GAIN_EXP)\r
- {\r
- s16b cur_exp = p_ptr->spell_exp[(increment ? 32 : 0) + spell];\r
- s16b exp_gain = 0;\r
-\r
- if (cur_exp < SPELL_EXP_BEGINNER)\r
- exp_gain += 60;\r
- else if (cur_exp < SPELL_EXP_SKILLED)\r
- {\r
- if ((dun_level > 4) && ((dun_level + 10) > p_ptr->lev))\r
- exp_gain = 8;\r
- }\r
- else if (cur_exp < SPELL_EXP_EXPERT)\r
- {\r
- if (((dun_level + 5) > p_ptr->lev) && ((dun_level + 5) > s_ptr->slevel))\r
- exp_gain = 2;\r
- }\r
- else if ((cur_exp < SPELL_EXP_MASTER) && !increment)\r
- {\r
- if (((dun_level + 5) > p_ptr->lev) && (dun_level > s_ptr->slevel))\r
- exp_gain = 1;\r
- }\r
- p_ptr->spell_exp[(increment ? 32 : 0) + spell] += exp_gain;\r
- }\r
- }\r
-\r
- take_turn(p_ptr, 100);;\r
-\r
-\r
- /* Over-exert the player */\r
- if (over_exerted)\r
- {\r
- int oops = need_mana;\r
-\r
- /* No mana left */\r
- p_ptr->csp = 0;\r
- p_ptr->csp_frac = 0;\r
-\r
- msg_print(_("精神を集中しすぎて気を失ってしまった!", "You faint from the effort!"));\r
-\r
- /* Hack -- Bypass free action */\r
- (void)set_paralyzed(p_ptr->paralyzed + randint1(5 * oops + 1));\r
-\r
- switch (realm)\r
- {\r
- case REALM_LIFE:\r
- chg_virtue(V_VITALITY, -10);\r
- break;\r
- case REALM_DEATH:\r
- chg_virtue(V_UNLIFE, -10);\r
- break;\r
- case REALM_DAEMON:\r
- chg_virtue(V_JUSTICE, 10);\r
- break;\r
- case REALM_NATURE:\r
- chg_virtue(V_NATURE, -10);\r
- break;\r
- case REALM_CRUSADE:\r
- chg_virtue(V_JUSTICE, -10);\r
- break;\r
- case REALM_HEX:\r
- chg_virtue(V_COMPASSION, 10);\r
- break;\r
- default:\r
- chg_virtue(V_KNOWLEDGE, -10);\r
- break;\r
- }\r
-\r
- /* Damage CON (possibly permanently) */\r
- if (randint0(100) < 50)\r
- {\r
- bool perm = (randint0(100) < 25);\r
-\r
- msg_print(_("体を悪くしてしまった!", "You have damaged your health!"));\r
-\r
- /* Reduce constitution */\r
- (void)dec_stat(A_CON, 15 + randint1(10), perm);\r
- }\r
- }\r
-\r
- p_ptr->window |= (PW_PLAYER);\r
- p_ptr->window |= (PW_SPELL);\r
-}\r
+/*!
+ @file cmd-spell.c
+ @brief 魔法のインターフェイスと発動 / Purpose: Do everything for each spell
+ @date 2013/12/31
+ @author
+ 2013 Deskull rearranged comment for Doxygen.
+ */
+
+#include "angband.h"
+#include "selfinfo.h"
+#include "spells-summon.h"
+#include "realm-arcane.h"
+#include "realm-chaos.h"
+#include "realm-craft.h"
+#include "realm-crusade.h"
+#include "realm-daemon.h"
+#include "realm-death.h"
+#include "realm-hex.h"
+#include "realm-hissatsu.h"
+#include "realm-life.h"
+#include "realm-nature.h"
+#include "realm-song.h"
+#include "realm-sorcery.h"
+#include "realm-trump.h"
+#include "angband.h"
+#include "avatar.h"
+#include "player-status.h"
+#include "object-hook.h"
+
+/*!
+ * @brief
+ * 魔法の効果を「キャプション:ダイス+定数値」のフォーマットで出力する / Generate dice info string such as "foo 2d10"
+ * @param str キャプション
+ * @param dice ダイス数
+ * @param sides ダイス目
+ * @param base 固定値
+ * @return フォーマットに従い整形された文字列
+ */
+concptr info_string_dice(concptr str, DICE_NUMBER dice, DICE_SID sides, int base)
+{
+ /* Fix value */
+ if (!dice)
+ return format("%s%d", str, base);
+
+ /* Dice only */
+ else if (!base)
+ return format("%s%dd%d", str, dice, sides);
+
+ /* Dice plus base value */
+ else
+ return format("%s%dd%d%+d", str, dice, sides, base);
+}
+
+
+/*!
+ * @brief 魔法によるダメージを出力する / Generate damage-dice info string such as "dam 2d10"
+ * @param dice ダイス数
+ * @param sides ダイス目
+ * @param base 固定値
+ * @return フォーマットに従い整形された文字列
+ */
+concptr info_damage(DICE_NUMBER dice, DICE_SID sides, int base)
+{
+ return info_string_dice(_("損傷:", "dam "), dice, sides, base);
+}
+
+/*!
+ * @brief 魔法の効果時間を出力する / Generate duration info string such as "dur 20+1d20"
+ * @param base 固定値
+ * @param sides ダイス目
+ * @return フォーマットに従い整形された文字列
+ */
+concptr info_duration(int base, DICE_SID sides)
+{
+ return format(_("期間:%d+1d%d", "dur %d+1d%d"), base, sides);
+}
+
+/*!
+ * @brief 魔法の効果範囲を出力する / Generate range info string such as "range 5"
+ * @param range 効果範囲
+ * @return フォーマットに従い整形された文字列
+ */
+concptr info_range(POSITION range)
+{
+ return format(_("範囲:%d", "range %d"), range);
+}
+
+/*!
+ * @brief 魔法による回復量を出力する / Generate heal info string such as "heal 2d8"
+ * @param dice ダイス数
+ * @param sides ダイス目
+ * @param base 固定値
+ * @return フォーマットに従い整形された文字列
+ */
+concptr info_heal(DICE_NUMBER dice, DICE_SID sides, int base)
+{
+ return info_string_dice(_("回復:", "heal "), dice, sides, base);
+}
+
+/*!
+ * @brief 魔法効果発動までの遅延ターンを出力する / Generate delay info string such as "delay 15+1d15"
+ * @param base 固定値
+ * @param sides ダイス目
+ * @return フォーマットに従い整形された文字列
+ */
+concptr info_delay(int base, DICE_SID sides)
+{
+ return format(_("遅延:%d+1d%d", "delay %d+1d%d"), base, sides);
+}
+
+
+/*!
+ * @brief 魔法によるダメージを出力する(固定値&複数回処理) / Generate multiple-damage info string such as "dam 25 each"
+ * @param dam 固定値
+ * @return フォーマットに従い整形された文字列
+ */
+concptr info_multi_damage(HIT_POINT dam)
+{
+ return format(_("損傷:各%d", "dam %d each"), dam);
+}
+
+
+/*!
+ * @brief 魔法によるダメージを出力する(ダイスのみ&複数回処理) / Generate multiple-damage-dice info string such as "dam 5d2 each"
+ * @param dice ダイス数
+ * @param sides ダイス目
+ * @return フォーマットに従い整形された文字列
+ */
+concptr info_multi_damage_dice(DICE_NUMBER dice, DICE_SID sides)
+{
+ return format(_("損傷:各%dd%d", "dam %dd%d each"), dice, sides);
+}
+
+/*!
+ * @brief 魔法による一般的な効力値を出力する(固定値) / Generate power info string such as "power 100"
+ * @param power 固定値
+ * @return フォーマットに従い整形された文字列
+ */
+concptr info_power(int power)
+{
+ return format(_("効力:%d", "power %d"), power);
+}
+
+
+/*!
+ * @brief 魔法による一般的な効力値を出力する(ダイス値) / Generate power info string such as "power 100"
+ * @param dice ダイス数
+ * @param sides ダイス目
+ * @return フォーマットに従い整形された文字列
+ */
+/*
+ * Generate power info string such as "power 1d100"
+ */
+concptr info_power_dice(DICE_NUMBER dice, DICE_SID sides)
+{
+ return format(_("効力:%dd%d", "power %dd%d"), dice, sides);
+}
+
+
+/*!
+ * @brief 魔法の効果半径を出力する / Generate radius info string such as "rad 100"
+ * @param rad 効果半径
+ * @return フォーマットに従い整形された文字列
+ */
+concptr info_radius(POSITION rad)
+{
+ return format(_("半径:%d", "rad %d"), rad);
+}
+
+
+/*!
+ * @brief 魔法効果の限界重量を出力する / Generate weight info string such as "max wgt 15"
+ * @param weight 最大重量
+ * @return フォーマットに従い整形された文字列
+ */
+concptr info_weight(WEIGHT weight)
+{
+#ifdef JP
+ return format("最大重量:%d.%dkg", lbtokg1(weight), lbtokg2(weight));
+#else
+ return format("max wgt %d", weight/10);
+#endif
+}
+
+/*!
+ * @brief 魔法処理のメインルーチン
+ * @param realm 魔法領域のID
+ * @param spell 各領域の魔法ID
+ * @param mode 求める処理
+ * @return 各領域魔法に各種テキストを求めた場合は文字列参照ポインタ、そうでない場合はNULLポインタを返す。
+ */
+concptr do_spell(REALM_IDX realm, SPELL_IDX spell, BIT_FLAGS mode)
+{
+ switch (realm)
+ {
+ case REALM_LIFE: return do_life_spell(spell, mode);
+ case REALM_SORCERY: return do_sorcery_spell(spell, mode);
+ case REALM_NATURE: return do_nature_spell(spell, mode);
+ case REALM_CHAOS: return do_chaos_spell(spell, mode);
+ case REALM_DEATH: return do_death_spell(spell, mode);
+ case REALM_TRUMP: return do_trump_spell(spell, mode);
+ case REALM_ARCANE: return do_arcane_spell(spell, mode);
+ case REALM_CRAFT: return do_craft_spell(spell, mode);
+ case REALM_DAEMON: return do_daemon_spell(spell, mode);
+ case REALM_CRUSADE: return do_crusade_spell(spell, mode);
+ case REALM_MUSIC: return do_music_spell(spell, mode);
+ case REALM_HISSATSU: return do_hissatsu_spell(spell, mode);
+ case REALM_HEX: return do_hex_spell(spell, mode);
+ }
+
+ return NULL;
+}
+
+
+/*!
+ * @brief 領域魔法の閲覧、学習、使用選択するインターフェイス処理
+ * Allow user to choose a spell/prayer from the given book.
+ * @param sn 選択した魔法IDを返す参照ポインタ
+ * @param prompt 魔法を利用する際の動詞表記
+ * @param sval 魔道書のsval
+ * @param learned 閲覧/使用選択ならばTRUE、学習処理ならFALSE
+ * @param use_realm 魔法領域ID
+ * @return
+ * <pre>
+ * If a valid spell is chosen, saves it in '*sn' and returns TRUE
+ * If the user hits escape, returns FALSE, and set '*sn' to -1
+ * If there are no legal choices, returns FALSE, and sets '*sn' to -2
+ * The "prompt" should be "cast", "recite", or "study"
+ * The "known" should be TRUE for cast/pray, FALSE for study
+ * </pre>
+ */
+static int get_spell(SPELL_IDX *sn, concptr prompt, OBJECT_SUBTYPE_VALUE sval, bool learned, REALM_IDX use_realm)
+{
+ int i;
+ SPELL_IDX spell = -1;
+ int num = 0;
+ int ask = TRUE;
+ MANA_POINT need_mana;
+ SPELL_IDX spells[64];
+ bool flag, redraw, okay;
+ char choice;
+ const magic_type *s_ptr;
+ char out_val[160];
+ concptr p;
+ COMMAND_CODE code;
+#ifdef JP
+ char jverb_buf[128];
+#endif
+ int menu_line = (use_menu ? 1 : 0);
+
+ /* Get the spell, if available */
+ if (repeat_pull(&code))
+ {
+ *sn = (SPELL_IDX)code;
+ /* Verify the spell */
+ if (spell_okay(*sn, learned, FALSE, use_realm))
+ {
+ /* Success */
+ return (TRUE);
+ }
+ }
+
+ p = spell_category_name(mp_ptr->spell_book);
+
+ /* Extract spells */
+ for (spell = 0; spell < 32; spell++)
+ {
+ /* Check for this spell */
+ if ((fake_spell_flags[sval] & (1L << spell)))
+ {
+ /* Collect this spell */
+ spells[num++] = spell;
+ }
+ }
+
+ /* Assume no usable spells */
+ okay = FALSE;
+
+ /* Assume no spells available */
+ (*sn) = -2;
+
+ /* Check for "okay" spells */
+ for (i = 0; i < num; i++)
+ {
+ /* Look for "okay" spells */
+ if (spell_okay(spells[i], learned, FALSE, use_realm)) okay = TRUE;
+ }
+
+ /* No "okay" spells */
+ if (!okay) return (FALSE);
+ if (((use_realm) != p_ptr->realm1) && ((use_realm) != p_ptr->realm2) && (p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE)) return FALSE;
+ if (((p_ptr->pclass == CLASS_SORCERER) || (p_ptr->pclass == CLASS_RED_MAGE)) && !is_magic(use_realm)) return FALSE;
+ if ((p_ptr->pclass == CLASS_RED_MAGE) && ((use_realm) != REALM_ARCANE) && (sval > 1)) return FALSE;
+
+ /* Assume cancelled */
+ *sn = (-1);
+
+ /* Nothing chosen yet */
+ flag = FALSE;
+
+ /* No redraw yet */
+ redraw = FALSE;
+
+ p_ptr->window |= (PW_SPELL);
+ handle_stuff();
+
+ /* Build a prompt (accept all spells) */
+#ifdef JP
+ jverb(prompt, jverb_buf, JVERB_AND);
+ (void)strnfmt(out_val, 78, "(%^s:%c-%c, '*'で一覧, ESCで中断) どの%sを%^sますか? ",
+ p, I2A(0), I2A(num - 1), p, jverb_buf);
+#else
+ (void)strnfmt(out_val, 78, "(%^ss %c-%c, *=List, ESC=exit) %^s which %s? ",
+ p, I2A(0), I2A(num - 1), prompt, p);
+#endif
+
+ /* Get a spell from the user */
+
+ choice = (always_show_list || use_menu) ? ESCAPE : 1;
+ while (!flag)
+ {
+ if (choice == ESCAPE) choice = ' ';
+ else if (!get_com(out_val, &choice, TRUE))break;
+
+ if (use_menu && choice != ' ')
+ {
+ switch (choice)
+ {
+ case '0':
+ {
+ screen_load();
+ return FALSE;
+ }
+
+ case '8':
+ case 'k':
+ case 'K':
+ {
+ menu_line += (num - 1);
+ break;
+ }
+
+ case '2':
+ case 'j':
+ case 'J':
+ {
+ menu_line++;
+ break;
+ }
+
+ case 'x':
+ case 'X':
+ case '\r':
+ case '\n':
+ {
+ i = menu_line - 1;
+ ask = FALSE;
+ break;
+ }
+ }
+ if (menu_line > num) menu_line -= num;
+ /* Display a list of spells */
+ print_spells(menu_line, spells, num, 1, 15, use_realm);
+ if (ask) continue;
+ }
+ else
+ {
+ /* Request redraw */
+ if ((choice == ' ') || (choice == '*') || (choice == '?'))
+ {
+ /* Show the list */
+ if (!redraw)
+ {
+ /* Show list */
+ redraw = TRUE;
+ screen_save();
+
+ /* Display a list of spells */
+ print_spells(menu_line, spells, num, 1, 15, use_realm);
+ }
+
+ /* Hide the list */
+ else
+ {
+ if (use_menu) continue;
+
+ /* Hide list */
+ redraw = FALSE;
+ screen_load();
+ }
+
+ /* Redo asking */
+ continue;
+ }
+
+
+ /* Note verify */
+ ask = (isupper(choice));
+
+ /* Lowercase */
+ if (ask) choice = (char)tolower(choice);
+
+ /* Extract request */
+ i = (islower(choice) ? A2I(choice) : -1);
+ }
+
+ /* Totally Illegal */
+ if ((i < 0) || (i >= num))
+ {
+ bell();
+ continue;
+ }
+
+ /* Save the spell index */
+ spell = spells[i];
+
+ /* Require "okay" spells */
+ if (!spell_okay(spell, learned, FALSE, use_realm))
+ {
+ bell();
+#ifdef JP
+ msg_format("その%sを%sことはできません。", p, prompt);
+#else
+ msg_format("You may not %s that %s.", prompt, p);
+#endif
+
+ continue;
+ }
+
+ /* Verify it */
+ if (ask)
+ {
+ char tmp_val[160];
+
+ /* Access the spell */
+ if (!is_magic(use_realm))
+ {
+ s_ptr = &technic_info[use_realm - MIN_TECHNIC][spell];
+ }
+ else
+ {
+ s_ptr = &mp_ptr->info[use_realm - 1][spell];
+ }
+
+ /* Extract mana consumption rate */
+ if (use_realm == REALM_HISSATSU)
+ {
+ need_mana = s_ptr->smana;
+ }
+ else
+ {
+ need_mana = mod_need_mana(s_ptr->smana, spell, use_realm);
+ }
+
+ /* Prompt */
+#ifdef JP
+ jverb(prompt, jverb_buf, JVERB_AND);
+ /* 英日切り替え機能に対応 */
+ (void)strnfmt(tmp_val, 78, "%s(MP%d, 失敗率%d%%)を%sますか? ",
+ do_spell(use_realm, spell, SPELL_NAME), need_mana,
+ spell_chance(spell, use_realm), jverb_buf);
+#else
+ (void)strnfmt(tmp_val, 78, "%^s %s (%d mana, %d%% fail)? ",
+ prompt, do_spell(use_realm, spell, SPELL_NAME), need_mana,
+ spell_chance(spell, use_realm));
+#endif
+
+
+ /* Belay that order */
+ if (!get_check(tmp_val)) continue;
+ }
+
+ /* Stop the loop */
+ flag = TRUE;
+ }
+
+ if (redraw) screen_load();
+
+ p_ptr->window |= (PW_SPELL);
+ handle_stuff();
+
+ /* Abort if needed */
+ if (!flag) return FALSE;
+
+ /* Save the choice */
+ (*sn) = spell;
+
+ repeat_push((COMMAND_CODE)spell);
+
+ /* Success */
+ return TRUE;
+}
+
+/*!
+ * @brief プレイヤーの職業が練気術師の時、領域魔法と練気術を切り換える処理のインターフェイス
+ * @param browse_only 魔法と技能の閲覧を行うならばTRUE
+ * @return 魔道書を一冊も持っていないならTRUEを返す
+ */
+static void confirm_use_force(bool browse_only)
+{
+ char which;
+ COMMAND_CODE code;
+
+ /* Get the item index */
+ if (repeat_pull(&code) && (code == INVEN_FORCE))
+ {
+ browse_only ? do_cmd_mind_browse() : do_cmd_mind();
+ return;
+ }
+
+ /* Show the prompt */
+ prt(_("('w'練気術, ESC) 'w'かESCを押してください。 ", "(w for the Force, ESC) Hit 'w' or ESC. "), 0, 0);
+
+ while (1)
+ {
+ /* Get a key */
+ which = inkey();
+
+ if (which == ESCAPE) break;
+ else if (which == 'w')
+ {
+ repeat_push(INVEN_FORCE);
+ break;
+ }
+ }
+
+ /* Clear the prompt line */
+ prt("", 0, 0);
+
+ if (which == 'w')
+ {
+ browse_only ? do_cmd_mind_browse() : do_cmd_mind();
+ }
+}
+
+
+/*!
+ * @brief プレイヤーの魔法と技能を閲覧するコマンドのメインルーチン /
+ * Peruse the spells/prayers in a book
+ * @return なし
+ * @details
+ * <pre>
+ * Note that *all* spells in the book are listed
+ *
+ * Note that browsing is allowed while confused or blind,
+ * and in the dark, primarily to allow browsing in stores.
+ * </pre>
+ */
+void do_cmd_browse(void)
+{
+ OBJECT_IDX item;
+ OBJECT_SUBTYPE_VALUE sval;
+ REALM_IDX use_realm = 0;
+ int j, line;
+ SPELL_IDX spell = -1;
+ int num = 0;
+
+ SPELL_IDX spells[64];
+ char temp[62 * 4];
+
+ object_type *o_ptr;
+
+ concptr q, s;
+
+ /* Warriors are illiterate */
+ if (!(p_ptr->realm1 || p_ptr->realm2) && (p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE))
+ {
+ msg_print(_("本を読むことができない!", "You cannot read books!"));
+ return;
+ }
+
+ if (p_ptr->special_defense & KATA_MUSOU)
+ {
+ set_action(ACTION_NONE);
+ }
+
+ if (p_ptr->pclass == CLASS_FORCETRAINER)
+ {
+ if (player_has_no_spellbooks())
+ {
+ confirm_use_force(TRUE);
+ return;
+ }
+ }
+
+ /* Restrict choices to "useful" books */
+ if (p_ptr->realm2 == REALM_NONE) item_tester_tval = mp_ptr->spell_book;
+ else item_tester_hook = item_tester_learn_spell;
+
+ q = _("どの本を読みますか? ", "Browse which book? ");
+ s = _("読める本がない。", "You have no books that you can read.");
+
+ o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR | (p_ptr->pclass == CLASS_FORCETRAINER ? USE_FORCE : 0)));
+ if (!o_ptr)
+ {
+ if (item == INVEN_FORCE) /* the_force */
+ {
+ do_cmd_mind_browse();
+ return;
+ }
+ return;
+ }
+
+ /* Access the item's sval */
+ sval = o_ptr->sval;
+
+ use_realm = tval2realm(o_ptr->tval);
+
+ /* Track the object kind */
+ object_kind_track(o_ptr->k_idx);
+ handle_stuff();
+
+ /* Extract spells */
+ for (spell = 0; spell < 32; spell++)
+ {
+ /* Check for this spell */
+ if ((fake_spell_flags[sval] & (1L << spell)))
+ {
+ /* Collect this spell */
+ spells[num++] = spell;
+ }
+ }
+
+ screen_save();
+ prt("", 0, 0);
+
+ /* Keep browsing spells. Exit browsing on cancel. */
+ while (TRUE)
+ {
+ /* Ask for a spell, allow cancel */
+ if (!get_spell(&spell, _("読む", "browse"), o_ptr->sval, TRUE, use_realm))
+ {
+ /* If cancelled, leave immediately. */
+ if (spell == -1) break;
+
+ /* Display a list of spells */
+ print_spells(0, spells, num, 1, 15, use_realm);
+
+ /* Notify that there's nothing to see, and wait. */
+ if (use_realm == REALM_HISSATSU)
+ prt(_("読める技がない。", "No techniques to browse."), 0, 0);
+ else
+ prt(_("読める呪文がない。", "No spells to browse."), 0, 0);
+ (void)inkey();
+
+ screen_load();
+
+ return;
+ }
+
+ /* Clear lines, position cursor (really should use strlen here) */
+ Term_erase(14, 14, 255);
+ Term_erase(14, 13, 255);
+ Term_erase(14, 12, 255);
+ Term_erase(14, 11, 255);
+
+ roff_to_buf(do_spell(use_realm, spell, SPELL_DESC), 62, temp, sizeof(temp));
+
+ for (j = 0, line = 11; temp[j]; j += 1 + strlen(&temp[j]))
+ {
+ prt(&temp[j], line, 15);
+ line++;
+ }
+ }
+ screen_load();
+}
+
+/*!
+ * @brief プレイヤーの第二魔法領域を変更する /
+ * @param next_realm 変更先の魔法領域ID
+ * @return なし
+ */
+static void change_realm2(CHARACTER_IDX next_realm)
+{
+ int i, j = 0;
+ char tmp[80];
+
+ for (i = 0; i < 64; i++)
+ {
+ p_ptr->spell_order[j] = p_ptr->spell_order[i];
+ if (p_ptr->spell_order[i] < 32) j++;
+ }
+ for (; j < 64; j++)
+ p_ptr->spell_order[j] = 99;
+
+ for (i = 32; i < 64; i++)
+ {
+ p_ptr->spell_exp[i] = SPELL_EXP_UNSKILLED;
+ }
+ p_ptr->spell_learned2 = 0L;
+ p_ptr->spell_worked2 = 0L;
+ p_ptr->spell_forgotten2 = 0L;
+
+ sprintf(tmp, _("魔法の領域を%sから%sに変更した。", "change magic realm from %s to %s."), realm_names[p_ptr->realm2], realm_names[next_realm]);
+ do_cmd_write_nikki(NIKKI_BUNSHOU, 0, tmp);
+ p_ptr->old_realm |= 1 << (p_ptr->realm2 - 1);
+ p_ptr->realm2 = next_realm;
+
+ p_ptr->update |= (PU_REORDER);
+ p_ptr->update |= (PU_SPELLS);
+ handle_stuff();
+
+ /* Load an autopick preference file */
+ autopick_load_pref(FALSE);
+}
+
+
+/*!
+ * @brief 魔法を学習するコマンドのメインルーチン /
+ * Study a book to gain a new spell/prayer
+ * @return なし
+ */
+void do_cmd_study(void)
+{
+ int i;
+ OBJECT_IDX item;
+ OBJECT_SUBTYPE_VALUE sval;
+ int increment = 0;
+ bool learned = FALSE;
+
+ /* Spells of realm2 will have an increment of +32 */
+ SPELL_IDX spell = -1;
+
+ concptr p = spell_category_name(mp_ptr->spell_book);
+
+ object_type *o_ptr;
+
+ concptr q, s;
+
+ if (!p_ptr->realm1)
+ {
+ msg_print(_("本を読むことができない!", "You cannot read books!"));
+ return;
+ }
+
+ if (p_ptr->blind || no_lite())
+ {
+ msg_print(_("目が見えない!", "You cannot see!"));
+ return;
+ }
+
+ if (cmd_limit_confused(p_ptr)) return;
+
+ if (!(p_ptr->new_spells))
+ {
+ msg_format(_("新しい%sを覚えることはできない!", "You cannot learn any new %ss!"), p);
+ return;
+ }
+
+ if (p_ptr->special_defense & KATA_MUSOU)
+ {
+ set_action(ACTION_NONE);
+ }
+
+#ifdef JP
+ if (p_ptr->new_spells < 10) {
+ msg_format("あと %d つの%sを学べる。", p_ptr->new_spells, p);
+ }
+ else {
+ msg_format("あと %d 個の%sを学べる。", p_ptr->new_spells, p);
+ }
+#else
+ msg_format("You can learn %d new %s%s.", p_ptr->new_spells, p,
+ (p_ptr->new_spells == 1 ? "" : "s"));
+#endif
+
+ msg_print(NULL);
+
+
+ /* Restrict choices to "useful" books */
+ if (p_ptr->realm2 == REALM_NONE) item_tester_tval = mp_ptr->spell_book;
+ else item_tester_hook = item_tester_learn_spell;
+
+ q = _("どの本から学びますか? ", "Study which book? ");
+ s = _("読める本がない。", "You have no books that you can read.");
+
+ o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR));
+ if (!o_ptr) return;
+
+ /* Access the item's sval */
+ sval = o_ptr->sval;
+
+ if (o_ptr->tval == REALM2_BOOK) increment = 32;
+ else if (o_ptr->tval != REALM1_BOOK)
+ {
+ if (!get_check(_("本当に魔法の領域を変更しますか?", "Really, change magic realm? "))) return;
+ change_realm2(tval2realm(o_ptr->tval));
+ increment = 32;
+ }
+
+ /* Track the object kind */
+ object_kind_track(o_ptr->k_idx);
+ handle_stuff();
+
+ /* Mage -- Learn a selected spell */
+ if (mp_ptr->spell_book != TV_LIFE_BOOK)
+ {
+ /* Ask for a spell, allow cancel */
+ if (!get_spell(&spell, _("学ぶ", "study"), sval, FALSE, o_ptr->tval - TV_LIFE_BOOK + 1) && (spell == -1)) return;
+ }
+
+ /* Priest -- Learn a random prayer */
+ else
+ {
+ int k = 0;
+ int gift = -1;
+
+ /* Extract spells */
+ for (spell = 0; spell < 32; spell++)
+ {
+ /* Check spells in the book */
+ if ((fake_spell_flags[sval] & (1L << spell)))
+ {
+ /* Skip non "okay" prayers */
+ if (!spell_okay(spell, FALSE, TRUE,
+ (increment ? p_ptr->realm2 : p_ptr->realm1))) continue;
+
+ /* Hack -- Prepare the randomizer */
+ k++;
+
+ /* Hack -- Apply the randomizer */
+ if (one_in_(k)) gift = spell;
+ }
+ }
+
+ /* Accept gift */
+ spell = gift;
+ }
+
+ /* Nothing to study */
+ if (spell < 0)
+ {
+ msg_format(_("その本には学ぶべき%sがない。", "You cannot learn any %ss in that book."), p);
+
+ /* Abort */
+ return;
+ }
+
+ if (increment) spell += increment;
+
+ /* Learn the spell */
+ if (spell < 32)
+ {
+ if (p_ptr->spell_learned1 & (1L << spell)) learned = TRUE;
+ else p_ptr->spell_learned1 |= (1L << spell);
+ }
+ else
+ {
+ if (p_ptr->spell_learned2 & (1L << (spell - 32))) learned = TRUE;
+ else p_ptr->spell_learned2 |= (1L << (spell - 32));
+ }
+
+ if (learned)
+ {
+ int max_exp = (spell < 32) ? SPELL_EXP_MASTER : SPELL_EXP_EXPERT;
+ int old_exp = p_ptr->spell_exp[spell];
+ int new_rank = EXP_LEVEL_UNSKILLED;
+ concptr name = do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME);
+
+ if (old_exp >= max_exp)
+ {
+ msg_format(_("その%sは完全に使いこなせるので学ぶ必要はない。", "You don't need to study this %s anymore."), p);
+ return;
+ }
+#ifdef JP
+ if (!get_check(format("%sの%sをさらに学びます。よろしいですか?", name, p)))
+#else
+ if (!get_check(format("You will study a %s of %s again. Are you sure? ", p, name)))
+#endif
+ {
+ return;
+ }
+ else if (old_exp >= SPELL_EXP_EXPERT)
+ {
+ p_ptr->spell_exp[spell] = SPELL_EXP_MASTER;
+ new_rank = EXP_LEVEL_MASTER;
+ }
+ else if (old_exp >= SPELL_EXP_SKILLED)
+ {
+ if (spell >= 32) p_ptr->spell_exp[spell] = SPELL_EXP_EXPERT;
+ else p_ptr->spell_exp[spell] += SPELL_EXP_EXPERT - SPELL_EXP_SKILLED;
+ new_rank = EXP_LEVEL_EXPERT;
+ }
+ else if (old_exp >= SPELL_EXP_BEGINNER)
+ {
+ p_ptr->spell_exp[spell] = SPELL_EXP_SKILLED + (old_exp - SPELL_EXP_BEGINNER) * 2 / 3;
+ new_rank = EXP_LEVEL_SKILLED;
+ }
+ else
+ {
+ p_ptr->spell_exp[spell] = SPELL_EXP_BEGINNER + old_exp / 3;
+ new_rank = EXP_LEVEL_BEGINNER;
+ }
+ msg_format(_("%sの熟練度が%sに上がった。", "Your proficiency of %s is now %s rank."), name, exp_level_str[new_rank]);
+ }
+ else
+ {
+ /* Find the next open entry in "p_ptr->spell_order[]" */
+ for (i = 0; i < 64; i++)
+ {
+ /* Stop at the first empty space */
+ if (p_ptr->spell_order[i] == 99) break;
+ }
+
+ /* Add the spell to the known list */
+ p_ptr->spell_order[i++] = spell;
+
+ /* Mention the result */
+#ifdef JP
+ /* 英日切り替え機能に対応 */
+ if (mp_ptr->spell_book == TV_MUSIC_BOOK)
+ {
+ msg_format("%sを学んだ。",
+ do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME));
+ }
+ else
+ {
+ msg_format("%sの%sを学んだ。",
+ do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME), p);
+ }
+#else
+ msg_format("You have learned the %s of %s.",
+ p, do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME));
+#endif
+ }
+
+ take_turn(p_ptr, 100);;
+
+ switch (mp_ptr->spell_book)
+ {
+ case TV_LIFE_BOOK:
+ chg_virtue(V_FAITH, 1);
+ break;
+ case TV_DEATH_BOOK:
+ chg_virtue(V_UNLIFE, 1);
+ break;
+ case TV_NATURE_BOOK:
+ chg_virtue(V_NATURE, 1);
+ break;
+ default:
+ chg_virtue(V_KNOWLEDGE, 1);
+ break;
+ }
+
+ sound(SOUND_STUDY);
+
+ /* One less spell available */
+ p_ptr->learned_spells++;
+
+ /* Update Study */
+ p_ptr->update |= (PU_SPELLS);
+ update_creature(p_ptr);
+
+ /* Redraw object recall */
+ p_ptr->window |= (PW_OBJECT);
+}
+
+
+/*!
+ * @brief 魔法を詠唱するコマンドのメインルーチン /
+ * Cast a spell
+ * @return なし
+ */
+void do_cmd_cast(void)
+{
+ OBJECT_IDX item;
+ OBJECT_SUBTYPE_VALUE sval;
+ SPELL_IDX spell;
+ REALM_IDX realm;
+ int chance;
+ int increment = 0;
+ REALM_IDX use_realm;
+ MANA_POINT need_mana;
+
+ concptr prayer;
+ object_type *o_ptr;
+ const magic_type *s_ptr;
+ concptr q, s;
+
+ bool over_exerted = FALSE;
+
+ /* Require spell ability */
+ if (!p_ptr->realm1 && (p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE))
+ {
+ msg_print(_("呪文を唱えられない!", "You cannot cast spells!"));
+ return;
+ }
+
+ /* Require lite */
+ if (p_ptr->blind || no_lite())
+ {
+ if (p_ptr->pclass == CLASS_FORCETRAINER) confirm_use_force(FALSE);
+ else
+ {
+ msg_print(_("目が見えない!", "You cannot see!"));
+ flush();
+ }
+ return;
+ }
+
+ if (cmd_limit_confused(p_ptr)) return;
+
+ /* Hex */
+ if (p_ptr->realm1 == REALM_HEX)
+ {
+ if (hex_spell_fully())
+ {
+ bool flag = FALSE;
+ msg_print(_("これ以上新しい呪文を詠唱することはできない。", "Can not spell new spells more."));
+ flush();
+ if (p_ptr->lev >= 35) flag = stop_hex_spell();
+ if (!flag) return;
+ }
+ }
+
+ if (p_ptr->pclass == CLASS_FORCETRAINER)
+ {
+ if (player_has_no_spellbooks())
+ {
+ confirm_use_force(FALSE);
+ return;
+ }
+ }
+
+ prayer = spell_category_name(mp_ptr->spell_book);
+
+ /* Restrict choices to spell books */
+ item_tester_tval = mp_ptr->spell_book;
+
+ q = _("どの呪文書を使いますか? ", "Use which book? ");
+ s = _("呪文書がない!", "You have no spell books!");
+
+ o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR | (p_ptr->pclass == CLASS_FORCETRAINER ? USE_FORCE : 0)));
+ if (!o_ptr)
+ {
+ if (item == INVEN_FORCE) /* the_force */
+ {
+ do_cmd_mind();
+ return;
+ }
+ return;
+ }
+
+ /* Access the item's sval */
+ sval = o_ptr->sval;
+
+ if ((p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE) && (o_ptr->tval == REALM2_BOOK)) increment = 32;
+
+ /* Track the object kind */
+ object_kind_track(o_ptr->k_idx);
+ handle_stuff();
+
+ if ((p_ptr->pclass == CLASS_SORCERER) || (p_ptr->pclass == CLASS_RED_MAGE))
+ realm = o_ptr->tval - TV_LIFE_BOOK + 1;
+ else if (increment) realm = p_ptr->realm2;
+ else realm = p_ptr->realm1;
+
+ /* Ask for a spell */
+#ifdef JP
+ if (!get_spell(&spell, ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "詠唱する" : (mp_ptr->spell_book == TV_MUSIC_BOOK) ? "歌う" : "唱える"),
+ sval, TRUE, realm))
+ {
+ if (spell == -2) msg_format("その本には知っている%sがない。", prayer);
+ return;
+ }
+#else
+ if (!get_spell(&spell, ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "recite" : "cast"),
+ sval, TRUE, realm))
+ {
+ if (spell == -2)
+ msg_format("You don't know any %ss in that book.", prayer);
+ return;
+ }
+#endif
+
+
+ use_realm = tval2realm(o_ptr->tval);
+
+ /* Hex */
+ if (use_realm == REALM_HEX)
+ {
+ if (hex_spelling(spell))
+ {
+ msg_print(_("その呪文はすでに詠唱中だ。", "You are already casting it."));
+ return;
+ }
+ }
+
+ if (!is_magic(use_realm))
+ {
+ s_ptr = &technic_info[use_realm - MIN_TECHNIC][spell];
+ }
+ else
+ {
+ s_ptr = &mp_ptr->info[realm - 1][spell];
+ }
+
+ /* Extract mana consumption rate */
+ need_mana = mod_need_mana(s_ptr->smana, spell, realm);
+
+ /* Verify "dangerous" spells */
+ if (need_mana > p_ptr->csp)
+ {
+ if (flush_failure) flush();
+
+ /* Warning */
+#ifdef JP
+ msg_format("その%sを%sのに十分なマジックポイントがない。", prayer,
+ ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "詠唱する" : (mp_ptr->spell_book == TV_LIFE_BOOK) ? "歌う" : "唱える"));
+#else
+ msg_format("You do not have enough mana to %s this %s.",
+ ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "recite" : "cast"),
+ prayer);
+#endif
+
+
+ if (!over_exert) return;
+
+ /* Verify */
+ if (!get_check_strict(_("それでも挑戦しますか? ", "Attempt it anyway? "), CHECK_OKAY_CANCEL)) return;
+ }
+
+ /* Spell failure chance */
+ chance = spell_chance(spell, use_realm);
+
+ /* Sufficient mana */
+ if (need_mana <= p_ptr->csp)
+ {
+ /* Use some mana */
+ p_ptr->csp -= need_mana;
+ }
+ else over_exerted = TRUE;
+ p_ptr->redraw |= (PR_MANA);
+
+ /* Failed spell */
+ if (randint0(100) < chance)
+ {
+ if (flush_failure) flush();
+
+ msg_format(_("%sをうまく唱えられなかった!", "You failed to get the %s off!"), prayer);
+ sound(SOUND_FAIL);
+
+ switch (realm)
+ {
+ case REALM_LIFE:
+ if (randint1(100) < chance) chg_virtue(V_VITALITY, -1);
+ break;
+ case REALM_DEATH:
+ if (randint1(100) < chance) chg_virtue(V_UNLIFE, -1);
+ break;
+ case REALM_NATURE:
+ if (randint1(100) < chance) chg_virtue(V_NATURE, -1);
+ break;
+ case REALM_DAEMON:
+ if (randint1(100) < chance) chg_virtue(V_JUSTICE, 1);
+ break;
+ case REALM_CRUSADE:
+ if (randint1(100) < chance) chg_virtue(V_JUSTICE, -1);
+ break;
+ case REALM_HEX:
+ if (randint1(100) < chance) chg_virtue(V_COMPASSION, -1);
+ break;
+ default:
+ if (randint1(100) < chance) chg_virtue(V_KNOWLEDGE, -1);
+ break;
+ }
+
+ /* Failure casting may activate some side effect */
+ do_spell(realm, spell, SPELL_FAIL);
+
+
+ if ((o_ptr->tval == TV_CHAOS_BOOK) && (randint1(100) < spell))
+ {
+ msg_print(_("カオス的な効果を発生した!", "You produce a chaotic effect!"));
+ wild_magic(spell);
+ }
+ else if ((o_ptr->tval == TV_DEATH_BOOK) && (randint1(100) < spell))
+ {
+ if ((sval == 3) && one_in_(2))
+ {
+ sanity_blast(0, TRUE);
+ }
+ else
+ {
+ msg_print(_("痛い!", "It hurts!"));
+ take_hit(DAMAGE_LOSELIFE, damroll(o_ptr->sval + 1, 6), _("暗黒魔法の逆流", "a miscast Death spell"), -1);
+
+ if ((spell > 15) && one_in_(6) && !p_ptr->hold_exp)
+ lose_exp(spell * 250);
+ }
+ }
+ else if ((o_ptr->tval == TV_MUSIC_BOOK) && (randint1(200) < spell))
+ {
+ msg_print(_("いやな音が響いた", "An infernal sound echoed."));
+ aggravate_monsters(0);
+ }
+ if (randint1(100) >= chance)
+ chg_virtue(V_CHANCE, -1);
+ }
+
+ /* Process spell */
+ else
+ {
+ /* Canceled spells cost neither a turn nor mana */
+ if (!do_spell(realm, spell, SPELL_CAST)) return;
+
+ if (randint1(100) < chance)
+ chg_virtue(V_CHANCE, 1);
+
+ /* A spell was cast */
+ if (!(increment ?
+ (p_ptr->spell_worked2 & (1L << spell)) :
+ (p_ptr->spell_worked1 & (1L << spell)))
+ && (p_ptr->pclass != CLASS_SORCERER)
+ && (p_ptr->pclass != CLASS_RED_MAGE))
+ {
+ int e = s_ptr->sexp;
+
+ /* The spell worked */
+ if (realm == p_ptr->realm1)
+ {
+ p_ptr->spell_worked1 |= (1L << spell);
+ }
+ else
+ {
+ p_ptr->spell_worked2 |= (1L << spell);
+ }
+
+ /* Gain experience */
+ gain_exp(e * s_ptr->slevel);
+
+ /* Redraw object recall */
+ p_ptr->window |= (PW_OBJECT);
+
+ switch (realm)
+ {
+ case REALM_LIFE:
+ chg_virtue(V_TEMPERANCE, 1);
+ chg_virtue(V_COMPASSION, 1);
+ chg_virtue(V_VITALITY, 1);
+ chg_virtue(V_DILIGENCE, 1);
+ break;
+ case REALM_DEATH:
+ chg_virtue(V_UNLIFE, 1);
+ chg_virtue(V_JUSTICE, -1);
+ chg_virtue(V_FAITH, -1);
+ chg_virtue(V_VITALITY, -1);
+ break;
+ case REALM_DAEMON:
+ chg_virtue(V_JUSTICE, -1);
+ chg_virtue(V_FAITH, -1);
+ chg_virtue(V_HONOUR, -1);
+ chg_virtue(V_TEMPERANCE, -1);
+ break;
+ case REALM_CRUSADE:
+ chg_virtue(V_FAITH, 1);
+ chg_virtue(V_JUSTICE, 1);
+ chg_virtue(V_SACRIFICE, 1);
+ chg_virtue(V_HONOUR, 1);
+ break;
+ case REALM_NATURE:
+ chg_virtue(V_NATURE, 1);
+ chg_virtue(V_HARMONY, 1);
+ break;
+ case REALM_HEX:
+ chg_virtue(V_JUSTICE, -1);
+ chg_virtue(V_FAITH, -1);
+ chg_virtue(V_HONOUR, -1);
+ chg_virtue(V_COMPASSION, -1);
+ break;
+ default:
+ chg_virtue(V_KNOWLEDGE, 1);
+ break;
+ }
+ }
+ switch (realm)
+ {
+ case REALM_LIFE:
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_TEMPERANCE, 1);
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_COMPASSION, 1);
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_VITALITY, 1);
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_DILIGENCE, 1);
+ break;
+ case REALM_DEATH:
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_UNLIFE, 1);
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, -1);
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, -1);
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_VITALITY, -1);
+ break;
+ case REALM_DAEMON:
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, -1);
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, -1);
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HONOUR, -1);
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_TEMPERANCE, -1);
+ break;
+ case REALM_CRUSADE:
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, 1);
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, 1);
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_SACRIFICE, 1);
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HONOUR, 1);
+ break;
+ case REALM_NATURE:
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_NATURE, 1);
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HARMONY, 1);
+ break;
+ case REALM_HEX:
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, -1);
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, -1);
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HONOUR, -1);
+ if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_COMPASSION, -1);
+ break;
+ }
+ if (mp_ptr->spell_xtra & MAGIC_GAIN_EXP)
+ {
+ s16b cur_exp = p_ptr->spell_exp[(increment ? 32 : 0) + spell];
+ s16b exp_gain = 0;
+
+ if (cur_exp < SPELL_EXP_BEGINNER)
+ exp_gain += 60;
+ else if (cur_exp < SPELL_EXP_SKILLED)
+ {
+ if ((dun_level > 4) && ((dun_level + 10) > p_ptr->lev))
+ exp_gain = 8;
+ }
+ else if (cur_exp < SPELL_EXP_EXPERT)
+ {
+ if (((dun_level + 5) > p_ptr->lev) && ((dun_level + 5) > s_ptr->slevel))
+ exp_gain = 2;
+ }
+ else if ((cur_exp < SPELL_EXP_MASTER) && !increment)
+ {
+ if (((dun_level + 5) > p_ptr->lev) && (dun_level > s_ptr->slevel))
+ exp_gain = 1;
+ }
+ p_ptr->spell_exp[(increment ? 32 : 0) + spell] += exp_gain;
+ }
+ }
+
+ take_turn(p_ptr, 100);;
+
+
+ /* Over-exert the player */
+ if (over_exerted)
+ {
+ int oops = need_mana;
+
+ /* No mana left */
+ p_ptr->csp = 0;
+ p_ptr->csp_frac = 0;
+
+ msg_print(_("精神を集中しすぎて気を失ってしまった!", "You faint from the effort!"));
+
+ /* Hack -- Bypass free action */
+ (void)set_paralyzed(p_ptr->paralyzed + randint1(5 * oops + 1));
+
+ switch (realm)
+ {
+ case REALM_LIFE:
+ chg_virtue(V_VITALITY, -10);
+ break;
+ case REALM_DEATH:
+ chg_virtue(V_UNLIFE, -10);
+ break;
+ case REALM_DAEMON:
+ chg_virtue(V_JUSTICE, 10);
+ break;
+ case REALM_NATURE:
+ chg_virtue(V_NATURE, -10);
+ break;
+ case REALM_CRUSADE:
+ chg_virtue(V_JUSTICE, -10);
+ break;
+ case REALM_HEX:
+ chg_virtue(V_COMPASSION, 10);
+ break;
+ default:
+ chg_virtue(V_KNOWLEDGE, -10);
+ break;
+ }
+
+ /* Damage CON (possibly permanently) */
+ if (randint0(100) < 50)
+ {
+ bool perm = (randint0(100) < 25);
+
+ msg_print(_("体を悪くしてしまった!", "You have damaged your health!"));
+
+ /* Reduce constitution */
+ (void)dec_stat(A_CON, 15 + randint1(10), perm);
+ }
+ }
+
+ p_ptr->window |= (PW_PLAYER);
+ p_ptr->window |= (PW_SPELL);
+}
-#define KWD_DAM _("損傷:", "dam ")\r
-#define KWD_RANGE _("射程:", "rng ")\r
-#define KWD_DURATION _("期間:", "dur ")\r
-#define KWD_SPHERE _("範囲:", "range ")\r
-#define KWD_HEAL _("回復:", "heal ")\r
-#define KWD_RANDOM _("ランダム", "random")\r
-\r
-extern concptr info_string_dice(concptr str, DICE_NUMBER dice, DICE_SID sides, int base);\r
-extern concptr info_damage(DICE_NUMBER dice, DICE_SID sides, int base);\r
-extern concptr info_duration(int base, DICE_SID sides);\r
-extern concptr info_range(POSITION range);\r
-extern concptr info_heal(DICE_NUMBER dice, DICE_SID sides, int base);\r
-extern concptr info_delay(int base, DICE_SID sides);\r
-extern concptr info_multi_damage(HIT_POINT dam);\r
-extern concptr info_multi_damage_dice(DICE_NUMBER dice, DICE_SID sides);\r
-extern concptr info_power(int power);\r
-extern concptr info_power_dice(DICE_NUMBER dice, DICE_SID sides);\r
-extern concptr info_radius(POSITION rad);\r
-extern concptr info_weight(WEIGHT weight);\r
-\r
-/* cmd5.c */\r
-extern void do_cmd_browse(void);\r
-extern void do_cmd_study(void);\r
-extern void do_cmd_cast(void);\r
+#define KWD_DAM _("損傷:", "dam ")
+#define KWD_RANGE _("射程:", "rng ")
+#define KWD_DURATION _("期間:", "dur ")
+#define KWD_SPHERE _("範囲:", "range ")
+#define KWD_HEAL _("回復:", "heal ")
+#define KWD_RANDOM _("ランダム", "random")
+
+extern concptr info_string_dice(concptr str, DICE_NUMBER dice, DICE_SID sides, int base);
+extern concptr info_damage(DICE_NUMBER dice, DICE_SID sides, int base);
+extern concptr info_duration(int base, DICE_SID sides);
+extern concptr info_range(POSITION range);
+extern concptr info_heal(DICE_NUMBER dice, DICE_SID sides, int base);
+extern concptr info_delay(int base, DICE_SID sides);
+extern concptr info_multi_damage(HIT_POINT dam);
+extern concptr info_multi_damage_dice(DICE_NUMBER dice, DICE_SID sides);
+extern concptr info_power(int power);
+extern concptr info_power_dice(DICE_NUMBER dice, DICE_SID sides);
+extern concptr info_radius(POSITION rad);
+extern concptr info_weight(WEIGHT weight);
+
+/* cmd5.c */
+extern void do_cmd_browse(void);
+extern void do_cmd_study(void);
+extern void do_cmd_cast(void);
-#include "angband.h"\r
-#include "projection.h"\r
-#include "spells-summon.h"\r
-#include "avatar.h"\r
-#include "player-status.h"\r
-#include "spells-status.h"\r
-\r
-\r
-\r
-/*!\r
-* @brief 杖の効果を発動する\r
-* @param sval オブジェクトのsval\r
-* @param use_charge 使用回数を消費したかどうかを返す参照ポインタ\r
-* @param powerful 強力発動上の処理ならばTRUE\r
-* @param magic 魔道具術上の処理ならばTRUE\r
-* @param known 判明済ならばTRUE\r
-* @return 発動により効果内容が確定したならばTRUEを返す\r
-*/\r
-int staff_effect(OBJECT_SUBTYPE_VALUE sval, bool *use_charge, bool powerful, bool magic, bool known)\r
-{\r
- int k;\r
- int ident = FALSE;\r
- PLAYER_LEVEL lev = powerful ? p_ptr->lev * 2 : p_ptr->lev;\r
- POSITION detect_rad = powerful ? DETECT_RAD_DEFAULT * 3 / 2 : DETECT_RAD_DEFAULT;\r
-\r
- /* Analyze the staff */\r
- switch (sval)\r
- {\r
- case SV_STAFF_DARKNESS:\r
- {\r
- if (!(p_ptr->resist_blind) && !(p_ptr->resist_dark))\r
- {\r
- if (set_blind(p_ptr->blind + 3 + randint1(5))) ident = TRUE;\r
- }\r
- if (unlite_area(10, (powerful ? 6 : 3))) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_STAFF_SLOWNESS:\r
- {\r
- if (set_slow(p_ptr->slow + randint1(30) + 15, FALSE)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_STAFF_HASTE_MONSTERS:\r
- {\r
- if (speed_monsters()) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_STAFF_SUMMONING:\r
- {\r
- const int times = randint1(powerful ? 8 : 4);\r
- for (k = 0; k < times; k++)\r
- {\r
- if (summon_specific(0, p_ptr->y, p_ptr->x, dun_level, 0, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0'))\r
- {\r
- ident = TRUE;\r
- }\r
- }\r
- break;\r
- }\r
-\r
- case SV_STAFF_TELEPORTATION:\r
- {\r
- teleport_player((powerful ? 150 : 100), 0L);\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_STAFF_IDENTIFY:\r
- {\r
- if (powerful) {\r
- if (!identify_fully(FALSE)) *use_charge = FALSE;\r
- }\r
- else {\r
- if (!ident_spell(FALSE)) *use_charge = FALSE;\r
- }\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_STAFF_REMOVE_CURSE:\r
- {\r
- bool result = powerful ? remove_all_curse() : remove_curse();\r
- if (result)\r
- {\r
- ident = TRUE;\r
- }\r
- break;\r
- }\r
-\r
- case SV_STAFF_STARLITE:\r
- ident = starlight(magic);\r
- break;\r
-\r
- case SV_STAFF_LITE:\r
- {\r
- if (lite_area(damroll(2, 8), (powerful ? 4 : 2))) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_STAFF_MAPPING:\r
- {\r
- map_area(powerful ? DETECT_RAD_MAP * 3 / 2 : DETECT_RAD_MAP);\r
- ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_STAFF_DETECT_GOLD:\r
- {\r
- if (detect_treasure(detect_rad)) ident = TRUE;\r
- if (detect_objects_gold(detect_rad)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_STAFF_DETECT_ITEM:\r
- {\r
- if (detect_objects_normal(detect_rad)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_STAFF_DETECT_TRAP:\r
- {\r
- if (detect_traps(detect_rad, known)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_STAFF_DETECT_DOOR:\r
- {\r
- if (detect_doors(detect_rad)) ident = TRUE;\r
- if (detect_stairs(detect_rad)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_STAFF_DETECT_INVIS:\r
- {\r
- if (detect_monsters_invis(detect_rad)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_STAFF_DETECT_EVIL:\r
- {\r
- if (detect_monsters_evil(detect_rad)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_STAFF_CURE_LIGHT:\r
- {\r
- ident = cure_light_wounds((powerful ? 4 : 2), 8);\r
- break;\r
- }\r
-\r
- case SV_STAFF_CURING:\r
- {\r
- ident = true_healing(0);\r
- if (set_shero(0, TRUE)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_STAFF_HEALING:\r
- {\r
- if (cure_critical_wounds(powerful ? 500 : 300)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_STAFF_THE_MAGI:\r
- {\r
- if (do_res_stat(A_INT)) ident = TRUE;\r
- ident |= restore_mana(FALSE);\r
- if (set_shero(0, TRUE)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_STAFF_SLEEP_MONSTERS:\r
- {\r
- if (sleep_monsters(lev)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_STAFF_SLOW_MONSTERS:\r
- {\r
- if (slow_monsters(lev)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_STAFF_SPEED:\r
- {\r
- if (set_fast(randint1(30) + (powerful ? 30 : 15), FALSE)) ident = TRUE;\r
- break;\r
- }\r
-\r
- case SV_STAFF_PROBING:\r
- {\r
- ident = probing();\r
- break;\r
- }\r
-\r
- case SV_STAFF_DISPEL_EVIL:\r
- {\r
- ident = dispel_evil(powerful ? 120 : 80);\r
- break;\r
- }\r
-\r
- case SV_STAFF_POWER:\r
- {\r
- ident = dispel_monsters(powerful ? 225 : 150) ;\r
- break;\r
- }\r
-\r
- case SV_STAFF_HOLINESS:\r
- {\r
- ident = cleansing_nova(p_ptr, magic, powerful);\r
- break;\r
- }\r
-\r
- case SV_STAFF_GENOCIDE:\r
- {\r
- ident = symbol_genocide((magic ? lev + 50 : 200), TRUE);\r
- break;\r
- }\r
-\r
- case SV_STAFF_EARTHQUAKES:\r
- {\r
- if (earthquake(p_ptr->y, p_ptr->x, (powerful ? 15 : 10)))\r
- ident = TRUE;\r
- else\r
- msg_print(_("ダンジョンが揺れた。", "The dungeon trembles."));\r
-\r
- break;\r
- }\r
-\r
- case SV_STAFF_DESTRUCTION:\r
- {\r
- ident = destroy_area(p_ptr->y, p_ptr->x, (powerful ? 18 : 13) + randint0(5), FALSE);\r
- break;\r
- }\r
-\r
- case SV_STAFF_ANIMATE_DEAD:\r
- {\r
- ident = animate_dead(0, p_ptr->y, p_ptr->x);\r
- break;\r
- }\r
-\r
- case SV_STAFF_MSTORM:\r
- {\r
- ident = unleash_mana_storm(p_ptr, powerful);\r
- break;\r
- }\r
-\r
- case SV_STAFF_NOTHING:\r
- {\r
- msg_print(_("何も起らなかった。", "Nothing happen."));\r
- if (prace_is_(RACE_SKELETON) || prace_is_(RACE_GOLEM) ||\r
- prace_is_(RACE_ZOMBIE) || prace_is_(RACE_SPECTRE))\r
- msg_print(_("もったいない事をしたような気がする。食べ物は大切にしなくては。", "What a waste. It's your food!"));\r
- break;\r
- }\r
- }\r
- return ident;\r
-}\r
-\r
-/*!\r
- * @brief 杖を使うコマンドのサブルーチン /\r
- * Use a staff. -RAK-\r
- * @param item 使うオブジェクトの所持品ID\r
- * @return なし\r
- * @details\r
- * One charge of one staff disappears.\r
- * Hack -- staffs of identify can be "cancelled".\r
- */\r
-void do_cmd_use_staff_aux(INVENTORY_IDX item)\r
-{\r
- int ident, chance, lev;\r
- object_type *o_ptr;\r
-\r
-\r
- /* Hack -- let staffs of identify get aborted */\r
- bool use_charge = TRUE;\r
-\r
-\r
- /* Get the item (in the pack) */\r
- if (item >= 0)\r
- {\r
- o_ptr = &inventory[item];\r
- }\r
-\r
- /* Get the item (on the floor) */\r
- else\r
- {\r
- o_ptr = &o_list[0 - item];\r
- }\r
-\r
-\r
- /* Mega-Hack -- refuse to use a pile from the ground */\r
- if ((item < 0) && (o_ptr->number > 1))\r
- {\r
- msg_print(_("まずは杖を拾わなければ。", "You must first pick up the staffs."));\r
- return;\r
- }\r
-\r
-\r
- take_turn(p_ptr, 100);;\r
-\r
- /* Extract the item level */\r
- lev = k_info[o_ptr->k_idx].level;\r
- if (lev > 50) lev = 50 + (lev - 50) / 2;\r
-\r
- /* Base chance of success */\r
- chance = p_ptr->skill_dev;\r
-\r
- /* Confusion hurts skill */\r
- if (p_ptr->confused) chance = chance / 2;\r
-\r
- /* Hight level objects are harder */\r
- chance = chance - lev;\r
-\r
- /* Give everyone a (slight) chance */\r
- if ((chance < USE_DEVICE) && one_in_(USE_DEVICE - chance + 1))\r
- {\r
- chance = USE_DEVICE;\r
- }\r
-\r
- if (cmd_limit_time_walk(p_ptr)) return;\r
-\r
- /* Roll for usage */\r
- if ((chance < USE_DEVICE) || (randint1(chance) < USE_DEVICE) || (p_ptr->pclass == CLASS_BERSERKER))\r
- {\r
- if (flush_failure) flush();\r
- msg_print(_("杖をうまく使えなかった。", "You failed to use the staff properly."));\r
- sound(SOUND_FAIL);\r
- return;\r
- }\r
-\r
- /* Notice empty staffs */\r
- if (o_ptr->pval <= 0)\r
- {\r
- if (flush_failure) flush();\r
- msg_print(_("この杖にはもう魔力が残っていない。", "The staff has no charges left."));\r
- o_ptr->ident |= (IDENT_EMPTY);\r
- p_ptr->update |= (PU_COMBINE | PU_REORDER);\r
- p_ptr->window |= (PW_INVEN);\r
-\r
- return;\r
- }\r
-\r
-\r
- sound(SOUND_ZAP);\r
-\r
- ident = staff_effect(o_ptr->sval, &use_charge, FALSE, FALSE, object_is_aware(o_ptr));\r
-\r
- if (!(object_is_aware(o_ptr)))\r
- {\r
- chg_virtue(V_PATIENCE, -1);\r
- chg_virtue(V_CHANCE, 1);\r
- chg_virtue(V_KNOWLEDGE, -1);\r
- }\r
- p_ptr->update |= (PU_COMBINE | PU_REORDER);\r
-\r
- /* Tried the item */\r
- object_tried(o_ptr);\r
-\r
- /* An identification was made */\r
- if (ident && !object_is_aware(o_ptr))\r
- {\r
- object_aware(o_ptr);\r
- gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev);\r
- }\r
-\r
- p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);\r
-\r
-\r
- /* Hack -- some uses are "free" */\r
- if (!use_charge) return;\r
-\r
-\r
- /* Use a single charge */\r
- o_ptr->pval--;\r
-\r
- /* XXX Hack -- unstack if necessary */\r
- if ((item >= 0) && (o_ptr->number > 1))\r
- {\r
- object_type forge;\r
- object_type *q_ptr;\r
- q_ptr = &forge;\r
-\r
- /* Obtain a local object */\r
- object_copy(q_ptr, o_ptr);\r
-\r
- /* Modify quantity */\r
- q_ptr->number = 1;\r
-\r
- /* Restore the charges */\r
- o_ptr->pval++;\r
-\r
- /* Unstack the used item */\r
- o_ptr->number--;\r
- p_ptr->total_weight -= q_ptr->weight;\r
- item = inven_carry(q_ptr);\r
-\r
- msg_print(_("杖をまとめなおした。", "You unstack your staff."));\r
- }\r
-\r
- /* Describe charges in the pack */\r
- if (item >= 0)\r
- {\r
- inven_item_charges(item);\r
- }\r
-\r
- /* Describe charges on the floor */\r
- else\r
- {\r
- floor_item_charges(0 - item);\r
- }\r
-}\r
-\r
-/*!\r
-* @brief 杖を使うコマンドのメインルーチン /\r
-* @return なし\r
-*/\r
-void do_cmd_use_staff(void)\r
-{\r
- OBJECT_IDX item;\r
- concptr q, s;\r
-\r
- if (p_ptr->wild_mode)\r
- {\r
- return;\r
- }\r
-\r
- if (cmd_limit_arena(p_ptr)) return;\r
-\r
- if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN))\r
- {\r
- set_action(ACTION_NONE);\r
- }\r
-\r
- /* Restrict choices to wands */\r
- item_tester_tval = TV_STAFF;\r
-\r
- q = _("どの杖を使いますか? ", "Use which staff? ");\r
- s = _("使える杖がない。", "You have no staff to use.");\r
-\r
- if (!choose_object(&item, q, s, (USE_INVEN | USE_FLOOR))) return;\r
-\r
- do_cmd_use_staff_aux(item);\r
-}\r
+#include "angband.h"
+#include "projection.h"
+#include "spells-summon.h"
+#include "avatar.h"
+#include "player-status.h"
+#include "spells-status.h"
+
+
+
+/*!
+* @brief 杖の効果を発動する
+* @param sval オブジェクトのsval
+* @param use_charge 使用回数を消費したかどうかを返す参照ポインタ
+* @param powerful 強力発動上の処理ならばTRUE
+* @param magic 魔道具術上の処理ならばTRUE
+* @param known 判明済ならばTRUE
+* @return 発動により効果内容が確定したならばTRUEを返す
+*/
+int staff_effect(OBJECT_SUBTYPE_VALUE sval, bool *use_charge, bool powerful, bool magic, bool known)
+{
+ int k;
+ int ident = FALSE;
+ PLAYER_LEVEL lev = powerful ? p_ptr->lev * 2 : p_ptr->lev;
+ POSITION detect_rad = powerful ? DETECT_RAD_DEFAULT * 3 / 2 : DETECT_RAD_DEFAULT;
+
+ /* Analyze the staff */
+ switch (sval)
+ {
+ case SV_STAFF_DARKNESS:
+ {
+ if (!(p_ptr->resist_blind) && !(p_ptr->resist_dark))
+ {
+ if (set_blind(p_ptr->blind + 3 + randint1(5))) ident = TRUE;
+ }
+ if (unlite_area(10, (powerful ? 6 : 3))) ident = TRUE;
+ break;
+ }
+
+ case SV_STAFF_SLOWNESS:
+ {
+ if (set_slow(p_ptr->slow + randint1(30) + 15, FALSE)) ident = TRUE;
+ break;
+ }
+
+ case SV_STAFF_HASTE_MONSTERS:
+ {
+ if (speed_monsters()) ident = TRUE;
+ break;
+ }
+
+ case SV_STAFF_SUMMONING:
+ {
+ const int times = randint1(powerful ? 8 : 4);
+ for (k = 0; k < times; k++)
+ {
+ if (summon_specific(0, p_ptr->y, p_ptr->x, dun_level, 0, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0'))
+ {
+ ident = TRUE;
+ }
+ }
+ break;
+ }
+
+ case SV_STAFF_TELEPORTATION:
+ {
+ teleport_player((powerful ? 150 : 100), 0L);
+ ident = TRUE;
+ break;
+ }
+
+ case SV_STAFF_IDENTIFY:
+ {
+ if (powerful) {
+ if (!identify_fully(FALSE)) *use_charge = FALSE;
+ }
+ else {
+ if (!ident_spell(FALSE)) *use_charge = FALSE;
+ }
+ ident = TRUE;
+ break;
+ }
+
+ case SV_STAFF_REMOVE_CURSE:
+ {
+ bool result = powerful ? remove_all_curse() : remove_curse();
+ if (result)
+ {
+ ident = TRUE;
+ }
+ break;
+ }
+
+ case SV_STAFF_STARLITE:
+ ident = starlight(magic);
+ break;
+
+ case SV_STAFF_LITE:
+ {
+ if (lite_area(damroll(2, 8), (powerful ? 4 : 2))) ident = TRUE;
+ break;
+ }
+
+ case SV_STAFF_MAPPING:
+ {
+ map_area(powerful ? DETECT_RAD_MAP * 3 / 2 : DETECT_RAD_MAP);
+ ident = TRUE;
+ break;
+ }
+
+ case SV_STAFF_DETECT_GOLD:
+ {
+ if (detect_treasure(detect_rad)) ident = TRUE;
+ if (detect_objects_gold(detect_rad)) ident = TRUE;
+ break;
+ }
+
+ case SV_STAFF_DETECT_ITEM:
+ {
+ if (detect_objects_normal(detect_rad)) ident = TRUE;
+ break;
+ }
+
+ case SV_STAFF_DETECT_TRAP:
+ {
+ if (detect_traps(detect_rad, known)) ident = TRUE;
+ break;
+ }
+
+ case SV_STAFF_DETECT_DOOR:
+ {
+ if (detect_doors(detect_rad)) ident = TRUE;
+ if (detect_stairs(detect_rad)) ident = TRUE;
+ break;
+ }
+
+ case SV_STAFF_DETECT_INVIS:
+ {
+ if (detect_monsters_invis(detect_rad)) ident = TRUE;
+ break;
+ }
+
+ case SV_STAFF_DETECT_EVIL:
+ {
+ if (detect_monsters_evil(detect_rad)) ident = TRUE;
+ break;
+ }
+
+ case SV_STAFF_CURE_LIGHT:
+ {
+ ident = cure_light_wounds((powerful ? 4 : 2), 8);
+ break;
+ }
+
+ case SV_STAFF_CURING:
+ {
+ ident = true_healing(0);
+ if (set_shero(0, TRUE)) ident = TRUE;
+ break;
+ }
+
+ case SV_STAFF_HEALING:
+ {
+ if (cure_critical_wounds(powerful ? 500 : 300)) ident = TRUE;
+ break;
+ }
+
+ case SV_STAFF_THE_MAGI:
+ {
+ if (do_res_stat(A_INT)) ident = TRUE;
+ ident |= restore_mana(FALSE);
+ if (set_shero(0, TRUE)) ident = TRUE;
+ break;
+ }
+
+ case SV_STAFF_SLEEP_MONSTERS:
+ {
+ if (sleep_monsters(lev)) ident = TRUE;
+ break;
+ }
+
+ case SV_STAFF_SLOW_MONSTERS:
+ {
+ if (slow_monsters(lev)) ident = TRUE;
+ break;
+ }
+
+ case SV_STAFF_SPEED:
+ {
+ if (set_fast(randint1(30) + (powerful ? 30 : 15), FALSE)) ident = TRUE;
+ break;
+ }
+
+ case SV_STAFF_PROBING:
+ {
+ ident = probing();
+ break;
+ }
+
+ case SV_STAFF_DISPEL_EVIL:
+ {
+ ident = dispel_evil(powerful ? 120 : 80);
+ break;
+ }
+
+ case SV_STAFF_POWER:
+ {
+ ident = dispel_monsters(powerful ? 225 : 150) ;
+ break;
+ }
+
+ case SV_STAFF_HOLINESS:
+ {
+ ident = cleansing_nova(p_ptr, magic, powerful);
+ break;
+ }
+
+ case SV_STAFF_GENOCIDE:
+ {
+ ident = symbol_genocide((magic ? lev + 50 : 200), TRUE);
+ break;
+ }
+
+ case SV_STAFF_EARTHQUAKES:
+ {
+ if (earthquake(p_ptr->y, p_ptr->x, (powerful ? 15 : 10)))
+ ident = TRUE;
+ else
+ msg_print(_("ダンジョンが揺れた。", "The dungeon trembles."));
+
+ break;
+ }
+
+ case SV_STAFF_DESTRUCTION:
+ {
+ ident = destroy_area(p_ptr->y, p_ptr->x, (powerful ? 18 : 13) + randint0(5), FALSE);
+ break;
+ }
+
+ case SV_STAFF_ANIMATE_DEAD:
+ {
+ ident = animate_dead(0, p_ptr->y, p_ptr->x);
+ break;
+ }
+
+ case SV_STAFF_MSTORM:
+ {
+ ident = unleash_mana_storm(p_ptr, powerful);
+ break;
+ }
+
+ case SV_STAFF_NOTHING:
+ {
+ msg_print(_("何も起らなかった。", "Nothing happen."));
+ if (prace_is_(RACE_SKELETON) || prace_is_(RACE_GOLEM) ||
+ prace_is_(RACE_ZOMBIE) || prace_is_(RACE_SPECTRE))
+ msg_print(_("もったいない事をしたような気がする。食べ物は大切にしなくては。", "What a waste. It's your food!"));
+ break;
+ }
+ }
+ return ident;
+}
+
+/*!
+ * @brief 杖を使うコマンドのサブルーチン /
+ * Use a staff. -RAK-
+ * @param item 使うオブジェクトの所持品ID
+ * @return なし
+ * @details
+ * One charge of one staff disappears.
+ * Hack -- staffs of identify can be "cancelled".
+ */
+void do_cmd_use_staff_aux(INVENTORY_IDX item)
+{
+ int ident, chance, lev;
+ object_type *o_ptr;
+
+
+ /* Hack -- let staffs of identify get aborted */
+ bool use_charge = TRUE;
+
+
+ /* Get the item (in the pack) */
+ if (item >= 0)
+ {
+ o_ptr = &inventory[item];
+ }
+
+ /* Get the item (on the floor) */
+ else
+ {
+ o_ptr = &o_list[0 - item];
+ }
+
+
+ /* Mega-Hack -- refuse to use a pile from the ground */
+ if ((item < 0) && (o_ptr->number > 1))
+ {
+ msg_print(_("まずは杖を拾わなければ。", "You must first pick up the staffs."));
+ return;
+ }
+
+
+ take_turn(p_ptr, 100);;
+
+ /* Extract the item level */
+ lev = k_info[o_ptr->k_idx].level;
+ if (lev > 50) lev = 50 + (lev - 50) / 2;
+
+ /* Base chance of success */
+ chance = p_ptr->skill_dev;
+
+ /* Confusion hurts skill */
+ if (p_ptr->confused) chance = chance / 2;
+
+ /* Hight level objects are harder */
+ chance = chance - lev;
+
+ /* Give everyone a (slight) chance */
+ if ((chance < USE_DEVICE) && one_in_(USE_DEVICE - chance + 1))
+ {
+ chance = USE_DEVICE;
+ }
+
+ if (cmd_limit_time_walk(p_ptr)) return;
+
+ /* Roll for usage */
+ if ((chance < USE_DEVICE) || (randint1(chance) < USE_DEVICE) || (p_ptr->pclass == CLASS_BERSERKER))
+ {
+ if (flush_failure) flush();
+ msg_print(_("杖をうまく使えなかった。", "You failed to use the staff properly."));
+ sound(SOUND_FAIL);
+ return;
+ }
+
+ /* Notice empty staffs */
+ if (o_ptr->pval <= 0)
+ {
+ if (flush_failure) flush();
+ msg_print(_("この杖にはもう魔力が残っていない。", "The staff has no charges left."));
+ o_ptr->ident |= (IDENT_EMPTY);
+ p_ptr->update |= (PU_COMBINE | PU_REORDER);
+ p_ptr->window |= (PW_INVEN);
+
+ return;
+ }
+
+
+ sound(SOUND_ZAP);
+
+ ident = staff_effect(o_ptr->sval, &use_charge, FALSE, FALSE, object_is_aware(o_ptr));
+
+ if (!(object_is_aware(o_ptr)))
+ {
+ chg_virtue(V_PATIENCE, -1);
+ chg_virtue(V_CHANCE, 1);
+ chg_virtue(V_KNOWLEDGE, -1);
+ }
+ p_ptr->update |= (PU_COMBINE | PU_REORDER);
+
+ /* Tried the item */
+ object_tried(o_ptr);
+
+ /* An identification was made */
+ if (ident && !object_is_aware(o_ptr))
+ {
+ object_aware(o_ptr);
+ gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev);
+ }
+
+ p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
+
+
+ /* Hack -- some uses are "free" */
+ if (!use_charge) return;
+
+
+ /* Use a single charge */
+ o_ptr->pval--;
+
+ /* XXX Hack -- unstack if necessary */
+ if ((item >= 0) && (o_ptr->number > 1))
+ {
+ object_type forge;
+ object_type *q_ptr;
+ q_ptr = &forge;
+
+ /* Obtain a local object */
+ object_copy(q_ptr, o_ptr);
+
+ /* Modify quantity */
+ q_ptr->number = 1;
+
+ /* Restore the charges */
+ o_ptr->pval++;
+
+ /* Unstack the used item */
+ o_ptr->number--;
+ p_ptr->total_weight -= q_ptr->weight;
+ item = inven_carry(q_ptr);
+
+ msg_print(_("杖をまとめなおした。", "You unstack your staff."));
+ }
+
+ /* Describe charges in the pack */
+ if (item >= 0)
+ {
+ inven_item_charges(item);
+ }
+
+ /* Describe charges on the floor */
+ else
+ {
+ floor_item_charges(0 - item);
+ }
+}
+
+/*!
+* @brief 杖を使うコマンドのメインルーチン /
+* @return なし
+*/
+void do_cmd_use_staff(void)
+{
+ OBJECT_IDX item;
+ concptr q, s;
+
+ if (p_ptr->wild_mode)
+ {
+ return;
+ }
+
+ if (cmd_limit_arena(p_ptr)) return;
+
+ if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN))
+ {
+ set_action(ACTION_NONE);
+ }
+
+ /* Restrict choices to wands */
+ item_tester_tval = TV_STAFF;
+
+ q = _("どの杖を使いますか? ", "Use which staff? ");
+ s = _("使える杖がない。", "You have no staff to use.");
+
+ if (!choose_object(&item, q, s, (USE_INVEN | USE_FLOOR))) return;
+
+ do_cmd_use_staff_aux(item);
+}
-extern int staff_effect(OBJECT_SUBTYPE_VALUE sval, bool *use_charge, bool powerful, bool magic, bool known);\r
-extern void do_cmd_use_staff_aux(INVENTORY_IDX item);\r
-extern void do_cmd_use_staff(void);\r
+extern int staff_effect(OBJECT_SUBTYPE_VALUE sval, bool *use_charge, bool powerful, bool magic, bool known);
+extern void do_cmd_use_staff_aux(INVENTORY_IDX item);
+extern void do_cmd_use_staff(void);
-#include "angband.h"\r
-\r
-void day_break()\r
-{\r
- POSITION y, x;\r
- msg_print(_("夜が明けた。", "The sun has risen."));\r
-\r
- if (!p_ptr->wild_mode)\r
- {\r
- /* Hack -- Scan the town */\r
- for (y = 0; y < cur_hgt; y++)\r
- {\r
- for (x = 0; x < cur_wid; x++)\r
- {\r
- /* Get the cave grid */\r
- cave_type *c_ptr = &cave[y][x];\r
-\r
- /* Assume lit */\r
- c_ptr->info |= (CAVE_GLOW);\r
-\r
- /* Hack -- Memorize lit grids if allowed */\r
- if (view_perma_grids) c_ptr->info |= (CAVE_MARK);\r
-\r
- /* Hack -- Notice spot */\r
- note_spot(y, x);\r
- }\r
- }\r
- }\r
-\r
- p_ptr->update |= (PU_MONSTERS | PU_MON_LITE);\r
- p_ptr->redraw |= (PR_MAP);\r
- p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);\r
-\r
- if (p_ptr->special_defense & NINJA_S_STEALTH)\r
- {\r
- if (cave[p_ptr->y][p_ptr->x].info & CAVE_GLOW) set_superstealth(FALSE);\r
- }\r
-\r
-}\r
-\r
-void night_falls(void)\r
-{\r
- POSITION y, x;\r
- msg_print(_("日が沈んだ。", "The sun has fallen."));\r
-\r
- if (!p_ptr->wild_mode)\r
- {\r
- /* Hack -- Scan the town */\r
- for (y = 0; y < cur_hgt; y++)\r
- {\r
- for (x = 0; x < cur_wid; x++)\r
- {\r
- /* Get the cave grid */\r
- cave_type *c_ptr = &cave[y][x];\r
-\r
- /* Feature code (applying "mimic" field) */\r
- feature_type *f_ptr = &f_info[get_feat_mimic(c_ptr)];\r
-\r
- if (!is_mirror_grid(c_ptr) && !have_flag(f_ptr->flags, FF_QUEST_ENTER) &&\r
- !have_flag(f_ptr->flags, FF_ENTRANCE))\r
- {\r
- /* Assume dark */\r
- c_ptr->info &= ~(CAVE_GLOW);\r
-\r
- if (!have_flag(f_ptr->flags, FF_REMEMBER))\r
- {\r
- /* Forget the normal floor grid */\r
- c_ptr->info &= ~(CAVE_MARK);\r
-\r
- /* Hack -- Notice spot */\r
- note_spot(y, x);\r
- }\r
- }\r
- }\r
-\r
- /* Glow deep lava and building entrances */\r
- glow_deep_lava_and_bldg();\r
- }\r
- }\r
-\r
- p_ptr->update |= (PU_MONSTERS | PU_MON_LITE);\r
- p_ptr->redraw |= (PR_MAP);\r
- p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);\r
-\r
- if (p_ptr->special_defense & NINJA_S_STEALTH)\r
- {\r
- if (cave[p_ptr->y][p_ptr->x].info & CAVE_GLOW) set_superstealth(FALSE);\r
- }\r
-\r
-}\r
-\r
-/*!\r
- * @brief 現在フロアに残っている敵モンスターの数を返す /\r
- * @return 現在の敵モンスターの数\r
- */\r
-MONSTER_NUMBER count_all_hostile_monsters(void)\r
-{\r
- POSITION x, y;\r
- MONSTER_NUMBER number_mon = 0;\r
-\r
- for (x = 0; x < cur_wid; ++x)\r
- {\r
- for (y = 0; y < cur_hgt; ++y)\r
- {\r
- MONSTER_IDX m_idx = cave[y][x].m_idx;\r
-\r
- if (m_idx > 0 && is_hostile(&m_list[m_idx]))\r
- {\r
- ++number_mon;\r
- }\r
- }\r
- }\r
-\r
- return number_mon;\r
-}\r
+#include "angband.h"
+
+void day_break()
+{
+ POSITION y, x;
+ msg_print(_("夜が明けた。", "The sun has risen."));
+
+ if (!p_ptr->wild_mode)
+ {
+ /* Hack -- Scan the town */
+ for (y = 0; y < cur_hgt; y++)
+ {
+ for (x = 0; x < cur_wid; x++)
+ {
+ /* Get the cave grid */
+ cave_type *c_ptr = &cave[y][x];
+
+ /* Assume lit */
+ c_ptr->info |= (CAVE_GLOW);
+
+ /* Hack -- Memorize lit grids if allowed */
+ if (view_perma_grids) c_ptr->info |= (CAVE_MARK);
+
+ /* Hack -- Notice spot */
+ note_spot(y, x);
+ }
+ }
+ }
+
+ p_ptr->update |= (PU_MONSTERS | PU_MON_LITE);
+ p_ptr->redraw |= (PR_MAP);
+ p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
+
+ if (p_ptr->special_defense & NINJA_S_STEALTH)
+ {
+ if (cave[p_ptr->y][p_ptr->x].info & CAVE_GLOW) set_superstealth(FALSE);
+ }
+
+}
+
+void night_falls(void)
+{
+ POSITION y, x;
+ msg_print(_("日が沈んだ。", "The sun has fallen."));
+
+ if (!p_ptr->wild_mode)
+ {
+ /* Hack -- Scan the town */
+ for (y = 0; y < cur_hgt; y++)
+ {
+ for (x = 0; x < cur_wid; x++)
+ {
+ /* Get the cave grid */
+ cave_type *c_ptr = &cave[y][x];
+
+ /* Feature code (applying "mimic" field) */
+ feature_type *f_ptr = &f_info[get_feat_mimic(c_ptr)];
+
+ if (!is_mirror_grid(c_ptr) && !have_flag(f_ptr->flags, FF_QUEST_ENTER) &&
+ !have_flag(f_ptr->flags, FF_ENTRANCE))
+ {
+ /* Assume dark */
+ c_ptr->info &= ~(CAVE_GLOW);
+
+ if (!have_flag(f_ptr->flags, FF_REMEMBER))
+ {
+ /* Forget the normal floor grid */
+ c_ptr->info &= ~(CAVE_MARK);
+
+ /* Hack -- Notice spot */
+ note_spot(y, x);
+ }
+ }
+ }
+
+ /* Glow deep lava and building entrances */
+ glow_deep_lava_and_bldg();
+ }
+ }
+
+ p_ptr->update |= (PU_MONSTERS | PU_MON_LITE);
+ p_ptr->redraw |= (PR_MAP);
+ p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
+
+ if (p_ptr->special_defense & NINJA_S_STEALTH)
+ {
+ if (cave[p_ptr->y][p_ptr->x].info & CAVE_GLOW) set_superstealth(FALSE);
+ }
+
+}
+
+/*!
+ * @brief 現在フロアに残っている敵モンスターの数を返す /
+ * @return 現在の敵モンスターの数
+ */
+MONSTER_NUMBER count_all_hostile_monsters(void)
+{
+ POSITION x, y;
+ MONSTER_NUMBER number_mon = 0;
+
+ for (x = 0; x < cur_wid; ++x)
+ {
+ for (y = 0; y < cur_hgt; ++y)
+ {
+ MONSTER_IDX m_idx = cave[y][x].m_idx;
+
+ if (m_idx > 0 && is_hostile(&m_list[m_idx]))
+ {
+ ++number_mon;
+ }
+ }
+ }
+
+ return number_mon;
+}
-void day_break(void);\r
-void night_falls(void);\r
-MONSTER_NUMBER count_all_hostile_monsters(void);\r
+void day_break(void);
+void night_falls(void);
+MONSTER_NUMBER count_all_hostile_monsters(void);
-/*** Input Options ***/\r
-\r
-extern bool rogue_like_commands; /* Rogue-like commands */\r
-extern bool always_pickup; /* Pick things up by default */\r
-extern bool carry_query_flag; /* Prompt before picking things up */\r
-extern bool quick_messages; /* Activate quick messages */\r
-extern bool auto_more; /* Automatically clear '-more-' prompts */\r
-extern bool command_menu; /* Enable command selection menu */\r
-extern bool other_query_flag; /* Prompt for floor item selection */\r
-extern bool use_old_target; /* Use old target by default */\r
-extern bool always_repeat; /* Repeat obvious commands */\r
-extern bool confirm_destroy; /* Prompt for destruction of known worthless items */\r
-extern bool confirm_wear; /* Confirm to wear/wield known cursed items */\r
-extern bool confirm_quest; /* Prompt before exiting a quest level */\r
-extern bool target_pet; /* Allow targetting pets */\r
-extern bool easy_open; /* Automatically open doors */\r
-extern bool easy_disarm; /* Automatically disarm traps */\r
-extern bool easy_floor; /* Display floor stacks in a list */\r
-extern bool use_command; /* Allow unified use command */\r
-extern bool over_exert; /* Allow casting spells when short of mana */\r
-extern bool numpad_as_cursorkey; /* Use numpad keys as cursor key in editor mode */\r
-\r
-\r
- /*** Map Screen Options ***/\r
-\r
-extern bool center_player; /* Center map while walking (*slow*) */\r
-extern bool center_running; /* Centering even while running */\r
-extern bool view_yellow_lite; /* Use special colors for torch-lit grids */\r
-extern bool view_bright_lite; /* Use special colors for 'viewable' grids */\r
-extern bool view_granite_lite; /* Use special colors for wall grids (slow) */\r
-extern bool view_special_lite; /* Use special colors for floor grids (slow) */\r
-extern bool view_perma_grids; /* Map remembers all perma-lit grids */\r
-extern bool view_torch_grids; /* Map remembers all torch-lit grids */\r
-extern bool view_unsafe_grids; /* Map marked by detect traps */\r
-extern bool view_reduce_view; /* Reduce view-radius in town */\r
-extern bool fresh_before; /* Flush output while continuous command */\r
-extern bool fresh_after; /* Flush output after monster's move */\r
-extern bool fresh_message; /* Flush output after every message */\r
-extern bool hilite_player; /* Hilite the player with the cursor */\r
-extern bool display_path; /* Display actual path before shooting */\r
-\r
-\r
- /*** Text Display Options ***/\r
-\r
-extern bool plain_descriptions; /* Plain object descriptions */\r
-extern bool plain_pickup; /* Plain pickup messages(japanese only) */\r
-extern bool always_show_list; /* Always show list when choosing items */\r
-extern bool depth_in_feet; /* Show dungeon level in feet */\r
-extern bool show_labels; /* Show labels in object listings */\r
-extern bool show_weights; /* Show weights in object listings */\r
-extern bool show_item_graph; /* Show items graphics */\r
-extern bool equippy_chars; /* Display 'equippy' chars */\r
-extern bool display_mutations; /* Display mutations in 'C'haracter Display */\r
-extern bool compress_savefile; /* Compress messages in savefiles */\r
-extern bool abbrev_extra; /* Describe obj's extra resistances by abbreviation */\r
-extern bool abbrev_all; /* Describe obj's all resistances by abbreviation */\r
-extern bool exp_need; /* Show the experience needed for next level */\r
-extern bool ignore_unview; /* Ignore whenever any monster does */\r
-extern bool show_ammo_detail; /* Show Description of ammo damage */\r
-extern bool show_ammo_no_crit; /* Show No-crit damage of ammo */\r
-extern bool show_ammo_crit_ratio; /* Show critical ratio of ammo */\r
-extern bool show_actual_value; /* Show actual value of skill */\r
-\r
- /*** Game-Play Options ***/\r
-\r
-extern bool stack_force_notes; /* Merge inscriptions when stacking */\r
-extern bool stack_force_costs; /* Merge discounts when stacking */\r
-extern bool expand_list; /* Expand the power of the list commands */\r
-extern bool small_levels; /* Allow unusually small dungeon levels */\r
-extern bool always_small_levels; /* Always create unusually small dungeon levels */\r
-extern bool empty_levels; /* Allow empty 'arena' levels */\r
-extern bool bound_walls_perm; /* Boundary walls become 'permanent wall' */\r
-extern bool last_words; /* Leave last words when your character dies */\r
-\r
-#ifdef WORLD_SCORE\r
-extern bool send_score; /* Send score dump to the world score server */\r
-#endif\r
-\r
-extern bool allow_debug_opts; /* Allow use of debug/cheat options */\r
-\r
-\r
- /*** Disturbance Options ***/\r
-\r
-extern bool find_ignore_stairs; /* Run past stairs */\r
-extern bool find_ignore_doors; /* Run through open doors */\r
-extern bool find_cut; /* Run past known corners */\r
-extern bool check_abort; /* Check for user abort while continuous command */\r
-extern bool flush_failure; /* Flush input on various failures */\r
-extern bool flush_disturb; /* Flush input whenever disturbed */\r
-extern bool disturb_move; /* Disturb whenever any monster moves */\r
-extern bool disturb_high; /* Disturb whenever high-level monster moves */\r
-extern bool disturb_near; /* Disturb whenever viewable monster moves */\r
-extern bool disturb_pets; /* Disturb when visible pets move */\r
-extern bool disturb_panel; /* Disturb whenever map panel changes */\r
-extern bool disturb_state; /* Disturb whenever player state changes */\r
-extern bool disturb_minor; /* Disturb whenever boring things happen */\r
-extern bool ring_bell; /* Audible bell (on errors, etc) */\r
-extern bool disturb_trap_detect; /* Disturb when leaving trap detected area */\r
-extern bool alert_trap_detect; /* Alert when leaving trap detected area */\r
-\r
-\r
- /*** Birth Options ***/\r
-\r
-extern bool manual_haggle; /* Manually haggle in stores */\r
-extern bool easy_band; /* Easy Mode (*) */\r
-extern bool smart_learn; /* Monsters learn from their mistakes (*) */\r
-extern bool smart_cheat; /* Monsters exploit players weaknesses (*) */\r
-extern bool vanilla_town; /* Use 'vanilla' town without quests and wilderness */\r
-extern bool lite_town; /* Use 'lite' town without a wilderness */\r
-extern bool ironman_shops; /* Stores are permanently closed (*) */\r
-extern bool ironman_small_levels; /* Always create unusually small dungeon levels (*) */\r
-extern bool ironman_downward; /* Disable recall and use of up stairs (*) */\r
-extern bool ironman_empty_levels; /* Always create empty 'arena' levels (*) */\r
-extern bool ironman_rooms; /* Always generate very unusual rooms (*) */\r
-extern bool ironman_nightmare; /* Nightmare mode(it isn't even remotely fair!)(*) */\r
-extern bool left_hander; /* Left-Hander */\r
-extern bool preserve_mode; /* Preserve artifacts (*) */\r
-extern bool autoroller; /* Allow use of autoroller for stats (*) */\r
-extern bool autochara; /* Autoroll for weight, height and social status */\r
-extern bool powerup_home; /* Increase capacity of your home (*) */\r
-\r
-\r
- /*** Easy Object Auto-Destroyer ***/\r
-\r
-extern bool destroy_items; /* Use easy auto-destroyer */\r
-extern bool destroy_feeling; /* Apply auto-destroy as sense feeling */\r
-extern bool destroy_identify; /* Apply auto-destroy as identify an item */\r
-extern bool leave_worth; /* Auto-destroyer leaves known worthy items */\r
-extern bool leave_equip; /* Auto-destroyer leaves weapons and armour */\r
-extern bool leave_chest; /* Auto-destroyer leaves closed chests */\r
-extern bool leave_wanted; /* Auto-destroyer leaves wanted corpses */\r
-extern bool leave_corpse; /* Auto-destroyer leaves corpses and skeletons */\r
-extern bool leave_junk; /* Auto-destroyer leaves junk */\r
-extern bool leave_special; /* Auto-destroyer leaves items your race/class needs */\r
-\r
-\r
- /*** Play-record Options ***/\r
-\r
-extern bool record_fix_art; /* Record fixed artifacts */\r
-extern bool record_rand_art; /* Record random artifacts */\r
-extern bool record_destroy_uniq; /* Record when destroy unique monster */\r
-extern bool record_fix_quest; /* Record fixed quests */\r
-extern bool record_rand_quest; /* Record random quests */\r
-extern bool record_maxdepth; /* Record movements to deepest level */\r
-extern bool record_stair; /* Record recall and stair movements */\r
-extern bool record_buy; /* Record purchased items */\r
-extern bool record_sell; /* Record sold items */\r
-extern bool record_danger; /* Record hitpoint warning */\r
-extern bool record_arena; /* Record arena victories */\r
-extern bool record_ident; /* Record first identified items */\r
-extern bool record_named_pet; /* Record informations of named pets */\r
-\r
-\r
-extern bool cheat_peek;\r
-extern bool cheat_hear;\r
-extern bool cheat_room;\r
-extern bool cheat_xtra;\r
-extern bool cheat_know;\r
-extern bool cheat_live;\r
-extern bool cheat_save;\r
-extern bool cheat_diary_output;\r
-extern bool cheat_turn;\r
-extern bool cheat_sight;\r
-\r
-extern byte hitpoint_warn;\r
-extern byte mana_warn;\r
-extern byte delay_factor;\r
-extern s16b autosave_freq;\r
-extern bool autosave_t;\r
-extern bool autosave_l;\r
+/*** Input Options ***/
+
+extern bool rogue_like_commands; /* Rogue-like commands */
+extern bool always_pickup; /* Pick things up by default */
+extern bool carry_query_flag; /* Prompt before picking things up */
+extern bool quick_messages; /* Activate quick messages */
+extern bool auto_more; /* Automatically clear '-more-' prompts */
+extern bool command_menu; /* Enable command selection menu */
+extern bool other_query_flag; /* Prompt for floor item selection */
+extern bool use_old_target; /* Use old target by default */
+extern bool always_repeat; /* Repeat obvious commands */
+extern bool confirm_destroy; /* Prompt for destruction of known worthless items */
+extern bool confirm_wear; /* Confirm to wear/wield known cursed items */
+extern bool confirm_quest; /* Prompt before exiting a quest level */
+extern bool target_pet; /* Allow targetting pets */
+extern bool easy_open; /* Automatically open doors */
+extern bool easy_disarm; /* Automatically disarm traps */
+extern bool easy_floor; /* Display floor stacks in a list */
+extern bool use_command; /* Allow unified use command */
+extern bool over_exert; /* Allow casting spells when short of mana */
+extern bool numpad_as_cursorkey; /* Use numpad keys as cursor key in editor mode */
+
+
+ /*** Map Screen Options ***/
+
+extern bool center_player; /* Center map while walking (*slow*) */
+extern bool center_running; /* Centering even while running */
+extern bool view_yellow_lite; /* Use special colors for torch-lit grids */
+extern bool view_bright_lite; /* Use special colors for 'viewable' grids */
+extern bool view_granite_lite; /* Use special colors for wall grids (slow) */
+extern bool view_special_lite; /* Use special colors for floor grids (slow) */
+extern bool view_perma_grids; /* Map remembers all perma-lit grids */
+extern bool view_torch_grids; /* Map remembers all torch-lit grids */
+extern bool view_unsafe_grids; /* Map marked by detect traps */
+extern bool view_reduce_view; /* Reduce view-radius in town */
+extern bool fresh_before; /* Flush output while continuous command */
+extern bool fresh_after; /* Flush output after monster's move */
+extern bool fresh_message; /* Flush output after every message */
+extern bool hilite_player; /* Hilite the player with the cursor */
+extern bool display_path; /* Display actual path before shooting */
+
+
+ /*** Text Display Options ***/
+
+extern bool plain_descriptions; /* Plain object descriptions */
+extern bool plain_pickup; /* Plain pickup messages(japanese only) */
+extern bool always_show_list; /* Always show list when choosing items */
+extern bool depth_in_feet; /* Show dungeon level in feet */
+extern bool show_labels; /* Show labels in object listings */
+extern bool show_weights; /* Show weights in object listings */
+extern bool show_item_graph; /* Show items graphics */
+extern bool equippy_chars; /* Display 'equippy' chars */
+extern bool display_mutations; /* Display mutations in 'C'haracter Display */
+extern bool compress_savefile; /* Compress messages in savefiles */
+extern bool abbrev_extra; /* Describe obj's extra resistances by abbreviation */
+extern bool abbrev_all; /* Describe obj's all resistances by abbreviation */
+extern bool exp_need; /* Show the experience needed for next level */
+extern bool ignore_unview; /* Ignore whenever any monster does */
+extern bool show_ammo_detail; /* Show Description of ammo damage */
+extern bool show_ammo_no_crit; /* Show No-crit damage of ammo */
+extern bool show_ammo_crit_ratio; /* Show critical ratio of ammo */
+extern bool show_actual_value; /* Show actual value of skill */
+
+ /*** Game-Play Options ***/
+
+extern bool stack_force_notes; /* Merge inscriptions when stacking */
+extern bool stack_force_costs; /* Merge discounts when stacking */
+extern bool expand_list; /* Expand the power of the list commands */
+extern bool small_levels; /* Allow unusually small dungeon levels */
+extern bool always_small_levels; /* Always create unusually small dungeon levels */
+extern bool empty_levels; /* Allow empty 'arena' levels */
+extern bool bound_walls_perm; /* Boundary walls become 'permanent wall' */
+extern bool last_words; /* Leave last words when your character dies */
+
+#ifdef WORLD_SCORE
+extern bool send_score; /* Send score dump to the world score server */
+#endif
+
+extern bool allow_debug_opts; /* Allow use of debug/cheat options */
+
+
+ /*** Disturbance Options ***/
+
+extern bool find_ignore_stairs; /* Run past stairs */
+extern bool find_ignore_doors; /* Run through open doors */
+extern bool find_cut; /* Run past known corners */
+extern bool check_abort; /* Check for user abort while continuous command */
+extern bool flush_failure; /* Flush input on various failures */
+extern bool flush_disturb; /* Flush input whenever disturbed */
+extern bool disturb_move; /* Disturb whenever any monster moves */
+extern bool disturb_high; /* Disturb whenever high-level monster moves */
+extern bool disturb_near; /* Disturb whenever viewable monster moves */
+extern bool disturb_pets; /* Disturb when visible pets move */
+extern bool disturb_panel; /* Disturb whenever map panel changes */
+extern bool disturb_state; /* Disturb whenever player state changes */
+extern bool disturb_minor; /* Disturb whenever boring things happen */
+extern bool ring_bell; /* Audible bell (on errors, etc) */
+extern bool disturb_trap_detect; /* Disturb when leaving trap detected area */
+extern bool alert_trap_detect; /* Alert when leaving trap detected area */
+
+
+ /*** Birth Options ***/
+
+extern bool manual_haggle; /* Manually haggle in stores */
+extern bool easy_band; /* Easy Mode (*) */
+extern bool smart_learn; /* Monsters learn from their mistakes (*) */
+extern bool smart_cheat; /* Monsters exploit players weaknesses (*) */
+extern bool vanilla_town; /* Use 'vanilla' town without quests and wilderness */
+extern bool lite_town; /* Use 'lite' town without a wilderness */
+extern bool ironman_shops; /* Stores are permanently closed (*) */
+extern bool ironman_small_levels; /* Always create unusually small dungeon levels (*) */
+extern bool ironman_downward; /* Disable recall and use of up stairs (*) */
+extern bool ironman_empty_levels; /* Always create empty 'arena' levels (*) */
+extern bool ironman_rooms; /* Always generate very unusual rooms (*) */
+extern bool ironman_nightmare; /* Nightmare mode(it isn't even remotely fair!)(*) */
+extern bool left_hander; /* Left-Hander */
+extern bool preserve_mode; /* Preserve artifacts (*) */
+extern bool autoroller; /* Allow use of autoroller for stats (*) */
+extern bool autochara; /* Autoroll for weight, height and social status */
+extern bool powerup_home; /* Increase capacity of your home (*) */
+
+
+ /*** Easy Object Auto-Destroyer ***/
+
+extern bool destroy_items; /* Use easy auto-destroyer */
+extern bool destroy_feeling; /* Apply auto-destroy as sense feeling */
+extern bool destroy_identify; /* Apply auto-destroy as identify an item */
+extern bool leave_worth; /* Auto-destroyer leaves known worthy items */
+extern bool leave_equip; /* Auto-destroyer leaves weapons and armour */
+extern bool leave_chest; /* Auto-destroyer leaves closed chests */
+extern bool leave_wanted; /* Auto-destroyer leaves wanted corpses */
+extern bool leave_corpse; /* Auto-destroyer leaves corpses and skeletons */
+extern bool leave_junk; /* Auto-destroyer leaves junk */
+extern bool leave_special; /* Auto-destroyer leaves items your race/class needs */
+
+
+ /*** Play-record Options ***/
+
+extern bool record_fix_art; /* Record fixed artifacts */
+extern bool record_rand_art; /* Record random artifacts */
+extern bool record_destroy_uniq; /* Record when destroy unique monster */
+extern bool record_fix_quest; /* Record fixed quests */
+extern bool record_rand_quest; /* Record random quests */
+extern bool record_maxdepth; /* Record movements to deepest level */
+extern bool record_stair; /* Record recall and stair movements */
+extern bool record_buy; /* Record purchased items */
+extern bool record_sell; /* Record sold items */
+extern bool record_danger; /* Record hitpoint warning */
+extern bool record_arena; /* Record arena victories */
+extern bool record_ident; /* Record first identified items */
+extern bool record_named_pet; /* Record informations of named pets */
+
+
+extern bool cheat_peek;
+extern bool cheat_hear;
+extern bool cheat_room;
+extern bool cheat_xtra;
+extern bool cheat_know;
+extern bool cheat_live;
+extern bool cheat_save;
+extern bool cheat_diary_output;
+extern bool cheat_turn;
+extern bool cheat_sight;
+
+extern byte hitpoint_warn;
+extern byte mana_warn;
+extern byte delay_factor;
+extern s16b autosave_freq;
+extern bool autosave_t;
+extern bool autosave_l;
-\r
-/*!\r
-* @brief ベースアイテム生成階層が加算される確率\r
-* @details\r
-* There is a 1/10 (10%) chance of inflating the requested object_level\r
-* during the creation of an object (see "get_obj_num()" in "object.c").\r
-* Lower values yield better objects more often.\r
-*/\r
-#define GREAT_OBJ 10\r
-\r
-/*!\r
-* @brief 深層モンスターが生成される(NASTY生成)の基本確率(1/x)\r
-* @details\r
-* There is a 1/25 (4%) chance of inflating the requested monster_level\r
-* during the creation of a monsters (see "get_mon_num()" in "monster.c").\r
-* Lower values yield harder monsters more often.\r
-*/\r
-#define NASTY_MON_BASE 25\r
-#define NASTY_MON_MAX 3 /*!< 深層モンスターが1フロアに生成される最大数 */\r
-#define NASTY_MON_PLUS_MAX 25 /*!< 深層モンスターの階層加算最大量 */\r
-\r
-#define PENETRATE_INVULNERABILITY 13 /*!< 無敵化が破られる確率(1/x) / 1/x chance of hurting even if invulnerable! */\r
-\r
-#define MAX_TELEPORT_DISTANCE 200 /*!< テレポート最大距離 */\r
-\r
-/*\r
-* Refueling constants\r
-*/\r
-#define FUEL_TORCH 5000 /*!< 松明の基本寿命値 / Maximum amount of fuel in a torch */\r
-#define FUEL_LAMP 15000 /*!< ランタンの基本寿命値 / Maximum amount of fuel in a lantern */\r
-\r
-/*\r
-* More maximum values\r
-*/\r
-#define MAX_SIGHT 20 /*!< プレイヤーの最大視界範囲(マス) / Maximum view distance */\r
-#define MAX_RANGE (p_ptr->inside_battle ? 36 : 18) /*!< プレイヤーの攻撃射程(マス) / Maximum range (spells, etc) */\r
-#define AAF_LIMIT 100 /*!< モンスターの限界感知範囲(マス) Limit of sensing radius */\r
-\r
-#define MIN_M_ALLOC_TD 4 /*!< 街(昼間)の最低住人配置数 / The town starts out with 4 residents during the day */\r
-#define MIN_M_ALLOC_TN 8 /*!< 街(夜間)の最低住人配置数 / The town starts out with 8 residents during the night */\r
-\r
-/*!\r
-* @brief モンスター増殖の最大数\r
-* @details\r
-* A monster can only "multiply" (reproduce) if there are fewer than 100\r
-* monsters on the level capable of such spontaneous reproduction. This\r
-* is a hack which prevents the "m_list[]" array from exploding due to\r
-* reproducing monsters. Messy, but necessary.\r
-*/\r
-#define MAX_REPRO 100\r
-\r
-#define MAX_VAMPIRIC_DRAIN 50 /*!< 吸血処理の最大回復HP */\r
-\r
-/*\r
-* Dungeon generation values\r
-*/\r
-#define DUN_UNUSUAL 250 /*!< 通常ではない部屋が生成される基本確率(レベル/定数) / Level/chance of unusual room (was 200) */\r
-#define DUN_DEST 18 /*!< 破壊地形がフロアに発生する基本確率(1/定数) / 1/chance of having a destroyed level */\r
-#define SMALL_LEVEL 3 /*!< 小さいフロアの生成される基本確率(1/定数) / 1/chance of smaller size (3) */\r
-#define EMPTY_LEVEL 24 /*!< アリーナレベル(外壁のないフロア)の生成される基本確率(1/定数) / 1/chance of being 'empty' (15) */\r
-#define LAKE_LEVEL 24 /*!< 川や湖のあるフロアの生成される確率(1/定数) / 1/chance of being a lake on the level */\r
-#define DARK_EMPTY 5 /*!< フロア全体が暗い可能性の基本確率(1/定数) / 1/chance of arena level NOT being lit (2) */\r
-#define DUN_CAVERN 20 /*!< 洞窟状のダンジョンが生成される基本確率(1/定数) / 1/chance of having a cavern level */\r
-\r
-/*\r
- * Dungeon tunnel generation values\r
- */\r
-#define DUN_TUN_RND_MIN 5 /* Chance of random direction (was 10) */\r
-#define DUN_TUN_RND_MAX 20\r
-#define DUN_TUN_CHG_MIN 20 /* Chance of changing direction (was 30) */\r
-#define DUN_TUN_CHG_MAX 60\r
-#define DUN_TUN_CON_MIN 10 /* Chance of extra tunneling (was 15) */\r
-#define DUN_TUN_CON_MAX 40\r
-#define DUN_TUN_PEN_MIN 30 /* Chance of doors at room entrances (was 25) */\r
-#define DUN_TUN_PEN_MAX 70\r
-#define DUN_TUN_JCT_MIN 60 /* Chance of doors at tunnel junctions (was 90) */\r
-#define DUN_TUN_JCT_MAX 90\r
-\r
-/*\r
- * Dungeon streamer generation values\r
- */\r
-#define DUN_STR_DEN 5 /* Density of streamers */\r
-#define DUN_STR_RNG 5 /* Width of streamers */\r
-#define DUN_STR_MAG 6 /* Number of magma streamers */\r
-#define DUN_STR_MC 30 /* 1/chance of treasure per magma */\r
-#define DUN_STR_QUA 4 /* Number of quartz streamers */\r
-#define DUN_STR_QC 15 /* 1/chance of treasure per quartz */\r
-#define DUN_STR_WLW 1 /* Width of lava & water streamers -KMW- */\r
-#define DUN_STR_DWLW 8 /* Density of water & lava streams -KMW- */\r
-\r
-#define DUN_MOS_DEN 2 /* Density of moss streamers */\r
-#define DUN_MOS_RNG 10 /* Width of moss streamers */\r
-#define DUN_STR_MOS 2 /* Number of moss streamers */\r
-#define DUN_WAT_DEN 15 /* Density of rivers */\r
-#define DUN_WAT_RNG 2 /* Width of rivers */\r
-#define DUN_STR_WAT 3 /* Max number of rivers */\r
-#define DUN_WAT_CHG 50 /* 1 in 50 chance of junction in river */\r
-\r
-/*\r
- * Dungeon treausre allocation values\r
- */\r
-#define DUN_AMT_ROOM 9 /* Amount of objects for rooms */\r
-#define DUN_AMT_ITEM 3 /* Amount of objects for rooms/corridors */\r
-#define DUN_AMT_GOLD 3 /* Amount of treasure for rooms/corridors */\r
-#define DUN_AMT_INVIS 3 /* Amount of invisible walls for rooms/corridors */\r
-\r
- /* Chance of using syllables to form the name instead of the "template" files */\r
-#define SINDARIN_NAME 10 /*!< ランダムアーティファクトにシンダリン銘をつける確率 */\r
-#define TABLE_NAME 20 /*!< ランダムアーティファクトに漢字銘をつける確率(正確には TABLE_NAME - SINDARIN_NAME %)となる */\r
-#define A_CURSED 13 /*!< 1/nの確率で生成の巻物以外のランダムアーティファクトが呪いつきになる。 */\r
-#define WEIRD_LUCK 12 /*!< 1/nの確率でrandom_resistance()の処理中バイアス外の耐性がつき、create_artifactで4を超えるpvalが許可される。*/\r
-#define SWORDFISH_LUCK 6 /*!< 1/nの確率で一定以上のスレイダメージを超える武器のスレイ喪失が回避される。 */\r
-#define BIAS_LUCK 20 /*!< 1/nの確率でrandom_resistance()で付加する元素耐性が免疫になる */\r
-#define IM_LUCK 7 /*!< 1/nの確率でrandom_resistance()で複数免疫の除去処理が免除される */\r
-\r
- /*! @note\r
- * Bias luck needs to be higher than weird luck,\r
- * since it is usually tested several times...\r
- */\r
-\r
-#define ACTIVATION_CHANCE 3 /*!< 1/nの確率でランダムアーティファクトに発動が付加される。ただし防具はさらに1/2 */\r
-\r
-#define TY_CURSE_CHANCE 200 /*!<太古の怨念の1ターン毎の発動確率(1/n)*/\r
-#define CHAINSWORD_NOISE 100 /*!<チェンソーの1ターン毎の発動確率(1/n)*/\r
-\r
-#define SPEAK_CHANCE 8\r
-#define GRINDNOISE 20\r
-#define CYBERNOISE 20\r
-\r
-#define GROUP_MAX 32 /*!< place_monster_group() 関数によるモンスターのGROUP生成時の配置最大数 / Maximum size of a group of monsters */\r
-\r
- /* ToDo: Make this global */\r
-#define HURT_CHANCE 16 /*!< 属性攻撃を受けた際に能力値低下を起こす確率(1/X) / 1/x chance of reducing stats (for elemental attacks) */\r
+
+/*!
+* @brief ベースアイテム生成階層が加算される確率
+* @details
+* There is a 1/10 (10%) chance of inflating the requested object_level
+* during the creation of an object (see "get_obj_num()" in "object.c").
+* Lower values yield better objects more often.
+*/
+#define GREAT_OBJ 10
+
+/*!
+* @brief 深層モンスターが生成される(NASTY生成)の基本確率(1/x)
+* @details
+* There is a 1/25 (4%) chance of inflating the requested monster_level
+* during the creation of a monsters (see "get_mon_num()" in "monster.c").
+* Lower values yield harder monsters more often.
+*/
+#define NASTY_MON_BASE 25
+#define NASTY_MON_MAX 3 /*!< 深層モンスターが1フロアに生成される最大数 */
+#define NASTY_MON_PLUS_MAX 25 /*!< 深層モンスターの階層加算最大量 */
+
+#define PENETRATE_INVULNERABILITY 13 /*!< 無敵化が破られる確率(1/x) / 1/x chance of hurting even if invulnerable! */
+
+#define MAX_TELEPORT_DISTANCE 200 /*!< テレポート最大距離 */
+
+/*
+* Refueling constants
+*/
+#define FUEL_TORCH 5000 /*!< 松明の基本寿命値 / Maximum amount of fuel in a torch */
+#define FUEL_LAMP 15000 /*!< ランタンの基本寿命値 / Maximum amount of fuel in a lantern */
+
+/*
+* More maximum values
+*/
+#define MAX_SIGHT 20 /*!< プレイヤーの最大視界範囲(マス) / Maximum view distance */
+#define MAX_RANGE (p_ptr->inside_battle ? 36 : 18) /*!< プレイヤーの攻撃射程(マス) / Maximum range (spells, etc) */
+#define AAF_LIMIT 100 /*!< モンスターの限界感知範囲(マス) Limit of sensing radius */
+
+#define MIN_M_ALLOC_TD 4 /*!< 街(昼間)の最低住人配置数 / The town starts out with 4 residents during the day */
+#define MIN_M_ALLOC_TN 8 /*!< 街(夜間)の最低住人配置数 / The town starts out with 8 residents during the night */
+
+/*!
+* @brief モンスター増殖の最大数
+* @details
+* A monster can only "multiply" (reproduce) if there are fewer than 100
+* monsters on the level capable of such spontaneous reproduction. This
+* is a hack which prevents the "m_list[]" array from exploding due to
+* reproducing monsters. Messy, but necessary.
+*/
+#define MAX_REPRO 100
+
+#define MAX_VAMPIRIC_DRAIN 50 /*!< 吸血処理の最大回復HP */
+
+/*
+* Dungeon generation values
+*/
+#define DUN_UNUSUAL 250 /*!< 通常ではない部屋が生成される基本確率(レベル/定数) / Level/chance of unusual room (was 200) */
+#define DUN_DEST 18 /*!< 破壊地形がフロアに発生する基本確率(1/定数) / 1/chance of having a destroyed level */
+#define SMALL_LEVEL 3 /*!< 小さいフロアの生成される基本確率(1/定数) / 1/chance of smaller size (3) */
+#define EMPTY_LEVEL 24 /*!< アリーナレベル(外壁のないフロア)の生成される基本確率(1/定数) / 1/chance of being 'empty' (15) */
+#define LAKE_LEVEL 24 /*!< 川や湖のあるフロアの生成される確率(1/定数) / 1/chance of being a lake on the level */
+#define DARK_EMPTY 5 /*!< フロア全体が暗い可能性の基本確率(1/定数) / 1/chance of arena level NOT being lit (2) */
+#define DUN_CAVERN 20 /*!< 洞窟状のダンジョンが生成される基本確率(1/定数) / 1/chance of having a cavern level */
+
+/*
+ * Dungeon tunnel generation values
+ */
+#define DUN_TUN_RND_MIN 5 /* Chance of random direction (was 10) */
+#define DUN_TUN_RND_MAX 20
+#define DUN_TUN_CHG_MIN 20 /* Chance of changing direction (was 30) */
+#define DUN_TUN_CHG_MAX 60
+#define DUN_TUN_CON_MIN 10 /* Chance of extra tunneling (was 15) */
+#define DUN_TUN_CON_MAX 40
+#define DUN_TUN_PEN_MIN 30 /* Chance of doors at room entrances (was 25) */
+#define DUN_TUN_PEN_MAX 70
+#define DUN_TUN_JCT_MIN 60 /* Chance of doors at tunnel junctions (was 90) */
+#define DUN_TUN_JCT_MAX 90
+
+/*
+ * Dungeon streamer generation values
+ */
+#define DUN_STR_DEN 5 /* Density of streamers */
+#define DUN_STR_RNG 5 /* Width of streamers */
+#define DUN_STR_MAG 6 /* Number of magma streamers */
+#define DUN_STR_MC 30 /* 1/chance of treasure per magma */
+#define DUN_STR_QUA 4 /* Number of quartz streamers */
+#define DUN_STR_QC 15 /* 1/chance of treasure per quartz */
+#define DUN_STR_WLW 1 /* Width of lava & water streamers -KMW- */
+#define DUN_STR_DWLW 8 /* Density of water & lava streams -KMW- */
+
+#define DUN_MOS_DEN 2 /* Density of moss streamers */
+#define DUN_MOS_RNG 10 /* Width of moss streamers */
+#define DUN_STR_MOS 2 /* Number of moss streamers */
+#define DUN_WAT_DEN 15 /* Density of rivers */
+#define DUN_WAT_RNG 2 /* Width of rivers */
+#define DUN_STR_WAT 3 /* Max number of rivers */
+#define DUN_WAT_CHG 50 /* 1 in 50 chance of junction in river */
+
+/*
+ * Dungeon treausre allocation values
+ */
+#define DUN_AMT_ROOM 9 /* Amount of objects for rooms */
+#define DUN_AMT_ITEM 3 /* Amount of objects for rooms/corridors */
+#define DUN_AMT_GOLD 3 /* Amount of treasure for rooms/corridors */
+#define DUN_AMT_INVIS 3 /* Amount of invisible walls for rooms/corridors */
+
+ /* Chance of using syllables to form the name instead of the "template" files */
+#define SINDARIN_NAME 10 /*!< ランダムアーティファクトにシンダリン銘をつける確率 */
+#define TABLE_NAME 20 /*!< ランダムアーティファクトに漢字銘をつける確率(正確には TABLE_NAME - SINDARIN_NAME %)となる */
+#define A_CURSED 13 /*!< 1/nの確率で生成の巻物以外のランダムアーティファクトが呪いつきになる。 */
+#define WEIRD_LUCK 12 /*!< 1/nの確率でrandom_resistance()の処理中バイアス外の耐性がつき、create_artifactで4を超えるpvalが許可される。*/
+#define SWORDFISH_LUCK 6 /*!< 1/nの確率で一定以上のスレイダメージを超える武器のスレイ喪失が回避される。 */
+#define BIAS_LUCK 20 /*!< 1/nの確率でrandom_resistance()で付加する元素耐性が免疫になる */
+#define IM_LUCK 7 /*!< 1/nの確率でrandom_resistance()で複数免疫の除去処理が免除される */
+
+ /*! @note
+ * Bias luck needs to be higher than weird luck,
+ * since it is usually tested several times...
+ */
+
+#define ACTIVATION_CHANCE 3 /*!< 1/nの確率でランダムアーティファクトに発動が付加される。ただし防具はさらに1/2 */
+
+#define TY_CURSE_CHANCE 200 /*!<太古の怨念の1ターン毎の発動確率(1/n)*/
+#define CHAINSWORD_NOISE 100 /*!<チェンソーの1ターン毎の発動確率(1/n)*/
+
+#define SPEAK_CHANCE 8
+#define GRINDNOISE 20
+#define CYBERNOISE 20
+
+#define GROUP_MAX 32 /*!< place_monster_group() 関数によるモンスターのGROUP生成時の配置最大数 / Maximum size of a group of monsters */
+
+ /* ToDo: Make this global */
+#define HURT_CHANCE 16 /*!< 属性攻撃を受けた際に能力値低下を起こす確率(1/X) / 1/x chance of reducing stats (for elemental attacks) */
-\r
-/*!\r
-* 生い立ちメッセージテーブル / Forward declare\r
-*/\r
-typedef struct hist_type hist_type;\r
-\r
-/*!\r
-* 生い立ちメッセージテーブルの構造体定義 / Player background information\r
-*/\r
-struct hist_type\r
-{\r
- concptr info; /*!> メッセージ本文 / Textual History */\r
-\r
- byte roll; /*!> 確率の重み / Frequency of this entry */\r
- byte chart; /*!> 生い立ちメッセージの流れを示すチャートID / Chart index */\r
- byte next; /*!> 次のチャートID */\r
- byte bonus; /*!> メッセージに伴う社会的地位の変化量(50が基準値) / Social Class Bonus + 50 */\r
-};\r
-\r
-struct hist_type;\r
-extern hist_type bg[];\r
+
+/*!
+* 生い立ちメッセージテーブル / Forward declare
+*/
+typedef struct hist_type hist_type;
+
+/*!
+* 生い立ちメッセージテーブルの構造体定義 / Player background information
+*/
+struct hist_type
+{
+ concptr info; /*!> メッセージ本文 / Textual History */
+
+ byte roll; /*!> 確率の重み / Frequency of this entry */
+ byte chart; /*!> 生い立ちメッセージの流れを示すチャートID / Chart index */
+ byte next; /*!> 次のチャートID */
+ byte bonus; /*!> メッセージに伴う社会的地位の変化量(50が基準値) / Social Class Bonus + 50 */
+};
+
+struct hist_type;
+extern hist_type bg[];
-/*!\r
-* @file main-win.c\r
-* @brief Windows版固有実装(メインエントリポイント含む)\r
-* @date 2018/03/16\r
-* @author Hengband Team\r
-* @detail\r
-*\r
-* <h3>概要</h3>\r
-* Windows98かその前後の頃を起点としたAPI実装。\r
-* 各種のゲームエンジンは無論、\r
-* DirectXといった昨今描画に標準的となったライブラリも用いていない。\r
-* タイルの描画処理などについては、現在動作の詳細を検証中。\r
-*\r
-* <h3>フォーク元の概要</h3>\r
-* <p>\r
-* Copyright (c) 1997 Ben Harrison, Skirmantas Kligys, and others\r
-*\r
-* This software may be copied and distributed for educational, research,\r
-* and not for profit purposes provided that this copyright and statement\r
-* are included in all such copies.\r
-* </p>\r
-* <p>\r
-* This file helps Angband work with Windows computers.\r
-*\r
-* To use this file, use an appropriate "Makefile" or "Project File",\r
-* make sure that "WINDOWS" and/or "WIN32" are defined somewhere, and\r
-* make sure to obtain various extra files as described below.\r
-*\r
-* The official compilation uses the CodeWarrior Pro compiler, which\r
-* includes a special project file and precompilable header file.\r
-* </p>\r
-*\r
-* <p>\r
-* <del>See also "main-dos.c" and "main-ibm.c".</del>\r
-* </p>\r
-*\r
-* <p>\r
-* The "lib/user/pref-win.prf" file contains keymaps, macro definitions,\r
-* and/or color redefinitions.\r
-* </p>\r
-*\r
-* <p>\r
-* The "lib/user/font-win.prf" contains attr/char mappings for use with the\r
-* normal "lib/xtra/font/*.fon" font files.\r
-* </p>\r
-*\r
-* <p>\r
-* The "lib/user/graf-win.prf" contains attr/char mappings for use with the\r
-* special "lib/xtra/graf/*.bmp" bitmap files, which are activated by a menu\r
-* item.\r
-* </p>\r
-*\r
-* <p>\r
-* Compiling this file, and using the resulting executable, requires\r
-* several extra files not distributed with the standard Angband code.\r
-* If "USE_GRAPHICS" is defined, then "readdib.h" and "readdib.c" must\r
-* be placed into "src/", and the "8X8.BMP" bitmap file must be placed\r
-* into "lib/xtra/graf". In any case, some "*.fon" files (including\r
-* "8X13.FON" if nothing else) must be placed into "lib/xtra/font/".\r
-* If "USE_SOUND" is defined, then some special library (for example,\r
-* "winmm.lib") may need to be linked in, and desired "*.WAV" sound\r
-* files must be placed into "lib/xtra/sound/". All of these extra\r
-* files can be found in the "ext-win" archive.\r
-* </p>\r
-*\r
-* <p>\r
-* The "Term_xtra_win_clear()" function should probably do a low-level\r
-* clear of the current window, and redraw the borders and other things,\r
-* if only for efficiency. \r
-* </p>\r
-*\r
-* <p>\r
-* A simpler method is needed for selecting the "tile size" for windows.\r
-* </p>\r
-*\r
-* <p>\r
-* The various "warning" messages assume the existance of the "screen.w"\r
-* window, I think, and only a few calls actually check for its existance,\r
-* this may be okay since "NULL" means "on top of all windows". (?) The\r
-* user must never be allowed to "hide" the main window, or the "menubar"\r
-* will disappear. \r
-* </p>\r
-*\r
-* <p>\r
-* Special "Windows Help Files" can be placed into "lib/xtra/help/" for\r
-* use with the "winhelp.exe" program. These files *may* be available\r
-* at the ftp site somewhere, but I have not seen them. \r
-* </p>\r
-*\r
-* <p>\r
-* Initial framework (and most code) by Ben Harrison (benh@phial.com).\r
-*\r
-* Original code by Skirmantas Kligys (kligys@scf.usc.edu).\r
-*\r
-* Additional code by Ross E Becker (beckerr@cis.ohio-state.edu),\r
-* and Chris R. Martin (crm7479@tam2000.tamu.edu).\r
-* </p>\r
-*/\r
-\r
-#include "angband.h"\r
-\r
-#ifdef WINDOWS\r
-#include <windows.h>\r
-#include <direct.h>\r
-#include <locale.h>\r
-#include "z-term.h"\r
-\r
-/*\r
- * Extract the "WIN32" flag from the compiler\r
- */\r
-#if defined(__WIN32__) || defined(__WINNT__) || defined(__NT__)\r
-# ifndef WIN32\r
-# define WIN32\r
-# endif\r
-#endif\r
-\r
-\r
-/*\r
- * Hack -- allow use of "screen saver" mode\r
- */\r
-#define USE_SAVER\r
-\r
-\r
-/*\r
- * Menu constants -- see "ANGBAND.RC"\r
- */\r
-\r
-#define IDM_FILE_NEW 100\r
-#define IDM_FILE_OPEN 101\r
-#define IDM_FILE_SAVE 110\r
-#define IDM_FILE_SCORE 120\r
-#define IDM_FILE_MOVIE 121\r
-#define IDM_FILE_EXIT 130\r
-\r
-#define IDM_WINDOW_VIS_0 200\r
-#define IDM_WINDOW_VIS_1 201\r
-#define IDM_WINDOW_VIS_2 202\r
-#define IDM_WINDOW_VIS_3 203\r
-#define IDM_WINDOW_VIS_4 204\r
-#define IDM_WINDOW_VIS_5 205\r
-#define IDM_WINDOW_VIS_6 206\r
-#define IDM_WINDOW_VIS_7 207\r
-\r
-#define IDM_WINDOW_FONT_0 210\r
-#define IDM_WINDOW_FONT_1 211\r
-#define IDM_WINDOW_FONT_2 212\r
-#define IDM_WINDOW_FONT_3 213\r
-#define IDM_WINDOW_FONT_4 214\r
-#define IDM_WINDOW_FONT_5 215\r
-#define IDM_WINDOW_FONT_6 216\r
-#define IDM_WINDOW_FONT_7 217\r
-\r
-#define IDM_WINDOW_POS_0 220\r
-#define IDM_WINDOW_POS_1 221\r
-#define IDM_WINDOW_POS_2 222\r
-#define IDM_WINDOW_POS_3 223\r
-#define IDM_WINDOW_POS_4 224\r
-#define IDM_WINDOW_POS_5 225\r
-#define IDM_WINDOW_POS_6 226\r
-#define IDM_WINDOW_POS_7 227\r
-\r
-#define IDM_WINDOW_BIZ_0 230\r
-#define IDM_WINDOW_BIZ_1 231\r
-#define IDM_WINDOW_BIZ_2 232\r
-#define IDM_WINDOW_BIZ_3 233\r
-#define IDM_WINDOW_BIZ_4 234\r
-#define IDM_WINDOW_BIZ_5 235\r
-#define IDM_WINDOW_BIZ_6 236\r
-#define IDM_WINDOW_BIZ_7 237\r
-\r
-#define IDM_WINDOW_I_WID_0 240\r
-#define IDM_WINDOW_I_WID_1 241\r
-#define IDM_WINDOW_I_WID_2 242\r
-#define IDM_WINDOW_I_WID_3 243\r
-#define IDM_WINDOW_I_WID_4 244\r
-#define IDM_WINDOW_I_WID_5 245\r
-#define IDM_WINDOW_I_WID_6 246\r
-#define IDM_WINDOW_I_WID_7 247\r
-\r
-#define IDM_WINDOW_D_WID_0 250\r
-#define IDM_WINDOW_D_WID_1 251\r
-#define IDM_WINDOW_D_WID_2 252\r
-#define IDM_WINDOW_D_WID_3 253\r
-#define IDM_WINDOW_D_WID_4 254\r
-#define IDM_WINDOW_D_WID_5 255\r
-#define IDM_WINDOW_D_WID_6 256\r
-#define IDM_WINDOW_D_WID_7 257\r
-\r
-#define IDM_WINDOW_I_HGT_0 260\r
-#define IDM_WINDOW_I_HGT_1 261\r
-#define IDM_WINDOW_I_HGT_2 262\r
-#define IDM_WINDOW_I_HGT_3 263\r
-#define IDM_WINDOW_I_HGT_4 264\r
-#define IDM_WINDOW_I_HGT_5 265\r
-#define IDM_WINDOW_I_HGT_6 266\r
-#define IDM_WINDOW_I_HGT_7 267\r
-\r
-#define IDM_WINDOW_D_HGT_0 270\r
-#define IDM_WINDOW_D_HGT_1 271\r
-#define IDM_WINDOW_D_HGT_2 272\r
-#define IDM_WINDOW_D_HGT_3 273\r
-#define IDM_WINDOW_D_HGT_4 274\r
-#define IDM_WINDOW_D_HGT_5 275\r
-#define IDM_WINDOW_D_HGT_6 276\r
-#define IDM_WINDOW_D_HGT_7 277\r
-\r
-#define IDM_OPTIONS_NO_GRAPHICS 400\r
-#define IDM_OPTIONS_OLD_GRAPHICS 401\r
-#define IDM_OPTIONS_NEW_GRAPHICS 402\r
-#define IDM_OPTIONS_NEW2_GRAPHICS 403\r
-#define IDM_OPTIONS_BIGTILE 409\r
-#define IDM_OPTIONS_SOUND 410\r
-#define IDM_OPTIONS_MUSIC 411\r
-#define IDM_OPTIONS_SAVER 420\r
-#define IDM_OPTIONS_MAP 430\r
-#define IDM_OPTIONS_BG 440\r
-#define IDM_OPTIONS_OPEN_BG 441\r
-\r
-#define IDM_DUMP_SCREEN_HTML 450\r
-\r
-#define IDM_HELP_CONTENTS 901\r
-\r
-/*\r
- * Exclude parts of WINDOWS.H that are not needed\r
- */\r
-#define NOCOMM /* Comm driver APIs and definitions */\r
-#define NOLOGERROR /* LogError() and related definitions */\r
-#define NOPROFILER /* Profiler APIs */\r
-#define NOLFILEIO /* _l* file I/O routines */\r
-#define NOOPENFILE /* OpenFile and related definitions */\r
-#define NORESOURCE /* Resource management */\r
-#define NOATOM /* Atom management */\r
-#define NOLANGUAGE /* Character test routines */\r
-#define NOLSTRING /* lstr* string management routines */\r
-#define NODBCS /* Double-byte character set routines */\r
-#define NOKEYBOARDINFO /* Keyboard driver routines */\r
-#define NOCOLOR /* COLOR_* color values */\r
-#define NODRAWTEXT /* DrawText() and related definitions */\r
-#define NOSCALABLEFONT /* Truetype scalable font support */\r
-#define NOMETAFILE /* Metafile support */\r
-#define NOSYSTEMPARAMSINFO /* SystemParametersInfo() and SPI_* definitions */\r
-#define NODEFERWINDOWPOS /* DeferWindowPos and related definitions */\r
-#define NOKEYSTATES /* MK_* message key state flags */\r
-#define NOWH /* SetWindowsHook and related WH_* definitions */\r
-#define NOCLIPBOARD /* Clipboard APIs and definitions */\r
-#define NOICONS /* IDI_* icon IDs */\r
-#define NOMDI /* MDI support */\r
-#define NOHELP /* Help support */\r
-\r
-/* Not defined since it breaks Borland C++ 5.5 */\r
-/* #define NOCTLMGR */ /* Control management and controls */\r
-\r
-/*\r
- * Exclude parts of WINDOWS.H that are not needed (Win32)\r
- */\r
-#define WIN32_LEAN_AND_MEAN\r
-#define NONLS /* All NLS defines and routines */\r
-#define NOSERVICE /* All Service Controller routines, SERVICE_ equates, etc. */\r
-#define NOKANJI /* Kanji support stuff. */\r
-#define NOMCX /* Modem Configuration Extensions */\r
-\r
-/*\r
- * Include the "windows" support file\r
- */\r
-#include <windows.h>\r
-\r
-/*\r
- * Exclude parts of MMSYSTEM.H that are not needed\r
- */\r
-#define MMNODRV /* Installable driver support */\r
-#define MMNOWAVE /* Waveform support */\r
-#define MMNOMIDI /* MIDI support */\r
-#define MMNOAUX /* Auxiliary audio support */\r
-#define MMNOTIMER /* Timer support */\r
-#define MMNOJOY /* Joystick support */\r
-#define MMNOMCI /* MCI support */\r
-#define MMNOMMIO /* Multimedia file I/O support */\r
-#define MMNOMMSYSTEM /* General MMSYSTEM functions */\r
-\r
-/*\r
- * Include some more files. Note: the Cygnus Cygwin compiler\r
- * doesn't use mmsystem.h instead it includes the winmm library\r
- * which performs a similar function.\r
- */\r
-#include <mmsystem.h>\r
-#include <commdlg.h>\r
-\r
-/*\r
- * HTML-Help requires htmlhelp.h and htmlhelp.lib from Microsoft's\r
- * HTML Workshop < http://msdn.microsoft.com/workshop/author/htmlhelp/ >.\r
- */\r
-/* #define HTML_HELP */\r
-\r
-#ifdef HTML_HELP\r
-#include <htmlhelp.h>\r
-#endif /* HTML_HELP */\r
-\r
-/*\r
- * Include the support for loading bitmaps\r
- */\r
-#ifdef USE_GRAPHICS\r
-# include "readdib.h"\r
-#endif\r
-\r
-/*\r
- * Hack -- Fake declarations from "dos.h" \r
- */\r
-#ifdef WIN32\r
-#define INVALID_FILE_NAME (DWORD)0xFFFFFFFF\r
-#else /* WIN32 */\r
-#define FA_LABEL 0x08 /* Volume label */\r
-#define FA_DIREC 0x10 /* Directory */\r
-unsigned _cdecl _dos_getfileattr(concptr , unsigned *);\r
-#endif /* WIN32 */\r
-\r
-/*\r
- * Silliness in WIN32 drawing routine\r
- */\r
-#ifdef WIN32\r
-# define MoveTo(H,X,Y) MoveToEx(H, X, Y, NULL)\r
-#endif /* WIN32 */\r
-\r
-/*\r
- * Silliness for Windows 95\r
- */\r
-#ifndef WS_EX_TOOLWINDOW\r
-# define WS_EX_TOOLWINDOW 0\r
-#endif\r
-\r
-/*\r
- * Foreground color bits (hard-coded by DOS)\r
- */\r
-#define VID_BLACK 0x00\r
-#define VID_BLUE 0x01\r
-#define VID_GREEN 0x02\r
-#define VID_CYAN 0x03\r
-#define VID_RED 0x04\r
-#define VID_MAGENTA 0x05\r
-#define VID_YELLOW 0x06\r
-#define VID_WHITE 0x07\r
-\r
-/*\r
- * Bright text (hard-coded by DOS)\r
- */\r
-#define VID_BRIGHT 0x08\r
-\r
-/*\r
- * Background color bits (hard-coded by DOS)\r
- */\r
-#define VUD_BLACK 0x00\r
-#define VUD_BLUE 0x10\r
-#define VUD_GREEN 0x20\r
-#define VUD_CYAN 0x30\r
-#define VUD_RED 0x40\r
-#define VUD_MAGENTA 0x50\r
-#define VUD_YELLOW 0x60\r
-#define VUD_WHITE 0x70\r
-\r
-/*\r
- * Blinking text (hard-coded by DOS)\r
- */\r
-#define VUD_BRIGHT 0x80\r
-\r
-\r
-/*\r
- * Forward declare\r
- */\r
-typedef struct _term_data term_data;\r
-\r
-/*!\r
- * @struct _term_data\r
- * @brief ターム情報構造体 / Extra "term" data\r
- * @details\r
- * <p>\r
- * pos_x / pos_y は各タームの左上点座標を指す。\r
- * </p>\r
- * <p>\r
- * tile_wid / tile_hgt は[ウィンドウ]メニューのタイルの幅/高さを~を\r
- * 1ドットずつ調整するステータスを指す。\r
- * また、フォントを変更すると都度自動調整される。\r
- * </p>\r
- * <p>\r
- * Note the use of "font_want" for the names of the font file requested by\r
- * the user, and the use of "font_file" for the currently active font file.\r
- *\r
- * The "font_file" is uppercased, and takes the form "8X13.FON", while\r
- * "font_want" can be in almost any form as long as it could be construed\r
- * as attempting to represent the name of a font.\r
- * </p>\r
- */\r
-struct _term_data\r
-{\r
- term t;\r
- concptr s;\r
- HWND w;\r
- DWORD dwStyle;\r
- DWORD dwExStyle;\r
-\r
- uint keys;\r
- TERM_LEN rows; /* int -> uint */\r
- TERM_LEN cols;\r
-\r
- uint pos_x; //!< タームの左上X座標\r
- uint pos_y; //!< タームの左上Y座標\r
- uint size_wid;\r
- uint size_hgt;\r
- uint size_ow1;\r
- uint size_oh1;\r
- uint size_ow2;\r
- uint size_oh2;\r
-\r
- bool size_hack;\r
- bool xtra_hack;\r
- bool visible;\r
- bool bizarre;\r
- concptr font_want;\r
- concptr font_file;\r
- HFONT font_id;\r
- int font_wid; //!< フォント横幅\r
- int font_hgt; //!< フォント縦幅\r
- int tile_wid; //!< タイル横幅\r
- int tile_hgt; //!< タイル縦幅\r
-\r
- uint map_tile_wid;\r
- uint map_tile_hgt;\r
-\r
- bool map_active;\r
-#if 1 /* #ifdef JP */\r
- LOGFONT lf;\r
-#endif\r
-\r
- bool posfix;\r
-\r
-};\r
-\r
-#define MAX_TERM_DATA 8 //!< Maximum number of windows \r
-\r
-static term_data data[MAX_TERM_DATA]; //!< An array of term_data's\r
-static term_data *my_td; //!< Hack -- global "window creation" pointer\r
-POINT normsize; //!< Remember normal size of main window when maxmized\r
-\r
-/*\r
- * was main window maximized on previous playing\r
- */\r
-bool win_maximized = FALSE;\r
-\r
-/*\r
- * game in progress\r
- */\r
-bool game_in_progress = FALSE;\r
-\r
-/*\r
- * note when "open"/"new" become valid\r
- */\r
-bool initialized = FALSE;\r
-\r
-/*\r
- * screen paletted, i.e. 256 colors\r
- */\r
-bool paletted = FALSE;\r
-\r
-/*\r
- * 16 colors screen, don't use RGB()\r
- */\r
-bool colors16 = FALSE;\r
-\r
-/*\r
- * Saved instance handle\r
- */\r
-static HINSTANCE hInstance;\r
-\r
-/*\r
- * Yellow brush for the cursor\r
- */\r
-static HBRUSH hbrYellow;\r
-\r
-/*\r
- * An icon\r
- */\r
-static HICON hIcon;\r
-\r
-/*\r
- * A palette\r
- */\r
-static HPALETTE hPal;\r
-\r
-/* bg */\r
-static HBITMAP hBG = NULL;\r
-static int use_bg = 0; //!< 背景使用フラグ、1なら私用。\r
-static char bg_bitmap_file[1024] = "bg.bmp"; //!< 現在の背景ビットマップファイル名。\r
-\r
-#ifdef USE_SAVER\r
-\r
-/*\r
- * The screen saver window\r
- */\r
-static HWND hwndSaver;\r
-\r
-#endif /* USE_SAVER */\r
-\r
-\r
-#ifdef USE_GRAPHICS\r
-\r
-/*!\r
- * 現在使用中のタイルID(0ならば未使用)\r
- * Flag set once "graphics" has been initialized\r
- */\r
-static byte_hack current_graphics_mode = 0;\r
-\r
-/*\r
- * The global bitmap\r
- */\r
-static DIBINIT infGraph;\r
-\r
-/*\r
- * The global bitmap mask\r
- */\r
-static DIBINIT infMask;\r
-\r
-#endif /* USE_GRAPHICS */\r
-\r
-\r
-#ifdef USE_SOUND\r
-\r
-/*\r
- * Flag set once "sound" has been initialized\r
- */\r
-static bool can_use_sound = FALSE;\r
-\r
-#define SAMPLE_MAX 8\r
-/*\r
- * An array of sound file names\r
- */\r
-static concptr sound_file[SOUND_MAX][SAMPLE_MAX];\r
-\r
-#endif /* USE_SOUND */\r
-\r
-\r
-\r
-#ifdef USE_MUSIC\r
-\r
-#define SAMPLE_MUSIC_MAX 16\r
-static concptr music_file[MUSIC_BASIC_MAX][SAMPLE_MUSIC_MAX];\r
-static concptr dungeon_music_file[1000][SAMPLE_MUSIC_MAX];\r
-static concptr town_music_file[1000][SAMPLE_MUSIC_MAX];\r
-static concptr quest_music_file[1000][SAMPLE_MUSIC_MAX];\r
-static bool can_use_music = FALSE;\r
-\r
-static MCI_OPEN_PARMS mop;\r
-static char mci_device_type[256];\r
-\r
-int current_music_type = 0;\r
-int current_music_id = 0;\r
-\r
-#endif /* USE_MUSIC */\r
-\r
-\r
-/*\r
- * Full path to ANGBAND.INI\r
- */\r
-static concptr ini_file = NULL;\r
-\r
-/*\r
- * Name of application\r
- */\r
-static concptr AppName = "ANGBAND";\r
-\r
-/*\r
- * Name of sub-window type\r
- */\r
-static concptr AngList = "AngList";\r
-\r
-/*\r
- * Directory names\r
- */\r
-static concptr ANGBAND_DIR_XTRA_GRAF;\r
-static concptr ANGBAND_DIR_XTRA_SOUND;\r
-static concptr ANGBAND_DIR_XTRA_MUSIC;\r
-static concptr ANGBAND_DIR_XTRA_HELP;\r
-#if 0 /* #ifndef JP */\r
-static concptr ANGBAND_DIR_XTRA_FONT;\r
-#endif\r
-#ifdef USE_MUSIC\r
-static concptr ANGBAND_DIR_XTRA_MUSIC;\r
-#endif\r
-\r
-\r
-/*\r
- * The "complex" color values\r
- */\r
-static COLORREF win_clr[256];\r
-\r
-\r
-/*\r
- * Flag for macro trigger with dump ASCII\r
- */\r
-static bool Term_no_press = FALSE;\r
-\r
-/*\r
- * Copy and paste\r
- */\r
-static bool mouse_down = FALSE;\r
-static bool paint_rect = FALSE;\r
-static TERM_LEN mousex = 0, mousey = 0;\r
-static TERM_LEN oldx, oldy;\r
-\r
-\r
-/*!\r
- * @brief The "simple" color values\r
- * @details\r
- * See "main-ibm.c" for original table information\r
- * The entries below are taken from the "color bits" defined above.\r
- * Note that many of the choices below suck, but so do crappy monitors.\r
- */\r
-static BYTE win_pal[256] =\r
-{\r
- VID_BLACK, /* Dark */\r
- VID_WHITE, /* White */\r
- VID_CYAN, /* Slate XXX */\r
- VID_RED | VID_BRIGHT, /* Orange XXX */\r
- VID_RED, /* Red */\r
- VID_GREEN, /* Green */\r
- VID_BLUE, /* Blue */\r
- VID_YELLOW, /* Umber XXX */\r
- VID_BLACK | VID_BRIGHT, /* Light Dark */\r
- VID_CYAN | VID_BRIGHT, /* Light Slate XXX */\r
- VID_MAGENTA, /* Violet XXX */\r
- VID_YELLOW | VID_BRIGHT, /* Yellow */\r
- VID_MAGENTA | VID_BRIGHT, /* Light Red XXX */\r
- VID_GREEN | VID_BRIGHT, /* Light Green */\r
- VID_BLUE | VID_BRIGHT, /* Light Blue */\r
- VID_YELLOW /* Light Umber XXX */\r
-};\r
-\r
-\r
-/*\r
- * Hack -- define which keys are "special"\r
- */\r
-static bool special_key[256];\r
-static bool ignore_key[256];\r
-\r
-#if 1\r
-/*\r
- * Hack -- initialization list for "special_key"\r
- */\r
-static byte special_key_list[] = {\r
- VK_CLEAR, VK_PAUSE, VK_CAPITAL,\r
- VK_KANA, VK_JUNJA, VK_FINAL, VK_KANJI,\r
- VK_CONVERT, VK_NONCONVERT, VK_ACCEPT, VK_MODECHANGE,\r
- VK_PRIOR, VK_NEXT, VK_END, VK_HOME,\r
- VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN,\r
- VK_SELECT, VK_PRINT, VK_EXECUTE, VK_SNAPSHOT,\r
- VK_INSERT, VK_DELETE, VK_HELP, VK_APPS,\r
- VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3,\r
- VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7,\r
- VK_NUMPAD8, VK_NUMPAD9, VK_MULTIPLY, VK_ADD,\r
- VK_SEPARATOR, VK_SUBTRACT, VK_DECIMAL, VK_DIVIDE,\r
- VK_F1, VK_F2, VK_F3, VK_F4, VK_F5, VK_F6,\r
- VK_F7, VK_F8, VK_F9, VK_F10, VK_F11, VK_F12,\r
- VK_F13, VK_F14, VK_F15, VK_F16, VK_F17, VK_F18,\r
- VK_F19,VK_F20, VK_F21, VK_F22, VK_F23, VK_F24,\r
- VK_NUMLOCK, VK_SCROLL, VK_ATTN, VK_CRSEL,\r
- VK_EXSEL, VK_EREOF, VK_PLAY, VK_ZOOM,\r
- VK_NONAME, VK_PA1,\r
- 0 /* End of List */\r
-};\r
-\r
-static byte ignore_key_list[] = {\r
- VK_ESCAPE, VK_TAB, VK_SPACE,\r
- 'F', 'W', 'O', /*'H',*/ /* these are menu characters.*/\r
- VK_SHIFT, VK_CONTROL, VK_MENU, VK_LWIN, VK_RWIN,\r
- VK_LSHIFT, VK_RSHIFT, VK_LCONTROL, VK_RCONTROL,\r
- VK_LMENU, VK_RMENU,\r
- 0 /* End of List */\r
-};\r
-#else\r
-/*\r
- * Hack -- initialization list for "special_key"\r
- *\r
- * We ignore the modifier keys (shift, control, alt, num lock, scroll lock),\r
- * and the normal keys (escape, tab, return, letters, numbers, etc), but we\r
- * catch the keypad keys (with and without numlock set, including keypad 5),\r
- * the function keys (including the "menu" key which maps to F10), and the\r
- * "pause" key (between scroll lock and numlock). We also catch a few odd\r
- * keys which I do not recognize, but which are listed among keys which we\r
- * do catch, so they should be harmless to catch.\r
- */\r
-static byte special_key_list[] =\r
-{\r
- VK_CLEAR, /* 0x0C (KP<5>) */\r
-\r
- VK_PAUSE, /* 0x13 (pause) */\r
-\r
- VK_PRIOR, /* 0x21 (KP<9>) */\r
- VK_NEXT, /* 0x22 (KP<3>) */\r
- VK_END, /* 0x23 (KP<1>) */\r
- VK_HOME, /* 0x24 (KP<7>) */\r
- VK_LEFT, /* 0x25 (KP<4>) */\r
- VK_UP, /* 0x26 (KP<8>) */\r
- VK_RIGHT, /* 0x27 (KP<6>) */\r
- VK_DOWN, /* 0x28 (KP<2>) */\r
- VK_SELECT, /* 0x29 (?????) */\r
- VK_PRINT, /* 0x2A (?????) */\r
- VK_EXECUTE, /* 0x2B (?????) */\r
- VK_SNAPSHOT, /* 0x2C (?????) */\r
- VK_INSERT, /* 0x2D (KP<0>) */\r
- VK_DELETE, /* 0x2E (KP<.>) */\r
- VK_HELP, /* 0x2F (?????) */\r
-#if 0\r
- VK_NUMPAD0, /* 0x60 (KP<0>) */\r
- VK_NUMPAD1, /* 0x61 (KP<1>) */\r
- VK_NUMPAD2, /* 0x62 (KP<2>) */\r
- VK_NUMPAD3, /* 0x63 (KP<3>) */\r
- VK_NUMPAD4, /* 0x64 (KP<4>) */\r
- VK_NUMPAD5, /* 0x65 (KP<5>) */\r
- VK_NUMPAD6, /* 0x66 (KP<6>) */\r
- VK_NUMPAD7, /* 0x67 (KP<7>) */\r
- VK_NUMPAD8, /* 0x68 (KP<8>) */\r
- VK_NUMPAD9, /* 0x69 (KP<9>) */\r
- VK_MULTIPLY, /* 0x6A (KP<*>) */\r
- VK_ADD, /* 0x6B (KP<+>) */\r
- VK_SEPARATOR, /* 0x6C (?????) */\r
- VK_SUBTRACT, /* 0x6D (KP<->) */\r
- VK_DECIMAL, /* 0x6E (KP<.>) */\r
- VK_DIVIDE, /* 0x6F (KP</>) */\r
-#endif\r
- VK_F1, /* 0x70 */\r
- VK_F2, /* 0x71 */\r
- VK_F3, /* 0x72 */\r
- VK_F4, /* 0x73 */\r
- VK_F5, /* 0x74 */\r
- VK_F6, /* 0x75 */\r
- VK_F7, /* 0x76 */\r
- VK_F8, /* 0x77 */\r
- VK_F9, /* 0x78 */\r
- VK_F10, /* 0x79 */\r
- VK_F11, /* 0x7A */\r
- VK_F12, /* 0x7B */\r
- VK_F13, /* 0x7C */\r
- VK_F14, /* 0x7D */\r
- VK_F15, /* 0x7E */\r
- VK_F16, /* 0x7F */\r
- VK_F17, /* 0x80 */\r
- VK_F18, /* 0x81 */\r
- VK_F19, /* 0x82 */\r
- VK_F20, /* 0x83 */\r
- VK_F21, /* 0x84 */\r
- VK_F22, /* 0x85 */\r
- VK_F23, /* 0x86 */\r
- VK_F24, /* 0x87 */\r
- 0\r
-};\r
-#endif\r
-\r
-\r
-/* Function prototype */\r
-\r
-static bool is_already_running(void);\r
-\r
-\r
-/* bg */\r
-static void delete_bg(void)\r
-{\r
- if (hBG != NULL)\r
- {\r
- DeleteObject(hBG);\r
- hBG = NULL;\r
- }\r
-}\r
-\r
-static int init_bg(void)\r
-{\r
- char * bmfile = bg_bitmap_file;\r
-\r
- delete_bg();\r
- if (use_bg == 0) return 0;\r
-\r
- hBG = LoadImage(NULL, bmfile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);\r
- if (!hBG) {\r
- plog_fmt(_("壁紙用ビットマップ '%s' を読み込めません。", "Can't load the bitmap file '%s'."), bmfile);\r
- use_bg = 0;\r
- return 0;\r
- }\r
- use_bg = 1;\r
- return 1;\r
-}\r
-\r
-static void DrawBG(HDC hdc, RECT *r)\r
-{\r
- HDC hdcSrc;\r
- HBITMAP hOld;\r
- BITMAP bm;\r
- int x = r->left, y = r->top;\r
- int nx, ny, sx, sy, swid, shgt, cwid, chgt;\r
- \r
- if (!use_bg || !hBG)\r
- return;\r
-\r
- nx = x; ny = y;\r
- GetObject(hBG, sizeof(bm), &bm);\r
- swid = bm.bmWidth; shgt = bm.bmHeight;\r
-\r
- hdcSrc = CreateCompatibleDC(hdc);\r
- hOld = SelectObject(hdcSrc, hBG);\r
-\r
- do {\r
- sx = nx % swid;\r
- cwid = MIN(swid - sx, r->right - nx);\r
- do {\r
- sy = ny % shgt;\r
- chgt = MIN(shgt - sy, r->bottom - ny);\r
- BitBlt(hdc, nx, ny, cwid, chgt, hdcSrc, sx, sy, SRCCOPY);\r
- ny += chgt;\r
- } while (ny < r->bottom);\r
- ny = y;\r
- nx += cwid;\r
- } while (nx < r->right);\r
- \r
- SelectObject(hdcSrc, hOld);\r
- DeleteDC(hdcSrc);\r
-}\r
-\r
-#if 0\r
-/*\r
- * Hack -- given a pathname, point at the filename\r
- */\r
-static concptr extract_file_name(concptr s)\r
-{\r
- concptr p;\r
-\r
- /* Start at the end */\r
- p = s + strlen(s) - 1;\r
-\r
- /* Back up to divider */\r
- while ((p >= s) && (*p != ':') && (*p != '\\')) p--;\r
-\r
- /* Return file name */\r
- return (p+1);\r
-}\r
-#endif\r
-\r
-\r
-/*\r
- * Hack -- given a simple filename, extract the "font size" info\r
- *\r
- * Return a pointer to a static buffer holding the capitalized base name.\r
- */\r
-#if 0 /* #ifndef JP */\r
-static char *analyze_font(char *path, int *wp, int *hp)\r
-{\r
- int wid, hgt;\r
-\r
- char *s, *p;\r
-\r
- /* Start at the end */\r
- p = path + strlen(path) - 1;\r
-\r
- /* Back up to divider */\r
- while ((p >= path) && (*p != ':') && (*p != '\\')) --p;\r
-\r
- /* Advance to file name */\r
- ++p;\r
-\r
- /* Capitalize */\r
- for (s = p; *s; ++s)\r
- {\r
- /* Capitalize (be paranoid) */\r
- if (islower(*s)) *s = toupper(*s);\r
- }\r
-\r
- /* Find first 'X' */\r
- s = my_strchr(p, 'X');\r
-\r
- /* Extract font width */\r
- wid = atoi(p);\r
-\r
- /* Extract height */\r
- hgt = s ? atoi(s+1) : 0;\r
-\r
- /* Save results */\r
- (*wp) = wid;\r
- (*hp) = hgt;\r
- return (p);\r
-}\r
-#endif\r
-\r
-\r
-/*\r
- * Check for existance of a file\r
- */\r
-static bool check_file(concptr s)\r
-{\r
- char path[1024];\r
-\r
-#ifdef WIN32\r
-\r
- DWORD attrib;\r
-\r
-#else /* WIN32 */\r
-\r
- unsigned int attrib;\r
-\r
-#endif /* WIN32 */\r
-\r
- /* Copy it */\r
- strcpy(path, s);\r
-\r
-#ifdef WIN32\r
-\r
- /* Examine */\r
- attrib = GetFileAttributes(path);\r
-\r
- /* Require valid filename */\r
- if (attrib == INVALID_FILE_NAME) return (FALSE);\r
-\r
- /* Prohibit directory */\r
- if (attrib & FILE_ATTRIBUTE_DIRECTORY) return (FALSE);\r
-\r
-#else /* WIN32 */\r
-\r
- /* Examine and verify */\r
- if (_dos_getfileattr(path, &attrib)) return (FALSE);\r
-\r
- /* Prohibit something */\r
- if (attrib & FA_LABEL) return (FALSE);\r
-\r
- /* Prohibit directory */\r
- if (attrib & FA_DIREC) return (FALSE);\r
-\r
-#endif /* WIN32 */\r
-\r
- /* Success */\r
- return (TRUE);\r
-}\r
-\r
-\r
-/*\r
- * Check for existance of a directory\r
- */\r
-static bool check_dir(concptr s)\r
-{\r
- int i;\r
-\r
- char path[1024];\r
-\r
-#ifdef WIN32\r
-\r
- DWORD attrib;\r
-\r
-#else /* WIN32 */\r
-\r
- unsigned int attrib;\r
-\r
-#endif /* WIN32 */\r
-\r
- /* Copy it */\r
- strcpy(path, s);\r
-\r
- /* Check length */\r
- i = strlen(path);\r
-\r
- /* Remove trailing backslash */\r
- if (i && (path[i-1] == '\\')) path[--i] = '\0';\r
-\r
-#ifdef WIN32\r
-\r
- /* Examine */\r
- attrib = GetFileAttributes(path);\r
-\r
- /* Require valid filename */\r
- if (attrib == INVALID_FILE_NAME) return (FALSE);\r
-\r
- /* Require directory */\r
- if (!(attrib & FILE_ATTRIBUTE_DIRECTORY)) return (FALSE);\r
-\r
-#else /* WIN32 */\r
-\r
- /* Examine and verify */\r
- if (_dos_getfileattr(path, &attrib)) return (FALSE);\r
-\r
- /* Prohibit something */\r
- if (attrib & FA_LABEL) return (FALSE);\r
-\r
- /* Require directory */\r
- if (!(attrib & FA_DIREC)) return (FALSE);\r
-\r
-#endif /* WIN32 */\r
-\r
- /* Success */\r
- return (TRUE);\r
-}\r
-\r
-\r
-/*\r
- * Validate a file\r
- */\r
-static void validate_file(concptr s)\r
-{\r
- /* Verify or fail */\r
- if (!check_file(s))\r
- {\r
- quit_fmt(_("必要なファイル[%s]が見あたりません。", "Cannot find required file:\n%s"), s);\r
- }\r
-}\r
-\r
-\r
-/*\r
- * Validate a directory\r
- */\r
-static void validate_dir(concptr s, bool vital)\r
-{\r
- /* Verify or fail */\r
- if (!check_dir(s))\r
- {\r
- /* This directory contains needed data */\r
- if (vital)\r
- {\r
- quit_fmt(_("必要なディレクトリ[%s]が見あたりません。", "Cannot find required directory:\n%s"), s);\r
- }\r
- /* Attempt to create this directory */\r
- else if (mkdir(s))\r
- {\r
- quit_fmt("Unable to create directory:\n%s", s);\r
- }\r
- }\r
-}\r
-\r
-\r
-/*!\r
- * @brief (Windows版固有実装)Get the "size" for a window\r
- */\r
-static void term_getsize(term_data *td)\r
-{\r
- RECT rc;\r
- TERM_LEN wid, hgt;\r
-\r
- /* Paranoia */\r
- if (td->cols < 1) td->cols = 1;\r
- if (td->rows < 1) td->rows = 1;\r
-\r
- /* Window sizes */\r
- wid = td->cols * td->tile_wid + td->size_ow1 + td->size_ow2;\r
- hgt = td->rows * td->tile_hgt + td->size_oh1 + td->size_oh2;\r
-\r
- /* Fake window size */\r
- rc.left = 0;\r
- rc.right = rc.left + wid;\r
- rc.top = 0;\r
- rc.bottom = rc.top + hgt;\r
-\r
- /* rc.right += 1; */\r
- /* rc.bottom += 1; */\r
-\r
- /* Adjust */\r
- AdjustWindowRectEx(&rc, td->dwStyle, TRUE, td->dwExStyle);\r
-\r
- /* Total size */\r
- td->size_wid = rc.right - rc.left;\r
- td->size_hgt = rc.bottom - rc.top;\r
-\r
- /* See CreateWindowEx */\r
- if (!td->w) return;\r
-\r
- /* Extract actual location */\r
- GetWindowRect(td->w, &rc);\r
-\r
- /* Save the location */\r
- td->pos_x = rc.left;\r
- td->pos_y = rc.top;\r
-}\r
-\r
-\r
-/*\r
- * Write the "prefs" for a single term\r
- */\r
-static void save_prefs_aux(int i)\r
-{\r
- term_data *td = &data[i];\r
- GAME_TEXT sec_name[128];\r
- char buf[1024];\r
-\r
- RECT rc;\r
- WINDOWPLACEMENT lpwndpl;\r
-\r
- /* Paranoia */\r
- if (!td->w) return;\r
-\r
- /* Make section name */\r
- sprintf(sec_name, "Term-%d", i);\r
-\r
- /* Visible */\r
- if (i > 0)\r
- {\r
- strcpy(buf, td->visible ? "1" : "0");\r
- WritePrivateProfileString(sec_name, "Visible", buf, ini_file);\r
- }\r
-\r
- /* Font */\r
-#ifdef JP\r
- strcpy(buf, td->lf.lfFaceName[0]!='\0' ? td->lf.lfFaceName : "MS ゴシック");\r
-#else\r
-#if 0\r
- strcpy(buf, td->font_file ? td->font_file : "8X13.FON");\r
-#else\r
- strcpy(buf, td->lf.lfFaceName[0]!='\0' ? td->lf.lfFaceName : "Courier");\r
-#endif\r
-#endif\r
-\r
- WritePrivateProfileString(sec_name, "Font", buf, ini_file);\r
-\r
-#if 1 /* #ifdef JP */\r
- wsprintf(buf, "%d", td->lf.lfWidth);\r
- WritePrivateProfileString(sec_name, "FontWid", buf, ini_file);\r
- wsprintf(buf, "%d", td->lf.lfHeight);\r
- WritePrivateProfileString(sec_name, "FontHgt", buf, ini_file);\r
- wsprintf(buf, "%d", td->lf.lfWeight);\r
- WritePrivateProfileString(sec_name, "FontWgt", buf, ini_file);\r
-#endif\r
- /* Bizarre */\r
- strcpy(buf, td->bizarre ? "1" : "0");\r
- WritePrivateProfileString(sec_name, "Bizarre", buf, ini_file);\r
-\r
- /* Tile size (x) */\r
- wsprintf(buf, "%d", td->tile_wid);\r
- WritePrivateProfileString(sec_name, "TileWid", buf, ini_file);\r
-\r
- /* Tile size (y) */\r
- wsprintf(buf, "%d", td->tile_hgt);\r
- WritePrivateProfileString(sec_name, "TileHgt", buf, ini_file);\r
-\r
- /* Get window placement and dimensions */\r
- lpwndpl.length = sizeof(WINDOWPLACEMENT);\r
- GetWindowPlacement(td->w, &lpwndpl);\r
-\r
- /* Acquire position in *normal* mode (not minimized) */\r
- rc = lpwndpl.rcNormalPosition;\r
-\r
- /* Window size (x) */\r
- if (i == 0) wsprintf(buf, "%d", normsize.x);\r
- else wsprintf(buf, "%d", td->cols);\r
- WritePrivateProfileString(sec_name, "NumCols", buf, ini_file);\r
-\r
- /* Window size (y) */\r
- if (i == 0) wsprintf(buf, "%d", normsize.y);\r
- else wsprintf(buf, "%d", td->rows);\r
- WritePrivateProfileString(sec_name, "NumRows", buf, ini_file);\r
-\r
- /* Maxmized (only main window) */\r
- if (i == 0)\r
- {\r
- strcpy(buf, IsZoomed(td->w) ? "1" : "0");\r
- WritePrivateProfileString(sec_name, "Maximized", buf, ini_file);\r
- }\r
-\r
- /* Acquire position */\r
- GetWindowRect(td->w, &rc);\r
-\r
- /* Window position (x) */\r
- wsprintf(buf, "%d", rc.left);\r
- WritePrivateProfileString(sec_name, "PositionX", buf, ini_file);\r
-\r
- /* Window position (y) */\r
- wsprintf(buf, "%d", rc.top);\r
- WritePrivateProfileString(sec_name, "PositionY", buf, ini_file);\r
-\r
- /* Window Z position */\r
- if (i > 0)\r
- {\r
- strcpy(buf, td->posfix ? "1" : "0");\r
- WritePrivateProfileString(sec_name, "PositionFix", buf, ini_file);\r
- }\r
-}\r
-\r
-\r
-/*\r
- * Write the "prefs"\r
- * We assume that the windows have all been initialized\r
- */\r
-static void save_prefs(void)\r
-{\r
- int i;\r
-\r
- char buf[128];\r
-\r
- /* Save the "arg_graphics" flag */\r
- sprintf(buf, "%d", arg_graphics);\r
- WritePrivateProfileString("Angband", "Graphics", buf, ini_file);\r
-\r
- /* Save the "arg_bigtile" flag */\r
- strcpy(buf, arg_bigtile ? "1" : "0");\r
- WritePrivateProfileString("Angband", "Bigtile", buf, ini_file);\r
-\r
- /* Save the "arg_sound" flag */\r
- strcpy(buf, arg_sound ? "1" : "0");\r
- WritePrivateProfileString("Angband", "Sound", buf, ini_file);\r
-\r
- /* Save the "arg_sound" flag */\r
- strcpy(buf, arg_music ? "1" : "0");\r
- WritePrivateProfileString("Angband", "Music", buf, ini_file);\r
-\r
- /* bg */\r
- strcpy(buf, use_bg ? "1" : "0");\r
- WritePrivateProfileString("Angband", "BackGround", buf, ini_file);\r
- WritePrivateProfileString("Angband", "BackGroundBitmap", \r
- bg_bitmap_file[0] != '\0' ? bg_bitmap_file : "bg.bmp", ini_file);\r
-\r
- /* Save window prefs */\r
- for (i = 0; i < MAX_TERM_DATA; ++i)\r
- {\r
- save_prefs_aux(i);\r
- }\r
-}\r
-\r
-\r
-/*\r
- * Load the "prefs" for a single term\r
- */\r
-static void load_prefs_aux(int i)\r
-{\r
- term_data *td = &data[i];\r
- GAME_TEXT sec_name[128];\r
- char tmp[1024];\r
-\r
- int wid, hgt, posx, posy;\r
- int dispx = GetSystemMetrics( SM_CXVIRTUALSCREEN);\r
- int dispy = GetSystemMetrics( SM_CYVIRTUALSCREEN);\r
- posx=0;\r
- posy=0;\r
- \r
- /* Make section name */\r
- sprintf(sec_name, "Term-%d", i);\r
-\r
- /* Make section name */\r
- sprintf(sec_name, "Term-%d", i);\r
-\r
- /* Visible */\r
- if (i > 0)\r
- {\r
- td->visible = (GetPrivateProfileInt(sec_name, "Visible", td->visible, ini_file) != 0);\r
- }\r
-\r
- /* Desired font, with default */\r
-#ifdef JP\r
- GetPrivateProfileString(sec_name, "Font", "MS ゴシック", tmp, 127, ini_file);\r
-#else\r
-#if 0\r
- GetPrivateProfileString(sec_name, "Font", "8X13.FON", tmp, 127, ini_file);\r
-#else\r
- GetPrivateProfileString(sec_name, "Font", "Courier", tmp, 127, ini_file);\r
-#endif\r
-#endif\r
-\r
-\r
- /* Bizarre */\r
- td->bizarre = (GetPrivateProfileInt(sec_name, "Bizarre", td->bizarre, ini_file) != 0);\r
-\r
- /* Analyze font, save desired font name */\r
-#if 1 /* #ifdef JP */\r
- td->font_want = string_make(tmp);\r
- hgt = 15; wid = 0;\r
- td->lf.lfWidth = GetPrivateProfileInt(sec_name, "FontWid", wid, ini_file);\r
- td->lf.lfHeight = GetPrivateProfileInt(sec_name, "FontHgt", hgt, ini_file);\r
- td->lf.lfWeight = GetPrivateProfileInt(sec_name, "FontWgt", 0, ini_file);\r
-#else\r
- td->font_want = string_make(analyze_font(tmp, &wid, &hgt));\r
-#endif\r
-\r
-\r
- /* Tile size */\r
-#if 1 /* #ifdef JP */\r
- td->tile_wid = GetPrivateProfileInt(sec_name, "TileWid", td->lf.lfWidth, ini_file);\r
- td->tile_hgt = GetPrivateProfileInt(sec_name, "TileHgt", td->lf.lfHeight, ini_file);\r
-#else\r
- td->tile_wid = GetPrivateProfileInt(sec_name, "TileWid", wid, ini_file);\r
- td->tile_hgt = GetPrivateProfileInt(sec_name, "TileHgt", hgt, ini_file);\r
-#endif\r
-\r
-\r
- /* Window size */\r
- td->cols = GetPrivateProfileInt(sec_name, "NumCols", td->cols, ini_file);\r
- td->rows = GetPrivateProfileInt(sec_name, "NumRows", td->rows, ini_file);\r
- normsize.x = td->cols; normsize.y = td->rows;\r
-\r
- /* Window size */\r
- if (i == 0)\r
- {\r
- win_maximized = (GetPrivateProfileInt(sec_name, "Maximized", win_maximized, ini_file) != 0);\r
- }\r
-\r
- /* Window position */\r
- posx = GetPrivateProfileInt(sec_name, "PositionX", posx, ini_file);\r
- posy = GetPrivateProfileInt(sec_name, "PositionY", posy, ini_file);\r
- td->pos_x = MIN(MAX(0, posx), dispx-128);\r
- td->pos_y = MIN(MAX(0, posy), dispy-128);\r
-\r
- /* Window Z position */\r
- if (i > 0)\r
- {\r
- td->posfix = (GetPrivateProfileInt(sec_name, "PositionFix", td->posfix, ini_file) != 0);\r
- }\r
-}\r
-\r
-\r
-/*\r
- * Load the "prefs"\r
- */\r
-static void load_prefs(void)\r
-{\r
- int i;\r
-\r
- /* Extract the "arg_graphics" flag */\r
- arg_graphics = (byte_hack)GetPrivateProfileInt("Angband", "Graphics", GRAPHICS_NONE, ini_file);\r
-\r
- /* Extract the "arg_bigtile" flag */\r
- arg_bigtile = (GetPrivateProfileInt("Angband", "Bigtile", FALSE, ini_file) != 0);\r
- use_bigtile = arg_bigtile;\r
-\r
- /* Extract the "arg_sound" flag */\r
- arg_sound = (GetPrivateProfileInt("Angband", "Sound", 0, ini_file) != 0);\r
-\r
- /* Extract the "arg_sound" flag */\r
- arg_music = (GetPrivateProfileInt("Angband", "Music", 0, ini_file) != 0);\r
-\r
- /* bg */\r
- use_bg = GetPrivateProfileInt("Angband", "BackGround", 0, ini_file);\r
- GetPrivateProfileString("Angband", "BackGroundBitmap", "bg.bmp", bg_bitmap_file, 1023, ini_file);\r
-\r
- /* Load window prefs */\r
- for (i = 0; i < MAX_TERM_DATA; ++i)\r
- {\r
- load_prefs_aux(i);\r
- }\r
-}\r
-\r
-#if defined(USE_SOUND) || defined(USE_MUSIC)\r
-\r
-/*\r
- * - Taken from files.c.\r
- *\r
- * Extract "tokens" from a buffer\r
- *\r
- * This function uses "whitespace" as delimiters, and treats any amount of\r
- * whitespace as a single delimiter. We will never return any empty tokens.\r
- * When given an empty buffer, or a buffer containing only "whitespace", we\r
- * will return no tokens. We will never extract more than "num" tokens.\r
- *\r
- * By running a token through the "text_to_ascii()" function, you can allow\r
- * that token to include (encoded) whitespace, using "\s" to encode spaces.\r
- *\r
- * We save pointers to the tokens in "tokens", and return the number found.\r
- */\r
-static s16b tokenize_whitespace(char *buf, s16b num, char **tokens)\r
-{\r
- s16b k = 0;\r
- char *s = buf;\r
-\r
- /* Process */\r
- while (k < num)\r
- {\r
- char *t;\r
-\r
- /* Skip leading whitespace */\r
- for ( ; *s && iswspace(*s); ++s) /* loop */;\r
-\r
- /* All done */\r
- if (!*s) break;\r
-\r
- /* Find next whitespace, if any */\r
- for (t = s; *t && !iswspace(*t); ++t) /* loop */;\r
-\r
- /* Nuke and advance (if necessary) */\r
- if (*t) *t++ = '\0';\r
-\r
- /* Save the token */\r
- tokens[k++] = s;\r
-\r
- /* Advance */\r
- s = t;\r
- }\r
-\r
- /* Count */\r
- return (k);\r
-}\r
-\r
-#endif /* USE_SOUND || USE_MUSIC */\r
-\r
-#ifdef USE_SOUND\r
-\r
-static void load_sound_prefs(void)\r
-{\r
- int i, j, num;\r
- char tmp[1024];\r
- char ini_path[1024];\r
- char wav_path[1024];\r
- char *zz[SAMPLE_MAX];\r
-\r
- /* Access the sound.cfg */\r
-\r
- path_build(ini_path, 1024, ANGBAND_DIR_XTRA_SOUND, "sound.cfg");\r
-\r
- for (i = 0; i < SOUND_MAX; i++)\r
- {\r
- GetPrivateProfileString("Sound", angband_sound_name[i], "", tmp, 1024, ini_path);\r
-\r
- num = tokenize_whitespace(tmp, SAMPLE_MAX, zz);\r
-\r
- for (j = 0; j < num; j++)\r
- {\r
- /* Access the sound */\r
- path_build(wav_path, 1024, ANGBAND_DIR_XTRA_SOUND, zz[j]);\r
-\r
- /* Save the sound filename, if it exists */\r
- if (check_file(wav_path))\r
- sound_file[i][j] = string_make(zz[j]);\r
- }\r
- }\r
-}\r
-\r
-#endif /* USE_SOUND */\r
-\r
-#ifdef USE_MUSIC\r
-\r
-static void load_music_prefs(void)\r
-{\r
- int i, j, num;\r
- char tmp[1024];\r
- char ini_path[1024];\r
- char wav_path[1024];\r
- char *zz[SAMPLE_MAX];\r
- char key[80];\r
-\r
- /* Access the music.cfg */\r
-\r
- path_build(ini_path, 1024, ANGBAND_DIR_XTRA_MUSIC, "music.cfg");\r
-\r
- GetPrivateProfileString("Device", "type", "", mci_device_type, 256, ini_path);\r
-\r
- for (i = 0; i < MUSIC_BASIC_MAX; i++)\r
- {\r
- GetPrivateProfileString("Basic", angband_music_basic_name[i], "", tmp, 1024, ini_path);\r
-\r
- num = tokenize_whitespace(tmp, SAMPLE_MUSIC_MAX, zz);\r
-\r
- for (j = 0; j < num; j++)\r
- {\r
- /* Access the sound */\r
- path_build(wav_path, 1024, ANGBAND_DIR_XTRA_MUSIC, zz[j]);\r
-\r
- /* Save the sound filename, if it exists */\r
- if (check_file(wav_path))\r
- music_file[i][j] = string_make(zz[j]);\r
- }\r
- }\r
-\r
- for (i = 0; i < max_d_idx; i++)\r
- {\r
- sprintf(key, "dungeon%03d", i);\r
- GetPrivateProfileString("Dungeon", key, "", tmp, 1024, ini_path);\r
-\r
- num = tokenize_whitespace(tmp, SAMPLE_MUSIC_MAX, zz);\r
-\r
- for (j = 0; j < num; j++)\r
- {\r
- /* Access the sound */\r
- path_build(wav_path, 1024, ANGBAND_DIR_XTRA_MUSIC, zz[j]);\r
-\r
- /* Save the sound filename, if it exists */\r
- if (check_file(wav_path))\r
- dungeon_music_file[i][j] = string_make(zz[j]);\r
- }\r
- }\r
-\r
- for (i = 0; i < max_q_idx; i++)\r
- {\r
- sprintf(key, "quest%03d", i);\r
- GetPrivateProfileString("Quest", key, "", tmp, 1024, ini_path);\r
-\r
- num = tokenize_whitespace(tmp, SAMPLE_MUSIC_MAX, zz);\r
-\r
- for (j = 0; j < num; j++)\r
- {\r
- /* Access the sound */\r
- path_build(wav_path, 1024, ANGBAND_DIR_XTRA_MUSIC, zz[j]);\r
-\r
- /* Save the sound filename, if it exists */\r
- if (check_file(wav_path))\r
- quest_music_file[i][j] = string_make(zz[j]);\r
- }\r
- }\r
-\r
- for (i = 0; i < 1000; i++) /*!< @todo 町最大数指定 */\r
- {\r
- sprintf(key, "town%03d", i);\r
- GetPrivateProfileString("Town", key, "", tmp, 1024, ini_path);\r
-\r
- num = tokenize_whitespace(tmp, SAMPLE_MUSIC_MAX, zz);\r
-\r
- for (j = 0; j < num; j++)\r
- {\r
- /* Access the sound */\r
- path_build(wav_path, 1024, ANGBAND_DIR_XTRA_MUSIC, zz[j]);\r
-\r
- /* Save the sound filename, if it exists */\r
- if (check_file(wav_path))\r
- town_music_file[i][j] = string_make(zz[j]);\r
- }\r
- }\r
-\r
-\r
-}\r
-\r
-#endif /* USE_MUSIC */\r
-\r
-/*\r
- * Create the new global palette based on the bitmap palette\r
- * (if any), and the standard 16 entry palette derived from\r
- * "win_clr[]" which is used for the basic 16 Angband colors.\r
- *\r
- * This function is never called before all windows are ready.\r
- *\r
- * This function returns FALSE if the new palette could not be\r
- * prepared, which should normally be a fatal error. XXX XXX\r
- *\r
- * Note that only some machines actually use a "palette".\r
- */\r
-static int new_palette(void)\r
-{\r
- HPALETTE hBmPal;\r
- HPALETTE hNewPal;\r
- HDC hdc;\r
- int i, nEntries;\r
- int pLogPalSize;\r
- int lppeSize;\r
- LPLOGPALETTE pLogPal;\r
- LPPALETTEENTRY lppe;\r
-\r
- term_data *td;\r
-\r
-\r
- /* This makes no sense */\r
- if (!paletted) return (TRUE);\r
-\r
-\r
- /* No bitmap */\r
- lppeSize = 0;\r
- lppe = NULL;\r
- nEntries = 0;\r
-\r
-#ifdef USE_GRAPHICS\r
-\r
- /* Check the bitmap palette */\r
- hBmPal = infGraph.hPalette;\r
-\r
- /* Use the bitmap */\r
- if (hBmPal)\r
- {\r
- lppeSize = 256 * sizeof(PALETTEENTRY);\r
- lppe = (LPPALETTEENTRY)ralloc(lppeSize);\r
- nEntries = GetPaletteEntries(hBmPal, 0, 255, lppe);\r
- if ((nEntries == 0) || (nEntries > 220))\r
- {\r
- /* Warn the user */\r
- plog(_("画面を16ビットか24ビットカラーモードにして下さい。", "Please switch to high- or true-color mode."));\r
-\r
- /* Cleanup */\r
- rnfree(lppe, lppeSize);\r
-\r
- /* Fail */\r
- return (FALSE);\r
- }\r
- }\r
-\r
-#endif /* USE_GRAPHICS */\r
-\r
- /* Size of palette */\r
- pLogPalSize = sizeof(LOGPALETTE) + (nEntries + 16) * sizeof(PALETTEENTRY);\r
-\r
- /* Allocate palette */\r
- pLogPal = (LPLOGPALETTE)ralloc(pLogPalSize);\r
-\r
- /* Version */\r
- pLogPal->palVersion = 0x300;\r
-\r
- /* Make room for bitmap and normal data */\r
- pLogPal->palNumEntries = nEntries + 16;\r
-\r
- /* Save the bitmap data */\r
- for (i = 0; i < nEntries; i++)\r
- {\r
- pLogPal->palPalEntry[i] = lppe[i];\r
- }\r
-\r
- /* Save the normal data */\r
- for (i = 0; i < 16; i++)\r
- {\r
- LPPALETTEENTRY p;\r
-\r
- /* Access the entry */\r
- p = &(pLogPal->palPalEntry[i+nEntries]);\r
-\r
- /* Save the colors */\r
- p->peRed = GetRValue(win_clr[i]);\r
- p->peGreen = GetGValue(win_clr[i]);\r
- p->peBlue = GetBValue(win_clr[i]);\r
-\r
- /* Save the flags */\r
- p->peFlags = PC_NOCOLLAPSE;\r
- }\r
-\r
- /* Free something */\r
- if (lppe) rnfree(lppe, lppeSize);\r
-\r
- /* Create a new palette, or fail */\r
- hNewPal = CreatePalette(pLogPal);\r
- if (!hNewPal) quit(_("パレットを作成できません!", "Cannot create palette!"));\r
-\r
- /* Free the palette */\r
- rnfree(pLogPal, pLogPalSize);\r
-\r
- /* Main window */\r
- td = &data[0];\r
-\r
- /* Realize the palette */\r
- hdc = GetDC(td->w);\r
- SelectPalette(hdc, hNewPal, 0);\r
- i = RealizePalette(hdc);\r
- ReleaseDC(td->w, hdc);\r
- if (i == 0) quit(_("パレットをシステムエントリにマップできません!", "Cannot realize palette!"));\r
-\r
-\r
- /* Sub-windows */\r
- for (i = 1; i < MAX_TERM_DATA; i++)\r
- {\r
- td = &data[i];\r
-\r
- hdc = GetDC(td->w);\r
- SelectPalette(hdc, hNewPal, 0);\r
- ReleaseDC(td->w, hdc);\r
- }\r
-\r
- /* Delete old palette */\r
- if (hPal) DeleteObject(hPal);\r
-\r
- /* Save new palette */\r
- hPal = hNewPal;\r
-\r
- /* Success */\r
- return (TRUE);\r
-}\r
-\r
-\r
-#ifdef USE_GRAPHICS\r
-/*!\r
- * @brief グラフィクスを初期化する / Initialize graphics\r
- * @details\r
- * <ul>\r
- * <li>メニュー[オプション]>[グラフィクス]が「なし」以外の時に描画処理を初期化する。</li>\r
- * <li>呼び出されるタイミングはロード時、及び同メニューで「なし」以外に変更される毎になる。</li>\r
- * </ul>\r
- */\r
-static bool init_graphics(void)\r
-{\r
- /* Initialize once */\r
- char buf[1024];\r
- BYTE wid, hgt, twid, thgt, ox, oy;\r
- concptr name;\r
-\r
- if (arg_graphics == GRAPHICS_ADAM_BOLT)\r
- {\r
- wid = 16;\r
- hgt = 16;\r
- twid = 16;\r
- thgt = 16;\r
- ox = 0;\r
- oy = 0;\r
- name = "16X16.BMP";\r
-\r
- ANGBAND_GRAF = "new";\r
- }\r
- else if (arg_graphics == GRAPHICS_HENGBAND)\r
- {\r
- /*! @todo redraw\r
- wid = 64;\r
- hgt = 64;\r
- twid = 32;\r
- thgt = 32;\r
- ox = -16;\r
- oy = -24;\r
- name = "64X64.BMP";\r
- */\r
-\r
- wid = 32;\r
- hgt = 32;\r
- twid = 32;\r
- thgt = 32;\r
- ox = 0;\r
- oy = 0;\r
- name = "32X32.BMP";\r
-\r
- ANGBAND_GRAF = "ne2";\r
- }\r
- else\r
- {\r
- wid = 8;\r
- hgt = 8;\r
- twid = 8;\r
- thgt = 8;\r
- ox = 0;\r
- oy = 0;\r
- name = "8X8.BMP";\r
- ANGBAND_GRAF = "old";\r
- }\r
-\r
- /* Access the bitmap file */\r
- path_build(buf, sizeof(buf), ANGBAND_DIR_XTRA_GRAF, name);\r
-\r
- /* Load the bitmap or quit */\r
- if (!ReadDIB(data[0].w, buf, &infGraph))\r
- {\r
- plog_fmt(_("ビットマップ '%s' を読み込めません。", "Cannot read bitmap file '%s'"), name);\r
- return (FALSE);\r
- }\r
-\r
- /* Save the new sizes */\r
- infGraph.CellWidth = wid;\r
- infGraph.CellHeight = hgt;\r
- infGraph.TileWidth = twid;\r
- infGraph.TileHeight = thgt;\r
- infGraph.OffsetX = ox;\r
- infGraph.OffsetY = oy;\r
-\r
- if (arg_graphics == GRAPHICS_ADAM_BOLT)\r
- {\r
- /* Access the mask file */\r
- path_build(buf, sizeof(buf), ANGBAND_DIR_XTRA_GRAF, "mask.bmp");\r
-\r
- /* Load the bitmap or quit */\r
- if (!ReadDIB(data[0].w, buf, &infMask))\r
- {\r
- plog_fmt("Cannot read bitmap file '%s'", buf);\r
- return (FALSE);\r
- }\r
- }\r
- if (arg_graphics == GRAPHICS_HENGBAND)\r
- {\r
- /* Access the mask file */\r
- path_build(buf, sizeof(buf), ANGBAND_DIR_XTRA_GRAF, "mask32.bmp");\r
-\r
- /* Load the bitmap or quit */\r
- if (!ReadDIB(data[0].w, buf, &infMask))\r
- {\r
- plog_fmt("Cannot read bitmap file '%s'", buf);\r
- return (FALSE);\r
- }\r
- }\r
-\r
- /* Activate a palette */\r
- if (!new_palette())\r
- {\r
- /* Free bitmap */\r
-\r
- plog(_("パレットを実現できません!", "Cannot activate palette!"));\r
- return (FALSE);\r
- }\r
-\r
- /* Graphics available */\r
- current_graphics_mode = arg_graphics;\r
- return (current_graphics_mode);\r
-}\r
-#endif /* USE_GRAPHICS */\r
-\r
-\r
-#ifdef USE_MUSIC\r
-/*\r
- * Initialize music\r
- */\r
-static bool init_music(void)\r
-{\r
- /* Initialize once */\r
- if (!can_use_music)\r
- {\r
- /* Load the prefs */\r
- load_music_prefs();\r
-\r
- /* Sound available */\r
- can_use_music = TRUE;\r
- }\r
- return (can_use_music);\r
-}\r
-\r
-/*\r
- * Hack -- Stop a music\r
- */\r
-static void stop_music(void)\r
-{\r
- mciSendCommand(mop.wDeviceID, MCI_STOP, 0, 0);\r
- mciSendCommand(mop.wDeviceID, MCI_CLOSE, 0, 0);\r
-}\r
-\r
-#endif /* USE_MUSIC */\r
-\r
-#ifdef USE_SOUND\r
-/*\r
- * Initialize sound\r
- */\r
-static bool init_sound(void)\r
-{\r
- /* Initialize once */\r
- if (!can_use_sound)\r
- {\r
- /* Load the prefs */\r
- load_sound_prefs();\r
-\r
- /* Sound available */\r
- can_use_sound = TRUE;\r
- }\r
- return (can_use_sound);\r
-}\r
-#endif /* USE_SOUND */\r
-\r
-\r
-/*\r
- * Resize a window\r
- */\r
-static void term_window_resize(term_data *td)\r
-{\r
- /* Require window */\r
- if (!td->w) return;\r
-\r
- /* Resize the window */\r
- SetWindowPos(td->w, 0, 0, 0,\r
- td->size_wid, td->size_hgt,\r
- SWP_NOMOVE | SWP_NOZORDER);\r
-\r
- /* Redraw later */\r
- InvalidateRect(td->w, NULL, TRUE);\r
-}\r
-\r
-\r
-/*\r
- * Force the use of a new "font file" for a term_data\r
- *\r
- * This function may be called before the "window" is ready\r
- *\r
- * This function returns zero only if everything succeeds.\r
- *\r
- * Note that the "font name" must be capitalized!!!\r
- */\r
-static errr term_force_font(term_data *td, concptr path)\r
-{\r
- int wid, hgt;\r
-\r
-#if 0 /* #ifndef JP */\r
- int i;\r
- char *base;\r
- char buf[1024];\r
-#endif\r
-\r
- /* Forget the old font (if needed) */\r
- if (td->font_id) DeleteObject(td->font_id);\r
-\r
-#if 1 /* #ifdef JP */\r
- /* Unused */\r
- (void)path;\r
-\r
- /* Create the font (using the 'base' of the font file name!) */\r
- td->font_id = CreateFontIndirect(&(td->lf));\r
- wid = td->lf.lfWidth;\r
- hgt = td->lf.lfHeight;\r
- if (!td->font_id) return (1);\r
-#else\r
- /* Forget old font */\r
- if (td->font_file)\r
- {\r
- bool used = FALSE;\r
-\r
- /* Scan windows */\r
- for (i = 0; i < MAX_TERM_DATA; i++)\r
- {\r
- /* Don't check when closing the application */\r
- if (!path) break;\r
-\r
- /* Check "screen" */\r
- if ((td != &data[i]) &&\r
- (data[i].font_file) &&\r
- (streq(data[i].font_file, td->font_file)))\r
- {\r
- used = TRUE;\r
- }\r
- }\r
-\r
- /* Remove unused font resources */\r
- if (!used) RemoveFontResource(td->font_file);\r
-\r
- /* Free the old name */\r
- string_free(td->font_file);\r
-\r
- /* Forget it */\r
- td->font_file = NULL;\r
- }\r
-\r
- /* No path given */\r
- if (!path) return (1);\r
-\r
- /* Local copy */\r
- strcpy(buf, path);\r
-\r
- /* Analyze font path */\r
- base = analyze_font(buf, &wid, &hgt);\r
-\r
- /* Verify suffix */\r
- if (!suffix(base, ".FON")) return (1);\r
-\r
- /* Verify file */\r
- if (!check_file(buf)) return (1);\r
-\r
- /* Load the new font */\r
- if (!AddFontResource(buf)) return (1);\r
-\r
- /* Save new font name */\r
- td->font_file = string_make(base);\r
-\r
- /* Remove the "suffix" */\r
- base[strlen(base)-4] = '\0';\r
-\r
- /* Create the font (using the 'base' of the font file name!) */\r
- td->font_id = CreateFont(hgt, wid, 0, 0, FW_DONTCARE, 0, 0, 0,\r
- ANSI_CHARSET, OUT_DEFAULT_PRECIS,\r
- CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,\r
- FIXED_PITCH | FF_DONTCARE, base);\r
-#endif\r
-\r
- /* Hack -- Unknown size */\r
- if (!wid || !hgt)\r
- {\r
- HDC hdcDesktop;\r
- HFONT hfOld;\r
- TEXTMETRIC tm;\r
-\r
- /* all this trouble to get the cell size */\r
- hdcDesktop = GetDC(HWND_DESKTOP);\r
- hfOld = SelectObject(hdcDesktop, td->font_id);\r
- GetTextMetrics(hdcDesktop, &tm);\r
- SelectObject(hdcDesktop, hfOld);\r
- ReleaseDC(HWND_DESKTOP, hdcDesktop);\r
-\r
- /* Font size info */\r
- wid = tm.tmAveCharWidth;\r
- hgt = tm.tmHeight;\r
- }\r
-\r
- /* Save the size info */\r
- td->font_wid = wid;\r
- td->font_hgt = hgt;\r
-\r
- /* Success */\r
- return (0);\r
-}\r
-\r
-\r
-\r
-/*\r
- * Allow the user to change the font for this window.\r
- */\r
-static void term_change_font(term_data *td)\r
-{\r
-#if 1 /* #ifdef JP */\r
- CHOOSEFONT cf;\r
-\r
- memset(&cf, 0, sizeof(cf));\r
- cf.lStructSize = sizeof(cf);\r
- cf.Flags = CF_SCREENFONTS | CF_FIXEDPITCHONLY | CF_NOVERTFONTS | CF_INITTOLOGFONTSTRUCT;\r
- cf.lpLogFont = &(td->lf);\r
-\r
- if (ChooseFont(&cf))\r
- {\r
- /* Force the font */\r
- term_force_font(td, NULL);\r
-\r
- /* Assume not bizarre */\r
- td->bizarre = TRUE;\r
-\r
- /* Reset the tile info */\r
- td->tile_wid = td->font_wid;\r
- td->tile_hgt = td->font_hgt;\r
-\r
- /* Analyze the font */\r
- term_getsize(td);\r
-\r
- /* Resize the window */\r
- term_window_resize(td);\r
- }\r
-\r
-#else\r
- OPENFILENAME ofn;\r
-\r
- char tmp[1024] = "";\r
-\r
- /* Extract a default if possible */\r
- if (td->font_file) strcpy(tmp, td->font_file);\r
-\r
- /* Ask for a choice */\r
- memset(&ofn, 0, sizeof(ofn));\r
- ofn.lStructSize = sizeof(ofn);\r
- ofn.hwndOwner = data[0].w;\r
- ofn.lpstrFilter = "Angband Font Files (*.fon)\0*.fon\0";\r
- ofn.nFilterIndex = 1;\r
- ofn.lpstrFile = tmp;\r
- ofn.nMaxFile = 128;\r
- ofn.lpstrInitialDir = ANGBAND_DIR_XTRA_FONT;\r
- ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;\r
- ofn.lpstrDefExt = "fon";\r
-\r
- /* Force choice if legal */\r
- if (GetOpenFileName(&ofn))\r
- {\r
- /* Force the font */\r
- if (term_force_font(td, tmp))\r
- {\r
- /* Access the standard font file */\r
- path_build(tmp, sizeof(tmp), ANGBAND_DIR_XTRA_FONT, "8X13.FON");\r
-\r
- /* Force the use of that font */\r
- (void)term_force_font(td, tmp);\r
- }\r
-\r
- /* Assume not bizarre */\r
- td->bizarre = FALSE;\r
-\r
- /* Reset the tile info */\r
- td->tile_wid = td->font_wid;\r
- td->tile_hgt = td->font_hgt;\r
-\r
- /* Analyze the font */\r
- term_getsize(td);\r
-\r
- /* Resize the window */\r
- term_window_resize(td);\r
- }\r
-#endif\r
-\r
-}\r
-\r
-/*\r
- * Allow the user to lock this window.\r
- */\r
-static void term_window_pos(term_data *td, HWND hWnd)\r
-{\r
- SetWindowPos(td->w, hWnd, 0, 0, 0, 0,\r
- SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);\r
-}\r
-\r
-static void windows_map(void);\r
-\r
-/*\r
- * Hack -- redraw a term_data\r
- */\r
-static void term_data_redraw(term_data *td)\r
-{\r
- if (td->map_active)\r
- {\r
- /* Redraw the map */\r
- windows_map();\r
- }\r
- else\r
- {\r
- /* Activate the term */\r
- Term_activate(&td->t);\r
-\r
- /* Redraw the contents */\r
- Term_redraw();\r
-\r
- /* Restore the term */\r
- Term_activate(term_screen);\r
- }\r
-}\r
-\r
-\r
-void Term_inversed_area(HWND hWnd, int x, int y, int w, int h)\r
-{\r
- HDC hdc;\r
- HPEN oldPen;\r
- HBRUSH myBrush, oldBrush;\r
-\r
- term_data *td = (term_data *)GetWindowLong(hWnd, 0);\r
- int tx = td->size_ow1 + x * td->tile_wid;\r
- int ty = td->size_oh1 + y * td->tile_hgt;\r
- int tw = w * td->tile_wid - 1;\r
- int th = h * td->tile_hgt - 1;\r
-\r
- hdc = GetDC(hWnd);\r
- myBrush = CreateSolidBrush(RGB(255, 255, 255));\r
- oldBrush = SelectObject(hdc, myBrush);\r
- oldPen = SelectObject(hdc, GetStockObject(NULL_PEN) );\r
-\r
- PatBlt(hdc, tx, ty, tw, th, PATINVERT);\r
-\r
- SelectObject(hdc, oldBrush);\r
- SelectObject(hdc, oldPen);\r
-}\r
-\r
-\r
-\r
-/*** Function hooks needed by "Term" ***/\r
-\r
-\r
-#if 0\r
-\r
-/*\r
- * Initialize a new Term\r
- */\r
-static void Term_init_win(term *t)\r
-{\r
- /* XXX Unused */\r
-}\r
-\r
-\r
-/*\r
- * Nuke an old Term\r
- */\r
-static void Term_nuke_win(term *t)\r
-{\r
- /* XXX Unused */\r
-}\r
-\r
-#endif\r
-\r
-\r
-/*!\r
- * @brief //!< Windows版ユーザ設定項目実装部(実装必須) /Interact with the User\r
- */\r
-static errr Term_user_win(int n)\r
-{\r
- /* Unused */\r
- (void)n;\r
-\r
- /* Success */\r
- return (0);\r
-}\r
-\r
-\r
-/*\r
- * React to global changes\r
- */\r
-static errr Term_xtra_win_react(void)\r
-{\r
- int i;\r
-\r
- /* Simple color */\r
- if (colors16)\r
- {\r
- /* Save the default colors */\r
- for (i = 0; i < 256; i++)\r
- {\r
- /* Simply accept the desired colors */\r
- win_pal[i] = angband_color_table[i][0];\r
- }\r
- }\r
-\r
- /* Complex color */\r
- else\r
- {\r
- COLORREF code;\r
-\r
- byte rv, gv, bv;\r
-\r
- bool change = FALSE;\r
-\r
- /* Save the default colors */\r
- for (i = 0; i < 256; i++)\r
- {\r
- /* Extract desired values */\r
- rv = angband_color_table[i][1];\r
- gv = angband_color_table[i][2];\r
- bv = angband_color_table[i][3];\r
-\r
- /* Extract a full color code */\r
- code = PALETTERGB(rv, gv, bv);\r
-\r
- /* Activate changes */\r
- if (win_clr[i] != code)\r
- {\r
- /* Note the change */\r
- change = TRUE;\r
-\r
- /* Apply the desired color */\r
- win_clr[i] = code;\r
- }\r
- }\r
-\r
- /* Activate the palette if needed */\r
- if (change) (void)new_palette();\r
- }\r
-\r
-\r
-#ifdef USE_SOUND\r
-\r
- /* Handle "arg_sound" */\r
- if (use_sound != arg_sound)\r
- {\r
- /* Initialize (if needed) */\r
- if (arg_sound && !init_sound())\r
- {\r
- /* Warning */\r
- plog(_("サウンドを初期化できません!", "Cannot initialize sound!"));\r
-\r
- /* Cannot enable */\r
- arg_sound = FALSE;\r
- }\r
-\r
- /* Change setting */\r
- use_sound = arg_sound;\r
- }\r
-\r
-#endif\r
-\r
-#ifdef USE_MUSIC\r
-\r
- /* Handle "arg_sound" */\r
- if (use_music != arg_music)\r
- {\r
- /* Initialize (if needed) */\r
- if (arg_music && !init_music())\r
- {\r
- /* Warning */\r
- plog(_("BGMを初期化できません!", "Cannot initialize BGM!"));\r
- /* Cannot enable */\r
- arg_music = FALSE;\r
- }\r
-\r
- /* Change setting */\r
- use_music = arg_music;\r
-\r
- if(!arg_music) stop_music();\r
- else select_floor_music();\r
-\r
- }\r
-\r
-#endif\r
-\r
-\r
-#ifdef USE_GRAPHICS\r
-\r
- /* Handle "arg_graphics" */\r
- if (use_graphics != arg_graphics)\r
- {\r
- /* Initialize (if needed) */\r
- if (arg_graphics && !init_graphics())\r
- {\r
- /* Warning */\r
- plog(_("グラフィックスを初期化できません!", "Cannot initialize graphics!"));\r
-\r
- /* Cannot enable */\r
- arg_graphics = GRAPHICS_NONE;\r
- }\r
-\r
- /* Change setting */\r
- use_graphics = arg_graphics;\r
-\r
- /* Reset visuals */\r
-#ifdef ANGBAND_2_8_1\r
- reset_visuals();\r
-#else /* ANGBAND_2_8_1 */\r
- reset_visuals(TRUE);\r
-#endif /* ANGBAND_2_8_1 */\r
- }\r
-\r
-#endif /* USE_GRAPHICS */\r
-\r
-\r
- /* Clean up windows */\r
- for (i = 0; i < MAX_TERM_DATA; i++)\r
- {\r
- term *old = Term;\r
-\r
- term_data *td = &data[i];\r
-\r
- /* Update resized windows */\r
- if ((td->cols != td->t.wid) || (td->rows != td->t.hgt))\r
- {\r
- /* Activate */\r
- Term_activate(&td->t);\r
-\r
- /* Hack -- Resize the term */\r
- Term_resize(td->cols, td->rows);\r
-\r
- /* Redraw the contents */\r
- Term_redraw();\r
- Term_activate(old);\r
- }\r
- }\r
-\r
-\r
- /* Success */\r
- return (0);\r
-}\r
-\r
-\r
-/*\r
- * Process at least one event\r
- */\r
-static errr Term_xtra_win_event(int v)\r
-{\r
- MSG msg;\r
-\r
- /* Wait for an event */\r
- if (v)\r
- {\r
- /* Block */\r
- if (GetMessage(&msg, NULL, 0, 0))\r
- {\r
- TranslateMessage(&msg);\r
- DispatchMessage(&msg);\r
- }\r
- }\r
-\r
- /* Check for an event */\r
- else\r
- {\r
- /* Check */\r
- if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))\r
- {\r
- TranslateMessage(&msg);\r
- DispatchMessage(&msg);\r
- }\r
- }\r
-\r
- /* Success */\r
- return 0;\r
-}\r
-\r
-\r
-/*\r
- * Process all pending events\r
- */\r
-static errr Term_xtra_win_flush(void)\r
-{\r
- MSG msg;\r
-\r
- /* Process all pending events */\r
- while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))\r
- {\r
- TranslateMessage(&msg);\r
- DispatchMessage(&msg);\r
- }\r
-\r
- /* Success */\r
- return (0);\r
-}\r
-\r
-\r
-/*\r
- * Hack -- clear the screen\r
- *\r
- * Make this more efficient \r
- */\r
-static errr Term_xtra_win_clear(void)\r
-{\r
- term_data *td = (term_data*)(Term->data);\r
-\r
- HDC hdc;\r
- RECT rc;\r
-\r
- /* Rectangle to erase */\r
- rc.left = td->size_ow1;\r
- rc.right = rc.left + td->cols * td->tile_wid;\r
- rc.top = td->size_oh1;\r
- rc.bottom = rc.top + td->rows * td->tile_hgt;\r
-\r
- /* Erase it */\r
- hdc = GetDC(td->w);\r
- SetBkColor(hdc, RGB(0, 0, 0));\r
- SelectObject(hdc, td->font_id);\r
- ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);\r
-\r
- /* bg */\r
- if (use_bg)\r
- {\r
- rc.left = 0; rc.top = 0;\r
- DrawBG(hdc, &rc);\r
- }\r
- ReleaseDC(td->w, hdc);\r
-\r
- /* Success */\r
- return 0;\r
-}\r
-\r
-\r
-/*\r
- * Hack -- make a noise\r
- */\r
-static errr Term_xtra_win_noise(void)\r
-{\r
- MessageBeep(MB_ICONASTERISK);\r
- return (0);\r
-}\r
-\r
-\r
-/*\r
- * Hack -- make a sound\r
- */\r
-static errr Term_xtra_win_sound(int v)\r
-{\r
-#ifdef USE_SOUND\r
- int i;\r
- char buf[1024];\r
-#endif /* USE_SOUND */\r
-\r
- /* Sound disabled */\r
- if (!use_sound) return (1);\r
-\r
- /* Illegal sound */\r
- if ((v < 0) || (v >= SOUND_MAX)) return (1);\r
-\r
-#ifdef USE_SOUND\r
-\r
- /* Count the samples */\r
- for (i = 0; i < SAMPLE_MAX; i++)\r
- {\r
- if (!sound_file[v][i])\r
- break;\r
- }\r
-\r
- /* No sample */\r
- if (i == 0) return (1);\r
-\r
- /* Build the path */\r
- path_build(buf, 1024, ANGBAND_DIR_XTRA_SOUND, sound_file[v][Rand_external(i)]);\r
-\r
-#ifdef WIN32\r
-\r
- /* Play the sound, catch errors */\r
- return (PlaySound(buf, 0, SND_FILENAME | SND_ASYNC));\r
-\r
-#else /* WIN32 */\r
-\r
- /* Play the sound, catch errors */\r
- return (sndPlaySound(buf, SND_ASYNC));\r
-\r
-#endif /* WIN32 */\r
-\r
-#else /* USE_SOUND */\r
-\r
- return (1);\r
-\r
-#endif /* USE_SOUND */\r
-}\r
-\r
-/*\r
- * Hack -- play a music\r
- */\r
-static errr Term_xtra_win_music(int n, int v)\r
-{\r
-#ifdef USE_MUSIC\r
- int i = 0;\r
- char buf[1024];\r
-#endif /* USE_MUSIC */\r
-\r
- /* Sound disabled */\r
-\r
- if(!use_music) return (1);\r
-\r
- /* Illegal sound */\r
- if(n == TERM_XTRA_MUSIC_BASIC && ((v < 0) || (v >= MUSIC_BASIC_MAX))) return (1);\r
- else if(v < 0 || v >= 1000) return(1); /*!< TODO */\r
-\r
-#ifdef USE_MUSIC\r
-\r
- switch(n)\r
- {\r
- case TERM_XTRA_MUSIC_BASIC:\r
- for (i = 0; i < SAMPLE_MAX; i++) if(!music_file[v][i]) break;\r
- break;\r
- case TERM_XTRA_MUSIC_DUNGEON:\r
- for (i = 0; i < SAMPLE_MAX; i++) if(!dungeon_music_file[v][i]) break;\r
- break;\r
- case TERM_XTRA_MUSIC_QUEST:\r
- for (i = 0; i < SAMPLE_MAX; i++) if(!quest_music_file[v][i]) break;\r
- break;\r
- case TERM_XTRA_MUSIC_TOWN:\r
- for (i = 0; i < SAMPLE_MAX; i++) if(!town_music_file[v][i]) break;\r
- break;\r
- }\r
-\r
- /* No sample */\r
- if (i == 0)\r
- {\r
- //mciSendCommand(mop.wDeviceID, MCI_STOP, 0, 0);\r
- //mciSendCommand(mop.wDeviceID, MCI_CLOSE, 0, 0);\r
- return (1);\r
- }\r
-\r
- switch(n)\r
- {\r
- case TERM_XTRA_MUSIC_BASIC:\r
- for (i = 0; i < SAMPLE_MAX; i++) if(!music_file[v][i]) break;\r
- break;\r
- case TERM_XTRA_MUSIC_DUNGEON:\r
- for (i = 0; i < SAMPLE_MAX; i++) if(!dungeon_music_file[v][i]) break;\r
- break;\r
- case TERM_XTRA_MUSIC_QUEST:\r
- for (i = 0; i < SAMPLE_MAX; i++) if(!quest_music_file[v][i]) break;\r
- break;\r
- case TERM_XTRA_MUSIC_TOWN:\r
- for (i = 0; i < SAMPLE_MAX; i++) if(!town_music_file[v][i]) break;\r
- break;\r
- }\r
-\r
- /* No sample */\r
- if (i == 0)\r
- {\r
- mciSendCommand(mop.wDeviceID, MCI_STOP, 0, 0);\r
- mciSendCommand(mop.wDeviceID, MCI_CLOSE, 0, 0);\r
- return (1);\r
- }\r
-\r
- switch(n)\r
- {\r
- case TERM_XTRA_MUSIC_BASIC:\r
- path_build(buf, 1024, ANGBAND_DIR_XTRA_MUSIC, music_file[v][Rand_external(i)]);\r
- break;\r
- case TERM_XTRA_MUSIC_DUNGEON:\r
- path_build(buf, 1024, ANGBAND_DIR_XTRA_MUSIC, dungeon_music_file[v][Rand_external(i)]);\r
- break;\r
- case TERM_XTRA_MUSIC_QUEST:\r
- path_build(buf, 1024, ANGBAND_DIR_XTRA_MUSIC, quest_music_file[v][Rand_external(i)]);\r
- break;\r
- case TERM_XTRA_MUSIC_TOWN:\r
- path_build(buf, 1024, ANGBAND_DIR_XTRA_MUSIC, town_music_file[v][Rand_external(i)]);\r
- break;\r
- }\r
-\r
- if(current_music_type == n && current_music_id == v)\r
- {\r
- return (0);\r
- }\r
- current_music_type = n;\r
- current_music_id = v;\r
-\r
-#ifdef WIN32\r
-\r
- mop.lpstrDeviceType = mci_device_type; \r
- mop.lpstrElementName = buf;\r
- mciSendCommand(mop.wDeviceID, MCI_STOP, 0, 0);\r
- mciSendCommand(mop.wDeviceID, MCI_CLOSE, 0, 0);\r
- mciSendCommand(mop.wDeviceID, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_ELEMENT, (DWORD)&mop);\r
- mciSendCommand(mop.wDeviceID, MCI_SEEK, MCI_SEEK_TO_START, 0);\r
- mciSendCommand(mop.wDeviceID, MCI_PLAY, MCI_NOTIFY, (DWORD)&mop);\r
- return (0);\r
-\r
-#endif /* WIN32 */\r
-\r
-#else /* USE_MUSIC */\r
-\r
- return (1);\r
-\r
-#endif /* USE_MUSIC */\r
-\r
-}\r
-\r
-\r
-/*\r
- * Delay for "x" milliseconds\r
- */\r
-static int Term_xtra_win_delay(int v)\r
-{\r
-\r
-#ifdef WIN32\r
-\r
- /* Sleep */\r
- Sleep(v);\r
-\r
-#else /* WIN32 */\r
-\r
- DWORD t;\r
- MSG msg;\r
-\r
- /* Final count */\r
- t = GetTickCount() + v;\r
-\r
- /* Wait for it */\r
- while (GetTickCount() < t)\r
- {\r
- /* Handle messages */\r
- if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))\r
- {\r
- TranslateMessage(&msg);\r
- DispatchMessage(&msg);\r
- }\r
- }\r
-\r
-#endif /* WIN32 */\r
-\r
- /* Success */\r
- return (0);\r
-}\r
-\r
-\r
-/*\r
- * Do a "special thing"\r
- */\r
-static errr Term_xtra_win(int n, int v)\r
-{\r
- /* Handle a subset of the legal requests */\r
- switch (n)\r
- {\r
- /* Make a bell sound */\r
- case TERM_XTRA_NOISE:\r
- {\r
- return (Term_xtra_win_noise());\r
- }\r
-\r
- /* Play a music */\r
- case TERM_XTRA_MUSIC_BASIC:\r
- case TERM_XTRA_MUSIC_DUNGEON:\r
- case TERM_XTRA_MUSIC_QUEST:\r
- case TERM_XTRA_MUSIC_TOWN:\r
- {\r
- return (Term_xtra_win_music(n, v));\r
- }\r
-\r
- /* Make a special sound */\r
- case TERM_XTRA_SOUND:\r
- {\r
- return (Term_xtra_win_sound(v));\r
- }\r
-\r
- /* Process random events */\r
- case TERM_XTRA_BORED:\r
- {\r
- return (Term_xtra_win_event(0));\r
- }\r
-\r
- /* Process an event */\r
- case TERM_XTRA_EVENT:\r
- {\r
- return (Term_xtra_win_event(v));\r
- }\r
-\r
- /* Flush all events */\r
- case TERM_XTRA_FLUSH:\r
- {\r
- return (Term_xtra_win_flush());\r
- }\r
-\r
- /* Clear the screen */\r
- case TERM_XTRA_CLEAR:\r
- {\r
- return (Term_xtra_win_clear());\r
- }\r
-\r
- /* React to global changes */\r
- case TERM_XTRA_REACT:\r
- {\r
- return (Term_xtra_win_react());\r
- }\r
-\r
- /* Delay for some milliseconds */\r
- case TERM_XTRA_DELAY:\r
- {\r
- return (Term_xtra_win_delay(v));\r
- }\r
- }\r
-\r
- return 1;\r
-}\r
-\r
-\r
-\r
-/*\r
- * Low level graphics (Assumes valid input).\r
- *\r
- * Draw a "cursor" at (x,y), using a "yellow box".\r
- */\r
-static errr Term_curs_win(int x, int y)\r
-{\r
- term_data *td = (term_data*)(Term->data);\r
-\r
- RECT rc;\r
- HDC hdc;\r
-\r
- int tile_wid, tile_hgt;\r
-\r
- if (td->map_active)\r
- {\r
- tile_wid = td->map_tile_wid;\r
- tile_hgt = td->map_tile_hgt;\r
- }\r
- else\r
- {\r
- tile_wid = td->tile_wid;\r
- tile_hgt = td->tile_hgt;\r
- }\r
-\r
- /* Frame the grid */\r
- rc.left = x * tile_wid + td->size_ow1;\r
- rc.right = rc.left + tile_wid;\r
- rc.top = y * tile_hgt + td->size_oh1;\r
- rc.bottom = rc.top + tile_hgt;\r
-\r
- /* Cursor is done as a yellow "box" */\r
- hdc = GetDC(td->w);\r
- FrameRect(hdc, &rc, hbrYellow);\r
- ReleaseDC(td->w, hdc);\r
-\r
- /* Success */\r
- return 0;\r
-}\r
-\r
-\r
-/*\r
- * Low level graphics (Assumes valid input).\r
- *\r
- * Draw a "big cursor" at (x,y), using a "yellow box".\r
- */\r
-static errr Term_bigcurs_win(int x, int y)\r
-{\r
- term_data *td = (term_data*)(Term->data);\r
-\r
- RECT rc;\r
- HDC hdc;\r
-\r
- int tile_wid, tile_hgt;\r
-\r
- if (td->map_active)\r
- {\r
- /* Normal cursor in map window */\r
- Term_curs_win(x, y);\r
- return 0;\r
- }\r
- else\r
- {\r
- tile_wid = td->tile_wid;\r
- tile_hgt = td->tile_hgt;\r
- }\r
-\r
- /* Frame the grid */\r
- rc.left = x * tile_wid + td->size_ow1;\r
- rc.right = rc.left + 2 * tile_wid;\r
- rc.top = y * tile_hgt + td->size_oh1;\r
- rc.bottom = rc.top + tile_hgt;\r
-\r
- /* Cursor is done as a yellow "box" */\r
- hdc = GetDC(td->w);\r
- FrameRect(hdc, &rc, hbrYellow);\r
- ReleaseDC(td->w, hdc);\r
-\r
- /* Success */\r
- return 0;\r
-}\r
-\r
-\r
-/*\r
- * Low level graphics (Assumes valid input).\r
- *\r
- * Erase a "block" of "n" characters starting at (x,y).\r
- */\r
-static errr Term_wipe_win(int x, int y, int n)\r
-{\r
- term_data *td = (term_data*)(Term->data);\r
-\r
- HDC hdc;\r
- RECT rc;\r
-\r
- /* Rectangle to erase in client coords */\r
- rc.left = x * td->tile_wid + td->size_ow1;\r
- rc.right = rc.left + n * td->tile_wid;\r
- rc.top = y * td->tile_hgt + td->size_oh1;\r
- rc.bottom = rc.top + td->tile_hgt;\r
-\r
- hdc = GetDC(td->w);\r
- SetBkColor(hdc, RGB(0, 0, 0));\r
- SelectObject(hdc, td->font_id);\r
- /* bg */\r
- if (use_bg)\r
- DrawBG(hdc, &rc);\r
- else\r
- ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);\r
- ReleaseDC(td->w, hdc);\r
-\r
- /* Success */\r
- return 0;\r
-}\r
-\r
-\r
-/*\r
- * Low level graphics. Assumes valid input.\r
- *\r
- * Draw several ("n") chars, with an attr, at a given location.\r
- *\r
- * All "graphic" data is handled by "Term_pict_win()", below.\r
- *\r
- * One would think there is a more efficient method for telling a window\r
- * what color it should be using to draw with, but perhaps simply changing\r
- * it every time is not too inefficient. \r
- */\r
-static errr Term_text_win(int x, int y, int n, TERM_COLOR a, concptr s)\r
-{\r
- term_data *td = (term_data*)(Term->data);\r
- RECT rc;\r
- HDC hdc;\r
-\r
-#if 1 /* #ifdef JP */\r
- static HBITMAP WALL;\r
- static HBRUSH myBrush, oldBrush;\r
- static HPEN oldPen;\r
- static bool init_done = FALSE;\r
-\r
- if (!init_done){\r
- WALL = LoadBitmap(hInstance, AppName);\r
- myBrush = CreatePatternBrush(WALL);\r
- init_done = TRUE;\r
- }\r
-#endif\r
-\r
- /* Total rectangle */\r
- rc.left = x * td->tile_wid + td->size_ow1;\r
- rc.right = rc.left + n * td->tile_wid;\r
- rc.top = y * td->tile_hgt + td->size_oh1;\r
- rc.bottom = rc.top + td->tile_hgt;\r
-\r
- /* Acquire DC */\r
- hdc = GetDC(td->w);\r
-\r
- /* Background color */\r
- SetBkColor(hdc, RGB(0, 0, 0));\r
-\r
- /* Foreground color */\r
- if (colors16)\r
- {\r
- SetTextColor(hdc, PALETTEINDEX(win_pal[a]));\r
- }\r
- else if (paletted)\r
- {\r
- SetTextColor(hdc, win_clr[a&0x0F]);\r
- }\r
- else\r
- {\r
- SetTextColor(hdc, win_clr[a]);\r
- }\r
-\r
- /* Use the font */\r
- SelectObject(hdc, td->font_id);\r
- \r
- /* bg */\r
- if (use_bg) SetBkMode(hdc, TRANSPARENT);\r
-\r
- /* Bizarre size */\r
- if (td->bizarre ||\r
- (td->tile_hgt != td->font_hgt) ||\r
- (td->tile_wid != td->font_wid))\r
- {\r
- int i;\r
-\r
- /* Erase complete rectangle */\r
- ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);\r
- \r
- /* bg */\r
- if (use_bg) DrawBG(hdc, &rc);\r
-\r
- /* New rectangle */\r
- rc.left += ((td->tile_wid - td->font_wid) / 2);\r
- rc.right = rc.left + td->font_wid;\r
- rc.top += ((td->tile_hgt - td->font_hgt) / 2);\r
- rc.bottom = rc.top + td->font_hgt;\r
-\r
- /* Dump each character */\r
- for (i = 0; i < n; i++)\r
- {\r
-#ifdef JP\r
- if (use_bigtile && *(s+i)=="■"[0] && *(s+i+1)=="■"[1])\r
- {\r
- rc.right += td->font_wid;\r
-\r
- oldBrush = SelectObject(hdc, myBrush);\r
- oldPen = SelectObject(hdc, GetStockObject(NULL_PEN) );\r
-\r
- /* Dump the wall */\r
- Rectangle(hdc, rc.left, rc.top, rc.right+1, rc.bottom+1);\r
-\r
- SelectObject(hdc, oldBrush);\r
- SelectObject(hdc, oldPen);\r
- rc.right -= td->font_wid;\r
-\r
- /* Advance */\r
- i++;\r
- rc.left += 2 * td->tile_wid;\r
- rc.right += 2 * td->tile_wid;\r
- }\r
- else if ( iskanji(*(s+i)) ) /* 2バイト文字 */\r
- {\r
- rc.right += td->font_wid;\r
- /* Dump the text */\r
- ExtTextOut(hdc, rc.left, rc.top, ETO_CLIPPED, &rc,\r
- s+i, 2, NULL);\r
- rc.right -= td->font_wid;\r
-\r
- /* Advance */\r
- i++;\r
- rc.left += 2 * td->tile_wid;\r
- rc.right += 2 * td->tile_wid;\r
- } else if (*(s+i)==127){\r
- oldBrush = SelectObject(hdc, myBrush);\r
- oldPen = SelectObject(hdc, GetStockObject(NULL_PEN) );\r
-\r
- /* Dump the wall */\r
- Rectangle(hdc, rc.left, rc.top, rc.right+1, rc.bottom+1);\r
-\r
- SelectObject(hdc, oldBrush);\r
- SelectObject(hdc, oldPen);\r
-\r
- /* Advance */\r
- rc.left += td->tile_wid;\r
- rc.right += td->tile_wid;\r
- } else {\r
- /* Dump the text */\r
- ExtTextOut(hdc, rc.left, rc.top, ETO_CLIPPED, &rc, s+i, 1, NULL);\r
-\r
- /* Advance */\r
- rc.left += td->tile_wid;\r
- rc.right += td->tile_wid;\r
- }\r
-#else\r
-#if 1\r
- if (*(s+i)==127){\r
- oldBrush = SelectObject(hdc, myBrush);\r
- oldPen = SelectObject(hdc, GetStockObject(NULL_PEN) );\r
-\r
- /* Dump the wall */\r
- Rectangle(hdc, rc.left, rc.top, rc.right+1, rc.bottom+1);\r
-\r
- SelectObject(hdc, oldBrush);\r
- SelectObject(hdc, oldPen);\r
-\r
- /* Advance */\r
- rc.left += td->tile_wid;\r
- rc.right += td->tile_wid;\r
- } else {\r
- /* Dump the text */\r
- ExtTextOut(hdc, rc.left, rc.top, ETO_CLIPPED, &rc,\r
- s+i, 1, NULL);\r
-\r
- /* Advance */\r
- rc.left += td->tile_wid;\r
- rc.right += td->tile_wid;\r
- }\r
-#else\r
- /* Dump the text */\r
- ExtTextOut(hdc, rc.left, rc.top, 0, &rc,\r
- s+i, 1, NULL);\r
-\r
- /* Advance */\r
- rc.left += td->tile_wid;\r
- rc.right += td->tile_wid;\r
-#endif\r
-#endif\r
-\r
- }\r
- }\r
-\r
- /* Normal size */\r
- else\r
- {\r
- /* Dump the text */\r
- ExtTextOut(hdc, rc.left, rc.top, ETO_OPAQUE | ETO_CLIPPED, &rc,\r
- s, n, NULL);\r
- }\r
-\r
- /* Release DC */\r
- ReleaseDC(td->w, hdc);\r
-\r
- /* Success */\r
- return 0;\r
-}\r
-\r
-\r
-/*\r
- * Low level graphics. Assumes valid input.\r
- *\r
- * Draw an array of "special" attr/char pairs at the given location.\r
- *\r
- * We use the "Term_pict_win()" function for "graphic" data, which are\r
- * encoded by setting the "high-bits" of both the "attr" and the "char"\r
- * data. We use the "attr" to represent the "row" of the main bitmap,\r
- * and the "char" to represent the "col" of the main bitmap. The use\r
- * of this function is induced by the "higher_pict" flag.\r
- *\r
- * If "graphics" is not available, we simply "wipe" the given grids.\r
- */\r
-static errr Term_pict_win(TERM_LEN x, TERM_LEN y, int n, const TERM_COLOR *ap, concptr cp, const TERM_COLOR *tap, concptr tcp)\r
-{\r
- term_data *td = (term_data*)(Term->data);\r
-\r
-#ifdef USE_GRAPHICS\r
-\r
- int i;\r
- TERM_LEN x1, y1, w1, h1, tw1, th1;\r
- TERM_LEN x2, y2, w2, h2, tw2 = 0;\r
- TERM_LEN x3, y3;\r
-\r
- HDC hdcMask = NULL;\r
-\r
- HDC hdc;\r
- HDC hdcSrc;\r
- HBITMAP hbmSrcOld;\r
-\r
- /* Paranoia */\r
- if (!use_graphics)\r
- {\r
- /* Erase the grids */\r
- return (Term_wipe_win(x, y, n));\r
- }\r
-\r
- /* Size of bitmap cell */\r
- w1 = infGraph.CellWidth;\r
- h1 = infGraph.CellHeight;\r
- tw1 = infGraph.TileWidth;\r
- th1 = infGraph.TileHeight;\r
-\r
- /* Size of window cell */\r
- if (td->map_active)\r
- {\r
- w2 = td->map_tile_wid;\r
- h2 = td->map_tile_hgt;\r
- }\r
- else\r
- {\r
- w2 = td->tile_wid;\r
- h2 = td->tile_hgt;\r
- tw2 = w2;\r
-\r
- /* big tile mode */\r
- if (use_bigtile) tw2 *= 2;\r
- }\r
-\r
- /* Location of window cell */\r
- x2 = x * w2 + td->size_ow1 + infGraph.OffsetX;\r
- y2 = y * h2 + td->size_oh1 + infGraph.OffsetY;\r
-\r
- /* Info */\r
- hdc = GetDC(td->w);\r
-\r
- /* More info */\r
- hdcSrc = CreateCompatibleDC(hdc);\r
- hbmSrcOld = SelectObject(hdcSrc, infGraph.hBitmap);\r
-\r
- if (arg_graphics == GRAPHICS_ADAM_BOLT || arg_graphics == GRAPHICS_HENGBAND)\r
- {\r
- hdcMask = CreateCompatibleDC(hdc);\r
- SelectObject(hdcMask, infMask.hBitmap);\r
- }\r
-\r
- /* Draw attr/char pairs */\r
- for (i = 0; i < n; i++, x2 += w2)\r
- {\r
- TERM_COLOR a = ap[i];\r
- char c = cp[i];\r
-\r
-\r
- /* Extract picture */\r
- int row = (a & 0x7F);\r
- int col = (c & 0x7F);\r
-\r
- /* Location of bitmap cell */\r
- x1 = col * w1;\r
- y1 = row * h1;\r
-\r
- if (arg_graphics == GRAPHICS_ADAM_BOLT || arg_graphics == GRAPHICS_HENGBAND)\r
- {\r
- x3 = (tcp[i] & 0x7F) * w1;\r
- y3 = (tap[i] & 0x7F) * h1;\r
- tw2 = tw2 * w1 / tw1;\r
- h2 = h2 * h1 / th1;\r
-\r
- /* Perfect size */\r
- if ((tw1 == tw2) && (th1 == h2))\r
- {\r
- /* Copy the terrain picture from the bitmap to the window */\r
- BitBlt(hdc, x2, y2, tw2, h2, hdcSrc, x3, y3, SRCCOPY);\r
-\r
- /* Mask out the tile */\r
- BitBlt(hdc, x2, y2, tw2, h2, hdcMask, x1, y1, SRCAND);\r
-\r
- /* Draw the tile */\r
- BitBlt(hdc, x2, y2, tw2, h2, hdcSrc, x1, y1, SRCPAINT);\r
- }\r
-\r
- /* Need to stretch */\r
- else\r
- {\r
- /* Set the correct mode for stretching the tiles */\r
- SetStretchBltMode(hdc, COLORONCOLOR);\r
-\r
- /* Copy the terrain picture from the bitmap to the window */\r
- StretchBlt(hdc, x2, y2, tw2, h2, hdcMask, x3, y3, w1, h1, SRCAND);\r
-\r
- StretchBlt(hdc, x2, y2, tw2, h2, hdcSrc, x3, y3, w1, h1, SRCPAINT);\r
-\r
- /* Only draw if terrain and overlay are different */\r
- if ((x1 != x3) || (y1 != y3))\r
- {\r
- /* Mask out the tile */\r
- StretchBlt(hdc, x2, y2, tw2, h2, hdcMask, x1, y1, w1, h1, SRCAND);\r
-\r
- /* Draw the tile */\r
- StretchBlt(hdc, x2, y2, tw2, h2, hdcSrc, x1, y1, w1, h1, SRCPAINT);\r
- }\r
- }\r
- }\r
- else\r
- {\r
- /* Perfect size */\r
- if ((w1 == tw2) && (h1 == h2))\r
- {\r
- /* Copy the picture from the bitmap to the window */\r
- BitBlt(hdc, x2, y2, tw2, h2, hdcSrc, x1, y1, SRCCOPY);\r
- }\r
-\r
- /* Need to stretch */\r
- else\r
- {\r
- /* Set the correct mode for stretching the tiles */\r
- SetStretchBltMode(hdc, COLORONCOLOR);\r
-\r
- /* Copy the picture from the bitmap to the window */\r
- StretchBlt(hdc, x2, y2, tw2, h2, hdcSrc, x1, y1, w1, h1, SRCCOPY);\r
- }\r
- }\r
- }\r
-\r
- /* Release */\r
- SelectObject(hdcSrc, hbmSrcOld);\r
- DeleteDC(hdcSrc);\r
-\r
- if (arg_graphics == GRAPHICS_ADAM_BOLT || arg_graphics == GRAPHICS_HENGBAND)\r
- {\r
- /* Release */\r
- SelectObject(hdcMask, hbmSrcOld);\r
- DeleteDC(hdcMask);\r
- }\r
-\r
- /* Release */\r
- ReleaseDC(td->w, hdc);\r
-\r
-#else /* USE_GRAPHICS */\r
-\r
- /* Just erase this grid */\r
- return (Term_wipe_win(x, y, n));\r
-\r
-#endif /* USE_GRAPHICS */\r
-\r
- /* Success */\r
- return 0;\r
-}\r
-\r
-\r
-static void windows_map(void)\r
-{\r
- term_data *td = &data[0];\r
- TERM_COLOR a;\r
- char c;\r
- TERM_LEN x, min_x, max_x;\r
- TERM_LEN y, min_y, max_y;\r
-\r
- TERM_COLOR ta;\r
- char tc;\r
-\r
- /* Only in graphics mode */\r
- if (!use_graphics) return;\r
- Term_xtra_win_clear();\r
-\r
- td->map_tile_wid = (td->tile_wid * td->cols) / MAX_WID;\r
- td->map_tile_hgt = (td->tile_hgt * td->rows) / MAX_HGT;\r
- td->map_active = TRUE;\r
-\r
- {\r
- min_x = 0;\r
- min_y = 0;\r
- max_x = cur_wid;\r
- max_y = cur_hgt;\r
- }\r
-\r
- /* Draw the map */\r
- for (x = min_x; x < max_x; x++)\r
- {\r
- for (y = min_y; y < max_y; y++)\r
- {\r
- map_info(y, x, &a, (char*)&c, &ta, (char*)&tc);\r
-\r
- /* Ignore non-graphics */\r
- if ((a & 0x80) && (c & 0x80))\r
- {\r
- Term_pict_win(x - min_x, y - min_y, 1, &a, &c, &ta, &tc);\r
- }\r
- }\r
- }\r
-\r
- /* Hilite the player */\r
- Term_curs_win(p_ptr->x - min_x, p_ptr->y - min_y);\r
-\r
- /* Wait for a keypress, flush key buffer */\r
- Term_inkey(&c, TRUE, TRUE);\r
- Term_flush();\r
-\r
- /* Switch off the map display */\r
- td->map_active = FALSE;\r
-\r
- /* Restore screen */\r
- Term_xtra_win_clear();\r
- Term_redraw();\r
-}\r
-\r
-\r
-/*** Other routines ***/\r
-\r
-\r
-/*\r
- * Create and initialize a "term_data" given a title\r
- */\r
-static void term_data_link(term_data *td)\r
-{\r
- term *t = &td->t;\r
-\r
- /* Initialize the term */\r
- term_init(t, td->cols, td->rows, td->keys);\r
-\r
- /* Use a "software" cursor */\r
- t->soft_cursor = TRUE;\r
-\r
- /* Use "Term_pict" for "graphic" data */\r
- t->higher_pict = TRUE;\r
-\r
- /* Erase with "white space" */\r
- t->attr_blank = TERM_WHITE;\r
- t->char_blank = ' ';\r
-\r
-#if 0\r
- /* Prepare the init/nuke hooks */\r
- t->init_hook = Term_init_win;\r
- t->nuke_hook = Term_nuke_win;\r
-#endif\r
-\r
- /* Prepare the template hooks */\r
- t->user_hook = Term_user_win;\r
- t->xtra_hook = Term_xtra_win;\r
- t->curs_hook = Term_curs_win;\r
- t->bigcurs_hook = Term_bigcurs_win;\r
- t->wipe_hook = Term_wipe_win;\r
- t->text_hook = Term_text_win;\r
- t->pict_hook = Term_pict_win;\r
-\r
- /* Remember where we came from */\r
- t->data = (vptr)(td);\r
-}\r
-\r
-\r
-/*\r
- * Create the windows\r
- *\r
- * First, instantiate the "default" values, then read the "ini_file"\r
- * to over-ride selected values, then create the windows, and fonts.\r
- *\r
- * Must use SW_SHOW not SW_SHOWNA, since on 256 color display\r
- * must make active to realize the palette. \r
- */\r
-static void init_windows(void)\r
-{\r
- int i;\r
-\r
- term_data *td;\r
-\r
-#if 0 /* #ifndef JP */\r
- char buf[1024];\r
-#endif\r
-\r
- /* Main window */\r
- td = &data[0];\r
- WIPE(td, term_data);\r
-#ifdef JP\r
- td->s = "変愚蛮怒";\r
-#else\r
- td->s = angband_term_name[0];\r
-#endif\r
-\r
- td->keys = 1024;\r
- td->rows = 24;\r
- td->cols = 80;\r
- td->visible = TRUE;\r
- td->size_ow1 = 2;\r
- td->size_ow2 = 2;\r
- td->size_oh1 = 2;\r
- td->size_oh2 = 2;\r
- td->pos_x = 7 * 30;\r
- td->pos_y = 7 * 20;\r
- td->posfix = FALSE;\r
-#if 1 /* #ifdef JP */\r
- td->bizarre = TRUE;\r
-#endif\r
- /* Sub windows */\r
- for (i = 1; i < MAX_TERM_DATA; i++)\r
- {\r
- td = &data[i];\r
- WIPE(td, term_data);\r
- td->s = angband_term_name[i];\r
- td->keys = 16;\r
- td->rows = 24;\r
- td->cols = 80;\r
- td->visible = FALSE;\r
- td->size_ow1 = 1;\r
- td->size_ow2 = 1;\r
- td->size_oh1 = 1;\r
- td->size_oh2 = 1;\r
- td->pos_x = (7 - i) * 30;\r
- td->pos_y = (7 - i) * 20;\r
- td->posfix = FALSE;\r
-#if 1 /* #ifdef JP */\r
- td->bizarre = TRUE;\r
-#endif\r
- }\r
-\r
-\r
- /* Load prefs */\r
- load_prefs();\r
-\r
-\r
- /* Main window (need these before term_getsize gets called) */\r
- td = &data[0];\r
- td->dwStyle = (WS_OVERLAPPED | WS_THICKFRAME | WS_SYSMENU |\r
- WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CAPTION |\r
- WS_VISIBLE);\r
- td->dwExStyle = 0;\r
- td->visible = TRUE;\r
-\r
- /* Sub windows (need these before term_getsize gets called) */\r
- for (i = 1; i < MAX_TERM_DATA; i++)\r
- {\r
- td = &data[i];\r
- td->dwStyle = (WS_OVERLAPPED | WS_THICKFRAME | WS_SYSMENU);\r
- td->dwExStyle = (WS_EX_TOOLWINDOW);\r
- }\r
-\r
-\r
- /* All windows */\r
- for (i = 0; i < MAX_TERM_DATA; i++)\r
- {\r
- td = &data[i];\r
-\r
-#if 1 /* #ifdef JP */\r
- strncpy(td->lf.lfFaceName, td->font_want, LF_FACESIZE);\r
- td->lf.lfCharSet = DEFAULT_CHARSET;\r
- td->lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;\r
- /* Activate the chosen font */\r
- term_force_font(td, NULL);\r
- if(!td->tile_wid) td->tile_wid = td->font_wid;\r
- if(!td->tile_hgt) td->tile_hgt = td->font_hgt;\r
-#else\r
- /* Access the standard font file */\r
- path_build(buf, sizeof(buf), ANGBAND_DIR_XTRA_FONT, td->font_want);\r
-\r
- /* Activate the chosen font */\r
- if (term_force_font(td, buf))\r
- {\r
- /* Access the standard font file */\r
- path_build(buf, sizeof(buf), ANGBAND_DIR_XTRA_FONT, "8X13.FON");\r
-\r
- /* Force the use of that font */\r
- (void)term_force_font(td, buf);\r
-\r
- td->tile_wid = 8;\r
- td->tile_hgt = 13;\r
-\r
- /* Assume not bizarre */\r
- td->bizarre = FALSE;\r
- }\r
-#endif\r
-\r
-\r
- /* Analyze the font */\r
- term_getsize(td);\r
-\r
- /* Resize the window */\r
- term_window_resize(td);\r
- }\r
-\r
-\r
- /* Sub windows (reverse order) */\r
- for (i = MAX_TERM_DATA - 1; i >= 1; --i)\r
- {\r
- td = &data[i];\r
-\r
- my_td = td;\r
- td->w = CreateWindowEx(td->dwExStyle, AngList,\r
- td->s, td->dwStyle,\r
- td->pos_x, td->pos_y,\r
- td->size_wid, td->size_hgt,\r
- HWND_DESKTOP, NULL, hInstance, NULL);\r
- my_td = NULL;\r
- if (!td->w) quit(_("サブウィンドウに作成に失敗しました", "Failed to create sub-window"));\r
-\r
- if (td->visible)\r
- {\r
- td->size_hack = TRUE;\r
- ShowWindow(td->w, SW_SHOW);\r
- td->size_hack = FALSE;\r
- }\r
-\r
- term_data_link(td);\r
- angband_term[i] = &td->t;\r
-\r
- if (td->visible)\r
- {\r
- /* Activate the window */\r
- SetActiveWindow(td->w);\r
- }\r
-\r
- if (data[i].posfix)\r
- {\r
- term_window_pos(&data[i], HWND_TOPMOST);\r
- }\r
- else\r
- {\r
- term_window_pos(&data[i], td->w);\r
- }\r
- }\r
-\r
-\r
- /* Main window */\r
- td = &data[0];\r
-\r
- /* Main window */\r
- my_td = td;\r
- td->w = CreateWindowEx(td->dwExStyle, AppName,\r
- td->s, td->dwStyle,\r
- td->pos_x, td->pos_y,\r
- td->size_wid, td->size_hgt,\r
- HWND_DESKTOP, NULL, hInstance, NULL);\r
- my_td = NULL;\r
- if (!td->w) quit(_("メインウィンドウの作成に失敗しました", "Failed to create Angband window"));\r
-\r
- term_data_link(td);\r
- angband_term[0] = &td->t;\r
- normsize.x = td->cols;\r
- normsize.y = td->rows;\r
-\r
- /* Activate the main window */\r
- if (win_maximized) ShowWindow(td->w, SW_SHOWMAXIMIZED);\r
- else ShowWindow(td->w, SW_SHOW);\r
-\r
- /* Bring main window back to top */\r
- SetWindowPos(td->w, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);\r
-\r
-\r
- /* New palette */\r
- (void)new_palette();\r
-\r
-\r
- /* Create a "brush" for drawing the "cursor" */\r
- hbrYellow = CreateSolidBrush(win_clr[TERM_YELLOW]);\r
-\r
-\r
- /* Process pending messages */\r
- (void)Term_xtra_win_flush();\r
-}\r
-\r
-\r
-\r
-/*\r
- * Prepare the menus\r
- */\r
-static void setup_menus(void)\r
-{\r
- int i;\r
-\r
- HMENU hm = GetMenu(data[0].w);\r
-\r
-\r
- /* Menu "File", Disable all */\r
- EnableMenuItem(hm, IDM_FILE_NEW,\r
- MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);\r
- EnableMenuItem(hm, IDM_FILE_OPEN,\r
- MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);\r
- EnableMenuItem(hm, IDM_FILE_SAVE,\r
- MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);\r
- EnableMenuItem(hm, IDM_FILE_EXIT,\r
- MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);\r
- EnableMenuItem(hm, IDM_FILE_SCORE,\r
- MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);\r
-\r
-\r
- /* No character available */\r
- if (!character_generated)\r
- {\r
- /* Menu "File", Item "New" */\r
- EnableMenuItem(hm, IDM_FILE_NEW, MF_BYCOMMAND | MF_ENABLED);\r
-\r
- /* Menu "File", Item "Open" */\r
- EnableMenuItem(hm, IDM_FILE_OPEN, MF_BYCOMMAND | MF_ENABLED);\r
- }\r
-\r
- /* A character available */\r
- if (character_generated)\r
- {\r
- /* Menu "File", Item "Save" */\r
- EnableMenuItem(hm, IDM_FILE_SAVE,\r
- MF_BYCOMMAND | MF_ENABLED);\r
- }\r
-\r
- /* Menu "File", Item "Exit" */\r
- EnableMenuItem(hm, IDM_FILE_EXIT,\r
- MF_BYCOMMAND | MF_ENABLED);\r
-\r
- EnableMenuItem(hm, IDM_FILE_SCORE,\r
- MF_BYCOMMAND | MF_ENABLED);\r
-\r
-\r
- /* Menu "Window::Visibility" */\r
- for (i = 0; i < MAX_TERM_DATA; i++)\r
- {\r
- EnableMenuItem(hm, IDM_WINDOW_VIS_0 + i,\r
- MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);\r
-\r
- CheckMenuItem(hm, IDM_WINDOW_VIS_0 + i,\r
- (data[i].visible ? MF_CHECKED : MF_UNCHECKED));\r
-\r
- EnableMenuItem(hm, IDM_WINDOW_VIS_0 + i,\r
- MF_BYCOMMAND | MF_ENABLED);\r
- }\r
-\r
- /* Menu "Window::Font" */\r
- for (i = 0; i < MAX_TERM_DATA; i++)\r
- {\r
- EnableMenuItem(hm, IDM_WINDOW_FONT_0 + i,\r
- MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);\r
-\r
- if (data[i].visible)\r
- {\r
- EnableMenuItem(hm, IDM_WINDOW_FONT_0 + i,\r
- MF_BYCOMMAND | MF_ENABLED);\r
- }\r
- }\r
-\r
- /* Menu "Window::Window Position Fix" */\r
- for (i = 0; i < MAX_TERM_DATA; i++)\r
- {\r
- EnableMenuItem(hm, IDM_WINDOW_POS_0 + i,\r
- MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);\r
-\r
- CheckMenuItem(hm, IDM_WINDOW_POS_0 + i,\r
- (data[i].posfix ? MF_CHECKED : MF_UNCHECKED));\r
-\r
- if (data[i].visible)\r
- {\r
- EnableMenuItem(hm, IDM_WINDOW_POS_0 + i,\r
- MF_BYCOMMAND | MF_ENABLED);\r
- }\r
- }\r
-\r
- /* Menu "Window::Bizarre Display" */\r
- for (i = 0; i < MAX_TERM_DATA; i++)\r
- {\r
- EnableMenuItem(hm, IDM_WINDOW_BIZ_0 + i,\r
- MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);\r
-\r
- CheckMenuItem(hm, IDM_WINDOW_BIZ_0 + i,\r
- (data[i].bizarre ? MF_CHECKED : MF_UNCHECKED));\r
-\r
- if (data[i].visible)\r
- {\r
- EnableMenuItem(hm, IDM_WINDOW_BIZ_0 + i,\r
- MF_BYCOMMAND | MF_ENABLED);\r
-\r
- }\r
- }\r
-\r
- /* Menu "Window::Increase Tile Width" */\r
- for (i = 0; i < MAX_TERM_DATA; i++)\r
- {\r
- EnableMenuItem(hm, IDM_WINDOW_I_WID_0 + i,\r
- MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);\r
-\r
- if (data[i].visible)\r
- {\r
- EnableMenuItem(hm, IDM_WINDOW_I_WID_0 + i,\r
- MF_BYCOMMAND | MF_ENABLED);\r
-\r
- }\r
- }\r
-\r
- /* Menu "Window::Decrease Tile Width" */\r
- for (i = 0; i < MAX_TERM_DATA; i++)\r
- {\r
- EnableMenuItem(hm, IDM_WINDOW_D_WID_0 + i,\r
- MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);\r
-\r
- if (data[i].visible)\r
- {\r
- EnableMenuItem(hm, IDM_WINDOW_D_WID_0 + i,\r
- MF_BYCOMMAND | MF_ENABLED);\r
-\r
- }\r
- }\r
-\r
- /* Menu "Window::Increase Tile Height" */\r
- for (i = 0; i < MAX_TERM_DATA; i++)\r
- {\r
- EnableMenuItem(hm, IDM_WINDOW_I_HGT_0 + i,\r
- MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);\r
-\r
- if (data[i].visible)\r
- {\r
- EnableMenuItem(hm, IDM_WINDOW_I_HGT_0 + i,\r
- MF_BYCOMMAND | MF_ENABLED);\r
-\r
- }\r
- }\r
-\r
- /* Menu "Window::Decrease Tile Height" */\r
- for (i = 0; i < MAX_TERM_DATA; i++)\r
- {\r
- EnableMenuItem(hm, IDM_WINDOW_D_HGT_0 + i,\r
- MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);\r
-\r
- if (data[i].visible)\r
- {\r
- EnableMenuItem(hm, IDM_WINDOW_D_HGT_0 + i,\r
- MF_BYCOMMAND | MF_ENABLED);\r
-\r
- }\r
- }\r
-\r
- /* Menu "Options", disable all */\r
- EnableMenuItem(hm, IDM_OPTIONS_NO_GRAPHICS,\r
- MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);\r
- EnableMenuItem(hm, IDM_OPTIONS_OLD_GRAPHICS,\r
- MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);\r
- EnableMenuItem(hm, IDM_OPTIONS_NEW_GRAPHICS,\r
- MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);\r
- EnableMenuItem(hm, IDM_OPTIONS_BIGTILE,\r
- MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);\r
- EnableMenuItem(hm, IDM_OPTIONS_SOUND,\r
- MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);\r
-#ifndef JP\r
- EnableMenuItem(hm, IDM_OPTIONS_SAVER,\r
- MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);\r
-#endif\r
-\r
- /* Menu "Options", Item "Map" */\r
- if (use_graphics != GRAPHICS_NONE)\r
- EnableMenuItem(GetMenu(data[0].w), IDM_OPTIONS_MAP, MF_BYCOMMAND | MF_ENABLED);\r
- else\r
- EnableMenuItem(GetMenu(data[0].w), IDM_OPTIONS_MAP,\r
- MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);\r
-\r
- /* Menu "Options", update all */\r
- CheckMenuItem(hm, IDM_OPTIONS_NO_GRAPHICS,\r
- (arg_graphics == GRAPHICS_NONE ? MF_CHECKED : MF_UNCHECKED));\r
- CheckMenuItem(hm, IDM_OPTIONS_OLD_GRAPHICS,\r
- (arg_graphics == GRAPHICS_ORIGINAL ? MF_CHECKED : MF_UNCHECKED));\r
- CheckMenuItem(hm, IDM_OPTIONS_NEW_GRAPHICS,\r
- (arg_graphics == GRAPHICS_ADAM_BOLT ? MF_CHECKED : MF_UNCHECKED));\r
- CheckMenuItem(hm, IDM_OPTIONS_NEW2_GRAPHICS,\r
- (arg_graphics == GRAPHICS_HENGBAND ? MF_CHECKED : MF_UNCHECKED));\r
- CheckMenuItem(hm, IDM_OPTIONS_BIGTILE,\r
- (arg_bigtile ? MF_CHECKED : MF_UNCHECKED));\r
- CheckMenuItem(hm, IDM_OPTIONS_MUSIC,\r
- (arg_music ? MF_CHECKED : MF_UNCHECKED));\r
- CheckMenuItem(hm, IDM_OPTIONS_SOUND,\r
- (arg_sound ? MF_CHECKED : MF_UNCHECKED));\r
- CheckMenuItem(hm, IDM_OPTIONS_BG,\r
- (use_bg ? MF_CHECKED : MF_UNCHECKED));\r
-#ifndef JP\r
- CheckMenuItem(hm, IDM_OPTIONS_SAVER,\r
- (hwndSaver ? MF_CHECKED : MF_UNCHECKED));\r
-#endif\r
-\r
-#ifdef USE_GRAPHICS\r
- /* Menu "Options", Item "Graphics" */\r
- EnableMenuItem(hm, IDM_OPTIONS_NO_GRAPHICS, MF_ENABLED);\r
- /* Menu "Options", Item "Graphics" */\r
- EnableMenuItem(hm, IDM_OPTIONS_OLD_GRAPHICS, MF_ENABLED);\r
- /* Menu "Options", Item "Graphics" */\r
- EnableMenuItem(hm, IDM_OPTIONS_NEW_GRAPHICS, MF_ENABLED);\r
- /* Menu "Options", Item "Graphics" */\r
- EnableMenuItem(hm, IDM_OPTIONS_BIGTILE, MF_ENABLED);\r
-#endif /* USE_GRAPHICS */\r
-\r
-#ifdef USE_SOUND\r
- /* Menu "Options", Item "Sound" */\r
- EnableMenuItem(hm, IDM_OPTIONS_SOUND, MF_ENABLED);\r
-#endif /* USE_SOUND */\r
-\r
-#ifdef USE_SAVER\r
- /* Menu "Options", Item "ScreenSaver" */\r
- EnableMenuItem(hm, IDM_OPTIONS_SAVER,\r
- MF_BYCOMMAND | MF_ENABLED);\r
-#endif /* USE_SAVER */\r
-}\r
-\r
-\r
-/*\r
- * Check for double clicked (or dragged) savefile\r
- *\r
- * Apparently, Windows copies the entire filename into the first\r
- * piece of the "command line string". Perhaps we should extract\r
- * the "basename" of that filename and append it to the "save" dir.\r
- */\r
-static void check_for_save_file(LPSTR cmd_line)\r
-{\r
- char *s;\r
-\r
- /* First arg */\r
- s = cmd_line;\r
-\r
- /* No args */\r
- if (!*s) return;\r
-\r
- /* Extract filename */\r
- strcat(savefile, s);\r
-\r
- /* Validate the file */\r
- validate_file(savefile);\r
-\r
- /* Game in progress */\r
- game_in_progress = TRUE;\r
-\r
- /* Play game */\r
- play_game(FALSE);\r
-}\r
-\r
-\r
-/*\r
- * Process a menu command\r
- */\r
-static void process_menus(WORD wCmd)\r
-{\r
- int i;\r
-\r
- term_data *td;\r
-\r
- OPENFILENAME ofn;\r
-\r
- /* Analyze */\r
- switch (wCmd)\r
- {\r
- /* New game */\r
- case IDM_FILE_NEW:\r
- {\r
- if (!initialized)\r
- {\r
- plog(_("まだ初期化中です...", "You cannot do that yet..."));\r
- }\r
- else if (game_in_progress)\r
- {\r
- plog(_("プレイ中は新しいゲームを始めることができません!", "You can't start a new game while you're still playing!"));\r
- }\r
- else\r
- {\r
- game_in_progress = TRUE;\r
- Term_flush();\r
- play_game(TRUE);\r
- quit(NULL);\r
- }\r
- break;\r
- }\r
-\r
- /* Open game */\r
- case IDM_FILE_OPEN:\r
- {\r
- if (!initialized)\r
- {\r
- plog(_("まだ初期化中です...", "You cannot do that yet..."));\r
- }\r
- else if (game_in_progress)\r
- {\r
- plog(_("プレイ中はゲームをロードすることができません!", "You can't open a new game while you're still playing!"));\r
- }\r
- else\r
- {\r
- memset(&ofn, 0, sizeof(ofn));\r
- ofn.lStructSize = sizeof(ofn);\r
- ofn.hwndOwner = data[0].w;\r
- ofn.lpstrFilter = "Save Files (*.)\0*\0";\r
- ofn.nFilterIndex = 1;\r
- ofn.lpstrFile = savefile;\r
- ofn.nMaxFile = 1024;\r
- ofn.lpstrInitialDir = ANGBAND_DIR_SAVE;\r
- ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR | OFN_HIDEREADONLY;\r
-\r
- if (GetOpenFileName(&ofn))\r
- {\r
- /* Load 'savefile' */\r
- validate_file(savefile);\r
- game_in_progress = TRUE;\r
- Term_flush();\r
- play_game(FALSE);\r
- quit(NULL);\r
- }\r
- }\r
- break;\r
- }\r
-\r
- /* Save game */\r
- case IDM_FILE_SAVE:\r
- {\r
- if (game_in_progress && character_generated)\r
- {\r
- /* Paranoia */\r
- if (!can_save)\r
- {\r
- plog(_("今はセーブすることは出来ません。", "You may not do that right now."));\r
- break;\r
- }\r
-\r
- /* Hack -- Forget messages */\r
- msg_flag = FALSE;\r
-\r
- /* Save the game */\r
-#ifdef ZANGBAND\r
- do_cmd_save_game(FALSE);\r
-#else /* ZANGBAND */\r
- do_cmd_save_game();\r
-#endif /* ZANGBAND */\r
- }\r
- else\r
- {\r
- plog(_("今、セーブすることは出来ません。", "You may not do that right now."));\r
- }\r
- break;\r
- }\r
-\r
- /* Exit */\r
- case IDM_FILE_EXIT:\r
- {\r
- if (game_in_progress && character_generated)\r
- {\r
- /* Paranoia */\r
- if (!can_save)\r
- {\r
- plog(_("今は終了できません。", "You may not do that right now."));\r
- break;\r
- }\r
-\r
- /* Hack -- Forget messages */\r
- msg_flag = FALSE;\r
-\r
- forget_lite();\r
- forget_view();\r
- clear_mon_lite();\r
-\r
- /* Save the game */\r
-#ifdef ZANGBAND\r
- /* do_cmd_save_game(FALSE); */\r
-#else /* ZANGBAND */\r
- /* do_cmd_save_game(); */\r
-#endif /* ZANGBAND */\r
- Term_key_push(SPECIAL_KEY_QUIT);\r
- break;\r
- }\r
- quit(NULL);\r
- break;\r
- }\r
-\r
- /* Show scores */\r
- case IDM_FILE_SCORE:\r
- {\r
- char buf[1024];\r
-\r
- /* Build the filename */\r
- path_build(buf, sizeof(buf), ANGBAND_DIR_APEX, "scores.raw");\r
-\r
- /* Open the binary high score file, for reading */\r
- highscore_fd = fd_open(buf, O_RDONLY);\r
-\r
- /* Paranoia -- No score file */\r
- if (highscore_fd < 0)\r
- {\r
- msg_print("Score file unavailable.");\r
- }\r
- else\r
- {\r
- screen_save();\r
- Term_clear();\r
-\r
- /* Display the scores */\r
- display_scores_aux(0, MAX_HISCORES, -1, NULL);\r
-\r
- /* Shut the high score file */\r
- (void)fd_close(highscore_fd);\r
-\r
- /* Forget the high score fd */\r
- highscore_fd = -1;\r
- screen_load();\r
-\r
- /* Hack - Flush it */\r
- Term_fresh();\r
- }\r
-\r
- break;\r
- }\r
-\r
- /* Open game */\r
- case IDM_FILE_MOVIE:\r
- {\r
- if (!initialized)\r
- {\r
- plog(_("まだ初期化中です...", "You cannot do that yet..."));\r
- }\r
- else if (game_in_progress)\r
- {\r
- plog(_("プレイ中はムービーをロードすることができません!", "You can't open a movie while you're playing!"));\r
- }\r
- else\r
- {\r
- memset(&ofn, 0, sizeof(ofn));\r
- ofn.lStructSize = sizeof(ofn);\r
- ofn.hwndOwner = data[0].w;\r
- ofn.lpstrFilter = "Angband Movie Files (*.amv)\0*.amv\0";\r
- ofn.nFilterIndex = 1;\r
- ofn.lpstrFile = savefile;\r
- ofn.nMaxFile = 1024;\r
- ofn.lpstrInitialDir = ANGBAND_DIR_USER;\r
- ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;\r
-\r
- if (GetOpenFileName(&ofn))\r
- {\r
- /* Load 'savefile' */\r
- prepare_browse_movie_aux(savefile);\r
- play_game(FALSE);\r
- quit(NULL);\r
- return;\r
- }\r
- }\r
- break;\r
- }\r
-\r
-\r
- case IDM_WINDOW_VIS_0:\r
- {\r
- plog(_("メインウィンドウは非表示にできません!", "You are not allowed to do that!"));\r
- break;\r
- }\r
-\r
- /* Window visibility */\r
- case IDM_WINDOW_VIS_1:\r
- case IDM_WINDOW_VIS_2:\r
- case IDM_WINDOW_VIS_3:\r
- case IDM_WINDOW_VIS_4:\r
- case IDM_WINDOW_VIS_5:\r
- case IDM_WINDOW_VIS_6:\r
- case IDM_WINDOW_VIS_7:\r
- {\r
- i = wCmd - IDM_WINDOW_VIS_0;\r
-\r
- if ((i < 0) || (i >= MAX_TERM_DATA)) break;\r
-\r
- td = &data[i];\r
-\r
- if (!td->visible)\r
- {\r
- td->visible = TRUE;\r
- ShowWindow(td->w, SW_SHOW);\r
- term_data_redraw(td);\r
- }\r
- else\r
- {\r
- td->visible = FALSE;\r
- td->posfix = FALSE;\r
- ShowWindow(td->w, SW_HIDE);\r
- }\r
-\r
- break;\r
- }\r
-\r
- /* Window fonts */\r
- case IDM_WINDOW_FONT_0:\r
- case IDM_WINDOW_FONT_1:\r
- case IDM_WINDOW_FONT_2:\r
- case IDM_WINDOW_FONT_3:\r
- case IDM_WINDOW_FONT_4:\r
- case IDM_WINDOW_FONT_5:\r
- case IDM_WINDOW_FONT_6:\r
- case IDM_WINDOW_FONT_7:\r
- {\r
- i = wCmd - IDM_WINDOW_FONT_0;\r
-\r
- if ((i < 0) || (i >= MAX_TERM_DATA)) break;\r
-\r
- td = &data[i];\r
-\r
- term_change_font(td);\r
-\r
- break;\r
- }\r
-\r
- /* Window Z Position */\r
- case IDM_WINDOW_POS_1:\r
- case IDM_WINDOW_POS_2:\r
- case IDM_WINDOW_POS_3:\r
- case IDM_WINDOW_POS_4:\r
- case IDM_WINDOW_POS_5:\r
- case IDM_WINDOW_POS_6:\r
- case IDM_WINDOW_POS_7:\r
- {\r
- i = wCmd - IDM_WINDOW_POS_0;\r
-\r
- if ((i < 0) || (i >= MAX_TERM_DATA)) break;\r
-\r
- td = &data[i];\r
-\r
- if (!td->posfix && td->visible)\r
- {\r
- td->posfix = TRUE;\r
- term_window_pos(td, HWND_TOPMOST);\r
- }\r
- else\r
- {\r
- td->posfix = FALSE;\r
- term_window_pos(td, data[0].w);\r
- }\r
-\r
- break;\r
- }\r
-\r
- /* Bizarre Display */\r
- case IDM_WINDOW_BIZ_0:\r
- case IDM_WINDOW_BIZ_1:\r
- case IDM_WINDOW_BIZ_2:\r
- case IDM_WINDOW_BIZ_3:\r
- case IDM_WINDOW_BIZ_4:\r
- case IDM_WINDOW_BIZ_5:\r
- case IDM_WINDOW_BIZ_6:\r
- case IDM_WINDOW_BIZ_7:\r
- {\r
- i = wCmd - IDM_WINDOW_BIZ_0;\r
-\r
- if ((i < 0) || (i >= MAX_TERM_DATA)) break;\r
-\r
- td = &data[i];\r
-\r
- td->bizarre = !td->bizarre;\r
-\r
- term_getsize(td);\r
-\r
- term_window_resize(td);\r
-\r
- break;\r
- }\r
-\r
- /* Increase Tile Width */\r
- case IDM_WINDOW_I_WID_0:\r
- case IDM_WINDOW_I_WID_1:\r
- case IDM_WINDOW_I_WID_2:\r
- case IDM_WINDOW_I_WID_3:\r
- case IDM_WINDOW_I_WID_4:\r
- case IDM_WINDOW_I_WID_5:\r
- case IDM_WINDOW_I_WID_6:\r
- case IDM_WINDOW_I_WID_7:\r
- {\r
- i = wCmd - IDM_WINDOW_I_WID_0;\r
-\r
- if ((i < 0) || (i >= MAX_TERM_DATA)) break;\r
-\r
- td = &data[i];\r
-\r
- td->tile_wid += 1;\r
-\r
- term_getsize(td);\r
-\r
- term_window_resize(td);\r
-\r
- break;\r
- }\r
-\r
- /* Decrease Tile Height */\r
- case IDM_WINDOW_D_WID_0:\r
- case IDM_WINDOW_D_WID_1:\r
- case IDM_WINDOW_D_WID_2:\r
- case IDM_WINDOW_D_WID_3:\r
- case IDM_WINDOW_D_WID_4:\r
- case IDM_WINDOW_D_WID_5:\r
- case IDM_WINDOW_D_WID_6:\r
- case IDM_WINDOW_D_WID_7:\r
- {\r
- i = wCmd - IDM_WINDOW_D_WID_0;\r
-\r
- if ((i < 0) || (i >= MAX_TERM_DATA)) break;\r
-\r
- td = &data[i];\r
-\r
- td->tile_wid -= 1;\r
-\r
- term_getsize(td);\r
-\r
- term_window_resize(td);\r
-\r
- break;\r
- }\r
-\r
- /* Increase Tile Height */\r
- case IDM_WINDOW_I_HGT_0:\r
- case IDM_WINDOW_I_HGT_1:\r
- case IDM_WINDOW_I_HGT_2:\r
- case IDM_WINDOW_I_HGT_3:\r
- case IDM_WINDOW_I_HGT_4:\r
- case IDM_WINDOW_I_HGT_5:\r
- case IDM_WINDOW_I_HGT_6:\r
- case IDM_WINDOW_I_HGT_7:\r
- {\r
- i = wCmd - IDM_WINDOW_I_HGT_0;\r
-\r
- if ((i < 0) || (i >= MAX_TERM_DATA)) break;\r
-\r
- td = &data[i];\r
-\r
- td->tile_hgt += 1;\r
-\r
- term_getsize(td);\r
-\r
- term_window_resize(td);\r
-\r
- break;\r
- }\r
-\r
- /* Decrease Tile Height */\r
- case IDM_WINDOW_D_HGT_0:\r
- case IDM_WINDOW_D_HGT_1:\r
- case IDM_WINDOW_D_HGT_2:\r
- case IDM_WINDOW_D_HGT_3:\r
- case IDM_WINDOW_D_HGT_4:\r
- case IDM_WINDOW_D_HGT_5:\r
- case IDM_WINDOW_D_HGT_6:\r
- case IDM_WINDOW_D_HGT_7:\r
- {\r
- i = wCmd - IDM_WINDOW_D_HGT_0;\r
-\r
- if ((i < 0) || (i >= MAX_TERM_DATA)) break;\r
-\r
- td = &data[i];\r
-\r
- td->tile_hgt -= 1;\r
-\r
- term_getsize(td);\r
-\r
- term_window_resize(td);\r
-\r
- break;\r
- }\r
-\r
- case IDM_OPTIONS_NO_GRAPHICS:\r
- {\r
- /* Paranoia */\r
- if (!inkey_flag)\r
- {\r
- plog("You may not do that right now.");\r
- break;\r
- }\r
-\r
- /* Toggle "arg_graphics" */\r
- if (arg_graphics != GRAPHICS_NONE)\r
- {\r
- arg_graphics = GRAPHICS_NONE;\r
-\r
- /* React to changes */\r
- Term_xtra_win_react();\r
-\r
- /* Hack -- Force redraw */\r
- Term_key_push(KTRL('R'));\r
- }\r
-\r
- break;\r
- }\r
-\r
- case IDM_OPTIONS_OLD_GRAPHICS:\r
- {\r
- /* Paranoia */\r
- if (!inkey_flag)\r
- {\r
- plog("You may not do that right now.");\r
- break;\r
- }\r
-\r
- /* Toggle "arg_graphics" */\r
- if (arg_graphics != GRAPHICS_ORIGINAL)\r
- {\r
- arg_graphics = GRAPHICS_ORIGINAL;\r
-\r
- /* React to changes */\r
- Term_xtra_win_react();\r
-\r
- /* Hack -- Force redraw */\r
- Term_key_push(KTRL('R'));\r
- }\r
-\r
- break;\r
- }\r
-\r
- case IDM_OPTIONS_NEW_GRAPHICS:\r
- {\r
- /* Paranoia */\r
- if (!inkey_flag)\r
- {\r
- plog("You may not do that right now.");\r
- break;\r
- }\r
-\r
- /* Toggle "arg_graphics" */\r
- if (arg_graphics != GRAPHICS_ADAM_BOLT)\r
- {\r
- arg_graphics = GRAPHICS_ADAM_BOLT;\r
-\r
- /* React to changes */\r
- Term_xtra_win_react();\r
-\r
- /* Hack -- Force redraw */\r
- Term_key_push(KTRL('R'));\r
- }\r
-\r
- break;\r
- }\r
-\r
- case IDM_OPTIONS_NEW2_GRAPHICS:\r
- {\r
- /* Paranoia */\r
- if (!inkey_flag)\r
- {\r
- plog("You may not do that right now.");\r
- break;\r
- }\r
-\r
- /* Toggle "arg_graphics" */\r
- if (arg_graphics != GRAPHICS_HENGBAND)\r
- {\r
- arg_graphics = GRAPHICS_HENGBAND;\r
-\r
- /* React to changes */\r
- Term_xtra_win_react();\r
-\r
- /* Hack -- Force redraw */\r
- Term_key_push(KTRL('R'));\r
- }\r
-\r
- break;\r
- }\r
-\r
- case IDM_OPTIONS_BIGTILE:\r
- {\r
- td = &data[0];\r
-\r
- /* Paranoia */\r
- if (!inkey_flag)\r
- {\r
- plog("You may not do that right now.");\r
- break;\r
- }\r
-\r
- /* Toggle "arg_sound" */\r
- arg_bigtile = !arg_bigtile;\r
-\r
- /* Activate */\r
- Term_activate(&td->t);\r
-\r
- /* Resize the term */\r
- Term_resize(td->cols, td->rows);\r
-\r
- /* Redraw later */\r
- InvalidateRect(td->w, NULL, TRUE);\r
-\r
- break;\r
- }\r
-\r
- case IDM_OPTIONS_MUSIC:\r
- {\r
- /* Paranoia */\r
- if (!inkey_flag)\r
- {\r
- plog("You may not do that right now.");\r
- break;\r
- }\r
-\r
- /* Toggle "arg_sound" */\r
- arg_music = !arg_music;\r
-\r
- /* React to changes */\r
- Term_xtra_win_react();\r
-\r
- /* Hack -- Force redraw */\r
- Term_key_push(KTRL('R'));\r
-\r
- break;\r
- }\r
-\r
- case IDM_OPTIONS_SOUND:\r
- {\r
- /* Paranoia */\r
- if (!inkey_flag)\r
- {\r
- plog("You may not do that right now.");\r
- break;\r
- }\r
-\r
- /* Toggle "arg_sound" */\r
- arg_sound = !arg_sound;\r
-\r
- /* React to changes */\r
- Term_xtra_win_react();\r
-\r
- /* Hack -- Force redraw */\r
- Term_key_push(KTRL('R'));\r
-\r
- break;\r
- }\r
-\r
- /* bg */\r
- case IDM_OPTIONS_BG:\r
- {\r
- /* Paranoia */\r
- if (!inkey_flag)\r
- {\r
- plog("You may not do that right now.");\r
- break;\r
- }\r
-\r
- /* Toggle "use_bg" */\r
- use_bg = !use_bg;\r
-\r
- init_bg();\r
-\r
- /* React to changes */\r
- Term_xtra_win_react();\r
-\r
- /* Hack -- Force redraw */\r
- Term_key_push(KTRL('R'));\r
-\r
- break;\r
- }\r
-\r
- /* bg */\r
- case IDM_OPTIONS_OPEN_BG:\r
- {\r
- /* Paranoia */\r
- if (!inkey_flag)\r
- {\r
- plog("You may not do that right now.");\r
- break;\r
- }\r
- else\r
- {\r
- memset(&ofn, 0, sizeof(ofn));\r
- ofn.lStructSize = sizeof(ofn);\r
- ofn.hwndOwner = data[0].w;\r
- ofn.lpstrFilter = "Bitmap Files (*.bmp)\0*.bmp\0";\r
- ofn.nFilterIndex = 1;\r
- ofn.lpstrFile = bg_bitmap_file;\r
- ofn.nMaxFile = 1023;\r
- ofn.lpstrInitialDir = NULL;\r
- ofn.lpstrTitle = _("壁紙を選んでね。", "Choose wall paper.");\r
- ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;\r
-\r
- if (GetOpenFileName(&ofn))\r
- {\r
- /* Load 'savefile' */\r
- use_bg = 1;\r
- init_bg();\r
- }\r
-\r
- /* React to changes */\r
- Term_xtra_win_react();\r
-\r
- /* Hack -- Force redraw */\r
- Term_key_push(KTRL('R'));\r
- }\r
- break;\r
- }\r
-\r
- case IDM_DUMP_SCREEN_HTML:\r
- {\r
- static char buf[1024] = "";\r
- memset(&ofn, 0, sizeof(ofn));\r
- ofn.lStructSize = sizeof(ofn);\r
- ofn.hwndOwner = data[0].w;\r
- ofn.lpstrFilter = "HTML Files (*.html)\0*.html\0";\r
- ofn.nFilterIndex = 1;\r
- ofn.lpstrFile = buf;\r
- ofn.nMaxFile = 1023;\r
- ofn.lpstrDefExt = "html";\r
- ofn.lpstrInitialDir = NULL;\r
- ofn.lpstrTitle = _("HTMLでスクリーンダンプを保存", "Save screen dump as HTML.");\r
- ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;\r
-\r
- if (GetSaveFileName(&ofn))\r
- {\r
- do_cmd_save_screen_html_aux(buf, 0);\r
- }\r
- break;\r
- }\r
-\r
-#ifdef USE_SAVER\r
-\r
- case IDM_OPTIONS_SAVER:\r
- {\r
- if (hwndSaver)\r
- {\r
- DestroyWindow(hwndSaver);\r
- hwndSaver = NULL;\r
- }\r
- else\r
- {\r
- /* Create a screen scaver window */\r
- hwndSaver = CreateWindowEx(WS_EX_TOPMOST, "WindowsScreenSaverClass",\r
- "Angband Screensaver",\r
- WS_POPUP | WS_MAXIMIZE | WS_VISIBLE,\r
- 0, 0, GetSystemMetrics(SM_CXSCREEN),\r
- GetSystemMetrics(SM_CYSCREEN),\r
- NULL, NULL, hInstance, NULL);\r
-\r
- if (hwndSaver)\r
- {\r
- /* Push the window to the bottom */\r
- SetWindowPos(hwndSaver, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);\r
- }\r
- else\r
- {\r
- plog(_("ウィンドウを作成出来ません", "Failed to create saver window"));\r
- }\r
- }\r
- break;\r
- }\r
-\r
-#endif\r
-\r
- case IDM_OPTIONS_MAP:\r
- {\r
- windows_map();\r
- break;\r
- }\r
-\r
- case IDM_HELP_CONTENTS:\r
- {\r
-#ifdef HTML_HELP\r
- char tmp[1024];\r
- path_build(tmp, sizeof(tmp), ANGBAND_DIR_XTRA_HELP, "zangband.chm");\r
- if (check_file(tmp))\r
- {\r
- HtmlHelp(data[0].w, tmp, HH_DISPLAY_TOPIC, 0);\r
- }\r
- else\r
- {\r
- plog_fmt(_("ヘルプファイル[%s]が見付かりません。", "Cannot find help file: %s"), tmp);\r
- plog(_("代わりにオンラインヘルプを使用してください。", "Use the online help files instead."));\r
- }\r
- break;\r
-#else /* HTML_HELP */\r
- char buf[1024];\r
- char tmp[1024];\r
- path_build(tmp, sizeof(tmp), ANGBAND_DIR_XTRA_HELP, "zangband.hlp");\r
- if (check_file(tmp))\r
- {\r
- sprintf(buf, "winhelp.exe %s", tmp);\r
- WinExec(buf, SW_NORMAL);\r
- }\r
- else\r
- {\r
- plog_fmt(_("ヘルプファイル[%s]が見付かりません。", "Cannot find help file: %s"), tmp);\r
- plog(_("代わりにオンラインヘルプを使用してください。", "Use the online help files instead."));\r
-\r
- }\r
- break;\r
-#endif /* HTML_HELP */\r
- }\r
- }\r
-}\r
-\r
-\r
-static bool process_keydown(WPARAM wParam, LPARAM lParam)\r
-{\r
- int i;\r
- bool mc = FALSE;\r
- bool ms = FALSE;\r
- bool ma = FALSE;\r
-\r
- /* Extract the modifiers */\r
- if (GetKeyState(VK_CONTROL) & 0x8000) mc = TRUE;\r
- if (GetKeyState(VK_SHIFT) & 0x8000) ms = TRUE;\r
- if (GetKeyState(VK_MENU) & 0x8000) ma = TRUE;\r
-\r
- Term_no_press = (ma) ? TRUE : FALSE;\r
-\r
- /* Handle "special" keys */\r
- if (special_key[(byte)(wParam)] || (ma && !ignore_key[(byte)(wParam)]) )\r
- {\r
- bool ext_key = (lParam & 0x1000000L) ? TRUE : FALSE;\r
- bool numpad = FALSE;\r
-\r
- /* Begin the macro trigger */\r
- Term_keypress(31);\r
-\r
- /* Send the modifiers */\r
- if (mc) Term_keypress('C');\r
- if (ms) Term_keypress('S');\r
- if (ma) Term_keypress('A');\r
-\r
- /* Extract "scan code" */\r
- i = LOBYTE(HIWORD(lParam));\r
-\r
- /* Introduce the scan code */\r
- Term_keypress('x');\r
-\r
- /* Extended key bit */\r
- switch (wParam)\r
- {\r
- /* Numpad Enter and '/' are extended key */\r
- case VK_DIVIDE:\r
- Term_no_press = TRUE;\r
- case VK_RETURN: /* Enter */\r
- numpad = ext_key;\r
- break;\r
- /* Other extended keys are on full keyboard */\r
- case VK_NUMPAD0:\r
- case VK_NUMPAD1:\r
- case VK_NUMPAD2:\r
- case VK_NUMPAD3:\r
- case VK_NUMPAD4:\r
- case VK_NUMPAD5:\r
- case VK_NUMPAD6:\r
- case VK_NUMPAD7:\r
- case VK_NUMPAD8:\r
- case VK_NUMPAD9:\r
- case VK_ADD:\r
- case VK_MULTIPLY:\r
- case VK_SUBTRACT:\r
- case VK_SEPARATOR:\r
- case VK_DECIMAL:\r
- Term_no_press = TRUE;\r
- case VK_CLEAR:\r
- case VK_HOME:\r
- case VK_END:\r
- case VK_PRIOR: /* Page Up */\r
- case VK_NEXT: /* Page Down */\r
- case VK_INSERT:\r
- case VK_DELETE:\r
- case VK_UP:\r
- case VK_DOWN:\r
- case VK_LEFT:\r
- case VK_RIGHT:\r
- numpad = !ext_key;\r
- }\r
-\r
- /* Special modifiers for keypad keys */\r
- if (numpad) Term_keypress('K');\r
-\r
- /* Encode the hexidecimal scan code */\r
- Term_keypress(hexsym[i/16]);\r
- Term_keypress(hexsym[i%16]);\r
-\r
- /* End the macro trigger */\r
- Term_keypress(13);\r
-\r
- return 1;\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-\r
-#ifdef __MWERKS__\r
-LRESULT FAR PASCAL AngbandWndProc(HWND hWnd, UINT uMsg,\r
- WPARAM wParam, LPARAM lParam);\r
-LRESULT FAR PASCAL AngbandWndProc(HWND hWnd, UINT uMsg,\r
- WPARAM wParam, LPARAM lParam)\r
-#else /* __MWERKS__ */\r
-LRESULT FAR PASCAL AngbandWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)\r
-#endif /* __MWERKS__ */\r
-{\r
- PAINTSTRUCT ps;\r
- HDC hdc;\r
- term_data *td;\r
-#if 0\r
- MINMAXINFO FAR *lpmmi;\r
- RECT rc;\r
-#endif\r
- int i;\r
-\r
-\r
- /* Acquire proper "term_data" info */\r
- td = (term_data *)GetWindowLong(hWnd, 0);\r
-\r
- /* Handle message */\r
- switch (uMsg)\r
- {\r
- case WM_NCCREATE:\r
- {\r
- SetWindowLong(hWnd, 0, (LONG)(my_td));\r
- break;\r
- }\r
-\r
- case WM_CREATE:\r
- {\r
-#ifdef USE_MUSIC\r
- mop.dwCallback=(DWORD)hWnd;\r
-#endif\r
- return 0;\r
- }\r
-\r
- case WM_GETMINMAXINFO:\r
- {\r
- MINMAXINFO FAR *lpmmi;\r
- RECT rc;\r
-\r
- lpmmi = (MINMAXINFO FAR *)lParam;\r
-\r
- /* this message was sent before WM_NCCREATE */\r
- if (!td) return 1;\r
-\r
- /* Minimum window size is 80x24 */\r
- rc.left = rc.top = 0;\r
- rc.right = rc.left + 80 * td->tile_wid + td->size_ow1 + td->size_ow2;\r
- rc.bottom = rc.top + 24 * td->tile_hgt + td->size_oh1 + td->size_oh2 + 1;\r
-\r
- /* Adjust */\r
- AdjustWindowRectEx(&rc, td->dwStyle, TRUE, td->dwExStyle);\r
-\r
- /* Save minimum size */\r
- lpmmi->ptMinTrackSize.x = rc.right - rc.left;\r
- lpmmi->ptMinTrackSize.y = rc.bottom - rc.top;\r
-\r
- return 0;\r
- }\r
-\r
- case WM_PAINT:\r
- {\r
- BeginPaint(hWnd, &ps);\r
- if (td) term_data_redraw(td);\r
- EndPaint(hWnd, &ps);\r
- ValidateRect(hWnd, NULL);\r
- return 0;\r
- }\r
-\r
-#ifdef USE_MUSIC\r
- case MM_MCINOTIFY:\r
- {\r
- if(wParam == MCI_NOTIFY_SUCCESSFUL)\r
- {\r
- mciSendCommand(mop.wDeviceID, MCI_SEEK, MCI_SEEK_TO_START, 0);\r
- mciSendCommand(mop.wDeviceID, MCI_PLAY, MCI_NOTIFY, (DWORD)&mop);\r
- }\r
- return 0;\r
- }\r
-#endif\r
-\r
- case WM_SYSKEYDOWN:\r
- case WM_KEYDOWN:\r
- {\r
- if (process_keydown(wParam, lParam))\r
- return 0;\r
- break;\r
- }\r
-\r
- case WM_CHAR:\r
- {\r
- if (Term_no_press) Term_no_press = FALSE;\r
- else Term_keypress(wParam);\r
- return 0;\r
- }\r
-\r
- case WM_LBUTTONDOWN:\r
- {\r
- mousex = MIN(LOWORD(lParam) / td->tile_wid, td->cols - 1);\r
- mousey = MIN(HIWORD(lParam) / td->tile_hgt, td->rows - 1);\r
- mouse_down = TRUE;\r
- oldx = mousex;\r
- oldy = mousey;\r
- return 0;\r
- }\r
-\r
- case WM_LBUTTONUP:\r
- {\r
- HGLOBAL hGlobal;\r
- LPSTR lpStr;\r
- int j, sz;\r
- TERM_LEN dx = abs(oldx - mousex) + 1;\r
- TERM_LEN dy = abs(oldy - mousey) + 1;\r
- TERM_LEN ox = (oldx > mousex) ? mousex : oldx;\r
- TERM_LEN oy = (oldy > mousey) ? mousey : oldy;\r
-\r
- mouse_down = FALSE;\r
- paint_rect = FALSE;\r
-\r
-#ifdef JP\r
- sz = (dx + 3) * dy;\r
-#else\r
- sz = (dx + 2) * dy;\r
-#endif\r
- hGlobal = GlobalAlloc(GHND, sz + 1);\r
- if (hGlobal == NULL) return 0;\r
- lpStr = (LPSTR)GlobalLock(hGlobal);\r
-\r
- for (i = 0; i < dy; i++)\r
- {\r
-#ifdef JP\r
- char *s;\r
- char **scr = data[0].t.scr->c;\r
-\r
- C_MAKE(s, (dx + 1), char);\r
- strncpy(s, &scr[oy + i][ox], dx);\r
-\r
- if (ox > 0)\r
- {\r
- if (iskanji(scr[oy + i][ox - 1])) s[0] = ' ';\r
- }\r
-\r
- if (ox + dx < data[0].cols)\r
- {\r
- if (iskanji(scr[oy + i][ox + dx - 1])) s[dx - 1] = ' ';\r
- }\r
-\r
- for (j = 0; j < dx; j++)\r
- {\r
- if (s[j] == 127) s[j] = '#';\r
- *lpStr++ = s[j];\r
- }\r
-#else\r
- for (j = 0; j < dx; j++)\r
- {\r
- *lpStr++ = data[0].t.scr->c[oy + i][ox + j];\r
- }\r
-#endif\r
- if (dy > 1)\r
- {\r
- *lpStr++ = '\r';\r
- *lpStr++ = '\n';\r
- }\r
- }\r
-\r
- GlobalUnlock(hGlobal);\r
- if (OpenClipboard(hWnd) == 0)\r
- {\r
- GlobalFree(hGlobal);\r
- return 0;\r
- }\r
- EmptyClipboard();\r
- SetClipboardData(CF_TEXT, hGlobal);\r
- CloseClipboard();\r
-\r
- Term_redraw();\r
-\r
- return 0;\r
- }\r
-\r
- case WM_MOUSEMOVE:\r
- {\r
- if (mouse_down)\r
- {\r
- int dx, dy;\r
- int cx = MIN(LOWORD(lParam) / td->tile_wid, td->cols - 1);\r
- int cy = MIN(HIWORD(lParam) / td->tile_hgt, td->rows - 1);\r
- int ox, oy;\r
-\r
- if (paint_rect)\r
- {\r
- dx = abs(oldx - mousex) + 1;\r
- dy = abs(oldy - mousey) + 1;\r
- ox = (oldx > mousex) ? mousex : oldx;\r
- oy = (oldy > mousey) ? mousey : oldy;\r
- Term_inversed_area(hWnd, ox, oy, dx, dy);\r
- }\r
- else\r
- {\r
- paint_rect = TRUE;\r
- }\r
-\r
- dx = abs(cx - mousex) + 1;\r
- dy = abs(cy - mousey) + 1;\r
- ox = (cx > mousex) ? mousex : cx;\r
- oy = (cy > mousey) ? mousey : cy;\r
- Term_inversed_area(hWnd, ox, oy, dx, dy);\r
-\r
- oldx = cx;\r
- oldy = cy;\r
- }\r
- return 0;\r
- }\r
-\r
- case WM_INITMENU:\r
- {\r
- setup_menus();\r
- return 0;\r
- }\r
-\r
- case WM_CLOSE:\r
- {\r
- if (game_in_progress && character_generated)\r
- {\r
- if (!can_save)\r
- {\r
- plog(_("今は終了できません。", "You may not do that right now."));\r
- return 0;\r
- }\r
-\r
- /* Hack -- Forget messages */\r
- msg_flag = FALSE;\r
-\r
- forget_lite();\r
- forget_view();\r
- clear_mon_lite();\r
-\r
- /* Save the game */\r
-#ifdef ZANGBAND\r
- /* do_cmd_save_game(FALSE); */\r
-#else /* ZANGBAND */\r
- /* do_cmd_save_game(); */\r
-#endif /* ZANGBAND */\r
- Term_key_push(SPECIAL_KEY_QUIT);\r
- return 0;\r
- }\r
- quit(NULL);\r
- return 0;\r
- }\r
-\r
- case WM_QUERYENDSESSION:\r
- {\r
- if (game_in_progress && character_generated)\r
- {\r
- /* Hack -- Forget messages */\r
- msg_flag = FALSE;\r
-\r
- /* Mega-Hack -- Delay death */\r
- if (p_ptr->chp < 0) p_ptr->is_dead = FALSE;\r
- do_cmd_write_nikki(NIKKI_GAMESTART, 0, _("----ゲーム中断----", "---- Save and Exit Game ----"));\r
-\r
- /* Hardcode panic save */\r
- p_ptr->panic_save = 1;\r
-\r
- /* Forbid suspend */\r
- signals_ignore_tstp();\r
-\r
- /* Indicate panic save */\r
- (void)strcpy(p_ptr->died_from, _("(緊急セーブ)", "(panic save)"));\r
-\r
- /* Panic save */\r
- (void)save_player();\r
- }\r
- quit(NULL);\r
- return 0;\r
- }\r
-\r
- case WM_QUIT:\r
- {\r
- quit(NULL);\r
- return 0;\r
- }\r
-\r
- case WM_COMMAND:\r
- {\r
- process_menus(LOWORD(wParam));\r
- return 0;\r
- }\r
-\r
- case WM_SIZE:\r
- {\r
- /* this message was sent before WM_NCCREATE */\r
- if (!td) return 1;\r
-\r
- /* it was sent from inside CreateWindowEx */\r
- if (!td->w) return 1;\r
-\r
- /* was sent from WM_SIZE */\r
- if (td->size_hack) return 1;\r
-\r
- switch (wParam)\r
- {\r
- case SIZE_MINIMIZED:\r
- {\r
- /* Hide sub-windows */\r
- for (i = 1; i < MAX_TERM_DATA; i++)\r
- {\r
- if (data[i].visible) ShowWindow(data[i].w, SW_HIDE);\r
- }\r
- return 0;\r
- }\r
-\r
- case SIZE_MAXIMIZED:\r
- {\r
- /* fall through */\r
- }\r
-\r
- case SIZE_RESTORED:\r
- {\r
- TERM_LEN cols = (LOWORD(lParam) - td->size_ow1) / td->tile_wid;\r
- TERM_LEN rows = (HIWORD(lParam) - td->size_oh1) / td->tile_hgt;\r
-\r
- /* New size */\r
- if ((td->cols != cols) || (td->rows != rows))\r
- {\r
- /* Save the new size */\r
- td->cols = cols;\r
- td->rows = rows;\r
-\r
- if (!IsZoomed(td->w) && !IsIconic(td->w))\r
- {\r
- normsize.x = td->cols;\r
- normsize.y = td->rows;\r
- }\r
-\r
- /* Activate */\r
- Term_activate(&td->t);\r
-\r
- /* Resize the term */\r
- Term_resize(td->cols, td->rows);\r
-\r
- /* Redraw later */\r
- InvalidateRect(td->w, NULL, TRUE);\r
- }\r
-\r
- td->size_hack = TRUE;\r
-\r
- /* Show sub-windows */\r
- for (i = 1; i < MAX_TERM_DATA; i++)\r
- {\r
- if (data[i].visible) ShowWindow(data[i].w, SW_SHOW);\r
- }\r
-\r
- td->size_hack = FALSE;\r
-\r
- return 0;\r
- }\r
- }\r
- break;\r
- }\r
-\r
- case WM_PALETTECHANGED:\r
- {\r
- /* Ignore if palette change caused by itself */\r
- if ((HWND)wParam == hWnd) return 0;\r
-\r
- /* Fall through... */\r
- }\r
-\r
- case WM_QUERYNEWPALETTE:\r
- {\r
- if (!paletted) return 0;\r
-\r
- hdc = GetDC(hWnd);\r
-\r
- SelectPalette(hdc, hPal, FALSE);\r
-\r
- i = RealizePalette(hdc);\r
-\r
- /* if any palette entries changed, repaint the window. */\r
- if (i) InvalidateRect(hWnd, NULL, TRUE);\r
-\r
- ReleaseDC(hWnd, hdc);\r
-\r
- return 0;\r
- }\r
-\r
- case WM_ACTIVATE:\r
- {\r
- if (wParam && !HIWORD(lParam))\r
- {\r
- /* Do something to sub-windows */\r
- for (i = 1; i < MAX_TERM_DATA; i++)\r
- {\r
- if (!data[i].posfix) term_window_pos(&data[i], hWnd);\r
- }\r
-\r
- /* Focus on main window */\r
- SetFocus(hWnd);\r
-\r
- return 0;\r
- }\r
-\r
- break;\r
- }\r
-\r
- case WM_ACTIVATEAPP:\r
- {\r
- if (IsIconic(td->w)) break;\r
-\r
- for (i = 1; i < MAX_TERM_DATA; i++)\r
- {\r
- if(data[i].visible)\r
- {\r
- if (wParam == TRUE)\r
- {\r
- ShowWindow(data[i].w, SW_SHOW);\r
- }\r
- else\r
- {\r
- ShowWindow(data[i].w, SW_HIDE);\r
- }\r
- }\r
- }\r
- }\r
- }\r
-\r
- return DefWindowProc(hWnd, uMsg, wParam, lParam);\r
-}\r
-\r
-\r
-#ifdef __MWERKS__\r
-LRESULT FAR PASCAL AngbandListProc(HWND hWnd, UINT uMsg,\r
- WPARAM wParam, LPARAM lParam);\r
-LRESULT FAR PASCAL AngbandListProc(HWND hWnd, UINT uMsg,\r
- WPARAM wParam, LPARAM lParam)\r
-#else /* __MWERKS__ */\r
-LRESULT FAR PASCAL AngbandListProc(HWND hWnd, UINT uMsg,\r
- WPARAM wParam, LPARAM lParam)\r
-#endif /* __MWERKS__ */\r
-{\r
- term_data *td;\r
-#if 0\r
- MINMAXINFO FAR *lpmmi;\r
- RECT rc;\r
-#endif\r
- PAINTSTRUCT ps;\r
- HDC hdc;\r
- int i;\r
-\r
-\r
- /* Acquire proper "term_data" info */\r
- td = (term_data *)GetWindowLong(hWnd, 0);\r
-\r
- /* Process message */\r
- switch (uMsg)\r
- {\r
- case WM_NCCREATE:\r
- {\r
- SetWindowLong(hWnd, 0, (LONG)(my_td));\r
- break;\r
- }\r
-\r
- case WM_CREATE:\r
- {\r
- return 0;\r
- }\r
-\r
- case WM_GETMINMAXINFO:\r
- {\r
- MINMAXINFO FAR *lpmmi;\r
- RECT rc;\r
-\r
- lpmmi = (MINMAXINFO FAR *)lParam;\r
-\r
- /* this message was sent before WM_NCCREATE */\r
- if (!td) return 1;\r
-\r
- /* Minimum window size is 80x24 */\r
- rc.left = rc.top = 0;\r
- rc.right = rc.left + 20 * td->tile_wid + td->size_ow1 + td->size_ow2;\r
- rc.bottom = rc.top + 3 * td->tile_hgt + td->size_oh1 + td->size_oh2 + 1;\r
-\r
- /* Adjust */\r
- AdjustWindowRectEx(&rc, td->dwStyle, TRUE, td->dwExStyle);\r
-\r
- /* Save minimum size */\r
- lpmmi->ptMinTrackSize.x = rc.right - rc.left;\r
- lpmmi->ptMinTrackSize.y = rc.bottom - rc.top;\r
-\r
- return 0;\r
- }\r
-\r
- case WM_SIZE:\r
- {\r
- TERM_LEN cols;\r
- TERM_LEN rows;\r
- \r
- /* this message was sent before WM_NCCREATE */\r
- if (!td) return 1;\r
-\r
- /* it was sent from inside CreateWindowEx */\r
- if (!td->w) return 1;\r
-\r
- /* was sent from inside WM_SIZE */\r
- if (td->size_hack) return 1;\r
-\r
- td->size_hack = TRUE;\r
-\r
- cols = (LOWORD(lParam) - td->size_ow1) / td->tile_wid;\r
- rows = (HIWORD(lParam) - td->size_oh1) / td->tile_hgt;\r
-\r
- /* New size */\r
- if ((td->cols != cols) || (td->rows != rows))\r
- {\r
- /* Save old term */\r
- term *old_term = Term;\r
-\r
- /* Save the new size */\r
- td->cols = cols;\r
- td->rows = rows;\r
-\r
- /* Activate */\r
- Term_activate(&td->t);\r
-\r
- /* Resize the term */\r
- Term_resize(td->cols, td->rows);\r
-\r
- /* Activate */\r
- Term_activate(old_term);\r
-\r
- /* Redraw later */\r
- InvalidateRect(td->w, NULL, TRUE);\r
-\r
- /* HACK - Redraw all windows */\r
- p_ptr->window = 0xFFFFFFFF;\r
- handle_stuff();\r
- }\r
-\r
- td->size_hack = FALSE;\r
-\r
- return 0;\r
- }\r
-\r
- case WM_PAINT:\r
- {\r
- BeginPaint(hWnd, &ps);\r
- if (td) term_data_redraw(td);\r
- EndPaint(hWnd, &ps);\r
- return 0;\r
- }\r
-\r
- case WM_SYSKEYDOWN:\r
- case WM_KEYDOWN:\r
- {\r
- if (process_keydown(wParam, lParam))\r
- return 0;\r
- break;\r
- }\r
-\r
- case WM_CHAR:\r
- {\r
- if (Term_no_press) Term_no_press = FALSE;\r
- else Term_keypress(wParam);\r
- return 0;\r
- }\r
-\r
- case WM_PALETTECHANGED:\r
- {\r
- /* ignore if palette change caused by itself */\r
- if ((HWND)wParam == hWnd) return FALSE;\r
- /* otherwise, fall through!!! */\r
- }\r
-\r
- case WM_QUERYNEWPALETTE:\r
- {\r
- if (!paletted) return 0;\r
- hdc = GetDC(hWnd);\r
- SelectPalette(hdc, hPal, FALSE);\r
- i = RealizePalette(hdc);\r
- /* if any palette entries changed, repaint the window. */\r
- if (i) InvalidateRect(hWnd, NULL, TRUE);\r
- ReleaseDC(hWnd, hdc);\r
- return 0;\r
- }\r
-\r
- case WM_NCLBUTTONDOWN:\r
- {\r
-\r
-#ifdef HTCLOSE\r
- if (wParam == HTCLOSE) wParam = HTSYSMENU;\r
-#endif /* HTCLOSE */\r
-\r
- if (wParam == HTSYSMENU)\r
- {\r
- if (td->visible)\r
- {\r
- td->visible = FALSE;\r
- ShowWindow(td->w, SW_HIDE);\r
- }\r
-\r
- return 0;\r
- }\r
-\r
- break;\r
- }\r
- }\r
-\r
- return DefWindowProc(hWnd, uMsg, wParam, lParam);\r
-}\r
-\r
-\r
-#ifdef USE_SAVER\r
-\r
-#define MOUSE_SENS 40\r
-\r
-#ifdef __MWERKS__\r
-LRESULT FAR PASCAL AngbandSaverProc(HWND hWnd, UINT uMsg,\r
- WPARAM wParam, LPARAM lParam);\r
-LRESULT FAR PASCAL AngbandSaverProc(HWND hWnd, UINT uMsg,\r
- WPARAM wParam, LPARAM lParam)\r
-#else /* __MWERKS__ */\r
-LRESULT FAR PASCAL AngbandSaverProc(HWND hWnd, UINT uMsg,\r
- WPARAM wParam, LPARAM lParam)\r
-#endif /* __MWERKS__ */\r
-{\r
- static int iMouse = 0;\r
- static WORD xMouse = 0;\r
- static WORD yMouse = 0;\r
-\r
- int dx, dy;\r
-\r
-\r
- /* Process */\r
- switch (uMsg)\r
- {\r
- case WM_NCCREATE:\r
- {\r
- break;\r
- }\r
-\r
- case WM_SETCURSOR:\r
- {\r
- SetCursor(NULL);\r
- return 0;\r
- }\r
-\r
-#if 0\r
- case WM_ACTIVATE:\r
- {\r
- if (LOWORD(wParam) == WA_INACTIVE) break;\r
-\r
- /* else fall through */\r
- }\r
-#endif\r
-\r
- case WM_LBUTTONDOWN:\r
- case WM_MBUTTONDOWN:\r
- case WM_RBUTTONDOWN:\r
- case WM_KEYDOWN:\r
- {\r
- SendMessage(hWnd, WM_CLOSE, 0, 0);\r
- return 0;\r
- }\r
-\r
- case WM_MOUSEMOVE:\r
- {\r
- if (iMouse)\r
- {\r
- dx = LOWORD(lParam) - xMouse;\r
- dy = HIWORD(lParam) - yMouse;\r
-\r
- if (dx < 0) dx = -dx;\r
- if (dy < 0) dy = -dy;\r
-\r
- if ((dx > MOUSE_SENS) || (dy > MOUSE_SENS))\r
- {\r
- SendMessage(hWnd, WM_CLOSE, 0, 0);\r
- }\r
- }\r
-\r
- /* Save last location */\r
- iMouse = 1;\r
- xMouse = LOWORD(lParam);\r
- yMouse = HIWORD(lParam);\r
-\r
- return 0;\r
- }\r
-\r
- case WM_CLOSE:\r
- {\r
- DestroyWindow(hwndSaver);\r
- hwndSaver = NULL;\r
- return 0;\r
- }\r
- }\r
-\r
- return DefWindowProc(hWnd, uMsg, wParam, lParam);\r
-}\r
-\r
-#endif /* USE_SAVER */\r
-\r
-\r
-\r
-\r
-\r
-/*** Temporary Hooks ***/\r
-\r
-\r
-/*\r
- * Display warning message (see "z-util.c")\r
- */\r
-static void hack_plog(concptr str)\r
-{\r
- /* Give a warning */\r
- if (str)\r
- {\r
-#ifdef JP\r
- MessageBox(NULL, str, "警告!",\r
- MB_ICONEXCLAMATION | MB_OK);\r
-#else\r
- MessageBox(NULL, str, "Warning",\r
- MB_ICONEXCLAMATION | MB_OK);\r
-#endif\r
-\r
- }\r
-}\r
-\r
-\r
-/*\r
- * Display error message and quit (see "z-util.c")\r
- */\r
-static void hack_quit(concptr str)\r
-{\r
- /* Give a warning */\r
- if (str)\r
- {\r
-#ifdef JP\r
- MessageBox(NULL, str, "エラー!",\r
- MB_ICONEXCLAMATION | MB_OK | MB_ICONSTOP);\r
-#else\r
- MessageBox(NULL, str, "Error",\r
- MB_ICONEXCLAMATION | MB_OK | MB_ICONSTOP);\r
-#endif\r
-\r
- }\r
-\r
- /* Unregister the classes */\r
- UnregisterClass(AppName, hInstance);\r
-\r
- /* Destroy the icon */\r
- if (hIcon) DestroyIcon(hIcon);\r
-\r
- /* Exit */\r
- exit(0);\r
-}\r
-\r
-\r
-\r
-/*** Various hooks ***/\r
-\r
-\r
-/*\r
- * Display warning message (see "z-util.c")\r
- */\r
-static void hook_plog(concptr str)\r
-{\r
- /* Warning */\r
- if (str)\r
- {\r
-#ifdef JP\r
- MessageBox(data[0].w, str, "警告!",\r
- MB_ICONEXCLAMATION | MB_OK);\r
-#else\r
- MessageBox(data[0].w, str, "Warning",\r
- MB_ICONEXCLAMATION | MB_OK);\r
-#endif\r
-\r
- }\r
-}\r
-\r
-\r
-/*\r
- * Display error message and quit (see "z-util.c")\r
- */\r
-static void hook_quit(concptr str)\r
-{\r
- int i;\r
-\r
-\r
- /* Give a warning */\r
- if (str)\r
- {\r
-#ifdef JP\r
- MessageBox(data[0].w, str, "エラー!",\r
- MB_ICONEXCLAMATION | MB_OK | MB_ICONSTOP);\r
-#else\r
- MessageBox(data[0].w, str, "Error",\r
- MB_ICONEXCLAMATION | MB_OK | MB_ICONSTOP);\r
-#endif\r
-\r
- }\r
-\r
-\r
- /* Save the preferences */\r
- save_prefs();\r
-\r
-\r
- /*** Could use 'Term_nuke_win()' */\r
-\r
- /* Destroy all windows */\r
- for (i = MAX_TERM_DATA - 1; i >= 0; --i)\r
- {\r
- term_force_font(&data[i], NULL);\r
- if (data[i].font_want) string_free(data[i].font_want);\r
- if (data[i].w) DestroyWindow(data[i].w);\r
- data[i].w = 0;\r
- }\r
-\r
- /* Free the bitmap stuff */\r
-#ifdef USE_GRAPHICS\r
- if (infGraph.hPalette) DeleteObject(infGraph.hPalette);\r
- if (infGraph.hBitmap) DeleteObject(infGraph.hBitmap);\r
-\r
- if (infMask.hPalette) DeleteObject(infMask.hPalette);\r
- if (infMask.hBitmap) DeleteObject(infMask.hBitmap);\r
-\r
-#endif /* USE_GRAPHICS */\r
-\r
- /*** Free some other stuff ***/\r
-\r
- DeleteObject(hbrYellow);\r
-\r
- /* bg */\r
- delete_bg();\r
-\r
- if (hPal) DeleteObject(hPal);\r
-\r
- UnregisterClass(AppName, hInstance);\r
-\r
- if (hIcon) DestroyIcon(hIcon);\r
-\r
- exit(0);\r
-}\r
-\r
-\r
-\r
-/*** Initialize ***/\r
-\r
-\r
-/*\r
- * Init some stuff\r
- */\r
-static void init_stuff(void)\r
-{\r
- int i;\r
-\r
- char path[1024];\r
-\r
-\r
- /* Get program name with full path */\r
- GetModuleFileName(hInstance, path, 512);\r
-\r
- /* Save the "program name" */\r
- argv0 = path;\r
-\r
- /* Get the name of the "*.ini" file */\r
- strcpy(path + strlen(path) - 4, ".INI");\r
-\r
- /* Save the the name of the ini-file */\r
- ini_file = string_make(path);\r
-\r
- /* Analyze the path */\r
- i = strlen(path);\r
-\r
- /* Get the path */\r
- for (; i > 0; i--)\r
- {\r
- if (path[i] == '\\')\r
- {\r
- /* End of path */\r
- break;\r
- }\r
- }\r
-\r
- /* Add "lib" to the path */\r
- strcpy(path + i + 1, "lib\\");\r
-\r
- /* Validate the path */\r
- validate_dir(path, TRUE);\r
-\r
- /* Init the file paths */\r
- init_file_paths(path);\r
-\r
- /* Hack -- Validate the paths */\r
- validate_dir(ANGBAND_DIR_APEX, FALSE);\r
- validate_dir(ANGBAND_DIR_BONE, FALSE);\r
-\r
- /* Allow missing 'edit' directory */\r
- if (!check_dir(ANGBAND_DIR_EDIT))\r
- {\r
- /* Must have 'data'! */\r
- validate_dir(ANGBAND_DIR_DATA, TRUE);\r
- }\r
- else\r
- {\r
- /* Don't need 'data' */\r
- validate_dir(ANGBAND_DIR_DATA, FALSE);\r
- }\r
-\r
- validate_dir(ANGBAND_DIR_FILE, TRUE);\r
- validate_dir(ANGBAND_DIR_HELP, FALSE);\r
- validate_dir(ANGBAND_DIR_INFO, FALSE);\r
- validate_dir(ANGBAND_DIR_PREF, TRUE);\r
- validate_dir(ANGBAND_DIR_SAVE, FALSE);\r
- validate_dir(ANGBAND_DIR_USER, TRUE);\r
- validate_dir(ANGBAND_DIR_XTRA, TRUE);\r
-\r
- /* Build the filename */\r
- path_build(path, sizeof(path), ANGBAND_DIR_FILE, _("news_j.txt", "news.txt"));\r
-\r
- /* Hack -- Validate the "news.txt" file */\r
- validate_file(path);\r
-\r
-\r
-#if 0 /* #ifndef JP */\r
- /* Build the "font" path */\r
- path_build(path, sizeof(path), ANGBAND_DIR_XTRA, "font");\r
-\r
- /* Allocate the path */\r
- ANGBAND_DIR_XTRA_FONT = string_make(path);\r
-\r
- /* Validate the "font" directory */\r
- validate_dir(ANGBAND_DIR_XTRA_FONT, TRUE);\r
-\r
- /* Build the filename */\r
- path_build(path, sizeof(path), ANGBAND_DIR_XTRA_FONT, "8X13.FON");\r
-\r
- /* Hack -- Validate the basic font */\r
- validate_file(path);\r
-#endif\r
-\r
-\r
-#ifdef USE_GRAPHICS\r
-\r
- /* Build the "graf" path */\r
- path_build(path, sizeof(path), ANGBAND_DIR_XTRA, "graf");\r
-\r
- /* Allocate the path */\r
- ANGBAND_DIR_XTRA_GRAF = string_make(path);\r
-\r
- /* Validate the "graf" directory */\r
- validate_dir(ANGBAND_DIR_XTRA_GRAF, TRUE);\r
-\r
-#endif /* USE_GRAPHICS */\r
-\r
-\r
-#ifdef USE_SOUND\r
-\r
- /* Build the "sound" path */\r
- path_build(path, sizeof(path), ANGBAND_DIR_XTRA, "sound");\r
-\r
- /* Allocate the path */\r
- ANGBAND_DIR_XTRA_SOUND = string_make(path);\r
-\r
- /* Validate the "sound" directory */\r
- validate_dir(ANGBAND_DIR_XTRA_SOUND, FALSE);\r
-\r
-#endif /* USE_SOUND */\r
-\r
-#ifdef USE_MUSIC\r
-\r
- /* Build the "music" path */\r
- path_build(path, sizeof(path), ANGBAND_DIR_XTRA, "music");\r
-\r
- /* Allocate the path */\r
- ANGBAND_DIR_XTRA_MUSIC = string_make(path);\r
-\r
- /* Validate the "music" directory */\r
- validate_dir(ANGBAND_DIR_XTRA_MUSIC, FALSE);\r
-\r
-#endif /* USE_MUSIC */\r
-\r
- /* Build the "help" path */\r
- path_build(path, sizeof(path), ANGBAND_DIR_XTRA, "help");\r
-\r
- /* Allocate the path */\r
- ANGBAND_DIR_XTRA_HELP = string_make(path);\r
-\r
- /* Validate the "help" directory */\r
- /* validate_dir(ANGBAND_DIR_XTRA_HELP); */\r
-}\r
-\r
-/*!\r
- * @brief (Windows固有)変愚蛮怒が起動済かどうかのチェック\r
- */\r
-static bool is_already_running(void)\r
-{\r
- bool result = FALSE;\r
- HANDLE hMutex;\r
-\r
- hMutex = CreateMutex(NULL, TRUE, VERSION_NAME);\r
- if (GetLastError() == ERROR_ALREADY_EXISTS)\r
- {\r
- result = TRUE;\r
- }\r
- return result;\r
-}\r
-\r
-\r
-/*!\r
- * @brief (Windows固有)Windowsアプリケーションとしてのエントリポイント\r
- */\r
-int FAR PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInst,\r
- LPSTR lpCmdLine, int nCmdShow)\r
-{\r
- int i;\r
-\r
- WNDCLASS wc;\r
- HDC hdc;\r
- MSG msg;\r
-\r
- setlocale(LC_ALL, "ja_JP.utf8");\r
-\r
- /* Unused */\r
- (void)nCmdShow;\r
-\r
- /* Save globally */\r
- hInstance = hInst;\r
- \r
- \r
- /* Prevent multiple run */\r
- if (is_already_running())\r
- {\r
- MessageBox(NULL,\r
- _("変愚蛮怒はすでに起動しています。", "Hengband is already running."), \r
- _("エラー!", "Error") ,\r
- MB_ICONEXCLAMATION | MB_OK | MB_ICONSTOP);\r
- return FALSE;\r
- }\r
-\r
- if (hPrevInst == NULL)\r
- {\r
- wc.style = CS_CLASSDC;\r
- wc.lpfnWndProc = AngbandWndProc;\r
- wc.cbClsExtra = 0;\r
- wc.cbWndExtra = 4; /* one long pointer to term_data */\r
- wc.hInstance = hInst;\r
- wc.hIcon = hIcon = LoadIcon(hInst, AppName);\r
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);\r
- wc.hbrBackground = GetStockObject(BLACK_BRUSH);\r
- wc.lpszMenuName = AppName;\r
- wc.lpszClassName = AppName;\r
-\r
- if (!RegisterClass(&wc)) exit(1);\r
-\r
- wc.lpfnWndProc = AngbandListProc;\r
- wc.lpszMenuName = NULL;\r
- wc.lpszClassName = AngList;\r
-\r
- if (!RegisterClass(&wc)) exit(2);\r
-\r
-#ifdef USE_SAVER\r
-\r
- wc.style = CS_VREDRAW | CS_HREDRAW | CS_SAVEBITS | CS_DBLCLKS;\r
- wc.lpfnWndProc = AngbandSaverProc;\r
- wc.hCursor = NULL;\r
- wc.lpszMenuName = NULL;\r
- wc.lpszClassName = "WindowsScreenSaverClass";\r
-\r
- if (!RegisterClass(&wc)) exit(3);\r
-\r
-#endif\r
-\r
- }\r
-\r
- /* Temporary hooks */\r
- plog_aux = hack_plog;\r
- quit_aux = hack_quit;\r
- core_aux = hack_quit;\r
-\r
- /* Prepare the filepaths */\r
- init_stuff();\r
-\r
- /* Initialize the keypress analyzer */\r
- for (i = 0; special_key_list[i]; ++i)\r
- {\r
- special_key[special_key_list[i]] = TRUE;\r
- }\r
- /* Initialize the keypress analyzer */\r
- for (i = 0; ignore_key_list[i]; ++i)\r
- {\r
- ignore_key[ignore_key_list[i]] = TRUE;\r
- }\r
-\r
- /* Determine if display is 16/256/true color */\r
- hdc = GetDC(NULL);\r
- colors16 = (GetDeviceCaps(hdc, BITSPIXEL) == 4);\r
- paletted = ((GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) ? TRUE : FALSE);\r
- ReleaseDC(NULL, hdc);\r
-\r
- /* Initialize the colors */\r
- for (i = 0; i < 256; i++)\r
- {\r
- byte rv, gv, bv;\r
-\r
- /* Extract desired values */\r
- rv = angband_color_table[i][1];\r
- gv = angband_color_table[i][2];\r
- bv = angband_color_table[i][3];\r
-\r
- /* Extract the "complex" code */\r
- win_clr[i] = PALETTERGB(rv, gv, bv);\r
-\r
- /* Save the "simple" code */\r
- angband_color_table[i][0] = win_pal[i];\r
- }\r
-\r
- /* Prepare the windows */\r
- init_windows();\r
-\r
- /* bg */\r
- init_bg();\r
-\r
- /* Activate hooks */\r
- plog_aux = hook_plog;\r
- quit_aux = hook_quit;\r
- core_aux = hook_quit;\r
-\r
- /* Set the system suffix */\r
- ANGBAND_SYS = "win";\r
-\r
- /* Set the keyboard suffix */\r
- if (7 != GetKeyboardType(0))\r
- ANGBAND_KEYBOARD = "0";\r
- else\r
- {\r
- /* Japanese keyboard */\r
- switch (GetKeyboardType(1))\r
- {\r
- case 0x0D01: case 0x0D02:\r
- case 0x0D03: case 0x0D04:\r
- case 0x0D05: case 0x0D06:\r
- /* NEC PC-98x1 */\r
- ANGBAND_KEYBOARD = "NEC98";\r
- break;\r
- default:\r
- /* PC/AT */\r
- ANGBAND_KEYBOARD = "JAPAN";\r
- }\r
- }\r
-\r
- /* Catch nasty signals */\r
- signals_init();\r
-\r
- Term_activate(term_screen);\r
- init_angband();\r
-\r
- /* We are now initialized */\r
- initialized = TRUE;\r
-#ifdef CHUUKEI\r
- if(lpCmdLine[0] == '-'){\r
- switch(lpCmdLine[1])\r
- {\r
- case 'p':\r
- case 'P':\r
- {\r
- if (!lpCmdLine[2]) break;\r
- chuukei_server = TRUE;\r
- if(connect_chuukei_server(&lpCmdLine[2])<0){\r
- msg_print("connect fail");\r
- return 0;\r
- }\r
- msg_print("connect");\r
- msg_print(NULL);\r
- break;\r
- }\r
-\r
- case 'c':\r
- case 'C':\r
- {\r
- if (!lpCmdLine[2]) break;\r
- chuukei_client = TRUE;\r
- connect_chuukei_server(&lpCmdLine[2]);\r
- play_game(FALSE);\r
- quit(NULL);\r
- return 0;\r
- }\r
- case 'X':\r
- case 'x':\r
- {\r
- if (!lpCmdLine[2]) break;\r
- prepare_browse_movie(&lpCmdLine[2]);\r
- play_game(FALSE);\r
- quit(NULL);\r
- return 0;\r
- }\r
- }\r
- }\r
-#endif\r
-\r
-#ifdef CHUUKEI\r
- /* Did the user double click on a save file? */\r
- if(!chuukei_server) check_for_save_file(lpCmdLine);\r
-#else\r
- /* Did the user double click on a save file? */\r
- check_for_save_file(lpCmdLine);\r
-#endif\r
-\r
- /* Prompt the user */\r
- prt(_("[ファイル] メニューの [新規] または [開く] を選択してください。", "[Choose 'New' or 'Open' from the 'File' menu]"), 23, _(8, 17));\r
-\r
- Term_fresh();\r
-\r
- /* Process messages forever */\r
- while (GetMessage(&msg, NULL, 0, 0))\r
- {\r
- TranslateMessage(&msg);\r
- DispatchMessage(&msg);\r
- }\r
-\r
- /* Paranoia */\r
- quit(NULL);\r
-\r
- /* Paranoia */\r
- return (0);\r
-}\r
-\r
-\r
-#endif /* WINDOWS */\r
-\r
+/*!
+* @file main-win.c
+* @brief Windows版固有実装(メインエントリポイント含む)
+* @date 2018/03/16
+* @author Hengband Team
+* @detail
+*
+* <h3>概要</h3>
+* Windows98かその前後の頃を起点としたAPI実装。
+* 各種のゲームエンジンは無論、
+* DirectXといった昨今描画に標準的となったライブラリも用いていない。
+* タイルの描画処理などについては、現在動作の詳細を検証中。
+*
+* <h3>フォーク元の概要</h3>
+* <p>
+* Copyright (c) 1997 Ben Harrison, Skirmantas Kligys, and others
+*
+* This software may be copied and distributed for educational, research,
+* and not for profit purposes provided that this copyright and statement
+* are included in all such copies.
+* </p>
+* <p>
+* This file helps Angband work with Windows computers.
+*
+* To use this file, use an appropriate "Makefile" or "Project File",
+* make sure that "WINDOWS" and/or "WIN32" are defined somewhere, and
+* make sure to obtain various extra files as described below.
+*
+* The official compilation uses the CodeWarrior Pro compiler, which
+* includes a special project file and precompilable header file.
+* </p>
+*
+* <p>
+* <del>See also "main-dos.c" and "main-ibm.c".</del>
+* </p>
+*
+* <p>
+* The "lib/user/pref-win.prf" file contains keymaps, macro definitions,
+* and/or color redefinitions.
+* </p>
+*
+* <p>
+* The "lib/user/font-win.prf" contains attr/char mappings for use with the
+* normal "lib/xtra/font/*.fon" font files.
+* </p>
+*
+* <p>
+* The "lib/user/graf-win.prf" contains attr/char mappings for use with the
+* special "lib/xtra/graf/*.bmp" bitmap files, which are activated by a menu
+* item.
+* </p>
+*
+* <p>
+* Compiling this file, and using the resulting executable, requires
+* several extra files not distributed with the standard Angband code.
+* If "USE_GRAPHICS" is defined, then "readdib.h" and "readdib.c" must
+* be placed into "src/", and the "8X8.BMP" bitmap file must be placed
+* into "lib/xtra/graf". In any case, some "*.fon" files (including
+* "8X13.FON" if nothing else) must be placed into "lib/xtra/font/".
+* If "USE_SOUND" is defined, then some special library (for example,
+* "winmm.lib") may need to be linked in, and desired "*.WAV" sound
+* files must be placed into "lib/xtra/sound/". All of these extra
+* files can be found in the "ext-win" archive.
+* </p>
+*
+* <p>
+* The "Term_xtra_win_clear()" function should probably do a low-level
+* clear of the current window, and redraw the borders and other things,
+* if only for efficiency.
+* </p>
+*
+* <p>
+* A simpler method is needed for selecting the "tile size" for windows.
+* </p>
+*
+* <p>
+* The various "warning" messages assume the existance of the "screen.w"
+* window, I think, and only a few calls actually check for its existance,
+* this may be okay since "NULL" means "on top of all windows". (?) The
+* user must never be allowed to "hide" the main window, or the "menubar"
+* will disappear.
+* </p>
+*
+* <p>
+* Special "Windows Help Files" can be placed into "lib/xtra/help/" for
+* use with the "winhelp.exe" program. These files *may* be available
+* at the ftp site somewhere, but I have not seen them.
+* </p>
+*
+* <p>
+* Initial framework (and most code) by Ben Harrison (benh@phial.com).
+*
+* Original code by Skirmantas Kligys (kligys@scf.usc.edu).
+*
+* Additional code by Ross E Becker (beckerr@cis.ohio-state.edu),
+* and Chris R. Martin (crm7479@tam2000.tamu.edu).
+* </p>
+*/
+
+#include "angband.h"
+
+#ifdef WINDOWS
+#include <windows.h>
+#include <direct.h>
+#include <locale.h>
+#include "z-term.h"
+
+/*
+ * Extract the "WIN32" flag from the compiler
+ */
+#if defined(__WIN32__) || defined(__WINNT__) || defined(__NT__)
+# ifndef WIN32
+# define WIN32
+# endif
+#endif
+
+
+/*
+ * Hack -- allow use of "screen saver" mode
+ */
+#define USE_SAVER
+
+
+/*
+ * Menu constants -- see "ANGBAND.RC"
+ */
+
+#define IDM_FILE_NEW 100
+#define IDM_FILE_OPEN 101
+#define IDM_FILE_SAVE 110
+#define IDM_FILE_SCORE 120
+#define IDM_FILE_MOVIE 121
+#define IDM_FILE_EXIT 130
+
+#define IDM_WINDOW_VIS_0 200
+#define IDM_WINDOW_VIS_1 201
+#define IDM_WINDOW_VIS_2 202
+#define IDM_WINDOW_VIS_3 203
+#define IDM_WINDOW_VIS_4 204
+#define IDM_WINDOW_VIS_5 205
+#define IDM_WINDOW_VIS_6 206
+#define IDM_WINDOW_VIS_7 207
+
+#define IDM_WINDOW_FONT_0 210
+#define IDM_WINDOW_FONT_1 211
+#define IDM_WINDOW_FONT_2 212
+#define IDM_WINDOW_FONT_3 213
+#define IDM_WINDOW_FONT_4 214
+#define IDM_WINDOW_FONT_5 215
+#define IDM_WINDOW_FONT_6 216
+#define IDM_WINDOW_FONT_7 217
+
+#define IDM_WINDOW_POS_0 220
+#define IDM_WINDOW_POS_1 221
+#define IDM_WINDOW_POS_2 222
+#define IDM_WINDOW_POS_3 223
+#define IDM_WINDOW_POS_4 224
+#define IDM_WINDOW_POS_5 225
+#define IDM_WINDOW_POS_6 226
+#define IDM_WINDOW_POS_7 227
+
+#define IDM_WINDOW_BIZ_0 230
+#define IDM_WINDOW_BIZ_1 231
+#define IDM_WINDOW_BIZ_2 232
+#define IDM_WINDOW_BIZ_3 233
+#define IDM_WINDOW_BIZ_4 234
+#define IDM_WINDOW_BIZ_5 235
+#define IDM_WINDOW_BIZ_6 236
+#define IDM_WINDOW_BIZ_7 237
+
+#define IDM_WINDOW_I_WID_0 240
+#define IDM_WINDOW_I_WID_1 241
+#define IDM_WINDOW_I_WID_2 242
+#define IDM_WINDOW_I_WID_3 243
+#define IDM_WINDOW_I_WID_4 244
+#define IDM_WINDOW_I_WID_5 245
+#define IDM_WINDOW_I_WID_6 246
+#define IDM_WINDOW_I_WID_7 247
+
+#define IDM_WINDOW_D_WID_0 250
+#define IDM_WINDOW_D_WID_1 251
+#define IDM_WINDOW_D_WID_2 252
+#define IDM_WINDOW_D_WID_3 253
+#define IDM_WINDOW_D_WID_4 254
+#define IDM_WINDOW_D_WID_5 255
+#define IDM_WINDOW_D_WID_6 256
+#define IDM_WINDOW_D_WID_7 257
+
+#define IDM_WINDOW_I_HGT_0 260
+#define IDM_WINDOW_I_HGT_1 261
+#define IDM_WINDOW_I_HGT_2 262
+#define IDM_WINDOW_I_HGT_3 263
+#define IDM_WINDOW_I_HGT_4 264
+#define IDM_WINDOW_I_HGT_5 265
+#define IDM_WINDOW_I_HGT_6 266
+#define IDM_WINDOW_I_HGT_7 267
+
+#define IDM_WINDOW_D_HGT_0 270
+#define IDM_WINDOW_D_HGT_1 271
+#define IDM_WINDOW_D_HGT_2 272
+#define IDM_WINDOW_D_HGT_3 273
+#define IDM_WINDOW_D_HGT_4 274
+#define IDM_WINDOW_D_HGT_5 275
+#define IDM_WINDOW_D_HGT_6 276
+#define IDM_WINDOW_D_HGT_7 277
+
+#define IDM_OPTIONS_NO_GRAPHICS 400
+#define IDM_OPTIONS_OLD_GRAPHICS 401
+#define IDM_OPTIONS_NEW_GRAPHICS 402
+#define IDM_OPTIONS_NEW2_GRAPHICS 403
+#define IDM_OPTIONS_BIGTILE 409
+#define IDM_OPTIONS_SOUND 410
+#define IDM_OPTIONS_MUSIC 411
+#define IDM_OPTIONS_SAVER 420
+#define IDM_OPTIONS_MAP 430
+#define IDM_OPTIONS_BG 440
+#define IDM_OPTIONS_OPEN_BG 441
+
+#define IDM_DUMP_SCREEN_HTML 450
+
+#define IDM_HELP_CONTENTS 901
+
+/*
+ * Exclude parts of WINDOWS.H that are not needed
+ */
+#define NOCOMM /* Comm driver APIs and definitions */
+#define NOLOGERROR /* LogError() and related definitions */
+#define NOPROFILER /* Profiler APIs */
+#define NOLFILEIO /* _l* file I/O routines */
+#define NOOPENFILE /* OpenFile and related definitions */
+#define NORESOURCE /* Resource management */
+#define NOATOM /* Atom management */
+#define NOLANGUAGE /* Character test routines */
+#define NOLSTRING /* lstr* string management routines */
+#define NODBCS /* Double-byte character set routines */
+#define NOKEYBOARDINFO /* Keyboard driver routines */
+#define NOCOLOR /* COLOR_* color values */
+#define NODRAWTEXT /* DrawText() and related definitions */
+#define NOSCALABLEFONT /* Truetype scalable font support */
+#define NOMETAFILE /* Metafile support */
+#define NOSYSTEMPARAMSINFO /* SystemParametersInfo() and SPI_* definitions */
+#define NODEFERWINDOWPOS /* DeferWindowPos and related definitions */
+#define NOKEYSTATES /* MK_* message key state flags */
+#define NOWH /* SetWindowsHook and related WH_* definitions */
+#define NOCLIPBOARD /* Clipboard APIs and definitions */
+#define NOICONS /* IDI_* icon IDs */
+#define NOMDI /* MDI support */
+#define NOHELP /* Help support */
+
+/* Not defined since it breaks Borland C++ 5.5 */
+/* #define NOCTLMGR */ /* Control management and controls */
+
+/*
+ * Exclude parts of WINDOWS.H that are not needed (Win32)
+ */
+#define WIN32_LEAN_AND_MEAN
+#define NONLS /* All NLS defines and routines */
+#define NOSERVICE /* All Service Controller routines, SERVICE_ equates, etc. */
+#define NOKANJI /* Kanji support stuff. */
+#define NOMCX /* Modem Configuration Extensions */
+
+/*
+ * Include the "windows" support file
+ */
+#include <windows.h>
+
+/*
+ * Exclude parts of MMSYSTEM.H that are not needed
+ */
+#define MMNODRV /* Installable driver support */
+#define MMNOWAVE /* Waveform support */
+#define MMNOMIDI /* MIDI support */
+#define MMNOAUX /* Auxiliary audio support */
+#define MMNOTIMER /* Timer support */
+#define MMNOJOY /* Joystick support */
+#define MMNOMCI /* MCI support */
+#define MMNOMMIO /* Multimedia file I/O support */
+#define MMNOMMSYSTEM /* General MMSYSTEM functions */
+
+/*
+ * Include some more files. Note: the Cygnus Cygwin compiler
+ * doesn't use mmsystem.h instead it includes the winmm library
+ * which performs a similar function.
+ */
+#include <mmsystem.h>
+#include <commdlg.h>
+
+/*
+ * HTML-Help requires htmlhelp.h and htmlhelp.lib from Microsoft's
+ * HTML Workshop < http://msdn.microsoft.com/workshop/author/htmlhelp/ >.
+ */
+/* #define HTML_HELP */
+
+#ifdef HTML_HELP
+#include <htmlhelp.h>
+#endif /* HTML_HELP */
+
+/*
+ * Include the support for loading bitmaps
+ */
+#ifdef USE_GRAPHICS
+# include "readdib.h"
+#endif
+
+/*
+ * Hack -- Fake declarations from "dos.h"
+ */
+#ifdef WIN32
+#define INVALID_FILE_NAME (DWORD)0xFFFFFFFF
+#else /* WIN32 */
+#define FA_LABEL 0x08 /* Volume label */
+#define FA_DIREC 0x10 /* Directory */
+unsigned _cdecl _dos_getfileattr(concptr , unsigned *);
+#endif /* WIN32 */
+
+/*
+ * Silliness in WIN32 drawing routine
+ */
+#ifdef WIN32
+# define MoveTo(H,X,Y) MoveToEx(H, X, Y, NULL)
+#endif /* WIN32 */
+
+/*
+ * Silliness for Windows 95
+ */
+#ifndef WS_EX_TOOLWINDOW
+# define WS_EX_TOOLWINDOW 0
+#endif
+
+/*
+ * Foreground color bits (hard-coded by DOS)
+ */
+#define VID_BLACK 0x00
+#define VID_BLUE 0x01
+#define VID_GREEN 0x02
+#define VID_CYAN 0x03
+#define VID_RED 0x04
+#define VID_MAGENTA 0x05
+#define VID_YELLOW 0x06
+#define VID_WHITE 0x07
+
+/*
+ * Bright text (hard-coded by DOS)
+ */
+#define VID_BRIGHT 0x08
+
+/*
+ * Background color bits (hard-coded by DOS)
+ */
+#define VUD_BLACK 0x00
+#define VUD_BLUE 0x10
+#define VUD_GREEN 0x20
+#define VUD_CYAN 0x30
+#define VUD_RED 0x40
+#define VUD_MAGENTA 0x50
+#define VUD_YELLOW 0x60
+#define VUD_WHITE 0x70
+
+/*
+ * Blinking text (hard-coded by DOS)
+ */
+#define VUD_BRIGHT 0x80
+
+
+/*
+ * Forward declare
+ */
+typedef struct _term_data term_data;
+
+/*!
+ * @struct _term_data
+ * @brief ターム情報構造体 / Extra "term" data
+ * @details
+ * <p>
+ * pos_x / pos_y は各タームの左上点座標を指す。
+ * </p>
+ * <p>
+ * tile_wid / tile_hgt は[ウィンドウ]メニューのタイルの幅/高さを~を
+ * 1ドットずつ調整するステータスを指す。
+ * また、フォントを変更すると都度自動調整される。
+ * </p>
+ * <p>
+ * Note the use of "font_want" for the names of the font file requested by
+ * the user, and the use of "font_file" for the currently active font file.
+ *
+ * The "font_file" is uppercased, and takes the form "8X13.FON", while
+ * "font_want" can be in almost any form as long as it could be construed
+ * as attempting to represent the name of a font.
+ * </p>
+ */
+struct _term_data
+{
+ term t;
+ concptr s;
+ HWND w;
+ DWORD dwStyle;
+ DWORD dwExStyle;
+
+ uint keys;
+ TERM_LEN rows; /* int -> uint */
+ TERM_LEN cols;
+
+ uint pos_x; //!< タームの左上X座標
+ uint pos_y; //!< タームの左上Y座標
+ uint size_wid;
+ uint size_hgt;
+ uint size_ow1;
+ uint size_oh1;
+ uint size_ow2;
+ uint size_oh2;
+
+ bool size_hack;
+ bool xtra_hack;
+ bool visible;
+ bool bizarre;
+ concptr font_want;
+ concptr font_file;
+ HFONT font_id;
+ int font_wid; //!< フォント横幅
+ int font_hgt; //!< フォント縦幅
+ int tile_wid; //!< タイル横幅
+ int tile_hgt; //!< タイル縦幅
+
+ uint map_tile_wid;
+ uint map_tile_hgt;
+
+ bool map_active;
+#if 1 /* #ifdef JP */
+ LOGFONT lf;
+#endif
+
+ bool posfix;
+
+};
+
+#define MAX_TERM_DATA 8 //!< Maximum number of windows
+
+static term_data data[MAX_TERM_DATA]; //!< An array of term_data's
+static term_data *my_td; //!< Hack -- global "window creation" pointer
+POINT normsize; //!< Remember normal size of main window when maxmized
+
+/*
+ * was main window maximized on previous playing
+ */
+bool win_maximized = FALSE;
+
+/*
+ * game in progress
+ */
+bool game_in_progress = FALSE;
+
+/*
+ * note when "open"/"new" become valid
+ */
+bool initialized = FALSE;
+
+/*
+ * screen paletted, i.e. 256 colors
+ */
+bool paletted = FALSE;
+
+/*
+ * 16 colors screen, don't use RGB()
+ */
+bool colors16 = FALSE;
+
+/*
+ * Saved instance handle
+ */
+static HINSTANCE hInstance;
+
+/*
+ * Yellow brush for the cursor
+ */
+static HBRUSH hbrYellow;
+
+/*
+ * An icon
+ */
+static HICON hIcon;
+
+/*
+ * A palette
+ */
+static HPALETTE hPal;
+
+/* bg */
+static HBITMAP hBG = NULL;
+static int use_bg = 0; //!< 背景使用フラグ、1なら私用。
+static char bg_bitmap_file[1024] = "bg.bmp"; //!< 現在の背景ビットマップファイル名。
+
+#ifdef USE_SAVER
+
+/*
+ * The screen saver window
+ */
+static HWND hwndSaver;
+
+#endif /* USE_SAVER */
+
+
+#ifdef USE_GRAPHICS
+
+/*!
+ * 現在使用中のタイルID(0ならば未使用)
+ * Flag set once "graphics" has been initialized
+ */
+static byte_hack current_graphics_mode = 0;
+
+/*
+ * The global bitmap
+ */
+static DIBINIT infGraph;
+
+/*
+ * The global bitmap mask
+ */
+static DIBINIT infMask;
+
+#endif /* USE_GRAPHICS */
+
+
+#ifdef USE_SOUND
+
+/*
+ * Flag set once "sound" has been initialized
+ */
+static bool can_use_sound = FALSE;
+
+#define SAMPLE_MAX 8
+/*
+ * An array of sound file names
+ */
+static concptr sound_file[SOUND_MAX][SAMPLE_MAX];
+
+#endif /* USE_SOUND */
+
+
+
+#ifdef USE_MUSIC
+
+#define SAMPLE_MUSIC_MAX 16
+static concptr music_file[MUSIC_BASIC_MAX][SAMPLE_MUSIC_MAX];
+static concptr dungeon_music_file[1000][SAMPLE_MUSIC_MAX];
+static concptr town_music_file[1000][SAMPLE_MUSIC_MAX];
+static concptr quest_music_file[1000][SAMPLE_MUSIC_MAX];
+static bool can_use_music = FALSE;
+
+static MCI_OPEN_PARMS mop;
+static char mci_device_type[256];
+
+int current_music_type = 0;
+int current_music_id = 0;
+
+#endif /* USE_MUSIC */
+
+
+/*
+ * Full path to ANGBAND.INI
+ */
+static concptr ini_file = NULL;
+
+/*
+ * Name of application
+ */
+static concptr AppName = "ANGBAND";
+
+/*
+ * Name of sub-window type
+ */
+static concptr AngList = "AngList";
+
+/*
+ * Directory names
+ */
+static concptr ANGBAND_DIR_XTRA_GRAF;
+static concptr ANGBAND_DIR_XTRA_SOUND;
+static concptr ANGBAND_DIR_XTRA_MUSIC;
+static concptr ANGBAND_DIR_XTRA_HELP;
+#if 0 /* #ifndef JP */
+static concptr ANGBAND_DIR_XTRA_FONT;
+#endif
+#ifdef USE_MUSIC
+static concptr ANGBAND_DIR_XTRA_MUSIC;
+#endif
+
+
+/*
+ * The "complex" color values
+ */
+static COLORREF win_clr[256];
+
+
+/*
+ * Flag for macro trigger with dump ASCII
+ */
+static bool Term_no_press = FALSE;
+
+/*
+ * Copy and paste
+ */
+static bool mouse_down = FALSE;
+static bool paint_rect = FALSE;
+static TERM_LEN mousex = 0, mousey = 0;
+static TERM_LEN oldx, oldy;
+
+
+/*!
+ * @brief The "simple" color values
+ * @details
+ * See "main-ibm.c" for original table information
+ * The entries below are taken from the "color bits" defined above.
+ * Note that many of the choices below suck, but so do crappy monitors.
+ */
+static BYTE win_pal[256] =
+{
+ VID_BLACK, /* Dark */
+ VID_WHITE, /* White */
+ VID_CYAN, /* Slate XXX */
+ VID_RED | VID_BRIGHT, /* Orange XXX */
+ VID_RED, /* Red */
+ VID_GREEN, /* Green */
+ VID_BLUE, /* Blue */
+ VID_YELLOW, /* Umber XXX */
+ VID_BLACK | VID_BRIGHT, /* Light Dark */
+ VID_CYAN | VID_BRIGHT, /* Light Slate XXX */
+ VID_MAGENTA, /* Violet XXX */
+ VID_YELLOW | VID_BRIGHT, /* Yellow */
+ VID_MAGENTA | VID_BRIGHT, /* Light Red XXX */
+ VID_GREEN | VID_BRIGHT, /* Light Green */
+ VID_BLUE | VID_BRIGHT, /* Light Blue */
+ VID_YELLOW /* Light Umber XXX */
+};
+
+
+/*
+ * Hack -- define which keys are "special"
+ */
+static bool special_key[256];
+static bool ignore_key[256];
+
+#if 1
+/*
+ * Hack -- initialization list for "special_key"
+ */
+static byte special_key_list[] = {
+ VK_CLEAR, VK_PAUSE, VK_CAPITAL,
+ VK_KANA, VK_JUNJA, VK_FINAL, VK_KANJI,
+ VK_CONVERT, VK_NONCONVERT, VK_ACCEPT, VK_MODECHANGE,
+ VK_PRIOR, VK_NEXT, VK_END, VK_HOME,
+ VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN,
+ VK_SELECT, VK_PRINT, VK_EXECUTE, VK_SNAPSHOT,
+ VK_INSERT, VK_DELETE, VK_HELP, VK_APPS,
+ VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3,
+ VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7,
+ VK_NUMPAD8, VK_NUMPAD9, VK_MULTIPLY, VK_ADD,
+ VK_SEPARATOR, VK_SUBTRACT, VK_DECIMAL, VK_DIVIDE,
+ VK_F1, VK_F2, VK_F3, VK_F4, VK_F5, VK_F6,
+ VK_F7, VK_F8, VK_F9, VK_F10, VK_F11, VK_F12,
+ VK_F13, VK_F14, VK_F15, VK_F16, VK_F17, VK_F18,
+ VK_F19,VK_F20, VK_F21, VK_F22, VK_F23, VK_F24,
+ VK_NUMLOCK, VK_SCROLL, VK_ATTN, VK_CRSEL,
+ VK_EXSEL, VK_EREOF, VK_PLAY, VK_ZOOM,
+ VK_NONAME, VK_PA1,
+ 0 /* End of List */
+};
+
+static byte ignore_key_list[] = {
+ VK_ESCAPE, VK_TAB, VK_SPACE,
+ 'F', 'W', 'O', /*'H',*/ /* these are menu characters.*/
+ VK_SHIFT, VK_CONTROL, VK_MENU, VK_LWIN, VK_RWIN,
+ VK_LSHIFT, VK_RSHIFT, VK_LCONTROL, VK_RCONTROL,
+ VK_LMENU, VK_RMENU,
+ 0 /* End of List */
+};
+#else
+/*
+ * Hack -- initialization list for "special_key"
+ *
+ * We ignore the modifier keys (shift, control, alt, num lock, scroll lock),
+ * and the normal keys (escape, tab, return, letters, numbers, etc), but we
+ * catch the keypad keys (with and without numlock set, including keypad 5),
+ * the function keys (including the "menu" key which maps to F10), and the
+ * "pause" key (between scroll lock and numlock). We also catch a few odd
+ * keys which I do not recognize, but which are listed among keys which we
+ * do catch, so they should be harmless to catch.
+ */
+static byte special_key_list[] =
+{
+ VK_CLEAR, /* 0x0C (KP<5>) */
+
+ VK_PAUSE, /* 0x13 (pause) */
+
+ VK_PRIOR, /* 0x21 (KP<9>) */
+ VK_NEXT, /* 0x22 (KP<3>) */
+ VK_END, /* 0x23 (KP<1>) */
+ VK_HOME, /* 0x24 (KP<7>) */
+ VK_LEFT, /* 0x25 (KP<4>) */
+ VK_UP, /* 0x26 (KP<8>) */
+ VK_RIGHT, /* 0x27 (KP<6>) */
+ VK_DOWN, /* 0x28 (KP<2>) */
+ VK_SELECT, /* 0x29 (?????) */
+ VK_PRINT, /* 0x2A (?????) */
+ VK_EXECUTE, /* 0x2B (?????) */
+ VK_SNAPSHOT, /* 0x2C (?????) */
+ VK_INSERT, /* 0x2D (KP<0>) */
+ VK_DELETE, /* 0x2E (KP<.>) */
+ VK_HELP, /* 0x2F (?????) */
+#if 0
+ VK_NUMPAD0, /* 0x60 (KP<0>) */
+ VK_NUMPAD1, /* 0x61 (KP<1>) */
+ VK_NUMPAD2, /* 0x62 (KP<2>) */
+ VK_NUMPAD3, /* 0x63 (KP<3>) */
+ VK_NUMPAD4, /* 0x64 (KP<4>) */
+ VK_NUMPAD5, /* 0x65 (KP<5>) */
+ VK_NUMPAD6, /* 0x66 (KP<6>) */
+ VK_NUMPAD7, /* 0x67 (KP<7>) */
+ VK_NUMPAD8, /* 0x68 (KP<8>) */
+ VK_NUMPAD9, /* 0x69 (KP<9>) */
+ VK_MULTIPLY, /* 0x6A (KP<*>) */
+ VK_ADD, /* 0x6B (KP<+>) */
+ VK_SEPARATOR, /* 0x6C (?????) */
+ VK_SUBTRACT, /* 0x6D (KP<->) */
+ VK_DECIMAL, /* 0x6E (KP<.>) */
+ VK_DIVIDE, /* 0x6F (KP</>) */
+#endif
+ VK_F1, /* 0x70 */
+ VK_F2, /* 0x71 */
+ VK_F3, /* 0x72 */
+ VK_F4, /* 0x73 */
+ VK_F5, /* 0x74 */
+ VK_F6, /* 0x75 */
+ VK_F7, /* 0x76 */
+ VK_F8, /* 0x77 */
+ VK_F9, /* 0x78 */
+ VK_F10, /* 0x79 */
+ VK_F11, /* 0x7A */
+ VK_F12, /* 0x7B */
+ VK_F13, /* 0x7C */
+ VK_F14, /* 0x7D */
+ VK_F15, /* 0x7E */
+ VK_F16, /* 0x7F */
+ VK_F17, /* 0x80 */
+ VK_F18, /* 0x81 */
+ VK_F19, /* 0x82 */
+ VK_F20, /* 0x83 */
+ VK_F21, /* 0x84 */
+ VK_F22, /* 0x85 */
+ VK_F23, /* 0x86 */
+ VK_F24, /* 0x87 */
+ 0
+};
+#endif
+
+
+/* Function prototype */
+
+static bool is_already_running(void);
+
+
+/* bg */
+static void delete_bg(void)
+{
+ if (hBG != NULL)
+ {
+ DeleteObject(hBG);
+ hBG = NULL;
+ }
+}
+
+static int init_bg(void)
+{
+ char * bmfile = bg_bitmap_file;
+
+ delete_bg();
+ if (use_bg == 0) return 0;
+
+ hBG = LoadImage(NULL, bmfile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
+ if (!hBG) {
+ plog_fmt(_("壁紙用ビットマップ '%s' を読み込めません。", "Can't load the bitmap file '%s'."), bmfile);
+ use_bg = 0;
+ return 0;
+ }
+ use_bg = 1;
+ return 1;
+}
+
+static void DrawBG(HDC hdc, RECT *r)
+{
+ HDC hdcSrc;
+ HBITMAP hOld;
+ BITMAP bm;
+ int x = r->left, y = r->top;
+ int nx, ny, sx, sy, swid, shgt, cwid, chgt;
+
+ if (!use_bg || !hBG)
+ return;
+
+ nx = x; ny = y;
+ GetObject(hBG, sizeof(bm), &bm);
+ swid = bm.bmWidth; shgt = bm.bmHeight;
+
+ hdcSrc = CreateCompatibleDC(hdc);
+ hOld = SelectObject(hdcSrc, hBG);
+
+ do {
+ sx = nx % swid;
+ cwid = MIN(swid - sx, r->right - nx);
+ do {
+ sy = ny % shgt;
+ chgt = MIN(shgt - sy, r->bottom - ny);
+ BitBlt(hdc, nx, ny, cwid, chgt, hdcSrc, sx, sy, SRCCOPY);
+ ny += chgt;
+ } while (ny < r->bottom);
+ ny = y;
+ nx += cwid;
+ } while (nx < r->right);
+
+ SelectObject(hdcSrc, hOld);
+ DeleteDC(hdcSrc);
+}
+
+#if 0
+/*
+ * Hack -- given a pathname, point at the filename
+ */
+static concptr extract_file_name(concptr s)
+{
+ concptr p;
+
+ /* Start at the end */
+ p = s + strlen(s) - 1;
+
+ /* Back up to divider */
+ while ((p >= s) && (*p != ':') && (*p != '\\')) p--;
+
+ /* Return file name */
+ return (p+1);
+}
+#endif
+
+
+/*
+ * Hack -- given a simple filename, extract the "font size" info
+ *
+ * Return a pointer to a static buffer holding the capitalized base name.
+ */
+#if 0 /* #ifndef JP */
+static char *analyze_font(char *path, int *wp, int *hp)
+{
+ int wid, hgt;
+
+ char *s, *p;
+
+ /* Start at the end */
+ p = path + strlen(path) - 1;
+
+ /* Back up to divider */
+ while ((p >= path) && (*p != ':') && (*p != '\\')) --p;
+
+ /* Advance to file name */
+ ++p;
+
+ /* Capitalize */
+ for (s = p; *s; ++s)
+ {
+ /* Capitalize (be paranoid) */
+ if (islower(*s)) *s = toupper(*s);
+ }
+
+ /* Find first 'X' */
+ s = my_strchr(p, 'X');
+
+ /* Extract font width */
+ wid = atoi(p);
+
+ /* Extract height */
+ hgt = s ? atoi(s+1) : 0;
+
+ /* Save results */
+ (*wp) = wid;
+ (*hp) = hgt;
+ return (p);
+}
+#endif
+
+
+/*
+ * Check for existance of a file
+ */
+static bool check_file(concptr s)
+{
+ char path[1024];
+
+#ifdef WIN32
+
+ DWORD attrib;
+
+#else /* WIN32 */
+
+ unsigned int attrib;
+
+#endif /* WIN32 */
+
+ /* Copy it */
+ strcpy(path, s);
+
+#ifdef WIN32
+
+ /* Examine */
+ attrib = GetFileAttributes(path);
+
+ /* Require valid filename */
+ if (attrib == INVALID_FILE_NAME) return (FALSE);
+
+ /* Prohibit directory */
+ if (attrib & FILE_ATTRIBUTE_DIRECTORY) return (FALSE);
+
+#else /* WIN32 */
+
+ /* Examine and verify */
+ if (_dos_getfileattr(path, &attrib)) return (FALSE);
+
+ /* Prohibit something */
+ if (attrib & FA_LABEL) return (FALSE);
+
+ /* Prohibit directory */
+ if (attrib & FA_DIREC) return (FALSE);
+
+#endif /* WIN32 */
+
+ /* Success */
+ return (TRUE);
+}
+
+
+/*
+ * Check for existance of a directory
+ */
+static bool check_dir(concptr s)
+{
+ int i;
+
+ char path[1024];
+
+#ifdef WIN32
+
+ DWORD attrib;
+
+#else /* WIN32 */
+
+ unsigned int attrib;
+
+#endif /* WIN32 */
+
+ /* Copy it */
+ strcpy(path, s);
+
+ /* Check length */
+ i = strlen(path);
+
+ /* Remove trailing backslash */
+ if (i && (path[i-1] == '\\')) path[--i] = '\0';
+
+#ifdef WIN32
+
+ /* Examine */
+ attrib = GetFileAttributes(path);
+
+ /* Require valid filename */
+ if (attrib == INVALID_FILE_NAME) return (FALSE);
+
+ /* Require directory */
+ if (!(attrib & FILE_ATTRIBUTE_DIRECTORY)) return (FALSE);
+
+#else /* WIN32 */
+
+ /* Examine and verify */
+ if (_dos_getfileattr(path, &attrib)) return (FALSE);
+
+ /* Prohibit something */
+ if (attrib & FA_LABEL) return (FALSE);
+
+ /* Require directory */
+ if (!(attrib & FA_DIREC)) return (FALSE);
+
+#endif /* WIN32 */
+
+ /* Success */
+ return (TRUE);
+}
+
+
+/*
+ * Validate a file
+ */
+static void validate_file(concptr s)
+{
+ /* Verify or fail */
+ if (!check_file(s))
+ {
+ quit_fmt(_("必要なファイル[%s]が見あたりません。", "Cannot find required file:\n%s"), s);
+ }
+}
+
+
+/*
+ * Validate a directory
+ */
+static void validate_dir(concptr s, bool vital)
+{
+ /* Verify or fail */
+ if (!check_dir(s))
+ {
+ /* This directory contains needed data */
+ if (vital)
+ {
+ quit_fmt(_("必要なディレクトリ[%s]が見あたりません。", "Cannot find required directory:\n%s"), s);
+ }
+ /* Attempt to create this directory */
+ else if (mkdir(s))
+ {
+ quit_fmt("Unable to create directory:\n%s", s);
+ }
+ }
+}
+
+
+/*!
+ * @brief (Windows版固有実装)Get the "size" for a window
+ */
+static void term_getsize(term_data *td)
+{
+ RECT rc;
+ TERM_LEN wid, hgt;
+
+ /* Paranoia */
+ if (td->cols < 1) td->cols = 1;
+ if (td->rows < 1) td->rows = 1;
+
+ /* Window sizes */
+ wid = td->cols * td->tile_wid + td->size_ow1 + td->size_ow2;
+ hgt = td->rows * td->tile_hgt + td->size_oh1 + td->size_oh2;
+
+ /* Fake window size */
+ rc.left = 0;
+ rc.right = rc.left + wid;
+ rc.top = 0;
+ rc.bottom = rc.top + hgt;
+
+ /* rc.right += 1; */
+ /* rc.bottom += 1; */
+
+ /* Adjust */
+ AdjustWindowRectEx(&rc, td->dwStyle, TRUE, td->dwExStyle);
+
+ /* Total size */
+ td->size_wid = rc.right - rc.left;
+ td->size_hgt = rc.bottom - rc.top;
+
+ /* See CreateWindowEx */
+ if (!td->w) return;
+
+ /* Extract actual location */
+ GetWindowRect(td->w, &rc);
+
+ /* Save the location */
+ td->pos_x = rc.left;
+ td->pos_y = rc.top;
+}
+
+
+/*
+ * Write the "prefs" for a single term
+ */
+static void save_prefs_aux(int i)
+{
+ term_data *td = &data[i];
+ GAME_TEXT sec_name[128];
+ char buf[1024];
+
+ RECT rc;
+ WINDOWPLACEMENT lpwndpl;
+
+ /* Paranoia */
+ if (!td->w) return;
+
+ /* Make section name */
+ sprintf(sec_name, "Term-%d", i);
+
+ /* Visible */
+ if (i > 0)
+ {
+ strcpy(buf, td->visible ? "1" : "0");
+ WritePrivateProfileString(sec_name, "Visible", buf, ini_file);
+ }
+
+ /* Font */
+#ifdef JP
+ strcpy(buf, td->lf.lfFaceName[0]!='\0' ? td->lf.lfFaceName : "MS ゴシック");
+#else
+#if 0
+ strcpy(buf, td->font_file ? td->font_file : "8X13.FON");
+#else
+ strcpy(buf, td->lf.lfFaceName[0]!='\0' ? td->lf.lfFaceName : "Courier");
+#endif
+#endif
+
+ WritePrivateProfileString(sec_name, "Font", buf, ini_file);
+
+#if 1 /* #ifdef JP */
+ wsprintf(buf, "%d", td->lf.lfWidth);
+ WritePrivateProfileString(sec_name, "FontWid", buf, ini_file);
+ wsprintf(buf, "%d", td->lf.lfHeight);
+ WritePrivateProfileString(sec_name, "FontHgt", buf, ini_file);
+ wsprintf(buf, "%d", td->lf.lfWeight);
+ WritePrivateProfileString(sec_name, "FontWgt", buf, ini_file);
+#endif
+ /* Bizarre */
+ strcpy(buf, td->bizarre ? "1" : "0");
+ WritePrivateProfileString(sec_name, "Bizarre", buf, ini_file);
+
+ /* Tile size (x) */
+ wsprintf(buf, "%d", td->tile_wid);
+ WritePrivateProfileString(sec_name, "TileWid", buf, ini_file);
+
+ /* Tile size (y) */
+ wsprintf(buf, "%d", td->tile_hgt);
+ WritePrivateProfileString(sec_name, "TileHgt", buf, ini_file);
+
+ /* Get window placement and dimensions */
+ lpwndpl.length = sizeof(WINDOWPLACEMENT);
+ GetWindowPlacement(td->w, &lpwndpl);
+
+ /* Acquire position in *normal* mode (not minimized) */
+ rc = lpwndpl.rcNormalPosition;
+
+ /* Window size (x) */
+ if (i == 0) wsprintf(buf, "%d", normsize.x);
+ else wsprintf(buf, "%d", td->cols);
+ WritePrivateProfileString(sec_name, "NumCols", buf, ini_file);
+
+ /* Window size (y) */
+ if (i == 0) wsprintf(buf, "%d", normsize.y);
+ else wsprintf(buf, "%d", td->rows);
+ WritePrivateProfileString(sec_name, "NumRows", buf, ini_file);
+
+ /* Maxmized (only main window) */
+ if (i == 0)
+ {
+ strcpy(buf, IsZoomed(td->w) ? "1" : "0");
+ WritePrivateProfileString(sec_name, "Maximized", buf, ini_file);
+ }
+
+ /* Acquire position */
+ GetWindowRect(td->w, &rc);
+
+ /* Window position (x) */
+ wsprintf(buf, "%d", rc.left);
+ WritePrivateProfileString(sec_name, "PositionX", buf, ini_file);
+
+ /* Window position (y) */
+ wsprintf(buf, "%d", rc.top);
+ WritePrivateProfileString(sec_name, "PositionY", buf, ini_file);
+
+ /* Window Z position */
+ if (i > 0)
+ {
+ strcpy(buf, td->posfix ? "1" : "0");
+ WritePrivateProfileString(sec_name, "PositionFix", buf, ini_file);
+ }
+}
+
+
+/*
+ * Write the "prefs"
+ * We assume that the windows have all been initialized
+ */
+static void save_prefs(void)
+{
+ int i;
+
+ char buf[128];
+
+ /* Save the "arg_graphics" flag */
+ sprintf(buf, "%d", arg_graphics);
+ WritePrivateProfileString("Angband", "Graphics", buf, ini_file);
+
+ /* Save the "arg_bigtile" flag */
+ strcpy(buf, arg_bigtile ? "1" : "0");
+ WritePrivateProfileString("Angband", "Bigtile", buf, ini_file);
+
+ /* Save the "arg_sound" flag */
+ strcpy(buf, arg_sound ? "1" : "0");
+ WritePrivateProfileString("Angband", "Sound", buf, ini_file);
+
+ /* Save the "arg_sound" flag */
+ strcpy(buf, arg_music ? "1" : "0");
+ WritePrivateProfileString("Angband", "Music", buf, ini_file);
+
+ /* bg */
+ strcpy(buf, use_bg ? "1" : "0");
+ WritePrivateProfileString("Angband", "BackGround", buf, ini_file);
+ WritePrivateProfileString("Angband", "BackGroundBitmap",
+ bg_bitmap_file[0] != '\0' ? bg_bitmap_file : "bg.bmp", ini_file);
+
+ /* Save window prefs */
+ for (i = 0; i < MAX_TERM_DATA; ++i)
+ {
+ save_prefs_aux(i);
+ }
+}
+
+
+/*
+ * Load the "prefs" for a single term
+ */
+static void load_prefs_aux(int i)
+{
+ term_data *td = &data[i];
+ GAME_TEXT sec_name[128];
+ char tmp[1024];
+
+ int wid, hgt, posx, posy;
+ int dispx = GetSystemMetrics( SM_CXVIRTUALSCREEN);
+ int dispy = GetSystemMetrics( SM_CYVIRTUALSCREEN);
+ posx=0;
+ posy=0;
+
+ /* Make section name */
+ sprintf(sec_name, "Term-%d", i);
+
+ /* Make section name */
+ sprintf(sec_name, "Term-%d", i);
+
+ /* Visible */
+ if (i > 0)
+ {
+ td->visible = (GetPrivateProfileInt(sec_name, "Visible", td->visible, ini_file) != 0);
+ }
+
+ /* Desired font, with default */
+#ifdef JP
+ GetPrivateProfileString(sec_name, "Font", "MS ゴシック", tmp, 127, ini_file);
+#else
+#if 0
+ GetPrivateProfileString(sec_name, "Font", "8X13.FON", tmp, 127, ini_file);
+#else
+ GetPrivateProfileString(sec_name, "Font", "Courier", tmp, 127, ini_file);
+#endif
+#endif
+
+
+ /* Bizarre */
+ td->bizarre = (GetPrivateProfileInt(sec_name, "Bizarre", td->bizarre, ini_file) != 0);
+
+ /* Analyze font, save desired font name */
+#if 1 /* #ifdef JP */
+ td->font_want = string_make(tmp);
+ hgt = 15; wid = 0;
+ td->lf.lfWidth = GetPrivateProfileInt(sec_name, "FontWid", wid, ini_file);
+ td->lf.lfHeight = GetPrivateProfileInt(sec_name, "FontHgt", hgt, ini_file);
+ td->lf.lfWeight = GetPrivateProfileInt(sec_name, "FontWgt", 0, ini_file);
+#else
+ td->font_want = string_make(analyze_font(tmp, &wid, &hgt));
+#endif
+
+
+ /* Tile size */
+#if 1 /* #ifdef JP */
+ td->tile_wid = GetPrivateProfileInt(sec_name, "TileWid", td->lf.lfWidth, ini_file);
+ td->tile_hgt = GetPrivateProfileInt(sec_name, "TileHgt", td->lf.lfHeight, ini_file);
+#else
+ td->tile_wid = GetPrivateProfileInt(sec_name, "TileWid", wid, ini_file);
+ td->tile_hgt = GetPrivateProfileInt(sec_name, "TileHgt", hgt, ini_file);
+#endif
+
+
+ /* Window size */
+ td->cols = GetPrivateProfileInt(sec_name, "NumCols", td->cols, ini_file);
+ td->rows = GetPrivateProfileInt(sec_name, "NumRows", td->rows, ini_file);
+ normsize.x = td->cols; normsize.y = td->rows;
+
+ /* Window size */
+ if (i == 0)
+ {
+ win_maximized = (GetPrivateProfileInt(sec_name, "Maximized", win_maximized, ini_file) != 0);
+ }
+
+ /* Window position */
+ posx = GetPrivateProfileInt(sec_name, "PositionX", posx, ini_file);
+ posy = GetPrivateProfileInt(sec_name, "PositionY", posy, ini_file);
+ td->pos_x = MIN(MAX(0, posx), dispx-128);
+ td->pos_y = MIN(MAX(0, posy), dispy-128);
+
+ /* Window Z position */
+ if (i > 0)
+ {
+ td->posfix = (GetPrivateProfileInt(sec_name, "PositionFix", td->posfix, ini_file) != 0);
+ }
+}
+
+
+/*
+ * Load the "prefs"
+ */
+static void load_prefs(void)
+{
+ int i;
+
+ /* Extract the "arg_graphics" flag */
+ arg_graphics = (byte_hack)GetPrivateProfileInt("Angband", "Graphics", GRAPHICS_NONE, ini_file);
+
+ /* Extract the "arg_bigtile" flag */
+ arg_bigtile = (GetPrivateProfileInt("Angband", "Bigtile", FALSE, ini_file) != 0);
+ use_bigtile = arg_bigtile;
+
+ /* Extract the "arg_sound" flag */
+ arg_sound = (GetPrivateProfileInt("Angband", "Sound", 0, ini_file) != 0);
+
+ /* Extract the "arg_sound" flag */
+ arg_music = (GetPrivateProfileInt("Angband", "Music", 0, ini_file) != 0);
+
+ /* bg */
+ use_bg = GetPrivateProfileInt("Angband", "BackGround", 0, ini_file);
+ GetPrivateProfileString("Angband", "BackGroundBitmap", "bg.bmp", bg_bitmap_file, 1023, ini_file);
+
+ /* Load window prefs */
+ for (i = 0; i < MAX_TERM_DATA; ++i)
+ {
+ load_prefs_aux(i);
+ }
+}
+
+#if defined(USE_SOUND) || defined(USE_MUSIC)
+
+/*
+ * - Taken from files.c.
+ *
+ * Extract "tokens" from a buffer
+ *
+ * This function uses "whitespace" as delimiters, and treats any amount of
+ * whitespace as a single delimiter. We will never return any empty tokens.
+ * When given an empty buffer, or a buffer containing only "whitespace", we
+ * will return no tokens. We will never extract more than "num" tokens.
+ *
+ * By running a token through the "text_to_ascii()" function, you can allow
+ * that token to include (encoded) whitespace, using "\s" to encode spaces.
+ *
+ * We save pointers to the tokens in "tokens", and return the number found.
+ */
+static s16b tokenize_whitespace(char *buf, s16b num, char **tokens)
+{
+ s16b k = 0;
+ char *s = buf;
+
+ /* Process */
+ while (k < num)
+ {
+ char *t;
+
+ /* Skip leading whitespace */
+ for ( ; *s && iswspace(*s); ++s) /* loop */;
+
+ /* All done */
+ if (!*s) break;
+
+ /* Find next whitespace, if any */
+ for (t = s; *t && !iswspace(*t); ++t) /* loop */;
+
+ /* Nuke and advance (if necessary) */
+ if (*t) *t++ = '\0';
+
+ /* Save the token */
+ tokens[k++] = s;
+
+ /* Advance */
+ s = t;
+ }
+
+ /* Count */
+ return (k);
+}
+
+#endif /* USE_SOUND || USE_MUSIC */
+
+#ifdef USE_SOUND
+
+static void load_sound_prefs(void)
+{
+ int i, j, num;
+ char tmp[1024];
+ char ini_path[1024];
+ char wav_path[1024];
+ char *zz[SAMPLE_MAX];
+
+ /* Access the sound.cfg */
+
+ path_build(ini_path, 1024, ANGBAND_DIR_XTRA_SOUND, "sound.cfg");
+
+ for (i = 0; i < SOUND_MAX; i++)
+ {
+ GetPrivateProfileString("Sound", angband_sound_name[i], "", tmp, 1024, ini_path);
+
+ num = tokenize_whitespace(tmp, SAMPLE_MAX, zz);
+
+ for (j = 0; j < num; j++)
+ {
+ /* Access the sound */
+ path_build(wav_path, 1024, ANGBAND_DIR_XTRA_SOUND, zz[j]);
+
+ /* Save the sound filename, if it exists */
+ if (check_file(wav_path))
+ sound_file[i][j] = string_make(zz[j]);
+ }
+ }
+}
+
+#endif /* USE_SOUND */
+
+#ifdef USE_MUSIC
+
+static void load_music_prefs(void)
+{
+ int i, j, num;
+ char tmp[1024];
+ char ini_path[1024];
+ char wav_path[1024];
+ char *zz[SAMPLE_MAX];
+ char key[80];
+
+ /* Access the music.cfg */
+
+ path_build(ini_path, 1024, ANGBAND_DIR_XTRA_MUSIC, "music.cfg");
+
+ GetPrivateProfileString("Device", "type", "", mci_device_type, 256, ini_path);
+
+ for (i = 0; i < MUSIC_BASIC_MAX; i++)
+ {
+ GetPrivateProfileString("Basic", angband_music_basic_name[i], "", tmp, 1024, ini_path);
+
+ num = tokenize_whitespace(tmp, SAMPLE_MUSIC_MAX, zz);
+
+ for (j = 0; j < num; j++)
+ {
+ /* Access the sound */
+ path_build(wav_path, 1024, ANGBAND_DIR_XTRA_MUSIC, zz[j]);
+
+ /* Save the sound filename, if it exists */
+ if (check_file(wav_path))
+ music_file[i][j] = string_make(zz[j]);
+ }
+ }
+
+ for (i = 0; i < max_d_idx; i++)
+ {
+ sprintf(key, "dungeon%03d", i);
+ GetPrivateProfileString("Dungeon", key, "", tmp, 1024, ini_path);
+
+ num = tokenize_whitespace(tmp, SAMPLE_MUSIC_MAX, zz);
+
+ for (j = 0; j < num; j++)
+ {
+ /* Access the sound */
+ path_build(wav_path, 1024, ANGBAND_DIR_XTRA_MUSIC, zz[j]);
+
+ /* Save the sound filename, if it exists */
+ if (check_file(wav_path))
+ dungeon_music_file[i][j] = string_make(zz[j]);
+ }
+ }
+
+ for (i = 0; i < max_q_idx; i++)
+ {
+ sprintf(key, "quest%03d", i);
+ GetPrivateProfileString("Quest", key, "", tmp, 1024, ini_path);
+
+ num = tokenize_whitespace(tmp, SAMPLE_MUSIC_MAX, zz);
+
+ for (j = 0; j < num; j++)
+ {
+ /* Access the sound */
+ path_build(wav_path, 1024, ANGBAND_DIR_XTRA_MUSIC, zz[j]);
+
+ /* Save the sound filename, if it exists */
+ if (check_file(wav_path))
+ quest_music_file[i][j] = string_make(zz[j]);
+ }
+ }
+
+ for (i = 0; i < 1000; i++) /*!< @todo 町最大数指定 */
+ {
+ sprintf(key, "town%03d", i);
+ GetPrivateProfileString("Town", key, "", tmp, 1024, ini_path);
+
+ num = tokenize_whitespace(tmp, SAMPLE_MUSIC_MAX, zz);
+
+ for (j = 0; j < num; j++)
+ {
+ /* Access the sound */
+ path_build(wav_path, 1024, ANGBAND_DIR_XTRA_MUSIC, zz[j]);
+
+ /* Save the sound filename, if it exists */
+ if (check_file(wav_path))
+ town_music_file[i][j] = string_make(zz[j]);
+ }
+ }
+
+
+}
+
+#endif /* USE_MUSIC */
+
+/*
+ * Create the new global palette based on the bitmap palette
+ * (if any), and the standard 16 entry palette derived from
+ * "win_clr[]" which is used for the basic 16 Angband colors.
+ *
+ * This function is never called before all windows are ready.
+ *
+ * This function returns FALSE if the new palette could not be
+ * prepared, which should normally be a fatal error. XXX XXX
+ *
+ * Note that only some machines actually use a "palette".
+ */
+static int new_palette(void)
+{
+ HPALETTE hBmPal;
+ HPALETTE hNewPal;
+ HDC hdc;
+ int i, nEntries;
+ int pLogPalSize;
+ int lppeSize;
+ LPLOGPALETTE pLogPal;
+ LPPALETTEENTRY lppe;
+
+ term_data *td;
+
+
+ /* This makes no sense */
+ if (!paletted) return (TRUE);
+
+
+ /* No bitmap */
+ lppeSize = 0;
+ lppe = NULL;
+ nEntries = 0;
+
+#ifdef USE_GRAPHICS
+
+ /* Check the bitmap palette */
+ hBmPal = infGraph.hPalette;
+
+ /* Use the bitmap */
+ if (hBmPal)
+ {
+ lppeSize = 256 * sizeof(PALETTEENTRY);
+ lppe = (LPPALETTEENTRY)ralloc(lppeSize);
+ nEntries = GetPaletteEntries(hBmPal, 0, 255, lppe);
+ if ((nEntries == 0) || (nEntries > 220))
+ {
+ /* Warn the user */
+ plog(_("画面を16ビットか24ビットカラーモードにして下さい。", "Please switch to high- or true-color mode."));
+
+ /* Cleanup */
+ rnfree(lppe, lppeSize);
+
+ /* Fail */
+ return (FALSE);
+ }
+ }
+
+#endif /* USE_GRAPHICS */
+
+ /* Size of palette */
+ pLogPalSize = sizeof(LOGPALETTE) + (nEntries + 16) * sizeof(PALETTEENTRY);
+
+ /* Allocate palette */
+ pLogPal = (LPLOGPALETTE)ralloc(pLogPalSize);
+
+ /* Version */
+ pLogPal->palVersion = 0x300;
+
+ /* Make room for bitmap and normal data */
+ pLogPal->palNumEntries = nEntries + 16;
+
+ /* Save the bitmap data */
+ for (i = 0; i < nEntries; i++)
+ {
+ pLogPal->palPalEntry[i] = lppe[i];
+ }
+
+ /* Save the normal data */
+ for (i = 0; i < 16; i++)
+ {
+ LPPALETTEENTRY p;
+
+ /* Access the entry */
+ p = &(pLogPal->palPalEntry[i+nEntries]);
+
+ /* Save the colors */
+ p->peRed = GetRValue(win_clr[i]);
+ p->peGreen = GetGValue(win_clr[i]);
+ p->peBlue = GetBValue(win_clr[i]);
+
+ /* Save the flags */
+ p->peFlags = PC_NOCOLLAPSE;
+ }
+
+ /* Free something */
+ if (lppe) rnfree(lppe, lppeSize);
+
+ /* Create a new palette, or fail */
+ hNewPal = CreatePalette(pLogPal);
+ if (!hNewPal) quit(_("パレットを作成できません!", "Cannot create palette!"));
+
+ /* Free the palette */
+ rnfree(pLogPal, pLogPalSize);
+
+ /* Main window */
+ td = &data[0];
+
+ /* Realize the palette */
+ hdc = GetDC(td->w);
+ SelectPalette(hdc, hNewPal, 0);
+ i = RealizePalette(hdc);
+ ReleaseDC(td->w, hdc);
+ if (i == 0) quit(_("パレットをシステムエントリにマップできません!", "Cannot realize palette!"));
+
+
+ /* Sub-windows */
+ for (i = 1; i < MAX_TERM_DATA; i++)
+ {
+ td = &data[i];
+
+ hdc = GetDC(td->w);
+ SelectPalette(hdc, hNewPal, 0);
+ ReleaseDC(td->w, hdc);
+ }
+
+ /* Delete old palette */
+ if (hPal) DeleteObject(hPal);
+
+ /* Save new palette */
+ hPal = hNewPal;
+
+ /* Success */
+ return (TRUE);
+}
+
+
+#ifdef USE_GRAPHICS
+/*!
+ * @brief グラフィクスを初期化する / Initialize graphics
+ * @details
+ * <ul>
+ * <li>メニュー[オプション]>[グラフィクス]が「なし」以外の時に描画処理を初期化する。</li>
+ * <li>呼び出されるタイミングはロード時、及び同メニューで「なし」以外に変更される毎になる。</li>
+ * </ul>
+ */
+static bool init_graphics(void)
+{
+ /* Initialize once */
+ char buf[1024];
+ BYTE wid, hgt, twid, thgt, ox, oy;
+ concptr name;
+
+ if (arg_graphics == GRAPHICS_ADAM_BOLT)
+ {
+ wid = 16;
+ hgt = 16;
+ twid = 16;
+ thgt = 16;
+ ox = 0;
+ oy = 0;
+ name = "16X16.BMP";
+
+ ANGBAND_GRAF = "new";
+ }
+ else if (arg_graphics == GRAPHICS_HENGBAND)
+ {
+ /*! @todo redraw
+ wid = 64;
+ hgt = 64;
+ twid = 32;
+ thgt = 32;
+ ox = -16;
+ oy = -24;
+ name = "64X64.BMP";
+ */
+
+ wid = 32;
+ hgt = 32;
+ twid = 32;
+ thgt = 32;
+ ox = 0;
+ oy = 0;
+ name = "32X32.BMP";
+
+ ANGBAND_GRAF = "ne2";
+ }
+ else
+ {
+ wid = 8;
+ hgt = 8;
+ twid = 8;
+ thgt = 8;
+ ox = 0;
+ oy = 0;
+ name = "8X8.BMP";
+ ANGBAND_GRAF = "old";
+ }
+
+ /* Access the bitmap file */
+ path_build(buf, sizeof(buf), ANGBAND_DIR_XTRA_GRAF, name);
+
+ /* Load the bitmap or quit */
+ if (!ReadDIB(data[0].w, buf, &infGraph))
+ {
+ plog_fmt(_("ビットマップ '%s' を読み込めません。", "Cannot read bitmap file '%s'"), name);
+ return (FALSE);
+ }
+
+ /* Save the new sizes */
+ infGraph.CellWidth = wid;
+ infGraph.CellHeight = hgt;
+ infGraph.TileWidth = twid;
+ infGraph.TileHeight = thgt;
+ infGraph.OffsetX = ox;
+ infGraph.OffsetY = oy;
+
+ if (arg_graphics == GRAPHICS_ADAM_BOLT)
+ {
+ /* Access the mask file */
+ path_build(buf, sizeof(buf), ANGBAND_DIR_XTRA_GRAF, "mask.bmp");
+
+ /* Load the bitmap or quit */
+ if (!ReadDIB(data[0].w, buf, &infMask))
+ {
+ plog_fmt("Cannot read bitmap file '%s'", buf);
+ return (FALSE);
+ }
+ }
+ if (arg_graphics == GRAPHICS_HENGBAND)
+ {
+ /* Access the mask file */
+ path_build(buf, sizeof(buf), ANGBAND_DIR_XTRA_GRAF, "mask32.bmp");
+
+ /* Load the bitmap or quit */
+ if (!ReadDIB(data[0].w, buf, &infMask))
+ {
+ plog_fmt("Cannot read bitmap file '%s'", buf);
+ return (FALSE);
+ }
+ }
+
+ /* Activate a palette */
+ if (!new_palette())
+ {
+ /* Free bitmap */
+
+ plog(_("パレットを実現できません!", "Cannot activate palette!"));
+ return (FALSE);
+ }
+
+ /* Graphics available */
+ current_graphics_mode = arg_graphics;
+ return (current_graphics_mode);
+}
+#endif /* USE_GRAPHICS */
+
+
+#ifdef USE_MUSIC
+/*
+ * Initialize music
+ */
+static bool init_music(void)
+{
+ /* Initialize once */
+ if (!can_use_music)
+ {
+ /* Load the prefs */
+ load_music_prefs();
+
+ /* Sound available */
+ can_use_music = TRUE;
+ }
+ return (can_use_music);
+}
+
+/*
+ * Hack -- Stop a music
+ */
+static void stop_music(void)
+{
+ mciSendCommand(mop.wDeviceID, MCI_STOP, 0, 0);
+ mciSendCommand(mop.wDeviceID, MCI_CLOSE, 0, 0);
+}
+
+#endif /* USE_MUSIC */
+
+#ifdef USE_SOUND
+/*
+ * Initialize sound
+ */
+static bool init_sound(void)
+{
+ /* Initialize once */
+ if (!can_use_sound)
+ {
+ /* Load the prefs */
+ load_sound_prefs();
+
+ /* Sound available */
+ can_use_sound = TRUE;
+ }
+ return (can_use_sound);
+}
+#endif /* USE_SOUND */
+
+
+/*
+ * Resize a window
+ */
+static void term_window_resize(term_data *td)
+{
+ /* Require window */
+ if (!td->w) return;
+
+ /* Resize the window */
+ SetWindowPos(td->w, 0, 0, 0,
+ td->size_wid, td->size_hgt,
+ SWP_NOMOVE | SWP_NOZORDER);
+
+ /* Redraw later */
+ InvalidateRect(td->w, NULL, TRUE);
+}
+
+
+/*
+ * Force the use of a new "font file" for a term_data
+ *
+ * This function may be called before the "window" is ready
+ *
+ * This function returns zero only if everything succeeds.
+ *
+ * Note that the "font name" must be capitalized!!!
+ */
+static errr term_force_font(term_data *td, concptr path)
+{
+ int wid, hgt;
+
+#if 0 /* #ifndef JP */
+ int i;
+ char *base;
+ char buf[1024];
+#endif
+
+ /* Forget the old font (if needed) */
+ if (td->font_id) DeleteObject(td->font_id);
+
+#if 1 /* #ifdef JP */
+ /* Unused */
+ (void)path;
+
+ /* Create the font (using the 'base' of the font file name!) */
+ td->font_id = CreateFontIndirect(&(td->lf));
+ wid = td->lf.lfWidth;
+ hgt = td->lf.lfHeight;
+ if (!td->font_id) return (1);
+#else
+ /* Forget old font */
+ if (td->font_file)
+ {
+ bool used = FALSE;
+
+ /* Scan windows */
+ for (i = 0; i < MAX_TERM_DATA; i++)
+ {
+ /* Don't check when closing the application */
+ if (!path) break;
+
+ /* Check "screen" */
+ if ((td != &data[i]) &&
+ (data[i].font_file) &&
+ (streq(data[i].font_file, td->font_file)))
+ {
+ used = TRUE;
+ }
+ }
+
+ /* Remove unused font resources */
+ if (!used) RemoveFontResource(td->font_file);
+
+ /* Free the old name */
+ string_free(td->font_file);
+
+ /* Forget it */
+ td->font_file = NULL;
+ }
+
+ /* No path given */
+ if (!path) return (1);
+
+ /* Local copy */
+ strcpy(buf, path);
+
+ /* Analyze font path */
+ base = analyze_font(buf, &wid, &hgt);
+
+ /* Verify suffix */
+ if (!suffix(base, ".FON")) return (1);
+
+ /* Verify file */
+ if (!check_file(buf)) return (1);
+
+ /* Load the new font */
+ if (!AddFontResource(buf)) return (1);
+
+ /* Save new font name */
+ td->font_file = string_make(base);
+
+ /* Remove the "suffix" */
+ base[strlen(base)-4] = '\0';
+
+ /* Create the font (using the 'base' of the font file name!) */
+ td->font_id = CreateFont(hgt, wid, 0, 0, FW_DONTCARE, 0, 0, 0,
+ ANSI_CHARSET, OUT_DEFAULT_PRECIS,
+ CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
+ FIXED_PITCH | FF_DONTCARE, base);
+#endif
+
+ /* Hack -- Unknown size */
+ if (!wid || !hgt)
+ {
+ HDC hdcDesktop;
+ HFONT hfOld;
+ TEXTMETRIC tm;
+
+ /* all this trouble to get the cell size */
+ hdcDesktop = GetDC(HWND_DESKTOP);
+ hfOld = SelectObject(hdcDesktop, td->font_id);
+ GetTextMetrics(hdcDesktop, &tm);
+ SelectObject(hdcDesktop, hfOld);
+ ReleaseDC(HWND_DESKTOP, hdcDesktop);
+
+ /* Font size info */
+ wid = tm.tmAveCharWidth;
+ hgt = tm.tmHeight;
+ }
+
+ /* Save the size info */
+ td->font_wid = wid;
+ td->font_hgt = hgt;
+
+ /* Success */
+ return (0);
+}
+
+
+
+/*
+ * Allow the user to change the font for this window.
+ */
+static void term_change_font(term_data *td)
+{
+#if 1 /* #ifdef JP */
+ CHOOSEFONT cf;
+
+ memset(&cf, 0, sizeof(cf));
+ cf.lStructSize = sizeof(cf);
+ cf.Flags = CF_SCREENFONTS | CF_FIXEDPITCHONLY | CF_NOVERTFONTS | CF_INITTOLOGFONTSTRUCT;
+ cf.lpLogFont = &(td->lf);
+
+ if (ChooseFont(&cf))
+ {
+ /* Force the font */
+ term_force_font(td, NULL);
+
+ /* Assume not bizarre */
+ td->bizarre = TRUE;
+
+ /* Reset the tile info */
+ td->tile_wid = td->font_wid;
+ td->tile_hgt = td->font_hgt;
+
+ /* Analyze the font */
+ term_getsize(td);
+
+ /* Resize the window */
+ term_window_resize(td);
+ }
+
+#else
+ OPENFILENAME ofn;
+
+ char tmp[1024] = "";
+
+ /* Extract a default if possible */
+ if (td->font_file) strcpy(tmp, td->font_file);
+
+ /* Ask for a choice */
+ memset(&ofn, 0, sizeof(ofn));
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hwndOwner = data[0].w;
+ ofn.lpstrFilter = "Angband Font Files (*.fon)\0*.fon\0";
+ ofn.nFilterIndex = 1;
+ ofn.lpstrFile = tmp;
+ ofn.nMaxFile = 128;
+ ofn.lpstrInitialDir = ANGBAND_DIR_XTRA_FONT;
+ ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
+ ofn.lpstrDefExt = "fon";
+
+ /* Force choice if legal */
+ if (GetOpenFileName(&ofn))
+ {
+ /* Force the font */
+ if (term_force_font(td, tmp))
+ {
+ /* Access the standard font file */
+ path_build(tmp, sizeof(tmp), ANGBAND_DIR_XTRA_FONT, "8X13.FON");
+
+ /* Force the use of that font */
+ (void)term_force_font(td, tmp);
+ }
+
+ /* Assume not bizarre */
+ td->bizarre = FALSE;
+
+ /* Reset the tile info */
+ td->tile_wid = td->font_wid;
+ td->tile_hgt = td->font_hgt;
+
+ /* Analyze the font */
+ term_getsize(td);
+
+ /* Resize the window */
+ term_window_resize(td);
+ }
+#endif
+
+}
+
+/*
+ * Allow the user to lock this window.
+ */
+static void term_window_pos(term_data *td, HWND hWnd)
+{
+ SetWindowPos(td->w, hWnd, 0, 0, 0, 0,
+ SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
+}
+
+static void windows_map(void);
+
+/*
+ * Hack -- redraw a term_data
+ */
+static void term_data_redraw(term_data *td)
+{
+ if (td->map_active)
+ {
+ /* Redraw the map */
+ windows_map();
+ }
+ else
+ {
+ /* Activate the term */
+ Term_activate(&td->t);
+
+ /* Redraw the contents */
+ Term_redraw();
+
+ /* Restore the term */
+ Term_activate(term_screen);
+ }
+}
+
+
+void Term_inversed_area(HWND hWnd, int x, int y, int w, int h)
+{
+ HDC hdc;
+ HPEN oldPen;
+ HBRUSH myBrush, oldBrush;
+
+ term_data *td = (term_data *)GetWindowLong(hWnd, 0);
+ int tx = td->size_ow1 + x * td->tile_wid;
+ int ty = td->size_oh1 + y * td->tile_hgt;
+ int tw = w * td->tile_wid - 1;
+ int th = h * td->tile_hgt - 1;
+
+ hdc = GetDC(hWnd);
+ myBrush = CreateSolidBrush(RGB(255, 255, 255));
+ oldBrush = SelectObject(hdc, myBrush);
+ oldPen = SelectObject(hdc, GetStockObject(NULL_PEN) );
+
+ PatBlt(hdc, tx, ty, tw, th, PATINVERT);
+
+ SelectObject(hdc, oldBrush);
+ SelectObject(hdc, oldPen);
+}
+
+
+
+/*** Function hooks needed by "Term" ***/
+
+
+#if 0
+
+/*
+ * Initialize a new Term
+ */
+static void Term_init_win(term *t)
+{
+ /* XXX Unused */
+}
+
+
+/*
+ * Nuke an old Term
+ */
+static void Term_nuke_win(term *t)
+{
+ /* XXX Unused */
+}
+
+#endif
+
+
+/*!
+ * @brief //!< Windows版ユーザ設定項目実装部(実装必須) /Interact with the User
+ */
+static errr Term_user_win(int n)
+{
+ /* Unused */
+ (void)n;
+
+ /* Success */
+ return (0);
+}
+
+
+/*
+ * React to global changes
+ */
+static errr Term_xtra_win_react(void)
+{
+ int i;
+
+ /* Simple color */
+ if (colors16)
+ {
+ /* Save the default colors */
+ for (i = 0; i < 256; i++)
+ {
+ /* Simply accept the desired colors */
+ win_pal[i] = angband_color_table[i][0];
+ }
+ }
+
+ /* Complex color */
+ else
+ {
+ COLORREF code;
+
+ byte rv, gv, bv;
+
+ bool change = FALSE;
+
+ /* Save the default colors */
+ for (i = 0; i < 256; i++)
+ {
+ /* Extract desired values */
+ rv = angband_color_table[i][1];
+ gv = angband_color_table[i][2];
+ bv = angband_color_table[i][3];
+
+ /* Extract a full color code */
+ code = PALETTERGB(rv, gv, bv);
+
+ /* Activate changes */
+ if (win_clr[i] != code)
+ {
+ /* Note the change */
+ change = TRUE;
+
+ /* Apply the desired color */
+ win_clr[i] = code;
+ }
+ }
+
+ /* Activate the palette if needed */
+ if (change) (void)new_palette();
+ }
+
+
+#ifdef USE_SOUND
+
+ /* Handle "arg_sound" */
+ if (use_sound != arg_sound)
+ {
+ /* Initialize (if needed) */
+ if (arg_sound && !init_sound())
+ {
+ /* Warning */
+ plog(_("サウンドを初期化できません!", "Cannot initialize sound!"));
+
+ /* Cannot enable */
+ arg_sound = FALSE;
+ }
+
+ /* Change setting */
+ use_sound = arg_sound;
+ }
+
+#endif
+
+#ifdef USE_MUSIC
+
+ /* Handle "arg_sound" */
+ if (use_music != arg_music)
+ {
+ /* Initialize (if needed) */
+ if (arg_music && !init_music())
+ {
+ /* Warning */
+ plog(_("BGMを初期化できません!", "Cannot initialize BGM!"));
+ /* Cannot enable */
+ arg_music = FALSE;
+ }
+
+ /* Change setting */
+ use_music = arg_music;
+
+ if(!arg_music) stop_music();
+ else select_floor_music();
+
+ }
+
+#endif
+
+
+#ifdef USE_GRAPHICS
+
+ /* Handle "arg_graphics" */
+ if (use_graphics != arg_graphics)
+ {
+ /* Initialize (if needed) */
+ if (arg_graphics && !init_graphics())
+ {
+ /* Warning */
+ plog(_("グラフィックスを初期化できません!", "Cannot initialize graphics!"));
+
+ /* Cannot enable */
+ arg_graphics = GRAPHICS_NONE;
+ }
+
+ /* Change setting */
+ use_graphics = arg_graphics;
+
+ /* Reset visuals */
+#ifdef ANGBAND_2_8_1
+ reset_visuals();
+#else /* ANGBAND_2_8_1 */
+ reset_visuals(TRUE);
+#endif /* ANGBAND_2_8_1 */
+ }
+
+#endif /* USE_GRAPHICS */
+
+
+ /* Clean up windows */
+ for (i = 0; i < MAX_TERM_DATA; i++)
+ {
+ term *old = Term;
+
+ term_data *td = &data[i];
+
+ /* Update resized windows */
+ if ((td->cols != td->t.wid) || (td->rows != td->t.hgt))
+ {
+ /* Activate */
+ Term_activate(&td->t);
+
+ /* Hack -- Resize the term */
+ Term_resize(td->cols, td->rows);
+
+ /* Redraw the contents */
+ Term_redraw();
+ Term_activate(old);
+ }
+ }
+
+
+ /* Success */
+ return (0);
+}
+
+
+/*
+ * Process at least one event
+ */
+static errr Term_xtra_win_event(int v)
+{
+ MSG msg;
+
+ /* Wait for an event */
+ if (v)
+ {
+ /* Block */
+ if (GetMessage(&msg, NULL, 0, 0))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+
+ /* Check for an event */
+ else
+ {
+ /* Check */
+ if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+
+ /* Success */
+ return 0;
+}
+
+
+/*
+ * Process all pending events
+ */
+static errr Term_xtra_win_flush(void)
+{
+ MSG msg;
+
+ /* Process all pending events */
+ while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ /* Success */
+ return (0);
+}
+
+
+/*
+ * Hack -- clear the screen
+ *
+ * Make this more efficient
+ */
+static errr Term_xtra_win_clear(void)
+{
+ term_data *td = (term_data*)(Term->data);
+
+ HDC hdc;
+ RECT rc;
+
+ /* Rectangle to erase */
+ rc.left = td->size_ow1;
+ rc.right = rc.left + td->cols * td->tile_wid;
+ rc.top = td->size_oh1;
+ rc.bottom = rc.top + td->rows * td->tile_hgt;
+
+ /* Erase it */
+ hdc = GetDC(td->w);
+ SetBkColor(hdc, RGB(0, 0, 0));
+ SelectObject(hdc, td->font_id);
+ ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
+
+ /* bg */
+ if (use_bg)
+ {
+ rc.left = 0; rc.top = 0;
+ DrawBG(hdc, &rc);
+ }
+ ReleaseDC(td->w, hdc);
+
+ /* Success */
+ return 0;
+}
+
+
+/*
+ * Hack -- make a noise
+ */
+static errr Term_xtra_win_noise(void)
+{
+ MessageBeep(MB_ICONASTERISK);
+ return (0);
+}
+
+
+/*
+ * Hack -- make a sound
+ */
+static errr Term_xtra_win_sound(int v)
+{
+#ifdef USE_SOUND
+ int i;
+ char buf[1024];
+#endif /* USE_SOUND */
+
+ /* Sound disabled */
+ if (!use_sound) return (1);
+
+ /* Illegal sound */
+ if ((v < 0) || (v >= SOUND_MAX)) return (1);
+
+#ifdef USE_SOUND
+
+ /* Count the samples */
+ for (i = 0; i < SAMPLE_MAX; i++)
+ {
+ if (!sound_file[v][i])
+ break;
+ }
+
+ /* No sample */
+ if (i == 0) return (1);
+
+ /* Build the path */
+ path_build(buf, 1024, ANGBAND_DIR_XTRA_SOUND, sound_file[v][Rand_external(i)]);
+
+#ifdef WIN32
+
+ /* Play the sound, catch errors */
+ return (PlaySound(buf, 0, SND_FILENAME | SND_ASYNC));
+
+#else /* WIN32 */
+
+ /* Play the sound, catch errors */
+ return (sndPlaySound(buf, SND_ASYNC));
+
+#endif /* WIN32 */
+
+#else /* USE_SOUND */
+
+ return (1);
+
+#endif /* USE_SOUND */
+}
+
+/*
+ * Hack -- play a music
+ */
+static errr Term_xtra_win_music(int n, int v)
+{
+#ifdef USE_MUSIC
+ int i = 0;
+ char buf[1024];
+#endif /* USE_MUSIC */
+
+ /* Sound disabled */
+
+ if(!use_music) return (1);
+
+ /* Illegal sound */
+ if(n == TERM_XTRA_MUSIC_BASIC && ((v < 0) || (v >= MUSIC_BASIC_MAX))) return (1);
+ else if(v < 0 || v >= 1000) return(1); /*!< TODO */
+
+#ifdef USE_MUSIC
+
+ switch(n)
+ {
+ case TERM_XTRA_MUSIC_BASIC:
+ for (i = 0; i < SAMPLE_MAX; i++) if(!music_file[v][i]) break;
+ break;
+ case TERM_XTRA_MUSIC_DUNGEON:
+ for (i = 0; i < SAMPLE_MAX; i++) if(!dungeon_music_file[v][i]) break;
+ break;
+ case TERM_XTRA_MUSIC_QUEST:
+ for (i = 0; i < SAMPLE_MAX; i++) if(!quest_music_file[v][i]) break;
+ break;
+ case TERM_XTRA_MUSIC_TOWN:
+ for (i = 0; i < SAMPLE_MAX; i++) if(!town_music_file[v][i]) break;
+ break;
+ }
+
+ /* No sample */
+ if (i == 0)
+ {
+ //mciSendCommand(mop.wDeviceID, MCI_STOP, 0, 0);
+ //mciSendCommand(mop.wDeviceID, MCI_CLOSE, 0, 0);
+ return (1);
+ }
+
+ switch(n)
+ {
+ case TERM_XTRA_MUSIC_BASIC:
+ for (i = 0; i < SAMPLE_MAX; i++) if(!music_file[v][i]) break;
+ break;
+ case TERM_XTRA_MUSIC_DUNGEON:
+ for (i = 0; i < SAMPLE_MAX; i++) if(!dungeon_music_file[v][i]) break;
+ break;
+ case TERM_XTRA_MUSIC_QUEST:
+ for (i = 0; i < SAMPLE_MAX; i++) if(!quest_music_file[v][i]) break;
+ break;
+ case TERM_XTRA_MUSIC_TOWN:
+ for (i = 0; i < SAMPLE_MAX; i++) if(!town_music_file[v][i]) break;
+ break;
+ }
+
+ /* No sample */
+ if (i == 0)
+ {
+ mciSendCommand(mop.wDeviceID, MCI_STOP, 0, 0);
+ mciSendCommand(mop.wDeviceID, MCI_CLOSE, 0, 0);
+ return (1);
+ }
+
+ switch(n)
+ {
+ case TERM_XTRA_MUSIC_BASIC:
+ path_build(buf, 1024, ANGBAND_DIR_XTRA_MUSIC, music_file[v][Rand_external(i)]);
+ break;
+ case TERM_XTRA_MUSIC_DUNGEON:
+ path_build(buf, 1024, ANGBAND_DIR_XTRA_MUSIC, dungeon_music_file[v][Rand_external(i)]);
+ break;
+ case TERM_XTRA_MUSIC_QUEST:
+ path_build(buf, 1024, ANGBAND_DIR_XTRA_MUSIC, quest_music_file[v][Rand_external(i)]);
+ break;
+ case TERM_XTRA_MUSIC_TOWN:
+ path_build(buf, 1024, ANGBAND_DIR_XTRA_MUSIC, town_music_file[v][Rand_external(i)]);
+ break;
+ }
+
+ if(current_music_type == n && current_music_id == v)
+ {
+ return (0);
+ }
+ current_music_type = n;
+ current_music_id = v;
+
+#ifdef WIN32
+
+ mop.lpstrDeviceType = mci_device_type;
+ mop.lpstrElementName = buf;
+ mciSendCommand(mop.wDeviceID, MCI_STOP, 0, 0);
+ mciSendCommand(mop.wDeviceID, MCI_CLOSE, 0, 0);
+ mciSendCommand(mop.wDeviceID, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_ELEMENT, (DWORD)&mop);
+ mciSendCommand(mop.wDeviceID, MCI_SEEK, MCI_SEEK_TO_START, 0);
+ mciSendCommand(mop.wDeviceID, MCI_PLAY, MCI_NOTIFY, (DWORD)&mop);
+ return (0);
+
+#endif /* WIN32 */
+
+#else /* USE_MUSIC */
+
+ return (1);
+
+#endif /* USE_MUSIC */
+
+}
+
+
+/*
+ * Delay for "x" milliseconds
+ */
+static int Term_xtra_win_delay(int v)
+{
+
+#ifdef WIN32
+
+ /* Sleep */
+ Sleep(v);
+
+#else /* WIN32 */
+
+ DWORD t;
+ MSG msg;
+
+ /* Final count */
+ t = GetTickCount() + v;
+
+ /* Wait for it */
+ while (GetTickCount() < t)
+ {
+ /* Handle messages */
+ if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+
+#endif /* WIN32 */
+
+ /* Success */
+ return (0);
+}
+
+
+/*
+ * Do a "special thing"
+ */
+static errr Term_xtra_win(int n, int v)
+{
+ /* Handle a subset of the legal requests */
+ switch (n)
+ {
+ /* Make a bell sound */
+ case TERM_XTRA_NOISE:
+ {
+ return (Term_xtra_win_noise());
+ }
+
+ /* Play a music */
+ case TERM_XTRA_MUSIC_BASIC:
+ case TERM_XTRA_MUSIC_DUNGEON:
+ case TERM_XTRA_MUSIC_QUEST:
+ case TERM_XTRA_MUSIC_TOWN:
+ {
+ return (Term_xtra_win_music(n, v));
+ }
+
+ /* Make a special sound */
+ case TERM_XTRA_SOUND:
+ {
+ return (Term_xtra_win_sound(v));
+ }
+
+ /* Process random events */
+ case TERM_XTRA_BORED:
+ {
+ return (Term_xtra_win_event(0));
+ }
+
+ /* Process an event */
+ case TERM_XTRA_EVENT:
+ {
+ return (Term_xtra_win_event(v));
+ }
+
+ /* Flush all events */
+ case TERM_XTRA_FLUSH:
+ {
+ return (Term_xtra_win_flush());
+ }
+
+ /* Clear the screen */
+ case TERM_XTRA_CLEAR:
+ {
+ return (Term_xtra_win_clear());
+ }
+
+ /* React to global changes */
+ case TERM_XTRA_REACT:
+ {
+ return (Term_xtra_win_react());
+ }
+
+ /* Delay for some milliseconds */
+ case TERM_XTRA_DELAY:
+ {
+ return (Term_xtra_win_delay(v));
+ }
+ }
+
+ return 1;
+}
+
+
+
+/*
+ * Low level graphics (Assumes valid input).
+ *
+ * Draw a "cursor" at (x,y), using a "yellow box".
+ */
+static errr Term_curs_win(int x, int y)
+{
+ term_data *td = (term_data*)(Term->data);
+
+ RECT rc;
+ HDC hdc;
+
+ int tile_wid, tile_hgt;
+
+ if (td->map_active)
+ {
+ tile_wid = td->map_tile_wid;
+ tile_hgt = td->map_tile_hgt;
+ }
+ else
+ {
+ tile_wid = td->tile_wid;
+ tile_hgt = td->tile_hgt;
+ }
+
+ /* Frame the grid */
+ rc.left = x * tile_wid + td->size_ow1;
+ rc.right = rc.left + tile_wid;
+ rc.top = y * tile_hgt + td->size_oh1;
+ rc.bottom = rc.top + tile_hgt;
+
+ /* Cursor is done as a yellow "box" */
+ hdc = GetDC(td->w);
+ FrameRect(hdc, &rc, hbrYellow);
+ ReleaseDC(td->w, hdc);
+
+ /* Success */
+ return 0;
+}
+
+
+/*
+ * Low level graphics (Assumes valid input).
+ *
+ * Draw a "big cursor" at (x,y), using a "yellow box".
+ */
+static errr Term_bigcurs_win(int x, int y)
+{
+ term_data *td = (term_data*)(Term->data);
+
+ RECT rc;
+ HDC hdc;
+
+ int tile_wid, tile_hgt;
+
+ if (td->map_active)
+ {
+ /* Normal cursor in map window */
+ Term_curs_win(x, y);
+ return 0;
+ }
+ else
+ {
+ tile_wid = td->tile_wid;
+ tile_hgt = td->tile_hgt;
+ }
+
+ /* Frame the grid */
+ rc.left = x * tile_wid + td->size_ow1;
+ rc.right = rc.left + 2 * tile_wid;
+ rc.top = y * tile_hgt + td->size_oh1;
+ rc.bottom = rc.top + tile_hgt;
+
+ /* Cursor is done as a yellow "box" */
+ hdc = GetDC(td->w);
+ FrameRect(hdc, &rc, hbrYellow);
+ ReleaseDC(td->w, hdc);
+
+ /* Success */
+ return 0;
+}
+
+
+/*
+ * Low level graphics (Assumes valid input).
+ *
+ * Erase a "block" of "n" characters starting at (x,y).
+ */
+static errr Term_wipe_win(int x, int y, int n)
+{
+ term_data *td = (term_data*)(Term->data);
+
+ HDC hdc;
+ RECT rc;
+
+ /* Rectangle to erase in client coords */
+ rc.left = x * td->tile_wid + td->size_ow1;
+ rc.right = rc.left + n * td->tile_wid;
+ rc.top = y * td->tile_hgt + td->size_oh1;
+ rc.bottom = rc.top + td->tile_hgt;
+
+ hdc = GetDC(td->w);
+ SetBkColor(hdc, RGB(0, 0, 0));
+ SelectObject(hdc, td->font_id);
+ /* bg */
+ if (use_bg)
+ DrawBG(hdc, &rc);
+ else
+ ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
+ ReleaseDC(td->w, hdc);
+
+ /* Success */
+ return 0;
+}
+
+
+/*
+ * Low level graphics. Assumes valid input.
+ *
+ * Draw several ("n") chars, with an attr, at a given location.
+ *
+ * All "graphic" data is handled by "Term_pict_win()", below.
+ *
+ * One would think there is a more efficient method for telling a window
+ * what color it should be using to draw with, but perhaps simply changing
+ * it every time is not too inefficient.
+ */
+static errr Term_text_win(int x, int y, int n, TERM_COLOR a, concptr s)
+{
+ term_data *td = (term_data*)(Term->data);
+ RECT rc;
+ HDC hdc;
+
+#if 1 /* #ifdef JP */
+ static HBITMAP WALL;
+ static HBRUSH myBrush, oldBrush;
+ static HPEN oldPen;
+ static bool init_done = FALSE;
+
+ if (!init_done){
+ WALL = LoadBitmap(hInstance, AppName);
+ myBrush = CreatePatternBrush(WALL);
+ init_done = TRUE;
+ }
+#endif
+
+ /* Total rectangle */
+ rc.left = x * td->tile_wid + td->size_ow1;
+ rc.right = rc.left + n * td->tile_wid;
+ rc.top = y * td->tile_hgt + td->size_oh1;
+ rc.bottom = rc.top + td->tile_hgt;
+
+ /* Acquire DC */
+ hdc = GetDC(td->w);
+
+ /* Background color */
+ SetBkColor(hdc, RGB(0, 0, 0));
+
+ /* Foreground color */
+ if (colors16)
+ {
+ SetTextColor(hdc, PALETTEINDEX(win_pal[a]));
+ }
+ else if (paletted)
+ {
+ SetTextColor(hdc, win_clr[a&0x0F]);
+ }
+ else
+ {
+ SetTextColor(hdc, win_clr[a]);
+ }
+
+ /* Use the font */
+ SelectObject(hdc, td->font_id);
+
+ /* bg */
+ if (use_bg) SetBkMode(hdc, TRANSPARENT);
+
+ /* Bizarre size */
+ if (td->bizarre ||
+ (td->tile_hgt != td->font_hgt) ||
+ (td->tile_wid != td->font_wid))
+ {
+ int i;
+
+ /* Erase complete rectangle */
+ ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
+
+ /* bg */
+ if (use_bg) DrawBG(hdc, &rc);
+
+ /* New rectangle */
+ rc.left += ((td->tile_wid - td->font_wid) / 2);
+ rc.right = rc.left + td->font_wid;
+ rc.top += ((td->tile_hgt - td->font_hgt) / 2);
+ rc.bottom = rc.top + td->font_hgt;
+
+ /* Dump each character */
+ for (i = 0; i < n; i++)
+ {
+#ifdef JP
+ if (use_bigtile && *(s+i)=="■"[0] && *(s+i+1)=="■"[1])
+ {
+ rc.right += td->font_wid;
+
+ oldBrush = SelectObject(hdc, myBrush);
+ oldPen = SelectObject(hdc, GetStockObject(NULL_PEN) );
+
+ /* Dump the wall */
+ Rectangle(hdc, rc.left, rc.top, rc.right+1, rc.bottom+1);
+
+ SelectObject(hdc, oldBrush);
+ SelectObject(hdc, oldPen);
+ rc.right -= td->font_wid;
+
+ /* Advance */
+ i++;
+ rc.left += 2 * td->tile_wid;
+ rc.right += 2 * td->tile_wid;
+ }
+ else if ( iskanji(*(s+i)) ) /* 2バイト文字 */
+ {
+ rc.right += td->font_wid;
+ /* Dump the text */
+ ExtTextOut(hdc, rc.left, rc.top, ETO_CLIPPED, &rc,
+ s+i, 2, NULL);
+ rc.right -= td->font_wid;
+
+ /* Advance */
+ i++;
+ rc.left += 2 * td->tile_wid;
+ rc.right += 2 * td->tile_wid;
+ } else if (*(s+i)==127){
+ oldBrush = SelectObject(hdc, myBrush);
+ oldPen = SelectObject(hdc, GetStockObject(NULL_PEN) );
+
+ /* Dump the wall */
+ Rectangle(hdc, rc.left, rc.top, rc.right+1, rc.bottom+1);
+
+ SelectObject(hdc, oldBrush);
+ SelectObject(hdc, oldPen);
+
+ /* Advance */
+ rc.left += td->tile_wid;
+ rc.right += td->tile_wid;
+ } else {
+ /* Dump the text */
+ ExtTextOut(hdc, rc.left, rc.top, ETO_CLIPPED, &rc, s+i, 1, NULL);
+
+ /* Advance */
+ rc.left += td->tile_wid;
+ rc.right += td->tile_wid;
+ }
+#else
+#if 1
+ if (*(s+i)==127){
+ oldBrush = SelectObject(hdc, myBrush);
+ oldPen = SelectObject(hdc, GetStockObject(NULL_PEN) );
+
+ /* Dump the wall */
+ Rectangle(hdc, rc.left, rc.top, rc.right+1, rc.bottom+1);
+
+ SelectObject(hdc, oldBrush);
+ SelectObject(hdc, oldPen);
+
+ /* Advance */
+ rc.left += td->tile_wid;
+ rc.right += td->tile_wid;
+ } else {
+ /* Dump the text */
+ ExtTextOut(hdc, rc.left, rc.top, ETO_CLIPPED, &rc,
+ s+i, 1, NULL);
+
+ /* Advance */
+ rc.left += td->tile_wid;
+ rc.right += td->tile_wid;
+ }
+#else
+ /* Dump the text */
+ ExtTextOut(hdc, rc.left, rc.top, 0, &rc,
+ s+i, 1, NULL);
+
+ /* Advance */
+ rc.left += td->tile_wid;
+ rc.right += td->tile_wid;
+#endif
+#endif
+
+ }
+ }
+
+ /* Normal size */
+ else
+ {
+ /* Dump the text */
+ ExtTextOut(hdc, rc.left, rc.top, ETO_OPAQUE | ETO_CLIPPED, &rc,
+ s, n, NULL);
+ }
+
+ /* Release DC */
+ ReleaseDC(td->w, hdc);
+
+ /* Success */
+ return 0;
+}
+
+
+/*
+ * Low level graphics. Assumes valid input.
+ *
+ * Draw an array of "special" attr/char pairs at the given location.
+ *
+ * We use the "Term_pict_win()" function for "graphic" data, which are
+ * encoded by setting the "high-bits" of both the "attr" and the "char"
+ * data. We use the "attr" to represent the "row" of the main bitmap,
+ * and the "char" to represent the "col" of the main bitmap. The use
+ * of this function is induced by the "higher_pict" flag.
+ *
+ * If "graphics" is not available, we simply "wipe" the given grids.
+ */
+static errr Term_pict_win(TERM_LEN x, TERM_LEN y, int n, const TERM_COLOR *ap, concptr cp, const TERM_COLOR *tap, concptr tcp)
+{
+ term_data *td = (term_data*)(Term->data);
+
+#ifdef USE_GRAPHICS
+
+ int i;
+ TERM_LEN x1, y1, w1, h1, tw1, th1;
+ TERM_LEN x2, y2, w2, h2, tw2 = 0;
+ TERM_LEN x3, y3;
+
+ HDC hdcMask = NULL;
+
+ HDC hdc;
+ HDC hdcSrc;
+ HBITMAP hbmSrcOld;
+
+ /* Paranoia */
+ if (!use_graphics)
+ {
+ /* Erase the grids */
+ return (Term_wipe_win(x, y, n));
+ }
+
+ /* Size of bitmap cell */
+ w1 = infGraph.CellWidth;
+ h1 = infGraph.CellHeight;
+ tw1 = infGraph.TileWidth;
+ th1 = infGraph.TileHeight;
+
+ /* Size of window cell */
+ if (td->map_active)
+ {
+ w2 = td->map_tile_wid;
+ h2 = td->map_tile_hgt;
+ }
+ else
+ {
+ w2 = td->tile_wid;
+ h2 = td->tile_hgt;
+ tw2 = w2;
+
+ /* big tile mode */
+ if (use_bigtile) tw2 *= 2;
+ }
+
+ /* Location of window cell */
+ x2 = x * w2 + td->size_ow1 + infGraph.OffsetX;
+ y2 = y * h2 + td->size_oh1 + infGraph.OffsetY;
+
+ /* Info */
+ hdc = GetDC(td->w);
+
+ /* More info */
+ hdcSrc = CreateCompatibleDC(hdc);
+ hbmSrcOld = SelectObject(hdcSrc, infGraph.hBitmap);
+
+ if (arg_graphics == GRAPHICS_ADAM_BOLT || arg_graphics == GRAPHICS_HENGBAND)
+ {
+ hdcMask = CreateCompatibleDC(hdc);
+ SelectObject(hdcMask, infMask.hBitmap);
+ }
+
+ /* Draw attr/char pairs */
+ for (i = 0; i < n; i++, x2 += w2)
+ {
+ TERM_COLOR a = ap[i];
+ char c = cp[i];
+
+
+ /* Extract picture */
+ int row = (a & 0x7F);
+ int col = (c & 0x7F);
+
+ /* Location of bitmap cell */
+ x1 = col * w1;
+ y1 = row * h1;
+
+ if (arg_graphics == GRAPHICS_ADAM_BOLT || arg_graphics == GRAPHICS_HENGBAND)
+ {
+ x3 = (tcp[i] & 0x7F) * w1;
+ y3 = (tap[i] & 0x7F) * h1;
+ tw2 = tw2 * w1 / tw1;
+ h2 = h2 * h1 / th1;
+
+ /* Perfect size */
+ if ((tw1 == tw2) && (th1 == h2))
+ {
+ /* Copy the terrain picture from the bitmap to the window */
+ BitBlt(hdc, x2, y2, tw2, h2, hdcSrc, x3, y3, SRCCOPY);
+
+ /* Mask out the tile */
+ BitBlt(hdc, x2, y2, tw2, h2, hdcMask, x1, y1, SRCAND);
+
+ /* Draw the tile */
+ BitBlt(hdc, x2, y2, tw2, h2, hdcSrc, x1, y1, SRCPAINT);
+ }
+
+ /* Need to stretch */
+ else
+ {
+ /* Set the correct mode for stretching the tiles */
+ SetStretchBltMode(hdc, COLORONCOLOR);
+
+ /* Copy the terrain picture from the bitmap to the window */
+ StretchBlt(hdc, x2, y2, tw2, h2, hdcMask, x3, y3, w1, h1, SRCAND);
+
+ StretchBlt(hdc, x2, y2, tw2, h2, hdcSrc, x3, y3, w1, h1, SRCPAINT);
+
+ /* Only draw if terrain and overlay are different */
+ if ((x1 != x3) || (y1 != y3))
+ {
+ /* Mask out the tile */
+ StretchBlt(hdc, x2, y2, tw2, h2, hdcMask, x1, y1, w1, h1, SRCAND);
+
+ /* Draw the tile */
+ StretchBlt(hdc, x2, y2, tw2, h2, hdcSrc, x1, y1, w1, h1, SRCPAINT);
+ }
+ }
+ }
+ else
+ {
+ /* Perfect size */
+ if ((w1 == tw2) && (h1 == h2))
+ {
+ /* Copy the picture from the bitmap to the window */
+ BitBlt(hdc, x2, y2, tw2, h2, hdcSrc, x1, y1, SRCCOPY);
+ }
+
+ /* Need to stretch */
+ else
+ {
+ /* Set the correct mode for stretching the tiles */
+ SetStretchBltMode(hdc, COLORONCOLOR);
+
+ /* Copy the picture from the bitmap to the window */
+ StretchBlt(hdc, x2, y2, tw2, h2, hdcSrc, x1, y1, w1, h1, SRCCOPY);
+ }
+ }
+ }
+
+ /* Release */
+ SelectObject(hdcSrc, hbmSrcOld);
+ DeleteDC(hdcSrc);
+
+ if (arg_graphics == GRAPHICS_ADAM_BOLT || arg_graphics == GRAPHICS_HENGBAND)
+ {
+ /* Release */
+ SelectObject(hdcMask, hbmSrcOld);
+ DeleteDC(hdcMask);
+ }
+
+ /* Release */
+ ReleaseDC(td->w, hdc);
+
+#else /* USE_GRAPHICS */
+
+ /* Just erase this grid */
+ return (Term_wipe_win(x, y, n));
+
+#endif /* USE_GRAPHICS */
+
+ /* Success */
+ return 0;
+}
+
+
+static void windows_map(void)
+{
+ term_data *td = &data[0];
+ TERM_COLOR a;
+ char c;
+ TERM_LEN x, min_x, max_x;
+ TERM_LEN y, min_y, max_y;
+
+ TERM_COLOR ta;
+ char tc;
+
+ /* Only in graphics mode */
+ if (!use_graphics) return;
+ Term_xtra_win_clear();
+
+ td->map_tile_wid = (td->tile_wid * td->cols) / MAX_WID;
+ td->map_tile_hgt = (td->tile_hgt * td->rows) / MAX_HGT;
+ td->map_active = TRUE;
+
+ {
+ min_x = 0;
+ min_y = 0;
+ max_x = cur_wid;
+ max_y = cur_hgt;
+ }
+
+ /* Draw the map */
+ for (x = min_x; x < max_x; x++)
+ {
+ for (y = min_y; y < max_y; y++)
+ {
+ map_info(y, x, &a, (char*)&c, &ta, (char*)&tc);
+
+ /* Ignore non-graphics */
+ if ((a & 0x80) && (c & 0x80))
+ {
+ Term_pict_win(x - min_x, y - min_y, 1, &a, &c, &ta, &tc);
+ }
+ }
+ }
+
+ /* Hilite the player */
+ Term_curs_win(p_ptr->x - min_x, p_ptr->y - min_y);
+
+ /* Wait for a keypress, flush key buffer */
+ Term_inkey(&c, TRUE, TRUE);
+ Term_flush();
+
+ /* Switch off the map display */
+ td->map_active = FALSE;
+
+ /* Restore screen */
+ Term_xtra_win_clear();
+ Term_redraw();
+}
+
+
+/*** Other routines ***/
+
+
+/*
+ * Create and initialize a "term_data" given a title
+ */
+static void term_data_link(term_data *td)
+{
+ term *t = &td->t;
+
+ /* Initialize the term */
+ term_init(t, td->cols, td->rows, td->keys);
+
+ /* Use a "software" cursor */
+ t->soft_cursor = TRUE;
+
+ /* Use "Term_pict" for "graphic" data */
+ t->higher_pict = TRUE;
+
+ /* Erase with "white space" */
+ t->attr_blank = TERM_WHITE;
+ t->char_blank = ' ';
+
+#if 0
+ /* Prepare the init/nuke hooks */
+ t->init_hook = Term_init_win;
+ t->nuke_hook = Term_nuke_win;
+#endif
+
+ /* Prepare the template hooks */
+ t->user_hook = Term_user_win;
+ t->xtra_hook = Term_xtra_win;
+ t->curs_hook = Term_curs_win;
+ t->bigcurs_hook = Term_bigcurs_win;
+ t->wipe_hook = Term_wipe_win;
+ t->text_hook = Term_text_win;
+ t->pict_hook = Term_pict_win;
+
+ /* Remember where we came from */
+ t->data = (vptr)(td);
+}
+
+
+/*
+ * Create the windows
+ *
+ * First, instantiate the "default" values, then read the "ini_file"
+ * to over-ride selected values, then create the windows, and fonts.
+ *
+ * Must use SW_SHOW not SW_SHOWNA, since on 256 color display
+ * must make active to realize the palette.
+ */
+static void init_windows(void)
+{
+ int i;
+
+ term_data *td;
+
+#if 0 /* #ifndef JP */
+ char buf[1024];
+#endif
+
+ /* Main window */
+ td = &data[0];
+ WIPE(td, term_data);
+#ifdef JP
+ td->s = "変愚蛮怒";
+#else
+ td->s = angband_term_name[0];
+#endif
+
+ td->keys = 1024;
+ td->rows = 24;
+ td->cols = 80;
+ td->visible = TRUE;
+ td->size_ow1 = 2;
+ td->size_ow2 = 2;
+ td->size_oh1 = 2;
+ td->size_oh2 = 2;
+ td->pos_x = 7 * 30;
+ td->pos_y = 7 * 20;
+ td->posfix = FALSE;
+#if 1 /* #ifdef JP */
+ td->bizarre = TRUE;
+#endif
+ /* Sub windows */
+ for (i = 1; i < MAX_TERM_DATA; i++)
+ {
+ td = &data[i];
+ WIPE(td, term_data);
+ td->s = angband_term_name[i];
+ td->keys = 16;
+ td->rows = 24;
+ td->cols = 80;
+ td->visible = FALSE;
+ td->size_ow1 = 1;
+ td->size_ow2 = 1;
+ td->size_oh1 = 1;
+ td->size_oh2 = 1;
+ td->pos_x = (7 - i) * 30;
+ td->pos_y = (7 - i) * 20;
+ td->posfix = FALSE;
+#if 1 /* #ifdef JP */
+ td->bizarre = TRUE;
+#endif
+ }
+
+
+ /* Load prefs */
+ load_prefs();
+
+
+ /* Main window (need these before term_getsize gets called) */
+ td = &data[0];
+ td->dwStyle = (WS_OVERLAPPED | WS_THICKFRAME | WS_SYSMENU |
+ WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CAPTION |
+ WS_VISIBLE);
+ td->dwExStyle = 0;
+ td->visible = TRUE;
+
+ /* Sub windows (need these before term_getsize gets called) */
+ for (i = 1; i < MAX_TERM_DATA; i++)
+ {
+ td = &data[i];
+ td->dwStyle = (WS_OVERLAPPED | WS_THICKFRAME | WS_SYSMENU);
+ td->dwExStyle = (WS_EX_TOOLWINDOW);
+ }
+
+
+ /* All windows */
+ for (i = 0; i < MAX_TERM_DATA; i++)
+ {
+ td = &data[i];
+
+#if 1 /* #ifdef JP */
+ strncpy(td->lf.lfFaceName, td->font_want, LF_FACESIZE);
+ td->lf.lfCharSet = DEFAULT_CHARSET;
+ td->lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
+ /* Activate the chosen font */
+ term_force_font(td, NULL);
+ if(!td->tile_wid) td->tile_wid = td->font_wid;
+ if(!td->tile_hgt) td->tile_hgt = td->font_hgt;
+#else
+ /* Access the standard font file */
+ path_build(buf, sizeof(buf), ANGBAND_DIR_XTRA_FONT, td->font_want);
+
+ /* Activate the chosen font */
+ if (term_force_font(td, buf))
+ {
+ /* Access the standard font file */
+ path_build(buf, sizeof(buf), ANGBAND_DIR_XTRA_FONT, "8X13.FON");
+
+ /* Force the use of that font */
+ (void)term_force_font(td, buf);
+
+ td->tile_wid = 8;
+ td->tile_hgt = 13;
+
+ /* Assume not bizarre */
+ td->bizarre = FALSE;
+ }
+#endif
+
+
+ /* Analyze the font */
+ term_getsize(td);
+
+ /* Resize the window */
+ term_window_resize(td);
+ }
+
+
+ /* Sub windows (reverse order) */
+ for (i = MAX_TERM_DATA - 1; i >= 1; --i)
+ {
+ td = &data[i];
+
+ my_td = td;
+ td->w = CreateWindowEx(td->dwExStyle, AngList,
+ td->s, td->dwStyle,
+ td->pos_x, td->pos_y,
+ td->size_wid, td->size_hgt,
+ HWND_DESKTOP, NULL, hInstance, NULL);
+ my_td = NULL;
+ if (!td->w) quit(_("サブウィンドウに作成に失敗しました", "Failed to create sub-window"));
+
+ if (td->visible)
+ {
+ td->size_hack = TRUE;
+ ShowWindow(td->w, SW_SHOW);
+ td->size_hack = FALSE;
+ }
+
+ term_data_link(td);
+ angband_term[i] = &td->t;
+
+ if (td->visible)
+ {
+ /* Activate the window */
+ SetActiveWindow(td->w);
+ }
+
+ if (data[i].posfix)
+ {
+ term_window_pos(&data[i], HWND_TOPMOST);
+ }
+ else
+ {
+ term_window_pos(&data[i], td->w);
+ }
+ }
+
+
+ /* Main window */
+ td = &data[0];
+
+ /* Main window */
+ my_td = td;
+ td->w = CreateWindowEx(td->dwExStyle, AppName,
+ td->s, td->dwStyle,
+ td->pos_x, td->pos_y,
+ td->size_wid, td->size_hgt,
+ HWND_DESKTOP, NULL, hInstance, NULL);
+ my_td = NULL;
+ if (!td->w) quit(_("メインウィンドウの作成に失敗しました", "Failed to create Angband window"));
+
+ term_data_link(td);
+ angband_term[0] = &td->t;
+ normsize.x = td->cols;
+ normsize.y = td->rows;
+
+ /* Activate the main window */
+ if (win_maximized) ShowWindow(td->w, SW_SHOWMAXIMIZED);
+ else ShowWindow(td->w, SW_SHOW);
+
+ /* Bring main window back to top */
+ SetWindowPos(td->w, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+
+
+ /* New palette */
+ (void)new_palette();
+
+
+ /* Create a "brush" for drawing the "cursor" */
+ hbrYellow = CreateSolidBrush(win_clr[TERM_YELLOW]);
+
+
+ /* Process pending messages */
+ (void)Term_xtra_win_flush();
+}
+
+
+
+/*
+ * Prepare the menus
+ */
+static void setup_menus(void)
+{
+ int i;
+
+ HMENU hm = GetMenu(data[0].w);
+
+
+ /* Menu "File", Disable all */
+ EnableMenuItem(hm, IDM_FILE_NEW,
+ MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+ EnableMenuItem(hm, IDM_FILE_OPEN,
+ MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+ EnableMenuItem(hm, IDM_FILE_SAVE,
+ MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+ EnableMenuItem(hm, IDM_FILE_EXIT,
+ MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+ EnableMenuItem(hm, IDM_FILE_SCORE,
+ MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+
+
+ /* No character available */
+ if (!character_generated)
+ {
+ /* Menu "File", Item "New" */
+ EnableMenuItem(hm, IDM_FILE_NEW, MF_BYCOMMAND | MF_ENABLED);
+
+ /* Menu "File", Item "Open" */
+ EnableMenuItem(hm, IDM_FILE_OPEN, MF_BYCOMMAND | MF_ENABLED);
+ }
+
+ /* A character available */
+ if (character_generated)
+ {
+ /* Menu "File", Item "Save" */
+ EnableMenuItem(hm, IDM_FILE_SAVE,
+ MF_BYCOMMAND | MF_ENABLED);
+ }
+
+ /* Menu "File", Item "Exit" */
+ EnableMenuItem(hm, IDM_FILE_EXIT,
+ MF_BYCOMMAND | MF_ENABLED);
+
+ EnableMenuItem(hm, IDM_FILE_SCORE,
+ MF_BYCOMMAND | MF_ENABLED);
+
+
+ /* Menu "Window::Visibility" */
+ for (i = 0; i < MAX_TERM_DATA; i++)
+ {
+ EnableMenuItem(hm, IDM_WINDOW_VIS_0 + i,
+ MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+
+ CheckMenuItem(hm, IDM_WINDOW_VIS_0 + i,
+ (data[i].visible ? MF_CHECKED : MF_UNCHECKED));
+
+ EnableMenuItem(hm, IDM_WINDOW_VIS_0 + i,
+ MF_BYCOMMAND | MF_ENABLED);
+ }
+
+ /* Menu "Window::Font" */
+ for (i = 0; i < MAX_TERM_DATA; i++)
+ {
+ EnableMenuItem(hm, IDM_WINDOW_FONT_0 + i,
+ MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+
+ if (data[i].visible)
+ {
+ EnableMenuItem(hm, IDM_WINDOW_FONT_0 + i,
+ MF_BYCOMMAND | MF_ENABLED);
+ }
+ }
+
+ /* Menu "Window::Window Position Fix" */
+ for (i = 0; i < MAX_TERM_DATA; i++)
+ {
+ EnableMenuItem(hm, IDM_WINDOW_POS_0 + i,
+ MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+
+ CheckMenuItem(hm, IDM_WINDOW_POS_0 + i,
+ (data[i].posfix ? MF_CHECKED : MF_UNCHECKED));
+
+ if (data[i].visible)
+ {
+ EnableMenuItem(hm, IDM_WINDOW_POS_0 + i,
+ MF_BYCOMMAND | MF_ENABLED);
+ }
+ }
+
+ /* Menu "Window::Bizarre Display" */
+ for (i = 0; i < MAX_TERM_DATA; i++)
+ {
+ EnableMenuItem(hm, IDM_WINDOW_BIZ_0 + i,
+ MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+
+ CheckMenuItem(hm, IDM_WINDOW_BIZ_0 + i,
+ (data[i].bizarre ? MF_CHECKED : MF_UNCHECKED));
+
+ if (data[i].visible)
+ {
+ EnableMenuItem(hm, IDM_WINDOW_BIZ_0 + i,
+ MF_BYCOMMAND | MF_ENABLED);
+
+ }
+ }
+
+ /* Menu "Window::Increase Tile Width" */
+ for (i = 0; i < MAX_TERM_DATA; i++)
+ {
+ EnableMenuItem(hm, IDM_WINDOW_I_WID_0 + i,
+ MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+
+ if (data[i].visible)
+ {
+ EnableMenuItem(hm, IDM_WINDOW_I_WID_0 + i,
+ MF_BYCOMMAND | MF_ENABLED);
+
+ }
+ }
+
+ /* Menu "Window::Decrease Tile Width" */
+ for (i = 0; i < MAX_TERM_DATA; i++)
+ {
+ EnableMenuItem(hm, IDM_WINDOW_D_WID_0 + i,
+ MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+
+ if (data[i].visible)
+ {
+ EnableMenuItem(hm, IDM_WINDOW_D_WID_0 + i,
+ MF_BYCOMMAND | MF_ENABLED);
+
+ }
+ }
+
+ /* Menu "Window::Increase Tile Height" */
+ for (i = 0; i < MAX_TERM_DATA; i++)
+ {
+ EnableMenuItem(hm, IDM_WINDOW_I_HGT_0 + i,
+ MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+
+ if (data[i].visible)
+ {
+ EnableMenuItem(hm, IDM_WINDOW_I_HGT_0 + i,
+ MF_BYCOMMAND | MF_ENABLED);
+
+ }
+ }
+
+ /* Menu "Window::Decrease Tile Height" */
+ for (i = 0; i < MAX_TERM_DATA; i++)
+ {
+ EnableMenuItem(hm, IDM_WINDOW_D_HGT_0 + i,
+ MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+
+ if (data[i].visible)
+ {
+ EnableMenuItem(hm, IDM_WINDOW_D_HGT_0 + i,
+ MF_BYCOMMAND | MF_ENABLED);
+
+ }
+ }
+
+ /* Menu "Options", disable all */
+ EnableMenuItem(hm, IDM_OPTIONS_NO_GRAPHICS,
+ MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+ EnableMenuItem(hm, IDM_OPTIONS_OLD_GRAPHICS,
+ MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+ EnableMenuItem(hm, IDM_OPTIONS_NEW_GRAPHICS,
+ MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+ EnableMenuItem(hm, IDM_OPTIONS_BIGTILE,
+ MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+ EnableMenuItem(hm, IDM_OPTIONS_SOUND,
+ MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+#ifndef JP
+ EnableMenuItem(hm, IDM_OPTIONS_SAVER,
+ MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+#endif
+
+ /* Menu "Options", Item "Map" */
+ if (use_graphics != GRAPHICS_NONE)
+ EnableMenuItem(GetMenu(data[0].w), IDM_OPTIONS_MAP, MF_BYCOMMAND | MF_ENABLED);
+ else
+ EnableMenuItem(GetMenu(data[0].w), IDM_OPTIONS_MAP,
+ MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+
+ /* Menu "Options", update all */
+ CheckMenuItem(hm, IDM_OPTIONS_NO_GRAPHICS,
+ (arg_graphics == GRAPHICS_NONE ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(hm, IDM_OPTIONS_OLD_GRAPHICS,
+ (arg_graphics == GRAPHICS_ORIGINAL ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(hm, IDM_OPTIONS_NEW_GRAPHICS,
+ (arg_graphics == GRAPHICS_ADAM_BOLT ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(hm, IDM_OPTIONS_NEW2_GRAPHICS,
+ (arg_graphics == GRAPHICS_HENGBAND ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(hm, IDM_OPTIONS_BIGTILE,
+ (arg_bigtile ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(hm, IDM_OPTIONS_MUSIC,
+ (arg_music ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(hm, IDM_OPTIONS_SOUND,
+ (arg_sound ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(hm, IDM_OPTIONS_BG,
+ (use_bg ? MF_CHECKED : MF_UNCHECKED));
+#ifndef JP
+ CheckMenuItem(hm, IDM_OPTIONS_SAVER,
+ (hwndSaver ? MF_CHECKED : MF_UNCHECKED));
+#endif
+
+#ifdef USE_GRAPHICS
+ /* Menu "Options", Item "Graphics" */
+ EnableMenuItem(hm, IDM_OPTIONS_NO_GRAPHICS, MF_ENABLED);
+ /* Menu "Options", Item "Graphics" */
+ EnableMenuItem(hm, IDM_OPTIONS_OLD_GRAPHICS, MF_ENABLED);
+ /* Menu "Options", Item "Graphics" */
+ EnableMenuItem(hm, IDM_OPTIONS_NEW_GRAPHICS, MF_ENABLED);
+ /* Menu "Options", Item "Graphics" */
+ EnableMenuItem(hm, IDM_OPTIONS_BIGTILE, MF_ENABLED);
+#endif /* USE_GRAPHICS */
+
+#ifdef USE_SOUND
+ /* Menu "Options", Item "Sound" */
+ EnableMenuItem(hm, IDM_OPTIONS_SOUND, MF_ENABLED);
+#endif /* USE_SOUND */
+
+#ifdef USE_SAVER
+ /* Menu "Options", Item "ScreenSaver" */
+ EnableMenuItem(hm, IDM_OPTIONS_SAVER,
+ MF_BYCOMMAND | MF_ENABLED);
+#endif /* USE_SAVER */
+}
+
+
+/*
+ * Check for double clicked (or dragged) savefile
+ *
+ * Apparently, Windows copies the entire filename into the first
+ * piece of the "command line string". Perhaps we should extract
+ * the "basename" of that filename and append it to the "save" dir.
+ */
+static void check_for_save_file(LPSTR cmd_line)
+{
+ char *s;
+
+ /* First arg */
+ s = cmd_line;
+
+ /* No args */
+ if (!*s) return;
+
+ /* Extract filename */
+ strcat(savefile, s);
+
+ /* Validate the file */
+ validate_file(savefile);
+
+ /* Game in progress */
+ game_in_progress = TRUE;
+
+ /* Play game */
+ play_game(FALSE);
+}
+
+
+/*
+ * Process a menu command
+ */
+static void process_menus(WORD wCmd)
+{
+ int i;
+
+ term_data *td;
+
+ OPENFILENAME ofn;
+
+ /* Analyze */
+ switch (wCmd)
+ {
+ /* New game */
+ case IDM_FILE_NEW:
+ {
+ if (!initialized)
+ {
+ plog(_("まだ初期化中です...", "You cannot do that yet..."));
+ }
+ else if (game_in_progress)
+ {
+ plog(_("プレイ中は新しいゲームを始めることができません!", "You can't start a new game while you're still playing!"));
+ }
+ else
+ {
+ game_in_progress = TRUE;
+ Term_flush();
+ play_game(TRUE);
+ quit(NULL);
+ }
+ break;
+ }
+
+ /* Open game */
+ case IDM_FILE_OPEN:
+ {
+ if (!initialized)
+ {
+ plog(_("まだ初期化中です...", "You cannot do that yet..."));
+ }
+ else if (game_in_progress)
+ {
+ plog(_("プレイ中はゲームをロードすることができません!", "You can't open a new game while you're still playing!"));
+ }
+ else
+ {
+ memset(&ofn, 0, sizeof(ofn));
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hwndOwner = data[0].w;
+ ofn.lpstrFilter = "Save Files (*.)\0*\0";
+ ofn.nFilterIndex = 1;
+ ofn.lpstrFile = savefile;
+ ofn.nMaxFile = 1024;
+ ofn.lpstrInitialDir = ANGBAND_DIR_SAVE;
+ ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR | OFN_HIDEREADONLY;
+
+ if (GetOpenFileName(&ofn))
+ {
+ /* Load 'savefile' */
+ validate_file(savefile);
+ game_in_progress = TRUE;
+ Term_flush();
+ play_game(FALSE);
+ quit(NULL);
+ }
+ }
+ break;
+ }
+
+ /* Save game */
+ case IDM_FILE_SAVE:
+ {
+ if (game_in_progress && character_generated)
+ {
+ /* Paranoia */
+ if (!can_save)
+ {
+ plog(_("今はセーブすることは出来ません。", "You may not do that right now."));
+ break;
+ }
+
+ /* Hack -- Forget messages */
+ msg_flag = FALSE;
+
+ /* Save the game */
+#ifdef ZANGBAND
+ do_cmd_save_game(FALSE);
+#else /* ZANGBAND */
+ do_cmd_save_game();
+#endif /* ZANGBAND */
+ }
+ else
+ {
+ plog(_("今、セーブすることは出来ません。", "You may not do that right now."));
+ }
+ break;
+ }
+
+ /* Exit */
+ case IDM_FILE_EXIT:
+ {
+ if (game_in_progress && character_generated)
+ {
+ /* Paranoia */
+ if (!can_save)
+ {
+ plog(_("今は終了できません。", "You may not do that right now."));
+ break;
+ }
+
+ /* Hack -- Forget messages */
+ msg_flag = FALSE;
+
+ forget_lite();
+ forget_view();
+ clear_mon_lite();
+
+ /* Save the game */
+#ifdef ZANGBAND
+ /* do_cmd_save_game(FALSE); */
+#else /* ZANGBAND */
+ /* do_cmd_save_game(); */
+#endif /* ZANGBAND */
+ Term_key_push(SPECIAL_KEY_QUIT);
+ break;
+ }
+ quit(NULL);
+ break;
+ }
+
+ /* Show scores */
+ case IDM_FILE_SCORE:
+ {
+ char buf[1024];
+
+ /* Build the filename */
+ path_build(buf, sizeof(buf), ANGBAND_DIR_APEX, "scores.raw");
+
+ /* Open the binary high score file, for reading */
+ highscore_fd = fd_open(buf, O_RDONLY);
+
+ /* Paranoia -- No score file */
+ if (highscore_fd < 0)
+ {
+ msg_print("Score file unavailable.");
+ }
+ else
+ {
+ screen_save();
+ Term_clear();
+
+ /* Display the scores */
+ display_scores_aux(0, MAX_HISCORES, -1, NULL);
+
+ /* Shut the high score file */
+ (void)fd_close(highscore_fd);
+
+ /* Forget the high score fd */
+ highscore_fd = -1;
+ screen_load();
+
+ /* Hack - Flush it */
+ Term_fresh();
+ }
+
+ break;
+ }
+
+ /* Open game */
+ case IDM_FILE_MOVIE:
+ {
+ if (!initialized)
+ {
+ plog(_("まだ初期化中です...", "You cannot do that yet..."));
+ }
+ else if (game_in_progress)
+ {
+ plog(_("プレイ中はムービーをロードすることができません!", "You can't open a movie while you're playing!"));
+ }
+ else
+ {
+ memset(&ofn, 0, sizeof(ofn));
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hwndOwner = data[0].w;
+ ofn.lpstrFilter = "Angband Movie Files (*.amv)\0*.amv\0";
+ ofn.nFilterIndex = 1;
+ ofn.lpstrFile = savefile;
+ ofn.nMaxFile = 1024;
+ ofn.lpstrInitialDir = ANGBAND_DIR_USER;
+ ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
+
+ if (GetOpenFileName(&ofn))
+ {
+ /* Load 'savefile' */
+ prepare_browse_movie_aux(savefile);
+ play_game(FALSE);
+ quit(NULL);
+ return;
+ }
+ }
+ break;
+ }
+
+
+ case IDM_WINDOW_VIS_0:
+ {
+ plog(_("メインウィンドウは非表示にできません!", "You are not allowed to do that!"));
+ break;
+ }
+
+ /* Window visibility */
+ case IDM_WINDOW_VIS_1:
+ case IDM_WINDOW_VIS_2:
+ case IDM_WINDOW_VIS_3:
+ case IDM_WINDOW_VIS_4:
+ case IDM_WINDOW_VIS_5:
+ case IDM_WINDOW_VIS_6:
+ case IDM_WINDOW_VIS_7:
+ {
+ i = wCmd - IDM_WINDOW_VIS_0;
+
+ if ((i < 0) || (i >= MAX_TERM_DATA)) break;
+
+ td = &data[i];
+
+ if (!td->visible)
+ {
+ td->visible = TRUE;
+ ShowWindow(td->w, SW_SHOW);
+ term_data_redraw(td);
+ }
+ else
+ {
+ td->visible = FALSE;
+ td->posfix = FALSE;
+ ShowWindow(td->w, SW_HIDE);
+ }
+
+ break;
+ }
+
+ /* Window fonts */
+ case IDM_WINDOW_FONT_0:
+ case IDM_WINDOW_FONT_1:
+ case IDM_WINDOW_FONT_2:
+ case IDM_WINDOW_FONT_3:
+ case IDM_WINDOW_FONT_4:
+ case IDM_WINDOW_FONT_5:
+ case IDM_WINDOW_FONT_6:
+ case IDM_WINDOW_FONT_7:
+ {
+ i = wCmd - IDM_WINDOW_FONT_0;
+
+ if ((i < 0) || (i >= MAX_TERM_DATA)) break;
+
+ td = &data[i];
+
+ term_change_font(td);
+
+ break;
+ }
+
+ /* Window Z Position */
+ case IDM_WINDOW_POS_1:
+ case IDM_WINDOW_POS_2:
+ case IDM_WINDOW_POS_3:
+ case IDM_WINDOW_POS_4:
+ case IDM_WINDOW_POS_5:
+ case IDM_WINDOW_POS_6:
+ case IDM_WINDOW_POS_7:
+ {
+ i = wCmd - IDM_WINDOW_POS_0;
+
+ if ((i < 0) || (i >= MAX_TERM_DATA)) break;
+
+ td = &data[i];
+
+ if (!td->posfix && td->visible)
+ {
+ td->posfix = TRUE;
+ term_window_pos(td, HWND_TOPMOST);
+ }
+ else
+ {
+ td->posfix = FALSE;
+ term_window_pos(td, data[0].w);
+ }
+
+ break;
+ }
+
+ /* Bizarre Display */
+ case IDM_WINDOW_BIZ_0:
+ case IDM_WINDOW_BIZ_1:
+ case IDM_WINDOW_BIZ_2:
+ case IDM_WINDOW_BIZ_3:
+ case IDM_WINDOW_BIZ_4:
+ case IDM_WINDOW_BIZ_5:
+ case IDM_WINDOW_BIZ_6:
+ case IDM_WINDOW_BIZ_7:
+ {
+ i = wCmd - IDM_WINDOW_BIZ_0;
+
+ if ((i < 0) || (i >= MAX_TERM_DATA)) break;
+
+ td = &data[i];
+
+ td->bizarre = !td->bizarre;
+
+ term_getsize(td);
+
+ term_window_resize(td);
+
+ break;
+ }
+
+ /* Increase Tile Width */
+ case IDM_WINDOW_I_WID_0:
+ case IDM_WINDOW_I_WID_1:
+ case IDM_WINDOW_I_WID_2:
+ case IDM_WINDOW_I_WID_3:
+ case IDM_WINDOW_I_WID_4:
+ case IDM_WINDOW_I_WID_5:
+ case IDM_WINDOW_I_WID_6:
+ case IDM_WINDOW_I_WID_7:
+ {
+ i = wCmd - IDM_WINDOW_I_WID_0;
+
+ if ((i < 0) || (i >= MAX_TERM_DATA)) break;
+
+ td = &data[i];
+
+ td->tile_wid += 1;
+
+ term_getsize(td);
+
+ term_window_resize(td);
+
+ break;
+ }
+
+ /* Decrease Tile Height */
+ case IDM_WINDOW_D_WID_0:
+ case IDM_WINDOW_D_WID_1:
+ case IDM_WINDOW_D_WID_2:
+ case IDM_WINDOW_D_WID_3:
+ case IDM_WINDOW_D_WID_4:
+ case IDM_WINDOW_D_WID_5:
+ case IDM_WINDOW_D_WID_6:
+ case IDM_WINDOW_D_WID_7:
+ {
+ i = wCmd - IDM_WINDOW_D_WID_0;
+
+ if ((i < 0) || (i >= MAX_TERM_DATA)) break;
+
+ td = &data[i];
+
+ td->tile_wid -= 1;
+
+ term_getsize(td);
+
+ term_window_resize(td);
+
+ break;
+ }
+
+ /* Increase Tile Height */
+ case IDM_WINDOW_I_HGT_0:
+ case IDM_WINDOW_I_HGT_1:
+ case IDM_WINDOW_I_HGT_2:
+ case IDM_WINDOW_I_HGT_3:
+ case IDM_WINDOW_I_HGT_4:
+ case IDM_WINDOW_I_HGT_5:
+ case IDM_WINDOW_I_HGT_6:
+ case IDM_WINDOW_I_HGT_7:
+ {
+ i = wCmd - IDM_WINDOW_I_HGT_0;
+
+ if ((i < 0) || (i >= MAX_TERM_DATA)) break;
+
+ td = &data[i];
+
+ td->tile_hgt += 1;
+
+ term_getsize(td);
+
+ term_window_resize(td);
+
+ break;
+ }
+
+ /* Decrease Tile Height */
+ case IDM_WINDOW_D_HGT_0:
+ case IDM_WINDOW_D_HGT_1:
+ case IDM_WINDOW_D_HGT_2:
+ case IDM_WINDOW_D_HGT_3:
+ case IDM_WINDOW_D_HGT_4:
+ case IDM_WINDOW_D_HGT_5:
+ case IDM_WINDOW_D_HGT_6:
+ case IDM_WINDOW_D_HGT_7:
+ {
+ i = wCmd - IDM_WINDOW_D_HGT_0;
+
+ if ((i < 0) || (i >= MAX_TERM_DATA)) break;
+
+ td = &data[i];
+
+ td->tile_hgt -= 1;
+
+ term_getsize(td);
+
+ term_window_resize(td);
+
+ break;
+ }
+
+ case IDM_OPTIONS_NO_GRAPHICS:
+ {
+ /* Paranoia */
+ if (!inkey_flag)
+ {
+ plog("You may not do that right now.");
+ break;
+ }
+
+ /* Toggle "arg_graphics" */
+ if (arg_graphics != GRAPHICS_NONE)
+ {
+ arg_graphics = GRAPHICS_NONE;
+
+ /* React to changes */
+ Term_xtra_win_react();
+
+ /* Hack -- Force redraw */
+ Term_key_push(KTRL('R'));
+ }
+
+ break;
+ }
+
+ case IDM_OPTIONS_OLD_GRAPHICS:
+ {
+ /* Paranoia */
+ if (!inkey_flag)
+ {
+ plog("You may not do that right now.");
+ break;
+ }
+
+ /* Toggle "arg_graphics" */
+ if (arg_graphics != GRAPHICS_ORIGINAL)
+ {
+ arg_graphics = GRAPHICS_ORIGINAL;
+
+ /* React to changes */
+ Term_xtra_win_react();
+
+ /* Hack -- Force redraw */
+ Term_key_push(KTRL('R'));
+ }
+
+ break;
+ }
+
+ case IDM_OPTIONS_NEW_GRAPHICS:
+ {
+ /* Paranoia */
+ if (!inkey_flag)
+ {
+ plog("You may not do that right now.");
+ break;
+ }
+
+ /* Toggle "arg_graphics" */
+ if (arg_graphics != GRAPHICS_ADAM_BOLT)
+ {
+ arg_graphics = GRAPHICS_ADAM_BOLT;
+
+ /* React to changes */
+ Term_xtra_win_react();
+
+ /* Hack -- Force redraw */
+ Term_key_push(KTRL('R'));
+ }
+
+ break;
+ }
+
+ case IDM_OPTIONS_NEW2_GRAPHICS:
+ {
+ /* Paranoia */
+ if (!inkey_flag)
+ {
+ plog("You may not do that right now.");
+ break;
+ }
+
+ /* Toggle "arg_graphics" */
+ if (arg_graphics != GRAPHICS_HENGBAND)
+ {
+ arg_graphics = GRAPHICS_HENGBAND;
+
+ /* React to changes */
+ Term_xtra_win_react();
+
+ /* Hack -- Force redraw */
+ Term_key_push(KTRL('R'));
+ }
+
+ break;
+ }
+
+ case IDM_OPTIONS_BIGTILE:
+ {
+ td = &data[0];
+
+ /* Paranoia */
+ if (!inkey_flag)
+ {
+ plog("You may not do that right now.");
+ break;
+ }
+
+ /* Toggle "arg_sound" */
+ arg_bigtile = !arg_bigtile;
+
+ /* Activate */
+ Term_activate(&td->t);
+
+ /* Resize the term */
+ Term_resize(td->cols, td->rows);
+
+ /* Redraw later */
+ InvalidateRect(td->w, NULL, TRUE);
+
+ break;
+ }
+
+ case IDM_OPTIONS_MUSIC:
+ {
+ /* Paranoia */
+ if (!inkey_flag)
+ {
+ plog("You may not do that right now.");
+ break;
+ }
+
+ /* Toggle "arg_sound" */
+ arg_music = !arg_music;
+
+ /* React to changes */
+ Term_xtra_win_react();
+
+ /* Hack -- Force redraw */
+ Term_key_push(KTRL('R'));
+
+ break;
+ }
+
+ case IDM_OPTIONS_SOUND:
+ {
+ /* Paranoia */
+ if (!inkey_flag)
+ {
+ plog("You may not do that right now.");
+ break;
+ }
+
+ /* Toggle "arg_sound" */
+ arg_sound = !arg_sound;
+
+ /* React to changes */
+ Term_xtra_win_react();
+
+ /* Hack -- Force redraw */
+ Term_key_push(KTRL('R'));
+
+ break;
+ }
+
+ /* bg */
+ case IDM_OPTIONS_BG:
+ {
+ /* Paranoia */
+ if (!inkey_flag)
+ {
+ plog("You may not do that right now.");
+ break;
+ }
+
+ /* Toggle "use_bg" */
+ use_bg = !use_bg;
+
+ init_bg();
+
+ /* React to changes */
+ Term_xtra_win_react();
+
+ /* Hack -- Force redraw */
+ Term_key_push(KTRL('R'));
+
+ break;
+ }
+
+ /* bg */
+ case IDM_OPTIONS_OPEN_BG:
+ {
+ /* Paranoia */
+ if (!inkey_flag)
+ {
+ plog("You may not do that right now.");
+ break;
+ }
+ else
+ {
+ memset(&ofn, 0, sizeof(ofn));
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hwndOwner = data[0].w;
+ ofn.lpstrFilter = "Bitmap Files (*.bmp)\0*.bmp\0";
+ ofn.nFilterIndex = 1;
+ ofn.lpstrFile = bg_bitmap_file;
+ ofn.nMaxFile = 1023;
+ ofn.lpstrInitialDir = NULL;
+ ofn.lpstrTitle = _("壁紙を選んでね。", "Choose wall paper.");
+ ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
+
+ if (GetOpenFileName(&ofn))
+ {
+ /* Load 'savefile' */
+ use_bg = 1;
+ init_bg();
+ }
+
+ /* React to changes */
+ Term_xtra_win_react();
+
+ /* Hack -- Force redraw */
+ Term_key_push(KTRL('R'));
+ }
+ break;
+ }
+
+ case IDM_DUMP_SCREEN_HTML:
+ {
+ static char buf[1024] = "";
+ memset(&ofn, 0, sizeof(ofn));
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hwndOwner = data[0].w;
+ ofn.lpstrFilter = "HTML Files (*.html)\0*.html\0";
+ ofn.nFilterIndex = 1;
+ ofn.lpstrFile = buf;
+ ofn.nMaxFile = 1023;
+ ofn.lpstrDefExt = "html";
+ ofn.lpstrInitialDir = NULL;
+ ofn.lpstrTitle = _("HTMLでスクリーンダンプを保存", "Save screen dump as HTML.");
+ ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
+
+ if (GetSaveFileName(&ofn))
+ {
+ do_cmd_save_screen_html_aux(buf, 0);
+ }
+ break;
+ }
+
+#ifdef USE_SAVER
+
+ case IDM_OPTIONS_SAVER:
+ {
+ if (hwndSaver)
+ {
+ DestroyWindow(hwndSaver);
+ hwndSaver = NULL;
+ }
+ else
+ {
+ /* Create a screen scaver window */
+ hwndSaver = CreateWindowEx(WS_EX_TOPMOST, "WindowsScreenSaverClass",
+ "Angband Screensaver",
+ WS_POPUP | WS_MAXIMIZE | WS_VISIBLE,
+ 0, 0, GetSystemMetrics(SM_CXSCREEN),
+ GetSystemMetrics(SM_CYSCREEN),
+ NULL, NULL, hInstance, NULL);
+
+ if (hwndSaver)
+ {
+ /* Push the window to the bottom */
+ SetWindowPos(hwndSaver, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ }
+ else
+ {
+ plog(_("ウィンドウを作成出来ません", "Failed to create saver window"));
+ }
+ }
+ break;
+ }
+
+#endif
+
+ case IDM_OPTIONS_MAP:
+ {
+ windows_map();
+ break;
+ }
+
+ case IDM_HELP_CONTENTS:
+ {
+#ifdef HTML_HELP
+ char tmp[1024];
+ path_build(tmp, sizeof(tmp), ANGBAND_DIR_XTRA_HELP, "zangband.chm");
+ if (check_file(tmp))
+ {
+ HtmlHelp(data[0].w, tmp, HH_DISPLAY_TOPIC, 0);
+ }
+ else
+ {
+ plog_fmt(_("ヘルプファイル[%s]が見付かりません。", "Cannot find help file: %s"), tmp);
+ plog(_("代わりにオンラインヘルプを使用してください。", "Use the online help files instead."));
+ }
+ break;
+#else /* HTML_HELP */
+ char buf[1024];
+ char tmp[1024];
+ path_build(tmp, sizeof(tmp), ANGBAND_DIR_XTRA_HELP, "zangband.hlp");
+ if (check_file(tmp))
+ {
+ sprintf(buf, "winhelp.exe %s", tmp);
+ WinExec(buf, SW_NORMAL);
+ }
+ else
+ {
+ plog_fmt(_("ヘルプファイル[%s]が見付かりません。", "Cannot find help file: %s"), tmp);
+ plog(_("代わりにオンラインヘルプを使用してください。", "Use the online help files instead."));
+
+ }
+ break;
+#endif /* HTML_HELP */
+ }
+ }
+}
+
+
+static bool process_keydown(WPARAM wParam, LPARAM lParam)
+{
+ int i;
+ bool mc = FALSE;
+ bool ms = FALSE;
+ bool ma = FALSE;
+
+ /* Extract the modifiers */
+ if (GetKeyState(VK_CONTROL) & 0x8000) mc = TRUE;
+ if (GetKeyState(VK_SHIFT) & 0x8000) ms = TRUE;
+ if (GetKeyState(VK_MENU) & 0x8000) ma = TRUE;
+
+ Term_no_press = (ma) ? TRUE : FALSE;
+
+ /* Handle "special" keys */
+ if (special_key[(byte)(wParam)] || (ma && !ignore_key[(byte)(wParam)]) )
+ {
+ bool ext_key = (lParam & 0x1000000L) ? TRUE : FALSE;
+ bool numpad = FALSE;
+
+ /* Begin the macro trigger */
+ Term_keypress(31);
+
+ /* Send the modifiers */
+ if (mc) Term_keypress('C');
+ if (ms) Term_keypress('S');
+ if (ma) Term_keypress('A');
+
+ /* Extract "scan code" */
+ i = LOBYTE(HIWORD(lParam));
+
+ /* Introduce the scan code */
+ Term_keypress('x');
+
+ /* Extended key bit */
+ switch (wParam)
+ {
+ /* Numpad Enter and '/' are extended key */
+ case VK_DIVIDE:
+ Term_no_press = TRUE;
+ case VK_RETURN: /* Enter */
+ numpad = ext_key;
+ break;
+ /* Other extended keys are on full keyboard */
+ case VK_NUMPAD0:
+ case VK_NUMPAD1:
+ case VK_NUMPAD2:
+ case VK_NUMPAD3:
+ case VK_NUMPAD4:
+ case VK_NUMPAD5:
+ case VK_NUMPAD6:
+ case VK_NUMPAD7:
+ case VK_NUMPAD8:
+ case VK_NUMPAD9:
+ case VK_ADD:
+ case VK_MULTIPLY:
+ case VK_SUBTRACT:
+ case VK_SEPARATOR:
+ case VK_DECIMAL:
+ Term_no_press = TRUE;
+ case VK_CLEAR:
+ case VK_HOME:
+ case VK_END:
+ case VK_PRIOR: /* Page Up */
+ case VK_NEXT: /* Page Down */
+ case VK_INSERT:
+ case VK_DELETE:
+ case VK_UP:
+ case VK_DOWN:
+ case VK_LEFT:
+ case VK_RIGHT:
+ numpad = !ext_key;
+ }
+
+ /* Special modifiers for keypad keys */
+ if (numpad) Term_keypress('K');
+
+ /* Encode the hexidecimal scan code */
+ Term_keypress(hexsym[i/16]);
+ Term_keypress(hexsym[i%16]);
+
+ /* End the macro trigger */
+ Term_keypress(13);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+
+#ifdef __MWERKS__
+LRESULT FAR PASCAL AngbandWndProc(HWND hWnd, UINT uMsg,
+ WPARAM wParam, LPARAM lParam);
+LRESULT FAR PASCAL AngbandWndProc(HWND hWnd, UINT uMsg,
+ WPARAM wParam, LPARAM lParam)
+#else /* __MWERKS__ */
+LRESULT FAR PASCAL AngbandWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+#endif /* __MWERKS__ */
+{
+ PAINTSTRUCT ps;
+ HDC hdc;
+ term_data *td;
+#if 0
+ MINMAXINFO FAR *lpmmi;
+ RECT rc;
+#endif
+ int i;
+
+
+ /* Acquire proper "term_data" info */
+ td = (term_data *)GetWindowLong(hWnd, 0);
+
+ /* Handle message */
+ switch (uMsg)
+ {
+ case WM_NCCREATE:
+ {
+ SetWindowLong(hWnd, 0, (LONG)(my_td));
+ break;
+ }
+
+ case WM_CREATE:
+ {
+#ifdef USE_MUSIC
+ mop.dwCallback=(DWORD)hWnd;
+#endif
+ return 0;
+ }
+
+ case WM_GETMINMAXINFO:
+ {
+ MINMAXINFO FAR *lpmmi;
+ RECT rc;
+
+ lpmmi = (MINMAXINFO FAR *)lParam;
+
+ /* this message was sent before WM_NCCREATE */
+ if (!td) return 1;
+
+ /* Minimum window size is 80x24 */
+ rc.left = rc.top = 0;
+ rc.right = rc.left + 80 * td->tile_wid + td->size_ow1 + td->size_ow2;
+ rc.bottom = rc.top + 24 * td->tile_hgt + td->size_oh1 + td->size_oh2 + 1;
+
+ /* Adjust */
+ AdjustWindowRectEx(&rc, td->dwStyle, TRUE, td->dwExStyle);
+
+ /* Save minimum size */
+ lpmmi->ptMinTrackSize.x = rc.right - rc.left;
+ lpmmi->ptMinTrackSize.y = rc.bottom - rc.top;
+
+ return 0;
+ }
+
+ case WM_PAINT:
+ {
+ BeginPaint(hWnd, &ps);
+ if (td) term_data_redraw(td);
+ EndPaint(hWnd, &ps);
+ ValidateRect(hWnd, NULL);
+ return 0;
+ }
+
+#ifdef USE_MUSIC
+ case MM_MCINOTIFY:
+ {
+ if(wParam == MCI_NOTIFY_SUCCESSFUL)
+ {
+ mciSendCommand(mop.wDeviceID, MCI_SEEK, MCI_SEEK_TO_START, 0);
+ mciSendCommand(mop.wDeviceID, MCI_PLAY, MCI_NOTIFY, (DWORD)&mop);
+ }
+ return 0;
+ }
+#endif
+
+ case WM_SYSKEYDOWN:
+ case WM_KEYDOWN:
+ {
+ if (process_keydown(wParam, lParam))
+ return 0;
+ break;
+ }
+
+ case WM_CHAR:
+ {
+ if (Term_no_press) Term_no_press = FALSE;
+ else Term_keypress(wParam);
+ return 0;
+ }
+
+ case WM_LBUTTONDOWN:
+ {
+ mousex = MIN(LOWORD(lParam) / td->tile_wid, td->cols - 1);
+ mousey = MIN(HIWORD(lParam) / td->tile_hgt, td->rows - 1);
+ mouse_down = TRUE;
+ oldx = mousex;
+ oldy = mousey;
+ return 0;
+ }
+
+ case WM_LBUTTONUP:
+ {
+ HGLOBAL hGlobal;
+ LPSTR lpStr;
+ int j, sz;
+ TERM_LEN dx = abs(oldx - mousex) + 1;
+ TERM_LEN dy = abs(oldy - mousey) + 1;
+ TERM_LEN ox = (oldx > mousex) ? mousex : oldx;
+ TERM_LEN oy = (oldy > mousey) ? mousey : oldy;
+
+ mouse_down = FALSE;
+ paint_rect = FALSE;
+
+#ifdef JP
+ sz = (dx + 3) * dy;
+#else
+ sz = (dx + 2) * dy;
+#endif
+ hGlobal = GlobalAlloc(GHND, sz + 1);
+ if (hGlobal == NULL) return 0;
+ lpStr = (LPSTR)GlobalLock(hGlobal);
+
+ for (i = 0; i < dy; i++)
+ {
+#ifdef JP
+ char *s;
+ char **scr = data[0].t.scr->c;
+
+ C_MAKE(s, (dx + 1), char);
+ strncpy(s, &scr[oy + i][ox], dx);
+
+ if (ox > 0)
+ {
+ if (iskanji(scr[oy + i][ox - 1])) s[0] = ' ';
+ }
+
+ if (ox + dx < data[0].cols)
+ {
+ if (iskanji(scr[oy + i][ox + dx - 1])) s[dx - 1] = ' ';
+ }
+
+ for (j = 0; j < dx; j++)
+ {
+ if (s[j] == 127) s[j] = '#';
+ *lpStr++ = s[j];
+ }
+#else
+ for (j = 0; j < dx; j++)
+ {
+ *lpStr++ = data[0].t.scr->c[oy + i][ox + j];
+ }
+#endif
+ if (dy > 1)
+ {
+ *lpStr++ = '\r';
+ *lpStr++ = '\n';
+ }
+ }
+
+ GlobalUnlock(hGlobal);
+ if (OpenClipboard(hWnd) == 0)
+ {
+ GlobalFree(hGlobal);
+ return 0;
+ }
+ EmptyClipboard();
+ SetClipboardData(CF_TEXT, hGlobal);
+ CloseClipboard();
+
+ Term_redraw();
+
+ return 0;
+ }
+
+ case WM_MOUSEMOVE:
+ {
+ if (mouse_down)
+ {
+ int dx, dy;
+ int cx = MIN(LOWORD(lParam) / td->tile_wid, td->cols - 1);
+ int cy = MIN(HIWORD(lParam) / td->tile_hgt, td->rows - 1);
+ int ox, oy;
+
+ if (paint_rect)
+ {
+ dx = abs(oldx - mousex) + 1;
+ dy = abs(oldy - mousey) + 1;
+ ox = (oldx > mousex) ? mousex : oldx;
+ oy = (oldy > mousey) ? mousey : oldy;
+ Term_inversed_area(hWnd, ox, oy, dx, dy);
+ }
+ else
+ {
+ paint_rect = TRUE;
+ }
+
+ dx = abs(cx - mousex) + 1;
+ dy = abs(cy - mousey) + 1;
+ ox = (cx > mousex) ? mousex : cx;
+ oy = (cy > mousey) ? mousey : cy;
+ Term_inversed_area(hWnd, ox, oy, dx, dy);
+
+ oldx = cx;
+ oldy = cy;
+ }
+ return 0;
+ }
+
+ case WM_INITMENU:
+ {
+ setup_menus();
+ return 0;
+ }
+
+ case WM_CLOSE:
+ {
+ if (game_in_progress && character_generated)
+ {
+ if (!can_save)
+ {
+ plog(_("今は終了できません。", "You may not do that right now."));
+ return 0;
+ }
+
+ /* Hack -- Forget messages */
+ msg_flag = FALSE;
+
+ forget_lite();
+ forget_view();
+ clear_mon_lite();
+
+ /* Save the game */
+#ifdef ZANGBAND
+ /* do_cmd_save_game(FALSE); */
+#else /* ZANGBAND */
+ /* do_cmd_save_game(); */
+#endif /* ZANGBAND */
+ Term_key_push(SPECIAL_KEY_QUIT);
+ return 0;
+ }
+ quit(NULL);
+ return 0;
+ }
+
+ case WM_QUERYENDSESSION:
+ {
+ if (game_in_progress && character_generated)
+ {
+ /* Hack -- Forget messages */
+ msg_flag = FALSE;
+
+ /* Mega-Hack -- Delay death */
+ if (p_ptr->chp < 0) p_ptr->is_dead = FALSE;
+ do_cmd_write_nikki(NIKKI_GAMESTART, 0, _("----ゲーム中断----", "---- Save and Exit Game ----"));
+
+ /* Hardcode panic save */
+ p_ptr->panic_save = 1;
+
+ /* Forbid suspend */
+ signals_ignore_tstp();
+
+ /* Indicate panic save */
+ (void)strcpy(p_ptr->died_from, _("(緊急セーブ)", "(panic save)"));
+
+ /* Panic save */
+ (void)save_player();
+ }
+ quit(NULL);
+ return 0;
+ }
+
+ case WM_QUIT:
+ {
+ quit(NULL);
+ return 0;
+ }
+
+ case WM_COMMAND:
+ {
+ process_menus(LOWORD(wParam));
+ return 0;
+ }
+
+ case WM_SIZE:
+ {
+ /* this message was sent before WM_NCCREATE */
+ if (!td) return 1;
+
+ /* it was sent from inside CreateWindowEx */
+ if (!td->w) return 1;
+
+ /* was sent from WM_SIZE */
+ if (td->size_hack) return 1;
+
+ switch (wParam)
+ {
+ case SIZE_MINIMIZED:
+ {
+ /* Hide sub-windows */
+ for (i = 1; i < MAX_TERM_DATA; i++)
+ {
+ if (data[i].visible) ShowWindow(data[i].w, SW_HIDE);
+ }
+ return 0;
+ }
+
+ case SIZE_MAXIMIZED:
+ {
+ /* fall through */
+ }
+
+ case SIZE_RESTORED:
+ {
+ TERM_LEN cols = (LOWORD(lParam) - td->size_ow1) / td->tile_wid;
+ TERM_LEN rows = (HIWORD(lParam) - td->size_oh1) / td->tile_hgt;
+
+ /* New size */
+ if ((td->cols != cols) || (td->rows != rows))
+ {
+ /* Save the new size */
+ td->cols = cols;
+ td->rows = rows;
+
+ if (!IsZoomed(td->w) && !IsIconic(td->w))
+ {
+ normsize.x = td->cols;
+ normsize.y = td->rows;
+ }
+
+ /* Activate */
+ Term_activate(&td->t);
+
+ /* Resize the term */
+ Term_resize(td->cols, td->rows);
+
+ /* Redraw later */
+ InvalidateRect(td->w, NULL, TRUE);
+ }
+
+ td->size_hack = TRUE;
+
+ /* Show sub-windows */
+ for (i = 1; i < MAX_TERM_DATA; i++)
+ {
+ if (data[i].visible) ShowWindow(data[i].w, SW_SHOW);
+ }
+
+ td->size_hack = FALSE;
+
+ return 0;
+ }
+ }
+ break;
+ }
+
+ case WM_PALETTECHANGED:
+ {
+ /* Ignore if palette change caused by itself */
+ if ((HWND)wParam == hWnd) return 0;
+
+ /* Fall through... */
+ }
+
+ case WM_QUERYNEWPALETTE:
+ {
+ if (!paletted) return 0;
+
+ hdc = GetDC(hWnd);
+
+ SelectPalette(hdc, hPal, FALSE);
+
+ i = RealizePalette(hdc);
+
+ /* if any palette entries changed, repaint the window. */
+ if (i) InvalidateRect(hWnd, NULL, TRUE);
+
+ ReleaseDC(hWnd, hdc);
+
+ return 0;
+ }
+
+ case WM_ACTIVATE:
+ {
+ if (wParam && !HIWORD(lParam))
+ {
+ /* Do something to sub-windows */
+ for (i = 1; i < MAX_TERM_DATA; i++)
+ {
+ if (!data[i].posfix) term_window_pos(&data[i], hWnd);
+ }
+
+ /* Focus on main window */
+ SetFocus(hWnd);
+
+ return 0;
+ }
+
+ break;
+ }
+
+ case WM_ACTIVATEAPP:
+ {
+ if (IsIconic(td->w)) break;
+
+ for (i = 1; i < MAX_TERM_DATA; i++)
+ {
+ if(data[i].visible)
+ {
+ if (wParam == TRUE)
+ {
+ ShowWindow(data[i].w, SW_SHOW);
+ }
+ else
+ {
+ ShowWindow(data[i].w, SW_HIDE);
+ }
+ }
+ }
+ }
+ }
+
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+
+#ifdef __MWERKS__
+LRESULT FAR PASCAL AngbandListProc(HWND hWnd, UINT uMsg,
+ WPARAM wParam, LPARAM lParam);
+LRESULT FAR PASCAL AngbandListProc(HWND hWnd, UINT uMsg,
+ WPARAM wParam, LPARAM lParam)
+#else /* __MWERKS__ */
+LRESULT FAR PASCAL AngbandListProc(HWND hWnd, UINT uMsg,
+ WPARAM wParam, LPARAM lParam)
+#endif /* __MWERKS__ */
+{
+ term_data *td;
+#if 0
+ MINMAXINFO FAR *lpmmi;
+ RECT rc;
+#endif
+ PAINTSTRUCT ps;
+ HDC hdc;
+ int i;
+
+
+ /* Acquire proper "term_data" info */
+ td = (term_data *)GetWindowLong(hWnd, 0);
+
+ /* Process message */
+ switch (uMsg)
+ {
+ case WM_NCCREATE:
+ {
+ SetWindowLong(hWnd, 0, (LONG)(my_td));
+ break;
+ }
+
+ case WM_CREATE:
+ {
+ return 0;
+ }
+
+ case WM_GETMINMAXINFO:
+ {
+ MINMAXINFO FAR *lpmmi;
+ RECT rc;
+
+ lpmmi = (MINMAXINFO FAR *)lParam;
+
+ /* this message was sent before WM_NCCREATE */
+ if (!td) return 1;
+
+ /* Minimum window size is 80x24 */
+ rc.left = rc.top = 0;
+ rc.right = rc.left + 20 * td->tile_wid + td->size_ow1 + td->size_ow2;
+ rc.bottom = rc.top + 3 * td->tile_hgt + td->size_oh1 + td->size_oh2 + 1;
+
+ /* Adjust */
+ AdjustWindowRectEx(&rc, td->dwStyle, TRUE, td->dwExStyle);
+
+ /* Save minimum size */
+ lpmmi->ptMinTrackSize.x = rc.right - rc.left;
+ lpmmi->ptMinTrackSize.y = rc.bottom - rc.top;
+
+ return 0;
+ }
+
+ case WM_SIZE:
+ {
+ TERM_LEN cols;
+ TERM_LEN rows;
+
+ /* this message was sent before WM_NCCREATE */
+ if (!td) return 1;
+
+ /* it was sent from inside CreateWindowEx */
+ if (!td->w) return 1;
+
+ /* was sent from inside WM_SIZE */
+ if (td->size_hack) return 1;
+
+ td->size_hack = TRUE;
+
+ cols = (LOWORD(lParam) - td->size_ow1) / td->tile_wid;
+ rows = (HIWORD(lParam) - td->size_oh1) / td->tile_hgt;
+
+ /* New size */
+ if ((td->cols != cols) || (td->rows != rows))
+ {
+ /* Save old term */
+ term *old_term = Term;
+
+ /* Save the new size */
+ td->cols = cols;
+ td->rows = rows;
+
+ /* Activate */
+ Term_activate(&td->t);
+
+ /* Resize the term */
+ Term_resize(td->cols, td->rows);
+
+ /* Activate */
+ Term_activate(old_term);
+
+ /* Redraw later */
+ InvalidateRect(td->w, NULL, TRUE);
+
+ /* HACK - Redraw all windows */
+ p_ptr->window = 0xFFFFFFFF;
+ handle_stuff();
+ }
+
+ td->size_hack = FALSE;
+
+ return 0;
+ }
+
+ case WM_PAINT:
+ {
+ BeginPaint(hWnd, &ps);
+ if (td) term_data_redraw(td);
+ EndPaint(hWnd, &ps);
+ return 0;
+ }
+
+ case WM_SYSKEYDOWN:
+ case WM_KEYDOWN:
+ {
+ if (process_keydown(wParam, lParam))
+ return 0;
+ break;
+ }
+
+ case WM_CHAR:
+ {
+ if (Term_no_press) Term_no_press = FALSE;
+ else Term_keypress(wParam);
+ return 0;
+ }
+
+ case WM_PALETTECHANGED:
+ {
+ /* ignore if palette change caused by itself */
+ if ((HWND)wParam == hWnd) return FALSE;
+ /* otherwise, fall through!!! */
+ }
+
+ case WM_QUERYNEWPALETTE:
+ {
+ if (!paletted) return 0;
+ hdc = GetDC(hWnd);
+ SelectPalette(hdc, hPal, FALSE);
+ i = RealizePalette(hdc);
+ /* if any palette entries changed, repaint the window. */
+ if (i) InvalidateRect(hWnd, NULL, TRUE);
+ ReleaseDC(hWnd, hdc);
+ return 0;
+ }
+
+ case WM_NCLBUTTONDOWN:
+ {
+
+#ifdef HTCLOSE
+ if (wParam == HTCLOSE) wParam = HTSYSMENU;
+#endif /* HTCLOSE */
+
+ if (wParam == HTSYSMENU)
+ {
+ if (td->visible)
+ {
+ td->visible = FALSE;
+ ShowWindow(td->w, SW_HIDE);
+ }
+
+ return 0;
+ }
+
+ break;
+ }
+ }
+
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+
+#ifdef USE_SAVER
+
+#define MOUSE_SENS 40
+
+#ifdef __MWERKS__
+LRESULT FAR PASCAL AngbandSaverProc(HWND hWnd, UINT uMsg,
+ WPARAM wParam, LPARAM lParam);
+LRESULT FAR PASCAL AngbandSaverProc(HWND hWnd, UINT uMsg,
+ WPARAM wParam, LPARAM lParam)
+#else /* __MWERKS__ */
+LRESULT FAR PASCAL AngbandSaverProc(HWND hWnd, UINT uMsg,
+ WPARAM wParam, LPARAM lParam)
+#endif /* __MWERKS__ */
+{
+ static int iMouse = 0;
+ static WORD xMouse = 0;
+ static WORD yMouse = 0;
+
+ int dx, dy;
+
+
+ /* Process */
+ switch (uMsg)
+ {
+ case WM_NCCREATE:
+ {
+ break;
+ }
+
+ case WM_SETCURSOR:
+ {
+ SetCursor(NULL);
+ return 0;
+ }
+
+#if 0
+ case WM_ACTIVATE:
+ {
+ if (LOWORD(wParam) == WA_INACTIVE) break;
+
+ /* else fall through */
+ }
+#endif
+
+ case WM_LBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ case WM_KEYDOWN:
+ {
+ SendMessage(hWnd, WM_CLOSE, 0, 0);
+ return 0;
+ }
+
+ case WM_MOUSEMOVE:
+ {
+ if (iMouse)
+ {
+ dx = LOWORD(lParam) - xMouse;
+ dy = HIWORD(lParam) - yMouse;
+
+ if (dx < 0) dx = -dx;
+ if (dy < 0) dy = -dy;
+
+ if ((dx > MOUSE_SENS) || (dy > MOUSE_SENS))
+ {
+ SendMessage(hWnd, WM_CLOSE, 0, 0);
+ }
+ }
+
+ /* Save last location */
+ iMouse = 1;
+ xMouse = LOWORD(lParam);
+ yMouse = HIWORD(lParam);
+
+ return 0;
+ }
+
+ case WM_CLOSE:
+ {
+ DestroyWindow(hwndSaver);
+ hwndSaver = NULL;
+ return 0;
+ }
+ }
+
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+#endif /* USE_SAVER */
+
+
+
+
+
+/*** Temporary Hooks ***/
+
+
+/*
+ * Display warning message (see "z-util.c")
+ */
+static void hack_plog(concptr str)
+{
+ /* Give a warning */
+ if (str)
+ {
+#ifdef JP
+ MessageBox(NULL, str, "警告!",
+ MB_ICONEXCLAMATION | MB_OK);
+#else
+ MessageBox(NULL, str, "Warning",
+ MB_ICONEXCLAMATION | MB_OK);
+#endif
+
+ }
+}
+
+
+/*
+ * Display error message and quit (see "z-util.c")
+ */
+static void hack_quit(concptr str)
+{
+ /* Give a warning */
+ if (str)
+ {
+#ifdef JP
+ MessageBox(NULL, str, "エラー!",
+ MB_ICONEXCLAMATION | MB_OK | MB_ICONSTOP);
+#else
+ MessageBox(NULL, str, "Error",
+ MB_ICONEXCLAMATION | MB_OK | MB_ICONSTOP);
+#endif
+
+ }
+
+ /* Unregister the classes */
+ UnregisterClass(AppName, hInstance);
+
+ /* Destroy the icon */
+ if (hIcon) DestroyIcon(hIcon);
+
+ /* Exit */
+ exit(0);
+}
+
+
+
+/*** Various hooks ***/
+
+
+/*
+ * Display warning message (see "z-util.c")
+ */
+static void hook_plog(concptr str)
+{
+ /* Warning */
+ if (str)
+ {
+#ifdef JP
+ MessageBox(data[0].w, str, "警告!",
+ MB_ICONEXCLAMATION | MB_OK);
+#else
+ MessageBox(data[0].w, str, "Warning",
+ MB_ICONEXCLAMATION | MB_OK);
+#endif
+
+ }
+}
+
+
+/*
+ * Display error message and quit (see "z-util.c")
+ */
+static void hook_quit(concptr str)
+{
+ int i;
+
+
+ /* Give a warning */
+ if (str)
+ {
+#ifdef JP
+ MessageBox(data[0].w, str, "エラー!",
+ MB_ICONEXCLAMATION | MB_OK | MB_ICONSTOP);
+#else
+ MessageBox(data[0].w, str, "Error",
+ MB_ICONEXCLAMATION | MB_OK | MB_ICONSTOP);
+#endif
+
+ }
+
+
+ /* Save the preferences */
+ save_prefs();
+
+
+ /*** Could use 'Term_nuke_win()' */
+
+ /* Destroy all windows */
+ for (i = MAX_TERM_DATA - 1; i >= 0; --i)
+ {
+ term_force_font(&data[i], NULL);
+ if (data[i].font_want) string_free(data[i].font_want);
+ if (data[i].w) DestroyWindow(data[i].w);
+ data[i].w = 0;
+ }
+
+ /* Free the bitmap stuff */
+#ifdef USE_GRAPHICS
+ if (infGraph.hPalette) DeleteObject(infGraph.hPalette);
+ if (infGraph.hBitmap) DeleteObject(infGraph.hBitmap);
+
+ if (infMask.hPalette) DeleteObject(infMask.hPalette);
+ if (infMask.hBitmap) DeleteObject(infMask.hBitmap);
+
+#endif /* USE_GRAPHICS */
+
+ /*** Free some other stuff ***/
+
+ DeleteObject(hbrYellow);
+
+ /* bg */
+ delete_bg();
+
+ if (hPal) DeleteObject(hPal);
+
+ UnregisterClass(AppName, hInstance);
+
+ if (hIcon) DestroyIcon(hIcon);
+
+ exit(0);
+}
+
+
+
+/*** Initialize ***/
+
+
+/*
+ * Init some stuff
+ */
+static void init_stuff(void)
+{
+ int i;
+
+ char path[1024];
+
+
+ /* Get program name with full path */
+ GetModuleFileName(hInstance, path, 512);
+
+ /* Save the "program name" */
+ argv0 = path;
+
+ /* Get the name of the "*.ini" file */
+ strcpy(path + strlen(path) - 4, ".INI");
+
+ /* Save the the name of the ini-file */
+ ini_file = string_make(path);
+
+ /* Analyze the path */
+ i = strlen(path);
+
+ /* Get the path */
+ for (; i > 0; i--)
+ {
+ if (path[i] == '\\')
+ {
+ /* End of path */
+ break;
+ }
+ }
+
+ /* Add "lib" to the path */
+ strcpy(path + i + 1, "lib\\");
+
+ /* Validate the path */
+ validate_dir(path, TRUE);
+
+ /* Init the file paths */
+ init_file_paths(path);
+
+ /* Hack -- Validate the paths */
+ validate_dir(ANGBAND_DIR_APEX, FALSE);
+ validate_dir(ANGBAND_DIR_BONE, FALSE);
+
+ /* Allow missing 'edit' directory */
+ if (!check_dir(ANGBAND_DIR_EDIT))
+ {
+ /* Must have 'data'! */
+ validate_dir(ANGBAND_DIR_DATA, TRUE);
+ }
+ else
+ {
+ /* Don't need 'data' */
+ validate_dir(ANGBAND_DIR_DATA, FALSE);
+ }
+
+ validate_dir(ANGBAND_DIR_FILE, TRUE);
+ validate_dir(ANGBAND_DIR_HELP, FALSE);
+ validate_dir(ANGBAND_DIR_INFO, FALSE);
+ validate_dir(ANGBAND_DIR_PREF, TRUE);
+ validate_dir(ANGBAND_DIR_SAVE, FALSE);
+ validate_dir(ANGBAND_DIR_USER, TRUE);
+ validate_dir(ANGBAND_DIR_XTRA, TRUE);
+
+ /* Build the filename */
+ path_build(path, sizeof(path), ANGBAND_DIR_FILE, _("news_j.txt", "news.txt"));
+
+ /* Hack -- Validate the "news.txt" file */
+ validate_file(path);
+
+
+#if 0 /* #ifndef JP */
+ /* Build the "font" path */
+ path_build(path, sizeof(path), ANGBAND_DIR_XTRA, "font");
+
+ /* Allocate the path */
+ ANGBAND_DIR_XTRA_FONT = string_make(path);
+
+ /* Validate the "font" directory */
+ validate_dir(ANGBAND_DIR_XTRA_FONT, TRUE);
+
+ /* Build the filename */
+ path_build(path, sizeof(path), ANGBAND_DIR_XTRA_FONT, "8X13.FON");
+
+ /* Hack -- Validate the basic font */
+ validate_file(path);
+#endif
+
+
+#ifdef USE_GRAPHICS
+
+ /* Build the "graf" path */
+ path_build(path, sizeof(path), ANGBAND_DIR_XTRA, "graf");
+
+ /* Allocate the path */
+ ANGBAND_DIR_XTRA_GRAF = string_make(path);
+
+ /* Validate the "graf" directory */
+ validate_dir(ANGBAND_DIR_XTRA_GRAF, TRUE);
+
+#endif /* USE_GRAPHICS */
+
+
+#ifdef USE_SOUND
+
+ /* Build the "sound" path */
+ path_build(path, sizeof(path), ANGBAND_DIR_XTRA, "sound");
+
+ /* Allocate the path */
+ ANGBAND_DIR_XTRA_SOUND = string_make(path);
+
+ /* Validate the "sound" directory */
+ validate_dir(ANGBAND_DIR_XTRA_SOUND, FALSE);
+
+#endif /* USE_SOUND */
+
+#ifdef USE_MUSIC
+
+ /* Build the "music" path */
+ path_build(path, sizeof(path), ANGBAND_DIR_XTRA, "music");
+
+ /* Allocate the path */
+ ANGBAND_DIR_XTRA_MUSIC = string_make(path);
+
+ /* Validate the "music" directory */
+ validate_dir(ANGBAND_DIR_XTRA_MUSIC, FALSE);
+
+#endif /* USE_MUSIC */
+
+ /* Build the "help" path */
+ path_build(path, sizeof(path), ANGBAND_DIR_XTRA, "help");
+
+ /* Allocate the path */
+ ANGBAND_DIR_XTRA_HELP = string_make(path);
+
+ /* Validate the "help" directory */
+ /* validate_dir(ANGBAND_DIR_XTRA_HELP); */
+}
+
+/*!
+ * @brief (Windows固有)変愚蛮怒が起動済かどうかのチェック
+ */
+static bool is_already_running(void)
+{
+ bool result = FALSE;
+ HANDLE hMutex;
+
+ hMutex = CreateMutex(NULL, TRUE, VERSION_NAME);
+ if (GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ result = TRUE;
+ }
+ return result;
+}
+
+
+/*!
+ * @brief (Windows固有)Windowsアプリケーションとしてのエントリポイント
+ */
+int FAR PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInst,
+ LPSTR lpCmdLine, int nCmdShow)
+{
+ int i;
+
+ WNDCLASS wc;
+ HDC hdc;
+ MSG msg;
+
+ setlocale(LC_ALL, "ja_JP.utf8");
+
+ /* Unused */
+ (void)nCmdShow;
+
+ /* Save globally */
+ hInstance = hInst;
+
+
+ /* Prevent multiple run */
+ if (is_already_running())
+ {
+ MessageBox(NULL,
+ _("変愚蛮怒はすでに起動しています。", "Hengband is already running."),
+ _("エラー!", "Error") ,
+ MB_ICONEXCLAMATION | MB_OK | MB_ICONSTOP);
+ return FALSE;
+ }
+
+ if (hPrevInst == NULL)
+ {
+ wc.style = CS_CLASSDC;
+ wc.lpfnWndProc = AngbandWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 4; /* one long pointer to term_data */
+ wc.hInstance = hInst;
+ wc.hIcon = hIcon = LoadIcon(hInst, AppName);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = GetStockObject(BLACK_BRUSH);
+ wc.lpszMenuName = AppName;
+ wc.lpszClassName = AppName;
+
+ if (!RegisterClass(&wc)) exit(1);
+
+ wc.lpfnWndProc = AngbandListProc;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = AngList;
+
+ if (!RegisterClass(&wc)) exit(2);
+
+#ifdef USE_SAVER
+
+ wc.style = CS_VREDRAW | CS_HREDRAW | CS_SAVEBITS | CS_DBLCLKS;
+ wc.lpfnWndProc = AngbandSaverProc;
+ wc.hCursor = NULL;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = "WindowsScreenSaverClass";
+
+ if (!RegisterClass(&wc)) exit(3);
+
+#endif
+
+ }
+
+ /* Temporary hooks */
+ plog_aux = hack_plog;
+ quit_aux = hack_quit;
+ core_aux = hack_quit;
+
+ /* Prepare the filepaths */
+ init_stuff();
+
+ /* Initialize the keypress analyzer */
+ for (i = 0; special_key_list[i]; ++i)
+ {
+ special_key[special_key_list[i]] = TRUE;
+ }
+ /* Initialize the keypress analyzer */
+ for (i = 0; ignore_key_list[i]; ++i)
+ {
+ ignore_key[ignore_key_list[i]] = TRUE;
+ }
+
+ /* Determine if display is 16/256/true color */
+ hdc = GetDC(NULL);
+ colors16 = (GetDeviceCaps(hdc, BITSPIXEL) == 4);
+ paletted = ((GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) ? TRUE : FALSE);
+ ReleaseDC(NULL, hdc);
+
+ /* Initialize the colors */
+ for (i = 0; i < 256; i++)
+ {
+ byte rv, gv, bv;
+
+ /* Extract desired values */
+ rv = angband_color_table[i][1];
+ gv = angband_color_table[i][2];
+ bv = angband_color_table[i][3];
+
+ /* Extract the "complex" code */
+ win_clr[i] = PALETTERGB(rv, gv, bv);
+
+ /* Save the "simple" code */
+ angband_color_table[i][0] = win_pal[i];
+ }
+
+ /* Prepare the windows */
+ init_windows();
+
+ /* bg */
+ init_bg();
+
+ /* Activate hooks */
+ plog_aux = hook_plog;
+ quit_aux = hook_quit;
+ core_aux = hook_quit;
+
+ /* Set the system suffix */
+ ANGBAND_SYS = "win";
+
+ /* Set the keyboard suffix */
+ if (7 != GetKeyboardType(0))
+ ANGBAND_KEYBOARD = "0";
+ else
+ {
+ /* Japanese keyboard */
+ switch (GetKeyboardType(1))
+ {
+ case 0x0D01: case 0x0D02:
+ case 0x0D03: case 0x0D04:
+ case 0x0D05: case 0x0D06:
+ /* NEC PC-98x1 */
+ ANGBAND_KEYBOARD = "NEC98";
+ break;
+ default:
+ /* PC/AT */
+ ANGBAND_KEYBOARD = "JAPAN";
+ }
+ }
+
+ /* Catch nasty signals */
+ signals_init();
+
+ Term_activate(term_screen);
+ init_angband();
+
+ /* We are now initialized */
+ initialized = TRUE;
+#ifdef CHUUKEI
+ if(lpCmdLine[0] == '-'){
+ switch(lpCmdLine[1])
+ {
+ case 'p':
+ case 'P':
+ {
+ if (!lpCmdLine[2]) break;
+ chuukei_server = TRUE;
+ if(connect_chuukei_server(&lpCmdLine[2])<0){
+ msg_print("connect fail");
+ return 0;
+ }
+ msg_print("connect");
+ msg_print(NULL);
+ break;
+ }
+
+ case 'c':
+ case 'C':
+ {
+ if (!lpCmdLine[2]) break;
+ chuukei_client = TRUE;
+ connect_chuukei_server(&lpCmdLine[2]);
+ play_game(FALSE);
+ quit(NULL);
+ return 0;
+ }
+ case 'X':
+ case 'x':
+ {
+ if (!lpCmdLine[2]) break;
+ prepare_browse_movie(&lpCmdLine[2]);
+ play_game(FALSE);
+ quit(NULL);
+ return 0;
+ }
+ }
+ }
+#endif
+
+#ifdef CHUUKEI
+ /* Did the user double click on a save file? */
+ if(!chuukei_server) check_for_save_file(lpCmdLine);
+#else
+ /* Did the user double click on a save file? */
+ check_for_save_file(lpCmdLine);
+#endif
+
+ /* Prompt the user */
+ prt(_("[ファイル] メニューの [新規] または [開く] を選択してください。", "[Choose 'New' or 'Open' from the 'File' menu]"), 23, _(8, 17));
+
+ Term_fresh();
+
+ /* Process messages forever */
+ while (GetMessage(&msg, NULL, 0, 0))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ /* Paranoia */
+ quit(NULL);
+
+ /* Paranoia */
+ return (0);
+}
+
+
+#endif /* WINDOWS */
+
-extern bool test_hit_norm(HIT_RELIABILITY chance, ARMOUR_CLASS ac, bool visible);\r
-extern PERCENTAGE hit_chance(HIT_RELIABILITY chance, ARMOUR_CLASS ac);\r
-extern HIT_POINT critical_norm(WEIGHT weight, int plus, HIT_POINT dam, s16b meichuu, BIT_FLAGS mode);\r
-extern bool py_attack(POSITION y, POSITION x, BIT_FLAGS mode);\r
-extern bool make_attack_normal(MONSTER_IDX m_idx);\r
-\r
+extern bool test_hit_norm(HIT_RELIABILITY chance, ARMOUR_CLASS ac, bool visible);
+extern PERCENTAGE hit_chance(HIT_RELIABILITY chance, ARMOUR_CLASS ac);
+extern HIT_POINT critical_norm(WEIGHT weight, int plus, HIT_POINT dam, s16b meichuu, BIT_FLAGS mode);
+extern bool py_attack(POSITION y, POSITION x, BIT_FLAGS mode);
+extern bool make_attack_normal(MONSTER_IDX m_idx);
+
-\r
-extern HIT_POINT mon_damage_mod(monster_type *m_ptr, HIT_POINT dam, bool is_psy_spear);\r
-extern bool mon_take_hit(MONSTER_IDX m_idx, HIT_POINT dam, bool *fear, concptr note);\r
-extern int get_mproc_idx(MONSTER_IDX m_idx, int mproc_type);\r
-\r
+
+extern HIT_POINT mon_damage_mod(monster_type *m_ptr, HIT_POINT dam, bool is_psy_spear);
+extern bool mon_take_hit(MONSTER_IDX m_idx, HIT_POINT dam, bool *fear, concptr note);
+extern int get_mproc_idx(MONSTER_IDX m_idx, int mproc_type);
+
-\r
-/*!\r
-* vaultに配置可能なモンスターの条件を指定するマクロ / Monster validation macro\r
-*\r
-* Line 1 -- forbid town monsters\r
-* Line 2 -- forbid uniques\r
-* Line 3 -- forbid aquatic monsters\r
-*/\r
-#define vault_monster_okay(I) \\r
- (mon_hook_dungeon(I) && \\r
- !(r_info[I].flags1 & RF1_UNIQUE) && \\r
- !(r_info[I].flags7 & RF7_UNIQUE2) && \\r
- !(r_info[I].flagsr & RFR_RES_ALL) && \\r
- !(r_info[I].flags7 & RF7_AQUATIC))\r
-\r
-extern int vault_aux_race;\r
-extern char vault_aux_char;\r
-extern BIT_FLAGS vault_aux_dragon_mask4;\r
-\r
-extern bool mon_hook_quest(MONRACE_IDX r_idx);\r
-extern bool mon_hook_dungeon(MONRACE_IDX r_idx);\r
-extern bool mon_hook_ocean(MONRACE_IDX r_idx);\r
-extern bool mon_hook_shore(MONRACE_IDX r_idx);\r
-extern bool mon_hook_waste(MONRACE_IDX r_idx);\r
-extern bool mon_hook_town(MONRACE_IDX r_idx);\r
-extern bool mon_hook_wood(MONRACE_IDX r_idx);\r
-extern bool mon_hook_volcano(MONRACE_IDX r_idx);\r
-extern bool mon_hook_wood(MONRACE_IDX r_idx);\r
-extern bool mon_hook_volcano(MONRACE_IDX r_idx);\r
-extern bool mon_hook_mountain(MONRACE_IDX r_idx);\r
-extern bool mon_hook_grass(MONRACE_IDX r_idx);\r
-extern bool mon_hook_deep_water(MONRACE_IDX r_idx);\r
-extern bool mon_hook_shallow_water(MONRACE_IDX r_idx);\r
-extern bool mon_hook_lava(MONRACE_IDX r_idx);\r
-extern bool mon_hook_floor(MONRACE_IDX r_idx);\r
-\r
-extern void vault_prep_clone(void);\r
-extern void vault_prep_dragon(void);\r
-extern void vault_prep_symbol(void);\r
-\r
-extern bool vault_aux_lite(MONRACE_IDX r_idx);\r
-extern bool vault_aux_shards(MONRACE_IDX r_idx);\r
-extern bool vault_aux_simple(MONRACE_IDX r_idx);\r
-extern bool vault_aux_jelly(MONRACE_IDX r_idx);\r
-extern bool vault_aux_animal(MONRACE_IDX r_idx);\r
-extern bool vault_aux_undead(MONRACE_IDX r_idx);\r
-extern bool vault_aux_chapel_g(MONRACE_IDX r_idx);\r
-extern bool vault_aux_kennel(MONRACE_IDX r_idx);\r
-extern bool vault_aux_mimic(MONRACE_IDX r_idx);\r
-extern bool vault_aux_clone(MONRACE_IDX r_idx);\r
-extern bool vault_aux_symbol_e(MONRACE_IDX r_idx);\r
-extern bool vault_aux_symbol_g(MONRACE_IDX r_idx);\r
-extern bool vault_aux_orc(MONRACE_IDX r_idx);\r
-extern bool vault_aux_troll(MONRACE_IDX r_idx);\r
-extern bool vault_aux_giant(MONRACE_IDX r_idx);\r
-extern bool vault_aux_dragon(MONRACE_IDX r_idx);\r
-extern bool vault_aux_demon(MONRACE_IDX r_idx);\r
-extern bool vault_aux_cthulhu(MONRACE_IDX r_idx);\r
-extern bool vault_aux_dark_elf(MONRACE_IDX r_idx);\r
-\r
-extern bool monster_living(MONRACE_IDX r_idx);\r
-extern bool no_questor_or_bounty_uniques(MONRACE_IDX r_idx);\r
-extern bool monster_hook_human(MONRACE_IDX r_idx);\r
-extern bool get_nightmare(MONRACE_IDX r_idx);\r
-extern bool monster_is_fishing_target(MONRACE_IDX r_idx);\r
-extern bool monster_can_entry_arena(MONRACE_IDX r_idx);\r
-\r
-\r
-\r
+
+/*!
+* vaultに配置可能なモンスターの条件を指定するマクロ / Monster validation macro
+*
+* Line 1 -- forbid town monsters
+* Line 2 -- forbid uniques
+* Line 3 -- forbid aquatic monsters
+*/
+#define vault_monster_okay(I) \
+ (mon_hook_dungeon(I) && \
+ !(r_info[I].flags1 & RF1_UNIQUE) && \
+ !(r_info[I].flags7 & RF7_UNIQUE2) && \
+ !(r_info[I].flagsr & RFR_RES_ALL) && \
+ !(r_info[I].flags7 & RF7_AQUATIC))
+
+extern int vault_aux_race;
+extern char vault_aux_char;
+extern BIT_FLAGS vault_aux_dragon_mask4;
+
+extern bool mon_hook_quest(MONRACE_IDX r_idx);
+extern bool mon_hook_dungeon(MONRACE_IDX r_idx);
+extern bool mon_hook_ocean(MONRACE_IDX r_idx);
+extern bool mon_hook_shore(MONRACE_IDX r_idx);
+extern bool mon_hook_waste(MONRACE_IDX r_idx);
+extern bool mon_hook_town(MONRACE_IDX r_idx);
+extern bool mon_hook_wood(MONRACE_IDX r_idx);
+extern bool mon_hook_volcano(MONRACE_IDX r_idx);
+extern bool mon_hook_wood(MONRACE_IDX r_idx);
+extern bool mon_hook_volcano(MONRACE_IDX r_idx);
+extern bool mon_hook_mountain(MONRACE_IDX r_idx);
+extern bool mon_hook_grass(MONRACE_IDX r_idx);
+extern bool mon_hook_deep_water(MONRACE_IDX r_idx);
+extern bool mon_hook_shallow_water(MONRACE_IDX r_idx);
+extern bool mon_hook_lava(MONRACE_IDX r_idx);
+extern bool mon_hook_floor(MONRACE_IDX r_idx);
+
+extern void vault_prep_clone(void);
+extern void vault_prep_dragon(void);
+extern void vault_prep_symbol(void);
+
+extern bool vault_aux_lite(MONRACE_IDX r_idx);
+extern bool vault_aux_shards(MONRACE_IDX r_idx);
+extern bool vault_aux_simple(MONRACE_IDX r_idx);
+extern bool vault_aux_jelly(MONRACE_IDX r_idx);
+extern bool vault_aux_animal(MONRACE_IDX r_idx);
+extern bool vault_aux_undead(MONRACE_IDX r_idx);
+extern bool vault_aux_chapel_g(MONRACE_IDX r_idx);
+extern bool vault_aux_kennel(MONRACE_IDX r_idx);
+extern bool vault_aux_mimic(MONRACE_IDX r_idx);
+extern bool vault_aux_clone(MONRACE_IDX r_idx);
+extern bool vault_aux_symbol_e(MONRACE_IDX r_idx);
+extern bool vault_aux_symbol_g(MONRACE_IDX r_idx);
+extern bool vault_aux_orc(MONRACE_IDX r_idx);
+extern bool vault_aux_troll(MONRACE_IDX r_idx);
+extern bool vault_aux_giant(MONRACE_IDX r_idx);
+extern bool vault_aux_dragon(MONRACE_IDX r_idx);
+extern bool vault_aux_demon(MONRACE_IDX r_idx);
+extern bool vault_aux_cthulhu(MONRACE_IDX r_idx);
+extern bool vault_aux_dark_elf(MONRACE_IDX r_idx);
+
+extern bool monster_living(MONRACE_IDX r_idx);
+extern bool no_questor_or_bounty_uniques(MONRACE_IDX r_idx);
+extern bool monster_hook_human(MONRACE_IDX r_idx);
+extern bool get_nightmare(MONRACE_IDX r_idx);
+extern bool monster_is_fishing_target(MONRACE_IDX r_idx);
+extern bool monster_can_entry_arena(MONRACE_IDX r_idx);
+
+
+
-#include "angband.h"\r
-\r
-/*!\r
- * @brief アイテムに付加される可能性のある呪いを指定する。\r
- * @param power 呪いの段階\r
- * @param o_ptr 呪いをかけられる装備オブジェクトの構造体参照ポインタ\r
- * @return 与える呪いのID\r
- */\r
-BIT_FLAGS get_curse(int power, object_type *o_ptr)\r
-{\r
- BIT_FLAGS new_curse;\r
-\r
- while(1)\r
- {\r
- new_curse = (1 << (randint0(MAX_CURSE)+4));\r
- if (power == 2)\r
- {\r
- if (!(new_curse & TRC_HEAVY_MASK)) continue;\r
- }\r
- else if (power == 1)\r
- {\r
- if (new_curse & TRC_SPECIAL_MASK) continue;\r
- }\r
- else if (power == 0)\r
- {\r
- if (new_curse & TRC_HEAVY_MASK) continue;\r
- }\r
- if (new_curse == TRC_LOW_MELEE && !object_is_weapon(o_ptr)) continue;\r
- if (new_curse == TRC_LOW_AC && !object_is_armour(o_ptr)) continue;\r
- break;\r
- }\r
- return new_curse;\r
-}\r
-\r
-/*!\r
- * @brief 装備への呪い付加判定と付加処理\r
- * @param chance 呪いの基本確率\r
- * @param heavy_chance さらに重い呪いとなる確率\r
- * @return なし\r
- */\r
-void curse_equipment(PERCENTAGE chance, PERCENTAGE heavy_chance)\r
-{\r
- bool changed = FALSE;\r
- int curse_power = 0;\r
- BIT_FLAGS new_curse;\r
- BIT_FLAGS oflgs[TR_FLAG_SIZE];\r
- object_type *o_ptr = &inventory[INVEN_RARM + randint0(12)];\r
- GAME_TEXT o_name[MAX_NLEN];\r
-\r
- if (randint1(100) > chance) return;\r
-\r
- if (!o_ptr->k_idx) return;\r
-\r
- object_flags(o_ptr, oflgs);\r
-\r
- object_desc(o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));\r
-\r
- /* Extra, biased saving throw for blessed items */\r
- if (have_flag(oflgs, TR_BLESSED))\r
- {\r
-#ifdef JP\r
- msg_format("祝福された%sは呪いを跳ね返した!", o_name,\r
-#else\r
- msg_format("Your blessed %s resist%s cursing!", o_name,\r
-#endif\r
-\r
- ((o_ptr->number > 1) ? "" : "s"));\r
- /* Hmmm -- can we wear multiple items? If not, this is unnecessary */\r
- return;\r
- }\r
-\r
- if ((randint1(100) <= heavy_chance) &&\r
- (object_is_artifact(o_ptr) || object_is_ego(o_ptr)))\r
- {\r
- if (!(o_ptr->curse_flags & TRC_HEAVY_CURSE))\r
- changed = TRUE;\r
- o_ptr->curse_flags |= TRC_HEAVY_CURSE;\r
- o_ptr->curse_flags |= TRC_CURSED;\r
- curse_power++;\r
- }\r
- else\r
- {\r
- if (!object_is_cursed(o_ptr))\r
- changed = TRUE;\r
- o_ptr->curse_flags |= TRC_CURSED;\r
- }\r
- if (heavy_chance >= 50) curse_power++;\r
-\r
- new_curse = get_curse(curse_power, o_ptr);\r
- if (!(o_ptr->curse_flags & new_curse))\r
- {\r
- changed = TRUE;\r
- o_ptr->curse_flags |= new_curse;\r
- }\r
-\r
- if (changed)\r
- {\r
- msg_format(_("悪意に満ちた黒いオーラが%sをとりまいた...", "There is a malignant black aura surrounding %s..."), o_name);\r
- o_ptr->feeling = FEEL_NONE;\r
- }\r
- p_ptr->update |= (PU_BONUS);\r
-}\r
-\r
+#include "angband.h"
+
+/*!
+ * @brief アイテムに付加される可能性のある呪いを指定する。
+ * @param power 呪いの段階
+ * @param o_ptr 呪いをかけられる装備オブジェクトの構造体参照ポインタ
+ * @return 与える呪いのID
+ */
+BIT_FLAGS get_curse(int power, object_type *o_ptr)
+{
+ BIT_FLAGS new_curse;
+
+ while(1)
+ {
+ new_curse = (1 << (randint0(MAX_CURSE)+4));
+ if (power == 2)
+ {
+ if (!(new_curse & TRC_HEAVY_MASK)) continue;
+ }
+ else if (power == 1)
+ {
+ if (new_curse & TRC_SPECIAL_MASK) continue;
+ }
+ else if (power == 0)
+ {
+ if (new_curse & TRC_HEAVY_MASK) continue;
+ }
+ if (new_curse == TRC_LOW_MELEE && !object_is_weapon(o_ptr)) continue;
+ if (new_curse == TRC_LOW_AC && !object_is_armour(o_ptr)) continue;
+ break;
+ }
+ return new_curse;
+}
+
+/*!
+ * @brief 装備への呪い付加判定と付加処理
+ * @param chance 呪いの基本確率
+ * @param heavy_chance さらに重い呪いとなる確率
+ * @return なし
+ */
+void curse_equipment(PERCENTAGE chance, PERCENTAGE heavy_chance)
+{
+ bool changed = FALSE;
+ int curse_power = 0;
+ BIT_FLAGS new_curse;
+ BIT_FLAGS oflgs[TR_FLAG_SIZE];
+ object_type *o_ptr = &inventory[INVEN_RARM + randint0(12)];
+ GAME_TEXT o_name[MAX_NLEN];
+
+ if (randint1(100) > chance) return;
+
+ if (!o_ptr->k_idx) return;
+
+ object_flags(o_ptr, oflgs);
+
+ object_desc(o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
+
+ /* Extra, biased saving throw for blessed items */
+ if (have_flag(oflgs, TR_BLESSED))
+ {
+#ifdef JP
+ msg_format("祝福された%sは呪いを跳ね返した!", o_name,
+#else
+ msg_format("Your blessed %s resist%s cursing!", o_name,
+#endif
+
+ ((o_ptr->number > 1) ? "" : "s"));
+ /* Hmmm -- can we wear multiple items? If not, this is unnecessary */
+ return;
+ }
+
+ if ((randint1(100) <= heavy_chance) &&
+ (object_is_artifact(o_ptr) || object_is_ego(o_ptr)))
+ {
+ if (!(o_ptr->curse_flags & TRC_HEAVY_CURSE))
+ changed = TRUE;
+ o_ptr->curse_flags |= TRC_HEAVY_CURSE;
+ o_ptr->curse_flags |= TRC_CURSED;
+ curse_power++;
+ }
+ else
+ {
+ if (!object_is_cursed(o_ptr))
+ changed = TRUE;
+ o_ptr->curse_flags |= TRC_CURSED;
+ }
+ if (heavy_chance >= 50) curse_power++;
+
+ new_curse = get_curse(curse_power, o_ptr);
+ if (!(o_ptr->curse_flags & new_curse))
+ {
+ changed = TRUE;
+ o_ptr->curse_flags |= new_curse;
+ }
+
+ if (changed)
+ {
+ msg_format(_("悪意に満ちた黒いオーラが%sをとりまいた...", "There is a malignant black aura surrounding %s..."), o_name);
+ o_ptr->feeling = FEEL_NONE;
+ }
+ p_ptr->update |= (PU_BONUS);
+}
+
-extern BIT_FLAGS get_curse(int power, object_type *o_ptr);\r
-extern void curse_equipment(PERCENTAGE chance, PERCENTAGE heavy_chance);\r
+extern BIT_FLAGS get_curse(int power, object_type *o_ptr);
+extern void curse_equipment(PERCENTAGE chance, PERCENTAGE heavy_chance);
-\r
-extern bool item_tester_hook_convertible(object_type *o_ptr);\r
-extern bool item_tester_hook_recharge(object_type *o_ptr);\r
-extern bool item_tester_hook_orthodox_melee_weapons(object_type *o_ptr);\r
-extern bool item_tester_hook_melee_weapon(object_type *o_ptr);\r
-extern bool item_tester_hook_ammo(object_type *o_ptr);\r
-extern bool item_tester_hook_broken_weapon(object_type *o_ptr);\r
-extern bool item_tester_hook_boomerang(object_type *o_ptr);\r
-extern bool item_tester_hook_eatable(object_type *o_ptr);\r
-extern bool item_tester_hook_mochikae(object_type *o_ptr);\r
-extern bool item_tester_hook_activate(object_type *o_ptr);\r
-extern bool item_tester_hook_wear(object_type *o_ptr);\r
-extern bool item_tester_hook_use(object_type *o_ptr);\r
-extern bool item_tester_hook_quaff(object_type *o_ptr);\r
-extern bool item_tester_hook_readable(object_type *o_ptr);\r
-extern bool item_tester_hook_melee_ammo(object_type *o_ptr);\r
-extern bool item_tester_hook_weapon_except_bow(object_type *o_ptr);\r
-extern bool item_tester_hook_cursed(object_type *o_ptr);\r
-extern bool item_tester_hook_nameless_weapon_armour(object_type *o_ptr);\r
-extern bool item_tester_hook_identify(object_type *o_ptr);\r
-extern bool item_tester_hook_identify_weapon_armour(object_type *o_ptr);\r
-extern bool item_tester_hook_identify_fully(object_type *o_ptr);\r
-extern bool item_tester_hook_identify_fully_weapon_armour(object_type *o_ptr);\r
-extern bool item_tester_hook_recharge(object_type *o_ptr);\r
-\r
-extern bool item_tester_learn_spell(object_type *o_ptr);\r
-extern bool item_tester_high_level_book(object_type *o_ptr);\r
-extern bool item_tester_refill_lantern(object_type *o_ptr);\r
+
+extern bool item_tester_hook_convertible(object_type *o_ptr);
+extern bool item_tester_hook_recharge(object_type *o_ptr);
+extern bool item_tester_hook_orthodox_melee_weapons(object_type *o_ptr);
+extern bool item_tester_hook_melee_weapon(object_type *o_ptr);
+extern bool item_tester_hook_ammo(object_type *o_ptr);
+extern bool item_tester_hook_broken_weapon(object_type *o_ptr);
+extern bool item_tester_hook_boomerang(object_type *o_ptr);
+extern bool item_tester_hook_eatable(object_type *o_ptr);
+extern bool item_tester_hook_mochikae(object_type *o_ptr);
+extern bool item_tester_hook_activate(object_type *o_ptr);
+extern bool item_tester_hook_wear(object_type *o_ptr);
+extern bool item_tester_hook_use(object_type *o_ptr);
+extern bool item_tester_hook_quaff(object_type *o_ptr);
+extern bool item_tester_hook_readable(object_type *o_ptr);
+extern bool item_tester_hook_melee_ammo(object_type *o_ptr);
+extern bool item_tester_hook_weapon_except_bow(object_type *o_ptr);
+extern bool item_tester_hook_cursed(object_type *o_ptr);
+extern bool item_tester_hook_nameless_weapon_armour(object_type *o_ptr);
+extern bool item_tester_hook_identify(object_type *o_ptr);
+extern bool item_tester_hook_identify_weapon_armour(object_type *o_ptr);
+extern bool item_tester_hook_identify_fully(object_type *o_ptr);
+extern bool item_tester_hook_identify_fully_weapon_armour(object_type *o_ptr);
+extern bool item_tester_hook_recharge(object_type *o_ptr);
+
+extern bool item_tester_learn_spell(object_type *o_ptr);
+extern bool item_tester_high_level_book(object_type *o_ptr);
+extern bool item_tester_refill_lantern(object_type *o_ptr);
-\r
-bool kind_is_cloak(KIND_OBJECT_IDX k_idx);\r
-bool kind_is_polearm(KIND_OBJECT_IDX k_idx);\r
-bool kind_is_sword(KIND_OBJECT_IDX k_idx);\r
-bool kind_is_book(KIND_OBJECT_IDX k_idx);\r
-bool kind_is_good_book(KIND_OBJECT_IDX k_idx);\r
-bool kind_is_armor(KIND_OBJECT_IDX k_idx);\r
-bool kind_is_hafted(KIND_OBJECT_IDX k_idx);\r
-bool kind_is_potion(KIND_OBJECT_IDX k_idx);\r
-\r
-\r
-\r
+
+bool kind_is_cloak(KIND_OBJECT_IDX k_idx);
+bool kind_is_polearm(KIND_OBJECT_IDX k_idx);
+bool kind_is_sword(KIND_OBJECT_IDX k_idx);
+bool kind_is_book(KIND_OBJECT_IDX k_idx);
+bool kind_is_good_book(KIND_OBJECT_IDX k_idx);
+bool kind_is_armor(KIND_OBJECT_IDX k_idx);
+bool kind_is_hafted(KIND_OBJECT_IDX k_idx);
+bool kind_is_potion(KIND_OBJECT_IDX k_idx);
+
+
+
-\r
-extern bool hates_acid(object_type *o_ptr);\r
-extern bool hates_elec(object_type *o_ptr);\r
-extern bool hates_fire(object_type *o_ptr);\r
-extern bool hates_cold(object_type *o_ptr);\r
-extern int set_acid_destroy(object_type *o_ptr);\r
-extern int set_elec_destroy(object_type *o_ptr);\r
-extern int set_fire_destroy(object_type *o_ptr);\r
-extern int set_cold_destroy(object_type *o_ptr);\r
-extern int inven_damage(inven_func typ, int perc);\r
-extern HIT_POINT acid_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura);\r
-extern HIT_POINT elec_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura);\r
-extern HIT_POINT fire_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura);\r
-extern HIT_POINT cold_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura);\r
+
+extern bool hates_acid(object_type *o_ptr);
+extern bool hates_elec(object_type *o_ptr);
+extern bool hates_fire(object_type *o_ptr);
+extern bool hates_cold(object_type *o_ptr);
+extern int set_acid_destroy(object_type *o_ptr);
+extern int set_elec_destroy(object_type *o_ptr);
+extern int set_fire_destroy(object_type *o_ptr);
+extern int set_cold_destroy(object_type *o_ptr);
+extern int inven_damage(inven_func typ, int perc);
+extern HIT_POINT acid_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura);
+extern HIT_POINT elec_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura);
+extern HIT_POINT fire_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura);
+extern HIT_POINT cold_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura);
-extern concptr do_arcane_spell(SPELL_IDX spell, BIT_FLAGS mode);\r
+extern concptr do_arcane_spell(SPELL_IDX spell, BIT_FLAGS mode);
-extern concptr do_chaos_spell(SPELL_IDX spell, BIT_FLAGS mode);\r
+extern concptr do_chaos_spell(SPELL_IDX spell, BIT_FLAGS mode);
-concptr do_craft_spell(SPELL_IDX spell, BIT_FLAGS mode);\r
+concptr do_craft_spell(SPELL_IDX spell, BIT_FLAGS mode);
-extern concptr do_crusade_spell(SPELL_IDX spell, BIT_FLAGS mode);\r
+extern concptr do_crusade_spell(SPELL_IDX spell, BIT_FLAGS mode);
-extern concptr do_daemon_spell(SPELL_IDX spell, BIT_FLAGS mode);\r
-\r
+extern concptr do_daemon_spell(SPELL_IDX spell, BIT_FLAGS mode);
+
-extern concptr do_death_spell(SPELL_IDX spell, BIT_FLAGS mode);\r
+extern concptr do_death_spell(SPELL_IDX spell, BIT_FLAGS mode);
-/*!\r
- * @file realm-hex.h\r
- */\r
-\r
-extern bool stop_hex_spell_all(void);\r
-extern bool stop_hex_spell(void);\r
-extern void check_hex(void);\r
-extern bool hex_spell_fully(void);\r
-extern void revenge_spell(void);\r
-extern void revenge_store(HIT_POINT dam);\r
-extern bool teleport_barrier(MONSTER_IDX m_idx);\r
-extern bool magic_barrier(MONSTER_IDX m_idx);\r
-extern bool multiply_barrier(MONSTER_IDX m_idx);\r
-extern concptr do_hex_spell(SPELL_IDX spell, BIT_FLAGS mode);\r
+/*!
+ * @file realm-hex.h
+ */
+
+extern bool stop_hex_spell_all(void);
+extern bool stop_hex_spell(void);
+extern void check_hex(void);
+extern bool hex_spell_fully(void);
+extern void revenge_spell(void);
+extern void revenge_store(HIT_POINT dam);
+extern bool teleport_barrier(MONSTER_IDX m_idx);
+extern bool magic_barrier(MONSTER_IDX m_idx);
+extern bool multiply_barrier(MONSTER_IDX m_idx);
+extern concptr do_hex_spell(SPELL_IDX spell, BIT_FLAGS mode);
-extern concptr do_hissatsu_spell(SPELL_IDX spell, BIT_FLAGS mode);\r
+extern concptr do_hissatsu_spell(SPELL_IDX spell, BIT_FLAGS mode);
-extern concptr do_life_spell(SPELL_IDX spell, BIT_FLAGS mode);\r
+extern concptr do_life_spell(SPELL_IDX spell, BIT_FLAGS mode);
-#include "angband.h"\r
-#include "cmd-spell.h"\r
-#include "projection.h"\r
-#include "spells-summon.h"\r
-#include "spells-status.h"\r
-#include "avatar.h"\r
-\r
-\r
-/*!\r
-* @brief 自然領域魔法の各処理を行う\r
-* @param spell 魔法ID\r
-* @param mode 処理内容 (SPELL_NAME / SPELL_DESC / SPELL_INFO / SPELL_CAST)\r
-* @return SPELL_NAME / SPELL_DESC / SPELL_INFO 時には文字列ポインタを返す。SPELL_CAST時はNULL文字列を返す。\r
-*/\r
-concptr do_nature_spell(SPELL_IDX spell, BIT_FLAGS mode)\r
-{\r
- bool name = (mode == SPELL_NAME) ? TRUE : FALSE;\r
- bool desc = (mode == SPELL_DESC) ? TRUE : FALSE;\r
- bool info = (mode == SPELL_INFO) ? TRUE : FALSE;\r
- bool cast = (mode == SPELL_CAST) ? TRUE : FALSE;\r
-\r
- DIRECTION dir;\r
- PLAYER_LEVEL plev = p_ptr->lev;\r
-\r
- switch (spell)\r
- {\r
- case 0:\r
- if (name) return _("モンスター感知", "Detect Creatures");\r
- if (desc) return _("近くの全ての見えるモンスターを感知する。", "Detects all monsters in your vicinity unless invisible.");\r
-\r
- {\r
- POSITION rad = DETECT_RAD_DEFAULT;\r
-\r
- if (info) return info_radius(rad);\r
-\r
- if (cast)\r
- {\r
- detect_monsters_normal(rad);\r
- }\r
- }\r
- break;\r
-\r
- case 1:\r
- if (name) return _("稲妻", "Lightning");\r
- if (desc) return _("電撃の短いビームを放つ。", "Fires a short beam of lightning.");\r
-\r
- {\r
- DICE_NUMBER dice = 3 + (plev - 1) / 5;\r
- DICE_SID sides = 4;\r
- POSITION range = plev / 6 + 2;\r
-\r
- if (info) return format("%s%dd%d %s%d", KWD_DAM, dice, sides, KWD_RANGE, range);\r
-\r
- if (cast)\r
- {\r
- project_length = range;\r
-\r
- if (!get_aim_dir(&dir)) return NULL;\r
-\r
- fire_beam(GF_ELEC, dir, damroll(dice, sides));\r
- }\r
- }\r
- break;\r
-\r
- case 2:\r
- if (name) return _("罠と扉感知", "Detect Doors and Traps");\r
- if (desc) return _("近くの全ての罠と扉を感知する。", "Detects traps, doors, and stairs in your vicinity.");\r
-\r
- {\r
- POSITION rad = DETECT_RAD_DEFAULT;\r
-\r
- if (info) return info_radius(rad);\r
-\r
- if (cast)\r
- {\r
- detect_traps(rad, TRUE);\r
- detect_doors(rad);\r
- detect_stairs(rad);\r
- }\r
- }\r
- break;\r
-\r
- case 3:\r
- if (name) return _("食糧生成", "Produce Food");\r
- if (desc) return _("食料を一つ作り出す。", "Produces a Ration of Food.");\r
-\r
- {\r
- if (cast)\r
- {\r
- object_type forge, *q_ptr = &forge;\r
- msg_print(_("食料を生成した。", "A food ration is produced."));\r
-\r
- /* Create the food ration */\r
- object_prep(q_ptr, lookup_kind(TV_FOOD, SV_FOOD_RATION));\r
-\r
- /* Drop the object from heaven */\r
- (void)drop_near(q_ptr, -1, p_ptr->y, p_ptr->x);\r
- }\r
- }\r
- break;\r
-\r
- case 4:\r
- if (name) return _("日の光", "Daylight");\r
- if (desc) return _("光源が照らしている範囲か部屋全体を永久に明るくする。", "Lights up nearby area and the inside of a room permanently.");\r
-\r
- {\r
- DICE_NUMBER dice = 2;\r
- DICE_SID sides = plev / 2;\r
- POSITION rad = (plev / 10) + 1;\r
-\r
- if (info) return info_damage(dice, sides, 0);\r
-\r
- if (cast)\r
- {\r
- lite_area(damroll(dice, sides), rad);\r
-\r
- if ((prace_is_(RACE_VAMPIRE) || (p_ptr->mimic_form == MIMIC_VAMPIRE)) && !p_ptr->resist_lite)\r
- {\r
- msg_print(_("日の光があなたの肉体を焦がした!", "The daylight scorches your flesh!"));\r
- take_hit(DAMAGE_NOESCAPE, damroll(2, 2), _("日の光", "daylight"), -1);\r
- }\r
- }\r
- }\r
- break;\r
-\r
- case 5:\r
- if (name) return _("動物習し", "Animal Taming");\r
- if (desc) return _("動物1体を魅了する。抵抗されると無効。", "Attempts to charm an animal.");\r
-\r
- {\r
- int power = plev;\r
-\r
- if (info) return info_power(power);\r
-\r
- if (cast)\r
- {\r
- if (!get_aim_dir(&dir)) return NULL;\r
-\r
- charm_animal(dir, plev);\r
- }\r
- }\r
- break;\r
-\r
- case 6:\r
- if (name) return _("環境への耐性", "Resist Environment");\r
- if (desc) return _("一定時間、冷気、炎、電撃に対する耐性を得る。装備による耐性に累積する。",\r
- "Gives resistance to fire, cold and electricity for a while. These resistances can be added to which from equipment for more powerful resistances.");\r
-\r
- {\r
- int base = 20;\r
-\r
- if (info) return info_duration(base, base);\r
-\r
- if (cast)\r
- {\r
- set_oppose_cold(randint1(base) + base, FALSE);\r
- set_oppose_fire(randint1(base) + base, FALSE);\r
- set_oppose_elec(randint1(base) + base, FALSE);\r
- }\r
- }\r
- break;\r
-\r
- case 7:\r
- if (name) return _("傷と毒治療", "Cure Wounds & Poison");\r
- if (desc) return _("怪我を全快させ、毒を体から完全に取り除き、体力を少し回復させる。", "Heals all cut and poison status. Heals HP a little.");\r
-\r
- {\r
- DICE_NUMBER dice = 2;\r
- DICE_SID sides = 8;\r
-\r
- if (info) return info_heal(dice, sides, 0);\r
-\r
- if (cast)\r
- {\r
- hp_player(damroll(dice, sides));\r
- set_cut(0);\r
- set_poisoned(0);\r
- }\r
- }\r
- break;\r
-\r
- case 8:\r
- if (name) return _("岩石溶解", "Stone to Mud");\r
- if (desc) return _("壁を溶かして床にする。", "Turns one rock square to mud.");\r
-\r
- {\r
- DICE_NUMBER dice = 1;\r
- DICE_SID sides = 30;\r
- int base = 20;\r
-\r
- if (info) return info_damage(dice, sides, base);\r
-\r
- if (cast)\r
- {\r
- if (!get_aim_dir(&dir)) return NULL;\r
-\r
- wall_to_mud(dir, 20 + randint1(30));\r
- }\r
- }\r
- break;\r
-\r
- case 9:\r
- if (name) return _("アイス・ボルト", "Frost Bolt");\r
- if (desc) return _("冷気のボルトもしくはビームを放つ。", "Fires a bolt or beam of cold.");\r
-\r
- {\r
- DICE_NUMBER dice = 3 + (plev - 5) / 4;\r
- DICE_SID sides = 8;\r
-\r
- if (info) return info_damage(dice, sides, 0);\r
-\r
- if (cast)\r
- {\r
- if (!get_aim_dir(&dir)) return NULL;\r
- fire_bolt_or_beam(beam_chance() - 10, GF_COLD, dir, damroll(dice, sides));\r
- }\r
- }\r
- break;\r
-\r
- case 10:\r
- if (name) return _("自然の覚醒", "Nature Awareness");\r
- if (desc) return _("周辺の地形を感知し、近くの罠、扉、階段、全てのモンスターを感知する。",\r
- "Maps nearby area. Detects all monsters, traps, doors and stairs.");\r
-\r
- {\r
- int rad1 = DETECT_RAD_MAP;\r
- int rad2 = DETECT_RAD_DEFAULT;\r
-\r
- if (info) return info_radius(MAX(rad1, rad2));\r
-\r
- if (cast)\r
- {\r
- map_area(rad1);\r
- detect_traps(rad2, TRUE);\r
- detect_doors(rad2);\r
- detect_stairs(rad2);\r
- detect_monsters_normal(rad2);\r
- }\r
- }\r
- break;\r
-\r
- case 11:\r
- if (name) return _("ファイア・ボルト", "Fire Bolt");\r
- if (desc) return _("火炎のボルトもしくはビームを放つ。", "Fires a bolt or beam of fire.");\r
-\r
- {\r
- DICE_NUMBER dice = 5 + (plev - 5) / 4;\r
- DICE_SID sides = 8;\r
-\r
- if (info) return info_damage(dice, sides, 0);\r
-\r
- if (cast)\r
- {\r
- if (!get_aim_dir(&dir)) return NULL;\r
- fire_bolt_or_beam(beam_chance() - 10, GF_FIRE, dir, damroll(dice, sides));\r
- }\r
- }\r
- break;\r
-\r
- case 12:\r
- if (name) return _("太陽光線", "Ray of Sunlight");\r
- if (desc) return _("光線を放つ。光りを嫌うモンスターに効果がある。", "Fires a beam of light which damages to light-sensitive monsters.");\r
-\r
- {\r
- DICE_NUMBER dice = 6;\r
- DICE_SID sides = 8;\r
-\r
- if (info) return info_damage(dice, sides, 0);\r
-\r
- if (cast)\r
- {\r
- if (!get_aim_dir(&dir)) return NULL;\r
- msg_print(_("太陽光線が現れた。", "A line of sunlight appears."));\r
- lite_line(dir, damroll(6, 8));\r
- }\r
- }\r
- break;\r
-\r
- case 13:\r
- if (name) return _("足かせ", "Entangle");\r
- if (desc) return _("視界内の全てのモンスターを減速させる。抵抗されると無効。", "Attempts to slow all monsters in sight.");\r
- {\r
- int power = plev;\r
- if (info) return info_power(power);\r
- if (cast) slow_monsters(plev);\r
- }\r
- break;\r
-\r
- case 14:\r
- if (name) return _("動物召喚", "Summon Animal");\r
- if (desc) return _("動物を1体召喚する。", "Summons an animal.");\r
-\r
- {\r
- if (cast)\r
- {\r
- if (!(summon_specific(-1, p_ptr->y, p_ptr->x, plev, SUMMON_ANIMAL_RANGER, (PM_ALLOW_GROUP | PM_FORCE_PET), '\0')))\r
- {\r
- msg_print(_("動物は現れなかった。", "No animals arrive."));\r
- }\r
- break;\r
- }\r
- }\r
- break;\r
-\r
- case 15:\r
- if (name) return _("薬草治療", "Herbal Healing");\r
- if (desc) return _("体力を大幅に回復させ、負傷、朦朧状態、毒から全快する。", "Heals HP greatly. And heals cut, stun and poison completely.");\r
- {\r
- int heal = 500;\r
- if (info) return info_heal(0, 0, heal);\r
- if (cast) (void)cure_critical_wounds(heal);\r
- }\r
- break;\r
-\r
- case 16:\r
- if (name) return _("階段生成", "Stair Building");\r
- if (desc) return _("自分のいる位置に階段を作る。", "Creates a stair which goes down or up.");\r
-\r
- {\r
- if (cast)\r
- {\r
- stair_creation();\r
- }\r
- }\r
- break;\r
-\r
- case 17:\r
- if (name) return _("肌石化", "Stone Skin");\r
- if (desc) return _("一定時間、ACを上昇させる。", "Gives bonus to AC for a while.");\r
-\r
- {\r
- int base = 20;\r
- DICE_SID sides = 30;\r
-\r
- if (info) return info_duration(base, sides);\r
-\r
- if (cast)\r
- {\r
- set_shield(randint1(sides) + base, FALSE);\r
- }\r
- }\r
- break;\r
-\r
- case 18:\r
- if (name) return _("真・耐性", "Resistance True");\r
- if (desc) return _("一定時間、酸、電撃、炎、冷気、毒に対する耐性を得る。装備による耐性に累積する。",\r
- "Gives resistance to fire, cold, electricity, acid and poison for a while. These resistances can be added to which from equipment for more powerful resistances.");\r
-\r
- {\r
- int base = 20;\r
-\r
- if (info) return info_duration(base, base);\r
-\r
- if (cast)\r
- {\r
- set_oppose_acid(randint1(base) + base, FALSE);\r
- set_oppose_elec(randint1(base) + base, FALSE);\r
- set_oppose_fire(randint1(base) + base, FALSE);\r
- set_oppose_cold(randint1(base) + base, FALSE);\r
- set_oppose_pois(randint1(base) + base, FALSE);\r
- }\r
- }\r
- break;\r
-\r
- case 19:\r
- if (name) return _("森林創造", "Forest Creation");\r
- if (desc) return _("周囲に木を作り出す。", "Creates trees in all adjacent squares.");\r
-\r
- {\r
- if (cast)\r
- {\r
- tree_creation();\r
- }\r
- }\r
- break;\r
-\r
- case 20:\r
- if (name) return _("動物友和", "Animal Friendship");\r
- if (desc) return _("視界内の全ての動物を魅了する。抵抗されると無効。", "Attempts to charm all animals in sight.");\r
-\r
- {\r
- int power = plev * 2;\r
- if (info) return info_power(power);\r
- if (cast) charm_animals(power);\r
- }\r
- break;\r
-\r
- case 21:\r
- if (name) return _("試金石", "Stone Tell");\r
- if (desc) return _("アイテムの持つ能力を完全に知る。", "*Identifies* an item.");\r
-\r
- {\r
- if (cast)\r
- {\r
- if (!identify_fully(FALSE)) return NULL;\r
- }\r
- }\r
- break;\r
-\r
- case 22:\r
- if (name) return _("石の壁", "Wall of Stone");\r
- if (desc) return _("自分の周囲に花崗岩の壁を作る。", "Creates granite walls in all adjacent squares.");\r
-\r
- {\r
- if (cast)\r
- {\r
- wall_stone();\r
- }\r
- }\r
- break;\r
-\r
- case 23:\r
- if (name) return _("腐食防止", "Protect from Corrosion");\r
- if (desc) return _("アイテムを酸で傷つかないよう加工する。", "Makes an equipment acid-proof.");\r
-\r
- {\r
- if (cast)\r
- {\r
- if (!rustproof()) return NULL;\r
- }\r
- }\r
- break;\r
-\r
- case 24:\r
- if (name) return _("地震", "Earthquake");\r
- if (desc) return _("周囲のダンジョンを揺らし、壁と床をランダムに入れ変える。",\r
- "Shakes dungeon structure, and results in random swapping of floors and walls.");\r
-\r
- {\r
- POSITION rad = 10;\r
-\r
- if (info) return info_radius(rad);\r
-\r
- if (cast)\r
- {\r
- earthquake(p_ptr->y, p_ptr->x, rad);\r
- }\r
- }\r
- break;\r
-\r
- case 25:\r
- if (name) return _("カマイタチ", "Whirlwind");\r
- if (desc) return _("全方向に向かって攻撃する。", "Attacks all adjacent monsters.");\r
- if (cast) massacre();\r
- break;\r
-\r
- case 26:\r
- if (name) return _("ブリザード", "Blizzard");\r
- if (desc) return _("巨大な冷気の球を放つ。", "Fires a huge ball of cold.");\r
-\r
- {\r
- HIT_POINT dam = 70 + plev * 3 / 2;\r
- POSITION rad = plev / 12 + 1;\r
-\r
- if (info) return info_damage(0, 0, dam);\r
-\r
- if (cast)\r
- {\r
- if (!get_aim_dir(&dir)) return NULL;\r
-\r
- fire_ball(GF_COLD, dir, dam, rad);\r
- }\r
- }\r
- break;\r
-\r
- case 27:\r
- if (name) return _("稲妻嵐", "Lightning Storm");\r
- if (desc) return _("巨大な電撃の球を放つ。", "Fires a huge electric ball.");\r
-\r
- {\r
- HIT_POINT dam = 90 + plev * 3 / 2;\r
- POSITION rad = plev / 12 + 1;\r
-\r
- if (info) return info_damage(0, 0, dam);\r
-\r
- if (cast)\r
- {\r
- if (!get_aim_dir(&dir)) return NULL;\r
- fire_ball(GF_ELEC, dir, dam, rad);\r
- break;\r
- }\r
- }\r
- break;\r
-\r
- case 28:\r
- if (name) return _("渦潮", "Whirlpool");\r
- if (desc) return _("巨大な水の球を放つ。", "Fires a huge ball of water.");\r
-\r
- {\r
- HIT_POINT dam = 100 + plev * 3 / 2;\r
- POSITION rad = plev / 12 + 1;\r
-\r
- if (info) return info_damage(0, 0, dam);\r
-\r
- if (cast)\r
- {\r
- if (!get_aim_dir(&dir)) return NULL;\r
- fire_ball(GF_WATER, dir, dam, rad);\r
- }\r
- }\r
- break;\r
-\r
- case 29:\r
- if (name) return _("陽光召喚", "Call Sunlight");\r
- if (desc) return _("自分を中心とした光の球を発生させる。さらに、その階全体を永久に照らし、ダンジョン内すべてのアイテムを感知する。",\r
- "Generates ball of light centered on you. Maps and lights whole dungeon level. Knows all objects location.");\r
-\r
- {\r
- HIT_POINT dam = 150;\r
- POSITION rad = 8;\r
-\r
- if (info) return info_damage(0, 0, dam / 2);\r
-\r
- if (cast)\r
- {\r
- fire_ball(GF_LITE, 0, dam, rad);\r
- chg_virtue(V_KNOWLEDGE, 1);\r
- chg_virtue(V_ENLIGHTEN, 1);\r
- wiz_lite(FALSE);\r
-\r
- if ((prace_is_(RACE_VAMPIRE) || (p_ptr->mimic_form == MIMIC_VAMPIRE)) && !p_ptr->resist_lite)\r
- {\r
- msg_print(_("日光があなたの肉体を焦がした!", "The sunlight scorches your flesh!"));\r
- take_hit(DAMAGE_NOESCAPE, 50, _("日光", "sunlight"), -1);\r
- }\r
- }\r
- }\r
- break;\r
-\r
- case 30:\r
- if (name) return _("精霊の刃", "Elemental Branding");\r
- if (desc) return _("武器に炎か冷気の属性をつける。", "Makes current weapon fire or frost branded.");\r
-\r
- {\r
- if (cast)\r
- {\r
- brand_weapon(randint0(2));\r
- }\r
- }\r
- break;\r
-\r
- case 31:\r
- if (name) return _("自然の脅威", "Nature's Wrath");\r
- if (desc) return _("近くの全てのモンスターにダメージを与え、地震を起こし、自分を中心とした分解の球を発生させる。",\r
- "Damages all monsters in sight. Makes quake. Generates disintegration ball centered on you.");\r
-\r
- {\r
- int d_dam = 4 * plev;\r
- int b_dam = (100 + plev) * 2;\r
- POSITION b_rad = 1 + plev / 12;\r
- POSITION q_rad = 20 + plev / 2;\r
-\r
- if (info) return format("%s%d+%d", KWD_DAM, d_dam, b_dam / 2);\r
-\r
- if (cast)\r
- {\r
- dispel_monsters(d_dam);\r
- earthquake(p_ptr->y, p_ptr->x, q_rad);\r
- project(0, b_rad, p_ptr->y, p_ptr->x, b_dam, GF_DISINTEGRATE, PROJECT_KILL | PROJECT_ITEM, -1);\r
- }\r
- }\r
- break;\r
- }\r
-\r
- return "";\r
-}\r
-\r
+#include "angband.h"
+#include "cmd-spell.h"
+#include "projection.h"
+#include "spells-summon.h"
+#include "spells-status.h"
+#include "avatar.h"
+
+
+/*!
+* @brief 自然領域魔法の各処理を行う
+* @param spell 魔法ID
+* @param mode 処理内容 (SPELL_NAME / SPELL_DESC / SPELL_INFO / SPELL_CAST)
+* @return SPELL_NAME / SPELL_DESC / SPELL_INFO 時には文字列ポインタを返す。SPELL_CAST時はNULL文字列を返す。
+*/
+concptr do_nature_spell(SPELL_IDX spell, BIT_FLAGS mode)
+{
+ bool name = (mode == SPELL_NAME) ? TRUE : FALSE;
+ bool desc = (mode == SPELL_DESC) ? TRUE : FALSE;
+ bool info = (mode == SPELL_INFO) ? TRUE : FALSE;
+ bool cast = (mode == SPELL_CAST) ? TRUE : FALSE;
+
+ DIRECTION dir;
+ PLAYER_LEVEL plev = p_ptr->lev;
+
+ switch (spell)
+ {
+ case 0:
+ if (name) return _("モンスター感知", "Detect Creatures");
+ if (desc) return _("近くの全ての見えるモンスターを感知する。", "Detects all monsters in your vicinity unless invisible.");
+
+ {
+ POSITION rad = DETECT_RAD_DEFAULT;
+
+ if (info) return info_radius(rad);
+
+ if (cast)
+ {
+ detect_monsters_normal(rad);
+ }
+ }
+ break;
+
+ case 1:
+ if (name) return _("稲妻", "Lightning");
+ if (desc) return _("電撃の短いビームを放つ。", "Fires a short beam of lightning.");
+
+ {
+ DICE_NUMBER dice = 3 + (plev - 1) / 5;
+ DICE_SID sides = 4;
+ POSITION range = plev / 6 + 2;
+
+ if (info) return format("%s%dd%d %s%d", KWD_DAM, dice, sides, KWD_RANGE, range);
+
+ if (cast)
+ {
+ project_length = range;
+
+ if (!get_aim_dir(&dir)) return NULL;
+
+ fire_beam(GF_ELEC, dir, damroll(dice, sides));
+ }
+ }
+ break;
+
+ case 2:
+ if (name) return _("罠と扉感知", "Detect Doors and Traps");
+ if (desc) return _("近くの全ての罠と扉を感知する。", "Detects traps, doors, and stairs in your vicinity.");
+
+ {
+ POSITION rad = DETECT_RAD_DEFAULT;
+
+ if (info) return info_radius(rad);
+
+ if (cast)
+ {
+ detect_traps(rad, TRUE);
+ detect_doors(rad);
+ detect_stairs(rad);
+ }
+ }
+ break;
+
+ case 3:
+ if (name) return _("食糧生成", "Produce Food");
+ if (desc) return _("食料を一つ作り出す。", "Produces a Ration of Food.");
+
+ {
+ if (cast)
+ {
+ object_type forge, *q_ptr = &forge;
+ msg_print(_("食料を生成した。", "A food ration is produced."));
+
+ /* Create the food ration */
+ object_prep(q_ptr, lookup_kind(TV_FOOD, SV_FOOD_RATION));
+
+ /* Drop the object from heaven */
+ (void)drop_near(q_ptr, -1, p_ptr->y, p_ptr->x);
+ }
+ }
+ break;
+
+ case 4:
+ if (name) return _("日の光", "Daylight");
+ if (desc) return _("光源が照らしている範囲か部屋全体を永久に明るくする。", "Lights up nearby area and the inside of a room permanently.");
+
+ {
+ DICE_NUMBER dice = 2;
+ DICE_SID sides = plev / 2;
+ POSITION rad = (plev / 10) + 1;
+
+ if (info) return info_damage(dice, sides, 0);
+
+ if (cast)
+ {
+ lite_area(damroll(dice, sides), rad);
+
+ if ((prace_is_(RACE_VAMPIRE) || (p_ptr->mimic_form == MIMIC_VAMPIRE)) && !p_ptr->resist_lite)
+ {
+ msg_print(_("日の光があなたの肉体を焦がした!", "The daylight scorches your flesh!"));
+ take_hit(DAMAGE_NOESCAPE, damroll(2, 2), _("日の光", "daylight"), -1);
+ }
+ }
+ }
+ break;
+
+ case 5:
+ if (name) return _("動物習し", "Animal Taming");
+ if (desc) return _("動物1体を魅了する。抵抗されると無効。", "Attempts to charm an animal.");
+
+ {
+ int power = plev;
+
+ if (info) return info_power(power);
+
+ if (cast)
+ {
+ if (!get_aim_dir(&dir)) return NULL;
+
+ charm_animal(dir, plev);
+ }
+ }
+ break;
+
+ case 6:
+ if (name) return _("環境への耐性", "Resist Environment");
+ if (desc) return _("一定時間、冷気、炎、電撃に対する耐性を得る。装備による耐性に累積する。",
+ "Gives resistance to fire, cold and electricity for a while. These resistances can be added to which from equipment for more powerful resistances.");
+
+ {
+ int base = 20;
+
+ if (info) return info_duration(base, base);
+
+ if (cast)
+ {
+ set_oppose_cold(randint1(base) + base, FALSE);
+ set_oppose_fire(randint1(base) + base, FALSE);
+ set_oppose_elec(randint1(base) + base, FALSE);
+ }
+ }
+ break;
+
+ case 7:
+ if (name) return _("傷と毒治療", "Cure Wounds & Poison");
+ if (desc) return _("怪我を全快させ、毒を体から完全に取り除き、体力を少し回復させる。", "Heals all cut and poison status. Heals HP a little.");
+
+ {
+ DICE_NUMBER dice = 2;
+ DICE_SID sides = 8;
+
+ if (info) return info_heal(dice, sides, 0);
+
+ if (cast)
+ {
+ hp_player(damroll(dice, sides));
+ set_cut(0);
+ set_poisoned(0);
+ }
+ }
+ break;
+
+ case 8:
+ if (name) return _("岩石溶解", "Stone to Mud");
+ if (desc) return _("壁を溶かして床にする。", "Turns one rock square to mud.");
+
+ {
+ DICE_NUMBER dice = 1;
+ DICE_SID sides = 30;
+ int base = 20;
+
+ if (info) return info_damage(dice, sides, base);
+
+ if (cast)
+ {
+ if (!get_aim_dir(&dir)) return NULL;
+
+ wall_to_mud(dir, 20 + randint1(30));
+ }
+ }
+ break;
+
+ case 9:
+ if (name) return _("アイス・ボルト", "Frost Bolt");
+ if (desc) return _("冷気のボルトもしくはビームを放つ。", "Fires a bolt or beam of cold.");
+
+ {
+ DICE_NUMBER dice = 3 + (plev - 5) / 4;
+ DICE_SID sides = 8;
+
+ if (info) return info_damage(dice, sides, 0);
+
+ if (cast)
+ {
+ if (!get_aim_dir(&dir)) return NULL;
+ fire_bolt_or_beam(beam_chance() - 10, GF_COLD, dir, damroll(dice, sides));
+ }
+ }
+ break;
+
+ case 10:
+ if (name) return _("自然の覚醒", "Nature Awareness");
+ if (desc) return _("周辺の地形を感知し、近くの罠、扉、階段、全てのモンスターを感知する。",
+ "Maps nearby area. Detects all monsters, traps, doors and stairs.");
+
+ {
+ int rad1 = DETECT_RAD_MAP;
+ int rad2 = DETECT_RAD_DEFAULT;
+
+ if (info) return info_radius(MAX(rad1, rad2));
+
+ if (cast)
+ {
+ map_area(rad1);
+ detect_traps(rad2, TRUE);
+ detect_doors(rad2);
+ detect_stairs(rad2);
+ detect_monsters_normal(rad2);
+ }
+ }
+ break;
+
+ case 11:
+ if (name) return _("ファイア・ボルト", "Fire Bolt");
+ if (desc) return _("火炎のボルトもしくはビームを放つ。", "Fires a bolt or beam of fire.");
+
+ {
+ DICE_NUMBER dice = 5 + (plev - 5) / 4;
+ DICE_SID sides = 8;
+
+ if (info) return info_damage(dice, sides, 0);
+
+ if (cast)
+ {
+ if (!get_aim_dir(&dir)) return NULL;
+ fire_bolt_or_beam(beam_chance() - 10, GF_FIRE, dir, damroll(dice, sides));
+ }
+ }
+ break;
+
+ case 12:
+ if (name) return _("太陽光線", "Ray of Sunlight");
+ if (desc) return _("光線を放つ。光りを嫌うモンスターに効果がある。", "Fires a beam of light which damages to light-sensitive monsters.");
+
+ {
+ DICE_NUMBER dice = 6;
+ DICE_SID sides = 8;
+
+ if (info) return info_damage(dice, sides, 0);
+
+ if (cast)
+ {
+ if (!get_aim_dir(&dir)) return NULL;
+ msg_print(_("太陽光線が現れた。", "A line of sunlight appears."));
+ lite_line(dir, damroll(6, 8));
+ }
+ }
+ break;
+
+ case 13:
+ if (name) return _("足かせ", "Entangle");
+ if (desc) return _("視界内の全てのモンスターを減速させる。抵抗されると無効。", "Attempts to slow all monsters in sight.");
+ {
+ int power = plev;
+ if (info) return info_power(power);
+ if (cast) slow_monsters(plev);
+ }
+ break;
+
+ case 14:
+ if (name) return _("動物召喚", "Summon Animal");
+ if (desc) return _("動物を1体召喚する。", "Summons an animal.");
+
+ {
+ if (cast)
+ {
+ if (!(summon_specific(-1, p_ptr->y, p_ptr->x, plev, SUMMON_ANIMAL_RANGER, (PM_ALLOW_GROUP | PM_FORCE_PET), '\0')))
+ {
+ msg_print(_("動物は現れなかった。", "No animals arrive."));
+ }
+ break;
+ }
+ }
+ break;
+
+ case 15:
+ if (name) return _("薬草治療", "Herbal Healing");
+ if (desc) return _("体力を大幅に回復させ、負傷、朦朧状態、毒から全快する。", "Heals HP greatly. And heals cut, stun and poison completely.");
+ {
+ int heal = 500;
+ if (info) return info_heal(0, 0, heal);
+ if (cast) (void)cure_critical_wounds(heal);
+ }
+ break;
+
+ case 16:
+ if (name) return _("階段生成", "Stair Building");
+ if (desc) return _("自分のいる位置に階段を作る。", "Creates a stair which goes down or up.");
+
+ {
+ if (cast)
+ {
+ stair_creation();
+ }
+ }
+ break;
+
+ case 17:
+ if (name) return _("肌石化", "Stone Skin");
+ if (desc) return _("一定時間、ACを上昇させる。", "Gives bonus to AC for a while.");
+
+ {
+ int base = 20;
+ DICE_SID sides = 30;
+
+ if (info) return info_duration(base, sides);
+
+ if (cast)
+ {
+ set_shield(randint1(sides) + base, FALSE);
+ }
+ }
+ break;
+
+ case 18:
+ if (name) return _("真・耐性", "Resistance True");
+ if (desc) return _("一定時間、酸、電撃、炎、冷気、毒に対する耐性を得る。装備による耐性に累積する。",
+ "Gives resistance to fire, cold, electricity, acid and poison for a while. These resistances can be added to which from equipment for more powerful resistances.");
+
+ {
+ int base = 20;
+
+ if (info) return info_duration(base, base);
+
+ if (cast)
+ {
+ set_oppose_acid(randint1(base) + base, FALSE);
+ set_oppose_elec(randint1(base) + base, FALSE);
+ set_oppose_fire(randint1(base) + base, FALSE);
+ set_oppose_cold(randint1(base) + base, FALSE);
+ set_oppose_pois(randint1(base) + base, FALSE);
+ }
+ }
+ break;
+
+ case 19:
+ if (name) return _("森林創造", "Forest Creation");
+ if (desc) return _("周囲に木を作り出す。", "Creates trees in all adjacent squares.");
+
+ {
+ if (cast)
+ {
+ tree_creation();
+ }
+ }
+ break;
+
+ case 20:
+ if (name) return _("動物友和", "Animal Friendship");
+ if (desc) return _("視界内の全ての動物を魅了する。抵抗されると無効。", "Attempts to charm all animals in sight.");
+
+ {
+ int power = plev * 2;
+ if (info) return info_power(power);
+ if (cast) charm_animals(power);
+ }
+ break;
+
+ case 21:
+ if (name) return _("試金石", "Stone Tell");
+ if (desc) return _("アイテムの持つ能力を完全に知る。", "*Identifies* an item.");
+
+ {
+ if (cast)
+ {
+ if (!identify_fully(FALSE)) return NULL;
+ }
+ }
+ break;
+
+ case 22:
+ if (name) return _("石の壁", "Wall of Stone");
+ if (desc) return _("自分の周囲に花崗岩の壁を作る。", "Creates granite walls in all adjacent squares.");
+
+ {
+ if (cast)
+ {
+ wall_stone();
+ }
+ }
+ break;
+
+ case 23:
+ if (name) return _("腐食防止", "Protect from Corrosion");
+ if (desc) return _("アイテムを酸で傷つかないよう加工する。", "Makes an equipment acid-proof.");
+
+ {
+ if (cast)
+ {
+ if (!rustproof()) return NULL;
+ }
+ }
+ break;
+
+ case 24:
+ if (name) return _("地震", "Earthquake");
+ if (desc) return _("周囲のダンジョンを揺らし、壁と床をランダムに入れ変える。",
+ "Shakes dungeon structure, and results in random swapping of floors and walls.");
+
+ {
+ POSITION rad = 10;
+
+ if (info) return info_radius(rad);
+
+ if (cast)
+ {
+ earthquake(p_ptr->y, p_ptr->x, rad);
+ }
+ }
+ break;
+
+ case 25:
+ if (name) return _("カマイタチ", "Whirlwind");
+ if (desc) return _("全方向に向かって攻撃する。", "Attacks all adjacent monsters.");
+ if (cast) massacre();
+ break;
+
+ case 26:
+ if (name) return _("ブリザード", "Blizzard");
+ if (desc) return _("巨大な冷気の球を放つ。", "Fires a huge ball of cold.");
+
+ {
+ HIT_POINT dam = 70 + plev * 3 / 2;
+ POSITION rad = plev / 12 + 1;
+
+ if (info) return info_damage(0, 0, dam);
+
+ if (cast)
+ {
+ if (!get_aim_dir(&dir)) return NULL;
+
+ fire_ball(GF_COLD, dir, dam, rad);
+ }
+ }
+ break;
+
+ case 27:
+ if (name) return _("稲妻嵐", "Lightning Storm");
+ if (desc) return _("巨大な電撃の球を放つ。", "Fires a huge electric ball.");
+
+ {
+ HIT_POINT dam = 90 + plev * 3 / 2;
+ POSITION rad = plev / 12 + 1;
+
+ if (info) return info_damage(0, 0, dam);
+
+ if (cast)
+ {
+ if (!get_aim_dir(&dir)) return NULL;
+ fire_ball(GF_ELEC, dir, dam, rad);
+ break;
+ }
+ }
+ break;
+
+ case 28:
+ if (name) return _("渦潮", "Whirlpool");
+ if (desc) return _("巨大な水の球を放つ。", "Fires a huge ball of water.");
+
+ {
+ HIT_POINT dam = 100 + plev * 3 / 2;
+ POSITION rad = plev / 12 + 1;
+
+ if (info) return info_damage(0, 0, dam);
+
+ if (cast)
+ {
+ if (!get_aim_dir(&dir)) return NULL;
+ fire_ball(GF_WATER, dir, dam, rad);
+ }
+ }
+ break;
+
+ case 29:
+ if (name) return _("陽光召喚", "Call Sunlight");
+ if (desc) return _("自分を中心とした光の球を発生させる。さらに、その階全体を永久に照らし、ダンジョン内すべてのアイテムを感知する。",
+ "Generates ball of light centered on you. Maps and lights whole dungeon level. Knows all objects location.");
+
+ {
+ HIT_POINT dam = 150;
+ POSITION rad = 8;
+
+ if (info) return info_damage(0, 0, dam / 2);
+
+ if (cast)
+ {
+ fire_ball(GF_LITE, 0, dam, rad);
+ chg_virtue(V_KNOWLEDGE, 1);
+ chg_virtue(V_ENLIGHTEN, 1);
+ wiz_lite(FALSE);
+
+ if ((prace_is_(RACE_VAMPIRE) || (p_ptr->mimic_form == MIMIC_VAMPIRE)) && !p_ptr->resist_lite)
+ {
+ msg_print(_("日光があなたの肉体を焦がした!", "The sunlight scorches your flesh!"));
+ take_hit(DAMAGE_NOESCAPE, 50, _("日光", "sunlight"), -1);
+ }
+ }
+ }
+ break;
+
+ case 30:
+ if (name) return _("精霊の刃", "Elemental Branding");
+ if (desc) return _("武器に炎か冷気の属性をつける。", "Makes current weapon fire or frost branded.");
+
+ {
+ if (cast)
+ {
+ brand_weapon(randint0(2));
+ }
+ }
+ break;
+
+ case 31:
+ if (name) return _("自然の脅威", "Nature's Wrath");
+ if (desc) return _("近くの全てのモンスターにダメージを与え、地震を起こし、自分を中心とした分解の球を発生させる。",
+ "Damages all monsters in sight. Makes quake. Generates disintegration ball centered on you.");
+
+ {
+ int d_dam = 4 * plev;
+ int b_dam = (100 + plev) * 2;
+ POSITION b_rad = 1 + plev / 12;
+ POSITION q_rad = 20 + plev / 2;
+
+ if (info) return format("%s%d+%d", KWD_DAM, d_dam, b_dam / 2);
+
+ if (cast)
+ {
+ dispel_monsters(d_dam);
+ earthquake(p_ptr->y, p_ptr->x, q_rad);
+ project(0, b_rad, p_ptr->y, p_ptr->x, b_dam, GF_DISINTEGRATE, PROJECT_KILL | PROJECT_ITEM, -1);
+ }
+ }
+ break;
+ }
+
+ return "";
+}
+
-extern concptr do_nature_spell(SPELL_IDX spell, BIT_FLAGS mode);\r
+extern concptr do_nature_spell(SPELL_IDX spell, BIT_FLAGS mode);
-extern concptr do_music_spell(SPELL_IDX spell, BIT_FLAGS mode);\r
+extern concptr do_music_spell(SPELL_IDX spell, BIT_FLAGS mode);
-extern concptr do_sorcery_spell(SPELL_IDX spell, BIT_FLAGS mode);\r
+extern concptr do_sorcery_spell(SPELL_IDX spell, BIT_FLAGS mode);
-extern concptr do_trump_spell(SPELL_IDX spell, BIT_FLAGS mode);\r
+extern concptr do_trump_spell(SPELL_IDX spell, BIT_FLAGS mode);
-#include "angband.h"\r
-#include "grid.h"\r
-#include "generate.h"\r
-#include "rooms.h"\r
-#include "rooms-city.h"\r
-#include "store.h"\r
-\r
-\r
-\r
-/*\r
-* Precalculate buildings' location of underground arcade\r
-*/\r
-static bool precalc_ugarcade(int town_hgt, int town_wid, int n)\r
-{\r
- POSITION i, y, x, center_y, center_x;\r
- int tmp, attempt = 10000;\r
- POSITION max_bldg_hgt = 3 * town_hgt / MAX_TOWN_HGT;\r
- POSITION max_bldg_wid = 5 * town_wid / MAX_TOWN_WID;\r
- ugbldg_type *cur_ugbldg;\r
- bool **ugarcade_used, abort;\r
-\r
- /* Allocate "ugarcade_used" array (2-dimension) */\r
- C_MAKE(ugarcade_used, town_hgt, bool *);\r
- C_MAKE(*ugarcade_used, town_hgt * town_wid, bool);\r
- for (y = 1; y < town_hgt; y++) ugarcade_used[y] = *ugarcade_used + y * town_wid;\r
-\r
- /* Calculate building locations */\r
- for (i = 0; i < n; i++)\r
- {\r
- cur_ugbldg = &ugbldg[i];\r
- (void)WIPE(cur_ugbldg, ugbldg_type);\r
-\r
- do\r
- {\r
- /* Find the "center" of the store */\r
- center_y = rand_range(2, town_hgt - 3);\r
- center_x = rand_range(2, town_wid - 3);\r
-\r
- /* Determine the store boundaries */\r
- tmp = center_y - randint1(max_bldg_hgt);\r
- cur_ugbldg->y0 = MAX(tmp, 1);\r
- tmp = center_x - randint1(max_bldg_wid);\r
- cur_ugbldg->x0 = MAX(tmp, 1);\r
- tmp = center_y + randint1(max_bldg_hgt);\r
- cur_ugbldg->y1 = MIN(tmp, town_hgt - 2);\r
- tmp = center_x + randint1(max_bldg_wid);\r
- cur_ugbldg->x1 = MIN(tmp, town_wid - 2);\r
-\r
- /* Scan this building's area */\r
- for (abort = FALSE, y = cur_ugbldg->y0; (y <= cur_ugbldg->y1) && !abort; y++)\r
- {\r
- for (x = cur_ugbldg->x0; x <= cur_ugbldg->x1; x++)\r
- {\r
- if (ugarcade_used[y][x])\r
- {\r
- abort = TRUE;\r
- break;\r
- }\r
- }\r
- }\r
-\r
- attempt--;\r
- } while (abort && attempt); /* Accept this building if no overlapping */\r
-\r
- /* Failed to generate underground arcade */\r
- if (!attempt) break;\r
-\r
- /*\r
- * Mark to ugarcade_used[][] as "used"\r
- * Note: Building-adjacent grids are included for preventing\r
- * connected bulidings.\r
- */\r
- for (y = cur_ugbldg->y0 - 1; y <= cur_ugbldg->y1 + 1; y++)\r
- {\r
- for (x = cur_ugbldg->x0 - 1; x <= cur_ugbldg->x1 + 1; x++)\r
- {\r
- ugarcade_used[y][x] = TRUE;\r
- }\r
- }\r
- }\r
-\r
- /* Free "ugarcade_used" array (2-dimension) */\r
- C_KILL(*ugarcade_used, town_hgt * town_wid, bool);\r
- C_KILL(ugarcade_used, town_hgt, bool *);\r
-\r
- /* If i < n, generation is not allowed */\r
- return i == n;\r
-}\r
-\r
-\r
-/*!\r
-* @brief タイプ16の部屋…地下都市生成のサブルーチン / Actually create buildings\r
-* @return なし\r
-* @param ltcy 生成基準Y座標\r
-* @param ltcx 生成基準X座標\r
-* @param stotes[] 生成する店舗のリスト\r
-* @param n 生成する店舗の数\r
-* @note\r
-* Note: ltcy and ltcx indicate "left top corner".\r
-*/\r
-static void build_stores(POSITION ltcy, POSITION ltcx, int stores[], int n)\r
-{\r
- int i;\r
- POSITION y, x;\r
- FEAT_IDX j;\r
- ugbldg_type *cur_ugbldg;\r
-\r
- for (i = 0; i < n; i++)\r
- {\r
- cur_ugbldg = &ugbldg[i];\r
-\r
- /* Generate new room */\r
- generate_room_floor(\r
- ltcy + cur_ugbldg->y0 - 2, ltcx + cur_ugbldg->x0 - 2,\r
- ltcy + cur_ugbldg->y1 + 2, ltcx + cur_ugbldg->x1 + 2,\r
- FALSE);\r
- }\r
-\r
- for (i = 0; i < n; i++)\r
- {\r
- cur_ugbldg = &ugbldg[i];\r
-\r
- /* Build an invulnerable rectangular building */\r
- generate_fill_perm_bold(\r
- ltcy + cur_ugbldg->y0, ltcx + cur_ugbldg->x0,\r
- ltcy + cur_ugbldg->y1, ltcx + cur_ugbldg->x1);\r
-\r
- /* Pick a door direction (S,N,E,W) */\r
- switch (randint0(4))\r
- {\r
- /* Bottom side */\r
- case 0:\r
- y = cur_ugbldg->y1;\r
- x = rand_range(cur_ugbldg->x0, cur_ugbldg->x1);\r
- break;\r
-\r
- /* Top side */\r
- case 1:\r
- y = cur_ugbldg->y0;\r
- x = rand_range(cur_ugbldg->x0, cur_ugbldg->x1);\r
- break;\r
-\r
- /* Right side */\r
- case 2:\r
- y = rand_range(cur_ugbldg->y0, cur_ugbldg->y1);\r
- x = cur_ugbldg->x1;\r
- break;\r
-\r
- /* Left side */\r
- default:\r
- y = rand_range(cur_ugbldg->y0, cur_ugbldg->y1);\r
- x = cur_ugbldg->x0;\r
- break;\r
- }\r
-\r
- for (j = 0; j < max_f_idx; j++)\r
- {\r
- if (have_flag(f_info[j].flags, FF_STORE))\r
- {\r
- if (f_info[j].subtype == stores[i]) break;\r
- }\r
- }\r
-\r
- /* Clear previous contents, add a store door */\r
- if (j < max_f_idx)\r
- {\r
- cave_set_feat(ltcy + y, ltcx + x, j);\r
-\r
- /* Init store */\r
- store_init(NO_TOWN, stores[i]);\r
- }\r
- }\r
-}\r
-\r
-\r
-/*!\r
-* @brief タイプ16の部屋…地下都市の生成 / Type 16 -- Underground Arcade\r
-* @return なし\r
-* @details\r
-* Town logic flow for generation of new town\n\r
-* Originally from Vanilla 3.0.3\n\r
-*\n\r
-* We start with a fully wiped cave of normal floors.\n\r
-*\n\r
-* Note that town_gen_hack() plays games with the R.N.G.\n\r
-*\n\r
-* This function does NOT do anything about the owners of the stores,\n\r
-* nor the contents thereof. It only handles the physical layout.\n\r
-*/\r
-bool build_type16(void)\r
-{\r
- int stores[] =\r
- {\r
- STORE_GENERAL, STORE_ARMOURY, STORE_WEAPON, STORE_TEMPLE,\r
- STORE_ALCHEMIST, STORE_MAGIC, STORE_BLACK, STORE_BOOK,\r
- };\r
- int n = sizeof stores / sizeof(int);\r
- POSITION i, y, x, y1, x1, yval, xval;\r
- int town_hgt = rand_range(MIN_TOWN_HGT, MAX_TOWN_HGT);\r
- int town_wid = rand_range(MIN_TOWN_WID, MAX_TOWN_WID);\r
- bool prevent_bm = FALSE;\r
-\r
- /* Hack -- If already exist black market, prevent building */\r
- for (y = 0; (y < cur_hgt) && !prevent_bm; y++)\r
- {\r
- for (x = 0; x < cur_wid; x++)\r
- {\r
- if (cave[y][x].feat == FF_STORE)\r
- {\r
- prevent_bm = (f_info[cave[y][x].feat].subtype == STORE_BLACK);\r
- break;\r
- }\r
- }\r
- }\r
- for (i = 0; i < n; i++)\r
- {\r
- if ((stores[i] == STORE_BLACK) && prevent_bm) stores[i] = stores[--n];\r
- }\r
- if (!n) return FALSE;\r
-\r
- /* Allocate buildings array */\r
- C_MAKE(ugbldg, n, ugbldg_type);\r
-\r
- /* If cannot build stores, abort */\r
- if (!precalc_ugarcade(town_hgt, town_wid, n))\r
- {\r
- /* Free buildings array */\r
- C_KILL(ugbldg, n, ugbldg_type);\r
- return FALSE;\r
- }\r
-\r
- /* Find and reserve some space in the dungeon. Get center of room. */\r
- if (!find_space(&yval, &xval, town_hgt + 4, town_wid + 4))\r
- {\r
- /* Free buildings array */\r
- C_KILL(ugbldg, n, ugbldg_type);\r
- return FALSE;\r
- }\r
-\r
- /* Get top left corner */\r
- y1 = yval - (town_hgt / 2);\r
- x1 = xval - (town_wid / 2);\r
-\r
- /* Generate new room */\r
- generate_room_floor(\r
- y1 + town_hgt / 3, x1 + town_wid / 3,\r
- y1 + town_hgt * 2 / 3, x1 + town_wid * 2 / 3, FALSE);\r
-\r
- /* Build stores */\r
- build_stores(y1, x1, stores, n);\r
-\r
- msg_print_wizard(CHEAT_DUNGEON, _("地下街を生成しました", "Underground arcade was generated."));\r
-\r
- /* Free buildings array */\r
- C_KILL(ugbldg, n, ugbldg_type);\r
-\r
- return TRUE;\r
-}\r
-\r
+#include "angband.h"
+#include "grid.h"
+#include "generate.h"
+#include "rooms.h"
+#include "rooms-city.h"
+#include "store.h"
+
+
+
+/*
+* Precalculate buildings' location of underground arcade
+*/
+static bool precalc_ugarcade(int town_hgt, int town_wid, int n)
+{
+ POSITION i, y, x, center_y, center_x;
+ int tmp, attempt = 10000;
+ POSITION max_bldg_hgt = 3 * town_hgt / MAX_TOWN_HGT;
+ POSITION max_bldg_wid = 5 * town_wid / MAX_TOWN_WID;
+ ugbldg_type *cur_ugbldg;
+ bool **ugarcade_used, abort;
+
+ /* Allocate "ugarcade_used" array (2-dimension) */
+ C_MAKE(ugarcade_used, town_hgt, bool *);
+ C_MAKE(*ugarcade_used, town_hgt * town_wid, bool);
+ for (y = 1; y < town_hgt; y++) ugarcade_used[y] = *ugarcade_used + y * town_wid;
+
+ /* Calculate building locations */
+ for (i = 0; i < n; i++)
+ {
+ cur_ugbldg = &ugbldg[i];
+ (void)WIPE(cur_ugbldg, ugbldg_type);
+
+ do
+ {
+ /* Find the "center" of the store */
+ center_y = rand_range(2, town_hgt - 3);
+ center_x = rand_range(2, town_wid - 3);
+
+ /* Determine the store boundaries */
+ tmp = center_y - randint1(max_bldg_hgt);
+ cur_ugbldg->y0 = MAX(tmp, 1);
+ tmp = center_x - randint1(max_bldg_wid);
+ cur_ugbldg->x0 = MAX(tmp, 1);
+ tmp = center_y + randint1(max_bldg_hgt);
+ cur_ugbldg->y1 = MIN(tmp, town_hgt - 2);
+ tmp = center_x + randint1(max_bldg_wid);
+ cur_ugbldg->x1 = MIN(tmp, town_wid - 2);
+
+ /* Scan this building's area */
+ for (abort = FALSE, y = cur_ugbldg->y0; (y <= cur_ugbldg->y1) && !abort; y++)
+ {
+ for (x = cur_ugbldg->x0; x <= cur_ugbldg->x1; x++)
+ {
+ if (ugarcade_used[y][x])
+ {
+ abort = TRUE;
+ break;
+ }
+ }
+ }
+
+ attempt--;
+ } while (abort && attempt); /* Accept this building if no overlapping */
+
+ /* Failed to generate underground arcade */
+ if (!attempt) break;
+
+ /*
+ * Mark to ugarcade_used[][] as "used"
+ * Note: Building-adjacent grids are included for preventing
+ * connected bulidings.
+ */
+ for (y = cur_ugbldg->y0 - 1; y <= cur_ugbldg->y1 + 1; y++)
+ {
+ for (x = cur_ugbldg->x0 - 1; x <= cur_ugbldg->x1 + 1; x++)
+ {
+ ugarcade_used[y][x] = TRUE;
+ }
+ }
+ }
+
+ /* Free "ugarcade_used" array (2-dimension) */
+ C_KILL(*ugarcade_used, town_hgt * town_wid, bool);
+ C_KILL(ugarcade_used, town_hgt, bool *);
+
+ /* If i < n, generation is not allowed */
+ return i == n;
+}
+
+
+/*!
+* @brief タイプ16の部屋…地下都市生成のサブルーチン / Actually create buildings
+* @return なし
+* @param ltcy 生成基準Y座標
+* @param ltcx 生成基準X座標
+* @param stotes[] 生成する店舗のリスト
+* @param n 生成する店舗の数
+* @note
+* Note: ltcy and ltcx indicate "left top corner".
+*/
+static void build_stores(POSITION ltcy, POSITION ltcx, int stores[], int n)
+{
+ int i;
+ POSITION y, x;
+ FEAT_IDX j;
+ ugbldg_type *cur_ugbldg;
+
+ for (i = 0; i < n; i++)
+ {
+ cur_ugbldg = &ugbldg[i];
+
+ /* Generate new room */
+ generate_room_floor(
+ ltcy + cur_ugbldg->y0 - 2, ltcx + cur_ugbldg->x0 - 2,
+ ltcy + cur_ugbldg->y1 + 2, ltcx + cur_ugbldg->x1 + 2,
+ FALSE);
+ }
+
+ for (i = 0; i < n; i++)
+ {
+ cur_ugbldg = &ugbldg[i];
+
+ /* Build an invulnerable rectangular building */
+ generate_fill_perm_bold(
+ ltcy + cur_ugbldg->y0, ltcx + cur_ugbldg->x0,
+ ltcy + cur_ugbldg->y1, ltcx + cur_ugbldg->x1);
+
+ /* Pick a door direction (S,N,E,W) */
+ switch (randint0(4))
+ {
+ /* Bottom side */
+ case 0:
+ y = cur_ugbldg->y1;
+ x = rand_range(cur_ugbldg->x0, cur_ugbldg->x1);
+ break;
+
+ /* Top side */
+ case 1:
+ y = cur_ugbldg->y0;
+ x = rand_range(cur_ugbldg->x0, cur_ugbldg->x1);
+ break;
+
+ /* Right side */
+ case 2:
+ y = rand_range(cur_ugbldg->y0, cur_ugbldg->y1);
+ x = cur_ugbldg->x1;
+ break;
+
+ /* Left side */
+ default:
+ y = rand_range(cur_ugbldg->y0, cur_ugbldg->y1);
+ x = cur_ugbldg->x0;
+ break;
+ }
+
+ for (j = 0; j < max_f_idx; j++)
+ {
+ if (have_flag(f_info[j].flags, FF_STORE))
+ {
+ if (f_info[j].subtype == stores[i]) break;
+ }
+ }
+
+ /* Clear previous contents, add a store door */
+ if (j < max_f_idx)
+ {
+ cave_set_feat(ltcy + y, ltcx + x, j);
+
+ /* Init store */
+ store_init(NO_TOWN, stores[i]);
+ }
+ }
+}
+
+
+/*!
+* @brief タイプ16の部屋…地下都市の生成 / Type 16 -- Underground Arcade
+* @return なし
+* @details
+* Town logic flow for generation of new town\n
+* Originally from Vanilla 3.0.3\n
+*\n
+* We start with a fully wiped cave of normal floors.\n
+*\n
+* Note that town_gen_hack() plays games with the R.N.G.\n
+*\n
+* This function does NOT do anything about the owners of the stores,\n
+* nor the contents thereof. It only handles the physical layout.\n
+*/
+bool build_type16(void)
+{
+ int stores[] =
+ {
+ STORE_GENERAL, STORE_ARMOURY, STORE_WEAPON, STORE_TEMPLE,
+ STORE_ALCHEMIST, STORE_MAGIC, STORE_BLACK, STORE_BOOK,
+ };
+ int n = sizeof stores / sizeof(int);
+ POSITION i, y, x, y1, x1, yval, xval;
+ int town_hgt = rand_range(MIN_TOWN_HGT, MAX_TOWN_HGT);
+ int town_wid = rand_range(MIN_TOWN_WID, MAX_TOWN_WID);
+ bool prevent_bm = FALSE;
+
+ /* Hack -- If already exist black market, prevent building */
+ for (y = 0; (y < cur_hgt) && !prevent_bm; y++)
+ {
+ for (x = 0; x < cur_wid; x++)
+ {
+ if (cave[y][x].feat == FF_STORE)
+ {
+ prevent_bm = (f_info[cave[y][x].feat].subtype == STORE_BLACK);
+ break;
+ }
+ }
+ }
+ for (i = 0; i < n; i++)
+ {
+ if ((stores[i] == STORE_BLACK) && prevent_bm) stores[i] = stores[--n];
+ }
+ if (!n) return FALSE;
+
+ /* Allocate buildings array */
+ C_MAKE(ugbldg, n, ugbldg_type);
+
+ /* If cannot build stores, abort */
+ if (!precalc_ugarcade(town_hgt, town_wid, n))
+ {
+ /* Free buildings array */
+ C_KILL(ugbldg, n, ugbldg_type);
+ return FALSE;
+ }
+
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&yval, &xval, town_hgt + 4, town_wid + 4))
+ {
+ /* Free buildings array */
+ C_KILL(ugbldg, n, ugbldg_type);
+ return FALSE;
+ }
+
+ /* Get top left corner */
+ y1 = yval - (town_hgt / 2);
+ x1 = xval - (town_wid / 2);
+
+ /* Generate new room */
+ generate_room_floor(
+ y1 + town_hgt / 3, x1 + town_wid / 3,
+ y1 + town_hgt * 2 / 3, x1 + town_wid * 2 / 3, FALSE);
+
+ /* Build stores */
+ build_stores(y1, x1, stores, n);
+
+ msg_print_wizard(CHEAT_DUNGEON, _("地下街を生成しました", "Underground arcade was generated."));
+
+ /* Free buildings array */
+ C_KILL(ugbldg, n, ugbldg_type);
+
+ return TRUE;
+}
+
-extern bool build_type16(void);\r
-\r
-/* Minimum & maximum town size */\r
-#define MIN_TOWN_WID ((MAX_WID / 3) / 2)\r
-#define MIN_TOWN_HGT ((MAX_HGT / 3) / 2)\r
-#define MAX_TOWN_WID ((MAX_WID / 3) * 2 / 3)\r
-#define MAX_TOWN_HGT ((MAX_HGT / 3) * 2 / 3)\r
-\r
-/* Struct for build underground buildings */\r
-typedef struct\r
-{\r
- POSITION y0, x0; /* North-west corner (relative) */\r
- POSITION y1, x1; /* South-east corner (relative) */\r
-}\r
-ugbldg_type;\r
-\r
-ugbldg_type *ugbldg;\r
+extern bool build_type16(void);
+
+/* Minimum & maximum town size */
+#define MIN_TOWN_WID ((MAX_WID / 3) / 2)
+#define MIN_TOWN_HGT ((MAX_HGT / 3) / 2)
+#define MAX_TOWN_WID ((MAX_WID / 3) * 2 / 3)
+#define MAX_TOWN_HGT ((MAX_HGT / 3) * 2 / 3)
+
+/* Struct for build underground buildings */
+typedef struct
+{
+ POSITION y0, x0; /* North-west corner (relative) */
+ POSITION y1, x1; /* South-east corner (relative) */
+}
+ugbldg_type;
+
+ugbldg_type *ugbldg;
-#include "angband.h"\r
-#include "grid.h"\r
-#include "generate.h"\r
-#include "rooms.h"\r
-#include "rooms-normal.h"\r
-\r
-/*!\r
-* @brief タイプ9の部屋…フラクタルカーブによる洞窟生成 / Type 9 -- Driver routine to create fractal cave system\r
-* @return なし\r
-*/\r
-bool build_type9(void)\r
-{\r
- int grd, roug, cutoff;\r
- POSITION xsize, ysize, y0, x0;\r
-\r
- bool done, light, room;\r
-\r
- /* get size: note 'Evenness'*/\r
- xsize = randint1(22) * 2 + 6;\r
- ysize = randint1(15) * 2 + 6;\r
-\r
- /* Find and reserve some space in the dungeon. Get center of room. */\r
- if (!find_space(&y0, &x0, ysize + 1, xsize + 1))\r
- {\r
- /* Limit to the minimum room size, and retry */\r
- xsize = 8;\r
- ysize = 8;\r
-\r
- /* Find and reserve some space in the dungeon. Get center of room. */\r
- if (!find_space(&y0, &x0, ysize + 1, xsize + 1))\r
- {\r
- /*\r
- * Still no space?!\r
- * Try normal room\r
- */\r
- return build_type1();\r
- }\r
- }\r
-\r
- light = done = FALSE;\r
- room = TRUE;\r
-\r
- if ((dun_level <= randint1(25)) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS)) light = TRUE;\r
-\r
- while (!done)\r
- {\r
- /* Note: size must be even or there are rounding problems\r
- * This causes the tunnels not to connect properly to the room */\r
-\r
- /* testing values for these parameters feel free to adjust */\r
- grd = 1 << (randint0(4));\r
-\r
- /* want average of about 16 */\r
- roug = randint1(8) * randint1(4);\r
-\r
- /* about size/2 */\r
- cutoff = randint1(xsize / 4) + randint1(ysize / 4) +\r
- randint1(xsize / 4) + randint1(ysize / 4);\r
-\r
- /* make it */\r
- generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);\r
-\r
- /* Convert to normal format + clean up */\r
- done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);\r
- }\r
-\r
- return TRUE;\r
-}\r
+#include "angband.h"
+#include "grid.h"
+#include "generate.h"
+#include "rooms.h"
+#include "rooms-normal.h"
+
+/*!
+* @brief タイプ9の部屋…フラクタルカーブによる洞窟生成 / Type 9 -- Driver routine to create fractal cave system
+* @return なし
+*/
+bool build_type9(void)
+{
+ int grd, roug, cutoff;
+ POSITION xsize, ysize, y0, x0;
+
+ bool done, light, room;
+
+ /* get size: note 'Evenness'*/
+ xsize = randint1(22) * 2 + 6;
+ ysize = randint1(15) * 2 + 6;
+
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&y0, &x0, ysize + 1, xsize + 1))
+ {
+ /* Limit to the minimum room size, and retry */
+ xsize = 8;
+ ysize = 8;
+
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&y0, &x0, ysize + 1, xsize + 1))
+ {
+ /*
+ * Still no space?!
+ * Try normal room
+ */
+ return build_type1();
+ }
+ }
+
+ light = done = FALSE;
+ room = TRUE;
+
+ if ((dun_level <= randint1(25)) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS)) light = TRUE;
+
+ while (!done)
+ {
+ /* Note: size must be even or there are rounding problems
+ * This causes the tunnels not to connect properly to the room */
+
+ /* testing values for these parameters feel free to adjust */
+ grd = 1 << (randint0(4));
+
+ /* want average of about 16 */
+ roug = randint1(8) * randint1(4);
+
+ /* about size/2 */
+ cutoff = randint1(xsize / 4) + randint1(ysize / 4) +
+ randint1(xsize / 4) + randint1(ysize / 4);
+
+ /* make it */
+ generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
+
+ /* Convert to normal format + clean up */
+ done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
+ }
+
+ return TRUE;
+}
-\r
-extern bool build_type9(void);\r
+
+extern bool build_type9(void);
-#include "angband.h"\r
-#include "grid.h"\r
-#include "trap.h"\r
-\r
-#include "rooms.h"\r
-\r
-\r
-/*!\r
-* @brief タイプ1の部屋…通常可変長方形の部屋を生成する / Type 1 -- normal rectangular rooms\r
-* @return なし\r
-*/\r
-bool build_type1(void)\r
-{\r
- POSITION y, x, y2, x2, yval, xval;\r
- POSITION y1, x1, xsize, ysize;\r
-\r
- bool light;\r
-\r
- cave_type *c_ptr;\r
-\r
- bool curtain = (d_info[p_ptr->dungeon_idx].flags1 & DF1_CURTAIN) &&\r
- one_in_((d_info[p_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) ? 48 : 512);\r
-\r
- /* Pick a room size */\r
- y1 = randint1(4);\r
- x1 = randint1(11);\r
- y2 = randint1(3);\r
- x2 = randint1(11);\r
-\r
- xsize = x1 + x2 + 1;\r
- ysize = y1 + y2 + 1;\r
-\r
- /* Find and reserve some space in the dungeon. Get center of room. */\r
- if (!find_space(&yval, &xval, ysize + 2, xsize + 2))\r
- {\r
- /* Limit to the minimum room size, and retry */\r
- y1 = 1;\r
- x1 = 1;\r
- y2 = 1;\r
- x2 = 1;\r
-\r
- xsize = x1 + x2 + 1;\r
- ysize = y1 + y2 + 1;\r
-\r
- /* Find and reserve some space in the dungeon. Get center of room. */\r
- if (!find_space(&yval, &xval, ysize + 2, xsize + 2)) return FALSE;\r
- }\r
-\r
- /* Choose lite or dark */\r
- light = ((dun_level <= randint1(25)) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS));\r
-\r
-\r
- /* Get corner values */\r
- y1 = yval - ysize / 2;\r
- x1 = xval - xsize / 2;\r
- y2 = yval + (ysize - 1) / 2;\r
- x2 = xval + (xsize - 1) / 2;\r
-\r
-\r
- /* Place a full floor under the room */\r
- for (y = y1 - 1; y <= y2 + 1; y++)\r
- {\r
- for (x = x1 - 1; x <= x2 + 1; x++)\r
- {\r
- c_ptr = &cave[y][x];\r
- place_floor_grid(c_ptr);\r
- c_ptr->info |= (CAVE_ROOM);\r
- if (light) c_ptr->info |= (CAVE_GLOW);\r
- }\r
- }\r
-\r
- /* Walls around the room */\r
- for (y = y1 - 1; y <= y2 + 1; y++)\r
- {\r
- c_ptr = &cave[y][x1 - 1];\r
- place_outer_grid(c_ptr);\r
- c_ptr = &cave[y][x2 + 1];\r
- place_outer_grid(c_ptr);\r
- }\r
- for (x = x1 - 1; x <= x2 + 1; x++)\r
- {\r
- c_ptr = &cave[y1 - 1][x];\r
- place_outer_grid(c_ptr);\r
- c_ptr = &cave[y2 + 1][x];\r
- place_outer_grid(c_ptr);\r
- }\r
-\r
-\r
- /* Hack -- Occasional curtained room */\r
- if (curtain && (y2 - y1 > 2) && (x2 - x1 > 2))\r
- {\r
- for (y = y1; y <= y2; y++)\r
- {\r
- c_ptr = &cave[y][x1];\r
- c_ptr->feat = feat_door[DOOR_CURTAIN].closed;\r
- c_ptr->info &= ~(CAVE_MASK);\r
- c_ptr = &cave[y][x2];\r
- c_ptr->feat = feat_door[DOOR_CURTAIN].closed;\r
- c_ptr->info &= ~(CAVE_MASK);\r
- }\r
- for (x = x1; x <= x2; x++)\r
- {\r
- c_ptr = &cave[y1][x];\r
- c_ptr->feat = feat_door[DOOR_CURTAIN].closed;\r
- c_ptr->info &= ~(CAVE_MASK);\r
- c_ptr = &cave[y2][x];\r
- c_ptr->feat = feat_door[DOOR_CURTAIN].closed;\r
- c_ptr->info &= ~(CAVE_MASK);\r
- }\r
- }\r
-\r
-\r
- /* Hack -- Occasional pillar room */\r
- if (one_in_(20))\r
- {\r
- for (y = y1; y <= y2; y += 2)\r
- {\r
- for (x = x1; x <= x2; x += 2)\r
- {\r
- c_ptr = &cave[y][x];\r
- place_inner_grid(c_ptr);\r
- }\r
- }\r
- }\r
-\r
- /* Hack -- Occasional room with four pillars */\r
- else if (one_in_(20))\r
- {\r
- if ((y1 + 4 < y2) && (x1 + 4 < x2))\r
- {\r
- c_ptr = &cave[y1 + 1][x1 + 1];\r
- place_inner_grid(c_ptr);\r
-\r
- c_ptr = &cave[y1 + 1][x2 - 1];\r
- place_inner_grid(c_ptr);\r
-\r
- c_ptr = &cave[y2 - 1][x1 + 1];\r
- place_inner_grid(c_ptr);\r
-\r
- c_ptr = &cave[y2 - 1][x2 - 1];\r
- place_inner_grid(c_ptr);\r
- }\r
- }\r
-\r
- /* Hack -- Occasional ragged-edge room */\r
- else if (one_in_(50))\r
- {\r
- for (y = y1 + 2; y <= y2 - 2; y += 2)\r
- {\r
- c_ptr = &cave[y][x1];\r
- place_inner_grid(c_ptr);\r
- c_ptr = &cave[y][x2];\r
- place_inner_grid(c_ptr);\r
- }\r
- for (x = x1 + 2; x <= x2 - 2; x += 2)\r
- {\r
- c_ptr = &cave[y1][x];\r
- place_inner_grid(c_ptr);\r
- c_ptr = &cave[y2][x];\r
- place_inner_grid(c_ptr);\r
- }\r
- }\r
- /* Hack -- Occasional divided room */\r
- else if (one_in_(50))\r
- {\r
- bool curtain2 = (d_info[p_ptr->dungeon_idx].flags1 & DF1_CURTAIN) &&\r
- one_in_((d_info[p_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) ? 2 : 128);\r
-\r
- if (randint1(100) < 50)\r
- {\r
- /* Horizontal wall */\r
- for (x = x1; x <= x2; x++)\r
- {\r
- place_inner_bold(yval, x);\r
- if (curtain2) cave[yval][x].feat = feat_door[DOOR_CURTAIN].closed;\r
- }\r
-\r
- /* Prevent edge of wall from being tunneled */\r
- place_solid_bold(yval, x1 - 1);\r
- place_solid_bold(yval, x2 + 1);\r
- }\r
- else\r
- {\r
- /* Vertical wall */\r
- for (y = y1; y <= y2; y++)\r
- {\r
- place_inner_bold(y, xval);\r
- if (curtain2) cave[y][xval].feat = feat_door[DOOR_CURTAIN].closed;\r
- }\r
-\r
- /* Prevent edge of wall from being tunneled */\r
- place_solid_bold(y1 - 1, xval);\r
- place_solid_bold(y2 + 1, xval);\r
- }\r
-\r
- place_random_door(yval, xval, TRUE);\r
- if (curtain2) cave[yval][xval].feat = feat_door[DOOR_CURTAIN].closed;\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
-/*!\r
-* @brief タイプ2の部屋…二重長方形の部屋を生成する / Type 2 -- Overlapping rectangular rooms\r
-* @return なし\r
-*/\r
-bool build_type2(void)\r
-{\r
- POSITION y, x, xval, yval;\r
- POSITION y1a, x1a, y2a, x2a;\r
- POSITION y1b, x1b, y2b, x2b;\r
- bool light;\r
- cave_type *c_ptr;\r
-\r
- /* Find and reserve some space in the dungeon. Get center of room. */\r
- if (!find_space(&yval, &xval, 11, 25)) return FALSE;\r
-\r
- /* Choose lite or dark */\r
- light = ((dun_level <= randint1(25)) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS));\r
-\r
- /* Determine extents of the first room */\r
- y1a = yval - randint1(4);\r
- y2a = yval + randint1(3);\r
- x1a = xval - randint1(11);\r
- x2a = xval + randint1(10);\r
-\r
- /* Determine extents of the second room */\r
- y1b = yval - randint1(3);\r
- y2b = yval + randint1(4);\r
- x1b = xval - randint1(10);\r
- x2b = xval + randint1(11);\r
-\r
-\r
- /* Place a full floor for room "a" */\r
- for (y = y1a - 1; y <= y2a + 1; y++)\r
- {\r
- for (x = x1a - 1; x <= x2a + 1; x++)\r
- {\r
- c_ptr = &cave[y][x];\r
- place_floor_grid(c_ptr);\r
- c_ptr->info |= (CAVE_ROOM);\r
- if (light) c_ptr->info |= (CAVE_GLOW);\r
- }\r
- }\r
-\r
- /* Place a full floor for room "b" */\r
- for (y = y1b - 1; y <= y2b + 1; y++)\r
- {\r
- for (x = x1b - 1; x <= x2b + 1; x++)\r
- {\r
- c_ptr = &cave[y][x];\r
- place_floor_grid(c_ptr);\r
- c_ptr->info |= (CAVE_ROOM);\r
- if (light) c_ptr->info |= (CAVE_GLOW);\r
- }\r
- }\r
-\r
-\r
- /* Place the walls around room "a" */\r
- for (y = y1a - 1; y <= y2a + 1; y++)\r
- {\r
- c_ptr = &cave[y][x1a - 1];\r
- place_outer_grid(c_ptr);\r
- c_ptr = &cave[y][x2a + 1];\r
- place_outer_grid(c_ptr);\r
- }\r
- for (x = x1a - 1; x <= x2a + 1; x++)\r
- {\r
- c_ptr = &cave[y1a - 1][x];\r
- place_outer_grid(c_ptr);\r
- c_ptr = &cave[y2a + 1][x];\r
- place_outer_grid(c_ptr);\r
- }\r
-\r
- /* Place the walls around room "b" */\r
- for (y = y1b - 1; y <= y2b + 1; y++)\r
- {\r
- c_ptr = &cave[y][x1b - 1];\r
- place_outer_grid(c_ptr);\r
- c_ptr = &cave[y][x2b + 1];\r
- place_outer_grid(c_ptr);\r
- }\r
- for (x = x1b - 1; x <= x2b + 1; x++)\r
- {\r
- c_ptr = &cave[y1b - 1][x];\r
- place_outer_grid(c_ptr);\r
- c_ptr = &cave[y2b + 1][x];\r
- place_outer_grid(c_ptr);\r
- }\r
-\r
-\r
-\r
- /* Replace the floor for room "a" */\r
- for (y = y1a; y <= y2a; y++)\r
- {\r
- for (x = x1a; x <= x2a; x++)\r
- {\r
- c_ptr = &cave[y][x];\r
- place_floor_grid(c_ptr);\r
- }\r
- }\r
-\r
- /* Replace the floor for room "b" */\r
- for (y = y1b; y <= y2b; y++)\r
- {\r
- for (x = x1b; x <= x2b; x++)\r
- {\r
- c_ptr = &cave[y][x];\r
- place_floor_grid(c_ptr);\r
- }\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
-/*!\r
-* @brief タイプ3の部屋…十字型の部屋を生成する / Type 3 -- Cross shaped rooms\r
-* @return なし\r
-* @details\r
-* Builds a room at a row, column coordinate\n\r
-*\n\r
-* Room "a" runs north/south, and Room "b" runs east/east\n\r
-* So the "central pillar" runs from x1a, y1b to x2a, y2b.\n\r
-*\n\r
-* Note that currently, the "center" is always 3x3, but I think that\n\r
-* the code below will work (with "bounds checking") for 5x5, or even\n\r
-* for unsymetric values like 4x3 or 5x3 or 3x4 or 3x5, or even larger.\n\r
-*/\r
-bool build_type3(void)\r
-{\r
- POSITION y, x, dy, dx, wy, wx;\r
- POSITION y1a, x1a, y2a, x2a;\r
- POSITION y1b, x1b, y2b, x2b;\r
- POSITION yval, xval;\r
- bool light;\r
- cave_type *c_ptr;\r
-\r
-\r
- /* Find and reserve some space in the dungeon. Get center of room. */\r
- if (!find_space(&yval, &xval, 11, 25)) return FALSE;\r
-\r
-\r
- /* Choose lite or dark */\r
- light = ((dun_level <= randint1(25)) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS));\r
-\r
- /* For now, always 3x3 */\r
- wx = wy = 1;\r
-\r
- /* Pick max vertical size (at most 4) */\r
- dy = rand_range(3, 4);\r
-\r
- /* Pick max horizontal size (at most 15) */\r
- dx = rand_range(3, 11);\r
-\r
-\r
- /* Determine extents of the north/south room */\r
- y1a = yval - dy;\r
- y2a = yval + dy;\r
- x1a = xval - wx;\r
- x2a = xval + wx;\r
-\r
- /* Determine extents of the east/west room */\r
- y1b = yval - wy;\r
- y2b = yval + wy;\r
- x1b = xval - dx;\r
- x2b = xval + dx;\r
-\r
-\r
- /* Place a full floor for room "a" */\r
- for (y = y1a - 1; y <= y2a + 1; y++)\r
- {\r
- for (x = x1a - 1; x <= x2a + 1; x++)\r
- {\r
- c_ptr = &cave[y][x];\r
- place_floor_grid(c_ptr);\r
- c_ptr->info |= (CAVE_ROOM);\r
- if (light) c_ptr->info |= (CAVE_GLOW);\r
- }\r
- }\r
-\r
- /* Place a full floor for room "b" */\r
- for (y = y1b - 1; y <= y2b + 1; y++)\r
- {\r
- for (x = x1b - 1; x <= x2b + 1; x++)\r
- {\r
- c_ptr = &cave[y][x];\r
- place_floor_grid(c_ptr);\r
- c_ptr->info |= (CAVE_ROOM);\r
- if (light) c_ptr->info |= (CAVE_GLOW);\r
- }\r
- }\r
-\r
-\r
- /* Place the walls around room "a" */\r
- for (y = y1a - 1; y <= y2a + 1; y++)\r
- {\r
- c_ptr = &cave[y][x1a - 1];\r
- place_outer_grid(c_ptr);\r
- c_ptr = &cave[y][x2a + 1];\r
- place_outer_grid(c_ptr);\r
- }\r
- for (x = x1a - 1; x <= x2a + 1; x++)\r
- {\r
- c_ptr = &cave[y1a - 1][x];\r
- place_outer_grid(c_ptr);\r
- c_ptr = &cave[y2a + 1][x];\r
- place_outer_grid(c_ptr);\r
- }\r
-\r
- /* Place the walls around room "b" */\r
- for (y = y1b - 1; y <= y2b + 1; y++)\r
- {\r
- c_ptr = &cave[y][x1b - 1];\r
- place_outer_grid(c_ptr);\r
- c_ptr = &cave[y][x2b + 1];\r
- place_outer_grid(c_ptr);\r
- }\r
- for (x = x1b - 1; x <= x2b + 1; x++)\r
- {\r
- c_ptr = &cave[y1b - 1][x];\r
- place_outer_grid(c_ptr);\r
- c_ptr = &cave[y2b + 1][x];\r
- place_outer_grid(c_ptr);\r
- }\r
-\r
-\r
- /* Replace the floor for room "a" */\r
- for (y = y1a; y <= y2a; y++)\r
- {\r
- for (x = x1a; x <= x2a; x++)\r
- {\r
- c_ptr = &cave[y][x];\r
- place_floor_grid(c_ptr);\r
- }\r
- }\r
-\r
- /* Replace the floor for room "b" */\r
- for (y = y1b; y <= y2b; y++)\r
- {\r
- for (x = x1b; x <= x2b; x++)\r
- {\r
- c_ptr = &cave[y][x];\r
- place_floor_grid(c_ptr);\r
- }\r
- }\r
-\r
-\r
-\r
- /* Special features (3/4) */\r
- switch (randint0(4))\r
- {\r
- /* Large solid middle pillar */\r
- case 1:\r
- {\r
- for (y = y1b; y <= y2b; y++)\r
- {\r
- for (x = x1a; x <= x2a; x++)\r
- {\r
- c_ptr = &cave[y][x];\r
- place_inner_grid(c_ptr);\r
- }\r
- }\r
- break;\r
- }\r
-\r
- /* Inner treasure vault */\r
- case 2:\r
- {\r
- /* Build the vault */\r
- for (y = y1b; y <= y2b; y++)\r
- {\r
- c_ptr = &cave[y][x1a];\r
- place_inner_grid(c_ptr);\r
- c_ptr = &cave[y][x2a];\r
- place_inner_grid(c_ptr);\r
- }\r
- for (x = x1a; x <= x2a; x++)\r
- {\r
- c_ptr = &cave[y1b][x];\r
- place_inner_grid(c_ptr);\r
- c_ptr = &cave[y2b][x];\r
- place_inner_grid(c_ptr);\r
- }\r
-\r
- /* Place a secret door on the inner room */\r
- switch (randint0(4))\r
- {\r
- case 0: place_secret_door(y1b, xval, DOOR_DEFAULT); break;\r
- case 1: place_secret_door(y2b, xval, DOOR_DEFAULT); break;\r
- case 2: place_secret_door(yval, x1a, DOOR_DEFAULT); break;\r
- case 3: place_secret_door(yval, x2a, DOOR_DEFAULT); break;\r
- }\r
-\r
- /* Place a treasure in the vault */\r
- place_object(yval, xval, 0L);\r
-\r
- /* Let's guard the treasure well */\r
- vault_monsters(yval, xval, randint0(2) + 3);\r
-\r
- /* Traps naturally */\r
- vault_traps(yval, xval, 4, 4, randint0(3) + 2);\r
-\r
- break;\r
- }\r
-\r
- /* Something else */\r
- case 3:\r
- {\r
- /* Occasionally pinch the center shut */\r
- if (one_in_(3))\r
- {\r
- /* Pinch the east/west sides */\r
- for (y = y1b; y <= y2b; y++)\r
- {\r
- if (y == yval) continue;\r
- c_ptr = &cave[y][x1a - 1];\r
- place_inner_grid(c_ptr);\r
- c_ptr = &cave[y][x2a + 1];\r
- place_inner_grid(c_ptr);\r
- }\r
-\r
- /* Pinch the north/south sides */\r
- for (x = x1a; x <= x2a; x++)\r
- {\r
- if (x == xval) continue;\r
- c_ptr = &cave[y1b - 1][x];\r
- place_inner_grid(c_ptr);\r
- c_ptr = &cave[y2b + 1][x];\r
- place_inner_grid(c_ptr);\r
- }\r
-\r
- /* Sometimes shut using secret doors */\r
- if (one_in_(3))\r
- {\r
- int door_type = ((d_info[p_ptr->dungeon_idx].flags1 & DF1_CURTAIN) &&\r
- one_in_((d_info[p_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :\r
- ((d_info[p_ptr->dungeon_idx].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);\r
-\r
- place_secret_door(yval, x1a - 1, door_type);\r
- place_secret_door(yval, x2a + 1, door_type);\r
- place_secret_door(y1b - 1, xval, door_type);\r
- place_secret_door(y2b + 1, xval, door_type);\r
- }\r
- }\r
-\r
- /* Occasionally put a "plus" in the center */\r
- else if (one_in_(3))\r
- {\r
- c_ptr = &cave[yval][xval];\r
- place_inner_grid(c_ptr);\r
- c_ptr = &cave[y1b][xval];\r
- place_inner_grid(c_ptr);\r
- c_ptr = &cave[y2b][xval];\r
- place_inner_grid(c_ptr);\r
- c_ptr = &cave[yval][x1a];\r
- place_inner_grid(c_ptr);\r
- c_ptr = &cave[yval][x2a];\r
- place_inner_grid(c_ptr);\r
- }\r
-\r
- /* Occasionally put a pillar in the center */\r
- else if (one_in_(3))\r
- {\r
- c_ptr = &cave[yval][xval];\r
- place_inner_grid(c_ptr);\r
- }\r
-\r
- break;\r
- }\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
-/*!\r
-* @brief タイプ4の部屋…固定サイズの二重構造部屋を生成する / Type 4 -- Large room with inner features\r
-* @return なし\r
-* @details\r
-* Possible sub-types:\n\r
-* 1 - Just an inner room with one door\n\r
-* 2 - An inner room within an inner room\n\r
-* 3 - An inner room with pillar(s)\n\r
-* 4 - Inner room has a maze\n\r
-* 5 - A set of four inner rooms\n\r
-*/\r
-bool build_type4(void)\r
-{\r
- POSITION y, x, y1, x1;\r
- POSITION y2, x2, tmp, yval, xval;\r
- bool light;\r
- cave_type *c_ptr;\r
-\r
-\r
- /* Find and reserve some space in the dungeon. Get center of room. */\r
- if (!find_space(&yval, &xval, 11, 25)) return FALSE;\r
-\r
- /* Choose lite or dark */\r
- light = ((dun_level <= randint1(25)) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS));\r
-\r
- /* Large room */\r
- y1 = yval - 4;\r
- y2 = yval + 4;\r
- x1 = xval - 11;\r
- x2 = xval + 11;\r
-\r
- /* Place a full floor under the room */\r
- for (y = y1 - 1; y <= y2 + 1; y++)\r
- {\r
- for (x = x1 - 1; x <= x2 + 1; x++)\r
- {\r
- c_ptr = &cave[y][x];\r
- place_floor_grid(c_ptr);\r
- c_ptr->info |= (CAVE_ROOM);\r
- if (light) c_ptr->info |= (CAVE_GLOW);\r
- }\r
- }\r
-\r
- /* Outer Walls */\r
- for (y = y1 - 1; y <= y2 + 1; y++)\r
- {\r
- c_ptr = &cave[y][x1 - 1];\r
- place_outer_grid(c_ptr);\r
- c_ptr = &cave[y][x2 + 1];\r
- place_outer_grid(c_ptr);\r
- }\r
- for (x = x1 - 1; x <= x2 + 1; x++)\r
- {\r
- c_ptr = &cave[y1 - 1][x];\r
- place_outer_grid(c_ptr);\r
- c_ptr = &cave[y2 + 1][x];\r
- place_outer_grid(c_ptr);\r
- }\r
-\r
-\r
- /* The inner room */\r
- y1 = y1 + 2;\r
- y2 = y2 - 2;\r
- x1 = x1 + 2;\r
- x2 = x2 - 2;\r
-\r
- /* The inner walls */\r
- for (y = y1 - 1; y <= y2 + 1; y++)\r
- {\r
- c_ptr = &cave[y][x1 - 1];\r
- place_inner_grid(c_ptr);\r
- c_ptr = &cave[y][x2 + 1];\r
- place_inner_grid(c_ptr);\r
- }\r
- for (x = x1 - 1; x <= x2 + 1; x++)\r
- {\r
- c_ptr = &cave[y1 - 1][x];\r
- place_inner_grid(c_ptr);\r
- c_ptr = &cave[y2 + 1][x];\r
- place_inner_grid(c_ptr);\r
- }\r
-\r
-\r
- /* Inner room variations */\r
- switch (randint1(5))\r
- {\r
- /* Just an inner room with a monster */\r
- case 1:\r
- {\r
- /* Place a secret door */\r
- switch (randint1(4))\r
- {\r
- case 1: place_secret_door(y1 - 1, xval, DOOR_DEFAULT); break;\r
- case 2: place_secret_door(y2 + 1, xval, DOOR_DEFAULT); break;\r
- case 3: place_secret_door(yval, x1 - 1, DOOR_DEFAULT); break;\r
- case 4: place_secret_door(yval, x2 + 1, DOOR_DEFAULT); break;\r
- }\r
-\r
- /* Place a monster in the room */\r
- vault_monsters(yval, xval, 1);\r
-\r
- break;\r
- }\r
-\r
- /* Treasure Vault (with a door) */\r
- case 2:\r
- {\r
- /* Place a secret door */\r
- switch (randint1(4))\r
- {\r
- case 1: place_secret_door(y1 - 1, xval, DOOR_DEFAULT); break;\r
- case 2: place_secret_door(y2 + 1, xval, DOOR_DEFAULT); break;\r
- case 3: place_secret_door(yval, x1 - 1, DOOR_DEFAULT); break;\r
- case 4: place_secret_door(yval, x2 + 1, DOOR_DEFAULT); break;\r
- }\r
-\r
- /* Place another inner room */\r
- for (y = yval - 1; y <= yval + 1; y++)\r
- {\r
- for (x = xval - 1; x <= xval + 1; x++)\r
- {\r
- if ((x == xval) && (y == yval)) continue;\r
- c_ptr = &cave[y][x];\r
- place_inner_grid(c_ptr);\r
- }\r
- }\r
-\r
- /* Place a locked door on the inner room */\r
- switch (randint1(4))\r
- {\r
- case 1: place_locked_door(yval - 1, xval); break;\r
- case 2: place_locked_door(yval + 1, xval); break;\r
- case 3: place_locked_door(yval, xval - 1); break;\r
- case 4: place_locked_door(yval, xval + 1); break;\r
- }\r
-\r
- /* Monsters to guard the "treasure" */\r
- vault_monsters(yval, xval, randint1(3) + 2);\r
-\r
- /* Object (80%) */\r
- if (randint0(100) < 80)\r
- {\r
- place_object(yval, xval, 0L);\r
- }\r
-\r
- /* Stairs (20%) */\r
- else\r
- {\r
- place_random_stairs(yval, xval);\r
- }\r
-\r
- /* Traps to protect the treasure */\r
- vault_traps(yval, xval, 4, 10, 2 + randint1(3));\r
-\r
- break;\r
- }\r
-\r
- /* Inner pillar(s). */\r
- case 3:\r
- {\r
- /* Place a secret door */\r
- switch (randint1(4))\r
- {\r
- case 1: place_secret_door(y1 - 1, xval, DOOR_DEFAULT); break;\r
- case 2: place_secret_door(y2 + 1, xval, DOOR_DEFAULT); break;\r
- case 3: place_secret_door(yval, x1 - 1, DOOR_DEFAULT); break;\r
- case 4: place_secret_door(yval, x2 + 1, DOOR_DEFAULT); break;\r
- }\r
-\r
- /* Large Inner Pillar */\r
- for (y = yval - 1; y <= yval + 1; y++)\r
- {\r
- for (x = xval - 1; x <= xval + 1; x++)\r
- {\r
- c_ptr = &cave[y][x];\r
- place_inner_grid(c_ptr);\r
- }\r
- }\r
-\r
- /* Occasionally, two more Large Inner Pillars */\r
- if (one_in_(2))\r
- {\r
- tmp = randint1(2);\r
- for (y = yval - 1; y <= yval + 1; y++)\r
- {\r
- for (x = xval - 5 - tmp; x <= xval - 3 - tmp; x++)\r
- {\r
- c_ptr = &cave[y][x];\r
- place_inner_grid(c_ptr);\r
- }\r
- for (x = xval + 3 + tmp; x <= xval + 5 + tmp; x++)\r
- {\r
- c_ptr = &cave[y][x];\r
- place_inner_grid(c_ptr);\r
- }\r
- }\r
- }\r
-\r
- /* Occasionally, some Inner rooms */\r
- if (one_in_(3))\r
- {\r
- int door_type = ((d_info[p_ptr->dungeon_idx].flags1 & DF1_CURTAIN) &&\r
- one_in_((d_info[p_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :\r
- ((d_info[p_ptr->dungeon_idx].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);\r
-\r
- /* Long horizontal walls */\r
- for (x = xval - 5; x <= xval + 5; x++)\r
- {\r
- c_ptr = &cave[yval - 1][x];\r
- place_inner_grid(c_ptr);\r
- c_ptr = &cave[yval + 1][x];\r
- place_inner_grid(c_ptr);\r
- }\r
-\r
- /* Close off the left/right edges */\r
- c_ptr = &cave[yval][xval - 5];\r
- place_inner_grid(c_ptr);\r
- c_ptr = &cave[yval][xval + 5];\r
- place_inner_grid(c_ptr);\r
-\r
- /* Secret doors (random top/bottom) */\r
- place_secret_door(yval - 3 + (randint1(2) * 2), xval - 3, door_type);\r
- place_secret_door(yval - 3 + (randint1(2) * 2), xval + 3, door_type);\r
-\r
- /* Monsters */\r
- vault_monsters(yval, xval - 2, randint1(2));\r
- vault_monsters(yval, xval + 2, randint1(2));\r
-\r
- /* Objects */\r
- if (one_in_(3)) place_object(yval, xval - 2, 0L);\r
- if (one_in_(3)) place_object(yval, xval + 2, 0L);\r
- }\r
-\r
- break;\r
- }\r
-\r
- /* Maze inside. */\r
- case 4:\r
- {\r
- /* Place a secret door */\r
- switch (randint1(4))\r
- {\r
- case 1: place_secret_door(y1 - 1, xval, DOOR_DEFAULT); break;\r
- case 2: place_secret_door(y2 + 1, xval, DOOR_DEFAULT); break;\r
- case 3: place_secret_door(yval, x1 - 1, DOOR_DEFAULT); break;\r
- case 4: place_secret_door(yval, x2 + 1, DOOR_DEFAULT); break;\r
- }\r
-\r
- /* Maze (really a checkerboard) */\r
- for (y = y1; y <= y2; y++)\r
- {\r
- for (x = x1; x <= x2; x++)\r
- {\r
- if (0x1 & (x + y))\r
- {\r
- c_ptr = &cave[y][x];\r
- place_inner_grid(c_ptr);\r
- }\r
- }\r
- }\r
-\r
- /* Monsters just love mazes. */\r
- vault_monsters(yval, xval - 5, randint1(3));\r
- vault_monsters(yval, xval + 5, randint1(3));\r
-\r
- /* Traps make them entertaining. */\r
- vault_traps(yval, xval - 3, 2, 8, randint1(3));\r
- vault_traps(yval, xval + 3, 2, 8, randint1(3));\r
-\r
- /* Mazes should have some treasure too. */\r
- vault_objects(yval, xval, 3);\r
-\r
- break;\r
- }\r
-\r
- /* Four small rooms. */\r
- case 5:\r
- {\r
- int door_type = ((d_info[p_ptr->dungeon_idx].flags1 & DF1_CURTAIN) &&\r
- one_in_((d_info[p_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :\r
- ((d_info[p_ptr->dungeon_idx].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);\r
-\r
- /* Inner "cross" */\r
- for (y = y1; y <= y2; y++)\r
- {\r
- c_ptr = &cave[y][xval];\r
- place_inner_grid(c_ptr);\r
- }\r
- for (x = x1; x <= x2; x++)\r
- {\r
- c_ptr = &cave[yval][x];\r
- place_inner_grid(c_ptr);\r
- }\r
-\r
- /* Doors into the rooms */\r
- if (randint0(100) < 50)\r
- {\r
- int i = randint1(10);\r
- place_secret_door(y1 - 1, xval - i, door_type);\r
- place_secret_door(y1 - 1, xval + i, door_type);\r
- place_secret_door(y2 + 1, xval - i, door_type);\r
- place_secret_door(y2 + 1, xval + i, door_type);\r
- }\r
- else\r
- {\r
- int i = randint1(3);\r
- place_secret_door(yval + i, x1 - 1, door_type);\r
- place_secret_door(yval - i, x1 - 1, door_type);\r
- place_secret_door(yval + i, x2 + 1, door_type);\r
- place_secret_door(yval - i, x2 + 1, door_type);\r
- }\r
-\r
- /* Treasure, centered at the center of the cross */\r
- vault_objects(yval, xval, 2 + randint1(2));\r
-\r
- /* Gotta have some monsters. */\r
- vault_monsters(yval + 1, xval - 4, randint1(4));\r
- vault_monsters(yval + 1, xval + 4, randint1(4));\r
- vault_monsters(yval - 1, xval - 4, randint1(4));\r
- vault_monsters(yval - 1, xval + 4, randint1(4));\r
-\r
- break;\r
- }\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
-\r
-/*!\r
-* @brief タイプ11の部屋…円形部屋の生成 / Type 11 -- Build an vertical oval room.\r
-* @return なし\r
-* @details\r
-* For every grid in the possible square, check the distance.\n\r
-* If it's less than the radius, make it a room square.\n\r
-*\n\r
-* When done fill from the inside to find the walls,\n\r
-*/\r
-bool build_type11(void)\r
-{\r
- POSITION rad, x, y, x0, y0;\r
- int light = FALSE;\r
-\r
- /* Occasional light */\r
- if ((randint1(dun_level) <= 15) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS)) light = TRUE;\r
-\r
- rad = randint0(9);\r
-\r
- /* Find and reserve some space in the dungeon. Get center of room. */\r
- if (!find_space(&y0, &x0, rad * 2 + 1, rad * 2 + 1)) return FALSE;\r
-\r
- /* Make circular floor */\r
- for (x = x0 - rad; x <= x0 + rad; x++)\r
- {\r
- for (y = y0 - rad; y <= y0 + rad; y++)\r
- {\r
- if (distance(y0, x0, y, x) <= rad - 1)\r
- {\r
- /* inside- so is floor */\r
- place_floor_bold(y, x);\r
- }\r
- else if (distance(y0, x0, y, x) <= rad + 1)\r
- {\r
- /* make granite outside so arena works */\r
- place_extra_bold(y, x);\r
- }\r
- }\r
- }\r
-\r
- /* Find visible outer walls and set to be FEAT_OUTER */\r
- add_outer_wall(x0, y0, light, x0 - rad, y0 - rad, x0 + rad, y0 + rad);\r
-\r
- return TRUE;\r
-}\r
-\r
-\r
-/*!\r
-* @brief タイプ12の部屋…ドーム型部屋の生成 / Type 12 -- Build crypt room.\r
-* @return なし\r
-* @details\r
-* For every grid in the possible square, check the (fake) distance.\n\r
-* If it's less than the radius, make it a room square.\n\r
-*\n\r
-* When done fill from the inside to find the walls,\n\r
-*/\r
-bool build_type12(void)\r
-{\r
- POSITION rad, x, y, x0, y0;\r
- int light = FALSE;\r
- bool emptyflag = TRUE;\r
-\r
- /* Make a random metric */\r
- POSITION h1, h2, h3, h4;\r
- h1 = randint1(32) - 16;\r
- h2 = randint1(16);\r
- h3 = randint1(32);\r
- h4 = randint1(32) - 16;\r
-\r
- /* Occasional light */\r
- if ((randint1(dun_level) <= 5) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS)) light = TRUE;\r
-\r
- rad = randint1(9);\r
-\r
- /* Find and reserve some space in the dungeon. Get center of room. */\r
- if (!find_space(&y0, &x0, rad * 2 + 3, rad * 2 + 3)) return FALSE;\r
-\r
- /* Make floor */\r
- for (x = x0 - rad; x <= x0 + rad; x++)\r
- {\r
- for (y = y0 - rad; y <= y0 + rad; y++)\r
- {\r
- /* clear room flag */\r
- cave[y][x].info &= ~(CAVE_ROOM);\r
-\r
- if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)\r
- {\r
- /* inside - so is floor */\r
- place_floor_bold(y, x);\r
- }\r
- else if (distance(y0, x0, y, x) < 3)\r
- {\r
- place_floor_bold(y, x);\r
- }\r
- else\r
- {\r
- /* make granite outside so arena works */\r
- place_extra_bold(y, x);\r
- }\r
-\r
- /* proper boundary for arena */\r
- if (((y + rad) == y0) || ((y - rad) == y0) ||\r
- ((x + rad) == x0) || ((x - rad) == x0))\r
- {\r
- place_extra_bold(y, x);\r
- }\r
- }\r
- }\r
-\r
- /* Find visible outer walls and set to be FEAT_OUTER */\r
- add_outer_wall(x0, y0, light, x0 - rad - 1, y0 - rad - 1,\r
- x0 + rad + 1, y0 + rad + 1);\r
-\r
- /* Check to see if there is room for an inner vault */\r
- for (x = x0 - 2; x <= x0 + 2; x++)\r
- {\r
- for (y = y0 - 2; y <= y0 + 2; y++)\r
- {\r
- if (!is_floor_bold(y, x))\r
- {\r
- /* Wall in the way */\r
- emptyflag = FALSE;\r
- }\r
- }\r
- }\r
-\r
- if (emptyflag && one_in_(2))\r
- {\r
- /* Build the vault */\r
- build_small_room(x0, y0);\r
-\r
- /* Place a treasure in the vault */\r
- place_object(y0, x0, 0L);\r
-\r
- /* Let's guard the treasure well */\r
- vault_monsters(y0, x0, randint0(2) + 3);\r
-\r
- /* Traps naturally */\r
- vault_traps(y0, x0, 4, 4, randint0(3) + 2);\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
+#include "angband.h"
+#include "grid.h"
+#include "trap.h"
+
+#include "rooms.h"
+
+
+/*!
+* @brief タイプ1の部屋…通常可変長方形の部屋を生成する / Type 1 -- normal rectangular rooms
+* @return なし
+*/
+bool build_type1(void)
+{
+ POSITION y, x, y2, x2, yval, xval;
+ POSITION y1, x1, xsize, ysize;
+
+ bool light;
+
+ cave_type *c_ptr;
+
+ bool curtain = (d_info[p_ptr->dungeon_idx].flags1 & DF1_CURTAIN) &&
+ one_in_((d_info[p_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) ? 48 : 512);
+
+ /* Pick a room size */
+ y1 = randint1(4);
+ x1 = randint1(11);
+ y2 = randint1(3);
+ x2 = randint1(11);
+
+ xsize = x1 + x2 + 1;
+ ysize = y1 + y2 + 1;
+
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&yval, &xval, ysize + 2, xsize + 2))
+ {
+ /* Limit to the minimum room size, and retry */
+ y1 = 1;
+ x1 = 1;
+ y2 = 1;
+ x2 = 1;
+
+ xsize = x1 + x2 + 1;
+ ysize = y1 + y2 + 1;
+
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&yval, &xval, ysize + 2, xsize + 2)) return FALSE;
+ }
+
+ /* Choose lite or dark */
+ light = ((dun_level <= randint1(25)) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS));
+
+
+ /* Get corner values */
+ y1 = yval - ysize / 2;
+ x1 = xval - xsize / 2;
+ y2 = yval + (ysize - 1) / 2;
+ x2 = xval + (xsize - 1) / 2;
+
+
+ /* Place a full floor under the room */
+ for (y = y1 - 1; y <= y2 + 1; y++)
+ {
+ for (x = x1 - 1; x <= x2 + 1; x++)
+ {
+ c_ptr = &cave[y][x];
+ place_floor_grid(c_ptr);
+ c_ptr->info |= (CAVE_ROOM);
+ if (light) c_ptr->info |= (CAVE_GLOW);
+ }
+ }
+
+ /* Walls around the room */
+ for (y = y1 - 1; y <= y2 + 1; y++)
+ {
+ c_ptr = &cave[y][x1 - 1];
+ place_outer_grid(c_ptr);
+ c_ptr = &cave[y][x2 + 1];
+ place_outer_grid(c_ptr);
+ }
+ for (x = x1 - 1; x <= x2 + 1; x++)
+ {
+ c_ptr = &cave[y1 - 1][x];
+ place_outer_grid(c_ptr);
+ c_ptr = &cave[y2 + 1][x];
+ place_outer_grid(c_ptr);
+ }
+
+
+ /* Hack -- Occasional curtained room */
+ if (curtain && (y2 - y1 > 2) && (x2 - x1 > 2))
+ {
+ for (y = y1; y <= y2; y++)
+ {
+ c_ptr = &cave[y][x1];
+ c_ptr->feat = feat_door[DOOR_CURTAIN].closed;
+ c_ptr->info &= ~(CAVE_MASK);
+ c_ptr = &cave[y][x2];
+ c_ptr->feat = feat_door[DOOR_CURTAIN].closed;
+ c_ptr->info &= ~(CAVE_MASK);
+ }
+ for (x = x1; x <= x2; x++)
+ {
+ c_ptr = &cave[y1][x];
+ c_ptr->feat = feat_door[DOOR_CURTAIN].closed;
+ c_ptr->info &= ~(CAVE_MASK);
+ c_ptr = &cave[y2][x];
+ c_ptr->feat = feat_door[DOOR_CURTAIN].closed;
+ c_ptr->info &= ~(CAVE_MASK);
+ }
+ }
+
+
+ /* Hack -- Occasional pillar room */
+ if (one_in_(20))
+ {
+ for (y = y1; y <= y2; y += 2)
+ {
+ for (x = x1; x <= x2; x += 2)
+ {
+ c_ptr = &cave[y][x];
+ place_inner_grid(c_ptr);
+ }
+ }
+ }
+
+ /* Hack -- Occasional room with four pillars */
+ else if (one_in_(20))
+ {
+ if ((y1 + 4 < y2) && (x1 + 4 < x2))
+ {
+ c_ptr = &cave[y1 + 1][x1 + 1];
+ place_inner_grid(c_ptr);
+
+ c_ptr = &cave[y1 + 1][x2 - 1];
+ place_inner_grid(c_ptr);
+
+ c_ptr = &cave[y2 - 1][x1 + 1];
+ place_inner_grid(c_ptr);
+
+ c_ptr = &cave[y2 - 1][x2 - 1];
+ place_inner_grid(c_ptr);
+ }
+ }
+
+ /* Hack -- Occasional ragged-edge room */
+ else if (one_in_(50))
+ {
+ for (y = y1 + 2; y <= y2 - 2; y += 2)
+ {
+ c_ptr = &cave[y][x1];
+ place_inner_grid(c_ptr);
+ c_ptr = &cave[y][x2];
+ place_inner_grid(c_ptr);
+ }
+ for (x = x1 + 2; x <= x2 - 2; x += 2)
+ {
+ c_ptr = &cave[y1][x];
+ place_inner_grid(c_ptr);
+ c_ptr = &cave[y2][x];
+ place_inner_grid(c_ptr);
+ }
+ }
+ /* Hack -- Occasional divided room */
+ else if (one_in_(50))
+ {
+ bool curtain2 = (d_info[p_ptr->dungeon_idx].flags1 & DF1_CURTAIN) &&
+ one_in_((d_info[p_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) ? 2 : 128);
+
+ if (randint1(100) < 50)
+ {
+ /* Horizontal wall */
+ for (x = x1; x <= x2; x++)
+ {
+ place_inner_bold(yval, x);
+ if (curtain2) cave[yval][x].feat = feat_door[DOOR_CURTAIN].closed;
+ }
+
+ /* Prevent edge of wall from being tunneled */
+ place_solid_bold(yval, x1 - 1);
+ place_solid_bold(yval, x2 + 1);
+ }
+ else
+ {
+ /* Vertical wall */
+ for (y = y1; y <= y2; y++)
+ {
+ place_inner_bold(y, xval);
+ if (curtain2) cave[y][xval].feat = feat_door[DOOR_CURTAIN].closed;
+ }
+
+ /* Prevent edge of wall from being tunneled */
+ place_solid_bold(y1 - 1, xval);
+ place_solid_bold(y2 + 1, xval);
+ }
+
+ place_random_door(yval, xval, TRUE);
+ if (curtain2) cave[yval][xval].feat = feat_door[DOOR_CURTAIN].closed;
+ }
+
+ return TRUE;
+}
+
+/*!
+* @brief タイプ2の部屋…二重長方形の部屋を生成する / Type 2 -- Overlapping rectangular rooms
+* @return なし
+*/
+bool build_type2(void)
+{
+ POSITION y, x, xval, yval;
+ POSITION y1a, x1a, y2a, x2a;
+ POSITION y1b, x1b, y2b, x2b;
+ bool light;
+ cave_type *c_ptr;
+
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&yval, &xval, 11, 25)) return FALSE;
+
+ /* Choose lite or dark */
+ light = ((dun_level <= randint1(25)) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS));
+
+ /* Determine extents of the first room */
+ y1a = yval - randint1(4);
+ y2a = yval + randint1(3);
+ x1a = xval - randint1(11);
+ x2a = xval + randint1(10);
+
+ /* Determine extents of the second room */
+ y1b = yval - randint1(3);
+ y2b = yval + randint1(4);
+ x1b = xval - randint1(10);
+ x2b = xval + randint1(11);
+
+
+ /* Place a full floor for room "a" */
+ for (y = y1a - 1; y <= y2a + 1; y++)
+ {
+ for (x = x1a - 1; x <= x2a + 1; x++)
+ {
+ c_ptr = &cave[y][x];
+ place_floor_grid(c_ptr);
+ c_ptr->info |= (CAVE_ROOM);
+ if (light) c_ptr->info |= (CAVE_GLOW);
+ }
+ }
+
+ /* Place a full floor for room "b" */
+ for (y = y1b - 1; y <= y2b + 1; y++)
+ {
+ for (x = x1b - 1; x <= x2b + 1; x++)
+ {
+ c_ptr = &cave[y][x];
+ place_floor_grid(c_ptr);
+ c_ptr->info |= (CAVE_ROOM);
+ if (light) c_ptr->info |= (CAVE_GLOW);
+ }
+ }
+
+
+ /* Place the walls around room "a" */
+ for (y = y1a - 1; y <= y2a + 1; y++)
+ {
+ c_ptr = &cave[y][x1a - 1];
+ place_outer_grid(c_ptr);
+ c_ptr = &cave[y][x2a + 1];
+ place_outer_grid(c_ptr);
+ }
+ for (x = x1a - 1; x <= x2a + 1; x++)
+ {
+ c_ptr = &cave[y1a - 1][x];
+ place_outer_grid(c_ptr);
+ c_ptr = &cave[y2a + 1][x];
+ place_outer_grid(c_ptr);
+ }
+
+ /* Place the walls around room "b" */
+ for (y = y1b - 1; y <= y2b + 1; y++)
+ {
+ c_ptr = &cave[y][x1b - 1];
+ place_outer_grid(c_ptr);
+ c_ptr = &cave[y][x2b + 1];
+ place_outer_grid(c_ptr);
+ }
+ for (x = x1b - 1; x <= x2b + 1; x++)
+ {
+ c_ptr = &cave[y1b - 1][x];
+ place_outer_grid(c_ptr);
+ c_ptr = &cave[y2b + 1][x];
+ place_outer_grid(c_ptr);
+ }
+
+
+
+ /* Replace the floor for room "a" */
+ for (y = y1a; y <= y2a; y++)
+ {
+ for (x = x1a; x <= x2a; x++)
+ {
+ c_ptr = &cave[y][x];
+ place_floor_grid(c_ptr);
+ }
+ }
+
+ /* Replace the floor for room "b" */
+ for (y = y1b; y <= y2b; y++)
+ {
+ for (x = x1b; x <= x2b; x++)
+ {
+ c_ptr = &cave[y][x];
+ place_floor_grid(c_ptr);
+ }
+ }
+
+ return TRUE;
+}
+
+/*!
+* @brief タイプ3の部屋…十字型の部屋を生成する / Type 3 -- Cross shaped rooms
+* @return なし
+* @details
+* Builds a room at a row, column coordinate\n
+*\n
+* Room "a" runs north/south, and Room "b" runs east/east\n
+* So the "central pillar" runs from x1a, y1b to x2a, y2b.\n
+*\n
+* Note that currently, the "center" is always 3x3, but I think that\n
+* the code below will work (with "bounds checking") for 5x5, or even\n
+* for unsymetric values like 4x3 or 5x3 or 3x4 or 3x5, or even larger.\n
+*/
+bool build_type3(void)
+{
+ POSITION y, x, dy, dx, wy, wx;
+ POSITION y1a, x1a, y2a, x2a;
+ POSITION y1b, x1b, y2b, x2b;
+ POSITION yval, xval;
+ bool light;
+ cave_type *c_ptr;
+
+
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&yval, &xval, 11, 25)) return FALSE;
+
+
+ /* Choose lite or dark */
+ light = ((dun_level <= randint1(25)) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS));
+
+ /* For now, always 3x3 */
+ wx = wy = 1;
+
+ /* Pick max vertical size (at most 4) */
+ dy = rand_range(3, 4);
+
+ /* Pick max horizontal size (at most 15) */
+ dx = rand_range(3, 11);
+
+
+ /* Determine extents of the north/south room */
+ y1a = yval - dy;
+ y2a = yval + dy;
+ x1a = xval - wx;
+ x2a = xval + wx;
+
+ /* Determine extents of the east/west room */
+ y1b = yval - wy;
+ y2b = yval + wy;
+ x1b = xval - dx;
+ x2b = xval + dx;
+
+
+ /* Place a full floor for room "a" */
+ for (y = y1a - 1; y <= y2a + 1; y++)
+ {
+ for (x = x1a - 1; x <= x2a + 1; x++)
+ {
+ c_ptr = &cave[y][x];
+ place_floor_grid(c_ptr);
+ c_ptr->info |= (CAVE_ROOM);
+ if (light) c_ptr->info |= (CAVE_GLOW);
+ }
+ }
+
+ /* Place a full floor for room "b" */
+ for (y = y1b - 1; y <= y2b + 1; y++)
+ {
+ for (x = x1b - 1; x <= x2b + 1; x++)
+ {
+ c_ptr = &cave[y][x];
+ place_floor_grid(c_ptr);
+ c_ptr->info |= (CAVE_ROOM);
+ if (light) c_ptr->info |= (CAVE_GLOW);
+ }
+ }
+
+
+ /* Place the walls around room "a" */
+ for (y = y1a - 1; y <= y2a + 1; y++)
+ {
+ c_ptr = &cave[y][x1a - 1];
+ place_outer_grid(c_ptr);
+ c_ptr = &cave[y][x2a + 1];
+ place_outer_grid(c_ptr);
+ }
+ for (x = x1a - 1; x <= x2a + 1; x++)
+ {
+ c_ptr = &cave[y1a - 1][x];
+ place_outer_grid(c_ptr);
+ c_ptr = &cave[y2a + 1][x];
+ place_outer_grid(c_ptr);
+ }
+
+ /* Place the walls around room "b" */
+ for (y = y1b - 1; y <= y2b + 1; y++)
+ {
+ c_ptr = &cave[y][x1b - 1];
+ place_outer_grid(c_ptr);
+ c_ptr = &cave[y][x2b + 1];
+ place_outer_grid(c_ptr);
+ }
+ for (x = x1b - 1; x <= x2b + 1; x++)
+ {
+ c_ptr = &cave[y1b - 1][x];
+ place_outer_grid(c_ptr);
+ c_ptr = &cave[y2b + 1][x];
+ place_outer_grid(c_ptr);
+ }
+
+
+ /* Replace the floor for room "a" */
+ for (y = y1a; y <= y2a; y++)
+ {
+ for (x = x1a; x <= x2a; x++)
+ {
+ c_ptr = &cave[y][x];
+ place_floor_grid(c_ptr);
+ }
+ }
+
+ /* Replace the floor for room "b" */
+ for (y = y1b; y <= y2b; y++)
+ {
+ for (x = x1b; x <= x2b; x++)
+ {
+ c_ptr = &cave[y][x];
+ place_floor_grid(c_ptr);
+ }
+ }
+
+
+
+ /* Special features (3/4) */
+ switch (randint0(4))
+ {
+ /* Large solid middle pillar */
+ case 1:
+ {
+ for (y = y1b; y <= y2b; y++)
+ {
+ for (x = x1a; x <= x2a; x++)
+ {
+ c_ptr = &cave[y][x];
+ place_inner_grid(c_ptr);
+ }
+ }
+ break;
+ }
+
+ /* Inner treasure vault */
+ case 2:
+ {
+ /* Build the vault */
+ for (y = y1b; y <= y2b; y++)
+ {
+ c_ptr = &cave[y][x1a];
+ place_inner_grid(c_ptr);
+ c_ptr = &cave[y][x2a];
+ place_inner_grid(c_ptr);
+ }
+ for (x = x1a; x <= x2a; x++)
+ {
+ c_ptr = &cave[y1b][x];
+ place_inner_grid(c_ptr);
+ c_ptr = &cave[y2b][x];
+ place_inner_grid(c_ptr);
+ }
+
+ /* Place a secret door on the inner room */
+ switch (randint0(4))
+ {
+ case 0: place_secret_door(y1b, xval, DOOR_DEFAULT); break;
+ case 1: place_secret_door(y2b, xval, DOOR_DEFAULT); break;
+ case 2: place_secret_door(yval, x1a, DOOR_DEFAULT); break;
+ case 3: place_secret_door(yval, x2a, DOOR_DEFAULT); break;
+ }
+
+ /* Place a treasure in the vault */
+ place_object(yval, xval, 0L);
+
+ /* Let's guard the treasure well */
+ vault_monsters(yval, xval, randint0(2) + 3);
+
+ /* Traps naturally */
+ vault_traps(yval, xval, 4, 4, randint0(3) + 2);
+
+ break;
+ }
+
+ /* Something else */
+ case 3:
+ {
+ /* Occasionally pinch the center shut */
+ if (one_in_(3))
+ {
+ /* Pinch the east/west sides */
+ for (y = y1b; y <= y2b; y++)
+ {
+ if (y == yval) continue;
+ c_ptr = &cave[y][x1a - 1];
+ place_inner_grid(c_ptr);
+ c_ptr = &cave[y][x2a + 1];
+ place_inner_grid(c_ptr);
+ }
+
+ /* Pinch the north/south sides */
+ for (x = x1a; x <= x2a; x++)
+ {
+ if (x == xval) continue;
+ c_ptr = &cave[y1b - 1][x];
+ place_inner_grid(c_ptr);
+ c_ptr = &cave[y2b + 1][x];
+ place_inner_grid(c_ptr);
+ }
+
+ /* Sometimes shut using secret doors */
+ if (one_in_(3))
+ {
+ int door_type = ((d_info[p_ptr->dungeon_idx].flags1 & DF1_CURTAIN) &&
+ one_in_((d_info[p_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :
+ ((d_info[p_ptr->dungeon_idx].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);
+
+ place_secret_door(yval, x1a - 1, door_type);
+ place_secret_door(yval, x2a + 1, door_type);
+ place_secret_door(y1b - 1, xval, door_type);
+ place_secret_door(y2b + 1, xval, door_type);
+ }
+ }
+
+ /* Occasionally put a "plus" in the center */
+ else if (one_in_(3))
+ {
+ c_ptr = &cave[yval][xval];
+ place_inner_grid(c_ptr);
+ c_ptr = &cave[y1b][xval];
+ place_inner_grid(c_ptr);
+ c_ptr = &cave[y2b][xval];
+ place_inner_grid(c_ptr);
+ c_ptr = &cave[yval][x1a];
+ place_inner_grid(c_ptr);
+ c_ptr = &cave[yval][x2a];
+ place_inner_grid(c_ptr);
+ }
+
+ /* Occasionally put a pillar in the center */
+ else if (one_in_(3))
+ {
+ c_ptr = &cave[yval][xval];
+ place_inner_grid(c_ptr);
+ }
+
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+/*!
+* @brief タイプ4の部屋…固定サイズの二重構造部屋を生成する / Type 4 -- Large room with inner features
+* @return なし
+* @details
+* Possible sub-types:\n
+* 1 - Just an inner room with one door\n
+* 2 - An inner room within an inner room\n
+* 3 - An inner room with pillar(s)\n
+* 4 - Inner room has a maze\n
+* 5 - A set of four inner rooms\n
+*/
+bool build_type4(void)
+{
+ POSITION y, x, y1, x1;
+ POSITION y2, x2, tmp, yval, xval;
+ bool light;
+ cave_type *c_ptr;
+
+
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&yval, &xval, 11, 25)) return FALSE;
+
+ /* Choose lite or dark */
+ light = ((dun_level <= randint1(25)) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS));
+
+ /* Large room */
+ y1 = yval - 4;
+ y2 = yval + 4;
+ x1 = xval - 11;
+ x2 = xval + 11;
+
+ /* Place a full floor under the room */
+ for (y = y1 - 1; y <= y2 + 1; y++)
+ {
+ for (x = x1 - 1; x <= x2 + 1; x++)
+ {
+ c_ptr = &cave[y][x];
+ place_floor_grid(c_ptr);
+ c_ptr->info |= (CAVE_ROOM);
+ if (light) c_ptr->info |= (CAVE_GLOW);
+ }
+ }
+
+ /* Outer Walls */
+ for (y = y1 - 1; y <= y2 + 1; y++)
+ {
+ c_ptr = &cave[y][x1 - 1];
+ place_outer_grid(c_ptr);
+ c_ptr = &cave[y][x2 + 1];
+ place_outer_grid(c_ptr);
+ }
+ for (x = x1 - 1; x <= x2 + 1; x++)
+ {
+ c_ptr = &cave[y1 - 1][x];
+ place_outer_grid(c_ptr);
+ c_ptr = &cave[y2 + 1][x];
+ place_outer_grid(c_ptr);
+ }
+
+
+ /* The inner room */
+ y1 = y1 + 2;
+ y2 = y2 - 2;
+ x1 = x1 + 2;
+ x2 = x2 - 2;
+
+ /* The inner walls */
+ for (y = y1 - 1; y <= y2 + 1; y++)
+ {
+ c_ptr = &cave[y][x1 - 1];
+ place_inner_grid(c_ptr);
+ c_ptr = &cave[y][x2 + 1];
+ place_inner_grid(c_ptr);
+ }
+ for (x = x1 - 1; x <= x2 + 1; x++)
+ {
+ c_ptr = &cave[y1 - 1][x];
+ place_inner_grid(c_ptr);
+ c_ptr = &cave[y2 + 1][x];
+ place_inner_grid(c_ptr);
+ }
+
+
+ /* Inner room variations */
+ switch (randint1(5))
+ {
+ /* Just an inner room with a monster */
+ case 1:
+ {
+ /* Place a secret door */
+ switch (randint1(4))
+ {
+ case 1: place_secret_door(y1 - 1, xval, DOOR_DEFAULT); break;
+ case 2: place_secret_door(y2 + 1, xval, DOOR_DEFAULT); break;
+ case 3: place_secret_door(yval, x1 - 1, DOOR_DEFAULT); break;
+ case 4: place_secret_door(yval, x2 + 1, DOOR_DEFAULT); break;
+ }
+
+ /* Place a monster in the room */
+ vault_monsters(yval, xval, 1);
+
+ break;
+ }
+
+ /* Treasure Vault (with a door) */
+ case 2:
+ {
+ /* Place a secret door */
+ switch (randint1(4))
+ {
+ case 1: place_secret_door(y1 - 1, xval, DOOR_DEFAULT); break;
+ case 2: place_secret_door(y2 + 1, xval, DOOR_DEFAULT); break;
+ case 3: place_secret_door(yval, x1 - 1, DOOR_DEFAULT); break;
+ case 4: place_secret_door(yval, x2 + 1, DOOR_DEFAULT); break;
+ }
+
+ /* Place another inner room */
+ for (y = yval - 1; y <= yval + 1; y++)
+ {
+ for (x = xval - 1; x <= xval + 1; x++)
+ {
+ if ((x == xval) && (y == yval)) continue;
+ c_ptr = &cave[y][x];
+ place_inner_grid(c_ptr);
+ }
+ }
+
+ /* Place a locked door on the inner room */
+ switch (randint1(4))
+ {
+ case 1: place_locked_door(yval - 1, xval); break;
+ case 2: place_locked_door(yval + 1, xval); break;
+ case 3: place_locked_door(yval, xval - 1); break;
+ case 4: place_locked_door(yval, xval + 1); break;
+ }
+
+ /* Monsters to guard the "treasure" */
+ vault_monsters(yval, xval, randint1(3) + 2);
+
+ /* Object (80%) */
+ if (randint0(100) < 80)
+ {
+ place_object(yval, xval, 0L);
+ }
+
+ /* Stairs (20%) */
+ else
+ {
+ place_random_stairs(yval, xval);
+ }
+
+ /* Traps to protect the treasure */
+ vault_traps(yval, xval, 4, 10, 2 + randint1(3));
+
+ break;
+ }
+
+ /* Inner pillar(s). */
+ case 3:
+ {
+ /* Place a secret door */
+ switch (randint1(4))
+ {
+ case 1: place_secret_door(y1 - 1, xval, DOOR_DEFAULT); break;
+ case 2: place_secret_door(y2 + 1, xval, DOOR_DEFAULT); break;
+ case 3: place_secret_door(yval, x1 - 1, DOOR_DEFAULT); break;
+ case 4: place_secret_door(yval, x2 + 1, DOOR_DEFAULT); break;
+ }
+
+ /* Large Inner Pillar */
+ for (y = yval - 1; y <= yval + 1; y++)
+ {
+ for (x = xval - 1; x <= xval + 1; x++)
+ {
+ c_ptr = &cave[y][x];
+ place_inner_grid(c_ptr);
+ }
+ }
+
+ /* Occasionally, two more Large Inner Pillars */
+ if (one_in_(2))
+ {
+ tmp = randint1(2);
+ for (y = yval - 1; y <= yval + 1; y++)
+ {
+ for (x = xval - 5 - tmp; x <= xval - 3 - tmp; x++)
+ {
+ c_ptr = &cave[y][x];
+ place_inner_grid(c_ptr);
+ }
+ for (x = xval + 3 + tmp; x <= xval + 5 + tmp; x++)
+ {
+ c_ptr = &cave[y][x];
+ place_inner_grid(c_ptr);
+ }
+ }
+ }
+
+ /* Occasionally, some Inner rooms */
+ if (one_in_(3))
+ {
+ int door_type = ((d_info[p_ptr->dungeon_idx].flags1 & DF1_CURTAIN) &&
+ one_in_((d_info[p_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :
+ ((d_info[p_ptr->dungeon_idx].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);
+
+ /* Long horizontal walls */
+ for (x = xval - 5; x <= xval + 5; x++)
+ {
+ c_ptr = &cave[yval - 1][x];
+ place_inner_grid(c_ptr);
+ c_ptr = &cave[yval + 1][x];
+ place_inner_grid(c_ptr);
+ }
+
+ /* Close off the left/right edges */
+ c_ptr = &cave[yval][xval - 5];
+ place_inner_grid(c_ptr);
+ c_ptr = &cave[yval][xval + 5];
+ place_inner_grid(c_ptr);
+
+ /* Secret doors (random top/bottom) */
+ place_secret_door(yval - 3 + (randint1(2) * 2), xval - 3, door_type);
+ place_secret_door(yval - 3 + (randint1(2) * 2), xval + 3, door_type);
+
+ /* Monsters */
+ vault_monsters(yval, xval - 2, randint1(2));
+ vault_monsters(yval, xval + 2, randint1(2));
+
+ /* Objects */
+ if (one_in_(3)) place_object(yval, xval - 2, 0L);
+ if (one_in_(3)) place_object(yval, xval + 2, 0L);
+ }
+
+ break;
+ }
+
+ /* Maze inside. */
+ case 4:
+ {
+ /* Place a secret door */
+ switch (randint1(4))
+ {
+ case 1: place_secret_door(y1 - 1, xval, DOOR_DEFAULT); break;
+ case 2: place_secret_door(y2 + 1, xval, DOOR_DEFAULT); break;
+ case 3: place_secret_door(yval, x1 - 1, DOOR_DEFAULT); break;
+ case 4: place_secret_door(yval, x2 + 1, DOOR_DEFAULT); break;
+ }
+
+ /* Maze (really a checkerboard) */
+ for (y = y1; y <= y2; y++)
+ {
+ for (x = x1; x <= x2; x++)
+ {
+ if (0x1 & (x + y))
+ {
+ c_ptr = &cave[y][x];
+ place_inner_grid(c_ptr);
+ }
+ }
+ }
+
+ /* Monsters just love mazes. */
+ vault_monsters(yval, xval - 5, randint1(3));
+ vault_monsters(yval, xval + 5, randint1(3));
+
+ /* Traps make them entertaining. */
+ vault_traps(yval, xval - 3, 2, 8, randint1(3));
+ vault_traps(yval, xval + 3, 2, 8, randint1(3));
+
+ /* Mazes should have some treasure too. */
+ vault_objects(yval, xval, 3);
+
+ break;
+ }
+
+ /* Four small rooms. */
+ case 5:
+ {
+ int door_type = ((d_info[p_ptr->dungeon_idx].flags1 & DF1_CURTAIN) &&
+ one_in_((d_info[p_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :
+ ((d_info[p_ptr->dungeon_idx].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);
+
+ /* Inner "cross" */
+ for (y = y1; y <= y2; y++)
+ {
+ c_ptr = &cave[y][xval];
+ place_inner_grid(c_ptr);
+ }
+ for (x = x1; x <= x2; x++)
+ {
+ c_ptr = &cave[yval][x];
+ place_inner_grid(c_ptr);
+ }
+
+ /* Doors into the rooms */
+ if (randint0(100) < 50)
+ {
+ int i = randint1(10);
+ place_secret_door(y1 - 1, xval - i, door_type);
+ place_secret_door(y1 - 1, xval + i, door_type);
+ place_secret_door(y2 + 1, xval - i, door_type);
+ place_secret_door(y2 + 1, xval + i, door_type);
+ }
+ else
+ {
+ int i = randint1(3);
+ place_secret_door(yval + i, x1 - 1, door_type);
+ place_secret_door(yval - i, x1 - 1, door_type);
+ place_secret_door(yval + i, x2 + 1, door_type);
+ place_secret_door(yval - i, x2 + 1, door_type);
+ }
+
+ /* Treasure, centered at the center of the cross */
+ vault_objects(yval, xval, 2 + randint1(2));
+
+ /* Gotta have some monsters. */
+ vault_monsters(yval + 1, xval - 4, randint1(4));
+ vault_monsters(yval + 1, xval + 4, randint1(4));
+ vault_monsters(yval - 1, xval - 4, randint1(4));
+ vault_monsters(yval - 1, xval + 4, randint1(4));
+
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+
+/*!
+* @brief タイプ11の部屋…円形部屋の生成 / Type 11 -- Build an vertical oval room.
+* @return なし
+* @details
+* For every grid in the possible square, check the distance.\n
+* If it's less than the radius, make it a room square.\n
+*\n
+* When done fill from the inside to find the walls,\n
+*/
+bool build_type11(void)
+{
+ POSITION rad, x, y, x0, y0;
+ int light = FALSE;
+
+ /* Occasional light */
+ if ((randint1(dun_level) <= 15) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS)) light = TRUE;
+
+ rad = randint0(9);
+
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&y0, &x0, rad * 2 + 1, rad * 2 + 1)) return FALSE;
+
+ /* Make circular floor */
+ for (x = x0 - rad; x <= x0 + rad; x++)
+ {
+ for (y = y0 - rad; y <= y0 + rad; y++)
+ {
+ if (distance(y0, x0, y, x) <= rad - 1)
+ {
+ /* inside- so is floor */
+ place_floor_bold(y, x);
+ }
+ else if (distance(y0, x0, y, x) <= rad + 1)
+ {
+ /* make granite outside so arena works */
+ place_extra_bold(y, x);
+ }
+ }
+ }
+
+ /* Find visible outer walls and set to be FEAT_OUTER */
+ add_outer_wall(x0, y0, light, x0 - rad, y0 - rad, x0 + rad, y0 + rad);
+
+ return TRUE;
+}
+
+
+/*!
+* @brief タイプ12の部屋…ドーム型部屋の生成 / Type 12 -- Build crypt room.
+* @return なし
+* @details
+* For every grid in the possible square, check the (fake) distance.\n
+* If it's less than the radius, make it a room square.\n
+*\n
+* When done fill from the inside to find the walls,\n
+*/
+bool build_type12(void)
+{
+ POSITION rad, x, y, x0, y0;
+ int light = FALSE;
+ bool emptyflag = TRUE;
+
+ /* Make a random metric */
+ POSITION h1, h2, h3, h4;
+ h1 = randint1(32) - 16;
+ h2 = randint1(16);
+ h3 = randint1(32);
+ h4 = randint1(32) - 16;
+
+ /* Occasional light */
+ if ((randint1(dun_level) <= 5) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS)) light = TRUE;
+
+ rad = randint1(9);
+
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&y0, &x0, rad * 2 + 3, rad * 2 + 3)) return FALSE;
+
+ /* Make floor */
+ for (x = x0 - rad; x <= x0 + rad; x++)
+ {
+ for (y = y0 - rad; y <= y0 + rad; y++)
+ {
+ /* clear room flag */
+ cave[y][x].info &= ~(CAVE_ROOM);
+
+ if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
+ {
+ /* inside - so is floor */
+ place_floor_bold(y, x);
+ }
+ else if (distance(y0, x0, y, x) < 3)
+ {
+ place_floor_bold(y, x);
+ }
+ else
+ {
+ /* make granite outside so arena works */
+ place_extra_bold(y, x);
+ }
+
+ /* proper boundary for arena */
+ if (((y + rad) == y0) || ((y - rad) == y0) ||
+ ((x + rad) == x0) || ((x - rad) == x0))
+ {
+ place_extra_bold(y, x);
+ }
+ }
+ }
+
+ /* Find visible outer walls and set to be FEAT_OUTER */
+ add_outer_wall(x0, y0, light, x0 - rad - 1, y0 - rad - 1,
+ x0 + rad + 1, y0 + rad + 1);
+
+ /* Check to see if there is room for an inner vault */
+ for (x = x0 - 2; x <= x0 + 2; x++)
+ {
+ for (y = y0 - 2; y <= y0 + 2; y++)
+ {
+ if (!is_floor_bold(y, x))
+ {
+ /* Wall in the way */
+ emptyflag = FALSE;
+ }
+ }
+ }
+
+ if (emptyflag && one_in_(2))
+ {
+ /* Build the vault */
+ build_small_room(x0, y0);
+
+ /* Place a treasure in the vault */
+ place_object(y0, x0, 0L);
+
+ /* Let's guard the treasure well */
+ vault_monsters(y0, x0, randint0(2) + 3);
+
+ /* Traps naturally */
+ vault_traps(y0, x0, 4, 4, randint0(3) + 2);
+ }
+
+ return TRUE;
+}
+
-extern bool build_type1(void);\r
-extern bool build_type2(void);\r
-extern bool build_type3(void);\r
-extern bool build_type4(void);\r
-extern bool build_type11(void);\r
-extern bool build_type12(void);\r
+extern bool build_type1(void);
+extern bool build_type2(void);
+extern bool build_type3(void);
+extern bool build_type4(void);
+extern bool build_type11(void);
+extern bool build_type12(void);
-#include "angband.h"\r
-#include "grid.h"\r
-#include "generate.h"\r
-#include "rooms.h"\r
-#include "rooms-pitnest.h"\r
-#include "monster.h"\r
-#include "monsterrace-hook.h"\r
-#include "sort.h"\r
-\r
-\r
-\r
-#define NUM_NEST_MON_TYPE 64 /*!<nestの種別数 */\r
-\r
-/*! pit/nest型情報のtypedef */\r
-typedef struct vault_aux_type vault_aux_type;\r
-\r
-/*! pit/nest型情報の構造体定義 */\r
-struct vault_aux_type\r
-{\r
- concptr name;\r
- bool(*hook_func)(MONRACE_IDX r_idx);\r
- void(*prep_func)(void);\r
- DEPTH level;\r
- int chance;\r
-};\r
-\r
-/*! nestのID定義 / Nest types code */\r
-#define NEST_TYPE_CLONE 0\r
-#define NEST_TYPE_JELLY 1\r
-#define NEST_TYPE_SYMBOL_GOOD 2\r
-#define NEST_TYPE_SYMBOL_EVIL 3\r
-#define NEST_TYPE_MIMIC 4\r
-#define NEST_TYPE_LOVECRAFTIAN 5\r
-#define NEST_TYPE_KENNEL 6\r
-#define NEST_TYPE_ANIMAL 7\r
-#define NEST_TYPE_CHAPEL 8\r
-#define NEST_TYPE_UNDEAD 9\r
-\r
-/*! pitのID定義 / Pit types code */\r
-#define PIT_TYPE_ORC 0\r
-#define PIT_TYPE_TROLL 1\r
-#define PIT_TYPE_GIANT 2\r
-#define PIT_TYPE_LOVECRAFTIAN 3\r
-#define PIT_TYPE_SYMBOL_GOOD 4\r
-#define PIT_TYPE_SYMBOL_EVIL 5\r
-#define PIT_TYPE_CHAPEL 6\r
-#define PIT_TYPE_DRAGON 7\r
-#define PIT_TYPE_DEMON 8\r
-#define PIT_TYPE_DARK_ELF 9\r
-\r
-\r
-/*!\r
-* @brief ダンジョン毎に指定されたピット配列を基準にランダムなpit/nestタイプを決める\r
-* @param l_ptr 選択されたpit/nest情報を返す参照ポインタ\r
-* @param allow_flag_mask 生成が許されるpit/nestのビット配列\r
-* @return 選択されたpit/nestのID、選択失敗した場合-1を返す。\r
-*/\r
-static int pick_vault_type(vault_aux_type *l_ptr, BIT_FLAGS16 allow_flag_mask)\r
-{\r
- int tmp, total, count;\r
-\r
- vault_aux_type *n_ptr;\r
-\r
- /* Calculate the total possibilities */\r
- for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)\r
- {\r
- /* Note end */\r
- if (!n_ptr->name) break;\r
-\r
- /* Ignore excessive depth */\r
- if (n_ptr->level > dun_level) continue;\r
-\r
- /* Not matched with pit/nest flag */\r
- if (!(allow_flag_mask & (1L << count))) continue;\r
-\r
- /* Count this possibility */\r
- total += n_ptr->chance * MAX_DEPTH / (MIN(dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);\r
- }\r
-\r
- /* Pick a random type */\r
- tmp = randint0(total);\r
-\r
- /* Find this type */\r
- for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)\r
- {\r
- /* Note end */\r
- if (!n_ptr->name) break;\r
-\r
- /* Ignore excessive depth */\r
- if (n_ptr->level > dun_level) continue;\r
-\r
- /* Not matched with pit/nest flag */\r
- if (!(allow_flag_mask & (1L << count))) continue;\r
-\r
- /* Count this possibility */\r
- total += n_ptr->chance * MAX_DEPTH / (MIN(dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);\r
-\r
- /* Found the type */\r
- if (tmp < total) break;\r
- }\r
-\r
- return n_ptr->name ? count : -1;\r
-}\r
-\r
-/*!\r
-* @brief デバッグ時に生成されたpit/nestの型を出力する処理\r
-* @param type pit/nestの型ID\r
-* @param nest TRUEならばnest、FALSEならばpit\r
-* @return デバッグ表示文字列の参照ポインタ\r
-* @details\r
-* Hack -- Get the string describing subtype of pit/nest\r
-* Determined in prepare function (some pit/nest only)\r
-*/\r
-static concptr pit_subtype_string(int type, bool nest)\r
-{\r
- static char inner_buf[256] = "";\r
-\r
- inner_buf[0] = '\0'; /* Init string */\r
-\r
- if (nest) /* Nests */\r
- {\r
- switch (type)\r
- {\r
- case NEST_TYPE_CLONE:\r
- sprintf(inner_buf, "(%s)", r_name + r_info[vault_aux_race].name);\r
- break;\r
- case NEST_TYPE_SYMBOL_GOOD:\r
- case NEST_TYPE_SYMBOL_EVIL:\r
- sprintf(inner_buf, "(%c)", vault_aux_char);\r
- break;\r
- }\r
- }\r
- else /* Pits */\r
- {\r
- switch (type)\r
- {\r
- case PIT_TYPE_SYMBOL_GOOD:\r
- case PIT_TYPE_SYMBOL_EVIL:\r
- sprintf(inner_buf, "(%c)", vault_aux_char);\r
- break;\r
- case PIT_TYPE_DRAGON:\r
- switch (vault_aux_dragon_mask4)\r
- {\r
- case RF4_BR_ACID: strcpy(inner_buf, _("(酸)", "(acid)")); break;\r
- case RF4_BR_ELEC: strcpy(inner_buf, _("(稲妻)", "(lightning)")); break;\r
- case RF4_BR_FIRE: strcpy(inner_buf, _("(火炎)", "(fire)")); break;\r
- case RF4_BR_COLD: strcpy(inner_buf, _("(冷気)", "(frost)")); break;\r
- case RF4_BR_POIS: strcpy(inner_buf, _("(毒)", "(poison)")); break;\r
- case (RF4_BR_ACID | RF4_BR_ELEC | RF4_BR_FIRE | RF4_BR_COLD | RF4_BR_POIS) :\r
- strcpy(inner_buf, _("(万色)", "(multi-hued)")); break;\r
- default: strcpy(inner_buf, _("(未定義)", "(undefined)")); break;\r
- }\r
- break;\r
- }\r
- }\r
-\r
- return inner_buf;\r
-}\r
-\r
-/*\r
-*! @brief nestのモンスターリストをソートするための関数 /\r
-* Comp function for sorting nest monster information\r
-* @param u ソート処理対象配列ポインタ\r
-* @param v 未使用\r
-* @param a 比較対象参照ID1\r
-* @param b 比較対象参照ID2\r
-*/\r
-static bool ang_sort_comp_nest_mon_info(vptr u, vptr v, int a, int b)\r
-{\r
- nest_mon_info_type *nest_mon_info = (nest_mon_info_type *)u;\r
- MONSTER_IDX w1 = nest_mon_info[a].r_idx;\r
- MONSTER_IDX w2 = nest_mon_info[b].r_idx;\r
- monster_race *r1_ptr = &r_info[w1];\r
- monster_race *r2_ptr = &r_info[w2];\r
- int z1, z2;\r
-\r
- /* Unused */\r
- (void)v;\r
-\r
- /* Extract used info */\r
- z1 = nest_mon_info[a].used;\r
- z2 = nest_mon_info[b].used;\r
-\r
- /* Compare used status */\r
- if (z1 < z2) return FALSE;\r
- if (z1 > z2) return TRUE;\r
-\r
- /* Compare levels */\r
- if (r1_ptr->level < r2_ptr->level) return TRUE;\r
- if (r1_ptr->level > r2_ptr->level) return FALSE;\r
-\r
- /* Compare experience */\r
- if (r1_ptr->mexp < r2_ptr->mexp) return TRUE;\r
- if (r1_ptr->mexp > r2_ptr->mexp) return FALSE;\r
-\r
- /* Compare indexes */\r
- return w1 <= w2;\r
-}\r
-\r
-/*!\r
-* @brief nestのモンスターリストをスワップするための関数 /\r
-* Swap function for sorting nest monster information\r
-* @param u スワップ処理対象配列ポインタ\r
-* @param v 未使用\r
-* @param a スワップ対象参照ID1\r
-* @param b スワップ対象参照ID2\r
-*/\r
-static void ang_sort_swap_nest_mon_info(vptr u, vptr v, int a, int b)\r
-{\r
- nest_mon_info_type *nest_mon_info = (nest_mon_info_type *)u;\r
- nest_mon_info_type holder;\r
-\r
- /* Unused */\r
- (void)v;\r
-\r
- /* Swap */\r
- holder = nest_mon_info[a];\r
- nest_mon_info[a] = nest_mon_info[b];\r
- nest_mon_info[b] = holder;\r
-}\r
-\r
-\r
-\r
-/*!nest情報テーブル*/\r
-static vault_aux_type nest_types[] =\r
-{\r
- { _("クローン", "clone"), vault_aux_clone, vault_prep_clone, 5, 3 },\r
- { _("ゼリー", "jelly"), vault_aux_jelly, NULL, 5, 6 },\r
- { _("シンボル(善)", "symbol good"), vault_aux_symbol_g, vault_prep_symbol, 25, 2 },\r
- { _("シンボル(悪)", "symbol evil"), vault_aux_symbol_e, vault_prep_symbol, 25, 2 },\r
- { _("ミミック", "mimic"), vault_aux_mimic, NULL, 30, 4 },\r
- { _("狂気", "lovecraftian"), vault_aux_cthulhu, NULL, 70, 2 },\r
- { _("犬小屋", "kennel"), vault_aux_kennel, NULL, 45, 4 },\r
- { _("動物園", "animal"), vault_aux_animal, NULL, 35, 5 },\r
- { _("教会", "chapel"), vault_aux_chapel_g, NULL, 75, 4 },\r
- { _("アンデッド", "undead"), vault_aux_undead, NULL, 75, 5 },\r
- { NULL, NULL, NULL, 0, 0 },\r
-};\r
-\r
-/*!pit情報テーブル*/\r
-static vault_aux_type pit_types[] =\r
-{\r
- { _("オーク", "orc"), vault_aux_orc, NULL, 5, 6 },\r
- { _("トロル", "troll"), vault_aux_troll, NULL, 20, 6 },\r
- { _("ジャイアント", "giant"), vault_aux_giant, NULL, 50, 6 },\r
- { _("狂気", "lovecraftian"), vault_aux_cthulhu, NULL, 80, 2 },\r
- { _("シンボル(善)", "symbol good"), vault_aux_symbol_g, vault_prep_symbol, 70, 1 },\r
- { _("シンボル(悪)", "symbol evil"), vault_aux_symbol_e, vault_prep_symbol, 70, 1 },\r
- { _("教会", "chapel"), vault_aux_chapel_g, NULL, 65, 2 },\r
- { _("ドラゴン", "dragon"), vault_aux_dragon, vault_prep_dragon, 70, 6 },\r
- { _("デーモン", "demon"), vault_aux_demon, NULL, 80, 6 },\r
- { _("ダークエルフ", "dark elf"), vault_aux_dark_elf, NULL, 45, 4 },\r
- { NULL, NULL, NULL, 0, 0 },\r
-};\r
-\r
-\r
-\r
-\r
-/*!\r
-* @brief タイプ5の部屋…nestを生成する / Type 5 -- Monster nests\r
-* @return なし\r
-* @details\r
-* A monster nest is a "big" room, with an "inner" room, containing\n\r
-* a "collection" of monsters of a given type strewn about the room.\n\r
-*\n\r
-* The monsters are chosen from a set of 64 randomly selected monster\n\r
-* races, to allow the nest creation to fail instead of having "holes".\n\r
-*\n\r
-* Note the use of the "get_mon_num_prep()" function, and the special\n\r
-* "get_mon_num_hook()" restriction function, to prepare the "monster\n\r
-* allocation table" in such a way as to optimize the selection of\n\r
-* "appropriate" non-unique monsters for the nest.\n\r
-*\n\r
-* Note that the "get_mon_num()" function may (rarely) fail, in which\n\r
-* case the nest will be empty.\n\r
-*\n\r
-* Note that "monster nests" will never contain "unique" monsters.\n\r
-*/\r
-bool build_type5(void)\r
-{\r
- POSITION y, x, y1, x1, y2, x2, xval, yval;\r
- int i;\r
- nest_mon_info_type nest_mon_info[NUM_NEST_MON_TYPE];\r
-\r
- monster_type align;\r
-\r
- cave_type *c_ptr;\r
-\r
- int cur_nest_type = pick_vault_type(nest_types, d_info[p_ptr->dungeon_idx].nest);\r
- vault_aux_type *n_ptr;\r
-\r
- /* No type available */\r
- if (cur_nest_type < 0) return FALSE;\r
-\r
- n_ptr = &nest_types[cur_nest_type];\r
-\r
- /* Process a preparation function if necessary */\r
- if (n_ptr->prep_func) (*(n_ptr->prep_func))();\r
- get_mon_num_prep(n_ptr->hook_func, NULL);\r
-\r
- align.sub_align = SUB_ALIGN_NEUTRAL;\r
-\r
- /* Pick some monster types */\r
- for (i = 0; i < NUM_NEST_MON_TYPE; i++)\r
- {\r
- MONRACE_IDX r_idx = 0;\r
- int attempts = 100;\r
- monster_race *r_ptr = NULL;\r
-\r
- while (attempts--)\r
- {\r
- /* Get a (hard) monster type */\r
- r_idx = get_mon_num(dun_level + 11);\r
- r_ptr = &r_info[r_idx];\r
-\r
- /* Decline incorrect alignment */\r
- if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;\r
-\r
- /* Accept this monster */\r
- break;\r
- }\r
-\r
- /* Notice failure */\r
- if (!r_idx || !attempts) return FALSE;\r
-\r
- /* Note the alignment */\r
- if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;\r
- if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;\r
-\r
- nest_mon_info[i].r_idx = (s16b)r_idx;\r
- nest_mon_info[i].used = FALSE;\r
- }\r
-\r
- /* Find and reserve some space in the dungeon. Get center of room. */\r
- if (!find_space(&yval, &xval, 11, 25)) return FALSE;\r
-\r
- /* Large room */\r
- y1 = yval - 4;\r
- y2 = yval + 4;\r
- x1 = xval - 11;\r
- x2 = xval + 11;\r
-\r
- /* Place the floor area */\r
- for (y = y1 - 1; y <= y2 + 1; y++)\r
- {\r
- for (x = x1 - 1; x <= x2 + 1; x++)\r
- {\r
- c_ptr = &cave[y][x];\r
- place_floor_grid(c_ptr);\r
- c_ptr->info |= (CAVE_ROOM);\r
- }\r
- }\r
-\r
- /* Place the outer walls */\r
- for (y = y1 - 1; y <= y2 + 1; y++)\r
- {\r
- c_ptr = &cave[y][x1 - 1];\r
- place_outer_grid(c_ptr);\r
- c_ptr = &cave[y][x2 + 1];\r
- place_outer_grid(c_ptr);\r
- }\r
- for (x = x1 - 1; x <= x2 + 1; x++)\r
- {\r
- c_ptr = &cave[y1 - 1][x];\r
- place_outer_grid(c_ptr);\r
- c_ptr = &cave[y2 + 1][x];\r
- place_outer_grid(c_ptr);\r
- }\r
-\r
-\r
- /* Advance to the center room */\r
- y1 = y1 + 2;\r
- y2 = y2 - 2;\r
- x1 = x1 + 2;\r
- x2 = x2 - 2;\r
-\r
- /* The inner walls */\r
- for (y = y1 - 1; y <= y2 + 1; y++)\r
- {\r
- c_ptr = &cave[y][x1 - 1];\r
- place_inner_grid(c_ptr);\r
- c_ptr = &cave[y][x2 + 1];\r
- place_inner_grid(c_ptr);\r
- }\r
-\r
- for (x = x1 - 1; x <= x2 + 1; x++)\r
- {\r
- c_ptr = &cave[y1 - 1][x];\r
- place_inner_grid(c_ptr);\r
- c_ptr = &cave[y2 + 1][x];\r
- place_inner_grid(c_ptr);\r
- }\r
- for (y = y1; y <= y2; y++)\r
- {\r
- for (x = x1; x <= x2; x++)\r
- {\r
- add_cave_info(y, x, CAVE_ICKY);\r
- }\r
- }\r
-\r
- /* Place a secret door */\r
- switch (randint1(4))\r
- {\r
- case 1: place_secret_door(y1 - 1, xval, DOOR_DEFAULT); break;\r
- case 2: place_secret_door(y2 + 1, xval, DOOR_DEFAULT); break;\r
- case 3: place_secret_door(yval, x1 - 1, DOOR_DEFAULT); break;\r
- case 4: place_secret_door(yval, x2 + 1, DOOR_DEFAULT); break;\r
- }\r
-\r
- msg_format_wizard(CHEAT_DUNGEON, _("モンスター部屋(nest)(%s%s)を生成します。", "Monster nest (%s%s)"), n_ptr->name, pit_subtype_string(cur_nest_type, TRUE));\r
-\r
- /* Place some monsters */\r
- for (y = yval - 2; y <= yval + 2; y++)\r
- {\r
- for (x = xval - 9; x <= xval + 9; x++)\r
- {\r
- MONRACE_IDX r_idx;\r
-\r
- i = randint0(NUM_NEST_MON_TYPE);\r
- r_idx = nest_mon_info[i].r_idx;\r
-\r
- /* Place that "random" monster (no groups) */\r
- (void)place_monster_aux(0, y, x, r_idx, 0L);\r
-\r
- nest_mon_info[i].used = TRUE;\r
- }\r
- }\r
-\r
- if (cheat_room)\r
- {\r
- ang_sort_comp = ang_sort_comp_nest_mon_info;\r
- ang_sort_swap = ang_sort_swap_nest_mon_info;\r
- ang_sort(nest_mon_info, NULL, NUM_NEST_MON_TYPE);\r
-\r
- /* Dump the entries (prevent multi-printing) */\r
- for (i = 0; i < NUM_NEST_MON_TYPE; i++)\r
- {\r
- if (!nest_mon_info[i].used) break;\r
- for (; i < NUM_NEST_MON_TYPE - 1; i++)\r
- {\r
- if (nest_mon_info[i].r_idx != nest_mon_info[i + 1].r_idx) break;\r
- if (!nest_mon_info[i + 1].used) break;\r
- }\r
- msg_format_wizard(CHEAT_DUNGEON, "Nest構成モンスターNo.%d:%s", i, r_name + r_info[nest_mon_info[i].r_idx].name);\r
- }\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
-\r
-/*!\r
-* @brief タイプ6の部屋…pitを生成する / Type 6 -- Monster pits\r
-* @return なし\r
-* @details\r
-* A monster pit is a "big" room, with an "inner" room, containing\n\r
-* a "collection" of monsters of a given type organized in the room.\n\r
-*\n\r
-* The inside room in a monster pit appears as shown below, where the\n\r
-* actual monsters in each location depend on the type of the pit\n\r
-*\n\r
-* XXXXXXXXXXXXXXXXXXXXX\n\r
-* X0000000000000000000X\n\r
-* X0112233455543322110X\n\r
-* X0112233467643322110X\n\r
-* X0112233455543322110X\n\r
-* X0000000000000000000X\n\r
-* XXXXXXXXXXXXXXXXXXXXX\n\r
-*\n\r
-* Note that the monsters in the pit are now chosen by using "get_mon_num()"\n\r
-* to request 16 "appropriate" monsters, sorting them by level, and using\n\r
-* the "even" entries in this sorted list for the contents of the pit.\n\r
-*\n\r
-* Hack -- all of the "dragons" in a "dragon" pit must be the same "color",\n\r
-* which is handled by requiring a specific "breath" attack for all of the\n\r
-* dragons. This may include "multi-hued" breath. Note that "wyrms" may\n\r
-* be present in many of the dragon pits, if they have the proper breath.\n\r
-*\n\r
-* Note the use of the "get_mon_num_prep()" function, and the special\n\r
-* "get_mon_num_hook()" restriction function, to prepare the "monster\n\r
-* allocation table" in such a way as to optimize the selection of\n\r
-* "appropriate" non-unique monsters for the pit.\n\r
-*\n\r
-* Note that the "get_mon_num()" function may (rarely) fail, in which case\n\r
-* the pit will be empty.\n\r
-*\n\r
-* Note that "monster pits" will never contain "unique" monsters.\n\r
-*/\r
-bool build_type6(void)\r
-{\r
- POSITION y, x, y1, x1, y2, x2, xval, yval;\r
- int i, j;\r
-\r
- MONRACE_IDX what[16];\r
-\r
- monster_type align;\r
-\r
- cave_type *c_ptr;\r
-\r
- int cur_pit_type = pick_vault_type(pit_types, d_info[p_ptr->dungeon_idx].pit);\r
- vault_aux_type *n_ptr;\r
-\r
- /* No type available */\r
- if (cur_pit_type < 0) return FALSE;\r
-\r
- n_ptr = &pit_types[cur_pit_type];\r
-\r
- /* Process a preparation function if necessary */\r
- if (n_ptr->prep_func) (*(n_ptr->prep_func))();\r
- get_mon_num_prep(n_ptr->hook_func, NULL);\r
-\r
- align.sub_align = SUB_ALIGN_NEUTRAL;\r
-\r
- /* Pick some monster types */\r
- for (i = 0; i < 16; i++)\r
- {\r
- MONRACE_IDX r_idx = 0;\r
- int attempts = 100;\r
- monster_race *r_ptr = NULL;\r
-\r
- while (attempts--)\r
- {\r
- /* Get a (hard) monster type */\r
- r_idx = get_mon_num(dun_level + 11);\r
- r_ptr = &r_info[r_idx];\r
-\r
- /* Decline incorrect alignment */\r
- if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;\r
-\r
- /* Accept this monster */\r
- break;\r
- }\r
-\r
- /* Notice failure */\r
- if (!r_idx || !attempts) return FALSE;\r
-\r
- /* Note the alignment */\r
- if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;\r
- if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;\r
-\r
- what[i] = r_idx;\r
- }\r
-\r
- /* Find and reserve some space in the dungeon. Get center of room. */\r
- if (!find_space(&yval, &xval, 11, 25)) return FALSE;\r
-\r
- /* Large room */\r
- y1 = yval - 4;\r
- y2 = yval + 4;\r
- x1 = xval - 11;\r
- x2 = xval + 11;\r
-\r
- /* Place the floor area */\r
- for (y = y1 - 1; y <= y2 + 1; y++)\r
- {\r
- for (x = x1 - 1; x <= x2 + 1; x++)\r
- {\r
- c_ptr = &cave[y][x];\r
- place_floor_grid(c_ptr);\r
- c_ptr->info |= (CAVE_ROOM);\r
- }\r
- }\r
-\r
- /* Place the outer walls */\r
- for (y = y1 - 1; y <= y2 + 1; y++)\r
- {\r
- c_ptr = &cave[y][x1 - 1];\r
- place_outer_grid(c_ptr);\r
- c_ptr = &cave[y][x2 + 1];\r
- place_outer_grid(c_ptr);\r
- }\r
- for (x = x1 - 1; x <= x2 + 1; x++)\r
- {\r
- c_ptr = &cave[y1 - 1][x];\r
- place_outer_grid(c_ptr);\r
- c_ptr = &cave[y2 + 1][x];\r
- place_outer_grid(c_ptr);\r
- }\r
-\r
- /* Advance to the center room */\r
- y1 = y1 + 2;\r
- y2 = y2 - 2;\r
- x1 = x1 + 2;\r
- x2 = x2 - 2;\r
-\r
- /* The inner walls */\r
- for (y = y1 - 1; y <= y2 + 1; y++)\r
- {\r
- c_ptr = &cave[y][x1 - 1];\r
- place_inner_grid(c_ptr);\r
- c_ptr = &cave[y][x2 + 1];\r
- place_inner_grid(c_ptr);\r
- }\r
- for (x = x1 - 1; x <= x2 + 1; x++)\r
- {\r
- c_ptr = &cave[y1 - 1][x];\r
- place_inner_grid(c_ptr);\r
- c_ptr = &cave[y2 + 1][x];\r
- place_inner_grid(c_ptr);\r
- }\r
- for (y = y1; y <= y2; y++)\r
- {\r
- for (x = x1; x <= x2; x++)\r
- {\r
- add_cave_info(y, x, CAVE_ICKY);\r
- }\r
- }\r
-\r
- /* Place a secret door */\r
- switch (randint1(4))\r
- {\r
- case 1: place_secret_door(y1 - 1, xval, DOOR_DEFAULT); break;\r
- case 2: place_secret_door(y2 + 1, xval, DOOR_DEFAULT); break;\r
- case 3: place_secret_door(yval, x1 - 1, DOOR_DEFAULT); break;\r
- case 4: place_secret_door(yval, x2 + 1, DOOR_DEFAULT); break;\r
- }\r
-\r
- /* Sort the entries */\r
- for (i = 0; i < 16 - 1; i++)\r
- {\r
- /* Sort the entries */\r
- for (j = 0; j < 16 - 1; j++)\r
- {\r
- int i1 = j;\r
- int i2 = j + 1;\r
-\r
- int p1 = r_info[what[i1]].level;\r
- int p2 = r_info[what[i2]].level;\r
-\r
- /* Bubble */\r
- if (p1 > p2)\r
- {\r
- MONRACE_IDX tmp = what[i1];\r
- what[i1] = what[i2];\r
- what[i2] = tmp;\r
- }\r
- }\r
- }\r
-\r
- msg_format_wizard(CHEAT_DUNGEON, _("モンスター部屋(pit)(%s%s)を生成します。", "Monster pit (%s%s)"), n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));\r
-\r
- /* Select the entries */\r
- for (i = 0; i < 8; i++)\r
- {\r
- /* Every other entry */\r
- what[i] = what[i * 2];\r
- msg_format_wizard(CHEAT_DUNGEON, _("Nest構成モンスター選択No.%d:%s", "Nest Monster Select No.%d:%s"), i, r_name + r_info[what[i]].name);\r
- }\r
-\r
- /* Top and bottom rows */\r
- for (x = xval - 9; x <= xval + 9; x++)\r
- {\r
- place_monster_aux(0, yval - 2, x, what[0], PM_NO_KAGE);\r
- place_monster_aux(0, yval + 2, x, what[0], PM_NO_KAGE);\r
- }\r
-\r
- /* Middle columns */\r
- for (y = yval - 1; y <= yval + 1; y++)\r
- {\r
- place_monster_aux(0, y, xval - 9, what[0], PM_NO_KAGE);\r
- place_monster_aux(0, y, xval + 9, what[0], PM_NO_KAGE);\r
-\r
- place_monster_aux(0, y, xval - 8, what[1], PM_NO_KAGE);\r
- place_monster_aux(0, y, xval + 8, what[1], PM_NO_KAGE);\r
-\r
- place_monster_aux(0, y, xval - 7, what[1], PM_NO_KAGE);\r
- place_monster_aux(0, y, xval + 7, what[1], PM_NO_KAGE);\r
-\r
- place_monster_aux(0, y, xval - 6, what[2], PM_NO_KAGE);\r
- place_monster_aux(0, y, xval + 6, what[2], PM_NO_KAGE);\r
-\r
- place_monster_aux(0, y, xval - 5, what[2], PM_NO_KAGE);\r
- place_monster_aux(0, y, xval + 5, what[2], PM_NO_KAGE);\r
-\r
- place_monster_aux(0, y, xval - 4, what[3], PM_NO_KAGE);\r
- place_monster_aux(0, y, xval + 4, what[3], PM_NO_KAGE);\r
-\r
- place_monster_aux(0, y, xval - 3, what[3], PM_NO_KAGE);\r
- place_monster_aux(0, y, xval + 3, what[3], PM_NO_KAGE);\r
-\r
- place_monster_aux(0, y, xval - 2, what[4], PM_NO_KAGE);\r
- place_monster_aux(0, y, xval + 2, what[4], PM_NO_KAGE);\r
- }\r
-\r
- /* Above/Below the center monster */\r
- for (x = xval - 1; x <= xval + 1; x++)\r
- {\r
- place_monster_aux(0, yval + 1, x, what[5], PM_NO_KAGE);\r
- place_monster_aux(0, yval - 1, x, what[5], PM_NO_KAGE);\r
- }\r
-\r
- /* Next to the center monster */\r
- place_monster_aux(0, yval, xval + 1, what[6], PM_NO_KAGE);\r
- place_monster_aux(0, yval, xval - 1, what[6], PM_NO_KAGE);\r
-\r
- /* Center monster */\r
- place_monster_aux(0, yval, xval, what[7], PM_NO_KAGE);\r
-\r
- return TRUE;\r
-}\r
-\r
-\r
-\r
-/*\r
-* Helper function for "trapped monster pit"\r
-*/\r
-static bool vault_aux_trapped_pit(MONRACE_IDX r_idx)\r
-{\r
- monster_race *r_ptr = &r_info[r_idx];\r
-\r
- if (!vault_monster_okay(r_idx)) return (FALSE);\r
-\r
- /* No wall passing monster */\r
- if (r_ptr->flags2 & (RF2_PASS_WALL | RF2_KILL_WALL)) return (FALSE);\r
-\r
- return (TRUE);\r
-}\r
-\r
-\r
-/*!\r
-* @brief タイプ13の部屋…トラップpitの生成 / Type 13 -- Trapped monster pits\r
-* @return なし\r
-* @details\r
-* A trapped monster pit is a "big" room with a straight corridor in\n\r
-* which wall opening traps are placed, and with two "inner" rooms\n\r
-* containing a "collection" of monsters of a given type organized in\n\r
-* the room.\n\r
-*\n\r
-* The trapped monster pit appears as shown below, where the actual\n\r
-* monsters in each location depend on the type of the pit\n\r
-*\n\r
-* XXXXXXXXXXXXXXXXXXXXXXXXX\n\r
-* X X\n\r
-* XXXXXXXXXXXXXXXXXXXXXXX X\n\r
-* XXXXX001123454321100XXX X\n\r
-* XXX0012234567654322100X X\n\r
-* XXXXXXXXXXXXXXXXXXXXXXX X\n\r
-* X ^ X\n\r
-* X XXXXXXXXXXXXXXXXXXXXXXX\n\r
-* X X0012234567654322100XXX\n\r
-* X XXX001123454321100XXXXX\n\r
-* X XXXXXXXXXXXXXXXXXXXXXXX\n\r
-* X X\n\r
-* XXXXXXXXXXXXXXXXXXXXXXXXX\n\r
-*\n\r
-* Note that the monsters in the pit are now chosen by using "get_mon_num()"\n\r
-* to request 16 "appropriate" monsters, sorting them by level, and using\n\r
-* the "even" entries in this sorted list for the contents of the pit.\n\r
-*\n\r
-* Hack -- all of the "dragons" in a "dragon" pit must be the same "color",\n\r
-* which is handled by requiring a specific "breath" attack for all of the\n\r
-* dragons. This may include "multi-hued" breath. Note that "wyrms" may\n\r
-* be present in many of the dragon pits, if they have the proper breath.\n\r
-*\n\r
-* Note the use of the "get_mon_num_prep()" function, and the special\n\r
-* "get_mon_num_hook()" restriction function, to prepare the "monster\n\r
-* allocation table" in such a way as to optimize the selection of\n\r
-* "appropriate" non-unique monsters for the pit.\n\r
-*\n\r
-* Note that the "get_mon_num()" function may (rarely) fail, in which case\n\r
-* the pit will be empty.\n\r
-*\n\r
-* Note that "monster pits" will never contain "unique" monsters.\n\r
-*/\r
-bool build_type13(void)\r
-{\r
- static int placing[][3] = {\r
- { -2, -9, 0 },{ -2, -8, 0 },{ -3, -7, 0 },{ -3, -6, 0 },\r
- { +2, -9, 0 },{ +2, -8, 0 },{ +3, -7, 0 },{ +3, -6, 0 },\r
- { -2, +9, 0 },{ -2, +8, 0 },{ -3, +7, 0 },{ -3, +6, 0 },\r
- { +2, +9, 0 },{ +2, +8, 0 },{ +3, +7, 0 },{ +3, +6, 0 },\r
- { -2, -7, 1 },{ -3, -5, 1 },{ -3, -4, 1 },\r
- { +2, -7, 1 },{ +3, -5, 1 },{ +3, -4, 1 },\r
- { -2, +7, 1 },{ -3, +5, 1 },{ -3, +4, 1 },\r
- { +2, +7, 1 },{ +3, +5, 1 },{ +3, +4, 1 },\r
- { -2, -6, 2 },{ -2, -5, 2 },{ -3, -3, 2 },\r
- { +2, -6, 2 },{ +2, -5, 2 },{ +3, -3, 2 },\r
- { -2, +6, 2 },{ -2, +5, 2 },{ -3, +3, 2 },\r
- { +2, +6, 2 },{ +2, +5, 2 },{ +3, +3, 2 },\r
- { -2, -4, 3 },{ -3, -2, 3 },\r
- { +2, -4, 3 },{ +3, -2, 3 },\r
- { -2, +4, 3 },{ -3, +2, 3 },\r
- { +2, +4, 3 },{ +3, +2, 3 },\r
- { -2, -3, 4 },{ -3, -1, 4 },\r
- { +2, -3, 4 },{ +3, -1, 4 },\r
- { -2, +3, 4 },{ -3, +1, 4 },\r
- { +2, +3, 4 },{ +3, +1, 4 },\r
- { -2, -2, 5 },{ -3, 0, 5 },{ -2, +2, 5 },\r
- { +2, -2, 5 },{ +3, 0, 5 },{ +2, +2, 5 },\r
- { -2, -1, 6 },{ -2, +1, 6 },\r
- { +2, -1, 6 },{ +2, +1, 6 },\r
- { -2, 0, 7 },{ +2, 0, 7 },\r
- { 0, 0, -1 }\r
- };\r
-\r
- POSITION y, x, y1, x1, y2, x2, xval, yval;\r
- int i, j;\r
-\r
- MONRACE_IDX what[16];\r
-\r
- monster_type align;\r
-\r
- cave_type *c_ptr;\r
-\r
- int cur_pit_type = pick_vault_type(pit_types, d_info[p_ptr->dungeon_idx].pit);\r
- vault_aux_type *n_ptr;\r
-\r
- /* Only in Angband */\r
- if (p_ptr->dungeon_idx != DUNGEON_ANGBAND) return FALSE;\r
-\r
- /* No type available */\r
- if (cur_pit_type < 0) return FALSE;\r
-\r
- n_ptr = &pit_types[cur_pit_type];\r
-\r
- /* Process a preparation function if necessary */\r
- if (n_ptr->prep_func) (*(n_ptr->prep_func))();\r
- get_mon_num_prep(n_ptr->hook_func, vault_aux_trapped_pit);\r
-\r
- align.sub_align = SUB_ALIGN_NEUTRAL;\r
-\r
- /* Pick some monster types */\r
- for (i = 0; i < 16; i++)\r
- {\r
- MONRACE_IDX r_idx = 0;\r
- int attempts = 100;\r
- monster_race *r_ptr = NULL;\r
-\r
- while (attempts--)\r
- {\r
- /* Get a (hard) monster type */\r
- r_idx = get_mon_num(dun_level + 0);\r
- r_ptr = &r_info[r_idx];\r
-\r
- /* Decline incorrect alignment */\r
- if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;\r
-\r
- /* Accept this monster */\r
- break;\r
- }\r
-\r
- /* Notice failure */\r
- if (!r_idx || !attempts) return FALSE;\r
-\r
- /* Note the alignment */\r
- if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;\r
- if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;\r
-\r
- what[i] = r_idx;\r
- }\r
-\r
- /* Find and reserve some space in the dungeon. Get center of room. */\r
- if (!find_space(&yval, &xval, 13, 25)) return FALSE;\r
-\r
- /* Large room */\r
- y1 = yval - 5;\r
- y2 = yval + 5;\r
- x1 = xval - 11;\r
- x2 = xval + 11;\r
-\r
- /* Fill with inner walls */\r
- for (y = y1 - 1; y <= y2 + 1; y++)\r
- {\r
- for (x = x1 - 1; x <= x2 + 1; x++)\r
- {\r
- c_ptr = &cave[y][x];\r
- place_inner_grid(c_ptr);\r
- c_ptr->info |= (CAVE_ROOM);\r
- }\r
- }\r
-\r
- /* Place the floor area 1 */\r
- for (x = x1 + 3; x <= x2 - 3; x++)\r
- {\r
- c_ptr = &cave[yval - 2][x];\r
- place_floor_grid(c_ptr);\r
- add_cave_info(yval - 2, x, CAVE_ICKY);\r
-\r
- c_ptr = &cave[yval + 2][x];\r
- place_floor_grid(c_ptr);\r
- add_cave_info(yval + 2, x, CAVE_ICKY);\r
- }\r
-\r
- /* Place the floor area 2 */\r
- for (x = x1 + 5; x <= x2 - 5; x++)\r
- {\r
- c_ptr = &cave[yval - 3][x];\r
- place_floor_grid(c_ptr);\r
- add_cave_info(yval - 3, x, CAVE_ICKY);\r
-\r
- c_ptr = &cave[yval + 3][x];\r
- place_floor_grid(c_ptr);\r
- add_cave_info(yval + 3, x, CAVE_ICKY);\r
- }\r
-\r
- /* Corridor */\r
- for (x = x1; x <= x2; x++)\r
- {\r
- c_ptr = &cave[yval][x];\r
- place_floor_grid(c_ptr);\r
- c_ptr = &cave[y1][x];\r
- place_floor_grid(c_ptr);\r
- c_ptr = &cave[y2][x];\r
- place_floor_grid(c_ptr);\r
- }\r
-\r
- /* Place the outer walls */\r
- for (y = y1 - 1; y <= y2 + 1; y++)\r
- {\r
- c_ptr = &cave[y][x1 - 1];\r
- place_outer_grid(c_ptr);\r
- c_ptr = &cave[y][x2 + 1];\r
- place_outer_grid(c_ptr);\r
- }\r
- for (x = x1 - 1; x <= x2 + 1; x++)\r
- {\r
- c_ptr = &cave[y1 - 1][x];\r
- place_outer_grid(c_ptr);\r
- c_ptr = &cave[y2 + 1][x];\r
- place_outer_grid(c_ptr);\r
- }\r
-\r
- /* Random corridor */\r
- if (one_in_(2))\r
- {\r
- for (y = y1; y <= yval; y++)\r
- {\r
- place_floor_bold(y, x2);\r
- place_solid_bold(y, x1 - 1);\r
- }\r
- for (y = yval; y <= y2 + 1; y++)\r
- {\r
- place_floor_bold(y, x1);\r
- place_solid_bold(y, x2 + 1);\r
- }\r
- }\r
- else\r
- {\r
- for (y = yval; y <= y2 + 1; y++)\r
- {\r
- place_floor_bold(y, x1);\r
- place_solid_bold(y, x2 + 1);\r
- }\r
- for (y = y1; y <= yval; y++)\r
- {\r
- place_floor_bold(y, x2);\r
- place_solid_bold(y, x1 - 1);\r
- }\r
- }\r
-\r
- /* Place the wall open trap */\r
- cave[yval][xval].mimic = cave[yval][xval].feat;\r
- cave[yval][xval].feat = feat_trap_open;\r
-\r
- /* Sort the entries */\r
- for (i = 0; i < 16 - 1; i++)\r
- {\r
- /* Sort the entries */\r
- for (j = 0; j < 16 - 1; j++)\r
- {\r
- int i1 = j;\r
- int i2 = j + 1;\r
-\r
- int p1 = r_info[what[i1]].level;\r
- int p2 = r_info[what[i2]].level;\r
-\r
- /* Bubble */\r
- if (p1 > p2)\r
- {\r
- MONRACE_IDX tmp = what[i1];\r
- what[i1] = what[i2];\r
- what[i2] = tmp;\r
- }\r
- }\r
- }\r
-\r
- msg_format_wizard(CHEAT_DUNGEON, _("%s%sの罠ピットが生成されました。", "Trapped monster pit (%s%s)"),\r
- n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));\r
-\r
- /* Select the entries */\r
- for (i = 0; i < 8; i++)\r
- {\r
- /* Every other entry */\r
- what[i] = what[i * 2];\r
-\r
- if (cheat_hear)\r
- {\r
- msg_print(r_name + r_info[what[i]].name);\r
- }\r
- }\r
-\r
- for (i = 0; placing[i][2] >= 0; i++)\r
- {\r
- y = yval + placing[i][0];\r
- x = xval + placing[i][1];\r
- place_monster_aux(0, y, x, what[placing[i][2]], PM_NO_KAGE);\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
+#include "angband.h"
+#include "grid.h"
+#include "generate.h"
+#include "rooms.h"
+#include "rooms-pitnest.h"
+#include "monster.h"
+#include "monsterrace-hook.h"
+#include "sort.h"
+
+
+
+#define NUM_NEST_MON_TYPE 64 /*!<nestの種別数 */
+
+/*! pit/nest型情報のtypedef */
+typedef struct vault_aux_type vault_aux_type;
+
+/*! pit/nest型情報の構造体定義 */
+struct vault_aux_type
+{
+ concptr name;
+ bool(*hook_func)(MONRACE_IDX r_idx);
+ void(*prep_func)(void);
+ DEPTH level;
+ int chance;
+};
+
+/*! nestのID定義 / Nest types code */
+#define NEST_TYPE_CLONE 0
+#define NEST_TYPE_JELLY 1
+#define NEST_TYPE_SYMBOL_GOOD 2
+#define NEST_TYPE_SYMBOL_EVIL 3
+#define NEST_TYPE_MIMIC 4
+#define NEST_TYPE_LOVECRAFTIAN 5
+#define NEST_TYPE_KENNEL 6
+#define NEST_TYPE_ANIMAL 7
+#define NEST_TYPE_CHAPEL 8
+#define NEST_TYPE_UNDEAD 9
+
+/*! pitのID定義 / Pit types code */
+#define PIT_TYPE_ORC 0
+#define PIT_TYPE_TROLL 1
+#define PIT_TYPE_GIANT 2
+#define PIT_TYPE_LOVECRAFTIAN 3
+#define PIT_TYPE_SYMBOL_GOOD 4
+#define PIT_TYPE_SYMBOL_EVIL 5
+#define PIT_TYPE_CHAPEL 6
+#define PIT_TYPE_DRAGON 7
+#define PIT_TYPE_DEMON 8
+#define PIT_TYPE_DARK_ELF 9
+
+
+/*!
+* @brief ダンジョン毎に指定されたピット配列を基準にランダムなpit/nestタイプを決める
+* @param l_ptr 選択されたpit/nest情報を返す参照ポインタ
+* @param allow_flag_mask 生成が許されるpit/nestのビット配列
+* @return 選択されたpit/nestのID、選択失敗した場合-1を返す。
+*/
+static int pick_vault_type(vault_aux_type *l_ptr, BIT_FLAGS16 allow_flag_mask)
+{
+ int tmp, total, count;
+
+ vault_aux_type *n_ptr;
+
+ /* Calculate the total possibilities */
+ for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)
+ {
+ /* Note end */
+ if (!n_ptr->name) break;
+
+ /* Ignore excessive depth */
+ if (n_ptr->level > dun_level) continue;
+
+ /* Not matched with pit/nest flag */
+ if (!(allow_flag_mask & (1L << count))) continue;
+
+ /* Count this possibility */
+ total += n_ptr->chance * MAX_DEPTH / (MIN(dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);
+ }
+
+ /* Pick a random type */
+ tmp = randint0(total);
+
+ /* Find this type */
+ for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)
+ {
+ /* Note end */
+ if (!n_ptr->name) break;
+
+ /* Ignore excessive depth */
+ if (n_ptr->level > dun_level) continue;
+
+ /* Not matched with pit/nest flag */
+ if (!(allow_flag_mask & (1L << count))) continue;
+
+ /* Count this possibility */
+ total += n_ptr->chance * MAX_DEPTH / (MIN(dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);
+
+ /* Found the type */
+ if (tmp < total) break;
+ }
+
+ return n_ptr->name ? count : -1;
+}
+
+/*!
+* @brief デバッグ時に生成されたpit/nestの型を出力する処理
+* @param type pit/nestの型ID
+* @param nest TRUEならばnest、FALSEならばpit
+* @return デバッグ表示文字列の参照ポインタ
+* @details
+* Hack -- Get the string describing subtype of pit/nest
+* Determined in prepare function (some pit/nest only)
+*/
+static concptr pit_subtype_string(int type, bool nest)
+{
+ static char inner_buf[256] = "";
+
+ inner_buf[0] = '\0'; /* Init string */
+
+ if (nest) /* Nests */
+ {
+ switch (type)
+ {
+ case NEST_TYPE_CLONE:
+ sprintf(inner_buf, "(%s)", r_name + r_info[vault_aux_race].name);
+ break;
+ case NEST_TYPE_SYMBOL_GOOD:
+ case NEST_TYPE_SYMBOL_EVIL:
+ sprintf(inner_buf, "(%c)", vault_aux_char);
+ break;
+ }
+ }
+ else /* Pits */
+ {
+ switch (type)
+ {
+ case PIT_TYPE_SYMBOL_GOOD:
+ case PIT_TYPE_SYMBOL_EVIL:
+ sprintf(inner_buf, "(%c)", vault_aux_char);
+ break;
+ case PIT_TYPE_DRAGON:
+ switch (vault_aux_dragon_mask4)
+ {
+ case RF4_BR_ACID: strcpy(inner_buf, _("(酸)", "(acid)")); break;
+ case RF4_BR_ELEC: strcpy(inner_buf, _("(稲妻)", "(lightning)")); break;
+ case RF4_BR_FIRE: strcpy(inner_buf, _("(火炎)", "(fire)")); break;
+ case RF4_BR_COLD: strcpy(inner_buf, _("(冷気)", "(frost)")); break;
+ case RF4_BR_POIS: strcpy(inner_buf, _("(毒)", "(poison)")); break;
+ case (RF4_BR_ACID | RF4_BR_ELEC | RF4_BR_FIRE | RF4_BR_COLD | RF4_BR_POIS) :
+ strcpy(inner_buf, _("(万色)", "(multi-hued)")); break;
+ default: strcpy(inner_buf, _("(未定義)", "(undefined)")); break;
+ }
+ break;
+ }
+ }
+
+ return inner_buf;
+}
+
+/*
+*! @brief nestのモンスターリストをソートするための関数 /
+* Comp function for sorting nest monster information
+* @param u ソート処理対象配列ポインタ
+* @param v 未使用
+* @param a 比較対象参照ID1
+* @param b 比較対象参照ID2
+*/
+static bool ang_sort_comp_nest_mon_info(vptr u, vptr v, int a, int b)
+{
+ nest_mon_info_type *nest_mon_info = (nest_mon_info_type *)u;
+ MONSTER_IDX w1 = nest_mon_info[a].r_idx;
+ MONSTER_IDX w2 = nest_mon_info[b].r_idx;
+ monster_race *r1_ptr = &r_info[w1];
+ monster_race *r2_ptr = &r_info[w2];
+ int z1, z2;
+
+ /* Unused */
+ (void)v;
+
+ /* Extract used info */
+ z1 = nest_mon_info[a].used;
+ z2 = nest_mon_info[b].used;
+
+ /* Compare used status */
+ if (z1 < z2) return FALSE;
+ if (z1 > z2) return TRUE;
+
+ /* Compare levels */
+ if (r1_ptr->level < r2_ptr->level) return TRUE;
+ if (r1_ptr->level > r2_ptr->level) return FALSE;
+
+ /* Compare experience */
+ if (r1_ptr->mexp < r2_ptr->mexp) return TRUE;
+ if (r1_ptr->mexp > r2_ptr->mexp) return FALSE;
+
+ /* Compare indexes */
+ return w1 <= w2;
+}
+
+/*!
+* @brief nestのモンスターリストをスワップするための関数 /
+* Swap function for sorting nest monster information
+* @param u スワップ処理対象配列ポインタ
+* @param v 未使用
+* @param a スワップ対象参照ID1
+* @param b スワップ対象参照ID2
+*/
+static void ang_sort_swap_nest_mon_info(vptr u, vptr v, int a, int b)
+{
+ nest_mon_info_type *nest_mon_info = (nest_mon_info_type *)u;
+ nest_mon_info_type holder;
+
+ /* Unused */
+ (void)v;
+
+ /* Swap */
+ holder = nest_mon_info[a];
+ nest_mon_info[a] = nest_mon_info[b];
+ nest_mon_info[b] = holder;
+}
+
+
+
+/*!nest情報テーブル*/
+static vault_aux_type nest_types[] =
+{
+ { _("クローン", "clone"), vault_aux_clone, vault_prep_clone, 5, 3 },
+ { _("ゼリー", "jelly"), vault_aux_jelly, NULL, 5, 6 },
+ { _("シンボル(善)", "symbol good"), vault_aux_symbol_g, vault_prep_symbol, 25, 2 },
+ { _("シンボル(悪)", "symbol evil"), vault_aux_symbol_e, vault_prep_symbol, 25, 2 },
+ { _("ミミック", "mimic"), vault_aux_mimic, NULL, 30, 4 },
+ { _("狂気", "lovecraftian"), vault_aux_cthulhu, NULL, 70, 2 },
+ { _("犬小屋", "kennel"), vault_aux_kennel, NULL, 45, 4 },
+ { _("動物園", "animal"), vault_aux_animal, NULL, 35, 5 },
+ { _("教会", "chapel"), vault_aux_chapel_g, NULL, 75, 4 },
+ { _("アンデッド", "undead"), vault_aux_undead, NULL, 75, 5 },
+ { NULL, NULL, NULL, 0, 0 },
+};
+
+/*!pit情報テーブル*/
+static vault_aux_type pit_types[] =
+{
+ { _("オーク", "orc"), vault_aux_orc, NULL, 5, 6 },
+ { _("トロル", "troll"), vault_aux_troll, NULL, 20, 6 },
+ { _("ジャイアント", "giant"), vault_aux_giant, NULL, 50, 6 },
+ { _("狂気", "lovecraftian"), vault_aux_cthulhu, NULL, 80, 2 },
+ { _("シンボル(善)", "symbol good"), vault_aux_symbol_g, vault_prep_symbol, 70, 1 },
+ { _("シンボル(悪)", "symbol evil"), vault_aux_symbol_e, vault_prep_symbol, 70, 1 },
+ { _("教会", "chapel"), vault_aux_chapel_g, NULL, 65, 2 },
+ { _("ドラゴン", "dragon"), vault_aux_dragon, vault_prep_dragon, 70, 6 },
+ { _("デーモン", "demon"), vault_aux_demon, NULL, 80, 6 },
+ { _("ダークエルフ", "dark elf"), vault_aux_dark_elf, NULL, 45, 4 },
+ { NULL, NULL, NULL, 0, 0 },
+};
+
+
+
+
+/*!
+* @brief タイプ5の部屋…nestを生成する / Type 5 -- Monster nests
+* @return なし
+* @details
+* A monster nest is a "big" room, with an "inner" room, containing\n
+* a "collection" of monsters of a given type strewn about the room.\n
+*\n
+* The monsters are chosen from a set of 64 randomly selected monster\n
+* races, to allow the nest creation to fail instead of having "holes".\n
+*\n
+* Note the use of the "get_mon_num_prep()" function, and the special\n
+* "get_mon_num_hook()" restriction function, to prepare the "monster\n
+* allocation table" in such a way as to optimize the selection of\n
+* "appropriate" non-unique monsters for the nest.\n
+*\n
+* Note that the "get_mon_num()" function may (rarely) fail, in which\n
+* case the nest will be empty.\n
+*\n
+* Note that "monster nests" will never contain "unique" monsters.\n
+*/
+bool build_type5(void)
+{
+ POSITION y, x, y1, x1, y2, x2, xval, yval;
+ int i;
+ nest_mon_info_type nest_mon_info[NUM_NEST_MON_TYPE];
+
+ monster_type align;
+
+ cave_type *c_ptr;
+
+ int cur_nest_type = pick_vault_type(nest_types, d_info[p_ptr->dungeon_idx].nest);
+ vault_aux_type *n_ptr;
+
+ /* No type available */
+ if (cur_nest_type < 0) return FALSE;
+
+ n_ptr = &nest_types[cur_nest_type];
+
+ /* Process a preparation function if necessary */
+ if (n_ptr->prep_func) (*(n_ptr->prep_func))();
+ get_mon_num_prep(n_ptr->hook_func, NULL);
+
+ align.sub_align = SUB_ALIGN_NEUTRAL;
+
+ /* Pick some monster types */
+ for (i = 0; i < NUM_NEST_MON_TYPE; i++)
+ {
+ MONRACE_IDX r_idx = 0;
+ int attempts = 100;
+ monster_race *r_ptr = NULL;
+
+ while (attempts--)
+ {
+ /* Get a (hard) monster type */
+ r_idx = get_mon_num(dun_level + 11);
+ r_ptr = &r_info[r_idx];
+
+ /* Decline incorrect alignment */
+ if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;
+
+ /* Accept this monster */
+ break;
+ }
+
+ /* Notice failure */
+ if (!r_idx || !attempts) return FALSE;
+
+ /* Note the alignment */
+ if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;
+ if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;
+
+ nest_mon_info[i].r_idx = (s16b)r_idx;
+ nest_mon_info[i].used = FALSE;
+ }
+
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&yval, &xval, 11, 25)) return FALSE;
+
+ /* Large room */
+ y1 = yval - 4;
+ y2 = yval + 4;
+ x1 = xval - 11;
+ x2 = xval + 11;
+
+ /* Place the floor area */
+ for (y = y1 - 1; y <= y2 + 1; y++)
+ {
+ for (x = x1 - 1; x <= x2 + 1; x++)
+ {
+ c_ptr = &cave[y][x];
+ place_floor_grid(c_ptr);
+ c_ptr->info |= (CAVE_ROOM);
+ }
+ }
+
+ /* Place the outer walls */
+ for (y = y1 - 1; y <= y2 + 1; y++)
+ {
+ c_ptr = &cave[y][x1 - 1];
+ place_outer_grid(c_ptr);
+ c_ptr = &cave[y][x2 + 1];
+ place_outer_grid(c_ptr);
+ }
+ for (x = x1 - 1; x <= x2 + 1; x++)
+ {
+ c_ptr = &cave[y1 - 1][x];
+ place_outer_grid(c_ptr);
+ c_ptr = &cave[y2 + 1][x];
+ place_outer_grid(c_ptr);
+ }
+
+
+ /* Advance to the center room */
+ y1 = y1 + 2;
+ y2 = y2 - 2;
+ x1 = x1 + 2;
+ x2 = x2 - 2;
+
+ /* The inner walls */
+ for (y = y1 - 1; y <= y2 + 1; y++)
+ {
+ c_ptr = &cave[y][x1 - 1];
+ place_inner_grid(c_ptr);
+ c_ptr = &cave[y][x2 + 1];
+ place_inner_grid(c_ptr);
+ }
+
+ for (x = x1 - 1; x <= x2 + 1; x++)
+ {
+ c_ptr = &cave[y1 - 1][x];
+ place_inner_grid(c_ptr);
+ c_ptr = &cave[y2 + 1][x];
+ place_inner_grid(c_ptr);
+ }
+ for (y = y1; y <= y2; y++)
+ {
+ for (x = x1; x <= x2; x++)
+ {
+ add_cave_info(y, x, CAVE_ICKY);
+ }
+ }
+
+ /* Place a secret door */
+ switch (randint1(4))
+ {
+ case 1: place_secret_door(y1 - 1, xval, DOOR_DEFAULT); break;
+ case 2: place_secret_door(y2 + 1, xval, DOOR_DEFAULT); break;
+ case 3: place_secret_door(yval, x1 - 1, DOOR_DEFAULT); break;
+ case 4: place_secret_door(yval, x2 + 1, DOOR_DEFAULT); break;
+ }
+
+ msg_format_wizard(CHEAT_DUNGEON, _("モンスター部屋(nest)(%s%s)を生成します。", "Monster nest (%s%s)"), n_ptr->name, pit_subtype_string(cur_nest_type, TRUE));
+
+ /* Place some monsters */
+ for (y = yval - 2; y <= yval + 2; y++)
+ {
+ for (x = xval - 9; x <= xval + 9; x++)
+ {
+ MONRACE_IDX r_idx;
+
+ i = randint0(NUM_NEST_MON_TYPE);
+ r_idx = nest_mon_info[i].r_idx;
+
+ /* Place that "random" monster (no groups) */
+ (void)place_monster_aux(0, y, x, r_idx, 0L);
+
+ nest_mon_info[i].used = TRUE;
+ }
+ }
+
+ if (cheat_room)
+ {
+ ang_sort_comp = ang_sort_comp_nest_mon_info;
+ ang_sort_swap = ang_sort_swap_nest_mon_info;
+ ang_sort(nest_mon_info, NULL, NUM_NEST_MON_TYPE);
+
+ /* Dump the entries (prevent multi-printing) */
+ for (i = 0; i < NUM_NEST_MON_TYPE; i++)
+ {
+ if (!nest_mon_info[i].used) break;
+ for (; i < NUM_NEST_MON_TYPE - 1; i++)
+ {
+ if (nest_mon_info[i].r_idx != nest_mon_info[i + 1].r_idx) break;
+ if (!nest_mon_info[i + 1].used) break;
+ }
+ msg_format_wizard(CHEAT_DUNGEON, "Nest構成モンスターNo.%d:%s", i, r_name + r_info[nest_mon_info[i].r_idx].name);
+ }
+ }
+
+ return TRUE;
+}
+
+
+/*!
+* @brief タイプ6の部屋…pitを生成する / Type 6 -- Monster pits
+* @return なし
+* @details
+* A monster pit is a "big" room, with an "inner" room, containing\n
+* a "collection" of monsters of a given type organized in the room.\n
+*\n
+* The inside room in a monster pit appears as shown below, where the\n
+* actual monsters in each location depend on the type of the pit\n
+*\n
+* XXXXXXXXXXXXXXXXXXXXX\n
+* X0000000000000000000X\n
+* X0112233455543322110X\n
+* X0112233467643322110X\n
+* X0112233455543322110X\n
+* X0000000000000000000X\n
+* XXXXXXXXXXXXXXXXXXXXX\n
+*\n
+* Note that the monsters in the pit are now chosen by using "get_mon_num()"\n
+* to request 16 "appropriate" monsters, sorting them by level, and using\n
+* the "even" entries in this sorted list for the contents of the pit.\n
+*\n
+* Hack -- all of the "dragons" in a "dragon" pit must be the same "color",\n
+* which is handled by requiring a specific "breath" attack for all of the\n
+* dragons. This may include "multi-hued" breath. Note that "wyrms" may\n
+* be present in many of the dragon pits, if they have the proper breath.\n
+*\n
+* Note the use of the "get_mon_num_prep()" function, and the special\n
+* "get_mon_num_hook()" restriction function, to prepare the "monster\n
+* allocation table" in such a way as to optimize the selection of\n
+* "appropriate" non-unique monsters for the pit.\n
+*\n
+* Note that the "get_mon_num()" function may (rarely) fail, in which case\n
+* the pit will be empty.\n
+*\n
+* Note that "monster pits" will never contain "unique" monsters.\n
+*/
+bool build_type6(void)
+{
+ POSITION y, x, y1, x1, y2, x2, xval, yval;
+ int i, j;
+
+ MONRACE_IDX what[16];
+
+ monster_type align;
+
+ cave_type *c_ptr;
+
+ int cur_pit_type = pick_vault_type(pit_types, d_info[p_ptr->dungeon_idx].pit);
+ vault_aux_type *n_ptr;
+
+ /* No type available */
+ if (cur_pit_type < 0) return FALSE;
+
+ n_ptr = &pit_types[cur_pit_type];
+
+ /* Process a preparation function if necessary */
+ if (n_ptr->prep_func) (*(n_ptr->prep_func))();
+ get_mon_num_prep(n_ptr->hook_func, NULL);
+
+ align.sub_align = SUB_ALIGN_NEUTRAL;
+
+ /* Pick some monster types */
+ for (i = 0; i < 16; i++)
+ {
+ MONRACE_IDX r_idx = 0;
+ int attempts = 100;
+ monster_race *r_ptr = NULL;
+
+ while (attempts--)
+ {
+ /* Get a (hard) monster type */
+ r_idx = get_mon_num(dun_level + 11);
+ r_ptr = &r_info[r_idx];
+
+ /* Decline incorrect alignment */
+ if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;
+
+ /* Accept this monster */
+ break;
+ }
+
+ /* Notice failure */
+ if (!r_idx || !attempts) return FALSE;
+
+ /* Note the alignment */
+ if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;
+ if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;
+
+ what[i] = r_idx;
+ }
+
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&yval, &xval, 11, 25)) return FALSE;
+
+ /* Large room */
+ y1 = yval - 4;
+ y2 = yval + 4;
+ x1 = xval - 11;
+ x2 = xval + 11;
+
+ /* Place the floor area */
+ for (y = y1 - 1; y <= y2 + 1; y++)
+ {
+ for (x = x1 - 1; x <= x2 + 1; x++)
+ {
+ c_ptr = &cave[y][x];
+ place_floor_grid(c_ptr);
+ c_ptr->info |= (CAVE_ROOM);
+ }
+ }
+
+ /* Place the outer walls */
+ for (y = y1 - 1; y <= y2 + 1; y++)
+ {
+ c_ptr = &cave[y][x1 - 1];
+ place_outer_grid(c_ptr);
+ c_ptr = &cave[y][x2 + 1];
+ place_outer_grid(c_ptr);
+ }
+ for (x = x1 - 1; x <= x2 + 1; x++)
+ {
+ c_ptr = &cave[y1 - 1][x];
+ place_outer_grid(c_ptr);
+ c_ptr = &cave[y2 + 1][x];
+ place_outer_grid(c_ptr);
+ }
+
+ /* Advance to the center room */
+ y1 = y1 + 2;
+ y2 = y2 - 2;
+ x1 = x1 + 2;
+ x2 = x2 - 2;
+
+ /* The inner walls */
+ for (y = y1 - 1; y <= y2 + 1; y++)
+ {
+ c_ptr = &cave[y][x1 - 1];
+ place_inner_grid(c_ptr);
+ c_ptr = &cave[y][x2 + 1];
+ place_inner_grid(c_ptr);
+ }
+ for (x = x1 - 1; x <= x2 + 1; x++)
+ {
+ c_ptr = &cave[y1 - 1][x];
+ place_inner_grid(c_ptr);
+ c_ptr = &cave[y2 + 1][x];
+ place_inner_grid(c_ptr);
+ }
+ for (y = y1; y <= y2; y++)
+ {
+ for (x = x1; x <= x2; x++)
+ {
+ add_cave_info(y, x, CAVE_ICKY);
+ }
+ }
+
+ /* Place a secret door */
+ switch (randint1(4))
+ {
+ case 1: place_secret_door(y1 - 1, xval, DOOR_DEFAULT); break;
+ case 2: place_secret_door(y2 + 1, xval, DOOR_DEFAULT); break;
+ case 3: place_secret_door(yval, x1 - 1, DOOR_DEFAULT); break;
+ case 4: place_secret_door(yval, x2 + 1, DOOR_DEFAULT); break;
+ }
+
+ /* Sort the entries */
+ for (i = 0; i < 16 - 1; i++)
+ {
+ /* Sort the entries */
+ for (j = 0; j < 16 - 1; j++)
+ {
+ int i1 = j;
+ int i2 = j + 1;
+
+ int p1 = r_info[what[i1]].level;
+ int p2 = r_info[what[i2]].level;
+
+ /* Bubble */
+ if (p1 > p2)
+ {
+ MONRACE_IDX tmp = what[i1];
+ what[i1] = what[i2];
+ what[i2] = tmp;
+ }
+ }
+ }
+
+ msg_format_wizard(CHEAT_DUNGEON, _("モンスター部屋(pit)(%s%s)を生成します。", "Monster pit (%s%s)"), n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
+
+ /* Select the entries */
+ for (i = 0; i < 8; i++)
+ {
+ /* Every other entry */
+ what[i] = what[i * 2];
+ msg_format_wizard(CHEAT_DUNGEON, _("Nest構成モンスター選択No.%d:%s", "Nest Monster Select No.%d:%s"), i, r_name + r_info[what[i]].name);
+ }
+
+ /* Top and bottom rows */
+ for (x = xval - 9; x <= xval + 9; x++)
+ {
+ place_monster_aux(0, yval - 2, x, what[0], PM_NO_KAGE);
+ place_monster_aux(0, yval + 2, x, what[0], PM_NO_KAGE);
+ }
+
+ /* Middle columns */
+ for (y = yval - 1; y <= yval + 1; y++)
+ {
+ place_monster_aux(0, y, xval - 9, what[0], PM_NO_KAGE);
+ place_monster_aux(0, y, xval + 9, what[0], PM_NO_KAGE);
+
+ place_monster_aux(0, y, xval - 8, what[1], PM_NO_KAGE);
+ place_monster_aux(0, y, xval + 8, what[1], PM_NO_KAGE);
+
+ place_monster_aux(0, y, xval - 7, what[1], PM_NO_KAGE);
+ place_monster_aux(0, y, xval + 7, what[1], PM_NO_KAGE);
+
+ place_monster_aux(0, y, xval - 6, what[2], PM_NO_KAGE);
+ place_monster_aux(0, y, xval + 6, what[2], PM_NO_KAGE);
+
+ place_monster_aux(0, y, xval - 5, what[2], PM_NO_KAGE);
+ place_monster_aux(0, y, xval + 5, what[2], PM_NO_KAGE);
+
+ place_monster_aux(0, y, xval - 4, what[3], PM_NO_KAGE);
+ place_monster_aux(0, y, xval + 4, what[3], PM_NO_KAGE);
+
+ place_monster_aux(0, y, xval - 3, what[3], PM_NO_KAGE);
+ place_monster_aux(0, y, xval + 3, what[3], PM_NO_KAGE);
+
+ place_monster_aux(0, y, xval - 2, what[4], PM_NO_KAGE);
+ place_monster_aux(0, y, xval + 2, what[4], PM_NO_KAGE);
+ }
+
+ /* Above/Below the center monster */
+ for (x = xval - 1; x <= xval + 1; x++)
+ {
+ place_monster_aux(0, yval + 1, x, what[5], PM_NO_KAGE);
+ place_monster_aux(0, yval - 1, x, what[5], PM_NO_KAGE);
+ }
+
+ /* Next to the center monster */
+ place_monster_aux(0, yval, xval + 1, what[6], PM_NO_KAGE);
+ place_monster_aux(0, yval, xval - 1, what[6], PM_NO_KAGE);
+
+ /* Center monster */
+ place_monster_aux(0, yval, xval, what[7], PM_NO_KAGE);
+
+ return TRUE;
+}
+
+
+
+/*
+* Helper function for "trapped monster pit"
+*/
+static bool vault_aux_trapped_pit(MONRACE_IDX r_idx)
+{
+ monster_race *r_ptr = &r_info[r_idx];
+
+ if (!vault_monster_okay(r_idx)) return (FALSE);
+
+ /* No wall passing monster */
+ if (r_ptr->flags2 & (RF2_PASS_WALL | RF2_KILL_WALL)) return (FALSE);
+
+ return (TRUE);
+}
+
+
+/*!
+* @brief タイプ13の部屋…トラップpitの生成 / Type 13 -- Trapped monster pits
+* @return なし
+* @details
+* A trapped monster pit is a "big" room with a straight corridor in\n
+* which wall opening traps are placed, and with two "inner" rooms\n
+* containing a "collection" of monsters of a given type organized in\n
+* the room.\n
+*\n
+* The trapped monster pit appears as shown below, where the actual\n
+* monsters in each location depend on the type of the pit\n
+*\n
+* XXXXXXXXXXXXXXXXXXXXXXXXX\n
+* X X\n
+* XXXXXXXXXXXXXXXXXXXXXXX X\n
+* XXXXX001123454321100XXX X\n
+* XXX0012234567654322100X X\n
+* XXXXXXXXXXXXXXXXXXXXXXX X\n
+* X ^ X\n
+* X XXXXXXXXXXXXXXXXXXXXXXX\n
+* X X0012234567654322100XXX\n
+* X XXX001123454321100XXXXX\n
+* X XXXXXXXXXXXXXXXXXXXXXXX\n
+* X X\n
+* XXXXXXXXXXXXXXXXXXXXXXXXX\n
+*\n
+* Note that the monsters in the pit are now chosen by using "get_mon_num()"\n
+* to request 16 "appropriate" monsters, sorting them by level, and using\n
+* the "even" entries in this sorted list for the contents of the pit.\n
+*\n
+* Hack -- all of the "dragons" in a "dragon" pit must be the same "color",\n
+* which is handled by requiring a specific "breath" attack for all of the\n
+* dragons. This may include "multi-hued" breath. Note that "wyrms" may\n
+* be present in many of the dragon pits, if they have the proper breath.\n
+*\n
+* Note the use of the "get_mon_num_prep()" function, and the special\n
+* "get_mon_num_hook()" restriction function, to prepare the "monster\n
+* allocation table" in such a way as to optimize the selection of\n
+* "appropriate" non-unique monsters for the pit.\n
+*\n
+* Note that the "get_mon_num()" function may (rarely) fail, in which case\n
+* the pit will be empty.\n
+*\n
+* Note that "monster pits" will never contain "unique" monsters.\n
+*/
+bool build_type13(void)
+{
+ static int placing[][3] = {
+ { -2, -9, 0 },{ -2, -8, 0 },{ -3, -7, 0 },{ -3, -6, 0 },
+ { +2, -9, 0 },{ +2, -8, 0 },{ +3, -7, 0 },{ +3, -6, 0 },
+ { -2, +9, 0 },{ -2, +8, 0 },{ -3, +7, 0 },{ -3, +6, 0 },
+ { +2, +9, 0 },{ +2, +8, 0 },{ +3, +7, 0 },{ +3, +6, 0 },
+ { -2, -7, 1 },{ -3, -5, 1 },{ -3, -4, 1 },
+ { +2, -7, 1 },{ +3, -5, 1 },{ +3, -4, 1 },
+ { -2, +7, 1 },{ -3, +5, 1 },{ -3, +4, 1 },
+ { +2, +7, 1 },{ +3, +5, 1 },{ +3, +4, 1 },
+ { -2, -6, 2 },{ -2, -5, 2 },{ -3, -3, 2 },
+ { +2, -6, 2 },{ +2, -5, 2 },{ +3, -3, 2 },
+ { -2, +6, 2 },{ -2, +5, 2 },{ -3, +3, 2 },
+ { +2, +6, 2 },{ +2, +5, 2 },{ +3, +3, 2 },
+ { -2, -4, 3 },{ -3, -2, 3 },
+ { +2, -4, 3 },{ +3, -2, 3 },
+ { -2, +4, 3 },{ -3, +2, 3 },
+ { +2, +4, 3 },{ +3, +2, 3 },
+ { -2, -3, 4 },{ -3, -1, 4 },
+ { +2, -3, 4 },{ +3, -1, 4 },
+ { -2, +3, 4 },{ -3, +1, 4 },
+ { +2, +3, 4 },{ +3, +1, 4 },
+ { -2, -2, 5 },{ -3, 0, 5 },{ -2, +2, 5 },
+ { +2, -2, 5 },{ +3, 0, 5 },{ +2, +2, 5 },
+ { -2, -1, 6 },{ -2, +1, 6 },
+ { +2, -1, 6 },{ +2, +1, 6 },
+ { -2, 0, 7 },{ +2, 0, 7 },
+ { 0, 0, -1 }
+ };
+
+ POSITION y, x, y1, x1, y2, x2, xval, yval;
+ int i, j;
+
+ MONRACE_IDX what[16];
+
+ monster_type align;
+
+ cave_type *c_ptr;
+
+ int cur_pit_type = pick_vault_type(pit_types, d_info[p_ptr->dungeon_idx].pit);
+ vault_aux_type *n_ptr;
+
+ /* Only in Angband */
+ if (p_ptr->dungeon_idx != DUNGEON_ANGBAND) return FALSE;
+
+ /* No type available */
+ if (cur_pit_type < 0) return FALSE;
+
+ n_ptr = &pit_types[cur_pit_type];
+
+ /* Process a preparation function if necessary */
+ if (n_ptr->prep_func) (*(n_ptr->prep_func))();
+ get_mon_num_prep(n_ptr->hook_func, vault_aux_trapped_pit);
+
+ align.sub_align = SUB_ALIGN_NEUTRAL;
+
+ /* Pick some monster types */
+ for (i = 0; i < 16; i++)
+ {
+ MONRACE_IDX r_idx = 0;
+ int attempts = 100;
+ monster_race *r_ptr = NULL;
+
+ while (attempts--)
+ {
+ /* Get a (hard) monster type */
+ r_idx = get_mon_num(dun_level + 0);
+ r_ptr = &r_info[r_idx];
+
+ /* Decline incorrect alignment */
+ if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;
+
+ /* Accept this monster */
+ break;
+ }
+
+ /* Notice failure */
+ if (!r_idx || !attempts) return FALSE;
+
+ /* Note the alignment */
+ if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;
+ if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;
+
+ what[i] = r_idx;
+ }
+
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&yval, &xval, 13, 25)) return FALSE;
+
+ /* Large room */
+ y1 = yval - 5;
+ y2 = yval + 5;
+ x1 = xval - 11;
+ x2 = xval + 11;
+
+ /* Fill with inner walls */
+ for (y = y1 - 1; y <= y2 + 1; y++)
+ {
+ for (x = x1 - 1; x <= x2 + 1; x++)
+ {
+ c_ptr = &cave[y][x];
+ place_inner_grid(c_ptr);
+ c_ptr->info |= (CAVE_ROOM);
+ }
+ }
+
+ /* Place the floor area 1 */
+ for (x = x1 + 3; x <= x2 - 3; x++)
+ {
+ c_ptr = &cave[yval - 2][x];
+ place_floor_grid(c_ptr);
+ add_cave_info(yval - 2, x, CAVE_ICKY);
+
+ c_ptr = &cave[yval + 2][x];
+ place_floor_grid(c_ptr);
+ add_cave_info(yval + 2, x, CAVE_ICKY);
+ }
+
+ /* Place the floor area 2 */
+ for (x = x1 + 5; x <= x2 - 5; x++)
+ {
+ c_ptr = &cave[yval - 3][x];
+ place_floor_grid(c_ptr);
+ add_cave_info(yval - 3, x, CAVE_ICKY);
+
+ c_ptr = &cave[yval + 3][x];
+ place_floor_grid(c_ptr);
+ add_cave_info(yval + 3, x, CAVE_ICKY);
+ }
+
+ /* Corridor */
+ for (x = x1; x <= x2; x++)
+ {
+ c_ptr = &cave[yval][x];
+ place_floor_grid(c_ptr);
+ c_ptr = &cave[y1][x];
+ place_floor_grid(c_ptr);
+ c_ptr = &cave[y2][x];
+ place_floor_grid(c_ptr);
+ }
+
+ /* Place the outer walls */
+ for (y = y1 - 1; y <= y2 + 1; y++)
+ {
+ c_ptr = &cave[y][x1 - 1];
+ place_outer_grid(c_ptr);
+ c_ptr = &cave[y][x2 + 1];
+ place_outer_grid(c_ptr);
+ }
+ for (x = x1 - 1; x <= x2 + 1; x++)
+ {
+ c_ptr = &cave[y1 - 1][x];
+ place_outer_grid(c_ptr);
+ c_ptr = &cave[y2 + 1][x];
+ place_outer_grid(c_ptr);
+ }
+
+ /* Random corridor */
+ if (one_in_(2))
+ {
+ for (y = y1; y <= yval; y++)
+ {
+ place_floor_bold(y, x2);
+ place_solid_bold(y, x1 - 1);
+ }
+ for (y = yval; y <= y2 + 1; y++)
+ {
+ place_floor_bold(y, x1);
+ place_solid_bold(y, x2 + 1);
+ }
+ }
+ else
+ {
+ for (y = yval; y <= y2 + 1; y++)
+ {
+ place_floor_bold(y, x1);
+ place_solid_bold(y, x2 + 1);
+ }
+ for (y = y1; y <= yval; y++)
+ {
+ place_floor_bold(y, x2);
+ place_solid_bold(y, x1 - 1);
+ }
+ }
+
+ /* Place the wall open trap */
+ cave[yval][xval].mimic = cave[yval][xval].feat;
+ cave[yval][xval].feat = feat_trap_open;
+
+ /* Sort the entries */
+ for (i = 0; i < 16 - 1; i++)
+ {
+ /* Sort the entries */
+ for (j = 0; j < 16 - 1; j++)
+ {
+ int i1 = j;
+ int i2 = j + 1;
+
+ int p1 = r_info[what[i1]].level;
+ int p2 = r_info[what[i2]].level;
+
+ /* Bubble */
+ if (p1 > p2)
+ {
+ MONRACE_IDX tmp = what[i1];
+ what[i1] = what[i2];
+ what[i2] = tmp;
+ }
+ }
+ }
+
+ msg_format_wizard(CHEAT_DUNGEON, _("%s%sの罠ピットが生成されました。", "Trapped monster pit (%s%s)"),
+ n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
+
+ /* Select the entries */
+ for (i = 0; i < 8; i++)
+ {
+ /* Every other entry */
+ what[i] = what[i * 2];
+
+ if (cheat_hear)
+ {
+ msg_print(r_name + r_info[what[i]].name);
+ }
+ }
+
+ for (i = 0; placing[i][2] >= 0; i++)
+ {
+ y = yval + placing[i][0];
+ x = xval + placing[i][1];
+ place_monster_aux(0, y, x, what[placing[i][2]], PM_NO_KAGE);
+ }
+
+ return TRUE;
+}
+
-\r
-/*! デバッグ時にnestのモンスター情報を確認するための構造体 / A struct for nest monster information with cheat_hear */\r
-typedef struct\r
-{\r
- MONRACE_IDX r_idx;\r
- bool used;\r
-}\r
-nest_mon_info_type;\r
-\r
-extern bool build_type5(void);\r
-extern bool build_type6(void);\r
-extern bool build_type13(void);\r
+
+/*! デバッグ時にnestのモンスター情報を確認するための構造体 / A struct for nest monster information with cheat_hear */
+typedef struct
+{
+ MONRACE_IDX r_idx;
+ bool used;
+}
+nest_mon_info_type;
+
+extern bool build_type5(void);
+extern bool build_type6(void);
+extern bool build_type13(void);
-#include "angband.h"\r
-#include "grid.h"\r
-#include "generate.h"\r
-#include "rooms.h"\r
-#include "monster.h"\r
-#include "monsterrace-hook.h"\r
-#include "objectkind-hook.h"\r
-\r
-\r
-/*!\r
-* @brief タイプ15の部屋…ガラス部屋の生成 / Type 15 -- glass rooms\r
-* @return なし\r
-*/\r
-bool build_type15(void)\r
-{\r
- POSITION y, x, y2, x2, yval, xval;\r
- POSITION y1, x1, xsize, ysize;\r
- bool light;\r
-\r
- cave_type *c_ptr;\r
-\r
- /* Pick a room size */\r
- xsize = rand_range(9, 13);\r
- ysize = rand_range(9, 13);\r
-\r
- /* Find and reserve some space in the dungeon. Get center of room. */\r
- if (!find_space(&yval, &xval, ysize + 2, xsize + 2)) return FALSE;\r
-\r
- /* Choose lite or dark */\r
- light = ((dun_level <= randint1(25)) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS));\r
-\r
- /* Get corner values */\r
- y1 = yval - ysize / 2;\r
- x1 = xval - xsize / 2;\r
- y2 = yval + (ysize - 1) / 2;\r
- x2 = xval + (xsize - 1) / 2;\r
-\r
- /* Place a full floor under the room */\r
- for (y = y1 - 1; y <= y2 + 1; y++)\r
- {\r
- for (x = x1 - 1; x <= x2 + 1; x++)\r
- {\r
- c_ptr = &cave[y][x];\r
- place_floor_grid(c_ptr);\r
- c_ptr->feat = feat_glass_floor;\r
- c_ptr->info |= (CAVE_ROOM);\r
- if (light) c_ptr->info |= (CAVE_GLOW);\r
- }\r
- }\r
-\r
- /* Walls around the room */\r
- for (y = y1 - 1; y <= y2 + 1; y++)\r
- {\r
- c_ptr = &cave[y][x1 - 1];\r
- place_outer_grid(c_ptr);\r
- c_ptr->feat = feat_glass_wall;\r
- c_ptr = &cave[y][x2 + 1];\r
- place_outer_grid(c_ptr);\r
- c_ptr->feat = feat_glass_wall;\r
- }\r
- for (x = x1 - 1; x <= x2 + 1; x++)\r
- {\r
- c_ptr = &cave[y1 - 1][x];\r
- place_outer_grid(c_ptr);\r
- c_ptr->feat = feat_glass_wall;\r
- c_ptr = &cave[y2 + 1][x];\r
- place_outer_grid(c_ptr);\r
- c_ptr->feat = feat_glass_wall;\r
- }\r
-\r
- switch (randint1(3))\r
- {\r
- case 1: /* 4 lite breathers + potion */\r
- {\r
- int dir1, dir2;\r
- get_mon_num_prep(vault_aux_lite, NULL);\r
-\r
- /* Place fixed lite berathers */\r
- for (dir1 = 4; dir1 < 8; dir1++)\r
- {\r
- MONRACE_IDX r_idx = get_mon_num(dun_level);\r
-\r
- y = yval + 2 * ddy_ddd[dir1];\r
- x = xval + 2 * ddx_ddd[dir1];\r
- if (r_idx) place_monster_aux(0, y, x, r_idx, PM_ALLOW_SLEEP);\r
-\r
- /* Walls around the breather */\r
- for (dir2 = 0; dir2 < 8; dir2++)\r
- {\r
- c_ptr = &cave[y + ddy_ddd[dir2]][x + ddx_ddd[dir2]];\r
- place_inner_grid(c_ptr);\r
- c_ptr->feat = feat_glass_wall;\r
- }\r
- }\r
-\r
- /* Walls around the potion */\r
- for (dir1 = 0; dir1 < 4; dir1++)\r
- {\r
- y = yval + 2 * ddy_ddd[dir1];\r
- x = xval + 2 * ddx_ddd[dir1];\r
- c_ptr = &cave[y][x];\r
- place_inner_perm_grid(c_ptr);\r
- c_ptr->feat = feat_permanent_glass_wall;\r
- cave[yval + ddy_ddd[dir1]][xval + ddx_ddd[dir1]].info |= (CAVE_ICKY);\r
- }\r
-\r
- /* Glass door */\r
- dir1 = randint0(4);\r
- y = yval + 2 * ddy_ddd[dir1];\r
- x = xval + 2 * ddx_ddd[dir1];\r
- place_secret_door(y, x, DOOR_GLASS_DOOR);\r
- c_ptr = &cave[y][x];\r
- if (is_closed_door(c_ptr->feat)) c_ptr->mimic = feat_glass_wall;\r
-\r
- /* Place a potion */\r
- get_obj_num_hook = kind_is_potion;\r
- place_object(yval, xval, AM_NO_FIXED_ART);\r
- cave[yval][xval].info |= (CAVE_ICKY);\r
- }\r
- break;\r
-\r
- case 2: /* 1 lite breather + random object */\r
- {\r
- MONRACE_IDX r_idx;\r
- DIRECTION dir1;\r
-\r
- /* Pillars */\r
- c_ptr = &cave[y1 + 1][x1 + 1];\r
- place_inner_grid(c_ptr);\r
- c_ptr->feat = feat_glass_wall;\r
-\r
- c_ptr = &cave[y1 + 1][x2 - 1];\r
- place_inner_grid(c_ptr);\r
- c_ptr->feat = feat_glass_wall;\r
-\r
- c_ptr = &cave[y2 - 1][x1 + 1];\r
- place_inner_grid(c_ptr);\r
- c_ptr->feat = feat_glass_wall;\r
-\r
- c_ptr = &cave[y2 - 1][x2 - 1];\r
- place_inner_grid(c_ptr);\r
- c_ptr->feat = feat_glass_wall;\r
- get_mon_num_prep(vault_aux_lite, NULL);\r
-\r
- r_idx = get_mon_num(dun_level);\r
- if (r_idx) place_monster_aux(0, yval, xval, r_idx, 0L);\r
-\r
- /* Walls around the breather */\r
- for (dir1 = 0; dir1 < 8; dir1++)\r
- {\r
- c_ptr = &cave[yval + ddy_ddd[dir1]][xval + ddx_ddd[dir1]];\r
- place_inner_grid(c_ptr);\r
- c_ptr->feat = feat_glass_wall;\r
- }\r
-\r
- /* Curtains around the breather */\r
- for (y = yval - 1; y <= yval + 1; y++)\r
- {\r
- place_closed_door(y, xval - 2, DOOR_CURTAIN);\r
- place_closed_door(y, xval + 2, DOOR_CURTAIN);\r
- }\r
- for (x = xval - 1; x <= xval + 1; x++)\r
- {\r
- place_closed_door(yval - 2, x, DOOR_CURTAIN);\r
- place_closed_door(yval + 2, x, DOOR_CURTAIN);\r
- }\r
-\r
- /* Place an object */\r
- place_object(yval, xval, AM_NO_FIXED_ART);\r
- cave[yval][xval].info |= (CAVE_ICKY);\r
- }\r
- break;\r
-\r
- case 3: /* 4 shards breathers + 2 potions */\r
- {\r
- DIRECTION dir1;\r
-\r
- /* Walls around the potion */\r
- for (y = yval - 2; y <= yval + 2; y++)\r
- {\r
- c_ptr = &cave[y][xval - 3];\r
- place_inner_grid(c_ptr);\r
- c_ptr->feat = feat_glass_wall;\r
- c_ptr = &cave[y][xval + 3];\r
- place_inner_grid(c_ptr);\r
- c_ptr->feat = feat_glass_wall;\r
- }\r
- for (x = xval - 2; x <= xval + 2; x++)\r
- {\r
- c_ptr = &cave[yval - 3][x];\r
- place_inner_grid(c_ptr);\r
- c_ptr->feat = feat_glass_wall;\r
- c_ptr = &cave[yval + 3][x];\r
- place_inner_grid(c_ptr);\r
- c_ptr->feat = feat_glass_wall;\r
- }\r
- for (dir1 = 4; dir1 < 8; dir1++)\r
- {\r
- c_ptr = &cave[yval + 2 * ddy_ddd[dir1]][xval + 2 * ddx_ddd[dir1]];\r
- place_inner_grid(c_ptr);\r
- c_ptr->feat = feat_glass_wall;\r
- }\r
- get_mon_num_prep(vault_aux_shards, NULL);\r
-\r
- /* Place shard berathers */\r
- for (dir1 = 4; dir1 < 8; dir1++)\r
- {\r
- MONRACE_IDX r_idx = get_mon_num(dun_level);\r
-\r
- y = yval + ddy_ddd[dir1];\r
- x = xval + ddx_ddd[dir1];\r
- if (r_idx) place_monster_aux(0, y, x, r_idx, 0L);\r
- }\r
-\r
- /* Place two potions */\r
- if (one_in_(2))\r
- {\r
- get_obj_num_hook = kind_is_potion;\r
- place_object(yval, xval - 1, AM_NO_FIXED_ART);\r
- get_obj_num_hook = kind_is_potion;\r
- place_object(yval, xval + 1, AM_NO_FIXED_ART);\r
- }\r
- else\r
- {\r
- get_obj_num_hook = kind_is_potion;\r
- place_object(yval - 1, xval, AM_NO_FIXED_ART);\r
- get_obj_num_hook = kind_is_potion;\r
- place_object(yval + 1, xval, AM_NO_FIXED_ART);\r
- }\r
-\r
- for (y = yval - 2; y <= yval + 2; y++)\r
- for (x = xval - 2; x <= xval + 2; x++)\r
- cave[y][x].info |= (CAVE_ICKY);\r
-\r
- }\r
- break;\r
- }\r
-\r
- msg_print_wizard(CHEAT_DUNGEON, _("ガラスの部屋が生成されました。", "Glass room was generated."));\r
-\r
- return TRUE;\r
-}\r
+#include "angband.h"
+#include "grid.h"
+#include "generate.h"
+#include "rooms.h"
+#include "monster.h"
+#include "monsterrace-hook.h"
+#include "objectkind-hook.h"
+
+
+/*!
+* @brief タイプ15の部屋…ガラス部屋の生成 / Type 15 -- glass rooms
+* @return なし
+*/
+bool build_type15(void)
+{
+ POSITION y, x, y2, x2, yval, xval;
+ POSITION y1, x1, xsize, ysize;
+ bool light;
+
+ cave_type *c_ptr;
+
+ /* Pick a room size */
+ xsize = rand_range(9, 13);
+ ysize = rand_range(9, 13);
+
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&yval, &xval, ysize + 2, xsize + 2)) return FALSE;
+
+ /* Choose lite or dark */
+ light = ((dun_level <= randint1(25)) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS));
+
+ /* Get corner values */
+ y1 = yval - ysize / 2;
+ x1 = xval - xsize / 2;
+ y2 = yval + (ysize - 1) / 2;
+ x2 = xval + (xsize - 1) / 2;
+
+ /* Place a full floor under the room */
+ for (y = y1 - 1; y <= y2 + 1; y++)
+ {
+ for (x = x1 - 1; x <= x2 + 1; x++)
+ {
+ c_ptr = &cave[y][x];
+ place_floor_grid(c_ptr);
+ c_ptr->feat = feat_glass_floor;
+ c_ptr->info |= (CAVE_ROOM);
+ if (light) c_ptr->info |= (CAVE_GLOW);
+ }
+ }
+
+ /* Walls around the room */
+ for (y = y1 - 1; y <= y2 + 1; y++)
+ {
+ c_ptr = &cave[y][x1 - 1];
+ place_outer_grid(c_ptr);
+ c_ptr->feat = feat_glass_wall;
+ c_ptr = &cave[y][x2 + 1];
+ place_outer_grid(c_ptr);
+ c_ptr->feat = feat_glass_wall;
+ }
+ for (x = x1 - 1; x <= x2 + 1; x++)
+ {
+ c_ptr = &cave[y1 - 1][x];
+ place_outer_grid(c_ptr);
+ c_ptr->feat = feat_glass_wall;
+ c_ptr = &cave[y2 + 1][x];
+ place_outer_grid(c_ptr);
+ c_ptr->feat = feat_glass_wall;
+ }
+
+ switch (randint1(3))
+ {
+ case 1: /* 4 lite breathers + potion */
+ {
+ int dir1, dir2;
+ get_mon_num_prep(vault_aux_lite, NULL);
+
+ /* Place fixed lite berathers */
+ for (dir1 = 4; dir1 < 8; dir1++)
+ {
+ MONRACE_IDX r_idx = get_mon_num(dun_level);
+
+ y = yval + 2 * ddy_ddd[dir1];
+ x = xval + 2 * ddx_ddd[dir1];
+ if (r_idx) place_monster_aux(0, y, x, r_idx, PM_ALLOW_SLEEP);
+
+ /* Walls around the breather */
+ for (dir2 = 0; dir2 < 8; dir2++)
+ {
+ c_ptr = &cave[y + ddy_ddd[dir2]][x + ddx_ddd[dir2]];
+ place_inner_grid(c_ptr);
+ c_ptr->feat = feat_glass_wall;
+ }
+ }
+
+ /* Walls around the potion */
+ for (dir1 = 0; dir1 < 4; dir1++)
+ {
+ y = yval + 2 * ddy_ddd[dir1];
+ x = xval + 2 * ddx_ddd[dir1];
+ c_ptr = &cave[y][x];
+ place_inner_perm_grid(c_ptr);
+ c_ptr->feat = feat_permanent_glass_wall;
+ cave[yval + ddy_ddd[dir1]][xval + ddx_ddd[dir1]].info |= (CAVE_ICKY);
+ }
+
+ /* Glass door */
+ dir1 = randint0(4);
+ y = yval + 2 * ddy_ddd[dir1];
+ x = xval + 2 * ddx_ddd[dir1];
+ place_secret_door(y, x, DOOR_GLASS_DOOR);
+ c_ptr = &cave[y][x];
+ if (is_closed_door(c_ptr->feat)) c_ptr->mimic = feat_glass_wall;
+
+ /* Place a potion */
+ get_obj_num_hook = kind_is_potion;
+ place_object(yval, xval, AM_NO_FIXED_ART);
+ cave[yval][xval].info |= (CAVE_ICKY);
+ }
+ break;
+
+ case 2: /* 1 lite breather + random object */
+ {
+ MONRACE_IDX r_idx;
+ DIRECTION dir1;
+
+ /* Pillars */
+ c_ptr = &cave[y1 + 1][x1 + 1];
+ place_inner_grid(c_ptr);
+ c_ptr->feat = feat_glass_wall;
+
+ c_ptr = &cave[y1 + 1][x2 - 1];
+ place_inner_grid(c_ptr);
+ c_ptr->feat = feat_glass_wall;
+
+ c_ptr = &cave[y2 - 1][x1 + 1];
+ place_inner_grid(c_ptr);
+ c_ptr->feat = feat_glass_wall;
+
+ c_ptr = &cave[y2 - 1][x2 - 1];
+ place_inner_grid(c_ptr);
+ c_ptr->feat = feat_glass_wall;
+ get_mon_num_prep(vault_aux_lite, NULL);
+
+ r_idx = get_mon_num(dun_level);
+ if (r_idx) place_monster_aux(0, yval, xval, r_idx, 0L);
+
+ /* Walls around the breather */
+ for (dir1 = 0; dir1 < 8; dir1++)
+ {
+ c_ptr = &cave[yval + ddy_ddd[dir1]][xval + ddx_ddd[dir1]];
+ place_inner_grid(c_ptr);
+ c_ptr->feat = feat_glass_wall;
+ }
+
+ /* Curtains around the breather */
+ for (y = yval - 1; y <= yval + 1; y++)
+ {
+ place_closed_door(y, xval - 2, DOOR_CURTAIN);
+ place_closed_door(y, xval + 2, DOOR_CURTAIN);
+ }
+ for (x = xval - 1; x <= xval + 1; x++)
+ {
+ place_closed_door(yval - 2, x, DOOR_CURTAIN);
+ place_closed_door(yval + 2, x, DOOR_CURTAIN);
+ }
+
+ /* Place an object */
+ place_object(yval, xval, AM_NO_FIXED_ART);
+ cave[yval][xval].info |= (CAVE_ICKY);
+ }
+ break;
+
+ case 3: /* 4 shards breathers + 2 potions */
+ {
+ DIRECTION dir1;
+
+ /* Walls around the potion */
+ for (y = yval - 2; y <= yval + 2; y++)
+ {
+ c_ptr = &cave[y][xval - 3];
+ place_inner_grid(c_ptr);
+ c_ptr->feat = feat_glass_wall;
+ c_ptr = &cave[y][xval + 3];
+ place_inner_grid(c_ptr);
+ c_ptr->feat = feat_glass_wall;
+ }
+ for (x = xval - 2; x <= xval + 2; x++)
+ {
+ c_ptr = &cave[yval - 3][x];
+ place_inner_grid(c_ptr);
+ c_ptr->feat = feat_glass_wall;
+ c_ptr = &cave[yval + 3][x];
+ place_inner_grid(c_ptr);
+ c_ptr->feat = feat_glass_wall;
+ }
+ for (dir1 = 4; dir1 < 8; dir1++)
+ {
+ c_ptr = &cave[yval + 2 * ddy_ddd[dir1]][xval + 2 * ddx_ddd[dir1]];
+ place_inner_grid(c_ptr);
+ c_ptr->feat = feat_glass_wall;
+ }
+ get_mon_num_prep(vault_aux_shards, NULL);
+
+ /* Place shard berathers */
+ for (dir1 = 4; dir1 < 8; dir1++)
+ {
+ MONRACE_IDX r_idx = get_mon_num(dun_level);
+
+ y = yval + ddy_ddd[dir1];
+ x = xval + ddx_ddd[dir1];
+ if (r_idx) place_monster_aux(0, y, x, r_idx, 0L);
+ }
+
+ /* Place two potions */
+ if (one_in_(2))
+ {
+ get_obj_num_hook = kind_is_potion;
+ place_object(yval, xval - 1, AM_NO_FIXED_ART);
+ get_obj_num_hook = kind_is_potion;
+ place_object(yval, xval + 1, AM_NO_FIXED_ART);
+ }
+ else
+ {
+ get_obj_num_hook = kind_is_potion;
+ place_object(yval - 1, xval, AM_NO_FIXED_ART);
+ get_obj_num_hook = kind_is_potion;
+ place_object(yval + 1, xval, AM_NO_FIXED_ART);
+ }
+
+ for (y = yval - 2; y <= yval + 2; y++)
+ for (x = xval - 2; x <= xval + 2; x++)
+ cave[y][x].info |= (CAVE_ICKY);
+
+ }
+ break;
+ }
+
+ msg_print_wizard(CHEAT_DUNGEON, _("ガラスの部屋が生成されました。", "Glass room was generated."));
+
+ return TRUE;
+}
-extern bool build_type15(void);\r
-\r
+extern bool build_type15(void);
+
-#include "angband.h"\r
-#include "grid.h"\r
-#include "generate.h"\r
-#include "rooms.h"\r
-\r
-\r
-/*!\r
-* @brief タイプ14の部屋…特殊トラップ部屋の生成 / Type 14 -- trapped rooms\r
-* @return なし\r
-* @details\r
-* A special trap is placed at center of the room\r
-*/\r
-bool build_type14(void)\r
-{\r
- POSITION y, x, y2, x2, yval, xval;\r
- POSITION y1, x1, xsize, ysize;\r
-\r
- bool light;\r
-\r
- cave_type *c_ptr;\r
- s16b trap;\r
-\r
- /* Pick a room size */\r
- y1 = randint1(4);\r
- x1 = randint1(11);\r
- y2 = randint1(3);\r
- x2 = randint1(11);\r
-\r
- xsize = x1 + x2 + 1;\r
- ysize = y1 + y2 + 1;\r
-\r
- /* Find and reserve some space in the dungeon. Get center of room. */\r
- if (!find_space(&yval, &xval, ysize + 2, xsize + 2)) return FALSE;\r
-\r
- /* Choose lite or dark */\r
- light = ((dun_level <= randint1(25)) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS));\r
-\r
-\r
- /* Get corner values */\r
- y1 = yval - ysize / 2;\r
- x1 = xval - xsize / 2;\r
- y2 = yval + (ysize - 1) / 2;\r
- x2 = xval + (xsize - 1) / 2;\r
-\r
-\r
- /* Place a full floor under the room */\r
- for (y = y1 - 1; y <= y2 + 1; y++)\r
- {\r
- for (x = x1 - 1; x <= x2 + 1; x++)\r
- {\r
- c_ptr = &cave[y][x];\r
- place_floor_grid(c_ptr);\r
- c_ptr->info |= (CAVE_ROOM);\r
- if (light) c_ptr->info |= (CAVE_GLOW);\r
- }\r
- }\r
-\r
- /* Walls around the room */\r
- for (y = y1 - 1; y <= y2 + 1; y++)\r
- {\r
- c_ptr = &cave[y][x1 - 1];\r
- place_outer_grid(c_ptr);\r
- c_ptr = &cave[y][x2 + 1];\r
- place_outer_grid(c_ptr);\r
- }\r
- for (x = x1 - 1; x <= x2 + 1; x++)\r
- {\r
- c_ptr = &cave[y1 - 1][x];\r
- place_outer_grid(c_ptr);\r
- c_ptr = &cave[y2 + 1][x];\r
- place_outer_grid(c_ptr);\r
- }\r
-\r
- if (dun_level < 30 + randint1(30))\r
- trap = feat_trap_piranha;\r
- else\r
- trap = feat_trap_armageddon;\r
-\r
- /* Place a special trap */\r
- c_ptr = &cave[rand_spread(yval, ysize / 4)][rand_spread(xval, xsize / 4)];\r
- c_ptr->mimic = c_ptr->feat;\r
- c_ptr->feat = trap;\r
-\r
- msg_format_wizard(CHEAT_DUNGEON, _("%sの部屋が生成されました。", "Room of %s was generated."), f_name + f_info[trap].name);\r
-\r
- return TRUE;\r
-}\r
-\r
+#include "angband.h"
+#include "grid.h"
+#include "generate.h"
+#include "rooms.h"
+
+
+/*!
+* @brief タイプ14の部屋…特殊トラップ部屋の生成 / Type 14 -- trapped rooms
+* @return なし
+* @details
+* A special trap is placed at center of the room
+*/
+bool build_type14(void)
+{
+ POSITION y, x, y2, x2, yval, xval;
+ POSITION y1, x1, xsize, ysize;
+
+ bool light;
+
+ cave_type *c_ptr;
+ s16b trap;
+
+ /* Pick a room size */
+ y1 = randint1(4);
+ x1 = randint1(11);
+ y2 = randint1(3);
+ x2 = randint1(11);
+
+ xsize = x1 + x2 + 1;
+ ysize = y1 + y2 + 1;
+
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&yval, &xval, ysize + 2, xsize + 2)) return FALSE;
+
+ /* Choose lite or dark */
+ light = ((dun_level <= randint1(25)) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS));
+
+
+ /* Get corner values */
+ y1 = yval - ysize / 2;
+ x1 = xval - xsize / 2;
+ y2 = yval + (ysize - 1) / 2;
+ x2 = xval + (xsize - 1) / 2;
+
+
+ /* Place a full floor under the room */
+ for (y = y1 - 1; y <= y2 + 1; y++)
+ {
+ for (x = x1 - 1; x <= x2 + 1; x++)
+ {
+ c_ptr = &cave[y][x];
+ place_floor_grid(c_ptr);
+ c_ptr->info |= (CAVE_ROOM);
+ if (light) c_ptr->info |= (CAVE_GLOW);
+ }
+ }
+
+ /* Walls around the room */
+ for (y = y1 - 1; y <= y2 + 1; y++)
+ {
+ c_ptr = &cave[y][x1 - 1];
+ place_outer_grid(c_ptr);
+ c_ptr = &cave[y][x2 + 1];
+ place_outer_grid(c_ptr);
+ }
+ for (x = x1 - 1; x <= x2 + 1; x++)
+ {
+ c_ptr = &cave[y1 - 1][x];
+ place_outer_grid(c_ptr);
+ c_ptr = &cave[y2 + 1][x];
+ place_outer_grid(c_ptr);
+ }
+
+ if (dun_level < 30 + randint1(30))
+ trap = feat_trap_piranha;
+ else
+ trap = feat_trap_armageddon;
+
+ /* Place a special trap */
+ c_ptr = &cave[rand_spread(yval, ysize / 4)][rand_spread(xval, xsize / 4)];
+ c_ptr->mimic = c_ptr->feat;
+ c_ptr->feat = trap;
+
+ msg_format_wizard(CHEAT_DUNGEON, _("%sの部屋が生成されました。", "Room of %s was generated."), f_name + f_info[trap].name);
+
+ return TRUE;
+}
+
-extern bool build_type14(void);\r
+extern bool build_type14(void);
-#include "angband.h"\r
-#include "generate.h"\r
-#include "grid.h"\r
-#include "rooms.h"\r
-#include "store.h"\r
-#include "trap.h"\r
-#include "monster.h"\r
-\r
-/*\r
-* This function creates a random vault that looks like a collection of bubbles.\r
-* It works by getting a set of coordinates that represent the center of each\r
-* bubble. The entire room is made by seeing which bubble center is closest. If\r
-* two centers are equidistant then the square is a wall, otherwise it is a floor.\r
-* The only exception is for squares really near a center, these are always floor.\r
-* (It looks better than without this check.)\r
-*\r
-* Note: If two centers are on the same point then this algorithm will create a\r
-* blank bubble filled with walls. - This is prevented from happening.\r
-*/\r
-static void build_bubble_vault(POSITION x0, POSITION y0, POSITION xsize, POSITION ysize)\r
-{\r
-#define BUBBLENUM 10 /* number of bubbles */\r
-\r
- /* array of center points of bubbles */\r
- coord center[BUBBLENUM];\r
-\r
- int i, j;\r
- POSITION x = 0, y = 0;\r
- u16b min1, min2, temp;\r
- bool done;\r
-\r
- /* Offset from center to top left hand corner */\r
- POSITION xhsize = xsize / 2;\r
- POSITION yhsize = ysize / 2;\r
-\r
- msg_print_wizard(CHEAT_DUNGEON, _("泡型ランダムVaultを生成しました。", "Room Vault."));\r
-\r
- /* Allocate center of bubbles */\r
- center[0].x = (byte)randint1(xsize - 3) + 1;\r
- center[0].y = (byte)randint1(ysize - 3) + 1;\r
-\r
- for (i = 1; i < BUBBLENUM; i++)\r
- {\r
- done = FALSE;\r
-\r
- /* get center and check to see if it is unique */\r
- while (!done)\r
- {\r
- done = TRUE;\r
-\r
- x = randint1(xsize - 3) + 1;\r
- y = randint1(ysize - 3) + 1;\r
-\r
- for (j = 0; j < i; j++)\r
- {\r
- /* rough test to see if there is an overlap */\r
- if ((x == center[j].x) && (y == center[j].y)) done = FALSE;\r
- }\r
- }\r
-\r
- center[i].x = x;\r
- center[i].y = y;\r
- }\r
-\r
-\r
- /* Top and bottom boundaries */\r
- for (i = 0; i < xsize; i++)\r
- {\r
- int side_x = x0 - xhsize + i;\r
-\r
- place_outer_noperm_bold(y0 - yhsize + 0, side_x);\r
- cave[y0 - yhsize + 0][side_x].info |= (CAVE_ROOM | CAVE_ICKY);\r
- place_outer_noperm_bold(y0 - yhsize + ysize - 1, side_x);\r
- cave[y0 - yhsize + ysize - 1][side_x].info |= (CAVE_ROOM | CAVE_ICKY);\r
- }\r
-\r
- /* Left and right boundaries */\r
- for (i = 1; i < ysize - 1; i++)\r
- {\r
- int side_y = y0 - yhsize + i;\r
-\r
- place_outer_noperm_bold(side_y, x0 - xhsize + 0);\r
- cave[side_y][x0 - xhsize + 0].info |= (CAVE_ROOM | CAVE_ICKY);\r
- place_outer_noperm_bold(side_y, x0 - xhsize + xsize - 1);\r
- cave[side_y][x0 - xhsize + xsize - 1].info |= (CAVE_ROOM | CAVE_ICKY);\r
- }\r
-\r
- /* Fill in middle with bubbles */\r
- for (x = 1; x < xsize - 1; x++)\r
- {\r
- for (y = 1; y < ysize - 1; y++)\r
- {\r
- /* Get distances to two closest centers */\r
-\r
- min1 = (u16b)distance(x, y, center[0].x, center[0].y);\r
- min2 = (u16b)distance(x, y, center[1].x, center[1].y);\r
-\r
- if (min1 > min2)\r
- {\r
- /* swap if in wrong order */\r
- temp = min1;\r
- min1 = min2;\r
- min2 = temp;\r
- }\r
-\r
- /* Scan the rest */\r
- for (i = 2; i < BUBBLENUM; i++)\r
- {\r
- temp = (u16b)distance(x, y, center[i].x, center[i].y);\r
-\r
- if (temp < min1)\r
- {\r
- /* smallest */\r
- min2 = min1;\r
- min1 = temp;\r
- }\r
- else if (temp < min2)\r
- {\r
- /* second smallest */\r
- min2 = temp;\r
- }\r
- }\r
- if (((min2 - min1) <= 2) && (!(min1 < 3)))\r
- {\r
- /* Boundary at midpoint+ not at inner region of bubble */\r
- place_outer_noperm_bold(y0 - yhsize + y, x0 - xhsize + x);\r
- }\r
- else\r
- {\r
- /* middle of a bubble */\r
- place_floor_bold(y0 - yhsize + y, x0 - xhsize + x);\r
- }\r
-\r
- /* clean up rest of flags */\r
- cave[y0 - yhsize + y][x0 - xhsize + x].info |= (CAVE_ROOM | CAVE_ICKY);\r
- }\r
- }\r
-\r
- /* Try to add some random doors */\r
- for (i = 0; i < 500; i++)\r
- {\r
- x = randint1(xsize - 3) - xhsize + x0 + 1;\r
- y = randint1(ysize - 3) - yhsize + y0 + 1;\r
- add_door(x, y);\r
- }\r
-\r
- /* Fill with monsters and treasure, low difficulty */\r
- fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5));\r
-}\r
-\r
-/* Create a random vault that looks like a collection of overlapping rooms */\r
-static void build_room_vault(POSITION x0, POSITION y0, POSITION xsize, POSITION ysize)\r
-{\r
- POSITION x1, x2, y1, y2, xhsize, yhsize;\r
- int i;\r
-\r
- /* get offset from center */\r
- xhsize = xsize / 2;\r
- yhsize = ysize / 2;\r
-\r
- msg_print_wizard(CHEAT_DUNGEON, _("部屋型ランダムVaultを生成しました。", "Room Vault."));\r
-\r
- /* fill area so don't get problems with arena levels */\r
- for (x1 = 0; x1 < xsize; x1++)\r
- {\r
- POSITION x = x0 - xhsize + x1;\r
-\r
- for (y1 = 0; y1 < ysize; y1++)\r
- {\r
- POSITION y = y0 - yhsize + y1;\r
-\r
- place_extra_bold(y, x);\r
- cave[y][x].info &= (~CAVE_ICKY);\r
- }\r
- }\r
-\r
- /* add ten random rooms */\r
- for (i = 0; i < 10; i++)\r
- {\r
- x1 = randint1(xhsize) * 2 + x0 - xhsize;\r
- x2 = randint1(xhsize) * 2 + x0 - xhsize;\r
- y1 = randint1(yhsize) * 2 + y0 - yhsize;\r
- y2 = randint1(yhsize) * 2 + y0 - yhsize;\r
- build_room(x1, x2, y1, y2);\r
- }\r
-\r
- /* Add some random doors */\r
- for (i = 0; i < 500; i++)\r
- {\r
- x1 = randint1(xsize - 3) - xhsize + x0 + 1;\r
- y1 = randint1(ysize - 3) - yhsize + y0 + 1;\r
- add_door(x1, y1);\r
- }\r
-\r
- /* Fill with monsters and treasure, high difficulty */\r
- fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5) + 5);\r
-}\r
-\r
-\r
-/* Create a random vault out of a fractal cave */\r
-static void build_cave_vault(POSITION x0, POSITION y0, POSITION xsiz, POSITION ysiz)\r
-{\r
- int grd, roug, cutoff;\r
- bool done, light, room;\r
- POSITION xhsize, yhsize, xsize, ysize, x, y;\r
-\r
- /* round to make sizes even */\r
- xhsize = xsiz / 2;\r
- yhsize = ysiz / 2;\r
- xsize = xhsize * 2;\r
- ysize = yhsize * 2;\r
-\r
- msg_print_wizard(CHEAT_DUNGEON, _("洞穴ランダムVaultを生成しました。", "Cave Vault."));\r
-\r
- light = done = FALSE;\r
- room = TRUE;\r
-\r
- while (!done)\r
- {\r
- /* testing values for these parameters feel free to adjust */\r
- grd = 1 << randint0(4);\r
-\r
- /* want average of about 16 */\r
- roug = randint1(8) * randint1(4);\r
-\r
- /* about size/2 */\r
- cutoff = randint1(xsize / 4) + randint1(ysize / 4) +\r
- randint1(xsize / 4) + randint1(ysize / 4);\r
-\r
- /* make it */\r
- generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);\r
-\r
- /* Convert to normal format+ clean up */\r
- done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);\r
- }\r
-\r
- /* Set icky flag because is a vault */\r
- for (x = 0; x <= xsize; x++)\r
- {\r
- for (y = 0; y <= ysize; y++)\r
- {\r
- cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;\r
- }\r
- }\r
-\r
- /* Fill with monsters and treasure, low difficulty */\r
- fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1, y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));\r
-}\r
-\r
-\r
-\r
-/*!\r
-* @brief Vault地形を回転、上下左右反転するための座標変換を返す / coordinate translation code\r
-* @param x 変換したい点のX座標参照ポインタ\r
-* @param y 変換したい点のY座標参照ポインタ\r
-* @param xoffset Vault生成時の基準X座標\r
-* @param yoffset Vault生成時の基準Y座標\r
-* @param transno 処理ID\r
-* @return なし\r
-*/\r
-static void coord_trans(POSITION *x, POSITION *y, POSITION xoffset, POSITION yoffset, int transno)\r
-{\r
- int i;\r
- int temp;\r
-\r
- /*\r
- * transno specifies what transformation is required. (0-7)\r
- * The lower two bits indicate by how much the vault is rotated,\r
- * and the upper bit indicates a reflection.\r
- * This is done by using rotation matrices... however since\r
- * these are mostly zeros for rotations by 90 degrees this can\r
- * be expressed simply in terms of swapping and inverting the\r
- * x and y coordinates.\r
- */\r
- for (i = 0; i < transno % 4; i++)\r
- {\r
- /* rotate by 90 degrees */\r
- temp = *x;\r
- *x = -(*y);\r
- *y = temp;\r
- }\r
-\r
- if (transno / 4)\r
- {\r
- /* Reflect depending on status of 3rd bit. */\r
- *x = -(*x);\r
- }\r
-\r
- /* Add offsets so vault stays in the first quadrant */\r
- *x += xoffset;\r
- *y += yoffset;\r
-}\r
-\r
-\r
-/*!\r
-* @brief Vaultをフロアに配置する / Hack -- fill in "vault" rooms\r
-* @param yval 生成基準Y座標\r
-* @param xval 生成基準X座標\r
-* @param ymax VaultのYサイズ\r
-* @param xmax VaultのXサイズ\r
-* @param data Vaultのデータ文字列\r
-* @param xoffset 変換基準X座標\r
-* @param yoffset 変換基準Y座標\r
-* @param transno 変換ID\r
-* @return なし\r
-*/\r
-static void build_vault(POSITION yval, POSITION xval, POSITION ymax, POSITION xmax, concptr data,\r
- POSITION xoffset, POSITION yoffset, int transno)\r
-{\r
- POSITION dx, dy, x, y, i, j;\r
- concptr t;\r
- cave_type *c_ptr;\r
-\r
- /* Place dungeon features and objects */\r
- for (t = data, dy = 0; dy < ymax; dy++)\r
- {\r
- for (dx = 0; dx < xmax; dx++, t++)\r
- {\r
- /* prevent loop counter from being overwritten */\r
- i = dx;\r
- j = dy;\r
-\r
- /* Flip / rotate */\r
- coord_trans(&i, &j, xoffset, yoffset, transno);\r
-\r
- /* Extract the location */\r
- if (transno % 2 == 0)\r
- {\r
- /* no swap of x/y */\r
- x = xval - (xmax / 2) + i;\r
- y = yval - (ymax / 2) + j;\r
- }\r
- else\r
- {\r
- /* swap of x/y */\r
- x = xval - (ymax / 2) + i;\r
- y = yval - (xmax / 2) + j;\r
- }\r
-\r
- /* Hack -- skip "non-grids" */\r
- if (*t == ' ') continue;\r
- c_ptr = &cave[y][x];\r
-\r
- /* Lay down a floor */\r
- place_floor_grid(c_ptr);\r
-\r
- /* Remove any mimic */\r
- c_ptr->mimic = 0;\r
-\r
- /* Part of a vault */\r
- c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);\r
-\r
- /* Analyze the grid */\r
- switch (*t)\r
- {\r
- /* Granite wall (outer) */\r
- case '%':\r
- place_outer_noperm_grid(c_ptr);\r
- break;\r
-\r
- /* Granite wall (inner) */\r
- case '#':\r
- place_inner_grid(c_ptr);\r
- break;\r
-\r
- /* Glass wall (inner) */\r
- case '$':\r
- place_inner_grid(c_ptr);\r
- c_ptr->feat = feat_glass_wall;\r
- break;\r
-\r
- /* Permanent wall (inner) */\r
- case 'X':\r
- place_inner_perm_grid(c_ptr);\r
- break;\r
-\r
- /* Permanent glass wall (inner) */\r
- case 'Y':\r
- place_inner_perm_grid(c_ptr);\r
- c_ptr->feat = feat_permanent_glass_wall;\r
- break;\r
-\r
- /* Treasure/trap */\r
- case '*':\r
- if (randint0(100) < 75)\r
- {\r
- place_object(y, x, 0L);\r
- }\r
- else\r
- {\r
- place_trap(y, x);\r
- }\r
- break;\r
-\r
- /* Treasure */\r
- case '[':\r
- place_object(y, x, 0L);\r
- break;\r
-\r
- /* Tree */\r
- case ':':\r
- c_ptr->feat = feat_tree;\r
- break;\r
-\r
- /* Secret doors */\r
- case '+':\r
- place_secret_door(y, x, DOOR_DEFAULT);\r
- break;\r
-\r
- /* Secret glass doors */\r
- case '-':\r
- place_secret_door(y, x, DOOR_GLASS_DOOR);\r
- if (is_closed_door(c_ptr->feat)) c_ptr->mimic = feat_glass_wall;\r
- break;\r
-\r
- /* Curtains */\r
- case '\'':\r
- place_secret_door(y, x, DOOR_CURTAIN);\r
- break;\r
-\r
- /* Trap */\r
- case '^':\r
- place_trap(y, x);\r
- break;\r
-\r
- /* Black market in a dungeon */\r
- case 'S':\r
- set_cave_feat(y, x, feat_black_market);\r
- store_init(NO_TOWN, STORE_BLACK);\r
- break;\r
-\r
- /* The Pattern */\r
- case 'p':\r
- set_cave_feat(y, x, feat_pattern_start);\r
- break;\r
-\r
- case 'a':\r
- set_cave_feat(y, x, feat_pattern_1);\r
- break;\r
-\r
- case 'b':\r
- set_cave_feat(y, x, feat_pattern_2);\r
- break;\r
-\r
- case 'c':\r
- set_cave_feat(y, x, feat_pattern_3);\r
- break;\r
-\r
- case 'd':\r
- set_cave_feat(y, x, feat_pattern_4);\r
- break;\r
-\r
- case 'P':\r
- set_cave_feat(y, x, feat_pattern_end);\r
- break;\r
-\r
- case 'B':\r
- set_cave_feat(y, x, feat_pattern_exit);\r
- break;\r
-\r
- case 'A':\r
- /* Reward for Pattern walk */\r
- object_level = base_level + 12;\r
- place_object(y, x, AM_GOOD | AM_GREAT);\r
- object_level = base_level;\r
- break;\r
-\r
- case '~':\r
- set_cave_feat(y, x, feat_shallow_water);\r
- break;\r
-\r
- case '=':\r
- set_cave_feat(y, x, feat_deep_water);\r
- break;\r
-\r
- case 'v':\r
- set_cave_feat(y, x, feat_shallow_lava);\r
- break;\r
-\r
- case 'w':\r
- set_cave_feat(y, x, feat_deep_lava);\r
- break;\r
-\r
- case 'f':\r
- set_cave_feat(y, x, feat_shallow_acid_puddle);\r
- break;\r
-\r
- case 'F':\r
- set_cave_feat(y, x, feat_deep_acid_puddle);\r
- break;\r
-\r
- case 'g':\r
- set_cave_feat(y, x, feat_shallow_poisonous_puddle);\r
- break;\r
-\r
- case 'G':\r
- set_cave_feat(y, x, feat_deep_poisonous_puddle);\r
- break;\r
-\r
- case 'h':\r
- set_cave_feat(y, x, feat_cold_zone);\r
- break;\r
-\r
- case 'H':\r
- set_cave_feat(y, x, feat_heavy_cold_zone);\r
- break;\r
-\r
- case 'i':\r
- set_cave_feat(y, x, feat_electrical_zone);\r
- break;\r
-\r
- case 'I':\r
- set_cave_feat(y, x, feat_heavy_electrical_zone);\r
- break;\r
-\r
- }\r
- }\r
- }\r
-\r
-\r
- /* Place dungeon monsters and objects */\r
- for (t = data, dy = 0; dy < ymax; dy++)\r
- {\r
- for (dx = 0; dx < xmax; dx++, t++)\r
- {\r
- /* prevent loop counter from being overwritten */\r
- i = dx;\r
- j = dy;\r
-\r
- /* Flip / rotate */\r
- coord_trans(&i, &j, xoffset, yoffset, transno);\r
-\r
- /* Extract the location */\r
- if (transno % 2 == 0)\r
- {\r
- /* no swap of x/y */\r
- x = xval - (xmax / 2) + i;\r
- y = yval - (ymax / 2) + j;\r
- }\r
- else\r
- {\r
- /* swap of x/y */\r
- x = xval - (ymax / 2) + i;\r
- y = yval - (xmax / 2) + j;\r
- }\r
-\r
- /* Hack -- skip "non-grids" */\r
- if (*t == ' ') continue;\r
-\r
- /* Analyze the symbol */\r
- switch (*t)\r
- {\r
- /* Monster */\r
- case '&':\r
- {\r
- monster_level = base_level + 5;\r
- place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));\r
- monster_level = base_level;\r
- break;\r
- }\r
-\r
- /* Meaner monster */\r
- case '@':\r
- {\r
- monster_level = base_level + 11;\r
- place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));\r
- monster_level = base_level;\r
- break;\r
- }\r
-\r
- /* Meaner monster, plus treasure */\r
- case '9':\r
- {\r
- monster_level = base_level + 9;\r
- place_monster(y, x, PM_ALLOW_SLEEP);\r
- monster_level = base_level;\r
- object_level = base_level + 7;\r
- place_object(y, x, AM_GOOD);\r
- object_level = base_level;\r
- break;\r
- }\r
-\r
- /* Nasty monster and treasure */\r
- case '8':\r
- {\r
- monster_level = base_level + 40;\r
- place_monster(y, x, PM_ALLOW_SLEEP);\r
- monster_level = base_level;\r
- object_level = base_level + 20;\r
- place_object(y, x, AM_GOOD | AM_GREAT);\r
- object_level = base_level;\r
- break;\r
- }\r
-\r
- /* Monster and/or object */\r
- case ',':\r
- {\r
- if (randint0(100) < 50)\r
- {\r
- monster_level = base_level + 3;\r
- place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));\r
- monster_level = base_level;\r
- }\r
- if (randint0(100) < 50)\r
- {\r
- object_level = base_level + 7;\r
- place_object(y, x, 0L);\r
- object_level = base_level;\r
- }\r
- break;\r
- }\r
-\r
- }\r
- }\r
- }\r
-}\r
-\r
-\r
-\r
-/*!\r
-* @brief タイプ7の部屋…v_info.txtより小型vaultを生成する / Type 7 -- simple vaults (see "v_info.txt")\r
-* @return なし\r
-*/\r
-bool build_type7(void)\r
-{\r
- vault_type *v_ptr = NULL;\r
- int dummy;\r
- POSITION x, y;\r
- POSITION xval, yval;\r
- POSITION xoffset, yoffset;\r
- int transno;\r
-\r
- /* Pick a lesser vault */\r
- for (dummy = 0; dummy < SAFE_MAX_ATTEMPTS; dummy++)\r
- {\r
- /* Access a random vault record */\r
- v_ptr = &v_info[randint0(max_v_idx)];\r
-\r
- /* Accept the first lesser vault */\r
- if (v_ptr->typ == 7) break;\r
- }\r
-\r
- /* No lesser vault found */\r
- if (dummy >= SAFE_MAX_ATTEMPTS)\r
- {\r
- msg_print_wizard(CHEAT_DUNGEON, _("小型固定Vaultを配置できませんでした。", "Could not place lesser vault."));\r
- return FALSE;\r
- }\r
-\r
- /* pick type of transformation (0-7) */\r
- transno = randint0(8);\r
-\r
- /* calculate offsets */\r
- x = v_ptr->wid;\r
- y = v_ptr->hgt;\r
-\r
- /* Some huge vault cannot be ratated to fit in the dungeon */\r
- if (x + 2 > cur_hgt - 2)\r
- {\r
- /* Forbid 90 or 270 degree ratation */\r
- transno &= ~1;\r
- }\r
-\r
- coord_trans(&x, &y, 0, 0, transno);\r
-\r
- if (x < 0)\r
- {\r
- xoffset = -x - 1;\r
- }\r
- else\r
- {\r
- xoffset = 0;\r
- }\r
-\r
- if (y < 0)\r
- {\r
- yoffset = -y - 1;\r
- }\r
- else\r
- {\r
- yoffset = 0;\r
- }\r
-\r
- /* Find and reserve some space in the dungeon. Get center of room. */\r
- if (!find_space(&yval, &xval, abs(y), abs(x))) return FALSE;\r
-\r
-#ifdef FORCE_V_IDX\r
- v_ptr = &v_info[2];\r
-#endif\r
-\r
- msg_format_wizard(CHEAT_DUNGEON, _("小型Vault(%s)を生成しました。", "Lesser vault (%s)."), v_name + v_ptr->name);\r
-\r
- /* Hack -- Build the vault */\r
- build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,\r
- v_text + v_ptr->text, xoffset, yoffset, transno);\r
-\r
- return TRUE;\r
-}\r
-\r
-/*!\r
-* @brief タイプ8の部屋…v_info.txtより大型vaultを生成する / Type 8 -- greater vaults (see "v_info.txt")\r
-* @return なし\r
-*/\r
-bool build_type8(void)\r
-{\r
- vault_type *v_ptr;\r
- int dummy;\r
- POSITION xval, yval;\r
- POSITION x, y;\r
- int transno;\r
- POSITION xoffset, yoffset;\r
-\r
- /* Pick a greater vault */\r
- for (dummy = 0; dummy < SAFE_MAX_ATTEMPTS; dummy++)\r
- {\r
- /* Access a random vault record */\r
- v_ptr = &v_info[randint0(max_v_idx)];\r
-\r
- /* Accept the first greater vault */\r
- if (v_ptr->typ == 8) break;\r
- }\r
-\r
- /* No greater vault found */\r
- if (dummy >= SAFE_MAX_ATTEMPTS)\r
- {\r
- msg_print_wizard(CHEAT_DUNGEON, _("大型固定Vaultを配置できませんでした。", "Could not place greater vault."));\r
- return FALSE;\r
- }\r
-\r
- /* pick type of transformation (0-7) */\r
- transno = randint0(8);\r
-\r
- /* calculate offsets */\r
- x = v_ptr->wid;\r
- y = v_ptr->hgt;\r
-\r
- /* Some huge vault cannot be ratated to fit in the dungeon */\r
- if (x + 2 > cur_hgt - 2)\r
- {\r
- /* Forbid 90 or 270 degree ratation */\r
- transno &= ~1;\r
- }\r
-\r
- coord_trans(&x, &y, 0, 0, transno);\r
-\r
- if (x < 0)\r
- {\r
- xoffset = -x - 1;\r
- }\r
- else\r
- {\r
- xoffset = 0;\r
- }\r
-\r
- if (y < 0)\r
- {\r
- yoffset = -y - 1;\r
- }\r
- else\r
- {\r
- yoffset = 0;\r
- }\r
-\r
- /*\r
- * Try to allocate space for room. If fails, exit\r
- *\r
- * Hack -- Prepare a bit larger space (+2, +2) to\r
- * prevent generation of vaults with no-entrance.\r
- */\r
- /* Find and reserve some space in the dungeon. Get center of room. */\r
- if (!find_space(&yval, &xval, (POSITION)(abs(y) + 2), (POSITION)(abs(x) + 2))) return FALSE;\r
-\r
-#ifdef FORCE_V_IDX\r
- v_ptr = &v_info[76 + randint1(3)];\r
-#endif\r
-\r
- msg_format_wizard(CHEAT_DUNGEON, _("大型固定Vault(%s)を生成しました。", "Greater vault (%s)."), v_name + v_ptr->name);\r
-\r
- /* Hack -- Build the vault */\r
- build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,\r
- v_text + v_ptr->text, xoffset, yoffset, transno);\r
-\r
- return TRUE;\r
-}\r
-\r
-\r
-/*\r
-* Build target vault.\r
-* This is made by two concentric "crypts" with perpendicular\r
-* walls creating the cross-hairs.\r
-*/\r
-static void build_target_vault(POSITION x0, POSITION y0, POSITION xsize, POSITION ysize)\r
-{\r
- POSITION rad, x, y;\r
-\r
- /* Make a random metric */\r
- POSITION h1, h2, h3, h4;\r
- h1 = randint1(32) - 16;\r
- h2 = randint1(16);\r
- h3 = randint1(32);\r
- h4 = randint1(32) - 16;\r
-\r
- msg_print_wizard(CHEAT_DUNGEON, _("対称形ランダムVaultを生成しました。", "Elemental Vault"));\r
-\r
- /* work out outer radius */\r
- if (xsize > ysize)\r
- {\r
- rad = ysize / 2;\r
- }\r
- else\r
- {\r
- rad = xsize / 2;\r
- }\r
-\r
- /* Make floor */\r
- for (x = x0 - rad; x <= x0 + rad; x++)\r
- {\r
- for (y = y0 - rad; y <= y0 + rad; y++)\r
- {\r
- /* clear room flag */\r
- cave[y][x].info &= ~(CAVE_ROOM);\r
-\r
- /* Vault - so is "icky" */\r
- cave[y][x].info |= CAVE_ICKY;\r
-\r
- if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)\r
- {\r
- /* inside- so is floor */\r
- place_floor_bold(y, x);\r
- }\r
- else\r
- {\r
- /* make granite outside so arena works */\r
- place_extra_bold(y, x);\r
- }\r
-\r
- /* proper boundary for arena */\r
- if (((y + rad) == y0) || ((y - rad) == y0) ||\r
- ((x + rad) == x0) || ((x - rad) == x0))\r
- {\r
- place_extra_bold(y, x);\r
- }\r
- }\r
- }\r
-\r
- /* Find visible outer walls and set to be FEAT_OUTER */\r
- add_outer_wall(x0, y0, FALSE, x0 - rad - 1, y0 - rad - 1,\r
- x0 + rad + 1, y0 + rad + 1);\r
-\r
- /* Add inner wall */\r
- for (x = x0 - rad / 2; x <= x0 + rad / 2; x++)\r
- {\r
- for (y = y0 - rad / 2; y <= y0 + rad / 2; y++)\r
- {\r
- if (dist2(y0, x0, y, x, h1, h2, h3, h4) == rad / 2)\r
- {\r
- /* Make an internal wall */\r
- place_inner_bold(y, x);\r
- }\r
- }\r
- }\r
-\r
- /* Add perpendicular walls */\r
- for (x = x0 - rad; x <= x0 + rad; x++)\r
- {\r
- place_inner_bold(y0, x);\r
- }\r
-\r
- for (y = y0 - rad; y <= y0 + rad; y++)\r
- {\r
- place_inner_bold(y, x0);\r
- }\r
-\r
- /* Make inner vault */\r
- for (y = y0 - 1; y <= y0 + 1; y++)\r
- {\r
- place_inner_bold(y, x0 - 1);\r
- place_inner_bold(y, x0 + 1);\r
- }\r
- for (x = x0 - 1; x <= x0 + 1; x++)\r
- {\r
- place_inner_bold(y0 - 1, x);\r
- place_inner_bold(y0 + 1, x);\r
- }\r
-\r
- place_floor_bold(y0, x0);\r
-\r
-\r
- /* Add doors to vault */\r
- /* get two distances so can place doors relative to centre */\r
- x = (rad - 2) / 4 + 1;\r
- y = rad / 2 + x;\r
-\r
- add_door(x0 + x, y0);\r
- add_door(x0 + y, y0);\r
- add_door(x0 - x, y0);\r
- add_door(x0 - y, y0);\r
- add_door(x0, y0 + x);\r
- add_door(x0, y0 + y);\r
- add_door(x0, y0 - x);\r
- add_door(x0, y0 - y);\r
-\r
- /* Fill with stuff - medium difficulty */\r
- fill_treasure(x0 - rad, x0 + rad, y0 - rad, y0 + rad, randint1(3) + 3);\r
-}\r
-\r
-\r
-#ifdef ALLOW_CAVERNS_AND_LAKES\r
-/*\r
-* This routine uses a modified version of the lake code to make a\r
-* distribution of some terrain type over the vault. This type\r
-* depends on the dungeon depth.\r
-*\r
-* Miniture rooms are then scattered across the vault.\r
-*/\r
-static void build_elemental_vault(POSITION x0, POSITION y0, POSITION xsiz, POSITION ysiz)\r
-{\r
- int grd, roug;\r
- int c1, c2, c3;\r
- bool done = FALSE;\r
- POSITION xsize, ysize, xhsize, yhsize, x, y;\r
- int i;\r
- int type;\r
-\r
- msg_print_wizard(CHEAT_DUNGEON, _("精霊界ランダムVaultを生成しました。", "Elemental Vault"));\r
-\r
- /* round to make sizes even */\r
- xhsize = xsiz / 2;\r
- yhsize = ysiz / 2;\r
- xsize = xhsize * 2;\r
- ysize = yhsize * 2;\r
-\r
- if (dun_level < 25)\r
- {\r
- /* Earth vault (Rubble) */\r
- type = LAKE_T_EARTH_VAULT;\r
- }\r
- else if (dun_level < 50)\r
- {\r
- /* Air vault (Trees) */\r
- type = LAKE_T_AIR_VAULT;\r
- }\r
- else if (dun_level < 75)\r
- {\r
- /* Water vault (shallow water) */\r
- type = LAKE_T_WATER_VAULT;\r
- }\r
- else\r
- {\r
- /* Fire vault (shallow lava) */\r
- type = LAKE_T_FIRE_VAULT;\r
- }\r
-\r
- while (!done)\r
- {\r
- /* testing values for these parameters: feel free to adjust */\r
- grd = 1 << (randint0(3));\r
-\r
- /* want average of about 16 */\r
- roug = randint1(8) * randint1(4);\r
-\r
- /* Make up size of various componants */\r
- /* Floor */\r
- c3 = 2 * xsize / 3;\r
-\r
- /* Deep water/lava */\r
- c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;\r
-\r
- /* Shallow boundary */\r
- c2 = (c1 + c3) / 2;\r
-\r
- /* make it */\r
- generate_hmap(y0, x0, xsize, ysize, grd, roug, c3);\r
-\r
- /* Convert to normal format+ clean up */\r
- done = generate_lake(y0, x0, xsize, ysize, c1, c2, c3, type);\r
- }\r
-\r
- /* Set icky flag because is a vault */\r
- for (x = 0; x <= xsize; x++)\r
- {\r
- for (y = 0; y <= ysize; y++)\r
- {\r
- cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;\r
- }\r
- }\r
-\r
- /* make a few rooms in the vault */\r
- for (i = 1; i <= (xsize * ysize) / 50; i++)\r
- {\r
- build_small_room(x0 + randint0(xsize - 4) - xsize / 2 + 2,\r
- y0 + randint0(ysize - 4) - ysize / 2 + 2);\r
- }\r
-\r
- /* Fill with monsters and treasure, low difficulty */\r
- fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1,\r
- y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));\r
-}\r
-#endif /* ALLOW_CAVERNS_AND_LAKES */\r
-\r
-\r
-/* Build a "mini" checkerboard vault\r
-*\r
-* This is done by making a permanent wall maze and setting\r
-* the diagonal sqaures of the checker board to be granite.\r
-* The vault has two entrances on opposite sides to guarantee\r
-* a way to get in even if the vault abuts a side of the dungeon.\r
-*/\r
-static void build_mini_c_vault(POSITION x0, POSITION y0, POSITION xsize, POSITION ysize)\r
-{\r
- POSITION dy, dx;\r
- POSITION y1, x1, y2, x2, y, x, total;\r
- int m, n, num_vertices;\r
- int *visited;\r
-\r
- msg_print_wizard(CHEAT_DUNGEON, _("小型チェッカーランダムVaultを生成しました。", "Mini Checker Board Vault."));\r
-\r
- /* Pick a random room size */\r
- dy = ysize / 2 - 1;\r
- dx = xsize / 2 - 1;\r
-\r
- y1 = y0 - dy;\r
- x1 = x0 - dx;\r
- y2 = y0 + dy;\r
- x2 = x0 + dx;\r
-\r
-\r
- /* generate the room */\r
- for (x = x1 - 2; x <= x2 + 2; x++)\r
- {\r
- if (!in_bounds(y1 - 2, x)) break;\r
-\r
- cave[y1 - 2][x].info |= (CAVE_ROOM | CAVE_ICKY);\r
-\r
- place_outer_noperm_bold(y1 - 2, x);\r
- }\r
-\r
- for (x = x1 - 2; x <= x2 + 2; x++)\r
- {\r
- if (!in_bounds(y2 + 2, x)) break;\r
-\r
- cave[y2 + 2][x].info |= (CAVE_ROOM | CAVE_ICKY);\r
-\r
- place_outer_noperm_bold(y2 + 2, x);\r
- }\r
-\r
- for (y = y1 - 2; y <= y2 + 2; y++)\r
- {\r
- if (!in_bounds(y, x1 - 2)) break;\r
-\r
- cave[y][x1 - 2].info |= (CAVE_ROOM | CAVE_ICKY);\r
-\r
- place_outer_noperm_bold(y, x1 - 2);\r
- }\r
-\r
- for (y = y1 - 2; y <= y2 + 2; y++)\r
- {\r
- if (!in_bounds(y, x2 + 2)) break;\r
-\r
- cave[y][x2 + 2].info |= (CAVE_ROOM | CAVE_ICKY);\r
-\r
- place_outer_noperm_bold(y, x2 + 2);\r
- }\r
-\r
- for (y = y1 - 1; y <= y2 + 1; y++)\r
- {\r
- for (x = x1 - 1; x <= x2 + 1; x++)\r
- {\r
- cave_type *c_ptr = &cave[y][x];\r
-\r
- c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);\r
-\r
- /* Permanent walls */\r
- place_inner_perm_grid(c_ptr);\r
- }\r
- }\r
-\r
-\r
- /* dimensions of vertex array */\r
- m = dx + 1;\r
- n = dy + 1;\r
- num_vertices = m * n;\r
-\r
- /* initialize array of visited vertices */\r
- C_MAKE(visited, num_vertices, int);\r
-\r
- /* traverse the graph to create a spannng tree, pick a random root */\r
- r_visit(y1, x1, y2, x2, randint0(num_vertices), 0, visited);\r
-\r
- /* Make it look like a checker board vault */\r
- for (x = x1; x <= x2; x++)\r
- {\r
- for (y = y1; y <= y2; y++)\r
- {\r
- total = x - x1 + y - y1;\r
- /* If total is odd- and is a floor then make a wall */\r
- if ((total % 2 == 1) && is_floor_bold(y, x))\r
- {\r
- place_inner_bold(y, x);\r
- }\r
- }\r
- }\r
-\r
- /* Make a couple of entrances */\r
- if (one_in_(2))\r
- {\r
- /* left and right */\r
- y = randint1(dy) + dy / 2;\r
- place_inner_bold(y1 + y, x1 - 1);\r
- place_inner_bold(y1 + y, x2 + 1);\r
- }\r
- else\r
- {\r
- /* top and bottom */\r
- x = randint1(dx) + dx / 2;\r
- place_inner_bold(y1 - 1, x1 + x);\r
- place_inner_bold(y2 + 1, x1 + x);\r
- }\r
-\r
- /* Fill with monsters and treasure, highest difficulty */\r
- fill_treasure(x1, x2, y1, y2, 10);\r
-\r
- C_KILL(visited, num_vertices, int);\r
-}\r
-\r
-/* Build a castle */\r
-/* Driver routine: clear the region and call the recursive\r
-* room routine.\r
-*\r
-*This makes a vault that looks like a castle/ city in the dungeon.\r
-*/\r
-static void build_castle_vault(POSITION x0, POSITION y0, POSITION xsize, POSITION ysize)\r
-{\r
- POSITION dy, dx;\r
- POSITION y1, x1, y2, x2;\r
- POSITION y, x;\r
-\r
- /* Pick a random room size */\r
- dy = ysize / 2 - 1;\r
- dx = xsize / 2 - 1;\r
-\r
- y1 = y0 - dy;\r
- x1 = x0 - dx;\r
- y2 = y0 + dy;\r
- x2 = x0 + dx;\r
-\r
- msg_print_wizard(CHEAT_DUNGEON, _("城型ランダムVaultを生成しました。", "Castle Vault"));\r
-\r
- /* generate the room */\r
- for (y = y1 - 1; y <= y2 + 1; y++)\r
- {\r
- for (x = x1 - 1; x <= x2 + 1; x++)\r
- {\r
- cave[y][x].info |= (CAVE_ROOM | CAVE_ICKY);\r
- /* Make everything a floor */\r
- place_floor_bold(y, x);\r
- }\r
- }\r
-\r
- /* Make the castle */\r
- build_recursive_room(x1, y1, x2, y2, randint1(5));\r
-\r
- /* Fill with monsters and treasure, low difficulty */\r
- fill_treasure(x1, x2, y1, y2, randint1(3));\r
-}\r
-\r
-\r
-\r
-/*!\r
-* @brief タイプ10の部屋…ランダム生成vault / Type 10 -- Random vaults\r
-* @return なし\r
-*/\r
-bool build_type10(void)\r
-{\r
- POSITION y0, x0, xsize, ysize, vtype;\r
-\r
- /* big enough to look good, small enough to be fairly common. */\r
- xsize = randint1(22) + 22;\r
- ysize = randint1(11) + 11;\r
-\r
- /* Find and reserve some space in the dungeon. Get center of room. */\r
- if (!find_space(&y0, &x0, ysize + 1, xsize + 1)) return FALSE;\r
-\r
- /* Select type of vault */\r
-#ifdef ALLOW_CAVERNS_AND_LAKES\r
- do\r
- {\r
- vtype = randint1(15);\r
- } while ((d_info[p_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) &&\r
- ((vtype == 1) || (vtype == 3) || (vtype == 8) || (vtype == 9) || (vtype == 11)));\r
-#else /* ALLOW_CAVERNS_AND_LAKES */\r
- do\r
- {\r
- vtype = randint1(7);\r
- } while ((d_info[p_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) &&\r
- ((vtype == 1) || (vtype == 3)));\r
-#endif /* ALLOW_CAVERNS_AND_LAKES */\r
-\r
- switch (vtype)\r
- {\r
- /* Build an appropriate room */\r
- case 1: case 9: build_bubble_vault(x0, y0, xsize, ysize); break;\r
- case 2: case 10: build_room_vault(x0, y0, xsize, ysize); break;\r
- case 3: case 11: build_cave_vault(x0, y0, xsize, ysize); break;\r
- case 4: case 12: build_maze_vault(x0, y0, xsize, ysize, TRUE); break;\r
- case 5: case 13: build_mini_c_vault(x0, y0, xsize, ysize); break;\r
- case 6: case 14: build_castle_vault(x0, y0, xsize, ysize); break;\r
- case 7: case 15: build_target_vault(x0, y0, xsize, ysize); break;\r
-#ifdef ALLOW_CAVERNS_AND_LAKES\r
- case 8: build_elemental_vault(x0, y0, xsize, ysize); break;\r
-#endif /* ALLOW_CAVERNS_AND_LAKES */\r
- /* I know how to add a few more... give me some time. */\r
-\r
- /* Paranoia */\r
- default: return FALSE;\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
-\r
-/*!\r
-* @brief タイプ17の部屋…v_info.txtより固定特殊部屋を生成する / Type 17 -- fixed special room (see "v_info.txt")\r
-* @return なし\r
-*/\r
-bool build_type17(void)\r
-{\r
- vault_type *v_ptr = NULL;\r
- int dummy;\r
- POSITION x, y;\r
- POSITION xval, yval;\r
- POSITION xoffset, yoffset;\r
- int transno;\r
-\r
- /* Pick a lesser vault */\r
- for (dummy = 0; dummy < SAFE_MAX_ATTEMPTS; dummy++)\r
- {\r
- /* Access a random vault record */\r
- v_ptr = &v_info[randint0(max_v_idx)];\r
-\r
- /* Accept the special fix room. */\r
- if (v_ptr->typ == 17) break;\r
- }\r
-\r
- /* No lesser vault found */\r
- if (dummy >= SAFE_MAX_ATTEMPTS)\r
- {\r
- msg_print_wizard(CHEAT_DUNGEON, _("固定特殊部屋を配置できませんでした。", "Could not place fixed special room."));\r
- return FALSE;\r
- }\r
-\r
- /* pick type of transformation (0-7) */\r
- transno = randint0(8);\r
-\r
- /* calculate offsets */\r
- x = v_ptr->wid;\r
- y = v_ptr->hgt;\r
-\r
- /* Some huge vault cannot be ratated to fit in the dungeon */\r
- if (x + 2 > cur_hgt - 2)\r
- {\r
- /* Forbid 90 or 270 degree ratation */\r
- transno &= ~1;\r
- }\r
-\r
- coord_trans(&x, &y, 0, 0, transno);\r
-\r
- if (x < 0)\r
- {\r
- xoffset = -x - 1;\r
- }\r
- else\r
- {\r
- xoffset = 0;\r
- }\r
-\r
- if (y < 0)\r
- {\r
- yoffset = -y - 1;\r
- }\r
- else\r
- {\r
- yoffset = 0;\r
- }\r
-\r
- /* Find and reserve some space in the dungeon. Get center of room. */\r
- if (!find_space(&yval, &xval, abs(y), abs(x))) return FALSE;\r
-\r
-#ifdef FORCE_V_IDX\r
- v_ptr = &v_info[2];\r
-#endif\r
-\r
- msg_format_wizard(CHEAT_DUNGEON, _("特殊固定部屋(%s)を生成しました。", "Special Fix room (%s)."), v_name + v_ptr->name);\r
-\r
- /* Hack -- Build the vault */\r
- build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,\r
- v_text + v_ptr->text, xoffset, yoffset, transno);\r
-\r
- return TRUE;\r
-}\r
-\r
+#include "angband.h"
+#include "generate.h"
+#include "grid.h"
+#include "rooms.h"
+#include "store.h"
+#include "trap.h"
+#include "monster.h"
+
+/*
+* This function creates a random vault that looks like a collection of bubbles.
+* It works by getting a set of coordinates that represent the center of each
+* bubble. The entire room is made by seeing which bubble center is closest. If
+* two centers are equidistant then the square is a wall, otherwise it is a floor.
+* The only exception is for squares really near a center, these are always floor.
+* (It looks better than without this check.)
+*
+* Note: If two centers are on the same point then this algorithm will create a
+* blank bubble filled with walls. - This is prevented from happening.
+*/
+static void build_bubble_vault(POSITION x0, POSITION y0, POSITION xsize, POSITION ysize)
+{
+#define BUBBLENUM 10 /* number of bubbles */
+
+ /* array of center points of bubbles */
+ coord center[BUBBLENUM];
+
+ int i, j;
+ POSITION x = 0, y = 0;
+ u16b min1, min2, temp;
+ bool done;
+
+ /* Offset from center to top left hand corner */
+ POSITION xhsize = xsize / 2;
+ POSITION yhsize = ysize / 2;
+
+ msg_print_wizard(CHEAT_DUNGEON, _("泡型ランダムVaultを生成しました。", "Room Vault."));
+
+ /* Allocate center of bubbles */
+ center[0].x = (byte)randint1(xsize - 3) + 1;
+ center[0].y = (byte)randint1(ysize - 3) + 1;
+
+ for (i = 1; i < BUBBLENUM; i++)
+ {
+ done = FALSE;
+
+ /* get center and check to see if it is unique */
+ while (!done)
+ {
+ done = TRUE;
+
+ x = randint1(xsize - 3) + 1;
+ y = randint1(ysize - 3) + 1;
+
+ for (j = 0; j < i; j++)
+ {
+ /* rough test to see if there is an overlap */
+ if ((x == center[j].x) && (y == center[j].y)) done = FALSE;
+ }
+ }
+
+ center[i].x = x;
+ center[i].y = y;
+ }
+
+
+ /* Top and bottom boundaries */
+ for (i = 0; i < xsize; i++)
+ {
+ int side_x = x0 - xhsize + i;
+
+ place_outer_noperm_bold(y0 - yhsize + 0, side_x);
+ cave[y0 - yhsize + 0][side_x].info |= (CAVE_ROOM | CAVE_ICKY);
+ place_outer_noperm_bold(y0 - yhsize + ysize - 1, side_x);
+ cave[y0 - yhsize + ysize - 1][side_x].info |= (CAVE_ROOM | CAVE_ICKY);
+ }
+
+ /* Left and right boundaries */
+ for (i = 1; i < ysize - 1; i++)
+ {
+ int side_y = y0 - yhsize + i;
+
+ place_outer_noperm_bold(side_y, x0 - xhsize + 0);
+ cave[side_y][x0 - xhsize + 0].info |= (CAVE_ROOM | CAVE_ICKY);
+ place_outer_noperm_bold(side_y, x0 - xhsize + xsize - 1);
+ cave[side_y][x0 - xhsize + xsize - 1].info |= (CAVE_ROOM | CAVE_ICKY);
+ }
+
+ /* Fill in middle with bubbles */
+ for (x = 1; x < xsize - 1; x++)
+ {
+ for (y = 1; y < ysize - 1; y++)
+ {
+ /* Get distances to two closest centers */
+
+ min1 = (u16b)distance(x, y, center[0].x, center[0].y);
+ min2 = (u16b)distance(x, y, center[1].x, center[1].y);
+
+ if (min1 > min2)
+ {
+ /* swap if in wrong order */
+ temp = min1;
+ min1 = min2;
+ min2 = temp;
+ }
+
+ /* Scan the rest */
+ for (i = 2; i < BUBBLENUM; i++)
+ {
+ temp = (u16b)distance(x, y, center[i].x, center[i].y);
+
+ if (temp < min1)
+ {
+ /* smallest */
+ min2 = min1;
+ min1 = temp;
+ }
+ else if (temp < min2)
+ {
+ /* second smallest */
+ min2 = temp;
+ }
+ }
+ if (((min2 - min1) <= 2) && (!(min1 < 3)))
+ {
+ /* Boundary at midpoint+ not at inner region of bubble */
+ place_outer_noperm_bold(y0 - yhsize + y, x0 - xhsize + x);
+ }
+ else
+ {
+ /* middle of a bubble */
+ place_floor_bold(y0 - yhsize + y, x0 - xhsize + x);
+ }
+
+ /* clean up rest of flags */
+ cave[y0 - yhsize + y][x0 - xhsize + x].info |= (CAVE_ROOM | CAVE_ICKY);
+ }
+ }
+
+ /* Try to add some random doors */
+ for (i = 0; i < 500; i++)
+ {
+ x = randint1(xsize - 3) - xhsize + x0 + 1;
+ y = randint1(ysize - 3) - yhsize + y0 + 1;
+ add_door(x, y);
+ }
+
+ /* Fill with monsters and treasure, low difficulty */
+ fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5));
+}
+
+/* Create a random vault that looks like a collection of overlapping rooms */
+static void build_room_vault(POSITION x0, POSITION y0, POSITION xsize, POSITION ysize)
+{
+ POSITION x1, x2, y1, y2, xhsize, yhsize;
+ int i;
+
+ /* get offset from center */
+ xhsize = xsize / 2;
+ yhsize = ysize / 2;
+
+ msg_print_wizard(CHEAT_DUNGEON, _("部屋型ランダムVaultを生成しました。", "Room Vault."));
+
+ /* fill area so don't get problems with arena levels */
+ for (x1 = 0; x1 < xsize; x1++)
+ {
+ POSITION x = x0 - xhsize + x1;
+
+ for (y1 = 0; y1 < ysize; y1++)
+ {
+ POSITION y = y0 - yhsize + y1;
+
+ place_extra_bold(y, x);
+ cave[y][x].info &= (~CAVE_ICKY);
+ }
+ }
+
+ /* add ten random rooms */
+ for (i = 0; i < 10; i++)
+ {
+ x1 = randint1(xhsize) * 2 + x0 - xhsize;
+ x2 = randint1(xhsize) * 2 + x0 - xhsize;
+ y1 = randint1(yhsize) * 2 + y0 - yhsize;
+ y2 = randint1(yhsize) * 2 + y0 - yhsize;
+ build_room(x1, x2, y1, y2);
+ }
+
+ /* Add some random doors */
+ for (i = 0; i < 500; i++)
+ {
+ x1 = randint1(xsize - 3) - xhsize + x0 + 1;
+ y1 = randint1(ysize - 3) - yhsize + y0 + 1;
+ add_door(x1, y1);
+ }
+
+ /* Fill with monsters and treasure, high difficulty */
+ fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5) + 5);
+}
+
+
+/* Create a random vault out of a fractal cave */
+static void build_cave_vault(POSITION x0, POSITION y0, POSITION xsiz, POSITION ysiz)
+{
+ int grd, roug, cutoff;
+ bool done, light, room;
+ POSITION xhsize, yhsize, xsize, ysize, x, y;
+
+ /* round to make sizes even */
+ xhsize = xsiz / 2;
+ yhsize = ysiz / 2;
+ xsize = xhsize * 2;
+ ysize = yhsize * 2;
+
+ msg_print_wizard(CHEAT_DUNGEON, _("洞穴ランダムVaultを生成しました。", "Cave Vault."));
+
+ light = done = FALSE;
+ room = TRUE;
+
+ while (!done)
+ {
+ /* testing values for these parameters feel free to adjust */
+ grd = 1 << randint0(4);
+
+ /* want average of about 16 */
+ roug = randint1(8) * randint1(4);
+
+ /* about size/2 */
+ cutoff = randint1(xsize / 4) + randint1(ysize / 4) +
+ randint1(xsize / 4) + randint1(ysize / 4);
+
+ /* make it */
+ generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
+
+ /* Convert to normal format+ clean up */
+ done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
+ }
+
+ /* Set icky flag because is a vault */
+ for (x = 0; x <= xsize; x++)
+ {
+ for (y = 0; y <= ysize; y++)
+ {
+ cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
+ }
+ }
+
+ /* Fill with monsters and treasure, low difficulty */
+ fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1, y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));
+}
+
+
+
+/*!
+* @brief Vault地形を回転、上下左右反転するための座標変換を返す / coordinate translation code
+* @param x 変換したい点のX座標参照ポインタ
+* @param y 変換したい点のY座標参照ポインタ
+* @param xoffset Vault生成時の基準X座標
+* @param yoffset Vault生成時の基準Y座標
+* @param transno 処理ID
+* @return なし
+*/
+static void coord_trans(POSITION *x, POSITION *y, POSITION xoffset, POSITION yoffset, int transno)
+{
+ int i;
+ int temp;
+
+ /*
+ * transno specifies what transformation is required. (0-7)
+ * The lower two bits indicate by how much the vault is rotated,
+ * and the upper bit indicates a reflection.
+ * This is done by using rotation matrices... however since
+ * these are mostly zeros for rotations by 90 degrees this can
+ * be expressed simply in terms of swapping and inverting the
+ * x and y coordinates.
+ */
+ for (i = 0; i < transno % 4; i++)
+ {
+ /* rotate by 90 degrees */
+ temp = *x;
+ *x = -(*y);
+ *y = temp;
+ }
+
+ if (transno / 4)
+ {
+ /* Reflect depending on status of 3rd bit. */
+ *x = -(*x);
+ }
+
+ /* Add offsets so vault stays in the first quadrant */
+ *x += xoffset;
+ *y += yoffset;
+}
+
+
+/*!
+* @brief Vaultをフロアに配置する / Hack -- fill in "vault" rooms
+* @param yval 生成基準Y座標
+* @param xval 生成基準X座標
+* @param ymax VaultのYサイズ
+* @param xmax VaultのXサイズ
+* @param data Vaultのデータ文字列
+* @param xoffset 変換基準X座標
+* @param yoffset 変換基準Y座標
+* @param transno 変換ID
+* @return なし
+*/
+static void build_vault(POSITION yval, POSITION xval, POSITION ymax, POSITION xmax, concptr data,
+ POSITION xoffset, POSITION yoffset, int transno)
+{
+ POSITION dx, dy, x, y, i, j;
+ concptr t;
+ cave_type *c_ptr;
+
+ /* Place dungeon features and objects */
+ for (t = data, dy = 0; dy < ymax; dy++)
+ {
+ for (dx = 0; dx < xmax; dx++, t++)
+ {
+ /* prevent loop counter from being overwritten */
+ i = dx;
+ j = dy;
+
+ /* Flip / rotate */
+ coord_trans(&i, &j, xoffset, yoffset, transno);
+
+ /* Extract the location */
+ if (transno % 2 == 0)
+ {
+ /* no swap of x/y */
+ x = xval - (xmax / 2) + i;
+ y = yval - (ymax / 2) + j;
+ }
+ else
+ {
+ /* swap of x/y */
+ x = xval - (ymax / 2) + i;
+ y = yval - (xmax / 2) + j;
+ }
+
+ /* Hack -- skip "non-grids" */
+ if (*t == ' ') continue;
+ c_ptr = &cave[y][x];
+
+ /* Lay down a floor */
+ place_floor_grid(c_ptr);
+
+ /* Remove any mimic */
+ c_ptr->mimic = 0;
+
+ /* Part of a vault */
+ c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
+
+ /* Analyze the grid */
+ switch (*t)
+ {
+ /* Granite wall (outer) */
+ case '%':
+ place_outer_noperm_grid(c_ptr);
+ break;
+
+ /* Granite wall (inner) */
+ case '#':
+ place_inner_grid(c_ptr);
+ break;
+
+ /* Glass wall (inner) */
+ case '$':
+ place_inner_grid(c_ptr);
+ c_ptr->feat = feat_glass_wall;
+ break;
+
+ /* Permanent wall (inner) */
+ case 'X':
+ place_inner_perm_grid(c_ptr);
+ break;
+
+ /* Permanent glass wall (inner) */
+ case 'Y':
+ place_inner_perm_grid(c_ptr);
+ c_ptr->feat = feat_permanent_glass_wall;
+ break;
+
+ /* Treasure/trap */
+ case '*':
+ if (randint0(100) < 75)
+ {
+ place_object(y, x, 0L);
+ }
+ else
+ {
+ place_trap(y, x);
+ }
+ break;
+
+ /* Treasure */
+ case '[':
+ place_object(y, x, 0L);
+ break;
+
+ /* Tree */
+ case ':':
+ c_ptr->feat = feat_tree;
+ break;
+
+ /* Secret doors */
+ case '+':
+ place_secret_door(y, x, DOOR_DEFAULT);
+ break;
+
+ /* Secret glass doors */
+ case '-':
+ place_secret_door(y, x, DOOR_GLASS_DOOR);
+ if (is_closed_door(c_ptr->feat)) c_ptr->mimic = feat_glass_wall;
+ break;
+
+ /* Curtains */
+ case '\'':
+ place_secret_door(y, x, DOOR_CURTAIN);
+ break;
+
+ /* Trap */
+ case '^':
+ place_trap(y, x);
+ break;
+
+ /* Black market in a dungeon */
+ case 'S':
+ set_cave_feat(y, x, feat_black_market);
+ store_init(NO_TOWN, STORE_BLACK);
+ break;
+
+ /* The Pattern */
+ case 'p':
+ set_cave_feat(y, x, feat_pattern_start);
+ break;
+
+ case 'a':
+ set_cave_feat(y, x, feat_pattern_1);
+ break;
+
+ case 'b':
+ set_cave_feat(y, x, feat_pattern_2);
+ break;
+
+ case 'c':
+ set_cave_feat(y, x, feat_pattern_3);
+ break;
+
+ case 'd':
+ set_cave_feat(y, x, feat_pattern_4);
+ break;
+
+ case 'P':
+ set_cave_feat(y, x, feat_pattern_end);
+ break;
+
+ case 'B':
+ set_cave_feat(y, x, feat_pattern_exit);
+ break;
+
+ case 'A':
+ /* Reward for Pattern walk */
+ object_level = base_level + 12;
+ place_object(y, x, AM_GOOD | AM_GREAT);
+ object_level = base_level;
+ break;
+
+ case '~':
+ set_cave_feat(y, x, feat_shallow_water);
+ break;
+
+ case '=':
+ set_cave_feat(y, x, feat_deep_water);
+ break;
+
+ case 'v':
+ set_cave_feat(y, x, feat_shallow_lava);
+ break;
+
+ case 'w':
+ set_cave_feat(y, x, feat_deep_lava);
+ break;
+
+ case 'f':
+ set_cave_feat(y, x, feat_shallow_acid_puddle);
+ break;
+
+ case 'F':
+ set_cave_feat(y, x, feat_deep_acid_puddle);
+ break;
+
+ case 'g':
+ set_cave_feat(y, x, feat_shallow_poisonous_puddle);
+ break;
+
+ case 'G':
+ set_cave_feat(y, x, feat_deep_poisonous_puddle);
+ break;
+
+ case 'h':
+ set_cave_feat(y, x, feat_cold_zone);
+ break;
+
+ case 'H':
+ set_cave_feat(y, x, feat_heavy_cold_zone);
+ break;
+
+ case 'i':
+ set_cave_feat(y, x, feat_electrical_zone);
+ break;
+
+ case 'I':
+ set_cave_feat(y, x, feat_heavy_electrical_zone);
+ break;
+
+ }
+ }
+ }
+
+
+ /* Place dungeon monsters and objects */
+ for (t = data, dy = 0; dy < ymax; dy++)
+ {
+ for (dx = 0; dx < xmax; dx++, t++)
+ {
+ /* prevent loop counter from being overwritten */
+ i = dx;
+ j = dy;
+
+ /* Flip / rotate */
+ coord_trans(&i, &j, xoffset, yoffset, transno);
+
+ /* Extract the location */
+ if (transno % 2 == 0)
+ {
+ /* no swap of x/y */
+ x = xval - (xmax / 2) + i;
+ y = yval - (ymax / 2) + j;
+ }
+ else
+ {
+ /* swap of x/y */
+ x = xval - (ymax / 2) + i;
+ y = yval - (xmax / 2) + j;
+ }
+
+ /* Hack -- skip "non-grids" */
+ if (*t == ' ') continue;
+
+ /* Analyze the symbol */
+ switch (*t)
+ {
+ /* Monster */
+ case '&':
+ {
+ monster_level = base_level + 5;
+ place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
+ monster_level = base_level;
+ break;
+ }
+
+ /* Meaner monster */
+ case '@':
+ {
+ monster_level = base_level + 11;
+ place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
+ monster_level = base_level;
+ break;
+ }
+
+ /* Meaner monster, plus treasure */
+ case '9':
+ {
+ monster_level = base_level + 9;
+ place_monster(y, x, PM_ALLOW_SLEEP);
+ monster_level = base_level;
+ object_level = base_level + 7;
+ place_object(y, x, AM_GOOD);
+ object_level = base_level;
+ break;
+ }
+
+ /* Nasty monster and treasure */
+ case '8':
+ {
+ monster_level = base_level + 40;
+ place_monster(y, x, PM_ALLOW_SLEEP);
+ monster_level = base_level;
+ object_level = base_level + 20;
+ place_object(y, x, AM_GOOD | AM_GREAT);
+ object_level = base_level;
+ break;
+ }
+
+ /* Monster and/or object */
+ case ',':
+ {
+ if (randint0(100) < 50)
+ {
+ monster_level = base_level + 3;
+ place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
+ monster_level = base_level;
+ }
+ if (randint0(100) < 50)
+ {
+ object_level = base_level + 7;
+ place_object(y, x, 0L);
+ object_level = base_level;
+ }
+ break;
+ }
+
+ }
+ }
+ }
+}
+
+
+
+/*!
+* @brief タイプ7の部屋…v_info.txtより小型vaultを生成する / Type 7 -- simple vaults (see "v_info.txt")
+* @return なし
+*/
+bool build_type7(void)
+{
+ vault_type *v_ptr = NULL;
+ int dummy;
+ POSITION x, y;
+ POSITION xval, yval;
+ POSITION xoffset, yoffset;
+ int transno;
+
+ /* Pick a lesser vault */
+ for (dummy = 0; dummy < SAFE_MAX_ATTEMPTS; dummy++)
+ {
+ /* Access a random vault record */
+ v_ptr = &v_info[randint0(max_v_idx)];
+
+ /* Accept the first lesser vault */
+ if (v_ptr->typ == 7) break;
+ }
+
+ /* No lesser vault found */
+ if (dummy >= SAFE_MAX_ATTEMPTS)
+ {
+ msg_print_wizard(CHEAT_DUNGEON, _("小型固定Vaultを配置できませんでした。", "Could not place lesser vault."));
+ return FALSE;
+ }
+
+ /* pick type of transformation (0-7) */
+ transno = randint0(8);
+
+ /* calculate offsets */
+ x = v_ptr->wid;
+ y = v_ptr->hgt;
+
+ /* Some huge vault cannot be ratated to fit in the dungeon */
+ if (x + 2 > cur_hgt - 2)
+ {
+ /* Forbid 90 or 270 degree ratation */
+ transno &= ~1;
+ }
+
+ coord_trans(&x, &y, 0, 0, transno);
+
+ if (x < 0)
+ {
+ xoffset = -x - 1;
+ }
+ else
+ {
+ xoffset = 0;
+ }
+
+ if (y < 0)
+ {
+ yoffset = -y - 1;
+ }
+ else
+ {
+ yoffset = 0;
+ }
+
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&yval, &xval, abs(y), abs(x))) return FALSE;
+
+#ifdef FORCE_V_IDX
+ v_ptr = &v_info[2];
+#endif
+
+ msg_format_wizard(CHEAT_DUNGEON, _("小型Vault(%s)を生成しました。", "Lesser vault (%s)."), v_name + v_ptr->name);
+
+ /* Hack -- Build the vault */
+ build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,
+ v_text + v_ptr->text, xoffset, yoffset, transno);
+
+ return TRUE;
+}
+
+/*!
+* @brief タイプ8の部屋…v_info.txtより大型vaultを生成する / Type 8 -- greater vaults (see "v_info.txt")
+* @return なし
+*/
+bool build_type8(void)
+{
+ vault_type *v_ptr;
+ int dummy;
+ POSITION xval, yval;
+ POSITION x, y;
+ int transno;
+ POSITION xoffset, yoffset;
+
+ /* Pick a greater vault */
+ for (dummy = 0; dummy < SAFE_MAX_ATTEMPTS; dummy++)
+ {
+ /* Access a random vault record */
+ v_ptr = &v_info[randint0(max_v_idx)];
+
+ /* Accept the first greater vault */
+ if (v_ptr->typ == 8) break;
+ }
+
+ /* No greater vault found */
+ if (dummy >= SAFE_MAX_ATTEMPTS)
+ {
+ msg_print_wizard(CHEAT_DUNGEON, _("大型固定Vaultを配置できませんでした。", "Could not place greater vault."));
+ return FALSE;
+ }
+
+ /* pick type of transformation (0-7) */
+ transno = randint0(8);
+
+ /* calculate offsets */
+ x = v_ptr->wid;
+ y = v_ptr->hgt;
+
+ /* Some huge vault cannot be ratated to fit in the dungeon */
+ if (x + 2 > cur_hgt - 2)
+ {
+ /* Forbid 90 or 270 degree ratation */
+ transno &= ~1;
+ }
+
+ coord_trans(&x, &y, 0, 0, transno);
+
+ if (x < 0)
+ {
+ xoffset = -x - 1;
+ }
+ else
+ {
+ xoffset = 0;
+ }
+
+ if (y < 0)
+ {
+ yoffset = -y - 1;
+ }
+ else
+ {
+ yoffset = 0;
+ }
+
+ /*
+ * Try to allocate space for room. If fails, exit
+ *
+ * Hack -- Prepare a bit larger space (+2, +2) to
+ * prevent generation of vaults with no-entrance.
+ */
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&yval, &xval, (POSITION)(abs(y) + 2), (POSITION)(abs(x) + 2))) return FALSE;
+
+#ifdef FORCE_V_IDX
+ v_ptr = &v_info[76 + randint1(3)];
+#endif
+
+ msg_format_wizard(CHEAT_DUNGEON, _("大型固定Vault(%s)を生成しました。", "Greater vault (%s)."), v_name + v_ptr->name);
+
+ /* Hack -- Build the vault */
+ build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,
+ v_text + v_ptr->text, xoffset, yoffset, transno);
+
+ return TRUE;
+}
+
+
+/*
+* Build target vault.
+* This is made by two concentric "crypts" with perpendicular
+* walls creating the cross-hairs.
+*/
+static void build_target_vault(POSITION x0, POSITION y0, POSITION xsize, POSITION ysize)
+{
+ POSITION rad, x, y;
+
+ /* Make a random metric */
+ POSITION h1, h2, h3, h4;
+ h1 = randint1(32) - 16;
+ h2 = randint1(16);
+ h3 = randint1(32);
+ h4 = randint1(32) - 16;
+
+ msg_print_wizard(CHEAT_DUNGEON, _("対称形ランダムVaultを生成しました。", "Elemental Vault"));
+
+ /* work out outer radius */
+ if (xsize > ysize)
+ {
+ rad = ysize / 2;
+ }
+ else
+ {
+ rad = xsize / 2;
+ }
+
+ /* Make floor */
+ for (x = x0 - rad; x <= x0 + rad; x++)
+ {
+ for (y = y0 - rad; y <= y0 + rad; y++)
+ {
+ /* clear room flag */
+ cave[y][x].info &= ~(CAVE_ROOM);
+
+ /* Vault - so is "icky" */
+ cave[y][x].info |= CAVE_ICKY;
+
+ if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
+ {
+ /* inside- so is floor */
+ place_floor_bold(y, x);
+ }
+ else
+ {
+ /* make granite outside so arena works */
+ place_extra_bold(y, x);
+ }
+
+ /* proper boundary for arena */
+ if (((y + rad) == y0) || ((y - rad) == y0) ||
+ ((x + rad) == x0) || ((x - rad) == x0))
+ {
+ place_extra_bold(y, x);
+ }
+ }
+ }
+
+ /* Find visible outer walls and set to be FEAT_OUTER */
+ add_outer_wall(x0, y0, FALSE, x0 - rad - 1, y0 - rad - 1,
+ x0 + rad + 1, y0 + rad + 1);
+
+ /* Add inner wall */
+ for (x = x0 - rad / 2; x <= x0 + rad / 2; x++)
+ {
+ for (y = y0 - rad / 2; y <= y0 + rad / 2; y++)
+ {
+ if (dist2(y0, x0, y, x, h1, h2, h3, h4) == rad / 2)
+ {
+ /* Make an internal wall */
+ place_inner_bold(y, x);
+ }
+ }
+ }
+
+ /* Add perpendicular walls */
+ for (x = x0 - rad; x <= x0 + rad; x++)
+ {
+ place_inner_bold(y0, x);
+ }
+
+ for (y = y0 - rad; y <= y0 + rad; y++)
+ {
+ place_inner_bold(y, x0);
+ }
+
+ /* Make inner vault */
+ for (y = y0 - 1; y <= y0 + 1; y++)
+ {
+ place_inner_bold(y, x0 - 1);
+ place_inner_bold(y, x0 + 1);
+ }
+ for (x = x0 - 1; x <= x0 + 1; x++)
+ {
+ place_inner_bold(y0 - 1, x);
+ place_inner_bold(y0 + 1, x);
+ }
+
+ place_floor_bold(y0, x0);
+
+
+ /* Add doors to vault */
+ /* get two distances so can place doors relative to centre */
+ x = (rad - 2) / 4 + 1;
+ y = rad / 2 + x;
+
+ add_door(x0 + x, y0);
+ add_door(x0 + y, y0);
+ add_door(x0 - x, y0);
+ add_door(x0 - y, y0);
+ add_door(x0, y0 + x);
+ add_door(x0, y0 + y);
+ add_door(x0, y0 - x);
+ add_door(x0, y0 - y);
+
+ /* Fill with stuff - medium difficulty */
+ fill_treasure(x0 - rad, x0 + rad, y0 - rad, y0 + rad, randint1(3) + 3);
+}
+
+
+#ifdef ALLOW_CAVERNS_AND_LAKES
+/*
+* This routine uses a modified version of the lake code to make a
+* distribution of some terrain type over the vault. This type
+* depends on the dungeon depth.
+*
+* Miniture rooms are then scattered across the vault.
+*/
+static void build_elemental_vault(POSITION x0, POSITION y0, POSITION xsiz, POSITION ysiz)
+{
+ int grd, roug;
+ int c1, c2, c3;
+ bool done = FALSE;
+ POSITION xsize, ysize, xhsize, yhsize, x, y;
+ int i;
+ int type;
+
+ msg_print_wizard(CHEAT_DUNGEON, _("精霊界ランダムVaultを生成しました。", "Elemental Vault"));
+
+ /* round to make sizes even */
+ xhsize = xsiz / 2;
+ yhsize = ysiz / 2;
+ xsize = xhsize * 2;
+ ysize = yhsize * 2;
+
+ if (dun_level < 25)
+ {
+ /* Earth vault (Rubble) */
+ type = LAKE_T_EARTH_VAULT;
+ }
+ else if (dun_level < 50)
+ {
+ /* Air vault (Trees) */
+ type = LAKE_T_AIR_VAULT;
+ }
+ else if (dun_level < 75)
+ {
+ /* Water vault (shallow water) */
+ type = LAKE_T_WATER_VAULT;
+ }
+ else
+ {
+ /* Fire vault (shallow lava) */
+ type = LAKE_T_FIRE_VAULT;
+ }
+
+ while (!done)
+ {
+ /* testing values for these parameters: feel free to adjust */
+ grd = 1 << (randint0(3));
+
+ /* want average of about 16 */
+ roug = randint1(8) * randint1(4);
+
+ /* Make up size of various componants */
+ /* Floor */
+ c3 = 2 * xsize / 3;
+
+ /* Deep water/lava */
+ c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
+
+ /* Shallow boundary */
+ c2 = (c1 + c3) / 2;
+
+ /* make it */
+ generate_hmap(y0, x0, xsize, ysize, grd, roug, c3);
+
+ /* Convert to normal format+ clean up */
+ done = generate_lake(y0, x0, xsize, ysize, c1, c2, c3, type);
+ }
+
+ /* Set icky flag because is a vault */
+ for (x = 0; x <= xsize; x++)
+ {
+ for (y = 0; y <= ysize; y++)
+ {
+ cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
+ }
+ }
+
+ /* make a few rooms in the vault */
+ for (i = 1; i <= (xsize * ysize) / 50; i++)
+ {
+ build_small_room(x0 + randint0(xsize - 4) - xsize / 2 + 2,
+ y0 + randint0(ysize - 4) - ysize / 2 + 2);
+ }
+
+ /* Fill with monsters and treasure, low difficulty */
+ fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1,
+ y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));
+}
+#endif /* ALLOW_CAVERNS_AND_LAKES */
+
+
+/* Build a "mini" checkerboard vault
+*
+* This is done by making a permanent wall maze and setting
+* the diagonal sqaures of the checker board to be granite.
+* The vault has two entrances on opposite sides to guarantee
+* a way to get in even if the vault abuts a side of the dungeon.
+*/
+static void build_mini_c_vault(POSITION x0, POSITION y0, POSITION xsize, POSITION ysize)
+{
+ POSITION dy, dx;
+ POSITION y1, x1, y2, x2, y, x, total;
+ int m, n, num_vertices;
+ int *visited;
+
+ msg_print_wizard(CHEAT_DUNGEON, _("小型チェッカーランダムVaultを生成しました。", "Mini Checker Board Vault."));
+
+ /* Pick a random room size */
+ dy = ysize / 2 - 1;
+ dx = xsize / 2 - 1;
+
+ y1 = y0 - dy;
+ x1 = x0 - dx;
+ y2 = y0 + dy;
+ x2 = x0 + dx;
+
+
+ /* generate the room */
+ for (x = x1 - 2; x <= x2 + 2; x++)
+ {
+ if (!in_bounds(y1 - 2, x)) break;
+
+ cave[y1 - 2][x].info |= (CAVE_ROOM | CAVE_ICKY);
+
+ place_outer_noperm_bold(y1 - 2, x);
+ }
+
+ for (x = x1 - 2; x <= x2 + 2; x++)
+ {
+ if (!in_bounds(y2 + 2, x)) break;
+
+ cave[y2 + 2][x].info |= (CAVE_ROOM | CAVE_ICKY);
+
+ place_outer_noperm_bold(y2 + 2, x);
+ }
+
+ for (y = y1 - 2; y <= y2 + 2; y++)
+ {
+ if (!in_bounds(y, x1 - 2)) break;
+
+ cave[y][x1 - 2].info |= (CAVE_ROOM | CAVE_ICKY);
+
+ place_outer_noperm_bold(y, x1 - 2);
+ }
+
+ for (y = y1 - 2; y <= y2 + 2; y++)
+ {
+ if (!in_bounds(y, x2 + 2)) break;
+
+ cave[y][x2 + 2].info |= (CAVE_ROOM | CAVE_ICKY);
+
+ place_outer_noperm_bold(y, x2 + 2);
+ }
+
+ for (y = y1 - 1; y <= y2 + 1; y++)
+ {
+ for (x = x1 - 1; x <= x2 + 1; x++)
+ {
+ cave_type *c_ptr = &cave[y][x];
+
+ c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
+
+ /* Permanent walls */
+ place_inner_perm_grid(c_ptr);
+ }
+ }
+
+
+ /* dimensions of vertex array */
+ m = dx + 1;
+ n = dy + 1;
+ num_vertices = m * n;
+
+ /* initialize array of visited vertices */
+ C_MAKE(visited, num_vertices, int);
+
+ /* traverse the graph to create a spannng tree, pick a random root */
+ r_visit(y1, x1, y2, x2, randint0(num_vertices), 0, visited);
+
+ /* Make it look like a checker board vault */
+ for (x = x1; x <= x2; x++)
+ {
+ for (y = y1; y <= y2; y++)
+ {
+ total = x - x1 + y - y1;
+ /* If total is odd- and is a floor then make a wall */
+ if ((total % 2 == 1) && is_floor_bold(y, x))
+ {
+ place_inner_bold(y, x);
+ }
+ }
+ }
+
+ /* Make a couple of entrances */
+ if (one_in_(2))
+ {
+ /* left and right */
+ y = randint1(dy) + dy / 2;
+ place_inner_bold(y1 + y, x1 - 1);
+ place_inner_bold(y1 + y, x2 + 1);
+ }
+ else
+ {
+ /* top and bottom */
+ x = randint1(dx) + dx / 2;
+ place_inner_bold(y1 - 1, x1 + x);
+ place_inner_bold(y2 + 1, x1 + x);
+ }
+
+ /* Fill with monsters and treasure, highest difficulty */
+ fill_treasure(x1, x2, y1, y2, 10);
+
+ C_KILL(visited, num_vertices, int);
+}
+
+/* Build a castle */
+/* Driver routine: clear the region and call the recursive
+* room routine.
+*
+*This makes a vault that looks like a castle/ city in the dungeon.
+*/
+static void build_castle_vault(POSITION x0, POSITION y0, POSITION xsize, POSITION ysize)
+{
+ POSITION dy, dx;
+ POSITION y1, x1, y2, x2;
+ POSITION y, x;
+
+ /* Pick a random room size */
+ dy = ysize / 2 - 1;
+ dx = xsize / 2 - 1;
+
+ y1 = y0 - dy;
+ x1 = x0 - dx;
+ y2 = y0 + dy;
+ x2 = x0 + dx;
+
+ msg_print_wizard(CHEAT_DUNGEON, _("城型ランダムVaultを生成しました。", "Castle Vault"));
+
+ /* generate the room */
+ for (y = y1 - 1; y <= y2 + 1; y++)
+ {
+ for (x = x1 - 1; x <= x2 + 1; x++)
+ {
+ cave[y][x].info |= (CAVE_ROOM | CAVE_ICKY);
+ /* Make everything a floor */
+ place_floor_bold(y, x);
+ }
+ }
+
+ /* Make the castle */
+ build_recursive_room(x1, y1, x2, y2, randint1(5));
+
+ /* Fill with monsters and treasure, low difficulty */
+ fill_treasure(x1, x2, y1, y2, randint1(3));
+}
+
+
+
+/*!
+* @brief タイプ10の部屋…ランダム生成vault / Type 10 -- Random vaults
+* @return なし
+*/
+bool build_type10(void)
+{
+ POSITION y0, x0, xsize, ysize, vtype;
+
+ /* big enough to look good, small enough to be fairly common. */
+ xsize = randint1(22) + 22;
+ ysize = randint1(11) + 11;
+
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&y0, &x0, ysize + 1, xsize + 1)) return FALSE;
+
+ /* Select type of vault */
+#ifdef ALLOW_CAVERNS_AND_LAKES
+ do
+ {
+ vtype = randint1(15);
+ } while ((d_info[p_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) &&
+ ((vtype == 1) || (vtype == 3) || (vtype == 8) || (vtype == 9) || (vtype == 11)));
+#else /* ALLOW_CAVERNS_AND_LAKES */
+ do
+ {
+ vtype = randint1(7);
+ } while ((d_info[p_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) &&
+ ((vtype == 1) || (vtype == 3)));
+#endif /* ALLOW_CAVERNS_AND_LAKES */
+
+ switch (vtype)
+ {
+ /* Build an appropriate room */
+ case 1: case 9: build_bubble_vault(x0, y0, xsize, ysize); break;
+ case 2: case 10: build_room_vault(x0, y0, xsize, ysize); break;
+ case 3: case 11: build_cave_vault(x0, y0, xsize, ysize); break;
+ case 4: case 12: build_maze_vault(x0, y0, xsize, ysize, TRUE); break;
+ case 5: case 13: build_mini_c_vault(x0, y0, xsize, ysize); break;
+ case 6: case 14: build_castle_vault(x0, y0, xsize, ysize); break;
+ case 7: case 15: build_target_vault(x0, y0, xsize, ysize); break;
+#ifdef ALLOW_CAVERNS_AND_LAKES
+ case 8: build_elemental_vault(x0, y0, xsize, ysize); break;
+#endif /* ALLOW_CAVERNS_AND_LAKES */
+ /* I know how to add a few more... give me some time. */
+
+ /* Paranoia */
+ default: return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/*!
+* @brief タイプ17の部屋…v_info.txtより固定特殊部屋を生成する / Type 17 -- fixed special room (see "v_info.txt")
+* @return なし
+*/
+bool build_type17(void)
+{
+ vault_type *v_ptr = NULL;
+ int dummy;
+ POSITION x, y;
+ POSITION xval, yval;
+ POSITION xoffset, yoffset;
+ int transno;
+
+ /* Pick a lesser vault */
+ for (dummy = 0; dummy < SAFE_MAX_ATTEMPTS; dummy++)
+ {
+ /* Access a random vault record */
+ v_ptr = &v_info[randint0(max_v_idx)];
+
+ /* Accept the special fix room. */
+ if (v_ptr->typ == 17) break;
+ }
+
+ /* No lesser vault found */
+ if (dummy >= SAFE_MAX_ATTEMPTS)
+ {
+ msg_print_wizard(CHEAT_DUNGEON, _("固定特殊部屋を配置できませんでした。", "Could not place fixed special room."));
+ return FALSE;
+ }
+
+ /* pick type of transformation (0-7) */
+ transno = randint0(8);
+
+ /* calculate offsets */
+ x = v_ptr->wid;
+ y = v_ptr->hgt;
+
+ /* Some huge vault cannot be ratated to fit in the dungeon */
+ if (x + 2 > cur_hgt - 2)
+ {
+ /* Forbid 90 or 270 degree ratation */
+ transno &= ~1;
+ }
+
+ coord_trans(&x, &y, 0, 0, transno);
+
+ if (x < 0)
+ {
+ xoffset = -x - 1;
+ }
+ else
+ {
+ xoffset = 0;
+ }
+
+ if (y < 0)
+ {
+ yoffset = -y - 1;
+ }
+ else
+ {
+ yoffset = 0;
+ }
+
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&yval, &xval, abs(y), abs(x))) return FALSE;
+
+#ifdef FORCE_V_IDX
+ v_ptr = &v_info[2];
+#endif
+
+ msg_format_wizard(CHEAT_DUNGEON, _("特殊固定部屋(%s)を生成しました。", "Special Fix room (%s)."), v_name + v_ptr->name);
+
+ /* Hack -- Build the vault */
+ build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,
+ v_text + v_ptr->text, xoffset, yoffset, transno);
+
+ return TRUE;
+}
+
-extern bool build_type7(void);\r
-extern bool build_type8(void);\r
-extern bool build_type10(void);\r
-extern bool build_type17(void);\r
-\r
+extern bool build_type7(void);
+extern bool build_type8(void);
+extern bool build_type10(void);
+extern bool build_type17(void);
+
-/*!\r
- * @file selfinfo.c\r
- * @brief 自己分析処理/ Self knowledge\r
- * @date 2018/09/07\r
- * @author\r
- * <pre>\r
- * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke\r
- * This software may be copied and distributed for educational, research,\r
- * and not for profit purposes provided that this copyright and statement\r
- * are included in all such copies. Other copyrights may also apply.\r
- * </pre>\r
- * 2018 Deskull\r
- * @details\r
- * spell2s.cから分離\r
- */\r
-\r
-#include "angband.h"\r
-#include "player-status.h"\r
-#include "avatar.h"\r
-\r
-/*!\r
- * @brief 自己分析処理(Nethackからのアイデア) / self-knowledge... idea from nethack.\r
- * @return なし\r
- * @details\r
- * <pre>\r
- * Useful for determining powers and\r
- * resistences of items. It saves the screen, clears it, then starts listing\r
- * attributes, a screenful at a time. (There are a LOT of attributes to\r
- * list. It will probably take 2 or 3 screens for a powerful character whose\r
- * using several artifacts...) -CFT\r
- *\r
- * It is now a lot more efficient. -BEN-\r
- *\r
- * See also "identify_fully()".\r
- *\r
- * Use the "show_file()" method, perhaps.\r
- * </pre>\r
- */\r
-void self_knowledge(void)\r
-{\r
- int i = 0, j, k;\r
-\r
- int v_nr = 0;\r
- char v_string [8] [128];\r
- char s_string [6] [128];\r
-\r
- BIT_FLAGS flgs[TR_FLAG_SIZE];\r
-\r
- object_type *o_ptr;\r
-\r
- char Dummy[80];\r
- char buf[2][80];\r
-\r
- concptr info[220];\r
-\r
- PLAYER_LEVEL plev = p_ptr->lev;\r
-\r
- int percent;\r
-\r
- for (j = 0; j < TR_FLAG_SIZE; j++)\r
- flgs[j] = 0L;\r
-\r
- p_ptr->knowledge |= (KNOW_STAT | KNOW_HPRATE);\r
-\r
- strcpy(Dummy, "");\r
-\r
- percent = (int)(((long)p_ptr->player_hp[PY_MAX_LEVEL - 1] * 200L) /\r
- (2 * p_ptr->hitdie +\r
- ((PY_MAX_LEVEL - 1+3) * (p_ptr->hitdie + 1))));\r
-\r
- sprintf(Dummy, _("現在の体力ランク : %d/100", "Your current Life Rating is %d/100."), percent);\r
- strcpy(buf[0], Dummy);\r
- info[i++] = buf[0];\r
- info[i++] = "";\r
-\r
- chg_virtue(V_KNOWLEDGE, 1);\r
- chg_virtue(V_ENLIGHTEN, 1);\r
-\r
- /* Acquire item flags from equipment */\r
- for (k = INVEN_RARM; k < INVEN_TOTAL; k++)\r
- {\r
- u32b tflgs[TR_FLAG_SIZE];\r
-\r
- o_ptr = &inventory[k];\r
-\r
- /* Skip non-objects */\r
- if (!o_ptr->k_idx) continue;\r
- object_flags(o_ptr, tflgs);\r
-\r
- /* Extract flags */\r
- for (j = 0; j < TR_FLAG_SIZE; j++)\r
- flgs[j] |= tflgs[j];\r
- }\r
-\r
- info[i++] = _("能力の最大値", "Limits of maximum stats");\r
-\r
- for (v_nr = 0; v_nr < A_MAX; v_nr++)\r
- {\r
- char stat_desc[80];\r
-\r
- sprintf(stat_desc, "%s 18/%d", stat_names[v_nr], p_ptr->stat_max_max[v_nr]-18);\r
-\r
- strcpy(s_string[v_nr], stat_desc);\r
-\r
- info[i++] = s_string[v_nr];\r
- }\r
- info[i++] = "";\r
-\r
- sprintf(Dummy, _("現在の属性 : %s(%ld)", "Your alighnment : %s(%ld)"), your_alignment(), (long int)p_ptr->align);\r
- strcpy(buf[1], Dummy);\r
- info[i++] = buf[1];\r
- for (v_nr = 0; v_nr < 8; v_nr++)\r
- {\r
- GAME_TEXT vir_name [20];\r
- char vir_desc[80];\r
- int tester = p_ptr->virtues[v_nr];\r
- \r
- strcpy(vir_name, virtue[(p_ptr->vir_types[v_nr])-1]);\r
- \r
- sprintf(vir_desc, _("おっと。%sの情報なし。", "Oops. No info about %s."), vir_name);\r
- if (tester < -100)\r
- sprintf(vir_desc, _("[%s]の対極 (%d)", "You are the polar opposite of %s (%d)."),\r
- vir_name, tester);\r
- else if (tester < -80)\r
- sprintf(vir_desc, _("[%s]の大敵 (%d)", "You are an arch-enemy of %s (%d)."),\r
- vir_name, tester);\r
- else if (tester < -60)\r
- sprintf(vir_desc, _("[%s]の強敵 (%d)", "You are a bitter enemy of %s (%d)."),\r
- vir_name, tester);\r
- else if (tester < -40)\r
- sprintf(vir_desc, _("[%s]の敵 (%d)", "You are an enemy of %s (%d)."),\r
- vir_name, tester);\r
- else if (tester < -20)\r
- sprintf(vir_desc, _("[%s]の罪者 (%d)", "You have sinned against %s (%d)."),\r
- vir_name, tester);\r
- else if (tester < 0)\r
- sprintf(vir_desc, _("[%s]の迷道者 (%d)", "You have strayed from the path of %s (%d)."),\r
- vir_name, tester);\r
- else if (tester == 0)\r
- sprintf(vir_desc, _("[%s]の中立者 (%d)", "You are neutral to %s (%d)."),\r
- vir_name, tester);\r
- else if (tester < 20)\r
- sprintf(vir_desc, _("[%s]の小徳者 (%d)", "You are somewhat virtuous in %s (%d)."),\r
- vir_name, tester);\r
- else if (tester < 40)\r
- sprintf(vir_desc, _("[%s]の中徳者 (%d)", "You are virtuous in %s (%d)."),\r
- vir_name, tester);\r
- else if (tester < 60)\r
- sprintf(vir_desc, _("[%s]の高徳者 (%d)", "You are very virtuous in %s (%d)."),\r
- vir_name, tester);\r
- else if (tester < 80)\r
- sprintf(vir_desc, _("[%s]の覇者 (%d)", "You are a champion of %s (%d)."),\r
- vir_name, tester);\r
- else if (tester < 100)\r
- sprintf(vir_desc, _("[%s]の偉大な覇者 (%d)", "You are a great champion of %s (%d)."),\r
- vir_name, tester);\r
- else\r
- sprintf(vir_desc, _("[%s]の具現者 (%d)", "You are the living embodiment of %s (%d)."),\r
- vir_name, tester);\r
- \r
- strcpy(v_string[v_nr], vir_desc);\r
- \r
- info[i++] = v_string[v_nr];\r
- }\r
- info[i++] = "";\r
- \r
- /* Racial powers... */\r
- if (p_ptr->mimic_form)\r
- {\r
- switch (p_ptr->mimic_form)\r
- {\r
- case MIMIC_DEMON:\r
- case MIMIC_DEMON_LORD:\r
- sprintf(Dummy, _("あなたは %d ダメージの地獄か火炎のブレスを吐くことができる。(%d MP)", \r
- "You can nether breathe, dam. %d (cost %d)."), 3 * plev, 10+plev/3);\r
-\r
- info[i++] = Dummy;\r
- break;\r
- case MIMIC_VAMPIRE:\r
- if (plev > 1)\r
- {\r
- sprintf(Dummy, _("あなたは敵から %d-%d HP の生命力を吸収できる。(%d MP)", \r
- "You can steal life from a foe, dam. %d-%d (cost %d)."),\r
- plev + MAX(1, plev / 10), plev + plev * MAX(1, plev / 10), 1 + (plev / 3));\r
- info[i++] = Dummy;\r
- }\r
- break;\r
- }\r
- }\r
- else\r
- {\r
- switch (p_ptr->prace)\r
- {\r
- case RACE_NIBELUNG:\r
- case RACE_DWARF:\r
- if (plev > 4)\r
- info[i++] = _("あなたは罠とドアと階段を感知できる。(5 MP)", "You can find traps, doors and stairs (cost 5).");\r
- break;\r
- case RACE_HOBBIT:\r
- if (plev > 14)\r
- {\r
- info[i++] = _("あなたは食料を生成できる。(10 MP)", "You can produce food (cost 10).");\r
- }\r
- break;\r
- case RACE_GNOME:\r
- if (plev > 4)\r
- {\r
- sprintf(Dummy, _("あなたは範囲 %d 以内にテレポートできる。(%d MP)", "You can teleport, range %d (cost %d)."),\r
- (1 + plev), (5 + (plev / 5)));\r
- info[i++] = Dummy;\r
- }\r
- break;\r
- case RACE_HALF_ORC:\r
- if (plev > 2)\r
- info[i++] = _("あなたは恐怖を除去できる。(5 MP)", "You can remove fear (cost 5).");\r
- break;\r
- case RACE_HALF_TROLL:\r
- if (plev > 9)\r
- info[i++] = _("あなたは狂暴化することができる。(12 MP) ", "You enter berserk fury (cost 12).");\r
- break;\r
- case RACE_AMBERITE:\r
- if (plev > 29)\r
- info[i++] = _("あなたはシャドウシフトすることができる。(50 MP)", "You can Shift Shadows (cost 50).");\r
-\r
- if (plev > 39)\r
- info[i++] = _("あなたは「パターン」を心に描いて歩くことができる。(75 MP)", "You can mentally Walk the Pattern (cost 75).");\r
-\r
- break;\r
- case RACE_BARBARIAN:\r
- if (plev > 7)\r
- info[i++] = _("あなたは狂暴化することができる。(10 MP) ", "You can enter berserk fury (cost 10).");\r
-\r
- break;\r
- case RACE_HALF_OGRE:\r
- if (plev > 24)\r
- info[i++] = _("あなたは爆発のルーンを仕掛けることができる。(35 MP)", "You can set an Explosive Rune (cost 35).");\r
-\r
- break;\r
- case RACE_HALF_GIANT:\r
- if (plev > 19)\r
- info[i++] = _("あなたは石の壁を壊すことができる。(10 MP)", "You can break stone walls (cost 10).");\r
- break;\r
- case RACE_HALF_TITAN:\r
- if (plev > 34)\r
- info[i++] = _("あなたはモンスターをスキャンすることができる。(20 MP)", "You can probe monsters (cost 20).");\r
- break;\r
- case RACE_CYCLOPS:\r
- if (plev > 19)\r
- {\r
- sprintf(Dummy, _("あなたは %d ダメージの岩石を投げることができる。(15 MP)", \r
- "You can throw a boulder, dam. %d (cost 15)."), 3 * plev);\r
- info[i++] = Dummy;\r
- }\r
- break;\r
- case RACE_YEEK:\r
- if (plev > 14)\r
- info[i++] = _("あなたは恐怖を呼び起こす叫び声を発することができる。(15 MP)", "You can make a terrifying scream (cost 15).");\r
- break;\r
- case RACE_KLACKON:\r
- if (plev > 8)\r
- {\r
- sprintf(Dummy, _("あなたは %d ダメージの酸を吹きかけることができる。(9 MP)", "You can spit acid, dam. %d (cost 9)."), plev);\r
- info[i++] = Dummy;\r
- }\r
- break;\r
- case RACE_KOBOLD:\r
- if (plev > 11)\r
- {\r
- sprintf(Dummy,\r
- _("あなたは %d ダメージの毒矢を投げることができる。(8 MP)", "You can throw a dart of poison, dam. %d (cost 8)."), plev);\r
- info[i++] = Dummy;\r
- }\r
- break;\r
- case RACE_DARK_ELF:\r
- if (plev > 1)\r
- {\r
- sprintf(Dummy, _("あなたは %d ダメージのマジック・ミサイルの呪文を使える。(2 MP)", "You can cast a Magic Missile, dam %d (cost 2)."),\r
- (3 + ((plev-1) / 5)));\r
- info[i++] = Dummy;\r
- }\r
- break;\r
- case RACE_DRACONIAN:\r
- sprintf(Dummy, _("あなたは %d ダメージのブレスを吐くことができる。(%d MP)", "You can breathe, dam. %d (cost %d)."), 2 * plev, plev);\r
- info[i++] = Dummy;\r
- break;\r
- case RACE_MIND_FLAYER:\r
- if (plev > 14)\r
- sprintf(Dummy, _("あなたは %d ダメージの精神攻撃をすることができる。(12 MP)", "You can mind blast your enemies, dam %d (cost 12)."), plev);\r
- info[i++] = Dummy;\r
- break;\r
- case RACE_IMP:\r
- if (plev > 29)\r
- {\r
- sprintf(Dummy, _("あなたは %d ダメージのファイア・ボールの呪文を使える。(15 MP)", "You can cast a Fire Ball, dam. %d (cost 15)."), plev);\r
- info[i++] = Dummy;\r
- }\r
- else if (plev > 8)\r
- {\r
- sprintf(Dummy, _("あなたは %d ダメージのファイア・ボルトの呪文を使える。(15 MP)", "You can cast a Fire Bolt, dam. %d (cost 15)."), plev);\r
- info[i++] = Dummy;\r
- }\r
- break;\r
- case RACE_GOLEM:\r
- if (plev > 19)\r
- info[i++] = _("あなたは d20+30 ターンの間肌を石に変化させられる。(15 MP)", "You can turn your skin to stone, dur d20+30 (cost 15).");\r
- break;\r
- case RACE_ZOMBIE:\r
- case RACE_SKELETON:\r
- if (plev > 29)\r
- info[i++] = _("あなたは失った経験値を回復することができる。(30 MP)", "You can restore lost experience (cost 30).");\r
- break;\r
- case RACE_VAMPIRE:\r
- if (plev > 1)\r
- {\r
- sprintf(Dummy, _("あなたは敵から %d-%d HP の生命力を吸収できる。(%d MP)", "You can steal life from a foe, dam. %d-%d (cost %d)."),\r
- plev + MAX(1, plev / 10), plev + plev * MAX(1, plev / 10), 1 + (plev / 3));\r
- info[i++] = Dummy;\r
- }\r
- break;\r
- case RACE_SPECTRE:\r
- if (plev > 3)\r
- {\r
- info[i++] = _("あなたは泣き叫んで敵を恐怖させることができる。(3 MP)", "You can wail to terrify your enemies (cost 3).");\r
- }\r
- break;\r
- case RACE_SPRITE:\r
- if (plev > 11)\r
- {\r
- info[i++] = _("あなたは敵を眠らせる魔法の粉を投げることができる。(12 MP)", "You can throw magical dust which induces sleep (cost 12).");\r
- }\r
- break;\r
- case RACE_DEMON:\r
- sprintf(Dummy, _("あなたは %d ダメージの地獄か火炎のブレスを吐くことができる。(%d MP)", \r
- "You can breathe nether, dam. %d (cost %d)."), 3 * plev, 10+plev/3);\r
-\r
- info[i++] = Dummy;\r
- break;\r
- case RACE_KUTAR:\r
- if (plev > 19)\r
- info[i++] = _("あなたは d20+30 ターンの間横に伸びることができる。(15 MP)", "You can expand horizontally, dur d20+30 (cost 15).");\r
- break;\r
- case RACE_ANDROID:\r
- if (plev < 10)\r
- sprintf(Dummy, _("あなたは %d ダメージのレイガンを撃つことができる。(7 MP)", "You can fire a ray gun with damage %d (cost 7)."), \r
- (plev + 1) / 2);\r
- else if (plev < 25)\r
- sprintf(Dummy, _("あなたは %d ダメージのブラスターを撃つことができる。(13 MP)", "You can fire a blaster with damage %d (cost 13)."), plev);\r
- else if (plev < 35)\r
- sprintf(Dummy, _("あなたは %d ダメージのバズーカを撃つことができる。(26 MP)", "You can fire a bazooka with damage %d (cost 26)."), plev * 2);\r
- else if (plev < 45)\r
- sprintf(Dummy, _("あなたは %d ダメージのビームキャノンを撃つことができる。(40 MP)", \r
- "You can fire a beam cannon with damage %d (cost 40)."), plev * 2);\r
- else\r
- sprintf(Dummy, _("あなたは %d ダメージのロケットを撃つことができる。(60 MP)", \r
- "You can fire a rocket with damage %d (cost 60)."), plev * 5);\r
-\r
- info[i++] = Dummy;\r
- break;\r
- default:\r
- break;\r
- }\r
- }\r
-\r
- switch(p_ptr->pclass)\r
- {\r
- case CLASS_WARRIOR:\r
- if (plev > 39)\r
- {\r
- info[i++] = _("あなたはランダムな方向に対して数回攻撃することができる。(75 MP)", \r
- "You can attack some random directions at a time (cost 75).");\r
- }\r
- break;\r
- case CLASS_HIGH_MAGE:\r
- if (p_ptr->realm1 == REALM_HEX) break;\r
- case CLASS_MAGE:\r
- case CLASS_SORCERER:\r
- if (plev > 24)\r
- {\r
- info[i++] = _("あなたはアイテムの魔力を吸収することができる。(1 MP)", \r
- "You can absorb charges from an item (cost 1).");\r
- }\r
- break;\r
- case CLASS_PRIEST:\r
- if (is_good_realm(p_ptr->realm1))\r
- {\r
- if (plev > 34)\r
- {\r
- info[i++] = _("あなたは武器を祝福することができる。(70 MP)", "You can bless a weapon (cost 70).");\r
- }\r
- }\r
- else\r
- {\r
- if (plev > 41)\r
- {\r
- info[i++] = _("あなたは周りのすべてのモンスターを攻撃することができる。(40 MP)", "You can damages all monsters in sight (cost 40).");\r
- }\r
- }\r
- break;\r
- case CLASS_ROGUE:\r
- if (plev > 7)\r
- {\r
- info[i++] = _("あなたは攻撃して即座に逃げることができる。(12 MP)", "You can hit a monster and teleport at a time (cost 12).");\r
- }\r
- break;\r
- case CLASS_RANGER:\r
- if (plev > 14)\r
- {\r
- info[i++] = _("あなたは怪物を調査することができる。(20 MP)", "You can prove monsters (cost 20).");\r
- }\r
- break;\r
- case CLASS_PALADIN:\r
- if (is_good_realm(p_ptr->realm1))\r
- {\r
- if (plev > 29)\r
- {\r
- info[i++] = _("あなたは聖なる槍を放つことができる。(30 MP)", "You can fires a holy spear (cost 30).");\r
- }\r
- }\r
- else\r
- {\r
- if (plev > 29)\r
- {\r
- info[i++] = _("あなたは生命力を減少させる槍を放つことができる。(30 MP)", "You can fires a spear which drains vitality (cost 30).");\r
- }\r
- }\r
- break;\r
- case CLASS_WARRIOR_MAGE:\r
- if (plev > 24)\r
- {\r
- info[i++] = _("あなたはHPをMPに変換することができる。(0 MP)", "You can convert HP to SP (cost 0).");\r
- info[i++] = _("あなたはMPをHPに変換することができる。(0 MP)", "You can convert SP to HP (cost 0).");\r
- }\r
- break;\r
- case CLASS_CHAOS_WARRIOR:\r
- if (plev > 39)\r
- {\r
- info[i++] = _("あなたは周囲に怪物を惑わす光を発生させることができる。(50 MP)",\r
- "You can radiate light which confuses nearby monsters (cost 50).");\r
- }\r
- break;\r
- case CLASS_MONK:\r
- if (plev > 24)\r
- {\r
- info[i++] = _("あなたは構えることができる。(0 MP)", "You can assume a posture of special form (cost 0).");\r
- }\r
- if (plev > 29)\r
- {\r
- info[i++] = _("あなたは通常の2倍の攻撃を行うことができる。(30 MP)", "You can perform double attacks in a time (cost 30).");\r
- }\r
- break;\r
- case CLASS_MINDCRAFTER:\r
- case CLASS_FORCETRAINER:\r
- if (plev > 14)\r
- {\r
- info[i++] = _("あなたは精神を集中してMPを回復させることができる。(0 MP)", "You can concentrate to regenerate your mana (cost 0).");\r
- }\r
- break;\r
- case CLASS_TOURIST:\r
- info[i++] = _("あなたは写真を撮影することができる。(0 MP)", "You can take a photograph (cost 0).");\r
- if (plev > 24)\r
- {\r
- info[i++] = _("あなたはアイテムを完全に鑑定することができる。(20 MP)", "You can *identify* items (cost 20).");\r
- }\r
- break;\r
- case CLASS_IMITATOR:\r
- if (plev > 29)\r
- {\r
- info[i++] = _("あなたは怪物の特殊攻撃をダメージ2倍でまねることができる。(100 MP)", \r
- "You can imitate monster's special attacks with double damage (cost 100).");\r
- }\r
- break;\r
- case CLASS_BEASTMASTER:\r
- info[i++] = _("あなたは1体の生命のあるモンスターを支配することができる。(レベル/4 MP)", "You can dominate a monster (cost level/4).");\r
- if (plev > 29)\r
- {\r
- info[i++] = _("あなたは視界内の生命のあるモンスターを支配することができる。((レベル+20)/2 MP)", \r
- "You can dominate living monsters in sight (cost (level+20)/4).");\r
- }\r
- break;\r
- case CLASS_MAGIC_EATER:\r
- info[i++] = _("あなたは杖/魔法棒/ロッドの魔力を自分のものにすることができる。", "You can absorb a staff, wand or rod itself.");\r
- break;\r
- case CLASS_RED_MAGE:\r
- if (plev > 47)\r
- {\r
- info[i++] = _("あなたは1ターンに2回魔法を唱えることができる。(20 MP)", "You can cast two spells in one time (cost 20).");\r
- }\r
- break;\r
- case CLASS_SAMURAI:\r
- {\r
- info[i++] = _("あなたは精神を集中して気合いを溜めることができる。", "You can concentrate to regenerate your mana.");\r
- }\r
- if (plev > 24)\r
- {\r
- info[i++] = _("あなたは特殊な型で構えることができる。", "You can assume a posture of special form.");\r
- }\r
- break;\r
- case CLASS_BLUE_MAGE:\r
- info[i++] = _("あなたは相手に使われた魔法を学ぶことができる。", "You can study spells which your enemy casts on you.");\r
- break;\r
- case CLASS_CAVALRY:\r
- if (plev > 9)\r
- {\r
- info[i++] = _("あなたはモンスターに乗って無理矢理ペットにすることができる。", "You can ride on a hostile monster forcibly to turn it into pet.");\r
- }\r
- break;\r
- case CLASS_BERSERKER:\r
- if (plev > 9)\r
- {\r
- info[i++] = _("あなたは街とダンジョンの間を行き来することができる。", "You can travel between town and the depths.");\r
- }\r
- break;\r
- case CLASS_MIRROR_MASTER:\r
- info[i++] = _("あなたは鏡を作り出すことができる。(2 MP)", "You can create a Mirror (cost 2).");\r
- info[i++] = _("あなたは鏡を割ることができる。(0 MP)", "You can break distant Mirrors (cost 0).");\r
- break;\r
- case CLASS_NINJA:\r
- if (plev > 19)\r
- {\r
- info[i++] = _("あなたは素早く移動することができる。", "You can walk extremery fast.");\r
- }\r
- break;\r
- }\r
-\r
- if (p_ptr->muta1)\r
- {\r
- if (p_ptr->muta1 & MUT1_SPIT_ACID)\r
- {\r
- info[i++] = _("あなたは酸を吹きかけることができる。(ダメージ レベルX1)", "You can spit acid (dam lvl).");\r
- }\r
- if (p_ptr->muta1 & MUT1_BR_FIRE)\r
- {\r
- info[i++] = _("あなたは炎のブレスを吐くことができる。(ダメージ レベルX2)", "You can breathe fire (dam lvl * 2).");\r
- }\r
- if (p_ptr->muta1 & MUT1_HYPN_GAZE)\r
- {\r
- info[i++] = _("あなたの睨みは催眠効果をもつ。", "Your gaze is hypnotic.");\r
- }\r
- if (p_ptr->muta1 & MUT1_TELEKINES)\r
- {\r
- info[i++] = _("あなたは念動力をもっている。", "You are telekinetic.");\r
- }\r
- if (p_ptr->muta1 & MUT1_VTELEPORT)\r
- {\r
- info[i++] = _("あなたは自分の意思でテレポートできる。", "You can teleport at will.");\r
- }\r
- if (p_ptr->muta1 & MUT1_MIND_BLST)\r
- {\r
- info[i++] = _("あなたは精神攻撃を行える。(ダメージ 3~12d3)", "You can Mind Blast your enemies (3 to 12d3 dam).");\r
- }\r
- if (p_ptr->muta1 & MUT1_RADIATION)\r
- {\r
- info[i++] = _("あなたは自分の意思で強い放射線を発生することができる。(ダメージ レベルX2)", "You can emit hard radiation at will (dam lvl * 2).");\r
- }\r
- if (p_ptr->muta1 & MUT1_VAMPIRISM)\r
- {\r
- info[i++] = _("あなたは吸血鬼のように敵から生命力を吸収することができる。(ダメージ レベルX2)", \r
- "You can drain life from a foe like a vampire (dam lvl * 2).");\r
- }\r
- if (p_ptr->muta1 & MUT1_SMELL_MET)\r
- {\r
- info[i++] = _("あなたは近くにある貴金属をかぎ分けることができる。", "You can smell nearby precious metal.");\r
- }\r
- if (p_ptr->muta1 & MUT1_SMELL_MON)\r
- {\r
- info[i++] = _("あなたは近くのモンスターの存在をかぎ分けることができる。", "You can smell nearby monsters.");\r
- }\r
- if (p_ptr->muta1 & MUT1_BLINK)\r
- {\r
- info[i++] = _("あなたは短い距離をテレポートできる。", "You can teleport yourself short distances.");\r
- }\r
- if (p_ptr->muta1 & MUT1_EAT_ROCK)\r
- {\r
- info[i++] = _("あなたは硬い岩を食べることができる。", "You can consume solid rock.");\r
- }\r
- if (p_ptr->muta1 & MUT1_SWAP_POS)\r
- {\r
- info[i++] = _("あなたは他の者と場所を入れ替わることができる。", "You can switch locations with another being.");\r
- }\r
- if (p_ptr->muta1 & MUT1_SHRIEK)\r
- {\r
- info[i++] = _("あなたは身の毛もよだつ叫び声を発することができる。(ダメージ レベルX2)", "You can emit a horrible shriek (dam 2 * lvl).");\r
- }\r
- if (p_ptr->muta1 & MUT1_ILLUMINE)\r
- {\r
- info[i++] = _("あなたは明るい光を放つことができる。", "You can emit bright light.");\r
- }\r
- if (p_ptr->muta1 & MUT1_DET_CURSE)\r
- {\r
- info[i++] = _("あなたは邪悪な魔法の危険を感じとることができる。", "You can feel the danger of evil magic.");\r
- }\r
- if (p_ptr->muta1 & MUT1_BERSERK)\r
- {\r
- info[i++] = _("あなたは自分の意思で狂乱戦闘状態になることができる。", "You can drive yourself into a berserk frenzy.");\r
- }\r
- if (p_ptr->muta1 & MUT1_POLYMORPH)\r
- {\r
- info[i++] = _("あなたは自分の意志で変化できる。", "You can polymorph yourself at will.");\r
- }\r
- if (p_ptr->muta1 & MUT1_MIDAS_TCH)\r
- {\r
- info[i++] = _("あなたは通常アイテムを金に変えることができる。", "You can turn ordinary items to gold.");\r
- }\r
- if (p_ptr->muta1 & MUT1_GROW_MOLD)\r
- {\r
- info[i++] = _("あなたは周囲にキノコを生やすことができる。", "You can cause mold to grow near you.");\r
- }\r
- if (p_ptr->muta1 & MUT1_RESIST)\r
- {\r
- info[i++] = _("あなたは元素の攻撃に対して身を硬くすることができる。", "You can harden yourself to the ravages of the elements.");\r
- }\r
- if (p_ptr->muta1 & MUT1_EARTHQUAKE)\r
- {\r
- info[i++] = _("あなたは周囲のダンジョンを崩壊させることができる。", "You can bring down the dungeon around your ears.");\r
- }\r
- if (p_ptr->muta1 & MUT1_EAT_MAGIC)\r
- {\r
- info[i++] = _("あなたは魔法のエネルギーを自分の物として使用できる。", "You can consume magic energy for your own use.");\r
- }\r
- if (p_ptr->muta1 & MUT1_WEIGH_MAG)\r
- {\r
- info[i++] = _("あなたは自分に影響を与える魔法の力を感じることができる。", "You can feel the strength of the magics affecting you.");\r
- }\r
- if (p_ptr->muta1 & MUT1_STERILITY)\r
- {\r
- info[i++] = _("あなたは集団的生殖不能を起こすことができる。", "You can cause mass impotence.");\r
- }\r
- if (p_ptr->muta1 & MUT1_PANIC_HIT)\r
- {\r
- info[i++] = _("あなたは攻撃した後身を守るため逃げることができる。", "You can run for your life after hitting something.");\r
- }\r
- if (p_ptr->muta1 & MUT1_DAZZLE)\r
- {\r
- info[i++] = _("あなたは混乱と盲目を引き起こす放射能を発生することができる。 ", "You can emit confusing, blinding radiation.");\r
- }\r
- if (p_ptr->muta1 & MUT1_LASER_EYE)\r
- {\r
- info[i++] = _("あなたは目からレーザー光線を発することができる。(ダメージ レベルX2)", "Your eyes can fire laser beams (dam 2 * lvl).");\r
- }\r
- if (p_ptr->muta1 & MUT1_RECALL)\r
- {\r
- info[i++] = _("あなたは街とダンジョンの間を行き来することができる。", "You can travel between town and the depths.");\r
- }\r
- if (p_ptr->muta1 & MUT1_BANISH)\r
- {\r
- info[i++] = _("あなたは邪悪なモンスターを地獄に落とすことができる。", "You can send evil creatures directly to Hell.");\r
- }\r
- if (p_ptr->muta1 & MUT1_COLD_TOUCH)\r
- {\r
- info[i++] = _("あなたは敵を触って凍らせることができる。(ダメージ レベルX3)", "You can freeze things with a touch (dam 3 * lvl).");\r
- }\r
- if (p_ptr->muta1 & MUT1_LAUNCHER)\r
- {\r
- info[i++] = _("あなたはアイテムを力強く投げることができる。", "You can hurl objects with great force.");\r
- }\r
- }\r
-\r
- if (p_ptr->muta2)\r
- {\r
- if (p_ptr->muta2 & MUT2_BERS_RAGE)\r
- {\r
- info[i++] = _("あなたは狂戦士化の発作を起こす。", "You are subject to berserker fits.");\r
- }\r
- if (p_ptr->muta2 & MUT2_COWARDICE)\r
- {\r
- info[i++] = _("あなたは時々臆病になる。", "You are subject to cowardice.");\r
- }\r
- if (p_ptr->muta2 & MUT2_RTELEPORT)\r
- {\r
- info[i++] = _("あなたはランダムにテレポートする。", "You are teleporting randomly.");\r
- }\r
- if (p_ptr->muta2 & MUT2_ALCOHOL)\r
- {\r
- info[i++] = _("あなたの体はアルコールを分泌する。", "Your body produces alcohol.");\r
- }\r
- if (p_ptr->muta2 & MUT2_HALLU)\r
- {\r
- info[i++] = _("あなたは幻覚を引き起こす精神錯乱に侵されている。", "You have a hallucinatory insanity.");\r
- }\r
- if (p_ptr->muta2 & MUT2_FLATULENT)\r
- {\r
- info[i++] = _("あなたは制御できない強烈な屁をこく。", "You are subject to uncontrollable flatulence.");\r
- }\r
- if (p_ptr->muta2 & MUT2_PROD_MANA)\r
- {\r
- info[i++] = _("あなたは制御不能な魔法のエネルギーを発している。", "You are producing magical energy uncontrollably.");\r
- }\r
- if (p_ptr->muta2 & MUT2_ATT_DEMON)\r
- {\r
- info[i++] = _("あなたはデーモンを引きつける。", "You attract demons.");\r
- }\r
- if (p_ptr->muta2 & MUT2_SCOR_TAIL)\r
- {\r
- info[i++] = _("あなたはサソリの尻尾が生えている。(毒、ダメージ 3d7)", "You have a scorpion tail (poison, 3d7).");\r
- }\r
- if (p_ptr->muta2 & MUT2_HORNS)\r
- {\r
- info[i++] = _("あなたは角が生えている。(ダメージ 2d6)", "You have horns (dam. 2d6).");\r
- }\r
- if (p_ptr->muta2 & MUT2_BEAK)\r
- {\r
- info[i++] = _("あなたはクチバシが生えている。(ダメージ 2d4)", "You have a beak (dam. 2d4).");\r
- }\r
- if (p_ptr->muta2 & MUT2_SPEED_FLUX)\r
- {\r
- info[i++] = _("あなたはランダムに早く動いたり遅く動いたりする。", "You move faster or slower randomly.");\r
- }\r
- if (p_ptr->muta2 & MUT2_BANISH_ALL)\r
- {\r
- info[i++] = _("あなたは時々近くのモンスターを消滅させる。", "You sometimes cause nearby creatures to vanish.");\r
- }\r
- if (p_ptr->muta2 & MUT2_EAT_LIGHT)\r
- {\r
- info[i++] = _("あなたは時々周囲の光を吸収して栄養にする。", "You sometimes feed off of the light around you.");\r
- }\r
- if (p_ptr->muta2 & MUT2_TRUNK)\r
- {\r
- info[i++] = _("あなたは象のような鼻を持っている。(ダメージ 1d4)", "You have an elephantine trunk (dam 1d4).");\r
- }\r
- if (p_ptr->muta2 & MUT2_ATT_ANIMAL)\r
- {\r
- info[i++] = _("あなたは動物を引きつける。", "You attract animals.");\r
- }\r
- if (p_ptr->muta2 & MUT2_TENTACLES)\r
- {\r
- info[i++] = _("あなたは邪悪な触手を持っている。(ダメージ 2d5)", "You have evil looking tentacles (dam 2d5).");\r
- }\r
- if (p_ptr->muta2 & MUT2_RAW_CHAOS)\r
- {\r
- info[i++] = _("あなたはしばしば純カオスに包まれる。", "You occasionally are surrounded with raw chaos.");\r
- }\r
- if (p_ptr->muta2 & MUT2_NORMALITY)\r
- {\r
- info[i++] = _("あなたは変異していたが、回復してきている。", "You may be mutated, but you're recovering.");\r
- }\r
- if (p_ptr->muta2 & MUT2_WRAITH)\r
- {\r
- info[i++] = _("あなたの肉体は幽体化したり実体化したりする。", "You fade in and out of physical reality.");\r
- }\r
- if (p_ptr->muta2 & MUT2_POLY_WOUND)\r
- {\r
- info[i++] = _("あなたの健康はカオスの力に影響を受ける。", "Your health is subject to chaotic forces.");\r
- }\r
- if (p_ptr->muta2 & MUT2_WASTING)\r
- {\r
- info[i++] = _("あなたは衰弱する恐ろしい病気にかかっている。", "You have a horrible wasting disease.");\r
- }\r
- if (p_ptr->muta2 & MUT2_ATT_DRAGON)\r
- {\r
- info[i++] = _("あなたはドラゴンを引きつける。", "You attract dragons.");\r
- }\r
- if (p_ptr->muta2 & MUT2_WEIRD_MIND)\r
- {\r
- info[i++] = _("あなたの精神はランダムに拡大したり縮小したりしている。", "Your mind randomly expands and contracts.");\r
- }\r
- if (p_ptr->muta2 & MUT2_NAUSEA)\r
- {\r
- info[i++] = _("あなたの胃は非常に落ち着きがない。", "You have a seriously upset stomach.");\r
- }\r
- if (p_ptr->muta2 & MUT2_CHAOS_GIFT)\r
- {\r
- info[i++] = _("あなたはカオスの守護悪魔から褒美をうけとる。", "Chaos deities give you gifts.");\r
- }\r
- if (p_ptr->muta2 & MUT2_WALK_SHAD)\r
- {\r
- info[i++] = _("あなたはしばしば他の「影」に迷い込む。", "You occasionally stumble into other shadows.");\r
- }\r
- if (p_ptr->muta2 & MUT2_WARNING)\r
- {\r
- info[i++] = _("あなたは敵に関する警告を感じる。", "You receive warnings about your foes.");\r
- }\r
- if (p_ptr->muta2 & MUT2_INVULN)\r
- {\r
- info[i++] = _("あなたは時々負け知らずな気分になる。", "You occasionally feel invincible.");\r
- }\r
- if (p_ptr->muta2 & MUT2_SP_TO_HP)\r
- {\r
- info[i++] = _("あなたは時々血が筋肉にどっと流れる。", "Your blood sometimes rushes to your muscles.");\r
- }\r
- if (p_ptr->muta2 & MUT2_HP_TO_SP)\r
- {\r
- info[i++] = _("あなたは時々頭に血がどっと流れる。", "Your blood sometimes rushes to your head.");\r
- }\r
- if (p_ptr->muta2 & MUT2_DISARM)\r
- {\r
- info[i++] = _("あなたはよくつまづいて物を落とす。", "You occasionally stumble and drop things.");\r
- }\r
- }\r
-\r
- if (p_ptr->muta3)\r
- {\r
- if (p_ptr->muta3 & MUT3_HYPER_STR)\r
- {\r
- info[i++] = _("あなたは超人的に強い。(腕力+4)", "You are superhumanly strong (+4 STR).");\r
- }\r
- if (p_ptr->muta3 & MUT3_PUNY)\r
- {\r
- info[i++] = _("あなたは虚弱だ。(腕力-4)", "You are puny (-4 STR).");\r
- }\r
- if (p_ptr->muta3 & MUT3_HYPER_INT)\r
- {\r
- info[i++] = _("あなたの脳は生体コンピュータだ。(知能&賢さ+4)", "Your brain is a living computer (+4 INT/WIS).");\r
- }\r
- if (p_ptr->muta3 & MUT3_MORONIC)\r
- {\r
- info[i++] = _("あなたは精神薄弱だ。(知能&賢さ-4)", "You are moronic (-4 INT/WIS).");\r
- }\r
- if (p_ptr->muta3 & MUT3_RESILIENT)\r
- {\r
- info[i++] = _("あなたは非常にタフだ。(耐久+4)", "You are very resilient (+4 CON).");\r
- }\r
- if (p_ptr->muta3 & MUT3_XTRA_FAT)\r
- {\r
- info[i++] = _("あなたは極端に太っている。(耐久+2,スピード-2)", "You are extremely fat (+2 CON, -2 speed).");\r
- }\r
- if (p_ptr->muta3 & MUT3_ALBINO)\r
- {\r
- info[i++] = _("あなたはアルビノだ。(耐久-4)", "You are albino (-4 CON).");\r
- }\r
- if (p_ptr->muta3 & MUT3_FLESH_ROT)\r
- {\r
- info[i++] = _("あなたの肉体は腐敗している。(耐久-2,魅力-1)", "Your flesh is rotting (-2 CON, -1 CHR).");\r
- }\r
- if (p_ptr->muta3 & MUT3_SILLY_VOI)\r
- {\r
- info[i++] = _("あなたの声は間抜けなキーキー声だ。(魅力-4)", "Your voice is a silly squeak (-4 CHR).");\r
- }\r
- if (p_ptr->muta3 & MUT3_BLANK_FAC)\r
- {\r
- info[i++] = _("あなたはのっぺらぼうだ。(魅力-1)", "Your face is featureless (-1 CHR).");\r
- }\r
- if (p_ptr->muta3 & MUT3_ILL_NORM)\r
- {\r
- info[i++] = _("あなたは幻影に覆われている。", "Your appearance is masked with illusion.");\r
- }\r
- if (p_ptr->muta3 & MUT3_XTRA_EYES)\r
- {\r
- info[i++] = _("あなたは余分に二つの目を持っている。(探索+15)", "You have an extra pair of eyes (+15 search).");\r
- }\r
- if (p_ptr->muta3 & MUT3_MAGIC_RES)\r
- {\r
- info[i++] = _("あなたは魔法への耐性をもっている。", "You are resistant to magic.");\r
- }\r
- if (p_ptr->muta3 & MUT3_XTRA_NOIS)\r
- {\r
- info[i++] = _("あなたは変な音を発している。(隠密-3)", "You make a lot of strange noise (-3 stealth).");\r
- }\r
- if (p_ptr->muta3 & MUT3_INFRAVIS)\r
- {\r
- info[i++] = _("あなたは素晴らしい赤外線視力を持っている。(+3)", "You have remarkable infravision (+3).");\r
- }\r
- if (p_ptr->muta3 & MUT3_XTRA_LEGS)\r
- {\r
- info[i++] = _("あなたは余分に二本の足が生えている。(加速+3)", "You have an extra pair of legs (+3 speed).");\r
- }\r
- if (p_ptr->muta3 & MUT3_SHORT_LEG)\r
- {\r
- info[i++] = _("あなたの足は短い突起だ。(加速-3)", "Your legs are short stubs (-3 speed).");\r
- }\r
- if (p_ptr->muta3 & MUT3_ELEC_TOUC)\r
- {\r
- info[i++] = _("あなたの血管には電流が流れている。", "Electricity is running through your veins.");\r
- }\r
- if (p_ptr->muta3 & MUT3_FIRE_BODY)\r
- {\r
- info[i++] = _("あなたの体は炎につつまれている。", "Your body is enveloped in flames.");\r
- }\r
- if (p_ptr->muta3 & MUT3_WART_SKIN)\r
- {\r
- info[i++] = _("あなたの肌はイボに被われている。(魅力-2, AC+5)", "Your skin is covered with warts (-2 CHR, +5 AC).");\r
- }\r
- if (p_ptr->muta3 & MUT3_SCALES)\r
- {\r
- info[i++] = _("あなたの肌は鱗になっている。(魅力-1, AC+10)", "Your skin has turned into scales (-1 CHR, +10 AC).");\r
- }\r
- if (p_ptr->muta3 & MUT3_IRON_SKIN)\r
- {\r
- info[i++] = _("あなたの肌は鉄でできている。(器用-1, AC+25)", "Your skin is made of steel (-1 DEX, +25 AC).");\r
- }\r
- if (p_ptr->muta3 & MUT3_WINGS)\r
- {\r
- info[i++] = _("あなたは羽を持っている。", "You have wings.");\r
- }\r
- if (p_ptr->muta3 & MUT3_FEARLESS)\r
- {\r
- /* Unnecessary */\r
- }\r
- if (p_ptr->muta3 & MUT3_REGEN)\r
- {\r
- /* Unnecessary */\r
- }\r
- if (p_ptr->muta3 & MUT3_ESP)\r
- {\r
- /* Unnecessary */\r
- }\r
- if (p_ptr->muta3 & MUT3_LIMBER)\r
- {\r
- info[i++] = _("あなたの体は非常にしなやかだ。(器用+3)", "Your body is very limber (+3 DEX).");\r
- }\r
- if (p_ptr->muta3 & MUT3_ARTHRITIS)\r
- {\r
- info[i++] = _("あなたはいつも関節に痛みを感じている。(器用-3)", "Your joints ache constantly (-3 DEX).");\r
- }\r
- if (p_ptr->muta3 & MUT3_VULN_ELEM)\r
- {\r
- info[i++] = _("あなたは元素の攻撃に弱い。", "You are susceptible to damage from the elements.");\r
- }\r
- if (p_ptr->muta3 & MUT3_MOTION)\r
- {\r
- info[i++] = _("あなたの動作は正確で力強い。(隠密+1)", "Your movements are precise and forceful (+1 STL).");\r
- }\r
- if (p_ptr->muta3 & MUT3_GOOD_LUCK)\r
- {\r
- info[i++] = _("あなたは白いオーラにつつまれている。", "There is a white aura surrounding you.");\r
- }\r
- if (p_ptr->muta3 & MUT3_BAD_LUCK)\r
- {\r
- info[i++] = _("あなたは黒いオーラにつつまれている。", "There is a black aura surrounding you.");\r
- }\r
- }\r
-\r
- if (p_ptr->blind)\r
- {\r
- info[i++] = _("あなたは目が見えない。", "You cannot see.");\r
- }\r
- if (p_ptr->confused)\r
- {\r
- info[i++] = _("あなたは混乱している。", "You are confused.");\r
- }\r
- if (p_ptr->afraid)\r
- {\r
- info[i++] = _("あなたは恐怖に侵されている。", "You are terrified.");\r
- }\r
- if (p_ptr->cut)\r
- {\r
- info[i++] = _("あなたは出血している。", "You are bleeding.");\r
- }\r
- if (p_ptr->stun)\r
- {\r
- info[i++] = _("あなたはもうろうとしている。", "You are stunned.");\r
- }\r
- if (p_ptr->poisoned)\r
- {\r
- info[i++] = _("あなたは毒に侵されている。", "You are poisoned.");\r
- }\r
- if (p_ptr->image)\r
- {\r
- info[i++] = _("あなたは幻覚を見ている。", "You are hallucinating.");\r
- }\r
- if (p_ptr->cursed & TRC_TY_CURSE)\r
- {\r
- info[i++] = _("あなたは邪悪な怨念に包まれている。", "You carry an ancient foul curse.");\r
- }\r
- if (p_ptr->cursed & TRC_AGGRAVATE)\r
- {\r
- info[i++] = _("あなたはモンスターを怒らせている。", "You aggravate monsters.");\r
- }\r
- if (p_ptr->cursed & TRC_DRAIN_EXP)\r
- {\r
- info[i++] = _("あなたは経験値を吸われている。", "You are drained.");\r
- }\r
- if (p_ptr->cursed & TRC_SLOW_REGEN)\r
- {\r
- info[i++] = _("あなたの回復力は非常に遅い。", "You regenerate slowly.");\r
- }\r
- if (p_ptr->cursed & TRC_ADD_L_CURSE)\r
- {\r
- info[i++] = _("あなたの弱い呪いは増える。","Your weak curses multiply."); /* 暫定的 -- henkma */\r
- }\r
- if (p_ptr->cursed & TRC_ADD_H_CURSE)\r
- {\r
- info[i++] = _("あなたの強い呪いは増える。","Your heavy curses multiply."); /* 暫定的 -- henkma */\r
- }\r
- if (p_ptr->cursed & TRC_CALL_ANIMAL)\r
- {\r
- info[i++] = _("あなたは動物に狙われている。", "You attract animals.");\r
- }\r
- if (p_ptr->cursed & TRC_CALL_DEMON)\r
- {\r
- info[i++] = _("あなたは悪魔に狙われている。", "You attract demons.");\r
- }\r
- if (p_ptr->cursed & TRC_CALL_DRAGON)\r
- {\r
- info[i++] = _("あなたはドラゴンに狙われている。", "You attract dragons.");\r
- }\r
- if (p_ptr->cursed & TRC_COWARDICE)\r
- {\r
- info[i++] = _("あなたは時々臆病になる。", "You are subject to cowardice.");\r
- }\r
- if (p_ptr->cursed & TRC_TELEPORT)\r
- {\r
- info[i++] = _("あなたの位置はひじょうに不安定だ。", "Your position is very uncertain.");\r
- }\r
- if (p_ptr->cursed & TRC_LOW_MELEE)\r
- {\r
- info[i++] = _("あなたの武器は攻撃を外しやすい。", "Your weapon causes you to miss blows.");\r
- }\r
- if (p_ptr->cursed & TRC_LOW_AC)\r
- {\r
- info[i++] = _("あなたは攻撃を受けやすい。", "You are subject to be hit.");\r
- }\r
- if (p_ptr->cursed & TRC_LOW_MAGIC)\r
- {\r
- info[i++] = _("あなたは魔法を失敗しやすい。", "You are subject to fail spellcasting.");\r
- }\r
- if (p_ptr->cursed & TRC_FAST_DIGEST)\r
- {\r
- info[i++] = _("あなたはすぐお腹がへる。", "You have a good appetite.");\r
- }\r
- if (p_ptr->cursed & TRC_DRAIN_HP)\r
- {\r
- info[i++] = _("あなたは体力を吸われている。", "You are drained.");\r
- }\r
- if (p_ptr->cursed & TRC_DRAIN_MANA)\r
- {\r
- info[i++] = _("あなたは魔力を吸われている。", "You brain is drained.");\r
- }\r
- if (IS_BLESSED())\r
- {\r
- info[i++] = _("あなたは高潔さを感じている。", "You feel rightous.");\r
- }\r
- if (IS_HERO())\r
- {\r
- info[i++] = _("あなたはヒーロー気分だ。", "You feel heroic.");\r
- }\r
- if (p_ptr->shero)\r
- {\r
- info[i++] = _("あなたは戦闘狂だ。", "You are in a battle rage.");\r
- }\r
- if (p_ptr->protevil)\r
- {\r
- info[i++] = _("あなたは邪悪なる存在から守られている。", "You are protected from evil.");\r
- }\r
- if (p_ptr->shield)\r
- {\r
- info[i++] = _("あなたは神秘のシールドで守られている。", "You are protected by a mystic shield.");\r
- }\r
- if (IS_INVULN())\r
- {\r
- info[i++] = _("あなたは現在傷つかない。", "You are temporarily invulnerable.");\r
- }\r
- if (p_ptr->wraith_form)\r
- {\r
- info[i++] = _("あなたは一時的に幽体化している。", "You are temporarily incorporeal.");\r
- }\r
- if (p_ptr->special_attack & ATTACK_CONFUSE)\r
- {\r
- info[i++] = _("あなたの手は赤く輝いている。", "Your hands are glowing dull red.");\r
- }\r
- if (p_ptr->special_attack & ATTACK_FIRE)\r
- {\r
- info[i++] = _("あなたの手は火炎に覆われている。", "You can strike the enemy with flame.");\r
- }\r
- if (p_ptr->special_attack & ATTACK_COLD)\r
- {\r
- info[i++] = _("あなたの手は冷気に覆われている。", "You can strike the enemy with cold.");\r
- }\r
- if (p_ptr->special_attack & ATTACK_ACID)\r
- {\r
- info[i++] = _("あなたの手は酸に覆われている。", "You can strike the enemy with acid.");\r
- }\r
- if (p_ptr->special_attack & ATTACK_ELEC)\r
- {\r
- info[i++] = _("あなたの手は電撃に覆われている。", "You can strike the enemy with electoric shock.");\r
- }\r
- if (p_ptr->special_attack & ATTACK_POIS)\r
- {\r
- info[i++] = _("あなたの手は毒に覆われている。", "You can strike the enemy with poison.");\r
- }\r
- switch (p_ptr->action)\r
- {\r
- case ACTION_SEARCH:\r
- info[i++] = _("あなたはひじょうに注意深く周囲を見渡している。", "You are looking around very carefully.");\r
- break;\r
- }\r
- if (p_ptr->new_spells)\r
- {\r
- info[i++] = _("あなたは呪文や祈りを学ぶことができる。", "You can learn some spells/prayers.");\r
- }\r
- if (p_ptr->word_recall)\r
- {\r
- info[i++] = _("あなたはすぐに帰還するだろう。", "You will soon be recalled.");\r
- }\r
- if (p_ptr->alter_reality)\r
- {\r
- info[i++] = _("あなたはすぐにこの世界を離れるだろう。", "You will soon be altered.");\r
- }\r
- if (p_ptr->see_infra)\r
- {\r
- info[i++] = _("あなたの瞳は赤外線に敏感である。", "Your eyes are sensitive to infrared light.");\r
- }\r
- if (p_ptr->see_inv)\r
- {\r
- info[i++] = _("あなたは透明なモンスターを見ることができる。", "You can see invisible creatures.");\r
- }\r
- if (p_ptr->levitation)\r
- {\r
- info[i++] = _("あなたは飛ぶことができる。", "You can fly.");\r
- }\r
- if (p_ptr->free_act)\r
- {\r
- info[i++] = _("あなたは麻痺知らずの効果を持っている。", "You have free action.");\r
- }\r
- if (p_ptr->regenerate)\r
- {\r
- info[i++] = _("あなたは素早く体力を回復する。", "You regenerate quickly.");\r
- }\r
- if (p_ptr->slow_digest)\r
- {\r
- info[i++] = _("あなたは食欲が少ない。", "Your appetite is small.");\r
- }\r
- if (p_ptr->telepathy)\r
- {\r
- info[i++] = _("あなたはテレパシー能力を持っている。", "You have ESP.");\r
- }\r
- if (p_ptr->esp_animal)\r
- {\r
- info[i++] = _("あなたは自然界の生物の存在を感じる能力を持っている。", "You sense natural creatures.");\r
- }\r
- if (p_ptr->esp_undead)\r
- {\r
- info[i++] = _("あなたはアンデッドの存在を感じる能力を持っている。", "You sense undead.");\r
- }\r
- if (p_ptr->esp_demon)\r
- {\r
- info[i++] = _("あなたは悪魔の存在を感じる能力を持っている。", "You sense demons.");\r
- }\r
- if (p_ptr->esp_orc)\r
- {\r
- info[i++] = _("あなたはオークの存在を感じる能力を持っている。", "You sense orcs.");\r
- }\r
- if (p_ptr->esp_troll)\r
- {\r
- info[i++] = _("あなたはトロルの存在を感じる能力を持っている。", "You sense trolls.");\r
- }\r
- if (p_ptr->esp_giant)\r
- {\r
- info[i++] = _("あなたは巨人の存在を感じる能力を持っている。", "You sense giants.");\r
- }\r
- if (p_ptr->esp_dragon)\r
- {\r
- info[i++] = _("あなたはドラゴンの存在を感じる能力を持っている。", "You sense dragons.");\r
- }\r
- if (p_ptr->esp_human)\r
- {\r
- info[i++] = _("あなたは人間の存在を感じる能力を持っている。", "You sense humans.");\r
- }\r
- if (p_ptr->esp_evil)\r
- {\r
- info[i++] = _("あなたは邪悪な生き物の存在を感じる能力を持っている。", "You sense evil creatures.");\r
- }\r
- if (p_ptr->esp_good)\r
- {\r
- info[i++] = _("あなたは善良な生き物の存在を感じる能力を持っている。", "You sense good creatures.");\r
- }\r
- if (p_ptr->esp_nonliving)\r
- {\r
- info[i++] = _("あなたは活動する無生物体の存在を感じる能力を持っている。", "You sense non-living creatures.");\r
- }\r
- if (p_ptr->esp_unique)\r
- {\r
- info[i++] = _("あなたは特別な強敵の存在を感じる能力を持っている。", "You sense unique monsters.");\r
- }\r
- if (p_ptr->hold_exp)\r
- {\r
- info[i++] = _("あなたは自己の経験値をしっかりと維持する。", "You have a firm hold on your experience.");\r
- }\r
- if (p_ptr->reflect)\r
- {\r
- info[i++] = _("あなたは矢の呪文を反射する。", "You reflect bolt spells.");\r
- }\r
- if (p_ptr->sh_fire)\r
- {\r
- info[i++] = _("あなたは炎のオーラに包まれている。", "You are surrounded with a fiery aura.");\r
- }\r
- if (p_ptr->sh_elec)\r
- {\r
- info[i++] = _("あなたは電気に包まれている。", "You are surrounded with electricity.");\r
- }\r
- if (p_ptr->sh_cold)\r
- {\r
- info[i++] = _("あなたは冷気のオーラに包まれている。", "You are surrounded with an aura of coldness.");\r
- }\r
- if (p_ptr->tim_sh_holy)\r
- {\r
- info[i++] = _("あなたは聖なるオーラに包まれている。", "You are surrounded with a holy aura.");\r
- }\r
- if (p_ptr->tim_sh_touki)\r
- {\r
- info[i++] = _("あなたは闘気のオーラに包まれている。", "You are surrounded with a energy aura.");\r
- }\r
- if (p_ptr->anti_magic)\r
- {\r
- info[i++] = _("あなたは反魔法シールドに包まれている。", "You are surrounded by an anti-magic shell.");\r
- }\r
- if (p_ptr->anti_tele)\r
- {\r
- info[i++] = _("あなたはテレポートできない。", "You cannot teleport.");\r
- }\r
- if (p_ptr->lite)\r
- {\r
- info[i++] = _("あなたの身体は光っている。", "You are carrying a permanent light.");\r
- }\r
- if (p_ptr->warning)\r
- {\r
- info[i++] = _("あなたは行動の前に危険を察知することができる。", "You will be warned before dangerous actions.");\r
- }\r
- if (p_ptr->dec_mana)\r
- {\r
- info[i++] = _("あなたは少ない消費魔力で魔法を唱えることができる。", "You can cast spells with fewer mana points.");\r
- }\r
- if (p_ptr->easy_spell)\r
- {\r
- info[i++] = _("あなたは低い失敗率で魔法を唱えることができる。", "Fail rate of your magic is decreased.");\r
- }\r
- if (p_ptr->heavy_spell)\r
- {\r
- info[i++] = _("あなたは高い失敗率で魔法を唱えなければいけない。", "Fail rate of your magic is increased.");\r
- }\r
- if (p_ptr->mighty_throw)\r
- {\r
- info[i++] = _("あなたは強く物を投げる。", "You can throw objects powerfully.");\r
- }\r
-\r
- if (p_ptr->immune_acid)\r
- {\r
- info[i++] = _("あなたは酸に対する完全なる免疫を持っている。", "You are completely immune to acid.");\r
- }\r
- else if (p_ptr->resist_acid && IS_OPPOSE_ACID())\r
- {\r
- info[i++] = _("あなたは酸への強力な耐性を持っている。", "You resist acid exceptionally well.");\r
- }\r
- else if (p_ptr->resist_acid || IS_OPPOSE_ACID())\r
- {\r
- info[i++] = _("あなたは酸への耐性を持っている。", "You are resistant to acid.");\r
- }\r
-\r
- if (p_ptr->immune_elec)\r
- {\r
- info[i++] = _("あなたは電撃に対する完全なる免疫を持っている。", "You are completely immune to lightning.");\r
- }\r
- else if (p_ptr->resist_elec && IS_OPPOSE_ELEC())\r
- {\r
- info[i++] = _("あなたは電撃への強力な耐性を持っている。", "You resist lightning exceptionally well.");\r
- }\r
- else if (p_ptr->resist_elec || IS_OPPOSE_ELEC())\r
- {\r
- info[i++] = _("あなたは電撃への耐性を持っている。", "You are resistant to lightning.");\r
- }\r
-\r
- if (prace_is_(RACE_ANDROID) && !p_ptr->immune_elec)\r
- {\r
- info[i++] = _("あなたは電撃に弱い。", "You are susceptible to damage from lightning.");\r
- }\r
-\r
- if (p_ptr->immune_fire)\r
- {\r
- info[i++] = _("あなたは火に対する完全なる免疫を持っている。", "You are completely immune to fire.");\r
- }\r
- else if (p_ptr->resist_fire && IS_OPPOSE_FIRE())\r
- {\r
- info[i++] = _("あなたは火への強力な耐性を持っている。", "You resist fire exceptionally well.");\r
- }\r
- else if (p_ptr->resist_fire || IS_OPPOSE_FIRE())\r
- {\r
- info[i++] = _("あなたは火への耐性を持っている。", "You are resistant to fire.");\r
- }\r
-\r
- if (prace_is_(RACE_ENT) && !p_ptr->immune_fire)\r
- {\r
- info[i++] = _("あなたは火に弱い。", "You are susceptible to damage from fire.");\r
- }\r
-\r
- if (p_ptr->immune_cold)\r
- {\r
- info[i++] = _("あなたは冷気に対する完全なる免疫を持っている。", "You are completely immune to cold.");\r
- }\r
- else if (p_ptr->resist_cold && IS_OPPOSE_COLD())\r
- {\r
- info[i++] = _("あなたは冷気への強力な耐性を持っている。", "You resist cold exceptionally well.");\r
- }\r
- else if (p_ptr->resist_cold || IS_OPPOSE_COLD())\r
- {\r
- info[i++] = _("あなたは冷気への耐性を持っている。", "You are resistant to cold.");\r
- }\r
-\r
- if (p_ptr->resist_pois && IS_OPPOSE_POIS())\r
- {\r
- info[i++] = _("あなたは毒への強力な耐性を持っている。", "You resist poison exceptionally well.");\r
- }\r
- else if (p_ptr->resist_pois || IS_OPPOSE_POIS())\r
- {\r
- info[i++] = _("あなたは毒への耐性を持っている。", "You are resistant to poison.");\r
- }\r
-\r
- if (p_ptr->resist_lite)\r
- {\r
- info[i++] = _("あなたは閃光への耐性を持っている。", "You are resistant to bright light.");\r
- }\r
-\r
- if (prace_is_(RACE_VAMPIRE) || prace_is_(RACE_S_FAIRY) || (p_ptr->mimic_form == MIMIC_VAMPIRE))\r
- {\r
- info[i++] = _("あなたは閃光に弱い。", "You are susceptible to damage from bright light.");\r
- }\r
-\r
- if (prace_is_(RACE_VAMPIRE) || (p_ptr->mimic_form == MIMIC_VAMPIRE) || p_ptr->wraith_form)\r
- {\r
- info[i++] = _("あなたは暗黒に対する完全なる免疫を持っている。", "You are completely immune to darkness.");\r
- }\r
-\r
- else if (p_ptr->resist_dark)\r
- {\r
- info[i++] = _("あなたは暗黒への耐性を持っている。", "You are resistant to darkness.");\r
- }\r
- if (p_ptr->resist_conf)\r
- {\r
- info[i++] = _("あなたは混乱への耐性を持っている。", "You are resistant to confusion.");\r
- }\r
- if (p_ptr->resist_sound)\r
- {\r
- info[i++] = _("あなたは音波の衝撃への耐性を持っている。", "You are resistant to sonic attacks.");\r
- }\r
- if (p_ptr->resist_disen)\r
- {\r
- info[i++] = _("あなたは劣化への耐性を持っている。", "You are resistant to disenchantment.");\r
- }\r
- if (p_ptr->resist_chaos)\r
- {\r
- info[i++] = _("あなたはカオスの力への耐性を持っている。", "You are resistant to chaos.");\r
- }\r
- if (p_ptr->resist_shard)\r
- {\r
- info[i++] = _("あなたは破片の攻撃への耐性を持っている。", "You are resistant to blasts of shards.");\r
- }\r
- if (p_ptr->resist_nexus)\r
- {\r
- info[i++] = _("あなたは因果混乱の攻撃への耐性を持っている。", "You are resistant to nexus attacks.");\r
- }\r
-\r
- if (prace_is_(RACE_SPECTRE))\r
- {\r
- info[i++] = _("あなたは地獄の力を吸収できる。", "You can drain nether forces.");\r
- }\r
- else if (p_ptr->resist_neth)\r
- {\r
- info[i++] = _("あなたは地獄の力への耐性を持っている。", "You are resistant to nether forces.");\r
- }\r
- if (p_ptr->resist_fear)\r
- {\r
- info[i++] = _("あなたは全く恐怖を感じない。", "You are completely fearless.");\r
- }\r
- if (p_ptr->resist_blind)\r
- {\r
- info[i++] = _("あなたの目は盲目への耐性を持っている。", "Your eyes are resistant to blindness.");\r
- }\r
- if (p_ptr->resist_time)\r
- {\r
- info[i++] = _("あなたは時間逆転への耐性を持っている。", "You are resistant to time.");\r
- }\r
-\r
- if (p_ptr->sustain_str)\r
- {\r
- info[i++] = _("あなたの腕力は維持されている。", "Your strength is sustained.");\r
- }\r
- if (p_ptr->sustain_int)\r
- {\r
- info[i++] = _("あなたの知能は維持されている。", "Your intelligence is sustained.");\r
- }\r
- if (p_ptr->sustain_wis)\r
- {\r
- info[i++] = _("あなたの賢さは維持されている。", "Your wisdom is sustained.");\r
- }\r
- if (p_ptr->sustain_con)\r
- {\r
- info[i++] = _("あなたの耐久力は維持されている。", "Your constitution is sustained.");\r
- }\r
- if (p_ptr->sustain_dex)\r
- {\r
- info[i++] = _("あなたの器用さは維持されている。", "Your dexterity is sustained.");\r
- }\r
- if (p_ptr->sustain_chr)\r
- {\r
- info[i++] = _("あなたの魅力は維持されている。", "Your charisma is sustained.");\r
- }\r
-\r
- if (have_flag(flgs, TR_STR))\r
- {\r
- info[i++] = _("あなたの腕力は装備によって影響を受けている。", "Your strength is affected by your equipment.");\r
- }\r
- if (have_flag(flgs, TR_INT))\r
- {\r
- info[i++] = _("あなたの知能は装備によって影響を受けている。", "Your intelligence is affected by your equipment.");\r
- }\r
- if (have_flag(flgs, TR_WIS))\r
- {\r
- info[i++] = _("あなたの賢さは装備によって影響を受けている。", "Your wisdom is affected by your equipment.");\r
- }\r
- if (have_flag(flgs, TR_DEX))\r
- {\r
- info[i++] = _("あなたの器用さは装備によって影響を受けている。", "Your dexterity is affected by your equipment.");\r
- }\r
- if (have_flag(flgs, TR_CON))\r
- {\r
- info[i++] = _("あなたの耐久力は装備によって影響を受けている。", "Your constitution is affected by your equipment.");\r
- }\r
- if (have_flag(flgs, TR_CHR))\r
- {\r
- info[i++] = _("あなたの魅力は装備によって影響を受けている。", "Your charisma is affected by your equipment.");\r
- }\r
-\r
- if (have_flag(flgs, TR_STEALTH))\r
- {\r
- info[i++] = _("あなたの隠密行動能力は装備によって影響を受けている。", "Your stealth is affected by your equipment.");\r
- }\r
- if (have_flag(flgs, TR_SEARCH))\r
- {\r
- info[i++] = _("あなたの探索能力は装備によって影響を受けている。", "Your searching ability is affected by your equipment.");\r
- }\r
- if (have_flag(flgs, TR_INFRA))\r
- {\r
- info[i++] = _("あなたの赤外線視力は装備によって影響を受けている。", "Your infravision is affected by your equipment.");\r
- }\r
- if (have_flag(flgs, TR_TUNNEL))\r
- {\r
- info[i++] = _("あなたの採掘能力は装備によって影響を受けている。", "Your digging ability is affected by your equipment.");\r
- }\r
- if (have_flag(flgs, TR_SPEED))\r
- {\r
- info[i++] = _("あなたのスピードは装備によって影響を受けている。", "Your speed is affected by your equipment.");\r
- }\r
- if (have_flag(flgs, TR_BLOWS))\r
- {\r
- info[i++] = _("あなたの攻撃速度は装備によって影響を受けている。", "Your attack speed is affected by your equipment.");\r
- }\r
-\r
-\r
- /* Access the current weapon */\r
- o_ptr = &inventory[INVEN_RARM];\r
-\r
- /* Analyze the weapon */\r
- if (o_ptr->k_idx)\r
- {\r
- /* Indicate Blessing */\r
- if (have_flag(flgs, TR_BLESSED))\r
- {\r
- info[i++] = _("あなたの武器は神の祝福を受けている。", "Your weapon has been blessed by the gods.");\r
- }\r
-\r
- if (have_flag(flgs, TR_CHAOTIC))\r
- {\r
- info[i++] = _("あなたの武器はログルスの徴の属性をもつ。", "Your weapon is branded with the Sign of Logrus.");\r
- }\r
-\r
- if (have_flag(flgs, TR_IMPACT))\r
- {\r
- info[i++] = _("あなたの武器は打撃で地震を発生することができる。", "The impact of your weapon can cause earthquakes.");\r
- }\r
-\r
- if (have_flag(flgs, TR_VORPAL))\r
- {\r
- info[i++] = _("あなたの武器は非常に鋭い。", "Your weapon is very sharp.");\r
- }\r
-\r
- if (have_flag(flgs, TR_VAMPIRIC))\r
- {\r
- info[i++] = _("あなたの武器は敵から生命力を吸収する。", "Your weapon drains life from your foes.");\r
- }\r
-\r
- /* Special "Attack Bonuses" */\r
- if (have_flag(flgs, TR_BRAND_ACID))\r
- {\r
- info[i++] = _("あなたの武器は敵を溶かす。", "Your weapon melts your foes.");\r
- }\r
- if (have_flag(flgs, TR_BRAND_ELEC))\r
- {\r
- info[i++] = _("あなたの武器は敵を感電させる。", "Your weapon shocks your foes.");\r
- }\r
- if (have_flag(flgs, TR_BRAND_FIRE))\r
- {\r
- info[i++] = _("あなたの武器は敵を燃やす。", "Your weapon burns your foes.");\r
- }\r
- if (have_flag(flgs, TR_BRAND_COLD))\r
- {\r
- info[i++] = _("あなたの武器は敵を凍らせる。", "Your weapon freezes your foes.");\r
- }\r
- if (have_flag(flgs, TR_BRAND_POIS))\r
- {\r
- info[i++] = _("あなたの武器は敵を毒で侵す。", "Your weapon poisons your foes.");\r
- }\r
-\r
- /* Special "slay" flags */\r
- if (have_flag(flgs, TR_KILL_ANIMAL))\r
- {\r
- info[i++] = _("あなたの武器は動物の天敵である。", "Your weapon is a great bane of animals.");\r
- }\r
- else if (have_flag(flgs, TR_SLAY_ANIMAL))\r
- {\r
- info[i++] = _("あなたの武器は動物に対して強い力を発揮する。", "Your weapon strikes at animals with extra force.");\r
- }\r
- if (have_flag(flgs, TR_KILL_EVIL))\r
- {\r
- info[i++] = _("あなたの武器は邪悪なる存在の天敵である。", "Your weapon is a great bane of evil.");\r
- }\r
- else if (have_flag(flgs, TR_SLAY_EVIL))\r
- {\r
- info[i++] = _("あなたの武器は邪悪なる存在に対して強い力を発揮する。", "Your weapon strikes at evil with extra force.");\r
- }\r
- if (have_flag(flgs, TR_KILL_HUMAN))\r
- {\r
- info[i++] = _("あなたの武器は人間の天敵である。", "Your weapon is a great bane of humans.");\r
- }\r
- else if (have_flag(flgs, TR_SLAY_HUMAN))\r
- {\r
- info[i++] = _("あなたの武器は人間に対して特に強い力を発揮する。", "Your weapon is especially deadly against humans.");\r
- }\r
- if (have_flag(flgs, TR_KILL_UNDEAD))\r
- {\r
- info[i++] = _("あなたの武器はアンデッドの天敵である。", "Your weapon is a great bane of undead.");\r
- }\r
- else if (have_flag(flgs, TR_SLAY_UNDEAD))\r
- {\r
- info[i++] = _("あなたの武器はアンデッドに対して神聖なる力を発揮する。", "Your weapon strikes at undead with holy wrath.");\r
- }\r
- if (have_flag(flgs, TR_KILL_DEMON))\r
- {\r
- info[i++] = _("あなたの武器はデーモンの天敵である。", "Your weapon is a great bane of demons.");\r
- }\r
- else if (have_flag(flgs, TR_SLAY_DEMON))\r
- {\r
- info[i++] = _("あなたの武器はデーモンに対して神聖なる力を発揮する。", "Your weapon strikes at demons with holy wrath.");\r
- }\r
- if (have_flag(flgs, TR_KILL_ORC))\r
- {\r
- info[i++] = _("あなたの武器はオークの天敵である。", "Your weapon is a great bane of orcs.");\r
- }\r
- else if (have_flag(flgs, TR_SLAY_ORC))\r
- {\r
- info[i++] = _("あなたの武器はオークに対して特に強い力を発揮する。", "Your weapon is especially deadly against orcs.");\r
- }\r
- if (have_flag(flgs, TR_KILL_TROLL))\r
- {\r
- info[i++] = _("あなたの武器はトロルの天敵である。", "Your weapon is a great bane of trolls.");\r
- }\r
- else if (have_flag(flgs, TR_SLAY_TROLL))\r
- {\r
- info[i++] = _("あなたの武器はトロルに対して特に強い力を発揮する。", "Your weapon is especially deadly against trolls.");\r
- }\r
- if (have_flag(flgs, TR_KILL_GIANT))\r
- {\r
- info[i++] = _("あなたの武器はジャイアントの天敵である。", "Your weapon is a great bane of giants.");\r
- }\r
- else if (have_flag(flgs, TR_SLAY_GIANT))\r
- {\r
- info[i++] = _("あなたの武器はジャイアントに対して特に強い力を発揮する。", "Your weapon is especially deadly against giants.");\r
- }\r
- /* Special "kill" flags */\r
- if (have_flag(flgs, TR_KILL_DRAGON))\r
- {\r
- info[i++] = _("あなたの武器はドラゴンの天敵である。", "Your weapon is a great bane of dragons.");\r
- }\r
- else if (have_flag(flgs, TR_SLAY_DRAGON))\r
- {\r
- info[i++] = _("あなたの武器はドラゴンに対して特に強い力を発揮する。", "Your weapon is especially deadly against dragons.");\r
- }\r
-\r
- if (have_flag(flgs, TR_FORCE_WEAPON))\r
- {\r
- info[i++] = _("あなたの武器はMPを使って攻撃する。", "Your weapon causes greate damages using your MP.");\r
- }\r
- if (have_flag(flgs, TR_THROW))\r
- {\r
- info[i++] = _("あなたの武器は投げやすい。", "Your weapon can be thrown well.");\r
- }\r
- }\r
-\r
- screen_save();\r
-\r
- /* Erase the screen */\r
- for (k = 1; k < 24; k++) prt("", k, 13);\r
-\r
- /* Label the information */\r
- prt(_(" あなたの状態:", " Your Attributes:"), 1, 15);\r
-\r
- /* We will print on top of the map (column 13) */\r
- for (k = 2, j = 0; j < i; j++)\r
- {\r
- /* Show the info */\r
- prt(info[j], k++, 15);\r
-\r
- /* Every 20 entries (lines 2 to 21), start over */\r
- if ((k == 22) && (j+1 < i))\r
- {\r
- prt(_("-- 続く --", "-- more --"), k, 15);\r
- inkey();\r
- for (; k > 2; k--) prt("", k, 15);\r
- }\r
- }\r
-\r
- /* Pause */\r
- prt(_("[何かキーを押すとゲームに戻ります]", "[Press any key to continue]"), k, 13);\r
- inkey();\r
- screen_load();\r
-}\r
-\r
-/*!\r
- * @brief 魔法効果時間のターン数に基づいて表現IDを返す。\r
- * @param dur 効果ターン数\r
- * @return 効果時間の表現ID\r
- */\r
-static int report_magics_aux(int dur)\r
-{\r
- if (dur <= 5)\r
- {\r
- return 0;\r
- }\r
- else if (dur <= 10)\r
- {\r
- return 1;\r
- }\r
- else if (dur <= 20)\r
- {\r
- return 2;\r
- }\r
- else if (dur <= 50)\r
- {\r
- return 3;\r
- }\r
- else if (dur <= 100)\r
- {\r
- return 4;\r
- }\r
- else if (dur <= 200)\r
- {\r
- return 5;\r
- }\r
- else\r
- {\r
- return 6;\r
- }\r
-}\r
-\r
-static concptr report_magic_durations[] =\r
-{\r
-#ifdef JP\r
- "ごく短い間",\r
- "少しの間",\r
- "しばらくの間",\r
- "多少長い間",\r
- "長い間",\r
- "非常に長い間",\r
- "信じ難いほど長い間",\r
- "モンスターを攻撃するまで"\r
-#else\r
- "for a short time",\r
- "for a little while",\r
- "for a while",\r
- "for a long while",\r
- "for a long time",\r
- "for a very long time",\r
- "for an incredibly long time",\r
- "until you hit a monster"\r
-#endif\r
-\r
-};\r
-\r
-/*!\r
- * @brief 現在の一時的効果一覧を返す / Report all currently active magical effects.\r
- * @return なし\r
- */\r
-void report_magics(void)\r
-{\r
- int i = 0, j, k;\r
- char Dummy[80];\r
- concptr info[128];\r
- int info2[128];\r
-\r
-\r
- if (p_ptr->blind)\r
- {\r
- info2[i] = report_magics_aux(p_ptr->blind);\r
- info[i++] = _("あなたは目が見えない", "You cannot see");\r
- }\r
- if (p_ptr->confused)\r
- {\r
- info2[i] = report_magics_aux(p_ptr->confused);\r
- info[i++] = _("あなたは混乱している", "You are confused");\r
- }\r
- if (p_ptr->afraid)\r
- {\r
- info2[i] = report_magics_aux(p_ptr->afraid);\r
- info[i++] = _("あなたは恐怖に侵されている", "You are terrified");\r
- }\r
- if (p_ptr->poisoned)\r
- {\r
- info2[i] = report_magics_aux(p_ptr->poisoned);\r
- info[i++] = _("あなたは毒に侵されている", "You are poisoned");\r
- }\r
- if (p_ptr->image)\r
- {\r
- info2[i] = report_magics_aux(p_ptr->image);\r
- info[i++] = _("あなたは幻覚を見ている", "You are hallucinating");\r
- }\r
- if (p_ptr->blessed)\r
- {\r
- info2[i] = report_magics_aux(p_ptr->blessed);\r
- info[i++] = _("あなたは高潔さを感じている", "You feel rightous");\r
- }\r
- if (p_ptr->hero)\r
- {\r
- info2[i] = report_magics_aux(p_ptr->hero);\r
- info[i++] = _("あなたはヒーロー気分だ", "You feel heroic");\r
- }\r
- if (p_ptr->shero)\r
- {\r
- info2[i] = report_magics_aux(p_ptr->shero);\r
- info[i++] = _("あなたは戦闘狂だ", "You are in a battle rage");\r
- }\r
- if (p_ptr->protevil)\r
- {\r
- info2[i] = report_magics_aux(p_ptr->protevil);\r
- info[i++] = _("あなたは邪悪なる存在から守られている", "You are protected from evil");\r
- }\r
- if (p_ptr->shield)\r
- {\r
- info2[i] = report_magics_aux(p_ptr->shield);\r
- info[i++] = _("あなたは神秘のシールドで守られている", "You are protected by a mystic shield");\r
- }\r
- if (p_ptr->invuln)\r
- {\r
- info2[i] = report_magics_aux(p_ptr->invuln);\r
- info[i++] = _("あなたは無敵だ", "You are invulnerable");\r
- }\r
- if (p_ptr->wraith_form)\r
- {\r
- info2[i] = report_magics_aux(p_ptr->wraith_form);\r
- info[i++] = _("あなたは幽体化している", "You are incorporeal");\r
- }\r
- if (p_ptr->special_attack & ATTACK_CONFUSE)\r
- {\r
- info2[i] = 7;\r
- info[i++] = _("あなたの手は赤く輝いている", "Your hands are glowing dull red.");\r
- }\r
- if (p_ptr->word_recall)\r
- {\r
- info2[i] = report_magics_aux(p_ptr->word_recall);\r
- info[i++] = _("この後帰還の詔が発動する", "You are waiting to be recalled");\r
- }\r
- if (p_ptr->alter_reality)\r
- {\r
- info2[i] = report_magics_aux(p_ptr->alter_reality);\r
- info[i++] = _("この後現実変容が発動する", "You waiting to be altered");\r
- }\r
- if (p_ptr->oppose_acid)\r
- {\r
- info2[i] = report_magics_aux(p_ptr->oppose_acid);\r
- info[i++] = _("あなたは酸への耐性を持っている", "You are resistant to acid");\r
- }\r
- if (p_ptr->oppose_elec)\r
- {\r
- info2[i] = report_magics_aux(p_ptr->oppose_elec);\r
- info[i++] = _("あなたは電撃への耐性を持っている", "You are resistant to lightning");\r
- }\r
- if (p_ptr->oppose_fire)\r
- {\r
- info2[i] = report_magics_aux(p_ptr->oppose_fire);\r
- info[i++] = _("あなたは火への耐性を持っている", "You are resistant to fire");\r
- }\r
- if (p_ptr->oppose_cold)\r
- {\r
- info2[i] = report_magics_aux(p_ptr->oppose_cold);\r
- info[i++] = _("あなたは冷気への耐性を持っている", "You are resistant to cold");\r
- }\r
- if (p_ptr->oppose_pois)\r
- {\r
- info2[i] = report_magics_aux(p_ptr->oppose_pois);\r
- info[i++] = _("あなたは毒への耐性を持っている", "You are resistant to poison");\r
- }\r
- screen_save();\r
-\r
- /* Erase the screen */\r
- for (k = 1; k < 24; k++) prt("", k, 13);\r
-\r
- /* Label the information */\r
- prt(_(" 現在かかっている魔法 :", " Your Current Magic:"), 1, 15);\r
-\r
-\r
- /* We will print on top of the map (column 13) */\r
- for (k = 2, j = 0; j < i; j++)\r
- {\r
- /* Show the info */\r
- sprintf(Dummy, _("%-28s : 期間 - %s ", "%s %s."), info[j],\r
- report_magic_durations[info2[j]]);\r
- prt(Dummy, k++, 15);\r
-\r
- /* Every 20 entries (lines 2 to 21), start over */\r
- if ((k == 22) && (j + 1 < i))\r
- {\r
- prt(_("-- 続く --", "-- more --"), k, 15);\r
- inkey();\r
- for (; k > 2; k--) prt("", k, 15);\r
- }\r
- }\r
-\r
- /* Pause */\r
- prt(_("[何かキーを押すとゲームに戻ります]", "[Press any key to continue]"), k, 13);\r
- inkey();\r
- screen_load();\r
-}\r
+/*!
+ * @file selfinfo.c
+ * @brief 自己分析処理/ Self knowledge
+ * @date 2018/09/07
+ * @author
+ * <pre>
+ * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
+ * This software may be copied and distributed for educational, research,
+ * and not for profit purposes provided that this copyright and statement
+ * are included in all such copies. Other copyrights may also apply.
+ * </pre>
+ * 2018 Deskull
+ * @details
+ * spell2s.cから分離
+ */
+
+#include "angband.h"
+#include "player-status.h"
+#include "avatar.h"
+
+/*!
+ * @brief 自己分析処理(Nethackからのアイデア) / self-knowledge... idea from nethack.
+ * @return なし
+ * @details
+ * <pre>
+ * Useful for determining powers and
+ * resistences of items. It saves the screen, clears it, then starts listing
+ * attributes, a screenful at a time. (There are a LOT of attributes to
+ * list. It will probably take 2 or 3 screens for a powerful character whose
+ * using several artifacts...) -CFT
+ *
+ * It is now a lot more efficient. -BEN-
+ *
+ * See also "identify_fully()".
+ *
+ * Use the "show_file()" method, perhaps.
+ * </pre>
+ */
+void self_knowledge(void)
+{
+ int i = 0, j, k;
+
+ int v_nr = 0;
+ char v_string [8] [128];
+ char s_string [6] [128];
+
+ BIT_FLAGS flgs[TR_FLAG_SIZE];
+
+ object_type *o_ptr;
+
+ char Dummy[80];
+ char buf[2][80];
+
+ concptr info[220];
+
+ PLAYER_LEVEL plev = p_ptr->lev;
+
+ int percent;
+
+ for (j = 0; j < TR_FLAG_SIZE; j++)
+ flgs[j] = 0L;
+
+ p_ptr->knowledge |= (KNOW_STAT | KNOW_HPRATE);
+
+ strcpy(Dummy, "");
+
+ percent = (int)(((long)p_ptr->player_hp[PY_MAX_LEVEL - 1] * 200L) /
+ (2 * p_ptr->hitdie +
+ ((PY_MAX_LEVEL - 1+3) * (p_ptr->hitdie + 1))));
+
+ sprintf(Dummy, _("現在の体力ランク : %d/100", "Your current Life Rating is %d/100."), percent);
+ strcpy(buf[0], Dummy);
+ info[i++] = buf[0];
+ info[i++] = "";
+
+ chg_virtue(V_KNOWLEDGE, 1);
+ chg_virtue(V_ENLIGHTEN, 1);
+
+ /* Acquire item flags from equipment */
+ for (k = INVEN_RARM; k < INVEN_TOTAL; k++)
+ {
+ u32b tflgs[TR_FLAG_SIZE];
+
+ o_ptr = &inventory[k];
+
+ /* Skip non-objects */
+ if (!o_ptr->k_idx) continue;
+ object_flags(o_ptr, tflgs);
+
+ /* Extract flags */
+ for (j = 0; j < TR_FLAG_SIZE; j++)
+ flgs[j] |= tflgs[j];
+ }
+
+ info[i++] = _("能力の最大値", "Limits of maximum stats");
+
+ for (v_nr = 0; v_nr < A_MAX; v_nr++)
+ {
+ char stat_desc[80];
+
+ sprintf(stat_desc, "%s 18/%d", stat_names[v_nr], p_ptr->stat_max_max[v_nr]-18);
+
+ strcpy(s_string[v_nr], stat_desc);
+
+ info[i++] = s_string[v_nr];
+ }
+ info[i++] = "";
+
+ sprintf(Dummy, _("現在の属性 : %s(%ld)", "Your alighnment : %s(%ld)"), your_alignment(), (long int)p_ptr->align);
+ strcpy(buf[1], Dummy);
+ info[i++] = buf[1];
+ for (v_nr = 0; v_nr < 8; v_nr++)
+ {
+ GAME_TEXT vir_name [20];
+ char vir_desc[80];
+ int tester = p_ptr->virtues[v_nr];
+
+ strcpy(vir_name, virtue[(p_ptr->vir_types[v_nr])-1]);
+
+ sprintf(vir_desc, _("おっと。%sの情報なし。", "Oops. No info about %s."), vir_name);
+ if (tester < -100)
+ sprintf(vir_desc, _("[%s]の対極 (%d)", "You are the polar opposite of %s (%d)."),
+ vir_name, tester);
+ else if (tester < -80)
+ sprintf(vir_desc, _("[%s]の大敵 (%d)", "You are an arch-enemy of %s (%d)."),
+ vir_name, tester);
+ else if (tester < -60)
+ sprintf(vir_desc, _("[%s]の強敵 (%d)", "You are a bitter enemy of %s (%d)."),
+ vir_name, tester);
+ else if (tester < -40)
+ sprintf(vir_desc, _("[%s]の敵 (%d)", "You are an enemy of %s (%d)."),
+ vir_name, tester);
+ else if (tester < -20)
+ sprintf(vir_desc, _("[%s]の罪者 (%d)", "You have sinned against %s (%d)."),
+ vir_name, tester);
+ else if (tester < 0)
+ sprintf(vir_desc, _("[%s]の迷道者 (%d)", "You have strayed from the path of %s (%d)."),
+ vir_name, tester);
+ else if (tester == 0)
+ sprintf(vir_desc, _("[%s]の中立者 (%d)", "You are neutral to %s (%d)."),
+ vir_name, tester);
+ else if (tester < 20)
+ sprintf(vir_desc, _("[%s]の小徳者 (%d)", "You are somewhat virtuous in %s (%d)."),
+ vir_name, tester);
+ else if (tester < 40)
+ sprintf(vir_desc, _("[%s]の中徳者 (%d)", "You are virtuous in %s (%d)."),
+ vir_name, tester);
+ else if (tester < 60)
+ sprintf(vir_desc, _("[%s]の高徳者 (%d)", "You are very virtuous in %s (%d)."),
+ vir_name, tester);
+ else if (tester < 80)
+ sprintf(vir_desc, _("[%s]の覇者 (%d)", "You are a champion of %s (%d)."),
+ vir_name, tester);
+ else if (tester < 100)
+ sprintf(vir_desc, _("[%s]の偉大な覇者 (%d)", "You are a great champion of %s (%d)."),
+ vir_name, tester);
+ else
+ sprintf(vir_desc, _("[%s]の具現者 (%d)", "You are the living embodiment of %s (%d)."),
+ vir_name, tester);
+
+ strcpy(v_string[v_nr], vir_desc);
+
+ info[i++] = v_string[v_nr];
+ }
+ info[i++] = "";
+
+ /* Racial powers... */
+ if (p_ptr->mimic_form)
+ {
+ switch (p_ptr->mimic_form)
+ {
+ case MIMIC_DEMON:
+ case MIMIC_DEMON_LORD:
+ sprintf(Dummy, _("あなたは %d ダメージの地獄か火炎のブレスを吐くことができる。(%d MP)",
+ "You can nether breathe, dam. %d (cost %d)."), 3 * plev, 10+plev/3);
+
+ info[i++] = Dummy;
+ break;
+ case MIMIC_VAMPIRE:
+ if (plev > 1)
+ {
+ sprintf(Dummy, _("あなたは敵から %d-%d HP の生命力を吸収できる。(%d MP)",
+ "You can steal life from a foe, dam. %d-%d (cost %d)."),
+ plev + MAX(1, plev / 10), plev + plev * MAX(1, plev / 10), 1 + (plev / 3));
+ info[i++] = Dummy;
+ }
+ break;
+ }
+ }
+ else
+ {
+ switch (p_ptr->prace)
+ {
+ case RACE_NIBELUNG:
+ case RACE_DWARF:
+ if (plev > 4)
+ info[i++] = _("あなたは罠とドアと階段を感知できる。(5 MP)", "You can find traps, doors and stairs (cost 5).");
+ break;
+ case RACE_HOBBIT:
+ if (plev > 14)
+ {
+ info[i++] = _("あなたは食料を生成できる。(10 MP)", "You can produce food (cost 10).");
+ }
+ break;
+ case RACE_GNOME:
+ if (plev > 4)
+ {
+ sprintf(Dummy, _("あなたは範囲 %d 以内にテレポートできる。(%d MP)", "You can teleport, range %d (cost %d)."),
+ (1 + plev), (5 + (plev / 5)));
+ info[i++] = Dummy;
+ }
+ break;
+ case RACE_HALF_ORC:
+ if (plev > 2)
+ info[i++] = _("あなたは恐怖を除去できる。(5 MP)", "You can remove fear (cost 5).");
+ break;
+ case RACE_HALF_TROLL:
+ if (plev > 9)
+ info[i++] = _("あなたは狂暴化することができる。(12 MP) ", "You enter berserk fury (cost 12).");
+ break;
+ case RACE_AMBERITE:
+ if (plev > 29)
+ info[i++] = _("あなたはシャドウシフトすることができる。(50 MP)", "You can Shift Shadows (cost 50).");
+
+ if (plev > 39)
+ info[i++] = _("あなたは「パターン」を心に描いて歩くことができる。(75 MP)", "You can mentally Walk the Pattern (cost 75).");
+
+ break;
+ case RACE_BARBARIAN:
+ if (plev > 7)
+ info[i++] = _("あなたは狂暴化することができる。(10 MP) ", "You can enter berserk fury (cost 10).");
+
+ break;
+ case RACE_HALF_OGRE:
+ if (plev > 24)
+ info[i++] = _("あなたは爆発のルーンを仕掛けることができる。(35 MP)", "You can set an Explosive Rune (cost 35).");
+
+ break;
+ case RACE_HALF_GIANT:
+ if (plev > 19)
+ info[i++] = _("あなたは石の壁を壊すことができる。(10 MP)", "You can break stone walls (cost 10).");
+ break;
+ case RACE_HALF_TITAN:
+ if (plev > 34)
+ info[i++] = _("あなたはモンスターをスキャンすることができる。(20 MP)", "You can probe monsters (cost 20).");
+ break;
+ case RACE_CYCLOPS:
+ if (plev > 19)
+ {
+ sprintf(Dummy, _("あなたは %d ダメージの岩石を投げることができる。(15 MP)",
+ "You can throw a boulder, dam. %d (cost 15)."), 3 * plev);
+ info[i++] = Dummy;
+ }
+ break;
+ case RACE_YEEK:
+ if (plev > 14)
+ info[i++] = _("あなたは恐怖を呼び起こす叫び声を発することができる。(15 MP)", "You can make a terrifying scream (cost 15).");
+ break;
+ case RACE_KLACKON:
+ if (plev > 8)
+ {
+ sprintf(Dummy, _("あなたは %d ダメージの酸を吹きかけることができる。(9 MP)", "You can spit acid, dam. %d (cost 9)."), plev);
+ info[i++] = Dummy;
+ }
+ break;
+ case RACE_KOBOLD:
+ if (plev > 11)
+ {
+ sprintf(Dummy,
+ _("あなたは %d ダメージの毒矢を投げることができる。(8 MP)", "You can throw a dart of poison, dam. %d (cost 8)."), plev);
+ info[i++] = Dummy;
+ }
+ break;
+ case RACE_DARK_ELF:
+ if (plev > 1)
+ {
+ sprintf(Dummy, _("あなたは %d ダメージのマジック・ミサイルの呪文を使える。(2 MP)", "You can cast a Magic Missile, dam %d (cost 2)."),
+ (3 + ((plev-1) / 5)));
+ info[i++] = Dummy;
+ }
+ break;
+ case RACE_DRACONIAN:
+ sprintf(Dummy, _("あなたは %d ダメージのブレスを吐くことができる。(%d MP)", "You can breathe, dam. %d (cost %d)."), 2 * plev, plev);
+ info[i++] = Dummy;
+ break;
+ case RACE_MIND_FLAYER:
+ if (plev > 14)
+ sprintf(Dummy, _("あなたは %d ダメージの精神攻撃をすることができる。(12 MP)", "You can mind blast your enemies, dam %d (cost 12)."), plev);
+ info[i++] = Dummy;
+ break;
+ case RACE_IMP:
+ if (plev > 29)
+ {
+ sprintf(Dummy, _("あなたは %d ダメージのファイア・ボールの呪文を使える。(15 MP)", "You can cast a Fire Ball, dam. %d (cost 15)."), plev);
+ info[i++] = Dummy;
+ }
+ else if (plev > 8)
+ {
+ sprintf(Dummy, _("あなたは %d ダメージのファイア・ボルトの呪文を使える。(15 MP)", "You can cast a Fire Bolt, dam. %d (cost 15)."), plev);
+ info[i++] = Dummy;
+ }
+ break;
+ case RACE_GOLEM:
+ if (plev > 19)
+ info[i++] = _("あなたは d20+30 ターンの間肌を石に変化させられる。(15 MP)", "You can turn your skin to stone, dur d20+30 (cost 15).");
+ break;
+ case RACE_ZOMBIE:
+ case RACE_SKELETON:
+ if (plev > 29)
+ info[i++] = _("あなたは失った経験値を回復することができる。(30 MP)", "You can restore lost experience (cost 30).");
+ break;
+ case RACE_VAMPIRE:
+ if (plev > 1)
+ {
+ sprintf(Dummy, _("あなたは敵から %d-%d HP の生命力を吸収できる。(%d MP)", "You can steal life from a foe, dam. %d-%d (cost %d)."),
+ plev + MAX(1, plev / 10), plev + plev * MAX(1, plev / 10), 1 + (plev / 3));
+ info[i++] = Dummy;
+ }
+ break;
+ case RACE_SPECTRE:
+ if (plev > 3)
+ {
+ info[i++] = _("あなたは泣き叫んで敵を恐怖させることができる。(3 MP)", "You can wail to terrify your enemies (cost 3).");
+ }
+ break;
+ case RACE_SPRITE:
+ if (plev > 11)
+ {
+ info[i++] = _("あなたは敵を眠らせる魔法の粉を投げることができる。(12 MP)", "You can throw magical dust which induces sleep (cost 12).");
+ }
+ break;
+ case RACE_DEMON:
+ sprintf(Dummy, _("あなたは %d ダメージの地獄か火炎のブレスを吐くことができる。(%d MP)",
+ "You can breathe nether, dam. %d (cost %d)."), 3 * plev, 10+plev/3);
+
+ info[i++] = Dummy;
+ break;
+ case RACE_KUTAR:
+ if (plev > 19)
+ info[i++] = _("あなたは d20+30 ターンの間横に伸びることができる。(15 MP)", "You can expand horizontally, dur d20+30 (cost 15).");
+ break;
+ case RACE_ANDROID:
+ if (plev < 10)
+ sprintf(Dummy, _("あなたは %d ダメージのレイガンを撃つことができる。(7 MP)", "You can fire a ray gun with damage %d (cost 7)."),
+ (plev + 1) / 2);
+ else if (plev < 25)
+ sprintf(Dummy, _("あなたは %d ダメージのブラスターを撃つことができる。(13 MP)", "You can fire a blaster with damage %d (cost 13)."), plev);
+ else if (plev < 35)
+ sprintf(Dummy, _("あなたは %d ダメージのバズーカを撃つことができる。(26 MP)", "You can fire a bazooka with damage %d (cost 26)."), plev * 2);
+ else if (plev < 45)
+ sprintf(Dummy, _("あなたは %d ダメージのビームキャノンを撃つことができる。(40 MP)",
+ "You can fire a beam cannon with damage %d (cost 40)."), plev * 2);
+ else
+ sprintf(Dummy, _("あなたは %d ダメージのロケットを撃つことができる。(60 MP)",
+ "You can fire a rocket with damage %d (cost 60)."), plev * 5);
+
+ info[i++] = Dummy;
+ break;
+ default:
+ break;
+ }
+ }
+
+ switch(p_ptr->pclass)
+ {
+ case CLASS_WARRIOR:
+ if (plev > 39)
+ {
+ info[i++] = _("あなたはランダムな方向に対して数回攻撃することができる。(75 MP)",
+ "You can attack some random directions at a time (cost 75).");
+ }
+ break;
+ case CLASS_HIGH_MAGE:
+ if (p_ptr->realm1 == REALM_HEX) break;
+ case CLASS_MAGE:
+ case CLASS_SORCERER:
+ if (plev > 24)
+ {
+ info[i++] = _("あなたはアイテムの魔力を吸収することができる。(1 MP)",
+ "You can absorb charges from an item (cost 1).");
+ }
+ break;
+ case CLASS_PRIEST:
+ if (is_good_realm(p_ptr->realm1))
+ {
+ if (plev > 34)
+ {
+ info[i++] = _("あなたは武器を祝福することができる。(70 MP)", "You can bless a weapon (cost 70).");
+ }
+ }
+ else
+ {
+ if (plev > 41)
+ {
+ info[i++] = _("あなたは周りのすべてのモンスターを攻撃することができる。(40 MP)", "You can damages all monsters in sight (cost 40).");
+ }
+ }
+ break;
+ case CLASS_ROGUE:
+ if (plev > 7)
+ {
+ info[i++] = _("あなたは攻撃して即座に逃げることができる。(12 MP)", "You can hit a monster and teleport at a time (cost 12).");
+ }
+ break;
+ case CLASS_RANGER:
+ if (plev > 14)
+ {
+ info[i++] = _("あなたは怪物を調査することができる。(20 MP)", "You can prove monsters (cost 20).");
+ }
+ break;
+ case CLASS_PALADIN:
+ if (is_good_realm(p_ptr->realm1))
+ {
+ if (plev > 29)
+ {
+ info[i++] = _("あなたは聖なる槍を放つことができる。(30 MP)", "You can fires a holy spear (cost 30).");
+ }
+ }
+ else
+ {
+ if (plev > 29)
+ {
+ info[i++] = _("あなたは生命力を減少させる槍を放つことができる。(30 MP)", "You can fires a spear which drains vitality (cost 30).");
+ }
+ }
+ break;
+ case CLASS_WARRIOR_MAGE:
+ if (plev > 24)
+ {
+ info[i++] = _("あなたはHPをMPに変換することができる。(0 MP)", "You can convert HP to SP (cost 0).");
+ info[i++] = _("あなたはMPをHPに変換することができる。(0 MP)", "You can convert SP to HP (cost 0).");
+ }
+ break;
+ case CLASS_CHAOS_WARRIOR:
+ if (plev > 39)
+ {
+ info[i++] = _("あなたは周囲に怪物を惑わす光を発生させることができる。(50 MP)",
+ "You can radiate light which confuses nearby monsters (cost 50).");
+ }
+ break;
+ case CLASS_MONK:
+ if (plev > 24)
+ {
+ info[i++] = _("あなたは構えることができる。(0 MP)", "You can assume a posture of special form (cost 0).");
+ }
+ if (plev > 29)
+ {
+ info[i++] = _("あなたは通常の2倍の攻撃を行うことができる。(30 MP)", "You can perform double attacks in a time (cost 30).");
+ }
+ break;
+ case CLASS_MINDCRAFTER:
+ case CLASS_FORCETRAINER:
+ if (plev > 14)
+ {
+ info[i++] = _("あなたは精神を集中してMPを回復させることができる。(0 MP)", "You can concentrate to regenerate your mana (cost 0).");
+ }
+ break;
+ case CLASS_TOURIST:
+ info[i++] = _("あなたは写真を撮影することができる。(0 MP)", "You can take a photograph (cost 0).");
+ if (plev > 24)
+ {
+ info[i++] = _("あなたはアイテムを完全に鑑定することができる。(20 MP)", "You can *identify* items (cost 20).");
+ }
+ break;
+ case CLASS_IMITATOR:
+ if (plev > 29)
+ {
+ info[i++] = _("あなたは怪物の特殊攻撃をダメージ2倍でまねることができる。(100 MP)",
+ "You can imitate monster's special attacks with double damage (cost 100).");
+ }
+ break;
+ case CLASS_BEASTMASTER:
+ info[i++] = _("あなたは1体の生命のあるモンスターを支配することができる。(レベル/4 MP)", "You can dominate a monster (cost level/4).");
+ if (plev > 29)
+ {
+ info[i++] = _("あなたは視界内の生命のあるモンスターを支配することができる。((レベル+20)/2 MP)",
+ "You can dominate living monsters in sight (cost (level+20)/4).");
+ }
+ break;
+ case CLASS_MAGIC_EATER:
+ info[i++] = _("あなたは杖/魔法棒/ロッドの魔力を自分のものにすることができる。", "You can absorb a staff, wand or rod itself.");
+ break;
+ case CLASS_RED_MAGE:
+ if (plev > 47)
+ {
+ info[i++] = _("あなたは1ターンに2回魔法を唱えることができる。(20 MP)", "You can cast two spells in one time (cost 20).");
+ }
+ break;
+ case CLASS_SAMURAI:
+ {
+ info[i++] = _("あなたは精神を集中して気合いを溜めることができる。", "You can concentrate to regenerate your mana.");
+ }
+ if (plev > 24)
+ {
+ info[i++] = _("あなたは特殊な型で構えることができる。", "You can assume a posture of special form.");
+ }
+ break;
+ case CLASS_BLUE_MAGE:
+ info[i++] = _("あなたは相手に使われた魔法を学ぶことができる。", "You can study spells which your enemy casts on you.");
+ break;
+ case CLASS_CAVALRY:
+ if (plev > 9)
+ {
+ info[i++] = _("あなたはモンスターに乗って無理矢理ペットにすることができる。", "You can ride on a hostile monster forcibly to turn it into pet.");
+ }
+ break;
+ case CLASS_BERSERKER:
+ if (plev > 9)
+ {
+ info[i++] = _("あなたは街とダンジョンの間を行き来することができる。", "You can travel between town and the depths.");
+ }
+ break;
+ case CLASS_MIRROR_MASTER:
+ info[i++] = _("あなたは鏡を作り出すことができる。(2 MP)", "You can create a Mirror (cost 2).");
+ info[i++] = _("あなたは鏡を割ることができる。(0 MP)", "You can break distant Mirrors (cost 0).");
+ break;
+ case CLASS_NINJA:
+ if (plev > 19)
+ {
+ info[i++] = _("あなたは素早く移動することができる。", "You can walk extremery fast.");
+ }
+ break;
+ }
+
+ if (p_ptr->muta1)
+ {
+ if (p_ptr->muta1 & MUT1_SPIT_ACID)
+ {
+ info[i++] = _("あなたは酸を吹きかけることができる。(ダメージ レベルX1)", "You can spit acid (dam lvl).");
+ }
+ if (p_ptr->muta1 & MUT1_BR_FIRE)
+ {
+ info[i++] = _("あなたは炎のブレスを吐くことができる。(ダメージ レベルX2)", "You can breathe fire (dam lvl * 2).");
+ }
+ if (p_ptr->muta1 & MUT1_HYPN_GAZE)
+ {
+ info[i++] = _("あなたの睨みは催眠効果をもつ。", "Your gaze is hypnotic.");
+ }
+ if (p_ptr->muta1 & MUT1_TELEKINES)
+ {
+ info[i++] = _("あなたは念動力をもっている。", "You are telekinetic.");
+ }
+ if (p_ptr->muta1 & MUT1_VTELEPORT)
+ {
+ info[i++] = _("あなたは自分の意思でテレポートできる。", "You can teleport at will.");
+ }
+ if (p_ptr->muta1 & MUT1_MIND_BLST)
+ {
+ info[i++] = _("あなたは精神攻撃を行える。(ダメージ 3~12d3)", "You can Mind Blast your enemies (3 to 12d3 dam).");
+ }
+ if (p_ptr->muta1 & MUT1_RADIATION)
+ {
+ info[i++] = _("あなたは自分の意思で強い放射線を発生することができる。(ダメージ レベルX2)", "You can emit hard radiation at will (dam lvl * 2).");
+ }
+ if (p_ptr->muta1 & MUT1_VAMPIRISM)
+ {
+ info[i++] = _("あなたは吸血鬼のように敵から生命力を吸収することができる。(ダメージ レベルX2)",
+ "You can drain life from a foe like a vampire (dam lvl * 2).");
+ }
+ if (p_ptr->muta1 & MUT1_SMELL_MET)
+ {
+ info[i++] = _("あなたは近くにある貴金属をかぎ分けることができる。", "You can smell nearby precious metal.");
+ }
+ if (p_ptr->muta1 & MUT1_SMELL_MON)
+ {
+ info[i++] = _("あなたは近くのモンスターの存在をかぎ分けることができる。", "You can smell nearby monsters.");
+ }
+ if (p_ptr->muta1 & MUT1_BLINK)
+ {
+ info[i++] = _("あなたは短い距離をテレポートできる。", "You can teleport yourself short distances.");
+ }
+ if (p_ptr->muta1 & MUT1_EAT_ROCK)
+ {
+ info[i++] = _("あなたは硬い岩を食べることができる。", "You can consume solid rock.");
+ }
+ if (p_ptr->muta1 & MUT1_SWAP_POS)
+ {
+ info[i++] = _("あなたは他の者と場所を入れ替わることができる。", "You can switch locations with another being.");
+ }
+ if (p_ptr->muta1 & MUT1_SHRIEK)
+ {
+ info[i++] = _("あなたは身の毛もよだつ叫び声を発することができる。(ダメージ レベルX2)", "You can emit a horrible shriek (dam 2 * lvl).");
+ }
+ if (p_ptr->muta1 & MUT1_ILLUMINE)
+ {
+ info[i++] = _("あなたは明るい光を放つことができる。", "You can emit bright light.");
+ }
+ if (p_ptr->muta1 & MUT1_DET_CURSE)
+ {
+ info[i++] = _("あなたは邪悪な魔法の危険を感じとることができる。", "You can feel the danger of evil magic.");
+ }
+ if (p_ptr->muta1 & MUT1_BERSERK)
+ {
+ info[i++] = _("あなたは自分の意思で狂乱戦闘状態になることができる。", "You can drive yourself into a berserk frenzy.");
+ }
+ if (p_ptr->muta1 & MUT1_POLYMORPH)
+ {
+ info[i++] = _("あなたは自分の意志で変化できる。", "You can polymorph yourself at will.");
+ }
+ if (p_ptr->muta1 & MUT1_MIDAS_TCH)
+ {
+ info[i++] = _("あなたは通常アイテムを金に変えることができる。", "You can turn ordinary items to gold.");
+ }
+ if (p_ptr->muta1 & MUT1_GROW_MOLD)
+ {
+ info[i++] = _("あなたは周囲にキノコを生やすことができる。", "You can cause mold to grow near you.");
+ }
+ if (p_ptr->muta1 & MUT1_RESIST)
+ {
+ info[i++] = _("あなたは元素の攻撃に対して身を硬くすることができる。", "You can harden yourself to the ravages of the elements.");
+ }
+ if (p_ptr->muta1 & MUT1_EARTHQUAKE)
+ {
+ info[i++] = _("あなたは周囲のダンジョンを崩壊させることができる。", "You can bring down the dungeon around your ears.");
+ }
+ if (p_ptr->muta1 & MUT1_EAT_MAGIC)
+ {
+ info[i++] = _("あなたは魔法のエネルギーを自分の物として使用できる。", "You can consume magic energy for your own use.");
+ }
+ if (p_ptr->muta1 & MUT1_WEIGH_MAG)
+ {
+ info[i++] = _("あなたは自分に影響を与える魔法の力を感じることができる。", "You can feel the strength of the magics affecting you.");
+ }
+ if (p_ptr->muta1 & MUT1_STERILITY)
+ {
+ info[i++] = _("あなたは集団的生殖不能を起こすことができる。", "You can cause mass impotence.");
+ }
+ if (p_ptr->muta1 & MUT1_PANIC_HIT)
+ {
+ info[i++] = _("あなたは攻撃した後身を守るため逃げることができる。", "You can run for your life after hitting something.");
+ }
+ if (p_ptr->muta1 & MUT1_DAZZLE)
+ {
+ info[i++] = _("あなたは混乱と盲目を引き起こす放射能を発生することができる。 ", "You can emit confusing, blinding radiation.");
+ }
+ if (p_ptr->muta1 & MUT1_LASER_EYE)
+ {
+ info[i++] = _("あなたは目からレーザー光線を発することができる。(ダメージ レベルX2)", "Your eyes can fire laser beams (dam 2 * lvl).");
+ }
+ if (p_ptr->muta1 & MUT1_RECALL)
+ {
+ info[i++] = _("あなたは街とダンジョンの間を行き来することができる。", "You can travel between town and the depths.");
+ }
+ if (p_ptr->muta1 & MUT1_BANISH)
+ {
+ info[i++] = _("あなたは邪悪なモンスターを地獄に落とすことができる。", "You can send evil creatures directly to Hell.");
+ }
+ if (p_ptr->muta1 & MUT1_COLD_TOUCH)
+ {
+ info[i++] = _("あなたは敵を触って凍らせることができる。(ダメージ レベルX3)", "You can freeze things with a touch (dam 3 * lvl).");
+ }
+ if (p_ptr->muta1 & MUT1_LAUNCHER)
+ {
+ info[i++] = _("あなたはアイテムを力強く投げることができる。", "You can hurl objects with great force.");
+ }
+ }
+
+ if (p_ptr->muta2)
+ {
+ if (p_ptr->muta2 & MUT2_BERS_RAGE)
+ {
+ info[i++] = _("あなたは狂戦士化の発作を起こす。", "You are subject to berserker fits.");
+ }
+ if (p_ptr->muta2 & MUT2_COWARDICE)
+ {
+ info[i++] = _("あなたは時々臆病になる。", "You are subject to cowardice.");
+ }
+ if (p_ptr->muta2 & MUT2_RTELEPORT)
+ {
+ info[i++] = _("あなたはランダムにテレポートする。", "You are teleporting randomly.");
+ }
+ if (p_ptr->muta2 & MUT2_ALCOHOL)
+ {
+ info[i++] = _("あなたの体はアルコールを分泌する。", "Your body produces alcohol.");
+ }
+ if (p_ptr->muta2 & MUT2_HALLU)
+ {
+ info[i++] = _("あなたは幻覚を引き起こす精神錯乱に侵されている。", "You have a hallucinatory insanity.");
+ }
+ if (p_ptr->muta2 & MUT2_FLATULENT)
+ {
+ info[i++] = _("あなたは制御できない強烈な屁をこく。", "You are subject to uncontrollable flatulence.");
+ }
+ if (p_ptr->muta2 & MUT2_PROD_MANA)
+ {
+ info[i++] = _("あなたは制御不能な魔法のエネルギーを発している。", "You are producing magical energy uncontrollably.");
+ }
+ if (p_ptr->muta2 & MUT2_ATT_DEMON)
+ {
+ info[i++] = _("あなたはデーモンを引きつける。", "You attract demons.");
+ }
+ if (p_ptr->muta2 & MUT2_SCOR_TAIL)
+ {
+ info[i++] = _("あなたはサソリの尻尾が生えている。(毒、ダメージ 3d7)", "You have a scorpion tail (poison, 3d7).");
+ }
+ if (p_ptr->muta2 & MUT2_HORNS)
+ {
+ info[i++] = _("あなたは角が生えている。(ダメージ 2d6)", "You have horns (dam. 2d6).");
+ }
+ if (p_ptr->muta2 & MUT2_BEAK)
+ {
+ info[i++] = _("あなたはクチバシが生えている。(ダメージ 2d4)", "You have a beak (dam. 2d4).");
+ }
+ if (p_ptr->muta2 & MUT2_SPEED_FLUX)
+ {
+ info[i++] = _("あなたはランダムに早く動いたり遅く動いたりする。", "You move faster or slower randomly.");
+ }
+ if (p_ptr->muta2 & MUT2_BANISH_ALL)
+ {
+ info[i++] = _("あなたは時々近くのモンスターを消滅させる。", "You sometimes cause nearby creatures to vanish.");
+ }
+ if (p_ptr->muta2 & MUT2_EAT_LIGHT)
+ {
+ info[i++] = _("あなたは時々周囲の光を吸収して栄養にする。", "You sometimes feed off of the light around you.");
+ }
+ if (p_ptr->muta2 & MUT2_TRUNK)
+ {
+ info[i++] = _("あなたは象のような鼻を持っている。(ダメージ 1d4)", "You have an elephantine trunk (dam 1d4).");
+ }
+ if (p_ptr->muta2 & MUT2_ATT_ANIMAL)
+ {
+ info[i++] = _("あなたは動物を引きつける。", "You attract animals.");
+ }
+ if (p_ptr->muta2 & MUT2_TENTACLES)
+ {
+ info[i++] = _("あなたは邪悪な触手を持っている。(ダメージ 2d5)", "You have evil looking tentacles (dam 2d5).");
+ }
+ if (p_ptr->muta2 & MUT2_RAW_CHAOS)
+ {
+ info[i++] = _("あなたはしばしば純カオスに包まれる。", "You occasionally are surrounded with raw chaos.");
+ }
+ if (p_ptr->muta2 & MUT2_NORMALITY)
+ {
+ info[i++] = _("あなたは変異していたが、回復してきている。", "You may be mutated, but you're recovering.");
+ }
+ if (p_ptr->muta2 & MUT2_WRAITH)
+ {
+ info[i++] = _("あなたの肉体は幽体化したり実体化したりする。", "You fade in and out of physical reality.");
+ }
+ if (p_ptr->muta2 & MUT2_POLY_WOUND)
+ {
+ info[i++] = _("あなたの健康はカオスの力に影響を受ける。", "Your health is subject to chaotic forces.");
+ }
+ if (p_ptr->muta2 & MUT2_WASTING)
+ {
+ info[i++] = _("あなたは衰弱する恐ろしい病気にかかっている。", "You have a horrible wasting disease.");
+ }
+ if (p_ptr->muta2 & MUT2_ATT_DRAGON)
+ {
+ info[i++] = _("あなたはドラゴンを引きつける。", "You attract dragons.");
+ }
+ if (p_ptr->muta2 & MUT2_WEIRD_MIND)
+ {
+ info[i++] = _("あなたの精神はランダムに拡大したり縮小したりしている。", "Your mind randomly expands and contracts.");
+ }
+ if (p_ptr->muta2 & MUT2_NAUSEA)
+ {
+ info[i++] = _("あなたの胃は非常に落ち着きがない。", "You have a seriously upset stomach.");
+ }
+ if (p_ptr->muta2 & MUT2_CHAOS_GIFT)
+ {
+ info[i++] = _("あなたはカオスの守護悪魔から褒美をうけとる。", "Chaos deities give you gifts.");
+ }
+ if (p_ptr->muta2 & MUT2_WALK_SHAD)
+ {
+ info[i++] = _("あなたはしばしば他の「影」に迷い込む。", "You occasionally stumble into other shadows.");
+ }
+ if (p_ptr->muta2 & MUT2_WARNING)
+ {
+ info[i++] = _("あなたは敵に関する警告を感じる。", "You receive warnings about your foes.");
+ }
+ if (p_ptr->muta2 & MUT2_INVULN)
+ {
+ info[i++] = _("あなたは時々負け知らずな気分になる。", "You occasionally feel invincible.");
+ }
+ if (p_ptr->muta2 & MUT2_SP_TO_HP)
+ {
+ info[i++] = _("あなたは時々血が筋肉にどっと流れる。", "Your blood sometimes rushes to your muscles.");
+ }
+ if (p_ptr->muta2 & MUT2_HP_TO_SP)
+ {
+ info[i++] = _("あなたは時々頭に血がどっと流れる。", "Your blood sometimes rushes to your head.");
+ }
+ if (p_ptr->muta2 & MUT2_DISARM)
+ {
+ info[i++] = _("あなたはよくつまづいて物を落とす。", "You occasionally stumble and drop things.");
+ }
+ }
+
+ if (p_ptr->muta3)
+ {
+ if (p_ptr->muta3 & MUT3_HYPER_STR)
+ {
+ info[i++] = _("あなたは超人的に強い。(腕力+4)", "You are superhumanly strong (+4 STR).");
+ }
+ if (p_ptr->muta3 & MUT3_PUNY)
+ {
+ info[i++] = _("あなたは虚弱だ。(腕力-4)", "You are puny (-4 STR).");
+ }
+ if (p_ptr->muta3 & MUT3_HYPER_INT)
+ {
+ info[i++] = _("あなたの脳は生体コンピュータだ。(知能&賢さ+4)", "Your brain is a living computer (+4 INT/WIS).");
+ }
+ if (p_ptr->muta3 & MUT3_MORONIC)
+ {
+ info[i++] = _("あなたは精神薄弱だ。(知能&賢さ-4)", "You are moronic (-4 INT/WIS).");
+ }
+ if (p_ptr->muta3 & MUT3_RESILIENT)
+ {
+ info[i++] = _("あなたは非常にタフだ。(耐久+4)", "You are very resilient (+4 CON).");
+ }
+ if (p_ptr->muta3 & MUT3_XTRA_FAT)
+ {
+ info[i++] = _("あなたは極端に太っている。(耐久+2,スピード-2)", "You are extremely fat (+2 CON, -2 speed).");
+ }
+ if (p_ptr->muta3 & MUT3_ALBINO)
+ {
+ info[i++] = _("あなたはアルビノだ。(耐久-4)", "You are albino (-4 CON).");
+ }
+ if (p_ptr->muta3 & MUT3_FLESH_ROT)
+ {
+ info[i++] = _("あなたの肉体は腐敗している。(耐久-2,魅力-1)", "Your flesh is rotting (-2 CON, -1 CHR).");
+ }
+ if (p_ptr->muta3 & MUT3_SILLY_VOI)
+ {
+ info[i++] = _("あなたの声は間抜けなキーキー声だ。(魅力-4)", "Your voice is a silly squeak (-4 CHR).");
+ }
+ if (p_ptr->muta3 & MUT3_BLANK_FAC)
+ {
+ info[i++] = _("あなたはのっぺらぼうだ。(魅力-1)", "Your face is featureless (-1 CHR).");
+ }
+ if (p_ptr->muta3 & MUT3_ILL_NORM)
+ {
+ info[i++] = _("あなたは幻影に覆われている。", "Your appearance is masked with illusion.");
+ }
+ if (p_ptr->muta3 & MUT3_XTRA_EYES)
+ {
+ info[i++] = _("あなたは余分に二つの目を持っている。(探索+15)", "You have an extra pair of eyes (+15 search).");
+ }
+ if (p_ptr->muta3 & MUT3_MAGIC_RES)
+ {
+ info[i++] = _("あなたは魔法への耐性をもっている。", "You are resistant to magic.");
+ }
+ if (p_ptr->muta3 & MUT3_XTRA_NOIS)
+ {
+ info[i++] = _("あなたは変な音を発している。(隠密-3)", "You make a lot of strange noise (-3 stealth).");
+ }
+ if (p_ptr->muta3 & MUT3_INFRAVIS)
+ {
+ info[i++] = _("あなたは素晴らしい赤外線視力を持っている。(+3)", "You have remarkable infravision (+3).");
+ }
+ if (p_ptr->muta3 & MUT3_XTRA_LEGS)
+ {
+ info[i++] = _("あなたは余分に二本の足が生えている。(加速+3)", "You have an extra pair of legs (+3 speed).");
+ }
+ if (p_ptr->muta3 & MUT3_SHORT_LEG)
+ {
+ info[i++] = _("あなたの足は短い突起だ。(加速-3)", "Your legs are short stubs (-3 speed).");
+ }
+ if (p_ptr->muta3 & MUT3_ELEC_TOUC)
+ {
+ info[i++] = _("あなたの血管には電流が流れている。", "Electricity is running through your veins.");
+ }
+ if (p_ptr->muta3 & MUT3_FIRE_BODY)
+ {
+ info[i++] = _("あなたの体は炎につつまれている。", "Your body is enveloped in flames.");
+ }
+ if (p_ptr->muta3 & MUT3_WART_SKIN)
+ {
+ info[i++] = _("あなたの肌はイボに被われている。(魅力-2, AC+5)", "Your skin is covered with warts (-2 CHR, +5 AC).");
+ }
+ if (p_ptr->muta3 & MUT3_SCALES)
+ {
+ info[i++] = _("あなたの肌は鱗になっている。(魅力-1, AC+10)", "Your skin has turned into scales (-1 CHR, +10 AC).");
+ }
+ if (p_ptr->muta3 & MUT3_IRON_SKIN)
+ {
+ info[i++] = _("あなたの肌は鉄でできている。(器用-1, AC+25)", "Your skin is made of steel (-1 DEX, +25 AC).");
+ }
+ if (p_ptr->muta3 & MUT3_WINGS)
+ {
+ info[i++] = _("あなたは羽を持っている。", "You have wings.");
+ }
+ if (p_ptr->muta3 & MUT3_FEARLESS)
+ {
+ /* Unnecessary */
+ }
+ if (p_ptr->muta3 & MUT3_REGEN)
+ {
+ /* Unnecessary */
+ }
+ if (p_ptr->muta3 & MUT3_ESP)
+ {
+ /* Unnecessary */
+ }
+ if (p_ptr->muta3 & MUT3_LIMBER)
+ {
+ info[i++] = _("あなたの体は非常にしなやかだ。(器用+3)", "Your body is very limber (+3 DEX).");
+ }
+ if (p_ptr->muta3 & MUT3_ARTHRITIS)
+ {
+ info[i++] = _("あなたはいつも関節に痛みを感じている。(器用-3)", "Your joints ache constantly (-3 DEX).");
+ }
+ if (p_ptr->muta3 & MUT3_VULN_ELEM)
+ {
+ info[i++] = _("あなたは元素の攻撃に弱い。", "You are susceptible to damage from the elements.");
+ }
+ if (p_ptr->muta3 & MUT3_MOTION)
+ {
+ info[i++] = _("あなたの動作は正確で力強い。(隠密+1)", "Your movements are precise and forceful (+1 STL).");
+ }
+ if (p_ptr->muta3 & MUT3_GOOD_LUCK)
+ {
+ info[i++] = _("あなたは白いオーラにつつまれている。", "There is a white aura surrounding you.");
+ }
+ if (p_ptr->muta3 & MUT3_BAD_LUCK)
+ {
+ info[i++] = _("あなたは黒いオーラにつつまれている。", "There is a black aura surrounding you.");
+ }
+ }
+
+ if (p_ptr->blind)
+ {
+ info[i++] = _("あなたは目が見えない。", "You cannot see.");
+ }
+ if (p_ptr->confused)
+ {
+ info[i++] = _("あなたは混乱している。", "You are confused.");
+ }
+ if (p_ptr->afraid)
+ {
+ info[i++] = _("あなたは恐怖に侵されている。", "You are terrified.");
+ }
+ if (p_ptr->cut)
+ {
+ info[i++] = _("あなたは出血している。", "You are bleeding.");
+ }
+ if (p_ptr->stun)
+ {
+ info[i++] = _("あなたはもうろうとしている。", "You are stunned.");
+ }
+ if (p_ptr->poisoned)
+ {
+ info[i++] = _("あなたは毒に侵されている。", "You are poisoned.");
+ }
+ if (p_ptr->image)
+ {
+ info[i++] = _("あなたは幻覚を見ている。", "You are hallucinating.");
+ }
+ if (p_ptr->cursed & TRC_TY_CURSE)
+ {
+ info[i++] = _("あなたは邪悪な怨念に包まれている。", "You carry an ancient foul curse.");
+ }
+ if (p_ptr->cursed & TRC_AGGRAVATE)
+ {
+ info[i++] = _("あなたはモンスターを怒らせている。", "You aggravate monsters.");
+ }
+ if (p_ptr->cursed & TRC_DRAIN_EXP)
+ {
+ info[i++] = _("あなたは経験値を吸われている。", "You are drained.");
+ }
+ if (p_ptr->cursed & TRC_SLOW_REGEN)
+ {
+ info[i++] = _("あなたの回復力は非常に遅い。", "You regenerate slowly.");
+ }
+ if (p_ptr->cursed & TRC_ADD_L_CURSE)
+ {
+ info[i++] = _("あなたの弱い呪いは増える。","Your weak curses multiply."); /* 暫定的 -- henkma */
+ }
+ if (p_ptr->cursed & TRC_ADD_H_CURSE)
+ {
+ info[i++] = _("あなたの強い呪いは増える。","Your heavy curses multiply."); /* 暫定的 -- henkma */
+ }
+ if (p_ptr->cursed & TRC_CALL_ANIMAL)
+ {
+ info[i++] = _("あなたは動物に狙われている。", "You attract animals.");
+ }
+ if (p_ptr->cursed & TRC_CALL_DEMON)
+ {
+ info[i++] = _("あなたは悪魔に狙われている。", "You attract demons.");
+ }
+ if (p_ptr->cursed & TRC_CALL_DRAGON)
+ {
+ info[i++] = _("あなたはドラゴンに狙われている。", "You attract dragons.");
+ }
+ if (p_ptr->cursed & TRC_COWARDICE)
+ {
+ info[i++] = _("あなたは時々臆病になる。", "You are subject to cowardice.");
+ }
+ if (p_ptr->cursed & TRC_TELEPORT)
+ {
+ info[i++] = _("あなたの位置はひじょうに不安定だ。", "Your position is very uncertain.");
+ }
+ if (p_ptr->cursed & TRC_LOW_MELEE)
+ {
+ info[i++] = _("あなたの武器は攻撃を外しやすい。", "Your weapon causes you to miss blows.");
+ }
+ if (p_ptr->cursed & TRC_LOW_AC)
+ {
+ info[i++] = _("あなたは攻撃を受けやすい。", "You are subject to be hit.");
+ }
+ if (p_ptr->cursed & TRC_LOW_MAGIC)
+ {
+ info[i++] = _("あなたは魔法を失敗しやすい。", "You are subject to fail spellcasting.");
+ }
+ if (p_ptr->cursed & TRC_FAST_DIGEST)
+ {
+ info[i++] = _("あなたはすぐお腹がへる。", "You have a good appetite.");
+ }
+ if (p_ptr->cursed & TRC_DRAIN_HP)
+ {
+ info[i++] = _("あなたは体力を吸われている。", "You are drained.");
+ }
+ if (p_ptr->cursed & TRC_DRAIN_MANA)
+ {
+ info[i++] = _("あなたは魔力を吸われている。", "You brain is drained.");
+ }
+ if (IS_BLESSED())
+ {
+ info[i++] = _("あなたは高潔さを感じている。", "You feel rightous.");
+ }
+ if (IS_HERO())
+ {
+ info[i++] = _("あなたはヒーロー気分だ。", "You feel heroic.");
+ }
+ if (p_ptr->shero)
+ {
+ info[i++] = _("あなたは戦闘狂だ。", "You are in a battle rage.");
+ }
+ if (p_ptr->protevil)
+ {
+ info[i++] = _("あなたは邪悪なる存在から守られている。", "You are protected from evil.");
+ }
+ if (p_ptr->shield)
+ {
+ info[i++] = _("あなたは神秘のシールドで守られている。", "You are protected by a mystic shield.");
+ }
+ if (IS_INVULN())
+ {
+ info[i++] = _("あなたは現在傷つかない。", "You are temporarily invulnerable.");
+ }
+ if (p_ptr->wraith_form)
+ {
+ info[i++] = _("あなたは一時的に幽体化している。", "You are temporarily incorporeal.");
+ }
+ if (p_ptr->special_attack & ATTACK_CONFUSE)
+ {
+ info[i++] = _("あなたの手は赤く輝いている。", "Your hands are glowing dull red.");
+ }
+ if (p_ptr->special_attack & ATTACK_FIRE)
+ {
+ info[i++] = _("あなたの手は火炎に覆われている。", "You can strike the enemy with flame.");
+ }
+ if (p_ptr->special_attack & ATTACK_COLD)
+ {
+ info[i++] = _("あなたの手は冷気に覆われている。", "You can strike the enemy with cold.");
+ }
+ if (p_ptr->special_attack & ATTACK_ACID)
+ {
+ info[i++] = _("あなたの手は酸に覆われている。", "You can strike the enemy with acid.");
+ }
+ if (p_ptr->special_attack & ATTACK_ELEC)
+ {
+ info[i++] = _("あなたの手は電撃に覆われている。", "You can strike the enemy with electoric shock.");
+ }
+ if (p_ptr->special_attack & ATTACK_POIS)
+ {
+ info[i++] = _("あなたの手は毒に覆われている。", "You can strike the enemy with poison.");
+ }
+ switch (p_ptr->action)
+ {
+ case ACTION_SEARCH:
+ info[i++] = _("あなたはひじょうに注意深く周囲を見渡している。", "You are looking around very carefully.");
+ break;
+ }
+ if (p_ptr->new_spells)
+ {
+ info[i++] = _("あなたは呪文や祈りを学ぶことができる。", "You can learn some spells/prayers.");
+ }
+ if (p_ptr->word_recall)
+ {
+ info[i++] = _("あなたはすぐに帰還するだろう。", "You will soon be recalled.");
+ }
+ if (p_ptr->alter_reality)
+ {
+ info[i++] = _("あなたはすぐにこの世界を離れるだろう。", "You will soon be altered.");
+ }
+ if (p_ptr->see_infra)
+ {
+ info[i++] = _("あなたの瞳は赤外線に敏感である。", "Your eyes are sensitive to infrared light.");
+ }
+ if (p_ptr->see_inv)
+ {
+ info[i++] = _("あなたは透明なモンスターを見ることができる。", "You can see invisible creatures.");
+ }
+ if (p_ptr->levitation)
+ {
+ info[i++] = _("あなたは飛ぶことができる。", "You can fly.");
+ }
+ if (p_ptr->free_act)
+ {
+ info[i++] = _("あなたは麻痺知らずの効果を持っている。", "You have free action.");
+ }
+ if (p_ptr->regenerate)
+ {
+ info[i++] = _("あなたは素早く体力を回復する。", "You regenerate quickly.");
+ }
+ if (p_ptr->slow_digest)
+ {
+ info[i++] = _("あなたは食欲が少ない。", "Your appetite is small.");
+ }
+ if (p_ptr->telepathy)
+ {
+ info[i++] = _("あなたはテレパシー能力を持っている。", "You have ESP.");
+ }
+ if (p_ptr->esp_animal)
+ {
+ info[i++] = _("あなたは自然界の生物の存在を感じる能力を持っている。", "You sense natural creatures.");
+ }
+ if (p_ptr->esp_undead)
+ {
+ info[i++] = _("あなたはアンデッドの存在を感じる能力を持っている。", "You sense undead.");
+ }
+ if (p_ptr->esp_demon)
+ {
+ info[i++] = _("あなたは悪魔の存在を感じる能力を持っている。", "You sense demons.");
+ }
+ if (p_ptr->esp_orc)
+ {
+ info[i++] = _("あなたはオークの存在を感じる能力を持っている。", "You sense orcs.");
+ }
+ if (p_ptr->esp_troll)
+ {
+ info[i++] = _("あなたはトロルの存在を感じる能力を持っている。", "You sense trolls.");
+ }
+ if (p_ptr->esp_giant)
+ {
+ info[i++] = _("あなたは巨人の存在を感じる能力を持っている。", "You sense giants.");
+ }
+ if (p_ptr->esp_dragon)
+ {
+ info[i++] = _("あなたはドラゴンの存在を感じる能力を持っている。", "You sense dragons.");
+ }
+ if (p_ptr->esp_human)
+ {
+ info[i++] = _("あなたは人間の存在を感じる能力を持っている。", "You sense humans.");
+ }
+ if (p_ptr->esp_evil)
+ {
+ info[i++] = _("あなたは邪悪な生き物の存在を感じる能力を持っている。", "You sense evil creatures.");
+ }
+ if (p_ptr->esp_good)
+ {
+ info[i++] = _("あなたは善良な生き物の存在を感じる能力を持っている。", "You sense good creatures.");
+ }
+ if (p_ptr->esp_nonliving)
+ {
+ info[i++] = _("あなたは活動する無生物体の存在を感じる能力を持っている。", "You sense non-living creatures.");
+ }
+ if (p_ptr->esp_unique)
+ {
+ info[i++] = _("あなたは特別な強敵の存在を感じる能力を持っている。", "You sense unique monsters.");
+ }
+ if (p_ptr->hold_exp)
+ {
+ info[i++] = _("あなたは自己の経験値をしっかりと維持する。", "You have a firm hold on your experience.");
+ }
+ if (p_ptr->reflect)
+ {
+ info[i++] = _("あなたは矢の呪文を反射する。", "You reflect bolt spells.");
+ }
+ if (p_ptr->sh_fire)
+ {
+ info[i++] = _("あなたは炎のオーラに包まれている。", "You are surrounded with a fiery aura.");
+ }
+ if (p_ptr->sh_elec)
+ {
+ info[i++] = _("あなたは電気に包まれている。", "You are surrounded with electricity.");
+ }
+ if (p_ptr->sh_cold)
+ {
+ info[i++] = _("あなたは冷気のオーラに包まれている。", "You are surrounded with an aura of coldness.");
+ }
+ if (p_ptr->tim_sh_holy)
+ {
+ info[i++] = _("あなたは聖なるオーラに包まれている。", "You are surrounded with a holy aura.");
+ }
+ if (p_ptr->tim_sh_touki)
+ {
+ info[i++] = _("あなたは闘気のオーラに包まれている。", "You are surrounded with a energy aura.");
+ }
+ if (p_ptr->anti_magic)
+ {
+ info[i++] = _("あなたは反魔法シールドに包まれている。", "You are surrounded by an anti-magic shell.");
+ }
+ if (p_ptr->anti_tele)
+ {
+ info[i++] = _("あなたはテレポートできない。", "You cannot teleport.");
+ }
+ if (p_ptr->lite)
+ {
+ info[i++] = _("あなたの身体は光っている。", "You are carrying a permanent light.");
+ }
+ if (p_ptr->warning)
+ {
+ info[i++] = _("あなたは行動の前に危険を察知することができる。", "You will be warned before dangerous actions.");
+ }
+ if (p_ptr->dec_mana)
+ {
+ info[i++] = _("あなたは少ない消費魔力で魔法を唱えることができる。", "You can cast spells with fewer mana points.");
+ }
+ if (p_ptr->easy_spell)
+ {
+ info[i++] = _("あなたは低い失敗率で魔法を唱えることができる。", "Fail rate of your magic is decreased.");
+ }
+ if (p_ptr->heavy_spell)
+ {
+ info[i++] = _("あなたは高い失敗率で魔法を唱えなければいけない。", "Fail rate of your magic is increased.");
+ }
+ if (p_ptr->mighty_throw)
+ {
+ info[i++] = _("あなたは強く物を投げる。", "You can throw objects powerfully.");
+ }
+
+ if (p_ptr->immune_acid)
+ {
+ info[i++] = _("あなたは酸に対する完全なる免疫を持っている。", "You are completely immune to acid.");
+ }
+ else if (p_ptr->resist_acid && IS_OPPOSE_ACID())
+ {
+ info[i++] = _("あなたは酸への強力な耐性を持っている。", "You resist acid exceptionally well.");
+ }
+ else if (p_ptr->resist_acid || IS_OPPOSE_ACID())
+ {
+ info[i++] = _("あなたは酸への耐性を持っている。", "You are resistant to acid.");
+ }
+
+ if (p_ptr->immune_elec)
+ {
+ info[i++] = _("あなたは電撃に対する完全なる免疫を持っている。", "You are completely immune to lightning.");
+ }
+ else if (p_ptr->resist_elec && IS_OPPOSE_ELEC())
+ {
+ info[i++] = _("あなたは電撃への強力な耐性を持っている。", "You resist lightning exceptionally well.");
+ }
+ else if (p_ptr->resist_elec || IS_OPPOSE_ELEC())
+ {
+ info[i++] = _("あなたは電撃への耐性を持っている。", "You are resistant to lightning.");
+ }
+
+ if (prace_is_(RACE_ANDROID) && !p_ptr->immune_elec)
+ {
+ info[i++] = _("あなたは電撃に弱い。", "You are susceptible to damage from lightning.");
+ }
+
+ if (p_ptr->immune_fire)
+ {
+ info[i++] = _("あなたは火に対する完全なる免疫を持っている。", "You are completely immune to fire.");
+ }
+ else if (p_ptr->resist_fire && IS_OPPOSE_FIRE())
+ {
+ info[i++] = _("あなたは火への強力な耐性を持っている。", "You resist fire exceptionally well.");
+ }
+ else if (p_ptr->resist_fire || IS_OPPOSE_FIRE())
+ {
+ info[i++] = _("あなたは火への耐性を持っている。", "You are resistant to fire.");
+ }
+
+ if (prace_is_(RACE_ENT) && !p_ptr->immune_fire)
+ {
+ info[i++] = _("あなたは火に弱い。", "You are susceptible to damage from fire.");
+ }
+
+ if (p_ptr->immune_cold)
+ {
+ info[i++] = _("あなたは冷気に対する完全なる免疫を持っている。", "You are completely immune to cold.");
+ }
+ else if (p_ptr->resist_cold && IS_OPPOSE_COLD())
+ {
+ info[i++] = _("あなたは冷気への強力な耐性を持っている。", "You resist cold exceptionally well.");
+ }
+ else if (p_ptr->resist_cold || IS_OPPOSE_COLD())
+ {
+ info[i++] = _("あなたは冷気への耐性を持っている。", "You are resistant to cold.");
+ }
+
+ if (p_ptr->resist_pois && IS_OPPOSE_POIS())
+ {
+ info[i++] = _("あなたは毒への強力な耐性を持っている。", "You resist poison exceptionally well.");
+ }
+ else if (p_ptr->resist_pois || IS_OPPOSE_POIS())
+ {
+ info[i++] = _("あなたは毒への耐性を持っている。", "You are resistant to poison.");
+ }
+
+ if (p_ptr->resist_lite)
+ {
+ info[i++] = _("あなたは閃光への耐性を持っている。", "You are resistant to bright light.");
+ }
+
+ if (prace_is_(RACE_VAMPIRE) || prace_is_(RACE_S_FAIRY) || (p_ptr->mimic_form == MIMIC_VAMPIRE))
+ {
+ info[i++] = _("あなたは閃光に弱い。", "You are susceptible to damage from bright light.");
+ }
+
+ if (prace_is_(RACE_VAMPIRE) || (p_ptr->mimic_form == MIMIC_VAMPIRE) || p_ptr->wraith_form)
+ {
+ info[i++] = _("あなたは暗黒に対する完全なる免疫を持っている。", "You are completely immune to darkness.");
+ }
+
+ else if (p_ptr->resist_dark)
+ {
+ info[i++] = _("あなたは暗黒への耐性を持っている。", "You are resistant to darkness.");
+ }
+ if (p_ptr->resist_conf)
+ {
+ info[i++] = _("あなたは混乱への耐性を持っている。", "You are resistant to confusion.");
+ }
+ if (p_ptr->resist_sound)
+ {
+ info[i++] = _("あなたは音波の衝撃への耐性を持っている。", "You are resistant to sonic attacks.");
+ }
+ if (p_ptr->resist_disen)
+ {
+ info[i++] = _("あなたは劣化への耐性を持っている。", "You are resistant to disenchantment.");
+ }
+ if (p_ptr->resist_chaos)
+ {
+ info[i++] = _("あなたはカオスの力への耐性を持っている。", "You are resistant to chaos.");
+ }
+ if (p_ptr->resist_shard)
+ {
+ info[i++] = _("あなたは破片の攻撃への耐性を持っている。", "You are resistant to blasts of shards.");
+ }
+ if (p_ptr->resist_nexus)
+ {
+ info[i++] = _("あなたは因果混乱の攻撃への耐性を持っている。", "You are resistant to nexus attacks.");
+ }
+
+ if (prace_is_(RACE_SPECTRE))
+ {
+ info[i++] = _("あなたは地獄の力を吸収できる。", "You can drain nether forces.");
+ }
+ else if (p_ptr->resist_neth)
+ {
+ info[i++] = _("あなたは地獄の力への耐性を持っている。", "You are resistant to nether forces.");
+ }
+ if (p_ptr->resist_fear)
+ {
+ info[i++] = _("あなたは全く恐怖を感じない。", "You are completely fearless.");
+ }
+ if (p_ptr->resist_blind)
+ {
+ info[i++] = _("あなたの目は盲目への耐性を持っている。", "Your eyes are resistant to blindness.");
+ }
+ if (p_ptr->resist_time)
+ {
+ info[i++] = _("あなたは時間逆転への耐性を持っている。", "You are resistant to time.");
+ }
+
+ if (p_ptr->sustain_str)
+ {
+ info[i++] = _("あなたの腕力は維持されている。", "Your strength is sustained.");
+ }
+ if (p_ptr->sustain_int)
+ {
+ info[i++] = _("あなたの知能は維持されている。", "Your intelligence is sustained.");
+ }
+ if (p_ptr->sustain_wis)
+ {
+ info[i++] = _("あなたの賢さは維持されている。", "Your wisdom is sustained.");
+ }
+ if (p_ptr->sustain_con)
+ {
+ info[i++] = _("あなたの耐久力は維持されている。", "Your constitution is sustained.");
+ }
+ if (p_ptr->sustain_dex)
+ {
+ info[i++] = _("あなたの器用さは維持されている。", "Your dexterity is sustained.");
+ }
+ if (p_ptr->sustain_chr)
+ {
+ info[i++] = _("あなたの魅力は維持されている。", "Your charisma is sustained.");
+ }
+
+ if (have_flag(flgs, TR_STR))
+ {
+ info[i++] = _("あなたの腕力は装備によって影響を受けている。", "Your strength is affected by your equipment.");
+ }
+ if (have_flag(flgs, TR_INT))
+ {
+ info[i++] = _("あなたの知能は装備によって影響を受けている。", "Your intelligence is affected by your equipment.");
+ }
+ if (have_flag(flgs, TR_WIS))
+ {
+ info[i++] = _("あなたの賢さは装備によって影響を受けている。", "Your wisdom is affected by your equipment.");
+ }
+ if (have_flag(flgs, TR_DEX))
+ {
+ info[i++] = _("あなたの器用さは装備によって影響を受けている。", "Your dexterity is affected by your equipment.");
+ }
+ if (have_flag(flgs, TR_CON))
+ {
+ info[i++] = _("あなたの耐久力は装備によって影響を受けている。", "Your constitution is affected by your equipment.");
+ }
+ if (have_flag(flgs, TR_CHR))
+ {
+ info[i++] = _("あなたの魅力は装備によって影響を受けている。", "Your charisma is affected by your equipment.");
+ }
+
+ if (have_flag(flgs, TR_STEALTH))
+ {
+ info[i++] = _("あなたの隠密行動能力は装備によって影響を受けている。", "Your stealth is affected by your equipment.");
+ }
+ if (have_flag(flgs, TR_SEARCH))
+ {
+ info[i++] = _("あなたの探索能力は装備によって影響を受けている。", "Your searching ability is affected by your equipment.");
+ }
+ if (have_flag(flgs, TR_INFRA))
+ {
+ info[i++] = _("あなたの赤外線視力は装備によって影響を受けている。", "Your infravision is affected by your equipment.");
+ }
+ if (have_flag(flgs, TR_TUNNEL))
+ {
+ info[i++] = _("あなたの採掘能力は装備によって影響を受けている。", "Your digging ability is affected by your equipment.");
+ }
+ if (have_flag(flgs, TR_SPEED))
+ {
+ info[i++] = _("あなたのスピードは装備によって影響を受けている。", "Your speed is affected by your equipment.");
+ }
+ if (have_flag(flgs, TR_BLOWS))
+ {
+ info[i++] = _("あなたの攻撃速度は装備によって影響を受けている。", "Your attack speed is affected by your equipment.");
+ }
+
+
+ /* Access the current weapon */
+ o_ptr = &inventory[INVEN_RARM];
+
+ /* Analyze the weapon */
+ if (o_ptr->k_idx)
+ {
+ /* Indicate Blessing */
+ if (have_flag(flgs, TR_BLESSED))
+ {
+ info[i++] = _("あなたの武器は神の祝福を受けている。", "Your weapon has been blessed by the gods.");
+ }
+
+ if (have_flag(flgs, TR_CHAOTIC))
+ {
+ info[i++] = _("あなたの武器はログルスの徴の属性をもつ。", "Your weapon is branded with the Sign of Logrus.");
+ }
+
+ if (have_flag(flgs, TR_IMPACT))
+ {
+ info[i++] = _("あなたの武器は打撃で地震を発生することができる。", "The impact of your weapon can cause earthquakes.");
+ }
+
+ if (have_flag(flgs, TR_VORPAL))
+ {
+ info[i++] = _("あなたの武器は非常に鋭い。", "Your weapon is very sharp.");
+ }
+
+ if (have_flag(flgs, TR_VAMPIRIC))
+ {
+ info[i++] = _("あなたの武器は敵から生命力を吸収する。", "Your weapon drains life from your foes.");
+ }
+
+ /* Special "Attack Bonuses" */
+ if (have_flag(flgs, TR_BRAND_ACID))
+ {
+ info[i++] = _("あなたの武器は敵を溶かす。", "Your weapon melts your foes.");
+ }
+ if (have_flag(flgs, TR_BRAND_ELEC))
+ {
+ info[i++] = _("あなたの武器は敵を感電させる。", "Your weapon shocks your foes.");
+ }
+ if (have_flag(flgs, TR_BRAND_FIRE))
+ {
+ info[i++] = _("あなたの武器は敵を燃やす。", "Your weapon burns your foes.");
+ }
+ if (have_flag(flgs, TR_BRAND_COLD))
+ {
+ info[i++] = _("あなたの武器は敵を凍らせる。", "Your weapon freezes your foes.");
+ }
+ if (have_flag(flgs, TR_BRAND_POIS))
+ {
+ info[i++] = _("あなたの武器は敵を毒で侵す。", "Your weapon poisons your foes.");
+ }
+
+ /* Special "slay" flags */
+ if (have_flag(flgs, TR_KILL_ANIMAL))
+ {
+ info[i++] = _("あなたの武器は動物の天敵である。", "Your weapon is a great bane of animals.");
+ }
+ else if (have_flag(flgs, TR_SLAY_ANIMAL))
+ {
+ info[i++] = _("あなたの武器は動物に対して強い力を発揮する。", "Your weapon strikes at animals with extra force.");
+ }
+ if (have_flag(flgs, TR_KILL_EVIL))
+ {
+ info[i++] = _("あなたの武器は邪悪なる存在の天敵である。", "Your weapon is a great bane of evil.");
+ }
+ else if (have_flag(flgs, TR_SLAY_EVIL))
+ {
+ info[i++] = _("あなたの武器は邪悪なる存在に対して強い力を発揮する。", "Your weapon strikes at evil with extra force.");
+ }
+ if (have_flag(flgs, TR_KILL_HUMAN))
+ {
+ info[i++] = _("あなたの武器は人間の天敵である。", "Your weapon is a great bane of humans.");
+ }
+ else if (have_flag(flgs, TR_SLAY_HUMAN))
+ {
+ info[i++] = _("あなたの武器は人間に対して特に強い力を発揮する。", "Your weapon is especially deadly against humans.");
+ }
+ if (have_flag(flgs, TR_KILL_UNDEAD))
+ {
+ info[i++] = _("あなたの武器はアンデッドの天敵である。", "Your weapon is a great bane of undead.");
+ }
+ else if (have_flag(flgs, TR_SLAY_UNDEAD))
+ {
+ info[i++] = _("あなたの武器はアンデッドに対して神聖なる力を発揮する。", "Your weapon strikes at undead with holy wrath.");
+ }
+ if (have_flag(flgs, TR_KILL_DEMON))
+ {
+ info[i++] = _("あなたの武器はデーモンの天敵である。", "Your weapon is a great bane of demons.");
+ }
+ else if (have_flag(flgs, TR_SLAY_DEMON))
+ {
+ info[i++] = _("あなたの武器はデーモンに対して神聖なる力を発揮する。", "Your weapon strikes at demons with holy wrath.");
+ }
+ if (have_flag(flgs, TR_KILL_ORC))
+ {
+ info[i++] = _("あなたの武器はオークの天敵である。", "Your weapon is a great bane of orcs.");
+ }
+ else if (have_flag(flgs, TR_SLAY_ORC))
+ {
+ info[i++] = _("あなたの武器はオークに対して特に強い力を発揮する。", "Your weapon is especially deadly against orcs.");
+ }
+ if (have_flag(flgs, TR_KILL_TROLL))
+ {
+ info[i++] = _("あなたの武器はトロルの天敵である。", "Your weapon is a great bane of trolls.");
+ }
+ else if (have_flag(flgs, TR_SLAY_TROLL))
+ {
+ info[i++] = _("あなたの武器はトロルに対して特に強い力を発揮する。", "Your weapon is especially deadly against trolls.");
+ }
+ if (have_flag(flgs, TR_KILL_GIANT))
+ {
+ info[i++] = _("あなたの武器はジャイアントの天敵である。", "Your weapon is a great bane of giants.");
+ }
+ else if (have_flag(flgs, TR_SLAY_GIANT))
+ {
+ info[i++] = _("あなたの武器はジャイアントに対して特に強い力を発揮する。", "Your weapon is especially deadly against giants.");
+ }
+ /* Special "kill" flags */
+ if (have_flag(flgs, TR_KILL_DRAGON))
+ {
+ info[i++] = _("あなたの武器はドラゴンの天敵である。", "Your weapon is a great bane of dragons.");
+ }
+ else if (have_flag(flgs, TR_SLAY_DRAGON))
+ {
+ info[i++] = _("あなたの武器はドラゴンに対して特に強い力を発揮する。", "Your weapon is especially deadly against dragons.");
+ }
+
+ if (have_flag(flgs, TR_FORCE_WEAPON))
+ {
+ info[i++] = _("あなたの武器はMPを使って攻撃する。", "Your weapon causes greate damages using your MP.");
+ }
+ if (have_flag(flgs, TR_THROW))
+ {
+ info[i++] = _("あなたの武器は投げやすい。", "Your weapon can be thrown well.");
+ }
+ }
+
+ screen_save();
+
+ /* Erase the screen */
+ for (k = 1; k < 24; k++) prt("", k, 13);
+
+ /* Label the information */
+ prt(_(" あなたの状態:", " Your Attributes:"), 1, 15);
+
+ /* We will print on top of the map (column 13) */
+ for (k = 2, j = 0; j < i; j++)
+ {
+ /* Show the info */
+ prt(info[j], k++, 15);
+
+ /* Every 20 entries (lines 2 to 21), start over */
+ if ((k == 22) && (j+1 < i))
+ {
+ prt(_("-- 続く --", "-- more --"), k, 15);
+ inkey();
+ for (; k > 2; k--) prt("", k, 15);
+ }
+ }
+
+ /* Pause */
+ prt(_("[何かキーを押すとゲームに戻ります]", "[Press any key to continue]"), k, 13);
+ inkey();
+ screen_load();
+}
+
+/*!
+ * @brief 魔法効果時間のターン数に基づいて表現IDを返す。
+ * @param dur 効果ターン数
+ * @return 効果時間の表現ID
+ */
+static int report_magics_aux(int dur)
+{
+ if (dur <= 5)
+ {
+ return 0;
+ }
+ else if (dur <= 10)
+ {
+ return 1;
+ }
+ else if (dur <= 20)
+ {
+ return 2;
+ }
+ else if (dur <= 50)
+ {
+ return 3;
+ }
+ else if (dur <= 100)
+ {
+ return 4;
+ }
+ else if (dur <= 200)
+ {
+ return 5;
+ }
+ else
+ {
+ return 6;
+ }
+}
+
+static concptr report_magic_durations[] =
+{
+#ifdef JP
+ "ごく短い間",
+ "少しの間",
+ "しばらくの間",
+ "多少長い間",
+ "長い間",
+ "非常に長い間",
+ "信じ難いほど長い間",
+ "モンスターを攻撃するまで"
+#else
+ "for a short time",
+ "for a little while",
+ "for a while",
+ "for a long while",
+ "for a long time",
+ "for a very long time",
+ "for an incredibly long time",
+ "until you hit a monster"
+#endif
+
+};
+
+/*!
+ * @brief 現在の一時的効果一覧を返す / Report all currently active magical effects.
+ * @return なし
+ */
+void report_magics(void)
+{
+ int i = 0, j, k;
+ char Dummy[80];
+ concptr info[128];
+ int info2[128];
+
+
+ if (p_ptr->blind)
+ {
+ info2[i] = report_magics_aux(p_ptr->blind);
+ info[i++] = _("あなたは目が見えない", "You cannot see");
+ }
+ if (p_ptr->confused)
+ {
+ info2[i] = report_magics_aux(p_ptr->confused);
+ info[i++] = _("あなたは混乱している", "You are confused");
+ }
+ if (p_ptr->afraid)
+ {
+ info2[i] = report_magics_aux(p_ptr->afraid);
+ info[i++] = _("あなたは恐怖に侵されている", "You are terrified");
+ }
+ if (p_ptr->poisoned)
+ {
+ info2[i] = report_magics_aux(p_ptr->poisoned);
+ info[i++] = _("あなたは毒に侵されている", "You are poisoned");
+ }
+ if (p_ptr->image)
+ {
+ info2[i] = report_magics_aux(p_ptr->image);
+ info[i++] = _("あなたは幻覚を見ている", "You are hallucinating");
+ }
+ if (p_ptr->blessed)
+ {
+ info2[i] = report_magics_aux(p_ptr->blessed);
+ info[i++] = _("あなたは高潔さを感じている", "You feel rightous");
+ }
+ if (p_ptr->hero)
+ {
+ info2[i] = report_magics_aux(p_ptr->hero);
+ info[i++] = _("あなたはヒーロー気分だ", "You feel heroic");
+ }
+ if (p_ptr->shero)
+ {
+ info2[i] = report_magics_aux(p_ptr->shero);
+ info[i++] = _("あなたは戦闘狂だ", "You are in a battle rage");
+ }
+ if (p_ptr->protevil)
+ {
+ info2[i] = report_magics_aux(p_ptr->protevil);
+ info[i++] = _("あなたは邪悪なる存在から守られている", "You are protected from evil");
+ }
+ if (p_ptr->shield)
+ {
+ info2[i] = report_magics_aux(p_ptr->shield);
+ info[i++] = _("あなたは神秘のシールドで守られている", "You are protected by a mystic shield");
+ }
+ if (p_ptr->invuln)
+ {
+ info2[i] = report_magics_aux(p_ptr->invuln);
+ info[i++] = _("あなたは無敵だ", "You are invulnerable");
+ }
+ if (p_ptr->wraith_form)
+ {
+ info2[i] = report_magics_aux(p_ptr->wraith_form);
+ info[i++] = _("あなたは幽体化している", "You are incorporeal");
+ }
+ if (p_ptr->special_attack & ATTACK_CONFUSE)
+ {
+ info2[i] = 7;
+ info[i++] = _("あなたの手は赤く輝いている", "Your hands are glowing dull red.");
+ }
+ if (p_ptr->word_recall)
+ {
+ info2[i] = report_magics_aux(p_ptr->word_recall);
+ info[i++] = _("この後帰還の詔が発動する", "You are waiting to be recalled");
+ }
+ if (p_ptr->alter_reality)
+ {
+ info2[i] = report_magics_aux(p_ptr->alter_reality);
+ info[i++] = _("この後現実変容が発動する", "You waiting to be altered");
+ }
+ if (p_ptr->oppose_acid)
+ {
+ info2[i] = report_magics_aux(p_ptr->oppose_acid);
+ info[i++] = _("あなたは酸への耐性を持っている", "You are resistant to acid");
+ }
+ if (p_ptr->oppose_elec)
+ {
+ info2[i] = report_magics_aux(p_ptr->oppose_elec);
+ info[i++] = _("あなたは電撃への耐性を持っている", "You are resistant to lightning");
+ }
+ if (p_ptr->oppose_fire)
+ {
+ info2[i] = report_magics_aux(p_ptr->oppose_fire);
+ info[i++] = _("あなたは火への耐性を持っている", "You are resistant to fire");
+ }
+ if (p_ptr->oppose_cold)
+ {
+ info2[i] = report_magics_aux(p_ptr->oppose_cold);
+ info[i++] = _("あなたは冷気への耐性を持っている", "You are resistant to cold");
+ }
+ if (p_ptr->oppose_pois)
+ {
+ info2[i] = report_magics_aux(p_ptr->oppose_pois);
+ info[i++] = _("あなたは毒への耐性を持っている", "You are resistant to poison");
+ }
+ screen_save();
+
+ /* Erase the screen */
+ for (k = 1; k < 24; k++) prt("", k, 13);
+
+ /* Label the information */
+ prt(_(" 現在かかっている魔法 :", " Your Current Magic:"), 1, 15);
+
+
+ /* We will print on top of the map (column 13) */
+ for (k = 2, j = 0; j < i; j++)
+ {
+ /* Show the info */
+ sprintf(Dummy, _("%-28s : 期間 - %s ", "%s %s."), info[j],
+ report_magic_durations[info2[j]]);
+ prt(Dummy, k++, 15);
+
+ /* Every 20 entries (lines 2 to 21), start over */
+ if ((k == 22) && (j + 1 < i))
+ {
+ prt(_("-- 続く --", "-- more --"), k, 15);
+ inkey();
+ for (; k > 2; k--) prt("", k, 15);
+ }
+ }
+
+ /* Pause */
+ prt(_("[何かキーを押すとゲームに戻ります]", "[Press any key to continue]"), k, 13);
+ inkey();
+ screen_load();
+}
-/*!\r
- * @file selfinfo.h\r
- * @brief 自己分析機能用ヘッダファイル /\r
- * @author 2018 Deskull\r
- */\r
-\r
-extern void self_knowledge(void);\r
-extern void report_magics(void);\r
+/*!
+ * @file selfinfo.h
+ * @brief 自己分析機能用ヘッダファイル /
+ * @author 2018 Deskull
+ */
+
+extern void self_knowledge(void);
+extern void report_magics(void);
-#include "angband.h"
+#include "angband.h"
#include "avatar.h"
#include "spells-status.h"
#include "projection.h"
#include "spells.h"
/*!
- * @brief \83\82\83\93\83X\83^\81[\89ñ\95\9c\8f\88\97\9d
- * @param dir \95û\8cü(5\82È\82ç\82Î\83O\83\8d\81[\83o\83\8b\95Ï\90\94 target_col/target_row \82Ì\8dÀ\95W\82ð\96Ú\95W\82É\82·\82é)
- * @param dam \88Ð\97Í
- * @return \8dì\97p\82ª\8eÀ\8dÛ\82É\82 \82Á\82½\8fê\8d\87TRUE\82ð\95Ô\82·
+ * @brief モンスター回復処理
+ * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
+ * @param dam 威力
+ * @return 作用が実際にあった場合TRUEを返す
*/
bool heal_monster(DIRECTION dir, HIT_POINT dam)
{
}
/*!
- * @brief \83\82\83\93\83X\83^\81[\89Á\91¬\8f\88\97\9d
- * @param dir \95û\8cü(5\82È\82ç\82Î\83O\83\8d\81[\83o\83\8b\95Ï\90\94 target_col/target_row \82Ì\8dÀ\95W\82ð\96Ú\95W\82É\82·\82é)
- * @param power \8cø\97Í
- * @return \8dì\97p\82ª\8eÀ\8dÛ\82É\82 \82Á\82½\8fê\8d\87TRUE\82ð\95Ô\82·
+ * @brief モンスター加速処理
+ * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
+ * @param power 効力
+ * @return 作用が実際にあった場合TRUEを返す
*/
bool speed_monster(DIRECTION dir, int power)
{
}
/*!
- * @brief \83\82\83\93\83X\83^\81[\8c¸\91¬\8f\88\97\9d
- * @param dir \95û\8cü(5\82È\82ç\82Î\83O\83\8d\81[\83o\83\8b\95Ï\90\94 target_col/target_row \82Ì\8dÀ\95W\82ð\96Ú\95W\82É\82·\82é)
- * @param power \8cø\97Í
- * @return \8dì\97p\82ª\8eÀ\8dÛ\82É\82 \82Á\82½\8fê\8d\87TRUE\82ð\95Ô\82·
+ * @brief モンスター減速処理
+ * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
+ * @param power 効力
+ * @return 作用が実際にあった場合TRUEを返す
*/
bool slow_monster(DIRECTION dir, int power)
{
}
/*!
- * @brief \83\82\83\93\83X\83^\81[\8dÃ\96°\8f\88\97\9d
- * @param dir \95û\8cü(5\82È\82ç\82Î\83O\83\8d\81[\83o\83\8b\95Ï\90\94 target_col/target_row \82Ì\8dÀ\95W\82ð\96Ú\95W\82É\82·\82é)
- * @param power \8cø\97Í
- * @return \8dì\97p\82ª\8eÀ\8dÛ\82É\82 \82Á\82½\8fê\8d\87TRUE\82ð\95Ô\82·
+ * @brief モンスター催眠処理
+ * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
+ * @param power 効力
+ * @return 作用が実際にあった場合TRUEを返す
*/
bool sleep_monster(DIRECTION dir, int power)
{
}
/*!
- * @brief \83\82\83\93\83X\83^\81[\8dS\91©(STASIS)\8f\88\97\9d
- * @param dir \95û\8cü(5\82È\82ç\82Î\83O\83\8d\81[\83o\83\8b\95Ï\90\94 target_col/target_row \82Ì\8dÀ\95W\82ð\96Ú\95W\82É\82·\82é)
- * @return \8dì\97p\82ª\8eÀ\8dÛ\82É\82 \82Á\82½\8fê\8d\87TRUE\82ð\95Ô\82·
- * @details \88Ð\97Í\82Í\83v\83\8c\83C\83\84\81[\83\8c\83x\83\8b*2\82É\8cÅ\92è
+ * @brief モンスター拘束(STASIS)処理
+ * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
+ * @return 作用が実際にあった場合TRUEを返す
+ * @details 威力はプレイヤーレベル*2に固定
*/
bool stasis_monster(DIRECTION dir)
{
}
/*!
- * @brief \8e×\88«\82È\83\82\83\93\83X\83^\81[\8dS\91©(STASIS)\8f\88\97\9d
- * @param dir \95û\8cü(5\82È\82ç\82Î\83O\83\8d\81[\83o\83\8b\95Ï\90\94 target_col/target_row \82Ì\8dÀ\95W\82ð\96Ú\95W\82É\82·\82é)
- * @return \8dì\97p\82ª\8eÀ\8dÛ\82É\82 \82Á\82½\8fê\8d\87TRUE\82ð\95Ô\82·
- * @details \88Ð\97Í\82Í\83v\83\8c\83C\83\84\81[\83\8c\83x\83\8b*2\82É\8cÅ\92è
+ * @brief 邪悪なモンスター拘束(STASIS)処理
+ * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
+ * @return 作用が実際にあった場合TRUEを返す
+ * @details 威力はプレイヤーレベル*2に固定
*/
bool stasis_evil(DIRECTION dir)
{
}
/*!
- * @brief \83\82\83\93\83X\83^\81[\8d¬\97\90\8f\88\97\9d
- * @param dir \95û\8cü(5\82È\82ç\82Î\83O\83\8d\81[\83o\83\8b\95Ï\90\94 target_col/target_row \82Ì\8dÀ\95W\82ð\96Ú\95W\82É\82·\82é)
- * @param plev \83v\83\8c\83C\83\84\81[\83\8c\83x\83\8b(=\8cø\97Í)
- * @return \8dì\97p\82ª\8eÀ\8dÛ\82É\82 \82Á\82½\8fê\8d\87TRUE\82ð\95Ô\82·
+ * @brief モンスター混乱処理
+ * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
+ * @param plev プレイヤーレベル(=効力)
+ * @return 作用が実際にあった場合TRUEを返す
*/
bool confuse_monster(DIRECTION dir, PLAYER_LEVEL plev)
{
}
/*!
- * @brief \83\82\83\93\83X\83^\81[\9eN\9eO\8f\88\97\9d
- * @param dir \95û\8cü(5\82È\82ç\82Î\83O\83\8d\81[\83o\83\8b\95Ï\90\94 target_col/target_row \82Ì\8dÀ\95W\82ð\96Ú\95W\82É\82·\82é)
- * @param plev \83v\83\8c\83C\83\84\81[\83\8c\83x\83\8b(=\8cø\97Í)
- * @return \8dì\97p\82ª\8eÀ\8dÛ\82É\82 \82Á\82½\8fê\8d\87TRUE\82ð\95Ô\82·
+ * @brief モンスター朦朧処理
+ * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
+ * @param plev プレイヤーレベル(=効力)
+ * @return 作用が実際にあった場合TRUEを返す
*/
bool stun_monster(DIRECTION dir, PLAYER_LEVEL plev)
{
}
/*!
- * @brief \83`\83F\83\93\83W\83\82\83\93\83X\83^\81[\8f\88\97\9d
- * @param dir \95û\8cü(5\82È\82ç\82Î\83O\83\8d\81[\83o\83\8b\95Ï\90\94 target_col/target_row \82Ì\8dÀ\95W\82ð\96Ú\95W\82É\82·\82é)
- * @param power \8cø\97Í
- * @return \8dì\97p\82ª\8eÀ\8dÛ\82É\82 \82Á\82½\8fê\8d\87TRUE\82ð\95Ô\82·
+ * @brief チェンジモンスター処理
+ * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
+ * @param power 効力
+ * @return 作用が実際にあった場合TRUEを返す
*/
bool poly_monster(DIRECTION dir, int power)
{
}
/*!
- * @brief \83N\83\8d\81[\83\93\83\82\83\93\83X\83^\81[\8f\88\97\9d
- * @param dir \95û\8cü(5\82È\82ç\82Î\83O\83\8d\81[\83o\83\8b\95Ï\90\94 target_col/target_row \82Ì\8dÀ\95W\82ð\96Ú\95W\82É\82·\82é)
- * @return \8dì\97p\82ª\8eÀ\8dÛ\82É\82 \82Á\82½\8fê\8d\87TRUE\82ð\95Ô\82·
+ * @brief クローンモンスター処理
+ * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
+ * @return 作用が実際にあった場合TRUEを返す
*/
bool clone_monster(DIRECTION dir)
{
}
/*!
- * @brief \83\82\83\93\83X\83^\81[\8b°\8dQ\8f\88\97\9d
- * @param dir \95û\8cü(5\82È\82ç\82Î\83O\83\8d\81[\83o\83\8b\95Ï\90\94 target_col/target_row \82Ì\8dÀ\95W\82ð\96Ú\95W\82É\82·\82é)
- * @param plev \83v\83\8c\83C\83\84\81[\83\8c\83x\83\8b(=\8cø\97Í)
- * @return \8dì\97p\82ª\8eÀ\8dÛ\82É\82 \82Á\82½\8fê\8d\87TRUE\82ð\95Ô\82·
+ * @brief モンスター恐慌処理
+ * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
+ * @param plev プレイヤーレベル(=効力)
+ * @return 作用が実際にあった場合TRUEを返す
*/
bool fear_monster(DIRECTION dir, PLAYER_LEVEL plev)
{
}
/*!
-* @brief \89Ì\82Ì\92â\8e~\82ð\8f\88\97\9d\82·\82é / Stop singing if the player is a Bard
-* @return \82È\82µ
+* @brief 歌の停止を処理する / Stop singing if the player is a Bard
+* @return なし
*/
void stop_singing(void)
{
{
if (creature_ptr->timewalk)
{
- msg_print(_("\8aù\82É\8e\9e\82Í\8e~\82Ü\82Á\82Ä\82¢\82é\81B", "Time is already stopped."));
+ msg_print(_("既に時は止まっている。", "Time is already stopped."));
return (FALSE);
}
creature_ptr->timewalk = TRUE;
- msg_print(_("\81u\8e\9e\82æ\81I\81v", "You yell 'Time!'"));
+ msg_print(_("「時よ!」", "You yell 'Time!'"));
msg_print(NULL);
/* Hack */
}
/*!
- * @brief \83v\83\8c\83C\83\84\81[\82Ì\83q\83b\83g\83_\83C\83X\82ð\90U\82é / Role Hitpoints
- * @param options \83X\83y\83\8b\8b¤\92Ê\83I\83v\83V\83\87\83\93
- * @return \82È\82µ
+ * @brief プレイヤーのヒットダイスを振る / Role Hitpoints
+ * @param options スペル共通オプション
+ * @return なし
*/
void roll_hitdice(SPOP_FLAGS options)
{
{
if (options & SPOP_DEBUG)
{
- msg_format(_("\8c»\8dÝ\82Ì\91Ì\97Í\83\89\83\93\83N\82Í %d/100 \82Å\82·\81B", "Your life rate is %d/100 now."), percent);
+ msg_format(_("現在の体力ランクは %d/100 です。", "Your life rate is %d/100 now."), percent);
p_ptr->knowledge |= KNOW_HPRATE;
}
else
{
- msg_print(_("\91Ì\97Í\83\89\83\93\83N\82ª\95Ï\82í\82Á\82½\81B", "Life rate is changed."));
+ msg_print(_("体力ランクが変わった。", "Life rate is changed."));
p_ptr->knowledge &= ~(KNOW_HPRATE);
}
}
}
if (message)
{
- msg_print(_("\91Ì\92\86\82É\90¶\96½\97Í\82ª\96\9e\82¿\82 \82Ó\82ê\82Ä\82«\82½\81I", "You feel life flow through your body!"));
+ msg_print(_("体中に生命力が満ちあふれてきた!", "You feel life flow through your body!"));
}
restore_level();
(void)set_poisoned(0);
p_ptr->magic_num1[i] -= ((p_ptr->magic_num2[i] < 10) ? EATER_ROD_CHARGE * 3 : p_ptr->magic_num2[i] * EATER_ROD_CHARGE / 3)*k_info[k_idx].pval;
if (p_ptr->magic_num1[i] < 0) p_ptr->magic_num1[i] = 0;
}
- msg_print(_("\93ª\82ª\83n\83b\83L\83\8a\82Æ\82µ\82½\81B", "You feel your head clear."));
+ msg_print(_("頭がハッキリとした。", "You feel your head clear."));
p_ptr->window |= (PW_PLAYER);
ident = TRUE;
}
{
p_ptr->csp = p_ptr->msp;
p_ptr->csp_frac = 0;
- msg_print(_("\93ª\82ª\83n\83b\83L\83\8a\82Æ\82µ\82½\81B", "You feel your head clear."));
+ msg_print(_("頭がハッキリとした。", "You feel your head clear."));
p_ptr->redraw |= (PR_MANA);
p_ptr->window |= (PW_PLAYER);
p_ptr->window |= (PW_SPELL);
-
+
extern bool heal_monster(DIRECTION dir, HIT_POINT dam);
extern bool speed_monster(DIRECTION dir, int power);
extern bool slow_monster(DIRECTION dir, int power);
-#include "angband.h"\r
-#include "spells-summon.h"\r
-\r
-/*!\r
-* @brief トランプ魔法独自の召喚処理を行う / Handle summoning and failure of trump spells\r
-* @param num summon_specific()関数を呼び出す回数\r
-* @param pet ペット化として召喚されるか否か\r
-* @param y 召喚位置のy座標\r
-* @param x 召喚位置のx座標\r
-* @param lev 召喚レベル\r
-* @param type 召喚条件ID\r
-* @param mode モンスター生成条件フラグ\r
-* @return モンスターが(敵対も含めて)召還されたならばTRUEを返す。\r
-*/\r
-bool trump_summoning(int num, bool pet, POSITION y, POSITION x, DEPTH lev, int type, BIT_FLAGS mode)\r
-{\r
- PLAYER_LEVEL plev = p_ptr->lev;\r
-\r
- MONSTER_IDX who;\r
- int i;\r
- bool success = FALSE;\r
-\r
- /* Default level */\r
- if (!lev) lev = plev * 2 / 3 + randint1(plev / 2);\r
-\r
- if (pet)\r
- {\r
- /* Become pet */\r
- mode |= PM_FORCE_PET;\r
-\r
- /* Only sometimes allow unique monster */\r
- if (mode & PM_ALLOW_UNIQUE)\r
- {\r
- /* Forbid often */\r
- if (randint1(50 + plev) >= plev / 10)\r
- mode &= ~PM_ALLOW_UNIQUE;\r
- }\r
-\r
- /* Player is who summons */\r
- who = -1;\r
- }\r
- else\r
- {\r
- /* Prevent taming, allow unique monster */\r
- mode |= PM_NO_PET;\r
-\r
- /* Behave as if they appear by themselfs */\r
- who = 0;\r
- }\r
-\r
- for (i = 0; i < num; i++)\r
- {\r
- if (summon_specific(who, y, x, lev, type, mode, '\0'))\r
- success = TRUE;\r
- }\r
-\r
- if (!success)\r
- {\r
- msg_print(_("誰もあなたのカードの呼び声に答えない。", "Nobody answers to your Trump call."));\r
- }\r
-\r
- return success;\r
-}\r
-\r
-\r
-bool cast_summon_demon(int power)\r
-{\r
- u32b flg = 0L;\r
- bool pet = !one_in_(3);\r
-\r
- if (pet) flg |= PM_FORCE_PET;\r
- else flg |= PM_NO_PET;\r
- if (!(pet && (p_ptr->lev < 50))) flg |= PM_ALLOW_GROUP;\r
-\r
- if (summon_specific((pet ? -1 : 0), p_ptr->y, p_ptr->x, power, SUMMON_DEMON, flg, '\0'))\r
- {\r
- msg_print(_("硫黄の悪臭が充満した。", "The area fills with a stench of sulphur and brimstone."));\r
- if (pet)\r
- {\r
- msg_print(_("「ご用でございますか、ご主人様」", "'What is thy bidding... Master?'"));\r
- }\r
- else\r
- {\r
- msg_print(_("「卑しき者よ、我は汝の下僕にあらず! お前の魂を頂くぞ!」",\r
- "'NON SERVIAM! Wretch! I shall feast on thy mortal soul!'"));\r
- }\r
- }\r
- return TRUE;\r
-}\r
-\r
-\r
-/*!\r
-* @brief 悪魔領域のグレーターデーモン召喚に利用可能な死体かどうかを返す。 / An "item_tester_hook" for offer\r
-* @param o_ptr オブジェクト構造体の参照ポインタ\r
-* @return 生贄に使用可能な死体ならばTRUEを返す。\r
-*/\r
-bool item_tester_offer(object_type *o_ptr)\r
-{\r
- /* Flasks of oil are okay */\r
- if (o_ptr->tval != TV_CORPSE) return (FALSE);\r
- if (o_ptr->sval != SV_CORPSE) return (FALSE);\r
-\r
- if (my_strchr("pht", r_info[o_ptr->pval].d_char)) return (TRUE);\r
-\r
- /* Assume not okay */\r
- return (FALSE);\r
-}\r
-\r
-/*!\r
-* @brief 悪魔領域のグレーターデーモン召喚を処理する / Daemon spell Summon Greater Demon\r
-* @return 処理を実行したならばTRUEを返す。\r
-*/\r
-bool cast_summon_greater_demon(void)\r
-{\r
- PLAYER_LEVEL plev = p_ptr->lev;\r
- OBJECT_IDX item;\r
- concptr q, s;\r
- int summon_lev;\r
- object_type *o_ptr;\r
-\r
- item_tester_hook = item_tester_offer;\r
- q = _("どの死体を捧げますか? ", "Sacrifice which corpse? ");\r
- s = _("捧げられる死体を持っていない。", "You have nothing to scrifice.");\r
- o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR));\r
- if (!o_ptr) return FALSE;\r
-\r
- summon_lev = plev * 2 / 3 + r_info[o_ptr->pval].level;\r
-\r
- if (summon_specific(-1, p_ptr->y, p_ptr->x, summon_lev, SUMMON_HI_DEMON, (PM_ALLOW_GROUP | PM_FORCE_PET), '\0'))\r
- {\r
- msg_print(_("硫黄の悪臭が充満した。", "The area fills with a stench of sulphur and brimstone."));\r
- msg_print(_("「ご用でございますか、ご主人様」", "'What is thy bidding... Master?'"));\r
-\r
- /* Decrease the item (from the pack) */\r
- if (item >= 0)\r
- {\r
- inven_item_increase(item, -1);\r
- inven_item_describe(item);\r
- inven_item_optimize(item);\r
- }\r
-\r
- /* Decrease the item (from the floor) */\r
- else\r
- {\r
- floor_item_increase(0 - item, -1);\r
- floor_item_describe(0 - item);\r
- floor_item_optimize(0 - item);\r
- }\r
- }\r
- else\r
- {\r
- msg_print(_("悪魔は現れなかった。", "No Greater Demon arrive."));\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
-/*!\r
- * @brief 同族召喚(援軍)処理\r
- * @param level 召喚基準レベル\r
- * @param y 召喚先Y座標\r
- * @param x 召喚先X座標\r
- * @param mode 召喚オプション\r
- * @return ターンを消費した場合TRUEを返す\r
- */\r
-bool summon_kin_player(DEPTH level, POSITION y, POSITION x, BIT_FLAGS mode)\r
-{\r
- bool pet = (bool)(mode & PM_FORCE_PET);\r
- SYMBOL_CODE symbol = '\0';\r
- if (!pet) mode |= PM_NO_PET;\r
-\r
- switch (p_ptr->mimic_form)\r
- {\r
- case MIMIC_NONE:\r
- switch (p_ptr->prace)\r
- {\r
- case RACE_HUMAN:\r
- case RACE_AMBERITE:\r
- case RACE_BARBARIAN:\r
- case RACE_BEASTMAN:\r
- case RACE_DUNADAN:\r
- symbol = 'p';\r
- break;\r
- case RACE_HALF_ELF:\r
- case RACE_ELF:\r
- case RACE_HOBBIT:\r
- case RACE_GNOME:\r
- case RACE_DWARF:\r
- case RACE_HIGH_ELF:\r
- case RACE_NIBELUNG:\r
- case RACE_DARK_ELF:\r
- case RACE_MIND_FLAYER:\r
- case RACE_KUTAR:\r
- case RACE_S_FAIRY:\r
- symbol = 'h';\r
- break;\r
- case RACE_HALF_ORC:\r
- symbol = 'o';\r
- break;\r
- case RACE_HALF_TROLL:\r
- symbol = 'T';\r
- break;\r
- case RACE_HALF_OGRE:\r
- symbol = 'O';\r
- break;\r
- case RACE_HALF_GIANT:\r
- case RACE_HALF_TITAN:\r
- case RACE_CYCLOPS:\r
- symbol = 'P';\r
- break;\r
- case RACE_YEEK:\r
- symbol = 'y';\r
- break;\r
- case RACE_KLACKON:\r
- symbol = 'K';\r
- break;\r
- case RACE_KOBOLD:\r
- symbol = 'k';\r
- break;\r
- case RACE_IMP:\r
- if (one_in_(13)) symbol = 'U';\r
- else symbol = 'u';\r
- break;\r
- case RACE_DRACONIAN:\r
- symbol = 'd';\r
- break;\r
- case RACE_GOLEM:\r
- case RACE_ANDROID:\r
- symbol = 'g';\r
- break;\r
- case RACE_SKELETON:\r
- if (one_in_(13)) symbol = 'L';\r
- else symbol = 's';\r
- break;\r
- case RACE_ZOMBIE:\r
- symbol = 'z';\r
- break;\r
- case RACE_VAMPIRE:\r
- symbol = 'V';\r
- break;\r
- case RACE_SPECTRE:\r
- symbol = 'G';\r
- break;\r
- case RACE_SPRITE:\r
- symbol = 'I';\r
- break;\r
- case RACE_ENT:\r
- symbol = '#';\r
- break;\r
- case RACE_ANGEL:\r
- symbol = 'A';\r
- break;\r
- case RACE_DEMON:\r
- symbol = 'U';\r
- break;\r
- default:\r
- symbol = 'p';\r
- break;\r
- }\r
- break;\r
- case MIMIC_DEMON:\r
- if (one_in_(13)) symbol = 'U';\r
- else symbol = 'u';\r
- break;\r
- case MIMIC_DEMON_LORD:\r
- symbol = 'U';\r
- break;\r
- case MIMIC_VAMPIRE:\r
- symbol = 'V';\r
- break;\r
- }\r
- return summon_specific((pet ? -1 : 0), y, x, level, SUMMON_KIN, mode, symbol);\r
-}\r
-\r
-/*!\r
- * @brief サイバーデーモンの召喚\r
- * @param who 召喚主のモンスターID(0ならばプレイヤー)\r
- * @param y 召喚位置Y座標\r
- * @param x 召喚位置X座標\r
- * @return 作用が実際にあった場合TRUEを返す\r
- */\r
-int summon_cyber(MONSTER_IDX who, POSITION y, POSITION x)\r
-{\r
- int i;\r
- int max_cyber = (easy_band ? 1 : (dun_level / 50) + randint1(2));\r
- int count = 0;\r
- BIT_FLAGS mode = PM_ALLOW_GROUP;\r
-\r
- /* Summoned by a monster */\r
- if (who > 0)\r
- {\r
- monster_type *m_ptr = &m_list[who];\r
- if (is_pet(m_ptr)) mode |= PM_FORCE_PET;\r
- }\r
-\r
- if (max_cyber > 4) max_cyber = 4;\r
-\r
- for (i = 0; i < max_cyber; i++)\r
- {\r
- count += summon_specific(who, y, x, 100, SUMMON_CYBER, mode, '\0');\r
- }\r
-\r
- return count;\r
+#include "angband.h"
+#include "spells-summon.h"
+
+/*!
+* @brief トランプ魔法独自の召喚処理を行う / Handle summoning and failure of trump spells
+* @param num summon_specific()関数を呼び出す回数
+* @param pet ペット化として召喚されるか否か
+* @param y 召喚位置のy座標
+* @param x 召喚位置のx座標
+* @param lev 召喚レベル
+* @param type 召喚条件ID
+* @param mode モンスター生成条件フラグ
+* @return モンスターが(敵対も含めて)召還されたならばTRUEを返す。
+*/
+bool trump_summoning(int num, bool pet, POSITION y, POSITION x, DEPTH lev, int type, BIT_FLAGS mode)
+{
+ PLAYER_LEVEL plev = p_ptr->lev;
+
+ MONSTER_IDX who;
+ int i;
+ bool success = FALSE;
+
+ /* Default level */
+ if (!lev) lev = plev * 2 / 3 + randint1(plev / 2);
+
+ if (pet)
+ {
+ /* Become pet */
+ mode |= PM_FORCE_PET;
+
+ /* Only sometimes allow unique monster */
+ if (mode & PM_ALLOW_UNIQUE)
+ {
+ /* Forbid often */
+ if (randint1(50 + plev) >= plev / 10)
+ mode &= ~PM_ALLOW_UNIQUE;
+ }
+
+ /* Player is who summons */
+ who = -1;
+ }
+ else
+ {
+ /* Prevent taming, allow unique monster */
+ mode |= PM_NO_PET;
+
+ /* Behave as if they appear by themselfs */
+ who = 0;
+ }
+
+ for (i = 0; i < num; i++)
+ {
+ if (summon_specific(who, y, x, lev, type, mode, '\0'))
+ success = TRUE;
+ }
+
+ if (!success)
+ {
+ msg_print(_("誰もあなたのカードの呼び声に答えない。", "Nobody answers to your Trump call."));
+ }
+
+ return success;
+}
+
+
+bool cast_summon_demon(int power)
+{
+ u32b flg = 0L;
+ bool pet = !one_in_(3);
+
+ if (pet) flg |= PM_FORCE_PET;
+ else flg |= PM_NO_PET;
+ if (!(pet && (p_ptr->lev < 50))) flg |= PM_ALLOW_GROUP;
+
+ if (summon_specific((pet ? -1 : 0), p_ptr->y, p_ptr->x, power, SUMMON_DEMON, flg, '\0'))
+ {
+ msg_print(_("硫黄の悪臭が充満した。", "The area fills with a stench of sulphur and brimstone."));
+ if (pet)
+ {
+ msg_print(_("「ご用でございますか、ご主人様」", "'What is thy bidding... Master?'"));
+ }
+ else
+ {
+ msg_print(_("「卑しき者よ、我は汝の下僕にあらず! お前の魂を頂くぞ!」",
+ "'NON SERVIAM! Wretch! I shall feast on thy mortal soul!'"));
+ }
+ }
+ return TRUE;
+}
+
+
+/*!
+* @brief 悪魔領域のグレーターデーモン召喚に利用可能な死体かどうかを返す。 / An "item_tester_hook" for offer
+* @param o_ptr オブジェクト構造体の参照ポインタ
+* @return 生贄に使用可能な死体ならばTRUEを返す。
+*/
+bool item_tester_offer(object_type *o_ptr)
+{
+ /* Flasks of oil are okay */
+ if (o_ptr->tval != TV_CORPSE) return (FALSE);
+ if (o_ptr->sval != SV_CORPSE) return (FALSE);
+
+ if (my_strchr("pht", r_info[o_ptr->pval].d_char)) return (TRUE);
+
+ /* Assume not okay */
+ return (FALSE);
+}
+
+/*!
+* @brief 悪魔領域のグレーターデーモン召喚を処理する / Daemon spell Summon Greater Demon
+* @return 処理を実行したならばTRUEを返す。
+*/
+bool cast_summon_greater_demon(void)
+{
+ PLAYER_LEVEL plev = p_ptr->lev;
+ OBJECT_IDX item;
+ concptr q, s;
+ int summon_lev;
+ object_type *o_ptr;
+
+ item_tester_hook = item_tester_offer;
+ q = _("どの死体を捧げますか? ", "Sacrifice which corpse? ");
+ s = _("捧げられる死体を持っていない。", "You have nothing to scrifice.");
+ o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR));
+ if (!o_ptr) return FALSE;
+
+ summon_lev = plev * 2 / 3 + r_info[o_ptr->pval].level;
+
+ if (summon_specific(-1, p_ptr->y, p_ptr->x, summon_lev, SUMMON_HI_DEMON, (PM_ALLOW_GROUP | PM_FORCE_PET), '\0'))
+ {
+ msg_print(_("硫黄の悪臭が充満した。", "The area fills with a stench of sulphur and brimstone."));
+ msg_print(_("「ご用でございますか、ご主人様」", "'What is thy bidding... Master?'"));
+
+ /* Decrease the item (from the pack) */
+ if (item >= 0)
+ {
+ inven_item_increase(item, -1);
+ inven_item_describe(item);
+ inven_item_optimize(item);
+ }
+
+ /* Decrease the item (from the floor) */
+ else
+ {
+ floor_item_increase(0 - item, -1);
+ floor_item_describe(0 - item);
+ floor_item_optimize(0 - item);
+ }
+ }
+ else
+ {
+ msg_print(_("悪魔は現れなかった。", "No Greater Demon arrive."));
+ }
+
+ return TRUE;
+}
+
+/*!
+ * @brief 同族召喚(援軍)処理
+ * @param level 召喚基準レベル
+ * @param y 召喚先Y座標
+ * @param x 召喚先X座標
+ * @param mode 召喚オプション
+ * @return ターンを消費した場合TRUEを返す
+ */
+bool summon_kin_player(DEPTH level, POSITION y, POSITION x, BIT_FLAGS mode)
+{
+ bool pet = (bool)(mode & PM_FORCE_PET);
+ SYMBOL_CODE symbol = '\0';
+ if (!pet) mode |= PM_NO_PET;
+
+ switch (p_ptr->mimic_form)
+ {
+ case MIMIC_NONE:
+ switch (p_ptr->prace)
+ {
+ case RACE_HUMAN:
+ case RACE_AMBERITE:
+ case RACE_BARBARIAN:
+ case RACE_BEASTMAN:
+ case RACE_DUNADAN:
+ symbol = 'p';
+ break;
+ case RACE_HALF_ELF:
+ case RACE_ELF:
+ case RACE_HOBBIT:
+ case RACE_GNOME:
+ case RACE_DWARF:
+ case RACE_HIGH_ELF:
+ case RACE_NIBELUNG:
+ case RACE_DARK_ELF:
+ case RACE_MIND_FLAYER:
+ case RACE_KUTAR:
+ case RACE_S_FAIRY:
+ symbol = 'h';
+ break;
+ case RACE_HALF_ORC:
+ symbol = 'o';
+ break;
+ case RACE_HALF_TROLL:
+ symbol = 'T';
+ break;
+ case RACE_HALF_OGRE:
+ symbol = 'O';
+ break;
+ case RACE_HALF_GIANT:
+ case RACE_HALF_TITAN:
+ case RACE_CYCLOPS:
+ symbol = 'P';
+ break;
+ case RACE_YEEK:
+ symbol = 'y';
+ break;
+ case RACE_KLACKON:
+ symbol = 'K';
+ break;
+ case RACE_KOBOLD:
+ symbol = 'k';
+ break;
+ case RACE_IMP:
+ if (one_in_(13)) symbol = 'U';
+ else symbol = 'u';
+ break;
+ case RACE_DRACONIAN:
+ symbol = 'd';
+ break;
+ case RACE_GOLEM:
+ case RACE_ANDROID:
+ symbol = 'g';
+ break;
+ case RACE_SKELETON:
+ if (one_in_(13)) symbol = 'L';
+ else symbol = 's';
+ break;
+ case RACE_ZOMBIE:
+ symbol = 'z';
+ break;
+ case RACE_VAMPIRE:
+ symbol = 'V';
+ break;
+ case RACE_SPECTRE:
+ symbol = 'G';
+ break;
+ case RACE_SPRITE:
+ symbol = 'I';
+ break;
+ case RACE_ENT:
+ symbol = '#';
+ break;
+ case RACE_ANGEL:
+ symbol = 'A';
+ break;
+ case RACE_DEMON:
+ symbol = 'U';
+ break;
+ default:
+ symbol = 'p';
+ break;
+ }
+ break;
+ case MIMIC_DEMON:
+ if (one_in_(13)) symbol = 'U';
+ else symbol = 'u';
+ break;
+ case MIMIC_DEMON_LORD:
+ symbol = 'U';
+ break;
+ case MIMIC_VAMPIRE:
+ symbol = 'V';
+ break;
+ }
+ return summon_specific((pet ? -1 : 0), y, x, level, SUMMON_KIN, mode, symbol);
+}
+
+/*!
+ * @brief サイバーデーモンの召喚
+ * @param who 召喚主のモンスターID(0ならばプレイヤー)
+ * @param y 召喚位置Y座標
+ * @param x 召喚位置X座標
+ * @return 作用が実際にあった場合TRUEを返す
+ */
+int summon_cyber(MONSTER_IDX who, POSITION y, POSITION x)
+{
+ int i;
+ int max_cyber = (easy_band ? 1 : (dun_level / 50) + randint1(2));
+ int count = 0;
+ BIT_FLAGS mode = PM_ALLOW_GROUP;
+
+ /* Summoned by a monster */
+ if (who > 0)
+ {
+ monster_type *m_ptr = &m_list[who];
+ if (is_pet(m_ptr)) mode |= PM_FORCE_PET;
+ }
+
+ if (max_cyber > 4) max_cyber = 4;
+
+ for (i = 0; i < max_cyber; i++)
+ {
+ count += summon_specific(who, y, x, 100, SUMMON_CYBER, mode, '\0');
+ }
+
+ return count;
}
\ No newline at end of file
-#pragma once\r
-#include "monster.h"\r
-\r
-extern bool summon_specific(MONSTER_IDX who, POSITION y1, POSITION x1, DEPTH lev, int type, BIT_FLAGS mode, SYMBOL_CODE symbol);\r
-extern bool summon_named_creature(MONSTER_IDX who, POSITION oy, POSITION ox, MONRACE_IDX r_idx, BIT_FLAGS mode);\r
-\r
-extern bool trump_summoning(int num, bool pet, POSITION y, POSITION x, DEPTH lev, int type, BIT_FLAGS mode);\r
-extern bool cast_summon_demon(int power);\r
-extern bool item_tester_offer(object_type *o_ptr);\r
-extern bool cast_summon_greater_demon(void);\r
-extern bool summon_kin_player(DEPTH level, POSITION y, POSITION x, BIT_FLAGS mode);\r
-extern int summon_cyber(MONSTER_IDX who, POSITION y, POSITION x);\r
-\r
+#pragma once
+#include "monster.h"
+
+extern bool summon_specific(MONSTER_IDX who, POSITION y1, POSITION x1, DEPTH lev, int type, BIT_FLAGS mode, SYMBOL_CODE symbol);
+extern bool summon_named_creature(MONSTER_IDX who, POSITION oy, POSITION ox, MONRACE_IDX r_idx, BIT_FLAGS mode);
+
+extern bool trump_summoning(int num, bool pet, POSITION y, POSITION x, DEPTH lev, int type, BIT_FLAGS mode);
+extern bool cast_summon_demon(int power);
+extern bool item_tester_offer(object_type *o_ptr);
+extern bool cast_summon_greater_demon(void);
+extern bool summon_kin_player(DEPTH level, POSITION y, POSITION x, BIT_FLAGS mode);
+extern int summon_cyber(MONSTER_IDX who, POSITION y, POSITION x);
+
-\r
-/*\r
- * Store types\r
- */\r
-#define STORE_GENERAL 0 /*!< \93X\95Ü\82Ì\8eí\97Þ: \8eG\89Ý\89® */\r
-#define STORE_ARMOURY 1 /*!< \93X\95Ü\82Ì\8eí\97Þ: \96h\8bï\89® */\r
-#define STORE_WEAPON 2 /*!< \93X\95Ü\82Ì\8eí\97Þ: \95\90\8aí\89® */\r
-#define STORE_TEMPLE 3 /*!< \93X\95Ü\82Ì\8eí\97Þ: \8e\9b\89@ */\r
-#define STORE_ALCHEMIST 4 /*!< \93X\95Ü\82Ì\8eí\97Þ: \98B\8bà\8fp\82Ì\93X */\r
-#define STORE_MAGIC 5 /*!< \93X\95Ü\82Ì\8eí\97Þ: \96\82\93¹\8bï\89® */\r
-#define STORE_BLACK 6 /*!< \93X\95Ü\82Ì\8eí\97Þ: \83u\83\89\83b\83N\81E\83}\81[\83P\83b\83g */\r
-#define STORE_HOME 7 /*!< \93X\95Ü\82Ì\8eí\97Þ: \89ä\82ª\89Æ */\r
-#define STORE_BOOK 8 /*!< \93X\95Ü\82Ì\8eí\97Þ: \8f\91\93X */\r
-#define STORE_MUSEUM 9 /*!< \93X\95Ü\82Ì\8eí\97Þ: \94\8e\95¨\8aÙ */\r
-#define MAX_STORES 10 /*!< store.c\97p\82Ì\93X\95Ü\82Ì\8eí\97Þ\8dÅ\91å\90\94 / Total number of stores (see "store.c", etc) */\r
-\r
-#define MAX_OWNERS 32 /*!< \8ae\93X\95Ü\96\88\82Ì\93X\8eå\92è\8b`\8dÅ\91å\90\94 / Total number of owners per store (see "store.c", etc) */\r
-\r
- /*\r
- * Store constants\r
- */\r
-#define STORE_INVEN_MAX 24 /* Max number of discrete objs in inven */\r
-#define STORE_CHOICES 48 /* Number of items to choose stock from */\r
-#define STORE_OBJ_LEVEL 5 /* Magic Level for normal stores */\r
-#define STORE_TURNOVER 9 /* Normal shop turnover, per day */\r
-#define STORE_MIN_KEEP 6 /* Min slots to "always" keep full */\r
-#define STORE_MAX_KEEP 18 /* Max slots to "always" keep full */\r
-#define STORE_SHUFFLE 21 /* 1/Chance (per day) of an owner changing */\r
-#define STORE_TICKS 1000 /* Number of ticks between turnovers */\r
-\r
-/* store.c */\r
-extern bool combine_and_reorder_home(int store_num);\r
-extern void do_cmd_store(void);\r
-extern void store_shuffle(int which);\r
-extern void store_maint(int town_num, int store_num);\r
-extern void store_init(int town_num, int store_num);\r
-extern void move_to_black_market(object_type * o_ptr);\r
-\r
-extern const owner_type owners[MAX_STORES][MAX_OWNERS];\r
-\r
-extern byte store_table[MAX_STORES][STORE_CHOICES][2];\r
-\r
-\r
-\r
+
+/*
+ * Store types
+ */
+#define STORE_GENERAL 0 /*!< 店舗の種類: 雑貨屋 */
+#define STORE_ARMOURY 1 /*!< 店舗の種類: 防具屋 */
+#define STORE_WEAPON 2 /*!< 店舗の種類: 武器屋 */
+#define STORE_TEMPLE 3 /*!< 店舗の種類: 寺院 */
+#define STORE_ALCHEMIST 4 /*!< 店舗の種類: 錬金術の店 */
+#define STORE_MAGIC 5 /*!< 店舗の種類: 魔道具屋 */
+#define STORE_BLACK 6 /*!< 店舗の種類: ブラック・マーケット */
+#define STORE_HOME 7 /*!< 店舗の種類: 我が家 */
+#define STORE_BOOK 8 /*!< 店舗の種類: 書店 */
+#define STORE_MUSEUM 9 /*!< 店舗の種類: 博物館 */
+#define MAX_STORES 10 /*!< store.c用の店舗の種類最大数 / Total number of stores (see "store.c", etc) */
+
+#define MAX_OWNERS 32 /*!< 各店舗毎の店主定義最大数 / Total number of owners per store (see "store.c", etc) */
+
+ /*
+ * Store constants
+ */
+#define STORE_INVEN_MAX 24 /* Max number of discrete objs in inven */
+#define STORE_CHOICES 48 /* Number of items to choose stock from */
+#define STORE_OBJ_LEVEL 5 /* Magic Level for normal stores */
+#define STORE_TURNOVER 9 /* Normal shop turnover, per day */
+#define STORE_MIN_KEEP 6 /* Min slots to "always" keep full */
+#define STORE_MAX_KEEP 18 /* Max slots to "always" keep full */
+#define STORE_SHUFFLE 21 /* 1/Chance (per day) of an owner changing */
+#define STORE_TICKS 1000 /* Number of ticks between turnovers */
+
+/* store.c */
+extern bool combine_and_reorder_home(int store_num);
+extern void do_cmd_store(void);
+extern void store_shuffle(int which);
+extern void store_maint(int town_num, int store_num);
+extern void store_init(int town_num, int store_num);
+extern void move_to_black_market(object_type * o_ptr);
+
+extern const owner_type owners[MAX_STORES][MAX_OWNERS];
+
+extern byte store_table[MAX_STORES][STORE_CHOICES][2];
+
+
+
-#include "angband.h"\r
-#include "floor.h"\r
-#include "trap.h"\r
-#include "player-damage.h"\r
-#include "projection.h"\r
-#include "spells-summon.h"\r
-#include "quest.h"\r
-#include "artifact.h"\r
-\r
-static s16b normal_traps[MAX_NORMAL_TRAPS];\r
-\r
-\r
-/*!\r
-* @brief タグに従って、基本トラップテーブルを初期化する / Initialize arrays for normal traps\r
-* @return なし\r
-*/\r
-void init_normal_traps(void)\r
-{\r
- int cur_trap = 0;\r
-\r
- normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_TRAPDOOR");\r
- normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_PIT");\r
- normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_SPIKED_PIT");\r
- normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_POISON_PIT");\r
- normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_TY_CURSE");\r
- normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_TELEPORT");\r
- normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_FIRE");\r
- normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_ACID");\r
- normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_SLOW");\r
- normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_LOSE_STR");\r
- normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_LOSE_DEX");\r
- normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_LOSE_CON");\r
- normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_BLIND");\r
- normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_CONFUSE");\r
- normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_POISON");\r
- normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_SLEEP");\r
- normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_TRAPS");\r
- normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_ALARM");\r
-}\r
-\r
-/*!\r
-* @brief 基本トラップをランダムに選択する /\r
-* Get random trap\r
-* @return 選択したトラップのID\r
-* @details\r
-* This routine should be redone to reflect trap "level".\n\r
-* That is, it does not make sense to have spiked pits at 50 feet.\n\r
-* Actually, it is not this routine, but the "trap instantiation"\n\r
-* code, which should also check for "trap doors" on quest levels.\n\r
-*/\r
-FEAT_IDX choose_random_trap(void)\r
-{\r
- FEAT_IDX feat;\r
-\r
- /* Pick a trap */\r
- while (1)\r
- {\r
- /* Hack -- pick a trap */\r
- feat = normal_traps[randint0(MAX_NORMAL_TRAPS)];\r
-\r
- /* Accept non-trapdoors */\r
- if (!have_flag(f_info[feat].flags, FF_MORE)) break;\r
-\r
- /* Hack -- no trap doors on special levels */\r
- if (p_ptr->inside_arena || quest_number(dun_level)) continue;\r
-\r
- /* Hack -- no trap doors on the deepest level */\r
- if (dun_level >= d_info[p_ptr->dungeon_idx].maxdepth) continue;\r
-\r
- break;\r
- }\r
-\r
- return feat;\r
-}\r
-\r
-/*!\r
-* @brief マスに存在するトラップを秘匿する /\r
-* Disclose an invisible trap\r
-* @param y 秘匿したいマスのY座標\r
-* @param x 秘匿したいマスのX座標\r
-* @return なし\r
-*/\r
-void disclose_grid(POSITION y, POSITION x)\r
-{\r
- cave_type *c_ptr = &cave[y][x];\r
-\r
- if (cave_have_flag_grid(c_ptr, FF_SECRET))\r
- {\r
- /* No longer hidden */\r
- cave_alter_feat(y, x, FF_SECRET);\r
- }\r
- else if (c_ptr->mimic)\r
- {\r
- /* No longer hidden */\r
- c_ptr->mimic = 0;\r
-\r
- note_spot(y, x);\r
- lite_spot(y, x);\r
- }\r
-}\r
-\r
-/*!\r
-* @brief マスをトラップを配置する /\r
-* The location must be a legal, naked, floor grid.\r
-* @param y 配置したいマスのY座標\r
-* @param x 配置したいマスのX座標\r
-* @return\r
-* Note that all traps start out as "invisible" and "untyped", and then\n\r
-* when they are "discovered" (by detecting them or setting them off),\n\r
-* the trap is "instantiated" as a visible, "typed", trap.\n\r
-*/\r
-void place_trap(POSITION y, POSITION x)\r
-{\r
- cave_type *c_ptr = &cave[y][x];\r
-\r
- /* Paranoia -- verify location */\r
- if (!in_bounds(y, x)) return;\r
-\r
- /* Require empty, clean, floor grid */\r
- if (!cave_clean_bold(y, x)) return;\r
-\r
- /* Place an invisible trap */\r
- c_ptr->mimic = c_ptr->feat;\r
- c_ptr->feat = choose_random_trap();\r
-}\r
-\r
-\r
-\r
-/*!\r
-* @brief プレイヤーへのトラップ命中判定 /\r
-* Determine if a trap affects the player.\r
-* @param power 基本回避難度\r
-* @return トラップが命中した場合TRUEを返す。\r
-* @details\r
-* Always miss 5% of the time, Always hit 5% of the time.\r
-* Otherwise, match trap power against player armor.\r
-*/\r
-static int check_hit(int power)\r
-{\r
- int k;\r
- ARMOUR_CLASS ac;\r
-\r
- /* Percentile dice */\r
- k = randint0(100);\r
-\r
- /* Hack -- 5% hit, 5% miss */\r
- if (k < 10) return (k < 5);\r
-\r
- if (p_ptr->pseikaku == SEIKAKU_NAMAKE)\r
- if (one_in_(20)) return (TRUE);\r
-\r
- /* Paranoia -- No power */\r
- if (power <= 0) return (FALSE);\r
-\r
- /* Total armor */\r
- ac = p_ptr->ac + p_ptr->to_a;\r
-\r
- /* Power competes against Armor */\r
- if (randint1(power) > ((ac * 3) / 4)) return (TRUE);\r
-\r
- /* Assume miss */\r
- return (FALSE);\r
-}\r
-\r
-\r
-/*!\r
-* @brief 落とし穴系トラップの判定とプレイヤーの被害処理\r
-* @param trap_feat_type トラップの種別ID\r
-* @return なし\r
-*/\r
-static void hit_trap_pit(int trap_feat_type)\r
-{\r
- HIT_POINT dam;\r
- concptr trap_name = "";\r
- concptr spike_name = "";\r
-\r
- switch (trap_feat_type)\r
- {\r
- case TRAP_PIT:\r
- trap_name = _("落とし穴", "a pit trap");\r
- break;\r
- case TRAP_SPIKED_PIT:\r
- trap_name = _("スパイクが敷かれた落とし穴", "a spiked pit");\r
- spike_name = _("スパイク", "spikes");\r
- break;\r
- case TRAP_POISON_PIT:\r
- trap_name = _("スパイクが敷かれた落とし穴", "a spiked pit");\r
- spike_name = _("毒を塗られたスパイク", "poisonous spikes");\r
- break;\r
- default:\r
- return;\r
- }\r
-\r
- if (p_ptr->levitation)\r
- {\r
- msg_format(_("%sを飛び越えた。", "You fly over %s."), trap_name);\r
- return;\r
- }\r
-\r
- msg_format(_("%sに落ちてしまった!", "You have fallen into %s!"), trap_name);\r
-\r
- /* Base damage */\r
- dam = damroll(2, 6);\r
-\r
- /* Extra spike damage */\r
- if ((trap_feat_type == TRAP_SPIKED_PIT || trap_feat_type == TRAP_POISON_PIT) &&\r
- one_in_(2))\r
- {\r
- msg_format(_("%sが刺さった!", "You are impaled on %s!"), spike_name);\r
-\r
- dam = dam * 2;\r
- (void)set_cut(p_ptr->cut + randint1(dam));\r
-\r
- if (trap_feat_type == TRAP_POISON_PIT) {\r
- if (p_ptr->resist_pois || IS_OPPOSE_POIS())\r
- {\r
- msg_print(_("しかし毒の影響はなかった!", "The poison does not affect you!"));\r
- }\r
- else\r
- {\r
- dam = dam * 2;\r
- (void)set_poisoned(p_ptr->poisoned + randint1(dam));\r
- }\r
- }\r
- }\r
-\r
- take_hit(DAMAGE_NOESCAPE, dam, trap_name, -1);\r
-}\r
-\r
-/*!\r
-* @brief ダーツ系トラップ(通常ダメージ)の判定とプレイヤーの被害処理\r
-* @return ダーツが命中した場合TRUEを返す\r
-*/\r
-static bool hit_trap_dart(void)\r
-{\r
- bool hit = FALSE;\r
-\r
- if (check_hit(125))\r
- {\r
- msg_print(_("小さなダーツが飛んできて刺さった!", "A small dart hits you!"));\r
- take_hit(DAMAGE_ATTACK, damroll(1, 4), _("ダーツの罠", "a dart trap"), -1);\r
- if (!CHECK_MULTISHADOW()) hit = TRUE;\r
- }\r
- else\r
- {\r
- msg_print(_("小さなダーツが飛んできた!が、運良く当たらなかった。", "A small dart barely misses you."));\r
- }\r
-\r
- return hit;\r
-}\r
-\r
-/*!\r
-* @brief ダーツ系トラップ(通常ダメージ+能力値減少)の判定とプレイヤーの被害処理\r
-* @param stat 低下する能力値ID\r
-* @return なし\r
-*/\r
-static void hit_trap_lose_stat(int stat)\r
-{\r
- if (hit_trap_dart())\r
- {\r
- do_dec_stat(stat);\r
- }\r
-}\r
-\r
-/*!\r
-* @brief ダーツ系トラップ(通常ダメージ+減速)の判定とプレイヤーの被害処理\r
-* @return なし\r
-*/\r
-static void hit_trap_slow(void)\r
-{\r
- if (hit_trap_dart())\r
- {\r
- set_slow(p_ptr->slow + randint0(20) + 20, FALSE);\r
- }\r
-}\r
-\r
-/*!\r
-* @brief ダーツ系トラップ(通常ダメージ+状態異常)の判定とプレイヤーの被害処理\r
-* @param trap_message メッセージの補完文字列\r
-* @param resist 状態異常に抵抗する判定が出たならTRUE\r
-* @param set_status 状態異常を指定する関数ポインタ\r
-* @param turn 状態異常の追加ターン量\r
-* @return なし\r
-*/\r
-static void hit_trap_set_abnormal_status(concptr trap_message, bool resist, bool(*set_status)(IDX), IDX turn_aux)\r
-{\r
- msg_print(trap_message);\r
- if (!resist)\r
- {\r
- set_status(turn_aux);\r
- }\r
-}\r
-\r
-/*!\r
-* @brief プレイヤーへのトラップ作動処理メインルーチン /\r
-* Handle player hitting a real trap\r
-* @param break_trap 作動後のトラップ破壊が確定しているならばTRUE\r
-* @return なし\r
-*/\r
-void hit_trap(bool break_trap)\r
-{\r
- int i, num, dam;\r
- POSITION x = p_ptr->x, y = p_ptr->y;\r
-\r
- /* Get the cave grid */\r
- cave_type *c_ptr = &cave[y][x];\r
- feature_type *f_ptr = &f_info[c_ptr->feat];\r
- int trap_feat_type = have_flag(f_ptr->flags, FF_TRAP) ? f_ptr->subtype : NOT_TRAP;\r
- concptr name = _("トラップ", "a trap");\r
-\r
- disturb(FALSE, TRUE);\r
-\r
- cave_alter_feat(y, x, FF_HIT_TRAP);\r
-\r
- /* Analyze */\r
- switch (trap_feat_type)\r
- {\r
- case TRAP_TRAPDOOR:\r
- {\r
- if (p_ptr->levitation)\r
- {\r
- msg_print(_("落とし戸を飛び越えた。", "You fly over a trap door."));\r
- }\r
- else\r
- {\r
- msg_print(_("落とし戸に落ちた!", "You have fallen through a trap door!"));\r
- if ((p_ptr->pseikaku == SEIKAKU_COMBAT) || (inventory[INVEN_BOW].name1 == ART_CRIMSON))\r
- msg_print(_("くっそ~!", ""));\r
- else if((p_ptr->pseikaku == SEIKAKU_CHARGEMAN))\r
- msg_print(_("ジュラル星人の仕業に違いない!", ""));\r
-\r
-\r
- sound(SOUND_FALL);\r
- dam = damroll(2, 8);\r
- name = _("落とし戸", "a trap door");\r
-\r
- take_hit(DAMAGE_NOESCAPE, dam, name, -1);\r
-\r
- /* Still alive and autosave enabled */\r
- if (autosave_l && (p_ptr->chp >= 0))\r
- do_cmd_save_game(TRUE);\r
-\r
- do_cmd_write_nikki(NIKKI_BUNSHOU, 0, _("落とし戸に落ちた", "You have fallen through a trap door!"));\r
- prepare_change_floor_mode(CFM_SAVE_FLOORS | CFM_DOWN | CFM_RAND_PLACE | CFM_RAND_CONNECT);\r
-\r
- /* Leaving */\r
- p_ptr->leaving = TRUE;\r
- }\r
- break;\r
- }\r
-\r
- case TRAP_PIT:\r
- case TRAP_SPIKED_PIT:\r
- case TRAP_POISON_PIT:\r
- {\r
- hit_trap_pit(trap_feat_type);\r
- break;\r
- }\r
-\r
- case TRAP_TY_CURSE:\r
- {\r
- msg_print(_("何かがピカッと光った!", "There is a flash of shimmering light!"));\r
- num = 2 + randint1(3);\r
- for (i = 0; i < num; i++)\r
- {\r
- (void)summon_specific(0, y, x, dun_level, 0, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0');\r
- }\r
-\r
- if (dun_level > randint1(100)) /* No nasty effect for low levels */\r
- {\r
- bool stop_ty = FALSE;\r
- int count = 0;\r
-\r
- do\r
- {\r
- stop_ty = activate_ty_curse(stop_ty, &count);\r
- } while (one_in_(6));\r
- }\r
- break;\r
- }\r
-\r
- case TRAP_TELEPORT:\r
- {\r
- msg_print(_("テレポート・トラップにひっかかった!", "You hit a teleport trap!"));\r
- teleport_player(100, TELEPORT_PASSIVE);\r
- break;\r
- }\r
-\r
- case TRAP_FIRE:\r
- {\r
- msg_print(_("炎に包まれた!", "You are enveloped in flames!"));\r
- dam = damroll(4, 6);\r
- (void)fire_dam(dam, _("炎のトラップ", "a fire trap"), -1, FALSE);\r
- break;\r
- }\r
-\r
- case TRAP_ACID:\r
- {\r
- msg_print(_("酸が吹きかけられた!", "You are splashed with acid!"));\r
- dam = damroll(4, 6);\r
- (void)acid_dam(dam, _("酸のトラップ", "an acid trap"), -1, FALSE);\r
- break;\r
- }\r
-\r
- case TRAP_SLOW:\r
- {\r
- hit_trap_slow();\r
- break;\r
- }\r
-\r
- case TRAP_LOSE_STR:\r
- {\r
- hit_trap_lose_stat(A_STR);\r
- break;\r
- }\r
-\r
- case TRAP_LOSE_DEX:\r
- {\r
- hit_trap_lose_stat(A_DEX);\r
- break;\r
- }\r
-\r
- case TRAP_LOSE_CON:\r
- {\r
- hit_trap_lose_stat(A_CON);\r
- break;\r
- }\r
-\r
- case TRAP_BLIND:\r
- {\r
- hit_trap_set_abnormal_status(\r
- _("黒いガスに包み込まれた!", "A black gas surrounds you!"),\r
- p_ptr->resist_blind,\r
- set_blind, p_ptr->blind + (TIME_EFFECT)randint0(50) + 25);\r
- break;\r
- }\r
-\r
- case TRAP_CONFUSE:\r
- {\r
- hit_trap_set_abnormal_status(\r
- _("きらめくガスに包み込まれた!", "A gas of scintillating colors surrounds you!"),\r
- p_ptr->resist_conf,\r
- set_confused, p_ptr->confused + (TIME_EFFECT)randint0(20) + 10);\r
- break;\r
- }\r
-\r
- case TRAP_POISON:\r
- {\r
- hit_trap_set_abnormal_status(\r
- _("刺激的な緑色のガスに包み込まれた!", "A pungent green gas surrounds you!"),\r
- p_ptr->resist_pois || IS_OPPOSE_POIS(),\r
- set_poisoned, p_ptr->poisoned + (TIME_EFFECT)randint0(20) + 10);\r
- break;\r
- }\r
-\r
- case TRAP_SLEEP:\r
- {\r
- msg_print(_("奇妙な白い霧に包まれた!", "A strange white mist surrounds you!"));\r
- if (!p_ptr->free_act)\r
- {\r
- msg_print(_("あなたは眠りに就いた。", "You fall asleep."));\r
-\r
- if (ironman_nightmare)\r
- {\r
- msg_print(_("身の毛もよだつ光景が頭に浮かんだ。", "A horrible vision enters your mind."));\r
-\r
- /* Have some nightmares */\r
- sanity_blast(NULL, FALSE);\r
-\r
- }\r
- (void)set_paralyzed(p_ptr->paralyzed + randint0(10) + 5);\r
- }\r
- break;\r
- }\r
-\r
- case TRAP_TRAPS:\r
- {\r
- msg_print(_("まばゆい閃光が走った!", "There is a bright flash of light!"));\r
- /* Make some new traps */\r
- project(0, 1, y, x, 0, GF_MAKE_TRAP, PROJECT_HIDE | PROJECT_JUMP | PROJECT_GRID, -1);\r
-\r
- break;\r
- }\r
-\r
- case TRAP_ALARM:\r
- {\r
- msg_print(_("けたたましい音が鳴り響いた!", "An alarm sounds!"));\r
-\r
- aggravate_monsters(0);\r
-\r
- break;\r
- }\r
-\r
- case TRAP_OPEN:\r
- {\r
- msg_print(_("大音響と共にまわりの壁が崩れた!", "Suddenly, surrounding walls are opened!"));\r
- (void)project(0, 3, y, x, 0, GF_DISINTEGRATE, PROJECT_GRID | PROJECT_HIDE, -1);\r
- (void)project(0, 3, y, x - 4, 0, GF_DISINTEGRATE, PROJECT_GRID | PROJECT_HIDE, -1);\r
- (void)project(0, 3, y, x + 4, 0, GF_DISINTEGRATE, PROJECT_GRID | PROJECT_HIDE, -1);\r
- aggravate_monsters(0);\r
-\r
- break;\r
- }\r
-\r
- case TRAP_ARMAGEDDON:\r
- {\r
- static int levs[10] = { 0, 0, 20, 10, 5, 3, 2, 1, 1, 1 };\r
- int evil_idx = 0, good_idx = 0;\r
-\r
- DEPTH lev;\r
- msg_print(_("突然天界の戦争に巻き込まれた!", "Suddenly, you are surrounded by immotal beings!"));\r
-\r
- /* Summon Demons and Angels */\r
- for (lev = dun_level; lev >= 20; lev -= 1 + lev / 16)\r
- {\r
- num = levs[MIN(lev / 10, 9)];\r
- for (i = 0; i < num; i++)\r
- {\r
- POSITION x1 = rand_spread(x, 7);\r
- POSITION y1 = rand_spread(y, 5);\r
-\r
- /* Skip illegal grids */\r
- if (!in_bounds(y1, x1)) continue;\r
-\r
- /* Require line of projection */\r
- if (!projectable(p_ptr->y, p_ptr->x, y1, x1)) continue;\r
-\r
- if (summon_specific(0, y1, x1, lev, SUMMON_ARMAGE_EVIL, (PM_NO_PET), '\0'))\r
- evil_idx = hack_m_idx_ii;\r
-\r
- if (summon_specific(0, y1, x1, lev, SUMMON_ARMAGE_GOOD, (PM_NO_PET), '\0'))\r
- {\r
- good_idx = hack_m_idx_ii;\r
- }\r
-\r
- /* Let them fight each other */\r
- if (evil_idx && good_idx)\r
- {\r
- monster_type *evil_ptr = &m_list[evil_idx];\r
- monster_type *good_ptr = &m_list[good_idx];\r
- evil_ptr->target_y = good_ptr->fy;\r
- evil_ptr->target_x = good_ptr->fx;\r
- good_ptr->target_y = evil_ptr->fy;\r
- good_ptr->target_x = evil_ptr->fx;\r
- }\r
- }\r
- }\r
- break;\r
- }\r
-\r
- case TRAP_PIRANHA:\r
- {\r
- msg_print(_("突然壁から水が溢れ出した!ピラニアがいる!", "Suddenly, the room is filled with water with piranhas!"));\r
-\r
- /* Water fills room */\r
- fire_ball_hide(GF_WATER_FLOW, 0, 1, 10);\r
-\r
- /* Summon Piranhas */\r
- num = 1 + dun_level / 20;\r
- for (i = 0; i < num; i++)\r
- {\r
- (void)summon_specific(0, y, x, dun_level, SUMMON_PIRANHAS, (PM_ALLOW_GROUP | PM_NO_PET), '\0');\r
- }\r
- break;\r
- }\r
- }\r
-\r
- if (break_trap && is_trap(c_ptr->feat))\r
- {\r
- cave_alter_feat(y, x, FF_DISARM);\r
- msg_print(_("トラップを粉砕した。", "You destroyed the trap."));\r
- }\r
-}\r
+#include "angband.h"
+#include "floor.h"
+#include "trap.h"
+#include "player-damage.h"
+#include "projection.h"
+#include "spells-summon.h"
+#include "quest.h"
+#include "artifact.h"
+
+static s16b normal_traps[MAX_NORMAL_TRAPS];
+
+
+/*!
+* @brief タグに従って、基本トラップテーブルを初期化する / Initialize arrays for normal traps
+* @return なし
+*/
+void init_normal_traps(void)
+{
+ int cur_trap = 0;
+
+ normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_TRAPDOOR");
+ normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_PIT");
+ normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_SPIKED_PIT");
+ normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_POISON_PIT");
+ normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_TY_CURSE");
+ normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_TELEPORT");
+ normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_FIRE");
+ normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_ACID");
+ normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_SLOW");
+ normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_LOSE_STR");
+ normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_LOSE_DEX");
+ normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_LOSE_CON");
+ normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_BLIND");
+ normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_CONFUSE");
+ normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_POISON");
+ normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_SLEEP");
+ normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_TRAPS");
+ normal_traps[cur_trap++] = f_tag_to_index_in_init("TRAP_ALARM");
+}
+
+/*!
+* @brief 基本トラップをランダムに選択する /
+* Get random trap
+* @return 選択したトラップのID
+* @details
+* This routine should be redone to reflect trap "level".\n
+* That is, it does not make sense to have spiked pits at 50 feet.\n
+* Actually, it is not this routine, but the "trap instantiation"\n
+* code, which should also check for "trap doors" on quest levels.\n
+*/
+FEAT_IDX choose_random_trap(void)
+{
+ FEAT_IDX feat;
+
+ /* Pick a trap */
+ while (1)
+ {
+ /* Hack -- pick a trap */
+ feat = normal_traps[randint0(MAX_NORMAL_TRAPS)];
+
+ /* Accept non-trapdoors */
+ if (!have_flag(f_info[feat].flags, FF_MORE)) break;
+
+ /* Hack -- no trap doors on special levels */
+ if (p_ptr->inside_arena || quest_number(dun_level)) continue;
+
+ /* Hack -- no trap doors on the deepest level */
+ if (dun_level >= d_info[p_ptr->dungeon_idx].maxdepth) continue;
+
+ break;
+ }
+
+ return feat;
+}
+
+/*!
+* @brief マスに存在するトラップを秘匿する /
+* Disclose an invisible trap
+* @param y 秘匿したいマスのY座標
+* @param x 秘匿したいマスのX座標
+* @return なし
+*/
+void disclose_grid(POSITION y, POSITION x)
+{
+ cave_type *c_ptr = &cave[y][x];
+
+ if (cave_have_flag_grid(c_ptr, FF_SECRET))
+ {
+ /* No longer hidden */
+ cave_alter_feat(y, x, FF_SECRET);
+ }
+ else if (c_ptr->mimic)
+ {
+ /* No longer hidden */
+ c_ptr->mimic = 0;
+
+ note_spot(y, x);
+ lite_spot(y, x);
+ }
+}
+
+/*!
+* @brief マスをトラップを配置する /
+* The location must be a legal, naked, floor grid.
+* @param y 配置したいマスのY座標
+* @param x 配置したいマスのX座標
+* @return
+* Note that all traps start out as "invisible" and "untyped", and then\n
+* when they are "discovered" (by detecting them or setting them off),\n
+* the trap is "instantiated" as a visible, "typed", trap.\n
+*/
+void place_trap(POSITION y, POSITION x)
+{
+ cave_type *c_ptr = &cave[y][x];
+
+ /* Paranoia -- verify location */
+ if (!in_bounds(y, x)) return;
+
+ /* Require empty, clean, floor grid */
+ if (!cave_clean_bold(y, x)) return;
+
+ /* Place an invisible trap */
+ c_ptr->mimic = c_ptr->feat;
+ c_ptr->feat = choose_random_trap();
+}
+
+
+
+/*!
+* @brief プレイヤーへのトラップ命中判定 /
+* Determine if a trap affects the player.
+* @param power 基本回避難度
+* @return トラップが命中した場合TRUEを返す。
+* @details
+* Always miss 5% of the time, Always hit 5% of the time.
+* Otherwise, match trap power against player armor.
+*/
+static int check_hit(int power)
+{
+ int k;
+ ARMOUR_CLASS ac;
+
+ /* Percentile dice */
+ k = randint0(100);
+
+ /* Hack -- 5% hit, 5% miss */
+ if (k < 10) return (k < 5);
+
+ if (p_ptr->pseikaku == SEIKAKU_NAMAKE)
+ if (one_in_(20)) return (TRUE);
+
+ /* Paranoia -- No power */
+ if (power <= 0) return (FALSE);
+
+ /* Total armor */
+ ac = p_ptr->ac + p_ptr->to_a;
+
+ /* Power competes against Armor */
+ if (randint1(power) > ((ac * 3) / 4)) return (TRUE);
+
+ /* Assume miss */
+ return (FALSE);
+}
+
+
+/*!
+* @brief 落とし穴系トラップの判定とプレイヤーの被害処理
+* @param trap_feat_type トラップの種別ID
+* @return なし
+*/
+static void hit_trap_pit(int trap_feat_type)
+{
+ HIT_POINT dam;
+ concptr trap_name = "";
+ concptr spike_name = "";
+
+ switch (trap_feat_type)
+ {
+ case TRAP_PIT:
+ trap_name = _("落とし穴", "a pit trap");
+ break;
+ case TRAP_SPIKED_PIT:
+ trap_name = _("スパイクが敷かれた落とし穴", "a spiked pit");
+ spike_name = _("スパイク", "spikes");
+ break;
+ case TRAP_POISON_PIT:
+ trap_name = _("スパイクが敷かれた落とし穴", "a spiked pit");
+ spike_name = _("毒を塗られたスパイク", "poisonous spikes");
+ break;
+ default:
+ return;
+ }
+
+ if (p_ptr->levitation)
+ {
+ msg_format(_("%sを飛び越えた。", "You fly over %s."), trap_name);
+ return;
+ }
+
+ msg_format(_("%sに落ちてしまった!", "You have fallen into %s!"), trap_name);
+
+ /* Base damage */
+ dam = damroll(2, 6);
+
+ /* Extra spike damage */
+ if ((trap_feat_type == TRAP_SPIKED_PIT || trap_feat_type == TRAP_POISON_PIT) &&
+ one_in_(2))
+ {
+ msg_format(_("%sが刺さった!", "You are impaled on %s!"), spike_name);
+
+ dam = dam * 2;
+ (void)set_cut(p_ptr->cut + randint1(dam));
+
+ if (trap_feat_type == TRAP_POISON_PIT) {
+ if (p_ptr->resist_pois || IS_OPPOSE_POIS())
+ {
+ msg_print(_("しかし毒の影響はなかった!", "The poison does not affect you!"));
+ }
+ else
+ {
+ dam = dam * 2;
+ (void)set_poisoned(p_ptr->poisoned + randint1(dam));
+ }
+ }
+ }
+
+ take_hit(DAMAGE_NOESCAPE, dam, trap_name, -1);
+}
+
+/*!
+* @brief ダーツ系トラップ(通常ダメージ)の判定とプレイヤーの被害処理
+* @return ダーツが命中した場合TRUEを返す
+*/
+static bool hit_trap_dart(void)
+{
+ bool hit = FALSE;
+
+ if (check_hit(125))
+ {
+ msg_print(_("小さなダーツが飛んできて刺さった!", "A small dart hits you!"));
+ take_hit(DAMAGE_ATTACK, damroll(1, 4), _("ダーツの罠", "a dart trap"), -1);
+ if (!CHECK_MULTISHADOW()) hit = TRUE;
+ }
+ else
+ {
+ msg_print(_("小さなダーツが飛んできた!が、運良く当たらなかった。", "A small dart barely misses you."));
+ }
+
+ return hit;
+}
+
+/*!
+* @brief ダーツ系トラップ(通常ダメージ+能力値減少)の判定とプレイヤーの被害処理
+* @param stat 低下する能力値ID
+* @return なし
+*/
+static void hit_trap_lose_stat(int stat)
+{
+ if (hit_trap_dart())
+ {
+ do_dec_stat(stat);
+ }
+}
+
+/*!
+* @brief ダーツ系トラップ(通常ダメージ+減速)の判定とプレイヤーの被害処理
+* @return なし
+*/
+static void hit_trap_slow(void)
+{
+ if (hit_trap_dart())
+ {
+ set_slow(p_ptr->slow + randint0(20) + 20, FALSE);
+ }
+}
+
+/*!
+* @brief ダーツ系トラップ(通常ダメージ+状態異常)の判定とプレイヤーの被害処理
+* @param trap_message メッセージの補完文字列
+* @param resist 状態異常に抵抗する判定が出たならTRUE
+* @param set_status 状態異常を指定する関数ポインタ
+* @param turn 状態異常の追加ターン量
+* @return なし
+*/
+static void hit_trap_set_abnormal_status(concptr trap_message, bool resist, bool(*set_status)(IDX), IDX turn_aux)
+{
+ msg_print(trap_message);
+ if (!resist)
+ {
+ set_status(turn_aux);
+ }
+}
+
+/*!
+* @brief プレイヤーへのトラップ作動処理メインルーチン /
+* Handle player hitting a real trap
+* @param break_trap 作動後のトラップ破壊が確定しているならばTRUE
+* @return なし
+*/
+void hit_trap(bool break_trap)
+{
+ int i, num, dam;
+ POSITION x = p_ptr->x, y = p_ptr->y;
+
+ /* Get the cave grid */
+ cave_type *c_ptr = &cave[y][x];
+ feature_type *f_ptr = &f_info[c_ptr->feat];
+ int trap_feat_type = have_flag(f_ptr->flags, FF_TRAP) ? f_ptr->subtype : NOT_TRAP;
+ concptr name = _("トラップ", "a trap");
+
+ disturb(FALSE, TRUE);
+
+ cave_alter_feat(y, x, FF_HIT_TRAP);
+
+ /* Analyze */
+ switch (trap_feat_type)
+ {
+ case TRAP_TRAPDOOR:
+ {
+ if (p_ptr->levitation)
+ {
+ msg_print(_("落とし戸を飛び越えた。", "You fly over a trap door."));
+ }
+ else
+ {
+ msg_print(_("落とし戸に落ちた!", "You have fallen through a trap door!"));
+ if ((p_ptr->pseikaku == SEIKAKU_COMBAT) || (inventory[INVEN_BOW].name1 == ART_CRIMSON))
+ msg_print(_("くっそ~!", ""));
+ else if((p_ptr->pseikaku == SEIKAKU_CHARGEMAN))
+ msg_print(_("ジュラル星人の仕業に違いない!", ""));
+
+
+ sound(SOUND_FALL);
+ dam = damroll(2, 8);
+ name = _("落とし戸", "a trap door");
+
+ take_hit(DAMAGE_NOESCAPE, dam, name, -1);
+
+ /* Still alive and autosave enabled */
+ if (autosave_l && (p_ptr->chp >= 0))
+ do_cmd_save_game(TRUE);
+
+ do_cmd_write_nikki(NIKKI_BUNSHOU, 0, _("落とし戸に落ちた", "You have fallen through a trap door!"));
+ prepare_change_floor_mode(CFM_SAVE_FLOORS | CFM_DOWN | CFM_RAND_PLACE | CFM_RAND_CONNECT);
+
+ /* Leaving */
+ p_ptr->leaving = TRUE;
+ }
+ break;
+ }
+
+ case TRAP_PIT:
+ case TRAP_SPIKED_PIT:
+ case TRAP_POISON_PIT:
+ {
+ hit_trap_pit(trap_feat_type);
+ break;
+ }
+
+ case TRAP_TY_CURSE:
+ {
+ msg_print(_("何かがピカッと光った!", "There is a flash of shimmering light!"));
+ num = 2 + randint1(3);
+ for (i = 0; i < num; i++)
+ {
+ (void)summon_specific(0, y, x, dun_level, 0, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0');
+ }
+
+ if (dun_level > randint1(100)) /* No nasty effect for low levels */
+ {
+ bool stop_ty = FALSE;
+ int count = 0;
+
+ do
+ {
+ stop_ty = activate_ty_curse(stop_ty, &count);
+ } while (one_in_(6));
+ }
+ break;
+ }
+
+ case TRAP_TELEPORT:
+ {
+ msg_print(_("テレポート・トラップにひっかかった!", "You hit a teleport trap!"));
+ teleport_player(100, TELEPORT_PASSIVE);
+ break;
+ }
+
+ case TRAP_FIRE:
+ {
+ msg_print(_("炎に包まれた!", "You are enveloped in flames!"));
+ dam = damroll(4, 6);
+ (void)fire_dam(dam, _("炎のトラップ", "a fire trap"), -1, FALSE);
+ break;
+ }
+
+ case TRAP_ACID:
+ {
+ msg_print(_("酸が吹きかけられた!", "You are splashed with acid!"));
+ dam = damroll(4, 6);
+ (void)acid_dam(dam, _("酸のトラップ", "an acid trap"), -1, FALSE);
+ break;
+ }
+
+ case TRAP_SLOW:
+ {
+ hit_trap_slow();
+ break;
+ }
+
+ case TRAP_LOSE_STR:
+ {
+ hit_trap_lose_stat(A_STR);
+ break;
+ }
+
+ case TRAP_LOSE_DEX:
+ {
+ hit_trap_lose_stat(A_DEX);
+ break;
+ }
+
+ case TRAP_LOSE_CON:
+ {
+ hit_trap_lose_stat(A_CON);
+ break;
+ }
+
+ case TRAP_BLIND:
+ {
+ hit_trap_set_abnormal_status(
+ _("黒いガスに包み込まれた!", "A black gas surrounds you!"),
+ p_ptr->resist_blind,
+ set_blind, p_ptr->blind + (TIME_EFFECT)randint0(50) + 25);
+ break;
+ }
+
+ case TRAP_CONFUSE:
+ {
+ hit_trap_set_abnormal_status(
+ _("きらめくガスに包み込まれた!", "A gas of scintillating colors surrounds you!"),
+ p_ptr->resist_conf,
+ set_confused, p_ptr->confused + (TIME_EFFECT)randint0(20) + 10);
+ break;
+ }
+
+ case TRAP_POISON:
+ {
+ hit_trap_set_abnormal_status(
+ _("刺激的な緑色のガスに包み込まれた!", "A pungent green gas surrounds you!"),
+ p_ptr->resist_pois || IS_OPPOSE_POIS(),
+ set_poisoned, p_ptr->poisoned + (TIME_EFFECT)randint0(20) + 10);
+ break;
+ }
+
+ case TRAP_SLEEP:
+ {
+ msg_print(_("奇妙な白い霧に包まれた!", "A strange white mist surrounds you!"));
+ if (!p_ptr->free_act)
+ {
+ msg_print(_("あなたは眠りに就いた。", "You fall asleep."));
+
+ if (ironman_nightmare)
+ {
+ msg_print(_("身の毛もよだつ光景が頭に浮かんだ。", "A horrible vision enters your mind."));
+
+ /* Have some nightmares */
+ sanity_blast(NULL, FALSE);
+
+ }
+ (void)set_paralyzed(p_ptr->paralyzed + randint0(10) + 5);
+ }
+ break;
+ }
+
+ case TRAP_TRAPS:
+ {
+ msg_print(_("まばゆい閃光が走った!", "There is a bright flash of light!"));
+ /* Make some new traps */
+ project(0, 1, y, x, 0, GF_MAKE_TRAP, PROJECT_HIDE | PROJECT_JUMP | PROJECT_GRID, -1);
+
+ break;
+ }
+
+ case TRAP_ALARM:
+ {
+ msg_print(_("けたたましい音が鳴り響いた!", "An alarm sounds!"));
+
+ aggravate_monsters(0);
+
+ break;
+ }
+
+ case TRAP_OPEN:
+ {
+ msg_print(_("大音響と共にまわりの壁が崩れた!", "Suddenly, surrounding walls are opened!"));
+ (void)project(0, 3, y, x, 0, GF_DISINTEGRATE, PROJECT_GRID | PROJECT_HIDE, -1);
+ (void)project(0, 3, y, x - 4, 0, GF_DISINTEGRATE, PROJECT_GRID | PROJECT_HIDE, -1);
+ (void)project(0, 3, y, x + 4, 0, GF_DISINTEGRATE, PROJECT_GRID | PROJECT_HIDE, -1);
+ aggravate_monsters(0);
+
+ break;
+ }
+
+ case TRAP_ARMAGEDDON:
+ {
+ static int levs[10] = { 0, 0, 20, 10, 5, 3, 2, 1, 1, 1 };
+ int evil_idx = 0, good_idx = 0;
+
+ DEPTH lev;
+ msg_print(_("突然天界の戦争に巻き込まれた!", "Suddenly, you are surrounded by immotal beings!"));
+
+ /* Summon Demons and Angels */
+ for (lev = dun_level; lev >= 20; lev -= 1 + lev / 16)
+ {
+ num = levs[MIN(lev / 10, 9)];
+ for (i = 0; i < num; i++)
+ {
+ POSITION x1 = rand_spread(x, 7);
+ POSITION y1 = rand_spread(y, 5);
+
+ /* Skip illegal grids */
+ if (!in_bounds(y1, x1)) continue;
+
+ /* Require line of projection */
+ if (!projectable(p_ptr->y, p_ptr->x, y1, x1)) continue;
+
+ if (summon_specific(0, y1, x1, lev, SUMMON_ARMAGE_EVIL, (PM_NO_PET), '\0'))
+ evil_idx = hack_m_idx_ii;
+
+ if (summon_specific(0, y1, x1, lev, SUMMON_ARMAGE_GOOD, (PM_NO_PET), '\0'))
+ {
+ good_idx = hack_m_idx_ii;
+ }
+
+ /* Let them fight each other */
+ if (evil_idx && good_idx)
+ {
+ monster_type *evil_ptr = &m_list[evil_idx];
+ monster_type *good_ptr = &m_list[good_idx];
+ evil_ptr->target_y = good_ptr->fy;
+ evil_ptr->target_x = good_ptr->fx;
+ good_ptr->target_y = evil_ptr->fy;
+ good_ptr->target_x = evil_ptr->fx;
+ }
+ }
+ }
+ break;
+ }
+
+ case TRAP_PIRANHA:
+ {
+ msg_print(_("突然壁から水が溢れ出した!ピラニアがいる!", "Suddenly, the room is filled with water with piranhas!"));
+
+ /* Water fills room */
+ fire_ball_hide(GF_WATER_FLOW, 0, 1, 10);
+
+ /* Summon Piranhas */
+ num = 1 + dun_level / 20;
+ for (i = 0; i < num; i++)
+ {
+ (void)summon_specific(0, y, x, dun_level, SUMMON_PIRANHAS, (PM_ALLOW_GROUP | PM_NO_PET), '\0');
+ }
+ break;
+ }
+ }
+
+ if (break_trap && is_trap(c_ptr->feat))
+ {
+ cave_alter_feat(y, x, FF_DISARM);
+ msg_print(_("トラップを粉砕した。", "You destroyed the trap."));
+ }
+}
-\r
-extern void init_normal_traps(void);\r
-extern FEAT_IDX choose_random_trap(void);\r
-extern void disclose_grid(POSITION y, POSITION x);\r
-extern void place_trap(POSITION y, POSITION x);\r
-extern void hit_trap(bool break_trap);\r
-\r
-/* Types of normal traps */\r
-#define NOT_TRAP -1\r
-#define TRAP_TRAPDOOR 0\r
-#define TRAP_PIT 1\r
-#define TRAP_SPIKED_PIT 2\r
-#define TRAP_POISON_PIT 3\r
-#define TRAP_TY_CURSE 4\r
-#define TRAP_TELEPORT 5\r
-#define TRAP_FIRE 6\r
-#define TRAP_ACID 7\r
-#define TRAP_SLOW 8\r
-\r
-#define TRAP_LOSE_STR 9\r
-#define TRAP_LOSE_DEX 10\r
-#define TRAP_LOSE_CON 11\r
-#define TRAP_BLIND 12\r
-#define TRAP_CONFUSE 13\r
-#define TRAP_POISON 14\r
-#define TRAP_SLEEP 15\r
-#define TRAP_TRAPS 16\r
-#define TRAP_ALARM 17\r
-\r
-#define MAX_NORMAL_TRAPS 18\r
-\r
-\r
-/* Types of special traps */\r
-#define TRAP_OPEN 18\r
-#define TRAP_ARMAGEDDON 19\r
-#define TRAP_PIRANHA 20\r
-\r
-\r
-\r
-/* See init_feat_variables() in init2.c */\r
+
+extern void init_normal_traps(void);
+extern FEAT_IDX choose_random_trap(void);
+extern void disclose_grid(POSITION y, POSITION x);
+extern void place_trap(POSITION y, POSITION x);
+extern void hit_trap(bool break_trap);
+
+/* Types of normal traps */
+#define NOT_TRAP -1
+#define TRAP_TRAPDOOR 0
+#define TRAP_PIT 1
+#define TRAP_SPIKED_PIT 2
+#define TRAP_POISON_PIT 3
+#define TRAP_TY_CURSE 4
+#define TRAP_TELEPORT 5
+#define TRAP_FIRE 6
+#define TRAP_ACID 7
+#define TRAP_SLOW 8
+
+#define TRAP_LOSE_STR 9
+#define TRAP_LOSE_DEX 10
+#define TRAP_LOSE_CON 11
+#define TRAP_BLIND 12
+#define TRAP_CONFUSE 13
+#define TRAP_POISON 14
+#define TRAP_SLEEP 15
+#define TRAP_TRAPS 16
+#define TRAP_ALARM 17
+
+#define MAX_NORMAL_TRAPS 18
+
+
+/* Types of special traps */
+#define TRAP_OPEN 18
+#define TRAP_ARMAGEDDON 19
+#define TRAP_PIRANHA 20
+
+
+
+/* See init_feat_variables() in init2.c */
-#include "angband.h"\r
-\r
-/*!\r
- * @brief ゲーム時間が日中かどうかを返す /\r
- * Whether daytime or not\r
- * @return 日中ならばTRUE、夜ならばFALSE\r
- */\r
-bool is_daytime(void)\r
-{\r
- s32b len = TURNS_PER_TICK * TOWN_DAWN;\r
- if ((turn % len) < (len / 2))\r
- return TRUE;\r
- else\r
- return FALSE;\r
-}\r
-\r
-/*!\r
- * @brief 現在の日数、時刻を返す /\r
- * Extract day, hour, min\r
- * @param day 日数を返すための参照ポインタ\r
- * @param hour 時数を返すための参照ポインタ\r
- * @param min 分数を返すための参照ポインタ\r
- */\r
-void extract_day_hour_min(int *day, int *hour, int *min)\r
-{\r
- const s32b A_DAY = TURNS_PER_TICK * TOWN_DAWN;\r
- s32b turn_in_today = (turn + A_DAY / 4) % A_DAY;\r
-\r
- switch (p_ptr->start_race)\r
- {\r
- case RACE_VAMPIRE:\r
- case RACE_SKELETON:\r
- case RACE_ZOMBIE:\r
- case RACE_SPECTRE:\r
- *day = (turn - A_DAY * 3 / 4) / A_DAY + 1;\r
- break;\r
- default:\r
- *day = (turn + A_DAY / 4) / A_DAY + 1;\r
- break;\r
- }\r
- *hour = (24 * turn_in_today / A_DAY) % 24;\r
- *min = (1440 * turn_in_today / A_DAY) % 60;\r
-}\r
+#include "angband.h"
+
+/*!
+ * @brief ゲーム時間が日中かどうかを返す /
+ * Whether daytime or not
+ * @return 日中ならばTRUE、夜ならばFALSE
+ */
+bool is_daytime(void)
+{
+ s32b len = TURNS_PER_TICK * TOWN_DAWN;
+ if ((turn % len) < (len / 2))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/*!
+ * @brief 現在の日数、時刻を返す /
+ * Extract day, hour, min
+ * @param day 日数を返すための参照ポインタ
+ * @param hour 時数を返すための参照ポインタ
+ * @param min 分数を返すための参照ポインタ
+ */
+void extract_day_hour_min(int *day, int *hour, int *min)
+{
+ const s32b A_DAY = TURNS_PER_TICK * TOWN_DAWN;
+ s32b turn_in_today = (turn + A_DAY / 4) % A_DAY;
+
+ switch (p_ptr->start_race)
+ {
+ case RACE_VAMPIRE:
+ case RACE_SKELETON:
+ case RACE_ZOMBIE:
+ case RACE_SPECTRE:
+ *day = (turn - A_DAY * 3 / 4) / A_DAY + 1;
+ break;
+ default:
+ *day = (turn + A_DAY / 4) / A_DAY + 1;
+ break;
+ }
+ *hour = (24 * turn_in_today / A_DAY) % 24;
+ *min = (1440 * turn_in_today / A_DAY) % 60;
+}
-extern bool is_daytime(void);\r
-extern void extract_day_hour_min(int *day, int *hour, int *min);\r
+extern bool is_daytime(void);
+extern void extract_day_hour_min(int *day, int *hour, int *min);