From f5ad2d06f0bac4de0a61d97b8887b70616006969 Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Tue, 15 Dec 2009 00:01:58 +0100 Subject: Make mimics hold the item they're mimicking, instead of fragile hacks with saving RNG state. --- crawl-ref/source/describe.cc | 10 +----- crawl-ref/source/directn.cc | 16 ++------- crawl-ref/source/mon-place.cc | 11 ++++++ crawl-ref/source/mon-stuff.cc | 79 +++++++++++++++++++++++++------------------ crawl-ref/source/mon-stuff.h | 3 +- crawl-ref/source/monster.cc | 8 ++--- crawl-ref/source/show.cc | 15 ++++---- crawl-ref/source/stash.cc | 9 ++--- crawl-ref/source/tilepick.cc | 11 ++---- crawl-ref/source/travel.cc | 12 ++----- 10 files changed, 81 insertions(+), 93 deletions(-) (limited to 'crawl-ref') diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index e77ff17982..83ea1d2e2b 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -2802,9 +2802,7 @@ void get_monster_db_desc(const monsters& mons, describe_info &inf, // For undetected mimics describe mimicked item instead. if (!force_seen && mons_is_unknown_mimic(&mons)) { - item_def item; - get_mimic_item(&mons, item); - get_item_desc(item, inf); + get_item_desc(get_mimic_item(&mons), inf); return; } @@ -2812,12 +2810,6 @@ void get_monster_db_desc(const monsters& mons, describe_info &inf, inf.title = mons.full_name(DESC_CAP_A, true); std::string db_name = mons.base_name(DESC_DBNAME, force_seen); - if (mons_is_mimic(mons.type) && mons.type != MONS_GOLD_MIMIC) - { - db_name = "mimic"; - if (inf.title.empty()) - inf.title = "A mimic"; - } // This is somewhat hackish, but it's a good way of over-riding monsters' // descriptions in Lua vaults by using MonPropsMarker. This is also the diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc index 34cef9c9f9..66d3b94f96 100644 --- a/crawl-ref/source/directn.cc +++ b/crawl-ref/source/directn.cc @@ -521,11 +521,7 @@ void full_describe_view() const bool unknown_mimic = (mon && mons_is_unknown_mimic(mon)); if (unknown_mimic) // It'll be on top. - { - item_def item; - get_mimic_item(mon, item); - list_items.push_back(item); - } + list_items.push_back(get_mimic_item(mon)); const int oid = igrd(*ri); if (oid == NON_ITEM) @@ -1754,11 +1750,7 @@ std::string get_terse_square_desc(const coord_def &gc) const monsters& mons = *monster_at(gc); if (mons_is_mimic(mons.type) && !(mons.flags & MF_KNOWN_MIMIC)) - { - item_def item; - get_mimic_item(&mons, item); - desc = item.name(DESC_PLAIN); - } + desc = get_mimic_item(&mons).name(DESC_PLAIN); else desc = mons.full_name(DESC_PLAIN, true); } @@ -3361,9 +3353,7 @@ static void _describe_cell(const coord_def& where, bool in_range) _describe_monster(mon); else { - item_def item; - get_mimic_item( mon, item ); - std::string name = get_menu_colour_prefix_tags(item, + std::string name = get_menu_colour_prefix_tags(get_mimic_item(mon), DESC_NOCAP_A); mprf(MSGCH_FLOOR_ITEMS, "You see %s here.", name.c_str()); } diff --git a/crawl-ref/source/mon-place.cc b/crawl-ref/source/mon-place.cc index 6629b8acf1..a4273c6a7c 100644 --- a/crawl-ref/source/mon-place.cc +++ b/crawl-ref/source/mon-place.cc @@ -1116,6 +1116,17 @@ static int _place_monster_aux(const mgen_data &mg, int id = mon->mindex(); env.mgrid(fpos) = id; + if (mons_is_mimic(mg.cls)) + { + // Mimics who mimic thin air get the axe. + if (!give_mimic_item(mon)) + { + mon->reset(); + mgrd(fpos) = NON_MONSTER; + return (-1); + } + } + // Generate a brand shiny new monster, or zombie. if (mons_class_is_zombified(mg.cls)) _define_zombie(id, mg.base_type, mg.cls, mg.power, fpos); diff --git a/crawl-ref/source/mon-stuff.cc b/crawl-ref/source/mon-stuff.cc index 4f9fa50ac8..2288d753db 100644 --- a/crawl-ref/source/mon-stuff.cc +++ b/crawl-ref/source/mon-stuff.cc @@ -62,13 +62,14 @@ static bool _wounded_damaged(monster_type mon_type); -// This function creates an artificial item to represent a mimic's -// appearance. Eventually, mimics could be redone to be more like -// dancing weapons: there'd only be one type and it would look like the -// item it carries. - bwr -void get_mimic_item( const monsters *mimic, item_def &item ) +int _make_mimic_item(monster_type type) { - ASSERT(mimic != NULL && mons_is_mimic( mimic->type)); + int it = items(0, OBJ_UNASSIGNED, 0, true, 0, 0); + + if (it == NON_ITEM) + return NON_ITEM; + + item_def &item = mitm[it]; item.base_type = OBJ_UNASSIGNED; item.sub_type = 0; @@ -78,22 +79,16 @@ void get_mimic_item( const monsters *mimic, item_def &item ) item.quantity = 1; item.plus = 0; item.plus2 = 0; - item.pos = mimic->pos(); item.link = NON_ITEM; - int prop = 127 * mimic->pos().x + 269 * mimic->pos().y; - - rng_save_excursion exc; - seed_rng( prop ); - - switch (mimic->type) + int prop; + switch (type) { case MONS_WEAPON_MIMIC: item.base_type = OBJ_WEAPONS; - item.sub_type = (59 * mimic->pos().x + 79 * mimic->pos().y) - % (WPN_MAX_NONBLESSED + 1); + item.sub_type = random2(WPN_MAX_NONBLESSED + 1); - prop %= 100; + prop = random2(100); if (prop < 20) make_item_randart(item); @@ -111,10 +106,9 @@ void get_mimic_item( const monsters *mimic, item_def &item ) case MONS_ARMOUR_MIMIC: item.base_type = OBJ_ARMOUR; - item.sub_type = (59 * mimic->pos().x + 79 * mimic->pos().y) - % NUM_ARMOURS; + item.sub_type = random2(NUM_ARMOURS); - prop %= 100; + prop = random2(100); if (prop < 20) make_item_randart(item); @@ -134,39 +128,55 @@ void get_mimic_item( const monsters *mimic, item_def &item ) case MONS_SCROLL_MIMIC: item.base_type = OBJ_SCROLLS; - item.sub_type = prop % NUM_SCROLLS; + item.sub_type = random2(NUM_SCROLLS); break; case MONS_POTION_MIMIC: item.base_type = OBJ_POTIONS; - item.sub_type = prop % NUM_POTIONS; + item.sub_type = random2(NUM_POTIONS); break; case MONS_GOLD_MIMIC: default: item.base_type = OBJ_GOLD; - item.quantity = 5 + prop % 30; + item.quantity = 5 + random2(1000); break; } item_colour(item); // also sets special vals for scrolls/potions + + return (it); +} + +item_def *give_mimic_item(monsters *mimic) +{ + ASSERT(mimic != NULL && mons_is_mimic(mimic->type)); + + mimic->destroy_inventory(); + int it = _make_mimic_item(mimic->type); + if (it == NON_ITEM) + return 0; + if (!mimic->pickup_misc(mitm[it], 0)) + ASSERT("Mimic failed to pickup its item."); + return (&mitm[mimic->inv[MSLOT_MISCELLANY]]); +} + +item_def &get_mimic_item(const monsters *mimic) +{ + ASSERT(mimic != NULL && mons_is_mimic(mimic->type)); + + ASSERT(mimic->inv[MSLOT_MISCELLANY] != NON_ITEM); + + return (mitm[mimic->inv[MSLOT_MISCELLANY]]); } // Sets the colour of a mimic to match its description... should be called // whenever a mimic is created or teleported. -- bwr int get_mimic_colour( const monsters *mimic ) { - ASSERT( mimic != NULL && mons_is_mimic( mimic->type ) ); + ASSERT(mimic != NULL); - if (mimic->type == MONS_SCROLL_MIMIC) - return (LIGHTGREY); - else if (mimic->type == MONS_GOLD_MIMIC) - return (YELLOW); - - item_def item; - get_mimic_item( mimic, item ); - - return (item.colour); + return (get_mimic_item(mimic).colour); } // Monster curses a random player inventory item. @@ -2126,6 +2136,8 @@ int monster_die(monsters *monster, killer_type killer, { _elven_twin_died(monster, in_transit); } + else if (mons_is_mimic(monster->type)) + monster->destroy_inventory(); else if (!monster->is_summoned()) { if (mons_genus(monster->type) == MONS_MUMMY) @@ -3733,7 +3745,10 @@ void monster_teleport(monsters *monster, bool instan, bool silent) monster_type old_type = monster->type; monster->type = static_cast( MONS_GOLD_MIMIC + random2(5)); + monster->destroy_inventory(); + give_mimic_item(monster); monster->colour = get_mimic_colour(monster); + was_seen = false; // If it's changed form, you won't recognise it. // This assumes that a non-gold mimic turning into another item of diff --git a/crawl-ref/source/mon-stuff.h b/crawl-ref/source/mon-stuff.h index 97acee430f..8455c89ecb 100644 --- a/crawl-ref/source/mon-stuff.h +++ b/crawl-ref/source/mon-stuff.h @@ -61,7 +61,8 @@ public: // for definition of type monsters {dlb} #include "externs.h" -void get_mimic_item( const monsters *mimic, item_def & item ); +item_def *give_mimic_item(monsters *mimic); +item_def &get_mimic_item(const monsters *mimic); int get_mimic_colour( const monsters *mimic ); void alert_nearby_monsters(void); diff --git a/crawl-ref/source/monster.cc b/crawl-ref/source/monster.cc index 4aff1df1c1..d31935af61 100644 --- a/crawl-ref/source/monster.cc +++ b/crawl-ref/source/monster.cc @@ -2065,12 +2065,8 @@ static std::string _str_monam(const monsters& mon, description_level_type desc, // Various special cases: // non-gold mimics, dancing weapons, ghosts, Pan demons - if (mons_is_mimic(mon.type) && mon.type != MONS_GOLD_MIMIC) - { - item_def item; - get_mimic_item(&mon, item); - return (item.name(desc)); - } + if (mons_is_mimic(mon.type)) + return (get_mimic_item(&mon).name(desc)); if (mon.type == MONS_DANCING_WEAPON && mon.inv[MSLOT_WEAPON] != NON_ITEM) { diff --git a/crawl-ref/source/show.cc b/crawl-ref/source/show.cc index 0d12f7f0ad..9ef5c303b9 100644 --- a/crawl-ref/source/show.cc +++ b/crawl-ref/source/show.cc @@ -218,19 +218,19 @@ static show_item_type _item_to_show_code(const item_def &item) void show_def::_update_item_at(const coord_def &gp, const coord_def &ep) { - item_def eitem; + item_def *eitem; // Check for mimics. const monsters* m = monster_at(gp); if (m && mons_is_unknown_mimic(m)) - get_mimic_item(m, eitem); + eitem = &get_mimic_item(m); else if (igrd(gp) != NON_ITEM) - eitem = mitm[igrd(gp)]; + eitem = &mitm[igrd(gp)]; else return; unsigned short &ecol = grid(ep).colour; - glyph g = get_item_glyph(&eitem); + glyph g = get_item_glyph(eitem); const dungeon_feature_type feat = grd(gp); if (Options.feature_item_brand && is_critical_feature(feat)) @@ -242,10 +242,13 @@ void show_def::_update_item_at(const coord_def &gp, const coord_def &ep) const unsigned short gcol = env.grid_colours(gp); ecol = (feat == DNGN_SHALLOW_WATER) ? (gcol != BLACK ? gcol : CYAN) : g.col; - if (eitem.link != NON_ITEM && !crawl_state.arena) + // monster(mimic)-owned items have link = NON_ITEM+1+midx + if (eitem->link > NON_ITEM && igrd(gp) != NON_ITEM) + ecol |= COLFLAG_ITEM_HEAP; + else if (eitem->link == NON_ITEM && !crawl_state.arena) ecol |= COLFLAG_ITEM_HEAP; grid(ep).cls = SH_ITEM; - grid(ep).item = _item_to_show_code(eitem); + grid(ep).item = _item_to_show_code(*eitem); } #ifdef USE_TILE diff --git a/crawl-ref/source/stash.cc b/crawl-ref/source/stash.cc index 9eb534b0ff..cb3a461b61 100644 --- a/crawl-ref/source/stash.cc +++ b/crawl-ref/source/stash.cc @@ -380,21 +380,16 @@ void Stash::update() // There's something on this square. Take a squint at it. const item_def *pitem; - item_def mimic_item; if (_grid_has_mimic_item(p)) - { - get_mimic_item(monster_at(p), mimic_item); - pitem = &mimic_item; - } + pitem = &get_mimic_item(monster_at(p)); else { pitem = &mitm[igrd(p)]; + tutorial_first_item(*pitem); } const item_def& item = *pitem; - tutorial_first_item(item); - if (!_grid_has_perceived_multiple_items(p)) items.clear(); diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc index 0e95c17d07..b8ac8a5941 100644 --- a/crawl-ref/source/tilepick.cc +++ b/crawl-ref/source/tilepick.cc @@ -769,12 +769,7 @@ int tileidx_monster_base(const monsters *mon, bool detected) case MONS_ARMOUR_MIMIC: case MONS_SCROLL_MIMIC: case MONS_POTION_MIMIC: - { - // Use item tile. - item_def item; - get_mimic_item( mon, item ); - return tileidx_item(item); - } + return tileidx_item(get_mimic_item(mon)); case MONS_DANCING_WEAPON: { @@ -4696,9 +4691,7 @@ void tile_place_monster(int gx, int gy, int idx, bool foreground, bool detected) t0 |= TILE_FLAG_S_UNDER; } - item_def item; - get_mimic_item( mon, item ); - if (item_needs_autopickup(item)) + if (item_needs_autopickup(get_mimic_item(mon)) { if (foreground) env.tile_bg[ep.x][ep.y] |= TILE_FLAG_CURSOR3; diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc index f8e4eb55cb..6da7bc6ee0 100644 --- a/crawl-ref/source/travel.cc +++ b/crawl-ref/source/travel.cc @@ -546,11 +546,7 @@ inline static void _check_interesting_square(int x, int y, if (const monsters *mons = monster_at(pos)) { if (mons_is_unknown_mimic(mons)) - { - item_def item; - get_mimic_item(mons, item); - ed.found_item(pos, item); - } + ed.found_item(pos, get_mimic_item(mons)); } if (igrd(pos) != NON_ITEM) @@ -1084,12 +1080,8 @@ static bool _is_greed_inducing_square(const LevelStashes *ls, if (const monsters *mons = monster_at(c)) { if (mons_is_unknown_mimic(mons) && mons_was_seen(mons)) - { - item_def mimic_item; - get_mimic_item(mons, mimic_item); - if (item_needs_autopickup(mimic_item)) + if (item_needs_autopickup(get_mimic_item(mons))) return (true); - } } return (false); } -- cgit v1.2.3-54-g00ecf