/* * Make a money object */ public static void make_gold(ref Object j_ptr, int lev, int coin_type) { int sval; /* This average is 20 at dlev0, 105 at dlev40, 220 at dlev100. */ /* Follows the formula: y=2x+20 */ int avg = 2 * lev + 20; int spread = lev + 10; int value = Random.rand_spread(avg, spread); /* Increase the range to infinite, moving the average to 110% */ while (Random.one_in_(100) && value * 10 <= short.MaxValue) { value *= 10; } /* Pick a treasure variety scaled by level, or force a type */ if (coin_type != (int)SVal.sval_gold.SV_GOLD_ANY) { sval = coin_type; } else { sval = (((value * 100) / MAX_GOLD_DROP) * (int)SVal.sval_gold.SV_GOLD_MAX) / 100; } /* Do not create illegal treasure types */ if (sval >= (int)SVal.sval_gold.SV_GOLD_MAX) { sval = (int)SVal.sval_gold.SV_GOLD_MAX - 1; } /* Prepare a gold object */ j_ptr.prep(Object_Kind.lookup_kind(TVal.TV_GOLD, sval), lev, aspect.RANDOMISE); /* If we're playing with no_selling, increase the value */ if (Option.birth_no_selling.value && Misc.p_ptr.depth != 0) { value = value * Math.Min(5, (int)Misc.p_ptr.depth); } /* Cap gold at max short (or alternatively make pvals s32b) */ if (value > short.MaxValue) { value = short.MaxValue; } j_ptr.pval[Misc.DEFAULT_PVAL] = (short)value; }
/** * Return the numeric sval of the object kind with the given `tval` and name `name`. */ public static int lookup_sval(int tval, string name) { uint r; if (uint.TryParse(name, out r)) { return((int)r); } /* Look for it */ for (int k = 1; k < Misc.z_info.k_max; k++) { Object_Kind k_ptr = Misc.k_info[k]; //Skip empty entries if (k_ptr == null) { continue; } string nm = k_ptr.Name; if (name == null) { continue; } //Basically, if name starts with &, skip the first two chars if (nm[0] == '&' && name.Length >= 2) { nm = nm.Substring(2); } //ORIGINAL //if (*nm == '&' && *(nm+1)) // nm += 2; /* Found a match */ if (k_ptr.tval == tval && name == nm) { return(k_ptr.sval); } } return(-1); }
//was in obj-util.c /** * Return the object kind with the given `tval` and `sval`, or null. */ public static Object_Kind lookup_kind(int tval, int sval) { /* Look for it */ for (int k = 0; k < Misc.z_info.k_max; k++) { Object_Kind kind = Misc.k_info[k]; if (kind == null) { continue; } if (kind.tval == tval && kind.sval == sval) { return(kind); } } /* Failure */ Utilities.msg("No object: {0}:{1} ({2})", tval, sval, TVal.find_name(tval)); return(null); }
static string obj_desc_get_modstr(Object_Kind kind) { switch (kind.tval) { case TVal.TV_AMULET: case TVal.TV_RING: case TVal.TV_STAFF: case TVal.TV_WAND: case TVal.TV_ROD: case TVal.TV_POTION: case TVal.TV_FOOD: case TVal.TV_SCROLL: return(kind.flavor != null ? kind.flavor.text : ""); case TVal.TV_MAGIC_BOOK: case TVal.TV_PRAYER_BOOK: return(kind.Name); } return(""); }
static void flavor_assign_fixed() { for (Flavor f = Misc.flavors; f != null; f = f.next) { if (f.sval == SVal.SV_UNKNOWN) { continue; } for (int i = 0; i < Misc.z_info.k_max; i++) { Object_Kind k = Misc.k_info[i]; if (k == null) { continue; } if (k.tval == f.tval && k.sval == f.sval) { k.flavor = f; } } } }
/* * Puts a very stripped-down version of an object's name into buf. * If easy_know is true, then the IDed names are used, otherwise * flavours, scroll names, etc will be used. * * Just truncates if the buffer isn't big enough. */ public static string object_kind_name(Object_Kind kind, bool easy_know) { string buf = ""; /* If not aware, use flavor */ if (!easy_know && !kind.aware && kind.flavor != null) { if (kind.tval == TVal.TV_FOOD && kind.sval > SVal.SV_FOOD_MIN_SHROOM) { buf = String.Format("{0} Mushroom", kind.flavor.text); } else { /* Plain flavour (e.g. Copper) will do. */ buf = kind.flavor.text; } } /* Use proper name (Healing, or whatever) */ else { string t = ""; if (kind.tval == TVal.TV_FOOD && kind.sval > SVal.SV_FOOD_MIN_SHROOM) { buf = "Mushroom of "; } /* Format remainder of the string */ obj_desc_name_format(ref t, kind.Name, null, false); buf += t; } return(buf); }
/* * Puts a very stripped-down version of an object's name into buf. * If easy_know is true, then the IDed names are used, otherwise * flavours, scroll names, etc will be used. * * Just truncates if the buffer isn't big enough. */ public static string object_kind_name(Object_Kind kind, bool easy_know) { string buf = ""; /* If not aware, use flavor */ if (!easy_know && !kind.aware && kind.flavor != null) { if (kind.tval == TVal.TV_FOOD && kind.sval > SVal.SV_FOOD_MIN_SHROOM) { buf = String.Format("{0} Mushroom", kind.flavor.text); } else { /* Plain flavour (e.g. Copper) will do. */ buf = kind.flavor.text; } } /* Use proper name (Healing, or whatever) */ else { string t = ""; if (kind.tval == TVal.TV_FOOD && kind.sval > SVal.SV_FOOD_MIN_SHROOM) { buf = "Mushroom of "; } /* Format remainder of the string */ obj_desc_name_format(ref t, kind.Name, null, false); buf += t; } return buf; }
/* * Mega-Hack -- Attempt to create one of the "Special Objects". * * We are only called from "make_object()" * * Note -- see "make_artifact()" and "apply_magic()". * * We *prefer* to create the special artifacts in order, but this is * normally outweighed by the "rarity" rolls for those artifacts. */ static bool make_artifact_special(ref Object o_ptr, int level) { int i; Object_Kind kind; /* No artifacts, do nothing */ if (Option.birth_no_artifacts.value) { return(false); } /* No artifacts in the town */ if (Misc.p_ptr.depth == 0) { return(false); } /* Check the special artifacts */ for (i = 0; i < Misc.ART_MIN_NORMAL; ++i) { Artifact a_ptr = Misc.a_info[i]; /* Skip "empty" artifacts */ if (a_ptr == null) { continue; } /* Cannot make an artifact twice */ if (a_ptr.created) { continue; } /* Enforce minimum "depth" (loosely) */ if (a_ptr.alloc_min > Misc.p_ptr.depth) { /* Get the "out-of-depth factor" */ int d = (a_ptr.alloc_min - Misc.p_ptr.depth) * 2; /* Roll for out-of-depth creation */ if (Random.randint0(d) != 0) { continue; } } /* Enforce maximum depth (strictly) */ if (a_ptr.alloc_max < Misc.p_ptr.depth) { continue; } /* Artifact "rarity roll" */ if (Random.randint1(100) > a_ptr.alloc_prob) { continue; } /* Find the base object */ kind = Object_Kind.lookup_kind(a_ptr.tval, a_ptr.sval); /* Make sure the kind was found */ if (kind == null) { continue; } /* Enforce minimum "object" level (loosely) */ if (kind.level > level) { /* Get the "out-of-depth factor" */ int d = (kind.level - level) * 5; /* Roll for out-of-depth creation */ if (Random.randint0(d) != 0) { continue; } } /* Assign the template */ o_ptr.prep(kind, a_ptr.alloc_min, aspect.RANDOMISE); /* Mark the item as an artifact */ o_ptr.artifact = a_ptr; /* Copy across all the data from the artifact struct */ o_ptr.copy_artifact_data(a_ptr); /* Mark the artifact as "created" */ a_ptr.created = true; /* Success */ return(true); } /* Failure */ return(false); }
/* * Determine if the attr and char should consider the item's flavor * * Identified scrolls should use their own tile. */ public static bool use_flavor_glyph(Object_Kind kind) { return ((kind).flavor != null && !((kind).tval == TVal.TV_SCROLL && (kind).aware)); }
/* * Return the "char" for a given item kind. * Use "flavor" if available. * Default to user definitions. */ public static char object_kind_char(Object_Kind k) { return (use_flavor_glyph(k) ? (k.flavor.x_char) : (k.x_char)); }
/* * Return the "attr" for a given item kind. * Use "flavor" if available. * Default to user definitions. */ public static ConsoleColor object_kind_attr(Object_Kind k) { return (use_flavor_glyph((k)) ? (k.flavor.x_attr) : (k.x_attr)); }
/* * Hack -- determine if a template is "good". * * Note that this test only applies to the object *kind*, so it is * possible to choose a kind which is "good", and then later cause * the actual object to be cursed. We do explicitly forbid objects * which are known to be boring or which start out somewhat damaged. */ static bool kind_is_good(Object_Kind kind) { /* Analyze the item type */ switch (kind.tval) { /* Armor -- Good unless damaged */ case TVal.TV_HARD_ARMOR: case TVal.TV_SOFT_ARMOR: case TVal.TV_DRAG_ARMOR: case TVal.TV_SHIELD: case TVal.TV_CLOAK: case TVal.TV_BOOTS: case TVal.TV_GLOVES: case TVal.TV_HELM: case TVal.TV_CROWN: { if (Random.randcalc(kind.to_a, 0, aspect.MINIMISE) < 0) return (false); return (true); } /* Weapons -- Good unless damaged */ case TVal.TV_BOW: return true; //HACK, it seems as if bows do no damage!!! case TVal.TV_SWORD: case TVal.TV_HAFTED: case TVal.TV_POLEARM: case TVal.TV_DIGGING: { if (Random.randcalc(kind.to_h, 0, aspect.MINIMISE) < 0) return (false); if (Random.randcalc(kind.to_d, 0, aspect.MINIMISE) < 0) return (false); return (true); } /* Ammo -- Arrows/Bolts are good */ case TVal.TV_BOLT: case TVal.TV_ARROW: { return (true); } /* Books -- High level books are good */ case TVal.TV_MAGIC_BOOK: case TVal.TV_PRAYER_BOOK: { if (kind.sval >= SVal.SV_BOOK_MIN_GOOD) return (true); return (false); } /* Rings -- Rings of Speed are good */ case TVal.TV_RING: { if (kind.sval == (byte)SVal.sval_ring.SV_RING_SPEED) return (true); return (false); } /* Amulets -- Amulets of the Magi are good */ case TVal.TV_AMULET: { if (kind.sval == (byte)SVal.sval_amulet.SV_AMULET_THE_MAGI) return (true); if (kind.sval == (byte)SVal.sval_amulet.SV_AMULET_DEVOTION) return (true); if (kind.sval == (byte)SVal.sval_amulet.SV_AMULET_WEAPONMASTERY) return (true); if (kind.sval == (byte)SVal.sval_amulet.SV_AMULET_TRICKERY) return (true); return (false); } } /* Assume not good */ return (false); }
public void WIPE() { kind = null; number = 0; }
/** * Wipe an object clean and make it a standard object of the specified kind. * Was previous "object_prep", is now a constructor for Object */ public void prep(Object_Kind k, int lev, aspect rand_aspect) { int flag, x; Bitflag flags = new Bitflag(Object_Flag.SIZE); // Assign the kind and copy across data this.kind = k; this.tval = k.tval; this.sval = k.sval; this.ac = k.ac; this.dd = k.dd; this.ds = k.ds; this.weight = k.weight; // Default number this.number = 1; for(int i = 0; i < pval_flags.Length; i++) { pval_flags[i] = new Bitflag(Object_Flag.SIZE); } // Apply pvals and then copy flags for (int i = 0; i < k.num_pvals; i++) { flags.copy(k.pval_flags[i]); flags.copy(k.pval_flags[i]); x = Random.randcalc(k.pval[i], lev, rand_aspect); for (flag = flags.next(Bitflag.FLAG_START); flag != Bitflag.FLAG_null; flag = flags.next(flag + 1)) add_pval(x, flag); } if(k.Base != null) { flags.copy(k.Base.flags); } flags.union(k.flags); // Assign charges (wands/staves only) if (tval == TVal.TV_WAND || tval == TVal.TV_STAFF) pval[Misc.DEFAULT_PVAL] = (short)Random.randcalc(k.charge, lev, rand_aspect); // Assign flagless pval for food or oil if (tval == TVal.TV_FOOD || tval == TVal.TV_POTION || tval == TVal.TV_FLASK) pval[Misc.DEFAULT_PVAL] = (short)Random.randcalc(k.pval[Misc.DEFAULT_PVAL], lev, rand_aspect); // Default fuel for lamps if (tval == TVal.TV_LIGHT) { if(sval == SVal.SV_LIGHT_TORCH) timeout = Misc.DEFAULT_TORCH; else if(sval == SVal.SV_LIGHT_LANTERN) timeout = Misc.DEFAULT_LAMP; } // Default magic to_h = (short)Random.randcalc(k.to_h, lev, rand_aspect); to_d = (short)Random.randcalc(k.to_d, lev, rand_aspect); to_a = (short)Random.randcalc(k.to_a, lev, rand_aspect); }
/* * Helper function: create an item with the given tval,sval pair, add it to the * store st. Return the slot in the inventory. */ int create_item(Object_Kind kind) { Object.Object obj = new Object.Object(); /* Create a new object of the chosen kind */ obj.prep(kind, 0, aspect.RANDOMISE); /* Item belongs to a store */ obj.ident |= Object.Object.IDENT_STORE; obj.origin = Origin.STORE; /* Attempt to carry the object */ return carry(obj); }
/* * Prepare the "variable" part of the "k_info" array. * * The "color"/"metal"/"type" of an item is its "flavor". * For the most part, flavors are assigned randomly each game. * * Initialize descriptions for the "colored" objects, including: * Rings, Amulets, Staffs, Wands, Rods, Food, Potions, Scrolls. * * The first 4 entries for potions are fixed (Water, Apple Juice, * Slime Mold Juice, Unused Potion). * * Scroll titles are always between 6 and 14 letters long. This is * ensured because every title is composed of whole words, where every * word is from 2 to 8 letters long, and that no scroll is finished * until it attempts to grow beyond 15 letters. The first time this * can happen is when the current title has 6 letters and the new word * has 8 letters, which would result in a 6 letter scroll title. * * Hack -- make sure everything stays the same for each saved game * This is accomplished by the use of a saved "random seed", as in * "town_gen()". Since no other functions are called while the special * seed is in effect, so this function is pretty "safe". */ public static void init() { int i, j; /* Hack -- Use the "simple" RNG */ Random.Rand_quick = true; /* Hack -- Induce consistant flavors */ Random.Rand_value = (uint)Misc.seed_flavor; flavor_assign_fixed(); flavor_assign_random(TVal.TV_RING); flavor_assign_random(TVal.TV_AMULET); flavor_assign_random(TVal.TV_STAFF); flavor_assign_random(TVal.TV_WAND); flavor_assign_random(TVal.TV_ROD); flavor_assign_random(TVal.TV_FOOD); flavor_assign_random(TVal.TV_POTION); /* Scrolls (random titles, always white) */ for (i = 0; i < MAX_TITLES; i++) { string buf = "\""; //26 string end = ""; int titlelen = 0; int wordlen; bool okay = true; wordlen = RandomName.randname_make(RandomName.randname_type.RANDNAME_SCROLL, 2, 8, ref end, 24, RandomName.name_sections); while (titlelen + wordlen < (int)(18 - 3)) //was scroll_adj[0].Length - 3, but we no longer have to worry about the null terminator { buf += end + " "; //end[wordlen] = ' '; titlelen += wordlen + 1; //end += wordlen + 1; end = ""; wordlen = RandomName.randname_make(RandomName.randname_type.RANDNAME_SCROLL, 2, 8, ref end, 24 - titlelen, RandomName.name_sections); } buf += end + "\""; //buf[titlelen] = '"'; //buf[titlelen+1] = '\0'; /* Check the scroll name hasn't already been generated */ for (j = 0; j < i; j++) { if (buf == scroll_adj[j]) { okay = false; break; } } if (okay) { scroll_adj[i] = buf; } else { /* Have another go at making a name */ i--; } } flavor_assign_random(TVal.TV_SCROLL); /* Hack -- Use the "complex" RNG */ Random.Rand_quick = false; /* Analyze every object */ for (i = 1; i < Misc.z_info.k_max; i++) { Object_Kind k_ptr = Misc.k_info[i]; /* Skip "empty" objects */ if (k_ptr == null || k_ptr.Name == null || k_ptr.Name.Length == 0) { continue; } /* No flavor yields aware */ if (k_ptr.flavor == null) { k_ptr.aware = true; } } }
/*** Autoinscription stuff ***/ public static string get_autoinscription(Object_Kind kind) { return (kind != null) && (kind.note != null) ? kind.note.ToString() : null; }
public static bool kind_is_squelched_unaware(Object_Kind k_ptr) { return (k_ptr.squelch & SQUELCH_IF_UNAWARE) != 0 ? true : false; }
/* * Remove any squelching of a particular flavor */ public static void kind_squelch_clear(Object_Kind k_ptr) { throw new NotImplementedException(); //k_ptr.squelch = 0; //p_ptr.notice |= PN_SQUELCH; }
/* Parsing functions for object.txt */ public static Parser.Error parse_k_n(Parser p) { int idx = p.getint("index"); string name = p.getstr("name"); Object_Kind h = p.priv as Object_Kind; Object_Kind k = new Object_Kind(); k.next = h; p.priv = k; k.kidx = (uint)idx; k.Name = name; return Parser.Error.NONE; }
static string obj_desc_get_modstr(Object_Kind kind) { switch (kind.tval) { case TVal.TV_AMULET: case TVal.TV_RING: case TVal.TV_STAFF: case TVal.TV_WAND: case TVal.TV_ROD: case TVal.TV_POTION: case TVal.TV_FOOD: case TVal.TV_SCROLL: return kind.flavor != null ? kind.flavor.text : ""; case TVal.TV_MAGIC_BOOK: case TVal.TV_PRAYER_BOOK: return kind.Name; } return ""; }
public static void kind_squelch_when_unaware(Object_Kind k_ptr) { throw new NotImplementedException(); //k_ptr.squelch |= SQUELCH_IF_UNAWARE; //p_ptr.notice |= PN_SQUELCH; }
public static void wr_object_memory() { wr_u16b(Misc.z_info.k_max); for (int k_idx = 0; k_idx < Misc.z_info.k_max; k_idx++) { byte tmp8u = 0; Object_Kind k_ptr = Misc.k_info[k_idx]; if (k_ptr == null) { k_ptr = new Object_Kind(); } if (k_ptr.aware) tmp8u |= 0x01; if (k_ptr.tried) tmp8u |= 0x02; if (Squelch.kind_is_squelched_aware(k_ptr)) tmp8u |= 0x04; if (k_ptr.everseen) tmp8u |= 0x08; if (Squelch.kind_is_squelched_unaware(k_ptr)) tmp8u |= 0x10; wr_byte(tmp8u); } }
/* * Reset the "visual" lists * * This involves resetting various things to their "default" state. * * If the "prefs" flag is true, then we will also load the appropriate * "user pref file" based on the current setting of the "use_graphics" * flag. This is useful for switching "graphics" on/off. */ /* XXX this does not belong here */ //Todo: Figure out where it goes. At a glance, init seems nice. //Nick: Was previously in "obj-util.c"... lulz public static void reset_visuals(bool load_prefs) { int i; Flavor f; /* Extract default attr/char code for features */ for (i = 0; i < Misc.z_info.f_max; i++) { int j; Feature f_ptr = Misc.f_info[i]; /* Assume we will use the underlying values */ for (j = 0; j < (int)Grid_Data.grid_light_level.FEAT_LIGHTING_MAX; j++) { f_ptr.x_attr[j] = f_ptr.d_attr; f_ptr.x_char[j] = f_ptr.d_char; } } /* Extract default attr/char code for objects */ for (i = 0; i < Misc.z_info.k_max; i++) { Object.Object_Kind k_ptr = Misc.k_info[i]; if (k_ptr == null) { continue; } /* Default attr/char */ k_ptr.x_attr = k_ptr.d_attr; k_ptr.x_char = k_ptr.d_char; } /* Extract default attr/char code for monsters */ for (i = 0; i < Misc.z_info.r_max; i++) { Monster.Monster_Race r_ptr = Misc.r_info[i]; if (r_ptr == null) { continue; } /* Default attr/char */ r_ptr.x_attr = r_ptr.d_attr; r_ptr.x_char = r_ptr.d_char; } /* Extract default attr/char code for flavors */ for (f = Misc.flavors; f != null; f = f.next) { f.x_attr = f.d_attr; f.x_char = f.d_char; } /* Extract attr/chars for inventory objects (by tval) */ for (i = 0; i < Misc.tval_to_attr.Length; i++) { /* Default to white */ Misc.tval_to_attr[i] = ConsoleColor.White; } if (!load_prefs) { return; } /* Graphic symbols */ if (Misc.use_graphics != 0) { Prefs.process_pref_file("graf.prf", false, false); } /* Normal symbols */ else { Prefs.process_pref_file("font.prf", false, false); } //#ifdef ALLOW_BORG_GRAPHICS // /* Initialize the translation table for the borg */ // init_translate_visuals(); //#endif /* ALLOW_BORG_GRAPHICS */ }