-/* File: obj_kind.c */
-
-/* Purpose: Code for the object templates */
-
-/*
- * Copyright (c) 1989 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.
+/*!
+ * @file obj_kind.c
+ * @brief ベースアイテムの実装
+ * @date 2014/01/10
+ * @author
+ * 2014 Deskull rearranged comment for Doxygen.
*/
#include "angband.h"
-
-/* Base size of k_info */
-#define K_INFO_BASE_SIZE 500
-
-/* Amount of entries to add when resizing k_info */
-#define K_INFO_RESIZE 50
-
-/* Size of the allocated */
-static s32b k_info_size = K_INFO_BASE_SIZE;
+/*!
+ * @brief オブジェクトが薬であるかを返す
+ * @param o_ptr 対象のオブジェクト構造体ポインタ
+ * @return オブジェクトが薬ならばTRUEを返す
+ */
+bool object_is_potion(object_type *o_ptr)
+{
+ return (k_info[o_ptr->k_idx].tval == TV_POTION);
+}
-/* Allocate k_info */
-errr k_info_alloc(void)
+/*!
+ * @brief オブジェクトが賞金首の報酬対象になるかを返す
+ * @param o_ptr 対象のオブジェクト構造体ポインタ
+ * @return オブジェクトが報酬対象になるならTRUEを返す
+ */
+bool object_is_shoukinkubi(object_type *o_ptr)
{
- /* Create the storage for the object templates */
- C_MAKE(k_info, k_info_size, object_kind);
+ int i;
- /* Success */
- return 0;
-}
+ /* Require corpse or skeleton */
+ if (o_ptr->tval != TV_CORPSE) return FALSE;
+ /* No wanted monsters in vanilla town */
+ if (vanilla_town) return FALSE;
-/* Free k_info */
-errr k_info_free(void)
-{
- k_info_size = K_INFO_BASE_SIZE;
+ /* Today's wanted */
+ if (p_ptr->today_mon > 0 && (streq(r_name + r_info[o_ptr->pval].name, r_name + r_info[today_mon].name))) return TRUE;
- C_KILL(k_info, k_info_size, object_kind);
+ /* Tsuchinoko */
+ if (o_ptr->pval == MON_TSUCHINOKO) return TRUE;
- /* Success */
- return 0;
-}
+ /* Unique monster */
+ for (i = 0; i < MAX_KUBI; i++)
+ if (o_ptr->pval == kubi_r_idx[i]) break;
+ if (i < MAX_KUBI) return TRUE;
+ /* Not wanted */
+ return FALSE;
+}
-void k_info_reset(void)
+/*!
+ * @brief オブジェクトがプレイヤーの職業に応じた適正武器か否かを返す / Favorite weapons
+ * @param o_ptr 対象のオブジェクト構造体ポインタ
+ * @return オブジェクトが適正武器ならばTRUEを返す
+ */
+bool object_is_favorite(object_type *o_ptr)
{
- int i;
-
- /* Reset the "objects" */
- for (i = 1; i < max_k_idx; i++)
+ /* Only melee weapons match */
+ if (!(o_ptr->tval == TV_POLEARM ||
+ o_ptr->tval == TV_SWORD ||
+ o_ptr->tval == TV_DIGGING ||
+ o_ptr->tval == TV_HAFTED))
{
- object_kind *k_ptr = &k_info[i];
+ return FALSE;
+ }
- /* Reset "tried" */
- k_ptr->tried = FALSE;
+ /* Favorite weapons are varied depend on the class */
+ switch (p_ptr->pclass)
+ {
+ case CLASS_PRIEST:
+ {
+ BIT_FLAGS flgs[TR_FLAG_SIZE];
+ object_flags_known(o_ptr, flgs);
- /* Reset "aware" */
- k_ptr->aware = FALSE;
+ if (!have_flag(flgs, TR_BLESSED) &&
+ !(o_ptr->tval == TV_HAFTED))
+ return FALSE;
+ break;
}
-}
+ case CLASS_MONK:
+ case CLASS_FORCETRAINER:
+ /* Icky to wield? */
+ if (!(s_info[p_ptr->pclass].w_max[o_ptr->tval-TV_WEAPON_BEGIN][o_ptr->sval]))
+ return FALSE;
+ break;
-/* Add a new object template */
-object_kind *k_info_add(object_kind *k_info_entry)
-{
- /* Resize if necessary */
- while (k_info_size <= max_k_idx)
+ case CLASS_BEASTMASTER:
+ case CLASS_CAVALRY:
{
- k_info_size += K_INFO_RESIZE;
-
- /* Reallocate the extra memory */
- k_info = realloc(k_info, k_info_size * sizeof(object_kind));
+ BIT_FLAGS flgs[TR_FLAG_SIZE];
+ object_flags_known(o_ptr, flgs);
- /* Failure */
-#ifdef JP
-if (!k_info) quit("¥á¥â¥ê¡¼ÉÔÂ!");
-#else
- if (!k_info) quit("Out of memory!");
-#endif
+ /* Is it known to be suitable to using while riding? */
+ if (!(have_flag(flgs, TR_RIDING)))
+ return FALSE;
-
- /* Wipe the new memory */
- (void)C_WIPE(&k_info[(k_info_size - K_INFO_RESIZE)], K_INFO_RESIZE, object_kind);
+ break;
}
- /* Increase the maximum index of the array */
- max_k_idx++;
+ case CLASS_NINJA:
+ /* Icky to wield? */
+ if (s_info[p_ptr->pclass].w_max[o_ptr->tval-TV_WEAPON_BEGIN][o_ptr->sval] <= WEAPON_EXP_BEGINNER)
+ return FALSE;
+ break;
- /* Copy the new object_kind */
- COPY(&k_info[max_k_idx-1], k_info_entry, object_kind);
+ default:
+ /* All weapons are okay for non-special classes */
+ return TRUE;
+ }
- /* Success */
- return (&k_info[max_k_idx-1]);
+ return TRUE;
}
-/*
- * Initialize some other arrays
+/*!
+ * @brief オブジェクトがレアアイテムかどうかを返す /
+ * Rare weapons/aromors including Blade of Chaos, Dragon armors, etc.
+ * @param o_ptr 対象のオブジェクト構造体ポインタ
+ * @return レアアイテムならばTRUEを返す
*/
-errr init_object_alloc(void)
+bool object_is_rare(object_type *o_ptr)
{
- int i, j;
- object_kind *k_ptr;
- alloc_entry *table;
- s16b num[MAX_DEPTH];
- s16b aux[MAX_DEPTH];
+ switch(o_ptr->tval)
+ {
+ case TV_HAFTED:
+ if (o_ptr->sval == SV_MACE_OF_DISRUPTION ||
+ o_ptr->sval == SV_WIZSTAFF) return TRUE;
+ break;
+
+ case TV_POLEARM:
+ if (o_ptr->sval == SV_SCYTHE_OF_SLICING ||
+ o_ptr->sval == SV_DEATH_SCYTHE) return TRUE;
+ break;
+
+ case TV_SWORD:
+ if (o_ptr->sval == SV_BLADE_OF_CHAOS ||
+ o_ptr->sval == SV_DIAMOND_EDGE ||
+ o_ptr->sval == SV_DOKUBARI ||
+ o_ptr->sval == SV_HAYABUSA) return TRUE;
+ break;
+
+ case TV_SHIELD:
+ if (o_ptr->sval == SV_DRAGON_SHIELD ||
+ o_ptr->sval == SV_MIRROR_SHIELD) return TRUE;
+ break;
+
+ case TV_HELM:
+ if (o_ptr->sval == SV_DRAGON_HELM) return TRUE;
+ break;
+
+ case TV_BOOTS:
+ if (o_ptr->sval == SV_PAIR_OF_DRAGON_GREAVE) return TRUE;
+ break;
+
+ case TV_CLOAK:
+ if (o_ptr->sval == SV_ELVEN_CLOAK ||
+ o_ptr->sval == SV_ETHEREAL_CLOAK ||
+ o_ptr->sval == SV_SHADOW_CLOAK) return TRUE;
+ break;
+
+ case TV_GLOVES:
+ if (o_ptr->sval == SV_SET_OF_DRAGON_GLOVES) return TRUE;
+ break;
+
+ case TV_SOFT_ARMOR:
+ if (o_ptr->sval == SV_KUROSHOUZOKU ||
+ o_ptr->sval == SV_ABUNAI_MIZUGI) return TRUE;
+ break;
+
+ case TV_DRAG_ARMOR:
+ return TRUE;
+
+ default:
+ break;
+ }
+ /* Any others are not "rare" objects. */
+ return FALSE;
+}
- /*** Analyze object allocation info ***/
- /* Clear the "aux" array */
- (void)C_WIPE(&aux, MAX_DEPTH, s16b);
+/*!
+ * @brief オブジェクトが武器として装備できるかどうかを返す / Check if an object is weapon (including bows and ammo)
+ * @param o_ptr 対象のオブジェクト構造体ポインタ
+ * @return 武器として使えるならばTRUEを返す
+ */
+bool object_is_weapon(object_type *o_ptr)
+{
+ if (TV_WEAPON_BEGIN <= o_ptr->tval && o_ptr->tval <= TV_WEAPON_END) return TRUE;
- /* Clear the "num" array */
- (void)C_WIPE(&num, MAX_DEPTH, s16b);
+ return FALSE;
+}
- /* Free the old "alloc_kind_table" (if it exists) */
- if (alloc_kind_table)
- {
- C_KILL(alloc_kind_table, alloc_kind_size, alloc_entry);
- }
- /* Size of "alloc_kind_table" */
- alloc_kind_size = 0;
+/*!
+ * @brief オブジェクトが武器や矢弾として使用できるかを返す / Check if an object is weapon (including bows and ammo)
+ * Rare weapons/aromors including Blade of Chaos, Dragon armors, etc.
+ * @param o_ptr 対象のオブジェクト構造体ポインタ
+ * @return 武器や矢弾として使えるならばTRUEを返す
+ */
+bool object_is_weapon_ammo(object_type *o_ptr)
+{
+ if (TV_MISSILE_BEGIN <= o_ptr->tval && o_ptr->tval <= TV_WEAPON_END) return TRUE;
- /* Scan the objects */
- for (i = 1; i < max_k_idx; i++)
- {
- k_ptr = &k_info[i];
-
- /* Scan allocation pairs */
- for (j = 0; j < 4; j++)
- {
- /* Count the "legal" entries */
- if (k_ptr->chance[j])
- {
- /* Count the entries */
- alloc_kind_size++;
-
- /* Group by level */
- num[k_ptr->locale[j]]++;
- }
- }
- }
+ return FALSE;
+}
- /* Collect the level indexes */
- for (i = 1; i < MAX_DEPTH; i++)
- {
- /* Group by level */
- num[i] += num[i-1];
- }
+/*!
+ * @brief オブジェクトが矢弾として使用できるかどうかを返す / Check if an object is ammo
+ * @param o_ptr 対象のオブジェクト構造体ポインタ
+ * @return 矢弾として使えるならばTRUEを返す
+ */
+bool object_is_ammo(object_type *o_ptr)
+{
+ if (TV_MISSILE_BEGIN <= o_ptr->tval && o_ptr->tval <= TV_MISSILE_END) return TRUE;
- /* Paranoia */
-#ifdef JP
-if (!num[0]) quit("Ä®¤Î¥¢¥¤¥Æ¥à¤¬¤Ê¤¤¡ª");
-#else
- if (!num[0]) quit("No town objects!");
-#endif
+ return FALSE;
+}
+/*!
+ * @brief オブジェクトが防具として装備できるかどうかを返す / Check if an object is armour
+ * @param o_ptr 対象のオブジェクト構造体ポインタ
+ * @return 矢弾として使えるならばTRUEを返す
+ */
+bool object_is_armour(object_type *o_ptr)
+{
+ if (TV_ARMOR_BEGIN <= o_ptr->tval && o_ptr->tval <= TV_ARMOR_END) return TRUE;
+ return FALSE;
+}
- /*** Initialize object allocation info ***/
+/*!
+ * @brief オブジェクトが武器、防具、矢弾として使用できるかを返す / Check if an object is weapon, armour or ammo
+ * @param o_ptr 対象のオブジェクト構造体ポインタ
+ * @return 武器、防具、矢弾として使えるならばTRUEを返す
+ */
+bool object_is_weapon_armour_ammo(object_type *o_ptr)
+{
+ if (object_is_weapon_ammo(o_ptr) || object_is_armour(o_ptr)) return TRUE;
- /* Allocate the alloc_kind_table */
- C_MAKE(alloc_kind_table, alloc_kind_size, alloc_entry);
+ return FALSE;
+}
- /* Access the table entry */
- table = alloc_kind_table;
- /* Scan the objects */
- for (i = 1; i < max_k_idx; i++)
- {
- k_ptr = &k_info[i];
-
- /* Scan allocation pairs */
- for (j = 0; j < 4; j++)
- {
- /* Count the "legal" entries */
- if (k_ptr->chance[j])
- {
- int p, x, y, z;
-
- /* Extract the base level */
- x = k_ptr->locale[j];
-
- /* Extract the base probability */
- p = (100 / k_ptr->chance[j]);
-
- /* Skip entries preceding our locale */
- y = (x > 0) ? num[x-1] : 0;
-
- /* Skip previous entries at this locale */
- z = y + aux[x];
-
- /* Load the entry */
- table[z].index = i;
- table[z].level = x;
- table[z].prob1 = p;
- table[z].prob2 = p;
- table[z].prob3 = p;
-
- /* Another entry complete for this locale */
- aux[x]++;
- }
- }
- }
+/*!
+ * @brief オブジェクトが近接武器として装備できるかを返す / Melee weapons
+ * @param o_ptr 対象のオブジェクト構造体ポインタ
+ * @return 近接武器として使えるならばTRUEを返す
+ */
+bool object_is_melee_weapon(object_type *o_ptr)
+{
+ if (TV_DIGGING <= o_ptr->tval && o_ptr->tval <= TV_SWORD) return TRUE;
- /* Success */
- return (0);
+ return FALSE;
}
-int get_object_level(object_type *o_ptr)
+/*!
+ * @brief オブジェクトが装備可能であるかを返す / Wearable including all weapon, all armour, bow, light source, amulet, and ring
+ * @param o_ptr 対象のオブジェクト構造体ポインタ
+ * @return 装備可能ならばTRUEを返す
+ */
+bool object_is_wearable(object_type *o_ptr)
{
-#if 0
- return (byte)get_object_level_callback(o_ptr);
-#else
- return k_info[o_ptr->k_idx].level;
-#endif
+ if (TV_WEARABLE_BEGIN <= o_ptr->tval && o_ptr->tval <= TV_WEARABLE_END) return TRUE;
+
+ return FALSE;
}
-s32b get_object_cost(object_type *o_ptr)
+/*!
+ * @brief オブジェクトが装備品であるかを返す(object_is_wearableに矢弾を含む) / Equipment including all wearable objects and ammo
+ * @param o_ptr 対象のオブジェクト構造体ポインタ
+ * @return 装備品ならばTRUEを返す
+ */
+bool object_is_equipment(object_type *o_ptr)
{
-#if 0
- return get_object_cost_callback(o_ptr);
-#else
- return k_info[o_ptr->k_idx].cost;
-#endif
+ if (TV_EQUIP_BEGIN <= o_ptr->tval && o_ptr->tval <= TV_EQUIP_END) return TRUE;
+
+ return FALSE;
}
-cptr get_object_name(object_type *o_ptr)
+/*!
+ * @brief オブジェクトが強化不能武器であるかを返す / Poison needle can not be enchanted
+ * @param o_ptr 対象のオブジェクト構造体ポインタ
+ * @return 強化不能ならばTRUEを返す
+ */
+bool object_refuse_enchant_weapon(object_type *o_ptr)
{
-#if 0
- return get_object_name_callback(o_ptr);
-#else
- return (k_name + k_info[o_ptr->k_idx].name);
-#endif
+ if (o_ptr->tval == TV_SWORD && o_ptr->sval == SV_DOKUBARI) return TRUE;
+
+ return FALSE;
}
-/* Default object attribute */
-byte get_object_d_attr(object_type *o_ptr)
+/*!
+ * @brief オブジェクトが強化可能武器であるかを返す /
+ * Check if an object is weapon (including bows and ammo) and allows enchantment
+ * @param o_ptr 対象のオブジェクト構造体ポインタ
+ * @return 強化可能ならばTRUEを返す
+ */
+bool object_allow_enchant_weapon(object_type *o_ptr)
{
-#if 0
- return get_object_d_attr_callback(o_ptr);
-#else
- return k_info[o_ptr->k_idx].d_attr;
-#endif
+ if (object_is_weapon_ammo(o_ptr) && !object_refuse_enchant_weapon(o_ptr)) return TRUE;
+
+ return FALSE;
}
-/* Default object character */
-byte get_object_x_attr(object_type *o_ptr)
+/*!
+ * @brief オブジェクトが強化可能な近接武器であるかを返す /
+ * Check if an object is melee weapon and allows enchantment
+ * @param o_ptr 対象のオブジェクト構造体ポインタ
+ * @return 強化可能な近接武器ならばTRUEを返す
+ */
+bool object_allow_enchant_melee_weapon(object_type *o_ptr)
{
-#if 0
- return get_object_x_attr_callback(o_ptr);
-#else
- return k_info[o_ptr->k_idx].x_attr;
-#endif
+ if (object_is_melee_weapon(o_ptr) && !object_refuse_enchant_weapon(o_ptr)) return TRUE;
+
+ return FALSE;
}
-/* Desired object attribute */
-char get_object_d_char(object_type *o_ptr)
+/*!
+ * @brief オブジェクトが鍛冶師のエッセンス付加済みかを返す /
+ * Check if an object is made by a smith's special ability
+ * @param o_ptr 対象のオブジェクト構造体ポインタ
+ * @return エッセンス付加済みならばTRUEを返す
+ */
+bool object_is_smith(object_type *o_ptr)
{
-#if 0
- return get_object_d_char_callback(o_ptr);
-#else
- return k_info[o_ptr->k_idx].d_char;
-#endif
-}
+ if (object_is_weapon_armour_ammo(o_ptr) && o_ptr->xtra3) return TRUE;
+ return FALSE;
+}
-/* Desired object character */
-char get_object_x_char(object_type *o_ptr)
+/*!
+ * @brief オブジェクトがアーティファクトかを返す /
+ * Check if an object is artifact
+ * @param o_ptr 対象のオブジェクト構造体ポインタ
+ * @return アーティファクトならばTRUEを返す
+ */
+bool object_is_artifact(object_type *o_ptr)
{
-#if 0
- return get_object_x_char_callback(o_ptr);
-#else
- return k_info[o_ptr->k_idx].x_char;
-#endif
+ if (object_is_fixed_artifact(o_ptr) || o_ptr->art_name) return TRUE;
+
+ return FALSE;
}
-/* The player is "aware" of the item's effects */
-bool get_object_aware(object_type *o_ptr)
+/*!
+ * @brief オブジェクトがランダムアーティファクトかを返す /
+ * Check if an object is random artifact
+ * @param o_ptr 対象のオブジェクト構造体ポインタ
+ * @return ランダムアーティファクトならばTRUEを返す
+ */
+bool object_is_random_artifact(object_type *o_ptr)
{
-#if 0
- return get_object_aware_callback(o_ptr);
-#else
- return k_info[o_ptr->k_idx].aware;
-#endif
-}
+ if (object_is_artifact(o_ptr) && !object_is_fixed_artifact(o_ptr)) return TRUE;
+ return FALSE;
+}
-/* The player has "tried" one of the items */
-bool get_object_tried(object_type *o_ptr)
+/*!
+ * @brief オブジェクトが通常のアイテム(アーティファクト、エゴ、鍛冶師エッセンス付加いずれでもない)かを返す /
+ * Check if an object is neither artifact, ego, nor 'smith' object
+ * @param o_ptr 対象のオブジェクト構造体ポインタ
+ * @return 通常のアイテムならばTRUEを返す
+ */
+bool object_is_nameless(object_type *o_ptr)
{
-#if 0
- return get_object_tried_callback(o_ptr);
-#else
- return k_info[o_ptr->k_idx].tried;
-#endif
+ if (!object_is_artifact(o_ptr) && !object_is_ego(o_ptr) && !object_is_smith(o_ptr))
+ return TRUE;
+
+ return FALSE;
}
-bool object_is_potion(object_type *o_ptr)
+/*!
+ * @brief オブジェクトが両手持ち可能な武器かを返す /
+ * Check if an object is melee weapon and allows wielding with two-hands
+ * @param o_ptr 対象のオブジェクト構造体ポインタ
+ * @return 両手持ち可能ならばTRUEを返す
+ */
+bool object_allow_two_hands_wielding(object_type *o_ptr)
{
- return (k_info[o_ptr->k_idx].tval == TV_POTION);
-}
+ if (object_is_melee_weapon(o_ptr) && ((o_ptr->weight > 99) || (o_ptr->tval == TV_POLEARM))) return TRUE;
-bool object_is_shoukinkubi(object_type *o_ptr)
-{
- int i;
- if (p_ptr->today_mon > 0 && o_ptr->pval == p_ptr->today_mon) return TRUE;
- if (o_ptr->pval == MON_TSUCHINOKO) return TRUE;
- for (i = 0; i < MAX_KUBI; i++)
- if (o_ptr->pval == kubi_r_idx[i]) break;
- if (i < MAX_KUBI) return TRUE;
return FALSE;
}