From 1e5379801fcefa4a1a3ea5f7301e2e48bf3a5ac8 Mon Sep 17 00:00:00 2001 From: GenericPseudonym Date: Sun, 27 Jan 2019 19:18:59 -0800 Subject: [PATCH 001/864] Quiet confirm_action in the ability menu (11738) The confirm prompt was still being generated when _check_ability_possible was called in "quiet" mode, though it shouldn't have been. [Committer's note: Closes #969] --- crawl-ref/source/ability.cc | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/crawl-ref/source/ability.cc b/crawl-ref/source/ability.cc index 58ed9906e448..e92472c37303 100644 --- a/crawl-ref/source/ability.cc +++ b/crawl-ref/source/ability.cc @@ -1420,21 +1420,24 @@ static bool _check_ability_possible(const ability_def& abil, bool quiet = false) return false; } - vector &actions = Options.confirm_action; - if (!actions.empty()) + if (!quiet) { - const char* name = ability_name(abil.ability); - for (const text_pattern &action : actions) + vector &actions = Options.confirm_action; + if (!actions.empty()) { - if (action.matches(name)) + const char* name = ability_name(abil.ability); + for (const text_pattern &action : actions) { - string prompt = "Really use " + string(name) + "?"; - if (!yesno(prompt.c_str(), false, 'n')) + if (action.matches(name)) { - canned_msg(MSG_OK); - return false; + string prompt = "Really use " + string(name) + "?"; + if (!yesno(prompt.c_str(), false, 'n')) + { + canned_msg(MSG_OK); + return false; + } + break; } - break; } } } From 14c3f5860993aa9edc8d22cfad4248eb7deb881a Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 29 Jan 2019 15:13:02 -0500 Subject: [PATCH 002/864] Expand out the seed vs generation test for a few more levels --- crawl-ref/source/test/d1_vaults.lua | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/test/d1_vaults.lua b/crawl-ref/source/test/d1_vaults.lua index d5a4347ef129..38f9f2ce0a74 100644 --- a/crawl-ref/source/test/d1_vaults.lua +++ b/crawl-ref/source/test/d1_vaults.lua @@ -8,6 +8,7 @@ local eol = string.char(13) for seed = 1,10 do + crawl.stderr("Seed: " .. seed .. eol) debug.reset_rng(seed) -- debug.enter_dungeon() crashes, for some reason -- the following runs through RNG state in the same way that starting a @@ -18,7 +19,22 @@ for seed = 1,10 do debug.generate_level() local vault_names = debug.vault_names() - crawl.stderr("D:1 vaults for seed " .. seed .. " are: " .. vault_names .. eol) + crawl.stderr(" D:1 vaults for seed " .. seed .. " are: " .. vault_names .. eol) + debug.goto_place("D:2") + debug.generate_level() + local vault_names = debug.vault_names() + + crawl.stderr(" D:2 vaults for seed " .. seed .. " are: " .. vault_names .. eol) + debug.goto_place("D:3") + debug.generate_level() + local vault_names = debug.vault_names() + + crawl.stderr(" D:3 vaults for seed " .. seed .. " are: " .. vault_names .. eol) + debug.goto_place("D:4") + debug.generate_level() + local vault_names = debug.vault_names() + + crawl.stderr(" D:4 vaults for seed " .. seed .. " are: " .. vault_names .. eol) end debug.reset_rng(1) From cdddf7c89e994c9635ff92de1d7f98a855bda0c5 Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 29 Jan 2019 15:07:19 -0500 Subject: [PATCH 003/864] Sequence many, many random calls whose order was undefined Also add some documentation about these issues for other developers. Basically, the call order for functions that are present in an arithmetic expression or a constructor is undefined and can vary (leading to different effects of seed). It would be foolish to think that this got everything, but I hope that this did get everything for dungeon generation per se; given the complexity of this problem getting real seeding for the gameplay UI may be a bit far off. Two areas of concern: * random_var is clever and fun, but also inherently not a good fit for wanting well-sequenced rng calls, because operators inherit this undefinedness. * I didn't really try to address div_rand_round in this commit, which is all over the place and potentially hidden in many return calls. --- crawl-ref/docs/develop/rng_guidelines.md | 133 +++++++++++++++++++++++ crawl-ref/source/abyss.cc | 20 ++-- crawl-ref/source/acquire.cc | 14 ++- crawl-ref/source/art-func.h | 15 ++- crawl-ref/source/beam.cc | 17 ++- crawl-ref/source/coord.cc | 15 ++- crawl-ref/source/dgn-irregular-box.cc | 16 ++- crawl-ref/source/dgn-layouts.cc | 32 ++++-- crawl-ref/source/dgn-shoals.cc | 18 +-- crawl-ref/source/dgn-swamp.cc | 7 +- crawl-ref/source/directn.cc | 6 +- crawl-ref/source/dungeon.cc | 47 +++++--- crawl-ref/source/evoke.cc | 26 +++-- crawl-ref/source/god-abil.cc | 14 ++- crawl-ref/source/mapdef.cc | 7 +- crawl-ref/source/maps.cc | 5 +- crawl-ref/source/melee-attack.cc | 3 +- crawl-ref/source/mon-behv.cc | 6 +- crawl-ref/source/mon-cast.cc | 23 ++-- crawl-ref/source/mon-movetarget.cc | 4 +- crawl-ref/source/mon-place.cc | 11 +- crawl-ref/source/ng-init.cc | 8 +- crawl-ref/source/ng-setup.cc | 7 +- crawl-ref/source/player.cc | 3 +- crawl-ref/source/random-var.cc | 34 ++++-- crawl-ref/source/shout.cc | 6 +- crawl-ref/source/teleport.cc | 8 +- crawl-ref/source/throw.cc | 4 +- crawl-ref/source/timed-effects.cc | 23 +++- crawl-ref/source/traps.cc | 15 +-- crawl-ref/source/view.cc | 4 +- crawl-ref/source/xom.cc | 6 +- 32 files changed, 412 insertions(+), 145 deletions(-) create mode 100644 crawl-ref/docs/develop/rng_guidelines.md diff --git a/crawl-ref/docs/develop/rng_guidelines.md b/crawl-ref/docs/develop/rng_guidelines.md new file mode 100644 index 000000000000..bba99d8f535a --- /dev/null +++ b/crawl-ref/docs/develop/rng_guidelines.md @@ -0,0 +1,133 @@ +# Developer guidelines for using random numbers in DCSS + +Crawl attempts to be deterministically seeded: given a seed (that may be +chosen randomly), dungeon generation (and ideally, everything) is deterministic +thereafter. It does this by using a random number generator that has +"reproducible" behavior, +[http://www.pcg-random.org/](http://www.pcg-random.org/). This leads to certain +practices and caveats that help maintain the usefulness of seeding. + +## 1. Background + +First, it may help to know a bit about how our RNG works. Given some seed, +a PCG generator generates a sequence of 32-bit unsigned integers, that is +deterministic but hard to predict. You can think of this like a code book: +for a given seed, the integer at index i will always be the same. The various +random functions (e.g. `random2`) then package information from these integers +in a way that is a bit more usable while programming. This means that the state +of the RNG is equivalent to the *number of draws from the generator*. If this +number of draws diverges for any reason between e.g. two versions of crawl, +then the randomization behavior will sharply diverge, probably permanently, +very soon after that. In most cases, the results of a single random draw at +some point in code execution will impact the number of random draws at a later +point. For example, during dungeon generation, the position of a vault might +be chosen by two `random2` calls (which usually does correspond to two random +draws from the raw generator). The position of this vault will then impact what +other vaults can be placed in the same layout, which is checked (roughly) by +randomly trying vaults until one fits -- which will lead to varying numbers of +rng draws. + +The dungeon generator RNGs are partitioned by branch, and separate from the UI +and gameplay RNGs. However, vault choice is not fully independent across branch, +so the order of branch generation matters quite a bit. Given a fixed order, a +seed *should* fully determine a dungeon, but this mapping is quite delicate. + +## 2. Breaking seed mappings + +The following changes (which are often desireable changes) can break the seed +to dungeon mappings, in some way: + +* adding or removing a vault +* adding or removing monster types or uniques +* adding or removing items, unique or otherwise + +It is extremely hard to predict how big the break will be -- it may be small, +or it may result in an entirely different dungeon. (For example, changing D:1 +arrival vaults will likely drastically change the mapping.) + +For this reason, seeds should be assumed to be tied to a specific version of +dungeon crawl. Changes that break seeds for stable releases should be avoided +without introducing a new stable release right away -- because online servers +usually update right away, this will cause seeds to diverge between online and +offline versions. + +All bets are off for trunk seed->dungeon mappings, which might at best be +specific to a single commit. Similarly, upgrading a game (trunk or otherwise) +where the dungeon is not pregenerated will lead to divergence from *both* seed +to dungeon mappings. + +## 3. Specific coding guidelines and caveats + +The biggest challenge in ensuring stable seed to dungeon mappings involves +ensuring that random numbers are drawn from the generators in the same order. +There are two specific areas where care is required. + +### 3.1 random call evaluation order + +C++, in many cases, does not guarantee stable evaluation order for function +calls, and this can result in different behaviors across compilers, OSs, and +potentially even execution instances. For background, see: + +* [https://en.cppreference.com/w/cpp/language/eval_order](https://en.cppreference.com/w/cpp/language/eval_order) +* [https://wiki.sei.cmu.edu/confluence/display/cplusplus/EXP50-CPP.+Do+not+depend+on+the+order+of+evaluation+for+side+effects](https://wiki.sei.cmu.edu/confluence/display/cplusplus/EXP50-CPP.+Do+not+depend+on+the+order+of+evaluation+for+side+effects) + +Because the RNG system works by side-effect, this means that there are various +cases where the compiler doesn't guarantee the order of random call side-effect. +The two most important cases to watch out for are: + +* order of calls within arithmetic expressions, and +* order of calls within comma-separated arguments to functions, including + constructors. + +For example, expressions like the following *does not have a guaranteed order of +function calls* in any version of C or C++: + + const int x = 10 + random2(5) - random2(3); // bad + auto y = f(random2(5), random2(3)); // bad + +A particularly tempting paradigm that was common in dcss code before seeding +that instantiates the latter is: + + const coord_def pos(random2(5), random2(5)); // bad + +This is not a theoretical concern: we have found that the order of calls in +cases like these does vary in practice between different compilers on different +OSs, and so any of these calls might get different results. (Because of the +layers of abstraction, the results of swapping call order are not as simple as +swapping the random number results, even if the calls appear the same.) + +In order to get stable behavior, what you need to do is ensure a "sequence +point" between any random number calls (see the links above). This unfortunately +leads to less compact code, and cases where `const`ing is not possible. For +example, here is a better version of two of the above cases: + + int x = 10 + random2(5); // sequence point + x -= random2(3); + + coord_def pos; + pos.x = random2(5); + pos.y = random2(5); + +Even operators that are commutative (e.g. `+`), because of the way `random2` is +implemented, in principle aren't safe to have in the same expression. + +What sorts of expressions *do* ensure evaluation order? See the above links for +the gory details, but the main safe one is boolean expressions, which do have a +stable order. This does include `? :` expressions. So for example the following +is ok (at least in terms of RNG call sequencing): + + if (x_chance_in_y(1,5) && coinflip()) // stable sequencing + do_something(); + +For everything else, when in doubt, break it into multiple expressions +that are sequenced by `;`s. + +### 3.2 choosing from lists + +When you are randomly choosing an item from a list (e.g. by randomly picking +an index in the list range), be careful about the underlying list order. This +is a case where the RNG behavior can be fine, but the list order itself could +lead to divergence. For example, when choosing from a list of files provided +by the OS, you cannot assume that all OSs and OS versions will give you these +files in a stable order - sort it yourself. + diff --git a/crawl-ref/source/abyss.cc b/crawl-ref/source/abyss.cc index 64886edfe698..48d8b58b81a4 100644 --- a/crawl-ref/source/abyss.cc +++ b/crawl-ref/source/abyss.cc @@ -87,8 +87,10 @@ static coord_def _place_feature_near(const coord_def ¢re, coord_def cp = INVALID_COORD; for (int i = 0; i < tries; ++i) { - cp = centre + coord_def(random_range(-radius, radius), - random_range(-radius, radius)); + coord_def offset; + offset.x = random_range(-radius, radius); + offset.y = random_range(-radius, radius); + cp = centre + offset; if (cp == centre || !in_bounds(cp)) continue; @@ -1242,7 +1244,8 @@ static void _update_abyss_terrain(const coord_def &p, if (feat == DNGN_FLOOR && in_los_bounds_g(rp)) { cloud_type cloud = _cloud_from_feat(currfeat); - int cloud_life = (_in_wastes(abyssal_state.major_coord) ? 5 : 2) + random2(2); + int cloud_life = _in_wastes(abyssal_state.major_coord) ? 5 : 2; + cloud_life += random2(2); // force a sequence point, just in case if (cloud != CLOUD_NONE) check_place_cloud(_cloud_from_feat(currfeat), rp, cloud_life, 0, 3); } @@ -1772,10 +1775,13 @@ static bool _spawn_corrupted_servant_near(const coord_def &pos) // Thirty tries for a place. for (int i = 0; i < 30; ++i) { - const int offsetX = random2avg(4, 3) + random2(3); - const int offsetY = random2avg(4, 3) + random2(3); - const coord_def p(pos.x + random_choose(offsetX, -offsetX), - pos.y + random_choose(offsetY, -offsetY)); + int offsetX = random2avg(4, 3); + offsetX += random2(3); // force a sequence point between random calls + int offsetY = random2avg(4, 3); + offsetY += random2(3); // ditto + coord_def p; + p.x = pos.x + random_choose(offsetX, -offsetX); + p.y = pos.y + random_choose(offsetY, -offsetY); if (!in_bounds(p) || actor_at(p)) continue; diff --git a/crawl-ref/source/acquire.cc b/crawl-ref/source/acquire.cc index 9cb241a6ae41..301064df0f95 100644 --- a/crawl-ref/source/acquire.cc +++ b/crawl-ref/source/acquire.cc @@ -271,9 +271,10 @@ static armour_type _acquirement_body_armour(bool divine) { // Using an arbitrary legacy formula, do we think the player doesn't care // about armour EVP? - const bool warrior = random2(_skill_rdiv(SK_SPELLCASTING, 3) - + _skill_rdiv(SK_DODGING)) - < random2(_skill_rdiv(SK_ARMOUR, 2)); + int light_pref = _skill_rdiv(SK_SPELLCASTING, 3); + light_pref += _skill_rdiv(SK_DODGING); + light_pref = random2(light_pref); + const bool warrior = light_pref < random2(_skill_rdiv(SK_ARMOUR, 2)); vector> weights; for (int i = ARM_FIRST_MUNDANE_BODY; i < NUM_ARMOURS; ++i) @@ -1350,11 +1351,12 @@ int acquirement_create_item(object_class_type class_wanted, { // New gold acquirement formula from dpeg. // Min=220, Max=5520, Mean=1218, Std=911 + int quantity_rnd = roll_dice(1, 8); // ensure rnd sequence points + quantity_rnd *= roll_dice(1, 8); + quantity_rnd *= roll_dice(1, 8); acq_item.quantity = 10 * (20 + roll_dice(1, 20) - + (roll_dice(1, 8) - * roll_dice(1, 8) - * roll_dice(1, 8))); + + quantity_rnd); } else if (class_wanted == OBJ_MISSILES && !divine) acq_item.quantity *= 5; diff --git a/crawl-ref/source/art-func.h b/crawl-ref/source/art-func.h index 5dd2bd41c9e6..a8a762ee7b86 100644 --- a/crawl-ref/source/art-func.h +++ b/crawl-ref/source/art-func.h @@ -154,8 +154,9 @@ static void _CURSES_equip(item_def *item, bool *show_msgs, bool unmeld) _equip_mpr(show_msgs, "A shiver runs down your spine."); if (!unmeld) { + const int pow = random2(9); MiscastEffect(&you, nullptr, {miscast_source::wield}, - spschool::necromancy, random2(9), random2(70), + spschool::necromancy, pow, random2(70), "the scythe of Curses", nothing_happens::NEVER); } } @@ -174,8 +175,9 @@ static void _CURSES_melee_effects(item_def* weapon, actor* attacker, did_god_conduct(DID_EVIL, 3); if (!mondied && defender->holiness() == MH_NATURAL) { + const int pow = random2(9); MiscastEffect(defender, attacker, {miscast_source::melee}, - spschool::necromancy, random2(9), random2(70), + spschool::necromancy, pow, random2(70), "the scythe of Curses", nothing_happens::NEVER); } } @@ -502,7 +504,8 @@ static bool _WUCAD_MU_evoke(item_def *item, bool* did_work, bool* unevokable) mpr("Magical energy flows into your mind!"); - inc_mp(3 + random2(5) + you.skill_rdiv(SK_EVOCATIONS, 1, 3)); + const int mp_inc_base = 3 + random2(5); + inc_mp(mp_inc_base + you.skill_rdiv(SK_EVOCATIONS, 1, 3)); make_hungry(50, false, true); *did_work = true; @@ -851,8 +854,9 @@ static void _PLUTONIUM_SWORD_melee_effects(item_def* weapon, actor* attacker, || !mons_immune_magic(*defender->as_monster()))) { mpr("Mutagenic energy flows through the plutonium sword!"); + const int pow = random2(9); MiscastEffect(defender, attacker, {miscast_source::melee}, - spschool::transmutation, random2(9), random2(70), + spschool::transmutation, pow, random2(70), "the plutonium sword", nothing_happens::NEVER); if (attacker->is_player()) @@ -1040,8 +1044,9 @@ static void _SPELLBINDER_melee_effects(item_def* weapon, actor* attacker, if (defender->antimagic_susceptible() && !mondied) { + const int pow = random2(9); MiscastEffect(defender, attacker, {miscast_source::melee}, - spschool::random, random2(9), random2(70), + spschool::random, pow, random2(70), "the demon whip \"Spellbinder\"", nothing_happens::NEVER); } } diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc index 721b270a120a..0c131a5ca815 100644 --- a/crawl-ref/source/beam.cc +++ b/crawl-ref/source/beam.cc @@ -708,8 +708,11 @@ void bolt::apply_beam_conducts() switch (flavour) { case BEAM_DAMNATION: - did_god_conduct(DID_EVIL, 2 + random2(3), god_cares()); + { + const int level = 2 + random2(3); + did_god_conduct(DID_EVIL, level, god_cares()); break; + } default: break; } @@ -2833,7 +2836,9 @@ bool bolt::fuzz_invis_tracer() return false; // Apply fuzz now. - coord_def fuzz(random_range(-2, 2), random_range(-2, 2)); + coord_def fuzz; + fuzz.x = random_range(-2, 2); + fuzz.y = random_range(-2, 2); coord_def newtarget = target + fuzz; if (in_bounds(newtarget)) @@ -5319,8 +5324,8 @@ mon_resist_type bolt::apply_enchantment_to_monster(monster* mon) obvious_effect = true; if (YOU_KILL(thrower)) { - did_god_conduct(DID_DELIBERATE_MUTATING, 2 + random2(3), - god_cares()); + const int level = 2 + random2(3); + did_god_conduct(DID_DELIBERATE_MUTATING, level, god_cares()); } return MON_AFFECTED; @@ -5330,8 +5335,8 @@ mon_resist_type bolt::apply_enchantment_to_monster(monster* mon) obvious_effect = true; if (YOU_KILL(thrower)) { - did_god_conduct(DID_DELIBERATE_MUTATING, 2 + random2(3), - god_cares()); + const int level = 2 + random2(3); + did_god_conduct(DID_DELIBERATE_MUTATING, level, god_cares()); } return MON_AFFECTED; diff --git a/crawl-ref/source/coord.cc b/crawl-ref/source/coord.cc index 85539797952a..6746f47bd470 100644 --- a/crawl-ref/source/coord.cc +++ b/crawl-ref/source/coord.cc @@ -51,13 +51,18 @@ coord_def random_in_bounds() { const coord_def &ul = crawl_view.glos1; // Upper left const coord_def &lr = crawl_view.glos2; // Lower right - - return coord_def(random_range(ul.x, lr.x - 1), - random_range(ul.y, lr.y - 1)); + coord_def res; + res.x = random_range(ul.x, lr.x - 1); + res.y = random_range(ul.y, lr.y - 1); + return res; } else - return coord_def(random_range(MAPGEN_BORDER, GXM - MAPGEN_BORDER - 1), - random_range(MAPGEN_BORDER, GYM - MAPGEN_BORDER - 1)); + { + coord_def res; + res.x = random_range(MAPGEN_BORDER, GXM - MAPGEN_BORDER - 1); + res.y = random_range(MAPGEN_BORDER, GYM - MAPGEN_BORDER - 1); + return res; + } } // Coordinate system conversions. diff --git a/crawl-ref/source/dgn-irregular-box.cc b/crawl-ref/source/dgn-irregular-box.cc index 8c54aa2f45ad..f73269a2e153 100644 --- a/crawl-ref/source/dgn-irregular-box.cc +++ b/crawl-ref/source/dgn-irregular-box.cc @@ -492,10 +492,18 @@ void make_irregular_box(map_lines& map, int x1, int y1, int x2, int y2, // -> the box may stick out past these // - coord_def in_tl(random2(in_x), random2(in_y)); - coord_def in_tr(random2(in_x), random2(in_y)); - coord_def in_bl(random2(in_x), random2(in_y)); - coord_def in_br(random2(in_x), random2(in_y)); + coord_def in_tl; + in_tl.x = random2(in_x); + in_tl.y = random2(in_y); + coord_def in_tr; + in_tr.x = random2(in_x); + in_tr.y = random2(in_y); + coord_def in_bl; + in_bl.x = random2(in_x); + in_bl.y = random2(in_y); + coord_def in_br; + in_br.x = random2(in_x); + in_br.y = random2(in_y); _randomly_force_sum_below(in_tl.x, in_tr.x, size_x - MIN_IRREGULAR_SIZE); _randomly_force_sum_below(in_bl.x, in_br.x, size_x - MIN_IRREGULAR_SIZE); _randomly_force_sum_below(in_tl.y, in_bl.y, size_y - MIN_IRREGULAR_SIZE); diff --git a/crawl-ref/source/dgn-layouts.cc b/crawl-ref/source/dgn-layouts.cc index 24cbf611c0d7..1ef303256a60 100644 --- a/crawl-ref/source/dgn-layouts.cc +++ b/crawl-ref/source/dgn-layouts.cc @@ -110,7 +110,8 @@ void dgn_build_basic_level() // Make some rooms: int doorlevel = random2(11); - int roomsize = 4 + random2(5) + random2(6); + int roomsize = 4 + random2(5); + roomsize += random2(6); // force a sequence point between random calls int no_rooms = random_choose_weighted(636, (5 + random2avg(29, 2)), 49, 100, @@ -182,8 +183,10 @@ void dgn_build_chaotic_city_level(dungeon_feature_type force_wall) uint8_t b1x, b1y, b2x, b2y; for (int i = 0; i < number_boxes; i++) { - int room_width = 3 + random2(7) + random2(5); - int room_height = 3 + random2(7) + random2(5); + int room_width = 3 + random2(7); + room_width += random2(5); // force a sequence point between random2s + int room_height = 3 + random2(7); + room_height += random2(5); // ditto b1x = 11 + random2(GXM - 21 - room_width); b1y = 11 + random2(GYM - 21 - room_height); @@ -685,8 +688,11 @@ static void _big_room(int level_number) do { - region = dgn_region(8 + random2(30), 8 + random2(22), - 21 + random2(10), 21 + random2(8)); + const int left = 8 + random2(30); + const int top = 8 + random2(22); + const int width = 21 + random2(10); + const int height = 21 + random2(8); + region = dgn_region(left, top, width, height); } while (_find_forbidden_in_area(region, MMT_VAULT) && overlap_tries-- > 0); @@ -718,8 +724,13 @@ static void _big_room(int level_number) // What now? do { - region = dgn_region(8 + random2(30), 8 + random2(22), - 21 + random2(10), 21 + random2(8)); + // TODO: code duplication with above + const int left = 8 + random2(30); + const int top = 8 + random2(22); + const int width = 21 + random2(10); + const int height = 21 + random2(8); + + region = dgn_region(left, top, width, height); } while (_find_forbidden_in_area(region, MMT_VAULT) && overlap_tries-- > 0); @@ -817,8 +828,11 @@ static void _diamond_rooms(int level_number) dgn_region room; do { - room = dgn_region(8 + random2(43), 8 + random2(35), - 6 + random2(15), 6 + random2(10)); + const int left = 8 + random2(43); + const int top = 8 + random2(35); + const int width = 6 + random2(15); + const int height = 6 + random2(10); + room = dgn_region(left, top, width, height); } while (_find_forbidden_in_area(room, MMT_VAULT) && overlap_tries-- > 0); diff --git a/crawl-ref/source/dgn-shoals.cc b/crawl-ref/source/dgn-shoals.cc index 7c8d6498e4a4..15b496e0304e 100644 --- a/crawl-ref/source/dgn-shoals.cc +++ b/crawl-ref/source/dgn-shoals.cc @@ -176,8 +176,10 @@ static void _shoals_build_cliff() coord_def place = cliffc + coord_def(static_cast(distance * cos(angle)), static_cast(distance * sin(angle))); - const coord_def fuzz = coord_def(random_range(-2, 2), - random_range(-2, 2)); + coord_def fuzz; + fuzz.x = random_range(-2, 2); + fuzz.y = random_range(-2, 2); + place += fuzz; dgn_island_centred_at(place, resolve_range(n_cliff_points), cliff_point_radius, cliff_height_increment, @@ -495,9 +497,9 @@ static void _shoals_plant_supercluster(coord_def c, dungeon_feature_type favoured_feat, grid_bool *verboten = nullptr) { - _shoals_plant_cluster(c, random_range(10, 17, 2), - random_range(3, 9), favoured_feat, - verboten); + int nplants = random_range(10, 17, 2); + int radius = random_range(3, 9); + _shoals_plant_cluster(c, nplants, radius, favoured_feat, verboten); const int nadditional_clusters(max(0, random_range(-1, 4, 2))); for (int i = 0; i < nadditional_clusters; ++i) @@ -506,9 +508,9 @@ static void _shoals_plant_supercluster(coord_def c, dgn_random_point_from(c, random_range(2, 12), _shoals_margin)); if (!satellite.origin()) { - _shoals_plant_cluster(satellite, random_range(5, 12, 2), - random_range(2, 7), - favoured_feat, + nplants = random_range(5, 12, 2); + radius = random_range(2, 7); + _shoals_plant_cluster(satellite, nplants, radius, favoured_feat, verboten); } } diff --git a/crawl-ref/source/dgn-swamp.cc b/crawl-ref/source/dgn-swamp.cc index 2069cf3afe71..3dfc3fec790d 100644 --- a/crawl-ref/source/dgn-swamp.cc +++ b/crawl-ref/source/dgn-swamp.cc @@ -22,11 +22,12 @@ static void _swamp_slushy_patches(int depth_multiplier) const coord_def center_delta(grdc - c); const int depth = 1600 - center_delta.abs(); const int depth_offset = depth * 10 / 1600; - dgn_island_centred_at(c, random_range(5, 25 - depth_multiplier / 2), - random_range(2, 6), + const int n_points = random_range(5, 25 - depth_multiplier / 2); + const int radius = random_range(2, 6); + dgn_island_centred_at(c, n_points, radius, int_range(8 + depth_offset, 17 + depth_offset), - margin); + margin); } } } diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc index 7ddc46342ce4..454a374c05d6 100644 --- a/crawl-ref/source/directn.cc +++ b/crawl-ref/source/directn.cc @@ -181,8 +181,10 @@ bool dist::isMe() const void dist::confusion_fuzz(int range) { - target = you.pos() + coord_def(random_range(-range, range), - random_range(-range, range)); + target = you.pos(); + target.x += random_range(-range, range); + target.y += random_range(-range, range); + choseRay = false; } diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 565aa9d8f9b4..284bec4364cd 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -1855,7 +1855,9 @@ static bool _add_feat_if_missing(bool (*iswanted)(const coord_def &), int i = 0; while (i++ < 2000) { - coord_def rnd(random2(GXM), random2(GYM)); + coord_def rnd; + rnd.x = random2(GXM); + rnd.y = random2(GYM); if (grd(rnd) != DNGN_FLOOR) continue; @@ -3314,8 +3316,10 @@ bool dgn_has_adjacent_feat(coord_def c, dungeon_feature_type feat) coord_def dgn_random_point_in_margin(int margin) { - return coord_def(random_range(margin, GXM - margin - 1), - random_range(margin, GYM - margin - 1)); + coord_def res; + res.x = random_range(margin, GXM - margin - 1); + res.y = random_range(margin, GYM - margin - 1); + return res; } static inline bool _point_matches_feat(coord_def c, @@ -4239,10 +4243,9 @@ static void _build_postvault_level(vault_placement &place) ngb_min = 1, ngb_max = random_range(5, 7); if (one_chance_in(20)) ngb_min = 3, ngb_max = 4; - delve(0, ngb_min, ngb_max, - random_choose(0, 5, 20, 50, 100), - -1, - random_choose(1, 20, 125, 500, 999999)); + const int connchance = random_choose(0, 5, 20, 50, 100); + const int top = random_choose(1, 20, 125, 500, 999999); + delve(0, ngb_min, ngb_max, connchance, -1, top); } else { @@ -5417,8 +5420,12 @@ int greed_for_shop_type(shop_type shop, int level_number) if (shop == SHOP_FOOD) return 10 + random2(5); if (_shop_sells_antiques(shop)) - return 15 + random2avg(19, 2) + random2(level_number); - return 10 + random2(5) + random2(level_number / 2); + { + const int rand = random2avg(19, 2); + return 15 + rand + random2(level_number); + } + const int rand = random2(5); + return 10 + rand + random2(level_number / 2); } /** @@ -6293,16 +6300,26 @@ bool dgn_region::overlaps(const map_mask &mask) const coord_def dgn_region::random_edge_point() const { - return x_chance_in_y(size.x, size.x + size.y) ? - coord_def(pos.x + random2(size.x), - random_choose(pos.y, pos.y + size.y - 1)) - : coord_def(random_choose(pos.x, pos.x + size.x - 1), - pos.y + random2(size.y)); + coord_def res; + if (x_chance_in_y(size.x, size.x + size.y)) + { + res.x = pos.x + random2(size.x); + res.y = random_choose(pos.y, pos.y + size.y - 1); + } + else + { + res.x = random_choose(pos.x, pos.x + size.x - 1); + res.y = pos.y + random2(size.y); + } + return res; } coord_def dgn_region::random_point() const { - return coord_def(pos.x + random2(size.x), pos.y + random2(size.y)); + coord_def res; + res.x = pos.x + random2(size.x); + res.y = pos.y + random2(size.y); + return res; } struct StairConnectivity diff --git a/crawl-ref/source/evoke.cc b/crawl-ref/source/evoke.cc index 46e38aeef1ab..8fd56f67e143 100644 --- a/crawl-ref/source/evoke.cc +++ b/crawl-ref/source/evoke.cc @@ -325,7 +325,9 @@ static void _spray_lightning(int range, int power) // range has no tracer, so randomness is ok beam.range = range; beam.source = you.pos(); - beam.target = you.pos() + coord_def(random2(13)-6, random2(13)-6); + beam.target = you.pos(); + beam.target.x += random2(13) - 6; + beam.target.y += random2(13) - 6; // Non-controlleable, so no player tracer. zapping(which_zap, power, beam); } @@ -609,10 +611,12 @@ static bool _box_of_beasts(item_def &box) mpr("You open the lid..."); // two rolls to reduce std deviation - +-6 so can get < max even at 27 sk + int rnd_factor = random2(7); + rnd_factor -= random2(7); const int hd_min = min(27, player_adjust_evoc_power( you.skill(SK_EVOCATIONS) - + random2(7) - random2(7), surge)); + + rnd_factor, surge)); const int tier = mutant_beast_tier(hd_min); ASSERT(tier < NUM_BEAST_TIERS); @@ -660,8 +664,9 @@ static bool _sack_of_spiders(item_def &sack) mpr("You reach into the bag..."); const int evo_skill = you.skill(SK_EVOCATIONS); + int rnd_factor = 1 + random2(2); int count = player_adjust_evoc_power( - 1 + random2(2) + random2(div_rand_round(evo_skill * 10, 30)), surge); + rnd_factor + random2(div_rand_round(evo_skill * 10, 30)), surge); const int power = player_adjust_evoc_power(evo_skill, surge); if (x_chance_in_y(5, 10 + power)) @@ -850,8 +855,10 @@ static vector _get_jitter_path(coord_def source, coord_def target, { for (int n = 0; n < NUM_TRIES; ++n) { - coord_def jitter = clamp_in_bounds(target + coord_def(random_range(-2, 2), - random_range(-2, 2))); + coord_def jitter_rnd; + jitter_rnd.x = random_range(-2, 2); + jitter_rnd.y = random_range(-2, 2); + coord_def jitter = clamp_in_bounds(target + jitter_rnd); if (jitter == target || jitter == source || cell_is_solid(jitter)) continue; @@ -877,8 +884,10 @@ static vector _get_jitter_path(coord_def source, coord_def target, for (int n = 0; n < NUM_TRIES; ++n) { - coord_def jitter = clamp_in_bounds(mid + coord_def(random_range(-3, 3), - random_range(-3, 3))); + coord_def jitter_rnd; + jitter_rnd.x = random_range(-3, 3); + jitter_rnd.y = random_range(-3, 3); + coord_def jitter = clamp_in_bounds(mid + jitter_rnd); if (jitter == mid || jitter.distance_from(mid) < 2 || jitter == source || cell_is_solid(jitter) || !cell_see_cell(source, jitter, LOS_NO_TRANS) @@ -1322,8 +1331,9 @@ static bool _phial_of_floods() vector elementals; // Flood the endpoint coord_def center = beam.path_taken.back(); + const int rnd_factor = random2(7); int num = player_adjust_evoc_power( - 5 + you.skill_rdiv(SK_EVOCATIONS, 3, 5) + random2(7), + 5 + you.skill_rdiv(SK_EVOCATIONS, 3, 5) + rnd_factor, surge); int dur = player_adjust_evoc_power( 40 + you.skill_rdiv(SK_EVOCATIONS, 8, 3), diff --git a/crawl-ref/source/god-abil.cc b/crawl-ref/source/god-abil.cc index bbc1bce9dc9e..f46e1c75cc36 100644 --- a/crawl-ref/source/god-abil.cc +++ b/crawl-ref/source/god-abil.cc @@ -3489,8 +3489,8 @@ void cheibriados_time_bend(int pow) monster* mon = monster_at(*ai); if (mon && !mon->is_stationary()) { - int res_margin = roll_dice(mon->get_hit_dice(), 3) - - random2avg(pow, 2); + int res_margin = roll_dice(mon->get_hit_dice(), 3); + res_margin -= random2avg(pow, 2); if (res_margin > 0) { mprf("%s%s", @@ -6130,10 +6130,12 @@ void ru_draw_out_power() you.duration[DUR_SLOW] = 0; you.duration[DUR_PETRIFYING] = 0; - inc_hp(div_rand_round(you.piety, 16) - + roll_dice(div_rand_round(you.piety, 20), 6)); - inc_mp(div_rand_round(you.piety, 48) - + roll_dice(div_rand_round(you.piety, 40), 4)); + int hp_inc = div_rand_round(you.piety, 16); + hp_inc += roll_dice(div_rand_round(you.piety, 20), 6); + inc_hp(hp_inc); + int mp_inc = div_rand_round(you.piety, 48); + mp_inc += roll_dice(div_rand_round(you.piety, 40), 4); + inc_mp(mp_inc); drain_player(30, false, true); } diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc index 40e91d5b29f1..ad7db4c0bda6 100644 --- a/crawl-ref/source/mapdef.cc +++ b/crawl-ref/source/mapdef.cc @@ -3039,9 +3039,10 @@ coord_def map_def::float_random_place() const if (GYM - 2 * minvborder < map.height()) minvborder = (GYM - map.height()) / 2 - 1; - return coord_def( - random_range(minhborder, GXM - minhborder - map.width()), - random_range(minvborder, GYM - minvborder - map.height())); + coord_def result; + result.x = random_range(minhborder, GXM - minhborder - map.width()); + result.y = random_range(minvborder, GYM - minvborder - map.height()); + return result; } point_vector map_def::anchor_points() const diff --git a/crawl-ref/source/maps.cc b/crawl-ref/source/maps.cc index e7a6b98ce5fa..9f9fdd33038f 100644 --- a/crawl-ref/source/maps.cc +++ b/crawl-ref/source/maps.cc @@ -544,8 +544,9 @@ static coord_def _find_minivault_place( // Find a target area which can be safely overwritten. for (int tries = 0; tries < 600; ++tries) { - coord_def v1(random_range(margin, GXM - margin - place.size.x), - random_range(margin, GYM - margin - place.size.y)); + coord_def v1; + v1.x = random_range(margin, GXM - margin - place.size.x); + v1.y = random_range(margin, GYM - margin - place.size.y); if (check_place && !map_place_valid(place.map, v1, place.size)) { diff --git a/crawl-ref/source/melee-attack.cc b/crawl-ref/source/melee-attack.cc index 54b716906d10..90a6f7d6b406 100644 --- a/crawl-ref/source/melee-attack.cc +++ b/crawl-ref/source/melee-attack.cc @@ -3632,7 +3632,8 @@ bool melee_attack::_player_vampire_draws_blood(const monster* mon, const int dam // Regain hp. if (you.hp < you.hp_max) { - int heal = 2 + random2(damage) + random2(damage); + int heal = 2 + random2(damage); + heal += random2(damage); if (heal > you.experience_level) heal = you.experience_level; diff --git a/crawl-ref/source/mon-behv.cc b/crawl-ref/source/mon-behv.cc index ce7b9dfbd38f..8c92ad07b6e2 100644 --- a/crawl-ref/source/mon-behv.cc +++ b/crawl-ref/source/mon-behv.cc @@ -853,10 +853,12 @@ void handle_behaviour(monster* mon) mon->props["idle_deadline"] = you.elapsed_time + 200; } + coord_def target_rnd; + target_rnd.x = random_range(-2, 2); + target_rnd.y = random_range(-2, 2); mon->target = clamp_in_bounds( mon->props["idle_point"].get_coord() - + coord_def(random_range(-2, 2), - random_range(-2, 2))); + + target_rnd); if (you.elapsed_time >= mon->props["idle_deadline"].get_int()) stop_retreat = true; diff --git a/crawl-ref/source/mon-cast.cc b/crawl-ref/source/mon-cast.cc index b8f93b43efe7..272021eafec4 100644 --- a/crawl-ref/source/mon-cast.cc +++ b/crawl-ref/source/mon-cast.cc @@ -2939,8 +2939,10 @@ static bool _place_druids_call_beast(const monster* druid, monster* beast, { // Attempt to find some random spot out of the target's los to place // the beast (but not too far away). - coord_def area = clamp_in_bounds(target->pos() + coord_def(random_range(-11, 11), - random_range(-11, 11))); + coord_def area_rnd; + area_rnd.x = random_range(-11, 11); + area_rnd.y = random_range(-11, 11); + coord_def area = clamp_in_bounds(target->pos() + area_rnd); if (cell_see_cell(target->pos(), area, LOS_DEFAULT)) continue; @@ -4480,7 +4482,8 @@ static void _mons_vampiric_drain(monster &mons, mon_spell_slot slot, bolt&) return; const int pow = mons_spellpower(mons, slot.spell); - int hp_cost = 3 + random2avg(9, 2) + 1 + random2(pow) / 7; + int hp_cost = 3 + random2avg(9, 2) + 1; + hp_cost += random2(pow) / 7; // force a sequence point between random calls hp_cost = min(hp_cost, target->stat_hp()); hp_cost = min(hp_cost, mons.max_hit_points - mons.hit_points); @@ -6164,9 +6167,9 @@ void mons_cast(monster* mons, bolt pbolt, spell_type spell_cast, case SPELL_BROTHERS_IN_ARMS: { // Invocation; don't use spell_hd - const int power = (mons->get_hit_dice() * 20) - + random2(mons->get_hit_dice() * 5) - - random2(mons->get_hit_dice() * 5); + int power = (mons->get_hit_dice() * 20) + + random2(mons->get_hit_dice() * 5); + power -= random2(mons->get_hit_dice() * 5); // force a sequence point monster_type to_summon; if (mons->type == MONS_SPRIGGAN_BERSERKER) @@ -6270,8 +6273,8 @@ void mons_cast(monster* mons, bolt pbolt, spell_type spell_cast, } case SPELL_SUMMON_HOLIES: // Holy monsters. - sumcount2 = 1 + random2(2) - + random2(mons->spell_hd(spell_cast) / 4 + 1); + sumcount2 = 1 + random2(2); // sequence point + sumcount2 += random2(mons->spell_hd(spell_cast) / 4 + 1); duration = min(2 + mons->spell_hd(spell_cast) / 5, 6); for (int i = 0; i < sumcount2; ++i) @@ -6513,8 +6516,10 @@ void mons_cast(monster* mons, bolt pbolt, spell_type spell_cast, apostrophise(mons->name(DESC_THE)).c_str()); } const int power = (mons->spell_hd(spell_cast) * 15) / 10; + const int rnd_power = random2(power); // sequence point + const int two_rnd_powers = rnd_power + random2(power); mons->add_ench(mon_enchant(ENCH_OZOCUBUS_ARMOUR, - 20 + random2(power) + random2(power), + 20 + two_rnd_powers, mons)); return; diff --git a/crawl-ref/source/mon-movetarget.cc b/crawl-ref/source/mon-movetarget.cc index 7df3393e727b..65bdb6262d04 100644 --- a/crawl-ref/source/mon-movetarget.cc +++ b/crawl-ref/source/mon-movetarget.cc @@ -726,7 +726,9 @@ void set_random_target(monster* mon) mon->target = random_in_bounds(); // If we don't find anything better. for (int tries = 0; tries < 150; ++tries) { - coord_def delta = coord_def(random2(13), random2(13)) - coord_def(6, 6); + coord_def delta; + delta.x = random2(13) - 6; + delta.y = random2(13) - 6; if (delta.origin()) continue; diff --git a/crawl-ref/source/mon-place.cc b/crawl-ref/source/mon-place.cc index 701b0e4d5f98..364df3ef4580 100644 --- a/crawl-ref/source/mon-place.cc +++ b/crawl-ref/source/mon-place.cc @@ -896,8 +896,9 @@ static monster* _place_monster_aux(const mgen_data &mg, const monster *leader, // We'll try 1000 times for a good spot. for (i = 0; i < 1000; ++i) { - fpos = mg.pos + coord_def(random_range(-3, 3), - random_range(-3, 3)); + fpos = mg.pos; + fpos.x += random_range(-3, 3); + fpos.y += random_range(-3, 3); // Place members within LOS_SOLID of their leader. // TODO nfm - allow placing around corners but not across walls. @@ -1211,9 +1212,9 @@ static monster* _place_monster_aux(const mgen_data &mg, const monster *leader, if (mon->has_spell(SPELL_OZOCUBUS_ARMOUR)) { const int power = (mon->spell_hd(SPELL_OZOCUBUS_ARMOUR) * 15) / 10; - mon->add_ench(mon_enchant(ENCH_OZOCUBUS_ARMOUR, - 20 + random2(power) + random2(power), - mon)); + int rnd_power = random2(power); + rnd_power += random2(power); + mon->add_ench(mon_enchant(ENCH_OZOCUBUS_ARMOUR, 20 + rnd_power, mon)); } if (mon->has_spell(SPELL_SHROUD_OF_GOLUBRIA)) diff --git a/crawl-ref/source/ng-init.cc b/crawl-ref/source/ng-init.cc index 35f602f4cb7e..81d7add81090 100644 --- a/crawl-ref/source/ng-init.cc +++ b/crawl-ref/source/ng-init.cc @@ -84,11 +84,9 @@ void initialise_branch_depths() // You will get one of Shoals/Swamp and one of Spider/Snake. // This way you get one "water" branch and one "poison" branch. - branch_type disabled_branch[] = - { - random_choose(BRANCH_SWAMP, BRANCH_SHOALS), - random_choose(BRANCH_SNAKE, BRANCH_SPIDER), - }; + vector disabled_branch; + disabled_branch.push_back(random_choose(BRANCH_SWAMP, BRANCH_SHOALS)); + disabled_branch.push_back(random_choose(BRANCH_SNAKE, BRANCH_SPIDER)); for (branch_type disabled : disabled_branch) { diff --git a/crawl-ref/source/ng-setup.cc b/crawl-ref/source/ng-setup.cc index cbd74d59ccc0..de46a3de8223 100644 --- a/crawl-ref/source/ng-setup.cc +++ b/crawl-ref/source/ng-setup.cc @@ -253,16 +253,19 @@ static void _give_items_skills(const newgame_def& ng) break; case JOB_CHAOS_KNIGHT: + { you.religion = GOD_XOM; you.piety = 100; - you.gift_timeout = max(5, random2(40) + random2(40)); + int timeout_rnd = random2(40); + timeout_rnd += random2(40); // force a sequence point between random2s + you.gift_timeout = max(5, timeout_rnd); if (species_apt(SK_ARMOUR) < species_apt(SK_DODGING)) you.skills[SK_DODGING]++; else you.skills[SK_ARMOUR]++; break; - + } case JOB_ABYSSAL_KNIGHT: you.religion = GOD_LUGONU; if (!crawl_state.game_is_sprint()) diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 91d72c937c4f..d234ca3f409c 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -7446,7 +7446,8 @@ bool player::attempt_escape(int attempts) const string object = direct ? themonst->name(DESC_ITS, true) : "the roots'"; // player breaks free if (4+n)d13 >= 5d(8+HD/4) - if (roll_dice(4 + escape_attempts, 13) + const int escape_score = roll_dice(4 + escape_attempts, 13); + if (escape_score >= roll_dice(5, 8 + div_rand_round(themonst->get_hit_dice(), 4))) { mprf("You escape %s grasp.", object.c_str()); diff --git a/crawl-ref/source/random-var.cc b/crawl-ref/source/random-var.cc index 425bb70589a2..9f4478b39870 100644 --- a/crawl-ref/source/random-var.cc +++ b/crawl-ref/source/random-var.cc @@ -4,6 +4,10 @@ #include "random.h" +// TODO: the design of this class, together with c++ operator eval order +// indeterminacy, is more or less a bad idea with the goal of deterministic +// seeding. It possibly should be removed. + random_var::random_var(int c) : start(c), end(c+1) { @@ -131,8 +135,10 @@ double random_var::expected() const random_var operator+(const random_var& x, const random_var& y) { - const int start = x.min() + y.min(); - const int end = x.max() + y.max() + 1; + int start = x.min(); + start += y.min(); // force a sequence point + int end = x.max(); + end += y.max() + 1; // force a sequence point vector weights(end - start, 0); for (int vx = x.min(); vx <= x.max(); ++vx) @@ -203,8 +209,12 @@ random_var div_rand_round(const random_var& x, int d) ASSERT(d != 0); // Round start down and end up, not both towards zero. - const int start = (x.min() - (x.min() < 0 ? d - 1 : 0)) / d; - const int end = (x.max() + (x.max() > 0 ? d - 1 : 0)) / d + 1; + const int x_min1 = x.min(); // force sequence points... + const int x_min2 = x.min(); + const int x_max1 = x.max(); + const int x_max2 = x.max(); + const int start = (x_min1 - (x_min2 < 0 ? d - 1 : 0)) / d; + const int end = (x_max1 + (x_max2 > 0 ? d - 1 : 0)) / d + 1; vector weights(end - start, 0); for (int v = x.min(); v <= x.max(); ++v) @@ -220,8 +230,12 @@ random_var div_rand_round(const random_var& x, int d) random_var rv::max(const random_var& x, const random_var& y) { - const int start = ::max(x.min(), y.min()); - const int end = ::max(x.max(), y.max()) + 1; + const int x_min = x.min(); // force sequence points... + const int y_min = y.min(); + const int x_max = x.max(); + const int y_max = y.max(); + const int start = ::max(x_min, y_min); + const int end = ::max(x_max, y_max) + 1; vector weights(end - start, 0); for (int vx = x.min(); vx <= x.max(); ++vx) @@ -233,8 +247,12 @@ random_var rv::max(const random_var& x, const random_var& y) random_var rv::min(const random_var& x, const random_var& y) { - const int start = ::min(x.min(), y.min()); - const int end = ::min(x.max(), y.max()) + 1; + const int x_min = x.min(); // force sequence points... + const int y_min = y.min(); + const int x_max = x.max(); + const int y_max = y.max(); + const int start = ::min(x_min, y_min); + const int end = ::min(x_max, y_max) + 1; vector weights(end - start, 0); for (int vx = x.min(); vx <= x.max(); ++vx) diff --git a/crawl-ref/source/shout.cc b/crawl-ref/source/shout.cc index d1fc628c5140..b1aa8735c772 100644 --- a/crawl-ref/source/shout.cc +++ b/crawl-ref/source/shout.cc @@ -1227,10 +1227,12 @@ coord_def noise_grid::noise_perceived_position(actor *act, : noise.noise_source; const int fuzz = extra_distance_covered; + coord_def fuzz_rnd; + fuzz_rnd.x = random_range(-fuzz, fuzz, 2); + fuzz_rnd.y = random_range(-fuzz, fuzz, 2); const coord_def perceived_point = fuzz? - noise_centroid + coord_def(random_range(-fuzz, fuzz, 2), - random_range(-fuzz, fuzz, 2)) + noise_centroid + fuzz_rnd : noise_centroid; const coord_def final_perceived_point = diff --git a/crawl-ref/source/teleport.cc b/crawl-ref/source/teleport.cc index eaae1e7f0568..00c5390448a6 100644 --- a/crawl-ref/source/teleport.cc +++ b/crawl-ref/source/teleport.cc @@ -125,7 +125,9 @@ static coord_def _random_monster_nearby_habitable_space(const monster& mon) for (tries = 0; tries < 150; ++tries) { - const coord_def delta(random2(13) - 6, random2(13) - 6); + coord_def delta; + delta.x = random2(13) - 6; + delta.y = random2(13) - 6; // Check that we don't get something too close to the // starting point. @@ -455,7 +457,9 @@ bool random_near_space(const actor* victim, for (int tries = 0; tries < 150; tries++) { - coord_def p = coord_def(random2(RNS_WIDTH), random2(RNS_WIDTH)); + coord_def p; + p.x = random2(RNS_WIDTH); + p.y = random2(RNS_WIDTH); if (tried(p)) continue; else diff --git a/crawl-ref/source/throw.cc b/crawl-ref/source/throw.cc index ff1543bb1314..01344be6b97f 100644 --- a/crawl-ref/source/throw.cc +++ b/crawl-ref/source/throw.cc @@ -785,7 +785,9 @@ bool throw_it(bolt &pbolt, int throw_2, dist *target) if (you.confused()) { - thr.target = you.pos() + coord_def(random2(13)-6, random2(13)-6); + thr.target = you.pos(); + thr.target.x += random2(13) - 6; + thr.target.y += random2(13) - 6; thr.isValid = true; } else if (target) diff --git a/crawl-ref/source/timed-effects.cc b/crawl-ref/source/timed-effects.cc index c682052f2a50..4726532aa4d6 100644 --- a/crawl-ref/source/timed-effects.cc +++ b/crawl-ref/source/timed-effects.cc @@ -84,8 +84,10 @@ static void _random_hell_miscast() 1, spschool::charms, 1, spschool::hexes); + const int pow = 4 + random2(6); + const int fail = random2avg(97, 3); MiscastEffect(&you, nullptr, {miscast_source::hell_effect}, which_miscast, - 4 + random2(6), random2avg(97, 3), + pow, fail, "the effects of Hell"); } @@ -150,8 +152,10 @@ static void _themed_hell_summon_or_miscast() } else { + const int pow = 4 + random2(6); + const int fail = random2avg(97, 3); MiscastEffect(&you, nullptr, {miscast_source::hell_effect}, - spec->miscast_type, 4 + random2(6), random2avg(97, 3), + spec->miscast_type, pow, fail, "the effects of Hell"); } } @@ -581,7 +585,9 @@ static void _monster_flee(monster *mon) } // Randomise the target so we have a direction to flee. - coord_def mshift(random2(3) - 1, random2(3) - 1); + coord_def mshift; + mshift.x = random2(3) - 1; + mshift.y = random2(3) - 1; // Bounds check: don't let fleeing monsters try to run off the grid. const coord_def s = mon->target + mshift; @@ -1066,7 +1072,11 @@ void timeout_malign_gateways(int duration) mmark->duration -= duration; if (mmark->duration > 0) - big_cloud(CLOUD_TLOC_ENERGY, 0, mmark->pos, 3+random2(10), 2+random2(5)); + { + const int pow = 3 + random2(10); + const int size = 2 + random2(5); + big_cloud(CLOUD_TLOC_ENERGY, 0, mmark->pos, pow, size); + } else { monster* mons = monster_at(mmark->pos); @@ -1098,8 +1108,11 @@ void timeout_malign_gateways(int duration) { tentacle->flags |= MF_NO_REWARD; tentacle->add_ench(ENCH_PORTAL_TIMER); + int dur = random2avg(mmark->power, 6); + dur -= random2(4); // sequence point between random calls + dur *= 10; mon_enchant kduration = mon_enchant(ENCH_PORTAL_PACIFIED, 4, - caster, (random2avg(mmark->power, 6)-random2(4))*10); + caster, dur); tentacle->props["base_position"].get_coord() = tentacle->pos(); tentacle->add_ench(kduration); diff --git a/crawl-ref/source/traps.cc b/crawl-ref/source/traps.cc index 52b925e89388..cfd2c3c4f889 100644 --- a/crawl-ref/source/traps.cc +++ b/crawl-ref/source/traps.cc @@ -578,13 +578,11 @@ void trap_def::trigger(actor& triggerer) case TRAP_BLADE: if (you_trigger) { + const int narrow_miss_rnd = random2(6) + 3; if (one_chance_in(3)) mpr("You avoid triggering a blade trap."); - else if (random2limit(you.evasion(), 40) - + random2(6) + 3 > 8) - { + else if (random2limit(you.evasion(), 40) + narrow_miss_rnd > 8) mpr("A huge blade swings just past you!"); - } else { mpr("A huge blade swings out and slices into you!"); @@ -668,11 +666,8 @@ void trap_def::trigger(actor& triggerer) item_def item = generate_trap_item(); copy_item_to_grid(item, you.pos()); - if (random2avg(2 * you.evasion(), 2) - > 18 + env.absdepth0 / 2) - { + if (random2avg(2 * you.evasion(), 2) > 18 + env.absdepth0 / 2) mpr("A net drops to the ground!"); - } else { mpr("A large net falls onto you!"); @@ -1156,7 +1151,9 @@ void trap_def::shoot_ammo(actor& act, bool was_known) item_def shot = generate_trap_item(); - int trap_hit = (20 + (to_hit_bonus()*2)) * random2(200) / 100; + int trap_hit = 20 + (to_hit_bonus()*2); + trap_hit *= random2(200); + trap_hit /= 100; if (int defl = act.missile_deflection()) trap_hit = random2(trap_hit / defl); diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index 9ef218d45d78..d052c5b812b9 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -1153,7 +1153,9 @@ class shake_viewport_animation: public animation void init_frame(int frame) override { - offset = coord_def(random2(3) - 1, random2(3) - 1); + offset = coord_def(); + offset.x = random2(3) - 1; + offset.y = random2(3) - 1; } coord_def cell_cb(const coord_def &pos, int &colour) override diff --git a/crawl-ref/source/xom.cc b/crawl-ref/source/xom.cc index f2a36bf33f32..e966d40f6851 100644 --- a/crawl-ref/source/xom.cc +++ b/crawl-ref/source/xom.cc @@ -3599,8 +3599,10 @@ static void _xom_bad_teleport(int sever) /// Place a one-tile chaos cloud on the player, with minor spreading. static void _xom_chaos_cloud(int /*sever*/) { - check_place_cloud(CLOUD_CHAOS, you.pos(), 3 + random2(12)*3, - nullptr, random_range(5,15)); + const int lifetime = 3 + random2(12) * 3; + const int spread_rate = random_range(5,15); + check_place_cloud(CLOUD_CHAOS, you.pos(), lifetime, + nullptr, spread_rate); take_note(Note(NOTE_XOM_EFFECT, you.piety, -1, "chaos cloud"), true); god_speaks(GOD_XOM, _get_xom_speech("cloud").c_str()); From 5a199981cbad0571377e7299513e1221979f33d2 Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 29 Jan 2019 15:34:46 -0500 Subject: [PATCH 004/864] checkwhite --- crawl-ref/docs/develop/rng_guidelines.md | 1 - crawl-ref/source/directn.cc | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/crawl-ref/docs/develop/rng_guidelines.md b/crawl-ref/docs/develop/rng_guidelines.md index bba99d8f535a..26c09242c699 100644 --- a/crawl-ref/docs/develop/rng_guidelines.md +++ b/crawl-ref/docs/develop/rng_guidelines.md @@ -130,4 +130,3 @@ is a case where the RNG behavior can be fine, but the list order itself could lead to divergence. For example, when choosing from a list of files provided by the OS, you cannot assume that all OSs and OS versions will give you these files in a stable order - sort it yourself. - diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc index 454a374c05d6..8746530ce160 100644 --- a/crawl-ref/source/directn.cc +++ b/crawl-ref/source/directn.cc @@ -184,7 +184,7 @@ void dist::confusion_fuzz(int range) target = you.pos(); target.x += random_range(-range, range); target.y += random_range(-range, range); - + choseRay = false; } From 4a9ad9352148acb923833485d6bb2bd7940ec002 Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 29 Jan 2019 19:32:52 -0500 Subject: [PATCH 005/864] Another batch of randomization sequence fixes mostly to do with items this time. --- crawl-ref/source/actor.cc | 7 +++++-- crawl-ref/source/artefact.cc | 9 ++++++--- crawl-ref/source/item-name.cc | 5 +++-- crawl-ref/source/item-use.cc | 5 ++++- crawl-ref/source/makeitem.cc | 28 +++++++++++++++++++++------- crawl-ref/source/monster.cc | 4 ++-- 6 files changed, 41 insertions(+), 17 deletions(-) diff --git a/crawl-ref/source/actor.cc b/crawl-ref/source/actor.cc index f60ccdd4ea9a..64b7dd31bb38 100644 --- a/crawl-ref/source/actor.cc +++ b/crawl-ref/source/actor.cc @@ -124,7 +124,8 @@ int actor::check_res_magic(int power) const int adj_pow = ench_power_stepdown(power); const int mrchance = (100 + mrs) - adj_pow; - const int mrch2 = random2(100) + random2(101); + int mrch2 = random2(100); + mrch2 += random2(101); dprf("Power: %d (%d pre-stepdown), MR: %d, target: %d, roll: %d", adj_pow, power, mrs, mrchance, mrch2); @@ -363,7 +364,9 @@ int actor::apply_ac(int damage, int max_damage, ac_type ac_rule, gdr /= 2; break; case AC_TRIPLE: - saved = random2(1 + ac) + random2(1 + ac) + random2(1 + ac); + saved = random2(1 + ac); + saved += random2(1 + ac); + saved += random2(1 + ac); ac *= 3; // apply GDR only twice rather than thrice, that's probably still waaay // too good. 50% gives 75% rather than 100%, too. diff --git a/crawl-ref/source/artefact.cc b/crawl-ref/source/artefact.cc index bc79fc59f9b8..840713ae9c6e 100644 --- a/crawl-ref/source/artefact.cc +++ b/crawl-ref/source/artefact.cc @@ -684,7 +684,7 @@ static const artefact_prop_data artp_data[] = #endif { "Slay", ARTP_VAL_ANY, 30, // ARTP_SLAYING, []() { return 2 + random2(2); }, - []() { return -(2 + random2(3) + random2(3)); }, 3, 2 }, + []() { return -(3 + random2(5)); }, 3, 2 }, { "*Curse", ARTP_VAL_POS, 0, nullptr, nullptr, 0 }, // ARTP_CURSE, { "Stlth", ARTP_VAL_ANY, 40, // ARTP_STEALTH, _gen_good_res_artp, _gen_bad_res_artp, 0, 0 }, @@ -850,7 +850,8 @@ static void _get_randart_properties(const item_def &item, // things get spammy. Extra "good" properties will be used to enhance // properties only, not to add more distinct properties. There is still a // small chance of >4 properties. - const int max_properties = 4 + one_chance_in(20) + one_chance_in(40); + int max_properties = 4 + one_chance_in(20); + max_properties += one_chance_in(40); int enhance = 0; if (good + bad > max_properties) { @@ -1707,7 +1708,9 @@ static void _make_faerie_armour(item_def &item) item.props = doodad.props; // On body armour, an enchantment of less than 0 is never viable. - item.plus = max(random2(6) + random2(6) - 2, random2(2)); + int high_plus = random2(6) - 2; + high_plus += random2(6); + item.plus = max(high_plus, random2(2)); } static jewellery_type octoring_types[8] = diff --git a/crawl-ref/source/item-name.cc b/crawl-ref/source/item-name.cc index 5b1af9396c96..cff226849b3e 100644 --- a/crawl-ref/source/item-name.cc +++ b/crawl-ref/source/item-name.cc @@ -2745,8 +2745,9 @@ string make_name(uint32_t seed, makename_type name_type) bool has_space = false; // Keep track of whether the name contains a space. - size_t len = 3 + rng.get_uint32() % 5 - + ((rng.get_uint32() % 5 == 0) ? rng.get_uint32() % 6 : 1); + size_t len = 3; + len += rng.get_uint32() % 5; + len += (rng.get_uint32() % 5 == 0) ? rng.get_uint32() % 6 : 1; if (name_type == MNAME_SCROLL) // scrolls have longer names len += 6; diff --git a/crawl-ref/source/item-use.cc b/crawl-ref/source/item-use.cc index 661c25262881..6dd18b33fad2 100644 --- a/crawl-ref/source/item-use.cc +++ b/crawl-ref/source/item-use.cc @@ -2999,6 +2999,7 @@ void read_scroll(item_def& scroll) break; case SCR_FOG: + { if (alreadyknown && (env.level_state & LSTATE_STILL_WINDS)) { mpr("The air is too still for clouds to form."); @@ -3006,8 +3007,10 @@ void read_scroll(item_def& scroll) break; } mpr("The scroll dissolves into smoke."); - big_cloud(random_smoke_type(), &you, you.pos(), 50, 8 + random2(8)); + auto smoke = random_smoke_type(); + big_cloud(smoke, &you, you.pos(), 50, 8 + random2(8)); break; + } case SCR_MAGIC_MAPPING: if (alreadyknown && !is_map_persistent()) diff --git a/crawl-ref/source/makeitem.cc b/crawl-ref/source/makeitem.cc index 9c78675058ad..9ed7c37d528e 100644 --- a/crawl-ref/source/makeitem.cc +++ b/crawl-ref/source/makeitem.cc @@ -225,7 +225,9 @@ static bool _try_make_weapon_artefact(item_def& item, int force_type, return false; // Mean enchantment +6. - item.plus = 12 - biased_random2(7,2) - biased_random2(7,2) - biased_random2(7,2); + item.plus = 12 - biased_random2(7,2); + item.plus -= biased_random2(7,2); + item.plus -= biased_random2(7,2); bool cursed = false; if (one_chance_in(5)) @@ -687,7 +689,10 @@ static void _generate_missile_item(item_def& item, int force_type, } else if (item.sub_type == MI_STONE) { - item.quantity = 1 + random2(7) + random2(10) + random2(12) + random2(10); + item.quantity = 1 + random2(7); // sequence points for random2 + item.quantity += random2(10); + item.quantity += random2(12); + item.quantity += random2(10); return; } else if (item.sub_type == MI_THROWING_NET) // no fancy nets, either @@ -709,10 +714,15 @@ static void _generate_missile_item(item_def& item, int force_type, { item.quantity = random_range(2, 8); } - else if (get_ammo_brand(item) != SPMSL_NORMAL) - item.quantity = 1 + random2(7) + random2(10) + random2(10); else - item.quantity = 1 + random2(7) + random2(10) + random2(10) + random2(12); + { + item.quantity = 1 + random2(7); // sequence points for random2 + item.quantity += random2(10); + item.quantity += random2(10); + if (get_ammo_brand(item) == SPMSL_NORMAL) + item.quantity += random2(12); + + } } static bool _armour_disallows_randart(int sub_type) @@ -1966,7 +1976,10 @@ int items(bool allow_uniques, if (force_good) item.quantity = 100 + random2(400); else - item.quantity = 1 + random2avg(19, 2) + random2(item_level); + { + item.quantity = 1 + random2avg(19, 2); + item.quantity += random2(item_level); + } break; } @@ -2169,9 +2182,10 @@ void makeitem_tests() item.brand = SPWPN_FORBID_BRAND; } #endif + auto weap_type = coinflip() ? OBJ_RANDOM : random2(NUM_WEAPONS); _generate_weapon_item(item, coinflip(), - coinflip() ? OBJ_RANDOM : random2(NUM_WEAPONS), + weap_type, level); } diff --git a/crawl-ref/source/monster.cc b/crawl-ref/source/monster.cc index eebd4947bc47..f37d45022871 100644 --- a/crawl-ref/source/monster.cc +++ b/crawl-ref/source/monster.cc @@ -4288,8 +4288,8 @@ bool monster::drain_exp(actor *agent, bool quiet, int pow) if (alive()) { - int dur = min(200 + random2(100), - 300 - get_ench(ENCH_DRAINED).duration - random2(50)); + int dur = 200 + random2(100); + dur = min(dur, 300 - get_ench(ENCH_DRAINED).duration - random2(50)); if (res_negative_energy()) dur /= (res_negative_energy() * 2); From 797c3c0885dbb8fb9a15502649bb0e9193f8eccb Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 29 Jan 2019 19:53:42 -0500 Subject: [PATCH 006/864] Fix accidental cursed slaying nerf (gammafunk) --- crawl-ref/source/artefact.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/artefact.cc b/crawl-ref/source/artefact.cc index 840713ae9c6e..2df00a5714f8 100644 --- a/crawl-ref/source/artefact.cc +++ b/crawl-ref/source/artefact.cc @@ -684,7 +684,7 @@ static const artefact_prop_data artp_data[] = #endif { "Slay", ARTP_VAL_ANY, 30, // ARTP_SLAYING, []() { return 2 + random2(2); }, - []() { return -(3 + random2(5)); }, 3, 2 }, + []() { return -(2 + random2(5)); }, 3, 2 }, { "*Curse", ARTP_VAL_POS, 0, nullptr, nullptr, 0 }, // ARTP_CURSE, { "Stlth", ARTP_VAL_ANY, 40, // ARTP_STEALTH, _gen_good_res_artp, _gen_bad_res_artp, 0, 0 }, From 964d818aa416390ea561458ecb4dbdf41eda02ba Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 29 Jan 2019 22:18:59 -0500 Subject: [PATCH 007/864] Use a separate rng for ghosts The most recent set of seed instabilities I've been seeing are because the ghost loading code makes a different number of random number draws depending on whether it loads from the permastore or not, and in a clean setup it was guaranteed to draw from the permastore on the first run, but not thereafter, for some seeds. (Because even a permastore ghost gets resaved as an ephemeral ghost if a level is vetoed - something that is perhaps a bug itself.) In general, it seems risky to use levelgen rng for something that may depend on what's on a particular file system, so separate this off into its own rng for cases like this, distinct also from the gameplay rng. Also, fixed a bug in loading of ephemeral ghost files where if there was more than one ghost in the file, the wrong one would be removed after a ghost was selected for use. --- crawl-ref/source/files.cc | 5 ++++- crawl-ref/source/rng-type.h | 10 +++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 547bec8e123d..998fffb0de1b 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -2177,6 +2177,8 @@ static vector _load_permastore_ghosts(bool backup_on_upgrade=false) */ bool define_ghost_from_bones(monster& mons) { + rng_generator rng(RNG_SYSTEM_SPECIFIC); + bool used_permastore = false; vector loaded_ghosts = _load_ephemeral_ghosts(); @@ -2206,7 +2208,7 @@ bool define_ghost_from_bones(monster& mons) if (!used_permastore) { - loaded_ghosts.erase(loaded_ghosts.begin()); + loaded_ghosts.erase(loaded_ghosts.begin() + place_i); if (!loaded_ghosts.empty()) save_ghosts(loaded_ghosts); @@ -2758,6 +2760,7 @@ static size_t _ghost_permastore_size() static vector _update_permastore(const vector &ghosts) { + rng_generator rng(RNG_SYSTEM_SPECIFIC); if (ghosts.empty()) return ghosts; diff --git a/crawl-ref/source/rng-type.h b/crawl-ref/source/rng-type.h index c9aec27b4efa..a72eca156b72 100644 --- a/crawl-ref/source/rng-type.h +++ b/crawl-ref/source/rng-type.h @@ -2,11 +2,11 @@ #include "branch-type.h" enum rng_type { - RNG_GAMEPLAY, - RNG_UI, - RNG_SPARE1, + RNG_GAMEPLAY, // gameplay effects in general + RNG_UI, // UI randomization + RNG_SYSTEM_SPECIFIC, // anything that may vary from system to system, e.g. ghosts RNG_SPARE2, RNG_SPARE3, - RNG_LEVELGEN, // branch 0 - NUM_RNGS = RNG_LEVELGEN + NUM_BRANCHES, + RNG_LEVELGEN, // branch 0, i.e. the dungeon + NUM_RNGS = RNG_LEVELGEN + NUM_BRANCHES, // and then one for each other branch }; From 1bb09026696bd0ca6d2e9a1487cb25d998e4187b Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 29 Jan 2019 23:39:09 -0500 Subject: [PATCH 008/864] Clear unrand state for relevant tests This was impacting generation and causing a false positive for seed inconsisticies. --- crawl-ref/source/l-debug.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/source/l-debug.cc b/crawl-ref/source/l-debug.cc index cd2e092f2efb..300bb1ce2316 100644 --- a/crawl-ref/source/l-debug.cc +++ b/crawl-ref/source/l-debug.cc @@ -94,6 +94,7 @@ LUAFN(debug_flush_map_memory) dgn_flush_map_memory(); init_level_connectivity(); you.unique_creatures.reset(); + you.unique_items.init(UNIQ_NOT_EXISTS); return 0; } From bed441b55a9dc02b47e2d692a82257b9a83a5d86 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Wed, 30 Jan 2019 18:59:35 -0500 Subject: [PATCH 009/864] Dissapate Guardian Golem clouds out of LOS (11701) Change guardian golem's inner flame actor to MID_YOU_FAULTLESS (from nullptr), and disappate clouds owned by MID_YOU_FAULTLESSS when out of LOS. --- crawl-ref/source/cloud.cc | 3 ++- crawl-ref/source/mon-abil.cc | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/cloud.cc b/crawl-ref/source/cloud.cc index 2c5530a767ea..2aab95644ec8 100644 --- a/crawl-ref/source/cloud.cc +++ b/crawl-ref/source/cloud.cc @@ -493,7 +493,8 @@ static int _cloud_dissipation_rate(const cloud_struct &cloud) // Player-created non-opaque clouds vanish instantly when outside LOS. // (Opaque clouds don't to prevent cloud suicide.) - if (cloud.source == MID_PLAYER && !you.see_cell_no_trans(cloud.pos) + if ((cloud.source == MID_PLAYER || cloud.source == MID_YOU_FAULTLESS) + && !you.see_cell_no_trans(cloud.pos) && !is_opaque_cloud(cloud.type)) { return cloud.decay; diff --git a/crawl-ref/source/mon-abil.cc b/crawl-ref/source/mon-abil.cc index 9a85933141d8..8dea394c67ab 100644 --- a/crawl-ref/source/mon-abil.cc +++ b/crawl-ref/source/mon-abil.cc @@ -1156,7 +1156,9 @@ bool mon_special_ability(monster* mons) && !mons->has_ench(ENCH_INNER_FLAME)) { simple_monster_message(*mons, " overheats!"); - mons->add_ench(mon_enchant(ENCH_INNER_FLAME, 0, 0, + mid_t act = mons->summoner == MID_PLAYER ? MID_YOU_FAULTLESS : + mons->summoner; + mons->add_ench(mon_enchant(ENCH_INNER_FLAME, 0, actor_by_mid(act), INFINITE_DURATION)); } break; From b30acc42871188601ac7392268179c601f85918c Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Wed, 30 Jan 2019 20:17:18 -0500 Subject: [PATCH 010/864] Prompt before using bad or dangerous consumables (11836) This covers immolation, vulnerability, noise, mutation, lignification, and degeneration, as well as torment and holy word when applicable. The new behavior can be disabled by setting an option `bad_item_prompt` to false. --- crawl-ref/docs/options_guide.txt | 5 ++++- crawl-ref/source/initfile.cc | 1 + crawl-ref/source/item-use.cc | 34 +++++++++++++++++++++++--------- crawl-ref/source/options.h | 1 + 4 files changed, 31 insertions(+), 10 deletions(-) diff --git a/crawl-ref/docs/options_guide.txt b/crawl-ref/docs/options_guide.txt index 71fce2f0a157..be8466bf78d1 100644 --- a/crawl-ref/docs/options_guide.txt +++ b/crawl-ref/docs/options_guide.txt @@ -62,7 +62,7 @@ The contents of this text are: automagic_slot, automagic_fight, automagic_stop, fail_severity_to_confirm, easy_door, warn_hatches, enable_recast_spell, confirm_action, regex_search, - autopickup_search + autopickup_search, bad_item_prompt 3-h Message and Display Improvements. hp_warning, mp_warning, hp_colour, mp_colour, stat_colour, status_caption_colour, enemy_hp_colour, clear_messages, @@ -1383,6 +1383,9 @@ autopickup_search = false option may slow down your game if you have a complicated custom autopickup function. +bad_item_prompt = true + Ask for confirmation before using bad or dangerous scrolls and potions. + 3-h Messages and Display Enhancements. ------------------------------------------ diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index 7e8de4eef2ef..a24c04834b97 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -204,6 +204,7 @@ const vector game_options::build_options_list() new BoolGameOption(SIMPLE_NAME(use_modifier_prefix_keys), true), new BoolGameOption(SIMPLE_NAME(ability_menu), true), new BoolGameOption(SIMPLE_NAME(easy_floor_use), true), + new BoolGameOption(SIMPLE_NAME(bad_item_prompt), true), new BoolGameOption(SIMPLE_NAME(dos_use_background_intensity), true), new BoolGameOption(SIMPLE_NAME(explore_greedy), true), new BoolGameOption(SIMPLE_NAME(explore_auto_rest), false), diff --git a/crawl-ref/source/item-use.cc b/crawl-ref/source/item-use.cc index 6dd18b33fad2..ad0325039ae4 100644 --- a/crawl-ref/source/item-use.cc +++ b/crawl-ref/source/item-use.cc @@ -2095,6 +2095,16 @@ void drink(item_def* potion) return; } + string prompt = make_stringf("Really quaff the %s?", + potion->name(DESC_DBNAME).c_str()); + if (alreadyknown && is_dangerous_item(*potion, true) + && Options.bad_item_prompt + && !yesno(prompt.c_str(), false, 'n')) + { + canned_msg(MSG_OK); + return; + } + // The "> 1" part is to reduce the amount of times that Xom is // stimulated when you are a low-level 1 trying your first unknown // potions on monsters. @@ -2805,6 +2815,10 @@ void read(item_def* scroll) bool penance = god_hates_item(*scroll); string verb_object = "read the " + scroll->name(DESC_DBNAME); + string penance_prompt = make_stringf("Really %s? This action would" + " place you under penance!", + verb_object.c_str()); + targeter_los hitfunc(&you, LOS_NO_TRANS); if (stop_attack_prompt(hitfunc, verb_object.c_str(), @@ -2816,15 +2830,17 @@ void read(item_def* scroll) { return; } - - string penance_prompt = make_stringf("Really %s? This action would" - " place you under penance!", - verb_object.c_str()); - // Having a separate prompt if the player is going to harm allies and - // get penance is a bit awkward; but for gods where this will happen - // the player is going to get punished both for hurting the allies and - // using a bad item so they'd better be sure. - if (penance && !yesno(penance_prompt.c_str(), false, 'n')) + else if (penance && !yesno(penance_prompt.c_str(), false, 'n')) + { + canned_msg(MSG_OK); + return; + } + else if ((is_dangerous_item(*scroll, true) + || is_bad_item(*scroll, true)) + && Options.bad_item_prompt + && !yesno(make_stringf("Really %s?", + verb_object.c_str()).c_str(), + false, 'n')) { canned_msg(MSG_OK); return; diff --git a/crawl-ref/source/options.h b/crawl-ref/source/options.h index 46ff41541413..67cdf2a1d57d 100644 --- a/crawl-ref/source/options.h +++ b/crawl-ref/source/options.h @@ -410,6 +410,7 @@ struct game_options // pickup bool ability_menu; // 'a'bility starts with a full-screen menu bool easy_floor_use; // , selects the floor item if there's 1 + bool bad_item_prompt; // Confirm before using a bad consumable int assign_item_slot; // How free slots are assigned maybe_bool show_god_gift; // Show {god gift} in item names From b84795dc94a124f5d16541b75c439684a3ca1562 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Wed, 30 Jan 2019 23:24:57 -0500 Subject: [PATCH 011/864] Describe tree form in potion of lignification (damerell) --- crawl-ref/source/dat/descript/items.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/dat/descript/items.txt b/crawl-ref/source/dat/descript/items.txt index 103ef9842297..936b6ddaadac 100644 --- a/crawl-ref/source/dat/descript/items.txt +++ b/crawl-ref/source/dat/descript/items.txt @@ -709,8 +709,10 @@ A potion which confers invisibility on one who consumes it. potion of lignification A potion which transforms the imbiber into an animated tree with branches -capable of holding weapons. Such a tree is very resilient, although it is -rooted in place while the transformation lasts, and cannot teleport. +capable of holding weapons. Such a tree has minimal evasion but increased +health and natural armour, and is resistant to poison and immune to negative +energy. However, it is rooted in place while the transformation lasts, and +cannot teleport. %%%% potion of magic From 46ee55fc946609c283ac45eaa0f9360d1937ecb1 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Thu, 31 Jan 2019 00:36:45 -0500 Subject: [PATCH 012/864] Don't use player spell colours for monster spellbooks --- crawl-ref/source/describe-spells.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/describe-spells.cc b/crawl-ref/source/describe-spells.cc index 130128cd7966..dad8222f126a 100644 --- a/crawl-ref/source/describe-spells.cc +++ b/crawl-ref/source/describe-spells.cc @@ -518,7 +518,8 @@ static void _describe_book(const spellbook_contents &book, { description.cprintf(" "); - description.textcolour(_spell_colour(spell, source_item)); + if (!mon_owner) + description.textcolour(_spell_colour(spell, source_item)); // don't crash if we have more spells than letters. auto entry = find_if(spell_map.begin(), spell_map.end(), From a9077f9e91af61645bcd1e8864e5deb5bfcf347e Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 30 Jan 2019 13:12:32 -0500 Subject: [PATCH 013/864] More improvements to randomization * don't use math.random for bazaar tiles * clean up rng and early D vault tests --- crawl-ref/docs/develop/rng_guidelines.md | 5 +++ crawl-ref/source/dat/des/portals/bazaar.des | 2 +- crawl-ref/source/test/00rng_test.lua | 40 --------------------- crawl-ref/source/test/d1_vaults.lua | 2 +- crawl-ref/source/test/rng_test.lua | 17 +++++++++ 5 files changed, 24 insertions(+), 42 deletions(-) delete mode 100644 crawl-ref/source/test/00rng_test.lua create mode 100644 crawl-ref/source/test/rng_test.lua diff --git a/crawl-ref/docs/develop/rng_guidelines.md b/crawl-ref/docs/develop/rng_guidelines.md index 26c09242c699..bf728693090b 100644 --- a/crawl-ref/docs/develop/rng_guidelines.md +++ b/crawl-ref/docs/develop/rng_guidelines.md @@ -130,3 +130,8 @@ is a case where the RNG behavior can be fine, but the list order itself could lead to divergence. For example, when choosing from a list of files provided by the OS, you cannot assume that all OSs and OS versions will give you these files in a stable order - sort it yourself. + +### 3.3 other sources of randomization + +Don't use other sources of randomization in crawl besides crawl RNGs. For +example, don't use lua's `math.rand`, or C stdlib's `rand`. diff --git a/crawl-ref/source/dat/des/portals/bazaar.des b/crawl-ref/source/dat/des/portals/bazaar.des index 61d6047d64b4..479f184e2bd0 100644 --- a/crawl-ref/source/dat/des/portals/bazaar.des +++ b/crawl-ref/source/dat/des/portals/bazaar.des @@ -65,7 +65,7 @@ local tilesets = { -- Chooses a bazaar tileset from a list of predefined ones. function random_bazaar_tileset() local keys = util.keys(tilesets) - return tilesets[keys[math.random(#keys)]] + return tilesets[keys[crawl.random2(#keys) + 1]] end -- This should be called for every bazaar vault, as it sets some standard map diff --git a/crawl-ref/source/test/00rng_test.lua b/crawl-ref/source/test/00rng_test.lua deleted file mode 100644 index bd68a06c3101..000000000000 --- a/crawl-ref/source/test/00rng_test.lua +++ /dev/null @@ -1,40 +0,0 @@ --- this test prints out the D:1 vaults for some test seeds. This can be used --- to diagnose when seeding changes or isn't working right. - --- this test messes with RNG state! It leaves the RNG with a clean seed 1, --- but if you are expecting deterministic test behavior, take that into --- account. - -local eol = string.char(13) - -debug.reset_rng(1) -crawl.stderr("Here are 10 random numbers from seed 1:" .. eol) -for i = 1,10 do - crawl.stderr(crawl.random2(100) .. " ") -end -crawl.stderr(eol) - -for seed = 1,10 do - debug.reset_rng(seed) - crawl.stderr(" initial rng: " .. debug.get_rng_state() .. eol) - -- debug.enter_dungeon() crashes, for some reason - -- the following runs through RNG state in the same way that starting a - -- regular game would -- if it produces different results, that's a bug. - debug.flush_map_memory() - debug.dungeon_setup() - crawl.stderr(" after dgn setup: " .. debug.get_rng_state() .. eol) - debug.goto_place("D:1") - debug.generate_level() - local vault_names = debug.vault_names() - - crawl.stderr("D:1 vaults for seed " .. seed .. " are: " .. vault_names .. eol) - crawl.stderr(" after D:1 gen: " .. debug.get_rng_state() .. eol) - debug.goto_place("Temple") - debug.generate_level() - local vault_names = debug.vault_names() - - crawl.stderr("Temple vaults for seed " .. seed .. " are: " .. vault_names .. eol) - -end - -debug.reset_rng(1) diff --git a/crawl-ref/source/test/d1_vaults.lua b/crawl-ref/source/test/d1_vaults.lua index 38f9f2ce0a74..c6cba3fb0897 100644 --- a/crawl-ref/source/test/d1_vaults.lua +++ b/crawl-ref/source/test/d1_vaults.lua @@ -1,4 +1,4 @@ --- this test prints out the D:1 vaults for some test seeds. This can be used +-- this test prints out the D:1-D:4 vaults for some test seeds. This can be used -- to diagnose when seeding changes or isn't working right. -- this test messes with RNG state! It leaves the RNG with a clean seed 1, diff --git a/crawl-ref/source/test/rng_test.lua b/crawl-ref/source/test/rng_test.lua new file mode 100644 index 000000000000..151257c7cbb8 --- /dev/null +++ b/crawl-ref/source/test/rng_test.lua @@ -0,0 +1,17 @@ +-- This test prints out some random numbers from seed 1. If they ever change, +-- something has broken the stability of the rng. + +local eol = string.char(13) + +local results = {49, 97, 51, 75, 3, 38, 66, 84, 28, 76} + +debug.reset_rng(1) +crawl.stderr("Here are 10 random numbers from seed 1:" .. eol) +for i = 1,10 do + n = crawl.random2(100) + crawl.stderr(" " .. n) + assert(n == results[i]) +end +crawl.stderr(eol) + +debug.reset_rng(1) From 18b65154750a31a5866a4b2ecbe71c581ff3657c Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 31 Jan 2019 08:14:14 -0500 Subject: [PATCH 014/864] Remove crawl.random_element and replace with something more stable Because lua iteration order, including at the C level, is not stable, this was leading to seed variation in parts of the dungeon that heavily use layout code. I've replaced it with a pure lua implementation of random_choose_weighted (that parallels the C++ version); in principle one could call into the C++ version, but it wasn't clear that there was much of a point to that amount of effort. This version is stable because it uses an array of pairs for the weight table; `ipairs` gives a stable iteration order. Notationally it's not any more effortful. --- crawl-ref/docs/develop/rng_guidelines.md | 23 +++- crawl-ref/source/dat/des/builder/layout.des | 49 +++++---- .../source/dat/des/builder/layout_city.des | 20 ++-- .../source/dat/des/builder/layout_delve.des | 32 +++--- .../dat/des/builder/layout_geoelf_castle.des | 19 ++-- .../source/dat/des/builder/layout_loops.des | 2 +- .../source/dat/des/builder/layout_pools.des | 2 +- crawl-ref/source/dat/des/portals/ossuary.des | 12 +- .../source/dat/des/variable/large_themed.des | 8 +- .../source/dat/des/variable/mini_features.des | 6 +- .../source/dat/dlua/layout/geoelf_glyphs.lua | 12 +- .../source/dat/dlua/layout/geoelf_rooms.lua | 103 +++++++++--------- crawl-ref/source/dat/dlua/layout/theme.lua | 10 +- crawl-ref/source/dat/dlua/util.lua | 27 ++++- crawl-ref/source/l-crawl.cc | 62 ----------- 15 files changed, 183 insertions(+), 204 deletions(-) diff --git a/crawl-ref/docs/develop/rng_guidelines.md b/crawl-ref/docs/develop/rng_guidelines.md index bf728693090b..48873907aea2 100644 --- a/crawl-ref/docs/develop/rng_guidelines.md +++ b/crawl-ref/docs/develop/rng_guidelines.md @@ -125,11 +125,24 @@ that are sequenced by `;`s. ### 3.2 choosing from lists When you are randomly choosing an item from a list (e.g. by randomly picking -an index in the list range), be careful about the underlying list order. This -is a case where the RNG behavior can be fine, but the list order itself could -lead to divergence. For example, when choosing from a list of files provided -by the OS, you cannot assume that all OSs and OS versions will give you these -files in a stable order - sort it yourself. +an index in the list range), be careful about both the underlying list order, +and the iteration order. + +**Underlying list order**: This is a case where the RNG behavior can be fine, +but the list order itself could lead to divergence. For example, when choosing +from a list of files provided by the OS, you cannot assume that all OSs and OS +versions will give you these files in a stable order - sort it yourself. + +**Iteration order**: If you are using some sort of reservoir-sampling style of +random choice algorithm, you will iterate through the container, stopping the +iteration at some point determined by one or more random draws. If the +iteration order is not guaranteed to be defined, this can lead to different +results from run to run. For example, in lua, iteration via `pairs` or the +C equivalents over a table is not guaranteed to have a stable order, and we +have found that in practice it doesn't -- leading to different choices with +the same random number draws. The `ipairs` iterator is safe, but places some +obvious constraints on the structure you are using. Sorting the underlying +container may be a solution as well. ### 3.3 other sources of randomization diff --git a/crawl-ref/source/dat/des/builder/layout.des b/crawl-ref/source/dat/des/builder/layout.des index c3b67b732da2..2408f4e3b50e 100644 --- a/crawl-ref/source/dat/des/builder/layout.des +++ b/crawl-ref/source/dat/des/builder/layout.des @@ -114,10 +114,10 @@ TAGS: overwritable layout no_primary_vault unrand layout_type_open obl = 5 + crawl.random2(20) end - local fill = crawl.random_element({ - ["."] = 10, - ["w"] = 5, - ["l"] = 1, + local fill = util.random_choose_weighted({ + {'.', 10}, + {'w', 5}, + {'l', 1}, }) octa_room{x1=25, y1=25, x2=gxm-25, y2=gym-25, oblique=obl, replace='x', inside=fill} @@ -281,15 +281,15 @@ TAGS: uniq_open_layout -- pillar types and relative weights local pillar_fill = { - ["x"] = 15, - ["b"] = 5, - ["v"] = 4, - ["m"] = 3, - ["w"] = 2, - ["l"] = 1, + {'x', 15}, + {'b', 5}, + {'v', 4}, + {'m', 3}, + {'w', 2}, + {'l', 1} } if (you.in_branch("lair")) then - pillar_fill["t"] = 15 + pillar_fill[#pillar_fill + 1] = {'t', 15} end -- Potential pillar drawing routines @@ -314,7 +314,7 @@ TAGS: uniq_open_layout 1 + crawl.random2((pfunc == make_diamond) and 3 or 2) circle_radius = circle_radius + pillar_radius * 2 + num / 2 if circle_radius >= (gym-oblique)/2 then break end - local fill = crawl.random_element(pillar_fill) + local fill = util.random_choose_weighted(pillar_fill) -- Finally, make the pillars local make_pillar = function(x, y) @@ -591,7 +591,8 @@ TAGS: no_rotate no_vmirror no_hmirror local rooms = {} local i, j - local wall_type = crawl.random_element { ['x'] = 3, ['c'] = 3, ['v'] = 2 } + local wall_type = util.random_choose_weighted( + { {'x', 3}, {'c', 3}, {'v', 2} } ) local percent_thickness_2 = crawl.random_range(0, 8) * crawl.random_range(0, 8) local percent_thickness_3 = crawl.random_range(0, 7) @@ -728,14 +729,14 @@ TAGS: no_rotate no_vmirror no_hmirror local outer_door = '+' local inner_door = '+' if thickness == 2 then - outer_door = crawl.random_element { ['+'] = 1, ['.'] = 2 } - inner_door = crawl.random_element { ['+'] = 1, ['.'] = 3 } + outer_door = util.random_choose_weighted { {'+', 1}, {'.', 2} } + inner_door = util.random_choose_weighted { {'+', 1}, {'.', 3} } elseif thickness == 3 then - outer_door = crawl.random_element { ['+'] = 2, ['.'] = 1 } - inner_door = crawl.random_element { ['+'] = 1, ['.'] = 2 } + outer_door = util.random_choose_weighted { {'+', 2}, {'.', 1} } + inner_door = util.random_choose_weighted { {'+', 1}, {'.', 2} } elseif thickness == 4 then - outer_door = crawl.random_element { ['+'] = 4, ['.'] = 1 } - inner_door = crawl.random_element { ['+'] = 1, ['.'] = 1 } + outer_door = util.random_choose_weighted { {'+', 4}, {'.', 1} } + inner_door = util.random_choose_weighted { {'+', 1}, {'.', 1} } end if outer_door == '.' and crawl.coinflip() then @@ -1062,8 +1063,8 @@ TAGS: overwritable layout no_primary_vault allow_dup unrand layout_type_rooms extend_map { width = gxm, height = gym, fill = 'x' } - local rows = crawl.random_element({[5] = 10, [4] = 5, [3] = 1}) - local cols = crawl.random_element({[5] = 10, [4] = 5, [3] = 1}) + local rows = util.random_choose_weighted({ {5, 10}, {4, 5}, {3, 1} }) + local cols = util.random_choose_weighted({ {5, 10}, {4, 5}, {3, 1} }) local xspace = 13 + 2*(5-cols) local yspace = 11 + 2*(5-rows) local xsize = 6 + 2*(5-cols) @@ -1144,9 +1145,9 @@ TAGS: overwritable layout no_primary_vault allow_dup unrand layout_type_rooms and (you.in_branch("D") or you.in_branch("Lair")) and crawl.x_chance_in_y(you.absdepth() - 9, 450) then - local feat = crawl.random_element { ['v'] = 2, - ['c'] = 3, - ['x'] = 3 } + local feat = util.random_choose_weighted({ {'v', 2}, + {'c', 3}, + {'x', 3} }) make_inner_room(room, feat) end end diff --git a/crawl-ref/source/dat/des/builder/layout_city.des b/crawl-ref/source/dat/des/builder/layout_city.des index fbf097da6a03..b69637e4c837 100644 --- a/crawl-ref/source/dat/des/builder/layout_city.des +++ b/crawl-ref/source/dat/des/builder/layout_city.des @@ -261,10 +261,10 @@ TAGS: no_rotate no_hmirror no_vmirror local percent_solid = { 0, 10, 40 } local in_distance = { 6, 5, 3 } - local base_wall_type = crawl.random_element - { ['x'] = 7, - ['c'] = 2, - ['v'] = 1 } + local base_wall_type = util.random_choose_weighted( + { {'x', 7}, + {'c', 2}, + {'v', 1} }) if you.in_branch("Dis") then base_wall_type = 'x' end @@ -314,12 +314,12 @@ TAGS: no_rotate no_hmirror no_vmirror if not blocked then local door_count = crawl.random_range(1, max_doors[current_stage]) local floor = '.' - local wall = crawl.random_element - { [base_wall_type] = base_wall_frequency, - ['x'] = 50, - ['c'] = 30, - ['v'] = 20, - ['b'] = 1 } + local wall = util.random_choose_weighted( + { {base_wall_type, base_wall_frequency}, + {'x', 50}, + {'c', 30}, + {'v', 20}, + {'b', 1} }) if you.in_branch("Dis") then wall = 'x' diff --git a/crawl-ref/source/dat/des/builder/layout_delve.des b/crawl-ref/source/dat/des/builder/layout_delve.des index 1ad09ba6cbca..dde0c72c0625 100644 --- a/crawl-ref/source/dat/des/builder/layout_delve.des +++ b/crawl-ref/source/dat/des/builder/layout_delve.des @@ -202,11 +202,11 @@ TAGS: no_rotate no_vmirror no_hmirror uniq_layout_twisted_delve local arm_thickness = crawl.random_range(1, 2) - local room_func = crawl.random_element( - { [make_circle] = 3, - [make_diamond] = 3, - [make_square] = 2, - [make_rounded_square] = 1 } ) + local room_func = util.random_choose_weighted( + { {make_circle, 3}, + {make_diamond, 3}, + {make_square, 2}, + {make_rounded_square, 1} } ) local room_radius = crawl.random_range(4, 7) if (i == 1) then @@ -434,10 +434,10 @@ TAGS: overwritable layout allow_dup unrand layout_type_narrow_caves ngb_min = 3 ngb_max = 4 end - local connchance = crawl.random_element - { [0] = 2, [5] = 1, [20] = 1, [50] = 1, [100] = 1 } - local top = crawl.random_element - { [1] = 1, [20] = 1, [125] = 1, [500] = 1, [999999] =1 } + local connchance = util.random_choose_weighted + { {0, 2}, {5, 1}, {20, 1}, {50, 1}, {100, 1} } + local top = util.random_choose_weighted + { {1, 1}, {20, 1}, {125, 1}, {500, 1}, {999999, 1} } crawl.dpr("delve(" .. ngb_min .. ", " .. ngb_max .. ", " .. connchance .. ", -1, " .. top .. ")") delve(ngb_min, ngb_max, connchance, -1, top) @@ -535,13 +535,13 @@ TAGS: no_rotate no_vmirror no_hmirror -- Delve some smaller paths for i = 1, crawl.random_range(1, 3) do - ngb_min = crawl.random_element { [1] = 3, [2] = 1 } + ngb_min = util.random_choose_weighted { {1, 3}, {2, 1} } ngb_max = crawl.random_range(2, 5) - connchance = crawl.random_element - { [0] = 1, [2] = 2, [5] = 1, [20] = 1 } + connchance = util.random_choose_weighted + { {0, 1}, {2, 2}, {5, 1}, {20, 1} } total_count = crawl.random_range(50, 150) - top = crawl.random_element - { [1] = 1, [20] = 1, [125] = 1, [500] = 1, [999999] = 1 } + top = util.random_choose_weighted + { {1, 1}, {20, 1}, {125, 1}, {500, 1}, {999999, 1} } delve(2, 3, 3, 150, 100) end @@ -564,8 +564,8 @@ TAGS: no_rotate no_vmirror no_hmirror for i = 1, crawl.random_range(15, 25) do local x = crawl.random_range(8, gxm-9) local y = crawl.random_range(8, gym-9) - local radius = crawl.random_element - { [1] = 30, [2] = 50, [3] = 15, [4] = 4, [5] = 1 } + local radius = util.random_choose_weighted + { {1, 30}, {2, 50}, {3, 15}, {4, 4}, {5, 1} } octa_room { x1 = x - radius, y1 = y - radius, x2 = x + radius, y2 = y + radius, diff --git a/crawl-ref/source/dat/des/builder/layout_geoelf_castle.des b/crawl-ref/source/dat/des/builder/layout_geoelf_castle.des index 9161f2bbcb4e..6b2dd7a062ca 100644 --- a/crawl-ref/source/dat/des/builder/layout_geoelf_castle.des +++ b/crawl-ref/source/dat/des/builder/layout_geoelf_castle.des @@ -999,15 +999,16 @@ TAGS: no_rotate no_vmirror no_hmirror end -- draw the turrets - local turret_center = crawl.random_element { - [geoelf.glyphs.TREE] = geoelf.glyphs.PLANTLIKE_OPTIONS[geoelf.glyphs.TREE], - [geoelf.glyphs.BUSH] = geoelf.glyphs.PLANTLIKE_OPTIONS[geoelf.glyphs.BUSH], - [geoelf.glyphs.PLANT] = geoelf.glyphs.PLANTLIKE_OPTIONS[geoelf.glyphs.PLANT], - [geoelf.glyphs.FUNGUS] = geoelf.glyphs.PLANTLIKE_OPTIONS[geoelf.glyphs.FUNGUS], - [geoelf.glyphs.STATUE] = geoelf.glyphs.FEATURE_OPTIONS[geoelf.glyphs.STATUE] * 5, - [geoelf.glyphs.FOUNTAIN] = geoelf.glyphs.FEATURE_OPTIONS[geoelf.glyphs.FOUNTAIN] * 5, - [INSIDE_GLYPH] = 15, - } + local turret_center_weights = {} + for i,p in ipairs(geoelf.glyphs.PLANTLIKE_OPTIONS) do + turrent_center_weights[#turret_center_weights + 1] = p + end + for i,p in ipairs(geoelf.glyphs.FEATURE_OPTIONS) do + turrent_center_weights[#turret_center_weights + 1] = {p[0], p[1] * 5} + end + turrent_center_weights[#turret_center_weights + 1] = {INSIDE_GLYPH, 15} + + local turret_center = util.random_choose_weighted(turret_center_weights) for i = geoelf.directions.COUNT_STRAIGHT, geoelf.directions.COUNT - 1 do if (castle.turret[i].is_placed) then diff --git a/crawl-ref/source/dat/des/builder/layout_loops.des b/crawl-ref/source/dat/des/builder/layout_loops.des index 572f19b8066b..05cd8d0c07ed 100644 --- a/crawl-ref/source/dat/des/builder/layout_loops.des +++ b/crawl-ref/source/dat/des/builder/layout_loops.des @@ -634,7 +634,7 @@ function loopsInsertRoom (e, center_x, center_y, radius, wall_glyph) end end else - local shape = crawl.random_element { [0] = 3, [1] = 2, [2] = 1 } + local shape = util.random_choose_weighted { {0, 3}, {1, 2}, {2, 1} } local center = crawl.random2(6) if you.in_branch("Elf") then shape = crawl.random2(4) diff --git a/crawl-ref/source/dat/des/builder/layout_pools.des b/crawl-ref/source/dat/des/builder/layout_pools.des index 1bcd09545e7d..ac06e5da1456 100644 --- a/crawl-ref/source/dat/des/builder/layout_pools.des +++ b/crawl-ref/source/dat/des/builder/layout_pools.des @@ -173,7 +173,7 @@ TAGS: no_rotate no_vmirror no_hmirror if you.in_branch("snake") then connection = '.' else - connection = crawl.random_element({['.'] = 1, ['+'] = 2}) + connection = util.random_choose_weighted({{'.', 1}, {'+', 2}}) end add_pools { replace = ".", diff --git a/crawl-ref/source/dat/des/portals/ossuary.des b/crawl-ref/source/dat/des/portals/ossuary.des index 94d1c7487857..5149f42341ed 100644 --- a/crawl-ref/source/dat/des/portals/ossuary.des +++ b/crawl-ref/source/dat/des/portals/ossuary.des @@ -656,15 +656,15 @@ flood(flood_x, flood_y, crawl.random_range(6, 16), function(x, y, distance) local c = mapgrd[x][y] local replacements = { - ['.'] = { ['.'] = 1, W = 2 }, - x = { x = 5, w = 5 }, - c = { c = 5, w = 3, W = 2, x = 1 }, - ['+'] = { ['+'] = 10, W = 5 }, - ['1'] = { ['2'] = 1 } + ['.'] = { {'.', 1}, {'W', 2} }, + ['x'] = { {'x', 5}, {'w', 5} }, + ['c'] = { {'c', 5}, {'w', 3}, {'W', 2}, {'x', 1} }, + ['+'] = { {'+', 10}, {'W', 5} }, + ['1'] = { {'2', 1} } } if replacements[c] then - mapgrd[x][y] = crawl.random_element(replacements[c]) + mapgrd[x][y] = util.random_choose_weighted(replacements[c]) end if c == '+' or c == 'v' then diff --git a/crawl-ref/source/dat/des/variable/large_themed.des b/crawl-ref/source/dat/des/variable/large_themed.des index 7648c17d1d51..c482cedde0d4 100644 --- a/crawl-ref/source/dat/des/variable/large_themed.des +++ b/crawl-ref/source/dat/des/variable/large_themed.des @@ -1618,19 +1618,19 @@ DEPTH: D:3-4 -- possible hobgoblin bosses and their weights bossw = {hobgoblin = 1, Ijyb = 10, Robin = 10} - bosses = {hobgoblin = 1} + bosses = { {"hobgoblin", 1}, } -- Find out which hobgoblin uniques we can use if not you.uniques("Ijyb") then - bosses["Ijyb"] = bossw["Ijyb"] + bosses[#bosses + 1] = {"Ijyb", bossw["Ijyb"]} end if not you.uniques("Robin") then - bosses["Robin"] = bossw["Robin"] + bosses[#bosses + 1] = {"Robin", bossw["Robin"]} end -- Choose a boss, and remove the supporting goblins if we select Robin, since -- she has her own band. - boss = crawl.random_element(bosses) + boss = util.random_choose_weighted(bosses) if boss == "Robin" then subst("B = .") boss = "Robin band" diff --git a/crawl-ref/source/dat/des/variable/mini_features.des b/crawl-ref/source/dat/des/variable/mini_features.des index 46e5a13ee8df..d59806680cbd 100644 --- a/crawl-ref/source/dat/des/variable/mini_features.des +++ b/crawl-ref/source/dat/des/variable/mini_features.des @@ -1810,11 +1810,11 @@ DEPTH: D, Depths -- Kind of a complicated version of init_hm_decor_walldepth to make sure that -- the glass matches the wall feature. local a = you.absdepth() * 5 -local weights = {["x"] = 50, ["c"] = a} +local weights = { {"x", 50}, {"c", a} } if a - 75 > 0 then - weights["b"] = a - 75 + weights[#weights + 1] = {"b", a - 75} end -local wall = crawl.random_element(weights) +local wall = util.random_choose_weighted(weights) local glass = 'm' if wall == 'c' then glass = 'n' diff --git a/crawl-ref/source/dat/dlua/layout/geoelf_glyphs.lua b/crawl-ref/source/dat/dlua/layout/geoelf_glyphs.lua index f211d31438fa..fa84d624f0ed 100644 --- a/crawl-ref/source/dat/dlua/layout/geoelf_glyphs.lua +++ b/crawl-ref/source/dat/dlua/layout/geoelf_glyphs.lua @@ -155,15 +155,15 @@ geoelf.glyphs.OUTLINE_SUBSTITUTIONS = -- choosing a random feature geoelf.glyphs.FEATURE_OPTIONS = - { [geoelf.glyphs.STATUE] = 2, - [geoelf.glyphs.FOUNTAIN] = 1 } + { {geoelf.glyphs.STATUE, 2}, + {geoelf.glyphs.FOUNTAIN, 1} } -- choosing a random plantlike thing geoelf.glyphs.PLANTLIKE_OPTIONS = - { [geoelf.glyphs.TREE] = 3, - [geoelf.glyphs.BUSH] = 1, - [geoelf.glyphs.PLANT] = 2, - [geoelf.glyphs.FUNGUS] = 4 } + { {geoelf.glyphs.TREE, 3}, + {geoelf.glyphs.BUSH, 1}, + {geoelf.glyphs.PLANT, 2}, + {geoelf.glyphs.FUNGUS, 4} } -- making things into glass if possible geoelf.glyphs.TO_GLASS = diff --git a/crawl-ref/source/dat/dlua/layout/geoelf_rooms.lua b/crawl-ref/source/dat/dlua/layout/geoelf_rooms.lua index 2cca8260696c..18e7f5ce18d6 100644 --- a/crawl-ref/source/dat/dlua/layout/geoelf_rooms.lua +++ b/crawl-ref/source/dat/dlua/layout/geoelf_rooms.lua @@ -168,63 +168,63 @@ geoelf.rooms.shape.CONNECTIONS = geoelf.rooms.shape.MIRRORINGS = { [geoelf.rooms.shape.SQUARE] = - { [geoelf.rooms.mirror.NONE] = 1, - [geoelf.rooms.mirror.X] = 1, - [geoelf.rooms.mirror.Y] = 1, - [geoelf.rooms.mirror.XY] = 1, - [geoelf.rooms.mirror.D] = 1, - [geoelf.rooms.mirror.DX] = 1, - [geoelf.rooms.mirror.DY] = 1, - [geoelf.rooms.mirror.DXY] = 1 }, + { {geoelf.rooms.mirror.NONE, 1}, -- why are these set up as weighted? + {geoelf.rooms.mirror.X, 1}, + {geoelf.rooms.mirror.Y, 1}, + {geoelf.rooms.mirror.XY, 1}, + {geoelf.rooms.mirror.D, 1}, + {geoelf.rooms.mirror.DX, 1}, + {geoelf.rooms.mirror.DY, 1}, + {geoelf.rooms.mirror.DXY, 1} }, [geoelf.rooms.shape.DIAMOND] = - { [geoelf.rooms.mirror.NONE] = 1, - [geoelf.rooms.mirror.X] = 1, - [geoelf.rooms.mirror.Y] = 1, - [geoelf.rooms.mirror.XY] = 1, - [geoelf.rooms.mirror.D] = 1, - [geoelf.rooms.mirror.DX] = 1, - [geoelf.rooms.mirror.DY] = 1, - [geoelf.rooms.mirror.DXY] = 1 }, + { {geoelf.rooms.mirror.NONE, 1}, + {geoelf.rooms.mirror.X, 1}, + {geoelf.rooms.mirror.Y, 1}, + {geoelf.rooms.mirror.XY, 1}, + {geoelf.rooms.mirror.D, 1}, + {geoelf.rooms.mirror.DX, 1}, + {geoelf.rooms.mirror.DY, 1}, + {geoelf.rooms.mirror.DXY, 1} }, [geoelf.rooms.shape.CROSS] = - { [geoelf.rooms.mirror.NONE] = 1, - [geoelf.rooms.mirror.X] = 1, - [geoelf.rooms.mirror.Y] = 1, - [geoelf.rooms.mirror.XY] = 1, - [geoelf.rooms.mirror.D] = 1, - [geoelf.rooms.mirror.DX] = 1, - [geoelf.rooms.mirror.DY] = 1, - [geoelf.rooms.mirror.DXY] = 1 }, + { {geoelf.rooms.mirror.NONE, 1}, + {geoelf.rooms.mirror.X, 1}, + {geoelf.rooms.mirror.Y, 1}, + {geoelf.rooms.mirror.XY, 1}, + {geoelf.rooms.mirror.D, 1}, + {geoelf.rooms.mirror.DX, 1}, + {geoelf.rooms.mirror.DY, 1}, + {geoelf.rooms.mirror.DXY, 1} }, [geoelf.rooms.shape.TRIANGLE_S] = - { [geoelf.rooms.mirror.D] = 1, - [geoelf.rooms.mirror.DX] = 1 }, + { {geoelf.rooms.mirror.D, 1}, + {geoelf.rooms.mirror.DX, 1} }, [geoelf.rooms.shape.TRIANGLE_N] = - { [geoelf.rooms.mirror.DY] = 1, - [geoelf.rooms.mirror.DXY] = 1 }, + { {geoelf.rooms.mirror.DY, 1}, + {geoelf.rooms.mirror.DXY, 1} }, [geoelf.rooms.shape.TRIANGLE_E] = - { [geoelf.rooms.mirror.NONE] = 1, - [geoelf.rooms.mirror.Y] = 1 }, + { {geoelf.rooms.mirror.NONE, 1}, + {geoelf.rooms.mirror.Y, 1} }, [geoelf.rooms.shape.TRIANGLE_W] = - { [geoelf.rooms.mirror.X] = 1, - [geoelf.rooms.mirror.XY] = 1 }, + { {geoelf.rooms.mirror.X, 1}, + {geoelf.rooms.mirror.XY, 1} }, [geoelf.rooms.shape.HEXAGON_NS] = - { [geoelf.rooms.mirror.D] = 1, - [geoelf.rooms.mirror.DX] = 1, - [geoelf.rooms.mirror.DY] = 1, - [geoelf.rooms.mirror.DXY] = 1 }, + { {geoelf.rooms.mirror.D, 1}, + {geoelf.rooms.mirror.DX, 1}, + {geoelf.rooms.mirror.DY, 1}, + {geoelf.rooms.mirror.DXY, 1} }, [geoelf.rooms.shape.HEXAGON_EW] = - { [geoelf.rooms.mirror.NONE] = 1, - [geoelf.rooms.mirror.X] = 1, - [geoelf.rooms.mirror.Y] = 1, - [geoelf.rooms.mirror.XY] = 1 }, + { {geoelf.rooms.mirror.NONE, 1}, + {geoelf.rooms.mirror.X, 1}, + {geoelf.rooms.mirror.Y, 1}, + {geoelf.rooms.mirror.XY, 1} }, [geoelf.rooms.shape.OCTAGON] = - { [geoelf.rooms.mirror.NONE] = 1, - [geoelf.rooms.mirror.X] = 1, - [geoelf.rooms.mirror.Y] = 1, - [geoelf.rooms.mirror.XY] = 1, - [geoelf.rooms.mirror.D] = 1, - [geoelf.rooms.mirror.DX] = 1, - [geoelf.rooms.mirror.DY] = 1, - [geoelf.rooms.mirror.DXY] = 1 } } + { {geoelf.rooms.mirror.NONE, 1}, + {geoelf.rooms.mirror.X, 1}, + {geoelf.rooms.mirror.Y, 1}, + {geoelf.rooms.mirror.XY, 1}, + {geoelf.rooms.mirror.D, 1}, + {geoelf.rooms.mirror.DX, 1}, + {geoelf.rooms.mirror.DY, 1}, + {geoelf.rooms.mirror.DXY, 1} } } @@ -324,9 +324,10 @@ function geoelf.rooms.draw (e, room_data, corridor_data, index, end -- draw the room - local mirror = crawl.random_element(geoelf.rooms.shape.MIRRORINGS[shape]) - local feature = crawl.random_element(geoelf.glyphs.FEATURE_OPTIONS) - local plantlike = crawl.random_element(geoelf.glyphs.PLANTLIKE_OPTIONS) + local mirror = util.random_choose_weighted( + geoelf.rooms.shape.MIRRORINGS[shape]) + local feature = util.random_choose_weighted(geoelf.glyphs.FEATURE_OPTIONS) + local plantlike = util.random_choose_weighted(geoelf.glyphs.PLANTLIKE_OPTIONS) if (geoelf.debug and fancy) then print(" Feature " .. feature .. " plantlike " .. plantlike) end diff --git a/crawl-ref/source/dat/dlua/layout/theme.lua b/crawl-ref/source/dat/dlua/layout/theme.lua index 5dd8d16a4fc3..2c510315933f 100644 --- a/crawl-ref/source/dat/dlua/layout/theme.lua +++ b/crawl-ref/source/dat/dlua/layout/theme.lua @@ -74,11 +74,11 @@ function theme.room_material(wall_type) return 'b' end - return crawl.random_element { - [wall_type] = 216, - ['c'] = 9, - ['x'] = 9, - ['v'] = 5 + return util.random_choose_weighted { + {wall_type, 216}, + {'c', 9}, + {'x', 9}, + {'v', 5} } end diff --git a/crawl-ref/source/dat/dlua/util.lua b/crawl-ref/source/dat/dlua/util.lua index e20bb1ee39fa..ef0f5dcdecfd 100644 --- a/crawl-ref/source/dat/dlua/util.lua +++ b/crawl-ref/source/dat/dlua/util.lua @@ -265,7 +265,7 @@ function util.contains(haystack, needle) end --- Pick a random element from a list (unweighted) --- @see crawl.random_element +-- @see util.random_choose_weighted function util.random_from(list) return list[ crawl.random2(#list) + 1 ] end @@ -328,6 +328,31 @@ function util.random_weighted_keys(weightfn, list, order) return chosen end +-- Given a list of pairs, where the second element of each pair is an integer +-- weight, randomly choose from the list. This *cannot* be reimplemented using +-- just a table, because iteration order through a table is indeterminate and +-- can mess with the random choice here (and we have found that this matters +-- in practice). That is, a table like {[a] = 1, [b] = 1}, with the exact same +-- rng state, could under some circumstances return either value. +-- +-- the implementation here is very similar to random_choose_weighted in +-- random.h. Someone clever could probably call that directly instead. +function util.random_choose_weighted(list) + local total = 0 + for i,k in ipairs(list) do + total = total + k[2] + end + local r = crawl.random2(total) + local sum = 0 + for i,k in ipairs(list) do + sum = sum + k[2] + if sum > r then + return k[1] + end + end + -- not reachable +end + --- Given a table of elements, choose a subset of size n without replacement. function util.random_subset(set, n) local result = {} diff --git a/crawl-ref/source/l-crawl.cc b/crawl-ref/source/l-crawl.cc index c7ff81f883b2..1edde2266d83 100644 --- a/crawl-ref/source/l-crawl.cc +++ b/crawl-ref/source/l-crawl.cc @@ -1187,67 +1187,6 @@ LUAWRAP(crawl_tutorial_skill, set_tutorial_skill(luaL_checkstring(ls, 1), luaL_c LUAWRAP(crawl_tutorial_hint, tutorial_init_hint(luaL_checkstring(ls, 1))) LUAWRAP(crawl_print_hint, print_hint(luaL_checkstring(ls, 1))) -/*** Choose a random element from a table. - * If passed an array, a random element is chosen from the array. If passed a - * table, the values should be numeric or convertible to numeric and give the - * weights for their corresponding keys. A value with no key will default to a - * weight of 1. A random key is then returned based on these weights. - * @tparam table in - * @return a random element from in. - * @function random_element -*/ -static int crawl_random_element(lua_State *ls) -{ - const int table_idx = 1; - const int value_idx = 2; - - if (lua_gettop(ls) == 0) - { - lua_pushnil(ls); - return 1; - } - - // Only the first arg does anything now. Maybe this should - // select from a variable number of table args? - lua_pop(ls, lua_gettop(ls) - 1); - - // Keep max value on the stack, as it could be any type of value. - lua_pushnil(ls); - int rollsize = 0; - - lua_pushnil(ls); - while (lua_next(ls, table_idx) != 0) - { - const int weight_idx = -1; - const int key_idx = -2; - - int this_weight = lua_isnil(ls, weight_idx) ? - 1 : (int)lua_tonumber(ls, weight_idx); - - if (rollsize > 0) - { - rollsize += this_weight; - if (x_chance_in_y(this_weight, rollsize)) - { - lua_pushvalue(ls, key_idx); - lua_replace(ls, value_idx); - } - } - else - { - lua_pushvalue(ls, key_idx); - lua_replace(ls, value_idx); - rollsize = this_weight; - } - - lua_pop(ls, 1); - } - - lua_pushvalue(ls, value_idx); - - return 1; -} - /*** Lua error trace a call * Attempts to call-trace a lua function that is producing an error. * Returns normally if the function runs normally, otherwise sends @@ -1411,7 +1350,6 @@ static const struct luaL_reg crawl_clib[] = { "roll_dice", crawl_roll_dice }, { "x_chance_in_y", crawl_x_chance_in_y }, { "random_range", crawl_random_range }, - { "random_element", crawl_random_element }, { "div_rand_round", crawl_div_rand_round }, { "random_real", crawl_random_real }, { "worley", crawl_worley }, From 542fcb7d11b2d39f43b8de148eee4e4332625302 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 31 Jan 2019 08:22:28 -0500 Subject: [PATCH 015/864] Don't use ui_random for bones file choice --- crawl-ref/source/files.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 998fffb0de1b..187292f006a6 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1939,7 +1939,7 @@ static string _find_ghost_file() vector bonefiles = _list_bones(); if (bonefiles.empty()) return ""; - return bonefiles[ui_random(bonefiles.size())]; + return bonefiles[random2(bonefiles.size())]; } static string _old_bones_filename(string ghost_filename, const save_version &v) From e63ed0601461568aaf9abab1a4a3c1c5c560d791 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 31 Jan 2019 08:25:22 -0500 Subject: [PATCH 016/864] More RNG initialization improvements Better reset for tests, initialize item descriptions with levelgen rng. Also add a bit more fulldebug spam. --- crawl-ref/source/dungeon.cc | 12 ++++++++++++ crawl-ref/source/l-debug.cc | 2 -- crawl-ref/source/ng-setup.cc | 3 +-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 284bec4364cd..d88a651580a0 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -639,6 +639,12 @@ void dgn_flush_map_memory() { you.uniq_map_tags.clear(); you.uniq_map_names.clear(); + you.unique_creatures.reset(); + you.unique_items.init(UNIQ_NOT_EXISTS); + you.vault_list.clear(); + you.branches_left.reset(); + you.branch_stairs.init(0); + you.octopus_king_rings = 0x00; } static void _dgn_load_colour_grid() @@ -3808,7 +3814,13 @@ static void _randomly_place_item(int item) destroy_item(item); } else + { + dprf(DIAG_DNGN, "builder placing %s (%s) at %d,%d", + mitm[item].name(DESC_PLAIN).c_str(), + mitm[item].name(DESC_PLAIN, false, true).c_str(), + itempos.x, itempos.y); move_item_to_grid(&item, itempos); + } } /** diff --git a/crawl-ref/source/l-debug.cc b/crawl-ref/source/l-debug.cc index 300bb1ce2316..c7430996553a 100644 --- a/crawl-ref/source/l-debug.cc +++ b/crawl-ref/source/l-debug.cc @@ -93,8 +93,6 @@ LUAFN(debug_flush_map_memory) { dgn_flush_map_memory(); init_level_connectivity(); - you.unique_creatures.reset(); - you.unique_items.init(UNIQ_NOT_EXISTS); return 0; } diff --git a/crawl-ref/source/ng-setup.cc b/crawl-ref/source/ng-setup.cc index de46a3de8223..f712765c0b25 100644 --- a/crawl-ref/source/ng-setup.cc +++ b/crawl-ref/source/ng-setup.cc @@ -458,6 +458,7 @@ void initial_dungeon_setup() initialise_branch_depths(); initialise_temples(); init_level_connectivity(); + initialise_item_descriptions(); } static void _setup_generic(const newgame_def& ng) @@ -523,8 +524,6 @@ static void _setup_generic(const newgame_def& ng) if (you.char_class == JOB_WANDERER) memorise_wanderer_spell(); - initialise_item_descriptions(); - // A first pass to link the items properly. for (int i = 0; i < ENDOFPACK; ++i) { From 0a484b665a293b32f6f78463c06be5312cf78d5d Mon Sep 17 00:00:00 2001 From: gammafunk Date: Thu, 31 Jan 2019 10:17:13 -0600 Subject: [PATCH 017/864] Tweak the no-teleport message for Gauntlets Add a little bit more flavor in the message. The old one was mostly copied from Dungeon Sprint, which disables teleports as part of the game mode itself. --- crawl-ref/source/player.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index d234ca3f409c..b570d17bbf96 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -6338,7 +6338,10 @@ string player::no_tele_reason(bool calc_unid, bool blinking) const if (crawl_state.game_is_sprint()) return "Long-range teleportation is disallowed in Dungeon Sprint."; else if (player_in_branch(BRANCH_GAUNTLET)) - return "Long-range teleportation does not work in a Gauntlet."; + { + return "A magic seal in the Gauntlet prevents long-range " + "teleports."; + } } if (stasis()) From 2c779b6b6d141ccecd750a0e88b59e27fb78d04a Mon Sep 17 00:00:00 2001 From: gammafunk Date: Thu, 31 Jan 2019 10:20:15 -0600 Subject: [PATCH 018/864] Prevent use of Passage of Golubria in Gauntlets (Yermak) Like use of teleport, Golubria passages can bypass the Gauntlet's usual one-way structure. Players can create a passage in the starting area, enter and quickly loot a chamber, then return back to start to gain access to other areas. This commit prevents casting the spell in Gauntlets entirely. --- crawl-ref/source/spl-transloc.cc | 7 +++++++ crawl-ref/source/spl-util.cc | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/crawl-ref/source/spl-transloc.cc b/crawl-ref/source/spl-transloc.cc index 598c53f6870b..e8d14b2e61a4 100644 --- a/crawl-ref/source/spl-transloc.cc +++ b/crawl-ref/source/spl-transloc.cc @@ -918,6 +918,13 @@ spret cast_golubrias_passage(const coord_def& where, bool fail) return spret::abort; } + if (player_in_branch(BRANCH_GAUNTLET)) + { + mprf(MSGCH_ORB, "A magic seal in the Gauntlet prevents you from " + "opening a passage!"); + return spret::abort; + } + // randomize position a bit to make it not as useful to use on monsters // chasing you, as well as to not give away hidden trap positions int tries = 0; diff --git a/crawl-ref/source/spl-util.cc b/crawl-ref/source/spl-util.cc index cae297f388eb..97a54fe76275 100644 --- a/crawl-ref/source/spl-util.cc +++ b/crawl-ref/source/spl-util.cc @@ -1294,6 +1294,11 @@ string spell_uselessness_reason(spell_type spell, bool temp, bool prevent, case SPELL_GOLUBRIAS_PASSAGE: if (orb_limits_translocation(temp)) return "the Orb prevents this spell from working."; + else if (temp && player_in_branch(BRANCH_GAUNTLET)) + { + return "a magic seal in the Gauntlet prevents this spell " + "from working."; + } default: break; From cd3d6b93d0892280aff5568c8d438ec9e6386db5 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Thu, 31 Jan 2019 13:37:22 -0600 Subject: [PATCH 019/864] Update documentation of a function --- crawl-ref/source/orb.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/orb.cc b/crawl-ref/source/orb.cc index 6e895e0ca094..1d8a430ec18b 100644 --- a/crawl-ref/source/orb.cc +++ b/crawl-ref/source/orb.cc @@ -77,7 +77,10 @@ void orb_pickup_noise(const coord_def& where, int loudness, const char* msg, con /** * Is the Orb interfering with translocations? - * @return True if the player is in Zot or is carrying the Orb. + * @param temp If true, consider temporary conditions. + * @return True if the player is carrying the Orb or, if we're considering + * temporary conditions, if the player is in Zot. Returns false + * otherwise. */ bool orb_limits_translocation(bool temp) { From 0b81bb8f681ffe2237f8495824219d0fca51736d Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 31 Jan 2019 17:28:14 -0500 Subject: [PATCH 020/864] Reset temple vault tags when doing temple setup This load() call was just adding in new tags to the previously loaded list each time a game was started, leading to seed instability both in tests and when a new game was started without exiting the program for temple vaults with variable numbers of altars. (Because the length of the list of tags changed, which leads to different behavior of the random draw as the list gets longer even for the same seed.) Possibly tags should be treated as a `set` or something, rather than just a raw string that is split on demand? --- crawl-ref/source/dungeon.cc | 16 ++++++++++++++++ crawl-ref/source/ng-init.cc | 3 ++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index d88a651580a0..b8165cbb9fee 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -637,6 +637,15 @@ void level_clear_vault_memory() void dgn_flush_map_memory() { + // it's probably better in general to just reset `you`. But that's not so + // convenient for lua tests, who are the only user of this function. + // This leaves some state uninitialized, and probably should be immediately + // followed by a call to `initial_dungeon_setup` and something that moves + // the player to a level or regenerates a level. + you.runes.reset(); + you.obtainable_runes = 15; + you.zigs_completed = 0; + you.zig_max = 0; you.uniq_map_tags.clear(); you.uniq_map_names.clear(); you.unique_creatures.reset(); @@ -645,6 +654,13 @@ void dgn_flush_map_memory() you.branches_left.reset(); you.branch_stairs.init(0); you.octopus_king_rings = 0x00; + you.item_description.init(255); + you.exploration = 0; + // would it be safe to just clear you.props? + you.props.erase(TEMPLE_SIZE_KEY); + you.props.erase(TEMPLE_MAP_KEY); + you.props.erase(OVERFLOW_TEMPLES_KEY); + you.props.erase(TEMPLE_GODS_KEY); } static void _dgn_load_colour_grid() diff --git a/crawl-ref/source/ng-init.cc b/crawl-ref/source/ng-init.cc index 81d7add81090..a34803c65a37 100644 --- a/crawl-ref/source/ng-init.cc +++ b/crawl-ref/source/ng-init.cc @@ -167,6 +167,7 @@ void initialise_temples() // Without all this find_glyph() returns 0. string err; + main_temple->tags.clear(); // anything else that needs to be cleared? main_temple->load(); main_temple->reinit(); err = main_temple->run_lua(true); @@ -180,7 +181,7 @@ void initialise_temples() continue; } - main_temple->fixup(); + main_temple->fixup(); err = main_temple->resolve(); if (!err.empty()) From 05a21ba7acd5a87080843e79e5e4596306f18505 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 31 Jan 2019 21:49:18 -0500 Subject: [PATCH 021/864] Various fixes for more stable lua iteration order I ended up auditing every instance of `pairs`; these are the ones that potentially interact with dungeon generation / randomness. Basically, the use of `pairs` is now dispreferred for anything like the code being touched here. I added a few utility functions for dealing with weight tables in various ways (would have made my life easier to add these before...) --- crawl-ref/source/dat/des/builder/rooms.des | 31 +++++++------------ .../source/dat/des/variable/d_encompass.des | 1 + crawl-ref/source/dat/dlua/dungeon.lua | 4 +-- crawl-ref/source/dat/dlua/ghost.lua | 10 ++++-- crawl-ref/source/dat/dlua/layout/zonify.lua | 9 ++++-- crawl-ref/source/dat/dlua/util.lua | 25 +++++++++++++-- crawl-ref/source/dat/dlua/vault.lua | 2 +- 7 files changed, 54 insertions(+), 28 deletions(-) diff --git a/crawl-ref/source/dat/des/builder/rooms.des b/crawl-ref/source/dat/des/builder/rooms.des index c73920f13ee8..25738db30e17 100644 --- a/crawl-ref/source/dat/des/builder/rooms.des +++ b/crawl-ref/source/dat/des/builder/rooms.des @@ -331,31 +331,24 @@ function sroom_demon_pit(e) local weight_d = 5 + runes local tier_twos = { - hell_beast = weight_a, - green_death = weight_a, - reaper = weight_b, - lorocyproca = weight_b, - balrug = weight_c, - blizzard_demon = weight_c, - hellion = weight_d, - tormentor = weight_d, - cacodemon = 5, + {"hell_beast", weight_a}, + {"green_death", weight_a}, + {"reaper", weight_b}, + {"lorocyproca", weight_b}, + {"balrug", weight_c}, + {"blizzard_demon", weight_c}, + {"hellion", weight_d}, + {"tormentor", weight_d}, + {"cacodemon", 5}, } -- Choose three demons as weighted above, -- and don't choose the same one twice. local mons = {} for mon_num=1,3 do - local mon = nil - local cweight = 0 - for k,wt in pairs(tier_twos) do - cweight = cweight + wt - if crawl.random2(cweight) < wt then - mon = k - end - end - mons[mon_num] = mon - tier_twos[mon] = 0 + local chosen = util.random_choose_weighted_i(tier_twos) + mons[mon_num] = tier_twos[chosen][1] + tier_twos[chosen][2] = 0 end lord_mon = "brimstone fiend / ice fiend / tzitzimitl / " .. diff --git a/crawl-ref/source/dat/des/variable/d_encompass.des b/crawl-ref/source/dat/des/variable/d_encompass.des index 7fd73d2e8fd4..a0f09d3aa439 100644 --- a/crawl-ref/source/dat/des/variable/d_encompass.des +++ b/crawl-ref/source/dat/des/variable/d_encompass.des @@ -158,6 +158,7 @@ KMONS: t = draconian knight / draconian scorcher / draconian annihilator : end : end : end +: table.sort(kmonsters) : kmons("s = " .. table.concat(kmonsters, " / ")) KITEM: ? = any ring randart w:390 / ring_of_the_octopus_king KITEM: ! = ring of slaying / ring of wizardry / any good_item ring no_uniq w:75 diff --git a/crawl-ref/source/dat/dlua/dungeon.lua b/crawl-ref/source/dat/dlua/dungeon.lua index 0a659b139629..0291d6634555 100644 --- a/crawl-ref/source/dat/dlua/dungeon.lua +++ b/crawl-ref/source/dat/dlua/dungeon.lua @@ -250,7 +250,7 @@ function dgn_run_map(...) error("No current map?") end local env = dgn_map_meta_wrap(g_dgn_curr_map, dgn) - for _, map_chunk_function in pairs(map_chunk_functions) do + for _, map_chunk_function in ipairs(map_chunk_functions) do if map_chunk_function then ret = setfenv(map_chunk_function, env)() end @@ -320,7 +320,7 @@ end function dgn.fnum_map(map) local fnmap = { } - for k, v in pairs(map) do + for k, v in pairs(map) do -- arbitrary iter order should be ok here fnmap[dgn.fnum(k)] = dgn.fnum(v) end return fnmap diff --git a/crawl-ref/source/dat/dlua/ghost.lua b/crawl-ref/source/dat/dlua/ghost.lua index 368002285622..a60ba555771f 100644 --- a/crawl-ref/source/dat/dlua/ghost.lua +++ b/crawl-ref/source/dat/dlua/ghost.lua @@ -51,13 +51,19 @@ function random_item_def(items, egos, args, separator) args = args ~= nil and " " .. args or "" separator = separator ~= nil and separator or '/' local item_def + items_list = util.sorted_weight_table(items) - for iname, iweight in pairs(items) do + for i, item_pair in ipairs(items_list) do + iname = item_pair[1] + iweight = item_pair[2] -- If we have egos, define an item spec with all item+ego -- combinations, each with weight scaled by item rarity and ego -- rarity. if egos ~= nil then - for ename, eweight in pairs(egos) do + egos_list = util.sorted_weight_table(egos) + for j, ego_pair in ipairs(egos_list) do + ename = ego_pair[1] + eweight = ego_pair[2] if (not iname:find("demon") or ename ~= "holy_wrath") and (not iname:find("quick blade") or ename ~= "speed") then def = iname .. args .. " ego:" .. ename .. " w:" .. diff --git a/crawl-ref/source/dat/dlua/layout/zonify.lua b/crawl-ref/source/dat/dlua/layout/zonify.lua index 0926549399c0..1cb53b0e1305 100644 --- a/crawl-ref/source/dat/dlua/layout/zonify.lua +++ b/crawl-ref/source/dat/dlua/layout/zonify.lua @@ -82,7 +82,11 @@ function zonify.fill_smallest_zones(zonemap, num_to_keep, fgroup, ffill, min_zon largest[n].size = -999999 end - for name,group in pairs(zonemap) do + local sorted_zones = {} + for name,group in pairs(zonemap) do table.insert(sorted_zones, name) end + table.sort(sorted_zones) + for i, name in ipairs(sorted_zones) do + group = zonemap[name] if type(fgroup) == "function" and fgroup(group) or name==fgroup then for i,zone in ipairs(group) do zsize = #(zone.cells) @@ -115,7 +119,8 @@ function zonify.fill_smallest_zones(zonemap, num_to_keep, fgroup, ffill, min_zon return false end - for name,group in pairs(zonemap) do + for i,name in ipairs(sorted_zones) do + group = zonemap[name] if type(fgroup) == "function" and fgroup(group) or name==fgroup then for i,zone in ipairs(group) do local replace = true diff --git a/crawl-ref/source/dat/dlua/util.lua b/crawl-ref/source/dat/dlua/util.lua index ef0f5dcdecfd..2ac71198d36f 100644 --- a/crawl-ref/source/dat/dlua/util.lua +++ b/crawl-ref/source/dat/dlua/util.lua @@ -328,6 +328,23 @@ function util.random_weighted_keys(weightfn, list, order) return chosen end +-- convert a table of key-to-weight mappings into a table of key-weight pairs, +-- as long as the keys are sortable. +function util.sorted_weight_table(t, sort) + local keys = { } + for k, v in pairs(t) do table.insert(keys, k) end + if sort == nil then + table.sort(keys) + else + table.sort(keys, sort) + end + local res = { } + for i, k in ipairs(keys) do + table.insert(res, { k, t[k] }) + end + return res +end + -- Given a list of pairs, where the second element of each pair is an integer -- weight, randomly choose from the list. This *cannot* be reimplemented using -- just a table, because iteration order through a table is indeterminate and @@ -337,7 +354,7 @@ end -- -- the implementation here is very similar to random_choose_weighted in -- random.h. Someone clever could probably call that directly instead. -function util.random_choose_weighted(list) +function util.random_choose_weighted_i(list) local total = 0 for i,k in ipairs(list) do total = total + k[2] @@ -347,12 +364,16 @@ function util.random_choose_weighted(list) for i,k in ipairs(list) do sum = sum + k[2] if sum > r then - return k[1] + return i end end -- not reachable end +function util.random_choose_weighted(list) + return list[util.random_choose_weighted_i(list)][1] +end + --- Given a table of elements, choose a subset of size n without replacement. function util.random_subset(set, n) local result = {} diff --git a/crawl-ref/source/dat/dlua/vault.lua b/crawl-ref/source/dat/dlua/vault.lua index ee04c90a3b31..c66a78f20479 100644 --- a/crawl-ref/source/dat/dlua/vault.lua +++ b/crawl-ref/source/dat/dlua/vault.lua @@ -89,7 +89,7 @@ end function hell_branches_remaining() local hell_branches = { "Geh", "Coc", "Dis", "Tar" } local ret = #hell_branches - for _, branch in pairs(hell_branches) do + for _, branch in ipairs(hell_branches) do if travel.find_deepest_explored(branch) == 7 then ret = ret - 1 end From e4bce670a7946a52377e51162b58fb665a5490f2 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 31 Jan 2019 23:01:03 -0500 Subject: [PATCH 022/864] Allow shafts in tests I'm not sure why these were disallowed, but it was 8 years ago and didn't break anything for me. Plus, disallowing this messes up seed testing. --- crawl-ref/source/traps.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crawl-ref/source/traps.cc b/crawl-ref/source/traps.cc index cfd2c3c4f889..983d795c2b4d 100644 --- a/crawl-ref/source/traps.cc +++ b/crawl-ref/source/traps.cc @@ -1287,11 +1287,8 @@ bool is_valid_shaft_level() // or generated, so should not depend on properties of the level itself, // but only on its level_id. const level_id place = level_id::current(); - if (crawl_state.test - || crawl_state.game_is_sprint()) - { + if (crawl_state.game_is_sprint()) return false; - } if (!is_connected_branch(place)) return false; From 2a401c07d103d99e7fafbb13a2588d3eef9ddddf Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 31 Jan 2019 23:40:22 -0500 Subject: [PATCH 023/864] Clear more global state for tests --- crawl-ref/source/dungeon.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index b8165cbb9fee..1b2009efc5d8 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -661,6 +661,7 @@ void dgn_flush_map_memory() you.props.erase(TEMPLE_MAP_KEY); you.props.erase(OVERFLOW_TEMPLES_KEY); you.props.erase(TEMPLE_GODS_KEY); + dlua.callfn("dgn_clear_data", ""); } static void _dgn_load_colour_grid() From 193e08148b4d5be22cbefb48c63337e2bee9ee7b Mon Sep 17 00:00:00 2001 From: advil Date: Fri, 1 Feb 2019 00:20:54 -0500 Subject: [PATCH 024/864] Randomness fix for swamp / pools --- crawl-ref/source/l-dgnbld.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/source/l-dgnbld.cc b/crawl-ref/source/l-dgnbld.cc index 1f170ff67904..160579df50e5 100644 --- a/crawl-ref/source/l-dgnbld.cc +++ b/crawl-ref/source/l-dgnbld.cc @@ -298,6 +298,7 @@ static vector _pool_fill_glyphs_from_table(lua_State *ls, // We might have not got anything, if so, use floor if (fill_glyphs.size() == 0) fill_glyphs.push_back('.'); + sort(fill_glyphs.begin(), fill_glyphs.end()); return fill_glyphs; } From 12d111dd0df58da8b30f98c1e2b2e2f7984aa860 Mon Sep 17 00:00:00 2001 From: advil Date: Fri, 1 Feb 2019 00:32:47 -0500 Subject: [PATCH 025/864] Fix some typos and lua mistakes --- crawl-ref/source/dat/des/builder/layout_geoelf_castle.des | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/dat/des/builder/layout_geoelf_castle.des b/crawl-ref/source/dat/des/builder/layout_geoelf_castle.des index 6b2dd7a062ca..597c26dd1835 100644 --- a/crawl-ref/source/dat/des/builder/layout_geoelf_castle.des +++ b/crawl-ref/source/dat/des/builder/layout_geoelf_castle.des @@ -1001,12 +1001,12 @@ TAGS: no_rotate no_vmirror no_hmirror -- draw the turrets local turret_center_weights = {} for i,p in ipairs(geoelf.glyphs.PLANTLIKE_OPTIONS) do - turrent_center_weights[#turret_center_weights + 1] = p + table.insert(turret_center_weights, p) end for i,p in ipairs(geoelf.glyphs.FEATURE_OPTIONS) do - turrent_center_weights[#turret_center_weights + 1] = {p[0], p[1] * 5} + table.insert(turret_center_weights, { p[1], p[2] * 5 }) end - turrent_center_weights[#turret_center_weights + 1] = {INSIDE_GLYPH, 15} + table.insert(turret_center_weights, { INSIDE_GLYPH, 15 }) local turret_center = util.random_choose_weighted(turret_center_weights) From 8489be958e629d4499452aafbccff87adf825562 Mon Sep 17 00:00:00 2001 From: advil Date: Fri, 1 Feb 2019 00:36:03 -0500 Subject: [PATCH 026/864] Add a new lua test for seed stability May need some adjusting so it doesn't add too much time to the travis build by default. It isn't impossible that this test will fail... --- crawl-ref/source/test/vault_catalog.lua | 126 ++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 crawl-ref/source/test/vault_catalog.lua diff --git a/crawl-ref/source/test/vault_catalog.lua b/crawl-ref/source/test/vault_catalog.lua new file mode 100644 index 000000000000..7cf58fa0d5b3 --- /dev/null +++ b/crawl-ref/source/test/vault_catalog.lua @@ -0,0 +1,126 @@ +-- this test checks for the stability of vault generation given various +-- particular seeds. It will print out a list of all vaults for one particular +-- seed, which can be useful for comparing across devices, and test stability +-- of seeds by rerunning the catalog for various seeds. The default settings +-- are relatively moderate in terms of time/CPU requirements for the sake of +-- travis CI. +-- +-- this test messes with RNG state! It leaves the RNG with a clean seed 1, +-- but if you are expecting deterministic test behavior, take that into +-- account. + +local catalog_seed = 1 -- seed to print out +local starting_seed = 2 -- fixed seed to start with +local fixed_seeds = 2 -- how many fixed seeds to run? +local per_seed_iters = 1 -- how many stability tests to run per seed +local rand_seeds = 2 -- how many random seeds to run + +-- matches pregeneration order +local generation_order = { + "D:1", + "D:2", "D:3", "D:4", "D:5", "D:6", "D:7", "D:8", "D:9", + "D:10", "D:11", "D:12", "D:13", "D:14", "D:15", + "Temple", + "Lair:1", "Lair:2", "Lair:3", "Lair:4", "Lair:5", "Lair:6", + "Orc:1", "Orc:2", + "Spider:1", "Spider:2", "Spider:3", "Spider:4", + "Snake:1", "Snake:2", "Snake:3", "Snake:4", + "Shoals:1", "Shoals:2", "Shoals:3", "Shoals:4", + "Swamp:1", "Swamp:2", "Swamp:3", "Swamp:4", + "Vaults:1", "Vaults:2", "Vaults:3", "Vaults:4", "Vaults:5", + "Crypt:1", "Crypt:2", "Crypt:3", + "Depths:1", "Depths:2", "Depths:3", "Depths:4", "Depths:5", + "Hell", + "Elf:1", "Elf:2", "Elf:3", + "Zot:1", "Zot:2", "Zot:3", "Zot:4", "Zot:5", + "Slime:1", "Slime:2", "Slime:3", "Slime:4", "Slime:5", + "Tomb:1", "Tomb:2", "Tomb:3", + } + -- pregen continues: tartarus, cocytus, dis, geh + +-- want to exercise these a bit +local generation_order_extended = { + "D:1", + "Tar:1", "Tar:2", "Tar:3", "Tar:4", "Tar:5", "Tar:6", "Tar:7", + "Coc:1", "Coc:2", "Coc:3", "Coc:4", "Coc:5", "Coc:6", "Coc:7", + "Dis:1", "Dis:2", "Dis:3", "Dis:4", "Dis:5", "Dis:6", "Dis:7", + "Pan", "Pan", "Pan", "Pan", "Pan", "Pan", "Pan" +} + +-- a bit redundant with mapstat? but simpler... +function catalog_dungeon_vaults(level_order, silent) + local result = {} + debug.flush_map_memory() + debug.dungeon_setup() + for i,lvl in ipairs(level_order) do + if (dgn.br_exists(string.match(lvl, "[^:]+"))) then + debug.goto_place(lvl) + debug.generate_level() + result[lvl] = debug.vault_names() + if (not silent) then + crawl.stderr(lvl .. " vaults are: ") + crawl.stderr(" " .. result[lvl]) + end + end + end + return result +end + +function compare_catalogs(order, run1, run2, seed) + local diverge = false + -- stop at the first divergence by generation order. Everything after that + -- is likely to be a mess with very little signal. + for i,lvl in ipairs(order) do + if run1[lvl] == nil and run2[lvl] ~= nil then + crawl.stderr("Run 1 is missing " .. lvl .. "!") + elseif run2[lvl] == nil and run1[lvl] ~= nil then + crawl.stderr("Run 2 is missing " .. lvl .. "!") + elseif run1[lvl] ~= run2[lvl] then + crawl.stderr("Runs diverge for seed " .. seed .. " on level " .. lvl .. "!") + crawl.stderr("Run 1: " .. run1[lvl]) + crawl.stderr("Run 2: " .. run2[lvl]) + end + assert(run1[lvl] == run2[lvl]) + end +end + +function test_seed(seed, iters, order, quiet) + debug.reset_rng(seed) + if quiet then + crawl.stderr(".") + else + crawl.stderr("Vault catalog for seed " .. seed .. ":") + end + run1 = catalog_dungeon_vaults(order, quiet) + + if not quiet then + crawl.stderr("....now testing vault generation stability for seed " ..seed.. ".") + end + + for i = 1,iters do + crawl.stderr(".") + debug.reset_rng(seed) + run2 = catalog_dungeon_vaults(order, true) + compare_catalogs(order, run1, run2, seed) + end +end + +test_seed(catalog_seed, per_seed_iters, generation_order, false) +-- just do a quick check of hell / pan stability +test_seed(catalog_seed, per_seed_iters, generation_order_extended, true) + +for i=starting_seed, starting_seed + fixed_seeds - 1 do + crawl.stderr("Testing seed " .. i .. ".") + test_seed(i, per_seed_iters, generation_order, true) +end + +if rand_seeds > 0 then + crawl.stderr("Testing " .. rand_seeds .. " random seed(s).") +end +for i=1,rand_seeds do + -- intentional use of non-crawl random(). random doesn't seem to accept + -- anything bigger than 32 bits for the range. + rand_seed = math.random(0x7FFFFFFF) + crawl.stderr("Testing random seed " .. rand_seed .. ".") + test_seed(rand_seed, per_seed_iters, generation_order, true) +end From 4429137cf8f27244d6ffbe69194133c582eb9e4a Mon Sep 17 00:00:00 2001 From: advil Date: Fri, 1 Feb 2019 09:53:28 -0500 Subject: [PATCH 027/864] Fix potential iteration order issue for autofight This is unrelated to my current randomization woes, but something I noticed while auditing lua/crawl interactions for iter order issues. The iteration order for lua_next is *not* in general guaranteed, even if the table is an array, and what I have noticed is that eventually, in a long execution session, it will start diverging. So this may have been the source of some of our more obscure reported autofight bugs. I'm not sure if this solution using `map` is absolutely the best way to deal with it; lua 5.3 has much better support for doing ipairs-style iteration in C than lua 5.1, and this was the easiest fix without me actually figuring out how that's supposed to work in lua 5.1 (which is a bit tricky from everything I've read). --- crawl-ref/source/l-crawl.cc | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/l-crawl.cc b/crawl-ref/source/l-crawl.cc index 1edde2266d83..353b9bc76302 100644 --- a/crawl-ref/source/l-crawl.cc +++ b/crawl-ref/source/l-crawl.cc @@ -466,17 +466,22 @@ static int crawl_do_commands(lua_State *ls) luaL_argerror(ls, 1, "Must be an array"); return 0; } - vector commands; + map command_map; // ordered by key lua_pushnil(ls); - while (lua_next(ls, 1)) + while (lua_next(ls, 1)) // in general, no guaranteed order for this { if (!lua_isstring(ls, -1)) { luaL_argerror(ls, 1, "Table contains non-string"); return 0; } - commands.push_back(lua_tostring(ls, -1)); + if (!lua_isnumber(ls, -2)) + { + luaL_argerror(ls, 1, "Must be an array"); + return 0; + } + command_map[lua_tonumber(ls, -2)] = lua_tostring(ls, -1); lua_pop(ls, 1); } @@ -484,8 +489,9 @@ static int crawl_do_commands(lua_State *ls) command_type firstcmd = CMD_NO_CMD; deque cmd_seq; - for (const auto& command : commands) + for (const auto& pair : command_map) { + const auto& command = pair.second; command_type cmd = name_to_command(command); if (cmd == CMD_NO_CMD) { From ca774cb5d5d2dfdd713158c460b042527ea0da7d Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Fri, 1 Feb 2019 14:08:45 -0500 Subject: [PATCH 028/864] Give a more helpful message for 'G>' at branch end (3734) --- crawl-ref/source/travel.cc | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc index 7e4c865dfe5d..76a9a8509364 100644 --- a/crawl-ref/source/travel.cc +++ b/crawl-ref/source/travel.cc @@ -2509,11 +2509,19 @@ static void _start_translevel_travel() // Update information for this level. travel_cache.get_level_info(level_id::current()).update(); - if (level_id::current() == level_target.id - && (level_target.pos.x == -1 || level_target.pos == you.pos())) + if (level_id::current() == level_target.id) { - mpr("You're already here!"); - return ; + if (level_target.pos.x == -1 && + level_target.id.depth == branches[level_target.id.branch].numlevels) + { + mpr("You're already at the bottom of this branch!"); + return; + } + else if (level_target.pos.x == -1 || level_target.pos == you.pos()) + { + mpr("You're already here!"); + return; + } } #ifdef DEBUG_TRAVEL From 788b6e38277a5d956846453a6d3c1b69607659d7 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Fri, 1 Feb 2019 21:01:51 -0500 Subject: [PATCH 029/864] Extend Fedhas' protection to non-beam spells (11310) Fedhas now protects plants from LOS damaging spells that don't use beams, as well as static discharge and irradiate. Additionally, attack prompts have been adjusted to account for Fedhas' plant protection. Finally, Fedhas prevents shatter from destroying trees. "Fire-through" is not a completely coherent notion for player spells, these inconsistencies were not always accompanied by a prompt, or had an erroneous prompt. Hopefully this change will clarify the situation. --- crawl-ref/source/melee-attack.cc | 8 +++-- crawl-ref/source/spl-damage.cc | 55 ++++++++++++++++++++++++++++---- 2 files changed, 54 insertions(+), 9 deletions(-) diff --git a/crawl-ref/source/melee-attack.cc b/crawl-ref/source/melee-attack.cc index 90a6f7d6b406..6d2fc44bc307 100644 --- a/crawl-ref/source/melee-attack.cc +++ b/crawl-ref/source/melee-attack.cc @@ -134,8 +134,12 @@ bool melee_attack::handle_phase_attempted() { targeter_los hitfunc(&you, LOS_NO_TRANS); - if (stop_attack_prompt(hitfunc, "attack", nullptr, nullptr, - defender->as_monster())) + if (stop_attack_prompt(hitfunc, "attack", + [](const actor *act) + { + return !(you.deity() == GOD_FEDHAS + && fedhas_protects(*act->as_monster())); + }, nullptr, defender->as_monster())) { cancel_attack = true; return false; diff --git a/crawl-ref/source/spl-damage.cc b/crawl-ref/source/spl-damage.cc index 9091cc8d30df..2f4ef8840c40 100644 --- a/crawl-ref/source/spl-damage.cc +++ b/crawl-ref/source/spl-damage.cc @@ -40,6 +40,7 @@ #include "mutation.h" #include "ouch.h" #include "prompt.h" +#include "religion.h" #include "shout.h" #include "spl-summoning.h" #include "spl-util.h" @@ -359,6 +360,12 @@ static void _player_hurt_monster(monster &mon, int damage, beam_type flavour, if (is_sanctuary(you.pos()) || is_sanctuary(mon.pos())) remove_sanctuary(true); + if (god_conducts && you.deity() == GOD_FEDHAS && fedhas_neutralises(mon)) + { + simple_god_message(" protects your plant from harm.", GOD_FEDHAS); + return; + } + god_conduct_trigger conducts[3]; if (god_conducts) set_attack_conducts(conducts, mon, you.can_see(mon)); @@ -546,7 +553,9 @@ static spret _cast_los_attack_spell(spell_type spell, int pow, verb = "frozen"; prompt_verb = "refrigerate"; vulnerable = [](const actor *caster, const actor *act) { - return act->is_player() || act->res_cold() < 3; + return act->is_player() || act->res_cold() < 3 + && !(caster->deity() == GOD_FEDHAS + && fedhas_protects(*act->as_monster())); }; break; @@ -569,7 +578,9 @@ static spret _cast_los_attack_spell(spell_type spell, int pow, verb = "blasted"; // prompt_verb = "sing" The singing sword prompts in melee-attack vulnerable = [](const actor *caster, const actor *act) { - return act != caster; + return act != caster + && !(caster->deity() == GOD_FEDHAS + && fedhas_protects(*act->as_monster())); }; break; @@ -983,15 +994,15 @@ static int _shatter_walls(coord_def where, int pow, actor *agent) break; } + if (agent->deity() == GOD_FEDHAS && feat_is_tree(grid)) + return 0; + if (x_chance_in_y(chance, 100)) { noisy(spell_effect_noise(SPELL_SHATTER), where); destroy_wall(where); - if (agent->is_player() && feat_is_tree(grid)) - did_god_conduct(DID_KILL_PLANT, 1); - return 1; } @@ -1214,6 +1225,9 @@ static bool _irradiate_is_safe() if (!mon) continue; + if (you.deity() == GOD_FEDHAS && fedhas_protects(*mon)) + continue; + if (stop_attack_prompt(mon, false, you.pos())) return false; } @@ -1243,6 +1257,15 @@ static int _irradiate_cell(coord_def where, int pow, actor *agent) attack_strength_punctuation(dam).c_str()); dprf("irr for %d (%d pow, max %d)", dam, pow, max_dam); + if (agent->deity() == GOD_FEDHAS && fedhas_protects(*mons)) + { + simple_god_message( + make_stringf(" protects %s plant from harm.", + agent->is_player() ? "your" : "a").c_str(), + GOD_FEDHAS); + return 0; + } + if (agent->is_player()) _player_hurt_monster(*mons, dam, BEAM_MMISSILE); else if (dam) @@ -1317,6 +1340,10 @@ static int _ignite_tracer_cloud_value(coord_def where, actor *agent) const int dam = actor_cloud_immune(*act, CLOUD_FIRE) ? 0 : resist_adjust_damage(act, BEAM_FIRE, 40); + + if (agent->deity() == GOD_FEDHAS && fedhas_protects(*act->as_monster())) + return 0; + return mons_aligned(act, agent) ? -dam : dam; } // We've done something, but its value is indeterminate @@ -1771,6 +1798,15 @@ static int _discharge_monsters(const coord_def &where, int pow, // rEelec monsters don't allow arcs to continue. else if (victim->res_elec() > 0) return 0; + else if (agent.deity() == GOD_FEDHAS + && fedhas_protects(*victim->as_monster())) + { + simple_god_message( + make_stringf(" protects %s plant from harm.", + agent.is_player() ? "your" : "a").c_str(), + GOD_FEDHAS); + return 0; + } else { monster* mons = victim->as_monster(); @@ -1825,8 +1861,12 @@ bool safe_discharge(coord_def where, vector &exclude) if (act->is_monster()) { // Harmless to these monsters, so don't prompt about them. - if (act->res_elec() > 0) + if (act->res_elec() > 0 + || you.deity() == GOD_FEDHAS + && fedhas_protects(*act->as_monster())) + { continue; + } if (stop_attack_prompt(act->as_monster(), false, where)) return false; @@ -2218,7 +2258,8 @@ spret cast_sandblast(int pow, bolt &beam, bool fail) static bool _elec_not_immune(const actor *act) { - return act->res_elec() < 3; + return act->res_elec() < 3 && !(you_worship(GOD_FEDHAS) + && fedhas_protects(*act->as_monster())); } spret cast_thunderbolt(actor *caster, int pow, coord_def aim, bool fail) From 43a6aff242bf5a0c306d90df70d82849c6b1fad1 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Fri, 1 Feb 2019 22:49:42 -0500 Subject: [PATCH 030/864] Disable mores during targeting (11717) --- crawl-ref/source/directn.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc index 8746530ce160..92e9cc09d0e9 100644 --- a/crawl-ref/source/directn.cc +++ b/crawl-ref/source/directn.cc @@ -2047,6 +2047,7 @@ bool direction_chooser::choose_direction() clear_messages(); msgwin_set_temporary(true); + unwind_bool save_more(crawl_state.show_more_prompt, false); show_initial_prompt(); need_text_redraw = false; From 0f9db6f4df2b44df59ae7c942e1f7c4564a44cd9 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Sat, 2 Feb 2019 00:05:22 -0500 Subject: [PATCH 031/864] Check for monster polearms and wands in i_feel_safe (11704, 11782) --- crawl-ref/source/mon-util.cc | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index a79a79df596f..790bd53e92d5 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -3836,10 +3836,35 @@ static bool _mons_has_usable_ranged_weapon(const monster* mon) return is_launched(mon, weapon, *missile) != launch_retval::FUMBLED; } +static bool _mons_has_usable_polearm(const monster& mon) +{ + const item_def *weapon = mon.melee_weapon(); + const item_def *primary = mon.mslot_item(MSLOT_WEAPON); + + // We don't have a usable melee weapon if a different cursed weapon + // is presently equipped. + if (weapon != primary && primary && primary->cursed()) + return false; + + if (weapon && item_attack_skill(*weapon) == SK_POLEARMS) + return true; + + return false; +} + +static bool _mons_has_attack_wand(const monster& mon) +{ + const item_def *wand = mon.mslot_item(MSLOT_WAND); + + return wand && is_offensive_wand(*wand); +} + bool mons_has_ranged_attack(const monster& mon) { return mons_has_ranged_spell(mon, true) - || _mons_has_usable_ranged_weapon(&mon); + || _mons_has_usable_ranged_weapon(&mon) + || _mons_has_usable_polearm(mon) + || _mons_has_attack_wand(mon); } bool mons_has_incapacitating_ranged_attack(const monster& mon, const actor& foe) From 4264f9c312a05338b21d357fa6e7bc4bfcc1875b Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Sat, 2 Feb 2019 00:49:03 -0500 Subject: [PATCH 032/864] Simplify a reaching check, actually fix 11704 (gammafunk) Commit 0f9db6f4df modified the function mons_has_ranged_attack; however, this was not checked by i_feel_safe, which instead checked mons_has_known_ranged_attack. The latter function is a relic from when monster equipment was not identified on sight and has been removed. --- crawl-ref/source/mon-info.cc | 2 +- crawl-ref/source/mon-util.cc | 55 ++----------------------------- crawl-ref/source/mon-util.h | 1 - crawl-ref/source/nearby-danger.cc | 2 +- 4 files changed, 4 insertions(+), 56 deletions(-) diff --git a/crawl-ref/source/mon-info.cc b/crawl-ref/source/mon-info.cc index af97cfdb4366..dc3be459677b 100644 --- a/crawl-ref/source/mon-info.cc +++ b/crawl-ref/source/mon-info.cc @@ -747,7 +747,7 @@ monster_info::monster_info(const monster* m, int milev) } } - if (mons_has_known_ranged_attack(*m)) + if (mons_has_ranged_attack(*m)) mb.set(MB_RANGED_ATTACK); // this must be last because it provides this structure to Lua code diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index 790bd53e92d5..ad84050d9f88 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -54,6 +54,7 @@ #include "notes.h" #include "options.h" #include "random.h" +#include "reach-type.h" #include "religion.h" #include "showsymb.h" #include "species.h" @@ -3836,22 +3837,6 @@ static bool _mons_has_usable_ranged_weapon(const monster* mon) return is_launched(mon, weapon, *missile) != launch_retval::FUMBLED; } -static bool _mons_has_usable_polearm(const monster& mon) -{ - const item_def *weapon = mon.melee_weapon(); - const item_def *primary = mon.mslot_item(MSLOT_WEAPON); - - // We don't have a usable melee weapon if a different cursed weapon - // is presently equipped. - if (weapon != primary && primary && primary->cursed()) - return false; - - if (weapon && item_attack_skill(*weapon) == SK_POLEARMS) - return true; - - return false; -} - static bool _mons_has_attack_wand(const monster& mon) { const item_def *wand = mon.mslot_item(MSLOT_WAND); @@ -3863,7 +3848,7 @@ bool mons_has_ranged_attack(const monster& mon) { return mons_has_ranged_spell(mon, true) || _mons_has_usable_ranged_weapon(&mon) - || _mons_has_usable_polearm(mon) + || mon.reach_range() != REACH_NONE || _mons_has_attack_wand(mon); } @@ -3904,42 +3889,6 @@ bool mons_has_incapacitating_ranged_attack(const monster& mon, const actor& foe) return false; } -static bool _mons_starts_with_ranged_weapon(monster_type mc) -{ - switch (mc) - { - case MONS_JOSEPH: - case MONS_DEEP_ELF_MASTER_ARCHER: - case MONS_CENTAUR: - case MONS_CENTAUR_WARRIOR: - case MONS_NESSOS: - case MONS_YAKTAUR: - case MONS_YAKTAUR_CAPTAIN: - case MONS_CHERUB: - case MONS_SONJA: - case MONS_HAROLD: - case MONS_POLYPHEMUS: - case MONS_CYCLOPS: - case MONS_STONE_GIANT: - case MONS_CHUCK: - case MONS_MERFOLK_JAVELINEER: - case MONS_URUG: - case MONS_FAUN: - case MONS_SATYR: - case MONS_NAGA_SHARPSHOOTER: - return true; - default: - return false; - } -} - -bool mons_has_known_ranged_attack(const monster& mon) -{ - return mon.flags & MF_SEEN_RANGED - || _mons_starts_with_ranged_weapon(mon.type) - && !(mon.flags & MF_KNOWN_SHIFTER); -} - bool mons_can_attack(const monster& mon) { const actor* foe = mon.get_foe(); diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h index 659e6e77ea00..c436eb903ee1 100644 --- a/crawl-ref/source/mon-util.h +++ b/crawl-ref/source/mon-util.h @@ -346,7 +346,6 @@ bool mons_has_los_ability(monster_type mon_type); bool mons_has_ranged_spell(const monster& mon, bool attack_only = false, bool ench_too = true); bool mons_has_ranged_attack(const monster& mon); -bool mons_has_known_ranged_attack(const monster& mon); bool mons_can_attack(const monster& mon); bool mons_has_incapacitating_spell(const monster& mon, const actor& foe); bool mons_has_incapacitating_ranged_attack(const monster& mon, const actor& foe); diff --git a/crawl-ref/source/nearby-danger.cc b/crawl-ref/source/nearby-danger.cc index 864a69f7a6d0..33809ddb85ca 100644 --- a/crawl-ref/source/nearby-danger.cc +++ b/crawl-ref/source/nearby-danger.cc @@ -106,7 +106,7 @@ bool mons_can_hurt_player(const monster* mon, const bool want_move) // Even if the monster can not actually reach the player it might // still use some ranged form of attack. if (you.see_cell_no_trans(mon->pos()) - && mons_has_known_ranged_attack(*mon)) + && mons_has_ranged_attack(*mon)) { return true; } From b2a911eaf4009f23af93ccb6a6c6403dc79e60e0 Mon Sep 17 00:00:00 2001 From: advil Date: Fri, 1 Feb 2019 22:23:49 -0500 Subject: [PATCH 033/864] Print test names to stderr as they run This lets there be visible progress during `make test`. It might be slightly annoying when some tests are not running headless, but then the user can just redirect stderr somewhere. --- crawl-ref/source/ctest.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crawl-ref/source/ctest.cc b/crawl-ref/source/ctest.cc index e77a0c11d3ba..f4db4e814011 100644 --- a/crawl-ref/source/ctest.cc +++ b/crawl-ref/source/ctest.cc @@ -124,6 +124,7 @@ static void run_test(const string &file) return; ++ntests; + fprintf(stderr, "Running test #%d: '%s'.\n", ntests, file.c_str()); mprf(MSGCH_DIAGNOSTICS, "Running %s %d: %s", activity, ntests, file.c_str()); flush_prev_message(); @@ -152,6 +153,7 @@ static void _run_test(const string &name, void (*func)()) if (!_has_test(name)) return; + fprintf(stderr, "Running test #%d: '%s'.\n", ntests, name.c_str()); ++ntests; try From 2941439957fec76e80287e03820bc86607cf5b24 Mon Sep 17 00:00:00 2001 From: advil Date: Fri, 1 Feb 2019 22:26:02 -0500 Subject: [PATCH 034/864] Further updates to rng development docs [skip ci] --- crawl-ref/docs/develop/rng_guidelines.md | 39 +++++++++++++++++++----- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/crawl-ref/docs/develop/rng_guidelines.md b/crawl-ref/docs/develop/rng_guidelines.md index 48873907aea2..4eaa85fab655 100644 --- a/crawl-ref/docs/develop/rng_guidelines.md +++ b/crawl-ref/docs/develop/rng_guidelines.md @@ -135,14 +135,37 @@ versions will give you these files in a stable order - sort it yourself. **Iteration order**: If you are using some sort of reservoir-sampling style of random choice algorithm, you will iterate through the container, stopping the -iteration at some point determined by one or more random draws. If the -iteration order is not guaranteed to be defined, this can lead to different -results from run to run. For example, in lua, iteration via `pairs` or the -C equivalents over a table is not guaranteed to have a stable order, and we -have found that in practice it doesn't -- leading to different choices with -the same random number draws. The `ipairs` iterator is safe, but places some -obvious constraints on the structure you are using. Sorting the underlying -container may be a solution as well. +iteration at some point determined by one or more random draws. If the iteration +order is not guaranteed to be defined, this can lead to different results from +run to run. For C++ code, this generally isn't an issue (or at least, hasn't +come up so far), but it does show up in lua code and in the lua-C++ interface. +In Lua, iteration via `pairs` or the C equivalents over a table is not +guaranteed to have a stable order, and we have found that in practice it doesn't +-- leading to different choices with the same random number draws. The `ipairs` +iterator is safe, but places some obvious constraints on the structure you are +using. Sorting the underlying container may be a solution as well. + +Some specific lua tips: rather than rolling your own weighted randomness, if at +all possible use one of the following functions: `util.random_choose_weighted`, +`util.random_choose_weighted_i`, and `util.random_weighted_from` (which all +operator on an array of some strip and use a stable iteration order), or +`util.random_random_weighted_keys`, which requires sortable keys and will use +the sort order of the keys in its iteration. If you have an unweighted list, +you can use `util.random_from`. If the items you are choosing from are +sortable (e.g, strings), you can still use a weight table as long as you turn +it into a stably-ordered array with `util.sorted_weight_table`. This takes a +table mapping values to weights, and produces an array of value-weight pairs +that then can be used for `util.random_choose_weighted`. + +When writing Lua-C++ interface code, be aware that `lua_next` does not guarantee +order any more than `pairs`, *even if* the table is an array. Bugs from this +will be fairly indeterminate and hard to spot, but do show up in practice. +Either use Lua's facilities for `ipairs`-style iteration (which are a bit weak +in the version of Lua we use), or sort the results on the C side (in a way that +doesn't rely on runtime information). For example, loading an array of strings +into a `map` will give you a stable sort order. Or, if the order +in the array is not important, you can use `lua_next` with a vector and +`push_back`, and then sort the results. ### 3.3 other sources of randomization From 59e0e63b9aff37c1454c7ef7e26513a79a325598 Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 2 Feb 2019 00:36:20 -0500 Subject: [PATCH 035/864] Further isolate ghost generation from levelgen rng The properties of a ghost can lead to variation in the number of random draws needed when placing it; for example, if a ghost knows certain enchantments, these will be applied immediately with a random duration, leading to an extra random draw relative to ghosts without an enchantment. This can lead to seeds diverging depending on what ghosts are in the local bones file. Isolate the entire placement process from the levelgen RNG so it won't impact seeds. --- crawl-ref/source/mon-place.cc | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/mon-place.cc b/crawl-ref/source/mon-place.cc index 364df3ef4580..fe7cb855114a 100644 --- a/crawl-ref/source/mon-place.cc +++ b/crawl-ref/source/mon-place.cc @@ -86,6 +86,10 @@ static monster* _place_monster_aux(const mgen_data &mg, const monster *leader, level_id place, bool force_pos = false, bool dont_place = false); +static monster* _place_pghost_aux(const mgen_data &mg, const monster *leader, + level_id place, + bool force_pos, bool dont_place); + /** * Is this feature "close enough" to the one we want for monster generation? @@ -721,8 +725,12 @@ monster* place_monster(mgen_data mg, bool force_pos, bool dont_place) else if (!_valid_monster_generation_location(mg) && !dont_place) return nullptr; - monster* mon = _place_monster_aux(mg, nullptr, place, force_pos, - dont_place); + monster* mon; + if (mg.cls == MONS_PLAYER_GHOST) + mon = _place_pghost_aux(mg, nullptr, place, force_pos, dont_place); + else + mon = _place_monster_aux(mg, nullptr, place, force_pos, dont_place); + if (!mon) return nullptr; @@ -1490,6 +1498,18 @@ static monster* _place_monster_aux(const mgen_data &mg, const monster *leader, return mon; } +static monster* _place_pghost_aux(const mgen_data &mg, const monster *leader, + level_id place, + bool force_pos, bool dont_place) +{ + // we need to isolate the generation of a pghost from the caller's RNG, + // since depending on the ghost, the aux call can trigger variation in + // things like whether an enchantment (with a random duration) is + // triggered. + rng_generator rng(RNG_SYSTEM_SPECIFIC); + return _place_monster_aux(mg, leader, place, force_pos, dont_place); +} + // Check base monster class against zombie type and position if set. static bool _good_zombie(monster_type base, monster_type cs, const coord_def& pos) From e6a56636f9f9b9835036759d50caac94faa2d2a3 Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 2 Feb 2019 00:41:51 -0500 Subject: [PATCH 036/864] Simplify test slightly Also, increase the timeout for `make test`; possibly this means that some of these tests could be pared back a bit, but for now I'll keep them slow. --- crawl-ref/source/test/stress/run | 2 +- crawl-ref/source/test/vault_catalog.lua | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crawl-ref/source/test/stress/run b/crawl-ref/source/test/stress/run index 986d3978706e..cef991d34e8d 100755 --- a/crawl-ref/source/test/stress/run +++ b/crawl-ref/source/test/stress/run @@ -1,7 +1,7 @@ #!/bin/sh set -e -CRAWL=${CRAWL:-timeout 595 ./crawl -seed 1 -no-save -name test -wizard -no-throttle} +CRAWL=${CRAWL:-timeout 655 ./crawl -seed 1 -no-save -name test -wizard -no-throttle} run_one() { diff --git a/crawl-ref/source/test/vault_catalog.lua b/crawl-ref/source/test/vault_catalog.lua index 7cf58fa0d5b3..6fc36dd279b6 100644 --- a/crawl-ref/source/test/vault_catalog.lua +++ b/crawl-ref/source/test/vault_catalog.lua @@ -9,8 +9,7 @@ -- but if you are expecting deterministic test behavior, take that into -- account. -local catalog_seed = 1 -- seed to print out -local starting_seed = 2 -- fixed seed to start with +local starting_seed = 1 -- fixed seed to start with local fixed_seeds = 2 -- how many fixed seeds to run? local per_seed_iters = 1 -- how many stability tests to run per seed local rand_seeds = 2 -- how many random seeds to run @@ -105,11 +104,11 @@ function test_seed(seed, iters, order, quiet) end end -test_seed(catalog_seed, per_seed_iters, generation_order, false) +test_seed(starting_seed, per_seed_iters, generation_order, false) -- just do a quick check of hell / pan stability -test_seed(catalog_seed, per_seed_iters, generation_order_extended, true) +--test_seed(starting_seed, per_seed_iters, generation_order_extended, true) -for i=starting_seed, starting_seed + fixed_seeds - 1 do +for i=starting_seed + 1, starting_seed + fixed_seeds - 2 do crawl.stderr("Testing seed " .. i .. ".") test_seed(i, per_seed_iters, generation_order, true) end @@ -120,6 +119,7 @@ end for i=1,rand_seeds do -- intentional use of non-crawl random(). random doesn't seem to accept -- anything bigger than 32 bits for the range. + math.randomseed(crawl.millis()) rand_seed = math.random(0x7FFFFFFF) crawl.stderr("Testing random seed " .. rand_seed .. ".") test_seed(rand_seed, per_seed_iters, generation_order, true) From f1fd2d0243764fcc7f159bc23d106f3a6d607036 Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 2 Feb 2019 01:20:18 -0500 Subject: [PATCH 037/864] Update the tags API to use sets This previously just used raw strings in rather hacky ways. The main reasons I'm updating this now are because (i) tag ordering was affecting randomness in some cases, and (ii) the lack of any uniqueness checking was causing weird effects where some lua code would just keep on adding duplicates of the same tag (which again, interacted with the random number generation because it changed the size of what was being drawn from in some cases). But, it also was a pretty creaky API with a lot of things that were strange and ad-hoc. This new version is definitely a bit heavier, but I'm not sure that will impact anything in a major way. --- crawl-ref/source/dungeon.cc | 35 +++++---- crawl-ref/source/english.cc | 6 +- crawl-ref/source/l-dgn.cc | 10 +-- crawl-ref/source/libutil.cc | 24 +++++++ crawl-ref/source/libutil.h | 2 + crawl-ref/source/mapdef.cc | 129 +++++++++++++++++++++------------- crawl-ref/source/mapdef.h | 12 +++- crawl-ref/source/ng-init.cc | 6 +- crawl-ref/source/stringutil.h | 9 +++ 9 files changed, 158 insertions(+), 75 deletions(-) diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 1b2009efc5d8..919daa7c81d2 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -717,15 +717,15 @@ static void _set_grd(const coord_def &c, dungeon_feature_type feat) grd(c) = feat; } -static void _dgn_register_vault(const string &name, const string &spaced_tags) +static void _dgn_register_vault(const string &name, const set &tags) { - if (spaced_tags.find(" allow_dup ") == string::npos) + if (!tags.count("allow_dup")) you.uniq_map_names.insert(name); - if (spaced_tags.find(" luniq ") != string::npos) + if (tags.count("luniq")) env.level_uniq_maps.insert(name); - for (const string &tag : split_string(" ", spaced_tags)) + for (const string &tag : tags) { if (starts_with(tag, "uniq_")) you.uniq_map_tags.insert(tag); @@ -734,12 +734,22 @@ static void _dgn_register_vault(const string &name, const string &spaced_tags) } } +static void _dgn_register_vault(const map_def &map) +{ + _dgn_register_vault(map.name, map.get_tags()); +} + +static void _dgn_register_vault(const string &name, string &spaced_tags) +{ + _dgn_register_vault(name, parse_tags(spaced_tags)); +} + static void _dgn_unregister_vault(const map_def &map) { you.uniq_map_names.erase(map.name); env.level_uniq_maps.erase(map.name); - for (const string &tag : split_string(" ", map.tags)) + for (const string &tag : map.get_tags()) { if (starts_with(tag, "uniq_")) you.uniq_map_tags.erase(tag); @@ -1048,7 +1058,7 @@ dgn_register_place(const vault_placement &place, bool register_vault) if (register_vault) { - _dgn_register_vault(place.map.name, place.map.tags); + _dgn_register_vault(place.map); for (int i = env.new_subvault_names.size() - 1; i >= 0; i--) { _dgn_register_vault(env.new_subvault_names[i], @@ -1076,7 +1086,7 @@ dgn_register_place(const vault_placement &place, bool register_vault) } // Find tags matching properties. - vector tags = place.map.get_tags(); + set tags = place.map.get_tags(); for (const auto &tag : tags) { @@ -2579,13 +2589,13 @@ static bool _vault_can_use_layout(const map_def *vault, const map_def *layout) ASSERT(layout->has_tag_prefix("layout_type_")); - vector tags = layout->get_tags(); + const set tags = layout->get_tags(); - for (string &tag : tags) + for (auto &tag : tags) { if (starts_with(tag, "layout_type_")) { - string type = strip_tag_prefix(tag, "layout_type_"); + string type = tag_without_prefix(tag, "layout_type_"); if (vault->has_tag("layout_" + type)) return true; else if (vault->has_tag("nolayout_" + type)) @@ -4211,13 +4221,12 @@ static const vault_placement *_build_vault_impl(const map_def *vault, if (is_layout && place.map.has_tag_prefix("layout_type_")) { - vector tag_list = place.map.get_tags(); - for (string &tag : tag_list) + for (auto &tag : place.map.get_tags()) { if (starts_with(tag, "layout_type_")) { env.level_layout_types.insert( - strip_tag_prefix(tag, "layout_type_")); + tag_without_prefix(tag, "layout_type_")); } } } diff --git a/crawl-ref/source/english.cc b/crawl-ref/source/english.cc index 89759696f34d..4c48686b216d 100644 --- a/crawl-ref/source/english.cc +++ b/crawl-ref/source/english.cc @@ -300,7 +300,7 @@ static string _tens_in_words(unsigned num) return string(tens[ten]) + (digit ? string("-") + numbers[digit] : ""); } -static string join_strings(const string &a, const string &b) +static string _join_strings(const string &a, const string &b) { if (!a.empty() && !b.empty()) return a + " " + b; @@ -313,7 +313,7 @@ static string _hundreds_in_words(unsigned num) unsigned dreds = num / 100, tens = num % 100; string sdreds = dreds? _tens_in_words(dreds) + " hundred" : ""; string stens = tens? _tens_in_words(tens) : ""; - return join_strings(sdreds, stens); + return _join_strings(sdreds, stens); } static string _number_in_words(unsigned num, unsigned period) @@ -332,7 +332,7 @@ static string _number_in_words(unsigned num, unsigned period) if (!rest && !thousands) return "zero"; - return join_strings((rest? _number_in_words(rest, period + 1) : ""), + return _join_strings((rest? _number_in_words(rest, period + 1) : ""), (thousands? _hundreds_in_words(thousands) + periods[period] : "")); diff --git a/crawl-ref/source/l-dgn.cc b/crawl-ref/source/l-dgn.cc index 93cddab49101..e68a2b59611f 100644 --- a/crawl-ref/source/l-dgn.cc +++ b/crawl-ref/source/l-dgn.cc @@ -145,14 +145,14 @@ static int dgn_tags(lua_State *ls) if (lua_gettop(ls) > 1) { if (lua_isnil(ls, 2)) - map->tags.clear(); + map->clear_tags(); else { const char *s = luaL_checkstring(ls, 2); - map->tags += " " + trimmed_string(s) + " "; + map->add_tags(s); } } - PLUARET(string, map->tags.c_str()); + PLUARET(string, map->tags_string().c_str()); } static int dgn_has_tag(lua_State *ls) @@ -169,9 +169,9 @@ static int dgn_tags_remove(lua_State *ls) for (int i = 2; i <= top; ++i) { const string axee = luaL_checkstring(ls, i); - while (strip_tag(map->tags, axee)); + map->remove_tags(axee); } - PLUARET(string, map->tags.c_str()); + PLUARET(string, map->tags_string().c_str()); } static void _chance_magnitude_check(lua_State *ls, int which_par, int chance) diff --git a/crawl-ref/source/libutil.cc b/crawl-ref/source/libutil.cc index ac95e456b21a..f1b8f749e78f 100644 --- a/crawl-ref/source/libutil.cc +++ b/crawl-ref/source/libutil.cc @@ -192,6 +192,23 @@ string strip_tag_prefix(string &s, const string &tagprefix) return argument; } +const string tag_without_prefix(const string &s, const string &tagprefix) +{ + string::size_type pos = s.find(tagprefix); + + while (pos && pos != string::npos && !isspace(s[pos - 1])) + pos = s.find(tagprefix, pos + 1); + + if (pos == string::npos) + return ""; + + string::size_type ns = s.find(" ", pos); + if (ns == string::npos) + ns = s.length(); + + return s.substr(pos + tagprefix.length(), ns - pos - tagprefix.length()); +} + int strip_number_tag(string &s, const string &tagprefix) { const string num = strip_tag_prefix(s, tagprefix); @@ -201,6 +218,13 @@ int strip_number_tag(string &s, const string &tagprefix) return x; } +set parse_tags(const string &tags) +{ + vector split_tags = split_string(" ", tags); + set ordered_tags(split_tags.begin(), split_tags.end()); + return ordered_tags; +} + bool parse_int(const char *s, int &i) { if (!s || !*s) diff --git a/crawl-ref/source/libutil.h b/crawl-ref/source/libutil.h index 3a4ad825fded..4dc603089d6d 100644 --- a/crawl-ref/source/libutil.h +++ b/crawl-ref/source/libutil.h @@ -73,6 +73,8 @@ bool strip_tag(string &s, const string &tag, bool nopad = false); int strip_number_tag(string &s, const string &tagprefix); vector strip_multiple_tag_prefix(string &s, const string &tagprefix); string strip_tag_prefix(string &s, const string &tagprefix); +const string tag_without_prefix(const string &s, const string &tagprefix); +set parse_tags(const string &tags); bool parse_int(const char *s, int &i); // String 'descriptions' diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc index ad7db4c0bda6..45707fdcb77f 100644 --- a/crawl-ref/source/mapdef.cc +++ b/crawl-ref/source/mapdef.cc @@ -2164,13 +2164,14 @@ string depth_ranges::describe() const const int DEFAULT_MAP_WEIGHT = 10; map_def::map_def() - : name(), description(), order(INT_MAX), tags(), place(), depths(), + : name(), description(), order(INT_MAX), place(), depths(), orient(), _chance(), _weight(DEFAULT_MAP_WEIGHT), map(), mons(), items(), random_mons(), prelude("dlprelude"), mapchunk("dlmapchunk"), main("dlmain"), validate("dlvalidate"), veto("dlveto"), epilogue("dlepilogue"), rock_colour(BLACK), floor_colour(BLACK), rock_tile(""), floor_tile(""), border_fill_type(DNGN_ROCK_WALL), + tags(), index_only(false), cache_offset(0L), validating_map_flag(false) { init(); @@ -2469,7 +2470,7 @@ void map_def::write_index(writer& outf) const _chance.write(outf, _marshall_map_chance); _weight.write(outf, marshallInt); marshallInt(outf, cache_offset); - marshallString4(outf, tags); + marshallString4(outf, tags_string()); place.write(outf); depths.write(outf); prelude.write(outf); @@ -2493,7 +2494,9 @@ void map_def::read_index(reader& inf) _chance = range_chance_t::read(inf, _unmarshall_map_chance); _weight = range_weight_t::read(inf, unmarshallInt); cache_offset = unmarshallInt(inf); - unmarshallString4(inf, tags); + string read_tags; + unmarshallString4(inf, read_tags); + set_tags(read_tags); place.read(inf); depths.read(inf); prelude.read(inf); @@ -2672,30 +2675,19 @@ string map_def::validate_temple_map() if (has_tag_prefix("temple_overflow_")) { - vector tag_list = get_tags(); - - auto tag = find_if(begin(tag_list), end(tag_list), - bind(starts_with, placeholders::_1, "temple_overflow_")); - - if (tag == end(tag_list)) - return make_stringf("Unknown temple tag."); - - string temple_tag = strip_tag_prefix(*tag, "temple_overflow_"); - - if (temple_tag.empty()) - return "Malformed temple_overflow_ tag"; - - if (starts_with(temple_tag, "generic_")) + if (has_tag_prefix("temple_overflow_generic_")) { - temple_tag = strip_tag_prefix(temple_tag, "generic_"); - - int num = 0; - parse_int(temple_tag.c_str(), num); - - if (((unsigned long) num) != altars.size()) + string matching_tag = make_stringf("temple_overflow_generic_%u", + (unsigned int) altars.size()); + if (!has_tag(matching_tag)) { - return make_stringf("Temple should contain %u altars, but " - "has %d.", (unsigned int)altars.size(), num); + return make_stringf( + "Temple ('%s') has %u altars and a " + "'temple_overflow_generic_' tag, but does not match the " + "number of altars: should have at least '%s'.", + tags_string().c_str(), + (unsigned int) altars.size(), + matching_tag.c_str()); } } else @@ -2734,7 +2726,7 @@ string map_def::validate_map_placeable() // Ok, the map wants to be placed by tag. In this case it should have // at least one tag that's not a map flag. bool has_selectable_tag = false; - for (const string &piece : split_string(" ", tags)) + for (const string &piece : get_tags()) { if (_map_tag_is_selectable(piece)) { @@ -2746,7 +2738,7 @@ string map_def::validate_map_placeable() return has_selectable_tag? "" : make_stringf("Map '%s' has no DEPTH, no PLACE and no " "selectable tag in '%s'", - name.c_str(), tags.c_str()); + name.c_str(), tags_string().c_str()); } /** @@ -2842,7 +2834,7 @@ string map_def::validate_map_def(const depth_ranges &default_depths) || map.height() > dimension_lower_bound) && !has_tag("no_rotate")) { - tags += " no_rotate "; + add_tags("no_rotate"); } } @@ -3243,39 +3235,81 @@ void map_def::fixup() if (orient == MAP_NONE) { orient = MAP_FLOAT; - tags += " minivault "; + add_tags("minivault"); } } -bool map_def::has_tag(const string &tagwanted) const +bool map_def::has_tag(const set &tagswanted) const { - if (tags.empty() || tagwanted.empty()) + if (tags.empty() || tagswanted.size() == 0) return false; - vector wanted_tags = split_string(" ", tagwanted); - - for (const string &tag : wanted_tags) - if (tags.find(" " + tag + " ") == string::npos) + for (const string &tag : tagswanted) + if (!tags.count(tag)) return false; return true; } +bool map_def::has_tag(const string &tagswanted) const +{ + return has_tag(parse_tags(tagswanted)); +} + bool map_def::has_tag_prefix(const string &prefix) const { - return !tags.empty() && !prefix.empty() - && tags.find(" " + prefix) != string::npos; + if (prefix.empty()) + return false; + for (const auto &tag : tags) + if (starts_with(tag, prefix)) + return true; + return false; } bool map_def::has_tag_suffix(const string &suffix) const { - return !tags.empty() && !suffix.empty() - && tags.find(suffix + " ") != string::npos; + if (suffix.empty()) + return false; + for (const auto &tag : tags) + if (ends_with(tag, suffix)) + return true; + return false; } -vector map_def::get_tags() const +const set map_def::get_tags() const { - return split_string(" ", tags); + return tags; +} + +void map_def::add_tags(const string &tag) +{ + auto parsed_tags = parse_tags(tag); + tags.insert(parsed_tags.begin(), parsed_tags.end()); +} + +bool map_def::remove_tags(const string &tag) +{ + bool removed = false; + auto parsed_tags = parse_tags(tag); + for (auto &t : parsed_tags) + removed = tags.erase(t) || removed; // would iterator overload be ok? + return removed; +} + +void map_def::clear_tags() +{ + tags.clear(); +} + +void map_def::set_tags(const string &tag) +{ + clear_tags(); + add_tags(tag); +} + +string map_def::tags_string() const +{ + return join_strings(tags.begin(), tags.end()); } keyed_mapspec *map_def::mapspec_at(const coord_def &c) @@ -3329,13 +3363,11 @@ string map_def::subvault_from_tagstring(const string &sub) static void _register_subvault(const string &name, const string &spaced_tags) { - if (spaced_tags.find(" allow_dup ") == string::npos - || spaced_tags.find(" luniq ") != string::npos) - { + auto parsed_tags = parse_tags(spaced_tags); + if (!parsed_tags.count("allow_dup") || parsed_tags.count("luniq")) env.new_used_subvault_names.insert(name); - } - for (const string &tag : split_string(" ", spaced_tags)) + for (const string &tag : parsed_tags) if (starts_with(tag, "uniq_") || starts_with(tag, "luniq_")) env.new_used_subvault_tags.insert(tag); } @@ -3408,8 +3440,9 @@ string map_def::apply_subvault(string_spec &spec) copy_hooks_from(vault, "post_place"); env.new_subvault_names.push_back(vault.name); - env.new_subvault_tags.push_back(vault.tags); - _register_subvault(vault.name, vault.tags); + const string vault_tags = vault.tags_string(); + env.new_subvault_tags.push_back(vault_tags); + _register_subvault(vault.name, vault_tags); subvault_places.emplace_back(subvault_corners.first, subvault_corners.second, vault); diff --git a/crawl-ref/source/mapdef.h b/crawl-ref/source/mapdef.h index 3517b87d2afe..fd71f3b4978e 100644 --- a/crawl-ref/source/mapdef.h +++ b/crawl-ref/source/mapdef.h @@ -1113,7 +1113,6 @@ class map_def string description; // Order among related maps; used only for tutorial/sprint. int order; - string tags; depth_ranges place; depth_ranges depths; @@ -1152,6 +1151,7 @@ class map_def vector subvault_places; private: + set tags; // This map has been loaded from an index, and not fully realised. bool index_only; mutable long cache_offset; @@ -1247,7 +1247,8 @@ class map_def bool is_minivault() const; bool is_overwritable_layout() const; - bool has_tag(const string &tag) const; + bool has_tag(const string &tagswanted) const; + bool has_tag(const set &tagswanted) const; bool has_tag_prefix(const string &tag) const; bool has_tag_suffix(const string &suffix) const; @@ -1260,7 +1261,12 @@ class map_def return false; } - vector get_tags() const; + const set get_tags() const; + void add_tags(const string &tag); + void set_tags(const string &tag); + bool remove_tags(const string &tag); + void clear_tags(); + string tags_string() const; vector get_shuffle_strings() const; vector get_subst_strings() const; diff --git a/crawl-ref/source/ng-init.cc b/crawl-ref/source/ng-init.cc index a34803c65a37..aacd18320355 100644 --- a/crawl-ref/source/ng-init.cc +++ b/crawl-ref/source/ng-init.cc @@ -142,12 +142,13 @@ void initialise_temples() if (main_temple->has_tag("temple_variable")) { vector sizes; - for (string &tag : main_temple->get_tags()) + for (auto &tag : main_temple->get_tags()) { if (starts_with(tag, "temple_altars_")) { sizes.push_back( - atoi(strip_tag_prefix(tag, "temple_altars_").c_str())); + atoi(tag_without_prefix(tag, + "temple_altars_").c_str())); } } if (sizes.empty()) @@ -167,7 +168,6 @@ void initialise_temples() // Without all this find_glyph() returns 0. string err; - main_temple->tags.clear(); // anything else that needs to be cleared? main_temple->load(); main_temple->reinit(); err = main_temple->run_lua(true); diff --git a/crawl-ref/source/stringutil.h b/crawl-ref/source/stringutil.h index 70340bff662c..9bbb1e290ae8 100644 --- a/crawl-ref/source/stringutil.h +++ b/crawl-ref/source/stringutil.h @@ -213,6 +213,15 @@ string comma_separated_line(Z start, Z end, const string &andc = " and ", andc, comma); } +/** + * For when the above functions are a bit over-elaborate... + */ +template +string join_strings(Z start, Z end, const string &sep = " ") +{ + return comma_separated_line(start, end, " ", " "); +} + static inline bool starts_with(const string &s, const string &prefix) { return s.rfind(prefix, 0) != string::npos; From 23bff18b8c44d8836aed731b50d3ea7db3eaee3b Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 2 Feb 2019 13:09:46 -0500 Subject: [PATCH 038/864] More documentation and notes on seeding Some of this might be fodder for a blog post too; writing this all down because eventually someone else might want to do some seed debugging, and there are a *lot* of blind alleys I've found while doing this. [skip ci] --- crawl-ref/docs/develop/rng_guidelines.md | 83 +++++++++++++++++++++++- 1 file changed, 80 insertions(+), 3 deletions(-) diff --git a/crawl-ref/docs/develop/rng_guidelines.md b/crawl-ref/docs/develop/rng_guidelines.md index 4eaa85fab655..f08b667aae82 100644 --- a/crawl-ref/docs/develop/rng_guidelines.md +++ b/crawl-ref/docs/develop/rng_guidelines.md @@ -56,13 +56,31 @@ specific to a single commit. Similarly, upgrading a game (trunk or otherwise) where the dungeon is not pregenerated will lead to divergence from *both* seed to dungeon mappings. +## 2.1. Detecting seed divergence + +Detecting this can be quite hard, but there are a few built-in tests that run +in Travis CI and can be run locally. These are `d1_vaults.lua` (which prints +vaults for a few dungeon levels for 10 seeds), and the deeper but less broad +`vault_catalog.lua` test, which prints the entire vault catalog for one seed, +and does a bunch of seed stability tests by comparing that vault catalog across +multiple runs, for several fixed and randomly chosen seeds. This test is quite +time and cpu-intensive (a bit like mapstat), and the default settings are quite +modest, but you can tweek the number of seeds, runs, and use it to hand check +custom seeds by running it locally. To directly run this test in the most +useful fashion, the magic invocation is (can be further combined with pipes or +redirects): + + util/fake_pty ./crawl -test vault_catalog.lua 2>&1 + +If you haven't already, you may need to run `make util/fake_pty` first. + ## 3. Specific coding guidelines and caveats The biggest challenge in ensuring stable seed to dungeon mappings involves ensuring that random numbers are drawn from the generators in the same order. There are two specific areas where care is required. -### 3.1 random call evaluation order +### 3.1. random call evaluation order C++, in many cases, does not guarantee stable evaluation order for function calls, and this can result in different behaviors across compilers, OSs, and @@ -122,7 +140,7 @@ is ok (at least in terms of RNG call sequencing): For everything else, when in doubt, break it into multiple expressions that are sequenced by `;`s. -### 3.2 choosing from lists +### 3.2. choosing from lists When you are randomly choosing an item from a list (e.g. by randomly picking an index in the list range), be careful about both the underlying list order, @@ -167,7 +185,66 @@ into a `map` will give you a stable sort order. Or, if the order in the array is not important, you can use `lua_next` with a vector and `push_back`, and then sort the results. -### 3.3 other sources of randomization +### 3.3. other sources of randomization Don't use other sources of randomization in crawl besides crawl RNGs. For example, don't use lua's `math.rand`, or C stdlib's `rand`. + +## 4. Dealing with seed divergence + +Seed divergence is when the same seed, with the same generation order, leads to +distinct dungeons under some circumstance. There are two main ways that seed +divergence can present: + +1. Seed instability on a single device +2. Seed instability across devices + +### 4.1. Seed instability on a single device + +This presents itself as extra "randomness" that is not determined by the seed. +The simplest case to find would be where some system-specific information is +directly interacting with one or more random draws: e.g. don't multiply a +random number by the current system time. More subtle instances of this, +mentioned above in section 3.2, are things like choosing randomly from a list +of files that might change from run to run. While some effort has been made +to partition player ghost generation off from levelgen, since player ghosts +can vary from one time to another, this is one potential source of divergence. +(For example, early in the implementation of strong seeding, a bug was present +where whether a ghost was generated with an enchantment would change the number +of random draws needed to place the ghost, leading to different rng state for +the next levelgen decision.) + +The more subtle kind of problem of this kind is when some sort of undefined +behavior is not so obviously undefined to the developer, but can lead to +run-to-run variation in corner cases. *By far* the biggest example so far has +been iteration order in lua, discussed above in section 3.2. (In general, +undefined behavior in C++ code is usually defined one way or the other by a +particular compiler and stdlib, and leads to seed instability across devices +rather than within devices; I wouldn't take this as a hard rule though.) + +This is, believe it or not, the easiest case to debug because it can usually be +replicated. However, before spending a lot of time trying to replicate a case of +this, first check the following issue: is the generation behavior different when +running crawl with a clean .des cache and bones file as later? Many early +seeding bugs presented themselves this way, and to replicate a bug of this kind +you will need to clear the caches. + +### 4.2. Seed instability across devices + +Seed instabilities across devices are often quite hard to replicate and debug, +so fire up the VM / container. In practice, most of the cases of this that we +have found involve things where C++ or stdlib behavior is undefined and +different compilers or build options (or OSs, perhaps) lead to different +choices. The biggest example is the ordering of random calls in arithmetic +expressions, discussed in section 4.1, so this is definitely the first thing +to look for. The ##crawl-dev population in aggregate has pretty detailed +knowledge of the C++ specs, so if you aren't sure whether somethig in particular +is defined, this is a good place to ask. + +Before opening the VM, however, if what you are seeing is a difference between +your device and Travis CI results - keep in mind that Travis runs its tests +from a clean state, and that this may be a case of seed instability within +a device that is dependent on the cache state. Also, many tests run first +before the vault catalog test, so double check if there's some game state factor +that is affected by earlier tests. (E.g. compare running the vault catalog test +directly with running `make test`). From c4805aa249044cc1c545b4c4e40f258580742558 Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 2 Feb 2019 13:36:17 -0500 Subject: [PATCH 039/864] Don't count gold as part of the level builder (joemaro) This was artificially inflating the prices of gozag for level pregeneration. It now runs when entering a level, if that level counts as just created (either by pregeneration or not). Resolves #972 --- crawl-ref/source/dungeon.cc | 47 +--------------------------------- crawl-ref/source/files.cc | 51 +++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 46 deletions(-) diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 919daa7c81d2..b585400f853a 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -231,51 +231,6 @@ static unique_ptr dgn_colour_grid; static string branch_epilogues[NUM_BRANCHES]; -static void _count_gold() -{ - vector gold_piles; - vector gold_places; - int gold = 0; - for (rectangle_iterator ri(0); ri; ++ri) - { - for (stack_iterator j(*ri); j; ++j) - { - if (j->base_type == OBJ_GOLD) - { - gold += j->quantity; - gold_piles.push_back(&(*j)); - gold_places.push_back(*ri); - } - } - } - - if (!player_in_branch(BRANCH_ABYSS)) - you.attribute[ATTR_GOLD_GENERATED] += gold; - - if (have_passive(passive_t::detect_gold)) - { - for (unsigned int i = 0; i < gold_places.size(); i++) - { - bool detected = false; - int dummy = gold_piles[i]->index(); - coord_def &pos = gold_places[i]; - unlink_item(dummy); - move_item_to_grid(&dummy, pos, true); - if (!env.map_knowledge(pos).item() - || env.map_knowledge(pos).item()->base_type != OBJ_GOLD) - { - detected = true; - } - update_item_at(pos, true); - if (detected) - { - ASSERT(env.map_knowledge(pos).item()); - env.map_knowledge(pos).flags |= MAP_DETECTED_ITEM; - } - } - } -} - /********************************************************************** * builder() - kickoff for the dungeon generator. *********************************************************************/ @@ -426,7 +381,6 @@ static bool _build_level_vetoable(bool enable_random_maps, strip_all_maps(); check_map_validity(); - _count_gold(); if (!_you_vault_list.empty()) { @@ -662,6 +616,7 @@ void dgn_flush_map_memory() you.props.erase(OVERFLOW_TEMPLES_KEY); you.props.erase(TEMPLE_GODS_KEY); dlua.callfn("dgn_clear_data", ""); + you.attribute[ATTR_GOLD_GENERATED] = 0; } static void _dgn_load_colour_grid() diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 187292f006a6..4006a07508c0 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1348,6 +1348,53 @@ static string _get_hatch_name() return ""; } + +static void _count_gold() +{ + vector gold_piles; + vector gold_places; + int gold = 0; + for (rectangle_iterator ri(0); ri; ++ri) + { + for (stack_iterator j(*ri); j; ++j) + { + if (j->base_type == OBJ_GOLD) + { + gold += j->quantity; + gold_piles.push_back(&(*j)); + gold_places.push_back(*ri); + } + } + } + + if (!player_in_branch(BRANCH_ABYSS)) + you.attribute[ATTR_GOLD_GENERATED] += gold; + + // TODO: this probably should fire when you join gozag, too? + if (have_passive(passive_t::detect_gold)) + { + for (unsigned int i = 0; i < gold_places.size(); i++) + { + bool detected = false; + int dummy = gold_piles[i]->index(); + coord_def &pos = gold_places[i]; + unlink_item(dummy); + move_item_to_grid(&dummy, pos, true); + if (!env.map_knowledge(pos).item() + || env.map_knowledge(pos).item()->base_type != OBJ_GOLD) + { + detected = true; + } + update_item_at(pos, true); + if (detected) + { + ASSERT(env.map_knowledge(pos).item()); + env.map_knowledge(pos).flags |= MAP_DETECTED_ITEM; + } + } + } +} + /** * Load the current level. * @@ -1594,7 +1641,11 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, } if (just_created_level) + { you.attribute[ATTR_ABYSS_ENTOURAGE] = 0; + _count_gold(); + } + if (load_mode != LOAD_VISITOR) dungeon_events.fire_event(DET_ENTERED_LEVEL); From 72233a740fad5fb5f289565d8e75641198ffba86 Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 2 Feb 2019 15:42:37 -0500 Subject: [PATCH 040/864] Better handle player position for debug/test levelgen This is another case of a bug in the tests, but not one that impacts actual levelgen. --- crawl-ref/source/dungeon.cc | 9 +++++++++ crawl-ref/source/files.cc | 3 +++ crawl-ref/source/test/vault_catalog.lua | 7 ++++--- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index b585400f853a..c705de55cfad 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -244,6 +244,15 @@ bool builder(bool enable_random_maps, dungeon_feature_type dest_stairs_type) const set uniq_tags = you.uniq_map_tags; const set uniq_names = you.uniq_map_names; + // For normal cases, this should already be taken care of by enter_level. + // However, we want to be really sure that the builder isn't ever run with + // the player at a real position on the level, e.g. during debug code or + // tests, because that can impact levelgen (somehow) and cause seed + // divergence. (I think it's because actor position can impact item gen, + // but it's a bit hard to track down.) + unwind_var saved_position(you.position); + you.position.reset(); + // Save a copy of unique creatures for vetoes. temp_unique_creatures = you.unique_creatures; // And unrands diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 4006a07508c0..92aeadf29847 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1460,6 +1460,9 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, _save_level(old_level); } + // TODO: for staged pregeneration this also needs to happen on + // LOAD_GENERATE. However, it's a bit tricky, because player position + // does need to be saved for the later LOAD_ENTER_LEVEL call. postpone. // The player is now between levels. you.position.reset(); diff --git a/crawl-ref/source/test/vault_catalog.lua b/crawl-ref/source/test/vault_catalog.lua index 6fc36dd279b6..0e1ca4406c2e 100644 --- a/crawl-ref/source/test/vault_catalog.lua +++ b/crawl-ref/source/test/vault_catalog.lua @@ -90,7 +90,7 @@ function test_seed(seed, iters, order, quiet) else crawl.stderr("Vault catalog for seed " .. seed .. ":") end - run1 = catalog_dungeon_vaults(order, quiet) + local run1 = catalog_dungeon_vaults(order, quiet) if not quiet then crawl.stderr("....now testing vault generation stability for seed " ..seed.. ".") @@ -99,14 +99,15 @@ function test_seed(seed, iters, order, quiet) for i = 1,iters do crawl.stderr(".") debug.reset_rng(seed) - run2 = catalog_dungeon_vaults(order, true) + local run2 = catalog_dungeon_vaults(order, true) compare_catalogs(order, run1, run2, seed) end end test_seed(starting_seed, per_seed_iters, generation_order, false) -- just do a quick check of hell / pan stability ---test_seed(starting_seed, per_seed_iters, generation_order_extended, true) +crawl.stderr("Checking some extended branches for seed " .. starting_seed .. "...") +test_seed(starting_seed, per_seed_iters, generation_order_extended, true) for i=starting_seed + 1, starting_seed + fixed_seeds - 2 do crawl.stderr("Testing seed " .. i .. ".") From d71c0661169dd9a84e0e710d3b33d47394db0a85 Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 2 Feb 2019 16:17:16 -0500 Subject: [PATCH 041/864] Shorten vault_catalog.lua test To try not to have to raise the timeout limit further. --- crawl-ref/source/test/vault_catalog.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/test/vault_catalog.lua b/crawl-ref/source/test/vault_catalog.lua index 0e1ca4406c2e..c5e35c68efcc 100644 --- a/crawl-ref/source/test/vault_catalog.lua +++ b/crawl-ref/source/test/vault_catalog.lua @@ -12,7 +12,7 @@ local starting_seed = 1 -- fixed seed to start with local fixed_seeds = 2 -- how many fixed seeds to run? local per_seed_iters = 1 -- how many stability tests to run per seed -local rand_seeds = 2 -- how many random seeds to run +local rand_seeds = 1 -- how many random seeds to run -- matches pregeneration order local generation_order = { From f098211c9e11aaf0211f258a0d706746b828472b Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 2 Feb 2019 21:57:18 +0000 Subject: [PATCH 042/864] Fix a pre-c++17 compilation issue This would be ok in c++17, but technically isn't before that. See: https://stackoverflow.com/questions/7411515/why-does-c-require-a-user-provided-default-constructor-to-default-construct-a http://open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#253 I guess our usual compilers aren't picky, but clang 6 on linux is. --- crawl-ref/source/decks.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/decks.cc b/crawl-ref/source/decks.cc index 03af2c183224..cb72651dde4a 100644 --- a/crawl-ref/source/decks.cc +++ b/crawl-ref/source/decks.cc @@ -128,7 +128,7 @@ struct deck_type_data string name; string flavour; /// The list of cards this deck contains. - const deck_archetype cards; + deck_archetype cards; int deck_max; }; From 330989f3788ec350c7b46bad0bcca043b3b79f2c Mon Sep 17 00:00:00 2001 From: gammafunk Date: Sun, 20 Jan 2019 21:30:01 -0600 Subject: [PATCH 043/864] Two 9x9 Gauntlet arenas One with plants arranged in an arrow pattern, and another with a double spiral having the loot at one end and the exit transporter at the other end. This brings the number of 9x9 arenas to 20, giving us a sizeable set in terms of variety. --- crawl-ref/source/dat/des/portals/gauntlet.des | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/crawl-ref/source/dat/des/portals/gauntlet.des b/crawl-ref/source/dat/des/portals/gauntlet.des index 94da29b5f937..95f0b182a1ef 100644 --- a/crawl-ref/source/dat/des/portals/gauntlet.des +++ b/crawl-ref/source/dat/des/portals/gauntlet.des @@ -472,6 +472,38 @@ n.a.a..a.an 22ddQdd22 ENDMAP +NAME: gammafunk_gauntlet_arena_arrow_garden +TAGS: gauntlet_arena_first gauntlet_arena_second allow_dup +SUBST: ~ = ^.. +: gauntlet_arena_setup(_G) +MAP +n.333n333.n +n.33xpx33.n +n.~xpPpx~.n +n~np.n.pn~n +nxp.xpx.pxn +n..xp^px..n + ^xp2n2px^ + xp2x1x2px + ddx2Q2xdd +ENDMAP + +NAME: gammafunk_gauntlet_arena_spirals +TAGS: gauntlet_arena_first gauntlet_arena_second allow_dup +SUBST: q = ^ n:190 +: gauntlet_arena_setup(_G) +MAP +nddxx....^n +ndqx.qxx^.n +ndx.xq.xx.n +n.x.x.x.x.n +n.q.qPq.q.n +n.x.x.x.x.n + .xx.qx.x. + .^xxq.xq. + ^....xxQx +ENDMAP + ############################################################################# # <<1.2>> 7x7 arenas ############################################################################# From 483b6fb38ed0ad83d6a22b0c787308d2cbaac801 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Sat, 2 Feb 2019 16:42:46 -0600 Subject: [PATCH 044/864] Incorporate net traps into Gauntlets When an arena rolls the chance to place traps, make each trap placed have a 50/50 chance between dispersal and net trap instead of 100% dispersal. --- crawl-ref/source/dat/dlua/gauntlet.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/dat/dlua/gauntlet.lua b/crawl-ref/source/dat/dlua/gauntlet.lua index 48166ede7e26..865110fb4c1c 100644 --- a/crawl-ref/source/dat/dlua/gauntlet.lua +++ b/crawl-ref/source/dat/dlua/gauntlet.lua @@ -244,7 +244,7 @@ function gauntlet_arena_terrain_setup(e, rock_unchanged, liquid, plant) else e.subst("^ : ^...") end - e.kfeat("^ = dispersal trap") + e.kfeat("^ = dispersal trap / net trap") if not plant then plant = "default" end if plant == "demonic" then From 0b2a0bf06af643a8702d225822f0744ed7401d56 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Sat, 2 Feb 2019 17:00:47 -0600 Subject: [PATCH 045/864] Don't allow multiple placements of Gauntlet arenas The commit removes the allow_dup tag from arena subvaults so that no subvault will be used more than once in a Gauntlet. Both 7x7 and 9x9 sets have over twice the number of vaults needed for all arenas in any Gauntlet map, so it's not necessary to allow reuse. Use of allow_dup dates from earlier in development of the portal when there weren't as many vaults available. --- crawl-ref/source/dat/des/portals/gauntlet.des | 94 +++++++++---------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/crawl-ref/source/dat/des/portals/gauntlet.des b/crawl-ref/source/dat/des/portals/gauntlet.des index 95f0b182a1ef..f3d4a72a5f70 100644 --- a/crawl-ref/source/dat/des/portals/gauntlet.des +++ b/crawl-ref/source/dat/des/portals/gauntlet.des @@ -168,7 +168,7 @@ default-depth: Gauntlet ############################################################################# NAME: gammafunk_gauntlet_arena_open -TAGS: gauntlet_arena_first gauntlet_arena_second allow_dup +TAGS: gauntlet_arena_first gauntlet_arena_second WEIGHT: 5 NSUBST: "' = 10=3, - = 6=2 / ^... SUBST: ' = ^..... @@ -186,7 +186,7 @@ n'''...'''n ENDMAP NAME: gammafunk_gauntlet_arena_corners -TAGS: gauntlet_arena_first gauntlet_arena_second allow_dup +TAGS: gauntlet_arena_first gauntlet_arena_second SUBST: ~ = ^.. NSUBST: ! = ^. / . : gauntlet_arena_setup(_G) @@ -203,7 +203,7 @@ n.^xx~xx^.n ENDMAP NAME: gammafunk_gauntlet_arena_hedges -TAGS: gauntlet_arena_first gauntlet_arena_second allow_dup +TAGS: gauntlet_arena_first gauntlet_arena_second SUBST: q = pp~, ~ = ^.. : gauntlet_arena_setup(_G) MAP @@ -219,7 +219,7 @@ n.qqq~qqq~n ENDMAP NAME: gammafunk_gauntlet_arena_split_x -TAGS: gauntlet_arena_first gauntlet_arena_second allow_dup +TAGS: gauntlet_arena_first gauntlet_arena_second SUBST: ~ = ^.. : gauntlet_arena_setup(_G) MAP @@ -235,7 +235,7 @@ n.^xxnxx^.n ENDMAP NAME: gammafunk_gauntlet_arena_grid -TAGS: gauntlet_arena_first gauntlet_arena_second allow_dup +TAGS: gauntlet_arena_first gauntlet_arena_second NSUBST: - = 10=3 / ^...., ' = 6=2 / ^.. : gauntlet_arena_setup(_G) MAP @@ -251,7 +251,7 @@ n-x-x-x-x-n ENDMAP NAME: gammafunk_gauntlet_arena_split_diamond -TAGS: gauntlet_arena_first gauntlet_arena_second allow_dup +TAGS: gauntlet_arena_first gauntlet_arena_second SUBST: ~ = ^.. NSUBST: ! = ^. / . : gauntlet_arena_setup(_G) @@ -268,7 +268,7 @@ n!x.....x!n ENDMAP NAME: nicolae_gauntlet_arena_t_cross -TAGS: gauntlet_arena_first gauntlet_arena_second allow_dup +TAGS: gauntlet_arena_first gauntlet_arena_second SUBST: ~ = ^.. NSUBST: P = P / ., ! = ^. / . : gauntlet_arena_setup(_G) @@ -285,7 +285,7 @@ n.n..x..n.n ENDMAP NAME: nicolae_gauntlet_arena_x -TAGS: gauntlet_arena_first gauntlet_arena_second allow_dup +TAGS: gauntlet_arena_first gauntlet_arena_second SUBST: ~ = ^.. : gauntlet_arena_setup(_G) MAP @@ -301,7 +301,7 @@ n..~x.x~..n ENDMAP NAME: nicolae_gauntlet_arena_flowing_pool -TAGS: gauntlet_arena_first gauntlet_arena_second allow_dup no_pool_fixup +TAGS: gauntlet_arena_first gauntlet_arena_second no_pool_fixup NSUBST: P = P / -, - = 10=3 / ^..., ' = 6=2 / ^.. : gauntlet_arena_setup(_G) MAP @@ -317,7 +317,7 @@ n-w-www-w-n ENDMAP NAME: nicolae_gauntlet_arena_quarters -TAGS: gauntlet_arena_first gauntlet_arena_second allow_dup +TAGS: gauntlet_arena_first gauntlet_arena_second SUBST: ~ = ^.. NSUBST: P = P / ., ! = ^. / . : gauntlet_arena_setup(_G) @@ -334,7 +334,7 @@ n.x..x..x.n ENDMAP NAME: nicolae_gauntlet_arena_blocks -TAGS: gauntlet_arena_first gauntlet_arena_second allow_dup +TAGS: gauntlet_arena_first gauntlet_arena_second SUBST: ~ = ^.. NSUBST: ! = ^. / . : gauntlet_arena_setup(_G) @@ -351,7 +351,7 @@ n..xx~xx..n ENDMAP NAME: nicolae_gauntlet_arena_grate_2 -TAGS: gauntlet_arena_first gauntlet_arena_second allow_dup +TAGS: gauntlet_arena_first gauntlet_arena_second KFEAT: qr = iron_grate NSUBST: "' = 10=3, - = 6=2 / ^.., ! = ^. / . SUBST: r = rr^, ' = ^... @@ -369,7 +369,7 @@ n---xqx...n ENDMAP NAME: nicolae_gauntlet_swirl -TAGS: gauntlet_arena_first gauntlet_arena_second allow_dup +TAGS: gauntlet_arena_first gauntlet_arena_second NSUBST: P = P / -, - = 10=3 / ., ' = 6=2 / ., ! = ^.. / . SUBST: ~ = ^. : gauntlet_arena_setup(_G) @@ -385,8 +385,8 @@ n!xx'n''''n d''dQdx'd ENDMAP -NAME: minmay_gauntlet_arena_make_your_own_arena -TAGS: gauntlet_arena_first gauntlet_arena_second allow_dup +NAME: minmay_gauntlet_arena_make_your_own_arena +TAGS: gauntlet_arena_first gauntlet_arena_second : gauntlet_arena_setup(_G) MAP n..=.P.=..n @@ -401,7 +401,7 @@ n==n...n==n ENDMAP NAME: gammafunk_gauntlet_arena_teeth -TAGS: gauntlet_arena_first gauntlet_arena_second allow_dup +TAGS: gauntlet_arena_first gauntlet_arena_second SUBST: ~ = ^... NSUBST: ! = ^. / . : gauntlet_arena_setup(_G) @@ -418,7 +418,7 @@ n.x~x~x~x.n ENDMAP NAME: gammafunk_gauntlet_arena_mazey -TAGS: gauntlet_arena_first gauntlet_arena_second allow_dup +TAGS: gauntlet_arena_first gauntlet_arena_second NSUBST: P = P / a # Ensure that at least one of the four paths is always open. SHUFFLE: qrsu @@ -437,10 +437,10 @@ n...rxxs2un a^ddQdx^x ENDMAP -NAME: gammafunk_gauntlet_arena_chambers -TAGS: gauntlet_arena_first gauntlet_arena_second allow_dup -SUBST: ~ = ^.. -NSUBST: ! = ^. / . +NAME: gammafunk_gauntlet_arena_chambers +TAGS: gauntlet_arena_first gauntlet_arena_second +SUBST: ~ = ^.. +NSUBST: ! = ^. / . : gauntlet_arena_setup(_G) MAP n333x.x333n @@ -455,7 +455,7 @@ nx..x^x..xn ENDMAP NAME: gammafunk_gauntlet_arena_crates -TAGS: gauntlet_arena_first gauntlet_arena_second allow_dup +TAGS: gauntlet_arena_first gauntlet_arena_second # At least one open path, but usually not the one adjacent to the landing site. SHUFFLE: Pq / Rr / Ss SUBST: a = ...^nn, q = ^nnn, r = .^nn, sRS = ., x = ^ x:150 @@ -473,7 +473,7 @@ n.a.a..a.an ENDMAP NAME: gammafunk_gauntlet_arena_arrow_garden -TAGS: gauntlet_arena_first gauntlet_arena_second allow_dup +TAGS: gauntlet_arena_first gauntlet_arena_second SUBST: ~ = ^.. : gauntlet_arena_setup(_G) MAP @@ -489,7 +489,7 @@ n..xp^px..n ENDMAP NAME: gammafunk_gauntlet_arena_spirals -TAGS: gauntlet_arena_first gauntlet_arena_second allow_dup +TAGS: gauntlet_arena_first gauntlet_arena_second SUBST: q = ^ n:190 : gauntlet_arena_setup(_G) MAP @@ -540,7 +540,7 @@ ENDMAP # NAME: minmay_gauntlet_arena_77_fan -TAGS: gauntlet_arena_77_first gauntlet_arena_77_second allow_dup +TAGS: gauntlet_arena_77_first gauntlet_arena_77_second : gauntlet_arena_setup(_G) MAP n2223xx3n @@ -553,7 +553,7 @@ n2^3x3nxn ENDMAP NAME: minmay_gauntlet_arena_77_two_lines -TAGS: gauntlet_arena_77_first gauntlet_arena_77_second allow_dup +TAGS: gauntlet_arena_77_first gauntlet_arena_77_second : gauntlet_arena_setup(_G) MAP n1.xx333n @@ -566,7 +566,7 @@ n22xx..3n ENDMAP NAME: minmay_gauntlet_arena_77_checkered -TAGS: gauntlet_arena_77_first gauntlet_arena_77_second allow_dup +TAGS: gauntlet_arena_77_first gauntlet_arena_77_second : gauntlet_arena_setup(_G) MAP nx2x3x2xn @@ -579,7 +579,7 @@ nx3x^x3xn ENDMAP NAME: minmay_gauntlet_arena_77_box -TAGS: gauntlet_arena_77_first gauntlet_arena_77_second allow_dup +TAGS: gauntlet_arena_77_first gauntlet_arena_77_second : gauntlet_arena_setup(_G) MAP n333333^n @@ -592,7 +592,7 @@ n2x..^x2n ENDMAP NAME: minmay_gauntlet_arena_77_double_cross -TAGS: gauntlet_arena_77_first gauntlet_arena_77_second allow_dup +TAGS: gauntlet_arena_77_first gauntlet_arena_77_second : gauntlet_arena_setup(_G) MAP n2......n @@ -605,7 +605,7 @@ n333xxx.n ENDMAP NAME: minmay_gauntlet_arena_77_museum -TAGS: gauntlet_arena_77_first gauntlet_arena_77_second allow_dup +TAGS: gauntlet_arena_77_first gauntlet_arena_77_second : gauntlet_arena_setup(_G, true) MAP n2223222n @@ -618,7 +618,7 @@ n^.p.p.^n ENDMAP NAME: minmay_gauntlet_arena_77_chump_sandwich -TAGS: gauntlet_arena_77_first gauntlet_arena_77_second allow_dup +TAGS: gauntlet_arena_77_first gauntlet_arena_77_second : gauntlet_arena_setup(_G) MAP n3322233n @@ -631,7 +631,7 @@ n.xxnxx.n ENDMAP NAME: minmay_gauntlet_arena_77_tiled_triplets -TAGS: gauntlet_arena_77_first gauntlet_arena_77_second allow_dup +TAGS: gauntlet_arena_77_first gauntlet_arena_77_second : gauntlet_arena_setup(_G) MAP n1xx2xx2n @@ -644,7 +644,7 @@ nx3nn3nxn ENDMAP NAME: minmay_gauntlet_arena_77_hold_the_fort -TAGS: gauntlet_arena_77_first gauntlet_arena_77_second allow_dup +TAGS: gauntlet_arena_77_first gauntlet_arena_77_second : gauntlet_arena_setup(_G) MAP n3333222n @@ -657,7 +657,7 @@ n.^nx.x3n ENDMAP NAME: minmay_gauntlet_arena_77_cramped -TAGS: gauntlet_arena_77_first gauntlet_arena_77_second allow_dup +TAGS: gauntlet_arena_77_first gauntlet_arena_77_second : gauntlet_arena_setup(_G) MAP nnn222nnn @@ -670,7 +670,7 @@ n3d=nn32n ENDMAP NAME: minmay_gauntlet_arena_77_p_blocks -TAGS: gauntlet_arena_77_first gauntlet_arena_77_second allow_dup +TAGS: gauntlet_arena_77_first gauntlet_arena_77_second : gauntlet_arena_setup(_G) MAP n33332xxn @@ -686,7 +686,7 @@ ENDMAP # the entry point by running clockwise around the vault. That is tedious, so the # runed door gets rid of the need for it. NAME: minmay_gauntlet_arena_77_path -TAGS: gauntlet_arena_77_first gauntlet_arena_77_second allow_dup +TAGS: gauntlet_arena_77_first gauntlet_arena_77_second : gauntlet_arena_setup(_G) MAP n222n^.Pn @@ -699,7 +699,7 @@ ndn333n3n ENDMAP NAME: minmay_gauntlet_arena_77_mirror -TAGS: gauntlet_arena_77_first gauntlet_arena_77_second allow_dup +TAGS: gauntlet_arena_77_first gauntlet_arena_77_second : gauntlet_arena_setup(_G) MAP n2221222n @@ -712,7 +712,7 @@ n3n...n3n ENDMAP NAME: minmay_gauntlet_arena_77_terracotta_army -TAGS: gauntlet_arena_77_first gauntlet_arena_77_second allow_dup +TAGS: gauntlet_arena_77_first gauntlet_arena_77_second : gauntlet_arena_setup(_G) MAP n22GxG22n @@ -725,7 +725,7 @@ nG3G^G3Gn ENDMAP NAME: minmay_gauntlet_arena_77_run_for_it -TAGS: gauntlet_arena_77_first gauntlet_arena_77_second allow_dup +TAGS: gauntlet_arena_77_first gauntlet_arena_77_second : gauntlet_arena_setup(_G) MAP n...Pn33n @@ -738,7 +738,7 @@ nnn===21n ENDMAP NAME: minmay_gauntlet_arena_77_squiggly -TAGS: gauntlet_arena_77_first gauntlet_arena_77_second allow_dup +TAGS: gauntlet_arena_77_first gauntlet_arena_77_second : gauntlet_arena_setup(_G) MAP n22222x3n @@ -751,7 +751,7 @@ n33nn..xn ENDMAP NAME: minmay_gauntlet_arena_77_radiant_squares -TAGS: gauntlet_arena_77_first gauntlet_arena_77_second allow_dup +TAGS: gauntlet_arena_77_first gauntlet_arena_77_second : gauntlet_arena_setup(_G) MAP n3332221n @@ -764,7 +764,7 @@ n.ddx3x3n ENDMAP NAME: minmay_gauntlet_arena_77_broken_ladder -TAGS: gauntlet_arena_77_first gauntlet_arena_77_second allow_dup +TAGS: gauntlet_arena_77_first gauntlet_arena_77_second : gauntlet_arena_setup(_G) MAP n3nnx333n @@ -777,7 +777,7 @@ n2nnx^.1n ENDMAP NAME: minmay_gauntlet_arena_77_shame_cube -TAGS: gauntlet_arena_77_first gauntlet_arena_77_second allow_dup +TAGS: gauntlet_arena_77_first gauntlet_arena_77_second : gauntlet_arena_setup(_G) MAP n^333333n @@ -790,7 +790,7 @@ n2nwwwn2n ENDMAP NAME: minmay_gauntlet_arena_77_mess -TAGS: gauntlet_arena_77_first gauntlet_arena_77_second allow_dup +TAGS: gauntlet_arena_77_first gauntlet_arena_77_second # there is one 3 on the map because a dispersal trap should not be on that # square NSUBST: ' = 9=3 / 6=2 / 1 / ^ / . @@ -806,7 +806,7 @@ n'n''xn'n ENDMAP NAME: minmay_gauntlet_arena_77_block_sizes -TAGS: gauntlet_arena_77_first gauntlet_arena_77_second allow_dup +TAGS: gauntlet_arena_77_first gauntlet_arena_77_second : gauntlet_arena_setup(_G) MAP n222.222n @@ -819,7 +819,7 @@ n3xnx^13n ENDMAP NAME: minmay_gauntlet_arena_77_braids -TAGS: gauntlet_arena_77_first gauntlet_arena_77_second allow_dup +TAGS: gauntlet_arena_77_first gauntlet_arena_77_second : gauntlet_arena_setup(_G) MAP n22n.n22n @@ -833,7 +833,7 @@ ENDMAP # to escape, face either the 1 or the plant NAME: minmay_gauntlet_arena_77_two_paths -TAGS: gauntlet_arena_77_first gauntlet_arena_77_second allow_dup +TAGS: gauntlet_arena_77_first gauntlet_arena_77_second : gauntlet_arena_setup(_G) MAP n222.222n From a05850b26e5e1c75f415ce13592631dd0bf54aba Mon Sep 17 00:00:00 2001 From: gammafunk Date: Sat, 2 Feb 2019 17:51:14 -0600 Subject: [PATCH 046/864] Add monsters to a Gauntlet arena Oops, forgot the monsters! --- crawl-ref/source/dat/des/portals/gauntlet.des | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/crawl-ref/source/dat/des/portals/gauntlet.des b/crawl-ref/source/dat/des/portals/gauntlet.des index f3d4a72a5f70..e6da985870af 100644 --- a/crawl-ref/source/dat/des/portals/gauntlet.des +++ b/crawl-ref/source/dat/des/portals/gauntlet.des @@ -493,15 +493,15 @@ TAGS: gauntlet_arena_first gauntlet_arena_second SUBST: q = ^ n:190 : gauntlet_arena_setup(_G) MAP -nddxx....^n -ndqx.qxx^.n -ndx.xq.xx.n -n.x.x.x.x.n -n.q.qPq.q.n -n.x.x.x.x.n - .xx.qx.x. - .^xxq.xq. - ^....xxQx +nddxx..33^n +ndqx.qxx^3n +ndx.xq.xx3n +n1x.x.x.x3n +n2q.qPq.q2n +n2x.x.x.x2n + 2xx.qx.x2 + 3^xxq.xq1 + ^3333xxQx ENDMAP ############################################################################# From a65fc5ffcd898337229e2b8d6ecf546748c7a51f Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 2 Feb 2019 22:47:52 -0500 Subject: [PATCH 047/864] Avoid a few cases of random tags in the .des cache These tags are set at builddb time, and saved in the cache, which probably isn't what anyone wants. They also impacts seed stability: these pan entry maps were either tagged with `luniq_hellpanabyss_threat_entry` in the cache or not depending on a random choice when the .des cache was first built, which then causes seed divergence between systems depending on what decision was initially made. This is far from the only kind of case where random decisions appear to be made during validation that might be getting saved in the cache, but it's the only one I've seen so far that's actually leading to divergence. Another kind of case is exemplified by `lemuel_altar_in_water`, where the tags are chosen randomly; but what seems to be happening for the cache is that the vault is parsed without running the lua and the initial tag set is drawn from this. I don't have a lot of confidence that what would happen with this map is correct, but at least it wouldn't lead to seed divergence. --- crawl-ref/docs/develop/rng_guidelines.md | 9 ++++++++- crawl-ref/source/dat/des/branches/pan.des | 2 ++ crawl-ref/source/dat/des/builder/alphashops.des | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/crawl-ref/docs/develop/rng_guidelines.md b/crawl-ref/docs/develop/rng_guidelines.md index f08b667aae82..181a5bb6a0a0 100644 --- a/crawl-ref/docs/develop/rng_guidelines.md +++ b/crawl-ref/docs/develop/rng_guidelines.md @@ -56,7 +56,7 @@ specific to a single commit. Similarly, upgrading a game (trunk or otherwise) where the dungeon is not pregenerated will lead to divergence from *both* seed to dungeon mappings. -## 2.1. Detecting seed divergence +## 2.1. Detecting unwanted seed divergence Detecting this can be quite hard, but there are a few built-in tests that run in Travis CI and can be run locally. These are `d1_vaults.lua` (which prints @@ -190,6 +190,13 @@ in the array is not important, you can use `lua_next` with a vector and Don't use other sources of randomization in crawl besides crawl RNGs. For example, don't use lua's `math.rand`, or C stdlib's `rand`. +### 3.4. Keeping the .des cache stable + +Try to avoid vault design elements that will lead to variable .des caches; any +random choices made here will be outside of levelgen rng, and potentially +set at the time the player first opens crawl. Especially try to avoid +determining a set of tags for a map randomly using lua `tags` calls. + ## 4. Dealing with seed divergence Seed divergence is when the same seed, with the same generation order, leads to diff --git a/crawl-ref/source/dat/des/branches/pan.des b/crawl-ref/source/dat/des/branches/pan.des index 586b4ae48483..de8a70890656 100644 --- a/crawl-ref/source/dat/des/branches/pan.des +++ b/crawl-ref/source/dat/des/branches/pan.des @@ -196,7 +196,9 @@ function pan_entry_vault_contents(e, glyph) e.tags("patrolling no_monster_gen nolayout_encompass") e.mons("common demon / base demonspawn w:2") e.mons("lesser demon") + if e.is_validating() then return end if crawl.x_chance_in_y(you.depth() + 3, you.depth() + 5) then + crawl.mpr("applying luniq_hellpanabyss_threat_entry") e.tags("luniq_hellpanabyss_threat_entry") e.kmons(glyph .. " = green death / blizzard demon / balrug / " .. " cacodemon / hell beast / hellion / reaper / " diff --git a/crawl-ref/source/dat/des/builder/alphashops.des b/crawl-ref/source/dat/des/builder/alphashops.des index 07debf255160..594d91aca948 100644 --- a/crawl-ref/source/dat/des/builder/alphashops.des +++ b/crawl-ref/source/dat/des/builder/alphashops.des @@ -214,6 +214,7 @@ WEIGHT: 5 # items or place itemcount items, whichever is less, where itemcount is # the number of item types. {{ +if is_validating() then return end local letter = pickletter() local itemlist = shopcontents(letter) local itemcount = #itemlist From 8d21aed9eeb4081db507b29ba81e87616fc569f5 Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 2 Feb 2019 22:55:59 -0500 Subject: [PATCH 048/864] Remove accidental debug message --- crawl-ref/source/dat/des/branches/pan.des | 1 - 1 file changed, 1 deletion(-) diff --git a/crawl-ref/source/dat/des/branches/pan.des b/crawl-ref/source/dat/des/branches/pan.des index de8a70890656..7d64ed68989b 100644 --- a/crawl-ref/source/dat/des/branches/pan.des +++ b/crawl-ref/source/dat/des/branches/pan.des @@ -198,7 +198,6 @@ function pan_entry_vault_contents(e, glyph) e.mons("lesser demon") if e.is_validating() then return end if crawl.x_chance_in_y(you.depth() + 3, you.depth() + 5) then - crawl.mpr("applying luniq_hellpanabyss_threat_entry") e.tags("luniq_hellpanabyss_threat_entry") e.kmons(glyph .. " = green death / blizzard demon / balrug / " .. " cacodemon / hell beast / hellion / reaper / " From 0ecae65ed9e9f7d57e197c12488300faa8ee64ca Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Sat, 2 Feb 2019 22:50:54 -0500 Subject: [PATCH 049/864] Convert mummy death curses to a fineff (11758) This ensures that when a monster is killed by Grand Finale the death curse effects all land on the killer. --- crawl-ref/source/fineff.cc | 60 +++++++++++++++++++++++++++++++ crawl-ref/source/fineff.h | 20 +++++++++++ crawl-ref/source/mon-death.cc | 66 ++++------------------------------- 3 files changed, 87 insertions(+), 59 deletions(-) diff --git a/crawl-ref/source/fineff.cc b/crawl-ref/source/fineff.cc index 18472d2968d7..da87cf80a48b 100644 --- a/crawl-ref/source/fineff.cc +++ b/crawl-ref/source/fineff.cc @@ -26,7 +26,9 @@ #include "mon-place.h" #include "ouch.h" #include "religion.h" +#include "spl-miscast.h" #include "state.h" +#include "stringutil.h" #include "terrain.h" #include "transform.h" #include "view.h" @@ -579,6 +581,64 @@ void make_derived_undead_fineff::fire() } } +void mummy_death_curse_fineff::fire() +{ + if (pow <= 0) + return; + + switch (killer) + { + // Mummy killed by trap or something other than the player or + // another monster, so no curse. + case KILL_MISC: + case KILL_RESET: + case KILL_DISMISSED: + // Mummy sent to the Abyss wasn't actually killed, so no curse. + case KILL_BANISHED: + return; + + default: + break; + } + + actor * victim; + + if (YOU_KILL(killer)) + victim = &you; + // Killed by a Zot trap, a god, etc, or suicide. + else if (!attacker() || attacker() == defender()) + return; + else + victim = attacker(); + + // Mummy was killed by a ballistomycete spore or ball lightning? + if (!victim->alive()) + return; + + // Mummies are smart enough not to waste curses on summons or allies. + if (victim->is_monster() && victim->as_monster()->friendly() + && !crawl_state.game_is_arena()) + { + victim = &you; + } + + // Stepped from time? + if (!in_bounds(victim->pos())) + return; + + if (victim->is_player()) + mprf(MSGCH_MONSTER_SPELL, "You feel extremely nervous for a moment..."); + else if (you.can_see(*victim)) + { + mprf(MSGCH_MONSTER_SPELL, "A malignant aura surrounds %s.", + victim->name(DESC_THE).c_str()); + } + const string cause = make_stringf("%s death curse", + apostrophise(name).c_str()); + MiscastEffect(victim, nullptr, {miscast_source::mummy}, spschool::necromancy, + pow, random2avg(88, 3), cause.c_str()); +} + // Effects that occur after all other effects, even if the monster is dead. // For example, explosions that would hit other creatures, but we want // to deal with only one creature at a time, so that's handled last. diff --git a/crawl-ref/source/fineff.h b/crawl-ref/source/fineff.h index 84a1081b2a50..e369124b5cac 100644 --- a/crawl-ref/source/fineff.h +++ b/crawl-ref/source/fineff.h @@ -362,4 +362,24 @@ class make_derived_undead_fineff : public final_effect string message; }; +class mummy_death_curse_fineff : public final_effect +{ +public: + bool mergeable(const final_effect &a) const override { return false; } + void fire() override; + + static void schedule(const actor * attack, string name, killer_type killer, int pow) + { + final_effect::schedule(new mummy_death_curse_fineff(attack, name, killer, pow)); + } +protected: + mummy_death_curse_fineff(const actor * attack, string _name, killer_type _killer, int _pow) + : final_effect(attack, 0, coord_def()), name(_name), killer(_killer), pow(_pow) + { + } + string name; + killer_type killer; + int pow; +}; + void fire_final_effects(); diff --git a/crawl-ref/source/mon-death.cc b/crawl-ref/source/mon-death.cc index 3f502eac10e0..1ee8e993227a 100644 --- a/crawl-ref/source/mon-death.cc +++ b/crawl-ref/source/mon-death.cc @@ -1001,64 +1001,6 @@ int mummy_curse_power(monster_type type) } } -static void _mummy_curse(monster* mons, int pow, killer_type killer, int index) -{ - if (pow <= 0) - return; - - switch (killer) - { - // Mummy killed by trap or something other than the player or - // another monster, so no curse. - case KILL_MISC: - case KILL_RESET: - case KILL_DISMISSED: - // Mummy sent to the Abyss wasn't actually killed, so no curse. - case KILL_BANISHED: - return; - - default: - break; - } - - actor* target; - - if (YOU_KILL(killer)) - target = &you; - // Killed by a Zot trap, a god, etc, or suicide. - else if (invalid_monster_index(index) || index == mons->mindex()) - return; - else - target = &menv[index]; - - // Mummy was killed by a ballistomycete spore or ball lightning? - if (!target->alive()) - return; - - // Mummies are smart enough not to waste curses on summons or allies. - if (target->is_monster() && target->as_monster()->friendly() - && !crawl_state.game_is_arena()) - { - target = &you; - } - - // Stepped from time? - if (!in_bounds(target->pos())) - return; - - if (target->is_player()) - mprf(MSGCH_MONSTER_SPELL, "You feel extremely nervous for a moment..."); - else if (you.can_see(*target)) - { - mprf(MSGCH_MONSTER_SPELL, "A malignant aura surrounds %s.", - target->name(DESC_THE).c_str()); - } - const string cause = make_stringf("%s death curse", - apostrophise(mons->name(DESC_A)).c_str()); - MiscastEffect(target, mons, {miscast_source::mummy}, spschool::necromancy, - pow, random2avg(88, 3), cause.c_str()); -} - template static void _search_dungeon(const coord_def & start, valid_T & valid_target, @@ -2676,7 +2618,13 @@ item_def* monster_die(monster& mons, killer_type killer, treant_release_fauna(mons); } else if (!mons.is_summoned() && mummy_curse_power(mons.type) > 0) - _mummy_curse(&mons, mummy_curse_power(mons.type), killer, killer_index); + { + mummy_death_curse_fineff::schedule( + actor_by_mid(killer_index), + mons.name(DESC_A), + killer, + mummy_curse_power(mons.type)); + } // Necromancy if (!was_banished && !mons_reset) From 542e47cbc9512dcb73fa3414a4132c64cf2fc3d3 Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 3 Feb 2019 10:45:19 -0500 Subject: [PATCH 050/864] Update the "seeded play" section of the manual --- crawl-ref/docs/crawl_manual.rst | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/crawl-ref/docs/crawl_manual.rst b/crawl-ref/docs/crawl_manual.rst index 4d8105de56e5..f14a277888a5 100644 --- a/crawl-ref/docs/crawl_manual.rst +++ b/crawl-ref/docs/crawl_manual.rst @@ -468,25 +468,31 @@ Seeded play ======================================== Crawl dungeons are determined by a "seed" number used to initialise the game's -random number generator. If you initialise the game with the same seed, you -will (within certain parameters) get the same dungeon. In offline games you can -view your game's seed with '?V' as well as in a character file; in online games -you normally must finish a game in order to see the game's seed. There are two -seeded modes: +random number generator. If you initialise the game, keeping the game version +constant, then the same seed should (within certain parameters) lead to the same +dungeon. In offline games you can view your game's seed with '?V' as well as in +a character file; in online games you normally must finish a game in order to +see the game's seed. There are two seeded modes: Without dungeon pregeneration ('pregen_dungeon = false') If dungeon pregeneration is turned off (the default), every game with the same seed will have at least the same initial dungeon level and temple layout. However, the order in which you explore levels after the first one - can lead to multiple possible dungeon layouts, depending on your choices. + can lead to multiple possible dungeon layouts, depending on your choices. This + is implicitly how dungeon generation always worked before version 0.23. With dungeon pregeneration ('pregen_dungeon = true') If dungeon pregeneration is turned on, the entire connected dungeon will be determined by the game seed. Portal vaults and chaotic zones such as the abyss are not guaranteed to be the same, though. -To set a game seed, use the 'game_seed' option, or the '-seed' command line -option. +To set a game seed, use the 'game_seed' rc file option, or the '-seed' command +line option. + +If you find that the same seed generates distinct parts of a dungeon on the +same or different devices, please report it as a bug. However, keep in mind +that upgrading your save game between multiple versions of crawl, or traversing +dungeon levels in different orders, will naturally lead to seed divergence. Further Help ======================================== From fe1993f7db78e312351b594bfaee628969cd787d Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 3 Feb 2019 10:47:01 -0500 Subject: [PATCH 051/864] Update seeding notes on changelog --- crawl-ref/docs/changelog.txt | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/crawl-ref/docs/changelog.txt b/crawl-ref/docs/changelog.txt index 2ebf3fbe6719..4f9fa90228cc 100644 --- a/crawl-ref/docs/changelog.txt +++ b/crawl-ref/docs/changelog.txt @@ -27,13 +27,20 @@ Branches, Environment * Layouts: - Concentric octagons is enabled for Lair. - Cave pools (with adjusted parameters) is enabled for the Dungeon. -* Translucent doors that can bee seen through when closed have been added and +* Translucent doors that can be seen through when closed have been added and are now used in Elf layouts and some vaults, including most runed door vaults. -* The dungeon RNG has been separated from the gameplay RNG +* The dungeon RNG has been separated from the gameplay RNG, for better + "deterministic randomness". Each game seed should now generate a unique + dungeon (including layout, monster placement, and item placement), and that + seed should always generate the same dungeon, for the same version + of crawl, as long as levels are generated in the same order. If you find + otherwise, that now counts as a bug! * A new option for pregenerating the entire connected dungeon based on a fixed - seed has been added. This option is not yet available for online play, but - can be used offline. See the manual section "Seeded play" for details. + seed has been added. This takes a bit of time, but ensures that any + playthroughs of a particular seed will (bugs aside) use the same dungeon. + This option is not yet available for online play, but can be used offline. + See the manual section "Seeded play" for details. Character --------- From a7f21a457d5d3fcce18c1772dd5d7c1b4b9e22b1 Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 3 Feb 2019 11:23:01 -0500 Subject: [PATCH 052/864] Update copyright date --- crawl-ref/source/ng-input.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/ng-input.cc b/crawl-ref/source/ng-input.cc index 0f23d27942b5..da7263a8a329 100644 --- a/crawl-ref/source/ng-input.cc +++ b/crawl-ref/source/ng-input.cc @@ -21,7 +21,7 @@ string opening_screen() { string msg = "Hello, welcome to " CRAWL " " + string(Version::Long) + "!\n" - "(c) Copyright 1997-2002 Linley Henzell, 2002-2018 Crawl DevTeam\n" + "(c) Copyright 1997-2002 Linley Henzell, 2002-2019 Crawl DevTeam\n" "Read the instructions for legal details. "; From b1230d1836c2548f02ce8f6998c46725678f3144 Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Sun, 3 Feb 2019 10:38:14 +0000 Subject: [PATCH 053/864] Update tutorial, fix tutorial/hints mode skill menu text (11851) Update a traps message that stated traps aren't always revealed, and a berserk hunger message that stated you can't berserk while very hungry; this restriction is now limited to near starving or worse. Shorten the "Read skill descriptions" button description to "Skill descriptions" to avoid this overlapping the text on the following line. --- crawl-ref/source/dat/descript/tutorial.txt | 11 ++++++----- crawl-ref/source/skill-menu.cc | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/crawl-ref/source/dat/descript/tutorial.txt b/crawl-ref/source/dat/descript/tutorial.txt index 6766379f9203..9718a7832fe2 100644 --- a/crawl-ref/source/dat/descript/tutorial.txt +++ b/crawl-ref/source/dat/descript/tutorial.txt @@ -371,9 +371,10 @@ of the screen. Rereading old messages with tutorial3 trap Traps can have a variety of unpleasant effects, such as alerting monsters or -teleporting you into danger. They will often be hidden until you discover them -by stepping on them. If there's no way around, you'll have to trigger the trap -and deal with the consequences. +teleporting you into danger. Some traps are permanent and will always be +revealed as part of the map, but other traps can be triggered by exploring new +tiles, and won't exist after being triggered. If there's no way around, you'll +have to trigger the trap and deal with the consequences. %%%% tutorial3 potion @@ -701,8 +702,8 @@ again. %%%% tutorial5 hunger -Berserking also causes a large amount of hunger. You cannot berserk while very -hungry, so you should always carry some food with you. +Berserking also causes a large amount of hunger. You cannot berserk while near +starving, so you should always carry some food with you. %%%% tutorial5 berserk2 diff --git a/crawl-ref/source/skill-menu.cc b/crawl-ref/source/skill-menu.cc index 2741dbd05b6b..e4bc900b17ad 100644 --- a/crawl-ref/source/skill-menu.cc +++ b/crawl-ref/source/skill-menu.cc @@ -1440,7 +1440,7 @@ void SkillMenu::refresh_button_row() const string helpstring = "[?] "; const string azstring = "[a-z] "; - string legend = is_set(SKMF_SIMPLE) ? "Read skill descriptions" : "Help"; + string legend = is_set(SKMF_SIMPLE) ? "Skill descriptions" : "Help"; string midlegend = ""; string clearlegend = ""; if (is_set(SKMF_HELP)) From 687177df5249d8a1f06513734e373c1066ce92ba Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Sun, 3 Feb 2019 16:29:33 -0500 Subject: [PATCH 054/864] Add cost and training targets info to hints mode --- crawl-ref/source/hints.cc | 34 ++++++++++++++++++++++++++++++++-- crawl-ref/source/hints.h | 2 ++ crawl-ref/source/skill-menu.cc | 8 +++++++- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/hints.cc b/crawl-ref/source/hints.cc index bc8548ddfb85..4621153f4806 100644 --- a/crawl-ref/source/hints.cc +++ b/crawl-ref/source/hints.cc @@ -2735,8 +2735,9 @@ string hints_skills_info() text << "<" << colour_to_str(channel_to_colour(MSGCH_TUTORIAL)) << ">"; string broken = "This screen shows the skill set of your character. " "The number next to the skill is your current level, the higher the " - "better. The brown percent value shows how much " - "experience is allocated to go towards that skill. " + "better. Training displays training percentages. " + "Costs displays relative training costs. " + "Targets displays skill training targets. " "You can toggle which skills to train by " "pressing their slot letters. A grey skill " "will not be trained and ease the training of others."; @@ -2762,6 +2763,35 @@ string hints_skill_training_info() return text.str(); } +string hints_skill_costs_info() +{ + textcolour(channel_to_colour(MSGCH_TUTORIAL)); + ostringstream text; + text << "<" << colour_to_str(channel_to_colour(MSGCH_TUTORIAL)) << ">"; + string broken = "The training cost (in cyan) " + "shows the experience cost to raise the given skill one level, " + "relative to the cost of raising an aptitude zero skill from level " + "zero to level one."; + text << broken; + text << ""; + + return text.str(); +} + +string hints_skill_targets_info() +{ + textcolour(channel_to_colour(MSGCH_TUTORIAL)); + ostringstream text; + text << "<" << colour_to_str(channel_to_colour(MSGCH_TUTORIAL)) << ">"; + string broken = "Press the letter of a skill to set a training target. " + "When the target is reached a message will appear and " + "the training of the skill will be disabled."; + text << broken; + text << ""; + + return text.str(); +} + string hints_skills_description_info() { textcolour(channel_to_colour(MSGCH_TUTORIAL)); diff --git a/crawl-ref/source/hints.h b/crawl-ref/source/hints.h index 7b34e006486e..6ad7c21f9754 100644 --- a/crawl-ref/source/hints.h +++ b/crawl-ref/source/hints.h @@ -173,6 +173,8 @@ void learned_something_new(hints_event_type seen_what, formatted_string hints_abilities_info(); string hints_skills_info(); string hints_skill_training_info(); +string hints_skill_costs_info(); +string hints_skill_targets_info(); string hints_skills_description_info(); string hints_memorise_info(); diff --git a/crawl-ref/source/skill-menu.cc b/crawl-ref/source/skill-menu.cc index e4bc900b17ad..ddd05c2ec391 100644 --- a/crawl-ref/source/skill-menu.cc +++ b/crawl-ref/source/skill-menu.cc @@ -652,7 +652,10 @@ string SkillMenuSwitch::get_help() return "The percentage of incoming experience used" " to train each skill is in brown.\n"; case SKM_VIEW_TARGETS: - return "The current training targets, if any.\n"; + if (skm.is_set(SKMF_SIMPLE)) + return hints_skill_targets_info(); + else + return "The current training targets, if any.\n"; case SKM_VIEW_PROGRESS: return "The percentage of the progress done before reaching next " "level is in cyan.\n"; @@ -662,6 +665,9 @@ string SkillMenuSwitch::get_help() "knowledge. The donating skill is marked with *."; case SKM_VIEW_COST: { + if (skm.is_set(SKMF_SIMPLE)) + return hints_skill_costs_info(); + string result = "The relative cost of raising each skill is in " "cyan"; From 776a2178cb1acffbf3931b979cb8b1f09436bca9 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Sun, 3 Feb 2019 16:30:06 -0500 Subject: [PATCH 055/864] Display the SEEN_RANDART hint only for randarts --- crawl-ref/source/items.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/items.cc b/crawl-ref/source/items.cc index db3b47bfe555..a09d5e31e212 100644 --- a/crawl-ref/source/items.cc +++ b/crawl-ref/source/items.cc @@ -2127,7 +2127,7 @@ static int _place_item_in_free_slot(item_def &it, int quant_got, if (crawl_state.game_is_hints()) { taken_new_item(item.base_type); - if (is_artefact(item) || get_equip_desc(item) != ISFLAG_NO_DESC) + if (is_artefact(item)) learned_something_new(HINT_SEEN_RANDART); } From 853fe2ed08124fbf7aaadc910457305d4bdaeb22 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Sun, 3 Feb 2019 18:28:56 -0500 Subject: [PATCH 056/864] Give a friendly fire warning for exploding portal projectiles (11315) --- crawl-ref/source/throw.cc | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/crawl-ref/source/throw.cc b/crawl-ref/source/throw.cc index 01344be6b97f..def9a5552c0d 100644 --- a/crawl-ref/source/throw.cc +++ b/crawl-ref/source/throw.cc @@ -13,6 +13,7 @@ #include "artefact.h" #include "chardump.h" #include "command.h" +#include "coordit.h" #include "directn.h" #include "english.h" #include "env.h" @@ -848,6 +849,18 @@ bool throw_it(bolt &pbolt, int throw_2, dist *target) monster *m = monster_at(thr.target); if (m) cancelled = stop_attack_prompt(m, false, thr.target); + + if (!cancelled /*&& pbolt.is_explosion*/) + { + for (adjacent_iterator ai(thr.target); ai; ++ai) + { + if (cancelled) + break; + monster *am = monster_at(*ai); + if (am) + cancelled = stop_attack_prompt(am, false, *ai); + } + } } else { From 8f193879509a2a63ef9300d2934c7767fe75297d Mon Sep 17 00:00:00 2001 From: gammafunk Date: Sun, 3 Feb 2019 18:02:20 -0600 Subject: [PATCH 057/864] Updates to the changelog Add release highlights, simplify wording to decrease length, reorganizing listings in each section roughly in order of importance, and give the seeded play details its own indented list. This should bring the changelog close to a state that's ready for the release. --- crawl-ref/docs/changelog.txt | 159 ++++++++++++++++++----------------- 1 file changed, 84 insertions(+), 75 deletions(-) diff --git a/crawl-ref/docs/changelog.txt b/crawl-ref/docs/changelog.txt index 4f9fa90228cc..4fcb2f7bfb88 100644 --- a/crawl-ref/docs/changelog.txt +++ b/crawl-ref/docs/changelog.txt @@ -1,5 +1,13 @@ -Stone Soup 0.23 (up to 0.23-a0-899-gbbae0a335a) ------------------------------------------------ +Stone Soup 0.23 (up to 0.23-b1-56-gfe314ee208) +---------------------------------------------- + +Highlights +---------- +* Trap system rework +* New Gauntlet portal to replace Labyrinths +* Nemelex Xobeh rework +* Nine unrandarts reworked and the new "Rift" unrandart added +* Supported for seeded dungeon play Branches, Environment --------------------- @@ -8,60 +16,51 @@ Branches, Environment - Exploration has a chance to trigger a "trap effect" independent from terrain traps. The possible effects are alarm, shaft, and teleport near monsters. - - Alarm traps only trigger in LOS, and always Mark the player when - triggered. + - Monsters only trigger traps in sight of the player. + - Alarm traps now always Mark the player whenever they are triggered in LOS. - Net traps now try to net the player whenever they are triggered in LOS. - New trap: dispersal trap. When triggered, every actor in sight of the trap is blinked. - - Mechanical traps save for net traps have been removed from Tomb and the - Hall of Zot on Zot:5, and traps have been adjusted in many Ossuaries. - - Grate traps (triggered by Lua pressure plates) have been removed. + - Trap placement in Ossuaries, Zot:5, and Tomb has been overhauled. In Zot:5 + and Tomb, all mechanical traps save for net traps have been removed. + - Grate traps (triggered by pressure plates) have been removed. * A new Gauntlet portal that replaces Labyrinths: - Gauntlets have the player choose a path through several combat arenas, each of which contains (sometimes exotic) monsters and loot. - - Arena access is one-way using transporters, and teleports are disabled. - - All paths lead to the minotaur who guards the exit and a pile of treasure. + - Access to each arena is one-way using transporters. Teleports and Passage + of Golubria are disabled. + - All paths lead to a minotaur who guards a pile of treasure and the exit. - Gauntlets are found where Labyrinths previously generated. -* New early vaults featuring thematic item shops and monsters guarding - manuals, as well as new ghost vaults for many branches. -* Layouts: - - Concentric octagons is enabled for Lair. - - Cave pools (with adjusted parameters) is enabled for the Dungeon. -* Translucent doors that can be seen through when closed have been added and - are now used in Elf layouts and some vaults, including most runed door - vaults. -* The dungeon RNG has been separated from the gameplay RNG, for better - "deterministic randomness". Each game seed should now generate a unique - dungeon (including layout, monster placement, and item placement), and that - seed should always generate the same dungeon, for the same version - of crawl, as long as levels are generated in the same order. If you find - otherwise, that now counts as a bug! -* A new option for pregenerating the entire connected dungeon based on a fixed - seed has been added. This takes a bit of time, but ensures that any - playthroughs of a particular seed will (bugs aside) use the same dungeon. - This option is not yet available for online play, but can be used offline. - See the manual section "Seeded play" for details. +* Support for seeded play: + - A new option for pregenerating the entire connected dungeon based on a fixed + seed has been added. This takes a bit of time, but ensures that any + playthroughs of a particular seed will use the same dungeon. + - This option is not yet available for online play, but can be used offline. + See the manual section "Seeded play" for details. + - The dungeon RNG has been separated from the gameplay RNG to allow this + feature to work. + - Each game seed generates a unique dungeon (including layout and + monster and item placement) that is always the same for the same version + of crawl, as long as levels are generated in the same order. + - If you see that two games with the same seed generate a different dungeon, + please report this as a bug! +* New vaults: early thematic item shops and monsters guarding manuals, as well + as new ghost vaults for many branches. +* Translucent doors that can be seen through when closed have been added. + These are used in most runed door vaults and in some Elf layouts. +* Two new dungeon layouts enabled, one for Dungeon and one for Lair. Character --------- -* Wanderer starting spell libraries are announced along with equipment. -* Wanderers that start with exactly one level 1 spell start with it memorized. * The player can no longer be put to sleep when paralyzed or petrified. -* Tengu EV bonuses are no longer applied to +EV from equipment. * Tengu Permanent Flight becomes immediately available at XL 5. +* Tengu EV bonuses are no longer applied to +EV from equipment. +* Wanderer starting spell libraries are announced along with equipment. +* Wanderers that start with exactly one level 1 spell start with it memorized. Gods ---- -* Monster conversion for Beogh, Gozag's Bribe, and Jiyva is attempted upon - sight instead of on the turn after the monster enters LOS. -* The acid damage from Makhleb's Minor Destruction has been reduced. -* Elyvilon's Heal Other's is adjusted: - - The formula depends only on monster type, not specific monster maxhp. - - Player Ghosts and Pandemonium Lords are now immune. - - The targeter displays the pacification chance. -* Exploration-based piety is no longer granted for the Temple, deep water, or - lava. -* Nemelex Xobeh's decks are moved into an abstract abilities: +* Nemelex Xobeh has been reworked: - Decks are are accessed through abilities and no longer exist as items. - Nemelex offers three abilities: "Draw Escape", "Draw Destruction", and "Draw Summoning", which provide card effects. @@ -78,19 +77,26 @@ Gods with a chance proportional to power. - The Storm card has been revised. It now performs a wind blast followed by one to nine electrical explosions. -* Ashenzari protects followers from exploration based trap effects. +* Elyvilon's Heal Other's is adjusted: + - The formula depends only on monster type, not specific monster maxhp. + - Player Ghosts and Pandemonium Lords are now immune. + - The targeter displays the pacification chance. +* Ashenzari protects followers from exploration-based trap effects. * Qazlal's cloud immunity is extended to elementals created with Elemental Force. +* Fedhas' protection of plants from player spells is extended to LOS-wide + attack spells. +* The acid damage from Makhleb's Minor Destruction has been reduced. +* Exploration-based piety is no longer granted for the Temple, deep water, or + lava. +* Monster conversion for Beogh, Gozag's Bribe, and Jiyva is attempted upon + sight instead of on the turn after the monster enters LOS. Interface --------- -* The Hepliakqana ancestor reaching full health interrupts resting. The exact - behavior of this interrupt can be configured by rest_wait_ancestor. -* WebTiles users can use a "Forgot Password" link to reset their password - via a link sent to their registration email address. This feature is not yet - enabled on most official servers. -* The new display_chars cloud_weak, cloud_fading, and cloud_terminal indicate - remaining cloud duration in console. +* Spell damage message punctuation has been adjusted to reflect damage done + using the same scale as melee damage. +* Damage brand message punctuation has been similarly adjusted. * Monster descriptions in 'xv' display spell ranges. * The Religion screen '^' gains a fourth pane for gods that need Extra information: @@ -100,37 +106,41 @@ Interface - Hepliaklqana displays ancestor upgrades. - Nemelex Xobeh displays deck information. - Wu Jian displays information about martial attacks. -* Spell damage message punctuation has been adjusted to reflect damage done - using the same scale as melee damage. -* Damage brand message punctuation has been similarly adjusted. +* The Hepliakqana ancestor reaching full health interrupts resting. The exact + behavior of this interrupt can be configured by rest_wait_ancestor. +* The new display_chars cloud_weak, cloud_fading, and cloud_terminal indicate + remaining cloud duration in console. +* WebTiles users can use a "Forgot Password" link to reset their password + via a link sent to their registration email address. This feature is not yet + enabled on most official servers. Items ----- -* Stash search can now search by handedness. -* Butchering a corpse always leaves a skeleton. -* Wand charges for wands of digging, enslavement, flame, paralysis, polymorph, - and random effects have been reduced. -* The blowgun targeter now displays the chance to affect the target. -* Unrandarts: - - The Singing Sword is now vorpal, and its sonic damage effect is stronger - and triggers on-hit instead of while wielded. - - The Spriggan's Knife loses Dex+4 and MR+ and converts all stabs to - sleep-tier stabs. - - The robe of Misfortune is now identified, and is +5 {*Contam *Corrode - *Drain Harm *Slow and EV+5}. - - The sceptre of Torment is now a +7 eveningstar of pain, and its torment +* Unrandart changes: + - New Unrand: the +8 demon trident "Rift" {distort, reach+}. A distortion + demon trident with a reaching range of 3 and smite-targeted attack. + - The Singing Sword's sonic damage effect is stronger, can trigger at low + tension, and triggers only on-hit. It also gains the vorpal brand. + - The Spriggan's Knife converts all stabs to sleep-tier stabs and loses + Dex+4 and MR+. + - The Robe of Misfortune is +5 {*Contam *Corrode *Drain Harm *Slow EV+5} and + is now always identified. + - The Sceptre of Torment is now a +7 eveningstar of pain, and its torment does not affect the wielder. - - The arc blade's effect now casts static discharge only once, but at very - high spellpower. The weapon's enchantment is now +8. - - Finisher loses Str+3 and gains a chance to instant-explode the target. + - The Arc Blade's effect now casts static discharge only once at very high + spellpower. The weapon's enchantment is now +8. + - Finisher gains a chance to instant-explode the target and loses Str+3. + - The Robe of Clouds is now +3 {+Thunder rCloud rElec}, providing evocable + storm clouds in place of its old mist. + - The Skin of Zhor gains a passive Metabolic Englaciation effect and SInv. + - The Storm Bow no longer occasionally creates rain clouds. - Unrandarts with melee effects that could anger nearby allies give a proper warning. - - The robe of Clouds is now +3 {+Thunder rCloud rElec}, providing evocable - storm clouds in place of its old mist. - - The storm bow no longer occasionally creates rain clouds. - - The skin of Zhor gains SInv and a passive Metabolic Englaciation effect. - - New Unrand: the +8 demon trident "Rift" {distort, reach+}. A distortion - demon trident with a reaching range of 3 and smite targeted attack. +* Wand charges for wands of digging, enslavement, flame, paralysis, polymorph, + and random effects have been reduced. +* Butchering a corpse always leaves a skeleton. +* The blowgun targeter now displays the chance to affect the target. +* Stash search can now search by handedness. Lua --- @@ -156,7 +166,6 @@ Monsters charmed/uncharmed, pacified, or slimified. * Confused monsters now get a 1 in 3 chance to move normally, like players do. * Giant monsters no longer tear through webs. -* Monsters only trigger traps in sight of the player. Spells ------ From ac335f24217d1dbecfc928e1ca9d6b6301d59fda Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Sun, 3 Feb 2019 23:11:59 -0500 Subject: [PATCH 058/864] Display bazaar items at the top of the shopping list (11649) A player in a Bazaar might wish to comparison shop, but it is helpful for the immediately relevant information to be displayed first. This changes the comparison function used to always sort items in a Bazaar before those not in a Bazaar. --- crawl-ref/source/shopping.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/shopping.cc b/crawl-ref/source/shopping.cc index 979bd6066d73..3b64f3940cd0 100644 --- a/crawl-ref/source/shopping.cc +++ b/crawl-ref/source/shopping.cc @@ -2378,7 +2378,14 @@ static bool _compare_shopping_things(const CrawlStoreValue& a, const int a_cost = hash_a[SHOPPING_THING_COST_KEY]; const int b_cost = hash_b[SHOPPING_THING_COST_KEY]; - return a_cost < b_cost; + const level_id id_a = hash_a[SHOPPING_THING_POS_KEY].get_level_pos().id; + const level_id id_b = hash_b[SHOPPING_THING_POS_KEY].get_level_pos().id; + + // Put Bazaar items at the top of the shopping list. + if (!player_in_branch(BRANCH_BAZAAR) || id_a.branch == id_b.branch) + return a_cost < b_cost; + else + return id_a.branch == BRANCH_BAZAAR; } // Reset max_buyable and min_unbuyable info. Call this anytime any of the From c8b47a3f3ee06f48ee846a4db827dbae00c82478 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Sun, 3 Feb 2019 23:12:58 -0600 Subject: [PATCH 059/864] Tiles for the Rift unrand (CanOfWorms) Both item and doll tiles for the unrand demon trident "Rift". --- .../item/weapon/artefact/urand_rift.png | Bin 955 -> 1135 bytes .../rltiles/player/hand1/artefact/rift.png | Bin 281 -> 994 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/crawl-ref/source/rltiles/item/weapon/artefact/urand_rift.png b/crawl-ref/source/rltiles/item/weapon/artefact/urand_rift.png index 9f3fd3152305f37ca702d27dca86efb4fd56b223..ee1a0e2662518d928b82216c47487ff28c68f3dd 100644 GIT binary patch literal 1135 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy93=&Q?(RM=#y~cMSA(WJkYY)9 z^mSxl*x1kgCy|wbftew|C&cyt|NlU#G>xu}ZhK$%p7?X)`P_Vl|J%9$ze!N_^i-N0 z1u}p*kif*Sg@J`QwWF#=Lts#ZK)kZ~QJ_N@lf2zs{x4-5aZ zXXa~Po_y@QZ(?M>tldwsc$wYz-z;8VIQjYm=`&5wAIs;xT|etN?^JJ=)t)oIDuSZM M)78&qol`;+09N#?Pyhe` delta 944 zcmV;h15f<#2)hT68Gi-<0047(dh`GQ00v@9M??Vs0RI60puMM)00009a7bBm000XU z000XU0RWnu7ytkO2XskIMF-;n778m4h)K7{0009>Nklm(R}sWu4+<)1vYJ8{K?~81k8zx|7k^A#gor38gbJ!fi=G#% z#aKxR<^(CB5n5)>{aW~am#b){ef7b>H|HGg|2+QZoO=cT=p;nlzKrnZ>HoI0(o^K* zm-{*RENCZ812>5J9sSn8nq!&cM}qPiySl-WR*#M7I_#Cy8OLuFiK4S2u?diXj1ZO% zN$HZ3X);pF0e|U|(swiGJdFi0tF~e!a1d1Mv^-(e9RjdSI4~#%=a+a#%OZryV*?@b z$zvH+c2$$MaY#~384i^Ic*v<2Xk3|P!U0cs({(~a!`vbV&q-b{}e!$DPVvIVL$R>_V~(T%6z$wK1vit?t#^XGBjuIXlu0=c&p_7Ks#_3cn9<-d4D^wcEW^nNR9P&! zH=q-^2HXHv*yD_xnYkXF>28|)9*$PR4&WIuAIJf+f!V-x;0q7~7AZ%wfvct>4{~ZV z;Es41@l@om)V&vojJxK6eje>C1?~WS%BCB*4Kx5R6tD+82Tq!dd=hX)0qQzGP!3HC zlz(Zj`i+lpzlhvcHEmbA0iX>iQf(;ydc2O&YBo@+*sar=1`YxXm7aeEzFXCEFhHyd z#cbQyVi^T|74Q)Fu4JEpb4G#3m~axfsd`ufpB2-Wm;$!czQ!d5z~sjZf{UdS*s5l^ ztH$Sc;0=&5`a%)>Y6%RFAByF>OfdVm!zm`vZeP^`*=LH`f6N2m5m3*6IzIuy#>xu}ZhK$%p7?X)`P_Vl|J%9$ze!N_^i-N0 z1u}p*kif*Sg@J`QwWF#=Lts#ZK)kZ~QJ_N@lf2zs{x4u6JCf1IItM`^EZGWg> zD7Qd`B}TXBtB2sJS!s6ZimRV8*sE3lYr5E&E&j(q{))}R_P4?F8B+G`XFUCz(WU(K Ru?|pZc)I$ztaD0e0szpKTxtLS delta 265 zcmaFFK9gyJWIY=L14D6D)fXVemgMd3!tfsi7wla=87RV8;1OBOz`!jG!i)^F=12eq z*-JcqUD+QqigB45%*~v-87Q>O)5S3);_%yPhJ1${cv#v^J~U0y@V~wMiDu=j&)h3~ z1cjKGI@x}!ywQI5Y%bavw{KazR&33F zu|oze6^W0xGrXy5nK8pmq3!64dj{+=C$8#$x0BDbTQ{#Zuz%9S#9E%^-+vm2@*I~@ z_9{QruC%WHkb~>)+ZQU-j{LnfHPNb}=nzxDVU78X-o1}!=>A}{leK@47V;<+=wt>@ MS3j3^PD}|+0Kb@Qn*aa+ From c4a3eeb67844ce57fe22fe91ee34d9240ebeed38 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 4 Feb 2019 01:27:20 -0500 Subject: [PATCH 060/864] Move seeded rng initialization later Previously, I was doing this at the game start. This means that setting a seed in an rc file impacts random choices at the newgame menu, and also that the gameplay rng is advanced by any randomness that happens here. Now, only initialize the rng from a chosen seed, or choose a seed, during newgame setup. --- crawl-ref/source/ng-setup.cc | 1 + crawl-ref/source/startup.cc | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/ng-setup.cc b/crawl-ref/source/ng-setup.cc index f712765c0b25..2b86b9bd1dad 100644 --- a/crawl-ref/source/ng-setup.cc +++ b/crawl-ref/source/ng-setup.cc @@ -463,6 +463,7 @@ void initial_dungeon_setup() static void _setup_generic(const newgame_def& ng) { + reset_rng(); _init_player(); #if TAG_MAJOR_VERSION == 34 diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index 0c6cc789e8c7..5c401c6ae13a 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -85,7 +85,7 @@ static void _initialize() you.symbol = MONS_PLAYER; msg::initialise_mpr_streams(); - reset_rng(); + seed_rng(); // don't use any chosen seed yet init_char_table(Options.char_set); init_show_table(); From cf4bcd280a726e840763e35cd5dc89e1738b9695 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 4 Feb 2019 11:35:14 -0500 Subject: [PATCH 061/864] Add a hacky but functional newgame menu for seed / pregen The way I implemented this is fairly wince-inducing, but also fairly consistent with the current state of how these menus are done. This commit also adds a new game type for when a custom seed has been chosen; this game type should (I think) be basically inaccessible in DGL for now and require no save compat. Hopefully it can be used to include seeded games in sequell (similar to how sprint games are treated). --- crawl-ref/source/cio.cc | 8 +++ crawl-ref/source/cio.h | 1 + crawl-ref/source/game-type.h | 1 + crawl-ref/source/initfile.cc | 23 +++++-- crawl-ref/source/newgame-def.h | 2 + crawl-ref/source/newgame.cc | 106 +++++++++++++++++++++++++++++++++ crawl-ref/source/ng-setup.cc | 13 +++- crawl-ref/source/options.h | 1 + crawl-ref/source/startup.cc | 34 ++++++++++- crawl-ref/source/state.cc | 7 ++- crawl-ref/source/tilepick.cc | 1 + 11 files changed, 188 insertions(+), 9 deletions(-) diff --git a/crawl-ref/source/cio.cc b/crawl-ref/source/cio.cc index 7f8353d17c00..b1aa3f7b17b1 100644 --- a/crawl-ref/source/cio.cc +++ b/crawl-ref/source/cio.cc @@ -353,6 +353,14 @@ string line_reader::get_text() const return buffer; } +void line_reader::set_text(string text) +{ + snprintf(buffer, bufsz, "%s", text.c_str()); + length = min(text.size(), bufsz); + cur = buffer + length; + pos = length; +} + void line_reader::set_input_history(input_history *i) { history = i; diff --git a/crawl-ref/source/cio.h b/crawl-ref/source/cio.h index f79333cc2a76..34eeae010291 100644 --- a/crawl-ref/source/cio.h +++ b/crawl-ref/source/cio.h @@ -271,6 +271,7 @@ class line_reader int read_line(const string &prefill); string get_text() const; + void set_text(string s); void set_input_history(input_history *ih); void set_keyproc(keyproc fn); diff --git a/crawl-ref/source/game-type.h b/crawl-ref/source/game-type.h index 1b42654428e1..e84a36c66b22 100644 --- a/crawl-ref/source/game-type.h +++ b/crawl-ref/source/game-type.h @@ -11,5 +11,6 @@ enum game_type GAME_TYPE_ZOTDEF, GAME_TYPE_INSTRUCTIONS, GAME_TYPE_HIGH_SCORES, + GAME_TYPE_CUSTOM_SEED, NUM_GAME_TYPE }; diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index a24c04834b97..a2e70c7f3a4a 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -648,6 +648,8 @@ string gametype_to_str(game_type type) { case GAME_TYPE_NORMAL: return "normal"; + case GAME_TYPE_CUSTOM_SEED: + return "seeded"; case GAME_TYPE_TUTORIAL: return "tutorial"; case GAME_TYPE_ARENA: @@ -1764,7 +1766,8 @@ void read_options(const string &s, bool runscript, bool clear_aliases) } game_options::game_options() - : seed(0), no_save(false), language(lang_t::EN), lang_name(nullptr) + : seed(0), seed_from_rc(0), + no_save(false), language(lang_t::EN), lang_name(nullptr) { reset_options(); } @@ -3407,11 +3410,22 @@ void game_options::read_option_line(const string &str, bool runscript) constants.insert(field); } #ifndef DGAMELAUNCH - else if (key == "game_seed") // special handling because of the large type + else if (key == "game_seed") { + // special handling because of the large type. uint64_t tmp_seed = 0; if (sscanf(field.c_str(), "%" SCNu64, &tmp_seed)) - Options.seed = tmp_seed; + { + // seed_from_rc is only ever set here, or by the CLO. The CLO gets + // first crack, so don't overwrite it here. + // Options.seed can be updated in-game from the custom seed menu, + // so also don't overwrite it when the CLO has set it, or the + // player has set it in-game. + if (!Options.seed_from_rc) + Options.seed_from_rc = tmp_seed; + if (!Options.seed) + Options.seed = tmp_seed; + } } #endif @@ -4891,8 +4905,9 @@ bool parse_args(int argc, char **argv, bool rc_only) if (!next_is_param) return false; - if (!sscanf(next_arg, "%" SCNu64, &Options.seed)) + if (!sscanf(next_arg, "%" SCNu64, &Options.seed_from_rc)) return false; + Options.seed = Options.seed_from_rc; nextUsed = true; break; diff --git a/crawl-ref/source/newgame-def.h b/crawl-ref/source/newgame-def.h index ea546bec23ff..ba14c967b1fc 100644 --- a/crawl-ref/source/newgame-def.h +++ b/crawl-ref/source/newgame-def.h @@ -13,6 +13,8 @@ struct newgame_def string name; game_type type; string filename; + uint64_t seed; + bool pregenerate; // map name for sprint (or others in the future) // XXX: "random" means a random eligible map diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 9c824bb3bb2a..bd3491656d66 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -68,6 +68,7 @@ static bool _choose_weapon(newgame_def& ng, newgame_def& ng_choice, newgame_def::newgame_def() : name(), type(GAME_TYPE_NORMAL), + seed(0), pregenerate(false), species(SP_UNKNOWN), job(JOB_UNKNOWN), weapon(WPN_UNKNOWN), fully_random(false) @@ -641,6 +642,105 @@ static void _choose_name(newgame_def& ng, newgame_def& choice) if (cancel || crawl_state.seen_hups) game_ended(game_exit::abort); } + + +static void _choose_seed(newgame_def& ng, newgame_def& choice, + const newgame_def& defaults) +{ + char buf[20]; // max unsigned 64 bit integer is 19 chars + buf[0] = '\0'; + resumable_line_reader reader(buf, sizeof(buf)); + if (Options.seed) + choice.seed = Options.seed; + else if (Options.seed_from_rc) + choice.seed = Options.seed_from_rc; + reader.set_text(make_stringf("%" PRIu64, choice.seed)); + + bool done = false; + bool cancel = false; + choice.pregenerate = true; // default for this menu + + auto prompt_ui = make_shared(); + prompt_ui->on(Widget::slots.event, [&](wm_event ev) { + if (ev.type != WME_KEYDOWN) + return false; + int key = ev.key.keysym.sym; + + if (key == CONTROL('I')) + { + choice.pregenerate = !choice.pregenerate; + return done = false; + } + if (key == 'd' || key == 'D') + { + time_t now; + struct tm * timeinfo; + + time(&now); + timeinfo = localtime(&now); + char timebuf[9]; + strftime(timebuf, sizeof(timebuf), "%Y%m%d", timeinfo); + reader.set_text(timebuf); + return done = false; + } + // TODO: digits only + key = reader.putkey(key); + + if (key != -1) + { + if (key_is_escape(key)) + return done = cancel = true; + return done = true; + } + return true; + }); + + auto box = make_shared(ui::Widget::VERT); + box->add_child(prompt_ui); + auto pregen_choice = make_shared( + "Pregenerate the dungeon ([tab] to switch)? Yes | No"); + box->add_child(pregen_choice); + + auto popup = make_shared(box); + ui::push_layout(move(popup)); + while (!done && !crawl_state.seen_hups) + { + formatted_string prompt; + prompt.textcolour(CYAN); + prompt.cprintf("Play a game with a custom seed.\n\n"); + prompt.textcolour(LIGHTGREY); + prompt.cprintf( + "Choose 0 for a random seed. Press [d] for today's daily seed.\n" + "The seed will determine the dungeon layout, monsters,\n" + "and items that you discover.\n\n"); + prompt.cprintf("Seed:"); + string seed_text = make_stringf("%-20s", buf); + prompt.cprintf("\n%s\n\n", seed_text.c_str()); + prompt_ui->set_text(prompt); + // yes this appalling, some day we will have real buttons and text + // input. The seed highlight doesn't do much on console, but makes + // tiles look a lot better. N.b. the newline before the seed above + // is really so that an empty seed string won't get multiple highlights. + prompt_ui->set_highlight_pattern(seed_text, false); + if (choice.pregenerate) + pregen_choice->set_highlight_pattern("Yes", false); + else + pregen_choice->set_highlight_pattern("No", false); + ui::pump_events(); + } + ui::pop_layout(); + + string result = reader.get_text(); + uint64_t tmp_seed = 0; + int found = sscanf(result.c_str(), "%" SCNu64, &tmp_seed); + + if (cancel || crawl_state.seen_hups || !found || result.size() == 0) + game_ended(game_exit::abort); + + Options.seed = choice.seed = tmp_seed; + Options.pregen_dungeon = choice.pregenerate; +} + #endif // Read a choice of game into ng. @@ -667,12 +767,18 @@ bool choose_game(newgame_def& ng, newgame_def& choice, { _choose_gamemode_map(ng, choice, defaults); } +#ifndef DGAMELAUNCH + else if (ng.type == GAME_TYPE_CUSTOM_SEED) + _choose_seed(ng, choice, defaults); +#endif _choose_char(ng, choice, defaults); // Set these again, since _mark_fully_random may reset ng. ng.name = choice.name; ng.type = choice.type; + ng.seed = choice.seed; + ng.pregenerate = choice.pregenerate; #ifndef DGAMELAUNCH // New: pick name _after_ character choices. diff --git a/crawl-ref/source/ng-setup.cc b/crawl-ref/source/ng-setup.cc index 2b86b9bd1dad..0710095ca098 100644 --- a/crawl-ref/source/ng-setup.cc +++ b/crawl-ref/source/ng-setup.cc @@ -380,12 +380,21 @@ static void _setup_generic(const newgame_def& ng); // Initialise a game based on the choice stored in ng. void setup_game(const newgame_def& ng) { - crawl_state.type = ng.type; + if (Options.seed_from_rc && ng.type == GAME_TYPE_NORMAL) + { + Options.seed = Options.seed_from_rc; + crawl_state.type = GAME_TYPE_CUSTOM_SEED; + } + else if (!Options.seed && ng.type == GAME_TYPE_CUSTOM_SEED) + crawl_state.type = GAME_TYPE_NORMAL; + else + crawl_state.type = ng.type; crawl_state.map = ng.map; switch (crawl_state.type) { case GAME_TYPE_NORMAL: + case GAME_TYPE_CUSTOM_SEED: _setup_normal_game(); break; case GAME_TYPE_TUTORIAL: @@ -463,7 +472,7 @@ void initial_dungeon_setup() static void _setup_generic(const newgame_def& ng) { - reset_rng(); + reset_rng(); // initialize rng from Options.seed _init_player(); #if TAG_MAJOR_VERSION == 34 diff --git a/crawl-ref/source/options.h b/crawl-ref/source/options.h index 67cdf2a1d57d..ef74a8c6f9ab 100644 --- a/crawl-ref/source/options.h +++ b/crawl-ref/source/options.h @@ -171,6 +171,7 @@ struct game_options vector additional_macro_files; uint64_t seed; // Non-random games. + uint64_t seed_from_rc; #ifndef DGAMELAUNCH bool pregen_dungeon; // Is the dungeon generated at the beginning? #endif diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index 5c401c6ae13a..7e1e4a206bae 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -495,6 +495,8 @@ static void _construct_game_modes_menu(MenuScroller* menu) tmp = new TextItem(); #endif text = "Dungeon Crawl"; + if (Options.seed_from_rc) + text += make_stringf(" (custom seed %" PRIu64 ")", Options.seed_from_rc); tmp->set_text(text); tmp->set_fg_colour(WHITE); tmp->set_highlight_colour(LIGHTGREY); @@ -502,8 +504,34 @@ static void _construct_game_modes_menu(MenuScroller* menu) // Scroller does not care about x-coordinates and only cares about // item height obtained from max.y - min.y tmp->set_bounds(coord_def(1, 1), coord_def(1, 2)); - tmp->set_description_text("Dungeon Crawl: The main game: full of monsters, " - "items, gods and danger!"); + if (Options.seed_from_rc) + { + tmp->set_description_text( + "Dungeon Crawl: The main game. " + "(Your options file has selected a custom seed.)"); + } + else + { + tmp->set_description_text( + "Dungeon Crawl: The main game: full of monsters, " + "items, gods and danger!"); + } + menu->attach_item(tmp); + tmp->set_visible(true); + +#ifdef USE_TILE_LOCAL + tmp = new TextTileItem(); + tmp->add_tile(tile_def(tileidx_gametype(GAME_TYPE_NORMAL), TEX_GUI)); +#else + tmp = new TextItem(); +#endif + text = "Choose game seed"; + tmp->set_text(text); + tmp->set_fg_colour(WHITE); + tmp->set_highlight_colour(LIGHTGREY); + tmp->set_id(GAME_TYPE_CUSTOM_SEED); + tmp->set_bounds(coord_def(1, 1), coord_def(1, 2)); + tmp->set_description_text("Play with a chosen custom dungeon seed."); menu->attach_item(tmp); tmp->set_visible(true); @@ -1064,6 +1092,7 @@ bool UIStartupMenu::on_event(const wm_event& ev) input_string = ""; break; case GAME_TYPE_NORMAL: + case GAME_TYPE_CUSTOM_SEED: case GAME_TYPE_TUTORIAL: case GAME_TYPE_SPRINT: case GAME_TYPE_HINTS: @@ -1104,6 +1133,7 @@ bool UIStartupMenu::on_event(const wm_event& ev) switch (id) { case GAME_TYPE_NORMAL: + case GAME_TYPE_CUSTOM_SEED: case GAME_TYPE_TUTORIAL: case GAME_TYPE_SPRINT: case GAME_TYPE_HINTS: diff --git a/crawl-ref/source/state.cc b/crawl-ref/source/state.cc index 96be20dd42eb..e1434d9faff6 100644 --- a/crawl-ref/source/state.cc +++ b/crawl-ref/source/state.cc @@ -555,7 +555,8 @@ bool game_state::game_standard_levelgen() const bool game_state::game_is_normal() const { ASSERT(type < NUM_GAME_TYPE); - return type == GAME_TYPE_NORMAL || type == GAME_TYPE_UNSPECIFIED; + return type == GAME_TYPE_NORMAL || type == GAME_TYPE_CUSTOM_SEED + ||type == GAME_TYPE_UNSPECIFIED; } bool game_state::game_is_tutorial() const @@ -602,6 +603,8 @@ string game_state::game_type_name_for(game_type _type) default: // No explicit game type name for default game. return ""; + case GAME_TYPE_CUSTOM_SEED: + return "Seeded"; case GAME_TYPE_TUTORIAL: return "Tutorial"; case GAME_TYPE_ARENA: @@ -618,6 +621,8 @@ string game_state::game_savedir_path() const string game_state::game_type_qualifier() const { + if (type == GAME_TYPE_CUSTOM_SEED) + return "-seeded"; if (crawl_state.game_is_sprint()) return "-sprint"; if (crawl_state.game_is_tutorial()) diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc index 4b26fb2a7c9f..8461598e8afd 100644 --- a/crawl-ref/source/tilepick.cc +++ b/crawl-ref/source/tilepick.cc @@ -3278,6 +3278,7 @@ tileidx_t tileidx_gametype(const game_type gtype) switch (gtype) { case GAME_TYPE_NORMAL: + case GAME_TYPE_CUSTOM_SEED: return TILEG_STARTUP_STONESOUP; case GAME_TYPE_TUTORIAL: return TILEG_STARTUP_TUTORIAL; From 27fda53bb8d0e3a397a8e75d3c0c40f788cb00ef Mon Sep 17 00:00:00 2001 From: Edgar Bering Date: Mon, 4 Feb 2019 15:47:42 -0500 Subject: [PATCH 062/864] Don't target net traps through glass (NormalPerson7) --- crawl-ref/source/traps.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crawl-ref/source/traps.cc b/crawl-ref/source/traps.cc index 983d795c2b4d..f30f4bbdd004 100644 --- a/crawl-ref/source/traps.cc +++ b/crawl-ref/source/traps.cc @@ -633,6 +633,9 @@ void trap_def::trigger(actor& triggerer) case TRAP_NET: { + // Nets need LOF to hit the player, no netting through glass. + if (!you.see_cell_no_trans(pos)) + break; bool triggered = false; if (you_trigger) { From a006759ab7688fd1ce7611ae1c8e35f8d49afa02 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Mon, 4 Feb 2019 15:05:51 -0600 Subject: [PATCH 063/864] Fix the area grid for klown pie silence When applying silence from a Klown pie, we weren't invalidating the area grid. This meant that silence wouldn't actually apply until something else updated the area grid, which might not be until the end of the next turn. --- crawl-ref/source/beam.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc index 0c131a5ca815..2445df037ab3 100644 --- a/crawl-ref/source/beam.cc +++ b/crawl-ref/source/beam.cc @@ -3659,6 +3659,10 @@ static const vector pie_effects = { mpr("An unnatural silence engulfs you."); you.increase_duration(DUR_SILENCE, 4 + random2(7), 10); + invalidate_agrid(true); + + if (you.beheld()) + you.update_beholders(); } }, 10 From 50940dbbcd7a3ff070017a066ac2e5c332a97d7a Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Mon, 4 Feb 2019 16:06:30 +0000 Subject: [PATCH 064/864] Fix message order when a player resists damage from an elemental bolt Previously, the "You resist" message (and other messages such as "You feel a terrible chill" that are to do with resistances) were being printed before the message to say the bolt had hit. Hence, fix this with a second call to check_your_resists specifically for printing these messages, and change the first call to be called with doEffects = false. In order to do this, it's necessary to save the pre-resist damage as a separate identifier. In doing so, a debug message is simplified. --- crawl-ref/source/beam.cc | 52 +++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc index 2445df037ab3..c748fe9ec9ac 100644 --- a/crawl-ref/source/beam.cc +++ b/crawl-ref/source/beam.cc @@ -3802,22 +3802,17 @@ void bolt::affect_player() // FIXME: Lots of duplicated code here (compare handling of // monsters) - int hurted = 0; + int pre_ac_dam = 0; // Roll the damage. if (!(origin_spell == SPELL_FLASH_FREEZE && you.duration[DUR_FROZEN])) - hurted += damage.roll(); + pre_ac_dam += damage.roll(); -#ifdef DEBUG_DIAGNOSTICS - const int preac = hurted; -#endif - - hurted = apply_AC(&you, hurted); + int pre_res_dam = apply_AC(&you, pre_ac_dam); #ifdef DEBUG_DIAGNOSTICS - const int postac = hurted; dprf(DIAG_BEAM, "Player damage: before AC=%d; after AC=%d", - preac, postac); + pre_ac_dam, pre_res_dam); #endif practise_being_shot(); @@ -3825,7 +3820,7 @@ void bolt::affect_player() bool was_affected = false; int old_hp = you.hp; - hurted = max(0, hurted); + pre_res_dam = max(0, pre_res_dam); // If the beam is an actual missile or of the MMISSILE type (Earth magic) // we might bleed on the floor. @@ -3833,11 +3828,12 @@ void bolt::affect_player() && (flavour == BEAM_MISSILE || flavour == BEAM_MMISSILE)) { // assumes DVORP_PIERCING, factor: 0.5 - int blood = min(you.hp, hurted / 2); + int blood = min(you.hp, pre_res_dam / 2); bleed_onto_floor(you.pos(), MONS_PLAYER, blood, true); } - hurted = check_your_resists(hurted, flavour, "", this); + // Apply resistances to damage, but don't print "You resist" messages yet + int final_dam = check_your_resists(pre_res_dam, flavour, "", this, false); // Tell the player the beam hit if (hit_verb.empty()) @@ -3846,18 +3842,24 @@ void bolt::affect_player() if (flavour != BEAM_VISUAL && !is_enchantment()) { mprf("The %s %s you%s%s", name.c_str(), hit_verb.c_str(), - hurted ? "" : " but does no damage", - attack_strength_punctuation(hurted).c_str()); + final_dam ? "" : " but does no damage", + attack_strength_punctuation(final_dam).c_str()); } - if (flavour == BEAM_MIASMA && hurted > 0) + // Now print the messages associated with checking resistances, so that + // these come after the beam actually hitting. + // Note that this must be called with the pre-resistance damage, so that + // poison effects etc work properly. + check_your_resists(pre_res_dam, flavour, "", this, true); + + if (flavour == BEAM_MIASMA && final_dam > 0) was_affected = miasma_player(agent(), name); if (flavour == BEAM_DEVASTATION) // DISINTEGRATION already handled - blood_spray(you.pos(), MONS_PLAYER, hurted / 5); + blood_spray(you.pos(), MONS_PLAYER, final_dam / 5); // Confusion effect for spore explosions - if (flavour == BEAM_SPORE && hurted + if (flavour == BEAM_SPORE && final_dam && !(you.holiness() & MH_UNDEAD) && !you.is_unbreathing()) { @@ -3895,7 +3897,7 @@ void bolt::affect_player() && coinflip()) { mprf("Your attached jelly eats %s!", item->name(DESC_THE).c_str()); - inc_hp(random2(hurted / 2)); + inc_hp(random2(final_dam / 2)); canned_msg(MSG_GAIN_HEALTH); drop_item = false; } @@ -3923,7 +3925,7 @@ void bolt::affect_player() // Manticore spikes - if (origin_spell == SPELL_THROW_BARBS && hurted > 0) + if (origin_spell == SPELL_THROW_BARBS && final_dam > 0) { mpr("The barbed spikes become lodged in your body."); if (!you.duration[DUR_BARBS]) @@ -3946,16 +3948,16 @@ void bolt::affect_player() if (origin_spell == SPELL_QUICKSILVER_BOLT) debuff_player(); - if (origin_spell == SPELL_THROW_PIE && hurted > 0) + if (origin_spell == SPELL_THROW_PIE && final_dam > 0) { const pie_effect effect = _random_pie_effect(you); mprf("%s!", effect.desc); effect.effect(you, *this); } - dprf(DIAG_BEAM, "Damage: %d", hurted); + dprf(DIAG_BEAM, "Damage: %d", final_dam); - if (hurted > 0 || old_hp < you.hp || was_affected) + if (final_dam > 0 || old_hp < you.hp || was_affected) { if (mons_att_wont_attack(attitude)) { @@ -3976,7 +3978,7 @@ void bolt::affect_player() foe_info.hurt++; } - internal_ouch(hurted); + internal_ouch(final_dam); // Acid. (Apply this afterward, to avoid bad message ordering.) if (flavour == BEAM_ACID) @@ -3984,8 +3986,8 @@ void bolt::affect_player() extra_range_used += range_used_on_hit(); - knockback_actor(&you, hurted); - pull_actor(&you, hurted); + knockback_actor(&you, final_dam); + pull_actor(&you, final_dam); if (origin_spell == SPELL_FLASH_FREEZE || name == "blast of ice" From f9871eb369673cb5d4d2f5571106dace0634725c Mon Sep 17 00:00:00 2001 From: Umer Shaikh Date: Sun, 3 Feb 2019 18:55:16 -0600 Subject: [PATCH 065/864] Escape angle brackets in macro assignment Closes #687 --- crawl-ref/source/macro.cc | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/crawl-ref/source/macro.cc b/crawl-ref/source/macro.cc index a1ff226c5abe..e62466554667 100644 --- a/crawl-ref/source/macro.cc +++ b/crawl-ref/source/macro.cc @@ -991,14 +991,16 @@ void macro_add_query() keyseq key; mouse_control mc(MOUSE_MODE_MACRO); key = _getch_mul(); + string key_str = vtostr(key); + key_str = replace_all(key_str, "<", "<<"); msgwin_reply(vtostr(key)); if (mapref.count(key) && !mapref[key].empty()) { - string action = vtostr(mapref[key]); - action = replace_all(action, "<", "<<"); - mprf(MSGCH_WARN, "Current Action: %s", action.c_str()); + string action_str = vtostr(mapref[key]); + action_str = replace_all(action_str, "<", "<<"); + mprf(MSGCH_WARN, "Current Action: %s", action_str.c_str()); mprf(MSGCH_PROMPT, "Do you wish to (r)edefine, (c)lear, or (a)bort? "); input = m_getch(); @@ -1013,8 +1015,8 @@ void macro_add_query() { mprf("Cleared %s '%s' => '%s'.", macro_type.c_str(), - vtostr(key).c_str(), - vtostr(mapref[key]).c_str()); + key_str.c_str(), + action_str.c_str()); macro_del(mapref, key); crawl_state.unsaved_macros = true; return; @@ -1034,17 +1036,18 @@ void macro_add_query() { mprf("Deleted %s for '%s'.", macro_type.c_str(), - vtostr(key).c_str()); + key_str.c_str()); } else canned_msg(MSG_OK); } else { + string action_str = vtostr(action); + action_str = replace_all(action_str, "<", "<<"); macro_add(mapref, key, action); mprf("Created %s '%s' => '%s'.", - macro_type.c_str(), - vtostr(key).c_str(), vtostr(action).c_str()); + macro_type.c_str(), key_str.c_str(), action_str.c_str()); } crawl_state.unsaved_macros = true; From 095630396997ac4e000c4a9b04694ce56afa12af Mon Sep 17 00:00:00 2001 From: Umer Shaikh Date: Sun, 3 Feb 2019 19:13:53 -0600 Subject: [PATCH 066/864] Make unassigned keys exit macro reassignment menu This makes the menu's behaviour more consistent with other crawl menus. [Commiter's note: Closes #974] --- crawl-ref/source/macro.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crawl-ref/source/macro.cc b/crawl-ref/source/macro.cc index e62466554667..c09738c2a022 100644 --- a/crawl-ref/source/macro.cc +++ b/crawl-ref/source/macro.cc @@ -1006,12 +1006,7 @@ void macro_add_query() input = m_getch(); input = toalower(input); - if (input == 'a' || key_is_escape(input)) - { - canned_msg(MSG_OK); - return; - } - else if (input == 'c') + if (input == 'c') { mprf("Cleared %s '%s' => '%s'.", macro_type.c_str(), @@ -1021,6 +1016,11 @@ void macro_add_query() crawl_state.unsaved_macros = true; return; } + else if (input != 'r') + { + canned_msg(MSG_OK); + return; + } } keyseq action; From 508cf822a6ccc7592fe38ea0fd9fa972f753772d Mon Sep 17 00:00:00 2001 From: Floodkiller Date: Mon, 4 Feb 2019 17:12:22 -0500 Subject: [PATCH 067/864] Re-enable stat shifting for Gnolls worshipping Jiyva Re-enables the stat shifting passive for Gnolls who are worshipping Jiyva. This is a leftover fragment from the static attribute iteration of Gnolls. --- crawl-ref/source/timed-effects.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crawl-ref/source/timed-effects.cc b/crawl-ref/source/timed-effects.cc index 4726532aa4d6..e4fb33040349 100644 --- a/crawl-ref/source/timed-effects.cc +++ b/crawl-ref/source/timed-effects.cc @@ -376,11 +376,9 @@ static void _jiyva_effects(int /*time_delta*/) } } - // Gnolls can't shift stats if (have_passive(passive_t::fluid_stats) && x_chance_in_y(you.piety / 4, MAX_PIETY) - && !player_under_penance() && one_chance_in(4) - && you.species != SP_GNOLL) + && !player_under_penance() && one_chance_in(4)) { jiyva_stat_action(); } From d6fbd69efe4d315594c08e68fc3155bb575d3139 Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 5 Feb 2019 12:54:02 -0500 Subject: [PATCH 068/864] For pregen morgues, only show visited levels (alexjurkiewicz) I did this by moving the code that saves vault names a bit later in the process, so that they only get entered into you.vault_list when the player actually enters the level, rather than during the level builder. This also unifies code for collecting vault names. For now I've also changed this to show layout names, which are useful for debugging. (cherry picked from commit 643a44d428fe4e8a720b83b0394e1465a4e5bddb) --- crawl-ref/source/dbg-util.cc | 8 +++++++- crawl-ref/source/dbg-util.h | 2 +- crawl-ref/source/dungeon.cc | 24 ------------------------ crawl-ref/source/files.cc | 4 ++++ crawl-ref/source/l-debug.cc | 2 +- 5 files changed, 13 insertions(+), 27 deletions(-) diff --git a/crawl-ref/source/dbg-util.cc b/crawl-ref/source/dbg-util.cc index 65af79b2f201..b6f1b56c1700 100644 --- a/crawl-ref/source/dbg-util.cc +++ b/crawl-ref/source/dbg-util.cc @@ -37,11 +37,17 @@ monster_type debug_prompt_for_monster() return MONS_NO_MONSTER; } -vector level_vault_names() +vector level_vault_names(bool force_all) { vector result; for (auto &vault : env.level_vaults) { + // TODO: should this suppress layouts? The code it is replacing did. + if (!force_all && (vault->map.has_tag_suffix("dummy") + || vault->map.has_tag("no_dump"))) + { + continue; + } string vault_name = vault->map.name; if (vault->map.subvault_places.size()) { diff --git a/crawl-ref/source/dbg-util.h b/crawl-ref/source/dbg-util.h index f81435b1dee9..3b8b5042aaef 100644 --- a/crawl-ref/source/dbg-util.h +++ b/crawl-ref/source/dbg-util.h @@ -33,4 +33,4 @@ string debug_mon_str(const monster* mon); void wizard_toggle_dprf(); void debug_list_vacant_keys(); -vector level_vault_names(); +vector level_vault_names(bool force_all=false); diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index c705de55cfad..961d9033cd3a 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -196,7 +196,6 @@ static bool use_random_maps = true; static bool dgn_check_connectivity = false; static int dgn_zones = 0; -static vector _you_vault_list; #ifdef DEBUG_STATISTICS static vector _you_all_vault_list; #endif @@ -391,12 +390,6 @@ static bool _build_level_vetoable(bool enable_random_maps, check_map_validity(); - if (!_you_vault_list.empty()) - { - vector &vec(you.vault_list[level_id::current()]); - vec.insert(vec.end(), _you_vault_list.begin(), _you_vault_list.end()); - } - #ifdef DEBUG_STATISTICS for (auto vault : _you_all_vault_list) mapstat_report_map_success(vault); @@ -1210,7 +1203,6 @@ void dgn_reset_level(bool enable_random_maps) you.unique_creatures = temp_unique_creatures; you.unique_items = temp_unique_items; - _you_vault_list.clear(); #ifdef DEBUG_STATISTICS _you_all_vault_list.clear(); #endif @@ -6896,22 +6888,6 @@ static dungeon_feature_type _vault_inspect_glyph(vault_placement &place, static void _remember_vault_placement(const vault_placement &place, bool extra) { - // Second we setup some info to be saved in the player's properties - // hash table, so the information can be included in the character - // dump when the player dies/quits/wins. - if (!place.map.is_overwritable_layout() - && !place.map.has_tag_suffix("dummy") - && !place.map.has_tag("no_dump")) - { - // When generating a level, vaults may be vetoed together with the - // whole level after being placed, thus we need to save them in a - // temp list. - if (crawl_state.generating_level) - _you_vault_list.push_back(place.map.name); - else - you.vault_list[level_id::current()].push_back(place.map.name); - } - #ifdef DEBUG_STATISTICS _you_all_vault_list.push_back(place.map.name); #endif diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 92aeadf29847..95b9544a75b9 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -34,6 +34,7 @@ #include "cloud.h" #include "coordit.h" #include "dactions.h" +#include "dbg-util.h" #include "dgn-overview.h" #include "directn.h" #include "dungeon.h" @@ -1510,7 +1511,10 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, } if (env.turns_on_level == 0) + { just_created_level = true; // in case level was pre-generated + you.vault_list[level_id::current()] = level_vault_names(); + } // Clear map knowledge stair emphasis. show_update_emphasis(); diff --git a/crawl-ref/source/l-debug.cc b/crawl-ref/source/l-debug.cc index c7430996553a..3386ce29359d 100644 --- a/crawl-ref/source/l-debug.cc +++ b/crawl-ref/source/l-debug.cc @@ -132,7 +132,7 @@ LUAFN(debug_dump_map) LUAFN(debug_vault_names) { - vector vnames = level_vault_names(); + vector vnames = level_vault_names(true); string r; r = comma_separated_line(vnames.begin(), vnames.end()); lua_pushstring(ls, r.c_str()); From 55f835606b540bb5b009ee4de097f4c2fdf7eb66 Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 5 Feb 2019 16:49:14 -0500 Subject: [PATCH 069/864] Invalidate LOS properly for level pregeneration It turns out that monster band placement checks LOS when placing the followers, and so if LOS is not properly invalidated, the builder will use the cache for the wrong level, leading to seed divergence. This moves a few other cleanups up that I think will matter a bit less. --- crawl-ref/source/dbg-util.cc | 2 +- crawl-ref/source/files.cc | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/crawl-ref/source/dbg-util.cc b/crawl-ref/source/dbg-util.cc index b6f1b56c1700..dcfaaa119692 100644 --- a/crawl-ref/source/dbg-util.cc +++ b/crawl-ref/source/dbg-util.cc @@ -110,7 +110,7 @@ void debug_dump_levgen() if (!env.level_vaults.empty()) { mpr("Level vaults:"); - auto vaults = level_vault_names(); + auto vaults = level_vault_names(true); for (auto &vname : vaults) mprf(" %s", vname.c_str()); } diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 95b9544a75b9..2297f713fda0 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1503,6 +1503,14 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, if (just_created_level) env.markers.init_all(); // init first, activation happens when entering + // Clear map knowledge stair emphasis. + show_update_emphasis(); + + // Shouldn't happen, but this is too unimportant to assert. + deleteAll(env.final_effects); + + los_changed(); + if (load_mode == LOAD_GENERATE) { if (just_created_level) @@ -1516,14 +1524,6 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, you.vault_list[level_id::current()] = level_vault_names(); } - // Clear map knowledge stair emphasis. - show_update_emphasis(); - - // Shouldn't happen, but this is too unimportant to assert. - deleteAll(env.final_effects); - - los_changed(); - // Markers must be activated early, since they may rely on // events issued later, e.g. DET_ENTERING_LEVEL or // the DET_TURN_ELAPSED from update_level. From f44d0c5ad20cc88c73c694df44ac0a645adc09d0 Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Tue, 5 Feb 2019 17:26:48 +0000 Subject: [PATCH 070/864] Fix dancing weapon description when multiple monsters enter LOS (11843) When multiple enemies entered line of sight at once including at least one dancing weapon, the message "There is." was being printed. This is because there was an unnecessary check for enemies not being dancing weapons in get_monster_equipment_desc. Remove this check, and add a special case to the helper function _describe_monster_weapon to prevent these messages being printed as "There is wielding a +4 trident." These messages should now properly print as e.g. "There is a +4 executioner's axe of electrocution." --- crawl-ref/source/directn.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc index 92e9cc09d0e9..626afcf7fe96 100644 --- a/crawl-ref/source/directn.cc +++ b/crawl-ref/source/directn.cc @@ -3001,6 +3001,8 @@ static string _describe_monster_weapon(const monster_info& mi, bool ident) if (mi.type == MONS_PANDEMONIUM_LORD) desc += " armed with "; + else if (mi.type == MONS_DANCING_WEAPON) + desc += " "; else desc += " wielding "; desc += name1; @@ -3297,7 +3299,7 @@ string get_monster_equipment_desc(const monster_info& mi, string weap = ""; - if (mi.type != MONS_DANCING_WEAPON && mi.type != MONS_SPECTRAL_WEAPON) + if (mi.type != MONS_SPECTRAL_WEAPON) weap = _describe_monster_weapon(mi, level == DESC_IDENTIFIED); // Print the rest of the equipment only for full descriptions. From ac12a559088a5574b46b67723399a0b35199fc94 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Mon, 4 Feb 2019 17:23:05 -0600 Subject: [PATCH 071/864] Fix loot in a Gauntlet exit vault The FeTm adventurer loot pile was missing a potential item. --- crawl-ref/source/dat/des/portals/gauntlet.des | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crawl-ref/source/dat/des/portals/gauntlet.des b/crawl-ref/source/dat/des/portals/gauntlet.des index e6da985870af..5a199d97db71 100644 --- a/crawl-ref/source/dat/des/portals/gauntlet.des +++ b/crawl-ref/source/dat/des/portals/gauntlet.des @@ -1137,6 +1137,8 @@ dgn.delayed_decay_extra(_G, "P", "felid skeleton", ", any jewellery good_item w:60 / manual of transmutations" .. " / manual of unarmed combat / manual of fighting" .. ", any wand w:20 / any misc / gold / any scroll / any potion" .. + " / nothing w:60" .. + ", any wand w:20 / any misc / gold / any scroll / any potion" .. " / nothing w:60") -- Halfling warper. From e688737648f84cf4b2867d443ec2ed48cc9e1d9a Mon Sep 17 00:00:00 2001 From: gammafunk Date: Tue, 5 Feb 2019 22:56:47 -0600 Subject: [PATCH 072/864] Add more exits and statues to some Gauntlets Add a second exit to the other end of the 9x9 gauntlet maps so it's more convenient to exit as well as symmetric on the map. Also add a few statues. I'll be revamping the wall decorations in a subsequent commit to use a common motif for these 9x9 maps. That change might not be ready for release, so these changes will do for now. --- crawl-ref/source/dat/des/portals/gauntlet.des | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/crawl-ref/source/dat/des/portals/gauntlet.des b/crawl-ref/source/dat/des/portals/gauntlet.des index 5a199d97db71..438efc03deec 100644 --- a/crawl-ref/source/dat/des/portals/gauntlet.des +++ b/crawl-ref/source/dat/des/portals/gauntlet.des @@ -1228,7 +1228,7 @@ SUBVAULT: y : gauntlet_exit : gauntlet_appearance(_G) MAP ccccccccccccccccccccccccccccccc - cG.............<.............Gc + cG............G Date: Tue, 5 Feb 2019 23:00:27 -0600 Subject: [PATCH 073/864] Shorten the path of a Gauntlet exit area In gammafunk_gauntlet_one_two_three, move the landing sites leading to the minotaur's vault closer together. This way there's less walking when taking transporters in the paths on the outer edges of the map. --- crawl-ref/source/dat/des/portals/gauntlet.des | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/crawl-ref/source/dat/des/portals/gauntlet.des b/crawl-ref/source/dat/des/portals/gauntlet.des index 438efc03deec..e1be51920102 100644 --- a/crawl-ref/source/dat/des/portals/gauntlet.des +++ b/crawl-ref/source/dat/des/portals/gauntlet.des @@ -1492,11 +1492,12 @@ c..nfffffffffn.ngggggggggn.nhhhhhhhhhn.niiiiiiiiin.njjjjjjjjjn.nkkkkkkkkkn..c c..nfffffffffn.ngggggggggn.nhhhhhhhhhn.niiiiiiiiin.njjjjjjjjjn.nkkkkkkkkkn..c c..nnnnnnnnnnn.nnnnnnnnnnn.nnnnnnnnnnn.nnnnnnnnnnn.nnnnnnnnnnn.nnnnnnnnnnn..c c...........................................................................c -cG...................................GTG...................................Gc -vvvvvvvnnnvvvvvvvvvnnnvvvvvvvvvnnnvvvvvvvvvnnnvvvvvvvvvnnnvvvvvvvvvnnnvvvvvvv - v.M...........O...........Q...........S...........q...........s.v - v...............................................................v - vvvvvvvvvvvvvvvvvvvvvvvvvyyyyyyyyyyyyyyyvvvvvvvvvvvvvvvvvvvvvvvvv +cG...................................G Date: Wed, 6 Feb 2019 21:29:19 +0800 Subject: [PATCH 074/864] Update crawl_manual.rst --- crawl-ref/docs/crawl_manual.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/docs/crawl_manual.rst b/crawl-ref/docs/crawl_manual.rst index f14a277888a5..7cace7ddf148 100644 --- a/crawl-ref/docs/crawl_manual.rst +++ b/crawl-ref/docs/crawl_manual.rst @@ -2098,7 +2098,7 @@ Elementalists elemental magic: air, fire, earth or ice. Fire Magic - tends towards destructive conjurations. Earth Elementalists begin with the + tends towards destructive conjurations. Fire Elementalists begin with the Book of Flames. Ice Magic From dd71560323a716373b3610a22c6d6cac75c0d010 Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 6 Feb 2019 09:33:30 -0500 Subject: [PATCH 075/864] Initialize int member variables of formatted_scroller (11838) For many scrollers, the initial position was being determined by the uninitialized m_scroll, leading to fairly random behavior (probably compiler-dependent, too). For good measure, I initialized all three. This also fixes a bug in the way FS_START_AT_END was handled for this class, where in some cases (maybe most cases) a scroller position would be set but then overrided by the uninitialized value of m_scroll. Since this value would usually be a large number, the scroller very often did start at the end. Did not track down why this behavior appears to have changed recently, since this bug is months old, but it could be to do with something about how uninitialized values are handled that we don't directly control. --- crawl-ref/source/scroller.cc | 11 +++++++++-- crawl-ref/source/scroller.h | 2 ++ .../source/webserver/game_data/static/ui-layouts.js | 4 +++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/scroller.cc b/crawl-ref/source/scroller.cc index 56c75d223a3b..0f163ec536a1 100644 --- a/crawl-ref/source/scroller.cc +++ b/crawl-ref/source/scroller.cc @@ -60,6 +60,14 @@ class UIHookedScroller : public Scroller formatted_scroller &fs; }; +void formatted_scroller::scroll_to_end() +{ + // this needs to match the value in ui-layout.js scroller_scroll_to_line + // (TODO: why?) + m_scroll = numeric_limits::max(); + m_scroll_dirty = true; +} + int formatted_scroller::show() { auto vbox = make_shared(Widget::VERT); @@ -147,9 +155,8 @@ int formatted_scroller::show() tiles.push_ui_layout("formatted-scroller", 2); #endif - // this needs to match the value in ui.js if (m_flags & FS_START_AT_END) - m_scroller->set_scroll(numeric_limits::max()); + scroll_to_end(); open_scrollers.push_back(this); if (m_scroll_dirty) diff --git a/crawl-ref/source/scroller.h b/crawl-ref/source/scroller.h index aa7ecd0eab87..3fcc41316425 100644 --- a/crawl-ref/source/scroller.h +++ b/crawl-ref/source/scroller.h @@ -18,6 +18,7 @@ class formatted_scroller { public: formatted_scroller(int flags, const string& text = "") + : m_lastch(0), m_flags(0x0), m_scroll(0) { m_flags = flags; add_text(text); @@ -39,6 +40,7 @@ class formatted_scroller void set_title() { m_title.clear(); }; void set_title(formatted_string title) { m_title = move(title); }; + void scroll_to_end(); void set_scroll(int y); const formatted_string& get_contents() { return contents; }; diff --git a/crawl-ref/source/webserver/game_data/static/ui-layouts.js b/crawl-ref/source/webserver/game_data/static/ui-layouts.js index 9ff7045d2b94..836d9773da22 100644 --- a/crawl-ref/source/webserver/game_data/static/ui-layouts.js +++ b/crawl-ref/source/webserver/game_data/static/ui-layouts.js @@ -542,7 +542,7 @@ function ($, comm, client, ui, enums, cr, util, scroller, main, gui, player) { scroller_scroll_page(scroller, 1); break; case 35: // end - scroller_scroll_to_line(scroller, 2147483647); + scroller_scroll_to_line(scroller, 2147483647); //int32_t max break; case 36: // home scroller_scroll_to_line(scroller, 0); @@ -609,6 +609,8 @@ function ($, comm, client, ui, enums, cr, util, scroller, main, gui, player) { function scroller_scroll_to_line(scroller, line) { var $scroller = $(scroller.scrollElement); + // TODO: can this work without special-casing int32_t max, where any + // pos greater than the max scrolls to end? if (line == 2147483647) // FS_START_AT_END { // special case for webkit: excessively large values don't work From 748db23bece377b9055ac7c488472092608a3364 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Wed, 6 Feb 2019 11:42:57 -0500 Subject: [PATCH 076/864] Only check for adjacent friendlies with exploding ammo (11857) Commit 853fe2ed08 added a friendly fire check for portal projectile fired exploding ammo; however it did not restrict this check to exploding bolt types. --- crawl-ref/source/throw.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crawl-ref/source/throw.cc b/crawl-ref/source/throw.cc index def9a5552c0d..77144bd1f0ca 100644 --- a/crawl-ref/source/throw.cc +++ b/crawl-ref/source/throw.cc @@ -845,12 +845,11 @@ bool throw_it(bolt &pbolt, int throw_2, dist *target) { // This block is roughly equivalent to bolt::affect_cell for // normal projectiles. - // FIXME: this does not handle exploding ammo! monster *m = monster_at(thr.target); if (m) cancelled = stop_attack_prompt(m, false, thr.target); - if (!cancelled /*&& pbolt.is_explosion*/) + if (!cancelled && (pbolt.is_explosion || pbolt.special_explosion)) { for (adjacent_iterator ai(thr.target); ai; ++ai) { From 9ff413599d79d97b5ca48318e2e2dd0fcaa67694 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Wed, 6 Feb 2019 11:56:04 -0600 Subject: [PATCH 077/864] Fix some Gauntlet decorations I ended up not using flame cloud decorations on this map, but didn't replace the glyphs. Use lava to surround the statues instead. --- crawl-ref/source/dat/des/portals/gauntlet.des | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/dat/des/portals/gauntlet.des b/crawl-ref/source/dat/des/portals/gauntlet.des index e1be51920102..f639371dd4ac 100644 --- a/crawl-ref/source/dat/des/portals/gauntlet.des +++ b/crawl-ref/source/dat/des/portals/gauntlet.des @@ -1477,10 +1477,10 @@ MAP c..n.ndddddddddn.naaaaaaaaan.neeeeeeeeen.n..c ccccccccccccc..n.ndddddddddn.naaaaaaaaan.neeeeeeeeen.n..ccccccccccccc cG.............n.nnnnddddddnnnnnnnnnnnnnnneeeeeennnn.n.............Gc -ccccc..............n.n--G--nF.........E.........Jn--G--n.n..............ccccc +ccccc..............n.nllGllnF.........E.........JnllGlln.n..............ccccc cG.....nnnnnnnnnnnnn.nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn.nnnnnnnnnnnnn.....Gc -c......nL...........N...........Pn.........nR...........p...........rn......c -c..nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn.nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn..c +c......nL...........N...........PnllllGllllnR...........p...........rn......c +c..nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn..c c..fffffffffff.ggggggggggg.hhhhhhhhhhh.iiiiiiiiiii.jjjjjjjjjjj.kkkkkkkkkkk..c c..fffffffffff.ggggggggggg.hhhhhhhhhhh.iiiiiiiiiii.jjjjjjjjjjj.kkkkkkkkkkk..c c..fffffffffff.ggggggggggg.hhhhhhhhhhh.iiiiiiiiiii.jjjjjjjjjjj.kkkkkkkkkkk..c From 6670cd2b35f0b83f40a6b8e14cd82a09caaa9759 Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 6 Feb 2019 16:02:29 -0500 Subject: [PATCH 078/864] Explicitly track visited levels My previous pregen-related commits tried to avoid this, but I don't think it can be avoided. The basic problem is that this information is also present in the turncount on a level, but that information is saved with the level chunk, and it turns out to be kind of useful to have in many cases where the player isn't on the level in question. Previously, whether a level was generated (which is tracked in a simple way in the save package) was synonymous with whether the level had been visited, so most code just used that. The new implementation uses a CrawlHashTable as a prop on the player. This commit specifically fixes three pregen bugs: (i) rune locks were broken (would always open), (ii) jiyva would eat items on all levels, not just levels you'd visited, and (iii) one of the perennial problems with pregen implementations, X] shows a blank screen. It also further cleans up the morgue vault listing code, and provides more information for a wizmode morgue. If there are any pregen games in the wild yet, this fix won't do save compat for them and they'll still have these bugs, but it will do save compat for regular games. --- crawl-ref/source/abyss.cc | 1 + crawl-ref/source/chardump.cc | 2 +- crawl-ref/source/dgn-overview.cc | 2 +- crawl-ref/source/dungeon.cc | 35 +++++++++++++++-- crawl-ref/source/files.cc | 66 ++++++++++++++++++++++++++++++-- crawl-ref/source/files.h | 1 + crawl-ref/source/god-passive.cc | 2 +- crawl-ref/source/main.cc | 2 +- crawl-ref/source/player.cc | 3 ++ crawl-ref/source/player.h | 4 ++ crawl-ref/source/stairs.cc | 2 +- crawl-ref/source/tilepick.cc | 4 +- crawl-ref/source/viewmap.cc | 6 +-- 13 files changed, 113 insertions(+), 17 deletions(-) diff --git a/crawl-ref/source/abyss.cc b/crawl-ref/source/abyss.cc index 48d8b58b81a4..f72a506c3379 100644 --- a/crawl-ref/source/abyss.cc +++ b/crawl-ref/source/abyss.cc @@ -1060,6 +1060,7 @@ static level_id _get_random_level() for (int j = 1; j <= brdepth[it->id]; ++j) { const level_id id(it->id, j); + // for pregen, this will use levels the player hasn't seen yet if (is_existing_level(id)) levels.push_back(id); } diff --git a/crawl-ref/source/chardump.cc b/crawl-ref/source/chardump.cc index d33ea296554e..da6688976b26 100644 --- a/crawl-ref/source/chardump.cc +++ b/crawl-ref/source/chardump.cc @@ -1116,7 +1116,7 @@ static void _sdump_vault_list(dump_params &par) #endif ) { - par.text += "Vault maps used:\n"; + par.text += "Levels and vault maps discovered:\n"; par.text += dump_vault_maps(); par.text += "\n"; } diff --git a/crawl-ref/source/dgn-overview.cc b/crawl-ref/source/dgn-overview.cc index d6a1ee4c353d..678afa4bedc0 100644 --- a/crawl-ref/source/dgn-overview.cc +++ b/crawl-ref/source/dgn-overview.cc @@ -485,7 +485,7 @@ static string _get_shops(bool display) { if (entry.first.id != last_id) { - const bool existing = is_existing_level(entry.first.id); + const bool existing = you.level_visited(entry.first.id); if (column_count > maxcolumn) { disp += "\n"; diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 961d9033cd3a..367728d3694a 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -6901,17 +6901,44 @@ string dump_vault_maps() for (const level_id &lid : levels) { - if (!you.vault_list.count(lid)) + // n.b. portal vaults get cleared from here, so won't show up. + // kind of spammy in wizmode. To test non-wizmode, use &ctrl-y + if (!you.wizard && (!you.level_visited(lid) + || !you.vault_list.count(lid)) + || branch_is_unfinished(lid.branch)) + { continue; + } - out += lid.describe() + ": " + string(max(8 - int(lid.describe().length()), 0), ' '); - + if (you.wizard) + { + if (!is_existing_level(lid)) + { + out += " (not gen.) " + lid.describe() + "\n"; + continue; + } + out += you.level_visited(lid) ? " (visited) " : "(unvisited) "; + } + out += lid.describe(); vector &maps(you.vault_list[lid]); + if (maps.size() == 0) + { + out += "\n"; + continue; + } + + out += ": " + string(max(8 - int(lid.describe().length()), 0), ' '); + + // TODO: some way of showing no_dump maps in wizmode? string vaults = comma_separated_line(maps.begin(), maps.end(), ", "); out += wordwrap_line(vaults, 70) + "\n"; while (!vaults.empty()) - out += " " + wordwrap_line(vaults, 70, false) + "\n"; + { + out += string(you.wizard ? 22 : 10, ' ') + + wordwrap_line(vaults, 70, false) + "\n"; + } + } return out; } diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 2297f713fda0..51d909b7e29a 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1396,6 +1396,59 @@ static void _count_gold() } } +static const string VISITED_LEVELS_KEY = "visited_levels"; + +#if TAG_MAJOR_VERSION == 34 +// n.b. these functions are in files.cc largely because this is where the fixup +// needs to happen. +// before pregeneration, whether the level had been visited was synonymous with +// whether it had been visited, but after, we need to track this information +// more directly. It is also inferrable from turns_on_level, but you can't get +// at that very easily without fully loading the level. +// no need for a minor version here, though there will be a brief window of +// offline pregen games that this doesn't handle right -- they will get things +// like broken runelock. (In principle this fixup could be done by loading +// each level and checking turns, but it's not worth the trouble for these few +// games.) +static void _fixup_visited_from_package() +{ + // for games started later than this fixup, this prop is initialized in + // player::player + CrawlHashTable &visited = you.props[VISITED_LEVELS_KEY].get_table(); + if (visited.size()) // only 0 for upgrades, or before entering D:1 + return; + vector levels = all_dungeon_ids(); + for (const level_id &lid : levels) + if (is_existing_level(lid)) + visited[lid.describe()] = true; +} +#endif + +void player::init_level_visited() +{ + if (!props.exists(VISITED_LEVELS_KEY)) + props[VISITED_LEVELS_KEY].new_table(); +} + +void player::set_level_visited(const level_id &level) +{ + ASSERT(props.exists(VISITED_LEVELS_KEY)); + auto &visited = props[VISITED_LEVELS_KEY].get_table(); + visited[level.describe()] = true; +} + +bool player::level_visited(const level_id &level) +{ + // this will mean that portal maps that the player is not currently on + // return false, since the map gets deleted. A continuation of legacy + // behavior... + if (!is_existing_level(level)) + return false; + ASSERT(props.exists(VISITED_LEVELS_KEY)); + const auto &visited = props[VISITED_LEVELS_KEY].get_table(); + return visited.exists(level.describe()); +} + /** * Load the current level. * @@ -1410,6 +1463,12 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, const bool make_changes = (load_mode == LOAD_START_GAME || load_mode == LOAD_ENTER_LEVEL); +#if TAG_MAJOR_VERSION == 34 + // fixup saves that don't have this prop initialized. + if (load_mode != LOAD_START_GAME && you.elapsed_time != 0) + _fixup_visited_from_package(); +#endif + // Did we get here by popping the level stack? bool popped = false; @@ -1489,6 +1548,7 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, ASSERT(load_mode != LOAD_VISITOR); dprf("Generating new level for '%s'.", level_name.c_str()); _make_level(stair_taken, old_level); + you.vault_list[level_id::current()] = level_vault_names(); just_created_level = true; } else @@ -1519,10 +1579,10 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, } if (env.turns_on_level == 0) - { just_created_level = true; // in case level was pre-generated - you.vault_list[level_id::current()] = level_vault_names(); - } + + if (load_mode != LOAD_VISITOR) + you.set_level_visited(level_id::current()); // Markers must be activated early, since they may rely on // events issued later, e.g. DET_ENTERING_LEVEL or diff --git a/crawl-ref/source/files.h b/crawl-ref/source/files.h index 39304959b8f6..fbe2db6a150e 100644 --- a/crawl-ref/source/files.h +++ b/crawl-ref/source/files.h @@ -103,6 +103,7 @@ class level_excursion protected: level_id original; bool ever_changed_levels; + bool allow_unvisited; public: level_excursion(); diff --git a/crawl-ref/source/god-passive.cc b/crawl-ref/source/god-passive.cc index ce5de5886a84..b49903d7eaf2 100644 --- a/crawl-ref/source/god-passive.cc +++ b/crawl-ref/source/god-passive.cc @@ -497,7 +497,7 @@ void jiyva_eat_offlevel_items() const level_id lid(static_cast(branch), level); - if (lid == level_id::current() || !is_existing_level(lid)) + if (lid == level_id::current() || !you.level_visited(lid)) continue; dprf("Checking %s", lid.describe().c_str()); diff --git a/crawl-ref/source/main.cc b/crawl-ref/source/main.cc index 50a1e2c92b0b..81103963359d 100644 --- a/crawl-ref/source/main.cc +++ b/crawl-ref/source/main.cc @@ -1281,7 +1281,7 @@ static bool _can_take_stairs(dungeon_feature_type ftype, bool down, if (ftype != it->entry_stairs) continue; - if (!is_existing_level(level_id(it->id, 1))) + if (!you.level_visited(level_id(it->id, 1))) { min_runes = runes_for_branch(it->id); if (runes_in_pack() < min_runes) diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index b570d17bbf96..799de7e6e112 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -34,6 +34,7 @@ #include "env.h" #include "errors.h" #include "exercise.h" +#include "files.h" #include "food.h" #include "god-abil.h" #include "god-conduct.h" @@ -5215,6 +5216,8 @@ player::player() travel_y = 0; travel_z = level_id(); + init_level_visited(); + running.clear(); travel_ally_pace = false; received_weapon_warning = false; diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h index 055d4484cc45..4819249f8f82 100644 --- a/crawl-ref/source/player.h +++ b/crawl-ref/source/player.h @@ -482,6 +482,10 @@ class player : public actor void shiftto(const coord_def &c); bool blink_to(const coord_def& c, bool quiet = false) override; + void init_level_visited(); + void set_level_visited(const level_id &level); + bool level_visited(const level_id &level); + int stat(stat_type stat, bool nonneg = true) const; int strength(bool nonneg = true) const; int intel(bool nonneg = true) const; diff --git a/crawl-ref/source/stairs.cc b/crawl-ref/source/stairs.cc index 9c2559bded7c..8ee150b38f68 100644 --- a/crawl-ref/source/stairs.cc +++ b/crawl-ref/source/stairs.cc @@ -543,7 +543,7 @@ static level_id _travel_destination(const dungeon_feature_type how, if (how != it->entry_stairs) continue; - if (!is_existing_level(level_id(it->id, 1)) + if (!you.level_visited(level_id(it->id, 1)) && runes_for_branch(it->id) > 0) { _rune_effect(how); diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc index 8461598e8afd..3056dd613822 100644 --- a/crawl-ref/source/tilepick.cc +++ b/crawl-ref/source/tilepick.cc @@ -316,14 +316,14 @@ tileidx_t tileidx_feature_base(dungeon_feature_type feat) case DNGN_ENTER_DEPTHS: return TILE_DNGN_ENTER_DEPTHS; case DNGN_ENTER_VAULTS: - return is_existing_level(level_id(BRANCH_VAULTS, 1)) ? TILE_DNGN_ENTER_VAULTS_OPEN + return you.level_visited(level_id(BRANCH_VAULTS, 1)) ? TILE_DNGN_ENTER_VAULTS_OPEN : TILE_DNGN_ENTER_VAULTS_CLOSED; case DNGN_ENTER_CRYPT: return TILE_DNGN_ENTER_CRYPT; case DNGN_ENTER_TOMB: return TILE_DNGN_ENTER_TOMB; case DNGN_ENTER_ZOT: - return is_existing_level(level_id(BRANCH_ZOT, 1)) ? TILE_DNGN_ENTER_ZOT_OPEN + return you.level_visited(level_id(BRANCH_ZOT, 1)) ? TILE_DNGN_ENTER_ZOT_OPEN : TILE_DNGN_ENTER_ZOT_CLOSED; case DNGN_ENTER_ZIGGURAT: return TILE_DNGN_PORTAL_ZIGGURAT; diff --git a/crawl-ref/source/viewmap.cc b/crawl-ref/source/viewmap.cc index fbc261c1ad01..ab9465e0e22c 100644 --- a/crawl-ref/source/viewmap.cc +++ b/crawl-ref/source/viewmap.cc @@ -1019,7 +1019,7 @@ bool show_map(level_pos &lpos, } if (dest.id.is_valid() && dest.id != level_id::current() - && is_existing_level(dest.id)) + && you.level_visited(dest.id)) { lpos = dest; } @@ -1038,7 +1038,7 @@ bool show_map(level_pos &lpos, if (pos.id.depth < 1 || pos.id.depth > brdepth[pos.id.branch] - || !is_existing_level(pos.id)) + || !you.level_visited(pos.id)) { canned_msg(MSG_OK); redraw_map = true; @@ -1188,7 +1188,7 @@ bool show_map(level_pos &lpos, move_y = you.travel_y - lpos.pos.y; } else if (allow_offlevel && you.travel_z.is_valid() - && is_existing_level(you.travel_z)) + && you.level_visited(you.travel_z)) { // previous travel target is offlevel lpos = level_pos(you.travel_z, From c81a88522234ca4b793bd6acaec6945f8f916625 Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 6 Feb 2019 16:25:18 -0500 Subject: [PATCH 079/864] Pregenerate the vestibule I'm beginning to think that this is_valid() check isn't very good... --- crawl-ref/source/startup.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index 7e1e4a206bae..78c838fc57c7 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -313,9 +313,11 @@ static void _pregen_dungeon() progress_popup progress("Generating dungeon...\n\n", 35); progress.advance_progress(); // TODO: why is dungeon invalid? it's not set up properly in - // `initialise_branch_depths` for some reason. + // `initialise_branch_depths` for some reason. The vestibule is invalid + // because its depth isn't set until the player actually enters a portal. for (auto br : generation_order) - if (brentry[br].is_valid() || br == BRANCH_DUNGEON) + if (brentry[br].is_valid() + || br == BRANCH_DUNGEON || br == BRANCH_VESTIBULE) { string status = "\nbuilding "; From e8a6cd6aab31865dd19e9b10ea144cc940a68a67 Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 6 Feb 2019 17:35:24 -0500 Subject: [PATCH 080/864] Improve webtiles support for seeding/pregen This adds a new command line option `-pregen`, as well as an argument-less version of "-seed" that triggers the seed choice menu and sets the right game type. Bothing seeding and pregen are usable from the command line in DGL builds, though rc file options that set these are still disabled in DGL builds so that server owners have some control. So calling "./crawl -name asdf -seed" will pop up the seed choice menu before starting the game, and (if a user picks a non-0 seed) will start a game of type "Seeded", and "./crawl -name asdf -seed 1 -pregen" will force pregeneration of seed 1 after character selection. This is pretty simple to set up in vanilla webtiles, I've included an example in config.py (which of course no one merges). One awkwardness (also for tutorial) is that these options will load a non-seeded game if there is one under the right name, which is logical but not very intuitive as a UI thing (you'd probably want to give an error). caveat emptor: nothing else in the crawl infrastructure (especially sequell) has been set up to handle the new game type, and I have no idea what would happen if you try to publish milestones using it. So if you are thinking about using this in a live server, test it out carefully... --- crawl-ref/source/initfile.cc | 14 ++++++++++++-- crawl-ref/source/newgame.cc | 5 +---- crawl-ref/source/options.h | 2 -- crawl-ref/source/startup.cc | 4 ---- crawl-ref/source/webserver/config.py | 13 +++++++++++++ 5 files changed, 26 insertions(+), 12 deletions(-) diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index a2e70c7f3a4a..f4f8343e86d1 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -297,6 +297,7 @@ const vector game_options::build_options_list() #ifndef DGAMELAUNCH new BoolGameOption(SIMPLE_NAME(pregen_dungeon), false), #endif + #ifdef DGL_SIMPLE_MESSAGING new BoolGameOption(SIMPLE_NAME(messaging), false), #endif @@ -3812,6 +3813,7 @@ enum commandline_option_type CLO_HELP, CLO_VERSION, CLO_SEED, + CLO_PREGEN, CLO_SAVE_VERSION, CLO_SPRINT, CLO_EXTRA_OPT_FIRST, @@ -3843,7 +3845,7 @@ static const char *cmd_ops[] = "scores", "name", "species", "background", "dir", "rc", "rcdir", "tscores", "vscores", "scorefile", "morgue", "macro", "mapstat", "dump-disconnect", "objstat", "iters", "force-map", "arena", "dump-maps", "test", "script", - "builddb", "help", "version", "seed", "save-version", "sprint", + "builddb", "help", "version", "seed", "pregen", "save-version", "sprint", "extra-opt-first", "extra-opt-last", "sprint-map", "edit-save", "print-charset", "tutorial", "wizard", "explore", "no-save", "gdb", "no-gdb", "nogdb", "throttle", "no-throttle", "playable-json", @@ -4903,7 +4905,11 @@ bool parse_args(int argc, char **argv, bool rc_only) case CLO_SEED: if (!next_is_param) - return false; + { + // show seed choice menu + Options.game.type = GAME_TYPE_CUSTOM_SEED; + break; + } if (!sscanf(next_arg, "%" SCNu64, &Options.seed_from_rc)) return false; @@ -4911,6 +4917,10 @@ bool parse_args(int argc, char **argv, bool rc_only) nextUsed = true; break; + case CLO_PREGEN: + Options.pregen_dungeon = true; + break; + case CLO_SPRINT: if (!rc_only) Options.game.type = GAME_TYPE_SPRINT; diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index bd3491656d66..6b3a1acf9901 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -643,6 +643,7 @@ static void _choose_name(newgame_def& ng, newgame_def& choice) game_ended(game_exit::abort); } +#endif static void _choose_seed(newgame_def& ng, newgame_def& choice, const newgame_def& defaults) @@ -741,8 +742,6 @@ static void _choose_seed(newgame_def& ng, newgame_def& choice, Options.pregen_dungeon = choice.pregenerate; } -#endif - // Read a choice of game into ng. // Returns false if a game (with name ng.name) should // be restored instead of starting a new character. @@ -767,10 +766,8 @@ bool choose_game(newgame_def& ng, newgame_def& choice, { _choose_gamemode_map(ng, choice, defaults); } -#ifndef DGAMELAUNCH else if (ng.type == GAME_TYPE_CUSTOM_SEED) _choose_seed(ng, choice, defaults); -#endif _choose_char(ng, choice, defaults); diff --git a/crawl-ref/source/options.h b/crawl-ref/source/options.h index ef74a8c6f9ab..3c0cfb390b8f 100644 --- a/crawl-ref/source/options.h +++ b/crawl-ref/source/options.h @@ -172,9 +172,7 @@ struct game_options uint64_t seed; // Non-random games. uint64_t seed_from_rc; -#ifndef DGAMELAUNCH bool pregen_dungeon; // Is the dungeon generated at the beginning? -#endif #ifdef DGL_SIMPLE_MESSAGING bool messaging; // Check for messages. diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index 78c838fc57c7..bc2a4e1b490c 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -237,7 +237,6 @@ static void _zap_los_monsters(bool items_also) } } -#ifndef DGAMELAUNCH /** * Ensure that the level given by `pos` is generated. This does not do much in * the way of cleanup, and the caller must ensure the player ends up somewhere @@ -340,7 +339,6 @@ static void _pregen_dungeon() progress.advance_progress(); } } -#endif static void _post_init(bool newc) { @@ -367,10 +365,8 @@ static void _post_init(bool newc) if (newc) { -#ifndef DGAMELAUNCH if (Options.pregen_dungeon && crawl_state.game_standard_levelgen()) _pregen_dungeon(); -#endif you.entering_level = false; you.transit_stair = DNGN_UNSEEN; diff --git a/crawl-ref/source/webserver/config.py b/crawl-ref/source/webserver/config.py index 32124efa1587..0b68afc15d27 100644 --- a/crawl-ref/source/webserver/config.py +++ b/crawl-ref/source/webserver/config.py @@ -74,6 +74,19 @@ client_path = "./webserver/game_data/", morgue_url = None, send_json_options = True)), + ("seeded-web-trunk", dict( + name = "DCSS trunk, custom seed", + crawl_binary = "./crawl", + rcfile_path = "./rcs/", + macro_path = "./rcs/", + morgue_path = "./rcs/%n", + inprogress_path = "./rcs/running", + ttyrec_path = "./rcs/ttyrecs/%n", + socket_path = "./rcs", + client_path = "./webserver/game_data/", + morgue_url = None, + send_json_options = True, + options = ["-seed"])), ("sprint-web-trunk", dict( name = "Sprint trunk", crawl_binary = "./crawl", From d227540562d14265d4750c4136ad9c592baff580 Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 6 Feb 2019 17:43:28 -0500 Subject: [PATCH 081/864] Fix progress bar webtiles behavior Not sure what happened here. --- crawl-ref/source/webserver/game_data/static/ui-layouts.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/webserver/game_data/static/ui-layouts.js b/crawl-ref/source/webserver/game_data/static/ui-layouts.js index 836d9773da22..242201be0cca 100644 --- a/crawl-ref/source/webserver/game_data/static/ui-layouts.js +++ b/crawl-ref/source/webserver/game_data/static/ui-layouts.js @@ -80,19 +80,18 @@ function ($, comm, client, ui, enums, cr, util, scroller, main, gui, player) { $popup.children(".header").remove(); else $popup.find(".header > span").html(msg.title); - $popup.children(".bar-text > span").html( - util.formatted_string_to_html(msg.bar_text)); + $popup.children(".bar-text").html("" + + util.formatted_string_to_html(msg.bar_text) + ""); $popup.children(".status > span").html(msg.status); return $popup; } function progress_bar_update(msg) { - console.log("progress bar update"); var $popup = ui.top_popup(); if (!$popup.hasClass("progress-bar")) return; - $popup.children(".bar-text").html("span" + + $popup.children(".bar-text").html("" + util.formatted_string_to_html(msg.bar_text) + ""); $popup.children(".status")[0].textContent = msg.status; } From cb1519bca2e6124cddf0d413dfbfa068c2fc042c Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 6 Feb 2019 18:12:29 -0500 Subject: [PATCH 082/864] checkwhite --- crawl-ref/source/files.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 51d909b7e29a..6f0c1362d8ed 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1404,7 +1404,7 @@ static const string VISITED_LEVELS_KEY = "visited_levels"; // before pregeneration, whether the level had been visited was synonymous with // whether it had been visited, but after, we need to track this information // more directly. It is also inferrable from turns_on_level, but you can't get -// at that very easily without fully loading the level. +// at that very easily without fully loading the level. // no need for a minor version here, though there will be a brief window of // offline pregen games that this doesn't handle right -- they will get things // like broken runelock. (In principle this fixup could be done by loading From f005ca4cc3c9c807b1eba8117eaf71839c013925 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Mon, 4 Feb 2019 15:51:36 -0600 Subject: [PATCH 083/864] Decorations for 9x9 Gauntlet maps Use a consistent statue display wall motif for all four 9x9 Gauntlets. Also add various statues and lava tiles throughout the maps. This helps give these 9x9 maps a common feel, similar to how the 7x7 and mixed 7x7/9x9 map sets each have their own decorative themes. --- crawl-ref/source/dat/des/portals/gauntlet.des | 449 +++++++++--------- 1 file changed, 229 insertions(+), 220 deletions(-) diff --git a/crawl-ref/source/dat/des/portals/gauntlet.des b/crawl-ref/source/dat/des/portals/gauntlet.des index f639371dd4ac..779a98199ac9 100644 --- a/crawl-ref/source/dat/des/portals/gauntlet.des +++ b/crawl-ref/source/dat/des/portals/gauntlet.des @@ -1227,67 +1227,70 @@ SUBVAULT: j : gauntlet_arena_second SUBVAULT: y : gauntlet_exit : gauntlet_appearance(_G) MAP - ccccccccccccccccccccccccccccccc - cG............G Date: Wed, 6 Feb 2019 22:10:58 -0500 Subject: [PATCH 084/864] Update CREDITS.txt [skip ci] --- crawl-ref/CREDITS.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crawl-ref/CREDITS.txt b/crawl-ref/CREDITS.txt index b5d678ac7e38..4d18a26d31cd 100644 --- a/crawl-ref/CREDITS.txt +++ b/crawl-ref/CREDITS.txt @@ -116,6 +116,7 @@ Cerol Rahul Chandra Thom Chiovoloni + Anthony Chuah Henry Cipolla Nicholas Connelly Tom Conrad @@ -145,6 +146,7 @@ Kyle Fox freepotion Chris Galardi + GenericPseudonym Ge0ff Benoît Giannangeli Ben Goetter @@ -240,6 +242,7 @@ Yuuma Oohara Julian Ospald Malwyn P + palyth panicbit William Parker Pedro @@ -278,6 +281,7 @@ Robert Shimmin Sigurd Edgar Simo + Skrybe Alex Smith Keanan Smith Richard Soderberg @@ -285,6 +289,7 @@ Solf Michael Spang David Speare + Martin Staffa John Stahara Jan 'heftig' Steffens Stenella From 091e5a18feebe401102f8e255d12d97d8bf38492 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 7 Feb 2019 09:20:14 -0500 Subject: [PATCH 085/864] Catch dgn_veto_exception when placing maps from lua When an exception is thrown across lua code, it severely messes with the lua stack and lua's use of setjmp/longjmp, at least for the way we have it configured. This was causing pretty bad crashes on post-place hooks when run from tests: the exception was thrown in c++ called from lua called from c++ called from lua called from c++, and caught in the intermediate c++ black, and basically treated as a lua error (I think), but just clobbered the lua stack, so the outer calling lua was left in an indeterminate state and any error there (which would happen immediately, as variables were shuffled) would cause a longjmp failure. This didn't go quite so badly in practice when there wasn't the outer test lua layer, but I still think it's pretty risky to allow throwing this, unless we shift lua to itself use try/catch. This commit *changes the behavior* of post-place hooks. Previously, they would implicitly veto the entire map if a post-place hook map placement call failed. Now, they will only veto if the post-place hook sets die_on_error (which none do). In practice, this probably comes up for serial vaults (e.g. serial_forest) which can place many subvaults, where some of the later tries fail on a crowded level. I have left a note in However, it may have bigger implications. The quick fix for any maps that really need the old behavior would be to call lua `error()`, though this will print an error message to the player. (cherry picked from commit 72689e85ba0b1ffd4eac588e90b4b83a4ce88d4b) --- crawl-ref/source/l-dgn.cc | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/crawl-ref/source/l-dgn.cc b/crawl-ref/source/l-dgn.cc index e68a2b59611f..b10e3faf1f37 100644 --- a/crawl-ref/source/l-dgn.cc +++ b/crawl-ref/source/l-dgn.cc @@ -1483,15 +1483,27 @@ LUAFN(_dgn_place_map) dgn_map_parameters mp(lua_gettop(ls) >= 6 ? luaL_checkstring(ls, 6) : ""); - if (dgn_place_map(map, check_collision, no_exits, where) - && !env.level_vaults.empty()) + try { - lua_pushlightuserdata(ls, env.level_vaults.back().get()); + if (dgn_place_map(map, check_collision, no_exits, where) + && !env.level_vaults.empty()) + { + lua_pushlightuserdata(ls, env.level_vaults.back().get()); + return 1; + } + } + catch (dgn_veto_exception& e) + { + // letting this exception go back across lua code can apparently + // do very bad things for the lua stack, if it isn't compiled with + // c++ mode. (Which we don't do by default.) + // Won't necessarily veto the level, but we want to report it still. + dprf(DIAG_DNGN, "veto in dgn.place_maps: %s: %s", + level_id::current().describe().c_str(), e.what()); } - else - lua_pushnil(ls); } - return 1; + lua_pushnil(ls); + return 0; } LUAFN(_dgn_in_vault) From 56b24058a9e152f3998092aa1b376c827b5d5054 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 7 Feb 2019 10:40:41 -0500 Subject: [PATCH 086/864] Adjust one post_place hook After auditing the post_place calls, I see some potential issues, but not many that are made worse by 091e5a18feeb (mostly cases where persistent dungeon state is probably not handled correctly if map placement fails). This is the only vault I found that really doesn't make sense unless the map placement works, and wasn't already set up to abort on failure. I didn't adjust any serial vaults, so it's conceivable that these could now place without any post_place placements working in rare cases, so they may need tweaking if this comes up a lot. The awkward thing about die_on_failure is that it (probably) prints a lua error to the player. However, the only reason why the old code didn't print a (more cryptic) error on a veto was because the error handling code was buggy in the face of an exception. It may be that we'd want a way of having a silent die_on_failure though. --- crawl-ref/source/dat/des/branches/pan.des | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/dat/des/branches/pan.des b/crawl-ref/source/dat/des/branches/pan.des index 7d64ed68989b..11b962ee4e43 100644 --- a/crawl-ref/source/dat/des/branches/pan.des +++ b/crawl-ref/source/dat/des/branches/pan.des @@ -222,8 +222,8 @@ function pan_highlights_setup(e) vaulttwo = "_" .. util.random_from(set) end e.hook('post_place', function () - dgn.place_maps{tag=("pan_fixed_rune" .. vaultone), count=1} - dgn.place_maps{tag=("pan_fixed_lure" .. vaulttwo), count=1} + dgn.place_maps{tag=("pan_fixed_rune" .. vaultone), count=1, die_on_error=true} + dgn.place_maps{tag=("pan_fixed_lure" .. vaulttwo), count=1, die_on_error=true} dgn.place_maps{tag=("serial_pan" .. vaultone), count=3} dgn.place_maps{tag=("serial_pan" .. vaulttwo), count=3} end) From f756fb0b9a79f8a3aac89cef304be1477b4d86d7 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Thu, 7 Feb 2019 10:15:57 -0600 Subject: [PATCH 087/864] Update the Debian changelog for 0.23 (cherry picked from commit 195ea7e421b6cb7e468f0b6391be23ac66777778) --- crawl-ref/source/debian/changelog | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crawl-ref/source/debian/changelog b/crawl-ref/source/debian/changelog index 41b7a5e45777..63da083b84fe 100644 --- a/crawl-ref/source/debian/changelog +++ b/crawl-ref/source/debian/changelog @@ -1,3 +1,8 @@ +crawl (2:0.23.0-1) UNRELEASED; urgency=low + + * New upstream release. + -- gammafunk Thu, 07 Feb 2019 10:07:00 -0600 + crawl (2:0.22.0-1) UNRELEASED; urgency=low * New upstream release. From b3eb09ec81ca312fbc33cb756b439beff689aeec Mon Sep 17 00:00:00 2001 From: gammafunk Date: Thu, 7 Feb 2019 11:07:09 -0600 Subject: [PATCH 088/864] Final changelog for 0.23 Some wording tweaks and typo corrections. [skip ci] --- crawl-ref/docs/changelog.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/crawl-ref/docs/changelog.txt b/crawl-ref/docs/changelog.txt index 4fcb2f7bfb88..83afe95ba11a 100644 --- a/crawl-ref/docs/changelog.txt +++ b/crawl-ref/docs/changelog.txt @@ -1,17 +1,17 @@ -Stone Soup 0.23 (up to 0.23-b1-56-gfe314ee208) ----------------------------------------------- +Stone Soup 0.23 (20190207) +-------------------------- Highlights ---------- -* Trap system rework +* Trap system overhaul * New Gauntlet portal to replace Labyrinths * Nemelex Xobeh rework * Nine unrandarts reworked and the new "Rift" unrandart added -* Supported for seeded dungeon play +* Support for seeded dungeon play Branches, Environment --------------------- -* Traps have been reworked: +* Trap system overhaul: - Traps that generate on the ground are always revealed. - Exploration has a chance to trigger a "trap effect" independent from terrain traps. The possible effects are alarm, shaft, and teleport near @@ -24,7 +24,7 @@ Branches, Environment - Trap placement in Ossuaries, Zot:5, and Tomb has been overhauled. In Zot:5 and Tomb, all mechanical traps save for net traps have been removed. - Grate traps (triggered by pressure plates) have been removed. -* A new Gauntlet portal that replaces Labyrinths: +* New Gauntlet portal to replace Labyrinths: - Gauntlets have the player choose a path through several combat arenas, each of which contains (sometimes exotic) monsters and loot. - Access to each arena is one-way using transporters. Teleports and Passage @@ -60,7 +60,7 @@ Character Gods ---- -* Nemelex Xobeh has been reworked: +* Nemelex Xobeh rework: - Decks are are accessed through abilities and no longer exist as items. - Nemelex offers three abilities: "Draw Escape", "Draw Destruction", and "Draw Summoning", which provide card effects. From ce0dbf48b24ca332c65fee4907495536bbfbcd72 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 7 Feb 2019 12:19:12 -0500 Subject: [PATCH 089/864] Fix vault printing in morgues after game end (NP7) It turns out that the save is already deleted at this point, so some of the checks I was using for level existence weren't working right. --- crawl-ref/source/dungeon.cc | 4 +++- crawl-ref/source/files.cc | 8 ++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 367728d3694a..57cd81a6a7d8 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -6912,7 +6912,9 @@ string dump_vault_maps() if (you.wizard) { - if (!is_existing_level(lid)) + // because the save is already gone at the point where we are + // printing a morgue, this check isn't reliable. Ignore it. + if (!is_existing_level(lid) && you.save) { out += " (not gen.) " + lid.describe() + "\n"; continue; diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 6f0c1362d8ed..1e1872d7f002 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1442,7 +1442,9 @@ bool player::level_visited(const level_id &level) // this will mean that portal maps that the player is not currently on // return false, since the map gets deleted. A continuation of legacy // behavior... - if (!is_existing_level(level)) + // `is_existing_level` is not reliable after the game end, because the + // save no longer exists, so we ignore it for printing morgues + if (!is_existing_level(level) && you.save) return false; ASSERT(props.exists(VISITED_LEVELS_KEY)); const auto &visited = props[VISITED_LEVELS_KEY].get_table(); @@ -2565,7 +2567,9 @@ static void _load_level(const level_id &level) } // Given a level returns true if the level has been created already -// in this game. +// in this game. Warning: after a game has ended, there is a phase where the +// save has been deleted and this check isn't usable, and this is when a moruge +// is generated. bool is_existing_level(const level_id &level) { return you.save && you.save->has_chunk(level.describe()); From a7c82940b45ba62c97a06872b4c0cba7e351d0b9 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 7 Feb 2019 20:24:26 -0500 Subject: [PATCH 090/864] Improve save compat for visited level tracking What I had written before wouldn't work for a turn 0 save, and it appears that the default constructor isn't necessarily getting called so the fixup needs to initialize the prop. --- crawl-ref/source/files.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 1e1872d7f002..5c282a0a2bb3 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1414,6 +1414,7 @@ static void _fixup_visited_from_package() { // for games started later than this fixup, this prop is initialized in // player::player + init_level_visited(); // is this necessary? CrawlHashTable &visited = you.props[VISITED_LEVELS_KEY].get_table(); if (visited.size()) // only 0 for upgrades, or before entering D:1 return; @@ -1467,7 +1468,7 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, #if TAG_MAJOR_VERSION == 34 // fixup saves that don't have this prop initialized. - if (load_mode != LOAD_START_GAME && you.elapsed_time != 0) + if (load_mode == LOAD_RESTART_GAME) _fixup_visited_from_package(); #endif From 4e4936a574234c6cefb5c3cdb9e9f6edddc0b693 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 7 Feb 2019 20:26:43 -0500 Subject: [PATCH 091/864] fix the fix --- crawl-ref/source/files.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 5c282a0a2bb3..2acb9159e74a 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1414,7 +1414,7 @@ static void _fixup_visited_from_package() { // for games started later than this fixup, this prop is initialized in // player::player - init_level_visited(); // is this necessary? + you.init_level_visited(); // is this necessary? CrawlHashTable &visited = you.props[VISITED_LEVELS_KEY].get_table(); if (visited.size()) // only 0 for upgrades, or before entering D:1 return; From 7d8ec5708864d2872871cd49295b12a5b291238d Mon Sep 17 00:00:00 2001 From: gammafunk Date: Fri, 8 Feb 2019 14:06:15 -0600 Subject: [PATCH 092/864] Add a trunk reminder for the 0.23 tournament [skip ci] --- crawl-ref/source/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/Makefile b/crawl-ref/source/Makefile index 7b2c5400a47e..75fa8b9bcfaf 100644 --- a/crawl-ref/source/Makefile +++ b/crawl-ref/source/Makefile @@ -112,7 +112,7 @@ CFOTHERS := -pipe $(EXTERNAL_FLAGS) CFWARN := CFWARN_L := -Wall -Wformat-security -Wundef -DEFINES := $(EXTERNAL_DEFINES) +DEFINES := -DTOURNEY='"0.23"' $(EXTERNAL_DEFINES) ifndef ANDROID LDFLAGS := From e1bfdf8443a35b3bb6124f329f4cf2d74e396399 Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 9 Feb 2019 15:20:53 -0500 Subject: [PATCH 093/864] Fix a shopping list crash This commit actually initializes the member variables for ShoppingList, most importantly `list`, and resets the global shopping_list object in _reset_game(). When a game had a shopping list and reset_after_save was true, then saving that game and opening a new one would lead to a stale pointer to the first game's deallocated shopping list prop. Having this object work by a live pointer to a member of you.props is probably not a great idea, all around... --- crawl-ref/source/main.cc | 1 + crawl-ref/source/shopping.cc | 2 ++ 2 files changed, 3 insertions(+) diff --git a/crawl-ref/source/main.cc b/crawl-ref/source/main.cc index 81103963359d..42c4fc8f808e 100644 --- a/crawl-ref/source/main.cc +++ b/crawl-ref/source/main.cc @@ -345,6 +345,7 @@ static void _reset_game() clear_message_store(); macro_clear_buffers(); the_lost_ones.clear(); + shopping_list = ShoppingList(); you = player(); reset_hud(); StashTrack = StashTracker(); diff --git a/crawl-ref/source/shopping.cc b/crawl-ref/source/shopping.cc index 3b64f3940cd0..ff7ca565068a 100644 --- a/crawl-ref/source/shopping.cc +++ b/crawl-ref/source/shopping.cc @@ -1642,6 +1642,8 @@ void list_shop_types() #define SHOPPING_THING_POS_KEY "pos_key" ShoppingList::ShoppingList() + : list(nullptr), min_unbuyable_cost(0), min_unbuyable_idx(0), + max_buyable_cost(0), max_buyable_idx(0) { } From 13aa1b5c4e15fba6a21952870a2d06cfffe83f75 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 11 Feb 2019 10:19:02 -0500 Subject: [PATCH 094/864] Clear even more state for tests As long as `acquire` is a possible item spec, then the builder can have some dependency on what items the player has seen before, and so this needs to be cleared. In a future commit I will limit the use of `acquire` to portals, but we still want to clear this for better control in tests. Also, reorganize this function a bit, and add yet more DIAG_DNGN spam (sry). --- crawl-ref/source/dungeon.cc | 44 ++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 57cd81a6a7d8..d554f3bc77a8 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -598,27 +598,43 @@ void dgn_flush_map_memory() // This leaves some state uninitialized, and probably should be immediately // followed by a call to `initial_dungeon_setup` and something that moves // the player to a level or regenerates a level. - you.runes.reset(); - you.obtainable_runes = 15; - you.zigs_completed = 0; - you.zig_max = 0; + + // vaults and map stuff you.uniq_map_tags.clear(); you.uniq_map_names.clear(); - you.unique_creatures.reset(); - you.unique_items.init(UNIQ_NOT_EXISTS); you.vault_list.clear(); you.branches_left.reset(); you.branch_stairs.init(0); - you.octopus_king_rings = 0x00; - you.item_description.init(255); + you.zigs_completed = 0; + you.zig_max = 0; you.exploration = 0; + you.seen_portals = 0; // should be just cosmetic // would it be safe to just clear you.props? you.props.erase(TEMPLE_SIZE_KEY); you.props.erase(TEMPLE_MAP_KEY); you.props.erase(OVERFLOW_TEMPLES_KEY); you.props.erase(TEMPLE_GODS_KEY); + you.clear_place_info(); + // the following is supposed to clear any persistent lua state related to + // the builder. However, it's susceptible to custom dlua doing its own + // thing... dlua.callfn("dgn_clear_data", ""); + + // monsters + you.unique_creatures.reset(); + + // item stuff that can interact with the builder + you.runes.reset(); + you.obtainable_runes = 15; + you.unique_items.init(UNIQ_NOT_EXISTS); + you.octopus_king_rings = 0x00; + you.item_description.init(255); // random names need reset after this, e.g. + // via debug.dungeon_setup() you.attribute[ATTR_GOLD_GENERATED] = 0; + // potentially relevant for item placement in e.g. troves: + you.seen_weapon.init(0); + you.seen_armour.init(0); + you.seen_misc.reset(); } static void _dgn_load_colour_grid() @@ -4533,7 +4549,13 @@ int dgn_place_item(const item_spec &spec, item.pos = where; if (_apply_item_props(item, spec, (useless_tries >= 10), false)) + { + dprf(DIAG_DNGN, "vault spec: placing %s (%s) at %d,%d", + mitm[item_made].name(DESC_PLAIN).c_str(), + mitm[item_made].name(DESC_PLAIN, false, true).c_str(), + where.x, where.y); return item_made; + } else { // _apply_item_props will not generate a rune you already have, @@ -5043,7 +5065,13 @@ static void _vault_grid_glyph(vault_placement &place, const coord_def& where, item_made = items(true, which_class, which_type, which_depth); if (item_made != NON_ITEM) + { mitm[item_made].pos = where; + dprf(DIAG_DNGN, "vault grid: placing %s (%s) at %d,%d", + mitm[item_made].name(DESC_PLAIN).c_str(), + mitm[item_made].name(DESC_PLAIN, false, true).c_str(), + mitm[item_made].pos.x, mitm[item_made].pos.y); + } } // defghijk - items From 4f8aab8ed993f6c510111ad548c9de1cb615582c Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 11 Feb 2019 10:23:25 -0500 Subject: [PATCH 095/864] Add a debugging hook This is kind of dumb but I can tell I'm going to need this again. This is aimed at debugging generation that may be happening deep in some test sequence: toggle this on to echo all dprfs to stderr for some window of time. (E.g. in a recent episode I used it to print all DNGN_DIAG messages while the builder was generating Lair:6 for a particular seed in vault_catalog.lua.) --- crawl-ref/source/message.cc | 10 +++++++++- crawl-ref/source/message.h | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/message.cc b/crawl-ref/source/message.cc index 9477920b8fa0..7baf2239f761 100644 --- a/crawl-ref/source/message.cc +++ b/crawl-ref/source/message.cc @@ -33,6 +33,13 @@ #include "unwind.h" #include "view.h" +static bool _msgs_to_stderr = false; + +void set_log_emergency_stderr(bool b) +{ + _msgs_to_stderr = b; +} + static void _mpr(string text, msg_channel_type channel=MSGCH_PLAIN, int param=0, bool nojoin=false, bool cap=true); @@ -1363,7 +1370,8 @@ static void _mpr(string text, msg_channel_type channel, int param, bool nojoin, #endif if (channel == MSGCH_ERROR && - (!crawl_state.io_inited || msgwin_errors_to_stderr())) + (!crawl_state.io_inited || msgwin_errors_to_stderr()) + || _msgs_to_stderr) { fprintf(stderr, "%s\n", text.c_str()); } diff --git a/crawl-ref/source/message.h b/crawl-ref/source/message.h index 609807f987b7..93b626f9dcbd 100644 --- a/crawl-ref/source/message.h +++ b/crawl-ref/source/message.h @@ -17,6 +17,8 @@ void display_message_window(); void clear_message_window(); +void set_log_emergency_stderr(bool b); + void scroll_message_window(int n); void clear_messages(bool force = false); From 88f18ea6ed1b6e374881a159f61bf735705c5c32 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 11 Feb 2019 10:26:51 -0500 Subject: [PATCH 096/864] constify a bunch of instances of PlaceInfo This didn't actually fix anything, but made me feel better. --- crawl-ref/source/chardump.cc | 102 +++++++++++++++++++---------------- crawl-ref/source/dungeon.cc | 2 +- 2 files changed, 56 insertions(+), 48 deletions(-) diff --git a/crawl-ref/source/chardump.cc b/crawl-ref/source/chardump.cc index da6688976b26..2dc9786b4667 100644 --- a/crawl-ref/source/chardump.cc +++ b/crawl-ref/source/chardump.cc @@ -273,7 +273,7 @@ static void _sdump_visits(dump_params &par) seen = "saw"; } - vector branches_visited = you.get_all_place_info(true, true); + const vector branches_visited = you.get_all_place_info(true, true); PlaceInfo branches_total; for (const PlaceInfo &branch : branches_visited) @@ -289,62 +289,70 @@ static void _sdump_visits(dump_params &par) seen.c_str(), branches_total.levels_seen); } - PlaceInfo place_info = you.get_place_info(BRANCH_PANDEMONIUM); - if (place_info.num_visits > 0) { - text += make_stringf("You %svisited Pandemonium %d time", - have.c_str(), place_info.num_visits); - if (place_info.num_visits > 1) - text += "s"; - text += make_stringf(", and %s %d of its levels.\n", - seen.c_str(), place_info.levels_seen); + const PlaceInfo place_info = you.get_place_info(BRANCH_PANDEMONIUM); + if (place_info.num_visits > 0) + { + text += make_stringf("You %svisited Pandemonium %d time", + have.c_str(), place_info.num_visits); + if (place_info.num_visits > 1) + text += "s"; + text += make_stringf(", and %s %d of its levels.\n", + seen.c_str(), place_info.levels_seen); + } } - place_info = you.get_place_info(BRANCH_ABYSS); - if (place_info.num_visits > 0) { - text += make_stringf("You %svisited the Abyss %d time", - have.c_str(), place_info.num_visits); - if (place_info.num_visits > 1) - text += "s"; - text += ".\n"; + const PlaceInfo place_info = you.get_place_info(BRANCH_ABYSS); + if (place_info.num_visits > 0) + { + text += make_stringf("You %svisited the Abyss %d time", + have.c_str(), place_info.num_visits); + if (place_info.num_visits > 1) + text += "s"; + text += ".\n"; + } } - place_info = you.get_place_info(BRANCH_BAZAAR); - if (place_info.num_visits > 0) { - text += make_stringf("You %svisited %d bazaar", - have.c_str(), place_info.num_visits); - if (place_info.num_visits > 1) - text += "s"; - text += ".\n"; + const PlaceInfo place_info = you.get_place_info(BRANCH_BAZAAR); + if (place_info.num_visits > 0) + { + text += make_stringf("You %svisited %d bazaar", + have.c_str(), place_info.num_visits); + if (place_info.num_visits > 1) + text += "s"; + text += ".\n"; + } } - place_info = you.get_place_info(BRANCH_ZIGGURAT); - if (place_info.num_visits > 0) { - int num_zigs = place_info.num_visits; - text += make_stringf("You %s%s %d ziggurat", - have.c_str(), - (num_zigs == you.zigs_completed) ? "completed" - : "visited", - num_zigs); - if (num_zigs > 1) - text += "s"; - if (num_zigs != you.zigs_completed && you.zigs_completed) - text += make_stringf(" (completing %d)", you.zigs_completed); - text += make_stringf(", and %s %d of %s levels", - seen.c_str(), place_info.levels_seen, - num_zigs > 1 ? "their" : "its"); - if (num_zigs != 1 && !you.zigs_completed) - text += make_stringf(" (deepest: %d)", you.zig_max); - text += ".\n"; + const PlaceInfo place_info = you.get_place_info(BRANCH_ZIGGURAT); + if (place_info.num_visits > 0) + { + int num_zigs = place_info.num_visits; + text += make_stringf("You %s%s %d ziggurat", + have.c_str(), + (num_zigs == you.zigs_completed) ? "completed" + : "visited", + num_zigs); + if (num_zigs > 1) + text += "s"; + if (num_zigs != you.zigs_completed && you.zigs_completed) + text += make_stringf(" (completing %d)", you.zigs_completed); + text += make_stringf(", and %s %d of %s levels", + seen.c_str(), place_info.levels_seen, + num_zigs > 1 ? "their" : "its"); + if (num_zigs != 1 && !you.zigs_completed) + text += make_stringf(" (deepest: %d)", you.zig_max); + text += ".\n"; + } } vector misc_portals; for (branch_type br : single_portals) { - place_info = you.get_place_info(br); + const PlaceInfo place_info = you.get_place_info(br); if (!place_info.num_visits) continue; string name = branches[br].shortname; @@ -434,9 +442,9 @@ static string _denanify(const string &s) return out; } -static string _sdump_turns_place_info(PlaceInfo place_info, string name = "") +static string _sdump_turns_place_info(const PlaceInfo place_info, string name = "") { - PlaceInfo gi = you.global_info; + const PlaceInfo gi = you.global_info; string out; if (name.empty()) @@ -489,7 +497,7 @@ static void _sdump_turns_by_place(dump_params &par) { string &text(par.text); - vector all_visited = you.get_all_place_info(true); + const vector all_visited = you.get_all_place_info(true); text += "Table legend:\n" @@ -999,7 +1007,7 @@ static void _sdump_kills(dump_params &par) par.text += "\n"; } -static string _sdump_kills_place_info(PlaceInfo place_info, string name = "") +static string _sdump_kills_place_info(const PlaceInfo place_info, string name = "") { string out; @@ -1044,7 +1052,7 @@ static void _sdump_kills_by_place(dump_params &par) { string &text(par.text); - vector all_visited = you.get_all_place_info(true); + const vector all_visited = you.get_all_place_info(true); string result = ""; diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index d554f3bc77a8..4bfc50ff90b6 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -2614,7 +2614,7 @@ static bool _pan_level() const char *pandemon_level_names[] = { "mnoleg", "lom_lobon", "cerebov", "gloorx_vloq", }; int which_demon = -1; - PlaceInfo &place_info = you.get_place_info(); + const PlaceInfo &place_info = you.get_place_info(); bool all_demons_generated = true; if (you.props.exists("force_map")) From 60e86920ebe896c6624afd8cdee16d7d05824b6f Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 11 Feb 2019 10:37:54 -0500 Subject: [PATCH 097/864] Deprecate acquire item specs for regular dungeon generation Conditioning level generation on the player is generally now deprecated (I think there's consensus that this is bad for various reasons, but the reason I care about is that it interferes with seeding). This is the latest case of this that I have run across. These item specs directly call the acquirement code, which has a bunch of conditioning on the player to try to make the generated item more usable or appropriate. For non-pregenerated games this can affect randomization afterwards, and for pregenerated games it simply doesn't make much sense given that the player is mostly a blank slate when the acquirement is run. If you really want the player to have an item generated by this code, just drop a scroll of acquirement. In very special cases, it is possible in principle to generate an item on the fly with this item spec (several sprint maps do this). I've done somewhat arbitrary choices of replacements depending on my mood and what the vault appeared to intend, trying to get equivalently good and appropriate items, but these might need further refinement. Vault designers can consider `superb_item`, `any good_item`, and `star_item` when their intent is, place something potentially great but fairly random. There are some rarely used special cases of this syntax that are still in the code, e.g. the god syntax: there was all of one non-trove instance of this syntax left, and it was using a god (TSO) that has barely any acquirement special casing; I changed this one to something a bit more specific. Possibly this syntax should just be removed. This commit leaves only a few instances of this item spec, mainly in troves (where it is not deprecated). There are a couple calls in abyss that seemed ok, but possibly should be changed, as well as some uses in sprints as mentioned above. --- crawl-ref/docs/develop/levels/syntax.txt | 9 ++++++--- crawl-ref/docs/develop/levels/triggerables.txt | 8 ++++---- .../source/dat/des/branches/depths_encompass.des | 2 +- crawl-ref/source/dat/des/branches/dis.des | 2 +- crawl-ref/source/dat/des/branches/lair.des | 13 ++++++------- crawl-ref/source/dat/des/branches/pan.des | 12 ++++++------ crawl-ref/source/dat/des/branches/snake.des | 2 +- crawl-ref/source/dat/des/branches/spider.des | 2 +- crawl-ref/source/dat/des/branches/zot.des | 2 +- crawl-ref/source/dat/des/variable/float.des | 12 ++++++------ crawl-ref/source/dat/des/variable/ghost.des | 2 +- crawl-ref/source/dat/des/variable/large_themed.des | 6 +++--- crawl-ref/source/dat/des/variable/mini_monsters.des | 4 ++-- 13 files changed, 39 insertions(+), 37 deletions(-) diff --git a/crawl-ref/docs/develop/levels/syntax.txt b/crawl-ref/docs/develop/levels/syntax.txt index 6844cdaaf3de..c70c3bcf6b09 100644 --- a/crawl-ref/docs/develop/levels/syntax.txt +++ b/crawl-ref/docs/develop/levels/syntax.txt @@ -506,11 +506,14 @@ ITEM: (list of items, separated by comma) bonus to depth for the item generation. The "|" item glyph uses this quality level (but with a different distribution of item classes, see above). - * "acquire" requests the use of the acquirement code itself, - ensuring that the player gets wearable armour, etc. You can + * "acquire" requests the use of the acquirement code + itself, ensuring that the player gets wearable armour, etc. You can also use acquire: to request that the acquired item be treated as a god gift. Examples: "acquire any", "acquire armour", - "acquire:sif_muna book", "acquire:trog weapon". + "acquire:sif_muna book", "acquire:trog weapon". Use of this outside + of specialized portals as part of the builder is *deprecated*, + because conditioning level generation on player properties + interferes with seeding. * "level:N" sets the object's item level (can't be used with "good_item"). If set to -2 then the object's item level will be the same as a "*" symbol item (five plus twice the diff --git a/crawl-ref/docs/develop/levels/triggerables.txt b/crawl-ref/docs/develop/levels/triggerables.txt index 28c4a09c530a..edbfa0e9c057 100644 --- a/crawl-ref/docs/develop/levels/triggerables.txt +++ b/crawl-ref/docs/develop/levels/triggerables.txt @@ -167,8 +167,8 @@ TriggerableFunctions. C. Examples of usage ==================== -These vaults have been taken in whole from the current crawl code repository, -and may have been updated since their original inclusion. Please see the +These vaults were taken in whole from the crawl code repository, and several +have been updated or removed since their original inclusion. Please see the referenced files for the current version. Annotations are marked as "** ". @@ -369,8 +369,8 @@ KMONS: 4 = col:gold skeletal warrior name:ancient_champion name_replace \ triple sword ego:vorpal | executioner's axe ego:vorpal SHUFFLE: 123 KPROP: ]v.1234+ABCDEFG!n$wr|" = no_rtele_into -KITEM: w = acquire weapon -KITEM: r = acquire armour +KITEM: w = weapon good_item +KITEM: r = armour good_item NSUBST: $ = 1:w / 1:r / 4:| / *:$ COLOUR: " = yellow KFEAT: " = . diff --git a/crawl-ref/source/dat/des/branches/depths_encompass.des b/crawl-ref/source/dat/des/branches/depths_encompass.des index dd3690968068..75811ddb7db8 100644 --- a/crawl-ref/source/dat/des/branches/depths_encompass.des +++ b/crawl-ref/source/dat/des/branches/depths_encompass.des @@ -590,7 +590,7 @@ KMONS: K = storm dragon KMONS: L = shadow dragon KMONS: M = quicksilver dragon KMONS: N = golden dragon -KITEM: KLMN> = acquire any +KITEM: KLMN> = any good_item KITEM: 12 = any MAP cc+cc diff --git a/crawl-ref/source/dat/des/branches/dis.des b/crawl-ref/source/dat/des/branches/dis.des index bef06e330ed4..30dd1efaed78 100644 --- a/crawl-ref/source/dat/des/branches/dis.des +++ b/crawl-ref/source/dat/des/branches/dis.des @@ -835,7 +835,7 @@ COLOUR: G = cyan KMONS: 8 = iron golem KMONS: 9 = war gargoyle ITEM: plate armour good_item / crystal plate armour good_item w:3 -ITEM: acquire weapon +ITEM: any weapon good_item KMONS: K = Hell Sentinel KITEM: K = | KMONS: J = Hell Sentinel diff --git a/crawl-ref/source/dat/des/branches/lair.des b/crawl-ref/source/dat/des/branches/lair.des index 8969b51e3d1e..5db90565581b 100644 --- a/crawl-ref/source/dat/des/branches/lair.des +++ b/crawl-ref/source/dat/des/branches/lair.des @@ -2567,7 +2567,7 @@ KMONS: P = plant # The one big reward and the several smaller stacks of items # are randomly split between the mostly-dog and mostly-bear sections. KITEM: % = any, any w:1 / nothing w:5, ration q:1 -KITEM: *| = gold, gold, gold, acquire any +KITEM: *| = gold, gold, gold, any good_item NSUBST: 2 = 2:22334 / *:3 SHUFFLE: %'*" / %'"| SUBST: X = xx., z = xx`, ' = ., " = x, p = PP. @@ -2761,7 +2761,7 @@ MONS: plant, elephant KMONS: S = anaconda KFEAT: S = deep_water KITEM: U = superb_item -KITEM: Q = acquire any +KITEM: Q = superb_item KFEAT: o = granite_statue KFEAT: i = granite_statue SUBST: X = xxx.., P = 1........., T = tttxxc @@ -2821,10 +2821,9 @@ MONS: red devil / ice devil w:15 / orange demon w:15 MONS: hellwing / smoke demon, sun demon / sixfirhy / hell beast w:4 KMONS: hH = hell hound KMONS: F = fungus -# XXX: no_pickup is incompatible with acquire any. -# Should be used here, loot is easily missed. -KITEM: A = acquire any, any good_item / no_pickup gold good_item w:15, \ - % no_pickup / nothing, % no_pickup / nothing +KITEM: A = superb_item no_pickup, any good_item no_pickup \ + / no_pickup gold good_item w:15, % no_pickup \ + / nothing, % no_pickup / nothing KFEAT: A = enter_hell KFEAT: _ = altar_makhleb KFEAT: L = endless_lava @@ -2975,7 +2974,7 @@ NAME: evilmike_catoblepas_cave TAGS: no_monster_gen no_rotate no_item_gen PLACE: Lair:$ ORIENT: northwest -ITEM: acquire any +ITEM: any good_item MONS: yak, death yak, manticore KMONS: 4C = patrolling catoblepas # These are still living plants for all intents and purposes... diff --git a/crawl-ref/source/dat/des/branches/pan.des b/crawl-ref/source/dat/des/branches/pan.des index 11b962ee4e43..7686b0daf5a1 100644 --- a/crawl-ref/source/dat/des/branches/pan.des +++ b/crawl-ref/source/dat/des/branches/pan.des @@ -2530,7 +2530,7 @@ MONS: pandemonium lord, eye of draining MONS: black sun, lorocyproca, any demon KMONS: 6O = ghost moth : if demonic_rune_vault_is_decoy() then -KITEM: O = acquire any / demonic rune of zot mimic +KITEM: O = superb_item / demonic rune of zot mimic : else KITEM: O = demonic rune of zot : end @@ -2619,7 +2619,7 @@ ORIENT: float MONS: fire bat, hellion, hellephant KMONS: O = pandemonium lord : if demonic_rune_vault_is_decoy() then -KITEM: O = acquire any / demonic rune of zot mimic +KITEM: O = superb_item / demonic rune of zot mimic : else KITEM: O = demonic rune of zot : end @@ -2692,7 +2692,7 @@ ORIENT: float MONS: pandemonium lord, brimstone fiend MONS: tormentor, smoke demon, any demon : if demonic_rune_vault_is_decoy() then -KITEM: O = acquire any / demonic rune of zot mimic +KITEM: O = superb_item / demonic rune of zot mimic : else KITEM: O = demonic rune of zot : end @@ -2758,7 +2758,7 @@ MONS: juggernaut simulacrum, ice devil KMONS: 56 = ice statue KMONS: P = pandemonium lord : if demonic_rune_vault_is_decoy() then -KITEM: O = acquire any / demonic rune of zot mimic +KITEM: O = superb_item / demonic rune of zot mimic : else KITEM: O = demonic rune of zot : end @@ -2847,7 +2847,7 @@ KMONS: p = demonic plant KMONS: P = pandemonium lord ITEM: any potion : if demonic_rune_vault_is_decoy() then -KITEM: O = acquire any / demonic rune of zot mimic +KITEM: O = superb_item / demonic rune of zot mimic : else KITEM: O = demonic rune of zot : end @@ -3933,7 +3933,7 @@ KITEM: O = demonic rune of Zot : end ITEM: w:5 any / potion of curing ITEM: any / potion of heal wounds -ITEM: acquire any +ITEM: any good_item ITEM: potion of cancellation ITEM: potion of might / potion of brilliance / potion of agility ITEM: any diff --git a/crawl-ref/source/dat/des/branches/snake.des b/crawl-ref/source/dat/des/branches/snake.des index 8f608d06dffa..6ce562bc4329 100644 --- a/crawl-ref/source/dat/des/branches/snake.des +++ b/crawl-ref/source/dat/des/branches/snake.des @@ -1300,7 +1300,7 @@ MONS: nagaraja w:20 / naga warrior w:5 / naga mage w:5 / \ naga ritualist w:5 / naga sharpshooter w:5 NSUBST: O = 1:A / 1:B KITEM: A = serpentine rune of Zot -KITEM: B = serpentine rune of Zot mimic / w:90 acquire any +KITEM: B = serpentine rune of Zot mimic / w:90 any good_item MAP cccccccc c.@..c cccccccc cccc..1...ccc c....c cccc..2...ccc diff --git a/crawl-ref/source/dat/des/branches/spider.des b/crawl-ref/source/dat/des/branches/spider.des index bcfe43808f39..af80061672bb 100644 --- a/crawl-ref/source/dat/des/branches/spider.des +++ b/crawl-ref/source/dat/des/branches/spider.des @@ -439,7 +439,7 @@ KMONS: 1 = tarantella : if you.in_branch("Zot") then KMONS: 2* = jumping spider / orb spider w:5 KMONS: 3| = ghost moth / moth of wrath -KITEM: | = acquire any w:5 / any good_item +KITEM: | = any good_item KFEAT: ` = known zot trap KFEAT: ^ = web w:7 / known web trap w:1 / any trap w:1 / . w:7 : if you.depth() == dgn.br_depth("Zot") - 1 then diff --git a/crawl-ref/source/dat/des/branches/zot.des b/crawl-ref/source/dat/des/branches/zot.des index 5c59fd9c79b0..e34192a7f933 100644 --- a/crawl-ref/source/dat/des/branches/zot.des +++ b/crawl-ref/source/dat/des/branches/zot.des @@ -1731,7 +1731,7 @@ KMONS: O = acid blob / nonbase yellow draconian w:6 KMONS: Z = golden dragon / killer klown / Tiamat, golden dragon / killer klown KITEM: BEHKN = $ w:15 / % w:25 / * KITEM: z = any good_item -KITEM: Z = acquire any +KITEM: Z = superb_item # Rotates out loot, upstairs, downstairs, # both (in an enclosed bubble), or nothing, at either end. SHUFFLE: defg{>Z' / defg{<'' / fgde>{'Z / fgde<{'' / defg'|Z' / fgde|''Z / \ diff --git a/crawl-ref/source/dat/des/variable/float.des b/crawl-ref/source/dat/des/variable/float.des index da4ded24a6d9..fd6db25cbe80 100644 --- a/crawl-ref/source/dat/des/variable/float.des +++ b/crawl-ref/source/dat/des/variable/float.des @@ -1408,7 +1408,7 @@ KMONS: 1 = slime creature w:20 / swamp worm w:50 / \ KMONS: 23 = alligator / swamp dragon / hydra KMONS: 45 = tentacled monstrosity / thorn hunter KITEM: 3 = any good_item / any potion / gold -KITEM: 5 = acquire any / gold good_item / any potion q:4 w:20 +KITEM: 5 = superb_item / gold good_item / any potion q:4 w:20 KMONS: P = plant KFEAT: 1324P = W NSUBST: @ = 1:@ / *:X @@ -1684,7 +1684,7 @@ WEIGHT: 4 DEPTH: Depths MONS: generate_awake angel / generate_awake daeva / w:1 angel / w:1 daeva KFEAT: A = altar_the_shining_one -KITEM: A = w:1 acquire:the_shining_one any / nothing +KITEM: A = w:1 any weapon ego:holy_wrath / nothing : if crawl.one_chance_in(3) then SUBST: | = . SUBST: % = | @@ -1729,7 +1729,7 @@ WEIGHT: 4 DEPTH: Depths MONS: generate_awake angel / generate_awake daeva / w:1 angel / w:1 daeva KFEAT: A = altar_the_shining_one -KITEM: A = w:1 acquire:the_shining_one any / nothing +KITEM: A = w:1 any weapon ego:holy_wrath / nothing : if crawl.one_chance_in(3) then SUBST: | = . SUBST: % = | @@ -2777,7 +2777,7 @@ NAME: ragdoll_tomb_raider TAGS: no_item_gen no_monster_gen patrolling DEPTH: D:14-, Depths, Crypt, !Crypt:$ ORIENT: float -KITEM: $ = amulet_of_vitality / acquire any +KITEM: $ = amulet_of_vitality / any good_item KITEM: 12345d = gold / any / nothing KITEM: 67M = superb_item / any KFEAT: ~ = known zot trap @@ -7946,7 +7946,7 @@ SUBST: def = c, ghi = v, jk = b KMONS: 8 = 8 band KMONS: 9 = 9 band KMONS: 0 = 0 band -KITEM: J = acquire any +KITEM: J = any good_item NSUBST: | = 1:J / 2:* / *:| SUBST: % = %., O = % MAP @@ -8113,7 +8113,7 @@ KMONS: F = 0 patrolling KMONS: H = 9 band patrolling KMONS: 8 = 8 patrolling #loot -KITEM: 8 = acquire any +KITEM: 8 = any good_item KITEM: 7 = * MAP ccc diff --git a/crawl-ref/source/dat/des/variable/ghost.des b/crawl-ref/source/dat/des/variable/ghost.des index c10ff4438e6f..a956b708d10b 100644 --- a/crawl-ref/source/dat/des/variable/ghost.des +++ b/crawl-ref/source/dat/des/variable/ghost.des @@ -749,7 +749,7 @@ ENDMAP NAME: gammafunk_ghost_hydra_chop DEPTH: D:8-, Lair, Swamp ORIENT: float -: setup_hydra_weapon(_G) +#: setup_hydra_weapon(_G) KMONS: O = player ghost {{ -- Set up hydra monster entry with a range of possible extra heads based on diff --git a/crawl-ref/source/dat/des/variable/large_themed.des b/crawl-ref/source/dat/des/variable/large_themed.des index c482cedde0d4..8509498be724 100644 --- a/crawl-ref/source/dat/des/variable/large_themed.des +++ b/crawl-ref/source/dat/des/variable/large_themed.des @@ -1026,7 +1026,7 @@ NSUBST: 4 = 2:4 / 1:5 : end MONS: human att:neutral KMONS: 7 = patrolling hell knight -ITEM: acquire any +ITEM: superb_item SUBST: '" = ., b = v MAP xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx @@ -1159,8 +1159,8 @@ MONS: deep elf blademaster, patrolling draconian knight : end KFEAT: _ = altar_okawaru # Lots of loot in this one. In true Okawaru fashion, most of it is junk! -ITEM: any armour, any armour good_item / acquire armour -ITEM: any weapon, any weapon good_item / acquire weapon +ITEM: any armour, any armour good_item +ITEM: any weapon, any weapon good_item ITEM: arrow, bolt, sling bullet, gold SHUFFLE: df, hi, jk, eg NSUBST: d = 1:e / *:d, f = 1:g / *:f diff --git a/crawl-ref/source/dat/des/variable/mini_monsters.des b/crawl-ref/source/dat/des/variable/mini_monsters.des index b40ccebab529..58a51042ce14 100644 --- a/crawl-ref/source/dat/des/variable/mini_monsters.des +++ b/crawl-ref/source/dat/des/variable/mini_monsters.des @@ -3358,7 +3358,7 @@ KITEM: 098 = superb_item : else SUBST: 9 = 98, 0 = 98 KITEM: 09 = superb_item -KITEM: 8 = any acquire +KITEM: 8 = any good_item : end MAP ....... @@ -3510,7 +3510,7 @@ KMONS: o = unseen horror KMONS: p = hornet KMONS: q = insubstantial wisp KMONS: r = wolf spider -KITEM: e = acquire armour / acquire weapon +KITEM: e = any armour good_item / any weapon good_item / scroll of acquirement SHUFFLE: bcdfghjklnopqr MAP ............. From 1c07cc13e6d9e4b8fdb5d21501d2ab079c085bba Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 11 Feb 2019 10:50:30 -0500 Subject: [PATCH 098/864] Small tweak to vault_catalog.lua Really, really clear everything before regenerating. --- crawl-ref/source/test/vault_catalog.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/source/test/vault_catalog.lua b/crawl-ref/source/test/vault_catalog.lua index c5e35c68efcc..f13311bbbd7c 100644 --- a/crawl-ref/source/test/vault_catalog.lua +++ b/crawl-ref/source/test/vault_catalog.lua @@ -49,6 +49,7 @@ local generation_order_extended = { -- a bit redundant with mapstat? but simpler... function catalog_dungeon_vaults(level_order, silent) local result = {} + dgn.reset_level() debug.flush_map_memory() debug.dungeon_setup() for i,lvl in ipairs(level_order) do From e52b27f00579602daa3845d8d09076b9eebb07cb Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 11 Feb 2019 11:13:18 -0500 Subject: [PATCH 099/864] Place AK start in abyss with pregeneration on (11871) The chapter check was basically in the wrong place; moved it up to outside the builder call. Also, just in case, unwind the chapter variable while doing pregeneration so that nothing can condition on it incorrectly. --- crawl-ref/source/files.cc | 19 ++++++++++--------- crawl-ref/source/startup.cc | 3 +++ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 2acb9159e74a..95a46bf72b9a 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1248,15 +1248,6 @@ static void _make_level(dungeon_feature_type stair_taken, env.turns_on_level = -1; - if (you.chapter == CHAPTER_POCKET_ABYSS - && player_in_branch(BRANCH_DUNGEON)) - { - // If we're leaving the Abyss for the first time as a Chaos - // Knight of Lugonu (who start out there), enable normal monster - // generation. - you.chapter = CHAPTER_ORB_HUNTING; - } - tile_init_default_flavour(); tile_clear_flavour(); env.tile_names.clear(); @@ -1545,6 +1536,16 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, bool just_created_level = false; + if (load_mode != LOAD_GENERATE + && you.chapter == CHAPTER_POCKET_ABYSS + && player_in_branch(BRANCH_DUNGEON)) + { + // If we're leaving the Abyss for the first time as a Chaos + // Knight of Lugonu (who start out there), enable normal monster + // generation. + you.chapter = CHAPTER_ORB_HUNTING; + } + // GENERATE new level when the file can't be opened: if (!you.save->has_chunk(level_name)) { diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index bc2a4e1b490c..a0de3a427938 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -278,6 +278,9 @@ static void _pregen_levels(const branch_type branch, progress_popup &progress) static void _pregen_dungeon() { + // be sure that AK start doesn't interfere with the builder + unwind_var chapter(you.chapter, CHAPTER_ORB_HUNTING); + // bel's original proposal generated D to lair depth, then lair, then D // to orc depth, then orc, then the rest of D. I have simplified this to // just generate whole branches at a time -- I am not sure how much real From 33396473a155e76679c88a3658fce116b7b95635 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 11 Feb 2019 21:50:13 -0500 Subject: [PATCH 100/864] Simplify levels_visited This was overly complicated because I didn't understand how CrawlStoreValue works; the necessary hash table is automatically created on the get_value() call. This also has the bonus of removing a dependency on a global from player::player(). --- crawl-ref/source/files.cc | 9 --------- crawl-ref/source/player.cc | 2 -- crawl-ref/source/player.h | 1 - 3 files changed, 12 deletions(-) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 95a46bf72b9a..b7510f1d66e7 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1405,7 +1405,6 @@ static void _fixup_visited_from_package() { // for games started later than this fixup, this prop is initialized in // player::player - you.init_level_visited(); // is this necessary? CrawlHashTable &visited = you.props[VISITED_LEVELS_KEY].get_table(); if (visited.size()) // only 0 for upgrades, or before entering D:1 return; @@ -1416,15 +1415,8 @@ static void _fixup_visited_from_package() } #endif -void player::init_level_visited() -{ - if (!props.exists(VISITED_LEVELS_KEY)) - props[VISITED_LEVELS_KEY].new_table(); -} - void player::set_level_visited(const level_id &level) { - ASSERT(props.exists(VISITED_LEVELS_KEY)); auto &visited = props[VISITED_LEVELS_KEY].get_table(); visited[level.describe()] = true; } @@ -1438,7 +1430,6 @@ bool player::level_visited(const level_id &level) // save no longer exists, so we ignore it for printing morgues if (!is_existing_level(level) && you.save) return false; - ASSERT(props.exists(VISITED_LEVELS_KEY)); const auto &visited = props[VISITED_LEVELS_KEY].get_table(); return visited.exists(level.describe()); } diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 799de7e6e112..9ae0ed50e9f7 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -5216,8 +5216,6 @@ player::player() travel_y = 0; travel_z = level_id(); - init_level_visited(); - running.clear(); travel_ally_pace = false; received_weapon_warning = false; diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h index 4819249f8f82..28230bdb7b74 100644 --- a/crawl-ref/source/player.h +++ b/crawl-ref/source/player.h @@ -482,7 +482,6 @@ class player : public actor void shiftto(const coord_def &c); bool blink_to(const coord_def& c, bool quiet = false) override; - void init_level_visited(); void set_level_visited(const level_id &level); bool level_visited(const level_id &level); From e13aadb210ac7751cfb85537baaca10534c22d3b Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 11 Feb 2019 22:29:34 -0500 Subject: [PATCH 101/864] Eliminate some more dependencies on globals from player::player On mingw builds, branch_info was not getting initialized correctly here because branch_iterator depends on a global, `branches`, which was not initialized before the constructor is called for the global `you`. Use the enum order instead of anything fancier to initialize `branch_info`. Also don't set the seed here, it isn't need and leads to another potential order issue. --- crawl-ref/source/place-info.cc | 11 +++++++---- crawl-ref/source/player.cc | 11 ++++++++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/crawl-ref/source/place-info.cc b/crawl-ref/source/place-info.cc index dd087ad68a2a..c653106b5a61 100644 --- a/crawl-ref/source/place-info.cc +++ b/crawl-ref/source/place-info.cc @@ -127,11 +127,14 @@ PlaceInfo& player::get_place_info(branch_type branch) const void player::clear_place_info() { global_xp_info = LevelXPInfo(); - for (branch_iterator it; it; ++it) + + // can't use branch_iterator here, because it depends on a global that + // may not be inited when you is first constructed. + for (int i = BRANCH_DUNGEON; i < NUM_BRANCHES; i++) { - branch_info[it->id] = PlaceInfo(); - branch_info[it->id].branch = it->id; - branch_info[it->id].assert_validity(); + branch_info[i] = PlaceInfo(); + branch_info[i].branch = static_cast(i); + branch_info[i].assert_validity(); } } diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 9ae0ed50e9f7..5034926969ba 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -5025,6 +5025,15 @@ int count_worn_ego(int which_ego) player::player() { + // warning: this constructor is called for `you` in an indeterminate order + // with respect to other globals, and so anything that depends on a global + // you should not do here. This includes things like `branches`, as well as + // any const static string prop name -- any object that needs to call a + // constructor is risky, and may or may not have called it yet. E.g. strings + // could be empty, branches could have every branch set as the dungeon, etc. + // One candidate location is startup.cc:_initialize, which is nearly the + // first things called in the launch game loop. + chr_god_name.clear(); chr_species_name.clear(); chr_class_name.clear(); @@ -5254,7 +5263,7 @@ player::player() shield_blocks = 0; abyss_speed = 0; - game_seed = crawl_state.seed; + game_seed = 0; game_is_seeded = true; old_hunger = hunger; From 7635c99b35658e33562b239784f4f9876285a6a8 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 11 Feb 2019 23:13:46 -0500 Subject: [PATCH 102/864] Revert "Eliminate some more dependencies on globals from player::player" bad branch order assumptions This reverts commit e13aadb210ac7751cfb85537baaca10534c22d3b. --- crawl-ref/source/place-info.cc | 11 ++++------- crawl-ref/source/player.cc | 11 +---------- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/crawl-ref/source/place-info.cc b/crawl-ref/source/place-info.cc index c653106b5a61..dd087ad68a2a 100644 --- a/crawl-ref/source/place-info.cc +++ b/crawl-ref/source/place-info.cc @@ -127,14 +127,11 @@ PlaceInfo& player::get_place_info(branch_type branch) const void player::clear_place_info() { global_xp_info = LevelXPInfo(); - - // can't use branch_iterator here, because it depends on a global that - // may not be inited when you is first constructed. - for (int i = BRANCH_DUNGEON; i < NUM_BRANCHES; i++) + for (branch_iterator it; it; ++it) { - branch_info[i] = PlaceInfo(); - branch_info[i].branch = static_cast(i); - branch_info[i].assert_validity(); + branch_info[it->id] = PlaceInfo(); + branch_info[it->id].branch = it->id; + branch_info[it->id].assert_validity(); } } diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 5034926969ba..9ae0ed50e9f7 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -5025,15 +5025,6 @@ int count_worn_ego(int which_ego) player::player() { - // warning: this constructor is called for `you` in an indeterminate order - // with respect to other globals, and so anything that depends on a global - // you should not do here. This includes things like `branches`, as well as - // any const static string prop name -- any object that needs to call a - // constructor is risky, and may or may not have called it yet. E.g. strings - // could be empty, branches could have every branch set as the dungeon, etc. - // One candidate location is startup.cc:_initialize, which is nearly the - // first things called in the launch game loop. - chr_god_name.clear(); chr_species_name.clear(); chr_class_name.clear(); @@ -5263,7 +5254,7 @@ player::player() shield_blocks = 0; abyss_speed = 0; - game_seed = 0; + game_seed = crawl_state.seed; game_is_seeded = true; old_hunger = hunger; From 372e6d594387f9adfd260a7159331edc5843f7fe Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 12 Feb 2019 09:11:30 -0500 Subject: [PATCH 103/864] Revert "Revert "Eliminate some more dependencies on globals from player::player"" On further inspection, this should be ok: I was concerned about save compat, but the save order for place_infos is entirely independent of the storage order. This reverts commit 7635c99b35658e33562b239784f4f9876285a6a8. --- crawl-ref/source/place-info.cc | 11 +++++++---- crawl-ref/source/player.cc | 11 ++++++++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/crawl-ref/source/place-info.cc b/crawl-ref/source/place-info.cc index dd087ad68a2a..c653106b5a61 100644 --- a/crawl-ref/source/place-info.cc +++ b/crawl-ref/source/place-info.cc @@ -127,11 +127,14 @@ PlaceInfo& player::get_place_info(branch_type branch) const void player::clear_place_info() { global_xp_info = LevelXPInfo(); - for (branch_iterator it; it; ++it) + + // can't use branch_iterator here, because it depends on a global that + // may not be inited when you is first constructed. + for (int i = BRANCH_DUNGEON; i < NUM_BRANCHES; i++) { - branch_info[it->id] = PlaceInfo(); - branch_info[it->id].branch = it->id; - branch_info[it->id].assert_validity(); + branch_info[i] = PlaceInfo(); + branch_info[i].branch = static_cast(i); + branch_info[i].assert_validity(); } } diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 9ae0ed50e9f7..5034926969ba 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -5025,6 +5025,15 @@ int count_worn_ego(int which_ego) player::player() { + // warning: this constructor is called for `you` in an indeterminate order + // with respect to other globals, and so anything that depends on a global + // you should not do here. This includes things like `branches`, as well as + // any const static string prop name -- any object that needs to call a + // constructor is risky, and may or may not have called it yet. E.g. strings + // could be empty, branches could have every branch set as the dungeon, etc. + // One candidate location is startup.cc:_initialize, which is nearly the + // first things called in the launch game loop. + chr_god_name.clear(); chr_species_name.clear(); chr_class_name.clear(); @@ -5254,7 +5263,7 @@ player::player() shield_blocks = 0; abyss_speed = 0; - game_seed = crawl_state.seed; + game_seed = 0; game_is_seeded = true; old_hunger = hunger; From e20b4fce8354229b5ecc23fff706dbaf7faee60e Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 12 Feb 2019 09:38:31 -0500 Subject: [PATCH 104/864] Restructure PlaceInfo fixup to handle gauntlet upgrades Saves upgraded to 0.23 on windows are crashing, because you.branch_info was not correctly initialized on mingw builds (see e13aadb210) and gauntlet was saved with a global PlaceInfo. This commit handles save compat for these files. This change makes the fixup slightly more generic and removes a save version check, which I don't think is really necessary here (the desolation fixup was one of the first things I did, before even being on the devteam, so I think I was being ultra-cautious with save compat). I've left the branch check though, so this will cause crashes if a new variant of this bug appears in the future, or if something else goes wrong with PlaceInfo. --- crawl-ref/source/tags.cc | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index 8eca55f9c6a8..c55b81d2f561 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -4191,23 +4191,34 @@ static void tag_read_you_dungeon(reader &th) for (int i = 0; i < count_p; i++) { place_info = unmarshallPlaceInfo(th); - if (place_info.is_global() - && th.getMinorVersion() <= TAG_MINOR_DESOLATION_GLOBAL) +#if TAG_MAJOR_VERSION == 34 + if (place_info.is_global()) { // This is to fix some crashing saves that didn't import - // correctly, where the desolation slot occasionally gets marked - // as global on conversion from pre-0.19 to post-0.19a. This - // assumes that the order in `logical_branch_order` (branch.cc) - // hasn't changed since the save version (which is moderately safe). + // correctly, where under certain circumstances upgrading + // a game to a version with an added branch could fail to + // initialize the branch number. This has happened at least three + // times now for slightly different reasons, for depths, + // desolation, and gauntlet. The depths fixup is old enough that + // it is handled differently. + // + // The basic assumption is that if a place is marked as global, it's + // not properly initialized. The fixup assumes that logical branch + // order (used by get_all_place_info) has not changed since the + // save except at the end. + const branch_type branch_to_fix = places[i].branch; - ASSERT(branch_to_fix == BRANCH_DESOLATION); + mprf(MSGCH_ERROR, + "Save file has uninitialized PlaceInfo for branch %s", + branches[places[i].branch].shortname); + // these are the known cases where this fix applies. It would + // probably be possible to drop this ASSERT... + ASSERT(branch_to_fix == BRANCH_DESOLATION || + branch_to_fix == BRANCH_GAUNTLET); place_info.branch = branch_to_fix; } - else - { - // These should all be branch-specific, not global - ASSERT(!place_info.is_global()); - } +#endif + ASSERT(!place_info.is_global()) you.set_place_info(place_info); } From 3d167c7f2c9dbcdb76bc322e4489a59ab88a5fd6 Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 12 Feb 2019 10:37:54 -0500 Subject: [PATCH 105/864] semicolon + checkwhite --- crawl-ref/source/tags.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index c55b81d2f561..cb4d581fad8a 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -4213,12 +4213,12 @@ static void tag_read_you_dungeon(reader &th) branches[places[i].branch].shortname); // these are the known cases where this fix applies. It would // probably be possible to drop this ASSERT... - ASSERT(branch_to_fix == BRANCH_DESOLATION || + ASSERT(branch_to_fix == BRANCH_DESOLATION || branch_to_fix == BRANCH_GAUNTLET); place_info.branch = branch_to_fix; } #endif - ASSERT(!place_info.is_global()) + ASSERT(!place_info.is_global()); you.set_place_info(place_info); } From cea5463b436e4f77f31e209e6570fd30ccc55667 Mon Sep 17 00:00:00 2001 From: Alan Malloy Date: Tue, 12 Feb 2019 09:34:56 -0800 Subject: [PATCH 106/864] Handle temporarily-changed terrain when asserting level validity (#11876) --- crawl-ref/source/tags.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index cb4d581fad8a..1ba00d8a4d28 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -1068,12 +1068,12 @@ static void _ensure_entry(branch_type br) { dungeon_feature_type entry = branches[br].entry_stairs; for (rectangle_iterator ri(1); ri; ++ri) - if (grd(*ri) == entry) + if (orig_terrain(*ri) == entry) return; // Find primary upstairs. for (rectangle_iterator ri(1); ri; ++ri) - if (grd(*ri) == DNGN_STONE_STAIRS_UP_I) + if (orig_terrain(*ri) == DNGN_STONE_STAIRS_UP_I) { for (distance_iterator di(*ri); di; ++di) if (in_bounds(*di) && grd(*di) == DNGN_FLOOR) From 431b8d2fe33875c625388c629376298d9910ba64 Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 13 Feb 2019 16:16:22 -0500 Subject: [PATCH 107/864] Change behavior of multiple DEPTH: lines, fixing some uniques (ebering) Previously, multiple DEPTH: lines would be interpreted as the last overriding any previous ones. This changes them to be additive, similar to how TAGS: lines work. It also removes an apparently vestigial function intended to do something with default depths that relied on the previous behavior; in fact, the `default-depth:` .des syntax is implemented in a different way using the `dgn.set_default_depth` call, not affected by this commit. This change fixes the placement of uniques touched in 402804a59a51, which accidentally have a fairly restricted placement in 0.23.0. (This fix will be in trunk and in a future point release of 0.23, but not during the tournament -- so anyone looking for Aizul etc may need to look in unexpected places!) This commit will likely affect many seeds. --- crawl-ref/docs/develop/levels/syntax.txt | 3 +++ crawl-ref/source/l-dgn.cc | 7 ------- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/crawl-ref/docs/develop/levels/syntax.txt b/crawl-ref/docs/develop/levels/syntax.txt index c70c3bcf6b09..1b087ea1c346 100644 --- a/crawl-ref/docs/develop/levels/syntax.txt +++ b/crawl-ref/docs/develop/levels/syntax.txt @@ -208,6 +208,9 @@ DEPTH: For random vaults, branch entry vaults, and minivaults, this Lair, for instance (Lair is treated as depth 10 for this purpose.) In general, you should avoid using such unconstrained DEPTHs. + If there are multiple DEPTH: declarations, later ones will be added + to previous ones. + CHANCE: [ () ] CHANCE allows you to control the probability that your map is used on diff --git a/crawl-ref/source/l-dgn.cc b/crawl-ref/source/l-dgn.cc index b10e3faf1f37..2b21cd3781fe 100644 --- a/crawl-ref/source/l-dgn.cc +++ b/crawl-ref/source/l-dgn.cc @@ -81,16 +81,10 @@ static int dgn_depth_proc(lua_State *ls, depth_ranges &dr, int s) return 0; } - dr.clear(); dgn_add_depths(dr, ls, s, lua_gettop(ls)); return 0; } -static int dgn_default_depth(lua_State *ls) -{ - return dgn_depth_proc(ls, lc_default_depths, 1); -} - static int dgn_depth(lua_State *ls) { MAP(ls, 1, map); @@ -1756,7 +1750,6 @@ const struct luaL_reg dgn_dlib[] = { { "reset_level", _dgn_reset_level }, -{ "default_depth", dgn_default_depth }, { "name", dgn_name }, { "depth", dgn_depth }, { "place", dgn_place }, From 011bc4bd618ba919aad67db917da24e0d5e518df Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Mon, 11 Feb 2019 07:21:51 +0000 Subject: [PATCH 108/864] Fix yellow draconians' rAcid mutation not being applied (malacante) --- crawl-ref/source/dat/species/draconian-yellow.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/source/dat/species/draconian-yellow.yaml b/crawl-ref/source/dat/species/draconian-yellow.yaml index 223884318f28..c6c6c3294d98 100644 --- a/crawl-ref/source/dat/species/draconian-yellow.yaml +++ b/crawl-ref/source/dat/species/draconian-yellow.yaml @@ -31,6 +31,7 @@ levelup_stat_frequency: 4 mutations: 1: MUT_COLD_BLOODED: 1 + 7: MUT_ACID_RESISTANCE: 1 14: MUT_ACIDIC_BITE: 1 From 9a59f91d9abe31c84d22a9f40119ff53d9f15950 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 14 Feb 2019 09:18:52 -0500 Subject: [PATCH 109/864] Improve a very old fixup --- crawl-ref/source/tags.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index 1ba00d8a4d28..f19ca801bac0 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -2911,8 +2911,12 @@ static void tag_read_you(reader &th) // tags. if (you.mutation[MUT_TELEPORT_CONTROL] == 1) you.mutation[MUT_TELEPORT_CONTROL] = 0; - if (you.mutation[MUT_TRAMPLE_RESISTANCE] > 0) + if (you.mutation[MUT_TRAMPLE_RESISTANCE] > 0 + || you.innate_mutation[MUT_TRAMPLE_RESISTANCE] > 0) + { you.mutation[MUT_TRAMPLE_RESISTANCE] = 0; + you.innate_mutation[MUT_TRAMPLE_RESISTANCE] = 0; + } if (you.mutation[MUT_CLING] == 1) you.mutation[MUT_CLING] = 0; if (you.species == SP_GARGOYLE) From f57072b2d6964a4f53699fce0de7f126760642f4 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 14 Feb 2019 11:49:56 -0500 Subject: [PATCH 110/864] Fix a couple of des cache random tag bugs Because lua code is run during des cache validation, any random decisions made during validation may be incorporated into the cache. I *think* this is mostly harmless but there are at least two problems that arise when it applies to vaults tags. First, random choices when selecting maps can be impacted by the number of tags *in the cache*, so seeds will potentially behave differently depending on choices made when first building the cache. Second, because tags are strictly additive, a tag choice made during cache building will never get removed; for example in `lemuel_altar_in_water` before this commit, if the cache rolled no_pool_fixup, this would be present in all instances of this vault regardless of rolls when actually placing the vault. It's possible that tags should be cleared when rerunning vault lua for placement, but that seems like a change that could potentially impact a lot of things and will require some testing, so I'm going to postpone it. In general it would probably be best to eliminate *all* randomization from the cache, but I'm not yet sure what the best technical solution to that is (there are quite a few vaults that use random calls like this to set SUBST or monster values, it doesn't seem ideal to impose is_validating checks on all of them). --- crawl-ref/source/dat/des/altar/altar.des | 8 +++----- crawl-ref/source/dat/des/variable/mini_monsters.des | 6 ++++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crawl-ref/source/dat/des/altar/altar.des b/crawl-ref/source/dat/des/altar/altar.des index 2fdaaa4c6464..d494be50d8f7 100644 --- a/crawl-ref/source/dat/des/altar/altar.des +++ b/crawl-ref/source/dat/des/altar/altar.des @@ -108,12 +108,10 @@ ENDMAP NAME: lemuel_altar_in_water DEPTH: D:2-, Swamp, Shoals WEIGHT: 9 -: local brnd = crawl.random2(13) -: if brnd > 10 then TAGS: transparent no_monster_gen no_rotate decor -# this case almost always has altar access -: else -TAGS: transparent no_monster_gen no_pool_fixup no_rotate decor +: local brnd = crawl.random2(13) +: if not is_validating() and brnd <= 10 then +TAGS: no_pool_fixup : end KPROP: C = no_tele_into KMASK: C = opaque diff --git a/crawl-ref/source/dat/des/variable/mini_monsters.des b/crawl-ref/source/dat/des/variable/mini_monsters.des index 58a51042ce14..8c14fb673533 100644 --- a/crawl-ref/source/dat/des/variable/mini_monsters.des +++ b/crawl-ref/source/dat/des/variable/mini_monsters.des @@ -131,12 +131,14 @@ KITEM: R = ration tile:food_honeycomb SUBST: ? : .w SUBST: * : *:20 R:3 # Since one has to dig the bees out, early meliai are fine. -: if crawl.x_chance_in_y(15, 27) then +: if not is_validating() then +: if crawl.x_chance_in_y(15, 27) then TAGS: uniq_beehive NSUBST: 1 = 1:3 / 1:1 / * = 1 x:2 -: else +: else TAGS: uniq_hornetnest SUBST: 1 : 4 5:4 +: end : end COLOUR: x = yellow TILE: x = wall_wax From fd6172a7371f4e555bf4a2a385cf61a0dc168f60 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 14 Feb 2019 14:16:31 -0500 Subject: [PATCH 111/864] Fix Beogh crash for polymorphed followers (11880 / reaverb) If an orc gets turned into something that cannot hold items (e.g. via a chaos cloud shapeshifter effect) it will drop its gift, but the gift prop does not get cleared, something the new ^ extra screen was not checking for. This commit fixes things at the point of the crash; it's possible that the prop should get cleared when the item is dropped in the first place. --- crawl-ref/source/describe-god.cc | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/describe-god.cc b/crawl-ref/source/describe-god.cc index 45431399278c..9debf0a050bd 100644 --- a/crawl-ref/source/describe-god.cc +++ b/crawl-ref/source/describe-god.cc @@ -587,11 +587,18 @@ static formatted_string _beogh_extra_description() mons->props.exists(BEOGH_RANGE_WPN_GIFT_KEY) ? MSLOT_ALT_WEAPON : MSLOT_WEAPON; - desc.cprintf(" ("); + // An orc can still lose its gift, e.g. by being turned into a + // shapeshifter via a chaos cloud. TODO: should the gift prop be + // deleted at that point? + if (mons->inv[slot] != NON_ITEM) + { + desc.cprintf(" ("); - item_def &gift = mitm[mons->inv[slot]]; - desc += formatted_string::parse_string(menu_colour_item_name(gift,DESC_PLAIN)); - desc.cprintf(")"); + item_def &gift = mitm[mons->inv[slot]]; + desc += formatted_string::parse_string( + menu_colour_item_name(gift,DESC_PLAIN)); + desc.cprintf(")"); + } } desc.cprintf("\n"); } From 3372e67c9135f2ce507b5e1389e5ae6d3be94ac6 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 14 Feb 2019 14:46:16 -0500 Subject: [PATCH 112/864] Uncomment an accidentally commented vault call --- crawl-ref/source/dat/des/variable/ghost.des | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/dat/des/variable/ghost.des b/crawl-ref/source/dat/des/variable/ghost.des index a956b708d10b..c10ff4438e6f 100644 --- a/crawl-ref/source/dat/des/variable/ghost.des +++ b/crawl-ref/source/dat/des/variable/ghost.des @@ -749,7 +749,7 @@ ENDMAP NAME: gammafunk_ghost_hydra_chop DEPTH: D:8-, Lair, Swamp ORIENT: float -#: setup_hydra_weapon(_G) +: setup_hydra_weapon(_G) KMONS: O = player ghost {{ -- Set up hydra monster entry with a range of possible extra heads based on From 597dbe2dff2d6d5b1818619a9beda534adffc837 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 14 Feb 2019 21:41:12 -0500 Subject: [PATCH 113/864] Fix a math error in a test --- crawl-ref/source/test/vault_catalog.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/test/vault_catalog.lua b/crawl-ref/source/test/vault_catalog.lua index f13311bbbd7c..f4efbd406113 100644 --- a/crawl-ref/source/test/vault_catalog.lua +++ b/crawl-ref/source/test/vault_catalog.lua @@ -110,7 +110,7 @@ test_seed(starting_seed, per_seed_iters, generation_order, false) crawl.stderr("Checking some extended branches for seed " .. starting_seed .. "...") test_seed(starting_seed, per_seed_iters, generation_order_extended, true) -for i=starting_seed + 1, starting_seed + fixed_seeds - 2 do +for i=starting_seed + 1, starting_seed + fixed_seeds - 1 do crawl.stderr("Testing seed " .. i .. ".") test_seed(i, per_seed_iters, generation_order, true) end From 5d539f04da09b0d340e52d25720a636763bd4e92 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 14 Feb 2019 23:13:24 -0500 Subject: [PATCH 114/864] shorten test again --- crawl-ref/source/test/vault_catalog.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/test/vault_catalog.lua b/crawl-ref/source/test/vault_catalog.lua index f4efbd406113..38e4a5ec0bd6 100644 --- a/crawl-ref/source/test/vault_catalog.lua +++ b/crawl-ref/source/test/vault_catalog.lua @@ -10,7 +10,7 @@ -- account. local starting_seed = 1 -- fixed seed to start with -local fixed_seeds = 2 -- how many fixed seeds to run? +local fixed_seeds = 1 -- how many fixed seeds to run? local per_seed_iters = 1 -- how many stability tests to run per seed local rand_seeds = 1 -- how many random seeds to run From d1555973324e0cf6ecfbfa250744372ba7d2f44b Mon Sep 17 00:00:00 2001 From: advil Date: Fri, 15 Feb 2019 10:09:00 -0500 Subject: [PATCH 115/864] Don't try to describe off-level orc gifts (11881) Instead just say that the orc is off-level. Better would be to describe both the item and where they are, but the the way off-level followers are implemented means that it's basically impossible to get the item information without either a level excursion or a major rewrite. One option might be to save the item string as a prop? --- crawl-ref/source/describe-god.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/describe-god.cc b/crawl-ref/source/describe-god.cc index 9debf0a050bd..237a1bccf4e0 100644 --- a/crawl-ref/source/describe-god.cc +++ b/crawl-ref/source/describe-god.cc @@ -579,7 +579,12 @@ static formatted_string _beogh_extra_description() has_named_followers = true; desc += formatted_string(mons->full_name(DESC_PLAIN).c_str()); - if (given_gift(mons)) + if (companion_is_elsewhere(mons->mid)) + { + desc += formatted_string::parse_string( + " (on another level)"); + } + else if (given_gift(mons)) { mon_inv_type slot = mons->props.exists(BEOGH_SH_GIFT_KEY) ? MSLOT_SHIELD : From d3e027da15580609d5fc9cf02dc45285558518bc Mon Sep 17 00:00:00 2001 From: gammafunk Date: Sat, 16 Feb 2019 22:16:16 -0600 Subject: [PATCH 116/864] Don't let vampirism drain temporary monsters (blorx1) Temporary monsters created with a "fake abjuration" timer are considered non-summons, since they're created from some object, e.g. Sticks to Snakes, Animate Dead, and Tukima's Dance. Natural holiness monsters created this way are currently susceptible to vampirism from Vampiric Drain and vampiric melee attacks. This is a problem since these temporary monsters can be created by the player cheaply and killed with vampiric effects to restore HP and satiation (in the case of player vampires). Vampirism of temporary summoned monsters is already prevented, so this commit prevents it for these other temporary monsters as well. The main things effected are Sticks to Snakes and the Ratskin Cloak. Other differences between these temporary allies and normal summoned allies (e.g. the former allow Inner Flame) are unchanged. Durably summoned monsters are likewise unchanged, since these are not player-created. --- crawl-ref/source/attack.cc | 6 +++--- crawl-ref/source/melee-attack.cc | 11 +++-------- crawl-ref/source/mon-util.cc | 23 +++++++++++++++++++++++ crawl-ref/source/mon-util.h | 1 + crawl-ref/source/spl-damage.cc | 9 ++++++--- 5 files changed, 36 insertions(+), 14 deletions(-) diff --git a/crawl-ref/source/attack.cc b/crawl-ref/source/attack.cc index 26a81d1352b2..0ba6ed1ab76b 100644 --- a/crawl-ref/source/attack.cc +++ b/crawl-ref/source/attack.cc @@ -1547,11 +1547,11 @@ bool attack::apply_damage_brand(const char *what) { if (!weapon || damage_done < 1 - || defender->is_summoned() - || !(defender->holiness() & MH_NATURAL) + || !actor_is_susceptible_to_vampirism(*defender) || attacker->stat_hp() == attacker->stat_maxhp() || attacker->is_player() && you.duration[DUR_DEATHS_DOOR] - || x_chance_in_y(2, 5) && !is_unrandom_artefact(*weapon, UNRAND_LEECH)) + || x_chance_in_y(2, 5) + && !is_unrandom_artefact(*weapon, UNRAND_LEECH)) { break; } diff --git a/crawl-ref/source/melee-attack.cc b/crawl-ref/source/melee-attack.cc index 6d2fc44bc307..39b25d2f4399 100644 --- a/crawl-ref/source/melee-attack.cc +++ b/crawl-ref/source/melee-attack.cc @@ -2724,11 +2724,7 @@ void melee_attack::mons_apply_attack_flavour() // deliberate fall-through case AF_VAMPIRIC: - if (!(defender->holiness() & MH_NATURAL)) - break; - - // Disallow draining of summoned monsters. - if (defender->is_summoned()) + if (!actor_is_susceptible_to_vampirism(*defender)) break; if (defender->stat_hp() < defender->stat_maxhp()) @@ -3659,7 +3655,6 @@ bool melee_attack::_vamp_wants_blood_from_monster(const monster* mon) { return you.species == SP_VAMPIRE && you.hunger_state < HS_SATIATED - && !mon->is_summoned() - && mons_has_blood(mon->type) - && !testbits(mon->flags, MF_SPECTRALISED); + && actor_is_susceptible_to_vampirism(*mon) + && mons_has_blood(mon->type); } diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index ad84050d9f88..e31ee632b888 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -1035,6 +1035,29 @@ bool mons_eats_items(const monster& mon) return mons_is_slime(mon) && have_passive(passive_t::jelly_eating); } +/* Is the actor susceptible to vampirism? + * + * Undead actors and summoned, temporary, or ghostified monsters are all not + * susceptible. + * @param act The actor. + * @returns True if the actor is susceptible to vampirism, false otherwise. + */ +bool actor_is_susceptible_to_vampirism(const actor& act) +{ + if (!(act.holiness() & MH_NATURAL) || act.is_summoned()) + return false; + + if (act.is_player()) + return true; + + const monster *mon = act.as_monster(); + // Don't allow HP draining from temporary monsters such as those created by + // Sticks to Snakes. + return !mon->has_ench(ENCH_FAKE_ABJURATION) + // Nor from now-ghostly monsters. + && !testbits(mon->flags, MF_SPECTRALISED); +} + bool invalid_monster(const monster* mon) { return !mon || invalid_monster_type(mon->type); diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h index c436eb903ee1..33cd476d4185 100644 --- a/crawl-ref/source/mon-util.h +++ b/crawl-ref/source/mon-util.h @@ -380,6 +380,7 @@ bool mons_is_slime(const monster& mon); bool mons_class_is_plant(monster_type mc); bool mons_is_plant(const monster& mon); bool mons_eats_items(const monster& mon); +bool actor_is_susceptible_to_vampirism(const actor& act); monster_type mons_genus(monster_type mc); monster_type mons_species(monster_type mc); monster_type draco_or_demonspawn_subspecies(const monster& mon); diff --git a/crawl-ref/source/spl-damage.cc b/crawl-ref/source/spl-damage.cc index 2f4ef8840c40..23cc1378b799 100644 --- a/crawl-ref/source/spl-damage.cc +++ b/crawl-ref/source/spl-damage.cc @@ -725,7 +725,10 @@ spret vampiric_drain(int pow, monster* mons, bool fail) return spret::abort; } - if (!mons || mons->submerged()) + const bool observable = mons && mons->observable(); + if (!mons + || mons->submerged() + || !observable && !actor_is_susceptible_to_vampirism(*mons)) { fail_check(); @@ -736,7 +739,7 @@ spret vampiric_drain(int pow, monster* mons, bool fail) } // TODO: check known rN instead of holiness - if (mons->observable() && !(mons->holiness() & MH_NATURAL)) + if (observable && !actor_is_susceptible_to_vampirism(*mons)) { mpr("You can't drain life from that!"); return spret::abort; @@ -774,7 +777,7 @@ spret vampiric_drain(int pow, monster* mons, bool fail) hp_gain = div_rand_round(hp_gain, 2); - if (hp_gain && !mons->is_summoned() && !you.duration[DUR_DEATHS_DOOR]) + if (hp_gain && !you.duration[DUR_DEATHS_DOOR]) { mpr("You feel life coursing into your body."); inc_hp(hp_gain); From 53b51606c3e9e82d1c48a31361246907f715bc3a Mon Sep 17 00:00:00 2001 From: gammafunk Date: Sat, 16 Feb 2019 23:04:20 -0600 Subject: [PATCH 117/864] Tidy up a monster class method In monster::is_summoned(), remove checks for derived undead spells that no longer apply, since those use fake abjuration now, and clean up comments. --- crawl-ref/source/mon-ench.cc | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/crawl-ref/source/mon-ench.cc b/crawl-ref/source/mon-ench.cc index 7ed8ff691aae..802cac6eba10 100644 --- a/crawl-ref/source/mon-ench.cc +++ b/crawl-ref/source/mon-ench.cc @@ -1906,6 +1906,21 @@ void monster::mark_summoned(int longevity, bool mark_items, int summon_type, boo ii->flags |= ISFLAG_SUMMONED; } +/* Is the monster temporarily summoned? + * + * Monsters must have ENCH_ABJ (giving how long they last) to be considered + * summons. If they additionally set ENCH_SUMMON, which gives how they were + * derived, this must not be from certain spells or "monster summoning types" + * we don't consider actual summons. Temporary monsters with + * ENCH_FAKE_ABJURATION also aren't summons, and durably summoned monsters + * aren't temporary. + * + * @param[out] duration The monster's summon duration in aut. + * @param[out] summon_type The monster's means of summoning. If positive, this + * is a spell_type, if negative, it's a + * mon_summon_type. + * @returns True if the monster is a temporary summon, false otherwise. + */ bool monster::is_summoned(int* duration, int* summon_type) const { const mon_enchant abj = get_ench(ENCH_ABJ); @@ -1932,20 +1947,17 @@ bool monster::is_summoned(int* duration, int* summon_type) const if (summon_type != nullptr) *summon_type = summ.degree; + // Conjured things (fire vortices, ball lightning, IOOD) are not summoned. if (mons_is_conjured(type)) return false; + // Certain spells or monster summon types that set abjuration but aren't + // considered summons. switch (summ.degree) { // Temporarily dancing weapons are really there. case SPELL_TUKIMAS_DANCE: - // A corpse/skeleton which was temporarily animated. - case SPELL_ANIMATE_DEAD: - case SPELL_ANIMATE_SKELETON: - - // Conjured stuff (fire vortices, ball lightning, IOOD) is handled above. - // Clones aren't really summoned (though their equipment might be). case MON_SUMM_CLONE: From 3d66cf40a65a3843061e5a6d1106f9fa5d2b0bdb Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 17 Feb 2019 23:50:32 -0500 Subject: [PATCH 118/864] Build for SSE2 on all systems, including 32bit targets Believe it or not, this is a seed stability fix. On 32 bit targets where SSE2 is not defined, Lua uses a different method for converting from numbers (doubles) to ints (see `lua_number2int` in `luaconf.h`), than what happens on other targets (which is just a regular cast). The two methods have different rounding behavior, which is leading seeds that involve layout that passes non-integer values to c++ code into trouble; for example, layout_rooms does this during its join_the_dots calls (see 11884, seed 5313719195296785585). In practice, the non-standard rounding was happening only for cross-compiled windows builds that I know of, but perhaps some linux builds are also 32bit; there's also a code path that might affect msvc. Using -msse2 should prevent lua from ever using the non-standard conversion code. This fix should have the added benefit of preventing x87 from ever being used. We'll see though if this will bring people out of the woodwork who are building on very old devices... This commit also includes an unrelated tweak to some ordering in the Makefile so that AUTO_OPT can be used. --- crawl-ref/source/Makefile | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/crawl-ref/source/Makefile b/crawl-ref/source/Makefile index 75fa8b9bcfaf..dab94d765d88 100644 --- a/crawl-ref/source/Makefile +++ b/crawl-ref/source/Makefile @@ -109,6 +109,9 @@ include Makefile.obj STDFLAG = -std=c++11 CFOTHERS := -pipe $(EXTERNAL_FLAGS) +# force SSE2 dependency, so as to avoid both x87 indeterminacies, and +# to prevent lua from using non-standard rounding methods. +CFOTHERS += -mfpmath=sse -msse2 CFWARN := CFWARN_L := -Wall -Wformat-security -Wundef @@ -492,21 +495,6 @@ WINDRES := $(CROSSHOST)-windres endif -# Define this to automatically generate code optimized for your machine -# (GCC only as of now). -# -# NOTE: Don't use this with a release build, since the generated code -# won't work for all machines. -ifdef HURRY -NO_AUTO_OPT = YesPlease -endif - -ifdef AUTO_OPT -ifndef NO_AUTO_OPT -CFOPTIMIZE += -march=native -endif -endif - ifdef USE_ICC # If you have a Core 2 processor, this _really_ makes things fly: #CFOPTIMIZE := -O2 -parallel -xT @@ -528,6 +516,21 @@ else endif endif +# Define this to automatically generate code optimized for your machine +# (GCC only as of now). +# +# NOTE: Don't use this with a release build, since the generated code +# won't work for all machines. +ifdef HURRY +NO_AUTO_OPT = YesPlease +endif + +ifdef AUTO_OPT +ifndef NO_AUTO_OPT +CFOPTIMIZE += -march=native +endif +endif + ifdef LTO ifeq ($(shell $(GXX) -v 2>&1|grep clang),) CFOPTIMIZE += -flto=jobserver -fwhole-program From 107517c6e49a09b38048a4d44431e2bd8d7097f5 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 18 Feb 2019 22:26:53 -0500 Subject: [PATCH 119/864] Prevent a PlaceInfo miscalculation and fix the resulting crash The level entry code (for purposes of pregeneration) assumed that 0 turns on level = the level hasn't been entered. There are in fact at least three ways to break this assumption: wizmode movement (e.g. &u,&d), taking an escape hatch and being shafted immediately, and being banished by something fast enough to move when you first enter the level (at least, ebering says this is possible). When this happened, the PlaceInfo accounting would be run twice, and so the level would get double-counted, leading to a crash deeper in the branch. Luckily I added the level_entered code towards the end of the project, and this does what this code needs. This commit also includes some save compat since there may be ongoing games during tournament that have this crash. --- crawl-ref/source/files.cc | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index b7510f1d66e7..59160fb6f32c 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1573,7 +1573,7 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, return just_created_level; } - if (env.turns_on_level == 0) + if (!you.level_visited(level_id::current())) just_created_level = true; // in case level was pre-generated if (load_mode != LOAD_VISITOR) @@ -1698,6 +1698,22 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, mprf(MSGCH_DIAGNOSTICS, "curr_PlaceInfo:: num_visits: %d, levels_seen: %d", curr_PlaceInfo.num_visits, curr_PlaceInfo.levels_seen); +#endif +#if TAG_MAJOR_VERSION == 34 + // this fixup is for a bug where turns_on_level==0 was used to set + // just_created_level, and there were some obscure ways to have 0 + // turns on a level that you had entered previously. It only applies + // to a narrow version range (basically 0.23.0) but there's no way to + // do a sensible minor version check here and the fixup can't happen + // on load. + if (curr_PlaceInfo.levels_seen > brdepth[curr_PlaceInfo.branch]) + { + mprf(MSGCH_ERROR, + "Fixing up corrupted PlaceInfo for %s (levels_seen is %d)", + branches[curr_PlaceInfo.branch].shortname, + curr_PlaceInfo.levels_seen); + curr_PlaceInfo.levels_seen = brdepth[BRANCH_DUNGEON]; + } #endif curr_PlaceInfo.assert_validity(); } From 429d40e2d63ad5bf1b5fb0c56a0ac80288287d37 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 18 Feb 2019 22:36:17 -0500 Subject: [PATCH 120/864] Set the branch depth correctly in 107517c6e49a ... --- crawl-ref/source/files.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 59160fb6f32c..7b72f42c2601 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1712,7 +1712,7 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, "Fixing up corrupted PlaceInfo for %s (levels_seen is %d)", branches[curr_PlaceInfo.branch].shortname, curr_PlaceInfo.levels_seen); - curr_PlaceInfo.levels_seen = brdepth[BRANCH_DUNGEON]; + curr_PlaceInfo.levels_seen = brdepth[curr_PlaceInfo.branch]; } #endif curr_PlaceInfo.assert_validity(); From ab847a317b82e2fb0316bf19c0c5e8f66163f2a7 Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Tue, 19 Feb 2019 20:35:09 +0000 Subject: [PATCH 121/864] Fix Ozocubu's Refrigeration (11885) Since fb95405, the damage of both the player and monster versions of Ozocubu's Refrigeration has been one third of what it should be, specifically 3d((5 + power/10)/3), leading to a very underwhelming level 6 spell. This was because fb95405 converted the original dice_def that was used to calculate the damage from this spell into a calcdice_calculator, without adjusting for the fact that the calc_dice function divides the number of sides on each die by the number of dice. One way to fix this would be to use a dicedef_calculator instead; however a calcdice_calculator is preferred for the fact that it randomly rounds power/N instead of always using integer division (which creates minor breakpoints). Therefore this commit instead fixes the damage by tripling the inside of the dice roll bracket, leading to a 3d((15 + 3*power/10)/3) dice roll which is equivalent to the old 3d(5 + power/10). --- crawl-ref/source/zap-data.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/zap-data.h b/crawl-ref/source/zap-data.h index 37691436bbe1..85674397c27a 100644 --- a/crawl-ref/source/zap-data.h +++ b/crawl-ref/source/zap-data.h @@ -1308,9 +1308,9 @@ _mon_hex_zap(ZAP_DRAIN_MAGIC, BEAM_DRAIN_MAGIC), ZAP_REFRIGERATE, "refrigeration", 200, - new calcdice_calculator<3, 5, 1, 10>, + new calcdice_calculator<3, 15, 3, 10>, new tohit_calculator<40>, - new calcdice_calculator<3, 5, 1, 10>, + new calcdice_calculator<3, 15, 3, 10>, new tohit_calculator<40>, LIGHTCYAN, false, From e09df0593cbd70cf18bbe2532558e6d1de8b2b3a Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 19 Feb 2019 17:22:51 -0500 Subject: [PATCH 122/864] Fix PlaceInfo fixup more (11890) ... --- crawl-ref/source/files.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 7b72f42c2601..417d1c66b3bd 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1706,7 +1706,9 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, // to a narrow version range (basically 0.23.0) but there's no way to // do a sensible minor version check here and the fixup can't happen // on load. - if (curr_PlaceInfo.levels_seen > brdepth[curr_PlaceInfo.branch]) + if (is_connected_branch(curr_PlaceInfo.branch) + && brdepth[curr_PlaceInfo.branch] > 0 + && curr_PlaceInfo.levels_seen > brdepth[curr_PlaceInfo.branch]) { mprf(MSGCH_ERROR, "Fixing up corrupted PlaceInfo for %s (levels_seen is %d)", From a2403f33072dc5ecb8d5d390848b63c791ccf40c Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 19 Feb 2019 17:35:45 -0500 Subject: [PATCH 123/864] Quiet a gcc warning (signed vs unsigned comparison) --- crawl-ref/source/files.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 417d1c66b3bd..d42008a6adc2 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1708,7 +1708,8 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, // on load. if (is_connected_branch(curr_PlaceInfo.branch) && brdepth[curr_PlaceInfo.branch] > 0 - && curr_PlaceInfo.levels_seen > brdepth[curr_PlaceInfo.branch]) + && static_cast(curr_PlaceInfo.levels_seen) + > brdepth[curr_PlaceInfo.branch]) { mprf(MSGCH_ERROR, "Fixing up corrupted PlaceInfo for %s (levels_seen is %d)", From 2bff182ff06dde757ae6a22834a7f19c08d69b52 Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Fri, 22 Feb 2019 17:06:56 +0000 Subject: [PATCH 124/864] Update a file path in git docs --- crawl-ref/docs/develop/git/config.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/docs/develop/git/config.txt b/crawl-ref/docs/develop/git/config.txt index c5e41ab4e18d..a540a11089ec 100644 --- a/crawl-ref/docs/develop/git/config.txt +++ b/crawl-ref/docs/develop/git/config.txt @@ -43,7 +43,7 @@ Some useful config options: Install a pre-commit sanity check From the root of the git tree type: -cp crawl-ref/git-hooks/pre-commit .git/hooks +cp crawl-ref/docs/develop/git/pre-commit .git/hooks ------------------------- From df024910cac5a2b5d868962791b38e7ca7ad5941 Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Fri, 22 Feb 2019 18:05:24 +0000 Subject: [PATCH 125/864] Fix character creation highlighting in console Darkgrey doesn't function in some terminals, so instead use the same colouring as webtiles builds. --- crawl-ref/source/newgame.cc | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 6b3a1acf9901..43ee7484a37e 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -50,13 +50,8 @@ static bool _choose_weapon(newgame_def& ng, newgame_def& ng_choice, # define STARTUP_HIGHLIGHT_BAD LIGHTGRAY # define STARTUP_HIGHLIGHT_CONTROL LIGHTGRAY # define STARTUP_HIGHLIGHT_GOOD LIGHTGREEN -#elif defined(USE_TILE_WEB) -# define STARTUP_HIGHLIGHT_NORMAL BLUE -# define STARTUP_HIGHLIGHT_BAD LIGHTGRAY -# define STARTUP_HIGHLIGHT_CONTROL BLUE -# define STARTUP_HIGHLIGHT_GOOD GREEN #else -# define STARTUP_HIGHLIGHT_NORMAL DARKGRAY +# define STARTUP_HIGHLIGHT_NORMAL BLUE # define STARTUP_HIGHLIGHT_BAD LIGHTGRAY # define STARTUP_HIGHLIGHT_CONTROL BLUE # define STARTUP_HIGHLIGHT_GOOD GREEN From 3f76249d505d5acc0c46f631ca08dde258fb9b16 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Sun, 24 Feb 2019 17:12:08 -0600 Subject: [PATCH 126/864] Remove the trunk reminder for the 0.23 tournament This reverts commit 7d8ec5708864d2872871cd49295b12a5b291238d. --- crawl-ref/source/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/Makefile b/crawl-ref/source/Makefile index dab94d765d88..4145987821fd 100644 --- a/crawl-ref/source/Makefile +++ b/crawl-ref/source/Makefile @@ -115,7 +115,7 @@ CFOTHERS += -mfpmath=sse -msse2 CFWARN := CFWARN_L := -Wall -Wformat-security -Wundef -DEFINES := -DTOURNEY='"0.23"' $(EXTERNAL_DEFINES) +DEFINES := $(EXTERNAL_DEFINES) ifndef ANDROID LDFLAGS := From fc1eed5d34c6ec5942309776f806e12eb0ccc867 Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 24 Feb 2019 13:08:02 -0500 Subject: [PATCH 127/864] Add a build option to not use SSE This is in response to #992. To use this, do e.g. make TILES=y NOSSE=y --- crawl-ref/source/Makefile | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crawl-ref/source/Makefile b/crawl-ref/source/Makefile index 4145987821fd..0fc10b93d0a6 100644 --- a/crawl-ref/source/Makefile +++ b/crawl-ref/source/Makefile @@ -62,6 +62,8 @@ # WEBDIR -- place to hold the Webtiles client data. Can be either # relative to prefix or absolute. # +# NOSSE -- build without SSE support, e.g. on a non-x86 processor. +# Defining this may affect seed stability. # ANDROID -- perform an Android build (see docs/develop/android.txt) # TOUCH_UI -- enable UI behaviour more compatible with touch-screens # @@ -108,10 +110,16 @@ include Makefile.obj # Which C++ standard to support STDFLAG = -std=c++11 +ifdef ANDROID +NOSSE := Yes +endif + CFOTHERS := -pipe $(EXTERNAL_FLAGS) +ifndef NOSSE # force SSE2 dependency, so as to avoid both x87 indeterminacies, and # to prevent lua from using non-standard rounding methods. CFOTHERS += -mfpmath=sse -msse2 +endif CFWARN := CFWARN_L := -Wall -Wformat-security -Wundef From 1e4b560c4d8210d682f9aeeee0cd1a65437850b0 Mon Sep 17 00:00:00 2001 From: Umer Shaikh Date: Sat, 23 Feb 2019 19:22:18 -0600 Subject: [PATCH 128/864] Clean up god gifts' interaction with delays (11825) Getting a Nemelex gift at the end of a successful passwall that revealed new cells caused the message "Your meditation is interrupted." to be printed. This is because do_god_gift interrupted running and resting in a way that interrupted and removed the passwall delay. We now call stop_running with the clear_delays parameter set to false in order to no longer clear delays. We also call stop_running instead of directly reaching down to you.running.stop. --- crawl-ref/source/religion.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index 049702006060..eef90c2d23f9 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -2049,7 +2049,7 @@ bool do_god_gift(bool forced) } // End of gift giving. if (success) - you.running.stop(); + stop_running(false); #if defined(DEBUG_DIAGNOSTICS) || defined(DEBUG_GIFTS) if (old_num_current_gifts < you.num_current_gifts[you.religion]) From db70d5e40e67d5362310165970ab0c9ed0a707a9 Mon Sep 17 00:00:00 2001 From: Alex Jurkiewicz Date: Sun, 10 Feb 2019 17:17:56 +1100 Subject: [PATCH 129/864] Expose MR and Stealth to Lua Two new functions return the number of pips for each of these resistances. --- crawl-ref/source/l-you.cc | 13 +++++++++++++ crawl-ref/source/output.cc | 4 ++-- crawl-ref/source/output.h | 2 ++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/l-you.cc b/crawl-ref/source/l-you.cc index 303628b24dc9..f30c4160d10a 100644 --- a/crawl-ref/source/l-you.cc +++ b/crawl-ref/source/l-you.cc @@ -32,6 +32,7 @@ #include "ouch.h" #include "output.h" #include "place.h" +#include "player.h" #include "prompt.h" #include "religion.h" #include "shopping.h" @@ -220,6 +221,16 @@ LUARET1(you_res_draining, number, player_prot_life(false)) * @function res_shock */ LUARET1(you_res_shock, number, player_res_electricity(false)) +/*** Stealth pips. + * @treturn int number of stealth pips + * @function stealth_pips + */ +LUARET1(you_stealth_pips, number, stealth_breakpoint(player_stealth())) +/*** Magic resistance (MR). + * @treturn int number of MR pips + * @function res_magic + */ +LUARET1(you_res_magic, number, player_res_magic(false) / MR_PIP) /*** Drowning resistance (rDrown). * @treturn int resistance level * @function res_drowning @@ -1162,6 +1173,8 @@ static const struct luaL_reg you_clib[] = { "res_cold" , you_res_cold }, { "res_draining", you_res_draining }, { "res_shock" , you_res_shock }, + { "stealth_pips", you_stealth_pips }, + { "res_magic" , you_res_magic }, { "res_drowning", you_res_drowning }, { "res_mutation", you_res_mutation }, { "see_invisible", you_see_invisible }, diff --git a/crawl-ref/source/output.cc b/crawl-ref/source/output.cc index cdc35943dd2a..e3e421534857 100644 --- a/crawl-ref/source/output.cc +++ b/crawl-ref/source/output.cc @@ -1913,7 +1913,7 @@ static const char* _determine_colour_string(int level, int max_level) } } -static int _stealth_breakpoint(int stealth) +int stealth_breakpoint(int stealth) { if (stealth == 0) return 0; @@ -1931,7 +1931,7 @@ static string _stealth_bar(int sw) //no colouring bar += _determine_colour_string(0, 5); bar += "Stlth "; - const int stealth_num = _stealth_breakpoint(player_stealth()); + const int stealth_num = stealth_breakpoint(player_stealth()); for (int i = 0; i < stealth_num; i++) bar += "+"; for (int i = 0; i < 10 - stealth_num; i++) diff --git a/crawl-ref/source/output.h b/crawl-ref/source/output.h index e5b7e65decc2..cff7d3e532ea 100644 --- a/crawl-ref/source/output.h +++ b/crawl-ref/source/output.h @@ -29,6 +29,8 @@ int update_monster_pane(); const char *equip_slot_to_name(int equip); int equip_name_to_slot(const char *s); +int stealth_breakpoint(int stealth); + void print_overview_screen(); string mutation_overview(); From a3c21ffb5ec2e4297eb2f50aa560c984ebd4707a Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 25 Feb 2019 19:42:34 -0500 Subject: [PATCH 130/864] Improve behavior of local tiles Text, especially on hidpi displays This commit ends up doing a number of things: 1. (most important) fix a bug on retina (and other hidpi) displays where the height of Text widget contents was not calculated correctly, because the code didn't handle fractional y advances. This resulted in ctrl-p dropping several lines at the end, among other things. 2. Fix handling of fractional y advances when drawing highlights, again a potential issue in long Texts (though less important, as highlighting is almost never used right now). In the course of this, I needed to understand how the highlight code worked and this forced me to add a lot of comments and do some code formatting, as well as address the following bugs: 3. Don't highlight lines more than once in hl_line mode, this results in unreadable text. 4. Handle the case where the end of a string coincides exactly with the end of the window and is highlighted, which was leading to glitches in my testing. 5. Better handling for cases where a highlight spans multiple slices of the formatted string. I'm not 100% sure if this was really broken before my fix of 4, but it works now. I'm still not entirely sure about all this highlighting code, and it's pretty complicated and monolithic, so it could probably use some more work and refactoring. --- crawl-ref/source/ui.cc | 150 ++++++++++++++++++++++++++++------------- 1 file changed, 104 insertions(+), 46 deletions(-) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index b76755a54ac3..eb2fe801547d 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -529,19 +529,26 @@ void Text::_render() wrap_text_to_size(m_region[2], m_region[3]); #ifdef USE_TILE_LOCAL - const int line_height = tiles.get_crt_font()->char_height(); - const unsigned line_min = (region[1]-m_region[1]) / line_height; - const unsigned line_max = (region[1]+region[3]-m_region[1]) / line_height; - + const int dev_line_height = tiles.get_crt_font()->char_height(false); + const int line_min_pos = display_density.logical_to_device( + region[1] - m_region[1]); + const int line_max_pos = display_density.logical_to_device( + region[1] + region[3] - m_region[1]); + const int line_min = line_min_pos / dev_line_height; + const int line_max = line_max_pos / dev_line_height; + + // find the earliest and latest ops in the string that could be displayed + // in the currently visible region, as well as the line offset of the + // earliest. int line_off = 0; int ops_min = 0, ops_max = m_text_wrapped.ops.size(); { int i = 1; - for (; i < (int)m_brkpts.size(); i++) + for (; i < (int) m_brkpts.size(); i++) if (m_brkpts[i].line >= line_min) { - ops_min = m_brkpts[i-1].op; - line_off = m_brkpts[i-1].line; + ops_min = m_brkpts[i - 1].op; + line_off = m_brkpts[i - 1].line; break; } for (; i < (int)m_brkpts.size(); i++) @@ -552,11 +559,15 @@ void Text::_render() } } + // the slice of the contained string that will be displayed formatted_string slice; slice.ops = vector( - m_text_wrapped.ops.begin()+ops_min, - m_text_wrapped.ops.begin()+ops_max); + m_text_wrapped.ops.begin() + ops_min, + m_text_wrapped.ops.begin() + ops_max); + // TODO: this is really complicated, can it be refactored? Does it + // really need to iterate over the formatted_text slices? I'm not sure + // the formatting ever matters for highlighting locations. if (!hl_pat.empty()) { const auto& full_text = m_text.tostring(); @@ -566,70 +577,115 @@ void Text::_render() // only because wordwrapping only replaces ' ' with '\n': in other words, // this is fairly brittle ASSERT(full_text.size() == m_text_wrapped.tostring().size()); - int begin_idx = ops_min == 0 ? 0 : m_text_wrapped.tostring(0, ops_min-1).size(); - int end_idx = begin_idx + m_text_wrapped.tostring(ops_min, ops_max-1).size(); + // index of the first and last ops that are being displayed + int begin_idx = ops_min == 0 ? + 0 : + m_text_wrapped.tostring(0, ops_min - 1).size(); + int end_idx = begin_idx + + m_text_wrapped.tostring(ops_min, ops_max-1).size(); + + vector highlights = _find_highlights(full_text, hl_pat, + begin_idx, end_idx); + + int ox = m_region[0]; + const int oy = display_density.logical_to_device(m_region[1]) + + dev_line_height * line_off; + size_t lacc = 0; // the start char of the current op relative to region + size_t line = 0; // the line we are at relative to the region - vector highlights = _find_highlights(full_text, hl_pat, begin_idx, end_idx); - - const int ox = m_region[0], oy = m_region[1]+line_height*line_off; - size_t lacc = 0, line = 0; FontWrapper *font = tiles.get_crt_font(); bool inside = false; + // Iterate over formatted_string op slices, looking for highlight + // sequences. Highlight sequences may span multiple op slices, hence + // some of the complexity here. + // All the y math in this section needs to be done in device pixels, + // in order to handle fractional advances. + set block_lines; for (unsigned i = 0; i < slice.ops.size() && !highlights.empty(); i++) { const auto& op = slice.ops[i]; if (op.type != FSOP_TEXT) continue; size_t oplen = op.text.size(); - size_t start = highlights[0] - begin_idx - lacc, - end = highlights[0] - begin_idx - lacc + hl_pat.size(); + // dimensions in chars of the pattern relative to current op + size_t start = highlights[0] - begin_idx - lacc; + size_t end = highlights[0] - begin_idx - lacc + hl_pat.size(); + + size_t op_line_start = begin_idx + lacc > 0 + ? full_text.rfind('\n', begin_idx + lacc - 1) + : string::npos; + op_line_start = op_line_start == string::npos + ? 0 + : op_line_start + 1; + string line_before_op = full_text.substr(op_line_start, + begin_idx + lacc - op_line_start); + // pixel positions for the current op + size_t op_x = font->string_width(line_before_op.c_str()); + const size_t op_y = + font->string_height(line_before_op.c_str(), false) + - dev_line_height; + + // positions in device pixels to highlight relative to current op size_t sx = 0, ex = font->string_width(op.text.c_str()); - size_t sy = 0, ey = line_height; - bool started = false, ended = false; + size_t sy = 0, ey = dev_line_height; + + bool started = false; // does the highlight start in the current op? + bool ended = false; // does the highlight end in the current op? if (start < oplen) // assume start is unsigned and so >=0 { - { - size_t line_start = full_text.rfind('\n', highlights[0]); - line_start = line_start == string::npos ? 0 : line_start+1; - const string before = full_text.substr(line_start, highlights[0]-line_start); - sx = font->string_width(before.c_str()); - } - { - const string before = full_text.substr(lacc+begin_idx, highlights[0]-lacc-begin_idx); - sy = font->string_height(before.c_str()) - line_height; - } + // hacky: reset op x to 0 if we've hit a linebreak in the op + // before start. This is to handle cases where the op starts + // midline, but the pattern is after a linebreak in the op. + const size_t linebreak_in_op = op.text.find("\n"); + if (start > linebreak_in_op) + op_x = 0; + // start position is somewhere in the current op + const string before = full_text.substr(begin_idx + lacc, start); + sx = font->string_width(before.c_str()); + sy = font->string_height(before.c_str(), false) + - dev_line_height; started = true; } - if (end < oplen) // assume end is unsigned and so >=0 + if (end <= oplen) // assume end is unsigned and so >=0 { - { - size_t line_start = full_text.rfind('\n', highlights[0]+hl_pat.size()-1); - line_start = line_start == string::npos ? 0 : line_start+1; - const string to_end = full_text.substr(line_start, highlights[0]+hl_pat.size()-line_start); - ex = font->string_width(to_end.c_str()); - } - { - const string to_end = full_text.substr(lacc+begin_idx, highlights[0]+hl_pat.size()-1-lacc-begin_idx); - ey = font->string_height(to_end.c_str()); - } + const string to_end = full_text.substr(begin_idx + lacc, end); + ex = font->string_width(to_end.c_str()); + ey = font->string_height(to_end.c_str(), false); ended = true; } if (started || ended || inside) { m_hl_buf.clear(); - for (size_t y = oy+line+sy; y < oy+line+ey; y+=line_height) + // TODO: as far as I can tell, the above code never produces + // multi-line spans for this to iterate over... + for (size_t y = oy + op_y + line + sy; + y < oy + op_y + line + ey; + y += dev_line_height) { + if (block_lines.count(y)) // kind of brittle... + continue; if (hl_line) { - m_hl_buf.add(region[0], y, region[0]+region[2], y + line_height, + block_lines.insert(y); + m_hl_buf.add(region[0], + display_density.device_to_logical(y), + region[0] + region[2], + display_density.device_to_logical(y + + dev_line_height), VColour(255, 255, 0, 50)); } else - m_hl_buf.add(ox + sx, y, ox + ex, y + line_height, + { + m_hl_buf.add(ox + op_x + sx, + display_density.device_to_logical(y), + ox + op_x + ex, + display_density.device_to_logical(y + + dev_line_height), VColour(255, 255, 0, 50)); + } } m_hl_buf.draw(); } @@ -637,13 +693,14 @@ void Text::_render() if (ended) { - highlights.erase(highlights.begin()+0); + highlights.erase(highlights.begin() + 0); i--; } else { lacc += oplen; - line += font->string_height(op.text.c_str()) - line_height; + line += font->string_height(op.text.c_str(), false) + - dev_line_height; } } } @@ -652,7 +709,8 @@ void Text::_render() // in FTFontWrapper, that, like render_textblock(), would automatically // handle swapping atlas glyphs as necessary. FontBuffer m_font_buf(tiles.get_crt_font()); - m_font_buf.add(slice, m_region[0], m_region[1]+line_height*line_off); + m_font_buf.add(slice, m_region[0], m_region[1] + + display_density.device_to_logical(dev_line_height * line_off)); m_font_buf.draw(); #else const auto& lines = m_wrapped_lines; From 11e5bb60195fbd640444704ffe2709e9e0cea5df Mon Sep 17 00:00:00 2001 From: Josh Braden Date: Tue, 26 Feb 2019 13:52:28 -0600 Subject: [PATCH 131/864] Remove incorrect fake_mutations from vampire (11870) --- crawl-ref/source/dat/species/vampire.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/crawl-ref/source/dat/species/vampire.yaml b/crawl-ref/source/dat/species/vampire.yaml index 52b749e5e10f..54e8d84bb631 100644 --- a/crawl-ref/source/dat/species/vampire.yaml +++ b/crawl-ref/source/dat/species/vampire.yaml @@ -49,10 +49,6 @@ mutations: MUT_FANGS: 3 MUT_ACUTE_VISION: 1 MUT_UNBREATHING: 1 -fake_mutations: - - long: Your body is rotting away. - short: rotting body - - long: You thrive on raw meat. recommended_jobs: - JOB_GLADIATOR - JOB_ASSASSIN From e4b1dceb6d97c3a73f9b49e99b68173afd9aa813 Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 26 Feb 2019 22:41:07 -0500 Subject: [PATCH 132/864] Change error reporting for post-place hook failures When a post-place hook tries to place a map, the main reason to set die_on_failure is just to trigger a veto in a sensible way. However, the way this was implemented inevitably printed an error message about the placement failure to the user, causing bug reports and confusion. This situation was expanded by 56b24058a9 and 091e5a18fee, after which the proper way for a post-place hook to trigger a veto when placing a map is exactly to set die_on_failure. This commit makes any lua error during a hook with a specific string indicating that it is a failure to place a subvault silent, but still vetoing. Conveniently, this will clean up the infamous "Failed to place map 'shoals_ilsuiw_ice'" errors too (10080, 10262), as this is one of the cases where previously a post-place hook correctly set die_on_failure. I should note that I don't know why it is specifically this map of the `shoal_guardian`-tagged maps that tends to fail to place, but from the debug build output when this failure happens I think it is just normal subvault placement failure; there must be *something* about it that is more likely to accrue placement failures than the others with this tag. --- crawl-ref/source/dat/dlua/dungeon.lua | 1 + crawl-ref/source/mapdef.cc | 22 ++++++++++++++-------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/crawl-ref/source/dat/dlua/dungeon.lua b/crawl-ref/source/dat/dlua/dungeon.lua index 0291d6634555..7bb66c7288cb 100644 --- a/crawl-ref/source/dat/dlua/dungeon.lua +++ b/crawl-ref/source/dat/dlua/dungeon.lua @@ -580,6 +580,7 @@ function dgn.place_maps(parameters) local n_placed = 0 local function map_error(name) + -- this prefix string is used in map_def::run_hook error("Failed to place map '" .. name .. "'") end diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc index 45707fdcb77f..1f539cca74e1 100644 --- a/crawl-ref/source/mapdef.cc +++ b/crawl-ref/source/mapdef.cc @@ -2577,16 +2577,22 @@ bool map_def::run_hook(const string &hook_name, bool die_on_lua_error) const dlua_set_map mset(this); if (!dlua.callfn("dgn_map_run_hook", "s", hook_name.c_str())) { - if (die_on_lua_error) + const string error = rewrite_chunk_errors(dlua.error); + // only show the error message if this isn't a hook map-placement + // failure, which should just lead to a silent veto. + if (error.find("Failed to place map") == string::npos) { - end(1, false, "Lua error running hook '%s' on map '%s': %s", - hook_name.c_str(), name.c_str(), - rewrite_chunk_errors(dlua.error).c_str()); + if (die_on_lua_error) + { + end(1, false, "Lua error running hook '%s' on map '%s': %s", + hook_name.c_str(), name.c_str(), error.c_str()); + } + else + { + mprf(MSGCH_ERROR, "Lua error running hook '%s' on map '%s': %s", + hook_name.c_str(), name.c_str(), error.c_str()); + } } - else - mprf(MSGCH_ERROR, "Lua error running hook '%s' on map '%s': %s", - hook_name.c_str(), name.c_str(), - rewrite_chunk_errors(dlua.error).c_str()); return false; } return true; From 8d2b5ac6c9c34d727f5554a5df7f30e6473b52b7 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Mon, 25 Feb 2019 16:25:32 -0600 Subject: [PATCH 133/864] Lower the chance for Boris to respawn Boris has a flat 1/3 chance to respawn in relevant branches as of 4636eb8. This has effectively doubled the total rate at which Boris spawns when comparing boris kills between the 0.23 and 0.22 tournaments. This commit lowers the chance to 1/6 to bring the respawning rate closer to the previous one. --- crawl-ref/source/mon-place.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/mon-place.cc b/crawl-ref/source/mon-place.cc index fe7cb855114a..0abec6137b98 100644 --- a/crawl-ref/source/mon-place.cc +++ b/crawl-ref/source/mon-place.cc @@ -3101,7 +3101,7 @@ void replace_boris() // a new level is entered. if (!you.props["killed_boris_once"] || you.unique_creatures[MONS_BORIS] - || !one_chance_in(3)) + || !one_chance_in(6)) { return; } From d0b080c8eba84a7dfee05b3d85595fd5ce64472d Mon Sep 17 00:00:00 2001 From: gammafunk Date: Sun, 17 Feb 2019 23:41:51 -0600 Subject: [PATCH 134/864] Correct a comment --- crawl-ref/source/mon-ench.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/mon-ench.cc b/crawl-ref/source/mon-ench.cc index 802cac6eba10..6f312e94198f 100644 --- a/crawl-ref/source/mon-ench.cc +++ b/crawl-ref/source/mon-ench.cc @@ -1916,9 +1916,8 @@ void monster::mark_summoned(int longevity, bool mark_items, int summon_type, boo * aren't temporary. * * @param[out] duration The monster's summon duration in aut. - * @param[out] summon_type The monster's means of summoning. If positive, this - * is a spell_type, if negative, it's a - * mon_summon_type. + * @param[out] summon_type The monster's means of summoning. If negative, this + * is a mon_summon_type, otherwise it's a spell_type. * @returns True if the monster is a temporary summon, false otherwise. */ bool monster::is_summoned(int* duration, int* summon_type) const From ff85673007d8a9edc3f113a819d6506a8c76e704 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Wed, 27 Feb 2019 19:35:56 -0600 Subject: [PATCH 135/864] Add the changelog for 0.22.1 --- crawl-ref/docs/changelog.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/crawl-ref/docs/changelog.txt b/crawl-ref/docs/changelog.txt index 83afe95ba11a..fb6c307e958a 100644 --- a/crawl-ref/docs/changelog.txt +++ b/crawl-ref/docs/changelog.txt @@ -171,6 +171,18 @@ Spells ------ * Confusing touch works with a weapon wielded +Stone Soup 0.22.1 (20180916) +---------------------------- + +Bugfix Release +-------------- +* Support for distributing player ghosts files with releases. Now local games + will have a starting set of ghosts available for ghost vaults. +* New tiles for Azrael, shock serpents, dream sheep, mana vipers, and the Robe + of Vines. +* An additional set of Gnoll player dolls tiles. +* Fix WebTiles menus for older versions of Firefox. +* 81 bugfixes, adjustments, and cleanups in total. Stone Soup 0.22 (20180810) -------------------------- From ad582e563c65d8b1b5cab1dd416d1ef4dab11250 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Wed, 27 Feb 2019 19:41:00 -0600 Subject: [PATCH 136/864] Add Debian changelog entries for past releases Entries for bugfix releases from 0.22, 0.21, and 0.20 that are missing from the current Debian changelog. --- crawl-ref/source/debian/changelog | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/crawl-ref/source/debian/changelog b/crawl-ref/source/debian/changelog index 63da083b84fe..9f243993d15b 100644 --- a/crawl-ref/source/debian/changelog +++ b/crawl-ref/source/debian/changelog @@ -3,16 +3,36 @@ crawl (2:0.23.0-1) UNRELEASED; urgency=low * New upstream release. -- gammafunk Thu, 07 Feb 2019 10:07:00 -0600 +crawl (2:0.22.1-1) UNRELEASED; urgency=low + + * New upstream release. + -- gammafunk Sun, 16 Sep 2018 20:57:38 -0500 + crawl (2:0.22.0-1) UNRELEASED; urgency=low * New upstream release. -- gammafunk Thu, 09 Aug 2018 17:16:37 -0500 +crawl (2:0.21.2-1) UNRELEASED; urgency=low + + * New upstream release. + -- gammafunk Sun, 16 Sep 2018 16:37:58 -0500 + +crawl (2:0.21.1-1) UNRELEASED; urgency=low + + * New upstream release. + -- gammafunk Thu, 01 Feb 2018 01:54:03 -0600 + crawl (2:0.21.0-1) UNRELEASED; urgency=low * New upstream release. -- gammafunk Sat, 30 Dec 2017 19:24:18 -0600 +crawl (2:0.20.1-1) UNRELEASED; urgency=low + + * New upstream release. + -- gammafunk Sat, 01 Jul 2017 18:12:17 -0500 + crawl (2:0.20.0-1) UNRELEASED; urgency=low * New upstream release. From d96d3d62bdec8cb52410f53fa3e9d706723a3735 Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Tue, 19 Feb 2019 20:25:12 +0000 Subject: [PATCH 137/864] Fix dancing weapon description on hover (11887) Previously the dancing weapon's name was being duplicated because there weren't proper checks for dancing weapons in the second half of get_monster_equipment_desc. This was broken in f44d0c5. --- crawl-ref/source/directn.cc | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc index 626afcf7fe96..3adb4c748cb1 100644 --- a/crawl-ref/source/directn.cc +++ b/crawl-ref/source/directn.cc @@ -3297,10 +3297,7 @@ string get_monster_equipment_desc(const monster_info& mi, } } - string weap = ""; - - if (mi.type != MONS_SPECTRAL_WEAPON) - weap = _describe_monster_weapon(mi, level == DESC_IDENTIFIED); + string weap = _describe_monster_weapon(mi, level == DESC_IDENTIFIED); // Print the rest of the equipment only for full descriptions. if (level == DESC_WEAPON || level == DESC_WEAPON_WARNING) @@ -3342,8 +3339,13 @@ string get_monster_equipment_desc(const monster_info& mi, vector item_descriptions; - if (!weap.empty()) + // Dancing weapons have all their weapon information in their full_name, so + // we don't need to add another weapon description here (see Mantis 11887). + if (!weap.empty() + && mi.type != MONS_DANCING_WEAPON && mi.type != MONS_SPECTRAL_WEAPON) + { item_descriptions.push_back(weap.substr(1)); // strip leading space + } if (mon_arm) { From b31aada2703f0249d5d7a191f914c27c690bdae0 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Wed, 27 Feb 2019 19:34:05 -0600 Subject: [PATCH 138/864] Update changelogs for 0.23.1 (cherry picked from commits eed6394480af98da628bc1a7c7918dbbe1e38c16 and d6e21ad81dcba7f7f8c15336e0e985f070ce85fb) --- crawl-ref/docs/changelog.txt | 15 +++++++++++++++ crawl-ref/source/debian/changelog | 5 +++++ 2 files changed, 20 insertions(+) diff --git a/crawl-ref/docs/changelog.txt b/crawl-ref/docs/changelog.txt index fb6c307e958a..26465c94e15f 100644 --- a/crawl-ref/docs/changelog.txt +++ b/crawl-ref/docs/changelog.txt @@ -1,3 +1,18 @@ +Stone Soup 0.23.1 (20190228) +---------------------------- + +Bugfix Release +-------------- +* Vampiric attacks by the player against allies created from Sticks to Snakes + and the Ratskin Cloak no longer restore HP or give vampires satiation. +* Damage from Ozocubu's Refrigeration has been increased to the correct + amount. +* Placement for the uniques Aizul, Bai Suzhen, Donald, Jorgrun, and Mara has + been fixed so they can place throughout their intended level ranges. +* The chance of Boris to respawn has been lowered to match previous rates. +* Yellow draconians now correctly receive their rCorr mutation at XL 7. +* 45 bugfixes, adjustments, and cleanups in total. + Stone Soup 0.23 (20190207) -------------------------- diff --git a/crawl-ref/source/debian/changelog b/crawl-ref/source/debian/changelog index 9f243993d15b..456631e2bbfd 100644 --- a/crawl-ref/source/debian/changelog +++ b/crawl-ref/source/debian/changelog @@ -1,3 +1,8 @@ +crawl (2:0.23.1-1) UNRELEASED; urgency=low + + * New upstream release. + -- gammafunk Wed, 27 Feb 2019 19:44:22 -0600 + crawl (2:0.23.0-1) UNRELEASED; urgency=low * New upstream release. From eb6712d24a62ed29fb56cde67feab460f5708b8e Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 28 Feb 2019 22:22:17 -0500 Subject: [PATCH 139/864] Quiet some gcc warnings --- crawl-ref/source/ui.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index eb2fe801547d..f1269f5633d3 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -545,14 +545,14 @@ void Text::_render() { int i = 1; for (; i < (int) m_brkpts.size(); i++) - if (m_brkpts[i].line >= line_min) + if (static_cast(m_brkpts[i].line) >= line_min) { ops_min = m_brkpts[i - 1].op; line_off = m_brkpts[i - 1].line; break; } for (; i < (int)m_brkpts.size(); i++) - if (m_brkpts[i].line > line_max) + if (static_cast(m_brkpts[i].line) > line_max) { ops_max = m_brkpts[i].op; break; From caa6c10b7c1b3c1329dc47b88e9fe829e23ebe61 Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Sun, 3 Mar 2019 17:37:44 +0000 Subject: [PATCH 140/864] Let barachim use grand finale at range 8 (11917) The range of grand finale was hardcoded as 7 rather than using LOS_RADIUS, so when barachim were added, this wasn't updated. This commit changes the grand finale targeter to use targeter_smite's default parameters, which include range = LOS_RADIUS. --- crawl-ref/source/god-abil.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/god-abil.cc b/crawl-ref/source/god-abil.cc index f46e1c75cc36..305c0b3ecf1c 100644 --- a/crawl-ref/source/god-abil.cc +++ b/crawl-ref/source/god-abil.cc @@ -6674,7 +6674,7 @@ spret uskayaw_grand_finale(bool fail) args.needs_path = false; args.top_prompt = "Aiming: Grand Finale"; args.self = CONFIRM_CANCEL; - targeter_smite tgt(&you, 7, 0, 0); + targeter_smite tgt(&you); args.hitfunc = &tgt; direction(beam, args); if (crawl_state.seen_hups) From 9a4444a37bf94243a64f60b2156247d9c14f3779 Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Thu, 17 Jan 2019 12:34:38 +0000 Subject: [PATCH 141/864] Convert `enum shadow_step_block_reason` to an enum class The name of this new enum class is shadow_step_blocked. --- crawl-ref/source/target.cc | 26 +++++++++++++------------- crawl-ref/source/target.h | 16 ++++++++-------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/crawl-ref/source/target.cc b/crawl-ref/source/target.cc index c4529c555c72..8993f33a982a 100644 --- a/crawl-ref/source/target.cc +++ b/crawl-ref/source/target.cc @@ -1181,15 +1181,15 @@ bool targeter_shadow_step::valid_aim(coord_def a) { switch (no_landing_reason) { - case BLOCKED_MOVE: - case BLOCKED_OCCUPIED: + case shadow_step_blocked::move: + case shadow_step_blocked::occupied: return notify_fail("There is no safe place near that" " location."); - case BLOCKED_PATH: + case shadow_step_blocked::path: return notify_fail("There's something in the way."); - case BLOCKED_NO_TARGET: + case shadow_step_blocked::no_target: return notify_fail("There isn't a shadow there."); - case BLOCKED_NONE: + case shadow_step_blocked::none: die("buggy no_landing_reason"); } } @@ -1203,7 +1203,7 @@ bool targeter_shadow_step::valid_landing(coord_def a, bool check_invis) if (!agent->is_habitable(a)) { - blocked_landing_reason = BLOCKED_MOVE; + blocked_landing_reason = shadow_step_blocked::move; return false; } if (agent->is_player()) @@ -1211,20 +1211,20 @@ bool targeter_shadow_step::valid_landing(coord_def a, bool check_invis) monster* beholder = you.get_beholder(a); if (beholder) { - blocked_landing_reason = BLOCKED_MOVE; + blocked_landing_reason = shadow_step_blocked::move; return false; } monster* fearmonger = you.get_fearmonger(a); if (fearmonger) { - blocked_landing_reason = BLOCKED_MOVE; + blocked_landing_reason = shadow_step_blocked::move; return false; } } if (!find_ray(agent->pos(), a, ray, opc_solid_see)) { - blocked_landing_reason = BLOCKED_PATH; + blocked_landing_reason = shadow_step_blocked::path; return false; } @@ -1238,7 +1238,7 @@ bool targeter_shadow_step::valid_landing(coord_def a, bool check_invis) { if (act && (!check_invis || agent->can_see(*act))) { - blocked_landing_reason = BLOCKED_OCCUPIED; + blocked_landing_reason = shadow_step_blocked::occupied; return false; } break; @@ -1309,11 +1309,11 @@ void targeter_shadow_step::get_additional_sites(coord_def a) || !agent->can_see(*victim) || !victim->umbraed()) { - no_landing_reason = BLOCKED_NO_TARGET; + no_landing_reason = shadow_step_blocked::no_target; return; } - no_landing_reason = BLOCKED_NONE; + no_landing_reason = shadow_step_blocked::none; for (adjacent_iterator ai(a, false); ai; ++ai) { // See if site is valid, record a putative reason for why no sites were @@ -1323,7 +1323,7 @@ void targeter_shadow_step::get_additional_sites(coord_def a) if (valid_landing(*ai)) { temp_sites.insert(*ai); - no_landing_reason = BLOCKED_NONE; + no_landing_reason = shadow_step_blocked::none; } else no_landing_reason = blocked_landing_reason; diff --git a/crawl-ref/source/target.h b/crawl-ref/source/target.h index b9f8bb0a4850..30ba48af1be1 100644 --- a/crawl-ref/source/target.h +++ b/crawl-ref/source/target.h @@ -225,13 +225,13 @@ class targeter_spray : public targeter int _range; }; -enum shadow_step_block_reason +enum class shadow_step_blocked { - BLOCKED_NONE, - BLOCKED_OCCUPIED, - BLOCKED_MOVE, - BLOCKED_PATH, - BLOCKED_NO_TARGET, + none, + occupied, + move, + path, + no_target, }; class targeter_shadow_step : public targeter @@ -250,8 +250,8 @@ class targeter_shadow_step : public targeter void set_additional_sites(coord_def a); void get_additional_sites(coord_def a); bool valid_landing(coord_def a, bool check_invis = true); - shadow_step_block_reason no_landing_reason; - shadow_step_block_reason blocked_landing_reason; + shadow_step_blocked no_landing_reason; + shadow_step_blocked blocked_landing_reason; set temp_sites; int range; }; From e9c4e45a534ea341d5289c5d1bb195408c22df8c Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Thu, 17 Jan 2019 12:53:36 +0000 Subject: [PATCH 142/864] Convert `enum passage_type` to an enum class The enum class has the same name as the original enum. Also split lines in the enum class definition so that each identifier gets its own line. --- crawl-ref/source/traps.cc | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/crawl-ref/source/traps.cc b/crawl-ref/source/traps.cc index f30f4bbdd004..817519ce3524 100644 --- a/crawl-ref/source/traps.cc +++ b/crawl-ref/source/traps.cc @@ -420,9 +420,11 @@ vector find_golubria_on_level() return ret; } -enum passage_type +enum class passage_type { - PASSAGE_FREE, PASSAGE_BLOCKED, PASSAGE_NONE + free, + blocked, + none, }; static passage_type _find_other_passage_side(coord_def& to) @@ -441,9 +443,9 @@ static passage_type _find_other_passage_side(coord_def& to) } const int choices = clear_passages.size(); if (choices < 1) - return has_blocks ? PASSAGE_BLOCKED : PASSAGE_NONE; + return has_blocks ? passage_type::blocked : passage_type::none; to = clear_passages[random2(choices)]; - return PASSAGE_FREE; + return passage_type::free; } void trap_def::trigger(actor& triggerer) @@ -494,7 +496,7 @@ void trap_def::trigger(actor& triggerer) { coord_def to = p; passage_type search_result = _find_other_passage_side(to); - if (search_result == PASSAGE_FREE) + if (search_result == passage_type::free) { if (you_trigger) mpr("You enter the passage of Golubria."); @@ -511,7 +513,7 @@ void trap_def::trigger(actor& triggerer) } else if (you_trigger) { - mprf("This passage %s!", search_result == PASSAGE_BLOCKED ? + mprf("This passage %s!", search_result == passage_type::blocked ? "seems to be blocked by something" : "doesn't lead anywhere"); } break; From dcab4b91bc14e4687a84fdd0ef366088e18e1b3f Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Thu, 17 Jan 2019 14:56:41 +0000 Subject: [PATCH 143/864] Convert `enum branch_noise_level` to `enum class branch_noise` --- crawl-ref/source/branch-data.h | 86 +++++++++++++++++----------------- crawl-ref/source/branch.cc | 6 +-- crawl-ref/source/branch.h | 10 ++-- 3 files changed, 51 insertions(+), 51 deletions(-) diff --git a/crawl-ref/source/branch-data.h b/crawl-ref/source/branch-data.h index bd4835fa8994..66818dc80921 100644 --- a/crawl-ref/source/branch-data.h +++ b/crawl-ref/source/branch-data.h @@ -18,7 +18,7 @@ const Branch branches[NUM_BRANCHES] = "Dungeon", "the Dungeon", "D", nullptr, LIGHTGREY, BROWN, - 'D', {}, BRANCH_NOISE_NORMAL }, + 'D', {}, branch_noise::normal }, { BRANCH_TEMPLE, BRANCH_DUNGEON, 4, 7, 1, 5, BFLAG_NO_ITEMS, @@ -26,7 +26,7 @@ const Branch branches[NUM_BRANCHES] = "Temple", "the Ecumenical Temple", "Temple", nullptr, LIGHTGREY, BROWN, - 'T', {}, BRANCH_NOISE_NORMAL }, + 'T', {}, branch_noise::normal }, { BRANCH_ORC, BRANCH_DUNGEON, 9, 12, 2, 10, BFLAG_SPOTTY, @@ -34,7 +34,7 @@ const Branch branches[NUM_BRANCHES] = "Orcish Mines", "the Orcish Mines", "Orc", nullptr, BROWN, BROWN, - 'O', {}, BRANCH_NOISE_NORMAL }, + 'O', {}, branch_noise::normal }, { BRANCH_ELF, BRANCH_ORC, 2, 2, 3, 15, BFLAG_DANGEROUS_END, @@ -42,7 +42,7 @@ const Branch branches[NUM_BRANCHES] = "Elven Halls", "the Elven Halls", "Elf", nullptr, WHITE, ETC_ELVEN_BRICK, - 'E', {}, BRANCH_NOISE_NORMAL }, + 'E', {}, branch_noise::normal }, #if TAG_MAJOR_VERSION == 34 { BRANCH_DWARF, BRANCH_ELF, -1, -1, 0, 17, @@ -51,7 +51,7 @@ const Branch branches[NUM_BRANCHES] = "Dwarven Hall", "the Dwarven Hall", "Dwarf", nullptr, BROWN, BROWN, - 'K', {}, BRANCH_NOISE_NORMAL }, + 'K', {}, branch_noise::normal }, #endif { BRANCH_LAIR, BRANCH_DUNGEON, 8, 11, 6, 10, @@ -60,7 +60,7 @@ const Branch branches[NUM_BRANCHES] = "Lair", "the Lair of Beasts", "Lair", nullptr, GREEN, BROWN, - 'L', {}, BRANCH_NOISE_NORMAL }, + 'L', {}, branch_noise::normal }, { BRANCH_SWAMP, BRANCH_LAIR, 2, 4, 4, 15, BFLAG_DANGEROUS_END | BFLAG_SPOTTY, @@ -68,7 +68,7 @@ const Branch branches[NUM_BRANCHES] = "Swamp", "the Swamp", "Swamp", nullptr, BROWN, BROWN, - 'S', { RUNE_SWAMP }, BRANCH_NOISE_NORMAL }, + 'S', { RUNE_SWAMP }, branch_noise::normal }, { BRANCH_SHOALS, BRANCH_LAIR, 2, 4, 4, 15, BFLAG_DANGEROUS_END, @@ -76,7 +76,7 @@ const Branch branches[NUM_BRANCHES] = "Shoals", "the Shoals", "Shoals", nullptr, BROWN, BROWN, - 'A', { RUNE_SHOALS }, BRANCH_NOISE_LOUD }, + 'A', { RUNE_SHOALS }, branch_noise::loud }, { BRANCH_SNAKE, BRANCH_LAIR, 2, 4, 4, 15, BFLAG_DANGEROUS_END, @@ -84,7 +84,7 @@ const Branch branches[NUM_BRANCHES] = "Snake Pit", "the Snake Pit", "Snake", nullptr, LIGHTGREEN, YELLOW, - 'P', { RUNE_SNAKE }, BRANCH_NOISE_NORMAL }, + 'P', { RUNE_SNAKE }, branch_noise::normal }, { BRANCH_SPIDER, BRANCH_LAIR, 2, 4, 4, 15, BFLAG_DANGEROUS_END, @@ -92,7 +92,7 @@ const Branch branches[NUM_BRANCHES] = "Spider Nest", "the Spider Nest", "Spider", nullptr, BROWN, YELLOW, - 'N', { RUNE_SPIDER }, BRANCH_NOISE_NORMAL }, + 'N', { RUNE_SPIDER }, branch_noise::normal }, { BRANCH_SLIME, BRANCH_LAIR, 5, 6, 5, 17, BFLAG_NO_ITEMS | BFLAG_DANGEROUS_END | BFLAG_SPOTTY, @@ -100,7 +100,7 @@ const Branch branches[NUM_BRANCHES] = "Slime Pits", "the Pits of Slime", "Slime", nullptr, GREEN, BROWN, - 'M', { RUNE_SLIME }, BRANCH_NOISE_QUIET }, + 'M', { RUNE_SLIME }, branch_noise::quiet }, { BRANCH_VAULTS, BRANCH_DUNGEON, 13, 14, 5, 19, BFLAG_DANGEROUS_END, @@ -108,7 +108,7 @@ const Branch branches[NUM_BRANCHES] = "Vaults", "the Vaults", "Vaults", nullptr, LIGHTGREY, BROWN, - 'V', { RUNE_VAULTS }, BRANCH_NOISE_NORMAL }, + 'V', { RUNE_VAULTS }, branch_noise::normal }, #if TAG_MAJOR_VERSION == 34 { BRANCH_BLADE, BRANCH_VAULTS, 3, 4, 1, 21, @@ -117,7 +117,7 @@ const Branch branches[NUM_BRANCHES] = "Hall of Blades", "the Hall of Blades", "Blade", nullptr, LIGHTGREY, BROWN, - 'B', {}, BRANCH_NOISE_QUIET }, + 'B', {}, branch_noise::quiet }, #endif { BRANCH_CRYPT, BRANCH_VAULTS, 2, 3, 3, 19, @@ -126,7 +126,7 @@ const Branch branches[NUM_BRANCHES] = "Crypt", "the Crypt", "Crypt", nullptr, LIGHTGREY, BROWN, - 'C', {}, BRANCH_NOISE_QUIET }, + 'C', {}, branch_noise::quiet }, { BRANCH_TOMB, BRANCH_CRYPT, 3, 3, 3, 21, BFLAG_ISLANDED | BFLAG_DANGEROUS_END | BFLAG_NO_SHAFTS, @@ -134,7 +134,7 @@ const Branch branches[NUM_BRANCHES] = "Tomb", "the Tomb of the Ancients", "Tomb", nullptr, BROWN, BROWN, - 'W', { RUNE_TOMB }, BRANCH_NOISE_QUIET }, + 'W', { RUNE_TOMB }, branch_noise::quiet }, #if TAG_MAJOR_VERSION > 34 { BRANCH_DEPTHS, BRANCH_DUNGEON, 15, 15, 5, 22, @@ -143,7 +143,7 @@ const Branch branches[NUM_BRANCHES] = "Depths", "the Depths", "Depths", nullptr, LIGHTGREY, BROWN, - 'U', {}, BRANCH_NOISE_NORMAL }, + 'U', {}, branch_noise::normal }, #endif { BRANCH_VESTIBULE, NUM_BRANCHES, 27, 27, 1, 27, @@ -152,7 +152,7 @@ const Branch branches[NUM_BRANCHES] = "Hell", "the Vestibule of Hell", "Hell", "Welcome to Hell!\nPlease enjoy your stay.", LIGHTGREY, LIGHTRED, - 'H', {}, BRANCH_NOISE_NORMAL }, + 'H', {}, branch_noise::normal }, { BRANCH_DIS, BRANCH_VESTIBULE, 1, 1, 7, 28, BFLAG_NO_ITEMS | BFLAG_DANGEROUS_END, @@ -160,7 +160,7 @@ const Branch branches[NUM_BRANCHES] = "Dis", "the Iron City of Dis", "Dis", nullptr, CYAN, BROWN, - 'I', { RUNE_DIS }, BRANCH_NOISE_NORMAL }, + 'I', { RUNE_DIS }, branch_noise::normal }, { BRANCH_GEHENNA, BRANCH_VESTIBULE, 1, 1, 7, 28, BFLAG_NO_ITEMS | BFLAG_DANGEROUS_END, @@ -168,7 +168,7 @@ const Branch branches[NUM_BRANCHES] = "Gehenna", "Gehenna", "Geh", nullptr, BROWN, RED, - 'G', { RUNE_GEHENNA }, BRANCH_NOISE_NORMAL }, + 'G', { RUNE_GEHENNA }, branch_noise::normal }, { BRANCH_COCYTUS, BRANCH_VESTIBULE, 1, 1, 7, 28, BFLAG_NO_ITEMS | BFLAG_DANGEROUS_END, @@ -176,7 +176,7 @@ const Branch branches[NUM_BRANCHES] = "Cocytus", "Cocytus", "Coc", nullptr, LIGHTBLUE, LIGHTCYAN, - 'X', { RUNE_COCYTUS }, BRANCH_NOISE_NORMAL }, + 'X', { RUNE_COCYTUS }, branch_noise::normal }, { BRANCH_TARTARUS, BRANCH_VESTIBULE, 1, 1, 7, 28, BFLAG_NO_ITEMS | BFLAG_DANGEROUS_END, @@ -184,7 +184,7 @@ const Branch branches[NUM_BRANCHES] = "Tartarus", "Tartarus", "Tar", nullptr, MAGENTA, MAGENTA, - 'Y', { RUNE_TARTARUS }, BRANCH_NOISE_NORMAL }, + 'Y', { RUNE_TARTARUS }, branch_noise::normal }, { BRANCH_ZOT, BRANCH_DEPTHS, 5, 5, 5, 27, BFLAG_DANGEROUS_END, @@ -193,7 +193,7 @@ const Branch branches[NUM_BRANCHES] = "Welcome to the Realm of Zot!\n" "You feel the power of the Orb interfering with translocations here.", BLACK, BLACK, // set per-map - 'Z', {}, BRANCH_NOISE_NORMAL }, + 'Z', {}, branch_noise::normal }, #if TAG_MAJOR_VERSION == 34 { BRANCH_FOREST, BRANCH_VAULTS, 2, 3, 5, 19, @@ -202,7 +202,7 @@ const Branch branches[NUM_BRANCHES] = "Forest", "the Enchanted Forest", "Forest", nullptr, BROWN, BROWN, - 'F', {}, BRANCH_NOISE_NORMAL }, + 'F', {}, branch_noise::normal }, #endif { BRANCH_ABYSS, NUM_BRANCHES, -1, -1, 5, 24, @@ -211,7 +211,7 @@ const Branch branches[NUM_BRANCHES] = "Abyss", "the Abyss", "Abyss", nullptr, BLACK, BLACK, // set specially - 'J', { RUNE_ABYSSAL }, BRANCH_NOISE_NORMAL }, + 'J', { RUNE_ABYSSAL }, branch_noise::normal }, { BRANCH_PANDEMONIUM, NUM_BRANCHES, -1, -1, 1, 24, BFLAG_NO_XLEV_TRAVEL, @@ -221,7 +221,7 @@ const Branch branches[NUM_BRANCHES] = "To return, you must find a gate leading back.", BLACK, BLACK, // set specially 'R', { RUNE_DEMONIC, RUNE_MNOLEG, RUNE_LOM_LOBON, RUNE_CEREBOV, - RUNE_GLOORX_VLOQ }, BRANCH_NOISE_NORMAL }, + RUNE_GLOORX_VLOQ }, branch_noise::normal }, { BRANCH_ZIGGURAT, BRANCH_DEPTHS, 1, 5, 27, 27, BFLAG_NO_XLEV_TRAVEL | BFLAG_NO_ITEMS, @@ -229,7 +229,7 @@ const Branch branches[NUM_BRANCHES] = "Ziggurat", "a ziggurat", "Zig", "You land on top of a ziggurat so tall you cannot make out the ground.", BLACK, BLACK, - 'Q', {}, BRANCH_NOISE_NORMAL }, + 'Q', {}, branch_noise::normal }, #if TAG_MAJOR_VERSION == 34 { BRANCH_LABYRINTH, NUM_BRANCHES, -1, -1, 1, 15, @@ -238,7 +238,7 @@ const Branch branches[NUM_BRANCHES] = "Labyrinth", "a Labyrinth", "Lab", "You enter a labyrinth!", BLACK, BLACK, - '0', {}, BRANCH_NOISE_NORMAL }, + '0', {}, branch_noise::normal }, #endif { BRANCH_BAZAAR, NUM_BRANCHES, -1, -1, 1, 18, @@ -247,7 +247,7 @@ const Branch branches[NUM_BRANCHES] = "Bazaar", "a bazaar", "Bazaar", "You enter an inter-dimensional bazaar!", BLUE, YELLOW, - '1', {}, BRANCH_NOISE_NORMAL }, + '1', {}, branch_noise::normal }, { BRANCH_TROVE, NUM_BRANCHES, -1, -1, 1, 18, BFLAG_NO_XLEV_TRAVEL | BFLAG_NO_ITEMS, @@ -255,7 +255,7 @@ const Branch branches[NUM_BRANCHES] = "Trove", "a treasure trove", "Trove", "You enter a treasure trove!", DARKGREY, BLUE, - '2', {}, BRANCH_NOISE_NORMAL }, + '2', {}, branch_noise::normal }, { BRANCH_SEWER, NUM_BRANCHES, -1, -1, 1, 4, BFLAG_NO_XLEV_TRAVEL | BFLAG_NO_ITEMS, @@ -263,7 +263,7 @@ const Branch branches[NUM_BRANCHES] = "Sewer", "a sewer", "Sewer", "You enter a sewer!", LIGHTGREY, BLUE, - '3', {}, BRANCH_NOISE_NORMAL }, + '3', {}, branch_noise::normal }, { BRANCH_OSSUARY, NUM_BRANCHES, -1, -1, 1, 6, BFLAG_NO_XLEV_TRAVEL | BFLAG_NO_ITEMS, @@ -271,7 +271,7 @@ const Branch branches[NUM_BRANCHES] = "Ossuary", "an ossuary", "Ossuary", "You enter an ossuary!", WHITE, YELLOW, - '4', {}, BRANCH_NOISE_NORMAL }, + '4', {}, branch_noise::normal }, { BRANCH_BAILEY, NUM_BRANCHES, -1, -1, 1, 11, BFLAG_NO_XLEV_TRAVEL | BFLAG_NO_ITEMS, @@ -279,7 +279,7 @@ const Branch branches[NUM_BRANCHES] = "Bailey", "a bailey", "Bailey", "You enter a bailey!", WHITE, LIGHTRED, - '5', {}, BRANCH_NOISE_NORMAL }, + '5', {}, branch_noise::normal }, #if TAG_MAJOR_VERSION > 34 { BRANCH_GAUNTLET, NUM_BRANCHES, -1, -1, 1, 15, @@ -288,7 +288,7 @@ const Branch branches[NUM_BRANCHES] = "Gauntlet", "a Gauntlet", "Gauntlet", "You enter a gauntlet!", BLACK, BLACK, - '6', {}, BRANCH_NOISE_NORMAL }, + '6', {}, branch_noise::normal }, #endif { BRANCH_ICE_CAVE, NUM_BRANCHES, -1, -1, 1, 15, @@ -298,10 +298,10 @@ const Branch branches[NUM_BRANCHES] = "You enter an ice cave!", BLUE, WHITE, #if TAG_MAJOR_VERSION == 34 - '6', {}, BRANCH_NOISE_NORMAL }, + '6', {}, branch_noise::normal }, #endif #if TAG_MAJOR_VERSION > 34 - '7', {}, BRANCH_NOISE_NORMAL }, + '7', {}, branch_noise::normal }, #endif { BRANCH_VOLCANO, NUM_BRANCHES, -1, -1, 1, 14, @@ -311,10 +311,10 @@ const Branch branches[NUM_BRANCHES] = "You enter a volcano!", RED, RED, #if TAG_MAJOR_VERSION == 34 - '7', {}, BRANCH_NOISE_NORMAL }, + '7', {}, branch_noise::normal }, #endif #if TAG_MAJOR_VERSION > 34 - '8', {}, BRANCH_NOISE_NORMAL }, + '8', {}, branch_noise::normal }, #endif { BRANCH_WIZLAB, NUM_BRANCHES, -1, -1, 1, 24, @@ -324,10 +324,10 @@ const Branch branches[NUM_BRANCHES] = "You enter a wizard's laboratory!", LIGHTGREY, BROWN, // set per-map #if TAG_MAJOR_VERSION == 34 - '8', {}, BRANCH_NOISE_NORMAL }, + '8', {}, branch_noise::normal }, #endif #if TAG_MAJOR_VERSION > 34 - '9', {}, BRANCH_NOISE_NORMAL }, + '9', {}, branch_noise::normal }, #endif #if TAG_MAJOR_VERSION == 34 @@ -337,7 +337,7 @@ const Branch branches[NUM_BRANCHES] = "Depths", "the Depths", "Depths", nullptr, LIGHTGREY, BROWN, - 'U', {}, BRANCH_NOISE_NORMAL }, + 'U', {}, branch_noise::normal }, #endif { BRANCH_DESOLATION, NUM_BRANCHES, -1, -1, 1, 20, @@ -347,10 +347,10 @@ const Branch branches[NUM_BRANCHES] = "You enter a great desolation of salt!", LIGHTGREY, BROWN, // TODO #if TAG_MAJOR_VERSION == 34 - '9', {}, BRANCH_NOISE_LOUD }, + '9', {}, branch_noise::loud }, #endif #if TAG_MAJOR_VERSION > 34 - '0', {}, BRANCH_NOISE_LOUD }, + '0', {}, branch_noise::loud }, #endif #if TAG_MAJOR_VERSION == 34 @@ -360,6 +360,6 @@ const Branch branches[NUM_BRANCHES] = "Gauntlet", "a Gauntlet", "Gauntlet", "You enter a gauntlet!", BLACK, BLACK, - '!', {}, BRANCH_NOISE_NORMAL }, + '!', {}, branch_noise::normal }, #endif }; diff --git a/crawl-ref/source/branch.cc b/crawl-ref/source/branch.cc index 842f058d2d08..eb69dab97c36 100644 --- a/crawl-ref/source/branch.cc +++ b/crawl-ref/source/branch.cc @@ -224,11 +224,11 @@ int ambient_noise(branch_type branch) { switch (branches[branch].ambient_noise) { - case BRANCH_NOISE_NORMAL: + case branch_noise::normal: return 0; - case BRANCH_NOISE_QUIET: + case branch_noise::quiet: return -BRANCH_NOISE_AMOUNT; - case BRANCH_NOISE_LOUD: + case branch_noise::loud: return BRANCH_NOISE_AMOUNT; default: die("Invalid noise level!"); diff --git a/crawl-ref/source/branch.h b/crawl-ref/source/branch.h index 5998f25a7983..46c2af279d3f 100644 --- a/crawl-ref/source/branch.h +++ b/crawl-ref/source/branch.h @@ -25,11 +25,11 @@ enum branch_flag_type BFLAG_NO_SHAFTS = (1 << 6), // Don't generate random shafts. }; -enum branch_noise_level +enum class branch_noise { - BRANCH_NOISE_NORMAL, - BRANCH_NOISE_QUIET, - BRANCH_NOISE_LOUD, + normal, + quiet, + loud, }; struct Branch @@ -56,7 +56,7 @@ struct Branch colour_t rock_colour; int travel_shortcut; // Which key to press for travel. vector runes; // Contained rune(s) (if any). - branch_noise_level ambient_noise; // affects noise loudness + branch_noise ambient_noise; // affects noise loudness }; enum branch_iterator_type From 0e0ca4a038d49e57aa83d9e1f4282101bc57a95f Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Thu, 17 Jan 2019 15:04:32 +0000 Subject: [PATCH 144/864] Convert `enum branch_iterator_type` to an enum class The enum class retains the same name. --- crawl-ref/source/branch.cc | 2 +- crawl-ref/source/branch.h | 8 ++++---- crawl-ref/source/item-name.cc | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crawl-ref/source/branch.cc b/crawl-ref/source/branch.cc index eb69dab97c36..0c4817f90a05 100644 --- a/crawl-ref/source/branch.cc +++ b/crawl-ref/source/branch.cc @@ -112,7 +112,7 @@ branch_iterator::branch_iterator(branch_iterator_type type) : const branch_type* branch_iterator::branch_order() const { - if (iter_type == BRANCH_ITER_DANGER) + if (iter_type == branch_iterator_type::danger) return danger_branch_order; return logical_branch_order; } diff --git a/crawl-ref/source/branch.h b/crawl-ref/source/branch.h index 46c2af279d3f..cc2474d2d5d7 100644 --- a/crawl-ref/source/branch.h +++ b/crawl-ref/source/branch.h @@ -59,16 +59,16 @@ struct Branch branch_noise ambient_noise; // affects noise loudness }; -enum branch_iterator_type +enum class branch_iterator_type { - BRANCH_ITER_LOGICAL, - BRANCH_ITER_DANGER, + logical, + danger, }; class branch_iterator { public: - branch_iterator(branch_iterator_type type = BRANCH_ITER_LOGICAL); + branch_iterator(branch_iterator_type type = branch_iterator_type::logical); operator bool() const; const Branch* operator*() const; diff --git a/crawl-ref/source/item-name.cc b/crawl-ref/source/item-name.cc index cff226849b3e..bda000f1dec1 100644 --- a/crawl-ref/source/item-name.cc +++ b/crawl-ref/source/item-name.cc @@ -2657,7 +2657,7 @@ void display_runes() if (!crawl_state.game_is_sprint()) { // Add the runes in order of challenge (semi-arbitrary). - for (branch_iterator it(BRANCH_ITER_DANGER); it; ++it) + for (branch_iterator it(branch_iterator_type::danger); it; ++it) { const branch_type br = it->id; if (!connected_branch_can_exist(br)) From c27245e1b52ffd9bb7d6f7120b497ed002e799a3 Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Thu, 17 Jan 2019 15:31:30 +0000 Subject: [PATCH 145/864] Convert `enum menu_type` to an enum class --- crawl-ref/source/adjust.cc | 5 +++-- crawl-ref/source/butcher.cc | 2 +- crawl-ref/source/directn.cc | 3 ++- crawl-ref/source/evoke.cc | 4 ++-- crawl-ref/source/externs.h | 2 +- crawl-ref/source/god-abil.cc | 8 +++++--- crawl-ref/source/initfile.cc | 16 ++++++++-------- crawl-ref/source/invent.cc | 23 ++++++++++++----------- crawl-ref/source/invent.h | 2 +- crawl-ref/source/item-name.cc | 2 +- crawl-ref/source/item-use.cc | 20 +++++++++++--------- crawl-ref/source/items.cc | 2 +- crawl-ref/source/menu-type.h | 14 +++++++------- crawl-ref/source/quiver.cc | 4 ++-- crawl-ref/source/spl-goditem.cc | 5 +++-- crawl-ref/source/throw.cc | 2 +- crawl-ref/source/tilereg-dgn.cc | 2 +- crawl-ref/source/wiz-item.cc | 12 +++++++----- crawl-ref/source/wiz-mon.cc | 2 +- 19 files changed, 70 insertions(+), 60 deletions(-) diff --git a/crawl-ref/source/adjust.cc b/crawl-ref/source/adjust.cc index 727f6db4ddbe..0018a4331a5e 100644 --- a/crawl-ref/source/adjust.cc +++ b/crawl-ref/source/adjust.cc @@ -51,7 +51,8 @@ void adjust_item(int from_slot) if (from_slot == -1) { - from_slot = prompt_invent_item("Adjust which item?", MT_INVLIST, -1); + from_slot = prompt_invent_item("Adjust which item?", + menu_type::invlist, -1); if (prompt_failed(from_slot)) return; @@ -59,7 +60,7 @@ void adjust_item(int from_slot) } const int to_slot = prompt_invent_item("Adjust to which letter? ", - MT_INVLIST, + menu_type::invlist, -1, OPER_ANY, invprompt_flag::unthings_ok | invprompt_flag::manual_list); diff --git a/crawl-ref/source/butcher.cc b/crawl-ref/source/butcher.cc index 84ff776447c8..fb645c47bed3 100644 --- a/crawl-ref/source/butcher.cc +++ b/crawl-ref/source/butcher.cc @@ -226,7 +226,7 @@ void butchery(item_def* specific_corpse) vector selected = select_items(meat, bottle_blood ? "Choose a corpse to bottle" : "Choose a corpse to butcher", - false, MT_ANY, _butcher_menu_title); + false, menu_type::any, _butcher_menu_title); redraw_screen(); for (SelItem sel : selected) if (_start_butchering(const_cast(*sel.item))) diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc index 3adb4c748cb1..a93abc33544b 100644 --- a/crawl-ref/source/directn.cc +++ b/crawl-ref/source/directn.cc @@ -627,7 +627,8 @@ void full_describe_view() desc_menu.set_title(new MenuEntry(title1, MEL_TITLE)); desc_menu.set_tag("pickup"); - desc_menu.set_type(MT_PICKUP); // necessary for sorting of the item submenu + // necessary for sorting of the item submenu + desc_menu.set_type(menu_type::pickup); desc_menu.action_cycle = Menu::CYCLE_TOGGLE; desc_menu.menu_action = InvMenu::ACT_EXECUTE; diff --git a/crawl-ref/source/evoke.cc b/crawl-ref/source/evoke.cc index 8fd56f67e143..cf90fb572bef 100644 --- a/crawl-ref/source/evoke.cc +++ b/crawl-ref/source/evoke.cc @@ -426,7 +426,7 @@ void zap_wand(int slot) else { item_slot = prompt_invent_item("Zap which item?", - MT_INVLIST, + menu_type::invlist, OBJ_WANDS, OPER_ZAP); } @@ -1480,7 +1480,7 @@ bool evoke_item(int slot, bool check_range) if (slot == -1) { slot = prompt_invent_item("Evoke which item? (* to show all)", - MT_INVLIST, + menu_type::invlist, OSEL_EVOKABLE, OPER_EVOKE); if (prompt_failed(slot)) diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h index 24cd1c8f57ba..e7cecc7a3c4b 100644 --- a/crawl-ref/source/externs.h +++ b/crawl-ref/source/externs.h @@ -874,7 +874,7 @@ struct menu_sort_condition item_sort_comparators cmp; public: - menu_sort_condition(menu_type mt = MT_INVLIST, int sort = 0); + menu_sort_condition(menu_type mt = menu_type::invlist, int sort = 0); menu_sort_condition(const string &s); bool matches(menu_type mt) const; diff --git a/crawl-ref/source/god-abil.cc b/crawl-ref/source/god-abil.cc index 305c0b3ecf1c..5f4f0f3d99e5 100644 --- a/crawl-ref/source/god-abil.cc +++ b/crawl-ref/source/god-abil.cc @@ -136,7 +136,8 @@ bool bless_weapon(god_type god, brand_type brand, colour_t colour) { ASSERT(can_do_capstone_ability(god)); - int item_slot = prompt_invent_item("Brand which weapon?", MT_INVLIST, + int item_slot = prompt_invent_item("Brand which weapon?", + menu_type::invlist, OSEL_BLESSABLE_WEAPON, OPER_ANY, invprompt_flag::escape_only); @@ -1583,7 +1584,7 @@ bool beogh_gift_item() return false; int item_slot = prompt_invent_item("Give which item?", - MT_INVLIST, OSEL_BEOGH_GIFT); + menu_type::invlist, OSEL_BEOGH_GIFT); if (item_slot == PROMPT_ABORT || item_slot == PROMPT_NOTHING) { @@ -3739,7 +3740,8 @@ bool ashenzari_curse_item(int num_rc) "Curse which item? (%d remove curse scroll%s left)" " (Esc to abort)", num_rc, num_rc == 1 ? "" : "s"); - const int item_slot = prompt_invent_item(prompt_msg.c_str(), MT_INVLIST, + const int item_slot = prompt_invent_item(prompt_msg.c_str(), + menu_type::invlist, OSEL_CURSABLE, OPER_ANY, invprompt_flag::escape_only); if (prompt_failed(item_slot)) diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index f4f8343e86d1..d98d5c819ead 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -2305,7 +2305,7 @@ void game_options::set_menu_sort(string field) menu_sort_condition cond(field); // Overrides all previous settings. - if (cond.mtype == MT_ANY) + if (cond.mtype == menu_type::any) sort_menus.clear(); // Override existing values, if necessary. @@ -5060,7 +5060,7 @@ menu_sort_condition::menu_sort_condition(menu_type _mt, int _sort) } menu_sort_condition::menu_sort_condition(const string &s) - : mtype(MT_ANY), sort(-1), cmp() + : mtype(menu_type::any), sort(-1), cmp() { string cp = s; set_menu_type(cp); @@ -5070,7 +5070,7 @@ menu_sort_condition::menu_sort_condition(const string &s) bool menu_sort_condition::matches(menu_type mt) const { - return mtype == MT_ANY || mtype == mt; + return mtype == menu_type::any || mtype == mt; } void menu_sort_condition::set_menu_type(string &s) @@ -5081,11 +5081,11 @@ void menu_sort_condition::set_menu_type(string &s) menu_type mtype; } menu_type_map[] = { - { "any:", MT_ANY }, - { "inv:", MT_INVLIST }, - { "drop:", MT_DROP }, - { "pickup:", MT_PICKUP }, - { "know:", MT_KNOW } + { "any:", menu_type::any }, + { "inv:", menu_type::invlist }, + { "drop:", menu_type::drop }, + { "pickup:", menu_type::pickup }, + { "know:", menu_type::know } }; for (const auto &mi : menu_type_map) diff --git a/crawl-ref/source/invent.cc b/crawl-ref/source/invent.cc index 4f7716524fad..a8a385b4bb7d 100644 --- a/crawl-ref/source/invent.cc +++ b/crawl-ref/source/invent.cc @@ -306,7 +306,7 @@ void InvEntry::set_show_glyph(bool doshow) } InvMenu::InvMenu(int mflags) - : Menu(mflags, "inventory"), type(MT_INVLIST), pre_select(nullptr), + : Menu(mflags, "inventory"), type(menu_type::invlist), pre_select(nullptr), title_annotate(nullptr) { #ifdef USE_TILE_LOCAL @@ -573,7 +573,7 @@ bool InvEntry::get_tiles(vector& tileset) const { return false; } bool InvMenu::is_selectable(int index) const { - if (type == MT_DROP) + if (type == menu_type::drop) { InvEntry *item = dynamic_cast(items[index]); if (item->is_cursed() && item->is_equipped()) @@ -885,13 +885,14 @@ vector InvMenu::get_selitems() const string InvMenu::help_key() const { - return type == MT_DROP || type == MT_PICKUP ? "pick-up" : ""; + return type == menu_type::drop || type == menu_type::pickup ? "pick-up" + : ""; } int InvMenu::getkey() const { auto mkey = lastch; - if (type == MT_KNOW && (mkey == 0 || mkey == CK_ENTER)) + if (type == menu_type::know && (mkey == 0 || mkey == CK_ENTER)) return mkey; if (!isaalnum(mkey) && mkey != '$' && mkey != '-' && mkey != '?' @@ -973,14 +974,14 @@ vector select_items(const vector &items, InvMenu menu; menu.set_type(mtype); menu.set_title(title); - if (mtype == MT_PICKUP) + if (mtype == menu_type::pickup) menu.set_tag("pickup"); menu.load_items(items); int new_flags = noselect ? MF_NOSELECT : MF_MULTISELECT | MF_ALLOW_FILTER; - if (mtype == MT_SELONE) + if (mtype == menu_type::sel_one) { new_flags |= MF_SINGLESELECT; new_flags &= ~MF_MULTISELECT; @@ -1138,9 +1139,9 @@ bool any_items_of_type(int selector, int excluded_slot, bool inspect_floor) } // Use title = nullptr for stock Inventory title -// type = MT_DROP allows the multidrop toggle +// type = menu_type::drop allows the multidrop toggle static unsigned char _invent_select(const char *title = nullptr, - menu_type type = MT_INVLIST, + menu_type type = menu_type::invlist, int item_selector = OSEL_ANY, int excluded_slot = -1, int flags = MF_NOSELECT, @@ -1176,7 +1177,7 @@ void display_inventory() { InvMenu menu(MF_SINGLESELECT | MF_ALLOW_FORMATTING); menu.load_inv_items(OSEL_ANY, -1); - menu.set_type(MT_INVLIST); + menu.set_type(menu_type::invlist); menu.on_single_selection = [](const MenuEntry& item) { @@ -1295,7 +1296,7 @@ vector prompt_drop_items(const vector &preselected_items) { // The "view inventory listing" mode. const int ch = _invent_select(prompt.c_str(), - MT_DROP, + menu_type::drop, OSEL_ANY, -1, MF_MULTISELECT | MF_ALLOW_FILTER, @@ -1806,7 +1807,7 @@ int prompt_invent_item(const char *prompt, if (!any_items_of_type(type_expect) && type_expect == OSEL_THROWABLE && (oper == OPER_FIRE || oper == OPER_QUIVER) - && mtype == MT_INVLIST) + && mtype == menu_type::invlist) { type_expect = OSEL_ANY; } diff --git a/crawl-ref/source/invent.h b/crawl-ref/source/invent.h index 52b17c281e43..9f204eca25d3 100644 --- a/crawl-ref/source/invent.h +++ b/crawl-ref/source/invent.h @@ -225,7 +225,7 @@ int prompt_invent_item(const char *prompt, vector select_items( const vector &items, const char *title, bool noselect = false, - menu_type mtype = MT_PICKUP, + menu_type mtype = menu_type::pickup, invtitle_annotator titlefn = nullptr); vector prompt_drop_items(const vector &preselected_items); diff --git a/crawl-ref/source/item-name.cc b/crawl-ref/source/item-name.cc index bda000f1dec1..44e4d9f8f432 100644 --- a/crawl-ref/source/item-name.cc +++ b/crawl-ref/source/item-name.cc @@ -2566,7 +2566,7 @@ void check_item_knowledge(bool unknown_items) menu.set_flags( MF_QUIET_SELECT | MF_ALLOW_FORMATTING | MF_USE_TWO_COLUMNS | ((unknown_items) ? MF_NOSELECT : MF_MULTISELECT | MF_ALLOW_FILTER)); - menu.set_type(MT_KNOW); + menu.set_type(menu_type::know); menu_letter ml; ml = menu.load_items(items, unknown_items ? unknown_item_mangle : known_item_mangle, 'a', false); diff --git a/crawl-ref/source/item-use.cc b/crawl-ref/source/item-use.cc index ad0325039ae4..b065477205d9 100644 --- a/crawl-ref/source/item-use.cc +++ b/crawl-ref/source/item-use.cc @@ -477,7 +477,7 @@ bool wield_weapon(bool auto_wield, int slot, bool show_weff_messages, { item_slot = prompt_invent_item( "Wield which item (- for none, * to show all)?", - MT_INVLIST, OSEL_WIELD, + menu_type::invlist, OSEL_WIELD, OPER_WIELD, invprompt_flag::no_warning, '-'); } else @@ -648,7 +648,8 @@ bool armour_prompt(const string & mesg, int *index, operation_types oper) int selector = OBJ_ARMOUR; if (oper == OPER_TAKEOFF && !Options.equip_unequip) selector = OSEL_WORN_ARMOUR; - int slot = prompt_invent_item(mesg.c_str(), MT_INVLIST, selector, oper); + int slot = prompt_invent_item(mesg.c_str(), menu_type::invlist, + selector, oper); if (!prompt_failed(slot)) { @@ -1027,8 +1028,9 @@ bool wear_armour(int item) if (item == -1) { - item = prompt_invent_item("Wear which item?", MT_INVLIST, OBJ_ARMOUR, - OPER_WEAR, invprompt_flag::no_warning); + item = prompt_invent_item("Wear which item?", menu_type::invlist, + OBJ_ARMOUR, OPER_WEAR, + invprompt_flag::no_warning); if (prompt_failed(item)) return false; } @@ -1548,7 +1550,7 @@ static bool _swap_rings(int ring_slot) // message is visible. unwanted = prompt_invent_item( "You're wearing all the rings you can. Remove which one?", - MT_INVLIST, OSEL_UNCURSED_WORN_RINGS, OPER_REMOVE, + menu_type::invlist, OSEL_UNCURSED_WORN_RINGS, OPER_REMOVE, invprompt_flag::no_warning | invprompt_flag::hide_known); } @@ -1857,8 +1859,8 @@ bool puton_ring(int slot, bool allow_prompt, bool check_for_inscriptions) else { item_slot = prompt_invent_item("Put on which piece of jewellery?", - MT_INVLIST, OBJ_JEWELLERY, OPER_PUTON, - invprompt_flag::no_warning); + menu_type::invlist, OBJ_JEWELLERY, + OPER_PUTON, invprompt_flag::no_warning); } if (prompt_failed(item_slot)) @@ -1919,7 +1921,7 @@ bool remove_ring(int slot, bool announce) { const int equipn = (slot == -1)? prompt_invent_item("Remove which piece of jewellery?", - MT_INVLIST, + menu_type::invlist, OBJ_JEWELLERY, OPER_REMOVE, invprompt_flag::no_warning @@ -2020,7 +2022,7 @@ void prompt_inscribe_item() } int item_slot = prompt_invent_item("Inscribe which item?", - MT_INVLIST, OSEL_ANY); + menu_type::invlist, OSEL_ANY); if (prompt_failed(item_slot)) return; diff --git a/crawl-ref/source/items.cc b/crawl-ref/source/items.cc index a09d5e31e212..1f46d35f37ed 100644 --- a/crawl-ref/source/items.cc +++ b/crawl-ref/source/items.cc @@ -996,7 +996,7 @@ void pickup_menu(int item_link) if (items.size() == 1 && items[0]->quantity > 1) prompt = "Select pick up quantity by entering a number, then select the item"; vector selected = select_items(items, prompt.c_str(), false, - MT_PICKUP); + menu_type::pickup); if (selected.empty()) canned_msg(MSG_OK); redraw_screen(); diff --git a/crawl-ref/source/menu-type.h b/crawl-ref/source/menu-type.h index 29fefc577578..e2bd4b282359 100644 --- a/crawl-ref/source/menu-type.h +++ b/crawl-ref/source/menu-type.h @@ -1,12 +1,12 @@ #pragma once -enum menu_type +enum class menu_type { - MT_ANY = -1, + any = -1, - MT_INVLIST, // List inventory - MT_DROP, - MT_PICKUP, - MT_KNOW, - MT_SELONE, // Select one + invlist, // List inventory + drop, + pickup, + know, + sel_one, // Select one }; diff --git a/crawl-ref/source/quiver.cc b/crawl-ref/source/quiver.cc index 66e15b733836..4d529b92fa19 100644 --- a/crawl-ref/source/quiver.cc +++ b/crawl-ref/source/quiver.cc @@ -181,8 +181,8 @@ void choose_item_for_quiver() } int slot = prompt_invent_item("Quiver which item? (- for none, * to show all)", - MT_INVLIST, OSEL_THROWABLE, OPER_QUIVER, - invprompt_flag::hide_known, '-'); + menu_type::invlist, OSEL_THROWABLE, + OPER_QUIVER, invprompt_flag::hide_known, '-'); if (prompt_failed(slot)) return; diff --git a/crawl-ref/source/spl-goditem.cc b/crawl-ref/source/spl-goditem.cc index afc82ec2f558..0ccaf0b5dea9 100644 --- a/crawl-ref/source/spl-goditem.cc +++ b/crawl-ref/source/spl-goditem.cc @@ -660,7 +660,8 @@ static bool _selectively_remove_curse(const string &pre_msg) return used; } - int item_slot = prompt_invent_item("Uncurse which item?", MT_INVLIST, + int item_slot = prompt_invent_item("Uncurse which item?", + menu_type::invlist, OSEL_CURSED_WORN, OPER_ANY, invprompt_flag::escape_only); if (prompt_failed(item_slot)) @@ -738,7 +739,7 @@ static bool _selectively_curse_item(bool armour, const string &pre_msg) { while (1) { - int item_slot = prompt_invent_item("Curse which item?", MT_INVLIST, + int item_slot = prompt_invent_item("Curse which item?", menu_type::invlist, armour ? OSEL_UNCURSED_WORN_ARMOUR : OSEL_UNCURSED_WORN_JEWELLERY, OPER_ANY, invprompt_flag::escape_only); diff --git a/crawl-ref/source/throw.cc b/crawl-ref/source/throw.cc index 77144bd1f0ca..1eb8f087b404 100644 --- a/crawl-ref/source/throw.cc +++ b/crawl-ref/source/throw.cc @@ -420,7 +420,7 @@ static int _fire_prompt_for_item() return -1; int slot = prompt_invent_item("Fire/throw which item? (* to show all)", - MT_INVLIST, + menu_type::invlist, OSEL_THROWABLE, OPER_FIRE); if (slot == PROMPT_ABORT || slot == PROMPT_NOTHING) diff --git a/crawl-ref/source/tilereg-dgn.cc b/crawl-ref/source/tilereg-dgn.cc index 221122e1bef3..e4725be0adf6 100644 --- a/crawl-ref/source/tilereg-dgn.cc +++ b/crawl-ref/source/tilereg-dgn.cc @@ -482,7 +482,7 @@ static item_def* _get_evokable_item(const actor* target) InvMenu menu(MF_SINGLESELECT | MF_ANYPRINTABLE | MF_ALLOW_FORMATTING | MF_SELECT_BY_PAGE); - menu.set_type(MT_ANY); + menu.set_type(menu_type::any); menu.set_title("Wand to zap?"); menu.load_items(list); menu.show(); diff --git a/crawl-ref/source/wiz-item.cc b/crawl-ref/source/wiz-item.cc index 17d890c467d5..a899be4e0fe4 100644 --- a/crawl-ref/source/wiz-item.cc +++ b/crawl-ref/source/wiz-item.cc @@ -392,7 +392,7 @@ void wizard_tweak_object() char specs[50]; int keyin; - int item = prompt_invent_item("Tweak which item? ", MT_INVLIST, -1); + int item = prompt_invent_item("Tweak which item? ", menu_type::invlist, -1); if (prompt_failed(item)) return; @@ -521,7 +521,8 @@ static bool _make_book_randart(item_def &book) /// Prompt for an item in inventory & print its base shop value. void wizard_value_item() { - const int i = prompt_invent_item("Value of which item?", MT_INVLIST, -1); + const int i = prompt_invent_item("Value of which item?", + menu_type::invlist, -1); if (prompt_failed(i)) return; @@ -591,7 +592,7 @@ void wizard_create_all_artefacts() void wizard_make_object_randart() { int i = prompt_invent_item("Make an artefact out of which item?", - MT_INVLIST, -1); + menu_type::invlist, -1); if (prompt_failed(i)) return; @@ -681,7 +682,8 @@ static bool _item_type_can_be_cursed(int type) void wizard_uncurse_item() { - const int i = prompt_invent_item("(Un)curse which item?", MT_INVLIST, -1); + const int i = prompt_invent_item("(Un)curse which item?", + menu_type::invlist, -1); if (!prompt_failed(i)) { @@ -1300,7 +1302,7 @@ static void _debug_rap_stats(FILE *ostat) { const int inv_index = prompt_invent_item("Generate randart stats on which item?", - MT_INVLIST, -1); + menu_type::invlist, -1); if (prompt_failed(inv_index)) return; diff --git a/crawl-ref/source/wiz-mon.cc b/crawl-ref/source/wiz-mon.cc index 387e9309e7bd..6d4f27eaab80 100644 --- a/crawl-ref/source/wiz-mon.cc +++ b/crawl-ref/source/wiz-mon.cc @@ -709,7 +709,7 @@ void wizard_give_monster_item(monster* mon) } int player_slot = prompt_invent_item("Give which item to monster?", - MT_DROP, -1); + menu_type::drop, -1); if (prompt_failed(player_slot)) return; From 9ae989b715f5a4ac9e96042b244d92b763d16b12 Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Thu, 17 Jan 2019 18:28:25 +0000 Subject: [PATCH 146/864] Change `enum activity_interrupt_type` to `enum class activity_interrupt` Convert the activity_interrupt_type enum to an enum class and rename the enum class to activity_interrupt to shorten identifier names somewhat. Also define NUM_ACTIVITY_INTERRUPTS as a `constexpr int` rather than it being inside the enum class definition and thereby taking the activity_interrupt type. --- crawl-ref/source/activity-interrupt-type.h | 39 +++++++------ crawl-ref/source/attack.cc | 5 +- crawl-ref/source/beam.cc | 7 ++- crawl-ref/source/delay.cc | 68 ++++++++++++---------- crawl-ref/source/delay.h | 4 +- crawl-ref/source/fight.cc | 3 +- crawl-ref/source/food.cc | 2 +- crawl-ref/source/initfile.cc | 16 ++--- crawl-ref/source/l-you.cc | 2 +- crawl-ref/source/message.cc | 7 ++- crawl-ref/source/mon-act.cc | 8 +-- crawl-ref/source/mon-ench.cc | 4 +- crawl-ref/source/mon-util.cc | 2 +- crawl-ref/source/monster.h | 2 +- crawl-ref/source/mutation.cc | 2 +- crawl-ref/source/options.h | 4 +- crawl-ref/source/ouch.cc | 2 +- crawl-ref/source/player-stats.cc | 4 +- crawl-ref/source/player.cc | 12 ++-- crawl-ref/source/prompt.cc | 4 +- crawl-ref/source/spl-transloc.cc | 4 +- crawl-ref/source/stairs.cc | 2 +- crawl-ref/source/state.cc | 22 +++---- crawl-ref/source/state.h | 2 +- crawl-ref/source/teleport.cc | 2 +- crawl-ref/source/view.cc | 5 +- 26 files changed, 127 insertions(+), 107 deletions(-) diff --git a/crawl-ref/source/activity-interrupt-type.h b/crawl-ref/source/activity-interrupt-type.h index eb118c08d2e3..95806175b3ad 100644 --- a/crawl-ref/source/activity-interrupt-type.h +++ b/crawl-ref/source/activity-interrupt-type.h @@ -1,26 +1,27 @@ #pragma once // Be sure to change activity_interrupt_names in delay.cc to match! -enum activity_interrupt_type +enum class activity_interrupt { - AI_FORCE_INTERRUPT = 0, // Forcibly kills any activity that can be - // interrupted. - AI_KEYPRESS, - AI_FULL_HP, // Player is fully healed - AI_FULL_MP, // Player has recovered all mp - AI_ANCESTOR_HP, // Player's ancestor is fully healed - AI_HUNGRY, // Hunger increased - AI_MESSAGE, // Message was displayed - AI_HP_LOSS, - AI_STAT_CHANGE, - AI_SEE_MONSTER, - AI_MONSTER_ATTACKS, - AI_TELEPORT, - AI_HIT_MONSTER, // Player hit monster (invis or - // mimic) during travel/explore. - AI_SENSE_MONSTER, - AI_MIMIC, + force = 0, // Forcibly kills any activity that can be + // interrupted. + keypress, // Not currently used + full_hp, // Player is fully healed + full_mp, // Player has recovered all mp + ancestor_hp, // Player's ancestor is fully healed + hungry, // Hunger increased + message, // Message was displayed + hp_loss, + stat_change, + see_monster, + monster_attacks, + teleport, + hit_monster, // Player hit invis monster during travel/explore. + sense_monster, + mimic, // Always the last. - NUM_AINTERRUPTS + COUNT }; +constexpr int NUM_ACTIVITY_INTERRUPTS + = static_cast(activity_interrupt::COUNT); diff --git a/crawl-ref/source/attack.cc b/crawl-ref/source/attack.cc index 0ba6ed1ab76b..44c658ff1e5f 100644 --- a/crawl-ref/source/attack.cc +++ b/crawl-ref/source/attack.cc @@ -440,7 +440,10 @@ void attack::alert_defender() && !attacker->as_monster()->wont_attack()) { if (defender->is_player()) - interrupt_activity(AI_MONSTER_ATTACKS, attacker->as_monster()); + { + interrupt_activity(activity_interrupt::monster_attacks, + attacker->as_monster()); + } if (you.pet_target == MHITNOT && env.sanctuary_time <= 0) you.pet_target = attacker->mindex(); } diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc index c748fe9ec9ac..8782f8bacb5a 100644 --- a/crawl-ref/source/beam.cc +++ b/crawl-ref/source/beam.cc @@ -3761,9 +3761,12 @@ void bolt::affect_player() if (!YOU_KILL(thrower)) { if (agent() && agent()->is_monster()) - interrupt_activity(AI_MONSTER_ATTACKS, agent()->as_monster()); + { + interrupt_activity(activity_interrupt::monster_attacks, + agent()->as_monster()); + } else - interrupt_activity(AI_MONSTER_ATTACKS); + interrupt_activity(activity_interrupt::monster_attacks); } if (flavour == BEAM_MISSILE && item) diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc index 67d19ac93a13..879cd54f1211 100644 --- a/crawl-ref/source/delay.cc +++ b/crawl-ref/source/delay.cc @@ -91,7 +91,7 @@ class interrupt_block int interrupt_block::interrupts_blocked = 0; static void _xom_check_corpse_waste(); -static const char *_activity_interrupt_name(activity_interrupt_type ai); +static const char *_activity_interrupt_name(activity_interrupt ai); void push_delay(shared_ptr delay) { @@ -962,12 +962,12 @@ void run_macro(const char *macroname) // Returns TRUE if the delay should be interrupted, MAYBE if the user function // had no opinion on the matter, FALSE if the delay should not be interrupted. static maybe_bool _userdef_interrupt_activity(Delay* delay, - activity_interrupt_type ai, + activity_interrupt ai, const activity_interrupt_data &at) { #ifdef CLUA_BINDINGS lua_State *ls = clua.state(); - if (!ls || ai == AI_FORCE_INTERRUPT) + if (!ls || ai == activity_interrupt::force) return MB_TRUE; const char *interrupt_name = _activity_interrupt_name(ai); @@ -1002,7 +1002,7 @@ static maybe_bool _userdef_interrupt_activity(Delay* delay, // Returns true if the activity should be interrupted, false otherwise. static bool _should_stop_activity(Delay* delay, - activity_interrupt_type ai, + activity_interrupt ai, const activity_interrupt_data &at) { switch (_userdef_interrupt_activity(delay, ai, at)) @@ -1024,15 +1024,20 @@ static bool _should_stop_activity(Delay* delay, // No monster will attack you inside a sanctuary, // so presence of monsters won't matter. - if (ai == AI_SEE_MONSTER && is_sanctuary(you.pos())) + if (ai == activity_interrupt::see_monster && is_sanctuary(you.pos())) return false; auto curr = current_delay(); // Not necessarily what we were passed. - if ((ai == AI_SEE_MONSTER || ai == AI_MIMIC) && player_stair_delay()) + if ((ai == activity_interrupt::see_monster + || ai == activity_interrupt::mimic) + && player_stair_delay()) + { return false; + } - if (ai == AI_FULL_HP || ai == AI_FULL_MP || ai == AI_ANCESTOR_HP) + if (ai == activity_interrupt::full_hp || ai == activity_interrupt::full_mp + || ai == activity_interrupt::ancestor_hp) { if ((Options.rest_wait_both && curr->is_resting() && !you.is_sufficiently_rested()) @@ -1044,14 +1049,14 @@ static bool _should_stop_activity(Delay* delay, } // Don't interrupt feeding or butchering for monsters already in view. - if (curr->is_butcher() && ai == AI_SEE_MONSTER + if (curr->is_butcher() && ai == activity_interrupt::see_monster && testbits(at.mons_data->flags, MF_WAS_IN_VIEW)) { return false; } - return ai == AI_FORCE_INTERRUPT - || Options.activity_interrupts[delay->name()][ai]; + return ai == activity_interrupt::force + || Options.activity_interrupts[delay->name()][static_cast(ai)]; } static string _abyss_monster_creation_message(const monster* mon) @@ -1088,17 +1093,17 @@ static string _abyss_monster_creation_message(const monster* mon) return *random_choose_weighted(messages); } -static inline bool _monster_warning(activity_interrupt_type ai, +static inline bool _monster_warning(activity_interrupt ai, const activity_interrupt_data &at, shared_ptr delay, vector* msgs_buf = nullptr) { - if (ai == AI_SENSE_MONSTER) + if (ai == activity_interrupt::sense_monster) { mprf(MSGCH_WARN, "You sense a monster nearby."); return true; } - if (ai != AI_SEE_MONSTER) + if (ai != activity_interrupt::see_monster) return false; if (delay && !delay->is_run() && !delay->is_butcher()) return false; @@ -1279,7 +1284,7 @@ void autotoggle_autopickup(bool off) } // Returns true if any activity was stopped. Not reentrant. -bool interrupt_activity(activity_interrupt_type ai, +bool interrupt_activity(activity_interrupt ai, const activity_interrupt_data &at, vector* msgs_buf) { @@ -1287,7 +1292,8 @@ bool interrupt_activity(activity_interrupt_type ai, return false; const interrupt_block block_recursive_interrupts; - if (ai == AI_HIT_MONSTER || ai == AI_MONSTER_ATTACKS) + if (ai == activity_interrupt::hit_monster + || ai == activity_interrupt::monster_attacks) { const monster* mon = at.mons_data; if (mon && !mon->visible_to(&you) && !mon->submerged()) @@ -1301,7 +1307,7 @@ bool interrupt_activity(activity_interrupt_type ai, { // Printing "[foo] comes into view." messages even when not // auto-exploring/travelling. - if (ai == AI_SEE_MONSTER) + if (ai == activity_interrupt::see_monster) return _monster_warning(ai, at, nullptr, msgs_buf); else return false; @@ -1310,7 +1316,7 @@ bool interrupt_activity(activity_interrupt_type ai, const auto delay = current_delay(); // If we get hungry while traveling, let's try to auto-eat a chunk. - if (ai == AI_HUNGRY && delay->want_autoeat() && _auto_eat() + if (ai == activity_interrupt::hungry && delay->want_autoeat() && _auto_eat() && prompt_eat_chunks(true) == 1) { return false; @@ -1319,17 +1325,17 @@ bool interrupt_activity(activity_interrupt_type ai, dprf("Activity interrupt: %s", _activity_interrupt_name(ai)); // First try to stop the current delay. - if (ai == AI_FULL_HP && !you.running.notified_hp_full) + if (ai == activity_interrupt::full_hp && !you.running.notified_hp_full) { you.running.notified_hp_full = true; mpr("HP restored."); } - else if (ai == AI_FULL_MP && !you.running.notified_mp_full) + else if (ai == activity_interrupt::full_mp && !you.running.notified_mp_full) { you.running.notified_mp_full = true; mpr("Magic restored."); } - else if (ai == AI_ANCESTOR_HP + else if (ai == activity_interrupt::ancestor_hp && !you.running.notified_ancestor_hp_full) { // This interrupt only triggers when the ancestor is in LOS, @@ -1342,7 +1348,7 @@ bool interrupt_activity(activity_interrupt_type ai, { _monster_warning(ai, at, delay, msgs_buf); // Teleport stops stair delays. - stop_delay(ai == AI_TELEPORT); + stop_delay(ai == activity_interrupt::teleport); return true; } @@ -1377,7 +1383,7 @@ bool interrupt_activity(activity_interrupt_type ai, return false; } -// Must match the order of activity_interrupt_type.h! +// Must match the order of activity_interrupt.h! static const char *activity_interrupt_names[] = { "force", "keypress", "full_hp", "full_mp", "ancestor_hp", "hungry", "message", @@ -1385,23 +1391,23 @@ static const char *activity_interrupt_names[] = "sense_monster", "mimic" }; -static const char *_activity_interrupt_name(activity_interrupt_type ai) +static const char *_activity_interrupt_name(activity_interrupt ai) { - COMPILE_CHECK(ARRAYSZ(activity_interrupt_names) == NUM_AINTERRUPTS); + COMPILE_CHECK(ARRAYSZ(activity_interrupt_names) == NUM_ACTIVITY_INTERRUPTS); - if (ai == NUM_AINTERRUPTS) + if (ai == activity_interrupt::COUNT) return ""; - return activity_interrupt_names[ai]; + return activity_interrupt_names[static_cast(ai)]; } -activity_interrupt_type get_activity_interrupt(const string &name) +activity_interrupt get_activity_interrupt(const string &name) { - COMPILE_CHECK(ARRAYSZ(activity_interrupt_names) == NUM_AINTERRUPTS); + COMPILE_CHECK(ARRAYSZ(activity_interrupt_names) == NUM_ACTIVITY_INTERRUPTS); - for (int i = 0; i < NUM_AINTERRUPTS; ++i) + for (int i = 0; i < NUM_ACTIVITY_INTERRUPTS; ++i) if (name == activity_interrupt_names[i]) - return activity_interrupt_type(i); + return activity_interrupt(i); - return NUM_AINTERRUPTS; + return activity_interrupt::COUNT; } diff --git a/crawl-ref/source/delay.h b/crawl-ref/source/delay.h index 9a80ca0993a0..ee6b95cb0ddd 100644 --- a/crawl-ref/source/delay.h +++ b/crawl-ref/source/delay.h @@ -716,12 +716,12 @@ bool already_learning_spell(int spell = -1); void clear_macro_process_key_delay(); -activity_interrupt_type get_activity_interrupt(const string &); +activity_interrupt get_activity_interrupt(const string &); void run_macro(const char *macroname = nullptr); void autotoggle_autopickup(bool off); -bool interrupt_activity(activity_interrupt_type ai, +bool interrupt_activity(activity_interrupt ai, const activity_interrupt_data &a = activity_interrupt_data(), vector* msgs_buf = nullptr); diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc index 85a9bc23ee0e..6361c80ff36a 100644 --- a/crawl-ref/source/fight.cc +++ b/crawl-ref/source/fight.cc @@ -158,7 +158,8 @@ bool fight_melee(actor *attacker, actor *defender, bool *did_hit, bool simu) attk.simu = true; // We're trying to hit a monster, break out of travel/explore now. - interrupt_activity(AI_HIT_MONSTER, defender->as_monster()); + interrupt_activity(activity_interrupt::hit_monster, + defender->as_monster()); // Check if the player is fighting with something unsuitable, // or someone unsuitable. diff --git a/crawl-ref/source/food.cc b/crawl-ref/source/food.cc index af2dd16bdbff..3d2c13169a0d 100644 --- a/crawl-ref/source/food.cc +++ b/crawl-ref/source/food.cc @@ -235,7 +235,7 @@ bool food_change(bool initial) you.redraw_status_lights = true; if (newstate < HS_SATIATED) - interrupt_activity(AI_HUNGRY); + interrupt_activity(activity_interrupt::hungry); if (you.species == SP_VAMPIRE) { diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index d98d5c819ead..ba2562c184b5 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -863,7 +863,7 @@ void game_options::set_default_activity_interrupts() } void game_options::set_activity_interrupt( - FixedBitVector &eints, + FixedBitVector &eints, const string &interrupt) { if (starts_with(interrupt, interrupt_prefix)) @@ -873,21 +873,21 @@ void game_options::set_activity_interrupt( if (!activity_interrupts.count(delay_name)) return report_error("Unknown delay: %s\n", delay_name.c_str()); - FixedBitVector &refints = + FixedBitVector &refints = activity_interrupts[delay_name]; eints |= refints; return; } - activity_interrupt_type ai = get_activity_interrupt(interrupt); - if (ai == NUM_AINTERRUPTS) + activity_interrupt ai = get_activity_interrupt(interrupt); + if (ai == activity_interrupt::COUNT) { return report_error("Delay interrupt name \"%s\" not recognised.\n", interrupt.c_str()); } - eints.set(ai); + eints.set(static_cast(ai)); } void game_options::set_activity_interrupt(const string &activity_name, @@ -900,11 +900,11 @@ void game_options::set_activity_interrupt(const string &activity_name, if (remove_interrupts) { - FixedBitVector refints; + FixedBitVector refints; for (const string &interrupt : interrupts) set_activity_interrupt(refints, interrupt); - for (int i = 0; i < NUM_AINTERRUPTS; ++i) + for (int i = 0; i < NUM_ACTIVITY_INTERRUPTS; ++i) if (refints[i]) eints.set(i, false); } @@ -917,7 +917,7 @@ void game_options::set_activity_interrupt(const string &activity_name, set_activity_interrupt(eints, interrupt); } - eints.set(AI_FORCE_INTERRUPT); + eints.set(static_cast(activity_interrupt::force)); } #if defined(DGAMELAUNCH) diff --git a/crawl-ref/source/l-you.cc b/crawl-ref/source/l-you.cc index f30c4160d10a..643070adc581 100644 --- a/crawl-ref/source/l-you.cc +++ b/crawl-ref/source/l-you.cc @@ -475,7 +475,7 @@ LUARET1(you_turns_on_level, number, env.turns_on_level) /*** Interrupt the current multi-turn activity or macro sequence. * @function stop_activity */ -LUAWRAP(you_stop_activity, interrupt_activity(AI_FORCE_INTERRUPT)) +LUAWRAP(you_stop_activity, interrupt_activity(activity_interrupt::force)) /*** Are you taking the stairs? * @treturn boolean * @function taking_stairs diff --git a/crawl-ref/source/message.cc b/crawl-ref/source/message.cc index 7baf2239f761..317ed4821289 100644 --- a/crawl-ref/source/message.cc +++ b/crawl-ref/source/message.cc @@ -1430,7 +1430,7 @@ static void _mpr(string text, msg_channel_type channel, int param, bool nojoin, _last_msg_turn = msg.turn; if (channel == MSGCH_ERROR) - interrupt_activity(AI_FORCE_INTERRUPT); + interrupt_activity(activity_interrupt::force); if (channel == MSGCH_PROMPT || channel == MSGCH_ERROR) set_more_autoclear(false); @@ -1612,7 +1612,10 @@ static void mpr_check_patterns(const string& message, } if (channel != MSGCH_DIAGNOSTICS && channel != MSGCH_EQUIPMENT) - interrupt_activity(AI_MESSAGE, channel_to_str(channel) + ":" + message); + { + interrupt_activity(activity_interrupt::message, + channel_to_str(channel) + ":" + message); + } } static bool channel_message_history(msg_channel_type channel) diff --git a/crawl-ref/source/mon-act.cc b/crawl-ref/source/mon-act.cc index 9065592bcdbf..7bc33724f2f3 100644 --- a/crawl-ref/source/mon-act.cc +++ b/crawl-ref/source/mon-act.cc @@ -161,7 +161,7 @@ static void _monster_regenerate(monster* mons) if (mons_is_hepliaklqana_ancestor(mons->type)) { if (mons->hit_points == mons->max_hit_points && you.can_see(*mons)) - interrupt_activity(AI_ANCESTOR_HP); + interrupt_activity(activity_interrupt::ancestor_hp); } } @@ -2670,7 +2670,7 @@ static void _mons_open_door(monster& mons, const coord_def &pos) if (!you.can_see(mons)) { mprf("Something unseen %s", open_str.c_str()); - interrupt_activity(AI_FORCE_INTERRUPT); + interrupt_activity(activity_interrupt::force); } else if (!you_are_delayed()) { @@ -3283,7 +3283,7 @@ static bool _do_move_monster(monster& mons, const coord_def& delta) if (!you.can_see(mons)) { mpr("The door bursts into shrapnel!"); - interrupt_activity(AI_FORCE_INTERRUPT); + interrupt_activity(activity_interrupt::force); } else simple_monster_message(mons, " bursts through the door, destroying it!"); @@ -3308,7 +3308,7 @@ static bool _do_move_monster(monster& mons, const coord_def& delta) if (!you.can_see(mons)) { mpr("The door mysteriously vanishes."); - interrupt_activity(AI_FORCE_INTERRUPT); + interrupt_activity(activity_interrupt::force); } else simple_monster_message(mons, " eats the door!"); diff --git a/crawl-ref/source/mon-ench.cc b/crawl-ref/source/mon-ench.cc index 6f312e94198f..c127b360c4c2 100644 --- a/crawl-ref/source/mon-ench.cc +++ b/crawl-ref/source/mon-ench.cc @@ -632,7 +632,7 @@ void monster::remove_enchantment_effect(const mon_enchant &me, bool quiet) if (you.can_see(*this)) { // and fire activity interrupts - interrupt_activity(AI_SEE_MONSTER, + interrupt_activity(activity_interrupt::see_monster, activity_interrupt_data(this, SC_UNCHARM)); } @@ -752,7 +752,7 @@ void monster::remove_enchantment_effect(const mon_enchant &me, bool quiet) else if (you.see_cell(pos()) && feat_is_watery(grd(pos()))) { mpr("Something invisible bursts forth from the water."); - interrupt_activity(AI_FORCE_INTERRUPT); + interrupt_activity(activity_interrupt::force); } break; diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index e31ee632b888..706f30785f0c 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -1103,7 +1103,7 @@ static void _mimic_vanish(const coord_def& pos, const string& name) mprf("The %s mimic %svanishes%s!", name.c_str(), cackle.c_str(), smoke_str); - interrupt_activity(AI_MIMIC); + interrupt_activity(activity_interrupt::mimic); } /** diff --git a/crawl-ref/source/monster.h b/crawl-ref/source/monster.h index aa1906d82ed8..d60823e46cc4 100644 --- a/crawl-ref/source/monster.h +++ b/crawl-ref/source/monster.h @@ -104,7 +104,7 @@ class monster : public actor unique_ptr ghost; // Ghost information. seen_context_type seen_context; // Non-standard context for - // AI_SEE_MONSTER + // activity_interrupt::see_monster int damage_friendly; // Damage taken, x2 you, x1 pets, x0 else. int damage_total; diff --git a/crawl-ref/source/mutation.cc b/crawl-ref/source/mutation.cc index ba1b67050f89..8eb8d4c4cab4 100644 --- a/crawl-ref/source/mutation.cc +++ b/crawl-ref/source/mutation.cc @@ -2789,7 +2789,7 @@ void check_monster_detect() if (you.see_cell(*ri2)) { mon->flags |= MF_SENSED; - interrupt_activity(AI_SENSE_MONSTER); + interrupt_activity(activity_interrupt::sense_monster); break; } } diff --git a/crawl-ref/source/options.h b/crawl-ref/source/options.h index 3c0cfb390b8f..dbaec3ad6c82 100644 --- a/crawl-ref/source/options.h +++ b/crawl-ref/source/options.h @@ -429,7 +429,7 @@ struct game_options vector drop_filter; - map> activity_interrupts; + map> activity_interrupts; #ifdef DEBUG_DIAGNOSTICS FixedBitVector quiet_debug_messages; #endif @@ -615,7 +615,7 @@ struct game_options message_filter parse_message_filter(const string &s); void set_default_activity_interrupts(); - void set_activity_interrupt(FixedBitVector &eints, + void set_activity_interrupt(FixedBitVector &eints, const string &interrupt); void set_activity_interrupt(const string &activity_name, const string &interrupt_names, diff --git a/crawl-ref/source/ouch.cc b/crawl-ref/source/ouch.cc index 4cbb02000224..e4bceb02ee7c 100644 --- a/crawl-ref/source/ouch.cc +++ b/crawl-ref/source/ouch.cc @@ -824,7 +824,7 @@ void ouch(int dam, kill_method_type death_type, mid_t source, const char *aux, dam = dam * 10 / 15; } ait_hp_loss hpl(dam, death_type); - interrupt_activity(AI_HP_LOSS, &hpl); + interrupt_activity(activity_interrupt::hp_loss, &hpl); // Don't wake the player with fatal or poison damage. if (dam > 0 && dam < you.hp && death_type != KILLED_BY_POISON) diff --git a/crawl-ref/source/player-stats.cc b/crawl-ref/source/player-stats.cc index 51b801714c9d..90f8128f689f 100644 --- a/crawl-ref/source/player-stats.cc +++ b/crawl-ref/source/player-stats.cc @@ -326,7 +326,7 @@ void modify_stat(stat_type which_stat, int amount, bool suppress_msg) // Stop delays if a stat drops. if (amount < 0) - interrupt_activity(AI_STAT_CHANGE); + interrupt_activity(activity_interrupt::stat_change); if (which_stat == STAT_RANDOM) which_stat = static_cast(random2(NUM_STATS)); @@ -353,7 +353,7 @@ void notify_stat_change(stat_type which_stat, int amount, bool suppress_msg) // Stop delays if a stat drops. if (amount < 0) - interrupt_activity(AI_STAT_CHANGE); + interrupt_activity(activity_interrupt::stat_change); if (which_stat == STAT_RANDOM) which_stat = static_cast(random2(NUM_STATS)); diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 5034926969ba..2226fd1ee2dd 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -407,8 +407,8 @@ bool swap_check(monster* mons, coord_def &loc, bool quiet) // Might not be ideal, but it's better than insta-killing // the monster... maybe try for a short blink instead? - bwr simple_monster_message(*mons, " cannot make way for you."); - // FIXME: AI_HIT_MONSTER isn't ideal. - interrupt_activity(AI_HIT_MONSTER, mons); + // FIXME: activity_interrupt::hit_monster isn't ideal. + interrupt_activity(activity_interrupt::hit_monster, mons); } return swap; @@ -3782,7 +3782,7 @@ void inc_mp(int mp_gain, bool silent) if (!silent) { if (_should_stop_resting(you.magic_points, you.max_magic_points)) - interrupt_activity(AI_FULL_MP); + interrupt_activity(activity_interrupt::full_mp); you.redraw_magic_points = true; } } @@ -3803,7 +3803,7 @@ void inc_hp(int hp_gain) you.hp = you.hp_max; if (_should_stop_resting(you.hp, you.hp_max)) - interrupt_activity(AI_FULL_HP); + interrupt_activity(activity_interrupt::full_hp); you.redraw_hit_points = true; } @@ -7781,7 +7781,7 @@ void player_open_door(coord_def doorpos) set_exclude(doorpos, 0); } } - interrupt_activity(AI_FORCE_INTERRUPT); + interrupt_activity(activity_interrupt::force); return; } ignore_exclude = true; @@ -7795,7 +7795,7 @@ void player_open_door(coord_def doorpos) if (!yesno(prompt.c_str(), true, 'n', true, false)) { canned_msg(MSG_OK); - interrupt_activity(AI_FORCE_INTERRUPT); + interrupt_activity(activity_interrupt::force); return; } } diff --git a/crawl-ref/source/prompt.cc b/crawl-ref/source/prompt.cc index d610c74d1d9f..274781d4405f 100644 --- a/crawl-ref/source/prompt.cc +++ b/crawl-ref/source/prompt.cc @@ -53,7 +53,7 @@ bool yesno(const char *str, bool allow_lowercase, int default_answer, bool clear { bool message = (region == GOTO_MSG); if (interrupt_delays && !crawl_state.is_repeating_cmd()) - interrupt_activity(AI_FORCE_INTERRUPT); + interrupt_activity(activity_interrupt::force); // Allow players to answer prompts via clua. maybe_bool res = clua.callmaybefn("c_answer_prompt", "s", str); @@ -220,7 +220,7 @@ int yesnoquit(const char* str, bool allow_lowercase, int default_answer, bool al bool clear_after, char alt_yes, char alt_yes2) { if (!crawl_state.is_repeating_cmd()) - interrupt_activity(AI_FORCE_INTERRUPT); + interrupt_activity(activity_interrupt::force); mouse_control mc(MOUSE_MODE_YESNO); diff --git a/crawl-ref/source/spl-transloc.cc b/crawl-ref/source/spl-transloc.cc index e8d14b2e61a4..581dd8b00504 100644 --- a/crawl-ref/source/spl-transloc.cc +++ b/crawl-ref/source/spl-transloc.cc @@ -569,7 +569,7 @@ static bool _teleport_player(bool wizard_tele, bool teleportitis, // After this point, we're guaranteed to teleport. Kill the appropriate // delays. Teleportitis needs to check the target square first, though. if (!teleportitis) - interrupt_activity(AI_TELEPORT); + interrupt_activity(activity_interrupt::teleport); // Update what we can see at the current location as well as its stash, // in case something happened in the exact turn that we teleported @@ -670,7 +670,7 @@ static bool _teleport_player(bool wizard_tele, bool teleportitis, } else { - interrupt_activity(AI_TELEPORT); + interrupt_activity(activity_interrupt::teleport); if (!reason.empty()) mpr(reason); mprf("You are suddenly yanked towards %s nearby monster%s!", diff --git a/crawl-ref/source/stairs.cc b/crawl-ref/source/stairs.cc index 8ee150b38f68..30c3b9528224 100644 --- a/crawl-ref/source/stairs.cc +++ b/crawl-ref/source/stairs.cc @@ -96,7 +96,7 @@ bool check_annotation_exclusion_warning() && !yesno("Enter next level anyway?", true, 'n', true, false)) { canned_msg(MSG_OK); - interrupt_activity(AI_FORCE_INTERRUPT); + interrupt_activity(activity_interrupt::force); crawl_state.level_annotation_shown = false; return false; } diff --git a/crawl-ref/source/state.cc b/crawl-ref/source/state.cc index e1434d9faff6..54ff23aeef1b 100644 --- a/crawl-ref/source/state.cc +++ b/crawl-ref/source/state.cc @@ -192,7 +192,7 @@ void game_state::zero_turns_taken() cancel_cmd_repeat(); } -bool interrupt_cmd_repeat(activity_interrupt_type ai, +bool interrupt_cmd_repeat(activity_interrupt ai, const activity_interrupt_data &at) { if (crawl_state.cmd_repeat_start) @@ -203,12 +203,12 @@ bool interrupt_cmd_repeat(activity_interrupt_type ai, switch (ai) { - case AI_HUNGRY: - case AI_TELEPORT: - case AI_FORCE_INTERRUPT: - case AI_HP_LOSS: - case AI_MONSTER_ATTACKS: - case AI_MIMIC: + case activity_interrupt::hungry: + case activity_interrupt::teleport: + case activity_interrupt::force: + case activity_interrupt::hp_loss: + case activity_interrupt::monster_attacks: + case activity_interrupt::mimic: crawl_state.cancel_cmd_repeat("Command repetition interrupted."); return true; @@ -216,7 +216,7 @@ bool interrupt_cmd_repeat(activity_interrupt_type ai, break; } - if (ai == AI_SEE_MONSTER) + if (ai == activity_interrupt::see_monster) { const monster* mon = at.mons_data; ASSERT(mon); @@ -261,9 +261,9 @@ bool interrupt_cmd_repeat(activity_interrupt_type ai, // then everything interrupts it. if (crawl_state.repeat_cmd == CMD_WAIT) { - if (ai == AI_FULL_MP) + if (ai == activity_interrupt::full_mp) crawl_state.cancel_cmd_repeat("Magic restored."); - else if (ai == AI_FULL_HP) + else if (ai == activity_interrupt::full_hp) crawl_state.cancel_cmd_repeat("HP restored"); else crawl_state.cancel_cmd_repeat("Command repetition interrupted."); @@ -274,7 +274,7 @@ bool interrupt_cmd_repeat(activity_interrupt_type ai, if (crawl_state.cmd_repeat_started_unsafe) return false; - if (ai == AI_HIT_MONSTER) + if (ai == activity_interrupt::hit_monster) { // This check is for when command repetition is used to // whack away at a 0xp monster, since the player feels safe diff --git a/crawl-ref/source/state.h b/crawl-ref/source/state.h index e82adb19ff23..82a05c3e31f4 100644 --- a/crawl-ref/source/state.h +++ b/crawl-ref/source/state.h @@ -265,5 +265,5 @@ class mon_acting monster* mon; }; -bool interrupt_cmd_repeat(activity_interrupt_type ai, +bool interrupt_cmd_repeat(activity_interrupt ai, const activity_interrupt_data &at); diff --git a/crawl-ref/source/teleport.cc b/crawl-ref/source/teleport.cc index 00c5390448a6..a1f2be658393 100644 --- a/crawl-ref/source/teleport.cc +++ b/crawl-ref/source/teleport.cc @@ -277,7 +277,7 @@ void monster_teleport(monster* mons, bool instan, bool silent) // delayed, the monster isn't hostile) we still want to give // a message. activity_interrupt_data ai(mons, SC_TELEPORT_IN); - if (!interrupt_activity(AI_SEE_MONSTER, ai)) + if (!interrupt_activity(activity_interrupt::see_monster, ai)) simple_monster_message(*mons, " appears out of thin air!"); } } diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index d052c5b812b9..bde582bd9ff2 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -102,7 +102,10 @@ bool handle_seen_interrupt(monster* mons, vector* msgs_buf) aid.context = SC_NEWLY_SEEN; if (!mons_is_safe(mons)) - return interrupt_activity(AI_SEE_MONSTER, aid, msgs_buf); + { + return interrupt_activity(activity_interrupt::see_monster, + aid, msgs_buf); + } return false; } From b51ee145e8873c68e76c340bd493c60e895b439e Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Fri, 18 Jan 2019 12:40:05 +0000 Subject: [PATCH 147/864] Convert `enum ev_ignore_bit` to `enum class ev_ignore` ...and change a couple of bitwise ands to use the testbits method, where required. --- crawl-ref/source/actor.h | 12 ++++++------ crawl-ref/source/ghost.cc | 2 +- crawl-ref/source/melee-attack.cc | 6 +++--- crawl-ref/source/mon-info.cc | 2 +- crawl-ref/source/monster.cc | 4 ++-- crawl-ref/source/monster.h | 2 +- crawl-ref/source/player.cc | 6 +++--- crawl-ref/source/player.h | 2 +- crawl-ref/source/ranged-attack.cc | 4 ++-- crawl-ref/source/spl-damage.cc | 2 +- 10 files changed, 21 insertions(+), 21 deletions(-) diff --git a/crawl-ref/source/actor.h b/crawl-ref/source/actor.h index 8442b7aaad6e..dbd1f9dd2459 100644 --- a/crawl-ref/source/actor.h +++ b/crawl-ref/source/actor.h @@ -18,13 +18,13 @@ #define CLING_KEY "clinging" // 'is creature clinging' property key -enum ev_ignore_bit +enum class ev_ignore { - EV_IGNORE_NONE = 0, - EV_IGNORE_HELPLESS = 1<<0, - EV_IGNORE_UNIDED = 1<<1, + none = 0, + helpless = 1<<0, + unided = 1<<1, }; -DEF_BITFIELD(ev_ignore_type, ev_ignore_bit); +DEF_BITFIELD(ev_ignore_type, ev_ignore); struct bolt; @@ -262,7 +262,7 @@ class actor virtual int gdr_perc() const = 0; int apply_ac(int damage, int max_damage = 0, ac_type ac_rule = AC_NORMAL, int stab_bypass = 0, bool for_real = true) const; - virtual int evasion(ev_ignore_type ign = EV_IGNORE_NONE, + virtual int evasion(ev_ignore_type ign = ev_ignore::none, const actor *attacker = nullptr) const = 0; virtual bool shielded() const = 0; virtual int shield_bonus() const = 0; diff --git a/crawl-ref/source/ghost.cc b/crawl-ref/source/ghost.cc index ee748c888cf8..734172071ef0 100644 --- a/crawl-ref/source/ghost.cc +++ b/crawl-ref/source/ghost.cc @@ -278,7 +278,7 @@ void ghost_demon::init_player_ghost(bool actual_ghost) name = you.your_name; max_hp = min(get_real_hp(false, false), MAX_GHOST_HP); - ev = min(you.evasion(EV_IGNORE_HELPLESS), MAX_GHOST_EVASION); + ev = min(you.evasion(ev_ignore::helpless), MAX_GHOST_EVASION); ac = you.armour_class(); dprf("ghost ac: %d, ev: %d", ac, ev); diff --git a/crawl-ref/source/melee-attack.cc b/crawl-ref/source/melee-attack.cc index 39b25d2f4399..3cc2975ddd4a 100644 --- a/crawl-ref/source/melee-attack.cc +++ b/crawl-ref/source/melee-attack.cc @@ -834,7 +834,7 @@ bool melee_attack::attack() // Calculate various ev values and begin to check them to determine the // correct handle_phase_ handler. - const int ev = defender->evasion(EV_IGNORE_NONE, attacker); + const int ev = defender->evasion(ev_ignore::none, attacker); ev_margin = test_hit(to_hit, ev, !attacker->is_player()); bool shield_blocked = attack_shield_blocked(true); @@ -1280,7 +1280,7 @@ bool melee_attack::player_aux_test_hit() // XXX We're clobbering did_hit did_hit = false; - const int evasion = defender->evasion(EV_IGNORE_NONE, attacker); + const int evasion = defender->evasion(ev_ignore::none, attacker); if (player_under_penance(GOD_ELYVILON) && god_hates_your_god(GOD_ELYVILON) @@ -1475,7 +1475,7 @@ void melee_attack::player_announce_aux_hit() string melee_attack::player_why_missed() { - const int ev = defender->evasion(EV_IGNORE_NONE, attacker); + const int ev = defender->evasion(ev_ignore::none, attacker); const int combined_penalty = attacker_armour_tohit_penalty + attacker_shield_tohit_penalty; if (to_hit < ev && to_hit + combined_penalty >= ev) diff --git a/crawl-ref/source/mon-info.cc b/crawl-ref/source/mon-info.cc index dc3be459677b..95fc531e8458 100644 --- a/crawl-ref/source/mon-info.cc +++ b/crawl-ref/source/mon-info.cc @@ -543,7 +543,7 @@ monster_info::monster_info(const monster* m, int milev) mintel = mons_intel(*m); hd = m->get_hit_dice(); ac = m->armour_class(false); - ev = m->evasion(EV_IGNORE_UNIDED); + ev = m->evasion(ev_ignore::unided); base_ev = m->base_evasion(); mr = m->res_magic(false); can_see_invis = m->can_see_invisible(false); diff --git a/crawl-ref/source/monster.cc b/crawl-ref/source/monster.cc index f37d45022871..1b5c0ae75c22 100644 --- a/crawl-ref/source/monster.cc +++ b/crawl-ref/source/monster.cc @@ -3436,7 +3436,7 @@ int monster::base_evasion() const **/ int monster::evasion(ev_ignore_type evit, const actor* /*act*/) const { - const bool calc_unid = !(evit & EV_IGNORE_UNIDED); + const bool calc_unid = !testbits(evit, ev_ignore::unided); int ev = base_evasion(); @@ -3465,7 +3465,7 @@ int monster::evasion(ev_ignore_type evit, const actor* /*act*/) const if (has_ench(ENCH_AGILE)) ev += 5; - if (evit & EV_IGNORE_HELPLESS) + if (evit & ev_ignore::helpless) return max(ev, 0); if (paralysed() || petrified() || petrifying() || asleep()) diff --git a/crawl-ref/source/monster.h b/crawl-ref/source/monster.h index d60823e46cc4..255aee226f5a 100644 --- a/crawl-ref/source/monster.h +++ b/crawl-ref/source/monster.h @@ -461,7 +461,7 @@ class monster : public actor int armour_class(bool calc_unid = true) const override; int gdr_perc() const override { return 0; } int base_evasion() const; - int evasion(ev_ignore_type evit = EV_IGNORE_NONE, + int evasion(ev_ignore_type evit = ev_ignore::none, const actor* /*attacker*/ = nullptr) const override; bool poison(actor *agent, int amount = 1, bool force = false) override; diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 2226fd1ee2dd..cd04e09e50bb 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -2228,7 +2228,7 @@ static int _player_evasion(ev_ignore_type evit) // Size is all that matters when paralysed or at 0 dex. if ((you.cannot_move() || you.duration[DUR_CLUMSY] || you.form == transformation::tree) - && !(evit & EV_IGNORE_HELPLESS)) + && !(evit & ev_ignore::helpless)) { return max(1, 2 + size_factor / 2); } @@ -6066,8 +6066,8 @@ int player::evasion(ev_ignore_type evit, const actor* act) const const int constrict_penalty = is_constricted() ? 3 : 0; const bool attacker_invis = act && !act->visible_to(this); - const int invis_penalty = attacker_invis && !(evit & EV_IGNORE_HELPLESS) ? - 10 : 0; + const int invis_penalty + = attacker_invis && !testbits(evit, ev_ignore::helpless) ? 10 : 0; return base_evasion - constrict_penalty - invis_penalty; } diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h index 28230bdb7b74..fefe8a8b7dd7 100644 --- a/crawl-ref/source/player.h +++ b/crawl-ref/source/player.h @@ -816,7 +816,7 @@ class player : public actor int base_ac(int scale) const; int armour_class(bool /*calc_unid*/ = true) const override; int gdr_perc() const override; - int evasion(ev_ignore_type evit = EV_IGNORE_NONE, + int evasion(ev_ignore_type evit = ev_ignore::none, const actor *attacker = nullptr) const override; int stat_hp() const override { return hp; } diff --git a/crawl-ref/source/ranged-attack.cc b/crawl-ref/source/ranged-attack.cc index 7cbf3ad17bb1..a1114b8cb8aa 100644 --- a/crawl-ref/source/ranged-attack.cc +++ b/crawl-ref/source/ranged-attack.cc @@ -105,7 +105,7 @@ bool ranged_attack::attack() return true; } - const int ev = defender->evasion(EV_IGNORE_NONE, attacker); + const int ev = defender->evasion(ev_ignore::none, attacker); ev_margin = test_hit(to_hit, ev, !attacker->is_player()); bool shield_blocked = attack_shield_blocked(false); @@ -223,7 +223,7 @@ bool ranged_attack::handle_phase_dodged() { did_hit = false; - const int ev = defender->evasion(EV_IGNORE_NONE, attacker); + const int ev = defender->evasion(ev_ignore::none, attacker); const int orig_ev_margin = test_hit(orig_to_hit, ev, !attacker->is_player()); diff --git a/crawl-ref/source/spl-damage.cc b/crawl-ref/source/spl-damage.cc index 23cc1378b799..24a04725c764 100644 --- a/crawl-ref/source/spl-damage.cc +++ b/crawl-ref/source/spl-damage.cc @@ -2415,7 +2415,7 @@ void forest_damage(const actor *mon) int dmg = 0; string msg; - if (!apply_chunked_AC(1, foe->evasion(EV_IGNORE_NONE, mon))) + if (!apply_chunked_AC(1, foe->evasion(ev_ignore::none, mon))) { msg = random_choose( "@foe@ @is@ waved at by a branch", From 1735f9d3598ae84db438e17dd418b90f09b344c3 Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Fri, 18 Jan 2019 12:46:14 +0000 Subject: [PATCH 148/864] Convert `enum ac_type` to an enum class The enum class retains the same name, because anything shorter (such as `ac`) risks being used somewhere else. --- crawl-ref/source/ac-type.h | 12 ++++++------ crawl-ref/source/actor.cc | 10 +++++----- crawl-ref/source/actor.h | 5 +++-- crawl-ref/source/attack.cc | 2 +- crawl-ref/source/beam.cc | 6 +++--- crawl-ref/source/beam.h | 2 +- crawl-ref/source/fineff.cc | 2 +- crawl-ref/source/melee-attack.cc | 2 +- crawl-ref/source/spl-damage.cc | 4 ++-- crawl-ref/source/spl-tornado.cc | 2 +- 10 files changed, 24 insertions(+), 23 deletions(-) diff --git a/crawl-ref/source/ac-type.h b/crawl-ref/source/ac-type.h index 4464860b0519..8e36a6b45653 100644 --- a/crawl-ref/source/ac-type.h +++ b/crawl-ref/source/ac-type.h @@ -1,12 +1,12 @@ #pragma once -enum ac_type +enum class ac_type { - AC_NONE, + none, // These types block small amounts of damage, hardly affecting big hits. - AC_NORMAL, - AC_HALF, - AC_TRIPLE, + normal, + half, + triple, // This one stays fair over arbitrary splits. - AC_PROPORTIONAL, + proportional, }; diff --git a/crawl-ref/source/actor.cc b/crawl-ref/source/actor.cc index 64b7dd31bb38..75672e819af7 100644 --- a/crawl-ref/source/actor.cc +++ b/crawl-ref/source/actor.cc @@ -347,23 +347,23 @@ int actor::apply_ac(int damage, int max_damage, ac_type ac_rule, int saved = 0; switch (ac_rule) { - case AC_NONE: + case ac_type::none: return damage; // no GDR, too - case AC_PROPORTIONAL: + case ac_type::proportional: ASSERT(stab_bypass == 0); saved = damage - apply_chunked_AC(damage, ac); saved = max(saved, div_rand_round(max_damage * gdr, 100)); return max(damage - saved, 0); - case AC_NORMAL: + case ac_type::normal: saved = random2(1 + ac); break; - case AC_HALF: + case ac_type::half: saved = random2(1 + ac) / 2; ac /= 2; gdr /= 2; break; - case AC_TRIPLE: + case ac_type::triple: saved = random2(1 + ac); saved += random2(1 + ac); saved += random2(1 + ac); diff --git a/crawl-ref/source/actor.h b/crawl-ref/source/actor.h index dbd1f9dd2459..350e74cb3c2c 100644 --- a/crawl-ref/source/actor.h +++ b/crawl-ref/source/actor.h @@ -260,8 +260,9 @@ class actor virtual int armour_class(bool calc_unid = true) const = 0; virtual int gdr_perc() const = 0; - int apply_ac(int damage, int max_damage = 0, ac_type ac_rule = AC_NORMAL, - int stab_bypass = 0, bool for_real = true) const; + int apply_ac(int damage, int max_damage = 0, + ac_type ac_rule = ac_type::normal, int stab_bypass = 0, + bool for_real = true) const; virtual int evasion(ev_ignore_type ign = ev_ignore::none, const actor *attacker = nullptr) const = 0; virtual bool shielded() const = 0; diff --git a/crawl-ref/source/attack.cc b/crawl-ref/source/attack.cc index 44c658ff1e5f..aaa1df02797c 100644 --- a/crawl-ref/source/attack.cc +++ b/crawl-ref/source/attack.cc @@ -1351,7 +1351,7 @@ int attack::apply_defender_ac(int damage, int damage_max) const stab_bypass = random2(div_rand_round(stab_bypass, 100 * stab_bonus)); } int after_ac = defender->apply_ac(damage, damage_max, - AC_NORMAL, stab_bypass); + ac_type::normal, stab_bypass); dprf(DIAG_COMBAT, "AC: att: %s, def: %s, ac: %d, gdr: %d, dam: %d -> %d", attacker->name(DESC_PLAIN, true).c_str(), defender->name(DESC_PLAIN, true).c_str(), diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc index 8782f8bacb5a..a212075562e5 100644 --- a/crawl-ref/source/beam.cc +++ b/crawl-ref/source/beam.cc @@ -4020,11 +4020,11 @@ int bolt::apply_AC(const actor *victim, int hurted) switch (flavour) { case BEAM_DAMNATION: - ac_rule = AC_NONE; break; + ac_rule = ac_type::none; break; case BEAM_ELECTRICITY: - ac_rule = AC_HALF; break; + ac_rule = ac_type::half; break; case BEAM_FRAG: - ac_rule = AC_TRIPLE; break; + ac_rule = ac_type::triple; break; default: ; } diff --git a/crawl-ref/source/beam.h b/crawl-ref/source/beam.h index 0d6006c20429..10b443565317 100644 --- a/crawl-ref/source/beam.h +++ b/crawl-ref/source/beam.h @@ -105,7 +105,7 @@ struct bolt // FROST etc so that we can change mulch rate // Do we draw animations? bool animate = bool(Options.use_animations & UA_BEAM); - ac_type ac_rule = AC_NORMAL; // How defender's AC affects damage. + ac_type ac_rule = ac_type::normal; // How defender's AC affects damage. #ifdef DEBUG_DIAGNOSTICS bool quiet_debug = false; // Disable any debug spam. #endif diff --git a/crawl-ref/source/fineff.cc b/crawl-ref/source/fineff.cc index da87cf80a48b..dacccc8c996e 100644 --- a/crawl-ref/source/fineff.cc +++ b/crawl-ref/source/fineff.cc @@ -472,7 +472,7 @@ void shock_serpent_discharge_fineff::fire() int amount = roll_dice(3, 4 + power * 3 / 2); amount = oppressor.apply_ac(oppressor.beam_resists(beam, amount, true), - 0, AC_HALF); + 0, ac_type::half); oppressor.hurt(serpent, amount, beam.flavour, KILLED_BY_BEAM, "a shock serpent", "electric aura"); if (amount) diff --git a/crawl-ref/source/melee-attack.cc b/crawl-ref/source/melee-attack.cc index 3cc2975ddd4a..f8271484eb5f 100644 --- a/crawl-ref/source/melee-attack.cc +++ b/crawl-ref/source/melee-attack.cc @@ -2980,7 +2980,7 @@ void melee_attack::mons_apply_attack_flavour() if (attacker->type == MONS_FIRE_VORTEX) attacker->as_monster()->suicide(-10); - special_damage = defender->apply_ac(base_damage, 0, AC_HALF); + special_damage = defender->apply_ac(base_damage, 0, ac_type::half); special_damage = resist_adjust_damage(defender, BEAM_FIRE, special_damage); diff --git a/crawl-ref/source/spl-damage.cc b/crawl-ref/source/spl-damage.cc index 24a04725c764..3e0d1a8a72ed 100644 --- a/crawl-ref/source/spl-damage.cc +++ b/crawl-ref/source/spl-damage.cc @@ -2306,7 +2306,7 @@ spret cast_thunderbolt(actor *caster, int pow, coord_def aim, bool fail) beam.colour = LIGHTCYAN; beam.range = 1; beam.hit = AUTOMATIC_HIT; - beam.ac_rule = AC_PROPORTIONAL; + beam.ac_rule = ac_type::proportional; beam.set_agent(caster); #ifdef USE_TILE beam.tile_beam = -1; @@ -2423,7 +2423,7 @@ void forest_damage(const actor *mon) "A root lunges up near @foe@"); } else if (!(dmg = foe->apply_ac(hd + random2(hd), hd * 2 - 1, - AC_PROPORTIONAL))) + ac_type::proportional))) { msg = random_choose( "@foe@ @is@ scraped by a branch", diff --git a/crawl-ref/source/spl-tornado.cc b/crawl-ref/source/spl-tornado.cc index b906c7892df9..2f23b8b1d185 100644 --- a/crawl-ref/source/spl-tornado.cc +++ b/crawl-ref/source/spl-tornado.cc @@ -386,7 +386,7 @@ void tornado_damage(actor *caster, int dur, bool is_vortex) { int dmg = victim->apply_ac( div_rand_round(roll_dice(9, rpow), 15), - 0, AC_PROPORTIONAL); + 0, ac_type::proportional); dprf("damage done: %d", dmg); victim->hurt(caster, dmg, BEAM_AIR, KILLED_BY_BEAM, "", "tornado"); From 5d75ef2713de3394a16d2dfae4fcfc44b644e817 Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Fri, 18 Jan 2019 12:58:02 +0000 Subject: [PATCH 149/864] Convert `enum area_centre_type` to an enum class The enum class retains this same long name. Ideally we would shorten the name of this enum class: area_centre is already taken by a struct though. --- crawl-ref/source/areas.cc | 33 +++++++++++++++++---------------- crawl-ref/source/areas.h | 25 +++++++++++++------------ crawl-ref/source/colour.cc | 9 +++++---- 3 files changed, 35 insertions(+), 32 deletions(-) diff --git a/crawl-ref/source/areas.cc b/crawl-ref/source/areas.cc index f3f1c5d27849..caf9bf5d9aa6 100644 --- a/crawl-ref/source/areas.cc +++ b/crawl-ref/source/areas.cc @@ -95,7 +95,7 @@ static void _actor_areas(actor *a) if ((r = a->silence_radius()) >= 0) { - _agrid_centres.emplace_back(AREA_SILENCE, a->pos(), r); + _agrid_centres.emplace_back(area_centre_type::silence, a->pos(), r); for (radius_iterator ri(a->pos(), r, C_SQUARE); ri; ++ri) _set_agrid_flag(*ri, areaprop::silence); @@ -104,7 +104,7 @@ static void _actor_areas(actor *a) if ((r = a->halo_radius()) >= 0) { - _agrid_centres.emplace_back(AREA_HALO, a->pos(), r); + _agrid_centres.emplace_back(area_centre_type::halo, a->pos(), r); for (radius_iterator ri(a->pos(), r, C_SQUARE, LOS_DEFAULT); ri; ++ri) _set_agrid_flag(*ri, areaprop::halo); @@ -113,7 +113,7 @@ static void _actor_areas(actor *a) if ((r = a->liquefying_radius()) >= 0) { - _agrid_centres.emplace_back(AREA_LIQUID, a->pos(), r); + _agrid_centres.emplace_back(area_centre_type::liquid, a->pos(), r); for (radius_iterator ri(a->pos(), r, C_SQUARE, LOS_SOLID); ri; ++ri) { @@ -129,7 +129,7 @@ static void _actor_areas(actor *a) if ((r = a->umbra_radius()) >= 0) { - _agrid_centres.emplace_back(AREA_UMBRA, a->pos(), r); + _agrid_centres.emplace_back(area_centre_type::umbra, a->pos(), r); for (radius_iterator ri(a->pos(), r, C_SQUARE, LOS_DEFAULT); ri; ++ri) _set_agrid_flag(*ri, areaprop::umbra); @@ -163,7 +163,7 @@ static void _update_agrid() if (player_has_orb() && !you.pos().origin()) { const int r = 2; - _agrid_centres.emplace_back(AREA_ORB, you.pos(), r); + _agrid_centres.emplace_back(area_centre_type::orb, you.pos(), r); for (radius_iterator ri(you.pos(), r, C_SQUARE, LOS_DEFAULT); ri; ++ri) _set_agrid_flag(*ri, areaprop::orb); no_areas = false; @@ -172,7 +172,7 @@ static void _update_agrid() if (you.duration[DUR_QUAD_DAMAGE]) { const int r = 2; - _agrid_centres.emplace_back(AREA_QUAD, you.pos(), r); + _agrid_centres.emplace_back(area_centre_type::quad, you.pos(), r); for (radius_iterator ri(you.pos(), r, C_SQUARE); ri; ++ri) { @@ -185,7 +185,8 @@ static void _update_agrid() if (you.duration[DUR_DISJUNCTION]) { const int r = 4; - _agrid_centres.emplace_back(AREA_DISJUNCTION, you.pos(), r); + _agrid_centres.emplace_back(area_centre_type::disjunction, + you.pos(), r); for (radius_iterator ri(you.pos(), r, C_SQUARE); ri; ++ri) { @@ -211,22 +212,22 @@ static area_centre_type _get_first_area(const coord_def& f) { areaprops a = _agrid(f); if (a & areaprop::sanctuary_1) - return AREA_SANCTUARY; + return area_centre_type::sanctuary; if (a & areaprop::sanctuary_2) - return AREA_SANCTUARY; + return area_centre_type::sanctuary; if (a & areaprop::silence) - return AREA_SILENCE; + return area_centre_type::silence; if (a & areaprop::halo) - return AREA_HALO; + return area_centre_type::halo; if (a & areaprop::umbra) - return AREA_UMBRA; + return area_centre_type::umbra; // liquid is always applied; actual_liquid is on top // of this. If we find the first, we don't care about // the second. if (a & areaprop::liquid) - return AREA_LIQUID; + return area_centre_type::liquid; - return AREA_NONE; + return area_centre_type::none; } coord_def find_centre_for(const coord_def& f, area_centre_type at) @@ -248,11 +249,11 @@ coord_def find_centre_for(const coord_def& f, area_centre_type at) // Unspecified area type; settle for the first valid one. // We checked for no aprop a bit ago. - if (at == AREA_NONE) + if (at == area_centre_type::none) at = _get_first_area(f); // on the off chance that there is an error, assert here - ASSERT(at != AREA_NONE); + ASSERT(at != area_centre_type::none); for (const area_centre &a : _agrid_centres) { diff --git a/crawl-ref/source/areas.h b/crawl-ref/source/areas.h index 491ccaca4ccc..8f56d3bf20a1 100644 --- a/crawl-ref/source/areas.h +++ b/crawl-ref/source/areas.h @@ -1,18 +1,18 @@ #pragma once -enum area_centre_type +enum class area_centre_type { - AREA_NONE, - AREA_SANCTUARY, - AREA_SILENCE, - AREA_HALO, - AREA_LIQUID, - AREA_ORB, - AREA_UMBRA, - AREA_QUAD, - AREA_DISJUNCTION, + none, + sanctuary, + silence, + halo, + liquid, + orb, + umbra, + quad, + disjunction, #if TAG_MAJOR_VERSION == 34 - AREA_HOT, + hot, #endif }; @@ -25,7 +25,8 @@ void create_sanctuary(const coord_def& center, int time); bool remove_sanctuary(bool did_attack = false); void decrease_sanctuary_radius(); -coord_def find_centre_for (const coord_def& f, area_centre_type at = AREA_NONE); +coord_def find_centre_for(const coord_def& f, + area_centre_type at = area_centre_type::none); bool silenced(const coord_def& p); diff --git a/crawl-ref/source/colour.cc b/crawl-ref/source/colour.cc index 4cafa456ae0e..0ba7afa6da9a 100644 --- a/crawl-ref/source/colour.cc +++ b/crawl-ref/source/colour.cc @@ -199,11 +199,12 @@ static int _etc_elemental(int, const coord_def& loc) int get_disjunct_phase(const coord_def& loc) { static int turns = you.num_turns; - static coord_def centre = find_centre_for(loc, AREA_DISJUNCTION); + static coord_def centre = find_centre_for(loc, + area_centre_type::disjunction); if (turns != you.num_turns || (centre-loc).abs() > 15) { - centre = find_centre_for(loc, AREA_DISJUNCTION); + centre = find_centre_for(loc, area_centre_type::disjunction); turns = you.num_turns; } @@ -236,11 +237,11 @@ static int _etc_disjunction(int, const coord_def& loc) static int _etc_liquefied(int, const coord_def& loc) { static int turns = you.num_turns; - static coord_def centre = find_centre_for(loc, AREA_LIQUID); + static coord_def centre = find_centre_for(loc, area_centre_type::liquid); if (turns != you.num_turns || (centre-loc).abs() > 15) { - centre = find_centre_for(loc, AREA_LIQUID); + centre = find_centre_for(loc, area_centre_type::liquid); turns = you.num_turns; } From 6e6263181cbae0ffbf08409b99cabe63d75e60dd Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Fri, 18 Jan 2019 13:51:32 +0000 Subject: [PATCH 150/864] Convert `enum branch_flag_type` to `enum class brflag` The name of the enum class changes to be significantly shorter, so that references to members of the enum class are of a similar length to before. Additionally, add a new bitfield type to use for the member variable Branch::branch_flags - this type is called branch_flags_t. Convert some uses of bitwise and to use testbits, where the raw bitwise and will now fail to compile (in return statements and variable definitions). --- crawl-ref/source/branch-data.h | 78 +++++++++++++++++----------------- crawl-ref/source/branch.cc | 2 +- crawl-ref/source/branch.h | 23 +++++----- crawl-ref/source/dbg-maps.cc | 2 +- crawl-ref/source/dungeon.cc | 10 ++--- crawl-ref/source/player.cc | 2 +- crawl-ref/source/traps.cc | 8 ++-- 7 files changed, 63 insertions(+), 62 deletions(-) diff --git a/crawl-ref/source/branch-data.h b/crawl-ref/source/branch-data.h index 66818dc80921..873a7001b7b4 100644 --- a/crawl-ref/source/branch-data.h +++ b/crawl-ref/source/branch-data.h @@ -13,7 +13,7 @@ const Branch branches[NUM_BRANCHES] = // travel shortcut, runes, ambient noise level { BRANCH_DUNGEON, NUM_BRANCHES, 0, 0, 15, 0, - BFLAG_NONE, + brflag::none, NUM_FEATURES, DNGN_EXIT_DUNGEON, NUM_FEATURES, "Dungeon", "the Dungeon", "D", nullptr, @@ -21,7 +21,7 @@ const Branch branches[NUM_BRANCHES] = 'D', {}, branch_noise::normal }, { BRANCH_TEMPLE, BRANCH_DUNGEON, 4, 7, 1, 5, - BFLAG_NO_ITEMS, + brflag::no_items, DNGN_ENTER_TEMPLE, DNGN_EXIT_TEMPLE, NUM_FEATURES, "Temple", "the Ecumenical Temple", "Temple", nullptr, @@ -29,7 +29,7 @@ const Branch branches[NUM_BRANCHES] = 'T', {}, branch_noise::normal }, { BRANCH_ORC, BRANCH_DUNGEON, 9, 12, 2, 10, - BFLAG_SPOTTY, + brflag::spotty, DNGN_ENTER_ORC, DNGN_EXIT_ORC, NUM_FEATURES, "Orcish Mines", "the Orcish Mines", "Orc", nullptr, @@ -37,7 +37,7 @@ const Branch branches[NUM_BRANCHES] = 'O', {}, branch_noise::normal }, { BRANCH_ELF, BRANCH_ORC, 2, 2, 3, 15, - BFLAG_DANGEROUS_END, + brflag::dangerous_end, DNGN_ENTER_ELF, DNGN_EXIT_ELF, NUM_FEATURES, "Elven Halls", "the Elven Halls", "Elf", nullptr, @@ -46,7 +46,7 @@ const Branch branches[NUM_BRANCHES] = #if TAG_MAJOR_VERSION == 34 { BRANCH_DWARF, BRANCH_ELF, -1, -1, 0, 17, - BFLAG_NONE, + brflag::none, DNGN_ENTER_DWARF, DNGN_EXIT_DWARF, NUM_FEATURES, "Dwarven Hall", "the Dwarven Hall", "Dwarf", nullptr, @@ -55,7 +55,7 @@ const Branch branches[NUM_BRANCHES] = #endif { BRANCH_LAIR, BRANCH_DUNGEON, 8, 11, 6, 10, - BFLAG_NONE, + brflag::none, DNGN_ENTER_LAIR, DNGN_EXIT_LAIR, NUM_FEATURES, "Lair", "the Lair of Beasts", "Lair", nullptr, @@ -63,7 +63,7 @@ const Branch branches[NUM_BRANCHES] = 'L', {}, branch_noise::normal }, { BRANCH_SWAMP, BRANCH_LAIR, 2, 4, 4, 15, - BFLAG_DANGEROUS_END | BFLAG_SPOTTY, + brflag::dangerous_end | brflag::spotty, DNGN_ENTER_SWAMP, DNGN_EXIT_SWAMP, NUM_FEATURES, "Swamp", "the Swamp", "Swamp", nullptr, @@ -71,7 +71,7 @@ const Branch branches[NUM_BRANCHES] = 'S', { RUNE_SWAMP }, branch_noise::normal }, { BRANCH_SHOALS, BRANCH_LAIR, 2, 4, 4, 15, - BFLAG_DANGEROUS_END, + brflag::dangerous_end, DNGN_ENTER_SHOALS, DNGN_EXIT_SHOALS, NUM_FEATURES, "Shoals", "the Shoals", "Shoals", nullptr, @@ -79,7 +79,7 @@ const Branch branches[NUM_BRANCHES] = 'A', { RUNE_SHOALS }, branch_noise::loud }, { BRANCH_SNAKE, BRANCH_LAIR, 2, 4, 4, 15, - BFLAG_DANGEROUS_END, + brflag::dangerous_end, DNGN_ENTER_SNAKE, DNGN_EXIT_SNAKE, NUM_FEATURES, "Snake Pit", "the Snake Pit", "Snake", nullptr, @@ -87,7 +87,7 @@ const Branch branches[NUM_BRANCHES] = 'P', { RUNE_SNAKE }, branch_noise::normal }, { BRANCH_SPIDER, BRANCH_LAIR, 2, 4, 4, 15, - BFLAG_DANGEROUS_END, + brflag::dangerous_end, DNGN_ENTER_SPIDER, DNGN_EXIT_SPIDER, NUM_FEATURES, "Spider Nest", "the Spider Nest", "Spider", nullptr, @@ -95,7 +95,7 @@ const Branch branches[NUM_BRANCHES] = 'N', { RUNE_SPIDER }, branch_noise::normal }, { BRANCH_SLIME, BRANCH_LAIR, 5, 6, 5, 17, - BFLAG_NO_ITEMS | BFLAG_DANGEROUS_END | BFLAG_SPOTTY, + brflag::no_items | brflag::dangerous_end | brflag::spotty, DNGN_ENTER_SLIME, DNGN_EXIT_SLIME, NUM_FEATURES, "Slime Pits", "the Pits of Slime", "Slime", nullptr, @@ -103,7 +103,7 @@ const Branch branches[NUM_BRANCHES] = 'M', { RUNE_SLIME }, branch_noise::quiet }, { BRANCH_VAULTS, BRANCH_DUNGEON, 13, 14, 5, 19, - BFLAG_DANGEROUS_END, + brflag::dangerous_end, DNGN_ENTER_VAULTS, DNGN_EXIT_VAULTS, NUM_FEATURES, "Vaults", "the Vaults", "Vaults", nullptr, @@ -112,7 +112,7 @@ const Branch branches[NUM_BRANCHES] = #if TAG_MAJOR_VERSION == 34 { BRANCH_BLADE, BRANCH_VAULTS, 3, 4, 1, 21, - BFLAG_NO_ITEMS, + brflag::no_items, DNGN_ENTER_BLADE, DNGN_EXIT_BLADE, NUM_FEATURES, "Hall of Blades", "the Hall of Blades", "Blade", nullptr, @@ -121,7 +121,7 @@ const Branch branches[NUM_BRANCHES] = #endif { BRANCH_CRYPT, BRANCH_VAULTS, 2, 3, 3, 19, - BFLAG_DANGEROUS_END, + brflag::dangerous_end, DNGN_ENTER_CRYPT, DNGN_EXIT_CRYPT, NUM_FEATURES, "Crypt", "the Crypt", "Crypt", nullptr, @@ -129,7 +129,7 @@ const Branch branches[NUM_BRANCHES] = 'C', {}, branch_noise::quiet }, { BRANCH_TOMB, BRANCH_CRYPT, 3, 3, 3, 21, - BFLAG_ISLANDED | BFLAG_DANGEROUS_END | BFLAG_NO_SHAFTS, + brflag::islanded | brflag::dangerous_end | brflag::no_shafts, DNGN_ENTER_TOMB, DNGN_EXIT_TOMB, NUM_FEATURES, "Tomb", "the Tomb of the Ancients", "Tomb", nullptr, @@ -138,7 +138,7 @@ const Branch branches[NUM_BRANCHES] = #if TAG_MAJOR_VERSION > 34 { BRANCH_DEPTHS, BRANCH_DUNGEON, 15, 15, 5, 22, - BFLAG_NONE, + brflag::none, DNGN_ENTER_DEPTHS, DNGN_EXIT_DEPTHS, NUM_FEATURES, "Depths", "the Depths", "Depths", nullptr, @@ -147,7 +147,7 @@ const Branch branches[NUM_BRANCHES] = #endif { BRANCH_VESTIBULE, NUM_BRANCHES, 27, 27, 1, 27, - BFLAG_NO_ITEMS, + brflag::no_items, DNGN_ENTER_HELL, DNGN_EXIT_HELL, NUM_FEATURES, "Hell", "the Vestibule of Hell", "Hell", "Welcome to Hell!\nPlease enjoy your stay.", @@ -155,7 +155,7 @@ const Branch branches[NUM_BRANCHES] = 'H', {}, branch_noise::normal }, { BRANCH_DIS, BRANCH_VESTIBULE, 1, 1, 7, 28, - BFLAG_NO_ITEMS | BFLAG_DANGEROUS_END, + brflag::no_items | brflag::dangerous_end, DNGN_ENTER_DIS, DNGN_ENTER_HELL, DNGN_ENTER_HELL, "Dis", "the Iron City of Dis", "Dis", nullptr, @@ -163,7 +163,7 @@ const Branch branches[NUM_BRANCHES] = 'I', { RUNE_DIS }, branch_noise::normal }, { BRANCH_GEHENNA, BRANCH_VESTIBULE, 1, 1, 7, 28, - BFLAG_NO_ITEMS | BFLAG_DANGEROUS_END, + brflag::no_items | brflag::dangerous_end, DNGN_ENTER_GEHENNA, DNGN_ENTER_HELL, DNGN_ENTER_HELL, "Gehenna", "Gehenna", "Geh", nullptr, @@ -171,7 +171,7 @@ const Branch branches[NUM_BRANCHES] = 'G', { RUNE_GEHENNA }, branch_noise::normal }, { BRANCH_COCYTUS, BRANCH_VESTIBULE, 1, 1, 7, 28, - BFLAG_NO_ITEMS | BFLAG_DANGEROUS_END, + brflag::no_items | brflag::dangerous_end, DNGN_ENTER_COCYTUS, DNGN_ENTER_HELL, DNGN_ENTER_HELL, "Cocytus", "Cocytus", "Coc", nullptr, @@ -179,7 +179,7 @@ const Branch branches[NUM_BRANCHES] = 'X', { RUNE_COCYTUS }, branch_noise::normal }, { BRANCH_TARTARUS, BRANCH_VESTIBULE, 1, 1, 7, 28, - BFLAG_NO_ITEMS | BFLAG_DANGEROUS_END, + brflag::no_items | brflag::dangerous_end, DNGN_ENTER_TARTARUS, DNGN_ENTER_HELL, DNGN_ENTER_HELL, "Tartarus", "Tartarus", "Tar", nullptr, @@ -187,7 +187,7 @@ const Branch branches[NUM_BRANCHES] = 'Y', { RUNE_TARTARUS }, branch_noise::normal }, { BRANCH_ZOT, BRANCH_DEPTHS, 5, 5, 5, 27, - BFLAG_DANGEROUS_END, + brflag::dangerous_end, DNGN_ENTER_ZOT, DNGN_EXIT_ZOT, NUM_FEATURES, "Zot", "the Realm of Zot", "Zot", "Welcome to the Realm of Zot!\n" @@ -197,7 +197,7 @@ const Branch branches[NUM_BRANCHES] = #if TAG_MAJOR_VERSION == 34 { BRANCH_FOREST, BRANCH_VAULTS, 2, 3, 5, 19, - BFLAG_SPOTTY, + brflag::spotty, DNGN_ENTER_FOREST, DNGN_EXIT_FOREST, NUM_FEATURES, "Forest", "the Enchanted Forest", "Forest", nullptr, @@ -206,7 +206,7 @@ const Branch branches[NUM_BRANCHES] = #endif { BRANCH_ABYSS, NUM_BRANCHES, -1, -1, 5, 24, - BFLAG_NO_XLEV_TRAVEL | BFLAG_NO_MAP, + brflag::no_x_level_travel | brflag::no_map, DNGN_ENTER_ABYSS, DNGN_EXIT_ABYSS, DNGN_FLOOR, // can't get trapped in abyss "Abyss", "the Abyss", "Abyss", nullptr, @@ -214,7 +214,7 @@ const Branch branches[NUM_BRANCHES] = 'J', { RUNE_ABYSSAL }, branch_noise::normal }, { BRANCH_PANDEMONIUM, NUM_BRANCHES, -1, -1, 1, 24, - BFLAG_NO_XLEV_TRAVEL, + brflag::no_x_level_travel, DNGN_ENTER_PANDEMONIUM, DNGN_EXIT_PANDEMONIUM, DNGN_TRANSIT_PANDEMONIUM, "Pandemonium", "Pandemonium", "Pan", "You enter the halls of Pandemonium!\n" @@ -224,7 +224,7 @@ const Branch branches[NUM_BRANCHES] = RUNE_GLOORX_VLOQ }, branch_noise::normal }, { BRANCH_ZIGGURAT, BRANCH_DEPTHS, 1, 5, 27, 27, - BFLAG_NO_XLEV_TRAVEL | BFLAG_NO_ITEMS, + brflag::no_x_level_travel | brflag::no_items, DNGN_ENTER_ZIGGURAT, DNGN_EXIT_ZIGGURAT, DNGN_FLOOR, "Ziggurat", "a ziggurat", "Zig", "You land on top of a ziggurat so tall you cannot make out the ground.", @@ -233,7 +233,7 @@ const Branch branches[NUM_BRANCHES] = #if TAG_MAJOR_VERSION == 34 { BRANCH_LABYRINTH, NUM_BRANCHES, -1, -1, 1, 15, - BFLAG_NO_XLEV_TRAVEL | BFLAG_NO_ITEMS, + brflag::no_x_level_travel | brflag::no_items, DNGN_ENTER_LABYRINTH, DNGN_EXIT_LABYRINTH, DNGN_EXIT_THROUGH_ABYSS, "Labyrinth", "a Labyrinth", "Lab", "You enter a labyrinth!", @@ -242,7 +242,7 @@ const Branch branches[NUM_BRANCHES] = #endif { BRANCH_BAZAAR, NUM_BRANCHES, -1, -1, 1, 18, - BFLAG_NO_XLEV_TRAVEL | BFLAG_NO_ITEMS, + brflag::no_x_level_travel | brflag::no_items, DNGN_ENTER_BAZAAR, DNGN_EXIT_BAZAAR, NUM_FEATURES, "Bazaar", "a bazaar", "Bazaar", "You enter an inter-dimensional bazaar!", @@ -250,7 +250,7 @@ const Branch branches[NUM_BRANCHES] = '1', {}, branch_noise::normal }, { BRANCH_TROVE, NUM_BRANCHES, -1, -1, 1, 18, - BFLAG_NO_XLEV_TRAVEL | BFLAG_NO_ITEMS, + brflag::no_x_level_travel | brflag::no_items, DNGN_ENTER_TROVE, DNGN_EXIT_TROVE, NUM_FEATURES, "Trove", "a treasure trove", "Trove", "You enter a treasure trove!", @@ -258,7 +258,7 @@ const Branch branches[NUM_BRANCHES] = '2', {}, branch_noise::normal }, { BRANCH_SEWER, NUM_BRANCHES, -1, -1, 1, 4, - BFLAG_NO_XLEV_TRAVEL | BFLAG_NO_ITEMS, + brflag::no_x_level_travel | brflag::no_items, DNGN_ENTER_SEWER, DNGN_EXIT_SEWER, NUM_FEATURES, "Sewer", "a sewer", "Sewer", "You enter a sewer!", @@ -266,7 +266,7 @@ const Branch branches[NUM_BRANCHES] = '3', {}, branch_noise::normal }, { BRANCH_OSSUARY, NUM_BRANCHES, -1, -1, 1, 6, - BFLAG_NO_XLEV_TRAVEL | BFLAG_NO_ITEMS, + brflag::no_x_level_travel | brflag::no_items, DNGN_ENTER_OSSUARY, DNGN_EXIT_OSSUARY, NUM_FEATURES, "Ossuary", "an ossuary", "Ossuary", "You enter an ossuary!", @@ -274,7 +274,7 @@ const Branch branches[NUM_BRANCHES] = '4', {}, branch_noise::normal }, { BRANCH_BAILEY, NUM_BRANCHES, -1, -1, 1, 11, - BFLAG_NO_XLEV_TRAVEL | BFLAG_NO_ITEMS, + brflag::no_x_level_travel | brflag::no_items, DNGN_ENTER_BAILEY, DNGN_EXIT_BAILEY, NUM_FEATURES, "Bailey", "a bailey", "Bailey", "You enter a bailey!", @@ -283,7 +283,7 @@ const Branch branches[NUM_BRANCHES] = #if TAG_MAJOR_VERSION > 34 { BRANCH_GAUNTLET, NUM_BRANCHES, -1, -1, 1, 15, - BFLAG_NO_XLEV_TRAVEL | BFLAG_NO_ITEMS, + brflag::no_x_level_travel | brflag::no_items, DNGN_ENTER_GAUNTLET, DNGN_EXIT_GAUNTLET, DNGN_EXIT_THROUGH_ABYSS, "Gauntlet", "a Gauntlet", "Gauntlet", "You enter a gauntlet!", @@ -292,7 +292,7 @@ const Branch branches[NUM_BRANCHES] = #endif { BRANCH_ICE_CAVE, NUM_BRANCHES, -1, -1, 1, 15, - BFLAG_NO_XLEV_TRAVEL | BFLAG_NO_ITEMS, + brflag::no_x_level_travel | brflag::no_items, DNGN_ENTER_ICE_CAVE, DNGN_EXIT_ICE_CAVE, NUM_FEATURES, "Ice Cave", "an ice cave", "IceCv", "You enter an ice cave!", @@ -305,7 +305,7 @@ const Branch branches[NUM_BRANCHES] = #endif { BRANCH_VOLCANO, NUM_BRANCHES, -1, -1, 1, 14, - BFLAG_NO_XLEV_TRAVEL | BFLAG_NO_ITEMS, + brflag::no_x_level_travel | brflag::no_items, DNGN_ENTER_VOLCANO, DNGN_EXIT_VOLCANO, NUM_FEATURES, "Volcano", "a volcano", "Volcano", "You enter a volcano!", @@ -318,7 +318,7 @@ const Branch branches[NUM_BRANCHES] = #endif { BRANCH_WIZLAB, NUM_BRANCHES, -1, -1, 1, 24, - BFLAG_NO_XLEV_TRAVEL | BFLAG_NO_ITEMS, + brflag::no_x_level_travel | brflag::no_items, DNGN_ENTER_WIZLAB, DNGN_EXIT_WIZLAB, NUM_FEATURES, "Wizlab", "a wizard's laboratory", "WizLab", "You enter a wizard's laboratory!", @@ -332,7 +332,7 @@ const Branch branches[NUM_BRANCHES] = #if TAG_MAJOR_VERSION == 34 { BRANCH_DEPTHS, BRANCH_DUNGEON, 15, 15, 5, 22, - BFLAG_NONE, + brflag::none, DNGN_ENTER_DEPTHS, DNGN_EXIT_DEPTHS, NUM_FEATURES, "Depths", "the Depths", "Depths", nullptr, @@ -341,7 +341,7 @@ const Branch branches[NUM_BRANCHES] = #endif { BRANCH_DESOLATION, NUM_BRANCHES, -1, -1, 1, 20, - BFLAG_NO_XLEV_TRAVEL | BFLAG_NO_ITEMS, + brflag::no_x_level_travel | brflag::no_items, DNGN_ENTER_DESOLATION, DNGN_EXIT_DESOLATION, NUM_FEATURES, // TODO "Desolation", "the Desolation of Salt", "Desolation", "You enter a great desolation of salt!", @@ -355,7 +355,7 @@ const Branch branches[NUM_BRANCHES] = #if TAG_MAJOR_VERSION == 34 { BRANCH_GAUNTLET, NUM_BRANCHES, -1, -1, 1, 15, - BFLAG_NO_XLEV_TRAVEL | BFLAG_NO_ITEMS, + brflag::no_x_level_travel | brflag::no_items, DNGN_ENTER_GAUNTLET, DNGN_EXIT_GAUNTLET, DNGN_EXIT_THROUGH_ABYSS, "Gauntlet", "a Gauntlet", "Gauntlet", "You enter a gauntlet!", diff --git a/crawl-ref/source/branch.cc b/crawl-ref/source/branch.cc index 0c4817f90a05..99410ce521f7 100644 --- a/crawl-ref/source/branch.cc +++ b/crawl-ref/source/branch.cc @@ -188,7 +188,7 @@ bool is_random_subbranch(branch_type branch) bool is_connected_branch(const Branch *branch) { - return !(branch->branch_flags & BFLAG_NO_XLEV_TRAVEL); + return !testbits(branch->branch_flags, brflag::no_x_level_travel); } bool is_connected_branch(branch_type branch) diff --git a/crawl-ref/source/branch.h b/crawl-ref/source/branch.h index cc2474d2d5d7..805a3504dee6 100644 --- a/crawl-ref/source/branch.h +++ b/crawl-ref/source/branch.h @@ -12,18 +12,19 @@ #define BRANCH_NOISE_AMOUNT 6 -enum branch_flag_type +enum class brflag { - BFLAG_NONE = 0, - - BFLAG_NO_MAP = (1 << 0), // Can't be magic mapped or remembered. - BFLAG_ISLANDED = (1 << 1), // May have isolated zones with no stairs. - BFLAG_NO_XLEV_TRAVEL = (1 << 2), // Can't cross-level travel to or from it. - BFLAG_NO_ITEMS = (1 << 3), // Branch gets no random items. - BFLAG_DANGEROUS_END = (1 << 4), // bottom level is more dangerous than normal - BFLAG_SPOTTY = (1 << 5), // Connect vaults with more open paths, not hallways. - BFLAG_NO_SHAFTS = (1 << 6), // Don't generate random shafts. + none = 0, + + no_map = (1 << 0), // Can't be magic mapped or remembered. + islanded = (1 << 1), // May have isolated zones with no stairs. + no_x_level_travel = (1 << 2), // Can't cross-level travel to or from it. + no_items = (1 << 3), // Branch gets no random items. + dangerous_end = (1 << 4), // bottom level is more dangerous than normal + spotty = (1 << 5), // Connect vaults with more open paths, not hallways. + no_shafts = (1 << 6), // Don't generate random shafts. }; +DEF_BITFIELD(branch_flags_t, brflag); enum class branch_noise { @@ -43,7 +44,7 @@ struct Branch int numlevels; // depth of the branch int absdepth; // base item generation/etc depth - uint32_t branch_flags; + branch_flags_t branch_flags; dungeon_feature_type entry_stairs; dungeon_feature_type exit_stairs; diff --git a/crawl-ref/source/dbg-maps.cc b/crawl-ref/source/dbg-maps.cc index 45eb5e75dd98..9edac687eaa2 100644 --- a/crawl-ref/source/dbg-maps.cc +++ b/crawl-ref/source/dbg-maps.cc @@ -63,7 +63,7 @@ static bool _is_disconnected_level() { // Don't care about non-Dungeon levels. if (!player_in_connected_branch() - || (branches[you.where_are_you].branch_flags & BFLAG_ISLANDED)) + || (branches[you.where_are_you].branch_flags & brflag::islanded)) { return false; } diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 4bfc50ff90b6..658ed5b9c772 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -1320,7 +1320,7 @@ void dgn_reset_level(bool enable_random_maps) static int _num_items_wanted(int absdepth0) { - if (branches[you.where_are_you].branch_flags & BFLAG_NO_ITEMS) + if (branches[you.where_are_you].branch_flags & brflag::no_items) return 0; else if (absdepth0 > 5 && one_chance_in(500 - 5 * absdepth0)) return 10 + random2avg(90, 2); // rich level! @@ -1910,7 +1910,7 @@ static bool _add_connecting_escape_hatches() // For any regions without a down stone stair case, add an // escape hatch. This will always allow (downward) progress. - if (branches[you.where_are_you].branch_flags & BFLAG_ISLANDED) + if (branches[you.where_are_you].branch_flags & brflag::islanded) return true; // Veto D:1 or Pan if there are disconnected areas. @@ -1993,7 +1993,7 @@ static void _dgn_verify_connectivity(unsigned nvaults) // Also check for isolated regions that have no stairs. if (player_in_connected_branch() - && !(branches[you.where_are_you].branch_flags & BFLAG_ISLANDED) + && !(branches[you.where_are_you].branch_flags & brflag::islanded) && dgn_count_disconnected_zones(true) > 0) { throw dgn_veto_exception("Isolated areas with no stairs."); @@ -4222,7 +4222,7 @@ static const vault_placement *_build_vault_impl(const map_def *vault, if (!make_no_exits) { const bool spotty = - branches[you.where_are_you].branch_flags & BFLAG_SPOTTY; + testbits(branches[you.where_are_you].branch_flags, brflag::spotty); if (place.connect(spotty) == 0 && place.exits.size() > 0 && !player_in_branch(BRANCH_ABYSS)) { @@ -6436,7 +6436,7 @@ static bool _fixup_interlevel_connectivity() if (!player_in_connected_branch() || brdepth[you.where_are_you] == -1) return true; - if (branches[you.where_are_you].branch_flags & BFLAG_ISLANDED) + if (branches[you.where_are_you].branch_flags & brflag::islanded) return true; StairConnectivity prev_con; diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index cd04e09e50bb..4364f50f1d1a 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -549,7 +549,7 @@ bool is_feat_dangerous(dungeon_feature_type grid, bool permanently, bool is_map_persistent() { - return !(your_branch().branch_flags & BFLAG_NO_MAP) + return !testbits(your_branch().branch_flags, brflag::no_map) || env.properties.exists(FORCE_MAPPABLE_KEY); } diff --git a/crawl-ref/source/traps.cc b/crawl-ref/source/traps.cc index 817519ce3524..1eec140bfb0d 100644 --- a/crawl-ref/source/traps.cc +++ b/crawl-ref/source/traps.cc @@ -1300,7 +1300,7 @@ bool is_valid_shaft_level() const Branch &branch = branches[place.branch]; - if (branch.branch_flags & BFLAG_NO_SHAFTS) + if (branch.branch_flags & brflag::no_shafts) return false; // Don't allow shafts from the bottom of a branch. @@ -1320,7 +1320,7 @@ bool is_valid_shaft_effect_level() // Don't shaft the player when we can't, and also when it would be into a // dangerous end. return is_valid_shaft_level() - && !(branch.branch_flags & BFLAG_DANGEROUS_END + && !(testbits(branch.branch_flags, brflag::dangerous_end) && brdepth[place.branch] - place.depth == 1); } @@ -1346,7 +1346,7 @@ static level_id _generic_shaft_dest(level_pos lpos, bool known = false) // Only shafts on the level immediately above a dangerous branch // bottom will take you to that dangerous bottom. - if (branches[lid.branch].branch_flags & BFLAG_DANGEROUS_END + if (branches[lid.branch].branch_flags & brflag::dangerous_end && lid.depth == max_depth && (max_depth - curr_depth) > 1) { @@ -1384,7 +1384,7 @@ void do_trap_effects() // Don't shaft the player when we can't, and also when it would be into a // dangerous end. if (is_valid_shaft_level() - && !(branch.branch_flags & BFLAG_DANGEROUS_END + && !(branch.branch_flags & brflag::dangerous_end && brdepth[place.branch] - place.depth == 1)) { dprf("Attempting to shaft player."); From 176abe67a9ddabc956fd244e5ba9fe43f3921dc8 Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Fri, 18 Jan 2019 14:05:42 +0000 Subject: [PATCH 151/864] Convert `enum cleansing_flame_source_type` to an enum class Turn this enum into the enum class cleansing_flame_source. Also convert the functions cleansing_flame and setup_cleansing_flame_beam to use type cleansing_flame_source instead of type int, as this is now mandatory. --- crawl-ref/source/ability.cc | 2 +- crawl-ref/source/cleansing-flame-source-type.h | 11 ++++++----- crawl-ref/source/god-wrath.cc | 2 +- crawl-ref/source/mon-cast.cc | 5 +++-- crawl-ref/source/spl-goditem.cc | 10 ++++++---- crawl-ref/source/spl-goditem.h | 6 ++++-- 6 files changed, 21 insertions(+), 15 deletions(-) diff --git a/crawl-ref/source/ability.cc b/crawl-ref/source/ability.cc index e92472c37303..3ce2675ad650 100644 --- a/crawl-ref/source/ability.cc +++ b/crawl-ref/source/ability.cc @@ -2280,7 +2280,7 @@ static spret _do_ability(const ability_def& abil, bool fail) } fail_check(); cleansing_flame(10 + you.skill_rdiv(SK_INVOCATIONS, 7, 6), - CLEANSING_FLAME_INVOCATION, you.pos(), &you); + cleansing_flame_source::invocation, you.pos(), &you); break; } diff --git a/crawl-ref/source/cleansing-flame-source-type.h b/crawl-ref/source/cleansing-flame-source-type.h index 4b2b34a78d6c..d8b3dce7a8f9 100644 --- a/crawl-ref/source/cleansing-flame-source-type.h +++ b/crawl-ref/source/cleansing-flame-source-type.h @@ -1,9 +1,10 @@ #pragma once -enum cleansing_flame_source_type +// Cleansing flame sources +enum class cleansing_flame_source { - CLEANSING_FLAME_GENERIC = -1, - CLEANSING_FLAME_SPELL = -2, // SPELL_FLAME_OF_CLEANSING - CLEANSING_FLAME_INVOCATION = -3, // ABIL_TSO_CLEANSING_FLAME - CLEANSING_FLAME_TSO = -4, // TSO effect + generic = -1, + spell = -2, // SPELL_FLAME_OF_CLEANSING + invocation = -3, // ABIL_TSO_CLEANSING_FLAME + tso = -4, // TSO effect }; diff --git a/crawl-ref/source/god-wrath.cc b/crawl-ref/source/god-wrath.cc index 4842dee62054..818fe7b03be6 100644 --- a/crawl-ref/source/god-wrath.cc +++ b/crawl-ref/source/god-wrath.cc @@ -1810,7 +1810,7 @@ static void _tso_blasts_cleansing_flame(const char *message) // damage is 2d(pow), *3/2 for undead and demonspawn cleansing_flame(5 + (you.experience_level * 7) / 12, - CLEANSING_FLAME_TSO, you.pos()); + cleansing_flame_source::tso, you.pos()); } static void _god_smites_you(god_type god, const char *message, diff --git a/crawl-ref/source/mon-cast.cc b/crawl-ref/source/mon-cast.cc index 272021eafec4..03bcacaf5d48 100644 --- a/crawl-ref/source/mon-cast.cc +++ b/crawl-ref/source/mon-cast.cc @@ -6816,7 +6816,7 @@ void mons_cast(monster* mons, bolt pbolt, spell_type spell_cast, case SPELL_CLEANSING_FLAME: simple_monster_message(*mons, " channels a blast of cleansing flame!"); cleansing_flame(5 + (5 * mons->spell_hd(spell_cast) / 12), - CLEANSING_FLAME_SPELL, mons->pos(), mons); + cleansing_flame_source::spell, mons->pos(), mons); return; case SPELL_GRAVITAS: @@ -8091,7 +8091,8 @@ static bool _ms_waste_of_time(monster* mon, mon_spell_slot slot) bolt tracer; setup_cleansing_flame_beam(tracer, 5 + (7 * mon->spell_hd(monspell)) / 12, - CLEANSING_FLAME_SPELL, mon->pos(), mon); + cleansing_flame_source::spell, + mon->pos(), mon); fire_tracer(mon, tracer, true); return !mons_should_fire(tracer); } diff --git a/crawl-ref/source/spl-goditem.cc b/crawl-ref/source/spl-goditem.cc index 0ccaf0b5dea9..3da8aa63efcf 100644 --- a/crawl-ref/source/spl-goditem.cc +++ b/crawl-ref/source/spl-goditem.cc @@ -1303,7 +1303,8 @@ void torment(actor *attacker, torment_source_type taux, const coord_def& where) torment_cell(*ri, attacker, taux); } -void setup_cleansing_flame_beam(bolt &beam, int pow, int caster, +void setup_cleansing_flame_beam(bolt &beam, int pow, + cleansing_flame_source caster, coord_def where, actor *attacker) { beam.flavour = BEAM_HOLY; @@ -1312,13 +1313,14 @@ void setup_cleansing_flame_beam(bolt &beam, int pow, int caster, beam.target = where; beam.name = "golden flame"; beam.colour = YELLOW; - beam.aux_source = (caster == CLEANSING_FLAME_TSO) + beam.aux_source = (caster == cleansing_flame_source::tso) ? "the Shining One's cleansing flame" : "cleansing flame"; beam.ex_size = 2; beam.is_explosion = true; - if (caster == CLEANSING_FLAME_GENERIC || caster == CLEANSING_FLAME_TSO) + if (caster == cleansing_flame_source::generic + || caster == cleansing_flame_source::tso) { beam.thrower = KILL_MISC; beam.source_id = MID_NOBODY; @@ -1339,7 +1341,7 @@ void setup_cleansing_flame_beam(bolt &beam, int pow, int caster, } } -void cleansing_flame(int pow, int caster, coord_def where, +void cleansing_flame(int pow, cleansing_flame_source caster, coord_def where, actor *attacker) { bolt beam; diff --git a/crawl-ref/source/spl-goditem.h b/crawl-ref/source/spl-goditem.h index ecf60da05d55..ab95a10b2d78 100644 --- a/crawl-ref/source/spl-goditem.h +++ b/crawl-ref/source/spl-goditem.h @@ -1,5 +1,6 @@ #pragma once +#include "cleansing-flame-source-type.h" #include "enchant-type.h" #include "holy-word-source-type.h" #include "spell-type.h" @@ -79,9 +80,10 @@ void torment(actor *attacker, torment_source_type taux, const coord_def& where); void torment_cell(coord_def where, actor *attacker, torment_source_type taux); void torment_player(actor *attacker, torment_source_type taux); -void setup_cleansing_flame_beam(bolt &beam, int pow, int caster, +void setup_cleansing_flame_beam(bolt &beam, int pow, + cleansing_flame_source caster, coord_def where, actor *attacker = nullptr); -void cleansing_flame(int pow, int caster, coord_def where, +void cleansing_flame(int pow, cleansing_flame_source caster, coord_def where, actor *attacker = nullptr); spret cast_random_effects(int pow, bolt& beam, bool fail); From c5fff3c665738e3d06d3c77b8c72989b23ce29e2 Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Fri, 18 Jan 2019 16:12:18 +0000 Subject: [PATCH 152/864] Convert `enum confirm_prompt_type` to an enum class The enum class retains the same name, in line with confirm_butcher_type. --- crawl-ref/source/confirm-prompt-type.h | 8 ++++---- crawl-ref/source/directn.cc | 16 +++++++++------- crawl-ref/source/directn.h | 2 +- crawl-ref/source/evoke.cc | 6 +++--- crawl-ref/source/god-abil.cc | 14 +++++++------- crawl-ref/source/initfile.cc | 8 ++++---- crawl-ref/source/spl-cast.cc | 4 ++-- crawl-ref/source/spl-goditem.cc | 2 +- 8 files changed, 31 insertions(+), 29 deletions(-) diff --git a/crawl-ref/source/confirm-prompt-type.h b/crawl-ref/source/confirm-prompt-type.h index 286d910896aa..6202792204f3 100644 --- a/crawl-ref/source/confirm-prompt-type.h +++ b/crawl-ref/source/confirm-prompt-type.h @@ -1,8 +1,8 @@ #pragma once -enum confirm_prompt_type +enum class confirm_prompt_type { - CONFIRM_CANCEL, // automatically answer 'no', i.e. disallow - CONFIRM_PROMPT, // prompt - CONFIRM_NONE, // automatically answer 'yes' + cancel, // automatically answer 'no', i.e. disallow + prompt, // prompt + none, // automatically answer 'yes' }; diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc index a93abc33544b..fbde6e26e4a9 100644 --- a/crawl-ref/source/directn.cc +++ b/crawl-ref/source/directn.cc @@ -899,21 +899,23 @@ bool direction_chooser::move_is_ok() const { if (!targets_objects() && targets_enemies()) { - if (self == CONFIRM_CANCEL - || self == CONFIRM_PROMPT - && Options.allow_self_target == CONFIRM_CANCEL) + if (self == confirm_prompt_type::cancel + || self == confirm_prompt_type::prompt + && Options.allow_self_target + == confirm_prompt_type::cancel) { mprf(MSGCH_EXAMINE_FILTER, "That would be overly suicidal."); return false; } - else if (self != CONFIRM_NONE - && Options.allow_self_target != CONFIRM_NONE) + else if (self != confirm_prompt_type::none + && Options.allow_self_target + != confirm_prompt_type::none) { return yesno("Really target yourself?", false, 'n'); } } - if (self == CONFIRM_CANCEL) + if (self == confirm_prompt_type::cancel) { mprf(MSGCH_EXAMINE_FILTER, "Sorry, you can't target yourself."); return false; @@ -1075,7 +1077,7 @@ coord_def direction_chooser::find_default_target() const LS_FLIPVH); } else if ((mode != TARG_ANY && mode != TARG_FRIEND) - || self == CONFIRM_CANCEL) + || self == confirm_prompt_type::cancel) { success = find_default_monster_target(result); } diff --git a/crawl-ref/source/directn.h b/crawl-ref/source/directn.h index 6b31eb61f62d..36c260e56b87 100644 --- a/crawl-ref/source/directn.h +++ b/crawl-ref/source/directn.h @@ -106,7 +106,7 @@ struct direction_chooser_args just_looking(false), needs_path(true), unrestricted(false), - self(CONFIRM_PROMPT), + self(confirm_prompt_type::prompt), target_prefix(nullptr), behaviour(nullptr), show_floor_desc(false), diff --git a/crawl-ref/source/evoke.cc b/crawl-ref/source/evoke.cc index cf90fb572bef..557834bf02f7 100644 --- a/crawl-ref/source/evoke.cc +++ b/crawl-ref/source/evoke.cc @@ -98,7 +98,7 @@ static bool _reaching_weapon_attack(const item_def& wpn) args.mode = TARG_HOSTILE; args.range = reach_range; args.top_prompt = "Attack whom?"; - args.self = CONFIRM_CANCEL; + args.self = confirm_prompt_type::cancel; unique_ptr hitfunc; if (reach_range == REACH_TWO) @@ -1011,7 +1011,7 @@ static bool _lamp_of_fire() args.restricts = DIR_TARGET; args.mode = TARG_HOSTILE; args.top_prompt = "Aim the lamp in which direction?"; - args.self = CONFIRM_CANCEL; + args.self = confirm_prompt_type::cancel; if (spell_direction(target, base_beam, &args)) { if (you.confused()) @@ -1389,7 +1389,7 @@ static spret _phantom_mirror() direction_chooser_args args; args.restricts = DIR_TARGET; args.needs_path = false; - args.self = CONFIRM_CANCEL; + args.self = confirm_prompt_type::cancel; args.top_prompt = "Aiming: Phantom Mirror"; args.hitfunc = &tgt; if (!spell_direction(spd, beam, &args)) diff --git a/crawl-ref/source/god-abil.cc b/crawl-ref/source/god-abil.cc index 5f4f0f3d99e5..bc43e628b9f6 100644 --- a/crawl-ref/source/god-abil.cc +++ b/crawl-ref/source/god-abil.cc @@ -1570,7 +1570,7 @@ bool beogh_gift_item() args.mode = TARG_BEOGH_GIFTABLE; args.range = LOS_RADIUS; args.needs_path = false; - args.self = CONFIRM_CANCEL; + args.self = confirm_prompt_type::cancel; args.show_floor_desc = true; args.top_prompt = "Select a follower to give a gift to."; @@ -3301,7 +3301,7 @@ spret fedhas_evolve_flora(bool fail) args.mode = TARG_EVOLVABLE_PLANTS; args.range = LOS_RADIUS; args.needs_path = false; - args.self = CONFIRM_CANCEL; + args.self = confirm_prompt_type::cancel; args.show_floor_desc = true; args.top_prompt = "Select plant or fungus to evolve."; args.get_desc_func = _evolution_name; @@ -4673,7 +4673,7 @@ spret qazlal_upheaval(coord_def target, bool quiet, bool fail) args.mode = TARG_HOSTILE; args.needs_path = false; args.top_prompt = "Aiming: Upheaval"; - args.self = CONFIRM_CANCEL; + args.self = confirm_prompt_type::cancel; args.hitfunc = &tgt; if (!spell_direction(spd, beam, &args)) return spret::abort; @@ -6169,7 +6169,7 @@ bool ru_power_leap() args.range = 3; args.needs_path = false; args.top_prompt = "Aiming: Power Leap"; - args.self = CONFIRM_CANCEL; + args.self = confirm_prompt_type::cancel; const int explosion_size = 1; targeter_smite tgt(&you, args.range, explosion_size, explosion_size); tgt.obeys_mesmerise = true; @@ -6675,7 +6675,7 @@ spret uskayaw_grand_finale(bool fail) args.mode = TARG_HOSTILE; args.needs_path = false; args.top_prompt = "Aiming: Grand Finale"; - args.self = CONFIRM_CANCEL; + args.self = confirm_prompt_type::cancel; targeter_smite tgt(&you); args.hitfunc = &tgt; direction(beam, args); @@ -6875,7 +6875,7 @@ static coord_def _get_transference_target() args.mode = TARG_MOBILE_MONSTER; args.range = LOS_RADIUS; args.needs_path = false; - args.self = CONFIRM_NONE; + args.self = confirm_prompt_type::none; args.show_floor_desc = true; args.top_prompt = "Select a target."; @@ -7292,7 +7292,7 @@ spret wu_jian_wall_jump_ability() args.range = 1; args.needs_path = false; // TODO: overridden by hitfunc? args.top_prompt = "Aiming: Wall Jump"; - args.self = CONFIRM_CANCEL; + args.self = confirm_prompt_type::cancel; targeter_walljump tgt; tgt.obeys_mesmerise = true; args.hitfunc = &tgt; diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index ba2562c184b5..a9b1c0b99a93 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -1044,7 +1044,7 @@ void game_options::reset_options() confirm_butcher = CONFIRM_AUTO; auto_butcher = HS_VERY_HUNGRY; easy_confirm = CONFIRM_SAFE_EASY; - allow_self_target = CONFIRM_PROMPT; + allow_self_target = confirm_prompt_type::prompt; skill_focus = SKM_FOCUS_ON; user_note_prefix = ""; @@ -2641,11 +2641,11 @@ void game_options::read_option_line(const string &str, bool runscript) else if (key == "allow_self_target") { if (field == "yes") - allow_self_target = CONFIRM_NONE; + allow_self_target = confirm_prompt_type::none; else if (field == "no") - allow_self_target = CONFIRM_CANCEL; + allow_self_target = confirm_prompt_type::cancel; else if (field == "prompt") - allow_self_target = CONFIRM_PROMPT; + allow_self_target = confirm_prompt_type::prompt; } else if (key == "confirm_butcher") { diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc index d6bb7ee3609b..6b70bf273640 100644 --- a/crawl-ref/source/spl-cast.cc +++ b/crawl-ref/source/spl-cast.cc @@ -1403,9 +1403,9 @@ spret your_spells(spell_type spell, int powc, bool allow_fail, args.show_boring_feats = false; // don't show "The floor." } if (testbits(flags, spflag::not_self)) - args.self = CONFIRM_CANCEL; + args.self = confirm_prompt_type::cancel; else - args.self = CONFIRM_NONE; + args.self = confirm_prompt_type::none; args.get_desc_func = additional_desc; if (!spell_direction(spd, beam, &args)) return spret::abort; diff --git a/crawl-ref/source/spl-goditem.cc b/crawl-ref/source/spl-goditem.cc index 3da8aa63efcf..308cbbdc1069 100644 --- a/crawl-ref/source/spl-goditem.cc +++ b/crawl-ref/source/spl-goditem.cc @@ -327,7 +327,7 @@ spret cast_healing(int pow, bool fail) args.restricts = DIR_TARGET; args.mode = TARG_INJURED_FRIEND; args.needs_path = false; - args.self = CONFIRM_CANCEL; + args.self = confirm_prompt_type::cancel; args.target_prefix = "Heal"; args.get_desc_func = bind(_desc_pacify_chance, placeholders::_1, pow); direction(spd, args); From 24134c8637665b8a9a6e6d80bdf79700bad58e22 Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Fri, 18 Jan 2019 16:43:18 +0000 Subject: [PATCH 153/864] Convert `enum tide_direction` to `enum class tide_dir` --- crawl-ref/source/dgn-shoals.cc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/crawl-ref/source/dgn-shoals.cc b/crawl-ref/source/dgn-shoals.cc index 15b496e0304e..cca4901e3f50 100644 --- a/crawl-ref/source/dgn-shoals.cc +++ b/crawl-ref/source/dgn-shoals.cc @@ -64,13 +64,13 @@ enum shoals_height_thresholds SHT_SHALLOW_WATER = -30, }; -enum tide_direction +enum class tide_dir { - TIDE_RISING, - TIDE_FALLING, + rising, + falling, }; -static tide_direction _shoals_tide_direction; +static tide_dir _shoals_tide_direction; static monster* tide_caller = nullptr; static coord_def tide_caller_pos; static int tide_called_turns = 0; @@ -858,7 +858,7 @@ static void _shoals_apply_tide_feature_at( // Determines if the tide is rising or falling based on before and // after features at the same square. -static tide_direction _shoals_feature_tide_height_change( +static tide_dir _shoals_feature_tide_height_change( dungeon_feature_type oldfeat, dungeon_feature_type newfeat) { @@ -866,7 +866,7 @@ static tide_direction _shoals_feature_tide_height_change( _shoals_feature_height(newfeat) - _shoals_feature_height(oldfeat); // If the apparent height of the new feature is greater (floor vs water), // the tide is receding. - return height_delta < 0 ? TIDE_RISING : TIDE_FALLING; + return height_delta < 0 ? tide_dir::rising : tide_dir::falling; } static void _shoals_apply_tide_at(coord_def c, int tide, bool incremental_tide) @@ -1064,7 +1064,7 @@ void shoals_apply_tides(int turns_elapsed, bool force, bool incremental_tide) || old_tide / TIDE_MULTIPLIER != tide / TIDE_MULTIPLIER) { _shoals_tide_direction = - tide > old_tide ? TIDE_RISING : TIDE_FALLING; + tide > old_tide ? tide_dir::rising : tide_dir::falling; _shoals_apply_tide(tide / TIDE_MULTIPLIER, incremental_tide); } } @@ -1103,7 +1103,7 @@ static void _shoals_force_tide(CrawlHashTable &props, int increment) tide += increment * TIDE_MULTIPLIER; tide = min(HIGH_TIDE, max(LOW_TIDE, tide)); props[PROPS_SHOALS_TIDE_KEY] = short(tide); - _shoals_tide_direction = increment > 0 ? TIDE_RISING : TIDE_FALLING; + _shoals_tide_direction = increment > 0 ? tide_dir::rising : tide_dir::falling; _shoals_apply_tide(tide / TIDE_MULTIPLIER, false); } From 5908fbaaba2c0dafe05e4162bd2ad86d84db3d79 Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Fri, 18 Jan 2019 16:15:08 +0000 Subject: [PATCH 154/864] Rename confirm-level-type.h to easy-confirm-type.h The following commit changes the enum to an enum class and its name to easy_confirm_type. These are done in separate commits because otherwise git pretends confirm-level-type.h and easy-confirm-type.h were deleted and created, respectively, rather than it simply being a rename. --- crawl-ref/source/{confirm-level-type.h => easy-confirm-type.h} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename crawl-ref/source/{confirm-level-type.h => easy-confirm-type.h} (100%) diff --git a/crawl-ref/source/confirm-level-type.h b/crawl-ref/source/easy-confirm-type.h similarity index 100% rename from crawl-ref/source/confirm-level-type.h rename to crawl-ref/source/easy-confirm-type.h From bbb2dcfae6b64bfed6a3fe2bd2872e2ee8fbe00b Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Fri, 18 Jan 2019 16:19:54 +0000 Subject: [PATCH 155/864] Convert `enum confirm_level_type` to `enum class easy_confirm_type` --- crawl-ref/source/MSVC/crawl.vcxproj | 2 +- crawl-ref/source/MSVC/crawl.vcxproj.filters | 6 +++--- crawl-ref/source/easy-confirm-type.h | 8 ++++---- crawl-ref/source/initfile.cc | 8 ++++---- crawl-ref/source/options.h | 4 ++-- crawl-ref/source/prompt.cc | 10 ++++++---- 6 files changed, 20 insertions(+), 18 deletions(-) diff --git a/crawl-ref/source/MSVC/crawl.vcxproj b/crawl-ref/source/MSVC/crawl.vcxproj index e18497dcd914..355cd1ea661c 100644 --- a/crawl-ref/source/MSVC/crawl.vcxproj +++ b/crawl-ref/source/MSVC/crawl.vcxproj @@ -874,7 +874,6 @@ perl.exe "util/gen-cflg.pl" compflag.h "<UNKNOWN>" "<UNKNOWN>" - @@ -918,6 +917,7 @@ perl.exe "util/gen-cflg.pl" compflag.h "<UNKNOWN>" "<UNKNOWN>" + diff --git a/crawl-ref/source/MSVC/crawl.vcxproj.filters b/crawl-ref/source/MSVC/crawl.vcxproj.filters index 439b2809a94e..1c12a6bfb42e 100644 --- a/crawl-ref/source/MSVC/crawl.vcxproj.filters +++ b/crawl-ref/source/MSVC/crawl.vcxproj.filters @@ -1092,9 +1092,6 @@ h - - h - h @@ -1218,6 +1215,9 @@ h + + h + h diff --git a/crawl-ref/source/easy-confirm-type.h b/crawl-ref/source/easy-confirm-type.h index 47fb74037a84..ac8a07ec3311 100644 --- a/crawl-ref/source/easy-confirm-type.h +++ b/crawl-ref/source/easy-confirm-type.h @@ -1,8 +1,8 @@ #pragma once -enum confirm_level_type +enum class easy_confirm_type { - CONFIRM_NONE_EASY, - CONFIRM_SAFE_EASY, - CONFIRM_ALL_EASY, + none, + safe, + all, }; diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index a9b1c0b99a93..b996c7f0c727 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -1043,7 +1043,7 @@ void game_options::reset_options() confirm_butcher = CONFIRM_AUTO; auto_butcher = HS_VERY_HUNGRY; - easy_confirm = CONFIRM_SAFE_EASY; + easy_confirm = easy_confirm_type::safe; allow_self_target = confirm_prompt_type::prompt; skill_focus = SKM_FOCUS_ON; @@ -2632,11 +2632,11 @@ void game_options::read_option_line(const string &str, bool runscript) { // decide when to allow both 'Y'/'N' and 'y'/'n' on yesno() prompts if (field == "none") - easy_confirm = CONFIRM_NONE_EASY; + easy_confirm = easy_confirm_type::none; else if (field == "safe") - easy_confirm = CONFIRM_SAFE_EASY; + easy_confirm = easy_confirm_type::safe; else if (field == "all") - easy_confirm = CONFIRM_ALL_EASY; + easy_confirm = easy_confirm_type::all; } else if (key == "allow_self_target") { diff --git a/crawl-ref/source/options.h b/crawl-ref/source/options.h index dbaec3ad6c82..958381784883 100644 --- a/crawl-ref/source/options.h +++ b/crawl-ref/source/options.h @@ -4,8 +4,8 @@ #include "activity-interrupt-type.h" #include "char-set-type.h" -#include "confirm-level-type.h" #include "confirm-prompt-type.h" +#include "easy-confirm-type.h" #include "feature.h" #include "flang-t.h" #include "flush-reason-type.h" @@ -246,7 +246,7 @@ struct game_options bool note_xom_effects; // take note of all Xom effects bool note_chat_messages; // log chat in Webtiles bool note_dgl_messages; // log chat in DGL - confirm_level_type easy_confirm; // make yesno() confirming easier + easy_confirm_type easy_confirm; // make yesno() confirming easier bool easy_quit_item_prompts; // make item prompts quitable on space confirm_prompt_type allow_self_target; // yes, no, prompt bool simple_targeting; // disable smart spell targeting diff --git a/crawl-ref/source/prompt.cc b/crawl-ref/source/prompt.cc index 274781d4405f..3b1217134e05 100644 --- a/crawl-ref/source/prompt.cc +++ b/crawl-ref/source/prompt.cc @@ -131,9 +131,10 @@ bool yesno(const char *str, bool allow_lowercase, int default_answer, bool clear tmp = default_answer; } - if (Options.easy_confirm == CONFIRM_ALL_EASY + if (Options.easy_confirm == easy_confirm_type::all || tmp == default_answer - || Options.easy_confirm == CONFIRM_SAFE_EASY && allow_lowercase) + || Options.easy_confirm == easy_confirm_type::safe + && allow_lowercase) { tmp = toupper(tmp); } @@ -243,9 +244,10 @@ int yesnoquit(const char* str, bool allow_lowercase, int default_answer, bool al if ((tmp == ' ' || tmp == '\r' || tmp == '\n') && default_answer) tmp = default_answer; - if (Options.easy_confirm == CONFIRM_ALL_EASY + if (Options.easy_confirm == easy_confirm_type::all || tmp == default_answer - || allow_lowercase && Options.easy_confirm == CONFIRM_SAFE_EASY) + || allow_lowercase + && Options.easy_confirm == easy_confirm_type::safe) { tmp = toupper(tmp); } From b23cc65123ff4ad7e5785228dd616615d1b7eece Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Fri, 18 Jan 2019 16:31:53 +0000 Subject: [PATCH 156/864] Change `enum activity_interrupt_payload_type` to `enum class ai_payload` Significantly shorten the enum class name in the process to make identifier names a reasonable length. AIP_INT and AIP_STRING are converted to ai_payload::int_payload and ai_payload::string_payload to avoid conflicting with type names. --- crawl-ref/source/cluautil.cc | 10 +++++----- crawl-ref/source/delay.cc | 2 +- crawl-ref/source/delay.h | 27 ++++++++++++++------------- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/crawl-ref/source/cluautil.cc b/crawl-ref/source/cluautil.cc index 940c7a20dfbe..422905eb64f7 100644 --- a/crawl-ref/source/cluautil.cc +++ b/crawl-ref/source/cluautil.cc @@ -9,22 +9,22 @@ int push_activity_interrupt(lua_State *ls, activity_interrupt_data *t) { switch (t->apt) { - case AIP_HP_LOSS: + case ai_payload::hp_loss: { lua_pushnumber(ls, t->ait_hp_loss_data->hp); lua_pushnumber(ls, t->ait_hp_loss_data->hurt_type); return 1; } - case AIP_INT: + case ai_payload::int_payload: lua_pushnumber(ls, *t->int_data); break; - case AIP_STRING: + case ai_payload::string_payload: lua_pushstring(ls, t->string_data); break; - case AIP_MONSTER: + case ai_payload::monster: push_monster(ls, t->mons_data); break; - case AIP_NONE: + case ai_payload::none: lua_pushnil(ls); break; } diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc index 879cd54f1211..6a05607453d3 100644 --- a/crawl-ref/source/delay.cc +++ b/crawl-ref/source/delay.cc @@ -1110,7 +1110,7 @@ static inline bool _monster_warning(activity_interrupt ai, if (at.context != SC_NEWLY_SEEN && !delay) return false; - ASSERT(at.apt == AIP_MONSTER); + ASSERT(at.apt == ai_payload::monster); monster* mon = at.mons_data; ASSERT(mon); if (!you.can_see(*mon)) diff --git a/crawl-ref/source/delay.h b/crawl-ref/source/delay.h index ee6b95cb0ddd..eff55285ce2a 100644 --- a/crawl-ref/source/delay.h +++ b/crawl-ref/source/delay.h @@ -16,18 +16,18 @@ class monster; struct ait_hp_loss; -enum activity_interrupt_payload_type +enum class ai_payload // activity interrupt payloads { - AIP_NONE, - AIP_INT, - AIP_STRING, - AIP_MONSTER, - AIP_HP_LOSS, + none, + int_payload, + string_payload, + monster, + hp_loss, }; struct activity_interrupt_data { - activity_interrupt_payload_type apt; + ai_payload apt; union { const char* string_data; @@ -40,27 +40,28 @@ struct activity_interrupt_data seen_context_type context; activity_interrupt_data() - : apt(AIP_NONE), no_data(nullptr), context(SC_NONE) + : apt(ai_payload::none), no_data(nullptr), context(SC_NONE) { } activity_interrupt_data(const int *i) - : apt(AIP_INT), int_data(i), context(SC_NONE) + : apt(ai_payload::int_payload), int_data(i), context(SC_NONE) { } activity_interrupt_data(const char *s) - : apt(AIP_STRING), string_data(s), context(SC_NONE) + : apt(ai_payload::string_payload), string_data(s), context(SC_NONE) { } activity_interrupt_data(const string &s) - : apt(AIP_STRING), string_data(s.c_str()), context(SC_NONE) + : apt(ai_payload::string_payload), string_data(s.c_str()), + context(SC_NONE) { } activity_interrupt_data(monster* m, seen_context_type ctx = SC_NONE) - : apt(AIP_MONSTER), mons_data(m), context(ctx) + : apt(ai_payload::monster), mons_data(m), context(ctx) { } activity_interrupt_data(const ait_hp_loss *ahl) - : apt(AIP_HP_LOSS), ait_hp_loss_data(ahl), context(SC_NONE) + : apt(ai_payload::hp_loss), ait_hp_loss_data(ahl), context(SC_NONE) { } }; From 36218c0b754a98aafed01e4915f3aa003a954fdc Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Fri, 18 Jan 2019 15:37:58 +0000 Subject: [PATCH 157/864] Convert `enum confirm_butcher_type` to an enum class The enum class retains the same name. It would be preferable to use something shorter, such as confirm_butcher, but this is already used as a member of Options, and changing this seems unnecessary. This change includes changing CONFIRM_AUTO to confirm_butcher_type::normal, because `auto` is a type and shouldn't be used for enum class members. [Committer's note: Closes #951] --- crawl-ref/source/butcher.cc | 4 ++-- crawl-ref/source/confirm-butcher-type.h | 8 ++++---- crawl-ref/source/initfile.cc | 8 ++++---- crawl-ref/source/options.h | 3 ++- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/crawl-ref/source/butcher.cc b/crawl-ref/source/butcher.cc index fb645c47bed3..75e2d0e4a501 100644 --- a/crawl-ref/source/butcher.cc +++ b/crawl-ref/source/butcher.cc @@ -206,8 +206,8 @@ void butchery(item_def* specific_corpse) // Butcher pre-chosen corpse, if found, or if there is only one corpse. if (specific_corpse || corpse_qualities.size() == 1 - && Options.confirm_butcher != CONFIRM_ALWAYS - || Options.confirm_butcher == CONFIRM_NEVER) + && Options.confirm_butcher != confirm_butcher_type::always + || Options.confirm_butcher == confirm_butcher_type::never) { //XXX: this assumes that we're not being called from a delay ourselves. if (_start_butchering(*corpse_qualities[0].first)) diff --git a/crawl-ref/source/confirm-butcher-type.h b/crawl-ref/source/confirm-butcher-type.h index 06103357fece..d5bb96308f35 100644 --- a/crawl-ref/source/confirm-butcher-type.h +++ b/crawl-ref/source/confirm-butcher-type.h @@ -1,8 +1,8 @@ #pragma once -enum confirm_butcher_type +enum class confirm_butcher_type { - CONFIRM_NEVER, - CONFIRM_ALWAYS, - CONFIRM_AUTO, + never, + always, + normal, }; diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index b996c7f0c727..8fc564f5ebf6 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -1041,7 +1041,7 @@ void game_options::reset_options() autopickups.set(OBJ_WANDS); autopickups.set(OBJ_FOOD); - confirm_butcher = CONFIRM_AUTO; + confirm_butcher = confirm_butcher_type::normal; auto_butcher = HS_VERY_HUNGRY; easy_confirm = easy_confirm_type::safe; allow_self_target = confirm_prompt_type::prompt; @@ -2650,11 +2650,11 @@ void game_options::read_option_line(const string &str, bool runscript) else if (key == "confirm_butcher") { if (field == "always") - confirm_butcher = CONFIRM_ALWAYS; + confirm_butcher = confirm_butcher_type::always; else if (field == "never") - confirm_butcher = CONFIRM_NEVER; + confirm_butcher = confirm_butcher_type::never; else if (field == "auto") - confirm_butcher = CONFIRM_AUTO; + confirm_butcher = confirm_butcher_type::normal; } else if (key == "auto_butcher") { diff --git a/crawl-ref/source/options.h b/crawl-ref/source/options.h index 958381784883..734e206eee2c 100644 --- a/crawl-ref/source/options.h +++ b/crawl-ref/source/options.h @@ -4,6 +4,7 @@ #include "activity-interrupt-type.h" #include "char-set-type.h" +#include "confirm-butcher-type.h" #include "confirm-prompt-type.h" #include "easy-confirm-type.h" #include "feature.h" @@ -232,7 +233,7 @@ struct game_options bool easy_door; // 'O', 'C' don't prompt with just one door. bool warn_hatches; // offer a y/n prompt when the player uses an escape hatch bool enable_recast_spell; // Allow recasting spells with 'z' Enter. - int confirm_butcher; // When to prompt for butchery + confirm_butcher_type confirm_butcher; // When to prompt for butchery hunger_state_t auto_butcher; // auto-butcher corpses while travelling bool easy_eat_chunks; // make 'e' auto-eat the oldest safe chunk bool auto_eat_chunks; // allow eating chunks while resting or travelling From 7c828743320302dce5962c2c96ff8e1f685472f6 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 4 Mar 2019 09:29:46 -0500 Subject: [PATCH 158/864] Add an extra digit to the seed choice input box (Siegurt) Until this is in stable, use the rc option `game_seed` or the command line option `-seed` to select a seed that needs the extra digit. --- crawl-ref/source/newgame.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 43ee7484a37e..acae4562d8f1 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -643,7 +643,8 @@ static void _choose_name(newgame_def& ng, newgame_def& choice) static void _choose_seed(newgame_def& ng, newgame_def& choice, const newgame_def& defaults) { - char buf[20]; // max unsigned 64 bit integer is 19 chars + char buf[21]; // max unsigned 64 bit integer is 20 chars in decimal, + // specifically 18446744073709551615 buf[0] = '\0'; resumable_line_reader reader(buf, sizeof(buf)); if (Options.seed) @@ -728,6 +729,8 @@ static void _choose_seed(newgame_def& ng, newgame_def& choice, string result = reader.get_text(); uint64_t tmp_seed = 0; + // TODO: if the user types in a number that exceeds the max value, sscanf + // will give back the max value. Probably better to print an error? int found = sscanf(result.c_str(), "%" SCNu64, &tmp_seed); if (cancel || crawl_state.seen_hups || !found || result.size() == 0) From f1ee1cdb4ee716c3e4f37ac1818bb71ac7e23339 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 4 Mar 2019 17:24:35 -0500 Subject: [PATCH 159/864] Allow debug.reset_rng to take a string for 128 bit seeds This isn't very elegant, but it gets around lua big number handling issues that I was otherwise having. --- crawl-ref/source/l-debug.cc | 21 +++++++++++++++++---- crawl-ref/source/test/vault_catalog.lua | 10 ++++++---- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/crawl-ref/source/l-debug.cc b/crawl-ref/source/l-debug.cc index 3386ce29359d..19fea9b92895 100644 --- a/crawl-ref/source/l-debug.cc +++ b/crawl-ref/source/l-debug.cc @@ -399,11 +399,24 @@ LUAFN(debug_reset_rng) { // call this with care... - // quick and dirty - use only 32 bit seeds - unsigned int seed = (unsigned int) luaL_checkint(ls, 1); - Options.seed = (uint64_t) seed; + if (lua_type(ls, 1) == LUA_TSTRING) + { + const char *seed_string = lua_tostring(ls, 1); + uint64_t tmp_seed = 0; + if (!sscanf(seed_string, "%" SCNu64, &tmp_seed)) + tmp_seed = 0; + Options.seed = tmp_seed; + } + else + { + // quick and dirty - use only 32 bit seeds + unsigned int seed = (unsigned int) luaL_checkint(ls, 1); + Options.seed = (uint64_t) seed; + } reset_rng(); - return 0; + const string ret = make_stringf("%" PRIu64, Options.seed); + lua_pushstring(ls, ret.c_str()); + return 1; } LUAFN(debug_get_rng_state) diff --git a/crawl-ref/source/test/vault_catalog.lua b/crawl-ref/source/test/vault_catalog.lua index 38e4a5ec0bd6..a9503bc56764 100644 --- a/crawl-ref/source/test/vault_catalog.lua +++ b/crawl-ref/source/test/vault_catalog.lua @@ -85,7 +85,7 @@ function compare_catalogs(order, run1, run2, seed) end function test_seed(seed, iters, order, quiet) - debug.reset_rng(seed) + seed_used = debug.reset_rng(seed) if quiet then crawl.stderr(".") else @@ -110,9 +110,11 @@ test_seed(starting_seed, per_seed_iters, generation_order, false) crawl.stderr("Checking some extended branches for seed " .. starting_seed .. "...") test_seed(starting_seed, per_seed_iters, generation_order_extended, true) -for i=starting_seed + 1, starting_seed + fixed_seeds - 1 do - crawl.stderr("Testing seed " .. i .. ".") - test_seed(i, per_seed_iters, generation_order, true) +if (type(starting_seed) ~= "string") then + for i=starting_seed + 1, starting_seed + fixed_seeds - 1 do + crawl.stderr("Testing seed " .. i .. ".") + test_seed(i, per_seed_iters, generation_order, true) + end end if rand_seeds > 0 then From fa3a8d60dbc7cd9abb3a193bce499daf431a0d5f Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 4 Mar 2019 23:30:10 -0500 Subject: [PATCH 160/864] Add a paste option to the seed ui for local tiles This is very ad-hoc and specific to the seed menu, but it'll do for now. Needs testing on windows/linux, but it's relying on SDL code so should work if that does. Also restrict text input for the seed text box to digits. --- crawl-ref/source/newgame.cc | 40 +++++++++++++++++++++++++-- crawl-ref/source/windowmanager-sdl.cc | 16 +++++++++++ crawl-ref/source/windowmanager-sdl.h | 2 ++ crawl-ref/source/windowmanager.h | 2 ++ 4 files changed, 57 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index acae4562d8f1..09a6beebbd88 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -640,6 +640,19 @@ static void _choose_name(newgame_def& ng, newgame_def& choice) #endif +static keyfun_action _keyfun_seed_input(int &ch) +{ + if (ch == CONTROL('K') || ch == CONTROL('D') || ch == CONTROL('W') || + ch == CONTROL('U') || ch == CONTROL('A') || ch == CONTROL('E') || + ch == CK_ENTER || ch == CK_BKSP || ch == CK_ESCAPE || + ch < 0 || // this should get all other special keys + isadigit(ch)) + { + return KEYFUN_PROCESS; + } + return KEYFUN_IGNORE; +} + static void _choose_seed(newgame_def& ng, newgame_def& choice, const newgame_def& defaults) { @@ -652,6 +665,7 @@ static void _choose_seed(newgame_def& ng, newgame_def& choice, else if (Options.seed_from_rc) choice.seed = Options.seed_from_rc; reader.set_text(make_stringf("%" PRIu64, choice.seed)); + reader.set_keyproc(_keyfun_seed_input); bool done = false; bool cancel = false; @@ -668,7 +682,7 @@ static void _choose_seed(newgame_def& ng, newgame_def& choice, choice.pregenerate = !choice.pregenerate; return done = false; } - if (key == 'd' || key == 'D') + else if (key == 'd' || key == 'D') { time_t now; struct tm * timeinfo; @@ -680,6 +694,19 @@ static void _choose_seed(newgame_def& ng, newgame_def& choice, reader.set_text(timebuf); return done = false; } +#ifdef USE_TILE_LOCAL + else if ((key == 'p' || key == 'P') && wm->has_clipboard()) + { + string clip = wm->get_clipboard(); + // try to avoid pasting in crazy garbage, by parsing as uint64 + // this could be done better + uint64_t clip_seed; + int clip_found = sscanf(clip.c_str(), "%" SCNu64, &clip_seed); + if (clip_found) + reader.set_text(make_stringf("%" PRIu64, clip_seed)); + return done = false; + } +#endif // TODO: digits only key = reader.putkey(key); @@ -708,8 +735,15 @@ static void _choose_seed(newgame_def& ng, newgame_def& choice, prompt.textcolour(LIGHTGREY); prompt.cprintf( "Choose 0 for a random seed. Press [d] for today's daily seed.\n" - "The seed will determine the dungeon layout, monsters,\n" - "and items that you discover.\n\n"); +#ifdef USE_TILE_LOCAL + "Press [p] to paste a seed from the clipboard (overwriting the\n" + "current value).\n" +#endif + "\n" + "The seed will determine the dungeon layout, monsters, and items\n" + "that you discover. Pregeneration will ensure that these remain\n" + "the same no matter what order you explore the dungeon in. (See\n" + "the manual for more details.)\n\n"); prompt.cprintf("Seed:"); string seed_text = make_stringf("%-20s", buf); prompt.cprintf("\n%s\n\n", seed_text.c_str()); diff --git a/crawl-ref/source/windowmanager-sdl.cc b/crawl-ref/source/windowmanager-sdl.cc index 5c524be10612..284cd4a2c581 100644 --- a/crawl-ref/source/windowmanager-sdl.cc +++ b/crawl-ref/source/windowmanager-sdl.cc @@ -711,6 +711,22 @@ unsigned short SDLWrapper::get_mouse_state(int *x, int *y) const return ret; } +string SDLWrapper::get_clipboard() +{ + string result; + char *clip = SDL_GetClipboardText(); + if (!clip) + return result; + result = string(clip); + SDL_free(clip); + return result; +} + +bool SDLWrapper::has_clipboard() +{ + return SDL_HasClipboardText() == SDL_TRUE; +} + static char32_t _key_suppresses_textinput(int keycode) { char result_char = 0; diff --git a/crawl-ref/source/windowmanager-sdl.h b/crawl-ref/source/windowmanager-sdl.h index 1e7b378c63ea..21fe18dc2f51 100644 --- a/crawl-ref/source/windowmanager-sdl.h +++ b/crawl-ref/source/windowmanager-sdl.h @@ -32,6 +32,8 @@ class SDLWrapper : public WindowManager virtual void set_mod_state(tiles_key_mod mod) override; virtual void set_mouse_cursor(mouse_cursor_type id) override; virtual unsigned short get_mouse_state(int *x, int *y) const override; + virtual string get_clipboard() override; + virtual bool has_clipboard() override; // System time functions virtual unsigned int set_timer(unsigned int interval, diff --git a/crawl-ref/source/windowmanager.h b/crawl-ref/source/windowmanager.h index 7d0272a5659d..1af2b78dcccf 100644 --- a/crawl-ref/source/windowmanager.h +++ b/crawl-ref/source/windowmanager.h @@ -154,6 +154,8 @@ class WindowManager virtual void set_mod_state(tiles_key_mod mod) = 0; virtual void set_mouse_cursor(mouse_cursor_type id) = 0; virtual unsigned short get_mouse_state(int *x, int *y) const = 0; + virtual string get_clipboard() = 0; + virtual bool has_clipboard() = 0; // System time functions virtual unsigned int set_timer(unsigned int interval, From 3f7990ae4ddb0e234c85aa0565bf6a2d59b45c24 Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 5 Mar 2019 00:14:06 -0500 Subject: [PATCH 161/864] Save game seed properly This was broken in 372e6d594387f, which caused the seed to save as 0 because of the timing of the call to the `player` constructor. After initial rng setup this value isn't used for anything meaningful (since what matters is the rng state itself), so its disappearance was entirely cosmetic -- but also very confusing to players. --- crawl-ref/source/ng-setup.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/source/ng-setup.cc b/crawl-ref/source/ng-setup.cc index 0710095ca098..972a3eaac68d 100644 --- a/crawl-ref/source/ng-setup.cc +++ b/crawl-ref/source/ng-setup.cc @@ -474,6 +474,7 @@ static void _setup_generic(const newgame_def& ng) { reset_rng(); // initialize rng from Options.seed _init_player(); + you.game_seed = crawl_state.seed; #if TAG_MAJOR_VERSION == 34 // Avoid the remove_dead_shops() Gozag fixup in new games: see From b74a2b47565df216dfee324586458fc1f758e854 Mon Sep 17 00:00:00 2001 From: Alex Jurkiewicz Date: Wed, 6 Mar 2019 05:10:31 +1100 Subject: [PATCH 162/864] TAG_MAJOR_VERSION improvements (#955) The program now almost compiles with TAG_MAJOR_VERSION=35. "Almost" because there are some changes that cannot be made compatible to both the current and the upcoming version. --- .gitignore | 2 + crawl-ref/source/ability.cc | 4 ++ crawl-ref/source/acquire.cc | 6 ++- crawl-ref/source/art-func.h | 6 +++ crawl-ref/source/artefact-prop-type.h | 3 ++ crawl-ref/source/artefact.cc | 5 +++ crawl-ref/source/daction-type.h | 3 +- crawl-ref/source/dactions.cc | 6 ++- crawl-ref/source/describe-god.cc | 4 ++ crawl-ref/source/describe-spells.cc | 5 ++- crawl-ref/source/describe.cc | 2 + crawl-ref/source/dungeon-feature-type.h | 1 + crawl-ref/source/end.cc | 2 + crawl-ref/source/evoke.cc | 59 +++++++++++++++++++++---- crawl-ref/source/feature-data.h | 2 + crawl-ref/source/god-abil.cc | 2 + crawl-ref/source/god-conduct.cc | 4 ++ crawl-ref/source/god-passive.cc | 2 + crawl-ref/source/god-type.h | 2 + crawl-ref/source/god-wrath.cc | 4 ++ crawl-ref/source/invent.cc | 5 ++- crawl-ref/source/item-name.cc | 2 + crawl-ref/source/item-prop-enum.h | 2 +- crawl-ref/source/items.cc | 2 + crawl-ref/source/lookup-help.cc | 4 +- crawl-ref/source/mapdef.cc | 2 +- crawl-ref/source/mon-cast.cc | 2 + crawl-ref/source/mon-death.cc | 23 +++++----- crawl-ref/source/mon-ench.cc | 6 ++- crawl-ref/source/mon-util.cc | 12 ++++- crawl-ref/source/ng-setup.cc | 4 +- crawl-ref/source/player-equip.cc | 4 ++ crawl-ref/source/player.cc | 2 + crawl-ref/source/religion.cc | 43 +++++++++++++++++- crawl-ref/source/rltiles/dc-item.txt | 16 +++++-- crawl-ref/source/showsymb.cc | 2 + crawl-ref/source/skills.cc | 2 + crawl-ref/source/spl-cast.cc | 14 ++++++ crawl-ref/source/spl-summoning.cc | 2 + crawl-ref/source/tags.cc | 4 ++ crawl-ref/source/terrain.cc | 2 + crawl-ref/source/transform.cc | 2 + crawl-ref/source/viewchar.cc | 9 +++- crawl-ref/source/wiz-item.cc | 5 ++- 44 files changed, 252 insertions(+), 43 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000000..a7e7e192da9d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.cquery_cache/ +.DS_Store diff --git a/crawl-ref/source/ability.cc b/crawl-ref/source/ability.cc index 3ce2675ad650..033134de4a68 100644 --- a/crawl-ref/source/ability.cc +++ b/crawl-ref/source/ability.cc @@ -2100,7 +2100,9 @@ static spret _do_ability(const ability_def& abil, bool fail) if (!invis_allowed()) return spret::abort; fail_check(); +#if TAG_MAJOR_VERSION == 34 surge_power(you.spec_evoke()); +#endif potionlike_effect(POT_INVISIBILITY, player_adjust_evoc_power( you.skill(SK_EVOCATIONS, 2) + 5)); @@ -2130,7 +2132,9 @@ static spret _do_ability(const ability_def& abil, bool fail) } else { +#if TAG_MAJOR_VERSION == 34 surge_power(you.spec_evoke()); +#endif fly_player( player_adjust_evoc_power(you.skill(SK_EVOCATIONS, 2) + 30)); } diff --git a/crawl-ref/source/acquire.cc b/crawl-ref/source/acquire.cc index 301064df0f95..fc7060c67f04 100644 --- a/crawl-ref/source/acquire.cc +++ b/crawl-ref/source/acquire.cc @@ -1239,7 +1239,11 @@ int acquirement_create_item(object_class_type class_wanted, ASSERT(class_wanted != OBJ_RANDOM); const bool divine = (agent == GOD_OKAWARU || agent == GOD_XOM - || agent == GOD_TROG || agent == GOD_PAKELLAS); + || agent == GOD_TROG +#if TAG_MAJOR_VERSION == 34 + || agent == GOD_PAKELLAS +#endif + ); int thing_created = NON_ITEM; int quant = 1; #define MAX_ACQ_TRIES 40 diff --git a/crawl-ref/source/art-func.h b/crawl-ref/source/art-func.h index a8a762ee7b86..bec8ad648e4a 100644 --- a/crawl-ref/source/art-func.h +++ b/crawl-ref/source/art-func.h @@ -1101,6 +1101,7 @@ static void _FIRESTARTER_melee_effects(item_def* weapon, actor* attacker, /////////////////////////////////////////////////// +#if TAG_MAJOR_VERSION == 34 static void _CHILLY_DEATH_equip(item_def *item, bool *show_msgs, bool unmeld) { _equip_mpr(show_msgs, "The dagger glows with an icy blue light!"); @@ -1134,9 +1135,11 @@ static void _CHILLY_DEATH_melee_effects(item_def* weapon, actor* attacker, } } } +#endif /////////////////////////////////////////////////// +#if TAG_MAJOR_VERSION == 34 static void _FLAMING_DEATH_equip(item_def *item, bool *show_msgs, bool unmeld) { _equip_mpr(show_msgs, "The scimitar bursts into red hot flame!"); @@ -1163,6 +1166,7 @@ static void _FLAMING_DEATH_melee_effects(item_def* weapon, actor* attacker, } } } +#endif /////////////////////////////////////////////////// @@ -1281,6 +1285,7 @@ static void _ETHERIC_CAGE_world_reacts(item_def *item) /////////////////////////////////////////////////// +#if TAG_MAJOR_VERSION == 34 static void _ETERNAL_TORMENT_equip(item_def *item, bool *show_msgs, bool unmeld) { calc_hp(); @@ -1297,6 +1302,7 @@ static void _ETERNAL_TORMENT_unequip(item_def *item, bool *show_msgs) { calc_hp(); } +#endif /////////////////////////////////////////////////// diff --git a/crawl-ref/source/artefact-prop-type.h b/crawl-ref/source/artefact-prop-type.h index 775115021a1f..e06f072ca34b 100644 --- a/crawl-ref/source/artefact-prop-type.h +++ b/crawl-ref/source/artefact-prop-type.h @@ -19,6 +19,9 @@ enum artefact_prop_type ARTP_SEE_INVISIBLE, ARTP_INVISIBLE, ARTP_FLY, +#if TAG_MAJOR_VERSION > 34 + ARTP_FOG, +#endif ARTP_BLINK, ARTP_BERSERK, ARTP_NOISE, diff --git a/crawl-ref/source/artefact.cc b/crawl-ref/source/artefact.cc index 2df00a5714f8..65ff3b871ba6 100644 --- a/crawl-ref/source/artefact.cc +++ b/crawl-ref/source/artefact.cc @@ -660,6 +660,9 @@ static const artefact_prop_data artp_data[] = []() { return 1; }, nullptr, 0, 0 }, { "+Fly", ARTP_VAL_BOOL, 15, // ARTP_FLY, []() { return 1; }, nullptr, 0, 0 }, +#if TAG_MAJOR_VERSION > 34 + { "+Fog", ARTP_VAL_BOOL, 0, nullptr, nullptr, 0, 0 }, // ARTP_FOG, +#endif { "+Blink", ARTP_VAL_BOOL, 15, // ARTP_BLINK, []() { return 1; }, nullptr, 0, 0 }, { "+Rage", ARTP_VAL_BOOL, 15, // ARTP_BERSERK, @@ -1542,7 +1545,9 @@ static bool _randart_is_conflicting(const item_def &item, break; case RING_TELEPORTATION: +#if TAG_MAJOR_VERSION == 34 case RING_TELEPORT_CONTROL: +#endif conflicts = ARTP_PREVENT_TELEPORTATION; break; diff --git a/crawl-ref/source/daction-type.h b/crawl-ref/source/daction-type.h index 409647303739..4ce4ffec579a 100644 --- a/crawl-ref/source/daction-type.h +++ b/crawl-ref/source/daction-type.h @@ -25,9 +25,8 @@ enum daction_type #if TAG_MAJOR_VERSION == 34 DACT_HOLY_PETS_GO_NEUTRAL, DACT_ALLY_TROG, -#endif - DACT_RECLAIM_DECKS, +#endif DACT_REAUTOMAP, DACT_REMOVE_JIYVA_ALTARS, DACT_PIKEL_SLAVES, diff --git a/crawl-ref/source/dactions.cc b/crawl-ref/source/dactions.cc index d971d8fbfa45..ce6b3879a768 100644 --- a/crawl-ref/source/dactions.cc +++ b/crawl-ref/source/dactions.cc @@ -47,9 +47,11 @@ static const char *daction_names[] = #else "slimes allow another conversion attempt", #endif +#if TAG_MAJOR_VERSION == 34 "holy beings go neutral", "Trog's gifts go hostile", "reclaim decks", +#endif "reapply passive mapping", "remove Jiyva altars", "Pikel's slaves go good-neutral", @@ -66,8 +68,8 @@ static const char *daction_names[] = "bribe timeout", "remove Gozag shops", "apply Gozag bribes", - "Makhleb's servants go hostile", #if TAG_MAJOR_VERSION == 34 + "Makhleb's servants go hostile", "make all monsters hate you", #endif "ancestor vanishes", @@ -293,9 +295,11 @@ static void _apply_daction(daction_type act) } break; +#if TAG_MAJOR_VERSION == 34 case DACT_RECLAIM_DECKS: reclaim_decks_on_level(); break; +#endif case DACT_REAUTOMAP: reautomap_level(); break; diff --git a/crawl-ref/source/describe-god.cc b/crawl-ref/source/describe-god.cc index 237a1bccf4e0..f1b3ae641c5f 100644 --- a/crawl-ref/source/describe-god.cc +++ b/crawl-ref/source/describe-god.cc @@ -225,9 +225,11 @@ static const char *divine_title[][8] = {"Sleeper", "Questioner", "Initiate", "Seeker of Truth", "@Walker@ of the Path","Lifter of the Veil", "Transcendent", "Drop of Water"}, +#if TAG_MAJOR_VERSION == 34 // Pakellas -- inventor theme {"Reactionary", "Apprentice", "Inquisitive", "Experimenter", "Inventor", "Pioneer", "Brilliant", "Grand Gadgeteer"}, +#endif // Uskayaw -- reveler theme {"Prude", "Wallflower", "Party-goer", "Dancer", @@ -966,6 +968,7 @@ static formatted_string _describe_god_powers(god_type which_god) desc.cprintf("Your life essence is reduced. (-10%% HP)\n"); break; +#if TAG_MAJOR_VERSION == 34 case GOD_PAKELLAS: { have_any = true; @@ -986,6 +989,7 @@ static formatted_string _describe_god_powers(god_type which_god) } break; } +#endif case GOD_LUGONU: have_any = true; diff --git a/crawl-ref/source/describe-spells.cc b/crawl-ref/source/describe-spells.cc index dad8222f126a..39ff6faeb559 100644 --- a/crawl-ref/source/describe-spells.cc +++ b/crawl-ref/source/describe-spells.cc @@ -570,8 +570,11 @@ static void _describe_book(const spellbook_contents &book, } string schools = +#if TAG_MAJOR_VERSION == 34 source_item->base_type == OBJ_RODS ? "Evocations" - : _spell_schools(spell); + : +#endif + _spell_schools(spell); description.cprintf("%s%d\n", chop_string(schools, 30).c_str(), spell_difficulty(spell)); diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index df14179b4669..14b093e28693 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -3487,7 +3487,9 @@ static string _flavour_base_desc(attack_flavour flavour) { AF_POISON_STRONG, "cause strong poisoning" }, { AF_ROT, "cause rotting" }, { AF_VAMPIRIC, "drain health from the living" }, +#if TAG_MAJOR_VERSION == 34 { AF_KLOWN, "cause random powerful effects" }, +#endif { AF_DISTORT, "cause wild translocation effects" }, { AF_RAGE, "cause berserking" }, { AF_STICKY_FLAME, "apply sticky flame" }, diff --git a/crawl-ref/source/dungeon-feature-type.h b/crawl-ref/source/dungeon-feature-type.h index f4b9fcffe0ee..912c7e5e67a4 100644 --- a/crawl-ref/source/dungeon-feature-type.h +++ b/crawl-ref/source/dungeon-feature-type.h @@ -197,6 +197,7 @@ enum dungeon_feature_type DNGN_ALTAR_PAKELLAS, DNGN_ALTAR_USKAYAW, DNGN_ALTAR_HEPLIAKLQANA, + DNGN_ALTAR_WU_JIAN, DNGN_ALTAR_ECUMENICAL, #endif diff --git a/crawl-ref/source/end.cc b/crawl-ref/source/end.cc index c0655e69c3bb..31922f84b479 100644 --- a/crawl-ref/source/end.cc +++ b/crawl-ref/source/end.cc @@ -386,12 +386,14 @@ NORETURN void end_game(scorefile_entry &se) } break; +#if TAG_MAJOR_VERSION == 34 case GOD_PAKELLAS: { const string result = getSpeakString("Pakellas death"); god_speaks(GOD_PAKELLAS, result.c_str()); break; } +#endif default: if (will_have_passive(passive_t::goldify_corpses) diff --git a/crawl-ref/source/evoke.cc b/crawl-ref/source/evoke.cc index 557834bf02f7..07d9a54b5239 100644 --- a/crawl-ref/source/evoke.cc +++ b/crawl-ref/source/evoke.cc @@ -240,8 +240,12 @@ static bool _evoke_horn_of_geryon() return false; } +#if TAG_MAJOR_VERSION == 34 const int surge = pakellas_surge_devices(); surge_power(you.spec_evoke() + surge); +#else + const int surge = 0; +#endif mprf(MSGCH_SOUND, "You produce a hideous howling noise!"); did_god_conduct(DID_EVIL, 3); int num = 1; @@ -346,8 +350,12 @@ static bool _lightning_rod() return false; } +#if TAG_MAJOR_VERSION == 34 const int surge = pakellas_surge_devices(); surge_power(you.spec_evoke() + surge); +#else + const int surge = 0; +#endif const int power = player_adjust_evoc_power(5 + you.skill(SK_EVOCATIONS, 3), surge); @@ -411,12 +419,14 @@ void zap_wand(int slot) return; } +#if TAG_MAJOR_VERSION == 34 if (player_under_penance(GOD_PAKELLAS)) { simple_god_message("'s wrath prevents you from evoking devices!", GOD_PAKELLAS); return; } +#endif const int mp_cost = wand_mp_cost(); @@ -606,8 +616,12 @@ static const pop_entry pop_spiders[] = static bool _box_of_beasts(item_def &box) { - const int surge = pakellas_surge_devices() + you.spec_evoke(); - surge_power(surge); +#if TAG_MAJOR_VERSION == 34 + const int surge = pakellas_surge_devices(); + surge_power(you.spec_evoke() + surge); +#else + const int surge = 0; +#endif mpr("You open the lid..."); // two rolls to reduce std deviation - +-6 so can get < max even at 27 sk @@ -659,8 +673,12 @@ static bool _sack_of_spiders_veto_mon(monster_type mon) static bool _sack_of_spiders(item_def &sack) { - const int surge = pakellas_surge_devices() + you.spec_evoke(); - surge_power(surge); +#if TAG_MAJOR_VERSION == 34 + const int surge = pakellas_surge_devices(); + surge_power(you.spec_evoke() + surge); +#else + const int surge = 0; +#endif mpr("You reach into the bag..."); const int evo_skill = you.skill(SK_EVOCATIONS); @@ -775,8 +793,12 @@ static bool _ball_of_energy() bool ret = false; mpr("You gaze into the crystal ball."); +#if TAG_MAJOR_VERSION == 34 const int surge = pakellas_surge_devices(); surge_power(you.spec_evoke() + surge); +#else + const int surge = 0; +#endif int use = player_adjust_evoc_power(random2(you.skill(SK_EVOCATIONS, 6)), surge); @@ -1017,8 +1039,12 @@ static bool _lamp_of_fire() if (you.confused()) target.confusion_fuzz(); +#if TAG_MAJOR_VERSION == 34 const int surge = pakellas_surge_devices(); surge_power(you.spec_evoke() + surge); +#else + const int surge = 0; +#endif mpr("The flames dance!"); @@ -1320,8 +1346,12 @@ static bool _phial_of_floods() beam.set_target(target); } +#if TAG_MAJOR_VERSION == 34 const int surge = pakellas_surge_devices(); surge_power(you.spec_evoke() + surge); +#else + const int surge = 0; +#endif const int power = player_adjust_evoc_power(base_pow, surge); // use real power to recalc hit/dam zappy(ZAP_PRIMAL_WAVE, power, false, beam); @@ -1422,8 +1452,12 @@ static spret _phantom_mirror() return spret::abort; } +#if TAG_MAJOR_VERSION == 34 const int surge = pakellas_surge_devices(); surge_power(you.spec_evoke() + surge); +#else + const int surge = 0; +#endif monster* mon = clone_mons(victim, true, nullptr, ATT_FRIENDLY); if (!mon) @@ -1588,18 +1622,21 @@ bool evoke_item(int slot, bool check_range) case OBJ_MISCELLANY: did_work = true; // easier to do it this way for misc items - if ((you.get_mutation_level(MUT_NO_ARTIFICE) - || player_under_penance(GOD_PAKELLAS)) - && item.sub_type != MISC_ZIGGURAT) + if (item.sub_type != MISC_ZIGGURAT) { if (you.get_mutation_level(MUT_NO_ARTIFICE)) + { mpr("You cannot evoke magical items."); - else + return false; + } +#if TAG_MAJOR_VERSION == 34 + if (player_under_penance(GOD_PAKELLAS)) { simple_god_message("'s wrath prevents you from evoking " "devices!", GOD_PAKELLAS); + return false; } - return false; +#endif } switch (item.sub_type) @@ -1618,8 +1655,12 @@ bool evoke_item(int slot, bool check_range) return false; } +#if TAG_MAJOR_VERSION == 34 const int surge = pakellas_surge_devices(); surge_power(you.spec_evoke() + surge); +#else + const int surge = 0; +#endif wind_blast(&you, player_adjust_evoc_power(you.skill(SK_EVOCATIONS, 15), surge), diff --git a/crawl-ref/source/feature-data.h b/crawl-ref/source/feature-data.h index 9f6101ac2866..3cac055b026a 100644 --- a/crawl-ref/source/feature-data.h +++ b/crawl-ref/source/feature-data.h @@ -535,7 +535,9 @@ ALTAR(DNGN_ALTAR_GOZAG, "opulent altar of Gozag", "altar_gozag", ETC_GOLD), // f ALTAR(DNGN_ALTAR_QAZLAL, "stormy altar of Qazlal", "altar_qazlal", ETC_ELEMENTAL), ALTAR(DNGN_ALTAR_RU, "sacrificial altar of Ru", "altar_ru", BROWN), ALTAR(DNGN_ALTAR_ECUMENICAL, "faded altar of an unknown god", "altar_ecumenical", ETC_DARK), +#if TAG_MAJOR_VERSION == 34 ALTAR(DNGN_ALTAR_PAKELLAS, "oddly glowing altar of Pakellas", "altar_pakellas", ETC_PAKELLAS), +#endif ALTAR(DNGN_ALTAR_USKAYAW, "hide-covered altar of Uskayaw", "altar_uskayaw", ETC_INCARNADINE), ALTAR(DNGN_ALTAR_HEPLIAKLQANA, "hazy altar of Hepliaklqana", "altar_hepliaklqana", LIGHTGREEN), ALTAR(DNGN_ALTAR_WU_JIAN, "ornate altar of the Wu Jian Council", "altar_wu_jian", ETC_WU_JIAN), diff --git a/crawl-ref/source/god-abil.cc b/crawl-ref/source/god-abil.cc index bc43e628b9f6..405c92a89b87 100644 --- a/crawl-ref/source/god-abil.cc +++ b/crawl-ref/source/god-abil.cc @@ -6381,6 +6381,7 @@ bool ru_apocalypse() return true; } +#if TAG_MAJOR_VERSION == 34 /** * Calculate the effective power of a surged hex wand. * Works by iterating over the possible rolls from random2avg(). @@ -6465,6 +6466,7 @@ int pakellas_surge_devices() } return severity; } +#endif static bool _mons_stompable(const monster &mons) { diff --git a/crawl-ref/source/god-conduct.cc b/crawl-ref/source/god-conduct.cc index 2edd84477f47..358427328628 100644 --- a/crawl-ref/source/god-conduct.cc +++ b/crawl-ref/source/god-conduct.cc @@ -449,6 +449,7 @@ static peeve_map divine_peeves[] = peeve_map(), // GOD_RU, peeve_map(), +#if TAG_MAJOR_VERSION == 34 // GOD_PAKELLAS { { DID_CHANNEL, { @@ -456,6 +457,7 @@ static peeve_map divine_peeves[] = 1, 1, } }, }, +#endif // GOD_USKAYAW, peeve_map(), // GOD_HEPLIAKLQANA, @@ -949,6 +951,7 @@ static like_map divine_likes[] = } } }, }, +#if TAG_MAJOR_VERSION == 34 // GOD_PAKELLAS, { { DID_KILL_LIVING, _on_kill("you kill living beings", MH_NATURAL, false, @@ -964,6 +967,7 @@ static like_map divine_likes[] = { DID_KILL_HOLY, KILL_HOLY_RESPONSE }, { DID_KILL_NONLIVING, KILL_NONLIVING_RESPONSE }, }, +#endif // GOD_USKAYAW { { DID_HURT_FOE, { diff --git a/crawl-ref/source/god-passive.cc b/crawl-ref/source/god-passive.cc index b49903d7eaf2..8a5fc780cfc0 100644 --- a/crawl-ref/source/god-passive.cc +++ b/crawl-ref/source/god-passive.cc @@ -397,6 +397,7 @@ static const vector god_passives[] = }, }, +#if TAG_MAJOR_VERSION == 34 // Pakellas { { -1, passive_t::no_mp_regen, @@ -407,6 +408,7 @@ static const vector god_passives[] = "GOD NOW collects and distills excess magic from your kills" }, }, +#endif // Uskayaw { }, diff --git a/crawl-ref/source/god-type.h b/crawl-ref/source/god-type.h index 37fd386566fb..a37024b785a7 100644 --- a/crawl-ref/source/god-type.h +++ b/crawl-ref/source/god-type.h @@ -25,7 +25,9 @@ enum god_type GOD_GOZAG, GOD_QAZLAL, GOD_RU, +#if TAG_MAJOR_VERSION == 34 GOD_PAKELLAS, +#endif GOD_USKAYAW, GOD_HEPLIAKLQANA, GOD_WU_JIAN, diff --git a/crawl-ref/source/god-wrath.cc b/crawl-ref/source/god-wrath.cc index 818fe7b03be6..c8906b642d0e 100644 --- a/crawl-ref/source/god-wrath.cc +++ b/crawl-ref/source/god-wrath.cc @@ -85,7 +85,9 @@ static const char *_god_wrath_adjectives[] = "greed", // Gozag (unused) "adversity", // Qazlal "disappointment", // Ru +#if TAG_MAJOR_VERSION == 34 "progress", // Pakellas +#endif "fury", // Uskayaw "memory", // Hepliaklqana (unused) "rancor", // Wu Jian @@ -1755,7 +1757,9 @@ bool divine_retribution(god_type god, bool no_bonus, bool force) case GOD_GOZAG: case GOD_RU: case GOD_HEPLIAKLQANA: +#if TAG_MAJOR_VERSION == 34 case GOD_PAKELLAS: +#endif // No reduction with time. return false; diff --git a/crawl-ref/source/invent.cc b/crawl-ref/source/invent.cc index a8a385b4bb7d..e80b13403054 100644 --- a/crawl-ref/source/invent.cc +++ b/crawl-ref/source/invent.cc @@ -1591,7 +1591,10 @@ bool needs_handle_warning(const item_def &item, operation_types oper, return true; if (oper == OPER_ATTACK && god_hates_item(item) - && !you_worship(GOD_PAKELLAS)) +#if TAG_MAJOR_VERSION == 34 + && !you_worship(GOD_PAKELLAS) +#endif + ) { penance = true; return true; diff --git a/crawl-ref/source/item-name.cc b/crawl-ref/source/item-name.cc index 44e4d9f8f432..54785cee443c 100644 --- a/crawl-ref/source/item-name.cc +++ b/crawl-ref/source/item-name.cc @@ -3572,8 +3572,10 @@ bool is_useless_item(const item_def &item, bool temp) || (temp && you.species == SP_VAMPIRE && you.hunger_state <= HS_STARVING); +#if TAG_MAJOR_VERSION == 34 case AMU_MANA_REGENERATION: return you_worship(GOD_PAKELLAS); +#endif case RING_SEE_INVISIBLE: return you.innate_sinv(); diff --git a/crawl-ref/source/item-prop-enum.h b/crawl-ref/source/item-prop-enum.h index bbc4b860d366..519c74b30b7b 100644 --- a/crawl-ref/source/item-prop-enum.h +++ b/crawl-ref/source/item-prop-enum.h @@ -100,8 +100,8 @@ enum armour_type ARM_SHADOW_DRAGON_ARMOUR, ARM_QUICKSILVER_DRAGON_HIDE, ARM_QUICKSILVER_DRAGON_ARMOUR, -#endif ARM_SCARF, +#endif NUM_ARMOURS }; diff --git a/crawl-ref/source/items.cc b/crawl-ref/source/items.cc index 1f46d35f37ed..78c720b3e7fa 100644 --- a/crawl-ref/source/items.cc +++ b/crawl-ref/source/items.cc @@ -3045,6 +3045,8 @@ static bool _similar_wands(const item_def& pickup_item, #if TAG_MAJOR_VERSION == 34 // Not similar if wand in inventory is empty. return !is_known_empty_wand(inv_item); +#else + return true; #endif } diff --git a/crawl-ref/source/lookup-help.cc b/crawl-ref/source/lookup-help.cc index e7ebf5552f87..44e255b5af7e 100644 --- a/crawl-ref/source/lookup-help.cc +++ b/crawl-ref/source/lookup-help.cc @@ -358,9 +358,11 @@ static vector _get_god_keys() for (int i = GOD_NO_GOD + 1; i < NUM_GODS; i++) { god_type which_god = static_cast(i); +#if TAG_MAJOR_VERSION == 34 // XXX: currently disabled. if (which_god != GOD_PAKELLAS) - names.push_back(god_name(which_god)); +#endif + names.push_back(god_name(which_god)); } return names; diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc index 1f539cca74e1..90f8248661d1 100644 --- a/crawl-ref/source/mapdef.cc +++ b/crawl-ref/source/mapdef.cc @@ -4927,8 +4927,8 @@ int str_to_ego(object_class_type item_type, string ego_str) "returning", #endif "chaos", - "evasion", #if TAG_MAJOR_VERSION == 34 + "evasion", "confuse", #endif "penetration", diff --git a/crawl-ref/source/mon-cast.cc b/crawl-ref/source/mon-cast.cc index 03bcacaf5d48..b0d58b23339d 100644 --- a/crawl-ref/source/mon-cast.cc +++ b/crawl-ref/source/mon-cast.cc @@ -1881,7 +1881,9 @@ bool setup_mons_cast(const monster* mons, bolt &pbolt, spell_type spell_cast, case SPELL_SEAL_DOORS: case SPELL_BERSERK_OTHER: case SPELL_SPELLFORGED_SERVITOR: +#if TAG_MAJOR_VERSION == 34 case SPELL_THROW: +#endif case SPELL_THROW_ALLY: case SPELL_CORRUPTING_PULSE: case SPELL_SIREN_SONG: diff --git a/crawl-ref/source/mon-death.cc b/crawl-ref/source/mon-death.cc index 1ee8e993227a..a583418b5c2d 100644 --- a/crawl-ref/source/mon-death.cc +++ b/crawl-ref/source/mon-death.cc @@ -2231,8 +2231,12 @@ item_def* monster_die(monster& mons, killer_type killer, && mons.evil()) && !mons_is_object(mons.type) && !player_under_penance() - && (you_worship(GOD_PAKELLAS) - || random2(you.piety) >= piety_breakpoint(0))) + && (random2(you.piety) >= piety_breakpoint(0) +#if TAG_MAJOR_VERSION == 34 + || you_worship(GOD_PAKELLAS) +#endif + ) + ) { int hp_heal = 0, mp_heal = 0; @@ -2249,16 +2253,11 @@ item_def* monster_die(monster& mons, killer_type killer, if (have_passive(passive_t::mp_on_kill)) { - switch (you.religion) - { - case GOD_PAKELLAS: + mp_heal = 1 + random2(mons.get_experience_level() / 2); +#if TAG_MAJOR_VERSION == 34 + if (you.religion == GOD_PAKELLAS) mp_heal = random2(2 + mons.get_experience_level() / 6); - break; - case GOD_VEHUMET: - default: - mp_heal = 1 + random2(mons.get_experience_level() / 2); - break; - } +#endif } if (hp_heal && you.hp < you.hp_max @@ -2277,6 +2276,7 @@ item_def* monster_die(monster& mons, killer_type killer, mp_heal -= tmp; } +#if TAG_MAJOR_VERSION == 34 // perhaps this should go to its own function if (mp_heal && have_passive(passive_t::bottle_mp) @@ -2306,6 +2306,7 @@ item_def* monster_die(monster& mons, killer_type killer, } } } +#endif } if (gives_player_xp && you_worship(GOD_RU) && you.piety < 200 diff --git a/crawl-ref/source/mon-ench.cc b/crawl-ref/source/mon-ench.cc index c127b360c4c2..de894911723f 100644 --- a/crawl-ref/source/mon-ench.cc +++ b/crawl-ref/source/mon-ench.cc @@ -2069,7 +2069,11 @@ static const char *enchant_names[] = "control_winds", "wind_aided", #endif "summon_capped", - "toxic_radiance", "grasping_roots_source", "grasping_roots", + "toxic_radiance", +#if TAG_MAJOR_VERSION == 34 + "grasping_roots_source", +#endif + "grasping_roots", "iood_charged", "fire_vuln", "tornado_cooldown", "merfolk_avatar_song", "barbs", #if TAG_MAJOR_VERSION == 34 diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index 706f30785f0c..0d9439a4b591 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -3079,7 +3079,11 @@ void ugly_thing_apply_uniform_band_colour(mgen_data &mg, static const char *drac_colour_names[] = { - "black", "", "yellow", "green", "purple", "red", "white", "grey", "pale" + "black", +#if TAG_MAJOR_VERSION == 34 + "", +#endif + "yellow", "green", "purple", "red", "white", "grey", "pale" }; string draconian_colour_name(monster_type mon_type) @@ -3110,7 +3114,11 @@ monster_type draconian_colour_by_name(const string &name) // TODO: Remove "putrid" when TAG_MAJOR_VERSION > 34 static const char *demonspawn_base_names[] = { - "monstrous", "gelid", "infernal", "putrid", "torturous", + "monstrous", "gelid", "infernal", +#if TAG_MAJOR_VERSION == 34 + "putrid", +#endif + "torturous", }; string demonspawn_base_name(monster_type mon_type) diff --git a/crawl-ref/source/ng-setup.cc b/crawl-ref/source/ng-setup.cc index 972a3eaac68d..7d538c6ea27b 100644 --- a/crawl-ref/source/ng-setup.cc +++ b/crawl-ref/source/ng-setup.cc @@ -22,9 +22,7 @@ #include "options.h" #include "prompt.h" #include "religion.h" -#if TAG_MAJOR_VERSION == 34 -# include "shopping.h" // REMOVED_DEAD_SHOPS_KEY -#endif +#include "shopping.h" #include "skills.h" #include "spl-book.h" #include "spl-util.h" diff --git a/crawl-ref/source/player-equip.cc b/crawl-ref/source/player-equip.cc index 4dd94e9dc5e0..409d9b7c9d0c 100644 --- a/crawl-ref/source/player-equip.cc +++ b/crawl-ref/source/player-equip.cc @@ -397,8 +397,10 @@ static void _equip_use_warning(const item_def& item) mpr("You really shouldn't be using a chaotic item like this."); else if (is_hasty_item(item) && you_worship(GOD_CHEIBRIADOS)) mpr("You really shouldn't be using a hasty item like this."); +#if TAG_MAJOR_VERSION == 34 else if (is_channeling_item(item) && you_worship(GOD_PAKELLAS)) mpr("You really shouldn't be trying to channel magic like this."); +#endif } static void _wield_cursed(item_def& item, bool known_cursed, bool unmeld) @@ -782,12 +784,14 @@ static void _spirit_shield_message(bool unmeld) { dec_mp(you.magic_points); mpr("You feel your power drawn to a protective spirit."); +#if TAG_MAJOR_VERSION == 34 if (you.species == SP_DEEP_DWARF && !(have_passive(passive_t::no_mp_regen) || player_under_penance(GOD_PAKELLAS))) { mpr("Now linked to your health, your magic stops regenerating."); } +#endif } else if (!unmeld && you.get_mutation_level(MUT_MANA_SHIELD)) mpr("You feel the presence of a powerless spirit."); diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 4364f50f1d1a..76388287309a 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -4026,9 +4026,11 @@ bool player_regenerates_mp() // damage shaving is enough. (due, dpeg) if (you.spirit_shield() && you.species == SP_DEEP_DWARF) return false; +#if TAG_MAJOR_VERSION == 34 // Pakellas blocks MP regeneration. if (have_passive(passive_t::no_mp_regen) || player_under_penance(GOD_PAKELLAS)) return false; +#endif return true; } diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index eef90c2d23f9..b10e61264565 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -353,12 +353,14 @@ const vector god_powers[NUM_GODS] = { 5, ABIL_RU_APOCALYPSE, "wreak a terrible wrath on your foes" }, }, +#if TAG_MAJOR_VERSION == 34 // Pakellas { { 0, "gain magical power from killing" }, { 3, ABIL_PAKELLAS_DEVICE_SURGE, "spend magic to empower your devices" }, }, +#endif // Uskayaw { @@ -472,9 +474,11 @@ static bool _is_disabled_god(god_type god) { switch (god) { +#if TAG_MAJOR_VERSION == 34 // Disabled, pending a rework. case GOD_PAKELLAS: return true; +#endif default: return false; @@ -555,7 +559,9 @@ bool active_penance(god_type god) && god != GOD_GOZAG && god != GOD_RU && god != GOD_HEPLIAKLQANA +#if TAG_MAJOR_VERSION == 34 && god != GOD_PAKELLAS +#endif && god != GOD_ELYVILON && (god == you.religion && !is_good_god(god) || god_hates_your_god(god, you.religion)); @@ -569,7 +575,9 @@ bool xp_penance(god_type god) && (god == GOD_ASHENZARI || god == GOD_GOZAG || god == GOD_HEPLIAKLQANA +#if TAG_MAJOR_VERSION == 34 || god == GOD_PAKELLAS +#endif || god == GOD_ELYVILON) && god_hates_your_god(god, you.religion); } @@ -654,13 +662,16 @@ void dec_penance(god_type god, int val) } else { +#if TAG_MAJOR_VERSION == 34 if (god == GOD_PAKELLAS) { // Penance just ended w/o worshipping Pakellas; // notify the player that MP regeneration will start again. mprf(MSGCH_GOD, god, "You begin regenerating magic."); } - else if (god == GOD_HEPLIAKLQANA) + else +#endif + if (god == GOD_HEPLIAKLQANA) { calc_hp(); // frailty ends mprf(MSGCH_GOD, god, "Your full life essence returns."); @@ -831,11 +842,13 @@ static void _inc_penance(god_type god, int val) you.redraw_armour_class = true; } } +#if TAG_MAJOR_VERSION == 34 else if (god == GOD_PAKELLAS) { if (you.duration[DUR_DEVICE_SURGE]) you.duration[DUR_DEVICE_SURGE] = 0; } +#endif else if (god == GOD_SIF_MUNA) { if (you.duration[DUR_CHANNEL_ENERGY]) @@ -1015,6 +1028,7 @@ static bool _give_nemelex_gift(bool forced = false) return false; } +#if TAG_MAJOR_VERSION == 34 /** * From the given list of items, return a random unseen item, if there are any. * Otherwise, just return any of them at random. @@ -1039,6 +1053,7 @@ static int _preferably_unseen_item(const vector &item_types, return unseen[random2(unseen.size())]; return item_types[random2(item_types.size())]; } +#endif static void _delayed_gift_callback(const mgen_data &mg, monster *&mon, int placed) @@ -1202,6 +1217,7 @@ static set _vehumet_get_spell_gifts() return offers; } +#if TAG_MAJOR_VERSION == 34 /// Has the player ID'd the given type of wand? static bool _seen_wand(int wand) { @@ -1340,6 +1356,7 @@ static bool _give_pakellas_gift() return false; } +#endif static bool _give_trog_oka_gift(bool forced) { @@ -2016,9 +2033,11 @@ bool do_god_gift(bool forced) success = _give_nemelex_gift(forced); break; +#if TAG_MAJOR_VERSION == 34 case GOD_PAKELLAS: success = _give_pakellas_gift(); break; +#endif case GOD_OKAWARU: case GOD_TROG: @@ -2107,7 +2126,9 @@ string god_name(god_type which_god, bool long_name) case GOD_GOZAG: return "Gozag"; case GOD_QAZLAL: return "Qazlal"; case GOD_RU: return "Ru"; +#if TAG_MAJOR_VERSION == 34 case GOD_PAKELLAS: return "Pakellas"; +#endif case GOD_USKAYAW: return "Uskayaw"; case GOD_HEPLIAKLQANA: return "Hepliaklqana"; case GOD_WU_JIAN: return "Wu Jian"; @@ -2671,7 +2692,9 @@ int initial_wrath_penance_for(god_type god) case GOD_CHEIBRIADOS: case GOD_DITHMENOS: case GOD_MAKHLEB: +#if TAG_MAJOR_VERSION == 34 case GOD_PAKELLAS: +#endif case GOD_QAZLAL: case GOD_VEHUMET: case GOD_ZIN: @@ -2934,6 +2957,7 @@ void excommunication(bool voluntary, god_type new_god) } break; +#if TAG_MAJOR_VERSION == 34 case GOD_PAKELLAS: simple_god_message(" continues to block your magic from regenerating.", old_god); @@ -2943,6 +2967,7 @@ void excommunication(bool voluntary, god_type new_god) - exp_needed(min(you.max_level, 27)); you.exp_docked_total[old_god] = you.exp_docked[old_god]; break; +#endif case GOD_CHEIBRIADOS: simple_god_message(" continues to slow your movements.", old_god); @@ -3109,11 +3134,13 @@ bool player_can_join_god(god_type which_god) if (you.get_mutation_level(MUT_NO_LOVE) && _god_rejects_loveless(which_god)) return false; +#if TAG_MAJOR_VERSION == 34 if (you.get_mutation_level(MUT_NO_ARTIFICE) && which_god == GOD_PAKELLAS) { return false; } +#endif return _transformed_player_can_join_god(which_god); } @@ -3547,12 +3574,14 @@ static void _join_zin() } } +#if TAG_MAJOR_VERSION == 34 // Setup when becoming an overworked assistant to Pakellas. static void _join_pakellas() { mprf(MSGCH_GOD, "You stop regenerating magic."); you.attribute[ATTR_PAKELLAS_EXTRA_MP] = POT_MAGIC_MP; } +#endif // Setup for joining the easygoing followers of Cheibriados. static void _join_cheibriados() @@ -3581,7 +3610,9 @@ static const map> on_join = { if (you.worshipped[GOD_LUGONU] == 0) gain_piety(20, 1, false); // allow instant access to first power }}, +#if TAG_MAJOR_VERSION == 34 { GOD_PAKELLAS, _join_pakellas }, +#endif { GOD_RU, _join_ru }, { GOD_TROG, _join_trog }, { GOD_ZIN, _join_zin }, @@ -3724,12 +3755,14 @@ void god_pitch(god_type which_god) simple_god_message(" does not accept worship from the loveless!", which_god); } +#if TAG_MAJOR_VERSION == 34 else if (you.get_mutation_level(MUT_NO_ARTIFICE) && which_god == GOD_PAKELLAS) { simple_god_message(" does not accept worship from those who are " "unable to use magical devices!", which_god); } +#endif else if (!_transformed_player_can_join_god(which_god)) { simple_god_message(" says: How dare you approach in such a " @@ -3918,10 +3951,12 @@ bool god_hates_spell(spell_type spell, god_type god, bool fake_spell) if (is_hasty_spell(spell)) return true; break; +#if TAG_MAJOR_VERSION == 34 case GOD_PAKELLAS: if (spell == SPELL_SUBLIMATION_OF_BLOOD) return true; break; +#endif default: break; } @@ -4056,7 +4091,9 @@ void handle_god_time(int /*time_delta*/) case GOD_KIKUBAAQUDGHA: case GOD_VEHUMET: case GOD_ZIN: +#if TAG_MAJOR_VERSION == 34 case GOD_PAKELLAS: +#endif case GOD_JIYVA: case GOD_WU_JIAN: if (one_chance_in(17)) @@ -4161,8 +4198,10 @@ int god_colour(god_type god) // mv - added case GOD_RU: return BROWN; +#if TAG_MAJOR_VERSION == 34 case GOD_PAKELLAS: return LIGHTGREEN; +#endif case GOD_NO_GOD: case NUM_GODS: @@ -4249,8 +4288,10 @@ colour_t god_message_altar_colour(god_type god) case GOD_RU: return BROWN; +#if TAG_MAJOR_VERSION == 34 case GOD_PAKELLAS: return random_choose(LIGHTMAGENTA, LIGHTGREEN, LIGHTCYAN); +#endif case GOD_USKAYAW: return random_choose(RED, MAGENTA); diff --git a/crawl-ref/source/rltiles/dc-item.txt b/crawl-ref/source/rltiles/dc-item.txt index 0e5b38dbe382..5b3c2b0d7d84 100644 --- a/crawl-ref/source/rltiles/dc-item.txt +++ b/crawl-ref/source/rltiles/dc-item.txt @@ -190,7 +190,7 @@ i-protection BRAND_PROTECTION i-draining BRAND_DRAINING i-speed BRAND_SPEED i-vorpal BRAND_VORPAL -# Remove the BRAND_FLAME and BRAND_FROST line s(but not the tiles, which are +# Remove the BRAND_FLAME and BRAND_FROST lines (but not the tiles, which are # still used for melee weapons) when TAG_MAJOR_VERSION > 34 i-flaming BRAND_FLAME i-freezing BRAND_FROST @@ -200,11 +200,12 @@ i-pain BRAND_PAIN i-antimagic BRAND_ANTIMAGIC %rim 0 i-distortion BRAND_DISTORTION -# Remove when TAG_MAJOR_VERSION > 34 +# Remove confusion when TAG_MAJOR_VERSION > 34 i-confusion BRAND_REACHING -# Move i-returning down to missile-only brands when TAG_MAJOR_VERSION > 34 +# Remove returning when TAG_MAJOR_VERSION > 34 i-returning BRAND_RETURNING i-chaos BRAND_CHAOS +# Remove evasion when TAG_MAJOR_VERSION > 34 i-evasion BRAND_EVASION # Move i-confusion down to missile-only brands when TAG_MAJOR_VERSION > 34 i-confusion BRAND_CONFUSION @@ -500,10 +501,12 @@ i-stealth BRAND_ARM_STEALTH i-resistance BRAND_ARM_RESISTANCE i-positive-energy BRAND_ARM_POSITIVE_ENERGY i-archmagi BRAND_ARM_ARCHMAGI +# Remove preservation when TAG_MAJOR_VERSION > 34 i-preservation BRAND_ARM_PRESERVATION i-reflection BRAND_ARM_REFLECTION i-spirit BRAND_ARM_SPIRIT_SHIELD i-archery BRAND_ARM_ARCHERY +# Remove jumping when TAG_MAJOR_VERSION > 34 i-jumping BRAND_ARM_JUMPING i-repulsion BRAND_ARM_REPULSION i-cloud-immune BRAND_ARM_CLOUD_IMMUNE BRAND_ARM_LAST @@ -609,6 +612,7 @@ i-fear SCR_FEAR i-noise SCR_NOISE %back scroll-yellow i-remove_curse SCR_REMOVE_CURSE +# aka scroll of summoning %back scroll-brown i-unholy_creation SCR_UNHOLY_CREATION %back scroll-green @@ -648,6 +652,7 @@ i-silence SCR_SILENCE i-amnesia SCR_AMNESIA %back scroll-grey #### Remove curse foo when TAG_MAJOR_VERSION > 34 +# Don't forget to update SCR_ID_LAST i-curse-jewellery SCR_CURSE_JEWELLERY SCR_ID_LAST %back none @@ -841,6 +846,7 @@ i-slowing POT_SLOWING i-cancel POT_CANCELLATION i-ambrosia POT_AMBROSIA i-invisibility POT_INVISIBILITY +# Remove porridge when TAG_MAJOR_VERSION > 34 i-porridge POT_PORRIDGE i-degeneration POT_DEGENERATION # please remove these 2 when TAG_MAJOR_VERSION is bumped @@ -857,9 +863,10 @@ i-cure-mutation POT_REMOVEME8 i-mutation POT_MUTATION i-resistance POT_RESISTANCE i-blood POT_BLOOD +# Remove coagulated blood when TAG_MAJOR_VERSION > 34 i-coagulated-blood POT_BLOOD_COAGULATED i-lignify POT_LIGNIFY -# please remove POT_BENEFICIAL_MUTATION when TAG_MAJOR_VERSION is bumped +# Remove beneficial mutation and update POT_ID_LAST when TAG_MAJOR_VERSION > 34 i-good-mutation POT_REMOVEME9 POT_ID_LAST %back none %rim 1 @@ -936,6 +943,7 @@ i-staff_conjuration STAFF_CONJURATION i-staff_enchantment STAFF_ENCHANTMENT i-staff_summoning STAFF_SUMMONING i-staff_air STAFF_AIR +# Remove channeling and update STAFF_ID_LAST when TAG_MAJOR_VERSION > 34 i-staff_earth STAFF_EARTH %rim 0 i-staff_channeling STAFF_CHANNELING STAFF_ID_LAST diff --git a/crawl-ref/source/showsymb.cc b/crawl-ref/source/showsymb.cc index ede24efc2306..56ea37319886 100644 --- a/crawl-ref/source/showsymb.cc +++ b/crawl-ref/source/showsymb.cc @@ -191,8 +191,10 @@ static int _get_mons_colour(const monster_info& mi) if (stype != mi.type && mi.type != MONS_SENSED) col = mons_class_colour(stype); +#if TAG_MAJOR_VERSION == 34 if (mi.is(MB_ROLLING)) col = ETC_BONE; +#endif if (mi.is(MB_BERSERK)) col = RED; diff --git a/crawl-ref/source/skills.cc b/crawl-ref/source/skills.cc index 313cc05aa24b..d04e461312fc 100644 --- a/crawl-ref/source/skills.cc +++ b/crawl-ref/source/skills.cc @@ -1701,10 +1701,12 @@ string skill_title_by_rank(skill_type best_skill, uint8_t skill_rank, result = god_title(god, species, piety); break; +#if TAG_MAJOR_VERSION == 34 case SK_EVOCATIONS: if (god == GOD_PAKELLAS) result = god_title(god, species, piety); break; +#endif default: break; diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc index 6b70bf273640..aa49e38503bd 100644 --- a/crawl-ref/source/spl-cast.cc +++ b/crawl-ref/source/spl-cast.cc @@ -85,6 +85,7 @@ static int _spell_enhancement(spell_type spell); static string _spell_failure_rate_description(spell_type spell); +#if TAG_MAJOR_VERSION == 34 void surge_power(const int enhanced) { if (enhanced) // one way or the other {dlb} @@ -112,6 +113,7 @@ void surge_power_wand(const int mp_cost) slight ? "." : "!"); } } +#endif static string _spell_base_description(spell_type spell, bool viewing) { @@ -1286,8 +1288,12 @@ vector desc_success_chance(const monster_info& mi, int pow, bool evoked, } else { +#if TAG_MAJOR_VERSION == 34 const int adj_pow = evoked ? pakellas_effective_hex_power(pow) : pow; +#else + const int adj_pow = pow; +#endif const int success = hex_success_chance(mr, adj_pow, 100); descs.push_back(make_stringf("chance to defeat MR: %d%%", success)); } @@ -1428,14 +1434,22 @@ spret your_spells(spell_type spell, int powc, bool allow_fail, if (evoked_item) { +#if TAG_MAJOR_VERSION == 34 const int surge = pakellas_surge_devices(); +#else + const int surge = 0; +#endif powc = player_adjust_evoc_power(powc, surge); +#if TAG_MAJOR_VERSION == 34 int mp_cost_of_wand = evoked_item->base_type == OBJ_WANDS ? wand_mp_cost() : 0; surge_power_wand(mp_cost_of_wand + surge * 3); +#endif } +#if TAG_MAJOR_VERSION == 34 else if (allow_fail) surge_power(_spell_enhancement(spell)); +#endif // Enhancers only matter for calc_spell_power() and raw_spell_fail(). // Not sure about this: is it flavour or misleading? (jpeg) diff --git a/crawl-ref/source/spl-summoning.cc b/crawl-ref/source/spl-summoning.cc index 9355afa8837a..29da4c99cfa8 100644 --- a/crawl-ref/source/spl-summoning.cc +++ b/crawl-ref/source/spl-summoning.cc @@ -1701,7 +1701,9 @@ static bool _raise_remains(const coord_def &pos, int corps, beh_type beha, *motions_r |= DEAD_ARE_HOPPING; } else if (mons_genus(zombie_type) == MONS_WORKER_ANT +#if TAG_MAJOR_VERSION == 34 || mons_genus(zombie_type) == MONS_BEETLE +#endif || mons_base_char(zombie_type) == 's') // many genera { *motions_r |= DEAD_ARE_CRAWLING; diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index f19ca801bac0..f74597979e51 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -304,7 +304,9 @@ static void tag_read_you(reader &th); static void tag_read_you_items(reader &th); static void tag_read_you_dungeon(reader &th); static void tag_read_lost_monsters(reader &th); +#if TAG_MAJOR_VERSION == 34 static void tag_read_lost_items(reader &th); +#endif static void tag_read_companions(reader &th); static void tag_construct_level(writer &th); @@ -2267,6 +2269,7 @@ void tag_read_char(reader &th, uint8_t format, uint8_t major, uint8_t minor) you.explore = unmarshallBoolean(th); } +#if TAG_MAJOR_VERSION == 34 static void _cap_mutation_at(mutation_type mut, int cap) { if (you.mutation[mut] > cap) @@ -2280,6 +2283,7 @@ static void _cap_mutation_at(mutation_type mut, int cap) if (you.innate_mutation[mut] > cap) you.innate_mutation[mut] = cap; } +#endif static void tag_read_you(reader &th) { diff --git a/crawl-ref/source/terrain.cc b/crawl-ref/source/terrain.cc index cedb4ca8fc30..c1c0ce6e0d84 100644 --- a/crawl-ref/source/terrain.cc +++ b/crawl-ref/source/terrain.cc @@ -541,7 +541,9 @@ static const pair _god_altars[] = { GOD_GOZAG, DNGN_ALTAR_GOZAG }, { GOD_QAZLAL, DNGN_ALTAR_QAZLAL }, { GOD_RU, DNGN_ALTAR_RU }, +#if TAG_MAJOR_VERSION == 34 { GOD_PAKELLAS, DNGN_ALTAR_PAKELLAS }, +#endif { GOD_USKAYAW, DNGN_ALTAR_USKAYAW }, { GOD_HEPLIAKLQANA, DNGN_ALTAR_HEPLIAKLQANA }, { GOD_WU_JIAN, DNGN_ALTAR_WU_JIAN }, diff --git a/crawl-ref/source/transform.cc b/crawl-ref/source/transform.cc index 6e9b6ddefc8d..c697c9c4a189 100644 --- a/crawl-ref/source/transform.cc +++ b/crawl-ref/source/transform.cc @@ -980,7 +980,9 @@ static const Form* forms[] = &FormPig::instance(), &FormAppendage::instance(), &FormTree::instance(), +#if TAG_MAJOR_VERSION == 34 &FormPorcupine::instance(), +#endif &FormWisp::instance(), #if TAG_MAJOR_VERSION == 34 diff --git a/crawl-ref/source/viewchar.cc b/crawl-ref/source/viewchar.cc index faef4c2d3557..399dc8661e4c 100644 --- a/crawl-ref/source/viewchar.cc +++ b/crawl-ref/source/viewchar.cc @@ -65,8 +65,13 @@ static const char32_t dchar_table[NUM_CSET][NUM_DCHAR_TYPES] = '#', '#', '*', '.', ',', '\'', '+', '^', '>', '<', '#', '_', // arch .. item_food '\\', '}', '~', '8', '{', '{', '{', '}', ')', '[', '/', '%', - // item_scroll .. item_amulet - '?', '=', '!', '(', ':', '|', '|', '}', '%', '%', '$', '"', + // item_scroll .. item_staff + '?', '=', '!', '(', ':', '|', +#if TAG_MAJOR_VERSION == 34 + '|', // rod +#endif + // miscellany .. amulet + '}', '%', '%', '$', '"', // cloud .. tree '0', '0', '0', '0', '7', #if TAG_MAJOR_VERSION == 34 diff --git a/crawl-ref/source/wiz-item.cc b/crawl-ref/source/wiz-item.cc index a899be4e0fe4..771da228cf68 100644 --- a/crawl-ref/source/wiz-item.cc +++ b/crawl-ref/source/wiz-item.cc @@ -1100,8 +1100,8 @@ static void _debug_acquirement_stats(FILE *ostat) "returning", #endif "chaos", - "evasion", #if TAG_MAJOR_VERSION == 34 + "evasion", "confusion", #endif "penetration", @@ -1463,6 +1463,9 @@ static void _debug_rap_stats(FILE *ostat) "ARTP_SEE_INVISIBLE", "ARTP_INVISIBLE", "ARTP_FLY", +#if TAG_MAJOR_VERSION > 34 + "ARTP_FOG", +#endif "ARTP_BLINK", "ARTP_BERSERK", "ARTP_NOISE", From 64c5a76fe24c2fd57ffc53d9492c4e4f103fc1d9 Mon Sep 17 00:00:00 2001 From: Alan Malloy Date: Tue, 5 Mar 2019 14:26:30 -0800 Subject: [PATCH 163/864] Don't feel safe while emergency-flying (/u/StairDancer) --- crawl-ref/source/nearby-danger.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crawl-ref/source/nearby-danger.cc b/crawl-ref/source/nearby-danger.cc index 33809ddb85ca..bd438dee0bbb 100644 --- a/crawl-ref/source/nearby-danger.cc +++ b/crawl-ref/source/nearby-danger.cc @@ -275,6 +275,14 @@ bool i_feel_safe(bool announce, bool want_move, bool just_monsters, return false; } + + if (you.props[EMERGENCY_FLIGHT_KEY]) + { + if (announce) + mprf(MSGCH_WARN, "You are being drained by your emergency flight!"); + + return false; + } } // Monster check. From 56e1b8fd0ee2b8544c10cc44545a6ac9b36759c4 Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 5 Mar 2019 21:36:37 -0500 Subject: [PATCH 164/864] Don't let explore options impact connectivity checks This was impacting seed stability: this code is called in various contexts, including stair checks / vault exit checks, plus from some lua code. The returned coordinate could be different depending on these options. The options that could potentially matter are `explore_wall_bias` and `explore_item_greed`, though I suspect the latter won't. The former I have verified to matter on seed 18127138284784505733 (UV4's game of the month seed right now), where setting it to 1 prior to this commit produces a different dungeon than the default value of 0. Thanks to u/kitchen_ace for noticing that deleting their rc file changed the dungeon, otherwise I'm not sure I would have ever found this bug. --- crawl-ref/source/travel.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc index 76a9a8509364..a716e5f5cca4 100644 --- a/crawl-ref/source/travel.cc +++ b/crawl-ref/source/travel.cc @@ -1211,8 +1211,8 @@ coord_def travel_pathfind::pathfind(run_mode_type rmode, bool fallback_explore) unexplored_place = greedy_place = coord_def(0, 0); unexplored_dist = greedy_dist = UNFOUND_DIST; - refdist = (Options.explore_item_greed > 0) ? &unexplored_dist - : &greedy_dist; + refdist = (runmode == RMODE_CONNECTIVITY || Options.explore_item_greed > 0) + ? &unexplored_dist : &greedy_dist; // Zap out previous distances array: this must happen before the // early exit checks below, since callers may want to inspect @@ -1286,8 +1286,11 @@ coord_def travel_pathfind::pathfind(run_mode_type rmode, bool fallback_explore) { if (runmode == RMODE_TRAVEL) return travel_move(); - else if (!Options.explore_wall_bias) + else if (runmode == RMODE_CONNECTIVITY + || !Options.explore_wall_bias) + { return explore_target(); + } else found_target = true; } From 1b465fed6c1aab4eebd53f2cbc4093a4104187ba Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 6 Mar 2019 00:07:39 -0500 Subject: [PATCH 165/864] Don't crash when there are game types from the future The save browser was crashing immediately on starting up in this case, which is triggered by the presence of seeded games from 0.23. This future-proofs a bunch of calls used by the save browser so that these games behave just like any other incompatible future-versioned save game in the main menu. (if you want to cherry-pick this to a past version, it is probably easier to use b7382820b72 from 0.22.) (cherry picked from commit b7382820b7259ae5d2ffec6fa48112b66c2509ab) --- crawl-ref/source/message.cc | 2 +- crawl-ref/source/state.cc | 21 +++++++++++++++------ crawl-ref/source/state.h | 1 + crawl-ref/source/tags.cc | 7 ++++++- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/crawl-ref/source/message.cc b/crawl-ref/source/message.cc index 317ed4821289..bd3acfb2066a 100644 --- a/crawl-ref/source/message.cc +++ b/crawl-ref/source/message.cc @@ -1361,7 +1361,7 @@ static void _mpr(string text, msg_channel_type channel, int param, bool nojoin, if (crawl_state.game_crashed) return; - if (crawl_state.game_is_arena()) + if (crawl_state.game_is_valid_type() && crawl_state.game_is_arena()) _debug_channel_arena(channel); #ifdef DEBUG_FATAL diff --git a/crawl-ref/source/state.cc b/crawl-ref/source/state.cc index 54ff23aeef1b..b5ddc1e2bc6f 100644 --- a/crawl-ref/source/state.cc +++ b/crawl-ref/source/state.cc @@ -552,34 +552,39 @@ bool game_state::game_standard_levelgen() const return game_is_normal() || game_is_hints(); } +bool game_state::game_is_valid_type() const +{ + return type < NUM_GAME_TYPE; +} + bool game_state::game_is_normal() const { - ASSERT(type < NUM_GAME_TYPE); + ASSERT(game_is_valid_type()); return type == GAME_TYPE_NORMAL || type == GAME_TYPE_CUSTOM_SEED - ||type == GAME_TYPE_UNSPECIFIED; + || type == GAME_TYPE_UNSPECIFIED; } bool game_state::game_is_tutorial() const { - ASSERT(type < NUM_GAME_TYPE); + ASSERT(game_is_valid_type()); return type == GAME_TYPE_TUTORIAL; } bool game_state::game_is_arena() const { - ASSERT(type < NUM_GAME_TYPE); + ASSERT(game_is_valid_type()); return type == GAME_TYPE_ARENA; } bool game_state::game_is_sprint() const { - ASSERT(type < NUM_GAME_TYPE); + ASSERT(game_is_valid_type()); return type == GAME_TYPE_SPRINT; } bool game_state::game_is_hints() const { - ASSERT(type < NUM_GAME_TYPE); + ASSERT(game_is_valid_type()); return type == GAME_TYPE_HINTS; } @@ -611,11 +616,15 @@ string game_state::game_type_name_for(game_type _type) return "Arena"; case GAME_TYPE_SPRINT: return "Dungeon Sprint"; + case NUM_GAME_TYPE: + return "Unknown"; } } string game_state::game_savedir_path() const { + if (!game_is_valid_type()) + return ""; // a game from the future -- avoid the ASSERT below return game_is_sprint()? "sprint/" : ""; } diff --git a/crawl-ref/source/state.h b/crawl-ref/source/state.h index 82a05c3e31f4..59b51961c7ba 100644 --- a/crawl-ref/source/state.h +++ b/crawl-ref/source/state.h @@ -198,6 +198,7 @@ struct game_state bool player_is_dead() const; bool game_standard_levelgen() const; + bool game_is_valid_type() const; bool game_is_normal() const; bool game_is_tutorial() const; bool game_is_arena() const; diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index f74597979e51..dd938e13baa1 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -2240,7 +2240,12 @@ void tag_read_char(reader &th, uint8_t format, uint8_t major, uint8_t minor) #endif crawl_state.type = (game_type) unmarshallUByte(th); - if (crawl_state.game_is_tutorial()) + // normalize invalid game types so they can be treated uniformly elsewhere + if (crawl_state.type > NUM_GAME_TYPE) + crawl_state.type = NUM_GAME_TYPE; + + // prevent an ASSERT in game_is_tutorial on game types from the future + if (crawl_state.game_is_valid_type() && crawl_state.game_is_tutorial()) crawl_state.map = unmarshallString2(th); else crawl_state.map = ""; From 8c2e5930553569adb5138b76c1584a7ac91c6ffd Mon Sep 17 00:00:00 2001 From: Doesnty Date: Wed, 6 Mar 2019 15:05:44 -0600 Subject: [PATCH 166/864] Let player ghosts be shafted (#1003) This was an artifact from when player ghosts were totally unable to leave the floor they started on by any means. Now that they don't have this trait, and don't broadcast it in their descriptions, there isn't any reason for them to be special-case immune to shafts, or for them to destroy shafts uselessly on moving over them. --- crawl-ref/source/monster.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/monster.cc b/crawl-ref/source/monster.cc index 1b5c0ae75c22..b3c8ef092a6f 100644 --- a/crawl-ref/source/monster.cc +++ b/crawl-ref/source/monster.cc @@ -5601,9 +5601,8 @@ bool monster::do_shaft() if (!is_valid_shaft_level()) return false; - // Tentacles & player ghosts are immune to shafting - if (mons_is_tentacle_or_tentacle_segment(type) - || type == MONS_PLAYER_GHOST) + // Tentacles are immune to shafting + if (mons_is_tentacle_or_tentacle_segment(type)) { return false; } From 029c7ce0acf44150939d4d2818de5a2e28a6b4a9 Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 6 Mar 2019 16:32:48 -0500 Subject: [PATCH 167/864] Don't change game chapter on a level excursion from abyss (11922) Level excursions can be used in the abyss to pull in ruined versions of terrain from regular connected levels. This bug didn't come up before, because if no levels have been explored (as is the case for an AK start), there is no level excursion. But with pregen, the builder can use terrain from levels the player hasn't seen yet, and if it chose to do this, the level excursion was resetting the chapter for an AK start to CHAPTER_ORB_HUNTING (for some seeds on turn 0). This generates an error message when leaving the abyss for wizards, a crash for non-wizards, and also would impact item/monster generation, because an AK character is no longer in the pocket abyss, for seeds that are affected. (But since AK starts that trigger this bug are just broken, that last part is not too big a deal.) This commit doesn't include save compat, because as far as I know this is rare, but save compat could be added if I'm wrong about this. --- crawl-ref/source/files.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index d42008a6adc2..18cc853a3efc 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1528,6 +1528,7 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, bool just_created_level = false; if (load_mode != LOAD_GENERATE + && load_mode != LOAD_VISITOR && you.chapter == CHAPTER_POCKET_ABYSS && player_in_branch(BRANCH_DUNGEON)) { From 8aad8c49190a408d01a35a101668c5236b571635 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Wed, 6 Mar 2019 19:03:02 -0600 Subject: [PATCH 168/864] Updates to the debian package guide Reorganize and rewrite sections to get the order of steps right and make the individual steps clearer. Also fix some typos and errors. --- crawl-ref/docs/develop/release/debian.txt | 291 +++++++++++----------- 1 file changed, 144 insertions(+), 147 deletions(-) diff --git a/crawl-ref/docs/develop/release/debian.txt b/crawl-ref/docs/develop/release/debian.txt index 02000e2f3f5a..75c9f89b089b 100644 --- a/crawl-ref/docs/develop/release/debian.txt +++ b/crawl-ref/docs/develop/release/debian.txt @@ -12,219 +12,216 @@ packages: https://www.debian.org/doc/manuals/maint-guide/index.en.html +1. Software Prerequisites and setup -0.1. Software Prerequisites +The cowbuilder and pbuilderrc can be set up once and re-used for each DCSS +release. The cowbuilder directory should be updated before - Install the cowbuilder and pbuilder packages: +See the following documentation if you have trouble with cowbuilder or +pbuilder during any of these steps: - sudo apt-get install cowbuilder +https://wiki.debian.org/cowbuilder +https://wiki.debian.org/PbuilderTricks - See the following websites if you have trouble with cowbuilder or pbuilder - during any of these steps: +1.1 Set up your pbuilderrc - https://wiki.debian.org/cowbuilder - https://wiki.debian.org/PbuilderTricks +We use the cowbuilder program to create the copy-on-write chroot directories, +and use pbuilder to build the packages in the chroot. A pbuilderrc file is +needed to tell pbuilder to use the cowbuilder system and to set downstream +shell variables. To use the example pbuilderrc file in this directory, copy it +to ~/.pbuilderrc or (as root) to /etc/pbuilderrc after making any +modifications. - Set up your DEBFULLNAME and DEBEMAIL shell variables using the name and - email you use in the git mailmap. This can be done in the shell or in your - pbuilderrc file (see below). To set them in the shell: +You can edit this file to set the variables DEBFULLNAME and DEBEMAIL to your +name and email. You can also set and export these variable directly in your +shell. - export DEBFULLNAME="yourname" - export DEBEMAIL="your@email" +In the example pbuilderrc, all pbuilder-related data go in +/var/cache/pbuilder. If you need to change this location, you'll need to modify +at least BASEPATH, BUILDPLACE, BUILDRESULT, and APTCACHE. +1.2 Install the cowbuilder and pbuilder packages -0.2 Release Prerequisites +This should get you the necessary packages: - Before building the packages, you should have the release version tagged - with all commits included, including final `docs/changelog.txt' entry for - the version and a commit updating the `crawl-ref/source/debian/changelog' - Debian changelog. + sudo apt-get install cowbuilder - To update the Debian changelog, add an entry at the top of this file in the - following format. +1.3 Create a .cow chroot directory for each architecture. - crawl (2:VER-1) unstable; urgency=low +You'll need a cowbuilder chroot directory for each architecture you want to +build. If you're using the example pbuilderrc, we use the scheme +`DIST-ARCH.cow'. For example, when building based on debian stable, we'd use: - * Major bugfix release + /var/cache/pbuilder/stable-amd64.cow + /var/cache/pbuilder/stable-i386.cow - -- devname TIMESTAMP +To create these, run the following: - You can copy the previous entry, update the version, and use output from the - `date' command to update the timestamp. A command like the following will - give you a valid timestamp: + sudo cowbuilder --create --architecture amd64 \ + --basepath /var/cache/pbuilder/stable-amd64.cow + sudo cowbuilder --create --architecture i386 \ + --basepath /var/cache/pbuilder/stable-i386.cow - date +'%a, %d %b %Y %R:%S %z' +This chroot directory needs to be created only once for each OS/ARCH/DIST +combination on which you what to build the package. If It doesn't need to be +recreated if you're only building a different DCSS version, but if you're using +a different value for any of OS, ARCH, or DIST, you'll need to create a +corresponding .cow chroot. - The entire entry must mach the format of previous entries; note the lines - following the first `crawl' line have leading spaces. Incorrect formatting - can cause debuild and hence pbuilder to fail. +2 Steps needed before release and before building the packages - Once the file is updated, commit the change to the repository so that it's - included in the release version tag. +The changelog update described in 2.1 should be done before you make the +release tag. If you forget, you can apply the changelog changes in the copy of +the debian directory you make in section 3.2. +2.1 Update and commit the Debian changelog -1. Make a copy of the of the source packages and extract +To update the Debian changelog, add an entry at the top of this file in the +following format. - The source packages should be made using the `package-source' target. Run - the following from the source directory if you haven't yet: +crawl (2:VERSION-1) unstable; urgency=low - make package-source + * Major bugfix release - This will make several files in the toplevel repo dir, but you specifically - need the `stone_soup-VER-nodeps.tar.xz' file. Copy this to a location where - you'd like to prepare the packages, then exactract the source directory and - rename the original file. Using version 0.17 as an example and with - ~/crawl-deb as my staging directory: + -- devname TIMESTAMP - mkdir -p ~/crawl-deb - cp stone_soup-0.17.0-nodeps.tar.xz ~/crawl-deb - cd ~/crawl-deb - tar Jxf stone_soup-0.17.0.tar.xz - mv stone_soup-0.17.0 crawl-0.17.0 - mv stone_soup-0.17.0-nodeps.tar.xz crawl-0.17.0.orig.tar.xz +You can copy the previous entry, update the version, and use output from the +`date' command to update the timestamp. A command like the following will +give you a valid timestamp: - Note that the name formats of crawl-VER and crawl-VER.orig.EXT for the - source directory and archive are specifically looked for by pbuilder, so - these file renaming steps are required. + date +'%a, %d %b %Y %R:%S %z' +The entire entry must mach the format of previous entries; note the lines +following the first `crawl' line have leading spaces. Incorrect formatting +can cause debuild and hence pbuilder to fail. -2. Copy and update the debian directory in the source directory +Once the file is updated, commit the change to the repository so that it's +included in the release version tag. - We need the crawl-ref/source/debian directory to be at the top level to - build the package. Using 0.17.0 as an example, and assuming we're already in - our staging directory with the unpacked source: +2.2 Updating the cow chroots - cd crawl-0.17.0 - cp -r source/debian . +It's good to update your cow chroot directory with the latest security/bugfix +updates to its packages: + sudo cowbuilder --update --architecture amd64 \ + --basepath /var/cache/pbuilder/stable-amd64.cow + sudo cowbuilder --update --architecture i386 \ + --basepath /var/cache/pbuilder/stable-i386.cow -3. Set up your pbuilderrc +3. Making the Debian packages - We use the cowbuilder program to create the copy-on-write chroot - directories, and use pbuilder to build the packages in the chroot. A - pbuilderrc file is needed to tell pbuilder to use the cowbuilder system and - to set downstream shell variables. To use the example pbuilderrc file in - this directory, copy it to ~/.pbuilderrc or (as root) to /etc/pbuilderrc - after making any modifications. +At this point the release should be tagged. - You can edit this file to set DEBFULLNAME and DEBEMAIL to your name and - email if you didn't do that in your shell already. In the example - pbuilderrc, all pbuilder-related data go in /var/cache/pbuilder. To change - this, you'll need to modify at least BASEPATH, BUILDPLACE, BUILDRESULT, and - APTCACHE. +3.1 Make a copy of the of the source packages and extract +The source packages should be made using the `package-source' target. Run +the following from the source directory if you haven't yet: -4. Create a .cow chroot directory for each architecture. + make package-source - You'll need a cowbuilder chroot directory for each architecture you want to - build. If you're using the example pbuilderrc, we use the scheme - `DIST-ARCH.cow'. For example, when building based on debian stable, we'd - use: +This will make several files in the toplevel repo dir, but you specifically +need the `stone_soup-VERSION-nodeps.tar.xz' file. Copy this to a location where +you'd like to prepare the packages, then extract the source directory and +rename the original file. Using version 0.17 as an example and with +~/crawl-deb as my staging directory: - /var/cache/pbuilder/stable-amd64.cow - /var/cache/pbuilder/stable-i386.cow + mkdir -p ~/crawl-deb + cp stone_soup-0.17.0-nodeps.tar.xz ~/crawl-deb + cd ~/crawl-deb + tar Jxf stone_soup-0.17.0.tar.xz + mv stone_soup-0.17.0 crawl-0.17.0 + mv stone_soup-0.17.0-nodeps.tar.xz crawl_0.17.0.orig.tar.xz - To create these, run the following: +Note that the name formats of crawl-VERSION and crawl_VERSION.orig.EXT for +the source directory and archive are specifically looked for by pbuilder. If +you receive errors, check that your source directory and archive follow this +format, using `crawl-` as a prefix for the directory but `crawl_` as a +prefix for the source archive. - sudo cowbuilder --create --architecture amd64 \ - --basepath /var/cache/pbuilder/stable-amd64.cow - sudo cowbuilder --create --architecture i386 \ - --basepath /var/cache/pbuilder/stable-i386.cow +3.2 Copy and update the debian directory in the source directory - This chroot directory needs to be created only once for each OS/ARCH/DIST - combination on which you what to build the package. It doesn't need to be - recreated if you're only building a different DCSS version, but if you're - using a different value for any of OS, ARCH, or DIST, you'll need to create - a corresponding .cow chroot. +We need the crawl-ref/source/debian directory to be at the top level to +build the package. Using 0.17.0 as an example, and assuming we're already in +our staging directory with the unpacked source: + cd crawl-0.17.0 + cp -r source/debian . -5. Build the packages +3.3 Build the packages - Asuming your pbuilderrc is based on the example one in this directory, you - need to set some of the shell variables ARCH, DIST, and OS to set up - downstream variables to build the packages for the architectures (e.g. i386 - or amd64) you want and against the distribution you want (e.g. stable or - testing for Debian), and possibly based on the OS you want (debian or - ubuntu) if you want to e.g. build against debian on an ubunutu host system. +Assuming your pbuilderrc is based on the example one in this directory, you +need to set some of the shell variables ARCH, DIST, and OS downstream +variables. The pbuilderrc uses these to build the packages for the +architectures (e.g. i386 or amd64) you want and against the distribution you +want (e.g. stable or testing for Debian), and based on the OS you want (e.g. +debian or ubuntu). - Run pdebuild from the `crawl-VER' source directory you made above. The - simplest build situation is making packages for the same architecture and - against the same distribution as your host system. Using our 0.17.0 example - building against debian stable on a debian stable system for amd64, simply: +Run pdebuild from the `crawl-VERSION' source directory you made above. The +simplest build situation is making packages for the same architecture and +against the same distribution as your host system. Using our 0.17.0 example +building against debian stable on a debian stable system for amd64, simply: - sudo pdebuild + sudo pdebuild - To build the i386 package: +Then to build the i386 package: - sudo ARCH=i386 pdebuild + sudo ARCH=i386 pdebuild - If you're on ubuntu, building against debian stable, you might need: +If you're on ubuntu, building against debian stable, you might need: - sudo OS=debian DIST=stable pdebuild - sudo OS=debian DIST=stable ARCH=i386 pdebuild + sudo OS=debian DIST=stable pdebuild + sudo OS=debian DIST=stable ARCH=i386 pdebuild - Once the package building is finished, the results well be in - /var/cache/pbuilder/result, if you're using the example pbuilderrc. +Once the package building is finished, the results will be in +/var/cache/pbuilder/result, if you're using the example pbuilderrc. +3.4 Upload files to CDO -6. Test install the packages +You'll need to upload all the files produced in /var/cache/pbuilder/result (not +just the deb and dsc files) to CDO. The staging directory +~/upload/VERSION/deb-files can be used for this. - Test the built packages in /var/cache/pbuilder/result by installing them; - you'll need to install the crawl_VER_ARCH.deb, crawl-tiles_VER_ARCH.deb, and - crawl-common_VER.deb packages. For example: +3.5 Install a new repo component (major release only) - dpkg -i /var/cache/pbuilder/results/crawl_0.17.0-1_amd64.deb \ - /var/cache/pbuilder/results/crawl-tiles_0.17.0-1_amd64.deb \ - /var/cache/pbuilder/results/crawl-common_0.17.0-1_amd64.deb \ - /var/cache/pbuilder/results/crawl-tiles-data_0.17.0-1_amd64.deb +For point releases, this step should be skipped. - Run the console version with `crawl' and the tiles version with - `crawl-tiles' to see if they work. +For major releases, we make a new release component for all releases of that +version. If you're logged into CDO, edit the `deb/conf/distributions` file, +adding the new version in the "Components:" field before the final entry for +"trunk": +Components: 0.10 0.11 0.12 0.13 0.14 0.15 0.16 0.17 trunk -7. Upload files to CDO, install into the repo, and test - You'll need to upload the deb files above in addition to the - `crawl_VER-1.dsc' file to the crawl account on CDO. The staging directory - ~/upload//deb-files can be used for this +3.6 Install the debian packages into the repository - We install each release into a component named after the major version of - the release. If you're logged into CDO, edit the `deb/conf/distributions` - file, adding the new version in the "Components:" field before the final - entry for "trunk". Example entry with 0.17 added: +Install the .deb files and the .dsc file using reprepro. An example using 0.17 +and `~/upload/0.17.0/deb-files' as a staging directory: - Components: 0.10 0.11 0.12 0.13 0.14 0.15 0.16 0.17 trunk + cd ~/deb + for i in ../upload/0.17.0/deb-files/*.deb + do reprepro -C 0.17 includedeb crawl "$i"; done + for i in ../upload/0.17.0/deb-files/*.dsc + do reprepro -C 0.17 includedsc crawl "$i"; done - Then install the .deb files and the .dsc file using reprepro. An example - using 0.17 and `~/upload/0.17.0/deb-files' as a staging directory: +Note that the other files produced by pdebuild in /var/cache/pbuilder/result +(section 3.3) must be present in the same directory as the dsc file you +install. - cd ~/deb - for i in ../upload/0.17.0/deb-files/*.deb - do reprepro -C 0.17 includedeb crawl "$i"; done - for i in ../upload/0.17.0/deb-files/*.dsc - do reprepro -C 0.17 includedsc crawl "$i"; done +Note: If you messed something up and need to upload a new build of packages +for a version already installed in the repo, you can remove the installed +debs with a command like the following (run from ~/deb): - Make sure to use the right major version number in those -C arguments. + reprepro -C 0.17 remove crawl crawl crawl-common crawl-tiles crawl-tiles-data - Note: If you messed something up and need to upload a new build of packages - for a version already installed in the repo, you can remove the installed - debs with a command like the following (run from ~/deb): +Test that the repository packages are working by following the apt instructions +on the download page to install and run them. - reprepro -C 0.17 remove crawl crawl crawl-common crawl-tiles crawl-tiles-data - - To test that the repository is working, follow the apt instructions on the - download page to add the DCSS repo and signing key, being sure to use the - correct crawl major version in sources.list. Then update your apt-cache with - `apt-get update`, install the crawl and crawl-tiles packages on your system, - and run them. - - -8. Update the download page - - The version in the Linux example command to add the repository URL should be - updated. See release.txt for details on keeping the CDO website in sync with - the website repository. +3.6 Update the download page +The version in the Linux example command to add the repository URL should be +updated. See release.txt for details on keeping the CDO website in sync with +the website repository. At this point, the repository should be working and the packages ready for users to install with apt. From 71aafec670c2c7326ff2fc128c852f18fbe18fe3 Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 6 Mar 2019 22:59:38 -0500 Subject: [PATCH 169/864] unbrace --- crawl-ref/source/monster.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/crawl-ref/source/monster.cc b/crawl-ref/source/monster.cc index b3c8ef092a6f..d6c7bb2ad2a1 100644 --- a/crawl-ref/source/monster.cc +++ b/crawl-ref/source/monster.cc @@ -5603,9 +5603,7 @@ bool monster::do_shaft() // Tentacles are immune to shafting if (mons_is_tentacle_or_tentacle_segment(type)) - { return false; - } // Handle instances of do_shaft() being invoked magically when // the monster isn't standing over a shaft. From d8427f5388a232a78fd1a3a47c897e7e7b166a3a Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 7 Mar 2019 09:17:39 -0500 Subject: [PATCH 170/864] Add a warning for setting `game_seed` online Before, this failed silently, which in at least one case seems to have confused a player into thinking that they succesfully set the seed. --- crawl-ref/source/initfile.cc | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index 8fc564f5ebf6..34e773adfe36 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -3410,9 +3410,15 @@ void game_options::read_option_line(const string &str, bool runscript) else constants.insert(field); } -#ifndef DGAMELAUNCH else if (key == "game_seed") { +#ifdef DGAMELAUNCH + // try to avoid confusing online players who put this in their rc + // file. N.b. it is still possible to use the -seed CLO. + report_error("Your rc file specifies a game seed, but this build of " + "crawl does not support seed selection. I will " + "choose a seed randomly."); +#else // special handling because of the large type. uint64_t tmp_seed = 0; if (sscanf(field.c_str(), "%" SCNu64, &tmp_seed)) @@ -3427,8 +3433,8 @@ void game_options::read_option_line(const string &str, bool runscript) if (!Options.seed) Options.seed = tmp_seed; } - } #endif + } // Catch-all else, copies option into map else if (runscript) From 9dfec575989f23c8c21e07fbc01c7facf7f6615a Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 11 Mar 2019 16:17:44 -0400 Subject: [PATCH 171/864] Fix cross-platform lua number->int conversion the hard way Lua 5.1 doesn't distinguish integers from numbers generally, and stores numbers as doubles, but on the c++ side we very often want ints. In 3d66cf40a65a384 I discovered that, depending on where the lua library is compiled, it may use different conversion methods in its conversion calls, which have different truncation behavior, leading to seed instability across systems (where it uses a specific hack on 32bit non-sse builds, a different one in msvc, and a regular cast otherwise). This behavior is determined at compile-time in luaconf.h, and the first attempt at a fix tried to prevent contrib lua from being built with the alternate behavior, always using a cast. This didn't generalize for at least two reasons: it creates problems trying to compile on other archs (see #992, #996), and it doesn't even cover all the problem situations: linux will typically build with system lua, and then we are at the mercy of whatever arch the system lua was built on anyways. (I have replicated the problem in a 32 bit ubuntu container, for example, even with the compilation fix.) This commit moves away from using lua's default calls for converting to ints, to conversion functions that we control in crawlcode. It's overkill to convert everything, only the dungeon and related calls are really needed, but converting everything was the most robust way to do it. Note that this *doesn't* address any instances of this call in the lua lib, with the hope that they won't matter. The only alternative that I can think of to a change like this would be to require building with contrib lua, and then fix the problem there, but this would seem to go against the spirit of our current build system. --- crawl-ref/source/clua.cc | 2 +- crawl-ref/source/cluautil.cc | 19 +++++ crawl-ref/source/cluautil.h | 10 ++- crawl-ref/source/l-crawl.cc | 44 ++++++------ crawl-ref/source/l-debug.cc | 14 ++-- crawl-ref/source/l-dgn.cc | 124 ++++++++++++++++----------------- crawl-ref/source/l-dgnbld.cc | 6 +- crawl-ref/source/l-dgnevt.cc | 4 +- crawl-ref/source/l-dgngrd.cc | 18 ++--- crawl-ref/source/l-dgnit.cc | 14 ++-- crawl-ref/source/l-dgnmon.cc | 2 +- crawl-ref/source/l-feat.cc | 2 +- crawl-ref/source/l-file.cc | 2 +- crawl-ref/source/l-item.cc | 28 ++++---- crawl-ref/source/l-mapgrd.cc | 4 +- crawl-ref/source/l-mapmrk.cc | 2 +- crawl-ref/source/l-mons.cc | 18 ++--- crawl-ref/source/l-spells.cc | 4 +- crawl-ref/source/l-subvault.cc | 4 +- crawl-ref/source/l-travel.cc | 12 ++-- crawl-ref/source/l-view.cc | 4 +- crawl-ref/source/l-wiz.cc | 2 +- crawl-ref/source/l-you.cc | 42 +++++------ 23 files changed, 203 insertions(+), 178 deletions(-) diff --git a/crawl-ref/source/clua.cc b/crawl-ref/source/clua.cc index 1fd3f698fa6e..8b87d935108f 100644 --- a/crawl-ref/source/clua.cc +++ b/crawl-ref/source/clua.cc @@ -416,7 +416,7 @@ void CLua::vfnreturns(const char *format, va_list args) break; case 'd': if (lua_isnumber(ls, sp)) - *(va_arg(args, int*)) = luaL_checkint(ls, sp); + *(va_arg(args, int*)) = luaL_safe_checkint(ls, sp); break; case 'b': *(va_arg(args, bool *)) = lua_toboolean(ls, sp); diff --git a/crawl-ref/source/cluautil.cc b/crawl-ref/source/cluautil.cc index 422905eb64f7..03ec096d35ff 100644 --- a/crawl-ref/source/cluautil.cc +++ b/crawl-ref/source/cluautil.cc @@ -106,3 +106,22 @@ int clua_pushpoint(lua_State *ls, const coord_def &pos) } return 1; } + +// these next two functions provide safe conversions to integers that will have +// stable behavior cross-platform. The lua 5.1 built-in conversions may not +// have stable behavior on all platforms if crawl is linked with a system lua +// library, because the technique it uses for doing this conversion is different +// depending on where that library was compiled. +lua_Integer luaL_safe_checkinteger(lua_State *L, int idx) +{ + lua_Number r = luaL_checknumber(L, idx); + // intentional use of C cast to mimic luaconf.h behavior + return (lua_Integer)(r); +} + +lua_Integer luaL_safe_tointeger(lua_State *L, int idx) +{ + lua_Number r = lua_tonumber(L, idx); + // intentional use of C cast to mimic luaconf.h behavior + return (lua_Integer)(r); +} diff --git a/crawl-ref/source/cluautil.h b/crawl-ref/source/cluautil.h index cef68d51dfcd..bb0e7655218a 100644 --- a/crawl-ref/source/cluautil.h +++ b/crawl-ref/source/cluautil.h @@ -11,6 +11,12 @@ extern "C" { #include } +lua_Integer luaL_safe_checkinteger(lua_State *L, int idx); +lua_Integer luaL_safe_tointeger(lua_State *L, int idx); +// override some #defines in the lua libs. +#define luaL_safe_checkint(L,n) ((int)luaL_safe_checkinteger(L, (n))) +#define luaL_safe_checklong(L,n) ((long)luaL_safe_checkinteger(L, (n))) + /* * Function definitions. */ @@ -145,8 +151,8 @@ level_id dlua_level_id(lua_State *ls, int ndx); #define GETCOORD(c, p1, p2, boundfn) \ coord_def c; \ - c.x = luaL_checkint(ls, p1); \ - c.y = luaL_checkint(ls, p2); \ + c.x = luaL_safe_checkint(ls, p1); \ + c.y = luaL_safe_checkint(ls, p2); \ if (!boundfn(c)) \ luaL_error( \ ls, \ diff --git a/crawl-ref/source/l-crawl.cc b/crawl-ref/source/l-crawl.cc index 353b9bc76302..b18d6b25569c 100644 --- a/crawl-ref/source/l-crawl.cc +++ b/crawl-ref/source/l-crawl.cc @@ -63,7 +63,7 @@ static int crawl_mpr(lua_State *ls) int ch = MSGCH_PLAIN; if (lua_isnumber(ls, 2)) - ch = luaL_checkint(ls, 2); + ch = luaL_safe_checkint(ls, 2); else { const char *channel = lua_tostring(ls, 2); @@ -94,7 +94,7 @@ static int crawl_formatted_mpr(lua_State *ls) int ch = MSGCH_PLAIN; if (lua_isnumber(ls, 2)) - ch = luaL_checkint(ls, 2); + ch = luaL_safe_checkint(ls, 2); else { const char *channel = lua_tostring(ls, 2); @@ -139,7 +139,7 @@ LUAFN(crawl_dpr) * @tparam int ms delay in milliseconds * @function delay */ -LUAWRAP(crawl_delay, delay(luaL_checkint(ls, 1))) +LUAWRAP(crawl_delay, delay(luaL_safe_checkint(ls, 1))) /*** Display a `--- more ---` prompt * @function more */ @@ -319,7 +319,7 @@ static void crawl_sendkeys_proc(lua_State *ls, int argi) } } else if (lua_isnumber(ls, argi)) - macro_sendkeys_end_add_expanded(luaL_checkint(ls, argi)); + macro_sendkeys_end_add_expanded(luaL_safe_checkint(ls, argi)); } /*** Send keypresses to crawl. @@ -627,7 +627,7 @@ static int crawl_msgch_num(lua_State *ls) */ static int crawl_msgch_name(lua_State *ls) { - int num = luaL_checkint(ls, 1); + int num = luaL_safe_checkint(ls, 1); string name = channel_to_str(num); lua_pushstring(ls, name.c_str()); return 1; @@ -651,7 +651,7 @@ static int crawl_take_note(lua_State *ls) */ static int crawl_messages(lua_State *ls) { - const int count = luaL_checkint(ls, 1); + const int count = luaL_safe_checkint(ls, 1); lua_pushstring(ls, get_last_messages(count).c_str()); return 1; } @@ -745,7 +745,7 @@ static int crawl_message_filter(lua_State *ls) if (!pattern) return 0; - int num = lua_isnumber(ls, 2)? luaL_checkint(ls, 2) : -1; + int num = lua_isnumber(ls, 2)? luaL_safe_checkint(ls, 2) : -1; message_filter **mf = clua_new_userdata< message_filter* >(ls, MESSF_METATABLE); if (mf) @@ -770,7 +770,7 @@ static int crawl_messf_matches(lua_State *ls) return 0; const char *pattern = luaL_checkstring(ls, 2); - int ch = luaL_checkint(ls, 3); + int ch = luaL_safe_checkint(ls, 3); if (pattern) { bool filt = (*mf)->is_filtered(ch, pattern); @@ -913,13 +913,13 @@ LUARET1(crawl_stat_gain_prompt, boolean, crawl_state.stat_gain_prompt) * @treturn int * @function random2 * */ -LUARET1(crawl_random2, number, random2(luaL_checkint(ls, 1))) +LUARET1(crawl_random2, number, random2(luaL_safe_checkint(ls, 1))) /*** Perform a weighted coinflip. * @tparam int in * @treturn boolean * @function one_chance_in */ -LUARET1(crawl_one_chance_in, boolean, one_chance_in(luaL_checkint(ls, 1))) +LUARET1(crawl_one_chance_in, boolean, one_chance_in(luaL_safe_checkint(ls, 1))) /*** Average num random rolls from [0, max). * @tparam int max * @tparam int num @@ -927,7 +927,7 @@ LUARET1(crawl_one_chance_in, boolean, one_chance_in(luaL_checkint(ls, 1))) * @function random2avg */ LUARET1(crawl_random2avg, number, - random2avg(luaL_checkint(ls, 1), luaL_checkint(ls, 2))) + random2avg(luaL_safe_checkint(ls, 1), luaL_safe_checkint(ls, 2))) /*** Random number in a range. * @tparam int min * @tparam int max @@ -935,8 +935,8 @@ LUARET1(crawl_random2avg, number, * @function random_range */ LUARET1(crawl_random_range, number, - random_range(luaL_checkint(ls, 1), luaL_checkint(ls, 2), - lua_isnumber(ls, 3)? luaL_checkint(ls, 3) : 1)) + random_range(luaL_safe_checkint(ls, 1), luaL_safe_checkint(ls, 2), + lua_isnumber(ls, 3)? luaL_safe_checkint(ls, 3) : 1)) /*** Flip a coin. * @treturn boolean * @function coinflip @@ -950,24 +950,24 @@ LUARET1(crawl_coinflip, boolean, coinflip()) */ LUARET1(crawl_roll_dice, number, lua_gettop(ls) == 1 - ? roll_dice(1, luaL_checkint(ls, 1)) - : roll_dice(luaL_checkint(ls, 1), luaL_checkint(ls, 2))) + ? roll_dice(1, luaL_safe_checkint(ls, 1)) + : roll_dice(luaL_safe_checkint(ls, 1), luaL_safe_checkint(ls, 2))) /*** Do a random draw. * @tparam int x * @tparam int y * @treturn boolean * @function x_chance_in_y */ -LUARET1(crawl_x_chance_in_y, boolean, x_chance_in_y(luaL_checkint(ls, 1), - luaL_checkint(ls, 2))) +LUARET1(crawl_x_chance_in_y, boolean, x_chance_in_y(luaL_safe_checkint(ls, 1), + luaL_safe_checkint(ls, 2))) /*** Random-round integer division. * @tparam int numerator * @tparam int denominator * @treturn int * @function div_rand_round */ -LUARET1(crawl_div_rand_round, number, div_rand_round(luaL_checkint(ls, 1), - luaL_checkint(ls, 2))) +LUARET1(crawl_div_rand_round, number, div_rand_round(luaL_safe_checkint(ls, 1), + luaL_safe_checkint(ls, 2))) /*** A random floating point number in [0,1.0) * @treturn number * @function random_real @@ -1188,8 +1188,8 @@ static int crawl_get_command(lua_State *ls) } LUAWRAP(crawl_endgame, screen_end_game(luaL_checkstring(ls, 1))) -LUAWRAP(crawl_tutorial_hunger, set_tutorial_hunger(luaL_checkint(ls, 1))) -LUAWRAP(crawl_tutorial_skill, set_tutorial_skill(luaL_checkstring(ls, 1), luaL_checkint(ls, 2))) +LUAWRAP(crawl_tutorial_hunger, set_tutorial_hunger(luaL_safe_checkint(ls, 1))) +LUAWRAP(crawl_tutorial_skill, set_tutorial_skill(luaL_checkstring(ls, 1), luaL_safe_checkint(ls, 2))) LUAWRAP(crawl_tutorial_hint, tutorial_init_hint(luaL_checkstring(ls, 1))) LUAWRAP(crawl_print_hint, print_hint(luaL_checkstring(ls, 1))) @@ -1600,7 +1600,7 @@ LUAFN(_crawl_god_speaks) */ LUAFN(_crawl_set_max_runes) { - int max_runes = luaL_checkinteger(ls, 1); + int max_runes = luaL_safe_checkint(ls, 1); if (max_runes < 0 || max_runes > NUM_RUNE_TYPES) luaL_error(ls, make_stringf("Bad number of max runes: %d", max_runes).c_str()); else diff --git a/crawl-ref/source/l-debug.cc b/crawl-ref/source/l-debug.cc index 19fea9b92895..945c955ac2ff 100644 --- a/crawl-ref/source/l-debug.cc +++ b/crawl-ref/source/l-debug.cc @@ -45,7 +45,7 @@ LUAFN(debug_goto_place) { const level_id id = level_id::parse_level_id(luaL_checkstring(ls, 1)); const int bind_entrance = - lua_isnumber(ls, 2)? luaL_checkint(ls, 2) : -1; + lua_isnumber(ls, 2)? luaL_safe_checkint(ls, 2) : -1; if (is_connected_branch(id.branch)) you.level_stack.clear(); @@ -152,11 +152,11 @@ LUAFN(debug_bouncy_beam) coord_def source; coord_def target; - source.x = luaL_checkint(ls, 1); - source.y = luaL_checkint(ls, 2); - target.x = luaL_checkint(ls, 3); - target.y = luaL_checkint(ls, 4); - int range = luaL_checkint(ls, 5); + source.x = luaL_safe_checkint(ls, 1); + source.y = luaL_safe_checkint(ls, 2); + target.x = luaL_safe_checkint(ls, 3); + target.y = luaL_safe_checkint(ls, 4); + int range = luaL_safe_checkint(ls, 5); bool findray = false; if (lua_gettop(ls) > 5) findray = lua_toboolean(ls, 6); @@ -410,7 +410,7 @@ LUAFN(debug_reset_rng) else { // quick and dirty - use only 32 bit seeds - unsigned int seed = (unsigned int) luaL_checkint(ls, 1); + unsigned int seed = (unsigned int) luaL_safe_checkint(ls, 1); Options.seed = (uint64_t) seed; } reset_rng(); diff --git a/crawl-ref/source/l-dgn.cc b/crawl-ref/source/l-dgn.cc index 2b21cd3781fe..fa1a57088ae4 100644 --- a/crawl-ref/source/l-dgn.cc +++ b/crawl-ref/source/l-dgn.cc @@ -129,7 +129,7 @@ static int dgn_desc(lua_State *ls) static int dgn_order(lua_State *ls) { MAP(ls, 1, map); - map->order = luaL_checkint(ls, 2); + map->order = luaL_safe_checkint(ls, 2); PLUARET(number, map->order); } @@ -183,7 +183,7 @@ static int dgn_chance(lua_State *ls) MAP(ls, 1, map); if (lua_isnumber(ls, 2)) { - const int chance = luaL_checkint(ls, 2); + const int chance = luaL_safe_checkint(ls, 2); _chance_magnitude_check(ls, 2, chance); map->_chance.set_default(map_chance(chance)); } @@ -194,7 +194,7 @@ static int dgn_depth_chance(lua_State *ls) { MAP(ls, 1, map); const string depth(luaL_checkstring(ls, 2)); - const int chance = luaL_checkint(ls, 3); + const int chance = luaL_safe_checkint(ls, 3); _chance_magnitude_check(ls, 3, chance); try { @@ -208,7 +208,7 @@ static int dgn_depth_chance(lua_State *ls) } #define WEIGHT(ls, n, weight) \ - const int weight = luaL_checkint(ls, n); \ + const int weight = luaL_safe_checkint(ls, n); \ if (weight < 0) \ luaL_error(ls, "Bad weight: %d (must be >= 0)", weight); @@ -330,8 +330,8 @@ static int dgn_map(lua_State *ls) // resolved and normalised. if (lua_gettop(ls) == 3 && lua_isnumber(ls, 2) && lua_isnumber(ls, 3)) { - const int gly = map->map.glyph(luaL_checkint(ls, 2), - luaL_checkint(ls, 3)); + const int gly = map->map.glyph(luaL_safe_checkint(ls, 2), + luaL_safe_checkint(ls, 3)); char buf[2] = ""; buf[0] = gly; lua_pushstring(ls, buf); @@ -345,7 +345,7 @@ static int dgn_map(lua_State *ls) } vector &lines = map->map.get_lines(); - int which_line = luaL_checkint(ls, 2); + int which_line = luaL_safe_checkint(ls, 2); if (which_line < 0) which_line += (int) lines.size(); if (lua_gettop(ls) == 2) @@ -410,7 +410,7 @@ static int dgn_mons(lua_State *ls) return 0; } - const int index = luaL_checkint(ls, 2); + const int index = luaL_safe_checkint(ls, 2); string err = map->mons.set_mons(index, luaL_checkstring(ls, 3)); if (!err.empty()) luaL_error(ls, err.c_str()); @@ -437,7 +437,7 @@ static int dgn_item(lua_State *ls) return 0; } - const int index = luaL_checkint(ls, 2); + const int index = luaL_safe_checkint(ls, 2); string err = map->items.set_item(index, luaL_checkstring(ls, 3)); if (!err.empty()) luaL_error(ls, err.c_str()); @@ -588,12 +588,12 @@ static int dgn_map_pathfind(lua_State *ls, int minargs, for (int i = 4; i < nargs; i += 2) { - const coord_def c(luaL_checkint(ls, i), - luaL_checkint(ls, i + 1)); + const coord_def c(luaL_safe_checkint(ls, i), + luaL_safe_checkint(ls, i + 1)); finder.add_point(c); } - const coord_def pos(luaL_checkint(ls, 2), luaL_checkint(ls, 3)); + const coord_def pos(luaL_safe_checkint(ls, 2), luaL_safe_checkint(ls, 3)); PLUARET(boolean, (finder.*f)(pos)); } @@ -735,7 +735,7 @@ static int _lua_colour(lua_State *ls, int ndx, int forbidden_colour = -1) { if (lua_isnumber(ls, ndx)) - return lua_tointeger(ls, ndx); + return luaL_safe_tointeger(ls, ndx); else if (const char *s = luaL_checkstring(ls, ndx)) { const int colour = str_to_colour(s, -1, false, true); @@ -801,15 +801,15 @@ static int dgn_colour_at(lua_State *ls) static int dgn_register_listener(lua_State *ls) { - unsigned mask = luaL_checkint(ls, 1); + unsigned mask = luaL_safe_checkint(ls, 1); MAPMARKER(ls, 2, mark); map_lua_marker *listener = dynamic_cast(mark); coord_def pos; // Was a position supplied? if (lua_gettop(ls) == 4) { - pos.x = luaL_checkint(ls, 3); - pos.y = luaL_checkint(ls, 4); + pos.x = luaL_safe_checkint(ls, 3); + pos.y = luaL_safe_checkint(ls, 4); } dungeon_events.register_listener(mask, listener, pos); @@ -824,8 +824,8 @@ static int dgn_remove_listener(lua_State *ls) // Was a position supplied? if (lua_gettop(ls) == 3) { - pos.x = luaL_checkint(ls, 2); - pos.y = luaL_checkint(ls, 3); + pos.x = luaL_safe_checkint(ls, 2); + pos.y = luaL_safe_checkint(ls, 3); } dungeon_events.remove_listener(listener, pos); return 0; @@ -858,15 +858,15 @@ static int dgn_terrain_changed(lua_State *ls) { dungeon_feature_type type = DNGN_UNSEEN; if (lua_isnumber(ls, 3)) - type = static_cast(luaL_checkint(ls, 3)); + type = static_cast(luaL_safe_checkint(ls, 3)); else if (lua_isstring(ls, 3)) type = dungeon_feature_by_name(lua_tostring(ls, 3)); const bool preserve_features = lua_isboolean(ls, 4)? lua_toboolean(ls, 4) : true; const bool preserve_items = lua_isboolean(ls, 5)? lua_toboolean(ls, 5) : true; - dungeon_terrain_changed(coord_def(luaL_checkint(ls, 1), - luaL_checkint(ls, 2)), + dungeon_terrain_changed(coord_def(luaL_safe_checkint(ls, 1), + luaL_safe_checkint(ls, 2)), type, preserve_features, preserve_items); return 0; } @@ -876,11 +876,11 @@ static int dgn_fprop_changed(lua_State *ls) feature_property_type prop = FPROP_NONE; if (lua_isnumber(ls, 3)) - prop = static_cast(luaL_checkint(ls, 3)); + prop = static_cast(luaL_safe_checkint(ls, 3)); else if (lua_isstring(ls, 3)) prop = str_to_fprop(lua_tostring(ls, 3)); - coord_def pos = coord_def(luaL_checkint(ls, 1), luaL_checkint(ls, 2)); + coord_def pos = coord_def(luaL_safe_checkint(ls, 1), luaL_safe_checkint(ls, 2)); if (in_bounds(pos) && prop != FPROP_NONE) { @@ -908,11 +908,11 @@ static int dgn_fprop_at(lua_State *ls) feature_property_type prop = FPROP_NONE; if (lua_isnumber(ls, 3)) - prop = static_cast(luaL_checkint(ls, 3)); + prop = static_cast(luaL_safe_checkint(ls, 3)); else if (lua_isstring(ls, 3)) prop = str_to_fprop(lua_tostring(ls, 3)); - coord_def pos = coord_def(luaL_checkint(ls, 1), luaL_checkint(ls, 2)); + coord_def pos = coord_def(luaL_safe_checkint(ls, 1), luaL_safe_checkint(ls, 2)); if (in_bounds(pos) && prop != FPROP_NONE) lua_pushboolean(ls, testbits(env.pgrid(pos), prop)); @@ -1076,9 +1076,9 @@ static int dgn_floor_halo(lua_State *ls) static int dgn_random_walk(lua_State *ls) { - const int x = luaL_checkint(ls, 1); - const int y = luaL_checkint(ls, 2); - const int dist = luaL_checkint(ls, 3); + const int x = luaL_safe_checkint(ls, 1); + const int y = luaL_safe_checkint(ls, 2); + const int dist = luaL_safe_checkint(ls, 3); if (!in_bounds(x, y)) { @@ -1116,20 +1116,20 @@ static kill_category dgn_kill_name_to_category(string name) static int dgn_apply_area_cloud(lua_State *ls) { - const int x = luaL_checkint(ls, 1); - const int y = luaL_checkint(ls, 2); - const int pow_min = luaL_checkint(ls, 3); - const int pow_max = luaL_checkint(ls, 4); - const int pow_rolls = luaL_checkint(ls, 5); - const int size = luaL_checkint(ls, 6); + const int x = luaL_safe_checkint(ls, 1); + const int y = luaL_safe_checkint(ls, 2); + const int pow_min = luaL_safe_checkint(ls, 3); + const int pow_max = luaL_safe_checkint(ls, 4); + const int pow_rolls = luaL_safe_checkint(ls, 5); + const int size = luaL_safe_checkint(ls, 6); const cloud_type ctype = cloud_name_to_type(luaL_checkstring(ls, 7)); const char* kname = lua_isstring(ls, 8) ? luaL_checkstring(ls, 8) : ""; const kill_category kc = dgn_kill_name_to_category(kname); - const int spread_rate = lua_isnumber(ls, 9) ? luaL_checkint(ls, 9) : -1; - const int excl_rad = lua_isnumber(ls, 10) ? luaL_checkint(ls, 10) : -1; + const int spread_rate = lua_isnumber(ls, 9) ? luaL_safe_checkint(ls, 9) : -1; + const int excl_rad = lua_isnumber(ls, 10) ? luaL_safe_checkint(ls, 10) : -1; if (!in_bounds(x, y)) { @@ -1219,17 +1219,17 @@ static int dgn_delete_cloud(lua_State *ls) static int dgn_place_cloud(lua_State *ls) { - const int x = luaL_checkint(ls, 1); - const int y = luaL_checkint(ls, 2); + const int x = luaL_safe_checkint(ls, 1); + const int y = luaL_safe_checkint(ls, 2); const cloud_type ctype = cloud_name_to_type(luaL_checkstring(ls, 3)); - const int cl_range = luaL_checkint(ls, 4); + const int cl_range = luaL_safe_checkint(ls, 4); const char* kname = lua_isstring(ls, 5) ? luaL_checkstring(ls, 5) : ""; const kill_category kc = dgn_kill_name_to_category(kname); - const int spread_rate = lua_isnumber(ls, 6) ? luaL_checkint(ls, 6) : -1; + const int spread_rate = lua_isnumber(ls, 6) ? luaL_safe_checkint(ls, 6) : -1; - const int excl_rad = lua_isnumber(ls, 7) ? luaL_checkint(ls, 7) : -1; + const int excl_rad = lua_isnumber(ls, 7) ? luaL_safe_checkint(ls, 7) : -1; if (!in_bounds(x, y)) { @@ -1272,7 +1272,7 @@ static int dgn_place_cloud(lua_State *ls) // XXX: Doesn't allow for messages or specifying the noise source. LUAFN(dgn_noisy) { - const int loudness = luaL_checkint(ls, 1); + const int loudness = luaL_safe_checkint(ls, 1); COORDS(pos, 2, 3); noisy(loudness, pos); @@ -1282,10 +1282,10 @@ LUAFN(dgn_noisy) static int _dgn_place_transporter(lua_State *ls) { - const coord_def trans_pos = coord_def(luaL_checkint(ls, 1), - luaL_checkint(ls, 2)); - const coord_def dest_pos = coord_def(luaL_checkint(ls, 3), - luaL_checkint(ls, 4)); + const coord_def trans_pos = coord_def(luaL_safe_checkint(ls, 1), + luaL_safe_checkint(ls, 2)); + const coord_def dest_pos = coord_def(luaL_safe_checkint(ls, 3), + luaL_safe_checkint(ls, 4)); dgn_place_transporter(trans_pos, dest_pos); return 0; @@ -1406,8 +1406,8 @@ LUAFN(dgn_with_map_anchors) { if (lua_isnumber(ls, i) && lua_isnumber(ls, i + 1)) { - map_anchor_points.emplace_back(lua_tointeger(ls, i), - lua_tointeger(ls, i + 1)); + map_anchor_points.emplace_back(luaL_safe_tointeger(ls, i), + luaL_safe_tointeger(ls, i + 1)); } } @@ -1503,7 +1503,7 @@ LUAFN(_dgn_place_map) LUAFN(_dgn_in_vault) { GETCOORD(c, 1, 2, map_bounds); - const int mask = lua_isnone(ls, 3) ? MMT_VAULT : lua_tointeger(ls, 3); + const int mask = lua_isnone(ls, 3) ? MMT_VAULT : luaL_safe_tointeger(ls, 3); lua_pushboolean(ls, env.level_map_mask(c) & mask); return 1; } @@ -1511,7 +1511,7 @@ LUAFN(_dgn_in_vault) LUAFN(_dgn_set_map_mask) { GETCOORD(c, 1, 2, map_bounds); - const int mask = lua_isnone(ls, 3) ? MMT_VAULT : lua_tointeger(ls, 3); + const int mask = lua_isnone(ls, 3) ? MMT_VAULT : luaL_safe_tointeger(ls, 3); env.level_map_mask(c) |= mask; return 1; } @@ -1519,7 +1519,7 @@ LUAFN(_dgn_set_map_mask) LUAFN(_dgn_unset_map_mask) { GETCOORD(c, 1, 2, map_bounds); - const int mask = lua_isnone(ls, 3) ? MMT_VAULT : lua_tointeger(ls, 3); + const int mask = lua_isnone(ls, 3) ? MMT_VAULT : luaL_safe_tointeger(ls, 3); env.level_map_mask(c) &= ~mask; return 1; } @@ -1576,7 +1576,7 @@ LUAFN(_dgn_find_marker_positions_by_prop) { const char *prop = luaL_checkstring(ls, 1); const string value(lua_gettop(ls) >= 2 ? luaL_checkstring(ls, 2) : ""); - const unsigned limit(lua_gettop(ls) >= 3 ? luaL_checkint(ls, 3) : 0); + const unsigned limit(lua_gettop(ls) >= 3 ? luaL_safe_checkint(ls, 3) : 0); const vector places = find_marker_positions_by_prop(prop, value, limit); clua_gentable(ls, places, clua_pushpoint); @@ -1593,7 +1593,7 @@ LUAFN(_dgn_find_markers_by_prop) { const char *prop = luaL_checkstring(ls, 1); const string value(lua_gettop(ls) >= 2 ? luaL_checkstring(ls, 2) : ""); - const unsigned limit(lua_gettop(ls) >= 3 ? luaL_checkint(ls, 3) : 0); + const unsigned limit(lua_gettop(ls) >= 3 ? luaL_safe_checkint(ls, 3) : 0); const vector places = find_markers_by_prop(prop, value, limit); clua_gentable(ls, places, _push_mapmarker); return 1; @@ -1601,8 +1601,8 @@ LUAFN(_dgn_find_markers_by_prop) LUAFN(_dgn_marker_at_pos) { - const int x = luaL_checkint(ls, 1); - const int y = luaL_checkint(ls, 2); + const int x = luaL_safe_checkint(ls, 1); + const int y = luaL_safe_checkint(ls, 2); coord_def p(x, y); @@ -1665,7 +1665,7 @@ LUAFN(_dgn_reuse_map) const bool flip_vert = _lua_boolean(ls, 5, false); // 1 for clockwise, -1 for anticlockwise, 0 for no rotation. - const int rotate_dir = lua_isnone(ls, 6) ? 0 : luaL_checkint(ls, 6); + const int rotate_dir = lua_isnone(ls, 6) ? 0 : luaL_safe_checkint(ls, 6); const bool register_place = _lua_boolean(ls, 7, true); const bool register_vault = register_place && _lua_boolean(ls, 8, false); @@ -1704,8 +1704,8 @@ LUAFN(_dgn_inspect_map) // Not using the COORDS macro because it checks against in_bounds which will fail 0,0 (!) coord_def c; - c.x = luaL_checkint(ls, 2); - c.y = luaL_checkint(ls, 3); + c.x = luaL_safe_checkint(ls, 2); + c.y = luaL_safe_checkint(ls, 3); lua_pushnumber(ls, vp.feature_at(c)); lua_pushboolean(ls, vp.is_exit(c)); @@ -1717,10 +1717,10 @@ LUAWRAP(_dgn_reset_level, dgn_reset_level()) LUAFN(dgn_fill_grd_area) { - int x1 = luaL_checkint(ls, 1); - int y1 = luaL_checkint(ls, 2); - int x2 = luaL_checkint(ls, 3); - int y2 = luaL_checkint(ls, 4); + int x1 = luaL_safe_checkint(ls, 1); + int y1 = luaL_safe_checkint(ls, 2); + int x2 = luaL_safe_checkint(ls, 3); + int y2 = luaL_safe_checkint(ls, 4); dungeon_feature_type feat = check_lua_feature(ls, 5); x1 = min(max(x1, X_BOUND_1+1), X_BOUND_2-1); diff --git a/crawl-ref/source/l-dgnbld.cc b/crawl-ref/source/l-dgnbld.cc index 160579df50e5..11646a338a69 100644 --- a/crawl-ref/source/l-dgnbld.cc +++ b/crawl-ref/source/l-dgnbld.cc @@ -31,7 +31,7 @@ static int _table_int(lua_State *ls, int idx, const char *name, int defval) bool valid = lua_isnumber(ls, idx); if (!nil && !valid) luaL_error(ls, "'%s' in table, but not an int.", name); - int ret = (!nil && valid ? luaL_checkint(ls, idx) : defval); + int ret = (!nil && valid ? luaL_safe_checkint(ls, idx) : defval); lua_pop(ls, 1); return ret; } @@ -103,7 +103,7 @@ static bool _table_bool(lua_State *ls, int idx, const char *name, bool defval) #define TABLE_BOOL(ls, val, def) bool val = _table_bool(ls, -1, #val, def); #define ARG_INT(ls, num, val, def) int val = lua_isnone(ls, num) ? \ - def : lua_tointeger(ls, num) + def : luaL_safe_tointeger(ls, num) // Read a set of box coords (x1, y1, x2, y2) from the table. // Return true if coords are valid. @@ -277,7 +277,7 @@ static vector _pool_fill_glyphs_from_table(lua_State *ls, // we use first character of string as glyph char glyph = (lua_tostring(ls, -2))[0]; - int count = lua_tointeger(ls, -1); + int count = luaL_safe_tointeger(ls, -1); // sanity-check if (count > 10000) count = 10000; diff --git a/crawl-ref/source/l-dgnevt.cc b/crawl-ref/source/l-dgnevt.cc index be651f7f615a..8d617d72fd31 100644 --- a/crawl-ref/source/l-dgnevt.cc +++ b/crawl-ref/source/l-dgnevt.cc @@ -106,7 +106,7 @@ static void dgn_push_event_type(lua_State *ls, int n) if (lua_isstring(ls, n)) lua_pushnumber(ls, dgn_event_type_by_name(lua_tostring(ls, n))); else if (lua_isnumber(ls, n)) - lua_pushstring(ls, dgn_event_type_name(luaL_checkint(ls, n))); + lua_pushstring(ls, dgn_event_type_name(luaL_safe_checkint(ls, n))); else lua_pushnil(ls); } @@ -126,7 +126,7 @@ static int dgn_dgn_event(lua_State *ls) static dgn_event_type dgn_param_to_event_type(lua_State *ls, int n) { if (lua_isnumber(ls, n)) - return static_cast(luaL_checkint(ls, n)); + return static_cast(luaL_safe_checkint(ls, n)); else if (lua_isstring(ls, n)) return dgn_event_type_by_name(lua_tostring(ls, n)); else diff --git a/crawl-ref/source/l-dgngrd.cc b/crawl-ref/source/l-dgngrd.cc index 558e60b400cc..f4dfd520f0ca 100644 --- a/crawl-ref/source/l-dgngrd.cc +++ b/crawl-ref/source/l-dgngrd.cc @@ -22,7 +22,7 @@ static int dgn_feature_number(lua_State *ls) static int dgn_feature_name(lua_State *ls) { - const unsigned feat = luaL_checkint(ls, 1); + const unsigned feat = luaL_safe_checkint(ls, 1); PLUARET(string, dungeon_feature_name(static_cast(feat))); } @@ -32,7 +32,7 @@ static dungeon_feature_type _get_lua_feature(lua_State *ls, int idx, { dungeon_feature_type feat = (dungeon_feature_type)0; if (lua_isnumber(ls, idx)) - feat = (dungeon_feature_type)luaL_checkint(ls, idx); + feat = (dungeon_feature_type)luaL_safe_checkint(ls, idx); else if (lua_isstring(ls, idx)) feat = dungeon_feature_by_name(luaL_checkstring(ls, idx)); else if (!optional) @@ -55,10 +55,10 @@ dungeon_feature_type f = check_lua_feature(ls, pos) static int dgn_feature_desc(lua_State *ls) { const dungeon_feature_type feat = - static_cast(luaL_checkint(ls, 1)); + static_cast(luaL_safe_checkint(ls, 1)); const description_level_type dtype = lua_isnumber(ls, 2)? - static_cast(luaL_checkint(ls, 2)) : + static_cast(luaL_safe_checkint(ls, 2)) : description_type_by_name(lua_tostring(ls, 2)); const bool need_stop = lua_isboolean(ls, 3)? lua_toboolean(ls, 3) : false; const string s = feature_description(feat, NUM_TRAPS, "", dtype, need_stop); @@ -70,11 +70,11 @@ static int dgn_feature_desc_at(lua_State *ls) { const description_level_type dtype = lua_isnumber(ls, 3)? - static_cast(luaL_checkint(ls, 3)) : + static_cast(luaL_safe_checkint(ls, 3)) : description_type_by_name(lua_tostring(ls, 3)); const bool need_stop = lua_isboolean(ls, 4)? lua_toboolean(ls, 4) : false; - const string s = feature_description_at(coord_def(luaL_checkint(ls, 1), - luaL_checkint(ls, 2)), + const string s = feature_description_at(coord_def(luaL_safe_checkint(ls, 1), + luaL_safe_checkint(ls, 2)), false, dtype, need_stop); lua_pushstring(ls, s.c_str()); return 1; @@ -89,8 +89,8 @@ static int dgn_max_bounds(lua_State *ls) static int dgn_in_bounds(lua_State *ls) { - int x = luaL_checkint(ls, 1); - int y = luaL_checkint(ls, 2); + int x = luaL_safe_checkint(ls, 1); + int y = luaL_safe_checkint(ls, 2); lua_pushboolean(ls, in_bounds(x, y)); return 1; diff --git a/crawl-ref/source/l-dgnit.cc b/crawl-ref/source/l-dgnit.cc index 69f1f3354b01..b3967f50197a 100644 --- a/crawl-ref/source/l-dgnit.cc +++ b/crawl-ref/source/l-dgnit.cc @@ -48,7 +48,7 @@ void register_itemlist(lua_State *ls) static int dgn_item_from_index(lua_State *ls) { - const int index = luaL_checkint(ls, 1); + const int index = luaL_safe_checkint(ls, 1); item_def *item = &mitm[index]; @@ -110,13 +110,13 @@ static int dgn_item_property_set(lua_State *ls) item->props[key].get_bool() = lua_toboolean(ls, 4); break; case 'b': - item->props[key].get_byte() = luaL_checkint(ls, 4); + item->props[key].get_byte() = luaL_safe_checkint(ls, 4); break; case 'S': - item->props[key].get_short() = luaL_checkint(ls, 4); + item->props[key].get_short() = luaL_safe_checkint(ls, 4); break; case 'i': - item->props[key].get_int() = luaL_checkint(ls, 4); + item->props[key].get_int() = luaL_safe_checkint(ls, 4); break; case 'f': item->props[key].get_float() = luaL_checknumber(ls, 4); @@ -125,8 +125,8 @@ static int dgn_item_property_set(lua_State *ls) item->props[key].get_string() = luaL_checkstring(ls, 4); break; case 'C': - item->props[key].get_coord() = coord_def(luaL_checkint(ls, 4), - luaL_checkint(ls, 5)); + item->props[key].get_coord() = coord_def(luaL_safe_checkint(ls, 4), + luaL_safe_checkint(ls, 5)); break; default: luaL_error(ls, "Unknown type: '%s'", type.c_str()); @@ -192,7 +192,7 @@ static int dgn_item_property(lua_State *ls) // Returns two arrays: one of floor items, one of shop items. static int dgn_stash_items(lua_State *ls) { - unsigned min_value = lua_isnumber(ls, 1) ? luaL_checkint(ls, 1) : 0; + unsigned min_value = lua_isnumber(ls, 1) ? luaL_safe_checkint(ls, 1) : 0; bool skip_stackable = lua_isboolean(ls, 2) ? lua_toboolean(ls, 2) : false; vector floor_items; diff --git a/crawl-ref/source/l-dgnmon.cc b/crawl-ref/source/l-dgnmon.cc index 98f77272dd2c..38c0e9f941e4 100644 --- a/crawl-ref/source/l-dgnmon.cc +++ b/crawl-ref/source/l-dgnmon.cc @@ -173,7 +173,7 @@ static int dgn_set_random_mon_list(lua_State *ls) static int dgn_mons_from_mid(lua_State *ls) { - const int mid = luaL_checkint(ls, 1); + const int mid = luaL_safe_checkint(ls, 1); monster* mons = monster_by_mid(mid); diff --git a/crawl-ref/source/l-feat.cc b/crawl-ref/source/l-feat.cc index f339ec1debe5..98f3af4d454d 100644 --- a/crawl-ref/source/l-feat.cc +++ b/crawl-ref/source/l-feat.cc @@ -21,7 +21,7 @@ } \ else if (lua_isnumber(ls, 1)) \ lua_pushboolean(ls, val(static_cast( \ - luaL_checkint(ls, 1)))); \ + luaL_safe_checkint(ls, 1)))); \ else if (lua_isstring(ls, 1)) \ lua_pushboolean(ls, val(dungeon_feature_by_name(\ luaL_checkstring(ls, 1))));\ diff --git a/crawl-ref/source/l-file.cc b/crawl-ref/source/l-file.cc index 8344be13f165..572930309a7f 100644 --- a/crawl-ref/source/l-file.cc +++ b/crawl-ref/source/l-file.cc @@ -36,7 +36,7 @@ static int file_marshall(lua_State *ls) writer &th(*static_cast(lua_touserdata(ls, 1))); ASSERT(!lua_isfunction(ls, 2)); if (lua_isnumber(ls, 2)) - marshallInt(th, luaL_checklong(ls, 2)); + marshallInt(th, luaL_safe_checklong(ls, 2)); else if (lua_isboolean(ls, 2)) marshallByte(th, lua_toboolean(ls, 2)); else if (lua_isstring(ls, 2)) diff --git a/crawl-ref/source/l-item.cc b/crawl-ref/source/l-item.cc index 61c2fc4b10ca..a683be2cd51c 100644 --- a/crawl-ref/source/l-item.cc +++ b/crawl-ref/source/l-item.cc @@ -244,7 +244,7 @@ static int l_item_do_drop(lua_State *ls) int qty = item->quantity; if (lua_isnumber(ls, 1)) { - int q = luaL_checkint(ls, 1); + int q = luaL_safe_checkint(ls, 1); if (q >= 1 && q <= item->quantity) qty = q; } @@ -409,7 +409,7 @@ static string _item_name(lua_State *ls, item_def* item) if (lua_isstring(ls, 1)) ndesc = description_type_by_name(lua_tostring(ls, 1)); else if (lua_isnumber(ls, 1)) - ndesc = static_cast(luaL_checkint(ls, 1)); + ndesc = static_cast(luaL_safe_checkint(ls, 1)); const bool terse = lua_toboolean(ls, 2); return item->name(ndesc, terse); } @@ -1045,7 +1045,7 @@ static int l_item_do_dec_quantity(lua_State *ls) } // The quantity to reduce by. - int quantity = luaL_checkint(ls, 1); + int quantity = luaL_safe_checkint(ls, 1); bool destroyed = false; @@ -1073,7 +1073,7 @@ static int l_item_do_inc_quantity(lua_State *ls) } // The quantity to increase by. - int quantity = luaL_checkint(ls, 1); + int quantity = luaL_safe_checkint(ls, 1); if (in_inventory(*item)) inc_inv_item_quantity(item->link, quantity); @@ -1225,7 +1225,7 @@ static int l_item_inventory(lua_State *ls) */ static int l_item_index_to_letter(lua_State *ls) { - int index = luaL_checkint(ls, 1); + int index = luaL_safe_checkint(ls, 1); char sletter[2] = "?"; if (index >= 0 && index <= ENDOFPACK) *sletter = index_to_letter(index); @@ -1255,8 +1255,8 @@ static int l_item_letter_to_index(lua_State *ls) */ static int l_item_swap_slots(lua_State *ls) { - int slot1 = luaL_checkint(ls, 1), - slot2 = luaL_checkint(ls, 2); + int slot1 = luaL_safe_checkint(ls, 1), + slot2 = luaL_safe_checkint(ls, 2); bool verbose = lua_toboolean(ls, 3); if (slot1 < 0 || slot1 >= ENDOFPACK || slot2 < 0 || slot2 >= ENDOFPACK @@ -1290,11 +1290,11 @@ static int dmx_get_qty(lua_State *ls, int ndx, int subndx) { lua_rawgeti(ls, ndx, subndx); if (lua_isnumber(ls, -1)) - qty = luaL_checkint(ls, -1); + qty = luaL_safe_checkint(ls, -1); lua_pop(ls, 1); } else if (lua_isnumber(ls, ndx)) - qty = luaL_checkint(ls, ndx); + qty = luaL_safe_checkint(ls, ndx); return qty; } @@ -1332,7 +1332,7 @@ static int l_item_pickup(lua_State *ls) ITEM(item, 1); int qty = item->quantity; if (lua_isnumber(ls, 2)) - qty = luaL_checkint(ls, 2); + qty = luaL_safe_checkint(ls, 2); if (l_item_pickup2(item, qty)) lua_pushnumber(ls, 1); @@ -1377,7 +1377,7 @@ static int l_item_equipped_at(lua_State *ls) { int eq = -1; if (lua_isnumber(ls, 1)) - eq = luaL_checkint(ls, 1); + eq = luaL_safe_checkint(ls, 1); else if (lua_isstring(ls, 1)) { const char *eqname = lua_tostring(ls, 1); @@ -1425,7 +1425,7 @@ static int l_item_fired_item(lua_State *ls) */ static int l_item_inslot(lua_State *ls) { - int index = luaL_checkint(ls, 1); + int index = luaL_safe_checkint(ls, 1); if (index >= 0 && index < 52 && you.inv[index].defined()) clua_push_item(ls, &you.inv[index]); else @@ -1443,8 +1443,8 @@ static int l_item_inslot(lua_State *ls) static int l_item_get_items_at(lua_State *ls) { coord_def s; - s.x = luaL_checkint(ls, 1); - s.y = luaL_checkint(ls, 2); + s.x = luaL_safe_checkint(ls, 1); + s.y = luaL_safe_checkint(ls, 2); coord_def p = player2grid(s); if (!query_map_knowledge(false, p, [](const map_cell& cell) { diff --git a/crawl-ref/source/l-mapgrd.cc b/crawl-ref/source/l-mapgrd.cc index 422dd573e6c3..17466db1b9de 100644 --- a/crawl-ref/source/l-mapgrd.cc +++ b/crawl-ref/source/l-mapgrd.cc @@ -18,7 +18,7 @@ static int mapgrd_get(lua_State *ls) // Return a metatable for this column in the map grid. map_def *map = *(map_def **) luaL_checkudata(ls, 1, MAPGRD_METATABLE); - int column = luaL_checkint(ls, 2); + int column = luaL_safe_checkint(ls, 2); mapcolumn *mapref = clua_new_userdata(ls, MAPGRD_COL_METATABLE); mapref->map = map; @@ -35,7 +35,7 @@ static int mapgrd_set(lua_State *ls) static char* mapgrd_glyph(lua_State *ls, int &col, int &row) { mapcolumn *mapc = (mapcolumn *)luaL_checkudata(ls, 1, MAPGRD_COL_METATABLE); - row = luaL_checkint(ls, 2); + row = luaL_safe_checkint(ls, 2); col = mapc->col; map_lines &lines = mapc->map->map; diff --git a/crawl-ref/source/l-mapmrk.cc b/crawl-ref/source/l-mapmrk.cc index e4d275b0bd51..61da04b7f555 100644 --- a/crawl-ref/source/l-mapmrk.cc +++ b/crawl-ref/source/l-mapmrk.cc @@ -17,7 +17,7 @@ static int mapmarker_pos(lua_State *ls) static int mapmarker_move(lua_State *ls) { MAPMARKER(ls, 1, mark); - const coord_def dest(luaL_checkint(ls, 2), luaL_checkint(ls, 3)); + const coord_def dest(luaL_safe_checkint(ls, 2), luaL_safe_checkint(ls, 3)); env.markers.move_marker(mark, dest); return 0; } diff --git a/crawl-ref/source/l-mons.cc b/crawl-ref/source/l-mons.cc index e799b6d28093..3923b81dc936 100644 --- a/crawl-ref/source/l-mons.cc +++ b/crawl-ref/source/l-mons.cc @@ -121,7 +121,7 @@ LUAFN(l_mons_add_energy) { ASSERT_DLUA; monster* mons = clua_get_lightuserdata(ls, lua_upvalueindex(1)); - mons->speed_increment += luaL_checkint(ls, 1); + mons->speed_increment += luaL_safe_checkint(ls, 1); return 0; } MDEFN(add_energy, add_energy) @@ -230,7 +230,7 @@ static int l_mons_set_hp(lua_State *ls) monster* mons = clua_get_lightuserdata(ls, lua_upvalueindex(1)); - int hp = luaL_checkint(ls, 1); + int hp = luaL_safe_checkint(ls, 1); if (hp <= 0) { luaL_argerror(ls, 1, "hp must be positive"); @@ -249,7 +249,7 @@ static int l_mons_set_max_hp(lua_State *ls) monster* mons = clua_get_lightuserdata(ls, lua_upvalueindex(1)); - int maxhp = luaL_checkint(ls, 1); + int maxhp = luaL_safe_checkint(ls, 1); if (maxhp <= 0) { luaL_argerror(ls, 1, "maxhp must be positive"); @@ -320,7 +320,7 @@ static int l_mons_do_set_prop(lua_State *ls) // NOTE: number has to be before string, or numbers will get converted // into strings. else if (lua_isnumber(ls, 2)) - mons->props[prop_name].get_int() = luaL_checklong(ls, 2); + mons->props[prop_name].get_int() = luaL_safe_checklong(ls, 2); else if (lua_isstring(ls, 2)) mons->props[prop_name] = lua_tostring(ls, 2); else if (lua_isfunction(ls, 2)) @@ -422,8 +422,8 @@ static int l_mons_do_add_ench(lua_State *ls) return 0; } - mons->add_ench(mon_enchant(met, luaL_checkint(ls, 2), 0, - luaL_checkint(ls, 3))); + mons->add_ench(mon_enchant(met, luaL_safe_checkint(ls, 2), 0, + luaL_safe_checkint(ls, 3))); return 0; } @@ -591,7 +591,7 @@ static int monster_set(lua_State *ls) if (!strcmp(attr, "beh")) { const beh_type beh = - lua_isnumber(ls, 3) ? static_cast(luaL_checkint(ls, 3)) : + lua_isnumber(ls, 3) ? static_cast(luaL_safe_checkint(ls, 3)) : lua_isstring(ls, 3) ? behaviour_by_name(lua_tostring(ls, 3)) : NUM_BEHAVIOURS; @@ -599,9 +599,9 @@ static int monster_set(lua_State *ls) mw->mons->behaviour = beh; } else if (!strcmp(attr, "targetx")) - mw->mons->target.x = luaL_checkint(ls, 3); + mw->mons->target.x = luaL_safe_checkint(ls, 3); else if (!strcmp(attr, "targety")) - mw->mons->target.y = luaL_checkint(ls, 3); + mw->mons->target.y = luaL_safe_checkint(ls, 3); return 0; } diff --git a/crawl-ref/source/l-spells.cc b/crawl-ref/source/l-spells.cc index 15ac97d51007..9c6b8cb0545f 100644 --- a/crawl-ref/source/l-spells.cc +++ b/crawl-ref/source/l-spells.cc @@ -123,8 +123,8 @@ LUAFN(l_spells_path) return 1; } coord_def a; - a.x = luaL_checkint(ls, 2); - a.y = luaL_checkint(ls, 3); + a.x = luaL_safe_checkint(ls, 2); + a.y = luaL_safe_checkint(ls, 3); coord_def aim = player2grid(a); coord_def s; diff --git a/crawl-ref/source/l-subvault.cc b/crawl-ref/source/l-subvault.cc index c4dec998b854..c43213b6f68e 100644 --- a/crawl-ref/source/l-subvault.cc +++ b/crawl-ref/source/l-subvault.cc @@ -25,8 +25,8 @@ static int dgn_subvault_cell_valid(lua_State *ls) { MAP(ls, 1, map); coord_def c; - c.x = luaL_checkint(ls, 2); - c.y = luaL_checkint(ls, 3); + c.x = luaL_safe_checkint(ls, 2); + c.y = luaL_safe_checkint(ls, 3); lua_pushboolean(ls, map->subvault_cell_valid(c)); return 1; diff --git a/crawl-ref/source/l-travel.cc b/crawl-ref/source/l-travel.cc index 019e4b1eacdd..fe348e935de0 100644 --- a/crawl-ref/source/l-travel.cc +++ b/crawl-ref/source/l-travel.cc @@ -22,15 +22,15 @@ LUAFN(l_set_exclude) { coord_def s; - s.x = luaL_checkint(ls, 1); - s.y = luaL_checkint(ls, 2); + s.x = luaL_safe_checkint(ls, 1); + s.y = luaL_safe_checkint(ls, 2); const coord_def p = player2grid(s); if (!in_bounds(p)) return 0; // XXX: dedup w/_get_full_exclusion_radius()? int r = LOS_RADIUS; if (lua_gettop(ls) > 2) - r = luaL_checkint(ls, 3); + r = luaL_safe_checkint(ls, 3); set_exclude(p, r); return 0; } @@ -44,8 +44,8 @@ LUAFN(l_set_exclude) LUAFN(l_del_exclude) { coord_def s; - s.x = luaL_checkint(ls, 1); - s.y = luaL_checkint(ls, 2); + s.x = luaL_safe_checkint(ls, 1); + s.y = luaL_safe_checkint(ls, 2); const coord_def p = player2grid(s); if (!in_bounds(p)) return 0; @@ -100,7 +100,7 @@ LUAFN(l_find_deepest_explored) */ LUAFN(l_waypoint_delta) { - int waynum = luaL_checkint(ls, 1); + int waynum = luaL_safe_checkint(ls, 1); if (waynum < 0 || waynum > 9) return 0; const level_pos waypoint = travel_cache.get_waypoint(waynum); diff --git a/crawl-ref/source/l-view.cc b/crawl-ref/source/l-view.cc index efc1eaa3ecbc..e4b86548dde5 100644 --- a/crawl-ref/source/l-view.cc +++ b/crawl-ref/source/l-view.cc @@ -21,8 +21,8 @@ #include "view.h" #define PLAYERCOORDS(p, p1, p2) \ - const coord_def p = player2grid(coord_def(luaL_checkint(ls,p1), \ - luaL_checkint(ls,p2))); + const coord_def p = player2grid(coord_def(luaL_safe_checkint(ls,p1), \ + luaL_safe_checkint(ls,p2))); /*** What is the feature here? * @tparam int x diff --git a/crawl-ref/source/l-wiz.cc b/crawl-ref/source/l-wiz.cc index 544a511f0e77..b65088b2da32 100644 --- a/crawl-ref/source/l-wiz.cc +++ b/crawl-ref/source/l-wiz.cc @@ -30,7 +30,7 @@ LUAFN(wiz_quick_fsim) string err = make_stringf("No such monster: '%s'.", mon_name.c_str()); return luaL_argerror(ls, 1, err.c_str()); } - const int fsim_rounds = luaL_checkint(ls, 2); + const int fsim_rounds = luaL_safe_checkint(ls, 2); Options.fsim_mons = mon_name; Options.fsim_rounds = fsim_rounds; diff --git a/crawl-ref/source/l-you.cc b/crawl-ref/source/l-you.cc index 643070adc581..b576d2167705 100644 --- a/crawl-ref/source/l-you.cc +++ b/crawl-ref/source/l-you.cc @@ -530,7 +530,7 @@ LUARET1(you_los, number, get_los_radius()) * @function see_cell */ LUARET1(you_see_cell_rel, boolean, - you.see_cell(coord_def(luaL_checkint(ls, 1), luaL_checkint(ls, 2)) + you.pos())) + you.see_cell(coord_def(luaL_safe_checkint(ls, 1), luaL_safe_checkint(ls, 2)) + you.pos())) /*** Can you see this cell without looking through a window? * Checks line of sight treating transparent rock and stone as opaque. * Uses player-centered coordinates. @@ -540,7 +540,7 @@ LUARET1(you_see_cell_rel, boolean, * @function see_cell_no_trans */ LUARET1(you_see_cell_no_trans_rel, boolean, - you.see_cell_no_trans(coord_def(luaL_checkint(ls, 1), luaL_checkint(ls, 2)) + you.pos())) + you.see_cell_no_trans(coord_def(luaL_safe_checkint(ls, 1), luaL_safe_checkint(ls, 2)) + you.pos())) /*** Can you see this cell without something solid in the way? * Checks line of sight treating all solid features as opaque. * Uses player-centered coordinates. @@ -551,8 +551,8 @@ LUARET1(you_see_cell_no_trans_rel, boolean, */ LUARET1(you_see_cell_solid_rel, boolean, cell_see_cell(you.pos(), - (coord_def(luaL_checkint(ls, 1), - luaL_checkint(ls, 2)) + you.pos()), + (coord_def(luaL_safe_checkint(ls, 1), + luaL_safe_checkint(ls, 2)) + you.pos()), LOS_SOLID)) /*** Can you see this cell with nothing in the way? * Checks line of sight treating all solid features as opaque and properly @@ -565,8 +565,8 @@ LUARET1(you_see_cell_solid_rel, boolean, */ LUARET1(you_see_cell_solid_see_rel, boolean, cell_see_cell(you.pos(), - (coord_def(luaL_checkint(ls, 1), - luaL_checkint(ls, 2)) + you.pos()), + (coord_def(luaL_safe_checkint(ls, 1), + luaL_safe_checkint(ls, 2)) + you.pos()), LOS_SOLID_SEE)) /*** Stars of piety. * @treturn int @@ -797,7 +797,7 @@ static int you_gold(lua_State *ls) { if (lua_gettop(ls) >= 1 && !CLua::get_vm(ls).managed_vm) { - const int new_gold = luaL_checkint(ls, 1); + const int new_gold = luaL_safe_checkint(ls, 1); const int old_gold = you.gold; you.set_gold(max(new_gold, 0)); if (new_gold > old_gold) @@ -823,7 +823,7 @@ static int _you_have_rune(lua_State *ls) { int which_rune = NUM_RUNE_TYPES; if (lua_gettop(ls) >= 1 && lua_isnumber(ls, 1)) - which_rune = luaL_checkint(ls, 1); + which_rune = luaL_safe_checkint(ls, 1); else if (lua_gettop(ls) >= 1 && lua_isstring(ls, 1)) { const char *spec = lua_tostring(ls, 1); @@ -1023,7 +1023,7 @@ LUAFN(you_train_skill) skill_type sk = str_to_skill_safe(luaL_checkstring(ls, 1)); if (lua_gettop(ls) >= 2 && can_enable_skill(sk)) { - you.train[sk] = min(max((training_status)luaL_checkint(ls, 2), + you.train[sk] = min(max((training_status)luaL_safe_checkint(ls, 2), TRAINING_DISABLED), TRAINING_FOCUSED); reset_training(); @@ -1275,15 +1275,15 @@ void cluaopen_you(lua_State *ls) // LUARET1(you_can_hear_pos, boolean, - player_can_hear(coord_def(luaL_checkint(ls,1), luaL_checkint(ls, 2)))) + player_can_hear(coord_def(luaL_safe_checkint(ls,1), luaL_safe_checkint(ls, 2)))) LUARET1(you_x_pos, number, you.pos().x) LUARET1(you_y_pos, number, you.pos().y) LUARET2(you_pos, number, you.pos().x, you.pos().y) LUARET1(you_see_cell, boolean, - you.see_cell(coord_def(luaL_checkint(ls, 1), luaL_checkint(ls, 2)))) + you.see_cell(coord_def(luaL_safe_checkint(ls, 1), luaL_safe_checkint(ls, 2)))) LUARET1(you_see_cell_no_trans, boolean, - you.see_cell_no_trans(coord_def(luaL_checkint(ls, 1), luaL_checkint(ls, 2)))) + you.see_cell_no_trans(coord_def(luaL_safe_checkint(ls, 1), luaL_safe_checkint(ls, 2)))) LUAFN(you_stop_running) { @@ -1294,7 +1294,7 @@ LUAFN(you_stop_running) LUAFN(you_moveto) { - const coord_def place(luaL_checkint(ls, 1), luaL_checkint(ls, 2)); + const coord_def place(luaL_safe_checkint(ls, 1), luaL_safe_checkint(ls, 2)); ASSERT(map_bounds(place)); you.moveto(place); return 0; @@ -1302,7 +1302,7 @@ LUAFN(you_moveto) LUAFN(you_teleport_to) { - const coord_def place(luaL_checkint(ls, 1), luaL_checkint(ls, 2)); + const coord_def place(luaL_safe_checkint(ls, 1), luaL_safe_checkint(ls, 2)); bool move_monsters = false; if (lua_gettop(ls) == 3) move_monsters = lua_toboolean(ls, 3); @@ -1355,7 +1355,7 @@ static int _you_piety(lua_State *ls) { if (lua_gettop(ls) >= 1) { - const int new_piety = min(max(luaL_checkint(ls, 1), 0), MAX_PIETY); + const int new_piety = min(max(luaL_safe_checkint(ls, 1), 0), MAX_PIETY); set_piety(new_piety); } PLUARET(number, you.piety); @@ -1363,15 +1363,15 @@ static int _you_piety(lua_State *ls) static int you_dock_piety(lua_State *ls) { - const int piety_loss = luaL_checkint(ls, 1); - const int penance = luaL_checkint(ls, 2); + const int piety_loss = luaL_safe_checkint(ls, 1); + const int penance = luaL_safe_checkint(ls, 2); dock_piety(piety_loss, penance); return 0; } static int you_lose_piety(lua_State *ls) { - const int piety_loss = luaL_checkint(ls, 1); + const int piety_loss = luaL_safe_checkint(ls, 1); lose_piety(piety_loss); return 0; } @@ -1415,7 +1415,7 @@ LUAFN(_you_at_branch_bottom) PLUARET(boolean, at_branch_bottom()); } -LUAWRAP(you_gain_exp, gain_exp(luaL_checkint(ls, 1))) +LUAWRAP(you_gain_exp, gain_exp(luaL_safe_checkint(ls, 1))) LUAFN(you_mutate) { @@ -1489,7 +1489,7 @@ LUAFN(you_change_species) #ifdef WIZARD LUAFN(you_set_xl) { - const int newxl = luaL_checkint(ls, 1); + const int newxl = luaL_safe_checkint(ls, 1); bool train = lua_toboolean(ls, 2); // whether to train skills if (newxl < 1 || newxl > you.get_max_xl()) { @@ -1524,7 +1524,7 @@ LUAFN(you_init) PLUARET(string, skill_name(item_attack_skill(OBJ_WEAPONS, ng.weapon))); } -LUARET1(you_exp_needed, number, exp_needed(luaL_checkint(ls, 1))) +LUARET1(you_exp_needed, number, exp_needed(luaL_safe_checkint(ls, 1))) LUAWRAP(you_exercise, exercise(str_to_skill(luaL_checkstring(ls, 1)), 1)) LUARET1(you_skill_cost_level, number, you.skill_cost_level) LUARET1(you_skill_points, number, From c07d39d5f47b3c974ec2696502d8203c1820d108 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 11 Mar 2019 16:32:23 -0400 Subject: [PATCH 172/864] Revert "Add a build option to not use SSE" No longer necessary. This reverts commit fc1eed5d34c6ec5942309776f806e12eb0ccc867. --- crawl-ref/source/Makefile | 8 -------- 1 file changed, 8 deletions(-) diff --git a/crawl-ref/source/Makefile b/crawl-ref/source/Makefile index 0fc10b93d0a6..4145987821fd 100644 --- a/crawl-ref/source/Makefile +++ b/crawl-ref/source/Makefile @@ -62,8 +62,6 @@ # WEBDIR -- place to hold the Webtiles client data. Can be either # relative to prefix or absolute. # -# NOSSE -- build without SSE support, e.g. on a non-x86 processor. -# Defining this may affect seed stability. # ANDROID -- perform an Android build (see docs/develop/android.txt) # TOUCH_UI -- enable UI behaviour more compatible with touch-screens # @@ -110,16 +108,10 @@ include Makefile.obj # Which C++ standard to support STDFLAG = -std=c++11 -ifdef ANDROID -NOSSE := Yes -endif - CFOTHERS := -pipe $(EXTERNAL_FLAGS) -ifndef NOSSE # force SSE2 dependency, so as to avoid both x87 indeterminacies, and # to prevent lua from using non-standard rounding methods. CFOTHERS += -mfpmath=sse -msse2 -endif CFWARN := CFWARN_L := -Wall -Wformat-security -Wundef From c15b636e9cf1c4702c907fe319bafe0722352ffc Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 11 Mar 2019 16:32:50 -0400 Subject: [PATCH 173/864] Revert "Build for SSE2 on all systems, including 32bit targets" No longer necessary. Results #996 (and #992 in a different way). This reverts commit 3d66cf40a65a3843061e5a6d1106f9fa5d2b0bdb. --- crawl-ref/source/Makefile | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/crawl-ref/source/Makefile b/crawl-ref/source/Makefile index 4145987821fd..7b2c5400a47e 100644 --- a/crawl-ref/source/Makefile +++ b/crawl-ref/source/Makefile @@ -109,9 +109,6 @@ include Makefile.obj STDFLAG = -std=c++11 CFOTHERS := -pipe $(EXTERNAL_FLAGS) -# force SSE2 dependency, so as to avoid both x87 indeterminacies, and -# to prevent lua from using non-standard rounding methods. -CFOTHERS += -mfpmath=sse -msse2 CFWARN := CFWARN_L := -Wall -Wformat-security -Wundef @@ -495,6 +492,21 @@ WINDRES := $(CROSSHOST)-windres endif +# Define this to automatically generate code optimized for your machine +# (GCC only as of now). +# +# NOTE: Don't use this with a release build, since the generated code +# won't work for all machines. +ifdef HURRY +NO_AUTO_OPT = YesPlease +endif + +ifdef AUTO_OPT +ifndef NO_AUTO_OPT +CFOPTIMIZE += -march=native +endif +endif + ifdef USE_ICC # If you have a Core 2 processor, this _really_ makes things fly: #CFOPTIMIZE := -O2 -parallel -xT @@ -516,21 +528,6 @@ else endif endif -# Define this to automatically generate code optimized for your machine -# (GCC only as of now). -# -# NOTE: Don't use this with a release build, since the generated code -# won't work for all machines. -ifdef HURRY -NO_AUTO_OPT = YesPlease -endif - -ifdef AUTO_OPT -ifndef NO_AUTO_OPT -CFOPTIMIZE += -march=native -endif -endif - ifdef LTO ifeq ($(shell $(GXX) -v 2>&1|grep clang),) CFOPTIMIZE += -flto=jobserver -fwhole-program From 1e706217e8ff188799de57579b205fcb313cd36d Mon Sep 17 00:00:00 2001 From: Alan Malloy Date: Mon, 11 Mar 2019 16:02:22 -0700 Subject: [PATCH 174/864] Don't return NaN from prompt_for_float --- crawl-ref/source/prompt.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/prompt.cc b/crawl-ref/source/prompt.cc index 3b1217134e05..6291e6aecd36 100644 --- a/crawl-ref/source/prompt.cc +++ b/crawl-ref/source/prompt.cc @@ -4,6 +4,7 @@ **/ #include "AppHdr.h" +#include // isnan #include "prompt.h" @@ -347,7 +348,7 @@ double prompt_for_float(const char* prompt) char *end; double ret = strtod(specs, &end); - if (ret == 0 && end == specs) + if (ret == 0 && end == specs || isnan(ret)) ret = -1; return ret; From e201941ac7c4b1fc96657424a5e2d94e01646e13 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 11 Mar 2019 16:50:13 -0400 Subject: [PATCH 175/864] Un-revert a Makefile fix This was lumped in with the sse change, doesn't need to be reverted. --- crawl-ref/source/Makefile | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/crawl-ref/source/Makefile b/crawl-ref/source/Makefile index 7b2c5400a47e..7f0b86353940 100644 --- a/crawl-ref/source/Makefile +++ b/crawl-ref/source/Makefile @@ -492,21 +492,6 @@ WINDRES := $(CROSSHOST)-windres endif -# Define this to automatically generate code optimized for your machine -# (GCC only as of now). -# -# NOTE: Don't use this with a release build, since the generated code -# won't work for all machines. -ifdef HURRY -NO_AUTO_OPT = YesPlease -endif - -ifdef AUTO_OPT -ifndef NO_AUTO_OPT -CFOPTIMIZE += -march=native -endif -endif - ifdef USE_ICC # If you have a Core 2 processor, this _really_ makes things fly: #CFOPTIMIZE := -O2 -parallel -xT @@ -528,6 +513,21 @@ else endif endif +# Define this to automatically generate code optimized for your machine +# (GCC only as of now). +# +# NOTE: Don't use this with a release build, since the generated code +# won't work for all machines. +ifdef HURRY +NO_AUTO_OPT = YesPlease +endif + +ifdef AUTO_OPT +ifndef NO_AUTO_OPT +CFOPTIMIZE += -march=native +endif +endif + ifdef LTO ifeq ($(shell $(GXX) -v 2>&1|grep clang),) CFOPTIMIZE += -flto=jobserver -fwhole-program From c3651c4c44431f1d7700df2d1515f9807738aa1c Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 11 Mar 2019 21:32:55 -0400 Subject: [PATCH 176/864] maybe fix the build --- crawl-ref/source/prompt.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/prompt.cc b/crawl-ref/source/prompt.cc index 6291e6aecd36..bb3936cb16aa 100644 --- a/crawl-ref/source/prompt.cc +++ b/crawl-ref/source/prompt.cc @@ -348,7 +348,7 @@ double prompt_for_float(const char* prompt) char *end; double ret = strtod(specs, &end); - if (ret == 0 && end == specs || isnan(ret)) + if (ret == 0 && end == specs || ::isnan(ret)) ret = -1; return ret; From 4d902318472b732ae930f8d934103d35724b2abd Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 12 Mar 2019 09:17:31 -0400 Subject: [PATCH 177/864] Fix build try 2 --- crawl-ref/source/prompt.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/prompt.cc b/crawl-ref/source/prompt.cc index bb3936cb16aa..4304b846c03b 100644 --- a/crawl-ref/source/prompt.cc +++ b/crawl-ref/source/prompt.cc @@ -4,7 +4,7 @@ **/ #include "AppHdr.h" -#include // isnan +#include // isnan #include "prompt.h" @@ -348,7 +348,7 @@ double prompt_for_float(const char* prompt) char *end; double ret = strtod(specs, &end); - if (ret == 0 && end == specs || ::isnan(ret)) + if (ret == 0 && end == specs || std::isnan(ret)) ret = -1; return ret; From 5963e8c6b7bb67c410ff78b59e3e9c53de4a04b7 Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 12 Mar 2019 19:11:27 -0400 Subject: [PATCH 178/864] Convert some floating point math to better fixed point math This math was leading to instability across seeds depending on the particular way in which floating point math was done on a build and system. This uses a suggestion from |amethyst - since callers always use `percent` values that are divisible by 10, can just do the math with a single decimal point rather than two, which takes up a lot less space. This makes the calculation more accurate than what it replaces (though it still truncates, rather than rounds). For that reason, I have put in a temporary stopgap with the quirks of the previous implementation when run using the SSE version of the old floating point calculation. I will remove this at some point after 0.23.2 is tagged. (But for now, this keeps the gotm stable.) --- crawl-ref/source/l-dgnbld.cc | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/crawl-ref/source/l-dgnbld.cc b/crawl-ref/source/l-dgnbld.cc index 11646a338a69..2d655b42e741 100644 --- a/crawl-ref/source/l-dgnbld.cc +++ b/crawl-ref/source/l-dgnbld.cc @@ -1383,13 +1383,27 @@ LUAFN(dgn_widen_paths) if (y2 >= lines.height() - 1) y2 = lines.height() - 2; - float antifraction_each = 1.0 - percent / 100.0f; - float antifraction_current = 1.0; - int percent_for_neighbours[9]; - for (int i = 0; i < 9; i++) + vector percent_for_neighbours; + // these cases are temporary, to keep a particular seed stable for a bit... + // They mimic some floating point quirks of the previous version. + // there's one more case in gehenna that I didn't bother with. + if (percent == 30) + percent_for_neighbours = {0, 30, 52, 66, 76, 84, 89, 92, 95}; + else if (percent == 50) + percent_for_neighbours = {0, 50, 75, 88, 94, 97, 99, 100, 100}; + else { - percent_for_neighbours[i] = 100 - (int)(antifraction_current * 100); - antifraction_current *= antifraction_each; + const long antifraction_each = 10 - percent / 10; // truncates... + long antifraction_current = 10 * antifraction_each; + long divisor = 1; + percent_for_neighbours.push_back(0); + for (int i = 1; i < 9; i++) + { + percent_for_neighbours.push_back( + 100 - antifraction_current / divisor); + antifraction_current *= antifraction_each; + divisor *= 10; + } } // We do not replace this as we go to avoid favouring some directions. From 7a2c91a3c8db3573e3bf56250be95b5c69f4af86 Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 12 Mar 2019 21:12:50 -0400 Subject: [PATCH 179/864] Add a debugging rng call Lets you look one step ahead. --- crawl-ref/source/random.cc | 6 ++++++ crawl-ref/source/random.h | 1 + 2 files changed, 7 insertions(+) diff --git a/crawl-ref/source/random.cc b/crawl-ref/source/random.cc index c5b45edbd0c1..be64976e95c0 100644 --- a/crawl-ref/source/random.cc +++ b/crawl-ref/source/random.cc @@ -82,6 +82,12 @@ uint32_t get_uint32() return get_uint32(_generator); } +uint32_t peek_uint32() +{ + PcgRNG tmp = rngs[_generator]; + return tmp.get_uint32(); +} + uint64_t get_uint64(rng_type generator) { return rngs[generator].get_uint64(); diff --git a/crawl-ref/source/random.h b/crawl-ref/source/random.h index 364cdbed956f..3342fa3d30b5 100644 --- a/crawl-ref/source/random.h +++ b/crawl-ref/source/random.h @@ -32,6 +32,7 @@ uint32_t get_uint32(rng_type generator); uint64_t get_uint64(rng_type generator); uint32_t get_uint32(); uint64_t get_uint64(); +uint32_t peek_uint32(); bool coinflip(); int div_rand_round(int num, int den); int rand_round(double x); From 654ca03102e98d616b074263110b987b04df3162 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Tue, 12 Mar 2019 23:37:17 -0500 Subject: [PATCH 180/864] New transporter and Golubria tiles (CanOfWorms) Transporters, transporter landing sites, and Golubria passages get tiles that better communicate how they are portals that take you to another location. --- crawl-ref/source/rltiles/dngn/transporter.png | Bin 697 -> 1229 bytes .../rltiles/dngn/transporter_landing_site.png | Bin 492 -> 1181 bytes .../rltiles/dngn/traps/passage_of_golubria.png | Bin 312 -> 1251 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/crawl-ref/source/rltiles/dngn/transporter.png b/crawl-ref/source/rltiles/dngn/transporter.png index 4baa0395a3bc26466449c8b75cd9188dc96fb403..7246617455ffbb6500c5774468cbe93a07b3c1da 100644 GIT binary patch literal 1229 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy93=&Q?(RM=#y~cMSA(WJkYY)9 z^mSxl*x1kgCy|wbftew|C&cyt|NlTKUSkQtNI9wLY6{0RvR><~{MdW@&&rSg?tye; z1L6E~D}}gD+o(UT(*3wf_0NN%-~SHaQLm|~>EYp#mX_Ao*tlT9g5$@JzkK-;o57=E zqai@o5GcO>&ID*7W0JSK3quF1tOtlw666=m;PC858j$Vf>EaktF{gEMWFNC3hl{V> zv;DCRwg0)#2^z6(v)=3KtP;g_zBMxD)WwvDpGit$%YHN&thsge?ruB5qyVN@dv|WP zHhlDIt#;IIp*<3hJzh(>SPM2ut~V*!FQ{qo=%MripGQR^4=UGYI;>vd_9)n!OM^AQ zHOn|@%7$1clg1unv4#V)B~utX?)P+C#6B_j%Wy(zMSQZD+j*HR@dU05F9Z*q5p3{t zn5McQ-NCP6_c|Hj73K`w9ZK^UBpLqyXaAtCa4LoUboY_h&qMG1$$MJE*98+;EaIfBe7M< zN;{1;9V+HeD`++7V32%YBi$pvZJpExmpRg_W1{Wf>8dYwP7rZmwBO5n?~u^O7lrry n*Y&FloHyXs<==L!!0I=>-%dYZbpa}MK^>bP0l+XkKLQ~W~ delta 684 zcmV;d0#p6X3AqK38Gi-<0047(dh`GQ00v@9M??Vs0RI60puMM)00009a7bBm000XU z000XU0RWnu7ytkO2XskIMF-&n8v!s9{7L0S0006;Nkl zlDBH>n5oo|y+AysfIS=No*{t5B16$NKxX>`tp0+SpHQ|+V}Evgz8$Wphm%wytxmZB zA&QiEU*|puymu03{7X}uC0rR3)%>3x`JhNTooOooHH^Q_+SS_}C~`jVDzQ5EgEjM- zadlup$|E2FV4w0wnS!`VXsi&kbD0~`&&2Ed6qKpgFmjdvOv@BlrU-n2V5Jax^?H#b z^!fsgrP(O$3x5s#{=sii%!1S=H)NRGTEWf&QT$>_ZWO9r0ssg-An?WH7GT<^4bo4^ zXdn0j`k5xp18n}g7}bGTyW0HKff~j}bHlu`#4;TW%i%Em^rfRE0lNgjN+AG%U4rt6 zdQbz(@(2X}#Cbs8>te?+gh+*)YkFY zLOlRZU4IQtsCC^D`u+W}ZgNk>HS;doUkYhgl&nB_%G}Hi@IsI0-JCH6^+J&{)q9#z ze(mgC3!+R7hMo7ZhbE>ttIzs?V8Kw#I;P)f4J(sQ~C=x+%8jS S%#3>g0000<~{MdW@&&rSg?tye; z1L6E~D}}gD+o(UT(*3wf_0NN%-~SHaQLm|~>EYp#mX_Ao*tlT9g5$@JzkK-;o57=E zqai@o5GcO>&ID*7W0JSK%m1b9pN@h!B|(0{3=Yq3qygDdo-U3d6?5iJj^5N_z~SL zm~7j3FJgR}|7ro}jKgo4Ou9Wf1+$+R+;1@RaNs;6!;-`F!sEa^1~~_r$mcT}_Aul& zxYjUcIQ(PY;B!a%pkI1zsG9Ur@d>k6sQERl4O6aYx9yjiAiefoZzuX1sIVZplx6k(pOelF{r5}E*e)5XjH delta 477 zcmV<30V4jL3G4%q8Gi%-007x@vVQ;o00Lr5M??VshmXv^00009a7bBm000XU000XU z0RWnu7ytkO2XskIMF-&r0SOu@<{p5`0004fNkle_YO+9pMkBNW zgUCcv>z-g7{6wvB%#SXyOvg}&puS#p4hXS20vruDcM0LV(g)*UFA0sKl))Ex2+dtN z@5=Z&fAgTlL4T4YK|ZhY!45o2I^TrQ>fdNnOkwouYnJba^T@Z~~LEoyMi@E5=E z(MDirZ+k~DS%s-wJNTzMGa3YXVdDiGp>vRYS}S4_*}j`xzP@PX0zt}g#FfzhIPsE3 zx=|x#(v<{pg{LfE=(0PO2&&pvNIJA+Ia|H`gpp@b=vHqkl4eAFC@JvgN1pS>G(k>+ zI?LAOdNh-bwV1-rbJo9S(n4h)RP{K#=|WAhu~+4>a=K}7<<~{MdW@&&rSg?tye; z1L6E~D}}gD+o(UT(*3wf_0NN%-~SHaQLm|~>EYp#mX_Ao*tlT9g5$@JzkK-;o57=E zqai@o5GcO>&ID*7W0JSK3quF1tOtlw666=m;PC858jzjf>EaktF{gEM-ZQ1($K+iXK2HV45_**hJuigDSt(;|-6yxXI9sT)9 z&(0oCvpS}J@Ysy&U1ujrbg$4qk;uMitH#R59FP0mV^}4WCOr=@75kVjs$nsER>%sz zz?Uj?Zl727uC z-P-!>g6oFRXwhdgZnoYmSyHx)g`?Q#q0+I%o*U{v1=gjyADa2*`PQj1n=(DREXr@~ zxbbh>?*+!Go_nR|iXT0?bC2|!MdFt}_pP?C*=N&PvD7kScW3J1r#Iu>zU%hz99$~^ Oigr&|KbLh*2~7YXIrDV@ delta 285 zcmV+&0pkAS3Ah4~B!47OOjJbx00000001xm06+i$fB*oX006)M0N?-s{{VphfWZI2 z|NsBr8+K;^0004WQchCcssmJeW84C16P1Y;Bq98qFrd7H0PuY7CCodBR=*yPYXVUR_zxVp0VOc6)rl5x zkvUPW2f%Is$phdYIh=TPgHHdgs~M<{)jI%q-#7un+<*&o0;za-Q5$6M=ke7h+H-#Q j!)r3e$3L&~cNXUtc>xM?D1>A|00000NkvXXu0mjfYC?7! From d121a6d4c08e280d8ccc9d3a319aead044c9f153 Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 13 Mar 2019 14:11:38 -0400 Subject: [PATCH 181/864] Make search_astar more stable across platforms This function is used by slime levelgen in order to ensure level connectivity that doesn't require touching slime walls, and because of this use matters for seeding in slime (both because its behavior impacts what wall squares get removed, and because this astar implementation draws heavily on the rng. The implementation was behaving differently across platforms. Because slime is pretty independent of other branches, the instability was localized to that branch, but usually affected the entire thing. The basic problem is that the search fringe was sorted only by distance in the priority queue, so if two coordinates were the same distance, their ordering in the queue was implementation-dependent (and was differing on mac vs linux builds at least). This fix makes the sort stable in such cases by comparing coordinates as well. This won't necessarily do anything for the speed of the search (perhaps LIFO behavior would be better)... I wonder if this overall approach is really the best way to ensure connectivity in slime? And why does this algorithm need randomization (classic a-star doesn't)? But this code is complicated enough that I'm not going to mess with it further right now. --- crawl-ref/source/nearby-danger.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crawl-ref/source/nearby-danger.h b/crawl-ref/source/nearby-danger.h index df29bcf65de3..82930a5d4c9d 100644 --- a/crawl-ref/source/nearby-danger.h +++ b/crawl-ref/source/nearby-danger.h @@ -91,6 +91,8 @@ struct path_less bool operator()(const set::iterator & left, const set::iterator & right) { + if (left->total_dist() == right->total_dist()) + return left->pos > right->pos; return left->total_dist() > right->total_dist(); } }; From c7eaa0789552f2bd8694c2a2d9db22e00f74e243 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 14 Mar 2019 15:20:27 -0400 Subject: [PATCH 182/864] Improvements to the seed selection ui * make game_seed a sticky preference. This won't override rc preferences or CLI seed selection, but makes it a lot more convenient to dispense with ever setting it in an rc. The main effect is that this autofills the text box in the seed selection sub-menu; it doesn't affect the regular game start button (in contrast to selecting a seed in the regular rc). * Fix a bug where a non-seeded game type could be started with a custom seed, if the game restarted after ending a seeded game started in the same session. * add - as a shortcut to clear the seed input --- crawl-ref/source/initfile.cc | 13 ++++++------- crawl-ref/source/newgame.cc | 10 ++++++++-- crawl-ref/source/ng-setup.cc | 2 ++ crawl-ref/source/startup.cc | 2 ++ 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index 34e773adfe36..191b5e3b5e19 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -1690,6 +1690,8 @@ newgame_def read_startup_prefs() temp.game.job = temp.game.allowed_jobs[0]; if (!temp.game.allowed_weapons.empty()) temp.game.weapon = temp.game.allowed_weapons[0]; + if (!Options.seed_from_rc) + Options.seed = temp.seed_from_rc; return temp.game; #endif // !DISABLE_STICKY_STARTUP_OPTIONS } @@ -1710,6 +1712,8 @@ static void write_newgame_options(const newgame_def& prefs, FILE *f) fprintf(f, "background = %s\n", _job_to_str(prefs.job).c_str()); if (prefs.weapon != WPN_UNKNOWN) fprintf(f, "weapon = %s\n", _weapon_to_str(prefs.weapon).c_str()); + if (prefs.seed != 0) + fprintf(f, "game_seed = %" PRIu64 "\n", prefs.seed); fprintf(f, "fully_random = %s\n", prefs.fully_random ? "yes" : "no"); } #endif // !DISABLE_STICKY_STARTUP_OPTIONS @@ -3425,13 +3429,8 @@ void game_options::read_option_line(const string &str, bool runscript) { // seed_from_rc is only ever set here, or by the CLO. The CLO gets // first crack, so don't overwrite it here. - // Options.seed can be updated in-game from the custom seed menu, - // so also don't overwrite it when the CLO has set it, or the - // player has set it in-game. - if (!Options.seed_from_rc) - Options.seed_from_rc = tmp_seed; - if (!Options.seed) - Options.seed = tmp_seed; + if (!seed_from_rc) + seed_from_rc = tmp_seed; } #endif } diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 09a6beebbd88..7fab5b394be8 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -694,6 +694,11 @@ static void _choose_seed(newgame_def& ng, newgame_def& choice, reader.set_text(timebuf); return done = false; } + else if (key == '-') + { + reader.set_text(""); + return done = false; + } #ifdef USE_TILE_LOCAL else if ((key == 'p' || key == 'P') && wm->has_clipboard()) { @@ -714,7 +719,8 @@ static void _choose_seed(newgame_def& ng, newgame_def& choice, { if (key_is_escape(key)) return done = cancel = true; - return done = true; + if (reader.get_text().size() > 0) + return done = true; } return true; }); @@ -744,7 +750,7 @@ static void _choose_seed(newgame_def& ng, newgame_def& choice, "that you discover. Pregeneration will ensure that these remain\n" "the same no matter what order you explore the dungeon in. (See\n" "the manual for more details.)\n\n"); - prompt.cprintf("Seed:"); + prompt.cprintf("Seed ([-] to clear):"); string seed_text = make_stringf("%-20s", buf); prompt.cprintf("\n%s\n\n", seed_text.c_str()); prompt_ui->set_text(prompt); diff --git a/crawl-ref/source/ng-setup.cc b/crawl-ref/source/ng-setup.cc index 7d538c6ea27b..beda49efa95e 100644 --- a/crawl-ref/source/ng-setup.cc +++ b/crawl-ref/source/ng-setup.cc @@ -383,6 +383,8 @@ void setup_game(const newgame_def& ng) Options.seed = Options.seed_from_rc; crawl_state.type = GAME_TYPE_CUSTOM_SEED; } + else if (Options.seed && ng.type == GAME_TYPE_NORMAL) + Options.seed = 0; else if (!Options.seed && ng.type == GAME_TYPE_CUSTOM_SEED) crawl_state.type = GAME_TYPE_NORMAL; else diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index a0de3a427938..d856f48a7262 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -1385,6 +1385,8 @@ bool startup_step() clear_message_store(); setup_game(ng); newchar = true; + choice.seed = Options.seed; // kind of ugly, but may be changed during + // setup_game. write_newgame_options_file(choice); } crawl_state.default_startup_name = you.your_name; From 890246250bbc7f239d24a39d98b4fd8b4430f663 Mon Sep 17 00:00:00 2001 From: Josh Braden Date: Thu, 14 Mar 2019 21:24:02 -0500 Subject: [PATCH 183/864] Use & instead of equal for holiness check (11909) (#1001) --- crawl-ref/source/mon-death.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/mon-death.cc b/crawl-ref/source/mon-death.cc index a583418b5c2d..3e8f4b53fd81 100644 --- a/crawl-ref/source/mon-death.cc +++ b/crawl-ref/source/mon-death.cc @@ -1716,7 +1716,7 @@ static void _fire_kill_conducts(monster &mons, killer_type killer, mon_holy_type holiness = mons.holiness(); - if (holiness == MH_DEMONIC) + if (holiness & MH_DEMONIC) did_kill_conduct(DID_KILL_DEMON, mons); else if (holiness & (MH_NATURAL | MH_PLANT)) { From cb5ae2cd75adb176013844d9e8642b1698213d6f Mon Sep 17 00:00:00 2001 From: Josh Gelbard Date: Fri, 15 Mar 2019 00:05:16 -0700 Subject: [PATCH 184/864] Start new wanderers with weapon in slot 'a' (#1006) All new characters who start with a weapon wielded will now find that weapon in slot 'a'. This was already true for all backgrounds except wanderer. --- crawl-ref/source/ng-setup.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crawl-ref/source/ng-setup.cc b/crawl-ref/source/ng-setup.cc index beda49efa95e..7b692db5dd12 100644 --- a/crawl-ref/source/ng-setup.cc +++ b/crawl-ref/source/ng-setup.cc @@ -547,6 +547,9 @@ static void _setup_generic(const newgame_def& ng) item_colour(item); // set correct special and colour } + if (you.equip[EQ_WEAPON] > 0) + swap_inv_slots(0, you.equip[EQ_WEAPON], false); + // A second pass to apply the item_slot option. for (auto &item : you.inv) { From c02bd79eda024b4fd058c66282735797166840f0 Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Thu, 7 Mar 2019 20:52:59 +0000 Subject: [PATCH 185/864] Fix cut-off ability cost description (11893) When the Sacrifice Purity ability is granted to the player with the inhibited regeneration mutation, the ability's cost description is Purity (inhibited regeneration) which is 31 characters, however the cost string was only allocated 30 characters, so the last parenthesis was being cut off. Hence, extend the string length for the ability cost description to 32 characters, and adjust the ability screen's title line accordingly. --- crawl-ref/source/ability.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crawl-ref/source/ability.cc b/crawl-ref/source/ability.cc index 033134de4a68..a2d1c3d1826d 100644 --- a/crawl-ref/source/ability.cc +++ b/crawl-ref/source/ability.cc @@ -3224,9 +3224,9 @@ int choose_ability_menu(const vector& talents) // Hack like the one in spl-cast.cc:list_spells() to align the title. ToggleableMenuEntry* me = new ToggleableMenuEntry("Ability - do what? " - "Cost Failure", + "Cost Failure", "Ability - describe what? " - "Cost Failure", + "Cost Failure", MEL_ITEM); me->colour = BLUE; abil_menu.set_title(me, true, true); @@ -3234,9 +3234,9 @@ int choose_ability_menu(const vector& talents) #else abil_menu.set_title( new ToggleableMenuEntry("Ability - do what? " - "Cost Failure", + "Cost Failure", "Ability - describe what? " - "Cost Failure", + "Cost Failure", MEL_TITLE), true, true); #endif abil_menu.set_tag("ability"); @@ -3359,7 +3359,7 @@ string describe_talent(const talent& tal) ostringstream desc; desc << left << chop_string(ability_name(tal.which), 32) - << chop_string(make_cost_description(tal.which), 30) + << chop_string(make_cost_description(tal.which), 32) << chop_string(failure, 12); return trimmed_string(desc.str()); } From 40992d5efd893f74808a4c55009a1f7dc1491580 Mon Sep 17 00:00:00 2001 From: Joshua Gelbard Date: Sat, 9 Mar 2019 00:17:25 -0800 Subject: [PATCH 186/864] Fix splash noises when dropping item into water Added a missing `!`. Behavior was reverse of intended: instead of swimming characters being the only ones exempt from item splash sounds, they were the only ones making them. --- crawl-ref/source/items.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/items.cc b/crawl-ref/source/items.cc index 78c720b3e7fa..e61586386e4e 100644 --- a/crawl-ref/source/items.cc +++ b/crawl-ref/source/items.cc @@ -2614,7 +2614,7 @@ bool drop_item(int item_dropped, int quant_drop) // If you drop an item in as a merfolk, it is below the water line and // makes no noise falling. - if (silenced(you.pos()) || you.swimming()) + if (!you.swimming()) feat_splash_noise(grd(you.pos())); // XP evoker has been handled in copy_item_to_grid From 2784ca5e572ec5611a9b61ed68e711ab1316d7f9 Mon Sep 17 00:00:00 2001 From: Umer Shaikh Date: Thu, 7 Mar 2019 11:13:41 -0600 Subject: [PATCH 187/864] Correct a comment The comment misdescribes when the parameter auto_wield is true or false; this commit brings it in line with the code. --- crawl-ref/source/item-use.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/item-use.cc b/crawl-ref/source/item-use.cc index b065477205d9..7c62bb84bad0 100644 --- a/crawl-ref/source/item-use.cc +++ b/crawl-ref/source/item-use.cc @@ -424,8 +424,8 @@ bool can_wield(const item_def *weapon, bool say_reason, } /** - * @param auto_wield true if this was initiated by the wield weapon command (w) - * false otherwise (e.g. switching between ranged and melee with the + * @param auto_wield false if this was initiated by the wield weapon command (w) + * true otherwise (e.g. switching between ranged and melee with the * auto_switch option) * @param slot Index into inventory of item to equip. Or one of following * special values: From 395302c1d307d6f21c25350a793495b8bc80dba7 Mon Sep 17 00:00:00 2001 From: Umer Shaikh Date: Fri, 8 Mar 2019 21:14:59 -0600 Subject: [PATCH 188/864] Correct a comment Lua function you.contaminated returns a number, not a boolean. --- crawl-ref/source/l-you.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/l-you.cc b/crawl-ref/source/l-you.cc index b576d2167705..edd9aea440ca 100644 --- a/crawl-ref/source/l-you.cc +++ b/crawl-ref/source/l-you.cc @@ -412,7 +412,7 @@ LUARET1(you_silenced, boolean, silenced(you.pos())) */ LUARET1(you_sick, boolean, you.disease) /*** Are you contaminated? - * @treturn boolean + * @treturn number * @function contaminated */ LUARET1(you_contaminated, number, get_contamination_level()) From 5d897e9104ac90bf7eeade97a9fd707dc081109f Mon Sep 17 00:00:00 2001 From: Nikolai Lavsky <3328424+nlavsky@users.noreply.github.com> Date: Fri, 1 Mar 2019 14:01:26 +0300 Subject: [PATCH 189/864] Prevent allied Shambling Mangroves from constricting themselves (11877) --- crawl-ref/source/mon-cast.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/mon-cast.cc b/crawl-ref/source/mon-cast.cc index b0d58b23339d..a80166010928 100644 --- a/crawl-ref/source/mon-cast.cc +++ b/crawl-ref/source/mon-cast.cc @@ -800,7 +800,7 @@ static void _cast_grasping_roots(monster &caster, mon_spell_slot, bolt&) } else { - caster.add_ench(mon_enchant(ENCH_GRASPING_ROOTS, 0, foe, + foe->as_monster()->add_ench(mon_enchant(ENCH_GRASPING_ROOTS, 0, &caster, turns * BASELINE_DELAY)); } } From 063869c3723ef6c111b1614b3be7ad74e54fba85 Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 17 Mar 2019 13:45:54 -0400 Subject: [PATCH 190/864] Run dactions on entering any level, fixing gozag+pregen (Goratrix) Previously, dactions run only on re-entering a level, and not on entering a generated level. For bribe branch, this was dealt with by having the builder set the relevant monster flags when generating a new level. For pregen, this needs to be done on entering the level, and the simplest way was to just run dactions when entering any level; this seems like a cleaner approach they way dactions are thought of anyways. There might actually be a few wrath-related actions that weren't being run as well. I don't *think* there will be unexpected consequences of this, and most dactions won't do anything on a new level. But, it's not impossible that this won't have some strange side effect I missed. --- crawl-ref/source/dungeon.cc | 5 ----- crawl-ref/source/files.cc | 11 +++++++---- crawl-ref/source/tags.cc | 2 ++ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 658ed5b9c772..31b46b37b363 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -272,12 +272,7 @@ bool builder(bool enable_random_maps, dungeon_feature_type dest_stairs_type) try { if (_build_level_vetoable(enable_random_maps, dest_stairs_type)) - { - for (monster_iterator mi; mi; ++mi) - gozag_set_bribe(*mi); - return true; - } } catch (map_load_exception &mload) { diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 18cc853a3efc..581de8b9b32f 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1589,15 +1589,18 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, if (make_changes && env.elapsed_time && !just_created_level) update_level(you.elapsed_time - env.elapsed_time); - // Apply all delayed actions, if any. + // Apply all delayed actions, if any. TODO: logic for marshalling this is + // kind of odd. if (just_created_level) - env.dactions_done = you.dactions.size(); - else - catchup_dactions(); + env.dactions_done = 0; // Here's the second cloud clearing, on load (see above). if (make_changes) { + // this includes various things that are irrelevant for new levels, but + // also some things that aren't, such as bribe branch. + catchup_dactions(); + delete_all_clouds(); _place_player(stair_taken, old_level.branch, return_pos, dest_pos, diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index dd938e13baa1..389dfdfc1291 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -4388,6 +4388,8 @@ static void tag_construct_level(writer &th) env.markers.write(th); env.properties.write(th); + // number of completed dactions. Assume, apparently, that a level can only + // be saved if they're complete? TODO: logic is kind of weird. marshallInt(th, you.dactions.size()); // Save heightmap, if present. From f5976a5f5feca9e6f44341e4665df2a7bcd3acc2 Mon Sep 17 00:00:00 2001 From: Martin Aigner Date: Sun, 24 Jun 2018 22:07:04 +0200 Subject: [PATCH 191/864] Highlight summoners when the cursor is over a summon in targeting mode As suggested by Antares on tavern. --- crawl-ref/source/directn.cc | 98 +++++++++++++++---- crawl-ref/source/directn.h | 10 +- crawl-ref/source/mon-info.h | 1 + crawl-ref/source/tilecell.cc | 1 + crawl-ref/source/tilecell.h | 1 + crawl-ref/source/tiledgnbuf.cc | 3 + crawl-ref/source/tileview.cc | 3 + crawl-ref/source/tileweb.cc | 3 + .../game_data/static/cell_renderer.js | 3 + 9 files changed, 103 insertions(+), 20 deletions(-) diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc index fbde6e26e4a9..8e89490c0abd 100644 --- a/crawl-ref/source/directn.cc +++ b/crawl-ref/source/directn.cc @@ -25,6 +25,7 @@ #include "describe.h" #include "dungeon.h" #include "english.h" +#include "externs.h" // INVALID_COORD #include "fight.h" // melee_confuse_chance #include "food.h" #include "god-abil.h" @@ -518,6 +519,8 @@ direction_chooser::direction_chooser(dist& moves_, hitfunc(args.hitfunc), default_place(args.default_place), unrestricted(args.unrestricted), + summ_loc(INVALID_COORD), + highlight_on_beam(false), needs_path(args.needs_path) { if (!behaviour) @@ -531,7 +534,7 @@ direction_chooser::direction_chooser(dist& moves_, needs_path = true; show_beam = !just_looking && needs_path; - need_beam_redraw = show_beam; + need_viewport_redraw = show_beam; have_beam = false; need_text_redraw = true; @@ -1125,17 +1128,12 @@ static void _draw_ray_cell(coord_def p, coord_def target, aff_type aff) #endif } -void direction_chooser::draw_beam_if_needed() +void direction_chooser::draw_beam() { - if (!need_beam_redraw) - return; - - need_beam_redraw = false; - if (!show_beam) { viewwindow( -#ifndef USE_TILE_LOCAL +#ifndef USE_TILE false #endif ); @@ -1159,8 +1157,13 @@ void direction_chooser::draw_beam_if_needed() ? LOS_NONE : LOS_DEFAULT; for (radius_iterator ri(you.pos(), los); ri; ++ri) if (aff_type aff = hitfunc->is_affected(*ri)) + { _draw_ray_cell(*ri, target(), aff); + if (summ_loc == *ri) + highlight_on_beam = true; + } + #ifdef USE_TILE viewwindow(true, true); #endif @@ -1193,6 +1196,9 @@ void direction_chooser::draw_beam_if_needed() if (p == you.pos()) continue; + if (summ_loc == p) + highlight_on_beam = true; + const bool inrange = in_range(p); #ifdef USE_TILE tile_place_ray(p, inrange ? AFF_YES : AFF_NO); @@ -1596,7 +1602,7 @@ void direction_chooser::toggle_beam() } show_beam = !show_beam; - need_beam_redraw = true; + need_viewport_redraw = true; if (show_beam) { @@ -1676,7 +1682,7 @@ void direction_chooser::handle_wizard_command(command_type key_command, show_beam = true; have_beam = find_ray(you.pos(), target(), beam, opc_solid_see, you.current_vision, show_beam); - need_beam_redraw = true; + need_viewport_redraw = true; return; case CMD_TARGET_WIZARD_DEBUG_PORTAL: @@ -1703,7 +1709,7 @@ void direction_chooser::handle_wizard_command(command_type key_command, if (target() != you.pos()) { wizard_create_feature(target()); - need_beam_redraw = true; + need_viewport_redraw = true; } return; @@ -1785,13 +1791,23 @@ void direction_chooser::do_redraws() if (need_all_redraw) { - need_beam_redraw = true; + need_viewport_redraw = true; need_text_redraw = true; need_cursor_redraw = true; need_all_redraw = false; } - draw_beam_if_needed(); + if (need_viewport_redraw) + { + highlight_on_beam = false; + find_summoner(); + draw_beam(); + // draw_beam calls viewwindow(true) at least one in tiles mode, and + // viewwindow(false) at least once in console, so the old highlight and + // the old beam are both gone here. + highlight_summoner(); + need_viewport_redraw = false; + } if (need_text_redraw) { @@ -1814,6 +1830,53 @@ void direction_chooser::do_redraws() } } +void direction_chooser::find_summoner() +{ + const monster* mon = monster_at(target()); + + if (!mon) + { + summ_loc = INVALID_COORD; + return; + } + + const monster *summ = monster_by_mid(mon -> summoner); + + if (!summ) + summ_loc = INVALID_COORD; + else + summ_loc = summ -> pos(); +} + +void direction_chooser::highlight_summoner() +{ + if (summ_loc == INVALID_COORD) + return; + +#ifdef USE_TILE + monster_info* summ_info = env.map_knowledge(summ_loc).monsterinfo(); + + if (!summ_info) // Can happen, e. g. if the summoner is invisible + return; + + summ_info->mb.set(MB_HIGHLIGHT); + + // The first argument must be false, because otherwise viewwindow would + // wipe any beams we might have drawn, and also reset the monster_info we + // just altered, before it draws anything. + viewwindow(false, true); +#else + char32_t glych = get_cell_glyph(summ_loc).ch; + int col = highlight_on_beam ? RED : CYAN; + col |= COLFLAG_REVERSE; + + const coord_def vp = grid2view(summ_loc); + cgotoxy(vp.x, vp.y, GOTO_DNGN); + textcolour(real_colour(col)); + putwch(glych); +#endif +} + bool direction_chooser::tiles_update_target() { #ifdef USE_TILE @@ -1891,8 +1954,7 @@ bool direction_chooser::do_main_loop() { const bool was_excluded = is_exclude_root(target()); cycle_exclude_radius(target()); - // XXX: abusing need_beam_redraw to force viewwindow call. - need_beam_redraw = true; + need_viewport_redraw = true; const bool is_excluded = is_exclude_root(target()); if (!was_excluded && is_excluded) mpr("Placed new exclusion."); @@ -1990,7 +2052,7 @@ bool direction_chooser::do_main_loop() have_beam = show_beam && find_ray(you.pos(), target(), beam, opc_solid_see, you.current_vision); need_text_redraw = true; - need_beam_redraw = true; + need_viewport_redraw = true; need_cursor_redraw = true; } do_redraws(); @@ -2043,10 +2105,10 @@ bool direction_chooser::choose_direction() { have_beam = find_ray(you.pos(), target(), beam, opc_solid_see, you.current_vision); - need_beam_redraw = have_beam; + need_viewport_redraw = have_beam; } if (hitfunc) - need_beam_redraw = true; + need_viewport_redraw = true; clear_messages(); msgwin_set_temporary(true); diff --git a/crawl-ref/source/directn.h b/crawl-ref/source/directn.h index 36c260e56b87..fb0d03487e24 100644 --- a/crawl-ref/source/directn.h +++ b/crawl-ref/source/directn.h @@ -227,9 +227,12 @@ class direction_chooser void toggle_beam(); void finalize_moves(); - void draw_beam_if_needed(); void do_redraws(); + void draw_beam(); + void highlight_summoner(); + void find_summoner(); + // Whether the current target is you. bool looking_at_you() const; @@ -265,7 +268,7 @@ class direction_chooser // position? // What we need to redraw. - bool need_beam_redraw; + bool need_viewport_redraw; bool need_cursor_redraw; bool need_text_redraw; bool need_all_redraw; // All of the above. @@ -277,6 +280,9 @@ class direction_chooser bool unrestricted; + coord_def summ_loc; + bool highlight_on_beam; + public: // TODO: fix the weird behavior that led to this hack bool needs_path; // Determine a ray while we're at it? diff --git a/crawl-ref/source/mon-info.h b/crawl-ref/source/mon-info.h index 6138f9dc77d8..f4a16dcaf9af 100644 --- a/crawl-ref/source/mon-info.h +++ b/crawl-ref/source/mon-info.h @@ -174,6 +174,7 @@ enum monster_info_flags MB_SLOWLY_DYING, MB_PINNED, MB_VILE_CLUTCH, + MB_HIGHLIGHT, NUM_MB_FLAGS }; diff --git a/crawl-ref/source/tilecell.cc b/crawl-ref/source/tilecell.cc index fa800b316734..020d790c83e1 100644 --- a/crawl-ref/source/tilecell.cc +++ b/crawl-ref/source/tilecell.cc @@ -24,6 +24,7 @@ void packed_cell::clear() flv.feat = 0; flv.special = 0; + is_highlighted = false; is_bloody = false; is_silenced = false; halo = HALO_NONE; diff --git a/crawl-ref/source/tilecell.h b/crawl-ref/source/tilecell.h index a21a9440ea4f..b4426a9ae56a 100644 --- a/crawl-ref/source/tilecell.h +++ b/crawl-ref/source/tilecell.h @@ -21,6 +21,7 @@ struct packed_cell tile_flavour flv; tileidx_t cloud; + bool is_highlighted; bool is_bloody; bool is_silenced; char halo; diff --git a/crawl-ref/source/tiledgnbuf.cc b/crawl-ref/source/tiledgnbuf.cc index 7766b2b78cab..93406107c011 100644 --- a/crawl-ref/source/tiledgnbuf.cc +++ b/crawl-ref/source/tiledgnbuf.cc @@ -369,6 +369,9 @@ void DungeonCellBuffer::pack_background(int x, int y, const packed_cell &cell) m_buf_feat.add(TILE_HALO_GD_NEUTRAL, x, y); else if (att_flag == TILE_FLAG_NEUTRAL) m_buf_feat.add(TILE_HALO_NEUTRAL, x, y); + + if (cell.is_highlighted) + m_buf_feat.add(TILE_HALO_FRIENDLY, x, y); } // Apply the travel exclusion under the foreground if the cell is diff --git a/crawl-ref/source/tileview.cc b/crawl-ref/source/tileview.cc index 72d7f0d8d51d..82217e09f454 100644 --- a/crawl-ref/source/tileview.cc +++ b/crawl-ref/source/tileview.cc @@ -1412,6 +1412,9 @@ void tile_apply_properties(const coord_def &gc, packed_cell &cell) else cell.halo = HALO_NONE; + if (mc.monsterinfo() && mc.monsterinfo()->is(MB_HIGHLIGHT)) + cell.is_highlighted = true; + if (mc.flags & MAP_LIQUEFIED) cell.is_liquefied = true; else if (print_blood && (_suppress_blood(mc) diff --git a/crawl-ref/source/tileweb.cc b/crawl-ref/source/tileweb.cc index 1ec48340c5cb..f8c30020d5e1 100644 --- a/crawl-ref/source/tileweb.cc +++ b/crawl-ref/source/tileweb.cc @@ -1299,6 +1299,9 @@ void TilesFramework::_send_cell(const coord_def &gc, if (next_pc.halo != current_pc.halo) json_write_int("halo", next_pc.halo); + if (next_pc.is_highlighted != current_pc.is_highlighted) + json_write_bool("highlighted", next_pc.is_highlighted); + if (next_pc.is_moldy != current_pc.is_moldy) json_write_bool("moldy", next_pc.is_moldy); diff --git a/crawl-ref/source/webserver/game_data/static/cell_renderer.js b/crawl-ref/source/webserver/game_data/static/cell_renderer.js index b889e4c18f00..c2b940dfc758 100644 --- a/crawl-ref/source/webserver/game_data/static/cell_renderer.js +++ b/crawl-ref/source/webserver/game_data/static/cell_renderer.js @@ -692,6 +692,9 @@ function ($, view_data, main, tileinfo_player, icons, dngn, enums, this.draw_dngn(dngn.HALO_GD_NEUTRAL, x, y); else if (fg.NEUTRAL) this.draw_dngn(dngn.HALO_NEUTRAL, x, y); + + if (cell.highlighted) + this.draw_dngn(dngn.HALO_NEUTRAL, x, y); } From 6afd290f2fd896f9dd92f24f60a10a32536ccb20 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Sun, 17 Mar 2019 16:52:49 -0400 Subject: [PATCH 192/864] Simplify and rename a variable (aidanh) --- crawl-ref/source/directn.cc | 38 +++++-------------- crawl-ref/source/directn.h | 6 +-- crawl-ref/source/mon-info.h | 2 +- crawl-ref/source/tilecell.cc | 2 +- crawl-ref/source/tilecell.h | 2 +- crawl-ref/source/tiledgnbuf.cc | 2 +- crawl-ref/source/tileview.cc | 4 +- crawl-ref/source/tileweb.cc | 8 +++- .../game_data/static/cell_renderer.js | 2 +- 9 files changed, 23 insertions(+), 43 deletions(-) diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc index 8e89490c0abd..c94454cc9dc9 100644 --- a/crawl-ref/source/directn.cc +++ b/crawl-ref/source/directn.cc @@ -519,8 +519,6 @@ direction_chooser::direction_chooser(dist& moves_, hitfunc(args.hitfunc), default_place(args.default_place), unrestricted(args.unrestricted), - summ_loc(INVALID_COORD), - highlight_on_beam(false), needs_path(args.needs_path) { if (!behaviour) @@ -1157,13 +1155,8 @@ void direction_chooser::draw_beam() ? LOS_NONE : LOS_DEFAULT; for (radius_iterator ri(you.pos(), los); ri; ++ri) if (aff_type aff = hitfunc->is_affected(*ri)) - { _draw_ray_cell(*ri, target(), aff); - if (summ_loc == *ri) - highlight_on_beam = true; - } - #ifdef USE_TILE viewwindow(true, true); #endif @@ -1196,9 +1189,6 @@ void direction_chooser::draw_beam() if (p == you.pos()) continue; - if (summ_loc == p) - highlight_on_beam = true; - const bool inrange = in_range(p); #ifdef USE_TILE tile_place_ray(p, inrange ? AFF_YES : AFF_NO); @@ -1799,8 +1789,6 @@ void direction_chooser::do_redraws() if (need_viewport_redraw) { - highlight_on_beam = false; - find_summoner(); draw_beam(); // draw_beam calls viewwindow(true) at least one in tiles mode, and // viewwindow(false) at least once in console, so the old highlight and @@ -1830,26 +1818,18 @@ void direction_chooser::do_redraws() } } -void direction_chooser::find_summoner() +coord_def direction_chooser::find_summoner() { - const monster* mon = monster_at(target()); - - if (!mon) - { - summ_loc = INVALID_COORD; - return; - } - - const monster *summ = monster_by_mid(mon -> summoner); - - if (!summ) - summ_loc = INVALID_COORD; - else - summ_loc = summ -> pos(); + if (const monster* mon = monster_at(target())) + if (const monster *summ = monster_by_mid(mon->summoner)) + return summ->pos(); + return INVALID_COORD; } void direction_chooser::highlight_summoner() { + const coord_def summ_loc = find_summoner(); + if (summ_loc == INVALID_COORD) return; @@ -1859,7 +1839,7 @@ void direction_chooser::highlight_summoner() if (!summ_info) // Can happen, e. g. if the summoner is invisible return; - summ_info->mb.set(MB_HIGHLIGHT); + summ_info->mb.set(MB_HIGHLIGHTED_SUMMONER); // The first argument must be false, because otherwise viewwindow would // wipe any beams we might have drawn, and also reset the monster_info we @@ -1867,7 +1847,7 @@ void direction_chooser::highlight_summoner() viewwindow(false, true); #else char32_t glych = get_cell_glyph(summ_loc).ch; - int col = highlight_on_beam ? RED : CYAN; + int col = CYAN; col |= COLFLAG_REVERSE; const coord_def vp = grid2view(summ_loc); diff --git a/crawl-ref/source/directn.h b/crawl-ref/source/directn.h index fb0d03487e24..b595a38c5f09 100644 --- a/crawl-ref/source/directn.h +++ b/crawl-ref/source/directn.h @@ -231,7 +231,7 @@ class direction_chooser void draw_beam(); void highlight_summoner(); - void find_summoner(); + coord_def find_summoner(); // Whether the current target is you. bool looking_at_you() const; @@ -279,10 +279,6 @@ class direction_chooser static targeting_behaviour stock_behaviour; bool unrestricted; - - coord_def summ_loc; - bool highlight_on_beam; - public: // TODO: fix the weird behavior that led to this hack bool needs_path; // Determine a ray while we're at it? diff --git a/crawl-ref/source/mon-info.h b/crawl-ref/source/mon-info.h index f4a16dcaf9af..fec7b744881b 100644 --- a/crawl-ref/source/mon-info.h +++ b/crawl-ref/source/mon-info.h @@ -174,7 +174,7 @@ enum monster_info_flags MB_SLOWLY_DYING, MB_PINNED, MB_VILE_CLUTCH, - MB_HIGHLIGHT, + MB_HIGHLIGHTED_SUMMONER, NUM_MB_FLAGS }; diff --git a/crawl-ref/source/tilecell.cc b/crawl-ref/source/tilecell.cc index 020d790c83e1..ae694f8aa08d 100644 --- a/crawl-ref/source/tilecell.cc +++ b/crawl-ref/source/tilecell.cc @@ -24,7 +24,7 @@ void packed_cell::clear() flv.feat = 0; flv.special = 0; - is_highlighted = false; + is_highlighted_summoner = false; is_bloody = false; is_silenced = false; halo = HALO_NONE; diff --git a/crawl-ref/source/tilecell.h b/crawl-ref/source/tilecell.h index b4426a9ae56a..960b4a1e0d73 100644 --- a/crawl-ref/source/tilecell.h +++ b/crawl-ref/source/tilecell.h @@ -21,7 +21,7 @@ struct packed_cell tile_flavour flv; tileidx_t cloud; - bool is_highlighted; + bool is_highlighted_summoner; bool is_bloody; bool is_silenced; char halo; diff --git a/crawl-ref/source/tiledgnbuf.cc b/crawl-ref/source/tiledgnbuf.cc index 93406107c011..d0bcb9a885e9 100644 --- a/crawl-ref/source/tiledgnbuf.cc +++ b/crawl-ref/source/tiledgnbuf.cc @@ -370,7 +370,7 @@ void DungeonCellBuffer::pack_background(int x, int y, const packed_cell &cell) else if (att_flag == TILE_FLAG_NEUTRAL) m_buf_feat.add(TILE_HALO_NEUTRAL, x, y); - if (cell.is_highlighted) + if (cell.is_highlighted_summoner) m_buf_feat.add(TILE_HALO_FRIENDLY, x, y); } diff --git a/crawl-ref/source/tileview.cc b/crawl-ref/source/tileview.cc index 82217e09f454..1583615ce9b2 100644 --- a/crawl-ref/source/tileview.cc +++ b/crawl-ref/source/tileview.cc @@ -1412,8 +1412,8 @@ void tile_apply_properties(const coord_def &gc, packed_cell &cell) else cell.halo = HALO_NONE; - if (mc.monsterinfo() && mc.monsterinfo()->is(MB_HIGHLIGHT)) - cell.is_highlighted = true; + if (mc.monsterinfo() && mc.monsterinfo()->is(MB_HIGHLIGHTED_SUMMONER)) + cell.is_highlighted_summoner = true; if (mc.flags & MAP_LIQUEFIED) cell.is_liquefied = true; diff --git a/crawl-ref/source/tileweb.cc b/crawl-ref/source/tileweb.cc index f8c30020d5e1..aee2ec23ba39 100644 --- a/crawl-ref/source/tileweb.cc +++ b/crawl-ref/source/tileweb.cc @@ -1299,8 +1299,12 @@ void TilesFramework::_send_cell(const coord_def &gc, if (next_pc.halo != current_pc.halo) json_write_int("halo", next_pc.halo); - if (next_pc.is_highlighted != current_pc.is_highlighted) - json_write_bool("highlighted", next_pc.is_highlighted); + if (next_pc.is_highlighted_summoner + != current_pc.is_highlighted_summoner) + { + json_write_bool("highlighted_summoner", + next_pc.is_highlighted_summoner); + } if (next_pc.is_moldy != current_pc.is_moldy) json_write_bool("moldy", next_pc.is_moldy); diff --git a/crawl-ref/source/webserver/game_data/static/cell_renderer.js b/crawl-ref/source/webserver/game_data/static/cell_renderer.js index c2b940dfc758..2f015a010f08 100644 --- a/crawl-ref/source/webserver/game_data/static/cell_renderer.js +++ b/crawl-ref/source/webserver/game_data/static/cell_renderer.js @@ -693,7 +693,7 @@ function ($, view_data, main, tileinfo_player, icons, dngn, enums, else if (fg.NEUTRAL) this.draw_dngn(dngn.HALO_NEUTRAL, x, y); - if (cell.highlighted) + if (cell.highlighted_summoner) this.draw_dngn(dngn.HALO_NEUTRAL, x, y); } From dbdffe56c59d64a8f29cbcb2def7ac067858f70f Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Sun, 17 Mar 2019 16:53:20 -0400 Subject: [PATCH 193/864] Tiles for summoner highlighting I went with cyan to match console. Closes #801 --- crawl-ref/source/rltiles/dc-feat.txt | 1 + crawl-ref/source/rltiles/misc/halo_summoner.png | Bin 0 -> 4196 bytes crawl-ref/source/tiledgnbuf.cc | 2 +- .../webserver/game_data/static/cell_renderer.js | 2 +- 4 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 crawl-ref/source/rltiles/misc/halo_summoner.png diff --git a/crawl-ref/source/rltiles/dc-feat.txt b/crawl-ref/source/rltiles/dc-feat.txt index 78699694be68..ee3e47f85b70 100644 --- a/crawl-ref/source/rltiles/dc-feat.txt +++ b/crawl-ref/source/rltiles/dc-feat.txt @@ -669,6 +669,7 @@ effect/heataura2 halo_friendly HALO_FRIENDLY halo_gd_neutral HALO_GD_NEUTRAL halo_neutral HALO_NEUTRAL +halo_summoner HALO_SUMMONER ray RAY ray_multi RAY_MULTI ray_out_of_range RAY_OUT_OF_RANGE diff --git a/crawl-ref/source/rltiles/misc/halo_summoner.png b/crawl-ref/source/rltiles/misc/halo_summoner.png new file mode 100644 index 0000000000000000000000000000000000000000..daa31f0116ea4227fecbd6ec01604bd58e5f6153 GIT binary patch literal 4196 zcmc&%O-vI(7@htgw2CfifD|k=L7NbM(hyIYhA6ES55x!u6EF4Pr6&__9KCt*$eD{b zFwq;99t^SZUvj;wm@j0v(_Y zq!5t>Q(zoi1($4N_kW-)i?RkF+<_<~;MJb<7Gt)%S7cfp;)0@xgIrD(XfT__Rwg5q z&A6~`M8(?n-XS_7U>HWesTZAa_^SbkkDoOeZ<>30g{A+BXb``6hcPe-X25-rXaW_m z9qc*~2FKpYdy!jfz6^#A}rb|XCZfrr*AdK`k zEWQ!(_4N&$PnVjFA_EZb!No!Qz|cAK<$f-Z1uy}g26hbcDF31=)kBO;4QgpIRRf$Bu68asfX}=dcdlt@C1Wm7gIe07&}LwS zubN!#l{|Az?4&Y54Qc@+JeW*vosB3TwhZ4kn1q-|U3<6LUkhv-+d2n!qaQBreOjL9 z47j<&$xY^8-}6e0rKv?tYV+XY_6o#!&7oG#_jZ8Wt6oS-O$QCw_+bIKx9f$B z)U?rnResfKz4-EPZeMCzX`rs4fh@o006(dEp-F0HX&}X90#Fx%P7V~QnWBL>GZ}!% zgkETunsFLfWf}!^>7`CBskur6OU&VzMxoA3rq*bomdqQMjL1-!y+)YB0fV(xr-syu zP@6MAgqc7xheMrdRIOmA2DN}N52^tsi_Bh`Kms1EohMZUwLH|2nX;O$Ycn8VVwTw} z6G&X>tD>+L%E#E$pqAEnWI#4dGke`hCNAOJ4;J=oF~@G${C3Up3o z-iCJJmL?{^O4bC&PB0c@GPcw}^$&{v3)n34wfg*+NMmZj?6oexW(6kd_j6icgvqNL fbb;J8tMYr^_w3Qu&V%lkh$lvUW8N1x0#AMeB|U*; literal 0 HcmV?d00001 diff --git a/crawl-ref/source/tiledgnbuf.cc b/crawl-ref/source/tiledgnbuf.cc index d0bcb9a885e9..9d0c034be63e 100644 --- a/crawl-ref/source/tiledgnbuf.cc +++ b/crawl-ref/source/tiledgnbuf.cc @@ -371,7 +371,7 @@ void DungeonCellBuffer::pack_background(int x, int y, const packed_cell &cell) m_buf_feat.add(TILE_HALO_NEUTRAL, x, y); if (cell.is_highlighted_summoner) - m_buf_feat.add(TILE_HALO_FRIENDLY, x, y); + m_buf_feat.add(TILE_HALO_SUMMONER, x, y); } // Apply the travel exclusion under the foreground if the cell is diff --git a/crawl-ref/source/webserver/game_data/static/cell_renderer.js b/crawl-ref/source/webserver/game_data/static/cell_renderer.js index 2f015a010f08..1e18cdd170d9 100644 --- a/crawl-ref/source/webserver/game_data/static/cell_renderer.js +++ b/crawl-ref/source/webserver/game_data/static/cell_renderer.js @@ -694,7 +694,7 @@ function ($, view_data, main, tileinfo_player, icons, dngn, enums, this.draw_dngn(dngn.HALO_NEUTRAL, x, y); if (cell.highlighted_summoner) - this.draw_dngn(dngn.HALO_NEUTRAL, x, y); + this.draw_dngn(dngn.HALO_SUMMONER, x, y); } From 9bee6ebae348acf1dfbde8e7ff7c774eeff37214 Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 17 Mar 2019 21:07:06 -0400 Subject: [PATCH 194/864] Save seed number in startup prefs on game end The effect of this change is to autofill the seed selection box with the seed from the last ended game. This saves only the seed in a kind of ad hoc way. However, the alternate behavior, which would be to repopulate the entire prefs file from the ended game, isn't trivial -- since it doesn't seem that all startup prefs are actually recoverable from a game save. (That ultimately still may be the most sensible behavior though.) --- crawl-ref/source/end.cc | 7 +++++++ crawl-ref/source/initfile.cc | 14 ++++++++++++++ crawl-ref/source/initfile.h | 1 + 3 files changed, 22 insertions(+) diff --git a/crawl-ref/source/end.cc b/crawl-ref/source/end.cc index 31922f84b479..bd976261d594 100644 --- a/crawl-ref/source/end.cc +++ b/crawl-ref/source/end.cc @@ -20,6 +20,7 @@ #include "god-passive.h" #include "ghost.h" #include "hints.h" +#include "initfile.h" #include "invent.h" #include "item-prop.h" #include "los.h" @@ -431,6 +432,12 @@ NORETURN void end_game(scorefile_entry &se) UNUSED(_exit_type_to_string); #endif +#ifndef DISABLE_STICKY_STARTUP_OPTIONS + // TODO: update all sticky prefs based on the dead char? Right now this + // would lose weapon choice, and random select, as far as I can tell. + save_seed_pref(); +#endif + if (!crawl_state.seen_hups) more(); diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index 191b5e3b5e19..132e6a72bc26 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -1764,6 +1764,20 @@ void save_player_name() #endif // !DISABLE_STICKY_STARTUP_OPTIONS } +#ifndef DISABLE_STICKY_STARTUP_OPTIONS +// TODO: can these functions be generalized? This is called on game end, maybe +// the entire pref should be updated then? +void save_seed_pref() +{ + // Read other preferences + newgame_def prefs = read_startup_prefs(); + prefs.seed = crawl_state.seed; + + // And save + write_newgame_options_file(prefs); +} +#endif // !DISABLE_STICKY_STARTUP_OPTIONS + void read_options(const string &s, bool runscript, bool clear_aliases) { StringLineInput st(s); diff --git a/crawl-ref/source/initfile.h b/crawl-ref/source/initfile.h index 14d16a874499..b51cd9ab1db9 100644 --- a/crawl-ref/source/initfile.h +++ b/crawl-ref/source/initfile.h @@ -75,6 +75,7 @@ struct newgame_def; void write_newgame_options_file(const newgame_def& prefs); void save_player_name(); +void save_seed_pref(); string channel_to_str(int ch); From 6c5f6a5ba46661cd51afd32cbf3a097ae18cc0af Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 18 Mar 2019 09:13:33 -0400 Subject: [PATCH 195/864] Disable seed .pref saving for DGL builds (11928 / kitchen_ace) I didn't do this before because it doesn't actually affect anything about starting a game, but I forgot that .pref reading uses regular options reading, which will trigger an error for dgl builds if game_seed is set. (There may be some harmless instances of this error remaining that will only be visible to server admins until .pref files get rewritten.) --- crawl-ref/source/initfile.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index 132e6a72bc26..89ac6fbb57e7 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -1769,12 +1769,14 @@ void save_player_name() // the entire pref should be updated then? void save_seed_pref() { +#ifndef DGAMELAUNCH // Read other preferences newgame_def prefs = read_startup_prefs(); prefs.seed = crawl_state.seed; // And save write_newgame_options_file(prefs); +#endif } #endif // !DISABLE_STICKY_STARTUP_OPTIONS From 3dc15b603402f012e0c7c2ed0d809d3268c19ef9 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 18 Mar 2019 10:05:10 -0400 Subject: [PATCH 196/864] Don't save seed pref for sprint, tutorial --- crawl-ref/source/initfile.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index 89ac6fbb57e7..a598d3048eb3 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -1770,6 +1770,8 @@ void save_player_name() void save_seed_pref() { #ifndef DGAMELAUNCH + if (!crawl_state.game_standard_levelgen()) + return; // Read other preferences newgame_def prefs = read_startup_prefs(); prefs.seed = crawl_state.seed; From 62cde1d77f5068e375109bb98cd6c28594429ca7 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 18 Mar 2019 12:00:39 -0400 Subject: [PATCH 197/864] Fix meatsprint (11834) Meatsprint distributed monsters by placing them in a secret room, and then letting them walk into permanent teleport traps. The trap changes in 0.23 broke I think several of the assumptions this strategy made, most importantly that tele traps work out of player los (66906bf02876). This commit uses fundamentally the same approach, but instead of teleport traps, uses a dlua call to teleport monsters immediately on placement. It might be even simpler to do some kind of random placement off the bat, but using the teleport code has various nice consequences in terms of finding free spaces, etc. I also didn't put much effort into seeing if there's a simple way to do this without the secret room. It turns out that the previous implementation was letting some degree of rate-limiting via monster random movement happen (I believe placement could fail in cases where a monster didn't move off the spawn point). I have done a rough rebalancing accordingly. With two spawn points instead of 4, the overall spawn numbers are very closely matched; I would guess that there's a slight increase in some of the higher-xp categories on average, but there's plenty of variance so I'm not sure. This may need more rebalancing based on feedback from people who have more experience playing this sprint. Here are some representative spawn numbers at turn 150: 0.23 with 2 spawn points: Monsters: The Meatlord, 25 meat beasts, The Captor, The Defiler, The Servant, 20 eight-headed meat hydras, 23 observers, 13 tyrants, 16 accurseds, 67 meat berserkers, 17 large bags of meat, 16 scourges, 33 destroyers, 13 wretched souls, 20 dreads, 161 bags of meat, 36 fleshlords, and 16 sculptors of flesh. 480 monsters, 35685031 total exp value (33124737 non-uniq) (with 4 spawn points in 0.23 you hit the monster limit so it's more annoying to compile the numbers, but they are unsurprisingly about double this.) 0.22, with 4 spawn points: Monsters: The Meatlord, 21 meat beasts, The Captor, The Defiler, The Servant, 21 eight-headed meat hydras, 14 observers, 18 tyrants, 17 accurseds, 70 meat berserkers, 14 large bags of meat, 18 scourges, 37 destroyers, 21 wretched souls, 16 dreads, 170 bags of meat, 31 fleshlords, and 15 sculptors of flesh. 487 monsters, 32820392 total exp value (30260098 non-uniq) --- crawl-ref/source/dat/des/sprint/meat.des | 41 +++++++++++++++++------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/crawl-ref/source/dat/des/sprint/meat.des b/crawl-ref/source/dat/des/sprint/meat.des index af5707ad0be4..b756ec110bbf 100644 --- a/crawl-ref/source/dat/des/sprint/meat.des +++ b/crawl-ref/source/dat/des/sprint/meat.des @@ -211,6 +211,15 @@ end end + function create_and_tele(x, y, spec) + -- TODO: could we do away with the secret placement room altogether? + m = dgn.create_monster(x, y, spec) + if m then + m.random_teleport() + end + return m + end + function blood_spawns(data, triggerable, triggerer, marker, ev) local phase if triggerer.type == "turn" then @@ -268,12 +277,20 @@ "" .. vile .. "" end --- dgn.create_monster(35, 63, phase) - dgn.create_monster(37, 63, phase) - dgn.create_monster(39, 63, phase) - dgn.create_monster(41, 63, phase) - dgn.create_monster(43, 63, phase) + -- here is a representative sample of what this spawn pattern generates with + -- two spawns per turn by turn 150: + -- + -- Monsters: The Meatlord, 25 meat beasts, The Captor, The Defiler, The Servant, + -- 20 eight-headed meat hydras, 23 observers, 13 tyrants, 16 accurseds, 67 meat + -- berserkers, 17 large bags of meat, 16 scourges, 33 destroyers, 13 wretched + -- souls, 20 dreads, 161 bags of meat, 36 fleshlords, and 16 sculptors of flesh. + -- 480 monsters, 35685031 total exp value (33124737 non-uniq) + + create_and_tele(39, 63, phase) + create_and_tele(41, 63, phase) + -- this isn't in order to spawn anything, it's to set the monster list for + -- shadow creatures. if you.turns() < 230 then dgn.set_random_mon_list("tzitzimitl / nothing") else @@ -281,11 +298,11 @@ end if data.spawn_count == 30 then - dgn.create_monster(33, 63, servant) + create_and_tele(33, 63, servant) elseif data.spawn_count == 60 then - dgn.create_monster(33, 63, captor) + create_and_tele(33, 63, captor) elseif data.spawn_count == 100 then - dgn.create_monster(33, 63, defiler) + create_and_tele(33, 63, defiler) elseif data.spawn_count == 150 then local m_x, m_y = marker:pos() local mons = dgn.mons_at(m_x, m_y) @@ -299,7 +316,7 @@ "" .. border_bottom .. "") crawl.more() elseif data.spawn_count == 300 then - dgn.create_monster(33, 63, avatar) + create_and_tele(33, 63, avatar) -- No message for the Unspeakable. end end @@ -412,8 +429,8 @@ NSUBST: ' = 1:& / *:. KITEM: + = ring of see invisible not_cursed ident:all no_pickup KITEM: * = ring of protection from fire not_cursed ident:all no_pickup SUBST: 1 = 1. +KPROP: - = no_tele_into KFEAT: _ = altar_makhleb -KFEAT: ^ = permanent teleport trap KFEAT: x = rock_wall COLOUR: xX = red TILE: xX = wall_hell @@ -484,8 +501,8 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxXXXXXXXXXXXXXXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -xxxxxxxxxxxxxxxxxxxxxxxxxxX^.^.^.^.^.^.^Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -xxxxxxxxxxxxxxxxxxxxxxxxxxX^^^^^^^^^^^^^Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxX-------------Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxX-------------Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxXXXXXXXXXXXXXXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxJxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx From 76deb67c05ace5a32e319b8a79ec3ebdf9737fab Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Mon, 18 Mar 2019 16:36:25 +0000 Subject: [PATCH 198/864] Don't highlight the summoner of rakshasa illusions And additionally don't highlight the source for perma-summons (such as Twisted Resurrection abominations), since they're not abjured by killing the summoner. --- crawl-ref/source/directn.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc index c94454cc9dc9..5479795e8c45 100644 --- a/crawl-ref/source/directn.cc +++ b/crawl-ref/source/directn.cc @@ -1820,9 +1820,12 @@ void direction_chooser::do_redraws() coord_def direction_chooser::find_summoner() { - if (const monster* mon = monster_at(target())) + const monster* mon = monster_at(target()); + + // Don't leak information about rakshasa mirrored illusions. + if (mon && mon->is_summoned() && !mon->has_ench(ENCH_PHANTOM_MIRROR)) if (const monster *summ = monster_by_mid(mon->summoner)) - return summ->pos(); + return summ->pos(); return INVALID_COORD; } From c186064d31aa64341b39eebe11a4559e90bc04c8 Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Mon, 18 Mar 2019 20:22:52 +0000 Subject: [PATCH 199/864] Don't highlight summoners that are out of LOS Fixes a crash when the summoner is entirely off-screen. --- crawl-ref/source/directn.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc index 5479795e8c45..cd51c5317961 100644 --- a/crawl-ref/source/directn.cc +++ b/crawl-ref/source/directn.cc @@ -1833,7 +1833,7 @@ void direction_chooser::highlight_summoner() { const coord_def summ_loc = find_summoner(); - if (summ_loc == INVALID_COORD) + if (summ_loc == INVALID_COORD || !you.see_cell(summ_loc)) return; #ifdef USE_TILE From aac6ce03dcdc324daee1b5a86a99afc5585766f8 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 18 Mar 2019 17:43:19 -0400 Subject: [PATCH 200/864] Add version number to seed selection menu To try to more clearly cue that this is version-specific. --- crawl-ref/source/command.cc | 2 +- crawl-ref/source/newgame.cc | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc index ddc018caafa4..14e8dfd652fb 100644 --- a/crawl-ref/source/command.cc +++ b/crawl-ref/source/command.cc @@ -103,7 +103,7 @@ static string _get_version_features() { result += make_stringf("Game seed: %" PRIu64, crawl_state.seed); if (Version::history_size() > 1) - result += " (game has been upgraded, seed may be broken)"; + result += " (game has been upgraded, seed may be affected)"; } else result += "Game is not seeded."; diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 7fab5b394be8..0aa3e537c7f4 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -737,7 +737,8 @@ static void _choose_seed(newgame_def& ng, newgame_def& choice, { formatted_string prompt; prompt.textcolour(CYAN); - prompt.cprintf("Play a game with a custom seed.\n\n"); + prompt.cprintf("Play a game with a custom seed for version %s.\n\n", + Version::Long); prompt.textcolour(LIGHTGREY); prompt.cprintf( "Choose 0 for a random seed. Press [d] for today's daily seed.\n" @@ -747,9 +748,10 @@ static void _choose_seed(newgame_def& ng, newgame_def& choice, #endif "\n" "The seed will determine the dungeon layout, monsters, and items\n" - "that you discover. Pregeneration will ensure that these remain\n" - "the same no matter what order you explore the dungeon in. (See\n" - "the manual for more details.)\n\n"); + "that you discover, relative to this version of the game.\n" + "Pregeneration will ensure that these remain the same no matter\n" + "what order you explore the dungeon in. (See the manual for more\n" + "details.)\n\n"); prompt.cprintf("Seed ([-] to clear):"); string seed_text = make_stringf("%-20s", buf); prompt.cprintf("\n%s\n\n", seed_text.c_str()); From f2055891f03d71e7da4261c832e1d593d7ba4fe8 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 18 Mar 2019 18:20:05 -0400 Subject: [PATCH 201/864] Better newgame messaging when a game already exists Before, if a game already existed under the name, any menu option that would start a game with that name prefilled (from prefs) would just load the existing game, regardless of game type. Before seeded games, this only affected tutorial vs. regular games, but it's now even more confusing with seeded games. These menus are still a bit of a mess, so this could use some more work (it might be better to prompt for a different name from the seed menu, or do the check before opening that menu). --- crawl-ref/source/files.cc | 28 +++++++++++++++++++++++++++- crawl-ref/source/newgame.cc | 2 +- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 581de8b9b32f..4e9b625a4099 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -2434,6 +2434,12 @@ bool load_ghosts(int max_ghosts, bool creating_level) return true; } +static string _type_name_processed(game_type t) +{ + string name = game_state::game_type_name_for(t); + return name.size() ? name : "regular"; +} + // returns false if a new game should start instead static bool _restore_game(const string& filename) { @@ -2444,6 +2450,7 @@ static bool _restore_game(const string& filename) // to send enough information to the webtiles client to render the display. // This is just cosmetic for other build targets. unwind_bool save_more(crawl_state.show_more_prompt, false); + game_type menu_game_type = crawl_state.type; clear_message_store(); @@ -2453,7 +2460,8 @@ static bool _restore_game(const string& filename) { // Note: if we are here, the save info was properly read, it would // raise an exception otherwise. - if (yesno(("This game comes from an incompatible version of Crawl (" + if (yesno(("There is an existing game for name '" + you.your_name + + "' from an incompatible version of Crawl (" + you.prev_save_version + ").\n" "Unless you reinstall that version, you can't load it.\n" "Do you want to DELETE that game and start a new one?" @@ -2472,6 +2480,24 @@ static bool _restore_game(const string& filename) you.your_name + " is from an incompatible version and can't be loaded."); } + if (!crawl_state.bypassed_startup_menu + && menu_game_type != crawl_state.type) + { + if (!yesno(("You already have a " + + _type_name_processed(crawl_state.type) + + " game saved under the name '" + you.your_name + "';\n" + "do you want to load that instead?").c_str(), + true, 'n')) + { + you.save->abort(); // don't even rewrite the header + delete you.save; + you.save = 0; + game_ended(game_exit::abort, + "Please use a different name to start a new " + + _type_name_processed(menu_game_type) + " game, then."); + } + } + crawl_state.default_startup_name = you.your_name; // for main menu if (numcmp(you.prev_save_version.c_str(), Version::Long, 2) == -1 diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 0aa3e537c7f4..241adba7958f 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -627,7 +627,7 @@ static void _choose_name(newgame_def& ng, newgame_def& choice) if (!good_name) prompt.cprintf("That's a silly name!"); else if (overwrite_prompt) - prompt.cprintf("Really overwrite? [Y/n]"); + prompt.cprintf("You have an existing game under this name; really overwrite? [Y/n]"); prompt_ui->set_text(prompt); ui::pump_events(); From 19c84a8c189113037b018a16e7fbead4a96a833e Mon Sep 17 00:00:00 2001 From: CanOfWorms Date: Mon, 25 Mar 2019 04:03:40 -0400 Subject: [PATCH 202/864] Update tgw_lugonu_bribe Fix some bribes that are no longer relevant due to changes in god conduct, and adjust some to match flavour better. * Dithmenos bribes are useless items that may be unsuitable for high stealth characters. * Jiyva bribes are removed now that jellies can eat stones. * The Shining One bribes are weapons with evil brands instead of a Poison book. * Zin bribes are changed to focus on the dislike for chaos and transmutations. Lignification potions replace evil weapons, which have been moved to the Shining One. --- crawl-ref/source/dat/des/altar/lugonu_bribe.des | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/crawl-ref/source/dat/des/altar/lugonu_bribe.des b/crawl-ref/source/dat/des/altar/lugonu_bribe.des index 4b21785727b0..2e14cbb10cba 100644 --- a/crawl-ref/source/dat/des/altar/lugonu_bribe.des +++ b/crawl-ref/source/dat/des/altar/lugonu_bribe.des @@ -31,8 +31,8 @@ function callback.tgw_lugonu_bribe_lugonu_item (data, triggerable, scroll of immolation ident:type q:3-6", Cheibriados="potion of haste ident:type q:2-4 /\ good_item quick blade", - Dithmenos="lamp of fire w:5 /\ - good_item " .. weapon .. " ego:flaming ident:type", + Dithmenos="ring of attention ident:type /\ + scroll of noise ident:type q:2-4", Elyvilon="book of Necromancy w:5 /\ book of Death w:5 / book of Unlife w:5", Fedhas="randbook owner:Lugonu spells:necromutation numspells:1 /\ @@ -40,11 +40,12 @@ function callback.tgw_lugonu_bribe_lugonu_item (data, triggerable, numspells:2", Gozag="amulet of the gourmand ident:type /\ randbook owner:Lugonu spells:corpse_rot&animate_dead numspells:2", - Jiyva="stone q:10-20 / large rock q:2-4", Kikubaaqudgha="randbook owner:Lugonu spells:dispel_undead \ numspells:1 / rat corpse w:5 / kobold corpse w:5", Pakellas="staff of energy / crystal ball of energy w:5", - ["the Shining One"]="Young Poisoner's Handbook /\ + ["the Shining One"]="good_item " .. weapon .. " ego:pain ident:type /\ + good_item " .. weapon .. " ego:draining ident:type /\ + good_item " .. weapon .. " ego:vampirism ident:type /\ potion of invisibility ident:type q:3-6", Trog="manual of Spellcasting / manual of Air Magic w:5 /\ manual of Earth Magic w:5 / manual of Fire Magic w:5 /\ @@ -55,10 +56,9 @@ function callback.tgw_lugonu_bribe_lugonu_item (data, triggerable, Xom="manual of Invocations", Yredelemnul= "scroll of holy word ident:type q:2-4 /\ good_item " .. weapon .. " ego:holy_wrath ident:type", - Zin="good_item " .. weapon .. " ego:draining ident:type /\ - good_item " .. weapon .. " ego:pain ident:type /\ - good_item " .. weapon .. " ego:chaos ident:type /\ - wand of polymorph ident:type", + Zin="good_item " .. weapon .. " ego:chaos ident:type /\ + wand of polymorph ident:type /\ + potion of lignification ident:type q:2-4", } data.triggered = true if item[you.god()] ~= nil then From f0bc1e94aeb460106674661d317c3b7122066a22 Mon Sep 17 00:00:00 2001 From: CanOfWorms Date: Mon, 25 Mar 2019 15:28:06 -0400 Subject: [PATCH 203/864] More tweaks to tgw_lugonu_bribe More adjustments to bribes: * Remove Pakellas from the bribe list. * Beogh's "bribe" is changed to an orc corpse. * Remove the book from Kiku's bribe, since the library makes it unlikely that the player will see the contents. --- crawl-ref/source/dat/des/altar/lugonu_bribe.des | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/crawl-ref/source/dat/des/altar/lugonu_bribe.des b/crawl-ref/source/dat/des/altar/lugonu_bribe.des index 2e14cbb10cba..1bd3bd3a2171 100644 --- a/crawl-ref/source/dat/des/altar/lugonu_bribe.des +++ b/crawl-ref/source/dat/des/altar/lugonu_bribe.des @@ -27,8 +27,7 @@ function callback.tgw_lugonu_bribe_lugonu_item (data, triggerable, local item = { ["No God"]="amulet of faith ident:type", Ashenzari="ring of see invisible ident:type", - Beogh="scroll of fear ident:type q:3-6 /\ - scroll of immolation ident:type q:3-6", + Beogh="orc corpse", Cheibriados="potion of haste ident:type q:2-4 /\ good_item quick blade", Dithmenos="ring of attention ident:type /\ @@ -40,9 +39,7 @@ function callback.tgw_lugonu_bribe_lugonu_item (data, triggerable, numspells:2", Gozag="amulet of the gourmand ident:type /\ randbook owner:Lugonu spells:corpse_rot&animate_dead numspells:2", - Kikubaaqudgha="randbook owner:Lugonu spells:dispel_undead \ - numspells:1 / rat corpse w:5 / kobold corpse w:5", - Pakellas="staff of energy / crystal ball of energy w:5", + Kikubaaqudgha="rat corpse / kobold corpse", ["the Shining One"]="good_item " .. weapon .. " ego:pain ident:type /\ good_item " .. weapon .. " ego:draining ident:type /\ good_item " .. weapon .. " ego:vampirism ident:type /\ From 6c8b4ebd3a968e5987c4e264c80bdbe8b0087966 Mon Sep 17 00:00:00 2001 From: Kyle Rawlins Date: Wed, 27 Mar 2019 22:06:54 -0400 Subject: [PATCH 204/864] Small tweaks to the .deb guide [skip ci] --- crawl-ref/docs/develop/release/debian.txt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/crawl-ref/docs/develop/release/debian.txt b/crawl-ref/docs/develop/release/debian.txt index 75c9f89b089b..62046ef88d10 100644 --- a/crawl-ref/docs/develop/release/debian.txt +++ b/crawl-ref/docs/develop/release/debian.txt @@ -44,7 +44,7 @@ at least BASEPATH, BUILDPLACE, BUILDRESULT, and APTCACHE. This should get you the necessary packages: - sudo apt-get install cowbuilder + sudo apt-get install cowbuilder debhelper 1.3 Create a .cow chroot directory for each architecture. @@ -62,6 +62,9 @@ To create these, run the following: sudo cowbuilder --create --architecture i386 \ --basepath /var/cache/pbuilder/stable-i386.cow +In order for these to run succesfully in docker, you will need to be running +the docker image with --privileged. + This chroot directory needs to be created only once for each OS/ARCH/DIST combination on which you what to build the package. If It doesn't need to be recreated if you're only building a different DCSS version, but if you're using @@ -91,7 +94,7 @@ give you a valid timestamp: date +'%a, %d %b %Y %R:%S %z' -The entire entry must mach the format of previous entries; note the lines +The entire entry must match the format of previous entries; note the lines following the first `crawl' line have leading spaces. Incorrect formatting can cause debuild and hence pbuilder to fail. @@ -128,7 +131,7 @@ rename the original file. Using version 0.17 as an example and with mkdir -p ~/crawl-deb cp stone_soup-0.17.0-nodeps.tar.xz ~/crawl-deb cd ~/crawl-deb - tar Jxf stone_soup-0.17.0.tar.xz + tar Jxf stone_soup-0.17.0-nodeps.tar.xz mv stone_soup-0.17.0 crawl-0.17.0 mv stone_soup-0.17.0-nodeps.tar.xz crawl_0.17.0.orig.tar.xz From 1d96822bd8ed83a27943f686bd6f35a3e0664069 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Wed, 27 Mar 2019 22:48:39 -0500 Subject: [PATCH 205/864] Remove a digging Trove The map trove_dig had the player individually dig out 20 items with dig wands, but this is very tedious. The items in this trove are just typical trove items, so the map isn't otherwise bringing anything interesting to the portal. --- crawl-ref/source/dat/des/portals/trove.des | 40 ---------------------- 1 file changed, 40 deletions(-) diff --git a/crawl-ref/source/dat/des/portals/trove.des b/crawl-ref/source/dat/des/portals/trove.des index d8b055a114d2..901c6764ddc1 100644 --- a/crawl-ref/source/dat/des/portals/trove.des +++ b/crawl-ref/source/dat/des/portals/trove.des @@ -963,46 +963,6 @@ xxxxx xdx xfx xfx xxx xxx xxx ENDMAP -# 20 items, but you have to dig for them. Wand is included. -NAME: trove_dig -TAGS: no_item_gen no_monster_gen allow_dup -WEIGHT: 5 -ORIENT: encompass -ITEM: acquire armour / any useful armour good_item / any armour w:2 -ITEM: acquire weapon / any useful weapon good_item / any weapon w:2 -ITEM: acquire jewellery / any useful jewellery good_item / any jewellery w:2 -ITEM: any useful armour good_item / any useful weapon good_item / \ - any useful jewellery good_item -: trove.good_scroll(_G) -KITEM: h = wand of digging ident:all, wand of digging ident:all -SHUFFLE: defg -: trove.setup_features(_G) -MAP - vvvvv -vvv...vvv -vem.<.mfv -vvv...vvv -vem...mfv -vvv...vvv -vem...mfv -vvv...vvv -vem...mfv -vvv...vvv -vem...mfv -vvv.h.vvv -vdm...mgv -vvv...vvv -vdm...mgv -vvv...vvv -vdm...mgv -vvv...vvv -vdm...mgv -vvv...vvv -vdm.A.mgv -vvv...vvv - vvvvv -ENDMAP - # 16 pieces of armour NAME: trove_armour_six_rooms TAGS: no_item_gen no_monster_gen allow_dup no_species_fe no_species_op From 696e1f2bf7e3024675cc207daec8b63bb9c06ffc Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Mon, 25 Mar 2019 14:32:24 +0000 Subject: [PATCH 206/864] Don't place shafts in ebering_ghost_disaster_area (11926) This commit prevents the vaults ebering_ghost_disaster_area and ebering_vaults_ghost_disaster_area from placing shaft traps, instead placing only water and lava tiles, implementing option 2 in 11926. This change is to prevent ghosts in these vaults from being shafted immediately when they enter line of sight of the player, before the player can do anything to stop this. These vaults were introduced by commits bb431e2 and a6a7277 respectively, and appear to have been introduced with the idea that ghosts cannot be shafted. Ghosts can now be shafted, as of 8c2e593, and this means that these vaults in particular could cause ghosts to be shafted to lower floors, leaving behind an empty (or mostly empty) ghost vault for the player to raid, and allowing the ghost to be encountered outside of its vault on a lower floor, with the player then unable to choose whether to fight the ghost. --- crawl-ref/source/dat/des/branches/vaults_rooms_ghost.des | 7 +------ crawl-ref/source/dat/des/variable/ghost.des | 7 +------ 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/crawl-ref/source/dat/des/branches/vaults_rooms_ghost.des b/crawl-ref/source/dat/des/branches/vaults_rooms_ghost.des index f5c9142a73f4..0218d63b45d8 100644 --- a/crawl-ref/source/dat/des/branches/vaults_rooms_ghost.des +++ b/crawl-ref/source/dat/des/branches/vaults_rooms_ghost.des @@ -256,14 +256,9 @@ ENDMAP NAME: ebering_vaults_ghost_disaster_area TAGS: vaults_orient_s KMONS: O = player ghost -NSUBST: ' = d / e / 8=wWlr / . +NSUBST: ' = d / e / 8=wWl / . : lone_ghost_guarded_loot(_G, "O") : lone_ghost_extra_loot(_G, ".") -: if you.depth() < dgn.br_depth(you.branch()) then -KFEAT: r = known shaft trap -: else -SUBST: r = wWl -: end SUBST: P = GTV : vaults_ghost_setup(_G) MAP diff --git a/crawl-ref/source/dat/des/variable/ghost.des b/crawl-ref/source/dat/des/variable/ghost.des index c10ff4438e6f..394a04bc259b 100644 --- a/crawl-ref/source/dat/des/variable/ghost.des +++ b/crawl-ref/source/dat/des/variable/ghost.des @@ -451,14 +451,9 @@ ENDMAP NAME: ebering_ghost_disaster_area ORIENT: float KMONS: O = player ghost -NSUBST: ' = d / e / 8=wWlr / - +NSUBST: ' = d / e / 8=wWl / - : lone_ghost_guarded_loot(_G, "O") : lone_ghost_extra_loot(_G, "-") -: if you.depth() < dgn.br_depth(you.branch()) then -KFEAT: r = known shaft trap -: else -SUBST: r = wWl -: end SUBST: P = GTV : ghost_setup(_G) MAP From c779bbd14b3b7bb4aa4718134b3d1567defdd789 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 28 Mar 2019 14:29:12 -0400 Subject: [PATCH 207/864] Don't let overwrite_floor_cell place on transporter markers (11936) This crash was happening because the abyss entry portal for depths 4 placed on top of a transporter map marker, and those markers get turned into transporters fairly late in levelgen in a way that unconditionally overwrites whatever features are there. Then the game crashed on the map debug scan because a portal is supposed to be guaranteed on this level. This fix explicitly checks for this kind of marker when placing vaults that have overwrite_floor_cell; this tag is used for all the fallback entry vaults for depth, as well as uniq vaults (where this issue doesn't matter). This solution fixes this exact problem but does point towards other potential levelgen issues, in that transporters are treated as floor terrain until the very last minute. I wonder if it might work better to place transporter features with the markers, and then only do the connection part at the end of levelgen? But it's also possible that this won't come up too much, since aside from this case I don't think there's a way to overwrite any transporter vaults. --- crawl-ref/source/maps.cc | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/maps.cc b/crawl-ref/source/maps.cc index 9f9fdd33038f..4d0adce313dc 100644 --- a/crawl-ref/source/maps.cc +++ b/crawl-ref/source/maps.cc @@ -397,6 +397,13 @@ static bool _is_portal_place(const coord_def &c) return _marker_is_portal(env.markers.find(c, MAT_LUA_MARKER)); } +static bool _is_transporter_place(const coord_def &c) +{ + auto m = env.markers.find(c, MAT_LUA_MARKER); + return m && (!m->property(TRANSPORTER_NAME_PROP).empty() + || !m->property(TRANSPORTER_DEST_NAME_PROP).empty()); +} + static bool _map_safe_vault_place(const map_def &map, const coord_def &c, const coord_def &size) @@ -440,12 +447,14 @@ static bool _map_safe_vault_place(const map_def &map, return false; } } - else if (grd(cp) != DNGN_FLOOR || env.pgrid(cp) & FPROP_NO_TELE_INTO) + else if (grd(cp) != DNGN_FLOOR || env.pgrid(cp) & FPROP_NO_TELE_INTO + || _is_transporter_place(cp)) { // Don't place overwrite_floor_cell vaults on anything but floor or // on squares that can't be teleported into, because // overwrite_floor_cell is used for things that are expected to be - // connected. + // connected. Don't place on transporter markers, because these will + // later themselves overwrite whatever feature this vault places. return false; } From 17bec22d17066b0ea76488563c2e03f0d7c4404c Mon Sep 17 00:00:00 2001 From: gammafunk Date: Thu, 28 Mar 2019 16:20:51 -0500 Subject: [PATCH 208/864] Don't try to generate Labyrinths in mapstat (vt) When running mapstat without any level specification, which implicitly means "all dungeon levels", don't include Labs. Labs no longer have a layout, so trying to generate the branch will crash. --- crawl-ref/source/dbg-maps.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/dbg-maps.cc b/crawl-ref/source/dbg-maps.cc index 9edac687eaa2..f28d3c8a9533 100644 --- a/crawl-ref/source/dbg-maps.cc +++ b/crawl-ref/source/dbg-maps.cc @@ -189,8 +189,8 @@ static void _dungeon_places() if (brdepth[it->id] == -1) continue; #if TAG_MAJOR_VERSION == 34 - // Don't want to include Forest since it doesn't generate - if (it->id == BRANCH_FOREST) + // Don't want to include branches that no longer generate. + if (it->id == BRANCH_FOREST || it->id == BRANCH_LABYRINTH) continue; #endif From 0fa666e6e4fdeaac18780adcc9ca711271a75b6c Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Fri, 22 Mar 2019 22:08:01 +0000 Subject: [PATCH 209/864] Let formicids dig statues (Yermak) Previously, the types of walls that formicids could dig was hardcoded in move_player_action. This commit changes the check to use the function feat_is_diggable, the same check that is used for digging wands, to make formicid digging exactly equivalent to the wand form. --- crawl-ref/source/movement.cc | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/crawl-ref/source/movement.cc b/crawl-ref/source/movement.cc index 55a2d24a17ba..03bae169b490 100644 --- a/crawl-ref/source/movement.cc +++ b/crawl-ref/source/movement.cc @@ -592,12 +592,8 @@ void move_player_action(coord_def move) you.digging = false; canned_msg(MSG_TOO_HUNGRY); } - else if (grd(targ) == DNGN_ROCK_WALL - || grd(targ) == DNGN_CLEAR_ROCK_WALL - || grd(targ) == DNGN_GRATE) - { + else if (feat_is_diggable(grd(targ))) targ_pass = true; - } else // moving or attacking ends dig { you.digging = false; From bac502f846c4c5338d1bfce96f12f3b4b5941218 Mon Sep 17 00:00:00 2001 From: Andrew O'Neill Date: Wed, 20 Mar 2019 17:15:20 -0700 Subject: [PATCH 210/864] Fix CMD_MAP_UNFORGET in colemak keybindings CMD_MAP_UNFORGET is overwritten in colemak_command_keys.txt I propose setting it to F since it is similar to CMD_MAP_FORGET [^F] --- crawl-ref/settings/colemak_command_keys.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crawl-ref/settings/colemak_command_keys.txt b/crawl-ref/settings/colemak_command_keys.txt index 978c507637ce..e8e28e225da3 100644 --- a/crawl-ref/settings/colemak_command_keys.txt +++ b/crawl-ref/settings/colemak_command_keys.txt @@ -63,6 +63,9 @@ bindkey = [U] CMD_MAP_FIND_EXCLUDED bindkey = [^U] CMD_TOGGLE_TRAVEL_SPEED bindkey = [^U] CMD_MAP_CLEAR_EXCLUDES +# fix overwrite on ^U +bindkey = [F] CMD_MAP_UNFORGET + # replace (i) with (y) bindkey = [y] CMD_DISPLAY_INVENTORY bindkey = [Y] CMD_DISPLAY_SPELLS From 51c60a924a4056f1f4d46b24d692d8b83cd07594 Mon Sep 17 00:00:00 2001 From: Joshua Gelbard Date: Mon, 25 Mar 2019 21:44:47 -0700 Subject: [PATCH 211/864] Don't ignore autopickup settings after autobutcher Food generated by autobutchery was being allowed to re-use the item_needs_autopickup result from back when it was a corpse. Force it to be re-checked after creation instead. --- crawl-ref/source/items.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crawl-ref/source/items.cc b/crawl-ref/source/items.cc index e61586386e4e..031b68364110 100644 --- a/crawl-ref/source/items.cc +++ b/crawl-ref/source/items.cc @@ -3214,10 +3214,8 @@ static void _do_autopickup() if (you_are_delayed() && current_delay()->want_autoeat()) butchery(&mi); else - { o = next; - continue; - } + continue; } // Do this before it's picked up, otherwise the picked up From 90687ab01aaf90c674d47bec0fbce9eb336946bc Mon Sep 17 00:00:00 2001 From: Joshua Gelbard Date: Wed, 27 Mar 2019 00:56:49 -0700 Subject: [PATCH 212/864] Add new message for re-corroding a corroded foe When reapplying ENCH_CORROSION on a monster, make it clearer in the printed message that it's just a duration increase and not a stacking effect. Old: zap wand of acid -> The acid corrodes the death yak! -> zap -> The acid corrodes the death yak! New: zap wand of acid -> The acid corrodes the death yak! -> zap -> The death yak seems to be corroded for longer. --- crawl-ref/source/monster.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/monster.cc b/crawl-ref/source/monster.cc index d6c7bb2ad2a1..fbb36c7b0047 100644 --- a/crawl-ref/source/monster.cc +++ b/crawl-ref/source/monster.cc @@ -4348,9 +4348,10 @@ bool monster::corrode_equipment(const char* corrosion_source, int degree) if (you.see_cell(pos())) { - mprf("%s corrodes %s!", - corrosion_source, - name(DESC_THE).c_str()); + if (!has_ench(ENCH_CORROSION)) + mprf("%s corrodes %s!", corrosion_source, name(DESC_THE).c_str()); + else + mprf("%s seems to be corroded for longer.", name(DESC_THE).c_str()); } add_ench(mon_enchant(ENCH_CORROSION, 0)); From 3ca0c319c68e9471105be357245b8cb46b38a224 Mon Sep 17 00:00:00 2001 From: kitchen-ace <68k@quikphix.org> Date: Sat, 2 Mar 2019 01:01:21 -0500 Subject: [PATCH 213/864] Merge Piercer into the storm bow The storm bow is functionally the same as a +8 elec longbow; fairly strong, but unremarkable. Piercer is a little better since it's a bow user's only way to get a penetration weapon, but that's still not too special. Adding a penetration effect to the storm bow makes it much more exciting, fits the electric/lightning theme, and puts it almost on par with the other unrand bow Zephyr. This also makes Piercer obsolete. --- crawl-ref/source/art-data.txt | 3 +++ crawl-ref/source/dat/descript/unrand.txt | 8 ++------ crawl-ref/source/throw.cc | 4 +++- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/crawl-ref/source/art-data.txt b/crawl-ref/source/art-data.txt index 79ddecb3b44b..aa1ec632ce8f 100644 --- a/crawl-ref/source/art-data.txt +++ b/crawl-ref/source/art-data.txt @@ -539,6 +539,7 @@ BRAND: SPWPN_VORPAL BOOL: seeinv INSCRIP: Acc+∞ +# TAG_MAJOR_VERSION == 34 NAME: longbow "Piercer" OBJ: OBJ_WEAPONS/WPN_LONGBOW PLUS: +7 @@ -547,6 +548,7 @@ TILE: urand_piercer TILE_EQ: great_bow BRAND: SPWPN_PENETRATION EV: -2 +BOOL: nogen # TAG_MAJOR_VERSION == 34 ENUM: BLOWGUN_ASSASSIN @@ -654,6 +656,7 @@ COLOUR: BLUE TILE: urand_storm_bow TILE_EQ: storm_bow BRAND: SPWPN_ELECTROCUTION +INSCRIP: penet NAME: large shield of Ignorance OBJ: OBJ_ARMOUR/ARM_LARGE_SHIELD diff --git a/crawl-ref/source/dat/descript/unrand.txt b/crawl-ref/source/dat/descript/unrand.txt index fe94c0fb5f97..3458ad9c3d33 100644 --- a/crawl-ref/source/dat/descript/unrand.txt +++ b/crawl-ref/source/dat/descript/unrand.txt @@ -281,12 +281,8 @@ relieve opponents of their weapons, dealing extra damage in the process. %%%% storm bow -A longbow with the colour of dark rain clouds. -{{ - if you.can_smell() then - return "It smells like a storm just past, or one about to begin." - end -}} +A longbow with the colour of dark rain clouds that fires arrows like +lightning. %%%% large shield of Ignorance diff --git a/crawl-ref/source/throw.cc b/crawl-ref/source/throw.cc index 1eb8f087b404..945e1a0f1093 100644 --- a/crawl-ref/source/throw.cc +++ b/crawl-ref/source/throw.cc @@ -10,6 +10,7 @@ #include #include +#include "art-enum.h" #include "artefact.h" #include "chardump.h" #include "command.h" @@ -60,7 +61,8 @@ bool is_penetrating_attack(const actor& attacker, const item_def* weapon, && get_ammo_brand(projectile) == SPMSL_PENETRATION || weapon && is_launched(&attacker, weapon, projectile) == launch_retval::LAUNCHED - && get_weapon_brand(*weapon) == SPWPN_PENETRATION; + && (get_weapon_brand(*weapon) == SPWPN_PENETRATION + || is_unrandom_artefact(*weapon, UNRAND_STORM_BOW)); } bool item_is_quivered(const item_def &item) From cd7e529e91d7e8728f7ebdc0c500fc19dceeffdd Mon Sep 17 00:00:00 2001 From: Umer Shaikh Date: Mon, 11 Mar 2019 18:28:37 -0500 Subject: [PATCH 214/864] Remove use of testbits in is_valid_shaft_effect_level Testbits isn't necessary here; it's sufficient to use & to see whether the branch has the dangerous_end flag. This is at least as easy to read and removes an unnecessary equality test. Note that this is what do_trap_effects already does in its version of this logic. --- crawl-ref/source/traps.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/traps.cc b/crawl-ref/source/traps.cc index 1eec140bfb0d..fba5d8d1f2f5 100644 --- a/crawl-ref/source/traps.cc +++ b/crawl-ref/source/traps.cc @@ -1320,7 +1320,7 @@ bool is_valid_shaft_effect_level() // Don't shaft the player when we can't, and also when it would be into a // dangerous end. return is_valid_shaft_level() - && !(testbits(branch.branch_flags, brflag::dangerous_end) + && !(branch.branch_flags & brflag::dangerous_end && brdepth[place.branch] - place.depth == 1); } From 494fbaca61bf1c37b3c1a40957ed56d065e8be36 Mon Sep 17 00:00:00 2001 From: Umer Shaikh Date: Mon, 11 Mar 2019 18:43:50 -0500 Subject: [PATCH 215/864] Use a function instead of duplicating logic The function do_trap_effects duplicates logic from is_valid_shaft_effect_level. The latter function is apparently never called. I suspect the intention was for do_trap_effects to call is_valid_shaft_effect_level and the author forgot to make the change. In any case, this commit removes the logic from do_trap_effects and inserts a call to is_valid_shaft_effect_level. --- crawl-ref/source/traps.cc | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/crawl-ref/source/traps.cc b/crawl-ref/source/traps.cc index fba5d8d1f2f5..88099eb60e77 100644 --- a/crawl-ref/source/traps.cc +++ b/crawl-ref/source/traps.cc @@ -1373,9 +1373,6 @@ void roll_trap_effects() */ void do_trap_effects() { - const level_id place = level_id::current(); - const Branch &branch = branches[place.branch]; - // Try to shaft, teleport, or alarm the player. int roll = random2(3); switch (roll) @@ -1383,9 +1380,7 @@ void do_trap_effects() case 0: // Don't shaft the player when we can't, and also when it would be into a // dangerous end. - if (is_valid_shaft_level() - && !(branch.branch_flags & brflag::dangerous_end - && brdepth[place.branch] - place.depth == 1)) + if (is_valid_shaft_effect_level()) { dprf("Attempting to shaft player."); you.do_shaft(); From b3ba8b5ca559d862345649a73512538822f9844d Mon Sep 17 00:00:00 2001 From: Umer Shaikh Date: Mon, 11 Mar 2019 20:46:06 -0500 Subject: [PATCH 216/864] Refer to function by name, not position, in comment This makes the comment a little less likely to go out of date if someone starts moving things around in the future. --- crawl-ref/source/traps.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/traps.cc b/crawl-ref/source/traps.cc index 88099eb60e77..203e161b14a1 100644 --- a/crawl-ref/source/traps.cc +++ b/crawl-ref/source/traps.cc @@ -1368,7 +1368,7 @@ void roll_trap_effects() } /*** - * Separate from the previous function so the trap triggers when crawl is in an + * Separate from roll_trap_effects so the trap triggers when crawl is in an * appropriate state */ void do_trap_effects() From 1152973720f3b281c72f7985a528c15f0fa40cc7 Mon Sep 17 00:00:00 2001 From: Umer Shaikh Date: Mon, 11 Mar 2019 21:00:03 -0500 Subject: [PATCH 217/864] Check trap effects' validity before choosing effect The current flow is to decide whether the player is trapped when revealing a tile (player_view_update_at calls roll_trap_effects); if so, you.trapped is set to true. The next time the world reacts, do_trap_effects is called and then you.trapped is cleared back to false. Currently do_trap_effects rolls for which trap effect will happen and then checks to see if it is allowed to happen in that place; if not, nothing happens. This has the result that, all else equal, the player is less likely to suffer any trap effect on floors where one of the effect types is ruled out, e.g., the player is less likely to get trapped on Snake:3 than Snake:2. This commit changes do_trap_effects to first find the valid trap effects for the location and then choose among them. So, all else equal, the player will be just as likely to get trapped on a floor where shafts cannot be placed---the other trap effect types will pick up the slack. (In general all else is not equal, since trap effect rate depends on depth; see trap_rate_for_place. But probably this means that code affecting rate of triggering trap effect should be there, and not rolled in with code choosing the effect in do_trap_effects.) [Committer's note: simplified using a random_iterator, Closes #1009] --- crawl-ref/source/traps.cc | 59 +++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/crawl-ref/source/traps.cc b/crawl-ref/source/traps.cc index 203e161b14a1..4de6be8db99d 100644 --- a/crawl-ref/source/traps.cc +++ b/crawl-ref/source/traps.cc @@ -1374,35 +1374,46 @@ void roll_trap_effects() void do_trap_effects() { // Try to shaft, teleport, or alarm the player. - int roll = random2(3); - switch (roll) + + // We figure out which possibilites are allowed before picking which happens + // so that the overall chance of being trapped doesn't depend on which + // possibilities are allowed. + + // Teleport effects are allowed everywhere, no need to check + vector available_traps = { TRAP_TELEPORT }; + // Don't shaft the player when shafts aren't allowed in the location or when + // it would be into a dangerous end. + if (is_valid_shaft_effect_level()) + available_traps.push_back(TRAP_SHAFT); + // No alarms on the first 3 floors + if (env.absdepth0 > 3) + available_traps.push_back(TRAP_ALARM); + + switch (*random_iterator(available_traps)) { - case 0: - // Don't shaft the player when we can't, and also when it would be into a - // dangerous end. - if (is_valid_shaft_effect_level()) - { - dprf("Attempting to shaft player."); - you.do_shaft(); - } + case TRAP_SHAFT: + dprf("Attempting to shaft player."); + you.do_shaft(); break; - case 1: - // No alarms on the first 3 floors - if (env.absdepth0 > 3) - { - // Alarm effect alarms are always noisy, even if the player is - // silenced, to avoid "travel only while silenced" behavior. - // XXX: improve messaging to make it clear theres a wail outside of the - // player's silence - mprf("You set off the alarm!"); - fake_noisy(40, you.pos()); - you.sentinel_mark(true); - } + + case TRAP_ALARM: + // Alarm effect alarms are always noisy, even if the player is + // silenced, to avoid "travel only while silenced" behavior. + // XXX: improve messaging to make it clear theres a wail outside of the + // player's silence + mprf("You set off the alarm!"); + fake_noisy(40, you.pos()); + you.sentinel_mark(true); break; - case 2: - // Teleportitis + + case TRAP_TELEPORT: you_teleport_now(false, true, "You stumble into a teleport trap!"); break; + + // Other cases shouldn't be possible, but having a default here quiets + // compiler warnings + default: + break; } } From a595e75330f5ac5d13da7a2a0293c268cc7491de Mon Sep 17 00:00:00 2001 From: advil Date: Fri, 29 Mar 2019 20:07:14 -0400 Subject: [PATCH 218/864] Place transporters consistently in abyss Before, they were placing correctly when first entering an abyss level, because that code used the builder; they were also shifting correctly. But when a transporter vault placed as part of tele/movement-based generation, transporters were not being placed on the markers correctly because this code path *doesn't* use the builder. So, call the transporter conversion function directly after placing new vaults. --- crawl-ref/source/abyss.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/source/abyss.cc b/crawl-ref/source/abyss.cc index f72a506c3379..c5641145d5e9 100644 --- a/crawl-ref/source/abyss.cc +++ b/crawl-ref/source/abyss.cc @@ -234,6 +234,7 @@ static void _abyss_postvault_fixup() { fixup_misplaced_items(); link_items(); + dgn_make_transporters_from_markers(); env.markers.activate_all(); } From 9656df7c86a9ee6ebac250dc318522470836fc26 Mon Sep 17 00:00:00 2001 From: Nikolai Lavsky <3328424+nlavsky@users.noreply.github.com> Date: Fri, 29 Mar 2019 14:50:41 +0300 Subject: [PATCH 219/864] Don't try to generate any removed branches in mapstat As a followup to 17bec22d, this commit prevents mapstat from generating the other removed branches: the Dwarven Hall and Hall of Blades. It affects only the latter though, because the Dwarven Hall doesn't have any maps and cannot be generated anyway. --- crawl-ref/source/dbg-maps.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/dbg-maps.cc b/crawl-ref/source/dbg-maps.cc index f28d3c8a9533..2ab2b0d2651a 100644 --- a/crawl-ref/source/dbg-maps.cc +++ b/crawl-ref/source/dbg-maps.cc @@ -190,7 +190,7 @@ static void _dungeon_places() continue; #if TAG_MAJOR_VERSION == 34 // Don't want to include branches that no longer generate. - if (it->id == BRANCH_FOREST || it->id == BRANCH_LABYRINTH) + if (branch_is_unfinished(it->id)) continue; #endif From 0142750c7a98e56101ca5f8cda0daba373f317b3 Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 30 Mar 2019 09:48:12 -0400 Subject: [PATCH 220/864] Linebreak level annotations in chardumps (11904) This isn't really a complete solution: in general, the chardump doesn't fully respect 80 chars, this was just the most egregious example. ?# on tiles is fine with everything else I tested, in that it typically doesn't expand past the end of the screen, but ?# on console truncates on the right rather than centering, so still has a bunch of issues. I think a complete solution needs: (i) on tiles, prevent formatted_scroller from being wider than the displayable area, (ii) implement left-right scrolling in formatted_scroller, and (iii) take another pass to see what can be truncated at 80 characters. (For some things, like the action table, this probably isn't possible, but long equipment names for example could be better managed.) I did consider truncating the entire main chardump at 80 characters but this tends to look kind of bad in a lot of cases. This commit also tweaks some wizmode formatting for vault lits so it's readable in console in ?#. --- crawl-ref/source/chardump.cc | 1 + crawl-ref/source/dungeon.cc | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/chardump.cc b/crawl-ref/source/chardump.cc index 2dc9786b4667..c2d0b9711653 100644 --- a/crawl-ref/source/chardump.cc +++ b/crawl-ref/source/chardump.cc @@ -1092,6 +1092,7 @@ static void _sdump_overview(dump_params &par) string overview = formatted_string::parse_string(overview_description_string(false)); trim_string(overview); + linebreak_string(overview, 80); par.text += overview; par.text += "\n\n"; } diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 31b46b37b363..03aab39d67f3 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -6939,10 +6939,10 @@ string dump_vault_maps() // printing a morgue, this check isn't reliable. Ignore it. if (!is_existing_level(lid) && you.save) { - out += " (not gen.) " + lid.describe() + "\n"; + out += "[-gen,-vis] " + lid.describe() + "\n"; continue; } - out += you.level_visited(lid) ? " (visited) " : "(unvisited) "; + out += you.level_visited(lid) ? "[+gen,+vis] " : "[+gen,-vis] "; } out += lid.describe(); vector &maps(you.vault_list[lid]); @@ -6957,11 +6957,11 @@ string dump_vault_maps() // TODO: some way of showing no_dump maps in wizmode? string vaults = comma_separated_line(maps.begin(), maps.end(), ", "); - out += wordwrap_line(vaults, 70) + "\n"; + out += wordwrap_line(vaults, you.wizard ? 58 : 70) + "\n"; while (!vaults.empty()) { out += string(you.wizard ? 22 : 10, ' ') - + wordwrap_line(vaults, 70, false) + "\n"; + + wordwrap_line(vaults, you.wizard ? 58 : 70, false) + "\n"; } } From 0b285d475d8059dc9e49e8e210d068f836f83743 Mon Sep 17 00:00:00 2001 From: Koen De Groote Date: Sat, 30 Mar 2019 17:04:26 +0100 Subject: [PATCH 221/864] Update religion.cc Typo --- crawl-ref/source/religion.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index b10e61264565..bc5fe2807b58 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -328,7 +328,7 @@ const vector god_powers[NUM_GODS] = { 0, "Qazlal grants you and your divine allies immunity to clouds." }, { 1, "You are now surrounded by a storm.", "Your storm dissipates completely.", - "Your are surrounded by a storm." }, + "You are surrounded by a storm." }, { 2, ABIL_QAZLAL_UPHEAVAL, "call upon nature to destroy your foes" }, { 3, ABIL_QAZLAL_ELEMENTAL_FORCE, "give life to nearby clouds" }, { 4, "The storm surrounding you is now powerful enough to repel missiles.", From 1ac5efaa63ecbfec781f565388a398b8cdcbbbab Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Thu, 28 Mar 2019 22:54:44 -0400 Subject: [PATCH 222/864] Update CREDITS.txt --- crawl-ref/CREDITS.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crawl-ref/CREDITS.txt b/crawl-ref/CREDITS.txt index 4d18a26d31cd..604191c1fdc9 100644 --- a/crawl-ref/CREDITS.txt +++ b/crawl-ref/CREDITS.txt @@ -88,6 +88,7 @@ Roy Axenov Steve 'nfogravity' Balady Max Bane + G. Bailey Beargit Bill Beher Alexander Beisig @@ -148,6 +149,7 @@ Chris Galardi GenericPseudonym Ge0ff + Joshua Gelbard Benoît Giannangeli Ben Goetter Aaron Golden @@ -239,6 +241,7 @@ Chris Oelmueller John Olender Aaron Olowin + Andrew O'Neill Yuuma Oohara Julian Ospald Malwyn P From ca936617586b19b2135f31ac0f34d63ca918cad4 Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 30 Mar 2019 19:09:55 -0400 Subject: [PATCH 223/864] Update sdl2 contrib with mac resize fix (11895) See the SDL2 commit message for details: https://github.com/crawl/crawl-sdl2/commit/07f787c0da7df6e37bd71a71b6e833fd9b88adea --- crawl-ref/source/contrib/sdl2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/contrib/sdl2 b/crawl-ref/source/contrib/sdl2 index 5c4ec98178a1..07f787c0da7d 160000 --- a/crawl-ref/source/contrib/sdl2 +++ b/crawl-ref/source/contrib/sdl2 @@ -1 +1 @@ -Subproject commit 5c4ec98178a1d04d3c7986b83e29a6a9acd77c68 +Subproject commit 07f787c0da7df6e37bd71a71b6e833fd9b88adea From df4562371cabe234613654904370d4b95e79aec6 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 28 Mar 2019 02:54:01 +0000 Subject: [PATCH 224/864] Update debian changelog for 0.22.2 (cherry picked from commit e965b3aba33ea031970dc6c595116b0a96a5b81e) --- crawl-ref/source/debian/changelog | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crawl-ref/source/debian/changelog b/crawl-ref/source/debian/changelog index 456631e2bbfd..b05ef5ecd38c 100644 --- a/crawl-ref/source/debian/changelog +++ b/crawl-ref/source/debian/changelog @@ -1,3 +1,8 @@ +crawl (2:0.22.2-1) UNRELEASED; urgency=low + + * New upstream release. + -- advil Wed, 27 Mar 2019 21:22:21 -0400 + crawl (2:0.23.1-1) UNRELEASED; urgency=low * New upstream release. From 710923106e45b02902814bba8a353f6f4f622ebe Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 30 Mar 2019 20:34:12 -0400 Subject: [PATCH 225/864] Sync changelog with 0.22 branch --- crawl-ref/docs/changelog.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/crawl-ref/docs/changelog.txt b/crawl-ref/docs/changelog.txt index 26465c94e15f..4fa8f0cf68b2 100644 --- a/crawl-ref/docs/changelog.txt +++ b/crawl-ref/docs/changelog.txt @@ -186,6 +186,17 @@ Spells ------ * Confusing touch works with a weapon wielded +Stone Soup 0.22.2 (20190327) +---------------------------- + +Bugfix Release +-------------- +* Fix a crash on startup when there are seeded games (from 0.23) in a shared + save directory. +* Let Barachim telefrag at their full range. +* Don't let ball lightnings climb stairs. +* 52 other bugfixes and cleanups in total. + Stone Soup 0.22.1 (20180916) ---------------------------- From ca05e9d32bbe5e1fcf8990079a46a79edbcd1d64 Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 30 Mar 2019 20:42:24 -0400 Subject: [PATCH 226/864] Update changelogs from 0.23 branch --- crawl-ref/docs/changelog.txt | 21 +++++++++++++++++++++ crawl-ref/source/debian/changelog | 5 +++++ 2 files changed, 26 insertions(+) diff --git a/crawl-ref/docs/changelog.txt b/crawl-ref/docs/changelog.txt index 4fa8f0cf68b2..ee0ffdef5e80 100644 --- a/crawl-ref/docs/changelog.txt +++ b/crawl-ref/docs/changelog.txt @@ -1,3 +1,24 @@ +Stone Soup 0.23.2 (20190330) +---------------------------- + +Bugfix Release +-------------- +* Various seed-related bugfixes and improvements: + - Seed input now supports pasting, and is autofilled from the last game. + - The seed input box now has an extra digit. + - The game seed is saved correctly and will no longer show as 0 for games + started after this fix. + - Seed stability for floating point calculations: for most configuration the + main dungeon should remain unchanged, but 32 bit systems (and 32-bit builds) + should now be much more stable, among others. Slime will likely differ. + - Seed stability for rc options: certain rc options affected the generation + of some layouts, leading to divergent seeds. +* AK starts will no longer crash when exiting the abyss in pregen games. +* Gozag bribe branch in pregen games now works correctly when entering a + previously unvisited level. +* Meatsprint is now difficult again. +* 37 other bugfixes and improvements in total. + Stone Soup 0.23.1 (20190228) ---------------------------- diff --git a/crawl-ref/source/debian/changelog b/crawl-ref/source/debian/changelog index b05ef5ecd38c..5bccdd76022b 100644 --- a/crawl-ref/source/debian/changelog +++ b/crawl-ref/source/debian/changelog @@ -1,3 +1,8 @@ +crawl (2:0.23.2-1) UNRELEASED; urgency=low + + * New upstream release. + -- advil Sat, 30 Mar 2019 20:39:33 -0400 + crawl (2:0.22.2-1) UNRELEASED; urgency=low * New upstream release. From 1a43be200669514182634035c87d5750787eaa9c Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Sat, 30 Mar 2019 22:26:05 +0000 Subject: [PATCH 227/864] Fix spurious message on moving into door with wall_jump_move (11940) When attempting to move into a closed door with the wall_jump_move option set to true, the function wu_jian_can_wall_jump was being called, which meant spurious messages describing why wall jumping was impossible in the current situation were being printed to the message log. To fix this, move the check for moving into a closed door (a situation where it is not possible to wall jump by moving) to inside the definition of bool can_wall_jump, before the function wu_jian_can_wall_jump() is called. Also remove an unnecessary variable (targ_grid) and replace it with grd(targ) everywhere. --- crawl-ref/source/movement.cc | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/crawl-ref/source/movement.cc b/crawl-ref/source/movement.cc index 03bae169b490..dc59fa88c93a 100644 --- a/crawl-ref/source/movement.cc +++ b/crawl-ref/source/movement.cc @@ -537,8 +537,13 @@ void move_player_action(coord_def move) const coord_def targ = you.pos() + move; string wall_jump_err; - bool can_wall_jump = Options.wall_jump_move && - wu_jian_can_wall_jump(targ, wall_jump_err); + // Don't allow wall jump against close doors via movement -- need to use + // the ability. Also, if moving into a closed door, don't call + // wu_jian_can_wall_jump, to avoid printing a spurious message (see 11940). + bool can_wall_jump = Options.wall_jump_move + && (!in_bounds(targ) + || !feat_is_closed_door(grd(targ))) + && wu_jian_can_wall_jump(targ, wall_jump_err); bool did_wall_jump = false; // You can't walk out of bounds! if (!in_bounds(targ) && !can_wall_jump) @@ -549,13 +554,6 @@ void move_player_action(coord_def move) return; } - const dungeon_feature_type targ_grid = grd(targ); - - // don't allow wall jump against close doors via movement -- need to use - // the ability - if (can_wall_jump && feat_is_closed_door(targ_grid)) - can_wall_jump = false; - const string walkverb = you.airborne() ? "fly" : you.swimming() ? "swim" : you.form == transformation::spider ? "crawl" @@ -817,7 +815,7 @@ void move_player_action(coord_def move) // BCR - Easy doors single move if ((Options.travel_open_doors || !you.running) && !attacking - && feat_is_closed_door(targ_grid)) + && feat_is_closed_door(grd(targ))) { open_door_action(move); move.reset(); From 05560da47184ebf643c624a4a9d2546b33d4f8e2 Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 31 Mar 2019 17:02:34 -0400 Subject: [PATCH 228/864] Update credits Noticed in a wordpress comment: http://crawl.develz.org/wordpress/crawl-0-23-nemelex-needs-traps-badly/comment-page-1#comment-3015 The comment didn't express a preference as to use, so I went with real name. --- crawl-ref/CREDITS.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/crawl-ref/CREDITS.txt b/crawl-ref/CREDITS.txt index 604191c1fdc9..a69f224b80a2 100644 --- a/crawl-ref/CREDITS.txt +++ b/crawl-ref/CREDITS.txt @@ -284,7 +284,6 @@ Robert Shimmin Sigurd Edgar Simo - Skrybe Alex Smith Keanan Smith Richard Soderberg From 3ce5c5b359fde7867bc1ab5a77b7efe6254de889 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 1 Apr 2019 10:10:39 -0400 Subject: [PATCH 229/864] Fix rng independence issues with setup_xom_dancing_weapon Because these variables were not set up as `locals` (so were part of the global state), and not every case in the if sequence initialized every call, subsequent calls to this could be affected by earlier calls in a non-intended way. As long as the calls were done in the same order this won't affect seed stability per se, but it shows up as a stability error in the test, and it's better not to do this with global state. This code *is* still dependent on global state in that it's affected by whether the mace of variability has spawned, but otherwise it should act independently on repeated calls. I've also pulled out the roll for variability so that it happens regardless of whether the mace has previously generated; this way the number of rng draws is independent of this global state. Ironically, the biggest problem here on the seed where this came up (185349672) was the mace of variability variable being global. --- crawl-ref/source/dat/dlua/ghost.lua | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/crawl-ref/source/dat/dlua/ghost.lua b/crawl-ref/source/dat/dlua/ghost.lua index a60ba555771f..f9121fcf7a06 100644 --- a/crawl-ref/source/dat/dlua/ghost.lua +++ b/crawl-ref/source/dat/dlua/ghost.lua @@ -265,9 +265,12 @@ end -- Set up the chaos dancing weapon for ebering_ghost_xom and -- ebering_vaults_ghost_xom. function setup_xom_dancing_weapon(e) - quality = "" - great_weight = 1 - great_weapons = {} + local quality = "" + local great_weight = 1 + local base_weapons = {} + local good_weapons = {} + local great_weapons = {} + local variability = nil -- Progress the base type of weapons so that it's more reasonable as reward -- as depth increases. The very rare weapons only show up at all in later @@ -309,12 +312,15 @@ function setup_xom_dancing_weapon(e) quality = crawl.coinflip() and "good_item" or crawl.coinflip() and "randart" or "" + -- do this check independently of global state so that the effect + -- on the rng is the same either way + local can_try_variability = crawl.one_chance_in(100) variability = not you.unrands("mace of Variability") - and crawl.one_chance_in(100) and "mace of Variability" + and can_try_variability and "mace of Variability" end -- Make one weapons table with each weapon getting weight by class. - weapons = {} + local weapons = {} for _, wname in ipairs(base_weapons) do weapons[wname] = 10 end From 536ed4e33c58614c11db38367961f938469eee4c Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 1 Apr 2019 15:43:25 -0400 Subject: [PATCH 230/864] Don't remain in % menu after dropping, etc. This menu lets you view items, and from there you drop them, take them off, etc. Before this commit, the player could trigger these arbitrary numbers of times from the % menu, lining up multiple armor-off delays for when they exit the menu, which would then crash. This change simply respects the return value for describe_item. --- crawl-ref/source/output.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/output.cc b/crawl-ref/source/output.cc index e3e421534857..6519411b4336 100644 --- a/crawl-ref/source/output.cc +++ b/crawl-ref/source/output.cc @@ -2504,7 +2504,8 @@ class overview_popup : public formatted_scroller if (find(equip_chars.begin(), equip_chars.end(), ch) != equip_chars.end()) { item_def& item = you.inv[letter_to_index(ch)]; - describe_item(item); + if (!describe_item(item)) + return false; return true; } return formatted_scroller::process_key(ch); From 9da92b9584df696325aa7ee343eeb22d3d78a9a8 Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 2 Apr 2019 19:33:11 -0400 Subject: [PATCH 231/864] Add a warning to the seed dialog for x87 x87 calculations in gcc, at least with -O2, lead to known differences from sse-based floating point calculations, and this will continue to be true until we get rid of floating point altogether. (This has mostly been rearing its head in dealing with the windows builds, for which I'm going to take a different approach, but can also come up for 32bit linux builds.) So, indicate that we don't fully support seeding on builds that use x87 math. (Where x87 math is assumed to happen on an x86 build that does not use SSE of some kind.) This *might* be solvable by messing with more fine-grained options on gcc, but if so I haven't figured it out. (This commit isn't meant to imply that x87 is the *only* thing like this that could lead to floating point instability, but it is the one that I've tested the most carefully.) --- crawl-ref/source/defines.h | 8 ++++++++ crawl-ref/source/newgame.cc | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/crawl-ref/source/defines.h b/crawl-ref/source/defines.h index 8bffc629930c..72bf32cacc61 100644 --- a/crawl-ref/source/defines.h +++ b/crawl-ref/source/defines.h @@ -7,6 +7,14 @@ #pragma once +// In this case, an x86 CPU will use x87 math for floating point calculations, +// which uses 80 bit intermediate results, andleads to difference from the +// (much more common, in 2019) SSE-based calculations. +// probably far from the only case where seeding isn't reliable... +#if defined(TARGET_CPU_X86) && !defined(__SSE__) +#define SEEDING_UNRELIABLE +#endif + // Minimum terminal size allowed. #define MIN_COLS 79 #define MIN_LINES 24 diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 241adba7958f..e10767cd2a33 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -752,6 +752,11 @@ static void _choose_seed(newgame_def& ng, newgame_def& choice, "Pregeneration will ensure that these remain the same no matter\n" "what order you explore the dungeon in. (See the manual for more\n" "details.)\n\n"); +#ifdef SEEDING_UNRELIABLE + prompt.cprintf( + "Warning: your build of crawl does not support stable seeding!\n" + "Levels may differ from 'official' seeded games.\n\n"); +#endif prompt.cprintf("Seed ([-] to clear):"); string seed_text = make_stringf("%-20s", buf); prompt.cprintf("\n%s\n\n", seed_text.c_str()); From 49d9ff80d89ea4728cd4b074dad02ec08f713a1e Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 2 Apr 2019 20:00:26 -0400 Subject: [PATCH 232/864] Force SSE2 (again) for win32 builds This is a much more restrained version of 3d66cf40a65a. As discussed in with windows being the exception: we (apparently) need to keep building windows as i386, which does not imply sse, but as of 2018 all windows versions >=7 require CPUs with SSE2 support. Since the revert in 6492a9889c, floating point issues on windows builds have continued to crop up, where x87 calculations return different values (because of intermediate 80 bit precision) than regular SSE-based calculations in some cases. It also turns out that x87 issues are exacerbated by building with -O2, which debug builds don't use (so I'd missed a bunch of cases until discovering this). It's possible that there are more specific / other compiler flags that could help mitigate these issues, but none of them seem very reliable or guaranteed. -ffloat-store reportedly works sometimes. If we were using C, then -fexcess-precision=standard might be an option, but as far as I can tell this still doesn't work for c++. Better to just avoid x87 entirely. (The real solution is to remove all floating point calculations...) For backstory, see: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=323 https://stackoverflow.com/questions/7517588/different-floating-point-result-with-optimization-enabled-compiler-bug https://yosefk.com/blog/consistency-how-to-defeat-the-purpose-of-ieee-floating-point.html --- crawl-ref/source/Makefile | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/Makefile b/crawl-ref/source/Makefile index 7f0b86353940..96cca37a678b 100644 --- a/crawl-ref/source/Makefile +++ b/crawl-ref/source/Makefile @@ -109,6 +109,13 @@ include Makefile.obj STDFLAG = -std=c++11 CFOTHERS := -pipe $(EXTERNAL_FLAGS) +# Build with FORCE_SSE=y to get better seed stability on 32 bit x86 builds. It +# is not recommended to do this unless you are building with contrib lua. +# On any 64bit builds where the arch supports it, (at least) sse2 is implied. +ifdef FORCE_SSE +CFOTHERS += -mfpmath=sse -msse2 +endif + CFWARN := CFWARN_L := -Wall -Wformat-security -Wundef @@ -1749,9 +1756,9 @@ ifneq ($(GAME),crawl.exe) @echo "This is only for Windows; please specify CROSSHOST.";false endif +$(MAKE) clean - +$(MAKE) TILES=y DESTDIR=build-win SAVEDIR='~/crawl' install + +$(MAKE) TILES=y DESTDIR=build-win FORCE_SSE=y SAVEDIR='~/crawl' install mv build-win/crawl.exe build-win/crawl-tiles.exe - +$(MAKE) TILES= DESTDIR=build-win SAVEDIR='~/crawl' install + +$(MAKE) TILES= DESTDIR=build-win FORCE_SSE=y SAVEDIR='~/crawl' install mv build-win/crawl.exe build-win/crawl-console.exe mv build-win/docs/CREDITS.txt build-win/ echo $(SRC_VERSION) >build-win/version.txt @@ -1762,11 +1769,11 @@ ifneq ($(GAME),crawl.exe) @echo "This is only for Windows; please specify CROSSHOST.";false endif +$(MAKE) clean - +$(MAKE) TILES=y DESTDIR=build-win/stone_soup-tiles-$(MAJOR_VERSION) install + +$(MAKE) TILES=y DESTDIR=build-win/stone_soup-tiles-$(MAJOR_VERSION) FORCE_SSE=y install cp -p $(ZIP_DOCS) build-win/stone_soup-tiles-$(MAJOR_VERSION)/ cd build-win && zip -9r ../stone_soup-$(SRC_VERSION)-tiles-win32.zip * rm -rf build-win - +$(MAKE) DESTDIR=build-win/stone_soup-$(MAJOR_VERSION) install + +$(MAKE) DESTDIR=build-win/stone_soup-$(MAJOR_VERSION) FORCE_SSE=y install cp -p $(ZIP_DOCS) build-win/stone_soup-$(MAJOR_VERSION)/ cd build-win && zip -9r ../stone_soup-$(SRC_VERSION)-win32.zip * rm -rf build-win From aef371a0c27124a943dea211a16064ef796948ea Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 4 Apr 2019 09:29:12 -0400 Subject: [PATCH 233/864] Fix a Makefile typo I noticed this reported in the following debian bug, it may be fixed downstream already: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=871419 --- crawl-ref/source/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/Makefile b/crawl-ref/source/Makefile index 96cca37a678b..555762b7e32c 100644 --- a/crawl-ref/source/Makefile +++ b/crawl-ref/source/Makefile @@ -174,7 +174,7 @@ ARCH := $(HOST) ifdef CROSSHOST ARCH := $(CROSSHOST) - ifneq (,$($shell which $(ARCH)-pkg-config 2>/dev/null)) + ifneq (,$(shell which $(ARCH)-pkg-config 2>/dev/null)) PKGCONFIG = $(ARCH)-pkg-config else ifneq (,$(wildcard /usr/$(ARCH)/lib/pkgconfig)) From 4d521536635c3bc9966b01861081920d708f6825 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 4 Apr 2019 09:57:04 -0400 Subject: [PATCH 234/864] Remove __DATE__ and __TIME__ from compilation info See https://reproducible-builds.org/docs/timestamps/ While looking at various downstream packaging setups, I noticed that they all have to patch this out anyways for reasons in the above link. If anyone has ever actually used this information for debugging (over and above the version info) I'm happy to rethink, but including this seems unnecessary to me. --- crawl-ref/source/version.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/version.cc b/crawl-ref/source/version.cc index b2056f26fccd..951ab56f30ce 100644 --- a/crawl-ref/source/version.cc +++ b/crawl-ref/source/version.cc @@ -39,7 +39,7 @@ namespace Version #endif const char* compilation_info = - "Compiled with " COMPILER " on " __DATE__ " at " __TIME__ "\n" + "Compiled with " COMPILER "\n" "Build platform: " CRAWL_HOST "\n" "Platform: " CRAWL_ARCH "\n" "CFLAGS: " CRAWL_CFLAGS "\n" From 3f03afcf10b295a662d58d426b776e16d1ab38b1 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 4 Apr 2019 13:34:27 -0400 Subject: [PATCH 235/864] Don't let unarmed skill when unarmed determine delay of fumble-throwing Probably fixes 11942. --- crawl-ref/source/player-act.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/player-act.cc b/crawl-ref/source/player-act.cc index 507503167cfe..ca1da670a6c2 100644 --- a/crawl-ref/source/player-act.cc +++ b/crawl-ref/source/player-act.cc @@ -256,7 +256,7 @@ random_var player::attack_delay(const item_def *projectile, bool rescale) const attk_delay = rv::max(attk_delay, random_var(FASTEST_PLAYER_THROWING_SPEED)); } - else if (!weap) + else if (!projectile && !weap) { int sk = form_uses_xl() ? experience_level * 10 : skill(SK_UNARMED_COMBAT, 10); From 38e41d773888fb2a235db09de21b34b841fabcba Mon Sep 17 00:00:00 2001 From: Alan Malloy Date: Mon, 8 Apr 2019 15:19:40 -0700 Subject: [PATCH 236/864] Don't message about tormented monsters outside LOS (Yermak) --- crawl-ref/source/spl-goditem.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/spl-goditem.cc b/crawl-ref/source/spl-goditem.cc index 308cbbdc1069..0b9ea19c6a91 100644 --- a/crawl-ref/source/spl-goditem.cc +++ b/crawl-ref/source/spl-goditem.cc @@ -1256,7 +1256,7 @@ void torment_cell(coord_def where, actor *attacker, torment_source_type taux) { if (mons->observable()) simple_monster_message(*mons, " convulses!"); - else + else if (you.see_cell(mons->pos())) mpr("Something is bathed in an unholy light!"); // Currently, torment doesn't annoy the monsters it affects From 81a6c4fb23e9c8da5c700b797b3dc4f8050bbd80 Mon Sep 17 00:00:00 2001 From: Alan Malloy Date: Mon, 8 Apr 2019 15:20:33 -0700 Subject: [PATCH 237/864] Remove an old die() that's been replaced by an ASSERT --- crawl-ref/source/losglobal.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/crawl-ref/source/losglobal.cc b/crawl-ref/source/losglobal.cc index 55273e47048a..5dd10675aa5f 100644 --- a/crawl-ref/source/losglobal.cc +++ b/crawl-ref/source/losglobal.cc @@ -126,9 +126,6 @@ bool cell_see_cell(const coord_def& p, const coord_def& q, los_type l) if (!(*flags & (l << LOS_KNOWN))) _update_globallos_at(p, l); - //if (!(*flags & (l << LOS_KNOWN))) - // die("cell_see_cell %d,%d %d,%d", p.x,p.y,q.x,q.y); ASSERT(*flags & (l << LOS_KNOWN)); - return *flags & l; } From ece4408007701a2614cf13ff3611b8bd120c697f Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Fri, 5 Apr 2019 19:26:45 +0100 Subject: [PATCH 238/864] Turn off skill targets when aptitudes change from level up (11943) Add a call to check_training_targets() into the function check_skill_level_change(). Also, update an inaccurate comment about this function. --- crawl-ref/source/player.cc | 2 +- crawl-ref/source/skills.cc | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 76388287309a..3f029d726e45 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -2912,7 +2912,7 @@ void level_change(bool skip_attribute_increase) // do_level_up = false) but save the old values; then when // we want the messages later, we restore the old skill // levels and call check_skill_level_change() again, this - // time passing do_update = true. + // time passing do_level_up = true. uint8_t saved_skills[NUM_SKILLS]; for (skill_type sk = SK_FIRST_SKILL; sk < NUM_SKILLS; ++sk) diff --git a/crawl-ref/source/skills.cc b/crawl-ref/source/skills.cc index d04e461312fc..2fa7408064b2 100644 --- a/crawl-ref/source/skills.cc +++ b/crawl-ref/source/skills.cc @@ -399,6 +399,8 @@ void check_skill_level_change(skill_type sk, bool do_level_up) else you.skills[sk] = new_level; } + + check_training_targets(); } // Fill a queue in random order with the values of the array. From aa57d617ac6bc1d982e844f9e6670bdb27df6813 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Higor=20Eur=C3=ADpedes?= Date: Tue, 2 Apr 2019 20:39:39 -0300 Subject: [PATCH 239/864] Warn the player that teleportation doesn't work in gauntlet Gauntlet prevents long distance translocations from happening (NoTele), but the user won't know about this until they check the % screen, read a scroll of teleportation or notice that teleportitis hasn't triggered since they entered the branch. --- crawl-ref/source/stairs.cc | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/crawl-ref/source/stairs.cc b/crawl-ref/source/stairs.cc index 30c3b9528224..2bdc1f05040f 100644 --- a/crawl-ref/source/stairs.cc +++ b/crawl-ref/source/stairs.cc @@ -7,6 +7,7 @@ #include "abyss.h" #include "act-iter.h" #include "areas.h" +#include "artefact.h" #include "bloodspatter.h" #include "branch.h" #include "chardump.h" @@ -399,6 +400,22 @@ static void _rune_effect(dungeon_feature_type ftype) } } +static void _gauntlet_effect() +{ + // already doomed + if (you.species == SP_FORMICID) + return; + + mprf(MSGCH_WARN, "The nature of this place prevents teleportation."); + + if (you.has_mutation(MUT_TELEPORT, true) + || you.wearing(EQ_RINGS, RING_TELEPORTATION, true) + || you.scan_artefacts(ARTP_CAUSE_TELEPORTATION, true)) + { + mpr("Your feel stable."); + } +} + static void _new_level_amuses_xom(dungeon_feature_type feat, dungeon_feature_type old_feat, bool shaft, int shaft_depth, bool voluntary) @@ -769,6 +786,9 @@ void floor_transition(dungeon_feature_type how, mpr(branches[branch].entry_message); else if (branch != BRANCH_ABYSS) // too many messages... mprf("Welcome to %s!", branches[branch].longname); + + if (how == DNGN_ENTER_GAUNTLET) + _gauntlet_effect(); } const set boring_branch_exits = { From 6e284d23e071832f746fcdfb06706e546484d911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Higor=20Eur=C3=ADpedes?= Date: Wed, 3 Apr 2019 19:23:29 -0300 Subject: [PATCH 240/864] Show NoTele warning every time the player enters gauntlet Now the message will be displayed when the player returns from the abyss. --- crawl-ref/source/stairs.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/stairs.cc b/crawl-ref/source/stairs.cc index 2bdc1f05040f..83dc6f162c68 100644 --- a/crawl-ref/source/stairs.cc +++ b/crawl-ref/source/stairs.cc @@ -786,11 +786,11 @@ void floor_transition(dungeon_feature_type how, mpr(branches[branch].entry_message); else if (branch != BRANCH_ABYSS) // too many messages... mprf("Welcome to %s!", branches[branch].longname); - - if (how == DNGN_ENTER_GAUNTLET) - _gauntlet_effect(); } + if (branch == BRANCH_GAUNTLET) + _gauntlet_effect(); + const set boring_branch_exits = { BRANCH_TEMPLE, BRANCH_BAZAAR, From 870ddcc6b6b95da0a7e0c0e47f8db05f1983cd11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Higor=20Eur=C3=ADpedes?= Date: Wed, 3 Apr 2019 19:28:03 -0300 Subject: [PATCH 241/864] Let the player know that the gauntlet effect isn't permanent Let the player know that the gauntlet effect isn't permanent --- crawl-ref/source/stairs.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/stairs.cc b/crawl-ref/source/stairs.cc index 83dc6f162c68..d2bf5be51f54 100644 --- a/crawl-ref/source/stairs.cc +++ b/crawl-ref/source/stairs.cc @@ -412,7 +412,7 @@ static void _gauntlet_effect() || you.wearing(EQ_RINGS, RING_TELEPORTATION, true) || you.scan_artefacts(ARTP_CAUSE_TELEPORTATION, true)) { - mpr("Your feel stable."); + mpr("Your feel stable on this floor."); } } From 98856730051ab32876efa96c0a77740302b9af9e Mon Sep 17 00:00:00 2001 From: gammafunk Date: Sat, 6 Apr 2019 02:21:17 -0500 Subject: [PATCH 242/864] Fix a comment typo --- crawl-ref/source/dat/des/variable/ghost.des | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/dat/des/variable/ghost.des b/crawl-ref/source/dat/des/variable/ghost.des index 394a04bc259b..da953a9e1fad 100644 --- a/crawl-ref/source/dat/des/variable/ghost.des +++ b/crawl-ref/source/dat/des/variable/ghost.des @@ -2090,7 +2090,7 @@ kmons("q = deep elf master archer; longbow randart " .. MONS: deep elf blademaster / deep elf master archer SUBST: fg = |*, h = *, i = $%, j= - # There aren't any good lower-tier, trog-appropriate warrior types. So use all -# blademasters and master archers, but reduce the reduce monster count. +# blademasters and master archers, but reduce the monster count. NSUBST: - = 1 / 2=1. / 2=L / q / 3=2. / . : elseif you.in_branch("Depths") then MONS: tengu warrior / deep troll / spriggan berserker / stone giant / ettin From 8f5f5cde13284b24721f272935d27d4c33238e24 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Mon, 8 Apr 2019 19:06:21 -0500 Subject: [PATCH 243/864] Don't use a more() for LOS spells (kitchen_ace) Currently LOS attack spells use a more() prompt every time they fire. This may be so that the flash animation they use can actually have time to display. The more() prompt is not removable by the player and is especially annoying for frequent LOS spells under e.g. the Singing Sword. This commit removes the more() and instead uses a delayed flash animation of 300ms, like we do for many other LOS-based spells. --- crawl-ref/source/spl-damage.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crawl-ref/source/spl-damage.cc b/crawl-ref/source/spl-damage.cc index 3e0d1a8a72ed..11607e5f3841 100644 --- a/crawl-ref/source/spl-damage.cc +++ b/crawl-ref/source/spl-damage.cc @@ -608,10 +608,7 @@ static spret _cast_los_attack_spell(spell_type spell, int pow, } mpr(player_msg); - flash_view(UA_PLAYER, beam.colour, &hitfunc); - more(); - clear_messages(); - flash_view(UA_PLAYER, 0); + flash_view_delay(UA_PLAYER, beam.colour, 300, &hitfunc); } else if (actual) { From a6a6ab7d13fb06b8471b772e09d49dea96a92b56 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Tue, 9 Apr 2019 16:15:05 -0500 Subject: [PATCH 244/864] Use the correct LOS for Sacrifice Courage (Reeces) Before this commit, monsters behind glass would cause the Horror debuff from Ru's Sacrifice Courage to apply. This is annoying due to the interruption and messaging it causes, and these monsters aren't actually dangerous. This commit has Sacrifice Courage consider monsters behind transparent walls as safe and uses an appropriate monster iterator instead of a distance-based one. --- crawl-ref/source/player-reacts.cc | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/crawl-ref/source/player-reacts.cc b/crawl-ref/source/player-reacts.cc index 306fb97cc019..a8a00e096e3d 100644 --- a/crawl-ref/source/player-reacts.cc +++ b/crawl-ref/source/player-reacts.cc @@ -289,26 +289,19 @@ static void _maybe_melt_armour() */ static int _current_horror_level() { - const coord_def& center = you.pos(); - const int radius = LOS_RADIUS; int horror_level = 0; - for (radius_iterator ri(center, radius, C_SQUARE); ri; ++ri) + for (monster_near_iterator mi(&you, LOS_NO_TRANS); mi; ++mi) { - const monster* const mon = monster_at(*ri); - if (mon == nullptr - || mons_aligned(mon, &you) - || !mons_is_threatening(*mon) - || !you.can_see(*mon) - || mons_is_tentacle_or_tentacle_segment(mon->type)) + if (mons_aligned(*mi, &you) + || !mons_is_threatening(**mi) + || mons_is_tentacle_or_tentacle_segment(mi->type)) { continue; } - ASSERT(mon); - - const mon_threat_level_type threat_level = mons_threat_level(*mon); + const mon_threat_level_type threat_level = mons_threat_level(**mi); if (threat_level == MTHRT_NASTY) horror_level += 3; else if (threat_level == MTHRT_TOUGH) From b50751227d1b4df484ca9ba996502a749c0ba979 Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Thu, 11 Apr 2019 20:17:44 +0100 Subject: [PATCH 245/864] Fix typo --- crawl-ref/source/stairs.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/stairs.cc b/crawl-ref/source/stairs.cc index d2bf5be51f54..10086120a24a 100644 --- a/crawl-ref/source/stairs.cc +++ b/crawl-ref/source/stairs.cc @@ -412,7 +412,7 @@ static void _gauntlet_effect() || you.wearing(EQ_RINGS, RING_TELEPORTATION, true) || you.scan_artefacts(ARTP_CAUSE_TELEPORTATION, true)) { - mpr("Your feel stable on this floor."); + mpr("You feel stable on this floor."); } } From b963c9a6341e8dc7d366c13c7e803002a450d5cb Mon Sep 17 00:00:00 2001 From: Nikolai Lavsky <3328424+nlavsky@users.noreply.github.com> Date: Thu, 11 Apr 2019 13:57:36 +0300 Subject: [PATCH 246/864] Always display the duration of the last action on the HUD (Yermak) Because of how the score is calculated, it might be more useful to have player turns instead of elapsed time on the HUD. `show_game_time = false` replaces time with player turns, but also hides the duration of the last action. The HUD is the only place that shows this duration, so players who care about their score have to use the default value for show_game_time and have to regularly check their turns via the E or % commands. After this commit, the HUD will display the duration regardless of the show_game_time's value. --- crawl-ref/docs/options_guide.txt | 5 +++-- crawl-ref/source/output.cc | 12 ++++++------ .../source/webserver/game_data/static/player.js | 5 +++-- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/crawl-ref/docs/options_guide.txt b/crawl-ref/docs/options_guide.txt index be8466bf78d1..b49a6e867d59 100644 --- a/crawl-ref/docs/options_guide.txt +++ b/crawl-ref/docs/options_guide.txt @@ -1454,12 +1454,13 @@ show_game_time = true By default, the counter in the stat area displays elapsed game time. Most actions take one unit of time, but some are quicker (putting on a ring, wielding a weapon, ...) and others are slower (swinging a weapon - with low skill, changing armour, ...). The duration of the last action - is displayed in parenthesis, after the time display. + with low skill, changing armour, ...). When set to false, the counter will display player turns instead, which is the number of actions taken regardless of their duration. It is this turn count which is used for scoring (and this turn count is always visible on the % overview screen). + The duration of the last action is displayed in parenthesis, after the + time/player turns display. equip_bar = false When set to true, this option replaces the noise bar with an diff --git a/crawl-ref/source/output.cc b/crawl-ref/source/output.cc index 6519411b4336..4cffc48a12ae 100644 --- a/crawl-ref/source/output.cc +++ b/crawl-ref/source/output.cc @@ -550,14 +550,14 @@ void update_turn_count() // Show the turn count starting from 1. You can still quit on turn 0. textcolour(HUD_VALUE_COLOUR); if (Options.show_game_time) - { - CPRINTF("%.1f (%.1f)%s", you.elapsed_time / 10.0, - (you.elapsed_time - you.elapsed_time_at_last_input) / 10.0, - // extra spaces to erase excess if previous output was longer - " "); - } + CPRINTF("%.1f", you.elapsed_time / 10.0); else CPRINTF("%d", you.num_turns); + + CPRINTF(" (%.1f)%s", + (you.elapsed_time - you.elapsed_time_at_last_input) / 10.0, + // extra spaces to erase excess if previous output was longer + " "); textcolour(LIGHTGREY); } diff --git a/crawl-ref/source/webserver/game_data/static/player.js b/crawl-ref/source/webserver/game_data/static/player.js index d61e2581b2e5..97d73b96cd5d 100644 --- a/crawl-ref/source/webserver/game_data/static/player.js +++ b/crawl-ref/source/webserver/game_data/static/player.js @@ -406,8 +406,6 @@ function ($, comm, enums, map_knowledge, messages, options) { { $("#stats_time_caption").text("Time:"); $("#stats_time").text((player.time / 10.0).toFixed(1)); - if (player.time_delta) - $("#stats_time").append(" (" + (player.time_delta / 10.0).toFixed(1) + ")"); } else { @@ -415,6 +413,9 @@ function ($, comm, enums, map_knowledge, messages, options) { $("#stats_time").text(player.turn); } + if (player.time_delta) + $("#stats_time").append(" (" + (player.time_delta / 10.0).toFixed(1) + ")"); + var place_desc = player.place; if (player.depth) place_desc += ":" + player.depth; $("#stats_place").text(place_desc); From 369f6e7680becec3e21aaa19ba905a3f9491a8a0 Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Fri, 12 Apr 2019 16:38:04 +0100 Subject: [PATCH 247/864] Improve description of protection brand --- crawl-ref/source/describe.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index 14b093e28693..6c0397ea2291 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -1271,8 +1271,8 @@ static string _describe_weapon(const item_def &item, bool verbose) description += "It poisons the flesh of those it strikes."; break; case SPWPN_PROTECTION: - description += "It protects the one who uses it against " - "injury (+AC on strike)."; + description += "It grants its wielder temporary protection when " + "it strikes (+7 to AC)."; break; case SPWPN_DRAINING: description += "A truly terrible weapon, it drains the " From e44751f50656182fcdd77e0d5f8636e6dba5b409 Mon Sep 17 00:00:00 2001 From: advil Date: Fri, 12 Apr 2019 11:08:48 -0400 Subject: [PATCH 248/864] Better messaging for when phantom mirror fails (Yermak) This now prints a specific message for every case, not just sac love. --- crawl-ref/source/evoke.cc | 8 +------ crawl-ref/source/mon-place.cc | 41 +++++++++++++++++++++++++---------- crawl-ref/source/mon-place.h | 2 +- 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/crawl-ref/source/evoke.cc b/crawl-ref/source/evoke.cc index 07d9a54b5239..17d8db5414bb 100644 --- a/crawl-ref/source/evoke.cc +++ b/crawl-ref/source/evoke.cc @@ -1443,14 +1443,8 @@ static spret _phantom_mirror() return spret::abort; } - if (player_will_anger_monster(*victim)) - { - if (you.get_mutation_level(MUT_NO_LOVE)) - mpr("The reflection would only feel hate for you!"); - else - simple_god_message(" forbids your reflecting this monster."); + if (player_angers_monster(victim, false)) return spret::abort; - } #if TAG_MAJOR_VERSION == 34 const int surge = pakellas_surge_devices(); diff --git a/crawl-ref/source/mon-place.cc b/crawl-ref/source/mon-place.cc index 0abec6137b98..8b4a2808cfab 100644 --- a/crawl-ref/source/mon-place.cc +++ b/crawl-ref/source/mon-place.cc @@ -2845,17 +2845,27 @@ conduct_type player_will_anger_monster(const monster &mon) return DID_NOTHING; } -bool player_angers_monster(monster* mon) +bool player_angers_monster(monster* mon, bool real) { ASSERT(mon); // XXX: change to monster &mon // Get the drawbacks, not the benefits... (to prevent e.g. demon-scumming). conduct_type why = player_will_anger_monster(*mon); - if (why && mon->wont_attack()) + if (why && (!real || mon->wont_attack())) { - mon->attitude = ATT_HOSTILE; - mon->del_ench(ENCH_CHARM); - behaviour_event(mon, ME_ALERT, &you); + if (real) + { + mon->attitude = ATT_HOSTILE; + mon->del_ench(ENCH_CHARM); + behaviour_event(mon, ME_ALERT, &you); + } + const string modal = real + ? ((why == DID_SACRIFICE_LOVE) ? "can " : "") + : "would "; + const string verb = (why == DID_SACRIFICE_LOVE) + ? "feel" + : real ? "is" : "be"; + const string vcomplex = modal + verb; if (you.can_see(*mon)) { @@ -2864,26 +2874,33 @@ bool player_angers_monster(monster* mon) switch (why) { case DID_EVIL: - mprf("%s is enraged by your holy aura!", mname.c_str()); + mprf("%s %s enraged by your holy aura!", + mname.c_str(), vcomplex.c_str()); break; case DID_CORPSE_VIOLATION: - mprf("%s is revulsed by your support of nature!", mname.c_str()); + mprf("%s %s revulsed by your support of nature!", + mname.c_str(), vcomplex.c_str()); break; case DID_HOLY: - mprf("%s is enraged by your evilness!", mname.c_str()); + mprf("%s %s enraged by your evilness!", + mname.c_str(), vcomplex.c_str()); break; case DID_UNCLEAN: case DID_CHAOS: - mprf("%s is enraged by your lawfulness!", mname.c_str()); + mprf("%s %s enraged by your lawfulness!", + mname.c_str(), vcomplex.c_str()); break; case DID_SPELL_CASTING: - mprf("%s is enraged by your magic-hating god!", mname.c_str()); + mprf("%s %s enraged by your magic-hating god!", + mname.c_str(), vcomplex.c_str()); break; case DID_SACRIFICE_LOVE: - mprf("%s can only feel hate for you!", mname.c_str()); + mprf("%s %s only hate for you!", + mname.c_str(), vcomplex.c_str()); break; default: - mprf("%s is enraged by a buggy thing about you!", mname.c_str()); + mprf("%s %s enraged by a buggy thing about you!", + mname.c_str(), vcomplex.c_str()); break; } } diff --git a/crawl-ref/source/mon-place.h b/crawl-ref/source/mon-place.h index 7e18bbef54c3..96375eed4a67 100644 --- a/crawl-ref/source/mon-place.h +++ b/crawl-ref/source/mon-place.h @@ -82,7 +82,7 @@ monster_type pick_random_monster(level_id place, conduct_type player_will_anger_monster(monster_type type); conduct_type player_will_anger_monster(const monster &mon); -bool player_angers_monster(monster* mon); +bool player_angers_monster(monster* mon, bool real = true); bool find_habitable_spot_near(const coord_def& where, monster_type mon_type, int radius, bool allow_centre, coord_def& empty, From 2af7e837d0e8c635062773465ab6fa9aa26e0078 Mon Sep 17 00:00:00 2001 From: advil Date: Fri, 12 Apr 2019 12:17:48 -0400 Subject: [PATCH 249/864] Prevent wand of enslavement from being used under sac love Before this commit, despite being grayed out, this wand worked just fine. The implementation, in order not to waste turns, just makes it completely unevokable with sac love. For the sake of consistency I applied this change to all evokers that are useless in this case. An alternative for enslavement might be to prevent it in targeting, which is how phantom mirror previously worked, but the present approach seemed cleaner and wastes the players time less. It might also be good to make a note in the item descriptions that they can't be used so this isn't indicated only by inventory color. In general, enslavement still works under other god conducts that otherwise prevent some but not all summons. This probably could use some thinking, because as NP7 pointed out in chat, it leads to confusing and variable behavior e.g. for spellcasters enslaved under Trog. However, to implement this without taking turns in the general case is a bit tricky. See also 706f6395352a. --- crawl-ref/source/invent.cc | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/crawl-ref/source/invent.cc b/crawl-ref/source/invent.cc index e80b13403054..6cd60ed8cd72 100644 --- a/crawl-ref/source/invent.cc +++ b/crawl-ref/source/invent.cc @@ -1978,6 +1978,27 @@ bool item_is_wieldable(const item_def &item) return is_weapon(item) && you.species != SP_FELID; } +/// Does the item only serve to produce summons or allies? +static bool _item_ally_only(const item_def &item) +{ + if (item.base_type == OBJ_WANDS) + return item.sub_type == WAND_ENSLAVEMENT; + else if (item.base_type == OBJ_MISCELLANY) + { + switch (item.sub_type) + { + case MISC_PHANTOM_MIRROR: + case MISC_HORN_OF_GERYON: + case MISC_BOX_OF_BEASTS: + case MISC_SACK_OF_SPIDERS: + return true; + default: + return false; + } + } + return false; +} + /** * Return whether an item can be evoked. * @@ -2033,6 +2054,14 @@ bool item_is_evokable(const item_def &item, bool reach, bool known, return false; } + // TODO: check other summoning constraints here? + if (_item_ally_only(item) && you.has_mutation(MUT_NO_LOVE)) + { + if (msg) + mpr("That item cannot be used by those hated by all!"); + return false; + } + const bool wielded = !equip || you.equip[EQ_WEAPON] == item.link && !item_is_melded(item); From 6074511092ad270a8202bd6f5d428e3cf35c838b Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 13 Apr 2019 09:58:29 -0400 Subject: [PATCH 250/864] Initialize `you.trapped` to false Previously, this was uninitialized, so on some builds the first time-taking action after loading the game could roll random trap effects, regardless of whether a new square was revealed. The exact behavior would be implementation/compiler-dependent, but on OS X it was getting a random-ish value presumably determined by whatever was in memory before, and I suspect this would be the typical behavior. --- crawl-ref/source/player.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 3f029d726e45..213eea6f29ec 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -5191,6 +5191,8 @@ player::player() num_turns = 0; exploration = 0; + trapped = false; + last_view_update = 0; spell_letter_table.init(-1); From 44e327ef0174bb6e82b4e4ed8ed497613d708ac3 Mon Sep 17 00:00:00 2001 From: ufshaikh Date: Mon, 15 Apr 2019 12:38:40 -0500 Subject: [PATCH 251/864] Show traps in ctrl-x screen (#1035) This commit exposes traps along with features in the ^X display of what is in LOS. This should cut down on manual movement of the cursor with xv to discover what type a trap is, and allow the player to quickly distinguish which types are currently in LOS in areas with many traps. --- crawl-ref/source/directn.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc index cd51c5317961..d9eb1efecc1a 100644 --- a/crawl-ref/source/directn.cc +++ b/crawl-ref/source/directn.cc @@ -557,7 +557,7 @@ class view_desc_proc void nextline() { cgotoxy(1, wherey() + 1); } }; -// Lists all the monsters and items currently in view by the player. +// Lists monsters, items, and some interesting features in the player's view. // TODO: Allow sorting of items lists. void full_describe_view() { @@ -570,7 +570,7 @@ void full_describe_view() you.xray_vision ? LOS_NONE : LOS_DEFAULT); ri; ++ri) { if (feat_stair_direction(grd(*ri)) != CMD_NO_CMD - || feat_is_altar(grd(*ri))) + || (feat_is_trap(grd(*ri)))) { list_features.push_back(*ri); } From 50762623a0cf7263db7b03ef29944f24a6613953 Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 16 Apr 2019 22:38:58 -0400 Subject: [PATCH 252/864] Remove some unused arguments These were used in placing stair mimics, but those haven't placed since 434df5b33ac1. --- crawl-ref/source/dungeon.cc | 20 +++++++++----------- crawl-ref/source/dungeon.h | 3 +-- crawl-ref/source/files.cc | 14 +++----------- 3 files changed, 13 insertions(+), 24 deletions(-) diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 03aab39d67f3..1ac9bee72aa7 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -80,9 +80,8 @@ #endif // DUNGEON BUILDERS -static bool _build_level_vetoable(bool enable_random_maps, - dungeon_feature_type dest_stairs_type); -static void _build_dungeon_level(dungeon_feature_type dest_stairs_type); +static bool _build_level_vetoable(bool enable_random_maps); +static void _build_dungeon_level(); static bool _valid_dungeon_level(); static bool _builder_by_type(); @@ -233,7 +232,7 @@ static string branch_epilogues[NUM_BRANCHES]; /********************************************************************** * builder() - kickoff for the dungeon generator. *********************************************************************/ -bool builder(bool enable_random_maps, dungeon_feature_type dest_stairs_type) +bool builder(bool enable_random_maps) { // Re-check whether we're in a valid place, it leads to obscure errors // otherwise. @@ -271,7 +270,7 @@ bool builder(bool enable_random_maps, dungeon_feature_type dest_stairs_type) try { - if (_build_level_vetoable(enable_random_maps, dest_stairs_type)) + if (_build_level_vetoable(enable_random_maps)) return true; } catch (map_load_exception &mload) @@ -305,8 +304,7 @@ bool builder(bool enable_random_maps, dungeon_feature_type dest_stairs_type) return false; } -static bool _build_level_vetoable(bool enable_random_maps, - dungeon_feature_type dest_stairs_type) +static bool _build_level_vetoable(bool enable_random_maps) { #ifdef DEBUG_STATISTICS mapstat_report_map_build_start(); @@ -319,7 +317,7 @@ static bool _build_level_vetoable(bool enable_random_maps, try { - _build_dungeon_level(dest_stairs_type); + _build_dungeon_level(); } catch (dgn_veto_exception& e) { @@ -2318,7 +2316,7 @@ static bool _mimic_at_level() && !crawl_state.game_is_tutorial(); } -static void _place_feature_mimics(dungeon_feature_type dest_stairs_type) +static void _place_feature_mimics() { for (rectangle_iterator ri(1); ri; ++ri) { @@ -2366,7 +2364,7 @@ static void _post_vault_build() } } -static void _build_dungeon_level(dungeon_feature_type dest_stairs_type) +static void _build_dungeon_level() { bool place_vaults = _builder_by_type(); @@ -2420,7 +2418,7 @@ static void _build_dungeon_level(dungeon_feature_type dest_stairs_type) _place_uniques(); if (_mimic_at_level()) - _place_feature_mimics(dest_stairs_type); + _place_feature_mimics(); _place_traps(); diff --git a/crawl-ref/source/dungeon.h b/crawl-ref/source/dungeon.h index 72c9148db0d5..623311687473 100644 --- a/crawl-ref/source/dungeon.h +++ b/crawl-ref/source/dungeon.h @@ -194,8 +194,7 @@ void init_level_connectivity(); void read_level_connectivity(reader &th); void write_level_connectivity(writer &th); -bool builder(bool enable_random_maps = true, - dungeon_feature_type dest_stairs_type = NUM_FEATURES); +bool builder(bool enable_random_maps = true); void dgn_clear_vault_placements(); void dgn_erase_unused_vault_placements(); diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 4e9b625a4099..0036616a4a0d 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1242,8 +1242,7 @@ static bool _leave_level(dungeon_feature_type stair_taken, * @param stair_taken The means used to leave the last level. * @param old_level The ID of the previous level. */ -static void _make_level(dungeon_feature_type stair_taken, - const level_id& old_level) +static void _make_level() { env.turns_on_level = -1; @@ -1252,15 +1251,8 @@ static void _make_level(dungeon_feature_type stair_taken, tile_clear_flavour(); env.tile_names.clear(); - // XXX: This is ugly. - bool dummy; - dungeon_feature_type stair_type = static_cast( - _get_dest_stair_type(old_level.branch, - static_cast(stair_taken), - dummy)); - _clear_env_map(); - builder(true, stair_type); + builder(true); env.turns_on_level = 0; // sanctuary @@ -1543,7 +1535,7 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, { ASSERT(load_mode != LOAD_VISITOR); dprf("Generating new level for '%s'.", level_name.c_str()); - _make_level(stair_taken, old_level); + _make_level(); you.vault_list[level_id::current()] = level_vault_names(); just_created_level = true; } From 26cb7716be52e652a346b03d8bd6e70913aa581a Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 17 Apr 2019 17:03:11 -0400 Subject: [PATCH 253/864] Don't use div_rand_round for noise values In wizmode, this could have the following effect: in a non-pregen game, when a noise happened before descending to a new level, as long as levelgen triggers a more, drawing the wizmode noise bar could cycle the levelgen rng while rerendering the hud during that more. (I hope there aren't more things like this, but there might be, as quite a lot of code gets called on a more. So it may be worth just forcing the ui rng for doing mores.) Luckily, non-wizmode noise rendering doesn't call this code path. --- crawl-ref/source/player.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 213eea6f29ec..9bb960fb9aff 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -5567,7 +5567,7 @@ int player::get_noise_perception(bool adjusted) const const int level = los_noise_last_turn; static const int BAR_MAX = 1000; // TODO: export to output.cc & webtiles if (!adjusted) - return div_rand_round(level, BAR_MAX); + return (level + 500) / BAR_MAX; static const vector NOISE_BREAKPOINTS = { 0, 6000, 13000, 29000 }; const int BAR_FRAC = BAR_MAX / (NOISE_BREAKPOINTS.size() - 1); From f493760c106ee6091b4d100717670827876d77d4 Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 17 Apr 2019 17:18:38 -0400 Subject: [PATCH 254/864] Prevent messages from impacting non-UI generators This may be overkill, but a lot of things can happen during messaging in crawlcode, so this will ensure that none of those things will ever affect the levelgen (or gameplay) rng. --- crawl-ref/source/message.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crawl-ref/source/message.cc b/crawl-ref/source/message.cc index bd3acfb2066a..8c2206f0903e 100644 --- a/crawl-ref/source/message.cc +++ b/crawl-ref/source/message.cc @@ -680,6 +680,8 @@ class message_window */ void more(bool full, bool user=false) { + rng_generator rng(RNG_UI); + if (_pre_more()) return; @@ -1355,6 +1357,8 @@ static int _last_msg_turn = -1; // Turn of last message. static void _mpr(string text, msg_channel_type channel, int param, bool nojoin, bool cap) { + rng_generator rng(RNG_UI); + if (_msg_dump_file != nullptr) fprintf(_msg_dump_file, "%s\n", text.c_str()); @@ -1762,6 +1766,8 @@ static bool _pre_more() void more(bool user_forced) { + rng_generator rng(RNG_UI); + if (!crawl_state.io_inited) return; flush_prev_message(); From 1d4c5a47d16daeefc8f4d7c30e2842c8f18edeb2 Mon Sep 17 00:00:00 2001 From: nlavsky <3328424+nlavsky@users.noreply.github.com> Date: Thu, 18 Apr 2019 22:59:34 +0300 Subject: [PATCH 255/864] Fix local tiles monster panel showing summoner halo for all enemies (#1038) This was happening because the packed_cell constructor was not initializing `is_highlighted_summoner`. --- crawl-ref/source/tilecell.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/tilecell.h b/crawl-ref/source/tilecell.h index 960b4a1e0d73..623ff533d682 100644 --- a/crawl-ref/source/tilecell.h +++ b/crawl-ref/source/tilecell.h @@ -44,7 +44,8 @@ struct packed_cell bool operator ==(const packed_cell &other) const; bool operator !=(const packed_cell &other) const { return !(*this == other); } - packed_cell() : num_dngn_overlay(0), fg(0), bg(0), cloud(0), is_bloody(false), + packed_cell() : num_dngn_overlay(0), fg(0), bg(0), cloud(0), + is_highlighted_summoner(false), is_bloody(false), is_silenced(false), halo(HALO_NONE), is_moldy(false), glowing_mold(false), is_sanctuary(false), is_liquefied(false), mangrove_water(false), awakened_forest(false), orb_glow(0), @@ -58,6 +59,7 @@ struct packed_cell packed_cell(const packed_cell* c) : num_dngn_overlay(c->num_dngn_overlay), fg(c->fg), bg(c->bg), flv(c->flv), cloud(c->cloud), + is_highlighted_summoner(c->is_highlighted_summoner), is_bloody(c->is_bloody), is_silenced(c->is_silenced), halo(c->halo), From 86c19343c97cc1917eb6ef2d10d0c35ceb8b1589 Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Thu, 18 Apr 2019 21:37:39 +0100 Subject: [PATCH 256/864] Fix a message colour entry --- crawl-ref/source/dat/defaults/messages.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/dat/defaults/messages.txt b/crawl-ref/source/dat/defaults/messages.txt index ec654edb9acc..639a71ad5b9f 100644 --- a/crawl-ref/source/dat/defaults/messages.txt +++ b/crawl-ref/source/dat/defaults/messages.txt @@ -64,7 +64,7 @@ msc += $warning:fails to return msc += $warning:no longer ripe msc += $warning:This .* contains the .* runes? of Zot. msc += $warning:They guard the .* runes? of Zot. -msc += $warning:Beware, you cannot shaft yourself on this level. +msc += $warning:Beware\, you cannot shaft yourself on this level. # Unimportant messages and combat clutter # From 927fd9e6cbeee1204f60a75af7c983c8b6d3b763 Mon Sep 17 00:00:00 2001 From: kitchen-ace <47063032+kitchen-ace@users.noreply.github.com> Date: Thu, 18 Apr 2019 16:53:18 -0400 Subject: [PATCH 257/864] Minor changes to default force_more_messages (#1037) "Careful!" was being triggered by allies that sometimes said "Be careful!". --- crawl-ref/source/dat/defaults/messages.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/dat/defaults/messages.txt b/crawl-ref/source/dat/defaults/messages.txt index 639a71ad5b9f..64d61f4d3164 100644 --- a/crawl-ref/source/dat/defaults/messages.txt +++ b/crawl-ref/source/dat/defaults/messages.txt @@ -91,7 +91,7 @@ msc += mute:Uskayaw will no longer force your foes to share their pain\. force_more_message += You have reached level force_more_message += Your scales start -force_more_message += You fall through a shaft +force_more_message += You (fall through|are sucked into) a shaft force_more_message += You fall into the water! force_more_message += You fall into the lava! force_more_message += You focus on prolonging your flight @@ -104,7 +104,7 @@ force_more_message += You don't have the energy to cast that spell force_more_message += This is a scroll of acquirement ## Reduce chance of draining because flight or form runs out: -force_more_message += Careful! +force_more_message += ^Careful! # Announcements of timed portal vaults: force_more_message += interdimensional caravan From b86c0f735e93801e4d99dbc07ea79478c88ddbba Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Thu, 18 Apr 2019 21:58:41 +0100 Subject: [PATCH 258/864] Clean up more default force_more_messages --- crawl-ref/source/dat/defaults/messages.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/dat/defaults/messages.txt b/crawl-ref/source/dat/defaults/messages.txt index 64d61f4d3164..2869c8fc4020 100644 --- a/crawl-ref/source/dat/defaults/messages.txt +++ b/crawl-ref/source/dat/defaults/messages.txt @@ -62,9 +62,9 @@ msc += $warning:settles down msc += lightcyan:LOW MAGIC WARNING msc += $warning:fails to return msc += $warning:no longer ripe -msc += $warning:This .* contains the .* runes? of Zot. -msc += $warning:They guard the .* runes? of Zot. -msc += $warning:Beware\, you cannot shaft yourself on this level. +msc += $warning:This .* contains the .* runes? of Zot +msc += $warning:They guard the .* runes? of Zot +msc += $warning:Beware\, you cannot shaft yourself on this level # Unimportant messages and combat clutter # @@ -126,7 +126,7 @@ force_more_message += You have lost your religion force_more_message += is wielding.*distortion # dancing weapons require special handling... force_more_message += there is a.*distortion -force_more_message += of distortion comes into view. +force_more_message += of distortion comes into view # Banishment force_more_message += You are cast into the Abyss From c7211da41105ccc2e1228da040ef87be5fe02e2f Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Thu, 18 Apr 2019 23:30:51 +0100 Subject: [PATCH 259/864] Remove some dead Cigotuvi's Embrace code --- crawl-ref/source/attribute-type.h | 2 ++ crawl-ref/source/enchant-type.h | 2 +- crawl-ref/source/monster.cc | 3 --- crawl-ref/source/output.cc | 3 +-- crawl-ref/source/player.cc | 1 - crawl-ref/source/player.h | 3 --- crawl-ref/source/spl-selfench.cc | 6 ------ crawl-ref/source/status.cc | 8 -------- crawl-ref/source/status.h | 1 - 9 files changed, 4 insertions(+), 25 deletions(-) diff --git a/crawl-ref/source/attribute-type.h b/crawl-ref/source/attribute-type.h index 3686328386e6..a5dff8de80db 100644 --- a/crawl-ref/source/attribute-type.h +++ b/crawl-ref/source/attribute-type.h @@ -82,7 +82,9 @@ enum attribute_type ATTR_DIVINE_AC, // Divine AC bonus (Qazlal). #endif ATTR_GOZAG_GOLD_USED, // Gold spent for Gozag abilities. +#if TAG_MAJOR_VERSION == 34 ATTR_BONE_ARMOUR, // Current amount of bony armour (from the spell) +#endif ATTR_LAST_FLIGHT_STATUS, // Whether SPARM_FLIGHT should be restored after form change ATTR_GOZAG_FIRST_POTION, // Gozag's free first usage of Potion Petition. ATTR_STAT_LOSS_XP, // Unmodified XP needed for stat recovery. diff --git a/crawl-ref/source/enchant-type.h b/crawl-ref/source/enchant-type.h index cea1f80deb6b..749ce1c83652 100644 --- a/crawl-ref/source/enchant-type.h +++ b/crawl-ref/source/enchant-type.h @@ -161,8 +161,8 @@ enum enchant_type #endif ENCH_RESISTANCE, ENCH_HEXED, - ENCH_BONE_ARMOUR, #if TAG_MAJOR_VERSION == 34 + ENCH_BONE_ARMOUR, ENCH_CHANT_FIRE_STORM, // chanting the fire storm spell ENCH_CHANT_WORD_OF_ENTROPY, // chanting word of entropy #endif diff --git a/crawl-ref/source/monster.cc b/crawl-ref/source/monster.cc index fbb36c7b0047..9f894f443c70 100644 --- a/crawl-ref/source/monster.cc +++ b/crawl-ref/source/monster.cc @@ -3120,7 +3120,6 @@ bool monster::pacified() const bool monster::shielded() const { return shield() - || has_ench(ENCH_BONE_ARMOUR) || wearing(EQ_AMULET_PLUS, AMU_REFLECTION) > 0; } @@ -3349,8 +3348,6 @@ int monster::armour_class(bool calc_unid) const ac += 4 + get_hit_dice() / 3; if (has_ench(ENCH_ICEMAIL)) ac += ICEMAIL_MAX; - if (has_ench(ENCH_BONE_ARMOUR)) - ac += 6 + get_hit_dice() / 3; if (has_ench(ENCH_IDEALISED)) ac += 4 + get_hit_dice() / 3; diff --git a/crawl-ref/source/output.cc b/crawl-ref/source/output.cc index 4cffc48a12ae..a422ec4af03a 100644 --- a/crawl-ref/source/output.cc +++ b/crawl-ref/source/output.cc @@ -511,8 +511,7 @@ static bool _boosted_ev() static bool _boosted_sh() { return you.duration[DUR_DIVINE_SHIELD] - || qazlal_sh_boost() > 0 - || you.attribute[ATTR_BONE_ARMOUR] > 0; + || qazlal_sh_boost() > 0; } #ifdef DGL_SIMPLE_MESSAGING diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 9bb960fb9aff..4e5c4eefcbee 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -5641,7 +5641,6 @@ bool player::shielded() const || duration[DUR_DIVINE_SHIELD] || get_mutation_level(MUT_LARGE_BONE_PLATES) > 0 || qazlal_sh_boost() > 0 - || attribute[ATTR_BONE_ARMOUR] > 0 || you.wearing(EQ_AMULET_PLUS, AMU_REFLECTION) > 0 || you.scan_artefacts(ARTP_SHIELDING); } diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h index fefe8a8b7dd7..42c4a047519c 100644 --- a/crawl-ref/source/player.h +++ b/crawl-ref/source/player.h @@ -68,9 +68,6 @@ static const int MR_PIP = 40; /// The standard unit of stealth; one level in %/@ screens static const int STEALTH_PIP = 50; -/// The rough number of aut getting hit takes off your bone armour -static const int BONE_ARMOUR_HIT_RATIO = 50; - /// The minimum aut cost for a player move (before haste) static const int FASTEST_PLAYER_MOVE_SPEED = 6; // relevant for swiftness, etc diff --git a/crawl-ref/source/spl-selfench.cc b/crawl-ref/source/spl-selfench.cc index 71510e36d627..37e5bfdaafae 100644 --- a/crawl-ref/source/spl-selfench.cc +++ b/crawl-ref/source/spl-selfench.cc @@ -72,12 +72,6 @@ spret ice_armour(int pow, bool fail) else mpr("A film of ice covers your body!"); - if (you.attribute[ATTR_BONE_ARMOUR] > 0) - { - you.attribute[ATTR_BONE_ARMOUR] = 0; - mpr("Your corpse armour falls away."); - } - you.increase_duration(DUR_ICY_ARMOUR, random_range(40, 50), 50); you.props[ICY_ARMOUR_KEY] = pow; you.redraw_armour_class = true; diff --git a/crawl-ref/source/status.cc b/crawl-ref/source/status.cc index 95a06861743d..86af014512c5 100644 --- a/crawl-ref/source/status.cc +++ b/crawl-ref/source/status.cc @@ -387,14 +387,6 @@ bool fill_status_info(int status, status_info& inf) _describe_stat_zero(inf, STAT_DEX); break; - case STATUS_BONE_ARMOUR: - if (you.attribute[ATTR_BONE_ARMOUR] > 0) - { - inf.short_text = "corpse armour"; - inf.long_text = "You are enveloped in carrion and bones."; - } - break; - case STATUS_CONSTRICTED: if (you.is_constricted()) { diff --git a/crawl-ref/source/status.h b/crawl-ref/source/status.h index 2a7c40036f83..054760cef9a4 100644 --- a/crawl-ref/source/status.h +++ b/crawl-ref/source/status.h @@ -49,7 +49,6 @@ enum status_type #endif STATUS_BRIBE, STATUS_CLOUD, - STATUS_BONE_ARMOUR, STATUS_ORB, STATUS_DIVINE_ENERGY, STATUS_STILL_WINDS, From 7384745ea90e3da0b4de0b9550ebf3385612f2e0 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Fri, 12 Apr 2019 22:34:39 -0400 Subject: [PATCH 260/864] Teach monsters to use scattershot, cloud, and iceblast wands This refactors monster wand usage to deduplicate some of the beam and tracer codepaths for wands and other beams. Specifically monster wand evocations now go through the mons_cast codepath. This has the unfortunate need of adding a spell flag to indicate an evoked spell; however the benefit is that monster wands now pass through the more sophisticated monster casting code that previously handled the rod versions of scattershot and cloud. As a result monsters now know how to use scattershot, cloud, and iceblast wands. The monsters use the new wands with a power of 30 + hd, identical to the power used for existing wands. This is a flatter power curve than the old rod spells, making them more dangerous on low HD monsters. However, some playtesting indicates that these are not worse than an early acid wand in damage level. --- crawl-ref/source/externs.h | 5 +- crawl-ref/source/mon-act.cc | 97 +++++++++++------------------------- crawl-ref/source/mon-cast.cc | 12 +++-- crawl-ref/source/mon-cast.h | 1 + 4 files changed, 41 insertions(+), 74 deletions(-) diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h index e7cecc7a3c4b..d439c0e03cc1 100644 --- a/crawl-ref/source/externs.h +++ b/crawl-ref/source/externs.h @@ -758,10 +758,11 @@ enum mon_spell_slot_flag MON_SPELL_SHORT_RANGE = 1 << 10, // only use at short distances MON_SPELL_LONG_RANGE = 1 << 11, // only use at long distances + MON_SPELL_EVOKE = 1 << 12, // a spell from an evoked item - MON_SPELL_LAST_FLAG = MON_SPELL_LONG_RANGE, + MON_SPELL_LAST_FLAG = MON_SPELL_EVOKE, }; -DEF_BITFIELD(mon_spell_slot_flags, mon_spell_slot_flag, 11); +DEF_BITFIELD(mon_spell_slot_flags, mon_spell_slot_flag, 12); const int MON_SPELL_LAST_EXPONENT = mon_spell_slot_flags::last_exponent; COMPILE_CHECK(mon_spell_slot_flags::exponent(MON_SPELL_LAST_EXPONENT) == MON_SPELL_LAST_FLAG); diff --git a/crawl-ref/source/mon-act.cc b/crawl-ref/source/mon-act.cc index 7bc33724f2f3..cae24ac24884 100644 --- a/crawl-ref/source/mon-act.cc +++ b/crawl-ref/source/mon-act.cc @@ -1039,55 +1039,8 @@ static bool _handle_scroll(monster& mons) return read; } -static bolt& _generate_item_beem(bolt &beem, bolt& from, monster& mons) -{ - beem.name = from.name; - beem.source_id = mons.mid; - beem.source = mons.pos(); - beem.colour = from.colour; - beem.range = from.range; - beem.damage = from.damage; - beem.ench_power = from.ench_power; - beem.hit = from.hit; - beem.glyph = from.glyph; - beem.flavour = from.flavour; - beem.thrower = from.thrower; - beem.pierce = from.pierce ; - beem.is_explosion = from.is_explosion; - beem.origin_spell = from.origin_spell; - return beem; -} - -static bool _setup_wand_beam(bolt& beem, monster& mons, const item_def& wand) -{ - if (item_type_removed(wand.base_type, wand.sub_type)) - return false; - - //XXX: implement these for monsters... (: - if (wand.sub_type == WAND_ICEBLAST - || wand.sub_type == WAND_RANDOM_EFFECTS - || wand.sub_type == WAND_CLOUDS - || wand.sub_type == WAND_SCATTERSHOT) - { - return false; - } - - const spell_type mzap = - spell_in_wand(static_cast(wand.sub_type)); - - // set up the beam - int power = 30 + mons.get_hit_dice(); - bolt theBeam = mons_spell_beam(&mons, mzap, power); - beem = _generate_item_beem(beem, theBeam, mons); - - beem.aux_source = - wand.name(DESC_QUALNAME, false, true, false, false); - - return true; -} - static void _mons_fire_wand(monster& mons, item_def &wand, bolt &beem, - bool was_visible, bool niceWand) + bool was_visible) { if (!simple_monster_message(mons, " zaps a wand.")) { @@ -1097,8 +1050,10 @@ static void _mons_fire_wand(monster& mons, item_def &wand, bolt &beem, // charge expenditure {dlb} wand.charges--; - beem.is_tracer = false; - beem.fire(); + const spell_type mzap = + spell_in_wand(static_cast(wand.sub_type)); + + mons_cast(&mons, beem, mzap, MON_SPELL_EVOKE, false); if (was_visible) { @@ -1137,14 +1092,21 @@ static bool _handle_wand(monster& mons) if (wand->charges <= 0) return false; - bool niceWand = false; - bool zap = false; - bool was_visible = you.can_see(mons); - bolt beem = setup_targetting_beam(mons); + if (item_type_removed(wand->base_type, wand->sub_type)) + return false; + + bolt beem; - if (!_setup_wand_beam(beem, mons, *wand)) + const spell_type mzap = + spell_in_wand(static_cast(wand->sub_type)); + + if (!setup_mons_cast(&mons, beem, mzap, true)) return false; + beem.source = mons.pos(); + beem.aux_source = + wand->name(DESC_QUALNAME, false, true, false, false); + const wand_type kind = (wand_type)wand->sub_type; switch (kind) { @@ -1154,26 +1116,22 @@ static bool _handle_wand(monster& mons) beem.damage.size = beem.damage.size * 2 / 3; break; + // XXX: Teach monsters to use this + case WAND_RANDOM_EFFECTS: + // This is handled elsewhere, so that the correct target is set. case WAND_DIGGING: - // This is handled elsewhere. return false; default: break; } - if (!niceWand) - { - // Fire tracer, if necessary. - fire_tracer(&mons, beem); - - // Good idea? - zap = mons_should_fire(beem); - } + // Fire tracer, if necessary. + fire_tracer(&mons, beem); - if (niceWand || zap) + if (mons_should_fire(beem)) { - _mons_fire_wand(mons, *wand, beem, was_visible, niceWand); + _mons_fire_wand(mons, *wand, beem, you.see_cell(mons.pos())); return true; } @@ -3547,9 +3505,12 @@ static bool _monster_move(monster* mons) { ASSERT(mons->mslot_item(MSLOT_WAND)); item_def &wand = *mons->mslot_item(MSLOT_WAND); + setup_mons_cast(mons, beem, SPELL_DIG, true); beem.target = mons->pos() + mmov; - _setup_wand_beam(beem, *mons, wand); - _mons_fire_wand(*mons, wand, beem, you.can_see(*mons), false); + _mons_fire_wand(*mons, wand, beem, you.can_see(*mons)); + + //_setup_wand_beam(beem, *mons, wand); + //_mons_fire_wand(*mons, wand, beem, you.can_see(*mons), false); } else simple_monster_message(*mons, " falters for a moment."); diff --git a/crawl-ref/source/mon-cast.cc b/crawl-ref/source/mon-cast.cc index a80166010928..c115d7a90969 100644 --- a/crawl-ref/source/mon-cast.cc +++ b/crawl-ref/source/mon-cast.cc @@ -867,7 +867,7 @@ void init_mons_spells() #if TAG_MAJOR_VERSION == 34 spell == SPELL_MELEE || #endif - setup_mons_cast(&fake_mon, pbolt, spell, true)) + setup_mons_cast(&fake_mon, pbolt, spell, false, true)) { _valid_mon_spells[i] = true; } @@ -1733,6 +1733,7 @@ bolt mons_spell_beam(const monster* mons, spell_type spell_cast, int power, // Set up bolt structure for monster spell casting. bool setup_mons_cast(const monster* mons, bolt &pbolt, spell_type spell_cast, + bool evoke, bool check_validity) { // always set these -- used by things other than fire_beam() @@ -1939,7 +1940,8 @@ bool setup_mons_cast(const monster* mons, bolt &pbolt, spell_type spell_cast, } } - const int power = mons_spellpower(*mons, spell_cast); + const int power = evoke ? 30 + mons->get_hit_dice() + : mons_spellpower(*mons, spell_cast); bolt theBeam = mons_spell_beam(mons, spell_cast, power); @@ -5722,9 +5724,10 @@ void mons_cast(monster* mons, bolt pbolt, spell_type spell_cast, false); return; } + bool evoke {slot_flags & MON_SPELL_EVOKE}; // Always do setup. It might be done already, but it doesn't hurt // to do it again (cheap). - setup_mons_cast(mons, pbolt, spell_cast); + setup_mons_cast(mons, pbolt, spell_cast, evoke); // single calculation permissible {dlb} const spell_flags flags = get_spell_flags(spell_cast); @@ -5772,7 +5775,8 @@ void mons_cast(monster* mons, bolt pbolt, spell_type spell_cast, } const god_type god = _find_god(*mons, slot_flags); - const int splpow = mons_spellpower(*mons, spell_cast); + const int splpow = evoke ? 30 + mons->get_hit_dice() + : mons_spellpower(*mons, spell_cast); switch (spell_cast) { diff --git a/crawl-ref/source/mon-cast.h b/crawl-ref/source/mon-cast.h index 2368ddb50b90..f608e154703d 100644 --- a/crawl-ref/source/mon-cast.h +++ b/crawl-ref/source/mon-cast.h @@ -37,6 +37,7 @@ void mons_cast(monster* mons, bolt pbolt, spell_type spell_cast, void mons_cast_noise(monster* mons, const bolt &pbolt, spell_type spell_cast, mon_spell_slot_flags slot_flags); bool setup_mons_cast(const monster* mons, bolt &pbolt, spell_type spell_cast, + bool evoke = false, bool check_validity = false); void mons_cast_haunt(monster* mons); From 13415af0d45bd743c1c2e34c3fd2cdd88c732f17 Mon Sep 17 00:00:00 2001 From: Joshua Gelbard Date: Wed, 17 Apr 2019 14:01:30 -0700 Subject: [PATCH 261/864] Fix a couple Engulf-related bugs Fix a bug where Engulf status wouldn't update on time if the player escaped via an instant action like Serpent's Lash movement or a retaliatory headbutt. (Instead of setting the remaining duration to one aut and waiting for the enchantment decrement step to finish it off, just clear it on the spot.) Also remove buggy immunity to engulf. Escaping from being engulfed was supposed to have been conferring one turn of immunity, but the amount given has always been effectively zero. Since no one seems to have noticed, it's probably fine to just remove it. --- crawl-ref/source/duration-data.h | 2 +- crawl-ref/source/duration-type.h | 2 ++ crawl-ref/source/melee-attack.cc | 3 +-- crawl-ref/source/mon-death.cc | 2 ++ crawl-ref/source/movement.cc | 2 +- crawl-ref/source/player.cc | 45 +++++++++----------------------- 6 files changed, 20 insertions(+), 36 deletions(-) diff --git a/crawl-ref/source/duration-data.h b/crawl-ref/source/duration-data.h index 9ffa0e51acfd..a63fffde57b8 100644 --- a/crawl-ref/source/duration-data.h +++ b/crawl-ref/source/duration-data.h @@ -596,7 +596,6 @@ static const duration_def duration_data[] = { DUR_VEHUMET_GIFT, 0, "", "", "vehumet gift", "", D_NO_FLAGS, {{""}}}, { DUR_SICKENING, 0, "", "", "sickening", "", D_DISPELLABLE, {{""}}}, { DUR_WATER_HOLD, 0, "", "", "drowning", "", D_NO_FLAGS}, - { DUR_WATER_HOLD_IMMUNITY, 0, "", "", "drowning immunity", "", D_NO_FLAGS, {{""}}}, { DUR_SLEEP_IMMUNITY, 0, "", "", "sleep immunity", "", D_NO_FLAGS, {{""}}}, { DUR_ELIXIR_HEALTH, 0, "", "", "elixir health", "", D_NO_FLAGS}, { DUR_ELIXIR_MAGIC, 0, "", "", "elixir magic", "", D_NO_FLAGS}, @@ -652,6 +651,7 @@ static const duration_def duration_data[] = { DUR_MAGIC_ARMOUR, 0, "", "", "old magic armour", "", D_NO_FLAGS}, { DUR_MAGIC_SHIELD, 0, "", "", "old magic shield", "", D_NO_FLAGS}, { DUR_FORTITUDE, 0, "", "", "old fortitude", "", D_NO_FLAGS}, + { DUR_WATER_HOLD_IMMUNITY, 0, "", "", "old drowning immunity", "", D_NO_FLAGS, {{""}}}, #endif }; diff --git a/crawl-ref/source/duration-type.h b/crawl-ref/source/duration-type.h index 5f40b56135b2..c21854464ceb 100644 --- a/crawl-ref/source/duration-type.h +++ b/crawl-ref/source/duration-type.h @@ -120,7 +120,9 @@ enum duration_type DUR_SENTINEL_MARK, DUR_SICKENING, DUR_WATER_HOLD, +#if TAG_MAJOR_VERSION == 34 DUR_WATER_HOLD_IMMUNITY, +#endif DUR_FLAYED, #if TAG_MAJOR_VERSION == 34 DUR_RETCHING, diff --git a/crawl-ref/source/melee-attack.cc b/crawl-ref/source/melee-attack.cc index f8271484eb5f..8511276da043 100644 --- a/crawl-ref/source/melee-attack.cc +++ b/crawl-ref/source/melee-attack.cc @@ -2949,8 +2949,7 @@ void melee_attack::mons_apply_attack_flavour() case AF_ENGULF: if (x_chance_in_y(2, 3) && attacker->can_constrict(defender, true)) { - if (defender->is_player() && !you.duration[DUR_WATER_HOLD] - && !you.duration[DUR_WATER_HOLD_IMMUNITY]) + if (defender->is_player() && !you.duration[DUR_WATER_HOLD]) { you.duration[DUR_WATER_HOLD] = 10; you.props["water_holder"].get_int() = attacker->as_monster()->mid; diff --git a/crawl-ref/source/mon-death.cc b/crawl-ref/source/mon-death.cc index 3e8f4b53fd81..de1f1d76e33b 100644 --- a/crawl-ref/source/mon-death.cc +++ b/crawl-ref/source/mon-death.cc @@ -2876,6 +2876,8 @@ void monster_cleanup(monster* mons) // cleaned up first, we wouldn't get a message anyway. mons->stop_constricting_all(false, true); + mons->clear_far_engulf(); + if (mons_is_tentacle_head(mons_base_type(*mons))) destroy_tentacles(mons); diff --git a/crawl-ref/source/movement.cc b/crawl-ref/source/movement.cc index dc59fa88c93a..1c988ab7a6af 100644 --- a/crawl-ref/source/movement.cc +++ b/crawl-ref/source/movement.cc @@ -717,8 +717,8 @@ void move_player_action(coord_def move) if (you.duration[DUR_WATER_HOLD]) { mpr("You slip free of the water engulfing you."); - you.duration[DUR_WATER_HOLD] = 1; you.props.erase("water_holder"); + you.clear_far_engulf(); } if (you.digging) diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 4e5c4eefcbee..8b9f0a5554d7 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -4948,7 +4948,6 @@ bool land_player(bool quiet) static void _end_water_hold() { you.duration[DUR_WATER_HOLD] = 0; - you.duration[DUR_WATER_HOLD_IMMUNITY] = 1; you.props.erase("water_holder"); } @@ -4958,7 +4957,7 @@ bool player::clear_far_engulf() return false; monster * const mons = monster_by_mid(you.props["water_holder"].get_int()); - if (!mons || !adjacent(mons->pos(), you.pos())) + if (!mons || !mons->alive() || !adjacent(mons->pos(), you.pos())) { if (you.res_water_drowning()) mpr("The water engulfing you falls away."); @@ -4973,40 +4972,22 @@ bool player::clear_far_engulf() void handle_player_drowning(int delay) { - if (you.duration[DUR_WATER_HOLD] == 1) + if (you.clear_far_engulf()) + return; + if (you.res_water_drowning()) { - if (!you.res_water_drowning()) - mpr("You gasp with relief as air once again reaches your lungs."); - _end_water_hold(); + // Reset so damage doesn't ramp up while able to breathe + you.duration[DUR_WATER_HOLD] = 10; } else { - monster* mons = monster_by_mid(you.props["water_holder"].get_int()); - if (!mons || !adjacent(mons->pos(), you.pos())) - { - if (you.res_water_drowning()) - mpr("The water engulfing you falls away."); - else - mpr("You gasp with relief as air once again reaches your lungs."); - - _end_water_hold(); - - } - else if (you.res_water_drowning()) - { - // Reset so damage doesn't ramp up while able to breathe - you.duration[DUR_WATER_HOLD] = 10; - } - else if (!you.res_water_drowning()) - { - you.duration[DUR_WATER_HOLD] += delay; - int dam = - div_rand_round((28 + stepdown((float)you.duration[DUR_WATER_HOLD], 28.0)) - * delay, - BASELINE_DELAY * 10); - ouch(dam, KILLED_BY_WATER, mons->mid); - mprf(MSGCH_WARN, "Your lungs strain for air!"); - } + you.duration[DUR_WATER_HOLD] += delay; + int dam = + div_rand_round((28 + stepdown((float)you.duration[DUR_WATER_HOLD], 28.0)) + * delay, + BASELINE_DELAY * 10); + ouch(dam, KILLED_BY_WATER, you.props["water_holder"].get_int()); + mprf(MSGCH_WARN, "Your lungs strain for air!"); } } From 6d359e791a8de0106f04c02a6895ea78382e01cf Mon Sep 17 00:00:00 2001 From: kitchen-ace <68k@quikphix.org> Date: Mon, 15 Apr 2019 01:59:59 -0400 Subject: [PATCH 262/864] Add second brand to description for Thermic Engine and Storm Bow --- crawl-ref/source/describe.cc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index 6c0397ea2291..a3825b997990 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -1343,6 +1343,20 @@ static string _describe_weapon(const item_def &item, bool verbose) } } + if (is_unrandom_artefact(item, UNRAND_STORM_BOW)) + { + description += "\n\nAmmo fired by it will pass through the " + "targets it hits, potentially hitting all targets in " + "its path until it reaches maximum range."; + } + else if (is_unrandom_artefact(item, UNRAND_THERMIC_ENGINE)) + { + description += "\n\nIt has been specially enchanted to freeze " + "those struck by it, causing extra injury to most foes " + "and up to half again as much damage against particularly " + "susceptible opponents."; + } + if (you.duration[DUR_EXCRUCIATING_WOUNDS] && &item == you.weapon()) { description += "\nIt is temporarily rebranded; it is actually a"; From bee43f90e2b7fd6a3e03b680d20e4816a30448cc Mon Sep 17 00:00:00 2001 From: olowin Date: Mon, 15 Apr 2019 10:13:51 -0400 Subject: [PATCH 263/864] Update Gyre and Gimble Remove the -3 Dex and add the protection brand which is not currently used by any unrand and compensates somewhat for locking out a shield. The enchantment is bumped to make the effective damage roughly the same as with the piercing brand. According to fsim, +7 gives slightly more and +6 gives slightly less than the orginal. [Closes #1026] --- crawl-ref/source/art-data.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/art-data.txt b/crawl-ref/source/art-data.txt index aa1ec632ce8f..d4aef559bbda 100644 --- a/crawl-ref/source/art-data.txt +++ b/crawl-ref/source/art-data.txt @@ -1212,9 +1212,8 @@ TYPE: pair of quick blades COLOUR: ETC_ENCHANT TILE: urand_gyre TILE_EQ: gyre -PLUS: 5 -BRAND: SPWPN_VORPAL -DEX: -3 +PLUS: 7 +BRAND: SPWPN_PROTECTION ENUM: ETHERIC_CAGE NAME: Maxwell's etheric cage From f46a3880409c03102ce3384e65a8ff327b3717ce Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Fri, 19 Apr 2019 07:52:03 -0400 Subject: [PATCH 264/864] Don't crash when a monster attempts to use Random Effects The spell is not implemented as a monster spell at present, which led to crashes. This is the quick fix to prevent those crashes. The XXX: teach monsters to use random effects remains outstanding. --- crawl-ref/source/mon-act.cc | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/crawl-ref/source/mon-act.cc b/crawl-ref/source/mon-act.cc index cae24ac24884..af17fffe0f09 100644 --- a/crawl-ref/source/mon-act.cc +++ b/crawl-ref/source/mon-act.cc @@ -1095,6 +1095,15 @@ static bool _handle_wand(monster& mons) if (item_type_removed(wand->base_type, wand->sub_type)) return false; + // XXX: Teach monsters to use random effects + // Digging is handled elsewhere so that sensible (wall) targets are + // chosen. + if (wand->sub_type == WAND_RANDOM_EFFECTS + || wand->sub_type == WAND_DIGGING) + { + return false; + } + bolt beem; const spell_type mzap = @@ -1116,12 +1125,6 @@ static bool _handle_wand(monster& mons) beem.damage.size = beem.damage.size * 2 / 3; break; - // XXX: Teach monsters to use this - case WAND_RANDOM_EFFECTS: - // This is handled elsewhere, so that the correct target is set. - case WAND_DIGGING: - return false; - default: break; } From 528a52db4b4d1d2edda9011ee266936a05158abf Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Sat, 20 Apr 2019 10:55:16 -0400 Subject: [PATCH 265/864] Update CREDITS.txt --- crawl-ref/CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/CREDITS.txt b/crawl-ref/CREDITS.txt index a69f224b80a2..e76071cba11e 100644 --- a/crawl-ref/CREDITS.txt +++ b/crawl-ref/CREDITS.txt @@ -105,6 +105,7 @@ Matthew Boeh Mike Boutin John Boyle + Josh Braden Daniel Mark Brownrigg Andre Bubel Trent W. Buck From 1edb078f7ae1ae39c1d83fece8bd6c14a67f4ef0 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Sat, 20 Apr 2019 12:29:32 -0500 Subject: [PATCH 266/864] Add the polymoth tile as a player tile (laurel) This fanciful monster never made it to the 0.13 release, but it had an especially nice tile: http://crawl.chaosforge.org/Polymoth Re-add the tile as a player tile option, which you can use by adding something like the following to your RC: ``` tile_player_tile = tile:mons_polymoth ``` --- crawl-ref/source/rltiles/dc-mon.txt | 1 + crawl-ref/source/rltiles/mon/player/polymoth.png | Bin 0 -> 482 bytes 2 files changed, 1 insertion(+) create mode 100644 crawl-ref/source/rltiles/mon/player/polymoth.png diff --git a/crawl-ref/source/rltiles/dc-mon.txt b/crawl-ref/source/rltiles/dc-mon.txt index bf843f9827a9..09f0dd08f034 100644 --- a/crawl-ref/source/rltiles/dc-mon.txt +++ b/crawl-ref/source/rltiles/dc-mon.txt @@ -1172,3 +1172,4 @@ old-serpent-geh MONS_OLD_SERPENT_GEH old-serpent-tar MONS_OLD_SERPENT_TAR wiglaf MONS_WIGLAF orb_guardian_fetus MONS_ORB_GUARDIAN_FETUS +polymoth MONS_POLYMOTH diff --git a/crawl-ref/source/rltiles/mon/player/polymoth.png b/crawl-ref/source/rltiles/mon/player/polymoth.png new file mode 100644 index 0000000000000000000000000000000000000000..45824904663b47cb92c7bffcb56550fc35cfc009 GIT binary patch literal 482 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy_5nU2u0R?Hgp)1BOlPRJo7yH^ z^56R~!lOEVqjILu?9Ql-Q*I{CSKPIE^X4rDhYt!1AC6(T9_4sv0mFl!i~s-sfAF*Z zDo{UTNswPKgTu2MX&_FLx4R2N2dk_Hki%Kv5n0T@z%2~Ij105pNB{-dOFVsD*&nlr z2&;3RZrhXt)Fb2R;uvCax^^<>q*etUmtM6Ty_$o+=a*WY=y`F%KQd%y-OB|ni7Oma z7cLYpaajEIh2WN^15WOxmns-S45!YW{n4glt4D;Qb=p7ojKZrkj|Xz@a(Nq3{;=Z7 zP05FD^S#|qlx@{0XWJFSdv0FD2{!2nwG)$LzAn|Q;+nj*Oqz9-#O0g`X>xPJ4kmIZ z&Qf@8{V-yVX3Jf(E2lTv*xXsO&wJyCxSFs>|HS7=eDq@3|6|VP_;&{!GA91b+?Zlv zQ^GLo+ItQ=txq;#Mh1NwzjPSx=V8Cm$6h9fyWV%AYEx%@myhV; V6Ajh=rwa@^22WQ%mvv4FO#n_Q!qfl& literal 0 HcmV?d00001 From 3a7c41be2ba71c8a4e50c1d4195b2fe1f15b986f Mon Sep 17 00:00:00 2001 From: mgdelmonte Date: Mon, 28 Jan 2019 10:52:46 -0500 Subject: [PATCH 267/864] Add more monster info to Lua Expose AC, EV, MR, and MaxHP in the CLua monster.info class. Provide an optional "full description" string from desc(). Add a function defeat_mr(spell, evoked) that returns the chance for the provided spell (from the spells module) to defeat the monster's MR. The parameter evoked indicates if the spell is fired from a wand. All of this information is provided to the player, so there are no information leaks. [Committer's note: Elaborated in the commit message, Closes #970] --- crawl-ref/source/l-moninf.cc | 124 +++++++++++++++++++++++++++++++++-- 1 file changed, 120 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/l-moninf.cc b/crawl-ref/source/l-moninf.cc index a62e3c9a2437..0545fcb60622 100644 --- a/crawl-ref/source/l-moninf.cc +++ b/crawl-ref/source/l-moninf.cc @@ -16,6 +16,11 @@ #include "spl-util.h" #include "stringutil.h" #include "transform.h" +#include "math.h" // ceil +#include "spl-zap.h" // calc_spell_power +#include "evoke.h" // wand_mp_cost +#include "god-abil.h" // pakellas_effective_hex_power +#include "describe.h" // describe_info, get_monster_db_desc #define MONINF_METATABLE "monster.info" @@ -208,6 +213,97 @@ MIRES1(res_shock, MR_RES_ELEC) */ MIRES1(res_corr, MR_RES_ACID) +/*** The monster's max HP given in its description. + * @treturn string describing the max HP (usually "about X"). + * @function max_hp + */ +static int moninf_get_max_hp(lua_State *ls) +{ + MONINF(ls, 1, mi); + lua_pushstring(ls, mi->get_max_hp_desc().c_str()); + return 1; +} + +/*** The monster's MR level, in "pips" (number of +'s shown on its description). + * Returns a value ranging from 0 to 125 (immune). + * @treturn int MR level + * @function mr + */ +static int moninf_get_mr(lua_State *ls) +{ + MONINF(ls, 1, mi); + lua_pushnumber(ls, ceil(1.0*mi->res_magic()/MR_PIP)); + return 1; +} + +/*** Your probability of defeating the monster's MR with a given spell or zap. + * Returns a value ranging from 0 (no chance) to 100 (guaranteed success). + * Returns nil if MR does not apply or the spell can't be cast. + * @tparam string spell name + * @tparam[opt] boolean true if this spell is evoked rather than cast; + * defaults to false + * @treturn int|string|nil percent chance of success (0-100); + * returns "magic immune" if monster is immune; + * returns nil if MR does not apply. + * @function defeat_mr + */ +static int moninf_get_defeat_mr(lua_State *ls) +{ + MONINF(ls, 1, mi); + spell_type spell = spell_by_name(luaL_checkstring(ls, 2), false); + bool is_evoked = lua_isboolean(ls, 3) ? lua_toboolean(ls, 3) : false; + int power = is_evoked ? + (15 + you.skill(SK_EVOCATIONS, 7) / 2) * (wand_mp_cost() + 9) / 9 : + calc_spell_power(spell, true); + spell_flags flags = get_spell_flags(spell); + bool mr_check = testbits(flags, spflag::MR_check) + && testbits(flags, spflag::dir_or_target) + && !testbits(flags, spflag::helpful); + if (power <= 0 || !mr_check) + { + lua_pushnil(ls); + return 1; + } + int mr = mi->res_magic(); + if (mr == MAG_IMMUNE) + { + lua_pushstring(ls, "magic immune"); + return 1; + } + zap_type zap = spell_to_zap(spell); + int eff_power = zap == NUM_ZAPS ? power : zap_ench_power(zap, power, false); + int adj_power = is_evoked ? pakellas_effective_hex_power(eff_power) : eff_power; + int success = hex_success_chance(mr, adj_power, 100); + lua_pushnumber(ls, success); + return 1; +} + +/*** The monster's AC value, in "pips" (number of +'s shown on its description). + * Returns a value ranging from 0 to 5 (highest). + * @treturn int AC level + * @function ac + */ +static int moninf_get_ac(lua_State *ls) +{ + MONINF(ls, 1, mi); + lua_pushnumber(ls, ceil(mi->ac/5.0)); + return 1; +} +/*** The monster's EV value, in "pips" (number of +'s shown on its description). + * Returns a value ranging from 0 to 5 (highest). + * @treturn int evasion level + * @function ev + */ +static int moninf_get_ev(lua_State *ls) +{ + MONINF(ls, 1, mi); + int value = mi->ev; + if (!value && mi->base_ev != INT_MAX) + value = mi->base_ev; + lua_pushnumber(ls, ceil(value/5.0)); + return 1; +} + /*** Get the monster's holiness. * If passed a holiness, returns a boolean test of whether the monster has the * given holiness. Otherwise returns a string describing the monster's @@ -494,16 +590,31 @@ LUAFN(moninf_get_damage_desc) } /*** A description of this monster. + * @tparam[opt] boolean set true to get the description information body + * displayed when examining the monster; if false (default) returns + * a short description. * @treturn string * @function desc */ LUAFN(moninf_get_desc) { MONINF(ls, 1, mi); - string desc; - int col; - mi->to_string(1, desc, col); - lua_pushstring(ls, desc.c_str()); + if (lua_isboolean(ls, 2) && lua_toboolean(ls, 2)) + { + // full description + describe_info inf; + bool has_stat_desc; + get_monster_db_desc(*mi, inf, has_stat_desc, false); + lua_pushstring(ls, inf.body.str().c_str()); + } + else + { + // short description + string desc; + int col; + mi->to_string(1, desc, col); + lua_pushstring(ls, desc.c_str()); + } return 1; } @@ -586,6 +697,11 @@ static const struct luaL_reg moninf_lib[] = MIREG(res_draining), MIREG(res_shock), MIREG(res_corr), + MIREG(max_hp), + MIREG(mr), + MIREG(defeat_mr), + MIREG(ac), + MIREG(ev), MIREG(x_pos), MIREG(y_pos), MIREG(pos), From 2aa1166087e44e6585b26cedf1fe81b3f3ba547f Mon Sep 17 00:00:00 2001 From: Chris Rendle-Short Date: Wed, 17 Apr 2019 20:18:04 +1000 Subject: [PATCH 268/864] Use high-res app icon on all platforms Previously the 512x512 app icon was only used on MacOS, and all other platforms used the 32x32 icon. This change is to use the 512x512 icon on all platforms. --- crawl-ref/source/tilesdl.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/crawl-ref/source/tilesdl.cc b/crawl-ref/source/tilesdl.cc index e089f03539fa..0d4175bbfbd7 100644 --- a/crawl-ref/source/tilesdl.cc +++ b/crawl-ref/source/tilesdl.cc @@ -351,11 +351,7 @@ bool TilesFramework::initialise() DATA_DIR_PATH #endif #endif -#ifdef TARGET_OS_MACOSX "dat/tiles/stone_soup_icon-512x512.png"; -#else - "dat/tiles/stone_soup_icon-32x32.png"; -#endif string title = string(CRAWL " ") + Version::Long; From 32ec7cac8f0eeab6629a97f431f111856d9ba804 Mon Sep 17 00:00:00 2001 From: Joshua Gelbard Date: Wed, 20 Mar 2019 15:33:39 -0700 Subject: [PATCH 269/864] Don't assume some identified jewellery is boring Make some autopickup-related lua code less eager to forget about potentially-useful jewellery. Old defaults for autopickup_exceptions would remove some items (e.g. ring of poison resistance) from autopickup as soon as the subtype was known, since you only ever need one. Now that it's possible to learn what an rPois ring looks like by seeing a monster wear it, that behavior occasionally leads to useful rings and amulets being left unnoticed on the ground. To prevent that, don't assume such only-need-one items are safe to ignore unless the player is actively carrying one around. --- .../dat/defaults/autopickup_exceptions.txt | 37 +++++++++++++++---- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/crawl-ref/source/dat/defaults/autopickup_exceptions.txt b/crawl-ref/source/dat/defaults/autopickup_exceptions.txt index ccec8572f96c..c4a78c3f9e7e 100644 --- a/crawl-ref/source/dat/defaults/autopickup_exceptions.txt +++ b/crawl-ref/source/dat/defaults/autopickup_exceptions.txt @@ -70,11 +70,32 @@ ae += [^n]identified.*spellbook : return it.stacks() or nil : end) -# Excluding amulets as you only need one of each. (If you know the subtype -# that means you already have one of it.). Some items may already be excluded -# as bad_item, e.g. inaccuracy. -ae += amulet of (nothing|inaccuracy|the gourmand|regeneration|harm) -ae += amulet of (rage|guardian spirit|faith|magic regeneration|the acrobat) - -# Likewise for some rings. -ae += ring of (see invisible|flight|poison resistance|resist corrosion) +# Excluding most amulets as you only need one of each. Likewise for some +# rings. Some items may already be excluded as bad_item, e.g. inaccuracy. +:add_autopickup_func(function (it, name) +: if not it.class(true) == "jewellery" then +: return +: end +: local itsubtype = it.subtype() +: if itsubtype == "amulet of faith" +: or itsubtype == "amulet of guardian spirit" +: or itsubtype == "amulet of harm" +: or itsubtype == "amulet of inaccuracy" +: or itsubtype == "amulet of magic regeneration" +: or itsubtype == "amulet of nothing" +: or itsubtype == "amulet of rage" +: or itsubtype == "amulet of regeneration" +: or itsubtype == "amulet of the acrobat" +: or itsubtype == "amulet of the gourmand" +: or itsubtype == "ring of flight" +: or itsubtype == "ring of poison resistance" +: or itsubtype == "ring of resist corrosion" +: or itsubtype == "ring of see invisible" then +: for inv in iter.invent_iterator:new(items.inventory()) do +: if inv.class(true) == "jewellery" and inv.subtype() == itsubtype then +: return false +: end +: end +: end +: return +:end) From bc55a458f40cde5eb38e4926d6c5fab185af17c1 Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 20 Apr 2019 17:19:09 -0400 Subject: [PATCH 270/864] Eliminate some spurious messaging on wizmode level change If you enter a monster's los, and then exit it off level (e.g. via &d) instantaneously, and the monster's slot is taken up by a new monster on the new level, you would be told that this new monster had moved out of view. This change causes the queue of just seen monsters to be cleared on a level change, otherwise it required a world_reacts cycle. It's hard to get this bug to happen without wizmode, but it might have been possible with serpent's lash and very specific stair placement. There's still some cases where this messaging interacts badly with 0-turn actions, e.g. serpent's lash on the same level, but there at least it prints a message about the correct monster. --- crawl-ref/source/los.cc | 2 ++ crawl-ref/source/mon-act.cc | 28 +++++++++++++++++++--------- crawl-ref/source/mon-act.h | 1 + 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/crawl-ref/source/los.cc b/crawl-ref/source/los.cc index 800e2513ba70..04bcb616c7b8 100644 --- a/crawl-ref/source/los.cc +++ b/crawl-ref/source/los.cc @@ -52,6 +52,7 @@ #include "coordit.h" #include "env.h" #include "losglobal.h" +#include "mon-act.h" // These determine what rays are cast in the precomputation, // and affect start-up time significantly. @@ -934,6 +935,7 @@ void los_terrain_changed(const coord_def& p) void los_changed() { + mons_reset_just_seen(); invalidate_los(); _handle_los_change(); } diff --git a/crawl-ref/source/mon-act.cc b/crawl-ref/source/mon-act.cc index af17fffe0f09..738df0005293 100644 --- a/crawl-ref/source/mon-act.cc +++ b/crawl-ref/source/mon-act.cc @@ -2293,24 +2293,34 @@ void mons_set_just_seen(monster *mon) just_seen_queue.push_back(mon); } +void mons_reset_just_seen() +{ + // this may be called when the pointers are not valid, so don't mess with + // seen_context. + just_seen_queue.clear(); +} + static void _display_just_seen() { // these are monsters that were marked as SC_JUST_SEEN at some point since // last time this was called. We announce any that leave all at once so // as to handle monsters that may move multiple times per world_reacts. - for (auto m : just_seen_queue) + if (in_bounds(you.pos())) { - if (!m || invalid_monster(m) || !m->alive()) - continue; - // can't use simple_monster_message here, because m is out of view. - // The monster should be visible to be in this queue. - if (in_bounds(m->pos()) && !you.see_cell(m->pos())) + for (auto m : just_seen_queue) { - mprf(MSGCH_PLAIN, "%s moves out of view.", - m->name(DESC_THE, true).c_str()); + if (!m || invalid_monster(m) || !m->alive()) + continue; + // can't use simple_monster_message here, because m is out of view. + // The monster should be visible to be in this queue. + if (in_bounds(m->pos()) && !you.see_cell(m->pos())) + { + mprf(MSGCH_PLAIN, "%s moves out of view.", + m->name(DESC_THE, true).c_str()); + } } } - just_seen_queue.clear(); + mons_reset_just_seen(); } /** diff --git a/crawl-ref/source/mon-act.h b/crawl-ref/source/mon-act.h index 88b9d0568cc6..e4a36ee71631 100644 --- a/crawl-ref/source/mon-act.h +++ b/crawl-ref/source/mon-act.h @@ -17,6 +17,7 @@ class MonsterActionQueueCompare }; void mons_set_just_seen(monster *mon); +void mons_reset_just_seen(); bool mon_can_move_to_pos(const monster* mons, const coord_def& delta, bool just_check = false); From a0fc33f7246dc8e3f7e9bd647f78399882ea6478 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 22 Apr 2019 16:24:36 -0400 Subject: [PATCH 271/864] Better separate level generation from level loading/entry These were previously completely intertwined. Before 0.23, level generation was only ever done on an attempt to enter a new level. For 0.23, level generation was a special case load mode for the call to load_level, with complicated shared setup code for the generation call. This commit pulls the relevant setup and cleanup out of load_level so that a level can be generated without needing to call load_level at all. There is a small cost in code duplication, but the comprehension cost for doing this together with level loading was much higher. --- crawl-ref/source/files.cc | 148 +++++++++++++++++++++--------------- crawl-ref/source/files.h | 2 +- crawl-ref/source/startup.cc | 33 +------- 3 files changed, 89 insertions(+), 94 deletions(-) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 0036616a4a0d..68c361ecfa30 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1232,34 +1232,6 @@ static bool _leave_level(dungeon_feature_type stair_taken, return popped; } - -/** - * Generate a new level. - * - * Cleanup the environment, build the level, and possibly place a ghost or - * handle initial AK entrance. - * - * @param stair_taken The means used to leave the last level. - * @param old_level The ID of the previous level. - */ -static void _make_level() -{ - - env.turns_on_level = -1; - - tile_init_default_flavour(); - tile_clear_flavour(); - env.tile_names.clear(); - - _clear_env_map(); - builder(true); - - env.turns_on_level = 0; - // sanctuary - env.sanctuary_pos = coord_def(-1, -1); - env.sanctuary_time = 0; -} - /** * Move the player to the appropriate entrance location in a level. * @@ -1426,6 +1398,81 @@ bool player::level_visited(const level_id &level) return visited.exists(level.describe()); } +static void _generic_level_reset() +{ + // TODO: can more be pulled into here? + + you.prev_targ = MHITNOT; + you.prev_grd_targ.reset(); + + // Lose all listeners. + dungeon_events.clear(); + clear_travel_trail(); +} + +/** + * Ensure that the level given by `l` is generated. This does not do much in + * the way of cleanup, and the caller must ensure the player ends up somewhere + * sensible afterwards (this will not place the player, and will wipe out their + * current location state if a level is built). Does not do anything if the + * save already contains the relevant level. + * + * @param l the level to try to build. + * @return whether a level was built. + */ +bool generate_level(const level_id &l) +{ + const string level_name = l.describe(); + if (you.save->has_chunk(level_name)) + return false; + + unwind_var depth(you.depth, l.depth); + unwind_var branch(you.where_are_you, l.branch); + unwind_var saved_position(you.position); + you.position.reset(); + + // simulate a reasonable stair to enter the level with + const dungeon_feature_type stair_taken = + you.depth == 1 + ? (you.where_are_you == BRANCH_DUNGEON + ? DNGN_UNSEEN + : branches[you.where_are_you].entry_stairs) + : DNGN_STONE_STAIRS_DOWN_I; + + unwind_var stair(you.transit_stair, stair_taken); + // TODO how necessary is this? + unwind_bool ylev(you.entering_level, true); + // n.b. crawl_state.generating_level is handled in builder + + _generic_level_reset(); + delete_all_clouds(); + los_changed(); // invalidate the los cache, which impacts monster placement + + // initialize env for builder + env.turns_on_level = -1; + tile_init_default_flavour(); + tile_clear_flavour(); + env.tile_names.clear(); + _clear_env_map(); + + // finally -- everything is set up, call the builder. + dprf("Generating new level for '%s'.", level_name.c_str()); + builder(true); + + you.vault_list[level_id::current()] = level_vault_names(); + + // initialize env for a new level + env.turns_on_level = 0; + env.sanctuary_pos = coord_def(-1, -1); + env.sanctuary_time = 0; + env.markers.init_all(); // init first, activation happens when entering + show_update_emphasis(); // Clear map knowledge stair emphasis in env. + + // save the level and associated env state + _save_level(level_id::current()); + return true; +} + /** * Load the current level. * @@ -1437,6 +1484,9 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, const level_id& old_level) { const string level_name = level_id::current().describe(); + if (!you.save->has_chunk(level_name) && load_mode == LOAD_VISITOR) + return false; + const bool make_changes = (load_mode == LOAD_START_GAME || load_mode == LOAD_ENTER_LEVEL); @@ -1455,7 +1505,7 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, if (feat_is_escape_hatch(stair_taken)) hatch_name = _get_hatch_name(); - if (load_mode != LOAD_VISITOR && load_mode != LOAD_GENERATE) + if (load_mode != LOAD_VISITOR) popped = _leave_level(stair_taken, old_level, &return_pos); unwind_var stair( @@ -1470,17 +1520,13 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, // Save position for hatches to place a marker on the destination level. coord_def dest_pos = you.pos(); - you.prev_targ = MHITNOT; - you.prev_grd_targ.reset(); + _generic_level_reset(); // We clear twice - on save and on load. // Once would be enough... if (make_changes) delete_all_clouds(); - // Lose all listeners. - dungeon_events.clear(); - // This block is to grab followers and save the old level to disk. if (load_mode == LOAD_ENTER_LEVEL) { @@ -1497,19 +1543,14 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, _save_level(old_level); } - // TODO: for staged pregeneration this also needs to happen on - // LOAD_GENERATE. However, it's a bit tricky, because player position - // does need to be saved for the later LOAD_ENTER_LEVEL call. postpone. // The player is now between levels. you.position.reset(); update_companions(); } - clear_travel_trail(); - #ifdef USE_TILE - if (load_mode != LOAD_VISITOR && load_mode != LOAD_GENERATE) + if (load_mode != LOAD_VISITOR) { tiles.clear_minimap(); crawl_view_buffer empty_vbuf; @@ -1517,10 +1558,7 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, } #endif - bool just_created_level = false; - - if (load_mode != LOAD_GENERATE - && load_mode != LOAD_VISITOR + if (load_mode != LOAD_VISITOR && you.chapter == CHAPTER_POCKET_ABYSS && player_in_branch(BRANCH_DUNGEON)) { @@ -1534,22 +1572,16 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, if (!you.save->has_chunk(level_name)) { ASSERT(load_mode != LOAD_VISITOR); - dprf("Generating new level for '%s'.", level_name.c_str()); - _make_level(); - you.vault_list[level_id::current()] = level_vault_names(); - just_created_level = true; + generate_level(level_id::current()); } else { dprf("Loading old level '%s'.", level_name.c_str()); _restore_tagged_chunk(you.save, level_name, TAG_LEVEL, "Level file is invalid."); - - if (load_mode != LOAD_GENERATE) - _redraw_all(); // TODO why is there a redraw call here? + _redraw_all(); // TODO why is there a redraw call here? } - if (just_created_level) - env.markers.init_all(); // init first, activation happens when entering + const bool just_created_level = !you.level_visited(level_id::current()); // Clear map knowledge stair emphasis. show_update_emphasis(); @@ -1559,16 +1591,6 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, los_changed(); - if (load_mode == LOAD_GENERATE) - { - if (just_created_level) - _save_level(level_id::current()); - return just_created_level; - } - - if (!you.level_visited(level_id::current())) - just_created_level = true; // in case level was pre-generated - if (load_mode != LOAD_VISITOR) you.set_level_visited(level_id::current()); diff --git a/crawl-ref/source/files.h b/crawl-ref/source/files.h index fbe2db6a150e..f7f184d544e0 100644 --- a/crawl-ref/source/files.h +++ b/crawl-ref/source/files.h @@ -19,7 +19,6 @@ enum load_mode_type LOAD_RESTART_GAME, // loaded savefile LOAD_ENTER_LEVEL, // entered a level normally LOAD_VISITOR, // Visitor pattern to see all levels - LOAD_GENERATE, // Generating the level only }; /// Exception indicating that a dangerous path was supplied. @@ -82,6 +81,7 @@ class level_id; void trackers_init_new_level(bool transit); +bool generate_level(const level_id &l); bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, const level_id& old_level); void delete_level(const level_id &level); diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index d856f48a7262..dbc1055f35a7 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -237,42 +237,15 @@ static void _zap_los_monsters(bool items_also) } } -/** - * Ensure that the level given by `pos` is generated. This does not do much in - * the way of cleanup, and the caller must ensure the player ends up somewhere - * sensible (this will not place the player). - */ -static bool _ensure_level_generated(const level_pos &pos) -{ - // TODO: how important is it to get stair_taken right? bel just used stone 1 - dungeon_feature_type stair_taken = - absdungeon_depth(pos.id.branch, pos.id.depth) > env.absdepth0 ? - DNGN_STONE_STAIRS_DOWN_I : DNGN_STONE_STAIRS_UP_I; - - if (pos.id.depth == brdepth[pos.id.branch]) - stair_taken = DNGN_STONE_STAIRS_DOWN_I; - - if (pos.id.depth == 1 && pos.id.branch != BRANCH_DUNGEON) - stair_taken = branches[pos.id.branch].entry_stairs; - - const level_id old_level = level_id::current(); - - you.where_are_you = static_cast(pos.id.branch); - you.depth = pos.id.depth; - - return load_level(stair_taken, LOAD_GENERATE, old_level); -} - static void _pregen_levels(const branch_type branch, progress_popup &progress) { for (int i = 1; i <= branches[branch].numlevels; i++) { level_id new_level = level_id(branch, i); - level_pos pos = level_pos(new_level); - dprf("Pregenerating %s:%d", branches[pos.id.branch].abbrevname, - pos.id.depth); + dprf("Pregenerating %s:%d", branches[new_level.branch].abbrevname, + new_level.depth); progress.advance_progress(); - _ensure_level_generated(pos); + generate_level(new_level); } } From 14115134c206528439226e57c192850df5666347 Mon Sep 17 00:00:00 2001 From: Alan Malloy Date: Wed, 24 Apr 2019 09:45:38 -0700 Subject: [PATCH 272/864] Revert "Better separate level generation from level loading/entry" (NP7) This reverts commit a0fc33f7246dc8e3f7e9bd647f78399882ea6478. It was causing serious graphical issues in Pandemonium for local tiles and webtiles builds. --- crawl-ref/source/files.cc | 148 +++++++++++++++--------------------- crawl-ref/source/files.h | 2 +- crawl-ref/source/startup.cc | 33 +++++++- 3 files changed, 94 insertions(+), 89 deletions(-) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 68c361ecfa30..0036616a4a0d 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1232,6 +1232,34 @@ static bool _leave_level(dungeon_feature_type stair_taken, return popped; } + +/** + * Generate a new level. + * + * Cleanup the environment, build the level, and possibly place a ghost or + * handle initial AK entrance. + * + * @param stair_taken The means used to leave the last level. + * @param old_level The ID of the previous level. + */ +static void _make_level() +{ + + env.turns_on_level = -1; + + tile_init_default_flavour(); + tile_clear_flavour(); + env.tile_names.clear(); + + _clear_env_map(); + builder(true); + + env.turns_on_level = 0; + // sanctuary + env.sanctuary_pos = coord_def(-1, -1); + env.sanctuary_time = 0; +} + /** * Move the player to the appropriate entrance location in a level. * @@ -1398,81 +1426,6 @@ bool player::level_visited(const level_id &level) return visited.exists(level.describe()); } -static void _generic_level_reset() -{ - // TODO: can more be pulled into here? - - you.prev_targ = MHITNOT; - you.prev_grd_targ.reset(); - - // Lose all listeners. - dungeon_events.clear(); - clear_travel_trail(); -} - -/** - * Ensure that the level given by `l` is generated. This does not do much in - * the way of cleanup, and the caller must ensure the player ends up somewhere - * sensible afterwards (this will not place the player, and will wipe out their - * current location state if a level is built). Does not do anything if the - * save already contains the relevant level. - * - * @param l the level to try to build. - * @return whether a level was built. - */ -bool generate_level(const level_id &l) -{ - const string level_name = l.describe(); - if (you.save->has_chunk(level_name)) - return false; - - unwind_var depth(you.depth, l.depth); - unwind_var branch(you.where_are_you, l.branch); - unwind_var saved_position(you.position); - you.position.reset(); - - // simulate a reasonable stair to enter the level with - const dungeon_feature_type stair_taken = - you.depth == 1 - ? (you.where_are_you == BRANCH_DUNGEON - ? DNGN_UNSEEN - : branches[you.where_are_you].entry_stairs) - : DNGN_STONE_STAIRS_DOWN_I; - - unwind_var stair(you.transit_stair, stair_taken); - // TODO how necessary is this? - unwind_bool ylev(you.entering_level, true); - // n.b. crawl_state.generating_level is handled in builder - - _generic_level_reset(); - delete_all_clouds(); - los_changed(); // invalidate the los cache, which impacts monster placement - - // initialize env for builder - env.turns_on_level = -1; - tile_init_default_flavour(); - tile_clear_flavour(); - env.tile_names.clear(); - _clear_env_map(); - - // finally -- everything is set up, call the builder. - dprf("Generating new level for '%s'.", level_name.c_str()); - builder(true); - - you.vault_list[level_id::current()] = level_vault_names(); - - // initialize env for a new level - env.turns_on_level = 0; - env.sanctuary_pos = coord_def(-1, -1); - env.sanctuary_time = 0; - env.markers.init_all(); // init first, activation happens when entering - show_update_emphasis(); // Clear map knowledge stair emphasis in env. - - // save the level and associated env state - _save_level(level_id::current()); - return true; -} - /** * Load the current level. * @@ -1484,9 +1437,6 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, const level_id& old_level) { const string level_name = level_id::current().describe(); - if (!you.save->has_chunk(level_name) && load_mode == LOAD_VISITOR) - return false; - const bool make_changes = (load_mode == LOAD_START_GAME || load_mode == LOAD_ENTER_LEVEL); @@ -1505,7 +1455,7 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, if (feat_is_escape_hatch(stair_taken)) hatch_name = _get_hatch_name(); - if (load_mode != LOAD_VISITOR) + if (load_mode != LOAD_VISITOR && load_mode != LOAD_GENERATE) popped = _leave_level(stair_taken, old_level, &return_pos); unwind_var stair( @@ -1520,13 +1470,17 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, // Save position for hatches to place a marker on the destination level. coord_def dest_pos = you.pos(); - _generic_level_reset(); + you.prev_targ = MHITNOT; + you.prev_grd_targ.reset(); // We clear twice - on save and on load. // Once would be enough... if (make_changes) delete_all_clouds(); + // Lose all listeners. + dungeon_events.clear(); + // This block is to grab followers and save the old level to disk. if (load_mode == LOAD_ENTER_LEVEL) { @@ -1543,14 +1497,19 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, _save_level(old_level); } + // TODO: for staged pregeneration this also needs to happen on + // LOAD_GENERATE. However, it's a bit tricky, because player position + // does need to be saved for the later LOAD_ENTER_LEVEL call. postpone. // The player is now between levels. you.position.reset(); update_companions(); } + clear_travel_trail(); + #ifdef USE_TILE - if (load_mode != LOAD_VISITOR) + if (load_mode != LOAD_VISITOR && load_mode != LOAD_GENERATE) { tiles.clear_minimap(); crawl_view_buffer empty_vbuf; @@ -1558,7 +1517,10 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, } #endif - if (load_mode != LOAD_VISITOR + bool just_created_level = false; + + if (load_mode != LOAD_GENERATE + && load_mode != LOAD_VISITOR && you.chapter == CHAPTER_POCKET_ABYSS && player_in_branch(BRANCH_DUNGEON)) { @@ -1572,16 +1534,22 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, if (!you.save->has_chunk(level_name)) { ASSERT(load_mode != LOAD_VISITOR); - generate_level(level_id::current()); + dprf("Generating new level for '%s'.", level_name.c_str()); + _make_level(); + you.vault_list[level_id::current()] = level_vault_names(); + just_created_level = true; } else { dprf("Loading old level '%s'.", level_name.c_str()); _restore_tagged_chunk(you.save, level_name, TAG_LEVEL, "Level file is invalid."); - _redraw_all(); // TODO why is there a redraw call here? + + if (load_mode != LOAD_GENERATE) + _redraw_all(); // TODO why is there a redraw call here? } - const bool just_created_level = !you.level_visited(level_id::current()); + if (just_created_level) + env.markers.init_all(); // init first, activation happens when entering // Clear map knowledge stair emphasis. show_update_emphasis(); @@ -1591,6 +1559,16 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, los_changed(); + if (load_mode == LOAD_GENERATE) + { + if (just_created_level) + _save_level(level_id::current()); + return just_created_level; + } + + if (!you.level_visited(level_id::current())) + just_created_level = true; // in case level was pre-generated + if (load_mode != LOAD_VISITOR) you.set_level_visited(level_id::current()); diff --git a/crawl-ref/source/files.h b/crawl-ref/source/files.h index f7f184d544e0..fbe2db6a150e 100644 --- a/crawl-ref/source/files.h +++ b/crawl-ref/source/files.h @@ -19,6 +19,7 @@ enum load_mode_type LOAD_RESTART_GAME, // loaded savefile LOAD_ENTER_LEVEL, // entered a level normally LOAD_VISITOR, // Visitor pattern to see all levels + LOAD_GENERATE, // Generating the level only }; /// Exception indicating that a dangerous path was supplied. @@ -81,7 +82,6 @@ class level_id; void trackers_init_new_level(bool transit); -bool generate_level(const level_id &l); bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, const level_id& old_level); void delete_level(const level_id &level); diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index dbc1055f35a7..d856f48a7262 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -237,15 +237,42 @@ static void _zap_los_monsters(bool items_also) } } +/** + * Ensure that the level given by `pos` is generated. This does not do much in + * the way of cleanup, and the caller must ensure the player ends up somewhere + * sensible (this will not place the player). + */ +static bool _ensure_level_generated(const level_pos &pos) +{ + // TODO: how important is it to get stair_taken right? bel just used stone 1 + dungeon_feature_type stair_taken = + absdungeon_depth(pos.id.branch, pos.id.depth) > env.absdepth0 ? + DNGN_STONE_STAIRS_DOWN_I : DNGN_STONE_STAIRS_UP_I; + + if (pos.id.depth == brdepth[pos.id.branch]) + stair_taken = DNGN_STONE_STAIRS_DOWN_I; + + if (pos.id.depth == 1 && pos.id.branch != BRANCH_DUNGEON) + stair_taken = branches[pos.id.branch].entry_stairs; + + const level_id old_level = level_id::current(); + + you.where_are_you = static_cast(pos.id.branch); + you.depth = pos.id.depth; + + return load_level(stair_taken, LOAD_GENERATE, old_level); +} + static void _pregen_levels(const branch_type branch, progress_popup &progress) { for (int i = 1; i <= branches[branch].numlevels; i++) { level_id new_level = level_id(branch, i); - dprf("Pregenerating %s:%d", branches[new_level.branch].abbrevname, - new_level.depth); + level_pos pos = level_pos(new_level); + dprf("Pregenerating %s:%d", branches[pos.id.branch].abbrevname, + pos.id.depth); progress.advance_progress(); - generate_level(new_level); + _ensure_level_generated(pos); } } From 1911a96622483b7eca18d3928b50ae19d5f82917 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 25 Apr 2019 10:48:10 -0400 Subject: [PATCH 273/864] Properly delete visited marker when a level is deleted and also clarify the semantics of level_visited. This fixes weird behavior when revisiting pan levels (it will also affect zigs, and revisiting portal vaults in wizmode) where state was not correctly initialized when entering a newly generated level, because the player had visited a level with that level_id before. If there's any games still saved in pan with the broken state, after upgrading to this they can fix with a save and reload. --- crawl-ref/source/files.cc | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 0036616a4a0d..0456d1fe5651 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1413,11 +1413,16 @@ void player::set_level_visited(const level_id &level) visited[level.describe()] = true; } +/** + * Has the player visited the level currently stored in the save under the id + * `level`, if there is one? Returns false if there isn't one. This stores + * *token level* visited state, not type-level -- it does not answer questions + * like, e.g. has the player ever visited a trove? For that, see place_info. + * This distinction matters mainly for portal branches, especially ones that can + * be revisited, e.g. Pan levels and zigs. + */ bool player::level_visited(const level_id &level) { - // this will mean that portal maps that the player is not currently on - // return false, since the map gets deleted. A continuation of legacy - // behavior... // `is_existing_level` is not reliable after the game end, because the // save no longer exists, so we ignore it for printing morgues if (!is_existing_level(level) && you.save) @@ -2620,6 +2625,10 @@ void delete_level(const level_id &level) if (you.save) you.save->delete_chunk(level.describe()); + + auto &visited = you.props[VISITED_LEVELS_KEY].get_table(); + visited.erase(level.describe()); + if (level.branch == BRANCH_ABYSS) { save_abyss_uniques(); From b3763e6d510daa0690e602736248c5ab1b2e4891 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 25 Apr 2019 10:13:11 -0400 Subject: [PATCH 274/864] Revert "Revert "Better separate level generation from level loading/entry" (NP7)" This reverts commit 14115134c206528439226e57c192850df5666347. --- crawl-ref/source/files.cc | 148 +++++++++++++++++++++--------------- crawl-ref/source/files.h | 2 +- crawl-ref/source/startup.cc | 33 +------- 3 files changed, 89 insertions(+), 94 deletions(-) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 0456d1fe5651..015c88eb5227 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1232,34 +1232,6 @@ static bool _leave_level(dungeon_feature_type stair_taken, return popped; } - -/** - * Generate a new level. - * - * Cleanup the environment, build the level, and possibly place a ghost or - * handle initial AK entrance. - * - * @param stair_taken The means used to leave the last level. - * @param old_level The ID of the previous level. - */ -static void _make_level() -{ - - env.turns_on_level = -1; - - tile_init_default_flavour(); - tile_clear_flavour(); - env.tile_names.clear(); - - _clear_env_map(); - builder(true); - - env.turns_on_level = 0; - // sanctuary - env.sanctuary_pos = coord_def(-1, -1); - env.sanctuary_time = 0; -} - /** * Move the player to the appropriate entrance location in a level. * @@ -1431,6 +1403,81 @@ bool player::level_visited(const level_id &level) return visited.exists(level.describe()); } +static void _generic_level_reset() +{ + // TODO: can more be pulled into here? + + you.prev_targ = MHITNOT; + you.prev_grd_targ.reset(); + + // Lose all listeners. + dungeon_events.clear(); + clear_travel_trail(); +} + +/** + * Ensure that the level given by `l` is generated. This does not do much in + * the way of cleanup, and the caller must ensure the player ends up somewhere + * sensible afterwards (this will not place the player, and will wipe out their + * current location state if a level is built). Does not do anything if the + * save already contains the relevant level. + * + * @param l the level to try to build. + * @return whether a level was built. + */ +bool generate_level(const level_id &l) +{ + const string level_name = l.describe(); + if (you.save->has_chunk(level_name)) + return false; + + unwind_var depth(you.depth, l.depth); + unwind_var branch(you.where_are_you, l.branch); + unwind_var saved_position(you.position); + you.position.reset(); + + // simulate a reasonable stair to enter the level with + const dungeon_feature_type stair_taken = + you.depth == 1 + ? (you.where_are_you == BRANCH_DUNGEON + ? DNGN_UNSEEN + : branches[you.where_are_you].entry_stairs) + : DNGN_STONE_STAIRS_DOWN_I; + + unwind_var stair(you.transit_stair, stair_taken); + // TODO how necessary is this? + unwind_bool ylev(you.entering_level, true); + // n.b. crawl_state.generating_level is handled in builder + + _generic_level_reset(); + delete_all_clouds(); + los_changed(); // invalidate the los cache, which impacts monster placement + + // initialize env for builder + env.turns_on_level = -1; + tile_init_default_flavour(); + tile_clear_flavour(); + env.tile_names.clear(); + _clear_env_map(); + + // finally -- everything is set up, call the builder. + dprf("Generating new level for '%s'.", level_name.c_str()); + builder(true); + + you.vault_list[level_id::current()] = level_vault_names(); + + // initialize env for a new level + env.turns_on_level = 0; + env.sanctuary_pos = coord_def(-1, -1); + env.sanctuary_time = 0; + env.markers.init_all(); // init first, activation happens when entering + show_update_emphasis(); // Clear map knowledge stair emphasis in env. + + // save the level and associated env state + _save_level(level_id::current()); + return true; +} + /** * Load the current level. * @@ -1442,6 +1489,9 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, const level_id& old_level) { const string level_name = level_id::current().describe(); + if (!you.save->has_chunk(level_name) && load_mode == LOAD_VISITOR) + return false; + const bool make_changes = (load_mode == LOAD_START_GAME || load_mode == LOAD_ENTER_LEVEL); @@ -1460,7 +1510,7 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, if (feat_is_escape_hatch(stair_taken)) hatch_name = _get_hatch_name(); - if (load_mode != LOAD_VISITOR && load_mode != LOAD_GENERATE) + if (load_mode != LOAD_VISITOR) popped = _leave_level(stair_taken, old_level, &return_pos); unwind_var stair( @@ -1475,17 +1525,13 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, // Save position for hatches to place a marker on the destination level. coord_def dest_pos = you.pos(); - you.prev_targ = MHITNOT; - you.prev_grd_targ.reset(); + _generic_level_reset(); // We clear twice - on save and on load. // Once would be enough... if (make_changes) delete_all_clouds(); - // Lose all listeners. - dungeon_events.clear(); - // This block is to grab followers and save the old level to disk. if (load_mode == LOAD_ENTER_LEVEL) { @@ -1502,19 +1548,14 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, _save_level(old_level); } - // TODO: for staged pregeneration this also needs to happen on - // LOAD_GENERATE. However, it's a bit tricky, because player position - // does need to be saved for the later LOAD_ENTER_LEVEL call. postpone. // The player is now between levels. you.position.reset(); update_companions(); } - clear_travel_trail(); - #ifdef USE_TILE - if (load_mode != LOAD_VISITOR && load_mode != LOAD_GENERATE) + if (load_mode != LOAD_VISITOR) { tiles.clear_minimap(); crawl_view_buffer empty_vbuf; @@ -1522,10 +1563,7 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, } #endif - bool just_created_level = false; - - if (load_mode != LOAD_GENERATE - && load_mode != LOAD_VISITOR + if (load_mode != LOAD_VISITOR && you.chapter == CHAPTER_POCKET_ABYSS && player_in_branch(BRANCH_DUNGEON)) { @@ -1539,22 +1577,16 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, if (!you.save->has_chunk(level_name)) { ASSERT(load_mode != LOAD_VISITOR); - dprf("Generating new level for '%s'.", level_name.c_str()); - _make_level(); - you.vault_list[level_id::current()] = level_vault_names(); - just_created_level = true; + generate_level(level_id::current()); } else { dprf("Loading old level '%s'.", level_name.c_str()); _restore_tagged_chunk(you.save, level_name, TAG_LEVEL, "Level file is invalid."); - - if (load_mode != LOAD_GENERATE) - _redraw_all(); // TODO why is there a redraw call here? + _redraw_all(); // TODO why is there a redraw call here? } - if (just_created_level) - env.markers.init_all(); // init first, activation happens when entering + const bool just_created_level = !you.level_visited(level_id::current()); // Clear map knowledge stair emphasis. show_update_emphasis(); @@ -1564,16 +1596,6 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, los_changed(); - if (load_mode == LOAD_GENERATE) - { - if (just_created_level) - _save_level(level_id::current()); - return just_created_level; - } - - if (!you.level_visited(level_id::current())) - just_created_level = true; // in case level was pre-generated - if (load_mode != LOAD_VISITOR) you.set_level_visited(level_id::current()); diff --git a/crawl-ref/source/files.h b/crawl-ref/source/files.h index fbe2db6a150e..f7f184d544e0 100644 --- a/crawl-ref/source/files.h +++ b/crawl-ref/source/files.h @@ -19,7 +19,6 @@ enum load_mode_type LOAD_RESTART_GAME, // loaded savefile LOAD_ENTER_LEVEL, // entered a level normally LOAD_VISITOR, // Visitor pattern to see all levels - LOAD_GENERATE, // Generating the level only }; /// Exception indicating that a dangerous path was supplied. @@ -82,6 +81,7 @@ class level_id; void trackers_init_new_level(bool transit); +bool generate_level(const level_id &l); bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, const level_id& old_level); void delete_level(const level_id &level); diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index d856f48a7262..dbc1055f35a7 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -237,42 +237,15 @@ static void _zap_los_monsters(bool items_also) } } -/** - * Ensure that the level given by `pos` is generated. This does not do much in - * the way of cleanup, and the caller must ensure the player ends up somewhere - * sensible (this will not place the player). - */ -static bool _ensure_level_generated(const level_pos &pos) -{ - // TODO: how important is it to get stair_taken right? bel just used stone 1 - dungeon_feature_type stair_taken = - absdungeon_depth(pos.id.branch, pos.id.depth) > env.absdepth0 ? - DNGN_STONE_STAIRS_DOWN_I : DNGN_STONE_STAIRS_UP_I; - - if (pos.id.depth == brdepth[pos.id.branch]) - stair_taken = DNGN_STONE_STAIRS_DOWN_I; - - if (pos.id.depth == 1 && pos.id.branch != BRANCH_DUNGEON) - stair_taken = branches[pos.id.branch].entry_stairs; - - const level_id old_level = level_id::current(); - - you.where_are_you = static_cast(pos.id.branch); - you.depth = pos.id.depth; - - return load_level(stair_taken, LOAD_GENERATE, old_level); -} - static void _pregen_levels(const branch_type branch, progress_popup &progress) { for (int i = 1; i <= branches[branch].numlevels; i++) { level_id new_level = level_id(branch, i); - level_pos pos = level_pos(new_level); - dprf("Pregenerating %s:%d", branches[pos.id.branch].abbrevname, - pos.id.depth); + dprf("Pregenerating %s:%d", branches[new_level.branch].abbrevname, + new_level.depth); progress.advance_progress(); - _ensure_level_generated(pos); + generate_level(new_level); } } From 6f7e2cb4ba9b7c7c7a69414ee38a02e2b3a7e36b Mon Sep 17 00:00:00 2001 From: advil Date: Fri, 26 Apr 2019 17:50:56 -0400 Subject: [PATCH 275/864] Fix signed casts causing build-specific behavior in random names Random letter choices in make_name were casting a pseudo-random unsigned 32bit integer to int and then modding it with something of type size_t, which will usually implicitly cast it back to size_t (which is unsigned and may vary across platforms; the cast is triggered because it typically is bigger than the int type so has a higher rank). If the int value ended up as negative in the first cast, the implicit cast to size_t was coming out differently on different platforms, leading to different random names (basically depending on whether it was a 32bit or 64bit build). This change maintains unsignedness throughout for more stable behavior. Because random naming uses its own rng objects, the effect of this was partitioned off from anything else in levelgen, leading to identical properties on randarts with different names across platforms in gotm 2 (since windows is a 32bit build). --- crawl-ref/source/item-name.cc | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/crawl-ref/source/item-name.cc b/crawl-ref/source/item-name.cc index 54785cee443c..7e3246598954 100644 --- a/crawl-ref/source/item-name.cc +++ b/crawl-ref/source/item-name.cc @@ -61,9 +61,9 @@ #include "viewgeom.h" static bool _is_consonant(char let); -static char _random_vowel(int seed); -static char _random_cons(int seed); -static string _random_consonant_set(int seed); +static char _random_vowel(uint32_t seed); +static char _random_cons(uint32_t seed); +static string _random_consonant_set(size_t seed); static void _maybe_identify_pack_item() { @@ -2764,7 +2764,6 @@ string make_name(uint32_t seed, makename_type name_type) : '\0'; const char penult_char = name.length() > 1 ? name[name.length() - 2] : '\0'; - if (name.empty() && name_type == MNAME_JIYVA) { // Start the name with a predefined letter. @@ -2921,7 +2920,7 @@ static bool _is_consonant(char let) // Returns a random vowel (a, e, i, o, u with equal probability) or space // or 'y' with lower chances. -static char _random_vowel(int seed) +static char _random_vowel(uint32_t seed) { static const char vowels[] = "aeiouaeiouaeiouy "; return vowels[ seed % (sizeof(vowels) - 1) ]; @@ -2929,7 +2928,7 @@ static char _random_vowel(int seed) // Returns a random consonant with not quite equal probability. // Does not include 'y'. -static char _random_cons(int seed) +static char _random_cons(uint32_t seed) { static const char consonants[] = "bcdfghjklmnpqrstvwxzcdfghlmnrstlmnrst"; return consonants[ seed % (sizeof(consonants) - 1) ]; @@ -2944,7 +2943,7 @@ static char _random_cons(int seed) * @return A random length 2 or 3 consonant set; e.g. "kl", "str", etc. * If the seed is out of bounds, return ""; */ -static string _random_consonant_set(int seed) +static string _random_consonant_set(size_t seed) { // Pick a random combination of consonants from the set below. // begin -> [RCS_BB, RCS_EB) = [ 0, 27) @@ -2974,7 +2973,7 @@ static string _random_consonant_set(int seed) }; COMPILE_CHECK(ARRAYSZ(consonant_sets) == RCS_END); - ASSERT_RANGE(seed, 0, (int) ARRAYSZ(consonant_sets)); + ASSERT_RANGE(seed, 0, ARRAYSZ(consonant_sets)); return consonant_sets[seed]; } From 8fb62dade4fc5bb419a7edb615f064fa98741a06 Mon Sep 17 00:00:00 2001 From: CanOfWorms Date: Sun, 28 Apr 2019 02:17:55 -0400 Subject: [PATCH 276/864] Remove a vault with an obsolete gimmick The design of this vault forces players to dig through walls to obtain loot, revealing an oklob hidden behind an opaque diggable wall. On top of encouraging spoilers, the change to wand targeting allows players to safely dig the walls without revealing the oklob, neutering the gimmick. The idea still exists in other vaults, e.g. minmay_lair_oklob_items, so there's no need to keep it around. --- crawl-ref/source/dat/des/variable/mini_monsters.des | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/crawl-ref/source/dat/des/variable/mini_monsters.des b/crawl-ref/source/dat/des/variable/mini_monsters.des index 8c14fb673533..a4fb8239390b 100644 --- a/crawl-ref/source/dat/des/variable/mini_monsters.des +++ b/crawl-ref/source/dat/des/variable/mini_monsters.des @@ -2831,15 +2831,14 @@ ENDMAP NAME: evilmike_surprise_oklob DEPTH: D:9-, Elf WEIGHT: 5 -KMASK: x = no_wall_fixup KMONS: 1 = oklob plant KITEM: 1 = star_item / nothing KITEM: | = gold, superb_item MAP -ccccccccccc -c1x|mmm...c -ccccccccc.c -ccccccccc@c +cccccccccc +c1m|mmm..c +cccccccc.c +cccccccc@c ENDMAP NAME: hangedman_tree_tricks From 67e63018d513bfb0a6566cfedfd7d9ccd78704fb Mon Sep 17 00:00:00 2001 From: CanOfWorms Date: Sun, 28 Apr 2019 02:19:05 -0400 Subject: [PATCH 277/864] Actually remove evilmike_surprise_oklob --- crawl-ref/source/dat/des/variable/mini_monsters.des | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/crawl-ref/source/dat/des/variable/mini_monsters.des b/crawl-ref/source/dat/des/variable/mini_monsters.des index a4fb8239390b..078c9f17ad6f 100644 --- a/crawl-ref/source/dat/des/variable/mini_monsters.des +++ b/crawl-ref/source/dat/des/variable/mini_monsters.des @@ -2828,19 +2828,6 @@ c.....c.....c.....c cccbcccc.@.ccccbccc ENDMAP -NAME: evilmike_surprise_oklob -DEPTH: D:9-, Elf -WEIGHT: 5 -KMONS: 1 = oklob plant -KITEM: 1 = star_item / nothing -KITEM: | = gold, superb_item -MAP -cccccccccc -c1m|mmm..c -cccccccc.c -cccccccc@c -ENDMAP - NAME: hangedman_tree_tricks DEPTH: D:8-, !D:$ TAGS: extra no_monster_gen From 81e821ac9a17bb13222c650325908cecbf9d54ce Mon Sep 17 00:00:00 2001 From: Michael Nowack <288042+syranez@users.noreply.github.com> Date: Sun, 28 Apr 2019 10:19:15 +0200 Subject: [PATCH 278/864] There are two tournaments per year. Actually, after each release a tournament will be held, but I do not think, it is relevant at this point. --- crawl-ref/docs/crawl_manual.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/docs/crawl_manual.rst b/crawl-ref/docs/crawl_manual.rst index 7cace7ddf148..b6de5a510cad 100644 --- a/crawl-ref/docs/crawl_manual.rst +++ b/crawl-ref/docs/crawl_manual.rst @@ -41,7 +41,7 @@ You can: - view your past games or those of others - battle ghosts of other players - compete using a common score list -- take part in the annual tournament +- take part in the semiannual tournament - play the most recent development version A full list of available servers and information on how to connect to them can From efa197325e125485735b90038dfc24e201bb3f60 Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Tue, 23 Apr 2019 19:53:11 +0100 Subject: [PATCH 279/864] Add bolt range behaviour to bolt spell descriptions Add a one-line description of how bolt spells' range is reduced by one for each monster the bolt strikes, to all relevant bolt and bolt-like spells and abilities. Until now, this information wasn't documented anywhere. The description is: "The range of the [bolt/blast/jet/ball] is decreased by one for every creature it strikes." The spells whose descriptions are changed by this commit are: Breathe Dispelling Energy Breathe Frost Breathe Steam Breathe Noxious Fumes Bolt of Cold Bolt of Draining Bolt of Fire Bolt of Magma Chilling Breath Cold Breath Corrosive Bolt Crystal Bolt Energy Bolt Fire Breath Metal Splinters Quicksilver Bolt Steam Ball Venom Bolt. The bolt-like spells and abilities whose descriptions are not affected by this commit are: Breathe Fire (I'm not actually sure what uses this ability, apart from red draconian players, for whom the ability is different anyway.) Random Bolt Shadow Bolt (used for Dithmenos worshippers). The five lightning-type bolt spells' ranges are not affected in this way and hence not changed. They are: Breathe Lightnng Blinkbolt Electrical Bolt Lightning Bolt Shock. --- crawl-ref/source/dat/descript/ability.txt | 9 ++++-- crawl-ref/source/dat/descript/spells.txt | 37 +++++++++++++++-------- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/crawl-ref/source/dat/descript/ability.txt b/crawl-ref/source/dat/descript/ability.txt index ebe3078270d0..98d4491300b8 100644 --- a/crawl-ref/source/dat/descript/ability.txt +++ b/crawl-ref/source/dat/descript/ability.txt @@ -14,7 +14,8 @@ Randomly translocates the user a short distance. Breathe Dispelling Energy ability Breathes a bolt of dispelling energy at a targeted creature, possibly removing -some of its enchantments. +some of its enchantments. The range of the bolt is decreased by one for every +creature it strikes. %%%% Breathe Fire ability @@ -51,11 +52,13 @@ for a short time. It may also splash onto other nearby creatures on impact. Breathe Steam ability Breathes a jet of steam at a targeted location, which will scald any creatures -it hits and will also obscure vision. +it hits and will also obscure vision. The range of the jet is decreased by one +for every creature it strikes. %%%% Breathe Noxious Fumes ability -Breathes a blast of noxious fumes at a targeted creature. +Breathes a blast of noxious fumes at a targeted creature. The range of the blast +is decreased by one for every creature it strikes. %%%% Bat Form ability diff --git a/crawl-ref/source/dat/descript/spells.txt b/crawl-ref/source/dat/descript/spells.txt index 93c46fb45550..81ccc7696425 100644 --- a/crawl-ref/source/dat/descript/spells.txt +++ b/crawl-ref/source/dat/descript/spells.txt @@ -176,21 +176,25 @@ the bolt's destination. %%%% Bolt of Cold spell -Fires a penetrating bolt of frost. +Fires a penetrating bolt of frost. The range of the bolt is decreased by one for +every creature it strikes. %%%% Bolt of Draining spell Fires a penetrating bolt of negative energy, which drains any living creature -it strikes. +it strikes. The range of the bolt is decreased by one for every creature it +hits. %%%% Bolt of Fire spell -Fires a penetrating bolt of flames. +Fires a penetrating bolt of flames. The range of the bolt is decreased by one +for every creature it strikes. %%%% Bolt of Magma spell Fires a penetrating bolt of molten rock. A portion of its damage bypasses -fire resistance. +fire resistance. The range of the bolt is decreased by one for every creature +it strikes. %%%% Borgnjor's Revivification spell @@ -270,7 +274,8 @@ Exhales a large cloud of fumes filled with the very essence of chaos. %%%% Chilling Breath spell -Exhales a blast of frost that may knock back airborne targets. +Exhales a blast of frost that may knock back airborne targets. The range of the +blast is decreased by one for every creature it strikes. %%%% Cleansing Flame spell @@ -287,6 +292,7 @@ become available. Cold Breath spell Exhales a focused blast of icy-cold air. It may knock back airborne targets. +The range of the blast is decreased by one for every creature it strikes. %%%% Confuse spell @@ -338,7 +344,8 @@ force of any creature it envelops. %%%% Corrosive Bolt spell -Fires a penetrating bolt of acid. +Fires a penetrating bolt of acid. The range of the bolt is decreased by one for +every creature it strikes. %%%% Corrupting Pulse spell @@ -350,7 +357,8 @@ Crystal Bolt spell Projects a penetrating projectile with peculiar magical properties. It is randomly imbued with either fire or ice, and additionally will reflect from -walls of any material due to the crystal embedded in the shot. +walls of any material due to the crystal embedded in the shot. The range of the +bolt is decreased by one for every creature it strikes. %%%% Darkness spell @@ -509,7 +517,8 @@ Throws a bolt of electricity at the target, with high accuracy. %%%% Energy Bolt spell -Fires a bolt of highly destructive energy. +Fires a bolt of highly destructive energy. The range of the bolt is decreased +by one for every creature it strikes. %%%% Enslavement spell @@ -541,7 +550,8 @@ ineffective against unnatural targets. %%%% Fire Breath spell -Breathes a blast of fire at a targeted creature. +Breathes a blast of fire at a targeted creature. The range of the blast is +decreased by one for every creature it strikes. %%%% Fire Storm spell @@ -882,7 +892,8 @@ shorter time. Metal Splinters spell Fires a directed stream of sharp metal splinters. Its damage is strongly -reduced by armour. +reduced by armour. The range of the stream is decreased by one for every +creature it strikes. %%%% Miasma Breath spell @@ -1280,7 +1291,8 @@ While transformed, any equipped body armour, gloves and boots are melded. %%%% Steam Ball spell -Throws a ball of hot steam towards a targeted creature. +Throws a ball of hot steam towards a targeted creature. The range of the ball +is decreased by one for every creature it strikes. %%%% Sticks to Snakes spell @@ -1557,7 +1569,8 @@ Life will not be drained in excess of what the caster can capably absorb. %%%% Venom Bolt spell -Fires a penetrating bolt of poison. +Fires a penetrating bolt of poison. The range of the bolt is decreased by one +for every creature it strikes. %%%% Virulence spell From a7546fe6749085ee4687ac0d76dda3353e1953fd Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 30 Apr 2019 08:37:06 -0400 Subject: [PATCH 280/864] Replace some lingering instances of piercer Piercer was merged into storm bow in 3ca0c319c68e. --- crawl-ref/source/dat/des/branches/vaults_rooms_hard.des | 8 ++++---- crawl-ref/source/dat/des/sprint/zigsprint.des | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crawl-ref/source/dat/des/branches/vaults_rooms_hard.des b/crawl-ref/source/dat/des/branches/vaults_rooms_hard.des index 1ba12adabe5a..5d914855b019 100644 --- a/crawl-ref/source/dat/des/branches/vaults_rooms_hard.des +++ b/crawl-ref/source/dat/des/branches/vaults_rooms_hard.des @@ -1304,14 +1304,14 @@ ENDMAP NAME: minmay_guarded_unrand_secular_launcher TAGS: vaults_hard vaults_orient_s WEIGHT: 3 -: if you.unrands("sniper") and you.unrands("piercer") then +: if you.unrands("sniper") and you.unrands("storm_bow") then ITEM: triple crossbow randart no_pickup / longbow randart no_pickup : elseif you.unrands("sniper") then -ITEM: piercer no_pickup -: elseif you.unrands("piercer") then +ITEM: storm_bow no_pickup +: elseif you.unrands("storm_bow") then ITEM: sniper no_pickup : else -ITEM: piercer no_pickup / sniper no_pickup +ITEM: storm_bow no_pickup / sniper no_pickup : end NSUBST: 3:9 / 6=9. / ., 8 = 2:8 / 6=8.. / . MAP diff --git a/crawl-ref/source/dat/des/sprint/zigsprint.des b/crawl-ref/source/dat/des/sprint/zigsprint.des index 4875197f5856..c949a5dea558 100644 --- a/crawl-ref/source/dat/des/sprint/zigsprint.des +++ b/crawl-ref/source/dat/des/sprint/zigsprint.des @@ -796,7 +796,7 @@ KITEM: R = obsidian_axe ident:all, \ dark_maul ident:all, \ sniper ident:all, \ majin-bo ident:all -KITEM: T = piercer ident:all, \ +KITEM: T = storm_bow ident:all, \ singing_sword ident:all, \ mace_of_variability ident:all, \ sword_of_power ident:all, \ From 7cec4da7ba2ce9a08520bf6c973333f464b2604b Mon Sep 17 00:00:00 2001 From: Alex Jurkiewicz Date: Wed, 1 May 2019 14:16:18 +1000 Subject: [PATCH 281/864] Improve create_enum docs (#1052) --- crawl-ref/docs/develop/species_creation.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crawl-ref/docs/develop/species_creation.md b/crawl-ref/docs/develop/species_creation.md index 32db6ca7b98a..8f0c88f093b5 100644 --- a/crawl-ref/docs/develop/species_creation.md +++ b/crawl-ref/docs/develop/species_creation.md @@ -12,8 +12,8 @@ You can view existing files to get a sense of the format, it's quite straightfor | key | type | required | description | | ---- | ---- | -------- | ----------- | -| enum | `string` | **Yes** | Set the species enum. Must match the pattern `SP_[A-Z]+`. | -| monster | `string` | **Yes** | Species' corresponding monster. Must match the pattern `MONS_[A-Z]+`. | +| enum | `string` | **Yes** | Set the species enum. Must match the pattern `SP_[A-Z_]+`. | +| monster | `string` | **Yes** | Species' corresponding monster. Must match the pattern `MONS_[A-Z_]+`. | | name | `string` | **Yes** | Species name, like 'Deep Dwarf' or 'Felid'. Required. Must be unique. | | short_name | `string` | No | Two letter species code. Must be unique (excepting special cases like Draconian sub-species). Defaults to the first two letters of the name. | | adjective | `string` | No | Species adjective, like 'Dwarven' or 'Feline'. Defaults to `$name`. | @@ -44,4 +44,4 @@ You probably don't need or want to use these. | key | type | required | description | | ---- | ---- | -------- | ----------- | | TAG_MAJOR_VERSION | `int` | No | Wrap the species in `#if TAG_MAJOR_VERSION == [...]` to deprecate it. See existing deprecated species for examples. | -| create_enum | `boolean` | No | Set `true` if the species already has an enum in species-type.h. Any new species should not set this (and will fail to compile if you try). Defaults to `false`. | +| create_enum | `boolean` | No | Set `false` if the species has a hardcoded enum in species-type.h. New species should use the default value. Defaults to `true`. | From 7ba0370b94342d010afd1f546c88852bde17b0e0 Mon Sep 17 00:00:00 2001 From: floraline Date: Sun, 14 Apr 2019 00:14:17 -0400 Subject: [PATCH 282/864] Log IPs correctly when behind a reverse proxy This change allows webtiles to accurately log IP addresses when it is running behind a reverse proxy. Webtiles logs IP addresses when users connect to the server. This is done by looking at the value of 'request.remote_ip', provided by Tornado. When webtiles is running behind a reverse proxy, the value returned by Tornado is the IP address of the proxy itself. This does not uniquely identify users and results in a mostly useless log file. This commit looks for the new setting 'http_xheaders' in config.py and, if it is found, passes it along to Tornado.HTTPServer. When HTTPServer is initialized with this setting, request.remote_ip will instead return the value of header X-Real-IP if it is present. This header can be set by a reverse proxy to indicate the actual IP of the real client. Be warned that enabling this option when webtiles is NOT protected behind a reverse proxy introduces a security risk. An attacker could inject a false address into the X-Real-IP header. Do not enable this option if the webtiles server is directly exposed to users. --- crawl-ref/source/webserver/config.py | 4 ++++ crawl-ref/source/webserver/server.py | 2 ++ 2 files changed, 6 insertions(+) diff --git a/crawl-ref/source/webserver/config.py b/crawl-ref/source/webserver/config.py index 0b68afc15d27..9e751e321cc2 100644 --- a/crawl-ref/source/webserver/config.py +++ b/crawl-ref/source/webserver/config.py @@ -153,6 +153,10 @@ # This needs a patch currently not in mainline tornado. http_connection_timeout = None +# Set this to true if you are behind a reverse proxy +# Your proxy must set header X-Real-IP +http_xheaders = None + kill_timeout = 10 # Seconds until crawl is killed after HUP is sent nick_regex = r"^[a-zA-Z0-9]{3,20}$" diff --git a/crawl-ref/source/webserver/server.py b/crawl-ref/source/webserver/server.py index f741aedbd0f5..9f9a5d96468a 100755 --- a/crawl-ref/source/webserver/server.py +++ b/crawl-ref/source/webserver/server.py @@ -136,6 +136,8 @@ def bind_server(): kwargs = {} if http_connection_timeout is not None: kwargs["connection_timeout"] = http_connection_timeout + if getattr(config, "http_xheaders", False): + kwargs["xheaders"] = http_xheaders servers = [] From 9fb9971df1517b0ecf62634a8e3256654599688e Mon Sep 17 00:00:00 2001 From: Edgar Bering Date: Fri, 3 May 2019 16:27:16 -0400 Subject: [PATCH 283/864] Add a security warning to the comments (CanOfWorms) --- crawl-ref/source/webserver/config.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crawl-ref/source/webserver/config.py b/crawl-ref/source/webserver/config.py index 9e751e321cc2..c89d33b536a9 100644 --- a/crawl-ref/source/webserver/config.py +++ b/crawl-ref/source/webserver/config.py @@ -155,6 +155,11 @@ # Set this to true if you are behind a reverse proxy # Your proxy must set header X-Real-IP +# +# Enabling this option when webtiles is NOT protected behind a reverse proxy +# introduces a security risk. An attacker could inject a false address into the +# X-Real-IP header. Do not enable this option if the webtiles server is +# directly exposed to users. http_xheaders = None kill_timeout = 10 # Seconds until crawl is killed after HUP is sent From 3c078ff0d031dc40b5608ea315f4236516c3840c Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 6 May 2019 22:20:20 -0400 Subject: [PATCH 284/864] Fix sprint inheriting seed from persistent options After regular game end, sprints were accidentally picking up the seed from the previous game. This commit still allows their seed to be set explicitly from an rc file, but otherwise causes them to ignore the seed UI. Also affects hints mode and tutorial, and will show an rc-set seed in the menus for sprint ant tutorial. --- crawl-ref/source/newgame.cc | 3 +++ crawl-ref/source/ng-setup.cc | 18 +++++++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index e10767cd2a33..268e9b9a484b 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -2337,6 +2337,9 @@ static void _prompt_gamemode_map(newgame_def& ng, newgame_def& ng_choice, formatted_string welcome; welcome.textcolour(BROWN); welcome.cprintf("%s\n", _welcome(ng).c_str()); + if (Options.seed_from_rc) + welcome.cprintf("Custom seed: %" PRIu64 "\n", Options.seed_from_rc); + welcome.textcolour(CYAN); welcome.cprintf("\nYou have a choice of %s:\n\n", ng_choice.type == GAME_TYPE_TUTORIAL ? "lessons" : "maps"); diff --git a/crawl-ref/source/ng-setup.cc b/crawl-ref/source/ng-setup.cc index 7b692db5dd12..1bc67d544f85 100644 --- a/crawl-ref/source/ng-setup.cc +++ b/crawl-ref/source/ng-setup.cc @@ -378,17 +378,25 @@ static void _setup_generic(const newgame_def& ng); // Initialise a game based on the choice stored in ng. void setup_game(const newgame_def& ng) { - if (Options.seed_from_rc && ng.type == GAME_TYPE_NORMAL) + crawl_state.type = ng.type; // by default + if (Options.seed_from_rc && ng.type != GAME_TYPE_CUSTOM_SEED) { + // rc seed overrides seed from other sources, and forces a normal game + // to be a custom seed game. There is currently no special designation + // for sprint etc. games that involve a custom seed. + // TODO: does this make any sense for hints mode? Options.seed = Options.seed_from_rc; - crawl_state.type = GAME_TYPE_CUSTOM_SEED; + if (ng.type == GAME_TYPE_NORMAL) + crawl_state.type = GAME_TYPE_CUSTOM_SEED; } - else if (Options.seed && ng.type == GAME_TYPE_NORMAL) + else if (Options.seed && ng.type != GAME_TYPE_CUSTOM_SEED) + { + // there's a seed lingering in the options, but we shouldn't use it. Options.seed = 0; + } else if (!Options.seed && ng.type == GAME_TYPE_CUSTOM_SEED) crawl_state.type = GAME_TYPE_NORMAL; - else - crawl_state.type = ng.type; + crawl_state.map = ng.map; switch (crawl_state.type) From 9f7f2584eba5c2cff43ed8bf11ac122e83f2548e Mon Sep 17 00:00:00 2001 From: nlavsky <3328424+nlavsky@users.noreply.github.com> Date: Tue, 7 May 2019 20:28:49 +0300 Subject: [PATCH 285/864] Remove some traces of the tome of Destruction (#1053) --- crawl-ref/source/dat/database/pl/miscname.txt | 5 ----- crawl-ref/source/dat/dlua/lm_trove.lua | 3 +-- crawl-ref/source/item-use.cc | 3 +-- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/crawl-ref/source/dat/database/pl/miscname.txt b/crawl-ref/source/dat/database/pl/miscname.txt index 8f33be579950..d9eb14a01f77 100644 --- a/crawl-ref/source/dat/database/pl/miscname.txt +++ b/crawl-ref/source/dat/database/pl/miscname.txt @@ -8,13 +8,8 @@ %%%% # "dust glows XXX", "eyes glow XXX", "hands glow XXX", " glows XXX". # If a language needs these keys split, please say so. -# -# Also used by Tome of Destruction below. #glowing_colour_name %%%% -# Tome of Destruction: "The book opens to a page covered in XXX." -#writing_name -%%%% # random uselessness: "You smell XXX." #smell_name %%%% diff --git a/crawl-ref/source/dat/dlua/lm_trove.lua b/crawl-ref/source/dat/dlua/lm_trove.lua index 9b06550bbb0d..b85ad3624b33 100644 --- a/crawl-ref/source/dat/dlua/lm_trove.lua +++ b/crawl-ref/source/dat/dlua/lm_trove.lua @@ -342,8 +342,7 @@ function TroveMarker:item_name(do_grammar) s = s .. " " .. item.base_type .. " of" end elseif item.base_type == "book" then - books = {"Necronomicon", "tome of Destruction", - "Young Poisoner's Handbook", "Grand Grimoire"} + books = {"Necronomicon", "Young Poisoner's Handbook", "Grand Grimoire"} if util.contains(books, item.sub_type) then if do_grammar == false then return item.sub_type diff --git a/crawl-ref/source/item-use.cc b/crawl-ref/source/item-use.cc index 7c62bb84bad0..f4148325ea8d 100644 --- a/crawl-ref/source/item-use.cc +++ b/crawl-ref/source/item-use.cc @@ -2780,8 +2780,7 @@ static bool _scroll_will_harm(const scroll_type scr, const actor &m) /** * Check to see if the player can read the item in the given slot, and if so, - * reads it. (Examining books, evoking the tome of destruction, & using - * scrolls.) + * reads it. (Examining books and using scrolls.) * * @param slot The slot of the item in the player's inventory. If -1, the * player is prompted to choose a slot. From 312109b4ccb1feffa3c220cb0c519646239a0ae8 Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Tue, 7 May 2019 17:52:45 +0100 Subject: [PATCH 286/864] Don't let Pikel slaves drop corpses or items Remove their animal skins and increase their base AC instead, and prevent them from dropping corpses. --- crawl-ref/source/mon-data.h | 2 +- crawl-ref/source/mon-death.cc | 3 ++- crawl-ref/source/mon-gear.cc | 1 - 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h index 2882a1155d9d..930f81bd631d 100644 --- a/crawl-ref/source/mon-data.h +++ b/crawl-ref/source/mon-data.h @@ -1781,7 +1781,7 @@ DUMMY(MONS_GIANT_LIZARD, 'l', LIGHTGREY, "giant lizard", TILEP_MONS_LEOPARD_GECK 10, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, 20, { {AT_HIT, AF_PLAIN, 10}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, 5, 275, - 2, 12, MST_NO_SPELLS, CE_CLEAN, S_SHOUT, + 4, 12, MST_NO_SPELLS, CE_CLEAN, S_SHOUT, I_HUMAN, HT_LAND, 10, DEFAULT_ENERGY, MONUSE_STARTING_EQUIPMENT, SIZE_MEDIUM, MON_SHAPE_HUMANOID, {TILEP_MONS_SLAVE}, TILE_ERROR diff --git a/crawl-ref/source/mon-death.cc b/crawl-ref/source/mon-death.cc index de1f1d76e33b..5005d2f3e526 100644 --- a/crawl-ref/source/mon-death.cc +++ b/crawl-ref/source/mon-death.cc @@ -529,7 +529,8 @@ static void _maybe_drop_monster_hide(const item_def &corpse, bool silent) item_def* place_monster_corpse(const monster& mons, bool silent, bool force) { if (mons.is_summoned() - || mons.flags & (MF_BANISHED | MF_HARD_RESET)) + || mons.flags & (MF_BANISHED | MF_HARD_RESET) + || mons.props.exists("pikel_band")) { return nullptr; } diff --git a/crawl-ref/source/mon-gear.cc b/crawl-ref/source/mon-gear.cc index 356c2847f74a..2369a7360b27 100644 --- a/crawl-ref/source/mon-gear.cc +++ b/crawl-ref/source/mon-gear.cc @@ -1804,7 +1804,6 @@ int make_mons_armour(monster_type type, int level) 2, ARM_CHAIN_MAIL); break; - case MONS_SLAVE: case MONS_GRUM: case MONS_SPRIGGAN_BERSERKER: item.base_type = OBJ_ARMOUR; From 2392399e09372588ea7f561fa987e8e0b1c07d3c Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Tue, 7 May 2019 18:19:05 +0100 Subject: [PATCH 287/864] Remove an unused monster flag M_ALWAYS_CORPSE was obsoleted with the removal of putrid demonspawn. --- crawl-ref/source/mon-death.cc | 11 +++-------- crawl-ref/source/mon-flags.h | 3 +-- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/crawl-ref/source/mon-death.cc b/crawl-ref/source/mon-death.cc index 5005d2f3e526..baf3fb1191fd 100644 --- a/crawl-ref/source/mon-death.cc +++ b/crawl-ref/source/mon-death.cc @@ -542,14 +542,9 @@ item_def* place_monster_corpse(const monster& mons, bool silent, bool force) && mons_gives_xp(mons, you) && !force; - const bool no_coinflip = - mons.props.exists("always_corpse") - || force - || goldify - || mons_class_flag(mons.type, M_ALWAYS_CORPSE) - || mons_is_demonspawn(mons.type) - && mons_class_flag(draco_or_demonspawn_subspecies(mons), - M_ALWAYS_CORPSE); + const bool no_coinflip = mons.props.exists("always_corpse") + || force + || goldify; // 50/50 chance of getting a corpse, usually. if (!no_coinflip && coinflip()) diff --git a/crawl-ref/source/mon-flags.h b/crawl-ref/source/mon-flags.h index 2e8bc14950b0..847f7b2261c2 100644 --- a/crawl-ref/source/mon-flags.h +++ b/crawl-ref/source/mon-flags.h @@ -113,8 +113,7 @@ enum monclass_flag_type : uint64_t /// An ancestor granted by Hepliaklqana M_ANCESTOR = BIT(35), - /// always leaves a corpse - M_ALWAYS_CORPSE = BIT(36), + //BIT(36), // was M_ALWAYS_CORPSE /// mostly doesn't try to melee M_DONT_MELEE = BIT(37), From 80dedec6f2b0d8c9494a2edf7dde17637a1cdb72 Mon Sep 17 00:00:00 2001 From: Michael Nowack <288042+syranez@users.noreply.github.com> Date: Tue, 7 May 2019 19:42:50 +0200 Subject: [PATCH 288/864] Update wand information in manual (#1050) * Wands have an other behavior since the wand merge I have used texts from https://crawl.develz.org/trunk/changes.txt * Integrated feedback 1. Lines should not be longer than 80 characters. 2. grammar mistake fixed. 3. use Australian English spelling. --- crawl-ref/docs/crawl_manual.rst | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/crawl-ref/docs/crawl_manual.rst b/crawl-ref/docs/crawl_manual.rst index b6de5a510cad..43e51d958247 100644 --- a/crawl-ref/docs/crawl_manual.rst +++ b/crawl-ref/docs/crawl_manual.rst @@ -883,12 +883,11 @@ the 'q' command. ======================================== Sometimes you will be lucky enough to find a stick which contains stored magical -energies. Wands each have a certain amount of charges, and a wand will cease to -function when its charges run out. You must identify a wand to find out how many -uses it has left. This can be done with a scroll of identify; characters with a -good Evocations skill may also deduce the number of charges simply upon evoking -the wand. Evoking a wand without having fully identified the number of charges -remaining will waste some charges. +energies. Wands each have a certain number of charges, which you immediately +recognise when you pick them up. When you pick up a wand of type you already +have in inventory, the charges from the new wand are merged into the existing +one, and the new wand no longer exists. Beware that when the last charge of a +wand is used, the wand is destroyed. Wands are aimed in the same way as missile weapons, and you can release the power of a wand by evoking it with 'V'. See section I for targeting. There are also a From bb66a672faf7e20187abf117cbc91f93575acd1d Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Tue, 7 May 2019 19:17:35 +0100 Subject: [PATCH 289/864] Update manual for wand and spell library changes --- crawl-ref/docs/crawl_manual.rst | 42 ++++++++++++++++----------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/crawl-ref/docs/crawl_manual.rst b/crawl-ref/docs/crawl_manual.rst index 43e51d958247..ac51518cd8d0 100644 --- a/crawl-ref/docs/crawl_manual.rst +++ b/crawl-ref/docs/crawl_manual.rst @@ -67,10 +67,13 @@ Game modes are: Dungeon Crawl Start a standard game of Crawl. +Choose game seed + Start a standard game of Crawl with a custom seed (see `Seeded play`_ below). + Tutorial for Dungeon Crawl Start one of several specialised tutorials to learn how to play. -Hints mode for Dungeon Crawl +Hints Mode for Dungeon Crawl Start a standard game of Crawl, modified to provide help as you play. Dungeon Sprint @@ -889,9 +892,8 @@ have in inventory, the charges from the new wand are merged into the existing one, and the new wand no longer exists. Beware that when the last charge of a wand is used, the wand is destroyed. -Wands are aimed in the same way as missile weapons, and you can release the power -of a wand by evoking it with 'V'. See section I for targeting. There are also a -number of wands that may be useful to aim at yourself. +Wands are aimed in the same way as missile weapons, and you can release the +power of a wand by evoking it with 'V'. See section I for targeting. =" Rings and Amulets ======================================== @@ -924,9 +926,10 @@ magic school tend to have no combat powers at all. : Books ======================================== -Most books contain magical spells which your character may be able to learn. You -can read a book with the 'r' command, which lets you access a description of -each spell or memorise spells from it with the 'M' command. +Most books contain magical spells which your character may be able to learn. +Upon picking up a book, all of the spells in it will be added to your spell +library, allowing you to access a description of each spell or memorise spells +from it with the 'M' command. Occasionally you will find manuals of some skill. Carrying these will cause your experience to have twice the effect as usual when used for training that skill. @@ -988,10 +991,9 @@ Air and Earth) and, finally, Poison. A particular spell can belong to (and thus allow training of) up to three areas. Being good in the areas of a spell will improve the casting chance and, in many cases, the effect as well. -Spells are stored in books, which you will occasionally find in the dungeon. You -can read books with 'r' to check what spells they contain; doing so will allow -you to read the individual spells' descriptions. In order to memorise a certain -spell, use the 'M' command. +Spells are stored in books, which you will occasionally find in the dungeon. +Once you have picked up a book and added its contents to your spell library, you +can memorise a spell using the 'M' command. In addition to picking up new spells, your character may also wish to get rid of old ones by reading a scroll of amnesia, which will let you pick a spell to @@ -1065,11 +1067,11 @@ There are some shortcuts while targeting: strokes. At times, it will be useful to switch targets with the '+' or '-' commands, though. -It is possible to target yourself: obviously beneficial effects like hasting or -healing will actually target the cursor on you, leaving to you only the pressing -of '.', Enter, etc. - except if you want to heal or haste someone else. If you -target yourself while firing something harmful (which can be sensible at times), -you will be asked for confirmation. +It is possible to target yourself, and some beneficial effects like invisibility +will automatically target the cursor on you, leaving to you only the pressing +of '.', Enter, etc. - except if you want to aim at someone else. If you target +yourself while firing something harmful (which can be sensible at times), you +will be asked for confirmation. Finally, the ':' key allows you to hide the path of your spell/wand/missile. @@ -1085,8 +1087,7 @@ faith (use the 'a' command - but most gods resent being scorned). Further detail can be seen with '!' while in the '^' screen. To use any powers which your god deems you fit for, access the abilities menu -via the 'a' command; god-given abilities are listed as invocations. The god -Fedhas Madash also has a corpse decay ability specially accessed through 'p'. +via the 'a' command; god-given abilities are listed as invocations. Depending on background, some characters start out religious; others have to pray at an altar to dedicate themselves to a life of servitude. There are altars @@ -2269,9 +2270,8 @@ Invocations Evocations This skill lets you use wands much more effectively, in terms of both damage - and precision. Furthermore, with high Evocations, you can easily deduce the - number of charges in a wand through usage. Similarly, various other items - that have evocable powers work better for characters trained in this skill. + and precision. Similarly, various other items that have evocable powers work + better for characters trained in this skill. Invocations and Evocations can increase your maximum magical reserves, although both have a smaller effect than Spellcasting in this regard. The From 79c1ce788cab67fa265b56548cb21113bc28b462 Mon Sep 17 00:00:00 2001 From: ByrelMitchell <44025439+ByrelMitchell@users.noreply.github.com> Date: Wed, 8 May 2019 13:34:34 -0400 Subject: [PATCH 290/864] Remove reference to Akashic Record in wizlab.des (Mintice) (#1058) --- crawl-ref/source/dat/des/portals/wizlab.des | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/dat/des/portals/wizlab.des b/crawl-ref/source/dat/des/portals/wizlab.des index dd3d44609557..3f6dfe1e7953 100644 --- a/crawl-ref/source/dat/des/portals/wizlab.des +++ b/crawl-ref/source/dat/des/portals/wizlab.des @@ -1351,7 +1351,7 @@ KITEM: d = scroll of blinking / scroll of teleportation q:3 w:15 / \ any scroll w:1 KITEM: e = any ring KITEM: f = book of spatial translocations w:5 / book of the warp w:5 / \ - akashic record w:5 / manual of translocations w:5 / \ + manual of translocations w:5 / \ randbook disc:translocation numspells:5 / \ randbook disc:translocation owner:Golubria numspells:7 \ spells:shroud_of_golubria&passage_of_golubria From 5c6fb1cd70b95b402c3098fa22ea09731ff0af72 Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Thu, 9 May 2019 18:30:25 +0100 Subject: [PATCH 291/864] Update CREDITS.txt --- crawl-ref/CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/CREDITS.txt b/crawl-ref/CREDITS.txt index e76071cba11e..85433be4e7e0 100644 --- a/crawl-ref/CREDITS.txt +++ b/crawl-ref/CREDITS.txt @@ -235,6 +235,7 @@ Nikolai Lavsky Jonathon Nooner NormalPerson7 + Michael Nowack Erkki Nurmi Mattias Nyberg nyra From 25935dc31647e9e545489a847cd95b2ed4223606 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Wed, 8 May 2019 21:24:15 -0400 Subject: [PATCH 292/864] Throwing Overhaul I: Remove blowguns, needles become darts The presence of a *launcher* modified by throwing skill is a wart left over from the 0.6 ranged reform. The rarity of blowguns limited the use of needles early on to some extent, the balance impact of this will be addressed in a subsequent needle-brand-consolidation commit. In exchange for this limit, the interaction of blowgun enchantment with success chance made finding an enchanted blowgun a 0-skill no brainer: it was always better to use it. This commit removes blowguns. Needles are replaced with darts which are thrown. Darts have the same brands as needles. To replace blowgun enchantment, hex dart succes scales as (2/3) * (throwing + stealth), preserving the ability to land hex darts against high HD targets, but requiring a strategic cost to do so. As a bonus, no more stories about bladders or bellows for mummies are required. --- crawl-ref/docs/crawl_manual.rst | 13 ++-- crawl-ref/docs/options_guide.txt | 10 +-- crawl-ref/source/acquire.cc | 2 +- crawl-ref/source/attack.cc | 2 +- crawl-ref/source/beam.cc | 2 +- crawl-ref/source/dat/des/branches/abyss.des | 2 +- .../source/dat/des/builder/alphashops.des | 6 +- crawl-ref/source/dat/des/builder/shops.des | 2 +- crawl-ref/source/dat/des/portals/ossuary.des | 8 +-- .../source/dat/des/sprint/arena_sprint.des | 4 +- crawl-ref/source/dat/des/sprint/sprint_mu.des | 12 ++-- crawl-ref/source/dat/des/variable/ghost.des | 8 +-- .../source/dat/des/variable/mini_monsters.des | 8 +-- crawl-ref/source/dat/descript/backgrounds.txt | 3 +- crawl-ref/source/dat/descript/items.txt | 18 ++--- crawl-ref/source/dat/descript/skills.txt | 7 +- crawl-ref/source/describe.cc | 9 +-- crawl-ref/source/god-blessing.cc | 6 -- crawl-ref/source/hints.cc | 2 +- crawl-ref/source/initfile.cc | 4 +- crawl-ref/source/item-prop-enum.h | 8 ++- crawl-ref/source/item-prop.cc | 16 +++-- crawl-ref/source/items.cc | 6 +- crawl-ref/source/job-data.h | 4 +- crawl-ref/source/makeitem.cc | 29 ++++---- crawl-ref/source/mon-gear.cc | 70 ++++++++----------- crawl-ref/source/mon-util.cc | 2 +- crawl-ref/source/monster.cc | 7 +- crawl-ref/source/ng-wanderer.cc | 10 +-- crawl-ref/source/quiver.cc | 19 +---- crawl-ref/source/quiver.h | 2 + crawl-ref/source/ranged-attack.cc | 42 +++++------ crawl-ref/source/ranged-attack.h | 4 +- crawl-ref/source/rltiles/dc-item.txt | 22 +++--- crawl-ref/source/throw.cc | 30 ++++---- crawl-ref/source/throw.h | 2 - crawl-ref/source/tilepick.cc | 18 ++--- crawl-ref/source/trap-type.h | 4 +- crawl-ref/source/traps.cc | 26 +++---- crawl-ref/source/xom.cc | 2 +- 40 files changed, 202 insertions(+), 249 deletions(-) diff --git a/crawl-ref/docs/crawl_manual.rst b/crawl-ref/docs/crawl_manual.rst index ac51518cd8d0..03068367720e 100644 --- a/crawl-ref/docs/crawl_manual.rst +++ b/crawl-ref/docs/crawl_manual.rst @@ -1975,8 +1975,8 @@ Hunters Assassins An Assassin is a stealthy character who is especially good at killing, using - daggers or blowguns. They start with a dagger, a robe and cloak, a blowgun, - poisoned needles, and a few deadly and rare curare needles. + daggers or darts. They start with a dagger, a robe and cloak, poisoned darts, + and a few deadly and rare curare darts. Adventurer backgrounds ====================== @@ -2187,16 +2187,15 @@ Ranged combat skills There are a number of individual weapon skills for missile weapons: - * Throwing (includes blowguns) + * Throwing * Bows * Crossbows * Slings Throwing is the skill for all things hurled without a launcher: tomahawks, -javelins, nets, etc. The other skills refer to various types of missiles shot -with a launcher. An exception to this are needles: these are launched using -blowguns, an action which uses the Throwing skill. Since stones can be thrown -without launchers to some effect, these skills crosstrain: +javelins, nets, darts, etc. The other skills refer to various types of missiles +shot with a launcher. Since stones can be thrown without launchers to some +effect, these skills crosstrain: * Throwing and Slings diff --git a/crawl-ref/docs/options_guide.txt b/crawl-ref/docs/options_guide.txt index b49a6e867d59..bc06502ae809 100644 --- a/crawl-ref/docs/options_guide.txt +++ b/crawl-ref/docs/options_guide.txt @@ -511,8 +511,8 @@ autopickup_exceptions ^= don't-pickup-regex, ... be subject to autopickup. An example: - autopickup_exceptions += and the match expression is significant, @@ -1293,7 +1293,7 @@ autofight_hunger_stop_undead = false autofight_throw = false If your quiver contains a throwable item, autofight will throw it at enemies out of melee range. Without this option, only a wielded - launcher (a bow, crossbow, sling or blowgun) will be considered. + launcher (a bow, crossbow or sling) will be considered. autofight_throw_nomove = true This works same as above, except only for ===hit_closest_nomove rather @@ -1739,7 +1739,7 @@ fire_items_start = a missiles to fire. The default is a. fire_order = launcher, return -fire_order += javelin / tomahawk / stone / rock / net +fire_order += javelin / tomahawk / stone / rock / net / dart fire_order += inscribed (Ordered list option) Controls the order of items autoselected for firing. Items @@ -1752,7 +1752,7 @@ fire_order += inscribed firing. 'launcher' refers to firing the appropriate missile for the - wielded weapon (i.e. crossbow, bow, sling, blowgun). You'll almost + wielded weapon (i.e. crossbow, bow, sling). You'll almost certainly want it first, as it'll be ignored when you're not wielding a ranged weapon. 'return' refers to (identified) weapons of returning. diff --git a/crawl-ref/source/acquire.cc b/crawl-ref/source/acquire.cc index fc7060c67f04..e9d35baf1f69 100644 --- a/crawl-ref/source/acquire.cc +++ b/crawl-ref/source/acquire.cc @@ -559,7 +559,7 @@ static int _acquirement_missile_subtype(bool /*divine*/, int & /*quantity*/) vector > missile_weights; missile_weights.emplace_back(MI_TOMAHAWK, 50); - missile_weights.emplace_back(MI_NEEDLE, 75); + missile_weights.emplace_back(MI_DART, 75); if (you.body_size() >= SIZE_MEDIUM) missile_weights.emplace_back(MI_JAVELIN, 100); diff --git a/crawl-ref/source/attack.cc b/crawl-ref/source/attack.cc index aaa1df02797c..706ebef8751c 100644 --- a/crawl-ref/source/attack.cc +++ b/crawl-ref/source/attack.cc @@ -1170,8 +1170,8 @@ int attack::player_apply_misc_modifiers(int damage) int attack::get_weapon_plus() { if (weapon->base_type == OBJ_STAVES - || weapon->sub_type == WPN_BLOWGUN #if TAG_MAJOR_VERSION == 34 + || weapon->sub_type == WPN_BLOWGUN || weapon->base_type == OBJ_RODS #endif ) diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc index a212075562e5..49e7b7cf9809 100644 --- a/crawl-ref/source/beam.cc +++ b/crawl-ref/source/beam.cc @@ -4438,7 +4438,7 @@ void bolt::monster_post_hit(monster* mon, int dmg) } - // Don't allow needles of sleeping to awaken monsters. + // Don't allow darts of sleeping to awaken monsters. if (m_brand == SPMSL_SLEEP && was_asleep && !mon->asleep()) mon->put_to_sleep(agent(), 0); } diff --git a/crawl-ref/source/dat/des/branches/abyss.des b/crawl-ref/source/dat/des/branches/abyss.des index bc3760e83747..63014768d32f 100644 --- a/crawl-ref/source/dat/des/branches/abyss.des +++ b/crawl-ref/source/dat/des/branches/abyss.des @@ -1459,7 +1459,7 @@ KMONS: 6 = lurking horror # Note: if anything in these two item sets becomes useful for more then a tiny # fraction of characters finding the abyssal rune, remove or replace them. KITEM: 4d = scroll of random uselessness w:15 q:1 / ration w:1 / \ - club w:6 / stone q:1 / needle q:1 ego:confusion / \ + club w:6 / stone q:1 / dart q:1 ego:confusion / \ mundane animal skin / mundane ring mail / gold q:1 KITEM: 5 = wand of random effects / wand of flame / whip not_cursed w:2 / \ hat not_cursed mundane w:5 diff --git a/crawl-ref/source/dat/des/builder/alphashops.des b/crawl-ref/source/dat/des/builder/alphashops.des index 594d91aca948..1d33dd2fc1c0 100644 --- a/crawl-ref/source/dat/des/builder/alphashops.des +++ b/crawl-ref/source/dat/des/builder/alphashops.des @@ -67,7 +67,7 @@ elseif s == "B" then i = { "bardiche", "battleaxe", "bolt", "book of battle", "book of beasts", "book of burglary", "box of beasts", "broad axe", "pair of boots", "potion of berserk rage", - "blowgun", "potion of blood", "potion of brilliance", + "potion of blood", "potion of brilliance", "scroll of blinking", "scroll of brand weapon", "manual of bows", "buckler" } @@ -82,7 +82,7 @@ "book of dreams", "book of the dragon", "dagger", "demon blade", "demon trident", "demon whip", "dire flail", "double sword", "ring of dexterity", "manual of dodging", "wand of disintegration", - "staff of death", "wand of digging" } + "staff of death", "wand of digging", "dart" } elseif s == "E" then i = { "book of enchantments", "manual of evocations", "eveningstar", "ring of evasion", "executioner's axe", @@ -127,7 +127,7 @@ "potion of mutation", "scroll of magic mapping", } elseif s == "N" then i = { "book of necromancy", "naga barding", - "necronomicon", "needle", "scroll of noise", "manual of necromancy" } + "necronomicon", "scroll of noise", "manual of necromancy" } elseif s == "O" then i = { "any" } diff --git a/crawl-ref/source/dat/des/builder/shops.des b/crawl-ref/source/dat/des/builder/shops.des index facf74d9cb51..493982d781ed 100644 --- a/crawl-ref/source/dat/des/builder/shops.des +++ b/crawl-ref/source/dat/des/builder/shops.des @@ -306,7 +306,7 @@ TAGS: no_monster_gen transparent DEPTH: D:4-, Depths MONS: ball python w:5 / adder / water moccasin, place:Snake:1 KFEAT: v = general shop type:Serpentskin suffix:Sales count:7 ; \ - w:8 blowgun | w:8 needle ego:poisoned | w:4 needle ego:curare | \ + w:8 dart ego:poisoned | w:4 dart ego:curare | \ w:14 tomahawk ego:poisoned | \ w:3 ring of poison resistance | w:6 randbook disc:poison | \ w:2 staff of poison | w:4 any weapon ego:venom | \ diff --git a/crawl-ref/source/dat/des/portals/ossuary.des b/crawl-ref/source/dat/des/portals/ossuary.des index 5149f42341ed..f4248d395e01 100644 --- a/crawl-ref/source/dat/des/portals/ossuary.des +++ b/crawl-ref/source/dat/des/portals/ossuary.des @@ -357,7 +357,7 @@ NAME: ossuary_tomb_2 WEIGHT: 40 ORIENT: encompass TAGS: no_item_gen no_monster_gen no_rotate -KFEAT: ~ = arrow trap w:2 / needle trap +KFEAT: ~ = arrow trap w:2 / dart trap KFEAT: ^ = arrow trap / floor w:5 # Number of 1's is 53, number of ~'s is 57. : if crawl.one_chance_in(10) then @@ -556,7 +556,7 @@ MONS: gnoll zombie / hobgoblin zombie / orc zombie / \ human zombie / kobold zombie / goblin zombie / \ big kobold zombie / centaur zombie / scorpion zombie w:20 ITEM: any scroll / any potion / any jewellery w:1 / nothing -KFEAT: ~ = needle trap / arrow trap / spear trap w:5 +KFEAT: ~ = dart trap / arrow trap / spear trap w:5 SUBST: 1 = 1. SUBST: 3 = 3. : ossuary_setup_features(_G) @@ -1110,7 +1110,7 @@ MONS: rat zombie / quokka zombie / adder zombie /\ big kobold zombie w:1 / human zombie w:1 / elf zombie w:1 / orc zombie w:1 MONS: generate_awake mummy ITEM: any scroll / any potion / gold w:4 -KFEAT: ~ = arrow trap / needle trap +KFEAT: ~ = arrow trap / dart trap : ossuary_setup_features(_G) MAP ccccc ccc ccc ccc @@ -1214,7 +1214,7 @@ KMONS: 3 = goblin zombie / hobgoblin zombie / kobold zombie / gnoll zombie w:2 big kobold zombie w:1 / human zombie w:1 / elf zombie w:1 / orc zombie w:1 /\ nothing w:36 KITEM: 12d = any potion / any scroll / any jewellery w:1 -KFEAT: . = needle trap / arrow trap / spear trap w:5 / floor w:600 +KFEAT: . = dart trap / arrow trap / spear trap w:5 / floor w:600 NSUBST: d = 1:1 / 3:2 / 4:. / *:d : ossuary_setup_features(_G) MAP diff --git a/crawl-ref/source/dat/des/sprint/arena_sprint.des b/crawl-ref/source/dat/des/sprint/arena_sprint.des index 5e30424c3ec9..d2528a593f19 100644 --- a/crawl-ref/source/dat/des/sprint/arena_sprint.des +++ b/crawl-ref/source/dat/des/sprint/arena_sprint.des @@ -437,7 +437,7 @@ function arena_sprint_get_monster_set(round, boss) "moth of wrath / w:20 stone giant", "ball lightning", "orb spider", "hungry ghost / harpy", "shining eye", "tormentor", - "skeletal warrior / w:5 skeletal warrior ; blowgun . needle ego:confusion" + "skeletal warrior / w:5 skeletal warrior ; dart ego:confusion" } elseif round <= 26 then mon_set = { @@ -503,7 +503,7 @@ function arena_sprint_get_monster_set(round, boss) "neqoxec", "smoke demon", "catoblepas", "moth of wrath / w:20 ettin", "orb spider", "fire crab", "shining eye", "tormentor", "tentacled monstrosity", - "skeletal warrior / skeletal warrior ; blowgun . needle ego:confusion", + "skeletal warrior / skeletal warrior ; dart ego:confusion", "unseen horror / lorocyproca / shadow wraith / ghost moth", "curse toe / w:20 wandering mushroom / w:4 murray", "reaper / hell beast / geryon w:1", diff --git a/crawl-ref/source/dat/des/sprint/sprint_mu.des b/crawl-ref/source/dat/des/sprint/sprint_mu.des index eb9c1dbb6258..87dc53b592f0 100644 --- a/crawl-ref/source/dat/des/sprint/sprint_mu.des +++ b/crawl-ref/source/dat/des/sprint/sprint_mu.des @@ -513,8 +513,8 @@ KMONS: g = tyrant leech KMONS: A = lindwurm KMONS: h = redback KMONS: i = hydra -KMONS: j = patrolling spriggan ; blowgun . q:5 needle ego:sleep | \ - q:5 needle ego:paralysis | q:5 needle ego:frenzy +KMONS: j = patrolling spriggan ; q:5 dart ego:sleep | \ + q:5 dart ego:paralysis | q:5 dart ego:frenzy KMONS: k = patrolling spriggan druid KMONS: q = electric eel KFEAT: q = deep_water @@ -817,26 +817,26 @@ KMONS: a = patrolling Sigmund hd:15 hp:100 \ iskenderun's_mystic_blast.16.wizard \ ; scythe ego:distortion KMONS: b = patrolling Edmund hp:150 ; great mace ego:freezing \ - . blowgun . needle ego:curare q:7 + . dart ego:curare q:7 : elseif d2rnd == 1 then KMONS: a = patrolling Dowan hd:15 hp:100 \ spells:bolt_of_cold.11.wizard;corona.11.wizard;blink_range.11.wizard;\ bolt_of_fire.11.wizard;;haste_other.11.wizard;minor_healing.11.wizard \ ; morningstar ego:distortion KMONS: b = patrolling Duvessa hp:150 ; great sword ego:freezing \ - . blowgun . needle ego:curare q:7 + . dart ego:curare q:7 : elseif d2rnd == 2 then KMONS: a = patrolling Harold hd:15 hp:100 \ spells:poison_arrow.16.wizard;teleport_other.16.wizard;\ minor_healing.16.wizard;slow.16.wizard \ ; dire flail ego:distortion KMONS: b = patrolling Joseph hd:5 hp:150 ; quarterstaff ego:freezing \ - . blowgun . needle ego:curare q:7 + . dart ego:curare q:7 : else KMONS: a = patrolling Donald ; war axe ego:holy_wrath . scale mail \ . shield ego:reflection KMONS: b = patrolling Frances ; war axe ego:holy_wrath \ - . blowgun . needle ego:curare q:7 + . dart ego:curare q:7 :end KITEM: & = lamp of fire, scroll of acquirement q:1 ident:all, \ scroll of acquirement q:1 ident:all / w:15 scroll of torment ident:all, \ diff --git a/crawl-ref/source/dat/des/variable/ghost.des b/crawl-ref/source/dat/des/variable/ghost.des index da953a9e1fad..3139c29a1225 100644 --- a/crawl-ref/source/dat/des/variable/ghost.des +++ b/crawl-ref/source/dat/des/variable/ghost.des @@ -1550,9 +1550,9 @@ KMONS: pq = plant / fungus KFEAT: q = W KMONS: O = player ghost MONS: kobold, big kobold, kobold demonologist -KMONS: D = kobold ; blowgun . needle ego:curare | needle ego:poisoned . dagger -KMONS: E = big kobold ; blowgun . needle ego:curare | \ - needle ego:poisoned w:5 . dagger | short sword | whip +KMONS: D = kobold ; dart ego:curare | dart ego:poisoned . dagger +KMONS: E = big kobold ; dart ego:curare | \ + dart ego:poisoned w:5 . dagger | short sword | whip KMONS: F = kobold ; wand of flame | wand of acid | wand of polymorph | \ wand of enslavement | wand of paralysis | \ wand of disintegration . dagger @@ -1998,7 +1998,7 @@ NSUBST: R = R / - {{ kmons("q = kobold; " .. wrathful_weapon("kobold", crawl.one_chance_in(3) and "randart" or "good_item") .. - " . blowgun good_item . needle ego:curare | needle ego:poisoned w:5") + " . dart ego:curare | dart ego:poisoned w:5") kmons("r = gnoll sergeant; " .. wrathful_weapon("sergeant", crawl.one_chance_in(3) and "randart" or "good_item") .. " . leather armour good_item | ring mail good_item" .. diff --git a/crawl-ref/source/dat/des/variable/mini_monsters.des b/crawl-ref/source/dat/des/variable/mini_monsters.des index 078c9f17ad6f..b05474a648ba 100644 --- a/crawl-ref/source/dat/des/variable/mini_monsters.des +++ b/crawl-ref/source/dat/des/variable/mini_monsters.des @@ -886,7 +886,7 @@ KMASK: 'f = opaque : if crawl.coinflip() then KITEM: f = javelin ego:poisoned q:4-6 / tomahawk ego:poisoned : else -KITEM: f = blowgun / w:5 nothing, needle ego:poisoned / needle ego:curare / needle ego:paralysis +KITEM: f = dart ego:poisoned / dart ego:curare / dart ego:paralysis : end KITEM: g = any potion q:2-3 MONS: plant, oklob sapling, ball python @@ -941,7 +941,7 @@ ITEM: Young Poisoner's Handbook / book of Changes / \ : if crawl.coinflip() then KITEM: f = javelin ego:poisoned q:4-6 / tomahawk ego:poisoned : else -KITEM: f = blowgun / w:5 nothing, needle ego:poisoned / needle ego:curare / needle ego:paralysis +KITEM: f = dart ego:poisoned / dart ego:curare / dart ego:paralysis : end KITEM: g = any potion q:2 / any potion q:3 MONS: plant, oklob sapling, ball python @@ -1300,8 +1300,8 @@ TAGS: transparent DEPTH: D:6- MONS: kobold ; tomahawk ego:dispersal q:2 / w:3 big kobold ; tomahawk ego:dispersal q:4 MONS: kobold ; tomahawk ego:exploding q:2 / w:3 big kobold ; tomahawk ego:exploding q:4 -MONS: kobold ; blowgun . needle ego:curare q:1 / \ - w:3 big kobold ; blowgun . needle ego:curare q:2 +MONS: kobold ; dart ego:curare q:1 / \ + w:3 big kobold ; dart ego:curare q:2 : if you.absdepth() > 13 then SUBST: 1 = 3 : elseif you.absdepth() > 11 then diff --git a/crawl-ref/source/dat/descript/backgrounds.txt b/crawl-ref/source/dat/descript/backgrounds.txt index e798d8d42a4e..fa57e9a0c7f7 100644 --- a/crawl-ref/source/dat/descript/backgrounds.txt +++ b/crawl-ref/source/dat/descript/backgrounds.txt @@ -21,8 +21,7 @@ tools. %%%% Assassin -Assassins carry a blowgun with poisoned needles, as well as a small number of -nasty curare needles. +Assassins carry poisoned darts and a small number of nasty curare darts. %%%% Berserker diff --git a/crawl-ref/source/dat/descript/items.txt b/crawl-ref/source/dat/descript/items.txt index 936b6ddaadac..393507177c76 100644 --- a/crawl-ref/source/dat/descript/items.txt +++ b/crawl-ref/source/dat/descript/items.txt @@ -90,11 +90,6 @@ battleaxe A large war axe with a formidable double-sided head. %%%% -blowgun - -A long, light tube, open at both ends, through which various types of needles -are propelled by puffs of breath at enemies. It makes very little noise. -%%%% bolt A metal projectile, shorter than an arrow, intended to be shot from a crossbow. @@ -348,6 +343,13 @@ dagger A double-edged fighting knife with a sharp point. %%%% +dart + +A thin piece of metal, typically coated in some harmful substance. When +thrown with skill it can deliver its toxins into the bloodstream of a +living or demonic being. In addition to throwing skill, stealth skill improves +the chance for a dart to affect its target. +%%%% decaying skeleton A decaying skeleton. @@ -607,12 +609,6 @@ An extremely rare book, powerful and sinister. Many foolhardy magicians have tried to study this tome, only to find themselves entangled within necromantic forces they could not hope to control. %%%% -needle - -A thin piece of metal, typically coated in some harmful substance. When -launched from a blowgun it can deliver its toxins into the bloodstream of a -living or demonic being. -%%%% orb of zot An invaluable artefact. Once you have escaped to the surface with it, your diff --git a/crawl-ref/source/dat/descript/skills.txt b/crawl-ref/source/dat/descript/skills.txt index c44d23b41df9..9c155e595f64 100644 --- a/crawl-ref/source/dat/descript/skills.txt +++ b/crawl-ref/source/dat/descript/skills.txt @@ -84,10 +84,9 @@ appropriate launcher and ammunition. %%%% Throwing -Training Throwing will make thrown weapons (such as javelins) and blowguns more -effective. In particular, it makes weapons of returning more likely to return -to their thrower, and makes certain magical needles more likely to have an -effect when fired from a blowgun. +Training Throwing will make thrown weapons (such as javelins)more effective. In +particular, it makes weapons of returning more likely to return to their +thrower, and makes certain magical darts more likely to have an effect. Being skilled in Throwing increases your effectiveness with Slings, and vice versa. diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index a3825b997990..acabcb589def 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -632,9 +632,7 @@ static string _randart_descrip(const item_def &item) static const char *trap_names[] = { -#if TAG_MAJOR_VERSION == 34 "dart", -#endif "arrow", "spear", #if TAG_MAJOR_VERSION > 34 "dispersal", @@ -642,7 +640,10 @@ static const char *trap_names[] = #endif "permanent teleport", "alarm", "blade", - "bolt", "net", "Zot", "needle", + "bolt", "net", "Zot", +#if TAG_MAJOR_VERSION == 34 + "needle", +#endif "shaft", "passage", "pressure plate", "web", #if TAG_MAJOR_VERSION == 34 "gas", "teleport", @@ -1486,7 +1487,7 @@ static string _describe_ammo(const item_def &item) "asphyxiation, dealing direct damage as well as " "poisoning and slowing those it strikes.\n" "It is twice as likely to be destroyed on impact as " - "other needles."; + "other darts."; break; case SPMSL_PARALYSIS: description += "It is tipped with a paralysing substance."; diff --git a/crawl-ref/source/god-blessing.cc b/crawl-ref/source/god-blessing.cc index 0c5414cc8298..557e5ea23513 100644 --- a/crawl-ref/source/god-blessing.cc +++ b/crawl-ref/source/god-blessing.cc @@ -173,12 +173,6 @@ void gift_ammo_to_orc(monster* orc, bool initial_gift) if (ammo.sub_type == MI_STONE) ammo.sub_type = MI_SLING_BULLET; // ugly special case - // XXX: should beogh be gifting needles? - // if not, we'd need special checks in player gifting, etc... better to - // go along for now. - if (ammo.sub_type == MI_NEEDLE) - ammo.brand = SPMSL_POISONED; - ammo.quantity = 30 + random2(10); if (initial_gift || !launcher) ammo.quantity /= 2; diff --git a/crawl-ref/source/hints.cc b/crawl-ref/source/hints.cc index 4621153f4806..49abefa04bfc 100644 --- a/crawl-ref/source/hints.cc +++ b/crawl-ref/source/hints.cc @@ -1206,7 +1206,7 @@ void learned_something_new(hints_event_type seen_what, coord_def gc) << "') " "you've picked up. Missiles like tomahawks and throwing nets " "can be thrown by hand, but other missiles like arrows and " - "needles require a launcher and training in using it to be " + "bolts require a launcher and training in using it to be " "really effective. " #ifdef USE_TILE_LOCAL "Right-clicking on " diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index a598d3048eb3..b3cea3407cd3 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -633,6 +633,8 @@ static fire_type _str_to_fire_types(const string &str) return FIRE_JAVELIN; else if (str == "tomahawk") return FIRE_TOMAHAWK; + else if (str == "dart") + return FIRE_DART; else if (str == "net") return FIRE_NET; else if (str == "return" || str == "returning") @@ -1077,7 +1079,7 @@ void game_options::reset_options() // Clear fire_order and set up the defaults. set_fire_order("launcher, return, " - "javelin / tomahawk / stone / rock / net, " + "javelin / tomahawk / stone / rock / net / dart, " "inscribed", false, false); diff --git a/crawl-ref/source/item-prop-enum.h b/crawl-ref/source/item-prop-enum.h index 519c74b30b7b..caf6007cc63c 100644 --- a/crawl-ref/source/item-prop-enum.h +++ b/crawl-ref/source/item-prop-enum.h @@ -325,10 +325,10 @@ const vector misc_types = enum missile_type { -#if TAG_MAJOR_VERSION == 34 MI_DART, -#endif +#if TAG_MAJOR_VERSION == 34 MI_NEEDLE, +#endif MI_ARROW, MI_BOLT, MI_JAVELIN, @@ -467,7 +467,7 @@ enum special_missile_type // to separate from weapons in general {dlb} SPMSL_EXPLODING, SPMSL_STEEL, SPMSL_SILVER, - SPMSL_PARALYSIS, // needle only from here on + SPMSL_PARALYSIS, // dart only from here on #if TAG_MAJOR_VERSION == 34 SPMSL_SLOW, #endif @@ -566,7 +566,9 @@ enum weapon_type WPN_GLAIVE, WPN_BARDICHE, +#if TAG_MAJOR_VERSION == 34 WPN_BLOWGUN, +#endif #if TAG_MAJOR_VERSION > 34 WPN_HAND_CROSSBOW, diff --git a/crawl-ref/source/item-prop.cc b/crawl-ref/source/item-prop.cc index 8b5bd870b644..7ea23c6ab3ae 100644 --- a/crawl-ref/source/item-prop.cc +++ b/crawl-ref/source/item-prop.cc @@ -610,9 +610,11 @@ static const weapon_def Weapon_prop[] = }}, // Range weapons +#if TAG_MAJOR_VERSION == 34 { WPN_BLOWGUN, "blowgun", 0, 2, 10, SK_THROWING, SIZE_LITTLE, SIZE_LITTLE, MI_NEEDLE, - DAMV_NON_MELEE, 5, 0, 25, {}, }, + DAMV_NON_MELEE, 0, 0, 0, {}, }, +#endif { WPN_HUNTING_SLING, "hunting sling", 5, 2, 12, SK_SLINGS, SIZE_LITTLE, SIZE_LITTLE, MI_STONE, @@ -652,10 +654,10 @@ struct missile_def static int Missile_index[NUM_MISSILES]; static const missile_def Missile_prop[] = { + { MI_DART, "dart", 0, 12, 2, true }, #if TAG_MAJOR_VERSION == 34 - { MI_DART, "dart", 2, 1, 1, true }, -#endif { MI_NEEDLE, "needle", 0, 12, 2, false }, +#endif { MI_STONE, "stone", 2, 8, 1, true }, { MI_ARROW, "arrow", 0, 8, 2, false }, { MI_BOLT, "bolt", 0, 8, 2, false }, @@ -1885,8 +1887,14 @@ bool is_brandable_weapon(const item_def &wpn, bool allow_ranged, bool divine) if (is_artefact(wpn)) return false; - if (!allow_ranged && is_range_weapon(wpn) || wpn.sub_type == WPN_BLOWGUN) + if (!allow_ranged && is_range_weapon(wpn) +#if TAG_MAJOR_VERSION == 34 + || wpn.sub_type == WPN_BLOWGUN +#endif + ) + { return false; + } // Only gods can rebrand blessed weapons, and they revert back to their // old base type in the process. diff --git a/crawl-ref/source/items.cc b/crawl-ref/source/items.cc index 031b68364110..60705162c019 100644 --- a/crawl-ref/source/items.cc +++ b/crawl-ref/source/items.cc @@ -3499,16 +3499,16 @@ colour_t item_def::missile_colour() const { case MI_STONE: return BROWN; -#if TAG_MAJOR_VERSION == 34 - case MI_DART: -#endif case MI_SLING_BULLET: return CYAN; case MI_LARGE_ROCK: return LIGHTGREY; case MI_ARROW: return BLUE; +#if TAG_MAJOR_VERSION == 34 case MI_NEEDLE: +#endif + case MI_DART: return WHITE; case MI_BOLT: return LIGHTBLUE; diff --git a/crawl-ref/source/job-data.h b/crawl-ref/source/job-data.h index 9bfc398d661a..04c24107254d 100644 --- a/crawl-ref/source/job-data.h +++ b/crawl-ref/source/job-data.h @@ -72,8 +72,8 @@ static const map job_data = 3, 3, 6, { SP_TROLL, SP_HALFLING, SP_SPRIGGAN, SP_DEMONSPAWN, SP_VAMPIRE, SP_VINE_STALKER, }, - { "dagger plus:2", "blowgun", "robe", "cloak", "needle ego:poisoned q:8", - "needle ego:curare q:2" }, + { "dagger plus:2", "robe", "cloak", "dart ego:poisoned q:8", + "dart ego:curare q:2" }, WCHOICE_NONE, { { SK_FIGHTING, 2 }, { SK_DODGING, 1 }, { SK_STEALTH, 4 }, { SK_THROWING, 2 }, { SK_WEAPON, 2 }, }, diff --git a/crawl-ref/source/makeitem.cc b/crawl-ref/source/makeitem.cc index 9ed7c37d528e..7a32c7c356e2 100644 --- a/crawl-ref/source/makeitem.cc +++ b/crawl-ref/source/makeitem.cc @@ -199,8 +199,8 @@ static bool _try_make_item_unrand(item_def& item, int force_type, int agent) static bool _weapon_disallows_randart(int sub_type) { - // Clubs and blowguns are never randarts. - return sub_type == WPN_CLUB || sub_type == WPN_BLOWGUN; + // Clubs are never randarts. + return sub_type == WPN_CLUB; } // Return whether we made an artefact. @@ -300,9 +300,6 @@ bool is_weapon_brand_ok(int type, int brand, bool strict) if (type == WPN_QUICK_BLADE && brand == SPWPN_SPEED) return false; - if (type == WPN_BLOWGUN) - return false; - switch ((brand_type)brand) { // Universal brands. @@ -519,9 +516,6 @@ static special_missile_type _determine_missile_brand(const item_def& item, switch (item.sub_type) { -#if TAG_MAJOR_VERSION == 34 - case MI_DART: -#endif case MI_THROWING_NET: case MI_STONE: case MI_LARGE_ROCK: @@ -530,7 +524,10 @@ static special_missile_type _determine_missile_brand(const item_def& item, case MI_BOLT: rc = SPMSL_NORMAL; break; + case MI_DART: +#if TAG_MAJOR_VERSION == 34 case MI_NEEDLE: +#endif // Curare is special cased, all the others aren't. if (got_curare_roll(item_level)) { @@ -586,12 +583,12 @@ bool is_missile_brand_ok(int type, int brand, bool strict) if (brand == SPMSL_FLAME || brand == SPMSL_FROST) return false; - // In contrast, needles should always be branded. - // And all of these brands save poison are unique to needles. + // In contrast, darts should always be branded. + // And all of these brands save poison are unique to darts. switch (brand) { case SPMSL_POISONED: - if (type == MI_NEEDLE) + if (type == MI_DART) return true; break; @@ -606,7 +603,7 @@ bool is_missile_brand_ok(int type, int brand, bool strict) case SPMSL_SICKNESS: #endif case SPMSL_FRENZY: - return type == MI_NEEDLE; + return type == MI_DART; #if TAG_MAJOR_VERSION == 34 case SPMSL_BLINDING: @@ -615,7 +612,7 @@ bool is_missile_brand_ok(int type, int brand, bool strict) #endif default: - if (type == MI_NEEDLE) + if (type == MI_DART) return false; } @@ -623,7 +620,7 @@ bool is_missile_brand_ok(int type, int brand, bool strict) if (brand == SPMSL_NORMAL) return true; - // In non-strict mode, everything other than needles is mostly ok. + // In non-strict mode, everything other than darts is mostly ok. if (!strict) return true; @@ -674,7 +671,7 @@ static void _generate_missile_item(item_def& item, int force_type, 20, MI_ARROW, 12, MI_BOLT, 12, MI_SLING_BULLET, - 10, MI_NEEDLE, + 10, MI_DART, 3, MI_TOMAHAWK, 2, MI_JAVELIN, 1, MI_THROWING_NET, @@ -709,7 +706,7 @@ static void _generate_missile_item(item_def& item, int force_type, // Reduced quantity if special. if (item.sub_type == MI_JAVELIN || item.sub_type == MI_TOMAHAWK - || (item.sub_type == MI_NEEDLE && get_ammo_brand(item) != SPMSL_POISONED) + || (item.sub_type == MI_DART && get_ammo_brand(item) != SPMSL_POISONED) || get_ammo_brand(item) == SPMSL_RETURNING) { item.quantity = random_range(2, 8); diff --git a/crawl-ref/source/mon-gear.cc b/crawl-ref/source/mon-gear.cc index 2369a7360b27..e59ef245b5eb 100644 --- a/crawl-ref/source/mon-gear.cc +++ b/crawl-ref/source/mon-gear.cc @@ -970,7 +970,6 @@ int make_mons_weapon(monster_type type, int level, bool melee_only) { WPN_SHORTBOW, 1 }, { WPN_LONGBOW, 1 }, } } }, - { MONS_SONJA, { { { WPN_BLOWGUN, 1 } } } }, // salamanders only have secondary weapons; melee or bow, not both { MONS_SALAMANDER, { { { WPN_HALBERD, 5 }, @@ -980,10 +979,6 @@ int make_mons_weapon(monster_type type, int level, bool melee_only) { WPN_SHORTBOW, 5 }, }, { 4, 0, 4 }, } }, - { MONS_SPRIGGAN_RIDER, { - { { WPN_BLOWGUN, 1 }, - { NUM_WEAPONS, 14 }, }, - } }, { MONS_WARMONGER, { { { WPN_LONGBOW, 10 }, // total 60 { WPN_ARBALEST, 9 }, @@ -1022,14 +1017,6 @@ int make_mons_weapon(monster_type type, int level, bool melee_only) switch (type) { case MONS_KOBOLD: - // A few of the smarter kobolds have blowguns. - if (one_chance_in(10) && level > 1) - { - item.base_type = OBJ_WEAPONS; - item.sub_type = WPN_BLOWGUN; - break; - } - // intentional fallthrough case MONS_BIG_KOBOLD: if (x_chance_in_y(3, 5)) // give hand weapon { @@ -1345,33 +1332,6 @@ static void _give_ammo(monster* mon, int level, bool mons_summoned) if (thing_created == NON_ITEM) return; - - if (xitt == MI_NEEDLE) - { - if (mon->type == MONS_SONJA) - { - set_item_ego_type(mitm[thing_created], OBJ_MISSILES, - SPMSL_CURARE); - - mitm[thing_created].quantity = random_range(4, 10); - } - else if (mon->type == MONS_SPRIGGAN_RIDER) - { - set_item_ego_type(mitm[thing_created], OBJ_MISSILES, - SPMSL_CURARE); - - mitm[thing_created].quantity = random_range(2, 4); - } - else - { - set_item_ego_type(mitm[thing_created], OBJ_MISSILES, - got_curare_roll(level) ? SPMSL_CURARE - : SPMSL_POISONED); - - if (get_ammo_brand(mitm[thing_created]) == SPMSL_CURARE) - mitm[thing_created].quantity = random_range(2, 8); - } - } else { // Sanity check to avoid useless brands. @@ -1406,9 +1366,19 @@ static void _give_ammo(monster* mon, int level, bool mons_summoned) // Give some monsters throwables. int weap_type = -1; int qty = 0; + int brand = SPMSL_NORMAL; + switch (mon->type) { case MONS_KOBOLD: + if (one_chance_in(10) && level > 1) + { + weap_type = MI_DART; + qty = random_range(2, 8); + brand = got_curare_roll(level) ? SPMSL_CURARE : SPMSL_POISONED; + break; + } + // intentional fallthrough case MONS_BIG_KOBOLD: if (x_chance_in_y(2, 5)) { @@ -1417,6 +1387,21 @@ static void _give_ammo(monster* mon, int level, bool mons_summoned) } break; + case MONS_SONJA: + weap_type = MI_DART; + brand = SPMSL_CURARE; + qty = random_range(4, 10); + break; + + case MONS_SPRIGGAN_RIDER: + if (one_chance_in(15)) + { + weap_type = MI_DART; + brand = SPMSL_CURARE; + qty = random_range(2, 8); + } + break; + case MONS_ORC_WARRIOR: if (one_chance_in( player_in_branch(BRANCH_ORC)? 9 : 20)) @@ -1441,6 +1426,7 @@ static void _give_ammo(monster* mon, int level, bool mons_summoned) case MONS_CHUCK: weap_type = MI_LARGE_ROCK; + brand = SPMSL_RETURNING; qty = 2; break; @@ -1507,8 +1493,8 @@ static void _give_ammo(monster* mon, int level, bool mons_summoned) { item_def& w(mitm[thing_created]); - if (mon->type == MONS_CHUCK) - set_item_ego_type(w, OBJ_MISSILES, SPMSL_RETURNING); + if (brand != SPMSL_NORMAL) + set_item_ego_type(w, OBJ_MISSILES, brand); w.quantity = qty; give_specific_item(mon, thing_created); diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index 0d9439a4b591..7c2703c949a4 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -3892,7 +3892,7 @@ bool mons_has_incapacitating_ranged_attack(const monster& mon, const actor& foe) if (missile && missile->sub_type == MI_THROWING_NET) return true; - else if (missile && missile->sub_type == MI_NEEDLE) + else if (missile && missile->sub_type == MI_DART) { switch (get_ammo_brand(*missile)) { diff --git a/crawl-ref/source/monster.cc b/crawl-ref/source/monster.cc index 9f894f443c70..083afc1397aa 100644 --- a/crawl-ref/source/monster.cc +++ b/crawl-ref/source/monster.cc @@ -1378,12 +1378,9 @@ static bool _is_signature_weapon(const monster* mons, const item_def &weapon) if (mons->type == MONS_DONALD) return mons->hands_reqd(weapon) == HANDS_ONE; - // What kind of assassin would forget her blowgun or dagger somewhere else? + // What kind of assassin would forget her dagger somewhere else? if (mons->type == MONS_SONJA) - { - return item_attack_skill(weapon) == SK_SHORT_BLADES - || wtype == WPN_BLOWGUN; - } + return item_attack_skill(weapon) == SK_SHORT_BLADES; if (mons->type == MONS_IMPERIAL_MYRMIDON) return item_attack_skill(weapon) == SK_LONG_BLADES; diff --git a/crawl-ref/source/ng-wanderer.cc b/crawl-ref/source/ng-wanderer.cc index 3a811b22103c..22ead0849a94 100644 --- a/crawl-ref/source/ng-wanderer.cc +++ b/crawl-ref/source/ng-wanderer.cc @@ -19,13 +19,13 @@ static void _give_wanderer_weapon(skill_type wpn_skill, int plus) // get curare here. if (plus) { - newgame_make_item(OBJ_MISSILES, MI_NEEDLE, 1 + random2(4), + newgame_make_item(OBJ_MISSILES, MI_DART, 1 + random2(4), 0, SPMSL_CURARE); } - // Otherwise, we just get some poisoned needles. + // Otherwise, we just get some poisoned darts. else { - newgame_make_item(OBJ_MISSILES, MI_NEEDLE, 5 + roll_dice(2, 5), + newgame_make_item(OBJ_MISSILES, MI_DART, 5 + roll_dice(2, 5), 0, SPMSL_POISONED); } } @@ -59,10 +59,6 @@ static void _give_wanderer_weapon(skill_type wpn_skill, int plus) sub_type = WPN_QUARTERSTAFF; break; - case SK_THROWING: - sub_type = WPN_BLOWGUN; - break; - case SK_BOWS: sub_type = WPN_SHORTBOW; break; diff --git a/crawl-ref/source/quiver.cc b/crawl-ref/source/quiver.cc index 4d529b92fa19..9cf0f86d59a1 100644 --- a/crawl-ref/source/quiver.cc +++ b/crawl-ref/source/quiver.cc @@ -166,7 +166,6 @@ void quiver_item(int slot) #endif mprf("Quivering %s for %s.", you.inv[slot].name(DESC_INVENTORY).c_str(), t == AMMO_THROW ? "throwing" : - t == AMMO_BLOWGUN ? "blowguns" : t == AMMO_SLING ? "slings" : t == AMMO_BOW ? "bows" : "crossbows"); @@ -194,7 +193,6 @@ void choose_item_for_quiver() mprf("Reset %s quiver to default.", t == AMMO_THROW ? "throwing" : - t == AMMO_BLOWGUN ? "blowgun" : t == AMMO_SLING ? "sling" : t == AMMO_BOW ? "bow" : "crossbow"); @@ -392,20 +390,9 @@ void player_quiver::_get_fire_order(vector& order, const int inv_start = (ignore_inscription_etc ? 0 : Options.fire_items_start); - // If in a net, cannot throw anything, and can only launch from blowgun. + // If in a net, cannot launch anything. if (you.attribute[ATTR_HELD]) - { - if (launcher && launcher->sub_type == WPN_BLOWGUN) - { - for (int i_inv = inv_start; i_inv < ENDOFPACK; i_inv++) - if (you.inv[i_inv].defined() - && you.inv[i_inv].launched_by(*launcher)) - { - order.push_back(i_inv); - } - } return; - } for (int i_inv = inv_start; i_inv < ENDOFPACK; i_inv++) { @@ -533,6 +520,8 @@ static bool _item_matches(const item_def &item, fire_type types, return true; if ((types & FIRE_TOMAHAWK) && item.sub_type == MI_TOMAHAWK) return true; + if ((types & FIRE_DART) && item.sub_type == MI_DART) + return true; if (types & FIRE_LAUNCHER) { @@ -589,8 +578,6 @@ static ammo_t _get_weapon_ammo_type(const item_def* weapon) switch (weapon->sub_type) { - case WPN_BLOWGUN: - return AMMO_BLOWGUN; case WPN_HUNTING_SLING: case WPN_FUSTIBALUS: return AMMO_SLING; diff --git a/crawl-ref/source/quiver.h b/crawl-ref/source/quiver.h index cb506f0f5045..674341f75d69 100644 --- a/crawl-ref/source/quiver.h +++ b/crawl-ref/source/quiver.h @@ -18,7 +18,9 @@ enum ammo_t AMMO_SLING, // wielded sling -> stones, sling bullets AMMO_CROSSBOW, // wielded crossbow -> bolts // Used to be hand crossbows +#if TAG_MAJOR_VERSION == 34 AMMO_BLOWGUN, // wielded blowgun -> needles +#endif NUM_AMMO }; diff --git a/crawl-ref/source/ranged-attack.cc b/crawl-ref/source/ranged-attack.cc index a1114b8cb8aa..34da34698700 100644 --- a/crawl-ref/source/ranged-attack.cc +++ b/crawl-ref/source/ranged-attack.cc @@ -272,9 +272,9 @@ bool ranged_attack::handle_phase_hit() if (!is_penetrating_attack(*attacker, weapon, *projectile)) range_used = BEAM_STOP; - if (projectile->is_type(OBJ_MISSILES, MI_NEEDLE)) + if (projectile->is_type(OBJ_MISSILES, MI_DART)) { - damage_done = blowgun_duration_roll(get_ammo_brand(*projectile)); + damage_done = dart_duration_roll(get_ammo_brand(*projectile)); set_attack_verb(0); announce_hit(); } @@ -290,7 +290,7 @@ bool ranged_attack::handle_phase_hit() else { damage_done = calc_damage(); - if (damage_done > 0 || projectile->is_type(OBJ_MISSILES, MI_NEEDLE)) + if (damage_done > 0 || projectile->is_type(OBJ_MISSILES, MI_DART)) { if (!handle_phase_damaged()) return false; @@ -528,7 +528,7 @@ special_missile_type ranged_attack::random_chaos_missile_brand() return brand; } -bool ranged_attack::blowgun_check(special_missile_type type) +bool ranged_attack::dart_check(special_missile_type type) { if (defender->holiness() & (MH_UNDEAD | MH_NONLIVING)) { @@ -545,13 +545,10 @@ bool ranged_attack::blowgun_check(special_missile_type type) return false; } - const int enchantment = using_weapon() ? weapon->plus : 0; - if (attacker->is_monster()) { int chance = 85 - ((defender->get_hit_dice() - attacker->get_hit_dice()) * 5 / 2); - chance += enchantment * 4; chance = min(95, chance); if (type == SPMSL_FRENZY) @@ -562,14 +559,14 @@ bool ranged_attack::blowgun_check(special_missile_type type) return x_chance_in_y(chance, 100); } - const int skill = you.skill_rdiv(SK_THROWING); + const int pow = (2 * (you.skill_rdiv(SK_THROWING) + + you.skill_rdiv(SK_STEALTH))) / 3; - // You have a really minor chance of hitting with no skills or good - // enchants. + // You have a really minor chance of hitting weak things no matter what if (defender->get_hit_dice() < 15 && random2(100) <= 2) return true; - const int resist_roll = 2 + random2(4 + skill + enchantment); + const int resist_roll = 2 + random2(4 + pow); dprf(DIAG_COMBAT, "Brand rolled %d against defender HD: %d.", resist_roll, defender->get_hit_dice()); @@ -590,7 +587,7 @@ bool ranged_attack::blowgun_check(special_missile_type type) } -int ranged_attack::blowgun_duration_roll(special_missile_type type) +int ranged_attack::dart_duration_roll(special_missile_type type) { // Leaving monster poison the same by separating it from player poison if (type == SPMSL_POISONED && attacker->is_monster()) @@ -603,9 +600,7 @@ int ranged_attack::blowgun_duration_roll(special_missile_type type) ? attacker->get_hit_dice() : attacker->skill_rdiv(SK_THROWING); - const int plus = using_weapon() ? weapon->plus : 0; - - // Scale down nastier needle effects against players. + // Scale down nastier dart effects against players. // Fixed duration regardless of power, since power already affects success // chance considerably, and this helps avoid effects being too nasty from // high HD shooters and too ignorable from low ones. @@ -624,9 +619,9 @@ int ranged_attack::blowgun_duration_roll(special_missile_type type) } } else if (type == SPMSL_POISONED) // Player poison needles - return random2(3 + base_power * 2 + plus); + return random2(3 + base_power * 2); else - return 5 + random2(base_power + plus); + return 5 + random2(base_power); } bool ranged_attack::apply_missile_brand() @@ -658,8 +653,7 @@ bool ranged_attack::apply_missile_brand() defender->expose_to_element(BEAM_COLD, 2); break; case SPMSL_POISONED: - if (projectile->is_type(OBJ_MISSILES, MI_NEEDLE) - && using_weapon() + if (projectile->is_type(OBJ_MISSILES, MI_DART) && damage_done > 0 || !one_chance_in(4)) { @@ -674,7 +668,7 @@ bool ranged_attack::apply_missile_brand() } defender->poison(attacker, - projectile->is_type(OBJ_MISSILES, MI_NEEDLE) + projectile->is_type(OBJ_MISSILES, MI_DART) ? damage_done : 6 + random2(8) + random2(damage_done * 3 / 2)); @@ -732,23 +726,23 @@ bool ranged_attack::apply_missile_brand() special_damage_message); break; case SPMSL_PARALYSIS: - if (!blowgun_check(brand)) + if (!dart_check(brand)) break; defender->paralyse(attacker, damage_done); break; case SPMSL_SLEEP: - if (!blowgun_check(brand)) + if (!dart_check(brand)) break; defender->put_to_sleep(attacker, damage_done); should_alert_defender = false; break; case SPMSL_CONFUSION: - if (!blowgun_check(brand)) + if (!dart_check(brand)) break; defender->confuse(attacker, damage_done); break; case SPMSL_FRENZY: - if (!blowgun_check(brand)) + if (!dart_check(brand)) break; if (defender->is_monster()) { diff --git a/crawl-ref/source/ranged-attack.h b/crawl-ref/source/ranged-attack.h index bd6f37247064..b6fc740b3032 100644 --- a/crawl-ref/source/ranged-attack.h +++ b/crawl-ref/source/ranged-attack.h @@ -35,8 +35,8 @@ class ranged_attack : public attack int apply_damage_modifiers(int damage, int damage_max) override; bool apply_damage_brand(const char *what = nullptr) override; special_missile_type random_chaos_missile_brand(); - bool blowgun_check(special_missile_type type); - int blowgun_duration_roll(special_missile_type type); + bool dart_check(special_missile_type type); + int dart_duration_roll(special_missile_type type); bool apply_missile_brand(); /* Weapon Effects */ diff --git a/crawl-ref/source/rltiles/dc-item.txt b/crawl-ref/source/rltiles/dc-item.txt index 5b3c2b0d7d84..480dc47c536f 100644 --- a/crawl-ref/source/rltiles/dc-item.txt +++ b/crawl-ref/source/rltiles/dc-item.txt @@ -293,19 +293,19 @@ effect/tomahawk6 MI_TOMAHAWK6 effect/tomahawk7 MI_TOMAHAWK7 %rim 1 -needle1 MI_NEEDLE +needle1 MI_DART needle2 -needle-p MI_NEEDLE_P -needle-c MI_NEEDLE_CURARE +needle-p MI_DART_P +needle-c MI_DART_CURARE # flying needles -effect/needle0 MI_NEEDLE0 -effect/needle1 MI_NEEDLE1 -effect/needle2 MI_NEEDLE2 -effect/needle3 MI_NEEDLE3 -effect/needle4 MI_NEEDLE4 -effect/needle5 MI_NEEDLE5 -effect/needle6 MI_NEEDLE6 -effect/needle7 MI_NEEDLE7 +effect/needle0 MI_DART0 +effect/needle1 MI_DART1 +effect/needle2 MI_DART2 +effect/needle3 MI_DART3 +effect/needle4 MI_DART4 +effect/needle5 MI_DART5 +effect/needle6 MI_DART6 +effect/needle7 MI_DART7 %rim 0 javelin1 MI_JAVELIN diff --git a/crawl-ref/source/throw.cc b/crawl-ref/source/throw.cc index 945e1a0f1093..d1804a97cf27 100644 --- a/crawl-ref/source/throw.cc +++ b/crawl-ref/source/throw.cc @@ -51,7 +51,7 @@ static int _fire_prompt_for_item(); static bool _fire_validate_item(int selected, string& err); -static int _get_blowgun_chance(const int hd); +static int _get_dart_chance(const int hd); bool is_penetrating_attack(const actor& attacker, const item_def* weapon, const item_def& projectile) @@ -285,15 +285,15 @@ vector fire_target_behaviour::get_monster_desc(const monster_info& mi) descs.emplace_back("immune to nets"); } - // Display the chance for a needle of para/confuse/sleep/frenzy + // Display the chance for a dart of para/confuse/sleep/frenzy // to affect monster - if (you.weapon() && you.weapon()->is_type(OBJ_WEAPONS, WPN_BLOWGUN)) + if (item->is_type(OBJ_MISSILES, MI_DART)) { special_missile_type brand = get_ammo_brand(*item); if (brand == SPMSL_PARALYSIS || brand == SPMSL_CONFUSION || brand == SPMSL_FRENZY || brand == SPMSL_SLEEP) { - int chance = _get_blowgun_chance(mi.hd); + int chance = _get_dart_chance(mi.hd); bool immune = false; if (mi.holi & (MH_UNDEAD | MH_NONLIVING)) immune = true; @@ -314,26 +314,26 @@ vector fire_target_behaviour::get_monster_desc(const monster_info& mi) } /** - * Chance for a needle fired by the player to affect a monster of a particular - * hit dice, given the player's throwing skill and blowgun enchantment. + * Chance for a dart fired by the player to affect a monster of a particular + * hit dice, given the player's throwing skill. * * @param hd The monster's hit dice. * @return The percentage chance for the player to affect the monster, * rounded down. * - * This chance is rolled in ranged_attack::blowgun_check using this formula for + * This chance is rolled in ranged_attack::dart_check using this formula for * success: * if hd < 15, fixed 3% chance to succeed regardless of roll * else, or if the 3% chance fails, - * succeed if 2 + random2(4 + skill + enchantment) >= hd + * succeed if 2 + random2(4 + (2/3)*(throwing + stealth) ) >= hd */ -static int _get_blowgun_chance(const int hd) +static int _get_dart_chance(const int hd) { ASSERT(you.weapon()->is_type(OBJ_WEAPONS, WPN_BLOWGUN)); - const int plus = you.weapon()->plus; - const int skill = you.skill_rdiv(SK_THROWING); + const int pow = (2 * (you.skill_rdiv(SK_THROWING) + + you.skill_rdiv(SK_STEALTH))) / 3; - int chance = 10000 - 10000 * (hd - 2) / (4 + skill + plus); + int chance = 10000 - 10000 * (hd - 2) / (4 + pow); chance = min(max(chance, 0), 10000); if (hd < 15) { @@ -723,15 +723,11 @@ static void _throw_noise(actor* act, const bolt &pbolt, const item_def &ammo) if (is_launched(act, launcher, ammo) != launch_retval::LAUNCHED) return; - // Throwing and blowguns are silent... int level = 0; const char* msg = nullptr; switch (launcher->sub_type) { - case WPN_BLOWGUN: - return; - case WPN_HUNTING_SLING: level = 1; msg = "You hear a whirring sound."; @@ -1073,7 +1069,7 @@ bool throw_it(bolt &pbolt, int throw_2, dist *target) && projected != launch_retval::FUMBLED && will_have_passive(passive_t::shadow_attacks) && thrown.base_type == OBJ_MISSILES - && thrown.sub_type != MI_NEEDLE) + && thrown.sub_type != MI_DART) { dithmenos_shadow_throw(thr, item); } diff --git a/crawl-ref/source/throw.h b/crawl-ref/source/throw.h index bf2f3db00fd4..d4ff01cccb65 100644 --- a/crawl-ref/source/throw.h +++ b/crawl-ref/source/throw.h @@ -13,9 +13,7 @@ enum fire_type { FIRE_NONE = 0x0000, FIRE_LAUNCHER = 0x0001, -#if TAG_MAJOR_VERSION == 34 FIRE_DART = 0x0002, -#endif FIRE_STONE = 0x0004, FIRE_JAVELIN = 0x0010, FIRE_ROCK = 0x0100, diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc index 3056dd613822..e8f32a5a6d0f 100644 --- a/crawl-ref/source/tilepick.cc +++ b/crawl-ref/source/tilepick.cc @@ -99,8 +99,8 @@ static tileidx_t _tileidx_trap(trap_type type) return TILE_DNGN_TRAP_NET; case TRAP_ZOT: return TILE_DNGN_TRAP_ZOT; - case TRAP_NEEDLE: - return TILE_DNGN_TRAP_NEEDLE; + case TRAP_DART: + return TILE_DNGN_TRAP_DART; case TRAP_SHAFT: return TILE_DNGN_TRAP_SHAFT; case TRAP_GOLUBRIA: @@ -2157,13 +2157,13 @@ static tileidx_t _tileidx_missile_base(const item_def &item) case SPMSL_SILVER: return TILE_MI_TOMAHAWK_SILVER; } - case MI_NEEDLE: + case MI_DART: switch (brand) { - default: return TILE_MI_NEEDLE + 1; - case 0: return TILE_MI_NEEDLE; - case SPMSL_POISONED: return TILE_MI_NEEDLE_P; - case SPMSL_CURARE: return TILE_MI_NEEDLE_CURARE; + default: return TILE_MI_DART + 1; + case 0: return TILE_MI_DART; + case SPMSL_POISONED: return TILE_MI_DART_P; + case SPMSL_CURARE: return TILE_MI_DART_CURARE; } case MI_ARROW: @@ -2739,8 +2739,8 @@ tileidx_t tileidx_item_throw(const item_def &item, int dx, int dy) case MI_BOLT: ch = TILE_MI_BOLT0; break; - case MI_NEEDLE: - ch = TILE_MI_NEEDLE0; + case MI_DART: + ch = TILE_MI_DART0; break; case MI_JAVELIN: ch = TILE_MI_JAVELIN0; diff --git a/crawl-ref/source/trap-type.h b/crawl-ref/source/trap-type.h index 2c0a7c43c44c..919722ebe288 100644 --- a/crawl-ref/source/trap-type.h +++ b/crawl-ref/source/trap-type.h @@ -2,9 +2,7 @@ enum trap_type { -#if TAG_MAJOR_VERSION == 34 TRAP_DART, -#endif TRAP_ARROW, TRAP_SPEAR, #if TAG_MAJOR_VERSION > 34 @@ -17,7 +15,9 @@ enum trap_type TRAP_BOLT, TRAP_NET, TRAP_ZOT, +#if TAG_MAJOR_VERSION == 34 TRAP_NEEDLE, +#endif TRAP_SHAFT, TRAP_GOLUBRIA, TRAP_PLATE, diff --git a/crawl-ref/source/traps.cc b/crawl-ref/source/traps.cc index 4de6be8db99d..a93e4e0dd0ff 100644 --- a/crawl-ref/source/traps.cc +++ b/crawl-ref/source/traps.cc @@ -64,10 +64,10 @@ bool trap_def::type_has_ammo() const switch (type) { #if TAG_MAJOR_VERSION == 34 - case TRAP_DART: + case TRAP_NEEDLE: #endif case TRAP_ARROW: case TRAP_BOLT: - case TRAP_NEEDLE: case TRAP_SPEAR: + case TRAP_DART: case TRAP_SPEAR: return true; default: break; @@ -102,7 +102,7 @@ void trap_def::prepare_ammo(int charges) { case TRAP_ARROW: case TRAP_BOLT: - case TRAP_NEEDLE: + case TRAP_DART: ammo_qty = 3 + random2avg(9, 3); break; case TRAP_SPEAR: @@ -188,7 +188,7 @@ bool trap_def::is_safe(actor* act) const return true; #endif - if (type == TRAP_NEEDLE) + if (type == TRAP_DART) return you.hp > 15; else if (type == TRAP_ARROW) return you.hp > 35; @@ -850,7 +850,7 @@ int trap_def::max_damage(const actor& act) switch (type) { - case TRAP_NEEDLE: return 0; + case TRAP_DART: return 0; case TRAP_ARROW: return mon ? 7 : 15; case TRAP_SPEAR: return mon ? 10 : 26; case TRAP_BOLT: return mon ? 18 : 40; @@ -883,7 +883,7 @@ int trap_def::to_hit_bonus() return 15; case TRAP_NET: return 5; - case TRAP_NEEDLE: + case TRAP_DART: return 8; // Irrelevant: default: @@ -1096,12 +1096,12 @@ item_def trap_def::generate_trap_item() switch (type) { #if TAG_MAJOR_VERSION == 34 - case TRAP_DART: base = OBJ_MISSILES; sub = MI_DART; break; + case TRAP_NEEDLE: base = OBJ_MISSILES; sub = MI_NEEDLE; break; #endif case TRAP_ARROW: base = OBJ_MISSILES; sub = MI_ARROW; break; case TRAP_BOLT: base = OBJ_MISSILES; sub = MI_BOLT; break; case TRAP_SPEAR: base = OBJ_WEAPONS; sub = WPN_SPEAR; break; - case TRAP_NEEDLE: base = OBJ_MISSILES; sub = MI_NEEDLE; break; + case TRAP_DART: base = OBJ_MISSILES; sub = MI_DART; break; case TRAP_NET: base = OBJ_MISSILES; sub = MI_THROWING_NET; break; default: return item; } @@ -1113,7 +1113,7 @@ item_def trap_def::generate_trap_item() if (base == OBJ_MISSILES) { set_item_ego_type(item, base, - (sub == MI_NEEDLE) ? SPMSL_POISONED : SPMSL_NORMAL); + (sub == MI_DART) ? SPMSL_POISONED : SPMSL_NORMAL); } else set_item_ego_type(item, base, SPWPN_NORMAL); @@ -1195,7 +1195,7 @@ void trap_def::shoot_ammo(actor& act, bool was_known) } else // OK, we've been hit. { - bool poison = type == TRAP_NEEDLE + bool poison = type == TRAP_DART && (x_chance_in_y(50 - (3*act.armour_class()) / 2, 100)); int damage_taken = act.apply_ac(shot_damage(act)); @@ -1266,12 +1266,12 @@ dungeon_feature_type trap_category(trap_type type) case TRAP_ARROW: case TRAP_SPEAR: case TRAP_BLADE: + case TRAP_DART: case TRAP_BOLT: - case TRAP_NEEDLE: case TRAP_NET: #if TAG_MAJOR_VERSION == 34 + case TRAP_NEEDLE: case TRAP_GAS: - case TRAP_DART: #endif case TRAP_PLATE: return DNGN_TRAP_MECHANICAL; @@ -1497,7 +1497,7 @@ trap_type random_vault_trap() trap_type type = TRAP_ARROW; if ((random2(1 + level_number) > 1) && one_chance_in(4)) - type = TRAP_NEEDLE; + type = TRAP_DART; if (random2(1 + level_number) > 3) type = TRAP_SPEAR; diff --git a/crawl-ref/source/xom.cc b/crawl-ref/source/xom.cc index e966d40f6851..9cc869a0e973 100644 --- a/crawl-ref/source/xom.cc +++ b/crawl-ref/source/xom.cc @@ -1271,7 +1271,7 @@ static int _xom_random_stickable(const int HD) { WPN_CLUB, WPN_SPEAR, WPN_TRIDENT, WPN_HALBERD, WPN_SCYTHE, WPN_GLAIVE, WPN_QUARTERSTAFF, - WPN_BLOWGUN, WPN_SHORTBOW, WPN_LONGBOW, WPN_GIANT_CLUB, + WPN_SHORTBOW, WPN_LONGBOW, WPN_GIANT_CLUB, WPN_GIANT_SPIKED_CLUB }; From 9adfa933843a578340473aada8e3211cbd279b40 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Wed, 8 May 2019 23:33:03 -0400 Subject: [PATCH 293/864] Throwing Overhaul II: Darts brand consolidation The hex darts (paralysis, confuse, and sleep) are redundant in several ways: mutually as a way for needles to generate stabs, with hexes, and with wands. The result is a clutter of darts. This commit removes these brands, replacing them with a single new brand: blinding. In addition to blinding the target for a long duration (depending on throwing skill) this brand also confuses the target for a shorter duration. The effect was chosen to be distinct from hexes (compared to dazzling spray's 4-8 turn blindness and invisibility) and hex wands. --- crawl-ref/source/beam.cc | 6 -- crawl-ref/source/dat/des/branches/abyss.des | 2 +- .../source/dat/des/sprint/arena_sprint.des | 4 +- crawl-ref/source/dat/des/sprint/sprint_mu.des | 3 +- .../source/dat/des/variable/mini_monsters.des | 4 +- crawl-ref/source/describe.cc | 18 ++---- crawl-ref/source/item-name.cc | 9 +-- crawl-ref/source/item-prop-enum.h | 8 +-- crawl-ref/source/items.cc | 1 - crawl-ref/source/makeitem.cc | 12 +--- crawl-ref/source/mapdef.cc | 5 +- crawl-ref/source/mon-util.cc | 8 +-- crawl-ref/source/ranged-attack.cc | 59 +++++------------- crawl-ref/source/rltiles/dc-item.txt | 5 +- .../rltiles/item/weapon/brands/i-blinding.png | Bin 0 -> 983 bytes crawl-ref/source/shopping.cc | 5 +- crawl-ref/source/throw.cc | 8 +-- crawl-ref/source/tilepick.cc | 8 ++- 18 files changed, 50 insertions(+), 115 deletions(-) create mode 100644 crawl-ref/source/rltiles/item/weapon/brands/i-blinding.png diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc index 49e7b7cf9809..33484d4ab32d 100644 --- a/crawl-ref/source/beam.cc +++ b/crawl-ref/source/beam.cc @@ -4423,7 +4423,6 @@ void bolt::monster_post_hit(monster* mon, int dmg) // did no damage. Hostiles will still take umbrage. if (dmg > 0 || !mon->wont_attack() || !YOU_KILL(thrower)) { - bool was_asleep = mon->asleep(); special_missile_type m_brand = SPMSL_FORBID_BRAND; if (item && item->base_type == OBJ_MISSILES) m_brand = get_ammo_brand(*item); @@ -4436,11 +4435,6 @@ void bolt::monster_post_hit(monster* mon, int dmg) if (!mon->alive()) return; } - - - // Don't allow darts of sleeping to awaken monsters. - if (m_brand == SPMSL_SLEEP && was_asleep && !mon->asleep()) - mon->put_to_sleep(agent(), 0); } if (YOU_KILL(thrower) && !mon->wont_attack() && !mons_is_firewood(*mon)) diff --git a/crawl-ref/source/dat/des/branches/abyss.des b/crawl-ref/source/dat/des/branches/abyss.des index 63014768d32f..dda855ba5613 100644 --- a/crawl-ref/source/dat/des/branches/abyss.des +++ b/crawl-ref/source/dat/des/branches/abyss.des @@ -1459,7 +1459,7 @@ KMONS: 6 = lurking horror # Note: if anything in these two item sets becomes useful for more then a tiny # fraction of characters finding the abyssal rune, remove or replace them. KITEM: 4d = scroll of random uselessness w:15 q:1 / ration w:1 / \ - club w:6 / stone q:1 / dart q:1 ego:confusion / \ + club w:6 / stone q:1 / dart q:1 ego:blind / \ mundane animal skin / mundane ring mail / gold q:1 KITEM: 5 = wand of random effects / wand of flame / whip not_cursed w:2 / \ hat not_cursed mundane w:5 diff --git a/crawl-ref/source/dat/des/sprint/arena_sprint.des b/crawl-ref/source/dat/des/sprint/arena_sprint.des index d2528a593f19..a5b01f91fa8a 100644 --- a/crawl-ref/source/dat/des/sprint/arena_sprint.des +++ b/crawl-ref/source/dat/des/sprint/arena_sprint.des @@ -437,7 +437,7 @@ function arena_sprint_get_monster_set(round, boss) "moth of wrath / w:20 stone giant", "ball lightning", "orb spider", "hungry ghost / harpy", "shining eye", "tormentor", - "skeletal warrior / w:5 skeletal warrior ; dart ego:confusion" + "skeletal warrior / w:5 skeletal warrior ; dart ego:blind" } elseif round <= 26 then mon_set = { @@ -503,7 +503,7 @@ function arena_sprint_get_monster_set(round, boss) "neqoxec", "smoke demon", "catoblepas", "moth of wrath / w:20 ettin", "orb spider", "fire crab", "shining eye", "tormentor", "tentacled monstrosity", - "skeletal warrior / skeletal warrior ; dart ego:confusion", + "skeletal warrior / skeletal warrior ; dart ego:blind", "unseen horror / lorocyproca / shadow wraith / ghost moth", "curse toe / w:20 wandering mushroom / w:4 murray", "reaper / hell beast / geryon w:1", diff --git a/crawl-ref/source/dat/des/sprint/sprint_mu.des b/crawl-ref/source/dat/des/sprint/sprint_mu.des index 87dc53b592f0..a530a4d512bc 100644 --- a/crawl-ref/source/dat/des/sprint/sprint_mu.des +++ b/crawl-ref/source/dat/des/sprint/sprint_mu.des @@ -513,8 +513,7 @@ KMONS: g = tyrant leech KMONS: A = lindwurm KMONS: h = redback KMONS: i = hydra -KMONS: j = patrolling spriggan ; q:5 dart ego:sleep | \ - q:5 dart ego:paralysis | q:5 dart ego:frenzy +KMONS: j = patrolling spriggan ; q:5 dart ego:blind | q:5 dart ego:frenzy KMONS: k = patrolling spriggan druid KMONS: q = electric eel KFEAT: q = deep_water diff --git a/crawl-ref/source/dat/des/variable/mini_monsters.des b/crawl-ref/source/dat/des/variable/mini_monsters.des index b05474a648ba..3b17951a8b97 100644 --- a/crawl-ref/source/dat/des/variable/mini_monsters.des +++ b/crawl-ref/source/dat/des/variable/mini_monsters.des @@ -886,7 +886,7 @@ KMASK: 'f = opaque : if crawl.coinflip() then KITEM: f = javelin ego:poisoned q:4-6 / tomahawk ego:poisoned : else -KITEM: f = dart ego:poisoned / dart ego:curare / dart ego:paralysis +KITEM: f = dart ego:poisoned / dart ego:curare / dart ego:blind : end KITEM: g = any potion q:2-3 MONS: plant, oklob sapling, ball python @@ -941,7 +941,7 @@ ITEM: Young Poisoner's Handbook / book of Changes / \ : if crawl.coinflip() then KITEM: f = javelin ego:poisoned q:4-6 / tomahawk ego:poisoned : else -KITEM: f = dart ego:poisoned / dart ego:curare / dart ego:paralysis +KITEM: f = dart ego:poisoned / dart ego:curare / dart ego:blind : end KITEM: g = any potion q:2 / any potion q:3 MONS: plant, oklob sapling, ball python diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index acabcb589def..54d824fc8587 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -1489,25 +1489,15 @@ static string _describe_ammo(const item_def &item) "It is twice as likely to be destroyed on impact as " "other darts."; break; - case SPMSL_PARALYSIS: - description += "It is tipped with a paralysing substance."; - break; - case SPMSL_SLEEP: - description += "It is coated with a fast-acting tranquilizer."; - break; - case SPMSL_CONFUSION: - description += "It is tipped with a substance that causes confusion."; - break; -#if TAG_MAJOR_VERSION == 34 - case SPMSL_SICKNESS: - description += "It has been contaminated by something likely to cause disease."; - break; -#endif case SPMSL_FRENZY: description += "It is tipped with a substance that sends those it " "hits into a mindless rage, attacking friend and " "foe alike."; break; + case SPMSL_BLINDING: + description += "It is tipped with a substance that causes " + "blindness and brief confusion."; + break; case SPMSL_RETURNING: description += "A skilled user can throw it in such a way that it " "will return to its owner."; diff --git a/crawl-ref/source/item-name.cc b/crawl-ref/source/item-name.cc index 7e3246598954..836b11cf088c 100644 --- a/crawl-ref/source/item-name.cc +++ b/crawl-ref/source/item-name.cc @@ -371,17 +371,15 @@ const char* missile_brand_name(const item_def &item, mbn_type t) return "steel"; case SPMSL_SILVER: return "silver"; +#if TAG_MAJOR_VERSION == 34 case SPMSL_PARALYSIS: return "paralysis"; -#if TAG_MAJOR_VERSION == 34 case SPMSL_SLOW: return t == MBN_TERSE ? "slow" : "slowing"; -#endif case SPMSL_SLEEP: return t == MBN_TERSE ? "sleep" : "sleeping"; case SPMSL_CONFUSION: return t == MBN_TERSE ? "conf" : "confusion"; -#if TAG_MAJOR_VERSION == 34 case SPMSL_SICKNESS: return t == MBN_TERSE ? "sick" : "sickness"; #endif @@ -395,10 +393,8 @@ const char* missile_brand_name(const item_def &item, mbn_type t) return t == MBN_TERSE ? "penet" : "penetration"; case SPMSL_DISPERSAL: return t == MBN_TERSE ? "disperse" : "dispersal"; -#if TAG_MAJOR_VERSION == 34 case SPMSL_BLINDING: return t == MBN_TERSE ? "blind" : "blinding"; -#endif case SPMSL_NORMAL: return ""; default: @@ -1627,9 +1623,6 @@ string item_def::name_aux(description_level_type desc, bool terse, bool ident, buff << ammo_name(static_cast(item_typ)); if (msl_brand != SPMSL_NORMAL -#if TAG_MAJOR_VERSION == 34 - && msl_brand != SPMSL_BLINDING -#endif && !basename && !dbname) { if (terse) diff --git a/crawl-ref/source/item-prop-enum.h b/crawl-ref/source/item-prop-enum.h index caf6007cc63c..45f3ca11bb2d 100644 --- a/crawl-ref/source/item-prop-enum.h +++ b/crawl-ref/source/item-prop-enum.h @@ -467,19 +467,17 @@ enum special_missile_type // to separate from weapons in general {dlb} SPMSL_EXPLODING, SPMSL_STEEL, SPMSL_SILVER, - SPMSL_PARALYSIS, // dart only from here on #if TAG_MAJOR_VERSION == 34 + SPMSL_PARALYSIS, // dart only from here on SPMSL_SLOW, -#endif SPMSL_SLEEP, SPMSL_CONFUSION, -#if TAG_MAJOR_VERSION == 34 SPMSL_SICKNESS, #endif SPMSL_FRENZY, - NUM_REAL_SPECIAL_MISSILES, SPMSL_BLINDING, - NUM_SPECIAL_MISSILES, + NUM_REAL_SPECIAL_MISSILES, + NUM_SPECIAL_MISSILES = NUM_REAL_SPECIAL_MISSILES, }; enum special_ring_type // jewellery mitm[].special values diff --git a/crawl-ref/source/items.cc b/crawl-ref/source/items.cc index 60705162c019..d0f8d7890573 100644 --- a/crawl-ref/source/items.cc +++ b/crawl-ref/source/items.cc @@ -3519,7 +3519,6 @@ colour_t item_def::missile_colour() const case MI_TOMAHAWK: return GREEN; case NUM_SPECIAL_MISSILES: - case NUM_REAL_SPECIAL_MISSILES: default: die("invalid missile type"); } diff --git a/crawl-ref/source/makeitem.cc b/crawl-ref/source/makeitem.cc index 7a32c7c356e2..670db0082b7d 100644 --- a/crawl-ref/source/makeitem.cc +++ b/crawl-ref/source/makeitem.cc @@ -535,10 +535,8 @@ static special_missile_type _determine_missile_brand(const item_def& item, break; } - rc = random_choose_weighted(30, SPMSL_SLEEP, - 30, SPMSL_CONFUSION, - 10, SPMSL_PARALYSIS, - 10, SPMSL_FRENZY, + rc = random_choose_weighted(60, SPMSL_BLINDING, + 30, SPMSL_FRENZY, nw, SPMSL_POISONED); break; case MI_JAVELIN: @@ -596,20 +594,16 @@ bool is_missile_brand_ok(int type, int brand, bool strict) case SPMSL_PARALYSIS: #if TAG_MAJOR_VERSION == 34 case SPMSL_SLOW: -#endif case SPMSL_SLEEP: case SPMSL_CONFUSION: -#if TAG_MAJOR_VERSION == 34 case SPMSL_SICKNESS: #endif case SPMSL_FRENZY: return type == MI_DART; -#if TAG_MAJOR_VERSION == 34 case SPMSL_BLINDING: // possible on ex-pies - return type == MI_TOMAHAWK && !strict; -#endif + return type == MI_DART || (type == MI_TOMAHAWK && !strict); default: if (type == MI_DART) diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc index 90f8248661d1..cf9ad4a8e961 100644 --- a/crawl-ref/source/mapdef.cc +++ b/crawl-ref/source/mapdef.cc @@ -4950,16 +4950,15 @@ int str_to_ego(object_class_type item_type, string ego_str) "exploding", "steel", "silver", - "paralysis", #if TAG_MAJOR_VERSION == 34 + "paralysis", "slow", -#endif "sleep", "confusion", -#if TAG_MAJOR_VERSION == 34 "sickness", #endif "frenzy", + "blind", nullptr }; COMPILE_CHECK(ARRAYSZ(missile_brands) == NUM_REAL_SPECIAL_MISSILES); diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index 7c2703c949a4..442286618295 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -3903,13 +3903,11 @@ bool mons_has_incapacitating_ranged_attack(const monster& mon, const actor& foe) return true; break; - case SPMSL_SLEEP: - if (foe.can_sleep()) - return true; - break; - + case SPMSL_BLINDING: +#if TAG_MAJOR_VERSION == 34 case SPMSL_CONFUSION: case SPMSL_PARALYSIS: +#endif return true; default: diff --git a/crawl-ref/source/ranged-attack.cc b/crawl-ref/source/ranged-attack.cc index 34da34698700..e98774b3e06b 100644 --- a/crawl-ref/source/ranged-attack.cc +++ b/crawl-ref/source/ranged-attack.cc @@ -445,11 +445,9 @@ special_missile_type ranged_attack::random_chaos_missile_brand() 10, SPMSL_FROST, 10, SPMSL_POISONED, 10, SPMSL_CHAOS, - 5, SPMSL_PARALYSIS, - 5, SPMSL_SLEEP, + 10, SPMSL_BLINDING, 5, SPMSL_FRENZY, 2, SPMSL_CURARE, - 2, SPMSL_CONFUSION, 2, SPMSL_DISPERSAL)); if (one_chance_in(3)) @@ -474,18 +472,6 @@ special_missile_type ranged_attack::random_chaos_missile_brand() if (defender->no_tele(true, false, true)) susceptible = false; break; - case SPMSL_CONFUSION: - if (defender->holiness() & MH_PLANT) - { - susceptible = false; - break; - } - // fall through - case SPMSL_SLEEP: - case SPMSL_PARALYSIS: - if (defender->holiness() & (MH_UNDEAD | MH_NONLIVING)) - susceptible = false; - break; case SPMSL_FRENZY: if (defender->holiness() & (MH_UNDEAD | MH_NONLIVING) || defender->is_player() @@ -514,9 +500,8 @@ special_missile_type ranged_attack::random_chaos_missile_brand() case SPMSL_CURARE: brand_name += "curare"; break; case SPMSL_CHAOS: brand_name += "chaos"; break; case SPMSL_DISPERSAL: brand_name += "dispersal"; break; - case SPMSL_SLEEP: brand_name += "sleep"; break; - case SPMSL_CONFUSION: brand_name += "confusion"; break; case SPMSL_FRENZY: brand_name += "frenzy"; break; + case SPMSL_BLINDING: brand_name += "blinding"; break; default: brand_name += "(other)"; break; } @@ -553,8 +538,6 @@ bool ranged_attack::dart_check(special_missile_type type) if (type == SPMSL_FRENZY) chance = chance / 2; - else if (type == SPMSL_PARALYSIS || type == SPMSL_SLEEP) - chance = chance * 4 / 5; return x_chance_in_y(chance, 100); } @@ -605,19 +588,7 @@ int ranged_attack::dart_duration_roll(special_missile_type type) // chance considerably, and this helps avoid effects being too nasty from // high HD shooters and too ignorable from low ones. if (defender->is_player()) - { - switch (type) - { - case SPMSL_PARALYSIS: - return 3 + random2(4); - case SPMSL_SLEEP: - return 5 + random2(5); - case SPMSL_CONFUSION: - return 2 + random2(4); - default: - return 5 + random2(5); - } - } + return 5 + random2(5); else if (type == SPMSL_POISONED) // Player poison needles return random2(3 + base_power * 2); else @@ -725,21 +696,19 @@ bool ranged_attack::apply_missile_brand() special_damage = silver_damages_victim(defender, damage_done, special_damage_message); break; - case SPMSL_PARALYSIS: + case SPMSL_BLINDING: if (!dart_check(brand)) break; - defender->paralyse(attacker, damage_done); - break; - case SPMSL_SLEEP: - if (!dart_check(brand)) - break; - defender->put_to_sleep(attacker, damage_done); - should_alert_defender = false; - break; - case SPMSL_CONFUSION: - if (!dart_check(brand)) - break; - defender->confuse(attacker, damage_done); + if (defender->is_monster()) + { + monster* mon = defender->as_monster(); + if (mons_can_be_blinded(mon->type)) + { + mon->add_ench(mon_enchant(ENCH_BLIND, 1, attacker, + damage_done * BASELINE_DELAY)); + } + } + defender->confuse(attacker, damage_done / 3); break; case SPMSL_FRENZY: if (!dart_check(brand)) diff --git a/crawl-ref/source/rltiles/dc-item.txt b/crawl-ref/source/rltiles/dc-item.txt index 480dc47c536f..531a3498b977 100644 --- a/crawl-ref/source/rltiles/dc-item.txt +++ b/crawl-ref/source/rltiles/dc-item.txt @@ -207,7 +207,7 @@ i-returning BRAND_RETURNING i-chaos BRAND_CHAOS # Remove evasion when TAG_MAJOR_VERSION > 34 i-evasion BRAND_EVASION -# Move i-confusion down to missile-only brands when TAG_MAJOR_VERSION > 34 +# Remove confusion down when TAG_MAJOR_VERSION > 34 i-confusion BRAND_CONFUSION i-penetration BRAND_PENETRATION i-reaping BRAND_REAPING BRAND_WEP_LAST @@ -217,12 +217,13 @@ i-explosion BRAND_EXPLOSION i-venom BRAND_POISONED i-curare BRAND_CURARE i-electrocution BRAND_ELECTRIC -# Remove sickness and slowing when TAG_MAJOR_VERSION > 34 +# Remove sickness, slowingr, paralysis, and sleep when TAG_MAJOR_VERSION > 34 i-sickness BRAND_SICKNESS i-slowing BRAND_SLOWING i-paralysis BRAND_PARALYSIS i-frenzy BRAND_FRENZY i-sleep BRAND_SLEEP +i-blinding BRAND_BLINDING %rim 1 %sdir item/weapon/ranged diff --git a/crawl-ref/source/rltiles/item/weapon/brands/i-blinding.png b/crawl-ref/source/rltiles/item/weapon/brands/i-blinding.png new file mode 100644 index 0000000000000000000000000000000000000000..e2299989653c785341e8291bd93af68e6eaf7e1c GIT binary patch literal 983 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy93=&Q?(RM=#y~cMSA(WJkYY)9 z^mSxl*x1kgCy|wbftew|C&cyt|NlU#moHx)uz!%DFd3wL6pV(zhzWsdtGSJUo@Gq( zc6a%|l>O6D5T_)_FPOpM*^M+HC&bgmF{EP7+X;qz4u%{~+(rM5!(V@y++RI;Q%Qx$ z#jW$^=?NJuXjx#)Fi~p9A|Z|B6YoV2R`H5E_3->E-O{+J&A7?-*i?blDLW=@{U2HU dpjKnK{;eei3^xz0KE4(d%$}}(F6*2UngGN!Pg4K@ literal 0 HcmV?d00001 diff --git a/crawl-ref/source/shopping.cc b/crawl-ref/source/shopping.cc index ff7ca565068a..4b4575841498 100644 --- a/crawl-ref/source/shopping.cc +++ b/crawl-ref/source/shopping.cc @@ -295,7 +295,10 @@ unsigned int item_value(item_def item, bool ident) break; case SPMSL_CURARE: + case SPMSL_BLINDING: +#if TAG_MAJOR_VERSION == 34 case SPMSL_PARALYSIS: +#endif case SPMSL_PENETRATION: case SPMSL_SILVER: case SPMSL_STEEL: @@ -306,11 +309,11 @@ unsigned int item_value(item_def item, bool ident) #if TAG_MAJOR_VERSION == 34 case SPMSL_FLAME: case SPMSL_FROST: -#endif case SPMSL_SLEEP: case SPMSL_CONFUSION: valued *= 25; break; +#endif case SPMSL_EXPLODING: case SPMSL_POISONED: diff --git a/crawl-ref/source/throw.cc b/crawl-ref/source/throw.cc index d1804a97cf27..6a77ed82771c 100644 --- a/crawl-ref/source/throw.cc +++ b/crawl-ref/source/throw.cc @@ -290,18 +290,14 @@ vector fire_target_behaviour::get_monster_desc(const monster_info& mi) if (item->is_type(OBJ_MISSILES, MI_DART)) { special_missile_type brand = get_ammo_brand(*item); - if (brand == SPMSL_PARALYSIS || brand == SPMSL_CONFUSION - || brand == SPMSL_FRENZY || brand == SPMSL_SLEEP) + if (brand == SPMSL_FRENZY || brand == SPMSL_BLINDING) { int chance = _get_dart_chance(mi.hd); bool immune = false; if (mi.holi & (MH_UNDEAD | MH_NONLIVING)) immune = true; - string verb = brand == SPMSL_PARALYSIS ? "paralyse" : - brand == SPMSL_CONFUSION ? "confuse" : - brand == SPMSL_FRENZY ? "frenzy" - /* SPMSL_SLEEP */ : "sleep"; + string verb = brand == SPMSL_FRENZY ? "frenzy" : "blind"; string chance_string = immune ? "immune to needles" : make_stringf("chance to %s on hit: %d%%", diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc index e8f32a5a6d0f..a70d6f5517a7 100644 --- a/crawl-ref/source/tilepick.cc +++ b/crawl-ref/source/tilepick.cc @@ -3764,20 +3764,22 @@ tileidx_t tileidx_known_brand(const item_def &item) return TILE_BRAND_DISPERSAL; case SPMSL_EXPLODING: return TILE_BRAND_EXPLOSION; +#if TAG_MAJOR_VERSION == 34 case SPMSL_CONFUSION: return TILE_BRAND_CONFUSION; case SPMSL_PARALYSIS: return TILE_BRAND_PARALYSIS; -#if TAG_MAJOR_VERSION == 34 case SPMSL_SLOW: return TILE_BRAND_SLOWING; case SPMSL_SICKNESS: return TILE_BRAND_SICKNESS; + case SPMSL_SLEEP: + return TILE_BRAND_SLEEP; #endif case SPMSL_FRENZY: return TILE_BRAND_FRENZY; - case SPMSL_SLEEP: - return TILE_BRAND_SLEEP; + case SPMSL_BLINDING: + return TILE_BRAND_BLINDING; default: break; } From a4302a11a93edbea06690b9849cf206a8066bf9a Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Wed, 8 May 2019 23:49:58 -0400 Subject: [PATCH 294/864] New dart tiles (CanOfWorms) --- .../weapon/ranged => UNUSED/weapons}/needle-c.png | Bin .../weapon/ranged => UNUSED/weapons}/needle-p.png | Bin .../weapon/ranged => UNUSED/weapons}/needle1.png | Bin .../weapon/ranged => UNUSED/weapons}/needle2.png | Bin crawl-ref/source/rltiles/dc-item.txt | 8 ++++---- .../source/rltiles/item/weapon/ranged/dart-c.png | Bin 0 -> 987 bytes .../source/rltiles/item/weapon/ranged/dart-p.png | Bin 0 -> 986 bytes .../source/rltiles/item/weapon/ranged/dart1.png | Bin 0 -> 981 bytes .../source/rltiles/item/weapon/ranged/dart2.png | Bin 0 -> 985 bytes 9 files changed, 4 insertions(+), 4 deletions(-) rename crawl-ref/source/rltiles/{item/weapon/ranged => UNUSED/weapons}/needle-c.png (100%) rename crawl-ref/source/rltiles/{item/weapon/ranged => UNUSED/weapons}/needle-p.png (100%) rename crawl-ref/source/rltiles/{item/weapon/ranged => UNUSED/weapons}/needle1.png (100%) rename crawl-ref/source/rltiles/{item/weapon/ranged => UNUSED/weapons}/needle2.png (100%) create mode 100644 crawl-ref/source/rltiles/item/weapon/ranged/dart-c.png create mode 100644 crawl-ref/source/rltiles/item/weapon/ranged/dart-p.png create mode 100644 crawl-ref/source/rltiles/item/weapon/ranged/dart1.png create mode 100644 crawl-ref/source/rltiles/item/weapon/ranged/dart2.png diff --git a/crawl-ref/source/rltiles/item/weapon/ranged/needle-c.png b/crawl-ref/source/rltiles/UNUSED/weapons/needle-c.png similarity index 100% rename from crawl-ref/source/rltiles/item/weapon/ranged/needle-c.png rename to crawl-ref/source/rltiles/UNUSED/weapons/needle-c.png diff --git a/crawl-ref/source/rltiles/item/weapon/ranged/needle-p.png b/crawl-ref/source/rltiles/UNUSED/weapons/needle-p.png similarity index 100% rename from crawl-ref/source/rltiles/item/weapon/ranged/needle-p.png rename to crawl-ref/source/rltiles/UNUSED/weapons/needle-p.png diff --git a/crawl-ref/source/rltiles/item/weapon/ranged/needle1.png b/crawl-ref/source/rltiles/UNUSED/weapons/needle1.png similarity index 100% rename from crawl-ref/source/rltiles/item/weapon/ranged/needle1.png rename to crawl-ref/source/rltiles/UNUSED/weapons/needle1.png diff --git a/crawl-ref/source/rltiles/item/weapon/ranged/needle2.png b/crawl-ref/source/rltiles/UNUSED/weapons/needle2.png similarity index 100% rename from crawl-ref/source/rltiles/item/weapon/ranged/needle2.png rename to crawl-ref/source/rltiles/UNUSED/weapons/needle2.png diff --git a/crawl-ref/source/rltiles/dc-item.txt b/crawl-ref/source/rltiles/dc-item.txt index 531a3498b977..c3eed890ca4b 100644 --- a/crawl-ref/source/rltiles/dc-item.txt +++ b/crawl-ref/source/rltiles/dc-item.txt @@ -294,10 +294,10 @@ effect/tomahawk6 MI_TOMAHAWK6 effect/tomahawk7 MI_TOMAHAWK7 %rim 1 -needle1 MI_DART -needle2 -needle-p MI_DART_P -needle-c MI_DART_CURARE +dart1 MI_DART +dart2 +dart-p MI_DART_P +dart-c MI_DART_CURARE # flying needles effect/needle0 MI_DART0 effect/needle1 MI_DART1 diff --git a/crawl-ref/source/rltiles/item/weapon/ranged/dart-c.png b/crawl-ref/source/rltiles/item/weapon/ranged/dart-c.png new file mode 100644 index 0000000000000000000000000000000000000000..8756b842164ebafef968f7c12becaae3bbd772f9 GIT binary patch literal 987 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy93=&Q?(RM=#y~cMSA(WJkYY)9 z^mSxl*x1kgCy|wbftew|C&cyt|NlTKdozoKi0~;*RT~!fDYWRiZ&L^9!wrDybCQ!* z%$$7Y(AG&pLYHkpjv)woqxCklTbj5PnN}|%sCZPtXb8|D1YY{|CIhWuO!9Vj`M;F? z(@_woB*-tA!Qt7BG$1F!)5S5QV$RzO8wD8@Ia~t&XYgKP_;UXdXEI01^qnu68IM=| zv~^goRLYn$F?OGT&Qq2dLT`5-j>>j=XHjmY|9n+i)Mh!ewc?-izW-Tw@aeP1Rehq? cb(TLF-tT1jvrc1A1JDizPgg&ebxsLQ012>Q#sB~S literal 0 HcmV?d00001 diff --git a/crawl-ref/source/rltiles/item/weapon/ranged/dart-p.png b/crawl-ref/source/rltiles/item/weapon/ranged/dart-p.png new file mode 100644 index 0000000000000000000000000000000000000000..d11baecb4a5f8adcda72c2b2c73554fe78ab9954 GIT binary patch literal 986 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy93=&Q?(RM=#y~cMSA(WJkYY)9 z^mSxl*x1kgCy|wbftew|C&cyt|NlTKdozoKi0~;*RT~!fDYWRiZ&L^9!wrDybCQ!* z%$$7Y(AG&pLYHkpjv)woqxCklTbj5PnN}|%sCZPtXb8|D1YY{|CIhWuO!9Vj`M;F? z(@_woB*-tA!Qt7BG$1G3)5S5QV$RzO8wD8@Ia~t&zwl7LP~WZIqc|b<*)o0>na5AR zGwkiU!n(n=?5ER)DZ&X}Tb}b}ujSnN_|D5cb5_sFJX>{ROWc{=cR%lDn?Ae$wPo0w bA5Wh!-{5AES+HrE0mzS@u6{1-oD!M&^Z}P19P=o!hcrNaSaw9K+^W zADJ6wY1S^h@uKDMDI53c+v3iuT|K?Gs-^hb*@t@~?)km{E)*kYm-lRy#mDpKn2HxL Ue|lP55e@R5r>mdKI;Vst08F4@=l}o! literal 0 HcmV?d00001 diff --git a/crawl-ref/source/rltiles/item/weapon/ranged/dart2.png b/crawl-ref/source/rltiles/item/weapon/ranged/dart2.png new file mode 100644 index 0000000000000000000000000000000000000000..6914eee0215df9154a7634b2d1a6ff6d1233b3b2 GIT binary patch literal 985 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy93=&Q?(RM=#y~cMSA(WJkYY)9 z^mSxl*x1kgCy|wbftew|C&cyt|NlTKdozoKi0~;*RT~!fDYWRiZ&L^9!wrDybCQ!* z%$$7Y(AG&pLYHkpjv)woqxCklTbj5PnN}|%sCZPtXb8|D1YY{|CIhWuO!9Vj`M;F? z(@_woB*-tA!Qt7BG$1F;)5S5QV$RzO8wD8@Ia~t&d1z|w6ZD%jPI=aZ(X2182J2f%q(~tJW Zm)WtGvEHfvwXO){MNd~hmvv4FO#r)%VOIbE literal 0 HcmV?d00001 From 193025e5b205d35b5eba7865a6228e961277aeb7 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Thu, 9 May 2019 00:07:29 -0400 Subject: [PATCH 295/864] Rename frenzy and blinding darts This commit is separate as renames tend to be controversial. All changes are cosmetic. Darts of frenzy become "datura-tipped darts" after the genus of toxic plant that can cause psychosis and darts of blinding become "atropa-tipped darts" after the genus of toxic plant that can cause visual distortion and confusion. Players aren't likely to know this (unless they're a botanist), but they probably also don't know that curare is (in addition to being a generic name for blowgun poisons) a genus of toxic plant. So it fits the "exotic" dart poisons into a nice family. --- crawl-ref/source/dat/des/branches/abyss.des | 2 +- crawl-ref/source/dat/des/sprint/arena_sprint.des | 4 ++-- crawl-ref/source/dat/des/sprint/sprint_mu.des | 2 +- crawl-ref/source/dat/des/variable/mini_monsters.des | 4 ++-- crawl-ref/source/item-name.cc | 6 ++++-- crawl-ref/source/mapdef.cc | 4 ++-- 6 files changed, 12 insertions(+), 10 deletions(-) diff --git a/crawl-ref/source/dat/des/branches/abyss.des b/crawl-ref/source/dat/des/branches/abyss.des index dda855ba5613..fb51bf74a8a7 100644 --- a/crawl-ref/source/dat/des/branches/abyss.des +++ b/crawl-ref/source/dat/des/branches/abyss.des @@ -1459,7 +1459,7 @@ KMONS: 6 = lurking horror # Note: if anything in these two item sets becomes useful for more then a tiny # fraction of characters finding the abyssal rune, remove or replace them. KITEM: 4d = scroll of random uselessness w:15 q:1 / ration w:1 / \ - club w:6 / stone q:1 / dart q:1 ego:blind / \ + club w:6 / stone q:1 / dart q:1 ego:atropa / \ mundane animal skin / mundane ring mail / gold q:1 KITEM: 5 = wand of random effects / wand of flame / whip not_cursed w:2 / \ hat not_cursed mundane w:5 diff --git a/crawl-ref/source/dat/des/sprint/arena_sprint.des b/crawl-ref/source/dat/des/sprint/arena_sprint.des index a5b01f91fa8a..b21ce43d21aa 100644 --- a/crawl-ref/source/dat/des/sprint/arena_sprint.des +++ b/crawl-ref/source/dat/des/sprint/arena_sprint.des @@ -437,7 +437,7 @@ function arena_sprint_get_monster_set(round, boss) "moth of wrath / w:20 stone giant", "ball lightning", "orb spider", "hungry ghost / harpy", "shining eye", "tormentor", - "skeletal warrior / w:5 skeletal warrior ; dart ego:blind" + "skeletal warrior / w:5 skeletal warrior ; dart ego:atropa" } elseif round <= 26 then mon_set = { @@ -503,7 +503,7 @@ function arena_sprint_get_monster_set(round, boss) "neqoxec", "smoke demon", "catoblepas", "moth of wrath / w:20 ettin", "orb spider", "fire crab", "shining eye", "tormentor", "tentacled monstrosity", - "skeletal warrior / skeletal warrior ; dart ego:blind", + "skeletal warrior / skeletal warrior ; dart ego:atropa", "unseen horror / lorocyproca / shadow wraith / ghost moth", "curse toe / w:20 wandering mushroom / w:4 murray", "reaper / hell beast / geryon w:1", diff --git a/crawl-ref/source/dat/des/sprint/sprint_mu.des b/crawl-ref/source/dat/des/sprint/sprint_mu.des index a530a4d512bc..1b8e066abd79 100644 --- a/crawl-ref/source/dat/des/sprint/sprint_mu.des +++ b/crawl-ref/source/dat/des/sprint/sprint_mu.des @@ -513,7 +513,7 @@ KMONS: g = tyrant leech KMONS: A = lindwurm KMONS: h = redback KMONS: i = hydra -KMONS: j = patrolling spriggan ; q:5 dart ego:blind | q:5 dart ego:frenzy +KMONS: j = patrolling spriggan ; q:5 dart ego:atropa | q:5 dart ego:datura KMONS: k = patrolling spriggan druid KMONS: q = electric eel KFEAT: q = deep_water diff --git a/crawl-ref/source/dat/des/variable/mini_monsters.des b/crawl-ref/source/dat/des/variable/mini_monsters.des index 3b17951a8b97..1be5124b9e4a 100644 --- a/crawl-ref/source/dat/des/variable/mini_monsters.des +++ b/crawl-ref/source/dat/des/variable/mini_monsters.des @@ -886,7 +886,7 @@ KMASK: 'f = opaque : if crawl.coinflip() then KITEM: f = javelin ego:poisoned q:4-6 / tomahawk ego:poisoned : else -KITEM: f = dart ego:poisoned / dart ego:curare / dart ego:blind +KITEM: f = dart ego:poisoned / dart ego:curare / dart ego:atropa : end KITEM: g = any potion q:2-3 MONS: plant, oklob sapling, ball python @@ -941,7 +941,7 @@ ITEM: Young Poisoner's Handbook / book of Changes / \ : if crawl.coinflip() then KITEM: f = javelin ego:poisoned q:4-6 / tomahawk ego:poisoned : else -KITEM: f = dart ego:poisoned / dart ego:curare / dart ego:blind +KITEM: f = dart ego:poisoned / dart ego:curare / dart ego:atropa : end KITEM: g = any potion q:2 / any potion q:3 MONS: plant, oklob sapling, ball python diff --git a/crawl-ref/source/item-name.cc b/crawl-ref/source/item-name.cc index 836b11cf088c..6e178934df4c 100644 --- a/crawl-ref/source/item-name.cc +++ b/crawl-ref/source/item-name.cc @@ -335,6 +335,8 @@ static bool _missile_brand_is_prefix(special_missile_type brand) { case SPMSL_POISONED: case SPMSL_CURARE: + case SPMSL_BLINDING: + case SPMSL_FRENZY: case SPMSL_EXPLODING: case SPMSL_STEEL: case SPMSL_SILVER: @@ -384,7 +386,7 @@ const char* missile_brand_name(const item_def &item, mbn_type t) return t == MBN_TERSE ? "sick" : "sickness"; #endif case SPMSL_FRENZY: - return "frenzy"; + return t == MBN_NAME ? "datura-tipped" : "datura"; case SPMSL_RETURNING: return t == MBN_TERSE ? "return" : "returning"; case SPMSL_CHAOS: @@ -394,7 +396,7 @@ const char* missile_brand_name(const item_def &item, mbn_type t) case SPMSL_DISPERSAL: return t == MBN_TERSE ? "disperse" : "dispersal"; case SPMSL_BLINDING: - return t == MBN_TERSE ? "blind" : "blinding"; + return t == MBN_NAME ? "atropa-tipped" : "atropa"; case SPMSL_NORMAL: return ""; default: diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc index cf9ad4a8e961..33b377a2aa65 100644 --- a/crawl-ref/source/mapdef.cc +++ b/crawl-ref/source/mapdef.cc @@ -4957,8 +4957,8 @@ int str_to_ego(object_class_type item_type, string ego_str) "confusion", "sickness", #endif - "frenzy", - "blind", + "datura", + "atropa", nullptr }; COMPILE_CHECK(ARRAYSZ(missile_brands) == NUM_REAL_SPECIAL_MISSILES); From 1701b1f0fecff789a962e1d87a944b10eca762ff Mon Sep 17 00:00:00 2001 From: sdynet Date: Sat, 27 Apr 2019 22:21:50 +0900 Subject: [PATCH 296/864] Throwing Overhaul III: Remove most tomahawk and javelin brands Now that blowguns are removed, throwing users do not need three ways to poison a monster. Steel is removed; silver now gets both bonuses, to be a "rare extra damage throwable" that fits a niche not available with other weapon types. This might be too good, which can be addressed in a couple of ways. Exploding, while "neat" was rarely different from yet another bonus damage throwable. Returning and penetration are removed, these effects will return in a different way in subsequent commits. [Committer's note: Closes #1048. Significant expansion of the original patch] --- crawl-ref/docs/options_guide.txt | 2 +- crawl-ref/source/dat/des/builder/shops.des | 4 +- crawl-ref/source/dat/des/portals/bailey.des | 40 +++++++++---------- .../source/dat/des/variable/mini_monsters.des | 10 +---- crawl-ref/source/describe.cc | 20 +--------- crawl-ref/source/initfile.cc | 4 +- crawl-ref/source/item-name.cc | 12 ++++-- crawl-ref/source/item-prop-enum.h | 6 +++ crawl-ref/source/makeitem.cc | 26 +++++------- crawl-ref/source/mapdef.cc | 6 +++ crawl-ref/source/ranged-attack.cc | 3 +- crawl-ref/source/shopping.cc | 8 ++-- crawl-ref/source/throw.h | 1 - 13 files changed, 61 insertions(+), 81 deletions(-) diff --git a/crawl-ref/docs/options_guide.txt b/crawl-ref/docs/options_guide.txt index bc06502ae809..a828a04dc6e7 100644 --- a/crawl-ref/docs/options_guide.txt +++ b/crawl-ref/docs/options_guide.txt @@ -1738,7 +1738,7 @@ fire_items_start = a Sets the first inventory item to consider when selecting missiles to fire. The default is a. -fire_order = launcher, return +fire_order = launcher fire_order += javelin / tomahawk / stone / rock / net / dart fire_order += inscribed (Ordered list option) diff --git a/crawl-ref/source/dat/des/builder/shops.des b/crawl-ref/source/dat/des/builder/shops.des index 493982d781ed..595f4bb46ceb 100644 --- a/crawl-ref/source/dat/des/builder/shops.des +++ b/crawl-ref/source/dat/des/builder/shops.des @@ -307,7 +307,6 @@ DEPTH: D:4-, Depths MONS: ball python w:5 / adder / water moccasin, place:Snake:1 KFEAT: v = general shop type:Serpentskin suffix:Sales count:7 ; \ w:8 dart ego:poisoned | w:4 dart ego:curare | \ - w:14 tomahawk ego:poisoned | \ w:3 ring of poison resistance | w:6 randbook disc:poison | \ w:2 staff of poison | w:4 any weapon ego:venom | \ w:4 any armour ego:poison_resistance | w:1 swamp dragon scales @@ -466,8 +465,7 @@ KFEAT: s = general shop type:Demolitions suffix:Depot ; \ randbook disc:conjuration | book of the tempests | book of clouds | \ wand of iceblast | wand of flame | wand of disintegration | \ wand of clouds | wand of scattershot | staff of conjuration | \ - large rock ego:exploding | javelin ego:exploding | wand of acid | \ - tomahawk ego:exploding | fan of gales | lightning rod | lamp of fire | \ + wand of acid | fan of gales | lightning rod | lamp of fire | \ phial of floods | scroll of immolation | book of flames | book of fire | \ book of air | manual of conjurations | manual of evocations FTILE: ' = floor_rough_red diff --git a/crawl-ref/source/dat/des/portals/bailey.des b/crawl-ref/source/dat/des/portals/bailey.des index f02606854f8c..653536776b9a 100644 --- a/crawl-ref/source/dat/des/portals/bailey.des +++ b/crawl-ref/source/dat/des/portals/bailey.des @@ -67,15 +67,15 @@ end -- Axes. function axe_returning(e) - e.mons("generate_awake kobold ; tomahawk ego:returning ident:type q:4 | \ - tomahawk ego:returning ident:type q:3 / \ - generate_awake hobgoblin ; tomahawk ego:returning ident:type q:4 | \ - tomahawk ego:returning ident:type q:3") + e.mons("generate_awake kobold ; tomahawk ident:type q:4 | \ + tomahawk ident:type q:3 / \ + generate_awake hobgoblin ; tomahawk ident:type q:4 | \ + tomahawk ident:type q:3") end function kobold_axe_returning(e) - e.mons("generate_awake kobold ; tomahawk ego:returning ident:type q:4 | \ - tomahawk ego:returning ident:type q:3") + e.mons("generate_awake kobold ; tomahawk ident:type q:4 | \ + tomahawk ident:type q:3") end function easy_axe_fighter(e) @@ -186,12 +186,12 @@ WEIGHT: 5 : local rnd = crawl.random2(2) : if rnd == 0 then MONS: goblin ; hand axe / hobgoblin ; hand axe / orc ; hand axe -MONS: goblin ; tomahawk ego:returning ident:type q:4 | \ - tomahawk ego:returning ident:type q:3 / \ - hobgoblin ; tomahawk ego:returning ident:type q:4 | \ - tomahawk ego:returning ident:type q:3 / \ - orc ; tomahawk ego:returning ident:type q:4 | \ - tomahawk ego:returning ident:type q:3 +MONS: goblin ; tomahawk ident:type q:4 | \ + tomahawk ident:type q:3 / \ + hobgoblin ; tomahawk ident:type q:4 | \ + tomahawk ident:type q:3 / \ + orc ; tomahawk ident:type q:4 | \ + tomahawk ident:type q:3 SUBST: 1 = 122 : bailey_portal_axe(_G) : elseif rnd == 1 then @@ -215,8 +215,8 @@ NAME: enter_bailey_5 TAGS: transparent : local rnd = crawl.random2(2) : if rnd == 0 then -MONS: goblin ; tomahawk ego:returning ident:type q:4 | \ - tomahawk ego:returning ident:type q:3 +MONS: goblin ; tomahawk ident:type q:4 | \ + tomahawk ident:type q:3 : bailey_portal_axe(_G) : elseif rnd == 1 then MONS: goblin ; spear @@ -320,8 +320,8 @@ TAGS: transparent WEIGHT: 1 : local rnd = crawl.random2(2) : if rnd == 0 then -MONS: orc ; tomahawk ego:returning ident:type q:3 | \ - tomahawk ego:returning ident:type q:4 . hand axe +MONS: orc ; tomahawk ident:type q:3 | \ + tomahawk ident:type q:4 . hand axe MONS: gnoll ; hand axe / goblin ; hand axe : bailey_portal_axe(_G) : elseif rnd == 1 then @@ -570,8 +570,8 @@ SUBST: N = nc SUBST: H = W. # the following KMONS duplicates monster 1 from kobold_axe_returning KFEAT: ( = exit_bailey -KMONS: ( = generate_awake kobold ; tomahawk ego:returning ident:type q:4 | \ - tomahawk ego:returning ident:type q:3 +KMONS: ( = generate_awake kobold ; tomahawk ident:type q:4 | \ + tomahawk ident:type q:3 # : kobold_axe_returning(_G) : easy_axe_fighter(_G) @@ -943,8 +943,8 @@ ORIENT: encompass TAGS: bailey_polearm no_item_gen no_monster_gen no_pool_fixup patrolling : orc_with_polearm(_G) : orc_warrior_with_polearm(_G) -MONS: centaur ; javelin ego:returning ident:type q:2 | \ - javelin ego:returning ident:type q:3 . spear | trident | halberd . \ +MONS: centaur ; javelin ident:type q:2 | \ + javelin ident:type q:3 . spear | trident | halberd . \ ring mail | scale mail | chain mail NSUBST: _ = 4:2 / 5:1 / *:. NSUBST: ; = 6:2 / 6:1 / *:. diff --git a/crawl-ref/source/dat/des/variable/mini_monsters.des b/crawl-ref/source/dat/des/variable/mini_monsters.des index 1be5124b9e4a..ea02e64de8bc 100644 --- a/crawl-ref/source/dat/des/variable/mini_monsters.des +++ b/crawl-ref/source/dat/des/variable/mini_monsters.des @@ -883,11 +883,7 @@ ITEM: Young Poisoner's Handbook / book of Changes / \ randbook numspells:4 title:Nature \ spells:beastly_appendage&sting&sticks_to_snakes&spider_form KMASK: 'f = opaque -: if crawl.coinflip() then -KITEM: f = javelin ego:poisoned q:4-6 / tomahawk ego:poisoned -: else KITEM: f = dart ego:poisoned / dart ego:curare / dart ego:atropa -: end KITEM: g = any potion q:2-3 MONS: plant, oklob sapling, ball python MONS: adder, oklob plant, water moccasin @@ -938,11 +934,7 @@ ITEM: Young Poisoner's Handbook / book of Changes / \ spells:beastly_appendage&summon_small_mammal&call_canine_familiar&spider_form / \ randbook numspells:4 title:Nature \ spells:beastly_appendage&sting&sticks_to_snakes&spider_form -: if crawl.coinflip() then -KITEM: f = javelin ego:poisoned q:4-6 / tomahawk ego:poisoned -: else KITEM: f = dart ego:poisoned / dart ego:curare / dart ego:atropa -: end KITEM: g = any potion q:2 / any potion q:3 MONS: plant, oklob sapling, ball python MONS: adder, oklob plant, water moccasin @@ -1299,7 +1291,7 @@ NAME: minmay_unpleasant_kobolds TAGS: transparent DEPTH: D:6- MONS: kobold ; tomahawk ego:dispersal q:2 / w:3 big kobold ; tomahawk ego:dispersal q:4 -MONS: kobold ; tomahawk ego:exploding q:2 / w:3 big kobold ; tomahawk ego:exploding q:4 +MONS: kobold ; tomahawk ego:silver q:2 / w:3 big kobold ; tomahawk ego:silver q:4 MONS: kobold ; dart ego:curare q:1 / \ w:3 big kobold ; dart ego:curare q:2 : if you.absdepth() > 13 then diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index 54d824fc8587..08c74f2a2d9d 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -1498,30 +1498,14 @@ static string _describe_ammo(const item_def &item) description += "It is tipped with a substance that causes " "blindness and brief confusion."; break; - case SPMSL_RETURNING: - description += "A skilled user can throw it in such a way that it " - "will return to its owner."; - break; - case SPMSL_PENETRATION: - description += "It will pass through any targets it hits, " - "potentially hitting all targets in its path until " - "it reaches its maximum range."; - break; case SPMSL_DISPERSAL: description += "It will cause any target it hits to blink, with a " "tendency towards blinking further away from the " "one who " + threw_or_fired + " it."; break; - case SPMSL_EXPLODING: - description += "It will explode into fragments upon hitting a " - "target, hitting an obstruction, or reaching its " - "maximum range."; - break; - case SPMSL_STEEL: - description += "It deals increased damage compared to normal ammo."; - break; case SPMSL_SILVER: - description += "It deals substantially increased damage to chaotic " + description += "It deals increased damage compared to normal ammo " + "and substantially increased damage to chaotic " "and magically transformed beings. It also inflicts " "extra damage against mutated beings, according to " "how mutated they are."; diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index b3cea3407cd3..f84fb7cf2a58 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -637,8 +637,6 @@ static fire_type _str_to_fire_types(const string &str) return FIRE_DART; else if (str == "net") return FIRE_NET; - else if (str == "return" || str == "returning") - return FIRE_RETURNING; else if (str == "inscribed") return FIRE_INSCRIBED; @@ -1078,7 +1076,7 @@ void game_options::reset_options() fire_items_start = 0; // start at slot 'a' // Clear fire_order and set up the defaults. - set_fire_order("launcher, return, " + set_fire_order("launcher," "javelin / tomahawk / stone / rock / net / dart, " "inscribed", false, false); diff --git a/crawl-ref/source/item-name.cc b/crawl-ref/source/item-name.cc index 6e178934df4c..9fe73ec7904e 100644 --- a/crawl-ref/source/item-name.cc +++ b/crawl-ref/source/item-name.cc @@ -338,7 +338,9 @@ static bool _missile_brand_is_prefix(special_missile_type brand) case SPMSL_BLINDING: case SPMSL_FRENZY: case SPMSL_EXPLODING: +#if TAG_MAJOR_VERSION == 34 case SPMSL_STEEL: +#endif case SPMSL_SILVER: return true; default: @@ -367,10 +369,16 @@ const char* missile_brand_name(const item_def &item, mbn_type t) return t == MBN_NAME ? "poisoned" : "poison"; case SPMSL_CURARE: return t == MBN_NAME ? "curare-tipped" : "curare"; +#if TAG_MAJOR_VERSION == 34 case SPMSL_EXPLODING: return t == MBN_TERSE ? "explode" : "exploding"; case SPMSL_STEEL: return "steel"; + case SPMSL_RETURNING: + return t == MBN_TERSE ? "return" : "returning"; + case SPMSL_PENETRATION: + return t == MBN_TERSE ? "penet" : "penetration"; +#endif case SPMSL_SILVER: return "silver"; #if TAG_MAJOR_VERSION == 34 @@ -387,12 +395,8 @@ const char* missile_brand_name(const item_def &item, mbn_type t) #endif case SPMSL_FRENZY: return t == MBN_NAME ? "datura-tipped" : "datura"; - case SPMSL_RETURNING: - return t == MBN_TERSE ? "return" : "returning"; case SPMSL_CHAOS: return "chaos"; - case SPMSL_PENETRATION: - return t == MBN_TERSE ? "penet" : "penetration"; case SPMSL_DISPERSAL: return t == MBN_TERSE ? "disperse" : "dispersal"; case SPMSL_BLINDING: diff --git a/crawl-ref/source/item-prop-enum.h b/crawl-ref/source/item-prop-enum.h index 45f3ca11bb2d..8d58cb700106 100644 --- a/crawl-ref/source/item-prop-enum.h +++ b/crawl-ref/source/item-prop-enum.h @@ -460,12 +460,18 @@ enum special_missile_type // to separate from weapons in general {dlb} SPMSL_FROST, SPMSL_POISONED, SPMSL_CURARE, // Needle-only brand +#if TAG_MAJOR_VERSION == 34 SPMSL_RETURNING, +#endif SPMSL_CHAOS, +#if TAG_MAJOR_VERSION == 34 SPMSL_PENETRATION, +#endif SPMSL_DISPERSAL, +#if TAG_MAJOR_VERSION == 34 SPMSL_EXPLODING, SPMSL_STEEL, +#endif SPMSL_SILVER, #if TAG_MAJOR_VERSION == 34 SPMSL_PARALYSIS, // dart only from here on diff --git a/crawl-ref/source/makeitem.cc b/crawl-ref/source/makeitem.cc index 670db0082b7d..5396921068a6 100644 --- a/crawl-ref/source/makeitem.cc +++ b/crawl-ref/source/makeitem.cc @@ -540,20 +540,12 @@ static special_missile_type _determine_missile_brand(const item_def& item, nw, SPMSL_POISONED); break; case MI_JAVELIN: - rc = random_choose_weighted(30, SPMSL_RETURNING, - 32, SPMSL_PENETRATION, - 32, SPMSL_POISONED, - 21, SPMSL_STEEL, - 20, SPMSL_SILVER, + rc = random_choose_weighted(120, SPMSL_SILVER, nw, SPMSL_NORMAL); break; case MI_TOMAHAWK: - rc = random_choose_weighted(15, SPMSL_POISONED, - 10, SPMSL_SILVER, - 10, SPMSL_STEEL, - 12, SPMSL_DISPERSAL, - 28, SPMSL_RETURNING, - 15, SPMSL_EXPLODING, + rc = random_choose_weighted(60, SPMSL_SILVER, + 30, SPMSL_DISPERSAL, nw, SPMSL_NORMAL); break; } @@ -626,18 +618,20 @@ bool is_missile_brand_ok(int type, int brand, bool strict) switch (brand) { case SPMSL_POISONED: - return type == MI_JAVELIN || type == MI_TOMAHAWK; - case SPMSL_RETURNING: - return type == MI_JAVELIN || type == MI_TOMAHAWK; + return false; case SPMSL_CHAOS: return type == MI_TOMAHAWK || type == MI_JAVELIN; - case SPMSL_PENETRATION: - return type == MI_JAVELIN; case SPMSL_DISPERSAL: return type == MI_TOMAHAWK; +#if TAG_MAJOR_VERSION == 34 + case SPMSL_RETURNING: + return type == MI_JAVELIN || type == MI_TOMAHAWK; + case SPMSL_PENETRATION: + return type == MI_JAVELIN; case SPMSL_EXPLODING: return type == MI_TOMAHAWK; case SPMSL_STEEL: // deliberate fall through +#endif case SPMSL_SILVER: return type == MI_JAVELIN || type == MI_TOMAHAWK; default: break; diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc index 33b377a2aa65..808abc205419 100644 --- a/crawl-ref/source/mapdef.cc +++ b/crawl-ref/source/mapdef.cc @@ -4943,12 +4943,18 @@ int str_to_ego(object_class_type item_type, string ego_str) "frost", "poisoned", "curare", +#if TAG_MAJOR_VERSION == 34 "returning", +#endif "chaos", +#if TAG_MAJOR_VERSION == 34 "penetration", +#endif "dispersal", +#if TAG_MAJOR_VERSION == 34 "exploding", "steel", +#endif "silver", #if TAG_MAJOR_VERSION == 34 "paralysis", diff --git a/crawl-ref/source/ranged-attack.cc b/crawl-ref/source/ranged-attack.cc index e98774b3e06b..a874815043ab 100644 --- a/crawl-ref/source/ranged-attack.cc +++ b/crawl-ref/source/ranged-attack.cc @@ -341,7 +341,7 @@ int ranged_attack::weapon_damage() int dam = property(*projectile, PWPN_DAMAGE); if (projectile->base_type == OBJ_MISSILES - && get_ammo_brand(*projectile) == SPMSL_STEEL) + && get_ammo_brand(*projectile) == SPMSL_SILVER) { if (dam) dam = div_rand_round(dam * 13, 10); @@ -417,7 +417,6 @@ bool ranged_attack::apply_damage_brand(const char *what) // No stacking elemental brands. if (projectile->base_type == OBJ_MISSILES && get_ammo_brand(*projectile) != SPMSL_NORMAL - && get_ammo_brand(*projectile) != SPMSL_PENETRATION && (brand == SPWPN_FLAMING || brand == SPWPN_FREEZING || brand == SPWPN_HOLY_WRATH diff --git a/crawl-ref/source/shopping.cc b/crawl-ref/source/shopping.cc index 4b4575841498..0b11ab6c3c3b 100644 --- a/crawl-ref/source/shopping.cc +++ b/crawl-ref/source/shopping.cc @@ -296,12 +296,12 @@ unsigned int item_value(item_def item, bool ident) case SPMSL_CURARE: case SPMSL_BLINDING: + case SPMSL_SILVER: #if TAG_MAJOR_VERSION == 34 case SPMSL_PARALYSIS: -#endif case SPMSL_PENETRATION: - case SPMSL_SILVER: case SPMSL_STEEL: +#endif case SPMSL_DISPERSAL: valued *= 30; break; @@ -315,10 +315,10 @@ unsigned int item_value(item_def item, bool ident) break; #endif - case SPMSL_EXPLODING: case SPMSL_POISONED: - case SPMSL_RETURNING: #if TAG_MAJOR_VERSION == 34 + case SPMSL_RETURNING: + case SPMSL_EXPLODING: case SPMSL_SLOW: case SPMSL_SICKNESS: #endif diff --git a/crawl-ref/source/throw.h b/crawl-ref/source/throw.h index d4ff01cccb65..8bf5910735d5 100644 --- a/crawl-ref/source/throw.h +++ b/crawl-ref/source/throw.h @@ -18,7 +18,6 @@ enum fire_type FIRE_JAVELIN = 0x0010, FIRE_ROCK = 0x0100, FIRE_NET = 0x0200, - FIRE_RETURNING = 0x0400, FIRE_TOMAHAWK = 0x0800, FIRE_INSCRIBED = 0x1000, // Only used for _get_fire_order }; From 6ea07b34f02e6fddd77dd1b2abe6254a25af882b Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Thu, 9 May 2019 01:32:32 -0400 Subject: [PATCH 297/864] Remove some unneeded TAG_MAJORs --- crawl-ref/source/makeitem.cc | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/crawl-ref/source/makeitem.cc b/crawl-ref/source/makeitem.cc index 5396921068a6..253cf26f2a0e 100644 --- a/crawl-ref/source/makeitem.cc +++ b/crawl-ref/source/makeitem.cc @@ -525,9 +525,6 @@ static special_missile_type _determine_missile_brand(const item_def& item, rc = SPMSL_NORMAL; break; case MI_DART: -#if TAG_MAJOR_VERSION == 34 - case MI_NEEDLE: -#endif // Curare is special cased, all the others aren't. if (got_curare_roll(item_level)) { @@ -584,12 +581,6 @@ bool is_missile_brand_ok(int type, int brand, bool strict) case SPMSL_CURARE: case SPMSL_PARALYSIS: -#if TAG_MAJOR_VERSION == 34 - case SPMSL_SLOW: - case SPMSL_SLEEP: - case SPMSL_CONFUSION: - case SPMSL_SICKNESS: -#endif case SPMSL_FRENZY: return type == MI_DART; @@ -623,15 +614,6 @@ bool is_missile_brand_ok(int type, int brand, bool strict) return type == MI_TOMAHAWK || type == MI_JAVELIN; case SPMSL_DISPERSAL: return type == MI_TOMAHAWK; -#if TAG_MAJOR_VERSION == 34 - case SPMSL_RETURNING: - return type == MI_JAVELIN || type == MI_TOMAHAWK; - case SPMSL_PENETRATION: - return type == MI_JAVELIN; - case SPMSL_EXPLODING: - return type == MI_TOMAHAWK; - case SPMSL_STEEL: // deliberate fall through -#endif case SPMSL_SILVER: return type == MI_JAVELIN || type == MI_TOMAHAWK; default: break; From ba011c803f3f9e2259ac25ddae0b1f6a66988805 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Thu, 9 May 2019 01:37:24 -0400 Subject: [PATCH 298/864] Throwing Overhaul IV: Returning and Penetration To differentiate the different types of throwables, javelins now always penetrate. This overlaps some with crossbows, which provide a penetrating brand, but a crossbow user can choose from many brands and has access to weapon enchantment. Tomahawks always return. This is more a QoL change than anything, and a step towards a broader ranged reform. In terms of ammo availability, the mulch rate remains the same, so throws per tomahawk at on strategic timescales are static. On tactical timescales, a player relying on tomahawks for damage will for the most part not be limited by ammo; a player 0-skill throwing tomahawks will get a few extra throws in the early game, but the damage from these extra throws isn't that much. Since this effect applies to monsters also, giving them a comparative buff, it should be a wash. --- crawl-ref/source/throw.cc | 51 +++++++++------------------------------ 1 file changed, 11 insertions(+), 40 deletions(-) diff --git a/crawl-ref/source/throw.cc b/crawl-ref/source/throw.cc index 6a77ed82771c..5c959a35612a 100644 --- a/crawl-ref/source/throw.cc +++ b/crawl-ref/source/throw.cc @@ -58,7 +58,7 @@ bool is_penetrating_attack(const actor& attacker, const item_def* weapon, { return is_launched(&attacker, weapon, projectile) != launch_retval::FUMBLED && projectile.base_type == OBJ_MISSILES - && get_ammo_brand(projectile) == SPMSL_PENETRATION + && projectile.sub_type == MI_JAVELIN || weapon && is_launched(&attacker, weapon, projectile) == launch_retval::LAUNCHED && (get_weapon_brand(*weapon) == SPWPN_PENETRATION @@ -672,7 +672,7 @@ static bool _setup_missile_beam(const actor *agent, bolt &beam, item_def &item, } returning = item.base_type == OBJ_MISSILES - && get_ammo_brand(item) == SPMSL_RETURNING; + && item.sub_type == MI_TOMAHAWK; if (item.base_type == OBJ_MISSILES && get_ammo_brand(item) == SPMSL_EXPLODING) @@ -952,15 +952,6 @@ bool throw_it(bolt &pbolt, int throw_2, dist *target) if (teleport) returning = false; - if (returning && projected != launch_retval::FUMBLED) - { - const skill_type sk = - projected == launch_retval::THROWN ? SK_THROWING - : item_attack_skill(*you.weapon()); - if (!one_chance_in(1 + skill_bump(sk))) - did_return = true; - } - you.time_taken = you.attack_delay(&item).roll(); // Create message. @@ -1004,14 +995,14 @@ bool throw_it(bolt &pbolt, int throw_2, dist *target) Hints.hints_throw_counter++; // Dropping item copy, since the launched item might be different. - pbolt.drop_item = !did_return; + pbolt.drop_item = !returning; pbolt.fire(); hit = !pbolt.hit_verb.empty(); // The item can be destroyed before returning. - if (did_return && thrown_object_destroyed(&item, pbolt.target)) - did_return = false; + if (returning && thrown_object_destroyed(&item, pbolt.target)) + returning = false; } if (bow_brand == SPWPN_CHAOS || ammo_brand == SPMSL_CHAOS) @@ -1023,28 +1014,15 @@ bool throw_it(bolt &pbolt, int throw_2, dist *target) if (ammo_brand == SPMSL_FRENZY) did_god_conduct(DID_HASTY, 6 + random2(3), true); - if (did_return) + if (returning) { // Fire beam in reverse. pbolt.setup_retrace(); viewwindow(); pbolt.fire(); - - msg::stream << item.name(DESC_THE) << " returns to your pack!" - << endl; - - // Player saw the item return. - if (!is_artefact(you.inv[throw_2])) - set_ident_flags(you.inv[throw_2], ISFLAG_KNOW_TYPE); } else { - // Should have returned but didn't. - if (returning && item_type_known(you.inv[throw_2])) - { - msg::stream << item.name(DESC_THE) - << " fails to return to your pack!" << endl; - } dec_inv_item_quantity(throw_2, 1); if (unwielded) canned_msg(MSG_EMPTY_HANDED_NOW); @@ -1168,14 +1146,7 @@ bool mons_throw(monster* mons, bolt &beam, int msl, bool teleport) _throw_noise(mons, beam, item); - // decrease inventory - bool really_returns; - if (returning && !one_chance_in(mons_power(mons->type) + 3)) - really_returns = true; - else - really_returns = false; - - beam.drop_item = !really_returns; + beam.drop_item = !returning; // Redraw the screen before firing, in case the monster just // came into view and the screen hasn't been updated yet. @@ -1185,7 +1156,7 @@ bool mons_throw(monster* mons, bolt &beam, int msl, bool teleport) beam.use_target_as_pos = true; beam.affect_cell(); beam.affect_endpoint(); - if (!really_returns) + if (!returning) beam.drop_object(); } else @@ -1193,11 +1164,11 @@ bool mons_throw(monster* mons, bolt &beam, int msl, bool teleport) beam.fire(); // The item can be destroyed before returning. - if (really_returns && thrown_object_destroyed(&item, beam.target)) - really_returns = false; + if (returning && thrown_object_destroyed(&item, beam.target)) + returning = false; } - if (really_returns) + if (returning) { // Fire beam in reverse. beam.setup_retrace(); From 48e52ebf6e0c1a208a8c5c2658d4a334156cac04 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Thu, 9 May 2019 10:40:32 -0400 Subject: [PATCH 299/864] Rename Tomahawks Boomerangs Now that they always return. And besides, the new name is significantly more Australian. --- crawl-ref/docs/options_guide.txt | 2 +- crawl-ref/source/acquire.cc | 4 +-- crawl-ref/source/arena.cc | 2 +- crawl-ref/source/dat/des/branches/abyss.des | 2 +- .../source/dat/des/builder/alphashops.des | 4 +-- crawl-ref/source/dat/des/builder/shops.des | 2 +- crawl-ref/source/dat/des/portals/bailey.des | 36 +++++++++---------- crawl-ref/source/dat/des/portals/gauntlet.des | 2 +- crawl-ref/source/dat/des/portals/wizlab.des | 14 ++++---- .../source/dat/des/serial/gnoll_camp.des | 6 ++-- crawl-ref/source/dat/des/tutorial/lesson2.des | 4 +-- .../source/dat/des/variable/mini_monsters.des | 6 ++-- crawl-ref/source/dat/descript/items.txt | 4 +-- crawl-ref/source/dat/descript/quotes.txt | 10 +++--- crawl-ref/source/dat/descript/tutorial.txt | 8 ++--- crawl-ref/source/god-blessing.cc | 4 +-- crawl-ref/source/hints.cc | 2 +- crawl-ref/source/initfile.cc | 8 ++--- crawl-ref/source/item-prop-enum.h | 4 +-- crawl-ref/source/item-prop.cc | 4 +-- crawl-ref/source/items.cc | 2 +- crawl-ref/source/job-data.h | 2 +- crawl-ref/source/makeitem.cc | 14 ++++---- crawl-ref/source/mon-gear.cc | 6 ++-- crawl-ref/source/monster.cc | 2 +- crawl-ref/source/newgame.cc | 4 +-- crawl-ref/source/ng-restr.cc | 2 +- crawl-ref/source/ng-setup.cc | 2 +- crawl-ref/source/quiver.cc | 2 +- crawl-ref/source/rltiles/dc-item.txt | 24 ++++++------- crawl-ref/source/tags.cc | 4 +-- crawl-ref/source/throw.cc | 2 +- crawl-ref/source/throw.h | 2 +- crawl-ref/source/tilepick.cc | 14 ++++---- 34 files changed, 106 insertions(+), 104 deletions(-) diff --git a/crawl-ref/docs/options_guide.txt b/crawl-ref/docs/options_guide.txt index a828a04dc6e7..7832b493d532 100644 --- a/crawl-ref/docs/options_guide.txt +++ b/crawl-ref/docs/options_guide.txt @@ -1739,7 +1739,7 @@ fire_items_start = a missiles to fire. The default is a. fire_order = launcher -fire_order += javelin / tomahawk / stone / rock / net / dart +fire_order += javelin / boomerang / stone / rock / net / dart fire_order += inscribed (Ordered list option) Controls the order of items autoselected for firing. Items diff --git a/crawl-ref/source/acquire.cc b/crawl-ref/source/acquire.cc index e9d35baf1f69..aaa29a4a7f45 100644 --- a/crawl-ref/source/acquire.cc +++ b/crawl-ref/source/acquire.cc @@ -545,7 +545,7 @@ static int _acquirement_missile_subtype(bool /*divine*/, int & /*quantity*/) skill = i; } - missile_type result = MI_TOMAHAWK; + missile_type result = MI_BOOMERANG; switch (skill) { @@ -558,7 +558,7 @@ static int _acquirement_missile_subtype(bool /*divine*/, int & /*quantity*/) // Choose from among all usable missile types. vector > missile_weights; - missile_weights.emplace_back(MI_TOMAHAWK, 50); + missile_weights.emplace_back(MI_BOOMERANG, 50); missile_weights.emplace_back(MI_DART, 75); if (you.body_size() >= SIZE_MEDIUM) diff --git a/crawl-ref/source/arena.cc b/crawl-ref/source/arena.cc index a64f75186f12..96fcfd1fdddd 100644 --- a/crawl-ref/source/arena.cc +++ b/crawl-ref/source/arena.cc @@ -1359,7 +1359,7 @@ int arena_cull_items() // Arrows/needles/etc on the floor is just clutter. if (item.base_type != OBJ_MISSILES || item.sub_type == MI_JAVELIN - || item.sub_type == MI_TOMAHAWK + || item.sub_type == MI_BOOMERANG || item.sub_type == MI_THROWING_NET) { ammo.push_back(idx); diff --git a/crawl-ref/source/dat/des/branches/abyss.des b/crawl-ref/source/dat/des/branches/abyss.des index fb51bf74a8a7..fac37bb321b9 100644 --- a/crawl-ref/source/dat/des/branches/abyss.des +++ b/crawl-ref/source/dat/des/branches/abyss.des @@ -68,7 +68,7 @@ ENDMAP NAME: marbit_kobold_abyss_entry TAGS: no_monster_gen nolayout_encompass WEIGHT: 5 -MONS: big kobold ; tomahawk ego:dispersal, kobold demonologist +MONS: big kobold ; boomerang ego:dispersal, kobold demonologist : abyss_entry(_G, '_') MAP xxxxxxxxxxxxxxx diff --git a/crawl-ref/source/dat/des/builder/alphashops.des b/crawl-ref/source/dat/des/builder/alphashops.des index 1d33dd2fc1c0..bc554461d0f4 100644 --- a/crawl-ref/source/dat/des/builder/alphashops.des +++ b/crawl-ref/source/dat/des/builder/alphashops.des @@ -69,7 +69,7 @@ "broad axe", "pair of boots", "potion of berserk rage", "potion of blood", "potion of brilliance", "scroll of blinking", "scroll of brand weapon", - "manual of bows", "buckler" } + "manual of bows", "buckler", "boomerang" } elseif s == "C" then i = { "book of callings", "book of cantrips", "club", "book of changes", "book of conjurations", "centaur barding", @@ -163,7 +163,7 @@ "book of transfigurations", "ring of teleportation", "scroll of teleportation", "triple sword", "triple crossbow", "troll leather armour", "manual of throwing", - "manual of translocations", "manual of transmutations", "tomahawk", + "manual of translocations", "manual of transmutations", "trident", "throwing net" } elseif s == "U" then i = { "book of unlife", "manual of unarmed combat" } diff --git a/crawl-ref/source/dat/des/builder/shops.des b/crawl-ref/source/dat/des/builder/shops.des index 595f4bb46ceb..61b6dfda31cf 100644 --- a/crawl-ref/source/dat/des/builder/shops.des +++ b/crawl-ref/source/dat/des/builder/shops.des @@ -411,7 +411,7 @@ TAGS: no_monster_gen no_trap_gen transparent SHUFFLE: _s KFEAT: s = general shop type:Hallowed suffix:Reliquary ; \ potion of heal wounds | potion of curing | \ - tomahawk ego:silver w:2 | javelin ego:silver w:2 | \ + boomerang ego:silver w:2 | javelin ego:silver w:2 | \ any weapon ego:holy_wrath | scroll of holy word |\ amulet of faith w:2 | ring of positive energy w:5 |\ any armour ego:positive_energy w:5 diff --git a/crawl-ref/source/dat/des/portals/bailey.des b/crawl-ref/source/dat/des/portals/bailey.des index 653536776b9a..caf6a8e6b8ed 100644 --- a/crawl-ref/source/dat/des/portals/bailey.des +++ b/crawl-ref/source/dat/des/portals/bailey.des @@ -67,15 +67,15 @@ end -- Axes. function axe_returning(e) - e.mons("generate_awake kobold ; tomahawk ident:type q:4 | \ - tomahawk ident:type q:3 / \ - generate_awake hobgoblin ; tomahawk ident:type q:4 | \ - tomahawk ident:type q:3") + e.mons("generate_awake kobold ; boomerang ident:type q:4 | \ + boomerang ident:type q:3 / \ + generate_awake hobgoblin ; boomerang ident:type q:4 | \ + boomerang ident:type q:3") end function kobold_axe_returning(e) - e.mons("generate_awake kobold ; tomahawk ident:type q:4 | \ - tomahawk ident:type q:3") + e.mons("generate_awake kobold ; boomerang ident:type q:4 | \ + boomerang ident:type q:3") end function easy_axe_fighter(e) @@ -186,12 +186,12 @@ WEIGHT: 5 : local rnd = crawl.random2(2) : if rnd == 0 then MONS: goblin ; hand axe / hobgoblin ; hand axe / orc ; hand axe -MONS: goblin ; tomahawk ident:type q:4 | \ - tomahawk ident:type q:3 / \ - hobgoblin ; tomahawk ident:type q:4 | \ - tomahawk ident:type q:3 / \ - orc ; tomahawk ident:type q:4 | \ - tomahawk ident:type q:3 +MONS: goblin ; boomerang ident:type q:4 | \ + boomerang ident:type q:3 / \ + hobgoblin ; boomerang ident:type q:4 | \ + boomerang ident:type q:3 / \ + orc ; boomerang ident:type q:4 | \ + boomerang ident:type q:3 SUBST: 1 = 122 : bailey_portal_axe(_G) : elseif rnd == 1 then @@ -215,8 +215,8 @@ NAME: enter_bailey_5 TAGS: transparent : local rnd = crawl.random2(2) : if rnd == 0 then -MONS: goblin ; tomahawk ident:type q:4 | \ - tomahawk ident:type q:3 +MONS: goblin ; boomerang ident:type q:4 | \ + boomerang ident:type q:3 : bailey_portal_axe(_G) : elseif rnd == 1 then MONS: goblin ; spear @@ -320,8 +320,8 @@ TAGS: transparent WEIGHT: 1 : local rnd = crawl.random2(2) : if rnd == 0 then -MONS: orc ; tomahawk ident:type q:3 | \ - tomahawk ident:type q:4 . hand axe +MONS: orc ; boomerang ident:type q:3 | \ + boomerang ident:type q:4 . hand axe MONS: gnoll ; hand axe / goblin ; hand axe : bailey_portal_axe(_G) : elseif rnd == 1 then @@ -570,8 +570,8 @@ SUBST: N = nc SUBST: H = W. # the following KMONS duplicates monster 1 from kobold_axe_returning KFEAT: ( = exit_bailey -KMONS: ( = generate_awake kobold ; tomahawk ident:type q:4 | \ - tomahawk ident:type q:3 +KMONS: ( = generate_awake kobold ; boomerang ident:type q:4 | \ + boomerang ident:type q:3 # : kobold_axe_returning(_G) : easy_axe_fighter(_G) diff --git a/crawl-ref/source/dat/des/portals/gauntlet.des b/crawl-ref/source/dat/des/portals/gauntlet.des index 779a98199ac9..f560b0104628 100644 --- a/crawl-ref/source/dat/des/portals/gauntlet.des +++ b/crawl-ref/source/dat/des/portals/gauntlet.des @@ -1146,7 +1146,7 @@ dgn.delayed_decay_extra(_G, "Q", "halfling skeleton", "randbook disc:translocation / book of spatial translocations" .. " / book of the warp" .. ", scroll of blinking / scroll of teleportation q:2" .. - " / tomahawk ego:dispersal" .. + " / boomerang ego:dispersal" .. ", dagger good_item / short sword good_item / rapier good_item" .. " / long sword good_item / double sword / demon blade" .. " / hunting sling randart / fustibalus good_item" .. diff --git a/crawl-ref/source/dat/des/portals/wizlab.des b/crawl-ref/source/dat/des/portals/wizlab.des index 3f6dfe1e7953..262148f52405 100644 --- a/crawl-ref/source/dat/des/portals/wizlab.des +++ b/crawl-ref/source/dat/des/portals/wizlab.des @@ -1314,19 +1314,19 @@ ENDMAP NAME: wizlab_golubria TAGS: no_pool_fixup KMONS: 1 = spatial vortex w:7 / blink frog / insubstantial wisp w:3 / nothing w:5 -KMONS: 2 = deep elf mage w:5 ; tomahawk ego:dispersal w:20 | tomahawk w:5 | nothing / \ - rakshasa w:5 ; tomahawk ego:dispersal w:20 | tomahawk w:5 | nothing / \ - boggart ; tomahawk ego:dispersal w:20 | tomahawk w:5 | nothing / \ - wizard ; tomahawk ego:dispersal w:20 | tomahawk w:5 | nothing +KMONS: 2 = deep elf mage w:5 ; boomerang ego:dispersal w:20 | boomerang w:5 | nothing / \ + rakshasa w:5 ; boomerang ego:dispersal w:20 | boomerang w:5 | nothing / \ + boggart ; boomerang ego:dispersal w:20 | boomerang w:5 | nothing / \ + wizard ; boomerang ego:dispersal w:20 | boomerang w:5 | nothing KMONS: 3 = rakshasa w:5 ; whip ego:distortion | whip ego:vorpal w:6 | dagger \ ego:distortion | dagger ego:vorpal w:6 | spear ego:distortion | \ - spear ego:vorpal w:6 . tomahawk ego:dispersal / \ + spear ego:vorpal w:6 . boomerang ego:dispersal / \ boggart w:5 ; whip ego:distortion | whip ego:vorpal w:6 | dagger \ ego:distortion | dagger ego:vorpal w:6 | spear ego:distortion | \ - spear ego:vorpal w:6 . tomahawk ego:dispersal / \ + spear ego:vorpal w:6 . boomerang ego:dispersal / \ wizard ; whip ego:distortion | whip ego:vorpal w:6 | dagger \ ego:distortion | dagger ego:vorpal w:6 | spear ego:distortion | \ - spear ego:vorpal w:6 . tomahawk ego:dispersal . robe + spear ego:vorpal w:6 . boomerang ego:dispersal . robe KMONS: 04 = large abomination w:15 / small abomination w:15 / unseen horror w:5 / \ thrashing horror w:30 / skeleton w:30 / freezing wraith w:5 / \ hellwing / chaos spawn w:5 / orange demon / ice devil / \ diff --git a/crawl-ref/source/dat/des/serial/gnoll_camp.des b/crawl-ref/source/dat/des/serial/gnoll_camp.des index 68f6392ed942..c284cc30ebf7 100644 --- a/crawl-ref/source/dat/des/serial/gnoll_camp.des +++ b/crawl-ref/source/dat/des/serial/gnoll_camp.des @@ -29,7 +29,7 @@ TAGS: serial_gnoll_camp patrolling no_pool_fixup WEIGHT: 8 KMASK: w = no_monster_gen MONS: gnoll -MONS: gnoll ; stone q:10 | tomahawk q:3 | throwing net q:3 / nothing +MONS: gnoll ; stone q:10 | boomerang q:3 | throwing net q:3 / nothing MONS: gnoll shaman MONS: gnoll sergeant MONS: jackal / hound / wolf w:1 @@ -56,7 +56,7 @@ NAME: gnoll_camp_medium_02 TAGS: serial_gnoll_camp patrolling WEIGHT: 8 MONS: gnoll -MONS: gnoll ; stone q:10 | tomahawk q:3 | throwing net q:3 +MONS: gnoll ; stone q:10 | boomerang q:3 | throwing net q:3 MONS: gnoll shaman MONS: gnoll sergeant MONS: jackal w:20 / hound / wolf w:1 / nothing w:5 @@ -141,7 +141,7 @@ MONS: gnoll MONS: gnoll shaman MONS: gnoll sergeant MONS: jackal / hound / wolf w:1 -MONS: gnoll ; stone q:10 | tomahawk q:3 | throwing net q:3 +MONS: gnoll ; stone q:10 | boomerang q:3 | throwing net q:3 MAP ....... .41.14. diff --git a/crawl-ref/source/dat/des/tutorial/lesson2.des b/crawl-ref/source/dat/des/tutorial/lesson2.des index 8b3d63f2b975..8ded75d477fa 100644 --- a/crawl-ref/source/dat/des/tutorial/lesson2.des +++ b/crawl-ref/source/dat/des/tutorial/lesson2.des @@ -100,10 +100,10 @@ FTILE: deABCDEF = tutorial_pad MONS: training dummy hp:2 ; stone q:10 MONS: rat always_corpse MONS: worm -ITEM: tomahawk mundane q:10 +ITEM: boomerang mundane q:10 ITEM: shortbow mundane not_cursed ITEM: arrow mundane q:30 -MARKER: d = lua:tutorial2.msg("tomahawks") +MARKER: d = lua:tutorial2.msg("boomerangs") MARKER: A = lua:tutorial2.msg("throwing") MARKER: B = lua:tutorial2.msg("resting_reminder") MARKER: e = lua:tutorial2.msg("wield_bow") diff --git a/crawl-ref/source/dat/des/variable/mini_monsters.des b/crawl-ref/source/dat/des/variable/mini_monsters.des index ea02e64de8bc..711b36ea3036 100644 --- a/crawl-ref/source/dat/des/variable/mini_monsters.des +++ b/crawl-ref/source/dat/des/variable/mini_monsters.des @@ -1290,8 +1290,8 @@ ENDMAP NAME: minmay_unpleasant_kobolds TAGS: transparent DEPTH: D:6- -MONS: kobold ; tomahawk ego:dispersal q:2 / w:3 big kobold ; tomahawk ego:dispersal q:4 -MONS: kobold ; tomahawk ego:silver q:2 / w:3 big kobold ; tomahawk ego:silver q:4 +MONS: kobold ; boomerang ego:dispersal q:2 / w:3 big kobold ; boomerang ego:dispersal q:4 +MONS: kobold ; boomerang ego:silver q:2 / w:3 big kobold ; boomerang ego:silver q:4 MONS: kobold ; dart ego:curare q:1 / \ w:3 big kobold ; dart ego:curare q:2 : if you.absdepth() > 13 then @@ -2259,7 +2259,7 @@ DEPTH: D:12-, Elf, !Elf:$ MONS: red devil ; spear | trident . ring mail | scale mail MONS: red devil ; spear | trident . buckler MONS: red devil ; spear good_item | trident good_item -MONS: red devil ; spear | trident . tomahawk +MONS: red devil ; spear | trident . boomerang SHUFFLE: 1234 KMASK: l = no_monster_gen MAP diff --git a/crawl-ref/source/dat/descript/items.txt b/crawl-ref/source/dat/descript/items.txt index 393507177c76..42985b3ae299 100644 --- a/crawl-ref/source/dat/descript/items.txt +++ b/crawl-ref/source/dat/descript/items.txt @@ -1136,9 +1136,9 @@ A mesh of ropes knotted together with weights around the edge, used to entangle and entrap targets. Struggling victims can eventually destroy the net and break free, if they live long enough. %%%% -tomahawk +boomerang -A small axe, designed for throwing. +A curved, flat, throwing baton designed to return to its user. %%%% trident diff --git a/crawl-ref/source/dat/descript/quotes.txt b/crawl-ref/source/dat/descript/quotes.txt index 136f8bc29833..f51ff4c5c891 100644 --- a/crawl-ref/source/dat/descript/quotes.txt +++ b/crawl-ref/source/dat/descript/quotes.txt @@ -2970,11 +2970,13 @@ against—whom?” -Jorge Luis Borges, “Toenails”. 1960. trans. Andrew Hurley, 1998. %%%% -tomahawk +boomerang -“Let them draw the sharpest knife, and whirl the swiftest tomahawk, for their -bitterest enemy is in their hands.” - -James Fenimore Cooper, “The Last of the Mohicans”, 1826. +“The weapon, thrown at 20 or 30 yards distance, twirled round in the air with +astonishing velocity, and alighting on the right arm of one of his opponents, +actually rebounded to a distance not less than 70 or 80 yards, leaving a +horrible contusion behind, and exciting universal admiration.” + -The Sydney Gazette and New South Wales Advertiser, 23 December 1804 %%%% tormentor diff --git a/crawl-ref/source/dat/descript/tutorial.txt b/crawl-ref/source/dat/descript/tutorial.txt index 9718a7832fe2..7b81166a705e 100644 --- a/crawl-ref/source/dat/descript/tutorial.txt +++ b/crawl-ref/source/dat/descript/tutorial.txt @@ -226,15 +226,15 @@ tutorial2 newlevel Remember: You can reread old messages with $cmd[CMD_REPLAY_MESSAGES]. %%%% -tutorial2 tomahawks +tutorial2 boomerangs -Now, for ranged combat! Pick up these tomahawks with +Now, for ranged combat! Pick up these boomerangs with $cmd[CMD_PICKUP] or g, or by mouseclick, and continue. %%%% tutorial2 throwing -You can fire your tomahawks at a monster with $cmd[CMD_FIRE] +You can fire your boomerangs at a monster with $cmd[CMD_FIRE] or by clicking on them in the inventory panel. To confirm the auto-targeted monster, press $cmd[CMD_TARGET_SELECT] or Enter. @@ -247,7 +247,7 @@ Pick up this shortbow and wield it with $cmd[CMD_WIELD_WEAPON] tutorial2 firing # FIXME: Lengthy because of the hint for choosing target. -Firing arrows from your wielded shortbow works exactly the same as throwing tomahawks: +Firing arrows from your wielded shortbow works exactly the same as throwing boomerangs: via $cmd[CMD_FIRE] or mouseclick . You can change the targeted monster by pressing $cmd[CMD_TARGET_CYCLE_FORWARD] while in target mode. The worm is diff --git a/crawl-ref/source/god-blessing.cc b/crawl-ref/source/god-blessing.cc index 557e5ea23513..bd2b77234ebd 100644 --- a/crawl-ref/source/god-blessing.cc +++ b/crawl-ref/source/god-blessing.cc @@ -166,7 +166,7 @@ void gift_ammo_to_orc(monster* orc, bool initial_gift) ammo.base_type = OBJ_MISSILES; if (!launcher) - ammo.sub_type = MI_TOMAHAWK; + ammo.sub_type = MI_BOOMERANG; else ammo.sub_type = fires_ammo_type(*launcher); @@ -287,7 +287,7 @@ static string _beogh_bless_ranged_weapon(monster* mon) } } - // If they have a shield but no launcher, give tomahawks. + // If they have a shield but no launcher, give boomerangs. if (mon->shield() != nullptr) { gift_ammo_to_orc(mon); diff --git a/crawl-ref/source/hints.cc b/crawl-ref/source/hints.cc index 49abefa04bfc..eb8c46ccd816 100644 --- a/crawl-ref/source/hints.cc +++ b/crawl-ref/source/hints.cc @@ -1204,7 +1204,7 @@ void learned_something_new(hints_event_type seen_what, coord_def gc) "('" << stringize_glyph(get_item_symbol(SHOW_ITEM_MISSILE)) << "') " - "you've picked up. Missiles like tomahawks and throwing nets " + "you've picked up. Missiles like boomerangs and throwing nets " "can be thrown by hand, but other missiles like arrows and " "bolts require a launcher and training in using it to be " "really effective. " diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index f84fb7cf2a58..627c9fdc89ab 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -553,7 +553,7 @@ static map _special_weapon_map = { {"thrown", WPN_THROWN}, {"rocks", WPN_THROWN}, - {"tomahawks", WPN_THROWN}, + {"boomerangs", WPN_THROWN}, {"javelins", WPN_THROWN}, {"random", WPN_RANDOM}, @@ -631,8 +631,8 @@ static fire_type _str_to_fire_types(const string &str) return FIRE_ROCK; else if (str == "javelin") return FIRE_JAVELIN; - else if (str == "tomahawk") - return FIRE_TOMAHAWK; + else if (str == "boomerang") + return FIRE_BOOMERANG; else if (str == "dart") return FIRE_DART; else if (str == "net") @@ -1077,7 +1077,7 @@ void game_options::reset_options() // Clear fire_order and set up the defaults. set_fire_order("launcher," - "javelin / tomahawk / stone / rock / net / dart, " + "javelin / boomerang / stone / rock / net / dart, " "inscribed", false, false); diff --git a/crawl-ref/source/item-prop-enum.h b/crawl-ref/source/item-prop-enum.h index 8d58cb700106..36c6aa976bd5 100644 --- a/crawl-ref/source/item-prop-enum.h +++ b/crawl-ref/source/item-prop-enum.h @@ -337,7 +337,7 @@ enum missile_type MI_LARGE_ROCK, MI_SLING_BULLET, MI_THROWING_NET, - MI_TOMAHAWK, + MI_BOOMERANG, NUM_MISSILES, MI_NONE // was MI_EGGPLANT... used for launch type detection @@ -637,7 +637,7 @@ enum weapon_type WPN_RANDOM, WPN_VIABLE, -// thrown weapons (for hunter weapon selection) - rocks, javelins, tomahawks +// thrown weapons (for hunter weapon selection) - rocks, javelins, boomerangs WPN_THROWN, }; diff --git a/crawl-ref/source/item-prop.cc b/crawl-ref/source/item-prop.cc index 7ea23c6ab3ae..ba16e19137b7 100644 --- a/crawl-ref/source/item-prop.cc +++ b/crawl-ref/source/item-prop.cc @@ -665,7 +665,7 @@ static const missile_def Missile_prop[] = { MI_SLING_BULLET, "sling bullet", 4, 8, 5, false }, { MI_JAVELIN, "javelin", 10, 20, 8, true }, { MI_THROWING_NET, "throwing net", 0, 0, 30, true }, - { MI_TOMAHAWK, "tomahawk", 6, 20, 5, true }, + { MI_BOOMERANG, "boomerang", 6, 20, 5, true }, }; struct food_def @@ -2074,7 +2074,7 @@ bool has_launcher(const item_def &ammo) && ammo.sub_type != MI_DART #endif && ammo.sub_type != MI_JAVELIN - && ammo.sub_type != MI_TOMAHAWK + && ammo.sub_type != MI_BOOMERANG && ammo.sub_type != MI_THROWING_NET; } diff --git a/crawl-ref/source/items.cc b/crawl-ref/source/items.cc index d0f8d7890573..35116fbc12d6 100644 --- a/crawl-ref/source/items.cc +++ b/crawl-ref/source/items.cc @@ -3516,7 +3516,7 @@ colour_t item_def::missile_colour() const return RED; case MI_THROWING_NET: return MAGENTA; - case MI_TOMAHAWK: + case MI_BOOMERANG: return GREEN; case NUM_SPECIAL_MISSILES: default: diff --git a/crawl-ref/source/job-data.h b/crawl-ref/source/job-data.h index 04c24107254d..658d6e691d5e 100644 --- a/crawl-ref/source/job-data.h +++ b/crawl-ref/source/job-data.h @@ -265,7 +265,7 @@ static const map job_data = { SP_FELID, SP_HALFLING, SP_DEEP_DWARF, SP_SPRIGGAN, SP_CENTAUR, SP_BASE_DRACONIAN, }, { "leather armour", "book of Spatial Translocations", "scroll of blinking", - "tomahawk ego:dispersal q:5" }, + "boomerang ego:dispersal q:5" }, WCHOICE_PLAIN, { { SK_FIGHTING, 2 }, { SK_ARMOUR, 1 }, { SK_DODGING, 2 }, { SK_SPELLCASTING, 2 }, { SK_TRANSLOCATIONS, 3 }, { SK_THROWING, 1 }, diff --git a/crawl-ref/source/makeitem.cc b/crawl-ref/source/makeitem.cc index 253cf26f2a0e..952833af48e9 100644 --- a/crawl-ref/source/makeitem.cc +++ b/crawl-ref/source/makeitem.cc @@ -540,7 +540,7 @@ static special_missile_type _determine_missile_brand(const item_def& item, rc = random_choose_weighted(120, SPMSL_SILVER, nw, SPMSL_NORMAL); break; - case MI_TOMAHAWK: + case MI_BOOMERANG: rc = random_choose_weighted(60, SPMSL_SILVER, 30, SPMSL_DISPERSAL, nw, SPMSL_NORMAL); @@ -586,7 +586,7 @@ bool is_missile_brand_ok(int type, int brand, bool strict) case SPMSL_BLINDING: // possible on ex-pies - return type == MI_DART || (type == MI_TOMAHAWK && !strict); + return type == MI_DART || (type == MI_BOOMERANG && !strict); default: if (type == MI_DART) @@ -611,11 +611,11 @@ bool is_missile_brand_ok(int type, int brand, bool strict) case SPMSL_POISONED: return false; case SPMSL_CHAOS: - return type == MI_TOMAHAWK || type == MI_JAVELIN; + return type == MI_BOOMERANG || type == MI_JAVELIN; case SPMSL_DISPERSAL: - return type == MI_TOMAHAWK; + return type == MI_BOOMERANG; case SPMSL_SILVER: - return type == MI_JAVELIN || type == MI_TOMAHAWK; + return type == MI_JAVELIN || type == MI_BOOMERANG; default: break; } @@ -642,7 +642,7 @@ static void _generate_missile_item(item_def& item, int force_type, 12, MI_BOLT, 12, MI_SLING_BULLET, 10, MI_DART, - 3, MI_TOMAHAWK, + 3, MI_BOOMERANG, 2, MI_JAVELIN, 1, MI_THROWING_NET, 1, MI_LARGE_ROCK); @@ -675,7 +675,7 @@ static void _generate_missile_item(item_def& item, int force_type, } // Reduced quantity if special. - if (item.sub_type == MI_JAVELIN || item.sub_type == MI_TOMAHAWK + if (item.sub_type == MI_JAVELIN || item.sub_type == MI_BOOMERANG || (item.sub_type == MI_DART && get_ammo_brand(item) != SPMSL_POISONED) || get_ammo_brand(item) == SPMSL_RETURNING) { diff --git a/crawl-ref/source/mon-gear.cc b/crawl-ref/source/mon-gear.cc index e59ef245b5eb..f6e35ca7eb79 100644 --- a/crawl-ref/source/mon-gear.cc +++ b/crawl-ref/source/mon-gear.cc @@ -1406,7 +1406,7 @@ static void _give_ammo(monster* mon, int level, bool mons_summoned) if (one_chance_in( player_in_branch(BRANCH_ORC)? 9 : 20)) { - weap_type = MI_TOMAHAWK; + weap_type = MI_BOOMERANG; qty = random_range(4, 8); } break; @@ -1414,7 +1414,7 @@ static void _give_ammo(monster* mon, int level, bool mons_summoned) case MONS_ORC: if (one_chance_in(20)) { - weap_type = MI_TOMAHAWK; + weap_type = MI_BOOMERANG; qty = random_range(2, 5); } break; @@ -1447,7 +1447,7 @@ static void _give_ammo(monster* mon, int level, bool mons_summoned) if (one_chance_in(3) || active_monster_band == BAND_MERFOLK_JAVELINEER) { - weap_type = MI_TOMAHAWK; + weap_type = MI_BOOMERANG; qty = random_range(4, 8); if (active_monster_band == BAND_MERFOLK_JAVELINEER) break; diff --git a/crawl-ref/source/monster.cc b/crawl-ref/source/monster.cc index 083afc1397aa..8643b1898b66 100644 --- a/crawl-ref/source/monster.cc +++ b/crawl-ref/source/monster.cc @@ -1970,7 +1970,7 @@ bool monster::pickup_missile(item_def &item, bool msg, bool force) // Allow upgrading throwing weapon brands (XXX: improve this!) if (item.sub_type == miss->sub_type - && (item.sub_type == MI_TOMAHAWK || item.sub_type == MI_JAVELIN) + && (item.sub_type == MI_BOOMERANG || item.sub_type == MI_JAVELIN) && get_ammo_brand(*miss) == SPMSL_NORMAL && get_ammo_brand(item) != SPMSL_NORMAL) { diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 268e9b9a484b..ada661f63616 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -1644,9 +1644,9 @@ static void _construct_weapon_menu(const newgame_def& ng, } else if (species_size(ng.species, PSIZE_TORSO) <= SIZE_SMALL) { - thrown_name = "tomahawks"; + thrown_name = "boomerangs"; #ifdef USE_TILE_LOCAL - tmp->add_tile(tile_def(TILE_MI_TOMAHAWK, TEX_DEFAULT)); + tmp->add_tile(tile_def(TILE_MI_BOOMERANG, TEX_DEFAULT)); #endif } else diff --git a/crawl-ref/source/ng-restr.cc b/crawl-ref/source/ng-restr.cc index e967d5b68c42..509662da0141 100644 --- a/crawl-ref/source/ng-restr.cc +++ b/crawl-ref/source/ng-restr.cc @@ -126,7 +126,7 @@ char_choice_restriction weapon_restriction(weapon_type wpn, return CC_BANNED; } - // Javelins are always good, tomahawks not so much. + // Javelins are always good, boomerangs not so much. if (wpn == WPN_THROWN) { return species_size(ng.species) >= SIZE_MEDIUM ? CC_UNRESTRICTED diff --git a/crawl-ref/source/ng-setup.cc b/crawl-ref/source/ng-setup.cc index 1bc67d544f85..f7837955552e 100644 --- a/crawl-ref/source/ng-setup.cc +++ b/crawl-ref/source/ng-setup.cc @@ -213,7 +213,7 @@ static void _give_ammo(weapon_type weapon, int plus) if (species_can_throw_large_rocks(you.species)) newgame_make_item(OBJ_MISSILES, MI_LARGE_ROCK, 4 + plus); else if (you.body_size(PSIZE_TORSO) <= SIZE_SMALL) - newgame_make_item(OBJ_MISSILES, MI_TOMAHAWK, 8 + 2 * plus); + newgame_make_item(OBJ_MISSILES, MI_BOOMERANG, 8 + 2 * plus); else newgame_make_item(OBJ_MISSILES, MI_JAVELIN, 5 + plus); newgame_make_item(OBJ_MISSILES, MI_THROWING_NET, 2); diff --git a/crawl-ref/source/quiver.cc b/crawl-ref/source/quiver.cc index 9cf0f86d59a1..d5ac1255c6bc 100644 --- a/crawl-ref/source/quiver.cc +++ b/crawl-ref/source/quiver.cc @@ -518,7 +518,7 @@ static bool _item_matches(const item_def &item, fire_type types, return true; if ((types & FIRE_NET) && item.sub_type == MI_THROWING_NET) return true; - if ((types & FIRE_TOMAHAWK) && item.sub_type == MI_TOMAHAWK) + if ((types & FIRE_BOOMERANG) && item.sub_type == MI_BOOMERANG) return true; if ((types & FIRE_DART) && item.sub_type == MI_DART) return true; diff --git a/crawl-ref/source/rltiles/dc-item.txt b/crawl-ref/source/rltiles/dc-item.txt index c3eed890ca4b..cca4ef3285e2 100644 --- a/crawl-ref/source/rltiles/dc-item.txt +++ b/crawl-ref/source/rltiles/dc-item.txt @@ -279,19 +279,19 @@ effect/bolt6 MI_BOLT6 effect/bolt7 MI_BOLT7 %rim 0 -tomahawk1 MI_TOMAHAWK +tomahawk1 MI_BOOMERANG tomahawk2 -steel_tomahawk MI_TOMAHAWK_STEEL -silver_tomahawk MI_TOMAHAWK_SILVER -# flying tomahawks -effect/tomahawk0 MI_TOMAHAWK0 -effect/tomahawk1 MI_TOMAHAWK1 -effect/tomahawk2 MI_TOMAHAWK2 -effect/tomahawk3 MI_TOMAHAWK3 -effect/tomahawk4 MI_TOMAHAWK4 -effect/tomahawk5 MI_TOMAHAWK5 -effect/tomahawk6 MI_TOMAHAWK6 -effect/tomahawk7 MI_TOMAHAWK7 +steel_tomahawk MI_BOOMERANG_STEEL +silver_tomahawk MI_BOOMERANG_SILVER +# flying boomerangs +effect/tomahawk0 MI_BOOMERANG0 +effect/tomahawk1 MI_BOOMERANG1 +effect/tomahawk2 MI_BOOMERANG2 +effect/tomahawk3 MI_BOOMERANG3 +effect/tomahawk4 MI_BOOMERANG4 +effect/tomahawk5 MI_BOOMERANG5 +effect/tomahawk6 MI_BOOMERANG6 +effect/tomahawk7 MI_BOOMERANG7 %rim 1 dart1 MI_DART diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index 389dfdfc1291..fe6e0110b7df 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -4511,13 +4511,13 @@ void unmarshallItem(reader &th, item_def &item) item.quantity = unmarshallShort(th); #if TAG_MAJOR_VERSION == 34 // These used to come in stacks in monster inventory as throwing weapons. - // Replace said stacks (but not single items) with tomahawks. + // Replace said stacks (but not single items) with boomerangs. if (item.quantity > 1 && item.base_type == OBJ_WEAPONS && (item.sub_type == WPN_CLUB || item.sub_type == WPN_HAND_AXE || item.sub_type == WPN_DAGGER || item.sub_type == WPN_SPEAR)) { item.base_type = OBJ_MISSILES; - item.sub_type = MI_TOMAHAWK; + item.sub_type = MI_BOOMERANG; item.plus = item.plus2 = 0; item.brand = SPMSL_NORMAL; } diff --git a/crawl-ref/source/throw.cc b/crawl-ref/source/throw.cc index 5c959a35612a..1fe9aa8dcfc0 100644 --- a/crawl-ref/source/throw.cc +++ b/crawl-ref/source/throw.cc @@ -672,7 +672,7 @@ static bool _setup_missile_beam(const actor *agent, bolt &beam, item_def &item, } returning = item.base_type == OBJ_MISSILES - && item.sub_type == MI_TOMAHAWK; + && item.sub_type == MI_BOOMERANG; if (item.base_type == OBJ_MISSILES && get_ammo_brand(item) == SPMSL_EXPLODING) diff --git a/crawl-ref/source/throw.h b/crawl-ref/source/throw.h index 8bf5910735d5..530f416746df 100644 --- a/crawl-ref/source/throw.h +++ b/crawl-ref/source/throw.h @@ -18,7 +18,7 @@ enum fire_type FIRE_JAVELIN = 0x0010, FIRE_ROCK = 0x0100, FIRE_NET = 0x0200, - FIRE_TOMAHAWK = 0x0800, + FIRE_BOOMERANG = 0x0800, FIRE_INSCRIBED = 0x1000, // Only used for _get_fire_order }; diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc index a70d6f5517a7..13d9555e30e8 100644 --- a/crawl-ref/source/tilepick.cc +++ b/crawl-ref/source/tilepick.cc @@ -2148,13 +2148,13 @@ static tileidx_t _tileidx_missile_base(const item_def &item) case MI_STONE: return TILE_MI_STONE; case MI_LARGE_ROCK: return TILE_MI_LARGE_ROCK; case MI_THROWING_NET: return TILE_MI_THROWING_NET; - case MI_TOMAHAWK: + case MI_BOOMERANG: switch (brand) { - default: return TILE_MI_TOMAHAWK + 1; - case 0: return TILE_MI_TOMAHAWK; - case SPMSL_STEEL: return TILE_MI_TOMAHAWK_STEEL; - case SPMSL_SILVER: return TILE_MI_TOMAHAWK_SILVER; + default: return TILE_MI_BOOMERANG + 1; + case 0: return TILE_MI_BOOMERANG; + case SPMSL_STEEL: return TILE_MI_BOOMERANG_STEEL; + case SPMSL_SILVER: return TILE_MI_BOOMERANG_SILVER; } case MI_DART: @@ -2748,8 +2748,8 @@ tileidx_t tileidx_item_throw(const item_def &item, int dx, int dy) case MI_THROWING_NET: ch = TILE_MI_THROWING_NET0; break; - case MI_TOMAHAWK: - ch = TILE_MI_TOMAHAWK0; + case MI_BOOMERANG: + ch = TILE_MI_BOOMERANG0; default: break; } From 46bf1127bad13f33c1a8939d94758e4d1f4612ac Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Thu, 9 May 2019 12:58:10 -0400 Subject: [PATCH 300/864] Throwing Overhaul V: Save Compatibility Old needles are converted to darts. Old brands are stripped or converted according to the following table. | old brand | new brand | | ----------- | --------- | | penetration | none | | returning | none | | exploding | none | | poison* | none | | steel | silver | | sleep | atropa | | paralysis | atropa | | confusion | atropa | * poison is removed from boomerangs and javelins, darts retain it --- crawl-ref/source/tag-version.h | 1 + crawl-ref/source/tags.cc | 36 ++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/crawl-ref/source/tag-version.h b/crawl-ref/source/tag-version.h index 74bbdb96e7cb..4035324c5136 100644 --- a/crawl-ref/source/tag-version.h +++ b/crawl-ref/source/tag-version.h @@ -230,6 +230,7 @@ enum tag_minor_version TAG_MINOR_REMOVE_DECKS, // Decks are no more TAG_MINOR_GAMESEEDS, // Game seeds + rng state saved TAG_MINOR_YELLOW_DRACONIAN_RACID, // Change yellow draconians' rAcid fake mutation to a true mutation. + TAG_MINOR_THROW_CONSOLIDATION, // Throwing brands consolidated #endif NUM_TAG_MINORS, TAG_MINOR_VERSION = NUM_TAG_MINORS - 1 diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index fe6e0110b7df..bd55537d3757 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -5001,6 +5001,42 @@ void unmarshallItem(reader &th, item_def &item) bind_item_tile(item); } + if (th.getMinorVersion() < TAG_MINOR_THROW_CONSOLIDATION + && item.base_type == OBJ_MISSILES) + { + if (item.sub_type == MI_NEEDLE) + { + item.sub_type = MI_DART; + + switch (item.brand) + { + case SPMSL_PARALYSIS: + case SPMSL_SLOW: + case SPMSL_SLEEP: + case SPMSL_CONFUSION: + case SPMSL_SICKNESS: + item.brand = SPMSL_BLINDING; + break; + default: break; + } + } + else if (item.sub_type == MI_BOOMERANG || item.sub_type == MI_JAVELIN) + { + switch (item.brand) + { + case SPMSL_RETURNING: + case SPMSL_EXPLODING: + case SPMSL_POISONED: + case SPMSL_PENETRATION: + item.brand = SPMSL_NORMAL; + break; + case SPMSL_STEEL: + item.brand = SPMSL_SILVER; + break; + } + } + } + #endif if (is_unrandom_artefact(item)) From bae0703f23c418ab6d21d5e60cb20b57c216ca0a Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Thu, 9 May 2019 13:39:36 -0400 Subject: [PATCH 301/864] Throwing Overhaul VI: Adjust brand weights Based on objstat runs, the initial weights for the new silver brand was too high, as was the relative frequency of datura darts. --- crawl-ref/source/makeitem.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/makeitem.cc b/crawl-ref/source/makeitem.cc index 952833af48e9..934868068944 100644 --- a/crawl-ref/source/makeitem.cc +++ b/crawl-ref/source/makeitem.cc @@ -533,15 +533,15 @@ static special_missile_type _determine_missile_brand(const item_def& item, } rc = random_choose_weighted(60, SPMSL_BLINDING, - 30, SPMSL_FRENZY, + 20, SPMSL_FRENZY, nw, SPMSL_POISONED); break; case MI_JAVELIN: - rc = random_choose_weighted(120, SPMSL_SILVER, + rc = random_choose_weighted(90, SPMSL_SILVER, nw, SPMSL_NORMAL); break; case MI_BOOMERANG: - rc = random_choose_weighted(60, SPMSL_SILVER, + rc = random_choose_weighted(30, SPMSL_SILVER, 30, SPMSL_DISPERSAL, nw, SPMSL_NORMAL); break; From 57add1ab2c55476f3aa1b96ee1b174c18f509a98 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Sat, 11 May 2019 11:59:58 -0400 Subject: [PATCH 302/864] Boomerang item tiles (CanOfWorms) Thrown boomerangs are animated on the beam path. --- .../rltiles/{effect => UNUSED}/tomahawk0.png | Bin .../rltiles/{effect => UNUSED}/tomahawk1.png | Bin .../rltiles/{effect => UNUSED}/tomahawk2.png | Bin .../rltiles/{effect => UNUSED}/tomahawk3.png | Bin .../rltiles/{effect => UNUSED}/tomahawk4.png | Bin .../rltiles/{effect => UNUSED}/tomahawk5.png | Bin .../rltiles/{effect => UNUSED}/tomahawk6.png | Bin .../rltiles/{effect => UNUSED}/tomahawk7.png | Bin .../weapons}/silver_tomahawk.png | Bin .../weapons}/steel_tomahawk.png | Bin .../ranged => UNUSED/weapons}/tomahawk1.png | Bin .../ranged => UNUSED/weapons}/tomahawk2.png | Bin crawl-ref/source/rltiles/dc-item.txt | 19 +++++++----------- .../source/rltiles/effect/boomerang0.png | Bin 0 -> 1029 bytes .../source/rltiles/effect/boomerang1.png | Bin 0 -> 1951 bytes .../source/rltiles/effect/boomerang2.png | Bin 0 -> 1951 bytes .../source/rltiles/effect/boomerang3.png | Bin 0 -> 1951 bytes .../rltiles/item/weapon/ranged/boomerang1.png | Bin 0 -> 1029 bytes .../rltiles/item/weapon/ranged/boomerang2.png | Bin 0 -> 1031 bytes .../item/weapon/ranged/silver_boomerang.png | Bin 0 -> 1031 bytes crawl-ref/source/tilepick.cc | 7 ++++--- 21 files changed, 11 insertions(+), 15 deletions(-) rename crawl-ref/source/rltiles/{effect => UNUSED}/tomahawk0.png (100%) rename crawl-ref/source/rltiles/{effect => UNUSED}/tomahawk1.png (100%) rename crawl-ref/source/rltiles/{effect => UNUSED}/tomahawk2.png (100%) rename crawl-ref/source/rltiles/{effect => UNUSED}/tomahawk3.png (100%) rename crawl-ref/source/rltiles/{effect => UNUSED}/tomahawk4.png (100%) rename crawl-ref/source/rltiles/{effect => UNUSED}/tomahawk5.png (100%) rename crawl-ref/source/rltiles/{effect => UNUSED}/tomahawk6.png (100%) rename crawl-ref/source/rltiles/{effect => UNUSED}/tomahawk7.png (100%) rename crawl-ref/source/rltiles/{item/weapon/ranged => UNUSED/weapons}/silver_tomahawk.png (100%) rename crawl-ref/source/rltiles/{item/weapon/ranged => UNUSED/weapons}/steel_tomahawk.png (100%) rename crawl-ref/source/rltiles/{item/weapon/ranged => UNUSED/weapons}/tomahawk1.png (100%) rename crawl-ref/source/rltiles/{item/weapon/ranged => UNUSED/weapons}/tomahawk2.png (100%) create mode 100644 crawl-ref/source/rltiles/effect/boomerang0.png create mode 100644 crawl-ref/source/rltiles/effect/boomerang1.png create mode 100644 crawl-ref/source/rltiles/effect/boomerang2.png create mode 100644 crawl-ref/source/rltiles/effect/boomerang3.png create mode 100644 crawl-ref/source/rltiles/item/weapon/ranged/boomerang1.png create mode 100644 crawl-ref/source/rltiles/item/weapon/ranged/boomerang2.png create mode 100644 crawl-ref/source/rltiles/item/weapon/ranged/silver_boomerang.png diff --git a/crawl-ref/source/rltiles/effect/tomahawk0.png b/crawl-ref/source/rltiles/UNUSED/tomahawk0.png similarity index 100% rename from crawl-ref/source/rltiles/effect/tomahawk0.png rename to crawl-ref/source/rltiles/UNUSED/tomahawk0.png diff --git a/crawl-ref/source/rltiles/effect/tomahawk1.png b/crawl-ref/source/rltiles/UNUSED/tomahawk1.png similarity index 100% rename from crawl-ref/source/rltiles/effect/tomahawk1.png rename to crawl-ref/source/rltiles/UNUSED/tomahawk1.png diff --git a/crawl-ref/source/rltiles/effect/tomahawk2.png b/crawl-ref/source/rltiles/UNUSED/tomahawk2.png similarity index 100% rename from crawl-ref/source/rltiles/effect/tomahawk2.png rename to crawl-ref/source/rltiles/UNUSED/tomahawk2.png diff --git a/crawl-ref/source/rltiles/effect/tomahawk3.png b/crawl-ref/source/rltiles/UNUSED/tomahawk3.png similarity index 100% rename from crawl-ref/source/rltiles/effect/tomahawk3.png rename to crawl-ref/source/rltiles/UNUSED/tomahawk3.png diff --git a/crawl-ref/source/rltiles/effect/tomahawk4.png b/crawl-ref/source/rltiles/UNUSED/tomahawk4.png similarity index 100% rename from crawl-ref/source/rltiles/effect/tomahawk4.png rename to crawl-ref/source/rltiles/UNUSED/tomahawk4.png diff --git a/crawl-ref/source/rltiles/effect/tomahawk5.png b/crawl-ref/source/rltiles/UNUSED/tomahawk5.png similarity index 100% rename from crawl-ref/source/rltiles/effect/tomahawk5.png rename to crawl-ref/source/rltiles/UNUSED/tomahawk5.png diff --git a/crawl-ref/source/rltiles/effect/tomahawk6.png b/crawl-ref/source/rltiles/UNUSED/tomahawk6.png similarity index 100% rename from crawl-ref/source/rltiles/effect/tomahawk6.png rename to crawl-ref/source/rltiles/UNUSED/tomahawk6.png diff --git a/crawl-ref/source/rltiles/effect/tomahawk7.png b/crawl-ref/source/rltiles/UNUSED/tomahawk7.png similarity index 100% rename from crawl-ref/source/rltiles/effect/tomahawk7.png rename to crawl-ref/source/rltiles/UNUSED/tomahawk7.png diff --git a/crawl-ref/source/rltiles/item/weapon/ranged/silver_tomahawk.png b/crawl-ref/source/rltiles/UNUSED/weapons/silver_tomahawk.png similarity index 100% rename from crawl-ref/source/rltiles/item/weapon/ranged/silver_tomahawk.png rename to crawl-ref/source/rltiles/UNUSED/weapons/silver_tomahawk.png diff --git a/crawl-ref/source/rltiles/item/weapon/ranged/steel_tomahawk.png b/crawl-ref/source/rltiles/UNUSED/weapons/steel_tomahawk.png similarity index 100% rename from crawl-ref/source/rltiles/item/weapon/ranged/steel_tomahawk.png rename to crawl-ref/source/rltiles/UNUSED/weapons/steel_tomahawk.png diff --git a/crawl-ref/source/rltiles/item/weapon/ranged/tomahawk1.png b/crawl-ref/source/rltiles/UNUSED/weapons/tomahawk1.png similarity index 100% rename from crawl-ref/source/rltiles/item/weapon/ranged/tomahawk1.png rename to crawl-ref/source/rltiles/UNUSED/weapons/tomahawk1.png diff --git a/crawl-ref/source/rltiles/item/weapon/ranged/tomahawk2.png b/crawl-ref/source/rltiles/UNUSED/weapons/tomahawk2.png similarity index 100% rename from crawl-ref/source/rltiles/item/weapon/ranged/tomahawk2.png rename to crawl-ref/source/rltiles/UNUSED/weapons/tomahawk2.png diff --git a/crawl-ref/source/rltiles/dc-item.txt b/crawl-ref/source/rltiles/dc-item.txt index cca4ef3285e2..979edf84f977 100644 --- a/crawl-ref/source/rltiles/dc-item.txt +++ b/crawl-ref/source/rltiles/dc-item.txt @@ -279,19 +279,14 @@ effect/bolt6 MI_BOLT6 effect/bolt7 MI_BOLT7 %rim 0 -tomahawk1 MI_BOOMERANG -tomahawk2 -steel_tomahawk MI_BOOMERANG_STEEL -silver_tomahawk MI_BOOMERANG_SILVER +boomerang1 MI_BOOMERANG +boomerang2 +silver_boomerang MI_BOOMERANG_SILVER # flying boomerangs -effect/tomahawk0 MI_BOOMERANG0 -effect/tomahawk1 MI_BOOMERANG1 -effect/tomahawk2 MI_BOOMERANG2 -effect/tomahawk3 MI_BOOMERANG3 -effect/tomahawk4 MI_BOOMERANG4 -effect/tomahawk5 MI_BOOMERANG5 -effect/tomahawk6 MI_BOOMERANG6 -effect/tomahawk7 MI_BOOMERANG7 +effect/boomerang0 MI_BOOMERANG0 +effect/boomerang1 MI_BOOMERANG1 +effect/boomerang2 MI_BOOMERANG2 +effect/boomerang3 MI_BOOMERANG3 %rim 1 dart1 MI_DART diff --git a/crawl-ref/source/rltiles/effect/boomerang0.png b/crawl-ref/source/rltiles/effect/boomerang0.png new file mode 100644 index 0000000000000000000000000000000000000000..8a447e9feb277502a7f8313f0046ffed7c03fffd GIT binary patch literal 1029 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy93=&Q?(RM=#y~cMSA(WJkYY)9 z^mSxl*x1kgCy|wbftew|C&cyt|NpioMlqp5jnxIKmd(6$@zjS8Zz7GfJHw4YTCo9N z&(xrVn*9D%v)3Lwa_;_<*B==ex)@xSU{ebcOLNj_k1|?TYJ6{p(}!De|9{V%Y#?{h zUIdr=QSs3bpj!xpsk^-eTE>{hE&XXJHe5U z$&iQHyzKUp|Njm2bT*`B3b?E2d^K5o?Buq;pHqKLF+XFY6tS-HtRMRcj&hAFlbvOz z=CRcmOj=RYx8J6HcHy6cQLk5?irpHrBh)E#=YeIjwC!5HB|25#Onhdi*QPpMp>E%| tBeoB%vOco(cd<%N-*B(q{1T)6Ebf(?SS9Xl)|v+j6i-(_mvv4FO#p?7f)4-y literal 0 HcmV?d00001 diff --git a/crawl-ref/source/rltiles/effect/boomerang1.png b/crawl-ref/source/rltiles/effect/boomerang1.png new file mode 100644 index 0000000000000000000000000000000000000000..5fd303bbe52edfe377000c3852d5b18f3c76bf7a GIT binary patch literal 1951 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabRA=0U}gyL32|j$D6lm#iU|#BtS(r! zZ04nlr#^gm6KSN~8Eynri52*IrUoU{Z@4#o)RGt74#Fnv+I* zl+m(M<9j=tKHQ4?|9j?S1G$U#BDmC#ijRf>-9q4fc}N4$GRBf1zhDN3XE)M7oFs2| z7lsa2Sq~tGv%n*=n1Ml08H5=tmfDvwFtBKQx;Tbd2r??L-2V+!GdKY!Cw_NvGT~Ri z$w*KEGXWEr2q|FaV8m+#Cp!l_0R`+F_!Te_RKP^Y1OndRWMX2$bOR?4Kq7#Xkr|5u zpe{ysh!S8(Gh>>-$;`sS!4CF5Co?uHI5~lS<6vh3TExhV)e4{tPz4hhU{e50-kh8q z9BdE;ELh_kq=JPF=m4M-utyfq9W1PDEX>TTn4SQK0MG~)Ru(o^Ru)|80jPqNg%zj( zs}n$m097!96krB4B#^->fQn#&4iiPD!P2-504c?90J34kvfUF|CHDUG+6z+e>FVdQ I&MBb@09(&Sr~m)} literal 0 HcmV?d00001 diff --git a/crawl-ref/source/rltiles/effect/boomerang2.png b/crawl-ref/source/rltiles/effect/boomerang2.png new file mode 100644 index 0000000000000000000000000000000000000000..6a7692d09c3d820d4395805569335c9f987d1260 GIT binary patch literal 1951 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabRA=0U}gyL32_B-ZB2|~LW3Hs3sx)|TXFw?&zx)^chO!1m-iY##$K?u;8Jr*$I2C|Z00R(@3Xl?Z7DVu&`vmM;CKjAQ0agzT4?+sChBOw- ahMdqDUsj37$}F=$4)=8Rb6Mw<&;$S(zC{55 literal 0 HcmV?d00001 diff --git a/crawl-ref/source/rltiles/effect/boomerang3.png b/crawl-ref/source/rltiles/effect/boomerang3.png new file mode 100644 index 0000000000000000000000000000000000000000..c15c2787345c1df557fbda561258e85d1bd21eea GIT binary patch literal 1951 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabRA=0U}gyL32_B-ZB2|~LW3Hs3sx)|TXFw?&zx)^chO!1m->MmCU?xhq za{`^f2sW3Klbw-?39A(l1wccvIDr9V1%@tUJ2-)Uz^{OVpaP)Zkc~uVb8@h=<5$2A z3_x^U$b3#l0ty&_-oR@DPysBQkPSv+b3#KJNeGq6Nx%kR1fXgdJiG(1StY6t|2_wD Nk*BMl%Q~loCIBoPM)d#y literal 0 HcmV?d00001 diff --git a/crawl-ref/source/rltiles/item/weapon/ranged/boomerang1.png b/crawl-ref/source/rltiles/item/weapon/ranged/boomerang1.png new file mode 100644 index 0000000000000000000000000000000000000000..8a447e9feb277502a7f8313f0046ffed7c03fffd GIT binary patch literal 1029 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy93=&Q?(RM=#y~cMSA(WJkYY)9 z^mSxl*x1kgCy|wbftew|C&cyt|NpioMlqp5jnxIKmd(6$@zjS8Zz7GfJHw4YTCo9N z&(xrVn*9D%v)3Lwa_;_<*B==ex)@xSU{ebcOLNj_k1|?TYJ6{p(}!De|9{V%Y#?{h zUIdr=QSs3bpj!xpsk^-eTE>{hE&XXJHe5U z$&iQHyzKUp|Njm2bT*`B3b?E2d^K5o?Buq;pHqKLF+XFY6tS-HtRMRcj&hAFlbvOz z=CRcmOj=RYx8J6HcHy6cQLk5?irpHrBh)E#=YeIjwC!5HB|25#Onhdi*QPpMp>E%| tBeoB%vOco(cd<%N-*B(q{1T)6Ebf(?SS9Xl)|v+j6i-(_mvv4FO#p?7f)4-y literal 0 HcmV?d00001 diff --git a/crawl-ref/source/rltiles/item/weapon/ranged/boomerang2.png b/crawl-ref/source/rltiles/item/weapon/ranged/boomerang2.png new file mode 100644 index 0000000000000000000000000000000000000000..e19c9237d3189a33a1e53c1697d125c3f0cc1027 GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy93=&Q?(RM=#y~cMSA(WJkYY)9 z^mSxl*x1kgCy|wbftew|C&cyt|NpioMlqp5jnxIKmd(6$@zjS8Zz7GfJHw4YTCo9N z&(xrVn*9D%v)3Lwa_;_<*B==ex)@xSU{ebcOLNj_k1|?TYJ6{p(}!De|9{V%Y#?{h zUIdr=QSs3bpj!xpsk^-eTE>{C^K=xmCHR+>bJk0pRO5v&){=M!d^BrYgPs2I|~E+ z`3gh2B>x=rTy)a%-zS;8V;|Y0vzKd?Uk!Q~#<}%5)9$QwKLmcYbN)?jpZR--#I%^E wA3tvie{Xrc;;OKXR#-~Rp{oCPJ=p(b=#?3WRPdKshk=5{)78&qol`;+0E(B0g8%>k literal 0 HcmV?d00001 diff --git a/crawl-ref/source/rltiles/item/weapon/ranged/silver_boomerang.png b/crawl-ref/source/rltiles/item/weapon/ranged/silver_boomerang.png new file mode 100644 index 0000000000000000000000000000000000000000..28da51f4c55ed4f781f1d352702c038a3ed8ec8a GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy93=&Q?(RM=#y~cMSA(WJkYY)9 z^mSxl*x1kgCy|wbftew|C&cyt|NpioMlqp5jnxIKmd(6$@zjS8Zz7GfJHw4YTCo9N z&(xrVn*9D%v)3Lwa_;_<*B==ex)@xSU{ebcOLNj_k1|?TYJ6{p(}!De|9{V%Y#?{h zUIdr=QSs3bpj!xpsk^-eTE>{o_R+fM$E@8agpiIh4b$mwl+c17W)-2XK*jh^xv_j6p!PS_mGV01{9>+2H% z_oXuq%Fj`mHRrMZ`G;vT^&7U9tttxF70sI(P_4IN^|LPih4nKo#Fx$3+25UbQnh3L wdfP((9eq)@2Nx%~9#dWO{eExBf&OPq{U3Qwe4I9SKPXr{UHx3vIVCg!05frfhyVZp literal 0 HcmV?d00001 diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc index 13d9555e30e8..d36053aba2b2 100644 --- a/crawl-ref/source/tilepick.cc +++ b/crawl-ref/source/tilepick.cc @@ -2153,7 +2153,6 @@ static tileidx_t _tileidx_missile_base(const item_def &item) { default: return TILE_MI_BOOMERANG + 1; case 0: return TILE_MI_BOOMERANG; - case SPMSL_STEEL: return TILE_MI_BOOMERANG_STEEL; case SPMSL_SILVER: return TILE_MI_BOOMERANG_SILVER; } @@ -2748,8 +2747,6 @@ tileidx_t tileidx_item_throw(const item_def &item, int dx, int dy) case MI_THROWING_NET: ch = TILE_MI_THROWING_NET0; break; - case MI_BOOMERANG: - ch = TILE_MI_BOOMERANG0; default: break; } @@ -2782,6 +2779,8 @@ tileidx_t tileidx_item_throw(const item_def &item, int dx, int dy) case MI_THROWING_NET: ch = TILE_MI_THROWING_NET0; break; + case MI_BOOMERANG: + ch = TILE_MI_BOOMERANG0; default: break; } @@ -3022,6 +3021,8 @@ tileidx_t vary_bolt_tile(tileidx_t tile, int dist) case TILE_BOLT_FLAME: case TILE_BOLT_IRRADIATE: return tile + ui_random(tile_main_count(tile)); + case TILE_MI_BOOMERANG0: + return tile + ui_random(4); default: return tile; } From 41c1c16e5370b10b25a32e09c543e9ecb4fc6708 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Sat, 11 May 2019 12:30:52 -0400 Subject: [PATCH 303/864] Add sdynet to CREDITS.txt --- crawl-ref/CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/CREDITS.txt b/crawl-ref/CREDITS.txt index 85433be4e7e0..e38fd80f21ad 100644 --- a/crawl-ref/CREDITS.txt +++ b/crawl-ref/CREDITS.txt @@ -276,6 +276,7 @@ Sebastian Salman Sandman25 Brett Scarborough + sdynet Roman Sêk Brennan Shacklett ShadyAmish From 9898fdd0ed0c3ab0fdb7cf3e48d2df9bfded4fd4 Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 11 May 2019 16:50:47 -0400 Subject: [PATCH 304/864] Remove an obsolete ASSERT --- crawl-ref/source/throw.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/crawl-ref/source/throw.cc b/crawl-ref/source/throw.cc index 1fe9aa8dcfc0..3af90851f2e0 100644 --- a/crawl-ref/source/throw.cc +++ b/crawl-ref/source/throw.cc @@ -325,7 +325,6 @@ vector fire_target_behaviour::get_monster_desc(const monster_info& mi) */ static int _get_dart_chance(const int hd) { - ASSERT(you.weapon()->is_type(OBJ_WEAPONS, WPN_BLOWGUN)); const int pow = (2 * (you.skill_rdiv(SK_THROWING) + you.skill_rdiv(SK_STEALTH))) / 3; From 42b690ea6c145d7780e73b3f8eba0ac9cf3efbca Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 11 May 2019 17:05:28 -0400 Subject: [PATCH 305/864] Add a few missing TAG_MAJOR checks --- crawl-ref/source/throw.cc | 5 ++++- crawl-ref/source/tilepick-p.cc | 2 ++ crawl-ref/source/tilepick.cc | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/throw.cc b/crawl-ref/source/throw.cc index 3af90851f2e0..44f4b8ae949c 100644 --- a/crawl-ref/source/throw.cc +++ b/crawl-ref/source/throw.cc @@ -471,7 +471,10 @@ bool fire_warn_if_impossible(bool silent) mprf("You cannot throw anything while %s.", held_status()); return true; } - else if (weapon->sub_type != WPN_BLOWGUN) + else +#if TAG_MAJOR_VERSION == 34 + if (weapon->sub_type != WPN_BLOWGUN) +#endif { if (!silent) { diff --git a/crawl-ref/source/tilepick-p.cc b/crawl-ref/source/tilepick-p.cc index 88ec83cdfb3b..55d4eb6c13bd 100644 --- a/crawl-ref/source/tilepick-p.cc +++ b/crawl-ref/source/tilepick-p.cc @@ -248,9 +248,11 @@ tileidx_t tilep_equ_weapon(const item_def &item) case WPN_TRIPLE_CROSSBOW: tile = TILEP_HAND1_TRIPLE_CROSSBOW; break; +#if TAG_MAJOR_VERSION == 34 case WPN_BLOWGUN: tile = TILEP_HAND1_BLOWGUN; break; +#endif case WPN_LONGBOW: tile = TILEP_HAND1_BOW3; break; diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc index d36053aba2b2..9a8fe430eb9b 100644 --- a/crawl-ref/source/tilepick.cc +++ b/crawl-ref/source/tilepick.cc @@ -2092,7 +2092,9 @@ static tileidx_t _tileidx_weapon_base(const item_def &item) case WPN_BROAD_AXE: return TILE_WPN_BROAD_AXE; case WPN_BATTLEAXE: return TILE_WPN_BATTLEAXE; case WPN_EXECUTIONERS_AXE: return TILE_WPN_EXECUTIONERS_AXE; +#if TAG_MAJOR_VERSION == 34 case WPN_BLOWGUN: return TILE_WPN_BLOWGUN; +#endif case WPN_HUNTING_SLING: return TILE_WPN_HUNTING_SLING; case WPN_FUSTIBALUS: return TILE_WPN_FUSTIBALUS; case WPN_SHORTBOW: return TILE_WPN_SHORTBOW; From f989941d98930c44706385c1c06dc7a4936673ca Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Sat, 11 May 2019 17:24:11 -0400 Subject: [PATCH 306/864] Add darts to item knowledge screen (gressup) --- crawl-ref/source/item-name.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/item-name.cc b/crawl-ref/source/item-name.cc index 9fe73ec7904e..f20015df7b5d 100644 --- a/crawl-ref/source/item-name.cc +++ b/crawl-ref/source/item-name.cc @@ -2515,7 +2515,7 @@ void check_item_knowledge(bool unknown_items) for (int i = 0; i < NUM_MISSILES; i++) { #if TAG_MAJOR_VERSION == 34 - if (i == MI_DART) + if (i == MI_NEEDLE) continue; #endif _add_fake_item(OBJ_MISSILES, i, selected_items, items_missile); From e86a0cf1eb74423783bbe56b6e96e73fd622cfd5 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 13 May 2019 10:28:00 -0400 Subject: [PATCH 307/864] Prevent deep water teleport closets in swamp (9880) This was recently reported here: https://www.reddit.com/r/dcss/comments/bn20bv/ive_never_seen_this_before_is_it_normal_to_have/ and thanks to seeding I was able to reliably replicate this bug from the morgue posted in that thread. I'll upload a save file to 9880 for posterity. (I'm assuming that 9880/11519 is the same bug and that players will tend not to notice/report these cases unless there's a monster in the closet.) Basically, what happens is this: there were two connectivity passes for swamp. The first was via zonify, and it finds and successfully fills in any teleport closets existing at the time with trees -- but does not check for overall level connectivity involving deep water. Then there's a c++ pass in dungeon.cc:_build_vault_impl that is swamp-specific. This pass handles connectivity issues involving deep water. Unfortunately, because it treats deep water as impassable, it does not fill in deep water squares, creating teleport closets of the kind that the zonify pass fixes. (Also, I've verified that these are teleport closets for flying/swimming chars.) To fix this I have inelegantly added a *third* pass on the c++ side, that finds and fills in any resulting deep water tele closets. It might be possible to do without the zonify pass now, since this (now) third pass would handle these cases, but I'm worried about kicking the tower of cards. Ideally, this would all be handled by zonify, but right now I don't understand zonify well enough to get this to happen. --- .../source/dat/des/builder/layout_cc.des | 2 ++ crawl-ref/source/dat/dlua/layout/zonify.lua | 5 ++++ crawl-ref/source/dgn-swamp.cc | 2 +- crawl-ref/source/dungeon.cc | 27 ++++++++++++++++--- 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/crawl-ref/source/dat/des/builder/layout_cc.des b/crawl-ref/source/dat/des/builder/layout_cc.des index 55e798603a44..0bfac37dae69 100644 --- a/crawl-ref/source/dat/des/builder/layout_cc.des +++ b/crawl-ref/source/dat/des/builder/layout_cc.des @@ -92,6 +92,8 @@ TAGS: overwritable layout allow_dup unrand layout_type_swamp dgn.layout_swamp() -- Prevent tele closets + -- TODO: there's also code in dungeon.cc (in _build_vault_impl) that does + -- something very similar; do we really need both? zonify.grid_fill_water_zones(1,"tree") }} diff --git a/crawl-ref/source/dat/dlua/layout/zonify.lua b/crawl-ref/source/dat/dlua/layout/zonify.lua index 1cb53b0e1305..fdeff9628efd 100644 --- a/crawl-ref/source/dat/dlua/layout/zonify.lua +++ b/crawl-ref/source/dat/dlua/layout/zonify.lua @@ -232,6 +232,11 @@ end -- is needed to fill in deep water zones and stop flyers/swimmers getting trapped. -- TODO: Need to simplify into a single pass that understands connectivity issues -- between different zone groups and can handle everything more elegantly. +-- TODO: This does not address zones separated by deep water, that in swamp +-- may be further filled by c++ code in _build_vault_impl, creating tele +-- closets of exactly the kind that this code prevents. Because of that, there's +-- yet *another* pass to fill these in there. This is all extremely redundant +-- and should be cleaned up one day. function zonify.grid_fill_water_zones(num_to_keep, feature, min_zone_size) if num_to_keep == nil then num_to_keep = 1 end if feature == nil then feature = 'rock_wall' end diff --git a/crawl-ref/source/dgn-swamp.cc b/crawl-ref/source/dgn-swamp.cc index 3dfc3fec790d..2eb985a437d0 100644 --- a/crawl-ref/source/dgn-swamp.cc +++ b/crawl-ref/source/dgn-swamp.cc @@ -54,7 +54,7 @@ static void _swamp_apply_features(int margin) grd(c) = DNGN_TREE; } else - grd(c) = _swamp_feature_for_height(dgn_height_at(c)); + grd(c) = _swamp_feature_for_height(dgn_height_at(c)); } } } diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 1ac9bee72aa7..d1ae914fc009 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -751,6 +751,17 @@ static bool _dgn_square_is_passable(const coord_def &c) return !(env.level_map_mask(c) & MMT_OPAQUE) && dgn_square_travel_ok(c); } +static bool _dgn_square_is_ever_passable(const coord_def &c) +{ + if (!(env.level_map_mask(c) & MMT_OPAQUE)) + { + const dungeon_feature_type feat = grd(c); + if (feat == DNGN_DEEP_WATER || feat == DNGN_LAVA) + return true; + } + return _dgn_square_is_passable(c); +} + static inline void _dgn_point_record_stub(const coord_def &) { } template @@ -905,8 +916,9 @@ static bool _is_exit_stair(const coord_def &c) // If fill is non-zero, it fills any disconnected regions with fill. // static int _process_disconnected_zones(int x1, int y1, int x2, int y2, - bool choose_stairless, - dungeon_feature_type fill) + bool choose_stairless, + dungeon_feature_type fill, + bool (*passable)(const coord_def &) = _dgn_square_is_passable) { memset(travel_point_distance, 0, sizeof(travel_distance_grid_t)); int nzones = 0; @@ -917,7 +929,7 @@ static int _process_disconnected_zones(int x1, int y1, int x2, int y2, { if (!map_bounds(x, y) || travel_point_distance[x][y] - || !_dgn_square_is_passable(coord_def(x, y))) + || !passable(coord_def(x, y))) { continue; } @@ -925,7 +937,7 @@ static int _process_disconnected_zones(int x1, int y1, int x2, int y2, const bool found_exit_stair = _dgn_fill_zone(coord_def(x, y), ++nzones, _dgn_point_record_stub, - _dgn_square_is_passable, + passable, choose_stairless ? (at_branch_bottom() ? _is_upwards_exit_stair : _is_exit_stair) : nullptr); @@ -4210,6 +4222,13 @@ static const vault_placement *_build_vault_impl(const map_def *vault, && player_in_branch(BRANCH_SWAMP)) { _process_disconnected_zones(0, 0, GXM-1, GYM-1, true, DNGN_TREE); + // do a second pass to remove tele closets consisting of deep water + // created by the first pass -- which will not fill in deep water + // because it is treated as impassable. + // TODO: get zonify to prevent these? + // TODO: does this come up anywhere outside of swamp? + _process_disconnected_zones(0, 0, GXM-1, GYM-1, true, DNGN_TREE, + _dgn_square_is_ever_passable); } if (!make_no_exits) From 1095bcad4c22080a9d4dacbbdf3eb3f36ad3d8e6 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 13 May 2019 13:11:12 -0400 Subject: [PATCH 308/864] Clear mon_acting on _reset_game (11971) If the player is killed at the same time as other monsters under certain conditions (I replicated it with inner flame), mon_acting would not get cleaned up. This could lead to a crash when starting a new game without exiting the program, as long as a monster would spawn in los. --- crawl-ref/source/state.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/source/state.cc b/crawl-ref/source/state.cc index b5ddc1e2bc6f..414db6e0f35c 100644 --- a/crawl-ref/source/state.cc +++ b/crawl-ref/source/state.cc @@ -84,6 +84,7 @@ void game_state::reset_game() need_save = false; type = GAME_TYPE_UNSPECIFIED; updating_scores = false; + clear_mon_acting(); reset_cmd_repeat(); reset_cmd_again(); } From 89f717de535220912c7c4dc57a6be251d2c2fd27 Mon Sep 17 00:00:00 2001 From: Edgar Bering Date: Tue, 14 May 2019 11:48:39 -0400 Subject: [PATCH 309/864] Update javelin description (Yermak) --- crawl-ref/source/dat/descript/items.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/dat/descript/items.txt b/crawl-ref/source/dat/descript/items.txt index 42985b3ae299..4fdce4050715 100644 --- a/crawl-ref/source/dat/descript/items.txt +++ b/crawl-ref/source/dat/descript/items.txt @@ -526,7 +526,9 @@ inedible chunk of flesh %%%% javelin -A lightweight spear, designed for throwing. +A lightweight spear, designed for throwing. It will pass through the targets it +hits, potentially hitting all targets in its path until it reaches maximum +range. {{ if you.race() == "Halfling" or you.race() == "Kobold" From 6b9ea3dd3dbb8a7e2a32617ae1d5f3ff6e43ac80 Mon Sep 17 00:00:00 2001 From: Doesnt Date: Fri, 10 May 2019 02:42:14 -0500 Subject: [PATCH 310/864] Let draconian scorchers and Azrael call down damnation when not at low hp --- crawl-ref/source/mon-spell.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/mon-spell.h b/crawl-ref/source/mon-spell.h index 735db82a2f54..3afb28ba9138 100644 --- a/crawl-ref/source/mon-spell.h +++ b/crawl-ref/source/mon-spell.h @@ -631,7 +631,7 @@ static const mon_spellbook mspell_list[] = { SPELL_BOLT_OF_MAGMA, 13, MON_SPELL_WIZARD }, { SPELL_FIREBALL, 13, MON_SPELL_WIZARD }, { SPELL_HURL_DAMNATION, 13, MON_SPELL_WIZARD }, - { SPELL_CALL_DOWN_DAMNATION, 13, MON_SPELL_WIZARD | MON_SPELL_EMERGENCY }, + { SPELL_CALL_DOWN_DAMNATION, 13, MON_SPELL_WIZARD }, } }, @@ -1968,7 +1968,7 @@ static const mon_spellbook mspell_list[] = { SPELL_STICKY_FLAME_RANGE, 13, MON_SPELL_MAGICAL }, { SPELL_FIREBALL, 13, MON_SPELL_MAGICAL }, { SPELL_HURL_DAMNATION, 13, MON_SPELL_MAGICAL }, - { SPELL_CALL_DOWN_DAMNATION, 13, MON_SPELL_MAGICAL | MON_SPELL_EMERGENCY }, + { SPELL_CALL_DOWN_DAMNATION, 13, MON_SPELL_MAGICAL }, } }, From 16217b4a02456184ef6e69d0e7443eefd863e3bb Mon Sep 17 00:00:00 2001 From: Edgar Bering Date: Tue, 14 May 2019 13:08:17 -0400 Subject: [PATCH 311/864] Display dart delay and base damage (Yermak) --- crawl-ref/source/describe.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index 08c74f2a2d9d..68125a5ee5dc 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -1514,7 +1514,7 @@ static string _describe_ammo(const item_def &item) } const int dam = property(item, PWPN_DAMAGE); - if (dam) + if (dam || item.sub_type == MI_DART) { const int throw_delay = (10 + dam / 2); const int target_skill = _item_training_target(item); From 4517bf713c99b7565a801d8f8562389a07eae0c9 Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Wed, 15 May 2019 18:45:15 +0100 Subject: [PATCH 312/864] Don't change max HP during DDoor (#11933, #11976) Changed in 1406302de, which broke DDoor's interaction with Revivification and HP-costing abilities. --- crawl-ref/source/duration-data.h | 1 - crawl-ref/source/player.cc | 5 +---- crawl-ref/source/spl-selfench.cc | 2 +- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/crawl-ref/source/duration-data.h b/crawl-ref/source/duration-data.h index a63fffde57b8..ba03268f79c5 100644 --- a/crawl-ref/source/duration-data.h +++ b/crawl-ref/source/duration-data.h @@ -273,7 +273,6 @@ static const duration_def duration_data[] = "You are standing in death's doorway.", D_EXPIRES, {{ "Your life is in your own hands again!", []() { you.duration[DUR_DEATHS_DOOR_COOLDOWN] = random_range(10, 30); - calc_hp(); }}, { "Your time is quickly running out!", 5 }}, 10}, { DUR_DEATHS_DOOR_COOLDOWN, YELLOW, "-DDoor", diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 8b9f0a5554d7..ae64033e1b17 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -3929,7 +3929,7 @@ int get_real_hp(bool trans, bool rotted) hitp /= 10; const bool hep_frail = have_passive(passive_t::frail) - || player_under_penance(GOD_HEPLIAKLQANA); + || player_under_penance(GOD_HEPLIAKLQANA); // Mutations that increase HP by a percentage hitp *= 100 + (you.get_mutation_level(MUT_ROBUST) * 10) @@ -3960,9 +3960,6 @@ int get_real_hp(bool trans, bool rotted) hitp = hitp * 4 / 5; #endif - if (trans && you.duration[DUR_DEATHS_DOOR] > 0) - hitp = allowed_deaths_door_hp(); - return max(1, hitp); } diff --git a/crawl-ref/source/spl-selfench.cc b/crawl-ref/source/spl-selfench.cc index 37e5bfdaafae..032e272f9c2e 100644 --- a/crawl-ref/source/spl-selfench.cc +++ b/crawl-ref/source/spl-selfench.cc @@ -47,7 +47,7 @@ spret cast_deaths_door(int pow, bool fail) you.set_duration(DUR_DEATHS_DOOR, 10 + random2avg(13, 3) + (random2(pow) / 10)); - calc_hp(false, true); + set_hp(allowed_deaths_door_hp()); if (you.duration[DUR_DEATHS_DOOR] > 25 * BASELINE_DELAY) you.duration[DUR_DEATHS_DOOR] = (23 + random2(5)) * BASELINE_DELAY; From 9a7f692d68afde9967f3c8b6b6f6fe659b9bde64 Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Wed, 15 May 2019 19:05:45 +0100 Subject: [PATCH 313/864] Use consistent capitalisation for DDoor messages --- crawl-ref/source/potion.cc | 4 ++-- crawl-ref/source/spl-other.cc | 2 +- crawl-ref/source/spl-util.cc | 2 +- crawl-ref/source/transform.cc | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crawl-ref/source/potion.cc b/crawl-ref/source/potion.cc index 4ef1749a74e1..8f5b1f00798c 100644 --- a/crawl-ref/source/potion.cc +++ b/crawl-ref/source/potion.cc @@ -89,7 +89,7 @@ class PotionCuring : public PotionEffect if (you.duration[DUR_DEATHS_DOOR]) { if (reason) - *reason = "You can't heal while in Death's door."; + *reason = "You can't heal while in death's door."; return false; } if (!you.can_potion_heal() @@ -175,7 +175,7 @@ class PotionHealWounds : public PotionEffect if (you.duration[DUR_DEATHS_DOOR]) { if (reason) - *reason = "You cannot heal while in Death's door!"; + *reason = "You cannot heal while in death's door."; return false; } if (you.hp == you.hp_max && player_rotted() == 0) diff --git a/crawl-ref/source/spl-other.cc b/crawl-ref/source/spl-other.cc index 1bd39265ea28..4179fb33d7df 100644 --- a/crawl-ref/source/spl-other.cc +++ b/crawl-ref/source/spl-other.cc @@ -30,7 +30,7 @@ spret cast_sublimation_of_blood(int pow, bool fail) bool success = false; if (you.duration[DUR_DEATHS_DOOR]) - mpr("You can't draw power from your own body while in Death's door."); + mpr("You can't draw power from your own body while in death's door."); else if (!you.can_bleed()) { if (you.species == SP_VAMPIRE) diff --git a/crawl-ref/source/spl-util.cc b/crawl-ref/source/spl-util.cc index 97a54fe76275..24c9159da630 100644 --- a/crawl-ref/source/spl-util.cc +++ b/crawl-ref/source/spl-util.cc @@ -1218,7 +1218,7 @@ string spell_uselessness_reason(spell_type spell, bool temp, bool prevent, return "you're too dead."; break; case SPELL_NECROMUTATION: - // only prohibted to actual undead, not lichformed players + // only prohibited to actual undead, not lichformed players if (you.undead_state(false)) return "you're too dead."; break; diff --git a/crawl-ref/source/transform.cc b/crawl-ref/source/transform.cc index c697c9c4a189..e37acec7e7a7 100644 --- a/crawl-ref/source/transform.cc +++ b/crawl-ref/source/transform.cc @@ -1665,7 +1665,7 @@ bool transform(int pow, transformation which_trans, bool involuntary, else if (which_trans == transformation::lich && you.duration[DUR_DEATHS_DOOR]) { - msg = "You cannot become a lich while in Death's Door."; + msg = "You cannot become a lich while in death's Door."; success = false; } From 49f49b0b75810b6aa984aeed3e58b733f569276a Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Wed, 15 May 2019 19:06:32 +0100 Subject: [PATCH 314/864] Re-brace --- crawl-ref/source/player.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index ae64033e1b17..1dd83d960f6f 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -2730,7 +2730,8 @@ void calc_hp(bool scale, bool set) you.hp_max = get_real_hp(true, true); - if (scale) { + if (scale) + { int hp = you.hp * 100 + you.hit_points_regeneration; int new_max = you.hp_max; hp = hp * new_max / old_max; From cf8e976b8c3a02d6799021ece93562eb0296e5bc Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Wed, 15 May 2019 20:10:48 +0100 Subject: [PATCH 315/864] Fix more capitalisation (NP7) --- crawl-ref/source/transform.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/transform.cc b/crawl-ref/source/transform.cc index e37acec7e7a7..26e31e945c09 100644 --- a/crawl-ref/source/transform.cc +++ b/crawl-ref/source/transform.cc @@ -1665,7 +1665,7 @@ bool transform(int pow, transformation which_trans, bool involuntary, else if (which_trans == transformation::lich && you.duration[DUR_DEATHS_DOOR]) { - msg = "You cannot become a lich while in death's Door."; + msg = "You cannot become a lich while in death's door."; success = false; } From 5cb8de4b220ce1f80f9e9642048ff994aeafdc83 Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 15 May 2019 16:36:09 -0400 Subject: [PATCH 316/864] Don't send invalid json to spectators when a popup is open (#1065) This prevents a trailing comma for the ui stack, which is not valid json (though it is valid javascript). Not sure if this had a practical impact on the main browsers in use, but there are definitely parsers that care, so this might matter for bots. Resolves #1065 --- crawl-ref/source/tileweb.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/tileweb.cc b/crawl-ref/source/tileweb.cc index aee2ec23ba39..352087870d29 100644 --- a/crawl-ref/source/tileweb.cc +++ b/crawl-ref/source/tileweb.cc @@ -1785,6 +1785,7 @@ void TilesFramework::_send_everything() json_open_array("items"); for (UIStackFrame &frame : m_menu_stack) { + json_write_comma(); // noop immediately following open if (frame.type == UIStackFrame::MENU) frame.menu->webtiles_write_menu(); else if (frame.type == UIStackFrame::CRT) @@ -1806,7 +1807,6 @@ void TilesFramework::_send_everything() } continue; } - json_write_comma(); } json_close_array(); json_close_object(); From 99e5aa4d39f5a72aa69f230fa97a40ce2e2b8f61 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 16 May 2019 10:38:24 -0400 Subject: [PATCH 317/864] Clean up some exit reason handling (alexjurkiewicz) Always send a tiles "cancel" message on game_exit::abort -- before, this was done manually on each game_ended call, and the seed menu was missing it. --- crawl-ref/source/end.cc | 4 ++++ crawl-ref/source/newgame.cc | 14 -------------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/crawl-ref/source/end.cc b/crawl-ref/source/end.cc index bd976261d594..e9e7216051de 100644 --- a/crawl-ref/source/end.cc +++ b/crawl-ref/source/end.cc @@ -518,6 +518,10 @@ NORETURN void game_ended(game_exit exit, const string &message) else end(retval); } +#ifdef USE_TILE_WEB + else if (exit == game_exit::abort) + tiles.send_exit_reason("cancel"); +#endif throw game_ended_condition(exit, message); } diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index ada661f63616..9151034755ef 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -397,12 +397,7 @@ static bool _reroll_random(newgame_def& ng) ui::run_layout(move(popup), done); if (key_is_escape(c) || toalower(c) == 'q' || crawl_state.seen_hups) - { -#ifdef USE_TILE_WEB - tiles.send_exit_reason("cancel"); -#endif game_ended(game_exit::abort); - } return toalower(c) == 'n' || c == '\t' || c == '!' || c == '#'; } @@ -433,9 +428,6 @@ static void _choose_char(newgame_def& ng, newgame_def& choice, if (!yesno("Trunk games don't count for the tournament, you want " TOURNEY ". Play trunk anyway? (Y/N)", false, 'n')) { -#ifdef USE_TILE_WEB - tiles.send_exit_reason("cancel"); -#endif game_ended(game_exit::abort); } } @@ -1438,9 +1430,6 @@ bool UINewGameMenu::on_event(const wm_event& ev) return done = end_game = true; CASE_ESCAPE case CK_MOUSE_CMD: -#ifdef USE_TILE_WEB - tiles.send_exit_reason("cancel"); -#endif return done = cancel = true; case CK_BKSP: if (choice_type == C_JOB) @@ -2375,9 +2364,6 @@ static void _prompt_gamemode_map(newgame_def& ng, newgame_def& ng_choice, end(0); break; CASE_ESCAPE -#ifdef USE_TILE_WEB - tiles.send_exit_reason("cancel"); -#endif return done = cancel = true; break; case ' ': From 827b87abe506e51fcf6f75532753800dda84a464 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 16 May 2019 10:56:57 -0400 Subject: [PATCH 318/864] Better handle webtiles messaging on game_exit::abort Some messaging on certain rare abort cases wasn't showing up in webtiles; most of these in practice only happen in offline settings. --- crawl-ref/source/end.cc | 2 +- crawl-ref/source/webserver/static/scripts/client.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/end.cc b/crawl-ref/source/end.cc index e9e7216051de..2d794c3515ea 100644 --- a/crawl-ref/source/end.cc +++ b/crawl-ref/source/end.cc @@ -520,7 +520,7 @@ NORETURN void game_ended(game_exit exit, const string &message) } #ifdef USE_TILE_WEB else if (exit == game_exit::abort) - tiles.send_exit_reason("cancel"); + tiles.send_exit_reason("cancel", message); #endif throw game_ended_condition(exit, message); } diff --git a/crawl-ref/source/webserver/static/scripts/client.js b/crawl-ref/source/webserver/static/scripts/client.js index ebcc2ba0ccee..216377498351 100644 --- a/crawl-ref/source/webserver/static/scripts/client.js +++ b/crawl-ref/source/webserver/static/scripts/client.js @@ -870,7 +870,8 @@ function (exports, $, key_conversion, chat, comm) { if (exit_reason) { - if (was_watching || normal_exit.indexOf(exit_reason) === -1) + if (was_watching || normal_exit.indexOf(exit_reason) === -1 + || exit_message.length > 0) { show_exit_dialog(exit_reason, exit_message, exit_dump, was_watching ? watching_username : null); From b207fdf2b9c6deaf243f6ccb005760cf51ee680c Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Thu, 16 May 2019 14:11:06 -0400 Subject: [PATCH 319/864] Always trigger net traps when a player steps on them Previously nets triggered on a one-chance-in-three like webs, but not symmetric with monsters interaction with net traps. The chance annoyed players attempting to disarm net traps and didn't otherwise contribute much. Making them always trigger is more consistent, less frustrating behavior. --- crawl-ref/source/traps.cc | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/crawl-ref/source/traps.cc b/crawl-ref/source/traps.cc index a93e4e0dd0ff..ceac3461b179 100644 --- a/crawl-ref/source/traps.cc +++ b/crawl-ref/source/traps.cc @@ -638,15 +638,8 @@ void trap_def::trigger(actor& triggerer) // Nets need LOF to hit the player, no netting through glass. if (!you.see_cell_no_trans(pos)) break; - bool triggered = false; - if (you_trigger) - { - if (one_chance_in(3)) - mpr("A net swings high above you."); - else - triggered = true; - } - else if (m) + bool triggered = you_triggered; + if (m) { if (mons_intel(*m) < I_HUMAN) { From 3e705edc117f1bd450afc447a59da8674d3f104b Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Thu, 16 May 2019 14:45:57 -0400 Subject: [PATCH 320/864] Fix the build --- crawl-ref/source/traps.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/traps.cc b/crawl-ref/source/traps.cc index ceac3461b179..10d472d5f123 100644 --- a/crawl-ref/source/traps.cc +++ b/crawl-ref/source/traps.cc @@ -638,7 +638,7 @@ void trap_def::trigger(actor& triggerer) // Nets need LOF to hit the player, no netting through glass. if (!you.see_cell_no_trans(pos)) break; - bool triggered = you_triggered; + bool triggered = you_trigger; if (m) { if (mons_intel(*m) < I_HUMAN) From c2ce88318c879099446056db63971e77e5e1d24d Mon Sep 17 00:00:00 2001 From: Umer Shaikh Date: Mon, 15 Apr 2019 13:46:41 -0500 Subject: [PATCH 321/864] Minor style cleanup Fix some typos, break some long lines, and adjust some indentation. --- crawl-ref/source/stash.cc | 44 ++++++++++++++++++++++----------------- crawl-ref/source/stash.h | 9 ++++---- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/crawl-ref/source/stash.cc b/crawl-ref/source/stash.cc index b5efca0d05a2..012e547ffb8a 100644 --- a/crawl-ref/source/stash.cc +++ b/crawl-ref/source/stash.cc @@ -1251,7 +1251,9 @@ static bool _is_potentially_boring(stash_search_result res) && (item_type_known(res.item) || !item_is_branded(res.item)); } -static bool _is_duplicate_for_search(stash_search_result l, stash_search_result r, bool ignore_missile_stacks=true) +static bool _is_duplicate_for_search(stash_search_result l, + stash_search_result r, + bool ignore_missile_stacks=true) { if (l.in_inventory || r.in_inventory) return false; @@ -1387,7 +1389,8 @@ static vector _stash_filter_duplicates(vector 0) { - matchtitle << " (" << res.duplicates << " further duplicate" << (res.duplicates == 1 ? "" : "s"); + matchtitle << " (" << res.duplicates << " further duplicate" << + (res.duplicates == 1 ? "" : "s"); if (res.duplicates != res.duplicate_piles) { matchtitle << " in " << res.duplicate_piles diff --git a/crawl-ref/source/stash.h b/crawl-ref/source/stash.h index b0a06e1c9f8d..07ab1f3dba70 100644 --- a/crawl-ref/source/stash.h +++ b/crawl-ref/source/stash.h @@ -129,7 +129,7 @@ struct stash_search_result // Item that was matched. item_def item; - // The shop in question, if this is result is for a shop name. + // The shop in question, if this result is for a shop name. const ShopInfo *shop; // Whether the found items are in the player's inventory. @@ -139,8 +139,9 @@ struct stash_search_result int duplicates; int duplicate_piles; - stash_search_result() : pos(), player_distance(0), match(), primary_sort(), item(), - shop(nullptr), in_inventory(false), duplicates(0), duplicate_piles(0) + stash_search_result() : pos(), player_distance(0), match(), primary_sort(), + item(), shop(nullptr), in_inventory(false), + duplicates(0), duplicate_piles(0) { } @@ -249,7 +250,7 @@ class StashTracker // Mark nets at (x,y) on current level as no longer trapping an actor. bool unmark_trapping_nets(const coord_def &c); - void add_stash(coord_def p); + void add_stash(coord_def p); void save(writer&) const; void load(reader&); From 98db4a99afdf39c1ba5dd88b9025b4175dc51a4f Mon Sep 17 00:00:00 2001 From: Umer Shaikh Date: Sat, 27 Apr 2019 20:40:52 -0500 Subject: [PATCH 322/864] Make StashTrack pay attention to traps When updating stashes in LOS, take traps seriously enough as a feature to add a stash for them. Something like this may have been already intended, since stashes have a trap field that is supposed to be set to a non-trivial value in Stash::update. This part of the code wasn't reached since is_boring_feature(feat) is false when feat is a trap. (See also commits 23c5277317de657f8376d1b5f33144948a811a42 and cbc0dd1c0e73770878e9a6df1b455e57995ef921.) This change has traps added to the stash tracker as the player comes upon them. Unfortunately players of ongoing games will not be able to search for traps they have encountered that are no longer in LOS. --- crawl-ref/source/stash.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/stash.cc b/crawl-ref/source/stash.cc index 012e547ffb8a..ef7a5312a2b2 100644 --- a/crawl-ref/source/stash.cc +++ b/crawl-ref/source/stash.cc @@ -225,7 +225,8 @@ bool Stash::needs_stop() const bool Stash::is_boring_feature(dungeon_feature_type feature) { // Count shops as boring features, because they are handled separately. - return !is_notable_terrain(feature) || feature == DNGN_ENTER_SHOP; + return !is_notable_terrain(feature) && !feat_is_trap(feature) + || feature == DNGN_ENTER_SHOP; } static bool _grid_has_perceived_item(const coord_def& pos) From 7b9fd8457661c3fcbbd0d93c66daa9ec5541c444 Mon Sep 17 00:00:00 2001 From: Umer Shaikh Date: Sun, 28 Apr 2019 12:56:02 -0500 Subject: [PATCH 323/864] Detach matching features in stash search from items on feature Prior to this change, this line meant that if you had a findable feature (e.g., a portal entrance) you would only see it in a stash search if you weren't also matching any of the items on top of it. I don't see why the player would reasonably expect this behaviour. --- crawl-ref/source/stash.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/stash.cc b/crawl-ref/source/stash.cc index ef7a5312a2b2..c494fea90c91 100644 --- a/crawl-ref/source/stash.cc +++ b/crawl-ref/source/stash.cc @@ -468,7 +468,7 @@ vector Stash::matches_search( } } - if (results.empty() && feat != DNGN_FLOOR) + if (feat != DNGN_FLOOR) { const string fdesc = feature_description(); if (!fdesc.empty() && search.matches(fdesc)) From 8f53b652b2632155ee910e00c14933c3886859cc Mon Sep 17 00:00:00 2001 From: Umer Shaikh Date: Sun, 28 Apr 2019 16:55:40 -0500 Subject: [PATCH 324/864] Add data about object matched to stash search result --- crawl-ref/source/stash.h | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/stash.h b/crawl-ref/source/stash.h index 07ab1f3dba70..51c2fb792f45 100644 --- a/crawl-ref/source/stash.h +++ b/crawl-ref/source/stash.h @@ -110,6 +110,15 @@ class ShopInfo friend class ST_ItemIterator; }; +enum stash_match_type +{ + MATCH_UNKNOWN, + MATCH_ITEM, + MATCH_SHOP, + MATCH_FEATURE, + MATCH_NUM_MATCH_TYPE +}; + struct stash_search_result { // Where's this thingummy of interest. @@ -119,6 +128,9 @@ struct stash_search_result // is on. int player_distance; + // Type of thing found. + stash_match_type match_type; + // Text that describes this search result - usually the name of // the first matching item in the stash or the name of the shop. string match; @@ -132,6 +144,9 @@ struct stash_search_result // The shop in question, if this result is for a shop name. const ShopInfo *shop; + // Type of feature, if this result is for a feature. + dungeon_feature_type feat; + // Whether the found items are in the player's inventory. bool in_inventory; @@ -139,9 +154,10 @@ struct stash_search_result int duplicates; int duplicate_piles; - stash_search_result() : pos(), player_distance(0), match(), primary_sort(), - item(), shop(nullptr), in_inventory(false), - duplicates(0), duplicate_piles(0) + stash_search_result() : pos(), player_distance(0), match_type(), match(), + primary_sort(), item(), shop(nullptr), feat(), + in_inventory(false), duplicates(0), + duplicate_piles(0) { } From 319a8a02d9f07204832276e7321511679a885e3c Mon Sep 17 00:00:00 2001 From: Umer Shaikh Date: Sun, 28 Apr 2019 20:13:24 -0500 Subject: [PATCH 325/864] Make stash searching for a place abbreviation pull up features Prior to this change, searching stashes with the search term '.' while on D:2 and searching for 'D:2' while on D:2 had different results. This was because the search term was matched against a location prefix for items but not for features. According to the search help screen the search term '.' should list everything on the current level, so I conclude the difference here is unintentional. --- crawl-ref/source/stash.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/stash.cc b/crawl-ref/source/stash.cc index c494fea90c91..9c4432bb8262 100644 --- a/crawl-ref/source/stash.cc +++ b/crawl-ref/source/stash.cc @@ -471,7 +471,7 @@ vector Stash::matches_search( if (feat != DNGN_FLOOR) { const string fdesc = feature_description(); - if (!fdesc.empty() && search.matches(fdesc)) + if (!fdesc.empty() && search.matches(prefix + " " + fdesc)) { stash_search_result res; res.match = fdesc; From c6a89e5090db31aff260ff0d2ce7fd50d8d7339b Mon Sep 17 00:00:00 2001 From: Umer Shaikh Date: Sun, 28 Apr 2019 20:19:26 -0500 Subject: [PATCH 326/864] Allow stash search deduplication to do its magic for features This commit allows trap features to be collapsed in the stash search results screen, as is the case for items. The commit should make it easy to extend that capability to other feature types, if it's decided that more features should be exposed to stash search. --- crawl-ref/source/stash.cc | 46 +++++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/crawl-ref/source/stash.cc b/crawl-ref/source/stash.cc index 9c4432bb8262..b72c8a936d8f 100644 --- a/crawl-ref/source/stash.cc +++ b/crawl-ref/source/stash.cc @@ -461,6 +461,7 @@ vector Stash::matches_search( || is_dumpable_artefact(item) && search.matches(chardump_desc(item))) { stash_search_result res; + res.match_type = MATCH_ITEM; res.match = s; res.primary_sort = item.name(DESC_QUALNAME); res.item = item; @@ -474,8 +475,10 @@ vector Stash::matches_search( if (!fdesc.empty() && search.matches(prefix + " " + fdesc)) { stash_search_result res; + res.match_type = MATCH_FEATURE; res.match = fdesc; res.primary_sort = fdesc; + res.feat = feat; results.push_back(res); } } @@ -708,6 +711,7 @@ vector ShopInfo::matches_search( stash_search_result res; res.match = shoptitle; res.primary_sort = shoptitle; + res.match_type = MATCH_SHOP; res.shop = this; res.pos.pos = shop.pos; results.push_back(res); @@ -730,6 +734,7 @@ vector ShopInfo::matches_search( || search.matches(shop_item_desc(item))) { stash_search_result res; + res.match_type = MATCH_ITEM; res.match = sname; res.primary_sort = item.name(DESC_QUALNAME); res.item = item; @@ -1245,11 +1250,13 @@ class stash_search_reader : public line_reader static bool _is_potentially_boring(stash_search_result res) { - return res.item.defined() && !res.in_inventory && !res.shop - && (res.item.base_type == OBJ_WEAPONS - || res.item.base_type == OBJ_ARMOUR - || res.item.base_type == OBJ_MISSILES) - && (item_type_known(res.item) || !item_is_branded(res.item)); + return res.match_type == MATCH_ITEM && res.item.defined() + && !res.in_inventory + && (res.item.base_type == OBJ_WEAPONS + || res.item.base_type == OBJ_ARMOUR + || res.item.base_type == OBJ_MISSILES) + && (item_type_known(res.item) || !item_is_branded(res.item)) + || res.match_type == MATCH_FEATURE && feat_is_trap(res.feat); } static bool _is_duplicate_for_search(stash_search_result l, @@ -1392,10 +1399,29 @@ static vector _stash_filter_duplicates(vector Date: Sun, 28 Apr 2019 21:32:11 -0500 Subject: [PATCH 327/864] Minor cleanup in stash search help screen Adjust some long lines, remove reference to an obsolete feature, change the example trap to a more currently relevant type of trap. [Closes #1051] --- crawl-ref/source/dat/database/help.txt | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/crawl-ref/source/dat/database/help.txt b/crawl-ref/source/dat/database/help.txt index 780534e46243..9d42ebf31320 100644 --- a/crawl-ref/source/dat/database/help.txt +++ b/crawl-ref/source/dat/database/help.txt @@ -110,12 +110,13 @@ that contain the spell. You can search for artefact item properties (such as /prevents.*teleport) to find artefacts that have the property. -You can search by some additional item properties: artefact or artifact will -find identified artefacts, ego or branded will find non-artefacts with a -brand and unidentified items which may be branded, throwable will find things -you can throw, dropped will find items you have dropped, in_shop will find -items in shops, and (if the autopickup_search option is enabled) autopickup will find -items that would be automatically picked up. +You can search by some additional item properties: artefact or +artifact will find identified artefacts, ego or branded +will find non-artefacts with a brand and unidentified items which may be +branded, throwable will find things you can throw, dropped will +find items you have dropped, in_shop will find items in shops, and (if +the autopickup_search option is enabled) autopickup will find items that +would be automatically picked up. Skill names (such as Polearms or Long Blades) will find all weapons that train that skill. You can also look for melee weapon and ranged weapon. @@ -126,10 +127,10 @@ Use armour && !!body to list all armour pieces except for body armour. Finding Dungeon Features: -You can search for dungeon features by name: all shops will be found by a -search for shop (including shops that do not have "shop" in their name); -other dungeon features can also be found by name: fountain, spear trap, -altar, etc. You can also search for altars by deity name: Zin. +You can search for dungeon features by name: all shops will be found by a search +for shop (including shops that do not have "shop" in their name); other +dungeon features can also be found by name: dispersal trap, altar, +etc. You can also search for altars by deity name: Zin. Non-regex operators: From 0b8c503fbf503534fb7a6d5a20d9210b95bca0ac Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Sun, 3 Mar 2019 19:53:40 +0000 Subject: [PATCH 328/864] Add a warning for summoning/enslaving monsters under OTR (11181, 11913) Add a prompt when casting a summoning spell that can create monsters that do not resist poison while under the Toxic status, and use this prompt for all summoning spells with the potential to create non-rPois monsters, as well as when enslaving non-rPois monsters. Note that this is never a penance prompt; a subsequent commit will make it so that Olgreb's Toxic Radiance triggers ally conducts when cast but not on subsequent turns (to avoid inadvertent penance). This commit also prevents Beogh from gifting orcs while OTR is active, which would cause the orcs to become hostile immediately (but not cause penance). --- crawl-ref/source/beam.cc | 13 ++++++++++++ crawl-ref/source/fight.cc | 35 +++++++++++++++++++++++++++++-- crawl-ref/source/fight.h | 2 ++ crawl-ref/source/god-blessing.cc | 5 +++++ crawl-ref/source/spl-summoning.cc | 32 ++++++++++++++++++++++++++++ 5 files changed, 85 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc index 33484d4ab32d..04d9c8127969 100644 --- a/crawl-ref/source/beam.cc +++ b/crawl-ref/source/beam.cc @@ -4189,6 +4189,19 @@ void bolt::handle_stop_attack_prompt(monster* mon) beam_cancelled = true; finish_beam(); } + // Handle enslaving monsters when OTR is up: give a prompt for attempting + // to enslave monsters that don't have rPois with Toxic status. + else if (flavour == BEAM_ENSLAVE && you.duration[DUR_TOXIC_RADIANCE] + && mon->res_poison() <= 0) + { + string verb = make_stringf("enslave %s", mon->name(DESC_THE).c_str()); + if (otr_stop_summoning_prompt(verb)) + { + beam_cancelled = true; + finish_beam(); + prompted = true; + } + } if (prompted) { diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc index 6361c80ff36a..c2b7df5905ca 100644 --- a/crawl-ref/source/fight.cc +++ b/crawl-ref/source/fight.cc @@ -873,8 +873,6 @@ int mons_usable_missile(monster* mons, item_def **launcher) } } - - bool bad_attack(const monster *mon, string& adj, string& suffix, bool& would_cause_penance, coord_def attack_pos) { @@ -1079,3 +1077,36 @@ bool stop_attack_prompt(targeter &hitfunc, const char* verb, return true; } } + +/** + * Does the player have Olgreb's Toxic Radiance up that would/could cause + * a hostile summon to be created? If so, prompt the player as to whether they + * want to continue to create their summon. Note that this prompt is never a + * penance prompt, because we don't cause penance when monsters enter line of + * sight when OTR is active, regardless of how they entered LOS. + * + * @param verb The verb to be used in the prompt. Defaults to "summon". + * @return True if the player wants to abort. + */ +bool otr_stop_summoning_prompt(string verb) +{ + if (!you.duration[DUR_TOXIC_RADIANCE]) + return false; + + if (crawl_state.disables[DIS_CONFIRMATIONS]) + return false; + + if (crawl_state.which_god_acting() == GOD_XOM) + return false; + + string prompt = make_stringf("Really %s while emitting a toxic aura?", + verb.c_str()); + + if (yesno(prompt.c_str(), false, 'n')) + return false; + else + { + canned_msg(MSG_OK); + return true; + } +} diff --git a/crawl-ref/source/fight.h b/crawl-ref/source/fight.h index 81fd5c016252..4d739e603322 100644 --- a/crawl-ref/source/fight.h +++ b/crawl-ref/source/fight.h @@ -73,3 +73,5 @@ bool stop_attack_prompt(targeter &hitfunc, const char* verb, function affects = nullptr, bool *prompted = nullptr, const monster *mons = nullptr); + +bool otr_stop_summoning_prompt(string verb = "summon"); diff --git a/crawl-ref/source/god-blessing.cc b/crawl-ref/source/god-blessing.cc index bd2b77234ebd..711bf1ad2881 100644 --- a/crawl-ref/source/god-blessing.cc +++ b/crawl-ref/source/god-blessing.cc @@ -575,6 +575,11 @@ static void _beogh_reinf_callback(const mgen_data &mg, monster *&mon, int placed // you out. static void _beogh_blessing_reinforcements() { + // Don't gift orcs if Toxic radiance is up, to avoid the player being + // penanced through no fault of their own. + if (you.duration[DUR_TOXIC_RADIANCE]) + return; + // Possible reinforcement. const monster_type followers[] = { diff --git a/crawl-ref/source/spl-summoning.cc b/crawl-ref/source/spl-summoning.cc index 29da4c99cfa8..0d2859d2e10c 100644 --- a/crawl-ref/source/spl-summoning.cc +++ b/crawl-ref/source/spl-summoning.cc @@ -92,6 +92,9 @@ static mgen_data _pal_data(monster_type pal, int dur, god_type god, spret cast_summon_butterflies(int pow, god_type god, bool fail) { + if (otr_stop_summoning_prompt()) + return spret::abort; + fail_check(); bool success = false; @@ -114,6 +117,9 @@ spret cast_summon_butterflies(int pow, god_type god, bool fail) spret cast_summon_small_mammal(int pow, god_type god, bool fail) { + if (otr_stop_summoning_prompt()) + return spret::abort; + fail_check(); monster_type mon = MONS_PROGRAM_BUG; @@ -157,6 +163,10 @@ spret cast_sticks_to_snakes(int pow, god_type god, bool fail) mpr("You don't have anything to turn into a snake."); return spret::abort; } + + if (otr_stop_summoning_prompt("create snakes")) + return spret::abort; + // Sort by the quantity if the player has no bow skill; this will // put arrows with the smallest quantity first in line // If the player has bow skill, we will already have plain arrows @@ -227,6 +237,9 @@ spret cast_sticks_to_snakes(int pow, god_type god, bool fail) spret cast_call_canine_familiar(int pow, god_type god, bool fail) { + if (otr_stop_summoning_prompt()) + return spret::abort; + fail_check(); monster_type mon = MONS_PROGRAM_BUG; @@ -266,6 +279,9 @@ spret cast_summon_ice_beast(int pow, god_type god, bool fail) spret cast_monstrous_menagerie(actor* caster, int pow, god_type god, bool fail) { + if (otr_stop_summoning_prompt()) + return spret::abort; + fail_check(); monster_type type = MONS_PROGRAM_BUG; @@ -382,6 +398,9 @@ spret cast_dragon_call(int pow, bool fail) return spret::abort; } + if (otr_stop_summoning_prompt("call dragons")) + return spret::abort; + fail_check(); mpr("You call out to the draconic realm, and the dragon horde roars back!"); @@ -1148,6 +1167,10 @@ bool summon_demon_type(monster_type mon, int pow, god_type god, spret cast_summon_demon(int pow, god_type god, bool fail) { + // Chaos spawn, orange demons and sixfirhies are not rPois + if (otr_stop_summoning_prompt()) + return spret::abort; + fail_check(); mpr("You open a gate to Pandemonium!"); @@ -1159,6 +1182,9 @@ spret cast_summon_demon(int pow, god_type god, bool fail) spret cast_summon_greater_demon(int pow, god_type god, bool fail) { + if (otr_stop_summoning_prompt()) + return spret::abort; + fail_check(); mpr("You open a gate to Pandemonium!"); @@ -1171,6 +1197,9 @@ spret cast_summon_greater_demon(int pow, god_type god, bool fail) spret cast_shadow_creatures(int st, god_type god, level_id place, bool fail) { + if (otr_stop_summoning_prompt("summon")) + return spret::abort; + fail_check(); const bool scroll = (st == MON_SUMM_SCROLL); mpr("Wisps of shadow whirl around you..."); @@ -1409,6 +1438,9 @@ spret cast_summon_forest(actor* caster, int pow, god_type god, bool fail) if (success) { + if (otr_stop_summoning_prompt("summon a forest")) + return spret::abort; + fail_check(); // Replace some rock walls with trees, then scatter a smaller number // of trees on unoccupied floor (such that they do not break connectivity) From 6e2f17f9f6ad3195020b3ab8896cffad9919735e Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Sun, 21 Apr 2019 11:26:25 +0100 Subject: [PATCH 329/864] Trigger ally conducts on casting Olgreb's Toxic Radiance Firstly, reduce the duration of the Toxic status by 1 turn and have OTR poison monsters on the turn it is cast, rather than starting the turn after it is cast. This means calling toxic_radiance_effect in the cast_toxic_radiance function. This keeps the damage from Olgreb's the same, and reduces the delay in dealing the damage by 1 turn. Secondly, with the help of this new call to toxic_radiance_effect, trigger ally conducts on casting Olgreb's Toxic Radiance when there are allies without rPois in line of sight, but don't trigger conducts when allies are hurt by the Toxic status on subsequent turns. This fixes the previously inaccurate penance warning on casting OTR with allies around (this penance warning is now correct), and prevents OTR being used to turn allies hostile on demand without penance with gods that give ally penance. This also prevents the player being placed under penance inadvertently through no/little fault of their own when allies walk into line of sight at the wrong time. For consistency's sake, this also means that, should the player summon non-rPois allies during OTR, the player won't receive penance. I don't think this is a problem, because the ally will still turn hostile and there is now a warning about summoning non-rPois monsters, so doing so would be ill-advised anyway. [Closes #999] --- crawl-ref/source/spl-damage.cc | 37 ++++++++++++++++++++++++++++------ crawl-ref/source/spl-damage.h | 2 +- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/crawl-ref/source/spl-damage.cc b/crawl-ref/source/spl-damage.cc index 11607e5f3841..4f1b1f27b149 100644 --- a/crawl-ref/source/spl-damage.cc +++ b/crawl-ref/source/spl-damage.cc @@ -2617,7 +2617,8 @@ spret cast_toxic_radiance(actor *agent, int pow, bool fail, bool mon_tracer) else mpr("Your toxic radiance grows in intensity."); - you.increase_duration(DUR_TOXIC_RADIANCE, 3 + random2(pow/20), 15); + you.increase_duration(DUR_TOXIC_RADIANCE, 2 + random2(pow/20), 15); + toxic_radiance_effect(&you, 1, true); flash_view_delay(UA_PLAYER, GREEN, 300, &hitfunc); @@ -2643,7 +2644,8 @@ spret cast_toxic_radiance(actor *agent, int pow, bool fail, bool mon_tracer) " begins to radiate toxic energy."); mon_agent->add_ench(mon_enchant(ENCH_TOXIC_RADIANCE, 1, mon_agent, - (5 + random2avg(pow/15, 2)) * BASELINE_DELAY)); + (4 + random2avg(pow/15, 2)) * BASELINE_DELAY)); + toxic_radiance_effect(agent, 1); targeter_los hitfunc(mon_agent, LOS_NO_TRANS); flash_view_delay(UA_MONSTER, GREEN, 300, &hitfunc); @@ -2652,7 +2654,20 @@ spret cast_toxic_radiance(actor *agent, int pow, bool fail, bool mon_tracer) } } -void toxic_radiance_effect(actor* agent, int mult) +/* + * Attempt to poison all monsters in line of sight of the caster. + * + * @param agent The caster. + * @param mult A number to multiply the damage by. + * This is the time taken for the player's action in turns, + * or 1 if the spell was cast this turn. + * @param on_cast Whether the spell was cast this turn. This only matters + * if the player cast the spell. If true, we trigger conducts + * if the player hurts allies; if false, we don't, to avoid + * the player being accidentally put under penance. + * Defaults to false. + */ +void toxic_radiance_effect(actor* agent, int mult, bool on_cast) { int pow; if (agent->is_player()) @@ -2689,7 +2704,20 @@ void toxic_radiance_effect(actor* agent, int mult) } else { + // We need to deal with conducts before damaging the monster, + // because otherwise friendly monsters that are one-shot won't + // trigger conducts. Only trigger conducts on the turn the player + // casts the spell (see PR #999). + if (on_cast && agent->is_player()) + { + god_conduct_trigger conducts[3]; + set_attack_conducts(conducts, *ai->as_monster()); + if (is_sanctuary(ai->pos())) + break_sanctuary = true; + } + ai->hurt(agent, dam, BEAM_POISON); + if (ai->alive()) { behaviour_event(ai->as_monster(), ME_ANNOY, agent, @@ -2697,9 +2725,6 @@ void toxic_radiance_effect(actor* agent, int mult) if (coinflip() || !ai->as_monster()->has_ench(ENCH_POISON)) poison_monster(ai->as_monster(), agent, 1); } - - if (agent->is_player() && is_sanctuary(ai->pos())) - break_sanctuary = true; } } diff --git a/crawl-ref/source/spl-damage.h b/crawl-ref/source/spl-damage.h index 3e61bc727078..cc7153f2c5b7 100644 --- a/crawl-ref/source/spl-damage.h +++ b/crawl-ref/source/spl-damage.h @@ -57,7 +57,7 @@ spret cast_dazzling_spray(int pow, coord_def aim, bool fail); spret cast_toxic_radiance(actor *caster, int pow, bool fail = false, bool mon_tracer = false); -void toxic_radiance_effect(actor* agent, int mult); +void toxic_radiance_effect(actor* agent, int mult, bool on_cast = false); spret cast_searing_ray(int pow, bolt &beam, bool fail); void handle_searing_ray(); From ea32a606ab6609538d492db51d74039ce29b958a Mon Sep 17 00:00:00 2001 From: Josh Braden Date: Fri, 3 May 2019 16:30:25 -0500 Subject: [PATCH 330/864] Don't place a wall if a monster is in the way (11967) Noticed in bug 11967, monsters are able to exist in walls if a floor is turned into a wall via dungeon_terrain_changed() Done in two parts: 1. Make _dgn_check_terrain_monsters return bool if a monster is present 2. Don't continue with wall placement if a monster is present --- crawl-ref/source/terrain.cc | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/terrain.cc b/crawl-ref/source/terrain.cc index c1c0ce6e0d84..77528b4dc7bf 100644 --- a/crawl-ref/source/terrain.cc +++ b/crawl-ref/source/terrain.cc @@ -1144,10 +1144,15 @@ static void _dgn_check_terrain_items(const coord_def &pos, bool preserve_items) } } -static void _dgn_check_terrain_monsters(const coord_def &pos) +static bool _dgn_check_terrain_monsters(const coord_def &pos) { if (monster* m = monster_at(pos)) + { m->apply_location_effects(pos); + return true; + } + else + return false; } // Clear blood or mold off of terrain that shouldn't have it. Also clear @@ -1223,6 +1228,8 @@ void dungeon_terrain_changed(const coord_def &pos, { if (grd(pos) == nfeat) return; + if (_dgn_check_terrain_monsters(pos) && feat_is_wall(nfeat)) + return; _dgn_check_terrain_covering(pos, grd(pos), nfeat); @@ -1248,7 +1255,6 @@ void dungeon_terrain_changed(const coord_def &pos, } _dgn_check_terrain_items(pos, preserve_items); - _dgn_check_terrain_monsters(pos); if (!wizmode) _dgn_check_terrain_player(pos); if (!temporary && feature_mimic_at(pos)) From 49c61e0142e268ce48e334172139df900768b58f Mon Sep 17 00:00:00 2001 From: Josh Braden Date: Thu, 2 May 2019 11:56:59 -0500 Subject: [PATCH 331/864] Check and clear emergency flight if transforming into something that can fly (11965) --- crawl-ref/source/transform.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crawl-ref/source/transform.cc b/crawl-ref/source/transform.cc index 26e31e945c09..484e6156f999 100644 --- a/crawl-ref/source/transform.cc +++ b/crawl-ref/source/transform.cc @@ -1880,6 +1880,14 @@ bool transform(int pow, transformation which_trans, bool involuntary, if (was_flying && !you.airborne()) move_player_to_grid(you.pos(), false); + // Stop emergency flight if it's activated and this form can fly + if (you.props[EMERGENCY_FLIGHT_KEY] + && form_can_fly() + && you.airborne()) + { + you.props.erase(EMERGENCY_FLIGHT_KEY); + } + // Update merfolk swimming for the form change. if (you.species == SP_MERFOLK) merfolk_check_swimming(false); From 864f2b5d03d6e7229e0d6d9bd128ba1eb3260925 Mon Sep 17 00:00:00 2001 From: Josh Braden Date: Wed, 1 May 2019 14:46:57 -0500 Subject: [PATCH 332/864] Stop constriction when Bai Suzhen transforms into a dragon (11954) --- crawl-ref/source/monster.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crawl-ref/source/monster.cc b/crawl-ref/source/monster.cc index 8643b1898b66..f56b2efbbde0 100644 --- a/crawl-ref/source/monster.cc +++ b/crawl-ref/source/monster.cc @@ -6159,6 +6159,8 @@ void monster::react_to_damage(const actor *oppressor, int damage, } if (caught()) check_net_will_hold_monster(this); + if (this->is_constricted()) + this->stop_being_constricted(); add_ench(ENCH_RING_OF_THUNDER); } From 5a7c77285f7285388c2c6fa79a8851b758eeaf3d Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Fri, 17 May 2019 16:42:48 +0100 Subject: [PATCH 333/864] Don't generate randart rings with rCorr and *Corrode Also fixes their descriptions missing information on the rCorr base type. --- crawl-ref/source/artefact.cc | 13 +++++++++++-- crawl-ref/source/describe.cc | 1 - 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/artefact.cc b/crawl-ref/source/artefact.cc index 65ff3b871ba6..878535a9896f 100644 --- a/crawl-ref/source/artefact.cc +++ b/crawl-ref/source/artefact.cc @@ -380,6 +380,7 @@ static map> jewellery_artps = { { RING_POISON_RESISTANCE, { { ARTP_POISON, 1 } } }, { RING_LIFE_PROTECTION, { { ARTP_NEGATIVE_ENERGY, 1 } } }, { RING_PROTECTION_FROM_MAGIC, { { ARTP_MAGIC_RESISTANCE, 1 } } }, + { RING_RESIST_CORROSION, { { ARTP_RCORR, 1 } } }, { RING_FIRE, { { ARTP_FIRE, 1 }, { ARTP_COLD, -1 } } }, { RING_ICE, { { ARTP_COLD, 1 }, { ARTP_FIRE, -1 } } }, @@ -409,7 +410,7 @@ static void _populate_jewel_intrinsic_artps(const item_def &item, return; const bool id_props = item_ident(item, ISFLAG_KNOW_PROPERTIES) - || item_ident(item, ISFLAG_KNOW_TYPE); + || item_ident(item, ISFLAG_KNOW_TYPE); for (const auto &fake_artp : *props) { @@ -1439,7 +1440,7 @@ static bool _randart_is_redundant(const item_def &item, break; case RING_SLAYING: - provides = ARTP_SLAYING; + provides = ARTP_SLAYING; break; case RING_SEE_INVISIBLE: @@ -1482,6 +1483,10 @@ static bool _randart_is_redundant(const item_def &item, provides = ARTP_MAGIC_RESISTANCE; break; + case RING_RESIST_CORROSION: + provides = ARTP_RCORR; + break; + case AMU_RAGE: provides = ARTP_BERSERK; break; @@ -1544,6 +1549,10 @@ static bool _randart_is_conflicting(const item_def &item, conflicts = ARTP_PREVENT_SPELLCASTING; break; + case RING_RESIST_CORROSION: + conflicts = ARTP_CORRODE; + break; + case RING_TELEPORTATION: #if TAG_MAJOR_VERSION == 34 case RING_TELEPORT_CONTROL: diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index 68125a5ee5dc..20bab2a5b9c5 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -235,7 +235,6 @@ const char* jewellery_base_ability_string(int subtype) case RING_FIRE: return "Fire"; case RING_ICE: return "Ice"; case RING_TELEPORTATION: return "*Tele"; - case RING_RESIST_CORROSION: return "rCorr"; #if TAG_MAJOR_VERSION == 34 case RING_TELEPORT_CONTROL: return "+cTele"; #endif From 06ca16af6cc759a4c209f43763f7d9984c26215a Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Fri, 17 May 2019 20:51:56 +0100 Subject: [PATCH 334/864] Fix spacing in a quote --- crawl-ref/source/dat/descript/quotes.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/dat/descript/quotes.txt b/crawl-ref/source/dat/descript/quotes.txt index f51ff4c5c891..ea8c1bb96e9a 100644 --- a/crawl-ref/source/dat/descript/quotes.txt +++ b/crawl-ref/source/dat/descript/quotes.txt @@ -2972,7 +2972,7 @@ against—whom?” %%%% boomerang -“The weapon, thrown at 20 or 30 yards distance, twirled round in the air with +“The weapon, thrown at 20 or 30 yards distance, twirled round in the air with astonishing velocity, and alighting on the right arm of one of his opponents, actually rebounded to a distance not less than 70 or 80 yards, leaving a horrible contusion behind, and exciting universal admiration.” From fcedfb35f78c44ff52411807c7f67ca3fdf27cd1 Mon Sep 17 00:00:00 2001 From: Joshua Gelbard Date: Fri, 15 Mar 2019 02:35:29 -0700 Subject: [PATCH 335/864] Add a menu shortcut to select last unequipped item In equipment-related menus and prompts, make ';' (semicolon) an alias for the letter of the player's most recently unequipped item. The goal of this change is to reduce the amount of time the player spends scanning through menus to remember which item is where. Examples: * Wear-IDing a good cloak ('f') and dropping your old one: Wfd; * Wear-IDing a bad cloak ('f') and re-equipping the old: WfW;d; * Swapping to a utility ring ('g') for a certain enemy, then going back to your usual ring: Pg 0) last_pickup[from_slot] = to_count; } + if (you.last_unequip == from_slot) + you.last_unequip = to_slot; } diff --git a/crawl-ref/source/dat/database/help.txt b/crawl-ref/source/dat/database/help.txt index 9d42ebf31320..b0ed7b12696d 100644 --- a/crawl-ref/source/dat/database/help.txt +++ b/crawl-ref/source/dat/database/help.txt @@ -22,8 +22,9 @@ You can quickly select items by type by pressing: / wands | magical staves ? scrolls : books " amulets = rings } miscellaneous % food Global selects: , select all * invert all - deselect all + ; select last unequipped Note that for dropping, the , command uses the drop_filter option, which -narrows the range of items to be (de)selected. The default are useless items. +narrows the range of items to be (de)selected. The default is to select useless items. %%%% known-menu diff --git a/crawl-ref/source/invent.cc b/crawl-ref/source/invent.cc index 6cd60ed8cd72..beef5fe11dd1 100644 --- a/crawl-ref/source/invent.cc +++ b/crawl-ref/source/invent.cc @@ -349,6 +349,14 @@ void InvMenu::set_title(const string &s) title_annotate)); } +int InvMenu::pre_process(int key) +{ + if (type == menu_type::drop || type == menu_type::invlist) + if (key == ';' && you.last_unequip != -1) + key = index_to_letter(you.last_unequip); + return key; +} + static bool _has_melded_armour() { for (int e = EQ_CLOAK; e <= EQ_BODY_ARMOUR; e++) @@ -1357,6 +1365,11 @@ vector prompt_drop_items(const vector &preselected_items) else break; } + else if (keyin == ';') + { + ret = you.last_unequip; + break; + } else if (!isspace(keyin)) { // We've got a character we don't understand... @@ -1943,6 +1956,11 @@ int prompt_invent_item(const char *prompt, else if (!do_warning || check_warning_inscriptions(you.inv[ret], oper)) break; } + else if (keyin == ';') + { + ret = you.last_unequip; + break; + } else if (!isspace(keyin)) { // We've got a character we don't understand... diff --git a/crawl-ref/source/invent.h b/crawl-ref/source/invent.h index 9f204eca25d3..2f6bc57e3f0a 100644 --- a/crawl-ref/source/invent.h +++ b/crawl-ref/source/invent.h @@ -196,6 +196,7 @@ class InvMenu : public Menu protected: void do_preselect(InvEntry *ie); + int pre_process(int key) override; virtual bool is_selectable(int index) const override; virtual string help_key() const override; diff --git a/crawl-ref/source/items.cc b/crawl-ref/source/items.cc index 35116fbc12d6..84cce5e568da 100644 --- a/crawl-ref/source/items.cc +++ b/crawl-ref/source/items.cc @@ -2629,6 +2629,8 @@ bool drop_item(int item_dropped, int quant_drop) you.turn_is_over = true; you.last_pickup.erase(item_dropped); + if (you.last_unequip == item.link) + you.last_unequip = -1; return true; } diff --git a/crawl-ref/source/menu.cc b/crawl-ref/source/menu.cc index 1540ae83f521..7cbc3ab8a053 100644 --- a/crawl-ref/source/menu.cc +++ b/crawl-ref/source/menu.cc @@ -1194,7 +1194,7 @@ bool Menu::process_key(int keyin) if (!page_down() && is_set(MF_WRAP)) m_ui.scroller->set_scroll(0); break; - case CK_PGUP: case '<': case ';': + case CK_PGUP: case '<': page_up(); break; case CK_UP: diff --git a/crawl-ref/source/player-equip.cc b/crawl-ref/source/player-equip.cc index 409d9b7c9d0c..f84c44d7ea6a 100644 --- a/crawl-ref/source/player-equip.cc +++ b/crawl-ref/source/player-equip.cc @@ -83,6 +83,7 @@ bool unequip_item(equipment_type slot, bool msg) else you.melded.set(slot, false); ash_check_bondage(); + you.last_unequip = item_slot; return true; } } diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 1dd83d960f6f..6066fe06bea1 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -5069,6 +5069,7 @@ player::player() equip.init(-1); melded.reset(); unrand_reacts.reset(); + last_unequip = -1; symbol = MONS_PLAYER; form = transformation::none; diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h index 42c4a047519c..25f6fa184eb8 100644 --- a/crawl-ref/source/player.h +++ b/crawl-ref/source/player.h @@ -393,7 +393,7 @@ class player : public actor // The last spell cast by the player. spell_type last_cast_spell; map last_pickup; - + int last_unequip; // --------------------------- // Volatile (same-turn) state: From 97e31042418dca85b2c03021017a6a7e014f3011 Mon Sep 17 00:00:00 2001 From: Joshua Gelbard Date: Sun, 17 Mar 2019 19:02:51 -0700 Subject: [PATCH 336/864] Fix '+' and '-' not being PGDN and PGUP as claimed Previously, menus using the default more prompt all claimed that '+' was pagedown and '-' was pageup, which was mostly false. This commit changes that to be mostly true and alters the prompt where it's not. On the drop, pickup, quiver, item knowledge, and wield menus, '-' has some other meaning, so those are the ones where '-' isn't listed as a usable pageup. '+' as pagedown should work everywhere. [Closes #1013] --- crawl-ref/docs/crawl_manual.rst | 2 +- crawl-ref/source/invent.cc | 16 ++++++++++++---- crawl-ref/source/menu.cc | 10 ++++++++-- crawl-ref/source/menu.h | 2 ++ 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/crawl-ref/docs/crawl_manual.rst b/crawl-ref/docs/crawl_manual.rst index e6993e68d6ec..3b44e9a9af50 100644 --- a/crawl-ref/docs/crawl_manual.rst +++ b/crawl-ref/docs/crawl_manual.rst @@ -2642,7 +2642,7 @@ will deselect it (except for ',' and '-', obviously). & Select all carrion and inedible food. -\+ or : +: Select all books. / diff --git a/crawl-ref/source/invent.cc b/crawl-ref/source/invent.cc index beef5fe11dd1..cafdc0fc0b70 100644 --- a/crawl-ref/source/invent.cc +++ b/crawl-ref/source/invent.cc @@ -351,9 +351,14 @@ void InvMenu::set_title(const string &s) int InvMenu::pre_process(int key) { - if (type == menu_type::drop || type == menu_type::invlist) - if (key == ';' && you.last_unequip != -1) - key = index_to_letter(you.last_unequip); + if (key == '-' && minus_is_pageup()) + key = CK_PGUP; + else if (key == ';' + && you.last_unequip != -1 + && (type == menu_type::drop || type == menu_type::invlist)) + { + key = index_to_letter(you.last_unequip); + } return key; } @@ -1888,12 +1893,15 @@ int prompt_invent_item(const char *prompt, // The "view inventory listing" mode. vector< SelItem > items; current_type_expected = keyin == '*' ? OSEL_ANY : type_expect; + int mflags = MF_SINGLESELECT | MF_ANYPRINTABLE | MF_NO_SELECT_QTY; + if (other_valid_char == '-') + mflags |= MF_SPECIAL_MINUS; keyin = _invent_select( prompt, mtype, current_type_expected, -1, - MF_SINGLESELECT | MF_ANYPRINTABLE | MF_NO_SELECT_QTY, + mflags, nullptr, &items); diff --git a/crawl-ref/source/menu.cc b/crawl-ref/source/menu.cc index 7cbc3ab8a053..2f7f38f76d59 100644 --- a/crawl-ref/source/menu.cc +++ b/crawl-ref/source/menu.cc @@ -912,6 +912,11 @@ void Menu::set_flags(int new_flags, bool use_options) #endif } +bool Menu::minus_is_pageup() const +{ + return !is_set(MF_MULTISELECT) && !is_set(MF_SPECIAL_MINUS); +} + void Menu::set_more(const formatted_string &fs) { m_keyhelp_more = false; @@ -922,9 +927,10 @@ void Menu::set_more(const formatted_string &fs) void Menu::set_more() { m_keyhelp_more = true; + string pageup_keys = minus_is_pageup() ? "-|<<" : "<<"; more = formatted_string::parse_string( "[+|>|Space]: page down " - "[-|<<]: page up " + "[" + pageup_keys + "]: page up " "[Esc]: close [XXX]" ); update_more(); @@ -1188,7 +1194,7 @@ bool Menu::process_key(int keyin) sel.clear(); lastch = keyin; return is_set(MF_UNCANCEL) && !crawl_state.seen_hups; - case ' ': case CK_PGDN: case '>': + case ' ': case CK_PGDN: case '>': case '+': case CK_MOUSE_B1: case CK_MOUSE_CLICK: if (!page_down() && is_set(MF_WRAP)) diff --git a/crawl-ref/source/menu.h b/crawl-ref/source/menu.h index f243225c16a6..eec5b038bca3 100644 --- a/crawl-ref/source/menu.h +++ b/crawl-ref/source/menu.h @@ -274,6 +274,7 @@ enum MenuFlag MF_USE_TWO_COLUMNS = 0x08000, ///< Only valid for tiles menus MF_UNCANCEL = 0x10000, ///< Menu is uncancellable + MF_SPECIAL_MINUS = 0x20000, ///< '-' isn't PGUP or clear multiselect }; class UIMenu; @@ -308,6 +309,7 @@ class Menu virtual bool is_set(int flag) const; void set_tag(const string& t) { tag = t; } + bool minus_is_pageup() const; // Sets a replacement for the default -more- string. void set_more(const formatted_string &more); // Shows a stock message about scrolling the menu instead of -more- From faf41a374d27c23002ebb7f4831033a95c112511 Mon Sep 17 00:00:00 2001 From: Joshua Gelbard Date: Fri, 29 Mar 2019 16:06:44 -0700 Subject: [PATCH 337/864] Let players disable autopickup from the drop menu Add a new "drop-and-disable-autopickup" mode for the drop menu, toggled with '\'. Items selected in this mode are marked with a '*' instead of a '+' and have their autopickup disabled when the menu is exited. This turns "drop unwanted item; disable autopickup for unwanted item" from a two-menu operation into a one-menu operation and makes the most vital bit of the '\' menu available in a more convenient location. InvEntry and SelItem each get a new field to record whether they're selected "normally" or in this new special way, and InvMenu gets a field recording which selection mode it's in. InvMenu now overrides ::pre_process() and ::select_item_index() to handle the new mode. Also, assorted cleanup/bugfixes: * Fix '_' on the drop prompt not actually bringing up the help menu. * _invent_select can't return PROMPT_GOT_SPECIAL, so don't check for it. * Replace anonymous you.force_autopickup ints with an enum * Add helper functions for easier access to you.force_autopickup * Demystify magic -1 to OSEL_ANY in a few places * Remove unused define PROMPT_INAPPROPRIATE --- crawl-ref/source/adjust.cc | 4 +- crawl-ref/source/butcher.cc | 2 +- crawl-ref/source/dat/database/help.txt | 7 +- .../source/dat/defaults/menu_colours.txt | 1 + crawl-ref/source/invent.cc | 113 ++++++++++++++---- crawl-ref/source/invent.h | 19 ++- crawl-ref/source/item-name.cc | 13 +- crawl-ref/source/items.cc | 42 ++++++- crawl-ref/source/items.h | 10 ++ crawl-ref/source/menu.h | 2 +- crawl-ref/source/ng-setup.cc | 2 +- crawl-ref/source/tags.cc | 2 +- crawl-ref/source/wiz-item.cc | 10 +- crawl-ref/source/wiz-mon.cc | 2 +- 14 files changed, 180 insertions(+), 49 deletions(-) diff --git a/crawl-ref/source/adjust.cc b/crawl-ref/source/adjust.cc index 38a1952f99f6..57771704d857 100644 --- a/crawl-ref/source/adjust.cc +++ b/crawl-ref/source/adjust.cc @@ -52,7 +52,7 @@ void adjust_item(int from_slot) if (from_slot == -1) { from_slot = prompt_invent_item("Adjust which item?", - menu_type::invlist, -1); + menu_type::invlist, OSEL_ANY); if (prompt_failed(from_slot)) return; @@ -61,7 +61,7 @@ void adjust_item(int from_slot) const int to_slot = prompt_invent_item("Adjust to which letter? ", menu_type::invlist, - -1, OPER_ANY, + OSEL_ANY, OPER_ANY, invprompt_flag::unthings_ok | invprompt_flag::manual_list); if (to_slot == PROMPT_ABORT diff --git a/crawl-ref/source/butcher.cc b/crawl-ref/source/butcher.cc index 75e2d0e4a501..6cd48971bca6 100644 --- a/crawl-ref/source/butcher.cc +++ b/crawl-ref/source/butcher.cc @@ -365,7 +365,7 @@ void turn_corpse_into_chunks(item_def &item, bool bloodspatter) item.quantity = stepdown_value(item.quantity, 4, 4, 12, 12); // Don't mark it as dropped if we are forcing autopickup of chunks. - if (you.force_autopickup[OBJ_FOOD][FOOD_CHUNK] <= 0 + if (you.force_autopickup[OBJ_FOOD][FOOD_CHUNK] <= AP_FORCE_NONE && is_bad_food(item)) { item.flags |= ISFLAG_DROPPED; diff --git a/crawl-ref/source/dat/database/help.txt b/crawl-ref/source/dat/database/help.txt index b0ed7b12696d..1db168d4132a 100644 --- a/crawl-ref/source/dat/database/help.txt +++ b/crawl-ref/source/dat/database/help.txt @@ -24,7 +24,12 @@ You can quickly select items by type by pressing: Global selects: , select all * invert all - deselect all ; select last unequipped Note that for dropping, the , command uses the drop_filter option, which -narrows the range of items to be (de)selected. The default is to select useless items. +narrows the range of items to be (de)selected. The default are useless items. + +Disabling autopickup via the drop menu +On the drop menu, items you select after pressing \ will be marked with a * +instead of the usual +. Autopickup for these items will be disabled when you +leave the menu. To return to the normal selection mode, press \ a second time. %%%% known-menu diff --git a/crawl-ref/source/dat/defaults/menu_colours.txt b/crawl-ref/source/dat/defaults/menu_colours.txt index f40146a811d6..da064ebf42ad 100644 --- a/crawl-ref/source/dat/defaults/menu_colours.txt +++ b/crawl-ref/source/dat/defaults/menu_colours.txt @@ -68,6 +68,7 @@ menu_colour += pickup:green:god gift # Highlight (partly) selected items menu_colour += inventory:white:\w \+\s menu_colour += inventory:white:\w \#\s +menu_colour += inventory:white:\w \*\s # Not really menu. diff --git a/crawl-ref/source/invent.cc b/crawl-ref/source/invent.cc index cafdc0fc0b70..1c865f7d1e0f 100644 --- a/crawl-ref/source/invent.cc +++ b/crawl-ref/source/invent.cc @@ -18,6 +18,7 @@ #include "colour.h" #include "command.h" #include "describe.h" +#include "english.h" #include "env.h" #include "food.h" #include "god-item.h" @@ -68,7 +69,7 @@ string InvTitle::get_text(const bool) const } InvEntry::InvEntry(const item_def &i) - : MenuEntry("", MEL_ITEM), item(&i) + : MenuEntry("", MEL_ITEM), item(&i), _has_star(false) { data = const_cast(item); @@ -175,6 +176,11 @@ void InvEntry::select(int qty) MenuEntry::select(qty); } +bool InvEntry::has_star() const +{ + return _has_star; +} + string InvEntry::get_filter_text() const { return item_prefix(*item) + " " + get_text(); @@ -204,6 +210,8 @@ string InvEntry::get_text(bool need_cursor) const tstr << '-'; else if (selected_qty < quantity) tstr << '#'; + else if (_has_star) + tstr << '*'; else tstr << '+'; @@ -307,7 +315,7 @@ void InvEntry::set_show_glyph(bool doshow) InvMenu::InvMenu(int mflags) : Menu(mflags, "inventory"), type(menu_type::invlist), pre_select(nullptr), - title_annotate(nullptr) + title_annotate(nullptr), _mode_special_drop(false) { #ifdef USE_TILE_LOCAL if (Options.tile_menu_icons) @@ -317,6 +325,11 @@ InvMenu::InvMenu(int mflags) InvEntry::set_show_cursor(false); } +bool InvMenu::mode_special_drop() const +{ + return _mode_special_drop; +} + void InvMenu::set_type(menu_type t) { type = t; @@ -351,17 +364,58 @@ void InvMenu::set_title(const string &s) int InvMenu::pre_process(int key) { - if (key == '-' && minus_is_pageup()) - key = CK_PGUP; + if (type == menu_type::drop && key == '\\') + { + _mode_special_drop = !_mode_special_drop; + key = CK_NO_KEY; + } else if (key == ';' && you.last_unequip != -1 && (type == menu_type::drop || type == menu_type::invlist)) { key = index_to_letter(you.last_unequip); } + else if (key == '-') + _mode_special_drop = false; return key; } +static bool _item_is_permadrop_candidate(const item_def &item) +{ + // Known, non-artefact items of the types you see on the '\' menu proper. + // (No disabling autopickup for "green fizzy potion", "+3 whip", etc.) + if (item_type_unknown(item)) + return false; + return item.base_type == OBJ_MISCELLANY + || is_stackable_item(item) + || item_type_has_ids(item.base_type); +} + +void InvMenu::select_item_index(int idx, int qty, bool draw_cursor) +{ + if (type != menu_type::drop) + return Menu::select_item_index(idx, qty, draw_cursor); + + InvEntry *ie = static_cast(items[idx]); + + bool should_toggle_star = _item_is_permadrop_candidate(ie->item[0]) + && (ie->has_star() || _mode_special_drop); + + if (should_toggle_star) + { + // Toggle starred items back to selected-but-not-starred in this mode + // instead of turning them all the way off. + qty = _mode_special_drop ? -2 : 0; + ie->set_star(!ie->has_star()); + } + Menu::select_item_index(idx, qty, draw_cursor); +} + +void InvEntry::set_star(bool val) +{ + _has_star = val; +} + static bool _has_melded_armour() { for (int e = EQ_CLOAK; e <= EQ_BODY_ARMOUR; e++) @@ -891,7 +945,7 @@ vector InvMenu::get_selitems() const { InvEntry *inv = dynamic_cast(me); selected_items.emplace_back(inv->hotkeys[0], inv->selected_qty, - inv->item); + inv->item, inv->has_star()); } return selected_items; } @@ -1256,6 +1310,30 @@ static string _drop_selitem_text(const vector *s) s->size() > 1? "s" : ""); } +static string _drop_prompt(bool as_menu_title, bool menu_autopickup_mode) +{ + string prompt_base; + + if (as_menu_title && menu_autopickup_mode) + prompt_base = "Drop (and turn off autopickup for) what? "; + else if (as_menu_title) + prompt_base = "Drop what? "; + else + prompt_base = "Drop what? "; + return prompt_base + slot_description() +#ifdef TOUCH_UI + + " ( or tap header to drop)"; +#else + + " (_ for help)"; +#endif +} + +static string _drop_menu_titlefn(const Menu *m, const string &) +{ + const InvMenu *invmenu = static_cast(m); + return _drop_prompt(true, invmenu->mode_special_drop()); +} + /** * Prompt the player to select zero or more items to drop. * TODO: deduplicate/merge with prompt_invent_item(). @@ -1265,14 +1343,6 @@ static string _drop_selitem_text(const vector *s) */ vector prompt_drop_items(const vector &preselected_items) { - const string prompt = "Drop what? " + slot_description() -#ifdef TOUCH_UI - + " ( or tap header to drop)" -#else - + " (_ for help)" -#endif - ; - unsigned char keyin = '?'; int ret = PROMPT_ABORT; @@ -1292,6 +1362,7 @@ vector prompt_drop_items(const vector &preselected_items) if (need_prompt) { + const string prompt = _drop_prompt(false, false); mprf(MSGCH_PROMPT, "%s (? for menu, Esc to quit)", prompt.c_str()); } @@ -1303,17 +1374,18 @@ vector prompt_drop_items(const vector &preselected_items) need_prompt = true; need_getch = true; - // Note: We handle any "special" character first, so that - // it can be used to override the others. - if (keyin == '?' || keyin == '*' || keyin == ',') + if (keyin == '_') + show_specific_help("pick-up"); + else if (keyin == '?' || keyin == '*' || keyin == ',') { // The "view inventory listing" mode. - const int ch = _invent_select(prompt.c_str(), + const int ch = _invent_select("", menu_type::drop, OSEL_ANY, -1, MF_MULTISELECT | MF_ALLOW_FILTER, - nullptr, &items, + _drop_menu_titlefn, + &items, &Options.drop_filter, _drop_selitem_text, &preselected_items); @@ -1388,10 +1460,7 @@ vector prompt_drop_items(const vector &preselected_items) } if (ret != PROMPT_ABORT) - { - items.emplace_back(ret, count, - ret != PROMPT_GOT_SPECIAL ? &you.inv[ret] : nullptr); - } + items.emplace_back(ret, count, &you.inv[ret]); return items; } diff --git a/crawl-ref/source/invent.h b/crawl-ref/source/invent.h index 2f6bc57e3f0a..451abc3c9e26 100644 --- a/crawl-ref/source/invent.h +++ b/crawl-ref/source/invent.h @@ -70,7 +70,6 @@ DEF_BITFIELD(invent_prompt_flags, invprompt_flag); #define PROMPT_ABORT -1 #define PROMPT_GOT_SPECIAL -2 #define PROMPT_NOTHING -3 -#define PROMPT_INAPPROPRIATE -4 #define SLOT_BARE_HANDS PROMPT_GOT_SPECIAL @@ -81,10 +80,10 @@ struct SelItem int slot; int quantity; const item_def *item; - - SelItem() : slot(0), quantity(0), item(nullptr) { } - SelItem(int s, int q, const item_def *it = nullptr) - : slot(s), quantity(q), item(it) + bool has_star; + SelItem() : slot(0), quantity(0), item(nullptr), has_star(false) { } + SelItem(int s, int q, const item_def *it = nullptr, bool do_star = false) + : slot(s), quantity(q), item(it), has_star(do_star) { } }; @@ -141,6 +140,8 @@ class InvEntry : public MenuEntry } virtual void select(int qty = -1) override; + void set_star(bool); + bool has_star() const; virtual string get_filter_text() const override; @@ -149,6 +150,7 @@ class InvEntry : public MenuEntry private: void add_class_hotkeys(const item_def &i); + bool _has_star; }; class InvMenu : public Menu @@ -194,8 +196,12 @@ class InvMenu : public Menu const menu_sort_condition *find_menu_sort_condition() const; void sort_menu(vector &items, const menu_sort_condition *cond); + // Drop menu only: if true, dropped items are removed from autopickup. + bool mode_special_drop() const; + protected: void do_preselect(InvEntry *ie); + void select_item_index(int idx, int qty, bool draw_cursor = true) override; int pre_process(int key) override; virtual bool is_selectable(int index) const override; virtual string help_key() const override; @@ -206,6 +212,9 @@ class InvMenu : public Menu invtitle_annotator title_annotate; string temp_title; + +private: + bool _mode_special_drop; }; void get_class_hotkeys(const int type, vector &glyphs); diff --git a/crawl-ref/source/item-name.cc b/crawl-ref/source/item-name.cc index f20015df7b5d..82e89010de13 100644 --- a/crawl-ref/source/item-name.cc +++ b/crawl-ref/source/item-name.cc @@ -2387,9 +2387,12 @@ class KnownEntry : public InvEntry else selected_qty = 0; - // Set the force_autopickup values - const int forceval = (selected_qty == 2 ? -1 : selected_qty); - you.force_autopickup[item->base_type][item->sub_type] = forceval; + if (selected_qty == 2) + set_item_autopickup(*item, AP_FORCE_OFF); + else if (selected_qty == 1) + set_item_autopickup(*item, AP_FORCE_ON); + else + set_item_autopickup(*item, AP_FORCE_NONE); } }; @@ -2461,9 +2464,9 @@ static void _add_fake_item(object_class_type base, int sub, items.push_back(ptmp); - if (you.force_autopickup[base][sub] == 1) + if (you.force_autopickup[base][sub] == AP_FORCE_ON) selected.emplace_back(0, 1, ptmp); - else if (you.force_autopickup[base][sub] == -1) + else if (you.force_autopickup[base][sub] == AP_FORCE_OFF) selected.emplace_back(0, 2, ptmp); } diff --git a/crawl-ref/source/items.cc b/crawl-ref/source/items.cc index 84cce5e568da..696db7f9a291 100644 --- a/crawl-ref/source/items.cc +++ b/crawl-ref/source/items.cc @@ -36,6 +36,7 @@ #include "dgn-event.h" #include "directn.h" #include "dungeon.h" +#include "english.h" #include "env.h" #include "food.h" #include "god-passive.h" @@ -962,7 +963,7 @@ static bool _id_floor_item(item_def &item) bool should_pickup = item_needs_autopickup(item); set_ident_type(item, true); if (!should_pickup) - you.force_autopickup[item.base_type][item.sub_type] = -1; + set_item_autopickup(item, AP_FORCE_OFF); return true; } } @@ -2715,6 +2716,38 @@ static bool _drop_item_order(const SelItem &first, const SelItem &second) return first.slot < second.slot; } +void set_item_autopickup(const item_def &item, autopickup_level_type ap) +{ + you.force_autopickup[item.base_type][_autopickup_subtype(item)] = ap; +} + +int item_autopickup_level(const item_def &item) +{ + return you.force_autopickup[item.base_type][_autopickup_subtype(item)]; +} + +static void _disable_autopickup_for_starred_items(vector &items) +{ + int autopickup_remove_count = 0; + const item_def *last_touched_item; + for (SelItem &si : items) + { + if (si.has_star && item_autopickup_level(si.item[0]) != AP_FORCE_OFF) + { + last_touched_item = si.item; + ++autopickup_remove_count; + set_item_autopickup(*last_touched_item, AP_FORCE_OFF); + } + } + if (autopickup_remove_count == 1) + { + mprf("Autopickup disabled for %s.", + pluralise(last_touched_item->name(DESC_DBNAME)).c_str()); + } + else if (autopickup_remove_count > 1) + mprf("Autopickup disabled for %d items.", autopickup_remove_count); +} + /** * Prompts the user for an item to drop. */ @@ -2736,6 +2769,7 @@ void drop() return; } + _disable_autopickup_for_starred_items(tmp_items); _multidrop(tmp_items); } @@ -2910,9 +2944,9 @@ static bool _is_option_autopickup(const item_def &item, bool ignore_force) if (item.base_type < NUM_OBJECT_CLASSES) { - const int force = you.force_autopickup[item.base_type][_autopickup_subtype(item)]; - if (!ignore_force && force != 0) - return force == 1; + const int force = item_autopickup_level(item); + if (!ignore_force && force != AP_FORCE_NONE) + return force == AP_FORCE_ON; } else return false; diff --git a/crawl-ref/source/items.h b/crawl-ref/source/items.h index 0bf7c58d6ed6..90ee59183589 100644 --- a/crawl-ref/source/items.h +++ b/crawl-ref/source/items.h @@ -29,6 +29,13 @@ enum item_source_type AQ_WIZMODE = 200, }; +enum autopickup_level_type +{ + AP_FORCE_OFF = -1, + AP_FORCE_NONE = 0, + AP_FORCE_ON = 1, +}; + /// top-priority item override colour #define FORCED_ITEM_COLOUR_KEY "forced_item_colour" @@ -135,6 +142,9 @@ bool can_autopickup(); bool need_to_autopickup(); void autopickup(); +void set_item_autopickup(const item_def &item, autopickup_level_type ap); +int item_autopickup_level(const item_def &item); + int find_free_slot(const item_def &i); bool need_to_autoinscribe(); diff --git a/crawl-ref/source/menu.h b/crawl-ref/source/menu.h index eec5b038bca3..b82eddcc8ba0 100644 --- a/crawl-ref/source/menu.h +++ b/crawl-ref/source/menu.h @@ -440,7 +440,7 @@ class Menu void deselect_all(bool update_view = true); virtual void select_items(int key, int qty = -1); - void select_item_index(int idx, int qty, bool draw_cursor = true); + virtual void select_item_index(int idx, int qty, bool draw_cursor = true); void select_index(int index, int qty = -1); bool is_hotkey(int index, int key); diff --git a/crawl-ref/source/ng-setup.cc b/crawl-ref/source/ng-setup.cc index f7837955552e..953d519277e5 100644 --- a/crawl-ref/source/ng-setup.cc +++ b/crawl-ref/source/ng-setup.cc @@ -71,7 +71,7 @@ static void _give_bonus_items() static void _autopickup_ammo(missile_type missile) { if (Options.autopickup_starting_ammo) - you.force_autopickup[OBJ_MISSILES][missile] = 1; + you.force_autopickup[OBJ_MISSILES][missile] = AP_FORCE_ON; } /** diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index bd55537d3757..5a75ec7c10f7 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -3958,7 +3958,7 @@ static void tag_read_you_items(reader &th) // If fruit pickup was not set explicitly during the time between // FOOD_PURGE and FOOD_PURGE_AP_FIX, copy the old exemplar FOOD_PEAR. - if (food_pickups[FOOD_FRUIT] == 0) + if (food_pickups[FOOD_FRUIT] == AP_FORCE_NONE) food_pickups[FOOD_FRUIT] = food_pickups[FOOD_PEAR]; } if (you.species == SP_FORMICID) diff --git a/crawl-ref/source/wiz-item.cc b/crawl-ref/source/wiz-item.cc index 771da228cf68..71034363ab13 100644 --- a/crawl-ref/source/wiz-item.cc +++ b/crawl-ref/source/wiz-item.cc @@ -392,7 +392,7 @@ void wizard_tweak_object() char specs[50]; int keyin; - int item = prompt_invent_item("Tweak which item? ", menu_type::invlist, -1); + int item = prompt_invent_item("Tweak which item? ", menu_type::invlist, OSEL_ANY); if (prompt_failed(item)) return; @@ -522,7 +522,7 @@ static bool _make_book_randart(item_def &book) void wizard_value_item() { const int i = prompt_invent_item("Value of which item?", - menu_type::invlist, -1); + menu_type::invlist, OSEL_ANY); if (prompt_failed(i)) return; @@ -592,7 +592,7 @@ void wizard_create_all_artefacts() void wizard_make_object_randart() { int i = prompt_invent_item("Make an artefact out of which item?", - menu_type::invlist, -1); + menu_type::invlist, OSEL_ANY); if (prompt_failed(i)) return; @@ -683,7 +683,7 @@ static bool _item_type_can_be_cursed(int type) void wizard_uncurse_item() { const int i = prompt_invent_item("(Un)curse which item?", - menu_type::invlist, -1); + menu_type::invlist, OSEL_ANY); if (!prompt_failed(i)) { @@ -1302,7 +1302,7 @@ static void _debug_rap_stats(FILE *ostat) { const int inv_index = prompt_invent_item("Generate randart stats on which item?", - menu_type::invlist, -1); + menu_type::invlist, OSEL_ANY); if (prompt_failed(inv_index)) return; diff --git a/crawl-ref/source/wiz-mon.cc b/crawl-ref/source/wiz-mon.cc index 6d4f27eaab80..ea409cecd843 100644 --- a/crawl-ref/source/wiz-mon.cc +++ b/crawl-ref/source/wiz-mon.cc @@ -709,7 +709,7 @@ void wizard_give_monster_item(monster* mon) } int player_slot = prompt_invent_item("Give which item to monster?", - menu_type::drop, -1); + menu_type::drop, OSEL_ANY); if (prompt_failed(player_slot)) return; From 442a7a25c4c10442a52689fea45f1e2d20b22433 Mon Sep 17 00:00:00 2001 From: Joshua Gelbard Date: Mon, 1 Apr 2019 20:33:55 -0700 Subject: [PATCH 338/864] Add misc. evocables section to known items menu Steal the space on the '\' menu formerly taken up by known spellbooks and give it to misc. evocables (previously grouped under "Other"). Now that the spell library exists, a list of your already-recognized books is pretty useless. Individual switches for evocables like lamps of fire will make much better use of that space. "Unknown items mode" is untouched -- evocables still won't appear there, and unknown spellbooks will still get their own category. Issues: check_item_knowledge() has received patchwork additions over the years and is creaking with duplicated code. This commit doesn't help, but it doesn't make it that much worse -- there were already four seprately-treated vectors of item_def pointers; now there are five. (My first attempt at making this change started with a refactor, but the result wasn't enough of an improvement to justify the diff, so I've gone with the polar opposite and followed the existing pattern exactly.) [Closes #1025] --- crawl-ref/source/item-name.cc | 36 ++++++++++++++++++++++++++--------- crawl-ref/source/items.cc | 2 -- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/crawl-ref/source/item-name.cc b/crawl-ref/source/item-name.cc index 82e89010de13..68bd526eda31 100644 --- a/crawl-ref/source/item-name.cc +++ b/crawl-ref/source/item-name.cc @@ -2322,12 +2322,7 @@ class KnownEntry : public InvEntry } } else if (item->base_type == OBJ_MISCELLANY) - { - if (item->sub_type == MISC_PHANTOM_MIRROR) - name = pluralise(item->name(DESC_PLAIN)); - else - name = "miscellaneous"; - } + name = pluralise(item->name(DESC_DBNAME)); else if (item->is_type(OBJ_BOOKS, BOOK_MANUAL)) name = "manuals"; else if (item->base_type == OBJ_GOLD) @@ -2475,6 +2470,7 @@ void check_item_knowledge(bool unknown_items) vector items; vector items_missile; //List of missiles should go after normal items vector items_food; //List of foods should come next + vector items_misc; vector items_other; //List of other items should go after everything vector selected_items; @@ -2489,7 +2485,7 @@ void check_item_knowledge(bool unknown_items) if (i == OBJ_JEWELLERY && j >= NUM_RINGS && j < AMU_FIRST_AMULET) continue; - if (i == OBJ_BOOKS && j > MAX_FIXED_BOOK) + if (i == OBJ_BOOKS && (j > MAX_FIXED_BOOK || !unknown_items)) continue; if (item_type_removed(i, j)) @@ -2510,7 +2506,7 @@ void check_item_knowledge(bool unknown_items) for (int ii = 0; ii < NUM_OBJECT_CLASSES; ii++) { object_class_type i = (object_class_type)ii; - if (!item_type_has_ids(i)) + if (i == OBJ_BOOKS || !item_type_has_ids(i)) continue; _add_fake_item(i, get_max_subtype(i), selected_items, items); } @@ -2533,12 +2529,31 @@ void check_item_knowledge(bool unknown_items) _add_fake_item(OBJ_FOOD, i, selected_items, items_food); } + for (int i = 0; i < NUM_MISCELLANY; i++) + { + if (i == MISC_HORN_OF_GERYON +#if TAG_MAJOR_VERSION == 34 + || is_deck_type(i) + || i == MISC_BUGGY_EBONY_CASKET + || i == MISC_BUGGY_LANTERN_OF_SHADOWS + || i == MISC_BOTTLED_EFREET + || i == MISC_RUNE_OF_ZOT + || i == MISC_STONE_OF_TREMORS + || i == MISC_XOMS_CHESSBOARD +#endif + || (i == MISC_QUAD_DAMAGE && !crawl_state.game_is_sprint())) + { + continue; + } + _add_fake_item(OBJ_MISCELLANY, i, selected_items, items_misc); + } + // Misc. static const pair misc_list[] = { { OBJ_BOOKS, BOOK_MANUAL }, { OBJ_GOLD, 1 }, - { OBJ_MISCELLANY, NUM_MISCELLANY }, + { OBJ_BOOKS, NUM_BOOKS }, { OBJ_RUNES, NUM_RUNE_TYPES }, }; for (auto e : misc_list) @@ -2548,6 +2563,7 @@ void check_item_knowledge(bool unknown_items) sort(items.begin(), items.end(), _identified_item_names); sort(items_missile.begin(), items_missile.end(), _identified_item_names); sort(items_food.begin(), items_food.end(), _identified_item_names); + sort(items_misc.begin(), items_misc.end(), _identified_item_names); KnownMenu menu; string stitle; @@ -2575,6 +2591,7 @@ void check_item_knowledge(bool unknown_items) ml = menu.load_items(items_missile, known_item_mangle, ml, false); ml = menu.load_items(items_food, known_item_mangle, ml, false); + ml = menu.load_items(items_misc, known_item_mangle, ml, false); if (!items_other.empty()) { menu.add_entry(new MenuEntry("Other Items", MEL_SUBTITLE)); @@ -2589,6 +2606,7 @@ void check_item_knowledge(bool unknown_items) deleteAll(items); deleteAll(items_missile); deleteAll(items_food); + deleteAll(items_misc); deleteAll(items_other); if (!all_items_known && (last_char == '\\' || last_char == '-')) diff --git a/crawl-ref/source/items.cc b/crawl-ref/source/items.cc index 696db7f9a291..cddee1e769c8 100644 --- a/crawl-ref/source/items.cc +++ b/crawl-ref/source/items.cc @@ -2920,8 +2920,6 @@ static int _autopickup_subtype(const item_def &item) case OBJ_POTIONS: case OBJ_STAVES: return item_type_known(item) ? item.sub_type : max_type; - case OBJ_MISCELLANY: - return max_type; case OBJ_BOOKS: if (item.sub_type == BOOK_MANUAL || item_type_known(item)) return item.sub_type; From 6f6d0e6ea3cf94e174b293c197f19f6abc24e113 Mon Sep 17 00:00:00 2001 From: Doesnt Date: Sat, 18 May 2019 20:49:23 -0500 Subject: [PATCH 339/864] Fix Avatar Song displayed success rate --- crawl-ref/source/mon-cast.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/source/mon-cast.cc b/crawl-ref/source/mon-cast.cc index c115d7a90969..8378a1e1f5ff 100644 --- a/crawl-ref/source/mon-cast.cc +++ b/crawl-ref/source/mon-cast.cc @@ -1077,6 +1077,7 @@ static int _mons_power_hd_factor(spell_type spell, bool random) return 10 * ENCH_POW_FACTOR; case SPELL_SIREN_SONG: + case SPELL_AVATAR_SONG: return 9 * ENCH_POW_FACTOR; case SPELL_MASS_CONFUSION: From 52ca42d3ec3915b30a88d05e5108cbf29dd27da1 Mon Sep 17 00:00:00 2001 From: Alex Jurkiewicz Date: Fri, 17 May 2019 11:41:40 +1000 Subject: [PATCH 340/864] Improve shaft messaging Always print the number of floors, so the message is consistent between falling one or multiple levels. --- crawl-ref/source/stairs.cc | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/crawl-ref/source/stairs.cc b/crawl-ref/source/stairs.cc index 10086120a24a..77bbddcf1549 100644 --- a/crawl-ref/source/stairs.cc +++ b/crawl-ref/source/stairs.cc @@ -540,13 +540,10 @@ static level_id _travel_destination(const dungeon_feature_type how, + shaft_dest.describe() + "."); } - string howfar; - if (shaft_depth > 1) - howfar = make_stringf(" for %d floors", shaft_depth); - - mprf("You %s a shaft%s!", you.airborne() ? "are sucked into" - : "fall through", - howfar.c_str()); + mprf("You %s a shaft and drop %d floor%s!", + you.airborne() ? "are sucked" : "fall", + shaft_depth, + shaft_depth > 1 ? "s" : ""); // Shafts are one-time-use. mpr("The shaft crumbles and collapses."); From ad4687c37dae478188cf5f48e906380952a8a2c4 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Mon, 20 May 2019 09:54:54 -0400 Subject: [PATCH 341/864] Replace a missing word --- crawl-ref/source/stairs.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/stairs.cc b/crawl-ref/source/stairs.cc index 77bbddcf1549..b3b1eda560dd 100644 --- a/crawl-ref/source/stairs.cc +++ b/crawl-ref/source/stairs.cc @@ -540,7 +540,7 @@ static level_id _travel_destination(const dungeon_feature_type how, + shaft_dest.describe() + "."); } - mprf("You %s a shaft and drop %d floor%s!", + mprf("You %s into a shaft and drop %d floor%s!", you.airborne() ? "are sucked" : "fall", shaft_depth, shaft_depth > 1 ? "s" : ""); From 48f6bceb6755db32399b5e13d3463dc18356c0c7 Mon Sep 17 00:00:00 2001 From: NormalPerson7 <37064413+NormalPerson7@users.noreply.github.com> Date: Tue, 21 May 2019 20:52:34 +0100 Subject: [PATCH 342/864] Fix a default force_more_message This was broken by the shaft message change in 52ca42d. --- crawl-ref/source/dat/defaults/messages.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/dat/defaults/messages.txt b/crawl-ref/source/dat/defaults/messages.txt index 2869c8fc4020..4d5c90bb03dc 100644 --- a/crawl-ref/source/dat/defaults/messages.txt +++ b/crawl-ref/source/dat/defaults/messages.txt @@ -91,7 +91,7 @@ msc += mute:Uskayaw will no longer force your foes to share their pain\. force_more_message += You have reached level force_more_message += Your scales start -force_more_message += You (fall through|are sucked into) a shaft +force_more_message += You (fall|are sucked) into a shaft force_more_message += You fall into the water! force_more_message += You fall into the lava! force_more_message += You focus on prolonging your flight From 13fca185acb1bef98dbd086b932dd9e5687f1b1b Mon Sep 17 00:00:00 2001 From: NormalPerson7 <37064413+NormalPerson7@users.noreply.github.com> Date: Tue, 21 May 2019 20:55:06 +0100 Subject: [PATCH 343/864] Fix a default note_messages --- crawl-ref/source/dat/defaults/misc.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/dat/defaults/misc.txt b/crawl-ref/source/dat/defaults/misc.txt index 8240419662a6..2ef03d4ea93b 100644 --- a/crawl-ref/source/dat/defaults/misc.txt +++ b/crawl-ref/source/dat/defaults/misc.txt @@ -12,5 +12,5 @@ sort_menus += inv: true : equipped, charged note_items += acquirement, running, of Zot note_messages += Your scales start note_messages += protects you from harm -note_messages += You (fall through|are sucked into) a shaft +note_messages += You (fall|are sucked) into a shaft note_monsters += orb of fire, ancient lich, Sigmund From 445242741243734bae0c92c3255465d7e487903e Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Mon, 20 May 2019 18:06:23 +0100 Subject: [PATCH 344/864] Allow holy wrath weapons to be cursed It was an almost invisible piece of flavour, since no external sources of cursing still exist other than initial generation, and it resulted in them being unable to be cursed under Ashenzari without any feedback as to why. --- crawl-ref/source/art-func.h | 2 +- crawl-ref/source/artefact.cc | 9 +------ crawl-ref/source/item-prop.cc | 44 ++++------------------------------- crawl-ref/source/item-prop.h | 4 ++-- crawl-ref/source/makeitem.cc | 2 -- 5 files changed, 9 insertions(+), 52 deletions(-) diff --git a/crawl-ref/source/art-func.h b/crawl-ref/source/art-func.h index bec8ad648e4a..da7bf6d6fa40 100644 --- a/crawl-ref/source/art-func.h +++ b/crawl-ref/source/art-func.h @@ -165,7 +165,7 @@ static void _CURSES_world_reacts(item_def *item) { // don't spam messages for ash worshippers if (one_chance_in(30) && !have_passive(passive_t::want_curses)) - curse_an_item(true); + curse_an_item(); } static void _CURSES_melee_effects(item_def* weapon, actor* attacker, diff --git a/crawl-ref/source/artefact.cc b/crawl-ref/source/artefact.cc index 878535a9896f..98f9161c5d0a 100644 --- a/crawl-ref/source/artefact.cc +++ b/crawl-ref/source/artefact.cc @@ -162,12 +162,6 @@ static bool _god_fits_artefact(const god_type which_god, const item_def &item, } break; - case GOD_ASHENZARI: - // Cursed god: no holy wrath (since that brand repels curses). - if (brand == SPWPN_HOLY_WRATH) - return false; - break; - case GOD_DITHMENOS: // No reducing stealth. if (artefact_property(item, ARTP_STEALTH) < 0) @@ -1522,8 +1516,7 @@ static bool _randart_is_conflicting(const item_def &item, { if (item.base_type == OBJ_WEAPONS && get_weapon_brand(item) == SPWPN_HOLY_WRATH - && (is_demonic(item) - || proprt[ARTP_CURSE])) + && is_demonic(item)) { return true; } diff --git a/crawl-ref/source/item-prop.cc b/crawl-ref/source/item-prop.cc index ba16e19137b7..f4b425a80538 100644 --- a/crawl-ref/source/item-prop.cc +++ b/crawl-ref/source/item-prop.cc @@ -832,34 +832,22 @@ static bool _maybe_note_found_unrand(const item_def &item) } /** - * Is the provided item cursable? Note: this function would leak - * information about unidentified holy wrath weapons, which is alright - * because only Ashenzari worshippers can deliberately curse items and - * they see all weapon egos anyway. + * Is the provided item cursable? * * @param item The item under consideration. - * @return Whether the given item is a blessed weapon. + * @return Whether the given item is cursable. */ -bool item_is_cursable(const item_def &item, bool ignore_holy_wrath) +bool item_is_cursable(const item_def &item) { if (!item_type_has_curses(item.base_type)) return false; if (item_known_cursed(item)) return false; - if (!ignore_holy_wrath - && item.base_type == OBJ_WEAPONS - && (get_weapon_brand(item) == SPWPN_HOLY_WRATH - || you.duration[DUR_EXCRUCIATING_WOUNDS] - && item_is_equipped(item) - && you.props[ORIGINAL_BRAND_KEY].get_int() == SPWPN_HOLY_WRATH)) - { - return false; - } return true; } // Curses a random player inventory item. -bool curse_an_item(bool ignore_holy_wrath) +bool curse_an_item() { // allowing these would enable mummy scumming if (have_passive(passive_t::want_curses)) @@ -877,7 +865,7 @@ bool curse_an_item(bool ignore_holy_wrath) if (!item.defined()) continue; - if (!item_is_cursable(item, ignore_holy_wrath)) + if (!item_is_cursable(item)) continue; // Item is valid for cursing, so we'll give it a chance. @@ -914,28 +902,6 @@ void do_curse_item(item_def &item, bool quiet) return; } - // Holy wrath weapons cannot be cursed. - if (item.base_type == OBJ_WEAPONS - && (get_weapon_brand(item) == SPWPN_HOLY_WRATH - || you.duration[DUR_EXCRUCIATING_WOUNDS] - && item_is_equipped(item) - && you.props[ORIGINAL_BRAND_KEY].get_int() == SPWPN_HOLY_WRATH)) - { - if (!quiet) - { - mprf("Your %s glows black briefly, but repels the curse.", - item.name(DESC_PLAIN).c_str()); - if (is_artefact(item)) - artefact_learn_prop(item, ARTP_BRAND); - else - set_ident_flags(item, ISFLAG_KNOW_TYPE); - - if (!item_brand_known(item)) - mprf_nocap("%s", item.name(DESC_INVENTORY_EQUIP).c_str()); - } - return; - } - if (!quiet) { mprf("Your %s glows black for a moment.", diff --git a/crawl-ref/source/item-prop.h b/crawl-ref/source/item-prop.h index 8c8d5f82cfe7..4c36cc2d0584 100644 --- a/crawl-ref/source/item-prop.h +++ b/crawl-ref/source/item-prop.h @@ -51,8 +51,8 @@ bool item_type_removed(object_class_type base, int subtype); // cursed: bool item_known_cursed(const item_def &item) PURE; -bool item_is_cursable(const item_def &item, bool ignore_holy_wrath = false); -bool curse_an_item(bool ignore_holy_wrath = false); +bool item_is_cursable(const item_def &item); +bool curse_an_item(); void do_curse_item(item_def &item, bool quiet = true); void do_uncurse_item(item_def &item, bool check_bondage = true); inline constexpr bool item_type_has_curses(object_class_type base_type) diff --git a/crawl-ref/source/makeitem.cc b/crawl-ref/source/makeitem.cc index 934868068944..62d92df45c33 100644 --- a/crawl-ref/source/makeitem.cc +++ b/crawl-ref/source/makeitem.cc @@ -247,8 +247,6 @@ static bool _try_make_weapon_artefact(item_def& item, int force_type, if (cursed) do_curse_item(item); - if (get_weapon_brand(item) == SPWPN_HOLY_WRATH) - item.flags &= (~ISFLAG_CURSED); return true; } From e062c78e247ae72d878eb09a27fda9254ee6e465 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Tue, 21 May 2019 16:31:06 -0400 Subject: [PATCH 345/864] Remove mentions to obsolete items from options_guide.txt --- crawl-ref/docs/options_guide.txt | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/crawl-ref/docs/options_guide.txt b/crawl-ref/docs/options_guide.txt index 7832b493d532..409da1c5076a 100644 --- a/crawl-ref/docs/options_guide.txt +++ b/crawl-ref/docs/options_guide.txt @@ -491,10 +491,8 @@ autopickup = $?!+"/% ! Potions + or : Books | Staves - \ Rods 0 Orbs } Misc. items - X Corpses $ Gold Note that _whether_ items are picked up automatically or not, is controlled by the in-game toggle Ctrl-A. Also note that picking @@ -517,7 +515,7 @@ autopickup_exceptions ^= don't-pickup-regex, ... Whitespace between <> and the match expression is significant, so the following won't work: - autopickup_exceptions += < ebony casket + autopickup_exceptions += < box of beasts autopickup_exceptions replace the older ban_pickup. Using autopickup_exceptions += >uselessness, >inaccuracy @@ -529,8 +527,7 @@ autopickup_exceptions ^= don't-pickup-regex, ... autopickup_exceptions += uselessness, inaccuracy You can use multiple autopickup_exceptions lines. Some examples: - autopickup_exceptions += inaccuracy, scrolls? of paper - autopickup_exceptions += immolation, curse (armour|weapon) + autopickup_exceptions += inaccuracy, immolation autopickup_exceptions += uselessness, noise, torment Unless you clear the list of exceptions, you won't need to set From 1a3e1d35ff9336fb3c87f0d3cd69625928173f48 Mon Sep 17 00:00:00 2001 From: Alex Jurkiewicz Date: Tue, 21 May 2019 15:38:02 +1000 Subject: [PATCH 346/864] Remove vestigial duplicate wrath timer --- crawl-ref/source/religion.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index bc5fe2807b58..8db50d6b153f 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -2985,7 +2985,6 @@ void excommunication(bool voluntary, god_type new_god) case GOD_WU_JIAN: you.attribute[ATTR_SERPENTS_LASH] = 0; you.attribute[ATTR_HEAVENLY_STORM] = 0; - _set_penance(old_god, 25); break; default: From 4006481e62a9d0f6b870a77c7557397bab6c6c2a Mon Sep 17 00:00:00 2001 From: Alan Malloy Date: Fri, 10 May 2019 17:25:31 -0700 Subject: [PATCH 347/864] Simplify item weights --- crawl-ref/source/dat/des/altar/lugonu_bribe.des | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crawl-ref/source/dat/des/altar/lugonu_bribe.des b/crawl-ref/source/dat/des/altar/lugonu_bribe.des index 1bd3bd3a2171..17f55bd9b413 100644 --- a/crawl-ref/source/dat/des/altar/lugonu_bribe.des +++ b/crawl-ref/source/dat/des/altar/lugonu_bribe.des @@ -32,8 +32,7 @@ function callback.tgw_lugonu_bribe_lugonu_item (data, triggerable, good_item quick blade", Dithmenos="ring of attention ident:type /\ scroll of noise ident:type q:2-4", - Elyvilon="book of Necromancy w:5 /\ - book of Death w:5 / book of Unlife w:5", + Elyvilon="book of Necromancy / book of Death / book of Unlife", Fedhas="randbook owner:Lugonu spells:necromutation numspells:1 /\ randbook owner:Lugonu spells:simulacrum&animate_dead \ numspells:2", From b8b2abe48885d272da806c952908f60a2a6cfdb2 Mon Sep 17 00:00:00 2001 From: Alan Malloy Date: Wed, 22 May 2019 17:09:42 -0700 Subject: [PATCH 348/864] Make it harder to accidentally waste ?amnesia (Jarrodb, #11985) --- crawl-ref/source/ability.cc | 3 +++ crawl-ref/source/item-use.cc | 18 +++++++++++++++--- crawl-ref/source/spl-selfench.cc | 1 - 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/ability.cc b/crawl-ref/source/ability.cc index a2d1c3d1826d..17a25285d1c2 100644 --- a/crawl-ref/source/ability.cc +++ b/crawl-ref/source/ability.cc @@ -2571,7 +2571,10 @@ static spret _do_ability(const ability_def& abil, bool fail) case ABIL_SIF_MUNA_FORGET_SPELL: fail_check(); if (cast_selective_amnesia() <= 0) + { + canned_msg(MSG_OK); return spret::abort; + } break; case ABIL_SIF_MUNA_CHANNEL_ENERGY: diff --git a/crawl-ref/source/item-use.cc b/crawl-ref/source/item-use.cc index f4148325ea8d..abfa4ee4f323 100644 --- a/crawl-ref/source/item-use.cc +++ b/crawl-ref/source/item-use.cc @@ -3184,10 +3184,22 @@ void read_scroll(item_def& scroll) } if (you.spell_no == 0) mpr("You feel forgetful for a moment."); - else if (!alreadyknown) - cast_selective_amnesia(); else - cancel_scroll = (cast_selective_amnesia(pre_succ_msg) == -1); + { + bool done; + bool aborted; + do + { + aborted = cast_selective_amnesia() == -1; + done = !aborted + || alreadyknown + || crawl_state.seen_hups + || yesno("Really abort (and waste the scroll)?", false, 0); + cancel_scroll = aborted && !alreadyknown; + } while (!done); + if (aborted) + canned_msg(MSG_OK); + } break; default: diff --git a/crawl-ref/source/spl-selfench.cc b/crawl-ref/source/spl-selfench.cc index 032e272f9c2e..9d5bbdf80af7 100644 --- a/crawl-ref/source/spl-selfench.cc +++ b/crawl-ref/source/spl-selfench.cc @@ -175,7 +175,6 @@ int cast_selective_amnesia(const string &pre_msg) } } - canned_msg(MSG_OK); return -1; } From 5b3daab8ba66175a399ad8925371f808803b41a4 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Wed, 22 May 2019 21:36:28 -0400 Subject: [PATCH 349/864] Don't place traps under vault placed items and monsters (11983) Randomly placed monsters and items do not place on traps, however the dungeon builder was placing random traps under vault placed items and monsters occasionally. This led to runes on dispersal traps as the worst outcome, but the asymmetry was occasionally noticed for other trap types too. Vaults that wish to have monsters or items start on a trapped grid will need to request this explicitly. --- crawl-ref/source/dungeon.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index d1ae914fc009..d479e4092948 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -3219,9 +3219,12 @@ static void _place_traps() { ts.pos.x = random2(GXM); ts.pos.y = random2(GYM); + // Don't place random traps under vault monsters; if a vault + // wants this they have to request it specifically. if (in_bounds(ts.pos) && grd(ts.pos) == DNGN_FLOOR - && !map_masked(ts.pos, MMT_NO_TRAP)) + && !map_masked(ts.pos, MMT_NO_TRAP) + && mgrd(ts.pos) == NON_MONSTER) { break; } @@ -4566,6 +4569,7 @@ int dgn_place_item(const item_spec &spec, mitm[item_made].name(DESC_PLAIN).c_str(), mitm[item_made].name(DESC_PLAIN, false, true).c_str(), where.x, where.y); + env.level_map_mask(where) |= MMT_NO_TRAP; return item_made; } else @@ -5079,6 +5083,7 @@ static void _vault_grid_glyph(vault_placement &place, const coord_def& where, if (item_made != NON_ITEM) { mitm[item_made].pos = where; + env.level_map_mask(where) |= MMT_NO_TRAP; dprf(DIAG_DNGN, "vault grid: placing %s (%s) at %d,%d", mitm[item_made].name(DESC_PLAIN).c_str(), mitm[item_made].name(DESC_PLAIN, false, true).c_str(), From 4011b8c8abdb1a1959955f12db627a9ada740bdb Mon Sep 17 00:00:00 2001 From: cut1less Date: Wed, 22 May 2019 22:45:05 -0500 Subject: [PATCH 350/864] Simplify missile description cases Previously, descriptions for projectiles were based largely around whether they had a damage value associated with them, under the logic that "inherent missile damage => throwable missile". This made life easy in dealing with the old needles and with regular launcher missiles. However, it led to: * the sling bullet description having lots of throwing information (despite sling bullets not being throwable) and * the throwing net description lacking the fact that a net's delay is lowered with Throwing skill With the changes to throwing missiles, we can now just focus on throwable-ness to fix these issues and more. --- crawl-ref/source/describe.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index 20bab2a5b9c5..f3431c37525c 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -937,7 +937,7 @@ static int _item_training_target(const item_def &item) return weapon_min_delay_skill(item) * 10; else if (is_shield(item)) return round(you.get_shield_skill_to_offset_penalty(item) * 10); - else if (item.base_type == OBJ_MISSILES && throw_dam) + else if (item.base_type == OBJ_MISSILES && is_throwable(&you, item, false)) return (((10 + throw_dam / 2) - FASTEST_PLAYER_THROWING_SPEED) * 2) * 10; else return 0; @@ -950,14 +950,13 @@ static int _item_training_target(const item_def &item) */ static skill_type _item_training_skill(const item_def &item) { - const int throw_dam = property(item, PWPN_DAMAGE); if (item.base_type == OBJ_WEAPONS || item.base_type == OBJ_STAVES) return item_attack_skill(item); else if (is_shield(item)) return SK_SHIELDS; // shields are armour, so do shields before armour else if (item.base_type == OBJ_ARMOUR) return SK_ARMOUR; - else if (item.base_type == OBJ_MISSILES && throw_dam) + else if (item.base_type == OBJ_MISSILES && is_throwable(&you, item, false)) return SK_THROWING; else if (item_is_evokable(item)) // not very accurate return SK_EVOCATIONS; @@ -1513,7 +1512,7 @@ static string _describe_ammo(const item_def &item) } const int dam = property(item, PWPN_DAMAGE); - if (dam || item.sub_type == MI_DART) + if (can_throw) { const int throw_delay = (10 + dam / 2); const int target_skill = _item_training_target(item); From 1cdb867ce8f287dd7a617443bef11525b4b442a6 Mon Sep 17 00:00:00 2001 From: cut1less Date: Thu, 23 May 2019 00:00:36 -0500 Subject: [PATCH 351/864] Don't fully describe unthrowable missiles --- crawl-ref/source/describe.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index f3431c37525c..2a4a23618b9e 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -1512,7 +1512,8 @@ static string _describe_ammo(const item_def &item) } const int dam = property(item, PWPN_DAMAGE); - if (can_throw) + const bool player_throwable = is_throwable(&you, item, false); + if (player_throwable) { const int throw_delay = (10 + dam / 2); const int target_skill = _item_training_target(item); From ff863c23c4f263c84d81c8afef9a870c5f0831c6 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 23 May 2019 10:30:59 -0400 Subject: [PATCH 352/864] Don't crash on gozag + gold in grunt_nemelex_the_gamble Unobtainable items don't appear in the stash tracker, and calls that try to add them to it silently fail. The only remaining "unobtainable" items are in grunt_nemelex_the_gamble; these are marked unobtainable so that if the player rolls the peril room they don't show up in the stash tracker. However, Gozag's gold detection code didn't take this flag into account, triggering an ASSERT on the expectation that any gold generated at all would be trackable. This isn't the most elegant solution, but it fixes the crash. I think what would be better is for (i) "unobtainable" to be removed, since it appears to have been deprecated for everything except this vault some time ago, and (ii) for this vault to do something like destroy the items if the player lands in the peril room. --- crawl-ref/source/files.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 015c88eb5227..ac98e701f649 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -51,6 +51,7 @@ #include "hints.h" #include "initfile.h" #include "item-name.h" +#include "item-status-flag-type.h" #include "items.h" #include "jobs.h" #include "kills.h" @@ -1314,7 +1315,7 @@ static void _count_gold() { for (stack_iterator j(*ri); j; ++j) { - if (j->base_type == OBJ_GOLD) + if (j->base_type == OBJ_GOLD && !(j->flags & ISFLAG_UNOBTAINABLE)) { gold += j->quantity; gold_piles.push_back(&(*j)); From 4488db6de095286baa3c5a4d935bc398f42a52aa Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 23 May 2019 16:27:19 -0400 Subject: [PATCH 353/864] Clean up and improve gozag gold detection This consolidates a bunch of gozag code and removes an ASSERT that I think was over-eager, firing when update_item_at doesn't lead to a gold pile in the stash tracker. There had previously been two versions of this code, and only one had the check, but it doesn't seem so obvious to me that update_item_at should really be expected to make any arbitrary gold pile visible in the stash. This commit also makes gold detection work in the abyss beyond the initial levelgen. --- crawl-ref/source/abyss.cc | 3 ++ crawl-ref/source/dactions.cc | 28 ++----------------- crawl-ref/source/files.cc | 49 +-------------------------------- crawl-ref/source/god-passive.cc | 45 ++++++++++++++++++++++++++++++ crawl-ref/source/god-passive.h | 1 + crawl-ref/source/religion.cc | 6 +--- 6 files changed, 53 insertions(+), 79 deletions(-) diff --git a/crawl-ref/source/abyss.cc b/crawl-ref/source/abyss.cc index c5641145d5e9..e47225837699 100644 --- a/crawl-ref/source/abyss.cc +++ b/crawl-ref/source/abyss.cc @@ -1489,6 +1489,9 @@ static void abyss_area_shift() place_transiting_monsters(); check_map_validity(); + // TODO: should dactions be rerun at this point instead? That would cover + // this particular case... + gozag_detect_level_gold(false); } void destroy_abyss() diff --git a/crawl-ref/source/dactions.cc b/crawl-ref/source/dactions.cc index ce6b3879a768..1278798dc73c 100644 --- a/crawl-ref/source/dactions.cc +++ b/crawl-ref/source/dactions.cc @@ -13,6 +13,7 @@ #include "decks.h" #include "dungeon.h" #include "god-companions.h" // hepliaklqana_ancestor +#include "god-passive.h" #include "items.h" #include "libutil.h" #include "mapmark.h" @@ -316,33 +317,8 @@ static void _apply_daction(daction_type act) item.freshness = 1; // thoroughly rotten break; case DACT_GOLD_ON_TOP: - { - for (rectangle_iterator ri(0); ri; ++ri) - { - for (stack_iterator j(*ri); j; ++j) - { - if (j->base_type == OBJ_GOLD) - { - bool detected = false; - int dummy = j->index(); - unlink_item(dummy); - move_item_to_grid(&dummy, *ri, true); - if (!env.map_knowledge(*ri).item() - || env.map_knowledge(*ri).item()->base_type != OBJ_GOLD) - { - detected = true; - } - update_item_at(*ri, true); - - // The gold might be beneath deep water. - if (detected && env.map_knowledge(*ri).item()) - env.map_knowledge(*ri).flags |= MAP_DETECTED_ITEM; - break; - } - } - } + gozag_detect_level_gold(false); break; - } case DACT_REMOVE_GOZAG_SHOPS: { vector markers = env.markers.get_all(MAT_FEATURE); diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index ac98e701f649..cfdd358cab64 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1305,53 +1305,6 @@ static string _get_hatch_name() return ""; } - -static void _count_gold() -{ - vector gold_piles; - vector gold_places; - int gold = 0; - for (rectangle_iterator ri(0); ri; ++ri) - { - for (stack_iterator j(*ri); j; ++j) - { - if (j->base_type == OBJ_GOLD && !(j->flags & ISFLAG_UNOBTAINABLE)) - { - gold += j->quantity; - gold_piles.push_back(&(*j)); - gold_places.push_back(*ri); - } - } - } - - if (!player_in_branch(BRANCH_ABYSS)) - you.attribute[ATTR_GOLD_GENERATED] += gold; - - // TODO: this probably should fire when you join gozag, too? - if (have_passive(passive_t::detect_gold)) - { - for (unsigned int i = 0; i < gold_places.size(); i++) - { - bool detected = false; - int dummy = gold_piles[i]->index(); - coord_def &pos = gold_places[i]; - unlink_item(dummy); - move_item_to_grid(&dummy, pos, true); - if (!env.map_knowledge(pos).item() - || env.map_knowledge(pos).item()->base_type != OBJ_GOLD) - { - detected = true; - } - update_item_at(pos, true); - if (detected) - { - ASSERT(env.map_knowledge(pos).item()); - env.map_knowledge(pos).flags |= MAP_DETECTED_ITEM; - } - } - } -} - static const string VISITED_LEVELS_KEY = "visited_levels"; #if TAG_MAJOR_VERSION == 34 @@ -1748,7 +1701,7 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, if (just_created_level) { you.attribute[ATTR_ABYSS_ENTOURAGE] = 0; - _count_gold(); + gozag_detect_level_gold(true); } diff --git a/crawl-ref/source/god-passive.cc b/crawl-ref/source/god-passive.cc index 8a5fc780cfc0..da2eb5c544be 100644 --- a/crawl-ref/source/god-passive.cc +++ b/crawl-ref/source/god-passive.cc @@ -1065,6 +1065,51 @@ int gozag_gold_in_los(actor *whom) return gold_count; } +void gozag_detect_level_gold(bool count) +{ + vector gold_piles; + vector gold_places; + int gold = 0; + for (rectangle_iterator ri(0); ri; ++ri) + { + for (stack_iterator j(*ri); j; ++j) + { + if (j->base_type == OBJ_GOLD && !(j->flags & ISFLAG_UNOBTAINABLE)) + { + gold += j->quantity; + gold_piles.push_back(&(*j)); + gold_places.push_back(*ri); + } + } + } + + if (!player_in_branch(BRANCH_ABYSS) && count) + you.attribute[ATTR_GOLD_GENERATED] += gold; + + if (have_passive(passive_t::detect_gold)) + { + for (unsigned int i = 0; i < gold_places.size(); i++) + { + bool detected = false; + int dummy = gold_piles[i]->index(); + coord_def &pos = gold_places[i]; + unlink_item(dummy); + move_item_to_grid(&dummy, pos, true); + if (!env.map_knowledge(pos).item() + || env.map_knowledge(pos).item()->base_type != OBJ_GOLD) + { + detected = true; + } + update_item_at(pos, true); + // the pile can still remain undetected if it is not in + // you.visible_igrd, for example if it is under deep water and the + // player will not be able to see it. + if (detected && env.map_knowledge(pos).item()) + env.map_knowledge(pos).flags |= MAP_DETECTED_ITEM; + } + } +} + int qazlal_sh_boost(int piety) { if (!have_passive(passive_t::storm_shield)) diff --git a/crawl-ref/source/god-passive.h b/crawl-ref/source/god-passive.h index b11100f1ad7a..b731eadb82dc 100644 --- a/crawl-ref/source/god-passive.h +++ b/crawl-ref/source/god-passive.h @@ -281,6 +281,7 @@ int ash_skill_boost(skill_type sk, int scale); bool ash_has_skill_boost(skill_type sk); map ash_get_boosted_skills(eq_type type); int gozag_gold_in_los(actor* whom); +void gozag_detect_level_gold(bool count); int qazlal_sh_boost(int piety = you.piety); int tso_sh_boost(); void qazlal_storm_clouds(); diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index 8db50d6b153f..b898d5152f9d 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -3466,7 +3466,7 @@ static void _join_gozag() #endif } - // Move gold to top of piles. + // Move gold to top of piles & detect it. add_daction(DACT_GOLD_ON_TOP); } @@ -3668,10 +3668,6 @@ void join_religion(god_type which_god) mprf(MSGCH_MONSTER_ENCHANT, "Your unholy and evil allies forsake you."); } - // Move gold to top of piles with Gozag. - if (have_passive(passive_t::detect_gold)) - add_daction(DACT_GOLD_ON_TOP); - const function *join_effect = map_find(on_join, you.religion); if (join_effect != nullptr) (*join_effect)(); From be4061de67c6c816c0a15ed96d44c7efc14637b9 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 23 May 2019 17:17:56 -0400 Subject: [PATCH 354/864] Fix another abyss gozag gold detection case --- crawl-ref/source/abyss.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/source/abyss.cc b/crawl-ref/source/abyss.cc index e47225837699..ee16c2db4715 100644 --- a/crawl-ref/source/abyss.cc +++ b/crawl-ref/source/abyss.cc @@ -1714,6 +1714,7 @@ void abyss_teleport() stop_delay(true); forget_map(false); clear_excludes(); + gozag_detect_level_gold(false); more(); } From 0de8e755f4222b22ce0462efe57fb069624b5340 Mon Sep 17 00:00:00 2001 From: advil Date: Fri, 24 May 2019 11:22:44 -0400 Subject: [PATCH 355/864] Test a theory about hep abyss crashes This is a conceivable way for hep ancestor items to get copied to the grid, if somehow the ancestor becomes invalid before this call but cleanup of the ancestor hasn't happened yet (since held_by_monster will return false if the monster that was holding the item isn't valid). If it trips, this ASSERT will give a more direct line on what the setup conditions for this situation might be, which I still don't understand. --- crawl-ref/source/abyss.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crawl-ref/source/abyss.cc b/crawl-ref/source/abyss.cc index ee16c2db4715..42611229504b 100644 --- a/crawl-ref/source/abyss.cc +++ b/crawl-ref/source/abyss.cc @@ -28,6 +28,7 @@ #include "god-passive.h" // passive_t::slow_abyss #include "hiscores.h" #include "item-prop.h" +#include "item-status-flag-type.h" #include "items.h" #include "libutil.h" #include "mapmark.h" @@ -667,6 +668,7 @@ static void _push_items() if (!_pushy_feature(grd(*di))) { int j = i; + ASSERT(!testbits(item.flags, ISFLAG_SUMMONED)); move_item_to_grid(&j, *di, true); break; } @@ -1670,6 +1672,7 @@ void abyss_morph() _abyss_apply_terrain(abyss_genlevel_mask, true); _place_displaced_monsters(); _push_items(); + // TODO: does gozag gold detection need to be here too? los_changed(); } From 793c10c1f609275fc0c96a0590616e744d36e7e3 Mon Sep 17 00:00:00 2001 From: advil Date: Fri, 24 May 2019 11:30:38 -0400 Subject: [PATCH 356/864] Better messaging when hep ancestor gets lost in abyss (11973) Addresses something mentioned in 11973: On abyss teleport (and some other cases that I don't fully understand; this happens sometimes but not often on abyss area shifts as well) the ancestor gets banished for a short period of time, but there was no messaging for this. In other cases the ancestor gets put into transit and there's also no messaging for this case; the only difference was that for the former recall isn't available. This commit ensures messaging if the banish case happens, and no messaging otherwise. This does the messaging at a relatively low-level point, so it could be that there will be cases of double messaging (but I have not found them in my testing). N.b. I'm not actually sure it makes gameplay sense to banish the ancestor on abyss teleport or even sure if this is intentional, so it might be worth trying to put the ancestor in transit for that case too. But it does fit with the randomness flavor of the abyss, I guess. But even with that change this lower-level code might still be triggered in complicated circumstances, and the ancestor really shouldn't ever be banished without messaging. --- crawl-ref/source/abyss.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/abyss.cc b/crawl-ref/source/abyss.cc index 42611229504b..8fe32805690f 100644 --- a/crawl-ref/source/abyss.cc +++ b/crawl-ref/source/abyss.cc @@ -590,6 +590,8 @@ static void _abyss_lose_monster(monster& mons) // make sure we don't end up with an invalid hep ancestor else if (hepliaklqana_ancestor() == mons.mid) { + simple_monster_message(mons, " is pulled into the Abyss.", + MSGCH_BANISHMENT); remove_companion(&mons); you.duration[DUR_ANCESTOR_DELAY] = random_range(50, 150); //~5-15 turns } @@ -628,7 +630,8 @@ static void _place_displaced_monsters() if (mon->alive() && !mon->find_home_near_place(mon->pos())) { maybe_bloodify_square(mon->pos()); - if (you.can_see(*mon)) + // hep messaging is done in _abyss_lose_monster + if (you.can_see(*mon) && hepliaklqana_ancestor() != mon->mid) { simple_monster_message(*mon, " is pulled into the Abyss.", MSGCH_BANISHMENT); From 53aee78b01eba145eea34d0b7d97039b7f8bae50 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Fri, 24 May 2019 14:13:09 -0400 Subject: [PATCH 357/864] Remove vestigal references to needles (11986) --- crawl-ref/source/dat/des/sprint/menkaure.des | 8 ++++---- crawl-ref/source/dat/des/sprint/sprint_mu.des | 8 ++++---- crawl-ref/source/throw.cc | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/crawl-ref/source/dat/des/sprint/menkaure.des b/crawl-ref/source/dat/des/sprint/menkaure.des index 2bb310041393..903a1e4ce9db 100644 --- a/crawl-ref/source/dat/des/sprint/menkaure.des +++ b/crawl-ref/source/dat/des/sprint/menkaure.des @@ -27,7 +27,7 @@ TAGS: sprint no_item_gen no_trap_gen no_pool_fixup no_rotate no_hmirror no_vmi ORIENT: encompass SHUFFLE: 12 SUBST: ' = '...... -KFEAT: ' = net trap / needle trap / bolt trap / spear trap / arrow trap +KFEAT: ' = net trap / dart trap / bolt trap / spear trap / arrow trap MONS: Menkaure, crocodile, kraken, flying skull MARKER: a = lua:fog_machine { \ pow_min = 1, pow_max = 2, delay = 3, \ @@ -722,7 +722,7 @@ TAGS: sprint2_transparent_cluster no_item_gen no_trap_gen no_monster_gen no_po MARKER: + = lua:restrict_door() MONS: oklob plant, orc warlord / Nikola / draconian knight, toenail golem, the Lernaean hydra SUBST: ' = '. -KFEAT: ' = net trap / needle trap / bolt trap / spear trap / arrow trap +KFEAT: ' = net trap / dart trap / bolt trap / spear trap / arrow trap KFEAT: , = book shop KFEAT: f = any shop NSUBST: | = 1:a / 2:b / 1:d / 6:$ / *:| @@ -765,7 +765,7 @@ KITEM: b = scroll of acquirement q:1 / potion of magic q:9 / potion of haste q: KITEM: h = potion of flight q:3 MONS: Nessos, jelly, sixfirhy, Gastronok, orc sorcerer, dire elephant SUBST: . = '..... -KFEAT: ' = net trap / needle trap / bolt trap / spear trap / arrow trap +KFEAT: ' = net trap / dart trap / bolt trap / spear trap / arrow trap KFEAT: q = book shop KFEAT: i = any shop MAP @@ -843,7 +843,7 @@ SUBST: e = . KITEM: Z = Orb of Zot NSUBST: a = 3:1 / 3:2 / 27:$ / *:' SUBST: ' = '........ -KFEAT: ' = net trap / needle trap / bolt trap / spear trap / arrow trap +KFEAT: ' = net trap / dart trap / bolt trap / spear trap / arrow trap KITEM: $ = gold q:27 MONS: quicksilver dragon, Lorocyproca, ballistomycete spore COLOUR: X = magenta diff --git a/crawl-ref/source/dat/des/sprint/sprint_mu.des b/crawl-ref/source/dat/des/sprint/sprint_mu.des index 1b8e066abd79..fcbef82cca23 100644 --- a/crawl-ref/source/dat/des/sprint/sprint_mu.des +++ b/crawl-ref/source/dat/des/sprint/sprint_mu.des @@ -1047,7 +1047,7 @@ KMONS: 7 = patrolling simulacrum SUBST: 1 = 1122334455667 KITEM: 1234567 = star_item / nothing KFEAT: ^ = zot trap -KFEAT: - = spear trap / needle trap / net trap / blade trap / bolt trap +KFEAT: - = spear trap / dart trap / net trap / blade trap / bolt trap NSUBST: ~ = 1:^ / 10:- / *:. SUBST: ! = + @@ -1069,7 +1069,7 @@ MONS: patrolling iron golem, patrolling necromancer MONS: patrolling hell knight, patrolling skeletal warrior KMONS: 5 = lich KITEM: 5 = star_item, star_item, star_item, star_item, star_item, star_item -KFEAT: - = spear trap / needle trap / net trap / blade trap / bolt trap +KFEAT: - = spear trap / dart trap / net trap / blade trap / bolt trap NSUBST: . = 6:- / *:. MAP @@ -1087,7 +1087,7 @@ ENDMAP NAME: sprint_mu_crypt_lich TAGS: sprint_mu_crypt no_rotate no_hmirror no_vmirror MONS: ancient lich, skeletal warrior -KFEAT: - = spear trap / needle trap / net trap / blade trap / bolt trap +KFEAT: - = spear trap / dart trap / net trap / blade trap / bolt trap NSUBST: . = 10:- / *:. SUBST: : = . @@ -1109,7 +1109,7 @@ NAME: sprint_mu_tomb_spiral TAGS: sprint_mu_tomb no_rotate no_hmirror no_vmirror MONS: patrolling greater mummy, patrolling mummy priest MONS: patrolling guardian mummy, patrolling sphinx -KFEAT: - = needle trap / net trap / blade trap / bolt trap / spear trap / zot trap +KFEAT: - = dart trap / net trap / blade trap / bolt trap / spear trap / zot trap SUBST: . = -----.................332 KITEM: $ = golden rune of zot KITEM: ? = scroll of acquirement ident:all q:5 diff --git a/crawl-ref/source/throw.cc b/crawl-ref/source/throw.cc index 44f4b8ae949c..1575aa00e5b4 100644 --- a/crawl-ref/source/throw.cc +++ b/crawl-ref/source/throw.cc @@ -299,7 +299,7 @@ vector fire_target_behaviour::get_monster_desc(const monster_info& mi) string verb = brand == SPMSL_FRENZY ? "frenzy" : "blind"; - string chance_string = immune ? "immune to needles" : + string chance_string = immune ? "immune to darts" : make_stringf("chance to %s on hit: %d%%", verb.c_str(), chance); descs.emplace_back(chance_string); From bc69b92bc9bb84d15868b5fe127de5f9d6bb3d95 Mon Sep 17 00:00:00 2001 From: NormalPerson7 <37064413+NormalPerson7@users.noreply.github.com> Date: Sat, 25 May 2019 20:23:40 +0100 Subject: [PATCH 358/864] Don't allow players to stop monster monstrous menagerie with OTR (11990) (#1073) The code for monsters casting monstrous menagerie uses the same code path as for players, which means an extra check that the caster is the player is required before asking the player whether they want to cancel the spell. --- crawl-ref/source/spl-summoning.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/spl-summoning.cc b/crawl-ref/source/spl-summoning.cc index 0d2859d2e10c..5518d9096cdc 100644 --- a/crawl-ref/source/spl-summoning.cc +++ b/crawl-ref/source/spl-summoning.cc @@ -279,7 +279,7 @@ spret cast_summon_ice_beast(int pow, god_type god, bool fail) spret cast_monstrous_menagerie(actor* caster, int pow, god_type god, bool fail) { - if (otr_stop_summoning_prompt()) + if (caster->is_player() && otr_stop_summoning_prompt()) return spret::abort; fail_check(); From 0dde086dc9d1482ee05b764859ae5c1b569ac519 Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 25 May 2019 15:34:17 -0400 Subject: [PATCH 359/864] Add a basic lua seed explorer This prints out information about vaults, monsters, and items so far; it is packaged as a test that prints these for the first 5 seeds (replacing a less interesting test), but is fairly configurable if you're willing to edit the lua. To run it directly, you'll need to use util/fake_pty (which may need to be built), e.g.: util/fake_pty ./crawl -test seed_explorer.lua This also introduces a few lua support things that were missing that might be of general interest, especially monster inventory (which is easy now that all monster items are id'd). --- crawl-ref/source/dungeon.cc | 15 +- crawl-ref/source/l-mons.cc | 19 ++ crawl-ref/source/l-wiz.cc | 5 +- crawl-ref/source/mon-place.cc | 6 +- crawl-ref/source/mon-place.h | 2 + crawl-ref/source/test/d1_vaults.lua | 40 --- crawl-ref/source/test/seed_explorer.lua | 326 ++++++++++++++++++++++++ 7 files changed, 370 insertions(+), 43 deletions(-) delete mode 100644 crawl-ref/source/test/d1_vaults.lua create mode 100644 crawl-ref/source/test/seed_explorer.lua diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index d479e4092948..a19c6c53588c 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -4726,6 +4726,8 @@ monster* dgn_place_monster(mons_spec &mspec, coord_def where, if (!mspec.place.is_valid()) mspec.place = level_id::current(); + bool chose_ood = false; + const int starting_depth = mspec.place.depth; if (type == RANDOM_SUPER_OOD || type == RANDOM_MODERATE_OOD) { @@ -4763,7 +4765,12 @@ monster* dgn_place_monster(mons_spec &mspec, coord_def where, if (mons_class_is_zombified(mspec.monbase)) type = pick_local_zombifiable_monster(mspec.place, mspec.monbase, coord_def()); else - type = pick_random_monster(mspec.place, mspec.monbase); + { + level_id place = mspec.place; + type = pick_random_monster(mspec.place, mspec.monbase, &place); + if (place.depth > starting_depth + 5) + chose_ood = true; + } if (!type) type = RANDOM_MONSTER; } @@ -4851,6 +4858,12 @@ monster* dgn_place_monster(mons_spec &mspec, coord_def where, mons->props[CUSTOM_SPELLS_KEY] = true; } + // this prop is mainly for the seed explorer. + // not a great or complete measure of monster danger: the builder can roll + // on the low side of the ood range, and vaults don't get this set. + if (chose_ood) + mons->props[MON_OOD_KEY].get_bool() = true; + if (!mspec.items.empty()) _dgn_give_mon_spec_items(mspec, mons, type); diff --git a/crawl-ref/source/l-mons.cc b/crawl-ref/source/l-mons.cc index 3923b81dc936..012987ae64d4 100644 --- a/crawl-ref/source/l-mons.cc +++ b/crawl-ref/source/l-mons.cc @@ -9,6 +9,7 @@ #include "cluautil.h" #include "database.h" #include "dlua.h" +#include "items.h" #include "libutil.h" #include "mon-act.h" #include "mon-behv.h" @@ -207,6 +208,23 @@ MDEF(muse) return 0; } +static int l_mons_get_inventory(lua_State *ls) +{ + monster* mons = clua_get_lightuserdata(ls, lua_upvalueindex(1)); + lua_newtable(ls); + int index = 0; + for (mon_inv_iterator ii(*mons); ii; ++ii) + { + if (ii->defined()) + { + clua_push_item(ls, &*ii); + lua_rawseti(ls, -2, ++index); + } + } + return 1; +} +MDEFN(inventory, get_inventory) + static int l_mons_do_dismiss(lua_State *ls) { // dismiss is only callable from dlua, not from managed VMs (i.e. @@ -521,6 +539,7 @@ static MonsAccessor mons_attrs[] = { "add_ench", l_mons_add_ench }, { "del_ench", l_mons_del_ench }, { "you_can_see", l_mons_you_can_see }, + { "get_inventory", l_mons_inventory }, { "speak", l_mons_speak } }; diff --git a/crawl-ref/source/l-wiz.cc b/crawl-ref/source/l-wiz.cc index b65088b2da32..f8eb52ffb922 100644 --- a/crawl-ref/source/l-wiz.cc +++ b/crawl-ref/source/l-wiz.cc @@ -12,6 +12,7 @@ module "crawl" #include "mon-util.h" #include "stringutil.h" #include "wiz-fsim.h" +#include "wiz-item.h" #ifdef WIZARD @@ -39,10 +40,12 @@ LUAFN(wiz_quick_fsim) PLUARET(number, fdata.player.av_eff_dam); } +LUAWRAP(wiz_identify_all_items, wizard_identify_all_items()) + static const struct luaL_reg wiz_dlib[] = { { "quick_fsim", wiz_quick_fsim }, - +{ "identify_all_items", wiz_identify_all_items}, { nullptr, nullptr } }; diff --git a/crawl-ref/source/mon-place.cc b/crawl-ref/source/mon-place.cc index 8b4a2808cfab..c4e3d3d88d6a 100644 --- a/crawl-ref/source/mon-place.cc +++ b/crawl-ref/source/mon-place.cc @@ -264,7 +264,7 @@ static void _apply_ood(level_id &place) if (fuzz) { place.depth += fuzz; - dprf(DIAG_MONPLACE, "Monster level fuzz: %d (old: %s, new: %s)", + dprf("Monster level fuzz: %d (old: %s, new: %s)", fuzz, old_place.describe().c_str(), place.describe().c_str()); } } @@ -646,6 +646,7 @@ monster* place_monster(mgen_data mg, bool force_pos, bool dont_place) mg.cls = resolve_monster_type(mg.cls, mg.base_type, mg.proximity, &mg.pos, mg.map_mask, &place, &want_band, allow_ood); + // TODO: it doesn't seem that this check can ever come out to be true?? bool chose_ood_monster = place.absdepth() > mg.place.absdepth() + 5; if (want_band) mg.flags |= MG_PERMIT_BANDS; @@ -737,6 +738,9 @@ monster* place_monster(mgen_data mg, bool force_pos, bool dont_place) if (mg.props.exists(MAP_KEY)) mon->set_originating_map(mg.props[MAP_KEY].get_string()); + if (chose_ood_monster) + mon->props[MON_OOD_KEY].get_bool() = true; + if (mg.needs_patrol_point() || (mon->type == MONS_ALLIGATOR && !testbits(mon->flags, MF_BAND_MEMBER))) diff --git a/crawl-ref/source/mon-place.h b/crawl-ref/source/mon-place.h index 96375eed4a67..ab620a5312c8 100644 --- a/crawl-ref/source/mon-place.h +++ b/crawl-ref/source/mon-place.h @@ -124,6 +124,8 @@ void replace_boris(); // Active monster band may influence gear generation on band followers. extern band_type active_monster_band; +#define MON_OOD_KEY "mons_is_ood" + #if TAG_MAJOR_VERSION == 34 #define VAULT_MON_TYPES_KEY "vault_mon_types" #define VAULT_MON_BASES_KEY "vault_mon_bases" diff --git a/crawl-ref/source/test/d1_vaults.lua b/crawl-ref/source/test/d1_vaults.lua deleted file mode 100644 index c6cba3fb0897..000000000000 --- a/crawl-ref/source/test/d1_vaults.lua +++ /dev/null @@ -1,40 +0,0 @@ --- this test prints out the D:1-D:4 vaults for some test seeds. This can be used --- to diagnose when seeding changes or isn't working right. - --- this test messes with RNG state! It leaves the RNG with a clean seed 1, --- but if you are expecting deterministic test behavior, take that into --- account. - -local eol = string.char(13) - -for seed = 1,10 do - crawl.stderr("Seed: " .. seed .. eol) - debug.reset_rng(seed) - -- debug.enter_dungeon() crashes, for some reason - -- the following runs through RNG state in the same way that starting a - -- regular game would -- if it produces different results, that's a bug. - debug.flush_map_memory() - debug.dungeon_setup() - debug.goto_place("D:1") - debug.generate_level() - local vault_names = debug.vault_names() - - crawl.stderr(" D:1 vaults for seed " .. seed .. " are: " .. vault_names .. eol) - debug.goto_place("D:2") - debug.generate_level() - local vault_names = debug.vault_names() - - crawl.stderr(" D:2 vaults for seed " .. seed .. " are: " .. vault_names .. eol) - debug.goto_place("D:3") - debug.generate_level() - local vault_names = debug.vault_names() - - crawl.stderr(" D:3 vaults for seed " .. seed .. " are: " .. vault_names .. eol) - debug.goto_place("D:4") - debug.generate_level() - local vault_names = debug.vault_names() - - crawl.stderr(" D:4 vaults for seed " .. seed .. " are: " .. vault_names .. eol) -end - -debug.reset_rng(1) diff --git a/crawl-ref/source/test/seed_explorer.lua b/crawl-ref/source/test/seed_explorer.lua new file mode 100644 index 000000000000..b55c8cbe06c1 --- /dev/null +++ b/crawl-ref/source/test/seed_explorer.lua @@ -0,0 +1,326 @@ +-- tools for seeing what's in a seed. Currently packaged as a test that prints +-- out a few levels from some early seeds in detail, but fairly configurable. +-- TODO: maybe move some of the core code out into dat/dlua? + +local starting_seed = 1 -- fixed seed to start with +local fixed_seeds = 5 -- how many fixed seeds to run? +local rand_seeds = 0 -- how many random seeds to run + +-- matches pregeneration order +local generation_order = { + "D:1", + "D:2", "D:3", "D:4", "D:5", "D:6", "D:7", "D:8", "D:9", + "D:10", "D:11", "D:12", "D:13", "D:14", "D:15", + "Temple", + "Lair:1", "Lair:2", "Lair:3", "Lair:4", "Lair:5", "Lair:6", + "Orc:1", "Orc:2", + "Spider:1", "Spider:2", "Spider:3", "Spider:4", + "Snake:1", "Snake:2", "Snake:3", "Snake:4", + "Shoals:1", "Shoals:2", "Shoals:3", "Shoals:4", + "Swamp:1", "Swamp:2", "Swamp:3", "Swamp:4", + "Vaults:1", "Vaults:2", "Vaults:3", "Vaults:4", "Vaults:5", + "Crypt:1", "Crypt:2", "Crypt:3", + "Depths:1", "Depths:2", "Depths:3", "Depths:4", "Depths:5", + "Hell", + "Elf:1", "Elf:2", "Elf:3", + "Zot:1", "Zot:2", "Zot:3", "Zot:4", "Zot:5", + "Slime:1", "Slime:2", "Slime:3", "Slime:4", "Slime:5", + "Tomb:1", "Tomb:2", "Tomb:3", + "Tar:1", "Tar:2", "Tar:3", "Tar:4", "Tar:5", "Tar:6", "Tar:7", + "Coc:1", "Coc:2", "Coc:3", "Coc:4", "Coc:5", "Coc:6", "Coc:7", + "Dis:1", "Dis:2", "Dis:3", "Dis:4", "Dis:5", "Dis:6", "Dis:7", + } + +-- this variable determines how deep in the generation order to go +--local max_depth = #generation_order +local max_depth = 5 + +------------------------------ +-- some generic list/string manipulation code + +function collapse_dups(l) + local result = {} + table.sort(l) + local cur = "" + local count = 0 + for i, name in ipairs(l) do + if name == cur then + count = count + 1 + else + if (cur ~= "") then + result[#result + 1] = { cur, count } + end + cur = name + count = 1 + end + end + if (cur ~= "") then + result[#result + 1] = { cur, count } + end + for i, name in ipairs(result) do + if result[i][2] > 1 then + result[i] = result[i][1] .. " x" .. result[i][2] + else + result[i] = result[i][1] + end + end + return result +end + +function fancy_join(l, indent, width, sep, initial_indent) + if #l == 0 then + return "" + end + local lines = {} + local cur_line = string.rep(" ", indent) + for i, s in ipairs(l) do + local full_s = s + if (i ~= #l) then + full_s = full_s .. sep + end + if #cur_line + #full_s > width then + lines[#lines + 1] = cur_line + cur_line = string.rep(" ", indent) + end + cur_line = cur_line .. full_s + end + lines[#lines + 1] = cur_line + if not initial_indent and #lines > 0 and indent > 0 then + lines[1] = string.sub(lines[1], indent + 1, #lines[1]) + end + return table.concat(lines, "\n") +end + +------------------------------ +-- code for looking at items + +function arts_only(item) + return item.artefact +end + +function item_ignore_boring(item) + -- TODO: + -- show gold totals? + -- missiles - early on? + -- unenchanted weapons/armour - early on? + if item.is_useless then + return false + elseif item.base_type == "gold" + or item.base_type == "missile" + or item.base_type == "food" then + return false + elseif (item.base_type == "weapon" or item.base_type == "armour") + and item.pluses() <= 0 and not item.branded then + return false + end + return true +end + +local item_notable = item_ignore_boring + +function catalog_items() + wiz.identify_all_items() + local gxm, gym = dgn.max_bounds() + local notable = {} + for p in iter.rect_iterator(dgn.point(1,1), dgn.point(gxm-2, gym-2)) do + local stack = dgn.items_at(p.x, p.y) + if #stack > 0 then + for i, item in ipairs(stack) do + if item_notable(item) then + notable[#notable + 1] = item.name() + end + end + end + -- TODO: shops + end + return notable +end + +------------------------------ +-- code for looking at monsters + +-- fairly subjective, some of these should probably be relative to depth +local always_interesting_mons = util.set{ + "ancient lich", + "orb of fire", + "greater mummy", + "Hell Sentinel", + "Ice Fiend", + "Brimstone Fiend", + "Tzitzimitl", + "shard shrike", + "caustic shrike", + "iron giant", + "juggernaut", + "Killer Klown", + "Orb Guardian", + "curse toe", +} + +function mons_ignore_boring(mons) + return (mons.unique + or always_interesting_mons[mons.name] + or mons.type_name == "player ghost" + or mons.type_name == "pandemonium lord") +end + +local mons_notable = mons_ignore_boring + +function describe_mons(mons) + -- TODO: does it make sense to use the same item notability function here? + local feats = util.map(function (i) return i.name() end, + util.filter(item_notable, mons.get_inventory())) + -- may or may not be useful -- OOD is an indicator of builder choices, not + -- intrinsic monster quality, and it is possible for monsters to be chosen + -- as OOD that are within range, e.g. you can sometimes get the same monster + -- generating as OOD and not OOD. + -- TODO: maybe worth rethinking what counts as OOD? might be something like, + -- average spawn depth for monster in branch is greater than depth + 5. + if mons.has_prop("mons_is_ood") then + feats[#feats + 1] = "OOD" + end + local feat_string = "" + if #feats > 0 then + feat_string = " (" .. table.concat(feats, ", ") .. ")" + end + + local name_string = "bug" + + if mons.type_name == "player ghost" then + name_string = mons.type_name + else + name_string = mons.name + end + if (mons_notable(mons) or #feats > 0) then + return name_string .. feat_string + else + return nil + end +end + +function get_all_monsters() + local gxm, gym = dgn.max_bounds() + local mons_list = {} + for p in iter.rect_iterator(dgn.point(1,1), dgn.point(gxm-2, gym-2)) do + local mons = dgn.mons_at(p.x, p.y) + if mons then + mons_list[#mons_list + 1] = mons + end + end + return mons_list +end + +function catalog_monsters() + wiz.identify_all_items() + return util.map(describe_mons, get_all_monsters()) +end + +function catalog_vaults() + -- TODO: just pass the list directly to lua... + local vaults = debug.vault_names() + first_split = crawl.split(vaults, " and ") + if #first_split < 2 then + return first_split + end + second_split = crawl.split(first_split[1], ", ") + second_split[#second_split + 1] = first_split[2] + return second_split +end + +function make_highlight(h, key, name, to_show, hide_empty) + if not h[key] or not to_show[key] then + return "" + end + s = fancy_join(collapse_dups(h[key]), #name, 80, ", ") + if (#s == 0 and hide_empty) then + return "" + end + return name .. s +end + +function catalog_current_place(lvl, to_show, hide_empty) + -- TODO: features (mainly just altars), shops + highlights = {} + highlights["vaults"] = catalog_vaults() + highlights["items"] = catalog_items() + highlights["monsters"] = catalog_monsters() + h_l = { } + h_l[#h_l+1] = make_highlight(highlights, "vaults", " Vaults: ", to_show, hide_empty) + h_l[#h_l+1] = make_highlight(highlights, "monsters", " Monsters: ", to_show, hide_empty) + h_l[#h_l+1] = make_highlight(highlights, "items", " Items: ", to_show, hide_empty) + h_l = util.filter(function (a) return #a > 0 end, h_l) + if #h_l > 0 or not hide_empty then + crawl.stderr(lvl .. ":") + for _, h in ipairs(h_l) do + crawl.stderr(h) + end + end + return highlights +end + +-- a bit redundant with mapstat? +function catalog_dungeon(level_order, to_show) + local result = {} + dgn.reset_level() + debug.flush_map_memory() + debug.dungeon_setup() + for i,lvl in ipairs(level_order) do + if i > max_depth then break end + if (dgn.br_exists(string.match(lvl, "[^:]+"))) then + debug.goto_place(lvl) + debug.generate_level() + result[lvl] = catalog_current_place(lvl, to_show, true) + end + end + return result +end + +function seed_items(seed) + seed_used = debug.reset_rng(seed) + crawl.stderr("Item catalog for seed " .. seed .. ":") + local run1 = catalog_dungeon(generation_order, util.set{ "items" }) +end + +function seed_arts(seed) + seed_used = debug.reset_rng(seed) + crawl.stderr("Artefact catalog for seed " .. seed .. ":") + item_notable = arts_only + local run1 = catalog_dungeon(generation_order, util.set{ "items" }) + item_notable = ignore_boring +end + +function seed_full_catalog(seed) + seed_used = debug.reset_rng(seed) + crawl.stderr("Catalog for seed " .. seed .. ":") + local run1 = catalog_dungeon(generation_order, util.set{ "vaults", "items", "monsters" }) +end + +function catalog_seeds(seeds, cat_fun) + for _, i in ipairs(seeds) do + cat_fun(i) + end +end + +local seed_seq = { starting_seed } + +if (type(starting_seed) ~= "string") then + for i=starting_seed + 1, starting_seed + fixed_seeds - 1 do + seed_seq[#seed_seq + 1] = i + end +end + +catalog_seeds(seed_seq, seed_full_catalog) + +local rand_seq = { } +math.randomseed(crawl.millis()) +for i=1,rand_seeds do + -- intentional use of non-crawl random(). random doesn't seem to accept + -- anything bigger than 32 bits for the range. + rand_seed = math.random(0x7FFFFFFF) + rand_seq[#rand_seq + 1] = rand_seed +end + +if rand_seeds > 0 then + crawl.stderr("Exploring " .. rand_seeds .. " random seed(s).") + catalog_seeds(rand_seq, seed_items) +end From 57161393b2dcdd40fe53907917b5bc6e1686843d Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 25 May 2019 16:18:03 -0400 Subject: [PATCH 360/864] Some cosmetic fixes for the seed explorer --- crawl-ref/source/test/seed_explorer.lua | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/test/seed_explorer.lua b/crawl-ref/source/test/seed_explorer.lua index b55c8cbe06c1..aa306e4c396e 100644 --- a/crawl-ref/source/test/seed_explorer.lua +++ b/crawl-ref/source/test/seed_explorer.lua @@ -68,6 +68,7 @@ function collapse_dups(l) end function fancy_join(l, indent, width, sep, initial_indent) + -- TODO: reflow around spaces? if #l == 0 then return "" end @@ -78,7 +79,7 @@ function fancy_join(l, indent, width, sep, initial_indent) if (i ~= #l) then full_s = full_s .. sep end - if #cur_line + #full_s > width then + if #cur_line + #full_s > width and i ~= 1 then lines[#lines + 1] = cur_line cur_line = string.rep(" ", indent) end @@ -231,7 +232,11 @@ function make_highlight(h, key, name, to_show, hide_empty) if not h[key] or not to_show[key] then return "" end - s = fancy_join(collapse_dups(h[key]), #name, 80, ", ") + local l = h[key] + if key ~= "vaults" then + l = collapse_dups(l) + end + s = fancy_join(l, #name, 80, ", ") if (#s == 0 and hide_empty) then return "" end @@ -250,7 +255,7 @@ function catalog_current_place(lvl, to_show, hide_empty) h_l[#h_l+1] = make_highlight(highlights, "items", " Items: ", to_show, hide_empty) h_l = util.filter(function (a) return #a > 0 end, h_l) if #h_l > 0 or not hide_empty then - crawl.stderr(lvl .. ":") + crawl.stderr(lvl .. " highlights:") for _, h in ipairs(h_l) do crawl.stderr(h) end From 0f23e7d634758ec3968e3c8aaaac8ef8eacec789 Mon Sep 17 00:00:00 2001 From: Brendan Hickey Date: Sun, 26 May 2019 08:55:53 -0400 Subject: [PATCH 361/864] Remove vampiric brand hunger cost. About ten years ago the vampiric brand increased your hunger clock. This led to tedious weapon swapping. We replaced it with an onwield hunger cost to relieve this obnoxious chore while maintaining a thematically appropriate cost for using a powerful brand. With crawl moving away from hunger as a forward progress clock there isn't a good reason to leave this in place. --- crawl-ref/source/item-use.cc | 15 --------------- crawl-ref/source/player-equip.cc | 10 ---------- 2 files changed, 25 deletions(-) diff --git a/crawl-ref/source/item-use.cc b/crawl-ref/source/item-use.cc index abfa4ee4f323..2684fd41587a 100644 --- a/crawl-ref/source/item-use.cc +++ b/crawl-ref/source/item-use.cc @@ -381,21 +381,6 @@ bool can_wield(const item_def *weapon, bool say_reason, else return false; } - else if (!ignore_temporary_disability - && you.hunger_state < HS_FULL - && get_weapon_brand(*weapon) == SPWPN_VAMPIRISM - && you.undead_state() == US_ALIVE - && !you_foodless() - && (item_type_known(*weapon) || !only_known)) - { - if (say_reason) - { - mpr("This weapon is vampiric, and you must be Full or above to equip it."); - id_brand = true; - } - else - return false; - } if (id_brand) { auto wwpn = const_cast(weapon); diff --git a/crawl-ref/source/player-equip.cc b/crawl-ref/source/player-equip.cc index f84c44d7ea6a..2574028f4526 100644 --- a/crawl-ref/source/player-equip.cc +++ b/crawl-ref/source/player-equip.cc @@ -602,16 +602,6 @@ static void _equip_weapon_effect(item_def& item, bool showMsgs, bool unmeld) // effect second switch (special) { - case SPWPN_VAMPIRISM: - if (you.species != SP_VAMPIRE - && you.undead_state() == US_ALIVE - && !you_foodless() - && !unmeld) - { - make_hungry(4500, false, false); - } - break; - case SPWPN_DISTORTION: if (!was_known) { From c4ac1b27a8b5fbcd1277d26ad5837b87c1763709 Mon Sep 17 00:00:00 2001 From: Brendan Hickey Date: Sun, 26 May 2019 10:37:12 -0400 Subject: [PATCH 362/864] Don't prompt when unwielding vampiric weapons. --- crawl-ref/source/invent.cc | 9 --------- 1 file changed, 9 deletions(-) diff --git a/crawl-ref/source/invent.cc b/crawl-ref/source/invent.cc index 1c865f7d1e0f..eeff73565eed 100644 --- a/crawl-ref/source/invent.cc +++ b/crawl-ref/source/invent.cc @@ -1696,15 +1696,6 @@ bool needs_handle_warning(const item_def &item, operation_types oper, return true; } - if (get_weapon_brand(item) == SPWPN_VAMPIRISM - && you.undead_state() == US_ALIVE - && !you_foodless() - // Don't prompt if you aren't wielding it and you can't. - && (you.hunger_state >= HS_FULL || _is_wielded(item))) - { - return true; - } - if (is_artefact(item) && artefact_property(item, ARTP_CONTAM)) { if (_is_wielded(item) && you_worship(GOD_ZIN)) From b5a06e84e3f35a24216bdc3c8e1097fc068101a0 Mon Sep 17 00:00:00 2001 From: Brendan Hickey Date: Sun, 26 May 2019 10:42:38 -0400 Subject: [PATCH 363/864] Fixup vampiric brand messages to remove hunger references. --- crawl-ref/source/player-equip.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/player-equip.cc b/crawl-ref/source/player-equip.cc index 2574028f4526..a2a42b588bb0 100644 --- a/crawl-ref/source/player-equip.cc +++ b/crawl-ref/source/player-equip.cc @@ -534,10 +534,8 @@ static void _equip_weapon_effect(item_def& item, bool showMsgs, bool unmeld) case SPWPN_VAMPIRISM: if (you.species == SP_VAMPIRE) mpr("You feel a bloodthirsty glee!"); - else if (you.undead_state() == US_ALIVE && !you_foodless()) - mpr("You feel a dreadful hunger."); - else - mpr("You feel an empty sense of dread."); + else + mpr("You feel a sense of dread."); break; case SPWPN_PAIN: From a4d96b6e6e8179b30945d2c9ed38909d3017f72e Mon Sep 17 00:00:00 2001 From: Brendan Hickey Date: Sun, 26 May 2019 12:35:04 -0400 Subject: [PATCH 364/864] Checkwhite fix --- crawl-ref/source/player-equip.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/player-equip.cc b/crawl-ref/source/player-equip.cc index a2a42b588bb0..8c105a9f0d7d 100644 --- a/crawl-ref/source/player-equip.cc +++ b/crawl-ref/source/player-equip.cc @@ -534,7 +534,7 @@ static void _equip_weapon_effect(item_def& item, bool showMsgs, bool unmeld) case SPWPN_VAMPIRISM: if (you.species == SP_VAMPIRE) mpr("You feel a bloodthirsty glee!"); - else + else mpr("You feel a sense of dread."); break; From c1c896e988c1c1615f8e180033dff0a7669ab11d Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 27 May 2019 13:21:42 -0400 Subject: [PATCH 365/864] Seed explorer improvements * Estimate OODness based on probability of generation at the relevant depth. There's also currently disabled code for indicating builder OOD rolls, which I found to be less useful. The supporting lua calls are available for player use in moninfo objects. * Highlight "non-native" monsters, basically things placed by a vault that don't usually show up in the branch. * Handle dancing weapons better. --- crawl-ref/source/l-moninf.cc | 30 ++++++++++++ crawl-ref/source/l-mons.cc | 30 +++++++++++- crawl-ref/source/mon-pick.cc | 39 ++++++++++++++++ crawl-ref/source/mon-pick.h | 5 +- crawl-ref/source/random-pick.h | 35 ++++++++++++++ crawl-ref/source/test/seed_explorer.lua | 61 ++++++++++++++++++++++++- 6 files changed, 195 insertions(+), 5 deletions(-) diff --git a/crawl-ref/source/l-moninf.cc b/crawl-ref/source/l-moninf.cc index 0545fcb60622..d4f7dd603343 100644 --- a/crawl-ref/source/l-moninf.cc +++ b/crawl-ref/source/l-moninf.cc @@ -13,6 +13,7 @@ #include "l-defs.h" #include "libutil.h" // map_find #include "mon-book.h" +#include "mon-pick.h" #include "spl-util.h" #include "stringutil.h" #include "transform.h" @@ -337,6 +338,33 @@ LUAFN(moninf_get_holiness) PLUARET(string, holiness_description(mi->holi).c_str()); } +/*** Get the monster's average depth of (random) generation in the current branch + * Returns -1 if the monster is not generated in this branch. Does not handle + * fish or zombies. + * @treturn number + * @function avg_local_depth + */ +LUAFN(moninf_get_avg_local_depth) +{ + MONINF(ls, 1, mi); + PLUARET(number, monster_pop_depth_avg(you.where_are_you, mi->type)); +} + +/*** Get the monster's probability of randomly generating on the current floor + * This can be used to estimate difficulty, but keep in mind that it is highly + * dependent on the branch's generation table. + * Returns -1 if the monster is not generated in this branch. Does not handle + * fish or zombies. + * @treturn number + * @function avg_local_prob + */ +LUAFN(moninf_get_avg_local_prob) +{ + MONINF(ls, 1, mi); + PLUARET(number, monster_probability(level_id::current(), mi->type)); +} + + // const char* here would save a tiny bit of memory, but every map // for an unique pair of types costs 35KB of code. We have // map elsewhere. @@ -705,6 +733,8 @@ static const struct luaL_reg moninf_lib[] = MIREG(x_pos), MIREG(y_pos), MIREG(pos), + MIREG(avg_local_depth), + MIREG(avg_local_prob), { nullptr, nullptr } }; diff --git a/crawl-ref/source/l-mons.cc b/crawl-ref/source/l-mons.cc index 012987ae64d4..8305fff38ffb 100644 --- a/crawl-ref/source/l-mons.cc +++ b/crawl-ref/source/l-mons.cc @@ -14,6 +14,7 @@ #include "mon-act.h" #include "mon-behv.h" #include "mon-death.h" +#include "mon-pick.h" #include "mon-speak.h" #include "monster.h" #include "mon-util.h" @@ -118,6 +119,19 @@ MDEF(energy) PLUARET(number, (mons->speed_increment - 79)); } +MDEF(in_local_population) +{ + // TODO: should this be in moninf? need a mons for the native check... + // The nativity check is because there are various cases where monsters are + // not in the population tables, but should be considered native, e.g. + // vault gaurds in vaults, orb guardians in zot 5 + PLUARET(boolean, + mons_is_native_in_branch(*mons, you.where_are_you) + || monster_in_population(you.where_are_you, mons->type) + || monster_in_population(you.where_are_you, mons->mons_species(false)) + || monster_in_population(you.where_are_you, mons->mons_species(true))); +} + LUAFN(l_mons_add_energy) { ASSERT_DLUA; @@ -492,6 +506,18 @@ static int l_mons_do_speak(lua_State *ls) MDEFN(speak, do_speak) +static int l_mons_do_get_info(lua_State *ls) +{ + // for a non-dlua version, see monster.get_monster_at + ASSERT_DLUA; + monster* m = clua_get_lightuserdata(ls, lua_upvalueindex(1)); + monster_info mi(m); + lua_push_moninf(ls, &mi); + return 1; +} + +MDEFN(get_info, do_get_info) + struct MonsAccessor { const char *attribute; @@ -540,8 +566,10 @@ static MonsAccessor mons_attrs[] = { "del_ench", l_mons_del_ench }, { "you_can_see", l_mons_you_can_see }, { "get_inventory", l_mons_inventory }, + { "in_local_population", l_mons_in_local_population }, - { "speak", l_mons_speak } + { "speak", l_mons_speak }, + { "get_info", l_mons_get_info } }; static int monster_get(lua_State *ls) diff --git a/crawl-ref/source/mon-pick.cc b/crawl-ref/source/mon-pick.cc index 6aa45e1584ae..fc7443751488 100644 --- a/crawl-ref/source/mon-pick.cc +++ b/crawl-ref/source/mon-pick.cc @@ -184,6 +184,45 @@ const pop_entry* zombie_population(branch_type br) return population_zombie[br].pop; } +bool monster_in_population(branch_type branch, monster_type m, bool check_noncore) +{ + for (const pop_entry *pop = population[branch].pop; pop->value; pop++) + if (pop->value == m) + return true; + if (check_noncore) + { + for (const pop_entry *pop = population_water[branch].pop; pop->value; pop++) + if (pop->value == m) + return true; + for (const pop_entry *pop = population_lava[branch].pop; pop->value; pop++) + if (pop->value == m) + return true; + for (const pop_entry *pop = population_zombie[branch].pop; pop->value; pop++) + if (pop->value == m) + return true; + } + return false; +} + +int monster_probability(level_id place, monster_type m) +{ + // TODO: does not check fish, zombies etc... + if (!monster_in_population(place.branch, m, false)) + return -1; + monster_picker picker = monster_picker(); + return picker.probability_at(m, population[place.branch].pop, place.depth); +} + +int monster_pop_depth_avg(branch_type branch, monster_type m) +{ + for (const pop_entry *pop = population[branch].pop; pop->value; pop++) + if (pop->value == m) + return max(0, (pop->minr + pop->maxr) / 2); + // negative values *are* sometimes used in the data, but the above max will + // prevent them from ever being naturally returned as an average. + return -1; +} + #if defined(DEBUG_DIAGNOSTICS) || defined(DEBUG_TESTS) static bool _not_skeletonable(monster_type mt) { diff --git a/crawl-ref/source/mon-pick.h b/crawl-ref/source/mon-pick.h index d77a9264d93e..ce52caad77f6 100644 --- a/crawl-ref/source/mon-pick.h +++ b/crawl-ref/source/mon-pick.h @@ -12,8 +12,9 @@ typedef random_pick_entry pop_entry; typedef bool (*mon_pick_vetoer)(monster_type); typedef bool (*mon_pick_pos_vetoer)(monster_type, coord_def); -int mons_rarity(monster_type mcls, branch_type branch); -int mons_depth(monster_type mcls, branch_type branch); +bool monster_in_population(branch_type branch, monster_type m, bool check_noncore=true); +int monster_probability(level_id place, monster_type m); +int monster_pop_depth_avg(branch_type branch, monster_type m); monster_type pick_monster(level_id place, mon_pick_vetoer veto = nullptr); monster_type pick_monster_from(const pop_entry *fpop, int depth, diff --git a/crawl-ref/source/random-pick.h b/crawl-ref/source/random-pick.h index 1add44c10853..8e8f4bfbbbf3 100644 --- a/crawl-ref/source/random-pick.h +++ b/crawl-ref/source/random-pick.h @@ -33,6 +33,7 @@ class random_picker public: virtual ~random_picker(); T pick(const random_pick_entry *weights, int level, T none); + int probability_at(T entry, const random_pick_entry *weights, int level); int rarity_at(const random_pick_entry *pop, int depth); virtual bool veto(T val) { return false; } @@ -80,6 +81,40 @@ T random_picker::pick(const random_pick_entry *weights, int level, die("random_pick roll out of range"); } +template +int random_picker::probability_at(T entry, + const random_pick_entry *weights, int level) +{ + struct { T value; int rarity; } valid[max]; + int nvalid = 0; + int totalrar = 0; + int entry_rarity = 0; + + for (const random_pick_entry *pop = weights; pop->rarity; pop++) + { + if (level < pop->minr || level > pop->maxr) + continue; + + if (veto(pop->value)) + continue; + + int rar = rarity_at(pop, level); + ASSERTM(rar > 0, "Rarity %d: %d at level %d", rar, pop->value, level); + + valid[nvalid].value = pop->value; + valid[nvalid].rarity = rar; + if (entry == pop->value) + entry_rarity = rar; + totalrar += rar; + nvalid++; + } + + if (totalrar == 0) + return 0; + return entry_rarity * 100 / totalrar; +} + + template int random_picker::rarity_at(const random_pick_entry *pop, int depth) { diff --git a/crawl-ref/source/test/seed_explorer.lua b/crawl-ref/source/test/seed_explorer.lua index aa306e4c396e..e3c081e34bb7 100644 --- a/crawl-ref/source/test/seed_explorer.lua +++ b/crawl-ref/source/test/seed_explorer.lua @@ -166,20 +166,70 @@ function mons_ignore_boring(mons) end local mons_notable = mons_ignore_boring +--local mons_notable = function (m) return false end + +function mons_always_native(m, mi) + return (mi:is_unique() + or m.type_name == "player ghost" + or mi:is_firewood()) +end + +function rare_ood(mi) + local depth = mi:avg_local_depth() + -- TODO: really, probability can't be interpreted without some sense of what + -- the overall distribution for the branch is, so this is fairly heuristic + local prob = mi:avg_local_prob() + local ood_threshold = math.max(2, dgn.br_depth() / 3) + return depth > you.depth() + ood_threshold and prob < 2 +end + +function feat_in_set(s) + return function (f) if s[f] then return f else return nil end end +end + +--mons_feat_filter = feat_in_set(util.set({ "OOD" })) +mons_feat_filter = nil function describe_mons(mons) + local mi = mons.get_info() + -- TODO: weird distribution of labor between mons and moninfo, can this be + -- cleaned up? -- TODO: does it make sense to use the same item notability function here? local feats = util.map(function (i) return i.name() end, util.filter(item_notable, mons.get_inventory())) + local force_notable = false + if mons_feat_filter then + feats = util.map(mons_feat_filter, feats) -- TODO don't brute force this + end + if mons.type_name == "dancing weapon" and #feats > 0 then + -- don't repeat the dancing weapon's item, but if the item_notable check + -- has deemed the item notable, make sure to show it. + feats = { } + force_notable = true + end + -- may or may not be useful -- OOD is an indicator of builder choices, not -- intrinsic monster quality, and it is possible for monsters to be chosen -- as OOD that are within range, e.g. you can sometimes get the same monster -- generating as OOD and not OOD. -- TODO: maybe worth rethinking what counts as OOD? might be something like, -- average spawn depth for monster in branch is greater than depth + 5. - if mons.has_prop("mons_is_ood") then + -- if mons.has_prop("mons_is_ood") then + -- feats[#feats + 1] = "builder OOD" + -- end + if rare_ood(mi) then feats[#feats + 1] = "OOD" end + if not mons.in_local_population and not mons_always_native(mons, mi) then + -- this is a different sense of "native" than used internally to crawl, + -- in that it includes anything that would normally generate in a + -- branch. The internal sense is just supposed to be about which + -- monsters "live" in a particular branch, which is covered as well. + feats[#feats + 1] = "non-native" + end + if mons_feat_filter then + feats = util.map(mons_feat_filter, feats) + end local feat_string = "" if #feats > 0 then feat_string = " (" .. table.concat(feats, ", ") .. ")" @@ -192,7 +242,7 @@ function describe_mons(mons) else name_string = mons.name end - if (mons_notable(mons) or #feats > 0) then + if (force_notable or mons_notable(mons) or #feats > 0) then return name_string .. feat_string else return nil @@ -294,6 +344,12 @@ function seed_arts(seed) item_notable = ignore_boring end +function seed_mons(seed) + seed_used = debug.reset_rng(seed) + crawl.stderr("Monster catalog for seed " .. seed .. ":") + local run1 = catalog_dungeon(generation_order, util.set{ "monsters" }) +end + function seed_full_catalog(seed) seed_used = debug.reset_rng(seed) crawl.stderr("Catalog for seed " .. seed .. ":") @@ -302,6 +358,7 @@ end function catalog_seeds(seeds, cat_fun) for _, i in ipairs(seeds) do + if _ > 1 then crawl.stderr("") end cat_fun(i) end end From 1748d93fb50ed57d02914a911638d99a2e8ec541 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 27 May 2019 18:48:55 -0400 Subject: [PATCH 366/864] Support random seeds only in seed explorer (alexjurkiewicz) --- crawl-ref/source/test/seed_explorer.lua | 38 +++++++++++++------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/crawl-ref/source/test/seed_explorer.lua b/crawl-ref/source/test/seed_explorer.lua index e3c081e34bb7..a97136955c29 100644 --- a/crawl-ref/source/test/seed_explorer.lua +++ b/crawl-ref/source/test/seed_explorer.lua @@ -2,8 +2,10 @@ -- out a few levels from some early seeds in detail, but fairly configurable. -- TODO: maybe move some of the core code out into dat/dlua? -local starting_seed = 1 -- fixed seed to start with -local fixed_seeds = 5 -- how many fixed seeds to run? +-- to use a >32bit seed, you will need to use a string here. If you use a +-- string, `fixed_seed` is maxed at 1. +local starting_seed = 1 -- fixed seed to start with, number or string +local fixed_seeds = 5 -- how many fixed seeds to run? Can be 0. local rand_seeds = 0 -- how many random seeds to run -- matches pregeneration order @@ -363,26 +365,26 @@ function catalog_seeds(seeds, cat_fun) end end -local seed_seq = { starting_seed } +if fixed_seeds > 0 then + local seed_seq = { starting_seed } -if (type(starting_seed) ~= "string") then - for i=starting_seed + 1, starting_seed + fixed_seeds - 1 do - seed_seq[#seed_seq + 1] = i + if (type(starting_seed) ~= "string") then + for i=starting_seed + 1, starting_seed + fixed_seeds - 1 do + seed_seq[#seed_seq + 1] = i + end end -end - -catalog_seeds(seed_seq, seed_full_catalog) - -local rand_seq = { } -math.randomseed(crawl.millis()) -for i=1,rand_seeds do - -- intentional use of non-crawl random(). random doesn't seem to accept - -- anything bigger than 32 bits for the range. - rand_seed = math.random(0x7FFFFFFF) - rand_seq[#rand_seq + 1] = rand_seed + catalog_seeds(seed_seq, seed_full_catalog) end if rand_seeds > 0 then + local rand_seq = { } + math.randomseed(crawl.millis()) + for i=1,rand_seeds do + -- intentional use of non-crawl random(). random doesn't seem to accept + -- anything bigger than 32 bits for the range. + rand_seed = math.random(0x7FFFFFFF) + rand_seq[#rand_seq + 1] = rand_seed + end crawl.stderr("Exploring " .. rand_seeds .. " random seed(s).") - catalog_seeds(rand_seq, seed_items) + catalog_seeds(rand_seq, seed_full_catalog) end From 0e0cebd0f35aafe5dc9093d1b4cca157704995b6 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 27 May 2019 19:18:38 -0400 Subject: [PATCH 367/864] Have fake_pty respond better to SIGINT and SIGTERM ...by killing the subprocess. The point of this is to allow ctrl-c at the command line to work. This is pretty hacky but it's better than nothing. If someone has any idea why SIGHUP won't work, let me know. --- crawl-ref/source/util/fake_pty.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/crawl-ref/source/util/fake_pty.c b/crawl-ref/source/util/fake_pty.c index c688b1396ccc..a8b4c19299c8 100644 --- a/crawl-ref/source/util/fake_pty.c +++ b/crawl-ref/source/util/fake_pty.c @@ -21,6 +21,15 @@ static void sigalrm(int signum) kill(crawl, SIGTERM); } +static void kill_crawl(int signum) +{ + // I can't figure out any other signal than this that works. SIGTERM + // prints a crash log, which is not what I'm going for. SIGHUP works + // normally, but just seems to freeze a crawl process run from fake_pty + // for some reason... + kill(crawl, SIGKILL); +} + static void slurp_output() { struct pollfd pfd; @@ -82,6 +91,14 @@ int main(int argc, char * const *argv) return 1; default: + { + struct sigaction sa; + sa.sa_handler = kill_crawl; + sigemptyset(&sa.sa_mask); + sigaction(SIGINT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + + /* Handle error */; close(slave); slurp_output(); if (waitpid(crawl, &ret, 0) != crawl) @@ -94,4 +111,5 @@ int main(int argc, char * const *argv) // fo the mother-in-law or what? return 1; } + } } From 78adf7823c89c138fdce218835c249e8b4584a99 Mon Sep 17 00:00:00 2001 From: Alan Malloy Date: Wed, 29 May 2019 09:57:10 -0700 Subject: [PATCH 368/864] Remove unused variables in random_picker::probability_at --- crawl-ref/source/random-pick.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/crawl-ref/source/random-pick.h b/crawl-ref/source/random-pick.h index 8e8f4bfbbbf3..9cbba26e1d21 100644 --- a/crawl-ref/source/random-pick.h +++ b/crawl-ref/source/random-pick.h @@ -85,8 +85,6 @@ template int random_picker::probability_at(T entry, const random_pick_entry *weights, int level) { - struct { T value; int rarity; } valid[max]; - int nvalid = 0; int totalrar = 0; int entry_rarity = 0; @@ -101,12 +99,9 @@ int random_picker::probability_at(T entry, int rar = rarity_at(pop, level); ASSERTM(rar > 0, "Rarity %d: %d at level %d", rar, pop->value, level); - valid[nvalid].value = pop->value; - valid[nvalid].rarity = rar; if (entry == pop->value) entry_rarity = rar; totalrar += rar; - nvalid++; } if (totalrar == 0) From 78e9d4e317b4fd8ea0553dd674af1e531ba3b321 Mon Sep 17 00:00:00 2001 From: Alan Malloy Date: Wed, 29 May 2019 10:23:29 -0700 Subject: [PATCH 369/864] Make Tomb stop printing warnings when in debug mode It was placing 3 exit stairs on purpose and relying on the dungeon builder to trim them down to 1 branch exit. Instead, it now places just one. --- crawl-ref/source/dat/des/branches/tomb.des | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/dat/des/branches/tomb.des b/crawl-ref/source/dat/des/branches/tomb.des index 6bf7507344f2..c0c854216513 100644 --- a/crawl-ref/source/dat/des/branches/tomb.des +++ b/crawl-ref/source/dat/des/branches/tomb.des @@ -98,11 +98,11 @@ function tomb_1_centre_setup(e) end --[[ -Setup Tomb:1 hall stairs. Vaults should place an P glyph for the hallway entry +Setup Tomb:1 hall stairs. Vaults should place a P glyph for the hallway entry destination, a Q glyph for the first hall exit (near P), and an R glyph for the second hall exit (to the second set of rooms on Tomb:2). Any '.' glyphs have a small chance of placing a '3' guardian or an appropriate trap type. About 7 '3' -and about 6 traps on-average. +and about 6 traps on average. ]] function tomb_1_stairs_setup(e) e.lua_marker("P", hatch_dest_name("tomb1_hall_entry")) @@ -469,7 +469,7 @@ SUBVAULT: B : tomb_1_hall_stairs MONS: greater mummy / nothing MONS: sphinx / nothing MONS: obsidian statue / orange crystal statue -SHUFFLE: ([{ +NSUBST: ( = 1:( / *:. # Set up decorative statues. : if crawl.coinflip() then SUBST: I = I:900 5, N = N:900 5 @@ -494,7 +494,7 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -xxxxxxxxx(.............................[..............................{xxxxxxxxx +xxxxxxxxx(.............................(..............................(xxxxxxxxx xxxxxxxxx..............................................................xxxxxxxxx xxxxxxxxx..............................................................xxxxxxxxx xxxxxxxxx..............................................................xxxxxxxxx From 4cc88bcadc24e0e6d1eeb39031464e7f27be8437 Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Sun, 26 May 2019 10:26:32 +0100 Subject: [PATCH 370/864] Update vine stalker description (11979) --- crawl-ref/source/dat/descript/species.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/dat/descript/species.txt b/crawl-ref/source/dat/descript/species.txt index 892c26481583..5bd9eab50077 100644 --- a/crawl-ref/source/dat/descript/species.txt +++ b/crawl-ref/source/dat/descript/species.txt @@ -128,6 +128,6 @@ stabbers and casters. %%%% Vine Stalker -Frail symbionts, Vine Stalkers cannot regain health from devices or potions. +Frail symbionts, Vine Stalkers cannot regain health from potions. Their magical reserves absorb damage, and they pack a magic-restoring bite. %%%% From 9fa3ae0aaa3e51e4a1dd3304eb7cdf4cb06e392c Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Fri, 24 May 2019 20:13:02 +0100 Subject: [PATCH 371/864] Mention draining gaze's healing effect Draining gaze heals ghost moths and eyes of draining for the amount of MP drained by the gaze. This commit adds a note to this effect to the draining gaze spell description. Note: orange crystal statues also cast this spell, but they don't get healed from it because they cannot regenerate HP. --- crawl-ref/source/dat/descript/spells.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/dat/descript/spells.txt b/crawl-ref/source/dat/descript/spells.txt index 81ccc7696425..9410d85a2b1d 100644 --- a/crawl-ref/source/dat/descript/spells.txt +++ b/crawl-ref/source/dat/descript/spells.txt @@ -500,7 +500,8 @@ antimagic weapon. Draining Gaze spell Causes the target's magic to leak into the air, as though they were hit by an -antimagic weapon, with no direct line of fire required. +antimagic weapon, and heals the caster for the amount of magic drained, +with no direct line of fire required. %%%% Dream Dust spell From 39439d866b87e4c0fe0d56dbc96eb4712fd95d15 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Wed, 29 May 2019 22:00:19 -0400 Subject: [PATCH 372/864] Fix an arena crash behavior_event only makes sense in non-arena mode, but was being called whenever an eldritch tentacle timed out --- crawl-ref/source/mon-ench.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/mon-ench.cc b/crawl-ref/source/mon-ench.cc index de894911723f..b54be1f03c61 100644 --- a/crawl-ref/source/mon-ench.cc +++ b/crawl-ref/source/mon-ench.cc @@ -1648,10 +1648,12 @@ void monster::apply_enchantment(const mon_enchant &me) maybe_bloodify_square(base_position); add_ench(ENCH_SEVERED); - // Severed tentacles immediately become "hostile" to everyone (or insane) + // Severed tentacles immediately become "hostile" to everyone + // (or insane) attitude = ATT_NEUTRAL; mons_att_changed(this); - behaviour_event(this, ME_ALERT); + if (!crawl_state.game_is_arena()) + behaviour_event(this, ME_ALERT); } } break; From 3ea9d24d9875e4fb03d23841ceca4826e8735b41 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 30 May 2019 08:52:33 -0400 Subject: [PATCH 373/864] Fix some missed random call sequencing resolve_range is just a wrapper on a random call, and so these calls need sequence points to be stable across compilers. (See cdddf7c89e9) --- crawl-ref/source/dgn-height.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/dgn-height.cc b/crawl-ref/source/dgn-height.cc index 3da07f4f1cd1..99768fa21bba 100644 --- a/crawl-ref/source/dgn-height.cc +++ b/crawl-ref/source/dgn-height.cc @@ -146,8 +146,10 @@ coord_def dgn_island_plan::pick_island_spot() void dgn_island_plan::build_island() { const coord_def c = pick_island_spot(); - dgn_island_centred_at(c, resolve_range(n_island_centre_delta_points), - resolve_range(island_centre_radius_range), + const int npoints = resolve_range(n_island_centre_delta_points); + const int radius = resolve_range(island_centre_radius_range); + dgn_island_centred_at(c, npoints, + radius, island_centre_point_height_increment, level_border_depth, x_chance_in_y(atoll_roll, 100)); @@ -161,9 +163,11 @@ void dgn_island_plan::build_island() dgn_random_point_from(c, addition_offset, level_border_depth); if (!offsetC.origin()) { + const int extra_npoints = resolve_range(n_island_aux_delta_points); + const int extra_radius = resolve_range(island_aux_radius_range); dgn_island_centred_at( - offsetC, resolve_range(n_island_aux_delta_points), - resolve_range(island_aux_radius_range), + offsetC, extra_npoints, + extra_radius, island_aux_point_height_increment, level_border_depth, x_chance_in_y(atoll_roll, 100)); From 4de66ed42b6e5dd9f00c00d6f9cd9cd40cff3924 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 30 May 2019 00:42:30 -0400 Subject: [PATCH 374/864] Properly reset tags on vaults rooms The initial tag change here was persisting on vault definitions until the next time crawl restarted, leading to seed instability in some cases. In the seed this came up in, serial_ice_m placed in D and mirrored horizontally. This vault is tagged with vaults_empty, and on vaults 4 was getting the no_hmirror tag (among others) even though it didn't ultimately place, and this was sticking around to any future games in the same crawl session that tried to place serial_ice_m, leading to the seed diverging after that point. (The more obvious divergence from the failure to hmirror in this seed came much later in _prepare_water, because the deep water positions in the map were affected by whether this vault mirrored or not.) --- crawl-ref/source/dat/dlua/v_rooms.lua | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/dat/dlua/v_rooms.lua b/crawl-ref/source/dat/dlua/v_rooms.lua index d8452170b3ba..f56c040dc89d 100644 --- a/crawl-ref/source/dat/dlua/v_rooms.lua +++ b/crawl-ref/source/dat/dlua/v_rooms.lua @@ -88,15 +88,23 @@ local function make_tagged_room(options,chosen) -- Temporarily prevent map getting mirrored / rotated during resolution because it'll seriously -- screw with our attempts to understand and position the vault later; and hardwire transparency because lack of it can fail a whole layout -- TODO: Store these tags on the room first so we can actually support them down the line ... - dgn.tags(mapdef, "no_vmirror no_hmirror no_rotate transparent"); + local old_tags = dgn.tags(mapdef) + dgn.tags(mapdef, "no_vmirror no_hmirror no_rotate transparent") -- Resolve the map so we can find its width / height local map, vplace = dgn.resolve_map(mapdef,false) local room,room_width,room_height -- If we can't find a map then we're probably not going to find one - if map == nil then return nil end + if map == nil then + dgn.tags(mapdef, nil) + dgn.tags(mapdef, old_tags) + return nil + end -- Allow map to be flipped and rotated again, otherwise we'll struggle later when we want to rotate it into the correct orientation dgn.tags_remove(map, "no_vmirror no_hmirror no_rotate") + -- restore the original tags to mapdef, since this state is persistent + dgn.tags(mapdef, nil) + dgn.tags(mapdef, old_tags .. " transparent") local room_width,room_height = dgn.mapsize(map) local veto = false From c54ef598922e0940e4e27bbbe1f7a4a5a315428c Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Thu, 30 May 2019 20:44:42 +0100 Subject: [PATCH 375/864] Remove an obsolete Donald line (#11994) --- crawl-ref/source/dat/database/monspeak.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/crawl-ref/source/dat/database/monspeak.txt b/crawl-ref/source/dat/database/monspeak.txt index 73e56f6943a9..70f4a4d994d6 100644 --- a/crawl-ref/source/dat/database/monspeak.txt +++ b/crawl-ref/source/dat/database/monspeak.txt @@ -3538,8 +3538,6 @@ w:50 @The_monster@ says, "Don't you get tired of all these old geezers telling you what to do?" -@The_monster@ says, "Heaven on Earth? Sounds overrated." - @The_monster@ says, "No way as a way? Sounds like nonsense." %%%% No God Donald From ee2287cf4384335a8010bfbd3f360fb0ab43cdbe Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Thu, 30 May 2019 20:45:08 +0100 Subject: [PATCH 376/864] Update WJC powers description (#11994) --- crawl-ref/source/dat/descript/gods.txt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/crawl-ref/source/dat/descript/gods.txt b/crawl-ref/source/dat/descript/gods.txt index 1c6d93923a87..3fd4e663f735 100644 --- a/crawl-ref/source/dat/descript/gods.txt +++ b/crawl-ref/source/dat/descript/gods.txt @@ -309,11 +309,10 @@ and armour; and mutate followers to better reflect Jiyva's image. %%%% Wu Jian powers -Disciples of the Council learn to perform three martial techniques, shown -below. They will also be taught to move at unfathomable speeds for short -distances, and become able to summon a storm of golden clouds to increase their -precision and damage for as long as they keep using martial attacks. - +Disciples of the Council learn to perform three martial techniques while moving +around in combat. They will also be taught to move at unfathomable speeds for +short distances, and become able to summon a storm of golden clouds to increase +their precision and damage for as long as they keep using martial attacks. %%%% Kikubaaqudgha powers From 94936e539ceaa9731ce42c9872be41eba4f68cd2 Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Fri, 31 May 2019 19:10:01 +0100 Subject: [PATCH 377/864] Fix ?amnesia reversed logic (#11998) --- crawl-ref/source/item-use.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/item-use.cc b/crawl-ref/source/item-use.cc index 2684fd41587a..5710287ed598 100644 --- a/crawl-ref/source/item-use.cc +++ b/crawl-ref/source/item-use.cc @@ -3177,10 +3177,11 @@ void read_scroll(item_def& scroll) { aborted = cast_selective_amnesia() == -1; done = !aborted - || alreadyknown - || crawl_state.seen_hups - || yesno("Really abort (and waste the scroll)?", false, 0); - cancel_scroll = aborted && !alreadyknown; + || alreadyknown + || crawl_state.seen_hups + || yesno("Really abort (and waste the scroll)?", + false, 0); + cancel_scroll = aborted && alreadyknown; } while (!done); if (aborted) canned_msg(MSG_OK); From c0b1d33993384d9be4e6c37991993ba62353d79d Mon Sep 17 00:00:00 2001 From: Edgar Bering Date: Sun, 2 Jun 2019 16:13:52 -0400 Subject: [PATCH 378/864] Add more teleport traps to grunt_tough_drop (11997) Now that teleport traps don't trigger out of LOS, this vault was not working properly. By adding teleport traps that give monsters room to move in the two hallways, a player passing through the hall will still cause the monsters to step on a permanent teleport trap. --- crawl-ref/source/dat/des/variable/mini_monsters.des | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/dat/des/variable/mini_monsters.des b/crawl-ref/source/dat/des/variable/mini_monsters.des index 711b36ea3036..91c8529c07e8 100644 --- a/crawl-ref/source/dat/des/variable/mini_monsters.des +++ b/crawl-ref/source/dat/des/variable/mini_monsters.des @@ -4532,9 +4532,9 @@ MAP ....n|n.... .cccc+cccc. .c8^n_n^8c. -.cccc.cccc. +.cc^c.c^cc. .c8^n.n^8c. -.cccc.cccc. +.cc^c.c^cc. .c8^n.n^8c. .cccc+cccc. ........... From 7ade4d1b3c49c31202db47c3985498137210dc9b Mon Sep 17 00:00:00 2001 From: Edgar Bering Date: Sun, 2 Jun 2019 16:36:15 -0400 Subject: [PATCH 379/864] Add a penance prompt for potion quaffing (12001) Prompt when a player attempts to quaff a known god-hated potion. --- crawl-ref/source/item-use.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/item-use.cc b/crawl-ref/source/item-use.cc index 5710287ed598..64e49fea4b06 100644 --- a/crawl-ref/source/item-use.cc +++ b/crawl-ref/source/item-use.cc @@ -2082,9 +2082,12 @@ void drink(item_def* potion) return; } - string prompt = make_stringf("Really quaff the %s?", - potion->name(DESC_DBNAME).c_str()); - if (alreadyknown && is_dangerous_item(*potion, true) + bool penance = god_hates_item(*potion); + string prompt = make_stringf("Really quaff the %s?%s", + potion->name(DESC_DBNAME).c_str(), + penance ? " This action would place" + " you under penance!" : ""); + if (alreadyknown && (is_dangerous_item(*potion, true) || penance) && Options.bad_item_prompt && !yesno(prompt.c_str(), false, 'n')) { From 637bb3806fda9021cf3beb44ccc69658059d2ad6 Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 2 Jun 2019 18:41:01 -0400 Subject: [PATCH 380/864] Add dungeon features to the seed explorer --- crawl-ref/source/l-dgngrd.cc | 12 +++--- crawl-ref/source/l-wiz.cc | 4 ++ crawl-ref/source/l-you.cc | 7 ++++ crawl-ref/source/test/seed_explorer.lua | 54 ++++++++++++++++++++++++- 4 files changed, 70 insertions(+), 7 deletions(-) diff --git a/crawl-ref/source/l-dgngrd.cc b/crawl-ref/source/l-dgngrd.cc index f4dfd520f0ca..843079d59bc0 100644 --- a/crawl-ref/source/l-dgngrd.cc +++ b/crawl-ref/source/l-dgngrd.cc @@ -57,9 +57,9 @@ static int dgn_feature_desc(lua_State *ls) const dungeon_feature_type feat = static_cast(luaL_safe_checkint(ls, 1)); const description_level_type dtype = - lua_isnumber(ls, 2)? - static_cast(luaL_safe_checkint(ls, 2)) : - description_type_by_name(lua_tostring(ls, 2)); + lua_isnumber(ls, 2)? + static_cast(luaL_safe_checkint(ls, 2)) : + description_type_by_name(lua_tostring(ls, 2)); const bool need_stop = lua_isboolean(ls, 3)? lua_toboolean(ls, 3) : false; const string s = feature_description(feat, NUM_TRAPS, "", dtype, need_stop); lua_pushstring(ls, s.c_str()); @@ -69,9 +69,9 @@ static int dgn_feature_desc(lua_State *ls) static int dgn_feature_desc_at(lua_State *ls) { const description_level_type dtype = - lua_isnumber(ls, 3)? - static_cast(luaL_safe_checkint(ls, 3)) : - description_type_by_name(lua_tostring(ls, 3)); + lua_isnumber(ls, 3) ? + static_cast(luaL_safe_checkint(ls, 3)) : + description_type_by_name(lua_tostring(ls, 3)); const bool need_stop = lua_isboolean(ls, 4)? lua_toboolean(ls, 4) : false; const string s = feature_description_at(coord_def(luaL_safe_checkint(ls, 1), luaL_safe_checkint(ls, 2)), diff --git a/crawl-ref/source/l-wiz.cc b/crawl-ref/source/l-wiz.cc index f8eb52ffb922..ad2b2bb1d889 100644 --- a/crawl-ref/source/l-wiz.cc +++ b/crawl-ref/source/l-wiz.cc @@ -11,6 +11,7 @@ module "crawl" #include "cluautil.h" #include "mon-util.h" #include "stringutil.h" +#include "wiz-dgn.h" #include "wiz-fsim.h" #include "wiz-item.h" @@ -42,10 +43,13 @@ LUAFN(wiz_quick_fsim) LUAWRAP(wiz_identify_all_items, wizard_identify_all_items()) +LUAWRAP(wiz_map_level, wizard_map_level()) + static const struct luaL_reg wiz_dlib[] = { { "quick_fsim", wiz_quick_fsim }, { "identify_all_items", wiz_identify_all_items}, +{ "map_level", wiz_map_level}, { nullptr, nullptr } }; diff --git a/crawl-ref/source/l-you.cc b/crawl-ref/source/l-you.cc index edd9aea440ca..335511e91605 100644 --- a/crawl-ref/source/l-you.cc +++ b/crawl-ref/source/l-you.cc @@ -1524,6 +1524,12 @@ LUAFN(you_init) PLUARET(string, skill_name(item_attack_skill(OBJ_WEAPONS, ng.weapon))); } +LUAFN(you_enter_wizard_mode) +{ + you.wizard = true; + return 0; +} + LUARET1(you_exp_needed, number, exp_needed(luaL_safe_checkint(ls, 1))) LUAWRAP(you_exercise, exercise(str_to_skill(luaL_checkstring(ls, 1)), 1)) LUARET1(you_skill_cost_level, number, you.skill_cost_level) @@ -1565,6 +1571,7 @@ static const struct luaL_reg you_dlib[] = { "delete_all_mutations", you_delete_all_mutations }, { "change_species", you_change_species }, #ifdef WIZARD +{ "enter_wizard_mode", you_enter_wizard_mode }, { "set_xl", you_set_xl }, #endif diff --git a/crawl-ref/source/test/seed_explorer.lua b/crawl-ref/source/test/seed_explorer.lua index a97136955c29..742d44948858 100644 --- a/crawl-ref/source/test/seed_explorer.lua +++ b/crawl-ref/source/test/seed_explorer.lua @@ -2,6 +2,10 @@ -- out a few levels from some early seeds in detail, but fairly configurable. -- TODO: maybe move some of the core code out into dat/dlua? +you.enter_wizard_mode() -- necessary so that magic mapping behaves correctly. + -- this is implied by you.save = false, so it shouldn't + -- affect other tests in actual test mode... + -- to use a >32bit seed, you will need to use a string here. If you use a -- string, `fixed_seed` is maxed at 1. local starting_seed = 1 -- fixed seed to start with, number or string @@ -139,6 +143,46 @@ function catalog_items() return notable end +------------------------------ +-- code for looking at features + +local hell_branches = util.set{ "Geh", "Coc", "Dis", "Tar" } + +function in_hell() + return hell_branches[you.branch()] +end + +function feat_interesting(feat_name) + -- most features are pretty boring... + if string.find(feat_name, "altar_") == 1 then + return true + elseif string.find(feat_name, "enter_") == 1 then -- could be more selective + if in_hell() then + return feat_name ~= "enter_hell" + else + return true + end + elseif feat_name == "transporter" or string.find(feat_name, "runed_") then + return true + end + return false +end + +function catalog_features() + -- TODO: this could be a lot more efficient in skipping things like walls + wiz.map_level() -- abyss will break this call... + local gxm, gym = dgn.max_bounds() + local notable = {} + for p in iter.rect_iterator(dgn.point(1,1), dgn.point(gxm-2, gym-2)) do + local feat = dgn.grid(p.x, p.y) + --crawl.stderr(dgn.feature_desc(feat)) + if feat_interesting(dgn.feature_name(feat)) then + notable[#notable + 1] = dgn.feature_desc_at(p.x, p.y, "A") + end + end + return notable +end + ------------------------------ -- code for looking at monsters @@ -301,10 +345,12 @@ function catalog_current_place(lvl, to_show, hide_empty) highlights["vaults"] = catalog_vaults() highlights["items"] = catalog_items() highlights["monsters"] = catalog_monsters() + highlights["features"] = catalog_features() h_l = { } h_l[#h_l+1] = make_highlight(highlights, "vaults", " Vaults: ", to_show, hide_empty) h_l[#h_l+1] = make_highlight(highlights, "monsters", " Monsters: ", to_show, hide_empty) h_l[#h_l+1] = make_highlight(highlights, "items", " Items: ", to_show, hide_empty) + h_l[#h_l+1] = make_highlight(highlights, "features", " Features: ", to_show, hide_empty) h_l = util.filter(function (a) return #a > 0 end, h_l) if #h_l > 0 or not hide_empty then crawl.stderr(lvl .. " highlights:") @@ -352,10 +398,16 @@ function seed_mons(seed) local run1 = catalog_dungeon(generation_order, util.set{ "monsters" }) end +function seed_feats(seed) + seed_used = debug.reset_rng(seed) + crawl.stderr("Dungeon feature catalog for seed " .. seed .. ":") + local run1 = catalog_dungeon(generation_order, util.set{ "features" }) +end + function seed_full_catalog(seed) seed_used = debug.reset_rng(seed) crawl.stderr("Catalog for seed " .. seed .. ":") - local run1 = catalog_dungeon(generation_order, util.set{ "vaults", "items", "monsters" }) + local run1 = catalog_dungeon(generation_order, util.set{ "vaults", "items", "features", "monsters" }) end function catalog_seeds(seeds, cat_fun) From 8e8615713e6ee5ab6bfd1d7fbf1b46d26cfbf1e0 Mon Sep 17 00:00:00 2001 From: Edgar Bering Date: Mon, 3 Jun 2019 11:42:20 -0400 Subject: [PATCH 381/864] Don't target chain spell arcs through actors (12003) In the target selection loop in cast_chain_spell, no check was made to ensure that the arc from source to target was not obstructed by an actor. As a result, the special-cased treatment of the caster was ignored occasionally. By tracing the ray for each potential target and checking for obstructions this problem is avoided. --- crawl-ref/source/spl-damage.cc | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/crawl-ref/source/spl-damage.cc b/crawl-ref/source/spl-damage.cc index 4f1b1f27b149..a1425f0bdb4c 100644 --- a/crawl-ref/source/spl-damage.cc +++ b/crawl-ref/source/spl-damage.cc @@ -30,6 +30,7 @@ #include "invent.h" #include "item-name.h" #include "items.h" +#include "los.h" #include "losglobal.h" #include "macro.h" #include "message.h" @@ -226,6 +227,18 @@ spret cast_chain_spell(spell_type spell_cast, int pow, continue; } + // check for actors along the arc path + ray_def ray; + if (!find_ray(source, mi->pos(), ray, opc_solid)) + continue; + + while (ray.advance()) + if (actor_at(ray.pos())) + break; + + if (ray.pos() != mi->pos()) + continue; + count++; if (dist < min_dist) From 2b49f6db2301572b5a43b35345545d1e2a350a68 Mon Sep 17 00:00:00 2001 From: Edgar Bering Date: Mon, 3 Jun 2019 13:26:07 -0400 Subject: [PATCH 382/864] Fix another arena crash Closely related to the crash fixed in 39439d866, check for arena state before dispatching a behavior event. --- crawl-ref/source/mon-ench.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/mon-ench.cc b/crawl-ref/source/mon-ench.cc index b54be1f03c61..02236e912957 100644 --- a/crawl-ref/source/mon-ench.cc +++ b/crawl-ref/source/mon-ench.cc @@ -1678,7 +1678,8 @@ void monster::apply_enchantment(const mon_enchant &me) attitude = ATT_HOSTILE; mons_att_changed(this); - behaviour_event(this, ME_ALERT, &you); + if (!crawl_state.game_is_arena()) + behaviour_event(this, ME_ALERT, &you); } } break; From 4b3246705cc55370f779a6f3db4f7f075be1ca26 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 3 Jun 2019 11:59:23 -0400 Subject: [PATCH 383/864] Refactor the seed explorer code into a module in dat/dlua Some minor cosmetic changes to the output while doing this, as well as some code cleanup, but the behavior shouldn't be majorly changed. --- crawl-ref/source/dat/dlua/explorer.lua | 451 ++++++++++++++++++++++++ crawl-ref/source/test/seed_explorer.lua | 410 +-------------------- 2 files changed, 455 insertions(+), 406 deletions(-) create mode 100644 crawl-ref/source/dat/dlua/explorer.lua diff --git a/crawl-ref/source/dat/dlua/explorer.lua b/crawl-ref/source/dat/dlua/explorer.lua new file mode 100644 index 000000000000..d0f6f6a48499 --- /dev/null +++ b/crawl-ref/source/dat/dlua/explorer.lua @@ -0,0 +1,451 @@ +-- tools for seeing what's in a seed. + +-- -- to use a >32bit seed, you will need to use a string here. If you use a +-- -- string, `fixed_seed` is maxed at 1. +-- local starting_seed = 1 -- fixed seed to start with, number or string +-- local fixed_seeds = 5 -- how many fixed seeds to run? Can be 0. +-- local rand_seeds = 0 -- how many random seeds to run + +util.namespace('explorer') + +-- matches pregeneration order +explorer.generation_order = { + "D:1", + "D:2", "D:3", "D:4", "D:5", "D:6", "D:7", "D:8", "D:9", + "D:10", "D:11", "D:12", "D:13", "D:14", "D:15", + "Temple", + "Lair:1", "Lair:2", "Lair:3", "Lair:4", "Lair:5", "Lair:6", + "Orc:1", "Orc:2", + "Spider:1", "Spider:2", "Spider:3", "Spider:4", + "Snake:1", "Snake:2", "Snake:3", "Snake:4", + "Shoals:1", "Shoals:2", "Shoals:3", "Shoals:4", + "Swamp:1", "Swamp:2", "Swamp:3", "Swamp:4", + "Vaults:1", "Vaults:2", "Vaults:3", "Vaults:4", "Vaults:5", + "Crypt:1", "Crypt:2", "Crypt:3", + "Depths:1", "Depths:2", "Depths:3", "Depths:4", "Depths:5", + "Hell", + "Elf:1", "Elf:2", "Elf:3", + "Zot:1", "Zot:2", "Zot:3", "Zot:4", "Zot:5", + "Slime:1", "Slime:2", "Slime:3", "Slime:4", "Slime:5", + "Tomb:1", "Tomb:2", "Tomb:3", + "Tar:1", "Tar:2", "Tar:3", "Tar:4", "Tar:5", "Tar:6", "Tar:7", + "Coc:1", "Coc:2", "Coc:3", "Coc:4", "Coc:5", "Coc:6", "Coc:7", + "Dis:1", "Dis:2", "Dis:3", "Dis:4", "Dis:5", "Dis:6", "Dis:7", + } + +explorer.zot_depth = 0 + +for i, l in ipairs(explorer.generation_order) do + if l == "Zot:5" then + explorer.zot_depth = i + break + end +end + +assert(explorer.zot_depth ~= 0) + +-- -- this variable determines how deep in the generation order to go +-- --local max_depth = #generation_order +-- local max_depth = 5 + +-- TODO: generalize, allow changing? +local out = function(s) if not explorer.quiet then crawl.stderr(s) end end + +------------------------------ +-- some generic list/string manipulation code + +function explorer.collapse_dups(l) + local result = {} + table.sort(l) + local cur = "" + local count = 0 + for i, name in ipairs(l) do + if name == cur then + count = count + 1 + else + if (cur ~= "") then + result[#result + 1] = { cur, count } + end + cur = name + count = 1 + end + end + if (cur ~= "") then + result[#result + 1] = { cur, count } + end + for i, name in ipairs(result) do + if result[i][2] > 1 then + result[i] = result[i][1] .. " x" .. result[i][2] + else + result[i] = result[i][1] + end + end + return result +end + +function explorer.fancy_join(l, indent, width, sep, initial_indent) + -- TODO: reflow around spaces? + if #l == 0 then + return "" + end + local lines = {} + local cur_line = string.rep(" ", indent) + for i, s in ipairs(l) do + local full_s = s + if (i ~= #l) then + full_s = full_s .. sep + end + if #cur_line + #full_s > width and i ~= 1 then + lines[#lines + 1] = cur_line + cur_line = string.rep(" ", indent) + end + cur_line = cur_line .. full_s + end + lines[#lines + 1] = cur_line + if not initial_indent and #lines > 0 and indent > 0 then + lines[1] = string.sub(lines[1], indent + 1, #lines[1]) + end + return table.concat(lines, "\n") +end + +------------------------------ +-- code for looking at items + +function explorer.arts_only(item) + return item.artefact +end + +function explorer.item_ignore_boring(item) + -- TODO: + -- show gold totals? + -- missiles - early on? + -- unenchanted weapons/armour - early on? + if item.is_useless then + return false + elseif item.base_type == "gold" + or item.base_type == "missile" + or item.base_type == "food" then + return false + elseif (item.base_type == "weapon" or item.base_type == "armour") + and item.pluses() <= 0 and not item.branded then + return false + end + return true +end + +explorer.item_notable = explorer.item_ignore_boring + +function explorer.catalog_items() + wiz.identify_all_items() + local gxm, gym = dgn.max_bounds() + local notable = {} + for p in iter.rect_iterator(dgn.point(1,1), dgn.point(gxm-2, gym-2)) do + local stack = dgn.items_at(p.x, p.y) + if #stack > 0 then + for i, item in ipairs(stack) do + if explorer.item_notable(item) then + notable[#notable + 1] = item.name() + end + end + end + -- TODO: shops + end + return notable +end + +------------------------------ +-- code for looking at features + +explorer.hell_branches = util.set{ "Geh", "Coc", "Dis", "Tar" } + +function explorer.in_hell() + return explorer.hell_branches[you.branch()] +end + +function explorer.feat_interesting(feat_name) + -- most features are pretty boring... + if string.find(feat_name, "altar_") == 1 then + return true + elseif string.find(feat_name, "enter_") == 1 then -- could be more selective + if explorer.in_hell() then + return feat_name ~= "enter_hell" + else + return true + end + elseif feat_name == "transporter" or string.find(feat_name, "runed_") then + return true + end + return false +end + +function explorer.catalog_features() + you.enter_wizard_mode() -- necessary so that magic mapping behaves + -- correctly. this is implied by you.save = false, + -- so it shouldn't affect other tests in actual + -- test mode... + -- TODO: this could be a lot more efficient in skipping things like walls + wiz.map_level() -- abyss will break this call... + local gxm, gym = dgn.max_bounds() + local notable = {} + for p in iter.rect_iterator(dgn.point(1,1), dgn.point(gxm-2, gym-2)) do + local feat = dgn.grid(p.x, p.y) + --crawl.stderr(dgn.feature_desc(feat)) + if explorer.feat_interesting(dgn.feature_name(feat)) then + notable[#notable + 1] = dgn.feature_desc_at(p.x, p.y, "A") + end + end + return notable +end + +------------------------------ +-- code for looking at monsters + +-- fairly subjective, some of these should probably be relative to depth +explorer.always_interesting_mons = util.set{ + "ancient lich", + "orb of fire", + "greater mummy", + "Hell Sentinel", + "Ice Fiend", + "Brimstone Fiend", + "Tzitzimitl", + "shard shrike", + "caustic shrike", + "iron giant", + "juggernaut", + "Killer Klown", + "Orb Guardian", + "curse toe", +} + +function explorer.mons_ignore_boring(mons) + return (mons.unique + or explorer.always_interesting_mons[mons.name] + or mons.type_name == "player ghost" + or mons.type_name == "pandemonium lord") +end + +explorer.mons_notable = explorer.mons_ignore_boring +--local mons_notable = function (m) return false end + +function explorer.mons_always_native(m, mi) + return (mi:is_unique() + or m.type_name == "player ghost" + or mi:is_firewood()) +end + +function explorer.rare_ood(mi) + local depth = mi:avg_local_depth() + -- TODO: really, probability can't be interpreted without some sense of what + -- the overall distribution for the branch is, so this is fairly heuristic + local prob = mi:avg_local_prob() + local ood_threshold = math.max(2, dgn.br_depth() / 3) + return depth > you.depth() + ood_threshold and prob < 2 +end + +function explorer.feat_in_set(s) + return function (f) if s[f] then return f else return nil end end +end + +--explorer.mons_feat_filter = explorer.feat_in_set(util.set({ "OOD" })) +explorer.mons_feat_filter = nil + +function explorer.describe_mons(mons) + local mi = mons.get_info() + -- TODO: weird distribution of labor between mons and moninfo, can this be + -- cleaned up? + -- TODO: does it make sense to use the same item notability function here? + local feats = util.map(function (i) return i.name() end, + util.filter(explorer.item_notable, mons.get_inventory())) + local force_notable = false + if explorer.mons_feat_filter then + feats = util.map(explorer.mons_feat_filter, feats) -- TODO don't brute force this + end + if mons.type_name == "dancing weapon" and #feats > 0 then + -- don't repeat the dancing weapon's item, but if the item_notable check + -- has deemed the item notable, make sure to show it. + feats = { } + force_notable = true + end + + -- may or may not be useful -- OOD is an indicator of builder choices, not + -- intrinsic monster quality, and it is possible for monsters to be chosen + -- as OOD that are within range, e.g. you can sometimes get the same monster + -- generating as OOD and not OOD. + -- TODO: maybe worth rethinking what counts as OOD? might be something like, + -- average spawn depth for monster in branch is greater than depth + 5. + -- if mons.has_prop("mons_is_ood") then + -- feats[#feats + 1] = "builder OOD" + -- end + if explorer.rare_ood(mi) then + feats[#feats + 1] = "OOD" + end + if not mons.in_local_population and not explorer.mons_always_native(mons, mi) then + -- this is a different sense of "native" than used internally to crawl, + -- in that it includes anything that would normally generate in a + -- branch. The internal sense is just supposed to be about which + -- monsters "live" in a particular branch, which is covered as well. + feats[#feats + 1] = "non-native" + end + if explorer.mons_feat_filter then + feats = util.map(explorer.mons_feat_filter, feats) + end + local feat_string = "" + if #feats > 0 then + feat_string = " (" .. table.concat(feats, ", ") .. ")" + end + + local name_string = "bug" + + if mons.type_name == "player ghost" then + name_string = mons.type_name + else + name_string = mons.name + end + if (force_notable or explorer.mons_notable(mons) or #feats > 0) then + return name_string .. feat_string + else + return nil + end +end + +function explorer.get_all_monsters() + local gxm, gym = dgn.max_bounds() + local mons_list = {} + for p in iter.rect_iterator(dgn.point(1,1), dgn.point(gxm-2, gym-2)) do + local mons = dgn.mons_at(p.x, p.y) + if mons then + mons_list[#mons_list + 1] = mons + end + end + return mons_list +end + +function explorer.catalog_monsters() + wiz.identify_all_items() + return util.map(explorer.describe_mons, explorer.get_all_monsters()) +end + +------------------------------ +-- code for looking at vaults + +function explorer.catalog_vaults() + -- this list has already been joined into a string, split it + -- TODO: just pass the list directly to lua... + local vaults = debug.vault_names() + first_split = crawl.split(vaults, " and ") + if #first_split < 2 then + return first_split + end + second_split = crawl.split(first_split[1], ", ") + second_split[#second_split + 1] = first_split[2] + return second_split +end + +------------------------------ +-- general code for building highlight descriptions + +explorer.catalog_funs = {vaults=explorer.catalog_vaults, + items=explorer.catalog_items, + monsters=explorer.catalog_monsters, + features=explorer.catalog_features} + +explorer.catalog_names = {vaults = " Vaults: ", + items = " Items: ", + monsters = " Monsters: ", + features = " Features: "} + +function explorer.make_highlight(h, key, hide_empty) + if not h[key] then + return "" + end + local name = explorer.catalog_names[key] + local l = h[key] + if key ~= "vaults" then + l = explorer.collapse_dups(l) + end + s = explorer.fancy_join(l, #name, 80, ", ") + if (#s == 0 and hide_empty) then + return "" + end + return name .. s +end + +function explorer.catalog_current_place(lvl, to_show, hide_empty) + -- TODO: shop items + highlights = {} + for _, cat in ipairs(to_show) do + if explorer.catalog_funs[cat] == nil then + crawl.stderr("Unknown seed explorer category '" .. cat .. "'!") + else + highlights[cat] = explorer.catalog_funs[cat]() + end + end + if not explorer.quiet then + h_l = { } + for _, cat in ipairs(to_show) do + h_l[#h_l+1] = explorer.make_highlight(highlights, cat, hide_empty) + end + h_l = util.filter(function (a) return #a > 0 end, h_l) + if #h_l > 0 or not hide_empty then + out(lvl .. " highlights:") + for _, h in ipairs(h_l) do + out(h) + end + end + end + return highlights +end + +-- a bit redundant with mapstat? +function explorer.catalog_dungeon(max_depth, to_show) + local result = {} + dgn.reset_level() + debug.flush_map_memory() + debug.dungeon_setup() + for i,lvl in ipairs(explorer.generation_order) do + if i > max_depth then break end + if (dgn.br_exists(string.match(lvl, "[^:]+"))) then + debug.goto_place(lvl) + debug.generate_level() + result[lvl] = explorer.catalog_current_place(lvl, to_show, true) + end + end + return result +end + +function explorer.catalog_seed(seed, depth, cats, describe_cat) + seed_used = debug.reset_rng(seed) + if describe_cat then + out(describe_cat(seed)) + else + out("Catalog for seed " .. seed .. + " (categories " .. table.concat(cats, ", ") .. "):") + end + return explorer.catalog_dungeon(depth, cats) +end + +explorer.available_categories = { "vaults", "items", "features", "monsters" } + + +-- seeds is an array of seeds. If you pass numbers in with this, keep in mind +-- that the max int limit is rather complicated and less than 64bits, because +-- these are numbers behind the scenes. This code will accept strings of digits +-- instead, which is always safe. +function explorer.catalog_seeds(seeds, depth, cats, describe_cat) + if depth == nil then depth = #explorer.generation_order end + if cats == nil then + cats = util.set(explorer.available_cats) + end + for _, i in ipairs(seeds) do + if _ > 1 then out("") end -- generates a newline for stderr output + explorer.catalog_seed(i, depth, cats, describe_cat) + end +end + +function explorer.catalog_arts(seeds, depth) + explorer.item_notable = arts_only + local run1 = explorer.catalog_dungeon(seeds, depth, { "items" }, + function(seed) out("Artefact catalog for seed " .. seed .. ":") end) + explorer.item_notable = ignore_boring +end diff --git a/crawl-ref/source/test/seed_explorer.lua b/crawl-ref/source/test/seed_explorer.lua index 742d44948858..855c09b8a687 100644 --- a/crawl-ref/source/test/seed_explorer.lua +++ b/crawl-ref/source/test/seed_explorer.lua @@ -2,9 +2,7 @@ -- out a few levels from some early seeds in detail, but fairly configurable. -- TODO: maybe move some of the core code out into dat/dlua? -you.enter_wizard_mode() -- necessary so that magic mapping behaves correctly. - -- this is implied by you.save = false, so it shouldn't - -- affect other tests in actual test mode... +crawl_require('dlua/explorer.lua') -- to use a >32bit seed, you will need to use a string here. If you use a -- string, `fixed_seed` is maxed at 1. @@ -12,411 +10,11 @@ local starting_seed = 1 -- fixed seed to start with, number or string local fixed_seeds = 5 -- how many fixed seeds to run? Can be 0. local rand_seeds = 0 -- how many random seeds to run --- matches pregeneration order -local generation_order = { - "D:1", - "D:2", "D:3", "D:4", "D:5", "D:6", "D:7", "D:8", "D:9", - "D:10", "D:11", "D:12", "D:13", "D:14", "D:15", - "Temple", - "Lair:1", "Lair:2", "Lair:3", "Lair:4", "Lair:5", "Lair:6", - "Orc:1", "Orc:2", - "Spider:1", "Spider:2", "Spider:3", "Spider:4", - "Snake:1", "Snake:2", "Snake:3", "Snake:4", - "Shoals:1", "Shoals:2", "Shoals:3", "Shoals:4", - "Swamp:1", "Swamp:2", "Swamp:3", "Swamp:4", - "Vaults:1", "Vaults:2", "Vaults:3", "Vaults:4", "Vaults:5", - "Crypt:1", "Crypt:2", "Crypt:3", - "Depths:1", "Depths:2", "Depths:3", "Depths:4", "Depths:5", - "Hell", - "Elf:1", "Elf:2", "Elf:3", - "Zot:1", "Zot:2", "Zot:3", "Zot:4", "Zot:5", - "Slime:1", "Slime:2", "Slime:3", "Slime:4", "Slime:5", - "Tomb:1", "Tomb:2", "Tomb:3", - "Tar:1", "Tar:2", "Tar:3", "Tar:4", "Tar:5", "Tar:6", "Tar:7", - "Coc:1", "Coc:2", "Coc:3", "Coc:4", "Coc:5", "Coc:6", "Coc:7", - "Dis:1", "Dis:2", "Dis:3", "Dis:4", "Dis:5", "Dis:6", "Dis:7", - } -- this variable determines how deep in the generation order to go ---local max_depth = #generation_order +--local max_depth = #explorer.generation_order local max_depth = 5 ------------------------------- --- some generic list/string manipulation code - -function collapse_dups(l) - local result = {} - table.sort(l) - local cur = "" - local count = 0 - for i, name in ipairs(l) do - if name == cur then - count = count + 1 - else - if (cur ~= "") then - result[#result + 1] = { cur, count } - end - cur = name - count = 1 - end - end - if (cur ~= "") then - result[#result + 1] = { cur, count } - end - for i, name in ipairs(result) do - if result[i][2] > 1 then - result[i] = result[i][1] .. " x" .. result[i][2] - else - result[i] = result[i][1] - end - end - return result -end - -function fancy_join(l, indent, width, sep, initial_indent) - -- TODO: reflow around spaces? - if #l == 0 then - return "" - end - local lines = {} - local cur_line = string.rep(" ", indent) - for i, s in ipairs(l) do - local full_s = s - if (i ~= #l) then - full_s = full_s .. sep - end - if #cur_line + #full_s > width and i ~= 1 then - lines[#lines + 1] = cur_line - cur_line = string.rep(" ", indent) - end - cur_line = cur_line .. full_s - end - lines[#lines + 1] = cur_line - if not initial_indent and #lines > 0 and indent > 0 then - lines[1] = string.sub(lines[1], indent + 1, #lines[1]) - end - return table.concat(lines, "\n") -end - ------------------------------- --- code for looking at items - -function arts_only(item) - return item.artefact -end - -function item_ignore_boring(item) - -- TODO: - -- show gold totals? - -- missiles - early on? - -- unenchanted weapons/armour - early on? - if item.is_useless then - return false - elseif item.base_type == "gold" - or item.base_type == "missile" - or item.base_type == "food" then - return false - elseif (item.base_type == "weapon" or item.base_type == "armour") - and item.pluses() <= 0 and not item.branded then - return false - end - return true -end - -local item_notable = item_ignore_boring - -function catalog_items() - wiz.identify_all_items() - local gxm, gym = dgn.max_bounds() - local notable = {} - for p in iter.rect_iterator(dgn.point(1,1), dgn.point(gxm-2, gym-2)) do - local stack = dgn.items_at(p.x, p.y) - if #stack > 0 then - for i, item in ipairs(stack) do - if item_notable(item) then - notable[#notable + 1] = item.name() - end - end - end - -- TODO: shops - end - return notable -end - ------------------------------- --- code for looking at features - -local hell_branches = util.set{ "Geh", "Coc", "Dis", "Tar" } - -function in_hell() - return hell_branches[you.branch()] -end - -function feat_interesting(feat_name) - -- most features are pretty boring... - if string.find(feat_name, "altar_") == 1 then - return true - elseif string.find(feat_name, "enter_") == 1 then -- could be more selective - if in_hell() then - return feat_name ~= "enter_hell" - else - return true - end - elseif feat_name == "transporter" or string.find(feat_name, "runed_") then - return true - end - return false -end - -function catalog_features() - -- TODO: this could be a lot more efficient in skipping things like walls - wiz.map_level() -- abyss will break this call... - local gxm, gym = dgn.max_bounds() - local notable = {} - for p in iter.rect_iterator(dgn.point(1,1), dgn.point(gxm-2, gym-2)) do - local feat = dgn.grid(p.x, p.y) - --crawl.stderr(dgn.feature_desc(feat)) - if feat_interesting(dgn.feature_name(feat)) then - notable[#notable + 1] = dgn.feature_desc_at(p.x, p.y, "A") - end - end - return notable -end - ------------------------------- --- code for looking at monsters - --- fairly subjective, some of these should probably be relative to depth -local always_interesting_mons = util.set{ - "ancient lich", - "orb of fire", - "greater mummy", - "Hell Sentinel", - "Ice Fiend", - "Brimstone Fiend", - "Tzitzimitl", - "shard shrike", - "caustic shrike", - "iron giant", - "juggernaut", - "Killer Klown", - "Orb Guardian", - "curse toe", -} - -function mons_ignore_boring(mons) - return (mons.unique - or always_interesting_mons[mons.name] - or mons.type_name == "player ghost" - or mons.type_name == "pandemonium lord") -end - -local mons_notable = mons_ignore_boring ---local mons_notable = function (m) return false end - -function mons_always_native(m, mi) - return (mi:is_unique() - or m.type_name == "player ghost" - or mi:is_firewood()) -end - -function rare_ood(mi) - local depth = mi:avg_local_depth() - -- TODO: really, probability can't be interpreted without some sense of what - -- the overall distribution for the branch is, so this is fairly heuristic - local prob = mi:avg_local_prob() - local ood_threshold = math.max(2, dgn.br_depth() / 3) - return depth > you.depth() + ood_threshold and prob < 2 -end - -function feat_in_set(s) - return function (f) if s[f] then return f else return nil end end -end - ---mons_feat_filter = feat_in_set(util.set({ "OOD" })) -mons_feat_filter = nil - -function describe_mons(mons) - local mi = mons.get_info() - -- TODO: weird distribution of labor between mons and moninfo, can this be - -- cleaned up? - -- TODO: does it make sense to use the same item notability function here? - local feats = util.map(function (i) return i.name() end, - util.filter(item_notable, mons.get_inventory())) - local force_notable = false - if mons_feat_filter then - feats = util.map(mons_feat_filter, feats) -- TODO don't brute force this - end - if mons.type_name == "dancing weapon" and #feats > 0 then - -- don't repeat the dancing weapon's item, but if the item_notable check - -- has deemed the item notable, make sure to show it. - feats = { } - force_notable = true - end - - -- may or may not be useful -- OOD is an indicator of builder choices, not - -- intrinsic monster quality, and it is possible for monsters to be chosen - -- as OOD that are within range, e.g. you can sometimes get the same monster - -- generating as OOD and not OOD. - -- TODO: maybe worth rethinking what counts as OOD? might be something like, - -- average spawn depth for monster in branch is greater than depth + 5. - -- if mons.has_prop("mons_is_ood") then - -- feats[#feats + 1] = "builder OOD" - -- end - if rare_ood(mi) then - feats[#feats + 1] = "OOD" - end - if not mons.in_local_population and not mons_always_native(mons, mi) then - -- this is a different sense of "native" than used internally to crawl, - -- in that it includes anything that would normally generate in a - -- branch. The internal sense is just supposed to be about which - -- monsters "live" in a particular branch, which is covered as well. - feats[#feats + 1] = "non-native" - end - if mons_feat_filter then - feats = util.map(mons_feat_filter, feats) - end - local feat_string = "" - if #feats > 0 then - feat_string = " (" .. table.concat(feats, ", ") .. ")" - end - - local name_string = "bug" - - if mons.type_name == "player ghost" then - name_string = mons.type_name - else - name_string = mons.name - end - if (force_notable or mons_notable(mons) or #feats > 0) then - return name_string .. feat_string - else - return nil - end -end - -function get_all_monsters() - local gxm, gym = dgn.max_bounds() - local mons_list = {} - for p in iter.rect_iterator(dgn.point(1,1), dgn.point(gxm-2, gym-2)) do - local mons = dgn.mons_at(p.x, p.y) - if mons then - mons_list[#mons_list + 1] = mons - end - end - return mons_list -end - -function catalog_monsters() - wiz.identify_all_items() - return util.map(describe_mons, get_all_monsters()) -end - -function catalog_vaults() - -- TODO: just pass the list directly to lua... - local vaults = debug.vault_names() - first_split = crawl.split(vaults, " and ") - if #first_split < 2 then - return first_split - end - second_split = crawl.split(first_split[1], ", ") - second_split[#second_split + 1] = first_split[2] - return second_split -end - -function make_highlight(h, key, name, to_show, hide_empty) - if not h[key] or not to_show[key] then - return "" - end - local l = h[key] - if key ~= "vaults" then - l = collapse_dups(l) - end - s = fancy_join(l, #name, 80, ", ") - if (#s == 0 and hide_empty) then - return "" - end - return name .. s -end - -function catalog_current_place(lvl, to_show, hide_empty) - -- TODO: features (mainly just altars), shops - highlights = {} - highlights["vaults"] = catalog_vaults() - highlights["items"] = catalog_items() - highlights["monsters"] = catalog_monsters() - highlights["features"] = catalog_features() - h_l = { } - h_l[#h_l+1] = make_highlight(highlights, "vaults", " Vaults: ", to_show, hide_empty) - h_l[#h_l+1] = make_highlight(highlights, "monsters", " Monsters: ", to_show, hide_empty) - h_l[#h_l+1] = make_highlight(highlights, "items", " Items: ", to_show, hide_empty) - h_l[#h_l+1] = make_highlight(highlights, "features", " Features: ", to_show, hide_empty) - h_l = util.filter(function (a) return #a > 0 end, h_l) - if #h_l > 0 or not hide_empty then - crawl.stderr(lvl .. " highlights:") - for _, h in ipairs(h_l) do - crawl.stderr(h) - end - end - return highlights -end - --- a bit redundant with mapstat? -function catalog_dungeon(level_order, to_show) - local result = {} - dgn.reset_level() - debug.flush_map_memory() - debug.dungeon_setup() - for i,lvl in ipairs(level_order) do - if i > max_depth then break end - if (dgn.br_exists(string.match(lvl, "[^:]+"))) then - debug.goto_place(lvl) - debug.generate_level() - result[lvl] = catalog_current_place(lvl, to_show, true) - end - end - return result -end - -function seed_items(seed) - seed_used = debug.reset_rng(seed) - crawl.stderr("Item catalog for seed " .. seed .. ":") - local run1 = catalog_dungeon(generation_order, util.set{ "items" }) -end - -function seed_arts(seed) - seed_used = debug.reset_rng(seed) - crawl.stderr("Artefact catalog for seed " .. seed .. ":") - item_notable = arts_only - local run1 = catalog_dungeon(generation_order, util.set{ "items" }) - item_notable = ignore_boring -end - -function seed_mons(seed) - seed_used = debug.reset_rng(seed) - crawl.stderr("Monster catalog for seed " .. seed .. ":") - local run1 = catalog_dungeon(generation_order, util.set{ "monsters" }) -end - -function seed_feats(seed) - seed_used = debug.reset_rng(seed) - crawl.stderr("Dungeon feature catalog for seed " .. seed .. ":") - local run1 = catalog_dungeon(generation_order, util.set{ "features" }) -end - -function seed_full_catalog(seed) - seed_used = debug.reset_rng(seed) - crawl.stderr("Catalog for seed " .. seed .. ":") - local run1 = catalog_dungeon(generation_order, util.set{ "vaults", "items", "features", "monsters" }) -end - -function catalog_seeds(seeds, cat_fun) - for _, i in ipairs(seeds) do - if _ > 1 then crawl.stderr("") end - cat_fun(i) - end -end - if fixed_seeds > 0 then local seed_seq = { starting_seed } @@ -425,7 +23,7 @@ if fixed_seeds > 0 then seed_seq[#seed_seq + 1] = i end end - catalog_seeds(seed_seq, seed_full_catalog) + explorer.catalog_seeds(seed_seq, max_depth, explorer.available_categories) end if rand_seeds > 0 then @@ -438,5 +36,5 @@ if rand_seeds > 0 then rand_seq[#rand_seq + 1] = rand_seed end crawl.stderr("Exploring " .. rand_seeds .. " random seed(s).") - catalog_seeds(rand_seq, seed_full_catalog) + explorer.catalog_seeds(rand_seq, max_depth, explorer.available_categories) end From 8afd68e6110fd1c0252a2074de00dcca0f2a2237 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 3 Jun 2019 12:22:44 -0400 Subject: [PATCH 384/864] Refactor the seed explorer to do only one dungeon pass instead of iterating through the dungeon for each category. This turns out to only get a negligable speedup (about 2s for a pass through the entire generation depth) but the code is still probably cleaner this way. --- crawl-ref/source/dat/dlua/explorer.lua | 96 ++++++++++++++++---------- 1 file changed, 60 insertions(+), 36 deletions(-) diff --git a/crawl-ref/source/dat/dlua/explorer.lua b/crawl-ref/source/dat/dlua/explorer.lua index d0f6f6a48499..3e230849e7b0 100644 --- a/crawl-ref/source/dat/dlua/explorer.lua +++ b/crawl-ref/source/dat/dlua/explorer.lua @@ -135,22 +135,19 @@ end explorer.item_notable = explorer.item_ignore_boring -function explorer.catalog_items() +function explorer.catalog_items_setup() wiz.identify_all_items() - local gxm, gym = dgn.max_bounds() - local notable = {} - for p in iter.rect_iterator(dgn.point(1,1), dgn.point(gxm-2, gym-2)) do - local stack = dgn.items_at(p.x, p.y) - if #stack > 0 then - for i, item in ipairs(stack) do - if explorer.item_notable(item) then - notable[#notable + 1] = item.name() - end +end + +function explorer.catalog_items(pos, notable) + local stack = dgn.items_at(pos.x, pos.y) + if #stack > 0 then + for i, item in ipairs(stack) do + if explorer.item_notable(item) then + notable[#notable + 1] = item.name() end end - -- TODO: shops end - return notable end ------------------------------ @@ -178,23 +175,19 @@ function explorer.feat_interesting(feat_name) return false end -function explorer.catalog_features() +function explorer.catalog_features_setup() you.enter_wizard_mode() -- necessary so that magic mapping behaves -- correctly. this is implied by you.save = false, -- so it shouldn't affect other tests in actual -- test mode... - -- TODO: this could be a lot more efficient in skipping things like walls wiz.map_level() -- abyss will break this call... - local gxm, gym = dgn.max_bounds() - local notable = {} - for p in iter.rect_iterator(dgn.point(1,1), dgn.point(gxm-2, gym-2)) do - local feat = dgn.grid(p.x, p.y) - --crawl.stderr(dgn.feature_desc(feat)) - if explorer.feat_interesting(dgn.feature_name(feat)) then - notable[#notable + 1] = dgn.feature_desc_at(p.x, p.y, "A") - end +end + +function explorer.catalog_features(pos, notable) + local feat = dgn.grid(pos.x, pos.y) + if explorer.feat_interesting(dgn.feature_name(feat)) then + notable[#notable + 1] = dgn.feature_desc_at(pos.x, pos.y, "A") end - return notable end ------------------------------ @@ -321,9 +314,15 @@ function explorer.get_all_monsters() return mons_list end -function explorer.catalog_monsters() +function explorer.catalog_monsters_setup() wiz.identify_all_items() - return util.map(explorer.describe_mons, explorer.get_all_monsters()) +end + +function explorer.catalog_monsters(pos, notable) + local mons = dgn.mons_at(pos.x, pos.y) + if mons then + notable[#notable + 1] = explorer.describe_mons(mons) + end end ------------------------------ @@ -345,15 +344,20 @@ end ------------------------------ -- general code for building highlight descriptions -explorer.catalog_funs = {vaults=explorer.catalog_vaults, - items=explorer.catalog_items, - monsters=explorer.catalog_monsters, - features=explorer.catalog_features} +-- could do this by having each category register itself... +explorer.catalog_funs = {vaults = explorer.catalog_vaults, + items = explorer.catalog_items_setup, + monsters = explorer.catalog_monsters_setup, + features = explorer.catalog_features_setup} -explorer.catalog_names = {vaults = " Vaults: ", - items = " Items: ", - monsters = " Monsters: ", - features = " Features: "} +explorer.catalog_pos_funs = {items = explorer.catalog_items, + monsters = explorer.catalog_monsters, + features = explorer.catalog_features} + +explorer.catalog_names = {vaults = " Vaults: ", + items = " Items: ", + monsters = " Monsters: ", + features = " Features: "} function explorer.make_highlight(h, key, hide_empty) if not h[key] then @@ -371,16 +375,36 @@ function explorer.make_highlight(h, key, hide_empty) return name .. s end +function explorer.catalog_all_positions(cats, highlights) + for _, c in ipairs(cats) do + if highlights[c] == nil then highlights[c] = { } end + end + local gxm, gym = dgn.max_bounds() + for p in iter.rect_iterator(dgn.point(1,1), dgn.point(gxm-2, gym-2)) do + for _,c in ipairs(cats) do + if explorer.catalog_pos_funs[c] ~= nil then + explorer.catalog_pos_funs[c](p, highlights[c]) + end + end + end + for _, c in ipairs(cats) do + if #highlights[c] == 0 then highlights[c] = nil end + end +end + function explorer.catalog_current_place(lvl, to_show, hide_empty) -- TODO: shop items highlights = {} + -- setup functions and anything that doesn't require looking at positions for _, cat in ipairs(to_show) do - if explorer.catalog_funs[cat] == nil then - crawl.stderr("Unknown seed explorer category '" .. cat .. "'!") - else + if explorer.catalog_funs[cat] ~= nil then highlights[cat] = explorer.catalog_funs[cat]() end end + -- explorer categories that collect information from map positions + explorer.catalog_all_positions(to_show, highlights) + + -- output if not explorer.quiet then h_l = { } for _, cat in ipairs(to_show) do From 6ad002bb795255f5e31fe3574e95d875bdac92cb Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 3 Jun 2019 13:32:29 -0400 Subject: [PATCH 385/864] Refactor the vault catalog test to use seed explorer code The comparison part is still specialized (and maybe could be generalized too) but otherwise the code for building the vault catalog is essentially the same as seed explorer code. --- crawl-ref/source/dat/dlua/explorer.lua | 41 ++++++--- crawl-ref/source/test/vault_catalog.lua | 116 ++++++++++-------------- 2 files changed, 74 insertions(+), 83 deletions(-) diff --git a/crawl-ref/source/dat/dlua/explorer.lua b/crawl-ref/source/dat/dlua/explorer.lua index 3e230849e7b0..7bcccb2c9ec1 100644 --- a/crawl-ref/source/dat/dlua/explorer.lua +++ b/crawl-ref/source/dat/dlua/explorer.lua @@ -341,23 +341,29 @@ function explorer.catalog_vaults() return second_split end +function explorer.catalog_vaults_raw() + return { debug.vault_names() } +end + ------------------------------ -- general code for building highlight descriptions -- could do this by having each category register itself... -explorer.catalog_funs = {vaults = explorer.catalog_vaults, - items = explorer.catalog_items_setup, - monsters = explorer.catalog_monsters_setup, - features = explorer.catalog_features_setup} - -explorer.catalog_pos_funs = {items = explorer.catalog_items, - monsters = explorer.catalog_monsters, - features = explorer.catalog_features} - -explorer.catalog_names = {vaults = " Vaults: ", - items = " Items: ", - monsters = " Monsters: ", - features = " Features: "} +explorer.catalog_funs = {vaults = explorer.catalog_vaults, + vaults_raw= explorer.catalog_vaults_raw, + items = explorer.catalog_items_setup, + monsters = explorer.catalog_monsters_setup, + features = explorer.catalog_features_setup} + +explorer.catalog_pos_funs = {items = explorer.catalog_items, + monsters = explorer.catalog_monsters, + features = explorer.catalog_features} + +explorer.catalog_names = {vaults = " Vaults: ", + vaults_raw= " Vaults: ", + items = " Items: ", + monsters = " Monsters: ", + features = " Features: "} function explorer.make_highlight(h, key, hide_empty) if not h[key] then @@ -376,9 +382,16 @@ function explorer.make_highlight(h, key, hide_empty) end function explorer.catalog_all_positions(cats, highlights) + funs = { } for _, c in ipairs(cats) do - if highlights[c] == nil then highlights[c] = { } end + if explorer.catalog_pos_funs[c] ~= nil then + if highlights[c] == nil then highlights[c] = { } end + funs[#funs + 1] = explorer.catalog_pos_funs[c] + end end + -- don't bother if there are no positional funs to run + if #funs == 0 then return end + local gxm, gym = dgn.max_bounds() for p in iter.rect_iterator(dgn.point(1,1), dgn.point(gxm-2, gym-2)) do for _,c in ipairs(cats) do diff --git a/crawl-ref/source/test/vault_catalog.lua b/crawl-ref/source/test/vault_catalog.lua index a9503bc56764..4769f5ac1baa 100644 --- a/crawl-ref/source/test/vault_catalog.lua +++ b/crawl-ref/source/test/vault_catalog.lua @@ -9,68 +9,35 @@ -- but if you are expecting deterministic test behavior, take that into -- account. +crawl_require('dlua/explorer.lua') + local starting_seed = 1 -- fixed seed to start with local fixed_seeds = 1 -- how many fixed seeds to run? local per_seed_iters = 1 -- how many stability tests to run per seed local rand_seeds = 1 -- how many random seeds to run --- matches pregeneration order -local generation_order = { - "D:1", - "D:2", "D:3", "D:4", "D:5", "D:6", "D:7", "D:8", "D:9", - "D:10", "D:11", "D:12", "D:13", "D:14", "D:15", - "Temple", - "Lair:1", "Lair:2", "Lair:3", "Lair:4", "Lair:5", "Lair:6", - "Orc:1", "Orc:2", - "Spider:1", "Spider:2", "Spider:3", "Spider:4", - "Snake:1", "Snake:2", "Snake:3", "Snake:4", - "Shoals:1", "Shoals:2", "Shoals:3", "Shoals:4", - "Swamp:1", "Swamp:2", "Swamp:3", "Swamp:4", - "Vaults:1", "Vaults:2", "Vaults:3", "Vaults:4", "Vaults:5", - "Crypt:1", "Crypt:2", "Crypt:3", - "Depths:1", "Depths:2", "Depths:3", "Depths:4", "Depths:5", - "Hell", - "Elf:1", "Elf:2", "Elf:3", - "Zot:1", "Zot:2", "Zot:3", "Zot:4", "Zot:5", - "Slime:1", "Slime:2", "Slime:3", "Slime:4", "Slime:5", - "Tomb:1", "Tomb:2", "Tomb:3", - } - -- pregen continues: tartarus, cocytus, dis, geh - --- want to exercise these a bit -local generation_order_extended = { - "D:1", - "Tar:1", "Tar:2", "Tar:3", "Tar:4", "Tar:5", "Tar:6", "Tar:7", - "Coc:1", "Coc:2", "Coc:3", "Coc:4", "Coc:5", "Coc:6", "Coc:7", - "Dis:1", "Dis:2", "Dis:3", "Dis:4", "Dis:5", "Dis:6", "Dis:7", - "Pan", "Pan", "Pan", "Pan", "Pan", "Pan", "Pan" -} +local max_depth = #explorer.generation_order --- a bit redundant with mapstat? but simpler... -function catalog_dungeon_vaults(level_order, silent) - local result = {} - dgn.reset_level() - debug.flush_map_memory() - debug.dungeon_setup() - for i,lvl in ipairs(level_order) do - if (dgn.br_exists(string.match(lvl, "[^:]+"))) then - debug.goto_place(lvl) - debug.generate_level() - result[lvl] = debug.vault_names() - if (not silent) then - crawl.stderr(lvl .. " vaults are: ") - crawl.stderr(" " .. result[lvl]) - end - end +function catalog_dungeon_vaults(silent) + -- TODO: this doesn't do any pan levels, but the previous version did + local old_quiet = explorer.quiet + explorer.quiet = silent + local catalog = explorer.catalog_dungeon(max_depth, + { "vaults_raw" }) + explorer.quiet = old_quiet + local result = { } + for lvl, cats in pairs(catalog) do + -- eliminate the extra catalog structure we aren't using here + result[lvl] = catalog[lvl]["vaults_raw"][1] end return result end -function compare_catalogs(order, run1, run2, seed) +function compare_catalogs(run1, run2, seed) local diverge = false -- stop at the first divergence by generation order. Everything after that -- is likely to be a mess with very little signal. - for i,lvl in ipairs(order) do + for i,lvl in ipairs(explorer.generation_order) do if run1[lvl] == nil and run2[lvl] ~= nil then crawl.stderr("Run 1 is missing " .. lvl .. "!") elseif run2[lvl] == nil and run1[lvl] ~= nil then @@ -84,14 +51,14 @@ function compare_catalogs(order, run1, run2, seed) end end -function test_seed(seed, iters, order, quiet) +function test_seed(seed, iters, quiet) seed_used = debug.reset_rng(seed) if quiet then crawl.stderr(".") else crawl.stderr("Vault catalog for seed " .. seed .. ":") end - local run1 = catalog_dungeon_vaults(order, quiet) + local run1 = catalog_dungeon_vaults(quiet) if not quiet then crawl.stderr("....now testing vault generation stability for seed " ..seed.. ".") @@ -100,31 +67,42 @@ function test_seed(seed, iters, order, quiet) for i = 1,iters do crawl.stderr(".") debug.reset_rng(seed) - local run2 = catalog_dungeon_vaults(order, true) - compare_catalogs(order, run1, run2, seed) + local run2 = catalog_dungeon_vaults(true) + compare_catalogs(run1, run2, seed) end end -test_seed(starting_seed, per_seed_iters, generation_order, false) --- just do a quick check of hell / pan stability -crawl.stderr("Checking some extended branches for seed " .. starting_seed .. "...") -test_seed(starting_seed, per_seed_iters, generation_order_extended, true) +function test_seed_sequence(seq, iters, quiet, quiet_first_only) + for _,s in ipairs(seq) do + crawl.stderr("Testing seed " .. s .. ".") + test_seed(s, iters, quiet or quiet_first_only and s ~= seq[1]) + end +end -if (type(starting_seed) ~= "string") then - for i=starting_seed + 1, starting_seed + fixed_seeds - 1 do - crawl.stderr("Testing seed " .. i .. ".") - test_seed(i, per_seed_iters, generation_order, true) +if fixed_seeds > 0 then + local seeds_to_test = { starting_seed } + if (type(starting_seed) ~= "string") then + for i=starting_seed + 1, starting_seed + fixed_seeds - 1 do + seeds_to_test[#seeds_to_test + 1] = i + end end + test_seed_sequence(seeds_to_test, per_seed_iters, quiet) end +-- shorten the depth here for the sake of travis: +max_depth = explorer.zot_depth + if rand_seeds > 0 then crawl.stderr("Testing " .. rand_seeds .. " random seed(s).") + local seeds_to_test = { } + for i=1,rand_seeds do + -- intentional use of non-crawl random(). random doesn't seem to accept + -- anything bigger than 32 bits for the range. + math.randomseed(crawl.millis()) + rand_seed = math.random(0x7FFFFFFF) + seeds_to_test[#seeds_to_test + 1] = rand_seed + end + test_seed_sequence(seeds_to_test, per_seed_iters, true) end -for i=1,rand_seeds do - -- intentional use of non-crawl random(). random doesn't seem to accept - -- anything bigger than 32 bits for the range. - math.randomseed(crawl.millis()) - rand_seed = math.random(0x7FFFFFFF) - crawl.stderr("Testing random seed " .. rand_seed .. ".") - test_seed(rand_seed, per_seed_iters, generation_order, true) -end + +debug.reset_rng(1) From d7d9f274c4eced0ba976da1f3acce156187dbd9c Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 3 Jun 2019 15:08:39 -0400 Subject: [PATCH 386/864] Add a script interface to the seed explorer Pretty basic right now, but you can run it with e.g.: util/fake_pty ./crawl -script seed_explorer.lua -seed 1 Supports multiple seeds, which can be random, and lets you pick the depth. In the future I will add more customization to what exactly is shown. This commit also fixes a bug where scripts got doubled command line arguments, and changes script behavior so that crawl only outputs what the script does. (Also a few small cosmetic things.) --- crawl-ref/source/ctest.cc | 16 ++++++++++++---- crawl-ref/source/dat/dlua/explorer.lua | 2 +- crawl-ref/source/initfile.cc | 3 +++ crawl-ref/source/test/seed_explorer.lua | 4 +--- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/crawl-ref/source/ctest.cc b/crawl-ref/source/ctest.cc index f4db4e814011..500e1e3e0b15 100644 --- a/crawl-ref/source/ctest.cc +++ b/crawl-ref/source/ctest.cc @@ -124,7 +124,8 @@ static void run_test(const string &file) return; ++ntests; - fprintf(stderr, "Running test #%d: '%s'.\n", ntests, file.c_str()); + if (!crawl_state.script) + fprintf(stderr, "Running test #%d: '%s'.\n", ntests, file.c_str()); mprf(MSGCH_DIAGNOSTICS, "Running %s %d: %s", activity, ntests, file.c_str()); flush_prev_message(); @@ -153,7 +154,8 @@ static void _run_test(const string &name, void (*func)()) if (!_has_test(name)) return; - fprintf(stderr, "Running test #%d: '%s'.\n", ntests, name.c_str()); + if (!crawl_state.script) + fprintf(stderr, "Running test #%d: '%s'.\n", ntests, name.c_str()); ++ntests; try @@ -219,8 +221,14 @@ void run_tests() fprintf(stderr, "%s error: %s\n", activity, fe.second.c_str()); const int code = failures.empty() ? 0 : 1; - end(code, false, "%d %ss, %d succeeded, %d failed", - ntests, activity, nsuccess, (int)failures.size()); + // scripts are responsible for printing their own errors + if (crawl_state.script && ntests == 1) + end(code, false); + else + { + end(code, false, "%d %ss, %d succeeded, %d failed", + ntests, activity, nsuccess, (int)failures.size()); + } } #endif // DEBUG_TESTS diff --git a/crawl-ref/source/dat/dlua/explorer.lua b/crawl-ref/source/dat/dlua/explorer.lua index 7bcccb2c9ec1..de52f8024637 100644 --- a/crawl-ref/source/dat/dlua/explorer.lua +++ b/crawl-ref/source/dat/dlua/explorer.lua @@ -457,7 +457,7 @@ function explorer.catalog_seed(seed, depth, cats, describe_cat) out(describe_cat(seed)) else out("Catalog for seed " .. seed .. - " (categories " .. table.concat(cats, ", ") .. "):") + " (" .. table.concat(cats, ", ") .. "):") end return explorer.catalog_dungeon(depth, cats) end diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index 627c9fdc89ab..f04728ae4522 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -4797,6 +4797,7 @@ bool parse_args(int argc, char **argv, bool rc_only) case CLO_SCRIPT: crawl_state.test = true; crawl_state.script = true; + crawl_state.script_args.clear(); if (current < argc - 1) { crawl_state.tests_selected = split_string(",", next_arg); @@ -4805,8 +4806,10 @@ bool parse_args(int argc, char **argv, bool rc_only) current = argc; } else + { end(1, false, "-script must specify comma-separated script names"); + } break; case CLO_BUILDDB: diff --git a/crawl-ref/source/test/seed_explorer.lua b/crawl-ref/source/test/seed_explorer.lua index 855c09b8a687..5ddbf744ed3c 100644 --- a/crawl-ref/source/test/seed_explorer.lua +++ b/crawl-ref/source/test/seed_explorer.lua @@ -1,6 +1,4 @@ --- tools for seeing what's in a seed. Currently packaged as a test that prints --- out a few levels from some early seeds in detail, but fairly configurable. --- TODO: maybe move some of the core code out into dat/dlua? +-- test to exercise seed explorer: look at the first 5 levels of 5 seeds. crawl_require('dlua/explorer.lua') From b57f36d6e0b1ca1ef7e37a16cd19ab8fe44bf4b8 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 3 Jun 2019 15:12:46 -0400 Subject: [PATCH 387/864] Actually commit the new seed explorer script... Partial repeat of the commit message from d7d9f274c4ec: Pretty basic right now, but you can run it with e.g.: util/fake_pty ./crawl -script seed_explorer.lua -seed 1 Supports multiple seeds, which can be random, and lets you pick the depth. In the future I will add more customization to what exactly is shown. --- crawl-ref/source/scripts/seed_explorer.lua | 79 ++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 crawl-ref/source/scripts/seed_explorer.lua diff --git a/crawl-ref/source/scripts/seed_explorer.lua b/crawl-ref/source/scripts/seed_explorer.lua new file mode 100644 index 000000000000..5dfaa9b16240 --- /dev/null +++ b/crawl-ref/source/scripts/seed_explorer.lua @@ -0,0 +1,79 @@ +-- script interface to the explorer.lua package + +crawl_require('dlua/explorer.lua') + +local basic_usage = [[ +Usage: seed_explorer.lua -seed [ ...] [-depth ] + : either a number, or 'random'. + : either a number, or 'all'. Defaults to 'all'.]] + +function parse_args(args, err_fun) + accum_init = { } + accum_params = { } + cur = nil + for _,a in ipairs(args) do + if string.find(a, '-') == 1 then + cur = a + if accum_params[a] ~= nil then err_fun("Repeated argument '" .. a .."'") end + accum_params[a] = { } + else + if cur == nil then + accum_init[#accum_init + 1] = a + else + accum_params[cur][#accum_params[cur] + 1] = a + end + end + end + return accum_init, accum_params +end + +function one_arg(args, a) + if args[a] == nil or #(args[a]) ~= 1 then return nil end + return args[a][1] +end + +function usage_error(extra) + local err = basic_usage + if extra ~= nil then + err = err .. "\n" .. extra + end + script.usage(err) +end + +local arg_list = crawl.script_args() +local args_init, args = parse_args(arg_list, usage_error) + +if #arg_list == 0 or #args_init ~= 0 or args["-seed"] == nil or #(args["-seed"]) < 1 then + usage_error("No seeds supplied!") +end + +-- let these be converted to numbers on the crawl side +local seed_seq = args["-seed"] + +math.randomseed(crawl.millis()) +for _, seed in ipairs(seed_seq) do + if seed == "random" then + -- intentional use of non-crawl random(). random doesn't seem to accept + -- anything bigger than 32 bits for the range. + seed_seq[_] = math.random(0x7FFFFFFF) + end +end + +local max_depth = nil +if args["-depth"] ~= nil then + max_depth = one_arg(args, "-depth") + if max_depth == "all" then + max_depth = nil + else + max_depth = tonumber(max_depth) + if max_depth == nil then + usage_error("\n must be a number or 'all'!") + end + end +end + +if max_depth == nil then + max_depth = #explorer.generation_order +end + +explorer.catalog_seeds(seed_seq, max_depth, explorer.available_categories) From 65887bbefe61ec2443ec3f85b86c0510fcae2dc7 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 3 Jun 2019 22:12:35 -0400 Subject: [PATCH 388/864] More seed explorer command line options * add some shortcuts for looking at multiple seeds * let categories be specified from the command line * a few special subcases for items and monsters For example, to look at all artefacts on the ground or held by monsters in seed 1, you can now do: util/fake_pty ./crawl -script seed_explorer.lua -seed 1 -cats monsters items -mon-items -artefacts (caveat, shops are still not implemented) --- crawl-ref/source/dat/dlua/explorer.lua | 66 ++++++++-------- crawl-ref/source/scripts/seed_explorer.lua | 87 ++++++++++++++++++++-- 2 files changed, 117 insertions(+), 36 deletions(-) diff --git a/crawl-ref/source/dat/dlua/explorer.lua b/crawl-ref/source/dat/dlua/explorer.lua index de52f8024637..7e282be893a1 100644 --- a/crawl-ref/source/dat/dlua/explorer.lua +++ b/crawl-ref/source/dat/dlua/explorer.lua @@ -133,8 +133,6 @@ function explorer.item_ignore_boring(item) return true end -explorer.item_notable = explorer.item_ignore_boring - function explorer.catalog_items_setup() wiz.identify_all_items() end @@ -193,24 +191,6 @@ end ------------------------------ -- code for looking at monsters --- fairly subjective, some of these should probably be relative to depth -explorer.always_interesting_mons = util.set{ - "ancient lich", - "orb of fire", - "greater mummy", - "Hell Sentinel", - "Ice Fiend", - "Brimstone Fiend", - "Tzitzimitl", - "shard shrike", - "caustic shrike", - "iron giant", - "juggernaut", - "Killer Klown", - "Orb Guardian", - "curse toe", -} - function explorer.mons_ignore_boring(mons) return (mons.unique or explorer.always_interesting_mons[mons.name] @@ -218,9 +198,6 @@ function explorer.mons_ignore_boring(mons) or mons.type_name == "pandemonium lord") end -explorer.mons_notable = explorer.mons_ignore_boring ---local mons_notable = function (m) return false end - function explorer.mons_always_native(m, mi) return (mi:is_unique() or m.type_name == "player ghost" @@ -240,15 +217,12 @@ function explorer.feat_in_set(s) return function (f) if s[f] then return f else return nil end end end ---explorer.mons_feat_filter = explorer.feat_in_set(util.set({ "OOD" })) -explorer.mons_feat_filter = nil - function explorer.describe_mons(mons) local mi = mons.get_info() -- TODO: weird distribution of labor between mons and moninfo, can this be -- cleaned up? -- TODO: does it make sense to use the same item notability function here? - local feats = util.map(function (i) return i.name() end, + local feats = util.map(function (i) return "item:" .. i.name() end, util.filter(explorer.item_notable, mons.get_inventory())) local force_notable = false if explorer.mons_feat_filter then @@ -283,6 +257,10 @@ function explorer.describe_mons(mons) if explorer.mons_feat_filter then feats = util.map(explorer.mons_feat_filter, feats) end + -- the `item:` prefix is really only there for filtering purposes + feats = util.map(function (s) + return s:find("item:") == 1 and s:sub(6) or s + end, feats) local feat_string = "" if #feats > 0 then feat_string = " (" .. table.concat(feats, ", ") .. ")" @@ -365,6 +343,30 @@ explorer.catalog_names = {vaults = " Vaults: ", monsters = " Monsters: ", features = " Features: "} +function explorer.reset_to_defaults() + --explorer.mons_feat_filter = explorer.feat_in_set(util.set({ "OOD" })) + explorer.mons_feat_filter = nil + explorer.mons_notable = explorer.mons_ignore_boring + -- fairly subjective, some of these should probably be relative to depth + explorer.always_interesting_mons = util.set{ + "ancient lich", + "orb of fire", + "greater mummy", + "Hell Sentinel", + "Ice Fiend", + "Brimstone Fiend", + "Tzitzimitl", + "shard shrike", + "caustic shrike", + "iron giant", + "juggernaut", + "Killer Klown", + "Orb Guardian", + "curse toe", + } + explorer.item_notable = explorer.item_ignore_boring +end + function explorer.make_highlight(h, key, hide_empty) if not h[key] then return "" @@ -463,7 +465,9 @@ function explorer.catalog_seed(seed, depth, cats, describe_cat) end explorer.available_categories = { "vaults", "items", "features", "monsters" } - +function explorer.is_category(c) + return util.set(explorer.available_categories)[c] +end -- seeds is an array of seeds. If you pass numbers in with this, keep in mind -- that the max int limit is rather complicated and less than 64bits, because @@ -481,8 +485,10 @@ function explorer.catalog_seeds(seeds, depth, cats, describe_cat) end function explorer.catalog_arts(seeds, depth) - explorer.item_notable = arts_only + explorer.item_notable = explorer.arts_only local run1 = explorer.catalog_dungeon(seeds, depth, { "items" }, function(seed) out("Artefact catalog for seed " .. seed .. ":") end) - explorer.item_notable = ignore_boring + explorer.item_notable = explorer.ignore_boring end + +explorer.reset_to_defaults() diff --git a/crawl-ref/source/scripts/seed_explorer.lua b/crawl-ref/source/scripts/seed_explorer.lua index 5dfaa9b16240..ea37eeb9ab83 100644 --- a/crawl-ref/source/scripts/seed_explorer.lua +++ b/crawl-ref/source/scripts/seed_explorer.lua @@ -2,10 +2,31 @@ crawl_require('dlua/explorer.lua') -local basic_usage = [[ -Usage: seed_explorer.lua -seed [ ...] [-depth ] - : either a number, or 'random'. - : either a number, or 'all'. Defaults to 'all'.]] +-- examples. +-- full catalog for a seed: +-- util/fake_pty ./crawl -script seed_explorer.lua -seed 1 +-- find all artefacts in a seed: +-- util/fake_pty ./crawl -script seed_explorer.lua -seed 1 -cats monsters items -mon-items -artefacts +-- look at D:1 for 10 random seeds: +-- util/fake_pty ./crawl -script seed_explorer.lua -seed random -count 10 -depth 1 + +local basic_usage = [=[ +Usage: seed_explorer.lua -seed ([ ...]|[-count ]) [-depth ] [-cats [: either a number, or 'random'. Random values are 32 bits only. + : a number of times to iterate from . If seed is a number, this + will count up; if it is 'random' it will choose n random seeds. + Note that this converts seed values to doubles in lua, so limits + the range of possible values to some degree. + : either a number, or 'all'. Defaults to 'all'. + : a seed explorer category, drawn from: + {]=] .. + table.concat(explorer.available_categories, ", ") .. [[} + The '-cats' list defaults to all categories. + Category-specific flags (ignored if category is not shown): + -artefacts: show only artefact items (items, monsters). + -mon-items: show only monsters with items (monsters). + -all-mons: show all monsters (monsters). + -all-items: show all items on ground (items).]] function parse_args(args, err_fun) accum_init = { } @@ -44,12 +65,30 @@ local arg_list = crawl.script_args() local args_init, args = parse_args(arg_list, usage_error) if #arg_list == 0 or #args_init ~= 0 or args["-seed"] == nil or #(args["-seed"]) < 1 then - usage_error("No seeds supplied!") + usage_error("\nNo seed(s) supplied!") end -- let these be converted to numbers on the crawl side local seed_seq = args["-seed"] +local count = 1 +if args["-count"] ~= nil then + count = tonumber(one_arg(args, "-count")) + if count == nil then usage_error("\nInvalid argument to -count") end +end + +if count > 1 then + if seed_seq[1] == "random" then + for i = 2, count do seed_seq[#seed_seq+1] = "random" end + else + -- this has the caveats that come with forcing this to be a number... + local n = tonumber(seed_seq[1]) + for i = n+1, n+count-1 do + seed_seq[#seed_seq+1] = i + end + end +end + math.randomseed(crawl.millis()) for _, seed in ipairs(seed_seq) do if seed == "random" then @@ -72,8 +111,44 @@ if args["-depth"] ~= nil then end end +local categories = { } +if args["-cats"] == nil then + categories = explorer.available_categories +else + categories = args["-cats"] +end + +categories = util.filter(explorer.is_category, categories) +if #categories == 0 then + usage_error("\nNo valid categories specified!") +end + if max_depth == nil then max_depth = #explorer.generation_order end -explorer.catalog_seeds(seed_seq, max_depth, explorer.available_categories) +-- TODO: these are kind of ad hoc, maybe some kind of more general interface? +local arts_only = (args["-artefacts"] ~= nil) +local all_items = (args["-all-items"] ~= nil) +if arts_only and all_items then + usage_error("\n-artefacts and -all-items are not compatible.") +end +local mon_items_only = (args["-mon-items"] ~= nil) +local all_mons = (args["-all-mons"] ~= nil) +if mon_items_only and all_mons then + usage_error("\n-mon-items and -all-mons are not compatible.") +end + +explorer.reset_to_defaults() +if arts_only then explorer.item_notable = explorer.arts_only end +if all_items then explorer.item_notable = function (x) return true end end +if mon_items_only then + explorer.mons_notable = function (m) return false end + explorer.mons_feat_filter = function (f) + return f:find("item:") == 1 and f or nil + end +end +if all_mons then explorer.mons_notable = function (x) return true end end + +explorer.catalog_seeds(seed_seq, max_depth, categories) +explorer.reset_to_defaults() From 54394cd99fa5c432558b7d739c41f7a7ea5ea98c Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Sat, 20 Apr 2019 13:29:30 -0400 Subject: [PATCH 389/864] Reduce vampires to two blood states Part 1 of a vampire revision. Vampire's mix of "togglable undead" with "food micromanagement" left a fun concept in an obnoxious place. The presence/absence of blood allowed the player to (tediously) remain in the hunger state of their choice almost all of the time. Since the extremes of the spectrum provided the most impact on playstyle, players tended to focus on one or the other. This commit simplifies vampires to the two extreme states: Alive and Bloodless. The next commits will decouple vampire state from the food clock, replacing state change with a delay, and removing blood drinking and blood potions. --- crawl-ref/source/ability.cc | 4 +- crawl-ref/source/chardump.cc | 14 ++-- crawl-ref/source/item-name.cc | 4 +- crawl-ref/source/melee-attack.cc | 2 +- crawl-ref/source/mutation.cc | 40 +++++----- crawl-ref/source/player.cc | 127 +++++++------------------------ crawl-ref/source/potion.cc | 2 +- crawl-ref/source/status.cc | 38 ++++++--- crawl-ref/source/transform.cc | 8 +- 9 files changed, 88 insertions(+), 151 deletions(-) diff --git a/crawl-ref/source/ability.cc b/crawl-ref/source/ability.cc index 17a25285d1c2..6fac820f526a 100644 --- a/crawl-ref/source/ability.cc +++ b/crawl-ref/source/ability.cc @@ -1196,7 +1196,7 @@ void no_ability_msg() mpr("You can't untransform!"); else { - ASSERT(you.hunger_state > HS_SATIATED); + ASSERT(you.hunger_state > HS_STARVING); mpr("Sorry, you're too full to transform right now."); } } @@ -3421,7 +3421,7 @@ vector your_talents(bool check_confused, bool include_unusable) } if (you.species == SP_VAMPIRE && you.experience_level >= 3 - && you.hunger_state <= HS_SATIATED + && you.hunger_state <= HS_STARVING && you.form != transformation::bat) { _add_talent(talents, ABIL_TRAN_BAT, check_confused); diff --git a/crawl-ref/source/chardump.cc b/crawl-ref/source/chardump.cc index c2d0b9711653..4fc37389d889 100644 --- a/crawl-ref/source/chardump.cc +++ b/crawl-ref/source/chardump.cc @@ -1517,13 +1517,13 @@ static const char* thirst_names[] = { "bloodless", "bloodless", - "near bloodless", - "very thirsty", - "thirsty", - "not thirsty", - "full", - "very full", - "almost alive", + "bloodless", + "alive", + "alive", + "alive", + "alive", + "alive", + "alive", }; COMPILE_CHECK(ARRAYSZ(thirst_names) == HS_ENGORGED + 1); diff --git a/crawl-ref/source/item-name.cc b/crawl-ref/source/item-name.cc index 68bd526eda31..d1232e18b2e1 100644 --- a/crawl-ref/source/item-name.cc +++ b/crawl-ref/source/item-name.cc @@ -3511,7 +3511,7 @@ bool is_useless_item(const item_def &item, bool temp) case POT_LIGNIFY: return you.undead_state(temp) && (you.species != SP_VAMPIRE - || temp && you.hunger_state < HS_SATIATED); + || temp && you.hunger_state <= HS_STARVING); case POT_FLIGHT: return you.permanent_flight() @@ -3559,7 +3559,7 @@ bool is_useless_item(const item_def &item, bool temp) case AMU_RAGE: return you.undead_state(temp) && (you.species != SP_VAMPIRE - || temp && you.hunger_state < HS_SATIATED) + || temp && you.hunger_state <= HS_STARVING) || you.species == SP_FORMICID || you.get_mutation_level(MUT_NO_ARTIFICE); diff --git a/crawl-ref/source/melee-attack.cc b/crawl-ref/source/melee-attack.cc index 8511276da043..a910cb8e08f8 100644 --- a/crawl-ref/source/melee-attack.cc +++ b/crawl-ref/source/melee-attack.cc @@ -3653,7 +3653,7 @@ bool melee_attack::_player_vampire_draws_blood(const monster* mon, const int dam bool melee_attack::_vamp_wants_blood_from_monster(const monster* mon) { return you.species == SP_VAMPIRE - && you.hunger_state < HS_SATIATED + && you.hunger_state <= HS_STARVING && actor_is_susceptible_to_vampirism(*mon) && mons_has_blood(mon->type); } diff --git a/crawl-ref/source/mutation.cc b/crawl-ref/source/mutation.cc index 8eb8d4c4cab4..1922be3e4cbe 100644 --- a/crawl-ref/source/mutation.cc +++ b/crawl-ref/source/mutation.cc @@ -646,9 +646,7 @@ string describe_mutations(bool drop_title) { if (you.hunger_state <= HS_STARVING) result += "You do not heal naturally.\n"; - else if (you.hunger_state < HS_SATIATED) - result += "You heal slowly.\n"; - else if (you.hunger_state >= HS_FULL) + else result += "Your natural rate of healing is unusually fast.\n"; } @@ -773,16 +771,14 @@ static int _vampire_bloodlessness() case HS_ENGORGED: case HS_VERY_FULL: case HS_FULL: - return 1; case HS_SATIATED: - return 2; case HS_HUNGRY: case HS_VERY_HUNGRY: case HS_NEAR_STARVING: - return 3; + return 1; case HS_STARVING: case HS_FAINTING: - return 4; + return 2; } die("bad hunger state %d", you.hunger_state); } @@ -794,41 +790,41 @@ static string _display_vampire_attributes() string result; const int lines = 12; - string column[lines][5] = + string column[lines][3] = { - {" ", "Full ", "Satiated ", "Thirsty ", "Bloodless"}, - //Full Satiated Thirsty Bloodless - {"Metabolism ", "fast ", "normal ", "slow ", "none "}, + {" ", "Alive ", "Bloodless"}, + //Full Bloodless + {"Metabolism ", "fast ", "none "}, - {"Regeneration ", "fast ", "normal ", "slow ", "none "}, + {"Regeneration ", "fast ", "none "}, - {"Stealth boost ", "none ", "none ", "minor ", "major "}, + {"Stealth boost ", "none ", "major "}, - {"Hunger costs ", "full ", "full ", "halved ", "none "}, + {"Hunger costs ", "full ", "none "}, {"\nResistances\n" - "Poison resistance ", " ", " ", "+ ", "immune"}, + "Poison resistance ", " ", "immune"}, - {"Cold resistance ", " ", " ", "+ ", "++ "}, + {"Cold resistance ", " ", "++ "}, - {"Negative resistance ", " ", " + ", "++ ", "+++ "}, + {"Negative resistance ", " ", "+++ "}, - {"Rotting resistance ", " ", " ", "+ ", "+ "}, + {"Rotting resistance ", " ", "+ "}, - {"Torment resistance ", " ", " ", " ", "+ "}, + {"Torment resistance ", " ", "+ "}, {"\nTransformations\n" - "Bat form ", "no ", "yes ", "yes ", "yes "}, + "Bat form ", "no ", "yes "}, {"Other forms and \n" - "berserk ", "yes ", "yes ", "no ", "no "} + "berserk ", "yes ", "no "} }; int current = _vampire_bloodlessness(); for (int y = 0; y < lines; y++) // lines (properties) { - for (int x = 0; x < 5; x++) // columns (hunger states) + for (int x = 0; x < 3; x++) // columns (hunger states) { if (y > 0 && x == current) result += ""; diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 6066fe06bea1..2ab2a545ed34 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -1136,11 +1136,9 @@ int player_regen() if (you.species == SP_VAMPIRE) { if (you.hunger_state <= HS_STARVING) - rr = 0; // No regeneration for starving vampires. - else if (you.hunger_state < HS_SATIATED) - rr /= 2; // Halved regeneration for hungry vampires. - else if (you.hunger_state >= HS_FULL) - rr += 20; // Bonus regeneration for full vampires. + rr = 0; // No regeneration for bloodless vampires. + else + rr += 20; // Bonus regeneration for alive vampires. } if (you.duration[DUR_COLLAPSE]) @@ -1241,25 +1239,10 @@ int player_hunger_rate(bool temp) if (you.species == SP_VAMPIRE) { - switch (you.hunger_state) - { - case HS_FAINTING: - case HS_STARVING: + if (you.hunger_state <= HS_STARVING) hunger -= 3; - break; - case HS_NEAR_STARVING: - case HS_VERY_HUNGRY: - case HS_HUNGRY: - hunger--; - break; - case HS_SATIATED: - break; - case HS_FULL: - case HS_VERY_FULL: - case HS_ENGORGED: + else hunger += 2; - break; - } } else { @@ -1442,13 +1425,8 @@ int player_res_cold(bool calc_unid, bool temp, bool items) rc += get_form()->res_cold(); - if (you.species == SP_VAMPIRE) - { - if (you.hunger_state <= HS_STARVING) + if (you.species == SP_VAMPIRE && you.hunger_state <= HS_STARVING) rc += 2; - else if (you.hunger_state < HS_SATIATED) - rc++; - } } if (items) @@ -1660,11 +1638,6 @@ int player_res_poison(bool calc_unid, bool temp, bool items) rp += you.get_mutation_level(MUT_POISON_RESISTANCE, temp); rp += you.get_mutation_level(MUT_SLIMY_GREEN_SCALES, temp) == 3 ? 1 : 0; - // Only thirsty vampires are naturally poison resistant. - // XXX: && temp? - if (you.species == SP_VAMPIRE && you.hunger_state < HS_SATIATED) - rp++; - if (temp) { // potions/cards: @@ -1843,26 +1816,8 @@ int player_prot_life(bool calc_unid, bool temp, bool items) // Hunger is temporary, true, but that's something you can control, // especially as life protection only increases the hungrier you // get. - if (you.species == SP_VAMPIRE) - { - switch (you.hunger_state) - { - case HS_FAINTING: - case HS_STARVING: + if (you.species == SP_VAMPIRE && you.hunger_state <= HS_STARVING) pl = 3; - break; - case HS_NEAR_STARVING: - case HS_VERY_HUNGRY: - case HS_HUNGRY: - pl = 2; - break; - case HS_SATIATED: - pl = 1; - break; - default: - break; - } - } // Same here. Your piety status, and, hence, TSO's protection, is // something you can more or less control. @@ -2878,7 +2833,7 @@ void level_change(bool skip_attribute_increase) case SP_VAMPIRE: if (you.experience_level == 3) { - if (you.hunger_state > HS_SATIATED) + if (you.hunger_state > HS_STARVING) { mprf(MSGCH_INTRINSIC_GAIN, "If you weren't so full, " "you could now transform into a vampire bat."); @@ -3187,13 +3142,11 @@ int player_stealth() if (you.duration[DUR_SILENCE]) stealth -= STEALTH_PIP; - // Thirsty vampires are stealthier. - if (you.species == SP_VAMPIRE) + // Bloodless vampires are stealthier. + if (you.species == SP_VAMPIRE + && (you.hunger_state <= HS_STARVING || you.form == transformation::bat)) { - if (you.hunger_state <= HS_STARVING || you.form == transformation::bat) stealth += STEALTH_PIP * 2; - else if (you.hunger_state <= HS_HUNGRY) - stealth += STEALTH_PIP; } if (!you.airborne()) @@ -3293,34 +3246,18 @@ static void _display_vampire_status() string msg = "At your current hunger state you "; vector attrib; - switch (you.hunger_state) + if (you.hunger_state <= HS_STARVING) { - case HS_FAINTING: - case HS_STARVING: - attrib.push_back("are immune to poison"); - attrib.push_back("significantly resist cold"); - attrib.push_back("are immune to negative energy"); - attrib.push_back("resist torment"); - attrib.push_back("do not heal."); - break; - case HS_NEAR_STARVING: - case HS_VERY_HUNGRY: - case HS_HUNGRY: - attrib.push_back("resist poison"); - attrib.push_back("resist cold"); - attrib.push_back("significantly resist negative energy"); - attrib.push_back("have a slow metabolism"); - attrib.push_back("heal slowly."); - break; - case HS_SATIATED: - attrib.push_back("resist negative energy."); - break; - case HS_FULL: - case HS_VERY_FULL: - case HS_ENGORGED: - attrib.push_back("have a fast metabolism"); - attrib.push_back("heal quickly."); - break; + attrib.push_back("are immune to poison"); + attrib.push_back("significantly resist cold"); + attrib.push_back("are immune to negative energy"); + attrib.push_back("resist torment"); + attrib.push_back("do not heal."); + } + else + { + attrib.push_back("have a fast metabolism"); + attrib.push_back("heal quickly."); } if (!attrib.empty()) @@ -4328,13 +4265,8 @@ void handle_player_poison(int delay) // Transforming into a form with no metabolism merely suspends the poison // but doesn't let your body get rid of it. - // Hungry vampires are less affected by poison (not at all when bloodless). - if (you.is_nonliving() || you.undead_state() - && (you.undead_state() != US_SEMI_UNDEAD - || x_chance_in_y(4 - you.hunger_state, 4))) - { + if (you.is_nonliving() || you.undead_state()) return; - } // Other sources of immunity (Zin, staff of Olgreb) let poison dissipate. bool do_dmg = (player_res_poison() >= 3 ? false : true); @@ -5516,13 +5448,8 @@ void player::banish(actor* /*agent*/, const string &who, const int power, // to 50% (hungry, very hungry, near starving) or zero (starving). int calc_hunger(int food_cost) { - if (you.undead_state() == US_SEMI_UNDEAD && you.hunger_state < HS_SATIATED) - { - if (you.hunger_state <= HS_STARVING) - return 0; - - return food_cost/2; - } + if (you.undead_state() == US_SEMI_UNDEAD && you.hunger_state <= HS_STARVING) + return 0; return food_cost; } @@ -6207,7 +6134,7 @@ int player::res_rotting(bool temp) const return 1; // rottable by Zin, not by necromancy case US_SEMI_UNDEAD: - if (temp && hunger_state < HS_SATIATED) + if (temp && hunger_state <= HS_STARVING) return 1; return 0; // no permanent resistance @@ -7089,7 +7016,7 @@ bool player::can_safely_mutate(bool temp) const bool player::is_lifeless_undead(bool temp) const { if (undead_state() == US_SEMI_UNDEAD) - return temp ? hunger_state < HS_SATIATED : false; + return temp ? hunger_state <= HS_STARVING : false; else return undead_state(temp) != US_ALIVE; } diff --git a/crawl-ref/source/potion.cc b/crawl-ref/source/potion.cc index 8f5b1f00798c..7e49c57d4df0 100644 --- a/crawl-ref/source/potion.cc +++ b/crawl-ref/source/potion.cc @@ -655,7 +655,7 @@ class PotionBerserk : public PotionEffect bool effect(bool was_known = true, int pow = 40, bool=true) const override { - if (you.species == SP_VAMPIRE && you.hunger_state < HS_SATIATED) + if (you.species == SP_VAMPIRE && you.hunger_state <= HS_STARVING) { mpr("You feel slightly irritated."); return false; diff --git a/crawl-ref/source/status.cc b/crawl-ref/source/status.cc index 86af014512c5..38c7dbd28f1f 100644 --- a/crawl-ref/source/status.cc +++ b/crawl-ref/source/status.cc @@ -732,13 +732,28 @@ bool fill_status_info(int status, status_info& inf) static void _describe_hunger(status_info& inf) { - const bool vamp = (you.species == SP_VAMPIRE); + + if (you.species == SP_VAMPIRE) + { + if (you.hunger_state <= HS_STARVING) + { + inf.light_colour = LIGHTRED; + inf.light_text = "Bloodless"; + inf.short_text = "bloodless"; + } + else + { + inf.light_colour = GREEN; + inf.light_text = "Alive"; + } + return; + } switch (you.hunger_state) { case HS_ENGORGED: - inf.light_colour = (vamp ? GREEN : LIGHTGREEN); - inf.light_text = (vamp ? "Alive" : "Engorged"); + inf.light_colour = LIGHTGREEN; + inf.light_text = "Engorged"; break; case HS_VERY_FULL: inf.light_colour = GREEN; @@ -750,25 +765,25 @@ static void _describe_hunger(status_info& inf) break; case HS_HUNGRY: inf.light_colour = YELLOW; - inf.light_text = (vamp ? "Thirsty" : "Hungry"); + inf.light_text = "Hungry"; break; case HS_VERY_HUNGRY: inf.light_colour = YELLOW; - inf.light_text = (vamp ? "Very Thirsty" : "Very Hungry"); + inf.light_text = "Very Hungry"; break; case HS_NEAR_STARVING: inf.light_colour = YELLOW; - inf.light_text = (vamp ? "Near Bloodless" : "Near Starving"); + inf.light_text = "Near Starving"; break; case HS_STARVING: inf.light_colour = LIGHTRED; - inf.light_text = (vamp ? "Bloodless" : "Starving"); - inf.short_text = (vamp ? "bloodless" : "starving"); + inf.light_text = "Starving"; + inf.short_text = "starving"; break; case HS_FAINTING: inf.light_colour = RED; - inf.light_text = (vamp ? "Bloodless" : "Fainting"); - inf.short_text = (vamp ? "bloodless" : "fainting"); + inf.light_text = "Fainting"; + inf.short_text = "fainting"; break; case HS_SATIATED: // no status light default: @@ -819,8 +834,7 @@ static void _describe_regen(status_info& inf) || you.duration[DUR_TROGS_HAND] > 0); const bool no_heal = !player_regenerates_hp(); // Does vampire hunger level affect regeneration rate significantly? - const bool vampmod = !no_heal && !regen && you.species == SP_VAMPIRE - && you.hunger_state != HS_SATIATED; + const bool vampmod = !no_heal && !regen && you.species == SP_VAMPIRE; if (regen) { diff --git a/crawl-ref/source/transform.cc b/crawl-ref/source/transform.cc index 484e6156f999..2223a92eb35d 100644 --- a/crawl-ref/source/transform.cc +++ b/crawl-ref/source/transform.cc @@ -1547,16 +1547,16 @@ undead_form_reason lifeless_prevents_form(transformation which_trans, if (which_trans == transformation::lich) return UFR_TOO_DEAD; // vampires can never lichform - if (which_trans == transformation::bat) // can batform on satiated or below + if (which_trans == transformation::bat) // can batform bloodless { if (involuntary) return UFR_TOO_DEAD; // but not as a forced polymorph effect - return you.hunger_state <= HS_SATIATED ? UFR_GOOD : UFR_TOO_ALIVE; + return you.hunger_state <= HS_STARVING ? UFR_GOOD : UFR_TOO_ALIVE; } - // other forms can only be entered when satiated or above. - return you.hunger_state >= HS_SATIATED ? UFR_GOOD : UFR_TOO_DEAD; + // other forms can only be entered when alive + return you.hunger_state > HS_STARVING ? UFR_GOOD : UFR_TOO_DEAD; } /** From b5eab8406da4596c2a6a97804dc2c09e80c3fcfa Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Sat, 20 Apr 2019 15:27:47 -0400 Subject: [PATCH 390/864] Remove blood bottling and blood drinking Part 2 of a vampire revision. This commit makes vampires foodless (but not drinkless) which has the appropriate effect on Gozag. Blood bottling and blood specific code are removed, as is the nutrition gain from melee attacks. This decouples vampires from the food system. [Committer's note: includes a fixup from gammafunk] --- crawl-ref/source/acquire.cc | 15 +- crawl-ref/source/art-func.h | 8 +- crawl-ref/source/butcher.cc | 121 +++-------------- crawl-ref/source/butcher.h | 6 +- crawl-ref/source/command.cc | 10 +- crawl-ref/source/dat/species/vampire.yaml | 3 + crawl-ref/source/delay.cc | 24 +--- crawl-ref/source/delay.h | 30 ---- crawl-ref/source/dungeon.cc | 12 -- crawl-ref/source/food.cc | 158 +++------------------- crawl-ref/source/god-abil.cc | 4 +- crawl-ref/source/invent.cc | 3 +- crawl-ref/source/item-name.cc | 2 - crawl-ref/source/item-use.cc | 39 +----- crawl-ref/source/l-food.cc | 14 -- crawl-ref/source/melee-attack.cc | 4 - crawl-ref/source/ng-init.cc | 4 +- crawl-ref/source/ng-setup.cc | 5 - crawl-ref/source/player-equip.cc | 3 +- crawl-ref/source/player.cc | 14 +- crawl-ref/source/tilepick.cc | 4 - crawl-ref/source/tilereg-inv.cc | 35 +---- 22 files changed, 61 insertions(+), 457 deletions(-) diff --git a/crawl-ref/source/acquire.cc b/crawl-ref/source/acquire.cc index aaa29a4a7f45..769b2233cddb 100644 --- a/crawl-ref/source/acquire.cc +++ b/crawl-ref/source/acquire.cc @@ -407,13 +407,6 @@ static int _acquirement_food_subtype(bool /*divine*/, int& quantity) // Food is a little less predictable now. - bwr if (you.species == SP_GHOUL) type_wanted = FOOD_CHUNK; - else if (you.species == SP_VAMPIRE) - { - // Vampires really don't want any OBJ_FOOD but OBJ_CORPSES - // but it's easier to just give them a potion of blood - // class type is set elsewhere - type_wanted = POT_BLOOD; - } else type_wanted = FOOD_RATION; @@ -771,10 +764,6 @@ static int _find_acquirement_subtype(object_class_type &class_wanted, if (class_wanted == OBJ_MISCELLANY) class_wanted = random_choose(OBJ_WANDS, OBJ_MISCELLANY); - // Vampires acquire blood, not food. - if (class_wanted == OBJ_FOOD && you.species == SP_VAMPIRE) - class_wanted = OBJ_POTIONS; - if (_subtype_finders[class_wanted]) type_wanted = (*_subtype_finders[class_wanted])(divine, quantity); @@ -1516,12 +1505,10 @@ bool acquirement(object_class_type class_wanted, int agent, { OBJ_BOOKS, "Book" }, { OBJ_STAVES, "Staff " }, { OBJ_MISCELLANY, "Evocable" }, - { OBJ_FOOD, 0 }, // amended below + { OBJ_FOOD, "Food" }, // amended below { OBJ_GOLD, 0 }, }; ASSERT(acq_classes[6].type == OBJ_FOOD); - acq_classes[6].name = you.species == SP_VAMPIRE ? "Blood": - "Food"; string gold_text = make_stringf("Gold (you have $%d)", you.gold); ASSERT(acq_classes[7].type == OBJ_GOLD); acq_classes[7].name = gold_text.c_str(); diff --git a/crawl-ref/source/art-func.h b/crawl-ref/source/art-func.h index da7bf6d6fa40..42564442d82c 100644 --- a/crawl-ref/source/art-func.h +++ b/crawl-ref/source/art-func.h @@ -522,7 +522,8 @@ static bool _WUCAD_MU_evoke(item_def *item, bool* did_work, bool* unevokable) static void _VAMPIRES_TOOTH_equip(item_def *item, bool *show_msgs, bool unmeld) { - if (you.undead_state() == US_ALIVE && !you_foodless()) + if (you.undead_state() == US_ALIVE + && (you.species == SP_VAMPIRE || !you_foodless())) { _equip_mpr(show_msgs, "You feel a strange hunger, and smell blood in the air..."); @@ -1348,8 +1349,11 @@ static void _FROSTBITE_melee_effects(item_def* weapon, actor* attacker, static void _LEECH_equip(item_def *item, bool *show_msgs, bool unmeld) { - if (you.undead_state() == US_ALIVE && !you_foodless()) + if (you.undead_state() == US_ALIVE + && (you.species == SP_VAMPIRE || !you_foodless())) + { _equip_mpr(show_msgs, "You feel a powerful hunger."); + } else if (you.species != SP_VAMPIRE) _equip_mpr(show_msgs, "You feel very empty."); // else let player-equip.cc handle message diff --git a/crawl-ref/source/butcher.cc b/crawl-ref/source/butcher.cc index 6cd48971bca6..0f31f9540f1e 100644 --- a/crawl-ref/source/butcher.cc +++ b/crawl-ref/source/butcher.cc @@ -43,28 +43,20 @@ */ static bool _start_butchering(item_def& corpse) { - const bool bottle_blood = - you.species == SP_VAMPIRE - && can_bottle_blood_from_corpse(corpse.mon_type); - if (is_forbidden_food(corpse)) { - mprf("It would be a sin to %sbutcher this!", - bottle_blood ? "bottle or " : ""); + mprf("It would be a sin to butcher this!"); return false; } // Yes, 0 is correct (no "continue butchering" stage). - if (bottle_blood) - start_delay(0, corpse); - else - start_delay(0, corpse); + start_delay(0, corpse); you.turn_is_over = true; return true; } -void finish_butchering(item_def& corpse, bool bottling) +void finish_butchering(item_def& corpse) { ASSERT(corpse.base_type == OBJ_CORPSES); ASSERT(corpse.sub_type == CORPSE_BODY); @@ -72,22 +64,10 @@ void finish_butchering(item_def& corpse, bool bottling) const bool was_intelligent = corpse_intelligence(corpse) >= I_HUMAN; const bool was_same_genus = is_player_same_genus(corpse.mon_type); - if (bottling) - { - mpr("You bottle the corpse's blood."); - - if (mons_skeleton(corpse.mon_type) && one_chance_in(3)) - turn_corpse_into_skeleton_and_blood_potions(corpse); - else - turn_corpse_into_blood_potions(corpse); - } - else - { - mprf("You butcher %s.", - corpse.name(DESC_THE).c_str()); + mprf("You butcher %s.", + corpse.name(DESC_THE).c_str()); - butcher_corpse(corpse); - } + butcher_corpse(corpse); if (was_same_genus) did_god_conduct(DID_CANNIBALISM, 2); @@ -126,9 +106,6 @@ void butchery(item_def* specific_corpse) return; } - const bool bottle_blood = you.species == SP_VAMPIRE; - const char * butcher_verb = bottle_blood ? "bottle" : "butcher"; - vector all_corpses; if (specific_corpse) @@ -140,7 +117,7 @@ void butchery(item_def* specific_corpse) if (all_corpses.empty()) { - mprf("There isn't anything to %s here.", butcher_verb); + mprf("There isn't anything to butcher here."); return; } if (you_foodless(false)) @@ -167,13 +144,10 @@ void butchery(item_def* specific_corpse) if (all_corpses.size() == 1) { mprf("%s %s.", all_corpses[0]->name(DESC_THE).c_str(), - bottle_blood ? "doesn't have any blood" : "isn't edible"); + "isn't edible"); } else - { - mprf("There isn't anything %s to %s here.", - bottle_blood ? "with blood" : "edible", butcher_verb); - } + mprf("There isn't anything edible to butcher here."); return; } @@ -188,14 +162,13 @@ void butchery(item_def* specific_corpse) { if (edible_corpses.size() == 1) { - mprf("It would be a sin to %s %s!", butcher_verb, + mprf("It would be a sin to butcher %s!", edible_corpses[0]->name(DESC_THE).c_str()); } else { - mprf("It would be a sin to %s any of the %scorpses here!", - butcher_verb, - (seen_inedible ? (bottle_blood ? "bloody " : "edible ") : "")); + mprf("It would be a sin to butcher any of the %scorpses here!", + seen_inedible ? "edible " : ""); } return; } @@ -224,8 +197,7 @@ void butchery(item_def* specific_corpse) meat.push_back(entry.first); vector selected = - select_items(meat, bottle_blood ? "Choose a corpse to bottle" - : "Choose a corpse to butcher", + select_items(meat, "Choose a corpse to butcher", false, menu_type::any, _butcher_menu_title); redraw_screen(); for (SelItem sel : selected) @@ -257,11 +229,8 @@ void butchery(item_def* specific_corpse) // Shall we butcher this corpse? do { - const bool can_bottle = - can_bottle_blood_from_corpse(it->mon_type); mprf(MSGCH_PROMPT, - "%s %s? [(y)es/(n)o/(a)ll/(q)uit/?]", - can_bottle ? "Bottle" : "Butcher", + "Butcher %s? [(y)es/(n)o/(a)ll/(q)uit/?]", corpse_name.c_str()); repeat_prompt = false; @@ -305,7 +274,7 @@ void butchery(item_def* specific_corpse) // No point in displaying this if the player pressed 'a' above. if (!to_eat && !butcher_all && !all_done) - mprf("There isn't anything else to %s here.", butcher_verb); + mprf("There isn't anything else to butcher here."); #endif //XXX: this assumes that we're not being called from a delay ourselves. @@ -370,7 +339,7 @@ void turn_corpse_into_chunks(item_def &item, bool bloodspatter) { item.flags |= ISFLAG_DROPPED; } - else if (you.species != SP_VAMPIRE) + else clear_item_pickup_flags(item); // Initialise timer depending on corpse age @@ -413,61 +382,3 @@ void butcher_corpse(item_def &item, bool skeleton, bool chunks) } } } - -bool can_bottle_blood_from_corpse(monster_type mons_class) -{ - return you.species == SP_VAMPIRE && mons_has_blood(mons_class); -} - -int num_blood_potions_from_corpse(monster_type mons_class) -{ - // Max. amount is about one third of the max. amount for chunks. - const int max_chunks = max_corpse_chunks(mons_class); - - // Max. amount is about one third of the max. amount for chunks. - int pot_quantity = max_chunks / 3; - pot_quantity = stepdown_value(pot_quantity, 2, 2, 6, 6); - - if (pot_quantity < 1) - pot_quantity = 1; - - return pot_quantity; -} - -// If autopickup is active, the potions are auto-picked up after creation. -void turn_corpse_into_blood_potions(item_def &item) -{ - ASSERT(item.base_type == OBJ_CORPSES); - - const item_def corpse = item; - const monster_type mons_class = corpse.mon_type; - - ASSERT(can_bottle_blood_from_corpse(mons_class)); - - item.base_type = OBJ_POTIONS; - item.sub_type = POT_BLOOD; - item_colour(item); - clear_item_pickup_flags(item); - item.props.clear(); - - item.quantity = num_blood_potions_from_corpse(mons_class); - - // Initialise timer depending on corpse age - init_perishable_stack(item, - item.freshness * ROT_TIME_FACTOR + FRESHEST_BLOOD); -} - -void turn_corpse_into_skeleton_and_blood_potions(item_def &item) -{ - item_def blood_potions = item; - - if (mons_skeleton(item.mon_type)) - turn_corpse_into_skeleton(item); - - int o = get_mitm_slot(); - if (o != NON_ITEM) - { - turn_corpse_into_blood_potions(blood_potions); - copy_item_to_grid(blood_potions, you.pos()); - } -} diff --git a/crawl-ref/source/butcher.h b/crawl-ref/source/butcher.h index 624173031419..52040f5c22ca 100644 --- a/crawl-ref/source/butcher.h +++ b/crawl-ref/source/butcher.h @@ -8,14 +8,10 @@ #include "maybe-bool.h" void butchery(item_def* specific_corpse = nullptr); -void finish_butchering(item_def& corpse, bool bottling); +void finish_butchering(item_def& corpse); void maybe_drop_monster_hide(const item_def &corpse); bool turn_corpse_into_skeleton(item_def &item); void turn_corpse_into_chunks(item_def &item, bool bloodspatter = true); void butcher_corpse(item_def &item, bool skeleton = true, bool chunks = true); -bool can_bottle_blood_from_corpse(monster_type mons_class); -int num_blood_potions_from_corpse(monster_type mons_class); -void turn_corpse_into_blood_potions(item_def &item); -void turn_corpse_into_skeleton_and_blood_potions(item_def &item); diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc index 14e8dfd652fb..4a122c93608b 100644 --- a/crawl-ref/source/command.cc +++ b/crawl-ref/source/command.cc @@ -962,14 +962,8 @@ static void _add_formatted_keyhelp(column_composer &cols) _add_command(cols, 1, CMD_INSCRIBE_ITEM, "inscribe item", 2); { - const bool vampire = you.species == SP_VAMPIRE; - string butcher = vampire ? "bottle blood from" - : "Chop up"; - _add_command(cols, 1, CMD_BUTCHER, butcher + " a corpse on floor", 2); - string interact = (you.species == SP_VAMPIRE ? "drain corpses" - : "Eat food"); - interact += " (tries floor first)\n"; - _add_command(cols, 1, CMD_EAT, interact, 2); + _add_command(cols, 1, CMD_BUTCHER, "Chop up a corpse on floor", 2); + _add_command(cols, 1, CMD_EAT, "Eat food (tries floor first) \n", 2); } _add_command(cols, 1, CMD_FIRE, "Fire next appropriate item", 2); _add_command(cols, 1, CMD_THROW_ITEM_NO_QUIVER, "select an item and Fire it", 2); diff --git a/crawl-ref/source/dat/species/vampire.yaml b/crawl-ref/source/dat/species/vampire.yaml index 54e8d84bb631..c0e73ec603ab 100644 --- a/crawl-ref/source/dat/species/vampire.yaml +++ b/crawl-ref/source/dat/species/vampire.yaml @@ -49,6 +49,9 @@ mutations: MUT_FANGS: 3 MUT_ACUTE_VISION: 1 MUT_UNBREATHING: 1 +fake_mutations: + - long: You do not eat. + short: no food recommended_jobs: - JOB_GLADIATOR - JOB_ASSASSIN diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc index 6a05607453d3..27796a9cb214 100644 --- a/crawl-ref/source/delay.cc +++ b/crawl-ref/source/delay.cc @@ -146,12 +146,6 @@ static void _interrupt_butchering(const char* action) mprf("You stop %s the corpse%s.", action, multiple_corpses ? "s" : ""); } -bool BottleBloodDelay::try_interrupt() -{ - _interrupt_butchering("bottling blood from"); - return true; -} - bool ButcherDelay::try_interrupt() { _interrupt_butchering("butchering"); @@ -601,11 +595,6 @@ bool ButcherDelay::invalidated() return _check_corpse_gone(corpse, "butcher it"); } -bool BottleBloodDelay::invalidated() -{ - return _check_corpse_gone(corpse, "bottle its blood"); -} - bool MultidropDelay::invalidated() { // Throw away invalid items. XXX: what are they? @@ -866,14 +855,14 @@ void BlurryScrollDelay::finish() read_scroll(scroll); } -static void _finish_butcher_delay(item_def& corpse, bool bottling) +static void _finish_butcher_delay(item_def& corpse) { // We know the item is valid and a real corpse, because invalidated() // checked for that. - finish_butchering(corpse, bottling); + finish_butchering(corpse); // Don't waste time picking up chunks if you're already // starving. (jpeg) - if ((you.hunger_state > HS_STARVING || you.species == SP_VAMPIRE) + if (you.hunger_state > HS_STARVING // Only pick up chunks if this is the last delay... && (you.delay_queue.size() == 1 // ...Or, equivalently, if it's the last butcher one. @@ -886,12 +875,7 @@ static void _finish_butcher_delay(item_def& corpse, bool bottling) void ButcherDelay::finish() { - _finish_butcher_delay(corpse, false); -} - -void BottleBloodDelay::finish() -{ - _finish_butcher_delay(corpse, true); + _finish_butcher_delay(corpse); } void DropItemDelay::finish() diff --git a/crawl-ref/source/delay.h b/crawl-ref/source/delay.h index eff55285ce2a..caae361ee934 100644 --- a/crawl-ref/source/delay.h +++ b/crawl-ref/source/delay.h @@ -342,36 +342,6 @@ class ButcherDelay : public Delay } }; -class BottleBloodDelay : public Delay -{ - item_def& corpse; - - bool invalidated() override; - - void finish() override; -public: - BottleBloodDelay(int dur, item_def& item) : - Delay(dur), corpse(item) - { } - - bool try_interrupt() override; - - bool is_butcher() const override - { - return true; - } - - bool is_being_used(const item_def* item, operation_types oper) const override - { - return oper == OPER_BUTCHER && (!item || &corpse == item); - } - - const char* name() const override - { - return "bottle_blood"; - } -}; - class PasswallDelay : public Delay { coord_def dest; diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index a19c6c53588c..51dd318a95d3 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -5658,12 +5658,6 @@ static void _stock_shop_item(int j, shop_type shop_type_, object_class_type basetype = item_in_shop(shop_type_); int subtype = OBJ_RANDOM; - if (spec.gozag && shop_type_ == SHOP_FOOD && you.species == SP_VAMPIRE) - { - basetype = OBJ_POTIONS; - subtype = POT_BLOOD; - } - if (!spec.items.empty() && !spec.use_all) { // shop spec lists a random set of items; choose one @@ -5719,12 +5713,6 @@ static void _stock_shop_item(int j, shop_type shop_type_, if (shop_type_ == SHOP_BOOK && !is_artefact(item)) stocked[item.sub_type]++; - if (spec.gozag && shop_type_ == SHOP_FOOD && you.species == SP_VAMPIRE) - { - ASSERT(is_blood_potion(item)); - item.quantity += random2(3); // blood for the vampire friends :) - } - // Identify the item, unless we don't do that. if (!_shop_sells_antiques(shop_type_)) set_ident_flags(item, ISFLAG_IDENT_MASK); diff --git a/crawl-ref/source/food.cc b/crawl-ref/source/food.cc index 3d2c13169a0d..85be812b4723 100644 --- a/crawl-ref/source/food.cc +++ b/crawl-ref/source/food.cc @@ -44,7 +44,6 @@ #include "xom.h" static void _describe_food_change(int hunger_increment); -static bool _vampire_consume_corpse(item_def& corpse); static void _heal_from_food(int hp_amt); void make_hungry(int hunger_amount, bool suppress_msg, @@ -120,16 +119,12 @@ void set_hunger(int new_hunger_level, bool suppress_msg) bool you_foodless(bool temp) { - return you.undead_state(temp) == US_UNDEAD; + return you.undead_state(temp) == US_UNDEAD + || you.undead_state(temp) == US_SEMI_UNDEAD; } bool prompt_eat_item(int slot) { - // There's nothing in inventory that a vampire can 'e', and floor corpses - // are handled by prompt_eat_chunks. - if (you.species == SP_VAMPIRE) - return false; - item_def* item = nullptr; if (slot == -1) { @@ -169,8 +164,7 @@ static bool _eat_check(bool check_hunger = true, bool silent = false, { if (!silent) { - mprf("You're too full to %s anything.", - you.species == SP_VAMPIRE ? "drain" : "eat"); + mprf("You're too full to eat anything."); crawl_state.zero_turns_taken(); } return false; @@ -194,9 +188,6 @@ bool eat_food(int slot) return false; } - if (you.species == SP_VAMPIRE) - mpr("There's nothing here to drain!"); - return prompt_eat_item(slot); } @@ -204,8 +195,6 @@ static string _how_hungry() { if (you.hunger_state > HS_SATIATED) return "full"; - else if (you.species == SP_VAMPIRE) - return "thirsty"; return "hungry"; } @@ -237,28 +226,6 @@ bool food_change(bool initial) if (newstate < HS_SATIATED) interrupt_activity(activity_interrupt::hungry); - if (you.species == SP_VAMPIRE) - { - const undead_form_reason form_reason = lifeless_prevents_form(); - if (form_reason == UFR_GOOD) - { - if (newstate == HS_ENGORGED && is_vampire_feeding()) // Alive - { - print_stats(); - mpr("You can't stomach any more blood right now."); - } - } - else if (you.duration[DUR_TRANSFORMATION]) - { - print_stats(); - mprf(MSGCH_WARN, - "Your blood-%s body can't sustain your transformation.", - form_reason == UFR_TOO_DEAD ? "deprived" : "filled"); - you.duration[DUR_TRANSFORMATION] = 1; // end at end of turn - // could maybe end immediately, but that makes me nervous - } - } - if (!initial) { string msg = "You "; @@ -270,10 +237,7 @@ bool food_change(bool initial) break; case HS_STARVING: - if (you.species == SP_VAMPIRE) - msg += "feel devoid of blood!"; - else - msg += "are starving!"; + msg += "are starving!"; mprf(MSGCH_FOOD, less_hungry, "%s", msg.c_str()); @@ -282,10 +246,7 @@ bool food_change(bool initial) break; case HS_NEAR_STARVING: - if (you.species == SP_VAMPIRE) - msg += "feel almost devoid of blood!"; - else - msg += "are near starving!"; + msg += "are near starving!"; mprf(MSGCH_FOOD, less_hungry, "%s", msg.c_str()); @@ -411,7 +372,7 @@ int prompt_eat_chunks(bool only_auto) // If we *know* the player can eat chunks, doesn't have the gourmand // effect and isn't hungry, don't prompt for chunks. - if (you.species != SP_VAMPIRE && you.hunger_state > _max_chunk_state()) + if (you.hunger_state > _max_chunk_state()) return 0; bool found_valid = false; @@ -419,15 +380,7 @@ int prompt_eat_chunks(bool only_auto) for (stack_iterator si(you.pos(), true); si; ++si) { - if (you.species == SP_VAMPIRE) - { - if (si->base_type != OBJ_CORPSES || si->sub_type != CORPSE_BODY) - continue; - - if (!mons_has_blood(si->mon_type)) - continue; - } - else if (si->base_type != OBJ_FOOD + if (si->base_type != OBJ_FOOD || si->sub_type != FOOD_CHUNK || is_bad_food(*si)) { @@ -444,10 +397,6 @@ int prompt_eat_chunks(bool only_auto) if (!item.defined()) continue; - // Vampires can't eat anything in their inventory. - if (you.species == SP_VAMPIRE) - continue; - if (item.base_type != OBJ_FOOD || item.sub_type != FOOD_CHUNK) continue; @@ -484,8 +433,7 @@ int prompt_eat_chunks(bool only_auto) return 0; else { - mprf(MSGCH_PROMPT, "%s %s%s? (ye/n/q)", - (you.species == SP_VAMPIRE ? "Drink blood from" : "Eat"), + mprf(MSGCH_PROMPT, "Eat %s%s? (ye/n/q)", ((item->quantity > 1) ? "one of " : ""), item_name.c_str()); } @@ -507,9 +455,7 @@ int prompt_eat_chunks(bool only_auto) { if (autoeat) { - mprf("%s %s%s.", - (you.species == SP_VAMPIRE ? "Drinking blood from" - : "Eating"), + mprf("Eating %s%s.", ((item->quantity > 1) ? "one of " : ""), item_name.c_str()); } @@ -666,19 +612,7 @@ static void _eat_chunk(item_def& food) bool eat_item(item_def &food) { if (food.is_type(OBJ_CORPSES, CORPSE_BODY)) - { - if (you.species != SP_VAMPIRE) - return false; - - if (_vampire_consume_corpse(food)) - { - count_action(CACT_EAT, -1); // subtype Corpse - you.turn_is_over = true; - return true; - } - return false; - } mprf("You eat %s%s.", food.quantity > 1 ? "one of " : "", food.name(DESC_THE).c_str()); @@ -739,19 +673,11 @@ bool is_inedible(const item_def &item, bool temp) if (item.sub_type == CORPSE_SKELETON) return true; - if (you.species == SP_VAMPIRE) - { - if (!mons_has_blood(item.mon_type)) - return true; - } - else - { - item_def chunk = item; - chunk.base_type = OBJ_FOOD; - chunk.sub_type = FOOD_CHUNK; - if (is_inedible(chunk, temp)) - return true; - } + item_def chunk = item; + chunk.base_type = OBJ_FOOD; + chunk.sub_type = FOOD_CHUNK; + if (is_inedible(chunk, temp)) + return true; } return false; @@ -762,15 +688,10 @@ bool is_inedible(const item_def &item, bool temp) // still be edible or even delicious. bool is_preferred_food(const item_def &food) { - // Mummies and liches don't eat. + // Mummies, vampirees, and liches don't eat. if (you_foodless()) return false; - // Vampires don't really have a preferred food type, but they really - // like blood potions. - if (you.species == SP_VAMPIRE) - return is_blood_potion(food); - if (you.species == SP_GHOUL) return food.is_type(OBJ_FOOD, FOOD_CHUNK); @@ -830,14 +751,7 @@ bool can_eat(const item_def &food, bool suppress_msg, bool check_hunger, if (is_noxious(food)) FAIL("It is completely inedible."); - if (you.species == SP_VAMPIRE) - { - if (food.is_type(OBJ_CORPSES, CORPSE_BODY)) - return true; - - FAIL("Blech - you need blood!") - } - else if (food.base_type == OBJ_CORPSES) + if (food.base_type == OBJ_CORPSES) return false; if (food_is_meaty(food)) @@ -889,7 +803,7 @@ corpse_effect_type determine_chunk_effect(corpse_effect_type chunktype) switch (chunktype) { case CE_NOXIOUS: - if (you.species == SP_GHOUL || you.species == SP_VAMPIRE) + if (you.species == SP_GHOUL) chunktype = CE_CLEAN; break; @@ -900,44 +814,6 @@ corpse_effect_type determine_chunk_effect(corpse_effect_type chunktype) return chunktype; } -static bool _vampire_consume_corpse(item_def& corpse) -{ - ASSERT(you.species == SP_VAMPIRE); - ASSERT(corpse.base_type == OBJ_CORPSES); - ASSERT(corpse.sub_type == CORPSE_BODY); - - const monster_type mons_type = corpse.mon_type; - - if (!mons_has_blood(mons_type)) - { - mpr("There is no blood in this body!"); - return false; - } - - mprf("This %sblood tastes delicious!", - mons_class_flag(mons_type, M_WARM_BLOOD) ? "warm " : ""); - - const int food_value = CHUNK_BASE_NUTRITION - * num_blood_potions_from_corpse(mons_type); - lessen_hunger(food_value, false); - - // this will never matter :) - if (mons_genus(mons_type) == MONS_ORC) - did_god_conduct(DID_DESECRATE_ORCISH_REMAINS, 2); - if (mons_class_holiness(mons_type) & MH_HOLY) - did_god_conduct(DID_DESECRATE_HOLY_REMAINS, 2); - - if (mons_skeleton(mons_type) && one_chance_in(3)) - { - turn_corpse_into_skeleton(corpse); - item_check(); - } - else - dec_mitm_item_quantity(corpse.index(), 1); - - return true; -} - static void _heal_from_food(int hp_amt) { if (hp_amt > 0) diff --git a/crawl-ref/source/god-abil.cc b/crawl-ref/source/god-abil.cc index 405c92a89b87..b5bb8e93cd9a 100644 --- a/crawl-ref/source/god-abil.cc +++ b/crawl-ref/source/god-abil.cc @@ -4266,9 +4266,7 @@ static string _gozag_special_shop_name(shop_type type) { if (type == SHOP_FOOD) { - if (you.species == SP_VAMPIRE) - return "Blood"; - else if (you.species == SP_GHOUL) + if (you.species == SP_GHOUL) return "Carrion"; // yum! } diff --git a/crawl-ref/source/invent.cc b/crawl-ref/source/invent.cc index eeff73565eed..a9e36ed09a58 100644 --- a/crawl-ref/source/invent.cc +++ b/crawl-ref/source/invent.cc @@ -1594,8 +1594,7 @@ static string _operation_verb(operation_types oper) case OPER_WIELD: return "wield"; case OPER_QUAFF: return "quaff"; case OPER_DROP: return "drop"; - case OPER_EAT: return you.species == SP_VAMPIRE ? - "drain" : "eat"; + case OPER_EAT: return "eat"; case OPER_TAKEOFF: return "take off"; case OPER_WEAR: return "wear"; case OPER_PUTON: return "put on"; diff --git a/crawl-ref/source/item-name.cc b/crawl-ref/source/item-name.cc index d1232e18b2e1..dbf59af3eb2e 100644 --- a/crawl-ref/source/item-name.cc +++ b/crawl-ref/source/item-name.cc @@ -3522,10 +3522,8 @@ bool is_useless_item(const item_def &item, bool temp) return you.species == SP_VAMPIRE || you.get_mutation_level(MUT_CARNIVOROUS) > 0; case POT_BLOOD_COAGULATED: -#endif case POT_BLOOD: return you.species != SP_VAMPIRE; -#if TAG_MAJOR_VERSION == 34 case POT_DECAY: return you.res_rotting(temp) > 0; case POT_STRONG_POISON: diff --git a/crawl-ref/source/item-use.cc b/crawl-ref/source/item-use.cc index 64e49fea4b06..e04283a74491 100644 --- a/crawl-ref/source/item-use.cc +++ b/crawl-ref/source/item-use.cc @@ -2015,31 +2015,9 @@ void prompt_inscribe_item() inscribe_item(you.inv[item_slot]); } -static bool _check_blood_corpses_on_ground() -{ - for (stack_iterator si(you.pos(), true); si; ++si) - { - if (si->is_type(OBJ_CORPSES, CORPSE_BODY) - && mons_has_blood(si->mon_type)) - { - return true; - } - } - return false; -} - -static void _vampire_corpse_help() -{ - if (you.species != SP_VAMPIRE) - return; - - if (_check_blood_corpses_on_ground()) - mpr("Use e to drain blood from corpses."); -} - void drink(item_def* potion) { - if (you_foodless()) + if (you_foodless() && you.species != SP_VAMPIRE) { mpr("You can't drink."); return; @@ -2062,10 +2040,7 @@ void drink(item_def* potion) potion = use_an_item(OBJ_POTIONS, OPER_QUAFF, "Drink which item?"); if (!potion) - { - _vampire_corpse_help(); return; - } } if (potion->base_type != OBJ_POTIONS) @@ -2117,11 +2092,6 @@ void drink(item_def* potion) // a dangerous monster nearby... xom_is_stimulated(200); } - if (is_blood_potion(*potion)) - { - // Always drink oldest potion. - remove_oldest_perishable_item(*potion); - } // We'll need this later, after destroying the item. const bool was_exp = potion->sub_type == POT_EXPERIENCE; @@ -3384,13 +3354,6 @@ void tile_item_use(int idx) wear_armour(idx); return; - case OBJ_CORPSES: - if (you.species != SP_VAMPIRE - || item.sub_type == CORPSE_SKELETON) - { - break; - } - // intentional fall-through for Vampires case OBJ_FOOD: if (check_warning_inscriptions(item, OPER_EAT)) eat_food(idx); diff --git a/crawl-ref/source/l-food.cc b/crawl-ref/source/l-food.cc index 59f9a4a211f6..ec8303d76b34 100644 --- a/crawl-ref/source/l-food.cc +++ b/crawl-ref/source/l-food.cc @@ -137,19 +137,6 @@ static int food_isveggie(lua_State *ls) return 1; } -/*** Can we bottle blood from this? - * @tparam items.Item body - * @treturn boolean if we succeed - * @function bottleable - */ -static int food_bottleable(lua_State *ls) -{ - LUA_ITEM(ls, item, 1); - lua_pushboolean(ls, item && item->is_type(OBJ_CORPSES, CORPSE_BODY) - && can_bottle_blood_from_corpse(item->mon_type)); - return 1; -} - /*** Is this edible? * Differs from can_eat in that it checks temporary forms? * @tparam items.Item morsel @@ -175,7 +162,6 @@ static const struct luaL_reg food_lib[] = { "isfruit", food_isfruit }, { "ismeaty", food_ismeaty }, { "isveggie", food_isveggie }, - { "bottleable", food_bottleable }, { "edible", food_edible }, { nullptr, nullptr }, }; diff --git a/crawl-ref/source/melee-attack.cc b/crawl-ref/source/melee-attack.cc index a910cb8e08f8..b1ea47fd08f7 100644 --- a/crawl-ref/source/melee-attack.cc +++ b/crawl-ref/source/melee-attack.cc @@ -3643,10 +3643,6 @@ bool melee_attack::_player_vampire_draws_blood(const monster* mon, const int dam } } - // Gain nutrition. - if (you.hunger_state != HS_ENGORGED) - lessen_hunger(30 + random2avg(59, 2), false); - return true; } diff --git a/crawl-ref/source/ng-init.cc b/crawl-ref/source/ng-init.cc index aacd18320355..c00510e02a88 100644 --- a/crawl-ref/source/ng-init.cc +++ b/crawl-ref/source/ng-init.cc @@ -392,7 +392,6 @@ static int _get_random_coagulated_blood_desc() return desc; } } -#endif static int _get_random_blood_desc() { @@ -400,15 +399,16 @@ static int _get_random_blood_desc() 1, PDQ_VISCOUS, 1, PDQ_SEDIMENTED), PDC_RED); } +#endif void initialise_item_descriptions() { // Must remember to check for already existing colours/combinations. you.item_description.init(255); +#if TAG_MAJOR_VERSION == 34 you.item_description[IDESC_POTIONS][POT_BLOOD] = _get_random_blood_desc(); -#if TAG_MAJOR_VERSION == 34 you.item_description[IDESC_POTIONS][POT_BLOOD_COAGULATED] = _get_random_coagulated_blood_desc(); you.item_description[IDESC_POTIONS][POT_PORRIDGE] diff --git a/crawl-ref/source/ng-setup.cc b/crawl-ref/source/ng-setup.cc index 953d519277e5..a45b1effd842 100644 --- a/crawl-ref/source/ng-setup.cc +++ b/crawl-ref/source/ng-setup.cc @@ -324,11 +324,6 @@ static void _give_starting_food() object_class_type base_type = OBJ_FOOD; int sub_type = FOOD_RATION; int quantity = 1; - if (you.species == SP_VAMPIRE) - { - base_type = OBJ_POTIONS; - sub_type = POT_BLOOD; - } // Give another one for hungry species. if (you.get_mutation_level(MUT_FAST_METABOLISM)) diff --git a/crawl-ref/source/player-equip.cc b/crawl-ref/source/player-equip.cc index 8c105a9f0d7d..23923c7c0390 100644 --- a/crawl-ref/source/player-equip.cc +++ b/crawl-ref/source/player-equip.cc @@ -1272,8 +1272,7 @@ static void _equip_jewellery_effect(item_def &item, bool unmeld, break; case AMU_THE_GOURMAND: - if (you.species == SP_VAMPIRE - || you_foodless() // Mummy or in lichform + if (you_foodless() // Mummy, vampire, or in lichform || you.get_mutation_level(MUT_HERBIVOROUS) > 0) // Spriggan { mpr("After a brief, frighteningly intense craving, " diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 2ab2a545ed34..c6e6bb7417b6 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -1237,18 +1237,8 @@ int player_hunger_rate(bool temp) hunger += 4; } - if (you.species == SP_VAMPIRE) - { - if (you.hunger_state <= HS_STARVING) - hunger -= 3; - else - hunger += 2; - } - else - { - hunger += you.get_mutation_level(MUT_FAST_METABOLISM) - - you.get_mutation_level(MUT_SLOW_METABOLISM); - } + hunger += you.get_mutation_level(MUT_FAST_METABOLISM) + - you.get_mutation_level(MUT_SLOW_METABOLISM); // If Cheibriados has slowed your life processes, you will hunger less. if (have_passive(passive_t::slow_metabolism)) diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc index 9a8fe430eb9b..08dcc09421c6 100644 --- a/crawl-ref/source/tilepick.cc +++ b/crawl-ref/source/tilepick.cc @@ -3802,10 +3802,6 @@ tileidx_t tileidx_corpse_brand(const item_def &item) if (item.base_type != OBJ_CORPSES || item.sub_type != CORPSE_BODY) return 0; - // Vampires are only interested in fresh blood. - if (you.species == SP_VAMPIRE && !mons_has_blood(item.mon_type)) - return TILE_FOOD_INEDIBLE; - // Harmful chunk effects > religious rules > reduced nutrition. if (is_noxious(item)) return TILE_FOOD_ROTTING; diff --git a/crawl-ref/source/tilereg-inv.cc b/crawl-ref/source/tilereg-inv.cc index 1ba442636264..8ca5abee789b 100644 --- a/crawl-ref/source/tilereg-inv.cc +++ b/crawl-ref/source/tilereg-inv.cc @@ -8,6 +8,7 @@ #include "cio.h" #include "describe.h" #include "env.h" +#include "food.h" #include "invent.h" #include "item-name.h" #include "item-prop.h" @@ -232,14 +233,6 @@ static bool _can_use_item(const item_def &item, bool equipped) return false; #endif - // Vampires can drain corpses. - if (item.base_type == OBJ_CORPSES) - { - return you.species == SP_VAMPIRE - && item.sub_type != CORPSE_SKELETON - && mons_has_blood(item.mon_type); - } - if (equipped && item.cursed()) { // Evocable items (e.g. dispater staff) are still evocable when cursed. @@ -352,23 +345,11 @@ bool InventoryRegion::update_tip_text(string& tip) if (item.base_type == OBJ_CORPSES && item.sub_type != CORPSE_SKELETON) { - tip += "\n[Shift + L-Click] "; - if (can_bottle_blood_from_corpse(item.mon_type)) - tip += "Bottle blood"; - else - tip += "Chop up"; - tip += " (%)"; + tip += "\n[Shift + L-Click] Chop up (%)"; cmd.push_back(CMD_BUTCHER); - - if (you.species == SP_VAMPIRE) - { - tip += "\n\n[Shift + R-Click] Drink blood (e)"; - cmd.push_back(CMD_EAT); - } } else if (item.base_type == OBJ_FOOD - && you.undead_state() != US_UNDEAD - && you.species != SP_VAMPIRE) + && !you_foodless()) { tip += "\n[Shift + R-Click] Eat (e)"; cmd.push_back(CMD_EAT); @@ -512,18 +493,8 @@ bool InventoryRegion::update_tip_text(string& tip) _handle_wield_tip(tmp, cmd, "\n[Ctrl + L-Click] ", true); break; case OBJ_CORPSES: - if (you.species == SP_VAMPIRE) - { - tmp += "Drink blood (%)"; - cmd.push_back(CMD_EAT); - } - if (wielded) - { - if (you.species == SP_VAMPIRE) - tmp += "\n"; _handle_wield_tip(tmp, cmd, "\n[Ctrl + L-Click] ", true); - } break; default: tmp += "Use"; From 3edcaf686906417f0643d2208b37b4da625626ee Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Sat, 20 Apr 2019 16:04:02 -0400 Subject: [PATCH 391/864] Remove potions of blood These are no longer needed, as vampires do not drink blood in bottles anymore. --- crawl-ref/source/acquire.cc | 2 -- crawl-ref/source/dat/des/branches/swamp.des | 2 +- crawl-ref/source/dat/des/builder/alphashops.des | 2 +- crawl-ref/source/dat/des/builder/shops.des | 4 ++-- crawl-ref/source/dat/des/portals/sewer.des | 4 ++-- crawl-ref/source/dat/des/sprint/arena_sprint.des | 3 +-- .../source/dat/des/variable/grated_community.des | 2 +- crawl-ref/source/dat/descript/items.txt | 1 + crawl-ref/source/dat/descript/quotes.txt | 1 + crawl-ref/source/item-name.cc | 2 +- crawl-ref/source/item-prop.cc | 5 ++--- crawl-ref/source/item-prop.h | 2 +- crawl-ref/source/mon-gear.cc | 15 +-------------- crawl-ref/source/monster.cc | 12 ++++++------ crawl-ref/source/mutation.cc | 2 -- crawl-ref/source/ng-setup.cc | 3 --- crawl-ref/source/potion-type.h | 2 +- crawl-ref/source/rltiles/dc-item.txt | 2 +- crawl-ref/source/shopping.cc | 4 ++-- 19 files changed, 25 insertions(+), 45 deletions(-) diff --git a/crawl-ref/source/acquire.cc b/crawl-ref/source/acquire.cc index 769b2233cddb..3043c09047a8 100644 --- a/crawl-ref/source/acquire.cc +++ b/crawl-ref/source/acquire.cc @@ -415,8 +415,6 @@ static int _acquirement_food_subtype(bool /*divine*/, int& quantity) // giving more of the lower food value items if (type_wanted == FOOD_CHUNK) quantity += 2 + random2avg(10, 2); - else if (type_wanted == POT_BLOOD) - quantity = 8 + random2(5); return type_wanted; } diff --git a/crawl-ref/source/dat/des/branches/swamp.des b/crawl-ref/source/dat/des/branches/swamp.des index d15764dd40ad..72159022288c 100644 --- a/crawl-ref/source/dat/des/branches/swamp.des +++ b/crawl-ref/source/dat/des/branches/swamp.des @@ -1613,7 +1613,7 @@ ENDMAP NAME: cheibrodos_swamp_pet_leeches TAGS: no_item_gen no_monster_gen DEPTH: Swamp, !Swamp:$ -MONS: vampire ; potion of blood . long sword . robe, tyrant leech +MONS: vampire ; long sword . robe, tyrant leech KPROP: e' = no_tele_into KPROP: .21 = bloody / w:30 nothing KPROP: e = bloody diff --git a/crawl-ref/source/dat/des/builder/alphashops.des b/crawl-ref/source/dat/des/builder/alphashops.des index bc554461d0f4..c6987a0f0f85 100644 --- a/crawl-ref/source/dat/des/builder/alphashops.des +++ b/crawl-ref/source/dat/des/builder/alphashops.des @@ -67,7 +67,7 @@ elseif s == "B" then i = { "bardiche", "battleaxe", "bolt", "book of battle", "book of beasts", "book of burglary", "box of beasts", "broad axe", "pair of boots", "potion of berserk rage", - "potion of blood", "potion of brilliance", + "potion of brilliance", "scroll of blinking", "scroll of brand weapon", "manual of bows", "buckler", "boomerang" } diff --git a/crawl-ref/source/dat/des/builder/shops.des b/crawl-ref/source/dat/des/builder/shops.des index 61b6dfda31cf..0bb15165e90d 100644 --- a/crawl-ref/source/dat/des/builder/shops.des +++ b/crawl-ref/source/dat/des/builder/shops.des @@ -359,7 +359,7 @@ DEPTH: D:12-, Depths KMONS: 1 = vampire / bat KMONS: 2 = vampire / vampire mage / vampire knight KFEAT: v = general shop type:Blood suffix:Bar count:7 ; \ - w:70 potion of blood | w:10 any weapon ego:vampirism | \ + w:70 nothing | w:10 any weapon ego:vampirism | \ w:9 randbook disc:necromancy | w:1 book of annihilations SUBST: ? = 2.Y : if you.in_branch("D") then @@ -385,7 +385,7 @@ SUBST: G : YlG : "type:Evil suffix:Emporium", "type:Profane suffix:Products", : "type:Sacrilege suffix:Store", "type:Wicked suffix:Wares"}) : kfeat("s = general shop " .. shopname .. " ; \ -: potion of blood | any weapon ego:draining w:15 | any weapon ego:pain | \ +: any weapon ego:draining w:15 | any weapon ego:pain | \ : any weapon ego:vampirism | any weapon ego:chaos w:1 | demon blade w:5 | \ : demon trident w:5 | demon whip w:5 | scroll of torment | staff of death | \ : book of necromancy | book of death | book of unlife | \ diff --git a/crawl-ref/source/dat/des/portals/sewer.des b/crawl-ref/source/dat/des/portals/sewer.des index 78118ba5d864..06d1d6e20fce 100644 --- a/crawl-ref/source/dat/des/portals/sewer.des +++ b/crawl-ref/source/dat/des/portals/sewer.des @@ -724,7 +724,7 @@ KMONS: 4 = Purgy, crocodile ITEM: potion of flight / potion of agility / potion of heal wounds / \ potion of invisibility / potion of mutation / potion of degeneration /\ scroll of blinking / scroll of teleportation / scroll of fear / \ - scroll of random uselessness / ration / potion of blood / \ + scroll of random uselessness / ration / \ nothing w:140 : sewer_setup(_G) MAP @@ -852,7 +852,7 @@ KMONS: 2 = purgy, crocodile ITEM: potion of flight / potion of agility / potion of heal wounds / \ potion of invisibility / potion of mutation / potion of degeneration / \ scroll of blinking / scroll of teleportation / scroll of fear / \ - scroll of random uselessness / ration / potion of blood / \ + scroll of random uselessness / ration / \ nothing w:140 NSUBST: e = 3:* / 9:d / *:. NSUBST: 0 = 5:1 / 1:2 / *:. diff --git a/crawl-ref/source/dat/des/sprint/arena_sprint.des b/crawl-ref/source/dat/des/sprint/arena_sprint.des index b21ce43d21aa..eea0df1224c9 100644 --- a/crawl-ref/source/dat/des/sprint/arena_sprint.des +++ b/crawl-ref/source/dat/des/sprint/arena_sprint.des @@ -1096,8 +1096,7 @@ KFEAT: R = general shop type:Premium suffix:Goods use_all count:11 greed:20 ; \ potion of haste q:5 | potion of haste q:5 |\ crystal ball of energy KFEAT: J = general shop type:Miscellaneous suffix:Merchandise count:14 greed:15 use_all ; \ - ration q:20 | potion of blood q:5 | potion of blood q:5 |\ - potion of blood q:5 | potion of blood q:5 | ring of poison resistance |\ + ration q:20 | ring of poison resistance |\ ring of protection from fire | ring of protection from cold |\ ring of protection from magic | amulet of regeneration |\ amulet of the gourmand | amulet of harm | amulet of reflection |\ diff --git a/crawl-ref/source/dat/des/variable/grated_community.des b/crawl-ref/source/dat/des/variable/grated_community.des index 5e2092a80363..3b2fd43724a6 100644 --- a/crawl-ref/source/dat/des/variable/grated_community.des +++ b/crawl-ref/source/dat/des/variable/grated_community.des @@ -132,7 +132,7 @@ KMONS: 2 = generate_awake spectral hound KMONS: 3 = generate_awake spectral wolf KMONS: 4 = generate_awake spectral warg KMONS: V = vampire knight / vampire mage -KITEM: V = potion of blood / q:2 potion of blood / q:3 potion of blood, any good_item +KITEM: V = any good_item KFEAT: g = iron_grate KFEAT: _ = altar_kikubaaqudgha KFEAT: ! = fountain_blood diff --git a/crawl-ref/source/dat/descript/items.txt b/crawl-ref/source/dat/descript/items.txt index 4fdce4050715..fb0838a54774 100644 --- a/crawl-ref/source/dat/descript/items.txt +++ b/crawl-ref/source/dat/descript/items.txt @@ -664,6 +664,7 @@ potion of berserk rage A potion which can send one into an incoherent rage. %%%% +# TAG_MAJOR_VERSION == 34 potion of blood A potion containing the essence of life. diff --git a/crawl-ref/source/dat/descript/quotes.txt b/crawl-ref/source/dat/descript/quotes.txt index ea8c1bb96e9a..319c3a67cc7a 100644 --- a/crawl-ref/source/dat/descript/quotes.txt +++ b/crawl-ref/source/dat/descript/quotes.txt @@ -2085,6 +2085,7 @@ potion Being the time the potion's force should cease.” -William Shakespeare, _Romeo and Juliet_ %%%% +# TAG_MAJOR_VERSION == 34 potion of blood “Only be sure that thou eat not the blood: for the blood _is_ the life; diff --git a/crawl-ref/source/item-name.cc b/crawl-ref/source/item-name.cc index dbf59af3eb2e..8a6627149ad8 100644 --- a/crawl-ref/source/item-name.cc +++ b/crawl-ref/source/item-name.cc @@ -728,8 +728,8 @@ const char* potion_type_name(int potiontype) case POT_CURE_MUTATION: return "cure mutation"; #endif case POT_MUTATION: return "mutation"; - case POT_BLOOD: return "blood"; #if TAG_MAJOR_VERSION == 34 + case POT_BLOOD: return "blood"; case POT_BLOOD_COAGULATED: return "coagulated blood"; #endif case POT_RESISTANCE: return "resistance"; diff --git a/crawl-ref/source/item-prop.cc b/crawl-ref/source/item-prop.cc index f4b425a80538..e23286a7bbae 100644 --- a/crawl-ref/source/item-prop.cc +++ b/crawl-ref/source/item-prop.cc @@ -750,6 +750,7 @@ const set > removed_items = { OBJ_POTIONS, POT_WATER }, { OBJ_POTIONS, POT_STRONG_POISON }, { OBJ_POTIONS, POT_BLOOD_COAGULATED }, + { OBJ_POTIONS, POT_BLOOD }, { OBJ_POTIONS, POT_PORRIDGE }, { OBJ_POTIONS, POT_SLOWING }, { OBJ_POTIONS, POT_DECAY }, @@ -2242,18 +2243,16 @@ bool is_real_food(food_type food) return food < NUM_FOODS && Food_index[food] < Food_index[FOOD_UNUSED]; } -#endif bool is_blood_potion(const item_def &item) { if (item.base_type != OBJ_POTIONS) return false; return item.sub_type == POT_BLOOD -#if TAG_MAJOR_VERSION == 34 || item.sub_type == POT_BLOOD_COAGULATED -#endif ; } +#endif bool food_is_meaty(int food_type) { diff --git a/crawl-ref/source/item-prop.h b/crawl-ref/source/item-prop.h index 4c36cc2d0584..3d04f027e48a 100644 --- a/crawl-ref/source/item-prop.h +++ b/crawl-ref/source/item-prop.h @@ -195,8 +195,8 @@ bool ring_has_stackable_effect(const item_def &item) PURE; // food functions: #if TAG_MAJOR_VERSION == 34 bool is_real_food(food_type food) PURE; -#endif bool is_blood_potion(const item_def &item) PURE; +#endif bool food_is_meaty(int food_type) PURE; bool food_is_meaty(const item_def &item) PURE; int food_value(const item_def &item) PURE; diff --git a/crawl-ref/source/mon-gear.cc b/crawl-ref/source/mon-gear.cc index f6e35ca7eb79..bbe706d72214 100644 --- a/crawl-ref/source/mon-gear.cc +++ b/crawl-ref/source/mon-gear.cc @@ -172,20 +172,7 @@ static void _give_wand(monster* mon, int level) static void _give_potion(monster* mon, int level) { - if (mons_species(mon->type) == MONS_VAMPIRE - && (one_chance_in(5) || mon->type == MONS_JORY)) - { - // This handles initialization of stack timer. - const int thing_created = - items(false, OBJ_POTIONS, POT_BLOOD, level); - - if (thing_created == NON_ITEM) - return; - - mitm[thing_created].flags = ISFLAG_KNOW_TYPE; - give_specific_item(mon, thing_created); - } - else if (mons_is_unique(mon->type) && one_chance_in(4) + if (mons_is_unique(mon->type) && one_chance_in(4) && _should_give_unique_item(mon)) { const int thing_created = items(false, OBJ_POTIONS, OBJ_RANDOM, diff --git a/crawl-ref/source/monster.cc b/crawl-ref/source/monster.cc index f56b2efbbde0..79c199c5b918 100644 --- a/crawl-ref/source/monster.cc +++ b/crawl-ref/source/monster.cc @@ -5789,11 +5789,11 @@ bool monster::can_drink_potion(potion_type ptype) const case POT_CURING: case POT_HEAL_WOUNDS: return !(holiness() & (MH_NONLIVING | MH_PLANT)); - case POT_BLOOD: #if TAG_MAJOR_VERSION == 34 + case POT_BLOOD: case POT_BLOOD_COAGULATED: -#endif return mons_species() == MONS_VAMPIRE; +#endif case POT_BERSERK_RAGE: return can_go_berserk(); case POT_HASTE: @@ -5822,11 +5822,11 @@ bool monster::should_drink_potion(potion_type ptype) const || has_ench(ENCH_CONFUSION); case POT_HEAL_WOUNDS: return hit_points <= max_hit_points / 2; - case POT_BLOOD: #if TAG_MAJOR_VERSION == 34 + case POT_BLOOD: case POT_BLOOD_COAGULATED: -#endif return hit_points <= max_hit_points / 2; +#endif case POT_BERSERK_RAGE: // this implies !berserk() return !has_ench(ENCH_MIGHT) && !has_ench(ENCH_HASTE) @@ -5879,16 +5879,16 @@ bool monster::drink_potion_effect(potion_type pot_eff, bool card) simple_monster_message(*this, " is healed!"); break; - case POT_BLOOD: #if TAG_MAJOR_VERSION == 34 + case POT_BLOOD: case POT_BLOOD_COAGULATED: -#endif if (mons_species() == MONS_VAMPIRE) { heal(10 + random2avg(28, 3)); simple_monster_message(*this, " is healed!"); } break; +#endif case POT_BERSERK_RAGE: enchant_actor_with_flavour(this, this, BEAM_BERSERK); diff --git a/crawl-ref/source/mutation.cc b/crawl-ref/source/mutation.cc index 1922be3e4cbe..3426b754b540 100644 --- a/crawl-ref/source/mutation.cc +++ b/crawl-ref/source/mutation.cc @@ -794,8 +794,6 @@ static string _display_vampire_attributes() { {" ", "Alive ", "Bloodless"}, //Full Bloodless - {"Metabolism ", "fast ", "none "}, - {"Regeneration ", "fast ", "none "}, {"Stealth boost ", "none ", "major "}, diff --git a/crawl-ref/source/ng-setup.cc b/crawl-ref/source/ng-setup.cc index a45b1effd842..2e8cdfe8d08f 100644 --- a/crawl-ref/source/ng-setup.cc +++ b/crawl-ref/source/ng-setup.cc @@ -358,9 +358,6 @@ static void _give_basic_knowledge() { identify_inventory(); - // Recognisable by appearance. - you.type_ids[OBJ_POTIONS][POT_BLOOD] = true; - // Removed item types are handled in _set_removed_types_as_identified. } diff --git a/crawl-ref/source/potion-type.h b/crawl-ref/source/potion-type.h index 1b0eecc41d6b..fcf5e8b908a9 100644 --- a/crawl-ref/source/potion-type.h +++ b/crawl-ref/source/potion-type.h @@ -41,8 +41,8 @@ enum potion_type #endif POT_MUTATION, POT_RESISTANCE, - POT_BLOOD, #if TAG_MAJOR_VERSION == 34 + POT_BLOOD, POT_BLOOD_COAGULATED, #endif POT_LIGNIFY, diff --git a/crawl-ref/source/rltiles/dc-item.txt b/crawl-ref/source/rltiles/dc-item.txt index 979edf84f977..01004694e31c 100644 --- a/crawl-ref/source/rltiles/dc-item.txt +++ b/crawl-ref/source/rltiles/dc-item.txt @@ -858,8 +858,8 @@ i-berserk-rage POT_BERSERK_RAGE i-cure-mutation POT_REMOVEME8 i-mutation POT_MUTATION i-resistance POT_RESISTANCE +# Remove all blood blood when TAG_MAJOR_VERSION > 34 i-blood POT_BLOOD -# Remove coagulated blood when TAG_MAJOR_VERSION > 34 i-coagulated-blood POT_BLOOD_COAGULATED i-lignify POT_LIGNIFY # Remove beneficial mutation and update POT_ID_LAST when TAG_MAJOR_VERSION > 34 diff --git a/crawl-ref/source/shopping.cc b/crawl-ref/source/shopping.cc index 0b11ab6c3c3b..e5ec0847da37 100644 --- a/crawl-ref/source/shopping.cc +++ b/crawl-ref/source/shopping.cc @@ -513,8 +513,8 @@ unsigned int item_value(item_def item, bool ident) case POT_PORRIDGE: case POT_SLOWING: case POT_DECAY: -#endif case POT_BLOOD: +#endif case POT_DEGENERATION: valued += 10; break; @@ -823,8 +823,8 @@ bool is_worthless_consumable(const item_def &item) switch (item.sub_type) { // Blood potions are worthless because they are easy to make. - case POT_BLOOD: #if TAG_MAJOR_VERSION == 34 + case POT_BLOOD: case POT_BLOOD_COAGULATED: case POT_SLOWING: case POT_DECAY: From 8336dd52f4342aab0647777f44c279953c03a784 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Sat, 20 Apr 2019 19:26:11 -0400 Subject: [PATCH 392/864] Boolean vampire undead state Part 3 of a vampire revision. Add a new player variable to track whether a vampire is alive or bloodless. Use this in place of the non-functional hunger checks. Vampires now transition between Alive and Bloodless via abilities, Exsanguinate and Revivify. These are interruptable delays of length 5, with no MP cost, to make them tactically difficult to use. The abilities are implemented separately so that Exsanguinate can splatter some blood; it might also be desirable to allow Revivify to be done without a delay if a corpse is available. Changing blood state ends the active transformation. There is a check for exsanguinate and revivify to prevent their use in places where the resulting untransform would be lethal to the player. There are several places where undead holiness is checked because this is provided for all actors, but for players the effect takes into account vampire undead state; Vampires are always MH_EVIL. --- crawl-ref/source/ability-type.h | 2 + crawl-ref/source/ability.cc | 53 ++++++++++++++--- crawl-ref/source/chardump.cc | 17 +----- crawl-ref/source/dat/descript/ability.txt | 8 +++ crawl-ref/source/delay.cc | 59 +++++++++++++++++++ crawl-ref/source/delay.h | 48 +++++++++++++++ crawl-ref/source/food.cc | 14 +++-- crawl-ref/source/food.h | 1 + crawl-ref/source/initfile.cc | 4 +- crawl-ref/source/item-name.cc | 6 +- crawl-ref/source/melee-attack.cc | 2 +- crawl-ref/source/mutation.cc | 20 +------ crawl-ref/source/player.cc | 49 ++++++++------- crawl-ref/source/player.h | 1 + crawl-ref/source/potion.cc | 2 +- crawl-ref/source/religion.cc | 2 +- crawl-ref/source/status.cc | 7 +-- crawl-ref/source/tag-version.h | 1 + crawl-ref/source/tags.cc | 11 ++++ crawl-ref/source/transform.cc | 17 +++++- crawl-ref/source/transform.h | 1 + .../webserver/game_data/templates/game.html | 26 ++++---- 22 files changed, 249 insertions(+), 102 deletions(-) diff --git a/crawl-ref/source/ability-type.h b/crawl-ref/source/ability-type.h index 599e138898d4..9cfb839a3985 100644 --- a/crawl-ref/source/ability-type.h +++ b/crawl-ref/source/ability-type.h @@ -42,6 +42,8 @@ enum ability_type #endif // Vampires ABIL_TRAN_BAT, + ABIL_EXSANGUINATE, + ABIL_REVIVIFY, #if TAG_MAJOR_VERSION == 34 ABIL_BOTTLE_BLOOD, #endif diff --git a/crawl-ref/source/ability.cc b/crawl-ref/source/ability.cc index 6fac820f526a..e94b23a3550d 100644 --- a/crawl-ref/source/ability.cc +++ b/crawl-ref/source/ability.cc @@ -311,12 +311,16 @@ static const ability_def Ability_List[] = 0, 0, 125, 0, {fail_basis::xl, 30, 1}, abflag::breath }, { ABIL_BREATHE_STEAM, "Breathe Steam", 0, 0, 75, 0, {fail_basis::xl, 20, 1}, abflag::breath }, - { ABIL_TRAN_BAT, "Bat Form", - 2, 0, 0, 0, {fail_basis::xl, 45, 2}, abflag::starve_ok }, - { ABIL_BREATHE_ACID, "Breathe Acid", 0, 0, 125, 0, {fail_basis::xl, 30, 1}, abflag::breath }, + { ABIL_TRAN_BAT, "Bat Form", + 2, 0, 0, 0, {fail_basis::xl, 45, 2}, abflag::starve_ok }, + { ABIL_EXSANGUINATE, "Exsanguinate", + 0, 0, 0, 0, {}, abflag::delay}, + { ABIL_REVIVIFY, "Revivify", + 0, 0, 0, 0, {}, abflag::delay}, + { ABIL_FLY, "Fly", 3, 0, 100, 0, {fail_basis::xl, 42, 3}, abflag::none }, { ABIL_STOP_FLYING, "Stop Flying", 0, 0, 0, 0, {}, abflag::starve_ok }, { ABIL_DAMNATION, "Hurl Damnation", @@ -1196,8 +1200,8 @@ void no_ability_msg() mpr("You can't untransform!"); else { - ASSERT(you.hunger_state > HS_STARVING); - mpr("Sorry, you're too full to transform right now."); + ASSERT(you.vampire_alive); + mpr("Sorry, you cannot become a bat while alive."); } } else if (you.get_mutation_level(MUT_TENGU_FLIGHT) @@ -1333,6 +1337,22 @@ static bool _check_ability_possible(const ability_def& abil, bool quiet = false) return false; } } + else if ((abil.ability == ABIL_EXSANGUINATE + || abil.ability == ABIL_REVIVIFY) + && you.form != transformation::none) + { + if (feat_dangerous_for_form(transformation::none, env.grid(you.pos()))) + { + if (!quiet) + { + mprf("Becoming %s right now would cause you to %s!", + abil.ability == ABIL_EXSANGUINATE ? "bloodless" : "alive", + env.grid(you.pos()) == DNGN_LAVA ? "burn" : "drown"); + } + + return false; + } + } if ((abil.ability == ABIL_EVOKE_BERSERK || abil.ability == ABIL_TROG_BERSERK) @@ -2804,6 +2824,16 @@ static spret _do_ability(const ability_def& abil, bool fail) } break; + case ABIL_EXSANGUINATE: + fail_check(); + start_delay(5); + break; + + case ABIL_REVIVIFY: + fail_check(); + start_delay(5); + break; + case ABIL_JIYVA_CALL_JELLY: { fail_check(); @@ -3420,11 +3450,16 @@ vector your_talents(bool check_confused, bool include_unusable) _add_talent(talents, draconian_breath(you.species), check_confused); } - if (you.species == SP_VAMPIRE && you.experience_level >= 3 - && you.hunger_state <= HS_STARVING - && you.form != transformation::bat) + if (you.species == SP_VAMPIRE) { - _add_talent(talents, ABIL_TRAN_BAT, check_confused); + if (!you.vampire_alive) + { + if (you.experience_level >= 3 && you.form != transformation::bat) + _add_talent(talents, ABIL_TRAN_BAT, check_confused); + _add_talent(talents, ABIL_REVIVIFY, check_confused); + } + else + _add_talent(talents, ABIL_EXSANGUINATE, check_confused); } if (you.racial_permanent_flight() && !you.attribute[ATTR_PERM_FLIGHT]) diff --git a/crawl-ref/source/chardump.cc b/crawl-ref/source/chardump.cc index 4fc37389d889..9aace82f92bb 100644 --- a/crawl-ref/source/chardump.cc +++ b/crawl-ref/source/chardump.cc @@ -1512,27 +1512,12 @@ static const char* hunger_names[] = }; COMPILE_CHECK(ARRAYSZ(hunger_names) == HS_ENGORGED + 1); -// Must match the order of hunger_state_t enums -static const char* thirst_names[] = -{ - "bloodless", - "bloodless", - "bloodless", - "alive", - "alive", - "alive", - "alive", - "alive", - "alive", -}; -COMPILE_CHECK(ARRAYSZ(thirst_names) == HS_ENGORGED + 1); - const char *hunger_level() { ASSERT(you.hunger_state <= HS_ENGORGED); if (you.species == SP_VAMPIRE) - return thirst_names[you.hunger_state]; + return you.vampire_alive ? "alive" : "bloodless"; return hunger_names[you.hunger_state]; } diff --git a/crawl-ref/source/dat/descript/ability.txt b/crawl-ref/source/dat/descript/ability.txt index 98d4491300b8..3a3cc0ff03b0 100644 --- a/crawl-ref/source/dat/descript/ability.txt +++ b/crawl-ref/source/dat/descript/ability.txt @@ -68,6 +68,14 @@ substantially weakening melee attacks. While tranformed, any equipped weapons, armour and rings are melded, and the user becomes unable to cast spells. %%%% +Exsanguinate ability + +Remove all of your blood, transitioning to a bloodless state. +%%%% +Revivify ability + +Return to life, transitioning from bloodless to alive. +%%%% Fly ability Starts flight. During flight you can safely cross water and similar obstacles. diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc index 27796a9cb214..1744853545ec 100644 --- a/crawl-ref/source/delay.cc +++ b/crawl-ref/source/delay.cc @@ -259,6 +259,38 @@ bool ShaftSelfDelay::try_interrupt() return true; } +bool ExsanguinateDelay::try_interrupt() +{ + if (duration > 1 && !was_prompted) + { + if (!crawl_state.disables[DIS_CONFIRMATIONS] + && !yesno("Keep bloodletting?", false, 0, false)) + { + mpr("You stop emptying yourself of blood."); + return true; + } + else + was_prompted = true; + } + return false; +} + +bool RevivifyDelay::try_interrupt() +{ + if (duration > 1 && !was_prompted) + { + if (!crawl_state.disables[DIS_CONFIRMATIONS] + && !yesno("Continue your ritual?", false, 0, false)) + { + mpr("You stop revivifying."); + return true; + } + else + was_prompted = true; + } + return false; +} + void stop_delay(bool stop_stair_travel) { if (you.delay_queue.empty()) @@ -477,6 +509,16 @@ void BlurryScrollDelay::start() mprf(MSGCH_MULTITURN_ACTION, "You begin reading the scroll."); } +void ExsanguinateDelay::start() +{ + mprf(MSGCH_MULTITURN_ACTION, "You begin bloodletting."); +} + +void RevivifyDelay::start() +{ + mprf(MSGCH_MULTITURN_ACTION, "You begin the revivification ritual."); +} + command_type RunDelay::move_cmd() const { return _get_running_command(); @@ -905,6 +947,23 @@ void DescendingStairsDelay::finish() down_stairs(); } +void ExsanguinateDelay::finish() +{ + blood_spray(you.pos(), MONS_PLAYER, 10); + you.vampire_alive = false; + you.redraw_status_lights = true; + mpr("Now bloodless."); + vampire_update_transformations(); +} + +void RevivifyDelay::finish() +{ + you.vampire_alive = true; + you.redraw_status_lights = true; + mpr("Now alive."); + vampire_update_transformations(); +} + void run_macro(const char *macroname) { #ifdef CLUA_BINDINGS diff --git a/crawl-ref/source/delay.h b/crawl-ref/source/delay.h index caae361ee934..2218ead88c22 100644 --- a/crawl-ref/source/delay.h +++ b/crawl-ref/source/delay.h @@ -664,6 +664,54 @@ class BlurryScrollDelay : public Delay } }; +class ExsanguinateDelay : public Delay +{ + bool was_prompted = false; + + void start() override; + + void tick() override + { + mprf(MSGCH_MULTITURN_ACTION, "You continue bloodletting."); + } + + void finish() override; +public: + ExsanguinateDelay(int dur) : Delay(dur) + { } + + bool try_interrupt() override; + + const char* name() const override + { + return "exsanguinate"; + } +}; + +class RevivifyDelay : public Delay +{ + bool was_prompted = false; + + void start() override; + + void tick() override + { + mprf(MSGCH_MULTITURN_ACTION, "You continue your ritual."); + } + + void finish() override; +public: + RevivifyDelay(int dur) : Delay(dur) + { } + + bool try_interrupt() override; + + const char* name() const override + { + return "revivify"; + } +}; + void push_delay(shared_ptr delay); template diff --git a/crawl-ref/source/food.cc b/crawl-ref/source/food.cc index 85be812b4723..808429f03e4c 100644 --- a/crawl-ref/source/food.cc +++ b/crawl-ref/source/food.cc @@ -198,6 +198,15 @@ static string _how_hungry() return "hungry"; } +hunger_state_t calc_hunger_state() +{ + // Get new hunger state. + hunger_state_t newstate = HS_FAINTING; + while (newstate < HS_ENGORGED && you.hunger > hunger_threshold[newstate]) + newstate = (hunger_state_t)(newstate + 1); + return newstate; +} + // "initial" is true when setting the player's initial hunger state on game // start or load: in that case it's not really a change, so we suppress the // state change message and don't identify rings or stimulate Xom. @@ -209,10 +218,7 @@ bool food_change(bool initial) you.hunger = max(you_min_hunger(), you.hunger); you.hunger = min(you_max_hunger(), you.hunger); - // Get new hunger state. - hunger_state_t newstate = HS_FAINTING; - while (newstate < HS_ENGORGED && you.hunger > hunger_threshold[newstate]) - newstate = (hunger_state_t)(newstate + 1); + hunger_state_t newstate = calc_hunger_state(); if (newstate != you.hunger_state) { diff --git a/crawl-ref/source/food.h b/crawl-ref/source/food.h index f918ce588822..cc81aaa43026 100644 --- a/crawl-ref/source/food.h +++ b/crawl-ref/source/food.h @@ -53,6 +53,7 @@ bool eat_item(item_def &food); int prompt_eat_chunks(bool only_auto = false); +hunger_state_t calc_hunger_state(); bool food_change(bool initial = false); bool prompt_eat_item(int slot = -1); diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index f04728ae4522..6804b8769f4c 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -838,8 +838,8 @@ void game_options::set_default_activity_interrupts() "interrupt_jewellery_on = interrupt_armour_on", "interrupt_memorise = hp_loss, monster_attack, stat", "interrupt_butcher = interrupt_armour_on, teleport, stat", - "interrupt_bottle_blood = interrupt_butcher", - "interrupt_vampire_feed = interrupt_butcher", + "interrupt_exsanguinate = interrupt_butcher", + "interrupt_revivify = interrupt_butcher", "interrupt_multidrop = hp_loss, monster_attack, teleport, stat", "interrupt_macro = interrupt_multidrop", "interrupt_travel = interrupt_butcher, hungry, hit_monster, " diff --git a/crawl-ref/source/item-name.cc b/crawl-ref/source/item-name.cc index 8a6627149ad8..84a104ca97b6 100644 --- a/crawl-ref/source/item-name.cc +++ b/crawl-ref/source/item-name.cc @@ -3511,7 +3511,7 @@ bool is_useless_item(const item_def &item, bool temp) case POT_LIGNIFY: return you.undead_state(temp) && (you.species != SP_VAMPIRE - || temp && you.hunger_state <= HS_STARVING); + || temp && !you.vampire_alive); case POT_FLIGHT: return you.permanent_flight() @@ -3557,7 +3557,7 @@ bool is_useless_item(const item_def &item, bool temp) case AMU_RAGE: return you.undead_state(temp) && (you.species != SP_VAMPIRE - || temp && you.hunger_state <= HS_STARVING) + || temp && !you.vampire_alive) || you.species == SP_FORMICID || you.get_mutation_level(MUT_NO_ARTIFICE); @@ -3587,7 +3587,7 @@ bool is_useless_item(const item_def &item, bool temp) && you.get_mutation_level(MUT_INHIBITED_REGENERATION) > 0 && regeneration_is_inhibited()) || (temp && you.species == SP_VAMPIRE - && you.hunger_state <= HS_STARVING); + && !you.vampire_alive); #if TAG_MAJOR_VERSION == 34 case AMU_MANA_REGENERATION: diff --git a/crawl-ref/source/melee-attack.cc b/crawl-ref/source/melee-attack.cc index b1ea47fd08f7..dd8e21cd9fd3 100644 --- a/crawl-ref/source/melee-attack.cc +++ b/crawl-ref/source/melee-attack.cc @@ -3649,7 +3649,7 @@ bool melee_attack::_player_vampire_draws_blood(const monster* mon, const int dam bool melee_attack::_vamp_wants_blood_from_monster(const monster* mon) { return you.species == SP_VAMPIRE - && you.hunger_state <= HS_STARVING + && !you.vampire_alive && actor_is_susceptible_to_vampirism(*mon) && mons_has_blood(mon->type); } diff --git a/crawl-ref/source/mutation.cc b/crawl-ref/source/mutation.cc index 3426b754b540..3208aa0d33ca 100644 --- a/crawl-ref/source/mutation.cc +++ b/crawl-ref/source/mutation.cc @@ -644,7 +644,7 @@ string describe_mutations(bool drop_title) if (you.species == SP_VAMPIRE) { - if (you.hunger_state <= HS_STARVING) + if (!you.vampire_alive) result += "You do not heal naturally.\n"; else result += "Your natural rate of healing is unusually fast.\n"; @@ -766,21 +766,7 @@ static formatted_string _vampire_Ascreen_footer(bool first_page) static int _vampire_bloodlessness() { - switch (you.hunger_state) - { - case HS_ENGORGED: - case HS_VERY_FULL: - case HS_FULL: - case HS_SATIATED: - case HS_HUNGRY: - case HS_VERY_HUNGRY: - case HS_NEAR_STARVING: - return 1; - case HS_STARVING: - case HS_FAINTING: - return 2; - } - die("bad hunger state %d", you.hunger_state); + return you.vampire_alive ? 1 : 2; } static string _display_vampire_attributes() @@ -798,8 +784,6 @@ static string _display_vampire_attributes() {"Stealth boost ", "none ", "major "}, - {"Hunger costs ", "full ", "none "}, - {"\nResistances\n" "Poison resistance ", " ", "immune"}, diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index c6e6bb7417b6..87337486b46a 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -1135,7 +1135,7 @@ int player_regen() // The better-fed you are, the faster you heal. if (you.species == SP_VAMPIRE) { - if (you.hunger_state <= HS_STARVING) + if (!you.vampire_alive) rr = 0; // No regeneration for bloodless vampires. else rr += 20; // Bonus regeneration for alive vampires. @@ -1415,7 +1415,7 @@ int player_res_cold(bool calc_unid, bool temp, bool items) rc += get_form()->res_cold(); - if (you.species == SP_VAMPIRE && you.hunger_state <= HS_STARVING) + if (you.species == SP_VAMPIRE && !you.vampire_alive) rc += 2; } @@ -1558,7 +1558,7 @@ bool player_res_torment(bool random) } return get_form()->res_neg() == 3 - || you.species == SP_VAMPIRE && you.hunger_state <= HS_STARVING + || you.species == SP_VAMPIRE && !you.vampire_alive || you.petrified() #if TAG_MAJOR_VERSION == 34 || player_equip_unrand(UNRAND_ETERNAL_TORMENT) @@ -1585,7 +1585,7 @@ int player_res_poison(bool calc_unid, bool temp, bool items) case US_UNDEAD: // mummies & lichform return 3; case US_SEMI_UNDEAD: // vampire - if (you.hunger_state <= HS_STARVING) // XXX: && temp? + if (!you.vampire_alive) // XXX: && temp? return 3; break; } @@ -1806,7 +1806,7 @@ int player_prot_life(bool calc_unid, bool temp, bool items) // Hunger is temporary, true, but that's something you can control, // especially as life protection only increases the hungrier you // get. - if (you.species == SP_VAMPIRE && you.hunger_state <= HS_STARVING) + if (you.species == SP_VAMPIRE && !you.vampire_alive) pl = 3; // Same here. Your piety status, and, hence, TSO's protection, is @@ -2823,9 +2823,9 @@ void level_change(bool skip_attribute_increase) case SP_VAMPIRE: if (you.experience_level == 3) { - if (you.hunger_state > HS_STARVING) + if (you.vampire_alive) { - mprf(MSGCH_INTRINSIC_GAIN, "If you weren't so full, " + mprf(MSGCH_INTRINSIC_GAIN, "If you were bloodless " "you could now transform into a vampire bat."); } else @@ -3133,11 +3133,8 @@ int player_stealth() stealth -= STEALTH_PIP; // Bloodless vampires are stealthier. - if (you.species == SP_VAMPIRE - && (you.hunger_state <= HS_STARVING || you.form == transformation::bat)) - { + if (you.species == SP_VAMPIRE && !you.vampire_alive) stealth += STEALTH_PIP * 2; - } if (!you.airborne()) { @@ -3233,10 +3230,10 @@ static void _display_char_status(int value, const char *fmt, ...) static void _display_vampire_status() { - string msg = "At your current hunger state you "; + string msg = "At your current blood state you "; vector attrib; - if (you.hunger_state <= HS_STARVING) + if (!you.vampire_alive) { attrib.push_back("are immune to poison"); attrib.push_back("significantly resist cold"); @@ -3245,10 +3242,7 @@ static void _display_vampire_status() attrib.push_back("do not heal."); } else - { - attrib.push_back("have a fast metabolism"); attrib.push_back("heal quickly."); - } if (!attrib.empty()) { @@ -3940,7 +3934,7 @@ bool player_regenerates_hp() { if (you.has_mutation(MUT_NO_REGENERATION)) return false; - if (you.species == SP_VAMPIRE && you.hunger_state <= HS_STARVING) + if (you.species == SP_VAMPIRE && !you.vampire_alive) return false; return true; } @@ -4255,7 +4249,7 @@ void handle_player_poison(int delay) // Transforming into a form with no metabolism merely suspends the poison // but doesn't let your body get rid of it. - if (you.is_nonliving() || you.undead_state()) + if (you.is_nonliving() || (you.undead_state() && !you.vampire_alive)) return; // Other sources of immunity (Zin, staff of Olgreb) let poison dissipate. @@ -5010,6 +5004,7 @@ player::player() royal_jelly_dead = false; transform_uncancellable = false; fishtail = false; + vampire_alive = true; pet_target = MHITNOT; @@ -5434,12 +5429,10 @@ void player::banish(actor* /*agent*/, const string &who, const int power, banished_power = power; } -// For semi-undead species (Vampire!) reduce food cost for spells and abilities -// to 50% (hungry, very hungry, near starving) or zero (starving). +// Currently a no-op, previously was used for vampire hunger modifications. +// Perhaps in the fullness of time this can be removed. int calc_hunger(int food_cost) { - if (you.undead_state() == US_SEMI_UNDEAD && you.hunger_state <= HS_STARVING) - return 0; return food_cost; } @@ -5992,7 +5985,8 @@ mon_holy_type player::holiness(bool temp) const mon_holy_type holi; // Lich form takes precedence over a species' base holiness - if (undead_state(temp)) + // Alive Vampires are MH_NATURAL + if (is_lifeless_undead(temp)) holi = MH_UNDEAD; else if (species == SP_GARGOYLE) holi = MH_NONLIVING; @@ -6010,8 +6004,11 @@ mon_holy_type player::holiness(bool temp) const if (is_good_god(religion)) holi |= MH_HOLY; - if (is_evil_god(religion) || species == SP_DEMONSPAWN) + if (is_evil_god(religion) + || species == SP_DEMONSPAWN || species == SP_VAMPIRE) + { holi |= MH_EVIL; + } // possible XXX: Monsters get evil/unholy bits set on spell selection // should players? @@ -6124,7 +6121,7 @@ int player::res_rotting(bool temp) const return 1; // rottable by Zin, not by necromancy case US_SEMI_UNDEAD: - if (temp && hunger_state <= HS_STARVING) + if (temp && !you.vampire_alive) return 1; return 0; // no permanent resistance @@ -7006,7 +7003,7 @@ bool player::can_safely_mutate(bool temp) const bool player::is_lifeless_undead(bool temp) const { if (undead_state() == US_SEMI_UNDEAD) - return temp ? hunger_state <= HS_STARVING : false; + return temp ? !you.vampire_alive : false; else return undead_state(temp) != US_ALIVE; } diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h index 25f6fa184eb8..8f8f7308254f 100644 --- a/crawl-ref/source/player.h +++ b/crawl-ref/source/player.h @@ -184,6 +184,7 @@ class player : public actor bool royal_jelly_dead; bool transform_uncancellable; bool fishtail; // Merfolk fishtail transformation + bool vampire_alive; unsigned short pet_target; diff --git a/crawl-ref/source/potion.cc b/crawl-ref/source/potion.cc index 7e49c57d4df0..2333c2abeee0 100644 --- a/crawl-ref/source/potion.cc +++ b/crawl-ref/source/potion.cc @@ -655,7 +655,7 @@ class PotionBerserk : public PotionEffect bool effect(bool was_known = true, int pow = 40, bool=true) const override { - if (you.species == SP_VAMPIRE && you.hunger_state <= HS_STARVING) + if (you.species == SP_VAMPIRE && !you.vampire_alive) { mpr("You feel slightly irritated."); return false; diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index b898d5152f9d..3faae81304c4 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -3124,7 +3124,7 @@ bool player_can_join_god(god_type which_god) return false; // Fedhas hates undead, but will accept demonspawn. - if (which_god == GOD_FEDHAS && you.holiness() & MH_UNDEAD) + if (which_god == GOD_FEDHAS && you.undead_state()) return false; if (which_god == GOD_GOZAG && you.gold < gozag_service_fee()) diff --git a/crawl-ref/source/status.cc b/crawl-ref/source/status.cc index 38c7dbd28f1f..1802ca8d96fe 100644 --- a/crawl-ref/source/status.cc +++ b/crawl-ref/source/status.cc @@ -735,7 +735,7 @@ static void _describe_hunger(status_info& inf) if (you.species == SP_VAMPIRE) { - if (you.hunger_state <= HS_STARVING) + if (!you.vampire_alive) { inf.light_colour = LIGHTRED; inf.light_text = "Bloodless"; @@ -872,10 +872,7 @@ static void _describe_regen(status_info& inf) else inf.short_text = "regenerating"; - if (you.hunger_state < HS_SATIATED) - inf.short_text += " slowly"; - else - inf.short_text += " quickly"; + inf.short_text += " quickly"; } } diff --git a/crawl-ref/source/tag-version.h b/crawl-ref/source/tag-version.h index 4035324c5136..4d9b003f1bd2 100644 --- a/crawl-ref/source/tag-version.h +++ b/crawl-ref/source/tag-version.h @@ -231,6 +231,7 @@ enum tag_minor_version TAG_MINOR_GAMESEEDS, // Game seeds + rng state saved TAG_MINOR_YELLOW_DRACONIAN_RACID, // Change yellow draconians' rAcid fake mutation to a true mutation. TAG_MINOR_THROW_CONSOLIDATION, // Throwing brands consolidated + TAG_MINOR_VAMPIRE_NO_EAT, // Decouple Vampires from the food system #endif NUM_TAG_MINORS, TAG_MINOR_VERSION = NUM_TAG_MINORS - 1 diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index 5a75ec7c10f7..1d6bd6453046 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -37,6 +37,8 @@ #if TAG_MAJOR_VERSION == 34 #include "cloud.h" #include "decks.h" + #include "food.h" + #include "hunger-state-t.h" #endif #include "colour.h" #include "coordit.h" @@ -1394,6 +1396,7 @@ static void tag_construct_you(writer &th) marshallShort(th, you.hunger); marshallBoolean(th, you.fishtail); + marshallBoolean(th, you.vampire_alive); _marshall_as_int(th, you.form); CANARY; @@ -2350,6 +2353,14 @@ static void tag_read_you(reader &th) you.hp = unmarshallShort(th); you.hunger = unmarshallShort(th); you.fishtail = unmarshallBoolean(th); +#if TAG_MAJOR_VERSION == 34 + if (th.getMinorVersion() >= TAG_MINOR_VAMPIRE_NO_EAT) + you.vampire_alive = unmarshallBoolean(th); + else + you.vampire_alive = calc_hunger_state() > HS_STARVING; +#else + you.vampire_alive = unmarshallBoolean(th); +#endif #if TAG_MAJOR_VERSION == 34 if (th.getMinorVersion() < TAG_MINOR_NOME_NO_MORE) unmarshallInt(th); diff --git a/crawl-ref/source/transform.cc b/crawl-ref/source/transform.cc index 2223a92eb35d..4ddd0d7fe3ba 100644 --- a/crawl-ref/source/transform.cc +++ b/crawl-ref/source/transform.cc @@ -1552,11 +1552,11 @@ undead_form_reason lifeless_prevents_form(transformation which_trans, if (involuntary) return UFR_TOO_DEAD; // but not as a forced polymorph effect - return you.hunger_state <= HS_STARVING ? UFR_GOOD : UFR_TOO_ALIVE; + return !you.vampire_alive ? UFR_GOOD : UFR_TOO_ALIVE; } // other forms can only be entered when alive - return you.hunger_state > HS_STARVING ? UFR_GOOD : UFR_TOO_DEAD; + return you.vampire_alive ? UFR_GOOD : UFR_TOO_DEAD; } /** @@ -2101,3 +2101,16 @@ void merfolk_stop_swimming() init_player_doll(); #endif } + +void vampire_update_transformations() +{ + const undead_form_reason form_reason = lifeless_prevents_form(); + if (form_reason != UFR_GOOD && you.duration[DUR_TRANSFORMATION]) + { + print_stats(); + mprf(MSGCH_WARN, + "Your blood-%s body can't sustain your transformation.", + form_reason == UFR_TOO_DEAD ? "deprived" : "filled"); + untransform(); + } +} diff --git a/crawl-ref/source/transform.h b/crawl-ref/source/transform.h index 92bc7110384b..9d46a8631257 100644 --- a/crawl-ref/source/transform.h +++ b/crawl-ref/source/transform.h @@ -300,3 +300,4 @@ void emergency_untransform(); void merfolk_check_swimming(bool stepped = false); void merfolk_start_swimming(bool step = false); void merfolk_stop_swimming(); +void vampire_update_transformations(); diff --git a/crawl-ref/source/webserver/game_data/templates/game.html b/crawl-ref/source/webserver/game_data/templates/game.html index 7de056a473e3..4092b508a567 100644 --- a/crawl-ref/source/webserver/game_data/templates/game.html +++ b/crawl-ref/source/webserver/game_data/templates/game.html @@ -165,22 +165,20 @@
- + - - - - - - - - - - - - - + + + + + + + + + + +
FullSatiatedThirstyBloodless
AliveBloodless
Metabolismfastnormalslownone
Regenerationfastnormalslownone
Stealth boostnonenoneminormajor
Hunger costsfullfullhalvednone
Resistances
Poison resistance+immune
Cold resistance+++
Negative resistance++++++
Rot resistance++
Torment resistance+
Transformations
Bat formnoyesyesyes
Other forms / berserkyesyesnono
Regenerationfastnone
Stealth boostnonemajor
Resistances
Poison resistanceimmune
Cold resistance++
Negative resistance+++
Rot resistance+
Torment resistance+
Transformations
Bat formnoyes
Other forms / berserkyesno
From 7fb00627a50e8446569372e6afe560d5dcd25aba Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Sun, 28 Apr 2019 19:50:10 -0600 Subject: [PATCH 393/864] Give bloodless vampires the ability to regenerate, and frail Having Bloodless vampires not regenerate at all created either a tedium headache for the player or a technical headache automating the switch. After some testing and discussion it's clear that a better approach will be to inhibit regen for bloodless vampires when monsters are in LOS, coupled with some strategic costs for switching form. Bloodless is significantly stronger than Alive, outside of a few niches it is almost always advantageous to be bloodless. To balance out the two states, this commit makes bloodless Vampires frail, adding a -20% HP that stacks with mutations. A Vampire now must trade between a weaker form with lower regen but undead resists and bat form access, and a stronger form with fast regen and alive transmutations. The choice of frail over other possible downsides for bloodless was informed by a desire to not further overlap Vp with other undead. --- crawl-ref/source/delay.cc | 1 + crawl-ref/source/mutation.cc | 11 +++++-- crawl-ref/source/player.cc | 31 ++++++------------- .../webserver/game_data/templates/game.html | 2 +- 4 files changed, 19 insertions(+), 26 deletions(-) diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc index 1744853545ec..b222a454d142 100644 --- a/crawl-ref/source/delay.cc +++ b/crawl-ref/source/delay.cc @@ -952,6 +952,7 @@ void ExsanguinateDelay::finish() blood_spray(you.pos(), MONS_PLAYER, 10); you.vampire_alive = false; you.redraw_status_lights = true; + calc_hp(true); mpr("Now bloodless."); vampire_update_transformations(); } diff --git a/crawl-ref/source/mutation.cc b/crawl-ref/source/mutation.cc index 3208aa0d33ca..a4210cea9653 100644 --- a/crawl-ref/source/mutation.cc +++ b/crawl-ref/source/mutation.cc @@ -645,7 +645,10 @@ string describe_mutations(bool drop_title) if (you.species == SP_VAMPIRE) { if (!you.vampire_alive) - result += "You do not heal naturally.\n"; + { + result += "You do not regenerate when monsters are visible.\n"; + result += "You are frail without blood (-20% HP).\n"; + } else result += "Your natural rate of healing is unusually fast.\n"; } @@ -775,12 +778,14 @@ static string _display_vampire_attributes() string result; - const int lines = 12; + const int lines = 11; string column[lines][3] = { {" ", "Alive ", "Bloodless"}, //Full Bloodless - {"Regeneration ", "fast ", "none "}, + {"Regeneration ", "fast ", "none with monsters in sight"}, + + {"HP Modifier ", "none ", "-20%"}, {"Stealth boost ", "none ", "major "}, diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 87337486b46a..c563368ffbe7 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -1090,12 +1090,9 @@ static int _player_bonus_regen() // Inhibited regeneration: stops regeneration when monsters are visible bool regeneration_is_inhibited() { - switch (you.get_mutation_level(MUT_INHIBITED_REGENERATION)) + if (you.get_mutation_level(MUT_INHIBITED_REGENERATION) == 1 + || (you.species == SP_VAMPIRE && !you.vampire_alive)) { - case 0: - return false; - case 1: - { for (monster_near_iterator mi(you.pos(), LOS_NO_TRANS); mi; ++mi) { if (mons_is_threatening(**mi) @@ -1106,12 +1103,9 @@ bool regeneration_is_inhibited() return true; } } - return false; - } - default: - die("Unknown inhibited regeneration level."); - break; } + + return false; } int player_regen() @@ -1131,15 +1125,9 @@ int player_regen() // to heal. rr = max(1, rr); - // Healing depending on satiation. - // The better-fed you are, the faster you heal. - if (you.species == SP_VAMPIRE) - { - if (!you.vampire_alive) - rr = 0; // No regeneration for bloodless vampires. - else - rr += 20; // Bonus regeneration for alive vampires. - } + // Bonus regeneration for alive vampires. + if (you.species == SP_VAMPIRE && you.vampire_alive) + rr += 20; if (you.duration[DUR_COLLAPSE]) rr /= 4; @@ -3859,7 +3847,8 @@ int get_real_hp(bool trans, bool rotted) + (you.get_mutation_level(MUT_RUGGED_BROWN_SCALES) ? you.get_mutation_level(MUT_RUGGED_BROWN_SCALES) * 2 + 1 : 0) - (you.get_mutation_level(MUT_FRAIL) * 10) - - (hep_frail ? 10 : 0); + - (hep_frail ? 10 : 0) + - (!you.vampire_alive ? 20 : 0); hitp /= 100; @@ -3934,8 +3923,6 @@ bool player_regenerates_hp() { if (you.has_mutation(MUT_NO_REGENERATION)) return false; - if (you.species == SP_VAMPIRE && !you.vampire_alive) - return false; return true; } diff --git a/crawl-ref/source/webserver/game_data/templates/game.html b/crawl-ref/source/webserver/game_data/templates/game.html index 4092b508a567..921c89f05abd 100644 --- a/crawl-ref/source/webserver/game_data/templates/game.html +++ b/crawl-ref/source/webserver/game_data/templates/game.html @@ -168,7 +168,7 @@ AliveBloodless - Regenerationfastnone + Regenerationfastnone with monsters in sight Stealth boostnonemajor Resistances Poison resistanceimmune From 301a64161102602e6b63d18e9ed53f67ca2bded0 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Sun, 28 Apr 2019 21:22:23 -0600 Subject: [PATCH 394/864] Increase costs for Vampire abilities Bat Form is really strong, in part because of its spamability and low MP cost. To rein it in, this commit adds a random stat drain of 2+binomial(5, 1/2) to the form. The choice of stat drain over skill drain is largely borne of a desire to avoid more uses of Drain. A secondary reason for the choice is that mutating the undead causes stat damage, so this is a flavourful choice. To make the choice of Vampire form strategic, instead of costly in tactical situations but otherwise trivial, revivification gives one level of temporary frail. This dovetails nicely with bloodless being frail---the frailty of undeath lingers. Exsanguination keeps its delay cost, but doesn't gain any other costs. The cost is paid only to reverse the process. --- crawl-ref/source/ability.cc | 11 +++++++++++ crawl-ref/source/dat/descript/ability.txt | 9 ++++++--- crawl-ref/source/delay.cc | 2 ++ .../source/webserver/game_data/templates/game.html | 1 + 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/ability.cc b/crawl-ref/source/ability.cc index e94b23a3550d..db2e32c1c51d 100644 --- a/crawl-ref/source/ability.cc +++ b/crawl-ref/source/ability.cc @@ -776,6 +776,12 @@ const string make_cost_description(ability_type ability) if (ability == ABIL_HEAL_WOUNDS) ret += make_stringf(", Permanent MP (%d left)", get_real_mp(false)); + if (ability == ABIL_TRAN_BAT) + ret += ", Stat Drain"; + + if (ability == ABIL_REVIVIFY) + ret += ", Frailty"; + if (abil.hp_cost) ret += make_stringf(", %d HP", abil.hp_cost.cost(you.hp_max)); @@ -2816,13 +2822,18 @@ static spret _do_ability(const ability_def& abil, bool fail) return fedhas_evolve_flora(fail); case ABIL_TRAN_BAT: + { fail_check(); if (!transform(100, transformation::bat)) { crawl_state.zero_turns_taken(); return spret::abort; } + int statslost = 2 + binomial(5, 50); + for (int i = 0; i < statslost; ++i) + lose_stat(random_choose(STAT_STR, STAT_INT, STAT_DEX), 1); break; + } case ABIL_EXSANGUINATE: fail_check(); diff --git a/crawl-ref/source/dat/descript/ability.txt b/crawl-ref/source/dat/descript/ability.txt index 3a3cc0ff03b0..90e59ef689c8 100644 --- a/crawl-ref/source/dat/descript/ability.txt +++ b/crawl-ref/source/dat/descript/ability.txt @@ -63,18 +63,21 @@ is decreased by one for every creature it strikes. Bat Form ability Transforms the user into a swift-moving vampire bat, increasing evasion but -substantially weakening melee attacks. +substantially weakening melee attacks. The transformation drains the user's +attributes. While tranformed, any equipped weapons, armour and rings are melded, and the user becomes unable to cast spells. %%%% Exsanguinate ability -Remove all of your blood, transitioning to a bloodless state. +Remove all of your blood, transitioning to a bloodless state. Returning to life +costs permanent hit points. %%%% Revivify ability -Return to life, transitioning from bloodless to alive. +Return to life, transitioning from bloodless to alive. This process renders +the user temporarily frail. %%%% Fly ability diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc index b222a454d142..b9d84c604c57 100644 --- a/crawl-ref/source/delay.cc +++ b/crawl-ref/source/delay.cc @@ -49,6 +49,7 @@ #include "mon-gear.h" #include "mon-tentacle.h" #include "mon-util.h" +#include "mutation.h" #include "nearby-danger.h" #include "notes.h" #include "options.h" @@ -962,6 +963,7 @@ void RevivifyDelay::finish() you.vampire_alive = true; you.redraw_status_lights = true; mpr("Now alive."); + temp_mutate(MUT_FRAIL, "vampire revification"); vampire_update_transformations(); } diff --git a/crawl-ref/source/webserver/game_data/templates/game.html b/crawl-ref/source/webserver/game_data/templates/game.html index 921c89f05abd..8a9d30cf58bd 100644 --- a/crawl-ref/source/webserver/game_data/templates/game.html +++ b/crawl-ref/source/webserver/game_data/templates/game.html @@ -170,6 +170,7 @@ Regenerationfastnone with monsters in sight Stealth boostnonemajor + HP modifiernone-20% Resistances Poison resistanceimmune Cold resistance++ From 2bae87b6a23b9baed56ef962372c0b86960a3f42 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Sat, 11 May 2019 11:01:33 -0400 Subject: [PATCH 395/864] Update the manual for Vampires Remove references to blood bottling and blood consumption. --- crawl-ref/docs/crawl_manual.rst | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/crawl-ref/docs/crawl_manual.rst b/crawl-ref/docs/crawl_manual.rst index 3b44e9a9af50..e2dc4282dde9 100644 --- a/crawl-ref/docs/crawl_manual.rst +++ b/crawl-ref/docs/crawl_manual.rst @@ -862,11 +862,6 @@ produce a number of 'chunks', which can be eaten with the 'e' command as above. Some species are happy to eat raw meat at any time, and others cannot eat meat at all. Information on special diets is displayed on the 'A' screen. -Vampires are a special case. Members of this species can try to drink blood -directly from a fresh corpse (use the 'e' command). They can also bottle potions -of blood from corpses instead of chopping corpses into chunks with the 'c' -command. - ? Magical Scrolls ======================================== @@ -1765,17 +1760,14 @@ Vine Stalkers (VS) spells' fuel with each voracious bite. Vampires (Vp) - Vampires are another form of undead, but with a peculiarity: by consuming - fresh blood, they may become alive. A bloodless Vampire has the traits of - an undead (immunity to poisons, negative energy and torment, resistant to - damage from the cold), but cannot regain lost physical attributes or - regenerate from wounds over time - in particular, magical items or spells - which increase the rate of regeneration will not work (though divine ones - will). On the other hand, a Vampire full with blood will regenerate very - quickly, but lose all undead powers. Vampires can never starve. They can - drink from fresh corpses with the 'e' command, or can bottle blood for later - use with 'c'. Upon growing, they learn to transform into quick bats. Unlike - other undead species, they may be mutated normally at all times. + Vampires are another form of undead, but with a peculiarity they may become + alive. A bloodless Vampire has the traits of an undead (immunity to poisons, + negative energy and torment, resistant to damage from the cold), but cannot + physically regenerate when monsters are in sight and are less resilient. On + the other hand, a Vampire full with blood will regenerate very quickly, but + will lose all undead powers. Vampires can never starve. Upon growing, they + learn to transform into quick bats. Unlike other undead species, they may be + mutated normally at all times. Demigods (Dg) Demigods are mortals with some divine or angelic ancestry, however distant; From 73b976d855374ecb231438b8b6164e4dab81ebe8 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Thu, 16 May 2019 11:00:15 -0400 Subject: [PATCH 396/864] New Vampire ability icons (CanOfWorms) [Closes #1043] --- crawl-ref/source/rltiles/dc-abilities.txt | 2 ++ .../rltiles/gui/abilities/exsanguinate.png | Bin 0 -> 1189 bytes .../source/rltiles/gui/abilities/revivify.png | Bin 0 -> 1172 bytes crawl-ref/source/tilepick.cc | 4 ++++ 4 files changed, 6 insertions(+) create mode 100644 crawl-ref/source/rltiles/gui/abilities/exsanguinate.png create mode 100644 crawl-ref/source/rltiles/gui/abilities/revivify.png diff --git a/crawl-ref/source/rltiles/dc-abilities.txt b/crawl-ref/source/rltiles/dc-abilities.txt index a40d5f233148..781125faadf1 100644 --- a/crawl-ref/source/rltiles/dc-abilities.txt +++ b/crawl-ref/source/rltiles/dc-abilities.txt @@ -18,12 +18,14 @@ evoke_ratskin ABILITY_EVOKE_RATSKIN evoke_thunder ABILITY_EVOKE_THUNDER evoke_invisibility_end ABILITY_EVOKE_INVISIBILITY_END evoke_invisibility ABILITY_EVOKE_INVISIBILITY +exsanguinate ABILITY_EXSANGUINATE flight ABILITY_EVOKE_FLIGHT flight_end ABILITY_FLIGHT_END flight ABILITY_FLIGHT heal_wounds ABILITY_HEAL_WOUNDS hop ABILITY_HOP hurl_damnation ABILITY_HURL_DAMNATION +revivify ABILITY_REVIVIFY shaft_self ABILITY_SHAFT_SELF spit_poison ABILITY_SPIT_POISON stop_recall ABILITY_STOP_RECALL diff --git a/crawl-ref/source/rltiles/gui/abilities/exsanguinate.png b/crawl-ref/source/rltiles/gui/abilities/exsanguinate.png new file mode 100644 index 0000000000000000000000000000000000000000..9ad0945488f25625adf64d7bad17316c4da38c01 GIT binary patch literal 1189 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy93=&Q?(RM=#y~cMSA(WJkYY)9 z^mSxl*x1kgCy|wbftew|C&cyt|Nlph9GNg-0#Jd0fkCJcgE23YgM-5!D~8vauke)z_18`FPAp<13ki+;ni(^Q|oZiXYeMc2ITz_{-Ix%he9sl-2=yKn>*o@fAs&o=grE) zhtHiazuWP7t@q8z8nG>nXBxOO7nQOp{NK=4zNl2gc6TqwT&uFOmyrw?7!I(kk)Cox z=Oc$({fa2s2_;&M)h)YK26 z_wD*CbKN_C@o*7PuT4i|OTZZ+Q5siC<0Q0RrF`j5`{9{78`O1Qd4C^=#8&6>a0&405h Xt`L0udWoPuC_#9-`njxgN@xNAw@vauke)z_18`FPAp<13ki+GL~pO|v%Jvb1oYPg1U?{IS=9 z<#Y1_3$s(2=S2VvUyikalKY1NPnAw3~>k}pk zSzDL!nJ~=yeB~FzmBU4A7w{d}TWZ&!L+rrCgA&2)JlB?+DX}(u^j^~ZQ#U)m)lqguHn$pMamaFA&n1>~-|s#CeAU%$ z>5L5T1LwEApYwKky3EmQ=7ny*{=3fk>bT`v;nBr468nYjiuTBVJ`E~=7(8A5T-G@y GGywp|hqiM7 literal 0 HcmV?d00001 diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc index 08dcc09421c6..e7bceb543b49 100644 --- a/crawl-ref/source/tilepick.cc +++ b/crawl-ref/source/tilepick.cc @@ -3348,6 +3348,10 @@ tileidx_t tileidx_ability(const ability_type ability) // Vampires case ABIL_TRAN_BAT: return TILEG_ABILITY_BAT_FORM; + case ABIL_EXSANGUINATE: + return TILEG_ABILITY_EXSANGUINATE; + case ABIL_REVIVIFY: + return TILEG_ABILITY_REVIVIFY; // Deep Dwarves case ABIL_HEAL_WOUNDS: return TILEG_ABILITY_HEAL_WOUNDS; From 4edc0ab2af20a26fdb7d67578d1a75e7a3688e5b Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Tue, 4 Jun 2019 09:02:12 -0400 Subject: [PATCH 397/864] Revise Exsanguinate's description (Yermak) --- crawl-ref/source/dat/descript/ability.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crawl-ref/source/dat/descript/ability.txt b/crawl-ref/source/dat/descript/ability.txt index 90e59ef689c8..a767145ae6b3 100644 --- a/crawl-ref/source/dat/descript/ability.txt +++ b/crawl-ref/source/dat/descript/ability.txt @@ -71,8 +71,7 @@ user becomes unable to cast spells. %%%% Exsanguinate ability -Remove all of your blood, transitioning to a bloodless state. Returning to life -costs permanent hit points. +Remove all of your blood, transitioning to a bloodless state. %%%% Revivify ability From 0a26ff3fdf8e5433e45a5011c2e3a980a151aa11 Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 4 Jun 2019 10:38:52 -0400 Subject: [PATCH 398/864] Add shop items to seed explorer This commit also changes &y and &Y to fully (un)identify items in shops; before they only dealt with items that are identified by type. --- crawl-ref/source/dat/dlua/explorer.lua | 11 ++++++++++- crawl-ref/source/l-dgnit.cc | 8 ++++++++ crawl-ref/source/l-item.cc | 21 ++++++++++++++------- crawl-ref/source/l-libs.h | 2 ++ crawl-ref/source/scripts/seed_explorer.lua | 9 +++++++++ crawl-ref/source/wiz-item.cc | 6 ++++++ 6 files changed, 49 insertions(+), 8 deletions(-) diff --git a/crawl-ref/source/dat/dlua/explorer.lua b/crawl-ref/source/dat/dlua/explorer.lua index 7e282be893a1..9c016bf4231b 100644 --- a/crawl-ref/source/dat/dlua/explorer.lua +++ b/crawl-ref/source/dat/dlua/explorer.lua @@ -146,6 +146,14 @@ function explorer.catalog_items(pos, notable) end end end + stack = dgn.shop_inventory_at(pos.x, pos.y) + if stack ~= nil and #stack > 0 then + for i, item in ipairs(stack) do + if explorer.item_notable(item[1]) then + notable[#notable + 1] = item[1].name() .. " (cost: " .. item[2] ..")" + end + end + end end ------------------------------ @@ -183,7 +191,7 @@ end function explorer.catalog_features(pos, notable) local feat = dgn.grid(pos.x, pos.y) - if explorer.feat_interesting(dgn.feature_name(feat)) then + if explorer.feat_notable(dgn.feature_name(feat)) then notable[#notable + 1] = dgn.feature_desc_at(pos.x, pos.y, "A") end end @@ -365,6 +373,7 @@ function explorer.reset_to_defaults() "curse toe", } explorer.item_notable = explorer.item_ignore_boring + explorer.feat_notable = explorer.feat_interesting end function explorer.make_highlight(h, key, hide_empty) diff --git a/crawl-ref/source/l-dgnit.cc b/crawl-ref/source/l-dgnit.cc index b3967f50197a..8e192959ea48 100644 --- a/crawl-ref/source/l-dgnit.cc +++ b/crawl-ref/source/l-dgnit.cc @@ -67,6 +67,13 @@ static int dgn_items_at(lua_State *ls) return 1; } +static int dgn_shop_inventory_at(lua_State *ls) +{ + // TODO: this could probably be done in a way that didn't need to be dlua. + COORDS(s, 1, 2); + return lua_push_shop_items_at(ls, s); +} + static int _dgn_item_spec(lua_State *ls) { const item_list ilist = _lua_get_ilist(ls, 1); @@ -248,6 +255,7 @@ const struct luaL_reg dgn_item_dlib[] = { { "item_from_index", dgn_item_from_index }, { "items_at", dgn_items_at }, + { "shop_inventory_at", dgn_shop_inventory_at }, { "create_item", dgn_create_item }, { "item_property_remove", dgn_item_property_remove }, { "item_property_set", dgn_item_property_set }, diff --git a/crawl-ref/source/l-item.cc b/crawl-ref/source/l-item.cc index a683be2cd51c..2a215bb98ea1 100644 --- a/crawl-ref/source/l-item.cc +++ b/crawl-ref/source/l-item.cc @@ -1467,16 +1467,13 @@ static int l_item_get_items_at(lua_State *ls) return 1; } -/*** See what a shop has for sale. - * Only works when standing at a shop. - * @treturn array|nil An array of @{Item} objects or nil if not on a shop - * @function shop_inventory - */ -static int l_item_shop_inventory(lua_State *ls) +int lua_push_shop_items_at(lua_State *ls, const coord_def &s) { - shop_struct *shop = shop_at(you.pos()); + // also used in l-dgnit.cc + shop_struct *shop = shop_at(s); if (!shop) return 0; + shopping_list.refresh(); // prevent crash if called during tests lua_newtable(ls); @@ -1497,6 +1494,16 @@ static int l_item_shop_inventory(lua_State *ls) return 1; } +/*** See what a shop has for sale. + * Only works when standing at a shop. + * @treturn array|nil An array of @{Item} objects or nil if not on a shop + * @function shop_inventory + */ +static int l_item_shop_inventory(lua_State *ls) +{ + return lua_push_shop_items_at(ls, you.pos()); +} + /*** Look at the shopping list. * @treturn array|nil Array of @{Item}s on the shopping list or nil if the * shopping list is empty diff --git a/crawl-ref/source/l-libs.h b/crawl-ref/source/l-libs.h index 5969ebc5bc0e..50267ac9a9cc 100644 --- a/crawl-ref/source/l-libs.h +++ b/crawl-ref/source/l-libs.h @@ -84,3 +84,5 @@ int dgn_map_add_transform(lua_State *ls, struct monster_info; void lua_push_moninf(lua_State *ls, monster_info *mi); + +int lua_push_shop_items_at(lua_State *ls, const coord_def &s); diff --git a/crawl-ref/source/scripts/seed_explorer.lua b/crawl-ref/source/scripts/seed_explorer.lua index ea37eeb9ab83..ec6db3afc554 100644 --- a/crawl-ref/source/scripts/seed_explorer.lua +++ b/crawl-ref/source/scripts/seed_explorer.lua @@ -9,6 +9,8 @@ crawl_require('dlua/explorer.lua') -- util/fake_pty ./crawl -script seed_explorer.lua -seed 1 -cats monsters items -mon-items -artefacts -- look at D:1 for 10 random seeds: -- util/fake_pty ./crawl -script seed_explorer.lua -seed random -count 10 -depth 1 +-- find all artefacts in shops (and print all shop names): +-- util/fake_pty ./crawl -script seed_explorer.lua -seed 1 -depth all -cats features items -shops -artefacts local basic_usage = [=[ Usage: seed_explorer.lua -seed ([ ...]|[-count ]) [-depth ] [-cats [ ([ ...]|[-count ]) [-depth Date: Tue, 4 Jun 2019 12:52:56 -0400 Subject: [PATCH 399/864] Add a bit more about how to run the seed explorer in comments --- crawl-ref/source/scripts/seed_explorer.lua | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/crawl-ref/source/scripts/seed_explorer.lua b/crawl-ref/source/scripts/seed_explorer.lua index ec6db3afc554..75b2fdbb7d50 100644 --- a/crawl-ref/source/scripts/seed_explorer.lua +++ b/crawl-ref/source/scripts/seed_explorer.lua @@ -2,6 +2,11 @@ crawl_require('dlua/explorer.lua') +-- This requires a debug build to run, as well as fake_pty, which may need to +-- be built manually. It also needs a pty-based system, i.e. linux or mac. +-- make debug OR (this will be a lot faster): make profile +-- make util/fake_pty +-- -- examples. -- full catalog for a seed: -- util/fake_pty ./crawl -script seed_explorer.lua -seed 1 @@ -11,6 +16,10 @@ crawl_require('dlua/explorer.lua') -- util/fake_pty ./crawl -script seed_explorer.lua -seed random -count 10 -depth 1 -- find all artefacts in shops (and print all shop names): -- util/fake_pty ./crawl -script seed_explorer.lua -seed 1 -depth all -cats features items -shops -artefacts +-- +-- When running scripts with fake_pty, all output goes to stderr, so to +-- redirect this to a file you will need to do something like: +-- util/fake_pty ./crawl -script seed_explorer.lua -seed 1 > out.txt 2>&1 local basic_usage = [=[ Usage: seed_explorer.lua -seed ([ ...]|[-count ]) [-depth ] [-cats [ Date: Tue, 4 Jun 2019 14:37:49 -0400 Subject: [PATCH 400/864] Don't place needle traps for TRAP_RANDOM (11991 / Yermak) Possibly the result of an over-eager search & replace. --- crawl-ref/source/dungeon.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 51dd318a95d3..445ffc2fb66c 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -27,6 +27,7 @@ #include "chardump.h" #include "cloud.h" #include "coordit.h" +#include "describe.h" #include "directn.h" #include "dbg-maps.h" #include "dbg-scan.h" @@ -3247,7 +3248,7 @@ static void _place_traps() grd(ts.pos) = ts.category(); ts.prepare_ammo(); env.trap[ts.pos] = ts; - dprf("placed a trap"); + dprf("placed a %s trap", trap_name(type).c_str()); } if (player_in_branch(BRANCH_SPIDER)) @@ -5931,7 +5932,7 @@ static void _place_specific_trap(const coord_def& where, trap_spec* spec, } while (!is_regular_trap(spec_type) #if TAG_MAJOR_VERSION == 34 - || spec_type == TRAP_DART || spec_type == TRAP_GAS + || spec_type == TRAP_NEEDLE || spec_type == TRAP_GAS || spec_type == TRAP_SHADOW || spec_type == TRAP_SHADOW_DORMANT #endif || !is_valid_shaft_level() && spec_type == TRAP_SHAFT); @@ -5943,6 +5944,7 @@ static void _place_specific_trap(const coord_def& where, trap_spec* spec, grd(where) = trap_category(spec_type); t.prepare_ammo(charges); env.trap[where] = t; + dprf("placed a %s trap", trap_name(spec_type).c_str()); } /** From 581a069569a3bf049e45fe61fc8bb81d698034ef Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 4 Jun 2019 15:27:39 -0400 Subject: [PATCH 401/864] Don't let monster digging allow out-of-los casting (11945, 11969) Since 5b187de83c, monsters that cast dig do so on a movement action (the burrowing mechanism), not usually as a regular spell. In fact, I couldn't get a monster to ever cast dig normally. Therefore, no monsters ever need to cast dig out-of-los via the normal spell code, and they definitely don't need to be able to cast arbitrary spells out-of-los if they have dig. I *think* that this is a pretty old bug, and only used to trigger under fairly rare conditions; a cacodemon still couldn't cast energy beam through a wall (though it would try). However, it would work through fog as reported in 11945. What changed recently is that LRD no longer destroys walls but is still area targeted, so that in some configurations a caster could attack out of los: > # > @#2 > # A LRD caster (e.g. a cacodemon) in this position could succesfully cast LRD on the wall in the lower left, damaging the player, instead of moving. In my testing a direct LRD cast, e.g. at the wall between the player, would still cast but have no effect or messaging, so even this case would still involve some monster wasted turns. Before the LRD change I think the caster could cast LRD succesfully on this square, destroying it in the process, so the setup conditions for the bug were much less common. Hence the recent reports of this bug. --- crawl-ref/source/mon-act.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/crawl-ref/source/mon-act.cc b/crawl-ref/source/mon-act.cc index 738df0005293..0b9915c93d06 100644 --- a/crawl-ref/source/mon-act.cc +++ b/crawl-ref/source/mon-act.cc @@ -1767,8 +1767,6 @@ void handle_monster_move(monster* mons) || mons->type == MONS_TEST_SPAWNER // Slime creatures can split when offscreen. || mons->type == MONS_SLIME_CREATURE - // Let monsters who have Dig use it off-screen. - || mons->has_spell(SPELL_DIG) // Let monsters who have Awaken Earth use it off-screen. || mons->has_spell(SPELL_AWAKEN_EARTH) ) From f268315891c1cc96f69daa4c8b208891f9b1ea06 Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 4 Jun 2019 16:05:03 -0400 Subject: [PATCH 402/864] Clean up some outdated comments and a few other misc fixes. --- crawl-ref/source/dat/dlua/explorer.lua | 63 +++++++++----------------- 1 file changed, 22 insertions(+), 41 deletions(-) diff --git a/crawl-ref/source/dat/dlua/explorer.lua b/crawl-ref/source/dat/dlua/explorer.lua index 9c016bf4231b..5d952bc1b514 100644 --- a/crawl-ref/source/dat/dlua/explorer.lua +++ b/crawl-ref/source/dat/dlua/explorer.lua @@ -1,10 +1,6 @@ --- tools for seeing what's in a seed. - --- -- to use a >32bit seed, you will need to use a string here. If you use a --- -- string, `fixed_seed` is maxed at 1. --- local starting_seed = 1 -- fixed seed to start with, number or string --- local fixed_seeds = 5 -- how many fixed seeds to run? Can be 0. --- local rand_seeds = 0 -- how many random seeds to run +-- tools for seeing what's in a seed. For example use cases, see both +-- crawl-ref/source/scripts/seed_explorer.lua, and +-- crawl-ref/source/tests/seed_explorer.lua. util.namespace('explorer') @@ -33,8 +29,8 @@ explorer.generation_order = { "Dis:1", "Dis:2", "Dis:3", "Dis:4", "Dis:5", "Dis:6", "Dis:7", } +-- a useful depth preset explorer.zot_depth = 0 - for i, l in ipairs(explorer.generation_order) do if l == "Zot:5" then explorer.zot_depth = i @@ -44,10 +40,6 @@ end assert(explorer.zot_depth ~= 0) --- -- this variable determines how deep in the generation order to go --- --local max_depth = #generation_order --- local max_depth = 5 - -- TODO: generalize, allow changing? local out = function(s) if not explorer.quiet then crawl.stderr(s) end end @@ -243,15 +235,14 @@ function explorer.describe_mons(mons) force_notable = true end - -- may or may not be useful -- OOD is an indicator of builder choices, not - -- intrinsic monster quality, and it is possible for monsters to be chosen - -- as OOD that are within range, e.g. you can sometimes get the same monster - -- generating as OOD and not OOD. - -- TODO: maybe worth rethinking what counts as OOD? might be something like, - -- average spawn depth for monster in branch is greater than depth + 5. + -- may or may not ever be useful -- builder OOD is an indicator of builder + -- choices, not intrinsic monster quality, and it is possible for monsters + -- to be chosen as OOD that are within range, e.g. you can sometimes get + -- the same monster generating as OOD and not OOD at the same depth. -- if mons.has_prop("mons_is_ood") then -- feats[#feats + 1] = "builder OOD" -- end + if explorer.rare_ood(mi) then feats[#feats + 1] = "OOD" end @@ -265,7 +256,7 @@ function explorer.describe_mons(mons) if explorer.mons_feat_filter then feats = util.map(explorer.mons_feat_filter, feats) end - -- the `item:` prefix is really only there for filtering purposes + -- the `item:` prefix is really only there for filtering purposes, remove it feats = util.map(function (s) return s:find("item:") == 1 and s:sub(6) or s end, feats) @@ -288,18 +279,6 @@ function explorer.describe_mons(mons) end end -function explorer.get_all_monsters() - local gxm, gym = dgn.max_bounds() - local mons_list = {} - for p in iter.rect_iterator(dgn.point(1,1), dgn.point(gxm-2, gym-2)) do - local mons = dgn.mons_at(p.x, p.y) - if mons then - mons_list[#mons_list + 1] = mons - end - end - return mons_list -end - function explorer.catalog_monsters_setup() wiz.identify_all_items() end @@ -351,12 +330,8 @@ explorer.catalog_names = {vaults = " Vaults: ", monsters = " Monsters: ", features = " Features: "} -function explorer.reset_to_defaults() - --explorer.mons_feat_filter = explorer.feat_in_set(util.set({ "OOD" })) - explorer.mons_feat_filter = nil - explorer.mons_notable = explorer.mons_ignore_boring - -- fairly subjective, some of these should probably be relative to depth - explorer.always_interesting_mons = util.set{ +-- fairly subjective, some of these should probably be relative to depth +explorer.dangerous_monsters = { "ancient lich", "orb of fire", "greater mummy", @@ -372,6 +347,13 @@ function explorer.reset_to_defaults() "Orb Guardian", "curse toe", } + +function explorer.reset_to_defaults() + --explorer.mons_feat_filter = explorer.feat_in_set(util.set({ "OOD" })) + explorer.mons_feat_filter = nil + explorer.mons_notable = explorer.mons_ignore_boring + + explorer.always_interesting_mons = util.set(explorer.dangerous_monsters) explorer.item_notable = explorer.item_ignore_boring explorer.feat_notable = explorer.feat_interesting end @@ -417,7 +399,6 @@ function explorer.catalog_all_positions(cats, highlights) end function explorer.catalog_current_place(lvl, to_show, hide_empty) - -- TODO: shop items highlights = {} -- setup functions and anything that doesn't require looking at positions for _, cat in ipairs(to_show) do @@ -473,14 +454,14 @@ function explorer.catalog_seed(seed, depth, cats, describe_cat) return explorer.catalog_dungeon(depth, cats) end -explorer.available_categories = { "vaults", "items", "features", "monsters" } +explorer.available_categories = { "vaults", "vaults_raw", "items", "features", "monsters" } function explorer.is_category(c) return util.set(explorer.available_categories)[c] end --- seeds is an array of seeds. If you pass numbers in with this, keep in mind +-- `seeds` is an array of seeds. If you pass numbers in with this, keep in mind -- that the max int limit is rather complicated and less than 64bits, because --- these are numbers behind the scenes. This code will accept strings of digits +-- these are doubles behind the scenes. This code will accept strings of digits -- instead, which is always safe. function explorer.catalog_seeds(seeds, depth, cats, describe_cat) if depth == nil then depth = #explorer.generation_order end From d14802f61fe331377cdde7a6b16ff36f9f13b3d6 Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Tue, 4 Jun 2019 20:32:14 +0100 Subject: [PATCH 403/864] Cap Shroud of Golubria power at 50 (#12000) Since it's only a level 2 spell and power just affects its duration rather than effectiveness. --- crawl-ref/source/spl-data.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/spl-data.h b/crawl-ref/source/spl-data.h index 78b87bf0e4ce..b4ce58c2ae8c 100644 --- a/crawl-ref/source/spl-data.h +++ b/crawl-ref/source/spl-data.h @@ -2536,7 +2536,7 @@ static const struct spell_desc spelldata[] = spschool::charms | spschool::translocation, spflag::selfench, 2, - 200, + 50, -1, -1, 2, 0, TILEG_SHROUD_OF_GOLUBRIA, From 6016cb4fb2e31835757a787c275f2815d783e5af Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Tue, 4 Jun 2019 20:44:08 +0100 Subject: [PATCH 404/864] Remove a misleading god message (#11220) Barachi being told "x welcomes you back!" when converting to a good god for the first time was supposed to be a reference to the species having originally been servants of the good gods, but is mostly more confusing than flavourful. --- crawl-ref/source/religion.cc | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index 3faae81304c4..a7ce6de99cab 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -3644,12 +3644,10 @@ void join_religion(god_type which_god) mark_milestone("god.worship", "became a worshipper of " + god_name(you.religion) + "."); take_note(Note(NOTE_GET_GOD, you.religion)); - const bool returning = you.worshipped[which_god] - || is_good_god(which_god) - && you.species == SP_BARACHI; - simple_god_message( - make_stringf(" welcomes you%s!", - returning ? " back" : "").c_str()); + + simple_god_message(make_stringf(" welcomes you%s!", + you.worshipped[which_god] ? " back" + : "").c_str()); // included in default force_more_message #ifdef DGL_WHEREIS whereis_record(); From 1d664f18495619cd5ec18ac3b5e42918df1d9d67 Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Tue, 4 Jun 2019 20:58:12 +0100 Subject: [PATCH 405/864] Mention noise in wand of iceblast description (#11902) --- crawl-ref/source/dat/descript/items.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/dat/descript/items.txt b/crawl-ref/source/dat/descript/items.txt index fb0838a54774..8dea07749143 100644 --- a/crawl-ref/source/dat/descript/items.txt +++ b/crawl-ref/source/dat/descript/items.txt @@ -1200,8 +1200,8 @@ A magical device which throws little puffs of flame. %%%% wand of iceblast -A magical device which throws exploding shards of ice, partially harming even -creatures resistant to cold. +A magical device which creates a loud explosion of ice shards, partially +harming even creatures resistant to cold. %%%% wand of paralysis From 86e7e0583bcd01d937f0eac9dddaa4486df7e55a Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Tue, 4 Jun 2019 21:00:07 +0100 Subject: [PATCH 406/864] Update easy_eat_chunks documentation (#12004) --- crawl-ref/docs/options_guide.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/crawl-ref/docs/options_guide.txt b/crawl-ref/docs/options_guide.txt index 409da1c5076a..a5944a9d6957 100644 --- a/crawl-ref/docs/options_guide.txt +++ b/crawl-ref/docs/options_guide.txt @@ -1044,7 +1044,6 @@ easy_eat_chunks = false If this is set to true then when using the (e)at command, the game will automatically determine the oldest chunk that is safe to eat, and eat it without prompting. - You will always be prompted to eat harmful chunks. auto_eat_chunks = true Setting this option to true will allow you to automatically eat a chunk From cc1054c7caed2e2e08b3be996bf1f68d14104f15 Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Tue, 4 Jun 2019 22:48:38 +0100 Subject: [PATCH 407/864] Checkwhite --- crawl-ref/source/dat/dlua/explorer.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/dat/dlua/explorer.lua b/crawl-ref/source/dat/dlua/explorer.lua index 5d952bc1b514..bc56598a6066 100644 --- a/crawl-ref/source/dat/dlua/explorer.lua +++ b/crawl-ref/source/dat/dlua/explorer.lua @@ -352,7 +352,7 @@ function explorer.reset_to_defaults() --explorer.mons_feat_filter = explorer.feat_in_set(util.set({ "OOD" })) explorer.mons_feat_filter = nil explorer.mons_notable = explorer.mons_ignore_boring - + explorer.always_interesting_mons = util.set(explorer.dangerous_monsters) explorer.item_notable = explorer.item_ignore_boring explorer.feat_notable = explorer.feat_interesting From da47cbf8c3a56b00bc71d06f4eb5fa7dc4a1203e Mon Sep 17 00:00:00 2001 From: Ashley Raine Date: Tue, 4 Jun 2019 00:43:19 +1000 Subject: [PATCH 408/864] Add missing loading images to webtiles. --- crawl-ref/source/Makefile | 5 ++++- crawl-ref/source/webserver/templates/client.html | 7 +++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/Makefile b/crawl-ref/source/Makefile index 555762b7e32c..286c2b6542e2 100644 --- a/crawl-ref/source/Makefile +++ b/crawl-ref/source/Makefile @@ -1196,7 +1196,10 @@ TITLEIMGS = denzi_dragon denzi_kitchen_duty denzi_summoner \ psiweapon_kiku white_noise_entering_the_dungeon \ white_noise_grabbing_the_orb pooryurik_knight \ psiweapon_roxanne baconkid_gastronok baconkid_mnoleg \ - peileppe_bloax_eye baconkid_duvessa_dowan + peileppe_bloax_eye baconkid_duvessa_dowan ploomutoo_ijyb \ + froggy_thunder_fist_nikola froggy_rune_and_run_failed_on_dis \ + froggy_natasha_and_boris froggy_jiyva_felid \ + froggy_goodgod_tengu_gold Cws_Minotauros STATICFILES = $(TILEIMAGEFILES:%=webserver/game_data/static/%.png) \ webserver/static/stone_soup_icon-32x32.png \ diff --git a/crawl-ref/source/webserver/templates/client.html b/crawl-ref/source/webserver/templates/client.html index 996fcc888b7a..16a387f34c40 100644 --- a/crawl-ref/source/webserver/templates/client.html +++ b/crawl-ref/source/webserver/templates/client.html @@ -207,6 +207,7 @@ + @@ -214,8 +215,14 @@ + + + + + + From b853c62f84f0777691330905ec507a2bcde68057 Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 5 Jun 2019 12:20:54 -0400 Subject: [PATCH 409/864] Seed explorer: more flexible depth args (ebering) This doesn't accept a full depth spec, but does accept level or branch names in short form. There's also now a parameter `-show` that allows only showing some levels (you provide a list), though of course it still has to generate everything before the shown levels. For example: util/fake_pty ./crawl -script seed_explorer.lua -seed random -count 10 -show Temple -cats features --- crawl-ref/source/dat/dlua/explorer.lua | 64 +++++++++++++++++----- crawl-ref/source/scripts/seed_explorer.lua | 55 +++++++++++++------ 2 files changed, 88 insertions(+), 31 deletions(-) diff --git a/crawl-ref/source/dat/dlua/explorer.lua b/crawl-ref/source/dat/dlua/explorer.lua index bc56598a6066..69426e3afc52 100644 --- a/crawl-ref/source/dat/dlua/explorer.lua +++ b/crawl-ref/source/dat/dlua/explorer.lua @@ -1,6 +1,7 @@ -- tools for seeing what's in a seed. For example use cases, see both -- crawl-ref/source/scripts/seed_explorer.lua, and -- crawl-ref/source/tests/seed_explorer.lua. +-- TODO: LDoc this util.namespace('explorer') @@ -29,15 +30,42 @@ explorer.generation_order = { "Dis:1", "Dis:2", "Dis:3", "Dis:4", "Dis:5", "Dis:6", "Dis:7", } --- a useful depth preset -explorer.zot_depth = 0 -for i, l in ipairs(explorer.generation_order) do - if l == "Zot:5" then - explorer.zot_depth = i - break +function explorer.level_to_gendepth(lvl) + -- TODO could parse l, handle things like Hell:1 + for i, l in ipairs(explorer.generation_order) do + if lvl:lower() == l:lower() then + return i + end + end + return nil +end + +function explorer.branch_to_gendepth(b) + if dgn.br_exists(b) then + local depth = dgn.br_depth(b) + if depth == 1 then + return b + else + return b .. ":" .. dgn.br_depth(b) + end end + return nil end +function explorer.to_gendepth(depth) + if type(depth) == "number" then return depth end + if depth == "all" then return #explorer.generation_order end + local num = string.match(depth, "^%d+$") + if num ~= nil then return tonumber(depth) end + local result = explorer.level_to_gendepth(depth) + if result == nil then + result = explorer.branch_to_gendepth(depth) + end + return result +end + +-- a useful depth preset +explorer.zot_depth = explorer.to_gendepth("Zot") assert(explorer.zot_depth ~= 0) -- TODO: generalize, allow changing? @@ -427,7 +455,7 @@ function explorer.catalog_current_place(lvl, to_show, hide_empty) end -- a bit redundant with mapstat? -function explorer.catalog_dungeon(max_depth, to_show) +function explorer.catalog_dungeon(max_depth, cats_to_show, show_level_fun) local result = {} dgn.reset_level() debug.flush_map_memory() @@ -437,13 +465,18 @@ function explorer.catalog_dungeon(max_depth, to_show) if (dgn.br_exists(string.match(lvl, "[^:]+"))) then debug.goto_place(lvl) debug.generate_level() - result[lvl] = explorer.catalog_current_place(lvl, to_show, true) + local old_quiet = explorer.quiet + if show_level_fun ~= nil and not show_level_fun(i) then + explorer.quiet = true + end + result[lvl] = explorer.catalog_current_place(lvl, cats_to_show, true) + explorer.quiet = old_quiet end end return result end -function explorer.catalog_seed(seed, depth, cats, describe_cat) +function explorer.catalog_seed(seed, depth, cats, show_level_fun, describe_cat) seed_used = debug.reset_rng(seed) if describe_cat then out(describe_cat(seed)) @@ -451,29 +484,32 @@ function explorer.catalog_seed(seed, depth, cats, describe_cat) out("Catalog for seed " .. seed .. " (" .. table.concat(cats, ", ") .. "):") end - return explorer.catalog_dungeon(depth, cats) + return explorer.catalog_dungeon(depth, cats, show_level_fun) end -explorer.available_categories = { "vaults", "vaults_raw", "items", "features", "monsters" } +explorer.internal_categories = { "vaults_raw" } +explorer.available_categories = { "vaults", "items", "features", "monsters" } function explorer.is_category(c) - return util.set(explorer.available_categories)[c] + return util.set(explorer.available_categories)[c] or + util.set(explorer.internal_categories)[c] end -- `seeds` is an array of seeds. If you pass numbers in with this, keep in mind -- that the max int limit is rather complicated and less than 64bits, because -- these are doubles behind the scenes. This code will accept strings of digits -- instead, which is always safe. -function explorer.catalog_seeds(seeds, depth, cats, describe_cat) +function explorer.catalog_seeds(seeds, depth, cats, show_level_fun, describe_cat) if depth == nil then depth = #explorer.generation_order end if cats == nil then cats = util.set(explorer.available_cats) end for _, i in ipairs(seeds) do if _ > 1 then out("") end -- generates a newline for stderr output - explorer.catalog_seed(i, depth, cats, describe_cat) + explorer.catalog_seed(i, depth, cats, show_level_fun, describe_cat) end end +-- example custom catalog function function explorer.catalog_arts(seeds, depth) explorer.item_notable = explorer.arts_only local run1 = explorer.catalog_dungeon(seeds, depth, { "items" }, diff --git a/crawl-ref/source/scripts/seed_explorer.lua b/crawl-ref/source/scripts/seed_explorer.lua index 75b2fdbb7d50..f87de7ebffe9 100644 --- a/crawl-ref/source/scripts/seed_explorer.lua +++ b/crawl-ref/source/scripts/seed_explorer.lua @@ -10,26 +10,39 @@ crawl_require('dlua/explorer.lua') -- examples. -- full catalog for a seed: -- util/fake_pty ./crawl -script seed_explorer.lua -seed 1 +-- -- find all artefacts in a seed: -- util/fake_pty ./crawl -script seed_explorer.lua -seed 1 -cats monsters items -mon-items -artefacts +-- -- look at D:1 for 10 random seeds: -- util/fake_pty ./crawl -script seed_explorer.lua -seed random -count 10 -depth 1 +-- -- find all artefacts in shops (and print all shop names): -- util/fake_pty ./crawl -script seed_explorer.lua -seed 1 -depth all -cats features items -shops -artefacts -- +-- show temple altars for 10 random seeds: +-- util/fake_pty ./crawl -script seed_explorer.lua -seed random -count 10 -show Temple -cats features +-- (This will need to generate all of D before getting to the temple, so is +-- somewhat slow.) +-- -- When running scripts with fake_pty, all output goes to stderr, so to -- redirect this to a file you will need to do something like: -- util/fake_pty ./crawl -script seed_explorer.lua -seed 1 > out.txt 2>&1 local basic_usage = [=[ -Usage: seed_explorer.lua -seed ([ ...]|[-count ]) [-depth ] [-cats [: either a number, or 'random'. Random values are 32 bits only. - : a number of times to iterate from . If seed is a number, this - will count up; if it is 'random' it will choose n random seeds. - Note that this converts seed values to doubles in lua, so limits - the range of possible values to some degree. - : either a number, or 'all'. Defaults to 'all'. - : a seed explorer category, drawn from: +Usage: seed_explorer.lua -seed ([ ...]|[-count ]) ([-depth ]|[-show [ ...]]) [-cats [: either a number, or 'random'. Random values are 32 bits only. + : a number of times to iterate from . If seed is a number, this + will count up; if it is 'random' it will choose n random seeds. + Note that this converts seed values to doubles in lua, so limits + the range of possible values to some degree. + : A level or branch name in short form, e.g. `Zot:5`, `Hell`, or + `D`, a number, or 'all'. If this is a number, then this value is + depth relative to the level generation order. Defaults to `all`. + : same format as , but will only show levels in the list. + Note that this doesn't affect which levels are generated, so + `-show Zot:5` will take as long to run as `-depth Zot:5`. + : a seed explorer category, drawn from: {]=] .. table.concat(explorer.available_categories, ", ") .. [[} The '-cats' list defaults to all categories. @@ -112,14 +125,9 @@ end local max_depth = nil if args["-depth"] ~= nil then - max_depth = one_arg(args, "-depth") - if max_depth == "all" then - max_depth = nil - else - max_depth = tonumber(max_depth) - if max_depth == nil then - usage_error("\n must be a number or 'all'!") - end + max_depth = explorer.to_gendepth(one_arg(args, "-depth")) + if max_depth == nil then + usage_error("\n must be level name/branch, a number, or 'all'!") end end @@ -135,6 +143,19 @@ if #categories == 0 then usage_error("\nNo valid categories specified!") end +local show_level_fun = nil + +if args["-show"] ~= nil then + local levels_to_show = util.map(explorer.to_gendepth, args["-show"]) + if #levels_to_show == 0 then + usage_error("\nNo valid levels or depths provided with -show!") + end + table.sort(levels_to_show) + if max_depth == nil then max_depth = levels_to_show[#levels_to_show] end + local levels_set = util.set(levels_to_show) + show_level_fun = function (l) return levels_set[l] end +end + if max_depth == nil then max_depth = #explorer.generation_order end @@ -168,5 +189,5 @@ if mon_items_only then end if all_mons then explorer.mons_notable = function (x) return true end end -explorer.catalog_seeds(seed_seq, max_depth, categories) +explorer.catalog_seeds(seed_seq, max_depth, categories, show_level_fun) explorer.reset_to_defaults() From 4df2b1290f6c90cc34ad383aca0ad1a346e6e6e3 Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 5 Jun 2019 14:48:18 -0400 Subject: [PATCH 410/864] Fix the build --- crawl-ref/source/dat/dlua/explorer.lua | 4 ++-- crawl-ref/source/scripts/seed_explorer.lua | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/dat/dlua/explorer.lua b/crawl-ref/source/dat/dlua/explorer.lua index 69426e3afc52..55cd8a8ef761 100644 --- a/crawl-ref/source/dat/dlua/explorer.lua +++ b/crawl-ref/source/dat/dlua/explorer.lua @@ -44,9 +44,9 @@ function explorer.branch_to_gendepth(b) if dgn.br_exists(b) then local depth = dgn.br_depth(b) if depth == 1 then - return b + return explorer.level_to_gendepth(b) else - return b .. ":" .. dgn.br_depth(b) + return explorer.level_to_gendepth(b .. ":" .. depth) end end return nil diff --git a/crawl-ref/source/scripts/seed_explorer.lua b/crawl-ref/source/scripts/seed_explorer.lua index f87de7ebffe9..8c61375dad69 100644 --- a/crawl-ref/source/scripts/seed_explorer.lua +++ b/crawl-ref/source/scripts/seed_explorer.lua @@ -41,7 +41,7 @@ Usage: seed_explorer.lua -seed ([ ...]|[-count ]) ([-depth : same format as , but will only show levels in the list. Note that this doesn't affect which levels are generated, so - `-show Zot:5` will take as long to run as `-depth Zot:5`. + `-show Zot:5` will take as long to run as `-depth Zot:5`. : a seed explorer category, drawn from: {]=] .. table.concat(explorer.available_categories, ", ") .. [[} From e138f7edaffdfdf69abc3e24ef26858bb61c66eb Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Wed, 5 Jun 2019 19:12:10 -0400 Subject: [PATCH 411/864] Update CREDITS --- crawl-ref/CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/CREDITS.txt b/crawl-ref/CREDITS.txt index e38fd80f21ad..029dd3c4e923 100644 --- a/crawl-ref/CREDITS.txt +++ b/crawl-ref/CREDITS.txt @@ -259,6 +259,7 @@ Iago Porto psywombats pubby + Ashley Elizabeth Raine Edward Randtke Derek Ray RealzHS From 536fa389852456007f5ef24e380b3f9b88161934 Mon Sep 17 00:00:00 2001 From: Edgar Bering Date: Thu, 6 Jun 2019 15:51:58 -0400 Subject: [PATCH 412/864] Nerf silver throwables Increasing the base damage by 30%, with throwing damage scaling, and combined with penetration and silver bonus damage made silver throwables overpowered (as feared in the initial commit). This commit tones them down; silver throwables now get max(vorpal bonus, silver bonus) bonus damage after the standard base damage, making them more consistent with other brands. --- crawl-ref/source/ranged-attack.cc | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/crawl-ref/source/ranged-attack.cc b/crawl-ref/source/ranged-attack.cc index a874815043ab..1f17860a2623 100644 --- a/crawl-ref/source/ranged-attack.cc +++ b/crawl-ref/source/ranged-attack.cc @@ -340,14 +340,6 @@ int ranged_attack::weapon_damage() return 0; int dam = property(*projectile, PWPN_DAMAGE); - if (projectile->base_type == OBJ_MISSILES - && get_ammo_brand(*projectile) == SPMSL_SILVER) - { - if (dam) - dam = div_rand_round(dam * 13, 10); - else - dam += 2; - } if (using_weapon()) dam += property(*weapon, PWPN_DAMAGE); else if (attacker->is_player()) @@ -692,8 +684,9 @@ bool ranged_attack::apply_missile_brand() } break; case SPMSL_SILVER: - special_damage = silver_damages_victim(defender, damage_done, - special_damage_message); + special_damage = max(1 + random2(damage_done) / 3, + silver_damages_victim(defender, damage_done, + special_damage_message); break; case SPMSL_BLINDING: if (!dart_check(brand)) From 39a21864626153ac2e74109be663805e769d41f0 Mon Sep 17 00:00:00 2001 From: Edgar Bering Date: Thu, 6 Jun 2019 15:55:20 -0400 Subject: [PATCH 413/864] Make the lajatang of Order's silver consistent This is a buff to Order, giving it the same max(vorpal, silver) as silver throwables. Order is rare, it's nice for its brand to not be so niche in its targets. --- crawl-ref/source/art-func.h | 2 ++ crawl-ref/source/dat/descript/unrand.txt | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/crawl-ref/source/art-func.h b/crawl-ref/source/art-func.h index 42564442d82c..a60ed410a6c2 100644 --- a/crawl-ref/source/art-func.h +++ b/crawl-ref/source/art-func.h @@ -1067,6 +1067,8 @@ static void _ORDER_melee_effects(item_def* item, actor* attacker, mpr(msg); defender->hurt(attacker, silver_dam); } + else if (dam > 0) + defender->hurt(attacker, 1 + random2(dam) / 3); } } diff --git a/crawl-ref/source/dat/descript/unrand.txt b/crawl-ref/source/dat/descript/unrand.txt index 3458ad9c3d33..12e83ee3f401 100644 --- a/crawl-ref/source/dat/descript/unrand.txt +++ b/crawl-ref/source/dat/descript/unrand.txt @@ -593,6 +593,10 @@ lajatang of Order A silver-bladed lajatang, once bestowed upon a favoured worshipper of Zin. It became the most prized weapon of the many priests of Zin. After their order was destroyed, it fell into disuse and vanished from history. + +It deals increased damage compared to a normal lajatang and substantially +increased damage to chaotic and magically transformed beings. It also inflicts +extra damage against mutated beings, according to how mutated they are. %%%% great mace "Firestarter" From 6d73c25c485060c63d18a87116c834595ccf27ae Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 6 Jun 2019 16:47:30 -0400 Subject: [PATCH 414/864] parens --- crawl-ref/source/ranged-attack.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/ranged-attack.cc b/crawl-ref/source/ranged-attack.cc index 1f17860a2623..a8d199298106 100644 --- a/crawl-ref/source/ranged-attack.cc +++ b/crawl-ref/source/ranged-attack.cc @@ -686,7 +686,7 @@ bool ranged_attack::apply_missile_brand() case SPMSL_SILVER: special_damage = max(1 + random2(damage_done) / 3, silver_damages_victim(defender, damage_done, - special_damage_message); + special_damage_message)); break; case SPMSL_BLINDING: if (!dart_check(brand)) From 56ce5178b7792111908b30c5f0eac0cd6719ffff Mon Sep 17 00:00:00 2001 From: Edgar Bering Date: Fri, 7 Jun 2019 20:14:29 -0400 Subject: [PATCH 415/864] Update default runrest stops for tweaked shaft messaging (vt) --- crawl-ref/source/dat/defaults/runrest_messages.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/dat/defaults/runrest_messages.txt b/crawl-ref/source/dat/defaults/runrest_messages.txt index 9f406ee25c40..794e6accb756 100644 --- a/crawl-ref/source/dat/defaults/runrest_messages.txt +++ b/crawl-ref/source/dat/defaults/runrest_messages.txt @@ -30,7 +30,7 @@ stop += emerges from the mists of memory ignore += You found a web! stop += found.*trap stop += You have blundered into a Zot trap -stop += You fall through a shaft +stop += You (are sucked|fall) into a shaft and drop stop += A sentinel's mark forms upon you\. # Enchantments From 1cce26a4d2aeb039577d182fa4b3e861c5779127 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sun, 9 Jun 2019 15:27:37 +0800 Subject: [PATCH 416/864] Fix dispersal trap not appearing in help/search The lookup-help system searches by feature name, and the stash tracker menu builder adds feature tiles by matching against the feature name. This misspelling caused dispersal traps to be absent from the lookup-help system, and a black tile to be shown instead of the correct tile in stash search. Other menus, such as the ctrl-x menu, weren't affected. --- crawl-ref/source/feature-data.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/feature-data.h b/crawl-ref/source/feature-data.h index 3cac055b026a..b80e7b015dc9 100644 --- a/crawl-ref/source/feature-data.h +++ b/crawl-ref/source/feature-data.h @@ -257,7 +257,7 @@ static feature_def feat_defs[] = } TRAP(DNGN_TRAP_MECHANICAL, "mechanical trap", "trap_mechanical", LIGHTCYAN), -TRAP(DNGN_TRAP_DISPERSAL, "disperal trap", "trap_dispersal", MAGENTA), +TRAP(DNGN_TRAP_DISPERSAL, "dispersal trap", "trap_dispersal", MAGENTA), TRAP(DNGN_TRAP_TELEPORT, "teleport trap", "trap_teleport", LIGHTBLUE), #if TAG_MAJOR_VERSION == 34 TRAP(DNGN_TRAP_SHADOW, "shadow trap", "trap_shadow", BLUE), From 9fa23b7c36003af211486deac1dbd86252a82bf1 Mon Sep 17 00:00:00 2001 From: Ashley Raine Date: Sun, 9 Jun 2019 00:59:40 +1000 Subject: [PATCH 417/864] Removed barehanded attack prompt while in treeform --- crawl-ref/source/fight.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc index c2b7df5905ca..9da4e72a7c90 100644 --- a/crawl-ref/source/fight.cc +++ b/crawl-ref/source/fight.cc @@ -619,10 +619,11 @@ bool wielded_weapon_check(item_def *weapon) return true; } - // Don't pester the player if they're using UC or if they don't have any - // melee weapons yet. + // Don't pester the player if they're using UC, in treeform, + // or if they don't have any melee weapons yet. if (!weapon && (you.skill(SK_UNARMED_COMBAT) > 0 + || you.form == transformation::tree || !any_of(you.inv.begin(), you.inv.end(), [](item_def &it) { return is_melee_weapon(it) && can_wield(&it); }))) From f7c4f17b881ee0622d999cd7b38a624fe47f5c43 Mon Sep 17 00:00:00 2001 From: NormalPerson7 <37064413+NormalPerson7@users.noreply.github.com> Date: Sun, 9 Jun 2019 17:10:05 +0100 Subject: [PATCH 418/864] Fix incorrect information in Aura of Brilliance description --- crawl-ref/source/dat/descript/spells.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crawl-ref/source/dat/descript/spells.txt b/crawl-ref/source/dat/descript/spells.txt index 9410d85a2b1d..d5e8edfa2846 100644 --- a/crawl-ref/source/dat/descript/spells.txt +++ b/crawl-ref/source/dat/descript/spells.txt @@ -55,9 +55,7 @@ This reduces their remaining time before being sent back where they came from. Aura of Brilliance spell Empowers the magic of nearby wizard allies of the caster, allowing them to -cast their magic more powerfully and more often, but at the price of fixing -the caster in place until they no longer have any nearby allies they can -empower. +cast their magic more powerfully and more often. %%%% Avatar Song spell From 24607be9ceed5a777259880ab54529f7683426c4 Mon Sep 17 00:00:00 2001 From: dplusplus Date: Mon, 10 Jun 2019 17:14:30 +0900 Subject: [PATCH 419/864] Fix hint for item description Commit 2b1cce4 introduced negated logic. [Closes #1082] --- crawl-ref/source/hints.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/hints.cc b/crawl-ref/source/hints.cc index eb8c46ccd816..c10f20436024 100644 --- a/crawl-ref/source/hints.cc +++ b/crawl-ref/source/hints.cc @@ -2933,7 +2933,7 @@ static string _hints_throw_stuff(const item_def &item) string result; result = "To do this, type % to fire, then "; - if (!item.slot) + if (item.slot) { result += ""; result += item.slot; From 6863ae89ae894713ca5896c2a71917be9d779783 Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Tue, 11 Jun 2019 19:08:59 +0100 Subject: [PATCH 420/864] Don't allow Vehumet to extend lightning rod range (#12007) --- crawl-ref/source/spl-util.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/spl-util.cc b/crawl-ref/source/spl-util.cc index 24c9159da630..cdf8f6690a17 100644 --- a/crawl-ref/source/spl-util.cc +++ b/crawl-ref/source/spl-util.cc @@ -957,7 +957,8 @@ int spell_range(spell_type spell, int pow, bool allow_bonus) && vehumet_supports_spell(spell) && have_passive(passive_t::spells_range) && maxrange > 1 - && spell != SPELL_GLACIATE) + && spell != SPELL_GLACIATE + && spell != SPELL_THUNDERBOLT) // lightning rod only { maxrange++; minrange++; From 9eff3895ba7dd8150099ade026dff9683b788b19 Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 11 Jun 2019 16:43:56 -0400 Subject: [PATCH 421/864] Optimize find_maps_for_tag somewhat This gets about 10x speedup on overflow temple selection (on a non-optimized build). It's still not great (since the overflow selection code is pretty insane, could be as many as 300 calls to find_maps_for_tag in my testing), but now according to my profiling the bottleneck isn't the use of set, but rather the construction of an iterator for each has_tag. It's worth noting that 99% of the calls to map_def::has_tag in the codebase have a single tag, and don't need this complexity. However, for typical uses I didn't see any obvious gain from optimizing them. --- crawl-ref/source/maps.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/maps.cc b/crawl-ref/source/maps.cc index 4d0adce313dc..d6d2bc242804 100644 --- a/crawl-ref/source/maps.cc +++ b/crawl-ref/source/maps.cc @@ -730,10 +730,11 @@ mapref_vector find_maps_for_tag(const string &tag, { mapref_vector maps; level_id place = level_id::current(); + set tag_set = parse_tags(tag); for (const map_def &mapdef : vdefs) { - if (mapdef.has_tag(tag) + if (mapdef.has_tag(tag_set) && !mapdef.has_tag("dummy") && (!check_depth || !mapdef.has_depth() || mapdef.is_usable_in(place)) From 6870c0f642a59e20eb89d29cbef1f1888c74325b Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 12 Jun 2019 14:08:02 -0400 Subject: [PATCH 422/864] Rewrite overflow vault selection code The old version brute-force searched through every 2-3 god combination among the gods selected for overflow vaults, with a somewhat indirect and complicated stopping criteria (with a goto, even) and a call to `find_maps_for_tag` for every combination it reached before the stopping condition. This is a huge search space and even with the stopping criteria it would still consider hundreds to thousands of combinations. On the other hand there are less than 20 vaults *total* that this code could even find. This rewrite flips things, and searches through the temple_overflow_n vaults themselves for compatible vaults rather than the space of god combinations. It's *much* faster. I expect this will change some seeds, since the order of rolls before was determined by bitvector order, and this will be determined by vault list order; also, where there are multiple vaults with the same god tags the weight calculation is different in this implementation. However, in my testing the results have been basically the same for most seeds. This code probably is biased towards 2-altar vaults over 3-altar vaults as is. --- crawl-ref/source/ng-init.cc | 118 ++++++++++++++++++++++++------------ 1 file changed, 79 insertions(+), 39 deletions(-) diff --git a/crawl-ref/source/ng-init.cc b/crawl-ref/source/ng-init.cc index c00510e02a88..a555d21655bb 100644 --- a/crawl-ref/source/ng-init.cc +++ b/crawl-ref/source/ng-init.cc @@ -268,58 +268,98 @@ void initialise_temples() overflow_weights[i] = 0; } - // Try to find combinations of overflow gods that have specialised - // overflow vaults. -multi_overflow: - for (unsigned int i = 1, size = 1 << overflow_gods.size(); - i <= size; i++) + // Check for temple_overflow vaults that specify certain gods. + mapref_vector maps; + // the >1 range is based on previous code; 1-altar temple_overflow maps + // are placed by the next part, though their weight is not used here. There + // are currently no such vaults with more than 3 altars, but there's not + // much cost to checking a few higher. + for (int num = 2; num <= 5; num++) { - unsigned int num = count_bits(i); - - // TODO: possibly make this place single-god vaults too? - // XXX: upper limit on num here because this code gets really - // slow otherwise. - if (num <= 1 || num > 3) - continue; + mapref_vector num_maps = find_maps_for_tag( + make_stringf("temple_overflow_%d", num)); + maps.insert(maps.end(), num_maps.begin(), num_maps.end()); + } + for (const map_def *map : maps) + { + if (overflow_gods.size() < 2) + break; + int num = 0; vector this_temple_gods; - vector new_overflow_gods; - - string tags = make_stringf("temple_overflow_%d", num); - for (unsigned int j = 0; j < overflow_gods.size(); j++) + for (auto &tag : map->get_tags()) { - if (i & (1 << j)) + if (!starts_with(tag, "temple_overflow_")) + continue; + string temple_tag = tag_without_prefix(tag, "temple_overflow_"); + if (temple_tag.empty()) { - string name = replace_all(god_name(overflow_gods[j]), " ", "_"); - lowercase(name); - tags = tags + " temple_overflow_" + name; - this_temple_gods.push_back(overflow_gods[j]); + mprf(MSGCH_ERROR, "Malformed temple tag '%s' in map %s", + tag.c_str(), map->name.c_str()); + continue; } + int test_num; + if (parse_int(temple_tag.c_str(), test_num)) + num = test_num; else - new_overflow_gods.push_back(overflow_gods[j]); + { + replace(temple_tag.begin(), temple_tag.end(), '_', ' '); + god_type this_god = str_to_god(temple_tag); + if (this_god == GOD_NO_GOD) + { + mprf(MSGCH_ERROR, "Malformed temple tag '%s' in map %s", + tag.c_str(), map->name.c_str()); + continue; + } + this_temple_gods.push_back(this_god); + } + if (num == 0) + { + if (this_temple_gods.size() > 0) + { + mprf(MSGCH_ERROR, + "Map %s has temple_overflow_god tags but no count tag", + map->name.c_str()); + } + continue; + } } - - mapref_vector maps = find_maps_for_tag(tags); - if (maps.empty()) + // there is one vault that currently triggers this, where it allows + // one of two specified gods on a particular altar. This code won't + // handle (or error) on that case right now. + if (num != this_temple_gods.size()) continue; - if (overflow_weights[num] > 0) - { - int chance = 0; - for (auto map : maps) + // does this temple place only gods that we need to place? + bool ok = true; + for (auto god : this_temple_gods) + if (count(overflow_gods.begin(), overflow_gods.end(), god) == 0) { - chance += map->weight(level_id(BRANCH_DUNGEON, - MAX_OVERFLOW_LEVEL)); + ok = false; + break; } - if (!x_chance_in_y(chance, overflow_weights[num] + chance)) - continue; + if (!ok) + continue; + // finally: this overflow vault will place a subset of our current + // overflow list. Do we actually place it? + // TODO: The weight calculation here is kind of odd, though based on + // what it is directly replacing. It should sum all compatible + // maps first. But, the end result of this choice isn't a map anyways... + // More generally, I wonder if this list should be shuffled before this + // step, so that it's not prioritizing smaller vaults? + int chance = map->weight(level_id(BRANCH_DUNGEON, + MAX_OVERFLOW_LEVEL)); + if (x_chance_in_y(chance, overflow_weights[num] + chance)) + { + vector new_overflow_gods; + for (auto god : overflow_gods) + if (count(this_temple_gods.begin(), this_temple_gods.end(), god) == 0) + new_overflow_gods.push_back(god); + fprintf(stderr,"Overflow temple with tags '%s'\n", map->tags_string().c_str()); + _use_overflow_temple(this_temple_gods); + + overflow_gods = new_overflow_gods; } - - _use_overflow_temple(this_temple_gods); - - overflow_gods = new_overflow_gods; - - goto multi_overflow; } // NOTE: The overflow temples don't have to contain only one From 8bd77c7716bc7dd9114f72706bf2a3cc3e02398b Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 12 Jun 2019 17:51:18 -0400 Subject: [PATCH 423/864] Remove debug code --- crawl-ref/source/ng-init.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/crawl-ref/source/ng-init.cc b/crawl-ref/source/ng-init.cc index a555d21655bb..f49ad7bcaf93 100644 --- a/crawl-ref/source/ng-init.cc +++ b/crawl-ref/source/ng-init.cc @@ -355,7 +355,6 @@ void initialise_temples() for (auto god : overflow_gods) if (count(this_temple_gods.begin(), this_temple_gods.end(), god) == 0) new_overflow_gods.push_back(god); - fprintf(stderr,"Overflow temple with tags '%s'\n", map->tags_string().c_str()); _use_overflow_temple(this_temple_gods); overflow_gods = new_overflow_gods; From d84787c25e2f9f72cff14660d829f0f50344051b Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 12 Jun 2019 17:52:37 -0400 Subject: [PATCH 424/864] Simplify has_tag somewhat The vast majority of calls to this involved just a single tag. This gets called a *lot* during levelgen, so it was slowing down a full pregen run noticeably (as much as 10%). Even this change makes a big difference, though it is still not extremely optimized. `has_tag` itself is still not very fast because of the use of `set`. --- crawl-ref/source/mapdef.cc | 11 ++++++++--- crawl-ref/source/mapdef.h | 5 +++-- crawl-ref/source/maps.cc | 4 ++-- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc index 808abc205419..a048ec18dfdf 100644 --- a/crawl-ref/source/mapdef.cc +++ b/crawl-ref/source/mapdef.cc @@ -3245,7 +3245,7 @@ void map_def::fixup() } } -bool map_def::has_tag(const set &tagswanted) const +bool map_def::has_tags(const set &tagswanted) const { if (tags.empty() || tagswanted.size() == 0) return false; @@ -3257,9 +3257,14 @@ bool map_def::has_tag(const set &tagswanted) const return true; } -bool map_def::has_tag(const string &tagswanted) const +bool map_def::has_tags(const string &tagswanted) const { - return has_tag(parse_tags(tagswanted)); + return has_tags(parse_tags(tagswanted)); +} + +bool map_def::has_tag(const string &tagwanted) const +{ + return tags.count(tagwanted) > 0; } bool map_def::has_tag_prefix(const string &prefix) const diff --git a/crawl-ref/source/mapdef.h b/crawl-ref/source/mapdef.h index fd71f3b4978e..cc285cc13b85 100644 --- a/crawl-ref/source/mapdef.h +++ b/crawl-ref/source/mapdef.h @@ -1247,8 +1247,9 @@ class map_def bool is_minivault() const; bool is_overwritable_layout() const; - bool has_tag(const string &tagswanted) const; - bool has_tag(const set &tagswanted) const; + bool has_tag(const string &tagwanted) const; + bool has_tags(const string &tagswanted) const; + bool has_tags(const set &tagswanted) const; bool has_tag_prefix(const string &tag) const; bool has_tag_suffix(const string &suffix) const; diff --git a/crawl-ref/source/maps.cc b/crawl-ref/source/maps.cc index d6d2bc242804..b63f4c56ee5e 100644 --- a/crawl-ref/source/maps.cc +++ b/crawl-ref/source/maps.cc @@ -734,7 +734,7 @@ mapref_vector find_maps_for_tag(const string &tag, for (const map_def &mapdef : vdefs) { - if (mapdef.has_tag(tag_set) + if (mapdef.has_tags(tag_set) && !mapdef.has_tag("dummy") && (!check_depth || !mapdef.has_depth() || mapdef.is_usable_in(place)) @@ -888,7 +888,7 @@ bool map_selector::accept(const map_def &mapdef) const } case TAG: - return mapdef.has_tag(tag) + return mapdef.has_tags(tag) // allow multiple tags, for temple overflow vaults && (!check_depth || !mapdef.has_depth() || mapdef.is_usable_in(place)) From cdd7612e187f008c7fb57380d02f9002f1dda8df Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 12 Jun 2019 18:27:12 -0400 Subject: [PATCH 425/864] Disable pattern matching against levelgen output On a debug build, this was the heaviest single code path after luaV_execute itself, and this output consists entirely of debug output that should be hidden anyways. If someone had a use case for leaving these enabled I can try to come up with other solutions, but right now I'm not seeing anything crucial. --- crawl-ref/source/message.cc | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/message.cc b/crawl-ref/source/message.cc index 8c2206f0903e..d00fcff7e908 100644 --- a/crawl-ref/source/message.cc +++ b/crawl-ref/source/message.cc @@ -1231,6 +1231,8 @@ static bool _updating_view = false; static bool _check_option(const string& line, msg_channel_type channel, const vector& option) { + if (crawl_state.generating_level) + return false; return any_of(begin(option), end(option), bind(mem_fn(&message_filter::is_filtered), @@ -1598,6 +1600,8 @@ static void mpr_check_patterns(const string& message, msg_channel_type channel, int param) { + if (crawl_state.generating_level) + return; for (const text_pattern &pat : Options.note_messages) { if (channel == MSGCH_EQUIPMENT || channel == MSGCH_FLOOR_ITEMS @@ -1655,12 +1659,15 @@ static msg_colour_type prepare_message(const string& imsg, if (colour != MSGCOL_MUTED) mpr_check_patterns(imsg, channel, param); - for (const message_colour_mapping &mcm : Options.message_colour_mappings) + if (!crawl_state.generating_level) { - if (mcm.message.is_filtered(channel, imsg)) + for (const message_colour_mapping &mcm : Options.message_colour_mappings) { - colour = mcm.colour; - break; + if (mcm.message.is_filtered(channel, imsg)) + { + colour = mcm.colour; + break; + } } } From 19b5fbe486af1fe7362e26186ead090dfe8fd877 Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 12 Jun 2019 19:09:11 -0400 Subject: [PATCH 426/864] Remove a redundant call Or at least I think it's redundant; it's called by load_level already, and I didn't spot any ill effects from removing it. --- crawl-ref/source/startup.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index dbc1055f35a7..cdba10ad06c4 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -421,7 +421,6 @@ static void _post_init(bool newc) ash_check_bondage(false); trackers_init_new_level(false); - tile_new_level(newc); if (newc) // start a new game { From 83a80d79a6b2f3a75d4e0e8e10ebcfc599bdeb79 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Wed, 12 Jun 2019 21:45:19 -0500 Subject: [PATCH 427/864] Fix missing item result delimiters in some vaults --- crawl-ref/source/dat/des/branches/vaults_rooms_ghost.des | 2 +- crawl-ref/source/dat/des/variable/ghost.des | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/dat/des/branches/vaults_rooms_ghost.des b/crawl-ref/source/dat/des/branches/vaults_rooms_ghost.des index 0218d63b45d8..b59f10bce25c 100644 --- a/crawl-ref/source/dat/des/branches/vaults_rooms_ghost.des +++ b/crawl-ref/source/dat/des/branches/vaults_rooms_ghost.des @@ -183,7 +183,7 @@ KITEM: P = robe cursed plus:-8 randart ident:all ITEM: quick blade good_item w:5 / rapier good_item / scimitar good_item / \ double sword good_item w:5 / demon blade good_item w:5 / \ triple sword good_item w:5 / morningstar good_item / \ - eveningstar good_item w:5 / demon whip good_item w:5 \ + eveningstar good_item w:5 / demon whip good_item w:5 / \ dire flail good_item / great mace good_item / broad axe good_item / \ battleaxe good_item / executioner's axe good_item w:5 / \ demon trident good_item w:5 / glaive good_item / \ diff --git a/crawl-ref/source/dat/des/variable/ghost.des b/crawl-ref/source/dat/des/variable/ghost.des index 3139c29a1225..e0ce59fd4353 100644 --- a/crawl-ref/source/dat/des/variable/ghost.des +++ b/crawl-ref/source/dat/des/variable/ghost.des @@ -812,7 +812,7 @@ KITEM: P = robe cursed plus:-8 randart ident:all ITEM: quick blade good_item w:5 / rapier good_item / scimitar good_item / \ double sword good_item w:5 / demon blade good_item w:5 / \ triple sword good_item w:5 / morningstar good_item / \ - eveningstar good_item w:5 / demon whip good_item w:5 \ + eveningstar good_item w:5 / demon whip good_item w:5 / \ dire flail good_item / great mace good_item / broad axe good_item / \ battleaxe good_item / executioner's axe good_item w:5 / \ demon trident good_item w:5 / glaive good_item / \ From 4608c8fa30f5c8063f613531f00ac7098e0d3f2c Mon Sep 17 00:00:00 2001 From: gammafunk Date: Wed, 12 Jun 2019 21:46:21 -0500 Subject: [PATCH 428/864] Use an existing item list for a vault Use the existing lists we have for aux armour in the dgn lua lib, since manually specifying these in vaults is error-prone. --- crawl-ref/source/dat/des/variable/ghost.des | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/dat/des/variable/ghost.des b/crawl-ref/source/dat/des/variable/ghost.des index e0ce59fd4353..9db25944a6f7 100644 --- a/crawl-ref/source/dat/des/variable/ghost.des +++ b/crawl-ref/source/dat/des/variable/ghost.des @@ -1078,9 +1078,8 @@ ENDMAP NAME: biasface_ghost_orc_armoury DEPTH: D:3-, Orc -ITEM: pair of boots / helmet / hat / pair of gloves / cloak -ITEM: pair of boots good_item / helmet good_item / hat good_item / \ - pair of gloves good_item / cloak good_item +:item(dgn.aux_armour) +:item(dgn.good_aux_armour) ITEM: any armour, any armour good_item, any weapon, any weapon good_item ITEM: any jewellery, any jewellery good_item KMONS: O = player ghost From 69c6a515889aeba157edda37645545cfa0bf5006 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 13 Jun 2019 09:43:07 -0400 Subject: [PATCH 429/864] Fix signed/unsigned comparison (gammafunk) --- crawl-ref/source/ng-init.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/ng-init.cc b/crawl-ref/source/ng-init.cc index f49ad7bcaf93..a7b388361021 100644 --- a/crawl-ref/source/ng-init.cc +++ b/crawl-ref/source/ng-init.cc @@ -285,7 +285,7 @@ void initialise_temples() { if (overflow_gods.size() < 2) break; - int num = 0; + unsigned int num = 0; vector this_temple_gods; for (auto &tag : map->get_tags()) { @@ -299,7 +299,7 @@ void initialise_temples() continue; } int test_num; - if (parse_int(temple_tag.c_str(), test_num)) + if (parse_int(temple_tag.c_str(), test_num) && test_num > 0) num = test_num; else { From 80c1907ebbf68b0f6e40264dfb70bfa6b7c4ed38 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 13 Jun 2019 11:40:59 -0400 Subject: [PATCH 430/864] Use unordered_set for tags, instead of set f1fd2d0243764f converted the tags API and internal representation from pure strings (that got split every access) into sets, to deal with order issues that were leading to seed divergence. However, it turns out that `has_tag` is called many, many more times than a sorted tag list is ever needed, and since `set` usually uses something like a binary tree internally, the costs of a search were substantially outweighing any gains from storing the tags in a sorted form. This commit converts to using unordered_set for better lookup time, which cuts about 50% of the time spent checking for tags. On a fulldebug build, this shaves at least 1s off a typical total pregen time. There is probably more to be gained as even with this change, the `count` call in has_tag is *still* about 1s total over a full pregen run. I've also slightly clarified some function names in this API. The cost of `get_tags` is negligable, about 1ms total. --- crawl-ref/source/dungeon.cc | 21 +++++++++++---------- crawl-ref/source/libutil.cc | 6 +++--- crawl-ref/source/libutil.h | 3 ++- crawl-ref/source/mapdef.cc | 30 ++++++++++++++---------------- crawl-ref/source/mapdef.h | 20 ++++++++++++++++---- crawl-ref/source/maps.cc | 6 +++--- crawl-ref/source/ng-init.cc | 4 ++-- 7 files changed, 51 insertions(+), 39 deletions(-) diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 445ffc2fb66c..97f3f9a77b5e 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -684,7 +684,7 @@ static void _set_grd(const coord_def &c, dungeon_feature_type feat) grd(c) = feat; } -static void _dgn_register_vault(const string &name, const set &tags) +static void _dgn_register_vault(const string &name, const unordered_set &tags) { if (!tags.count("allow_dup")) you.uniq_map_names.insert(name); @@ -692,7 +692,10 @@ static void _dgn_register_vault(const string &name, const set &tags) if (tags.count("luniq")) env.level_uniq_maps.insert(name); - for (const string &tag : tags) + vector sorted_tags(tags.begin(), tags.end()); + sort(sorted_tags.begin(), sorted_tags.end()); + + for (const string &tag : sorted_tags) { if (starts_with(tag, "uniq_")) you.uniq_map_tags.insert(tag); @@ -703,7 +706,7 @@ static void _dgn_register_vault(const string &name, const set &tags) static void _dgn_register_vault(const map_def &map) { - _dgn_register_vault(map.name, map.get_tags()); + _dgn_register_vault(map.name, map.get_tags_unsorted()); } static void _dgn_register_vault(const string &name, string &spaced_tags) @@ -716,7 +719,7 @@ static void _dgn_unregister_vault(const map_def &map) you.uniq_map_names.erase(map.name); env.level_uniq_maps.erase(map.name); - for (const string &tag : map.get_tags()) + for (const string &tag : map.get_tags_unsorted()) { if (starts_with(tag, "uniq_")) you.uniq_map_tags.erase(tag); @@ -1065,9 +1068,7 @@ dgn_register_place(const vault_placement &place, bool register_vault) } // Find tags matching properties. - set tags = place.map.get_tags(); - - for (const auto &tag : tags) + for (const auto &tag : place.map.get_tags_unsorted()) { const feature_property_type prop = str_to_fprop(tag); if (prop == FPROP_NONE) @@ -2567,9 +2568,9 @@ static bool _vault_can_use_layout(const map_def *vault, const map_def *layout) ASSERT(layout->has_tag_prefix("layout_type_")); - const set tags = layout->get_tags(); - - for (auto &tag : tags) + // in principle, tag order can matter here, even though that is probably + // a vault designer error + for (const auto &tag : layout->get_tags()) { if (starts_with(tag, "layout_type_")) { diff --git a/crawl-ref/source/libutil.cc b/crawl-ref/source/libutil.cc index f1b8f749e78f..e224154cb2de 100644 --- a/crawl-ref/source/libutil.cc +++ b/crawl-ref/source/libutil.cc @@ -218,11 +218,11 @@ int strip_number_tag(string &s, const string &tagprefix) return x; } -set parse_tags(const string &tags) +unordered_set parse_tags(const string &tags) { vector split_tags = split_string(" ", tags); - set ordered_tags(split_tags.begin(), split_tags.end()); - return ordered_tags; + unordered_set tags_set(split_tags.begin(), split_tags.end()); + return tags_set; } bool parse_int(const char *s, int &i) diff --git a/crawl-ref/source/libutil.h b/crawl-ref/source/libutil.h index 4dc603089d6d..aa3bfea89ddd 100644 --- a/crawl-ref/source/libutil.h +++ b/crawl-ref/source/libutil.h @@ -9,6 +9,7 @@ #include #include #include +#include #include "enum.h" @@ -74,7 +75,7 @@ int strip_number_tag(string &s, const string &tagprefix); vector strip_multiple_tag_prefix(string &s, const string &tagprefix); string strip_tag_prefix(string &s, const string &tagprefix); const string tag_without_prefix(const string &s, const string &tagprefix); -set parse_tags(const string &tags); +unordered_set parse_tags(const string &tags); bool parse_int(const char *s, int &i); // String 'descriptions' diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc index a048ec18dfdf..4bfb99d50776 100644 --- a/crawl-ref/source/mapdef.cc +++ b/crawl-ref/source/mapdef.cc @@ -2732,7 +2732,7 @@ string map_def::validate_map_placeable() // Ok, the map wants to be placed by tag. In this case it should have // at least one tag that's not a map flag. bool has_selectable_tag = false; - for (const string &piece : get_tags()) + for (const string &piece : tags) { if (_map_tag_is_selectable(piece)) { @@ -3245,21 +3245,10 @@ void map_def::fixup() } } -bool map_def::has_tags(const set &tagswanted) const +bool map_def::has_all_tags(const string &tagswanted) const { - if (tags.empty() || tagswanted.size() == 0) - return false; - - for (const string &tag : tagswanted) - if (!tags.count(tag)) - return false; - - return true; -} - -bool map_def::has_tags(const string &tagswanted) const -{ - return has_tags(parse_tags(tagswanted)); + const auto &tags_set = parse_tags(tagswanted); + return has_all_tags(tags_set.begin(), tags_set.end()); } bool map_def::has_tag(const string &tagwanted) const @@ -3287,11 +3276,20 @@ bool map_def::has_tag_suffix(const string &suffix) const return false; } -const set map_def::get_tags() const +const unordered_set map_def::get_tags_unsorted() const { return tags; } +const vector map_def::get_tags() const +{ + // this might seem inefficient, but get_tags is not called very much; the + // hotspot revealed by profiling is actually has_tag checks. + vector result(tags.begin(), tags.end()); + sort(result.begin(), result.end()); + return result; +} + void map_def::add_tags(const string &tag) { auto parsed_tags = parse_tags(tag); diff --git a/crawl-ref/source/mapdef.h b/crawl-ref/source/mapdef.h index cc285cc13b85..de7ba151563e 100644 --- a/crawl-ref/source/mapdef.h +++ b/crawl-ref/source/mapdef.h @@ -17,6 +17,7 @@ #include #include #include +#include #include "dlua.h" #include "enum.h" @@ -1151,7 +1152,7 @@ class map_def vector subvault_places; private: - set tags; + unordered_set tags; // This map has been loaded from an index, and not fully realised. bool index_only; mutable long cache_offset; @@ -1248,11 +1249,21 @@ class map_def bool is_minivault() const; bool is_overwritable_layout() const; bool has_tag(const string &tagwanted) const; - bool has_tags(const string &tagswanted) const; - bool has_tags(const set &tagswanted) const; bool has_tag_prefix(const string &tag) const; bool has_tag_suffix(const string &suffix) const; + template + bool has_all_tags(TagIterator begin, TagIterator end) const + { + if (tags.empty() || begin == end) // legacy behavior for empty case + return false; + for ( ; begin != end; ++begin) + if (!has_tag(*begin)) + return false; + return true; + } + bool has_all_tags(const string &tagswanted) const; + template bool has_any_tag(TagIterator begin, TagIterator end) const { @@ -1262,7 +1273,8 @@ class map_def return false; } - const set get_tags() const; + const vector get_tags() const; + const unordered_set get_tags_unsorted() const; void add_tags(const string &tag); void set_tags(const string &tag); bool remove_tags(const string &tag); diff --git a/crawl-ref/source/maps.cc b/crawl-ref/source/maps.cc index b63f4c56ee5e..a77e161e4361 100644 --- a/crawl-ref/source/maps.cc +++ b/crawl-ref/source/maps.cc @@ -730,11 +730,11 @@ mapref_vector find_maps_for_tag(const string &tag, { mapref_vector maps; level_id place = level_id::current(); - set tag_set = parse_tags(tag); + unordered_set tag_set = parse_tags(tag); for (const map_def &mapdef : vdefs) { - if (mapdef.has_tags(tag_set) + if (mapdef.has_all_tags(tag_set.begin(), tag_set.end()) && !mapdef.has_tag("dummy") && (!check_depth || !mapdef.has_depth() || mapdef.is_usable_in(place)) @@ -888,7 +888,7 @@ bool map_selector::accept(const map_def &mapdef) const } case TAG: - return mapdef.has_tags(tag) // allow multiple tags, for temple overflow vaults + return mapdef.has_all_tags(tag) // allow multiple tags, for temple overflow vaults && (!check_depth || !mapdef.has_depth() || mapdef.is_usable_in(place)) diff --git a/crawl-ref/source/ng-init.cc b/crawl-ref/source/ng-init.cc index a7b388361021..1b79920a6cfb 100644 --- a/crawl-ref/source/ng-init.cc +++ b/crawl-ref/source/ng-init.cc @@ -142,7 +142,7 @@ void initialise_temples() if (main_temple->has_tag("temple_variable")) { vector sizes; - for (auto &tag : main_temple->get_tags()) + for (const auto &tag : main_temple->get_tags()) { if (starts_with(tag, "temple_altars_")) { @@ -287,7 +287,7 @@ void initialise_temples() break; unsigned int num = 0; vector this_temple_gods; - for (auto &tag : map->get_tags()) + for (const auto &tag : map->get_tags()) { if (!starts_with(tag, "temple_overflow_")) continue; From 90a09432193dd52c236996eb77dd7d186a63129c Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 13 Jun 2019 13:39:05 -0400 Subject: [PATCH 431/864] Cache the top three vault tags as bools These tags account for >50% of the `has_tag` calls, which over the course of a full pregeneration run really adds up -- this is nearly 5000000 calls for `has_tag`. This change shaves about 0.5s off a full (non-optimized) pregen run. This commit also adds some (disabled) profiling stuff for tags. For reference here's the call count for the top 7 tags, everything lower than this is <1%: 208774 ( 2%): vaults_empty 208774 ( 2%): vaults_room 439758 ( 5%): layout 550983 ( 6%): place_unique 1150916 (14%): overwritable 1243580 (15%): extra 2554449 (31%): minivault Total: 8144269 --- crawl-ref/source/abyss.cc | 2 +- crawl-ref/source/ctest.cc | 5 +++ crawl-ref/source/dungeon.cc | 8 ++--- crawl-ref/source/mapdef.cc | 66 +++++++++++++++++++++++++++++++++++-- crawl-ref/source/mapdef.h | 14 ++++++++ crawl-ref/source/maps.cc | 6 ++-- 6 files changed, 90 insertions(+), 11 deletions(-) diff --git a/crawl-ref/source/abyss.cc b/crawl-ref/source/abyss.cc index 8fe32805690f..42b6e196960a 100644 --- a/crawl-ref/source/abyss.cc +++ b/crawl-ref/source/abyss.cc @@ -1378,7 +1378,7 @@ static int _abyss_place_vaults(const map_bitmask &abyss_genlevel_mask) const map_def *map = random_map_in_depth(level_id::current(), extra); if (map) { - if (_abyss_place_map(map) && !map->has_tag("extra")) + if (_abyss_place_map(map) && !map->is_extra_vault()) { extra = true; diff --git a/crawl-ref/source/ctest.cc b/crawl-ref/source/ctest.cc index 500e1e3e0b15..84c032426e73 100644 --- a/crawl-ref/source/ctest.cc +++ b/crawl-ref/source/ctest.cc @@ -30,6 +30,7 @@ #include "item-name.h" #include "jobs.h" #include "libutil.h" +#include "mapdef.h" #include "maps.h" #include "message.h" #include "mon-pick.h" @@ -214,6 +215,10 @@ void run_tests() } } +#ifdef DEBUG_TAG_PROFILING + tag_profile_out(); +#endif + if (crawl_state.test_list) end(0); cio_cleanup(); diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 97f3f9a77b5e..e32ae2632391 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -1139,7 +1139,7 @@ dgn_register_place(const vault_placement &place, bool register_vault) vault_placement *new_vault_place = new vault_placement(place); env.level_vaults.emplace_back(new_vault_place); if (register_vault) - _remember_vault_placement(place, place.map.has_tag("extra")); + _remember_vault_placement(place, place.map.is_extra_vault()); return new_vault_place; } @@ -1156,7 +1156,7 @@ static bool _dgn_ensure_vault_placed(bool vault_success, static bool _ensure_vault_placed_ex(bool vault_success, const map_def *vault) { return _dgn_ensure_vault_placed(vault_success, - (!vault->has_tag("extra") + (!vault->is_extra_vault() && vault->orient == MAP_ENCOMPASS)); } @@ -3161,7 +3161,7 @@ static void _place_minivaults() if (vault) _build_secondary_vault(vault); } // if ALL maps eligible are "extra" but fail to place, we'd be screwed - while (vault && vault->has_tag("extra") && tries++ < 10000); + while (vault && vault->is_extra_vault() && tries++ < 10000); } } @@ -3541,7 +3541,7 @@ static void _place_extra_vaults() if (_build_secondary_vault(vault)) { const map_def &map(*vault); - if (map.has_tag("extra")) + if (map.is_extra_vault()) continue; use_random_maps = false; } diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc index 4bfb99d50776..ee811fdafe2e 100644 --- a/crawl-ref/source/mapdef.cc +++ b/crawl-ref/source/mapdef.cc @@ -47,6 +47,36 @@ #include "tiledef-dngn.h" #include "tiledef-player.h" +#ifdef DEBUG_TAG_PROFILING +static map _tag_profile; + +static void _profile_inc_tag(const string &tag) +{ + if (!_tag_profile.count(tag)) + _tag_profile[tag] = 0; + _tag_profile[tag]++; +} + +void tag_profile_out() +{ + long total = 0; + vector> resort; + fprintf(stderr, "\nTag hits:\n"); + for (auto k : _tag_profile) + { + resort.emplace_back(k.second, k.first); + total += k.second; + } + sort(resort.begin(), resort.end()); + for (auto p : resort) + { + long percent = ((long) p.first) * 100 / total; + fprintf(stderr, "%8d (%2ld%%): %s\n", p.first, percent, p.second.c_str()); + } + fprintf(stderr, "Total: %ld\n", total); +} +#endif + static const char *map_section_names[] = { "", @@ -2172,7 +2202,8 @@ map_def::map_def() rock_colour(BLACK), floor_colour(BLACK), rock_tile(""), floor_tile(""), border_fill_type(DNGN_ROCK_WALL), tags(), - index_only(false), cache_offset(0L), validating_map_flag(false) + index_only(false), cache_offset(0L), validating_map_flag(false), + cache_minivault(false), cache_overwritable(false), cache_extra(false) { init(); } @@ -2231,6 +2262,7 @@ void map_def::reinit() mons.clear(); feat_renames.clear(); subvault_places.clear(); + update_cached_tags(); } bool map_def::map_already_used() const @@ -2933,16 +2965,37 @@ bool map_def::has_depth() const return !depths.empty(); } +void map_def::update_cached_tags() +{ + cache_minivault = has_tag("minivault"); + cache_overwritable = has_tag("overwritable"); + cache_extra = has_tag("extra"); +} + bool map_def::is_minivault() const { - return has_tag("minivault"); +#ifdef DEBUG_TAG_PROFILING + ASSERT(cache_minivault == has_tag("minivault")); +#endif + return cache_minivault; } // Returns true if the map is a layout that allows other vaults to be // built on it. bool map_def::is_overwritable_layout() const { - return has_tag("overwritable"); +#ifdef DEBUG_TAG_PROFILING + ASSERT(cache_overwritable == has_tag("overwritable")); +#endif + return cache_overwritable; +} + +bool map_def::is_extra_vault() const +{ +#ifdef DEBUG_TAG_PROFILING + ASSERT(cache_extra == has_tag("extra")); +#endif + return cache_extra; } // Tries to dock a floating vault - push it to one edge of the level. @@ -3253,6 +3306,9 @@ bool map_def::has_all_tags(const string &tagswanted) const bool map_def::has_tag(const string &tagwanted) const { +#ifdef DEBUG_TAG_PROFILING + _profile_inc_tag(tagwanted); +#endif return tags.count(tagwanted) > 0; } @@ -3294,6 +3350,7 @@ void map_def::add_tags(const string &tag) { auto parsed_tags = parse_tags(tag); tags.insert(parsed_tags.begin(), parsed_tags.end()); + update_cached_tags(); } bool map_def::remove_tags(const string &tag) @@ -3302,18 +3359,21 @@ bool map_def::remove_tags(const string &tag) auto parsed_tags = parse_tags(tag); for (auto &t : parsed_tags) removed = tags.erase(t) || removed; // would iterator overload be ok? + update_cached_tags(); return removed; } void map_def::clear_tags() { tags.clear(); + update_cached_tags(); } void map_def::set_tags(const string &tag) { clear_tags(); add_tags(tag); + update_cached_tags(); } string map_def::tags_string() const diff --git a/crawl-ref/source/mapdef.h b/crawl-ref/source/mapdef.h index de7ba151563e..fcf87dce36a2 100644 --- a/crawl-ref/source/mapdef.h +++ b/crawl-ref/source/mapdef.h @@ -42,6 +42,10 @@ #define RANDBK_SLVLS_KEY "randbook_slevels" #define RANDBK_NSPELLS_KEY "randbook_num_spells" +#ifdef DEBUG_TAG_PROFILING +void tag_profile_out(); +#endif + class mon_enchant; extern const char *traversable_glyphs; @@ -1165,6 +1169,14 @@ class map_def // True if this map is in the process of being validated. bool validating_map_flag; + // values cached from tags -- adding to this is only recommended if you've + // actually done the profiling... + // These are the top three worst tags, which jointly amount to about 3-4% + // of levelgen time if not cached. + bool cache_minivault; + bool cache_overwritable; + bool cache_extra; + public: map_def(); @@ -1248,6 +1260,7 @@ class map_def bool is_minivault() const; bool is_overwritable_layout() const; + bool is_extra_vault() const; bool has_tag(const string &tagwanted) const; bool has_tag_prefix(const string &tag) const; bool has_tag_suffix(const string &suffix) const; @@ -1327,6 +1340,7 @@ class map_def string apply_subvault(string_spec &); string validate_map_placeable(); bool has_exit() const; + void update_cached_tags(); }; const int CHANCE_ROLL = 10000; diff --git a/crawl-ref/source/maps.cc b/crawl-ref/source/maps.cc index a77e161e4361..90c0a597587f 100644 --- a/crawl-ref/source/maps.cc +++ b/crawl-ref/source/maps.cc @@ -861,7 +861,7 @@ bool map_selector::accept(const map_def &mapdef) const return false; } return mapdef.is_minivault() == mini - && _is_extra_compatible(extra, mapdef.has_tag("extra")) + && _is_extra_compatible(extra, mapdef.is_extra_vault()) && mapdef.place.is_usable_in(place) && _map_matches_layout_type(mapdef) && !mapdef.map_already_used(); @@ -870,7 +870,7 @@ bool map_selector::accept(const map_def &mapdef) const { const map_chance chance(mapdef.chance(place)); return mapdef.is_minivault() == mini - && _is_extra_compatible(extra, mapdef.has_tag("extra")) + && _is_extra_compatible(extra, mapdef.is_extra_vault()) && (!chance.valid() || mapdef.has_tag("dummy")) && depth_selectable(mapdef) && !mapdef.map_already_used(); @@ -883,7 +883,7 @@ bool map_selector::accept(const map_def &mapdef) const return chance.valid() && !mapdef.has_tag("dummy") && depth_selectable(mapdef) - && _is_extra_compatible(extra, mapdef.has_tag("extra")) + && _is_extra_compatible(extra, mapdef.is_extra_vault()) && !mapdef.map_already_used(); } From be6fa4f6cc9d141c8b089f81ecb6c984345de91c Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 13 Jun 2019 16:35:02 -0400 Subject: [PATCH 432/864] Faster starts_with implementation The previous implementation was really inefficient; this change is minor in the scale of things (about 1% of a pregen run, or 200-300ms total) but it's also a very easy fix. --- crawl-ref/source/stringutil.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/stringutil.h b/crawl-ref/source/stringutil.h index 9bbb1e290ae8..1ba46887e81d 100644 --- a/crawl-ref/source/stringutil.h +++ b/crawl-ref/source/stringutil.h @@ -224,7 +224,7 @@ string join_strings(Z start, Z end, const string &sep = " ") static inline bool starts_with(const string &s, const string &prefix) { - return s.rfind(prefix, 0) != string::npos; + return s.compare(0, prefix.size(), prefix) == 0; } static inline bool ends_with(const string &s, const string &suffix) From d57e52fea8716df6ddb9e5da0a666c01122373c1 Mon Sep 17 00:00:00 2001 From: ufshaikh Date: Fri, 14 Jun 2019 13:50:42 -0500 Subject: [PATCH 433/864] Remove possible placement of blowgun from vault (#1087) Should fix a bug where this vault places an item marked as removed. --- crawl-ref/source/dat/des/variable/arcadia.des | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/dat/des/variable/arcadia.des b/crawl-ref/source/dat/des/variable/arcadia.des index b2533d5161bf..ea4d0e848c23 100644 --- a/crawl-ref/source/dat/des/variable/arcadia.des +++ b/crawl-ref/source/dat/des/variable/arcadia.des @@ -36,7 +36,7 @@ KMONS: N = spriggan ; robe . quarterstaff KMONS: O = dire elephant / death yak / emperor scorpion / anaconda w:5 KMONS: Q = bush KMONS: R = plant -ITEM: dagger / short sword / rapier / flail / whip / blowgun / shortbow +ITEM: dagger / short sword / rapier / flail / whip / shortbow ITEM: robe / cloak / hat / buckler / steam dragon scales w:1 ITEM: ration q:3 KFEAT: _ = altar_trog From 1ba1822a901933c9d9ee16ee0342f2572708ba75 Mon Sep 17 00:00:00 2001 From: Quinten Konyn Date: Sat, 8 Jun 2019 19:32:55 -0700 Subject: [PATCH 434/864] Add singular they pronouns for Hepliaklqana ancestors Updates Hepliaklqana ancestors to use "they" instead of "it" when selecting "neither" as their gender - implements handling for they/them pronouns and correctly conjugates applicable messages. [Squashed PR, added spacing fixes and rewrote commit message, closes #1080 - MarvinPA] --- crawl-ref/source/describe-spells.cc | 17 +++-- crawl-ref/source/describe.cc | 107 ++++++++++++++++++++-------- crawl-ref/source/directn.cc | 100 ++++++++++++++++++-------- crawl-ref/source/english.cc | 3 +- crawl-ref/source/gender-type.h | 1 + crawl-ref/source/god-abil.cc | 14 ++-- crawl-ref/source/mon-info.cc | 13 +++- crawl-ref/source/mon-info.h | 1 + 8 files changed, 183 insertions(+), 73 deletions(-) diff --git a/crawl-ref/source/describe-spells.cc b/crawl-ref/source/describe-spells.cc index 39ff6faeb559..56006d3e91c5 100644 --- a/crawl-ref/source/describe-spells.cc +++ b/crawl-ref/source/describe-spells.cc @@ -10,6 +10,7 @@ #include "cio.h" #include "delay.h" #include "describe.h" +#include "english.h" #include "externs.h" #include "invent.h" #include "libutil.h" @@ -124,16 +125,18 @@ static string _describe_spell_filtering(mon_spell_slot_flag type, const char* pr * "possesses the following natural abilities:" */ static string _booktype_header(mon_spell_slot_flag type, size_t num_books, - bool has_silencable, bool has_filtered, const char* pronoun) + bool has_silencable, bool has_filtered, + const char* pronoun, bool pronoun_plural) { const string vulnerabilities = _ability_type_vulnerabilities(type, has_silencable); - const string spell_filter_desc = has_filtered ? _describe_spell_filtering(type, pronoun) - : ""; + const string spell_filter_desc = + has_filtered ? _describe_spell_filtering(type, pronoun) : ""; if (type == MON_SPELL_WIZARD) { - return make_stringf("has mastered %s%s%s:", + return make_stringf("%s mastered %s%s%s:", + conjugate_verb("have", pronoun_plural).c_str(), num_books > 1 ? "one of the following spellbooks" : "the following spells", spell_filter_desc.c_str(), @@ -142,7 +145,8 @@ static string _booktype_header(mon_spell_slot_flag type, size_t num_books, const string descriptor = _ability_type_descriptor(type); - return make_stringf("possesses the following %s abilities%s%s:", + return make_stringf("%s the following %s abilities%s%s:", + conjugate_verb("possess", pronoun_plural).c_str(), descriptor.c_str(), spell_filter_desc.c_str(), vulnerabilities.c_str()); @@ -261,7 +265,8 @@ static void _monster_spellbooks(const monster_info &mi, uppercase_first(mi.pronoun(PRONOUN_SUBJECTIVE)) + " " + _booktype_header(type, valid_books.size(), has_silencable, - filtered_books, mi.pronoun(PRONOUN_OBJECTIVE)); + filtered_books, mi.pronoun(PRONOUN_OBJECTIVE), + mi.pronoun_plurality()); } else { diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index 2a4a23618b9e..e75cbd5353d5 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -3931,16 +3931,19 @@ static string _monster_stat_description(const monster_info& mi) } const char* pronoun = mi.pronoun(PRONOUN_SUBJECTIVE); + const bool plural = mi.pronoun_plurality(); if (mi.threat != MTHRT_UNDEF) { - result << uppercase_first(pronoun) << " looks " + result << uppercase_first(pronoun) << " " + << conjugate_verb("look", plural) << " " << _get_threat_desc(mi.threat) << ".\n"; } if (!resist_descriptions.empty()) { - result << uppercase_first(pronoun) << " is " + result << uppercase_first(pronoun) << " " + << conjugate_verb("are", plural) << " " << comma_separated_line(resist_descriptions.begin(), resist_descriptions.end(), "; and ", "; ") @@ -3950,15 +3953,17 @@ static string _monster_stat_description(const monster_info& mi) // Is monster susceptible to anything? (On a new line.) if (!suscept.empty()) { - result << uppercase_first(pronoun) << " is susceptible to " + result << uppercase_first(pronoun) << " " + << conjugate_verb("are", plural) << " susceptible to " << comma_separated_line(suscept.begin(), suscept.end()) << ".\n"; } if (mi.is(MB_CHAOTIC)) { - result << uppercase_first(pronoun) << " is vulnerable to silver and" - " hated by Zin.\n"; + result << uppercase_first(pronoun) << " " + << conjugate_verb("are", plural) + << " vulnerable to silver and hated by Zin.\n"; } if (mons_class_flag(mi.type, M_STATIONARY) @@ -3970,8 +3975,9 @@ static string _monster_stat_description(const monster_info& mi) if (mons_class_flag(mi.type, M_COLD_BLOOD) && get_resist(resist, MR_RES_COLD) <= 0) { - result << uppercase_first(pronoun) << " is cold-blooded and may be " - "slowed by cold attacks.\n"; + result << uppercase_first(pronoun) + << " " << conjugate_verb("are", plural) + << " cold-blooded and may be slowed by cold attacks.\n"; } // Seeing invisible. @@ -3980,7 +3986,11 @@ static string _monster_stat_description(const monster_info& mi) // Echolocation, wolf noses, jellies, etc if (!mons_can_be_blinded(mi.type)) - result << uppercase_first(pronoun) << " is immune to blinding.\n"; + { + result << uppercase_first(pronoun) << " " + << conjugate_verb("are", plural) + << " immune to blinding.\n"; + } // XXX: could mention "immune to dazzling" here, but that's spammy, since // it's true of such a huge number of monsters. (undead, statues, plants). // Might be better to have some place where players can see holiness & @@ -3989,12 +3999,14 @@ static string _monster_stat_description(const monster_info& mi) if (mi.intel() <= I_BRAINLESS) { // Matters for Ely. - result << uppercase_first(pronoun) << " is mindless.\n"; + result << uppercase_first(pronoun) << " " + << conjugate_verb("are", plural) << " mindless.\n"; } else if (mi.intel() >= I_HUMAN) { // Matters for Yred, Gozag, Zin, TSO, Alistair.... - result << uppercase_first(pronoun) << " is intelligent.\n"; + result << uppercase_first(pronoun) << " " + << conjugate_verb("are", plural) << " intelligent.\n"; } // Unusual monster speed. @@ -4003,7 +4015,9 @@ static string _monster_stat_description(const monster_info& mi) if (speed != 10 && speed != 0) { did_speed = true; - result << uppercase_first(pronoun) << " is " << mi.speed_description(); + result << uppercase_first(pronoun) << " " + << conjugate_verb("are", plural) << " " + << mi.speed_description(); } const mon_energy_usage def = DEFAULT_ENERGY; if (!(mi.menergy == def)) @@ -4012,22 +4026,40 @@ static string _monster_stat_description(const monster_info& mi) vector fast, slow; if (!did_speed) result << uppercase_first(pronoun) << " "; - _add_energy_to_string(speed, me.move, "covers ground", fast, slow); + _add_energy_to_string(speed, me.move, + conjugate_verb("cover", plural) + " ground", + fast, slow); // since MOVE_ENERGY also sets me.swim if (me.swim != me.move) - _add_energy_to_string(speed, me.swim, "swims", fast, slow); - _add_energy_to_string(speed, me.attack, "attacks", fast, slow); + { + _add_energy_to_string(speed, me.swim, + conjugate_verb("swim", plural), fast, slow); + } + _add_energy_to_string(speed, me.attack, + conjugate_verb("attack", plural), fast, slow); if (mons_class_itemuse(mi.type) >= MONUSE_STARTING_EQUIPMENT) - _add_energy_to_string(speed, me.missile, "shoots", fast, slow); + { + _add_energy_to_string(speed, me.missile, + conjugate_verb("shoot", plural), fast, slow); + } _add_energy_to_string( speed, me.spell, - mi.is_actual_spellcaster() ? "casts spells" : - mi.is_priest() ? "uses invocations" - : "uses natural abilities", fast, slow); - _add_energy_to_string(speed, me.special, "uses special abilities", + mi.is_actual_spellcaster() ? conjugate_verb("cast", plural) + + " spells" : + mi.is_priest() ? conjugate_verb("use", plural) + + " invocations" + : conjugate_verb("use", plural) + + " natural abilities", fast, slow); + _add_energy_to_string(speed, me.special, + conjugate_verb("use", plural) + + " special abilities", fast, slow); if (mons_class_itemuse(mi.type) >= MONUSE_STARTING_EQUIPMENT) - _add_energy_to_string(speed, me.item, "uses items", fast, slow); + { + _add_energy_to_string(speed, me.item, + conjugate_verb("use", plural) + " items", + fast, slow); + } if (speed >= 10) { @@ -4071,8 +4103,9 @@ static string _monster_stat_description(const monster_info& mi) if (mi.type == MONS_SHADOW) { // Cf. monster::action_energy() in monster.cc. - result << uppercase_first(pronoun) << " covers ground more" - << " quickly when invisible.\n"; + result << uppercase_first(pronoun) << " " + << conjugate_verb("cover", plural) + << " ground more quickly when invisible.\n"; } if (mi.airborne()) @@ -4082,11 +4115,17 @@ static string _monster_stat_description(const monster_info& mi) if (!mi.can_regenerate()) result << uppercase_first(pronoun) << " cannot regenerate.\n"; else if (mons_class_fast_regen(mi.type)) - result << uppercase_first(pronoun) << " regenerates quickly.\n"; + result << uppercase_first(pronoun) << " " + << conjugate_verb("regenerate", plural) + << " quickly.\n"; const char* mon_size = get_size_adj(mi.body_size(), true); if (mon_size) - result << uppercase_first(pronoun) << " is " << mon_size << ".\n"; + { + result << uppercase_first(pronoun) << " " + << conjugate_verb("are", plural) << " " + << mon_size << ".\n"; + } if (in_good_standing(GOD_ZIN, 0) && !mi.pos.origin() && monster_at(mi.pos)) { @@ -4100,8 +4139,9 @@ static string _monster_stat_description(const monster_info& mi) } else if (eligibility == RE_TOO_STRONG) { - result << uppercase_first(pronoun) << - " is too strong to be affected by reciting Zin's laws."; + result << uppercase_first(pronoun) << " " + << conjugate_verb("are", plural) + << " too strong to be affected by reciting Zin's laws."; } else // RE_ELIGIBLE || RE_RECITE_TIMER { @@ -4206,6 +4246,7 @@ void get_monster_db_desc(const monster_info& mi, describe_info &inf, const string it = mi.pronoun(PRONOUN_SUBJECTIVE); const string it_o = mi.pronoun(PRONOUN_OBJECTIVE); const string It = uppercase_first(it); + const string is = conjugate_verb("are", mi.pronoun_plurality()); switch (mi.type) { @@ -4316,7 +4357,7 @@ void get_monster_db_desc(const monster_info& mi, describe_info &inf, bool stair_use = false; if (!mons_class_can_use_stairs(mi.type)) { - inf.body << It << " is incapable of using stairs.\n"; + inf.body << It << " " << is << " incapable of using stairs.\n"; stair_use = true; } @@ -4326,14 +4367,17 @@ void get_monster_db_desc(const monster_info& mi, describe_info &inf, "temporary. Killing " << it_o << " yields no experience, " "nutrition or items"; if (!stair_use) - inf.body << ", and " << it << " is incapable of using stairs"; + { + inf.body << ", and " << it << " " << is + << " incapable of using stairs"; + } inf.body << ".\n"; } else if (mi.is(MB_PERM_SUMMON)) { inf.body << "\nThis monster has been summoned in a durable way. " "Killing " << it_o << " yields no experience, nutrition " - "or items, but " << it_o << " cannot be abjured.\n"; + "or items, but " << it << " cannot be abjured.\n"; } else if (mi.is(MB_NO_REWARD)) { @@ -4342,8 +4386,9 @@ void get_monster_db_desc(const monster_info& mi, describe_info &inf, } else if (mons_class_leaves_hide(mi.type)) { - inf.body << "\nIf " << it << " is slain, it may be possible to " - "recover " << mi.pronoun(PRONOUN_POSSESSIVE) + inf.body << "\nIf " << it << " " << is << + " slain, it may be possible to recover " + << mi.pronoun(PRONOUN_POSSESSIVE) << " hide, which can be used as armour.\n"; } diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc index d9eb1efecc1a..1e39d76b91fd 100644 --- a/crawl-ref/source/directn.cc +++ b/crawl-ref/source/directn.cc @@ -3086,7 +3086,9 @@ static string _mon_enchantments_string(const monster_info& mi) if (!enchant_descriptors.empty()) { return uppercase_first(mi.pronoun(PRONOUN_SUBJECTIVE)) - + " is " + + " " + + conjugate_verb("are", mi.pronoun_plurality()) + + " " + comma_separated_line(enchant_descriptors.begin(), enchant_descriptors.end()) + "."; @@ -3183,59 +3185,91 @@ static string _get_monster_desc(const monster_info& mi) string pronoun = uppercase_first(mi.pronoun(PRONOUN_SUBJECTIVE)); if (mi.is(MB_CLINGING)) - text += pronoun + " is clinging to the wall.\n"; + { + text += pronoun + " " + conjugate_verb("are", mi.pronoun_plurality()) + + " clinging to the wall.\n"; + } if (mi.is(MB_MESMERIZING)) { text += string("You are mesmerised by ") - + mi.pronoun(PRONOUN_POSSESSIVE) + " song.\n"; + + mi.pronoun(PRONOUN_POSSESSIVE) + " song.\n"; } if (mi.is(MB_SLEEPING) || mi.is(MB_DORMANT)) { - text += pronoun + " appears to be " - + (mi.is(MB_CONFUSED) ? "sleepwalking" - : "resting") - + ".\n"; + text += pronoun + " " + + conjugate_verb("appear", mi.pronoun_plurality()) + " to be " + + (mi.is(MB_CONFUSED) ? "sleepwalking" : "resting") + ".\n"; } // Applies to both friendlies and hostiles else if (mi.is(MB_FLEEING)) - text += pronoun + " is fleeing.\n"; + { + text += pronoun + " " + conjugate_verb("are", mi.pronoun_plurality()) + + " fleeing.\n"; + } // hostile with target != you - else if (mi.attitude == ATT_HOSTILE && (mi.is(MB_UNAWARE) || mi.is(MB_WANDERING))) - text += pronoun + " doesn't appear to have noticed you.\n"; + else if (mi.attitude == ATT_HOSTILE + && (mi.is(MB_UNAWARE) || mi.is(MB_WANDERING))) + { + text += pronoun + " " + conjugate_verb("have", mi.pronoun_plurality()) + + " not noticed you.\n"; + } if (mi.attitude == ATT_FRIENDLY) - text += pronoun + " is friendly.\n"; + { + text += pronoun + " " + conjugate_verb("are", mi.pronoun_plurality()) + + " friendly.\n"; + } else if (mi.attitude == ATT_GOOD_NEUTRAL) - text += pronoun + " seems to be peaceful towards you.\n"; + { + text += pronoun + " " + conjugate_verb("seem", mi.pronoun_plurality()) + + " to be peaceful towards you.\n"; + } else if (mi.attitude != ATT_HOSTILE && !mi.is(MB_INSANE)) { // don't differentiate between permanent or not - text += pronoun + " is indifferent to you.\n"; + text += pronoun + " " + conjugate_verb("are", mi.pronoun_plurality()) + + " indifferent to you.\n"; } if (mi.is(MB_SUMMONED) || mi.is(MB_PERM_SUMMON)) { - text += pronoun + " has been summoned"; + text += pronoun + " " + conjugate_verb("have", mi.pronoun_plurality()) + + " been summoned"; if (mi.is(MB_SUMMONED_CAPPED)) - text += ", and is expiring"; + { + text += ", and " + conjugate_verb("are", mi.pronoun_plurality()) + + " expiring"; + } else if (mi.is(MB_PERM_SUMMON)) text += " but will not time out"; text += ".\n"; } if (mi.is(MB_HALOED)) - text += pronoun + " is illuminated by a divine halo.\n"; + { + text += pronoun + " " + conjugate_verb("are", mi.pronoun_plurality()) + + " illuminated by a divine halo.\n"; + } if (mi.is(MB_UMBRAED)) - text += pronoun + " is wreathed by an umbra.\n"; + { + text += pronoun + " " + conjugate_verb("are", mi.pronoun_plurality()) + + " wreathed by an umbra.\n"; + } if (mi.intel() <= I_BRAINLESS) - text += pronoun + " is mindless.\n"; + { + text += pronoun + " " + conjugate_verb("are", mi.pronoun_plurality()) + + " mindless.\n"; + } if (mi.is(MB_CHAOTIC)) - text += pronoun + " is chaotic.\n"; + { + text += pronoun + " " + conjugate_verb("are", mi.pronoun_plurality()) + + " chaotic.\n"; + } if (mi.is(MB_POSSESSABLE)) { @@ -3243,21 +3277,30 @@ static string _get_monster_desc(const monster_info& mi) + " soul is ripe for the taking.\n"; } else if (mi.is(MB_ENSLAVED)) - text += pronoun + " is a disembodied soul.\n"; + { + text += pronoun + " " + conjugate_verb("are", mi.pronoun_plurality()) + + " a disembodied soul.\n"; + } if (mi.is(MB_MIRROR_DAMAGE)) - text += pronoun + " is reflecting injuries back at attackers.\n"; + { + text += pronoun + " " + conjugate_verb("are", mi.pronoun_plurality()) + + " reflecting injuries back at attackers.\n"; + } if (mi.is(MB_INNER_FLAME)) - text += pronoun + " is filled with an inner flame.\n"; + { + text += pronoun + " " + conjugate_verb("are", mi.pronoun_plurality()) + + " filled with an inner flame.\n"; + } if (mi.fire_blocker) { text += string("Your line of fire to ") + mi.pronoun(PRONOUN_OBJECTIVE) - + " is blocked by " // FIXME: renamed features - + feature_description(mi.fire_blocker, NUM_TRAPS, "", - DESC_A) - + "\n"; + + " is blocked by " // FIXME: renamed features + + feature_description(mi.fire_blocker, NUM_TRAPS, "", + DESC_A) + + "\n"; } text += _mon_enchantments_string(mi); @@ -3580,8 +3623,9 @@ static void _describe_cell(const coord_def& where, bool in_range) if (!in_range) { - mprf(MSGCH_EXAMINE_FILTER, "%s is out of range.", - mon->pronoun(PRONOUN_SUBJECTIVE).c_str()); + mprf(MSGCH_EXAMINE_FILTER, "%s %s out of range.", + mon->pronoun(PRONOUN_SUBJECTIVE).c_str(), + conjugate_verb("are", mi.pronoun_plurality()).c_str()); } #ifndef DEBUG_DIAGNOSTICS monster_described = true; diff --git a/crawl-ref/source/english.cc b/crawl-ref/source/english.cc index 4c48686b216d..0aae62ff1bae 100644 --- a/crawl-ref/source/english.cc +++ b/crawl-ref/source/english.cc @@ -202,7 +202,7 @@ string apostrophise(const string &name) if (name == "herself") return "her own"; - if (name == "themselves") + if (name == "themselves" || name == "themself") return "their own"; if (name == "yourself") @@ -269,6 +269,7 @@ static const char * const _pronoun_declension[][NUM_PRONOUN_CASES] = { "he", "his", "himself", "him" }, // masculine { "she", "her", "herself", "her" }, // feminine { "you", "your", "yourself", "you" }, // 2nd person + { "they", "their", "themself", "them" }, // neutral }; const char *decline_pronoun(gender_type gender, pronoun_type variant) diff --git a/crawl-ref/source/gender-type.h b/crawl-ref/source/gender-type.h index 1395b2af1145..d132db98f84c 100644 --- a/crawl-ref/source/gender-type.h +++ b/crawl-ref/source/gender-type.h @@ -6,5 +6,6 @@ enum gender_type GENDER_MALE, GENDER_FEMALE, GENDER_YOU, // A person, not a gender, but close enough. + GENDER_NEUTRAL, NUM_GENDERS }; diff --git a/crawl-ref/source/god-abil.cc b/crawl-ref/source/god-abil.cc index b5bb8e93cd9a..52277c061995 100644 --- a/crawl-ref/source/god-abil.cc +++ b/crawl-ref/source/god-abil.cc @@ -7040,12 +7040,13 @@ static void _hepliaklqana_choose_gender() static const string gender_names[] = { "neither", "male", "female" }; const int current_gender = you.props[HEPLIAKLQANA_ALLY_GENDER_KEY].get_int(); - ASSERT(size_t(current_gender) < ARRAYSZ(gender_names)); + const int hep_current_gender = current_gender == 4 ? 0 : current_gender; + ASSERT(size_t(hep_current_gender) < ARRAYSZ(gender_names)); mprf(MSGCH_PROMPT, "Was %s a) male, b) female, or c) neither? (Currently %s.)", hepliaklqana_ally_name().c_str(), - gender_names[current_gender].c_str()); + gender_names[hep_current_gender].c_str()); int keyin = toalower(get_ch()); if (!isaalpha(keyin)) @@ -7055,14 +7056,15 @@ static void _hepliaklqana_choose_gender() } const uint32_t choice = keyin - 'a'; - if (choice > ARRAYSZ(gender_names)) + if (choice >= ARRAYSZ(gender_names)) { canned_msg(MSG_OK); return; } - // fun trick - const int new_gender = (choice + 1) % 3; + const int new_gender = choice == 2 ? 4 : choice + 1; + const int hep_new_gender = (choice + 1) % 3; + if (new_gender == current_gender) { canned_msg(MSG_OK); @@ -7072,7 +7074,7 @@ static void _hepliaklqana_choose_gender() you.props[HEPLIAKLQANA_ALLY_GENDER_KEY] = new_gender; mprf("%s was always %s, you're pretty sure.", hepliaklqana_ally_name().c_str(), - gender_names[new_gender].c_str()); + gender_names[hep_new_gender].c_str()); upgrade_hepliaklqana_ancestor(true); } diff --git a/crawl-ref/source/mon-info.cc b/crawl-ref/source/mon-info.cc index 95fc531e8458..5e81c460d767 100644 --- a/crawl-ref/source/mon-info.cc +++ b/crawl-ref/source/mon-info.cc @@ -1551,7 +1551,11 @@ string monster_info::wounds_description_sentence() const if (wounds.empty()) return ""; else - return string(pronoun(PRONOUN_SUBJECTIVE)) + " is " + wounds + "."; + { + return string(pronoun(PRONOUN_SUBJECTIVE)) + " " + + conjugate_verb("are", pronoun_plurality()) + + " " + wounds + "."; + } } string monster_info::wounds_description(bool use_colour) const @@ -1841,3 +1845,10 @@ const char *monster_info::pronoun(pronoun_type variant) const } return mons_pronoun(type, variant, true); } + +const bool monster_info::pronoun_plurality() const +{ + if (props.exists(MON_GENDER_KEY)) + return props[MON_GENDER_KEY].get_int() == GENDER_NEUTRAL ? true : false; + return false; +} diff --git a/crawl-ref/source/mon-info.h b/crawl-ref/source/mon-info.h index fec7b744881b..864164cc193b 100644 --- a/crawl-ref/source/mon-info.h +++ b/crawl-ref/source/mon-info.h @@ -305,6 +305,7 @@ struct monster_info : public monster_info_base vector attributes() const; const char *pronoun(pronoun_type variant) const; + const bool pronoun_plurality() const; string wounds_description_sentence() const; string wounds_description(bool colour = false) const; From dba641b7393abb6947b3eae1b32a770070b52d7e Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Sun, 9 Jun 2019 21:32:44 +0100 Subject: [PATCH 435/864] Refactor Hepliaklqana ancester gender choice --- crawl-ref/source/god-abil.cc | 29 +++++++++++++++++++---------- crawl-ref/source/tag-version.h | 1 + crawl-ref/source/tags.cc | 6 ++++++ 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/crawl-ref/source/god-abil.cc b/crawl-ref/source/god-abil.cc index 52277c061995..52377fde0565 100644 --- a/crawl-ref/source/god-abil.cc +++ b/crawl-ref/source/god-abil.cc @@ -7037,16 +7037,22 @@ static void _hepliaklqana_choose_name() static void _hepliaklqana_choose_gender() { - static const string gender_names[] = { "neither", "male", "female" }; - const int current_gender - = you.props[HEPLIAKLQANA_ALLY_GENDER_KEY].get_int(); - const int hep_current_gender = current_gender == 4 ? 0 : current_gender; - ASSERT(size_t(hep_current_gender) < ARRAYSZ(gender_names)); + static const map gender_map = + { + { GENDER_NEUTRAL, "neither" }, + { GENDER_MALE, "male" }, + { GENDER_FEMALE, "female" }, + }; + + const gender_type current_gender = + (gender_type)you.props[HEPLIAKLQANA_ALLY_GENDER_KEY].get_int(); + const string* desc = map_find(gender_map, current_gender); + ASSERT(desc); mprf(MSGCH_PROMPT, "Was %s a) male, b) female, or c) neither? (Currently %s.)", hepliaklqana_ally_name().c_str(), - gender_names[hep_current_gender].c_str()); + desc->c_str()); int keyin = toalower(get_ch()); if (!isaalpha(keyin)) @@ -7055,15 +7061,18 @@ static void _hepliaklqana_choose_gender() return; } + static const gender_type gender_options[] = { GENDER_MALE, + GENDER_FEMALE, + GENDER_NEUTRAL }; + const uint32_t choice = keyin - 'a'; - if (choice >= ARRAYSZ(gender_names)) + if (choice >= ARRAYSZ(gender_options)) { canned_msg(MSG_OK); return; } - const int new_gender = choice == 2 ? 4 : choice + 1; - const int hep_new_gender = (choice + 1) % 3; + const gender_type new_gender = gender_options[choice]; if (new_gender == current_gender) { @@ -7074,7 +7083,7 @@ static void _hepliaklqana_choose_gender() you.props[HEPLIAKLQANA_ALLY_GENDER_KEY] = new_gender; mprf("%s was always %s, you're pretty sure.", hepliaklqana_ally_name().c_str(), - gender_names[hep_new_gender].c_str()); + map_find(gender_map, new_gender)->c_str()); upgrade_hepliaklqana_ancestor(true); } diff --git a/crawl-ref/source/tag-version.h b/crawl-ref/source/tag-version.h index 4d9b003f1bd2..775f387f6950 100644 --- a/crawl-ref/source/tag-version.h +++ b/crawl-ref/source/tag-version.h @@ -232,6 +232,7 @@ enum tag_minor_version TAG_MINOR_YELLOW_DRACONIAN_RACID, // Change yellow draconians' rAcid fake mutation to a true mutation. TAG_MINOR_THROW_CONSOLIDATION, // Throwing brands consolidated TAG_MINOR_VAMPIRE_NO_EAT, // Decouple Vampires from the food system + TAG_MINOR_SINGULAR_THEY, // Add singular they pronouns #endif NUM_TAG_MINORS, TAG_MINOR_VERSION = NUM_TAG_MINORS - 1 diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index 1d6bd6453046..7e8b9612af47 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -3750,6 +3750,12 @@ static void tag_read_you(reader &th) for (int i = 0; i < you.props[THUNDERBOLT_CHARGES_KEY].get_int(); i++) expend_xp_evoker(MISC_LIGHTNING_ROD); } + if (th.getMinorVersion() < TAG_MINOR_SINGULAR_THEY + && you.props.exists(HEPLIAKLQANA_ALLY_GENDER_KEY)) + { + if (you.props[HEPLIAKLQANA_ALLY_GENDER_KEY].get_int() == GENDER_NEUTER) + you.props[HEPLIAKLQANA_ALLY_GENDER_KEY] = GENDER_NEUTRAL; + } #endif } From f4a770e8ca082ab2e1e1c979adca52b58c96e2e2 Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Thu, 13 Jun 2019 22:00:06 +0100 Subject: [PATCH 436/864] Add handling for non-ancestor monsters with they/them pronouns --- crawl-ref/source/delay.cc | 8 ++++++-- crawl-ref/source/melee-attack.cc | 6 ++++-- crawl-ref/source/mon-death.cc | 9 +++++---- crawl-ref/source/mon-flags.h | 3 +++ crawl-ref/source/mon-info.cc | 5 +++-- crawl-ref/source/mon-util.cc | 18 +++++++++++------- crawl-ref/source/mon-util.h | 2 ++ crawl-ref/source/monster.cc | 14 ++++++++++++-- crawl-ref/source/monster.h | 1 + crawl-ref/source/spl-goditem.cc | 7 +++++-- crawl-ref/source/view.cc | 7 ++++++- 11 files changed, 58 insertions(+), 22 deletions(-) diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc index b9d84c604c57..3948da770f22 100644 --- a/crawl-ref/source/delay.cc +++ b/crawl-ref/source/delay.cc @@ -23,6 +23,7 @@ #include "describe.h" #include "directn.h" #include "dungeon.h" +#include "english.h" #include "enum.h" #include "env.h" #include "exclude.h" @@ -1242,7 +1243,9 @@ static inline bool _monster_warning(activity_interrupt ai, god_warning = uppercase_first(god_name(you.religion)) + " warns you: " + uppercase_first(mon->pronoun(PRONOUN_SUBJECTIVE)) - + " is a foul "; + + " " + + conjugate_verb("are", mon->pronoun_plurality()) + + " a foul "; if (mon->has_ench(ENCH_GLOWING_SHAPESHIFTER)) god_warning += "glowing "; god_warning += "shapeshifter."; @@ -1255,7 +1258,8 @@ static inline bool _monster_warning(activity_interrupt ai, if (!mweap.empty()) { - text += " " + uppercase_first(mon->pronoun(PRONOUN_SUBJECTIVE)) + " is" + text += " " + uppercase_first(mon->pronoun(PRONOUN_SUBJECTIVE)) + + " " + conjugate_verb("are", mi.pronoun_plurality()) + (mweap[0] != ' ' ? " " : "") + mweap + "."; } diff --git a/crawl-ref/source/melee-attack.cc b/crawl-ref/source/melee-attack.cc index dd8e21cd9fd3..e974b2911a45 100644 --- a/crawl-ref/source/melee-attack.cc +++ b/crawl-ref/source/melee-attack.cc @@ -694,9 +694,11 @@ static void _hydra_consider_devouring(monster &defender) if (defender.is_shapeshifter()) { // handle this carefully, so the player knows what's going on - mprf("You spit out %s as %s twists & changes in your mouth!", + mprf("You spit out %s as %s %s & %s in your mouth!", defender.name(DESC_THE).c_str(), - defender.pronoun(PRONOUN_SUBJECTIVE).c_str()); + defender.pronoun(PRONOUN_SUBJECTIVE).c_str(), + conjugate_verb("twist", defender.pronoun_plurality()).c_str(), + conjugate_verb("change", defender.pronoun_plurality()).c_str()); return; } diff --git a/crawl-ref/source/mon-death.cc b/crawl-ref/source/mon-death.cc index baf3fb1191fd..b45bc725eed8 100644 --- a/crawl-ref/source/mon-death.cc +++ b/crawl-ref/source/mon-death.cc @@ -1798,8 +1798,8 @@ static void _special_corpse_messaging(monster &mons) if (!(mons.flags & MF_KNOWN_SHIFTER)) { const string message = "'s shape twists and changes as " - + mons.pronoun(PRONOUN_SUBJECTIVE) - + " dies."; + + mons.pronoun(PRONOUN_SUBJECTIVE) + " " + + conjugate_verb("die", mons.pronoun_plurality()) + "."; simple_monster_message(mons, message.c_str()); } @@ -1815,8 +1815,9 @@ static void _special_corpse_messaging(monster &mons) const string message = " returns to " + mons.pronoun(PRONOUN_POSSESSIVE) + " original shape as " + - mons.pronoun(PRONOUN_SUBJECTIVE) + - " dies."; + mons.pronoun(PRONOUN_SUBJECTIVE) + " " + + conjugate_verb("die", mons.pronoun_plurality()) + + "."; simple_monster_message(mons, message.c_str()); } diff --git a/crawl-ref/source/mon-flags.h b/crawl-ref/source/mon-flags.h index 847f7b2261c2..5443f4ac5d30 100644 --- a/crawl-ref/source/mon-flags.h +++ b/crawl-ref/source/mon-flags.h @@ -169,6 +169,9 @@ enum monclass_flag_type : uint64_t /// monster always receives a wand M_ALWAYS_WAND = BIT(56), + + /// uses they/them pronouns + M_GENDER_NEUTRAL = BIT(57), }; DEF_BITFIELD(monclass_flags_t, monclass_flag_type); diff --git a/crawl-ref/source/mon-info.cc b/crawl-ref/source/mon-info.cc index 5e81c460d767..edb50b3ae739 100644 --- a/crawl-ref/source/mon-info.cc +++ b/crawl-ref/source/mon-info.cc @@ -1849,6 +1849,7 @@ const char *monster_info::pronoun(pronoun_type variant) const const bool monster_info::pronoun_plurality() const { if (props.exists(MON_GENDER_KEY)) - return props[MON_GENDER_KEY].get_int() == GENDER_NEUTRAL ? true : false; - return false; + return props[MON_GENDER_KEY].get_int() == GENDER_NEUTRAL; + + return mons_class_gender(type) == GENDER_NEUTRAL; } diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index 442286618295..86cf1f69c531 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -3936,15 +3936,17 @@ bool mons_can_attack(const monster& mon) * Used for pronoun selection. * * @param mc The type of monster in question - * @return GENDER_NEUTER, _FEMALE, or _MALE. + * @return GENDER_NEUTER, _NEUTRAL, _FEMALE, or _MALE. */ -static gender_type _mons_class_gender(monster_type mc) +gender_type mons_class_gender(monster_type mc) { const bool female = mons_class_flag(mc, M_FEMALE); const bool male = mons_class_flag(mc, M_MALE); - ASSERT(!(male && female)); + const bool neutral = mons_class_flag(mc, M_GENDER_NEUTRAL); + ASSERT(male + female + neutral <= 1); return male ? GENDER_MALE : female ? GENDER_FEMALE : + neutral ? GENDER_NEUTRAL : GENDER_NEUTER; } @@ -3957,7 +3959,7 @@ const char *mons_pronoun(monster_type mon_type, pronoun_type variant, bool visible) { const gender_type gender = !visible ? GENDER_NEUTER - : _mons_class_gender(mon_type); + : mons_class_gender(mon_type); return decline_pronoun(gender, variant); } @@ -4986,8 +4988,9 @@ void debug_mondata() const bool male = mons_class_flag(mc, M_MALE); const bool female = mons_class_flag(mc, M_FEMALE); - if (male && female) - fails += make_stringf("%s is both male and female\n", name); + const bool neutral = mons_class_flag(mc, M_GENDER_NEUTRAL); + if (male + female + neutral > 1) + fails += make_stringf("%s has too many genders\n", name); if (md->shape == MON_SHAPE_BUGGY) fails += make_stringf("%s has no defined shape\n", name); @@ -5010,7 +5013,8 @@ void debug_mondata() fails += make_stringf("%s has a corpse tile & no corpse\n", name); } - } else if (!has_corpse_tile) + } + else if (!has_corpse_tile) fails += make_stringf("%s has a corpse but no corpse tile\n", name); } diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h index 33cd476d4185..dda91703fbc2 100644 --- a/crawl-ref/source/mon-util.h +++ b/crawl-ref/source/mon-util.h @@ -8,6 +8,7 @@ #include #include "enum.h" +#include "gender-type.h" #include "los-type.h" #include "mon-enum.h" #include "mon-inv-type.h" @@ -350,6 +351,7 @@ bool mons_can_attack(const monster& mon); bool mons_has_incapacitating_spell(const monster& mon, const actor& foe); bool mons_has_incapacitating_ranged_attack(const monster& mon, const actor& foe); +gender_type mons_class_gender(monster_type mc); const char *mons_pronoun(monster_type mon_type, pronoun_type variant, bool visible = true); diff --git a/crawl-ref/source/monster.cc b/crawl-ref/source/monster.cc index 79c199c5b918..ca868829c3eb 100644 --- a/crawl-ref/source/monster.cc +++ b/crawl-ref/source/monster.cc @@ -847,13 +847,14 @@ void monster::equip_weapon_message(item_def &item) { bool plural = true; string hand = hand_name(true, &plural); - mprf("%s %s briefly %s through it before %s manages to get a " + mprf("%s %s briefly %s through it before %s %s to get a " "firm grip on it.", pronoun(PRONOUN_POSSESSIVE).c_str(), hand.c_str(), // Not conj_verb: the monster isn't the subject. conjugate_verb("pass", plural).c_str(), - pronoun(PRONOUN_SUBJECTIVE).c_str()); + pronoun(PRONOUN_SUBJECTIVE).c_str(), + conjugate_verb("manage", pronoun_plurality()).c_str()); } break; case SPWPN_REAPING: @@ -2351,6 +2352,15 @@ string monster::pronoun(pronoun_type pro, bool force_visible) const return mons_pronoun(type, pro, seen); } +bool monster::pronoun_plurality(bool force_visible) const +{ + const bool seen = force_visible || you.can_see(*this); + if (seen && props.exists(MON_GENDER_KEY)) + return props[MON_GENDER_KEY].get_int() == GENDER_NEUTRAL; + + return seen && mons_class_gender(type) == GENDER_NEUTRAL; +} + string monster::conj_verb(const string &verb) const { return conjugate_verb(verb, false); diff --git a/crawl-ref/source/monster.h b/crawl-ref/source/monster.h index 255aee226f5a..db18e2f3e80e 100644 --- a/crawl-ref/source/monster.h +++ b/crawl-ref/source/monster.h @@ -332,6 +332,7 @@ class monster : public actor // will return "Arbolt the orc priest". string full_name(description_level_type type) const; string pronoun(pronoun_type pro, bool force_visible = false) const override; + bool pronoun_plurality(bool force_visible = false) const; string conj_verb(const string &verb) const override; string hand_name(bool plural, bool *can_plural = nullptr) const override; string foot_name(bool plural, bool *can_plural = nullptr) const override; diff --git a/crawl-ref/source/spl-goditem.cc b/crawl-ref/source/spl-goditem.cc index 0b9ea19c6a91..97d229919d95 100644 --- a/crawl-ref/source/spl-goditem.cc +++ b/crawl-ref/source/spl-goditem.cc @@ -12,6 +12,7 @@ #include "coordit.h" #include "database.h" #include "directn.h" +#include "english.h" #include "env.h" #include "fight.h" #include "god-conduct.h" @@ -101,9 +102,11 @@ string unpacifiable_reason(const monster_info& mi) if (mi.is(MB_SLEEPING)) // not aware of what is happening { - return make_stringf("You cannot pacify this monster while %s is " + return make_stringf("You cannot pacify this monster while %s %s " "sleeping!", - mi.pronoun(PRONOUN_SUBJECTIVE)); + mi.pronoun(PRONOUN_SUBJECTIVE), + conjugate_verb("are", + mi.pronoun_plurality()).c_str()); } // pacifiable, maybe! diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index bde582bd9ff2..3c1c47909354 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -305,7 +305,12 @@ static string _monster_headsup(const vector &monsters, monname = mon->full_name(DESC_A); warning_msg += uppercase_first(monname); - warning_msg += " is"; + warning_msg += " "; + if (monsters.size() == 1) + warning_msg += conjugate_verb("are", mon->pronoun_plurality()); + else + warning_msg += "is"; + if (!divine) { warning_msg += get_monster_equipment_desc(mi, DESC_WEAPON_WARNING, From ec079b9e983224845d71d486bd07cc79537ee5d0 Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Thu, 13 Jun 2019 22:01:19 +0100 Subject: [PATCH 437/864] Change some uniques to use they/them pronouns Nessos, Xtahua, Fannar, Robin, Dissolution and Saint Roka now use "they", as do the demon/pan lords that previously used "it". Some random Gozag shopkeepers and the wizlab Cloud Mage/Hellbinder also use "they" instead of "it". --- crawl-ref/source/dat/database/monspeak.txt | 2 +- crawl-ref/source/dat/descript/monsters.txt | 30 +++++++++---------- crawl-ref/source/god-abil.cc | 2 +- crawl-ref/source/mon-data.h | 34 +++++++++++++--------- crawl-ref/source/mon-place.cc | 2 +- 5 files changed, 39 insertions(+), 31 deletions(-) diff --git a/crawl-ref/source/dat/database/monspeak.txt b/crawl-ref/source/dat/database/monspeak.txt index 70f4a4d994d6..65472c2794f2 100644 --- a/crawl-ref/source/dat/database/monspeak.txt +++ b/crawl-ref/source/dat/database/monspeak.txt @@ -5436,7 +5436,7 @@ _Nessos_rare_ @The_monster@ says, "Even if you were a mare, I'd kill you!" -@The_monster@ shouts, "I'm half man! Half horse! And all stone-cold KILLER!" +@The_monster@ shouts, "I'm half human! Half horse! And all stone-cold KILLER!" w:1 @The_monster@ says, "Hold still for a moment, will you? I've got a trick shot I want to try here." diff --git a/crawl-ref/source/dat/descript/monsters.txt b/crawl-ref/source/dat/descript/monsters.txt index d94dc3823de6..134d78c92dff 100644 --- a/crawl-ref/source/dat/descript/monsters.txt +++ b/crawl-ref/source/dat/descript/monsters.txt @@ -87,16 +87,16 @@ on to his ears with hooks? Dispater Greatest of the Lords of Hell, Dispater was born when first an iron sword drank -mortal blood. It despises mortal vanities, the pursuit of ‘reason’ and ‘beauty’ -- the only art it enjoys is the art of war. +mortal blood. They despise mortal vanities, the pursuit of ‘reason’ and +‘beauty’ - the only art they enjoy is the art of war. %%%% Dissolution The Pits of Slime used to be a thriving civilization, and Dissolution was the prophet of their god. When the city was overtaken by its current residents, -only Dissolution survived, for he alone turned faithfully to the Slime God. -Dissolution became a tremendous mass of acidic ooze, yet retained his -intelligence. He is filled with hatred for anything that can hold a form. +only Dissolution survived, for they alone turned faithfully to the Slime God. +Dissolution became a tremendous mass of acidic ooze, yet retained their +intelligence. They are filled with hatred for anything that can hold a form. %%%% Donald @@ -162,9 +162,9 @@ honour. %%%% Fannar -A cold-hearted elven sorcerer, draped in robes of high office. He whispers -grimly to himself as he stalks the dungeon, trailing ice crystals through the -air behind him. +A cold-hearted elven sorcerer, draped in robes of high office. They whisper +grimly to themself as they stalk the dungeon, trailing ice crystals through the +air behind them. %%%% Frances @@ -276,11 +276,11 @@ for prey to slake its bottomless appetite. %%%% Lom Lobon -Stoic and inscrutable, Lom Lobon is an ancient demon infamous for its mastery +Stoic and inscrutable, Lom Lobon is an ancient demon infamous for their mastery of magic. Rumoured to be the most learned being in the halls of Pandemonium, -it is at times sought out by mortal wizards who offer their souls in exchange -for the secrets of the arcane. Lacking the terrible wrath present in most -demons, Lom Lobon's single eye instead hides a cold, impartial cruelty. +they are at times sought out by mortal wizards who offer their souls in +exchange for the secrets of the arcane. Lacking the terrible wrath present in +most demons, Lom Lobon's single eye instead hides a cold, impartial cruelty. %%%% Louise @@ -359,8 +359,8 @@ fear her; the dead obey her every command. She has a soft spot for the latter. %%%% Nessos -A centaur warrior, skilled at warfare and deceit. He slew a mighty hydra, and -now its deadly blood drips, still-fuming, from his arrows. +A centaur warrior, skilled at warfare and deceit. They slew a mighty hydra, and +now its deadly blood drips, still-fuming, from their arrows. %%%% Nikola @@ -412,7 +412,7 @@ A human whose savage roars bring terror to all those who hear them. %%%% Saint Roka -A mighty warlord. Some orcs even say he is the Chosen One of Beogh. +A mighty warlord. Some orcs even say they are the Chosen One of Beogh. %%%% Sigmund diff --git a/crawl-ref/source/god-abil.cc b/crawl-ref/source/god-abil.cc index 52377fde0565..8847d4f9dfa9 100644 --- a/crawl-ref/source/god-abil.cc +++ b/crawl-ref/source/god-abil.cc @@ -4387,7 +4387,7 @@ static void _gozag_place_shop(int index) ASSERT(shop); const gender_type gender = random_choose(GENDER_FEMALE, GENDER_MALE, - GENDER_NEUTER); + GENDER_NEUTRAL); mprf(MSGCH_GOD, "%s invites you to visit %s %s%s%s.", shop->shop_name.c_str(), diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h index 930f81bd631d..cba6c89e5216 100644 --- a/crawl-ref/source/mon-data.h +++ b/crawl-ref/source/mon-data.h @@ -6202,7 +6202,7 @@ DUMMY(MONS_HELL_LORD, '&', COLOUR_UNDEF, "hell lord", TILEP_MONS_PROGRAM_BUG) // "c"entaurs. { MONS_NESSOS, 'c', MAGENTA, "Nessos", - M_UNIQUE | M_WARM_BLOOD | M_ARCHER | M_SPEAKS | M_MALE, + M_UNIQUE | M_WARM_BLOOD | M_ARCHER | M_SPEAKS | M_GENDER_NEUTRAL, MR_NO_FLAGS, 18, MONS_CENTAUR, MONS_CENTAUR, MH_NATURAL, 20, { {AT_HIT, AF_PLAIN, 16}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -6288,7 +6288,8 @@ DUMMY(MONS_HELL_LORD, '&', COLOUR_UNDEF, "hell lord", TILEP_MONS_PROGRAM_BUG) // "D"ragons and hydras. { MONS_XTAHUA, 'D', RED, "Xtahua", - M_UNIQUE | M_SEE_INVIS | M_WARM_BLOOD | M_SPEAKS | M_FEMALE | M_CRASH_DOORS | M_FLIES, + M_UNIQUE | M_SEE_INVIS | M_WARM_BLOOD | M_SPEAKS | M_GENDER_NEUTRAL + | M_CRASH_DOORS | M_FLIES, MR_RES_POISON | mrd(MR_RES_FIRE, 2) | MR_VUL_COLD, 18, MONS_DRAGON, MONS_FIRE_DRAGON, MH_NATURAL, 180, { {AT_BITE, AF_PLAIN, 35}, {AT_CLAW, AF_PLAIN, 17}, @@ -6412,7 +6413,7 @@ DUMMY(MONS_HELL_LORD, '&', COLOUR_UNDEF, "hell lord", TILEP_MONS_PROGRAM_BUG) { MONS_FANNAR, 'e', LIGHTBLUE, "Fannar", - M_UNIQUE | M_WARM_BLOOD | M_SPEAKS | M_MALE, + M_UNIQUE | M_WARM_BLOOD | M_SPEAKS | M_GENDER_NEUTRAL, MR_NO_FLAGS, 16, MONS_ELF, MONS_ELF, MH_NATURAL, 80, { {AT_HIT, AF_PLAIN, 8}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -6453,7 +6454,7 @@ DUMMY(MONS_HELL_LORD, '&', COLOUR_UNDEF, "hell lord", TILEP_MONS_PROGRAM_BUG) { MONS_ROBIN, 'g', LIGHTCYAN, "Robin", - M_UNIQUE | M_WARM_BLOOD | M_SPEAKS | M_FEMALE, + M_UNIQUE | M_WARM_BLOOD | M_SPEAKS | M_GENDER_NEUTRAL, MR_NO_FLAGS, 10, MONS_GOBLIN, MONS_HOBGOBLIN, MH_NATURAL, 10, { {AT_HIT, AF_PLAIN, 5}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -6589,7 +6590,7 @@ DUMMY(MONS_HELL_LORD, '&', COLOUR_UNDEF, "hell lord", TILEP_MONS_PROGRAM_BUG) { MONS_DISSOLUTION, 'J', LIGHTMAGENTA, "Dissolution", M_UNIQUE | M_SEE_INVIS | M_UNBLINDABLE | M_ACID_SPLASH | M_BURROWS - | M_SPEAKS | M_FAST_REGEN | M_MALE | M_EAT_DOORS, + | M_SPEAKS | M_FAST_REGEN | M_GENDER_NEUTRAL | M_EAT_DOORS, MR_RES_POISON | mrd(MR_RES_ACID, 3), 60, MONS_JELLY, MONS_JELLY, MH_NATURAL, 120, { {AT_HIT, AF_ACID, 50}, {AT_HIT, AF_ACID, 30}, AT_NO_ATK, AT_NO_ATK }, @@ -6757,7 +6758,7 @@ DUMMY(MONS_HELL_LORD, '&', COLOUR_UNDEF, "hell lord", TILEP_MONS_PROGRAM_BUG) { MONS_SAINT_ROKA, 'o', LIGHTBLUE, "Saint Roka", - M_UNIQUE | M_FIGHTER | M_WARM_BLOOD | M_SPEAKS | M_MALE, + M_UNIQUE | M_FIGHTER | M_WARM_BLOOD | M_SPEAKS | M_GENDER_NEUTRAL, MR_NO_FLAGS, 15, MONS_ORC, MONS_ORC, MH_NATURAL | MH_EVIL, 80, { {AT_HIT, AF_PLAIN, 35}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -7226,7 +7227,8 @@ DUMMY(MONS_HELL_LORD, '&', COLOUR_UNDEF, "hell lord", TILEP_MONS_PROGRAM_BUG) // unique major demons ('&') { MONS_MNOLEG, '&', LIGHTGREEN, "Mnoleg", - M_UNIQUE | M_FIGHTER | M_SEE_INVIS | M_SPEAKS | M_TALL_TILE, + M_UNIQUE | M_FIGHTER | M_SEE_INVIS | M_SPEAKS | M_TALL_TILE + | M_GENDER_NEUTRAL, MR_RES_ELEC | MR_RES_POISON | MR_RES_FIRE, 15, MONS_PANDEMONIUM_LORD, MONS_MNOLEG, MH_DEMONIC, MAG_IMMUNE, { {AT_CLAW, AF_PLAIN, 40}, {AT_TENTACLE_SLAP, AF_MUTATE, 35}, @@ -7240,7 +7242,8 @@ DUMMY(MONS_HELL_LORD, '&', COLOUR_UNDEF, "hell lord", TILEP_MONS_PROGRAM_BUG) { MONS_LOM_LOBON, '&', LIGHTBLUE, "Lom Lobon", - M_UNIQUE | M_FIGHTER | M_SEE_INVIS | M_SPEAKS | M_FLIES | M_TALL_TILE, + M_UNIQUE | M_FIGHTER | M_SEE_INVIS | M_SPEAKS | M_FLIES | M_TALL_TILE + | M_GENDER_NEUTRAL, MR_RES_POISON | MR_RES_FIRE | mrd(MR_RES_COLD | MR_RES_ELEC, 3), 15, MONS_PANDEMONIUM_LORD, MONS_LOM_LOBON, MH_DEMONIC, MAG_IMMUNE, { {AT_HIT, AF_ANTIMAGIC, 40}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -7253,7 +7256,8 @@ DUMMY(MONS_HELL_LORD, '&', COLOUR_UNDEF, "hell lord", TILEP_MONS_PROGRAM_BUG) { MONS_CEREBOV, '&', RED, "Cerebov", - M_UNIQUE | M_FIGHTER | M_SEE_INVIS | M_SPEAKS | M_TALL_TILE, + M_UNIQUE | M_FIGHTER | M_SEE_INVIS | M_SPEAKS | M_TALL_TILE + | M_GENDER_NEUTRAL, MR_RES_POISON | MR_RES_DAMNATION | mrd(MR_RES_FIRE, 3), 15, MONS_PANDEMONIUM_LORD, MONS_CEREBOV, MH_DEMONIC, MAG_IMMUNE, { {AT_HIT, AF_PLAIN, 60}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -7266,7 +7270,8 @@ DUMMY(MONS_HELL_LORD, '&', COLOUR_UNDEF, "hell lord", TILEP_MONS_PROGRAM_BUG) { MONS_GLOORX_VLOQ, '&', LIGHTGREY, "Gloorx Vloq", - M_UNIQUE | M_FIGHTER | M_SEE_INVIS | M_SPEAKS | M_FLIES | M_TALL_TILE, + M_UNIQUE | M_FIGHTER | M_SEE_INVIS | M_SPEAKS | M_FLIES | M_TALL_TILE + | M_GENDER_NEUTRAL, MR_RES_POISON | MR_RES_COLD | MR_RES_ELEC, 15, MONS_PANDEMONIUM_LORD, MONS_GLOORX_VLOQ, MH_DEMONIC, MAG_IMMUNE, { {AT_HIT, AF_PLAIN, 45}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -7279,7 +7284,8 @@ DUMMY(MONS_HELL_LORD, '&', COLOUR_UNDEF, "hell lord", TILEP_MONS_PROGRAM_BUG) { MONS_GERYON, '&', GREEN, "Geryon", - M_UNIQUE | M_FIGHTER | M_SEE_INVIS | M_SPEAKS | M_MALE | M_FLIES | M_TALL_TILE, + M_UNIQUE | M_FIGHTER | M_SEE_INVIS | M_SPEAKS | M_MALE | M_FLIES + | M_TALL_TILE, MR_NO_FLAGS, 15, MONS_HELL_LORD, MONS_GERYON, MH_DEMONIC, 120, { {AT_TAIL_SLAP, AF_REACH, 35}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -7293,7 +7299,8 @@ DUMMY(MONS_HELL_LORD, '&', COLOUR_UNDEF, "hell lord", TILEP_MONS_PROGRAM_BUG) { MONS_DISPATER, '&', MAGENTA, "Dispater", - M_UNIQUE | M_FIGHTER | M_SEE_INVIS | M_SPEAKS | M_TALL_TILE, + M_UNIQUE | M_FIGHTER | M_SEE_INVIS | M_SPEAKS | M_TALL_TILE + | M_GENDER_NEUTRAL, mrd(MR_RES_ELEC | MR_RES_FIRE, 3) | MR_RES_POISON | MR_RES_DAMNATION | MR_RES_COLD, 15, MONS_HELL_LORD, MONS_DISPATER, MH_DEMONIC, MAG_IMMUNE, @@ -7307,7 +7314,8 @@ DUMMY(MONS_HELL_LORD, '&', COLOUR_UNDEF, "hell lord", TILEP_MONS_PROGRAM_BUG) { MONS_ASMODEUS, '&', LIGHTRED, "Asmodeus", - M_UNIQUE | M_FIGHTER | M_SEE_INVIS | M_SPEAKS | M_MALE | M_FLIES | M_TALL_TILE, + M_UNIQUE | M_FIGHTER | M_SEE_INVIS | M_SPEAKS | M_MALE | M_FLIES + | M_TALL_TILE, MR_RES_ELEC | MR_RES_POISON | MR_RES_DAMNATION | mrd(MR_RES_FIRE, 3), 25, MONS_HELL_LORD, MONS_ASMODEUS, MH_DEMONIC, MAG_IMMUNE, { {AT_HIT, AF_PLAIN, 50}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, diff --git a/crawl-ref/source/mon-place.cc b/crawl-ref/source/mon-place.cc index c4e3d3d88d6a..46f37b2efee0 100644 --- a/crawl-ref/source/mon-place.cc +++ b/crawl-ref/source/mon-place.cc @@ -1218,7 +1218,7 @@ static monster* _place_monster_aux(const mgen_data &mg, const monster *leader, if (mon->type == MONS_HELLBINDER || mon->type == MONS_CLOUD_MAGE) { mon->props[MON_GENDER_KEY] = random_choose(GENDER_FEMALE, GENDER_MALE, - GENDER_NEUTER); + GENDER_NEUTRAL); } if (mon->has_spell(SPELL_OZOCUBUS_ARMOUR)) From 6dd8730de2082ba4e29eb1a552753443cc4a8422 Mon Sep 17 00:00:00 2001 From: Chris Campbell Date: Sat, 15 Jun 2019 01:33:37 +0100 Subject: [PATCH 438/864] Update CREDITS.txt --- crawl-ref/CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/CREDITS.txt b/crawl-ref/CREDITS.txt index 029dd3c4e923..fdd257948c65 100644 --- a/crawl-ref/CREDITS.txt +++ b/crawl-ref/CREDITS.txt @@ -189,6 +189,7 @@ Vesa Kivimäki Daniel Klein Jon Knapp + Quinten Konyn Ilkka Koskela infiniplex Vambola Kotkas From f98416c20e4994822a2db3167cac49c2498230f0 Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 18 Jun 2019 11:13:42 -0400 Subject: [PATCH 439/864] Don't use locale-sensitive string comparison for table.sort This is leading to seed divergence on different systems depending on locale, most immediately because some locales collate capital letters with their lowercase versions, and some don't. Lua uses locale-sensitive string comparisons unless you override it at build time, and it's not practical to set the locale in a way that avoids this (or at least I haven't managed). Capitalization isn't the only issue that could come up here, either, and it isn't appropriate for internal data to be affected by locale in this way (wtf lua), so this commit just exports c++ string comparison and uses that instead, which should use lexicographic byte ordering. --- .../source/dat/des/variable/d_encompass.des | 2 +- crawl-ref/source/dat/dlua/explorer.lua | 2 +- crawl-ref/source/dat/dlua/layout/zonify.lua | 2 +- crawl-ref/source/dat/dlua/util.lua | 27 ++++++++++++++++--- crawl-ref/source/l-crawl.cc | 18 +++++++++++++ crawl-ref/source/scripts/seed_explorer.lua | 2 +- 6 files changed, 46 insertions(+), 7 deletions(-) diff --git a/crawl-ref/source/dat/des/variable/d_encompass.des b/crawl-ref/source/dat/des/variable/d_encompass.des index a0f09d3aa439..f8a80f33a7ee 100644 --- a/crawl-ref/source/dat/des/variable/d_encompass.des +++ b/crawl-ref/source/dat/des/variable/d_encompass.des @@ -158,7 +158,7 @@ KMONS: t = draconian knight / draconian scorcher / draconian annihilator : end : end : end -: table.sort(kmonsters) +: util.sort(kmonsters) : kmons("s = " .. table.concat(kmonsters, " / ")) KITEM: ? = any ring randart w:390 / ring_of_the_octopus_king KITEM: ! = ring of slaying / ring of wizardry / any good_item ring no_uniq w:75 diff --git a/crawl-ref/source/dat/dlua/explorer.lua b/crawl-ref/source/dat/dlua/explorer.lua index 55cd8a8ef761..b58a309009a4 100644 --- a/crawl-ref/source/dat/dlua/explorer.lua +++ b/crawl-ref/source/dat/dlua/explorer.lua @@ -76,7 +76,7 @@ local out = function(s) if not explorer.quiet then crawl.stderr(s) end end function explorer.collapse_dups(l) local result = {} - table.sort(l) + util.sort(l) local cur = "" local count = 0 for i, name in ipairs(l) do diff --git a/crawl-ref/source/dat/dlua/layout/zonify.lua b/crawl-ref/source/dat/dlua/layout/zonify.lua index fdeff9628efd..b537cd47b663 100644 --- a/crawl-ref/source/dat/dlua/layout/zonify.lua +++ b/crawl-ref/source/dat/dlua/layout/zonify.lua @@ -84,7 +84,7 @@ function zonify.fill_smallest_zones(zonemap, num_to_keep, fgroup, ffill, min_zon local sorted_zones = {} for name,group in pairs(zonemap) do table.insert(sorted_zones, name) end - table.sort(sorted_zones) + util.sort(sorted_zones) for i, name in ipairs(sorted_zones) do group = zonemap[name] if type(fgroup) == "function" and fgroup(group) or name==fgroup then diff --git a/crawl-ref/source/dat/dlua/util.lua b/crawl-ref/source/dat/dlua/util.lua index 2ac71198d36f..d47ddec4fae7 100644 --- a/crawl-ref/source/dat/dlua/util.lua +++ b/crawl-ref/source/dat/dlua/util.lua @@ -118,6 +118,27 @@ function util.pairs(map) return mappairs end +--- a locale-insensitive less-than operation. +function util.stable_lessthan(x1, x2) + if type(t) == "string" then + return crawl.string_compare(s1, s2) == -1 + else + return x1 < x2 + end +end + +--- A wrapper on `table.sort` that uses locale-insensitive comparison for +--- strings by default. Like `table.sort`, this sorts an array in-place. +--- @tparam t an array to sort. +--- @tparam f an optional less-than function to use for determining sort order. +function util.sort(t, f) + if f == nil then + return table.sort(t, util.stable_lessthan) + else + return table.sort(t, f) + end +end + --- Creates a string of the elements in list joined by separator. function util.join(sep, list) return table.concat(list, sep) @@ -313,9 +334,9 @@ function util.random_weighted_keys(weightfn, list, order) keys[#keys+1] = k end if order then - table.sort(keys, order) + util.sort(keys, order) else - table.sort(keys) + util.sort(keys) end for i,k in ipairs(keys) do v = list[k] @@ -334,7 +355,7 @@ function util.sorted_weight_table(t, sort) local keys = { } for k, v in pairs(t) do table.insert(keys, k) end if sort == nil then - table.sort(keys) + util.sort(keys) else table.sort(keys, sort) end diff --git a/crawl-ref/source/l-crawl.cc b/crawl-ref/source/l-crawl.cc index b18d6b25569c..0326b951fe39 100644 --- a/crawl-ref/source/l-crawl.cc +++ b/crawl-ref/source/l-crawl.cc @@ -846,6 +846,23 @@ static int crawl_split(lua_State *ls) return 1; } +/*** Compare two strings in a locale-independent way. + * Lua's built in comparison operations for strings are dependent on locale, + * which isn't always desireable. This is just a wrapper on + * std::basic_string::compare. + * + * @tparam string s1 the first string. + * @tparam string s2 the second sring. + * @treturn -1 if s1 < s2, 1 if s2 < s1, 0 if s1 == s2. + */ +static int crawl_string_compare(lua_State *ls) +{ + const string s1 = luaL_checkstring(ls, 1), + s2 = luaL_checkstring(ls, 2); + lua_pushnumber(ls, s1.compare(s2)); + return 1; +} + /*** Grammatically describe something. * Crawl provides the following description types: * @@ -1390,6 +1407,7 @@ static const struct luaL_reg crawl_clib[] = { "message_filter", crawl_message_filter }, { "trim", crawl_trim }, { "split", crawl_split }, + { "string_compare", crawl_string_compare }, { "grammar", _crawl_grammar }, { "article_a", crawl_article_a }, { "game_started", crawl_game_started }, diff --git a/crawl-ref/source/scripts/seed_explorer.lua b/crawl-ref/source/scripts/seed_explorer.lua index 8c61375dad69..a130dcbb65b3 100644 --- a/crawl-ref/source/scripts/seed_explorer.lua +++ b/crawl-ref/source/scripts/seed_explorer.lua @@ -150,7 +150,7 @@ if args["-show"] ~= nil then if #levels_to_show == 0 then usage_error("\nNo valid levels or depths provided with -show!") end - table.sort(levels_to_show) + util.sort(levels_to_show) if max_depth == nil then max_depth = levels_to_show[#levels_to_show] end local levels_set = util.set(levels_to_show) show_level_fun = function (l) return levels_set[l] end From 27f0392e16c336d4e317aa478f86ffa89c362448 Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 18 Jun 2019 11:18:03 -0400 Subject: [PATCH 440/864] Fix some obscure sequence points that can be builder-triggered Noticed while auditing code, I don't know if this affects any actual seeds. --- crawl-ref/source/mon-ench.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/mon-ench.cc b/crawl-ref/source/mon-ench.cc index 02236e912957..c72b332a7dcb 100644 --- a/crawl-ref/source/mon-ench.cc +++ b/crawl-ref/source/mon-ench.cc @@ -1811,8 +1811,9 @@ void monster::apply_enchantment(const mon_enchant &me) if (res_water_drowning() <= 0) { lose_ench_duration(me, -speed_to_duration(speed)); + int dur = speed_to_duration(speed); // sequence point for randomness int dam = div_rand_round((50 + stepdown((float)me.duration, 30.0)) - * speed_to_duration(speed), + * dur, BASELINE_DELAY * 10); if (res_water_drowning() < 0) dam = dam * 3 / 2; @@ -2299,10 +2300,13 @@ int mon_enchant::calc_duration(const monster* mons, cturn = 1200 / _mod_speed(200, mons->speed); break; case ENCH_SLOWLY_DYING: + { // This may be a little too direct but the randomization at the end // of this function is excessive for toadstools. -cao + int dur = speed_to_duration(mons->speed); // uses div_rand_round, so we need a sequence point return (2 * FRESHEST_CORPSE + random2(10)) - * speed_to_duration(mons->speed); + * dur; + } case ENCH_SPORE_PRODUCTION: // This is used as a simple timer, when the enchantment runs out // the monster will create a ballistomycete spore. From bf76ec32ab3cc14b5662d32cd1df35597702f3c9 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 20 Jun 2019 11:39:39 -0400 Subject: [PATCH 441/864] Don't let locale-specific casing affect ascii characters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a locale changes the upper/lower case correspondents of an ascii character, this would break many things. For example, as in #846, in Turkish (tr_TR.utf8), the lowercase version of I is a dotless i (ı). Since these case functions are used for all sorts of internal purposes (e.g. producing filenames from capitalized tile names), crawl would fail to even start. Though this issue only illustrated the first error, this is the tip of the iceberg and nearly every use of lowercasing was broken in this locale. I think, ideally, we'd be using two different case swapping functions: one for internal data (which is always ASCII) and one for UI-facing strings (which may be in arbitrary UTF-8 encodings). However, when I tried to adjust the API along these lines to fix Turkish, it turned out that there is not a clean distinction in crawlcode between these two uses and even stuff like the name functions which might be expected to be UI-facing are used for internal purposes as well. Based on my attempts, if this does come up for what little localization we have, it would be better/safer to let the ASCII behavior be the default for ascii characters and add in localized casing piecemeal. This commit also adjusts various hotkeys, and I'm not sure what impact this will have (it might be going too far); it could cause problems to e.g. users on a Turkish keyboard. --- crawl-ref/source/cio.cc | 4 +-- crawl-ref/source/command.cc | 2 +- crawl-ref/source/dbg-util.cc | 2 +- crawl-ref/source/describe-god.cc | 4 +-- crawl-ref/source/describe.cc | 6 ++-- crawl-ref/source/hiscores.cc | 6 ++-- crawl-ref/source/item-name.cc | 2 +- crawl-ref/source/libutil.h | 11 +++++++ crawl-ref/source/lookup-help.cc | 8 ++--- crawl-ref/source/macro.cc | 2 +- crawl-ref/source/mon-util.cc | 5 +-- crawl-ref/source/notes.cc | 4 +-- crawl-ref/source/place.cc | 3 +- crawl-ref/source/player-stats.cc | 2 +- crawl-ref/source/prompt.cc | 4 +-- crawl-ref/source/rltiles/tool/tile.h | 33 +++++++++++++++++++ .../rltiles/tool/tile_list_processor.cc | 21 ++++++------ crawl-ref/source/shout.cc | 2 +- crawl-ref/source/skill-menu.cc | 2 +- crawl-ref/source/stairs.cc | 2 +- crawl-ref/source/stringutil.cc | 19 +++++++++-- crawl-ref/source/travel.cc | 2 +- crawl-ref/source/wizard.cc | 2 +- 23 files changed, 104 insertions(+), 44 deletions(-) diff --git a/crawl-ref/source/cio.cc b/crawl-ref/source/cio.cc index b1aa3f7b17b1..6c28320dbcbf 100644 --- a/crawl-ref/source/cio.cc +++ b/crawl-ref/source/cio.cc @@ -94,7 +94,7 @@ int unmangle_direction_keys(int keyin, KeymapContext keymap, cprintf("CTRL"); keyin = getchm(keymap); // return control-key - keyin = CONTROL(toupper(_numpad2vi(keyin))); + keyin = CONTROL(toaupper(_numpad2vi(keyin))); } else if (keyin == '/') { @@ -102,7 +102,7 @@ int unmangle_direction_keys(int keyin, KeymapContext keymap, cprintf("SHIFT"); keyin = getchm(keymap); // return shift-key - keyin = toupper(_numpad2vi(keyin)); + keyin = toaupper(_numpad2vi(keyin)); } } diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc index 4a122c93608b..550fa9a5bf04 100644 --- a/crawl-ref/source/command.cc +++ b/crawl-ref/source/command.cc @@ -1201,7 +1201,7 @@ static int _get_help_section(int section, formatted_string &header_out, formatte text += formatted_string(buf); if (next_is_hotkey && (isaupper(buf[0]) || isadigit(buf[0]))) { - int hotkey = tolower(buf[0]); + int hotkey = toalower(buf[0]); hotkeys[hotkey] = count_occurrences(text.tostring(), "\n"); } diff --git a/crawl-ref/source/dbg-util.cc b/crawl-ref/source/dbg-util.cc index dcfaaa119692..328e7e2f2156 100644 --- a/crawl-ref/source/dbg-util.cc +++ b/crawl-ref/source/dbg-util.cc @@ -472,7 +472,7 @@ void debug_list_vacant_keys() { check(base, string(1, base)); - char lower = tolower(base); + char lower = toalower(base); check(lower, string(1, lower)); char ctrl = CONTROL(base); diff --git a/crawl-ref/source/describe-god.cc b/crawl-ref/source/describe-god.cc index f1b3ae641c5f..cccaa4555111 100644 --- a/crawl-ref/source/describe-god.cc +++ b/crawl-ref/source/describe-god.cc @@ -1360,14 +1360,14 @@ bool describe_god_with_join(god_type which_god) goto update_ui; } - if (keyin != 'Y' && toupper(keyin) != 'N') + if (keyin != 'Y' && toaupper(keyin) != 'N') { yesno_only = true; goto update_ui; } yesno_only = false; - if (toupper(keyin) == 'N') + if (toaupper(keyin) == 'N') { canned_msg(MSG_OK); return done = true; diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index e75cbd5353d5..61b3185c0c77 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -2533,7 +2533,7 @@ static command_type _get_action(int key, vector actions) { CMD_SET_SKILL_TARGET, 's' }, }; - key = tolower(key); + key = toalower(key); for (auto cmd : actions) if (key == act_key.at(cmd)) @@ -3196,7 +3196,7 @@ void describe_spell(spell_type spell, const monster_info *mon_owner, if (ev.type != WME_KEYDOWN) return false; lastch = ev.key.keysym.sym; - done = (toupper(lastch) == 'M' && can_mem || lastch == CK_ESCAPE + done = (toaupper(lastch) == 'M' && can_mem || lastch == CK_ESCAPE || lastch == CK_ENTER || lastch == ' '); return done; }); @@ -3222,7 +3222,7 @@ void describe_spell(spell_type spell, const monster_info *mon_owner, tiles.pop_ui_layout(); #endif - if (toupper(lastch) == 'M' && can_mem) + if (toaupper(lastch) == 'M' && can_mem) { redraw_screen(); // necessary to ensure stats is redrawn (!?) if (!learn_spell(spell) || !you.turn_is_over) diff --git a/crawl-ref/source/hiscores.cc b/crawl-ref/source/hiscores.cc index 970c9e786628..bb33a3c1b117 100644 --- a/crawl-ref/source/hiscores.cc +++ b/crawl-ref/source/hiscores.cc @@ -1313,7 +1313,7 @@ string scorefile_entry::long_kill_message() const { string msg = death_description(DDV_LOGVERBOSE); msg = make_oneline(msg); - msg[0] = tolower(msg[0]); + msg[0] = toalower(msg[0]); trim_string(msg); return msg; } @@ -1322,7 +1322,7 @@ string scorefile_entry::short_kill_message() const { string msg = death_description(DDV_ONELINE); msg = make_oneline(msg); - msg[0] = tolower(msg[0]); + msg[0] = toalower(msg[0]); trim_string(msg); return msg; } @@ -2667,7 +2667,7 @@ string scorefile_entry::death_description(death_desc_verbosity verbosity) const } if (oneline && desc.length() > 2) - desc[1] = tolower(desc[1]); + desc[1] = toalower(desc[1]); // TODO: Eventually, get rid of "..." for cases where the text fits. if (terse) diff --git a/crawl-ref/source/item-name.cc b/crawl-ref/source/item-name.cc index 84a104ca97b6..9c430a64ffb6 100644 --- a/crawl-ref/source/item-name.cc +++ b/crawl-ref/source/item-name.cc @@ -2915,7 +2915,7 @@ string make_name(uint32_t seed, makename_type name_type) ASSERT(name[i] != ' '); if (name_type == MNAME_SCROLL || i == 0 || name[i - 1] == ' ') - uppercased_name += toupper(name[i]); + uppercased_name += toaupper(name[i]); else uppercased_name += name[i]; } diff --git a/crawl-ref/source/libutil.h b/crawl-ref/source/libutil.h index aa3bfea89ddd..70263e91a9ce 100644 --- a/crawl-ref/source/libutil.h +++ b/crawl-ref/source/libutil.h @@ -63,6 +63,17 @@ static inline int toalower(int c) return isaupper(c) ? c + 'a' - 'A' : c; } +static inline char32_t toaupper(char32_t c) +{ + return isalower(c) ? c + 'A' - 'a' : c; +} + +// Same thing with signed int, so we can pass though -1 undisturbed. +static inline int toaupper(int c) +{ + return isalower(c) ? c + 'A' - 'a' : c; +} + int numcmp(const char *a, const char *b, int limit = 0); bool numcmpstr(const string &a, const string &b); diff --git a/crawl-ref/source/lookup-help.cc b/crawl-ref/source/lookup-help.cc index 44e255b5af7e..05886a23850c 100644 --- a/crawl-ref/source/lookup-help.cc +++ b/crawl-ref/source/lookup-help.cc @@ -737,7 +737,7 @@ static MenuEntry* _branch_menu_gen(char letter, const string &str, string &key) const branch_type branch = branch_by_shortname(str); int hotkey = branches[branch].travel_shortcut; - me->hotkeys = {hotkey, tolower(hotkey)}; + me->hotkeys = {hotkey, toalower(hotkey)}; #ifdef USE_TILE me->add_tile(tile_def(tileidx_branch(branch), TEX_FEAT)); #endif @@ -783,10 +783,10 @@ static MenuEntry* _cloud_menu_gen(char letter, const string &str, string &key) string LookupType::prompt_string() const { string prompt_str = lowercase_string(type); - const size_t symbol_pos = prompt_str.find(tolower(symbol)); + const size_t symbol_pos = prompt_str.find(toalower(symbol)); ASSERT(symbol_pos != string::npos); - prompt_str.replace(symbol_pos, 1, make_stringf("(%c)", toupper(symbol))); + prompt_str.replace(symbol_pos, 1, make_stringf("(%c)", toaupper(symbol))); return prompt_str; } @@ -1426,7 +1426,7 @@ static int _lookup_prompt() ch = getchm(); } } - return toupper(ch); + return toaupper(ch); } /** diff --git a/crawl-ref/source/macro.cc b/crawl-ref/source/macro.cc index c09738c2a022..3bf890da9813 100644 --- a/crawl-ref/source/macro.cc +++ b/crawl-ref/source/macro.cc @@ -261,7 +261,7 @@ static int read_key_code(string s) else if (s[0] == '^') { // ^A = 1, etc. - return 1 + toupper(s[1]) - 'A'; + return 1 + toaupper(s[1]) - 'A'; } char *tail; diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index 86cf1f69c531..708bca2eed81 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -192,6 +192,7 @@ void init_mon_name_cache() { string name = me.name; lowercase(name); + dprf("lowercasing %s to %s", me.name, name.c_str()); const int mtype = me.mc; const monster_type mon = monster_type(mtype); @@ -4492,7 +4493,7 @@ string do_mon_str_replacements(const string &in_msg, const monster& mons, msg = replace_all(msg, "@a_something@", mons.name(DESC_A)); msg = replace_all(msg, "@the_something@", mons.name(nocap)); - something[0] = toupper(something[0]); + something[0] = toaupper(something[0]); msg = replace_all(msg, "@Something@", something); msg = replace_all(msg, "@A_something@", mons.name(DESC_A)); msg = replace_all(msg, "@The_something@", mons.name(cap)); @@ -4505,7 +4506,7 @@ string do_mon_str_replacements(const string &in_msg, const monster& mons, msg = replace_all(msg, "@a_monster@", mons.name(DESC_A)); msg = replace_all(msg, "@the_monster@", mons.name(nocap)); - plain[0] = toupper(plain[0]); + plain[0] = toaupper(plain[0]); msg = replace_all(msg, "@Monster@", plain); msg = replace_all(msg, "@A_monster@", mons.name(DESC_A)); msg = replace_all(msg, "@The_monster@", mons.name(cap)); diff --git a/crawl-ref/source/notes.cc b/crawl-ref/source/notes.cc index 67823cf064f7..5d61ee1e2eb4 100644 --- a/crawl-ref/source/notes.cc +++ b/crawl-ref/source/notes.cc @@ -414,7 +414,7 @@ void Note::check_milestone() const string branch = place.describe(true, false); if (starts_with(branch, "The ")) - branch[0] = tolower(branch[0]); + branch[0] = toalower(branch[0]); if (dep == 1) { @@ -426,7 +426,7 @@ void Note::check_milestone() const { string level = place.describe(true, true); if (starts_with(level, "Level ")) - level[0] = tolower(level[0]); + level[0] = toalower(level[0]); mark_milestone(br == BRANCH_ZIGGURAT ? "zig" : "br.end", "reached " + level + "."); diff --git a/crawl-ref/source/place.cc b/crawl-ref/source/place.cc index d98ef59d8a5f..5acc71bc02cc 100644 --- a/crawl-ref/source/place.cc +++ b/crawl-ref/source/place.cc @@ -8,6 +8,7 @@ #include "place.h" #include "branch.h" +#include "libutil.h" #include "player.h" // Prepositional form of branch level name. For example, "in the @@ -16,7 +17,7 @@ string prep_branch_level_name(level_id id) { string place = id.describe(true, true); if (!place.empty() && place != "Pandemonium") - place[0] = tolower(place[0]); + place[0] = toalower(place[0]); return place.find("level") == 0 ? "on " + place : "in " + place; } diff --git a/crawl-ref/source/player-stats.cc b/crawl-ref/source/player-stats.cc index 90f8128f689f..9cfd974575e3 100644 --- a/crawl-ref/source/player-stats.cc +++ b/crawl-ref/source/player-stats.cc @@ -156,7 +156,7 @@ bool attribute_increase() { string result; clua.fnreturns(">s", &result); - keyin = toupper(result[0]); + keyin = toaupper(result[0]); } else { diff --git a/crawl-ref/source/prompt.cc b/crawl-ref/source/prompt.cc index 4304b846c03b..2492021f784f 100644 --- a/crawl-ref/source/prompt.cc +++ b/crawl-ref/source/prompt.cc @@ -137,7 +137,7 @@ bool yesno(const char *str, bool allow_lowercase, int default_answer, bool clear || Options.easy_confirm == easy_confirm_type::safe && allow_lowercase) { - tmp = toupper(tmp); + tmp = toaupper(tmp); } if (clear_after && message) @@ -250,7 +250,7 @@ int yesnoquit(const char* str, bool allow_lowercase, int default_answer, bool al || allow_lowercase && Options.easy_confirm == easy_confirm_type::safe) { - tmp = toupper(tmp); + tmp = toaupper(tmp); } if (clear_after) diff --git a/crawl-ref/source/rltiles/tool/tile.h b/crawl-ref/source/rltiles/tool/tile.h index 175bad30262d..aa83bb006904 100644 --- a/crawl-ref/source/rltiles/tool/tile.h +++ b/crawl-ref/source/rltiles/tool/tile.h @@ -6,6 +6,39 @@ #include using namespace std; +// copied from libutil.h +static inline bool isalower(int c) +{ + return c >= 'a' && c <= 'z'; +} + +static inline bool isaupper(int c) +{ + return c >= 'A' && c <= 'Z'; +} + +static inline char32_t toalower(char32_t c) +{ + return isaupper(c) ? c + 'a' - 'A' : c; +} + +// Same thing with signed int, so we can pass though -1 undisturbed. +static inline int toalower(int c) +{ + return isaupper(c) ? c + 'a' - 'A' : c; +} + +static inline char32_t toaupper(char32_t c) +{ + return isalower(c) ? c + 'A' - 'a' : c; +} + +// Same thing with signed int, so we can pass though -1 undisturbed. +static inline int toaupper(int c) +{ + return isalower(c) ? c + 'A' - 'a' : c; +} + class tile { public: diff --git a/crawl-ref/source/rltiles/tool/tile_list_processor.cc b/crawl-ref/source/rltiles/tool/tile_list_processor.cc index e08bfdd0b2fb..3598600bdce7 100644 --- a/crawl-ref/source/rltiles/tool/tile_list_processor.cc +++ b/crawl-ref/source/rltiles/tool/tile_list_processor.cc @@ -190,7 +190,7 @@ static int str_to_colour(string colour) return 0; for (unsigned int c = 0; c < colour.size(); c++) - colour[c] = tolower(colour[c]); + colour[c] = toalower(colour[c]); for (int i = 0; i < 16; ++i) { @@ -894,8 +894,8 @@ bool tile_list_processor::write_data(bool image, bool code) string ucname = m_name; for (unsigned int i = 0; i < m_name.size(); i++) { - lcname[i] = tolower(m_name[i]); - ucname[i] = toupper(m_name[i]); + lcname[i] = toalower(m_name[i]); + ucname[i] = toaupper(m_name[i]); } string max = m_prefix; max += "_"; @@ -1055,7 +1055,7 @@ bool tile_list_processor::write_data(bool image, bool code) max_enum += "_MAX"; for (char& c : max_enum) - c = toupper(c); + c = toaupper(c); fprintf(fp, " %s_%s_MAX = %s\n};\n\n", m_prefix.c_str(), ucname.c_str(), max_enum.c_str()); } @@ -1112,6 +1112,7 @@ bool tile_list_processor::write_data(bool image, bool code) fprintf(fp, "// This file has been automatically generated.\n\n"); fprintf(fp, "#include \"AppHdr.h\"\n"); + fprintf(fp, "#include \"libutil.h\"\n"); fprintf(fp, "#include \"tiledef-%s.h\"\n\n", lcname.c_str()); fprintf(fp, "static unsigned int _tile_%s_count[%s - %s] =\n{\n", @@ -1258,7 +1259,7 @@ bool tile_list_processor::write_data(bool image, bool code) string lcenum = enumname; for (unsigned int c = 0; c < enumname.size(); c++) - lcenum[c] = tolower(enumname[c]); + lcenum[c] = toalower(enumname[c]); table.insert(sort_map::value_type(lcenum, i)); } @@ -1282,7 +1283,7 @@ bool tile_list_processor::write_data(bool image, bool code) "\n" " string lc = str;\n" " for (unsigned int i = 0; i < lc.size(); i++)\n" - " lc[i] = tolower(lc[i]);\n" + " lc[i] = toalower(lc[i]);\n" "\n" " int num_pairs = sizeof(%s_name_pairs) / sizeof(%s_name_pairs[0]);\n" " bool result = binary_search(\n" @@ -1371,7 +1372,7 @@ bool tile_list_processor::write_data(bool image, bool code) max_enum += "_MAX"; for (char& c : max_enum) - c = toupper(c); + c = toaupper(c); uc_max_enum.push_back(max_enum); @@ -1472,7 +1473,7 @@ bool tile_list_processor::write_data(bool image, bool code) { string lcenum = m_page.m_tiles[i]->enumname(0); for (unsigned int c = 0; c < lcenum.size(); c++) - lcenum[c] = tolower(lcenum[c]); + lcenum[c] = toalower(lcenum[c]); if (i == 0 || m_page.m_counts[i] == 1) fprintf(fp, "%s", lcenum.c_str()); @@ -1704,7 +1705,7 @@ bool tile_list_processor::write_data(bool image, bool code) max_enum += "_MAX"; for (char& c : max_enum) - c = toupper(c); + c = toaupper(c); fprintf(fp, "exports.%s_MAX = window.%s_%s_MAX = %s.%s;\n\n", ucname.c_str(), m_prefix.c_str(), ucname.c_str() @@ -1719,7 +1720,7 @@ bool tile_list_processor::write_data(bool image, bool code) string max_enum = abstract.first; max_enum += "_MAX"; for (char& c : max_enum) - c = toupper(c); + c = toaupper(c); max_enum = abstract.first + "." + max_enum; diff --git a/crawl-ref/source/shout.cc b/crawl-ref/source/shout.cc index b1aa8735c772..afdcb3267ef4 100644 --- a/crawl-ref/source/shout.cc +++ b/crawl-ref/source/shout.cc @@ -521,7 +521,7 @@ static int _issue_orders_prompt() if (!you.cannot_speak()) { string cap_shout = you.shout_verb(false); - cap_shout[0] = toupper(cap_shout[0]); + cap_shout[0] = toaupper(cap_shout[0]); mprf(" t - %s!", cap_shout.c_str()); } diff --git a/crawl-ref/source/skill-menu.cc b/crawl-ref/source/skill-menu.cc index ddd05c2ec391..16d188b48540 100644 --- a/crawl-ref/source/skill-menu.cc +++ b/crawl-ref/source/skill-menu.cc @@ -226,7 +226,7 @@ void SkillMenuEntry::set_name(bool keep_hotkey) if (!keep_hotkey) { m_name->add_hotkey(++m_letter); - m_name->add_hotkey(toupper(m_letter)); + m_name->add_hotkey(toaupper(m_letter)); } m_name->set_id(m_sk); m_name->allow_highlight(true); diff --git a/crawl-ref/source/stairs.cc b/crawl-ref/source/stairs.cc index b3b1eda560dd..fd0f45ee896a 100644 --- a/crawl-ref/source/stairs.cc +++ b/crawl-ref/source/stairs.cc @@ -800,7 +800,7 @@ void floor_transition(dungeon_feature_type how, { string old_branch_string = branches[old_level.branch].longname; if (starts_with(old_branch_string, "The ")) - old_branch_string[0] = tolower(old_branch_string[0]); + old_branch_string[0] = toalower(old_branch_string[0]); mark_milestone("br.exit", "left " + old_branch_string + ".", old_level.describe()); you.branches_left.set(old_level.branch); diff --git a/crawl-ref/source/stringutil.cc b/crawl-ref/source/stringutil.cc index 37c76f3f18e1..5f22eb7c0ade 100644 --- a/crawl-ref/source/stringutil.cc +++ b/crawl-ref/source/stringutil.cc @@ -44,7 +44,16 @@ string lowercase_string(const string &s) char32_t c; char buf[4]; for (const char *tp = s.c_str(); int len = utf8towc(&c, tp); tp += len) - res.append(buf, wctoutf8(buf, towlower(c))); + { + // crawl breaks horribly if this is allowed to affect ascii chars, + // so override locale-specific casing for ascii. (For example, in + // Turkish; tr_TR.utf8 lowercase I is a dotless i that is not + // ascii, which breaks many things.) + if (isaalpha(tp[0])) + res.append(1, toalower(tp[0])); + else + res.append(buf, wctoutf8(buf, towlower(c))); + } return res; } @@ -57,8 +66,12 @@ string &lowercase(string &s) string &uppercase(string &s) { for (char &ch : s) - ch = toupper(ch); - + { + if (isaalpha(ch)) + ch = toaupper(ch); + else + ch = toupper(ch); + } return s; } diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc index a716e5f5cca4..d6d17992b4c6 100644 --- a/crawl-ref/source/travel.cc +++ b/crawl-ref/source/travel.cc @@ -2175,7 +2175,7 @@ static int _prompt_travel_branch(int prompt_flags) // Is this a branch hotkey? for (branch_type br : brs) { - if (toupper(keyin) == branches[br].travel_shortcut) + if (toaupper(keyin) == branches[br].travel_shortcut) { #ifdef WIZARD const Branch &target = branches[br]; diff --git a/crawl-ref/source/wizard.cc b/crawl-ref/source/wizard.cc index 8c73062f23b2..7835941d81d9 100644 --- a/crawl-ref/source/wizard.cc +++ b/crawl-ref/source/wizard.cc @@ -316,7 +316,7 @@ void handle_wizard_command() cursor_control con(true); wiz_command = getchm(); if (wiz_command == '*') - wiz_command = CONTROL(toupper(getchm())); + wiz_command = CONTROL(toaupper(getchm())); } if (crawl_state.cmd_repeat_start) From 80245de3859f936dd0aa1445b5e46714254ab2d7 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 20 Jun 2019 12:20:11 -0400 Subject: [PATCH 442/864] Better handling for single-char case swaps This restores any locale-specific casing behavior for non-ascii characters that might have been removed by bf76ec3. --- crawl-ref/source/cio.cc | 4 ++-- crawl-ref/source/command.cc | 2 +- crawl-ref/source/dbg-util.cc | 2 +- crawl-ref/source/describe-god.cc | 4 ++-- crawl-ref/source/describe.cc | 6 +++--- crawl-ref/source/hiscores.cc | 6 +++--- crawl-ref/source/item-name.cc | 2 +- crawl-ref/source/libutil.h | 10 ++++++++++ crawl-ref/source/lookup-help.cc | 8 ++++---- crawl-ref/source/macro.cc | 2 +- crawl-ref/source/mon-util.cc | 5 ++--- crawl-ref/source/notes.cc | 4 ++-- crawl-ref/source/place.cc | 2 +- crawl-ref/source/player-stats.cc | 2 +- crawl-ref/source/prompt.cc | 4 ++-- crawl-ref/source/shout.cc | 2 +- crawl-ref/source/skill-menu.cc | 2 +- crawl-ref/source/stairs.cc | 2 +- crawl-ref/source/stringutil.cc | 7 +------ crawl-ref/source/travel.cc | 2 +- crawl-ref/source/wizard.cc | 2 +- 21 files changed, 42 insertions(+), 38 deletions(-) diff --git a/crawl-ref/source/cio.cc b/crawl-ref/source/cio.cc index 6c28320dbcbf..cdf902e9d219 100644 --- a/crawl-ref/source/cio.cc +++ b/crawl-ref/source/cio.cc @@ -94,7 +94,7 @@ int unmangle_direction_keys(int keyin, KeymapContext keymap, cprintf("CTRL"); keyin = getchm(keymap); // return control-key - keyin = CONTROL(toaupper(_numpad2vi(keyin))); + keyin = CONTROL(toupper_safe(_numpad2vi(keyin))); } else if (keyin == '/') { @@ -102,7 +102,7 @@ int unmangle_direction_keys(int keyin, KeymapContext keymap, cprintf("SHIFT"); keyin = getchm(keymap); // return shift-key - keyin = toaupper(_numpad2vi(keyin)); + keyin = toupper_safe(_numpad2vi(keyin)); } } diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc index 550fa9a5bf04..165303c09f1f 100644 --- a/crawl-ref/source/command.cc +++ b/crawl-ref/source/command.cc @@ -1201,7 +1201,7 @@ static int _get_help_section(int section, formatted_string &header_out, formatte text += formatted_string(buf); if (next_is_hotkey && (isaupper(buf[0]) || isadigit(buf[0]))) { - int hotkey = toalower(buf[0]); + int hotkey = tolower_safe(buf[0]); hotkeys[hotkey] = count_occurrences(text.tostring(), "\n"); } diff --git a/crawl-ref/source/dbg-util.cc b/crawl-ref/source/dbg-util.cc index 328e7e2f2156..522d042db412 100644 --- a/crawl-ref/source/dbg-util.cc +++ b/crawl-ref/source/dbg-util.cc @@ -472,7 +472,7 @@ void debug_list_vacant_keys() { check(base, string(1, base)); - char lower = toalower(base); + char lower = tolower_safe(base); check(lower, string(1, lower)); char ctrl = CONTROL(base); diff --git a/crawl-ref/source/describe-god.cc b/crawl-ref/source/describe-god.cc index cccaa4555111..463bff701997 100644 --- a/crawl-ref/source/describe-god.cc +++ b/crawl-ref/source/describe-god.cc @@ -1360,14 +1360,14 @@ bool describe_god_with_join(god_type which_god) goto update_ui; } - if (keyin != 'Y' && toaupper(keyin) != 'N') + if (keyin != 'Y' && toupper_safe(keyin) != 'N') { yesno_only = true; goto update_ui; } yesno_only = false; - if (toaupper(keyin) == 'N') + if (toupper_safe(keyin) == 'N') { canned_msg(MSG_OK); return done = true; diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index 61b3185c0c77..ab61ba38e60c 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -2533,7 +2533,7 @@ static command_type _get_action(int key, vector actions) { CMD_SET_SKILL_TARGET, 's' }, }; - key = toalower(key); + key = tolower_safe(key); for (auto cmd : actions) if (key == act_key.at(cmd)) @@ -3196,7 +3196,7 @@ void describe_spell(spell_type spell, const monster_info *mon_owner, if (ev.type != WME_KEYDOWN) return false; lastch = ev.key.keysym.sym; - done = (toaupper(lastch) == 'M' && can_mem || lastch == CK_ESCAPE + done = (toupper_safe(lastch) == 'M' && can_mem || lastch == CK_ESCAPE || lastch == CK_ENTER || lastch == ' '); return done; }); @@ -3222,7 +3222,7 @@ void describe_spell(spell_type spell, const monster_info *mon_owner, tiles.pop_ui_layout(); #endif - if (toaupper(lastch) == 'M' && can_mem) + if (toupper_safe(lastch) == 'M' && can_mem) { redraw_screen(); // necessary to ensure stats is redrawn (!?) if (!learn_spell(spell) || !you.turn_is_over) diff --git a/crawl-ref/source/hiscores.cc b/crawl-ref/source/hiscores.cc index bb33a3c1b117..845f6e3f1849 100644 --- a/crawl-ref/source/hiscores.cc +++ b/crawl-ref/source/hiscores.cc @@ -1313,7 +1313,7 @@ string scorefile_entry::long_kill_message() const { string msg = death_description(DDV_LOGVERBOSE); msg = make_oneline(msg); - msg[0] = toalower(msg[0]); + msg[0] = tolower_safe(msg[0]); trim_string(msg); return msg; } @@ -1322,7 +1322,7 @@ string scorefile_entry::short_kill_message() const { string msg = death_description(DDV_ONELINE); msg = make_oneline(msg); - msg[0] = toalower(msg[0]); + msg[0] = tolower_safe(msg[0]); trim_string(msg); return msg; } @@ -2667,7 +2667,7 @@ string scorefile_entry::death_description(death_desc_verbosity verbosity) const } if (oneline && desc.length() > 2) - desc[1] = toalower(desc[1]); + desc[1] = tolower_safe(desc[1]); // TODO: Eventually, get rid of "..." for cases where the text fits. if (terse) diff --git a/crawl-ref/source/item-name.cc b/crawl-ref/source/item-name.cc index 9c430a64ffb6..31e5f4a44f9b 100644 --- a/crawl-ref/source/item-name.cc +++ b/crawl-ref/source/item-name.cc @@ -2915,7 +2915,7 @@ string make_name(uint32_t seed, makename_type name_type) ASSERT(name[i] != ' '); if (name_type == MNAME_SCROLL || i == 0 || name[i - 1] == ' ') - uppercased_name += toaupper(name[i]); + uppercased_name += toupper_safe(name[i]); else uppercased_name += name[i]; } diff --git a/crawl-ref/source/libutil.h b/crawl-ref/source/libutil.h index 70263e91a9ce..507398c056e2 100644 --- a/crawl-ref/source/libutil.h +++ b/crawl-ref/source/libutil.h @@ -74,6 +74,16 @@ static inline int toaupper(int c) return isalower(c) ? c + 'A' - 'a' : c; } +template inline T tolower_safe(T c) +{ + return isaupper(c) ? toalower(c) : tolower(c); +} + +template inline T toupper_safe(T c) +{ + return isalower(c) ? toaupper(c) : toupper(c); +} + int numcmp(const char *a, const char *b, int limit = 0); bool numcmpstr(const string &a, const string &b); diff --git a/crawl-ref/source/lookup-help.cc b/crawl-ref/source/lookup-help.cc index 05886a23850c..e87883ee4260 100644 --- a/crawl-ref/source/lookup-help.cc +++ b/crawl-ref/source/lookup-help.cc @@ -737,7 +737,7 @@ static MenuEntry* _branch_menu_gen(char letter, const string &str, string &key) const branch_type branch = branch_by_shortname(str); int hotkey = branches[branch].travel_shortcut; - me->hotkeys = {hotkey, toalower(hotkey)}; + me->hotkeys = {hotkey, tolower_safe(hotkey)}; #ifdef USE_TILE me->add_tile(tile_def(tileidx_branch(branch), TEX_FEAT)); #endif @@ -783,10 +783,10 @@ static MenuEntry* _cloud_menu_gen(char letter, const string &str, string &key) string LookupType::prompt_string() const { string prompt_str = lowercase_string(type); - const size_t symbol_pos = prompt_str.find(toalower(symbol)); + const size_t symbol_pos = prompt_str.find(tolower_safe(symbol)); ASSERT(symbol_pos != string::npos); - prompt_str.replace(symbol_pos, 1, make_stringf("(%c)", toaupper(symbol))); + prompt_str.replace(symbol_pos, 1, make_stringf("(%c)", toupper_safe(symbol))); return prompt_str; } @@ -1426,7 +1426,7 @@ static int _lookup_prompt() ch = getchm(); } } - return toaupper(ch); + return toupper_safe(ch); } /** diff --git a/crawl-ref/source/macro.cc b/crawl-ref/source/macro.cc index 3bf890da9813..f4abd68e5a96 100644 --- a/crawl-ref/source/macro.cc +++ b/crawl-ref/source/macro.cc @@ -261,7 +261,7 @@ static int read_key_code(string s) else if (s[0] == '^') { // ^A = 1, etc. - return 1 + toaupper(s[1]) - 'A'; + return 1 + toupper_safe(s[1]) - 'A'; } char *tail; diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index 708bca2eed81..da56a7517e0c 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -192,7 +192,6 @@ void init_mon_name_cache() { string name = me.name; lowercase(name); - dprf("lowercasing %s to %s", me.name, name.c_str()); const int mtype = me.mc; const monster_type mon = monster_type(mtype); @@ -4493,7 +4492,7 @@ string do_mon_str_replacements(const string &in_msg, const monster& mons, msg = replace_all(msg, "@a_something@", mons.name(DESC_A)); msg = replace_all(msg, "@the_something@", mons.name(nocap)); - something[0] = toaupper(something[0]); + something[0] = toupper_safe(something[0]); msg = replace_all(msg, "@Something@", something); msg = replace_all(msg, "@A_something@", mons.name(DESC_A)); msg = replace_all(msg, "@The_something@", mons.name(cap)); @@ -4506,7 +4505,7 @@ string do_mon_str_replacements(const string &in_msg, const monster& mons, msg = replace_all(msg, "@a_monster@", mons.name(DESC_A)); msg = replace_all(msg, "@the_monster@", mons.name(nocap)); - plain[0] = toaupper(plain[0]); + plain[0] = toupper_safe(plain[0]); msg = replace_all(msg, "@Monster@", plain); msg = replace_all(msg, "@A_monster@", mons.name(DESC_A)); msg = replace_all(msg, "@The_monster@", mons.name(cap)); diff --git a/crawl-ref/source/notes.cc b/crawl-ref/source/notes.cc index 5d61ee1e2eb4..aa03496b4853 100644 --- a/crawl-ref/source/notes.cc +++ b/crawl-ref/source/notes.cc @@ -414,7 +414,7 @@ void Note::check_milestone() const string branch = place.describe(true, false); if (starts_with(branch, "The ")) - branch[0] = toalower(branch[0]); + branch[0] = tolower_safe(branch[0]); if (dep == 1) { @@ -426,7 +426,7 @@ void Note::check_milestone() const { string level = place.describe(true, true); if (starts_with(level, "Level ")) - level[0] = toalower(level[0]); + level[0] = tolower_safe(level[0]); mark_milestone(br == BRANCH_ZIGGURAT ? "zig" : "br.end", "reached " + level + "."); diff --git a/crawl-ref/source/place.cc b/crawl-ref/source/place.cc index 5acc71bc02cc..735cd2d58425 100644 --- a/crawl-ref/source/place.cc +++ b/crawl-ref/source/place.cc @@ -17,7 +17,7 @@ string prep_branch_level_name(level_id id) { string place = id.describe(true, true); if (!place.empty() && place != "Pandemonium") - place[0] = toalower(place[0]); + place[0] = tolower_safe(place[0]); return place.find("level") == 0 ? "on " + place : "in " + place; } diff --git a/crawl-ref/source/player-stats.cc b/crawl-ref/source/player-stats.cc index 9cfd974575e3..b1ade9dfb781 100644 --- a/crawl-ref/source/player-stats.cc +++ b/crawl-ref/source/player-stats.cc @@ -156,7 +156,7 @@ bool attribute_increase() { string result; clua.fnreturns(">s", &result); - keyin = toaupper(result[0]); + keyin = toupper_safe(result[0]); } else { diff --git a/crawl-ref/source/prompt.cc b/crawl-ref/source/prompt.cc index 2492021f784f..a22337ceb84e 100644 --- a/crawl-ref/source/prompt.cc +++ b/crawl-ref/source/prompt.cc @@ -137,7 +137,7 @@ bool yesno(const char *str, bool allow_lowercase, int default_answer, bool clear || Options.easy_confirm == easy_confirm_type::safe && allow_lowercase) { - tmp = toaupper(tmp); + tmp = toupper_safe(tmp); } if (clear_after && message) @@ -250,7 +250,7 @@ int yesnoquit(const char* str, bool allow_lowercase, int default_answer, bool al || allow_lowercase && Options.easy_confirm == easy_confirm_type::safe) { - tmp = toaupper(tmp); + tmp = toupper_safe(tmp); } if (clear_after) diff --git a/crawl-ref/source/shout.cc b/crawl-ref/source/shout.cc index afdcb3267ef4..53c0281aa147 100644 --- a/crawl-ref/source/shout.cc +++ b/crawl-ref/source/shout.cc @@ -521,7 +521,7 @@ static int _issue_orders_prompt() if (!you.cannot_speak()) { string cap_shout = you.shout_verb(false); - cap_shout[0] = toaupper(cap_shout[0]); + cap_shout[0] = toupper_safe(cap_shout[0]); mprf(" t - %s!", cap_shout.c_str()); } diff --git a/crawl-ref/source/skill-menu.cc b/crawl-ref/source/skill-menu.cc index 16d188b48540..000f1ef1ed33 100644 --- a/crawl-ref/source/skill-menu.cc +++ b/crawl-ref/source/skill-menu.cc @@ -226,7 +226,7 @@ void SkillMenuEntry::set_name(bool keep_hotkey) if (!keep_hotkey) { m_name->add_hotkey(++m_letter); - m_name->add_hotkey(toaupper(m_letter)); + m_name->add_hotkey(toupper_safe(m_letter)); } m_name->set_id(m_sk); m_name->allow_highlight(true); diff --git a/crawl-ref/source/stairs.cc b/crawl-ref/source/stairs.cc index fd0f45ee896a..8ef208e2caf1 100644 --- a/crawl-ref/source/stairs.cc +++ b/crawl-ref/source/stairs.cc @@ -800,7 +800,7 @@ void floor_transition(dungeon_feature_type how, { string old_branch_string = branches[old_level.branch].longname; if (starts_with(old_branch_string, "The ")) - old_branch_string[0] = toalower(old_branch_string[0]); + old_branch_string[0] = tolower_safe(old_branch_string[0]); mark_milestone("br.exit", "left " + old_branch_string + ".", old_level.describe()); you.branches_left.set(old_level.branch); diff --git a/crawl-ref/source/stringutil.cc b/crawl-ref/source/stringutil.cc index 5f22eb7c0ade..a707ff65ea24 100644 --- a/crawl-ref/source/stringutil.cc +++ b/crawl-ref/source/stringutil.cc @@ -66,12 +66,7 @@ string &lowercase(string &s) string &uppercase(string &s) { for (char &ch : s) - { - if (isaalpha(ch)) - ch = toaupper(ch); - else - ch = toupper(ch); - } + ch = toupper_safe(ch); return s; } diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc index d6d17992b4c6..70f6d388c52e 100644 --- a/crawl-ref/source/travel.cc +++ b/crawl-ref/source/travel.cc @@ -2175,7 +2175,7 @@ static int _prompt_travel_branch(int prompt_flags) // Is this a branch hotkey? for (branch_type br : brs) { - if (toaupper(keyin) == branches[br].travel_shortcut) + if (toupper_safe(keyin) == branches[br].travel_shortcut) { #ifdef WIZARD const Branch &target = branches[br]; diff --git a/crawl-ref/source/wizard.cc b/crawl-ref/source/wizard.cc index 7835941d81d9..0b2113339650 100644 --- a/crawl-ref/source/wizard.cc +++ b/crawl-ref/source/wizard.cc @@ -316,7 +316,7 @@ void handle_wizard_command() cursor_control con(true); wiz_command = getchm(); if (wiz_command == '*') - wiz_command = CONTROL(toaupper(getchm())); + wiz_command = CONTROL(toupper_safe(getchm())); } if (crawl_state.cmd_repeat_start) From f09efd6d0bed66322416ae6ba191198941b96da1 Mon Sep 17 00:00:00 2001 From: Alex Jurkiewicz Date: Thu, 13 Jun 2019 17:29:39 +1000 Subject: [PATCH 443/864] Guard against out of bounds array access --- crawl-ref/source/describe.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index ab61ba38e60c..fc3283da5881 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -3841,6 +3841,7 @@ COMPILE_CHECK(ARRAYSZ(size_adj) == NUM_SIZE_LEVELS); // This is used in monster description and on '%' screen for player size const char* get_size_adj(const size_type size, bool ignore_medium) { + ASSERT_RANGE(static_cast(size), 0, ARRAYSZ(size_adj)); if (ignore_medium && size == SIZE_MEDIUM) return nullptr; // don't mention medium size return size_adj[size]; From d5110b030ae9ae561ab613044044abfc1576c71f Mon Sep 17 00:00:00 2001 From: dplusplus Date: Tue, 11 Jun 2019 09:04:54 +0900 Subject: [PATCH 444/864] Add stop for Merfolk fake-mutation description --- crawl-ref/source/dat/species/merfolk.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/dat/species/merfolk.yaml b/crawl-ref/source/dat/species/merfolk.yaml index 76825a6a53a1..fc3b859dff56 100644 --- a/crawl-ref/source/dat/species/merfolk.yaml +++ b/crawl-ref/source/dat/species/merfolk.yaml @@ -42,7 +42,7 @@ int: 7 dex: 9 levelup_stat_frequency: 5 fake_mutations: - - long: You revert to your normal form in water + - long: You revert to your normal form in water. short: change form in water - long: You are very nimble and swift while swimming. short: swift swim From 87df7205b4690a58f4d7bf59979662eed7397d2a Mon Sep 17 00:00:00 2001 From: Alex Jurkiewicz Date: Sun, 23 Jun 2019 07:58:16 +1000 Subject: [PATCH 445/864] Don't ignore torment damage for Jiyva jelly spawns (#1088) And also Xom butterfly spawns. This exception dates back to when Jiyva was first introduced (in 0.6.0-a0-258-g6d7627cb65). It's an exception which isn't mentioned anywhere to the player and probably unnecessary in terms of balance for both gods. --- crawl-ref/source/ouch.cc | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/crawl-ref/source/ouch.cc b/crawl-ref/source/ouch.cc index e4bceb02ee7c..9d3abdb07604 100644 --- a/crawl-ref/source/ouch.cc +++ b/crawl-ref/source/ouch.cc @@ -533,8 +533,7 @@ static void _maybe_ru_retribution(int dam, mid_t death_source) } } -static void _maybe_spawn_monsters(int dam, const bool is_torment, - kill_method_type death_type, +static void _maybe_spawn_monsters(int dam, kill_method_type death_type, mid_t death_source) { monster* damager = monster_by_mid(death_source); @@ -543,10 +542,6 @@ static void _maybe_spawn_monsters(int dam, const bool is_torment, if (!damager) return; - // Exclude torment damage. Ugh. - if (is_torment) - return; - monster_type mon; int how_many = 0; @@ -797,10 +792,6 @@ void ouch(int dam, kill_method_type death_type, mid_t source, const char *aux, int drain_amount = 0; - const bool is_torment = (aux && (strstr(aux, "torment") - || strstr(aux, "Torment") - || strstr(aux, "exploding lurking horror"))); - // Multiply damage if amulet of harm is in play if (dam != INSTANT_DEATH) dam = _apply_extra_harm(dam, source); @@ -958,7 +949,7 @@ void ouch(int dam, kill_method_type death_type, mid_t source, const char *aux, _deteriorate(dam); _yred_mirrors_injury(dam, source); _maybe_ru_retribution(dam, source); - _maybe_spawn_monsters(dam, is_torment, death_type, source); + _maybe_spawn_monsters(dam, death_type, source); _maybe_fog(dam); _powered_by_pain(dam); if (sanguine_armour_valid()) From e8da9206dcf968f6ef8c376723c9dfc58d2cd1a9 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 24 Jun 2019 14:10:52 -0400 Subject: [PATCH 446/864] Fix lua sorting in f98416c20 ...and demonstrate basic programming competence. (Though partial blame goes to lua scoping.) --- crawl-ref/source/dat/dlua/util.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/dat/dlua/util.lua b/crawl-ref/source/dat/dlua/util.lua index d47ddec4fae7..3eea18b234d6 100644 --- a/crawl-ref/source/dat/dlua/util.lua +++ b/crawl-ref/source/dat/dlua/util.lua @@ -120,8 +120,8 @@ end --- a locale-insensitive less-than operation. function util.stable_lessthan(x1, x2) - if type(t) == "string" then - return crawl.string_compare(s1, s2) == -1 + if type(x1) == "string" then + return crawl.string_compare(x1, x2) < 0 else return x1 < x2 end From 8f2d45b691dc0e18d645d593e43fdf87dfd8f4cd Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 25 Jun 2019 09:54:37 -0400 Subject: [PATCH 447/864] Sort tags_string() again This is a regression from 80c1907ebbf6. --- crawl-ref/source/mapdef.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc index ee811fdafe2e..7258f931bf2f 100644 --- a/crawl-ref/source/mapdef.cc +++ b/crawl-ref/source/mapdef.cc @@ -3378,7 +3378,8 @@ void map_def::set_tags(const string &tag) string map_def::tags_string() const { - return join_strings(tags.begin(), tags.end()); + auto sorted_tags = get_tags(); + return join_strings(sorted_tags.begin(), sorted_tags.end()); } keyed_mapspec *map_def::mapspec_at(const coord_def &c) From c0fab7842f11dc1db4698ee9e711216b27c615b4 Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 25 Jun 2019 10:00:12 -0400 Subject: [PATCH 448/864] Fix a des cache random tag issue See f57072b2d696. I suspect this has been responsible for a whole bunch of issues where beast_lair_carwin maps have been showing up. --- crawl-ref/source/dat/des/branches/lair.des | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/dat/des/branches/lair.des b/crawl-ref/source/dat/des/branches/lair.des index 5db90565581b..afa953501c86 100644 --- a/crawl-ref/source/dat/des/branches/lair.des +++ b/crawl-ref/source/dat/des/branches/lair.des @@ -58,7 +58,9 @@ function beast_lair_populate_mons_large(e) if you.depth() > 3 then set = set + 3 end - e.tags("no_monster_gen") + if not e.is_validating() then + e.tags("no_monster_gen") + end e.mons("plant") -- 1 is always plant. if set == 0 then e.mons("hound / wolf") From 1dd085888ca359b820f08486262821c3e0db055f Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 25 Jun 2019 10:28:55 -0400 Subject: [PATCH 449/864] More des cache stability fixes Aiming for completely reproducible des caches, at least relative to a particular system. --- crawl-ref/source/dat/des/arrival/twisted.des | 2 +- crawl-ref/source/dat/des/branches/temple_compat.des | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crawl-ref/source/dat/des/arrival/twisted.des b/crawl-ref/source/dat/des/arrival/twisted.des index 751dde2cf6c3..5590f4bfdc44 100644 --- a/crawl-ref/source/dat/des/arrival/twisted.des +++ b/crawl-ref/source/dat/des/arrival/twisted.des @@ -556,7 +556,7 @@ SHUFFLE: {}, XXT COLOUR: ' : brown / white FTILE: ' = floor_dirt SUBST: '=., X=x, T:tttT, T=t x:1 -: if crawl.coinflip() then +: if not is_validating() and crawl.coinflip() then TAGS: no_pool_fixup : end WEIGHT: 3 diff --git a/crawl-ref/source/dat/des/branches/temple_compat.des b/crawl-ref/source/dat/des/branches/temple_compat.des index 37d7f9e369d8..3e20a0edc1f6 100644 --- a/crawl-ref/source/dat/des/branches/temple_compat.des +++ b/crawl-ref/source/dat/des/branches/temple_compat.des @@ -713,7 +713,7 @@ ENDMAP NAME: minmay_temple_bridge_a_8 TAGS: no_pool_fixup SUBST: A : TUV -: if crawl.one_chance_in(10) then +: if not is_validating() and crawl.one_chance_in(10) then SUBST: w = l : set_border_fill_type("endless_lava") : else @@ -759,7 +759,7 @@ ENDMAP NAME: minmay_temple_bridge_b_8 TAGS: no_pool_fixup SUBST: A : TUV -: if crawl.one_chance_in(10) then +: if not is_validating() and crawl.one_chance_in(10) then SUBST: w = l : set_border_fill_type("endless_lava") : else @@ -805,7 +805,7 @@ ENDMAP NAME: minmay_temple_bridge_c_8 TAGS: no_pool_fixup SUBST: A : TUV -: if crawl.one_chance_in(10) then +: if not is_validating() and crawl.one_chance_in(10) then SUBST: w = l : set_border_fill_type("endless_lava") : else @@ -851,7 +851,7 @@ ENDMAP NAME: minmay_temple_bridge_d_8 TAGS: no_pool_fixup SUBST: A : TUV -: if crawl.one_chance_in(10) then +: if not is_validating() and crawl.one_chance_in(10) then SUBST: w = l : set_border_fill_type("endless_lava") : else From 263dff2034ed8b9b189f66d8d7583cef5eee241f Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 25 Jun 2019 17:29:32 -0400 Subject: [PATCH 450/864] Tweak the beast_lair_carwin fix For vaults that call the `large` monster function unconditionally, let the tags in the des cache be adjusted. This will keep the behavior of randomization more like before the first fix. --- crawl-ref/source/dat/des/branches/lair.des | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/dat/des/branches/lair.des b/crawl-ref/source/dat/des/branches/lair.des index afa953501c86..442e915e69a1 100644 --- a/crawl-ref/source/dat/des/branches/lair.des +++ b/crawl-ref/source/dat/des/branches/lair.des @@ -58,9 +58,7 @@ function beast_lair_populate_mons_large(e) if you.depth() > 3 then set = set + 3 end - if not e.is_validating() then - e.tags("no_monster_gen") - end + e.tags("no_monster_gen") e.mons("plant") -- 1 is always plant. if set == 0 then e.mons("hound / wolf") @@ -90,7 +88,8 @@ function beast_lair_populate_mons_large(e) end function beast_lair_populate_mons_small(e) - if crawl.one_chance_in(25) then + -- don't do this while validating because this call changes the tags + if not e.is_validating() and crawl.one_chance_in(25) then beast_lair_populate_mons_large(e) else local monster_list = {} From 26b8ecb3bfd179ec83e93c5f3e31c4b2657877b7 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Sat, 15 Jun 2019 21:55:27 -0500 Subject: [PATCH 451/864] Sif Rework Part 1: Piety on kills Sif Muna has some major design issues that weren't resolved the last time she was changed in version 0.19. This commit is the first in a series to change Sif's piety gain, her MP-related abilities, and to add a new high piety cost spell casting active ability. Sif's biggest issue is piety gain. She receives some piety from kills but also piety from training schools related to casting spells. The latter system has never worked well in practice. Players starting with spells want to train spell skills in order to get spells castable but generally want to switch to defensive skills or other suitably lower-cost skills afterwards. Sif currently tries to encourage training spell skills past this point to get gifts, but players trying to survive ignore this incentive for some time. The decision of whether to train spell schools for gifts is thus not an interesting one, since the answer is generally just to wait for them to happen naturally. This commit gives Sif normal piety on kills. We lose a distinct piety gain system, but her skill training system never worked well in either the full or partial versions. --- crawl-ref/source/god-conduct.cc | 50 ++++----------------------------- crawl-ref/source/religion.cc | 2 +- 2 files changed, 6 insertions(+), 46 deletions(-) diff --git a/crawl-ref/source/god-conduct.cc b/crawl-ref/source/god-conduct.cc index 358427328628..61fc46f0c792 100644 --- a/crawl-ref/source/god-conduct.cc +++ b/crawl-ref/source/god-conduct.cc @@ -773,51 +773,11 @@ static like_map divine_likes[] = }, // GOD_SIF_MUNA, { - { DID_KILL_LIVING, _on_kill("you kill living beings", MH_NATURAL, false, - [](int &piety, int &denom, - const monster* victim) - { - denom *= 3; - } - ) }, - { DID_KILL_UNDEAD, _on_kill("you destroy the undead", MH_UNDEAD, false, - [](int &piety, int &denom, - const monster* victim) - { - denom *= 3; - } - ) }, - { DID_KILL_DEMON, _on_kill("you kill demons", MH_DEMONIC, false, - [](int &piety, int &denom, - const monster* victim) - { - denom *= 3; - } - ) }, - { DID_KILL_HOLY, _on_kill("you kill holy beings", MH_HOLY, false, - [](int &piety, int &denom, - const monster* victim) - { - denom *= 3; - } - ) }, - { DID_KILL_NONLIVING, _on_kill("you destroy nonliving beings", - MH_NONLIVING, false, - [](int &piety, int &denom, - const monster* victim) - { - denom *= 3; - } - ) }, - { DID_SPELL_PRACTISE, { - "you train your various spell casting skills", true, - 0, 0, 0, nullptr, - [] (int &piety, int &denom, const monster* /*victim*/) - { - // piety = denom = level at the start of the function - denom = 6; - } - } }, + { DID_KILL_LIVING, KILL_LIVING_RESPONSE }, + { DID_KILL_UNDEAD, KILL_UNDEAD_RESPONSE }, + { DID_KILL_DEMON, KILL_DEMON_RESPONSE }, + { DID_KILL_HOLY, KILL_HOLY_RESPONSE }, + { DID_KILL_NONLIVING, KILL_NONLIVING_RESPONSE }, }, // GOD_TROG, { diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index a7ce6de99cab..2da167107f2d 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -4089,6 +4089,7 @@ void handle_god_time(int /*time_delta*/) #endif case GOD_JIYVA: case GOD_WU_JIAN: + case GOD_SIF_MUNA: if (one_chance_in(17)) lose_piety(1); break; @@ -4098,7 +4099,6 @@ void handle_god_time(int /*time_delta*/) case GOD_HEPLIAKLQANA: case GOD_FEDHAS: case GOD_CHEIBRIADOS: - case GOD_SIF_MUNA: case GOD_SHINING_ONE: case GOD_NEMELEX_XOBEH: if (one_chance_in(35)) From 3db0654b3e36291c269ba4210591d721d19112c5 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Sat, 15 Jun 2019 22:00:46 -0500 Subject: [PATCH 452/864] Sif Rework Part 2: Grant some abilities earlier Sif currently has two MP restoration abilities, Divine Energy granted at 1* and Channel Energy granted at 3*. Sif doesn't need two MP restoration abilities, and Channel Energy works better in practice than Divine Energy in terms of UI and in terms of effectiveness throughout the game. Hence we'll remove Divine Energy in a subsequent commit and move Channel Energy to 1*. Its piety cost remains the same. This commit also moves Forget Spell to 3* piety, since we'll be adding a new ability at 4*. --- crawl-ref/source/ability.cc | 4 ++-- crawl-ref/source/religion.cc | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crawl-ref/source/ability.cc b/crawl-ref/source/ability.cc index db2e32c1c51d..43ce012659cf 100644 --- a/crawl-ref/source/ability.cc +++ b/crawl-ref/source/ability.cc @@ -434,14 +434,14 @@ static const ability_def Ability_List[] = {fail_basis::invo, 90, 2, 5}, abflag::hostile }, // Sif Muna + { ABIL_SIF_MUNA_CHANNEL_ENERGY, "Channel Magic", + 0, 0, 200, 2, {fail_basis::invo, 60, 4, 25}, abflag::none }, { ABIL_SIF_MUNA_DIVINE_ENERGY, "Divine Energy", 0, 0, 0, 0, {fail_basis::invo}, abflag::instant | abflag::starve_ok }, { ABIL_SIF_MUNA_STOP_DIVINE_ENERGY, "Stop Divine Energy", 0, 0, 0, 0, {fail_basis::invo}, abflag::instant | abflag::starve_ok }, { ABIL_SIF_MUNA_FORGET_SPELL, "Forget Spell", 0, 0, 0, 8, {fail_basis::invo}, abflag::none }, - { ABIL_SIF_MUNA_CHANNEL_ENERGY, "Channel Magic", - 0, 0, 200, 2, {fail_basis::invo, 60, 4, 25}, abflag::none }, // Trog { ABIL_TROG_BERSERK, "Berserk", diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index 2da167107f2d..e7c2d2062557 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -179,15 +179,15 @@ const vector god_powers[NUM_GODS] = }, // Sif Muna - { { 1, ABIL_SIF_MUNA_DIVINE_ENERGY, + { { 1, ABIL_SIF_MUNA_CHANNEL_ENERGY, + "call upon Sif Muna for magical energy" }, + { 1, ABIL_SIF_MUNA_DIVINE_ENERGY, "request divine energy to cast spells with insufficient magic", "request divine energy" }, { 2, "Sif Muna is now protecting you from the effects of miscast magic.", "Sif Muna will no longer protect you from the effects of miscast magic.", "Sif Muna protects you from the effects of miscast magic." }, - { 3, ABIL_SIF_MUNA_CHANNEL_ENERGY, - "call upon Sif Muna for magical energy" }, - { 4, ABIL_SIF_MUNA_FORGET_SPELL, + { 3, ABIL_SIF_MUNA_FORGET_SPELL, "freely open your mind to new spells", "forget spells at will" }, { 5, "Sif Muna will now gift you books as you gain piety.", From 0c6bcda0379877e00596d41de75a8fb2f05ff68d Mon Sep 17 00:00:00 2001 From: gammafunk Date: Sat, 15 Jun 2019 22:25:34 -0500 Subject: [PATCH 453/864] Sif Rework Part 3: Remove Divine Energy As discussed in 3db0654b, Sif doesn't need two MP restoration abilities, and Channel Energy, which is now granted at 1*, is the better design. --- crawl-ref/source/ability-type.h | 2 ++ crawl-ref/source/ability.cc | 22 ------------- crawl-ref/source/attribute-type.h | 2 +- crawl-ref/source/dat/descript/ability.txt | 10 ------ crawl-ref/source/duration-data.h | 4 +-- crawl-ref/source/duration-type.h | 2 ++ crawl-ref/source/religion.cc | 9 ++++-- crawl-ref/source/rltiles/dc-invocations.txt | 2 -- .../invocations/sif_muna_divine_energy.png | Bin 1707 -> 0 bytes .../sif_muna_stop_divine_energy.png | Bin 1692 -> 0 bytes crawl-ref/source/spl-book.cc | 4 +++ crawl-ref/source/spl-cast.cc | 29 ++---------------- crawl-ref/source/status.cc | 18 ----------- crawl-ref/source/status.h | 2 ++ crawl-ref/source/tilepick.cc | 4 --- 15 files changed, 21 insertions(+), 89 deletions(-) delete mode 100644 crawl-ref/source/rltiles/gui/invocations/sif_muna_divine_energy.png delete mode 100644 crawl-ref/source/rltiles/gui/invocations/sif_muna_stop_divine_energy.png diff --git a/crawl-ref/source/ability-type.h b/crawl-ref/source/ability-type.h index 9cfb839a3985..bf0f3c6cca37 100644 --- a/crawl-ref/source/ability-type.h +++ b/crawl-ref/source/ability-type.h @@ -119,8 +119,10 @@ enum ability_type // Sif Muna ABIL_SIF_MUNA_CHANNEL_ENERGY = 1070, ABIL_SIF_MUNA_FORGET_SPELL, +#if TAG_MAJOR_VERSION == 34 ABIL_SIF_MUNA_DIVINE_ENERGY, ABIL_SIF_MUNA_STOP_DIVINE_ENERGY, +#endif // Trog ABIL_TROG_BERSERK = 1080, ABIL_TROG_REGEN_MR, diff --git a/crawl-ref/source/ability.cc b/crawl-ref/source/ability.cc index 43ce012659cf..eb5cfe885300 100644 --- a/crawl-ref/source/ability.cc +++ b/crawl-ref/source/ability.cc @@ -436,10 +436,6 @@ static const ability_def Ability_List[] = // Sif Muna { ABIL_SIF_MUNA_CHANNEL_ENERGY, "Channel Magic", 0, 0, 200, 2, {fail_basis::invo, 60, 4, 25}, abflag::none }, - { ABIL_SIF_MUNA_DIVINE_ENERGY, "Divine Energy", - 0, 0, 0, 0, {fail_basis::invo}, abflag::instant | abflag::starve_ok }, - { ABIL_SIF_MUNA_STOP_DIVINE_ENERGY, "Stop Divine Energy", - 0, 0, 0, 0, {fail_basis::invo}, abflag::instant | abflag::starve_ok }, { ABIL_SIF_MUNA_FORGET_SPELL, "Forget Spell", 0, 0, 0, 8, {fail_basis::invo}, abflag::none }, @@ -1024,11 +1020,6 @@ ability_type fixup_ability(ability_type ability) else return ability; - case ABIL_SIF_MUNA_DIVINE_ENERGY: - if (you.attribute[ATTR_DIVINE_ENERGY]) - return ABIL_SIF_MUNA_STOP_DIVINE_ENERGY; - return ability; - case ABIL_ASHENZARI_TRANSFER_KNOWLEDGE: if (you.species == SP_GNOLL) return ABIL_NON_ABILITY; @@ -2581,19 +2572,6 @@ static spret _do_ability(const ability_def& abil, bool fail) &you); break; - case ABIL_SIF_MUNA_DIVINE_ENERGY: - simple_god_message(" will now grant you divine energy when your " - "reserves of magic are depleted."); - mpr("You will briefly lose access to your magic after casting a " - "spell in this manner."); - you.attribute[ATTR_DIVINE_ENERGY] = 1; - break; - - case ABIL_SIF_MUNA_STOP_DIVINE_ENERGY: - simple_god_message(" stops granting you divine energy."); - you.attribute[ATTR_DIVINE_ENERGY] = 0; - break; - case ABIL_SIF_MUNA_FORGET_SPELL: fail_check(); if (cast_selective_amnesia() <= 0) diff --git a/crawl-ref/source/attribute-type.h b/crawl-ref/source/attribute-type.h index a5dff8de80db..ae23565aeef3 100644 --- a/crawl-ref/source/attribute-type.h +++ b/crawl-ref/source/attribute-type.h @@ -91,8 +91,8 @@ enum attribute_type #if TAG_MAJOR_VERSION == 34 ATTR_SURGE_REMOVED, // Was surge power applied to next evocation. ATTR_PAKELLAS_EXTRA_MP, // MP to be collected to get a !magic from P -#endif ATTR_DIVINE_ENERGY, // Divine energy from Sif to cast with no MP. +#endif ATTR_SERPENTS_LASH, // Remaining instant movement actions. ATTR_HEAVENLY_STORM, // Strength of Heavenly Storm slaying. ATTR_WALL_JUMP_READY, // Ready to perform a wall jump. diff --git a/crawl-ref/source/dat/descript/ability.txt b/crawl-ref/source/dat/descript/ability.txt index a767145ae6b3..feb161ecbdb9 100644 --- a/crawl-ref/source/dat/descript/ability.txt +++ b/crawl-ref/source/dat/descript/ability.txt @@ -310,16 +310,6 @@ Summons a major demon. Failing to use this ability correctly will turn the demon hostile. %%%% # Sif Muna -Divine Energy ability - -Calls on Sif Muna for divine energy. While active, Sif Muna will allow you to -cast spells even with insufficient reserves of magic. Doing so will cause you -to briefly lose access to your magic after the spell is cast. -%%%% -Stop Divine Energy ability - -Stops requesting divine energy from Sif Muna, no longer allowing you to cast -spells without sufficient magical reserves. %%%% Channel Magic ability diff --git a/crawl-ref/source/duration-data.h b/crawl-ref/source/duration-data.h index ba03268f79c5..ebb7f666191e 100644 --- a/crawl-ref/source/duration-data.h +++ b/crawl-ref/source/duration-data.h @@ -607,8 +607,6 @@ static const duration_def duration_data[] = { DUR_BRAINLESS, 0, "", "", "brainless", "", D_NO_FLAGS }, { DUR_CLUMSY, 0, "", "", "clumsy", "", D_NO_FLAGS }, { DUR_ANCESTOR_DELAY, 0, "", "", "ancestor delay", "", D_NO_FLAGS, {{""}}}, - { DUR_NO_CAST, 0, "", "", "no cast", "", D_NO_FLAGS, - {{ "You regain access to your magic." }, {}, true }}, { DUR_HEAVENLY_STORM, 0, "", "", "", "", D_NO_FLAGS, {{ "", wu_jian_heaven_tick }}}, { DUR_GRASPING_ROOTS, 0, "", "grasped by roots", "grasping roots", @@ -651,6 +649,6 @@ static const duration_def duration_data[] = { DUR_MAGIC_SHIELD, 0, "", "", "old magic shield", "", D_NO_FLAGS}, { DUR_FORTITUDE, 0, "", "", "old fortitude", "", D_NO_FLAGS}, { DUR_WATER_HOLD_IMMUNITY, 0, "", "", "old drowning immunity", "", D_NO_FLAGS, {{""}}}, - + { DUR_NO_CAST, 0, "", "", "old no cast", "", D_NO_FLAGS}, #endif }; diff --git a/crawl-ref/source/duration-type.h b/crawl-ref/source/duration-type.h index c21854464ceb..ab8b01d4dbd7 100644 --- a/crawl-ref/source/duration-type.h +++ b/crawl-ref/source/duration-type.h @@ -189,7 +189,9 @@ enum duration_type DUR_VERTIGO, DUR_ANCESTOR_DELAY, DUR_SANGUINE_ARMOUR, +#if TAG_MAJOR_VERSION == 34 DUR_NO_CAST, +#endif DUR_CHANNEL_ENERGY, DUR_SPWPN_PROTECTION, DUR_NO_HOP, diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index e7c2d2062557..6f27240f6c8f 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -181,9 +181,6 @@ const vector god_powers[NUM_GODS] = // Sif Muna { { 1, ABIL_SIF_MUNA_CHANNEL_ENERGY, "call upon Sif Muna for magical energy" }, - { 1, ABIL_SIF_MUNA_DIVINE_ENERGY, - "request divine energy to cast spells with insufficient magic", - "request divine energy" }, { 2, "Sif Muna is now protecting you from the effects of miscast magic.", "Sif Muna will no longer protect you from the effects of miscast magic.", "Sif Muna protects you from the effects of miscast magic." }, @@ -853,8 +850,10 @@ static void _inc_penance(god_type god, int val) { if (you.duration[DUR_CHANNEL_ENERGY]) you.duration[DUR_CHANNEL_ENERGY] = 0; +#if TAG_MAJOR_VERSION == 34 if (you.attribute[ATTR_DIVINE_ENERGY]) you.attribute[ATTR_DIVINE_ENERGY] = 0; +#endif } if (you_worship(god)) @@ -2569,9 +2568,11 @@ void lose_piety(int pgn) end(you.ability_letter_table), ABIL_YRED_ANIMATE_DEAD, ABIL_YRED_ANIMATE_REMAINS); } +#if TAG_MAJOR_VERSION == 34 // Deactivate the toggle if (power.abil == ABIL_SIF_MUNA_DIVINE_ENERGY) you.attribute[ATTR_DIVINE_ENERGY] = 0; +#endif } } #ifdef USE_TILE_LOCAL @@ -2840,8 +2841,10 @@ void excommunication(bool voluntary, god_type new_god) case GOD_SIF_MUNA: if (you.duration[DUR_CHANNEL_ENERGY]) you.duration[DUR_CHANNEL_ENERGY] = 0; +#if TAG_MAJOR_VERSION == 34 if (you.attribute[ATTR_DIVINE_ENERGY]) you.attribute[ATTR_DIVINE_ENERGY] = 0; +#endif break; case GOD_NEMELEX_XOBEH: diff --git a/crawl-ref/source/rltiles/dc-invocations.txt b/crawl-ref/source/rltiles/dc-invocations.txt index 1e9e81342d69..3f7a96c42ef2 100644 --- a/crawl-ref/source/rltiles/dc-invocations.txt +++ b/crawl-ref/source/rltiles/dc-invocations.txt @@ -113,8 +113,6 @@ ru_sacrifice_resistance ABILITY_RU_SACRIFICE_RESISTANCE ru_reject_sacrifices ABILITY_RU_REJECT_SACRIFICES sif_muna_amnesia ABILITY_SIF_MUNA_AMNESIA sif_muna_channel ABILITY_SIF_MUNA_CHANNEL -sif_muna_divine_energy ABILITY_SIF_MUNA_DIVINE_ENERGY -sif_muna_stop_divine_energy ABILITY_SIF_MUNA_STOP_DIVINE_ENERGY trog_berserk ABILITY_TROG_BERSERK trog_brothers_in_arms ABILITY_TROG_BROTHERS_IN_ARMS trog_hand ABILITY_TROG_HAND diff --git a/crawl-ref/source/rltiles/gui/invocations/sif_muna_divine_energy.png b/crawl-ref/source/rltiles/gui/invocations/sif_muna_divine_energy.png deleted file mode 100644 index 75d6f75ed54d7105e390d76848977ba04392631c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1707 zcmV;c22}ZpP)4Tx062|}Rb6NtRTMtEb7vzY&QokOg>Hg1+lHrgWS zWcKdPn90sKGrRqvPeo9CG3uKX#J{(IASm?@+di}}l?o-=)F3E6wD^Ni=!>T7nL9I? zX}YoAW$t|Qo$sD|?zw001?ah|SeB6#0T!CBEf+H4bBB+JJu8rehoBb*p;u8ID_yBf z0ya+zcePvJL&AGs+11_tpRKn>9TgyPA7ZoSs0)aX0r00)%XR^J`jH<$>RKN5V(7Oq zK*TS4xZz{h!*f1C3ECFkK$#7nA@pGN!$;%jYvwjAKwmYb0gKL(K8 z-kPtb5${A?tlI~wzMrJ6wTdBr=Y%%%EaEMQ&o}4FQ^DA)s*}Z>!FI&AHCpoWI|RUq zx?7s@$8!5^Q=anY%X@i5{QA6kNcMelpE>R6eCYFpmMsVTrI(b06~u#xf1yS} z_UGdMvD``!0~u->P=lA4?YN`hilQ|3tHka)7T{2CGqw zjZfMwx$5irQN_*|e4l)UHmiYuz74Yp1t^#>hrJ3-SOXDcC_o0^7T9R1gAN8V6s;5) zieI5-7aQlmJn}lUna#nz!j%5V$X|o`xX!dHWQRV27P1=rj;t2bW$~+pTw@bIek?Zv zKPDL<64`^#UNTAck#RBsB6*5DP4<%UA_FqU$I>2EH_cM;u)Q~SI+rg`Rn{L_AC5qq~L$#SMj%U z$6Cz0vP{G5Y*=%5RT^yu;}-DInZ=349rJPVM6C3K^oO)8y(fJr{l>k`ead~!ea?NsT>_Ci%bnxC;Vy6=b6>{xYV#Ue-+LB$ z7`JEXmTRm^AtP)R9u{)KHsMiWGV&)32xCG~*nyU<>-!d;FP=Re4r3qYr~6#KE>;1F z`>_J_P5xC?ROxV(DIHdCO*p$HRQI@7^PwV@Pvuf+5K}u-6REM(K@W$s zrgorh0{i?O)v0c>QtHxU-hBdD(>iYJ4b2sIOVX2K8m~4gmYVA5h^QEb$V`rCQ-|7Z zS{nuL-t>?3n=-o(6I(7vocj#GzCZEo`!3>+v;dYIfPu#&ZWzzX2i^rZ^Mu;6+rb@? zNPG+6)c5T6zxpzGe*M(x+{AON=PiJ>H#?ob-|uwRK0yDg0B4PV0id6JRZw95ZvX%S zSxH1eR9FecRy%USFc4KdDQM`@(@cW0xAJON)=DzN zjM0oOX}@njvgO>9$4klo@p$|z@$RLc&u6#a?@eE?HDlZDw#J^!Td&te*{;Z$i7^X+ z<#JgJ=OF-#uV06!HEy?CQG|Nnk%sHPi?$QSZnw*tIyUA200Py=N1O1&{$$YVcHqZ1 zCiL9o5^$>Z+#h~m!;cfa!3(soCt~9@89;w{BU6;}6+8O$G(3Jp8a4wB%f@H|;D}*| zLAWa-*G~MJXpj=R)&)loJ{eU2Y=CDna78A>i5LY<=+L2Z_{>;?Pev60N6cxr3|X}3 z983aiNd;OJ07Mvsq*#o>QIeg3B}Y>-B3fZJsRR%u2U*Pry63}L1|mjXJ`G#~^JkCCDMt!g zB%G_3fCVWM{OycWz%u5Xl%os+y44IwS4)Zkin22D95SW9daT29sxY|(`b)-+$Ddfx ziAI^y5!=oIWl{+==EONVIyyTU4W~h9EBU(1Nj3%L2+hS&@eFxhk7wJKrp6BuuFj|n zQp5GRTrOI+`C|#f3_?_`YdQN6snKe$X?e75 zom8SrxAX6w4xn0s&1MtND{{k4T3VO*^XK&rkN@oO7TOcxi75a8002ovPDHLkV1ldN BJ?j7f diff --git a/crawl-ref/source/rltiles/gui/invocations/sif_muna_stop_divine_energy.png b/crawl-ref/source/rltiles/gui/invocations/sif_muna_stop_divine_energy.png deleted file mode 100644 index 0b190915b23ef02bb1e5c044f9b780ec97ceed05..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1692 zcmV;N24ne&P)4Tx062|}Rb6NtRTMtEb7vzY&QokOg>Hg1+lHrgWS zWcKdPn90sKGrRqvPeo9CG3uKX#J{(IASm?@+di}}l?o-=)F3E6wD^Ni=!>T7nL9I? zX}YoAW$t|Qo$sD|?zw001?ah|SeB6#0T!CBEf+H4bBB+JJu8rehoBb*p;u8ID_yBf z0ya+zcePvJL&AGs+11_tpRKn>9TgyPA7ZoSs0)aX0r00)%XR^J`jH<$>RKN5V(7Oq zK*TS4xZz{h!*f1C3ECFkK$#7nA@pGN!$;%jYvwjAKwmYb0gKL(K8 z-kPtb5${A?tlI~wzMrJ6wTdBr=Y%%%EaEMQ&o}4FQ^DA)s*}Z>!FI&AHCpoWI|RUq zx?7s@$8!5^Q=anY%X@i5{QA6kNcMelpE>R6eCYFpmMsVTrI(b06~u#xf1yS} z_UGdMvD``!0~u->P=lA4?YN`hilQ|3tHka)7T{2CGqw zjZfMwx$5irQN_*|e4l)UHmiYuz74Yp1t^#>hrJ3-SOXDcC_o0^7T9R1gAN8V6s;5) zieI5-7aQlmJn}lUna#nz!j%5V$X|o`xX!dHWQRV27P1=rj;t2bW$~+pTw@bIek?Zv zKPDL<64`^#UNTAck#RBsB6*5DP4<%UA_FqU$I>2EH_cM;u)Q~SI+rg`Rn{L_AC5qq~L$#SMj%U z$6Cz0vP{G5Y*=%5RT^yu;}-DInZ=349rJPVM6C3K^oO)8y(fJr{l>k`ead~!ea?NsT>_Ci%bnxC;Vy6=b6>{xYV#Ue-+LB$ z7`JEXmTRm^AtP)R9u{)KHsMiWGV&)32xCG~*nyU<>-!d;FP=Re4r3qYr~6#KE>;1F z`>_J_P5xC?ROxV(DIHdCO*p$HRQI@7^PwV@Pvuf+5K}u-6REM(K@W$s zrgorh0{i?O)v0c>QtHxU-hBdD(>iYJ4b2sIOVX2K8m~4gmYVA5h^QEb$V`rCQ-|7Z zS{nuL-t>?3n=-o(6I(7vocj#GzCZEo`!3>+v;dYIfPu#&ZWzzX2i^rZ^Mu;6+rb@? zNPG+6)c5T6zxpzGe*M(x+{AON=PiJ>H#?ob-|uwRK0yDg0B4PV0id6JRZw95ZvX%S zN=ZaPR9Fecmb-02F%*VxqLi=&3(znC9m6mJ6(cYV9VHSpR7?VWaz2aSI@kC`A`wfz zK0fcKVHo~-eU$9)_xtY>?N$8ocpSFdZPwOTP1$O-s*$^Cv)Qc3`&p#CiSQN&rqgLL zoIg3RUatpsYu#?QB1`Cjzck$SdMzsVgw1C2)YP#t9}d7!-4^YL&V8|1JmFe;pj%@i zH*}XksrKjTbVA2qPJ|O0INbxX@#%J8x7!6(q{qtpYY;9J{dN40LGg-N=9#F(ey9=NS61n>0a5z+X zn-gUsuspj?`(RBs+3C2|CQk Date: Sat, 15 Jun 2019 22:11:27 -0500 Subject: [PATCH 454/864] Sif Rework Part 4: Add a Divine Exegesis ability Sif currently has one active that uses piety, Channel Energy, an ability that becomes more about convenience than power as the game progresses since players get access to a large MP pool. This commit adds a powerful new active to help Sif be relevant at the middle and late portions of the game and to help cement her role as the more active magical god counterpart to the more passive Vehumet. The Divine Exegesis ability allows casting any spell in the player's library with 100% success and with a spell power bonus of 1.5 x Invocations skill in addition to any spell-power coming from Int, Spellcasting, and any training in the spell schools of the spell. Thus players can cast a spell that normally has a 100% fail rate due to no or little training in the relevant skills. Divine Exegesis is granted at 4* and has a high piety cost of 12, meaning several uses of the ability is likely to bring a player under 4*. The ability will be useful to a wide variety of spell using characters, granting limited access to high level spells that normally remain totally inaccessible behind high skill requirements. --- crawl-ref/source/ability-type.h | 1 + crawl-ref/source/ability.cc | 12 ++ crawl-ref/source/dat/descript/ability.txt | 6 + crawl-ref/source/describe.cc | 7 +- crawl-ref/source/player.cc | 1 + crawl-ref/source/player.h | 2 + crawl-ref/source/religion.cc | 2 + crawl-ref/source/rltiles/dc-invocations.txt | 1 + .../gui/invocations/sif_muna_exegesis.png | Bin 0 -> 1707 bytes crawl-ref/source/spl-book.cc | 148 +++++++++++++----- crawl-ref/source/spl-book.h | 1 + crawl-ref/source/spl-cast.cc | 6 +- crawl-ref/source/spl-cast.h | 2 +- crawl-ref/source/tilepick.cc | 2 + 14 files changed, 152 insertions(+), 39 deletions(-) create mode 100644 crawl-ref/source/rltiles/gui/invocations/sif_muna_exegesis.png diff --git a/crawl-ref/source/ability-type.h b/crawl-ref/source/ability-type.h index bf0f3c6cca37..f46a4b4d81ee 100644 --- a/crawl-ref/source/ability-type.h +++ b/crawl-ref/source/ability-type.h @@ -123,6 +123,7 @@ enum ability_type ABIL_SIF_MUNA_DIVINE_ENERGY, ABIL_SIF_MUNA_STOP_DIVINE_ENERGY, #endif + ABIL_SIF_MUNA_DIVINE_EXEGESIS, // Trog ABIL_TROG_BERSERK = 1080, ABIL_TROG_REGEN_MR, diff --git a/crawl-ref/source/ability.cc b/crawl-ref/source/ability.cc index eb5cfe885300..f5fbfc5b5446 100644 --- a/crawl-ref/source/ability.cc +++ b/crawl-ref/source/ability.cc @@ -61,6 +61,7 @@ #include "prompt.h" #include "religion.h" #include "skills.h" +#include "spl-book.h" #include "spl-cast.h" #include "spl-clouds.h" #include "spl-damage.h" @@ -438,6 +439,8 @@ static const ability_def Ability_List[] = 0, 0, 200, 2, {fail_basis::invo, 60, 4, 25}, abflag::none }, { ABIL_SIF_MUNA_FORGET_SPELL, "Forget Spell", 0, 0, 0, 8, {fail_basis::invo}, abflag::none }, + { ABIL_SIF_MUNA_DIVINE_EXEGESIS, "Divine Exegesis", + 0, 0, 0, 12, {fail_basis::invo, 80, 4, 25}, abflag::none }, // Trog { ABIL_TROG_BERSERK, "Berserk", @@ -1555,6 +1558,9 @@ static bool _check_ability_possible(const ability_def& abil, bool quiet = false) } return true; + case ABIL_SIF_MUNA_DIVINE_EXEGESIS: + return can_cast_spells(); + case ABIL_ASHENZARI_TRANSFER_KNOWLEDGE: if (!trainable_skills(true)) { @@ -2589,6 +2595,12 @@ static spret _do_ability(const ability_def& abil, bool fail) break; } + case ABIL_SIF_MUNA_DIVINE_EXEGESIS: + { + return divine_exegesis(fail); + break; + } + case ABIL_ELYVILON_LIFESAVING: fail_check(); if (you.duration[DUR_LIFESAVING]) diff --git a/crawl-ref/source/dat/descript/ability.txt b/crawl-ref/source/dat/descript/ability.txt index feb161ecbdb9..2b0409bbd020 100644 --- a/crawl-ref/source/dat/descript/ability.txt +++ b/crawl-ref/source/dat/descript/ability.txt @@ -320,6 +320,12 @@ Forget Spell ability Removes a known spell from memory, so as to free memory to learn others. %%%% +Divine Exegesis ability + +Casts any spell from your spell library with guaranteed success. You receive a +bonus to spell power based on your Invocations skill that is worth 50% more +than equivalent levels of training in the relevant skills of the spell itself. +%%%% # Trog Berserk ability diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index fc3283da5881..55bb89541493 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -2833,7 +2833,12 @@ static string _player_spell_stats(const spell_type spell) return description; // all other info is player-dependent } - const string failure = failure_rate_to_string(raw_spell_fail(spell)); + + string failure; + if (you.divine_exegesis) + failure = "0%"; + else + failure = failure_rate_to_string(raw_spell_fail(spell)); description += make_stringf(" Fail: %s", failure.c_str()); description += "\n\nPower : "; diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index c563368ffbe7..0d7d7a38c1b9 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -5108,6 +5108,7 @@ player::player() // Non-saved UI state: prev_targ = MHITNOT; prev_grd_targ.reset(); + divine_exegesis = false; travel_x = 0; travel_y = 0; diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h index 8f8f7308254f..e969a9a06002 100644 --- a/crawl-ref/source/player.h +++ b/crawl-ref/source/player.h @@ -366,6 +366,8 @@ class player : public actor // ------------------- unsigned short prev_targ; coord_def prev_grd_targ; + // Examining spell library spells for Sif Muna's ability + bool divine_exegesis; // Coordinates of last travel target; note that this is never used by // travel itself, only by the level-map to remember the last travel target. diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index 6f27240f6c8f..151aca061905 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -187,6 +187,8 @@ const vector god_powers[NUM_GODS] = { 3, ABIL_SIF_MUNA_FORGET_SPELL, "freely open your mind to new spells", "forget spells at will" }, + { 4, ABIL_SIF_MUNA_DIVINE_EXEGESIS, + "call upon Sif Muna to cast any spell from your library" }, { 5, "Sif Muna will now gift you books as you gain piety.", "Sif Muna will no longer gift you books.", "Sif Muna will gift you books as you gain piety." }, diff --git a/crawl-ref/source/rltiles/dc-invocations.txt b/crawl-ref/source/rltiles/dc-invocations.txt index 3f7a96c42ef2..80d042ecf3a0 100644 --- a/crawl-ref/source/rltiles/dc-invocations.txt +++ b/crawl-ref/source/rltiles/dc-invocations.txt @@ -113,6 +113,7 @@ ru_sacrifice_resistance ABILITY_RU_SACRIFICE_RESISTANCE ru_reject_sacrifices ABILITY_RU_REJECT_SACRIFICES sif_muna_amnesia ABILITY_SIF_MUNA_AMNESIA sif_muna_channel ABILITY_SIF_MUNA_CHANNEL +sif_muna_exegesis ABILITY_SIF_MUNA_EXEGESIS trog_berserk ABILITY_TROG_BERSERK trog_brothers_in_arms ABILITY_TROG_BROTHERS_IN_ARMS trog_hand ABILITY_TROG_HAND diff --git a/crawl-ref/source/rltiles/gui/invocations/sif_muna_exegesis.png b/crawl-ref/source/rltiles/gui/invocations/sif_muna_exegesis.png new file mode 100644 index 0000000000000000000000000000000000000000..75d6f75ed54d7105e390d76848977ba04392631c GIT binary patch literal 1707 zcmV;c22}ZpP)4Tx062|}Rb6NtRTMtEb7vzY&QokOg>Hg1+lHrgWS zWcKdPn90sKGrRqvPeo9CG3uKX#J{(IASm?@+di}}l?o-=)F3E6wD^Ni=!>T7nL9I? zX}YoAW$t|Qo$sD|?zw001?ah|SeB6#0T!CBEf+H4bBB+JJu8rehoBb*p;u8ID_yBf z0ya+zcePvJL&AGs+11_tpRKn>9TgyPA7ZoSs0)aX0r00)%XR^J`jH<$>RKN5V(7Oq zK*TS4xZz{h!*f1C3ECFkK$#7nA@pGN!$;%jYvwjAKwmYb0gKL(K8 z-kPtb5${A?tlI~wzMrJ6wTdBr=Y%%%EaEMQ&o}4FQ^DA)s*}Z>!FI&AHCpoWI|RUq zx?7s@$8!5^Q=anY%X@i5{QA6kNcMelpE>R6eCYFpmMsVTrI(b06~u#xf1yS} z_UGdMvD``!0~u->P=lA4?YN`hilQ|3tHka)7T{2CGqw zjZfMwx$5irQN_*|e4l)UHmiYuz74Yp1t^#>hrJ3-SOXDcC_o0^7T9R1gAN8V6s;5) zieI5-7aQlmJn}lUna#nz!j%5V$X|o`xX!dHWQRV27P1=rj;t2bW$~+pTw@bIek?Zv zKPDL<64`^#UNTAck#RBsB6*5DP4<%UA_FqU$I>2EH_cM;u)Q~SI+rg`Rn{L_AC5qq~L$#SMj%U z$6Cz0vP{G5Y*=%5RT^yu;}-DInZ=349rJPVM6C3K^oO)8y(fJr{l>k`ead~!ea?NsT>_Ci%bnxC;Vy6=b6>{xYV#Ue-+LB$ z7`JEXmTRm^AtP)R9u{)KHsMiWGV&)32xCG~*nyU<>-!d;FP=Re4r3qYr~6#KE>;1F z`>_J_P5xC?ROxV(DIHdCO*p$HRQI@7^PwV@Pvuf+5K}u-6REM(K@W$s zrgorh0{i?O)v0c>QtHxU-hBdD(>iYJ4b2sIOVX2K8m~4gmYVA5h^QEb$V`rCQ-|7Z zS{nuL-t>?3n=-o(6I(7vocj#GzCZEo`!3>+v;dYIfPu#&ZWzzX2i^rZ^Mu;6+rb@? zNPG+6)c5T6zxpzGe*M(x+{AON=PiJ>H#?ob-|uwRK0yDg0B4PV0id6JRZw95ZvX%S zSxH1eR9FecRy%USFc4KdDQM`@(@cW0xAJON)=DzN zjM0oOX}@njvgO>9$4klo@p$|z@$RLc&u6#a?@eE?HDlZDw#J^!Td&te*{;Z$i7^X+ z<#JgJ=OF-#uV06!HEy?CQG|Nnk%sHPi?$QSZnw*tIyUA200Py=N1O1&{$$YVcHqZ1 zCiL9o5^$>Z+#h~m!;cfa!3(soCt~9@89;w{BU6;}6+8O$G(3Jp8a4wB%f@H|;D}*| zLAWa-*G~MJXpj=R)&)loJ{eU2Y=CDna78A>i5LY<=+L2Z_{>;?Pev60N6cxr3|X}3 z983aiNd;OJ07Mvsq*#o>QIeg3B}Y>-B3fZJsRR%u2U*Pry63}L1|mjXJ`G#~^JkCCDMt!g zB%G_3fCVWM{OycWz%u5Xl%os+y44IwS4)Zkin22D95SW9daT29sxY|(`b)-+$Ddfx ziAI^y5!=oIWl{+==EONVIyyTU4W~h9EBU(1Nj3%L2+hS&@eFxhk7wJKrp6BuuFj|n zQp5GRTrOI+`C|#f3_?_`YdQN6snKe$X?e75 zom8SrxAX6w4xn0s&1MtND{{k4T3VO*^XK&rkN@oO7TOcxi75a8002ovPDHLkV1ldN BJ?j7f literal 0 HcmV?d00001 diff --git a/crawl-ref/source/spl-book.cc b/crawl-ref/source/spl-book.cc index afc8aca42059..cc785cdb1f9c 100644 --- a/crawl-ref/source/spl-book.cc +++ b/crawl-ref/source/spl-book.cc @@ -36,6 +36,7 @@ #include "output.h" #include "prompt.h" #include "religion.h" +#include "spl-cast.h" #include "spl-util.h" #include "state.h" #include "stringutil.h" @@ -412,7 +413,9 @@ static spell_list _get_spell_list(bool just_check = false, for (const spell_type spell : available_spells) { if (you.has_spell(spell)) + { num_known++; + // Divine Exegesis includes spells the player already knows. if (you.divine_exegesis) mem_spells.emplace_back(spell); @@ -515,11 +518,30 @@ static bool _sort_mem_spells(const sortable_spell &a, const sortable_spell &b) return strcasecmp(spell_title(a.spell), spell_title(b.spell)) < 0; } +static bool _sort_divine_spells(const sortable_spell &a, const sortable_spell &b) +{ + // Put useless spells last + const bool useful_a = !spell_is_useless(a.spell, true, true); + const bool useful_b = !spell_is_useless(b.spell, true, true); + if (useful_a != useful_b) + return useful_a; + + // Put higher levels spells first, as they're more likely to be what we + // want. + if (a.difficulty != b.difficulty) + return a.difficulty > b.difficulty; + + return strcasecmp(spell_title(a.spell), spell_title(b.spell)) < 0; +} + vector get_sorted_spell_list(bool silent, bool memorise_only) { spell_list mem_spells(_get_spell_list(silent, memorise_only)); - sort(mem_spells.begin(), mem_spells.end(), _sort_mem_spells); + if (you.divine_exegesis) + sort(mem_spells.begin(), mem_spells.end(), _sort_divine_spells); + else + sort(mem_spells.begin(), mem_spells.end(), _sort_mem_spells); vector result; for (auto s : mem_spells) @@ -528,23 +550,22 @@ vector get_sorted_spell_list(bool silent, bool memorise_only) return result; } -class MemoriseMenu : public Menu +class SpellLibraryMenu : public Menu { public: - enum class action { memorise, describe, hide, unhide } current_action; + enum class action { cast, memorise, describe, hide, unhide } current_action; protected: virtual formatted_string calc_title() override { return formatted_string::parse_string( - make_stringf("Spells %s Type Failure Level ", - current_action == action::memorise ? - "(Memorise)" : - current_action == action::describe ? - "(Describe)" : - current_action == action::hide ? - "(Hide) " : - "(Show) ")); + make_stringf("Spells %s Type %sLevel ", + current_action == action::cast ? "(Cast)" : + current_action == action::memorise ? "(Memorise)" : + current_action == action::describe ? "(Describe)" : + current_action == action::hide ? "(Hide) " : + "(Show) ", + you.divine_exegesis ? "" : "Failure ")); } private: @@ -582,17 +603,20 @@ class MemoriseMenu : public Menu } desc << "\n"; + const string act = you.divine_exegesis ? "Cast" : "Memorise"; // line 2 desc << "[?] help " "[Ctrl-f] search " "[!] "; - desc << ( current_action == action::memorise + desc << ( current_action == action::cast + ? "Cast|Describe|Hide|Show" + : current_action == action::memorise ? "Memorise|Describe|Hide|Show" : current_action == action::describe - ? "Memorise|Describe|Hide|Show" + ? act + "|Describe|Hide|Show" : current_action == action::hide - ? "Memorise|Describe|Hide|Show" - : "Memorise|Describe|Hide|Show"); + ? act + "|Describe|Hide|Show" + : act + "|Describe|Hide|Show"); set_more(formatted_string::parse_string(desc.str())); } @@ -608,6 +632,7 @@ class MemoriseMenu : public Menu #endif switch (current_action) { + case action::cast: case action::memorise: current_action = action::describe; entries_changed = true; // need to add hotkeys @@ -620,7 +645,8 @@ class MemoriseMenu : public Menu entries_changed = true; break; case action::unhide: - current_action = action::memorise; + current_action = you.divine_exegesis ? action::cast + : action::memorise; entries_changed = true; break; } @@ -718,18 +744,24 @@ class MemoriseMenu : public Menu desc << string(60 - so_far, ' '); desc << ""; - colour = spell.fail_rate_colour; - desc << "<" << colour_to_str(colour) << ">"; - desc << chop_string(failure_rate_to_string(spell.raw_fail), 12); - desc << ""; + if (!you.divine_exegesis) + { + colour = spell.fail_rate_colour; + desc << "<" << colour_to_str(colour) << ">"; + desc << chop_string(failure_rate_to_string(spell.raw_fail), 12); + desc << ""; + } + desc << spell.difficulty; MenuEntry* me = new MenuEntry(desc.str(), MEL_ITEM, 1, - // don't add a hotkey if you can't memorise it + // don't add a hotkey if you can't memorise/cast it (current_action == action::memorise && - !you_can_memorise(spell.spell)) ? ' ' : char(hotkey)); - // But do increment hotkeys anyway, to keep the memorise and - // describe hotkeys consistent. + !you_can_memorise(spell.spell)) + || current_action == action::cast && + spell_is_useless(spell.spell, true, true) + ? ' ' : char(hotkey)); + // But do increment hotkeys anyway, to keep the hotkeys consistent. ++hotkey; #ifdef USE_TILE @@ -743,26 +775,31 @@ class MemoriseMenu : public Menu } public: - MemoriseMenu(spell_list& list) + SpellLibraryMenu(spell_list& list) : Menu(MF_SINGLESELECT | MF_ANYPRINTABLE | MF_ALWAYS_SHOW_MORE | MF_ALLOW_FORMATTING // To have the ctrl-f menu show up in webtiles | MF_ALLOW_FILTER, "spell"), - current_action(action::memorise), + current_action(you.divine_exegesis ? action::cast : action::memorise), spells(list), hidden_count(0) { set_highlighter(nullptr); - set_title(new MenuEntry(""), true, true); // Actual text handled by calc_title + // Actual text handled by calc_title + set_title(new MenuEntry(""), true, true); - spell_levels_str = make_stringf("%d spell level%s" - "", player_spell_levels(), - (player_spell_levels() > 1 || player_spell_levels() == 0) - ? "s left" : " left "); - if (player_spell_levels() < 9) - spell_levels_str += " "; + if (!you.divine_exegesis) + { + spell_levels_str = make_stringf("%d spell level%s" + "", player_spell_levels(), + (player_spell_levels() > 1 || player_spell_levels() == 0) + ? "s left" : " left "); + if (player_spell_levels() < 9) + spell_levels_str += " "; + + set_more(formatted_string::parse_string(spell_levels_str + "\n")); + } - set_more(formatted_string::parse_string(spell_levels_str + "\n")); #ifdef USE_TILE_LOCAL FontWrapper *font = tiles.get_crt_font(); int title_width = font->string_width(calc_title()); @@ -780,6 +817,7 @@ class MemoriseMenu : public Menu switch (current_action) { case action::memorise: + case action::cast: return false; case action::describe: describe_spell(spell, nullptr); @@ -802,7 +840,7 @@ static spell_type _choose_mem_spell(spell_list &spells) // If we've gotten this far, we know that at least one spell here is // memorisable, which is enough. - MemoriseMenu spell_menu(spells); + SpellLibraryMenu spell_menu(spells); const vector sel = spell_menu.show(); if (!crawl_state.doing_prev_cmd_again) @@ -842,7 +880,7 @@ bool can_learn_spell(bool silent) bool learn_spell() { - spell_list spells(_get_spell_list(false, true)); + spell_list spells(_get_spell_list()); if (spells.empty()) return false; @@ -1002,3 +1040,41 @@ bool book_has_title(const item_def &book) return book.props.exists(BOOK_TITLED_KEY) && book.props[BOOK_TITLED_KEY].get_bool() == true; } + +spret divine_exegesis(bool fail) +{ + unwind_var dk(you.divine_exegesis, true); + + spell_list spells(_get_spell_list(true, true)); + if (spells.empty()) + { + mpr("You don't know of any spells!"); + return spret::abort; + } + + sort(spells.begin(), spells.end(), _sort_divine_spells); + // If we've gotten this far, we know at least one useful spell. + + SpellLibraryMenu spell_menu(spells); + + const vector sel = spell_menu.show(); + if (!crawl_state.doing_prev_cmd_again) + redraw_screen(); + + if (sel.empty()) + return spret::abort; + + const spell_type spell = *static_cast(sel[0]->data); + if (spell == SPELL_NO_SPELL) + return spret::abort; + + ASSERT(is_valid_spell(spell)); + + if (fail) + return spret::fail; + + if (cast_a_spell(false, spell)) + return spret::success; + + return spret::abort; +} diff --git a/crawl-ref/source/spl-book.h b/crawl-ref/source/spl-book.h index 427454cfe301..d69184def1e4 100644 --- a/crawl-ref/source/spl-book.h +++ b/crawl-ref/source/spl-book.h @@ -42,3 +42,4 @@ bool you_can_memorise(spell_type spell) PURE; bool has_spells_to_memorise(bool silent = true); vector get_sorted_spell_list(bool silent = false, bool memorise_only = true); +spret divine_exegesis(bool fail); diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc index a66eebae7c8e..4cd8c4ccd5fc 100644 --- a/crawl-ref/source/spl-cast.cc +++ b/crawl-ref/source/spl-cast.cc @@ -442,6 +442,9 @@ int calc_spell_power(spell_type spell, bool apply_intel, bool fail_rate_check, power += you.skill(SK_SPELLCASTING, 50); + if (you.divine_exegesis) + power += you.skill(SK_INVOCATIONS, 300); + if (fail_rate_check) { // Scale appropriately. @@ -839,7 +842,8 @@ bool cast_a_spell(bool check_range, spell_type spell) // Silently take MP before the spell. dec_mp(cost, true); - const spret cast_result = your_spells(spell, 0, true); + const spret cast_result = your_spells(spell, 0, !you.divine_exegesis, + nullptr); if (cast_result == spret::abort) { crawl_state.zero_turns_taken(); diff --git a/crawl-ref/source/spl-cast.h b/crawl-ref/source/spl-cast.h index 5b9c4a866569..120daef571e5 100644 --- a/crawl-ref/source/spl-cast.h +++ b/crawl-ref/source/spl-cast.h @@ -103,7 +103,7 @@ class targeter; vector desc_success_chance(const monster_info& mi, int pow, bool evoked, targeter* hitfunc); spret your_spells(spell_type spell, int powc = 0, bool allow_fail = true, - const item_def* const evoked_item = nullptr); + const item_def* const evoked_item = nullptr); extern const char *fail_severity_adjs[]; diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc index e03869cc7463..d1770344f608 100644 --- a/crawl-ref/source/tilepick.cc +++ b/crawl-ref/source/tilepick.cc @@ -3444,6 +3444,8 @@ tileidx_t tileidx_ability(const ability_type ability) return TILEG_ABILITY_SIF_MUNA_CHANNEL; case ABIL_SIF_MUNA_FORGET_SPELL: return TILEG_ABILITY_SIF_MUNA_AMNESIA; + case ABIL_SIF_MUNA_DIVINE_EXEGESIS: + return TILEG_ABILITY_SIF_MUNA_EXEGESIS; // Trog case ABIL_TROG_BERSERK: return TILEG_ABILITY_TROG_BERSERK; From 09db7996fae9fbe0bad22cd92b271ab44894f249 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Sat, 15 Jun 2019 22:24:53 -0500 Subject: [PATCH 455/864] Sif Rework Part 5: Remove miscast protection As a passive, the protection was hard for players to reason about, since they had to know both a chance of successful protection based on their piety as well as the kind of miscast effect they might face should the protection fail. 100% protection was granted at 6*, but even then there tended to be a quite narrow set of relevant spells where the player might have some appreciable chance of successfully casting the spell. Repeatedly casting a high fail rate spell until successful is also tedious in terms of UI. The new Divine Exegesis active is basically an active ability version of miscast protection and provides access to more spells. Hence Sif no longer needs the passive. --- crawl-ref/source/god-passive.cc | 5 +---- crawl-ref/source/god-passive.h | 3 --- crawl-ref/source/religion.cc | 3 --- crawl-ref/source/spl-cast.cc | 27 +-------------------------- 4 files changed, 2 insertions(+), 36 deletions(-) diff --git a/crawl-ref/source/god-passive.cc b/crawl-ref/source/god-passive.cc index da2eb5c544be..06090f0bbece 100644 --- a/crawl-ref/source/god-passive.cc +++ b/crawl-ref/source/god-passive.cc @@ -220,10 +220,7 @@ static const vector god_passives[] = }, // Sif Muna - { - { 2, passive_t::miscast_protection, - "GOD NOW protects you from miscasts" }, - }, + { }, // Trog { diff --git a/crawl-ref/source/god-passive.h b/crawl-ref/source/god-passive.h index b731eadb82dc..c3de3467aeed 100644 --- a/crawl-ref/source/god-passive.h +++ b/crawl-ref/source/god-passive.h @@ -147,9 +147,6 @@ enum class passive_t /// Torment resistance, piety dependent. resist_torment, - /// Protection against miscasts. Piety dependent. - miscast_protection, - /// Protection against necromancy miscasts and mummy death curses. miscast_protection_necromancy, diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index 151aca061905..16d4b4707b64 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -181,9 +181,6 @@ const vector god_powers[NUM_GODS] = // Sif Muna { { 1, ABIL_SIF_MUNA_CHANNEL_ENERGY, "call upon Sif Muna for magical energy" }, - { 2, "Sif Muna is now protecting you from the effects of miscast magic.", - "Sif Muna will no longer protect you from the effects of miscast magic.", - "Sif Muna protects you from the effects of miscast magic." }, { 3, ABIL_SIF_MUNA_FORGET_SPELL, "freely open your mind to new spells", "forget spells at will" }, diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc index 4cd8c4ccd5fc..5105157e69e7 100644 --- a/crawl-ref/source/spl-cast.cc +++ b/crawl-ref/source/spl-cast.cc @@ -1203,16 +1203,6 @@ static unique_ptr _spell_targeter(spell_type spell, int pow, return nullptr; } -static double _chance_miscast_prot() -{ - double miscast_prot = 0; - - if (have_passive(passive_t::miscast_protection)) - miscast_prot = (double) you.piety/piety_breakpoint(5); - - return min(1.0, miscast_prot); -} - // Returns the nth triangular number. static int _triangular_number(int n) { @@ -1544,12 +1534,6 @@ spret your_spells(spell_type spell, int powc, bool allow_fail, flush_input_buffer(FLUSH_ON_FAILURE); learned_something_new(HINT_SPELL_MISCAST); - if (decimal_chance(_chance_miscast_prot())) - { - simple_god_message(" protects you from the effects of your miscast!"); - return spret::fail; - } - // All spell failures give a bit of magical radiation. // Failure is a function of power squared multiplied by how // badly you missed the spell. High power spells can be @@ -2028,15 +2012,6 @@ double get_miscast_chance(spell_type spell, int severity) return chance; } -static double _get_miscast_chance_with_miscast_prot(spell_type spell) -{ - double raw_chance = get_miscast_chance(spell); - double miscast_prot = _chance_miscast_prot(); - double chance = raw_chance * (1 - miscast_prot); - - return chance; -} - const char *fail_severity_adjs[] = { "safe", @@ -2048,7 +2023,7 @@ COMPILE_CHECK(ARRAYSZ(fail_severity_adjs) > 3); int fail_severity(spell_type spell) { - const double chance = _get_miscast_chance_with_miscast_prot(spell); + const double chance = get_miscast_chance(spell); return (chance < 0.001) ? 0 : (chance < 0.005) ? 1 : From aec789570c1ddf4c5b408b0825ed3e0d430eb943 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Tue, 25 Jun 2019 16:42:47 -0500 Subject: [PATCH 456/864] Clean up a condition --- crawl-ref/source/religion.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index 16d4b4707b64..3f4b965983f7 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -1505,8 +1505,8 @@ static bool _gift_sif_kiku_gift(bool forced) gift = BOOK_DEATH; } } - else if (forced || you.piety >= piety_breakpoint(4) - && random2(you.piety) > 100) + else if (forced + || you.piety >= piety_breakpoint(4) && random2(you.piety) > 100) { // Sif Muna special: Keep quiet if acquirement fails // because the player already has seen all spells. From fcb5e6da0e9c8a004602530bbcd9f548c7252dde Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 25 Jun 2019 21:03:28 -0400 Subject: [PATCH 457/864] More specific documentation about des stability and tags [skip ci] --- crawl-ref/docs/develop/levels/advanced.txt | 14 ++++++++++++++ crawl-ref/docs/develop/rng_guidelines.md | 14 +++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/crawl-ref/docs/develop/levels/advanced.txt b/crawl-ref/docs/develop/levels/advanced.txt index 55d5d488e60b..a0ca239a4416 100644 --- a/crawl-ref/docs/develop/levels/advanced.txt +++ b/crawl-ref/docs/develop/levels/advanced.txt @@ -114,6 +114,10 @@ two contexts: 1) An initial compilation phase before the game starts. 2) The actual mapgen phase when the dungeon builder is at work. +There are a number of caveats that go with phase 1. You can detect this phase +by using the `is_validating()` call or an `e.is_validating()` call where `e` is +the current map (`_G`). + In context (1), you will not get useful answers from the Crawl Lua API in general, because the game hasn't started. This is generally ignorable (as in the case above) because the compilation phase just @@ -156,6 +160,16 @@ Lua code can detect the compile phase using crawl.game_started() which returns true only when the player has started a game (and will return false when the map is being initially compiled). +In phase (1), you should avoid conditionals that impact tags randomly, and if +you are using any form of tag randomization, wrap it in a validating check. For +example: + +: if not is_validating() and crawl.coinflip() then +TAGS: no_pool_fixup +: end + +See `rng_guidelines.md` for more details on this particular caveat. + For more details on the available Lua API and syntax, see the Lua reference section. diff --git a/crawl-ref/docs/develop/rng_guidelines.md b/crawl-ref/docs/develop/rng_guidelines.md index 181a5bb6a0a0..3e18dee1e220 100644 --- a/crawl-ref/docs/develop/rng_guidelines.md +++ b/crawl-ref/docs/develop/rng_guidelines.md @@ -195,7 +195,19 @@ example, don't use lua's `math.rand`, or C stdlib's `rand`. Try to avoid vault design elements that will lead to variable .des caches; any random choices made here will be outside of levelgen rng, and potentially set at the time the player first opens crawl. Especially try to avoid -determining a set of tags for a map randomly using lua `tags` calls. +determining a set of tags for a map randomly using lua `tags` calls. If you +must randomize tags, wrap your conditionals in a validating check. For lua, +this usually looks like: + + if not e.is_validating() and crawl.one_chance_in(25) then + e.tags("no_monster_gen") + end + +and for conditionalizing the TAGS field in a .des file, this looks like: + + : if not is_validating() and crawl.coinflip() then + TAGS: no_pool_fixup + : end ## 4. Dealing with seed divergence From 225fefd5308d168af4209389d2be6864448f21b4 Mon Sep 17 00:00:00 2001 From: Alex Jurkiewicz Date: Fri, 28 Jun 2019 03:41:36 +1000 Subject: [PATCH 458/864] Mark some runed door vaults as no_tele_into (#1092) Replace an empty square in one with $ to simplify the KPROP logic. --- crawl-ref/source/dat/des/variable/float.des | 1 + crawl-ref/source/dat/des/variable/mini_monsters.des | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/dat/des/variable/float.des b/crawl-ref/source/dat/des/variable/float.des index fd6db25cbe80..73fd5f6f8050 100644 --- a/crawl-ref/source/dat/des/variable/float.des +++ b/crawl-ref/source/dat/des/variable/float.des @@ -8502,6 +8502,7 @@ DEPTH: D:8-, Depths ORIENT: float KMONS: 8 = 8 KITEM: 8 = | +KPROP: 8 = no_tele_into SUBST: c : cvb, x : xcvb MAP xxxxxx@xx diff --git a/crawl-ref/source/dat/des/variable/mini_monsters.des b/crawl-ref/source/dat/des/variable/mini_monsters.des index 91c8529c07e8..6cc11fcd80b8 100644 --- a/crawl-ref/source/dat/des/variable/mini_monsters.des +++ b/crawl-ref/source/dat/des/variable/mini_monsters.des @@ -4831,6 +4831,7 @@ ENDMAP NAME: minmay_hidden_floor DEPTH: D:12-, Depths SUBST: 9 = 9999., 8 = 8888. +KPROP: 8*$ = no_tele_into MAP @ cccccnccccc @@ -4838,7 +4839,7 @@ c.........c c.ccc9ccc.c c.c8ncn8c.c c.cn***nc.c -@.9c*.*c9.n@ +@.9c*$*c9.n@ cncn***nc.c c.=8ncn8c.c c.ccc9ccc.c From 36f2fa8efd7e25e99234f16fd133e896591860ff Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 30 Jun 2019 15:22:07 -0400 Subject: [PATCH 459/864] Let store classes save strings >32k This is a bit of a hacky way to do this, in order to avoid any save compat issues; it adds a save-only type, SV_STR_LONG that is normalized to SV_STR once the store is loaded. --- crawl-ref/source/store.cc | 33 ++++++++++++++++++++++++++++----- crawl-ref/source/store.h | 3 ++- crawl-ref/source/tags.cc | 12 +++++++++--- 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/crawl-ref/source/store.cc b/crawl-ref/source/store.cc index bbcec5df264b..74cedb32e23b 100644 --- a/crawl-ref/source/store.cc +++ b/crawl-ref/source/store.cc @@ -429,13 +429,18 @@ store_val_type CrawlStoreValue::get_type() const // Read/write from/to savefile void CrawlStoreValue::write(writer &th) const { - ASSERT(type != SV_NONE || (flags & SFLAG_UNSET)); - ASSERT(!(flags & SFLAG_UNSET) || type == SV_NONE); - - marshallByte(th, (char) type); + auto _type = type; + ASSERT(_type != SV_NONE || (flags & SFLAG_UNSET)); + ASSERT(!(flags & SFLAG_UNSET) || _type == SV_NONE); + // if the string is too long to save using the regular way, write it with + // a 4 byte length. SV_STR_LONG is for saving/loading only. + if (_type == SV_STR && static_cast(val.ptr)->length() > SHRT_MAX) + _type = SV_STR_LONG; + + marshallByte(th, (char) _type); marshallByte(th, (char) flags); - switch (type) + switch (_type) { case SV_BOOL: marshallBoolean(th, val.boolean); @@ -468,6 +473,13 @@ void CrawlStoreValue::write(writer &th) const break; } + case SV_STR_LONG: + { + string* str = static_cast(val.ptr); + marshallString4(th, *str); + break; + } + case SV_COORD: { coord_def* coord = static_cast(val.ptr); @@ -575,6 +587,15 @@ void CrawlStoreValue::read(reader &th) break; } + case SV_STR_LONG: + { + val.ptr = (void*) new string(); + unmarshallString4(th, *static_cast(val.ptr)); + // SV_STR_LONG is used only for saving + type = SV_STR; + break; + } + case SV_COORD: { const coord_def coord = unmarshallCoord(th); @@ -650,6 +671,7 @@ void CrawlStoreValue::read(reader &th) break; case NUM_STORE_VAL_TYPES: + default: die("unknown stored value type"); } } @@ -1264,6 +1286,7 @@ void CrawlHashTable::assert_validity() const ASSERT(key == trimmed); ASSERT(val.type != SV_NONE); + ASSERT(val.type != SV_STR_LONG); ASSERT(!(val.flags & SFLAG_UNSET)); switch (val.type) diff --git a/crawl-ref/source/store.h b/crawl-ref/source/store.h index 6daba94f70ea..db21b940494e 100644 --- a/crawl-ref/source/store.h +++ b/crawl-ref/source/store.h @@ -49,7 +49,8 @@ enum store_val_type SV_MONST, SV_LUA, SV_INT64, - NUM_STORE_VAL_TYPES + NUM_STORE_VAL_TYPES, + SV_STR_LONG, // this is a save-only type }; enum store_flag_type diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index 7e8b9612af47..4f7d775d5ec2 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -866,14 +866,20 @@ static string unmarshallString2(reader &th) // string -- 4 byte length, non-terminated string data. void marshallString4(writer &th, const string &data) { - marshallInt(th, data.length()); - th.write(data.c_str(), data.length()); + const size_t len = data.length(); + if (len > INT_MAX) + die("trying to marshall too long a string (len=%ld)", (long int) len); + marshallInt(th, len); + th.write(data.c_str(), len); } + void unmarshallString4(reader &th, string& s) { const int len = unmarshallInt(th); + ASSERT(len >= 0); s.resize(len); - if (len) th.read(&s.at(0), len); + if (len) + th.read(&s.at(0), len); } // boolean (to avoid system-dependent bool implementations) From 720adc72dc6388897f02ba0704ccf64870894a60 Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 30 Jun 2019 15:25:05 -0400 Subject: [PATCH 460/864] Save builder logs in save file for debug builds This specifically requires DEBUG_DIAGNOSTICS, since it only makes sense to enable if `dprf` is going to work. What this does is just store any logging that happens during levelgen into a hashtable in you.props. For a fully pregenerated build, this can increase the size of a save file by about 300k, so it may be non-trivial, but it's only going to be enabled in dev settings I think. If that bugs anyone it would certainly be possible to make it more conditional. This change is because scrutinizing these logs is stop 1 of fixing any seed divergence, and this commit will make it a lot easier to get at them, as well as deal with cases where the build logs are bigger than the default log line limit. --- crawl-ref/source/dbg-util.cc | 41 ++++++++++++++++++++++++++++++++ crawl-ref/source/dbg-util.h | 1 + crawl-ref/source/dungeon.cc | 9 +++++++ crawl-ref/source/message.cc | 46 ++++++++++++++++++++++++++++++++++++ crawl-ref/source/message.h | 16 +++++++++++++ crawl-ref/source/wizard.cc | 8 ++++++- 6 files changed, 120 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/dbg-util.cc b/crawl-ref/source/dbg-util.cc index 522d042db412..72f40baa724a 100644 --- a/crawl-ref/source/dbg-util.cc +++ b/crawl-ref/source/dbg-util.cc @@ -10,12 +10,14 @@ #include "artefact.h" #include "directn.h" #include "dungeon.h" +#include "format.h" #include "item-name.h" #include "libutil.h" #include "macro.h" #include "message.h" #include "options.h" #include "religion.h" +#include "scroller.h" #include "shopping.h" #include "skills.h" #include "spl-util.h" @@ -117,6 +119,45 @@ void debug_dump_levgen() mpr(""); } +void debug_show_builder_logs() +{ + if (!you.props.exists("debug_builder_logs")) + { + mprf("This save was not generated on a build that stores logs."); + return; + } + const string cur_level = level_id::current().describe(); + CrawlHashTable &log_table = you.props["debug_builder_logs"].get_table(); + if (!log_table.exists(cur_level) + || log_table[cur_level].get_string().size() == 0) + { + mprf("No builder logs are saved for %s.", cur_level.c_str()); + return; + } + const string &props_text = log_table[cur_level].get_string(); + stringstream st(props_text); + string text; + formatted_string lines; + + while (getline(st, text)) + { + linebreak_string(text, cgetsize(GOTO_CRT).x - 1); + vector parts; + formatted_string::parse_string_to_multiple(text, parts, 80); + for (unsigned int j = 0; j < parts.size(); ++j) + { + if (!lines.empty()) + lines.add_glyph('\n'); + lines += parts[j]; + } + } + + formatted_scroller hist(FS_PREWRAPPED_TEXT); + hist.set_more(); + hist.add_formatted_string(lines, !lines.empty()); + hist.show(); +} + string debug_coord_str(const coord_def &pos) { return make_stringf("(%d, %d)%s", pos.x, pos.y, diff --git a/crawl-ref/source/dbg-util.h b/crawl-ref/source/dbg-util.h index 3b8b5042aaef..b7175fdb706b 100644 --- a/crawl-ref/source/dbg-util.h +++ b/crawl-ref/source/dbg-util.h @@ -12,6 +12,7 @@ skill_type skill_from_name(const char *name); int debug_cap_stat(int stat); void debug_dump_levgen(); +void debug_show_builder_logs(); struct item_def; string debug_art_val_str(const item_def& item); diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index e32ae2632391..7bae889b37b7 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -50,6 +50,7 @@ #include "libutil.h" #include "mapmark.h" #include "maps.h" +#include "message.h" #include "mon-death.h" #include "mon-pick.h" #include "mon-place.h" @@ -260,6 +261,14 @@ bool builder(bool enable_random_maps) unwind_bool levelgen(crawl_state.generating_level, true); rng_generator levelgen_rng(you.where_are_you); +#ifdef DEBUG_DIAGNOSTICS // no point in enabling unless dprf works + CrawlHashTable &debug_logs = you.props["debug_builder_logs"].get_table(); + string &cur_level_log = debug_logs[level_id::current().describe()].get_string(); + message_tee debug_messages(cur_level_log); + debug_messages.append_line(make_stringf("Builder log for %s:", + level_id::current().describe().c_str())); +#endif + // N tries to build the level, after which we bail with a capital B. int tries = 50; while (tries-- > 0) diff --git a/crawl-ref/source/message.cc b/crawl-ref/source/message.cc index d00fcff7e908..3ea82f8503bc 100644 --- a/crawl-ref/source/message.cc +++ b/crawl-ref/source/message.cc @@ -945,6 +945,49 @@ static msg_colour_type prepare_message(const string& imsg, msg_channel_type channel, int param); +static unordered_set current_message_tees; + +message_tee::message_tee() + : target(nullptr) +{ + current_message_tees.insert(this); +} + +message_tee::message_tee(string &_target) + : target(&_target) +{ + current_message_tees.insert(this); +} + +message_tee::~message_tee() +{ + if (target) + *target += get_store(); + current_message_tees.erase(this); +} + +void message_tee::append(const string &s) +{ + // could use a more c++y external interface -- but that just complicates things + store << s; +} + +void message_tee::append_line(const string &s) +{ + store << s << "\n"; +} + +string message_tee::get_store() const +{ + return store.str(); +} + +static void _append_to_tees(const string &s) +{ + for (auto tee : current_message_tees) + tee->append(s); +} + no_messages::no_messages() : msuppressed(suppress_messages) { suppress_messages = true; @@ -1416,6 +1459,9 @@ static void _mpr(string text, msg_channel_type channel, int param, bool nojoin, string col = colour_to_str(colour_msg(colour)); text = "<" + col + ">" + text + ""; // XXX + if (current_message_tees.size()) + _append_to_tees(text + "\n"); + formatted_string fs = formatted_string::parse_string(text); // TODO: this kind of check doesn't really belong in logging code... diff --git a/crawl-ref/source/message.h b/crawl-ref/source/message.h index 93b626f9dcbd..c61a3cc4038b 100644 --- a/crawl-ref/source/message.h +++ b/crawl-ref/source/message.h @@ -8,6 +8,7 @@ #include #include #include +#include #include "canned-message-type.h" #include "enum.h" @@ -95,6 +96,21 @@ void msgwin_new_turn(); bool msgwin_errors_to_stderr(); +class message_tee +{ +public: + message_tee(); + message_tee(string &_target); + ~message_tee(); + void append(const string &s); + void append_line(const string &s); + string get_store() const; + +private: + stringstream store; + string *target; +}; + class no_messages { public: diff --git a/crawl-ref/source/wizard.cc b/crawl-ref/source/wizard.cc index 0b2113339650..d9f46efd994f 100644 --- a/crawl-ref/source/wizard.cc +++ b/crawl-ref/source/wizard.cc @@ -115,7 +115,7 @@ static void _do_wizard_command(int wiz_command) case 'l': wizard_set_xl(); break; case 'L': debug_place_map(false); break; - // case CONTROL('L'): break; + case CONTROL('L'): debug_show_builder_logs(); break; case 'M': case 'm': wizard_create_spec_monster_name(); break; @@ -442,6 +442,12 @@ int list_wizard_commands(bool do_redraw_screen) "{ magic mapping\n" "Ctrl-W change Shoals' tide speed\n" "Ctrl-E dump level builder information\n" +#ifdef DEBUG + // might be present in any save, but only generated + // in debug builds; hide this for regular wizmode so as + // to not confuse non-devs. The command will still work. + "Ctrl-L show builder logs for level\n" +#endif "Ctrl-R regenerate current level\n" "P create a level based on a vault\n", true); From e24419a6adaac8cf32b735498beb86b67f250139 Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 30 Jun 2019 15:56:59 -0400 Subject: [PATCH 461/864] Use int32_t for a size check for string marshalling --- crawl-ref/source/tags.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index 4f7d775d5ec2..9b51e1dc329f 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -376,6 +376,7 @@ uint8_t unmarshallUByte(reader &th) // Marshall 2 byte short in network order. void marshallShort(writer &th, short data) { + // TODO: why does this use `short` and `char` when unmarshall uses int16_t?? CHECK_INITIALIZED(data); const char b2 = (char)(data & 0x00FF); const char b1 = (char)((data & 0xFF00) >> 8); @@ -830,7 +831,7 @@ float unmarshallFloat(reader &th) void marshallString(writer &th, const string &data) { size_t len = data.length(); - // A limit of 32K. + // A limit of 32K. TODO: why doesn't this use int16_t? if (len > SHRT_MAX) die("trying to marshall too long a string (len=%ld)", (long int)len); marshallShort(th, len); @@ -840,7 +841,7 @@ void marshallString(writer &th, const string &data) string unmarshallString(reader &th) { - char buffer[SHRT_MAX]; + char buffer[SHRT_MAX]; // TODO: why doesn't this use int16_t? short len = unmarshallShort(th); ASSERT(len >= 0); @@ -867,7 +868,7 @@ static string unmarshallString2(reader &th) void marshallString4(writer &th, const string &data) { const size_t len = data.length(); - if (len > INT_MAX) + if (len > numeric_limits::max()) die("trying to marshall too long a string (len=%ld)", (long int) len); marshallInt(th, len); th.write(data.c_str(), len); From 3510def36b312a4d80f43876ce94e509f06c3390 Mon Sep 17 00:00:00 2001 From: Seve Monahan Date: Wed, 26 Jun 2019 21:43:13 -0400 Subject: [PATCH 462/864] Fix a text bug. (#11665) This fixes a text bug which occurred when a feared monster was hit by an explosion from a wild magic card. --- crawl-ref/source/spl-miscast.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/spl-miscast.cc b/crawl-ref/source/spl-miscast.cc index dfdb2beed323..dcd72efd809c 100644 --- a/crawl-ref/source/spl-miscast.cc +++ b/crawl-ref/source/spl-miscast.cc @@ -495,7 +495,7 @@ bool MiscastEffect::_explosion() // wild magic card if (special_source.source == miscast_source::deck) - beam.thrower = KILL_MISCAST; + beam.thrower = KILL_YOU; int max_dam = beam.damage.num * beam.damage.size; max_dam = check_your_resists(max_dam, beam.flavour, cause); From 6b2be6b8c740fd9c1477db39ead10a81a8e1a772 Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 2 Jul 2019 10:42:03 -0400 Subject: [PATCH 463/864] Don't let `X.` show completely inaccessible travel targets This fixes some aspects of 11771, though not the main issue reported there (which is more of a UI issue than a bug per se). This commit, for example, will prevent an off-level travel target from being shown in abyss, because off-level travel doesn't work at all there. --- crawl-ref/source/viewmap.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/source/viewmap.cc b/crawl-ref/source/viewmap.cc index ab9465e0e22c..1283e82b944e 100644 --- a/crawl-ref/source/viewmap.cc +++ b/crawl-ref/source/viewmap.cc @@ -1188,6 +1188,7 @@ bool show_map(level_pos &lpos, move_y = you.travel_y - lpos.pos.y; } else if (allow_offlevel && you.travel_z.is_valid() + && can_travel_to(you.travel_z) && you.level_visited(you.travel_z)) { // previous travel target is offlevel From 4402b9e188df1cdef53e46d8b1653fc5420b394c Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 3 Jul 2019 10:26:26 -0400 Subject: [PATCH 464/864] Improve zooming behavior (mainly for local tiles) This commit makes two changes: it adds an option that lets you zoom the dungeon view via a multiplier, rather than a number of pixels, and it lets this zoom be adjusted in-game via CMD_ZOOM_IN and CMD_ZOOM_OUT (previously only available for the small screen ui). The first change is just because using pixel values is not the most intuitive thing for most players (I've noticed), and is basically cosmetic if you already know how to change the tile size. In local tiles, these commands are bound to ctrl-'-' and ctrl-'='. I was unable to find a good binding for these commands in webtiles, so they are unbound (though they should work), but that's probably ok because browser zoom already works ok in accomplishing a similar thing. The zoom level is reset to its rc value on start and currently not saved. --- crawl-ref/docs/options_guide.txt | 14 +++++++---- crawl-ref/source/cmd-keys.h | 5 ++++ crawl-ref/source/command-type.h | 7 +++--- crawl-ref/source/initfile.cc | 18 +++++++++++++++ crawl-ref/source/macro.cc | 4 ++++ crawl-ref/source/main.cc | 3 +-- crawl-ref/source/options.h | 1 + crawl-ref/source/tilesdl.cc | 23 +++++++++++++++++-- crawl-ref/source/tileweb.cc | 18 +++++++++++++++ crawl-ref/source/tileweb.h | 2 ++ crawl-ref/source/ui.cc | 1 + .../game_data/static/dungeon_renderer.js | 6 +++-- .../webserver/game_data/static/options.js | 13 +++++++++-- 13 files changed, 98 insertions(+), 17 deletions(-) diff --git a/crawl-ref/docs/options_guide.txt b/crawl-ref/docs/options_guide.txt index a5944a9d6957..55c2c147325f 100644 --- a/crawl-ref/docs/options_guide.txt +++ b/crawl-ref/docs/options_guide.txt @@ -2034,12 +2034,16 @@ tile_map_pixels = 0 downside is that travelling by clicking on the minimap becomes much harder. If set to zero, it will auto-size the minimap. +tile_viewport_scale = 1.0 + A scale factor to apply to the dungeon view. The minimum value is 0.2 + and the maximum value is determined by resolution; zoom will be capped + so that at a minimum, your line of sight is always visible. This can + also be adjusted in-game in local tiles with ctrl-'-' and ctrl-'='. + tile_cell_pixels = 32 - The width and height of tiles in the dungeon view. If you want - to see the tiles in all their glory and have a large - resolution, set this to 48 or even 64; but note that tiles - will be automatically scaled down to fit the visible area on - the screen. + The width and height of tiles in the dungeon view at 1.0 scale, in + (logical) pixels. This is a legacy option, and it is recommended that + you adjust scaling via tile_viewport_scale instead. tile_filter_scaling = false Used in conjunction with tile_cell_pixels. Setting it to true filters diff --git a/crawl-ref/source/cmd-keys.h b/crawl-ref/source/cmd-keys.h index 9a2045263592..83c4b3d6247b 100644 --- a/crawl-ref/source/cmd-keys.h +++ b/crawl-ref/source/cmd-keys.h @@ -377,6 +377,11 @@ // zoom functions {CK_NUMPAD_PLUS, CMD_ZOOM_IN}, {CK_NUMPAD_MINUS, CMD_ZOOM_OUT}, +#elif defined(USE_TILE_LOCAL) +{'=' - SDLK_a + 1, CMD_ZOOM_IN}, // Believe it or not, this is how we map SDL +{'-' - SDLK_a + 1, CMD_ZOOM_OUT}, // ctrl scancodes... +// no good webtiles keys available, and browser zoom already more or less +// accomplishes this anyways. #endif {'\0', CMD_NO_CMD} diff --git a/crawl-ref/source/command-type.h b/crawl-ref/source/command-type.h index b09380bdbe68..01bf1b6dc534 100644 --- a/crawl-ref/source/command-type.h +++ b/crawl-ref/source/command-type.h @@ -137,16 +137,15 @@ enum command_type #endif #ifdef USE_TILE + CMD_ZOOM_IN, + CMD_ZOOM_OUT, + CMD_EDIT_PLAYER_TILE, CMD_MIN_TILE = CMD_EDIT_PLAYER_TILE, CMD_MAX_TILE = CMD_EDIT_PLAYER_TILE, #endif #ifdef TOUCH_UI - // zoom on dungeon - CMD_ZOOM_IN, - CMD_ZOOM_OUT, - // bring up the on-screen keyboard if needed CMD_SHOW_KEYBOARD, #endif diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index 6804b8769f4c..f9fdb1ceeec8 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -1131,6 +1131,7 @@ void game_options::reset_options() tile_weapon_offsets.second = INT_MAX; tile_shield_offsets.first = INT_MAX; tile_shield_offsets.second = INT_MAX; + tile_viewport_scale = 100; #endif #ifdef USE_TILE_WEB @@ -3452,6 +3453,22 @@ void game_options::read_option_line(const string &str, bool runscript) } #endif } +#ifdef USE_TILE + else if (key == "tile_viewport_scale") + { + float tmp_scale; + if (sscanf(field.c_str(), "%f", &tmp_scale)) + { + tile_viewport_scale = min(1600, max(20, + static_cast(tmp_scale * 100))); + } + else + { + report_error("Expected a decimal value for tile_viewport_scale," + " but got '%s'.", field.c_str()); + } + } +#endif // Catch-all else, copies option into map else if (runscript) @@ -4468,6 +4485,7 @@ void game_options::write_webtiles_options(const string& name) tiles.json_write_string("tile_display_mode", Options.tile_display_mode); tiles.json_write_int("tile_cell_pixels", Options.tile_cell_pixels); + tiles.json_write_int("tile_viewport_scale", Options.tile_viewport_scale); tiles.json_write_bool("tile_filter_scaling", Options.tile_filter_scaling); tiles.json_write_bool("tile_water_anim", Options.tile_water_anim); tiles.json_write_bool("tile_misc_anim", Options.tile_misc_anim); diff --git a/crawl-ref/source/macro.cc b/crawl-ref/source/macro.cc index f4abd68e5a96..c38d4d6a36a7 100644 --- a/crawl-ref/source/macro.cc +++ b/crawl-ref/source/macro.cc @@ -31,6 +31,10 @@ #include #include +#ifdef USE_TILE_LOCAL +#include +#endif + #include "cio.h" #include "command.h" #include "files.h" diff --git a/crawl-ref/source/main.cc b/crawl-ref/source/main.cc index 42c4fc8f808e..801f9600c567 100644 --- a/crawl-ref/source/main.cc +++ b/crawl-ref/source/main.cc @@ -1791,8 +1791,7 @@ void process_command(command_type cmd) case CMD_DISPLAY_OVERMAP: display_overview(); break; case CMD_DISPLAY_MAP: _do_display_map(); break; -#ifdef TOUCH_UI - // zoom commands +#ifdef USE_TILE case CMD_ZOOM_IN: tiles.zoom_dungeon(true); break; case CMD_ZOOM_OUT: tiles.zoom_dungeon(false); break; #endif diff --git a/crawl-ref/source/options.h b/crawl-ref/source/options.h index 734e206eee2c..ba6e6257aa05 100644 --- a/crawl-ref/source/options.h +++ b/crawl-ref/source/options.h @@ -553,6 +553,7 @@ struct game_options maybe_bool tile_use_small_layout; #endif int tile_cell_pixels; + int tile_viewport_scale; bool tile_filter_scaling; int tile_map_pixels; diff --git a/crawl-ref/source/tilesdl.cc b/crawl-ref/source/tilesdl.cc index 0d4175bbfbd7..df29dcc72276 100644 --- a/crawl-ref/source/tilesdl.cc +++ b/crawl-ref/source/tilesdl.cc @@ -892,8 +892,8 @@ static int round_up_to_multiple(int a, int b) void TilesFramework::do_layout() { // View size in pixels is (m_viewsc * crawl_view.viewsz) - m_viewsc.x = Options.tile_cell_pixels; - m_viewsc.y = Options.tile_cell_pixels; + m_viewsc.x = Options.tile_cell_pixels * Options.tile_viewport_scale / 100; + m_viewsc.y = Options.tile_cell_pixels * Options.tile_viewport_scale / 100; crawl_view.viewsz.x = Options.view_max_width; crawl_view.viewsz.y = Options.view_max_height; @@ -1088,9 +1088,28 @@ bool TilesFramework::is_using_small_layout() return Options.tile_use_small_layout == MB_TRUE; #endif } + +#define ZOOM_INC 10 + void TilesFramework::zoom_dungeon(bool in) { +#ifdef TOUCH_UI m_region_tile->zoom(in); +#elif defined(USE_TILE_LOCAL) + // max zoom relative to to tile size that keeps LOS in view + int max_zoom = 100 * m_windowsz.y / Options.tile_cell_pixels + / ENV_SHOW_DIAMETER; + if (max_zoom % ZOOM_INC != 0) + max_zoom += ZOOM_INC - max_zoom % ZOOM_INC; // round up + Options.tile_viewport_scale = min(max_zoom, max(20, + Options.tile_viewport_scale + (in ? ZOOM_INC : -ZOOM_INC))); + do_layout(); // recalculate the viewport setup + dprf("Zooming to %d", Options.tile_viewport_scale); + ui::ui_force_render(); // this will trigger a redraw -- need to do a + // higher-level rerender than just a tiles redraw, + // otherwise some text gets blanked out (not sure + // why). +#endif } bool TilesFramework::zoom_to_minimap() diff --git a/crawl-ref/source/tileweb.cc b/crawl-ref/source/tileweb.cc index 352087870d29..93a36c3535da 100644 --- a/crawl-ref/source/tileweb.cc +++ b/crawl-ref/source/tileweb.cc @@ -550,6 +550,24 @@ void TilesFramework::_send_options() finish_message(); } +#define ZOOM_INC 10 + +void TilesFramework::zoom_dungeon(bool in) +{ + Options.tile_viewport_scale = min(300, max(20, + Options.tile_viewport_scale + (in ? ZOOM_INC : -ZOOM_INC))); + tiles.json_open_object(); + tiles.json_write_string("msg", "set_option"); + tiles.json_write_string("name", "tile_viewport_scale"); + tiles.json_write_int("value", Options.tile_viewport_scale); + tiles.json_close_object(); + tiles.finish_message(); + dprf("Zooming to %d", Options.tile_viewport_scale); + // calling redraw explicitly is not needed here: it triggers from a + // listener on the webtiles side. + // TODO: how to implement dynamic max zoom that reacts to the webtiles side? +} + void TilesFramework::_send_layout() { tiles.json_open_object(); diff --git a/crawl-ref/source/tileweb.h b/crawl-ref/source/tileweb.h index 359fb762f307..80cbd04d1716 100644 --- a/crawl-ref/source/tileweb.h +++ b/crawl-ref/source/tileweb.h @@ -208,6 +208,8 @@ class TilesFramework bool send_doll = true); void write_tileidx(tileidx_t t); + void zoom_dungeon(bool in); + protected: int m_sock; int m_max_msg_size; diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index f1269f5633d3..00ac246153d0 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -1723,6 +1723,7 @@ static void remap_key(wm_event &event) void ui_force_render() { ui_root.layout(); + ui_root.needs_paint = true; ui_root.render(); } diff --git a/crawl-ref/source/webserver/game_data/static/dungeon_renderer.js b/crawl-ref/source/webserver/game_data/static/dungeon_renderer.js index 6f1d64784447..3c2e5d997f64 100644 --- a/crawl-ref/source/webserver/game_data/static/dungeon_renderer.js +++ b/crawl-ref/source/webserver/game_data/static/dungeon_renderer.js @@ -236,9 +236,11 @@ function ($, cr, map_knowledge, options, dngn, util, view_data, enums) { fit_to: function(width, height, min_diameter) { var ratio = window.devicePixelRatio; + var tile_size = Math.floor(options.get("tile_cell_pixels") + * options.get("tile_viewport_scale") / 100); var cell_size = { - w: Math.floor(options.get("tile_cell_pixels") * ratio), - h: Math.floor(options.get("tile_cell_pixels") * ratio) + w: Math.floor(tile_size * ratio), + h: Math.floor(tile_size * ratio) }; if (options.get("tile_display_mode") == "glyphs") diff --git a/crawl-ref/source/webserver/game_data/static/options.js b/crawl-ref/source/webserver/game_data/static/options.js index b7759b732e1a..15440bb0ad3a 100644 --- a/crawl-ref/source/webserver/game_data/static/options.js +++ b/crawl-ref/source/webserver/game_data/static/options.js @@ -27,6 +27,7 @@ function ($, comm) { return options[name]; } + // writes all options at once: usable only on first connecting. function handle_options_message(data) { if (options == null || data["watcher"] == true) @@ -41,21 +42,29 @@ function ($, comm) { listeners.add(callback); } - // for testing purposes only - window.set_option = function(name, value) + function set_option(name, value) { var old = get_option(name); console.log(name + ": '" + old + "' => '" + value + "'"); options[name] = value; listeners.fire(); + } + + function handle_set_option(data) + { + set_option(data.name, data.value); }; + window.set_option = set_option; + comm.register_handlers({ "options": handle_options_message, + "set_option": handle_set_option }); return { get: get_option, + set: set_option, clear: clear_options, add_listener: add_listener, }; From f8f69c1b1ce2daf4fd1b853d4bcd9ee020441935 Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 3 Jul 2019 11:32:00 -0400 Subject: [PATCH 465/864] Start local tiles on the current display Previously, it just started on display 0 regardless of where the focus was, which is pretty annoying if you have a laptop+monitor setup. This uses mouse location to find the current display, and opens the window there. (N.b. this may differ from OS-specific means of finding the "current" display, for example, Cocoa uses keyboard focus, not mouse focus. But SDL doesn't seem to provide an interface to any of these checks.) This is tested and works on os x, but it would be useful to know before a release if this works on windows/linux... --- crawl-ref/source/windowmanager-sdl.cc | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/windowmanager-sdl.cc b/crawl-ref/source/windowmanager-sdl.cc index 284cd4a2c581..88732108df02 100644 --- a/crawl-ref/source/windowmanager-sdl.cc +++ b/crawl-ref/source/windowmanager-sdl.cc @@ -362,8 +362,28 @@ int SDLWrapper::init(coord_def *m_windowsz) return false; } + // find the current display, based on the mouse position + // TODO: probably want to allow configuring this? + int mouse_x, mouse_y; + SDL_GetGlobalMouseState(&mouse_x, &mouse_y); + + int displays = SDL_GetNumVideoDisplays(); + int cur_display; + for (cur_display = 0; cur_display < displays; cur_display++) + { + SDL_Rect bounds; + SDL_GetDisplayBounds(cur_display, &bounds); + if (mouse_x >= bounds.x && mouse_y >= bounds.y && + mouse_x < bounds.x + bounds.w && mouse_y < bounds.y + bounds.h) + { + break; + } + } + if (cur_display >= displays) + cur_display = 0; // can this happen? + SDL_DisplayMode display_mode; - SDL_GetDesktopDisplayMode(0, &display_mode); + SDL_GetDesktopDisplayMode(cur_display, &display_mode); _desktop_width = display_mode.w; _desktop_height = display_mode.h; @@ -439,8 +459,8 @@ int SDLWrapper::init(coord_def *m_windowsz) string title = string(CRAWL " ") + Version::Long; m_window = SDL_CreateWindow(title.c_str(), - SDL_WINDOWPOS_UNDEFINED, - SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_CENTERED_DISPLAY(cur_display), + SDL_WINDOWPOS_CENTERED_DISPLAY(cur_display), m_windowsz->x, m_windowsz->y, flags); glDebug("SDL_CreateWindow"); if (!m_window) From a9e2c0f7d088d4a5b8b8e55560cf668af753445a Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 3 Jul 2019 17:36:04 -0400 Subject: [PATCH 466/864] Let X be zoomed differently from main map, default to 60% In console, the `X` view is really useful in terms of getting a quick overview of the level map. However, it's always struck me as a bit useless / vestigial on tiles, because the amount of map displayed wasn't much different from what `x` displays, just with a different set of keys and behavior. The situation is slightly better on webtiles, where at least the message pane is hidden, but on local tiles it literally was not different. This commit allows the `X` view to be zoomed differently from the main map, and defaults it to 60% zoom (as opposed to default 100% zoom). You can also now change the zoom in game using {,}. On local tiles, ctrl-'-' and ctrl-'=' also work (as with the main view). To return this behavior to its previous state, set the (new) rc option `tile_map_scale` to 1.0. There are a few awkward issues remaining. In webtiles, some status messages printed using `mpr` are no longer visible in `X` mode, though prompts will work (see 65f37df). I'm not yet sure what the best solution for these is. Also, unlike local tiles, webtiles lets you zoom beyond what will actually display, because I couldn't figure out a simple way of getting this information back from the client (though there are certainly complex ways of doing this). --- crawl-ref/docs/options_guide.txt | 5 +++ crawl-ref/source/cmd-keys.h | 10 ++++- crawl-ref/source/command-type.h | 5 +++ crawl-ref/source/dat/database/help.txt | 1 + crawl-ref/source/initfile.cc | 17 ++++++++ crawl-ref/source/options.h | 1 + crawl-ref/source/tilesdl.cc | 23 ++++++---- crawl-ref/source/tileweb.cc | 32 +++++++++----- crawl-ref/source/viewmap.cc | 43 +++++++++++++------ .../game_data/static/dungeon_renderer.js | 13 +++++- .../source/webserver/game_data/static/game.js | 3 ++ 11 files changed, 116 insertions(+), 37 deletions(-) diff --git a/crawl-ref/docs/options_guide.txt b/crawl-ref/docs/options_guide.txt index 55c2c147325f..4c2c4ab585e7 100644 --- a/crawl-ref/docs/options_guide.txt +++ b/crawl-ref/docs/options_guide.txt @@ -2040,6 +2040,11 @@ tile_viewport_scale = 1.0 so that at a minimum, your line of sight is always visible. This can also be adjusted in-game in local tiles with ctrl-'-' and ctrl-'='. +tile_map_scale = 0.6 + A scale factor to apply to the dungeon view in map mode (X). This can + also be adjusted in map mode in tiles with '{' and '}', as well as in + local tiles with ctrl-'-' and ctrl-'='. + tile_cell_pixels = 32 The width and height of tiles in the dungeon view at 1.0 scale, in (logical) pixels. This is a legacy option, and it is recommended that diff --git a/crawl-ref/source/cmd-keys.h b/crawl-ref/source/cmd-keys.h index 83c4b3d6247b..b3fe0987e2c5 100644 --- a/crawl-ref/source/cmd-keys.h +++ b/crawl-ref/source/cmd-keys.h @@ -378,10 +378,16 @@ {CK_NUMPAD_PLUS, CMD_ZOOM_IN}, {CK_NUMPAD_MINUS, CMD_ZOOM_OUT}, #elif defined(USE_TILE_LOCAL) +// no good webtiles keys available for the main view case, and browser zoom +// already more or less accomplishes this. {'=' - SDLK_a + 1, CMD_ZOOM_IN}, // Believe it or not, this is how we map SDL {'-' - SDLK_a + 1, CMD_ZOOM_OUT}, // ctrl scancodes... -// no good webtiles keys available, and browser zoom already more or less -// accomplishes this anyways. +{'=' - SDLK_a + 1, CMD_MAP_ZOOM_IN}, +{'-' - SDLK_a + 1, CMD_MAP_ZOOM_OUT}, +#endif +#ifdef USE_TILE +{'}', CMD_MAP_ZOOM_IN}, +{'{', CMD_MAP_ZOOM_OUT}, #endif {'\0', CMD_NO_CMD} diff --git a/crawl-ref/source/command-type.h b/crawl-ref/source/command-type.h index 01bf1b6dc534..590f93ba4a2f 100644 --- a/crawl-ref/source/command-type.h +++ b/crawl-ref/source/command-type.h @@ -221,6 +221,11 @@ enum command_type CMD_MAP_FORGET, CMD_MAP_UNFORGET, +#ifdef USE_TILE + CMD_MAP_ZOOM_IN, + CMD_MAP_ZOOM_OUT, +#endif + CMD_MAP_EXIT_MAP, CMD_MAX_OVERMAP = CMD_MAP_EXIT_MAP, diff --git a/crawl-ref/source/dat/database/help.txt b/crawl-ref/source/dat/database/help.txt index 1db168d4132a..247f2890ae65 100644 --- a/crawl-ref/source/dat/database/help.txt +++ b/crawl-ref/source/dat/database/help.txt @@ -162,6 +162,7 @@ level-map [ or ] : Examine the next higher or lower level G : Go to another level by branch and depth o : Move the cursor to the next autoexplore target. +{ or } : Zoom out or in (tiles only). Travel exclusions e : Create a travel exclusion, change its radius, or remove it. diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index f9fdb1ceeec8..23b309173346 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -1132,6 +1132,7 @@ void game_options::reset_options() tile_shield_offsets.first = INT_MAX; tile_shield_offsets.second = INT_MAX; tile_viewport_scale = 100; + tile_map_scale = 60; #endif #ifdef USE_TILE_WEB @@ -3454,6 +3455,7 @@ void game_options::read_option_line(const string &str, bool runscript) #endif } #ifdef USE_TILE + // TODO: generalize these to an option type? else if (key == "tile_viewport_scale") { float tmp_scale; @@ -3468,6 +3470,20 @@ void game_options::read_option_line(const string &str, bool runscript) " but got '%s'.", field.c_str()); } } + else if (key == "tile_map_scale") + { + float tmp_scale; + if (sscanf(field.c_str(), "%f", &tmp_scale)) + { + tile_map_scale = min(1600, max(20, + static_cast(tmp_scale * 100))); + } + else + { + report_error("Expected a decimal value for tile_map_scale," + " but got '%s'.", field.c_str()); + } + } #endif // Catch-all else, copies option into map @@ -4486,6 +4502,7 @@ void game_options::write_webtiles_options(const string& name) tiles.json_write_string("tile_display_mode", Options.tile_display_mode); tiles.json_write_int("tile_cell_pixels", Options.tile_cell_pixels); tiles.json_write_int("tile_viewport_scale", Options.tile_viewport_scale); + tiles.json_write_int("tile_map_scale", Options.tile_map_scale); tiles.json_write_bool("tile_filter_scaling", Options.tile_filter_scaling); tiles.json_write_bool("tile_water_anim", Options.tile_water_anim); tiles.json_write_bool("tile_misc_anim", Options.tile_misc_anim); diff --git a/crawl-ref/source/options.h b/crawl-ref/source/options.h index ba6e6257aa05..e85f750309c0 100644 --- a/crawl-ref/source/options.h +++ b/crawl-ref/source/options.h @@ -554,6 +554,7 @@ struct game_options #endif int tile_cell_pixels; int tile_viewport_scale; + int tile_map_scale; bool tile_filter_scaling; int tile_map_pixels; diff --git a/crawl-ref/source/tilesdl.cc b/crawl-ref/source/tilesdl.cc index df29dcc72276..d6f81cf43915 100644 --- a/crawl-ref/source/tilesdl.cc +++ b/crawl-ref/source/tilesdl.cc @@ -297,6 +297,8 @@ void TilesFramework::set_map_display(const bool display) m_map_mode_enabled = display; if (!display && !tiles.is_using_small_layout()) m_region_tab->activate_tab(TAB_ITEM); + do_layout(); // recalculate the viewport setup for zoom levels + redraw_screen(false); } bool TilesFramework::get_map_display() @@ -307,6 +309,8 @@ bool TilesFramework::get_map_display() void TilesFramework::do_map_display() { m_map_mode_enabled = true; + do_layout(); // recalculate the viewport setup for zoom levels + redraw_screen(false); m_region_tab->activate_tab(TAB_NAVIGATION); } @@ -892,8 +896,10 @@ static int round_up_to_multiple(int a, int b) void TilesFramework::do_layout() { // View size in pixels is (m_viewsc * crawl_view.viewsz) - m_viewsc.x = Options.tile_cell_pixels * Options.tile_viewport_scale / 100; - m_viewsc.y = Options.tile_cell_pixels * Options.tile_viewport_scale / 100; + const int scale = m_map_mode_enabled ? Options.tile_map_scale + : Options.tile_viewport_scale; + m_viewsc.x = Options.tile_cell_pixels * scale / 100; + m_viewsc.y = Options.tile_cell_pixels * scale / 100; crawl_view.viewsz.x = Options.view_max_width; crawl_view.viewsz.y = Options.view_max_height; @@ -1096,19 +1102,18 @@ void TilesFramework::zoom_dungeon(bool in) #ifdef TOUCH_UI m_region_tile->zoom(in); #elif defined(USE_TILE_LOCAL) + int ¤t_scale = m_map_mode_enabled ? Options.tile_map_scale + : Options.tile_viewport_scale; // max zoom relative to to tile size that keeps LOS in view int max_zoom = 100 * m_windowsz.y / Options.tile_cell_pixels / ENV_SHOW_DIAMETER; if (max_zoom % ZOOM_INC != 0) max_zoom += ZOOM_INC - max_zoom % ZOOM_INC; // round up - Options.tile_viewport_scale = min(max_zoom, max(20, - Options.tile_viewport_scale + (in ? ZOOM_INC : -ZOOM_INC))); + current_scale = min(max_zoom, max(20, + current_scale + (in ? ZOOM_INC : -ZOOM_INC))); do_layout(); // recalculate the viewport setup - dprf("Zooming to %d", Options.tile_viewport_scale); - ui::ui_force_render(); // this will trigger a redraw -- need to do a - // higher-level rerender than just a tiles redraw, - // otherwise some text gets blanked out (not sure - // why). + dprf("Zooming to %d", current_scale); + redraw_screen(false); #endif } diff --git a/crawl-ref/source/tileweb.cc b/crawl-ref/source/tileweb.cc index 93a36c3535da..432db41794f1 100644 --- a/crawl-ref/source/tileweb.cc +++ b/crawl-ref/source/tileweb.cc @@ -552,17 +552,32 @@ void TilesFramework::_send_options() #define ZOOM_INC 10 -void TilesFramework::zoom_dungeon(bool in) +static void _set_option_int(string name, int value) { - Options.tile_viewport_scale = min(300, max(20, - Options.tile_viewport_scale + (in ? ZOOM_INC : -ZOOM_INC))); tiles.json_open_object(); tiles.json_write_string("msg", "set_option"); - tiles.json_write_string("name", "tile_viewport_scale"); - tiles.json_write_int("value", Options.tile_viewport_scale); + tiles.json_write_string("name", name); + tiles.json_write_int("value", value); tiles.json_close_object(); tiles.finish_message(); - dprf("Zooming to %d", Options.tile_viewport_scale); +} + +void TilesFramework::zoom_dungeon(bool in) +{ + if (m_ui_state == UI_VIEW_MAP) + { + Options.tile_map_scale = min(300, max(20, + Options.tile_map_scale + (in ? ZOOM_INC : -ZOOM_INC))); + _set_option_int("tile_map_scale", Options.tile_map_scale); + dprf("Zooming map to %d", Options.tile_map_scale); + } + else + { + Options.tile_viewport_scale = min(300, max(20, + Options.tile_viewport_scale + (in ? ZOOM_INC : -ZOOM_INC))); + _set_option_int("tile_viewport_scale", Options.tile_viewport_scale); + dprf("Zooming to %d", Options.tile_viewport_scale); + } // calling redraw explicitly is not needed here: it triggers from a // listener on the webtiles side. // TODO: how to implement dynamic max zoom that reacts to the webtiles side? @@ -1856,11 +1871,6 @@ void TilesFramework::cgotoxy(int x, int y, GotoRegion region) m_print_x = x - 1; m_print_y = y - 1; - // XXX: an ugly hack necessary for webtiles X to work properly - // when showing message prompts (e.g. X!, XG) - if (region == GOTO_STAT || region == GOTO_MSG) - set_ui_state(UI_NORMAL); - bool crt_popup = region == GOTO_CRT && !m_menu_stack.empty() && m_menu_stack.back().type == UIStackFrame::CRT; m_print_area = crt_popup ? &m_text_menu : nullptr; diff --git a/crawl-ref/source/viewmap.cc b/crawl-ref/source/viewmap.cc index 1283e82b944e..31f379a18784 100644 --- a/crawl-ref/source/viewmap.cc +++ b/crawl-ref/source/viewmap.cc @@ -1028,26 +1028,29 @@ bool show_map(level_pos &lpos, } case CMD_MAP_GOTO_LEVEL: - { if (!allow_offlevel) break; - string name; - const level_pos pos - = prompt_translevel_target(TPF_DEFAULT_OPTIONS, name); - - if (pos.id.depth < 1 - || pos.id.depth > brdepth[pos.id.branch] - || !you.level_visited(pos.id)) { - canned_msg(MSG_OK); - redraw_map = true; - break; - } + string name; +#ifdef USE_TILE_WEB + tiles_ui_control msgwin(UI_NORMAL); +#endif + const level_pos pos + = prompt_translevel_target(TPF_DEFAULT_OPTIONS, name); + + if (pos.id.depth < 1 + || pos.id.depth > brdepth[pos.id.branch] + || !you.level_visited(pos.id)) + { + canned_msg(MSG_OK); + redraw_map = true; + break; + } - lpos = pos; + lpos = pos; + } continue; - } case CMD_MAP_JUMP_DOWN_LEFT: move_x = -block_step; @@ -1109,6 +1112,13 @@ bool show_map(level_pos &lpos, } break; +#ifdef USE_TILE + case CMD_MAP_ZOOM_IN: + case CMD_MAP_ZOOM_OUT: + tiles.zoom_dungeon(cmd == CMD_MAP_ZOOM_IN); + break; +#endif + case CMD_MAP_FIND_UPSTAIR: case CMD_MAP_FIND_DOWNSTAIR: case CMD_MAP_FIND_PORTAL: @@ -1214,7 +1224,12 @@ bool show_map(level_pos &lpos, if (!is_map_persistent()) mpr("You can't annotate this level."); else + { +#ifdef USE_TILE_WEB + tiles_ui_control msgwin(UI_NORMAL); +#endif do_annotate(lpos.id); + } redraw_map = true; break; diff --git a/crawl-ref/source/webserver/game_data/static/dungeon_renderer.js b/crawl-ref/source/webserver/game_data/static/dungeon_renderer.js index 3c2e5d997f64..3eec39e75097 100644 --- a/crawl-ref/source/webserver/game_data/static/dungeon_renderer.js +++ b/crawl-ref/source/webserver/game_data/static/dungeon_renderer.js @@ -51,6 +51,7 @@ function ($, cr, map_knowledge, options, dngn, util, view_data, enums) { this.view = { x: 0, y: 0 }; this.view_center = { x: 0, y: 0 }; + this.ui_state = -1; } DungeonViewRenderer.prototype = new cr.DungeonCellRenderer(); @@ -236,8 +237,13 @@ function ($, cr, map_knowledge, options, dngn, util, view_data, enums) { fit_to: function(width, height, min_diameter) { var ratio = window.devicePixelRatio; + var scale; + if (this.ui_state == enums.ui.VIEW_MAP) + scale = options.get("tile_map_scale"); + else + scale = options.get("tile_viewport_scale"); var tile_size = Math.floor(options.get("tile_cell_pixels") - * options.get("tile_viewport_scale") / 100); + * scale / 100); var cell_size = { w: Math.floor(tile_size * ratio), h: Math.floor(tile_size * ratio) @@ -350,6 +356,11 @@ function ($, cr, map_knowledge, options, dngn, util, view_data, enums) { renderer.draw_tiles(tiles); return renderer; + }, + + set_ui_state: function(s) + { + this.ui_state = s; } }); diff --git a/crawl-ref/source/webserver/game_data/static/game.js b/crawl-ref/source/webserver/game_data/static/game.js index 9a611e20cfc6..18c75760682e 100644 --- a/crawl-ref/source/webserver/game_data/static/game.js +++ b/crawl-ref/source/webserver/game_data/static/game.js @@ -137,13 +137,16 @@ function ($, comm, client, dungeon_renderer, display, minimap, enums, messages, messages.show(); } minimap.stop_minimap_farview(); + minimap.update_overlay(); display.invalidate(true); display.display(); } function set_ui_state(state) { + dungeon_renderer.set_ui_state(state); if (state == ui_state) return; + var old_state = ui_state; ui_state = state; switch (ui_state) From 378ef55cfb79986e30ee3e1db40bee620dc36b27 Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 3 Jul 2019 18:06:12 -0400 Subject: [PATCH 467/864] Add local tiles zoom to key reference --- crawl-ref/source/command.cc | 8 ++++++-- crawl-ref/source/macro.cc | 5 +++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc index 165303c09f1f..2985ed0617cc 100644 --- a/crawl-ref/source/command.cc +++ b/crawl-ref/source/command.cc @@ -914,9 +914,9 @@ static void _add_formatted_keyhelp(column_composer &cols) 1, "Dungeon Interaction and Information:\n"); - _add_insert_commands(cols, 1, "%/% : Open/Close door", + _add_insert_commands(cols, 1, "%/% : Open/Close door", { CMD_OPEN_DOOR, CMD_CLOSE_DOOR }); - _add_insert_commands(cols, 1, "%/% : use staircase", + _add_insert_commands(cols, 1, "%/% : use staircase", { CMD_GO_UPSTAIRS, CMD_GO_DOWNSTAIRS }); _add_command(cols, 1, CMD_INSPECT_FLOOR, "examine occupied tile and"); @@ -939,6 +939,10 @@ static void _add_formatted_keyhelp(column_composer &cols) _add_command(cols, 1, CMD_TOGGLE_TRAVEL_SPEED, "set your travel speed to your"); cols.add_formatted(1, " slowest ally\n", false); +#ifdef USE_TILE_LOCAL + _add_insert_commands(cols, 1, "%/% : zoom out/in", + { CMD_ZOOM_OUT, CMD_ZOOM_IN }); +#endif cols.add_formatted( 1, diff --git a/crawl-ref/source/macro.cc b/crawl-ref/source/macro.cc index c38d4d6a36a7..1fc59967a26f 100644 --- a/crawl-ref/source/macro.cc +++ b/crawl-ref/source/macro.cc @@ -1508,6 +1508,11 @@ string command_to_string(command_type cmd, bool tutorial) const int numpad = (key - 1000); result = make_stringf("Numpad %d", numpad); } +#ifdef USE_TILE_LOCAL + // SDL allows control modifiers for some extra punctuation + else if (key < 0 && key > SDLK_EXCLAIM - SDLK_a + 1) + result = make_stringf("Ctrl-%c", (char) (key + SDLK_a - 1)); +#endif else { const int ch = key + 'A' - 1; From 4a4e93562d0d45c326bc1370fc1160714ce445c9 Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 3 Jul 2019 21:55:50 -0400 Subject: [PATCH 468/864] Remove old 3rd party sdl build from travis --- .travis/apt.pl | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis/apt.pl b/.travis/apt.pl index 61a34772acca..d871e289d7c6 100644 --- a/.travis/apt.pl +++ b/.travis/apt.pl @@ -3,7 +3,6 @@ use warnings; run(qw(sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y)); -run(qw(sudo add-apt-repository ppa:zoogie/sdl2-snapshots -y)); retry(qw(sudo apt-get update -qq)); From c1e67f237a3487a0684910313acedafe5db37b8a Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 3 Jul 2019 22:13:21 -0400 Subject: [PATCH 469/864] More travis tweaking for local tiles --- .travis/deps.pl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis/deps.pl b/.travis/deps.pl index 1427ea2c15c9..ef191c1ac236 100644 --- a/.travis/deps.pl +++ b/.travis/deps.pl @@ -23,6 +23,8 @@ ); push @deps, qw( + libegl1-mesa-dev + libgles2-mesa-dev libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev From 3302cd442e81faa00c26680b9e7ccc0943d431e0 Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 3 Jul 2019 22:52:46 -0400 Subject: [PATCH 470/864] Try xenial (travis) This apparently could happen any day now anyways. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 35cbcf1355bd..023ce86161f9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: cpp +dist: xenial compiler: - clang - gcc From 7b9cff83cf45b7958a8811fb77d7bb228926e4e2 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 4 Jul 2019 08:54:58 -0400 Subject: [PATCH 471/864] More travis dependency updates, this time for BUILD_ALL --- .travis/deps.pl | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis/deps.pl b/.travis/deps.pl index ef191c1ac236..5ec8e5e27155 100644 --- a/.travis/deps.pl +++ b/.travis/deps.pl @@ -12,6 +12,7 @@ push @deps, qw( libegl1-mesa-dev + mesa-common-dev libasound2-dev libxss-dev ); From 7d615089e71685322f979a7e641ba68f1eca7f8a Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 4 Jul 2019 09:52:29 -0400 Subject: [PATCH 472/864] Another travis dep... --- .travis/deps.pl | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis/deps.pl b/.travis/deps.pl index 5ec8e5e27155..0f7ea7c8bc2a 100644 --- a/.travis/deps.pl +++ b/.travis/deps.pl @@ -13,6 +13,7 @@ push @deps, qw( libegl1-mesa-dev mesa-common-dev + libglu1-mesa-dev libasound2-dev libxss-dev ); From 47c397e050513d7c26548b9e75d3ba47c2995940 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 4 Jul 2019 11:26:09 -0400 Subject: [PATCH 473/864] Travis: Update mingw package names for xenial --- .travis/apt.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis/apt.pl b/.travis/apt.pl index d871e289d7c6..8c08458075c3 100644 --- a/.travis/apt.pl +++ b/.travis/apt.pl @@ -9,7 +9,7 @@ my @common_libs = qw(xorg-dev python3-yaml); if ($ENV{CROSSCOMPILE}) { - retry(qw(sudo apt-get install -qq mingw32 mingw32-binutils mingw32-runtime g++-mingw-w64-i686 gcc-mingw-w64-i686 nsis)); + retry(qw(sudo apt-get install -qq mingw-w64 binutils-mingw-w64 g++-mingw-w64-i686 gcc-mingw-w64-i686 nsis)); } if ($ENV{CXX} eq "clang++") { From 5b41c6f1980f3410e7bffc00aa6cf1fe1d2493f2 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Thu, 4 Jul 2019 14:37:30 -0500 Subject: [PATCH 474/864] Fix Death's Door HP at time of cast (Wise Wolf) Certain spells such as Death's Door, Tornado, and Dragon's Call do calculations of spell-power each turn for the purposes of spell effects. In the case of Death's Door, HP sanity checking code would immediately set hp to a value that didn't consider any spell-power bonuses that might be no longer active. This meant that HP would be lowered when using Sif's Divine Exegesis (due to loss of the Invocations bonus) or when swapping off e.g. a staff of death. This commit records the spell-power-derived HP at the time of casting and uses this for all subsequent turns of the current Death's Door duration. Changing the HP on subsequent turns is a result of the technical issue of implementing the sanity check for Death's Door and not part of the spell's intended design. This is a more general issue of how to handle spell-power for any spell with effects over multiple turns. Most duration-based spells, all summon spells, all conjurations that create a summon-like conjuration, and all cloud spells don't reconsider spell-power with every turn, which is inconsistent with how we do for Dragon's Call, Tornado, Borg's Vile Clutch, Searing Ray, and Olgreb's Toxic Radiance. If discouraging swaps is so important, we should not limit that restriction to a narrow subset of spells mainly for technical reasons. Clarity is the most important reason; most players probably don't expect that the former list of spells become worse over subsequent turns if they swap off enhancers. If we agree that encouraging swaps is bad, we should likely make *all* spells that have effects over time reconsider spell-power on each turn. --- crawl-ref/source/attribute-type.h | 1 + crawl-ref/source/player-reacts.cc | 11 +++++++++-- crawl-ref/source/spl-selfench.cc | 11 +++-------- crawl-ref/source/spl-selfench.h | 1 - 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/crawl-ref/source/attribute-type.h b/crawl-ref/source/attribute-type.h index ae23565aeef3..e27116166183 100644 --- a/crawl-ref/source/attribute-type.h +++ b/crawl-ref/source/attribute-type.h @@ -96,5 +96,6 @@ enum attribute_type ATTR_SERPENTS_LASH, // Remaining instant movement actions. ATTR_HEAVENLY_STORM, // Strength of Heavenly Storm slaying. ATTR_WALL_JUMP_READY, // Ready to perform a wall jump. + ATTR_DEATHS_DOOR_HP, // How much HP we should have under Death's Door NUM_ATTRIBUTES }; diff --git a/crawl-ref/source/player-reacts.cc b/crawl-ref/source/player-reacts.cc index a8a00e096e3d..a9b5b990e0a8 100644 --- a/crawl-ref/source/player-reacts.cc +++ b/crawl-ref/source/player-reacts.cc @@ -748,11 +748,18 @@ static void _decrement_durations() } } - if (you.duration[DUR_DEATHS_DOOR] && you.hp > allowed_deaths_door_hp()) + if (you.duration[DUR_DEATHS_DOOR] + && you.attribute[ATTR_DEATHS_DOOR_HP] > 0 + && you.hp > you.attribute[ATTR_DEATHS_DOOR_HP]) { - set_hp(allowed_deaths_door_hp()); + set_hp(you.attribute[ATTR_DEATHS_DOOR_HP]); you.redraw_hit_points = true; } + else if (!you.duration[DUR_DEATHS_DOOR] + && you.attribute[ATTR_DEATHS_DOOR_HP] > 0) + { + you.attribute[ATTR_DEATHS_DOOR_HP] = 0; + } if (_decrement_a_duration(DUR_CLOUD_TRAIL, delay, "Your trail of clouds dissipates.")) diff --git a/crawl-ref/source/spl-selfench.cc b/crawl-ref/source/spl-selfench.cc index 9d5bbdf80af7..33b5e8d0307c 100644 --- a/crawl-ref/source/spl-selfench.cc +++ b/crawl-ref/source/spl-selfench.cc @@ -31,13 +31,6 @@ #include "view.h" #include "viewchar.h" -int allowed_deaths_door_hp() -{ - int hp = calc_spell_power(SPELL_DEATHS_DOOR, true) / 10; - - return max(hp, 1); -} - spret cast_deaths_door(int pow, bool fail) { fail_check(); @@ -47,7 +40,9 @@ spret cast_deaths_door(int pow, bool fail) you.set_duration(DUR_DEATHS_DOOR, 10 + random2avg(13, 3) + (random2(pow) / 10)); - set_hp(allowed_deaths_door_hp()); + const int hp = max(calc_spell_power(SPELL_DEATHS_DOOR, true) / 10, 1); + you.attribute[ATTR_DEATHS_DOOR_HP] = hp; + set_hp(hp); if (you.duration[DUR_DEATHS_DOOR] > 25 * BASELINE_DELAY) you.duration[DUR_DEATHS_DOOR] = (23 + random2(5)) * BASELINE_DELAY; diff --git a/crawl-ref/source/spl-selfench.h b/crawl-ref/source/spl-selfench.h index 6e3ce67e7fa7..4a656d882ee6 100644 --- a/crawl-ref/source/spl-selfench.h +++ b/crawl-ref/source/spl-selfench.h @@ -4,7 +4,6 @@ #include "spl-cast.h" #include "transformation.h" -int allowed_deaths_door_hp(); spret cast_deaths_door(int pow, bool fail); void remove_ice_armour(); spret ice_armour(int pow, bool fail); From f6c7d2a2e8a82dbddbe79f3f7c9d38d0cafa7ccc Mon Sep 17 00:00:00 2001 From: Alex Jurkiewicz Date: Fri, 5 Jul 2019 23:44:36 +1000 Subject: [PATCH 475/864] Old Vampire cleanup (#1096) [committer's note: these braces are left over from b5eab8406da.] --- crawl-ref/source/command.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc index 2985ed0617cc..e4b63b56905f 100644 --- a/crawl-ref/source/command.cc +++ b/crawl-ref/source/command.cc @@ -965,10 +965,8 @@ static void _add_formatted_keyhelp(column_composer &cols) "Item Interaction:\n"); _add_command(cols, 1, CMD_INSCRIBE_ITEM, "inscribe item", 2); - { - _add_command(cols, 1, CMD_BUTCHER, "Chop up a corpse on floor", 2); - _add_command(cols, 1, CMD_EAT, "Eat food (tries floor first) \n", 2); - } + _add_command(cols, 1, CMD_BUTCHER, "Chop up a corpse on floor", 2); + _add_command(cols, 1, CMD_EAT, "Eat food (tries floor first) \n", 2); _add_command(cols, 1, CMD_FIRE, "Fire next appropriate item", 2); _add_command(cols, 1, CMD_THROW_ITEM_NO_QUIVER, "select an item and Fire it", 2); _add_command(cols, 1, CMD_QUIVER_ITEM, "select item slot to be Quivered", 2); From 132cf697da2f636ea0d0aff8a78f0d46e364b0da Mon Sep 17 00:00:00 2001 From: Stephen Date: Fri, 5 Jul 2019 09:48:27 -0400 Subject: [PATCH 476/864] Fedora build deps rename SDL* to SDL2* (#1076) The SDL build dependencies on Fedora are provided by the SDL2-devel and SDL2_image-devel packages. The current, non-"2", versions will cause the build to fail. [committer's note: copied PR message into commit] --- crawl-ref/INSTALL.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/INSTALL.txt b/crawl-ref/INSTALL.txt index 64748f06d8ad..f8de8d639266 100644 --- a/crawl-ref/INSTALL.txt +++ b/crawl-ref/INSTALL.txt @@ -134,7 +134,7 @@ On Fedora, and possibly other RPM-based systems, you can get the dependencies by running the following as root: dnf install gcc gcc-c++ make bison flex ncurses-devel compat-lua-devel \ - sqlite-devel zlib-devel pkgconfig python-yaml SDL-devel SDL_image-devel \ + sqlite-devel zlib-devel pkgconfig python-yaml SDL2-devel SDL2_image-devel \ libpng-devel freetype-devel dejavu-sans-fonts dejavu-sans-mono-fonts (the last six are needed only for tile builds). As with Debian, this package From e3eab0557c78c52b8ddff13b457b94d6ab3c3377 Mon Sep 17 00:00:00 2001 From: advil Date: Fri, 5 Jul 2019 10:29:53 -0400 Subject: [PATCH 477/864] Fix join_strings args (amalloy) --- crawl-ref/source/stringutil.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/stringutil.h b/crawl-ref/source/stringutil.h index 1ba46887e81d..a7f09b6cdfcf 100644 --- a/crawl-ref/source/stringutil.h +++ b/crawl-ref/source/stringutil.h @@ -219,7 +219,7 @@ string comma_separated_line(Z start, Z end, const string &andc = " and ", template string join_strings(Z start, Z end, const string &sep = " ") { - return comma_separated_line(start, end, " ", " "); + return comma_separated_line(start, end, sep, sep); } static inline bool starts_with(const string &s, const string &prefix) From 9a978d2894835e292e4741bab86879e7794d0ac7 Mon Sep 17 00:00:00 2001 From: Kyle Rawlins Date: Fri, 5 Jul 2019 12:22:18 -0400 Subject: [PATCH 478/864] Travis modernization (#1095) * Travis modernization * Enable ccache: travis can now save caches between builds (for every cell in the build matrix even!) so in the best case this massively speeds things up. Required some footwork for clang. * Move all apt stuff into .travis.yml, using a more complex build matrix and yaml references to cut down on repitition. This isn't quite as clean as the perl code it replaces, but doing this directly allows travis the option to do whatever caches / retries / etc it wants for apt. * Don't mess with compiler versions; xenial has modern enough compilers for c++11. * Switch the build matrix to use include rather than exclude, and prune it down so that clang isn't fully crossed with every env option. The choice of which builds to do with clang is a bit arbitrary and could be further tweaked if anyone has preferences. * Don't build non-needed contribs on BUILD_ALL for webtiles; this is covered by regular tiles builds and simplifies the dependencies. --- .travis.yml | 114 ++++++++++++++++++++++++++++++-------- .travis/apt.pl | 49 ---------------- .travis/deps.pl | 30 +--------- crawl-ref/source/Makefile | 14 +++-- 4 files changed, 104 insertions(+), 103 deletions(-) delete mode 100644 .travis/apt.pl diff --git a/.travis.yml b/.travis.yml index 023ce86161f9..2d75ddafd3c2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,37 +1,107 @@ language: cpp dist: xenial compiler: - - clang - gcc + - clang +cache: ccache sudo: required -before_install: - - sudo apt-get update --option Acquire::Retries=100 --option Acquire::http::Timeout="60" - - perl .travis/apt.pl - - if [ "$CXX" = "g++" ]; then export CXX="g++-4.7" CC="gcc-4.7"; fi +addons: + apt: + update: true + retries: true + packages: &basic_deps + - xorg-dev + - python3-yaml + - liblua5.1-0-dev # strictly speaking, only BUILD_ALL builds + - liblua5.1-0-dbg + - gdb + env: - - NOTHING=1 - - UNBRACE=1 - - CHECKWHITE=1 - - FULLDEBUG=1 - - TILES=1 - - TILES=1 FULLDEBUG=1 - - WEBTILES=1 - - WEBTILES=1 FULLDEBUG=1 - - USE_DGAMELAUNCH=1 EXTERNAL_DEFINES=-UTOURNEY - - USE_DGAMELAUNCH=1 WEBTILES=1 EXTERNAL_DEFINES=-UTOURNEY - - TILES=1 BUILD_ALL=1 - - WEBTILES=1 BUILD_ALL=1 - - CROSSCOMPILE=1 + global: + - CCACHE_CPP2=yes + matrix: # anything here is fully crossed with compilers, uses *basic_deps + - NOTHING=1 + - FULLDEBUG=1 + - WEBTILES=1 FULLDEBUG=1 + git: submodules: false + +# the rest of the build matrix, specifying each combo directly. Anything +# without explicit addons here will uses *basic_deps above, and any addons list +# overrides the global one. matrix: - exclude: + include: + # lint-type checks + - env: CHECKWHITE=1 + addons: {apt: {packages: [] }} + - env: UNBRACE=1 + addons: {apt: {packages: [] }} + # the rest of the actual builds. + - compiler: gcc + env: WEBTILES=1 + - compiler: gcc + env: WEBTILES=1 BUILD_ALL=1 + - compiler: gcc + env: TILES=1 + addons: + apt: + packages: + - *basic_deps + - &sdl_deps [libegl1-mesa-dev, libgles2-mesa-dev, libsdl2-dev, libsdl2-image-dev, libsdl2-mixer-dev] - compiler: clang - env: UNBRACE=1 + env: TILES=1 + addons: + apt: + packages: + - *basic_deps + - *sdl_deps + - compiler: gcc + env: TILES=1 FULLDEBUG=1 + addons: + apt: + packages: + - *basic_deps + - *sdl_deps - compiler: clang - env: CHECKWHITE=1 + env: TILES=1 FULLDEBUG=1 + addons: + apt: + packages: + - *basic_deps + - *sdl_deps + - compiler: gcc + env: TILES=1 BUILD_ALL=1 + addons: + apt: + packages: + - *basic_deps + - &sdl_buildall_deps [libegl1-mesa-dev, mesa-common-dev, libglu1-mesa-dev, libasound2-dev, libxss-dev] - compiler: clang - env: CROSSCOMPILE=1 + env: TILES=1 BUILD_ALL=1 + addons: + apt: + packages: + - *basic_deps + - *sdl_buildall_deps + - env: CROSSCOMPILE=1 + addons: + apt: + packages: + - mingw-w64 + - binutils-mingw-w64 + - g++-mingw-w64-i686 + - gcc-mingw-w64-i686 + - nsis + - *sdl_buildall_deps + - compiler: gcc + env: USE_DGAMELAUNCH=1 EXTERNAL_DEFINES=-UTOURNEY + - compiler: gcc + env: USE_DGAMELAUNCH=1 WEBTILES=1 EXTERNAL_DEFINES=-UTOURNEY + +before_install: + - if [ "$TRAVIS_OS_NAME" == "linux" ]; then if [ "$CC" == "clang" ]; then sudo ln -s `which ccache` /usr/lib/ccache/clang; fi; fi + - if [ "$TRAVIS_OS_NAME" == "linux" ]; then if [ "$CXX" == "clang++" ]; then sudo ln -s `which ccache` /usr/lib/ccache/clang++; fi; fi install: perl .travis/deps.pl script: perl .travis/build.pl notifications: diff --git a/.travis/apt.pl b/.travis/apt.pl deleted file mode 100644 index 8c08458075c3..000000000000 --- a/.travis/apt.pl +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env perl -use strict; -use warnings; - -run(qw(sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y)); - -retry(qw(sudo apt-get update -qq)); - -my @common_libs = qw(xorg-dev python3-yaml); - -if ($ENV{CROSSCOMPILE}) { - retry(qw(sudo apt-get install -qq mingw-w64 binutils-mingw-w64 g++-mingw-w64-i686 gcc-mingw-w64-i686 nsis)); -} - -if ($ENV{CXX} eq "clang++") { - retry(qw(sudo apt-get install -qq libstdc++6-4.7-dev), @common_libs); -} -elsif ($ENV{CXX} eq "g++") { - retry(qw(sudo apt-get install -qq g++-4.7), @common_libs); -} - -sub run { - my @cmd = @_; - - print "Running '@cmd'\n"; - my $ret = system(@cmd); - exit($ret) if $ret; - return; -} - -sub retry { - my (@cmd) = @_; - - my $tries = 5; - my $sleep = 5; - - my $ret; - while ($tries--) { - print "Running '@cmd'\n"; - $ret = system(@cmd); - return if $ret == 0; - print "'@cmd' failed ($ret), retrying in $sleep seconds...\n"; - sleep $sleep; - } - - print "Failed to run '@cmd' ($ret)\n"; - # 1 if there was a signal or system() failed, otherwise the exit status. - exit($ret & 127 ? 1 : $ret >> 8); -} diff --git a/.travis/deps.pl b/.travis/deps.pl index 0f7ea7c8bc2a..ff70825f3572 100644 --- a/.travis/deps.pl +++ b/.travis/deps.pl @@ -2,38 +2,12 @@ use strict; use warnings; -my @deps = qw( - gdb -); - +# this file used to do a bunch of apt stuff, but that's now all done in the +# travis build matrix. if ($ENV{BUILD_ALL} || $ENV{CROSSCOMPILE}) { retry(qw(git fetch --unshallow)); retry(qw(git submodule update --init --recursive)); - - push @deps, qw( - libegl1-mesa-dev - mesa-common-dev - libglu1-mesa-dev - libasound2-dev - libxss-dev - ); } -else { - push @deps, qw( - liblua5.1-0-dev - liblua5.1-0-dbg - ); - - push @deps, qw( - libegl1-mesa-dev - libgles2-mesa-dev - libsdl2-dev - libsdl2-image-dev - libsdl2-mixer-dev - ) if $ENV{TILES} || $ENV{WEBTILES}; -} - -retry(qw(sudo apt-get install), @deps); sub retry { my (@cmd) = @_; diff --git a/crawl-ref/source/Makefile b/crawl-ref/source/Makefile index 286c2b6542e2..03a4f7f5faf6 100644 --- a/crawl-ref/source/Makefile +++ b/crawl-ref/source/Makefile @@ -261,10 +261,17 @@ ifneq (,$(findstring CYGWIN,$(uname_S))) endif ifdef BUILD_ALL - BUILD_FREETYPE = YesPlease + ifdef TILES + BUILD_FREETYPE = YesPlease + BUILD_SDL2 = YesPlease + BUILD_SDL2IMAGE = YesPlease + BUILD_LIBPNG = YesPlease + endif + ifdef WEBTILES + BUILD_LIBPNG = YesPlease + endif + BUILD_PCRE = YesPlease - BUILD_SDL2 = YesPlease - BUILD_SDL2IMAGE = YesPlease ifdef SOUND ifndef WIN32 BUILD_SDL2MIXER = YesPlease @@ -272,7 +279,6 @@ ifdef BUILD_ALL endif BUILD_SQLITE = YesPlease BUILD_LUA = YesPlease - BUILD_LIBPNG = YesPlease BUILD_ZLIB = YesPlease endif From 7da6c1453bbf8c17e1e812d27e72f0f68dd32992 Mon Sep 17 00:00:00 2001 From: Alex Jurkiewicz Date: Mon, 8 Jul 2019 23:26:37 +1000 Subject: [PATCH 479/864] align braces --- crawl-ref/source/religion.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index 3f4b965983f7..4fbbd126cd86 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -3399,12 +3399,12 @@ static void _set_initial_god_piety() // monk bonus... you.props[RU_SACRIFICE_PROGRESS_KEY] = 0; // offer the first sacrifice faster than normal - { - int delay = 50; - if (crawl_state.game_is_sprint()) - delay /= SPRINT_MULTIPLIER; - you.props[RU_SACRIFICE_DELAY_KEY] = delay; - } + { + int delay = 50; + if (crawl_state.game_is_sprint()) + delay /= SPRINT_MULTIPLIER; + you.props[RU_SACRIFICE_DELAY_KEY] = delay; + } you.props[RU_SACRIFICE_PENALTY_KEY] = 0; break; From a9b13e7d511b94964d8cc86f7e56e2736a8d2d75 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 8 Jul 2019 14:15:44 -0400 Subject: [PATCH 480/864] Handle delay 0 values correctly in lm_trig.lua I think this code was infected by a classic lua gotcha: 0 does not evaluate to false, so the "or 1" here did not ever apply (since at least one of delay and delay_min/mix were guaranteed to not be nil). So if you set up a turn triggerer with delay 0, in `DgnTriggerer:turn` the countdown counter never got incremented and the loop there only exited because of the countdown_limit check. This means it ran 200 times, where the intended max appears to have been 10 for a single turn. (The 200 limit looks like it's something to do with apocalypserobin issues in the distant past, but I haven't figured out exactly under what conditions it was intended to apply.) Consequently, each fog machine in desolation ran 200 times per turn. This does a great job at getting lots of fog, but is really slow. From reading the logs it looks like no one realized this is how it was operating. I'll address desolation fog machines in a separate commit (since with this commit they will run only 10x a turn, and this turns out to mean putting out about half the fog.) Running 10x a turn is still heavy in the scale of things but in my testing it's negligible compared to the old 200x cap, so these changes may effectively fix the server cpu issues for salt even without further tweaking delay (which my next commit will also do). --- crawl-ref/source/dat/dlua/lm_fog.lua | 1 + crawl-ref/source/dat/dlua/lm_trig.lua | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/dat/dlua/lm_fog.lua b/crawl-ref/source/dat/dlua/lm_fog.lua index cccc0f435f31..4a912b2c145b 100644 --- a/crawl-ref/source/dat/dlua/lm_fog.lua +++ b/crawl-ref/source/dat/dlua/lm_fog.lua @@ -114,6 +114,7 @@ function FogMachine:new(pars) m.buildup_turns = 0 local tick_pars = {} + -- this allows params <= 0, but that value here is min'd to 1 in lm_trig.lua tick_pars.delay_min = pars.delay_min or pars.delay or 1 tick_pars.delay_max = pars.delay_max or pars.delay tick_pars.type = "turn" diff --git a/crawl-ref/source/dat/dlua/lm_trig.lua b/crawl-ref/source/dat/dlua/lm_trig.lua index 7d688c8cb0a9..0d4ff4f6acdb 100644 --- a/crawl-ref/source/dat/dlua/lm_trig.lua +++ b/crawl-ref/source/dat/dlua/lm_trig.lua @@ -240,7 +240,6 @@ function Triggerable:event(marker, ev) error("Triggerable type " .. class .. " at (" ..x .. ", " .. y .. ") " .. "has no triggerers for dgn_event " .. e_type ) end - for _, trig_idx in ipairs(trig_list) do self.triggerers[trig_idx]:event(self, marker, ev) @@ -627,8 +626,9 @@ function DgnTriggerer:new(pars) tr:setup() if tr.type == "turn" and (tr.delay or (tr.delay_min and tr.delay_max)) then - tr.delay_min = tr.delay_min or tr.delay or 1 - tr.delay_max = tr.delay_max or tr.delay + -- lua gotcha reminder: 0 does not evaluate to false. + tr.delay_min = math.max(tr.delay_min or tr.delay, 1) + tr.delay_max = math.max(tr.delay_max or tr.delay, tr.delay_min) tr.buildup_turns = 0 tr.countdown = 0 From e98fbd9498798444d945ccf744a6694a55de205c Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 8 Jul 2019 14:43:11 -0400 Subject: [PATCH 481/864] Adjust desolation fog machines It turns out that the desolation fog machines achieved their effect by running 200 times per turn (by being set with delay 0). After my previous commit causing delay to be max'd at 1, the amount of fog produced by these machines with the same settings is approximately halved. This commit tweaks the fog machines to try to get something more like the originally intended effect. They may need further tweaking from anyone who has a better sense how desolation fog should "feel". It's possible that the portal fog should be toned down more, as well. Needless to say, with a delay of 5 (2x per turn) these machines are a lot easier on the cpu than they used to be. This probably makes something like #948 not needed. --- crawl-ref/source/dat/des/portals/desolation.des | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/crawl-ref/source/dat/des/portals/desolation.des b/crawl-ref/source/dat/des/portals/desolation.des index 660b644654b7..633e6e8b0789 100644 --- a/crawl-ref/source/dat/des/portals/desolation.des +++ b/crawl-ref/source/dat/des/portals/desolation.des @@ -138,7 +138,8 @@ KMONS: O = saltling band SUBST: . = ;. FTILE: ;OP = FLOOR_SALT MARKER: P = lua:fog_machine { cloud_type = "salt", walk_dist=3, \ - pow_max=6, delay=0, size=5, spread_rate=3, } + pow_min=6, pow_max=20, \ + delay=5, size=5, spread_rate=5, } MAP ....... .;;;;;. @@ -177,8 +178,9 @@ TAGS: transparent no_monster_gen SUBST: C = c;, - = ; .:50 KMONS: O = saltling band FTILE: ;Os = FLOOR_SALT -MARKER: O = lua:fog_machine { cloud_type = "salt", walk_dist = 4, size = 3, \ - pow_max = 6, delay = 10 } +MARKER: O = lua:fog_machine { cloud_type = "salt", walk_dist=3, \ + pow_min=6, pow_max=20, \ + delay=5, size=5, spread_rate=5, } MAP ........... .-;-;--;--. @@ -965,7 +967,8 @@ ORIENT: float NSUBST: - = 2:c / 2:x / 2=c. / 2=x. / 4:% / 1:G. / 2:1 / 2:2 / 1:S / *:. SUBST: C = c.., c = ccccx MARKER: S = lua:fog_machine { cloud_type = "salt", walk_dist=3, \ - pow_max=6, delay=0, size=5, spread_rate=3, } + pow_min=6, pow_max=20, \ + delay=5, size=5, spread_rate=5, } : desolation_ruins_setup(_G) MAP C.........C. @@ -1011,7 +1014,8 @@ TAGS: desolation_ruin transparent ORIENT: float NSUBST: c = 4:- / *=cccx-, - = 7:% / 2:x / 2:2 / 2:1 / *:., . = S / . MARKER: S = lua:fog_machine { cloud_type = "salt", walk_dist=3, \ - pow_max=6, delay=0, size=5, spread_rate=3, } + pow_min=6, pow_max=20, \ + delay=5, size=5, spread_rate=5, } : desolation_ruins_setup(_G) MAP ............ @@ -1309,7 +1313,8 @@ MONS: saltling band : set_border_fill_type('endless_salt') : set_feature_name("granite_statue", "ruined idol") MARKER: S = lua:fog_machine { cloud_type = "salt", walk_dist=3, \ - pow_max=6, delay=0, size=5, spread_rate=3, } + pow_min=6, pow_max=20, \ + delay=5, size=15, spread_rate=10, } MAP PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP From 98ea13e501196c615aa865efede93e8dc3c9f7bd Mon Sep 17 00:00:00 2001 From: Alex Jurkiewicz Date: Fri, 5 Jul 2019 19:15:06 +1000 Subject: [PATCH 482/864] Simplify logic --- crawl-ref/source/status.cc | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/crawl-ref/source/status.cc b/crawl-ref/source/status.cc index d7e28b9dfbc4..5a508860d64c 100644 --- a/crawl-ref/source/status.cc +++ b/crawl-ref/source/status.cc @@ -849,11 +849,7 @@ static void _describe_regen(status_info& inf) } else if (vampmod) { - if (you.disease) - inf.short_text = "recuperating"; - else - inf.short_text = "regenerating"; - + inf.short_text = you.disease ? "recuperating" : "regenerating"; inf.short_text += " quickly"; } } From 962a3eeff77e5360451b2d88a07dc8c9343fb290 Mon Sep 17 00:00:00 2001 From: Nikolai Lavsky <3328424+nlavsky@users.noreply.github.com> Date: Fri, 28 Jun 2019 13:40:11 +0300 Subject: [PATCH 483/864] Remove dump_book_spells option Obsolete since the introduction of the spell library. --- crawl-ref/docs/options_guide.txt | 7 +------ crawl-ref/source/chardump.cc | 6 +----- crawl-ref/source/describe.cc | 3 +-- crawl-ref/source/initfile.cc | 1 - crawl-ref/source/options.h | 1 - 5 files changed, 3 insertions(+), 15 deletions(-) diff --git a/crawl-ref/docs/options_guide.txt b/crawl-ref/docs/options_guide.txt index 4c2c4ab585e7..3e0d4cb2987e 100644 --- a/crawl-ref/docs/options_guide.txt +++ b/crawl-ref/docs/options_guide.txt @@ -122,7 +122,7 @@ The contents of this text are: 4-b Items and Kills. kill_map, dump_kill_places, dump_kill_breakdowns, dump_item_origins, dump_item_origin_price, dump_message_count, - dump_order, dump_book_spells + dump_order 4-c Notes. user_note_prefix, note_items, note_monsters, note_hp_percent, note_skill_levels, note_all_skill_levels, note_skill_max, @@ -2282,11 +2282,6 @@ dump_order += monlist,kills,notes,skill_gains,action_counts in trunk builds of Crawl (not releases or pre-release betas), appearing between "notes" and "skill_gains". -dump_book_spells = true - By default all randart spellbooks in inventory will have all their - spells listed in the dump. If this option is set to true, spells will - also be dumped for non-randart spellbooks. - 4-c Notes. -------------- diff --git a/crawl-ref/source/chardump.cc b/crawl-ref/source/chardump.cc index 9aace82f92bb..7ea2d93c8d2f 100644 --- a/crawl-ref/source/chardump.cc +++ b/crawl-ref/source/chardump.cc @@ -809,12 +809,8 @@ static void _sdump_inventory(dump_params &par) if (origin_describable(item) && _dump_item_origin(item)) text += "\n" " (" + origin_desc(item) + ")"; - if (is_dumpable_artefact(item) - || Options.dump_book_spells - && item.base_type == OBJ_BOOKS) - { + if (is_dumpable_artefact(item)) text += chardump_desc(item); - } else text += "\n"; } diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index 55bb89541493..197c05e49f16 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -1982,8 +1982,7 @@ string get_item_description(const item_def &item, bool verbose, break; case OBJ_BOOKS: - if (!verbose - && (Options.dump_book_spells || is_random_artefact(item))) + if (!verbose && is_random_artefact(item)) { desc += describe_item_spells(item); if (desc.empty()) diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index 23b309173346..411560a5d0a1 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -216,7 +216,6 @@ const vector game_options::build_options_list() new BoolGameOption(SIMPLE_NAME(wall_jump_prompt), false), new BoolGameOption(SIMPLE_NAME(wall_jump_move), false), new BoolGameOption(SIMPLE_NAME(darken_beyond_range), true), - new BoolGameOption(SIMPLE_NAME(dump_book_spells), true), new BoolGameOption(SIMPLE_NAME(arena_dump_msgs), false), new BoolGameOption(SIMPLE_NAME(arena_dump_msgs_all), false), new BoolGameOption(SIMPLE_NAME(arena_list_eq), false), diff --git a/crawl-ref/source/options.h b/crawl-ref/source/options.h index e85f750309c0..ca4cd9c9dfc4 100644 --- a/crawl-ref/source/options.h +++ b/crawl-ref/source/options.h @@ -401,7 +401,6 @@ struct game_options int dump_item_origins; // Show where items came from? int dump_item_origin_price; - bool dump_book_spells; // Order of sections in the character dump. vector dump_order; From e77e6fb25671b620b189569595a5cd502b6f876b Mon Sep 17 00:00:00 2001 From: marksg07 Date: Mon, 8 Jul 2019 18:35:48 -0400 Subject: [PATCH 484/864] Add clua function to set waypoint (#1098) --- crawl-ref/source/l-travel.cc | 35 +++++++++++++++++++++++++++++------ crawl-ref/source/travel.cc | 9 +++++++-- crawl-ref/source/travel.h | 1 + 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/crawl-ref/source/l-travel.cc b/crawl-ref/source/l-travel.cc index fe348e935de0..b3216fd4ec7f 100644 --- a/crawl-ref/source/l-travel.cc +++ b/crawl-ref/source/l-travel.cc @@ -13,7 +13,7 @@ #include "travel.h" /*** Set an exclusion. - * Uses player centered coordinates + * Uses player-centered coordinates * @tparam int x * @tparam int y * @tparam[opt=LOS_RADIUS] int r @@ -26,7 +26,7 @@ LUAFN(l_set_exclude) s.y = luaL_safe_checkint(ls, 2); const coord_def p = player2grid(s); if (!in_bounds(p)) - return 0; + return luaL_error(ls, "Coordinates out of bounds: (%d, %d)", s.x, s.y); // XXX: dedup w/_get_full_exclusion_radius()? int r = LOS_RADIUS; if (lua_gettop(ls) > 2) @@ -36,7 +36,7 @@ LUAFN(l_set_exclude) } /*** Remove an exclusion. - * Uses player centered coordinates + * Uses player-centered coordinates * @tparam int x * @tparam int y * @function del_eclude @@ -48,7 +48,7 @@ LUAFN(l_del_exclude) s.y = luaL_safe_checkint(ls, 2); const coord_def p = player2grid(s); if (!in_bounds(p)) - return 0; + return luaL_error(ls, "Coordinates out of bounds: (%d, %d)", s.x, s.y); del_exclude(p); return 0; } @@ -101,8 +101,8 @@ LUAFN(l_find_deepest_explored) LUAFN(l_waypoint_delta) { int waynum = luaL_safe_checkint(ls, 1); - if (waynum < 0 || waynum > 9) - return 0; + if (waynum < 0 || waynum >= TRAVEL_WAYPOINT_COUNT) + return luaL_error(ls, "Bad waypoint number: %d", waynum); const level_pos waypoint = travel_cache.get_waypoint(waynum); if (waypoint.id != level_id::current()) return 0; @@ -112,6 +112,28 @@ LUAFN(l_waypoint_delta) return 2; } +/*** Set a numbered waypoint. + * Uses player-centered coordinates + * @tparam int waynum + * @tparam int x + * @tparam int y + * @function set_waypoint + */ +LUAFN(l_set_waypoint) +{ + int waynum = luaL_safe_checkint(ls, 1); + if (waynum < 0 || waynum >= TRAVEL_WAYPOINT_COUNT) + return luaL_error(ls, "Bad waypoint number: %d", waynum); + coord_def s; + s.x = luaL_safe_checkint(ls, 2); + s.y = luaL_safe_checkint(ls, 3); + const coord_def p = player2grid(s); + if (!in_bounds(p)) + return luaL_error(ls, "Coordinates out of bounds: (%d, %d)", s.x, s.y); + travel_cache.set_waypoint(waynum, p.x, p.y); + return 0; +} + static const struct luaL_reg travel_lib[] = { { "set_exclude", l_set_exclude }, @@ -120,6 +142,7 @@ static const struct luaL_reg travel_lib[] = { "feature_solid", l_feature_is_solid }, { "find_deepest_explored", l_find_deepest_explored }, { "waypoint_delta", l_waypoint_delta }, + { "set_waypoint", l_set_waypoint }, { nullptr, nullptr } }; diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc index 70f6d388c52e..135b171d3a4d 100644 --- a/crawl-ref/source/travel.cc +++ b/crawl-ref/source/travel.cc @@ -3962,8 +3962,13 @@ void TravelCache::add_waypoint(int x, int y) return; } - int waynum = keyin - '0'; + set_waypoint(keyin - '0', x, y); +} + +void TravelCache::set_waypoint(int waynum, int x, int y) +{ + ASSERT_RANGE(waynum, 0, TRAVEL_WAYPOINT_COUNT); coord_def pos(x,y); if (x == -1 || y == -1) pos = you.pos(); @@ -3984,7 +3989,7 @@ void TravelCache::add_waypoint(int x, int y) if (overwrite) { if (lid == old_lid) // same level - mprf("Waypoint %d re-assigned to your current position.", waynum); + mprf("Waypoint %d re-assigned to %s.", waynum, new_dest.c_str()); else { mprf("Waypoint %d re-assigned from %s to %s.", diff --git a/crawl-ref/source/travel.h b/crawl-ref/source/travel.h index bff9e8cfa942..8e3ee8ae281f 100644 --- a/crawl-ref/source/travel.h +++ b/crawl-ref/source/travel.h @@ -449,6 +449,7 @@ class TravelCache void set_level_excludes(); void add_waypoint(int x = -1, int y = -1); + void set_waypoint(int waynum, int x, int y); void delete_waypoint(); uint8_t is_waypoint(const level_pos &lp) const; void list_waypoints() const; From ed8816983f89672710483837fefa4bbe2bcb44da Mon Sep 17 00:00:00 2001 From: Alan Malloy Date: Mon, 8 Jul 2019 15:43:25 -0700 Subject: [PATCH 485/864] Add gmarks to CREDITS and mailmap after e77e6fb --- .mailmap | 1 + crawl-ref/CREDITS.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/.mailmap b/.mailmap index 59b94c8e7b77..d72e418ac059 100644 --- a/.mailmap +++ b/.mailmap @@ -176,3 +176,4 @@ Yermak <33148474+Mindcrafter@users.noreply.github.com> EMTedronai Alcon Patashu +gmarks diff --git a/crawl-ref/CREDITS.txt b/crawl-ref/CREDITS.txt index fdd257948c65..18e3a98298ef 100644 --- a/crawl-ref/CREDITS.txt +++ b/crawl-ref/CREDITS.txt @@ -217,6 +217,7 @@ Paul Maloney Pablo Mansanet Wille Mäntylä + Gabriel Marks Jean Martel James 'Eronarn' Meickle Jacob Meigs From 57318f2ed029b552f95f19592fde3e1be0da0968 Mon Sep 17 00:00:00 2001 From: Alex Jurkiewicz Date: Tue, 9 Jul 2019 14:46:12 +1000 Subject: [PATCH 486/864] Unify two loot lines (#1101) Based on absolutely nothing, I think the average stack size of mutation potions is a touch over 1, adjust the new weight accordingly. --- crawl-ref/source/dat/dlua/ziggurat.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crawl-ref/source/dat/dlua/ziggurat.lua b/crawl-ref/source/dat/dlua/ziggurat.lua index 17f84d98dea9..41f28fc7a14a 100644 --- a/crawl-ref/source/dat/dlua/ziggurat.lua +++ b/crawl-ref/source/dat/dlua/ziggurat.lua @@ -587,8 +587,7 @@ local function ziggurat_create_loot_at(c) dgn.good_scrolls) local super_loot = dgn.item_spec("| no_pickup w:7000 /" .. "potion of experience no_pickup w:190 q:1 /" .. - "potion of mutation no_pickup w:190 /" .. - "potion of mutation no_pickup w:40 q:1 /" .. + "potion of mutation no_pickup w:220 /" .. "ration no_pickup w:80 /" .. "potion of heal wounds q:5 no_pickup / " .. "potion of haste q:5 no_pickup / " .. From 33f6f7b652e423c6c8530d5fa1179093cf9fbe18 Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 10 Jul 2019 18:08:33 -0400 Subject: [PATCH 487/864] Arena error improvements * keep arena from causing a full game exit if you mistype a monster. (In fact, just restart arena, at least if it was run from the main menu.) * Print multiple rounds messaging into a popup, it wasn't showing at all in interactive arena before. There's still a bunch of improvements that could be made to arena messaging, it doesn't say anything for 1-round fights, and is generally kind of lacking in local tiles (because of the lack of monster list). --- crawl-ref/source/arena.cc | 206 +++++++++++++++++++++++++++++++----- crawl-ref/source/arena.h | 4 +- crawl-ref/source/startup.cc | 64 +---------- 3 files changed, 183 insertions(+), 91 deletions(-) diff --git a/crawl-ref/source/arena.cc b/crawl-ref/source/arena.cc index 96fcfd1fdddd..81a508cb0f8c 100644 --- a/crawl-ref/source/arena.cc +++ b/crawl-ref/source/arena.cc @@ -15,6 +15,7 @@ #include "dungeon.h" #include "end.h" #include "food.h" +#include "initfile.h" #include "item-name.h" #include "item-status-flag-type.h" #include "items.h" @@ -22,12 +23,14 @@ #include "los.h" #include "macro.h" #include "maps.h" +#include "menu.h" #include "message.h" #include "misc.h" #include "mgen-data.h" #include "mon-death.h" #include "mon-pick.h" #include "mon-tentacle.h" +#include "newgame-def.h" #include "ng-init.h" #include "spl-miscast.h" #include "state.h" @@ -48,16 +51,62 @@ using namespace ui; extern void world_reacts(); +static void _results_popup(string msg, bool error=false) +{ + // TODO: shared code here with end.cc + linebreak_string(msg, 79); + +#ifdef USE_TILE_WEB + tiles_crt_popup show_as_popup; + tiles.set_ui_state(UI_CRT); +#endif + + if (error) + { + msg = string("Arena error:\n\n") + + replace_all(msg, "<", "<<"); + msg += ""; + } + else + msg = string("Arena results:\n\n") + msg; + + msg += "\n\nHit any key to continue, " + "ctrl-p for the full log."; + + auto prompt_ui = make_shared( + formatted_string::parse_string(msg)); + bool done = false; + prompt_ui->on(Widget::slots.event, [&](wm_event ev) { + if (ev.type == WME_KEYDOWN) + { + if (ev.key.keysym.sym == CONTROL('P')) + replay_messages(); + else + done = true; + } + return done; + }); + + mouse_control mc(MOUSE_MODE_MORE); + auto popup = make_shared(prompt_ui); + ui::run_layout(move(popup), done); +} + namespace arena { + static bool skipped_arena_ui = true; // whether this is an interactive session static void write_error(const string &error); struct arena_error : public runtime_error { - explicit arena_error(const string &msg) : runtime_error(msg) {} - explicit arena_error(const char *msg) : runtime_error(msg) {} + explicit arena_error(const string &msg, bool _fatal=true) + : runtime_error(msg), fatal(_fatal) {} + explicit arena_error(const char *msg, bool _fatal=true) + : runtime_error(msg), fatal(_fatal) {} + bool fatal; }; #define arena_error_f(...) arena_error(make_stringf(__VA_ARGS__)) +#define arena_error_nonfatal_f(...) arena_error(make_stringf(__VA_ARGS__), false) // A faction is just a big list of monsters. Monsters will be dropped // around the appropriate marker. @@ -310,7 +359,7 @@ namespace arena { const string err = fact.members.add_mons(monster, false); if (!err.empty()) - throw arena_error(err); + throw arena_error(err, false); } } @@ -334,7 +383,10 @@ namespace arena summon_throttle = strip_number_tag(spec, "summon_throttle:"); if (real_summons && respawn) - throw arena_error("Can't set real_summons and respawn at same time."); + { + throw arena_error("Can't set real_summons and respawn at same time.", + false); + } if (summon_throttle <= 0) summon_throttle = INT_MAX; @@ -368,7 +420,7 @@ namespace arena } catch (const bad_level_id &err) { - throw arena_error_f("Bad place '%s': %s", + throw arena_error_nonfatal_f("Bad place '%s': %s", arena_place.c_str(), err.what()); } @@ -385,7 +437,8 @@ namespace arena if (factions.size() != 2) { - throw arena_error_f("Expected arena monster spec \"xxx v yyy\", " + throw arena_error_nonfatal_f( + "Expected arena monster spec \"xxx v yyy\", " "but got \"%s\"", spec.c_str()); } @@ -396,7 +449,7 @@ namespace arena } catch (const arena_error &err) { - throw arena_error_f("Bad monster spec \"%s\": %s", + throw arena_error_nonfatal_f("Bad monster spec \"%s\": %s", spec.c_str(), err.what()); } @@ -917,15 +970,7 @@ namespace arena teams = arena_teams; // Set various options from the arena spec's tags - try - { - parse_monster_spec(); - } - catch (const arena_error &error) - { - write_error(error.what()); - game_ended_with_error(error.what()); - } + parse_monster_spec(); // may throw an arena_error if (file != nullptr) end(0, false, "Results file already open"); @@ -1023,6 +1068,7 @@ namespace arena { write_error(error.what()); game_ended_with_error(error.what()); + continue; } do_fight(); @@ -1031,14 +1077,20 @@ namespace arena } while (!contest_cancelled && trials_done < total_trials); + ui_delay(Options.view_delay * 5); + if (total_trials > 0) { - mprf("Final score: %s (%d); %s (%d) [%d ties]", + string outcome = make_stringf( + "Final score: %s (%d); %s (%d) [%d ties]", faction_a.desc.c_str(), team_a_wins, faction_b.desc.c_str(), trials_done - team_a_wins - ties, ties); + mpr(outcome); + if (!skipped_arena_ui) + _results_popup(outcome); } - ui_delay(Options.view_delay * 5); + ui::pop_layout(); write_results(); @@ -1411,19 +1463,119 @@ static void _init_arena() initialise_item_descriptions(); } -NORETURN void run_arena(const string& teams) +static void _choose_arena_teams(newgame_def& choice, + const string &default_arena_teams) { - _init_arena(); +#ifdef USE_TILE_WEB + tiles_crt_popup show_as_popup; +#endif - ASSERT(!crawl_state.arena_suspended); + if (!choice.arena_teams.empty()) + return; + arena::skipped_arena_ui = false; + clear_message_store(); + + char buf[80]; + resumable_line_reader reader(buf, sizeof(buf)); + bool done = false; + bool cancel = false; + auto prompt_ui = make_shared(); + + prompt_ui->on(Widget::slots.event, [&](wm_event ev) { + if (ev.type != WME_KEYDOWN) + return false; + int key = ev.key.keysym.sym; + if (key == CONTROL('P')) + { + replay_messages(); + return false; + } + key = reader.putkey(key); + if (key == -1) + return true; + cancel = !!key; + return done = true; + }); + + auto popup = make_shared(prompt_ui); + ui::push_layout(move(popup)); + while (!done && !crawl_state.seen_hups) + { + string hlbuf = formatted_string(buf).to_colour_string(); + if (hlbuf.find(" v ") != string::npos) + hlbuf = "" + replace_all(hlbuf, " v ", " v ") + ""; + + formatted_string prompt; + prompt.cprintf("Enter your choice of teams:\n\n "); + prompt += formatted_string::parse_string(hlbuf); + + prompt.cprintf("\n\n"); + if (!default_arena_teams.empty()) + prompt.cprintf("Enter - %s\n", default_arena_teams.c_str()); + prompt.cprintf("\n"); + prompt.cprintf("Examples:\n"); + prompt.cprintf(" Sigmund v Jessica\n"); + prompt.cprintf(" 99 orc v the Royal Jelly\n"); + prompt.cprintf(" 20-headed hydra v 10 kobold ; scimitar ego:flaming"); + prompt_ui->set_text(prompt); + + ui::pump_events(); + } + ui::pop_layout(); + + if (cancel || crawl_state.seen_hups) + { + game_ended(crawl_state.bypassed_startup_menu + ? game_exit::death : game_exit::abort); + } + choice.arena_teams = buf; + if (choice.arena_teams.empty()) + choice.arena_teams = default_arena_teams; +} + +NORETURN void run_arena(const newgame_def& choice, const string &default_arena_teams) +{ + ASSERT(crawl_state.game_is_arena()); + + newgame_def arena_choice = choice; + string last_teams = default_arena_teams; + + do + { + try + { + _choose_arena_teams(arena_choice, last_teams); + write_newgame_options_file(arena_choice); + _init_arena(); + + ASSERT(!crawl_state.arena_suspended); #ifdef WIZARD - // The player has wizard powers for the duration of the arena. - unwind_bool wiz(you.wizard, true); + // The player has wizard powers for the duration of the arena. + unwind_bool wiz(you.wizard, true); #endif - arena::global_setup(teams); - arena::simulate(); - arena::global_shutdown(); - game_ended(game_exit::death); // there is only death in the arena + arena::global_setup(arena_choice.arena_teams); + arena::simulate(); + arena::global_shutdown(); + game_ended(game_exit::death); // there is only death in the arena + } + catch (const arena::arena_error &error) + { + if (error.fatal || arena::skipped_arena_ui) + { + arena::write_error(error.what()); + game_ended_with_error(error.what()); + } + else + { + arena::write_error(error.what()); + _results_popup(error.what(), true); + last_teams = arena_choice.arena_teams; + arena_choice.arena_teams = ""; + // fallthrough + } + } + } + while (true); } diff --git a/crawl-ref/source/arena.h b/crawl-ref/source/arena.h index 95afedcddd47..33404a027a40 100644 --- a/crawl-ref/source/arena.h +++ b/crawl-ref/source/arena.h @@ -13,7 +13,9 @@ struct mgen_data; struct coord_def; -NORETURN void run_arena(const string& teams); +struct newgame_def; + +NORETURN void run_arena(const newgame_def& choice, const string &default_arena_teams); monster_type arena_pick_random_monster(const level_id &place); diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index cdba10ad06c4..73e795cbf75a 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -1188,66 +1188,6 @@ static void _show_startup_menu(newgame_def& ng_choice, } #endif -static void _choose_arena_teams(newgame_def& choice, - const newgame_def& defaults) -{ -#ifdef USE_TILE_WEB - tiles_crt_popup show_as_popup; -#endif - - if (!choice.arena_teams.empty()) - return; - clear_message_store(); - - char buf[80]; - resumable_line_reader reader(buf, sizeof(buf)); - bool done = false, cancel; - auto prompt_ui = make_shared(); - - prompt_ui->on(Widget::slots.event, [&](wm_event ev) { - if (ev.type != WME_KEYDOWN) - return false; - int key = ev.key.keysym.sym; - key = reader.putkey(key); - if (key == -1) - return true; - cancel = !!key; - return done = true; - }); - - auto popup = make_shared(prompt_ui); - ui::push_layout(move(popup)); - while (!done && !crawl_state.seen_hups) - { - string hlbuf = formatted_string(buf).to_colour_string(); - if (hlbuf.find(" v ") != string::npos) - hlbuf = "" + replace_all(hlbuf, " v ", " v ") + ""; - - formatted_string prompt; - prompt.cprintf("Enter your choice of teams:\n\n "); - prompt += formatted_string::parse_string(hlbuf); - - prompt.cprintf("\n\n"); - if (!defaults.arena_teams.empty()) - prompt.cprintf("Enter - %s\n", defaults.arena_teams.c_str()); - prompt.cprintf("\n"); - prompt.cprintf("Examples:\n"); - prompt.cprintf(" Sigmund v Jessica\n"); - prompt.cprintf(" 99 orc v the Royal Jelly\n"); - prompt.cprintf(" 20-headed hydra v 10 kobold ; scimitar ego:flaming"); - prompt_ui->set_text(prompt); - - ui::pump_events(); - } - ui::pop_layout(); - - if (cancel || crawl_state.seen_hups) - game_ended(game_exit::abort); - choice.arena_teams = buf; - if (choice.arena_teams.empty()) - choice.arena_teams = defaults.arena_teams; -} - #ifndef DGAMELAUNCH static bool _exit_type_allows_menu_bypass(game_exit exit) { @@ -1334,10 +1274,8 @@ bool startup_step() // choose_game and setup_game if (choice.type == GAME_TYPE_ARENA) { - _choose_arena_teams(choice, defaults); - write_newgame_options_file(choice); crawl_state.last_type = GAME_TYPE_ARENA; - run_arena(choice.arena_teams); // this is NORETURN + run_arena(choice, defaults.arena_teams); // this is NORETURN } bool newchar = false; From 1c7b743a30f0ffe3337a8d576059ebbbcae2e84a Mon Sep 17 00:00:00 2001 From: marksg07 Date: Wed, 10 Jul 2019 20:33:25 -0400 Subject: [PATCH 488/864] Allow running clua from map viewing mode (#1103) This is made possible by adding user function recognition to key inputs while viewing map. A clua function can be run by adding a levelmap key map from a given key to ===functionName. When the clua function finishes, we will still be in map mode unless the function took us out of it. Additionally add clua functions for asking about map mode: crawl.in_map_mode, crawl.cursor_pos, and crawl.cursor_level cursor_pos and cursor_level return nil outside of map mode. cursor_pos also returns nil if the level of the cursor is not the same as the level of the player, because giving the relative position to the player in that case would leak information about the level map. --- crawl-ref/source/l-crawl.cc | 46 ++++++++++++++++++++++++++++++++++++- crawl-ref/source/state.cc | 1 + crawl-ref/source/state.h | 15 ++++++++++++ crawl-ref/source/viewmap.cc | 14 +++++++++-- 4 files changed, 73 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/l-crawl.cc b/crawl-ref/source/l-crawl.cc index 0326b951fe39..d1a4973cfd02 100644 --- a/crawl-ref/source/l-crawl.cc +++ b/crawl-ref/source/l-crawl.cc @@ -912,6 +912,47 @@ static int crawl_article_a(lua_State *ls) return 1; } +/*** If we are in map mode and the cursor is on the same + * level as the player, get player-relative position of cursor. + * @treturn int, int + * @function cursor_pos + */ +LUAFN(crawl_cursor_pos) +{ + map_mode_state &info = crawl_state.map_mode_info; + if (!crawl_state.in_map_mode + || info.cursor_lpos.id != info.original_lid) + { + return 0; + } + + lua_pushinteger(ls, info.cursor_lpos.pos.x - you.position.x); + lua_pushinteger(ls, info.cursor_lpos.pos.y - you.position.y); + + return 2; +} + +/*** If we are in map mode, get description of cursor level + * in the form :. + * @treturn string + * @function cursor_level + */ +LUAFN(crawl_cursor_level) +{ + if (!crawl_state.in_map_mode) + return 0; + + lua_pushstring(ls, crawl_state.map_mode_info.cursor_lpos.id.describe().c_str()); + + return 1; +} + +/*** Are we in map mode? + * @treturn boolean + * @function in_map_mode + */ +LUARET1(crawl_in_map_mode, boolean, crawl_state.in_map_mode) + /*** Has the game started? * @treturn boolean * @function game_started @@ -1424,7 +1465,10 @@ static const struct luaL_reg crawl_clib[] = { "call_dlua", crawl_call_dlua }, #endif { "version", crawl_version }, - { "weapon_check", crawl_weapon_check}, + { "weapon_check", crawl_weapon_check }, + { "in_map_mode", crawl_in_map_mode }, + { "cursor_pos", crawl_cursor_pos }, + { "cursor_level", crawl_cursor_level }, { nullptr, nullptr }, }; diff --git a/crawl-ref/source/state.cc b/crawl-ref/source/state.cc index 414db6e0f35c..48d88471f5cf 100644 --- a/crawl-ref/source/state.cc +++ b/crawl-ref/source/state.cc @@ -61,6 +61,7 @@ game_state::game_state() darken_range(nullptr), unsaved_macros(false), disables(), minor_version(-1), save_rcs_version(), nonempty_buffer_flush_errors(false), + in_map_mode(false), map_mode_info({}), mon_act(nullptr) { reset_cmd_repeat(); diff --git a/crawl-ref/source/state.h b/crawl-ref/source/state.h index 59b51961c7ba..cdac8194d6f4 100644 --- a/crawl-ref/source/state.h +++ b/crawl-ref/source/state.h @@ -30,6 +30,15 @@ struct god_act_state int depth; }; +struct map_mode_state +{ + // Absolute position + level_id of the cursor + level_pos cursor_lpos; + + // Stored level_id of the player character + level_id original_lid; +}; + // Track various aspects of Crawl game state. struct game_state { @@ -139,6 +148,12 @@ struct game_state // Should flushing a nonempty key buffer error or crash? Used for tests. bool nonempty_buffer_flush_errors; + // Whether we are in "map mode", i.e. currently in eXamine + bool in_map_mode; + + // Info pertaining to map mode, if we are in map mode. If we aren't, value is undefined. + map_mode_state map_mode_info; + protected: void reset_cmd_repeat(); void reset_cmd_again(); diff --git a/crawl-ref/source/viewmap.cc b/crawl-ref/source/viewmap.cc index 31f379a18784..465ba4e0a2fd 100644 --- a/crawl-ref/source/viewmap.cc +++ b/crawl-ref/source/viewmap.cc @@ -38,6 +38,7 @@ #include "view.h" #include "viewchar.h" #include "viewgeom.h" +#include "delay.h" #ifdef USE_TILE #endif @@ -618,6 +619,7 @@ static void _forget_map(bool wizard_forget = false) bool show_map(level_pos &lpos, bool travel_mode, bool allow_esc, bool allow_offlevel) { + unwind_bool _in_map_mode(crawl_state.in_map_mode, true); bool chose = false; #ifdef USE_TILE_LOCAL bool first_run = true; @@ -636,6 +638,7 @@ bool show_map(level_pos &lpos, { levelview_excursion le(travel_mode); level_id original(level_id::current()); + unwind_var _original_lid(crawl_state.map_mode_info.original_lid, original); if (!lpos.id.is_valid() || !allow_offlevel) lpos.id = level_id::current(); @@ -807,17 +810,24 @@ bool show_map(level_pos &lpos, #ifndef USE_TILE_LOCAL cursorxy(curs_x, curs_y + top - 1); #endif + crawl_state.map_mode_info.cursor_lpos = lpos; redraw_map = true; c_input_reset(true); #ifdef USE_TILE_LOCAL const int key = getchm(KMC_LEVELMAP); - command_type cmd = key_to_command(key, KMC_LEVELMAP); #else const int key = unmangle_direction_keys(getchm(KMC_LEVELMAP), KMC_LEVELMAP); - command_type cmd = key_to_command(key, KMC_LEVELMAP); #endif + if (is_userfunction(key)) + { + run_macro(get_userfunction(key).c_str()); + continue; + } + + command_type cmd = key_to_command(key, KMC_LEVELMAP); + if (cmd < CMD_MIN_OVERMAP || cmd > CMD_MAX_OVERMAP) cmd = CMD_NO_CMD; From 534e725bec97e867708e9946495397aa42c0ba3f Mon Sep 17 00:00:00 2001 From: marksg07 Date: Thu, 11 Jul 2019 13:44:49 -0400 Subject: [PATCH 489/864] Check for known map bounds in the clua travel library (#1102) The set_exclude, del_exclude, and set_waypoint functions all previously ignored the bounds normally set on your cursor in map mode, i.e. you can only move your cursors to points within the bounding box of the screen. This being ignored meant both that clua could do something that couldn't be done manually, and that your absolute coordinates could be leaked by careful use of the above functions. This fix will prevent both from happening. --- crawl-ref/source/l-travel.cc | 14 +++++++++++--- crawl-ref/source/map-knowledge.cc | 28 ++++++++++++++++++++++++++++ crawl-ref/source/map-knowledge.h | 8 ++++++++ crawl-ref/source/viewmap.cc | 29 +++++------------------------ 4 files changed, 52 insertions(+), 27 deletions(-) diff --git a/crawl-ref/source/l-travel.cc b/crawl-ref/source/l-travel.cc index b3216fd4ec7f..885484546e80 100644 --- a/crawl-ref/source/l-travel.cc +++ b/crawl-ref/source/l-travel.cc @@ -11,6 +11,14 @@ #include "player.h" #include "terrain.h" #include "travel.h" +#include "map-knowledge.h" + +static bool _in_map_bounds(const coord_def& p) +{ + std::pair b = known_map_bounds(); + return p.x >= b.first.x && p.y >= b.first.y + && p.x <= b.second.x && p.y <= b.second.y; +} /*** Set an exclusion. * Uses player-centered coordinates @@ -25,7 +33,7 @@ LUAFN(l_set_exclude) s.x = luaL_safe_checkint(ls, 1); s.y = luaL_safe_checkint(ls, 2); const coord_def p = player2grid(s); - if (!in_bounds(p)) + if (!_in_map_bounds(p)) return luaL_error(ls, "Coordinates out of bounds: (%d, %d)", s.x, s.y); // XXX: dedup w/_get_full_exclusion_radius()? int r = LOS_RADIUS; @@ -47,7 +55,7 @@ LUAFN(l_del_exclude) s.x = luaL_safe_checkint(ls, 1); s.y = luaL_safe_checkint(ls, 2); const coord_def p = player2grid(s); - if (!in_bounds(p)) + if (!_in_map_bounds(p)) return luaL_error(ls, "Coordinates out of bounds: (%d, %d)", s.x, s.y); del_exclude(p); return 0; @@ -128,7 +136,7 @@ LUAFN(l_set_waypoint) s.x = luaL_safe_checkint(ls, 2); s.y = luaL_safe_checkint(ls, 3); const coord_def p = player2grid(s); - if (!in_bounds(p)) + if (!_in_map_bounds(p)) return luaL_error(ls, "Coordinates out of bounds: (%d, %d)", s.x, s.y); travel_cache.set_waypoint(waynum, p.x, p.y); return 0; diff --git a/crawl-ref/source/map-knowledge.cc b/crawl-ref/source/map-knowledge.cc index 1681c3495a38..5aa2bd43addd 100644 --- a/crawl-ref/source/map-knowledge.cc +++ b/crawl-ref/source/map-knowledge.cc @@ -326,3 +326,31 @@ bool map_cell::update_cloud_state() // TODO: track decay & vanish appropriately (based on some worst case?) return false; } + +std::pair known_map_bounds() { + int min_x = GXM, max_x = 0, min_y = 0, max_y = 0; + bool found_y = false; + + for (int j = 0; j < GYM; j++) + for (int i = 0; i < GXM; i++) + { + if (env.map_knowledge[i][j].known()) + { + if (!found_y) + { + found_y = true; + min_y = j; + } + + max_y = j; + + if (i < min_x) + min_x = i; + + if (i > max_x) + max_x = i; + } + } + + return std::make_pair(coord_def(min_x, min_y), coord_def(max_x, max_y)); +} diff --git a/crawl-ref/source/map-knowledge.h b/crawl-ref/source/map-knowledge.h index 345571370bb0..9675035520a9 100644 --- a/crawl-ref/source/map-knowledge.h +++ b/crawl-ref/source/map-knowledge.h @@ -3,6 +3,7 @@ #include "coord.h" #include "enum.h" #include "feature.h" +#include "externs.h" void set_terrain_mapped(const coord_def c); void set_terrain_seen(const coord_def c); @@ -41,3 +42,10 @@ map_feature get_cell_map_feature(const map_cell& cell); bool is_explore_horizon(const coord_def& c); void reautomap_level(); + +/** + * @brief Get the bounding box of the known map. + * + * @return pair of {topleft coord, bottomright coord} of bbox. + */ +std::pair known_map_bounds(); diff --git a/crawl-ref/source/viewmap.cc b/crawl-ref/source/viewmap.cc index 465ba4e0a2fd..0d50db3dc8fb 100644 --- a/crawl-ref/source/viewmap.cc +++ b/crawl-ref/source/viewmap.cc @@ -644,7 +644,6 @@ bool show_map(level_pos &lpos, lpos.id = level_id::current(); cursor_control ccon(!Options.use_fake_cursor); - int i, j; int move_x = 0, move_y = 0, scroll_y = 0; @@ -705,29 +704,11 @@ bool show_map(level_pos &lpos, feats.init(); - min_x = GXM, max_x = 0, min_y = 0, max_y = 0; - bool found_y = false; - - for (j = 0; j < GYM; j++) - for (i = 0; i < GXM; i++) - { - if (env.map_knowledge[i][j].known()) - { - if (!found_y) - { - found_y = true; - min_y = j; - } - - max_y = j; - - if (i < min_x) - min_x = i; - - if (i > max_x) - max_x = i; - } - } + std::pair bounds = known_map_bounds(); + min_x = bounds.first.x; + min_y = bounds.first.y; + max_x = bounds.second.x; + max_y = bounds.second.y; map_lines = max_y - min_y + 1; From 29c01f8b84739b1796e8a648fb8119d06bb96984 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 11 Jul 2019 15:36:00 -0400 Subject: [PATCH 490/864] Fix arena logging (10060) For some time, arena logging has been writing the entire message history on each turn. This commit redoes arena logging using the message_tee paradigm instead of trying to read from the log history directly; doing it this way better handles continuous updates and the possibility of the message log filling up. --- crawl-ref/source/arena.cc | 148 +++++++++++++++++++----------------- crawl-ref/source/message.cc | 12 +-- crawl-ref/source/message.h | 8 +- 3 files changed, 88 insertions(+), 80 deletions(-) diff --git a/crawl-ref/source/arena.cc b/crawl-ref/source/arena.cc index 81a508cb0f8c..132a6413bb6a 100644 --- a/crawl-ref/source/arena.cc +++ b/crawl-ref/source/arena.cc @@ -49,6 +49,71 @@ using namespace ui; #define ARENA_VERBOSE +// wrap a message tee around a file ptr, which can be null. +// for a more general purpose application you'd want this to handle opening +// and closing the file too, but that would require some restructuring of the +// arena. +class arena_message_tee : message_tee +{ +public: + arena_message_tee(FILE **_file) : message_tee(), file(_file) { } + + ~arena_message_tee() + { + if (*file) + fflush(*file); + } + + void append(const string &s, msg_channel_type ch = MSGCH_PLAIN) + { + if (Options.arena_dump_msgs && *file) + { + if (!s.size()) + return; + string prefix; + switch (ch) + { + case MSGCH_DIAGNOSTICS: + prefix = "DIAG: "; + if (Options.arena_dump_msgs_all) + break; + return; + + // Ignore messages generated while the user examines + // the arnea. + case MSGCH_PROMPT: + case MSGCH_MONSTER_TARGET: + case MSGCH_FLOOR_ITEMS: + case MSGCH_EXAMINE: + case MSGCH_EXAMINE_FILTER: + return; + + // If a monster-damage message ends with '!' it's a + // death message, otherwise it's an examination message + // and should be skipped. + case MSGCH_MONSTER_DAMAGE: + if (s[s.size() - 1] != '!') + return; + break; + + case MSGCH_ERROR: prefix = "ERROR: "; break; + case MSGCH_WARN: prefix = "WARN: "; break; + case MSGCH_SOUND: prefix = "SOUND: "; break; + + case MSGCH_TALK_VISUAL: + case MSGCH_TALK: prefix = "TALK: "; break; + default: break; + } + formatted_string fs = formatted_string::parse_string(s); + fprintf(*file, "%s%s", prefix.c_str(), fs.tostring().c_str()); + fflush(*file); + } + } + +private: + FILE **file; +}; + extern void world_reacts(); static void _results_popup(string msg, bool error=false) @@ -192,6 +257,7 @@ namespace arena static FILE *file = nullptr; static level_id place(BRANCH_DEPTHS, 1); + static string arena_log; static void adjust_spells(monster* mons, bool no_summons, bool no_animate) { @@ -640,59 +706,6 @@ namespace arena return faction_a.active_members > 0 && faction_b.active_members > 0; } - static void dump_messages() - { - if (!Options.arena_dump_msgs || file == nullptr) - return; - - vector messages; - vector channels; - get_recent_messages(messages, channels); - - for (unsigned int i = 0; i < messages.size(); i++) - { - string msg = messages[i]; - int chan = channels[i]; - - string prefix; - switch (chan) - { - case MSGCH_DIAGNOSTICS: - prefix = "DIAG: "; - if (Options.arena_dump_msgs_all) - break; - continue; - - // Ignore messages generated while the user examines - // the arnea. - case MSGCH_PROMPT: - case MSGCH_MONSTER_TARGET: - case MSGCH_FLOOR_ITEMS: - case MSGCH_EXAMINE: - case MSGCH_EXAMINE_FILTER: - continue; - - // If a monster-damage message ends with '!' it's a - // death message, otherwise it's an examination message - // and should be skipped. - case MSGCH_MONSTER_DAMAGE: - if (msg[msg.length() - 1] != '!') - continue; - break; - - case MSGCH_ERROR: prefix = "ERROR: "; break; - case MSGCH_WARN: prefix = "WARN: "; break; - case MSGCH_SOUND: prefix = "SOUND: "; break; - - case MSGCH_TALK_VISUAL: - case MSGCH_TALK: prefix = "TALK: "; break; - } - msg = prefix + msg; - - fprintf(file, "%s\n", msg.c_str()); - } - } - // Try to prevent random luck from letting one spawner fill up the // arena with so many monsters that the other spawner can never get // back on even footing. @@ -842,6 +855,7 @@ namespace arena { viewwindow(); clear_messages(true); + { cursor_control coff(false); while (fight_is_on() && !contest_cancelled) @@ -865,7 +879,6 @@ namespace arena balance_spawners(); ui_delay(Options.view_delay); clear_messages(); - dump_messages(); ASSERT(you.pet_target == MHITNOT); } viewwindow(); @@ -874,8 +887,8 @@ namespace arena if (contest_cancelled) { mpr("Canceled contest at user request"); + ui_delay(Options.view_delay); clear_messages(); - dump_messages(); return; } @@ -950,7 +963,6 @@ namespace arena mprf(msg.c_str(), faction_a.won ? faction_a.desc.c_str() : faction_b.desc.c_str()); - dump_messages(); } static void global_setup(const string& arena_teams) @@ -964,6 +976,7 @@ namespace arena memset(banned_glyphs, 0, sizeof(banned_glyphs)); arena_type = ""; place = level_id(BRANCH_DEPTHS, 1); + arena_log = ""; // [ds] Turning off view_lock crashes arena. Options.view_lock_x = Options.view_lock_y = true; @@ -972,19 +985,6 @@ namespace arena // Set various options from the arena spec's tags parse_monster_spec(); // may throw an arena_error - if (file != nullptr) - end(0, false, "Results file already open"); - file = fopen("arena.result", "w"); - - if (file != nullptr) - { - string spec = find_monster_spec(); - fprintf(file, "%s\n", spec.c_str()); - - if (Options.arena_dump_msgs || Options.arena_list_eq) - fprintf(file, "========================================\n"); - } - expand_mlist(5); for (monster_type i = MONS_0; i < NUM_MONSTERS; ++i) @@ -1003,6 +1003,7 @@ namespace arena fclose(file); file = nullptr; + arena_log = ""; } static void write_results() @@ -1525,6 +1526,7 @@ static void _choose_arena_teams(newgame_def& choice, if (cancel || crawl_state.seen_hups) { + arena::global_shutdown(); game_ended(crawl_state.bypassed_startup_menu ? game_exit::death : game_exit::abort); } @@ -1539,6 +1541,12 @@ NORETURN void run_arena(const newgame_def& choice, const string &default_arena_t newgame_def arena_choice = choice; string last_teams = default_arena_teams; + if (arena::file != nullptr) + end(0, false, "Results file already open"); + // would be more elegant if arena_message_tee handled file open/close, but + // that would need a bunch of refactoring of how the file is handled here. + arena::file = fopen("arena.result", "w"); + arena_message_tee log(&arena::file); do { @@ -1569,7 +1577,7 @@ NORETURN void run_arena(const newgame_def& choice, const string &default_arena_t } else { - arena::write_error(error.what()); + mprf(MSGCH_ERROR, "%s", error.what()); _results_popup(error.what(), true); last_teams = arena_choice.arena_teams; arena_choice.arena_teams = ""; diff --git a/crawl-ref/source/message.cc b/crawl-ref/source/message.cc index 3ea82f8503bc..66a6f426fd93 100644 --- a/crawl-ref/source/message.cc +++ b/crawl-ref/source/message.cc @@ -966,15 +966,15 @@ message_tee::~message_tee() current_message_tees.erase(this); } -void message_tee::append(const string &s) +void message_tee::append(const string &s, msg_channel_type ch) { // could use a more c++y external interface -- but that just complicates things store << s; } -void message_tee::append_line(const string &s) +void message_tee::append_line(const string &s, msg_channel_type ch) { - store << s << "\n"; + append(s + "\n", ch); } string message_tee::get_store() const @@ -982,10 +982,10 @@ string message_tee::get_store() const return store.str(); } -static void _append_to_tees(const string &s) +static void _append_to_tees(const string &s, msg_channel_type ch) { for (auto tee : current_message_tees) - tee->append(s); + tee->append(s, ch); } no_messages::no_messages() : msuppressed(suppress_messages) @@ -1460,7 +1460,7 @@ static void _mpr(string text, msg_channel_type channel, int param, bool nojoin, text = "<" + col + ">" + text + ""; // XXX if (current_message_tees.size()) - _append_to_tees(text + "\n"); + _append_to_tees(text + "\n", channel); formatted_string fs = formatted_string::parse_string(text); diff --git a/crawl-ref/source/message.h b/crawl-ref/source/message.h index c61a3cc4038b..67de88e4b146 100644 --- a/crawl-ref/source/message.h +++ b/crawl-ref/source/message.h @@ -101,10 +101,10 @@ class message_tee public: message_tee(); message_tee(string &_target); - ~message_tee(); - void append(const string &s); - void append_line(const string &s); - string get_store() const; + virtual ~message_tee(); + virtual void append(const string &s, msg_channel_type ch = MSGCH_PLAIN); + virtual void append_line(const string &s, msg_channel_type ch = MSGCH_PLAIN); + virtual string get_store() const; private: stringstream store; From df4b510d7aceeb9728d1fd54326f3cda840eeec2 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 11 Jul 2019 16:57:06 -0400 Subject: [PATCH 491/864] Trigger fineffs after blurrily reading a scroll (12016) Otherwise, they need to wait until the next turn. Two cases that I have tested: torment vs TRJ, and torment vs shock serpents. This is not a very general fix, and in principle might need to be generalized to any delay that queues a fineff. --- crawl-ref/source/delay.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc index 3948da770f22..a6f683c4276e 100644 --- a/crawl-ref/source/delay.cc +++ b/crawl-ref/source/delay.cc @@ -28,6 +28,7 @@ #include "env.h" #include "exclude.h" #include "exercise.h" +#include "fineff.h" #include "food.h" #include "fprop.h" #include "god-abil.h" @@ -896,7 +897,17 @@ void BlurryScrollDelay::finish() { // Make sure the scroll still exists, the player isn't confused, etc if (_can_read_scroll(scroll)) + { read_scroll(scroll); + // we are now probably out of sync with regular world_reacts timing, so + // trigger any fineffs that might have been caused by reading this + // scroll, e.g. torment vs. TRJ. Otherwise they'd have to wait until + // the next world_reacts. + // TODO: is there a more general condition that this can be triggered + // under? it might impact other obscure cases, e.g. passwalling with + // spiny. + fire_final_effects(); + } } static void _finish_butcher_delay(item_def& corpse) From 7e4ddcd485eeba31288a0a50f9787c09acda0ea7 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 11 Jul 2019 17:25:51 -0400 Subject: [PATCH 492/864] Fix a pronoun (12011) Ideally this should reflect player choice, but given that we aren't using the `it` form at all any more, this is at least more consistent. --- crawl-ref/source/dat/descript/monsters.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/dat/descript/monsters.txt b/crawl-ref/source/dat/descript/monsters.txt index 134d78c92dff..3e4e76e24332 100644 --- a/crawl-ref/source/dat/descript/monsters.txt +++ b/crawl-ref/source/dat/descript/monsters.txt @@ -527,7 +527,7 @@ ancestor A humanoid construct of insubstantial memory, floating through the air. Though perhaps somewhat changed in shape and bearing few discernable features, still -it seems somehow to resemble a warrior from the distantly remembered past. +they seem somehow to resemble a warrior from the distantly remembered past. %%%% ancient champion From 17ce2c7205cc5e2fc3ed4b9e3a3ce52a56e554fc Mon Sep 17 00:00:00 2001 From: Seve Monahan Date: Fri, 12 Jul 2019 00:16:51 -0400 Subject: [PATCH 493/864] Correct alphabetization in Makefile.obj --- crawl-ref/source/Makefile.obj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/Makefile.obj b/crawl-ref/source/Makefile.obj index 7c4010e21953..9944d3f3b9d8 100644 --- a/crawl-ref/source/Makefile.obj +++ b/crawl-ref/source/Makefile.obj @@ -196,8 +196,8 @@ random.o \ random-var.o \ ranged-attack.o \ ray.o \ -rot.o \ religion.o \ +rot.o \ scroller.o \ shopping.o \ shout.o \ From d30f2f123c34f1af0c2e8b86c7921c1bf11caaaa Mon Sep 17 00:00:00 2001 From: olowin Date: Fri, 12 Jul 2019 11:48:05 -0400 Subject: [PATCH 494/864] Remove blood from Gozag shop description Now that vampires are hungerless. --- crawl-ref/source/dat/descript/ability.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crawl-ref/source/dat/descript/ability.txt b/crawl-ref/source/dat/descript/ability.txt index 2b0409bbd020..f99694c7eab3 100644 --- a/crawl-ref/source/dat/descript/ability.txt +++ b/crawl-ref/source/dat/descript/ability.txt @@ -599,7 +599,7 @@ Call Merchant ability Sends funds to a merchant to help them set up shop at your location. The cost of funding a shop increases with the number of shops funded.{{ - if you.race() == "Mummy" then + if you.race() == "Mummy" or you.race() == "Vampire" then return end @@ -607,8 +607,6 @@ funding a shop increases with the number of shops funded.{{ if you.race() == "Ghoul" then desc = desc .. "carrion" - elseif you.race() == "Vampire" then - desc = desc .. "blood" else desc = desc .. "food" end From be733cd003b066fcee63b25d5f1f37efec17096c Mon Sep 17 00:00:00 2001 From: marksg07 Date: Fri, 12 Jul 2019 16:43:31 -0400 Subject: [PATCH 495/864] Revert "Allow running clua from map viewing mode (#1103)" (#1107) This reverts commit 1c7b743a30f0ffe3337a8d576059ebbbcae2e84a. --- crawl-ref/source/l-crawl.cc | 46 +------------------------------------ crawl-ref/source/state.cc | 1 - crawl-ref/source/state.h | 15 ------------ crawl-ref/source/viewmap.cc | 14 ++--------- 4 files changed, 3 insertions(+), 73 deletions(-) diff --git a/crawl-ref/source/l-crawl.cc b/crawl-ref/source/l-crawl.cc index d1a4973cfd02..0326b951fe39 100644 --- a/crawl-ref/source/l-crawl.cc +++ b/crawl-ref/source/l-crawl.cc @@ -912,47 +912,6 @@ static int crawl_article_a(lua_State *ls) return 1; } -/*** If we are in map mode and the cursor is on the same - * level as the player, get player-relative position of cursor. - * @treturn int, int - * @function cursor_pos - */ -LUAFN(crawl_cursor_pos) -{ - map_mode_state &info = crawl_state.map_mode_info; - if (!crawl_state.in_map_mode - || info.cursor_lpos.id != info.original_lid) - { - return 0; - } - - lua_pushinteger(ls, info.cursor_lpos.pos.x - you.position.x); - lua_pushinteger(ls, info.cursor_lpos.pos.y - you.position.y); - - return 2; -} - -/*** If we are in map mode, get description of cursor level - * in the form :. - * @treturn string - * @function cursor_level - */ -LUAFN(crawl_cursor_level) -{ - if (!crawl_state.in_map_mode) - return 0; - - lua_pushstring(ls, crawl_state.map_mode_info.cursor_lpos.id.describe().c_str()); - - return 1; -} - -/*** Are we in map mode? - * @treturn boolean - * @function in_map_mode - */ -LUARET1(crawl_in_map_mode, boolean, crawl_state.in_map_mode) - /*** Has the game started? * @treturn boolean * @function game_started @@ -1465,10 +1424,7 @@ static const struct luaL_reg crawl_clib[] = { "call_dlua", crawl_call_dlua }, #endif { "version", crawl_version }, - { "weapon_check", crawl_weapon_check }, - { "in_map_mode", crawl_in_map_mode }, - { "cursor_pos", crawl_cursor_pos }, - { "cursor_level", crawl_cursor_level }, + { "weapon_check", crawl_weapon_check}, { nullptr, nullptr }, }; diff --git a/crawl-ref/source/state.cc b/crawl-ref/source/state.cc index 48d88471f5cf..414db6e0f35c 100644 --- a/crawl-ref/source/state.cc +++ b/crawl-ref/source/state.cc @@ -61,7 +61,6 @@ game_state::game_state() darken_range(nullptr), unsaved_macros(false), disables(), minor_version(-1), save_rcs_version(), nonempty_buffer_flush_errors(false), - in_map_mode(false), map_mode_info({}), mon_act(nullptr) { reset_cmd_repeat(); diff --git a/crawl-ref/source/state.h b/crawl-ref/source/state.h index cdac8194d6f4..59b51961c7ba 100644 --- a/crawl-ref/source/state.h +++ b/crawl-ref/source/state.h @@ -30,15 +30,6 @@ struct god_act_state int depth; }; -struct map_mode_state -{ - // Absolute position + level_id of the cursor - level_pos cursor_lpos; - - // Stored level_id of the player character - level_id original_lid; -}; - // Track various aspects of Crawl game state. struct game_state { @@ -148,12 +139,6 @@ struct game_state // Should flushing a nonempty key buffer error or crash? Used for tests. bool nonempty_buffer_flush_errors; - // Whether we are in "map mode", i.e. currently in eXamine - bool in_map_mode; - - // Info pertaining to map mode, if we are in map mode. If we aren't, value is undefined. - map_mode_state map_mode_info; - protected: void reset_cmd_repeat(); void reset_cmd_again(); diff --git a/crawl-ref/source/viewmap.cc b/crawl-ref/source/viewmap.cc index 0d50db3dc8fb..326b0fd0daf0 100644 --- a/crawl-ref/source/viewmap.cc +++ b/crawl-ref/source/viewmap.cc @@ -38,7 +38,6 @@ #include "view.h" #include "viewchar.h" #include "viewgeom.h" -#include "delay.h" #ifdef USE_TILE #endif @@ -619,7 +618,6 @@ static void _forget_map(bool wizard_forget = false) bool show_map(level_pos &lpos, bool travel_mode, bool allow_esc, bool allow_offlevel) { - unwind_bool _in_map_mode(crawl_state.in_map_mode, true); bool chose = false; #ifdef USE_TILE_LOCAL bool first_run = true; @@ -638,7 +636,6 @@ bool show_map(level_pos &lpos, { levelview_excursion le(travel_mode); level_id original(level_id::current()); - unwind_var _original_lid(crawl_state.map_mode_info.original_lid, original); if (!lpos.id.is_valid() || !allow_offlevel) lpos.id = level_id::current(); @@ -791,24 +788,17 @@ bool show_map(level_pos &lpos, #ifndef USE_TILE_LOCAL cursorxy(curs_x, curs_y + top - 1); #endif - crawl_state.map_mode_info.cursor_lpos = lpos; redraw_map = true; c_input_reset(true); #ifdef USE_TILE_LOCAL const int key = getchm(KMC_LEVELMAP); + command_type cmd = key_to_command(key, KMC_LEVELMAP); #else const int key = unmangle_direction_keys(getchm(KMC_LEVELMAP), KMC_LEVELMAP); -#endif - if (is_userfunction(key)) - { - run_macro(get_userfunction(key).c_str()); - continue; - } - command_type cmd = key_to_command(key, KMC_LEVELMAP); - +#endif if (cmd < CMD_MIN_OVERMAP || cmd > CMD_MAX_OVERMAP) cmd = CMD_NO_CMD; From 5a03d68f59656b7a87f1a9b57388edfddc017b24 Mon Sep 17 00:00:00 2001 From: Seve Monahan Date: Fri, 12 Jul 2019 19:02:33 -0400 Subject: [PATCH 496/864] Ensure train targets turn off once reached with !experience (#11993) This bug was caused by commit ece4408. I have tested the bug fixed by ece4408 (#11943) to ensure this commit did not cause a regression. --- crawl-ref/source/player.cc | 5 +++++ crawl-ref/source/skills.cc | 2 -- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 0d7d7a38c1b9..f4f715ec3d58 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -2882,6 +2882,11 @@ void level_change(bool skip_attribute_increase) check_skill_level_change(sk); } + // It's possible we passed a training target due to + // skills being rescaled to new aptitudes. Thus, we must + // check the training targets. + check_training_targets(); + // Tell the player about their new species for (auto &mut : fake_mutations(you.species, false)) mprf(MSGCH_INTRINSIC_GAIN, "%s", mut.c_str()); diff --git a/crawl-ref/source/skills.cc b/crawl-ref/source/skills.cc index 2fa7408064b2..d04e461312fc 100644 --- a/crawl-ref/source/skills.cc +++ b/crawl-ref/source/skills.cc @@ -399,8 +399,6 @@ void check_skill_level_change(skill_type sk, bool do_level_up) else you.skills[sk] = new_level; } - - check_training_targets(); } // Fill a queue in random order with the values of the array. From e00f04a389b562e677337e03b3aa2fca3e2c8913 Mon Sep 17 00:00:00 2001 From: Seve Monahan Date: Fri, 12 Jul 2019 17:53:16 -0400 Subject: [PATCH 497/864] Extract new helper function "_player_is_gnoll()" in skills.cc --- crawl-ref/source/skills.cc | 53 +++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/crawl-ref/source/skills.cc b/crawl-ref/source/skills.cc index d04e461312fc..9f3d290f728d 100644 --- a/crawl-ref/source/skills.cc +++ b/crawl-ref/source/skills.cc @@ -508,10 +508,15 @@ static void _check_start_train() you.start_train.clear(); } +static bool _player_is_gnoll() +{ + return you.species == SP_GNOLL; +} + static void _check_stop_train() { // Gnolls can't stop training skills. - if (you.species == SP_GNOLL) + if (_player_is_gnoll()) return; _check_inventory_skills(); @@ -555,7 +560,7 @@ void update_can_train() bool training_restricted(skill_type sk) { - if (you.species == SP_GNOLL) + if (_player_is_gnoll()) return false; switch (sk) @@ -602,15 +607,13 @@ void init_can_train() void init_train() { - const bool is_gnoll = you.species == SP_GNOLL; - for (int i = 0; i < NUM_SKILLS; ++i) { if (you.can_train[i] && you.skill_points[i]) you.train[i] = you.train_alt[i] = TRAINING_ENABLED; else { - const bool gnoll_enable = is_gnoll && + const bool gnoll_enable = _player_is_gnoll() && !is_removed_skill((skill_type) i); // Skills are on by default in auto mode and off in manual. you.train[i] = (training_status) (gnoll_enable @@ -747,7 +750,7 @@ bool check_selected_skills() mpr("You need to enable at least one skill for training."); // Training will be fixed up on load if this ASSERT triggers. - ASSERT(you.species != SP_GNOLL); + ASSERT(!_player_is_gnoll()); more(); reset_training(); skill_menu(); @@ -763,10 +766,9 @@ bool check_selected_skills() */ void reset_training() { - const bool is_gnoll = you.species == SP_GNOLL; // Disable this here since we don't want any autotraining related skilling // changes for Gnolls. - if (is_gnoll) + if (_player_is_gnoll()) you.auto_training = false; // We clear the values in the training array. In auto mode they are set @@ -776,7 +778,7 @@ void reset_training() { // skill_trained doesn't work for gnolls, but all existent skills // will be set as enabled here. - if (!is_gnoll && (you.auto_training || !skill_trained(i))) + if (!_player_is_gnoll() && (you.auto_training || !skill_trained(i))) you.training[i] = 0; else you.training[i] = you.train[i]; @@ -827,7 +829,7 @@ void reset_training() } _scale_array(you.training, 100, you.auto_training); - if (is_gnoll) + if (_player_is_gnoll()) { // we use the full set of skills to calculate gnoll percentages, // but they don't actually get to train sacrificed skills. @@ -888,7 +890,7 @@ int _gnoll_total_skill_cost(); void train_skills(bool simu) { int cost, exp; - if (you.species == SP_GNOLL) + if (_player_is_gnoll()) { do { @@ -960,7 +962,7 @@ static void _train_skills(int exp, const int cost, const bool simu) if (you.training[i] > 0) { sk_exp[i] = you.training[i] * exp / 100; - if (sk_exp[i] < cost && you.species != SP_GNOLL) + if (sk_exp[i] < cost && !_player_is_gnoll()) { // One skill has a too low training to be trained at all. // We skip the first phase and go directly to the random @@ -976,7 +978,7 @@ static void _train_skills(int exp, const int cost, const bool simu) { // We randomize the order, to avoid a slight bias to first skills. // Being trained first can make a difference if skill cost increases. - if (you.species == SP_GNOLL) + if (_player_is_gnoll()) reverse(training_order.begin(), training_order.end()); else shuffle_array(training_order); @@ -984,7 +986,7 @@ static void _train_skills(int exp, const int cost, const bool simu) { int gain = 0; - if (you.species == SP_GNOLL) + if (_player_is_gnoll()) sk_exp[sk] = exp; while (sk_exp[sk] >= cost && you.training[sk]) { @@ -994,7 +996,7 @@ static void _train_skills(int exp, const int cost, const bool simu) ASSERT(exp >= 0); if (_level_up_check(sk, simu)) sk_exp[sk] = 0; - if (you.species == SP_GNOLL) + if (_player_is_gnoll()) break; } @@ -1010,7 +1012,7 @@ static void _train_skills(int exp, const int cost, const bool simu) // with random_choose_weighted. while (exp >= cost) { - if (you.species == SP_GNOLL) + if (_player_is_gnoll()) break; int gain; skill_type sk = SK_NONE; @@ -1053,7 +1055,7 @@ static void _train_skills(int exp, const int cost, const bool simu) for (int i = 0; i < NUM_SKILLS; ++i) { skill_type sk = static_cast(i); - if (total_gain[sk] && !simu && you.species != SP_GNOLL) + if (total_gain[sk] && !simu && !_player_is_gnoll()) { dprf(DIAG_SKILLS, "Trained %s by %d.", skill_name(sk), total_gain[sk]); @@ -1247,7 +1249,7 @@ static int _train(skill_type exsk, int &max_exp, bool simu) // This will be deducted from you.exp_available. int cost = calc_skill_cost(you.skill_cost_level); - if (you.species == SP_GNOLL) + if (_player_is_gnoll()) { int useless_count = _useless_skill_count(); int total_count = _total_skill_count(); @@ -1529,7 +1531,7 @@ bool player::set_training_target(const skill_type sk, const int target, bool ann const int ranged_target = min(max((int) target, 0), 270); if (announce && ranged_target != (int) training_targets[sk]) { - if (you.species == SP_GNOLL) + if (_player_is_gnoll()) mprf("Gnolls can't set training targets!"); else if (ranged_target == 0) mprf("Clearing the skill training target for %s.", skill_name(sk)); @@ -1943,7 +1945,7 @@ float species_apt_factor(skill_type sk, species_type sp) vector get_crosstrain_skills(skill_type sk) { // Gnolls do not have crosstraining. - if (you.species == SP_GNOLL) + if (_player_is_gnoll()) return {}; switch (sk) @@ -2071,7 +2073,7 @@ int skill_transfer_amount(skill_type sk) int transfer_skill_points(skill_type fsk, skill_type tsk, int skp_max, bool simu, bool boost) { - ASSERT(you.species != SP_GNOLL); + ASSERT(!_player_is_gnoll()); ASSERT(!is_invalid_skill(fsk) && !is_invalid_skill(tsk)); const int penalty = 90; // 10% XP penalty @@ -2250,7 +2252,6 @@ void skill_state::restore_training() // Sanitize skills after an upgrade, racechange, etc. void fixup_skills() { - const bool is_gnoll = you.species == SP_GNOLL; for (skill_type sk = SK_FIRST_SKILL; sk < NUM_SKILLS; ++sk) { if (is_useless_skill(sk)) @@ -2259,12 +2260,12 @@ void fixup_skills() // gnolls have everything existent enabled, so that the // training percentage is calculated correctly. (Useless // skills still won't be trained for them.) - if (is_gnoll && !is_removed_skill(sk)) + if (_player_is_gnoll() && !is_removed_skill(sk)) you.train[sk] = TRAINING_ENABLED; else you.train[sk] = TRAINING_DISABLED; } - else if (is_gnoll) + else if (_player_is_gnoll()) you.train[sk] = TRAINING_ENABLED; you.skill_points[sk] = min(you.skill_points[sk], skill_exp_needed(MAX_SKILL_LEVEL, sk)); @@ -2273,7 +2274,7 @@ void fixup_skills() init_can_train(); reset_training(); - if (you.exp_available >= 10 * calc_skill_cost(you.skill_cost_level) && !is_gnoll) + if (you.exp_available >= 10 * calc_skill_cost(you.skill_cost_level) && !_player_is_gnoll()) skill_menu(SKMF_EXPERIENCE); check_training_targets(); @@ -2289,7 +2290,7 @@ void fixup_skills() bool can_enable_skill(skill_type sk, bool override) { // TODO: should this check you.skill_points or you.skills? - return you.species != SP_GNOLL + return !_player_is_gnoll() && you.skills[sk] < MAX_SKILL_LEVEL && !is_useless_skill(sk) && (override || (you.can_train[sk] && !is_harmful_skill(sk))); From 1074bba3cf70459d4844383c930c628471ac28af Mon Sep 17 00:00:00 2001 From: Seve Monahan Date: Sat, 13 Jul 2019 01:02:54 -0400 Subject: [PATCH 498/864] Ensure Bat Form warns about Stat Zero (Mantis #12006) I have changed the bat form drain formula to drain 2 from each stat. The old formula was very high variance (For example, there was a 1 in 70,000 chance of causing any particular stat to drop by 7). This made it difficult to communicate to the player the chance of causing stat zero, which I think is important. The old formula drained an average of 4.5 points, while the new formula drains 6 points. I do not believe this is a significant change. --- crawl-ref/source/ability.cc | 96 +++++++++++++++++++++++++++++++++++-- 1 file changed, 92 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/ability.cc b/crawl-ref/source/ability.cc index f5fbfc5b5446..13f5b732a5cf 100644 --- a/crawl-ref/source/ability.cc +++ b/crawl-ref/source/ability.cc @@ -762,6 +762,8 @@ static string _nemelex_card_text(ability_type ability) return make_stringf("(%d in deck)", cards); } +static const int VAMPIRE_BAT_FORM_STAT_DRAIN = 2; + const string make_cost_description(ability_type ability) { const ability_def& abil = get_ability_def(ability); @@ -776,7 +778,10 @@ const string make_cost_description(ability_type ability) ret += make_stringf(", Permanent MP (%d left)", get_real_mp(false)); if (ability == ABIL_TRAN_BAT) - ret += ", Stat Drain"; + { + ret += make_stringf(", Stat Drain (%d each)", + VAMPIRE_BAT_FORM_STAT_DRAIN); + } if (ability == ABIL_REVIVIFY) ret += ", Frailty"; @@ -1861,6 +1866,87 @@ static bool _cleansing_flame_affects(const actor *act) return act->res_holy_energy() < 3; } +static string _vampire_str_int_info_blurb(string stats_affected) +{ + return make_stringf("This will reduce your %s to zero. ", + stats_affected.c_str()); +} + +/* + * Create a string which informs the player of the consequences of bat form. + * + * @param str_affected Whether the player will cause strength stat zero by + * Bat Form's stat drain ability cost. + * @param dex_affected Whether the player will cause dexterity stat zero by + * Bat Form's stat drain ability cost, disregarding Bat Form's dexterity boost. + * @param int_affected Whether the player will cause intelligence stat zero by + * Bat Form's stat drain ability cost. + * @returns The string prompt to give the player. + */ +static string _vampire_bat_transform_prompt(bool str_affected, bool dex_affected, + bool intel_affected) +{ + string prompt = ""; + + if (str_affected && intel_affected) + prompt += _vampire_str_int_info_blurb("strength and intelligence"); + else if (str_affected) + prompt += _vampire_str_int_info_blurb("strength"); + else if (intel_affected) + prompt += _vampire_str_int_info_blurb("intelligence"); + + // Bat form's dexterity boost will keep a vampire's dexterity above zero until + // they untransform. + if (dex_affected) + prompt += "This will reduce your dexterity to zero once you untransform. "; + + prompt += "Continue?"; + + return prompt; +} + +static bool _stat_affected_by_bat_form_stat_drain(int stat_value) +{ + // We check whether the stat is greater than zero to avoid prompting if a + // stat is already zero. + return 0 < stat_value && stat_value <= VAMPIRE_BAT_FORM_STAT_DRAIN; +} + +/* + * Give the player a chance to cancel a bat form transformation which could + * cause their stats to be drained to zero. + * + * @returns Whether the player canceled the transformation. + */ +static bool _player_cancels_vampire_bat_transformation() +{ + + bool str_affected = _stat_affected_by_bat_form_stat_drain(you.strength()); + bool dex_affected = _stat_affected_by_bat_form_stat_drain(you.dex()); + bool intel_affected = _stat_affected_by_bat_form_stat_drain(you.intel()); + + // Don't prompt if there's no risk of stat-zero + if (!str_affected && !dex_affected && !intel_affected) + return false; + + string prompt = _vampire_bat_transform_prompt(str_affected, dex_affected, + intel_affected); + + bool proceed_with_transformation = yesno(prompt.c_str(), false, 'n'); + + if (!proceed_with_transformation) + canned_msg(MSG_OK); + + return !proceed_with_transformation; +} + +static void _cause_vampire_bat_form_stat_drain() +{ + lose_stat(STAT_STR, VAMPIRE_BAT_FORM_STAT_DRAIN); + lose_stat(STAT_INT, VAMPIRE_BAT_FORM_STAT_DRAIN); + lose_stat(STAT_DEX, VAMPIRE_BAT_FORM_STAT_DRAIN); +} + /* * Use an ability. * @@ -2813,15 +2899,17 @@ static spret _do_ability(const ability_def& abil, bool fail) case ABIL_TRAN_BAT: { + if (_player_cancels_vampire_bat_transformation()) + return spret::abort; fail_check(); if (!transform(100, transformation::bat)) { crawl_state.zero_turns_taken(); return spret::abort; } - int statslost = 2 + binomial(5, 50); - for (int i = 0; i < statslost; ++i) - lose_stat(random_choose(STAT_STR, STAT_INT, STAT_DEX), 1); + + _cause_vampire_bat_form_stat_drain(); + break; } From 46574c2197aaab5b77d2a7117d825c083e07c2c4 Mon Sep 17 00:00:00 2001 From: Seve Monahan Date: Sun, 14 Jul 2019 00:59:35 -0400 Subject: [PATCH 499/864] Add escape hatch to mumra_spider_spiderweb (Mantis #12013) It was possible for the inner area of this vault to generate cut off from the rest of the level (by deep water). --- crawl-ref/source/dat/des/branches/spider.des | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/dat/des/branches/spider.des b/crawl-ref/source/dat/des/branches/spider.des index af80061672bb..28fe3eafbdcd 100644 --- a/crawl-ref/source/dat/des/branches/spider.des +++ b/crawl-ref/source/dat/des/branches/spider.des @@ -413,7 +413,7 @@ MAP ...xxxxW.Wxxwwx4xxxxxxxxxxwW.Wxx.. .3xxxxxW.2xxxxxwwxxxxxxxxxwxxW.Wxx... .xxxxx7.WxxxxxxxxwwxxxxxxwxxxxW7Wxxx. - .x4xx.WWxxxxxxx2...w.22.wxxxxxxW.www. + .x4xx.WWxxxxxxx2>..w.22.wxxxxxxW.www. .xxw.WXxxxxxx2..2|x2w..w.xxxxwwwW.Wx. ..xx7WXxxxxx2..2.x2www.w..2wwwxxxW7Wx. ..xxW.Wxxxxx2.x...ww11wwxwww2xxxxxXW.x. From c560d0b20cfb7c66bfcd55cc8a0eafb767425d48 Mon Sep 17 00:00:00 2001 From: Alex Jurkiewicz Date: Mon, 15 Jul 2019 14:22:11 +1000 Subject: [PATCH 500/864] Mark two unrand vaults no_tele_into As both are protected by runed doors / transporters, it shouldn't be possible to teleport randomly inside. --- .../source/dat/des/variable/mini_monsters.des | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/crawl-ref/source/dat/des/variable/mini_monsters.des b/crawl-ref/source/dat/des/variable/mini_monsters.des index 6cc11fcd80b8..a8ae20f4b118 100644 --- a/crawl-ref/source/dat/des/variable/mini_monsters.des +++ b/crawl-ref/source/dat/des/variable/mini_monsters.des @@ -6971,18 +6971,20 @@ ITEM: large shield randart no_pickup ITEM: large_shield_of_ignorance no_pickup : end MONS: orange crystal statue -MAP -........... -.cccc=cccc. -.c1.....1c. -.c.c...c.c. -.c.......c. -.n...d...n. -.c.......c. -.c.c...c.c. -.c1.....1c. -.cncc=cccc. -........... +KPROP: .d1 = no_tele_into +SUBST: - = . +MAP +----------- +-cccc=cccc- +-c1.....1c- +-c.c...c.c- +-c.......c- +-n...d...n- +-c.......c- +-c.c...c.c- +-c1.....1c- +-cncc=cccc- +----------- ENDMAP NAME: chequers_guarded_unrand_mask_of_the_dragon @@ -7010,6 +7012,7 @@ MARKER: R = lua:transp_loc("mask_of_the_dragon_exit") MARKER: S = lua:transp_dest_loc("mask_of_the_dragon_exit") KMASK: @" = !opaque KFEAT: " = floor +KPROP: -$*|rQDEFH = no_tele_into MAP """"""""" """""""""ccccccc" From e6e1909c86487098d86bce0532e9ab44c57ea020 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 15 Jul 2019 15:08:40 +0800 Subject: [PATCH 501/864] Fix visual jump when toggling floor / inv items For unselectable items, the hotkey is a space character, which produced an extra (presumably unintentional) indentation. I tried indenting to align the item titles, but this looked even more out of place, so flush left it is. --- crawl-ref/source/invent.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/invent.cc b/crawl-ref/source/invent.cc index a9e36ed09a58..5fccbd413b00 100644 --- a/crawl-ref/source/invent.cc +++ b/crawl-ref/source/invent.cc @@ -195,10 +195,12 @@ string InvEntry::get_text(bool need_cursor) const const bool nosel = hotkeys.empty(); const char key = nosel ? ' ' : static_cast(hotkeys[0]); - tstr << ' ' << key; + tstr << ' '; if (!nosel || tag == "pickup") { + tstr << key; + if (need_cursor) tstr << '['; else From b815cdf0ff89385f293dfdedb87486d7ddb88df3 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Thu, 11 Jul 2019 14:22:46 +0800 Subject: [PATCH 502/864] Fix spurious key events when adjusting map zoom --- crawl-ref/source/windowmanager-sdl.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/windowmanager-sdl.cc b/crawl-ref/source/windowmanager-sdl.cc index 88732108df02..3045e74d2810 100644 --- a/crawl-ref/source/windowmanager-sdl.cc +++ b/crawl-ref/source/windowmanager-sdl.cc @@ -809,7 +809,15 @@ int SDLWrapper::send_textinput(wm_event *event) int wc_bytelen = utf8towc(&wc, m_textinput_queue.c_str()); m_textinput_queue.erase(0, wc_bytelen); - if (prev_keycode && _key_suppresses_textinput(prev_keycode) == wc) + // SDL2 on linux sends an apparently spurious '=' text event for ctrl-=, + // but not for key combinations like ctrl-f (no 'f' text event is sent). + // this is relevant only for ctrl-- and ctrl-= bindings at the moment, + // and I'm somewhat nervous about blocking genuine text entry via the alt + // key, so for the moment this only blacklists text events with ctrl held + bool nontext_modifier_held = wm->get_mod_state() == TILES_MOD_CTRL; + + bool should_suppress = prev_keycode && _key_suppresses_textinput(prev_keycode) == wc; + if (nontext_modifier_held || should_suppress) { // this needs to return something, or the event loop in // TilesFramework::getch_ck will block. Currently, CK_NO_KEY From cfb02b9d073afaef6f3aab6602ae0b16e3773d50 Mon Sep 17 00:00:00 2001 From: nlavsky <3328424+nlavsky@users.noreply.github.com> Date: Mon, 15 Jul 2019 22:46:23 +0300 Subject: [PATCH 503/864] Update scroll of brand weapon description (#1114) As blowguns are no more. --- crawl-ref/source/dat/descript/items.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/dat/descript/items.txt b/crawl-ref/source/dat/descript/items.txt index 8dea07749143..a0361ca41aaa 100644 --- a/crawl-ref/source/dat/descript/items.txt +++ b/crawl-ref/source/dat/descript/items.txt @@ -926,8 +926,8 @@ contaminated with magical energy. scroll of brand weapon A scroll that imbues a weapon with a random brand, such as flame, freezing, or -venom. Any existing brand will be replaced. Blowguns and artefacts cannot be -branded in this way. +venom. Any existing brand will be replaced. Artefacts cannot be branded in this +way. %%%% scroll of enchant armour From bda620ff8eeadaef1d2a8e22b70c147c811d0a0b Mon Sep 17 00:00:00 2001 From: Seve Monahan Date: Sun, 14 Jul 2019 01:20:05 -0400 Subject: [PATCH 504/864] Fix misspelling in describe.cc comment --- crawl-ref/source/describe.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index 197c05e49f16..4cd290d1122e 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -988,7 +988,7 @@ static bool _could_set_training_target(const item_def &item, bool ignore_current /** * Produce the "Your skill:" line for item descriptions where specific skill targets - * are releveant (weapons, missiles, shields) + * are relevant (weapons, missiles, shields) * * @param skill the skill to look at. * @param show_target_button whether to show the button for setting a skill target. From 958ff8eaa047c815e460f0b871ae376d23ed20f7 Mon Sep 17 00:00:00 2001 From: Seve Monahan Date: Tue, 16 Jul 2019 20:32:32 -0400 Subject: [PATCH 505/864] Make Qazlal's noise conduct more clear (Mantis #12025) Specifically, clarify that Qazlal followers generate noise even if there are no clouds around them. --- crawl-ref/source/dat/descript/gods.txt | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/crawl-ref/source/dat/descript/gods.txt b/crawl-ref/source/dat/descript/gods.txt index 3fd4e663f735..23fdc3888080 100644 --- a/crawl-ref/source/dat/descript/gods.txt +++ b/crawl-ref/source/dat/descript/gods.txt @@ -371,13 +371,14 @@ its normal limits. Qazlal powers Followers of Qazlal are protected from all clouds. As a follower of Qazlal -gains divine favour, they are slowly surrounded by a loud storm, causing -elemental clouds to appear near them, blocking attacks, and (for the -particularly devout) deflecting incoming projectiles. Qazlal allows followers -to incite nature against their foes, causing a localised natural disturbance -or, for particularly devout followers, a more widespread disaster. -Followers of Qazlal eventually gain temporary resistances after taking damage, -and can give life to clouds, turning them into allied elementals. +gains divine favour, they are slowly surrounded by a loud storm. In addition to +generating noise, the storm causes elemental clouds to appear near followers, +blocks attacks, and (for the particularly devout) deflects incoming +projectiles. Qazlal allows followers to incite nature against their foes, +causing a localised natural disturbance or, for particularly devout followers, +a more widespread disaster. Followers of Qazlal eventually gain temporary +resistances after taking damage, and can give life to clouds, turning them into +allied elementals. %%%% Ru powers From 3e8b2426320f02ba514909374422257ac00586fc Mon Sep 17 00:00:00 2001 From: Seve Monahan Date: Wed, 17 Jul 2019 21:04:30 -0400 Subject: [PATCH 506/864] Clarify Beastly Appendage Octopode mutation conflict. (Mantis #12028) This makes it explicit in the description for Beastly Appendage it is ineffective for Octopodes which already have levels of the tentacle spike mutation. --- crawl-ref/source/dat/descript/spells.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/dat/descript/spells.txt b/crawl-ref/source/dat/descript/spells.txt index d5e8edfa2846..5a1c8260a7eb 100644 --- a/crawl-ref/source/dat/descript/spells.txt +++ b/crawl-ref/source/dat/descript/spells.txt @@ -94,7 +94,8 @@ Beastly Appendage spell if you.race() == "Octopode" then return "Causes a vicious spike to grow from one of the caster's " .. "tentacles, increasing the damage of their extra tentacle " .. - "attacks." + "attacks. It is not powerful enough to affect tentacles " .. + "which are already mutated." else return "Causes monstrous horns or talons to grow from the caster's " .. "body, granting them a chance of making an extra attack in " .. From af07aaf8029077debced614d84349ea068b75258 Mon Sep 17 00:00:00 2001 From: Alex Jurkiewicz Date: Fri, 19 Jul 2019 11:47:22 +1000 Subject: [PATCH 507/864] Add guidelines for no_tele_into usage (#1118) Discourage overuse and explicitly reject the idea all runed door / transporter vaults require it. --- crawl-ref/docs/develop/levels/guidelines.md | 34 +++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/crawl-ref/docs/develop/levels/guidelines.md b/crawl-ref/docs/develop/levels/guidelines.md index c3efaa727c2b..6b3bea5c0562 100644 --- a/crawl-ref/docs/develop/levels/guidelines.md +++ b/crawl-ref/docs/develop/levels/guidelines.md @@ -3,6 +3,7 @@ 1. [Guidelines for D:1 arrival vaults](#guidelines-for-d1-arrival-vaults) 2. [Guidelines for creating serial vaults](#guidelines-for-creating-serial-vaults) 3. [Guidelines for creating ghost vaults](#guidelines-for-creating-ghost-vaults) +4. [Guidelines for no_tele_into](#guidelines-for-no_tele_into) ## Guidelines for D:1 arrival vaults @@ -186,3 +187,36 @@ CHANCE directly in the vault. For ghost vault rooms for Vaults, instead set the Other tags we generally require for ghost vaults are `no_tele_into` and `no_trap_gen`. If you use `allow_dup` in your vault, also use `luniq_player_ghost` to avoid multiple vault placement on the same level. + + +## Guidelines for no_tele_into + +The `no_tele_into` KPROP prevents teleports landing you on the tagged locations. + +Example: + +``` +NAME: example_vault +KPROP: - = no_tele_into +SUBST: - = . +MAP +xxxxxx ++.m--x +xxxxxx +ENDMAP +``` + +Teleports will never land the player behind the glass wall. + +Don't overuse this property. It's a hidden mechanic not exposed to the player. + +Good places to use `no_tele_into`: + +* Vaults which need the player to enter in a controlled manner to understand/enjoy. For example `gammafunk_steamed_eel`. +* Teleport closets: areas the player cannot escape without a scroll of teleportation (or similar). For example `lemuel_altar_in_water`. +* Egregiously dangerous/unfair situations. For example `chequers_guarded_unrand_ignorance` (four orange crystal statues). + +Bad places to use `no_tele_into`: + +* Any old runed door / transporter vault. It's fine for players to teleport into tough or scary situations. +* Islands: areas the player can also reach with flight or similar tools. `no_tele_into` would be an incomplete solution. It's better to place a hatch/shaft, which solves all cases. From a1643a67888938846c216071bd1190932618c114 Mon Sep 17 00:00:00 2001 From: Seve Monahan Date: Thu, 18 Jul 2019 22:38:43 -0400 Subject: [PATCH 508/864] Ensure artefact jewellery is always auto-picked-up (Mantis #12029) This was caused by commit 32ec7cac8f0e. 32ec7cac8f0e did not correctly handle artefact jewellery when it changed some jewellery autopickup from using simple autopickup exclusions to a lua function which checks the player's inventory. --- crawl-ref/source/dat/defaults/autopickup_exceptions.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/dat/defaults/autopickup_exceptions.txt b/crawl-ref/source/dat/defaults/autopickup_exceptions.txt index c4a78c3f9e7e..47e0b063bcbd 100644 --- a/crawl-ref/source/dat/defaults/autopickup_exceptions.txt +++ b/crawl-ref/source/dat/defaults/autopickup_exceptions.txt @@ -73,7 +73,7 @@ ae += [^n]identified.*spellbook # Excluding most amulets as you only need one of each. Likewise for some # rings. Some items may already be excluded as bad_item, e.g. inaccuracy. :add_autopickup_func(function (it, name) -: if not it.class(true) == "jewellery" then +: if (not it.class(true) == "jewellery") or it.artefact then : return : end : local itsubtype = it.subtype() From 9253d746ad11c3c17687860cefcd5c23c25c711d Mon Sep 17 00:00:00 2001 From: Alex Jurkiewicz Date: Sun, 30 Jun 2019 21:08:41 +1000 Subject: [PATCH 509/864] Compress title PNGs a little bit better Using: advpng -z4 -i 1000 Then: zopflipng --iterations=1000 --filters=01234mepb --lossy_transparent --- crawl-ref/source/dat/tiles/logo.png | Bin 27302 -> 27111 bytes crawl-ref/source/dat/tiles/logosmall.png | Bin 13682 -> 13036 bytes .../dat/tiles/stone_soup_icon-32x32.png | Bin 579 -> 576 bytes .../dat/tiles/stone_soup_icon-512x512.png | Bin 122452 -> 113030 bytes .../dat/tiles/stone_soup_icon-win32.png | Bin 337 -> 311 bytes .../source/dat/tiles/title_Cws_Minotauros.png | Bin 221267 -> 177708 bytes .../tiles/title_baconkid_duvessa_dowan.png | Bin 58164 -> 55507 bytes .../dat/tiles/title_baconkid_gastronok.png | Bin 49052 -> 45466 bytes .../dat/tiles/title_baconkid_mnoleg.png | Bin 86170 -> 82902 bytes .../source/dat/tiles/title_denzi_dragon.png | Bin 29212 -> 24423 bytes .../dat/tiles/title_denzi_evil_mage.png | Bin 35346 -> 30666 bytes .../source/dat/tiles/title_denzi_invasion.png | Bin 36236 -> 31110 bytes .../dat/tiles/title_denzi_kitchen_duty.png | Bin 33459 -> 28977 bytes .../source/dat/tiles/title_denzi_summoner.png | Bin 43909 -> 38315 bytes .../dat/tiles/title_denzi_undead_warrior.png | Bin 44233 -> 38159 bytes crawl-ref/source/dat/tiles/title_firemage.png | Bin 77597 -> 68671 bytes .../tiles/title_froggy_goodgod_tengu_gold.png | Bin 40254 -> 18617 bytes .../dat/tiles/title_froggy_jiyva_felid.png | Bin 21213 -> 18541 bytes .../tiles/title_froggy_natasha_and_boris.png | Bin 37496 -> 32568 bytes ...itle_froggy_rune_and_run_failed_on_dis.png | Bin 36414 -> 31574 bytes .../title_froggy_thunder_fist_nikola.png | Bin 82056 -> 75039 bytes .../dat/tiles/title_omndra_zot_demon.png | Bin 49566 -> 45009 bytes .../dat/tiles/title_peileppe_bloax_eye.png | Bin 55337 -> 48656 bytes .../source/dat/tiles/title_ploomutoo_ijyb.png | Bin 206083 -> 200808 bytes .../dat/tiles/title_pooryurik_knight.png | Bin 31308 -> 26878 bytes .../source/dat/tiles/title_psiweapon_kiku.png | Bin 227063 -> 219095 bytes .../dat/tiles/title_psiweapon_roxanne.png | Bin 24008 -> 19773 bytes .../dat/tiles/title_shadyamish_octm.png | Bin 74469 -> 66639 bytes ...title_white_noise_entering_the_dungeon.png | Bin 82202 -> 73306 bytes .../title_white_noise_grabbing_the_orb.png | Bin 66443 -> 57912 bytes 30 files changed, 0 insertions(+), 0 deletions(-) diff --git a/crawl-ref/source/dat/tiles/logo.png b/crawl-ref/source/dat/tiles/logo.png index a6d1e2b89422c43b31b1ddb100e3c0bddd21e566..f8d463fe87cbbee9e9bb419912e62b3ffbd88675 100644 GIT binary patch literal 27111 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

)=t`TtprrQB(4F2M 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 literal 27302 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 Zx*nZ1zBf>K(e|IGQB%@XESI+o{y!+dq^AG? diff --git a/crawl-ref/source/dat/tiles/logosmall.png b/crawl-ref/source/dat/tiles/logosmall.png index 2177329c501f899a67c979e314c332d2186bab1d..292e7a06fe3ab033d508bc219ce8a8715c181eea 100644 GIT binary patch literal 13036 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 X9Y-O$uUO=T{|S+kQk1L|HwyS)qxd+1 literal 13682 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𝔓l`ujYSy5roHW(ft2mJ` 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�VJfL%9XcJh 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 diff --git a/crawl-ref/source/dat/tiles/stone_soup_icon-32x32.png b/crawl-ref/source/dat/tiles/stone_soup_icon-32x32.png index 726f4078dea0ab75699361f31142e1b5aca18dc8..31fe81985956b90db3d1579b75079f73a8d5c509 100644 GIT binary patch delta 399 zcmV;A0dW4q1i%E4yMJ&=L_t(|+I^4*mct+n1((EHSu&*eO4xq?3+_iD5Bn8QdS<9^ zV>tIV?musC+|Nh+NHF5v3lr{EgCh5Z5F8kI$jjxzlL80O4=^@M;wMCCj`QHE=Lykr z8PDmQ;u(+Sl8*C9E=rJP{7dmS#Xr1$&+#~4E^EM-OCA?fOn=Z3^I(z?s0ON+i$%FH z2~7xU;ngA>@(j(wOl-acK7&Rirlp9m5ceh^4jvC{c1hIZA!Uhj%D=T)Iy)r*0Ygat48E%aN5C2?2XiZk+1rXT$R+v|11hltc&0Eh3UmmX+{E5mM z=GEhAMfSEyzkhYFV~Uywrs1t9J_n+f*aI4{^lyqKC)MY~d@WRmh04I|qFF2!8tfFo zD}FQ!af9Ifdf0AHcW^pw4~KUPdcN(t&FA&=^ZV!f>vs6)x?$m_)23~^!^iFO>+^Ql t%-Uu;b;Xy&HK0Y+f~Ijr51UH0|LZ6sE?#pg@Bjb+00>D%PDHLkV1hIo!ngnc delta 402 zcmV;D0d4-k1j7W7yMJ>@L_t(|+Le>ta)K}rMvW4e4M_nJML`-7t-k*Y_G9I@7tZus za*;VFyAv2zpQ6<2GjD74naAM&6+Uw{Ms_uXB|P?V4x1$htg4FEeaInm0cSg?=^d@% zoMNX&4y<*W`m!k-U!u}fpW-!)LFk}=HU8Q77uK`%r#MX~fq$y1JLenU0DJU76X*0K z7*ipT;JhKQhAI%ox|*#l$nV&%^GNO7A4N1VPjD&BgSij4o=C! z(c`Lme$_`~vz^MAvnudQKUEWiU|oJ%M$mVY~-Gkp5x_H-;eSqX-%0mJE1b zLkD}-{S4v8;(rlCIxxY=)o@KV!V$sXVt@|<8&RZy5n`IZY8GYWcm_Uwu7!cM;3f%@ zBr#5I;jFnI{Fa0|#N01E&B07*qoM6N<$f+Q8aS^xk5 diff --git a/crawl-ref/source/dat/tiles/stone_soup_icon-512x512.png b/crawl-ref/source/dat/tiles/stone_soup_icon-512x512.png index c07378acc5801f472b7d40cfc81db0d92e72a83e..0577d0c330847cd46dbc13642bf9c86532615e82 100644 GIT binary patch literal 113030 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

*RJhbi}C)wdu+D@qE@8? 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 %6@ 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 diff --git a/crawl-ref/source/dat/tiles/stone_soup_icon-win32.png b/crawl-ref/source/dat/tiles/stone_soup_icon-win32.png index f5a618e48c955eba1259c4aa59c0ffd44f08ea2f..fff8fa6b7badb90eb451fe5c1c4fa07c659e62e8 100644 GIT binary patch delta 295 zcmV+?0oeZ00=EK?8Gi-<0047(dh`GQ0RBltK~#7F?UWG^!!Q(v>r|&XMdsmAoZ=Lx z$h=N*Dv#>!S9h3ocYpWMTcDPAx7>Y@?7jDYm&-c&Uk=tG{0lJXB3n3N?@xfnl#*E2 z^(V`+2A7{2_96S|0sbV029~`_9nn1;_p=BBw7N&Id$~;6)+<0 t%K`OdFM@OGY#^{_0oHK|*60HN^#P9RzfKfuLJ$A|002ovPDHLkV1lP)h8zF@ delta 321 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

i0H-AJ` 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 -? zGFYIxZ!i7bUF_T4$GT5U9Sn>KloeR_(ZO};u$Po=u^uV2uDZJ{lgRmlZ1@$Jw_hMBRr2ojdC0}3~hp- zP$nqk(R~49DMtjhE@^bQLP`qjhaus?A!b#+{^RHHiVIh>w53tjU>=n}P?qia40w&Q zjG%D;ur)5iJLGbfv`E6CBK7`3;@*I=5LTcG0Z2%#Af4aF@x?0FpX~FQF2Q#@4K+QT z@jsvZz1vZhz)B%sQuxzwqs|-8>$R)7^8L?bdAmogXM|vI7+r`NH3FplJqW;;6z-aQ z?i0m}pS6e^zWM?dH%W@ydKg@vC+r#3k*&LkgRt?MH>UJN<35Ez2x~Uc8q??wbfYgo zfRr918}g9!U>?qd8$P#=OJ8>~!`r%uOC^dMH&G+Wx=&0$7?{YW+(cXUgH{=QW``NR% z#y4*-bK`xAN@!bku=BO#cke|=iS{&c400Y0fG=EgK9#;9R1j0^=|yQD5gWdB*Bnc5 zg!Mc${C9TVPMIm?jdf)CtviXTb;OuriNM4frR-?zi=SM_yDvSFk?q|KZ>}LcaiG%^ zpp`*-lCfUSgc|($j}cyc?jmmZ$_rTBEEwIjpZ-Vl1ieFa?W^&v`)l0zP&{6j;m+4F zym7l7`5I7>LB<9n=3CZ6ZurUzS)7xMcJ8D9{yf3{A-ei%eCy#FH*P#oR-ETaR zk@Z~+ZLK1uu#ZdFk(&+-!nejrj-6|s*k1i>*PY8-->{a_&OU}79i+NtFL8d9_x{fC z%g)JZWxduMS}E%Rhy_}K&@&j~kDf>Vp>0H!8bUUnivm?Q2;U&nhJXLiNtAZ%WN*Re zJGTw++3)QDVC@MDxbZV5)8WSmDUqopnUyQ4boJ2Y!8b3-@}_TBrxng}*?%3lU*F^Q z|G9v(kN2q#<_QN!33~h4+*RWnf2{F~M`NnveZlLvPJ zZD3Xa2t6<7rNaq;qm!?F`dr@n`n8n$2gr97DQ(?GSQzDsA83BHVQP+SKbNzO2!Rj= z6C3m#9qxzUc`8en6yv42?XD4SzO%$Ff9xC25*F^fn4wKOk)8l8tU=MtD_hvO zVc65d;PxS^o!x}_QLgxf;a6M3gB=?rSATCd-81XpWW22HJq$fMMCFmag!v*@+-~^Q z_Jhho;J0Kku}1iUC|^YfcI4K%Kc3fbDt7iT_~0Ow&E4$WHNu5A#S=zVihsGGlVhLu zY+kfDM8^i|G09cSsBYN!Y>5pKVjq4nF4p2Q%mmrZG!pSGIO?cKcd3w!v< z9|k5}YwNCIUh|PH-230pp}4yTBqWzDptN-_!t;2>QaPgsV2roEb`4+q+&W6#eH3^0 zQQ5Yauu$Y5ZqnSob(+4QDT7hUdVLV+sNvP}<{AtN5`}lxc{4gNmPcvFLCD;7M)#FS}$d zgWGqag{JWEW>mGtyS}5jV@o)LM_x4M(F9t6islXiyy(TpQOy_Zc^cv%M)>o0b!)AW z!j3GI!ZunVX6(qkrYtHn2p?o@P@#cHv-qr&D0cUA?Y9T`^8ZXfN9i?X(OP4KhtviY zVg-kopJ5nya4V`7P`I}f6Ggo1=bAfqO#PvA^*d%hW!I9x($Al7`dQ_Nk?9h-?OA%#D6qLksazn=d1|M-8KdG$B{iu{AS z5fW0%S}3j8h=k;^L~N`0+`g;+xSsK(_qR2Njx`2>6dDy9 z{A?DP&GDvdck%1{ho`;Xrfnmn7q>IAz1s>{zY*vLm^s?$zg_hgy!-8^Gq7PBsuohX zzY`P1yz8fmJGMnL*i*YCSPCnU$J*R%?fS!)pTg3mS$ZGZgY+fU?!oa${JjIg{2zvt zXsscN@!Q)8yKS7q1*b{w+A@1zB7{JW^<7V(Sadi6@TBG9zh1#*Z#KPAj*toGR{X~w+d^$*5RArXVcqgGxI(AxC}WK=!b!_QK^vqg9MHm_SqS8UbKS#bd+X z>F0(ozR;F4@P{p^Ag1uZ9^y*OABqWzmFc|(cRf5zYEdgXQV7pOBq0tALRo`8W1S0u zjvB#ozBMH21uX=l5f@&wg^hb=dtL$^Ya|k_?74b=F{y{lXFq;ErER@L#TxN&m9VFX z@C4u4ba=PI76^{__>J$Ce~;?bg7C7K}fi_N6h+8z55+! zF!*re{oSyu@&0<;zHJ_T!B}O-Ky7yQdeMuIqdGV;-iMe#Arju98)0#vAM&zU2nBju5KoF}b zgYhY}wRicqH^#NO#-+nkg{Lk&<=TqF?Ls+O1jZ_bm_2|rHz3BPJ zQ6DUTgwi8@#GyuelK1?6<`LItuQ{LM)*ix<3UR(l&|g9b_{sJ;-VfhHD}~fxq`^ei zbCcHzAedz|Z1Y;l(TzubmE zQt2A9aV4=~OX2XV4Xtd3O`)v^pgvfk+Bf_B_SNq_4HHHftpQ1CM?V@t6bP=kwLbeh zwWp7uTqPcRr=;XN4@8I7R_5VSKmNE@s>A&@iI}#_h##w9)7n665J{gXHV99!IAdn- zOJW1Y_FYQZF^uDh$E90%5^?3_wlgd4?*nD1>>Yx@D&j5u^B9q9jWHUdwH;H2cP^)$0Ahvl0VNL1P0rWZr!+=@kOCbTObmF_ zcfPNFf9IqMuxg3{w&B{AR8 zS*-2zi3D-n@DLs51TV`MXQ}PjXGN@muvE88Q!$O8*uyLUl(sqR$2?ebjFNjdUQC9N z-tGHP)sW%4_h8Zq-ulxzoAWb2Yy18VVvIrHehzPm8Gdn zlDKX?K|=tFB8ZCx(~HW0^{hWl{t(TUa)v`wdJ<`GG2M>GBx+) z+MB&!GS+5GgNj8X`N#a-uR=&v7@?Fv8Ysu!%!Xm#J{x2u4N)Pm%LW_wJ=GT`8Q!uN z&-2i+9#6a?6CV3-8$u-HjMZ}T>Q>4dccG<$5Q1_5k;Y6gLTguL`M^6*=b{Twq)o*1 z{Nf=-H}*05U=KS~f_MEfq*R?fNbcklS}8rS)5Z)KLoga5eKBWH+l!vNoVXHTguxg= zdFKc!fKHWQDwt1DXk~L3jR6nS8IflXsOZhSlu`efD-^uAr>si z(A!cr1UTn>s~f9=K;vIq#5iTwL3CqG`gZ#`qwAXyk-#t?~x>$?7Tr-4X8b^h3=jb zBM+|~kxwbR|eWP|L?Fme%(9E4&=f%%oMP<)0#z1XvE9 zm^->#Yi%cFbz`1Zn0e0&+jA9hIl?sZ0Q4T_9bWxRg1A%zPvCjNE;ocZN1Ts|MjJDp z041ykYJy-k26W$L6t?XpD%IHegFjO3t8o7#qkN-Nao3*t3!eoG)AVjCTd$V_6KI=^ zig~n6&$dk=l@%vr?QD)j7B)cF!w6+#M5f{XpIPI-@2*EU^EkoxKYBVBe|*#AI*POn zlvLR37;GTooZh`gzZbb(Oq~FDDn5*)PgJWTg#=-Um7dXPP2b@fjBG6Fi!^es%r%V! zJBY^Usi+Z&+0XgUPoK+cFFuX^e|)&HK74Em;oRqrjS8i(^TKg-XfZ~1$1qJe8laRw zgoa1@r?)76$|tPUkd1V&anwk^J59%OaK80KM>8r^kQ7J-QDhn}$(iphjzXmGBSX-_ zqvxkPNG<85`NTGKq^Smm(NMEv>nOMF3AwrJG0aaJQ1uX*@@*%ZN}@uAFou=w3A#t7 zUh@UdXy>%2EoRSu-w(<#d`~Yrf=}%c43y@!#-=d^VD#9Ccb?B|%+n$z(MX6^R**hg zIs9&UrD8mMGzz7xV0)sLk!!6XmPnzABb!`F95j+1-qeLmc!;FLOL?5R(Bq>Ccwl*o zU-ZGBcF!%m{8WN4s3Cl8&x-O7u<{de0V!M(;vvQrcuA0*tWb$$5C~3>p)JePvi%%l9=<99rDn z3GVLh6j~@wf#U8KTnhv*6o+ChTHM{CxD^c$AVq^)kvI2u@Bj1rDbJHYa%N`lwbtIV z&KxZ9BpMnyLI*2y1#(q?b3B3-CPQi1692Mw2@eLY+OIV~Z|N)YZ$+u57es6KW(534 z3o6iNytx&D3Y)YOfxHFT^I40-EfPUJhVb?gBaU!D>h0>3^o|EFKDZt=L8Sf(qP-x{+$_~Kxc>@$IM!Q*cXqi z?SFyKktnFS%{A0i_z7=&?A#t{d&Sp$s*(-lJij{QzNGf(6qoS@>wB;lz(_v$@0%Nt z{vQgE-wn~)-Cp^UTYo*FdX50>{)mz$c+Hb^rF&UF)?q=1br@p5f1`l8wn-m0%kLW) zk_gIzZ?-(ver!}y5jWD6wPNH~u20?skq{8arHQc;P4T1BHow*$$`*7DL=EQqtZ|3k zIWnTn(ue+@REO;M^pv^Nz$KIL#ydz{(i4%mOBYtwne+Q#fqnV{<)2CE5O$({&!kKf zFKn@dV^#tEbl*(e-qYXEl>F6oYya$@Rmm8VdpEjrXPv1m?g!R zYXsPGCH;R17PQBQy!4V`*TRr2>_kgnXI+u{`+cpYr15+gKjIoSow0GL{hiO0#b>g~ z_Z$Y3&MW%cfs16MNm^HWbo1hmi%)n@}_J#uG z+vWS-sjs?0-NkMlW$?lZWKTG-p3`XJ(Z~BI0C~00O4I)X8M2pZfo9P4z^a*;xUx!9 ziOwQ!F!_woE;oS;j|1FuHIg)f5GBR82_bcCq z%ZzFjbC1g|#1Fv7+TZS%c`D!mf&I(Zp4uA;C?ezn2YX}*yy?m@0I+02G7^9>=@@kX zQnQNMt1i`<2MfMac(&9;LQW5?B2`?Q1Zpr?L4ovq!xJvZXgPzwpuY<@CP-K6NK$@M z=n>JF;N&Zi_SLz9q1c}Z5R{qQw}rmU;eH^Z&u5EzC+9X9Gqt-iZ8juo%k}Zot(1@J zT7-t*>&$AZyxw*B%{l-=Xh1g-K}&_blf)dlq~%EA?jh{P9lVcMa~BD2{m{X+I#@Ua z_qux7(ONj+zF)ty_gshMaEpF9ltIMZr6C^{P`ae)X8GF0bEGfu$Klr)EPy#PYF1e4OH#KZc~d{(Ps^G*B9Y!75y+qw#j*ak?r?C3}V5yYSL zZN~CuA~P@U%T40gpBR7KQ1TtDh{S)sw?XldFYTa40uQhb9ERk#zgy?@y?Uo^d%sK~ zjE9{m3-67cG!`s|Won$6(fOIvhiUkIr~P&n!0ccJ@=sUw;RIYc;P8A(Y&D6R2<)^n654p&l6MNLEJo9rz;7%otc&5?4NylZa%uG zFH+#+B#izDY?T*lZ0UulbRXe~*+3d<^8@$Cn49TGtslc&Iqm0Wu`9*&A?~-hEuD{y zTqfUR9T2IejRw1Eyu$=cS`9AtB4gqfuAG_ptX6!PZ7bVYkd7g z%l9B3kh85$abA|_s!i32OAuwIqa*32h|DKz3RtTh1`8)j zQ4|&WAWz0}h*bCEd9VukPF#3o{*wTJ^!IAiuK>UNPq($G6k+WyJ8-~fSbg;oI&E1h zau1sx)@Dimj2r~Jte$lc&>&KJkJ_>F96y<`z~ne(H1rlq-BF^wHanIJ3JyQgB(;dx zAm@!y@;l~67dolA*h&-w_XK@qjbrX$rC|6}LW}9#W4BMPLk^n7EOs8e0eS=%+-6RY zb%yZk0O)%xkm*pCeFL%IfAddZs|u*V$t>@o+19~i>VS8*+q;Kbf|rxXgQcEsod(i` z3={K0^8EF5e^j&`l$kyrXp>1@UF_x7{kGL>kXt+n+5S$%wkIhM$|oMqlqT({atBY} z5@gUPgim`9&7X>XoLI4+XtN`;mbNm$Lw za=NA@_N1b_E&q2Ll*{()LlXW6c*C3sw|n=Y{?kvNI|3fi=Wo+Jw8|nTO2zi#U7*AU zV%m37FD#im=5wm}D}=%70gs)J1A(LgA4%rYMk7D{^+ii*sJi<4o(4p_VV7TX%^hqn z>H2&h<@K^OH7T68u4Xa8s*oKbBI^-Up8dR`AZ&8+yDA@~iO_U*0O&1~6r^4!J9`p; zofytlmf7FHI($&&C zuWdd$1Ql-Z(aR>t483xG?CUI}X+&kvxsFZamZp$i`E$D|-3F#`B)vZgbc!KhPe9cZ z98JjL*XrL!?oBgB7$gTF*ncM>S5nueQpq((fT{>2mDcSu;IsBrq2Lg8F?-^QD%{ln*Gsg zoAJ2IpD75osI^Z3qJZz^qjCZmldvaKMhAO)Wk5K^HLRb(IHK$|xXzOvBI(dapo~503HVa&=r!&}El2p3u*t7Xvw$2}$d0T9kW%A;?8*ir> zkP47t5UT*QAXgi3bxs>p+4#?4m1m&lS@pA@nLBk-WjFb^KM_gBga<6gdG+d-gmM^< zxr}d|@QXeX(zrWcp4|qTi)(zC7kLBzIIw-!;Da4flc;*ziPH9ndW-w!z#l_RZ~2SF z%BFS90Nk7(I)1)hlaut?|H?yQQw@+oh|SmrOQ z`_NHmJRV!;ESI1;YxA=$a`GHxR*oO2?r)AC z3@s#htK-!RAHmC}h$iJ#Ue?)Kxf!f5@at6v^X5ocyTHE8MqET9KicwjWR4I4oApIo z+C=^pRl}|?u~kScpdemp(}=fdQ-L9~{;S(o$F2VP;+*h}0$@5p1se z>g8(LUx%73C-9sL{GcJCt#Ma?ho+=q)nmH@qv*)TO>Q(0oki-GMtf`J{+(p!$S6y;{)32oZ zq>yE&^oI0DMDts514a#@<_6M<^ZK$Epco?0Jvi+aB>fS=wtKS=`pf49vYfql`D3}D zI+!_K(y=XVsJCxK>(>U{jkkf#I5k_rbAW7o&$+~RI45*wDFo3m3qC3Zw4zo`RtmP!{o=F-!r$*!b& zuOZ%J7|nLOw%KG$&%^yW?DUkf!~g>i?f%eV5pz1IPkm*>m{FfR!Q#XadLb>{0df}i zIfoQHCWyQdg?5tAm43Z`cJ1`wWqx+Guc2))maI zXOXQo+V|(~3_b0;Xsydn6cNHsTq5_s$9Y?w?!O(+{qf~3O6hC#fz-W`izsej*vs7` z%W%?KXRXW+^7gv)|6!&|saf^eE$j&)qFB(u;#UV(5K&%^&@Z5z)n&0msf3lYTj5NB;4!Tsqgw=^b-luZnk^JCYxS-F$qwtJn!F9Nz18 z@}YZr&lM;b0`K?@C;5M`?7cbdPw)%^_grfk5p!6NbR)goA0(aqEqIx3Re?_yG*!cI zAw2f=E%^NFk>Gbd|9Nrn$a4|q7l%P*@RL!qYw)M304hjK%hTuPDD{;^@$t;sC!U@* zYY(cuISf=~hgkc_siWr`CZ_|y+~T|38$$#IBZ6phQB9_&4RGgIsweB4E0S|Y;MPek zbo(!iyteo<{}KqCE~Xw{_l3et7(7G}x7;Y}UejlN`cx827#{L+I&H7Tk|pv^Xn$uU z*3fiE#|d3duzEXx^t^JpKIErHm0(Z%eNQ=%h7Fw_lxyK-h(l!Y9ar}(rKKm_)L2;S zSxR?7Ua*+t)zPMJ(8X*-ppV}PqyXGb3RKHSpiQfloa|n!tpc-FL1%IbjaQj_uh+%H|M=&UUiP}d7p1*pCIi& zUdE9W73LhsuHn90!F6uW&b;|OV)2(y*4&`WVgvhr*8Fz}gG%qJqTVHF^X2V%ySC*T zNit&-;cPtR97ILWEl?CM!w0Fst^ohjddNoD1xoQE0tWB|n#bX!Ufcxo{@vIVzZT-o zAbr2zBUuxmY3-5QVY8h8E@(Jy1MYf)%idNL?bsbkIwHYp_nvJk^=kB#%1qJNyFB8f`Rup}2q$$Y++ zWGuq0TPH;$UIHPegvWC2{qA3|h;@FzYKm{+K6Y=sl|1ecI^b?~x@B%Dms~hBr}=n4 z(fs*qjtyB@%=lZJtAxEswdnvFi%&fyx@Y$^&Lv%f@##WZvI$SYR;~9G1>0q?peNqt zBirYra>|ek!v*r$8>D0UPp_Uz>5YY-v$>xptml^;3k75g&r7x^gk8(J1VJn(?m0rR zeVm@h^D47A9tTo4&epRXU)&MiTgk>O?M^5*!e+=~Prdgv&$9--nuX#V<@DUP$eh~* z0#)LG23uN=#9^K+N6DOMc)%WSW}1dA#?c~K&Sg;u{01T3_!h|L-M6RitG2w#R7p=Y z=h>ov3@2|5#s2l{Q{=1OyZkE3isFDV7kjR+}n{ zCt|J>!Y@=LKuJJ%H4h0IrW?(wuL3xi980~SWZ`fvEoRc>+t&QdNZL`OPPO r{x z<(G)2uGU!8aDOR0E*(mJjO zAF>Gf%<#|eoa&y;s*>;d+b>3VP_y|k@ViR@IgDS<443k)WYx1hIOWvf8{Z`|m~U5G z@BeQop9V<3$MCX~2+n7#7p2QmSZ&eq1aFpoT*V@?uF{9 z8`({kCC`yRmB3QeSyWhpfYWCDy4fYL*<4M0M@>RUK0tw2zwLcLGv;1z1^_!hvzPYx zFw8$y^`Ud?pz^o)+me0wlK=Z7akyLB21%|zi+!{)=Tr+&ChZeV=lXYUI6f*r@E;(S zzWx$0xHIe}!VJ0g5idJuX6t4C*O`H&><$(hxa{?Sg3=RF zqa5A4{Kkpc=J@!tsJb)D}0D#8;TK>Cgqtt6E? zq|Jv+Tik-~MAP1~6vL{cCghua%>u)mYLXXySYKhItWfG57H!&vGr~u)K6r#J252zv z>0l9}j+PN{*iY-SF55e*y~7~<5)d1=Sk)J*zS@xMzAkrBD%Q>7@3t1YCeZtDQb}-e zhw<*Jd;8piz6nVDy&{r;*|QtAeUDPHuaH%!5*U^V^vrfz-52K%Wf^SE>`N2+K0W;E zw;lp#)+dH%8C@(ZAi!`Yl`ij$v^v_30kBLDXQElGt-#bw35bD%?5~|>j-DVpZi}jO z$vO>6ipTp3ww5UVxd`S-BRC@ zaNKY;NqSv!I^^!FV-I-%k5ckkRoG2wi2+s$2oSMU#)vUphE2_ey1?KJ0&;%!;)WJ< zhwH^>t1ttDyMnm~h8{{_`~VsTr$UQ5a*xA0EEOgos%dE9{}Rnz!0HX(j6kG5ma=y#NJC-Q!d4R4u>8PXsD}9}8CXfFw;*`6|OrrT$wHNGr;xcNjv) zwC~A@QJ{^9*W0H2dzHs+RF$-%2G39IeUQ5DABj233A&nHP} z4cV@fiLh2@QI}w(yRD_1xj!4D-uIWAV72u$&^TkOk*#LWF#>B-+*AZRv2RFTXCB(U zy0;94VpPaR3SgR(XEfT5WgbmZV`&|K5~8p+!tnefacF>TmQoS|<%idO)S2 zlL2bR_&+p+j9NOGnSYfhKs+c}R_StNH~{e`=p!}5%fP`s=g#w}@*V&1ZOc4e!4mR8 z_;j2|qBx{{6U;0r257z;w$)M39;zmTpA=GT@Onl1ecvVWibgn`0VcDMON}DaQwON~^Z-H#>qiILoJ)cf`xt9%kMSuKE(zynzNpH30+Q0TS#X`)5}CkB~>^2^2H zBGa)-GIAD+h9CS3QUT2js=3UK_$1NrgIor$NMq_egsIS&@ zxU>v+QL{zl=9hIvi+qu`>^a=#sE8Ra&5{Ou3mD89<1%kf�f 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 z�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 diff --git a/crawl-ref/source/dat/tiles/title_baconkid_gastronok.png b/crawl-ref/source/dat/tiles/title_baconkid_gastronok.png index 5f635ccc9acb9f3417161ecfeaf2348ddafe4d4e..fe3fa8ee0f0cc884a7f9f2615ebf38b456e15283 100644 GIT binary patch literal 45466 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�W^nW=LNm62(MU#6zqZo+KC_obUdcdJjfPbTq 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 diff --git a/crawl-ref/source/dat/tiles/title_baconkid_mnoleg.png b/crawl-ref/source/dat/tiles/title_baconkid_mnoleg.png index 662e129d8ca43d6d7659f45b9006eefac21e41a6..71be971fc058d47c5b9e85406f8a6aa872fa1b74 100644 GIT binary patch literal 82902 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

5jkr#^BS>4R&;;N-810Tyhog#AN90Z@?Uk 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%0AsWX(gG3mgQom7F2H%_gA#Z@uBkIj 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%0AMqG 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

8bEgO}f#Ycit&w7^wZnDv=ApfA;tR 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 Hu0mjfl{&K+ diff --git a/crawl-ref/source/dat/tiles/title_denzi_dragon.png b/crawl-ref/source/dat/tiles/title_denzi_dragon.png index 740c841b17b9a0a9abe26d43f8d1e88a4e62b27c..2ddff51eda9be0ae3032282d1659fad79356c797 100644 GIT binary patch literal 24423 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

}?8@cb+9fsWCfXLYrRLeVLjhZ3o= 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 DCYA$k diff --git a/crawl-ref/source/dat/tiles/title_denzi_summoner.png b/crawl-ref/source/dat/tiles/title_denzi_summoner.png index 4a9128fe7c97a2cc19050382df8935edb85a15f7..8bcfc74a386f50b84b71378395426c7eb756d2fd 100644 GIT binary patch literal 38315 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 z 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 LNkvXXu0mjfb`>8M literal 43909 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 diff --git a/crawl-ref/source/dat/tiles/title_denzi_undead_warrior.png b/crawl-ref/source/dat/tiles/title_denzi_undead_warrior.png index 9b2fa9e5bd8cb2bf51feb1a0392e2ca729153fce..96a182acc4d0cecb479c45c2fbf9d5950ba19e64 100644 GIT binary patch literal 38159 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 IM6N<$g6FhCp8x;= literal 44233 zcmbTdbyS;A@Gc&_IK>GL#k~;Rq0kmB?piFk2G`=&LW{e*yB06*!QCae>*e$P-ShkJ zo_o&SoNP8LZ)WD5dFI(<6RxZ%i-`tA0{{S+Up`B#003}lZ_l6a;NN-(HY5n%UJxxL z6eIwE>R9wAW2CqDRHmO*6aWBEdH}%x2LSN!*5$ts0Jw4j0Eb2ZfM5~;K;)3t@=f?{ z0LA5t!Y7nX1SE78ssh`h$hR(J6FFIF!0UgHtoFiq0HAdAi?oEA`{J<=io4n@^d`VX zJlY4bFX&423d>X?LS@EUq8*o@+5pLmAyBJ|I${b{!SkCS97cPvq9?YM%Oj-o^-}b9 z%>tSXIy&|l`+)OVQtN18Tv+ucE!o-p6tX%Cg5|_9t3NfezLh@`FV0O!hKPiO=EQ%b z-Nq|#JH1FRU5$*5Lma=opk}$)9RV+W_d2mbug(_js-)KE*T%-h?=ZI3&ZF-H(?&DJ zU$$OTLHldT*g)E?0I}&8N0ZrlhPhP-r|3uyEOfbhuBfAdwzY%Ppi#dyjoV(G)hG)O za&CyoovcacTI|*Hv%}gN-UH?9!QmE51zu1kHoBZPchrbPpl;Z?nAPhY_s*)R33o-y z%N_IEQYLa8!`oLUiu-HvOhfFOXP85$X(VkdTl4Pxl=a2io;%pT6%z(v&wP|7 zFx3&&zQ6YOdRB=ak*J6HX}ZPD?ZeKx{{1Bfhn9m`S2xT3e~UmpmS&t$+>f5m@Trcg zJ4lfg%v!yv=Vb2oU3i7J%Z}#uk#Y+{5S{v5u0+ao$A#u|3qrz#DI2sdPQ{a))bpBLZjLP$ z5B4lKlcn-Pw`Di*ZMrrdZB3zGg2;W%UorJR%<8L@tIR$F&#&<}>xP5aPafL_9Z{@L zvPBs)eoiRQBx?s(LyKMvbKbBGmQsy!;9VJJh_Oxo( EbJFO)O?UEG`x9yh*mjK2 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 diff --git a/crawl-ref/source/dat/tiles/title_firemage.png b/crawl-ref/source/dat/tiles/title_firemage.png index b4e16719a13c1b66216cede56c027061e0d09a90..2a996abfe17ed35b9ae9579b49b77fbf46170653 100644 GIT binary patch literal 68671 zcmV)KK)Sz)P)ETFYfbvT0##Y8aa?!B5%aXPgiaZ~*YBr;UQCXwE=9 z%vJH(3Jl43&KW<~4jJKhaAQX}Jt>}ElN4H$9HvW+#E#lv#~iTZ4iInv@ad-wU0MV( zQ9zK<7RiW!fNMJ@CPvRH=QHs^Ok!|#a(MYctBOOm6^Csh-~iyWOdCu>aCM!G2dpZN z*i{^{g@9`p&nxE9u>nkcAd?tcw#TA;pLO|OYX~?1_$<=~l98^Jv3$2VGO_$%J7t7` ztDH|p`BO2dtRW@aI+yOSD&1+>+M2>Y1_MC*r9jgL8U4D9mZiHy8QTa19C6o|y6;ED z1Ql-VRJ6siXme9FH8esPF8F15-hK7MTakD66+kt??Z+WAPBku>~t?iV*-U87?O@n+qo|nyLQ)SpS zucBRDPX1ylu4@yGD}KG%%|3x7U+)3Gf*K+eAzk;Z^-aDgVd51Jk`;WMl#iEkiBdjU zK^=6Xj&?!l|6V@f?r%TobF>dK)m*Cl-F@RONT}H0;yvzp8_e^!*m@1=&>|V50!0}i z;98D6w6^muNtiSxpQ+-~xbQi>1Yd>Uw-SevXY@&oiTc#T@Bq&{ zCnF!{Ol6}Y$qPRCv5DA;3D~iTRY%5Q$0y<^C*tS4a{um__pf>0f9CJ+hqy>CLCU4n zuE^0YWJ3;mjYa>6J|^X|>>KIcX$eNt+9}dGjAf`s%}h18He8$ zWXu(0G>3p|p76lh&MTazOO+5&{@6|LsvBNaH@(o?itCeVKc0-=_RU`OiXE#8ZyRf( zTZm=JVTPqLLlUFx;7?^(E;Dn(%)HEuVP;O28I7_WDA)o!{b`wZM{&tDEWP%A^I$k0 z`Ochk=1P3>egXM_^Y7YL(aEpOeG0kaUL1ZCB zHb!Le^HRh=ns!V8b%4!1I0xvG0fy?3T3-VTi3~)agF!$_*Bb|Gv-C%we`)bZNpRy{ z&wnktC^=4bqnqhw5z{7NJ8<1;o<0F35>ZzPy?9(ga+9Sa`ur1%M>2vNw|f3-{*{E^ z8aC0@BBoYCJs(aSM)Zf#maU%fxr=Py>hG~MN1c0U(VHhimWNo60Mkz2H4AKxt`sws zBBoBJKjNX=j}rU&LEh7C#jxAb8cn?QR(9U+oYGMf*_ZMIE3@Q`p79&82AxY7I58X4Wf z^^R$koO@!nE)^qEu)Ni%iyO>o)2H=TulVA#4d#JpWA(Dp`+^$|djTJ=2m$!Oaf~CF z4hWWu>9a8>lO6>-hN(=oOSHKNQ7A}QWjpC@W5!J$-=Ez|58}p_a9t@%6bqV9dpR>W zdO&6sBT>xPmkIRc*A4DBnfK8u=G7>}6G56{K0e=uc^vteJyfrh9+0!c(VBcjTZBQ_ z*HpC3A4V3ynBgdG0jABvw7DG2nZZ$=Qo38t^hawl5N!?y0YF>YfyHcs0Z6w?m_A&S zjA+xb(Tc#&KVD0<3Qe7gf&;VSgux(q>qP)ewThVz3EKl;o;D5Brh`aaZv3r(n(8AB z`GJ~K2tLzh<8T^sxTd&H`078Y%1A?UfMy?p-)fT(w)G?I`sGNbT7352dD=aE?OwDv z-myaNT*GDi&(J@O&qnA^1=OvYeuM3LyhKJGb2U2=%`X1KE8Xp-`>lSH z>4gYD0$#n%O|yePniBB;w^o~;4L80bE7(3GHvCErIq>tBz+2rQr)DSrFX{*O0>pqr zBBa$F_0S#QMF{eebNGnuLauKuszipKT`uXkV*{?vOCuRyLyAEY!)Q zU;qD)*V4U;kwY22Jt$XZBdS~!!oH>t7f8QQZ#4By!m@ZAEc05J zP0n^P)g_~Q<;qka{OYqrt%tJ8!noG~T*#jP#nVyTFAmK|w<=t+o zt%!1~14+Q)$oS-PfYHy3KD*uRv%8UrMw#iEh|O^!4r&PCrfQ=Lotdk=cN7_`>*`zmJdJHuv*H#2TrD_j2 zW*!{2&vyt-Jrb%PSElk*87Ksx?55TR%Ny~RVM^Qf+xO}Gq#03Nxbielm5eHrP{)^U zh%hyYfK|XzA}%a~?HJKPY4W@Z>>W~MN6(#%Yj zBU^GZfrkb`h9TKJ#$OFuc*hVlpKp~*_g-Pby^)&vg5kCs@K)8(z1u(&8@W~A z9-RT?z>{NpH|bjPqBXVfGu%0Cu+=)SV{C7Uu4O4kurTZXzxFOuDve5&sW(5eH(%F~ z78QhPYTvX?8?3SPZ5Z2~jow~>KQ53W`3puVHx1TWgiOM-40&=92K#=E^s!zkGYwW* zgfwDc-T1*u3luAU55HR@eWt=NyO2eAvXLj}rV7q=G;R2zU8yn$-irS+kAfDqJ%YmC zZCIXMYZz=aebs91DItIV_;}wZ4{2%`xY3}rnx$&GXB`D*_#`trq#sVq05=XiKMriu zQW81{n!%tkcSZt?KhyVQDu+~W_v{33V^6dpQx<5Zd!N#M`E+FK#yEU%j$998&($yj zIa+Wy=N(HM?oO3YB>S2Zg=diG*+`ong*vX{0keGAsvMsz?4>+UM#A_dHuQ(W!IRUZ zYuIkevnSHCOT%!Q9cFpIRXIFa*g|=BM#8{P-E5FM&C32{VLjRR)YzV#IP+<6i$QL` z4tqB1U;v1T9BY@G&Av|`5mu9)HE3~sn32;2hc4OVN~7=XM}&ORQ-BuZGRz-O|M}cP zrP}zr-M2#-@i~zb;v%ri8#-^3N)5i(9_F(sVF@+$UKA?8;-^XSXADfur;tKAI+YcJ zEjaPxB>7WDDK+tSvbX3r-Pv0I;x(nu8Mt_Kr;)-^BxHqOa29&(zvU9C!XTHM`ZteP z>vB2u;KZ;5wdGam<$9yiY!(WL?p0Aj35ESH(<~GIt&~Xhdb!oq|I7r>I^$!DO4<8D0V3sx%@KWD@*nBMi{_;iX-qkbJrYFJQn`QJ|z zKVy7vC%EkdpF%xvfz82T?7~z&uK9%9M)7v76hdfztd~lSuEhkOLGdZ!_fho+ zGvV?LRw$PnJ=wAFulaOzOT?I)DY!sIl2pUU4Mul1$rmEN1iw7do%8eMMN&QU=l34q zizztJkNig6aJ(N{Oj4Vv_u28_E@3^={4j#S+}8}Y5#i7Dho_9}ZG0ly)s#Vbxv!;6 zd(DCk)@YH^J6BH<7Nb zI@fjtU?@yFWOZ&Jxy^`MuVFa2i4ogO@;<9`H3_5!2V1HxNo-=ke_cfcw-Uk7FdR$+ zEVrAw3JI>!U&qQ^1T_umu%t}v|P>b*)d!Oa%Bb!s_pi}+OJzCd*67}xrpe>h8bW=@W*X zLpT>uT?;h~2frN;nkqb>a4u385O#igPGx-4K3)8jmdcne8_A_0SBj<O9HE(yVy5{X*AAa!iBusO4T#XN;Y%`<`aoa{p8C;q;HS=$AQS2}~iV1c#9tO-?ofxQR#1^9?k8~CxwrE7n>O_A%HpS)yM^2rzJRwj;drK4i6*LU7*5F7b*(~JDLP3*$)06vk=Tv`L zl32<(?4)Bs#FYit;}H{0=A_*#oX-4f?{cNy+P~*6$J~gD8M@f0h~ThkYTdbCHBIq< z2-juwgvGP&fRE#R@5To{q`9=1E3>HovvU>DZ6wP!)_}vzENe(CbHL1D zX2!>ii^&?oWM-MeoET-vk}bt~3|UDdcHog?e`c<+^H+h9zQ4TZEY7)SVz{bRcip#W+`D^9L*2PD zPm#iygn|n{NE@!fxr)S|a#>Hc(zFtNunvE)0q5ck{C4il(V0IA`}Ze%`t+%8wexV9}GcYo_bD=#z8f5{UfioW$w#LueM+PR92r| z@^7A~MQc!A?I^XJ>Kf4Lj~ zSGtV9>PYWxOn9sgwPg_x*N!WW8@+Uf_q2zPAsld?lQ_?b-37AFr2_Cc05ADkabmwF z&3Q&_`H2v0t1}*-Iu`M@>a^!j&QoIdd6^*^>59R+V!bhak=Y|e=OV-ygQ;TzH#p8N zPctwaPl3EM1~Db!#$@k*I>3PWG&FHL$oy#cRgrZ1wIJEep%bpyxA+AfgJBC)$n z+L4SH(lJ8@_NKwv&XJBhv8zyONWctn=)+AD%x^7t^uu}G-9Hx4}IhARlKQeS5w>5(VaWBqN7oaJCZ!c$}+1(y`aS-P z!&c2W8l+%|y3MG5I}QLY53QDQT$Dmg&9V{N)dKAr^rMrU>G8AkjxB-Z!(VqVchtz7 zkl-pQG;ywag>E&f-+=4a`-oXaIm)>vPPZJ@uf_qu^63sGl(SOu@N1Lxt8o2tjG5^r zdrK~la1_(7a)~Y(>BzwJ8T=*pi`F&&WZrDQKsoYgSBXRykLZ&zeah?P+tsP=61n3% z?KsE$>hO$?r6|;J$Ruy4HZ*JVMswxK>?di!uMW-BMWVWB?0b^eOZ4aMYyW&J-f@yK zEuWx`!V_n6!}Q}>>`{?DhlakaU4iJrF@T>I63C8YboZKx95WQ9rw49HT(nFPj0G&) z5H}LW(h-f$o`em@;B4mzN4_^B9m&{7OVr?z__D}p_p&68LdsbtX3rAcyC>??vAY?; zNeghF0ShTdDJL*ZVvsgnpk4lwXyg7@v=5d!DkRP-8A$Pk8kg~?(JR^t+EFcW*2sRJ zxzKWkes*OEJZ|y#zgz$KMwG2maxaU37s1^Q0jmMhKeog@H>TOEC62m*D%&(rW!roN zukjWma5^|z;Qv>G&#l4P>S)I$iSw#VvmViI#kHIHbqxEp|HN(qgR|E{cP7)UMYNkR z0PobZYRX*jPj<6Kq`j1G&%m@9SZNZ^=}HhZ zdp^Wo00qFbM2~2T32Iv!^brR%ofbQ5P}9Aw$*|Y~g9A7V8O>ru8;1d23pjVy=>GOJ z`zgwPnsS_@fAh`Rx|m>1IC5}45;B*+tMa2c*hT7ZOSR>Y_G6^u6!mc16iq17CJovx z84Ek#K!}Z+!8R>_S{==PKpNA=7mD$5BL)856Z&QAdqR6A={Qcei3J)3+O9zP=Wxy# zIEu`^A7aZSHF6Y~CCZV0hcE=cz95CM*pHLHJTRj@4Aq8X-(kS711v}`eWyeGWMuG4 z44>RnqvWz&!kD&A(57IzBs_jD##;z%J_wA4z8<#W1`cK}{Yz^?e`gw?w>{C*pyEVT zMt@`FfM^RjGN;DW0W~i7A=*;Xu4Xt?h;8Kz$R1#;faQgx;s>IS(gk1JE5&xT*j_2I zS4-h*C?DtLAyt|GVuS^IUsr1X!}R{2FZYzp@|4f%DVzJn>fo%^qz#(5E7InS5iP5O zT2{g@yuwO_I?v(i{4a)NO9jbRGi()OZ;-aGL^NwL%{u<6x0I7W<52z*$`}^X%zQZR zo2p6108_^Z_yQiXoE5TpBzuAI)GD7|i~Pgw#eZ&$>(iz7b)*3P+!F7uQdrLlo8A)k zX;ZByL)fzwhB;4(1DOiy`t_poxAKlxS*r!S9 zYf0&A2vT#?v z!j?t;YVXVop`#Z~MtH1^&*02&FSH&Nfp4~uf;I`-Dn9nrizsAYK&KdpjdFLDL0S%_JaGZfC$JcFm( zH1W_UKkrHf{8^Xax}vg_i5icIdcot$2v$wQ=SEW+(!3IDUco>0<`R(=rnQ{57E#s` ziY=k6rQ()j;+%c+*Tqi9aPL+WXvJJ00uFp?HO3$B-|`{$+(JlpsmeTU6C z3%EWmmuyl9nj_GbNR)R6deWqk*?U5o-lDC?No$VCi);X4%_O*c7WW04O=_2pZdPDT zQcO59C@9EBw4K7HAJdkjgym=m!2FKzXWw0LdCSZX5+*H~h5>Ep%U&?J4}UV>@}3Ab z*X{`gO%&Ql@z3Gk*mgcHi+J?I1&u%>(WDvpFxoe-UxO)IkA`qlkr`rx&h)Ifr$qIn zChAYuVxPCB45GIs#gY}m9wY2$s3s}WqQY8L7_Y%WMyzL`vnCsrTt)!A?{Lxt{2zY1 z9zLkp3!?4=Q<|5c&5O}JB8(^CIiWR=fb3iI2~ZkaKv)WymMl7F&%AX@UllEo&vR)-wF1-Ik(wr$Wzb`Z&5t@$<+&|#F+X8n$c8DcQ2w+c$?va8< zDGCTc53eoLK0H1j8umvy3+{&^jgjcJ#lfGHXaf@upTQj(C`OV871WDDuA(fJVAr#X$9K60{xsDT;O>fda42^2TtRj&bzj#W9P)uFnk+4;w}gpwi9`KpG$|P`S@)B z!2@upfL;>79R6wVP({fn39r4Rlh!&z{3I>=%T$C4##u1OVJm zMzjG>6o2IgdVLNJE^y5Sl-EzntN|bQdxM9o;Qq-E_LHB(PtN8(&QI~rQ7XSQxK9ef zBLJUh%0Je!{~vbh00RLq2%_+8UEl`+(8UAjnk|nI0wUw_VGV%wX3FaZv?KsO4V(;| zBxS0c%q>^$9+C{)rtO}rOeCo%ZPcwHaFPt%$t>=Yx=Au{6m1bWN=M@u+1Fe+@VRhH z#lAm0i-G$u>s0v)NS1I3#ETaRQ@nT{ zFNj$F3{m7xfk^fQ2qOa=htj}NFnttA9R&@CfuzBoJoF_F{3c&~AMnN}-k9*j#-6Cb zjmXF}beWvtp))jaga*bC!9MIJTcBqT^lb2>YXy8Ai?3r0;Wg}e+k2k&u4g(#YuEi} zECd^9>}B!Fp}+(OhfQ#5g-a50o#3)vhz#9^ks*pPJdnGdPy}5Ne*y=fR@0&dQ#cao zBg%^~GB^q8E-+NBVPe{>m}(zrs8Ee&!tA~|tX%0-WU9Eyn6W{ob}Mm0<5p*k$W60{ zVhfLue723OmVqv&Nq(uCss8=D?6WVvIlle5+JBus3k+HQH}(G?ocOap|G|C!)puki zlKU;1EQhT9@>`nGNBOXCQpSa_QVV@v}EWTb7k8p3O}kGfoUSOKkRv>vtKdQh7< ziEIb5o7h28htmeN;vARjKI`(0&<7S=%4-u;yB#2DJI)wm`nOwU0NG7yt4MQ08Dj~I zF}-8K)e!dqqUkv8$4PL>#gh~NficE{TNMXoBjmF82$6jy1vkLiL)D^4|0mxV3$EKJ zS4LC`?v3RH`6MLoH4y( z!6}qUa0i$Q&%_q0+G=ELDeoRk7mK*bn!2*xUvuWNzK0*`n*L^A%~)_%Lt+ys!R;W? ze41o4&cRLFcB?=3&H+}Etc&A$vGHLsHlMM!qK#L<+P25`JlnRdZQEv5SKHn14dP@^ zb!}?v-5O6Y=;WW9&Z&z&r*nUOPD&XF#n|9OXTCGZb@ zzI|7wJ#$Vy6Ljfkxg zXm23`e;z%=;ZUTza;YJHmfCk)=D zQGq$T=yBQz^qEolW;H(Ms2~44G^_DXD!r2m&wn3W1*59E#^3z#+t=U!a#Z3Omw7?# z?^D|~1_bP0&}9}pMjN@t@Q~O&BqnYu0=u*Gv_uld)(r{QZQgp_A&tEg(0_<$%qskM zX^AZ|r}58g0?eL2?>WRXg*b*F2${qgyvQ*Ic%~Kh-}W7r+9D!LSY!=NNi0vk@Ctp% zV57w-&HoB!V%@0f)A};dzDwu ztUw!e6jHnyHHj)_fBM7eibjPqHZJ$<$jpV|bRS4$MkK_T)Qv2mb1w~uT!SKfP~_UN zJBzlfUCCa)tDo;e`X4Q+2XJ)ru&ujuQu9NTu`4HEY>RbroZlQMMfzV`iyC}V>FeXW z9$dBhx)C^D)&MLUk`UWiu7O|RGBVceU!GEUrD^1Cu%BhrenzFn65~?Ou$Vw#p~L}Lct0OQM#&uU zE{+p`wQkE!iY8PCu|3wh;B5a3?Ju-Mx;S{-yn~)U@6jhGCDvhy=l8Si$fDO1tP*XV zv$roeL1Qv6z-~g}n^gFwResQn+Q0Iv#(=_od>nNROZM~e0U?eot#KuXMZ~CtVBV^^ zZC9qjvpgnqPbkm;8of)?N)Pj&qv(mJ#0Ct0h_m&5wDGo-RvK`SMF8VyQN<~h!BOWQ z*xA|D0fz$d4m@>$+%vdp?K-GHN2NsfqTz}I)p(*`fDN+tGbOn*)|mnpb64-qEfAQa zZS(f8_ZFkTvPPR`?Je_mWCQce(fVm?!;B5-&oxJ@CoMG-=GsZ?por)f5PbrCZ)tb- zBTv)5+-3wGUb7ae-KJS<^@xhuUu285%-Px(9cGm9#eKu99f&T({cozxISLR+Mn1QtyJ zGQ%1dSqFr~uV-4>yOd)LSC0d&EQozkA1)s?RgRkx`@B9>I&3T-F(Gyo0k;}~4O_N% zOv!o$M9sK){nkuo1h~dX?WDP3%DTceG3nZGXWH1Si*3;q5bdwN_31}n|5VpIwV(^G zTDumCT!-}LwY1WJW1nQ8=mw(8RXEkKJ%iLnMjm%X!6BFdTDJX8 zW8C+9j`B?5S+#Fg?Vlm#n^O5(CY2w2cYu21|CJGDi8jtyo9Ap-JjykN$@FT<0?dNs zrBC33c299v)>SgBSzV}jz*stj0&7|mJlCf$9xx#GNmbxXkM3-r{%oJFan{j1?`WE{ zH_t)qfJ`vE@bR09z{fux>=U?K=bfN7(4w<#!Fj$%^yX)OvLgUrwQR^(Iby09F?DjV z9v%(}8o0(z9_jNQ5Ql~tE2w&0|IRlDDLb6=ZJf2X&Z7Z@v$sIQPLAVm_RauOv$Txk z=iXhi5o;G&423BM&;k_zERzaDf{}^_f<-_?%3ukD2tt5Gfg;EdkW|0|0RaL4)Zh8> z^E%I*&m8xg{mysh89$$MzkBa6^PcZ_p7(v8=Y9E`T5V^e1s4H5AV!;EmP&CiENAM3A;sY%uj94BF~WbgV~0N%!wy(t>c34lvezvX=L=lyP!1T4TA!GSYVlxH&of(vU0Zecgj zYln>Bnx^mVu;1_v+(E=CDsA>3OmEnfYMF=>!3}ofhg)sU(dkF{-q+v^;_hL$VXMoi zP3vhlSzmoKeCy$F4o=_XVW*>l;Czk3*!}I%GzFxF-A)TmyBXz~g|J7p1=qCT4$J-z zVIYEw-M)Eq8@uI|;$D-d=1=ukSlDg+nbB@7xaPpL;C4MK%uG>IycQnLt8ZhC$O9P! zw@5531n2Tx3$8gfJjL@GT5!8tgG=#;r6G~p!tS)H5?W;y4+KRl;St7VNE_MSnmr#xh5_b1>-g;VaV>+T8*Bl1aR&i~* zr>GZZEb(=U8h?>th|#oLd*RDwA243vyO ze#W{vGY=pL&cQad)PidcAh;5>!Sbw<7Tkr0%8h&jJ*Tl%!nCL@;JCa71Q+*N39RPm zZNO_1yE#AYGRSMEsg2vUQVMod5Z8jU(3gYj6Tva})Nw*%!+1UepNyk-iO3`5eaNDW9YAh>Eb1=po;%~1u%@{8;upVoq_ zBNV}rMWxf;1vtQQW9L?|K^4J;#R8niryl8n*0kV|*9pftUunU8%B+Uj^l90M%DS6& zGu5Eo>J}rQ;A$@_<9+R#Yq~~6PCM?B5A}}V+=tQ>DiIu-8!JV^SnEq}0bWLM7W(!q zwYgsEr>0Wv)`Gj(P_Y{7z{Ei$8LWd-Z6NuUg41!eKm@>@7Plx9QEe@_*OQLm_O;yHWg?zUjCjf~zg4t7~xGq;(X!4(>{(s4Y0{#;ID5W}eJy`}vzw>?Tf8bzJI2Vl*bF zqu_)uUE^!79fKAewBW8_ifSe_c-G8^MR4OpRn6rmqp*s0lY5Tw%(V}E({`&tTrb1z zah&Wwb#nSR`<2f|i{MUV8xUMtQ&E_(9tYz5^!i7=X}hfmt}8`$nCHH4TLL`{^Pw|U zaDw1sH&0Dn^e}K;Vmbxaj=M@)aB2%`eXkeHhvYIhd<%{Ok+H!(w#sYd6_GJT4KEa2 z7T_MTv&c~B8`dJYXtWB>Ct*A8s_6wdw@3=P|2;bxT5y*cCq{zCEYD%^v_K*_f;hem ztie4RPS`?lwH>vRJK(ML8|6AjwCO5e+JS(>GY7{FkM;}ff7ybIp4gy#6r2YJjaNw_T$eRw|#$9{^*OpuHDKN?lpSI(AyCf=mAI5I8+R#}* zaD3^}sDWv0AbhKW6CJme6wvB?57Tor6 zBD$t~A*xDTmherx5x99ByHOf~-~t2bEES!tq2pR`$DkcI<`!~?6R(l1!)wlR2;%P7 zV>1iqcU%jO=2He^R2z&*hM?dG-*jA!;3_W^+KD@0vQP$=acHR-~wvng8r>Kx_ww`voluH3(ijy zzAXe7{F42|>bkS|<$2m6I)d{MhFFQ`4~~n)s^E;{0?Tlz1ZFD{hmg7I%Qy~n9Q%v7 z{u*%HXW!_;k-gLNQ(&+E8pJujA%eq()m&$8hv*0nNB}W5p2m<#D3O|`({4h7l{N;R zRM>4*aO+7`1P5-O-a*{{>G`RGLtF0;L7X24SE$W1xLp`Ptrk9m;978?>4 zy-00lu+|sBnQ&kr72Ij6;LI_#$aU27=6Tzu7zl3&N+pW%cc#v0goLB%%R8b*iu_m}HI%RdI14b~F*Pxi5 z432v`8|}B#O~?hWc@xJO!QryNwdgqT^akw)fZZ-7I2gbD;a9%^yxDYyfspO}a_~8C z()eg)956qvl7iY4;c3F#4q9!&L46{*&p5GFhK)^=61)BGjVWL^$d?J?s0t>vYUdVf zs~_ZbU2xjXLklHdyX@d;G~ZEhzS(s6RwpRqcK>xZ3YKEL$*bT%yFqo_X1lfE2$v8X zBS&{?1eZa|Vw{27v-#rpZ%!X)qB;}D*^2L=S|#_e1nS_(g@xeuFn(2MEx5KD;GofN zfa54BWz&E6q{z3t&rOo9?VV};mZk#*_fio+Pf_b0eqWpeD+Gk#*k2^|ZjoAy7QyB9 zkJI#gn&P;;iQqi0fm0gzmB+K-4AF%UZ?VuIK)CMswd3|c+YM;UB4N4^oZ(yGvlHUG zFAtk3anIK(U#W4NAjeKJY#TyrGN@O4FbmGjFWFxtF2ieo&Fc(7+_Rx*?#WEl=5d1g zT@$RT&4|4U4zPubnjYGZmx!|L~))LlvBF9*?$L^$zXZW)<=Zb}!_%Cp#A`Eubz+Lsd=+&d_grhM@%~ zZ_i^ut^i?W5{lqRGB8X1*X{K8X$m+lKf`Wu04%^!0F2kT8|v1WaU83s4Bie?sQ4>* zv9Q}=1=oTrrMB+A1KLf&u}hLqcc(0L?D!O4V_{P5cAoI91sAV{=qZlN3^Z!PaSWxg&zJN+{UcVms<(ix@Rm4czpa)bQ=_g6pL>;whG=tKEXL zR2Vmfb*54aL{4|zFRH1!+5S#Rq6|_b^_X4ZP}}^ zd%bbw^UvOyup1q&Llu{%{;aFTnK3f{*vEVSu3rzYOs?B$E#*bENGtqD%MNv-T{!NKMtI99E$BUvm4(|2KWC1_*x0y47Uc)1ym;2w`kU?k|%BF})`{_@TguSI0Jj?}Olc?ODp5gf0W zE)dGG4Ck>Apy0xO1P9e?sx8#-?%8h8g1e*Oc=q3?h-wy`9XoDkEgH=SxjT+5ab$sjvg^9w;F5wnQ7p1sc&HG& zvEzITZY%Y4O(HUj*mDustiK8_5YTBiV!(T46P*^^EAL*oH}4~oLCUfMOAL?aWjN9c z263^Qg3Bzm3XXL;_8k$r9rCx)dmk1hLMFxUA~;j7UYyr)R}{NxHwBjwX~EsmarZ4& zw^MumyeyJt04Q&Jjjkw_bRxv-PJ9)M9W0r87Ib!LuV-NwZ2!i5y6d#RMo~sqPBqA0ukIJ=clFjer>xX z*r>KM+zQ|L(&r8nzCkQ8?Wy4YtfL9LC>>}a$k_OarOPvf|IiZaoCNEY+PqO-u1rxCMS%0$u*NIm1srJOs4l{AJJLKs1zZ+Pywf0 zyd}k$)$XT`GIoBVebVg$aK;qa2sO4ej3b4L5k~+HaIffn2Y-FE0SO#!RpAl)$j@e%yAtG3zNZ+zv=8{ni{1WGPL{}f$V zaC@X1Gc#Y4OkL`G3BWbF5t6f@-BbhLFJHpGwpwfdl>irOQS%?oS~<)&wqnSg%Qqo( zGs6Jmg0N&20yxaK*F0eJhR1GR`S4B7D0oNPxY%(R?QD?R0OxA0h`*s)WGh>qqPpXx z$j(gSDVp=^_k5UuL)lLYK{vAvaO5%s+;mZ+HF<^$Z4K;FGUfP3r1L%OQ?q@f#tJF(#M zQSQ&6>{ySO0V5u9$=Oy{n4tUYA|`ZxjSItL%>&d&?L?YWf*n>?}xB{zoKhDb8h z&7Om;a814ac^GkGPLYK;A>HrY>zZ*<+xm2XjVLJTNPz*;EhSw; zy4~0qA-x|+NJ-a5NH@|W9gTD&J*7cVKtMu#_x=O>?6c?DbzkRu&bj5++wGWKB8RDe zEIry`+bl-KuQ21%lw?3_CM7F?)kylXjFEx!2R`)VT_^9DVAXDEaNiGh1ZDW{L)wp- z0+QXaPJV`^u%aryv^{pD1SvDN1gAPUz}@FTwMfj70xzIxSHI#{y+2a(o(T}WqkwS= zx>{oGt{G?dG5PzeMfUqJAk%9({Hg_jp(+;`RVL2@HCwa-+TxAFLf!f32i3(VgoKvq zHiKOr4qmAf!I*_uFS_W`y&{o)I?Ypy@<;Yy!8N57&paane-(KGvSsqYZB=40O-GJO z!e0{H0o$gwbet8yVQ-MZlxM>CCLK^adX@REQt{%Uu6FoXf$VaB#PO9Nz%|bMC&DY7gK+6x$e)a6I_j!-71NtGVjR4?}hS0PbHADd|sjw_7oRR<+4X~-04RcP9z z##=K~Y-syzrV@S<>MQZGqzcZ?=V|2|!UkD*u&FaO;V){ z#IG>r7}K`60vcs$LG}9)ec@FjU#5UVVS&H2q2GdzITRW=nqAYl0cG@LpRMXx{=In8 zQh-9Ln!RIe*E`cYB7+4`VJR{rm@jMLhGq2r^ggO@z(0vVL=s+2`C0c7gta57867vk z@)aPfWXtuUqAq^Er_Yyq97T$O)B))%;6_||gv4aQ&~?hto4I@iyE6uVMFMb(DGl!V z^kEb=v_XB-8z6nC^82}f$Cm-ZL_KrU^>Yep9H`I7-AY^9L$Bo`iU>xhhT#YeSa6_x z5HK!NhJt-e6PHMcB|Ni}aXC2sWLv=A>*VQUOzHvPNTjkfS@`yd^%5#4kgJMq_T3-d z*riRrEn9pTdeQmhi(TI18)AncAkp#9hh6VUm_v@b3|KVVMA}RUVfsAmw+{7ZxYz^6 zCpOsG<`gj^A$>s{ck48qE!QtpNgBYM1kCaxq~-k7RdOFPiX7!mIMZz%qoiDQbJ`mF zc)bR3wrE0oD#g4Upa$CUKPRqXx@J_QSl zY94!0y_lU6v-Sb?zmY)%AQu0Ipr+PrL0G1N1&DCx`Kap?;SrJ<8W6X&I!Y?xRGcrD zA9%lYCO8#tJ>ClDS(~$8bg7Zvu!tPw8vAn#s1?q06=CV^pl>57byg$jRG>jt#Wx}( z>svVZc62L^7)Atzt=>uQSL4#Yn!e{Lma|1x!QW{|mu@GH8St-&|C%ebl?fmvFlUx} z=WI4e0-;WEBFB9%Bm^-Is#_prYtCid%}jO{_JUG`VOb!i)IHW|pIZri3FT<*Uc*uitHe)oV_n(#vI*Xb3gj+mW9^Ipf9!IivRErGQtA3ki78 z$&d)7*7Deog9s2!&+INGp7;=Su{0C7sFRDNT2ratPdJSz%caY5nbpbtVmzB^O6KKN z(GT8cE7ti5cn0zf^-H3Mv1#%Fb3T0Kp);@?K2R%LiWmA4P@Ga({1z^Z< zC4p)Tl`SNvi9E~84b{mj*%naiAm7~$#g!P*3^7T>mU{j9^q&<(D8;)?RQRQ=WaX#0 zPn(z}8EzphnBWQLqg)9jTQVsqG>N3<#_F7qS#XmWJyEfbw@ulf1mmX)x|Lou9AvgS{=J)T5rB1M(NaQq~>i*dRWsw zh!8Gj44}sgN$9Y*n5#rmf?WQb5JA7L7=E^Qd5zgI`5;N{Yn8q0LJa%H%*25L@)PWu zSwFy^A(pUxk(6wD>~^S*bVOau{(y?`L!WDUR*OG_lB}Eg&}Mu8CtA+vkJ9^o0$6p| z7M~t3&X7a4QI^S6aYIh7&5TSTt)|LrU<|^v}eRGl7Ff)SoqaF|8ici6Q5a+_>L#lj8S>@{|1z9$TerWD8eA~4TcwFM&Miu;P$i3rN3qicDaKE^AfKC@x*`gxggE;Yt^Q)dQ3WZ{q9PwXb!@py}bK5-n?T-<4 za)kOoW2JUItTu5obJJstl;;xN;xoXgn8#1S4bw9&-+^g8W56Qu6{r2Fg;QQ?(o>0i zldO0Y((}O+nZ|TDK)*d(!_JJy)z_1yM<-43XBNQ_4R&n7BNciy@v-yid6m@D&|Rfu zwdfDUW@{fx?SdRyN5iixMQdk(Prbzs3vXjC9xeGVVr5e~*n8jhisB@XiC15{ zAbD3zRNsqOZzZe}d&s4we6rCu9J;hNk$*S)( zPVD}AEf}>htH+^>RZsBgNINyd0%3ahfu8q|n%b$URzZcR54qX{3uah#g&lj2eUtCK zlA#VO{Vqc?8hQSUbI2Js`enB>!z*2&T;3|-#KP?a?2P*0EkK%xa@NnWIbcpoIA#G* z8`7Qc-sVWc;YhVz{sEDzO1vYk)$(x~XigfVcH)F)3O#&eQAX~0o=c}2$%I&?+9Xbm z&~Bv!O~$Zjo7a8D7uu^9V354a`0J>;zqf9#Nt}7mqvWy6@ZW(X;3uFzugNj(o6$Od zAJJ=z>d6#&A1NBI3-oCAw+TNV+ihx>Dg7<+)|>f<5nwEHEg|9q9n4w}*imd634Lyf z;5Z3uq6YEB-cN4hY76s|FvlhiRN4s*#V-j+BB_4t(J&KW=;-1^Y}-8glVdCI!)oT` z)e(RRn-jglpATS##iRa<0O5%AcsbyrzPfCNJ)pT%h|I$yXpzUPv+0L133|Sh6hU`3 zWO}*PpoOs9rKi9|Nt7KfY^kQ@r$eW~zmlk^zvyAz-$H$j6X{?I4H(mPeJ%yG;VqXX z|0R@wPlH@z%>_;Yo>k}NRvM@=hv`U7{mMZMm}tkM3_iFKt@hy3^qI4`vXnjLyovjW+xoR! z>xDphrt!_;!UGb3e&gsJca3=B3yY(wVQs+B#jal(_P&$Djp+!B!VY1I3ux4B$LOcM z=y43e?x`;QAe&Lz$umYY(iqW>kt?3(%a&GS=oI@3mr1ezq|DocLF%?s$gxICW{#dV zHvNM{p=L?Ae^HM;Y0N6$HVP2`$qDlmuVfvIKjlLF)7~I^F6J+g=b3MbAlHga`F(&lCH+hQd_x;ez2Zd(s5E2ee zAm+N`)28S)=BZ2$qF~RweMvc%IWz>2#01>O1LjWEq&*X|JFP_@M&?}#Q&ilvRMyFR^=3&&sr2i;E6_Ktvem_IaJHE4jlxTpTRR!pKmB8M^21? z-u#-1{(Ru5c-z&FF1ChVY^zQTy|5)l<%JG0hXsbJhZ=^)DO$|BDGb>B7GA78xDXqj z@v;6Vba~H*Mm5nQ{5FQ-xgB%Qc8icF5jxUV6Qy1=Ew?{Nay{$=Ny&|UiZ1#wZL3|hOaSxAI_=_X zYg`Vg`4KKnnT~Ye?Y{LCaHe_|{JkNfABP<`SNI_yQ#cv)$5=K0^7Bo^memvSX)?NG8hG?)jhkYn3!E(??Mh?tBO3;me|$Qx@b+?LiMgCp>Z zh*YS}ygAuLSxsnO+w!VcBe)ULblYY*Pm$vlWUKG7~D)lqRB=|U$o!N<#*@QYl z>(m{>R%10s5KI;$foCNZlv87=m82qVJI)L+i}0DFM@ZuW8q$i+c+n2toixrso))I} zzs}v79$-WMxrVJW%l}FiV>t^-_?2blyDcCdK>3NApp2w!b9y0ZOtIY9`ej zaetJgxN&DOdu2FzI-IEpKSgF^P#>k6=^9ZtW13|o940yOh-bKEi~TPTiDCV{qO*lh zjKnsGIs7>IWMXBs&FwE;!|sNpRx=fdi#}RoE}Sm|hd(IX3b@$d(G+ZtIIE(F2E0ux z?pPp*>s8(_wR1=hps3O%AGIJijXMHv)+w|67rMoS4j`3SePqy{{J_efl>%eM(GS6W zVTgQ511n|zs^Ck5^DYsXqXa!fX+XAZa;+U|S>d%yD)ZCpT$@aQGNw+GL^-hu-afr? z59_aUl5QYI984#og}T^cf+c;EdgN;=s0J>>!+M$h^X4C6Lrf$YVPdMX^;qi^FspC1 zQLgDGW|x06uk@(Y43Ox*1}_!fUEZvu8iZ@*)5$FpOQ1O#30^nM#VL^z3>#IZd}BGK2!|2ZfNJ zX++AD*c)7s^4i0q{3`EAaj$A+9H?q%hyD|d?QGaL@nII7f@)F=4-1qr84FT7r!un#q<4#Btt{9 zB=&@8;tkaZX!#`W=)7@9SQHR zPu|BwZ>9rjxe~plTKcn>>4nFK__O#;XC7$f>!N#}VZ}PmCe4eyy(~rU+u4fpcJ49d zgfNkta2n+3qai?|Bcs;*b0MG6FC098XgiLPQGl?|X!LGFY&<2X*LCN(zD+lZ612D? zcc~j`-{13WC7MM~O7i1vu)O7F$W_o+@6R(eEqLvU1*(m>RQeSD5)8)VW~$IRkTv~B zmG^Z|fe`jBhY(=_>yH2Q(_7w2O;mVjDX-_^Vj)hhtD4^Yn6>*?SYa)%W;6ZN$ym8? zoz?g#Ao0IqM-EfX=KrcCQ_fz@D9UU3YFRi&5ty8at^ttne#z$s`g*MNTz zUR7YN7E%}4{rpwoYvTG(_V|4@<+5u%g$3-u1f2YIS@EbcO@vvulLC{i-^GaQ)WE7M zRWkjC0-a85_WZD00!W@5CK7oW2GZ^FFFTJ0&4u5N8mx;UMwI5SU{EEGjX1Q(y!f5pDOIBH?5eA+vrA_M$PO*(266 zths+`6yK`uMUj~AM}3+LZ{cbi{mad&`J3iUuid_b6`pEFu3CLfXDuzWUDEP!QTnXr z;ljY?VhX-tS}frD>Ei0xm13nJUe#3>GmIlZ*4h8(&`_ z5D#=~manaY)>qp&^}gJD0%60tM>;F@>m_ylCCG*1RV;0?zV8w9P^VLXYA$h>J7MDI zktvba9uN~C4w<`rqi}Y%<^6iTUSXdN3ttB|7Z=Afz;;-RQJDh&mfJT9mOH|%a%Zvn z0KKO7FT&l(&wxX%cQehb@1W(=M|}Bh0q3sZO~{6CKF8;y0cm>Jv0wW`7%!zs2?~UW z!&HEEVF^!I8kr}F2HhVn#PV|kld}+naV?{-qRUoZV%sduchuH$PX;$b(6;kYxrU=Upm%zk1xH`bz4Acqb{oW4Wm%rynga zm2CN^j8LC3R*G~Po(fNZzTRZP1BkL8+HD<(mz8O{DqVthLfbs$NnA3x=FOZidZZ&eTle6^ zC0`=yzVxBigDw0f*aOh4ALG6IMs4=lsfVBO0vs^SvFNbxM>|M!YeVPuy2l zt9IvVj~PGzvxEZc5)>oK$8mKpN^nu(P~X4I!ii9rD?Br&HN^u)(Pc>zyDYfbv__0K zcOFr`FD!^po**lv&T|w0myIbQ#Op5O)^cd`_6SGLsZJ|`1Y;^ETU7&g#8p0f$i|_p zedK&F8}*dt_i4!-kEf39)vqZ%5)Ye?uXQ^C6U{V)6WervL<%SSxg&!bE1G9E@JhyL3a2%5ameo_Od3>g8BqM}g zm$i{fVtd3zncsxW5P7j1KAO3m&HuZBS`3-top7(^8=R4CXv=MUp!MK*flpw(Dn2_q zyS5^E#K+k-nVO$S>H7!1ri}vKwHl=7XDTXT<~g#n0AjQcYAkkP3iA4c{g0QSV^3W) z)=Y%K9yK5SX}MKIrz`Vq z&JlC)J{Y3JuzpU32QZI~L;Dg@zNBk{I6J&TB!n{mn_E>$6U##FSij<523QW}xWC)t z9{jkHsdx(AxEt=!wCBj$jKMVcJtPw%mL7Ban6j7xwLuzS|7r_tz4H;TZF`h&*lxrg z6$c()*2;;?p82+nhmud{=G5?)|B9N5@U&B`dE6+C2gP+#H0%hw{Jj1g^m`}&VQ0Y2 zStZP*l}LZky}zxf0LcK+SL+a*FQJ`3t%HP;pylj6yE*&AQ{kgXA|(bGkcVJR2^DWV z?qtjcEx)6g51w_N(5^D_)6P3Ux6_#>HLr%xcRE?=@w)Ypc+d+AIcQW4$BYb&%@cz74z5VS zD@;^mp)|Op8Y*g+9?+QdR&P*)mRG>ZPKg1{W}#9Ik+2m2?Z?4{Hc*+4LWhw;c@E?E z!YrkWrei#jo~w%FxI!HQeNU=d$qWJogTQVT8WRCaseyq|ULpjBPlM*R`V6(H_ z8?}n8@fo#V4xAdtutO_ejgH2^_n7`J^!-dLVge5i&x>poWyz#Mqtp&2G|8JRX;sqY zURNTkR$K@%W2Sm4D;a9d6YnEGWE8W+ej)K&`3zX~Gtq8+&Din>F9=p>mLBV5L$Eni zi@g|*#w+*OWpPqi0Zj%FK->Ne?XfGw!-mLoLy09>HIIv&mSpkNRic$7554IIzoe0Z zrW*kmm+o=Q$`%_}Nt`Uz$y))O&l`h|GTo!VC(9n5bbA_Fv@1Y9db;X(9>=6BrozXE zL1EutPaSP#iMbY7+gzsbT)op`HvML<-!xB3=cHrvp9E_(Oj%sVCdu(1`yNyM%V*35 z_>C;~S$|q02aGD-6K~8;L1jNw`FLjw@v>iJ1GN+$PR!7tH4F%iPQyh1fxj_pJcRxDCjk@zb_UT@R zBN2y4Gw~uj9HFCR5hbqiwjjq{xTV!LX6U7K0;ooccofSTq2-w>5s`suQ&RXHigz)Jb%8wPZ(5!I5@wMuZ~ZJ0*+Up^#m5T z)fyaYnm>4Zcl2)a`#=Cq)E%2R^z1CFl?F@%s=8twQ-7#e!(4!(Gve%hmW_YOKmI9e zt7toE+n|AUu2O>1MLFC&vlt*i(%nXVgEl{FUwkD-bPf3B0p2G)yLeP}D@+2iEMhpo zymr5Z62Klkn+Zp?nS{CDC?#GAC;dP70o#G1#FX?p51hf=5+{zt=m#(i zI@l$&*}3Zul5eY!u}?!IklV;}IaXrE`54E9c`e7eNE;yWABf$0Ca&`M$=bys6C%$i zj8xW^w}1)lTv1V+3LSmQLjz02FBXH&){~~@w*l|`S&Ge)l5FrE%JC0AJtB1cti{R* zNVqBmD*KTEc1L+tUV3FlP*&eI8Wk-%QDQak^#C%XcLsDNUe#1Ms5J!QEg`R)PkN-& zb?fJ5hNOWxggTm%j{cn{>1tz$36_XPV$O%om92@laNGO&6g%9V6BlG^$Ii89)?VBl zBHMut+|`5ijL?HD>x@zHEuEa#?vdYeBP~VoTrs0}zi@e+HKSr7O0P|vjXqA5fO6L;||G)LF+Ux?FmMmJY=6hgrMzMO+yZfmw z)%HpgMnBSfFpf>Q`08w$YMMk6^vIRuJRUC7#Ns>1&R(qjfus`KZGS1MzBG`u&zpj? zg`C(uv<*qng`b84`r_d#B5z*5XCDoV3Hp1`da#(8VN3=wVF1}Q*|B>>vmiq2}}tWSf1$DoCQaQVpSLFQKxV(Rg~ z>E&SvNiSl zrALEEvEFN{O#sI$s^LNk&>?n>r6**W{Fm_nMVq*td)lAIe;@`q;&;#&f$t@EuWG*W zu9*bSgQGr;if((Gm_%>Y926vN$K?0CDE_9Nc$`0Uykot&KSTtY&Gl#P4OWFZv43;h za+bW_aXsB^&ZS~HXKc;q3GjD8I*_87V1qwBP`0U+F{#-I-nKMU2ur#n)`DvxvP!sf zz~=k}#5-jPpf$w`*gA9s7+pVqD^Q1KetuTteE$|WZt`11tplL{S@PB+uOe$SfDne} z%caESD6u=ZP-3i#j?)&jiD3%#k8=}LlkjOU0m?7G6QwI%WgmEH@CdV-hSG;U2uF>) zP_2CjXMsaKKYYD>ZF9l|UU@lK0D8u7Mp%1it0e8YbpOBaa$xI-1(JKgIjEr2lX{Ng z3WY?i;`;$4N*1set5a-Ek30C(Nnpd7@)fb-EzEaL9Ee4=cZUqQvOtS~jCcvkg(;qt zgM+{)jX45C_1Xb6g=)3aIg)Af@Gt9r<*Gt~2?vY~#K4ReU+tB9mW=nf{GIBHluRYHmC3%dCEQ(I(u>-&g zyGBS=aaw|oZ2VA~k7@iX^3TI%ve)BQLbnV`2JX@r+&AP71M9U1%=|)cIoJjE6y@(b z=gk?et))p&iLtt-JocFlXMhmaUgS~CQTN6I!);$sg~;yQ7NZoNl`?&RFgp%VKz6LF zD6tEh+Rs`lKT%XxJCb!=Wr*oO5>!`4iv$@en9Sy0AfEoA?rXM^dV-@<98I4;ZVY}F zT+QxpKvm1jdJz8LKpjo+IP>bAxY7y%GyVIjyL}&%q9unUfpzLu4ifOzh%13+`_f2J z1QAqY!3r>;Tw=jv6Oo(({pGnp9aJ)pI1)FFfCu$+fQ>&|v+Rx-!=%Qgp&`Fa8g6;>Om8(rC*Jen3MnxD3cM+BKC_4ET+JtSJJ!z$cJuowgI(N#X7}h~1UMr| z7TIDnjReS5<4Mq&mctqcNnL6Pqoxz+1VD1d3$`w4P_t4}B45)e@gC7{wDq!;6g0#D z`!Nr|Io$K;(ZhZLnS)s7+?ZDXaW(uEu?L-FBZL8ShPif?16+fPcs@+Xm6b-OPoQV2O2h6uZqht0#(^~k}B(6szgJN=yk-?933|}W8ru=ZUU$m8z z5)kEHxZ%f%~< zi%l7oGC5gwdG3zrNsWXspK=m0LfY^GXRN8euLJa@mcY091;>y0%lb1H0j>U;%{ld= z!ak~^!bqy9Q+CwRU_?eRKay%WEwOA=F&EhE$=*}9to#mu7BEburogJ>)dJN70G%aq zk@AyJ1Dq&9J(S<`JTIB4MXC-+Yh4nPdKOEJp7EOvHoi`$fn6Q!bbGvM9AlZ;&v_gU zg`b}(x@m$hgPNR)zGl|#cG!f z>{*Kb&c!~T@sbQo!{cM6O?DrqcQI@NUVXj@RBJqXYR(3=Cc^x6X214wTJ(6j>CnSk zK)&|2xS7U5a2eg#_K2BbK~#1}by_VrD0Wx8Qk8B8AHGU}LL_8}1c0Qj|Hw)4@K~XI zl^E8%y_gJ`AWR$tMQ%G+{%6&qOKVnQ!9e`po7bz2gLA#D<-M4Vfng)A^ALY`0;BQc zE~efJ76<-K){o`L*@Tk1x}zrDNdumVoQ@3^d2vs>0YITRM_;2M-`cH!tVw)PZB7od z$_t(*x9l@MYZ5yA+bErj8~6N#MH(wpuC$s94YgV$H~dx@dI8LS%hzaS&|5;NVU^pu zP;$rsvZu?p3!w;CW`G$oxpZxb8SZ6}EUpk_z8%FAS$c!(tt}mubAdGN5AcgBG7-_qL*Xxup>cYY5+WrQ=Ss+q2&cFsYXfzXFwC zlzQL54S5nkL<}=}^@^%$zT_pU$;Yk|-{a54p-73+(I&SGT8JSpE~Z;qden`U1SAvA zi^HdFR+ZA1X`2^PoSxzYBQCNaS;<4BcuKLCQGpT|?-y;EABpftPAz#%Sapmp$Xq6t zF9QEix%L@XCe&|QDz(M-fOw_CTuWR-p4@bFRtx_cIgyvJ(aDclR@nRsD09srK;a#i z<=5zcJpyr+Ha4BUD6PxbdpugkqKZwm<5q<(LrbD@qG+E~I1TKl!%v8kug&aDtvu^v zJ)~8HsGT@2&Ey+-nm4gg_%bLqfz>MQU1GmD389$^a(IYwS|B_L-5c{=DQ0^UAWj}N zNxoe~`S4Sy(ue0wBj!~1d5Os-85qT7_z>3{XL7fH5H>emXFvSwx)v11u=&xh@`r1l zb?4oeXF;`x-QD~FJ&GmkI(E&ReEThbphWtL19+=tF@^~Cg1y-K_a7fQ7Py>1>-69k zpb12qzvKNIDyYdb4!}^GIq~Y>mKA!K{B2}yXPWe5i%*LPgO9H1iITH^sooVGM5=x< z$UYg#l?wlj?!Vc935YYnC0ME`@%e_<`WtM5iWSolbEWSg--f?v_rD-S>)m zMI-6_a^m6L*WT*BhQr6rv^lJhe$!ezd;5M8Yo#Lq=p7e16mzrF_(A&h z@E!*wXk1xLY6cBy&n`G#1@YO38WoivcSCmPh+9d)=FUB!%TYQlqr_tIZxKS>_-w9y zKmEHv`+wYtgTyNQe&1pG%3rhLmP&-QBIf{1uAF#O$X6e=c7dru3b=otk!0uh1P3%y zjunm`=4m2m4VZfr5yCx~N`pDcIgCdHZ1D4-kjD9S7*q!&++lH<+z_}($B*D6`gDR%0<{=3{GOo3>8 z5mWf>`mn7w@$(cdD{AburY^^K4Ver(Um++!)!}zeHr#L;b6;LLS$)M?AlvNTVINV$_ z1=RFbTNl!_Xjc}Kr{EuKNE-*5t2c^>55Q2G3bYeIA}peX>m zE%I}?jzT@Gx?`S*&kBXcv4~^$v=m{}cCis5>0Bv*!@$!&TF-SlSasRWqGIqeDc9m znM+cmi7?es6d0b(24~cs91`KJso8NMvU(~R<711e@xqEN4O62YPW);@%CW5>%jUB}&bF3>HrrHbs8^9{hU}QPZ4r76%pp@<3f@s^Y zK5DYD8&on6`KVzTu8$q5 z9>oj7-_TXJ1XFCjrCPOQr{L(Gj*_z`cqyA4`d5?xD;nvDLaxeQXj&4hK!_6mB;U3V zfU5rnOJ^u13-}=%$G6Sz!-5`oKOYu7eNw`Hpcu>GbT6C&Q+8qGC3?)L&lzvr%Jvk3 zz1sH0o{!S{fxX)4Pu?5`5hbR-c}Bi%*4pUaQLZ(!r03)~as6LZqC=y)jH6m}SE)iE zQx_6C{pTuoGwQ9ur!@`I(4l_r%S89rE4lwE*b57~lp$5UOv|Js=8!p3HWS)m#-*R# zhd$cVWshX(7u$n>fGnrfM_p{}9>09cd}sF&qgxi)w8G&on99)gj%!D&Q?alhOf8N*>%BC(!ek$Mju^8~p7Q7?)Mi~P4-Irx)rI$;C)Oukln%AQuJl(xMd@mV{iGbfSbCBUqy+~GF@OrdnxD++xH%ba_ z`BuQb0&~2Fp)rsqh^E33tqvr-jjwtw=Eb%~yjq}ZYxtL~MzlFZ$#$b|3CZrWV%Meq zTJnx6vf}CHs=Bhwr0dHsG*Rq6qnXvJfFXTypT^j{?Z>zzWaGg@g^RHEI6})W-xz&( zW{=`q?0Yx?LmRbk#(zezdC?Z-eN2jukFd>hpB%Le70*Gc5^(qw z@teMBqa#6AB`Kv}z7No)0ZsUO+CD_pX|;Bqk}3YJSe&yh{t_;wm-8|L9vUzZJnOQG zWRE{fccp^f(q?(lfE2`cbS%A@w;i2%<|&e1H?GgtR=g(yz`}S=UTM z!edGXT&O1Y&mynQyNkj^948tBCz;SSY7Oy0LY<8Pd~2&w46xym6OMo$(T%y$L>AKz zl%O(tO-8NLr(veJHJ@Gn9Z8(0xk?wvT#8F+4}WKV%uPC1NH;WGYUPW-h4LOk2CyrI zPQTcqBe9-jAHDTVMjE#jl0;uc{njlDtCY4^;t?150HICIPDZNEBnV0q8TkkQddB(t zQ&y@-gNww(rVHA_Ftm+e@dcaDSte@=obZGiyd7Q)N&^+iRZeWjef*u(J+P5#{hQZj!3y`sP4OD|Nt@W3VHI(D1Wo)~H25q|a zQS1p(N7vmFusQtvJwYZ)?M#mV)K_8Vxzu8gU3!P?=VCTqQAiPPxrZFBme`BB?-A1r ziU27PU5V)OQZApWzM3EbPx0cp$Ae&k)dCa~he%wt7U%f0^gjQMe~EIpsH?E5(^7`S zDFFIzpZU$z(ue*a0zPi87ZakZeUN_0pdROVD?xSc7Tj)?bhQ*{9@yH??MFbi2D+Rc z@cZPFqi%JT!47-v)vlgV*Lc6(%V=`^yYoeFGIZgK^k%Q5Xqm#b|L!1ILRcp!mq|W8 zO0L}ZGb)5n99_Ts#AddJ{q~skd7lIcr{hR@;2Ug({B&EiEb50Q4bkbEa`1tj7FIxr z00726JV(C7wB$dPGyfe??_W$Tx7gVX663RQ8sKZ;;4_gIH(j4kgLQub@tf``4!{xj zVBePgfDp0~U)hutG&s0T1)HInjvO=#Cp_ME@%qe*m0W(YRMGPA-Z^zEcd;MM5>igI zb?HD+u_!}w>F%8iW*pC7>~vRp?4mHCXIzhpJ72|SD}F=`M>iWG0JM?L))1)* zJ_7WUywCNsHK{w&gG4E;EY0-mAN0hgzrn_(pWs9{Ua@3O@_PM+l7ZNa!gZo52P{VG zZRVzqB5dOuKn<_*5PIL*Ny7tJMMz-~O!NHve<>m0Jth*r7on2h+do-ieZwF0#!zi? z9DKV8gWq0E^+EgGxhOhpz7+WR#Vq@Du)}UXuRowA8{EHlka2xQ33_KRwWiy{l&=ui zlf-ZKnAsmrC~rH|$aT~<0jMQ%wsbG9zK2z3f%Ezvza-@oyV~3ScTRuUlJYfjk)_NE zF^yjxwj-pM-3~k37B5Y@5ge6naX#k$RVPxqZ;h_vN0J{D(9}u3BZ+PyVcza%Y^;yw zUZYbKMD{%%r^km9t0{b_U;(T$LbuNwgNMEc)wLJ8N?-Q5=C5mTAlZS`a{G&&&apRv z-ngs2hp6T{*N^;gguwDtw&&uwbY1>_sZ`5yj2s|Qt_6rOG}-iv&i6$q+qKzdl)b%I z>tpKK?~sWxST<;?04YV&+(=y8%@LBAxCa~V~3aEeHJ(%IS?fW6}VMfj_+2C3M%AA*gWL13(g01Lw zcsn8`^|LyICMteRsiCA70IvON+5fODh?t9SO?_tZo~9ah`!gwokd`XZqH>gFY#_KV z-1uT|(l+@i5VxEt0U=qAZ6pQzbL_wQ1Z}Fn;T2H&ctnZ|)SaIt)Yp5m8*>rw+G*m1 z9&VkqZ=C_2xt&c%+1lyz=wmAifFc^0d-`_66sztpqoAM9GxPp#=Kt&F_lfiVJ~Aw| zs>D8G;D#00tBC(f2ueExU*@koSI2aK@5_us292lvwAUU8AE-Ane7c7Ws>$ZAgtX?a z)Sr|IdO3y)$WQC^_%oOVBu5Ul06x6lbFm?y<;{O1n#t3^@k&-pb@cIX!}js`marQx zJqE6;&h>c`T)ZfYQ^ESq6~ncnhCTW{4+CuJ)x-{`upn}_@6Um^e#g^YXoVX2SF|3_ zJ-g#ZO%Y#eFGDX5T=hn*Pvt!%&q9Sx-AQlnOt31o#^{0qlE^3x;@**vrX}4=hwn4o zkSWraR}g?CaNa2o7@DT9v(*DsP;wzwuv!(an~t*KJy%H1@7-*Tg|koc%B`8Sn$Cbb zNlO?C-jR6V)~|<_#9gm$h9Ew@*hqoX$0IsyGG}oDerWe}$H62Y)!bPqj?jy_G)tyf zz3%eh|1}JEI3Z4@{u6Z{4F$+pgBx$S`K4NB6VfJcNXyE70Ri}8>d(^xDpH_BtZ8eX zTV=KXB)|;+LRKYzw@Ra5);}y>yiRBrob@fGCtG`CQTc!=i~(zp;RKYO;`@QmK>HU7 zwr?-~{nHeVbKSU>F?u?U7|iBPfl!^|-Y#s%kZz7WT?j{*HFeC5=FZ54^sW*W!phUx3oPSqol4f*Ew$>`-F4t>@PMyD^)F-@Cnh^T3Q zvL~U5NvF06K$(E$7QD85Y%*$?AFb)h#oA8q#KJye`GpeOb9gDJJJ#~(m&cfTppATL zkGx25x$*%e%9#tyT+P@^{B3xC2e0Y{MMLbw#r z{+YEm1Wh__X7y?YzxCx9_KOwS93D490m3lqHI*jV5!YYm{U`v3TTrN)j6YJip0C${ z4ITllRq-MUBLGB$uRDp3g;Jli5lHVbvBFrm`dcc@_s9B(YAfKP3lmpvuKo|;cb^QC zW5|G-B+E_=I$CXHi-gutA!%VA(h;pz@`8AB)5P20Q+cV=%jKHw1fPjyVpWHdebW9>ImFd1vGycej98Z+4#(!o*eyC0T~(+rO1GJj;R7 zWg*{oDBJb-!wE98h z+l+&#{+Z<$CVVwn&*m}zrIagQG` zr1;?*DUJ?LXTC(?MFEp$A|UZw%JYbwFk%>+Lj?Rt`PcWyVe?1}Y(3SN?rIc$&Y|iA z24F!1>jS2L*z4Jq0f@7f(bBpfqJujcRp*FYT0fnQmVUBx;K`aJYcX~RJ_)`Lql=BF z%YI<#ys8j8FWDqF2Rr=bChe3Cb=u;#jsjo~cnEP?loX3&r`y4_p`@_lYAVn%FL-C2 z^=Ijp73>{-^+wD$sU01QUynG@?PU!q&XIS|e2AE4eisIl)3PD$$t)bSOaGv5W%A4O>3x4lv@;POWCCPZ++`b}RXT=x~kzOC5dKGGQmbdKF^cU~nSLYUXDJaoSsz}gfj zaiXl)8vA!2^`u#c>TBBQ!(o%XU@1Vf6Z-qNS@rWNn(apF<(R?-8nR^&#d4Al5ya4p zh`@K1pngptN9R#*VTMpHKkdVb@#-fu?A@i_=JBP?K! zE^6iH-EYL-iAh3`-$owlME75!Lw6*c<%1OryJ$Nog&>5kK>4YL{hl)wrYu#}B$6-- zUJ0L6Na#s=@y5B3F&q=FR$Z4B=^wuQ`a8Z&KH=Lpf>tZ_&UERPy{NCW5C1;OWqtRE zlM!ZY5E%&SW%*%C4^x+3{IFi`=DA6wEnOT&iK7-Tx1$|AL3E!4q@%c_RMh|TOk<{7 zd;~e{e+Xmqx!8YR-{y*QClWAkR!rrR!+cRpi^`SxwM@XA`X6s55v+29b|N}BTUt~u z^Z2w~AnuzZhU`2O1+{_+<~#50JVYZ?p@#YZuo+RZF{>tniD>lI&R`=Ugq-oEbR^HG zR(A`s&eSWnGoZtfrFJQg{Z}I@NDO6FjiV`Wf5%O@kG_r;zXAomKCG)HkWW>yxC>-c=d4fE0V`7ivLXk zcQZkm(Y&g@N~=yXd~D-AjFWV;$&WMesLZAB0Nmf@Y=3sU&Y8izCk0@p=+B=D58}YG zRyHC4Hyi4;G6KG%5V?jeFh4Zd=R`>v zDzZ3!rOl)Sfmo__+QSy*SN`AOX!^rlI`OdlQ)Te=w2!~4w44*R3PnSqNZ}$$q~XdP zve);0UrsuA-6Tb`**BD`!2>dYQ+9Xn)G_u)Al(7uY*Se!S83yz z0>L|@9=fFvB!)EDjL7^>3tY^y)6e;svBCu}A6AlvstK={fLokTm4Noq`R4?h>mSA6 z6w1XV_AvL@D+Ls1-nmAywq+vi8q+WPU5jSM_s1#rsEYpy=~EV`daZJe*mlj@)ID`G z`*&eSg-QEh{iG{zW8=Ql2b;P$m7ck>{%>wv$wyh}P&Ry0a$2NSp*Q}>w$qFJd?((ixs}K%J19v@ z5-ht4g%GBh7x!E@o=EA$X@Y=`sAOpe8OqSTd<%k7AP?)dYq&II z;^*+OqcF-2qNOAmD>C08Wv;oD@CWJU$JN;YTcX+X^MRr1QsWXynB3K z)&Sy(`xKvjlNi`r<7o~5Pnml{dYqOtO9===l>7{N8~MMJDIi+7KG}P1h8aJku{aRayYA0O)_!$%)FbH8yA{i(Dc7S2(KqvUgjhgU^A8WF3jpzSyeerbmS4%(qgJu~q2+Koo)dX-{Rs1pX61cXHRU5{>gsZ$ zhVjSq%?I!LGijC9SCXlawU0V!mJQOf$E>*KCYeGv&bX0evn6|qa}@{qta=yv9H%e0 zRY|pXZS_;^l}Vnok(n6~W5+{CFUz*~buWgJ&Gr8TvT2Vy28i#vFhUsf| zJDE`=L)&p)Qzm0^Hy@ohZY0V*ef{o2jJV8oq@wI+vZd@TxT87?)R_=u@>N~+a`kt> z`krGNxWW*xLj7|0KbjTFUsaxp@8)kWney?Wz@i;?MG(g%D> z8q^rW0Y(rk`l3?$CQ)Rn(wKoADR-YpVash%pU&Vmr^SZ^L&fQENibbK7?*}=DYHY@ z6eVJkIaRDQ;ho$zyr;gEbv`q3BuycQs~6T}{9CA;&_}@%566dm?x)=TwIb=JOcET9 z+jvO|?@Ja^ejYn(EosATAnLM!SNZmk5*B%QmcKha%SIA;(Avsg74B|048vSKzGV~HG z=?Vk92+byHRh!4W>JKVE|1gdxCy4B+Kg!YgBCxVnW)7t!x$BtzLJZMSj%in(kQf&3 zsDc+1h}lZ)$v~7g-2b768unzUIR9$TT^b_(r6rcPkONMM)NVF-=qP$wUh-n?cKapo z|MSX{iwgcH^@{b9?Sc$QAg4+Fa$B>vR;JjsN+lUH`Jb4`9}Se~OJf+ePKtCwNy+)b zEwye)>8p{Xu?7%>;)UNosBN+A1N?H5S1+jK2a6c?Dmwnpz<$^;JM_$`2Q=y}1(<^3u<* zk8o{#?=6MQ=cNoph{SbGPPtZfh|B{ooIV7}GB6i6158DDg!wVWNUDVmi zENq^L=&Gu`I=#*;`Uk25@k4Nr@ng@8v#P6?TOVWM+L$}+-fcY-eBgEAuWplbJ<01c zIbKwzcf|-SZ+=5W!C=N|^WlJ%{6qHW$Mg4CAOGAYShH-cDkN=wyVuGhdJRY(KX9H! zD~QOSY-7d!SZR*2mcz%iB*##3M>O>~H|2gB4Um^i0)21MJMo`o!Qy|dc`w@AzP{-G z)HTJePXSAR2MzB4@6c-*sps?KbI;&q<&}g;5JJy1x?rdKgkfVc0Iz&|py^|1eO&Zv zIVy)`y^DFO*2smx}(X8oU3yUc=1>ln1PUXRnS`i1Cvw!&LSXH-hp*{gH#jI+R6E) zR2RD+M|QneM|#pSZ*kF*nEYxGbcxO@x>HFTC0`2@Xz}#Dy|t1Lx*9oxCKg{s|I>kL z_t@M@7Id5QNR0Q1ey|DDEj<*-L2tp#3DtiOB&gslqO9mND%!#7UW%uo;ism+(UrN$KjXpbKukXh(#2p2WLbXa9{(asO<*><#c2 zoSf${w{g8_TfKsmBf2HJ@D=|klRivSoK8v zEy}`CCKMmIb@=NRahm)i@gimg<<#Kzl$qTmi*0rKwZ`NaUEljjlOtPZrFZ-p4c|8r z5tJ#S#@|ZuMY7DWt`84{RROsI=kphW0snNiz5nar*AitX8{P6^QauIxal(gX=j<`b z(kNa2m+r+!I9M`hyeG&f<->ER)o`W8s^ZauZppS_EgQUs8*k_XoIZujL5LJ-01>>m zF6THI>N!jl2?L)eQehef^7>z&)(5V@6Dc{0fqhuNVqWHbUz8kFmY*ksI(&T~qycWrTsD#wSb{ew!<1-&rA#lxkZCogd#e*II16PE97 z5_ye?D2pfHfzNmofUfvW)8inQyxL>u!=b0N6_$-D+yK22amvx?!WaIPR7fu9PR;)N zQ`fD9XE`jt-^->i4Cr7W<&pzjUn+PF3RkUJQ<}=Q?%`c+DNVQfL8f@MAevVWlSvi! z4ZSqBllaBo689ggsqJx-pdB2!(Q*dHOgxWXW&PwlE?>7h+PAa_vy(W#s0t+))$djo ziVxVeUGB9d!E7RHw}YN6ApZ*chS}1FYB713IMuOv4(90%@!##H%e~&0+!tS>l=&`H zoj33NeKrzgYq@Q6Z9y}alCPeUMRXkXoTrdtHO9hfLW&r!*=Jb5D>z~K>^Q64z$wH{ zYU$cYx%Jgs$|R$eOkY~u1y36P^dDJaZ2t}m%|KX!Jx~t=j++sNtÞj=^xRs#LEX_F+=C8CSHQlpNQM6!faW(&Jp(;x^_ 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 diff --git a/crawl-ref/source/dat/tiles/title_froggy_goodgod_tengu_gold.png b/crawl-ref/source/dat/tiles/title_froggy_goodgod_tengu_gold.png index 64879eadf93114f62de394ea2d5e0b5fa1d245c0..ab1de72f13800729cdec1689e037c371ec1b64d8 100644 GIT binary patch literal 18617 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 Ltj<-Obx-&|C8115 literal 37496 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�(F9&W#HL@bD0;v) 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 ZArmE5mt9upDy-ovexJHUN`$Rtv)BXCt;7E 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

i6|CS`*F?E4pLHEx#SxG4rzfQ3zmW z!K?uR3!c=cdjjry0ayw`<2tHXzMI$ve;yF6x3uP;H9v~z>udTbLPo-uk|9giLS*p9 z1)iIXUqA^N7*i$-d3VCCrl! z^&LODe%Jep!|$~6UcG@;*|#jPC*yE~DHD4{ZIP}et9<{_QdIc0hi6~6( z<~NGnqXVxS2D)fTJ)YWc7uVxVLOo|nz_MN#Da}t|mKhnAf`CUlpqX0N1780Dz=)!& z`Twz-Ekka6L`0=1L@A=Urz;ZA+RfwVm@>)7k#|K25^r7LNAHdi5UC53Z@sM~q0tYq zs*(QiUmC|>z}dc?m&wI!QEKm^-?UGTUI073`#v|kdQ&atczFlIghDugv->H3#o8EV z;K(N-57mFU!66C~RypoYxy&FJ|9Xy3-NTegc6~cVN0ccdD*am;&|9Y!eACV4uRJU} zw4X7s@X@c!nh&9ZxBvzkkLV}AWIy?RIHP}l_`cljSH90{Tputq0&a1DLmvl0`E_Fhp+r`#C;&YW&F~y6cxB%aLv*0>&F2P$>y;e(CxQQl`K4 zEPVJ&A)^-U_yP{j&Ubx%QD_HGQ&`*e=Cyl&0L+r>|AKl3UEliiGi)K18M#puq7${e zVi0vB4O`pwktr9G2;C(5R$RHZMFCNmA6O_5J~8dqlC2;W?t4K68zQe5^uM-l0$MLf zHHUk5K0dq*i2!2C#VgiF-1RJrt^jhQ5t8mfqMxt)K)KbTcMR+T zu2*HI!x*MrZVT7DQZHtbKIyIZ6F{hz-8~3i!m;&KFb(RFxDZRr>vMf|Y!0JO6`v{xVFh7W&kp18h>>%mT|2~_i+CyaQ^)7y!5yEE3}q1 zudn`g_-Sq$%mp&$;7dYF?_+H7``Nkj2bgkNkVEASClmDFa6B-!jKtYQe{v#r{gCg$ zZ*MVz^Eoee*KaCk-ueVE`Va!}YbAEZ6nj^^N3pSnOTUiW>0Zwn|M!6HI(aPzAz}T# zHym%f{0G(|wr&pd4`WD-`Df0p?fT>8+~JJ%6GadbgIXyeO2U{j8AQ<)on-v$XTW*H z>`L=xH&RHY7$k}^vi10|5QI~4y`NFvUQ^dkV#nkN`ToxCz7P1xplI-y zSShuy`Q~ha;W4&?y}OYRDAG?9KYUeS$|Mn?@O^MNU9Ie)9aEoU78n2g9(B*Eb0RL^ z9b323M@?$)AwjIn-uG($)b*3&-*xrscocx&>~MmJAdiUTNxjEf6sO+?HuTEa{`t?^ zzuq4FUJS$h90&{ve2n7HU7Im^OnY)-x(aZLNLP%3*1w(h!8~Q(u(N*5u));cMIWVV zg8yJSVch#HQ@HCdCR;a$XU7{qhlnCXEZ_@cM&P{U2c9v!>$m!(@|h-p#FU9e?)nIV zUpyAS^+*7I^y&Z%yOC;y$!PPRa$xbb_YzAKQMnR`3KkkyyXz^tw}U`(<9kS6z8}4e zGwFL}-SyshGwuTY7Lmyc*e6_ZB?s@+axJ)(yMG+xgJ%8y>`Om%c(^&^%1YGnR z9H_7{KDx|Z9nO?Y*(wIcUP=tIRjzk-z5H@iN+pUy$mk=@J;o7=UbXidPwhPbjqdu% zA8*-necD20DGX;a6MTRDB1}bQ;t5bfL@Dr4k0??oG6Gw)v3BrZ`w&(uIn?t9C-nRG z>$mUIZ``L}KdxUpu3tGWY7mIcV>;!yZ=ZzVC+~?|5Yg$@@6Xua;(iIGVHTP-d%{(A zZUfKgm9A(owcp_-d#~Y)*`Z@N#JrvzzFM10(I{nRm}G`wfFK|?guobqQA<7b#es*< z2S9)m#owHcpLabd7Q*IiW={YDQW2b79A5*Bi- zK_B_8-Jk8#ayFRYdj)^pnfvfnoncDAA8WI;Qzgf4Y2rEchPP`L@}GcjseUv0EFb%h?hE%Dh1D-?)sF} zJ6kFG>SONxdgG7uZh8e69M0_bjz2SG`JQb;j!I$X$IoI&U^0b1(P_j4zx5Yq$j#>= zUran_mzha?>OO0lbwn4(X-7gJfEmWfOtDIHyIBg=3%W%aF{6(WQu`tjBZ^`E8rGs% zy4i30&F+3DR?9d$6?c8g>qqay`L)N1;rNCRn0vn}eYf^T5`6dgijk9=H(W}pwZA9$ z+d};T;_CX9H>g30O0g0UL9sZ#@b1rKL;{n*UF~?sa*Q&>v-g;wfR1RDQ03Q;$HTqDnrn){ef+6rjG-S3)XbXxy@iXtMp#A`4EsP3!skhZMjep1$H zJ+B|J?XpJk8UhY25a+`kI z;$&AOE}yX|s50xNhAEq)d&nU-UU4u0W@JVl$j!1k<8R_ez6ldlQB=8%ggR0Qu`2qw zdZWVM+TnN^hu7a98G)fhKg9Qdit*juy%=#=vHuC+qVENs&Xb=1c=Y|Hm0)|43mFki zie>>K3fQpUUSsQave_YbRnEV7-vy61nVTJXtU{GWP8Kj@c7}eIN|89!Fp1~|EN7b9 zZ!*DXc)WOj_`5SP7!8m?u&z`H32n{SJ7r+1nSv>)gGzAAqaFZ6sY^YFZoHqhIC;~h z+oxn-C8hSR`*o)FuIv#%C)O(LcuIbO?iYW|>pa6QsCwPzukNdVruv7Bxb}PQ&M#){ zgu%Jq>Ywf{W%-rVr}kI?Q}@h;6a2^p*<{zdWh9PV${;g=J((E*FWevKBZ4tyGYOCz z%@hse1^YvKg_)4TtYMgelLf@)u=vKiX+S3WkpK*kVpl5rEH6?>ojS{ZJeWwwhZ}k`MD_-_@2WvRJXVO~?o4osz+xIjpt#=+xxp*`9A?8~* zP+9yPkU` zO9ep#nY|eXLS0k>71zh5I?=Ne@EHl!O3q+E<%Tsqs_|)t zuCGh{5B&BQt{FJn%lK|;tnUV#(6|cN{nS@6KzZ&%W`UJ3%v3IOL5$X`&$j;IT#6V3DMj$Av8sL-Tg7xrn)+)ftZaQ~7>!`*N@hI(BqW**HjR*?faea-}y`VpG8E1r% z4BnJksmxRsTD`mG|KCZw@{!=K_qq+e`?{pQ*75_!KmFBzi2n)O;yAG;+p~6R|6hbzEco+aMl1+9br>{~=w}0StCiZNn>%w4Yt~orJ+q;N!B8#TR9!#3^taIU)n!{>v-M8=GG*xQSr`49 z-vEG`IST%Ijp*-uVYucWBIyPvy)t0@KG#p;BCQi3V5`Q*0=V?+DbKzKFMZ=rp0_t& z-gmv4-COEuCxfomcf?hSP2~Qr1ZMbbHH=Z2B1i_O9ce`tJz6ELNITLIW#m83=*{P} z99fR)M7pBrUn;Gcek`%vUiS>--7k4G8|A>$-@WgtufP5q-aJ^kvBp8d3>fF-<@=kA zpFxki>nj^*)BWhXXDq*yM48A`2Px<{slVb+KlIZc9 zta-f`SB)ygnRi%dddVI~tDyqRYxmLTtgh4LzFpOZvi#sHo166;Q#J)p=lipGzZUSf zr=$5ZrP58Lgy?73-g*}@8VzO|E7vR=DBt_)y2R#^RG#WHbqu`Qy7dRmawBM>$~eR4 z>@NCWe{9^8BKtTJeBW*R4=?^h-}34;9A9^>E7|w1b*>)}dOZWlzUTP#uAbdbC^>}H z@M2DAT#r+&uWS zZv4To_Fwb0*-1~*hvc%R0l#ys^m9=#MrNASi;mp#;x(tD83xv8_7Y0r`}&Y{$30*e zTz)CQxkX~hLW{Cw-yU#2>qY$0tJ!p1<->jwEFJxg*gd0iQLzKsHm*-{PYM3^=7oRv zgH0zS_Zxr02~<=2(0Hhs_f1qOPQ4K8=D-zTg!b8G{@< zCpIhVU%KNL%B7FR<=bQDnBp>s?aVst@0FY}r1l&8D`Z7~)YR?=$~dFpf5_yINHYV& zf)PUFVdg?#YmwFf6d^wF{?7nq%}0Xyo7w5NJ^H{Wd=Qf?Ga3w%55g(xB^9q`G*l><-w)T$~6_W^wPW*$9) zRTlr`Hpnd7MeGooqgQx}bMK7pV?Ec$;w7oaJzHEP}m*a!Zz4!C>Jn4@> zDwi#rWl;APF$jI!nn{LEwIC9Gm zPjdYzEjrdP%drg0N38HX@V=MD;*`3lR4ypCQHgWG)mop6xgA{Za=+jNG{(jVCrMR{ z_4PHJolfp$9P2OR^jyF18SkKiP+a)vH$dnw?#J%!5VM)bTG&IPee{nZ%v|$DitTEv zvQY?uiA-w9axoi-n!BdKpzFO>Geiouk-UB>YAFIdY8D)^ai*z#SE~`-^@Zpp*OyWW zQHar5zws?kkx}K`hrevkqyK=RIrH`#VtI~o$!F~BT-@@>_@wJ3;yF9RB=}q9`f3F~ zRdOb@`##4D_dRi^h8$+E{t6I%bWi*%7{sjk5C9BhSXta_VHZRd_mE!+YV5zUdBw{t z%tDERe|L5wAiAr0pmJH%-1UtS=V5*J5n z;yw#=5CAC6G9=V)-}M(WSALF>5rQljI08dZde)akodFv4uHTx}-r1L%Q6a8Z_I@6^ zFZMoIQ~SP#OZh9^=GK_2qLM0BO;@#*4tY1&zNU`F{Ji_ht7a= ztjn&z?D}2Lv~UmJWlt$yv_JHkFAGr&xV|iFrx^Y1zY;}R@`~q=kl+tbTvoYAY@x1C zP1uR25_)Ps*o)b_vi+&g-09`@uKSCT+Ix%6=fQa#ix_u5WI*+Qj|nJF$=Xh04^C6-nD^+2L9a%0ANGm{gz+ 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 W6lt%2o_>ypD;76wu7A4bk@$bY&P|~J literal 82056 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

UND^5gCrC~SF-anCqA-2U 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 I_H*F>0n%_pDF6Tf diff --git a/crawl-ref/source/dat/tiles/title_omndra_zot_demon.png b/crawl-ref/source/dat/tiles/title_omndra_zot_demon.png index c427641e9c0a53cb1408f681ff74033ad59d19de..3b06d9af1326ebb5d91fdb2cce96c78aa68631ab 100644 GIT binary patch delta 44573 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 delta 49165 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 diff --git a/crawl-ref/source/dat/tiles/title_peileppe_bloax_eye.png b/crawl-ref/source/dat/tiles/title_peileppe_bloax_eye.png index be107fc1ee6fc35238ccf816e56f319238f60c68..1339f0989cfcc51ef4e40415d28ce68d21c06ca0 100644 GIT binary patch literal 48656 zcmV)GK)%0;P)TqIo)%)tylo1OkD45@5jVb~L_aY=J-^5E$_9zXAn%c21f3f6u$NHk_t0 zc~*izAdqh$;BOk5i)sZ{Oubb!_GV!=uYxQtF9ScCNSsI|j;A0H2;{2;eDciyd)&3Q zVXid7Po#+K8im?y)+J*cBN_Wh#wo`R#$$(*fDi}-@`VGwa4d*+pc{D^T#gzAW;~jV z9Tl4yyLC*uT{6DbGNRTx(rcHYdt%VN3Fy8A1OkD4@qqU_Mgu4E;>{Qf%m{>tivWMW zyH(R^<51c>tj0R3VnOh>4atwsRK6|Ub;4{ zY<*POhR6^2c!NM7A885@@PzhxGe(wej1=Wg!LJM;uMH%1LyJ~~7O##hUKQ!HQ$Th8 z|EWX%wagoN+1EW;oI{O3ATWnsxzxSVv7Dg?b)>FwRoZXkV*UL5_yXSn&zo`3V>1FL z0*P{`U>Ey=wL)AQoWCTrU|9r^kNTngzPndGnXxO;vwe#<);;i3pwLR8t-jmsyX-U0 zrT7mNK@S1y;q^8z8DKpjr;Y0CRyAi(a7G1dR&Z7|xg(9-Qy1tn+~srr-FLX=W?y$_ zvUb(0|1}(!lloyLn2j$HV$zK$nzvzwE7_Vw{uVN~Gbx_r*u6eUU&9h_P^a;mUm8?z0Iy1-v66#Q0 zpqJX+wq@MC>gkMG&VouuI=M$e?yF1f6Uu@D{ikF$UNfhU=bYlYD+4?jUkPMSC-+Jy zq4<3+enLi@)tp@o=KGQ4{O_Ydr*_q)cE10C$7QrZ&6(A#ULnY&CO4%~+v-wVr0;s# zu&1Z#RKR}B<$>O_-S7={FaDb{b82F2Y|u-?E%Xqb&RiYMYUQk6MQltXHcNqo9tQYN z$>4kFKCQTJNoVy+RwI8>yg?}bRE!!dy?j7+D|alTkrBuHV|#m{`+K5$dsXl5j_&J) z9q5G}?VI;kNd7Dw)3=6_vnr<6B2v^CyipgG!qWWZ?qSeyTr&v0(C;C$Rsq#U z+C~2gW5Mda?utYwfz+M;D>c}9sVnYI-PV1pNGR@5@47)rh)wEbELnG#H%T>2pl5x~ zJDkYne)8_UUyMHy&Yuj2zwB|1>vov)jZxHAjM^!oc8M=z=pX{x<9u@z+pMIvqPA_4 zxG99Ut>F%7_#@$t2Ar#rSo@Hb!9ko{IePttrmR zFt$+66)E^)C9hMt>r6sF>oS~L=XX!v9z8??CHkXUExG_)yE%ww|*K72YW)l{Ls1V!4(SvCfGDbTnwF6qL#!Z0UGN&|v!qGrrM3@-Zj@x>gJA zQ}T5rbkNbDW)22hQ&B3NsD*`i`-I}eDE^RJJZhJgG{W7(VGhs(NYwR|qglf?lJ2LR zN3>KHPHg~zb#u5nkB?$&W!8MWC9kVbQa7hcztm3yvdwVs`F*U@B z1I)M$11CcL=hCE4fUDW(BAsuI?x+qv{qoTA*uV)7`M8@6*Y{^;vxiCUC?t#4v=Osx zkyy5hFQc`28l*CJEd1>5o6VagmV9E^08|tSdBHZSIOxz(tvMUB=-c2a5eQ%xZtO&dK)ctR)8xl0wb6S&9t`=zYEZ7CEcJnSD~OK+YbJ@j9hx5n_(U&CzI1 zvixWJ{Euq1%zl~htWa=6#_W~4Z@a-j3-#wUHe>3oKie04c48t^AU&Nr(6Rzm--=ud z_}LN77D~B;Lgt!RA(l8C%401bHEEeL8CRiz;%kJCSQ2q66N49(e6{@WQ_{(*!EW%a z!vjwhtJq4RcU+a?;tO|}lL<=_kuwGF;+;#c-o2WNCVtiSh~sd$z3AaHI|i4o4482L zHSGgE2pSUvW_AlKlkjr5;*fxF5Hd9iQx?a+}ez5wmWQSiy|{scS}rtJxn;=8lEgUKnKDh>>?A9+;oG#Y~fuJ*?)B zg&T8G(*^>nGnMS2{t(On11eJ0G4rZ9C%wn5Du3OA;qrYr)gQ>Vezkr4B2 zje=_?jfto!l{m9);Fm2COqGY8+!NNHQ}-GOhKqEae#3NO5TE8|BpR>hE?wm<%;ANw%=`9jG3bG zjiZS!*gicv-u`NcHD*A`WY1IU`AsUeNCAn!?310_e3x+nYFvmtJ;}H8{J*zG(tAPx z3HbK8KF0ajnWO<u@r>=r`Uk1Yi;`f7cCKNljiiZ zH@UQp59^P1`!iW^8FN>?k`dX;`XqL0BoI;^3q!bdgMb!Z*R%oW6R7?P^v`H)*dRjq2%t>E6v!=c{bAL*>AruMO_*LmFs+la zWpe#;A5&r=1WI^N-yWi1dV#$pgeePUs}%axh+#dhk0H8hU!#VukQ-C{+T(HZHXl(V zfEpPPSe;8?AlhWy+u=%I(l!n-s2lkvL~vQN>db4myDgS74Q4BDM!Na38FSob{BK;t z1{3i9f?#F{I&8VsCsNalStK3QX_0-o zO)32hD=}T9sDY8QZYDyMGn_oCA@*M*9h8fivewmoNZmW?0oTqhEzTR_bszN(zW%fp8O9IlGf)qYVR1-nJl-062`0{27TQrMv)3wHRwJ!3IFvZ7IH;pM)c!lORsr3%^?uh{;Lvz0 z4+ADycCZjChw-1JoHCD@nK{giWgIWDW47foTasmuc?bSKrcZT7?z6U&;XB{qtMAdh zSJ$vR*}VZje*YCmZi|%aIiT}z9|a%UB8Nh=+?wO>PvC0f+-vYdYsoCdFO|*LBia5| zJ@-PKdkKDMDVc?m4f969S3?WlZ`Yr?V>0NUsR+CJVi~&IaJH{e$2}d(6cg?eV&-*Z zD9s498h;%PQ!}}^yMTPVI1=e8Lbb+UOTXV3&*b38mS1+bT$GkXPhUL^5y_R0yGu!T z@z@V1QFFz={FS~IoxeH$#Fnc>hbkkYC;TE$5!$r=ZvFfH3GSuX;nm^pN&<#GIgGv4aNyna>;J!=lzDFKC zDdbUlcj0nrU2AY=J;`j4OAyZ6OZx^zuoJ)=NM;=wym9J0%X{^{UfuC~u4Gn{K+5Qe z~0#hF4f_F}OUN`xzfdRl0p zk8QY;DIl19;?gMmA{Z#M;9pS-bu{;a%9VpLxx^!hay0BEwNRz?)$5(}FjqFgRGMzHR_#N7*j|vxnsA0_E*y(q`(UO&H6*-QLt;KfE*_q|4Tf@+oJJx(Ec91s~l&R zkxV6ed4j9rE7L+>H|=@(MrH*87aez*c;IM048;4k#UFd$%1B2!DiXe3_}9}F-gXUJ6KgNWY%9W0hVmUBazug+ z>RlV7oFc)3T`!o8U@HNFts^LtUP}vqx8R@uL zN@b7+Y@2Y02>Ww*%8_>pKN-&O?$HYe5-giZ>sHdbMN0qNAjR+0LpC$7!>pS~s8BHP z4n1Tu%PP#einOkl(m&Tt@dJ8cM}lPqW?h2@1B`7~d%J02KyO)$+m@5o<&r(y)qFS2 zbxw@^?*r_PdxTZ>6saq#RP zA6fL#&Y66ZMrfohIk;uM%shXTk&)qeMgDc}cZ&XUtnB^nq!V{ev&@mTq{*YgWk`OD z-3~AMux|$c8l(@(G#k1R=6PrlW~EPoKdo>tDZQ^zj{Hb-2GKGrJd{na&nWm8)xv99 z(=5!ANtiRmo|0etP6grr*L&jZ?i_| zpe=crwV1G$65oZ#sT0Bm>5^Z7RQu{$T2%80Fr;1T1-Nx0q{>3k5-O@fUBUus@OCMSJ(^&1-SXdeX8%>L}ShH9ts0=rXUwEo(_A^lkyRO)J7y;g%Jo z1$8}ey|nuBe}BH-)1l^jY44!kyaWd%;L%gJDY;IKw~scLVwOb&l+-#~lzb<3t~$})Aqs?E>RIqglzCrD6rOa8FC6BP=6BmAG#?`3# zDz&$nGG&bSyrB4GPui#ZGQJwh`f6z5X9qKVZThoMMB9s^>eIt#O~8IiGi%tFRqV@3 zzD6@LYdqKr6cV|;e)gB|EMQ+$p1S9HaEg%(;>t)_D4RIGIJ{4mO6G%5gqCU1#HJ#Lye@$EOQ9+Tyg4O)UY}ZqRNFg0_osO<9zt) z{mctDGPg~5COs^E3h^_9utMmL=i4Z7it_{`p+b`Oi}fBL*bmuQ5rVXxD!vD}tpn=; zVnYQP3g4%Loc{c#*dIOB1M>NS%2rCK3@ye#a=^+wgBos|mfx*2tdbem5>OIaJ=df1 z3{cz-+OSkMQb|CeVcjaWpW?Rb45c#TA_D3{*xJQ0@Ik=8JB97mvJh4JX$i2{vq=F_ zh3nQD3NT|S0VT0c0DIchC!V~{Sb~of61ODE5t#Zowo%EosSR1Ok$l{k7n0@w`fTml zS7X>ZCEuhTo+~ph#En__g`RTuMkZoWhhLHzs3qCX*66Jo|Vw zeC*<0QV++=3@NxVCA6n}ejfac;`q(i7?LnR-lCNM5(_x{Y&6&kSECx9Av31ohSXo` zDd%2`VQa-3F~E&v;Uii2_cvP?%Qh?F%8uSY#kM5!_1v%rlgWf>Qj!y&YF4r>YOaei zTNS`PpGor=#M+|Xgy-Lr3hTE|+hIJ`CeQN0WPWDCb6^wtc5c}@WOAFH{S3NZoa_QH$ z98aeP48_x~hN!~zXom_gLn&b>3DL7D*3&FTm7yHWP(VOQ39=!UZB^MfU2e!H3^}-B zB7tCeRkWu*j%!v8&6N#j;f5?U%Uy33{^ex(xmRO7RdHN{YA8cyn2Q_c1%vl=%;y^@ z&nt1Bmlf{y6NYDDAe$R5#m06o(2c9ooO><~%DrylP!cwjg5RbJR)zE3qEG(E%~gOk zjyBBKob9 z*NK)v4W1#i@wH;PWq|LmZJ@Z=j^icZv6VZGd z?d?)uf6@-LF(4`sa3uAH-*U56%$pL&e6GAJLDjG(IxNG7~Vf?W?Vu;cZ{@9dU-TsK2guj6)-eF&id&Bg81TsNOhttxJaurOQ)x1|V2H5R8WE6uNkR64prd1%nKYML-@TH-c949Jitknlk7^wS2y+U?oGN{^Y&!{NBHE8an~H}s zD?;_?y_80=Mx0iFaT5XG!l`s-B1|3zkdy$n7U!F2h>bH9VRRUiDXl5R_r(1A{ge16 z>g{VcF&P+O(@L3?!zKtHSw48aOsP9ziqh@#E3ENKNQkk+fi3 zcN7~lF(9NgX&Z5o`5iQj0FMaz*+MEca_w=(@X2$9l&CnOy+6zPHI94)QtbP)43g27 zxx|(iWX}tdHtV4H$HW9@PDKaLf}&yRqH7A^rH|I#f^%>r?KIa!aV-?zLUFBXdy(37 zY4E8@TQCeex>ezBz`+Kz*^+|Tb(l>$JXgAF6kG!VGa&0;nJoncNFLFzJr_8i_iWkzijchYy2+Y};JE48FGTxN?!?Qy8& z&*}Pg%ZwK*t@qMgG0B4Ma---IHM1l@-4=cq}p;vmK{;E_@v_wwz#((p4(m{uA7SnbeYf$n0V2XxK>bKsBE*OQ0l(1E{hk#K;2MPKoqLXrWsD>+5mDdLAV*ROg@T$+76>K}f_fP|= zGD{W;Sp0kZNSjI8zy$60?z28N1Y7nX14;7eO~``GCxJts>4V*+#2qJZQ*A&OJPM05 zy`9H7{PfI^Zro{BA}>)`^crNLb^s(&e?h4E4$`g1-47|;g@3^EE^UvHX{mDp5po5xAb*<6zb7AG)!tF8q!asiH<|Y6C4@kdDCOZ>` zvez_+%Fo$~&Yr{n^#{}opBi_HWoeD#1&!>b$bYeO2O0o?Fc3h||NnEx05~Wj?@1ES zEZ}Tq8K(J?Dkn{^h8_hsn{svl000000FrblH*<#n^oBqB0-Jq%N|PiCq5wR57@JF) zwq3SuC)>8Ug3-$6+#8X1^fu3(-~XiK>$_vP)9s9g>6+*-jM6R=l_sD{RGu z%~)QD<~Jj`ji?mKu9I+fEu3MY%xWkt1R=E|Ee9lja@n6)@+FqU7~+fIl{_)q8?!wS z1ZzV?h` z+S_8D)|96SlkNs{H6~njGQLn##^$SRt}@EXBeT*>Y1lC|U1U=Q7$lSV0c9fBuZ(A* z55_X^Ss5j1H3qe{PY_4-!vy4DK;TOZf^+F1n1&(@!%T^c%tCn-=AZ)fbVNP%1i0!j zDR7BUEAxJE}jDRtf zJ^HptkWWEmHAWC)wuMwbe){V7&tPmFf6F(I_~%pQC%bll0RRX?0rVCHI(t_Q0Yl^? z^d1;}Az@>)^|4Qh#-E>hKR8eNK0g2e0000001$59l*~=C*1^ps|MH>o+M*MSoofJg zB#WXcTk9R0-&k9vEw2h|+qO0MwrxAu*mf(Oj-C8JC|B*x->GcU$sc?A)T!V$UhYY~ z^X?7$$~KFi|2nL-k$B)J;#;w=(&kIpyooP=_&v2J6*+EpCoGx`w3zI$&T7CfrLqiW(r{QEyD3{+I@h$-=? z5{oLZC@UB4e&Es0(RmFSm!T0UlB667%aAbKo`nKm|8hW}!!?e$0*k zH9NJQi3LzVN5-{e3CU;VVC_swZMb87eXH?4!C>icJ&e);_;UwC^;?w(P4 zfUGPu^-qK83~-HkC3mEP0!wII<{Fn#XQaUXf?@-efMc7-C7ZVGJoO*DhGt>^ae*bj z^#7sdXqc_{arFN5JwN^CC!saSHwS>UlMsQUe2ZUb&4_>T?avA{EVYNENN`?mzx%<* zQk$%vgaQpI&>)KegUcLR)T_oLB5UB5^&3zBGRjcMEb8d)kiy@!ZE7MqqjK-bD@s2c zmg`A5HLY;b_BXngN2Sg&DLE!}?%9{0itC(-A(3-L1VHyE%9&QheLpb8=)t?*8&%&lw5;qeQycSPz!~PAfg& zFSBazoZ7pf^#K=kzRZ^z1>+kQk@VCYi4hSwDxt^q&cuY2nvzrLmC>%fd1m*@w9+-J zrVD8CEH7x>>1JJi=RGpB1Kx;(EyFAZ46e{mUe|5d1g*`Kf*RnNbGrr^9}zpoU<&1e ziiq~DdPGKxQCKRrMY=iIyWdvOJpzfeFJYY=j20K#A}tF@>mo{v3v7{wIeX)*t!WM! zlTssMYFJEuTRBire((8G;MVmUp^a)^LK-Hu>2WC?%^c_bq>Su(XR z4s_=zg3!pS2Vsvt^ZG0Ae$qTN&ou_tZP*Ci6Q~Ean^o^bhr|wgy~BXP6@(AJ`Bi8Q zL2tjL^DQRno!9z0=QJ;U@I%H&3H0tG(zb|nu+f}b1=diqh?uv7O~4X8EOx@}Hx>Q) zYt#`-#$d&$rD~k+5exdjp$Oy;D$n z=NT#R>PJ5gi(OqD0@w}Y5#3zk@SybRH@?nR0A6bKxTS8=T03d&<2we0B$OeL+FB(N zeDn)Cv@RmRh8fdy@BMh9-a#U5OGp=oE}#O7f&umMan>~o2295UkI(0CN#OCR3&tq+4&ou^m&2j?K3=tMiv>&E1N+U*Oxd9eTh00000 z0000000000000000000}70k~707xqU06G)^0I383cz%ackMCAqKhE_%0|0J+K1M15 z07+ytuV6n-DD!!usy*BG0RZ3l!08}!M z&J5*grT&^w0Dy{~J0N{(AYcZA^#$oJ&U7!qh!7kW^yHFP{LtUtgJCPhSe#&<*d(KZ71cQ~8e}aLi zxBGX@P=2Vb{NVbJd$5G+52$=m6L_t~tb1O#nR4JwUuQ%QtpEMk*kES*Iu2qZ3_V6` z|7pkQW6W>u>>|c2A{1a^`X)9uc3Ytb+6oiGwBb_=sQC zNthh1&!?UyrjxPx9KcE3n7iuKlh7fJaF86KV0p_7g&FiJo^K5s8yi_YK2fz34?=1q zo*a`bLv21C;7;T#z%Z*!aS~D+!jYoLRge_s<6_=#-9mZ^&9K&ZzWiKD&LhQ zG<~fk-s6`!NP`Y*qebsfxC$aZ^hRlfGdTS~Y>;awTr*S7FdgEa^&n}4%9M%~y;MRc z8@DtPd||ditAAzA^4s`5i`jU+RO9!Yl?=5!&SW%vBre8rMr5iVc2Y%MS-jM+M4Cu< zg_E^Klr*e8#YkM)LRCW5X%c49NyJn7t+282+uZo94Q0K}DSgw830Uvm2<6A5+OXy- z>RbYaB~3r96VDJy9jPq$a2aAAD=eKbO$(-JtdmB#0!4#nX{afiu2HfQtS>c`74K~> z`>S;~HilXrUOFL-YsQL9YSKfbrYB~DaElU@Mu_N17-l{9q_X%=;nb7F3ro=AC}hc7 zrs&mEQkR|rH+L2Ky|J+y3cs}ey5bwkEHCT#TgmE~*u)Pw(MOJh!5!X)f5a zm5t}|CzaciBuB8WcDhMg%eK;Sixt7hgACwGS6G;OQb=ZyWpLz$v3o)$RO-pv;j!W? z@$w|(Y{kvxD^QX(ThY+!Cc#=?V+C#mtk1s_bz|fCc?!z&7iTD|O6vdqz8m7nQ`^-_ z&a5HfTb^h#0?z5h2Cfy>0dr=cNc5CU6T#G;+r&Z-SFWd=JALK;^xjr7Txb%NFO$ZT zTD2fP%mEq{~Uz*LkA(w z5XstdMMj)%Q)|Lf)QlCjoS~?j@`^A?l;(tGW8)b-cFXgQKB5#zzcdsPVPddWz5b5pr$2jmV*~X6L|xxh*Z41cXJ8yht~24u0$DH& zX2C3&#bm)OCXC5qv$&t+SJQ<T`dK=?vj!lTnr|3ivaVQb&7W`+@lYnOsSY9+t=y?n`&`V$f$@ZvGeEFZ zXW#mkbB+UY!~j&xzb;t5Kfa5U9~IMDr+lbc%2&}28;S!$DW@NwS6m=f{MtKJ&6`{r zU2||h?I0pmpp~1SUj|RXGEfrq1kvEFEJ44iM~|jXvsLw&>yb!6XgL=lvPo71$$S)Y z_%q)rm)NuWw>^|^rSm<9vKG%j#6x+Vw-gGKuTSqL4%8E8T|;4V4jqxoUyQDmr&KGwrIeYA)9maZ6cmbl7IlJ%2Jm7sX05yxy2~6m6g;gc0ylRng_75upeIqY zSJycI->@BZ|Mp$){it=o;D1Wu`uV(ctyZIYo9 zl7JjPU3)H{dn^0+JvICN@jJ{cT%|!JD+;h#dbEiOl@LWG<2li?I3@Zo@u6}cKP3f1 z8P5?fa!;(N2P8siDUnN|Ok@a!h_NDQPl6~$grevdCWu@}gtUk?JUPBUzCS+r_^Hz< z7USot#CLXDwpSCO_|A^Z)TCp6{mG18p-d_%PnDFMOA?R_JWpnx6X2{MB@g`4F@Kfu z)jQ{g|9Y5uLnstFL9cd=ujYKt$gx94`!5jo}zl{q!xg;yDG-CnE7~OP~@G zu=)FX`(B~XolAf!y;faRpVF7sIe&|C9 zR6-PkkPLH#Z^W7vp^V%H&e2Hf$@2vDVQ7{C%eXBwn%tZQ#T*$b0X=V$Eh#mUxG4^1 zS)COkx_)y$&P^vMDUVOePbsv&Kfb#^pL-}z{6L|k8B3{GX%|bRUw4lhkR7PksAA9{ zwT)P+Qzd0ShfNa4iw8=&9f`!4lSl{MF~6(MTqu|+)H{Pv8oJ3SaG)MJxIIpq8}tF? zU3_E8ut_uXhkz!Ov&&Y1P4YE}!}W&NsE|t`Zbw&=Bbs2fi2C35R_w$0eS-P>V?U$) z#uepx_0a6FoHG_I@&tAmkVq*fXN$*|h~*^SXN5r|G&;0{8tzzvSE6NJ1wbOugv~f! zFlrV%IxomW8IY5rosw>s3L1+1mSsERg;{%qvxOwuyFD!SY5ew9zCDz+pTg7hzK4P~!GgUtx|;0K4uwHA z=pzuy>?of%X988K6d}1bu;5Q8m*)@=9`JQr(R1cgz}+7fO0Z{A)|kQ7z+3D2jO8w+ z9l2L+d{vXRUZJP~^ne^~qL@6PFcAl*ba)c!pOzy*CB%+&BoYXvxYn{Lh8X)nu@uTM z%g=5Cet&$=r=-6}`#_;wMdPrI!aeLWZ-sa$ey&8m70UNV^iXW)p@>!vW8Db?f%-+fAa=OV zssiWHCY&vf*P2Dc~1A-XT7ZU z=R@X{*JP#EpZNVL`Uxl$z^4!jF>nfmLZraCW`t8f84(^)LXKKNxs*I9W;w&MnOg}l zS*8LCYUTUm`@?=R0&if7HACudeJ1#PG1nM@Oq*| zis<9w^(0a;ToN{i(}Fg+Q^6{}CzTMNa>*2tBvGXJBg-9>JP|runA)T>&n7c>iIpOj z;kh4>d&(lB?AxGOmXKia-pb&Y34fmJr+Oj`;5tt3nMGWwhS_$v7CkMHge5q#*UocZb$(4mem-5K1I9w(LXurh9sZvwD3WNJv@ z@Y6cf{n3;0ll5J^^Yc_IJs#S$1c@ll@is_J#&E9W+~y&`anJ`?>lESHdW}xuQ?ZH2 zC0e#tiF_-RKXa2)(i5}Y1TFTe zpB8~is9ZE5a%Z`x525rNLIF?%`<8O)ujhMv4y0Bb(Il=nX5NJHwi&IXaS*Xxb17WD zbjP3wMdy!mxtY6HZ%7Jd5e>z3NxwiVsbZjrU!WKgkxT3W`GI|>R;rItt>kdva5=`} znI)|!ZdLfibBV|I$G1ZHVeudODcA8DZ`#)_yM&~(350^Cm`vfJ{?60oMWJBC z1KO!clQ?ltPEryq!|beF;Xx>2HkT(Ufq2yDFrpC1Wr9RaAMMl6&RY?nm1Tn&s1#yO ze}|STTmzx_2;SKmmx#_%L9p=T+gtgMKfW8!QK2ZeuP)FiN9$xFg#wjO=1}RNGUmYh zE&G-?o- z;++&YCC!=r1+8eNHl8g6UX_G=xqGF#oHkI+)!oy)Clo|Vq6Z{bN_=JTON3QP5>G1~fmXC5?sK*BJz4v`YZgKwU3e&Elsm8H>XcgD_UZOu+MiZp z8#q<9d#{5%_?6NI=LMP5*@2QL5K5pGVS z^h?U>Sc_8x=mviAZDtagwZ6^V683Epj{rBw&*+Nvm=4Q_K_x<-gi>?OZlXVtENSIP z9iCQ1E*rJ-{qgOpyuTTL*YTm`L0Qmh(VLcy(;efh#MW3kt!WgA6fj#nRoaBo2`VA- z1W1e^hz9$l#NrYUUB7fY#Q;gUqs#zl@BaY{Z7eHPI-6b#^Pr0Kf?0h5Q ztq39%Md-%6D$2nru&xR9aiorUXa@qwNEOYk&}`PtszT5#;uP3~=;72#j^4`8a#eux zr4k44-$`V`PgXJC9?E(q#f<2li&kdm_y!yTL>Hh?cs_F4w8S!F8VPeHJ-Jh%#iJ9$ zR8O8tMocId)jKq$mK2qh&cmucn9 zi<#k+S;`F_NnAw+wWaxFe0AZf@TsUIIa)!jI4hTFS~!KInrW7QFpgkFiCkNiLXJ=b z>6FCZwYOK`6rTI@Uq7=LG4LrXZSXIBeD{59xz$ZnlB_@|cY5ijQQ9=rJE#)CIhuIR zI6Feg&-coI@fW0L7h8iz==d_88?FRn&P{`G*U^*0Y}-8>%$*3NK_;Q3j*$S7OMrXM zcVYcXp^QX2rBsO&B^_Fu(j%nv)rf8TO0ZY~Vd&PKKg{llP7GxSjl*SM3gO^}lgc3` z6SGtZ<%u7vl`UV8{5<@7KFjxJd?S&EvQjA4F?`wF5CUiu@yJ9QF&7bvYuVPj6cNhJ zf#X_OU!pR{5lSHrf~bvm=5yXB0a?5_qb+sh0fRvfQ2^v3ns_-q0^OiQ&ZEZxN~*gQ z$O1=Z{8rBq2Yr+>a9EF`751$>v{Gh7x#Y{819HeMtxhdl84)-w6XxO?Nt|bK%P41} zSX36pA}FUP!XQDXJh7ySty=LP_Wq6@MUNjxF~@hk^UEhw;#N1UFcMF&SH)?=EONiA`rfo>hdx%qt7%DYC{B@raKGl~`v72!#R%3~}Kk ziRMkT4z|u>q>4()=?LYj%3EtG_k6^1lArVS5K0@wQ5*C@A*R(TDbKr;ZT^a7epZ~Rd=N7spU`oK5sXd}lWG2IR1*EO{xO#(`{l{)RxNhk%%7_pXf#OfoeWX2+G zGLy!q>{aP;&evS$k!MV=#JYy_I&f+St@Iqt(rf_n)!Ydn+RP+kkbrQH2X4!BRfrW@ zslGjABA3_$A}5v^HL7ntCpt){JGo`#E4oeDFVWFd1hFoM_>v-b%WaiVV!REq`Vc35)ld%BPt%3Ayotv3eb)f z!Oz!rT1k#dK=fJm-JCb5N7_VDPeK&FspJ>xl-&d^on!Vtb~M(Y@t!wlxYiM=Rw!GX zLJ{c{?)35TDSt{!W!M(56+B{D#DVjIHtBIZQH`T*Z!?~=ZmJlfsZNfllk74hb`n0C zqYaDT7}6)1gmSWV1zUF#hqXBrz_a8@%?{9Ctb$AJBvw!IPd$X7dB0NX$$zez0{c+MOt4!rUy`@NfFpR%PqnWba4L=o3T4ueBa}L)!kCvW z#S@Co>5K?@iGT{z`i!wA4%%qt3cndh4Q+A`O<|2MNuhW`Ng|Xa_!7q>q#DN*? zHrj?YD-WSq?Ea8z7r*N(1D-%MA`vBmEL(QRiB@J2l$=^gB96UsaowCvB#8|2tx$fc zLfPMoOt0sDafFBWCp1Az7($tS)=4O-dO~r~uxx=N==g{-~_k|(f9Bots7>Y+I5k)KJN6DxFrzKAJ>Cw~>?PSGgJ9C^s)?!a3St!Qb} z^l{^TK(LJ8voAs!Na_KBlX&EyQ{=61c9~Cg8<}QU$i*zhA^&|cC9N#mr#)275;1ry zD2t_Ua%}rMA;KwdYm@K2D!)v{#Hm@F6nH^V9h{4KFr1WJ)otN)AMDeCn|rk^PJvLs z)GVA2yq>l(uc`eZ(;|2T=VPNX)DO83Q5Gt8blF%S6m64(I3SV!dKY<8TudV#2hq_= zb+L_Dnsm)&6$K=60Vg_WnzB#^o=cBV1|1)93URq)-_wf7rLGAD`bhaOgbApVS>P1! zwt(UzaCbAiUADk4L#RZaPy~rPc(QRlfU{jENEV%)-|}3~w|gQFMKK>|Jub%Zp%Ugq zAr#)v-bqp4r$=29#y0|ZMA3gb7zdPw%t53K`IB?Y6clr0gAq799r`#T6ejL+BWhAc zR3ayZCO6cxCKM=xqGl0Oou(`rClU%VD^fs7L(K>n!-GmzorCO20(yZt;K;EsO(YS|JIx@r|m}3@P717F!cq_@CXcin0 z7mb)jKtAq$8IKQk+q0W$Lr3oPAE@LcOo~xMTrFh5Q;857Vo%sc!zi- zE~#d`{gEdPLP491n!+HI;^ax|pb%rJ{jgVf4#=s|=ma@J5h4DKN>D47MHYA^h@&!N zlY7E*PYtM&$#=?cm-{CT`CxQ>tw_H>E0eRD8OIJ`7AA2=6rsqM?MP>}a?TD^|LBQ+ z+vPBTLg82BtN!dVQ94DIZPKiYX8D6oS-@9D3tCaNf(65;>*-q&3LrngAD~dabxQKI zGB(RT9~28`}1mz*U;$2I_Ys3nc0dNJsPh;I^cyN zPjWre*;46Iq^8lb7l2Jlg?dmZqLRl|$$>Hy%VGDKMmMM7{+b%hiaa55l89J|Q2`|p z4d2D$duDLk)G4BsiFzSbL@UqqeM_}jJJWfU)>4_Lja;zJjw(E-$R@M4%3K`=n^l+?WHgLpvrizhxNM8!57{)xmEjslCXXu3)qA>7px7EQrk#J zhhURZ22=+*VroQ9(>@-@F-hc*xL^vFPhk_r*d}W@5&_rI5!8y9WsNf_0S!@rCi1jm zS@E*MS?AFYvRn*1iE}`cP*QDnPeZr$2%Bhbg;(mB@{CDw;7Po3I}<4sQ?XOI63ES` z6xp;-^hXLk9Ic!#Mp}t##bnlAw;9?G0>dwESU%a)6&5cZ+a z`qd(9yx2z_jJ-;}@PR>`jWQo1QZkX^NZatSY%8RL$=Y*>pp;s3eF~fgg+VTiy0I0- zbz6L$av(O~R@cCM~(C&f4BCQ;WC+Cr2mezB(3l5#)kNkMF z8P!*Qau2_xHkTRcD07)%`TL-)UxKee5t=oOS4&YB!yDX ziYoD2ORz;TT*;|%a7N0E{nv#K0*R1EL@KFEZ-ofn*DR7qA{0j}jN#>H0}Itq2I~9x zxfMZM5yUJ@wNl{={&4irPt)>(Tr1jS#4K$RAjRR<)|Qo8spKS{fMPC06%$S&+ne|< zYW}sDLY%vWcq>)(0&!A6eQp7%9*2k}iBam6$V@6pcuxMVa@ngDMYQf@b0Tz4A2z8$i4b|drxIQx+|5KHpQ)8K*PQZDA(W_Ais(aKp~ZY{ znh`v%&C{ddGIsc-IYMcvM;m~J)g+p^kD`^8P65Ra=DU`S9`b@{*19&cWXo2$xUNu- z@9kST*7>(i`Kjl6i0p-IcB>3g511v@T!%cUgkDUMd(t>S2~~C^ZBI?PD@2j4TQohhSw(Q{MJy8^vbn}k45?Eu;FJNih5;ZLM zKI5)+m9^2d+WHBGW;il3rJ+QgKULWD3)dL^YmDC!xHU-bH`TJCfc6iQ23UWstE98`&?l1&tL4h!*$n&o{2W&ulD zxmapD^o4O`d9fo-iCg<7g+jze(J;;_58F6NsCkyGA$_7S8H6*+iM+>2C?i58?h=pW z4*?-nL@SCm5f#d=;{(jcJ^l@~^6jLUkCwReScit?YoIAqs&L*<^Q^Aeak=a7z$u6k zt#s?ae3eMymxID4gEX&Dbl|8%B~K~U{R?kPWwD_T;PYn;uiR&CX`VBh_kr~|AF3dV z-U=dRp;ihk^j5+!ejS7|-~Udeu+mYbO(~7F zX*e3Wu_hAI3B4Yo2*q;>gmRx1TKPMnG!%;FVqN5#i^oIB6ZD7K;%=mz>&o3%ae)Jj_VDPoO| zkJQSyLissrZp)E>d#X(jt8406eX2!fxooU$cXTzW1f zLM-d>S<<8xoj;t_P<0oiLMR=VIAyAvFsq{FlH|=z*#d-#jFoD2#sY$6n-0q}!Y{6) z>?1&`sI?5O{6L+euNv{wy(;_s`202h3ukB<6$oYKHjO=Yi8TJwamY!z>)1c*nj z#@OD75v33X_=TmjoDYOkdb}g80GQ%!wX(wL&lb;kTM?~DuoSl<+b^t@jY2)eu>atK zoLj1XPM-u6Cs}Ul*5J9cH-TmR)U0m*_4T@&tuta?Bt^EF-Bm0^2De=&t z@6q^m)9!N8O5TCWkbd#Ko>z{OvYt?YCfuloU=2q%RnxlY7d4FgL#V_P3KnU=o>s6< z0@2$E^ca8jLc@2%|UX6yk#%CRW5IQYbUA9&P>-Hjs$Nh(_Gd%0jIu?#=`$SKm6i z!qPJTnp*ijg`9iDG}UU@SF$;uQZ*4PQqbuhzaO91upY&awDBCW5Y$wb27yrS8=X=+ z)Zf_?3Kpz-F`^PdJQ4^6d-!V57I8fB5xnY>ToQ58NWR5;i2k}}j z;47f@#LC8J*~hqCvnNZ9*JLuxx>J%8Upfi%2fU8%vGo zjFlc|YkA?Vgxuo!p!eZjn4h9kzB@iik=YY}P?)By2u0_QB~qd_ORP=bj=4LK{VIHC z&E~4rv-+`^DHKrJdMiSy78QyIb0t0Q6^hp;%-t-b0HKIhgjX)ktVONZ>53q!6$mBR zD^aa%eU_EIVh{>3%;V>octYWwPZ1Q3CUa?_0Eq;t0-<tY}4j-%Sr_ zAEP#TPsMDv*n;;xls|J4_b2R{wP4NCZSlit1KG8ZMHxtmRPQ93s6nTwbQ*~WCD-Tm z9aZ2VYKSj2E;H44<&zakP)W5O^4+3`5>6N|=TN*tkt$KaHF)Ipw;0q)D1T;E2%$`v z;jM^J2B4K|t5fy}eu~RmhESv?5;_H1sb;6&Q#}YMHMa22L~UkwD-e;EP-K?CDWa7; zs~$!8OLdTR%32z@`C64f01ox??b@Np6 z6_z@M|1L)>a#e6Tj3`>U&$tmzxj5o|wL%0fW$Ba(tvopA^P+mkbdM@*QazZa_216f zZo&B}y15-dD~7kyV`Apb5e>8gjs?6~TN$f;XyptM{jyXs_K*D+=dJ8c10Da%-ip1S z>x$AT@-OC4xNlgr!b9HML>VGnXCYT55DJXIw?I{}35bLOrvM&O^^jQUxt~L!Q!D!u za(T1Y6Fd}#?v_*{+_$Hd0MSu8Af<+JML((gW55^@bNeGjF;sCxI`U59Fb6n?ztj_a=R{% zU*^bZW3kCbp-}Z`0_DOnkwV!+-b$^4XoagnmTCn+D}Ed2zfAiz|pQS=j0{H&N1Kj*G8FLpq~OEIkTV#4PImfHa~MiV=faS?ZL-&8p-h z(8`8f-c>H-20rjszIDnbqV)1n$3emKrQtO62=9MC@P_EXJ?V+MGjdWGrB~G>U*;i{ z*4GgPg+eY)iG)%wok9)@MSx0{gd!|^J#uINfljH-p8v6ir;{t3;&lpyBCr`hlt1)< z9#}-=j_9X=chm||7pIC-aAd)4A{2VhmZ1qpLqsiD$YzS#t|FT@bbo9DLh-NztSuFB zN;z8Rlnt$TwW7G!EW-Bm(00>`;*U{QU;Pqr(n|#y3tqbv%@XP z`$%dPdANz&OU+|(iokOz6m7a6HlYZmBMRe0@{e>%o*&`QJ)1F28wlmH zqfN+FkxnTZ+h4@BtKuO}Q4~-sw6WMV=Yw%{(~vo@6$cjceu@!OHG7w z=ZtE&6D;EvyV-(J1l`ibTrCIt4-@ z`j0f1-FuxPa`Cj%AzE>2%ZS2k+pm2VpYOdDXa$-Oxk!xAJVt;N!!8l67z4PWb5w~y z6r&gmA7f&r0}@$F70b3Ne}bjb(T*2t1zI8g=W4}>L8okQUk-SGKIOlEPl{T|&pXkd z>nRY*m_0dgM)XyUx_X5&k<)$lSVSoP2oJbVH{O=3%wUbHsN@L>W!|u3Y;5!YjC+ML zzI3L&pK_mrn9lROT8=u!)5;gQ2xa*()Jo>A=%J?u4jY_uB+-gErN^&y%KW|A{z8vI zj_h0Unk8p>D??mB7V{lmLJ@?@aM~mt#&C-6R6gl6GoQksiZ$)i_feZxe0SO99VKDY zsuN^+v(b5@Ut3H4dY6JJBxkGz9ke2qyzgvBG25tBNV@nR_;mW^+mLz z!pCoNyXS^fM!C5E*t3a)p;JUFL7@noGj6GfP>2u;@ogt%{gKVaLK*ofhcy@Blwu?1 zd6T>w)mK!F<8Y1m{*(-oTKOHh<6rhrL?}HryKgI~4?4$g+#c!C z;ZFdb5DJ%UbiffE5+Fc?!Vb6aRgJOn%8pBG+y=P$SUM#|DtXsWS?iQnl}?E#eL!{} zB9y&O;X{)t?Jy#QBFk1frDb;lD3Hq@+cV7_N}!2!9BTK98sxBCBie-|5wnnpO%{M_ z)cw(&?Ur2kXGZVKM(n#k!KP(qAgGmZrPn66YmAv~=@ly^1s1@bD_UZXUD7GRL_hjD*S`4sM2B6)Y9!{r7 zp_u6eGnE>&B0}j9p=ews3nuP3Ml`xS@CZ3E;s{URl!(YFls}$U1ZX9ym5p+Fe{MxO z<G(KYE-bjkUhv{+y|tfk0O>F|WoAx~sP)CZJN z)MjqJwXCmlmmmtIC7nEG4`Zf(Tn6LlT+af$qtGdv^FG8oXVzr{&g?8{1@8FxBN7S` zNUDfa9Em88(c?1WO^gah2X9OG z1vVj0>?{?ve(ucQwrFK=3eZ^XQmup>Z0A;%R~-WT3jd3{W<@AA4E&3(Ez~dwrOqyl znlJ6vjm6BZ%;IPehw!qFtn)zwA{6zKv*(mkz&E+A$h*Cd#BTZyE-meVI|8%l^7B9_ z_$f_{WKs@y*6cc&zq*_6_fMOLY5tdSA%_-?`wBma}9li%d+^7}e2Wn-;_5Rxbq4^Yl zZPK$x>zt;S?AYfpvCV(Ip_O(|x=8?X8I)m#X<8A=b)=a{hD=lv_`-2Y2I!QTq$(E% zox;c96f;Q@z272w)pL{VbV^I6>%O3spjOyH+wz)i9pOK(Lna*9(c zKxcoJI^}hbSiDY|bG_~qkIfv8Fi$I@4~@6ziNMdKm!zCygh0DgR2dPC_$8-w6gtY{ zlvmL}(wbJ(2@-cK@;7E!KH3ZS->g>Bve!e@-w-v37RSzkw|UMuH!jxkIt7l9LSbi$ ztl5czigAQegF!3nm)LP9H>z*>DvcR@5GtJk-PfbOPuuAfVu!BI5Q17!{-5X+!;#Gv z2<3g90+x3J2`~}Z&#Djsu8NKk;}dHscS{9T0+qlW&)x%licS%7wIU|UM$8#PnN4Ly zW>UcV_)p}NSpLxZdDT~sp$F8zx;eqDJj8#bR=l4A{ww_yTR)C>9vdmvY)7K-$<&^*Tigg}7HM0h=Y*8&?Hd@k#_j2`dhG-rx~Mzm+zq75!wh zqJxEVK7}~nkt4cuKtu@T-HviQ2B&yh@v|z?Td^9L1qSg^c;i6Ouiv)+>o?01VO9tw zjhGWHb{=0pnGQ3W>(yN>Z^S z4YI;Yr(9pTDuXzn6%c4ev7_bB|IaA4Qz)KLngv>PXg=B=(k#1K74R(I2F0w+C(i^e zF%dzF+yUZ4sKnh>m?tV~h3IBy&0#bA=Fbz>SpMXoR$>oGQFvdi7=-erPD$^d0Q$2! zIJ;a5h3Kr=%pYHui*pTq8OWLQ$81I6lpt0MUdb~cJNSif;W@Mdp#Z&rFNsG;xTp{k z8QLUGl?0)rb4CrqCC(qKbY9?EC88A%Xr-OpK+3KY78EFYwbJ9~BE=2}1*{1L>Jg_z zh4O}4xxBYBY2{kXsw^Uh8_nwE5%O!Y39*@xbKVE_ksfH;ty$|)K#BBN4r0;;KyHjB z`4h=Lg0)mJb(CHCQ~ZVZ{~xV*wPK=@wYRd}$e-+Ynx-{nKS7Bsq7ls#N-;~^nF7b_ zP5w%W6UoSvj>nxHywFn8(Lrn!Zbv3Zyr}j8YBS^70+a|6#@n>gDPVr%1i!1`GDJiV z0>75%)Cw$9pDVs}IjLwR#?Q*1bU-LZY+n;f2XZVb6wqRPXQo!Urxjt)Xp&i8oApm~ zkKkfHh1p-e#L-R48GII<5}HuoM>8x>fg>uh z6KkuZ22Xkvp-fcOH8WNX(TYJF3JD%?^i6uy69BCkzomTV%-k*O3q&ZMT%eNucz$qI z7^36nvo)5;FGm!u{8Lw@nq3xkO0^M#LV;FZ*SipX2+#z10Hsg_SH9IbQaF1(z>5?? zpNe7xXa#wqI>;l?hiC;DQO_NgoTAoGv{X8$Tz}npK`YBs%OMKONtW36(Me_UolZH{ z@i+Uhy%LGf7llvpg%4yu4#}kor_4fT7$V}7{)FZZ0tAQEdm>Zdq@JKtc#f;m<8>qm z1*q7;{q2c>pW;5P*Zk)WH6g!tKc50LO}p*^sr;#>%9u=pR(07Uk)%eJ#pngAQl~#KOnS zRyXI5LDX{}70(ZmdBTpyxK|z)!V7C@Ozojez7J zZIUfJzt-s#%f9w;v_if<`13kP6s=sxmp!1hTCp1DR)m$M@?YYlBp*NS_{d4gM;+A8 zp}}0I=zT;=yQxjY8qZitdd($6Gp{0}o}*K^xPuqJ4suWc+m)aX5z1EzrKN&SY1vrC zsBQj1p|~7!39ibTP)J<)<7lNgwF04#WP9kw6yXsdg|gHsfl##IT7>eETCqJ)D2Osn ze!p@R$F-CxeCEwz@JIw*WWQxnMrARG2A1jYGi)mu45A@@n1%V;%3X!hDVrhvXwxQ! z-=LM~s(4!Ic*j-oPVH8wqz`UZ{_Q;!<@?uIc6(AzbPA>k{g+$kiRVMi4hH1ge7C$( z0yvil4WMgGhZ!L%$!Y_EEY&lAGUNiY&;vR}DAfFTw3i(W=F2qY!k|^{BbXk74Xv<{ zr5c2iMJxQeTK-5bDjDF9WkyuVi-(R%wuKKe;VlvYAIz#KLX@nMz?WrSw#CL3E_BIOP&Z#BZfcidus0OCF--Ft@V0@n<#pRwqvCpq;C-CKQWPwvJ8W zTFE!Iz5Tu(%A$j_e!hLN?0Os25=I9~bT6fE0xJ_!aY6;R{n zj2!oboR;%rrqBSI6cd}rSADfqR1Hmf8t-u4%+E+gTJ(=&f#3;6X6?v<$c48${|-y7 z2uoE0cL*wWmV_c&`N~NF@2Zth1nqH6G{~_~TJ{`{3)h}PD_ozfJKK8%vS!b)ON9v( zqMK?1n6+uXSW6^1@&kz|0+?uR)B5$aaX-_fk`r3-u8MTZ2i>2y{FLp9K!A6aYNch}WIO<^C~EB^#34fQB;v^>!gqWgkhg52 zk5AOfdwW&>y611NK;P}Miq?>0!tvq>gIOG*@F@}MA!ezS^c?LG3J;}6xH5Tum$v6; zs6-o8L?tFdS?QFx@;Xkbpi^S`v+w>yg|eQem6`JXd7s~FQdW8-=I=(^=oDZ0T%}2; zum>MP5vNF`OinqpGesAMsr#eWvRku6Jc)Dsze=G{^$2$or%X2K$T|#N@iMAeXOnjH zSQ*%l+T^bIDFNDnKokP4ct9x70rUaLeZ1dLD5`pdX5n|TAQ$qFbqb(rqtSL*g}YBz z>F_CN52jif(K##{lQn-|>P(Eyp5&@)5HD_EKksfP6s-vHdUhVJ4-?)QLWw#h+O(VU zXT53Vt8>ZaYn^iVJjUO)v-4(73?un;d_1RgaA3z13N+Cm6j>_yVUXl{H<%z)L**1- zU;v{*__6X(f>X=M=9Utp6B^PVD3wkVy-!_5%uPeYA^LfY{ zi9s%=E0dv;4k$xFn-Ir`>j!OgO1PRMS}JFtm0kCTvp@0FvJ}d8KE+?nu~jJcd#s`U zK$R$(qA7;H4}VzA8k};Tr*8inPb3hGYNd!x7?5XuL667^Xa$9W5*ay!BI|@>$Mxbl z&}%wW3OSJ?ozl=LOk2&#*T46GlAM(FV17V+13R^Xu_9Ul5K5pG#Wft21VZuatR11O z$z@HHUGL`AMKxh1EJZj%i~^SAW5ej&-8t5A{2i? z*J~xcvr%{H z6!|GA6K)nv-{w9ea6s)XF_Op#8hxoY};A~-2b#8&RO;aIQ~a{m(Zlylf& zcnhsh&oT>fs5yZyn$it~5Q5G${-b^l%oj<8YG1?a;r^6r2=M zNyt4~inIbCi!Im=M&PvJ*%1mz=a4E|k~Vb8yx6q%sGrawzQCZJNxQZB0Ctd6 zu|hk^E0k~pq3-&Dj5;`=)RVd3vId2+#hPNgWh+h*R0?^PQLQAzZxo?q+nTb9yR}S^ z%U+?#mqnrUI4?6b2xTM?1c|Ftyb`&5bZUj(O2u zJxODjjaxz4hOdD)%oHxu2&-xx@L$?}!YPh=toVg*N;+#)8r4W1q7+Kc#b1`!PD)d* zt@=^9Ec8Nq1dAy~H=s2uG@gYvjawR@>F*YA(YMQhgjROLZw*3O6c@^Y^1IQgiL@f<`7%~B zCPbE4>!y%5@Rpy_*aV)R)|jDFqJbhR>CmU%K%wuWl1C3~xE08)#aHdK7b&`(WBW2a z4;2tk_N^aJDAFm5rgAW7VGTzjF*gvmz5RQKl0QFfthiAqZ$yhxCz9b~D;Fn^Yhypi zEQQ*GTf#*D&#`P#ssut2t#ojF{@D^xRnBzyqlV-4*7L@f#1UE?NtB_><-0x6LjYkR zRhZ@HH4L+?CR1Vr(kUCT7!8_uGqUCX4Pmk_!4!d`MWSFlVNzBKg{2LzhjURSQ)^(O zWRVMiK1jqYUa;_0L`o4JZQ^a$J<>qha0=LrsQmx!WNzQjAa;LRbX989Da5@(QQUTa zHt~1#Q#J}^6Lo+vjV+OP?n5Q$k*DNo#QPlP-~4Bx$MIeKZ>_!z zY6U8Bgi>LdFpnG7HBtDmf*`C`ahv+RT7g-ft-5VJp-=KgT$2mMg|}cqd;Z(sD04m< z#*g$hQZSf880MwKn-&r#Sayty8L5;jqti zOeU=)chZMt@toW*r9lLzFLRo1P^PDVhtglnG=zk=hFPEzPb&kOd?N-zDNSAgVnm#B zKi><~pKi&!wr#w-nyt%}$D*pQt=`^u~}?REhi;Jl`|!&3*UVzfwU;wbP1 zCa&uT2~5zQmUW9DaF-3{^oCB+p+Pax772v;lx6Ls8(*o6QKbAT<4P6oN}KPTA3$kAe44Jdw19{=&6JVmCU4ZEDcVfjPKxb^=FxW zz2~PQ6m}r!@S)^Jq!krD^BBGq3V@OT&*2wzO||^&$F7_GY0<0|txWa&Z?efM#^2|} zLbGsknkgPUa`c_ILL5}jCJ_pT5kw>Xa!=**yfOiLI=+R>WD3#shIb-`(}O(O(olM^ z8+(hVe$uk_w{9vsOC|a#HUX7@6o+UmA9K^RSwS zK)@>r3dL!YN|n))V2J<8Dg0|mzj;zgst^kM0eYg^2TpN>0vepsfgS5ho{mrrK~m5P zTWrxRxVAy9KqdPVK>r%{gtEW!2lqsKb9Kx@!X#KEM3e}*PENWKN!|*ktN}lJ0(>i4 zeI@@Iv5C$o0~Jkat5bw%rnuTi?PPR{&LW3Ds_3djv)1`3QJbt4isoqLr~DyXY4;uq zaqXuRMLm&D(LyG43h}vKqc;AXFU?WOt4GbDNfGo<&;F6lmXh|lqEqg}*oTG}b5s6s ztLc#>RVH%a2olZ^F`44`una!R3BvM#r(hPHi<{(n6>*cd?FwhsX=oG`A^d+_Ccr?3+k zg`y!^qyZiZ%B4pLMOz&)M9+L(^@SoBkWR^|9mZ;c>BVMdSgwOR+tVZkQGi=>`%Ids z_E9%SgraqGJ!+LCr+zx18@wUZ3O%EqU|xo{vErIOc0}+YJaGt8=liiY4>fn7lDic6 z8baw2T&O~g-iJw9Gme{gLYXmXXy6om%vd~ls4+QljTz4si#wN0tRj>NjFqjolAsk) z2??c#I3<}lC0-jw6p2Wud~MeL{~n4KhR8|rI>j^KpFN+l^i5{I&?&I;b5+>Oa|&<8 zP9;yt^Ae%F5>1+WB%WDFu;uhAHpi}Oit3yn2#0`fa z{avRVo=`X?j8;m_wr~QarAcbrc@W8vpF}7!fXSC?#T_8r5enLb{ykg7rBJFtDEuL( zix_SxP1&usMy==;Fh(K=Z?U)7m1LJ`4z1qKz=0A=} zC@gkKlmje<#1jdSd*WmW5yV*)CtFY@fl$C|L?x#cr-)EI zW$;9rMG?9Qu8Mb3oHp4g6k>XRO66C2DEp3&@}(Y$ghF)tXq(*-N>3c8R4J7C)y9s< z=Tv)&gpw+L%Edc5KLb|`#X=}lE}{~Ui@#s_emX(g)X$KGI7J+UBkL5(Boq}sMOR@Q zlt`SMMtk4JyD^DYHmzLY1O1{WOZrg08_91ALV-;*08P&rdBV&H4pe^#iNGx6L~bnQ ztU0^#F;jf8fuVKAmbk05hBk;Dp=>y1Gh8byrHWrkD^3Zcv?2>W4Kb({6+~NC0ikpbDW}1Be$Z&DG%!(h>A})7*pYu3oo- z%+ZPi`aWF&EeJ&s@Dq3fXLa~tx#U<$<0@24(@#-{sM%3*0njPh5knuUV&Cp{${vwZ zcoJv@;&@A;gz~2rY8(zs4Wtu7Q9GvMMn6=dNJ4(~2#L&MhbPd=8BJXEbWCSjP^m2$ zUrk7xKq$dC5u3aLT^_cuR4j7JSAI%|*D1+3c}#R_#Zd`4-vZ*6d@NzTr-*y}wC>M3 z{z#p&?(Bq^mO6z$ZbS+=)7gPS!KUrBqTz1ODLr`<3QHuJg`H%P5~_rK*M3vvEP^tG zBKi<`vWMpm|FA<_vL&5xSZIqf!^GT;KULHr?*&s5PkkES?LE1IJfa8(vaLCeU>9o!*< zMnnUrPcqcIC&tXOFi((fy{|P7;$VK3dt-+R!y(*5_6h4aU`4lWz4opy^ zG4eP5!zp>#9g|UBay@PUiIAi0wBjFw>B%7!T?_zOJTM}JqV@0bc$!jO3A-eE5TKXwBqMbd`H!}JipI;%37!VP$wn%Tsj3>!6)Y& zXR}Eq=Z!+?c_0*R*+8MpB=h`EmBT*NP1uL8bV4qyQ&Pzza|G~whg^dmK?*rSkp<&^ zY$?;?shl>DdC7M{D2SBjKM=Q~0^Rt*2n@pEtx^a=Sv}tzO~f=A$Ym0W+Y}Q{Y+F8q zJORlUJ|yr67&*A6=upRJ#FUjI>#{uuS^(tr_x&kFa6KatO8QWnq_?JNZOth?3Ze!d zrB;Zd5@K*weD~*A>y)IZ<4AwP-N}2k;uOj%N46~P{HDyI8i)F7Nco{_)})5;^))28QbFC=?m9rJ5-<*DHoW<^TG#KuD*&<0)31~o}W1I)Qn}KC+U244jh3{0L0;;{idCV|dc{~&;6b;>j_m#*x_h*syE?v#$d)?uk6h|mkYGp|) zJan@vq5G4d74Uw?=NIfx`TP{}`@J5hWJYp>P-cYMHG`;Im&7SDP*`C-C5*;r%j^){ z!`WrR)tpkO^_fpOdqmG`&r?sJ5+5aAo)@I$B#UNhwJ-sZ!V5IFf??dj1_o*bew2>1 z016+7Nrd8X^0xPG3(8{I@!`5MREb`R2631_wzeMmqlUsbVa%-{PfK3MBUSH!*}2yc z%8FJ17ltTrLP`+IMLbLtqZ`iDA*RUE5be{qE_xmtJv%Qple`JvKUTh6osXHK!ly%o zVuS1=tq{FJA+F1xl}`EezU1Fpp&UCZAxfcGB6^)N{|Z=q&ypxiO2H+wWU}3*ZPy$Lo|#?u|xK42e)4Wc7gXUoaGg19BX^MY$LC zq;^9A=>#1tQ!4ZXvoQ4sxo}(nNVyQ5?c!|RTX~EyEF{88NBvsWAd94Cu)kyILLe}N z(xV84x#R?!s9Q`fHX-4lAb>%1I@v@ho?QG09H8*YdJ+x+X&=g#P!hmuc@Lr8;|ia+ zKP4<%N?xZ>!Vukp$m}#rxc3L@aowMVLQx*!K7OH}a(vYB*;7gNQG^0#hw?{fI|UeWF~?}K#kF46^K&zF*%l)n*5eMV8lDG`Mz=uR@t+RhQU zgX2Ya&PXbzOZl-{T!uRfp*$_{s<%1`)d$9N1jP|3DMV@|02%2g&sZQ4;(+q;%7l)9 zVwjN!^o*fnxhIWDHhCz?Ms(WbG7`58G^~$)XgKq|zezzKmBdXqsoRS2~3F-mw zZc&N1udjN^(V$%xJ{D=^jBRGO`RzlU@_SCu?mzZ>QuxmX$*PaybteK{`D3@%56+$A zt?QIF2R%;9_$l;ycmip+R5}5|r8NP#)O{5SBMNvf%G0=+Jp06$W>iz%&KV7GMK0*6|LRssSQ08PG^WoxiI=O>= z;@Gs4Qz(4usRH4-j=Q)%;vBlA$WNC8mI`-txIVE@T%HF+C`+aYoU+b&G4cmOp)ROZ zohiNrprQQoO8r{G&HKugBol=$%mZ->(36Ua0azr=^446dW$=(lU|TmI41HwsB(Lf& zrAHA8vAJvEJ)sc!>O|c9#*;uRD^4*b#08tINhB&4P^@U_L9}e0K^r*5*FMQ{ip&)0 z6qrKA&XQJE#%!(ycKI8K{&!-sahESFyqL@s%PW|vV(Kz*kPNCOBoP?64Pyln5 z&<$n9YgR+rjeM)UqMZgnIoJx5=%nZediYnm6F`$w%IU_{ft;E}%cZu8%}6J@mqLQzCB!X4+|aCmJ3BY^5=Qg|+@ zQuWFwrm!gAQu4QFJo&;~St$|vM;*n=R;LKbgup3_5&NZ1DH~epF~`N%zWd|O`z-tv z9v;6`t?=>BW>ReLq)4HNGKgYpo-h5Bo>x2X^x|LO!4Ae`3IZhiF(>8R^DqwD_jukd zxo>gre>Hk8@e2_(5zhMvr78*{1r4?-4kQCQql}-T@71OSEw3bo6G^_5;J3}5XYYpe z2(yIy6*(KF0x-%SG?AYJPLW558l?eV*}2okkycu~pH%LNyUj-)ibMwwB}ODqh?b>F z-hm3DRmUfVhfn+2Z;D*sLl_7p_$gr)_6t8Ht!RZPT2bk=+L-@=PWdg*`U=rbqMQh=Kq#sBDrUM^p3%P)6et*@uXIXYa!Qyn=~(L&;-bMEHOpd&ykGLn~ghNUGR+nszgv0*+ter;x3$Pk&RP zI6_%>d7@fzgc5ZMX06rB>T_ie-Bzztz=B!uL1z(k;;>Xq!I6jY*|h5f5&gW0a~7OO zYYxf1!H_2-;hYYH(!Uz33@HnqsC>u?PH{byr1v&a9cbN8BzjVO%+&I1x^pzd>vQ#` zlTK8MP!t2FyfA2M_2+t;qXwv4qkZmTQy^wJ@SB5dQJ;Iga_N~g5d=St;%gjQJe*K% z)|UFET7gse#&^t=^mk542BG-4DSwE1z9yID>Ew@hrjY+4RkF?_XX_6I0rWfz!z^>r z3h=Iqw`tqdDYNxc2B*LyNjK4rPfg1*W(+u84+x#oD1`=w&+7J!tvN-Iu0cWYjiQ4G z77%zrehS`7{0W|4+&6+3cB~!uq!lf!RJ{4aNk-pCibIqk>A{@=_vubNO`?GTgQN5e z)Fcs#SZpGD#phc;jMD3Z9?2_RxZ$G=6llc}3P=DwLiAl82t}uRO5hYTQ#=$0Wi)FY z$?BqQJa{7Es`SK`$9$zwjy0#yuTj+S+qV2k9h>(~yn)bu@A(v+@%dmk%9dq`%QA;3 zKc(m|19BO(V)dN!^_(lCH%TM8TJ~%ba?RJ$^=Qsv;pgx#C*%@1MN!y&Nm51SkEaG- z9A%!MQ)>JPLR?~WyxiN8=ke@f;y)@kcPlHJg8H@jE2ZK$K1gR2tP<$s}5 zFl9*qx$pigbjnVx6ryNFuiyJAzp<<0eoxDj#~N%~vMe!qS`ncTgHGXZMVx|-GN;rp zt2BN3!y$%EI%UNvn!9zkNnJ#0dt6(sahrMEo)1!_fR(sd6N-KgY6VX5#)Q6$C_+Kt z_(rnKU^RO9c3pxq<;kftN6P7T;SKX#iwighz_$}0LK#tQ@R=ZrneI{FB?sALsY{@C3Cr(9Mkf+npLr&FMkwOY|^ zs5(K!yA<-~=2pP9o`tPyuZRKyf-2#=&_NeZs2Vs==$}~L5Q=^+-|-2s~gc(#mwAOhAYS72_1g7r4h}aJQhsa#7_fvpd~Y{md8EGe^)5_ zG#IpOdn+?$?AV}9fLRKJvIT`tvFdEvU{A=MjhylZp}a{eo0wgUr+)V5lJ`9Dn{p7e8MJUS{QLV^fL8r(jlv?rIQq~itx$ehp z`Cbvha?S-mWm!G>zO2AcBN3!im^b0ZMVTE^DBw9$qkfa|Ges*pbfY50lgkon346Ol zXN!YEA!l;;bk&X2iW`|F*Bw1>QdTo5@>$U)Xx08f0>lnPGwv9ycCHnQnWFkW$z8`0 zbxJ%s=yl4PR-BU(X$9!M9u+kpPcR#%ws=$;&cl3O7eI2cvLe0(P)uEP$(|C z4zZxc*TFZjOp?u7DqKXj*~~-)SSo2^arL?<6rwXz!hSXvuG`JB>O5i-m@?a^Fk|CxcKT>ib-a31GHla>u~Yqo~1q zD}MiGbV*{>BlvR09AWW<4F-`uIK-^H+5`O%JLuDen|-8H5@0TAQc3(L#1 zhBDT1Re7>Mh4P1ukfZ#m?eSKMT0hp~B(=?C?S0>``_<7>p|JO}wlB+y5DIa*iFSXW zP9!2Ch>|Buq-;zX^T4eTt-uBG&Su{LCU!WT0!?_G@=7|loqH6mH1DmrC_)i*GEju& zpGcc%*Q|d6pppk8FSgJoUbf`0oAy{J6p55(t$(%0VuiwIg%nNzCCr^z{(wc*<7<2! z{PPpE8(IlEMYN)LY@;0uwE}iCwS4?)Z^f37P6>awA`7s{A@volWT#W06?#2grwm%j zP3Mv`^)}@azpmqvs8g=L?&~iqAe~;TGHxv^e;wv&#m|x`0r69w5Jd+-FLs(`$ti*t z2>MbyF+e+s5j&?fpcQNv-sFK+=65kopLiL)A@8kxjYILdW!?KJ9kvB*P6UvP)yE%^ zP9e&g<*V7njw00!O`MNm}kJ3qy%5OPG!bQ?bEDqQDL#%lbS11 zWvN!K^L4{1b9t@)hgRYgiYeYR@{a9@wTV|HDog}F2`1>3OJ>n`36mOl1M7*VU8iZ1 zpa!*vv^7?qiw4a6)-@uRBK9cBgIWPFh&nr>Bo90hCS@^eMI1hQRO0IT9uy5!0u~+$ z$$TP031hN%d38W5dQDHFDp@SVhq=~;kJ*Ay!nB+J|Jl(>)F~pA{awg=wPM7eR(|AU zt^FJGDGRtWJ{?}vi6#_z=t*QrC`3dGTT~vMQm)ci^;VyY_*<$yX8ugSp4RVd(wU{l zp4VK@bPnXP>{i}NAQa*`;-S%!o|7oVc8{S|6cSSsmrh`aE1(bMwkFjmcM31KxH!|ziDIH#qka!fG78&^`XOSC` z-_>t6S(}L4vp=hoK9+)?5(q^ikSOMkq_d`#Hupki)QYx~W^fp;if530UP`@M>p;A8 zpQT#9yiQ3jPHhjT5P|NmiO2=|a4{fhKZ|TvqMrMzM}A5emIJC>WUu<;h%?D7f1Mr* zkT}BbP24@CQ%Ia(;Jl@1g`Xe#NAgEbH*PP4MQv=B^Pt!P`AKw&M=+;K9vspp0QW=+ z1zJf~cOHszan`ewX`&{Ph=J_mL|GO-UZJnn9h~NAd>nU9;ER2iPOpbN&xjP$;Xoc2cHD$s8ao{Eim1k_8cpI3<+x zGHc-%(TYD|4A!$MPJ@V6_He&jp8T4-ew6RGsF>pWI)x~mvWw;krKtO(@@EXx&b!K) zd27#LCAH6)&IGS%Qf8}Gx;F8ILLJns`R-4Mz6b(Xr0zsd!QfaS1#%I02$C%#6h-a^ z>QT3g>F^PWybqFasQPl<96emD&IKvCZ}CI-NAOm}DT4UodbmS-QdD3fPb6@PXypKM zQdZk!R|-Y)1oR5m|6K>)Bz@WOfxl9<(oupzYsBmk{_R}q6yoxxp1n@l_ke5>vyb*@ z7QJUTYUNjXEB1y|iSsFve-o#!s@K(x$~QWte|1i&6s=IPzB6Uwo)Q6i^6DDn#5q7}GwrB+ghQ!8t41sE|tG5=(( zQ-0amAIEcGKc(X5Q-WC~5x9&io3=nJ8q&X0?X)rprM73p{*_yq7xCO@D$}w>0N1QG z(9X5hr#)&4Rx0{F2l2tH7S&B&)6gR!lzozvEu{ep~M1T)%}uC!n+`tweRVawOX--PO%B) z>-E>ad>^d|?@y_y`vdSzL?R^Q`pfV>i|SHtCM;IFPN`O?dT>=Zyu;N$_c>xVl*^DR z{Co8-P%ixg@zNU8aj2EcMN!Okz$_|Nl5jh-HUgp%L>B&giJntDP2>irL|O^9uG{nC zrcRQ!^Doy#UXJ?^BPxQ#DJ0~;kKR|)sbV=PB&_%+$~}>9!ndTb8--jRttXUuP@};h zFaA9^@A>JQ9*U5R-v)$oy%$_%`583os9^`uUeS1skRJJoU|E+jnD85GJs zhfM?>I~1Wvt%O7tGY_0Hz=*w8x`|2-ODPrerH$4aI9i$bs!l0$G- zJZMIV^eU|`$fd`$9O}QHJ`wM5e`d!UB{ZkWS50M}yB{J!Q7Tg~&doiD{@2p^9W{gR z4y}EIN1SmhXj?UQNhp7O4tMwsCTZr{jY2sig;I2qST2cPAVTr)|1bn#rP*{(&S9N& zSgNSk&Q8L7rBs_7-BJN(%mILw>x32iw$BC39Y+wnSVjvVL z5jT*MeES))^AbrH#fzi>51&>}n$e&Yz67&~Q08jpU#@J%pc&l~gW z%om&z6bkvW%L5BM8-KEyx=X28)+(m2#_*FHNCClog))e5kjuGuRo+)9;LF@;liz1P z<#=NsEm*kX5K8n@Lir%Zmw8yE$1XoInT3B$KmwGZPYJ^o-3Zu(3%G%;s^z#u%9W6(rI4Sy&y5nCT4NZ zkI=yxltFcq_^SE!OCy0+bTl#9vlt=!ZL%Kf?`YnH3J6-M56~})fE=ac_r)s7M}kUd z5+hH-zX#CA8<8Jao89n>kFd!^#lcycDWU37L$gCvGM_KV1%w#L7Vj`|X6w^87e3s_FYLjIPS-i7v zMbAYjfPWZO&wI;OgwhTRam<@NO9fllp^a_^b}E~HI74^GN)$U?xh(~D4G7T;>zzJ8Gpa&q{b2M^4k1;ZDvx4 zcYS#(0j}dy)bUwvatnoz{+9+KksqX1-khUdJ1OAz@lg1%kGH+en1i1piMUiNBe$qf zhz#jhx1_dOfkcok742=U=XWU`Trf5U@Jp-Xx4|Kf!a2h?QOuwc`7BJ|P$B`kKVkZ| z5v5-!7IdmmQB^H=#+Y$Py2dzYf0@ez}LnM_U z6f2O3E;c3RVUy+Q&Q|_i+#eSVRS(4B;=n! zOU02o2xotKBB&Hn9@I**f>ddSS}7ffl%8m}eoKQ>?lRZb=KN~&m3oI;p03LAJ~Rs# zrsH54z&xIo7_pGmucwT(;)dL3#B(ts=l8s0BFdN#LC_!ukGKeougXdBYn&Lv*N*$g zVR5?-EbBM(IJGt-&*h}(zZAh}xF;@JK%fKTiKS+PN(Nt_cP9~M7dx8Wyg1^`j*sQ& zp0IeSM+3fvZ2LVas(J#a$OnwM`I(fcP-2HvJMjTJ<->`Se>{eZwO4604#K{bH*+{e;svRakBZNt_ZuCb zKrY1di5GTnnz=2^-9}?*!f%uG5Iy+`U2?Pxw4$}xbdLH%E`&#$Oto@|V&I^#NCmj{ zZqi~QidKvWOgbg(RZ7ViIms8=1YGBE&@iw%-uycfl`sfrU(Cy97LSte*Do#qjdTqM zAQIWey4z5z7}d(U@58%q8`E!i#wW5*j0+_D`s@$1;@KJ&4`+Xfnyl4q3v6=d7p_XN zT60B)6wBwdY$u_N3GJ4KPPvQY6mB5QZA`?~3odwDtwf(iQUwWZ@qp9?8R<4Jfnmc^e88bNY9Btrd!~6td&VgO;)Nw3`Z_9ifCVPU2dv ztamnpFsric^88_bO6dNOynFV?-I*3L^w_CbN_>i(#f|?=+^} zI%cV#ua>8ol8Bd;hEB;ts)$xTQ!DH%4cp|p)zaZ5%&RosoPO0)^O5H{FTYAbB&h-g z1VU-6r3!w3ZO|!;Wo~n{M0?vjJHRPg9IMeac_lG2=Z-(3=x|xp*&L=|;S^K}&;QZi zOPJi3(&;+IcX@c3Bng0DoI_XOSLMSM*`@qtd+ zI4{hz=-d#FV}IV`sKqR|Wrv6-xhP-LN{?^r6reF#`6&=Y!xo_-l`veNbHhZsHbnPa zJso)^A^P5}8-$f(a$o4U2MR6-sWk;Hv&`@%I4O~BA9t(Vd<)T0)6~8HxuT!&;FF%jX&n{)dCwu&*+ptb;dIJC0pqzU^E)a z$(uGa0#}))?fe3>%#(+8ls|Kw?a1qk{VDFip?$1e;1L0TF+6|Oiz$_;Tf95gQCR%=M zPuLwPnt(pS0UvS7L?je(%KIH3B82jRTG9SDVzSR&6=1(~2ki&0$_kO=r5?2fF0X3H z3c^M>eTmoiC+HNUia3QK$ZRYz#9NsMf65q6(>sB?fvy6l3=xiT%hCg_8vIP8(0GJvdO*t9FpB~Imr*hD(3oZ>~RApoRsC-j}BNCKf8E;?=Eqh+WB zX9Q@+{b22OQO?MFVsSZ~B1U*0{1QvGBKdNzA5v`NjC6~8KZ_^;zsgvQlW>7XVc@gJp7I$pCG zhlkRvsa|mBk5eENamwoY9^#r);ERn;@l#jrc#&^$x_Ldp_S6Xf@1znw#t#h{{QjpI@=I0lRl_@I(p8zH3}kV zg~j?m9E-9jo$`9sExOYj{Exd@h=+^zW^6N7<9=vYSVey%x+ls*funfLb2_HU*Yl+4 zfHXaj51%#K-gixo-t$myylS{)9d*q=wB~0bs zWl)b;CUdTL_IjP)kwUD3R7rBaNlJlM%GbRcj{HF@JVBLY2*py(lO-#yE)8VOERZW#3_GU!nD^Zwpxx4s`w%hiee_Z?oUuFeCbKn zvnmUbBEE~!{yBd2e9HT0e~19?{Q8F1>St{gN7KiLRTOm46vev>znZWc8}d+S<=hE*nni2%awQUapb9?-|b;w$g{DZ_p!m zDWa8@c@AYj9~oyv^ucq6({j$-h@?9P22&3w{oY_Qi5yxr*wjJSp=8njVXTiUf0)~`&N{H_IhGIY7j46 ztk)BsYt&`T1edCZsy@n*CJQstI;yRqbV?ISsdRsP98cQ7c$dCL3B!x^+Y6L|UE)Pb zPxz%NaDLLC4|g#2$h=}_IzCM+Lg8}$s%_QIodxP8KbL_f$0=n-5XVx&O%FZ>wE~r( zO~@6cR^Gl%dF7$Z2tJ=ri68dIsTGijKsVQmTmX48P?LMk>&uw(cE^8Y)=seg8dJ6& ziQzZRr%WEn)r`7e&<(qw*{(VxcFg!!`qWU|Pe;6dsEs)>_P>NVmri!PjH(2nVy5d{ ztCc`cC@(}u&$*AWfAmlNbC%jsyufk&IX_2kYtQ*Jf$v81-tG?+3gygx4h0Q$SC-@7 zuW8eCWbHZuMv^d(*HlOK`Zzy{fS##X6y|@t=wmYRv5kjVws=hv*^Ad-denSVGTuIBd$ScsKG>cNh4<+ zPyDsaE8wOeFo&`}uqd_(ML7_&KCJ_fsw4NM5b5QDwR+ zS+pW=<(g<#=o!zYO@n1_nza}%PbWxA%(#8|sh9>OK`wsz*mdgN{_i21c~!!|D7_W2 z1`2}nd*~Fg#w>6WpK3Ob=Yglf))LW{etxo_XqrG|*{tR&)z;ahp0(LcEwctaDJ$CB z#+(~B7Gl|UcurA`V3tDF6Wm!KLIKK`_xSLQ!ATMHRdT77m8tWB+iaPJOV}WVT_Wz#BrB~YPbfi!@fvU!+F?ITi7cMa zv&$XSI~>IX^9YY^kWr~{%8}g8ltMM6+6O`b8bw*Pd&DWgYm?8_N?3^y)XLgbiGB(( z?-k1Lv@!ql6F{HiX_#5OBUZa4oI)8N%%>bpL;9=&Y(J|K&q42WZ$ zo6Vli)7If?!47oOhETwBo#4ry6g7z->6)Eu+aV(}OwC44k=77#$V}a;l{i@|=o}C+ zz^j$0Q$E>23x55_yWOAdUX{FmPJFvh6ggWFo#LldW|HYKSF5NME(4<%T8{JNY{$UlFdv;H;Tr1MDs=#d>O za0*SFJ)s;kR`ltSSp*pfr9;p4Z@53#vzeWhlM-k}F2P zQvTEr$A~`_?wn|t$~DGnCtAW)(X7ghO=^Y7+MYk-`Jh=Dcq|oe0>4Td54G@}p-d!9 z%5&p(X|$YiD=Kxtm;{08I^9&=EA$PBV;k@KH!s#{6Oi^IrP>L7Br_3;ziK1-s%OTf zXD3b(p}e!1&Ap}q>Lwv9V3w2O5KaI&weqG;`NbcfPt!)V;#u?4xK}F{=2=u6k+T8& z>Hf&0g;wB{ItV2xhSQRhVZ%r|?kCAo`ROHP_5B=(${umMU%RWEFctw#8?2 z8Sm%6?a#N6yQl>b!-$>tZ_r>8q4Wr$ya`w%+|fe|**`a@P=ZJS%lp;$8)Ox~npGig z?uyv%RayHf(L;IPH~EvMX@5RMD?JgdP>1Va;X^Bh{gMx}6qtoAa4kK<`&2+PLBI4w zI)$DQGyD0`FC8sqPWP8-=)RsA4QA4t_P=*%VeS8n5?SW7qTr62D_><hw z)_9&9Ui)65_~&p(k92>u)}TK`r+7lyR6U{R+$LD;|5;}!h{=_^BItBgmtSrjRQ{89n zPA&J;Pz@2eqEOdy`e8H8dURkq@`MQf=sc20I+=VGeE=LN_S&OL1V&?7pil2+)hf=g zMgZI)|Mj`bCm~nGHMS_Fi9m!>MJP~1IFF;a*C|W25@M)>_%2bE9|7IYr-1aQ`X;}? zPg!~^t36%y@LQT{hnB6NRytGkgu(~ob|9T7mzEODQsEkV%Ab^wDrufMeBCc}N&=Qd zE_HsFXk|p%x3fbu{t@<n zI^}titvF7(X%;xaQbDH`{90}@)aC7yQ}W+Yz?k1hr&wlOwKI!2ML@7*lG$eJ#L**@ zY3LL`NB^sp1^E2u(DS04>ABR(>rM=q@K6jAL3!v0b9aL$`Ae>$%yGog^FSzz8%yIb zek2qukM|V{adQG_6SsR+yei*!e2!1=@%i;qCFVZla-k2+>*pfw%#6R< z&mt7P*?5!iF!YbaETypC>67`FQYsQdJMP(OpmWCl*Xp_Sh@OWtI34|~rp@&oJij~X zkT_vN-fnisb`-k2+p1^tB*7_uS!5V*(^uWq7E32ZgmN9P#b%Qa`abXKl)9uaaf-%4 z_fxZfR%eG8mBsR_A1D;X4<=TK!CR?z@~_8|E?usYCka0#^C^>Z+`BAJ$u_uvrPGTu_GT#U3p z9}}!uCD(KBck0Fuk(Xc8s9y^@AeUO9{(`(89O~4po&@$-tIMc!9|JYb3pXb^md6^ughl&XV9fJ8t`uv!jzhxQ}VES8e0Eqrd}>g*kF*% z5%C*7O9HVQn3DO69DE*aS_mbtJQSOF-$U`LWS46oWxwt1{o}}g)Q1IZ@BK+6+vjQF z(QK5?TBi_`7@epdP_K$Z`2%1Uhq)SV@`wPrylNT$@RpNVxNJ}W5+kSQ$a0V9h4yTy zRPT8&>GNbC7A(lKK)Lk%YK=EPfKUK$X8P8gGeW;;BP@$lL%b zPvMT#4m=muzN*+Ew@EHHHI$9q4q>lW(f||#8Cg$spV=)EQ4YoMzJ)$`0`3y;)}i#k zM)8|vwc$;~;d?avCi}auGcGupS)5i#1A??A^%g=ik|N|_2amARkE&3 z>2;3`|HgNU|MW>Me{5>h3tCg7lG*?BruhP9# zDMFsH8jH3D`V%+>Riem_`w-7M+E{P!`T&ve+zM7XL6ViwooQrkEe1&^AJE*1Yx2P&B==ycjU$Qh#X( znozouu|~KBizlgaIg@n(|6bxSUw}&VF>u;=NBU{+`8)}yKqyELR0bNs6pB^Zf~?2K zEm&13%Q2MSRY8l7Bl9O4lp|SyXQSD)EY@;4WovEkZlt6n%x6>SQ8+3J>TmXF%$71$(z1F>*Ihfd-)f z&;H&|D05ng6L19D!L^B7y_)NkRjc>TZu6N>$^R~f@(FWNcs5kYZJK5N8T>xxjzOm! zQY%cEY~@Q47LG#FDbNaZqrnK8Z15)z1!AwWPea=Lk<7U|O>}P37^fOFq_dUKIjxfg zFfK?C_$Ur2+1J_cK45=ZKa%e+*pMH!RNK# z6l{*y+O31XpbPoUm$BExUyQTN`iab^y^!jr16m=fA}eM=o*-3p6dFt8M)9H~(J57Q z3)ibgsJ^yCTi72Lxyz<1$#sgwys#kJEgXlV6(cFCYy9Z6IGeszKmLFmz6eAY(=Fj`cv!Fu*{${k%q`g)U;aaagIvR zIs_r*Qb(NvW|3EBBjAs`qpx!f)``OAUA!6UMS1#29<^~Mij8B4tTBsywrLgIMocFG zxt@_wW_RdJ@4#HpDQ?-5+XIEdX&s%CXMDi#>G9d`1B&;@Rhd4z% zqJ~336f@$lA?4h39~JSG&MAl#(#EYFV}3V6vZW(Q`k-P4+fiP!!MjSEhI_|`I`EBJ zftXwk)vBM1`B@{rjii7gti@2$S8KK(yKujy&2U3C5G#R7{NC;nNk_8THH5GiNpa== z!6B9VV=MSApMyK?R2HOGIQK#;FOw>#L$dihsiL9$K;$x3e8?YuZ(UMX*r9}2Mt~`x z7##H(K>^J1XQj;oy>JkVpt`f39%921t(YI*?M#sV+ci!>q@Xx*h2png=JhGdqni$V z=xkawE2Ih~_SMIS-tSZL^<10e`pCx@mzi1-PXEvyaq-nHQe~XCVrb$KrHZbUvn533 zSNskL1(-;gS}}r1Bx2+gts^mJQ5db8vhdi-lqTxT-w3jn)CbhCBsuAILII=#5hQY!+- z9|#3#MH{+5R^L*?KC8Asya4AEN^D=zM#X`z8F5Mac|s_W3lM*ou%2x(`El1W1NJ771ElNn%94QObjKXp7qMwq;F_Xtzh{EbC3p! zT507=YNeBlNT>Uvo=zgNLMz?syV67}N)nBEpJ_&;$_7x+Aplj5p^b4_)=?t(Nem^a zI?H&+`+CYUvy_?Rxb?7Ouwo@S(<~2E0@g)J9#27!A&s6)R^#tz6@CzWNGkMNrQ>MYj;j>s&eUsz{X%BDiFKJb9rNS1U#Za`6&_d*vvkl|wI;L9O_}RJfy~ zVzrpmsu)a_#09Hl*#qxg(hf^pFn^=Jx{=?>P{)`>@aH^w(!g>g<(OC@FG881u4Q~a zpH^bc4;R2O()C7RoLg4y8$#Irn(rM{s>5wR#q5~j$pNhlQ+I8IBmTZd&)B{R#r@)%0i zZ7e%2{O2qNr*uD-YEstgQ$Fa~RwxU0{mCc7xmppeNV5oCr*vAmZk+rJwW5Pk_oGxr zRfyV#B!>R~RjQ9jG1RIX!cDDItj%PVAL&tOrPj9Q3I#viQ&wk}EX73TZ`o2P5h9C5 zE*XV_7LXlvN`@tcB75MkiIfV8>y)J!%JW1T)&+G+!(m;~`0<_Z^HzwnjO}4WZN(kJ z8K6D-EL&Y1C7p6ysUpZlKP*kOB2J;gJsN6dtQ>VBfKVc0&?$1zDOkOl^aptw=;x8d zT+8O>{QwFC0im!$AI+jpL0KeMtgrO-xI%HidXG=EG+X*SH|d&tJCgXS31c!yY6UA= zd5K3*oszYsO09@f^yQE+QJh5-6Gkhw((}^B*a|v@2~R@EPBJyg5JvewO(?M- zHzqsH8d%>Aqj=(PIy9dRt2)K?NN#~^6IrkxNqNMG`#9Np*u6sL$AUk*DKVxMw^zaS z5o0DO4%CVqLMk0ZTNJ(>JE27@+%luzBKeb`MqIuHYoh_}9PaM)$cuPKsO$mnRV!Jj z72KLC2KG}yHR|XK@?EERmM5v8T~R1U+IdWt2Zb`t_{b4ze)ic|f3ih)Jpp1+%jgt- zg+wa`O$JmWqLRuw1o5>v>ElJ=zgDoG@eR)e$%>msf*{b#3b;6>vd8LE-cKlr28qaC zy^B!zlZo@dbxJG+Q%0R)Sk@`8d6ozJ=#+Pqw`@Hzn;vf2B4F~^X{AhPg*&C>UwI-p zrFBblGbv00uApAvT_a_nQ{=}$E3Q+RDNA5DO$p)Ljy$hieoUJ{AC?>$1D~=`KRU(Q z1yLpVaw5GR3=)~vumEBxPAjOVlvZv@>pV}qY32)p8A1_eYDFPis%fQGx-VXUo}^P+ zkhTn@imaUe$j+wER*K(5Nsg%0!tkF>-PAX7N6BkaSic+4fwRm^1%MD{^|C^q_epe$ zfDh9CWBIW?E#={ebw6@`S&zBoSs`L8oSAh2rIZN46m$x8E0o(du2n^MpjJu+V@<6} zTI3iVFg9U?)=jNQr=VpnU6Z#3&QUf(v-xD{x3Ec#!+OL}CD*$AQK4Yx)hJk2P#=ra z+k_H6Vw?bbYHaMYNb@B_G<-8#z#6u{zW39 zwh(=^fly!~c2-sf+7gS+bV_w!WV%5mhK2bCZ;>ZLolgInD3p>-a*F}0IwiqG`%HC8 zd{U3kLo2{144!OanV_SukF+xM5D}UYtsJn4R>rfBfIlh}g?o)wPOu_cIYHz_zE69* z3l+coE~GJ(%eM@mUu;@ktvJ{N*l(OdO^Ol9NB8(Vv|`NS_u&5Ri&p4nrYIYTN(cax z1A;`L66}ePT0w&}GC@(rAWgm;XeB(V0t@WpeUXu}UM9=_MMN4y0j^5qCprae=#)v6 z=dBGsPn_lc$KotjacliSWA)^;r$e>2<9drjngz?hvLh17W?+#N#zZyr3%)odumP=L z7s#dVo_*dAJ(0sIr-`Rbt7Zl2P?DI)LiT4ro?@Rlsiu8mCBOL&0K2m;9iO58W(M!_rl8~cXdi$ zfs$iWtt2-M#zs8lx6sG)tTd8v-sbFWS94q65F~P0j_YlVvk+|&&JD7S*ot7jctrlF zP2_;PZseLSmUm!$VhbV^!DA?{EPjepP%DC^y5plq96a4d$#31ld<|H`XoVXQg)#RG zAR2Paq8PG5@Q7BR5@?9H3|Xf+gZR3mxZQ90+XYYHY{7NPzCrHg;Qea}(*gLO9_Ml=kgh4 zHSUb6OgUwCr%!!!%7;BQWft#a_9{tNC=L~~h!NCM#1sWPI*nFb1FfLF$6+oV+TX5i z9j1Wza+41#rFzUYydUqbqYb2XN62;ye1;+WlV^Og^+_ph)(3=CnbxWlfOh+ii$9K5 z9_8ZV*{+O{Z!5NlYj|Y9-6x{o{Db4QgfNluz&dd7k8^_nbZ~Jr`UH4bd+`m`zmrQc-MKFTPk;J?~d5 zjtyE7egTy{&kgzfGz~N$`EB&>!FWx5zO0IgsKSLmFA{0veE+^;YNh)^_petc%;Nc` z3HLdzD56wOYqVl>KsIng+IT;<^7`kom2|4U{~xQ?XSOl4ve5hUJfGGR1lEOXwQ>wr zjGF+=!mnbdm9P2*iM&D~-ebJ^Ox@C*ZaS_=F!2{Z&x6_7$H_&%v1k^3>2W&NVkPF z5g7VU=E&vu{2pIO2Uadr}aDQR$_!!mMCVuQ~8OfJP*$eRh}_J&B+CH z;?OCHOtXkX>)iq*4A5KjUcTsF+<6E7tt4La%KezZb_PMKJQl;-lOp|9%6^{bK%`eU zU@@1|&)^B{996X9rQ$ab%EH~)H{V(r?ytkuiUT58fFvGtlfQTUzT`)(Jc8wZR3SX9 zi$6n*Xuw0WcM^)B{I9(;Pze}_Vd(y%f3g4nJOK^_LJ1N(dhj0Qn0g@8EsL>ov*Dt~ zw?TVVj??lzH_N;3PIT0jxU*&gSMnM9-2-Kb#KoMBoJz^L z0DcL|>`eZU=-sS0cU&v@H%sXC<&|p3l$%or<$rw4dWsLhiskzfgasc{7Ca;m%6Ir*gqI*G~VFqMnk(ZJ2kd@S(9&o;~ z04gi;`R_|*Za=lyxvc0UAS=1D@EBBHX;Kcb#nKCZ$v#vd{Hpu!A5gS?o6k)E*2{`s zdl`z~@b`D}Ye4~6FDp5T2f1HdYCLnv|2hT$q%Fj;fMpFFKsx{1oxVW*lk|72YyLaHSc)i! zKtMDkAiWvG{<|hKl~z@NfbgM)fCvhMfOz>Q3Oa^>aA$^qI5mQR;LU`9z;(*)RN?>cf6JbOwIRDkq z|E=n@s~n9mqr#yqI{r`NO4d- z9yp5oHq~+e;pu7m%v~a#WO!W$9jwROR>N|-F%@|3__6ljGqSXhJgo{yb=^Vw5R!?T zqW{9+a~J3e|3Pyk$lrMN&UkAmrKRW1;B?=h!Lh%WN^x-R-%nq(d2uII|IDO&N`f-a zJuN6X75^HbaPm0b-_uKU{3_@2NhzckV78)R^=E`ZVr=Uj7RZL~-%!ZU+i_@vTOC zZBKg9ZN|n-wN2s?YuqO!k0@O(Dqdc=fA`XzU5^1A>Hp;aRDI6;r_=l>>z0cj&C9oLq*8T0_KQNXIVOIA8)^waD!>l$4mQv(vK^m^ z-^{@4!`~&0PO5F)&2MdT#M7o@5A%jvKa&eQ@W-?AUxKbs?bBK=@;^sGSC7rUfqY&W zdcvyvkIGMxFHJ_J1 zG}ASQNrIfj_X}7nac;vi=Sg6AXaJAX$d3EQ?ZoO9TAcH`Y+cu(S9fgL`{dcpdhd2e zAX?J;!fR)isUsrX3vk_k>8iggK#t&g?Gm#0lK5Kpx^~aimc&q-FpdqZ^D$-E=HFql z{^)xu&`Z+J_U4(Qc`wvcrS&oKQ)jQzQmM1q_qLtYe)vLQ{GVG09hf8!ryn$EoA0`( zy#We6w;7?HB%90ce@aQDS~rta@PIU~u17hK?s$VTz%${C5Il)w#>ADY?{@{|A8 zM(<_k-qOYU$>>}jjh3E6*Zu0`*5m6|Y;dpLm8ac8oD_~b52*NdM?zl|iI>D+{ov1| zeth+D{nNs<_A6d!{w1+ZtWVkd#~|May#0p1=UZpl zRUMyC?$4ECFP}*sCjHsAGb)3%&DM!A?inauy|ck&Rh-PlqD7!YXuu{HS#ziEWwC7r z2z@VHM95sg&uxvdW3F~6=j;sW#j~6QQcd)%i(H$h5!P{79)w>7EK(LF^|*umtuGc_8@Y5Z?aM@NItY70d2L;j zt=Ho`d-0j`-dCaTpHO{)@pFL+OSp(W_O~r~^yF#(^j~7L9zQ{64@I^&~-3Z1i4q7ycU7Xf7g^ZhhXyuOzV&Xhk=8->Q4P@R1^TeZ<&Ctg~L@rTLnC#T#bfi9C4%LwS}qK9?^q9k??fnX!^i z51raCmGK~4mR690>n20^HRHpLgZ+;H2zl#wY;f7)qvTbYnMdS5{q%_wyljP9JE4wU zmlFx+wTwrpK-7(t0R)>VUk)4r7w0SLh6R(VLSW&Nm@99AuG`b=59{fX(%$664;#^C zA3Q$>@bC;;p4gVBAgIvxh0yurN`2gm@0a^HL8QmVt?qTasTEa0Su2)6Py8?Qyje_s zP@&u`NYmPJxTII#zG4Kv9|v&H6|VVv_e6A2RqJhQ&>?cxM_4ZP?bxZn7Cbg}T|{Z? zQ;a4jO)8^h8pgClDYU5$YSv$cN9d9gZ!8XYvseR$zRwPi;f^%DN6uQ@jTGe_x8P5g>iMvEFY`br*mZPlziMV-+Whc4Nj9)S=C}LyIojFF-QYU< zGmJqXStwTNz1ZiJ_A#M>W`^{a%V_82idwDQbGy$e{DO`CiQ+!G0ao3)dPx4vDhb`y zP#J1nzRlL>u?(qxpy@0io{F9~qxu-@=K{xlUi-XfRY?!#=ZEdZCoPd1mH=aOkfz5l z4Z~H~6y48NjQH75C4c%K_SzimvY-F(LaMXTZRFE5kzm7s=cmHdItCV<_9^gE=}Nxh z3rqJ<^rqvyI0#dxB;SQK1;ft4ljy8=Z?9QoIWA~l&q#C==-|F74fpL{t)@+!D6^Mn zoU%DvPk&Ljm3k{l#Cw6rYHw)DI=LrJsr_#=CT^LDaI6&Qb}N~6iYlkht< z#dV`^OaXVpN&`XzoR$M{Ff-s znh0)z9qn3bJK$gUK}&cBMs)Rkn>B~vgX|!5bbkz-_Zf0;ZM}b~HN3>Mrd#ZI82HS1 zR0d~HMdGx{K68`b|2~Z|=v+op17Py?TgbmN3tpt0S{F^R$aj>HdN0fP%PqQ(KWXwj z8T%bYG{n1p(0YTcG)8s@fBbUaKtoNCBhf*LyOwKFs}t^vRTRsRB~f8~ezzID^4^pR zqmvlt#i=`1ZR~vQZ`)0d)R4n@5DNVJnZtqJ?*~RBmW9eg>mkT^vuI)X)DXJ5)M_ra z-)XF+%&+!U%OTLH6bGloq&G9^tdci>%_GWrlWf`N!j#oH$Y~kywr7nnba%4SJ0dh0 zFYcD=+2*aWvdD?ms^fnW*E>49z`fIWhW58;J6mtFe32Y7ySJN$Gn|+4A z%M1#vl|qG16L?|+(r~9|o%NqV}K|<41^oH*e z$!@w5Qt0AR3sh-)xYRPbs#xwWp+~1VUMMyDL(G@vVs3oqLl!@2=DgGEF;0xrRAz9} z>j45*=v=Daqv@CJ*ii=Y6WK4<_vP;nqeAUMRXZs&#qYcB7##a3ys0yFoNgfeH>cp9}1HRl~AFEA2FP*Gmf!A_Y zDxDP9c403JlcXM-S;_Rk5$ETZeZ^%oE|NQMjyn)ZI9y zd$u=w+LZ0Degx;<>tzo3T)Ku}Au#}Bb*9KlA;au5?Raw1`vxlEU8vp2dTk($7@+Bi z+C$Ry$=LjfxsC&;V^7@q66#f(ceX{X#~*2QoB+2zl9_oghd#B8t8T8T zty`!%$JP*MMpOkmeeUjyOTNO#H+qNZ_aCpH)0CmNy{c#mR{Go}7ncFEqhhrTx$CW? z9N^2x>+9_|$3LTUtCu}&KGWUKzL!<#rRRE^SMw1)|L!fS?7FK%ef-_8iVtD$y5DN53Q>6*Fq-$IbyTj zA@a@Um)q)v_CPBr-j#!KcQ2`8Vd59ax(k0X@an^hgX@NQM^nyKAe-Qm=D>Oxlgk$O z__4*h6sPHRjVqj*NA0nv&D8~L)vD#RL+9&7yTH}AJC$xb($L%VW;*TF%bBtGF2m@J zTS+K_ow7W6-*V;|DpEyX9*=~i`lFIBnXKH7A~_*L7pROE?XMln0%DjmPD1t`<00Yp zsEiK1ucMjJjs`uB$FNDYJZ0wnem*z(mV2{Kh6lQ@I1>&j00?@n;+5g=>fV z!-B9Wy5_HhmjPrJ)1l7Y8?6d|$3AElts_fYWxYG7S3hMQsr1}cQePJW&QpYX%pW3A zk}qR7{I%?k&h|hL@|(*Ruv^W-fxIWJnH%qWnp@t%^rid$3)Mz;F=BhVH1}~Ub%vdf zo2M8LQ`amtOrh9I(;J3D~WbeJ*L7#jXC-;)!x>jI#veHdmi2b~$Yv!*WxMa^F1HDV2w|`Ui zXMtquwN+xX9p@DYqNoV8Q|(=r`w{E>36g?4@|$J9%E4LrpzeB+q}jmXtF{NdS_3&I z35yN`*KCezX1iVnsqf?NL6J_Ab@OlF8jpu~MFR93x3v?ozWLb=3>lHDdLxr6fk%TV zL3h>9_U|eh^dWQ|DcJ`~wkpg`3$?zc$s_%e zCikwLdXmHDDd3XNC!bc~Ld)wYx3hp3W4(TTUw*vnr;Gk-#eB;}PPc^ym%IBo-*9@c(ld6@ZxcZ#4s$e(Wq0(Ve6IH++94LbMU3M zIO^T=>_NxfX?`PJwfFsQG1BDBmmeGB1n=5oo5WS;-e2gkMv@?6*_j^;EL>qg>mLIx zuH7FKCk+3>u~3co2F4x z`?;vqrRctFH*`#oD)=kfcVEmbS0Rn)heqs$qzGMk*q8!A&XY)`tRe8AC7a*rW#o_eD8R?EiCWNh2O@7~LACw}Zy z8CZb+ptPtdzS7(ZV0wl8aeMP%OlKeWO5ch z9wF(F`+2}<+jNlCUNb#p@6Y-7V>*A0-_n?VaFSC9qx=4(y+&!oJ1@Pf0DIR$mn3fU z#cF+VgyQ1!9DmaFuvwH~COxvKP4F^+m6y@hW^Nsy@#e63m6h2dhons-!E3TY!PTPq zPyQki@Xcub6uzpf`ldwRwTyE*XV&CQpGEg7Zo|j0dYm+G`J1QgZ8ccIg_=W(($Qy} zv2Dbzo6SKtlR~-i>SH%N&y|{eoN&uTZYz^fposIanEocjhUM|TE5LJ?xc92}XeQPJ zKF+pnort4C_bq&(5cEfRbn`W)=PdP>%7k>1Ya^@{r|VhsQDM2ux8}1LZQ`Ta`7&eD z^RCOtHDOssztX#3d{HXSMbJL`v81y??k=6slxqtQLG91zB>LmZJR?CK{*2;Q&9(2; zZ|^hD?fTy3o;UeC$&Lbjxh%+;8uHW z(&ezZezEmE#%Zi9@6+&7tSGuvL(uy3v#=5*WS2%ZA@zgA3+R9JVHgo|l z7+EVkF%KjmPUfkxo~p)?hF*OWM&`xLyZR_AW1q_3M79>rxr*O(31lEh+B_;A=9$Z} z^jmPc6`0k%jLGrwbpjdt8Z=zpEIqo`)nG|A~v0Wg9^Szo;)6j72kkn+yirPraS z!FE19=U>LZs*%f!;J#Io7k=MSf@uidBlL+#_msO`QXr`Gn-}=yUbD<<7Z!PI(L9y) zmxvrz$H-at^3kAqB*JVLmb!ZQl^^Hgj+%#UcGV%e0NxSC*dDrI-*4$F_)bNMtNwja zzS%!a|3NxTUvtcYA1P#0=WyL(<#s-Ih;d1XpvBmUfdJ#dW_W@+%Qf4Q$*SR_zdSC~ zgsT&O_}ZE++icPyU!eEkrK^Z@owTdp{u7Nvo0JX;Hipk^Qn?9TBWr_VVDu>)lYqQ3 zSwKvGOUUQfpes%Tt`BSILBOpl9QKB6~fmc zyY>y&v`=Rsq@2fDWOB`%8Y=|s{k%d zuk!}v-m3ld;!oz|Q{#&&&u-q*iRlCIUD7?PkbUaAM2Z5}NZl1d(=R!NqI*vOVd0mNd-Q6vz>WP8MHRx%p#mj!5&6-l#(+ibH}S zA)2PHodj24?dBB1UoCk8gpOfxk0Z6cxV@vb_H_fr9QT_O_}@t^ZmaPp)BV?*?Th42 z9J3Tyd&SgCsLmTv47%(rQmT25n{k8$@ml&#+4523MXu~L_a=BI8;`2a;3Vq;**)G1 zqj1$b2;R~qq(bCDrx6gr=1_OXIJt1ff*wlH0*zJqbkNaduGpGM+z~l#o}!fIXXrk z%9wPwm^}QqG9`^4U_oOe^W$%=#t(zkXAaRX4W1J(o0nC7T1I_WqmLG`4v9Ra#t-e( zXFlRJy;K(OHB%`W@@H9WwcdxgC~QKG&Aw4LrWsbv_73geUheXdI)6T7THpiO#Z4bE zITl-D43@|(tTG8rjj5{#wax#VoZZbf26`S0VO`uhw_sQxZ}Z$Zo~zZW?O`-`{+q20TQk;)&G}vj0k|-4p4s(hO7+R)16r@(!CXYRE8nNb zcCBHE=K+%)P_Se4FUI|hwbhg`Zf=C++^)t(g2N(fDaUB8h{uY6Sq92o`;(h78*1!3 z%Xu?fs+|sRY4NmGCQp~lBFG}zQ=+C@$m62>Qi<34K4@$1QYnBCT+X^^jQaT7B% z;*4Xil>JZUEcb7_+_rj!oxh4hRh`5Ju5;kY?s&&jce9Pj4%eS$3jZvYfScZJKUAKi zSD)bU)w0d9CcnOl*ASz3c?6Ac^wwmskf@|lN4H7VT>QuGE2w7?_EYQHX_f1qZJ0}M zj?cpWDih2_(_Z_lnaSbL6G2UfWEJm|re{rKXN-H`*l>f* z-|RgW?aVUXrrv-1AiAbdldI;&X%DF{WV5C_xwY`>mo@R<&AMKlE-SmeWu!eh=OQxA z%ooMH*qwVeA)EG2=LK;NpSV+0@1>>ckHBZNvTk3om+P14$)ee;y`SoTJ|f9o+|=%L zSOqJAckPX(?su!4EKFhEm*YL~*L$~H=+Dt)9Tk)2-gCO!W&E|X>A|>l-5eGhlMMnk z-VF71Gf=is%eI^6n%|5n$9MYTM!0OOh;&@lF00eMR1~b9&M(YnjPnYAKdwOP_yjnI6;hM-;GJ2*abkZ(iCer)jNn4O;*(NwgE-OUng#eNnCr*OJ0 zoi8*qx-~B*B+=&LK3zW8!xCMaaP((8mFcY1e-2$BXMszSYLg&kd5&03(5HJ+N#=d7 z$GZOgg#N2zw8$RdRAb}EllYjW``_VtB|?3sB|B%UfUZKSJkjwkQr)H7*Bk4PtAu3=C&p{Da*J7{8m`)PG^<+rU_pfnoxNT zXQRQt>fR*inEWm=m)pR2OWi#BA*(>D68K2TA=y^F2>x5nDsWb$^sU$1|J2tVL%pWb z(A_=dSXj+d{`t6NQON!zgSYy!wd;piS&ajczqjZDfPoDrX#`4Or>QtlJ#fuGqsAuw zhwi~&G2XS7hqR8EsG9j-b{f9w| zW0A7>+Kgom-Ui>h${f=wNiBCBBjAz(;Tn1k3-2x1{?SkF-34RbQZV#tVF_7Gi6&j;3?{43Y{>YjA=A?_YYLeuM|L-Ns z_eJxerm@ly`*Dt%L;4lf@p_Q2XlXr0T5KJEBsG=p{%}L}srSIuDN1@?ZAaFKW3u_t21+kF~0l{^vY@82;1UeC=4{qENqAk*WLJN2mx_wO5hxsnori)MCpp zyw$uMu>smN<+aEv{QZ(gMXPF@&MbSWB50h8y?a&6T@$p*Y_8p%YRpv(@)Wz#b@u>y zZREb%fCBeQ^6F@TmqE-2+qNxgn-w{Npv}L$8d~g82Ah5FB>A#|w1J{)(8KQIv)1=T zj+);q%b~?7h~)jR;QZ(#wi4r?mMr6Lhg%pjH+#$i+KPg8jfr&JZO5YiVZJ&8Y#oZN zP^8%si_mg!d5sm0a3*csiixld3z%5-4|w z9fuXFOW`dg@p-8*To9vYyg2irGbOAcn04AOu)R9p)oxb$78tB$IvfT!-mOL1bC}6n z|DiU_VQ}s6+ZauMt=^*;v~LmjgA}~%9uvVOn-x|rTXbNRv2oZvKD;E6!{Y7|nj2n& znBK~yXTH`U#kKeR=P;j6?X*l`B-X6Ee+TYPORaR_Hyc69DdpR5 zQRC&rrJfeXm7h|PL~pH%V}m}{a|8_C4W}-Q1aW|J8*}~+hO*g8&MNq~ zbib<}jFt?~*q^J6t@qd}X@yFK9BxKl7yC-5_|P`&oeZ6SfdgC0!_|I|PM-q4pZc~d zC@MniQP%z{>gL^$FiF2jI|H&*guJ~r_C3$Op_%UaBWKWErGWcU=qOJMk{+BlO75$E zI1+S&tleNqNq0Ztg(~B$PJ)w`7;UjzK>BxYiq1y^g*D4l{vme5FF#CGp*xexIHj}n zNF`UR;l>?mI(J)-)7m6}2ksAT8%1N+#sUV+y?Y60`m8kv+n8a6)$4rwCq!7O5b95fsdZg z(}hw80;#03fYdR)R2OU6B#QrZlBgC-|6eCTVN$$Nb?QkD*mR%8jOgBc(sWhwS>4X_ zOLA|_!#_H9D}NS7dJIgE3VpcjjF{r=JdcNy{$lazkF<+@Gx>-#oFILE2B8T?dT+u5 zC*QZ5yeS29_;%+yehY6?3)wvQ7WMdEVe&`#v)V3?SWWmn z?&(|wuwxGMkruK*59?A+wvBq(?%%Zu7VJ%8%*}W~$L**YgFZg6@alenNn%IqP(xWx z(u`ALJ!!f_M#T4s`3(XrcjX+Fys~05HVM#7k9GGVdSpgo90Oi=3B5o;!)IHGEDzqS zAMdNnfxR#Hu5|$@x2|=5;loX4{HC$qi+G`jmIji0<7LJm_Lqtb$=`4D%KZ66FGDFz z0WA9xylCFwTXLqbI9#w-a<16O4AXU8irlPi@|lnr{KuSIVw*UeKhO)r`S84S{Tc{~ zb`!n%bO?I`38pCl`Ve&@yhVWC9=v>FHuE94P&WFsj`IdRu`jP}tw52(saoM>*Svx3 zzsm-G``kjGA@od=oUNUU6hYtIjlO~9d%kbJn&B9HH(NSeMQk8jS(cT`WcpBYqQ1d{Scwl^Ap(@a`G#wB7AXOcP)tz ze;rzzX6Qv(%UNMrOdFMfJSIvf%`9ThH7kMFhxsTuDhoH+wP?BDX~MNZ9YVW}k3L(fYl_GHZazDPYGP zL()4Oy;DK{W1w*0Wxzujc+Klv-%AdypnvlyG<4SMlbk)@i&QZF9x^g^8|Z^hu&>D< z0^cp+G%{1~u-8O->&y4V?4%$vd{~X?hUN*@x73jT_OI1P^)r;$1GcRO zztrOBZQW1$NTxE}O}z1pm6*j9X^I(jkp5>J69PAg4?x!PmR@E4#5}Z7rz3zmktmlycA+KX~ zmz|2xa2l}R@qB-X8vKnC2`zVv5GmS7TGz(9>%(L4{s8dtAa6NGPLhPg_eL=)u-kag zA}ca*Bh8(kE~iKEd~de@ZBK@W#>0YmE6dwY>d<+~bMs(0e-5{HJA6?ETUM)+WHF~!qCdAp2yBjstf1OBT^`8yESzd1`z^A}$|*W-TvI;K^@ z^cOLZT@m%9OTtGhaGhcV`zGN%;*y-8^)`o-o*(RMGplqmR3_>7aq)4!J2As_99@v4 zbK@$BkbeM3bE$;}tTwuT%xE+geE ztF-3>~BGQMbpQ5DNeId2g4o#j)J*v`#*& zjVQ0zOU&h#a}l_i@67IO`0qy`)oxZDNWjl@Z083)=oP|dEc_hTxG z7+hSwo!C2EJ-J$G2^KqOV!?)M*g#AAJyW^y6#-c^c^+vaqqZQoo4V zHf3Bgh(9&*S6E4?&Q=NxS;0KutZkh-!}#5D9qi@jjUfIgptm%+!0DtK5hbuXk9gIBN~%ITrEbwC>TXRh>dJm2IB~m2#@u z2P`KES#F4U&i@hUFmjzLtY?I2q$j+E4a4BXE|SQZtQfJV9({Y{E6T%53a~ppoj9>& zC9ZRn7vQwkc-a?@*t>Hf@dMa-&4kID}%x}&Of<=$Dev&U+bbh7#KwepU$ zS~0^Vwk6BS&BP0za7KKoGUM2KaFn_39InG?;Ds97+uQx9)G(tMMAG5BEGp6SOJu5J zdI_(Aq3iZ_Ce^56AkZb^vhUuVaO!7=>*nDbcwDuvYD*pjO_-dZsGY>?ZQglNWdED= z;$F$JJ+UCx6eg6_vG;Sd|C5t?O1Hx!u>6o?iQ)obLjc1Ae~U-Z(RE4`tv;RNfIsn< zW5Rl-3(Uzw)uTy1>9TIKixT(_yNlEpEWl)nI4c;hfKaR?H{tYt5|K)oDPAov#vI&J zc;q-GcDq(&$@RF6QT0el(#`BWVL~HWy^8zd_Ypjcl&5Dsl%K40bopub5j=f(1#INC zUCpkph|Ze(I-48*6u(-k)^XW~$iqTkJeX#f5zBgcaBsAR2af(|Rek-$LUP2QcUnr2y!Z7!G7 zzXA&*{7)g7UTsWB!?e;VP5AX$W9-?7XFiLq?0fp7UmYRd^YH%%pZh;c$p1z4{{Ifi z>PS@dHT*BSIM&gx`M-JN6pALr%Ku`L2kRC;{x_wxOo*m6ZmOFY2`nqG9RXap|Ceo! z359m#>TB-a|LghsuSXvh^2H##5>TBMsu&l8(-Np&!T`PJ*66XuGOrZ{Py$DX*}pdEf9y83HyS?=AtB+0DPwrCc|$CKEva!LsZNc@nIa#!K0Yi`i&mE!-jQqF72VwN-@v3zyG?~X z9wCEXqwJ_y#lSuB)H)IWwSs6{&fQf01(TA=!8(C|mvf0eR45^n->G*Z);>0%;FTjCXmR-32R{qKps-tEIKKwvbP=zsw zc{0d>0DyCC-Khjl@x;EaunLn8qokI^6q5?gCHhivECr~b715Vs<7F(jDOI|EWf#g? zK=krEudA{&Lirb_l1A9_NDeoFV>Qt)1b^%(Kz;DC(zBwS!2txSX=E>qcYw+WY#Tx--UV^@JAt+GxZNf`N4f=d5A@DJW7PacPI2Px~Q@O{9Duw1lp*y#L$8* zVXt6em_zgl0Ck9*G#hg@?H3*NYO;tBc!557m``gs+CCj*pKY;kLo>e%23ckZe+Y?z zL+-~+eqcXmC!LFpJv*?^q9_}L$j6Yg1!KnZECo9~e$NS>2 zO~hKXgdM_w_)>vGW@YmAyw46cB8ZN6k1n=m*$Xf>6E?~Ep)l4lrJRZgG7!}KDwsi~ zRtlP+;^!0xlb3|ha%Uzyv4kAs!7|g53D3TfF9hL2s?{Sb&hR*CSBv|F*MH^j13^g_ z4{)$#e}PuR-hCJO2D_#yZ=p?&Ohu&39$aQMAP-+Iy?(BG8Ec~pqs;B9QerPL)?p{c z^O`_pih9ffk2OAJ0tp!IK!C^HK+#n9E2yv>v;XEn&J0W>Rj_3>sacAT~`Ov|5bm>PL+`GW_X z3Wxc7@O*WRacp?l>%H-TAXdi}?1!m$L)pLC^6ZZ62nqMFx=@E$ba3_P@vn|4F z`|47%ki&Ps9MGASW)^DK55P67R_1?@@xNK2r-E(G7B}8R24=+hVvf#Z?mBbc#~ad9 zd)ufR%(zs80p-QZwW`Ka5v8=8s89|@Zo*bbp~!_BK^x-tri6fS28wECMCe6L2XEMW zsUbmPH4Ox%S!lCXZlq{rp*wq9hIk;Lop zI^B^Uu#j}x9i`KPJ5;Br4plKEF{hNj4@kK|`nbW1&CWbFD5><<_G4wCN5aKJqR-lJ1f}mbGxo_!wt| z-(Vrq^2;k2dJPIj;Y|dUC?YsM+EiN@Gt+uGCqY*}r~{@$0XMepyT@5#CRS!NO89e7 zCbndA8Lh|y#0Cx7;83tP6&W?W@qkIxp>F>{bvXQ=lgmt#Kk^iGfxXG9&zxAmX*owG zQZeVeh7)lvx`N{X7QfA5O(JM4QetZXxCAbQ>lu!+3(Xb?*hvDUU^Q!5a!J}Ra=#kB z^Y&pLFs0iM@$_wBp`W)Ddh!(Dr6=H@h~Eh#dGee+{PG@Y;ubw@pB%c#_hrst25xki zi6zM&^&;kj444F@-%d{YJG}`d5aJd)eI-mTHzU;Uq=Q zJXabn8WG=v4Nl!G5J;SVVY!%{u@35 zZ9{2S;g39?tnxQjWS`t~NhA8^0?6E;A5|vF6yl5D(K8*hOx1ydM~FG*!#QAuMv6P#eZ6JX56f4exFhvyWyZd0LmGE7lG=u z9;)FX55l7AV`-#5q-1b12>YtKH5dehBknzG?k%5+xfQvftAtjz@&ifwZb-_sV&uw&Y>YD4)!*WOeRrGD`orQCDBUN> z5}v3|)`$CLa|x^zN}#SqZeVsuScn|%6(VW@@u@C0Qy|EQdR%P74Xg=2Py`)ZA!opfN$t1={RX<@|^SjJrdnXjt z5^d?SiLpB(PHF<4Udzr9yp@wc0YrZ|S!hB5v@CbQj53#BP#k5ah6~*v$nZ>S@U^Lw zY9hWvXsZ9eWr-|gaZEje0%0)QR5fZ=e1k^XR!{}U^k#z0w}hMJa?!y!c;$x6Rxl7o zDKW2RnR^^xv$;h2O3B-v)_j-FU>#<<(}7HZ2124(OeBO(WL(b#M!FcGpCB|BdJ$zz z_KVUltHQr`CaT?xc&HS97G^L&F)#RM#!wQre9<^MBVmyslWaXkD2@@;5T^nFTy#{s zI%6;h;;m2?ddKPDr|(yEo`R9$^cs%0dHOJXzyYBPsWN{*`b`ACm=;W>3Aa3>!wl(4 ztIH)bmURrz6^5*{zsn}$7)Kkf^CjtDw?3Hhm;qJs?Qar~Vh$|NDt#eeHxf8`B+w<< z@z{lv8*&<{0H(VFiaOOYbtd z>>-W6_lKjNTR~N#%V}CD7XrScG0tL=u|v=U)R^QGLJL>p=bw=_Gu z0b;joZRBfXc&uHOVHUgjGUzwawuo&wR3x?ryM$e=2l6Ik{5Igjhbe(B3+a^L0_vDi>)fmI}?oS@o+H2-`aJf#tOuX zly}uQ0_533*@tD>7Y-d!AK{}b6XE{2TyjH}^-mv0I%~!h+AX6EI|IV()6F9({ zz=AT`X)A!SfFOXtLdoUpEck)1Y_$rAaTgy88NvPgg-$#18(9!uxEVxr!*>FNU}y0j z?S)OUhA1q*zX~`Ca^w-}-8lFF3LF6=0NPT}ld^;&1Cy%G$hE<-2GjUFUHNLEOwJGuk6QE4s=^`=L?g#KPL!uQXotU*E%bprqjK z5X})$_ox}#GFh-dkthO2CN@Fd0PDYf-nb)8_C`!hwc<#Sukk<|{ze?xsziIGLL+St zG#^JR;2wob)ZsCCh%B|wkfy{C1vNkc94v1Y&X-J_S@@GboR(X8R|^uR7&lC2M|<%mAdKGD2M8RbIg8hH6Fbuc7}b zACv=AV*(oy4z*1_a9|ppqKy=jM0F0WjquDUsfyN2}4S?IiEm-{C9T2@V=}l>bK?TkVkhU^W!tkAR@IGqr*d8 zrm4aX44m0ksA$pFH?oW$OEx8SZDW^mR9WLZmFyJ*F*`DMmsAyEALy`H^an~9jHQ{* z<$!~4obqpo-!PG|m5vW17l*j-C7HVb05r{tSh8|9@jA#&$jqKry&~co zuSwp>FFQ+Hv0*59jj7r#LJVWG!w-$2+G(K%qcRJ_mr{|n0-*}y7Rz43Eh&L@hug10z4FGo^%0=fVYie&lgPt7Z$M@tw zY(@eiY;p1&+SA0+`?JgS-v>^c_rIbOwP#mqZ<0PB_OO03EGTH}QRMZcbH z%Ps1NGM#H-{PY%|Ye7ag??kVe!bfRW;*#|r$iW+9{DbVOnjRh^OC4aA0!udPaDY-A zozG}d4UV?pChAb5oHHm8@LN*5n4yYnd>H`2{@vaY8BC47S*qe=B1%z+PbRUWT_zIr zuWIE7R-Y)RasKfa^N273rlBj~?!Unn-s>2$7-#@Rz&010eNDh>#v%6^vhKV`-9zg~x5m!iPd(0Xw*(~AAd73De)ef7-D zz{NwvGvSU(JpRfn{px0u=PbS+6R1^23*FGP{#_nYB6c!dOF9J2af@=*nYbbX)d>L+ z?&sm%Y_-Wtq5TjX{Uxe}ZaW~c{hUL7!RR3G4XXO-Hw%@^V2uS=1%z>fC4$TvAa%}@ zzl#~mH$H()P~tJ`i#$VwXhB#d59p{v62uS64!(?xqrua3$H_ z8HVAuf6vUm6BObvA0`!*2S?74q^^$6o6FmQQ1WdDdC1tf;S{vOK=%(F(5FM;{ebT` zSiTOwG)Q&TJqVTZ_vIGxB!VmGucY8D+ynSCLc zm7M~WoieS{ONWHbRE$%r`LMidm!sXD>exa9LmJ>vAtX52SX18o^F0%`z$nldtJIsZ=3 zS5*42d|FL?ZUYtA%`|AKFpPQ%1?fW;36ua4QjWX)g}PGhYhGS_=^{-fgrOxREsdzIz37 zS4U~CMcGLJnk!RVSbNGw;MGYg{|MXr^jQDeWp^Ved6!gJytw%`_{+ZOUNV;`E$(h0HT(;?va*norp9L zUe6)b`-uDSA}lbfnVQC1D>D|0N5SB!4-91SCEtcmAg#3~Ga#e&pyf@7mQm&`(9IY=Cy z2%-~DE4oN`re}?VKQ~q8v9*te-Rs`Yr;$eRdn$9((qh+OE4BYO9SDs zG6ns2G@|}!Dgpw|K?tCbbYv@)*#%q##fQO-O6#z2h7#nZCrK?^PEz;*ucQxU-vD&H zLTpVh!oo6@9YME3{-NE7OEZQv!wxaJkch}4`VB2CQ`s?Nl%cR<0HCnBf^0?cu&pR( za!5PN8DuLySC5a)hT>!>_%v*n)l5nRfSZ^?y?cnwCp+H)6zZ}yaCJ2XC_zX#CTIe2 zC>A%-geVeR*inO)g8|+sLrelByZ|htrb^5Z_`4kt#K$23z=gv^NZ=y?H^4;vKBC~L z3RS6eTKF0)GWe}RF&73Kb_c z9>_1o#R)o5SR@MtAX|-F9>}kUWgZGS%_;{D&QsW|+m#@tG~0?&hNY-P`fOshF=Hq^mj~k92%vD1;^H2Kp!IHQn2b>GkJxXJ#rVVP2zSuQ2IvlG>uPvLf7BqJW5YdRC`f=-S4QF zEerur6jscM*I}_6Rxqq6ioM7a8HUAHD#x}GVW=Ln^Bl$H^~j2k#Fxsnp?KL-6c_K0 z6Hu7y0V)67!$K@07Kl)AVWpKsKv8L7YF_jJ?^VBH0SbwEg#z?c$s#<(-eH516krw@ zN(i8Uf)nH=scm&?X@ChY2Wt>z#DWstF91rwIyOyoGCIby?uTPPIUfMU#K2*g6h1%^ zW2IFvZ&LA_#D7sI|J9-IkH}UmA2aj*1UN&n*=uQKY+lP&jI4#S35Mdwvj877!%)B! zMpz78sKa89SP>bDYL8ek!q|%9V7L+ER$LiM1zCy8M!7IW${ArRVvdgzfuUeD35Fn! zKB%&s9o|}$8deM%@GkNc7KTq-d=Wr_AQULhBtQwS1qclq%`*(BtAb_{ zUlZ`-_Z+~#t3tU3KNL(L9h6BmNy1r(^%wdpTa8eurx}i^NyX{?vF98z@O-p?}eh6A)J$FpYg3Ds?DNoT@byzZ6))Sq? zwvt#lNH3=S)xmdTu=GM94h7Hz0^3ZQ>BHM)Xe;lyCwh%@R7d+H3w`um~=oS z3$x%7jHAX87W<1`S2$}KiXo7QK4KffBfs~7^?L|uShTufHh#lSWkJOYKOp(zhlZFqeqq9|b>Fo6=L<`C6J7Z{3$;pQ)0 z=pz?LzXCOuoloJgN`9cHU?0xRrfRh(6rwHW)Jji46d@wH;3LZSpIqG1IAmY>lR zztC=((~|%TgcC#HptcjJLIgw<5l|q?)|xHXk7vC&G3!Sx2WO`(h^_c-Y(<>QVdGH4 zY$8t91FXd1lk!o9f@k3s{<_qC&bZwq!m;YGr-*>U?XtF<9TQBmnH>lpk#y+3iRfo>I#^3322?7?dnY3s3kz?{x z;x7kND=`LX04oBf(EK3Qq21Eau(gFG`&hC3LjECsokz_P>xl&@_QCA3DlZDhLvMM! zTsT|NiG7y`#i=$xVFjE7g$P3X8CwbGERp>+ik*qL*kv3HMPMQtSAXa$KDEpYMMBIO zXD&{L0*4q-j1Ywql1xm2L#PP={rB*8^)o=xpxAvtfEC)y!Wz6^kD*hWE0nOM%{O4% zGdHkGN-ME=d163e3Kw%HLFq}8*-cCuo(q57wD3+dEEPsodAV%XK^^aNR!B{QR2tH3 z6d#irUm1H?2(4gIxz^QyZh)5uK*1EsT${F%*D3)N%4-5*LuHI9Lcl(&S<7eQ6w~ST zX(|x)hzrrQDhCu^%a&q_4MChrkUe^Z7s_@teiw6>(KQX~1|r5?SGH0%r;MsNEvz={ ziQ_>0Z)tuXDSs?<9WeqA^Xk>PU9@VkwC~o??sizGSg~0^&&AB zHO&KpZax}yxB!~qhQt6Ln0FXJL#)g_P<9mJti|ud6d4u=6vQ$>$?{X)0fA>4Um8lYB3XUP> z{ZYkeTEh)i7*A1DVy3m3Zz+@*;cz4BL5ed<#YzRjZXoI{QdK8gQAG=jmnBtDw=FA) z&y}0Fa27S}`jVlXO?!$X8q%_)U|)~!=PUp)f(BoZZOl607|aCADjR45pco`74B};( z3)yOKP5_0>CR3DXtpnNvi1Z1AL>sH*3cMKtYQRnWm{TaGs$1HY=C=Wg$^k{?hFj1$ z5H2tf(JbGPDjIajtm5Co5x4kE5+;XJfm9(nhLRfIa*!!dq^=5u2_+zK6G$WAUSwb> z%+{+0XrE@vR=5j^7HuNBl9jtm{_8BWLIFi_dVdtnQHx)*`~NSsvm*MLpX(%C4^&e1F&PEY6+(&wgR^t zP?)~Pf3kR3?vFCtSF8!e^RLNuiOTu2c6jf-UMcW|f>w6QV`HM&M^=)DY{}5oAVLU>26L z!<&uS0fkqSqrgD}-b`UO!k~nJ2npV&Gldm_xxnx0Cg(LIfR*wc4lV}q{(y&=xsx@p zxj-PC$zoDOOc6^Wh(-48utLGba0e9H!~>y;E|3%wtfuF*IDkP|^$)Um`{Y#H_70j;OL+oTOrP)nnUeDRHo`l&@e3}n!i~tS8r$i$_0YYOr zJEA3p`+ZcgNthMw#*5~Qu);#}O%@twQkp|Z3Z_3uC(@`wVbYL%o!WFXleZHCBM89} zlg*|GDAZCzEGgjR2Iz4I6o3p+YFuU#GDpBAKwZ=Vpy+~@D6HYJg*(;`_w(}998fHe4}`Zl^xbmPEC)mpN`S494Nt*Bu~G_kNGuerC)}~ZVFFkQ zxUS(iC>)EgQ1gcZ9$!W10Y+ejU>1(nXK9B}ZQoQ(?raX&?6Rs~#kH*c!~=x{Uzxpa za(z62p}=2cjL%VpUlVx>C_$K|l8C1WmC1D%`=$XVHcNnM77T5g2-H3`pfb!+c4k=q&XOYcvVS%4RkwRpGG0 zqVLf!BDg`HJ)o1%g|m%p%8qXNm8lKI@a`OBh#_zcR=C$$w*|s!;eaA!EgLKq$j@Mf zgNrkVh%pzNZ^&L{POLS@UoX{$Qr^mM5`!v}xj0*GBPcIEn6h1TC2mZS>9Z^+6h_IQqIY&Qb_kx z-DeCg3I!Lx>NyJoD%Tp!#S5HBWHH=n&8zKG_pl0S3K(C4sz!tQHJrlA2xu&{EJNr5$unq$Fj#8QU`X(OAoSuiOxKlmf1Lb1VntCTtE~oi%-#Y zR>p~-h5#Zk0zN$KY{fzr*8$)n;EPE~fx@jS3{W&a2T0l!#t0v_jOf&y1bILNP_VKS zBnDj*I18Li<5pCaw_A239EustLj1nMVpTXpQMj^W(3U_}e2Q+FX|3Y>qSMDwVV@-d z@!1J0PPU?O^Q|fXie|xzPh>QuG8D;H&K^(U9v`rwkO;SsjZ+(&P!EN=et98l zodv&>T}=SRQhX?a81^Qov~MZxUdr2^LI6HZ1ty?FjjRADXf^AGp&3lUF}WKEg9r(A z<5f|Zw?))bd_YFfkN!d*GN_8Pa|8rfap5cq2Nw<{p>SBSGZ!A zEF|3Css#r;CE(T|Rj8#v{mMcfqg5n9C{jy$iLuJq(9BS`2il4Su?<^acdL-CkoDsL z2+J7+c|cyUQkL1`DUsr3%VM=Xy{}#=6|koONx>~jAw-Qurg0^OmR2HGTb7*+&Kf^0 ze6L$o-E0dfMV!Y(QH!ah%*$!Z*Z#(uUZmh+mCHa?yn^lLNepO z%h-nqBJP0Vgc8Hmwi1b|cykufsVwr8pcRIvu?j5q#$&uUkS%V-f)&5L%!(^pF(_W} zs2_{D@Mv0tbT2e0H!&R5RqPs&z$R$fTHTGU7-F!T9e|w2j_x0v#n`iuWjX6}h?}_g zLMF9^U@IAvFX*hbC^2(FE{~OJ43$$X`zY($!&Dw8B{2lW#}EQ%iQ;3qmQ9mJ?$Tx& z0TO#+;w7#bT(?5M4)GxVu;^7VNrItNWFq9iU!#PVN=29A4u|UMz+Cq%b)MsR~ ztpLz4a0J_JP-tK%R7jw&m{x|NLBfbJ5IDMvIbA%E6T}A#-se4lB2qiCZ4FB5f;`7Kc)b3mK6VY&1ZMy1hLptrTziS)D`^D!JjASxGTx zQH7S~^n9H*&|s}LSQ$5(YDittw5Jd8D?eJIGuwELCvy?JLRJn@ zDTKvWTGuhjQ_f6Y59KL=zli;hsv$x|2~lUD9WsIv@WtrddSXHXp-|4+;0`0O)Pm*3 z>H#KH(kD^;c(C?8%qVLFxCe(N7P9WB0B5B1v?H@dhmw&58qmIVa1%Hd|I2^sc+nMZ z%3@n_VJH#sg~5uO;no&D$Ek{GE48oK+ZbAj%RH=(*O4@ZW~oG}(HvL|`95M}!|;xU z^cA7?GHb)E^QJ$F3#{lu@!CkRQYugJx$+dnJ!8nbYNWKMoBaQyU5ib=PrptU`-C3A>%!L|j=(Fc`GG zLKHOGOOOnJ63hrRg_WmP!2p3vH`|*)y_idst{i|v67lT z5l|?^n4F=6HSXY9%LXrrpfWcQ%TCs5PLR$^)e=QXw+M@n1f)Veeew$7DXPt$V$Uj8 zS=yn8vDOAFVQfWpwWnCQ&gJOo^N;AeuAHTr0t)sVW0GPECtZV`05ei7 z)>4ZML4OIy6ljnh3{r~;%|bT7eM6~=?gwSZ7QH5r6rS}PATxGwXo_V8pjXtSrdM%ju$6UpWx5E-Xh2X+>f!V1klB-)T6 zG)Sd@LKA`vQ>d*k#;Wk*lDyK2SQ5eD^=p}7#UNpCJXXbFvL%(`@T{_K%5JqzC|j{= zWfRx39abvNQ^d+FUS1)kQf({cJ?9^h<3midX3$X@mfJySRTRVEJ-STN-3A=Mf`5lA zN4gM+uXC*jyg8Q21H%Xez{^8;3Uv0fY_VXhg}{6O6v9xT@u)^>AXt1sWGEz-Bpg=6 zK@hd=skOtQhK-8GW$8;+Prwi&2IWWSFwLG^_Ywr5%- zMPw^>g$VEkiq87kw>>mJ3_4+jQ5C_eQaW348-6jjSW(1+2^iNHVbO&W*LeFEXmAU{ZL8}x#HO&SEOfhNr z9E;Wk{=yx`&@B*he=R@>_`;nskzs|JPV56)H%bE(U@kb3PuHOwqz8FVDtSdvI!7{`=j4+G97M(d;5jhJuxx&CjWl9h&YE2`@cwq!; zwN)Z;laQOfbm zP!!EC_5)(DLNb`c^c{pI)YmJ(2kYjegsUg^x=pSTD`m8^gmW3E6~^bnS;9QfzRJi6 zQvO>ZsVv7KH!k1d8`m8}N&fCI~tLZjLkxUe$R zknT((Usx$d8=&CgwVa_4OA3iVDK|q2nB2-^ipTD-BIrIGP{6hVTOI1Hz#JjUHstE- z@iMj8XWRi6yvP=;sJwoypM{f zoRx?}6=rA0QlTELl@ml<%dWN++p*%7A5^v>T4DYXJmu{8dZ=lZ#-4~-IjZ2t30V2Z z7D=(2X03pI_Uk%}l+(mg_=0IxGpy3H?6Q_Ig=9a2uZIH)_&&mIC~O!I*j6e-35f7P z{9G=x2rh;Ttl+wqma!JtisBcPAc3veY%5@1iR=#wd3%C5TM>&$IpXm(h8i4DVCRb^ z^?7(cZ(8Uu(27(=j96h-6;cv`U0EE88_I-t+X$m7u09~o*^Qf&g~dduVp|q_im%MJ zmGgkPR93B7#bKJI-WFSMnoczu?m}ih9elFN%0wHc&3wy)+;kxcP}6yJHCFk}unmJn z*^?j9W~ThNNP}T0p@bOsnwa0xO{k7sip0eRilqcJ+s7g#akD zYAo1RIH175uo5T(Pl@aj;`S8b7<^v3#U@nVX^h0kDt@s}H7Rz>x*)PfLae8&5>8mW zZ7aV2rihiljiHFW-Ectzs-9@J+H1@K?BF0KU<#|W<_}L4v}GI9N+^c)yOfv+InA7^ zkQZ64Cf+VXgC-bU&j3t-(A5UZ|)g~^r6{$jJOcxMAu+@7MG?~qi+ zW7eV+ll%Z}Q4IZtMOe{P=Ib@=_EhK!My)CiK(SOFC{nHIJkE`Ii|j=b#IQH26Y&Pj zI&Hqi;!v2UmYF{t71$zLQXDoE8gv%{P(my)kHU&Bsy|%up-yFLRZ*Oa5xcGn^2|?kWpzydAdp%uU z;4io*nJVV~7&HTj(G$PbuFy&d@Uzl0j$uO+>Hrcdst624j8y@);>lAitBL{5q&TuL zeDQN|DV4L7$7f{A52}nRw*LqlN?0>6LiW(3!iABsxrD``K#5r}%4$M8bQ_@%yfZ8s z1v(1Cbp*AA1-9_O6R`)N1tosFg+&O!C)MqPI#qmd@}6by6taN>W#TE}ULMRr%7Q5Z zpis6V@)XiyU0^FJ#H!#1K!W;%7B3iOBe0cF#L_AbeBrhg^nTDW*K|PH;jqFLq5$i5 zh#3m5M5(ims5S*hP@^<^2NE$wKo^lkEUa(Eswl*8Yt0s0apfsKAyx&jBOF%Tz@_ZW z#ZV)%m9joWn3zoC%L59#0h-M+XFcc0b0e3)g_4sgK54X;igQp^uvQ*EPqt#m4yQfEHEzX?t?(JT8gfht(E7CoDd}VZ3h_NFnxH`W?dd;I zU_pZzIf^nmS9!op>+t?4%=IJ2)T&mOuLvd;j422{5T-C>GIfXU@<T{Ptk}t?z=`Xf<~zbfD%AxLI$_0 zaGs*OgzdZJ1cf4(R`IBrfNnl@W0UP|Ft#GrceMa1m5H295pd=%53Oz3yo zQ<%RAni<)F!{J4yuQSf#;Q->^A6-;`{JtQX0be+p*i9{Ev9q{ZSX|;(l>e3}+q070 zql5x~k&;U$2NY}+FjyxIO}7X=Kme}8b7Tk>7DqT7%yz{GzVw-;mf?$&s$fRo(PCXN zsi1-G5U>>vD(9d;C`*d~6B+Zc-JqeTY1 z?J4LD;ErN`-0jfGQ$$$tICcdTE|{%ov{y7Pu!079&j?e9NyX+=CI?yDhja;ZOD@liZh5@9Qpp@dYGbxrq~ zb|pw~Du=0W9-bg4#JI)Xy0s$XP8o&v=n<;(YC@1c_?V&eBxf$XeMdln-UB+so`_V1 zcP|uMi12J6!zXqE0?xuoiijzyJ*?Ii{069jbRW1+Tn`F|6)(0@ULTNytth3l6Z#~^r4Ic0%`?7vDc%e*g+YJ z&S6DRe5^`tK~f(-7eMoo;hZR?Q3L21SOzWWt$$=pjpArF9TrDZ#qTymC z1W>@9LU{_EDW(u5NF$x(9X$-GJ;kp&ktI-uSX+;X72*TdxK%|HqG?qY(Qn#qv8H87 z(FBh&Rcb8CV=sn4y+zRZOkuq{1Z07JK$_3RQtK7`#$7)MH8}h_*b3Ht+!=~E#OPZu z+e(;W#aAx2qWlBxDXOUQ0HFBrat{WfpD~m*(NrPa9;k<5&j9oTpg@xi0w{K6M`MEl z3afhW_$duzV@6q)-9y`w($2?>r>HJyQf7NfI8UL@V1cJt**#=vVZs$3CF1Jgktrth zGiHFoO}3WzM-wuD0`9hz2qPFFo`tsxA}~Rs-K;7VWa(>4l!&ABUMX$X0>KRy?dKB3tp7fwQ=Jf}DMty)&4Ve{6h; zRqPikm}5t>Mx)nQD2kAh1D$llnvan9!+45CQn<1M_7UDlj24bGSw}(Z;zIZw#T2l% zkT$8fcMkxHNy>Uy?TW)O1r7qG#HUc60+rdkV1;oOlawdIi^#($8$lp24?_tVl&!F1 zQTM^g$`nvsOE=kGiR1}#31FcC&_YiSk*6?*q9{CrnQCebR#u^ z3ho4kHvowN@zi>_C55q-@V2BPPZ5hMSvfmyup)wp$W4?otQ&NHO`ig=5)c?lI8UKK z8SuHYm4L4l+X}O)M5?+%Q-J_YEX7Bs$;v9HCjnYz(n1r{=PXhwrYXa)ry$b`PnriY z5t0dAsEW7xV~8dd_~Jmv4o^@-w&E`{TQSr~@wH{Nt^Bj%Q$)qbAPv=7e7*Aj+q)L) z#&sRYF4zUjU>EFyU8oCnp)%BkySPupj{rZC?0h!KbB>OV*70Vui8US!27@F^&dKnG z-Q0Dhj!(7QS3n`Ifq()$g^H$-Yb;Y*O>3DyOS=Stp{zkBk1>ZaV*fZ5#EHE$TQype z8=P4!Ith*}J#vW4CYPGb>~yf=KlVCk0Yw!)tEMW>nRfCv?F9AO%5mQLywALFDr03a zWs9%6tRCtCjrIVbEMteN%hU9dy7l=7Fanx zg@@Q`=WJye=`1IcL4#F??s~o9|CbxZ3845Q;NzUmLeOvkN`@|sG+)q8Lc>1bTPej6 zp$TD%2Q=aNAf8cH8audEY-d!TcxuDSB-Z=V&b;dQ~}=N*fRF-igMJ0d9gE&}=T+D!FMHP$)g$D;gpb z%t?tUh$)c|5@i<_dO=SCo`N5+LB=ae(sW*H5mXRlbu&E$&$yQdmuXP>W7!I3&>q(x z{M`Vcgc+ci=z~?w{*1MiQAD<7D_T|2xhk5clpjb=$?_BopyMeXFV2+645i^I%H9$? zw&JCiB-c1bX!KeibY*1oC5M<2*rdM*reJ}KKdm9GNGC{7Gxyh*9+sDK;r=pP3Bz6w zp5-^hH3$dC7Q-9N8An>Iqj?HqL}e(LoFdXJVoFp!BR$ch8$+^09gt-Y%Bp|BQ(B{V z#_VX1+&r|eXLE!7#2rr&wj!%DRQY4rid=t$r+8Fkqo3(1*F2>TMouS~n||||S4D9a zR8`a%F-I{_)_)>5EkOzR+&K4u|0r2a93_ckgn&em&XE9xLRIK2o|Nj)_h-Y(zAJyQ z_4CLzdrNvijjGZN8QSaI4h@r|5ZK3&xJyHMi8t)X%?wUDSRRi1O@^WaOH1Q z_~20A0TUrmz_nls?ES7)4;DU%DW1)8wRwbPj!Hs7ZlVZ_ft3vhbSp)m0+nE1h;*FcCU~WY>a^$&+f!&A1Ys#3^*>Q?hqSgAV80cS7&zKii>&QMI0q;Fwy zpsH-wc9nh(Xy{cb2ZwLdcj9Tu89QjbHoqy9iM=%2JQz6xfp-;RkV>vuDvGBxO`o~> zP0thNw)}}LTj_g1imfb9u@yh|*Q(7yPfP&)rVh@PnP|retg^K~E%ieV++c z@zPONP+K*w5!vJFcicgIuvn633dm&yU7 zVo;3vz>b5q6a;~T{V5(%rhJM=HzT=eyqXe%+*ws6C1xwMFPWf(dO#@6MwQPbP-3%G zW>lq8-|>u<{y7*{^y%iTx=Lk(n=GrJV+nZV^>I+tut36+TehB}S9r1yF>W zR3EMPO^)QMrW!(flH;RDydQxY%RBQKx05@ zRNKCf(f)!nx|B}0wVFcdPpZMToU(Sz|zL)x;9wk+eyw+xm-kGqFFDJe`+8qUH%6V@(B zMcGnXou!8lffeo6@B2POOz~ZkzBu0=+kY4**1*bSYI(+422Pf~@57VI1Tk}-;;yEC zew?;4WFmvdZQ+w_;ZwlA49Nw;6ewgs5MfN&T%_g>5)eK9mq?&3x1uMWLXU&0vcs!T zw}fi3gX(Wo{uI(vOGt8^7NU!jvx#o`Yto8{_>NO_m$C6yR;g5%SiiMTlv2w;%IuA?V z2J%`=@v@usB(wIX*wUW!!rs1zwKF2Q=l@WY}fj}EL3ZL?2MTjNHATKPNQvhx- zB_BZtUw;P#kohg9s<6aNO(MxLFdZMoUqGor`)mU98}y{Zw4=?VjZsU*731xaB&rPEe4RT1W* zyFVn~;)Fz*oI)Rp@DVyAl#sl_vp*|=Z$OuA29-pl%T$eXD3L@n+A~2GLrm;)0qGNH;Fy6@Py-lBUa76K zh?pXJ%5jGX-2li?hPO<53O-JhL_MDbTG&lRa&MhE-$l1y;-+4;VPs zt~LS`E`LU2fujwl9u_Jay|#u(>e|Pf@~6%yH-kS%36H`G!irY&oAPJOR;sObnR!+G z-KNj4QBuMS=TXOpl$4TekRCKN2n9=l6(lK?KE0|z9<-%|2ZRifMMc0U(l#Gj+<{Lv zO=aoD`cT^c=vafO{h;ln$XwJ)}=MwM7> zQeOGqg8xpSyA8m_k5pK#rp4=_2dk>rJtM5v*V!3&{!u zE}YE9J9yZl5!0q+ihoU<5l4^17(SlSiLMoq^#M6 zG!$A$s22~evi4Mk9>^S!toRV-(twCgr3~sUA=tI#(b=?Zd zfYP~a`$V|9Yxz1q<>zWB;||WWvokyUb_y8^pIF1|!8x*F7A$v>g{J^g9Jh*t*f-ov zh%-J5Uy#=xDxej=4$n7dx~7&h@74(H!A))RcsqDf`FFV*D)3b9aJ-q>QV|CIaumbB1W%^b# z6xdZ7P4vN5wc8&`}2pnnl#9}zeNP&9}%wa<*FXoiA$k&P>+rF1ZX}(b!gGU(_8C%oepEhM zOjIE#@ijtaK1tY0D%GX3C=1-Asod%*lR2QqP1{H6e{+7yN1d{M;yv+q&;Ep`=)z~i z@BzJ-*?lOtu0AxZ=z{T@uQEgQ4{8p5wvxI~jq?7-;VE zl$FayXtcqm!SZun^y+oB9a%~qU@HOE5>{b_ZL;3(OQk4DFxsNp5(Q9_G3>{)&4e98 z>DIHWPj$nDDAOWa8Fqj4KA@A;sKf2cqq*cX=PB-9D(w&J?A*U@8p#K~aK}es3Kl+k zK^GM!c_lz$NhLCZ1l7A?5u`kbLJ8sp3BU{0IOxhnl46xwoNR_#BXP5nEpQlmfSF_7 z%PL~p!91BuZf-vW8o58mY$cH1k;w)|8#5LiOsz6y&l$?vhq)~`@}nhTEpSR)wc5tp{#9BW}8oFuE_$26U@QO%4C8P+!kiTC2QuJ zSN=C2PIyYQnxmCemKIh{x<5Gk(@ibUQs4%2$sG80!chD_)KlE0hVqPVQX`k_Bb1hM z{EUuQ8e+<_EOq;zkd)(2rfMZsG(m&BuQ^Q6Ct}Wm;w$VbrE*536C686lA;3*;!EuO|tU-uP26W&5w!Q`U-sZCKe;CC_sTGk=l-o zJO%JhB*TNGEO;~5?vm1Lw}A!jY>1|7Gar96!#Iv`0ojTk1#AkOVX-ru>!E!7?LwL* z@9!qAwsR$Atg2w30dkXrLTW(CX32(Mm7cP+8`mZ5+GN&Bc#7sM^u;|Vq)hB8CY2Uu z3$;UE%_#fMpAsZTQZHsFH|^58RA#vQxZ?)Kf`uVJJozcX>`<;{Z6G$43p5}rNlZz|?Luv1 zs-EH^`U`mKf?ka*dJ3*IT}o|FZ?^PB@Q;98KoILhxpFok%^qIe3p*Cgb*0tz1GC52P1m=bV20*g&C!giDR`>NMQ?g2rB zwPa1!@+WeZZSD1N#iTY6%B~*-BXX}ec)SE$<^e-FJ$i`IlC6dn0hh&9$k3&Y7I)jf zD1Z|ExhQKuWGc!!JMS}QDD13BsG-0zQ_p~cvIxaQ+Ewb6i8LJ_#a3wP@)RI=3&%}N z(LALAl-WvlXECLbX@#Mjj1*cur5_s1%AazQO`C+LSYgF|HCu6~Sasd;8S#{OdL0`m z>3K>z3JTf0A($eM2%tcm3P>t}dZ@+RopCEDrs0d>4aF2$reUIL)dBiTStPoPI*Xs8 zLP^Gd=wgGwK`6u)At?`GDA=y{9K|qHQr52ISzG2Z;0r4g7R@y*bJ6-s4O@KO>nIyU55;2vDMVISkWk6`-VUS7GY(l&PEc%18Ta^prTd_DW9~ z@D#XH+?IF~80jf1E%eF^D8Bl;@V%=9DTY|!V|mn7>UjfLp@IcN(h3ClBr(@IL{bJ0 z#kaE8m=zOD3kI!(|<9fZ0^4}(U3MGL@ZjE{5DFXq8)e|p&)B+0jeWc`(2XnU-NJr!c>!Y0liZ`Ju zv#0q{1>{dL1zSHFP=u%SP31-0?I{5;?(q4Jb; zQ2PxhkMoN8AW#a)Qkz|fiM-}8Y_YNu1Qdo9+6|Nvrv&6$&WJ%SGoauSAC;xTW?Yr? z#)2*`-z8;N$0HzM0aXz%KY8S0oHjox?}VP2x2-(cPc61Z#N8Iw*pg zErn>|L56~%4G+d#WF^2gP)3OgTJ&z~llmGRJGW_GLIe5;PY9l&n;h>c?&4nxOEZ2m%|e zqLTVGTOnkjRNZy#(4VRp6VPeE1&fQ^F_)G9?{~_aSIqeBenQ_clwy`)OsB>$g7yVHA^Y!^DFRw$Nds3d`DMmdR@sx5q@UYKH%Z!7X^ue%r zoZN@0Gbna!nIjvNDFU)!4Z6{a8-j_qm{|}?46MMXh*_v%Ld{b|3n1M@3LpNvV)@7O z8nkM=mb+{9v$A5?2~w;f-^7K_I;P*-)S2RHL_TM`&;bLS;DSw?nJ^~SS%Z`uVj@id zg6vZJL2}TjA^6s4i=cAfV_-_S!Bgxcp}!(E{akYB?fK0HWvqJEIjl&mq>er~?eZW) z$peORv5oNe_*1Sl6t8#pG>^+%GA5_c63-%GKrsSsppA2PFkw(b3F{_{xJYm;jdWQk z<4boVQ3w-wb0PN>!Vm~h)TR!SW<^Y~utJ3ojNw;5iwL@M&CG=-hKi=k`Plg^KdlpM z=?>?-m2X3nGtSbiAL%#?O-|#)7Vk^iXpGo513^Glb zMMUo$yWJk$_zyOo(Ne+F0NE@jv(*p<^z$I%ie4`lNww{S&yzCeQeOEUSZM{?A!ot< zj^yU@n1z}NG!hA)tBp-2Csm15-6*`MR2G04c{SS^Wyw8g{3*g{a3UFpk}o|hqxAgH zjQoi04VUvu`Y>MWAJt4%VX@ZeDVCee7z!yVRZsaXskG-BiauLCC3WRb5}qP~OvqD+ ztx18_=)1~v*zEi*)5-ZMAk1v?nFmbcFbou>F|fNwAixpshp z;aIZNF)j=cDI#6ST_Dt(d z!->)MWOuR~VT$k+fee8UgqYQ;Dq5^Px8ZjhN)%A5HaxTB^pknY0GdE$zbi97{-W0t zp6v3ZTRa6bfr+8)GUErgal)PsewF}*Qyr<55H}1u!RYzQQ(}3e!)OA~Vk3H3iZw35 znjQ=*UWn6fb-C$C#&Vx0*FC zizdxi=+}mfZEyPE<_dY8vXzf`8aLlyOq9DqK`JB3F-Z21swdaV zh`PvizdDP!Nhhr+K*0(qUT7;6_|_~WrqY8kMOr@s&QjpW89_wzl!;h-t)WO@h*DCN z#dOM3exE;OpqpqtMe`IyWnLBb(3nEw#Rrs7$@36EDFY+;{_io^G3o=u79lm3IwP1r za@^h|&;ogRaN$EmklxgxcnX?L2vay-dq;wU;gy=FI1MN?B@F*uKyM39pd8;`L7!7U z$R!Q=AfSiD2Lj&s^R;1oR-+iLJUzMSF0u=ZmqmwN(xsWSw2;(GL86XrBO1VX3 z4Z9@5B^^%-!mU6LDk(uFswCcXN+}1Db>M5-8^=cuk!8+PMwo)q6JDTdD*@MdUM){S zSP`*SOthU3h0-cTLlFn<=~mNE=>EK(GU4}AZB+ho5%CQ<>ba?Hj@RuPoI_D|)_`WK+N*D^n`YT5- zTLde7dvQYVB$ue!rNE0gsw_epN^(_aNlI{8R5;Vn6dO5LMQF&-kV0M+MO(Po@!gWs zFtVt`Fv1i86b%^yF&a=-<*e1JN~fd{H<>e(o~MMLrKe~OZAE-I#E#ZVqFQdo!vPql{@P+-4L8Jx#EIkMqO#(eV1QV2r{9&p1;e(lbkAW7;+ zlSRc8!64bAObi78MGBuJt1ujvNH{r-+?)2draH=e(#pNB-QF*tv|cmw@-{v<4JeEz zHLYrcnLug@6C;brP4=3YTL&y~V=2y>V^%(jDYn?DV?o#q!fZ|Suq?JX3Yw=>XKfh9 zFNI-)xrLPznb!9jt;UoM00ntRbH>L7R`6)VT3h}Y9|{9m(x7%4^7d(}%Cr8I`_nyl zcuE@blyJpUcG``3R5TeG3aGXZ5oKBOteAq_1YgsR*02I|<6F~8t*T-R?A<9l4l01CP$6v(B z0tF63Opq-<7D}9EC?}Y5Vy=~ANLAWMTEdjpN{dL*1B$?ku$87Pny4x>4P|I6J1*qBy0Kg0F=@L!X7i)?UB3`k`j7`f<-tvWj&5BJIZbH5-15Y zha(QK?*j@;2PjQ7gkOOl*$7jVSuSL=>x1noyWdJ ziCkQrX<2yp;38Xo2vZcGG`h(ZnlxP=)L90SiVvfh>j6($El&wNd5l&R%~te6WxQ5i z6`PVzl5ld@>WTmA?$2jAQ|@+rCfpq6g+o+^rU z6?}mq+;f;}Qprulq`{QliF;Nzb^HaI7L?7F0RV8?>kLamoWd9*x6uy@^=H#mi+XyI$T09ZmC^ymM(w^^nmx>?r6r?KnM??^O zoy*W*4=deHUN@!q3@AruZ7m#>>^nl47U?|1> zR{BBWOx1vb`(Ji^&u6a+IZ%S+GiBN?NStCpwxWEru?Dpb;Ug@g2jMMRHjs(Wg<}(F z5h6;tDA@q;(Hk$QHZ-i5RD>m%Q0b<{NJ`2I;3Fq7ww%bTGlrsp<77AhdpiHof^@FY z(DDcWagVZpi1&E^$u@4fJ3Ot<~(mohK^5RD^ad# zT+s7Ci>Do?>_(~jh#pYRil^N0$ew#=Z@6hEwT}h}3n;0+l`4g$$oNyBr zO%Hj_Psu=1%8Vj6m64T*Qj6M(^BPu|u7|VQNByy8JJn`$+@-r5(9uicqNM6#b;hgL zaqom$B%)!3nF}Gy_H?Uw$Y@X~A^5-!H_nL5q$O+>F5Xcp;$nngFs}rAhOp- zyaEwk2>||-mAcW?3DMcGA%t5-|`?iPTO1yfhB*F(Y~-2W9&=p4-ccA+zklSP)LhT47> zYn=F2NHC7H9TjT?{8Fol3-MI=(9V$D9Shy|N^Rj~7ejS6V;U|tfDH$!2YlJQ^5PM! z7AdI!w}Nm>zK%y`vko0P_sWFQ!wRtyS{Opt%9#>qQ!?#KRuID*&Z43unMq3IGACo# zNhiGB&}BpMwm(5$oGpL4x#Sw1zw*p6q71?W0*WtS*TPDpun5r1%AYAud3s;+k7g+D zs^n1&#nV~y6!;yeMb;&KZ`;8Fhgm)=7e1`Bz~eZEQy$sTpTfiSaSu#4ps3k(-ip*L zh!MwqrFlxEYb7*>>Y#1dO10|CqOt{_xx-`tm{w5TEOr&H-AJ%hrc#glgLV!{sPRro zEmV{=yhxghmR+i>yQ^z^WpbH!Y-3E+Vf;_L|W_BEQeef-(A35GBO`N@gpH!jukBG_0h$lT5s}#RBJWya?X* zBjV%6Usi(4NSzHe>{86cIQO&$u0CXGN$QFt)uYj8QDI0WN#-kOpR})p1XsLHnYJ}U zk&?tC&wOE3Wg}1Ypp%U?l;DM}=!GHJLSF4wjXGFZg19*8TE-fr8DzfOI)#i~o?*VM zNV;CuZa6jlVIHCa*7>Op+N0ukF1<|6SWPpQ2gCl67|BtiR za6X{a3xp=2Mo%+-;ZKaj=CU0v$dEBD&W8dS6dgitkcW zX)B;GeAHo|$a~k%>z$!(AN}|VU9$rvCCo6z9Ny?D#=7R4j!y$95ebNnVrpPTrRUd_ zeBJ%Ip`^HPW-I<Ez?scy<$Gfge=(J33UKIN7p=ud#?=Kp7*&3{wULQACD9BZUE*KGc~q+Awe^6JFW zT#_K);Vum4`|E|UNgl~kB4G&z>l5L9K4u1&SX1eI_YI(&?9{NetBIV&0!LzYb)&3m zEqudJR^G?Dsu|@)!OGIX$_P`u;wB-TP4P4!GGZ=83{DbyFqCY~EV44x%6nu`m?C0| z@DxM}DRw5X(hIk3LalbGe0av^C;C&ocFj%zWdtIXp~R;AIp_)eCRUvKL7sxW9z3r+ zj-1pod&$mNX`y%7_yyyI!~%9{ujotzgD-==a&xpwN;5H}{w_UJPXHB6NsF?p*Li4o z@*V~ZMG7c(bC60+$zNnwCva&u$+JoVbz(qAFV1R%rh~hL17lpe`2Ws+EG%_fdmF7i zX062AcsHlHiPn0v@}%J7LRD16B%MPOl+VM&dMS^dPM&ms>N9c7CzY4(1yAYBDJ`Z< zQf3>Tl1^X+O|&-nT6cf+yic#EgwghO_fNEyr#vbCN=c~@Z?NEABwg)$u;hIfI<84Savb9$i_kwYk&nv6-45LSEibIA30L4XLYCT(&^|; z{TQSYyv!)0o}%!}GZNL1?S3LjmlF7GW6rZyLpX{dH~STFHcAS>mi`2Z>6K1a7|tkc zCb=qUW~Zi&ea}|xUO`b$^fsTMM*$HyHpNyNdV)+XPNtA&bID=c@o5{$+K{+5m0ZwE6$J*F7I zBHO4?6&mVy?Nqe#wy4{+wy{?WD_YAiYZblz3R;&*SC!omT(P#DUQ1;SYt zG#;FF12xGQPvtiF;$W??l$xGYSS)LN<`3p~U1o)n+PgdgiXGw_}H0 z8DeL7MbzAM9$n1UxhqG?lCa(C%9#Hk`!O2q&}El-f(8`+NBOgx2I!b<-zP|l3a=|Q z70uFVu8scMECbVk((X&Q`fIa>9qcMm&-+l^WYMRW;Y4z*V(oZYvLEo2q<3-1EDyno zYA5@CAaDdLwiL?BpVGT&&;2R>t8wA%+O7mU+jBf*C>l^^T^`F;Vy~(QPbp%pFFU|^ zWe;{+HBWIfwt_k+6hR9rESVb$2p`Hm8_qgG@`(6Nw6ajE7;Q)o`Ubj5sFd;|jJgw)V9RQeuFH>hz+W=# zoPxN6IKz}iObHfK0s)FSpO!y^-e?alqv_<2WTyCk#Y$$^7PI+>!aw5ib+i9fsVY^b zU4f@S>n8!GMBF~d>FVW=-h^ei=2%n@Xy+^sZZj91RppGGV2XY>4y1QDU)hTCm~@B1 z1<_MbTWP;S({)ns_GnH;1K5sT8_{3*yi@ze%ZQL!HBV-lgzlRHJ&T%n%0x`+=&&Bq zhEzHOC^73FkuW~p`avtbTF~P+V;AAQ9FEQ@q|u zSkFb$E)*E14*E_|!HGbs3iXu-8MMSu+!#}ofvq-%N2-eEDbhch-bZ!=;m`J`*cqRv zvr*Y^C~ZF}X)6EcA8ob_HU413S2gJULxYEMVpw4m3P>pbnzwjoBx^XqNNN{yXe41q$S)mGNss|~F(_rzTx zt-{bAV*V$DQ&iO^gqcZ4c#0ewWT0eEASj};6hz8r?oDXW!^Xs7Cydlzba9Th~)&7qbID8rl6MNHy)_s#`8p%}*_R{5v(n;B9?b%{x zj(D*d!4qe`sNjNx3H6(N5dsuhoe`wPPJB%T-)|-e6222pfz|Aw6q|>{TRqf-DjLZ!92@0Ql#Z$bQ^ob2gQ8PZ~d=^_h zI*aqAQGz+}?U(2&orBh&@)Tpb@3={_P|^d+AW@=}KYm9&rNkPPw-hXb4p>Qwr?_BV zKn7XF8!DY3Jnt!GbxY`olWpvU&9%K^K&Nrac~i)sF+XLMkOJXMNp+fZitPwcPh!y^*l7Uf$HroJO%tF zxN)(H9n4UqwBb7+`%UyU1y*F}W>><8fXnPy>#D$7G_5t{&DkJpkIvo2_K&siK2>*| z?C3F0S@EQ>&dNbeq-3So{}Ucswc@jWn%4usoyF-fRbFArfw`ElzLET9b0WS{{{uy$E* z9w5xsa-WzbZjQZwzDYjE4zbF7Q&q6iO}Kv?ix`)15#3cX6WzVsOO8P{hmH%M*ff$6O}dDK#z#xAVz(eS zab;I$#aTXeI@$kYe@fr+37u=UV<^LOZuAsPL`6vj>z!hy^*ao$l%v!>T2Ik$Q@&*@ z8!SaV&b$xY$+8%@qso1|kcXvQ=W0=vLMGh97i*%mbcW(-@wRVt83P=AZRTjqWDqeC z?)z*52QZ~%0(T$}t6~sN+&6V9dZLm%2H+y)j8}l=>EH6~sZj@I&GNONNtQ2C`sJ}( zV;amv4{sw3Ub=qj&BG5YaH)(qQUYm)F3&(u@uImP9Z)NNDy9UJZ(ypPw&^3D6cu!k zN3Zn%5}{|1aW%}=@JDdR!G6UdkWN>3CqKLyJlOoS}uPg$3P+Dekv zk0&2NK5^FW`~KJ;$5Do2cmha-+Xpn8>5Px?t^4QN${75bc?bF73RrONLw}w63~@;k7oLK!g1w%DrxaL; ztIQ=+z0KuP`I-|wrSO#PzkU0UDjtHqhlM^LHm=3$|-D32Vu(VUi z%~8=@CF6SvpykBbpxBB?v-DYY*6N8ip_J?kzaBL&vJ!nh>GOZPK_1KMGR(b>ROqF!+2fI;*x4Z)5P3>4 z9iPwuP!o}l<}avygx_#2-iM4aueVwsSpi_ddp~4C|!>XuK@U&&fWS4njFY-oJ$)hW?V>i zypJ6(KG9ZsK-nn{-ift@w@G-i*td&2ecj`ut+ZymFidq^g-0?y&<#?j!75eGzFkql zRjp#&bG~|4Cy%)Igz0SzD^vmP1R|kp8>6Gg6i{NBRdGtr@{tx(Qk@vC`bhND59VRp zFzg36^fPvhBeFsE_|0O;bBm#no0Pu8lNNgp3NJ;eZu%GWe0n?2}^U}c3|NMb9JP8yX1%KNiP z<>or2T=d#?Me_34AK6D!_ylzZZcms($b!?x{ptw;8b1?9)OcYaZKW4$!O5~~X;!9( zx+y-XTtr^gKWp~K&kcn#@{|-C%#sF<2kPPVah(|6!3tx_QLSL# zhclnyy)k-rF&GP+yF3n_@>q5R6kQW-UHNm|ZwxE`(eAq%0ZK2gj;{ND(5~ee8O*Z_ zhQ*3DjO<^zzxuo8PEMHfCDtSr2*Co5-4 zGhrOZUKPzjEL)i!`n#RWD__3r$K6P!J@?U0c}lQ6BiD+f2xfP!^UAw+%mhtIYMfvyWhG&Xi1=t^;gK3qLVgaRn?;P=zVPN%1*!8gd z>3PbCp+tT5%vnbM+Sl|H|4n@#OI3P*O6D}pEI(G+u4Xo^&3Q`6wka-^R3lViL)Z=z zJ%lL-xIh*>cqKEEUU-#E@w}?GY2|K0M$Dp4&=^)kLvals87Q(9M+OGjvC13sZt5fT z#o^!8*={;ZMZ{G7%?M<)m{MEO;%(u5&&*a<^;dAcjwmLQx3szHLqT~}aTC+!L7i1= zv5C=yH5Bp7Rz-G{P3^kbobp>M#VqiY$M#>->+#;t7>b?)QXQY1IOw2NQVgIpn6gM9 z+gK|c!HQRzDVD8-I`1>`q%_2&ZwWQqLcYhVa)0(Gb_+MoTq>PErB;< z$5e$fP!z1Fm;yb!ywa902g^OsSu3$A()Zyk6*Qy-s(MmKPjr`ObXY(slcgZXhGom( zYC{VW^?J_cdctTgvJ^fUCVjfjaj&5y?Z=n*%Q>uM1uHkYKUb=XZ@2tt4drB=SWvh5 zKg*-N=y(rZD!Thqe(r2Blx_8TFRa?PmhC>2jGGBlF}!V%6@3_Awa=qNJ$ijtu(*ZEvF`q&!uu>?c(CP_9ZJBr|AV<_G#u{+-M(j9hj`?{GF=8-6Gxo z)ol(a8dGKr<&>>te`iMdT2+~)GFE@e$W!}o^pukw&R*rGq)C$7B0NQ~95+-;4scTh zHLy|=YKy8;!mg30ERMDj;&zUb>WI|}K}_K+$0J<(9N$p+P^#_tICxE2x6GJQa1eeW zg;zsRb`LJQw)PtqLw%y1EG@pZ>hpeb4r=nFrn0JfjPeQ_2zdqCUb&Cg5z{*5M4G{n z5tCHnY}#AlmS9B&i`NP(wSdw|D7Y_KPYFYfL)j=;&Im(EGD)mdl2qd(L$m`szA*uS z{iLWTOOZ|<@M}_=7(AeuR7k|L>YalDY!p?9|ECMd)%JBnY&+W=#VVJO3n5BpGXQBI~s9A3Ih0ed|d z#Wb_w2W3bRlF}IP8`tzD3d)Dl=qXM4BR^$A zab`Drq>gd|pFYa8CG-G&`T?{$5LvJ*bYKcuzoA=%wuSPGymYTX+#H%Ox#b)LQ4S45`5{ZaX*+%)t({ z6@&^LW;7eKm|aE_15fvaxY@17c4ay%CZ77l_|B_6__F7q*&Z3F+3bR?O(>?|__7Qo zB%*Ks_3sBK45eW!$K4B&k)hf36PcuB=ooqv4H<_0V`(At+KsGCCS$V@s(1>`{>T$ZaG@NzvO7`c1~okCBUP^91XI8@YqFQf zqZmTu{;`~gdPjieJIBu%YaBU1K$-r&PCO}i-Vc)3EiF|YpQJlJeUe*O_$=}s*@aqv zoUPpS(T{w59uj-c~Z|-DAd|Al&DPlS%uVsfJ(K`0^J{YDHmVd zp3-sPg0W)2Pep|(5n<)!lGL2x^>Ms{$h^-w3%YN_+foW8=>9bBTLzTMU#iKK5n*rV zkDcC+ql=e5#AH_caIc!841~+D`<5`2!I=A>wnG6fV~$1wvJe&9d}{%H;6A5=H9T|cNEI~{X9<|(H$ z%GyoaXecwbqJII8^Z=f+@IetOn0F2GElx0}()0ll_aH1#^?1yML&9>u6GXx-J8q$o zR9^Qevf$%|kOQo&cCuL~^$V=nrDe53X~Gr>Twl= zfD}(5!+uf_(`-#`qpCwKfozA1^-C`M6+H^>llDmf`h0O0vlqvZ~6+ zpW@ZJzPX+fZg^7u<-TP9e3ps<^?vq87-M5s5m?b|B@{OPfRI{bD+w_L03}Jbeo1f2 zg{PF*+87@zJX7xQlApXjWm*w0T;q<@1rdkllFWgDtU8{ug%xFTmkHpdnp2CH&nPAp zGOX-kZSs#=`&2_+&B6D2eRAZ6agdCAR#;Tl0S^<_AV^NY-zevilobA-M(OVaU?_YZ z8`w;=Jrp3tWuME>wiwvJ;*3S>0SD*5ql=D@kF9!w!Als*?{QvCTFCw~Cq<028dH>0 z++KU_Nog5M*C9>1g{t+GmwYJSs-)b`roEA&e?wKt{iO0xVdn`&acsKTg#v2f%69mkqT(F zP_lGqh83UfN@HcZSGh{100GO%!BCizJm9B#{Gw67g67Vx-;oBCqfqh_zig!7(IzJH zB73R#r1X1{PtW-@p>`H4IqUoQ`Tf`@r~H%|A9v-Bn+*O;W`A_r8`Hlm4QAaHs=)}# z+k$Aa#|Nq^2Tg^2w+YC0;VA`EAb0k->wJ}uX=P)e@Y2AI~6_)YbCtE5KYNE zBDgz8d5+eH!m%lZr|2o3To?4Tu!1{!0=={irqoPXXc7|&96zPFVMQsJa_4t3V<_m; zKe+9fp>QZ9;fs?UrbgOvB-;&wX@DD@B091|@A2h$fgrV3Aq zD`p+o7w&Uxh4V^Hn%sZ8v9uIMlh%!$wYf5v_FU#=MxW)fh^WWf?&zvKr4OAnS#ye~ z48q*NTB38?vRW{JWll}HXT>DC@tFpQ;Vz}KItujjY>v2KVR&ap_3AjD`n@#H{n{j2 z9!-}g@Qy()c_eyPh>5>XQcwgO0!ph4PT9(sp$t~FU-6VvPs+_1pMR{aT+JxEnOCJ9 zlo*;3iMjY3ZT*RQ3f4XdD~Tu5%d5ZW8Xl^i(g0e$=h~;ZXfegMEFMb_JU@U?yhc@K z$_x2fcy5Rk$EDmnr4|F5{HQ|&kHj>Fn+hxAJv(EbLPxc_?L5)5P|jl{(>?BE4m>w3 zo>x#qcr|)`d~sSa@y*#=R^p8o8%nw`@;E*ipfkeC@e8$f`zIO70a!bUyBK|-*@qxV zb66_&~2$uYm zI&kP;W-h&%1;4C*@F;U6w%A%#^p{T_E!Jm1-VgZ~mWjf6kNN+OR2`4UvM$tZfta+eElZWXki8 zN06r=RS`^yl+A@9hNP_&NhK9?n%oJv8>qM*fW?&OK+%Mu2NE^-GEXV2L?)Y;2M;k) zO{5E=(%|q(`a}=5#!WPr)|K0wR|7ijwc3Rol?e^LT8IKDi)sU>j;AEocXQwj4AFCh zl3lD*n)i>D${Ep~Fu0sa%F{n>Z-;<1PZ9cqBqb_9(c^-IFJ{Tc1W;T!QD^JqP8T_* zEu9@($xSx1z8AdNi=6GKQSY67K~M4jwr6}-PvPs{t1{&*e!yA!oPF(5Nen9nQ;wSx zkpnRpYtUS)^5jQQOcIC&7YK zj*f3BG%GB{3-uZF*%9Ozt#O|_m7O?Ji}lgknytw>rY_-iojM#Qi%}E!xaz&6ytj` z*!D~LQ)d5i;V$J25zW+z+kGt5zTB)f2oP7C0H+Z<0zgS(b&04(20rAbt2qqwS88LZWP%F_a*i z25YaU)lj^drWtM95S}6%kV2%M*878W@vjDfB;!+vcRDO`2 z|Fo*&ZnBl@&4dIfk(Anck zg4QysDpgxqT$Hr^12Q6x|A0)plQWH0^O8F*mLBsC>0uGy*+BZaOkKHulpvV$7Fy;5 zq8eJ!Qj559OLdSR%1{S$z1ZumdPiu^+3ez~@Ikr>7FG&Y(!6(rBYy%b9{eVFi{d-~ zQSxkPoQGByGL)*DKmk(LVt^=%ht4{Anwv-ryqfDdK8m*hF&d&|qw&J>A|YPJE}Z3* zr}#-YerkpW8$b!(Xe+w=quGj?ymw=-%7CPFId326{`?Ss%B|U-sMoV=ZKd1rnzh%~ zp3`LGa^WeSc?tzJF;6+JtzMf!rUhbBBH&iMJs@*GB2U4HY>e%I%0Hn2jPgN3`DK?n z$mdUFE5qv^Q;wt2bm{JeHS$FTKF&*SQtA7qujV7ie^6kh6qEdTAoz%=j0k)PPbn|( z7;z(#>=-CWoxwMW>hmK%64xw&BNTX6^*J6t8*F0ae7AXa9s?2wBQlZEBapGfIA8f5@ETi^UY;S*o>6Q^?Kw zhuMse6h6Z|6dwG^!|so^v~Yhji&v#{sl=11ANPa(DKEQe-Ffm`x2v$*2Q=a=o!Sx= zLrMK}1Xe^+;g`_?F^O8mAQ>cJ@&G6ieJf?3VF-vd#~*npj+RB>(!Ap0$K31uxS6-| zY(C5IImiFKAuqUC@3_#97pqH2-Zf9gJ3m2#2D_)nS1Scben{jUF0Y7G%amuatt8{AW|oEwluI;8!7>dM6E&Oj$v+?5!Gy^*4@k6Tse7D^A2|<2sv$GoBfVr= z1{xHmq|tu$+VRnw9-6aeD+ndXO?uAK_kd2fDGxQ2)H&K;^QZh2H|=X|MKdw_Mat%S z0TEutS2wOIit2j>n7YoFO>IAPzDwQcMq8gZmiwoi>p0 z;}~iu#mn(Uj>kz$X6)E`lMdotY2N$&1%@&+1Zf`%a;QC1IQ|1<8q`qCmQv~LU@}d^U(~yhn_iEKv#*$d*$#ck7TB`Elj*tIW=y0B; zGGHrLeezq(#UW=g%q5Jrv}J)6%xWt8eLSUOKz)RSC1J)2#7ahJ@sub@+zJNaZxolE zi_Vv^EKrIZ!yr$A}LT5rEZXOVqFa%+{hXsJPzi%hTviH0xrRjS>Ol2HCSC7eKN1mc`^FIIo-n-hU*eMQ_(#Z3ZdIt|2QZH4otIZu@ zvg5uF?d}sa8O)J%3?+5varZ}*l*V6cy|yh|@g}0FzV&|0pYqeil>0lCpI2K>mefk; z2%f`qy!zlJvbnUa0wd)>xYQ}C?3Y?(v2)#4-HTC07YKev|VkrI#MH2+FqO60a zL)f?Mc`0um%1uA2dVC;R%0=$@V4Olm$u?O`ks1MBX=&E((Vi3p5j@oOV2_UuHq;40 z91XYV>xQlPCP>A9Tu=Fd45dp{QEbIOb3S1%VZvNgZ%990AV4xD7sM2lSCFR^^Bbkr zCIl4TxQtz)BIxcIWXng!ph;jWM_H8A#=H$P`tyc2p?q42KfI z*ji?YaDKmR7f);1^^wzKEyG6?cYv?RZ>KFc=VcDOK$d~{g6K2WKE8~7%rund+Cw(Y zgWEc|S`dd1accP-P06&(mHD!ZAF%i zHHT#@Jx_UI#>f9CytwZE%yU)Z<>SKymPwyzpr_y&d5U$ZVC9^^LY9fGz%n52`()Hv zXw#VDDGRz7N@(MXU06&50h9sqvSb{D+n3UCrLGDbji2TCth#6Xw=)`hjrPLl@aSv5 zw;o&$963G^O;A0-b)}J3c}>y8v62Ew=}`wk3ZNjS;N#Wd)&@j|S>e+wDY{eBOSZ$o z!ln~6n^zW8(q0wa*0|?M`K=%R6M4${R%U)bXlq)83S7!u^K_ZSpL%1BaRI!bX9^4vwaM2<1U#-9V!>{j8H+x|~L=j?P|3+;v z0iYb`%VMW#_w+k@u!U?NR}94s0A;ve{YHZ9GU6#ywldxoG0s()=_x}E#r@2jl&|)u ze2A?etne#_Cs50NpPd^(2rCKmB^g-~A`7L!1vc+v1%%cWNvJzPP|HDN3YiUK5b{lkaaPvlKZ~sTTdvIt7=XcN|5G$t4 z7)r3lSp*J`iV05lP!b@&R9xHZX{#QA6;V>u%JfAxhh4E1>#VhNK>gl`j;EwnPq{ne z^J}V`lPs0XT$Quy&t)rO)raj03(n&STM@#7s!Ha<2iXdG_QA`KTRQ^s6jEL&vM8dT zYG3kyM`gncYZBK)xS~+jacZ-fcs*bTz^c+i{l&1$#H6R&gAf@ew;jf8|v^AsO=G{jiiaE7oHp&GJM~Gmo?Q8$4ykR))+)EO5HW z@}1T5L{Is38p_O#_f2}rNLv}?bV;TpPrhdfTS2yRAVn_SBHCd{uo4zxF1W!n#7sI1 zmp_51N`RTe;|4&UB0+=#E*bt--SV5(y~?+xLsZ^`%@VR-&rM1h7){&j_$@p*)d3%u z{OSU-@qu!z1{8e!yx6hn_QsP!`+C&t0ee8Hl9zr^a5!#eOm5x8u-xhcwxSe}Y$cT} znJImjXLR%~m1p}tzeP{+HGNw#6!$R=nVAT@o_(JkIz$SZ}*emZcZYc`&L@tE&5ZGhlL7e?Ecg=Y}(q9vpPyplgE8y8N*ia zAld>{<@mrA9|cn)DYf{vj6^+-mh44y4%yLIfQ-*z@{_~@G=BUpQIWC&zM+4FxPWp7 zu&}GY;zN<5*_I|M$#E15&${azrV1j=N>D>V6CL(NQ8pnNe;qUuXt~8WjRcm*W8h7Da zk@}h03i1@xRx({@rK+r`t<>7bQ97KomQiFm?h}$)0;##srG^<<2ovz!U~ZD)HMn3O z8lMkA++_2w?Pt5*@Hj_`o_BgV8NcTfvK+TP%+bB#f5E>C6`5q*L#6@G8S8%wH4fw> z`f)vjQz%JTyd>9i`=8zbu@N@bsV6kA#}K#9@)0z0GTH+h}j8 zC@BaiTiG`~Og4F;?{kNzl^)Lhh3|C zp!X#cCIEN4C@-YHEK36lC9=Sq-ikc#?K2ySQ4D*)F9f_~Mp59SK6wvf*q1N0N2{>H zx>%N71AW^t(k&5igejTIoP&8?LWvDnnt#fN22iH!O8sDWk0L2G(16>z`u3h_C}SmM zqNntnWz0~_XmXvO{!Ja9oBkBdIBxkc2KBu+Y<`Y})8j!!qii9MjBDsIXjK9c1u2@?+% zZ;s-@&#Aoere)>4IDi187%}k3a-ti+t(;J~sDkK((npT1FFFfr7RX#mLwa2wD)3G0 zxstbreQTUEqJAwW!eWq$zySiv2J{CL4`}IXUYjnAlruqg8>?MhMaPXM6JO5_@1WYs zAIqwpdoEb4Uo?XB%#P|r|;+RrH)$MqWa zp`P-4F~vWls<;m*DNlbjyDyFo4jjcs^3JaLjMoZN7S$E1eIH>fWg7<7J_&cEVgx_1 zo0wFwBdjEq;s|ObfSVzXjMxeVS)yAv!uOx*KC``sHuAMdyvP3t;e%oy;h;UuDrN~w zk3E~m3#P2QCLML+Mq=L*8C!9Rie{-`nu+t)5{~(K9`@7R#HkrSH-eI25f*JG;Vyib z8Nwb`xX;?H@96+V`(*>O60aDF=qV#5Wv-zN&h(raL+Qg)e%++cQ&}nve(AxlL(`;x1IcDRnJkkMB2l!7V5Q!+Gtp!O+mO=Z&vX*#P6$<`cf{(Zg zPa%^YawQltK*ppG0gm(kk-N)HVz4{gSwJCJxlK>TY^94h3*A<*)JU_Il|*&Ek|47`VYAcwHkUDK8iHBw3?s_ic~H z-Mu|yD=u6=r?MXZ~DCLr|1P8gYBCAs<6sX+}xA$ zS8`JBu$9m9r##V7@>*4?Z$A9nf^%Ug7%>UXeZ-Vhp@aa1hvF++DbvOWpsf2*{y=M) z=72KEvsrbYp9an#R6p zcBK3BpxLLspA$?`N(wFEmfVxko~dC5Lb{ysY0kkv$xxoqP=1+%wrM2ySt_TjN?U^;%K(WHQGuuo!o3PjC_rll4Rp@HS8}4E2)-0i-b89xdC{}8nTEiWVbKxvDgMq zVta#F?2NuR!W4W7*Hou)Nke);_httqoEpZ$XY-K;+=ty9R?X)^k`MmN0HuKytLP`4 z|2o==sd-AgKjU+L9ywgHUijOjGPe^N*s^&HP3g?D7gM!9pugcB@DWRc3r736wONX zo+)`eOsPsf@zFlXQ2MQd{*QT5?%3~6wt}5q-_Tk5d7|dJju(1~!e&@8stUYxWC%!8 zm8fj{>}1g{TL@b!RE4&1g%bWmksOI2hO#LWyc@?-3T0+4zVZ}uvLLdwbxrKr9HA9= z-D^DMo8=OB%4nVelv|3)IX!9Kb(}4Ym18w3rVvK^F!Md0Vjk(2pAIEn*|Dh^3U{VX za#H>Rn%tQK`f9c^9&2=ULaa^z1@*?lY$fBFY;T;lj}XJj*u2SstZ{i`WGUw|n-e8B ztl=pl3LsU1CXtAyn0`L0DJiYPIaTG+?}2Jy9DlhK4D2c zPw6x-3n(`xeePhKyM-w=)y$ zs;hV6TZyCDqQ-GM%73d9Kv}CQ$Vwt>D`;JzKf>c`H&B0IO@twGNNUR3-3(C)G{d50 zTIj`So)X#4-|Hz+AxrF36?{31S6xNA-ksu|1g25*JNBwgi$wl~GQz?NwYlt`8ivLf*CG#oA`~6&$Ake|3z@~&1|Lr2~H-Jydks>p)$j(f9%AC?Q6%p~7FB>(~&#zNbpcxZQK5p`3m;Tym2uOlgLCwCy#8 zc6li09NWF!nx|Y%Bv1LsoTQ{zl@#}v%AcE(%I9h;{#0A3(M`>yGRbW4o0hs)U?nwF zg)`!0{%}ZDFqB_eO9?*2@ez1N){Mg`N*%mXQoLa+f)u(SiackeCl8bE#VU3aMy=&A zS6;%sRDpBV<^)#UshD!!Hu5*V>^)4W4mZU(P8dqJ{qmMS+4Pu)^j~w$7g^t zzpu0NZ1~#?OyqKN+GXFzU2FpCv=wG6bWk(MZGa=2UEwZyE9RgrnbazxmUG__l}Q$F zE1-%mX900-2n+PB%`~&PavO)PRexQW_jFKO8N$R+Eq*~{bvLfP^01urq@M>AZ(D&$ z2SoNNhSKBCHvZgjsm%C@u#(j5QEhmNzm<>g{{|~LzkX`t`XyV5lUbp0_ovB)Yjagx z_1DsxjzUQ?5fev6kfADMiZf`Eh^NS+kLtb^5Btb%5j3m}F-0u4305G6HrvT#M%+pJ zc>pN>nt=3$*i+q>J2O76`-?+Y3zlQbBNy%~CMUff3n=1Ux@0KfTuGVfDMN=w@eg+U=p^)c!1Ty%UU>%o%sp$tY1eLKt3U#D95+|5bx ze;!lLUAFE?CUVJTo{EpEBg;B6qt2ufTPXw;ilB|XwvZvnJS9=TIWyS_QVQWC89(I= zTd{$uUUip4J@;eBSI+%l^_0#X=Uz5_T>f2m!@xH5r1Yd?$YoyY?~Do`ty!2q_UcLO zwh>;ElstFPrYEUNc*#5a2Vv!=&e9h?XWHr&TWONzPG*9t!s5+R)RwJ~wnA(LyFzra zx(9||BoT2zQo)8a08>EP0v8EtBHRFv5Jt27V<&zitPs0V=ShP(%ts2fUVEO^a!E;^ zB@y@CuFq<{&jU)(5wi{Bu)8Z$!%F&d-|^}Fvggyr+NY}-imJteOdU)a!V7L{goFO3W=R`PXTTr~PjUZm_0F@#7C$RhhA`|0Q_;>c7uW3`GI=Z2!=lE+M733Wu(7F} zH}}BBQN&ZYRV3iT>x2ka5=|R{!yTan&Sn!$0|d1QQn_cGDIbivHi+hOG9MHs|In8X z0nId5_v({BAfOOHC_t&zZnIwQoTsSK!RddliM6InTo>J{|!dCn= z`FR+^=)WFT+(>ghal6eXfaZGU{Ww#eGRaRd)9p7H zNhH|E`=7CMyt4mHC^3Ly3Cn29 zv)LJTEvEQ+KK^ZsW{b3;8_nf)lA)LbTAA<C+6$8 zgZmM1?$t1)d9w6(pvm#e>XOhTah~vnv=zlr`iU^>Mv-$=TH91lnK6{p?oaSeC*$|I zvvHn)`P6;%)>i(Rf}`so?g4q(db`+8GwHS1U?x~;*b2N{FbCH}y13f$L7qa_5|2PT zg979mM7^sV0Z5)1>LV4lNXHp~NEj_GPao;>xXEPTSEI?Cp7?H3M(-iC48@%#x!FnL zn>^(*DkV;K_uQO9e*05?C9Kp^$j$^coghp|sIa1Dh(wx+)wwH^0fwz~tHKRK0lC-0 z3e`lFyzsuhs=QRbb2IJj`Q?6J1ruL+oM|ZPIyJ1sPgk$!(LU2*T$5hmZe&_vD4i1Y zp7HsUurkOlHCyI_7g(WbW^Kw2nx0gYksgp)4<2}Vm_Up&%LN1x9w{OOiEO2dB&h@y z0i|Ije0opk%h-pzZH$wj#4DftziGEjN`9|wH?q0aIZ|7xSNw2oUn zA2f1Lns*`e+M36~sG^1dG`N@&Nj00L#x_bytl`^HwX4Ym!#u@6iEx%q7=C@_h5yQ0 z=E>XX4)i2Dp>7z;APKOW>k0RknVwH1KclDkc}l*&v32l`H9y+RJ0L9nDn0|}n*K&g(s5mRO1VZ^Hzr{&!d83*5!;FmGd<-FpnScr#6K@3 zypW`E;+jqVc7p6j*vfFzpnpYAdBewVt$+rDBvNln?d?aI8p>Kni>M3tz`MHR4mWiuV0Jc zFzQrve&5StcuCY4DoCMgZ+1zfaWL%HEAIk~QSionWkJ!O!RA0~QAwJ%p z5BUqdjFRd%>o_RmUU98bTQ8(^BDhH)x+G>jdLfqVJU2uAp^mF{uyWOMmMQA5Q&m)0 ze7MORUrJVQXyylbO42+AH-rfgh9bd)H5&F!U_Wo8O)yM=T8~f(g%JQ&#@KX##|UZf zt$=RAN;^#W0p0rj@teWL+HF&F9lEz8^+?FnZ;rfiwRVflGZ{yk7co3DDuE`#qSZxB zsgcxz07Shc6-qRm6|kHo_(^K4`&44$1_jO?_VIElG*ney<|$9BDq~C;?DPq5p7O^& z!YQ(}bIc=`WXn+O15Bf{83r$Nr$-v4&RRawBu+Pkg{?`-lr2< z&9$4y`>fJNO$L8lvVBpq;bJrBT-cM2&*|g6mG*27NT|xttJ0J|+N(0lY<}OXe}=iV zh!s!`bV^qRWL;yy|I07%uC$NaJ>$T?+!=w#B?I~{B2Iz zp@wqVr+dk(;={+NN*;EUUt}wM zbcu;XGTJSfU3SQHV#S&y>A8B@o%uHA5MyTTEW~saCVYU-JauDyWcB5AiSmalpx0n! zJW}|4Q~3=me*{_7L}?EeF8IsLj>$bN^UXSQP;9sotc_v)_$geR2p6j^prTr|h%fHb z)x0AFbS8eeo1?wB4gB5w_rBeB*(m)`Yxx`4%B2_1UrZ{$q2xCq!pr^q8+&=r-e-by z-SnUmO`B_cA)+RN4j1_&gGki*{!$_dTd7e}brfZUETcAdgMAIGc;4pA>1z6aeV+XO zkrL_CJ3+m+l0L4joTlohKBrdyE+pI7-JMhp?_2uMpwg61-`qdnaTz}#3w#K&$h+bJ zD@#}eL=s87S#LhWY3T!QHcpUI`pb07%((Wk;DYb5y7-rc;gd|0%e~irL|fcwZt$ae z%Fq<^c}383oMo6(>z-pPZ?X38gUbuGeb0LQ5M0XMRln@vk(sa{Prv*mp^YP`TzE_y!tNc zojVm!!D&uQS2@};a*VFdc9G?0h&%O}E(f)iyuSf#^mno&1?if~6&K3G?#E>^Ho% zetr<#iF4nNk3pEz%$2LPn6W@>3!mGN{r>oWFNi+U{?wX__cu`H-u@bN_ilhDy;VGX zo+rh99&@?5hx?^GgtN_r>BbMUJ~LFfiI-cGpZ}S^*~*)+eC|7HC+oUvaG7~(27P7s z$qdDPvAF0zsUQmOIXHgd82`*)9V2|h%Ktm8y!ejlCr&e8QKomG1#iUyH}SK%*LTg_ zXC>eKlXstEiu(j`nQlk^FqFK}FY!C~pml#Pg$Lf8me*gx?=O6i_a22KOxx^Op*rUSau6=5n%$`IA`5 zo1wfvKH&!V&KA;lhTZ=q!g40Qe6}+6?()1pzWjdpX8q;k-jknpGyIUB-pfDd_s9F= z3t{Dla2aVn9EnxmF}l@$KD_BkN3xKRa^ds4)y+cbC&nVhcM;YvdDc+ zj?DYx{qaVYzw^UIow;1@Bzk|mKi(hjj~AKCv(I^dyg%L_?~f^P{3#ImAGT~5UR~Lh+W-InC3Hnt zbYx+4WjbSWWnpw>05UK!I4v+UEig4yFf%$dGdeReD=;`ZFfbssxEcTe03~!qSaf7z zbY(hiZ)9m^c>ppnF*q$SGc7PRR4_9-G&4FgGAl4RIxsL%=m4ew0000S`S`W{h+m zRUzNre;!G3&ULvEf_y`ejzr3XV>3wkNqkM5bAOxahkG??)%k&SaOcFF5?`w@s+@DA zJUl*=lul4~!s_?l!Uf}3E}pSz)%|v(S$k58F@_KZ3>Z+=4(OaaxNCBXk)(*IY8CbB zgR=V7@6x&)TO{6m8}Rt%MJ-ApbIzVt&Q;hRHm`cntTmoLsHc=v^~3+zw+(CjoIPjv zEgL_qNtjS1l*}MZL;(Dwv@%0c1cMc!5a)UYU?CL0zxrKXpW7|cM1*+d;q?nzmLg0k zeMqb7gvuM%OB;5a9yn|SG5``_GDa}r-}TSIgJ=d%E7xN}DE_29jGMjt_CtxyX1i98 zjb@Hn64)}fKvFtDkPdL++OsflFw6i0kTWcsW&3x_V9G^N1ibBWCeHP@5A9+5slg*g z!ZMKw%gGEdm~@6xIsiZ=38*LqOpu_$|1*w03?=8>`Pc1%W(=wVNk&sC#RKb8sxT@= zg^17)L@6)Wy9)3)j%58;&+G~elJU$TQy9+S97Et8^LOu8^U(8AVnmyKEG$R%>dF%*G~2C-m9 zJofxYT=j$VO6hDVK04mfw}0RG3x5y|ve*Q|LaZ;);E!xLNP$z?iU>wC2ug(y6CZBT z|ML@uFte-wflv69CoF&J#cNJFu4(lmD{6^o13(l=S(Wzfux$V*yfXLT#}YK-fgb*z z{tth7y~@474@QNo zv%e`KmEfL;ZQGND<bv~ zq-+R|f6YTAJho}oA}gXq%>4-uZYSFY%kgi_KPa}xFMsMKKHCBnu?&|B;uM_0(T;At zbDX|gSlbbF&={)BPPEi~tVJ1tF0wPv+Pl}WU0<%RvjA2DM zaYM`IKRvlLG)_vvww$)A1GzfI82}eNa`9zPSpE3(7oV`gGL8rKpbI(~FOO%p9OTRQ zs+)HdF@<_Edyr5QqV)wPVS$A!_Yco2#xteyk=Xve{fFZJ`=k3+?jX}W>X|nW?|D}9 z3A)g6*yK~+coBW@>c$&)>zO(oK)~XOSVH(`X|inm9r5JHEPMN_H=cP?lT#=wTux`*Y=O(M+#sgX zDA`teUy3XXkSWn0C4|;DI@zL=$#W%F8A8S9VivL#08%QmGl_@=56t#a3E%#jjc2a) z3FCQ_%T;oypb9ZUwofRO`D+rkRe{A!0cK!3V{Mb0%vWMr9Z#1NR3QQppwO^#S^4nA zQo7{n_KSW`U0EgJZ1tqnU%O1v5rAx!*_PHuydR$|!b2NTOk2^BHZ_xeePWSE}E;=T+|5@o>Jz^^Y zOp&R9K&Vu_h!5LVz8;>G-rrr-gMcC`v#07n5;^^p<-h&LrUenVoXF^j!E}L05S$IE z1>DqdihbzRv#pn}vtIbCaPuXCyRLmgx}#S+E(Cx;eBV)!Ra6iFA|Sv7;Yv`-O7BS_ zYJrc4He9*?XZ82KuqoNuuk-ob-UB5>pY!c-v!Khzc`jKjxG<68n#Kx<@a(hL*a{U1Tn@JhcQ}+#TRHL zunc6B>gaKc6$J`pB!&$Wgx~X~GvD`y_35s`WLu0Zf&jjt*od-JP`1Ql2mwbp>xR(r z4cXq2*w&OYlGxwt{OlfYb9Xg_L?nOcImvyUes2P!MHvx#5QN7zW)Ba?Zc8~siT#7l z&-QwodnXBV2cDg}w~LfAC6^7zNN-+MD&?Al0oy6ZG~^BqkKd3U>`TA<5BWV~T0n1l z`pS1ab%C%DWX`7b*}D#yvi`-z^3>~^69qmJiobtCa@%1qTUHi{2*H|kHTXSmKK*^K zTc6(Dm)Jh6R8W6}0Ct0vDk?CBgnT$VJmbl$e)Q!{`JPzfuY;vS13I03{jJuPUT^B1 z602nn8$$}v#0JEZ^;|@z#**68=@!aLQJ^2=2pLh0a>Mt}$oKT^7^H7s6Te|cjG5Og zpLh9Z)-G+(q?C$An^vzb_KzGl$GqpU>I-*J_@b+-i1Jh}Ch6I)}44wI!S zBXKZ9FcNo^QlS|NAVwep5qw&rC z#e;+UJF_pknV31C`uf#X&{jy}Jp9WsG^o z#jAe#%?tB`W4Z33V&{OH$-Vws+ScvC2l=q)Hi!>^)PW}&mmJPzu}j(z1sz#l(Kv%rHF!MGcmzd@z`_wQ7Bm$xb%E+4AY+NB5N{ev?9xpw8eQq%J!5@zQ?v_}f6}k@- z#vH8TSd0s@1vFC#jqmC(Whb+vLp<*d*U|RABO#=G0MI^aOhHY;9qqc{X18>R)^E6j zw)fwU@RW6};&@_&Eq0T6!+_@BcBz1{2HRb2y69%MbQmMAxmy{d1FFEE-~LJ0OD?}C zwX>HL8kWt^?_!Fmi&|aRrD!xtL{mPr7t9fdsR7V1CBT-Jv)AU^Mn8B(;&*qAhkRHy z)(ippbFF5jvrw<`l(u3UB*w@?s5X~Y4_?&i) z6kJsvNSH~J0MLjoZE;K9rSEKOAE<~(Ag24WDiKIDllaCa@N1ocfBl^Ju1@26+1-6y z)@_-{w!TUzgaQQH4K<=DOn7d5YrD}px2umUx~*Vu>kkv2c4DiSEeVS_T#*q^r# z4LiZZha!CZ?snto%)R}(sBg_g^F^1anu(?!W-#V7ESb-qATvsrQ_F{7%?gT5)tKe~yW;rOH_yv=j(NGVPL|w}99i_s zLppe{hK7de0}mdfzN-U0K#UNv5J?%TB~l*A+_g7dbM7c&i)Mz!`I5LGg)M`Md2(qs zefoYfF@1Y|J?!oA^L+Sc+pPVnJ$D?l5RF%B<#Q zI3h%+tx#G!5Bw_e6P6H(D`W!he~O%C19K|tYmUT>X$oA4JG+t zBLEXf8`SgpF{_&kePc$m0%^}TW7G#R3y6tHyCA9COR{D}scPnls_6I~2iy89L6}7% zkx;ZVGsrg%mYFp}=o{zd`(kdcu1|AVXkY`%}jW*G)dT2gYfk) zTUSZsp^!f?rd?)By?cuebrwN{=Q>8+bWx{DPApG^KXjX5yy4Vo`*+hAqC`9bBWWVc zl^|hF_o0BrGZ2U&Q`Yet+uDYmdOj54Dy;@{}!+I^bN$ELP@9m z=~L>LJHsiphQR7C$Ig4?;!-LtMwr-WumJR+2FNVXLQ&h(LKZD+=BfVoeu1L}!UQq~ zO!()4!qGrPvsBVaRVC#{#-OD*n1Dm#N@s$Cruu=j!YsnVY+PZd`W+9zy!la6slYd@ z+CaD>GvDnJ;~RUzZuNU@GZFE8GYuzE(4`|{3Kt)O7!hV+Unsf;XAnZ!o)KYF8c2#! z;z`%E5F$FN&ub9oIz~iEsV^y7v2#Dd;7cBN{?gM+V3ev&@E!lSChPBXt>IPwdqN?e5@TQ~FImYK*+%Zm%l`+_xN?&X(^mea* zh?Enrh%0h`J%nM5uRk)55Q8k#tlXKh1AvSe4}=;|`PuiM_WsZALkPsdyMbE6ViA%c zvT6s86750xare)Aadh?z!?2R(S8}P~DrhC|kn$bFY}HYc@B|c?jVB^9WA#%YX2&-o z)CEBdv#N5k=Ns2yHAXA~lo(Aau$uW2Fe&4D#*h-^wFT&K2qnga1xmb(1Dil#WA4|# zD3xp*uq=x`4(?&8h&6IUf^0*4m=hJ8#O^Vx5>WvF^_o5 zYfoIiSdHAUC%bnnyKAIfN8h!L3nhRk*ejf*3fLaCv~;jfSVY9hy2>Vz+N+7PPHNRf zM@U4d(49684(Vw7m{W7>nvFoQA~G(N9L*Q}f9phvfk6b>b_{plbempp`*>lb?(v?CKiEMi)HshdgWuvqf}nROidE z$YNqw2oMs?9+OfOi(p7Js-Q^)CflB!=^XU(?Jiu^!@GtV;5rTu^e{KJ zxetcLKpaNIny!biXf4HtNf{_0P@_;i&62i+jCg@TI9m;EJMgq~ZQ&Ik|K-S$p?OT? zKZ!?>P^k?qBN$U=|5UH$JWM$&+7$6h6-5dp+Ax7;-V|dNQLGr+Ve=Dq&SAfM9-8;1(MB4H!iLrtUba~gJYjxj{8?2U0K1xK4B{^dhO z3fdEeu-m5pF|u%;aSfuR3_MSi2nfvKqNhDqS+;V)WR3i>tKku&^VYVq$HlUYl;vQ1 z;f@h~_lPGxf?x;^A8UA9U@ER^u*G9)h#J?B$colTqJ-&anHzcPQ&#t1aW9M{w~w-i zPYzg#f=5I(X~i%sB@%Qcprd63DCMPHHY9@m1tA}p6^zjqY>pUXAfAZ)E%r^cQpDO5 znw~HeB@gteh(!?KP#Rnz)d(BDx(JI9fxMDY5dkUq zAWZB!FS+;$t6uTEHHDEx&vn~KDbWT5p(>}U-`EORG?60KP?!-S!mLCUhH~PO7`bUU zl!b#jW+VbKG(+^-wte>>E_M^S;Hrcu5)DBO>l^N{DUa+(uLJj4{n8v}X4tpy)Zv@Vy>P$2GrvbbMR4DLdnLj=E+3 z>`3H}F>mUELaiJmY(yzG8j3IzSj33fQs~by6SUlvlGz{ch=?oPAmp%$M2uqyvSL9b zQN*kfY&Q!}>VfYov=e=?Qn+A4jZ*p z#0Cj@1*4)2tCnbo<2`@aOqLSO0LUWtpk^Gm7z37tXRNlH8|JTCl>P8BW~90XhkA>h zW8Skq(SP-a*Q{UJux^R`@J;jQEITgMIRFNXKQxyhfXuY{D~iM;VestVc>f0^tl2kN z!c2-pU>p$vSWpYMUG;b;lfQ58fQ>uj9+qYyGMd-D>XCLdsv`FAn{B%>3XpNV;&{6I zhV7QEzH@!~i(h?g*I%|y7)Y=$MgXM#CaV%Y%15tR-o&maEUZnTH%~yfXLrP0<)a3n z#csi<2t$CWl~;9xe90wGtZFpfHZ<^;YQ+{7F>Ku0ll|_G@4EXtrzLmyfn@%Pttx7z z_awi4jJ`6d?xKdC`>t69o4CR6>uM-q`_`$6d;5qmfBk%~;N{yhmq;bEw&mJECBo;Q zwdm{b+1S)Soas*{w#4=gIUgKAzA}00SM!87xIF~JqQIUAgzEWlSrb=0u(0MrPXUA; zvOD6Q@_~nr8*UlhIIo(`g)wJcOJ;YHh@QO!-!INOz=Cj9qV6{%fiN7$yJ=_X#(R^G zIdj2}-ng7yv*dzhu{%eb(o$el_h=Q_mJ9oiSBy`4m z3J>dTEE^9e*f7)tM3)R{1|RuE0vTwE408~;% zpojnhs344F&w%>em5GBrnJ<3J_8)-ZH!n<5cbVx5A_5~-v-%(XvgaLFie~{z?MaFU z0X}k%skOgLECLoT=?!l@-EOL8)uG6QKpO&P?RcfpWY?8_{V8kH?Yd+i+IAd z1Uee8JmtfOfAg|dCsP1Z)9U6q$IrE*_6O%Qd^i$qSTILLEf|0RnH&+>c4o_NR9z~Y zzFZ2keYEq}FK%&C1u$AqU9jMcg;q53LC}Yy5f!nFvKhfL2Lw;OwI@i1fi>^%)IqL;kTVl&pXC=WoO~J zONOrMgOazdE^SLRgC8I;El>cVk}4rxn*LA0nD-1=pSw0$747$IU*Uie@xb+pECowK z3nY-K9$yX)$#?!7yK`?&MErLgqi^}%*m)Zp-td&gC#?W62?hIB%wC}L8KX>zE*eCF z$+QrHqVe`V)m*KTeK*D_q6ic^FZzdcShH`kghe!KV>Z0zOuI3nB9Vc&+SR!AQEiCg z>CPJl22$#*^VcLg`c*Y<*|=aFrCB8*@dOG42w4Lu+TB&!+3j3+Pu6w4$%}A=pmTvD z&xIxRC`p8cjj(7(NTmKnjkTG*?Owr4?M;)SuMR~LrP_Ns66{$5m1H60J|Qb!Q2Y8T zH|}$8*^?@~{qeCKhb={z+~5FFjcV4`mbu_#nKxgu=!|9daV^GFs^8t51EA2KfDjl^ z_uY_CG<^NAoA<=vy+l8OZy!lBJY>{J|HBe;}R|-YxkGWk5eQSGVTT)Me znP=D$3lCXaP~vG=_1E;Te9;M+JKA(nr*>z^R$nbflI7YytdDRuf9l6NfAzxoZmPiG z)>B#+p0P+Z*q?50_-s=&(%fLrZ-kGDY?ZjDM_EcmRo8FgDiR#XHj$6;SeRkpJz!Br zK7y?M-Jf*6`MSpp-nN^Rn!BMT)0TzD&t6=)ax9eANx)(Z7_cUj6q7xe!tS2(&K~!= zd#8yuxaqD8SUg8mJv9bqh6!M(woy6ITfTgA{_sF<>dOAq8x-5yoxAt6pe1%b{%6Gp{$9A<9&|4X-=Xj#eXg@a;z;Hz;hO7X=9C(2 z;w)Tyh1NPSp4NUK%(?!`X`HI2jY#$0jioE8_Oao=40FW#$tQm|61;p{n>Gyce>egJFWiLLuAGT2`1^W0VqqVyd$2yV zE0xs#(c!<0Reczz-T9CYA2Ndcd(meyZ+z0iGnZP&wiqsJRJ5C`O!nOpcp^v^!far~ zxFVtdN<=+9)JLvlnjW#hxJE@W_k_90T^X|J(na#yAwA*n5aELs?d4kQ89)8#8nb;& zO=|{p`y+8$aXP2u;jer87Kf@wlUX z?O|sU_45w+?|y|isxv?(o0>RE+Cncp0k`hYVADxL0LHsimE zUqAiw^QXS~{_Dk$=eB+2=grMjRW{ue9A?2;C(HWPFUzMr@tX?{K7ncUAK6Ai&2C{v zBAq(kNGhBW^Qa%guaExa!>>QP?d$KpUH*7!+t;QuF>C<%_lDPgFS9xG#5fml?6r=? zA?-r2GdKG+ff-mUS`Edj zTqQ^6C^#(C)^1(7+hMOLN)`k-LMQ~k?7w`xWp6%`Wwac_=8*IHY!0?dXwYqRP;ORc zGQj6VI&I!n{T3&q+QN>=nyCpD5YJXY#UQL!IIH=%t=Ud8=mZ*RRsmKYY`SR%dc0^| z6Ce&dKtE&HoXuSyYl_u`+Jm-x6z;Ub%)wx60JU!~39Ep<6za&=k!&l_80M_U&`^$H z-%*}udxd)I+_=qGgVSeS;Q#A_oDLs6s)RVG9_R z&C3pcMBP*zdC|BEj+-f~9%?j|NLgcbP>oXfDg%dvfxM(LR0`?xY%O#1b>~r$efK}) z;;ZlZ=bss?iE`d>_1RNH0oxjSw#fj{NGG3l*}~!i<&zUY$%jxqRLlBAK%ql*l=$;Ms(-BWw@^BuI?W$ET+Ulng_R_40cD z;N=$=`4LZQE(h6&bi}2`w}jmT zrr-kFDq%f=)NK-4>6)O^Ejb_%o3J)@;k3HCt|(CFcd6YYR#@e$s|-GMaJ%yZu^XV& z)kz%$wjKO**G01hc?Da=x-ST85R@9U6>Jsg6JZ4=`}-4tprIhFK&-ifo&rHwvE~Z? z3aSbOVfA>~RsK<(nl{d|AUE{v>^nf|&Q3^ z+UCpJy0)>lZQHhO+l;eDur`C4?$SHcXSVL_Oul@xkD0suuX@i^okG6)bE;Ey{;qun zR`yq41UbvQQH(=43l7CRkSqN_v;R>oy_yffaWy31} z*0@FfA|(l>QgZ+Rk5!6%BwPPDSDwY|wm(SL;kjCIr@dpZ!S%lQhA@S5*V*}+B|lcY zP^x^TUm7*fQ>cVN82Z;9-(9LzI_J~QK)de!E7ho*HT#Q{G57QFYZlF(JZgYPl`>(K zer?>MK;aUEx`ZU8ZfhmCq2F6(N8zHy?;ReE9IFVM95iU;WxfGnqh^mu-!jzPM2F((y@GoB#aP z={T4F^@lIq1ECs4$nw6-K(4$6r!8LhAjLR;A%0Y^FRvuUXRIPIZr0Mm#Y-n%y4LW= zFHgm|n%))>pPWX3$FXTd?fRczzMaCk@E!uC;`T$krmF5!QM>+USMQ`UD6fh_CCYbb z-Tc^r-RS?&i6kIC--hP@uui&LV2m@)F`YICz~82L$)veUVCCFTakOjrUHsWox~>z$ z1!96yDkT-527VM`3vdwTpbR9cpb8r0Rg6BvC*&zuBI)|0-tGQ~2|p|gWD5;)7!*oD zEpUrsnd65Kc;lt4cAdgUV;AlCp+VKQzkRuU_W0#c{$dxd zJQ&=$aa@$k|3|s=1qTJ#b+UK+1}yL6_q-vK=K)RJx|cSf{VxgUPD5S84LA>y!g>xF zm#aXrgzFFcwr?04@z>C@h6FkLNt|7k0(KKd4Sw~7P`kr91iRht-X+4hVQ_;mcl)>z zgI<0<)NW9)cWUSQE8BEa$*A#(pme#;$pu+$jWU8iiYt-Q8Mui{l*QvR+v3Q0E%L1?!W~IT4_rMWl^M61H(RGIqf8Ex8{jImBFW&{5 zK6_d+t`HBgLdv*7C=gbE)2-lwFzzrotm@10 zXE4FM%?91j2o=zZ^z7zeeVC>LuZ&+E_sR<)oCCA+V-XRXm(PqjvPWuy`nV~sT{4H1 zz{B3c1I)m%*;^kZ+YNh~I~P-~B&Qm{+a5zRBSaRlf3s&-IoFAki>2km9J!|~TAz6R zKA~JyyoSb{Z= z7_g#-O`JoSFbM0@`e#_l5I{i?g_RIailICJ>v+Ln+%Pz}lya>Fik9j!aQw}Csi)$O zP9EGr+Fjl#*9{5=ldS@5HXD9KDaQ!QL;IFcW|;9^+b;`Xe1~?ta0{M&*BO+OT+%tr zzN9F4Verg{cl{k^K(<1NlTZSvcw%USoI^VucWmOob{_tTa|jfowmM%oeEW?T zN|vwuUXFr4HK;gn#s-~mY}Avm%!&QB(#OyuvZovxQlv##7GXV$z?bWd+IFk``A-g= zVBiI2F4Wt%Zfx8*d(OCijB^F!3(s{Z4E+fz!IdxHDC>j*VNG0n9KryYyn3{8HZr!^Tv2o6d>4WjDoa~a$xUTa6O^jI)`{MH<0cP^LW8o27SHjTt zdPhJ8F$svP4SsG-2syNOL;F9!;hewzV%9Sk?*?k#gryjdIU1S63g?2E03#~4 zrsGY4kIu0!p{50C+}{#a&(o zLz8i+h0FjM>RJ(2rua&DTQp2+i<#pylu(vS4wHuq#<&nc0h&%|^&0gO6XS2*xt;px z9WE{xpujU_don_>dd*( zhqs4@hOodO#%1W>m#|<#%~bEOtQ&<=W`=u;(D(`sYBR=!c=grSOIL54cKzCb;iDfu zN>v5bG@%Ghv0%YZH-qw}yFcv*RcQO~$X4=idEntGQ)S8P!c>T0o9*5A-)s0yxejfb z-MXI^sB$gL6@AEzcNbi7exAxxzvY(I zYMa391u+{E-%XfZz!Kvjl=K}gs z7!HT1qt$qJ4geq_CICI7?$)#RtVyZgQ+2?4=DSy^a{&ZY+se;8ZeHaz)P9fvgCUs7 zHQk*lT0Jo{jt?Tq$&xb(K+yw$5N2kV_V2vm#IYl*@b&c}Jet{9tR&OOy%Ch0wKb@D z4epiz5>MHlwP#I2GW|d2VF>^lIHjxh3V4mtiVfN(5CD~&8@StOR8F_2Zo2J7JGU>A z5H>ANO-!(~hJ6K0b-Qo;OJCEHnSdGTgdj0&K$8)s(GN&Qk&(PCl;ohxA2Y0v`cs<#2N#s_J!$ zfBkR&?Vd$Dd+wAV0ssY#L2iN(PIp%~WQT6L{l?s4wf-Bw{5M_0D!L@1o^KO`f`#k$ z->|fM_u}HVGM18Jj7V*JI^%fBXKCTH_LQMY^^Oif<c;9h-HcBup@EQNoqWJtWvX zg%fLQ{Foedzy_v~5E5=MAte#ZvJ>pK=fCX86BmE?_dn8UcUgl{L6Vw{WBsZHMP)R0 zr~b;<|K-EapI^Rsa;+-+{gG`zh9r$21|YglojciW;l1zv-5ooZ#?g`>uf-cu_>}gn zll81AK~=4HZT8LW&-}?Cz}iGKa5D~(072CL5?&A@>hjk3;PkmAB(dqErPH?rK{c7_ z7Q~TgR><*Z8q_N*0}kBuqA&i6Z}|0}|Nd6DxV(1BV@wAqIe^+sEbC|>2cVEm_hw(P zu)Xcwwad%>l~pPVP>K+)v)Vv(r)JKdKK&=Z|DF%N|J^e)Gh-(Uyc%gx5?peDk^=}( z3MzZn{`{J*)=(P-`ixOR)<2sPv#uaqIZa4`2q7sTthd+dhy^rj21Fozf*`lXtcJ0U zFHG0~foftF>$RpYg3|4-!=}KRPHu=*l(b{-zAyTkZ^Q7ya5%bf;W90R5XP9qdX06G zRl9l#V5ew(!}tBrV9?2DvmgA)pR8h(z~<OwWNQoU+z(G8TS z4`c=stkE_mpm1gHkyO_7#?f)kF^4um{r@S8cY+a>tzsV zaE~sZo}2rsZ~M`mGubcy;?H01ujZ{BRRwsx22iQZ8iSSU6(VGzn4a#%!KIb+)q1P! zkE$wVD{pA_B+S6PbNtlli;sP9`<@$q{QJItVcV>v=&mvN5KrCYa`%9sD!ROt6%s6! z_RPnuXGk}0mhtsN5Nj164>+K=yz|8U1z*eiXxA_!9Je3ek zNSI~7rg8+TF86?Nhr6mWx;x-Sk>xoPBGwc!A%Rn(N(2o`y0RSZiIW-#3X*^bxF{eb zhbx(C?W?sO@QunE<9xNzNh32BxdCKdwNjFuf&l;`qgu>oXXbC%#!jdA@W~Gk`y&EC z1Xv$m1Po~lw?b>zY`e&(rk57xqg$s4@Pf=GZFY@Q*#bz$=!1U0ooBHcJ%0S$t`2|s z*Z$5_r)Ly^G_q&7qRdt>qZAF0(Sg~i>CgLXU;ID*+kY8>%#1XG&k(H|&)PF;WP^kR zY20BrDaO*SB9e1Lv2|yp9-NsXBB_KrHP({uhzo)$cbD89K%Ub=lHr?mq%WJs{V52k zpBfAXND>@U4fSeX3+rkTuxT=~90FY0BzqeHihzK;WeKGuKuG5ZfT}2%imCQDe(#TF zmR(p~ec$ii<5otmfG|cljf)n<&7Q0z0SW|-BWT}W`OBkrVPXCJrM2F4A%LX2*X~En z?+^f)F@$Wb-|tr=%8y^bRIk(SOZNz1A4Z%|G62je7Y`^iG^s~pD9rQpsN5ZZB^SAGtdMQ^^+UXRY}E`#*M475D5e% zx#Zdqg0dVmV)OW!YS@)D7$$0*910qcfusPJ;6TI}vkY}&DAdO_YfQ>Wi3Feoo|NDM z1Q()EM$a-!Zf=c=8fdV+HlZj%1_K!t z0aVOhcH6DncJ}1mZadd-WDJm-S#($P86p6>yL-%N)o66rnNv&KjB6|3_}Q=QwA+9L z)RTEi+Dc`YKr;ajYqtuF`d|4iKlZ)f^No+(_4_``d^AF!H9WNmra#xA3C}19o6MTG z%K0g2%PUGY8Qp~XAQb_URN`clr{No}@;PE-Zyh=Wh(KK$A4ejH5Nnu~3Q0f(0HQ#E za1cNUpdncuQzQti`&?w=vVtfQWT1h`N%7Re&H6dPnkYAJJpmUy3SixngCHj*0wf~9 z0FZ)+G`YBvM+eji#Si`TFLtL27MIHPwNZZ{L?2(90HA)?q>!-|6Opjm01~iZ2xr&h zN*`W!d!5Vc>me|N9DotcCq@DwqnU-Ws;XH1i(me=%gckseTT#RzB~{TPy@R3t%+7H zmkfeeWw+hRFxqwS(6@iZx2~1=^?&xSmX}XE9S)aY;UlI$zado(dXTR53Ub~*Rlg=3 zf3;#?v;C5`N|r5&$+kqj#`mN-3%sJ4F7|1{FgFdkZ~gp1o7+bupN7OH%u0vVm>$Qd zL4g)X+pOg{1Wz4}bq`C>7|;MBqcH)SRL89Pr@(ZA>X&K;5P(945Qt=?1VS<*%RrJD znHgv#X<$Yg@;qyI=N7U!VkZpu{=0wonxre@3G_B!iLiSa!NodC~rrzxS{H=np>f@S}h5gWvnT{b4_n5MUsAMdE8h zQ~p_yva64ry7FDkr1d0I1FkwpemZ5sbv0qAd2kbtCZMpSW`T{iY5ayKYV%siEB3GL z>4P0B|P9Rh9Nw-hpl%$%ww5c;l1ewv&{>@?* z68u4yKvR;#p?c~BIZ(8$C^95s2p2#X0E7$#2w4DvF|(?y%8@{unY&?TVb{u|51v^) zamOc46_%n%xVz?e?~X9li6H&gZuN6W{Y=McxKr zDWpyAs38ytGXoi;B3$d$hdy}M)Lg4OziUr#iXjK!X;B#{;XlR?Wq9&*k1z@T#{QgNn6;soQ&@#Z@Pt$U@QuPJ7NR~5e^tsWMO)4D({9)(fzzH|Lalf*tTtP zX8W-8;jprdWWradti+t2lzWICVFm(4lt2U^v|;eX??6vfjbo)e73y$F zNXmUf*aicMCxGR>SNV&tU)rQA- z_s2hS$DMyXSnZ!%Td{ztRyz-run|;Md&Acs$0z}`h_lNVPhB`SSX*xIU{T}%Hx9$N zJCVsiGYcV*ndRBxSANG!UU1{Xr|uYD>|Z=`@7l%H;b-2I^7%~oUw$6D#8H=LQW8+Ff}thGq*U`YCV4R#NzI4v-A6C0YPxpLn=~CyN@|9 zC{hB5;d+&K;EE6-LGkkPsH{c@4jj7i=I2k(OwYEg)!qKJU-N}v0P23b#-n~|qZwUJ z)BFGEj_LVrdv@%5-pw!EF*lbNc|!rOeJ5OARh4_SZEoR5zwXt?9)0A@sny4iKmND= z^}icd0}yZrlqN>8+5N^$L2_-_1d)N{WDKg?Q$njI-?`Gg4ciJwnvk>!!kDayEKR1y z8muc>z4j&yHECLX*H+4X6LXQupFkw*mXHY`Ad$&Q094nTw@RtPrwg!{{_3FMVcl9sp3j7mhd9oThNlIk(eO_K@Qlj&ab0Lk=Y6D``vh6rd#7?zKpB zD9s-f0sv5?Fj%SDy^KakFj!rh0sH-`91TFU+JS_LsE`qG!VsgPAjN8R{S9CAT?=!& zXJ)(IEF6365xFBW1VfS`>zW!#7eJVx2p0&LAy#Nj1;D{T3zpGiJaO^V^4i)1_kS`k z^7p;_-Me<*I^FJAVBNQG_%)JXG{Ii_+E;Afv3UIKv2&+~f90(&&w@!!&w}Y;m0U*K zyKC3N_FYi5ZTrrPr_WwEeXIgvjIoMh>NXQZ*+f^(3}9XDoZQDINHAAJ!zm&tpZ zSJy-klJ$1hkF48P>%ul~LQ_221dC1F+%$f-6~$}*Y=YV*@T#BEL}39ghaeXj5-JFg zWnqF3#JZ~abWY77Hl-pMZwySZMWD_hy%q^CfI=EElwcw#LJkQ640Jg*)R08hvXz*R}DHn;7Xwm^3w0|B_;phP2xvh>h03kHWfHi~yemrG@I zxsz!3a+fQ5Sw)1lB0@$A2BI}{^PYv}l}mdM?2MIm&d(A;kN|>pIxR__bR?;0X8=4x z6$FHg?#Mf40RV=>s*1XN+OJ#Kb?D~na~~Xj-gDN=tkrHA0?8)dLG8DZ44AiSeQmU` zxNCNC{w<&T`FWP59#wxdg}Qf^nOf67{F6Ubv|8@IxG>wQ%3*(XR8}AeUWrJQqz&YG z$IKu#9{o@4SY2^IKmxdiO?F9|WNlN)%>$af{mL4j5Mc{uw^empg-tZ^?o)bUm|$CY zyG_Kb9V3#-yH5`{REr^>3@nhY9J$7bV)7?(U+ddkgim`G@5Z!V7@lz~X7cO5a%fSpB4Ef1D#D0%J1dGz)#w9%^zP;1`laOy7Xx>++e_Q#{`xy# z-DwwsCI>ExYG*vKZJYA)*h7yz_Shrvj3mJ36N%J+T;6GSfBn~gvkCInBv-VCJ`s{50T-brwt!8vx+=iZ)|;9B8Yyk+=>>#( zNIIC14MG}{O8*!Q47nBUfXv2sFNIgZ1y3T0BaKO!1)5PVuf;B??qzWUzzhfg=~WfW zq0Fq93N*$_ii%OOQdz<)C<+3|tQ{=S0mY5d+#y$tDof9*;zxh{$2*02EM2MwF87e- zJFk1yY<7Bh_SDgbj)zu$?B4f{R#)OEx;tEmfPsNii)~mCB)Pjs$fIPwWAB0m^N4Ds zL0<}BfXiDgvhC+jKDf5Ne&4yqtiWm_UyxtJP?9To;vm=QaoaCm_z1i1AEzT5>4@72qHVxx=ecF^R;8DB83D_cY_i zT~W!Wg~J)J;lynKmZHnuGe>8p_YeQ(&zC5(+yDa+-Sbxd*3bW}oqP9v@J~N@+qd@ss05;72^bYLa#W?Nvb^u!hZYw0 zyzu5*0UbEJduD#$FZ}QiblR=vOSoiUTjD=&P}3m$s#$oWs+6{{hDX76o6UOEOALaWn_!&CTF!Htut-{b@8U^ju9H659z z=Y_3}$+jxCS>|M(Tfel)pA&TY33u;G1`W5Oy%XZX>X&K%$5ON+3Uf1pqh^H+(v;q)IXBeMuncn^z5B-Dx{O-}HBq!@iOP>reFEx-&|c?ZT6q1idoHLw&GBA zi!lOdVr$bU{ggJrPx+L}_m!MjCyY!sf&A9-<*Dv!igc4(+x(w0BZ)kusAz$iB{n3u zu+;z|xAcm#Yqva?(zb-86rhx!4ire%mdqg=PGSo8hATzHD-OiM;P8lzB8mDk?-}V# z^lG|Qt(8^F%f81lMh8i795Nw-Km=I2IZ%KZ5hcMzGh@p!QjB0F3xt${hJXM7$cSpg z=~$fZ-FV~cuiyVV;@!f4nWGc{qs6LPIe%htVb7t1`-Ym@)0cd%i8tlul`w8Rn}^~@GXCFy4%gd z=;r6&{CmIm;m7;u2W1)EH+9-n^=678cbe^5-1fCU_A`Ug>A|3M_YlIT4D)G%NWFQJ zxf{vm-c6@ZmX;@kL|nnH38?p!%bYx7u$8R7>C0BPal++KxT~8EvtR(ToMq`7QgdKT zq2mAr5!7aaW&otbxAb%ejy6ja$D22;#z4@35G>>dqg?Kuj)4d^Q>+6_1AK}bTdd&x z{!Xix5roqt+$9$X3DE&p9BS0}YHgHH<(*DGv#T?^y7ftYul7gkt6Lq@V$Y6qW^%Xti1|e$`+7#=r9V_x{>1M6Wzb0yC2UIE~jI+I#;e zKfG{Y-@W(U`}m_L``L7-Gm{rx7B;M6-bU7Kwx*sX_d4Q57~*(OyYMHJ+p_x2Ya zy#A(_Jn!~L?tEbOz+$dZIlAB;>qu9(ZoB=xU;FvnW;;_e+lE@6?u1ieUd-9Brkj9N z?{uqu_*HK|*z5kypZe9|U_FFvLJ0K)<~2bJZ=SLhm#N$2K=29p@|1Tad#Wc+KE6pR z&8&XRCLe7JeQNxkYXV&TdlSfzLcuM^sH`MOXty%~o8)Ujb?F;SgoThGU8BHJHRoTW z9yBV)_)3i-w@xp#yIBa7kT5{$DmP67O#jpitY8)A_IEprIWt;XVpyup{Wb_FN4|Qg zUzSx|FSB0O=~5=?jy3RF$BEWT4T^YGERV)Ja6r%tEVZf8k$y6I=NQ z&z$e~m*EZv2^bJST0TAf!WZ8D;KOGRT)*$J)2HV3-;GxFz&#(` zS>VaSn?R!`21y}g?U~-|UjK&6XHKoJtjFl&W*($uY}!)?h^xei=80Etlij+l@Np}Z zZL5%dGi!#GHYwf&DZQ?6H9@MWri~-8N)RB`Zs(O;aCtqG3zN|8n@ON1M!H`^8HF{~c0i&tmt{S(j49UCQJeH<28#WD z91P>~>3&rqw3!!{<-v?f#S-IiY&pzmfdUA*Bc(HCYKb`Z7)gLc(P~}yoL8=_uC@2x zaCT&683D>SfGxmC%+K$9{tKSp4eLvLx6g6<^wD$XRbcR{ssXM2lhPaHk{=!J)#czkKs!NvWDzw+xozaQmrGTY>06j|}I zcYIa<%oEkhu$LF-&!2A3_CEH3_s6o@6v3zsb6Nmf7gn+Vc`tm+o8BbY^up3}7u0HX zJe54T?>W$$>iqOi{^G5R`A_`JPY;IcW_5ZpnWJ58eg%?Oo(gI*xLmn?%8AWe>DCk4 zS;tT{tm#rUIdv2DwrW8AEO*~(Jk;F>=O46r6w z2gnsmj7A!bA{mR0g;oeT1w;s*CTwg9#7Nhl*dt=4{?MyR?&`Fx=wu8Arwd*|k{pPr zN-65etBz@)mt9a(67*EfIl!Gky3 zdrNcHGpNUfR`d8_06#Dn&pJcjTQQ z0#z+Vf}=)8HNGuWjEW92bZ6VsQ|&D8Jokk!f647H?akQi(vEk&^HsMz|227TkONh{ zSAZzm?RUKTmgl|dRSzFOx^sK)^Z&+Q8?4}W?z*e2O46E7Jixr@-1@2?S=zDtk^Am@ z-~V{md~f!HAHAbr!M#t~gv2BD8A5rxvuF3Vnc11LEMtsY4LNPa;I1Y$`vk#THJg0a z(~_xq!hFe3=}R^}Uw3a7I9W|=O7C0o#O7g}N>ef;Lr4SuwJb$W3W9*-P^HyQh|tj3 zg{>@m+O>8z+^bEo@a`%Hih&^miM*g?0j{zVs+3@q%^>=eTQ5maau^|^jOcVjUSRc7 zL{x;MBm<%ZH<*)zSe8mjTHq!N2nb+|6~-7KfD*Y$p_WUa5p1xSje7t`6o%+$`EJF5BV{;3Q1Ja`26XNPat{bhgUZNKsl z{^JN`j0zbksFDX{tq_M137ANj2*5J)(h-0vwNg5~*zOZ|(dkH7cb@7=X`4^XZy zuYU9+A31w;=GK?KqSI=v=Y?WLhLk!PnT1^kZ}H*koge!6b^8w7bKiX*`rwD&`L@qn zxx6aJlNuJuu?`}M7DE07pRpO7SNDb-Vu1C+#o3V@F@hqIYCOL0>eX9Q&`)YG7$OYWt636yYQPJ%bS;&ouIF+qZ3> zoe5TfKDF2i0gwnP$g7y=xaZ^d@99nNURvC{XIH!9)@tv%Ag)zqCj?9?Ol5g z%qm4mLwPHJ zq5!5raBY=;G{N6B_OLwhHBLzJKF(228Au38Ym#7;8DKDj6^s=;5{^_{eGpU|!0d#{ zVWFvjR^pa2>SGNrs0aLLHBR0xETxdpl$iChOsUco}5+5#bo zaF5ZLVS2tZSRIW95danPsr*a7{%dyhW{({^ec_4IF2)jrETdHpz$}MG84*HOyy4}~J#p^x z6z%R~M<4v7yKZ{L%co905lGS`px#9Z$Xcyp>84jo%a1>F;_=5HDf0HdrJWDo_3&fM zXBje*^$F7T9-@sU3-jsenf-_M=dpEub@?~`=5LMq1De$_YpY;|=G%TUh+Ih!`BgyA z)t<6NB<&StgP2@k6XLHtcSZBwHp_3)rxe^rGPx_F;6)xB2*xT(0-OMhHO0yRhf;Y> z1?#FkEH?khdL9JUV^)!}eAZ$cl1?=q-gLPTUG6{x02(a-0U!ZS2P1u^9Dfmrl*23c z%DqH6&~Ox6UCXDkkWr#LBu~y6#-R)jh%o{NiO7ru0W&f+(4!Cq$&kD}m&#ZURSieX zQM3aPD1^u&Z?CQ|Pi>pozQ1KO0D{wy7nbKHFbWFmA=C2u`i%$nS8MBc-v1|O&aQQf za%OtE$O_320awx_;FSmyAO}oxNpOdNEN9j>Kn__!tXGHI{XP43zx6F|YEA7s`N(~F z*QRR!^SM8iiGrA;?A+XabZn^DskDs_et{*sba~G{W*Y7`d`UtVsAC*<~ z&HjsEMw)%kw|~jp;&k3>EnjR+&rF{^bL#pVm!AKEn~>U_Ucfef+!N?@rrO)K@40dR zjk9QZIb0tMU80$c`cPLZ*k6N%T_>bxm~`Y8qW)yb{7P1!xRUJ2 zE@|^*2CHEWyVJP{0F|KBgKI7h6Fo@WYs|r(M!*tKHzvF?fP|%}015(Aib2#93)Ut> zkAcfK`lma*1U;p?%0MGw>Auv~XBS|AJT~J7RQ2sd71K zfQb<3DZdJk#6gEhr5QXM?eR*A0<>|Z(y%X80MP1!1`pweT{~Ny>EWfmk2)L3;DDnV zd0sH&77WXmbo|)aV~;+3=JAtD2loBNH~r=3-Ezy(}~bzePNO{Q9tv8*X?KUI=DS$b~V59{D ziF#IpfYHz`K-!e}z+nXH30#Eqn;=N&S|;$5688)U0ii(109p!b66!)!f*lYTw>ouE z$2c3Mla2s}mK9xV^|DqsB!wg;=!*b13X=Rs;%5w4C-A5L8&g8wR3m4V{0)QAd zNZzmyYoR@x%`fy`{^A$z*tvI&+JD{l58ZRmJr6weoSR>&!SKt!ax@zK-bX)NuCG3L*FD4Kwbjd)E+0F0!*gC#Ri)(h z-jh~K4T{xhP_@F`3tsa4hadXn$3FD2|1HMtUCIk&21JjNH>Q*d5XmAhzVW+%e72J< zpI_Z`VCR4P$A7mRt#hkP1N9QpR(FRsEInW~Z3Xt}tlf|dPoGUr(RGz_`{WRZaWq^* z@M=a;G1&yKYEwC>xbfs0Gh-kDr6lJtWR~)HS3(@aL?{9RVYNu5nVGditE<7%u8+ThGi`Xq3TBv01yRBbrWs~2ABoHOF$Tvk%XK`H-!jCZudVlw96NXZ(I+rEF|}~`-~QWwyKTqr+3xhCC-Z~X z?di?Wce8(Aa$<> z;@|y)KgtRndEm&7rCr%zr9{Zgqe{{`tzx>}vDHg?t9$9x$s2AtaP$+8F{0O**OZ?< zeX84;T3KDADvvRQAPIon72E)8;n-u3zwf>8nV*|Jb@9v%1ZjK!qf@UL;ykxISOVX9SB6MAc!t^z>w#L0E`HCh?_8_ z_C9{vJuIa{S(D!+uMkUkL?kSv+T;aqV*dpZx7#c>Nn* z_JTLQ{jo>yyzYiupL5Iem)BN~eDdhA#3~|*S#THRE*fa# zWnSfq70OD6tUUYBW0%%H@ZNWgSngT6@dF?DpMwEU_VAJEcsO@oCU-8=8Nt6j8?o;rT)%*mCNQ=zl%*1dc3+(?3q?zLB|IbvQ7%JutR z|K>NZS7aGaoj!ZdeV;tIXNl~=(ez$6+Dzq{?P|AGp{!y%U-)aEd%J;1W@M8aZVK~Z zYKobGAQ=J!aq!@wR?z`q_SAcR`uUj$EGD}~)uqBG<6{Hj(}|n6b8}d4u<;_FQ6i8P z!2*qd5F71M zNdhJcUb&a+ z<}X>v#a-7gudjBES$pcfBcFKxAHIM8{ykZH;gJ)o4w~y$e((8y|K@$y6-B$(+rG3k`?+8IRnt=ofe`A90Imoa&CAZ-vRr$| z+uz}#d-S2BpYztYt(?DDY1QixlV(39m*2$fvEz@g^;gS5iLB}@y&@}$aTg*1coIFf z!Yl#741`BF+Hf%1v+ss#u+}O9jR5iglugLYbv4_Yz|<78Ca=?j6els>E+B=orvwIR z&0SX@>$B?RprBZr?N(3@CAtMmvKI^~&Q#YNumlKbE|TLwQjSR&DM1c-oe_cn8%04W z^vU54a|%*Kj3|c~jkK~{jz(2pSZ6xq9Wx`~1ZtWF1jJIR>Pqp&i{Nj@- zYXAZ;nM+>w|HHrh$NLZNc==0T{+yS*;JWK}-+aTZ$4;D@nV)^m;aeX+cH$eq^}9me z84Z!=v^*eX6jS6lEqy@V4j|wHkY|BhIdszv_uTpMeM{Q_?%Ol}@jD*8eDTrsm6I=h z)l19u^}+D6(@?sAfP889p))6re&DV@ebZ~+cI@FN?m2Sg%*lsOT)sGrvD4;9{`lkP zFJA0)LThSnZE`s+PbQBqlz`))Y&8^8MFmsT!cUS4&d+@+uS zcJ-JwDcCA~Z^VKn@3pC0seUk|l&FpdBge6kIT2uHic(C;EGxhzz#$k>K@K=bAQ()5 z>O%Nu&ci~jIwmBNr;P*y%?KunBdN{<0fEh>!kY+?BfN%#0DORY25CR2xoed*K zz)?!Qi#)J&zzENK&$)hI9QCu787T>7mcfXqcc3Fg%%36R4Fd(#*Up%*N1rWMg?LPd; zqig;1^V=4)y#291`s4NWOUsuB(ILP9Qm=jeD|apJTFQ3(lYjOPX0E^Ct*?GvyVJ#b z|M5p3xc|t>8*eD@CkQ=u?`PzrDbks@`6Wi;l4!FoWsvYAGj{PFdXH1P8xte2be|jDz{78YOdns1;i3grASoNQp=~#?QjAx&?qR&llqee zxY1k})gT}#N3>AWfSPN=egJtpn3`#aELa8ssG!o}5+KNOSU|{OfiMV&BM=b5 z0A_#*1l&PF4x=PF+!P7}AOXRU&=!s$zgVy{-FoEFQ=>ur@^AjGsZJ*f3}(3z2)X6$ zY|t;)25Sq4_rKuKZSD5-!mjE29=Ky|4ROWd_UTwo0?e`uyN9Tn50R(RBC6f=+c^znO-Jm6~=w)eJOUcG$ax*a#{ntAc_U(jhYWI9I39I^r)0k3I9N%PqBcDh!8)m#Qz0;qBO>mjT}VtjHa3(N}(fvGVZHz^(Og!4&O zsIM9(tN03a%^l~o+69OhOHdM&l57r*D5{>JR=e2kT%g9>0_VQRKT zum0iR`K|uy!@u(fcMv_R@V|4jT+}6Bxww1Zbvt_7r@FghHE||vse^{HUHp8ez#rBh1Tfqdmb2CF+JVwb*DEb=t!;@ zkPjmE?|S~1f5jI)ap}zY%a>mFikGbqhvzP>zxLH{`@XOH#=I!F;fRVvieGkPSh($F z`*!Tr>R{vp%gY_RcP;dKMQAJejsh@Y%uXN)$)$Et6f<+>iHEG!DhH#{aAX$D?9T+P zBt0`p<>VFZx612KJ6)^={lX>5EX|Oko9IyqZ-j9|OoouMb0(aU3v?K&SmRU^Qn>3H z0v6G%NeP?Abth$&0wls+qo@$rZfD(Yo)?CCfl7Z4MMTL3_0E9l{~^D zAXH_HWgHDlUn`kg$Fg=ir$kb&SV|+6eZ>)C1sA-80Susn5D6G8q*k~P(~vCzh$-^5 za%7oxyTL%l_%HtUFP*$_dWd1a8V*;MeePBRLp!)j?$I%d?jz4~R;!oe)S<vex$O8`#`gZ#4`KexaX=(SHKlgLH|J$rZB1#h6(eCCXumJ_AM(~l^t=`B+ zXU?3WkKFTp2j(B`pPHK8W1*`-xj1+5wXb>eCqMSF6K5~F!{Jli+>pQNov%D|`rM0O z`0BadTrtBNZ+=0D81<_oCoja6(ecwyoOyUI`4|7}U+tRPv9xE$e}310UAf#x)&1X5V7LLWCR+Y7-7j_u55~r{Xejk<#|ZD7VE2Wse*6BB?!(~dO1?81kgb< zh5)0{EJ~seN{_>8SSiT!mN8?<4W<~~%UaL_;65g>94}&;whM|t6yo@*q602>uOd2~ zjGe3;jdm?;Uz}NpmrkE3C=vi|+w`Tbe9MT8BvFQOV%y}3?N;NG_&5I{YhyTEef-$5^^)6m6!+eH$8CoXtq=QA(a5s$_EfN{vt!?`th;vG zD_-@yrQ7bh=c5qsd+@%Z#i?zb(aQQ7Mo&C`{C9rueRu!q13&jOKQTQ$pBY{5=5gfx z%WGvE{`J51`J-VxefES(Tv$2&*r^9DT`2E;V)^slcze-qGtIyxv=Lqi+tHnQBLA z;&Fc_m__nR7Sor+nl(29gh0qh5`hLdAPJbK}sMLMaUCQG(>h0 zViL85NftVt4zAXidUWwsJ zfTPn1qtR&F|6=bipzJuV?Q!^2Rnui2X3dCMvdAPu634+8hR4j5?=ippAdi`uUzig+ zjva$6$+DQGVaChUR8?R8RjbzYy36x(UTi;ft5>g{=DE7P=bTgf>^(d((9vEht%V{X z%*exUc<|#N{j}@boHC+`Y*$+AAXY0DItDuS?>U@GMQ!fRO-=X?G%65^YFBTL7Aoaf zD!ZjEeD2CMU$EM+=-l?1AC8y^kndCKQ-bvNj- z7EFS{cSknu8lM>Z_V>R3%g>yko(mjY-*XvFWe!c>eE!(I_nbX-I-5>RPR*`XYIhvH zqfuO$TPe)V&r{Epsf8?KV1)FL@zBF>H!LHZ*3UlmoE5e-66qf5dGe_zo34 zN+4$xn8OJN-(wE-Wka)R>d9mznTkbYAw&?UzC@Azf#WjnaW2SLLdg)AQif7K^#bjE z$r=TaS(Q*~*EAr807E8By?ilK&U~hZ|3uMUngn8`>0va!Y zrtw&#Ua8lchy$fQf!J_oR>KB}8aaUEKOm8ZI;A2#clN|*zxc%%Xa|lSHV6gcudJ1p zmS%L{EZ8h)NHmeEH*I7Aa3C0b1P=EdY-e(D9q`sITc^gSW~Rr^UA=Vm(&eE|J05%Dk^D-* zcm1KQI~P`$Z{E6uHGHdDPbWhp5|>^($o2l^Z+|J22|xAp6Yc3tlR{ywe*cl9Po8*U zU|=X53%}u^`;ZaB2qa-gs$fx<{^=(^V}_7jcefwd+iW%*r+M?@rEhxOgStinMb3?f zi74fq<=Rs}^eex%G%@uPzxcQH+JqA7;{Sn__5b8(wGruIV}~)dCqR{CJfQJ}lxHzh zuR`!};EYjUnz$$?Fcx;jKoD09Z1q@3k}dxoiKAQru|!aX9Ko53rNk^1rie8LNNSLZ zz0?KU^=;d?-KOLCx(4x>mCMBAaf@iu(u^}vhw?n|9Wg{m5eV-uiAVAP4x%Gk-a#sl zifB~gnyw?=(uj^kE-8hHWroTClohfhy<%d8NH}MiA!5b}1|+W~2L_}xj>;K1#q48$ z_XnWxX)wShoSH~DO66sty zU+nH`_pvu|=`ur>W{_}1M>0TVK&6tZ4?d@qK{%BqP2Rp~`1XzSp2H0n?>lf9Bh8A& zh!Jlx`oKdE?B2ECri?jE*99xYqrT5R_Q?~6_8kd_w9kF)ADLaxgsjQiv(Z@k{Hezg zO$-h8#m!K?R?OzIb-RA`%1yJm_LD#K!y%xukIQG&Z?bJe!&`fI>ZVc2uMQ3OJ@wRM zez|h`*^}8!XUQRnutjteVfkVJ7iYcco}-OIaW!B1^uK&$X|YhLmUkXLxWp`-7#bmJ zEb@hWK_u?!U!BZ!+-5z!nOdXaxtuWpiwOQFPn`3w^?;2n`xPTJ2wt+{9`rmG8bYcg zm;uMC+AamYfis^1^JEvTXxY~=A_(hP6fsm$SO9=#V8G)2ZKbll@+sl^z$ad}L`4DU z)9Wm0dXo)f~M_f0xSVzcf_>9RTloo}MCu5Wm0vgfY{;u~A z^$+M_-FEGWP8R0Yo;~$!qtV1f<~wTe5#emd$e#Tpv$OLv(-V&8?bx?_Zfc6?kr#e zb9`d#7WetBTccA`^N!cV7!bieWf%i@Y8f+z3~zP0=!y_C8BZ3<#omD)P1knr-fu-h zH?CdIWO|kt#$Dfc8)#_z9UWT!#@LeUIdV|1cX0FY=KhtnN;qoiCM*}47{JiOKD8gb z`#3?)^u(;~y7IHaoMZ5>O;rva*kqcq+hfzoOw`gKztXe}PCR>|SfRcP^5_;}Pq8LY ziA2MZZ~Nc>r#qrG@{6DP+?O1u2?!C4)VJ$@5N^Hnmg$XbhgzgqAh0E1$)`$=08*+& zieUv06(na2l7lIGM^x0J2rsJ40{@;7R-mC-6FMqbC!i6mVWbm{V95{yU~x5SSW=RN59Y z@RSWfl!@*fh71#H1|o{(Di{b%3X>`i2+{mp_YvoQ&94`1)563MK@yW6K9dp-jDqJ< z;80zuujGp}lk*0I!m;qsmcgiQ=^FMN@y4lPejmfa+|}{9a>Mb`*{+Dru3kJ_Dixy< z?KSruNhKl|p1YimWq;wP-lzE{F@YEY(p75_w(Z$nxjv^@uawG> z5aEpIq3~LM;ppA>@7T6&et8-Q<*}_+EUfFg=$QAH3XT;H&&-dpMs03unjS$D9 zs|!ohi?a^1KJZgNoCrsiL>8tTH&(8>P3pR^XV=!tS8h(stX1nvBiptff9OpXkzOQB z^*IA?4F>=)vLewVoyl~p?H7Le|4^?19F))?{12X9Tte&X*eH8>Rnc4p8X}+y%EgEs z%&;_7pbElI_{Sq`J85%qf@su8p?KO8`YZU_}nRr z2bG@_1Ik?6ZkFn-dw6(wS2SiOqLHrl?qY4(Zu;rI{wL3zg=XUo4;=SxPAn)C%DV48 zd+O0tDjvd`CIGAMvgb}bHa$C)N@VnS#$gR?`I??2*zM@)IeFs5&Rx4!8)h^f2}hD3 z{|*6lJv)`kO-x?Yb@ZLz{$9@Mj^X{52}>)5*WSP1vO*Xmu2St_ElX19EW`Z4U;LG& z@#@mr^?IY`*&w4a83eo{Kpd6*twfhKSrZy(HBnx+vV z^H8Eom;~x^gyA(0-P_gKqk-<&&86i6AwVpHHXW*2^V5?{^UK9r^WHn}2GI&5RlG3K zWlis+UwoRmGmT1qwPJ_Dv1>Ok@7{g5&{(~6;;H=H+|{|c&pq;Zu08j}qfc9wLBj0V z?&ICtH-F$Ke^e8HdUTDJ@+*nH;hx@h%VM7GF3qmo9=mG0_~y0idNk5#8heL3fBBbw zF>D}?bpXUY?s|6Fu5KFHy>HLH%a^Y+&_4a>#~XEi?AYF(fkQinIxJI@qf5agUj83r zg0OCcxSks@L-nkmp>&`5dcy(cC`e~nE)W_10jGlL!c& z4dv(HOXWQECl@g({K6UK6myO^CS0V47@;8TOO6t%A;R?s3Mkm9Qj+>X%36Wl^sR`l zM+wq^QmKH-g}#mW6&Po7L{h+<@H0X{B-s?O$WDfO2h+(m!-{w0lCJIb_4I`kRw5cD zh)|I|O0J5ebj?m$dK z0E2;8h+u8()_AQ{w(TYf>lm1B86h)z^sZwXXO(6n6tX<8e)Z}_@c|1Ez#t{?xx;Rq z{9-KKv2|qYmMz1tdH7*)>?`M=XOx(_hN8*tTxS37y}6#DY$mc?EXESKQmq2D>g?xeUs z0!6D9^BQ&WSE7c6TKj#}U%G%deJ}+S6ZK_aBVbEISQ8%%mg>;KNK$=UWpL#IWrFR= zf%;VHVu24_pq>ga6(v^zGo{K;kaEGiR3$VfOuV>!P~~Hc0BeM3;M>%3e9plLlTefZ zN50Fb&w+_EgOBNRa74JvkfvjdF$3;1OtCpzS`9_@<*8e9ljF~xJJ;UU_3-QNMHq>a*CZaE&|p!s=qN7_*Emy9ONaItQ|axh3CYy#uMj?DJYU$^~yv5?=&- zV}iBK!vlyw!){MZ{yt=Td??6~1^(xD?C$3$+j`Gw* z90MoBHwl|q!P&l!_C(v?{Mp~k&5nQZ(Pxs$oL#M*c=j2WdfU6&t0nlkU;T9}VsH?3 zKi{hq3Y=0a33Jnnw{D+q>*{Q-l?gX)++KL-p*J7hdDt{8AS!QH-)O|Sp_{rD-kNJS zak%Mte$!u1f;ha2RxgKtyZS%@^WZ*ZVkHRMpje4=xG9)Xibi}QuFxvfjx7^2uA(&c z9tCc{an}t0Hv*R8=?8r#0&)t$2rKxbQZx@v2n7UDrTaUnKmOeK+; za$v#q9hg`rSYAN1Nnze-(mg{X0FdbJ@96E?I=p$MP)emDCeb;j@|g+7z$v5NndhF= zbiC(|W8IydjZ)DtLuXE&&^7bc#N}GEzH@lUE|z!f*hd{7i=tb=qY&$+F*LH>b{x|* zF+vL~DXIJN7U+V1nGu2x8!on;jIslU{g!X}mah&qe)fw`GU^l-$HRt+4MYCdbI<D39Xvvf6t0W&}WLM2A67V-$Njskh2@*yVjN0rC~qGb8Tft&;Jm6$is#gn%}|8`nK z5HisQ?bIy?C~H?WqX67;Rq~RKFfvod&>C&Zg{T%Q_X@dFy!CRa`26x-T;*G01(dF_ z`VG`Gh`mAiErt6C7zKn8^#K9+RN$qCkcNmREe-*wGVe_ux;Z3{tAG~Axj{Y-ep5MQH z+sg7%A-`6y*6%vB|J=okBmJ3t)o<$@FpL;&+R=J*er=)BsDxtN)T|Hu$d8rR7OtH- zQ?509p!HgvGuGYFaq`4z3+c>Rt;cg+R$Gthp1V0NDjA3}z}P;#eaHCtEY6sVlQT`~ z4G(X2FyGP9E)`-a@I@Ua&IOt8 zA(bj34C)kMsmhb@b_EZdn*g}Z%)fWF5#0nS*H@@F2OxH`?iwKOdbl;^AYGbg_? zHZkMrB&jD#E3?G{J$UDRK69yPX5?7@_kxb`!8;$wbY!t*aH6?QFOldOFU%gl_juFe zbNOlNH^Z@LwX!<1w5-?pmcC&k)VN&Fw?YPGzHV_tcXd7W{MnPwKJ)zP=gwv`$!fE< z_t=3=L%llTx5h^AzVm3kK{J`$;e9*%dfJVs*0ycSw}0Dr0vJw3tJ}P0uSMe-FO<6b zz9U}A^O@$j&Dn*OLq`vdPTwlkJXBr2xj1q6o8M|iOoHUdE+w81q3GRr@A4Xrj(Dy! z+j;ugb6a|cZ!R`BWpj~8M<^6EOu|*axtKJ~B+G?DHe!Jzzxnjl^3}^bVFa#pF%bV0 zrGdA;|57=b2jeG%HD#dNs@=k|Y@`it4Gy(IfK;#60A8XA#fG(fwNc%Boo=rdyd~yR zD2TW!Pf)Q0kZ}`|RUV(q{EafzcqCDrauh5Os=noQZ|ilU1C}`~XaHPt4x|$;T2H!B z(EUOjKsoY(VT3fqI6{&fuK@Nf!NbLBH5!dBO=sIWJD+;$%eh#tR4pT&Q3iXC zKm5$cK8z7WGlpHGoXS)bY!0_?Tx!o9eD8bS_m_Y5S1!P6e%ft%pL^mnF&2&(Mx?FV zYgXdf?qnw6B;z-4Ue~l3V@-sh*>E&HRy~$$53PnuQ@9*1eQEjDBZBHf+9=vOL zc|H-&=|pQXK6CT-Qla9MnjIavnT6S#SFY;B!y&G5dbtqlZ%i=khmbL_c^jF(xnvf4-vZFXuals9LW7Q5SX z4ZG6anad_)jd}wiSN+cb))>adwjG<7@*Wfs7)L6eU?^Y~FE--9 z@j$5p9YUnx0OA;ed@2<=X*%H$RBBSmjG{|$aXYEm^iqrNobwGrs15uH#pd;yt2ua% zTBsw|i>p|Ea!eJWB!sDENrHihbJvBbgeaA)%!~8a2PrVZNJpSyY+x*x1|cR^l5!X+ z3YeG!zG*TlWB{u91_?!Z#p_~%Hy0RDAXrep0AVd2NqqDB-=1pM2fA~$2HdzgbM59R zXko`$^}uEf`#uK_zRx%Uj0hq|qH}nyP*3QQ$d%Z6s1gJZ5&}(g*hM9UR(@AU(M2jt7oDTq)xl*KV(rDz=B# zs(D`bI{G^d&^v~*%X5umhabFfZ4u#!(+n}tKJ$D3CtqzQB5hBfKI4&kZ>rdk-;2{brptD&i}kBCJ>Atd~s}N;Z5jzyUhDf(WI|9tcY$ z;Kiltn4XMSy=>N=^k zmd}?nsT}2Kbo`d^&H{`<4Ld+-b#2qY=AOR(TD{zsYzvuYsaD>(ZQsQBSi}r(?iwEl(XQ=B)mjC#z$!+~zw{V}>$#LlcQZhkY}tJP^ZK!aht}5eU;N@19LE8Gm%()A z)$j_nZVHr>kXXaIL8RMYYpBE5YfypQic8iwW1wj=!U$AipR2=GYZCDpJtu1~e@ zRGW|tJme%R#0p;ns#XflR6s8Qq1E(N`3_(tRzNo2V2p@{4U-@M%7iGp5<3TpBl29P z#=BikZQHZC8Pb91R>F*BEi;5Q6JZfR$$JKA8Y+SX*-U`(dix_1-qaXlLJ-jr0wjd_ z04TS@@o)aopGC+&eC$A6!|_BXcsQHQc6D_>_xzl^CweDA`!=NriE=;$y*H6G1;>vz4szdyx&r`ar}Gg>Se zYLA!$gTst+*C{pXjp4)H{oO;ExRvVc&bEazsl>jcyX$s27x8XhxivMpcK-UZ<6_Pu z9A#|JeCr#-5f<_==}W|undI8sRCizh>tAz3H`BJwF|fUN-G_*^cy+;Zbd4aXh72BG zURj(iESV;%ts#Ov%88wKA!dd%sW3Qg=}a^hCPWVmf1}y4rCnW{A9?K2%Qvn75^bfg zPA`|Bxym&V!L9qmdr28ZK^#!z@ZhA1@LbyA00yLV0aV7M8s(Jq6_y9J;>^p%!{RUY zYcq9E2|olOf`}?5we~$raFfTXP3lk;uPLYk3X;6esHD7u5hGG=fm2RFSaqo0K3URN z6+`e`Za4f|(ROXGx@I>Uwq_FDB%1NnS;SB{_<8a5+%PyuAR;WLkQM95u#9ll#2A>* z0O=amQM2CB)(MT~*vwq2J-)Iu**DyGYvNWY68hqoo&l&>F%5`l{o$a2?vF2dsJON` z7uB@2)!O{xTz;iM5UMolVCZHjT`yD-C#7>k{D5Oc>R z%t*3}qhkjT9lAb#Yi@Nm70qnjzV-6?XJ*HzmKT~++^0T{CyiJn+11fjEU<7QU8$}fy<;234MwZsP(GU@ z`$mp5IlA-i{jYiW_51d1rPw0GIrrRHe@Fa{Z-3LlEeAAY-oK;c&et7|#N(zF=JHe4 zv1w>s9m7r;2KIJ0OSE?&g`)b+Qx_(0PkNkRJb&))2ks7qOoT!7b^^k*d)tAs@7#U- zzP;ObYMN$+k|I+6y4wg}jjbRUn=0N951>Y1^qqpL!!TvLE|VcuP*&CzL?3Be~OL4FQXS0A*e$b>*72?#aPEbjv zlnZAFVKa=SxinCY0t8x7*v1G;3>S}}NxmrPIxq@M!lIzaV~~P;!Fr)m%TfOsDqvMo ze)0jSB!(f=fK)shPIPVCzI$8G@N#u=>c;Jk&Y^fb5l_a655;=rbD#fArDQV%x{0Oz zk!G3%yVZO%+ub{}Ji%>NEf%BUTqYA(1SM!}-c;B$gZ+92)2y85-zs>+0(4=-RpSs{;VLbz-)4ve!Rw z=c8Z#Ql(bOwMSB^#LxV|w@2gM;Z(e^;uTky2#Jl}ym|ECJ*8?r97#LApGw9Zx7OR2 zL#Rn~^Ot`1=kf*5v`kHFi=+-6IMAJlnY;FExpDpG$mY$RovFozDyGHT({o*IxpZ63 z0_KqjP**3R&wt_buG^%P8HTxi|7#8(?r%2P(S!R&Z!eVBmhXDgeb+CI4i9ZQeD5LC zGFO|(D6Hixb>DZf2rH2u?aGF8nWSH~S0`?a&&@GL1=AYC*Vjn+Dqy|P>)YZrsx}2% zNn`*8DlEec7{c*vCLPqsoX)kRt%p&^cBS76(wm$&_O%+$FG~c@X{CpZqzkvi8Ku zClB4RKiZb|5MkV#nVt_*lnm<)#{-Q4M~I0|JcA)dVr}hYOyUtxeGJEb~#CaN7x#*;T@XTIUx zuRnc#tXOl=dVcZh^lyMFP(hNKkn~|u!{1E4Z0hBa>nhh1^{T)-$+1QN)EmxJti#le z)H#3<)|ARG2i}4lNNz?iTE@~|Mr~=%A*eqZ{H=*>+eWRGdL?`u1oyx)P=FVeaz*>Z z%&u}>6Y{$jGA+%mQRXp5MFTcw-~%Su2OyH*u3%j<1Elg8^N^;2rXgRT01^b-mU3aXlXg$(b1JQ^~r@>%=f9w5XKBM z<^l0x%iRyu8;j9YYOP)h`9>oib{#hnNjBr2E3|ItL z3?pHpLz~U|iKou?_m8YBHu`%9-u9-=`GvWqC3o-6BNXFWVX?Ma{HwqE2Vu7)P3ASt z2xFi7X6U|qH{X5dn-cLTA~a=b6uX9r))wc(G1IR*Rv6j!MZ39FDUTJa9e??^&pz|i zDW9Wk#-mINhb^La<-%|IY6cqCniG?5*a}x0tfM34bBIJj%L~gpc5Wr06AkOpwxf6M zxIH<}rHltbIzlvr2|@38-#2~olOM@uGwlPz3yTY9&z>k(n}7Z{e|hJf_mt^kSNKra z2syq7lu?cy$5~lhnx9!r#?s4cWkV-A(R`nB#t@OBi16amtCPxNS{hY24ZNAbue(Av z>DRelIaGyoVqi+S+K7V5oe~OC7si;$T?~QP#{-QcK_bOV;$gk?HbY=Y4(DN}RHW9u zfjJ6r+SgqR6;VFGgHT8+$6OfzLA9c1gb){YqoIW6In1e1@VSsMr84ED3O5BLid%?_ zGf}xrhq;lQTbe*KDi*90PXQ#P!*Wl#zTu1{A z{9GiBaw$UAF;qA31I5wpaoT0su+zafARS0JQ#rlKAbO2UrAX ziZ5;yp!UW$v{5HhD1oQ7d4A5+_xawIANq+yUbCrN8SZ+&^M`-O-DH+h5di#rI2eDFTXaDzn%R7GkPyd#xcSY3_UIndJ zpfVv2to3l!t1oLjm{Hy`%EpCl0&pBSOe|l(ClLb@dwJ`Spep<*A@o-Qu*5@cyeGI< z;f1t@C6YUZ5kW$LkOC(%0h2M5bQ20dt)im_%X8k4~H?OPLnjRjE{3BP)`G(zR$q4VxbVOmWp1bU>G5T*BJ|A z!pm!oTCLoc?&uxfIePoT;X99oB5l{Noa`OE^W4>c;ut~^t66tIJfG(_Ii;Wahu?Vp z!{4UMW z@B8sz>S^zZCnL1hNJiU0D@;z$U>3?ZYF)iOjp`b64FIkY%&6-&R}+bp%^(u8G@>mo z%yqSQR9Vw-yl5&lH9DJ&YvYeUnNGz@^-8lTo1*BKp1b~-OYyBH0}YMQyKy ze5MF{UsL`4)rrwyX-BQG7NlwcI(2*yYA_&imLkUo&y&!o8d{JzQ+CCv(^Z_J)>K&X zN<>&2V-`{wUa(rn)l#4bF#sW?nP73^c$9mbiiijZNUEkhUKZ~KYy`TFxcXH^aLI%$ zly3vV-1C7FMhp~&*uQ z2q&&f8I}LfqJkyBixA8Z`H>I&n2n%A$Hg*TSzYb#?2N>srQ*uvt7F5PH%(5LZQJMA zz{J%sI4)p7hwgc(rz5oBR2UB#Vbd*_Z0r!*$>iD+5p%WZHR|Pt>z@4bS4NKBHL&g2 zKyUhqr$14v8q_Vv!UiX1ty;x6q9dZ~>?@D_S@_77-}}2i>dJ-x{I9=%WK*?&s7pYS zE>LMrfKE*;a{_~+0A+zzK0paTPId837z7vrKmx+BSlTM9CjbY4+zmt*S8f`aM+~U` z<3Il_R4U8Gr%s*x#h?5cBW%R}@Gt&kZPo4R?bwmVXU>!}G1K;8cI>9-mbi?0K?_^v z#Q1dIK-w};Z(CP78CfkmTf1_XFOPNa?rSTruB=r%`(q#YsSl2R;x~T%kxPt$Mzq^! zAN`(p|5h>*OR(DNd?6FFnvT`<8FPq5b^Q%vtc--+S z2rw}a7A5zQfzCuUxi~k2AOyhfJpNEDtj{hiW!nd;O;zUl)U4lsJo~v%fAi4hYBKd!fUN-i04o3vz^uR; z5@5ObVmk&1NJw+wTnZ{5-V`03k@UG+R33Y!l+czDQvRm>PanBOqL{x_qCxO^+e2Yls07cH5HBs)Zuq zANipVY~9|S>FO#Mm)hF;2L=aqUC*|+kKVWruGTY{Yfr^L@ySm+zKtjc3<)E|u<>o* z^SxhvEfLZ7AG&*SZajj#WcNTO6UjxQYsHdBp;BKvv~Qnb8WA&g;NTs%FJFG!yT9X( zL%UC(Im2Av(0m43XM4;B@>_rW`|o?_&ToFN@#Y7=+wn$BeH+vra8{tX2CfZ00wbnk zB?|zHrKuuoA|Q#0bqt`Z?~x@S$x_KY1*if<#E+IZMTRpaar_+s2LJ{ETb=!(_r9}m zaBt)%e(awjgS#^@RL-wOvbF#Fi@&nGR`GmKGmuF_|NGZ}@A9oH_Z&I) zSLqeVDVHfF^M#WI;{*$!&_uc^KM*Reiy@rQ4XN6!5zsMKUwDKNV?00`1&+XXx#w|A zKx%PO$^e6*8|8Wvb7N_CeqpxiImOxO$!aw}KfkbPWMpD-v|OuCPhO{3LL=fFdybpQ zw9U>em1=8+{7NA|+uPMoA`!1%yLEFc9E|`ljOo0J$D*<14s-5 zvZ59?Q6`h5#Q4O=|L$P#>7n+K{`T*Tx8>qF8=wji7a|cz#vmStND3e!(!;F48eJe) z6M(ANs;VfzNFi55eI;xWi-iP2adDy{flO>f3j18Ks|#Qkz(Yo4`@SRkNB^MhBY*m1 zA3gPHD>GACD_#d*t{AE*|a+qUmYBx6VJKB8gRykloB9wAV?^WL}h>hlH1{k=c__82(7^WBxT8X&z?U3uW%`@07EPCfaRs@?P) z4*?&a8h_WrcU#d^S8q37D_*agx36FJY?}jb%?e+gT3*8d>G1^#qx^-!oYsx4{_Vjl zAQargRbClvD^~r&s9N%%^{$_bOoyioI zmuj`T6*iB*=E3q(ZK=GLOn2!7S6sSzWM?E~Zr-)Eyjsp?li^52Cn3i*{^XDT_gsGd z_y6!G;`*Y2HtR-+xK;2pAOr{jQv)*zrUMWMu*6IOu*&$Nvdbw@y3)ilqylXl)Cf!< zHzWX99qfuNj@sfX*y3V%5s58Wl=dHq>z9o9?x&x+#x%Q}M?OM&*ovCb*S_W(qDeia z>tQ3jR9xM=?_egIE9DD24s<{M#V=*kJu3^#i;Igy_uu;PTUS@+Q_0NsErU-yaoYDB z5&h!a(1GjM&UU5Ku5O0C%7sf;>Yl@WiUZ9iD5#P9sun{q6AWzHsG`Hw@&z(Vt`szb zRe27YjyZ3A%_U|r8L`WXvMP(UL{=@2ivB%#SS^OBYQ2S?0BS2oisB^TRvIJAP>HHP z1VV-iNrEgQoah)hrarZsJ`)#Fp`2Ig0;F+_fl^p6r(vXwCq${rp;&7E zVITxiX@bvH;wj2cpaNdXI3Zdzni}qlapup=&b{F+50BoM$gi%23BBuqhp$||;JI$X zN?p0~=vuMjyMT41VVxspn9Mym^pUwQgOb#9j7Xjj)@PkhLar0i<* z{Oo8flgwq4iFD4Vu3M}A?9cx2FMsf-Hg9T=m}Y0R18M}c0um z01_MpP}!U#wk(S+1V9%{AKX0H4#d;qfRNZu#flH>ldeK7L#)U+%T-{901SnIL}i*g z0pdpb*{t{UU;M%D_k8E$p-5aebpqzE{MMhe_iH8?#4>J8FEh{Ab?xM{Cpx;bu;vd9 z^)Jk?cusNCV1GDdHV{1j{PXd2M{h?M8vqT=DD%ON_C@;I_B1IAVHnxH<(Gcy$3O53 zzgqJ>#yAetLU=%-NG)G@?2PmOwos)KH8r}vPA}xGVa*1GBqRy$j0Y;oT%CeBFxibm zecsvy!{ta1#u$X-WS{~jR}?k7<&Nr@SFnb~TYpw_kO0pmEVoWd8lA}l#gPbtQm06e z(TSlO8ZjbzygeLETAD!+Mk0X|{uE5LZK|0`JGi zUHO3@|ItJuapcgzaG%+k0??7&Scb*FG-@EG^B=&hFX24FO<1G&Qw+`}W1UW31FFYo)^6#KiV(Bk4qZ zW@c2QJ|Tbr(Wd+9Kl!V~V0vPCrnr({8lRad8hCuSPWDgZNSWOi|uHta&V zGRkzxl}@`_2QQOmg+oP0u&M=5-&f ztgVIO*@oSW_zonJ03MiffX@VI20*F?^$Hjo&<0?vk~8HL$^n78U|@rVSHk4WpOr>YiraSz}(~ay$gWmo7Mc>^jd!Q=J>4Z0OL$IiKgjY z!SGc5KRQO6O2&1RKlFb-^{=1*+$Vl^)9#&6#G^OHG%Xp9k}zueKFg+Jt4kAIne7nM03+}z zXmXgZ0>Hs`L5l(SP_IEGE|i`nviPDShXA3Vg~0YfvjE~i2tY`H8j~5Hm`$e+s_sjqLt@LO6uy0X>iIh#`reg`g<{*@`ycFHn`!{mIx<~mG%`0fna;*9 z-M;L*)q2B^rLAL!9*9T%?vC8~Yo~Lm)ZF6YwxNNMzW&FbK0~R85JWUgtk7Kt_xaWG zm21}@y#IcO=9XtJk4>)n)R7f|AS9u$UAjQc!7cw4C)8?K101RK7l~k6xZWERwSu05 z0X`|`LCF<$AYV6-X*EF%hGwrsgtfti)H7lvLn9R;ZJ_kW)bIKtRlq=D4ub>_DmD|4 zuJnQQTSFQ~SVN-i9BG=aYs8A0k!T1D14NEM-kwoWlxJdHCZ0?Jta=a%JfJ;~5h4Z# z#-(hY@AHTeO0^FhzyIDdr_W@K6?S19t`8)5smk|Bjxzo1m z5rUC;>S&lyvwh#*?aoRyl1mx};Yh1Ds~$y|=*e_y^YDm;t&Z+CoBGK}sA*R|^Mz;r z^`Cxb(~i#B>vNY*o*;hHBoT~JVSYIsiL4dsMm*Z^i;;m2&=R1@D4c;^1&x5F%b*>M z5CC4Mk5UfURjextK7j9l=0n{E&x2+ICS$#d4>rTgN)HRqfzqHaQjdQ}!U%%~p-uhS-Qm<|h zjJ{Ue(cQoD-XZ+n+AG9v&##WYIS`4_VmQ8%Uwjo zXTh0fYOg*1np&keIx)L*_vZ5#&$jh;r90ZXa=Ao0d)K}9wI_3_-VQTrggnlx%Rl<_ zzxsQ>`;&VI%qve^dhTyNzU%1Gft`bPd8RxwliJjy(U2DNlbU7M*TN(YQOQ?G0MtN> zfa?Hl0vQt65wrja3AC~SLLg_2fffb34B;@?Hc$sN3y22tTj4rDWERN+#rTFQW4U4` z098d#Ws2}M0I&)WP3wEWx|!}df6tNc`Ic|_(7WIDj*w**s%5Nci<9%sdO=U?C%*D5 zLg8(j`mbDmZpYU9R#ql2J$Lc?tL+dKCic z3+_P#mY{|<=3WE`ahNFWYJiaH!@#nH#YMEmDdK=JUjKk)gd|9$f>Mt_HtPV#0ipu} znY!|p=2=Owzz7HuY7I=fO~30>FTSewu3@0wX#8M@?Qk4(0W;h|3C9Yv_V#=lDiFd zX&Mrm1-upTR3QcF2$aQp@M>xu>pBu%F|A!NVzDt5>y;_G2l7#YS<18*$vhEM+!N$} z3cOd#7ps?veoDc^qDniA0i}$qmSpAruVkVzATH8IUyMdDIg8t4r0W=I5(|}Wk2nUg z^>!cSc_a`}1YR0J96-~^p8MZe7{A@u*%=}h7$hCn+uDZ~3M=LO^5Hx0W%=5pI{{I_$i=RB6a-uUFV-TzxC*@$*~&`zy2+jMFs}8rLt*cYMx7ayTXj& z8=w2FZ}{$a?@A}>iVrk z-=}vSJV?Rp8R_ot>eEfyY}#wfWi1>X%C&v=D<@sMCMuHV554DG&tG|V^T5#4C%$~( z&N~2-A?BVte}!VqnG*94j+P@iw+fmd6r^iySdSO;e{ReQ)Rp-E^C8g&5mqqTX^pUg z9lShv0R)=td~Vf%Y9$_UE>kUaQ1Jgp!NJCy283RAT7yC>waV2yFIE){WA!IbY~+l$ z5YxmdTrK4c>s4?@l zLm6k%6klEyb5Z#b07wBd#5r?{m674CRwT8wymsoDlQ(XTKX>wploico6605I-5k9U zjzsgT`Et1m;#nwFtTRei=NICs^r7QN>{99VZ+`Rm(*91>;Ey5FN9oQOPJpnfc01KejC)PTG2`@U)Bg~gGzwvgpoJI(l1usT&d(B1R6n_iHV^JM3dPg5_7;2 zC{W;q8|b`feZE)~M$NizNtP@#gTAfHe&zZeKSLYje*H0*-^Zyg($3s)OLgoKt# zbw&Rmr#{12KRA2@Wy6aTx3b;co!xEGRP^e^SZ%d5x4PhaKF3h=Z3J2}k-L54Dg&Pj z`l=Lu#v0kaedN}~@$BFrl6%J=Ra`VrhB+pWwm8`pN7y$CtHXPWX6cf~%dGYLr2VqgIDnkdX zBaX3rX@l2S&&gZN>eaT^hv)niY|VKAKEEmvwFq?~yaZeBYwa%8Tw+AQUdzxn>L8>8*<+~VR)fA7fPK-c`--172lvuSfG zPL|*bT1Vf3eY^V$OKSx?KQyuvb0-{0-F%7r=RE;=^MRrt+Ok!WB2~G<+t-Z-19%Mx{%c?8^q~e&G}UFgY=O z<<`x+?z+dWluRpGuT~r2R903Zr1^6{{gVS7L$qH1`+vQ#WHZ7bM72%riNeZSqvB(p z_m4*?nW{LZS7%GAMV?HY~Rs(rJ3q$vxs4ZO{_j0Jq)&Ak7S0x zYp$*3b3JXg-RK(Zz-8Nrg@5&fKlkvv-{%#_9{JNxQ%9R#EHcc2P!@vuna1n4htpryLNC{TyF4p3KcxD2ev2(bugdb3!W9A7Gwiq~#k znz=oF{rt`8>Dgybk2BX@DCc!8R47b6`s6bQ4;>*+_y@l0TM-LOfPz?3!&c%lvq%h@JcyaYQL+KBd&Bocf}VkO^XxP6*Kn7kCu#-u?dX&~d}D$v|h@ zc)nJzu5k*!uBRAwHSPZ6_pVkd-RWHS$fhSA`}EA{;$m^x^<5*ZW5zw7bIjdJ@f+Xu z4V~S+^NWj#NYXdl5U+vT@aHRw3v7PFvj6(swF zxKTpDWlSWAJB{$3<43oD{KF>(hVP$VS>C%RyQOa!G`=ubTw5uSc$6~l*0~$ocWwK~ zzkH-pZPXhMU@Z~}@7g-JbI+m0iBZQO<@`!pTQ76n?vD0qz1r8_ed@XAsm~EcuXKSU z2u~XfCcg5yAOc~j!dscwt)ZXV()zS7&~3QUwaXk6Lk0F_J#4H!p5 z$G>5Ea_ZUBXY2XZn>R0)7bhzvuTr-kxbI-utEbb6(YZ-`wHZoAPCW6YV)gz)z!J~-k!HeigSW-3tsk^8~U}Zz5maU3IK^1p(qS_VEa>nbw2quWju!u=uQ9=}0iQ5Zyr%3id zdf@=9J4**cHgRPH@^Zm(Ze{5VT>ax{eO(c^7#FG;m`E0dq`hH4*fMwA_m;R_3Nasr z3>Q2fd9}KiNLWXY+*8*LT3p+=@9r2TC_+-2adPaU=AcTWV%KfXIhA^Wh-;i5J96*% z)HTdVe_vlT370Gy)IQEOLHUu+Zfb^1WQU@u@Rn_RZZFN0^R?-j`F(r#e&GvW%$G~G znujn%qmj)A_jh$hwrtvE8QP8U(Fcw{FgH1gh#A7x@aB=ve(sTmt8?m#uj{{On)dHn z*g~xlit02Dj;W!IDF|P4ryXzI69@@f{hEU>--g-`;vEu%MgqV$rc=BWz(TEPrQ$Zu zgZ;@oD3Yc)oFI-<>l`sI4pHtv!RSyR0tR`mJOCI2!QE8PfDjfxi8dVIK39~~V3Snf ze@n@gfi$^kbqe8(gD7#S+?oXPSCMRWWFCF%JFh?WsNJZCYdqYZ9>}y+ zYIWE3E}lJiWdEU+wR|KTIeqyAr7kkF+_&$3;23GZ-0~7*91&qmO~4@J^y$+Nz2;3_ z-93q}OoowP{M`@#=y$Y_Ju-T3X3nNGk&M@ywPM55HGgM!rjGgXd-p^;wotd!mPnp` z{*nffNT#i^vbbCVf0ItaHKHwgJkm4c` zfIQeP#M@*63p6R|X9`AD3F?jc>*t!T<5uTcd8JXWS#bp5iwj0nvtdds%K$MErcD8~ zi|bpe1JM^3JP7b{&FuT;ADKL~|9}Q{pLpq5_R^KJy&ZAS^BHw^^mcy!iKiMhN;!*$ zLh*R?{yVmtkx0l0PtA`zcC}JnjmO(I4G+}w#rcW(vsbR#^|}hTH;RK=<*{Co!qzK> zStxkXjjQBe6I!9KNgV+Nk*W0%w1HY_YeTSl=P@Ek^dW8_q4!dI2^A3V;KWtgT3BQe zf<*v=85cN$IYvZ07{LT1(2#~O!kCE`W2#C@(r{v3kzHldLDZ2OfiYE!;%ivJukMkJ+$hT zoNA%bKnRRz%w(kD)b2QZcyoV$rRHC~dhV_}AMjj8HEZvl&dXQF0O_2%%w-;T6PEGZ z#mjHH|85|?X0P@6fBwsRI?2@;wj*UN*6Ni;bFtXmm1`eNgsvBg-}M7;(^$1!DaOsL zty#Voa=^Lv^s`gT%TTRRr`)KP*2ZUd?Kv_%em>c?6I=)EH6T(?#&oA|kz^X&6(C&I z;0u6taI0dAB}!4Ea5_H)u{acqpkW}gEin(3dTC~UZe}sx@NS;IdgaV@Tko14ohmGr z{HBvMI9M@&R6zaR6t$`;kscDTH9;;lWj3lfS-s2iXCC{)v+sMy1Ix?xXs82Ov@M=q zE0yx|v!%N8iBCUTYdW6iG7eEI^6&%4XoM~1SC?m&o8{sicO7?}Y9U|Dv~}qrYQ|zG zPCnOc`eHm?m2@`XBD`XZDs_=pCeA`Zvxp!9sW2xvse@Z=je{p_5DtA!(&s8A-7uI_ z!-ZHLCtp-0o!tlj2jyAm06ES%>Z)@z=;U$bb{iMc-Yb$+pjte&u50I zagUi1ix2}iC5Qm$w&xN;9B>`G>DE2Tj>2^PJHi90CT?}wLBKd`<&$uUVoV&UOd^C1 zvJXsV!dQJ>r7n>%ug_0_jMcx2bW z*7=p`;??=v)fIrmAN=XR0(f(!O5D`%8R+icJLo&h;am)8HA)FA&VlAbE)5Wc`Zz@T zjcgZy=rp7*5W&Ne*__c3(bG*Zbbvm9Dd^t?Kp-PIQ$ql=r3+IRu8;oIZ+ygcY@d2M zA_#Nu@4o~XX_|h=NZ(yY2444$x3&)_0ftqtA{ANTb%6T;o(6hnKpTER9CjPvZ`-?v z7w0c5RQixUQ)zgb4e404zkd_={M1_cxl`w<5R@^o{*B-Cjc#+nEmzv3*?l|rO-x=s zefs3lqjxo%H*egyP+e)5Pyz%Rp@4AkrQ!U=C0U0GhO{p5!}*a(Lkp-Qdcdkv2xK#T>lN|4XXWcI0u26DKNbK$$C+FL|` zrOYLQP%ovhsFD*CXaxi`U8LEJBZ7f(N(s1J$dRtAHOPOh|7}9xRb-Z2W~mtYR;H^r zV$IyDY#P|rs265trfqH~(>d3pk3IUSwsePG(YVRJ`03BoY2&Mce1NQ6IDVhxG2-QyX5!ti+4F|C zz89$R{J0hFBxxP$ zlMvr7ER~8t%Rn?BO>k>qL=}nD6ov2%SPs;$Lqzm5yJavepsPT%lmGa;ANlB&M{iFZ zY|A3%Hw!R)$I!KFGlhzyhxA&#@yw-blS@mzTaQFTsYtg8&{SEZElTg71$Zw+RsgoB zoHPkg1lT!$n|5#R*gOQ>UXDfj5Ey0>O4F0`^DBw$(4YL_&$@1tbFLeDBplLcerheR z>(Jd1`tnmx9on@|4|f%2Cz2uDJ-jzxT57jKANk@b`5g%W#EUmAbN&=GiQ>WRWzyKq{LC69GE7C#ilb38!8hs)8!(batu(yz_ zJptc$Mj5d6>jrl6;PI`Lef0Iw8q}|)5iHyE3{&gOq<-^9e)Rjk|NFk}o4)bf+4DzU z``Yih@4k+%_Q=*da-Grkkxi#hU-;Nhf1qpoU^dyF(Cmn=htsh{+-hs<7)qqS=lG#F zzV`L|JF@4-Cb5Y{f+*zaMWBcgs0x<^5|sq1uok3z6$1_}_KeCTLP0+hON5B_scHHGzl1Kxs3Qmmyn4S8Uzkl+JSD(1K;Fg=yrOHAL7Mh`|hsGLTc;v}uv(a=sBW&&1wF6PNttXp^hGrL+mMfJzc5Pi+&X3Q` z^l#k)Ce&6}|LBkYv0QI(&I!Q)d}D_C3v6j!qL)9~Qa`>7UJ{H+tt9zAh$Yeppm=-N zKm5V(e#>hfeE+w7`@7%r&YKrbHIU`m4PTfQOQ)znfflK>t+kGhP;k9P%y0e3R^P5b z3y=!$1TF@y83@jT*HVY581d_>VId$0bH<29C}jwEHWBa2_J7N_e|yUEbK%INCr|y! z|NRvps8Xq$o(ts_Sev_N{{hRfX$axE1CbaI4Qx@|r5+#yw)P|owSnQ`cfIA|$DTaF zv8f~M3VtUBwEhu_HCdZ$5ldz)kUXm2Pyx0$9IbD`7!ys_(||GAw~QF2l<{WWMM7wh zVbDZ}bMT{54o^#j!Z41*gn|E%Rot_Vo5FqAKc<+1PGkWuOu07sp z=BK7+J)io%J-lP@)YRnG&0Euvc&)i=yG}OUv9i31LJ^&Cj*0IuhjYK?L@Z-$u}CpK zx^?S9zFe%9)A9Iw-*L~b?ddhU^SgfN|6ZF~jA_K9oDlxi13cemlvz5KidMrtJ=dnD z7fRKo`AQTyon76Lj$Wuc5UGIK4Rj5fB`}DxdiDY8f`%1VQ*PF6mwLeBdidVH?4N!1>CJtK!EGY~0bQjR z_`FCtcfsN*i0xCf!U#YfAWuuz+uCdY^5N3MuX`8vom*35>HdUQEC1|I{7S>AH=9jF za3+;~-COS+-qg*#>bc94U1oT-P@0<^k0s6C{;uavpI%*FK=sPmYh$+Uy{KV5LN5wf zUoV#my-b*eT9+uGgCm_>0BagSW+-f6LadNQw0Ji2slWaB9le>hu4KlkwQufy*P)~P zQi)TOGt~23-*2fwgTfLNRQwEx1p|7K(Ze9^D<~GVfvq72S;Yd?!Kx+|sn(w%qT1=!4l}xjmcKXz{_3LDSNp-Y~5s5l~Y#e#u`z3PFRN z=NxgyO^ozVqPIKU)i<09>vQu9b&vHAkAxz|g_CC)cy>QA;;GJTW<*&2}u$ z&k({UrWfpHv#-CCa%MLipJ0nbdE9he^8R1?DK@WYHKe{@(#3_WMmhIS_1H~LTGBMFK-SgdOBwDW3EGxt{y!ij8?JuBY&C0tE^tbn` z<<(W~a@@z=7#J94a0wO&#E3$iFTxiH2_zvQP6QGlPVnG1Ff+)w`y7`(?NV;9?Y-|> zU8~kP{mr?v0ypya$af<{owmXRVYJ-3j zQ~`o6{y27ZKvPhamEb*p^KsV~aT51}I8jNIgo#OXsNIaSR%4d+jicY)fRa#XtRvKb}8+IF5Sv-}Tf)ai~?V?7i^PneG1Jql=T}ttQ=@ z9^Lxs&wQ)h4H9K++ZqgMeo(34|Nm^=pNWi{t+>v%-y49)00P9>$KP5jtu=_0D`%#s z{_&6B`>GqSKYZ}0m2%$u>+gO3Wo1>VNXN#O5X)X?>+^5=>E~T{-hth>-}g|W60MPz zwQ&rE0i(gVMEWgZaUUqXQ-j631wh z%Xz-%X2Li%Hc7@uCrPG=o5L$IJV{qozW?n%oBM*vX`v)a(QMK< zMZ1aCOy#hLwq1JZjjwsbEuZ-Gma(a9HkW8kqR;l;kwOj(NwNBQ{hr)dmazMgHw;|) z&<17bTl)=|sDqP1kQRgVM$ja&0d17g8XcqK4K%c+lt>#X5g?>7!XP)Or)Z^gKXu30 zCTv%(yXtwfCyqbx=o7A=ihI5K%JQ{WUWZgF4i}eBG<2YYPP^C4=dwadow6s!clrLX zWjk@F8+Ogs$?b1?-J3>z-_OQb39dfeN+b@X7$9~S0dwG}FBu@_x;^x^mW7T@ zvXQa2f7?j6*7@GI?m$%`01rx#fkn8EIEOm~z!KD<0~r|EUAi}lYI94g^YiO}`G0@^ z&U=>Xm5PdEEa7LocfI#_9zXcqdUN&I;l-@$H>1||FM0u1@cmnlDC78}saTiB$Hx;) z9LMskDf`Cu2X=6Owx01>nm%#n{>+YY@Z8|9;Na2OAJ%`%nJAadN9KUmrjJ&R=Z=($ z2hP9fmXCk@#)~h#?z$Up|EKrv+qLVJH(XC6Y}pw|(M_Qp{46UAuHAddwb$(3vvXo} ztXRkt^ZB7-zML;)(q77Q^u{Od|KC{#q2}Dd(9bNODU2~Fr9dCpzQsuwU$tEfUw@6P*Jw6UUYYzjIwWW^HItV5dtbT#>T55Gn)P(I zhtzm6B2TSCIY+C3QXD^taj{}L8Wh=-r{lud@M~W7s^?yI;a9(RchKz#gOmeDmq7r% z5K>4X&f>C51kyO3WdxW$Vu3kpQa@-c&-lBmjRhDOxMgW=Kq!q?2#GeJ2c!OtuV{p@ zY$>F494R+a5LF_iFGfa2%afxg4jvvE8(yzhZC5@0=+SOiz2VC1j-EKNWy{V;=_u%~ z)oZDg|06GXSrF9LR^}9{I6O8yHR9Wu^Ddg%fAMv%ylU6|4?mI8o%1fbA*`Ob`MgVx zE-mULs<%2LrPLq3>z8G!@zcNb?=g10-B!kwM@HMNwm@pFj1iWU29k|Ypwh}1gfy-# zSKG-%(b~Izrm@m34{IEaJq{6M2VwLQ9I#kg!nLqnhzSCsCHyJK25a#@{PU+;z22T3 z6RmETByke!b{uN0`z?fG@Jb;-8zE1xHg-&ne&x1@U-_Ch=X0a51{Ms%G}PcBtn;7^ z!yqAqQTX(+^CZGE*>t&beoPSCqx@1E6Tr~dulKGSHm6OAn_Apr*E!VlTWZN{l*cbGYIgfGv+ zrL(V1&kYhVrIb<%DK?fd2rQ76?594-jqB_|?MAYuPN!2th2nqw%?E$`r(T~A1a4$C zLgTovf7wmddixjN`@SFhwKrpWjOA%Z2sf&qSX^xvMyKEMybHhc^z6s};qP91&2=xk z@w(T&<)^OOF*Ccg8Ya3I2mN#vt&NmYJPR&wp2CYhK>>3vDUaC%Z9-sy*!XG9;8gc>?B4RbZnAXIWCrOS)PR@IGc%YFldvQJ|})-WAw%{7?c5n<}7LBK;I+#Gk7U% zVcQ!8oh2Plcqu29_WhJCE#qhoKl$im_dZ-I6iVgsp=_?b9tE9l))~6+ae*Gn7l)QYK0XklNU`u%$#A zG{SOp)IHr{WwGLlIul#)hhP;1w9leJ0fvd)_+^%kfCmx&R#329soz#>c8Ju|#}^&P zQh<~gOuv}brr&)FgJL81LmJ1C3k%C(ulvz|`XIsl029|Bgm2+4!?8iSy#Wn(fF4ba z#=UB5xgEtl<3zSpxw4ye{nx+#<$HH*J^0{#`t;mVW%a;S7dm#Z|I&+g?LGgMuYTRZ z`wm@o#U+nF{K(S>AM3`kG769u0OHKQL59=dE`*euml*stlwxoV_yA{Gwr97O5w?xv zU^^Rk8!69P0@?oz{YwhyzlMX7NozHTdsIp*MWXtbV!$oxzoVb>hl}}7eCQvq*)!wX z7NZVZhOF)5mY*kX=1lAI(XlW8(^olNrx{{tdM$T+=U92Pa`Y%2`OiQ5roa8Gzq#bX z>E~Q<-hq_&!Yi-(yWjhbPki7#6^p!LICqDeQGds72x>sv7sjbp%t5`Xc!>BfvjRk%>IADTG9@})7FP(H3(J**cRpRMS1L<2PCQCo5+r0|>H#BVN)yObd2-7~-t(*FOu=$3 zArK&pIlIyZ26}G{0&TE_Nf5|f*)B|^ietWCbljY@9Ek;>6Qh()Vy$AWl+p3V&!a)1 z1zMvAIzl1(JIx@o5DPR4RD#kb4hcGOyBkD_5sp;SyyCS#GBsXmblQ(U_E@XeE0puu z=`6mjZL3l1WYT_mXgCa`UauK+st-PL-*wNqOsV!2mtFSc6Hf?XfBB35CE}HxyC!CK zjAiy;qHV9%%_y0)D$S#fb`-VK8TW>(t`1tYV+X&Yy1ghCxne2^ljC!9Q5-K-m+S2y zjAP4^+9+wuUKm@pC5#kON+V)pRw~O+-gVd9!IM7{Bf2wE-jV>08VGNtSd*Io1GpMTqPZ@g}`a$1^rX2-scH22+q z%oC|>D!W`+KXmxP3oo1+8Y@ptk34;BISN9{mcHk>u5CM(C2?%4j}#aL!oUVF^)W>_ zjR!1g2|j)^0Zgd{;5wC=BgRRNg6b(W(F zgSm?tEX?L+$`}P&gX?;urJ=8W`pcK?9wO_IazQb>%=$8xMS9FHrGEX7fB#co`t;lW z;%{kI2_lMRr0bUQ#mQXY1hMPAdEEZ#U;9&vL-}pxT+ZLMb?4a3w!eGdyN7Z^MxW8H z4DuKB=9clPR(W)aPGdu9J)uRi)_3=+U_`SR4k3P*ho!JMd z3X+64;MkL_9;R2N6OHb?D3i;$mU{-B^k&~xgV|VT)Zv0CAZaQUs5n%%rCrC`z${x@ z{Sg*MvElci`{Elg8q=>01P03pX^hceltL#4&X{Z&t-)w9a4prui7~NCIo6Yp&-vM5 z&+%-jRL~29UcBBc4`*Ao=B{mHmtA&6&T@Bb-IGpd=9U)d#Yg8>Gr7Xt+`xx~|j?}K5z4C>ZWQHdKGo2Wzi5u09?TD1) zNn3Z?F@QiRZ4elwka4VxFkpINnDP8}yO(G+G&NLTTBWlN?ST!c2k}4=oq{Z^Lz>PU zD_sa6gStI7nJ|iaJ)KW^mMt7-T@5+cGWV?Aw}FX80wqc-~FVeZ}a=_>@e1C!e<6uYdVl zi}STi(pz1qJ^lDy#}6$&{P@wSiS+ls{;hxc_s=IrJGK=?N+}h`NgOI6h+~CeqoFsJ zWu!2U1KOyBI5KgpHkOHF2201WQHmrn7<0yR#GGqb{*1q)W*~dj+JM=74c<1mpJ840 z@4{@BH20Sl7*N7k+Srz`#z!)r{?r$?r47bLD-uPh!Nb;sUAhfcD|G9hc>f>Gudb?U zM7fBc5Vi@mRml0}k@6+`E_l^XuC1M@-}8Oe+t&2BtK;E7@7=w-T*_s#8EyLghtS$E zAQU|VR>V2c=1iEfeGX!X=`VAJ@;(T4*le=@i~;@+09bvGDA%_?^r3&)Iz4VVUG0gw z29cuG4C>Wx&_w$b3d9}ac6n&1q)ia}xEXqyUI(LDn#V6(@PZqQqvfSq`%mwF^ya_% z*Y*3pKUY1*Qk!g%^dzI((V(JlgS15G2? zMrdR^4j(x9#FbZF7VD(d?G=YdbNO^9Q0uGpM0HQi*YCRbp83_eMtePsqQdZ4(5)VP z=)u|3%Q-jqg)e@)Q*TEm8X3=Z^g_!HA6Z^Y6#w+GFU>{07wy^_h0)1c@P^mjJU%Sw zS-<}WAI-S7Mra|77Eu(c$mFxGWlKw9TeeX~*tQU0S^cUsm&^2`Ua#A3*27b46-P$R zr6!gI4%h%z8VZAO`4a2|fnQ>5gnA1av<~0>&!0*XB^}cVdvTJ)I@y@$AwfzZpsv5i6NSgO@la}ayc>qis9F_?zVAoacpGx)ua-=c#g_4gnAi@*JoKY!nQ z{^@t${<_)O>XrNAFMa)cPaHbIM$;aErh1%;##;lYU>D(j7xq)g+89A zvWTnx{ZD`Yb${^t9ABl?!As#Jv=x;uM^6>c-}#Bxzv}P5c4xg(jT$jyrA*PAmd=OX z{DNFM>qu#|Iup_?%tpg%FwcOTO;Mz09tnw2&u;TFkn|3Oy8~!CXR`DUSYcU~J?#0T zUKj1Av;W!sLlB>hwz)rWW~q$NGyaNe~o=+k$=(rbGPCe~fY0tGyWY$)fy4@J5s`YBh@q~&k@C7MP#`N0t&Sh6$ zGnt-6zsM^spq zwk)NcFjlrDT;JU>HR;(-quG^07_1Fml;eUhN@!zSwrAU&c2{U2ZP(3N(d^vX!fHO_ zFt-G4W}hOc126|Ykg!7YZfFv;pi9w%d1U%4hu2~U9ZO}5FoM2ozS4t}3TzOTu=_|M zWgIBab3qn7&oyMz0ay?YY_LwlB#hzig8&*}qaIR9u7(}k^Jm7KdgvXv)@ruB%WvNM z@T2$b+`IqcojdmLnR1;(IHXdZ6sFneTDn=UXAewGe&Lq;f=X(~bL?#4w)e1=5Etxj9|ooXEAw z75xl^2{bTx_;IShI9dKRE$QEmK)XHXdUi`vhx$OHHDf;nFM%YFQ ztMBb=gg8_FJ;Or=JvaiS->8^#^2yHrK?fp3F(6Dn^937h#Qz+yj4?)qmSy#{+o)#> zX_3)up{7?Q=LWsN9DI=4hU-Dp}s2 zzvUHw^{N;D_}_i(?SJ)GnWG1r%X2KuH>-^&l|Qog@(XhL(jWfmU#vHRm%Zxp45K4stF|!+$^%)}S(QzY>Ws&3aA9h=y; z`-%%L9t#&+BV$w5xu;8`m*vKW+jNFUM;pyV^`h!Z0z-VDfY*!d?e6%q}p!-KJ zmN4c_wv50$^CVFY5;F&_Vt<{>bm|$CWpnn7T5JM61qeHpFFo%ySKfH(3=@~CFk~W) zKZ@66Z|~T*KZ%~DyuwJ4A&?s+?ZPPe^atMe&fow1t*WtMY3&tg_XuhfO76bt;{FTX zzHRu4wffxYRc7bu^|1WXNMUMx>SKTYryFuQ*BFz8N*M;Bc;;MYSZDhipGgRNCg>P* z?&#^k%Vf}-(n<%r{-^x`Dl9C^@}zB3^@npy&rg#7M68f z_CD~Je}1yriK4^+(jbMAXTJc0{pKPZEkN|kd!zbCfoNrPjEYc!K|?=c3mjisLJsUG zg-XydQDBl#$$s^qRiFJJg%lQm(P%IVgy~0JkYFOE;^2cH{LAOO@cMmQb_!{=dYwkI z8*AbCj&z+=#y3fK{{_31AC2aRI^Ax&y43ErOnosE#*^b&H*0O1*sbe9MypFM+M3Pe zGWo*#`r+x}Tp=sNIPrx=6)Wug#xI{2yH2FE6qaL&M8#;`>7s?uNn%@W7{<%hinIhu z3yCp_mh>XE`~0g$XNHbHd}RBsYbcj-eTw@kcl~oT`&}qO9x9Y}5gY=8YGG;CPD34B zD>0U*g`H0#RHEZJ!B|4rTAwj@wFEe9a67$x#_vXWkZ}Pwq z#`S_6cM1Tj45ki}mm09(?kzKX~msZ~5M5KgX$CaT)mKe|v>$5!_3N>a@) z9DQ`*(2;LHdgRC7`b&F$=Ks9%jX(3>_aExkYC2H@FcOUcBt~xjdCv6Gg92L_lt7_l zLu^dkXM}34j81eEnj}OkBeXCE%N^hq!jcFyrXRqAiitungJz*$uuJ5C?uMgDv;tf! zOycJJ?9pS#F23fvnR2<^Xl6aDQE#rUt~to-uf2BH#Qsw!YQB?BtjNSBl`f2o4Rv}H zrb^Gd@!0#U~dS!mDU)c5w7FA(y|;QtA{4{?kvre+>!+&PT zf1$eYeP{rv7Saa?e5@=ZLofp=M&D6Ld&R7>9E5F;jg*HA`A8@B8REboG+Gmeakbv+ z25Q*%$BLfxM5d7TCx)Q{DL4)vgBqu@1lyqrdDsRH&ACZzq3!qn*&nKgvu)S*(Sl>^ z{LIwIp1r$UYt2JXpSH0Ie(H%QjxH~*K79XErx({orzY0tPS)xTjJBi@jEh!6v%Jp!yK5K*W`N@l(4Xsu7qm3MDf zae^fn45Cp=%MD(PG|C9105OO)7s9eEYY-%k24nsoQq~U=2_b+Gl(b&^ws$t#b#y@W zTew|%_Z>?HZ1(vkVonU3wZ49B*Z<7FeSwn|x^?PJ ztR4lIkqH_t+qe$W9&mXNrvSIQQwc9U#|Oz~HLK9LES(yFitq1?&a}ViWkR)Mq zwYI#p&|0f&V(H-6ASJrrg7sMl#`N=V&eYJ)kX@SouykNksx^AU0bXs~H)^g#8=)~~ z&w)@?3=@UyXeJW`jp9&|LP>g$Yh)Zpu4VQ0tG!O|GhhEEM&)ybc8~~&bYzS| z7~i&xrL{I2eXvz3jZBrsXeqE+n)~VB`A99ulyjp`9$P0!U<50Tn~P=-LqfAgWFQ3w z>);3elzq^EIa`v)?!Lmk~c63J?KJ*eAgeDwq4gmZNH?drUw41$w$ zONWl0PT5|Pm|`g}Y%i@EyLVsKOKgoafI(;@3}~Hb)$7Gc7`d+Vfj|Giwq4%?dtu?T zcD^8O0evMK5-hL;5~R==Wm&3RGHX>|Nc*SWD#2@qGUcg6OUsh3EfvPH`os^*$$FNT z5!tep8I`HB@P?#UlK!ytOPNC1&*Y^g1b{LOh=2O*%#(A26$WvZb#MwSZ9e}GAGGv! z(c+J@_9^)1Q^!71i{jV5Wi`<%<2H{kuHXGckIphHN0}I5XqdE*Q=qp@I`yv??)t@V ze2S4Vk^qrHr6FX;)_gJhi`#~$hqCzNWU|N?G30mBc-i!8Yk;<;&mu{=eLQ z_h;^S^qaGbE#1}Nc(&_XVx#laNDKO&d@wM-Fq>z5=VrnR2P(K5gF; zLJF<40U@RBW7!BxI2Kra>R=zUHf55T4aCHjmJ!PC+X09;P}-Q~xw%%O_u^OGyklzX z{ON_|>e|-Hu~a7Q*tR3wYp%Y$W$ZXs&B}Tw?n=krd;Z>CTXvqDJ$c>*7j@Pf#fj4H zUHcu6e6EP&|HEIt`-f%fG>>bWN_eIZ77yQim6R_u{uXt@UL7KV~hIc*q#8nqx zG(438H<*3Y8=k<}wCfb6Ab^wb`DW#j&wjqC!Lx+tI<74@BCnAkHb^7dn1Lu?B`Qvo z3EG_<8B;gzJAV1KrSS`(4GBC9YaCs{Y@rcS93SwoYN*G03&%e9HRqS#`RgW9rxsT< zy_HJs#8Xe6m|YHnxEqDrwoWWAt&R?7+PzpLYIH1X9RJ@xaf{Z0)=JXXqYr|jkgg}Q z*+Qn6`{|#(Y$)|nteJdXeE9FzdQr>(t{8Ym4vHk{2+?ZGD7J2Ve(~S_O{gQg|K;<` zjh1jMr4_v>(TR3_WBc~>)qAvCDqQ@ReeqAq+{?zVd_~;a zDT2olY@|R5(1Y&KJgc1eOm7GVL;}JPsqm|}-Lmtt?JK>7JMLL}=vel*-+8FoO2Rla z7+WUKf9t;WUI-;m3U?Y{7Q;aihqTUM*h`T2Q2?N4ra<)kK3gvs zFx>;FW35{$^|QbK!VGEObu)JA#L-7@{rc^t(Xki5X zoh+?%woH`cB#L7#=-R+ljAo%j1qeF2z>M z*&&nNsjHL)A6oqh&k(faj`s}Gw0s$LsE(OQ21UfOg)A_C6 zy6xxQ{`hdN~=eZa9}?|Y#pCS7lv>mx(ZiN9xhFKGtYTGy^x}3?bv$FmDi+)e9N+>5dQ-` z(|}(F=b*3~gLoEZs4+&IIe`430SgS>*fSaS4H0zFjOd7^6D+NeDN>pVvbKNe^$h38 zde|PR6z5%pS0qlb99qi+Jv@(~$MGYWkde%bf91D)J7Y{A2ZV+s(qR|{oiGlQeuFEd zupD8z!f}OV3t@{5mGhbGFKq^5&5f%cJ*dqf>Upz&;((r}<5(wAU#Vm0v-^~eL!ESW z5^5C~5==j>Cr0<>)Igu&3>Ly9ChA231aw!UZYNe6toT3v;V&P2{Laeq+K;^I1?_eX zq%qFo;(E6iAK1U|vWqUR)!ShhX3~Whzw+hU)W3JfZEHc$Xtp1C{J!g+|NOPpwNs~N ztJS9C;rkp)?|AfNbvoxBf8dTt$E-Y7ApF<|-ik4;Ue5yCvUQ(yBBj()N^L+omhby- ze&t&nX+3%5sONbvdENyVJm`r!FDyKsZQv$C+yf27ut`+jphdqwVwsiDhv#1mw% z*)jIwY41YMo=AdxSET~~%4z?y$+72LV&`{e_I_yWvJa<+FSk-9FYWR__>B|;I&MzN z*GjQf0;1Im*DFD#sw!38>?m!{{IEKSwevtsKgjUf)v(hc}QyYU!VWiFo|s6 z|C9H;Z*oWt<+D+56{}gFt^CAK|Hk5SGtr3>q&)Yvm+y?*L9Mw+a15gI?&pAkB2g6- z#4tf={lETmraV$Mnoh5)bRsQbNdT*l=Fm5Q4U?$XOY#}9nuuTg<=2&VObvKmEePRn zzW>!A9GZx_fDcWO;NgR%@B6g5`Jx|(A)4W2Y3uaNn|+(-y*5769@Lk{0s04}9n!c5Ll{4KCc5PTyqP=MLlRFC(xW zIXs#B%YXPkl=6^*=h{Zv7MYyL4~s1?7}@{U*XM5jh`sd%mXqFl9{C}x9JXbtw7dO= zsoa&j)L6+XSh=#5pYd~($a2w{-f8W+q>l>{%a z>^EAXe*kV^a2ELti$Ot{*o*DA5G5==jIz-It8>H-mLl!5bq9NQ6Rr|=>D6g1a`FiH zh0**z*U9g_7-CM(Qmt9SzG-U4svhOoB5h4J`{Qr?ao_g_FVs0eYA{lM#>0*EEOs%Q zhk2X5A;b?~VWEZel8~VZ(6kzi?MFzu7M&KSj*ZN0uPjzkhLt)>flH|nv;&GmxCOTE zXKa|3qBI0P^*TYXG*S?jDC7$xrID$Tk&)7{CvBbRI95rl^#)+6#OTE6n2j~CVHotd zt|!xJCzE!I!>RI?^w4BBKkWE<%SmsLKL^Ko0%2J)?aN%&9vR6^Z7WYqmxo64+5EUFcRpiulpH=Xl0C&ttk5NKYsM)n_pKdjvhGw zf<1e-?B6#XgzEBZuUEp$q=rU@#{XZUdGtiB7w71fNp=(`zWbm5`HpPHLrBMF$JCT#*;<=K z_v=Nmw$|wNf?h8~n?L)&A78ZFAD!A=PN&>$Tjzi^L4ej2rekt3gAu*;_P?8M5$P7HLJZCt#q#!$Dz?0+d?61OJvdxO8dS)UMhO7 zYILH%dhbvF*ejohm4+OQLJ3x>_6|K}CWkL^_g@2f7zYPBU^+d0-7E5WKTpsgQAo?N zMPb-&E-asa-qdHl^xxTG`_#eHQt4i|=SfpS2%83z_|$)LS*32o$RMm*$+u;R62EqW^h@X@nT??)$IjudD|ZxS${p& z36>wD4HsR__T5bG!t$wg8JgJmm2_}jFqF2^s1+UgCpTYDa}7I3 z($J}6rv$MlXTcNOs5ACVMxX^J<=)fqaXg4dvE#D zZ6E&ouYc(MZ@lu7iPBIZmvwDh0)1NrwXrrrQ+b9Mz!>5r30h%T591&b;5fqeh2vX} zXE~15cgsQwVcWKCX)Tq~wh)f(3Wa3}%N4d`S)Og#(y}B%7%=_bQuT3jV`-z6R+uy9 zw5BgNLv4I}{b8z7suOgcTwjilp2*wzq@#` zQF7;#N8=>Pde-~??!O+m|B z9)EnSUZ<51<@`kPox3}tkk_$HXZ(B~wb~I-UBV5?rnvCxk?_b$I-8AKJ(-S@NW^Mb zq;{kye^F*{7FI!8zK~)tsqQ<2P=wcb>6^pu#Ytl2a_Ll7T8J}e+H&&&`GEPXl4`5* zt}iS%XUAwH)m;Z$Iw?@BE##ml`Ox&r()$PASqLPnp5?+0aLvDaYRMMi5-$U*0b7^s!BRtZL%BvRe57k0xa={HgciL`{}Nx9J{4rucjjS+nUDrnPp z=GuTi1OxSkIm4#t5C64Fjy!bVb#H#NG^X8S_T=H=;i-kC#S1Rj-HF(~ZTh7ze8JJD z56&-FQW^SM|-!>CQY9oh283T?zHa`4EfAEf1KJTLCCm$T& zw%yw?4&OidBRh6q=QS7XkrAv>aKHr% ze7Mxkt^M?CCU1IS?XzF#c0-d-`C*(GDJ+C-+hgO!Bo2GMq#dejuD|AQ{`TG5_Y|lc zCY^&kOu#C5*ii~BS@)-|fq|1svWC8U{^+4kd_(-y&%PsFObOXsSeUmhqqO+UXTO@x zctmRZ*3!Yli$Y7svWK^qFL=&#zx0(mKlrC_A0EGUB)#yNFE4aD2^b-T)W)@CaoGFp ze_oXzEx=uH37mvOUMKk0H=^~HrOyRgQi$TP^%sBPZrd+GKn7mDJU{Z8FW)=y@*#8J z!@Xd;$cLUvyJI9Kncs@xJo#pge$M#L{_)@G~ z=?fbZRGKE2j#T0mu8?}~(AWh!d@7E6fRLh)7CFV2to)Bid~GlS%)?TBE(k*CI~dy* zT0bLT3xp6_Q$IcXoNd?2Cmzh-^h#15y2H^UjBTf!!uL6Rf=3>tG=&l93fg0I!X6nT zmnLZ9ION7@)Tl%(JjD2J3L{tv?P}0ze)5*@^@8wB74$#Mh&Y$tXmbT-HhVyyDYSn0 zsCr1EUWas!T95TQy*iC~4n9G*Njgm`;n3Y2d4%J~kdl=;!ow{SG)WTtJgs#)U80zF zgD4q8!9La zSQf62mlaM*+K$x9sEuX%ykQH0Fw!JSMR6SWR2->(-PCV6`#m5+*tT?h%l2){mRJZO z{hVDI_wysJux(-J7hHp$aj-U?K^uh7N;R9czyE`G4o{A~>CLY`@4^d`u>1TQZj7R6 zb>XCK+mAhcs8(;6^F`ZA@7O*vR2qHs@k6E3NIF}({GtmJ6)RN%pjaHcq}xp*N4Au8 z!HqW_ed-~$Uqfe%HBs2|$-8d$r+ z9;6l|;6ex)f}1Jjc3pDyC;uTkHAX7XikyycojSBg^0Y=68=DKPj*dT)fp1 z;+m^2YDG=ow(_}DLei;p4nF*yIF3`^$KX%NMW6cM&hk*&wk+R9*kYud`P9dMdumq$ z{t6;E1s;qs=Ka;5?aCHiTVrjeG8%*9m{+`%=RIc&7_i|6_|i}P+&^Fai^bIB1rxjX zXSeT=LB_K38rB`I+2@A~!99<57CX!xsT9XD_DpH<{@K-Is`}L0Pze>%J=RQm1xjV1 zTQV*4S5KsdQz;9-Sae3p#RJdD?z-9Xw~XFCuX13mluDAY>`uMmmAENdRkX(y*RXb&Mio4EPGQ-MZ^dz$U1fADLb7%mqwsQc zy3|6tA--VheCiFHGEeVSJ}Cj^$PVR9(aIGgX$sTMd%?Do;pqdW+R)kw!-i@g*;IU)x&6d0Vy|^ zcK+hu?{A~X4UzJhD6q7G=T8ldf9bE@|HjKM_8iM-FavA$a|r>Y6pkkxS2(V;ZQFA# z*R`ZAw4&c5NP&=GVT|dM-VO9!KsI9^eF($!F-}ONNp##*GVP>FsZ35dS<6dVt}n3# zqTd(xQBNz?$5pc-mDROI;{$*6d+m1g+Sk4gTi2+WTLR19=C;${{3|+Xx_gu$stKtLTD5UkaEiyb+>CD-ayKur#hPi*ye?cB4rellz}cke3Q^U#yCr(3-w z-m)`${dIdq7`2brOk!wW4n3?(CN3`i*T4NrF6)j?_uCT3eN+Lh0f?$!xd#WJSe2%9vg_ ze*TCvQ)*U3Zs)s-sp61jjcf7umOG&oCdPBYK(egV8g8P`h!$0>flcEi0fW8c$(hTq z;qsfYV@@q{VvZgJ2@8v~n=H-p;v3nyllCHoEPjrH$Iji%Op;E~SfLx^Wl0o%78|6d zJWM*3ifcwB7|o{Z+=R$8Mu~$Q8OIjVVl$-_ZJ*L|?$ zq#?!0gJjEed$`HO&i%jkGjG53@H-c4l^}^W1wXPWC=FryW|B&S(nttkP zW@&aIpP!jus4gzox^YxYiPCUkexbf|YS{O^Cr&Mw#z!+-7C^upBs=yzSxC93SAulL zy!!)XtOsBMELZ^pQ}BHF59J-Q39vv4j1dY9wh{Tf$mRXfu_4$EkAmt{&D(zY*3p++ zt;O9Hqr!Sa0Fpp$zh*pFP-&xARH!<3!GHKzGnLPDdND!0_e5yz8LKP=cFA{A8J)&* zsuE98F+nf(XNc z5S3ikbQ6*e^e>~HtrZhm$)Rq8wR!3-Mn~~rZI0m_jRuP+s5TjLs7APBbk|rsOlKW0 z$9jhylen{lM;Sjr1D1}{ILzuiAwaSWjKtDJn4<&(@liVG7{$QJEYdJ(ONwC#%!D@9PHXvj)L zOwW+=*l{`8QMw^s3KI^w>FbAwf9Jg)XjW?YB}k)O>J3sQg2u#6*M8-re}CcBgk#GA ztPFVPgQYQAqg0>giB>uZRNT`lG)fr+4A5yH>N4gTa&t6i@N3ii2w_Xhv6M8C(NT<2 zCJs#;qoOkhvbMKjJu)x>?2DpJBHG>Fw?6xi+P3$cf5lsW@-3;9f6dj;lW~-ElHD^~ zn)Tk&vDt0gcUC&p>UwK>V#0BfX0tgyz8!**kwUAb9N+u7-+Ws(pD7Myc3gc`XZ@HJ zKq`k-fFczIV+7a1l2sZmk8Euw?PjfOZQV~DbY*R6h0;bOD$7Tne6$@Ux@R0m+ES)n zFPAM$jAqjrw;hFXoQSk-!}#8vs}DUw6oP;NvS1(v1B#TruyhJ`z>RR@uJeC%X3viD z$hN7eS8Uty+8yV=l^_cOY@9snRf6uow+~p_*k6)4a6z`*T{(4s=hSzg37u|mQU~2a zKK=Xe{JoK~=Xlw*){?Z-U;O%~j~qGp(%0OuZO^C*MLSYSFEO??x8A6AyGU!t^Y`a7 z0c?R}0}YS;+sEHKI-DsM^_4r@aA8z=8g|1BYyls>1YI{>E#(nLmP`fGqfNT{Z*NYNeEVW6+4x;{~T|w*u8Zx{{vA3$1#yt7^I9)Ymh)o?~H? zZE6lPT2lP(|A!sA3n4S<)Q`XV=3;i7xK6WypJmq$_KYw; zPq)XG3z&PHE$6egLN8=&oRbR>QW(Wp*e-oCM6bu*X(Epxz}0rXv~&NZpZM~B@87k% z;E2@FFuhrnMaD-5v~_NB_<0vz@#XJ+zuD~|h0wwXfjQ$_j~1dIe99m<5YPjcJ#8dn zkOzR#^y$s#@^HpCrTsq9e3XG z+~?kW`0&%+C|Wpr#FeS_mE|k1xw=-ZZQs3PYHCXq^YWM8xV*gL*?u<&^4Uzg+v)_p zLa}h{$dOABhAg2c}eH%OOJ0@;F&7uLdh)zeL~ z&84Rwo4Mp7YAs@mRMq8)|M=93P(+E`HZ?3#*6;uEZ@%cp`AaYP@q6yR-%ndXR|v}= z9ZA3bjj#4bXCMFpJ~*fvatlQG>AaPSs!LWzV^&BUXk%RDDyoMJur2CK_!&e%A&&@< zIVgdEBEdJXQ}B>m9?hoGLFjwM^PuJP`214vsn6(}Z+vxn(kjYatn8j@b=w_?tLwFy zncYVZ9x09a(k10^;rUxTt@>J}`@Y|J`ILVLDI03A2JL+Dski=2@uz;OlFmukW~GXM@3{N#*5YEinDFl^`(07yDw`#xyR^-!{#@_&TiWTitSoQVSEzH zDir^$-E0bCuo(QOzL^a{pMEHW6e8oK{_0QPyJOoh*&?+DO3|ESbqOPQ?0zP8leXEu zg?7UF0y{3jc4;n=9bq(!RU&0^=pm*i5ivt09(;tHz|vGXws{pD}{+WS8G#Si@I8@%27{i8MO>OH80 zRDqxa{>+XopZm-A-}v*t-tIOS7;~RJ(9)`pIR=4XppPCn?J0pYY*-`@I^)f9X(Rw* z@W2?2#t4+5kAKocp^_RD(lRPRIzlIC0}7# zTYv6nvW3Fv)z^LRmTx})1vlRR&_n0%*|XNFtgg*od-XNdN_*%2T_fW=)Z($RiIKuk zsS{Yo4?VgtJCDn2e&o{p%moDZxh+j0ckJ}B%IUe{#L(D|QT!|zwOY3(ij{|+Dvyp< z7v}H!;)6T)+Iy~jAyo~F=m3rtOAA9o-IWkGlk4dE-~Yq=cJIh1ji^%pwv!EfK?mE& z~~K&)Gjwg>5hb^TE<{KmE0 z1S?CiR=tx8Tl1W{<%^xQdrZ<0aV$k_8%qgoyprpU#MO)JEiX!}Q731RVbF?Mw2|?t zxtbP4i#45g{gm_haPg9;d#&rOXjOOo9Wuu9zT9jyg_v;tw&Qi9o+}2DN3d*LMakJ| z_k9F&r0r(XyY_B@3?`)8AycHQS*tNoVtN}#A7RTD77if{dhgDe+hHP(a?=a+7!nKLxytn zYIr`00~XDWzi<0^*bIVdvzff^9l!dKU;f3J<_Z(Lh+>SOmoSzZY3=;zpTF;|@A$1S zO8UO5Y)*7kN+{Kj4Fmy702r+WD1$L3k$t-lGy;q?0~i+QK~Xj6zy-np*1#%1RvNis z?;uE|bkWI~@mXKfYJ?G5*p4ME<47w>8>59ZQUyASlGWu?ANt$Bec@GC-tfHV*`8cm zSQ{T7k}3c4-B*{MZ3pY zyXEjb55>yPLM^kpM!rmYjj<96ENftk+#L|j9XKBr0nluH z46c9{y<{WPN$Vkr;{XDnQb-et+|EObSkxH_x5(9a_M;&TiwO0 z4(#~Gy${LgKjEk0E|`Ve;ZDfG2jMNS0RMzCSleJ39)%1vpbb3=S!tWZNk1nDmQ41W zIWKVK+kfRY#+-lo_Fr(==7OJ^AN_~gnz&$kq>+8QFAL5E&hoMytyoiggX51MR}Vhb zJN6kGCr zX@~R9!_DJJ!Y+1h1M;(kG1)Y6L@tY48q(1XS6%drfA#M&;Q2eIMr}>01OiKwPEpMJ zE_3VkFMjoFDp3YKP)15)Hjd;5cZ}GueG$;t2MWOe_Jz?JGe`(P_D5g>efI0!{|ulF z0+cauCdk|LbzK`_(-Nc4)VhPuBXs|Jz!)VE7!bBV2(1k&$!>klsNXz%bUrm!9L|qd zEA?z9C0+mEk>f9W$qk1OJ#BlQj)LXZ+B<&fSHJkBFaO~mz5lm=^(QX6WEgL_{^0k# znVIeTcNKH~>C>Euh})pk-of7`K#?k?mDUdBoitT;Gz;%IJYYG^DMhrZ+L`rOm5 zla|HHU=6-h9P+(n4X*_kz~sjLII<@TpLxRz_f75eGa0Z(z=iezvn^AR#Q<*0-Lfj-|!K+s%SUtT$GgmvdV4_lZUU+~ zjAmMzecW@2U2&Ug!Qyc6+B0C)t#VUDfOochY0!B%6&^PK{qV zedO?0U({Rc3OO#tI7waW-G27d+WY;m(QrIV8zF=(B|=z2YJp`;qz!;US{RK4+qa8; z_Q!wv$ENq}q8DMs)Yh4t;n@AeG4(aPVai#0b?Q}&#CB;NBs+m=QLm93qOnG9f@&3^ z(Ce&*WQI9>3u1`&8riU@(zo4r?|dsX21LKzd4_E5+z&R9M8z|G{p98ZXc(Ah{7^G2 zj8Tz!=?mDsSh#PTXiA`PeJId31uZS2^=%q|uy1QntbcA8?E z^e`(=kR8L4Sb};R&yY|IyRW#th77 z7DQLA$D;m1zD?1syNR-9PD?p+5C&mP?|v+dGLE(*J?ojZ4T z+tseIzWOhJ`_$2;fBKvEU9vAfHCCp#51( zxUdEG!cC-hX8Z$Km%}LdeYB$9z&8-nw+zLFbx81YkOLcU3?%6^*rY6E9$I83KtKa8 z4MQLx3&YTW5@=9Rg~wp;#^&zd{v&x{`%mr|&v(LQ-O+w7)96%`a;GMW4?O(ji9;uy z?CQx=>(Xy!N2ZI#@u*uld~)GUZ^&me1!zEd09&0w8Rf&m#^x+}^O?f7auc)|BJTU){_XS(8-FbN1Q*)19vHil=Egs6NVWu;SwTHi5 z{lt5=SD$=olB zgYDaP%HK#Yb3JJ}{Rl;+v;nOYLKZ!LXy(G7dHGd2KZRBxX*F1EkW@ELc#ktPLu4^j zLJ9H~B1<(UnY!wn7Jbb`yWL2lgd$)MUUL|jmute)7;#lTsA+kW9s1H+wF-RnT(Xj zHF%ZNvt@e(dk?PLeDqc;HknH=Bv{42fKCQ0!XH2kEda(~jbJ5OoOO#AfDJxDhvh?z zkKlWt2F2HDf(}uKe7|#4P=p9N8ygFjUHrPmE&s|O#%sI)2bC%DTlD(P3yDw;RMg%X#;^-&2XYl}ZaC*6OXi;|kyTyWe^1 zL~(>7oTzTlgHr4)@U7GIT&yyoM;4rzVveR}EK7ThT!v#u**!xf5iJ6RRU}?V6qr3m zW{7+5U~-Dw5Ti33Fr&eed&l8G3GoaIK7$bhSF|&vP`zoowTaVU&N09;&q$3nKX8R5 z0HL)uLS9}P%eLooGt(@t(CbjzgYM9^7@1(tg~%athPf4T7LlY|C0(GiLJu-I){asx zklli6VkA}!K5>u9DX-l{WG*eH#xLBDpC>m>dzJMyQW?^6cCPY|pZQ#nM3L4QVPX@- ziBho{nWwgT)bI&=i|Z0YU>TIy;M2h)uC*0~VYXz`$n{ z1nA9;dmrYsU=TiMNr6BqrBH_+zT<%hpLoFyH=R0lELF&6ZP(AFOwx0*e!)xT)*9cr z^_JJY@T#@hgToWsPCoLLy_dc;ikhNj*W&ichaTB}V4vq^viVj)7JEAGtk*0%7dK|z zp^|5qTU?#qzURd8M~gETtQ~q_bjJlzyIE`20+m=vQ<;jZ6L04pHIjhmAC~*-Awv3t=PVHI2Hb%O0pxb!r<1wod4=ae#UO&ps$u-sIPR5}{Bq}{SAR-muZxr1g)i7wsiP~+ z%mq7oCxYy*?JFy*cc#ai^;5UF#g(Xa#g5(o`Uk&r^{%1vmR-eip)fU6933k9{z%rI zbkytK_{N`j*^6HE!W&-x!kZROADLTQ8A*@5`E{=>j}>s`Myn2%q0yw1P&2r;XP#A%W1iVHZbqyh-cjaR0Ly>`V??5#URr+j%`Y!@E98e59irJ{W*p0*I7DWc zcq3lWP9uG!AXZ30I?wPB)e41CygW&O=MpCPSxiKfAO$7{7h%zC&}m~yf(|L4;R3NY zzdZNPpZQ!*$5LsdiM7)GKC3^NqVH0mjnD`L2x*KQAo@V1c@BHD0k9iDBE^6ku{myO z@BtVzP-GghIcRRvc?San%K^fPL8XQ*CANrqoolbVeqv~5ap|NKc5W!2&iLhwb!y#h z9ev>Iw|wu0{c@!2l_w{I#9BUju(rN3vSq8I>atWcotE*6>9Ji=uUW4);~>nB=K8#< zuvarOYOF0~hsx_Ka~EI!Jj>*JdNJ!}l1?ObN}ER7^^j6kXXW^Q+7(42i{n(5kTq-{ z0+3+g0=3TU5w|!+v`S-^lt-gYa0=grkc?#UNgPRBrLjcDL-jBM=}}$7?;;s!dKl2S z?7>{DJD4jqK*A01Nw@vfAAID|mtA|ao%V?uA~Ef#H8*!yTc**hJaPZ2v60mD$k3L3 zGh6pu>?ehXAA9t-{&4uhoi-#OAc7pE2Eq3Z00u&M3p@o4cq<%+97JG4FQerbZi^O- z^BgUtNa9GuBo4-xw1oe;F!6WC%c<8`_U;kusS{uR^Svg1lb_7Q zOH^JZD~aia$xlVe>m-TRmR6m1t6?Q&a9w9n*t>P|ZLL~X*iAA@jkMO4YS$cB#j6eN zr_HL7{)n!voOHrW#-1(}KlFdze!;$JJdf?8RGYXS-7Z5Jludcmt~K1Dl4HB0(__20 zZ~M%rzy7h0{pBu4dXq(*6wL+_!VoJ>RHHo1sZ|cHaLEOX4AGVhjj?=!xQCap`x;V$ zT!D#c1eAuTwut41`=+6O49XjsSQUCytEazuaG}*pOkV`Zvt8nx@*432f|U8eXIOHh zEJ?KX9dpBrZ<^e8Kn`Va3Zx7wi{~)B0~)kL+!VqPDuNcigYRQyNGukPVnefo;}U`; zY1T0U*Chz?(g0C}Na2K(cW$t6eX!}aUiY?NZAMz@5Ydmu)B<$hAi-eHM7^T5(Px@t zF=)}wluu$~NhvK$IL^i-QwnJf>?g&U#`

Olg^*$(=M|2KNbY))G{W6O-}e=4Ij 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 Eg0zsgvH$=8 diff --git a/crawl-ref/source/dat/tiles/title_pooryurik_knight.png b/crawl-ref/source/dat/tiles/title_pooryurik_knight.png index b3b7a214fb9fc406c4d2afc56feb815bb509239f..51b6e996cb258d2d01e5c4cb453531e1c31ca1b7 100644 GIT binary patch literal 26878 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 literal 31308 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 Njm2^Em!>{3{|96>s2>0T diff --git a/crawl-ref/source/dat/tiles/title_psiweapon_kiku.png b/crawl-ref/source/dat/tiles/title_psiweapon_kiku.png index 24be7c2f411931a34f6c05af48bea7cbc9d6e6fa..1d1745417e04efc923760f0061d3639fe6e1d446 100644 GIT binary patch literal 219095 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⋙ZV*t~>nr7X<06Ukz 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 literal 24008 zcmYJZ1yoes_dh&CH^b0945Oe3h#=jJfQkqrAgxG>fVA|`7nD*;njs}cx)nxIdH_K> zq`N!*m*@L?*SlD(nS0K;`|Q2X&d-@}Elo9Q3N{J|1VVjZ9sL9XfyRRWpU6nS5p`!O zY4C%{TIrDz1X3PNdG>-Bd`7%ffAR| z)Ou}MaDvqJ{-b-OvxLNy0*E~Of_LB$iTOh{H01K?FS9BCBLrgHbsw$t^zG<+8fg;4 zkD&D9vDiHkfM2#9!7-{E{NXSX^mkf zQqm#_L<^^}am-E`4yd9aWZ+1k8m}e-%kqE|B-cSmw{4ZcgdF7 Wc@;Dy3oP)NQ< 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

mN{cRFdgrmJai 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 XI65#eQRo1s00000NkvXXu0mjfjyO1U diff --git a/crawl-ref/source/dat/tiles/title_white_noise_entering_the_dungeon.png b/crawl-ref/source/dat/tiles/title_white_noise_entering_the_dungeon.png index 93efdad0f24904a9aceb62143a8c49d45fdf78fe..d606d6ec07d86dff228338e3fa3592c40b964e01 100644 GIT binary patch literal 73306 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 QdH?_b07*qoM6N<$f~($uUH||9 literal 82202 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

    "); $.each(book.spells, function (i, spell) { var $item = $("
  1. "); From 61eb7a8b7595143948ba07e89ac608782e24df68 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sun, 18 Aug 2019 21:09:28 +0800 Subject: [PATCH 543/864] Fix newline at end of message log --- crawl-ref/source/message.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/message.cc b/crawl-ref/source/message.cc index 66a6f426fd93..a150415b1961 100644 --- a/crawl-ref/source/message.cc +++ b/crawl-ref/source/message.cc @@ -2176,7 +2176,7 @@ static void _replay_messages_core(formatted_scroller &hist) } } - hist.add_formatted_string(lines, !lines.empty()); + hist.add_formatted_string(lines); hist.show(); } From 070f72b007c478799c7b6210fd4ce8416dc5f516 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sun, 18 Aug 2019 23:12:08 +0800 Subject: [PATCH 544/864] Speed up level traversal by 33% The Wang tile generator in domino.h is unfortunately pretty slow. It's also not necessary on levels outside the crypt, which don't use wang tiles, so defaulting to random tile indices in this case is a simple fix. Improves (not-into-crypt) level traversal speed by around a third. --- crawl-ref/source/tileview.cc | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/tileview.cc b/crawl-ref/source/tileview.cc index 1583615ce9b2..946346053a61 100644 --- a/crawl-ref/source/tileview.cc +++ b/crawl-ref/source/tileview.cc @@ -313,12 +313,21 @@ void tile_clear_flavour() void tile_init_flavour() { vector output; + output.reserve(X_WIDTH * Y_WIDTH); { - domino::DominoSet dominoes(domino::cohen_set, 8); uint64_t seed[] = { static_cast(you.where_are_you ^ you.game_seed), static_cast(you.depth) }; PcgRNG rng(seed, ARRAYSZ(seed)); - dominoes.Generate(X_WIDTH, Y_WIDTH, output, rng); + if (you.where_are_you == BRANCH_CRYPT) + { + domino::DominoSet dominoes(domino::cohen_set, 8); + dominoes.Generate(X_WIDTH, Y_WIDTH, output, rng); + } + else + { + for (auto &o : output) + o = rng(); + } } for (rectangle_iterator ri(0); ri; ++ri) { From 0c8b59c11852779ec219904b830e58828822f0d4 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 19 Aug 2019 00:26:00 +0800 Subject: [PATCH 545/864] Revert "Speed up level traversal by 33%" This reverts commit 070f72b007c478799c7b6210fd4ce8416dc5f516. --- crawl-ref/source/tileview.cc | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/crawl-ref/source/tileview.cc b/crawl-ref/source/tileview.cc index 946346053a61..1583615ce9b2 100644 --- a/crawl-ref/source/tileview.cc +++ b/crawl-ref/source/tileview.cc @@ -313,21 +313,12 @@ void tile_clear_flavour() void tile_init_flavour() { vector output; - output.reserve(X_WIDTH * Y_WIDTH); { + domino::DominoSet dominoes(domino::cohen_set, 8); uint64_t seed[] = { static_cast(you.where_are_you ^ you.game_seed), static_cast(you.depth) }; PcgRNG rng(seed, ARRAYSZ(seed)); - if (you.where_are_you == BRANCH_CRYPT) - { - domino::DominoSet dominoes(domino::cohen_set, 8); - dominoes.Generate(X_WIDTH, Y_WIDTH, output, rng); - } - else - { - for (auto &o : output) - o = rng(); - } + dominoes.Generate(X_WIDTH, Y_WIDTH, output, rng); } for (rectangle_iterator ri(0); ri; ++ri) { From 45f0056d81b7728871642d49297b814b5ce96714 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sun, 18 Aug 2019 23:12:08 +0800 Subject: [PATCH 546/864] Speed up level traversal by 33% The Wang tile generator in domino.h is unfortunately pretty slow. It's also not necessary on levels outside the crypt, which don't use wang tiles, so defaulting to random tile indices in this case is a simple fix. Improves (not-into-crypt) level traversal speed by around a third. --- crawl-ref/source/tileview.cc | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/tileview.cc b/crawl-ref/source/tileview.cc index 1583615ce9b2..b63569f471a5 100644 --- a/crawl-ref/source/tileview.cc +++ b/crawl-ref/source/tileview.cc @@ -314,11 +314,21 @@ void tile_init_flavour() { vector output; { - domino::DominoSet dominoes(domino::cohen_set, 8); uint64_t seed[] = { static_cast(you.where_are_you ^ you.game_seed), static_cast(you.depth) }; PcgRNG rng(seed, ARRAYSZ(seed)); - dominoes.Generate(X_WIDTH, Y_WIDTH, output, rng); + if (you.where_are_you == BRANCH_CRYPT) + { + output.reserve(X_WIDTH * Y_WIDTH); + domino::DominoSet dominoes(domino::cohen_set, 8); + dominoes.Generate(X_WIDTH, Y_WIDTH, output, rng); + } + else + { + output.resize(X_WIDTH * Y_WIDTH); + for (auto &o : output) + o = rng(); + } } for (rectangle_iterator ri(0); ri; ++ri) { From 11bec3899533c70ac5720a1c0b55dd6677ef545b Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 22 Apr 2019 22:02:51 -0400 Subject: [PATCH 547/864] Initial implementation for incremental pregeneration This accomplishes the main mechanics, but doesn't solve most of the hard seeding problems. After this commit, the dungeon always generates in a stable order for non-pregen games; if you skip levels relative to the defined order it will catch up. --- crawl-ref/source/files.cc | 148 ++++++++++++++++++++++++++++++++++-- crawl-ref/source/files.h | 1 + crawl-ref/source/startup.cc | 81 +------------------- 3 files changed, 143 insertions(+), 87 deletions(-) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index cfdd358cab64..6a701a6c3a90 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -83,6 +83,7 @@ #include "tileview.h" #include "tiles-build-specific.h" #include "timed-effects.h" +#include "ui.h" #include "unwind.h" #include "version.h" #include "view.h" @@ -1432,6 +1433,143 @@ bool generate_level(const level_id &l) return true; } +// bel's original proposal generated D to lair depth, then lair, then D +// to orc depth, then orc, then the rest of D. I have simplified this to +// just generate whole branches at a time -- I am not sure how much real +// impact this has. One idea might be to shuffle this slightly based on +// the seed. +// TODO: probably need to do portal vaults too? +// Should this use something like logical_branch_order? +static const vector branch_generation_order = +{ + BRANCH_DUNGEON, + BRANCH_TEMPLE, + BRANCH_LAIR, + BRANCH_ORC, + BRANCH_SPIDER, + BRANCH_SNAKE, + BRANCH_SHOALS, + BRANCH_SWAMP, + BRANCH_VAULTS, + BRANCH_CRYPT, + BRANCH_DEPTHS, + BRANCH_VESTIBULE, + BRANCH_ELF, + BRANCH_ZOT, + BRANCH_SLIME, + BRANCH_TOMB, + BRANCH_TARTARUS, + BRANCH_COCYTUS, + BRANCH_DIS, + BRANCH_GEHENNA, + NUM_BRANCHES, +}; + +static bool _branch_pregenerates(branch_type b) +{ + return count(branch_generation_order.begin(), + branch_generation_order.end(), b) > 0; +} + +/** +* Generate dungeon branches in a stable order until the level `stopping_point` +* is found; `stopping_point` will be generated if it doesn't already exist. If +* it does exist, the function is a noop. +* +* If `stopping_point` is not in the generation order, it will be generated on +* its own. +* +* To generate all generatable levels, pass a level_id with NUM_BRANCHES as the +* branch. +*/ +bool pregen_dungeon(const level_id &stopping_point) +{ + if (stopping_point.is_valid()) + { + if (you.save->has_chunk(stopping_point.describe())) + return false; + + if (!_branch_pregenerates(stopping_point.branch)) + return generate_level(stopping_point); + } + + vector to_generate; + bool at_end = false; + for (auto br : branch_generation_order) + { + // TODO: why is dungeon invalid? it's not set up properly in + // `initialise_branch_depths` for some reason. The vestibule is invalid + // because its depth isn't set until the player actually enters a portal. + if (br < NUM_BRANCHES && + (brentry[br].is_valid() + || br == BRANCH_DUNGEON || br == BRANCH_VESTIBULE)) + { + for (int i = 1; i <= branches[br].numlevels; i++) + { + level_id new_level = level_id(br, i); + if (you.save->has_chunk(new_level.describe())) + continue; + + to_generate.push_back(new_level); + + if (br == stopping_point.branch + && (i == stopping_point.depth + || i == branches[br].numlevels)) + { + at_end = true; + break; + } + } + } + if (at_end) + break; + } + + if (to_generate.size() == 0) + return false; + else if (to_generate.size() == 1) + return generate_level(to_generate[0]); // no popup for this case + else + { + // be sure that AK start doesn't interfere with the builder + unwind_var chapter(you.chapter, CHAPTER_ORB_HUNTING); + + ui::progress_popup progress("Generating dungeon...\n\n", 35); + progress.advance_progress(); + + // in normal usage if we get to here, something will generate. But it + // is possible to call this in a way that doesn't lead to generation. + bool generated = false; + + for (const level_id &new_level : to_generate) + { + string status = "\nbuilding "; + + switch (new_level.branch) + { + case BRANCH_SPIDER: + case BRANCH_SNAKE: + status += "a lair branch"; + break; + case BRANCH_SHOALS: + case BRANCH_SWAMP: + status += "another lair branch"; + break; + default: + status += branches[new_level.branch].longname; + break; + } + progress.set_status_text(status); + dprf("Pregenerating %s:%d", + branches[new_level.branch].abbrevname, new_level.depth); + progress.advance_progress(); + generated = generate_level(new_level) || generated; + } + + return generated; + } +} + /** * Load the current level. * @@ -1527,14 +1665,10 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, you.chapter = CHAPTER_ORB_HUNTING; } - // GENERATE new level when the file can't be opened: - if (!you.save->has_chunk(level_name)) - { - ASSERT(load_mode != LOAD_VISITOR); - generate_level(level_id::current()); - } - else + // GENERATE new level(s) when the file can't be opened: + if (!pregen_dungeon(level_id::current())) { + ASSERT(you.save->has_chunk(level_name)); dprf("Loading old level '%s'.", level_name.c_str()); _restore_tagged_chunk(you.save, level_name, TAG_LEVEL, "Level file is invalid."); _redraw_all(); // TODO why is there a redraw call here? diff --git a/crawl-ref/source/files.h b/crawl-ref/source/files.h index f7f184d544e0..e64ecd62459f 100644 --- a/crawl-ref/source/files.h +++ b/crawl-ref/source/files.h @@ -82,6 +82,7 @@ class level_id; void trackers_init_new_level(bool transit); bool generate_level(const level_id &l); +bool pregen_dungeon(const level_id &stopping_point); bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, const level_id& old_level); void delete_level(const level_id &level); diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index 474b3b3278de..b139f34f152f 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -237,85 +237,6 @@ static void _zap_los_monsters(bool items_also) } } -static void _pregen_levels(const branch_type branch, progress_popup &progress) -{ - for (int i = 1; i <= branches[branch].numlevels; i++) - { - level_id new_level = level_id(branch, i); - dprf("Pregenerating %s:%d", branches[new_level.branch].abbrevname, - new_level.depth); - progress.advance_progress(); - generate_level(new_level); - } -} - -static void _pregen_dungeon() -{ - // be sure that AK start doesn't interfere with the builder - unwind_var chapter(you.chapter, CHAPTER_ORB_HUNTING); - - // bel's original proposal generated D to lair depth, then lair, then D - // to orc depth, then orc, then the rest of D. I have simplified this to - // just generate whole branches at a time -- I am not sure how much real - // impact this has. One idea might be to shuffle this slightly based on - // the seed. - // TODO: probably need to do portal vaults too? - // Should this use something like logical_branch_order? - const vector generation_order = - { - BRANCH_DUNGEON, - BRANCH_TEMPLE, - BRANCH_LAIR, - BRANCH_ORC, - BRANCH_SPIDER, - BRANCH_SNAKE, - BRANCH_SHOALS, - BRANCH_SWAMP, - BRANCH_VAULTS, - BRANCH_CRYPT, - BRANCH_DEPTHS, - BRANCH_VESTIBULE, - BRANCH_ELF, - BRANCH_ZOT, - BRANCH_SLIME, - BRANCH_TOMB, - BRANCH_TARTARUS, - BRANCH_COCYTUS, - BRANCH_DIS, - BRANCH_GEHENNA, - }; - - progress_popup progress("Generating dungeon...\n\n", 35); - progress.advance_progress(); - // TODO: why is dungeon invalid? it's not set up properly in - // `initialise_branch_depths` for some reason. The vestibule is invalid - // because its depth isn't set until the player actually enters a portal. - for (auto br : generation_order) - if (brentry[br].is_valid() - || br == BRANCH_DUNGEON || br == BRANCH_VESTIBULE) - { - string status = "\nbuilding "; - - switch (br) - { - case BRANCH_SPIDER: - case BRANCH_SNAKE: - status += "a lair branch"; - break; - case BRANCH_SHOALS: - case BRANCH_SWAMP: - status += "another lair branch"; - break; - default: - status += branches[br].longname; - break; - } - progress.set_status_text(status); - _pregen_levels(br, progress); - progress.advance_progress(); - } -} - static void _post_init(bool newc) { ASSERT(strwidth(you.your_name) <= MAX_NAME_LENGTH); @@ -342,7 +263,7 @@ static void _post_init(bool newc) if (newc) { if (Options.pregen_dungeon && crawl_state.game_standard_levelgen()) - _pregen_dungeon(); + pregen_dungeon(level_id(NUM_BRANCHES, -1)); you.entering_level = false; you.transit_stair = DNGN_UNSEEN; From 62a95a1fbf00ca13280e4737949f8dea483f94d0 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 25 Apr 2019 10:06:32 -0400 Subject: [PATCH 548/864] Add an option to disable incremental pregen, use it for fireworks This option isn't a very direct solution to the immediate problem, but it's something players might want anyway. The immediate problem is that after the incremental pregen commit, wizmode `&~` is not safe to use in a long sendkeys sequence, because if it triggers pregen, the pregen progress window will absorb any following keystrokes until it is done. For fireworks, the script just goes to temple because it's a straightforward area clear of monsters that it's safe to use for testing, so disabling pregen makes sense. No other official scripts really use this. If it turns out that a more complete solution is needed for some reason, I could imagine either (i) letting wizmode `&~` trigger a fancier menu that has an option to toggle pregen, or (ii) adding some kind of bot mode that suppresses the progress popup. Most bots trigger on ready() though, so won't get tripped up by this popup as far as I can see. --- crawl-ref/source/files.cc | 2 ++ crawl-ref/source/initfile.cc | 3 +++ crawl-ref/source/macro.cc | 27 +++++++++++++++++++++-- crawl-ref/source/options.h | 3 ++- crawl-ref/source/test/stress/fireworks.rc | 1 + 5 files changed, 33 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 6a701a6c3a90..71995c681615 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1467,6 +1467,8 @@ static const vector branch_generation_order = static bool _branch_pregenerates(branch_type b) { + if (!Options.incremental_pregen) + return false; return count(branch_generation_order.begin(), branch_generation_order.end(), b) > 0; } diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index 411560a5d0a1..da9000b114bc 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -296,6 +296,9 @@ const vector game_options::build_options_list() #ifndef DGAMELAUNCH new BoolGameOption(SIMPLE_NAME(pregen_dungeon), false), #endif + // TODO: should setting this to false be allowed outside of debug builds? + new BoolGameOption(SIMPLE_NAME(incremental_pregen), true), + #ifdef DGL_SIMPLE_MESSAGING new BoolGameOption(SIMPLE_NAME(messaging), false), diff --git a/crawl-ref/source/macro.cc b/crawl-ref/source/macro.cc index 1fc59967a26f..a5710515610a 100644 --- a/crawl-ref/source/macro.cc +++ b/crawl-ref/source/macro.cc @@ -816,6 +816,24 @@ int getch_with_command_macros() return macro_buf_get(); } +static string _buffer_to_string() +{ + string s; + for (const int k : Buffer) + { + if (k > 0 && k <= numeric_limits::max()) + { + char c = static_cast(k); + if (c == '[' || c == ']') + s += "\\"; + s += c; + } + else + s += make_stringf("[%d]", k); + } + return s; +} + /* * Flush the buffer. Later we'll probably want to give the player options * as to when this happens (ex. always before command input, casting failed). @@ -845,11 +863,16 @@ void flush_input_buffer(int reason) || reason == FLUSH_REPLAY_SETUP_FAILURE || reason == FLUSH_REPEAT_SETUP_DONE) { - if (crawl_state.nonempty_buffer_flush_errors) + if (crawl_state.nonempty_buffer_flush_errors && !Buffer.empty()) { if (you.wizard) // crash -- intended for tests + { + mprf(MSGCH_ERROR, + "Flushing non-empty key buffer (Buffer is '%s')", + _buffer_to_string().c_str()); ASSERT(Buffer.empty()); - else if (!Buffer.empty()) + } + else mprf(MSGCH_ERROR, "Flushing non-empty key buffer"); } while (!Buffer.empty()) diff --git a/crawl-ref/source/options.h b/crawl-ref/source/options.h index ca4cd9c9dfc4..fe2e193a6376 100644 --- a/crawl-ref/source/options.h +++ b/crawl-ref/source/options.h @@ -173,7 +173,8 @@ struct game_options uint64_t seed; // Non-random games. uint64_t seed_from_rc; - bool pregen_dungeon; // Is the dungeon generated at the beginning? + bool pregen_dungeon; // Is the dungeon completely generated at the beginning? + bool incremental_pregen; // Does the dungeon always generate in a specified order? #ifdef DGL_SIMPLE_MESSAGING bool messaging; // Check for messages. diff --git a/crawl-ref/source/test/stress/fireworks.rc b/crawl-ref/source/test/stress/fireworks.rc index 34dbd33ad849..40eb959f1389 100644 --- a/crawl-ref/source/test/stress/fireworks.rc +++ b/crawl-ref/source/test/stress/fireworks.rc @@ -7,6 +7,7 @@ species = mu background = ar restart_after_game = false show_more = false +incremental_pregen = false #message_colour = mute:.* : bot_start = true From 159d84b62b3faa92a4f5cc01894e77cc5ebd332f Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 27 Apr 2019 11:07:31 -0400 Subject: [PATCH 549/864] Cosmetic refactoring of the rng interface Move the more internal parts into their own namespace, and rename some functions accordingly. This still leaves the external interface (random2 etc) outside the `rng` namespace, because I'm not up for the consequent mass edit right now. --- crawl-ref/source/abyss.cc | 10 +- crawl-ref/source/dungeon.cc | 2 +- crawl-ref/source/fight.cc | 2 +- crawl-ref/source/files.cc | 4 +- crawl-ref/source/item-name.cc | 8 +- crawl-ref/source/item-name.h | 2 +- crawl-ref/source/l-debug.cc | 4 +- crawl-ref/source/message.cc | 6 +- crawl-ref/source/mon-place.cc | 2 +- crawl-ref/source/ng-init.cc | 2 +- crawl-ref/source/ng-setup.cc | 4 +- crawl-ref/source/pcg.cc | 93 ++++---- crawl-ref/source/pcg.h | 43 ++-- crawl-ref/source/random.cc | 224 +++++++++--------- crawl-ref/source/random.h | 47 ++-- crawl-ref/source/rng-type.h | 21 +- crawl-ref/source/show.cc | 2 +- crawl-ref/source/startup.cc | 2 +- crawl-ref/source/tags.cc | 10 +- crawl-ref/source/tileview.cc | 3 +- crawl-ref/source/util/monster/monster-main.cc | 2 +- 21 files changed, 258 insertions(+), 235 deletions(-) diff --git a/crawl-ref/source/abyss.cc b/crawl-ref/source/abyss.cc index 42b6e196960a..dab0c5db5932 100644 --- a/crawl-ref/source/abyss.cc +++ b/crawl-ref/source/abyss.cc @@ -1437,11 +1437,11 @@ static void _generate_area(const map_bitmask &abyss_genlevel_mask) static void _initialize_abyss_state() { - abyssal_state.major_coord.x = get_uint32() & 0x7FFFFFFF; - abyssal_state.major_coord.y = get_uint32() & 0x7FFFFFFF; - abyssal_state.seed = get_uint32() & 0x7FFFFFFF; + abyssal_state.major_coord.x = rng::get_uint32() & 0x7FFFFFFF; + abyssal_state.major_coord.y = rng::get_uint32() & 0x7FFFFFFF; + abyssal_state.seed = rng::get_uint32() & 0x7FFFFFFF; abyssal_state.phase = 0.0; - abyssal_state.depth = get_uint32() & 0x7FFFFFFF; + abyssal_state.depth = rng::get_uint32() & 0x7FFFFFFF; abyssal_state.destroy_all_terrain = false; abyssal_state.level = _get_random_level(); abyss_sample_queue = sample_queue(ProceduralSamplePQCompare()); @@ -1451,7 +1451,7 @@ void set_abyss_state(coord_def coord, uint32_t depth) { abyssal_state.major_coord = coord; abyssal_state.depth = depth; - abyssal_state.seed = get_uint32() & 0x7FFFFFFF; + abyssal_state.seed = rng::get_uint32() & 0x7FFFFFFF; abyssal_state.phase = 0.0; abyssal_state.destroy_all_terrain = true; abyss_sample_queue = sample_queue(ProceduralSamplePQCompare()); diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 7bae889b37b7..03f6bdf0597b 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -259,7 +259,7 @@ bool builder(bool enable_random_maps) temp_unique_items = you.unique_items; unwind_bool levelgen(crawl_state.generating_level, true); - rng_generator levelgen_rng(you.where_are_you); + rng::generator levelgen_rng(you.where_are_you); #ifdef DEBUG_DIAGNOSTICS // no point in enabling unless dprf works CrawlHashTable &debug_logs = you.props["debug_builder_logs"].get_table(); diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc index 9da4e72a7c90..3231faa7f0a8 100644 --- a/crawl-ref/source/fight.cc +++ b/crawl-ref/source/fight.cc @@ -599,7 +599,7 @@ int apply_chunked_AC(int dam, int ac) int hurt = 0; for (int i = 0; i < dam; i++) - if (get_uint32() < cr) + if (rng::get_uint32() < cr) hurt++; return hurt; diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 71995c681615..bae5e98a55df 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -2422,7 +2422,7 @@ static vector _load_permastore_ghosts(bool backup_on_upgrade=false) */ bool define_ghost_from_bones(monster& mons) { - rng_generator rng(RNG_SYSTEM_SPECIFIC); + rng::generator rng(rng::SYSTEM_SPECIFIC); bool used_permastore = false; @@ -3037,7 +3037,7 @@ static size_t _ghost_permastore_size() static vector _update_permastore(const vector &ghosts) { - rng_generator rng(RNG_SYSTEM_SPECIFIC); + rng::generator rng(rng::SYSTEM_SPECIFIC); if (ghosts.empty()) return ghosts; diff --git a/crawl-ref/source/item-name.cc b/crawl-ref/source/item-name.cc index 31e5f4a44f9b..3681036ee026 100644 --- a/crawl-ref/source/item-name.cc +++ b/crawl-ref/source/item-name.cc @@ -2759,7 +2759,7 @@ const size_t RCS_END = RCS_EM; string make_name(uint32_t seed, makename_type name_type) { uint64_t sarg[1] = { static_cast(seed) }; - PcgRNG rng = PcgRNG(sarg, ARRAYSZ(sarg)); + rng::PcgRNG rng = rng::PcgRNG(sarg, ARRAYSZ(sarg)); string name; @@ -3035,10 +3035,10 @@ static void _test_jiyva_names(const string& fname) sysfail("can't write test output"); string longest; - seed_rng(27); + rng::seed(27); for (int i = 0; i < 1000000; i++) { - const string name = make_name(get_uint32(), MNAME_JIYVA); + const string name = make_name(rng::get_uint32(), MNAME_JIYVA); ASSERT(name[0] == 'J'); if (name.length() > longest.length()) longest = name; @@ -3060,7 +3060,7 @@ void make_name_tests() _test_jiyva_names("jiyva_names.out"); _test_scroll_names("scroll_names.out"); - seed_rng(27); + rng::seed(27); for (int i = 0; i < 1000000; ++i) make_name(); } diff --git a/crawl-ref/source/item-name.h b/crawl-ref/source/item-name.h index bef0f62b7553..acd1b65dc9bd 100644 --- a/crawl-ref/source/item-name.h +++ b/crawl-ref/source/item-name.h @@ -121,7 +121,7 @@ bool is_bad_item(const item_def &item, bool temp = false); bool is_dangerous_item(const item_def& item, bool temp = false); bool is_useless_item(const item_def &item, bool temp = false); -string make_name(uint32_t seed = get_uint32(), +string make_name(uint32_t seed = rng::get_uint32(), makename_type name_type = MNAME_DEFAULT); void make_name_tests(); diff --git a/crawl-ref/source/l-debug.cc b/crawl-ref/source/l-debug.cc index 945c955ac2ff..4088c77833cc 100644 --- a/crawl-ref/source/l-debug.cc +++ b/crawl-ref/source/l-debug.cc @@ -413,7 +413,7 @@ LUAFN(debug_reset_rng) unsigned int seed = (unsigned int) luaL_safe_checkint(ls, 1); Options.seed = (uint64_t) seed; } - reset_rng(); + rng::reset(); const string ret = make_stringf("%" PRIu64, Options.seed); lua_pushstring(ls, ret.c_str()); return 1; @@ -423,7 +423,7 @@ LUAFN(debug_get_rng_state) { string r = make_stringf("seed: %" PRIu64 ", generator states: ", Options.seed); - vector states = get_rng_states(); + vector states = rng::get_states(); for (auto i : states) r += make_stringf("%" PRIu64 " ", i); lua_pushstring(ls, r.c_str()); diff --git a/crawl-ref/source/message.cc b/crawl-ref/source/message.cc index a150415b1961..90791caf77c3 100644 --- a/crawl-ref/source/message.cc +++ b/crawl-ref/source/message.cc @@ -680,7 +680,7 @@ class message_window */ void more(bool full, bool user=false) { - rng_generator rng(RNG_UI); + rng::generator rng(rng::UI); if (_pre_more()) return; @@ -1402,7 +1402,7 @@ static int _last_msg_turn = -1; // Turn of last message. static void _mpr(string text, msg_channel_type channel, int param, bool nojoin, bool cap) { - rng_generator rng(RNG_UI); + rng::generator rng(rng::UI); if (_msg_dump_file != nullptr) fprintf(_msg_dump_file, "%s\n", text.c_str()); @@ -1819,7 +1819,7 @@ static bool _pre_more() void more(bool user_forced) { - rng_generator rng(RNG_UI); + rng::generator rng(rng::UI); if (!crawl_state.io_inited) return; diff --git a/crawl-ref/source/mon-place.cc b/crawl-ref/source/mon-place.cc index 46f37b2efee0..9c9e8fd5b764 100644 --- a/crawl-ref/source/mon-place.cc +++ b/crawl-ref/source/mon-place.cc @@ -1510,7 +1510,7 @@ static monster* _place_pghost_aux(const mgen_data &mg, const monster *leader, // since depending on the ghost, the aux call can trigger variation in // things like whether an enchantment (with a random duration) is // triggered. - rng_generator rng(RNG_SYSTEM_SPECIFIC); + rng::generator rng(rng::SYSTEM_SPECIFIC); return _place_monster_aux(mg, leader, place, force_pos, dont_place); } diff --git a/crawl-ref/source/ng-init.cc b/crawl-ref/source/ng-init.cc index 1b79920a6cfb..d88022a60ca2 100644 --- a/crawl-ref/source/ng-init.cc +++ b/crawl-ref/source/ng-init.cc @@ -540,6 +540,6 @@ void initialise_item_descriptions() void fix_up_jiyva_name() { - you.jiyva_second_name = make_name(get_uint32(), MNAME_JIYVA); + you.jiyva_second_name = make_name(rng::get_uint32(), MNAME_JIYVA); ASSERT(you.jiyva_second_name[0] == 'J'); } diff --git a/crawl-ref/source/ng-setup.cc b/crawl-ref/source/ng-setup.cc index a8557325be7a..c46bc55eb04a 100644 --- a/crawl-ref/source/ng-setup.cc +++ b/crawl-ref/source/ng-setup.cc @@ -462,7 +462,7 @@ static void _free_up_slot(char letter) void initial_dungeon_setup() { - rng_generator levelgen_rng(BRANCH_DUNGEON); + rng::generator levelgen_rng(BRANCH_DUNGEON); initialise_branch_depths(); initialise_temples(); @@ -472,7 +472,7 @@ void initial_dungeon_setup() static void _setup_generic(const newgame_def& ng) { - reset_rng(); // initialize rng from Options.seed + rng::reset(); // initialize rng from Options.seed _init_player(); you.game_seed = crawl_state.seed; diff --git a/crawl-ref/source/pcg.cc b/crawl-ref/source/pcg.cc index 3796548f77d2..517ab3d00929 100644 --- a/crawl-ref/source/pcg.cc +++ b/crawl-ref/source/pcg.cc @@ -10,56 +10,59 @@ #include "pcg.h" -uint32_t -PcgRNG::get_uint32() +namespace rng { - count_++; - uint64_t oldstate = state_; - // Advance internal state - state_ = oldstate * static_cast(6364136223846793005ULL) + (inc_|1); - // Calculate output function (XSH RR), uses old state for max ILP - uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u; - uint32_t rot = oldstate >> 59u; - return (xorshifted >> rot) | (xorshifted << ((-rot) & 31)); -} + uint32_t + PcgRNG::get_uint32() + { + count_++; + uint64_t oldstate = state_; + // Advance internal state + state_ = oldstate * static_cast(6364136223846793005ULL) + (inc_|1); + // Calculate output function (XSH RR), uses old state for max ILP + uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u; + uint32_t rot = oldstate >> 59u; + return (xorshifted >> rot) | (xorshifted << ((-rot) & 31)); + } -uint64_t -PcgRNG::get_uint64() -{ - return static_cast(get_uint32()) << 32 | get_uint32(); -} + uint64_t + PcgRNG::get_uint64() + { + return static_cast(get_uint32()) << 32 | get_uint32(); + } -PcgRNG::PcgRNG() - // Choose base state arbitrarily. There's nothing up my sleeve. - : state_(static_cast(18446744073709551557ULL)), // Largest 64-bit prime. - inc_(static_cast(2305843009213693951ULL)), // Largest Mersenne prime under 64-bits. - count_(0) + PcgRNG::PcgRNG() + // Choose base state arbitrarily. There's nothing up my sleeve. + : state_(static_cast(18446744073709551557ULL)), // Largest 64-bit prime. + inc_(static_cast(2305843009213693951ULL)), // Largest Mersenne prime under 64-bits. + count_(0) -{ } + { } -PcgRNG::PcgRNG(uint64_t init_key[], int key_length) - : PcgRNG() -{ - if (key_length > 0) - state_ = init_key[0]; - if (key_length > 1) - inc_ = init_key[1]; - else - inc_ ^= get_uint32(); -} + PcgRNG::PcgRNG(uint64_t init_key[], int key_length) + : PcgRNG() + { + if (key_length > 0) + state_ = init_key[0]; + if (key_length > 1) + inc_ = init_key[1]; + else + inc_ ^= get_uint32(); + } -PcgRNG::PcgRNG(const CrawlVector &v) - : PcgRNG() -{ - ASSERT(v.size() == 2); - state_ = static_cast(v[0].get_int64()); - inc_ = static_cast(v[1].get_int64()); -} + PcgRNG::PcgRNG(const CrawlVector &v) + : PcgRNG() + { + ASSERT(v.size() == 2); + state_ = static_cast(v[0].get_int64()); + inc_ = static_cast(v[1].get_int64()); + } -CrawlVector PcgRNG::to_vector() -{ - CrawlVector store; - store.push_back(static_cast(state_)); - store.push_back(static_cast(inc_)); - return store; + CrawlVector PcgRNG::to_vector() + { + CrawlVector store; + store.push_back(static_cast(state_)); + store.push_back(static_cast(inc_)); + return store; + } } diff --git a/crawl-ref/source/pcg.h b/crawl-ref/source/pcg.h index ae4a403af4fe..5e81e5a3f775 100644 --- a/crawl-ref/source/pcg.h +++ b/crawl-ref/source/pcg.h @@ -1,27 +1,30 @@ #pragma once class CrawlVector; -class PcgRNG +namespace rng { - public: - PcgRNG(); - PcgRNG(uint64_t init_key[], int key_length); - PcgRNG(const CrawlVector &v); - CrawlVector to_vector(); - uint32_t get_uint32(); - uint64_t get_uint64(); - uint32_t operator()() { return get_uint32(); } + class PcgRNG + { + public: + PcgRNG(); + PcgRNG(uint64_t init_key[], int key_length); + PcgRNG(const CrawlVector &v); + CrawlVector to_vector(); + uint32_t get_uint32(); + uint64_t get_uint64(); + uint32_t operator()() { return get_uint32(); } - typedef uint32_t result_type; - static constexpr uint32_t min() { return 0; } - static constexpr uint32_t max() { return 0xffffffffU; } + typedef uint32_t result_type; + static constexpr uint32_t min() { return 0; } + static constexpr uint32_t max() { return 0xffffffffU; } - uint64_t get_state() { return state_; }; - uint64_t get_inc() { return inc_; }; - uint64_t get_count() { return count_; }; + uint64_t get_state() { return state_; }; + uint64_t get_inc() { return inc_; }; + uint64_t get_count() { return count_; }; - private: - uint64_t state_; - uint64_t inc_; - uint64_t count_; -}; + private: + uint64_t state_; + uint64_t inc_; + uint64_t count_; + }; +} diff --git a/crawl-ref/source/random.cc b/crawl-ref/source/random.cc index be64976e95c0..17dfcd834142 100644 --- a/crawl-ref/source/random.cc +++ b/crawl-ref/source/random.cc @@ -17,130 +17,138 @@ #include "store.h" #include "options.h" -static FixedVector rngs; -static rng_type _generator = RNG_GAMEPLAY; - -CrawlVector generators_to_vector() +namespace rng { - CrawlVector store; - for (PcgRNG& rng : rngs) - store.push_back(rng.to_vector()); // TODO is this ok memory-wise? - return store; -} + // global/persistent rng state that will be saved + static FixedVector _global_state; -vector get_rng_states() -{ - // this doesn't return the internal state per se, but it returns the count - // of 32 bit integers that have been drawn, which amounts to the same thing. - // This isn't saved, though, so it's mainly useful for debugging within a - // session. - vector result; - for (PcgRNG& rng : rngs) - result.push_back(rng.get_count()); - return result; -} + // temporary rng state + static rng_type _generator = rng::GAMEPLAY; -void load_generators(const CrawlVector &v) -{ - // as-is, decreasing the number of rngs (e.g. by removing a branch) will - // break save compatibility. - ASSERT(v.size() <= rngs.size()); - for (int i = 0; i < v.size(); i++) + CrawlVector generators_to_vector() { - CrawlVector state = v[i].get_vector(); - rngs[i] = PcgRNG(state); + CrawlVector store; + for (PcgRNG& rng : _global_state) + store.push_back(rng.to_vector()); // TODO is this ok memory-wise? + return store; } -} -rng_generator::rng_generator(rng_type g) : previous(_generator) -{ - _generator = g; -} + vector get_states() + { + // this doesn't return the internal state per se, but it returns the count + // of 32 bit integers that have been drawn, which amounts to the same thing. + // This isn't saved, though, so it's mainly useful for debugging within a + // session. + vector result; + for (PcgRNG& rng : _global_state) + result.push_back(rng.get_count()); + return result; + } -static rng_type _get_branch_generator(const branch_type b) -{ - return static_cast(RNG_LEVELGEN + static_cast(b)); -} + void load_generators(const CrawlVector &v) + { + // as-is, decreasing the number of rngs (e.g. by removing a branch) will + // break save compatibility. + ASSERT(v.size() <= _global_state.size()); + for (int i = 0; i < v.size(); i++) + { + CrawlVector state = v[i].get_vector(); + _global_state[i] = PcgRNG(state); + } + } -rng_generator::rng_generator(branch_type b) : previous(_generator) -{ - _generator = _get_branch_generator(b); -} + generator::generator(rng_type g) : previous(_generator) + { + _generator = g; + } -rng_generator::~rng_generator() -{ - _generator = previous; -} + static rng_type _get_branch_generator(const branch_type b) + { + return static_cast(rng::LEVELGEN + static_cast(b)); + } -uint32_t get_uint32(rng_type generator) -{ - return rngs[generator].get_uint32(); -} + generator::generator(branch_type b) : previous(_generator) + { + _generator = _get_branch_generator(b); + } -uint32_t get_uint32() -{ - return get_uint32(_generator); -} + generator::~generator() + { + _generator = previous; + } -uint32_t peek_uint32() -{ - PcgRNG tmp = rngs[_generator]; - return tmp.get_uint32(); -} + uint32_t get_uint32(rng_type generator) + { + return _global_state[generator].get_uint32(); + } -uint64_t get_uint64(rng_type generator) -{ - return rngs[generator].get_uint64(); -} + uint32_t get_uint32() + { + return get_uint32(_generator); + } -uint64_t get_uint64() -{ - return get_uint64(_generator); -} + uint32_t peek_uint32() + { + PcgRNG tmp = _global_state[_generator]; + return tmp.get_uint32(); + } -static void _seed_rng(uint64_t seed_array[], int seed_len) -{ - PcgRNG seeded(seed_array, seed_len); - // TODO: don't initialize gameplay/ui rng? - // Use the just seeded RNG to initialize the rest. - for (PcgRNG& rng : rngs) + uint64_t get_uint64(rng_type generator) { - uint64_t key[2] = { seeded.get_uint64(), seeded.get_uint64() }; - rng = PcgRNG(key, ARRAYSZ(key)); + return _global_state[generator].get_uint64(); } -} -void seed_rng(uint64_t seed) -{ - uint64_t sarg[1] = { seed }; - _seed_rng(sarg, ARRAYSZ(sarg)); -} + uint64_t get_uint64() + { + return get_uint64(_generator); + } -void seed_rng() -{ - /* Use a 128-bit wide seed */ - uint64_t seed_key[2]; - bool seeded = read_urandom((char*)(&seed_key), sizeof(seed_key)); - ASSERT(seeded); - _seed_rng(seed_key, ARRAYSZ(seed_key)); -} + static void _do_seeding(uint64_t seed_array[], int seed_len) + { + PcgRNG seeded(seed_array, seed_len); + // TODO: don't initialize gameplay/ui rng? + // Use the just seeded RNG to initialize the rest. + for (PcgRNG& rng : _global_state) + { + uint64_t key[2] = { seeded.get_uint64(), seeded.get_uint64() }; + rng = PcgRNG(key, ARRAYSZ(key)); + } + } -/** - * Reset RNG to Options seed, and if that seed is 0, generate a new one. - */ -void reset_rng() -{ - crawl_state.seed = Options.seed; - while (!crawl_state.seed) // 0 = random seed + void seed(uint64_t seed) { - seed_rng(); // reset entirely via read_urandom - crawl_state.seed = get_uint64(); + uint64_t sarg[1] = { seed }; + _do_seeding(sarg, ARRAYSZ(sarg)); + } + + void seed() + { + /* Use a 128-bit wide seed */ + uint64_t seed_key[2]; + bool seeded = read_urandom((char*)(&seed_key), sizeof(seed_key)); + ASSERT(seeded); + _do_seeding(seed_key, ARRAYSZ(seed_key)); + } + + /** + * Reset RNG to Options seed, and if that seed is 0, generate a new one. + */ + void reset() + { + crawl_state.seed = Options.seed; + while (!crawl_state.seed) // 0 = random seed + { + rng::seed(); // reset entirely via read_urandom + crawl_state.seed = get_uint64(); + } + dprf("Setting game seed to %" PRIu64, crawl_state.seed); + you.game_seed = crawl_state.seed; + rng::seed(crawl_state.seed); } - dprf("Setting game seed to %" PRIu64, crawl_state.seed); - you.game_seed = crawl_state.seed; - seed_rng(crawl_state.seed); } +// TODO: probably this could all be in the rng namespace + // [low, high] int random_range(int low, int high) { @@ -156,16 +164,16 @@ int random_range(int low, int high, int nrolls) return low + roll; } -static int _random2(int max, rng_type rng) +static int _random2(int max, rng::rng_type rng) { if (max <= 1) return 0; - uint32_t partn = PcgRNG::max() / max; + uint32_t partn = rng::PcgRNG::max() / max; while (true) { - uint32_t bits = get_uint32(rng); + uint32_t bits = rng::get_uint32(rng); uint32_t val = bits / partn; if (val < (uint32_t)max) @@ -176,13 +184,13 @@ static int _random2(int max, rng_type rng) // [0, max) int random2(int max) { - return _random2(max, _generator); + return _random2(max, rng::_generator); } // [0, max), separate RNG state int ui_random(int max) { - return _random2(max, RNG_UI); + return _random2(max, rng::UI); } // [0, 1] @@ -367,7 +375,7 @@ double random_real() { static const uint64_t UPPER_BITS = 0x3FF0000000000000ULL; static const uint64_t LOWER_MASK = 0x000FFFFFFFFFFFFFULL; - const uint64_t value = UPPER_BITS | (get_uint64() & LOWER_MASK); + const uint64_t value = UPPER_BITS | (rng::get_uint64() & LOWER_MASK); double result; // Portable memory transmutation. The union trick almost always // works, but this is safer. @@ -427,7 +435,7 @@ bool defer_rand::x_chance_in_y_contd(int x, int y, int index) do { if (index == int(bits.size())) - bits.push_back(get_uint32()); + bits.push_back(rng::get_uint32()); uint64_t expn_rand_1 = uint64_t(bits[index++]) * y; uint64_t expn_rand_2 = expn_rand_1 + y; @@ -450,7 +458,7 @@ int defer_rand::random2(int maxp1) return 0; if (bits.empty()) - bits.push_back(get_uint32()); + bits.push_back(rng::get_uint32()); uint64_t expn_rand_1 = uint64_t(bits[0]) * maxp1; uint64_t expn_rand_2 = expn_rand_1 + maxp1; diff --git a/crawl-ref/source/random.h b/crawl-ref/source/random.h index 3342fa3d30b5..36da2700c96c 100644 --- a/crawl-ref/source/random.h +++ b/crawl-ref/source/random.h @@ -8,31 +8,36 @@ #include "hash.h" #include "rng-type.h" -class rng_generator +class CrawlVector; + +namespace rng { -public: - rng_generator(rng_type g); - rng_generator(branch_type b); - ~rng_generator(); -private: - rng_type previous; -}; + class generator + { + public: + generator(rng_type g); + generator(branch_type b); + ~generator(); + private: + rng_type previous; + }; -class CrawlVector; -CrawlVector generators_to_vector(); -void load_generators(const CrawlVector &v); -vector get_rng_states(); + CrawlVector generators_to_vector(); + void load_generators(const CrawlVector &v); + vector get_states(); -void seed_rng(); -void seed_rng(uint64_t seed); -void seed_rng(uint64_t[], int); -void reset_rng(); + void seed(); + void seed(uint64_t seed); + void seed(uint64_t[], int); + void reset(); + + uint32_t get_uint32(rng_type generator); + uint64_t get_uint64(rng_type generator); + uint32_t get_uint32(); + uint64_t get_uint64(); + uint32_t peek_uint32(); +} -uint32_t get_uint32(rng_type generator); -uint64_t get_uint64(rng_type generator); -uint32_t get_uint32(); -uint64_t get_uint64(); -uint32_t peek_uint32(); bool coinflip(); int div_rand_round(int num, int den); int rand_round(double x); diff --git a/crawl-ref/source/rng-type.h b/crawl-ref/source/rng-type.h index a72eca156b72..04ca5b702f43 100644 --- a/crawl-ref/source/rng-type.h +++ b/crawl-ref/source/rng-type.h @@ -1,12 +1,15 @@ #pragma once #include "branch-type.h" -enum rng_type { - RNG_GAMEPLAY, // gameplay effects in general - RNG_UI, // UI randomization - RNG_SYSTEM_SPECIFIC, // anything that may vary from system to system, e.g. ghosts - RNG_SPARE2, - RNG_SPARE3, - RNG_LEVELGEN, // branch 0, i.e. the dungeon - NUM_RNGS = RNG_LEVELGEN + NUM_BRANCHES, // and then one for each other branch -}; +namespace rng +{ + enum rng_type { + GAMEPLAY, // gameplay effects in general + UI, // UI randomization + SYSTEM_SPECIFIC, // anything that may vary from system to system, e.g. ghosts + SPARE2, + SPARE3, + LEVELGEN, // branch 0, i.e. the dungeon + NUM_RNGS = LEVELGEN + NUM_BRANCHES, // and then one for each other branch + }; +} diff --git a/crawl-ref/source/show.cc b/crawl-ref/source/show.cc index 871f964b2a29..9b881d0cdff0 100644 --- a/crawl-ref/source/show.cc +++ b/crawl-ref/source/show.cc @@ -441,7 +441,7 @@ static void _update_monster(monster* mons) if (you.attribute[ATTR_SEEN_INVIS_TURN] != you.num_turns) { you.attribute[ATTR_SEEN_INVIS_TURN] = you.num_turns; - you.attribute[ATTR_SEEN_INVIS_SEED] = get_uint32(); + you.attribute[ATTR_SEEN_INVIS_SEED] = rng::get_uint32(); } // After the player finishes this turn, the monster's unseen pos (and // its invis indicator due to going unseen) will be erased. diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index b139f34f152f..8229cc634fde 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -85,7 +85,7 @@ static void _initialize() you.symbol = MONS_PLAYER; msg::initialise_mpr_streams(); - seed_rng(); // don't use any chosen seed yet + rng::seed(); // don't use any chosen seed yet init_char_table(Options.char_set); init_show_table(); diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index 7ef4ee95e5b4..397c3e84ad4a 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -1671,7 +1671,7 @@ static void tag_construct_you(writer &th) marshallUByte(th, 1); // number of seeds, for historical reasons: always 1 marshallUnsigned(th, you.game_seed); marshallBoolean(th, you.game_is_seeded); - CrawlVector rng_states = generators_to_vector(); + CrawlVector rng_states = rng::generators_to_vector(); rng_states.write(th); CANARY; @@ -3609,7 +3609,7 @@ static void tag_read_you(reader &th) if (th.getMinorVersion() >= TAG_MINOR_REMOVE_ABYSS_SEED && th.getMinorVersion() < TAG_MINOR_ADD_ABYSS_SEED) { - abyssal_state.seed = get_uint32(); + abyssal_state.seed = rng::get_uint32(); } else #endif @@ -3623,7 +3623,7 @@ static void tag_read_you(reader &th) unmarshallFloat(th); // converted abyssal_state.depth to int. abyssal_state.depth = 0; abyssal_state.destroy_all_terrain = true; - abyssal_state.seed = get_uint32(); + abyssal_state.seed = rng::get_uint32(); } #endif abyssal_state.phase = unmarshallFloat(th); @@ -3688,7 +3688,7 @@ static void tag_read_you(reader &th) ASSERT(th.getMinorVersion() < TAG_MINOR_GAMESEEDS || count == 1); if (th.getMinorVersion() < TAG_MINOR_GAMESEEDS) { - you.game_seed = count > 0 ? unmarshallInt(th) : get_uint64(); + you.game_seed = count > 0 ? unmarshallInt(th) : rng::get_uint64(); dprf("Upgrading from unseeded game."); crawl_state.seed = you.game_seed; you.game_is_seeded = false; @@ -3707,7 +3707,7 @@ static void tag_read_you(reader &th) you.game_is_seeded = unmarshallBoolean(th); CrawlVector rng_states; rng_states.read(th); - load_generators(rng_states); + rng::load_generators(rng_states); #if TAG_MAJOR_VERSION == 34 } #endif diff --git a/crawl-ref/source/tileview.cc b/crawl-ref/source/tileview.cc index b63569f471a5..67adbfba240d 100644 --- a/crawl-ref/source/tileview.cc +++ b/crawl-ref/source/tileview.cc @@ -313,10 +313,11 @@ void tile_clear_flavour() void tile_init_flavour() { vector output; + { uint64_t seed[] = { static_cast(you.where_are_you ^ you.game_seed), static_cast(you.depth) }; - PcgRNG rng(seed, ARRAYSZ(seed)); + rng::PcgRNG rng(seed, ARRAYSZ(seed)); if (you.where_are_you == BRANCH_CRYPT) { output.reserve(X_WIDTH * Y_WIDTH); diff --git a/crawl-ref/source/util/monster/monster-main.cc b/crawl-ref/source/util/monster/monster-main.cc index 5c935b06a16d..14a63b142a95 100644 --- a/crawl-ref/source/util/monster/monster-main.cc +++ b/crawl-ref/source/util/monster/monster-main.cc @@ -703,7 +703,7 @@ int main(int argc, char* argv[]) } else if (!strcmp(argv[1], "-name") || !strcmp(argv[1], "--name")) { - seed_rng(); + rng::seed(); printf("%s\n", make_name().c_str()); return 0; } From 8fead6faaf77c77157ac9027496acfb08b826137 Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 27 Apr 2019 13:30:09 -0400 Subject: [PATCH 550/864] Change PCG initialization to something more standard Perhaps because of the age of our PCG implementation (it comes from before the official implementations were well-developed/documented), our initialization process was fairly ad-hoc, which is not usually a good idea in RNG design. This commit converts the initialization behavior to match what the official implementations do, for example: https://github.com/imneme/pcg-c-basic/blob/master/pcg_basic.c Possibly it would be best even to just use the official c++ PCG implementation, but this commit doesn't go that far. Needless to say, this change affects all seeds. --- crawl-ref/source/item-name.cc | 4 +-- crawl-ref/source/pcg.cc | 43 +++++++++++++++++++++--------- crawl-ref/source/pcg.h | 37 ++++++++++++------------- crawl-ref/source/random.cc | 18 +++++++------ crawl-ref/source/test/rng_test.lua | 2 +- crawl-ref/source/tileview.cc | 8 +++--- 6 files changed, 67 insertions(+), 45 deletions(-) diff --git a/crawl-ref/source/item-name.cc b/crawl-ref/source/item-name.cc index 3681036ee026..5decf9549129 100644 --- a/crawl-ref/source/item-name.cc +++ b/crawl-ref/source/item-name.cc @@ -2758,8 +2758,8 @@ const size_t RCS_END = RCS_EM; */ string make_name(uint32_t seed, makename_type name_type) { - uint64_t sarg[1] = { static_cast(seed) }; - rng::PcgRNG rng = rng::PcgRNG(sarg, ARRAYSZ(sarg)); + // TODO: better conversion of the seed to 64 bits + rng::PcgRNG rng = rng::PcgRNG(static_cast(seed)); string name; diff --git a/crawl-ref/source/pcg.cc b/crawl-ref/source/pcg.cc index 517ab3d00929..2b0e90cdd763 100644 --- a/crawl-ref/source/pcg.cc +++ b/crawl-ref/source/pcg.cc @@ -17,8 +17,12 @@ namespace rng { count_++; uint64_t oldstate = state_; - // Advance internal state - state_ = oldstate * static_cast(6364136223846793005ULL) + (inc_|1); + // Advance internal state. Use the 'official' multiplier. Don't change + // this without carefully consulting official sources, as not all + // multipliers are ok: see + // http://www.pcg-random.org/posts/critiquing-pcg-streams.html + state_ = oldstate * static_cast(6364136223846793005ULL) + + (inc_|1); // Calculate output function (XSH RR), uses old state for max ILP uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u; uint32_t rot = oldstate >> 59u; @@ -31,25 +35,38 @@ namespace rng return static_cast(get_uint32()) << 32 | get_uint32(); } + // Initialization values only. + // don't generate unseeded versions of this. But if you must, go get the + // constants from the official PCG implementation... PcgRNG::PcgRNG() - // Choose base state arbitrarily. There's nothing up my sleeve. - : state_(static_cast(18446744073709551557ULL)), // Largest 64-bit prime. - inc_(static_cast(2305843009213693951ULL)), // Largest Mersenne prime under 64-bits. + : state_(static_cast(0)), + inc_(static_cast(1)), count_(0) - { } - PcgRNG::PcgRNG(uint64_t init_key[], int key_length) + /** + * Seed a PCG RNG instance based on a seed (`init_state`) and a sequence/ + * stream id. Both of these can be any value, but the highest bit of + * `sequence` will be discarded. + * + * @param init_state the seed value to initialize PCG state with. + * @param sequence the sequence number/stream id. + */ + PcgRNG::PcgRNG(uint64_t init_state, uint64_t sequence) : PcgRNG() { - if (key_length > 0) - state_ = init_key[0]; - if (key_length > 1) - inc_ = init_key[1]; - else - inc_ ^= get_uint32(); + inc_ = sequence << 1u | 1u; // any odd value is ok + get_uint32(); + state_ += init_state; + get_uint32(); + count_ = 0; } + PcgRNG::PcgRNG(uint64_t init_state) + : PcgRNG(init_state, static_cast(2305843009213693951ULL)) + // Largest Mersenne prime under 64-bits. + { } + PcgRNG::PcgRNG(const CrawlVector &v) : PcgRNG() { diff --git a/crawl-ref/source/pcg.h b/crawl-ref/source/pcg.h index 5e81e5a3f775..c3a5f6658719 100644 --- a/crawl-ref/source/pcg.h +++ b/crawl-ref/source/pcg.h @@ -5,26 +5,27 @@ namespace rng { class PcgRNG { - public: - PcgRNG(); - PcgRNG(uint64_t init_key[], int key_length); - PcgRNG(const CrawlVector &v); - CrawlVector to_vector(); - uint32_t get_uint32(); - uint64_t get_uint64(); - uint32_t operator()() { return get_uint32(); } + public: + PcgRNG(); + PcgRNG(uint64_t init_state, uint64_t sequence); + PcgRNG(uint64_t init_state); + PcgRNG(const CrawlVector &v); + CrawlVector to_vector(); + uint32_t get_uint32(); + uint64_t get_uint64(); + uint32_t operator()() { return get_uint32(); } - typedef uint32_t result_type; - static constexpr uint32_t min() { return 0; } - static constexpr uint32_t max() { return 0xffffffffU; } + typedef uint32_t result_type; + static constexpr uint32_t min() { return 0; } + static constexpr uint32_t max() { return 0xffffffffU; } - uint64_t get_state() { return state_; }; - uint64_t get_inc() { return inc_; }; - uint64_t get_count() { return count_; }; + uint64_t get_state() { return state_; }; + uint64_t get_inc() { return inc_; }; + uint64_t get_count() { return count_; }; - private: - uint64_t state_; - uint64_t inc_; - uint64_t count_; + private: + uint64_t state_; + uint64_t inc_; + uint64_t count_; }; } diff --git a/crawl-ref/source/random.cc b/crawl-ref/source/random.cc index 17dfcd834142..c75c8e978e30 100644 --- a/crawl-ref/source/random.cc +++ b/crawl-ref/source/random.cc @@ -103,31 +103,33 @@ namespace rng return get_uint64(_generator); } - static void _do_seeding(uint64_t seed_array[], int seed_len) + static void _do_seeding(PcgRNG &master) { - PcgRNG seeded(seed_array, seed_len); // TODO: don't initialize gameplay/ui rng? // Use the just seeded RNG to initialize the rest. for (PcgRNG& rng : _global_state) { - uint64_t key[2] = { seeded.get_uint64(), seeded.get_uint64() }; - rng = PcgRNG(key, ARRAYSZ(key)); + uint64_t init_state = master.get_uint64(); + uint64_t seq = master.get_uint64(); + rng = PcgRNG(init_state, seq); } } void seed(uint64_t seed) { - uint64_t sarg[1] = { seed }; - _do_seeding(sarg, ARRAYSZ(sarg)); + // use the default stream + PcgRNG master = PcgRNG(seed); + _do_seeding(master); } void seed() { - /* Use a 128-bit wide seed */ + // seed both state and sequence from system randomness. uint64_t seed_key[2]; bool seeded = read_urandom((char*)(&seed_key), sizeof(seed_key)); ASSERT(seeded); - _do_seeding(seed_key, ARRAYSZ(seed_key)); + PcgRNG master = PcgRNG(seed_key[0], seed_key[1]); + _do_seeding(master); } /** diff --git a/crawl-ref/source/test/rng_test.lua b/crawl-ref/source/test/rng_test.lua index 151257c7cbb8..a2ec7c3c8f14 100644 --- a/crawl-ref/source/test/rng_test.lua +++ b/crawl-ref/source/test/rng_test.lua @@ -3,7 +3,7 @@ local eol = string.char(13) -local results = {49, 97, 51, 75, 3, 38, 66, 84, 28, 76} +local results = {51, 11, 78, 21, 19, 95, 21, 43, 33, 75} debug.reset_rng(1) crawl.stderr("Here are 10 random numbers from seed 1:" .. eol) diff --git a/crawl-ref/source/tileview.cc b/crawl-ref/source/tileview.cc index 67adbfba240d..b43aa2d5bb5f 100644 --- a/crawl-ref/source/tileview.cc +++ b/crawl-ref/source/tileview.cc @@ -315,9 +315,11 @@ void tile_init_flavour() vector output; { - uint64_t seed[] = { static_cast(you.where_are_you ^ you.game_seed), - static_cast(you.depth) }; - rng::PcgRNG rng(seed, ARRAYSZ(seed)); +<<<<<<< HEAD + rng::PcgRNG rng( + static_cast(you.where_are_you ^ you.game_seed), + static_cast(you.depth)); + if (you.where_are_you == BRANCH_CRYPT) { output.reserve(X_WIDTH * Y_WIDTH); From bc886685f78b1fe7bca6120f04d34b82f03937a5 Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 28 Apr 2019 14:35:18 -0400 Subject: [PATCH 551/864] Update the bounded random implementation This moves to an implementation of unbiased bounded random number generation based on a recent algorithm by Daniel Lemire with an implementation by Melissa O'Neill. This change has two advantages: (i) the big one, this is off-the-shelf code written by an rng expert, implementing an algorithm designed by someone who specializes in this kind of optimization. Ours was *probably* fine, but didn't exactly match any standard way of doing this that I was able to find. (ii) It gets a 10% speedup for typical range values compared to our old implementation, because it avoids using /,% where possible. This is probably not a big deal in the scale of things that are slow in crawlcode, but we do call the rng a *lot*, mostly with range values that this function is optimized for. See: http://www.pcg-random.org/posts/bounded-rands.html https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ https://arxiv.org/abs/1805.10941 This also updates the API for this call, moving it the implementation into the pcg class, as well as updates some comments in pcg.cc to be more detailed and correct. --- LICENSE | 2 +- crawl-ref/source/pcg.cc | 70 +++++++++++++++++++++++++++--- crawl-ref/source/pcg.h | 1 + crawl-ref/source/random.cc | 29 +++++-------- crawl-ref/source/test/rng_test.lua | 11 +++++ 5 files changed, 88 insertions(+), 25 deletions(-) diff --git a/LICENSE b/LICENSE index 08656b10161f..9069e9579daa 100644 --- a/LICENSE +++ b/LICENSE @@ -18,7 +18,7 @@ These include: resize-observer-polyfill, and scrollbarwidth worley.{cc,h} * zlib: webserver/static/scripts/contrib/inflate.js -* Apache v2: pcg.cc +* Apache v2, MIT (see comments in the file for details): pcg.cc The majority of Crawl's tiles and artwork are released under the CC0 license (https://creativecommons.org/publicdomain/zero/1.0/), and new submissions are diff --git a/crawl-ref/source/pcg.cc b/crawl-ref/source/pcg.cc index 2b0e90cdd763..f4cd5015b67e 100644 --- a/crawl-ref/source/pcg.cc +++ b/crawl-ref/source/pcg.cc @@ -1,9 +1,26 @@ -/* This class implements a 128-bit pseudo-random number generator. - * Despite a reduction in state space, it still passes TestU01 BigCrush. +/* This file implements a 32-bit pseudo-random number generator with 64 bit + * internal state: see http://www.pcg-random.org/. * - * get_uint32 is derived from M.E. O'Neill's minimal PCG implementation. - * That function (c) 2014 M.E. O'Neill / pcg-random.org + * "PCG is a family of simple fast space-efficient statistically good + * algorithms for random number generation. Unlike many general-purpose RNGs, + * they are also hard to predict." + * + * TODO: should we eventually switch to just directly using the official c++ + * implementation? + * + * PcgRNG::PcgRNG() and get_uint32 are derived/modified from M.E. O'Neill's + * minimal PCG implementation: + * https://github.com/imneme/pcg-c-basic/blob/master/pcg_basic.c + * Original source is (c) 2014 Melissa O'Neill * Licensed under Apache License 2.0 + * + * get_bounded_uint32 is derived/modified from an implemention by Melissa + * O'Neill of an algorithm by Daniel Lemire as part of a comparison of bounded + * random functions: + * http://www.pcg-random.org/posts/bounded-rands.html + * https://github.com/imneme/bounded-rands/blob/master/bounded32.cpp + * Original source is Copyright (c) 2018 Melissa E. O'Neill + * Licensed under The MIT License */ #include "AppHdr.h" @@ -12,8 +29,10 @@ namespace rng { - uint32_t - PcgRNG::get_uint32() + /** + * Generate a uniformly distributed 32-bit random number. + */ + uint32_t PcgRNG::get_uint32() { count_++; uint64_t oldstate = state_; @@ -35,6 +54,45 @@ namespace rng return static_cast(get_uint32()) << 32 | get_uint32(); } + /** + * Generate a uniformly distributed number, r, where 0 <= r < range. + * This uses a technique due to Daniel Lemire, with implementation and + * additional tweaks from Melissa O'Neil. It's designed to avoid /,% for + * small values of `range`. + * + * See: + * http://www.pcg-random.org/posts/bounded-rands.html + * https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ + * https://arxiv.org/abs/1805.10941 or https://dl.acm.org/citation.cfm?id=3230636 + */ + uint32_t PcgRNG::get_bounded_uint32(uint32_t range) + { + uint32_t x = get_uint32(); + uint64_t m = uint64_t(x) * uint64_t(range); + uint32_t l = uint32_t(m); + if (l < range) + { + // TODO: will this generate warnings somewhere? the PCG c++ + // implementation has a different version of this step that may be + // useful. + uint32_t t = -range; + + if (t >= range) + { + t -= range; + if (t >= range) + t %= range; + } + while (l < t) + { + x = get_uint32(); + m = uint64_t(x) * uint64_t(range); + l = uint32_t(m); + } + } + return m >> 32; + } + // Initialization values only. // don't generate unseeded versions of this. But if you must, go get the // constants from the official PCG implementation... diff --git a/crawl-ref/source/pcg.h b/crawl-ref/source/pcg.h index c3a5f6658719..5620550c5287 100644 --- a/crawl-ref/source/pcg.h +++ b/crawl-ref/source/pcg.h @@ -12,6 +12,7 @@ namespace rng PcgRNG(const CrawlVector &v); CrawlVector to_vector(); uint32_t get_uint32(); + uint32_t get_bounded_uint32(uint32_t bound); uint64_t get_uint64(); uint32_t operator()() { return get_uint32(); } diff --git a/crawl-ref/source/random.cc b/crawl-ref/source/random.cc index c75c8e978e30..c0ddbc732418 100644 --- a/crawl-ref/source/random.cc +++ b/crawl-ref/source/random.cc @@ -77,6 +77,11 @@ namespace rng _generator = previous; } + PcgRNG ¤t_generator() + { + return _global_state[_generator]; + } + uint32_t get_uint32(rng_type generator) { return _global_state[generator].get_uint32(); @@ -166,33 +171,21 @@ int random_range(int low, int high, int nrolls) return low + roll; } -static int _random2(int max, rng::rng_type rng) +// [0, max) +int random2(int max) { if (max <= 1) return 0; - uint32_t partn = rng::PcgRNG::max() / max; - - while (true) - { - uint32_t bits = rng::get_uint32(rng); - uint32_t val = bits / partn; - - if (val < (uint32_t)max) - return (int)val; - } -} - -// [0, max) -int random2(int max) -{ - return _random2(max, rng::_generator); + return rng::current_generator().get_bounded_uint32(max); } // [0, max), separate RNG state int ui_random(int max) { - return _random2(max, rng::UI); + rng::generator ui(rng::UI); + + return random2(max); } // [0, 1] diff --git a/crawl-ref/source/test/rng_test.lua b/crawl-ref/source/test/rng_test.lua index a2ec7c3c8f14..b449a65c98d0 100644 --- a/crawl-ref/source/test/rng_test.lua +++ b/crawl-ref/source/test/rng_test.lua @@ -3,6 +3,15 @@ local eol = string.char(13) +function big_rng_test() + crawl.stderr("Running big rng test, this may take a while...") + for i = 1, 0xffffffff do + crawl.random2(i) + end + debug.reset_rng(1) + +end + local results = {51, 11, 78, 21, 19, 95, 21, 43, 33, 75} debug.reset_rng(1) @@ -15,3 +24,5 @@ end crawl.stderr(eol) debug.reset_rng(1) + +--big_rng_test() From 9ece634645fb835cd975064c986ecb580c504647 Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 28 Apr 2019 23:21:28 -0400 Subject: [PATCH 552/864] Improve the rng subgenerator API This makes it easier to spin up a temporary rng based on current rng state (or not). Subgenerators are designed for one-off calculations where it is desirable to keep the main rng state fairly stable. A couple pieces of code already use this technique, and they are now a lot better, both converted to use unbiased bounded random calls (though the domino code is complicated enough that I didn't want to convert it over fully). This commit changes make_name to be use randomness better relative to its 32 bit seed parameter; I'm not sure if it will be qualitatively noticeable but the old behavior is recoverable if necessary. --- crawl-ref/source/domino.h | 8 +++--- crawl-ref/source/item-name.cc | 53 ++++++++++++++++++----------------- crawl-ref/source/pcg.h | 1 + crawl-ref/source/random.cc | 49 ++++++++++++++++++++++++-------- crawl-ref/source/random.h | 16 +++++++++++ crawl-ref/source/rng-type.h | 1 + crawl-ref/source/tileview.cc | 9 +++--- 7 files changed, 91 insertions(+), 46 deletions(-) diff --git a/crawl-ref/source/domino.h b/crawl-ref/source/domino.h index e2deb554f931..4e3d94cfed43 100644 --- a/crawl-ref/source/domino.h +++ b/crawl-ref/source/domino.h @@ -441,7 +441,7 @@ class DominoSet tiling[pt] = choices[0]; } else - tiling[pt] = rng() % adjacencies_.size(); + tiling[pt] = rng(adjacencies_.size()); has_conflicts |= Conflicts(pt, tiling); } @@ -475,7 +475,7 @@ class DominoSet tiling[pt] = choices[0]; } else - tiling[pt] = rng() % adjacencies_.size(); + tiling[pt] = rng(adjacencies_.size()); int after = Conflicts(pt, tiling); if (after >= conflicts) @@ -574,13 +574,13 @@ class DominoSet for (int y = -sz; y <= sz; ++y) { Point nb = {pt.x + x, pt.y + y}; - if (tiling.find(nb) != tiling.end() && rng() % 2) + if (tiling.find(nb) != tiling.end() && rng(2)) shuffle.insert(nb); } } } for (auto itr : shuffle) - tiling[itr] = rng() % adjacencies_.size(); + tiling[itr] = rng(adjacencies_.size()); } int Conflicts(Point pt, const std::map& tiling) const diff --git a/crawl-ref/source/item-name.cc b/crawl-ref/source/item-name.cc index 5decf9549129..76080da73020 100644 --- a/crawl-ref/source/item-name.cc +++ b/crawl-ref/source/item-name.cc @@ -15,7 +15,6 @@ #include "areas.h" #include "artefact.h" #include "art-enum.h" -#include "pcg.h" // for make_name()'s use #include "branch.h" #include "butcher.h" #include "cio.h" @@ -61,8 +60,8 @@ #include "viewgeom.h" static bool _is_consonant(char let); -static char _random_vowel(uint32_t seed); -static char _random_cons(uint32_t seed); +static char _random_vowel(); +static char _random_cons(); static string _random_consonant_set(size_t seed); static void _maybe_identify_pack_item() @@ -2746,7 +2745,7 @@ const size_t RCS_END = RCS_EM; * * @param seed The seed to generate the name from. * The same seed will always generate the same name. - * By default a random number from the RNG. + * By default a random number from the current RNG. * @param name_type The type of name to be generated. * If MNAME_SCROLL, increase length by 6 and force to allcaps. * If MNAME_JIYVA, start with J, do not generate spaces, @@ -2758,16 +2757,18 @@ const size_t RCS_END = RCS_EM; */ string make_name(uint32_t seed, makename_type name_type) { - // TODO: better conversion of the seed to 64 bits - rng::PcgRNG rng = rng::PcgRNG(static_cast(seed)); + // use the seed to select sequence, rather than seed per se. This is + // because it is not important that the sequence be randomly distributed + // in uint64_t. + rng::subgenerator subgen(you.game_seed, static_cast(seed)); string name; bool has_space = false; // Keep track of whether the name contains a space. size_t len = 3; - len += rng.get_uint32() % 5; - len += (rng.get_uint32() % 5 == 0) ? rng.get_uint32() % 6 : 1; + len += random2(5); + len += (random2(5) == 0) ? random2(6) : 1; if (name_type == MNAME_SCROLL) // scrolls have longer names len += 6; @@ -2792,11 +2793,11 @@ string make_name(uint32_t seed, makename_type name_type) else if (name.empty() || prev_char == ' ') { // Start the word with any letter. - name += 'a' + (rng.get_uint32() % 26); + name += 'a' + random2(26); } else if (!has_space && name_type != MNAME_JIYVA && name.length() > 5 && name.length() < len - 4 - && rng.get_uint32() % 5 != 0) // 4/5 chance + && random2(5) != 0) // 4/5 chance { // Hand out a space. name += ' '; @@ -2806,10 +2807,10 @@ string make_name(uint32_t seed, makename_type name_type) || (name.length() > 1 && !_is_consonant(prev_char) && _is_consonant(penult_char) - && rng.get_uint32() % 5 <= 1))) // 2/5 + && random2(5) <= 1))) // 2/5 { // Place a vowel. - const char vowel = _random_vowel(rng.get_uint32()); + const char vowel = _random_vowel(); if (vowel == ' ') { @@ -2833,7 +2834,7 @@ string make_name(uint32_t seed, makename_type name_type) else if (name.length() > 1 && vowel == prev_char && (vowel == 'y' || vowel == 'i' - || rng.get_uint32() % 5 <= 1)) + || random2(5) <= 1)) { // Replace the vowel with something else if the previous // letter was the same, and it's a 'y', 'i' or with 2/5 chance. @@ -2850,7 +2851,7 @@ string make_name(uint32_t seed, makename_type name_type) // Use one of number of predefined letter combinations. if ((len > 3 || !name.empty()) - && rng.get_uint32() % 7 <= 1 // 2/7 chance + && random2(7) <= 1 // 2/7 chance && (!beg || !end)) { const int first = (beg ? RCS_BB : (end ? RCS_BE : RCS_BM)); @@ -2858,7 +2859,7 @@ string make_name(uint32_t seed, makename_type name_type) const int range = last - first; - const int cons_seed = rng.get_uint32() % range + first; + const int cons_seed = random2(range) + first; const string consonant_set = _random_consonant_set(cons_seed); @@ -2869,7 +2870,7 @@ string make_name(uint32_t seed, makename_type name_type) else // Place a single letter instead. { // Pick a random consonant. - name += _random_cons(rng.get_uint32()); + name += _random_cons(); } } @@ -2888,10 +2889,10 @@ string make_name(uint32_t seed, makename_type name_type) && !_is_consonant(name[name.length() - 1]) && (name.length() < len // early exit || (len < 8 - && rng.get_uint32() % 3 != 0))) // 2/3 chance for other short names + && random2(3) != 0))) // 2/3 chance for other short names { // Specifically, add a consonant. - name += _random_cons(rng.get_uint32()); + name += _random_cons(); } if (maxlen != SIZE_MAX) @@ -2903,7 +2904,7 @@ string make_name(uint32_t seed, makename_type name_type) { // convolute & recurse if (name_type == MNAME_JIYVA) - return make_name(rng.get_uint32(), MNAME_JIYVA); + return make_name(rng::get_uint32(), MNAME_JIYVA); name = "plog"; } @@ -2940,18 +2941,18 @@ static bool _is_consonant(char let) // Returns a random vowel (a, e, i, o, u with equal probability) or space // or 'y' with lower chances. -static char _random_vowel(uint32_t seed) +static char _random_vowel() { static const char vowels[] = "aeiouaeiouaeiouy "; - return vowels[ seed % (sizeof(vowels) - 1) ]; + return vowels[random2(sizeof(vowels) - 1)]; } // Returns a random consonant with not quite equal probability. // Does not include 'y'. -static char _random_cons(uint32_t seed) +static char _random_cons() { static const char consonants[] = "bcdfghjklmnpqrstvwxzcdfghlmnrstlmnrst"; - return consonants[ seed % (sizeof(consonants) - 1) ]; + return consonants[random2(sizeof(consonants) - 1)]; } /** @@ -2963,7 +2964,7 @@ static char _random_cons(uint32_t seed) * @return A random length 2 or 3 consonant set; e.g. "kl", "str", etc. * If the seed is out of bounds, return ""; */ -static string _random_consonant_set(size_t seed) +static string _random_consonant_set(size_t c) { // Pick a random combination of consonants from the set below. // begin -> [RCS_BB, RCS_EB) = [ 0, 27) @@ -2993,9 +2994,9 @@ static string _random_consonant_set(size_t seed) }; COMPILE_CHECK(ARRAYSZ(consonant_sets) == RCS_END); - ASSERT_RANGE(seed, 0, ARRAYSZ(consonant_sets)); + ASSERT_RANGE(c, 0, ARRAYSZ(consonant_sets)); - return consonant_sets[seed]; + return consonant_sets[c]; } /** diff --git a/crawl-ref/source/pcg.h b/crawl-ref/source/pcg.h index 5620550c5287..05670fcb774e 100644 --- a/crawl-ref/source/pcg.h +++ b/crawl-ref/source/pcg.h @@ -15,6 +15,7 @@ namespace rng uint32_t get_bounded_uint32(uint32_t bound); uint64_t get_uint64(); uint32_t operator()() { return get_uint32(); } + uint32_t operator()(uint32_t bound) { return get_bounded_uint32(bound); } typedef uint32_t result_type; static constexpr uint32_t min() { return 0; } diff --git a/crawl-ref/source/random.cc b/crawl-ref/source/random.cc index c0ddbc732418..1527f40c9276 100644 --- a/crawl-ref/source/random.cc +++ b/crawl-ref/source/random.cc @@ -24,6 +24,8 @@ namespace rng // temporary rng state static rng_type _generator = rng::GAMEPLAY; + // TODO: once we have c++17, convert to type optional + static PcgRNG * _sub_generator = nullptr; CrawlVector generators_to_vector() { @@ -77,35 +79,58 @@ namespace rng _generator = previous; } - PcgRNG ¤t_generator() + subgenerator::subgenerator(uint64_t seed, uint64_t sequence) + : current(seed, sequence), + previous(_sub_generator), + previous_main(_generator) { - return _global_state[_generator]; + _generator = rng::SUB_GENERATOR; + _sub_generator = ¤t; } - uint32_t get_uint32(rng_type generator) + subgenerator::~subgenerator() { - return _global_state[generator].get_uint32(); + _generator = previous_main; + _sub_generator = previous; } - uint32_t get_uint32() + subgenerator::subgenerator(uint64_t seed) + : subgenerator(seed, get_uint64()) + { } + + subgenerator::subgenerator() + : subgenerator(get_uint64(), get_uint64()) + { } + + PcgRNG *get_generator(rng_type r) { - return get_uint32(_generator); + if (_generator == SUB_GENERATOR) + return _sub_generator; + else + return &_global_state[_generator]; } - uint32_t peek_uint32() + PcgRNG ¤t_generator() { - PcgRNG tmp = _global_state[_generator]; - return tmp.get_uint32(); + PcgRNG *ret = get_generator(_generator); + ASSERT(ret); + return *ret; } - uint64_t get_uint64(rng_type generator) + uint32_t get_uint32() + { + return current_generator().get_uint32(); + } + + uint32_t peek_uint32() { - return _global_state[generator].get_uint64(); + PcgRNG tmp = current_generator(); // make a copy + return tmp.get_uint32(); } uint64_t get_uint64() { - return get_uint64(_generator); + return current_generator().get_uint64(); } static void _do_seeding(PcgRNG &master) diff --git a/crawl-ref/source/random.h b/crawl-ref/source/random.h index 36da2700c96c..f72632d981b4 100644 --- a/crawl-ref/source/random.h +++ b/crawl-ref/source/random.h @@ -7,6 +7,7 @@ #include "hash.h" #include "rng-type.h" +#include "pcg.h" class CrawlVector; @@ -22,9 +23,24 @@ namespace rng rng_type previous; }; + class subgenerator + { + public: + subgenerator(); + subgenerator(uint64_t seed); + subgenerator(uint64_t seed, uint64_t sequence); + ~subgenerator(); + private: + PcgRNG current; + PcgRNG *previous; + rng_type previous_main; + }; + CrawlVector generators_to_vector(); void load_generators(const CrawlVector &v); vector get_states(); + PcgRNG *get_generator(rng_type r); + PcgRNG ¤t_generator(); void seed(); void seed(uint64_t seed); diff --git a/crawl-ref/source/rng-type.h b/crawl-ref/source/rng-type.h index 04ca5b702f43..1d8018a0600b 100644 --- a/crawl-ref/source/rng-type.h +++ b/crawl-ref/source/rng-type.h @@ -11,5 +11,6 @@ namespace rng SPARE3, LEVELGEN, // branch 0, i.e. the dungeon NUM_RNGS = LEVELGEN + NUM_BRANCHES, // and then one for each other branch + SUB_GENERATOR, // unsaved -- past NUM_RNGS }; } diff --git a/crawl-ref/source/tileview.cc b/crawl-ref/source/tileview.cc index b43aa2d5bb5f..5dadb4a0f38b 100644 --- a/crawl-ref/source/tileview.cc +++ b/crawl-ref/source/tileview.cc @@ -315,8 +315,7 @@ void tile_init_flavour() vector output; { -<<<<<<< HEAD - rng::PcgRNG rng( + rng::subgenerator sub_rng( static_cast(you.where_are_you ^ you.game_seed), static_cast(you.depth)); @@ -324,13 +323,15 @@ void tile_init_flavour() { output.reserve(X_WIDTH * Y_WIDTH); domino::DominoSet dominoes(domino::cohen_set, 8); - dominoes.Generate(X_WIDTH, Y_WIDTH, output, rng); + // TODO: don't pass a PcgRNG object + dominoes.Generate(X_WIDTH, Y_WIDTH, output, + rng::current_generator()); } else { output.resize(X_WIDTH * Y_WIDTH); for (auto &o : output) - o = rng(); + o = rng::get_uint32(); } } for (rectangle_iterator ri(0); ri; ++ri) From a46ea00bafb01708cc34ccf3bc913984991b3f9a Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 1 May 2019 18:07:17 -0400 Subject: [PATCH 553/864] Remove almost all instances of you.unrands This technique for controlling unrand placement has a bad interaction with incremental pregen. Basically, any change to item placement in a vault description can impact rng state, and it's a bit hard to keep these effects limited. (Though possibly, uses of this technique that replace exactly one unrand with exactly one other thing might be more or less ok.) With full pregen, this is not an issue, because dungeon unrand selection is done before the player can do anything. With incremental pregen, because unrands can be generated by acquirement, any such generation can the effect levels that are in the future. Crawl already did some automatic fallback placement for unrands that were not wrapped in you.unrands checks: if unrand placement fails, it placed an unrand with the same base type and subtype. However, in various cases vault designers wanted something more specific. To solve this problem, this commit makes the following changes: 1. Item generation all happens on a sub-generator, so all single items make exactly the same number of draws from the level's rng (4). This means that fallback placement as described above doesn't affect the rng over and above regular unrand placement. 2. The vast majority of uses of you.unrands in vault design just tweaked what would happen without a lua check slightly, by adding a brand or changing the subtype. I've enhanced the syntax of art-data.txt to allow explicit specification of fallback type and subtype (e.g. so things like Glaive of the Guard can place as a bardiche), as well as allowing specification of a brand for the fallback. Before, item generation didn't try to mimic the unrand's brand, but now it does. Nearly everything that was previously done with you.unrands in lua can now be done with the new syntax in art-data.txt, in a more generalized way. Most of the time I took the fallback details from specific vaults. In a few cases, the logic that this replaces was complicated enough that I didn't try to reproduce it exactly, but I really don't think that most of these extra complicated cases added much. So, here's an example of what should happen. Suppose the old item spec looked like this: ``` : if you.unrands("frostbite") then KITEM: 2 = executioner's axe ego:freezing randart ident:type / \ battleaxe ego:freezing randart ident:type / \ broad axe ego:freezing randart ident:type : else KITEM: 2 = frostbite / \ battleaxe ego:freezing randart ident:type / \ broad axe ego:freezing randart ident:type : end ``` This has been replaced by the following, which now accomplishes exactly the same thing: KITEM: 2 = frostbite / \ battleaxe ego:freezing randart ident:type / \ broad axe ego:freezing randart ident:type If frostbite has already generated, and the vault rolls the first item in this list, then it will generate a fallback randart of the same type and subtype (exec axe). In fact this would have already happened with this item spec before this commit. Because frostbite specifies a brand (SPWPN_FREEZING), the randart will pick this up as well (this part is new). Because all this is partitioned off from the levelgen rng, nothing else about a level should change beyond the substitution of an unrand with a similar randart. There's still some details not in this commit; in particular there're a few shops that still use you.unrands that I'll address in a separate commit. --- crawl-ref/docs/develop/levels/syntax.txt | 6 +- crawl-ref/source/art-data.txt | 50 ++++++ crawl-ref/source/artefact.cc | 6 + crawl-ref/source/artefact.h | 3 + crawl-ref/source/dat/des/branches/elf.des | 4 - crawl-ref/source/dat/des/branches/lair.des | 6 - .../dat/des/branches/vaults_rooms_hard.des | 14 +- crawl-ref/source/dat/des/portals/wizlab.des | 4 - crawl-ref/source/dat/des/variable/float.des | 53 +------ .../source/dat/des/variable/mini_monsters.des | 63 +------- crawl-ref/source/dat/dlua/ghost.lua | 9 +- crawl-ref/source/items.cc | 2 + crawl-ref/source/makeitem.cc | 144 ++++++++++++++---- crawl-ref/source/mon-gear.cc | 2 + crawl-ref/source/util/art-data.pl | 41 ++++- crawl-ref/source/wiz-item.cc | 59 +++++-- crawl-ref/source/wiz-item.h | 2 +- crawl-ref/source/wizard.cc | 4 +- 18 files changed, 293 insertions(+), 179 deletions(-) diff --git a/crawl-ref/docs/develop/levels/syntax.txt b/crawl-ref/docs/develop/levels/syntax.txt index 1b087ea1c346..607bf212092f 100644 --- a/crawl-ref/docs/develop/levels/syntax.txt +++ b/crawl-ref/docs/develop/levels/syntax.txt @@ -634,9 +634,9 @@ ITEM: (list of items, separated by comma) will be created instead. Staff unrands, since they have no corresponding type that can be transformed into a randart, are replaced by an appropriate magical staff. (E.g. a staff of poison.) - The lua function you.unrands() ('you.unrands("scythe of curses")') - can be used to check whether an unrand has already been seen, if - you don't want to use the default fallback. + You should not use `you.unrands` to check whether an unrand has been + seen in normal levelgen scenarios, as it will impact seeding. Some + details about default fallbacks can be specified in art-data.txt. Randart spell books ------------------- diff --git a/crawl-ref/source/art-data.txt b/crawl-ref/source/art-data.txt index e8bded931609..d43375735ffa 100644 --- a/crawl-ref/source/art-data.txt +++ b/crawl-ref/source/art-data.txt @@ -123,6 +123,11 @@ # PLUS: The pluses of the artefact. +# FALLBACK: if an artifact has already generated, the builder instead usually +# creates a randart with the same base type. This field allows overriding the +# base type for certain special cases (e.g. if a randart's special properties +# put it on par with a much stronger base type). + ##### # Explanation of normal fields: @@ -160,6 +165,7 @@ ENUM: DUMMY1 NAME: DUMMY UNRANDART 1 OBJ: OBJ_UNASSIGNED/250 +FALLBACK: OBJ_UNASSIGNED/250 PLUS: 250 COLOUR: BLACK @@ -177,6 +183,7 @@ BRAND: SPWPN_VORPAL NAME: Wrath of Trog OBJ: OBJ_WEAPONS/WPN_BATTLEAXE +FALLBACK: OBJ_WEAPONS/WPN_EXECUTIONERS_AXE PLUS: +8 COLOUR: ETC_BLOOD TILE: spwpn_wrath_of_trog @@ -187,6 +194,7 @@ BRAND: SPWPN_ANTIMAGIC NAME: mace of Variability OBJ: OBJ_WEAPONS/WPN_GREAT_MACE +FALLBACK: OBJ_WEAPONS/OBJ_RANDOM INSCRIP: chain chaos PLUS: +7 COLOUR: ETC_RANDOM @@ -207,6 +215,7 @@ BRAND: SPWPN_VORPAL NAME: sword of Power OBJ: OBJ_WEAPONS/WPN_GREAT_SWORD +FB_BRAND: SPWPN_VORPAL PLUS: +0 # Set on wield COLOUR: RED TILE: spwpn_sword_of_power @@ -235,6 +244,7 @@ VALUE: 1000 NAME: Vampire's Tooth OBJ: OBJ_WEAPONS/WPN_QUICK_BLADE # it's a quick blade made from a tooth -> no TYPE +FB_BRAND: SPWPN_VAMPIRISM PLUS: +12 COLOUR: ETC_BONE TILE: spwpn_vampires_tooth @@ -270,6 +280,7 @@ COLOUR: ETC_BONE TILE: spwpn_sword_of_zonguldrok TILE_EQ: zonguldrok BRAND: SPWPN_REAPING +FB_BRAND: SPWPN_PAIN VALUE: 800 BOOL: evil, corpse_violating @@ -405,6 +416,8 @@ COLOUR: ETC_SLIME TILE: urand_punk TILE_EQ: punk BRAND: SPWPN_ACID +# random fallback brand +FB_BRAND: SPWPN_NORMAL BOOL: rCorr NAME: longbow "Zephyr" @@ -428,6 +441,7 @@ STR: 7 NAME: glaive of the Guard OBJ: OBJ_WEAPONS/WPN_GLAIVE +FALLBACK: OBJ_WEAPONS/WPN_BARDICHE PLUS: +8 COLOUR: ETC_ELECTRICITY TILE: urand_guard @@ -443,6 +457,7 @@ PLUS: +10 COLOUR: ETC_HOLY TILE: unrand_zealot_sword TILE_EQ: zealot_sword +# fallback places a randart eudemon blade! BRAND: SPWPN_HOLY_WRATH EV: 3 ANGRY: 5 @@ -451,6 +466,7 @@ LIFE: 1 NAME: arbalest "Damnation" INSCRIP: damnation, OBJ: OBJ_WEAPONS/WPN_ARBALEST +FB_BRAND: SPWPN_FLAMING PLUS: +6 COLOUR: ETC_FIRE TILE: urand_damnation @@ -492,6 +508,7 @@ COLOUR: ETC_UNHOLY TILE: urand_botono TILE_EQ: botono BRAND: SPWPN_REAPING +FB_BRAND: SPWPN_PAIN HP: -6 LIFE: 1 BOOL: poison, nogen @@ -517,6 +534,8 @@ MAGIC: 1 NAME: Elemental Staff OBJ: OBJ_WEAPONS/WPN_STAFF +FALLBACK: OBJ_WEAPONS/WPN_LAJATANG +FB_BRAND: SPWPN_FREEZING PLUS: +3 COLOUR: DARKGREY TILE: urand_elemental @@ -555,6 +574,8 @@ ENUM: BLOWGUN_ASSASSIN NAME: blowgun of the Assassin INSCRIP: stab, OBJ: OBJ_WEAPONS/WPN_BLOWGUN +# fallback is just to prevent errors +FALLBACK: OBJ_WEAPONS/WPN_LONGBOW PLUS: +6 COLOUR: ETC_DEATH TILE: urand_blowgun @@ -564,6 +585,8 @@ BOOL: inv, tilerim, nogen NAME: lance "Wyrmbane" OBJ: OBJ_WEAPONS/WPN_SPEAR +FALLBACK: OBJ_WEAPONS/WPN_DEMON_TRIDENT +FB_BRAND: SPWPN_VORPAL INSCRIP: slay drac, TYPE: lance BASE_DAM: +2 @@ -589,6 +612,7 @@ STEALTH: 1 NAME: plutonium sword OBJ: OBJ_WEAPONS/WPN_TRIPLE_SWORD +FB_BRAND: SPWPN_CHAOS PLUS: +11 COLOUR: ETC_MUTAGENIC TILE: urand_plutonium @@ -600,6 +624,7 @@ VALUE: 1000 NAME: great mace "Undeadhunter" INSCRIP: disrupt, OBJ: OBJ_WEAPONS/WPN_GREAT_MACE +FB_BRAND: SPWPN_HOLY_WRATH PLUS: +7 COLOUR: LIGHTGREY TILE: urand_undeadhunter @@ -608,6 +633,7 @@ LIFE: 1 NAME: whip "Snakebite" OBJ: OBJ_WEAPONS/WPN_WHIP +FALLBACK: OBJ_WEAPONS/WPN_DEMON_WHIP INSCRIP: curare, PLUS: +8 COLOUR: DARKGREY @@ -679,6 +705,7 @@ DEX: 4 NAME: cloak of the Thief OBJ: OBJ_ARMOUR/ARM_CLOAK +FB_BRAND: SPARM_INVISIBILITY INSCRIP: +Fog PLUS: +2 COLOUR: ETC_DARK @@ -700,6 +727,7 @@ BOOL: nogen NAME: crown of Dyrovepreva OBJ: OBJ_ARMOUR/ARM_HAT +FB_BRAND: SPARM_SEE_INVISIBLE PLUS: +3 COLOUR: ETC_JEWEL TILE: urand_dyrovepreva @@ -713,6 +741,7 @@ PLUS: +2 COLOUR: DARKGREY TILE: urand_bear TILE_EQ: bear +# TODO: why isn't this brand working on the fallback? BRAND: SPARM_SPIRIT_SHIELD BOOL: berserk MAGIC: 2 @@ -720,6 +749,8 @@ LIFE: 1 NAME: robe of Misfortune OBJ: OBJ_ARMOUR/ARM_ROBE +# try to make it bad, this is the only bad SPARM: +FB_BRAND: SPARM_PONDEROUSNESS PLUS: 5 COLOUR: LIGHTMAGENTA TILE: urand_misfortune @@ -740,6 +771,7 @@ BOOL: fly, nogen ENUM: BOOTS_ASSASSIN NAME: boots of the Assassin OBJ: OBJ_ARMOUR/ARM_BOOTS +FB_BRAND: SPARM_STEALTH INSCRIP: Detection Stab+ PLUS: +2 COLOUR: BROWN @@ -751,6 +783,7 @@ VALUE: 600 ENUM: LEAR NAME: Lear's hauberk OBJ: OBJ_ARMOUR/ARM_CHAIN_MAIL +FALLBACK: OBJ_ARMOUR/ARM_PLATE_ARMOUR PLUS: 27 COLOUR: ETC_GOLD TILE: urand_lear @@ -759,6 +792,9 @@ BOOL: special NAME: skin of Zhor OBJ: OBJ_ARMOUR/ARM_ANIMAL_SKIN +# because animal skins count as "mundane" use something else to ensure a randart +# is generated; this isn't a great match: +FALLBACK: OBJ_ARMOUR/ARM_STEAM_DRAGON_ARMOUR PLUS: +4 COLOUR: BROWN TILE: urand_zhor @@ -770,6 +806,7 @@ INSCRIP: Hibernate ENUM: SALAMANDER NAME: salamander hide armour OBJ: OBJ_ARMOUR/ARM_LEATHER_ARMOUR +FB_BRAND: SPARM_FIRE_RESISTANCE PLUS: +3 COLOUR: ETC_FIRE TILE: urand_salamander @@ -827,6 +864,7 @@ BOOL: seeinv NAME: robe of Night OBJ: OBJ_ARMOUR/ARM_ROBE +# there's not a very appropriate fallback brand that works on robes... PLUS: +5 INSCRIP: Dark COLOUR: ETC_DARK @@ -893,6 +931,7 @@ BOOL: poison NAME: shield of the Gong OBJ: OBJ_ARMOUR/ARM_SHIELD +FALLBACK: OBJ_ARMOUR/ARM_LARGE_SHIELD PLUS: +18 COLOUR: ETC_GOLD TILE: urand_gong @@ -999,6 +1038,7 @@ COLOUR: ETC_UNHOLY TILE: spwpn_demon_axe TILE_EQ: demon_axe BRAND: SPWPN_VORPAL +FB_BRAND: SPWPN_PAIN BOOL: evil, seeinv, fly, curse NAME: lightning scales @@ -1029,6 +1069,7 @@ TILE: urand_vitality NAME: autumn katana OBJ: OBJ_WEAPONS/WPN_LONG_SWORD +FALLBACK: OBJ_WEAPONS/WPN_DOUBLE_SWORD TYPE: katana TILE: urand_katana TILE_EQ: katana_slant @@ -1043,6 +1084,8 @@ BRAND: SPWPN_VORPAL NAME: shillelagh "Devastator" INSCRIP: shatter OBJ: OBJ_WEAPONS/WPN_CLUB +FALLBACK: OBJ_WEAPONS/WPN_EVENINGSTAR +FB_BRAND: SPWPN_VORPAL TYPE: shillelagh TILE: urand_shillelagh TILE_EQ: shillelagh @@ -1145,6 +1188,8 @@ BOOL: nogen NAME: arc blade INSCRIP: discharge, OBJ: OBJ_WEAPONS/WPN_RAPIER +FALLBACK: OBJ_WEAPONS/WPN_QUICK_BLADE +FB_BRAND: SPWPN_ELECTROCUTION PLUS: +8 COLOUR: ETC_ELECTRICITY TILE: urand_arc_blade @@ -1165,6 +1210,8 @@ MAGIC: 1 NAME: lajatang of Order INSCRIP: silver, OBJ: OBJ_WEAPONS/WPN_LAJATANG +# not really comparable... +FB_BRAND: SPWPN_HOLY_WRATH COLOUR: ETC_SILVER TILE: urand_order TILE_EQ: order @@ -1191,12 +1238,14 @@ TILE_EQ: orange_crystal PLUS: 8 INT: 3 BRAND: SPARM_ARCHMAGI +FB_BRAND: SPWPN_NORMAL BOOL: clarity ENUM: MAJIN NAME: Majin-Bo INSCRIP: Archmagi OBJ: OBJ_WEAPONS/WPN_QUARTERSTAFF +FALLBACK: OBJ_WEAPONS/WPN_LAJATANG PLUS: +6 COLOUR: ETC_UNHOLY TILE: spwpn_majin @@ -1214,6 +1263,7 @@ TILE: urand_gyre TILE_EQ: gyre PLUS: 7 BRAND: SPWPN_PROTECTION +FB_BRAND: SPWPN_VORPAL ENUM: ETHERIC_CAGE NAME: Maxwell's etheric cage diff --git a/crawl-ref/source/artefact.cc b/crawl-ref/source/artefact.cc index 98f9161c5d0a..08b471dfcfae 100644 --- a/crawl-ref/source/artefact.cc +++ b/crawl-ref/source/artefact.cc @@ -460,6 +460,12 @@ static void _add_randart_weapon_brand(const item_def &item, { const int item_type = item.sub_type; + if (!is_weapon_brand_ok(item_type, item_props[ARTP_BRAND], true)) + item_props[ARTP_BRAND] = SPWPN_NORMAL; + + if (item_props[ARTP_BRAND] != SPWPN_NORMAL) + return; + if (is_range_weapon(item)) { item_props[ARTP_BRAND] = random_choose_weighted( diff --git a/crawl-ref/source/artefact.h b/crawl-ref/source/artefact.h index f8e71fcbc2cb..97188487ad20 100644 --- a/crawl-ref/source/artefact.h +++ b/crawl-ref/source/artefact.h @@ -52,6 +52,9 @@ struct unrandart_entry object_class_type base_type; uint8_t sub_type; + object_class_type fallback_base_type; + uint8_t fallback_sub_type; + int fallback_brand; short plus; short plus2; colour_t colour; diff --git a/crawl-ref/source/dat/des/branches/elf.des b/crawl-ref/source/dat/des/branches/elf.des index 6766fd64fdf2..5e9122d1f041 100644 --- a/crawl-ref/source/dat/des/branches/elf.des +++ b/crawl-ref/source/dat/des/branches/elf.des @@ -1275,11 +1275,7 @@ ENDMAP NAME: minmay_guarded_unrand_folly DEPTH: Elf ORIENT: float -: if you.unrands("robe_of_folly") then -ITEM: robe randart no_pickup -: else ITEM: robe_of_folly no_pickup -: end MONS: deep elf sorcerer / deep elf annihilator NSUBST: 1 = 2:2 / 5=1.. / . SUBST: 2 = 1. diff --git a/crawl-ref/source/dat/des/branches/lair.des b/crawl-ref/source/dat/des/branches/lair.des index 442e915e69a1..733c44d7f3ff 100644 --- a/crawl-ref/source/dat/des/branches/lair.des +++ b/crawl-ref/source/dat/des/branches/lair.des @@ -2379,13 +2379,7 @@ NAME: minmay_guarded_unrand_snakebite TAGS: ruin DEPTH: Lair ORIENT: southeast -: if you.unrands("snakebite") then -# A randart venom demon whip is unlikely to be useful -# for someone with snakebite, so just do this -ITEM: demon whip good_item -: else ITEM: snakebite no_pickup -: end KMONS: A = adder KMONS: B = water moccasin KMONS: C = black mamba diff --git a/crawl-ref/source/dat/des/branches/vaults_rooms_hard.des b/crawl-ref/source/dat/des/branches/vaults_rooms_hard.des index 5d914855b019..8448a1ff5008 100644 --- a/crawl-ref/source/dat/des/branches/vaults_rooms_hard.des +++ b/crawl-ref/source/dat/des/branches/vaults_rooms_hard.des @@ -1276,11 +1276,7 @@ ENDMAP NAME: minmay_guarded_unrand_guard_vaults TAGS: vaults_hard vaults_orient_n WEIGHT: 3 -: if you.unrands("glaive_of_the_guard") then -ITEM: bardiche randart no_pickup -: else ITEM: glaive_of_the_guard no_pickup -: end SUBST: b : bxcmG.T NSUBST: 3:9 / 4=9. / ., 8 = 2:8 / 6=8.. / . MAP @@ -1304,15 +1300,9 @@ ENDMAP NAME: minmay_guarded_unrand_secular_launcher TAGS: vaults_hard vaults_orient_s WEIGHT: 3 -: if you.unrands("sniper") and you.unrands("storm_bow") then -ITEM: triple crossbow randart no_pickup / longbow randart no_pickup -: elseif you.unrands("sniper") then -ITEM: storm_bow no_pickup -: elseif you.unrands("storm_bow") then -ITEM: sniper no_pickup -: else +# n.b. if one of these has generated, this may fall back on a randart. If both +# have generated, it is guaranteed to. ITEM: storm_bow no_pickup / sniper no_pickup -: end NSUBST: 3:9 / 6=9. / ., 8 = 2:8 / 6=8.. / . MAP vvvvv diff --git a/crawl-ref/source/dat/des/portals/wizlab.des b/crawl-ref/source/dat/des/portals/wizlab.des index 262148f52405..2a8aac3c26fe 100644 --- a/crawl-ref/source/dat/des/portals/wizlab.des +++ b/crawl-ref/source/dat/des/portals/wizlab.des @@ -881,11 +881,7 @@ KMONS: & = col:mutagenic primal ox-sting-weird mutant beast \ name:Cigotuvi's_Monster name_replace tile:mons_cigotuvis_monster ITEM: potion of mutation ITEM: potion of mutation q:1, potion of mutation -: if you.unrands("hat of the alchemist") then -ITEM: any jewellery randart -: else ITEM: any jewellery randart / w:5 hat_of_the_alchemist -: end ITEM: randbook disc:transmutation disc2:necromancy owner:Cigotuvi ITEM: book of transfigurations / randbook disc:transmutation ITEM: staff of death, scroll of summoning diff --git a/crawl-ref/source/dat/des/variable/float.des b/crawl-ref/source/dat/des/variable/float.des index 73fd5f6f8050..d728e10ad11a 100644 --- a/crawl-ref/source/dat/des/variable/float.des +++ b/crawl-ref/source/dat/des/variable/float.des @@ -3245,11 +3245,7 @@ KMONS: 2 = shock serpent / storm dragon ITEM: book of air / book of the sky / manual of air magic / \ staff of air ident:type / lightning rod w:15 / fan of gales w:15 / \ storm dragon scales w:5 -: if you.unrands("arc blade") then -KITEM: 2 = quick blade ego:electrocution randart ident:type -: else -KITEM: 2 = arc_blade -: end +KITEM: 2 = arc_blade ident:type : minmay_elemental_octagon_setup(_G) MAP xxx@xxx @@ -3277,11 +3273,7 @@ KMONS: 2 = stone giant / iron dragon ITEM: book of geomancy / book of the earth / manual of earth magic / \ staff of earth ident:type / ring of protection ident:type / \ wand of scattershot ident:type / crystal plate armour w:5 -: if you.unrands("devastator") then -KITEM: 2 = eveningstar randart -: else KITEM: 2 = devastator -: end : minmay_elemental_octagon_setup(_G) MAP xxx@xxx @@ -3309,15 +3301,9 @@ KMONS: 2 = frost giant / ice dragon ITEM: book of frost / book of ice / manual of ice magic / \ wand of iceblast ident:type / staff of cold ident:type / \ ring of ice ident:type / phial of floods / ice dragon scales w:5 -: if you.unrands("frostbite") then -KITEM: 2 = executioner's axe ego:freezing randart ident:type / \ - battleaxe ego:freezing randart ident:type / \ - broad axe ego:freezing randart ident:type -: else -KITEM: 2 = frostbite / \ +KITEM: 2 = frostbite ident:type / \ battleaxe ego:freezing randart ident:type / \ broad axe ego:freezing randart ident:type -: end : minmay_elemental_octagon_setup(_G) MAP xxx@xxx @@ -3345,11 +3331,7 @@ KMONS: 2 = fire giant / fire dragon ITEM: book of flames / book of fire / manual of fire magic / \ staff of fire ident:type / ring of fire ident:type / lamp of fire / \ fire dragon scales w:5 -: if you.unrands("firestarter") then -KITEM: 2 = great mace ego:flaming randart ident:type -: else -KITEM: 2 = firestarter -: end +KITEM: 2 = firestarter ident:type : minmay_elemental_octagon_setup(_G) MAP xxx@xxx @@ -3374,12 +3356,7 @@ ORIENT: float DEPTH: Depths, Crypt MONS: necromancer / vampire mage MONS: lich / ancient lich w:5 -: if you.unrands("majin-bo") then -ITEM: quarterstaff randart ego:vampirism ident:type no_pickup \ - / good_item lajatang no_pickup -: else -ITEM: majin-bo no_pickup -: end +ITEM: majin-bo no_pickup ident:type ITEM: any magical staff / any book NSUBST: d = 1:d / *:e NSUBST: 1 = 4:1 / 8=1... / . @@ -3408,11 +3385,7 @@ NAME: minmay_guarded_unrand_sceptre_of_torment ORIENT: float DEPTH: Depths, Crypt MONS: mummy priest, greater mummy -: if you.unrands("sceptre_of_torment") then -KITEM: d = any weapon good_item randart no_pickup -: else -KITEM: d = sceptre_of_torment no_pickup -: end +KITEM: d = sceptre_of_torment no_pickup ident:type KMONS: d = greater mummy MAP ccccccccccc@ccccccccccc @@ -3432,11 +3405,7 @@ NAME: minmay_guarded_unrand_sword_of_power ORIENT: float DEPTH: D:13- MONS: vault guard -: if you.unrands("sword_of_power") then -ITEM: any weapon good_item randart no_pickup -: else ITEM: sword_of_power no_pickup -: end MAP vvvvvvvv vv......vv @@ -3454,11 +3423,7 @@ ENDMAP NAME: minmay_guarded_unrand_guard DEPTH: D:12-, Depths:1-4 ORIENT: float -: if you.unrands("glaive_of_the_guard") then -ITEM: bardiche randart no_pickup -: else ITEM: glaive_of_the_guard no_pickup -: end SUBST: b : bxcmG.T NSUBST: 3:9 / 4=9. / ., 8 = 2:8 / 6=8.. / . MAP @@ -9109,13 +9074,7 @@ NAME: emtedronai_trogs_sanctum TAGS: no_monster_gen no_trap_gen no_tele_into no_item_gen DEPTH: D:13-, Depths ORIENT: float -: if not you.unrands("necklace_of_bloodlust") then -KITEM: _ = necklace of bloodlust no_pickup -: elseif not you.unrands("wrath_of_trog") then -KITEM: _ = wrath of trog no_pickup -: else -KITEM: _ = nothing -: end +KITEM: _ = necklace of bloodlust no_pickup / wrath of trog no_pickup ITEM: manual of armour w:30 / manual of fighting w:30 / \ manual of long blades / manual of axes / manual of maces & flails / \ manual of polearms / manual of dodging / manual of shields diff --git a/crawl-ref/source/dat/des/variable/mini_monsters.des b/crawl-ref/source/dat/des/variable/mini_monsters.des index a8ae20f4b118..9bc9c256497e 100644 --- a/crawl-ref/source/dat/des/variable/mini_monsters.des +++ b/crawl-ref/source/dat/des/variable/mini_monsters.des @@ -6709,11 +6709,7 @@ DEPTH: D:12- MONS: deep elf mage / ogre mage / wizard / \ kobold demonologist w:2 / vampire mage w:2 / naga mage w:2 NSUBST: 1 = 6:1 / 10=1.... / . -: if you.unrands("glaive of prune") then -ITEM: any weapon good_item randart no_pickup -: else ITEM: glaive_of_prune no_pickup -: end SUBST: " : .:50 cvbnG SUBST: ' : .:50 cvbnG SUBST: ? : .:50 cvbnG @@ -6748,12 +6744,7 @@ TAGS: transparent DEPTH: D:8- MONS: chaos spawn KFEAT: _ = altar_xom -: if you.unrands("mace of variability") then -# could be a launcher! -ITEM: any weapon good_item randart ego:chaos ident:type no_pickup -: else -ITEM: mace_of_variability no_pickup -: end +ITEM: mace_of_variability no_pickup ident:type # walls are carefully placed and guarantee no islands SUBST: x = xcvbmGwWlTUVYt+ <:4 >:4 A:2 1:160 NSUBST: 1 = 2:1 / 2:% / 3=1%...... / . @@ -6777,12 +6768,8 @@ TAGS: no_monster_gen no_trap_gen transparent MONS: worker ant / soldier ant MONS: killer bee MONS: adder / water moccasin -: if you.unrands("staff_of_olgreb") then -ITEM: young poisoner's handbook / ring of poison resistance ident:type / \ - staff of poison ident:type / swamp dragon scales -: else -ITEM: staff_of_olgreb no_pickup -: end +# TODO: built in fallback for staff of olgreb is kind of dumb +ITEM: staff_of_olgreb no_pickup ident:type NSUBST: 1 = 5:1 / 6=1.. / ., 2 = 5:2 / 9=2.. / ., 3 = 5:3 / 6=1.. / . MAP ... @@ -6820,11 +6807,7 @@ MONS: vampire mosquito / tyrant leech / vampire, vampire knight : else MONS: vampire knight, vampire mage : end -: if you.unrands("vampires_tooth") then -ITEM: quick blade randart no_pickup -: else ITEM: vampires_tooth no_pickup -: end MAP ......... .ccc.ccc. @@ -6842,11 +6825,7 @@ TAGS: transparent DEPTH: D:14-, Depths MONS: spriggan berserker NSUBST: 1 = 3:1 / 9=1...... / . -: if you.unrands("wrath_of_trog") then -ITEM: executioner's axe randart ego:antimagic ident:type no_pickup -: else -ITEM: wrath_of_trog no_pickup -: end +ITEM: wrath_of_trog no_pickup ident:type MAP ....... ..""""".. @@ -6874,12 +6853,7 @@ NSUBST: d = 1:d / *:* MONS: skeletal warrior NSUBST: d = 1:d / *:% : end -: if you.unrands("skullcrusher") then -ITEM: giant club randart ego:speed ident:type no_pickup / \ - giant spiked club randart no_pickup -: else -ITEM: skullcrusher no_pickup -: end +ITEM: skullcrusher no_pickup ident:type NSUBST: ' = 12:1 / 14=1...... / . SUBST: " = 1., ! = 2. MAP @@ -6913,11 +6887,7 @@ NAME: minmay_guarded_unrand_finisher TAGS: transparent DEPTH: D:7-13 MONS: wraith -: if you.unrands("finisher") then -ITEM: scythe randart ego:speed ident:type no_pickup -: else -ITEM: finisher no_pickup -: end +ITEM: finisher no_pickup ident:type SUBST: 1 = 1. NSUBST: A = 1:. / *:c, B = 1:. / *:c SUBST: c = c .:2 @@ -6941,12 +6911,7 @@ NAME: minmay_guarded_unrand_resistance DEPTH: D:9-14 TAGS: no_monster_gen no_trap_gen transparent KMASK: lw = opaque -: if you.unrands("shield_of_resistance") then -ITEM: buckler randart no_pickup / shield randart no_pickup / \ - large shield randart no_pickup -: else ITEM: shield_of_resistance no_pickup -: end MONS: fire dragon, ice dragon MAP ........... @@ -6965,11 +6930,7 @@ ENDMAP NAME: chequers_guarded_unrand_ignorance DEPTH: D:7-12, Orc TAGS: no_monster_gen no_trap_gen transparent -: if you.unrands("large_shield_of_ignorance") then -ITEM: large shield randart no_pickup -: else ITEM: large_shield_of_ignorance no_pickup -: end MONS: orange crystal statue KPROP: .d1 = no_tele_into SUBST: - = . @@ -6990,11 +6951,7 @@ ENDMAP NAME: chequers_guarded_unrand_mask_of_the_dragon DEPTH: Zot, !Zot:$ TAGS: no_monster_gen no_trap_gen -: if you.unrands("mask_of_the_dragon") then -ITEM: hat randart no_pickup -: else ITEM: mask_of_the_dragon no_pickup -: end # Shuffle one transporter destination location NSUBST: r = 1:R / *:- # Randomly swap which transporter is the entrance and the loot locations. @@ -7040,11 +6997,7 @@ ENDMAP NAME: brannock_guarded_unrand_thermic_engine DEPTH: Depths TAGS: no_monster_gen no_item_gen transparent -: if you.unrands("maxwell's_thermic_engine") then -ITEM: demon blade randart no_pickup -: else ITEM: maxwell's_thermic_engine no_pickup -: end MONS: ice devil, blizzard demon, ice fiend MONS: sun demon, balrug, brimstone fiend # 6-2-1, 9 total demons for each side @@ -7068,11 +7021,7 @@ TAGS: no_monster_gen no_item_gen transparent DEPTH: D:5-8 ORIENT: float MONS: rat, river rat, hell rat -: if you.unrands("ratskin_cloak") then -ITEM: cloak randart -: else ITEM: ratskin_cloak -:end NSUBST: - = 8:1 / *:. NSUBST: ' = 6:1 / 4:2 / 2:23 / 1:3 / *:. MAP diff --git a/crawl-ref/source/dat/dlua/ghost.lua b/crawl-ref/source/dat/dlua/ghost.lua index f9121fcf7a06..d17fd09f942d 100644 --- a/crawl-ref/source/dat/dlua/ghost.lua +++ b/crawl-ref/source/dat/dlua/ghost.lua @@ -312,11 +312,10 @@ function setup_xom_dancing_weapon(e) quality = crawl.coinflip() and "good_item" or crawl.coinflip() and "randart" or "" - -- do this check independently of global state so that the effect - -- on the rng is the same either way - local can_try_variability = crawl.one_chance_in(100) - variability = not you.unrands("mace of Variability") - and can_try_variability and "mace of Variability" + + -- if variability has already generated, this will end up with a + -- chaos branded great mace as a backup. + variability = crawl.one_chance_in(100) and "mace of Variability" end -- Make one weapons table with each weapon getting weight by class. diff --git a/crawl-ref/source/items.cc b/crawl-ref/source/items.cc index cddee1e769c8..69635fb172cb 100644 --- a/crawl-ref/source/items.cc +++ b/crawl-ref/source/items.cc @@ -4241,6 +4241,8 @@ static bool _book_from_spell(const char* specs, item_def &item) bool get_item_by_name(item_def *item, const char* specs, object_class_type class_wanted, bool create_for_real) { + // used only for wizmode and item lookup + int type_wanted = -1; int special_wanted = 0; diff --git a/crawl-ref/source/makeitem.cc b/crawl-ref/source/makeitem.cc index 62d92df45c33..d9b2c2989af0 100644 --- a/crawl-ref/source/makeitem.cc +++ b/crawl-ref/source/makeitem.cc @@ -1115,10 +1115,26 @@ static void _generate_armour_item(item_def& item, bool allow_uniques, // Forced randart. if (item_level == ISPEC_RANDART) { + int ego = item.brand; for (int i = 0; i < 100; ++i) if (_try_make_armour_artefact(item, force_type, 0, true, agent) && is_artefact(item)) { + // borrowed from similar code for weapons -- is this really the + // best way to force an ego?? + if (ego > SPARM_NORMAL) + { + item.props[ARTEFACT_PROPS_KEY].get_vector()[ARTP_BRAND].get_short() = ego; + if (randart_is_bad(item)) // recheck, the brand changed + { + force_type = item.sub_type; + item.clear(); + item.quantity = 1; + item.base_type = OBJ_ARMOUR; + item.sub_type = force_type; + continue; + } + } return; } // fall back to an ordinary item @@ -1738,6 +1754,102 @@ void squash_plusses(int item_slot) set_equip_desc(item, ISFLAG_NO_DESC); } +static bool _ego_unrand_only(int base_type, int ego) +{ + if (base_type == OBJ_WEAPONS) + { + switch (static_cast(ego)) + { + case SPWPN_REAPING: + case SPWPN_ACID: + return true; + default: + return false; + } + } + // all armours are ok? + return false; +} + +// Make a corresponding randart instead as a fallback. +// Attempts to use base type, sub type, and ego (for armour/weapons). +// Artefacts can explicitly specify a base type and fallback type. + +// Could be even more flexible: maybe allow an item spec to describe +// complex fallbacks? +static void _setup_fallback_randart(const int unrand_id, + item_def &item, + int &force_type, + int &item_level) +{ + ASSERT(get_unrand_entry(unrand_id)); + const unrandart_entry &unrand = *get_unrand_entry(unrand_id); + dprf("Placing fallback randart for %s", unrand.name); + + uint8_t fallback_sub_type; + if (unrand.fallback_base_type != OBJ_UNASSIGNED) + { + item.base_type = unrand.fallback_base_type; + fallback_sub_type = unrand.fallback_sub_type; + } + else + { + item.base_type = unrand.base_type; + fallback_sub_type = unrand.sub_type; + } + + if (item.base_type == OBJ_WEAPONS + && fallback_sub_type == WPN_STAFF) + { + item.base_type = OBJ_STAVES; + if (unrand_id == UNRAND_WUCAD_MU) + force_type = STAFF_ENERGY; + else if (unrand_id == UNRAND_OLGREB) + force_type = STAFF_POISON; + else + force_type = OBJ_RANDOM; + // XXX: small chance of the other unrand... + // (but we won't hit this case until a new staff unrand is added) + } + else if (item.base_type == OBJ_JEWELLERY + && fallback_sub_type == AMU_NOTHING) + { + force_type = NUM_JEWELLERY; + } + else + force_type = fallback_sub_type; + + // import some brand information from the unrand. TODO: I'm doing this for + // the sake of vault designers who make themed vaults. But it also often + // makes the item more redundant with the unrand; maybe add a bit more + // flexibility in item specs so that this part is optional? However, from a + // seeding perspective, it also makes sense if the item generated is + // very comparable. + + // unset fallback_brand is -1. In that case it will try to use the regular + // brand if there is one. If the end result here is 0, the brand (for + // weapons) will be chosen randomly. So to force randomness, use + // SPWPN_NORMAL on the fallback ego, or set neither. (Randarts cannot be + // unbranded.) + item.brand = unrand.fallback_brand; // no type checking here... + + if (item.brand < 0 + && !_ego_unrand_only(item.base_type, unrand.prpty[ARTP_BRAND]) + && item.base_type == unrand.base_type // brand isn't well-defined for != case + && ((item.base_type == OBJ_WEAPONS + && is_weapon_brand_ok(item.sub_type, unrand.prpty[ARTP_BRAND], true)) + || (item.base_type == OBJ_ARMOUR + && is_armour_brand_ok(item.sub_type, unrand.prpty[ARTP_BRAND], true)))) + { + // maybe do jewellery too? + item.brand = unrand.prpty[ARTP_BRAND]; + } + if (item.brand < 0) + item.brand = 0; + + item_level = ISPEC_RANDART; +} + /** * Create an item. * @@ -1766,6 +1878,8 @@ int items(bool allow_uniques, int force_ego, int agent) { + rng::subgenerator item_rng; + ASSERT(force_ego <= 0 || force_class == OBJ_WEAPONS || force_class == OBJ_ARMOUR @@ -1848,34 +1962,8 @@ int items(bool allow_uniques, return p; } - // make a corresponding randart instead. - const unrandart_entry* unrand = get_unrand_entry(unrand_id); - ASSERT(unrand); - item.base_type = unrand->base_type; - - if (unrand->base_type == OBJ_WEAPONS - && unrand->sub_type == WPN_STAFF) - { - item.base_type = OBJ_STAVES; - if (unrand_id == UNRAND_WUCAD_MU) - force_type = STAFF_ENERGY; - else if (unrand_id == UNRAND_OLGREB) - force_type = STAFF_POISON; - else - force_type = OBJ_RANDOM; - // XXX: small chance of the other unrand... - // (but we won't hit this case until a new staff unrand is added) - } - else if (unrand->base_type == OBJ_JEWELLERY - && unrand->sub_type == AMU_NOTHING) - { - force_type = NUM_JEWELLERY; - } - else - force_type = unrand->sub_type; - - item_level = ISPEC_RANDART; - item.brand = 0; + _setup_fallback_randart(unrand_id, item, force_type, item_level); + allow_uniques = false; } // Determine sub_type accordingly. {dlb} diff --git a/crawl-ref/source/mon-gear.cc b/crawl-ref/source/mon-gear.cc index bbe706d72214..c5a9dbf294e3 100644 --- a/crawl-ref/source/mon-gear.cc +++ b/crawl-ref/source/mon-gear.cc @@ -285,6 +285,8 @@ static bool _apply_weapon_spec(const mon_weapon_spec &spec, item_def &item, */ int make_mons_weapon(monster_type type, int level, bool melee_only) { + rng::subgenerator item_rng; + static const weapon_list GOBLIN_WEAPONS = // total 10 { { WPN_DAGGER, 3 }, { WPN_CLUB, 3 }, diff --git a/crawl-ref/source/util/art-data.pl b/crawl-ref/source/util/art-data.pl index 254824ff4664..581f164b6e0f 100755 --- a/crawl-ref/source/util/art-data.pl +++ b/crawl-ref/source/util/art-data.pl @@ -92,6 +92,9 @@ plus2 => "num", base_type => "enum", sub_type => "enum", + fallback_base_type => "enum", + fallback_sub_type => "enum", + FB_BRAND => "enum", unused => "unused", ); @@ -171,6 +174,17 @@ sub finish_art } } + if (!exists($artefact->{FALLBACK})) + { + $artefact->{fallback_base_type} = "OBJ_UNASSIGNED"; + $artefact->{fallback_sub_type} = 250; + } + + if (!exists($artefact->{FB_BRAND})) + { + $artefact->{FB_BRAND} = "-1"; + } + # Appearance is no longer mandatory. $artefact->{APPEAR} = $artefact->{NAME} unless defined($artefact->{APPEAR}); @@ -364,6 +378,29 @@ sub process_line $artefact->{base_type} = $parts[0]; $artefact->{sub_type} = $parts[1]; } + elsif ($field eq "FALLBACK") + { + my @parts = split(m!/!, $value); + + if (@parts > 2) + { + error($artefact, "Too many parts to FALLBACK"); + return; + } + elsif (@parts == 1) + { + error($artefact, "Too few parts to FALLBACK"); + return; + } + + if ($parts[0] !~ /^OBJ_/) + { + error($artefact, "FALLBACK base type must start with 'OBJ_'"); + return; + } + $artefact->{fallback_base_type} = $parts[0]; + $artefact->{fallback_sub_type} = $parts[1]; + } elsif ($field eq "PLUS") { my @parts = split(m!/!, $value); @@ -480,7 +517,9 @@ sub process_line my @art_order = ( "NAME", "APPEAR", "TYPE", "INSCRIP", "\n", - "base_type", "sub_type", "plus", "plus2", "COLOUR", "VALUE", "\n", + "base_type", "sub_type", "\n", + "fallback_base_type", "fallback_sub_type", "FB_BRAND", "\n", + "plus", "plus2", "COLOUR", "VALUE", "\n", "flags", # Move FOG after FLY, and remove four copies of "unused", when diff --git a/crawl-ref/source/wiz-item.cc b/crawl-ref/source/wiz-item.cc index fd36bad8ff49..95c723612acb 100644 --- a/crawl-ref/source/wiz-item.cc +++ b/crawl-ref/source/wiz-item.cc @@ -536,7 +536,14 @@ void wizard_value_item() mprf("Value: %d", real_value); } -void wizard_create_all_artefacts() +/** + * Generate every unrand (including removed ones). + * + * @param override_unique if true, will generate unrands that have alread + * placed in the game. If false, will generate fallback randarts for any + * unrands that have already placed. + */ +void wizard_create_all_artefacts(bool override_unique) { you.octopus_king_rings = 0x00; int octorings = 8; @@ -551,18 +558,50 @@ void wizard_create_all_artefacts() if (entry->base_type == OBJ_UNASSIGNED) continue; - int islot = get_mitm_slot(); - if (islot == NON_ITEM) - break; + int islot; - item_def& item = mitm[islot]; - make_item_unrandart(item, index); - item.quantity = 1; + if (override_unique) + { + // force create: use make_item_unrandart to override a bunch of the + // usual checks on getting randarts. + islot = get_mitm_slot(); + if (islot == NON_ITEM) + break; + + item_def &tmp_item = mitm[islot]; + make_item_unrandart(tmp_item, index); + tmp_item.quantity = 1; + } + else + { + // mimic the way unrands are created normally, and respect + // uniqueness. If an unrand has already generated, this will place + // a relevant fallback randart instead. Useful for testing fallback + // properties, since various error conditions will print. + islot = items(true, entry->base_type, 0, 0, -index, -1); + if (islot == NON_ITEM) + { + mprf(MSGCH_ERROR, "Failed to generate item for '%s'", + entry->name); + continue; + } + } + item_def &item = mitm[islot]; set_ident_flags(item, ISFLAG_IDENT_MASK); - msg::streams(MSGCH_DIAGNOSTICS) << "Made " << item.name(DESC_A) - << " (" << debug_art_val_str(item) - << ")" << endl; + if (!is_artefact(item)) + { + // for now, staves are ok... + mprf(item.base_type == OBJ_STAVES ? MSGCH_DIAGNOSTICS : MSGCH_ERROR, + "Made non-artefact '%s' when trying to make '%s'", + item.name(DESC_A).c_str(), entry->name); + } + else + { + msg::streams(MSGCH_DIAGNOSTICS) << "Made " << item.name(DESC_A) + << " (" << debug_art_val_str(item) + << ")" << endl; + } move_item_to_grid(&islot, you.pos()); // Make all eight. diff --git a/crawl-ref/source/wiz-item.h b/crawl-ref/source/wiz-item.h index 67987cca9fd5..13d6fa172237 100644 --- a/crawl-ref/source/wiz-item.h +++ b/crawl-ref/source/wiz-item.h @@ -11,7 +11,7 @@ void wizard_tweak_object(); void wizard_make_object_randart(); void wizard_value_item(); void wizard_uncurse_item(); -void wizard_create_all_artefacts(); +void wizard_create_all_artefacts(bool override_unique = true); void wizard_identify_pack(); void wizard_unidentify_pack(); void wizard_draw_card(); diff --git a/crawl-ref/source/wizard.cc b/crawl-ref/source/wizard.cc index d9f46efd994f..033ede8b2bbb 100644 --- a/crawl-ref/source/wizard.cc +++ b/crawl-ref/source/wizard.cc @@ -210,7 +210,8 @@ static void _do_wizard_command(int wiz_command) break; case '\\': debug_make_shop(); break; - case '|': wizard_create_all_artefacts(); break; + case '|': wizard_create_all_artefacts(true); break; + case CONTROL('\\'): wizard_create_all_artefacts(false); break; case ';': wizard_list_levels(); break; case ':': wizard_list_branches(); break; @@ -486,6 +487,7 @@ int list_wizard_commands(bool do_redraw_screen) "Ctrl-V show gold value of an item\n" "- get a god gift\n" "| create all unrand artefacts\n" + "Ctrl-\\ create all unrands / fallbacks\n" "+ make randart from item\n" "' list items\n" "J Jiyva off-level sacrifice\n" From 82437c2fa6f9bf1fc32f80780a31d1eee4035d0d Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 6 May 2019 09:34:21 -0400 Subject: [PATCH 554/864] Update seed menu for incremental pregen Removes the toggle except on debug builds. It is still possible to enable full pregen in the rc file for offline games. --- crawl-ref/docs/crawl_manual.rst | 43 +++++++++++++++--------------- crawl-ref/source/chardump.cc | 4 ++- crawl-ref/source/command.cc | 2 +- crawl-ref/source/newgame.cc | 47 ++++++++++++++++++++++----------- 4 files changed, 56 insertions(+), 40 deletions(-) diff --git a/crawl-ref/docs/crawl_manual.rst b/crawl-ref/docs/crawl_manual.rst index e2dc4282dde9..1ddb55763024 100644 --- a/crawl-ref/docs/crawl_manual.rst +++ b/crawl-ref/docs/crawl_manual.rst @@ -471,31 +471,30 @@ Seeded play ======================================== Crawl dungeons are determined by a "seed" number used to initialise the game's -random number generator. If you initialise the game, keeping the game version -constant, then the same seed should (within certain parameters) lead to the same -dungeon. In offline games you can view your game's seed with '?V' as well as in -a character file; in online games you normally must finish a game in order to -see the game's seed. There are two seeded modes: - -Without dungeon pregeneration ('pregen_dungeon = false') - If dungeon pregeneration is turned off (the default), every game with the - same seed will have at least the same initial dungeon level and temple - layout. However, the order in which you explore levels after the first one - can lead to multiple possible dungeon layouts, depending on your choices. This - is implicitly how dungeon generation always worked before version 0.23. - -With dungeon pregeneration ('pregen_dungeon = true') - If dungeon pregeneration is turned on, the entire connected dungeon will be - determined by the game seed. Portal vaults and chaotic zones such as the - abyss are not guaranteed to be the same, though. - -To set a game seed, use the 'game_seed' rc file option, or the '-seed' command -line option. +random number generator. You may either let the game choose a seed randomly, +or specify a seed; if you choose a seed this puts the game in "Seeded" mode, +which is scored separately. Playing games with the same seed value, as long as +the game version is constant, should (within certain parameters) lead to the +same dungeon. The entire connected dungeon will be determined by the game +seed, including dungeon layout, monster placement, and items. Portal vaults +and chaotic zones such as the abyss are not guaranteed to be the same, and the +placement of rare unique artefacts may vary depending on certain player +actions. + +To set a game seed, use the "Choose game seed" option from the main menu; you +can also use the 'game_seed' rc file option, or the '-seed' command line +option. In offline games you can view your game's seed with '?V' as well as in +a character file; in online games a randomly chosen seed will only be shown to +you after finishing the game. If you find that the same seed generates distinct parts of a dungeon on the same or different devices, please report it as a bug. However, keep in mind -that upgrading your save game between multiple versions of crawl, or traversing -dungeon levels in different orders, will naturally lead to seed divergence. +that upgrading your save game between multiple versions of crawl will +naturally lead to seed divergence. When playing offline, if you would like to +ensure that your game can be upgraded without divergence, you can set +'pregen_dungeon = true' in your options file. (This will also ensure +completely stable unique artefact placement.) On the other hand, to completely +disable incremental pregeneration, you can set 'incremental_pregen = false'. Further Help ======================================== diff --git a/crawl-ref/source/chardump.cc b/crawl-ref/source/chardump.cc index 7ea2d93c8d2f..9597a55558c3 100644 --- a/crawl-ref/source/chardump.cc +++ b/crawl-ref/source/chardump.cc @@ -214,7 +214,9 @@ static void _sdump_header(dump_params &par) if (you.game_is_seeded #ifdef DGAMELAUNCH - && par.se // for online games, only show seed for a dead char + && (par.se // for online games, show seed for a dead char + || you.wizard + || crawl_state.type == GAME_TYPE_CUSTOM_SEED) #endif ) { diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc index 206930a8742a..ae930593f487 100644 --- a/crawl-ref/source/command.cc +++ b/crawl-ref/source/command.cc @@ -95,7 +95,7 @@ static string _get_version_features() string result; if (crawl_state.need_save #ifdef DGAMELAUNCH - && you.wizard + && (you.wizard || crawl_state.type == GAME_TYPE_CUSTOM_SEED) #endif ) { diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 9151034755ef..f4465812f00b 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -658,10 +658,16 @@ static void _choose_seed(newgame_def& ng, newgame_def& choice, choice.seed = Options.seed_from_rc; reader.set_text(make_stringf("%" PRIu64, choice.seed)); reader.set_keyproc(_keyfun_seed_input); + const bool show_pregen_toggle = +#ifdef DEBUG + true; +#else + false; +#endif bool done = false; bool cancel = false; - choice.pregenerate = true; // default for this menu + choice.pregenerate = Options.pregen_dungeon; auto prompt_ui = make_shared(); prompt_ui->on(Widget::slots.event, [&](wm_event ev) { @@ -669,7 +675,7 @@ static void _choose_seed(newgame_def& ng, newgame_def& choice, return false; int key = ev.key.keysym.sym; - if (key == CONTROL('I')) + if (show_pregen_toggle && key == CONTROL('I')) { choice.pregenerate = !choice.pregenerate; return done = false; @@ -686,6 +692,8 @@ static void _choose_seed(newgame_def& ng, newgame_def& choice, reader.set_text(timebuf); return done = false; } + else if (key == '?') + show_help('D', "Seeded play"); // TODO: scroll to section else if (key == '-') { reader.set_text(""); @@ -719,9 +727,13 @@ static void _choose_seed(newgame_def& ng, newgame_def& choice, auto box = make_shared(ui::Widget::VERT); box->add_child(prompt_ui); - auto pregen_choice = make_shared( - "Pregenerate the dungeon ([tab] to switch)? Yes | No"); + auto pregen_choice = make_shared(""); box->add_child(pregen_choice); + if (show_pregen_toggle) + { + pregen_choice->set_text( + "Pregenerate the dungeon ([tab] to switch)? Yes | No"); + } auto popup = make_shared(box); ui::push_layout(move(popup)); @@ -738,30 +750,33 @@ static void _choose_seed(newgame_def& ng, newgame_def& choice, "Press [p] to paste a seed from the clipboard (overwriting the\n" "current value).\n" #endif - "\n" + "\n"); + prompt.cprintf("Seed ([-] to clear):"); + string seed_text = make_stringf("%-20s", buf); + prompt.cprintf("\n%s\n\n", seed_text.c_str()); + + prompt.cprintf( "The seed will determine the dungeon layout, monsters, and items\n" - "that you discover, relative to this version of the game.\n" - "Pregeneration will ensure that these remain the same no matter\n" - "what order you explore the dungeon in. (See the manual for more\n" - "details.)\n\n"); + "that you discover, relative to this version of crawl. (See the \n" + "manual for more details.)\n\n"); #ifdef SEEDING_UNRELIABLE prompt.cprintf( "Warning: your build of crawl does not support stable seeding!\n" "Levels may differ from 'official' seeded games.\n\n"); #endif - prompt.cprintf("Seed ([-] to clear):"); - string seed_text = make_stringf("%-20s", buf); - prompt.cprintf("\n%s\n\n", seed_text.c_str()); prompt_ui->set_text(prompt); // yes this appalling, some day we will have real buttons and text // input. The seed highlight doesn't do much on console, but makes // tiles look a lot better. N.b. the newline before the seed above // is really so that an empty seed string won't get multiple highlights. prompt_ui->set_highlight_pattern(seed_text, false); - if (choice.pregenerate) - pregen_choice->set_highlight_pattern("Yes", false); - else - pregen_choice->set_highlight_pattern("No", false); + if (show_pregen_toggle) + { + if (choice.pregenerate) + pregen_choice->set_highlight_pattern("Yes", false); + else + pregen_choice->set_highlight_pattern("No", false); + } ui::pump_events(); } ui::pop_layout(); From cbae52a9c16ea00d91407e265d1e756b0fa9a2c9 Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 19 May 2019 15:42:08 -0400 Subject: [PATCH 555/864] Make ds, wn, and dswn starts more deterministic by seed This should make the rng for setting up each of these start categories fully determined by the game seed, and independent from each other (as well as all other start choices). Before, these were somewhat accidentally dependent on seed, but dswn led to an interaction between the two (and potentially with any other randomness that might happen during character initialization, if there is any). Even if we decide that this is a bad idea at some point, these are still the right code changes to make these rolls independent of the rng as well -- would just need to initialize the subgenerator differently. Thanks to discord user Blue for pointing out the dswn interaction. --- crawl-ref/source/jobs.cc | 2 ++ crawl-ref/source/mutation.cc | 6 ++++++ crawl-ref/source/ng-setup.cc | 9 +++------ crawl-ref/source/ng-wanderer.cc | 6 ++++++ 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/crawl-ref/source/jobs.cc b/crawl-ref/source/jobs.cc index 96d8668f86dc..209b12b8a703 100644 --- a/crawl-ref/source/jobs.cc +++ b/crawl-ref/source/jobs.cc @@ -68,6 +68,8 @@ job_type get_job_by_name(const char *name) // Must be called after species_stat_init for the wanderer formula to work. void job_stat_init(job_type job) { + rng::subgenerator stat_rng; + you.hp_max_adj_perm = 0; you.base_stats[STAT_STR] += _job_def(job).s; diff --git a/crawl-ref/source/mutation.cc b/crawl-ref/source/mutation.cc index a4210cea9653..9ef34dd6d4e8 100644 --- a/crawl-ref/source/mutation.cc +++ b/crawl-ref/source/mutation.cc @@ -2540,6 +2540,12 @@ _schedule_ds_mutations(vector muts) void roll_demonspawn_mutations() { + // intentionally create the subgenerator either way, so that this has the + // same impact on the current main rng for all chars. + rng::subgenerator ds_rng; + + if (you.species != SP_DEMONSPAWN) + return; you.demonic_traits = _schedule_ds_mutations( _order_ds_mutations( _select_ds_mutations())); diff --git a/crawl-ref/source/ng-setup.cc b/crawl-ref/source/ng-setup.cc index c46bc55eb04a..baa4333c1e14 100644 --- a/crawl-ref/source/ng-setup.cc +++ b/crawl-ref/source/ng-setup.cc @@ -234,6 +234,8 @@ static void _give_ammo(weapon_type weapon, int plus) static void _give_items_skills(const newgame_def& ng) { + create_wanderer(); + switch (you.char_class) { case JOB_BERSERKER: @@ -277,10 +279,6 @@ static void _give_items_skills(const newgame_def& ng) break; - case JOB_WANDERER: - create_wanderer(); - break; - default: break; } @@ -508,8 +506,7 @@ static void _setup_generic(const newgame_def& ng) // This function depends on stats and mutations being finalised. _give_items_skills(ng); - if (you.species == SP_DEMONSPAWN) - roll_demonspawn_mutations(); + roll_demonspawn_mutations(); _give_starting_food(); diff --git a/crawl-ref/source/ng-wanderer.cc b/crawl-ref/source/ng-wanderer.cc index 22ead0849a94..3dcf5fdc9077 100644 --- a/crawl-ref/source/ng-wanderer.cc +++ b/crawl-ref/source/ng-wanderer.cc @@ -683,6 +683,12 @@ static void _wanderer_cover_equip_holes() // levels/equipment, but pretty randomised. void create_wanderer() { + // intentionally create the subgenerator either way, so that this has the + // same impact on the current main rng for all chars. + rng::subgenerator wn_rng; + if (you.char_class != JOB_WANDERER) + return; + // Decide what our character roles are. stat_type primary_role = _wanderer_choose_role(); stat_type secondary_role = _wanderer_choose_role(); From 7e99aecb7ec6ef2e6194acad36e3d5e5857974d9 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 30 May 2019 09:39:39 -0400 Subject: [PATCH 556/864] Use fallback randarts for minmay_shop_chei This works fine, you get randart bardings/hats with ponder. --- crawl-ref/source/dat/des/builder/shops.des | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/dat/des/builder/shops.des b/crawl-ref/source/dat/des/builder/shops.des index 0bb15165e90d..f1666cd00253 100644 --- a/crawl-ref/source/dat/des/builder/shops.des +++ b/crawl-ref/source/dat/des/builder/shops.des @@ -709,7 +709,7 @@ local kstr = local i = 0 while i < itemCount do local itm = items[crawl.random2(#items) + 1] - if not (chosen[itm] or you.unrands(itm)) then + if not (chosen[itm]) then i = i + 1 chosen[itm] = true kstr = kstr .. itm From 38a37b7ff7ab38f706b8171252c3b01dfe807e8d Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 30 May 2019 11:26:42 -0400 Subject: [PATCH 557/864] Isolate shop rolls from levelgen This will make it not a complete disaster to try to place specific unrands in shops, though I would still want to discourage this. I believe there is currently one shop that does this, minmay_shop_mayhem, which doesn't have a simple fix. (One option might be to let some lua post-place script cull shop items, rather than try to filter the list beforehand, but I think this would be pretty involved.) --- crawl-ref/source/dungeon.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 03f6bdf0597b..f63024fab62e 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -5746,6 +5746,7 @@ static void _stock_shop_item(int j, shop_type shop_type_, */ void place_spec_shop(const coord_def& where, shop_spec &spec, int shop_level) { + rng::subgenerator shop_rng; // isolate shop rolls from levelgen no_notes nx; shop_struct& shop = env.shop[where]; From 66c84cb112ec03a2c54d77f0c02e1016ce5a2c4e Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 30 May 2019 15:03:04 -0400 Subject: [PATCH 558/864] Add pan to level generation order This forces everything before pan to be generated before entering pan; since there is occasional overlap of vaults and uniques, entering pan can therefore interfere in any later levelgen. --- crawl-ref/source/files.cc | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index bae5e98a55df..d9f5d15e3983 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1462,6 +1462,7 @@ static const vector branch_generation_order = BRANCH_COCYTUS, BRANCH_DIS, BRANCH_GEHENNA, + BRANCH_PANDEMONIUM, NUM_BRANCHES, }; @@ -1501,17 +1502,18 @@ bool pregen_dungeon(const level_id &stopping_point) { // TODO: why is dungeon invalid? it's not set up properly in // `initialise_branch_depths` for some reason. The vestibule is invalid - // because its depth isn't set until the player actually enters a portal. + // because its depth isn't set until the player actually enters a + // portal, similarly for other portal branches. if (br < NUM_BRANCHES && (brentry[br].is_valid() - || br == BRANCH_DUNGEON || br == BRANCH_VESTIBULE)) + || br == BRANCH_DUNGEON || br == BRANCH_VESTIBULE + || !is_connected_branch(br))) { for (int i = 1; i <= branches[br].numlevels; i++) { level_id new_level = level_id(br, i); if (you.save->has_chunk(new_level.describe())) continue; - to_generate.push_back(new_level); if (br == stopping_point.branch @@ -1528,7 +1530,10 @@ bool pregen_dungeon(const level_id &stopping_point) } if (to_generate.size() == 0) + { + dprf("levelgen: No valid levels to generate."); return false; + } else if (to_generate.size() == 1) return generate_level(to_generate[0]); // no popup for this case else From 44eecae16b7868fd7edb08e51b38405515262467 Mon Sep 17 00:00:00 2001 From: advil Date: Fri, 31 May 2019 18:02:48 -0400 Subject: [PATCH 559/864] Generate portal levels at the same time as their source Whenever a regular level has a portal, this will generate the portal levels immediately after the regular level's generation is triggered. This imposes a deterministic generation order on portal levels for incremental pregen, as well as a deterministic order between portals when there are multiple ones from the same level (which is missing from even full pregen before this commit). This commit also puts ziggurats in the generation order, though they are handled a bit differently; this is so everything else generates before they do, to try to minimize the impacts of item placement in zigs. --- crawl-ref/source/files.cc | 81 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index d9f5d15e3983..b2b96022efd3 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -69,6 +69,7 @@ #include "prompt.h" #include "species.h" #include "spl-summoning.h" +#include "stairs.h" #include "stash.h" // for fedhas_rot_all_corpses #include "state.h" #include "stringutil.h" @@ -1370,6 +1371,63 @@ static void _generic_level_reset() clear_travel_trail(); } + +// used to resolve generation order for cases where a single level has multiple +// portals. +static const vector portal_generation_order = +{ + BRANCH_SEWER, + BRANCH_OSSUARY, + BRANCH_ICE_CAVE, + BRANCH_VOLCANO, + BRANCH_BAILEY, + BRANCH_GAUNTLET, +#if TAG_MAJOR_VERSION == 34 + BRANCH_LABYRINTH, +#endif + BRANCH_BAZAAR, + // do not pregenerate trove + BRANCH_WIZLAB, + BRANCH_DESOLATION, +}; + +static void _update_portal_entrances() +{ + for (rectangle_iterator ri(0); ri; ++ri) + { + dungeon_feature_type feat = env.grid(*ri); + // excludes pan, hell, abyss. + if (feat_is_portal_entrance(feat)) + { + level_id whither = stair_destination(feat, "", false); + if (whither.branch == BRANCH_ZIGGURAT || whither.branch == BRANCH_TROVE) + continue; // handle these differently + dprf("Setting up entry for %s.", whither.describe().c_str()); + ASSERT(count(portal_generation_order.begin(), + portal_generation_order.end(), + whither.branch) == 1); + ASSERT(brentry[whither.branch] == level_id()); // violated by multiple portals + brentry[whither.branch] = level_id::current(); + } + } +} + +static bool _generate_portal_levels() +{ + // find any portals that branch off of the current level. + level_id here = level_id::current(); + vector to_build; + for (auto b : portal_generation_order) + if (brentry[b] == here) + for (int i = 1; i <= branches[b].numlevels; i++) + to_build.push_back(level_id(b, i)); + + bool generated = false; + for (auto lid : to_build) + generated = generate_level(lid) || generated; + return generated; +} + /** * Ensure that the level given by `l` is generated. This does not do much in * the way of cleanup, and the caller must ensure the player ends up somewhere @@ -1427,9 +1485,22 @@ bool generate_level(const level_id &l) env.sanctuary_time = 0; env.markers.init_all(); // init first, activation happens when entering show_update_emphasis(); // Clear map knowledge stair emphasis in env. + _update_portal_entrances(); // save the level and associated env state _save_level(level_id::current()); + + const string save_name = level_id::current().describe(); // should be same as level_name... + + // generate levels for all portals that branch off from here + if (_generate_portal_levels()) + { + // if portals were generated, we're currently elsewhere. + ASSERT(you.save->has_chunk(save_name)); + dprf("Reloading new level '%s'.", save_name.c_str()); + _restore_tagged_chunk(you.save, save_name, TAG_LEVEL, + "Level file is invalid."); + } return true; } @@ -1463,6 +1534,7 @@ static const vector branch_generation_order = BRANCH_DIS, BRANCH_GEHENNA, BRANCH_PANDEMONIUM, + BRANCH_ZIGGURAT, NUM_BRANCHES, }; @@ -1500,6 +1572,15 @@ bool pregen_dungeon(const level_id &stopping_point) bool at_end = false; for (auto br : branch_generation_order) { + if (br == BRANCH_ZIGGURAT && + stopping_point.branch == BRANCH_ZIGGURAT) + { + // zigs delete levels as they go, so don't catchup when we're + // already in one. Zigs are only handled this way so that everything + // else generates first. + to_generate.push_back(stopping_point); + continue; + } // TODO: why is dungeon invalid? it's not set up properly in // `initialise_branch_depths` for some reason. The vestibule is invalid // because its depth isn't set until the player actually enters a From da9c0b029ad506fdca018a5fc23787d9302fa957 Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 26 Jun 2019 13:47:54 -0400 Subject: [PATCH 560/864] Update seed explorer for incremental pregeneration This mostly consists of handling portals correctly. Also, smaller changes: * Add Gehenna to the seed explorer. Somehow this was missing? * Change the seed explorer default depth to exclude hells; the hells are too spammy, and not what most use cases are interested in. --- crawl-ref/source/dat/dlua/explorer.lua | 77 +++++++++++++++++++--- crawl-ref/source/files.cc | 4 +- crawl-ref/source/files.h | 1 + crawl-ref/source/l-debug.cc | 1 + crawl-ref/source/scripts/seed_explorer.lua | 20 ++++-- 5 files changed, 87 insertions(+), 16 deletions(-) diff --git a/crawl-ref/source/dat/dlua/explorer.lua b/crawl-ref/source/dat/dlua/explorer.lua index b58a309009a4..61482f31322d 100644 --- a/crawl-ref/source/dat/dlua/explorer.lua +++ b/crawl-ref/source/dat/dlua/explorer.lua @@ -28,7 +28,25 @@ explorer.generation_order = { "Tar:1", "Tar:2", "Tar:3", "Tar:4", "Tar:5", "Tar:6", "Tar:7", "Coc:1", "Coc:2", "Coc:3", "Coc:4", "Coc:5", "Coc:6", "Coc:7", "Dis:1", "Dis:2", "Dis:3", "Dis:4", "Dis:5", "Dis:6", "Dis:7", + "Geh:1", "Geh:2", "Geh:3", "Geh:4", "Geh:5", "Geh:6", "Geh:7", } +-- generation order continues: pan, zig. However, these are really only in the +-- official generation order so that entering them forces the rest of the +-- dungeon to generate first, so we ignore them here. + +explorer.portal_order = { + "Sewer", + "Ossuary", + "IceCv", + "Volcano", + "Bailey", + "Gauntlet", + "Bazaar", + -- Trove is not pregenerated, so should be ignored here + "WizLab", + "Desolation" +} + function explorer.level_to_gendepth(lvl) -- TODO could parse l, handle things like Hell:1 @@ -37,6 +55,11 @@ function explorer.level_to_gendepth(lvl) return i end end + for i, l in ipairs(explorer.portal_order) do + if lvl:lower() == l:lower() then + return -i -- fairly hacky + end + end return nil end @@ -274,11 +297,15 @@ function explorer.describe_mons(mons) if explorer.rare_ood(mi) then feats[#feats + 1] = "OOD" end - if not mons.in_local_population and not explorer.mons_always_native(mons, mi) then + if not mons.in_local_population and not explorer.mons_always_native(mons, mi) + and not util.set(explorer.portal_order)[you.branch()] then -- this is a different sense of "native" than used internally to crawl, -- in that it includes anything that would normally generate in a -- branch. The internal sense is just supposed to be about which -- monsters "live" in a particular branch, which is covered as well. + -- + -- portals are ignored because their monsters are mostly determined by + -- vaults, so too many things show up as "non-native". feats[#feats + 1] = "non-native" end if explorer.mons_feat_filter then @@ -454,6 +481,31 @@ function explorer.catalog_current_place(lvl, to_show, hide_empty) return highlights end +function explorer.catalog_place(i, lvl, cats_to_show, show_level_fun) + local result = nil + if (dgn.br_exists(string.match(lvl, "[^:]+"))) then + debug.goto_place(lvl) + debug.generate_level() + local old_quiet = explorer.quiet + if show_level_fun ~= nil and not show_level_fun(i) then + explorer.quiet = true + end + result = explorer.catalog_current_place(lvl, cats_to_show, true) + explorer.quiet = old_quiet + end + return result +end + +function explorer.catalog_portals(i, lvl, cats_to_show, show_level_fun) + local result = { } + for j,port in ipairs(explorer.portal_order) do + if you.where() == dgn.level_name(dgn.br_entrance(port)) then + result[port] = explorer.catalog_place(-j, port, cats_to_show, show_level_fun) + end + end + return result +end + -- a bit redundant with mapstat? function explorer.catalog_dungeon(max_depth, cats_to_show, show_level_fun) local result = {} @@ -462,16 +514,21 @@ function explorer.catalog_dungeon(max_depth, cats_to_show, show_level_fun) debug.dungeon_setup() for i,lvl in ipairs(explorer.generation_order) do if i > max_depth then break end - if (dgn.br_exists(string.match(lvl, "[^:]+"))) then - debug.goto_place(lvl) - debug.generate_level() - local old_quiet = explorer.quiet - if show_level_fun ~= nil and not show_level_fun(i) then - explorer.quiet = true - end - result[lvl] = explorer.catalog_current_place(lvl, cats_to_show, true) - explorer.quiet = old_quiet + result[lvl] = explorer.catalog_place(i, lvl, cats_to_show, show_level_fun) + local portals = explorer.catalog_portals(i, lvl, cats_to_show, show_level_fun) + for port, cat in pairs(portals) do + result[port] = cat end + -- if (dgn.br_exists(string.match(lvl, "[^:]+"))) then + -- debug.goto_place(lvl) + -- debug.generate_level() + -- local old_quiet = explorer.quiet + -- if show_level_fun ~= nil and not show_level_fun(i) then + -- explorer.quiet = true + -- end + -- result[lvl] = explorer.catalog_current_place(lvl, cats_to_show, true) + -- explorer.quiet = old_quiet + -- end end return result end diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index b2b96022efd3..eb60caf776b5 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1391,7 +1391,7 @@ static const vector portal_generation_order = BRANCH_DESOLATION, }; -static void _update_portal_entrances() +void update_portal_entrances() { for (rectangle_iterator ri(0); ri; ++ri) { @@ -1485,7 +1485,7 @@ bool generate_level(const level_id &l) env.sanctuary_time = 0; env.markers.init_all(); // init first, activation happens when entering show_update_emphasis(); // Clear map knowledge stair emphasis in env. - _update_portal_entrances(); + update_portal_entrances(); // save the level and associated env state _save_level(level_id::current()); diff --git a/crawl-ref/source/files.h b/crawl-ref/source/files.h index e64ecd62459f..e5459ad43825 100644 --- a/crawl-ref/source/files.h +++ b/crawl-ref/source/files.h @@ -81,6 +81,7 @@ class level_id; void trackers_init_new_level(bool transit); +void update_portal_entrances(); bool generate_level(const level_id &l); bool pregen_dungeon(const level_id &stopping_point); bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, diff --git a/crawl-ref/source/l-debug.cc b/crawl-ref/source/l-debug.cc index 4088c77833cc..2c499a95263b 100644 --- a/crawl-ref/source/l-debug.cc +++ b/crawl-ref/source/l-debug.cc @@ -105,6 +105,7 @@ LUAFN(debug_generate_level) tile_clear_flavour(); tile_new_level(true); builder(lua_isboolean(ls, 1)? lua_toboolean(ls, 1) : true); + update_portal_entrances(); return 0; } diff --git a/crawl-ref/source/scripts/seed_explorer.lua b/crawl-ref/source/scripts/seed_explorer.lua index a130dcbb65b3..ba5bb7a02df2 100644 --- a/crawl-ref/source/scripts/seed_explorer.lua +++ b/crawl-ref/source/scripts/seed_explorer.lua @@ -38,7 +38,8 @@ Usage: seed_explorer.lua -seed ([ ...]|[-count ]) ([-depth : A level or branch name in short form, e.g. `Zot:5`, `Hell`, or `D`, a number, or 'all'. If this is a number, then this value is - depth relative to the level generation order. Defaults to `all`. + depth relative to the level generation order. Defaults to Tomb:3, + i.e. excluding the hells. : same format as , but will only show levels in the list. Note that this doesn't affect which levels are generated, so `-show Zot:5` will take as long to run as `-depth Zot:5`. @@ -150,14 +151,25 @@ if args["-show"] ~= nil then if #levels_to_show == 0 then usage_error("\nNo valid levels or depths provided with -show!") end - util.sort(levels_to_show) - if max_depth == nil then max_depth = levels_to_show[#levels_to_show] end + if max_depth == nil then + -- this doesn't handle portal-only lists correctly + max_depth = 0 + for i, depth in ipairs(levels_to_show) do + if depth > max_depth then max_depth = depth end + end + if max_depth == 0 then + -- portals only. + -- TODO: this is a heuristic; but no portals currently generate + -- later than this. (In fact, elf:2 is really the latest.) + max_depth = explorer.level_to_gendepth("Zot:4") + end + end local levels_set = util.set(levels_to_show) show_level_fun = function (l) return levels_set[l] end end if max_depth == nil then - max_depth = #explorer.generation_order + max_depth = explorer.level_to_gendepth("Tomb:3") end -- TODO: these are kind of ad hoc, maybe some kind of more general interface? From 215db2b00707160e0702acc2121cd27e73e86b1a Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 26 Jun 2019 17:02:48 -0400 Subject: [PATCH 561/864] Reset brentry for portals correctly in tests/wizmode Now that portal information is stored here, we need to deal with tests that clear uniq_map data, allowing portals to be generated multiple times. --- crawl-ref/source/dat/dlua/test.lua | 2 +- crawl-ref/source/dungeon.cc | 3 +++ crawl-ref/source/files.cc | 18 +++++++++++++++++- crawl-ref/source/files.h | 1 + 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/dat/dlua/test.lua b/crawl-ref/source/dat/dlua/test.lua index 2242e84a61f0..c2ef1835984f 100644 --- a/crawl-ref/source/dat/dlua/test.lua +++ b/crawl-ref/source/dat/dlua/test.lua @@ -44,7 +44,7 @@ function test.regenerate_level(place, use_random_maps) if place then debug.goto_place(place) end - debug.flush_map_memory() + debug.flush_map_memory() -- TODO: this is overkill for a single level dgn.reset_level() debug.generate_level(use_random_maps) end diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index f63024fab62e..772e290a72a7 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -612,6 +612,7 @@ void dgn_flush_map_memory() you.zig_max = 0; you.exploration = 0; you.seen_portals = 0; // should be just cosmetic + reset_portal_entrances(); // would it be safe to just clear you.props? you.props.erase(TEMPLE_SIZE_KEY); you.props.erase(TEMPLE_MAP_KEY); @@ -1332,6 +1333,8 @@ void dgn_reset_level(bool enable_random_maps) tile_init_default_flavour(); tile_clear_flavour(); env.tile_names.clear(); + + update_portal_entrances(); } static int _num_items_wanted(int absdepth0) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index eb60caf776b5..aa9aad72a1b9 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1393,6 +1393,9 @@ static const vector portal_generation_order = void update_portal_entrances() { + unordered_set> seen_portals; + auto const cur_level = level_id::current(); + // add any portals not currently registered for (rectangle_iterator ri(0); ri; ++ri) { dungeon_feature_type feat = env.grid(*ri); @@ -1407,9 +1410,22 @@ void update_portal_entrances() portal_generation_order.end(), whither.branch) == 1); ASSERT(brentry[whither.branch] == level_id()); // violated by multiple portals - brentry[whither.branch] = level_id::current(); + brentry[whither.branch] = cur_level; + seen_portals.insert(whither.branch); } } + // clean up any portals that aren't actually here -- comes up for wizmode + // and test mode cases. + for (auto b : portal_generation_order) + if (!seen_portals.count(b) && brentry[b] == cur_level) + brentry[b] = level_id(); +} + +void reset_portal_entrances() +{ + for (auto b : portal_generation_order) + if (brentry[b].is_valid()) + brentry[b] = level_id(); } static bool _generate_portal_levels() diff --git a/crawl-ref/source/files.h b/crawl-ref/source/files.h index e5459ad43825..44909dc1a02d 100644 --- a/crawl-ref/source/files.h +++ b/crawl-ref/source/files.h @@ -82,6 +82,7 @@ class level_id; void trackers_init_new_level(bool transit); void update_portal_entrances(); +void reset_portal_entrances(); bool generate_level(const level_id &l); bool pregen_dungeon(const level_id &stopping_point); bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, From aa2f355350bce622415fb0bcf5ab5ffa132beac2 Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 30 Jun 2019 21:03:02 -0400 Subject: [PATCH 562/864] Isolate shoals tide from levelgen rng The builder calls some tide code when finishing up a shoals level, roughly to initialize things. However, tide code is dependent on global state, for things like shoals tide direction, and it is also randomized, so it would have a different impact on the rng depending on this state. This means that for incremental pregen (or just regular games before incremental pregen) the outcome of later levelgen would be impacted by the global tide state when entering a level. This commit ensures that tide state only ever impacts the gameplay rng. --- crawl-ref/source/dgn-shoals.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crawl-ref/source/dgn-shoals.cc b/crawl-ref/source/dgn-shoals.cc index cca4901e3f50..8540511a13cf 100644 --- a/crawl-ref/source/dgn-shoals.cc +++ b/crawl-ref/source/dgn-shoals.cc @@ -1018,6 +1018,13 @@ void shoals_apply_tides(int turns_elapsed, bool force, bool incremental_tide) return; } + // isolate from main levelgen rng if called from there; the behavior of + // this function is dependent on global state (tide direction, etc) that + // may impact the number of rolls depending on when the player changes + // shoals levels, so doing this with the levelgen rng has downstream + // effects. + rng::generator tide_rng(rng::GAMEPLAY); + CrawlHashTable &props(you.props); _shoals_init_tide(); From ad2a1014089230d1344302f53f6bf87197f43f2e Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 7 Jul 2019 13:00:03 -0400 Subject: [PATCH 563/864] Fix a sequence point issue in rng::subgenerator --- crawl-ref/source/random.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/random.cc b/crawl-ref/source/random.cc index 1527f40c9276..4be7180466d2 100644 --- a/crawl-ref/source/random.cc +++ b/crawl-ref/source/random.cc @@ -98,8 +98,10 @@ namespace rng : subgenerator(seed, get_uint64()) { } + // call the 1-arg constructor so as to ensure a sequence point between the + // two get_uint64 calls. subgenerator::subgenerator() - : subgenerator(get_uint64(), get_uint64()) + : subgenerator(get_uint64()) { } PcgRNG *get_generator(rng_type r) From 5121451e89b1886df99bbcf115243aa9360075f6 Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 7 Jul 2019 13:36:55 -0400 Subject: [PATCH 564/864] Don't pregenerate bazaars (for now at least) The problem is that multiple bazaars can generate, which I hadn't realized. It would be possible to pregenerate the first one without too much trouble, but this leads to some oddness with the current incremental pregen setup. Ideally, we would pregenerate all bazaars, but this would require some tricky changes to how portal vaults are currently handled. --- crawl-ref/source/files.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index aa9aad72a1b9..aa633557eee0 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1385,7 +1385,7 @@ static const vector portal_generation_order = #if TAG_MAJOR_VERSION == 34 BRANCH_LABYRINTH, #endif - BRANCH_BAZAAR, + // do not pregenerate bazaar (TODO: this is non-ideal) // do not pregenerate trove BRANCH_WIZLAB, BRANCH_DESOLATION, @@ -1403,8 +1403,12 @@ void update_portal_entrances() if (feat_is_portal_entrance(feat)) { level_id whither = stair_destination(feat, "", false); - if (whither.branch == BRANCH_ZIGGURAT || whither.branch == BRANCH_TROVE) + if (whither.branch == BRANCH_ZIGGURAT // not (quite) pregenerated + || whither.branch == BRANCH_TROVE // not pregenerated + || whither.branch == BRANCH_BAZAAR) // multiple bazaars possible + { continue; // handle these differently + } dprf("Setting up entry for %s.", whither.describe().c_str()); ASSERT(count(portal_generation_order.begin(), portal_generation_order.end(), From 452b1d95eac4bbede07a57cedf542ff48fe6c84e Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 15 Jul 2019 10:04:15 -0400 Subject: [PATCH 565/864] Handle certain random attack specs differently Four monsters (chaos spawn, cherubs, eidolons, and ghost moths) have a random attack type or flavor that is randomized as part of `mons_attack_spec`. This led to two bugs. First, the monster description changed each time you look at it; this is cosmetic for chaos spawn/cherub as the damage wasn't affected, but for eidolons and ghost moths a newer player would not realize that the stat affected by AF_DRAIN_STAT is randomized per hit. Second, and more involved, this led to a seed bug, depending on the state of the area grid when the builder was called. When placing an item, the builder checks if the player can hear the position where the item is, in order to decide whether to make a splash noise. As part of this check, it looks to see if the position is silenced. This involves checking the area grid, and if the area grid is invalid, rebuilds it. Part of rebuilding the area grid involves running holiness checks on potentially every monster in the level. Running a holiness check involves checking attack flavors, to look for evil attacks etc. This would therefore then do some random calls, on the levelgen rng. The result: the rng state was different depending on whether the area grid is valid. (Probably every stage of this calculation could be simplified out of existence for the levelgen case, but no matter.) I *think* that the area grid should always be valid except on turn 0, so this mainly led to a difference between the seed explorer and actual games; because these monsters are not super common it wouldn't manifest until lair branches or depths usually. This commit fixes these bugs in two ways. First, it makes `mons_attack_spec` non-random unless that is explicitly called for, which it only should be when actually doing the attack. This leads to better descriptions of these four monsters. Second, as a sanity check it also isolates the area grid rng, in case there's other code that could be triggered by it that is random. There's also a bit of debugging code / builder spam adjustment in this commit. --- crawl-ref/source/areas.cc | 3 +++ crawl-ref/source/attack.cc | 3 ++- crawl-ref/source/dungeon.cc | 13 +++++++------ crawl-ref/source/mon-place.cc | 7 +++++++ crawl-ref/source/mon-util.cc | 21 +++++++++++++-------- crawl-ref/source/mon-util.h | 2 +- crawl-ref/source/monster.cc | 2 ++ crawl-ref/source/random.cc | 6 ++++++ crawl-ref/source/random.h | 14 ++++++++++++++ 9 files changed, 55 insertions(+), 16 deletions(-) diff --git a/crawl-ref/source/areas.cc b/crawl-ref/source/areas.cc index caf9bf5d9aa6..3910ffcd770b 100644 --- a/crawl-ref/source/areas.cc +++ b/crawl-ref/source/areas.cc @@ -145,6 +145,9 @@ static void _actor_areas(actor *a) */ static void _update_agrid() { + // sanitize rng in case this gets indirectly called by the builder. + rng::generator gameplay(rng::GAMEPLAY); + if (no_areas) { _agrid_valid = true; diff --git a/crawl-ref/source/attack.cc b/crawl-ref/source/attack.cc index 706ebef8751c..46710314a3c7 100644 --- a/crawl-ref/source/attack.cc +++ b/crawl-ref/source/attack.cc @@ -381,7 +381,8 @@ void attack::init_attack(skill_type unarmed_skill, int attack_number) if (attacker->is_monster()) { mon_attack_def mon_attk = mons_attack_spec(*attacker->as_monster(), - attack_number); + attack_number, + false); attk_type = mon_attk.type; attk_flavour = mon_attk.flavour; diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 772e290a72a7..b8021f2a6574 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -3831,13 +3831,14 @@ static void _randomly_place_item(int item) } if (!found) { + dprf(DIAG_DNGN, "Builder failed to place %s", + mitm[item].name(DESC_PLAIN, false, true).c_str()); // Couldn't find a single good spot! destroy_item(item); } else { - dprf(DIAG_DNGN, "builder placing %s (%s) at %d,%d", - mitm[item].name(DESC_PLAIN).c_str(), + dprf(DIAG_DNGN, "Builder placing %s at %d,%d", mitm[item].name(DESC_PLAIN, false, true).c_str(), itempos.x, itempos.y); move_item_to_grid(&item, itempos); @@ -4579,8 +4580,7 @@ int dgn_place_item(const item_spec &spec, if (_apply_item_props(item, spec, (useless_tries >= 10), false)) { - dprf(DIAG_DNGN, "vault spec: placing %s (%s) at %d,%d", - mitm[item_made].name(DESC_PLAIN).c_str(), + dprf(DIAG_DNGN, "vault spec: placing %s at %d,%d", mitm[item_made].name(DESC_PLAIN, false, true).c_str(), where.x, where.y); env.level_map_mask(where) |= MMT_NO_TRAP; @@ -5111,8 +5111,7 @@ static void _vault_grid_glyph(vault_placement &place, const coord_def& where, { mitm[item_made].pos = where; env.level_map_mask(where) |= MMT_NO_TRAP; - dprf(DIAG_DNGN, "vault grid: placing %s (%s) at %d,%d", - mitm[item_made].name(DESC_PLAIN).c_str(), + dprf(DIAG_DNGN, "vault grid: placing %s at %d,%d", mitm[item_made].name(DESC_PLAIN, false, true).c_str(), mitm[item_made].pos.x, mitm[item_made].pos.y); } @@ -5736,6 +5735,8 @@ static void _stock_shop_item(int j, shop_type shop_type_, item.pos = shop.pos; item.link = ITEM_IN_SHOP; shop.stock.push_back(item); + dprf(DIAG_DNGN, "shop spec: placing %s", + item.name(DESC_PLAIN, false, true).c_str()); } /** diff --git a/crawl-ref/source/mon-place.cc b/crawl-ref/source/mon-place.cc index 9c9e8fd5b764..3e336bd00c21 100644 --- a/crawl-ref/source/mon-place.cc +++ b/crawl-ref/source/mon-place.cc @@ -578,6 +578,10 @@ static bool _valid_monster_generation_location(const mgen_data &mg, || monster_at(mg_pos) || you.pos() == mg_pos && !fedhas_passthrough_class(mg.cls)) { + ASSERT(!crawl_state.generating_level + || !in_bounds(mg_pos) + || you.pos() != mg_pos + || you.where_are_you == BRANCH_ABYSS); return false; } @@ -594,6 +598,7 @@ static bool _valid_monster_generation_location(const mgen_data &mg, if (mg.proximity == PROX_AWAY_FROM_PLAYER && close_to_player || mg.proximity == PROX_CLOSE_TO_PLAYER && !close_to_player) { + ASSERT(!crawl_state.generating_level || you.where_are_you == BRANCH_ABYSS); return false; } // Check that the location is not proximal to level stairs. @@ -828,6 +833,8 @@ monster* place_monster(mgen_data mg, bool force_pos, bool dont_place) member->props["kirke_band"] = true; } } + dprf(DIAG_DNGN, "Placing %s at %d,%d", mon->name(DESC_PLAIN, true).c_str(), + mon->pos().x, mon->pos().y); // Placement of first monster, at least, was a success. return mon; diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index da56a7517e0c..d90efbb6ffee 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -2023,14 +2023,19 @@ mon_attack_def mons_attack_spec(const monster& m, int attk_number, attk.damage = max(1, you.skill_rdiv(SK_UNARMED_COMBAT, 10, 20)); } - if (attk.type == AT_RANDOM) - attk.type = random_choose(AT_HIT, AT_GORE); + if (!base_flavour) + { + // TODO: randomization here is not the greatest way of doing any of + // these... + if (attk.type == AT_RANDOM) + attk.type = random_choose(AT_HIT, AT_GORE); - if (attk.type == AT_CHERUB) - attk.type = random_choose(AT_HIT, AT_BITE, AT_PECK, AT_GORE); + if (attk.type == AT_CHERUB) + attk.type = random_choose(AT_HIT, AT_BITE, AT_PECK, AT_GORE); - if (attk.flavour == AF_DRAIN_STAT) - attk.flavour = random_choose(AF_DRAIN_STR, AF_DRAIN_INT,AF_DRAIN_DEX); + if (attk.flavour == AF_DRAIN_STAT) + attk.flavour = random_choose(AF_DRAIN_STR, AF_DRAIN_INT,AF_DRAIN_DEX); + } // Slime creature attacks are multiplied by the number merged. if (mon.type == MONS_SLIME_CREATURE && mon.blob_size > 1) @@ -2088,12 +2093,12 @@ string mon_attack_name(attack_type attack, bool with_object) #if TAG_MAJOR_VERSION == 34 "sting", #endif - "hit", // AT_CHERUB + "hit, bite, peck, or gore", // AT_CHERUB #if TAG_MAJOR_VERSION == 34 "hit", // AT_SHOOT #endif "hit", // AT_WEAP_ONLY, - "hit", // AT_RANDOM + "hit or gore", // AT_RANDOM }; COMPILE_CHECK(ARRAYSZ(attack_types) == NUM_ATTACK_TYPES - AT_FIRST_ATTACK); diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h index dda91703fbc2..ec1358b63e13 100644 --- a/crawl-ref/source/mon-util.h +++ b/crawl-ref/source/mon-util.h @@ -245,7 +245,7 @@ bool mons_class_sees_invis(monster_type type, monster_type base); bool mons_immune_magic(const monster& mon); -mon_attack_def mons_attack_spec(const monster& mon, int attk_number, bool base_flavour = false); +mon_attack_def mons_attack_spec(const monster& mon, int attk_number, bool base_flavour = true); string mon_attack_name(attack_type attack, bool with_object = true); bool flavour_triggers_damageless(attack_flavour flavour); int flavour_damage(attack_flavour flavour, int HD, bool random = true); diff --git a/crawl-ref/source/monster.cc b/crawl-ref/source/monster.cc index ca868829c3eb..928a58cb1b23 100644 --- a/crawl-ref/source/monster.cc +++ b/crawl-ref/source/monster.cc @@ -3533,6 +3533,8 @@ void monster::suicide(int hp_target) mon_holy_type monster::holiness(bool /*temp*/) const { + rng::ASSERT_stable rng_check; + // zombie kraken tentacles if (testbits(flags, MF_FAKE_UNDEAD)) return MH_UNDEAD; diff --git a/crawl-ref/source/random.cc b/crawl-ref/source/random.cc index 4be7180466d2..91423e9e0070 100644 --- a/crawl-ref/source/random.cc +++ b/crawl-ref/source/random.cc @@ -135,6 +135,12 @@ namespace rng return current_generator().get_uint64(); } + uint64_t peek_uint64() + { + PcgRNG tmp = current_generator(); // make a copy + return tmp.get_uint64(); + } + static void _do_seeding(PcgRNG &master) { // TODO: don't initialize gameplay/ui rng? diff --git a/crawl-ref/source/random.h b/crawl-ref/source/random.h index f72632d981b4..1ed64c6ee3db 100644 --- a/crawl-ref/source/random.h +++ b/crawl-ref/source/random.h @@ -52,6 +52,20 @@ namespace rng uint32_t get_uint32(); uint64_t get_uint64(); uint32_t peek_uint32(); + uint64_t peek_uint64(); + + class ASSERT_stable + { + public: + ASSERT_stable() : initial_peek(peek_uint64()) { } + ~ASSERT_stable() + { + ASSERT(peek_uint64() == initial_peek); + } + + private: + uint64_t initial_peek; + }; } bool coinflip(); From 93dbe2d410df0bbf5fb32eb6d9f2b1f91bb509eb Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 15 Jul 2019 16:49:41 -0400 Subject: [PATCH 566/864] Isolate trove portal generation from levelgen rng The toll is calculated while generating the trove, and the number of rng draws that make up this calculation depends on the player (skills, species, etc). So, isolate it as a subgenerator calculation so that it always makes the same number of draws from the main rng. --- crawl-ref/source/dat/des/portals/trove.des | 5 ++- crawl-ref/source/l-crawl.cc | 46 ++++++++++++++++++++++ crawl-ref/source/random.cc | 5 ++- crawl-ref/source/random.h | 1 + 4 files changed, 54 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/dat/des/portals/trove.des b/crawl-ref/source/dat/des/portals/trove.des index 901c6764ddc1..dc9875e0f878 100644 --- a/crawl-ref/source/dat/des/portals/trove.des +++ b/crawl-ref/source/dat/des/portals/trove.des @@ -194,7 +194,10 @@ function trove.get_toll_nopiety() end function trove.portal(e) - local toll = trove.get_trove_toll(e) + -- dependent on player stats (skills, race, etc) so needs to be isolated + -- from gameplay rng. + local toll = crawl.rng_wrap(function () return trove.get_trove_toll(e) end, + "subgenerator") local function stair () return trove_marker { diff --git a/crawl-ref/source/l-crawl.cc b/crawl-ref/source/l-crawl.cc index 0326b951fe39..c11c4321e61d 100644 --- a/crawl-ref/source/l-crawl.cc +++ b/crawl-ref/source/l-crawl.cc @@ -6,6 +6,7 @@ #include "l-libs.h" +#include "branch.h" #include "chardump.h" #include "cluautil.h" #include "command.h" @@ -1652,6 +1653,50 @@ LUAFN(crawl_hints_type) return 1; } +LUAFN(crawl_rng_wrap) +{ + if (!lua_isstring(ls, 2)) + luaL_error(ls, "rng_wrap missing rng name"); + string rng_name = lua_tostring(ls, 2); + if (!rng_name.size()) + luaL_error(ls, "rng_wrap missing rng name"); + rng::rng_type r = rng::NUM_RNGS; + if (rng_name == "gameplay") + r = rng::GAMEPLAY; + else if (rng_name == "ui") + r = rng::UI; + else if (rng_name == "system_specific") + r = rng::SYSTEM_SPECIFIC; + else if (rng_name == "subgenerator") + r = rng::SUB_GENERATOR; + else + { + branch_type b = NUM_BRANCHES; + if ((b = branch_by_shortname(rng_name)) == NUM_BRANCHES) + if ((b = branch_by_abbrevname(rng_name)) == NUM_BRANCHES) + luaL_error(ls, "Unknown rng name %s", rng_name.c_str()); + r = rng::get_branch_generator(b); + } + + lua_pop(ls, 1); // get rid of the rng name + if (!lua_isfunction(ls, 1)) + luaL_error(ls, "rng_wrap missing function"); + int result; + if (r == rng::SUB_GENERATOR) + { + rng::subgenerator subgen; // TODO: implement seed + seq? + result = lua_pcall(ls, 0, LUA_MULTRET, 0); + } + else + { + rng::generator gen(r); // generator to use + result = lua_pcall(ls, 0, LUA_MULTRET, 0); + } + if (result != 0) + luaL_error(ls, "Failed to run rng-wrapped function (%d)", result); + return lua_gettop(ls); +} + static const struct luaL_reg crawl_dlib[] = { { "args", _crawl_args }, @@ -1669,6 +1714,7 @@ static const struct luaL_reg crawl_dlib[] = { "mark_game_won", _crawl_mark_game_won }, { "hints_type", crawl_hints_type }, { "unavailable_god", _crawl_unavailable_god }, +{ "rng_wrap", crawl_rng_wrap }, { nullptr, nullptr } }; diff --git a/crawl-ref/source/random.cc b/crawl-ref/source/random.cc index 91423e9e0070..392a9adc798b 100644 --- a/crawl-ref/source/random.cc +++ b/crawl-ref/source/random.cc @@ -61,17 +61,18 @@ namespace rng generator::generator(rng_type g) : previous(_generator) { + ASSERT(g != rng::SUB_GENERATOR); _generator = g; } - static rng_type _get_branch_generator(const branch_type b) + rng_type get_branch_generator(const branch_type b) { return static_cast(rng::LEVELGEN + static_cast(b)); } generator::generator(branch_type b) : previous(_generator) { - _generator = _get_branch_generator(b); + _generator = get_branch_generator(b); } generator::~generator() diff --git a/crawl-ref/source/random.h b/crawl-ref/source/random.h index 1ed64c6ee3db..e417a37eb605 100644 --- a/crawl-ref/source/random.h +++ b/crawl-ref/source/random.h @@ -36,6 +36,7 @@ namespace rng rng_type previous_main; }; + rng_type get_branch_generator(const branch_type b); CrawlVector generators_to_vector(); void load_generators(const CrawlVector &v); vector get_states(); From b9928c75779d3eadf2db6f488989af6798621ceb Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 16 Jul 2019 10:05:25 -0400 Subject: [PATCH 567/864] Remove some mutation validation ASSERTs (11807) If the player gets a lot of xp, the temporary mutation xp value may well be negative and stay negative. A negative value means that the player will get more temp mutations removed the next time they got any xp. There are various alternatives (e.g. maxing this value at 1, running temp_mutation_wanes in a loop until it is non-negative), but I've convinced myself that the current behavior is more or less what's intended. --- crawl-ref/source/mutation.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/crawl-ref/source/mutation.cc b/crawl-ref/source/mutation.cc index 9ef34dd6d4e8..c91c610ab170 100644 --- a/crawl-ref/source/mutation.cc +++ b/crawl-ref/source/mutation.cc @@ -585,9 +585,6 @@ void validate_mutations(bool debug_msg) } } ASSERT(total_temp == you.attribute[ATTR_TEMP_MUTATIONS]); - ASSERT(you.attribute[ATTR_TEMP_MUT_XP] >=0); - if (total_temp > 0) - ASSERT(you.attribute[ATTR_TEMP_MUT_XP] > 0); } string describe_mutations(bool drop_title) From bd264f57081082be2816d3d92b76971e1749e240 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 18 Jul 2019 10:55:45 -0400 Subject: [PATCH 568/864] Separate unique vault tracking for abyss from everything else This commit doesn't affect vaults that place only in one or the other, but for vaults that place in both and are supposed to be unique (e.g. hangedman_summoners_spam, lemuel_flamethrower_hall), these vaults can now in principle independently place twice, once in the abyss and once outside. (The behavior of unseen vaults in the abyss isn't changed, so if they aren't seen in the abyss, they can keep re-placing there.) This is consistent with abyss's flavor as a shadowy mirror of the outside world. Something like this is necessary for seed stability, as long as regular levelgen can be interleaved with the abyss: maps that can place in both abyss and elsewhere and are unique in some way can interfere with incremental pregeneration if they place in the abyss and are seen there, and then would try to place in an as-yet-ungenerated level. There aren't a lot of vaults that this affects, but there are a few, mostly placing in depths and elf. Abyss should be the only branch that this problem applies to. Pan is handled differently, by forcing everything else to pregenerate, and zigs + bazaars have non-overlapping vault lists (plus zigs will force complete pregeneration as well). The implementation is therefore a bit ad hoc in terms of serializing, though I have generalized how unique vault lists are accessed. Semi-related debugging changes: This commit also affects how vaults are shown in morgues, and might be kind of spammy for abyss / pan (it shows every vault that ever places), so this part may need further tweaking. There's also a bit of useful debugging infrastructure. --- crawl-ref/docs/develop/levels/advanced.txt | 16 +++--- crawl-ref/docs/develop/levels/syntax.txt | 6 ++- crawl-ref/source/abyss.cc | 18 +++++++ crawl-ref/source/dbg-maps.cc | 4 ++ crawl-ref/source/dungeon.cc | 57 +++++++++++++++------- crawl-ref/source/dungeon.h | 3 ++ crawl-ref/source/files.cc | 16 +++++- crawl-ref/source/mapdef.cc | 6 +-- crawl-ref/source/player.cc | 2 + crawl-ref/source/player.h | 2 + crawl-ref/source/random.cc | 1 + crawl-ref/source/rng-type.h | 1 + crawl-ref/source/stairs.cc | 8 +++ crawl-ref/source/tag-version.h | 1 + crawl-ref/source/tags.cc | 17 +++++++ crawl-ref/source/wiz-dgn.cc | 4 ++ 16 files changed, 133 insertions(+), 29 deletions(-) diff --git a/crawl-ref/docs/develop/levels/advanced.txt b/crawl-ref/docs/develop/levels/advanced.txt index a0ca239a4416..7dfaf9435d6a 100644 --- a/crawl-ref/docs/develop/levels/advanced.txt +++ b/crawl-ref/docs/develop/levels/advanced.txt @@ -275,10 +275,14 @@ a. Abyssal vaults must be small: no larger than 28x23. 23x23 or smaller vaults are best so that they can be rotated and fit in anywhere on the level. -b. The player may never get a chance to explore unique abyss vaults - (vaults without the "allow_dup" tag). The player may be teleported - away to a different area of the abyss, or never notice your vault - before it shifts away. +b. Unique vaults (vaults without the "allow_dup" tag) are tracked + separately for the abyss, so if a map's DEPTH spec allows it to + place both inside and outside of the abyss, it may appear up to + two times even if unique. The same applies to unique tags. + +c. The player may never get a chance to explore unique abyss vaults. + The player may be teleported away to a different area of the abyss, + or never notice your vault before it shifts away. Unique vaults that the player never sees will be reused by the abyss builder, but it is still possible for the player to see an @@ -287,9 +291,9 @@ b. The player may never get a chance to explore unique abyss vaults can finish exploring it. Once any square of a unique vault has been seen by the player in - the abyss, that vault cannot be reused. + the abyss, that vault cannot be reused within the abyss. -c. Timers and other listeners in an abyssal vault may be discarded at +d. Timers and other listeners in an abyssal vault may be discarded at any time when the abyss shifts and the vault is destroyed. You can still use timers to modify your vaults, but be aware that the timer may be removed at any time as the abyss shifts away from your diff --git a/crawl-ref/docs/develop/levels/syntax.txt b/crawl-ref/docs/develop/levels/syntax.txt index 607bf212092f..14c435b699a6 100644 --- a/crawl-ref/docs/develop/levels/syntax.txt +++ b/crawl-ref/docs/develop/levels/syntax.txt @@ -327,7 +327,8 @@ TAGS: Tags go on a TAGS: line and are space-separated. You can have several property to every square of the vault. See KPROP: below. * "allow_dup": Vaults are normally used only once per game. If you have a vault that can be used more than once, use allow_dup to tell - the dungeon builder that the vault can be reused. + the dungeon builder that the vault can be reused. This is tracked + separately for the abyss and the rest of the dungeon. * "chance_FOO": Maps can be tagged chance_ with any unique suffix to indicate that if the map's CHANCE roll is made, one of the maps tagged chance_FOO should be picked. @@ -379,7 +380,8 @@ TAGS: Tags go on a TAGS: line and are space-separated. You can have several * "uniq_BAR": (uniq_ with any suffix) specifies that only one of the vaults with this tag can be used in a game. In particular, late-Dungeon encompass vaults have the tag uniq_d_encompass, so - that only one will occur per game. + that only one will occur per game. This is tracked separately + for the abyss and the rest of the dungeon. * "luniq": specifies that this vault can be used only once on a given level. "luniq" is only relevant when used with "allow_dup". * "luniq_BAR": (luniq_ with any suffix) specifies that only one diff --git a/crawl-ref/source/abyss.cc b/crawl-ref/source/abyss.cc index dab0c5db5932..f263ef16839e 100644 --- a/crawl-ref/source/abyss.cc +++ b/crawl-ref/source/abyss.cc @@ -20,6 +20,7 @@ #include "colour.h" #include "coordit.h" #include "dbg-scan.h" +#include "dbg-util.h" #include "delay.h" #include "dgn-overview.h" #include "dgn-proclayouts.h" @@ -1493,6 +1494,15 @@ static void abyss_area_shift() // And allow monsters in transit another chance to return. place_transiting_monsters(); + auto &vault_list = you.vault_list[level_id::current()]; +#ifdef DEBUG + vault_list.push_back("[shift]"); +#endif + const auto &level_vaults = level_vault_names(); + vault_list.insert(vault_list.end(), + level_vaults.begin(), level_vaults.end()); + + check_map_validity(); // TODO: should dactions be rerun at this point instead? That would cover // this particular case... @@ -1721,6 +1731,14 @@ void abyss_teleport() forget_map(false); clear_excludes(); gozag_detect_level_gold(false); + auto &vault_list = you.vault_list[level_id::current()]; +#ifdef DEBUG + vault_list.push_back("[tele]"); +#endif + const auto &level_vaults = level_vault_names(); + vault_list.insert(vault_list.end(), + level_vaults.begin(), level_vaults.end()); + more(); } diff --git a/crawl-ref/source/dbg-maps.cc b/crawl-ref/source/dbg-maps.cc index 2ab2b0d2651a..541eae5a77be 100644 --- a/crawl-ref/source/dbg-maps.cc +++ b/crawl-ref/source/dbg-maps.cc @@ -263,6 +263,8 @@ bool mapstat_build_levels() dlua.callfn("dgn_clear_data", ""); you.uniq_map_tags.clear(); you.uniq_map_names.clear(); + you.uniq_map_tags_abyss.clear(); + you.uniq_map_names_abyss.clear(); you.unique_creatures.reset(); initialise_branch_depths(); init_level_connectivity(); @@ -303,6 +305,8 @@ static void _report_available_random_vaults(FILE *outf) { you.uniq_map_tags.clear(); you.uniq_map_names.clear(); + you.uniq_map_tags_abyss.clear(); + you.uniq_map_names_abyss.clear(); fprintf(outf, "\n\nRandom vaults available by dungeon level:\n"); for (auto lvl : generated_levels) diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index b8021f2a6574..1511b363229b 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -231,6 +231,22 @@ static unique_ptr dgn_colour_grid; static string branch_epilogues[NUM_BRANCHES]; +set &get_uniq_map_tags() +{ + if (you.where_are_you == BRANCH_ABYSS) + return you.uniq_map_tags_abyss; + else + return you.uniq_map_tags; +} + +set &get_uniq_map_names() +{ + if (you.where_are_you == BRANCH_ABYSS) + return you.uniq_map_names_abyss; + else + return you.uniq_map_names; +} + /********************************************************************** * builder() - kickoff for the dungeon generator. *********************************************************************/ @@ -241,8 +257,8 @@ bool builder(bool enable_random_maps) ASSERT_RANGE(you.where_are_you, 0, NUM_BRANCHES); ASSERT_RANGE(you.depth, 0 + 1, brdepth[you.where_are_you] + 1); - const set uniq_tags = you.uniq_map_tags; - const set uniq_names = you.uniq_map_names; + const set uniq_tags = get_uniq_map_tags(); + const set uniq_names = get_uniq_map_names(); // For normal cases, this should already be taken care of by enter_level. // However, we want to be really sure that the builder isn't ever run with @@ -290,8 +306,8 @@ bool builder(bool enable_random_maps) reread_maps(); } - you.uniq_map_tags = uniq_tags; - you.uniq_map_names = uniq_names; + get_uniq_map_tags() = uniq_tags; + get_uniq_map_names() = uniq_names; } if (!crawl_state.map_stat_gen && !crawl_state.obj_stat_gen) @@ -605,6 +621,8 @@ void dgn_flush_map_memory() // vaults and map stuff you.uniq_map_tags.clear(); you.uniq_map_names.clear(); + you.uniq_map_tags_abyss.clear(); + you.uniq_map_names_abyss.clear(); you.vault_list.clear(); you.branches_left.reset(); you.branch_stairs.init(0); @@ -697,7 +715,7 @@ static void _set_grd(const coord_def &c, dungeon_feature_type feat) static void _dgn_register_vault(const string &name, const unordered_set &tags) { if (!tags.count("allow_dup")) - you.uniq_map_names.insert(name); + get_uniq_map_names().insert(name); if (tags.count("luniq")) env.level_uniq_maps.insert(name); @@ -708,7 +726,7 @@ static void _dgn_register_vault(const string &name, const unordered_set for (const string &tag : sorted_tags) { if (starts_with(tag, "uniq_")) - you.uniq_map_tags.insert(tag); + get_uniq_map_tags().insert(tag); else if (starts_with(tag, "luniq_")) env.level_uniq_map_tags.insert(tag); } @@ -726,13 +744,13 @@ static void _dgn_register_vault(const string &name, string &spaced_tags) static void _dgn_unregister_vault(const map_def &map) { - you.uniq_map_names.erase(map.name); + get_uniq_map_names().erase(map.name); env.level_uniq_maps.erase(map.name); for (const string &tag : map.get_tags_unsorted()) { if (starts_with(tag, "uniq_")) - you.uniq_map_tags.erase(tag); + get_uniq_map_tags().erase(tag); else if (starts_with(tag, "luniq_")) env.level_uniq_map_tags.erase(tag); } @@ -2118,8 +2136,8 @@ static void _build_overflow_temples() } if (num_gods == 1 - && you.uniq_map_tags.find("uniq_altar_" + name) - != you.uniq_map_tags.end()) + && get_uniq_map_tags().find("uniq_altar_" + name) + != get_uniq_map_tags().end()) { // We've already placed a specialized temple for this // god, so do nothing. @@ -2367,8 +2385,8 @@ static void _place_feature_mimics() // another one to spawn. const char* dst = branches[stair_destination(pos).branch].abbrevname; const string tag = "uniq_" + lowercase_string(dst); - if (you.uniq_map_tags.count(tag)) - you.uniq_map_tags.erase(tag); + if (get_uniq_map_tags().count(tag)) + get_uniq_map_tags().erase(tag); } } } @@ -2648,7 +2666,7 @@ static bool _pan_level() for (int i = 0; i < 4; i++) { - if (!you.uniq_map_tags.count(string("uniq_") + pandemon_level_names[i])) + if (!get_uniq_map_tags().count(string("uniq_") + pandemon_level_names[i])) { all_demons_generated = false; break; @@ -2665,7 +2683,7 @@ static bool _pan_level() { which_demon = random2(4); } - while (you.uniq_map_tags.count(string("uniq_") + while (get_uniq_map_tags().count(string("uniq_") + pandemon_level_names[which_demon])); } @@ -6979,10 +6997,15 @@ string dump_vault_maps() // printing a morgue, this check isn't reliable. Ignore it. if (!is_existing_level(lid) && you.save) { - out += "[-gen,-vis] " + lid.describe() + "\n"; - continue; + out += "[-gen] "; + if (!you.vault_list.count(lid)) + { + out += lid.describe() + "\n"; + continue; + } } - out += you.level_visited(lid) ? "[+gen,+vis] " : "[+gen,-vis] "; + else + out += you.level_visited(lid) ? "[+gen,+vis] " : "[+gen,-vis] "; } out += lid.describe(); vector &maps(you.vault_list[lid]); diff --git a/crawl-ref/source/dungeon.h b/crawl-ref/source/dungeon.h index 623311687473..550cb436bf35 100644 --- a/crawl-ref/source/dungeon.h +++ b/crawl-ref/source/dungeon.h @@ -190,6 +190,9 @@ extern vector Temp_Vaults; extern const map_bitmask *Vault_Placement_Mask; +set &get_uniq_map_tags(); +set &get_uniq_map_names(); + void init_level_connectivity(); void read_level_connectivity(reader &th); void write_level_connectivity(writer &th); diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index aa633557eee0..a43122ebba25 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1497,7 +1497,21 @@ bool generate_level(const level_id &l) dprf("Generating new level for '%s'.", level_name.c_str()); builder(true); - you.vault_list[level_id::current()] = level_vault_names(); + auto &vault_list = you.vault_list[level_id::current()]; +#ifdef DEBUG + // places where a level can generate multiple times. + // could add portals to this list for debugging purposes? + if ( you.where_are_you == BRANCH_ABYSS + || you.where_are_you == BRANCH_PANDEMONIUM + || you.where_are_you == BRANCH_BAZAAR + || you.where_are_you == BRANCH_ZIGGURAT) + { + vault_list.push_back("[gen]"); + } +#endif + const auto &level_vaults = level_vault_names(); + vault_list.insert(vault_list.end(), + level_vaults.begin(), level_vaults.end()); // initialize env for a new level env.turns_on_level = 0; diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc index 7258f931bf2f..7cb86d40d034 100644 --- a/crawl-ref/source/mapdef.cc +++ b/crawl-ref/source/mapdef.cc @@ -2267,13 +2267,13 @@ void map_def::reinit() bool map_def::map_already_used() const { - return you.uniq_map_names.count(name) + return get_uniq_map_names().count(name) || env.level_uniq_maps.find(name) != env.level_uniq_maps.end() || env.new_used_subvault_names.find(name) != env.new_used_subvault_names.end() - || has_any_tag(you.uniq_map_tags.begin(), - you.uniq_map_tags.end()) + || has_any_tag(get_uniq_map_tags().begin(), + get_uniq_map_tags().end()) || has_any_tag(env.level_uniq_map_tags.begin(), env.level_uniq_map_tags.end()) || has_any_tag(env.new_used_subvault_tags.begin(), diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 759747d6a03a..6d08d432ad37 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -5089,6 +5089,8 @@ player::player() uniq_map_tags.clear(); uniq_map_names.clear(); + uniq_map_tags_abyss.clear(); + uniq_map_names_abyss.clear(); vault_list.clear(); global_info = PlaceInfo(); diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h index 4eed0737ade3..025dd4640398 100644 --- a/crawl-ref/source/player.h +++ b/crawl-ref/source/player.h @@ -309,6 +309,8 @@ class player : public actor // Maps without allow_dup that have been already used. set uniq_map_tags; set uniq_map_names; + set uniq_map_tags_abyss; + set uniq_map_names_abyss; // All maps, by level. map > vault_list; diff --git a/crawl-ref/source/random.cc b/crawl-ref/source/random.cc index 392a9adc798b..1fdd7a59a233 100644 --- a/crawl-ref/source/random.cc +++ b/crawl-ref/source/random.cc @@ -107,6 +107,7 @@ namespace rng PcgRNG *get_generator(rng_type r) { + ASSERT(_generator != ASSERT_NO_RNG); if (_generator == SUB_GENERATOR) return _sub_generator; else diff --git a/crawl-ref/source/rng-type.h b/crawl-ref/source/rng-type.h index 1d8018a0600b..ce3b87a2da0d 100644 --- a/crawl-ref/source/rng-type.h +++ b/crawl-ref/source/rng-type.h @@ -12,5 +12,6 @@ namespace rng LEVELGEN, // branch 0, i.e. the dungeon NUM_RNGS = LEVELGEN + NUM_BRANCHES, // and then one for each other branch SUB_GENERATOR, // unsaved -- past NUM_RNGS + ASSERT_NO_RNG, // debugging tool }; } diff --git a/crawl-ref/source/stairs.cc b/crawl-ref/source/stairs.cc index 8ef208e2caf1..36351bb8fce2 100644 --- a/crawl-ref/source/stairs.cc +++ b/crawl-ref/source/stairs.cc @@ -232,6 +232,14 @@ void leaving_level_now(dungeon_feature_type stair_used) you.depth)); } + if (stair_used == DNGN_EXIT_ABYSS) + { +#ifdef DEBUG + auto &vault_list = you.vault_list[level_id::current()]; + vault_list.push_back("[exit]"); +#endif + } + dungeon_events.fire_position_event(DET_PLAYER_CLIMBS, you.pos()); dungeon_events.fire_event(DET_LEAVING_LEVEL); diff --git a/crawl-ref/source/tag-version.h b/crawl-ref/source/tag-version.h index 775f387f6950..e478b5c6bcfb 100644 --- a/crawl-ref/source/tag-version.h +++ b/crawl-ref/source/tag-version.h @@ -233,6 +233,7 @@ enum tag_minor_version TAG_MINOR_THROW_CONSOLIDATION, // Throwing brands consolidated TAG_MINOR_VAMPIRE_NO_EAT, // Decouple Vampires from the food system TAG_MINOR_SINGULAR_THEY, // Add singular they pronouns + TAG_MINOR_ABYSS_UNIQUE_VAULTS, // Separate abyss vault tracking from main dungeon #endif NUM_TAG_MINORS, TAG_MINOR_VERSION = NUM_TAG_MINORS - 1 diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index 397c3e84ad4a..b2526698a9b6 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -1838,6 +1838,10 @@ static void tag_construct_you_dungeon(writer &th) marshallString); marshall_iterator(th, you.uniq_map_names.begin(), you.uniq_map_names.end(), marshallString); + marshall_iterator(th, you.uniq_map_tags_abyss.begin(), + you.uniq_map_tags_abyss.end(), marshallString); + marshall_iterator(th, you.uniq_map_names_abyss.begin(), + you.uniq_map_names_abyss.end(), marshallString); marshallMap(th, you.vault_list, marshall_level_id, marshallStringVector); write_level_connectivity(th); @@ -4297,6 +4301,19 @@ static void tag_read_you_dungeon(reader &th) &string_set::insert, unmarshallString); #if TAG_MAJOR_VERSION == 34 + if (th.getMinorVersion() >= TAG_MINOR_ABYSS_UNIQUE_VAULTS) + { +#endif + unmarshall_container(th, you.uniq_map_tags_abyss, + (ssipair (string_set::*)(const string &)) + &string_set::insert, + unmarshallString); + unmarshall_container(th, you.uniq_map_names_abyss, + (ssipair (string_set::*)(const string &)) + &string_set::insert, + unmarshallString); +#if TAG_MAJOR_VERSION == 34 + } if (th.getMinorVersion() >= TAG_MINOR_VAULT_LIST) // 33:17 has it #endif unmarshallMap(th, you.vault_list, unmarshall_level_id, diff --git a/crawl-ref/source/wiz-dgn.cc b/crawl-ref/source/wiz-dgn.cc index 94c447c6e106..2bdae7b9e11e 100644 --- a/crawl-ref/source/wiz-dgn.cc +++ b/crawl-ref/source/wiz-dgn.cc @@ -588,6 +588,8 @@ static void debug_load_map_by_name(string name, bool primary) { unwind_var um(you.uniq_map_names, string_set()); unwind_var umt(you.uniq_map_tags, string_set()); + unwind_var um_a(you.uniq_map_names_abyss, string_set()); + unwind_var umt_a(you.uniq_map_tags_abyss, string_set()); unwind_var lum(env.level_uniq_maps, string_set()); unwind_var lumt(env.level_uniq_map_tags, string_set()); if (dgn_place_map(toplace, false, false, where)) @@ -790,6 +792,8 @@ void wizard_clear_used_vaults() { you.uniq_map_tags.clear(); you.uniq_map_names.clear(); + you.uniq_map_tags_abyss.clear(); + you.uniq_map_names_abyss.clear(); env.level_uniq_maps.clear(); env.level_uniq_map_tags.clear(); mpr("All vaults are now eligible for [re]use."); From 58b1be019b8ca5dc29bae02a979d95f45d42b02a Mon Sep 17 00:00:00 2001 From: advil Date: Fri, 16 Aug 2019 16:57:14 -0400 Subject: [PATCH 569/864] Default disable incremental pregen for testing This is for the merge of the incremental_pregen branch: the branch includes a wide range of rng improvements etc that are independent of the generation method, so it will be simpler to test the branch online without incremental pregen being enabled by default. If players are interested, they can still enable it in their rc file (`incremental_pregen=true`). Later, I'll default this to true. --- crawl-ref/source/initfile.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index da9000b114bc..52e8d3456622 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -296,8 +296,7 @@ const vector game_options::build_options_list() #ifndef DGAMELAUNCH new BoolGameOption(SIMPLE_NAME(pregen_dungeon), false), #endif - // TODO: should setting this to false be allowed outside of debug builds? - new BoolGameOption(SIMPLE_NAME(incremental_pregen), true), + new BoolGameOption(SIMPLE_NAME(incremental_pregen), false), #ifdef DGL_SIMPLE_MESSAGING From b1ee012021ac18eba2ab70020e491cec500c7449 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 19 Aug 2019 14:07:38 -0400 Subject: [PATCH 570/864] Further domino call refactoring If a level does not use dominoes, there is no need to pass a value at all to the domino parameter as far as I can tell. Random tile variants are selected via other means. --- crawl-ref/source/tileview.cc | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/crawl-ref/source/tileview.cc b/crawl-ref/source/tileview.cc index 5dadb4a0f38b..edd1ac1b6c93 100644 --- a/crawl-ref/source/tileview.cc +++ b/crawl-ref/source/tileview.cc @@ -308,37 +308,36 @@ void tile_clear_flavour() tile_clear_flavour(*ri); } +static bool _level_uses_dominoes() +{ + return you.where_are_you == BRANCH_CRYPT; +} + // For floors and walls that have not already been set to a particular tile, // set them to a random instance of the default floor and wall tileset. void tile_init_flavour() { - vector output; - + if (_level_uses_dominoes()) { - rng::subgenerator sub_rng( - static_cast(you.where_are_you ^ you.game_seed), - static_cast(you.depth)); + vector output; - if (you.where_are_you == BRANCH_CRYPT) { + rng::subgenerator sub_rng( + static_cast(you.where_are_you ^ you.game_seed), + static_cast(you.depth)); output.reserve(X_WIDTH * Y_WIDTH); domino::DominoSet dominoes(domino::cohen_set, 8); // TODO: don't pass a PcgRNG object dominoes.Generate(X_WIDTH, Y_WIDTH, output, rng::current_generator()); } - else - { - output.resize(X_WIDTH * Y_WIDTH); - for (auto &o : output) - o = rng::get_uint32(); - } - } - for (rectangle_iterator ri(0); ri; ++ri) - { - unsigned int idx = ri->x + ri->y * GXM; - tile_init_flavour(*ri, output[idx]); + + for (rectangle_iterator ri(0); ri; ++ri) + tile_init_flavour(*ri, output[ri->x + ri->y * GXM]); } + else + for (rectangle_iterator ri(0); ri; ++ri) + tile_init_flavour(*ri, 0); } // 11111333333 55555555 From 7d3d5a44bdd0c52f2155259033ff80f27af59e3f Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 19 Aug 2019 17:20:01 -0400 Subject: [PATCH 571/864] Simplify pregen options and update documentation. --- crawl-ref/docs/crawl_manual.rst | 4 +-- crawl-ref/docs/options_guide.txt | 19 +++++++----- crawl-ref/source/initfile.cc | 36 +++++++++++++++++++---- crawl-ref/source/test/stress/fireworks.rc | 2 +- 4 files changed, 45 insertions(+), 16 deletions(-) diff --git a/crawl-ref/docs/crawl_manual.rst b/crawl-ref/docs/crawl_manual.rst index 1ddb55763024..52d8ac756873 100644 --- a/crawl-ref/docs/crawl_manual.rst +++ b/crawl-ref/docs/crawl_manual.rst @@ -492,9 +492,9 @@ same or different devices, please report it as a bug. However, keep in mind that upgrading your save game between multiple versions of crawl will naturally lead to seed divergence. When playing offline, if you would like to ensure that your game can be upgraded without divergence, you can set -'pregen_dungeon = true' in your options file. (This will also ensure +'pregen_dungeon = full' in your options file. (This will also ensure completely stable unique artefact placement.) On the other hand, to completely -disable incremental pregeneration, you can set 'incremental_pregen = false'. +disable incremental pregeneration, you can set 'pregen_dungeon = false'. Further Help ======================================== diff --git a/crawl-ref/docs/options_guide.txt b/crawl-ref/docs/options_guide.txt index 3e0d4cb2987e..877dd327d12f 100644 --- a/crawl-ref/docs/options_guide.txt +++ b/crawl-ref/docs/options_guide.txt @@ -410,14 +410,17 @@ game_seed = none "-seed", which will override any rc file setting. This value is an unsigned 64 bit integer. -pregen_dungeon = false - When set to true, the game will pregenerate the entire connected dungeon - when starting a new character. This leads to more deterministic dungeon - generation relative to a particular game seed. If this is false, levels - will be generated as you enter them, and the order in which you traverse - the dungeon will lead to different dungeons for the same game seed. With - this set to true, you still may encounter variation in portal vaults, - the abyss, pandemonium, and ziggurats. +pregen_dungeon = classic + When set to `true` or `full`, the game will pregenerate the entire + connected dungeon when starting a new character. This leads to + deterministic dungeon generation relative to a particular game seed, at + the cost of a slow game start. If set to `incremental`, the game will + generate levels as needed so that it always generates them in the same + order, also producing a deterministic dungeon. You still may encounter + variation in bazaars, the abyss, pandemonium, and ziggurats, and for + incremental pregeneration, artefacts. When set to `false` or `classic`, + the game will generate all levels on level entry, as was the rule before + 0.23. Some servers may disallow full pregeneration. 2- File System. ================ diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index 52e8d3456622..c42914a8fbeb 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -293,11 +293,6 @@ const vector game_options::build_options_list() new ColourThresholdOption(stat_colour, {"stat_colour", "stat_color"}, "3:red", _first_less), new StringGameOption(SIMPLE_NAME(sound_file_path), ""), -#ifndef DGAMELAUNCH - new BoolGameOption(SIMPLE_NAME(pregen_dungeon), false), -#endif - new BoolGameOption(SIMPLE_NAME(incremental_pregen), false), - #ifdef DGL_SIMPLE_MESSAGING new BoolGameOption(SIMPLE_NAME(messaging), false), @@ -1032,6 +1027,9 @@ void game_options::reset_options() char_set = CSET_DEFAULT; + incremental_pregen = false; + pregen_dungeon = false; + // set it to the .crawlrc default autopickups.reset(); autopickups.set(OBJ_GOLD); @@ -3455,6 +3453,34 @@ void game_options::read_option_line(const string &str, bool runscript) } #endif } + else if (key == "pregen_dungeon") + { + // TODO: probably convert the underlying values to some kind of enum + // TODO: store these options in a save? + if (field == "true" || field == "full") + { +#ifdef DGAMELAUNCH + report_error( + "Full pregeneration is not allowed on this build of crawl."); +#else + pregen_dungeon = true; + incremental_pregen = true; // still affects loading games not + // started with full pregen +#endif + } + else if (field == "incremental") + { + pregen_dungeon = false; + incremental_pregen = true; + } + else if (field == "false" || field == "classic") + pregen_dungeon = incremental_pregen = false; + else + { + report_error("Unknown value '%s' for pregen_dungeon.", + field.c_str()); + } + } #ifdef USE_TILE // TODO: generalize these to an option type? else if (key == "tile_viewport_scale") diff --git a/crawl-ref/source/test/stress/fireworks.rc b/crawl-ref/source/test/stress/fireworks.rc index 40eb959f1389..f2449ebf8b75 100644 --- a/crawl-ref/source/test/stress/fireworks.rc +++ b/crawl-ref/source/test/stress/fireworks.rc @@ -7,7 +7,7 @@ species = mu background = ar restart_after_game = false show_more = false -incremental_pregen = false +pregen_dungeon = false #message_colour = mute:.* : bot_start = true From d66451a9e92fd8140856af317dc872710e4d13ed Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 20 Aug 2019 11:35:51 -0400 Subject: [PATCH 572/864] Handle portals differently in dungeon overview (12048) 44eecae1 changed how portals are handled in the branch structure, and in so doing caused a change in behavior where they got added to `stair_level` if entered (via enter_branch, which didn't used to get called on them), and therefore showed up in the overview and G menu even though after exiting the portal branch. The entry in that structure is just an empty set, which previously wasn't possible, and caused them to render in a confusing way in the overview. This commit embraces the bug and shows previously entered portals in the overview as e.g. `IceCv (visited)`. A portal you are currently in will show as `IceCv (1/1)`. The empty set case is also now handled for `G`. An empty entry to stair_level, previously not possible, now has the semantics of a branch that no longer has stairs; it is worth noting that I didn't implement any way for portal stair sources to actually appear in this structure, so this semantics as described is not fully implemented (in that a portal branch will still have no source stairs even while the player is in it or have seen but not traversed the portal entry). There are some complexities with fully implementing this part that made it not seem worthwhile, including handling seen portals vanishing while not in los, and the fact that multiple bazaar entries could in principle exist at once (I think). Any game played between 44eecae1 and now may have missing portal branches if they were entered with `<` instead of `>` -- not going to worry about this. --- crawl-ref/source/dgn-overview.cc | 23 +++++++++++++++++++---- crawl-ref/source/stairs.cc | 4 ++-- crawl-ref/source/travel.cc | 2 +- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/crawl-ref/source/dgn-overview.cc b/crawl-ref/source/dgn-overview.cc index 87726da9c601..1bc053addc91 100644 --- a/crawl-ref/source/dgn-overview.cc +++ b/crawl-ref/source/dgn-overview.cc @@ -254,6 +254,8 @@ static string _get_seen_branches(bool display) if (branch == root_branch || stair_level.count(branch)) { + // having an entry for branch that is an empty set means a branch + // that no longer has any stairs. level_id lid(branch, 0); lid = find_deepest_explored(lid); @@ -266,10 +268,21 @@ static string _get_seen_branches(bool display) ? it->shortname : it->abbrevname); - snprintf(buffer, sizeof buffer, - "%*s (%d/%d)%s", - branch == root_branch ? -7 : 7, - brname, lid.depth, brdepth[branch], entry_desc.c_str()); + if (entry_desc.size() == 0 && branch != BRANCH_DUNGEON + && you.where_are_you != branch) + { + // previously visited portal branches + snprintf(buffer, sizeof buffer, + "%7s (visited)", + brname); + } + else + { + snprintf(buffer, sizeof buffer, + "%*s (%d/%d)%s", + branch == root_branch ? -7 : 7, + brname, lid.depth, brdepth[branch], entry_desc.c_str()); + } disp += buffer; num_printed_branches++; @@ -810,6 +823,8 @@ void explored_tracked_feature(dungeon_feature_type feat) void enter_branch(branch_type branch, level_id from) { + // this will ensure that branch is in stair_level either way + // TODO: track stair levels for portal branches somehow? if (stair_level[branch].size() > 1) { stair_level[branch].clear(); diff --git a/crawl-ref/source/stairs.cc b/crawl-ref/source/stairs.cc index 36351bb8fce2..22fe69f8b6b1 100644 --- a/crawl-ref/source/stairs.cc +++ b/crawl-ref/source/stairs.cc @@ -824,8 +824,8 @@ void floor_transition(dungeon_feature_type how, mpr(rune_msg); } - // Entered a regular (non-portal) branch from above. - if (!going_up && parent_branch(branch) == old_level.branch) + // Entered a branch from its parent. + if (parent_branch(branch) == old_level.branch) enter_branch(branch, old_level); } diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc index 7ba0bd5ea555..e25fa01fd844 100644 --- a/crawl-ref/source/travel.cc +++ b/crawl-ref/source/travel.cc @@ -2040,7 +2040,7 @@ bool is_known_branch_id(branch_type branch) // If the overview knows the stairs to this branch, we know the branch. return stair_level.find(static_cast(branch)) - != stair_level.end(); + != stair_level.end() && stair_level[branch].size(); } static bool _is_known_branch(const Branch &br) From 91963d7417d8e2c616ca70aa8b00915a2aef419d Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 20 Aug 2019 13:41:25 -0400 Subject: [PATCH 573/864] Remove a debugging check that is tripping for dith chars Will return once I figure out why this is triggering. --- crawl-ref/source/monster.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/crawl-ref/source/monster.cc b/crawl-ref/source/monster.cc index 928a58cb1b23..ca868829c3eb 100644 --- a/crawl-ref/source/monster.cc +++ b/crawl-ref/source/monster.cc @@ -3533,8 +3533,6 @@ void monster::suicide(int hp_target) mon_holy_type monster::holiness(bool /*temp*/) const { - rng::ASSERT_stable rng_check; - // zombie kraken tentacles if (testbits(flags, MF_FAKE_UNDEAD)) return MH_UNDEAD; From dfe76135efb4fbd6ce75af206eb522423c840e4a Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 20 Aug 2019 14:46:18 -0400 Subject: [PATCH 574/864] Put seed in crashlogs This is risky in that it has some cheating potential, we may even want to disable this for tournaments or in general, but it's incredibly frustrating to not have this information in trunk crashes right now. --- crawl-ref/source/dbg-asrt.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crawl-ref/source/dbg-asrt.cc b/crawl-ref/source/dbg-asrt.cc index e535e70ab3dd..2e9e20169e2e 100644 --- a/crawl-ref/source/dbg-asrt.cc +++ b/crawl-ref/source/dbg-asrt.cc @@ -564,6 +564,12 @@ static void _dump_ver_stuff(FILE* file) #else fprintf(file, "Tiles: no\n\n"); #endif + if (you.game_is_seeded) + fprintf(file, "Seed: %" PRIu64 "\n", crawl_state.seed); + if (Version::history_size() > 1) + { + fprintf(file, "Version history:\n%s\n\n", Version::history().c_str()); + } } static void _dump_command_line(FILE *file) From f1077d32986cf6467d21ea71a9a20814b1eb34b4 Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 20 Aug 2019 15:06:32 -0400 Subject: [PATCH 575/864] Don't update brentry for portal mimics Also, change the ASSERT to an mprf for now, in lieu of real save compat (which doesn't seem worth the effort). I will likely change this back at some point, because annoying as it is, this ASSERT has found a ton of bugs and edge cases. --- crawl-ref/source/files.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index a43122ebba25..3b629c7fc1b3 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1400,7 +1400,7 @@ void update_portal_entrances() { dungeon_feature_type feat = env.grid(*ri); // excludes pan, hell, abyss. - if (feat_is_portal_entrance(feat)) + if (feat_is_portal_entrance(feat) && !feature_mimic_at(*ri)) { level_id whither = stair_destination(feat, "", false); if (whither.branch == BRANCH_ZIGGURAT // not (quite) pregenerated @@ -1413,7 +1413,11 @@ void update_portal_entrances() ASSERT(count(portal_generation_order.begin(), portal_generation_order.end(), whither.branch) == 1); - ASSERT(brentry[whither.branch] == level_id()); // violated by multiple portals + if (brentry[whither.branch] != level_id()) + { + mprf(MSGCH_ERROR, "Second portal entrance for %s!", + whither.describe().c_str()); + } brentry[whither.branch] = cur_level; seen_portals.insert(whither.branch); } From 962dd19927ed352175a5f49fb5c6c76483002fa5 Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 20 Aug 2019 15:23:09 -0400 Subject: [PATCH 576/864] Fix a gcc warning Noticed while rebuilding cbro --- crawl-ref/source/tags.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index b2526698a9b6..82714051a8d8 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -868,7 +868,7 @@ static string unmarshallString2(reader &th) void marshallString4(writer &th, const string &data) { const size_t len = data.length(); - if (len > numeric_limits::max()) + if (len > static_cast(numeric_limits::max())) die("trying to marshall too long a string (len=%ld)", (long int) len); marshallInt(th, len); th.write(data.c_str(), len); From 6a6c3f83c19575dbe09a523c4e2fa26e2ad1b6f0 Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 20 Aug 2019 15:26:51 -0400 Subject: [PATCH 577/864] Fix another misc compiler warning Also, unbrace. --- crawl-ref/source/dbg-asrt.cc | 2 -- crawl-ref/source/dbg-objstat.cc | 1 - 2 files changed, 3 deletions(-) diff --git a/crawl-ref/source/dbg-asrt.cc b/crawl-ref/source/dbg-asrt.cc index 2e9e20169e2e..68d05ccabb14 100644 --- a/crawl-ref/source/dbg-asrt.cc +++ b/crawl-ref/source/dbg-asrt.cc @@ -567,9 +567,7 @@ static void _dump_ver_stuff(FILE* file) if (you.game_is_seeded) fprintf(file, "Seed: %" PRIu64 "\n", crawl_state.seed); if (Version::history_size() > 1) - { fprintf(file, "Version history:\n%s\n\n", Version::history().c_str()); - } } static void _dump_command_line(FILE *file) diff --git a/crawl-ref/source/dbg-objstat.cc b/crawl-ref/source/dbg-objstat.cc index 81a5b1ea15a2..248108be9847 100644 --- a/crawl-ref/source/dbg-objstat.cc +++ b/crawl-ref/source/dbg-objstat.cc @@ -1103,7 +1103,6 @@ static void _write_branch_item_stats(branch_type br, const item_type &item) { unsigned int level_count = 0; const vector &fields = item_fields[item.base_type]; - vector::const_iterator li; const string name = _item_name(item); const char *num_field = _item_has_antiquity(item.base_type) ? "AllNum" : "Num"; From c0fa6600bf77c549186ab8d4e74820f4ac84c170 Mon Sep 17 00:00:00 2001 From: runrin <52256543+runrin@users.noreply.github.com> Date: Wed, 21 Aug 2019 16:15:06 -0700 Subject: [PATCH 578/864] Add attack-no-move bindings for Colemak --- crawl-ref/settings/colemak_command_keys.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/crawl-ref/settings/colemak_command_keys.txt b/crawl-ref/settings/colemak_command_keys.txt index e8e28e225da3..80ad2defdadc 100644 --- a/crawl-ref/settings/colemak_command_keys.txt +++ b/crawl-ref/settings/colemak_command_keys.txt @@ -54,6 +54,15 @@ bindkey = [L] CMD_MAP_JUMP_UP_RIGHT bindkey = [B] CMD_MAP_JUMP_DOWN_LEFT bindkey = [K] CMD_MAP_JUMP_DOWN_RIGHT +bindkey = [^H] CMD_ATTACK_LEFT +bindkey = [^N] CMD_ATTACK_DOWN +bindkey = [^E] CMD_ATTACK_UP +bindkey = [^I] CMD_ATTACK_RIGHT +bindkey = [^J] CMD_ATTACK_UP_LEFT +bindkey = [^L] CMD_ATTACK_UP_RIGHT +bindkey = [^B] CMD_ATTACK_DOWN_LEFT +bindkey = [^K] CMD_ATTACK_DOWN_RIGHT + # replace (e) with (u) bindkey = [u] CMD_EAT bindkey = [u] CMD_TARGET_EXCLUDE From 4d4af813a0195fbcfa9d582311f468b014b814c9 Mon Sep 17 00:00:00 2001 From: Alan Malloy Date: Sun, 25 Aug 2019 12:40:14 -0700 Subject: [PATCH 579/864] Revert "Add attack-no-move bindings for Colemak" (#1140) This reverts commit c0fa6600bf77c549186ab8d4e74820f4ac84c170. --- crawl-ref/settings/colemak_command_keys.txt | 9 --------- 1 file changed, 9 deletions(-) diff --git a/crawl-ref/settings/colemak_command_keys.txt b/crawl-ref/settings/colemak_command_keys.txt index 80ad2defdadc..e8e28e225da3 100644 --- a/crawl-ref/settings/colemak_command_keys.txt +++ b/crawl-ref/settings/colemak_command_keys.txt @@ -54,15 +54,6 @@ bindkey = [L] CMD_MAP_JUMP_UP_RIGHT bindkey = [B] CMD_MAP_JUMP_DOWN_LEFT bindkey = [K] CMD_MAP_JUMP_DOWN_RIGHT -bindkey = [^H] CMD_ATTACK_LEFT -bindkey = [^N] CMD_ATTACK_DOWN -bindkey = [^E] CMD_ATTACK_UP -bindkey = [^I] CMD_ATTACK_RIGHT -bindkey = [^J] CMD_ATTACK_UP_LEFT -bindkey = [^L] CMD_ATTACK_UP_RIGHT -bindkey = [^B] CMD_ATTACK_DOWN_LEFT -bindkey = [^K] CMD_ATTACK_DOWN_RIGHT - # replace (e) with (u) bindkey = [u] CMD_EAT bindkey = [u] CMD_TARGET_EXCLUDE From 87330a484a5e8253640eea2ee8783b60cf2fc93c Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 27 Aug 2019 13:38:39 -0400 Subject: [PATCH 580/864] Enable incremental pregen as a default for new games, track in save Finally flipping the switch. Reason for adding to the save: This turns out to make more sense if the option sets a flag in the save, rather than the option determining the behavior of the current crawl session. Something like this should probably have been in the beginning, but the option of using "classic" levelgen was added quite late in the process. All of this could be simplified from the user's perspective by making the existence of classic levelgen less obvious, or debug-only, and I may do this in a future commit. --- crawl-ref/docs/options_guide.txt | 2 +- crawl-ref/source/chardump.cc | 7 +++++-- crawl-ref/source/command.cc | 9 ++++++--- crawl-ref/source/dbg-asrt.cc | 7 +++++-- crawl-ref/source/files.cc | 2 +- crawl-ref/source/initfile.cc | 2 +- crawl-ref/source/ng-setup.cc | 1 + crawl-ref/source/player.cc | 3 ++- crawl-ref/source/player.h | 4 +++- crawl-ref/source/tag-version.h | 1 + crawl-ref/source/tags.cc | 16 +++++++++++++--- 11 files changed, 39 insertions(+), 15 deletions(-) diff --git a/crawl-ref/docs/options_guide.txt b/crawl-ref/docs/options_guide.txt index 877dd327d12f..23540949de6d 100644 --- a/crawl-ref/docs/options_guide.txt +++ b/crawl-ref/docs/options_guide.txt @@ -410,7 +410,7 @@ game_seed = none "-seed", which will override any rc file setting. This value is an unsigned 64 bit integer. -pregen_dungeon = classic +pregen_dungeon = incremental When set to `true` or `full`, the game will pregenerate the entire connected dungeon when starting a new character. This leads to deterministic dungeon generation relative to a particular game seed, at diff --git a/crawl-ref/source/chardump.cc b/crawl-ref/source/chardump.cc index 9597a55558c3..c238c037ac27 100644 --- a/crawl-ref/source/chardump.cc +++ b/crawl-ref/source/chardump.cc @@ -212,7 +212,7 @@ static void _sdump_header(dump_params &par) #endif par.text += " character file.\n\n"; - if (you.game_is_seeded + if (you.fully_seeded #ifdef DGAMELAUNCH && (par.se // for online games, show seed for a dead char || you.wizard @@ -220,7 +220,10 @@ static void _sdump_header(dump_params &par) #endif ) { - par.text += make_stringf("Game seed: %" PRIu64 "\n\n", crawl_state.seed); + par.text += make_stringf( + "Game seed: %" PRIu64 ", levelgen mode: %s\n\n", + crawl_state.seed, you.deterministic_levelgen + ? "deterministic" : "classic"); } } diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc index ae930593f487..a04372c19c48 100644 --- a/crawl-ref/source/command.cc +++ b/crawl-ref/source/command.cc @@ -99,11 +99,14 @@ static string _get_version_features() #endif ) { - if (you.game_is_seeded) + if (you.fully_seeded) { - result += make_stringf("Game seed: %" PRIu64, crawl_state.seed); + result += make_stringf( + "Game seed: %" PRIu64 ", levelgen mode: %s", + crawl_state.seed, you.deterministic_levelgen + ? "deterministic" : "classic"); if (Version::history_size() > 1) - result += " (game has been upgraded, seed may be affected)"; + result += " (seed may be affected by game upgrades)"; } else result += "Game is not seeded."; diff --git a/crawl-ref/source/dbg-asrt.cc b/crawl-ref/source/dbg-asrt.cc index 68d05ccabb14..9a9d8a012000 100644 --- a/crawl-ref/source/dbg-asrt.cc +++ b/crawl-ref/source/dbg-asrt.cc @@ -564,8 +564,11 @@ static void _dump_ver_stuff(FILE* file) #else fprintf(file, "Tiles: no\n\n"); #endif - if (you.game_is_seeded) - fprintf(file, "Seed: %" PRIu64 "\n", crawl_state.seed); + if (you.fully_seeded) + { + fprintf(file, "Seed: %" PRIu64 ", deterministic pregen: %d\n", + crawl_state.seed, (int) you.deterministic_levelgen); + } if (Version::history_size() > 1) fprintf(file, "Version history:\n%s\n\n", Version::history().c_str()); } diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 3b629c7fc1b3..2d34ee0c907f 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1578,7 +1578,7 @@ static const vector branch_generation_order = static bool _branch_pregenerates(branch_type b) { - if (!Options.incremental_pregen) + if (!you.deterministic_levelgen) return false; return count(branch_generation_order.begin(), branch_generation_order.end(), b) > 0; diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index c42914a8fbeb..a6855db89d71 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -1027,7 +1027,7 @@ void game_options::reset_options() char_set = CSET_DEFAULT; - incremental_pregen = false; + incremental_pregen = true; pregen_dungeon = false; // set it to the .crawlrc default diff --git a/crawl-ref/source/ng-setup.cc b/crawl-ref/source/ng-setup.cc index baa4333c1e14..4cdab13271a5 100644 --- a/crawl-ref/source/ng-setup.cc +++ b/crawl-ref/source/ng-setup.cc @@ -473,6 +473,7 @@ static void _setup_generic(const newgame_def& ng) rng::reset(); // initialize rng from Options.seed _init_player(); you.game_seed = crawl_state.seed; + you.deterministic_levelgen = Options.incremental_pregen; #if TAG_MAJOR_VERSION == 34 // Avoid the remove_dead_shops() Gozag fixup in new games: see diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 6d08d432ad37..1d9bff7551cb 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -5160,7 +5160,8 @@ player::player() abyss_speed = 0; game_seed = 0; - game_is_seeded = true; + fully_seeded = true; + deterministic_levelgen = true; old_hunger = hunger; diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h index 025dd4640398..1b6092f09911 100644 --- a/crawl-ref/source/player.h +++ b/crawl-ref/source/player.h @@ -361,7 +361,9 @@ class player : public actor // Hash seed for deterministic stuff. uint64_t game_seed; - bool game_is_seeded; + bool fully_seeded; // true on all games started since 0.23 seeding changes + bool deterministic_levelgen; // true if a game was started with incremental + // or full pregen. // ------------------- // Non-saved UI state: diff --git a/crawl-ref/source/tag-version.h b/crawl-ref/source/tag-version.h index e478b5c6bcfb..a9530484646b 100644 --- a/crawl-ref/source/tag-version.h +++ b/crawl-ref/source/tag-version.h @@ -234,6 +234,7 @@ enum tag_minor_version TAG_MINOR_VAMPIRE_NO_EAT, // Decouple Vampires from the food system TAG_MINOR_SINGULAR_THEY, // Add singular they pronouns TAG_MINOR_ABYSS_UNIQUE_VAULTS, // Separate abyss vault tracking from main dungeon + TAG_MINOR_INCREMENTAL_PREGEN, // save tracks whether the game is an incremental pregen game #endif NUM_TAG_MINORS, TAG_MINOR_VERSION = NUM_TAG_MINORS - 1 diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index 82714051a8d8..600d48e5cdcd 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -1670,7 +1670,8 @@ static void tag_construct_you(writer &th) marshallUByte(th, 1); // number of seeds, for historical reasons: always 1 marshallUnsigned(th, you.game_seed); - marshallBoolean(th, you.game_is_seeded); + marshallBoolean(th, you.fully_seeded); // TODO: remove on major version inc? + marshallBoolean(th, you.deterministic_levelgen); CrawlVector rng_states = rng::generators_to_vector(); rng_states.write(th); @@ -3695,7 +3696,7 @@ static void tag_read_you(reader &th) you.game_seed = count > 0 ? unmarshallInt(th) : rng::get_uint64(); dprf("Upgrading from unseeded game."); crawl_state.seed = you.game_seed; - you.game_is_seeded = false; + you.fully_seeded = false; for (int i = 1; i < count; i++) unmarshallInt(th); } @@ -3708,7 +3709,16 @@ static void tag_read_you(reader &th) you.game_seed = unmarshallUnsigned(th); dprf("Unmarshalling seed %" PRIu64, you.game_seed); crawl_state.seed = you.game_seed; - you.game_is_seeded = unmarshallBoolean(th); + you.fully_seeded = unmarshallBoolean(th); +#if TAG_MAJOR_VERSION == 34 + // there is no way to tell the levelgen method for games before this + // tag, unfortunately. Though if there are unvisited generated levels, + // that guarantees some form of deterministic pregen. + if (th.getMinorVersion() < TAG_MINOR_INCREMENTAL_PREGEN) + you.deterministic_levelgen = false; + else +#endif + you.deterministic_levelgen = unmarshallBoolean(th); CrawlVector rng_states; rng_states.read(th); rng::load_generators(rng_states); From 9d6b971ae405f9fbefc81b386ae4fa3a08c3f442 Mon Sep 17 00:00:00 2001 From: Nikolai Lavsky <3328424+nlavsky@users.noreply.github.com> Date: Tue, 27 Aug 2019 16:00:40 +0300 Subject: [PATCH 581/864] Add missing feature tiles to the stash search menu PR #1051 allowed searching for traps, but several trap tiles are absent from the stash search menu. As mentioned in 276b1762, the current method of picking feature tiles by the search result description has some limitations. It works correctly for features that have a separate dungeon_feature_type, for example, regular teleport traps or altars. But there are dungeon features that have the same dungeon_feature_type, but different description: * Net traps, pressure plates, and all other mechanical traps are all DNGN_TRAP_MECHANICAL. * Permanent teleport traps share DNGN_TRAP_TELEPORT type with regular teleport traps. * Doors can have different descriptions too: 2-3 adjacent runed doors become "large runed doors", 4+ doors become "huge runed gates." If there is no matching description, feat_by_desc() returns DNGN_UNSEEN, which is why the search menu doesn't show tiles for these dungeon features. This commit fixes that by handling tile picking for traps and runed doors separately. --- crawl-ref/source/stash.cc | 12 ++++++++++++ crawl-ref/source/stash.h | 7 +++++-- crawl-ref/source/tilepick.cc | 4 ++-- crawl-ref/source/tilepick.h | 2 ++ 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/stash.cc b/crawl-ref/source/stash.cc index 3129406e8376..d3bf2af35e57 100644 --- a/crawl-ref/source/stash.cc +++ b/crawl-ref/source/stash.cc @@ -479,6 +479,7 @@ vector Stash::matches_search( res.match = fdesc; res.primary_sort = fdesc; res.feat = feat; + res.trap = trap; results.push_back(res); } } @@ -1759,6 +1760,17 @@ bool StashTracker::display_search_results( } else if (res.shop) me->add_tile(tile_def(tileidx_shop(&res.shop->shop), TEX_FEAT)); + else if (feat_is_trap(res.feat)) + { + const tileidx_t idx = tileidx_trap(res.trap); + me->add_tile(tile_def(idx, get_dngn_tex(idx))); + } + else if (feat_is_runed(res.feat)) + { + // Handle large doors and huge gates + const tileidx_t idx = tileidx_feature_base(res.feat); + me->add_tile(tile_def(idx, get_dngn_tex(idx))); + } else { const dungeon_feature_type feat = feat_by_desc(res.match); diff --git a/crawl-ref/source/stash.h b/crawl-ref/source/stash.h index f5f27829c987..4cebd2d3435a 100644 --- a/crawl-ref/source/stash.h +++ b/crawl-ref/source/stash.h @@ -147,6 +147,9 @@ struct stash_search_result // Type of feature, if this result is for a feature. dungeon_feature_type feat; + // Type of trap, if this result is for a trap. + trap_type trap; + // Whether the found items are in the player's inventory. bool in_inventory; @@ -156,8 +159,8 @@ struct stash_search_result stash_search_result() : pos(), player_distance(0), match_type(), match(), primary_sort(), item(), shop(nullptr), feat(), - in_inventory(false), duplicates(0), - duplicate_piles(0) + trap(TRAP_UNASSIGNED), in_inventory(false), + duplicates(0), duplicate_piles(0) { } diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc index 38c19ebc9f0c..38ebe76c397e 100644 --- a/crawl-ref/source/tilepick.cc +++ b/crawl-ref/source/tilepick.cc @@ -75,7 +75,7 @@ TextureID get_dngn_tex(tileidx_t idx) return TEX_FEAT; } -static tileidx_t _tileidx_trap(trap_type type) +tileidx_t tileidx_trap(trap_type type) { switch (type) { @@ -558,7 +558,7 @@ tileidx_t tileidx_feature(const coord_def &gc) case DNGN_TRAP_MECHANICAL: case DNGN_TRAP_TELEPORT: - return _tileidx_trap(env.map_knowledge(gc).trap()); + return tileidx_trap(env.map_knowledge(gc).trap()); case DNGN_TRAP_WEB: { diff --git a/crawl-ref/source/tilepick.h b/crawl-ref/source/tilepick.h index ae6996b29d95..d825552f90b2 100644 --- a/crawl-ref/source/tilepick.h +++ b/crawl-ref/source/tilepick.h @@ -8,6 +8,7 @@ #include "ability-type.h" #include "command-type.h" #include "game-type.h" +#include "trap-type.h" #include "tiledef_defines.h" #define TILE_NUM_KEY "tile_num" @@ -24,6 +25,7 @@ bool is_door_tile(tileidx_t tile); // Tile index lookup from Crawl data. tileidx_t tileidx_feature(const coord_def &gc); +tileidx_t tileidx_trap(trap_type type); tileidx_t tileidx_shop(const shop_struct *shop); tileidx_t tileidx_feature_base(dungeon_feature_type feat); tileidx_t tileidx_out_of_bounds(int branch); From 5c5dc1b5cbf4915a3c6f8be9ceb49c9f07ac0468 Mon Sep 17 00:00:00 2001 From: Kate <601195+semitonal@users.noreply.github.com> Date: Tue, 3 Sep 2019 18:58:58 +0100 Subject: [PATCH 582/864] Update CREDITS.txt [skip ci] --- crawl-ref/CREDITS.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/CREDITS.txt b/crawl-ref/CREDITS.txt index fa2ef6b1f23d..c80b1330dfa6 100644 --- a/crawl-ref/CREDITS.txt +++ b/crawl-ref/CREDITS.txt @@ -341,7 +341,7 @@ The Dungeon Crawl Stone Soup development team is: Corin Buchanan-Howland James Bulgin Robert Burnham - Chris Campbell + Kate Campbell Matthew Cline Florian Diebold Rax E. Dillon From 8e0e932a4cf3f16331e567f9e4398f94090c86b4 Mon Sep 17 00:00:00 2001 From: Kate <601195+semitonal@users.noreply.github.com> Date: Fri, 6 Sep 2019 23:44:08 +0100 Subject: [PATCH 583/864] Update mailmap [skip ci] --- .mailmap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mailmap b/.mailmap index d72e418ac059..5cdf0f857a52 100644 --- a/.mailmap +++ b/.mailmap @@ -36,7 +36,7 @@ galehar galehar elliptic edlothiol -MarvinPA +kate- <601195+semitonal@users.noreply.github.com> SamB |amethyst dolorous From aff5e891e6c0bd1d4b0ce619415e44e34b232c2e Mon Sep 17 00:00:00 2001 From: kitchen-ace <68k@quikphix.org> Date: Thu, 5 Sep 2019 16:47:32 -0400 Subject: [PATCH 584/864] Show scarves on player in tiles (11977) Scarves weren't being shown at all unless the player chose one through the doll editor. And even then they were practically invisible, since they were drawn behind the body (like cloaks) instead of in front where I think they were meant to be. The green scarf tile looks quite strange to me, but that's a separate problem. --- crawl-ref/source/tiledoll.cc | 11 +++++++++++ crawl-ref/source/tilepick-p.cc | 15 +++++++++++++-- crawl-ref/source/tileweb.cc | 11 +++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/tiledoll.cc b/crawl-ref/source/tiledoll.cc index a18dd316ca28..a1cc462717ff 100644 --- a/crawl-ref/source/tiledoll.cc +++ b/crawl-ref/source/tiledoll.cc @@ -546,6 +546,17 @@ void pack_doll_buf(SubmergedTileBuffer& buf, const dolls_data &doll, p_order[6] = TILEP_PART_LEG; } + // Draw scarves above other clothing. + if (doll.parts[TILEP_PART_CLOAK] >= TILEP_CLOAK_SCARF_FIRST_NORM) + { + p_order[4] = p_order[5]; + p_order[5] = p_order[6]; + p_order[6] = p_order[7]; + p_order[7] = p_order[8]; + p_order[8] = p_order[9]; + p_order[9] = TILEP_PART_CLOAK; + } + // Special case bardings from being cut off. const bool is_naga = is_player_tile(doll.parts[TILEP_PART_BASE], TILEP_BASE_NAGA); diff --git a/crawl-ref/source/tilepick-p.cc b/crawl-ref/source/tilepick-p.cc index 55d4eb6c13bd..efaa58b734a3 100644 --- a/crawl-ref/source/tilepick-p.cc +++ b/crawl-ref/source/tilepick-p.cc @@ -346,7 +346,7 @@ tileidx_t tilep_equ_armour(const item_def &item) tileidx_t tilep_equ_cloak(const item_def &item) { - if (item.base_type != OBJ_ARMOUR || item.sub_type != ARM_CLOAK) + if (item.base_type != OBJ_ARMOUR) return 0; if (item.props.exists("worn_tile")) @@ -359,7 +359,18 @@ tileidx_t tilep_equ_cloak(const item_def &item) return tile; } - return _modrng(item.rnd, TILEP_CLOAK_FIRST_NORM, TILEP_CLOAK_LAST_NORM); + switch (item.sub_type) + { + case ARM_CLOAK: + return _modrng(item.rnd, TILEP_CLOAK_FIRST_NORM, + TILEP_CLOAK_LAST_NORM); + + case ARM_SCARF: + return _modrng(item.rnd, TILEP_CLOAK_SCARF_FIRST_NORM, + TILEP_CLOAK_SCARF_LAST_NORM); + } + + return 0; } tileidx_t tilep_equ_helm(const item_def &item) diff --git a/crawl-ref/source/tileweb.cc b/crawl-ref/source/tileweb.cc index 432db41794f1..b6f282b49aab 100644 --- a/crawl-ref/source/tileweb.cc +++ b/crawl-ref/source/tileweb.cc @@ -1132,6 +1132,17 @@ static void _send_doll(const dolls_data &doll, bool submerged, bool ghost) p_order[6] = TILEP_PART_LEG; } + // Draw scarves above other clothing. + if (doll.parts[TILEP_PART_CLOAK] >= TILEP_CLOAK_SCARF_FIRST_NORM) + { + p_order[4] = p_order[5]; + p_order[5] = p_order[6]; + p_order[6] = p_order[7]; + p_order[7] = p_order[8]; + p_order[8] = p_order[9]; + p_order[9] = TILEP_PART_CLOAK; + } + // Special case bardings from being cut off. const bool is_naga = is_player_tile(doll.parts[TILEP_PART_BASE], TILEP_BASE_NAGA); From 8e11da7cb54b4df51c6c3e1a0af84908f49510f0 Mon Sep 17 00:00:00 2001 From: dplusplus Date: Tue, 20 Aug 2019 08:18:37 +0900 Subject: [PATCH 585/864] fix mutations/vamp-attrs toggle --- crawl-ref/source/mutation.cc | 8 +++++--- crawl-ref/source/webserver/game_data/templates/game.html | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/crawl-ref/source/mutation.cc b/crawl-ref/source/mutation.cc index c91c610ab170..7d6556dcbcab 100644 --- a/crawl-ref/source/mutation.cc +++ b/crawl-ref/source/mutation.cc @@ -888,14 +888,16 @@ void display_mutations() lastch = ev.key.keysym.sym; if (you.species == SP_VAMPIRE && (lastch == '!' || lastch == CK_MOUSE_CMD || lastch == '^')) { - int c = 1 - switcher->current(); - switcher->current() = c; + int& c = switcher->current(); + + bottom->set_text(_vampire_Ascreen_footer(c)); + + c = 1 - c; #ifdef USE_TILE_WEB tiles.json_open_object(); tiles.json_write_int("pane", c); tiles.ui_state_change("mutations", 0); #endif - bottom->set_text(_vampire_Ascreen_footer(c)); } else done = !vbox->on_event(ev); return true; diff --git a/crawl-ref/source/webserver/game_data/templates/game.html b/crawl-ref/source/webserver/game_data/templates/game.html index 8a9d30cf58bd..f25a16c0b4e4 100644 --- a/crawl-ref/source/webserver/game_data/templates/game.html +++ b/crawl-ref/source/webserver/game_data/templates/game.html @@ -186,8 +186,8 @@

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 literal 66443 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 DEJ@sq From 71c5d99ebce4c92fd374b1fd589715d3931a3846 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 18 Jul 2019 22:31:20 -0400 Subject: [PATCH 510/864] Handle hidpi screens in webtiles glyph mode This was not factoring in the device pixel ratio correctly, and so ended up too small on hidpi screens. This commit also adds support for crawl-internal zooming (via rc options, or {} in X) of the dungeon. Browser zoom affecting glyph mode is a different story, I'm not sure how possible this is going to be. --- .../webserver/game_data/static/cell_renderer.js | 16 +++++++++++++--- .../game_data/static/dungeon_renderer.js | 13 +++++++++---- .../source/webserver/game_data/static/game.js | 3 ++- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/crawl-ref/source/webserver/game_data/static/cell_renderer.js b/crawl-ref/source/webserver/game_data/static/cell_renderer.js index 1e18cdd170d9..ce5ed79ae5d8 100644 --- a/crawl-ref/source/webserver/game_data/static/cell_renderer.js +++ b/crawl-ref/source/webserver/game_data/static/cell_renderer.js @@ -7,8 +7,11 @@ function ($, view_data, main, tileinfo_player, icons, dngn, enums, function DungeonCellRenderer() { + // see also, renderer_settings in game.js. In fact, do these values + // do anything? + var ratio = window.devicePixelRatio; this.set_cell_size(32, 32); - this.glyph_mode_font_size = 24; + this.glyph_mode_font_size = 24 * ratio; this.glyph_mode_font = "monospace"; } @@ -98,8 +101,15 @@ function ($, view_data, main, tileinfo_player, icons, dngn, enums, glyph_mode_font_name: function () { - return (this.glyph_mode_font_size + "px " + - this.glyph_mode_font); + var glyph_scale; + if (this.ui_state == enums.ui.VIEW_MAP) + glyph_scale = options.get("tile_map_scale"); + else + glyph_scale = options.get("tile_viewport_scale"); + console.log("scale is " + glyph_scale); + + return (Math.floor(this.glyph_mode_font_size * glyph_scale / 100) + + "px " + this.glyph_mode_font); }, render_cursors: function(cx, cy, x, y) diff --git a/crawl-ref/source/webserver/game_data/static/dungeon_renderer.js b/crawl-ref/source/webserver/game_data/static/dungeon_renderer.js index 3eec39e75097..5c94f5f68b60 100644 --- a/crawl-ref/source/webserver/game_data/static/dungeon_renderer.js +++ b/crawl-ref/source/webserver/game_data/static/dungeon_renderer.js @@ -251,17 +251,22 @@ function ($, cr, map_knowledge, options, dngn, util, view_data, enums) { if (options.get("tile_display_mode") == "glyphs") { + // font size ratio: handled in cell_renderer.js + var margin = 2 * ratio; this.ctx.font = this.glyph_mode_font_name(); var metrics = this.ctx.measureText("@"); - this.set_cell_size(metrics.width + 2, this.glyph_mode_font_size + 2); + this.set_cell_size(metrics.width + margin, + Math.floor(this.glyph_mode_font_size * scale / 100) + + margin); } else if ((min_diameter * cell_size.w / ratio > width) || (min_diameter * cell_size.h / ratio > height)) { - var scale = Math.min(width * ratio / (min_diameter * cell_size.w), + // scale down if necessary, so that los is in view + var rescale = Math.min(width * ratio / (min_diameter * cell_size.w), height * ratio / (min_diameter * cell_size.h)); - this.set_cell_size(Math.floor(cell_size.w * scale), - Math.floor(cell_size.h * scale)); + this.set_cell_size(Math.floor(cell_size.w * rescale), + Math.floor(cell_size.h * rescale)); } else this.set_cell_size(cell_size.w, cell_size.h); diff --git a/crawl-ref/source/webserver/game_data/static/game.js b/crawl-ref/source/webserver/game_data/static/game.js index 18c75760682e..37c4fdb72e62 100644 --- a/crawl-ref/source/webserver/game_data/static/game.js +++ b/crawl-ref/source/webserver/game_data/static/game.js @@ -225,8 +225,9 @@ function ($, comm, client, dungeon_renderer, display, minimap, enums, messages, document.title = data.text; } + var device_ratio = window.devicePixelRatio; var renderer_settings = { - glyph_mode_font_size: 24, + glyph_mode_font_size: 24 * device_ratio, glyph_mode_font: "monospace" }; From 2b48af375b3012802c2bf90855d64ad3afbc374a Mon Sep 17 00:00:00 2001 From: advil Date: Fri, 19 Jul 2019 09:02:23 -0400 Subject: [PATCH 511/864] Fix a potential cursor rendering issue in glyph mode What was happening here was if w or h were non-integer, then the scale value ended up slightly different than the cell sizes. In glyph mode, this was happening to the width parameter depending on font details (applying at least to firefox/mac on default settings). When rendering the mouse cursor, this scale value is used, so it would be a bit larger horizontally than a single cell, by 1-2 pixels. On firefox this meant that the cursor didn't get cleanly cleared when it moved, leaving vertical lines when moving the mouse cursor across the dungeon view. In testing, I have seen no consequences of using a scale based on the floored versions of w and h, even though in principle this might mean that the width of glyphs is slightly larger than the cell size is expecting. --- crawl-ref/source/webserver/game_data/static/cell_renderer.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/webserver/game_data/static/cell_renderer.js b/crawl-ref/source/webserver/game_data/static/cell_renderer.js index ce5ed79ae5d8..dbe2f04f7115 100644 --- a/crawl-ref/source/webserver/game_data/static/cell_renderer.js +++ b/crawl-ref/source/webserver/game_data/static/cell_renderer.js @@ -95,8 +95,8 @@ function ($, view_data, main, tileinfo_player, icons, dngn, enums, { this.cell_width = Math.floor(w); this.cell_height = Math.floor(h); - this.x_scale = w / 32; - this.y_scale = h / 32; + this.x_scale = this.cell_width / 32; + this.y_scale = this.cell_height / 32; }, glyph_mode_font_name: function () @@ -106,7 +106,6 @@ function ($, view_data, main, tileinfo_player, icons, dngn, enums, glyph_scale = options.get("tile_map_scale"); else glyph_scale = options.get("tile_viewport_scale"); - console.log("scale is " + glyph_scale); return (Math.floor(this.glyph_mode_font_size * glyph_scale / 100) + "px " + this.glyph_mode_font); From 284f782df5609fc92ff285a17f15558e889db033 Mon Sep 17 00:00:00 2001 From: Seve Monahan Date: Fri, 19 Jul 2019 22:50:02 -0400 Subject: [PATCH 512/864] Show XL to reach relevant skill level on more items (Mantis #12018) Before, if you could not *currently* train a particular skill, you would not see the "At X% training you would reach Y in about Z XLs" line. For example, if you did not have any short blades in your inventory but were looking at a rapier in a shop, the line would be missing. This fixes the description code to only exclude the line if a skill is *permanently* untrainable. --- crawl-ref/source/describe.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index 4cd290d1122e..e05acfb559a8 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -981,7 +981,7 @@ static bool _could_set_training_target(const item_def &item, bool ignore_current const int target = min(_item_training_target(item), 270); - return target && you.can_train[skill] + return target && !is_useless_skill(skill) && you.skill(skill, 10, false, false, false) < target && (ignore_current || you.get_training_target(skill) < target); } From a379d5e2002d1753cc2fdd47a06dc70336d03bd7 Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 20 Jul 2019 14:05:38 -0400 Subject: [PATCH 513/864] Don't crash if redrawing a prompt triggers a flash This is probably a webtiles-specific bug: if a prompt triggered a flash (on just webtiles builds, I think), and there were monsters in view, then the redraw involved in the flash would lose the cursor position and leave the region in the mlist. This is a kind of minimalistic fix in that it only addresses flash calls specifically -- viewwindow on relevant builds (as well as update_monster_pane) can change the region as a side effect, leaving it in the monster list. However, I'm not yet certain whether it would have other consequences to adjust this more generally. But probably a more general fix is needed, and all the occasional cursor out of bounds issues we see with GOTO_MLIST do result from this side effect of viewwindow. --- crawl-ref/source/cio.cc | 1 + crawl-ref/source/view.cc | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/crawl-ref/source/cio.cc b/crawl-ref/source/cio.cc index cdf902e9d219..798973f0b55d 100644 --- a/crawl-ref/source/cio.cc +++ b/crawl-ref/source/cio.cc @@ -599,6 +599,7 @@ int line_reader::read_line(bool clear_previous, bool reset_cursor) draw_colour draw(fg_colour, bg_colour); region = get_cursor_region(); + ASSERT(region != GOTO_MLIST); if (start.x < 0) start = cgetpos(region); // inherit location from cursor else diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index 3c1c47909354..f1e51738fa47 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -928,7 +928,10 @@ void flash_view(use_animation_type a, colour_t colour, targeter *where) { you.flash_colour = colour; you.flash_where = where; + const auto region = get_cursor_region(); + const coord_def pos = cgetpos(region); viewwindow(false); + cgotoxy(pos.x, pos.y, region); } } @@ -1456,6 +1459,7 @@ void viewwindow(bool show_updates, bool tiles_only, animation *a) { puttext(crawl_view.viewp.x, crawl_view.viewp.y, crawl_view.vbuf); update_monster_pane(); + // these can change region... } #endif #ifdef USE_TILE From be7f5e2e8dd2d2250346b0928555b9967f520fba Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 20 Jul 2019 15:17:44 -0400 Subject: [PATCH 514/864] Revert "Don't crash if redrawing a prompt triggers a flash" This reverts commit a379d5e2002d1753cc2fdd47a06dc70336d03bd7. --- crawl-ref/source/cio.cc | 1 - crawl-ref/source/view.cc | 4 ---- 2 files changed, 5 deletions(-) diff --git a/crawl-ref/source/cio.cc b/crawl-ref/source/cio.cc index 798973f0b55d..cdf902e9d219 100644 --- a/crawl-ref/source/cio.cc +++ b/crawl-ref/source/cio.cc @@ -599,7 +599,6 @@ int line_reader::read_line(bool clear_previous, bool reset_cursor) draw_colour draw(fg_colour, bg_colour); region = get_cursor_region(); - ASSERT(region != GOTO_MLIST); if (start.x < 0) start = cgetpos(region); // inherit location from cursor else diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index f1e51738fa47..3c1c47909354 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -928,10 +928,7 @@ void flash_view(use_animation_type a, colour_t colour, targeter *where) { you.flash_colour = colour; you.flash_where = where; - const auto region = get_cursor_region(); - const coord_def pos = cgetpos(region); viewwindow(false); - cgotoxy(pos.x, pos.y, region); } } @@ -1459,7 +1456,6 @@ void viewwindow(bool show_updates, bool tiles_only, animation *a) { puttext(crawl_view.viewp.x, crawl_view.viewp.y, crawl_view.vbuf); update_monster_pane(); - // these can change region... } #endif #ifdef USE_TILE From 9de272bb65679e0acb2c0d648a7bf934a2dbe1e2 Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 20 Jul 2019 19:01:55 -0400 Subject: [PATCH 515/864] Another try at "Don't crash if redrawing a prompt triggers a flash" Not exactly a revert of be7f5e2e8dd2d2250346b0928555b9967f520fba. This tries under fewer circumstances to restore cursor position after a flash, doing it only while printing to the message window; it is apparently possible for a flash to be called in situations where the cursor position is incoherent with the region. However, things should be coherent within _mpr. This also disables flashing entirely in the arena, as the arena reliably instantiates one of these cases, and I couldn't figure out why. --- crawl-ref/source/cio.cc | 21 +-------------------- crawl-ref/source/cio.h | 20 ++++++++++++++++++++ crawl-ref/source/libutil.cc | 3 ++- crawl-ref/source/message.cc | 6 +++++- crawl-ref/source/view.cc | 1 + 5 files changed, 29 insertions(+), 22 deletions(-) diff --git a/crawl-ref/source/cio.cc b/crawl-ref/source/cio.cc index cdf902e9d219..32a17f89f39c 100644 --- a/crawl-ref/source/cio.cc +++ b/crawl-ref/source/cio.cc @@ -58,26 +58,6 @@ static keycode_type _numpad2vi(keycode_type key) return key; } -// Save and restore the cursor region. -class unwind_cursor -{ -public: - unwind_cursor() - : region(get_cursor_region()), pos(cgetpos(get_cursor_region())) - { } - unwind_cursor(int x, int y, GotoRegion reg) : unwind_cursor() - { - cgotoxy(x, y, reg); - } - ~unwind_cursor() - { - cgotoxy(pos.x, pos.y, region); - } -private: - GotoRegion region; - coord_def pos; -}; - int unmangle_direction_keys(int keyin, KeymapContext keymap, bool allow_fake_modifiers) { @@ -599,6 +579,7 @@ int line_reader::read_line(bool clear_previous, bool reset_cursor) draw_colour draw(fg_colour, bg_colour); region = get_cursor_region(); + ASSERT(region != GOTO_MLIST); if (start.x < 0) start = cgetpos(region); // inherit location from cursor else diff --git a/crawl-ref/source/cio.h b/crawl-ref/source/cio.h index 34eeae010291..51c23311d21c 100644 --- a/crawl-ref/source/cio.h +++ b/crawl-ref/source/cio.h @@ -364,3 +364,23 @@ class resumable_line_reader : public line_reader typedef int keycode_type; keyfun_action keyfun_num_and_char(int &ch); + +// Save and restore the cursor region. +class unwind_cursor +{ +public: + unwind_cursor() + : region(get_cursor_region()), pos(cgetpos(get_cursor_region())) + { } + unwind_cursor(int x, int y, GotoRegion reg) : unwind_cursor() + { + cgotoxy(x, y, reg); + } + ~unwind_cursor() + { + cgotoxy(pos.x, pos.y, region); + } +private: + GotoRegion region; + coord_def pos; +}; diff --git a/crawl-ref/source/libutil.cc b/crawl-ref/source/libutil.cc index e224154cb2de..d905fbea0f29 100644 --- a/crawl-ref/source/libutil.cc +++ b/crawl-ref/source/libutil.cc @@ -386,7 +386,8 @@ void cgotoxy(int x, int y, GotoRegion region) #ifdef ASSERTS if (x < 1 || y < 1 || x > sz.x || y > sz.y) { - save_game(false); // should be safe + if (!crawl_state.game_is_arena()) + save_game(false); // should be safe die("screen write out of bounds: (%d,%d) into (%d,%d)", x, y, sz.x, sz.y); } diff --git a/crawl-ref/source/message.cc b/crawl-ref/source/message.cc index 66a6f426fd93..36a8a3b5057c 100644 --- a/crawl-ref/source/message.cc +++ b/crawl-ref/source/message.cc @@ -1490,8 +1490,12 @@ static void _mpr(string text, msg_channel_type channel, int param, bool nojoin, if (domore) more(true); - if (do_flash_screen) + if (do_flash_screen && !crawl_state.game_is_arena()) + { + // unwind cursor doesn't work, for unclear reasons, in arena + unwind_cursor pos; flash_view_delay(UA_ALWAYS_ON, YELLOW, 50); + } } diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index 3c1c47909354..cbf2ef6ba5f7 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -1456,6 +1456,7 @@ void viewwindow(bool show_updates, bool tiles_only, animation *a) { puttext(crawl_view.viewp.x, crawl_view.viewp.y, crawl_view.vbuf); update_monster_pane(); + // these can change region... } #endif #ifdef USE_TILE From d52e2fb918bf6d98f4b05b9b3ee69d58149c2698 Mon Sep 17 00:00:00 2001 From: Seve Monahan Date: Sun, 21 Jul 2019 18:29:30 -0400 Subject: [PATCH 516/864] Revert "Another try at "Don't crash if redrawing a prompt triggers a flash"" This reverts commit 9de272bb65679e0acb2c0d648a7bf934a2dbe1e2. This commit appears to cause crashes similar to a379d5e2002d17 Example: https://crawl.xtahua.com/crawl/morgue/hittemvvvvvvvhard/crash-hittemvvvvvvvhard-20190721-214938.txt It's possible this is coincidence, if so this commit can be reverted. --- crawl-ref/source/cio.cc | 21 ++++++++++++++++++++- crawl-ref/source/cio.h | 20 -------------------- crawl-ref/source/libutil.cc | 3 +-- crawl-ref/source/message.cc | 6 +----- crawl-ref/source/view.cc | 1 - 5 files changed, 22 insertions(+), 29 deletions(-) diff --git a/crawl-ref/source/cio.cc b/crawl-ref/source/cio.cc index 32a17f89f39c..cdf902e9d219 100644 --- a/crawl-ref/source/cio.cc +++ b/crawl-ref/source/cio.cc @@ -58,6 +58,26 @@ static keycode_type _numpad2vi(keycode_type key) return key; } +// Save and restore the cursor region. +class unwind_cursor +{ +public: + unwind_cursor() + : region(get_cursor_region()), pos(cgetpos(get_cursor_region())) + { } + unwind_cursor(int x, int y, GotoRegion reg) : unwind_cursor() + { + cgotoxy(x, y, reg); + } + ~unwind_cursor() + { + cgotoxy(pos.x, pos.y, region); + } +private: + GotoRegion region; + coord_def pos; +}; + int unmangle_direction_keys(int keyin, KeymapContext keymap, bool allow_fake_modifiers) { @@ -579,7 +599,6 @@ int line_reader::read_line(bool clear_previous, bool reset_cursor) draw_colour draw(fg_colour, bg_colour); region = get_cursor_region(); - ASSERT(region != GOTO_MLIST); if (start.x < 0) start = cgetpos(region); // inherit location from cursor else diff --git a/crawl-ref/source/cio.h b/crawl-ref/source/cio.h index 51c23311d21c..34eeae010291 100644 --- a/crawl-ref/source/cio.h +++ b/crawl-ref/source/cio.h @@ -364,23 +364,3 @@ class resumable_line_reader : public line_reader typedef int keycode_type; keyfun_action keyfun_num_and_char(int &ch); - -// Save and restore the cursor region. -class unwind_cursor -{ -public: - unwind_cursor() - : region(get_cursor_region()), pos(cgetpos(get_cursor_region())) - { } - unwind_cursor(int x, int y, GotoRegion reg) : unwind_cursor() - { - cgotoxy(x, y, reg); - } - ~unwind_cursor() - { - cgotoxy(pos.x, pos.y, region); - } -private: - GotoRegion region; - coord_def pos; -}; diff --git a/crawl-ref/source/libutil.cc b/crawl-ref/source/libutil.cc index d905fbea0f29..e224154cb2de 100644 --- a/crawl-ref/source/libutil.cc +++ b/crawl-ref/source/libutil.cc @@ -386,8 +386,7 @@ void cgotoxy(int x, int y, GotoRegion region) #ifdef ASSERTS if (x < 1 || y < 1 || x > sz.x || y > sz.y) { - if (!crawl_state.game_is_arena()) - save_game(false); // should be safe + save_game(false); // should be safe die("screen write out of bounds: (%d,%d) into (%d,%d)", x, y, sz.x, sz.y); } diff --git a/crawl-ref/source/message.cc b/crawl-ref/source/message.cc index 36a8a3b5057c..66a6f426fd93 100644 --- a/crawl-ref/source/message.cc +++ b/crawl-ref/source/message.cc @@ -1490,12 +1490,8 @@ static void _mpr(string text, msg_channel_type channel, int param, bool nojoin, if (domore) more(true); - if (do_flash_screen && !crawl_state.game_is_arena()) - { - // unwind cursor doesn't work, for unclear reasons, in arena - unwind_cursor pos; + if (do_flash_screen) flash_view_delay(UA_ALWAYS_ON, YELLOW, 50); - } } diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index cbf2ef6ba5f7..3c1c47909354 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -1456,7 +1456,6 @@ void viewwindow(bool show_updates, bool tiles_only, animation *a) { puttext(crawl_view.viewp.x, crawl_view.viewp.y, crawl_view.vbuf); update_monster_pane(); - // these can change region... } #endif #ifdef USE_TILE From 9d8d8d5b783ab39a5062678589f4ff8657a66d4a Mon Sep 17 00:00:00 2001 From: Seve Monahan Date: Mon, 22 Jul 2019 17:20:50 -0400 Subject: [PATCH 517/864] Ensure the Faerie Dragon scales are always id-ed (Mantis 12031) Now if you managed to kill the Enchantress before seeing her, the Faerie Dragon scales will be identified. This also ensures that if the Faerie Dragon scales are placed in a vault, they will be identified. --- crawl-ref/source/art-data.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/art-data.txt b/crawl-ref/source/art-data.txt index d4aef559bbda..e8bded931609 100644 --- a/crawl-ref/source/art-data.txt +++ b/crawl-ref/source/art-data.txt @@ -313,7 +313,7 @@ PLUS: +3 COLOUR: ETC_JEWEL TILE: urand_faerie TILE_EQ: faerie_dragon_armour -BOOL: nogen, unided, no_upgrade +BOOL: nogen, no_upgrade NAME: demon blade "Bloodbane" OBJ: OBJ_WEAPONS/WPN_DEMON_BLADE From 7ac07d978e2f3128e1638731dd05f34681828bbb Mon Sep 17 00:00:00 2001 From: Seve Monahan Date: Mon, 22 Jul 2019 22:23:04 -0400 Subject: [PATCH 518/864] Rename you.can_train to you.can_currently_train Logic errors such as the one fixed by 284f782df56 are much less likely to occur with this more precise name. Lua functions are unchanged to conserve compatibility with old scripts. Crash dumps will be changed in the next commit. --- crawl-ref/source/dbg-asrt.cc | 2 +- crawl-ref/source/god-abil.cc | 2 +- crawl-ref/source/item-use.cc | 2 +- crawl-ref/source/l-you.cc | 2 +- crawl-ref/source/main.cc | 4 +-- crawl-ref/source/ng-setup.cc | 2 +- crawl-ref/source/player-reacts.cc | 2 +- crawl-ref/source/player.cc | 2 +- crawl-ref/source/player.h | 2 +- crawl-ref/source/religion.cc | 6 ++-- crawl-ref/source/skill-menu.cc | 12 +++---- crawl-ref/source/skills.cc | 59 ++++++++++++++++--------------- crawl-ref/source/skills.h | 6 ++-- crawl-ref/source/startup.cc | 2 +- crawl-ref/source/tags.cc | 8 ++--- crawl-ref/source/tilereg-skl.cc | 4 +-- crawl-ref/source/wiz-dump.cc | 2 +- 17 files changed, 61 insertions(+), 58 deletions(-) diff --git a/crawl-ref/source/dbg-asrt.cc b/crawl-ref/source/dbg-asrt.cc index 96607deebb6c..033a08f6aef5 100644 --- a/crawl-ref/source/dbg-asrt.cc +++ b/crawl-ref/source/dbg-asrt.cc @@ -212,7 +212,7 @@ static void _dump_player(FILE *file) fprintf(file, "%-16s| %c | %u | %3u | %2d | %6d | %d/%d\n", skill_name(sk), - you.can_train[sk] ? 'X' : ' ', + you.can_currently_train[sk] ? 'X' : ' ', you.train[sk], you.training[sk], you.skills[sk], diff --git a/crawl-ref/source/god-abil.cc b/crawl-ref/source/god-abil.cc index 8847d4f9dfa9..a4818149566a 100644 --- a/crawl-ref/source/god-abil.cc +++ b/crawl-ref/source/god-abil.cc @@ -5660,7 +5660,7 @@ static bool _execute_sacrifice(ability_type sac, const char* message) static void _ru_kill_skill(skill_type skill) { change_skill_points(skill, -you.skill_points[skill], true); - you.can_train.set(skill, false); + you.can_currently_train.set(skill, false); reset_training(); check_selected_skills(); } diff --git a/crawl-ref/source/item-use.cc b/crawl-ref/source/item-use.cc index e04283a74491..e4bfed9b7b2c 100644 --- a/crawl-ref/source/item-use.cc +++ b/crawl-ref/source/item-use.cc @@ -571,7 +571,7 @@ bool wield_weapon(bool auto_wield, int slot, bool show_weff_messages, if (unwield_item(show_weff_messages)) { // Enable skills so they can be re-disabled later - update_can_train(); + update_can_currently_train(); } else return false; diff --git a/crawl-ref/source/l-you.cc b/crawl-ref/source/l-you.cc index 335511e91605..e209aa778314 100644 --- a/crawl-ref/source/l-you.cc +++ b/crawl-ref/source/l-you.cc @@ -188,7 +188,7 @@ LUARET1(you_skill_progress, number, * @function can_train_skill */ LUARET1(you_can_train_skill, boolean, - lua_isstring(ls, 1) ? you.can_train[str_to_skill(lua_tostring(ls, 1))] + lua_isstring(ls, 1) ? you.can_currently_train[str_to_skill(lua_tostring(ls, 1))] : false) /*** Best skill. * @treturn string diff --git a/crawl-ref/source/main.cc b/crawl-ref/source/main.cc index 801f9600c567..c3e6848336a8 100644 --- a/crawl-ref/source/main.cc +++ b/crawl-ref/source/main.cc @@ -1071,7 +1071,7 @@ static void _input() } if (!you_are_delayed()) - update_can_train(); + update_can_currently_train(); #ifdef USE_TILE_WEB tiles.flush_messages(); @@ -1189,7 +1189,7 @@ static void _input() viewwindow(); } - update_can_train(); + update_can_currently_train(); _update_replay_state(); diff --git a/crawl-ref/source/ng-setup.cc b/crawl-ref/source/ng-setup.cc index 2e8cdfe8d08f..a8557325be7a 100644 --- a/crawl-ref/source/ng-setup.cc +++ b/crawl-ref/source/ng-setup.cc @@ -564,7 +564,7 @@ static void _setup_generic(const newgame_def& ng) reassess_starting_skills(); init_skill_order(); - init_can_train(); + init_can_currently_train(); init_train(); init_training(); diff --git a/crawl-ref/source/player-reacts.cc b/crawl-ref/source/player-reacts.cc index a9b5b990e0a8..1cd4aabd55eb 100644 --- a/crawl-ref/source/player-reacts.cc +++ b/crawl-ref/source/player-reacts.cc @@ -454,7 +454,7 @@ void player_reacts_to_monsters() { // In case Maurice managed to steal a needed item for example. if (!you_are_delayed()) - update_can_train(); + update_can_currently_train(); if (you.duration[DUR_FIRE_SHIELD] > 0) manage_fire_shield(you.time_taken); diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index f4f715ec3d58..759747d6a03a 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -5191,7 +5191,7 @@ void player::init_skills() train.init(TRAINING_DISABLED); train_alt.init(TRAINING_DISABLED); training.init(0); - can_train.reset(); + can_currently_train.reset(); skill_points.init(0); ct_skill_points.init(0); skill_order.init(MAX_SKILL_ORDER); diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h index e969a9a06002..4eed0737ade3 100644 --- a/crawl-ref/source/player.h +++ b/crawl-ref/source/player.h @@ -207,7 +207,7 @@ class player : public actor FixedVector train; ///< see enum def FixedVector train_alt; ///< config of other mode FixedVector training; ///< percentage of XP used - FixedBitVector can_train; ///< Is training this skill allowed? + FixedBitVector can_currently_train; ///< Is training this skill allowed? FixedVector skill_points; FixedVector training_targets; ///< Training targets, scaled by 10 (so [0,270]). 0 means no target. diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index 4fbbd126cd86..0d0e83733870 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -3007,8 +3007,8 @@ void excommunication(bool voluntary, god_type new_god) for (ability_type abil : get_god_abilities()) you.stop_train.insert(abil_skill(abil)); - update_can_train(); - you.can_train.set(SK_INVOCATIONS, false); + update_can_currently_train(); + you.can_currently_train.set(SK_INVOCATIONS, false); reset_training(); // Perhaps we abandoned Trog with everything but Spellcasting maxed out. @@ -3692,7 +3692,7 @@ void join_religion(god_type which_god) vector abilities = get_god_abilities(); for (ability_type abil : abilities) you.start_train.insert(abil_skill(abil)); - update_can_train(); + update_can_currently_train(); // now that you have a god, you can't save any piety from your prev god you.previous_good_god = GOD_NO_GOD; diff --git a/crawl-ref/source/skill-menu.cc b/crawl-ref/source/skill-menu.cc index 000f1ef1ed33..e4de27cded3f 100644 --- a/crawl-ref/source/skill-menu.cc +++ b/crawl-ref/source/skill-menu.cc @@ -111,7 +111,7 @@ static bool _show_skill(skill_type sk, skill_menu_state state) switch (state) { case SKM_SHOW_DEFAULT: - return you.can_train[sk] || you.skill(sk, 10, false, false) + return you.can_currently_train[sk] || you.skill(sk, 10, false, false) || sk == you.transfer_from_skill || sk == you.transfer_to_skill; case SKM_SHOW_ALL: return true; default: return false; @@ -149,7 +149,7 @@ bool SkillMenuEntry::is_selectable(bool keep_hotkey) return false; } - if (!you.can_train[m_sk] && !is_set(SKMF_RESKILL_TO) + if (!you.can_currently_train[m_sk] && !is_set(SKMF_RESKILL_TO) && !is_set(SKMF_RESKILL_FROM)) { return false; @@ -336,7 +336,7 @@ string SkillMenuEntry::get_prefix() else letter = ' '; - const int sign = (!you.can_train[m_sk] || mastered()) ? ' ' : + const int sign = (!you.can_currently_train[m_sk] || mastered()) ? ' ' : (you.train[m_sk] == TRAINING_FOCUSED) ? '*' : you.train[m_sk] ? '+' : '-'; @@ -791,9 +791,9 @@ void SkillMenu::init_experience() for (int i = 0; i < NUM_SKILLS; ++i) { const skill_type sk = skill_type(i); - if (!is_useless_skill(sk) && !you.can_train[sk]) + if (!is_useless_skill(sk) && !you.can_currently_train[sk]) { - you.can_train.set(sk); + you.can_currently_train.set(sk); you.train[sk] = TRAINING_DISABLED; } } @@ -1603,7 +1603,7 @@ void SkillMenu::set_skills() void SkillMenu::toggle_practise(skill_type sk, int keyn) { - ASSERT(you.can_train[sk]); + ASSERT(you.can_currently_train[sk]); if (keyn >= 'A' && keyn <= 'Z') you.train.init(TRAINING_DISABLED); if (get_state(SKM_DO) == SKM_DO_PRACTISE) diff --git a/crawl-ref/source/skills.cc b/crawl-ref/source/skills.cc index 9f3d290f728d..b1047f7fc421 100644 --- a/crawl-ref/source/skills.cc +++ b/crawl-ref/source/skills.cc @@ -488,9 +488,9 @@ static void _check_start_train() if (is_invalid_skill(sk) || is_useless_skill(sk)) continue; - if (!you.can_train[sk] && you.train[sk]) + if (!you.can_currently_train[sk] && you.train[sk]) skills.insert(sk); - you.can_train.set(sk); + you.can_currently_train.set(sk); } reset_training(); @@ -536,7 +536,7 @@ static void _check_stop_train() if (skill_trained(sk) && you.training[sk]) skills.insert(sk); - you.can_train.set(sk, false); + you.can_currently_train.set(sk, false); } if (!skills.empty()) @@ -549,7 +549,7 @@ static void _check_stop_train() you.stop_train.clear(); } -void update_can_train() +void update_can_currently_train() { if (!you.start_train.empty()) _check_start_train(); @@ -580,15 +580,15 @@ bool training_restricted(skill_type sk) } /* - * Init the can_train array by examining inventory and spell list to see which - * skills can be trained. + * Init the can_currently_train array by examining inventory and spell list to + * see which skills can be trained. */ -void init_can_train() +void init_can_currently_train() { // Clear everything out, in case this isn't the first game. you.start_train.clear(); you.stop_train.clear(); - you.can_train.reset(); + you.can_currently_train.reset(); for (int i = 0; i < NUM_SKILLS; ++i) { @@ -597,7 +597,7 @@ void init_can_train() if (is_useless_skill(sk)) continue; - you.can_train.set(sk); + you.can_currently_train.set(sk); if (training_restricted(sk)) you.stop_train.insert(sk); } @@ -609,7 +609,7 @@ void init_train() { for (int i = 0; i < NUM_SKILLS; ++i) { - if (you.can_train[i] && you.skill_points[i]) + if (you.can_currently_train[i] && you.skill_points[i]) you.train[i] = you.train_alt[i] = TRAINING_ENABLED; else { @@ -824,8 +824,11 @@ void reset_training() // Focused skills get at least 20% training. for (int sk = 0; sk < NUM_SKILLS; ++sk) - if (you.train[sk] == 2 && you.training[sk] < 20 && you.can_train[sk]) + if (you.train[sk] == 2 && you.training[sk] < 20 + && you.can_currently_train[sk]) + { you.training[sk] += 5 * (5 - you.training[sk] / 4); + } } _scale_array(you.training, 100, you.auto_training); @@ -1082,7 +1085,7 @@ static void _train_skills(int exp, const int cost, const bool simu) bool skill_trained(int i) { - return you.can_train[i] && you.train[i]; + return you.can_currently_train[i] && you.train[i]; } /** @@ -2042,7 +2045,7 @@ void dump_skills(string &text) { text += make_stringf(" %c Level %.*f%s %s\n", real == 270 ? 'O' : - !you.can_train[i] ? ' ' : + !you.can_currently_train[i] ? ' ' : you.train[i] == 2 ? '*' : you.train[i] ? '+' : '-', @@ -2192,18 +2195,18 @@ skill_state::skill_state() : void skill_state::save() { - can_train = you.can_train; - skills = you.skills; - train = you.train; - training = you.training; - skill_points = you.skill_points; - training_targets = you.training_targets; - ct_skill_points = you.ct_skill_points; - skill_cost_level = you.skill_cost_level; - skill_order = you.skill_order; - auto_training = you.auto_training; - exp_available = you.exp_available; - total_experience = you.total_experience; + can_currently_train = you.can_currently_train; + skills = you.skills; + train = you.train; + training = you.training; + skill_points = you.skill_points; + training_targets = you.training_targets; + ct_skill_points = you.ct_skill_points; + skill_cost_level = you.skill_cost_level; + skill_order = you.skill_order; + auto_training = you.auto_training; + exp_available = you.exp_available; + total_experience = you.total_experience; get_all_manual_charges(manual_charges); for (int i = 0; i < NUM_SKILLS; i++) { @@ -2244,7 +2247,7 @@ void skill_state::restore_training() } } - you.can_train = can_train; + you.can_currently_train = can_currently_train; you.auto_training = auto_training; reset_training(); } @@ -2271,7 +2274,7 @@ void fixup_skills() skill_exp_needed(MAX_SKILL_LEVEL, sk)); check_skill_level_change(sk); } - init_can_train(); + init_can_currently_train(); reset_training(); if (you.exp_available >= 10 * calc_skill_cost(you.skill_cost_level) && !_player_is_gnoll()) @@ -2293,5 +2296,5 @@ bool can_enable_skill(skill_type sk, bool override) return !_player_is_gnoll() && you.skills[sk] < MAX_SKILL_LEVEL && !is_useless_skill(sk) - && (override || (you.can_train[sk] && !is_harmful_skill(sk))); + && (override || (you.can_currently_train[sk] && !is_harmful_skill(sk))); } diff --git a/crawl-ref/source/skills.h b/crawl-ref/source/skills.h index 0bf7cfb67687..df2a6308ace6 100644 --- a/crawl-ref/source/skills.h +++ b/crawl-ref/source/skills.h @@ -12,7 +12,7 @@ struct skill_state { skill_state(); - FixedBitVector can_train; + FixedBitVector can_currently_train; FixedVector skills; FixedVector real_skills; // Those two are FixedVector changed_skills; // scaled by 10. @@ -62,9 +62,9 @@ bool training_restricted(skill_type sk); void reassess_starting_skills(); bool check_selected_skills(); void init_train(); -void init_can_train(); +void init_can_currently_train(); void init_training(); -void update_can_train(); +void update_can_currently_train(); void reset_training(); int calc_skill_level_change(skill_type sk, int starting_level, int sk_points); void check_skill_level_change(skill_type sk, bool do_level_up = true); diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index 73e795cbf75a..474b3b3278de 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -443,7 +443,7 @@ static void _post_init(bool newc) if (newc) run_map_epilogues(); - // Sanitize skills, init can_train[]. + // Sanitize skills, init can_currently_train[]. fixup_skills(); } diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index 9b51e1dc329f..7ef4ee95e5b4 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -1267,10 +1267,10 @@ void tag_read(reader &inf, tag_type tag_id) #endif tag_read_companions(th); - // If somebody SIGHUP'ed out of the skill menu with all skills disabled. - // Doing this here rather in tag_read_you() because you.can_train() - // requires the player's equipment be loaded. - init_can_train(); + // If somebody SIGHUP'ed out of the skill menu with every skill + // disabled. Doing this here rather in tag_read_you() because + // you.can_currently_train() requires the player's equipment be loaded. + init_can_currently_train(); check_selected_skills(); break; case TAG_LEVEL: diff --git a/crawl-ref/source/tilereg-skl.cc b/crawl-ref/source/tilereg-skl.cc index 62e31e9f3361..68fdb818b98f 100644 --- a/crawl-ref/source/tilereg-skl.cc +++ b/crawl-ref/source/tilereg-skl.cc @@ -72,7 +72,7 @@ int SkillRegion::handle_mouse(MouseEvent &event) } #endif m_last_clicked_item = item_idx; - if (!you.can_train[skill]) + if (!you.can_currently_train[skill]) mpr("You cannot train this skill."); else if (you.species == SP_GNOLL) mpr("Gnolls can't change their training allocations!"); @@ -248,7 +248,7 @@ void SkillRegion::update() desc.idx = idx; desc.quantity = you.skills[skill]; - if (!you.can_train[skill] || you.skills[skill] >= 27) + if (!you.can_currently_train[skill] || you.skills[skill] >= 27) desc.flag |= TILEI_FLAG_INVALID; m_items.push_back(desc); diff --git a/crawl-ref/source/wiz-dump.cc b/crawl-ref/source/wiz-dump.cc index a28cd2127e5c..a9fd821ba6e1 100644 --- a/crawl-ref/source/wiz-dump.cc +++ b/crawl-ref/source/wiz-dump.cc @@ -607,7 +607,7 @@ bool chardump_parser::_parse_from_file(const string &full_filename) if (seen_skills) { init_skill_order(); - init_can_train(); + init_can_currently_train(); init_train(); init_training(); } From 8fd06ad0bc42af20fedee00f3bb04b6c8a391aea Mon Sep 17 00:00:00 2001 From: Seve Monahan Date: Mon, 22 Jul 2019 22:23:52 -0400 Subject: [PATCH 519/864] Rename a column of crash dumps from "can_train" to "can_currently_train" Split this off from 7ac07d978e2f31 so that this commit can be easily reverted. Reverting this commit would be useful if some outside system is fragile to the crash format changing. It might be better to split the skills table header into two lines for readability's sake. This would allow each column header to wrap once. --- crawl-ref/source/dbg-asrt.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/dbg-asrt.cc b/crawl-ref/source/dbg-asrt.cc index 033a08f6aef5..e535e70ab3dd 100644 --- a/crawl-ref/source/dbg-asrt.cc +++ b/crawl-ref/source/dbg-asrt.cc @@ -197,7 +197,8 @@ static void _dump_player(FILE *file) } fprintf(file, "Skills (mode: %s)\n", you.auto_training ? "auto" : "manual"); - fprintf(file, "Name | can_train | train | training | level | points | progress\n"); + fprintf(file, "Name | can_currently_train | train | training |" + " level | points | progress\n"); for (size_t i = 0; i < NUM_SKILLS; ++i) { const skill_type sk = skill_type(i); @@ -210,7 +211,7 @@ static void _dump_player(FILE *file) if (sk >= 0 && you.skills[sk] < 27) needed_max = skill_exp_needed(you.skills[sk] + 1, sk); - fprintf(file, "%-16s| %c | %u | %3u | %2d | %6d | %d/%d\n", + fprintf(file, "%-16s| %c | %u | %3u | %2d | %6d | %d/%d\n", skill_name(sk), you.can_currently_train[sk] ? 'X' : ' ', you.train[sk], From 122614bf49bb707e59254087421790cf4929cc4d Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 27 Jul 2019 17:21:15 +0800 Subject: [PATCH 520/864] Fix typo (runrin) --- crawl-ref/source/dat/descript/monsters.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/dat/descript/monsters.txt b/crawl-ref/source/dat/descript/monsters.txt index 3e4e76e24332..d7fb69b6c3a1 100644 --- a/crawl-ref/source/dat/descript/monsters.txt +++ b/crawl-ref/source/dat/descript/monsters.txt @@ -1606,7 +1606,7 @@ prey. %%%% meliai -A nymphal hybrid, with a winged torso of a human ontop of the stinging abdomen +A nymphal hybrid, with a winged torso of a human atop the stinging abdomen of a bee. The meliai serve under many roles: priestesses of nature, nurses to the divine, and warrior-champions for their hives. %%%% From bf7f94f634575a441b85159287c26451ce6afdd3 Mon Sep 17 00:00:00 2001 From: rmcneive <44419782+rmcneive@users.noreply.github.com> Date: Sat, 27 Jul 2019 11:05:17 -0400 Subject: [PATCH 521/864] Update quotes.txt --- crawl-ref/source/dat/descript/quotes.txt | 30 ++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/dat/descript/quotes.txt b/crawl-ref/source/dat/descript/quotes.txt index 319c3a67cc7a..d427e0a74a2d 100644 --- a/crawl-ref/source/dat/descript/quotes.txt +++ b/crawl-ref/source/dat/descript/quotes.txt @@ -121,11 +121,24 @@ A broken pillar A faded altar of an unknown god “Then Paul stood in the midst of Mars' hill, and said, Ye men of Athens, I -perceive that in all things ye are too superstitious. For as I passed by, and -beheld your devotions, I found an altar with this inscription, TO THE UNKNOWN -GOD.” + perceive that in all things ye are too superstitious. For as I passed by, and + beheld your devotions, I found an altar with this inscription, TO THE UNKNOWN + GOD.” -KJV Bible, Acts 17:23-24. %%%% +A flagged portal + +“We made an expedition; + We met a host and quelled it; + We forced a strong position, + And killed the men who held it. + ... +“Fierce warriors rushed to meet us; + We met them, and o’erthrew them: + They struggled hard to beat us; + But we conquered them, and slew them.” + -Thomas Love Peacock, “The War Song of Dinas Vawr”. 1829. +%%%% A gateway to Hell “I am the way into the city of woe. @@ -812,7 +825,16 @@ amulet of magic regeneration %%%% amulet of rage - +“We there, in strife bewild’ring, + Split blood enough to swim in: + We orphaned many children, + And widowed many women. + The eagles and the ravens + We glutted with our foemen; + The heroes and the cravens, + The spearmen and the bowmen.” + -Thomas Love Peacock, “The War Song of Dinas Vawr”. 1829. + %%%% amulet of regeneration From 04f7f4e3a98f22c136ed730b5a691e133798c3d6 Mon Sep 17 00:00:00 2001 From: Seve Monahan Date: Mon, 29 Jul 2019 20:16:11 -0400 Subject: [PATCH 522/864] Use "spell power" over "magical power" in !brill description (Yermak) "Magical power" is often used to refer to magic points, such as in the ring of magical power. There should probably be more consistent names for magical points and spell power, which should ideally both avoid using the word "power". --- crawl-ref/source/dat/descript/items.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/dat/descript/items.txt b/crawl-ref/source/dat/descript/items.txt index a0361ca41aaa..593b59c8bff0 100644 --- a/crawl-ref/source/dat/descript/items.txt +++ b/crawl-ref/source/dat/descript/items.txt @@ -671,7 +671,7 @@ A potion containing the essence of life. %%%% potion of brilliance -A potion which greatly increases the intelligence and magical power of one who +A potion which greatly increases the intelligence and spell power of one who drinks it. %%%% potion of cancellation From e2f623c2b95e0c4ac06e4943cb13d72d2b6c06b7 Mon Sep 17 00:00:00 2001 From: Seve Monahan Date: Mon, 29 Jul 2019 23:00:39 -0400 Subject: [PATCH 523/864] Have fsim test magical staffs with different Staves skill values (#12034) It would probably better to give the fsim user control over which skill(s) to vary, but if somebody needs that functionality it should be relatively simple to implement. --- crawl-ref/source/wiz-fsim.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/wiz-fsim.cc b/crawl-ref/source/wiz-fsim.cc index ea9098418012..44f5c6f41e54 100644 --- a/crawl-ref/source/wiz-fsim.cc +++ b/crawl-ref/source/wiz-fsim.cc @@ -86,7 +86,7 @@ static skill_type _equipped_skill() const int weapon = you.equip[EQ_WEAPON]; const item_def * iweap = weapon != -1 ? &you.inv[weapon] : nullptr; - if (iweap && iweap->base_type == OBJ_WEAPONS) + if (iweap && is_weapon(*iweap)) return item_attack_skill(*iweap); if (!iweap && you.m_quiver.get_fire_item() != -1) From f43b32f8989dcecb1f57fc879b65cdd77f1804a1 Mon Sep 17 00:00:00 2001 From: Seve Monahan Date: Mon, 29 Jul 2019 23:22:00 -0400 Subject: [PATCH 524/864] Ensure Zigsprint never fails to place guaranteed items (#12033) --- crawl-ref/source/dat/des/sprint/zigsprint.des | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/dat/des/sprint/zigsprint.des b/crawl-ref/source/dat/des/sprint/zigsprint.des index c949a5dea558..c374ab8363a6 100644 --- a/crawl-ref/source/dat/des/sprint/zigsprint.des +++ b/crawl-ref/source/dat/des/sprint/zigsprint.des @@ -810,10 +810,18 @@ KITEM: S = lightning rod ident:all KFEAT: ^ = granite_statue KFEAT: & = granite_statue COLOUR: & = magenta + +# Don't place the guaranteed artefacts (represented by glyphs R and T) any +# lower in this subvault. They are placed on the top line to ensure they are +# generated before any superb_items in the sprint. If the superb_items were +# generated before the guaranteed artefacts, they would be able to generate the +# guaranteed artefacts elsewhere in the sprint, which would prevent them from +# spawning in the initial room. + MAP ^g^h^j&A&k^l^m^ -f.............n -^.........RT..^ +f.........RT..n +^.............^ e..HG.........o ^..IF.........^ d..JE.....S...q From 9231cdcba1c1726ba81ad8a2991a2da3f74c68ae Mon Sep 17 00:00:00 2001 From: Seve Monahan Date: Wed, 31 Jul 2019 00:09:01 -0400 Subject: [PATCH 525/864] Don't mention Invocations skill in Drain Life spell description (#11947) --- crawl-ref/source/dat/descript/ability.txt | 2 ++ crawl-ref/source/dat/descript/spells.txt | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/dat/descript/ability.txt b/crawl-ref/source/dat/descript/ability.txt index f99694c7eab3..947336f135b2 100644 --- a/crawl-ref/source/dat/descript/ability.txt +++ b/crawl-ref/source/dat/descript/ability.txt @@ -261,6 +261,8 @@ skeletons cannot leave the level they were created on. %%%% Drain Life ability +# Note: part of this description duplicates the Drain Life spell description. + Drains the life force of any nearby creatures, healing the user depending on the damage dealt. The amount of life force drained is increased by Invocations skill. diff --git a/crawl-ref/source/dat/descript/spells.txt b/crawl-ref/source/dat/descript/spells.txt index 5a1c8260a7eb..1d055e1017c4 100644 --- a/crawl-ref/source/dat/descript/spells.txt +++ b/crawl-ref/source/dat/descript/spells.txt @@ -489,7 +489,10 @@ reserves. After the call ends, it cannot be issued again for a short time. %%%% Drain Life spell - +# Note: this description duplicates part of the Drain Life ability description. + +Drains the life force of any nearby creatures, healing the user depending on +the damage dealt. %%%% Drain Magic spell From cb87913eb9f71a80820e4f4dae0b5ad28a725876 Mon Sep 17 00:00:00 2001 From: Nikolai Lavsky <3328424+nlavsky@users.noreply.github.com> Date: Thu, 1 Aug 2019 14:17:47 +0300 Subject: [PATCH 526/864] Warn the player about leaving a ziggurat figurine behind (u/Quatzecoatl) Ziggurat figurines are usually buried below other loot and could be easy to miss. This commit adds a confirmation prompt when exiting Zig:27 without the figurine. This change was suggested here: https://www.reddit.com/r/dcss/comments/al6bxh/ --- crawl-ref/source/main.cc | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/crawl-ref/source/main.cc b/crawl-ref/source/main.cc index c3e6848336a8..f63a284a0302 100644 --- a/crawl-ref/source/main.cc +++ b/crawl-ref/source/main.cc @@ -1367,6 +1367,18 @@ static bool _prompt_stairs(dungeon_feature_type ygrd, bool down, bool shaft) } } + // Leaving ziggurat figurines behind. + if (ygrd == DNGN_EXIT_ZIGGURAT + && you.depth == brdepth[BRANCH_ZIGGURAT] + && find_floor_item(OBJ_MISCELLANY, MISC_ZIGGURAT)) + { + if (!yesno("Really leave the ziggurat figurine behind?", false, 'n')) + { + canned_msg(MSG_OK); + return false; + } + } + // Leaving Pan runes behind. if (!_prompt_unique_pan_rune(ygrd)) { From 98e85ec62a23fd20082119dadd6dc90002a7f157 Mon Sep 17 00:00:00 2001 From: Seve Monahan Date: Sun, 4 Aug 2019 11:18:03 -0400 Subject: [PATCH 527/864] Add Nikolai Lavsky to CREDITS.txt --- crawl-ref/CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/CREDITS.txt b/crawl-ref/CREDITS.txt index 18e3a98298ef..77839d5b0c1d 100644 --- a/crawl-ref/CREDITS.txt +++ b/crawl-ref/CREDITS.txt @@ -199,6 +199,7 @@ Lorenzo Lami Lantier Maciej Lapinski + Nikolai Lavsky Lamil Lerran Jordan Lewis Sami Liedes From 0b98641fa2dce082d24ca035b468be667d562b54 Mon Sep 17 00:00:00 2001 From: Seve Monahan Date: Tue, 6 Aug 2019 00:43:34 -0400 Subject: [PATCH 528/864] Remove extraneous Nikoli Lavsky credit --- crawl-ref/CREDITS.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/crawl-ref/CREDITS.txt b/crawl-ref/CREDITS.txt index 77839d5b0c1d..f3a75056f822 100644 --- a/crawl-ref/CREDITS.txt +++ b/crawl-ref/CREDITS.txt @@ -235,7 +235,6 @@ Naruni neofelis nicolae - Nikolai Lavsky Jonathon Nooner NormalPerson7 Michael Nowack From 18ba70b503b4f029c1369686a8194202c2b46cc5 Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 6 Aug 2019 07:37:22 -0400 Subject: [PATCH 529/864] Don't let dgn_move_entities_at move statues onto clouds This resulted in a crash in world_reacts; it could be reliably replicated by running lugonu corrupt near the vault statue_in_the_mist_lemuel. --- crawl-ref/source/terrain.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crawl-ref/source/terrain.cc b/crawl-ref/source/terrain.cc index 77528b4dc7bf..0b84466b9ca3 100644 --- a/crawl-ref/source/terrain.cc +++ b/crawl-ref/source/terrain.cc @@ -1077,7 +1077,10 @@ void dgn_move_entities_at(coord_def src, coord_def dst, move_item_stack_to_grid(src, dst); if (cell_is_solid(dst)) + { delete_cloud(src); + delete_cloud(dst); // in case there was already a clear there + } else move_cloud(src, dst); From 939521aa74e7c81af3e77e836991cb08964d6626 Mon Sep 17 00:00:00 2001 From: Seve Monahan Date: Thu, 8 Aug 2019 19:10:12 -0400 Subject: [PATCH 530/864] Add rmcneive to CREDITS.txt --- crawl-ref/CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/CREDITS.txt b/crawl-ref/CREDITS.txt index f3a75056f822..fa2ef6b1f23d 100644 --- a/crawl-ref/CREDITS.txt +++ b/crawl-ref/CREDITS.txt @@ -270,6 +270,7 @@ Remsleep Ryan Riegel RjY + rmcneive Andy Roche rockygargoyle Will Rogers From 42aaa33449af9d1291160b62171829cb1e7c005a Mon Sep 17 00:00:00 2001 From: gammafunk Date: Thu, 8 Aug 2019 18:23:41 -0500 Subject: [PATCH 531/864] Remove an unused description --- crawl-ref/source/dat/descript/features.txt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/crawl-ref/source/dat/descript/features.txt b/crawl-ref/source/dat/descript/features.txt index 0c7d22dcb558..a41c609dd7c9 100644 --- a/crawl-ref/source/dat/descript/features.txt +++ b/crawl-ref/source/dat/descript/features.txt @@ -86,11 +86,6 @@ An iron altar of Okawaru An altar of iron and steel dedicated to the Warmaster Okawaru. Its edges are surprisingly sharp. %%%% -An oddly glowing altar of Pakellas - -An altar to Pakellas the Inventive, adorned with strange half-completed devices -and tools, and glowing with an odd, persistent light. -%%%% A stormy altar of Qazlal An altar dedicated to Qazlal Stormbringer, surrounded by fierce winds, From bb0d440638a3221e108df45201618948c4d3251c Mon Sep 17 00:00:00 2001 From: gammafunk Date: Thu, 8 Aug 2019 20:02:54 -0500 Subject: [PATCH 532/864] Update Sif Muna's altar (CanOfWorms) This adds new animated altar tiles courtesy of CanOfWorms. The tile concept is a sort of shimmering orb of magic atop a deep blue pedestal inscribed in powerful LORE. The description is updated accordingly, and Sif's altar now has ETC_SHIMMERING_BLUE as its color instead of simply blue. --- crawl-ref/source/dat/descript/features.txt | 7 ++++--- crawl-ref/source/feature-data.h | 2 +- crawl-ref/source/rltiles/dc-feat.txt | 5 ++++- .../source/rltiles/dngn/altars/sif_muna.png | Bin 367 -> 0 bytes .../source/rltiles/dngn/altars/sif_muna1.png | Bin 0 -> 1136 bytes .../source/rltiles/dngn/altars/sif_muna2.png | Bin 0 -> 1133 bytes .../source/rltiles/dngn/altars/sif_muna3.png | Bin 0 -> 1140 bytes .../source/rltiles/dngn/altars/sif_muna4.png | Bin 0 -> 1125 bytes 8 files changed, 9 insertions(+), 5 deletions(-) delete mode 100644 crawl-ref/source/rltiles/dngn/altars/sif_muna.png create mode 100644 crawl-ref/source/rltiles/dngn/altars/sif_muna1.png create mode 100644 crawl-ref/source/rltiles/dngn/altars/sif_muna2.png create mode 100644 crawl-ref/source/rltiles/dngn/altars/sif_muna3.png create mode 100644 crawl-ref/source/rltiles/dngn/altars/sif_muna4.png diff --git a/crawl-ref/source/dat/descript/features.txt b/crawl-ref/source/dat/descript/features.txt index a41c609dd7c9..8f0b243fd0fb 100644 --- a/crawl-ref/source/dat/descript/features.txt +++ b/crawl-ref/source/dat/descript/features.txt @@ -96,10 +96,11 @@ A sacrificial altar of Ru An altar to Ru the Awakened in the shape of a pair of scales, with a heart in one scale and a pictogram representing power and enlightenment in the other. %%%% -A deep blue altar of Sif Muna +A shimmering blue altar of Sif Muna -An altar of the deepest blue, covered in intricate patterns and writings in -long forgotten scripts, devoted to Sif Muna the Loreminder. +An altar to Sif Muna the Loreminder, covered in intricate patterns and writings +in long forgotten scripts. Atop a deep blue pedestal hovers a shimmering +condensation of pure magic. %%%% A bloodstained altar of Trog diff --git a/crawl-ref/source/feature-data.h b/crawl-ref/source/feature-data.h index b80e7b015dc9..9e6b183acf45 100644 --- a/crawl-ref/source/feature-data.h +++ b/crawl-ref/source/feature-data.h @@ -520,7 +520,7 @@ ALTAR(DNGN_ALTAR_XOM, "shimmering altar of Xom", "altar_xom", ETC_RANDOM), ALTAR(DNGN_ALTAR_VEHUMET, "radiant altar of Vehumet", "altar_vehumet", ETC_VEHUMET), ALTAR(DNGN_ALTAR_OKAWARU, "iron altar of Okawaru", "altar_okawaru", CYAN), ALTAR(DNGN_ALTAR_MAKHLEB, "burning altar of Makhleb", "altar_makhleb", ETC_FIRE), -ALTAR(DNGN_ALTAR_SIF_MUNA, "deep blue altar of Sif Muna", "altar_sif_muna", BLUE), +ALTAR(DNGN_ALTAR_SIF_MUNA, "shimmering blue altar of Sif Muna", "altar_sif_muna", ETC_SHIMMER_BLUE), ALTAR(DNGN_ALTAR_TROG, "bloodstained altar of Trog", "altar_trog", RED), ALTAR(DNGN_ALTAR_NEMELEX_XOBEH, "sparkling altar of Nemelex Xobeh", "altar_nemelex_xobeh", LIGHTMAGENTA), ALTAR(DNGN_ALTAR_ELYVILON, "white marble altar of Elyvilon", "altar_elyvilon", WHITE), diff --git a/crawl-ref/source/rltiles/dc-feat.txt b/crawl-ref/source/rltiles/dc-feat.txt index ee3e47f85b70..e39b36300ea5 100644 --- a/crawl-ref/source/rltiles/dc-feat.txt +++ b/crawl-ref/source/rltiles/dc-feat.txt @@ -461,7 +461,10 @@ makhleb_flame5 makhleb_flame6 makhleb_flame7 makhleb_flame8 -sif_muna DNGN_ALTAR_SIF_MUNA +sif_muna1 DNGN_ALTAR_SIF_MUNA +sif_muna2 +sif_muna3 +sif_muna4 trog DNGN_ALTAR_TROG nemelex1 DNGN_ALTAR_NEMELEX_XOBEH nemelex2 diff --git a/crawl-ref/source/rltiles/dngn/altars/sif_muna.png b/crawl-ref/source/rltiles/dngn/altars/sif_muna.png deleted file mode 100644 index 82e462f73a56a6c85124edb5adfb16a276f769da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 367 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyx&b~Ru0R?L7#SE?7#R2%7*rV; z{1_OfGBEsSVAp2g@nsOHW{}&)p#9&-=)ZT(odlq2#*!evU%B&FJwXsrRVr|P~LjeiX&kZtn=I(0z%r;5kh_gdpgyH^0Tg9GlnAtzg zH^=vVma)9x?Q5^ZOsCAKS@iq|yULxPat+MMLD7$N9awJ6?_lwoX|m)yo0GI|*>}E! zDFT;tw)|FSyKC(H_3m`n&eic%_KF%^PSabic3fMzHZ%OX)|Pc;RXZ(t(l*-GX24qsIuzaNug^kR_)i9X-pTXU{ng`T{Y?A;wVtCdAjzd-DjE46VT;)U`m4oKmr8X^1ZrYn zU<8?g2H3S3czhWc{1`;485pKA$Zca__-|wcG72kzn6D(*Bqp|0)OLxe|4y-{L#l_) zV^s_kR2I;a5s46$Xy%n&$Ll(aH?NI%dJ)foI9%!nzxcyx+yosd&D6one2T&T14Gsa ziH%PhZ~eLd|KI1&p9yLlRX}zK#O3}i2Wn8 zi(^Q|oVgRilUfXTT-NShU8O&F;sI|3BYDZ3m}d(QN&KID^H{-(Y4ZyDEt!2<%o%!q z{uH^$RPdO=$nEj(7NzCw-=C&3HeL^WAzv+Fr@KIt;i0gHk~WX@cN0mO^wpmn6dca% zU_827w&7)ki$r?ps+o?Vv(@}Ecdd5`eE0r{wnK@^t)~kMq7tndZuE*@WJ*%o;_t7s z>W~X>v$twmzd-DjE46VT;)U`m4oKmr8X^1ZrYn zU<8?g2H3S3czhWc{1`;485pKA$Zca__-|wcG72kzn6D(*Bqp|0)OLxe|4y-{L#l_) zV^s_kR2I;a5s46$Xy%n&$Ll(aH?NI%dJ)foI9%!nzxcyx+yosd&D6one2T&T14Gsa ziH%PhZ~eLd|KI1&p9yLlRX}zK#O3}i2Wn`UoRKj-_qPdUKF>cW3vJy(c-gY@F*nitDBQy3b#UO7#OE0f}GaGA$ctHXC` z1M`M`XA?~fpQ>$5S?6h6^HAo#EAOu&zd-DjE46VT;)U`m4oKmr8X^1ZrYn zU<8?g2H3S3czhWc{1`;485pKA$Zca__-|wcG72kzn6D(*Bqp|0)OLxe|4y-{L#l_) zV^s_kR2I;a5s46$Xy%n&$Ll(aH?NI%dJ)foI9%!nzxcyx+yosd&D6one2T&T14Gsa ziH%PhZ~eLd|KI1&p9yLlRX}zK#O3}i2Wnuwlnb%|+Yp@_qZm(>B>XmV1)nKixb3FDYBNu35>fH2KjS z#4%|>deimHDX4ey(h*n^w!)Fyv47-w(2a?vvhgO$zrLp z-ueoUpBX%`eh{Jlb2UFhD6>UX-WRVD{|#R{+~4vFygYh$Zk3z&g935h>wOm1!o}P7 zd8|~*YFJs)`$1q)7Eh?&dmdBM<;$`cy522$D0%1l0zLVbHTFk(lz6gY#J?wnM-aQ|gYbtJ}r5VkB P1PW76S3j3^P6zd-DjE46VT;)U`m4oKmr8X^1ZrYn zU<8?g2H3S3czhWc{1`;485pKA$Zca__-|wcG72kzn6D(*Bqp|0)OLxe|4y-{L#l_) zV^s_kR2I;a5s46$Xy%n&$Ll(aH?NI%dJ)foI9%!nzxcyx+yosd&D6one2T&T14Gsa ziH%PhZ~eLd|KI1&p9yLlRX}zK#O3}i2Wn% zi(^Q|oZboDV$BLX&M)_WKf14qbD!DuDlyTCF|!^?)N3i_O}3t}@%K#Cjk!lEm;xIL zp3kXvJE!yadbWBO*NS}&Jo&%oOcs<>71UOUWVsxlu=B);uiw}d4i=|fWqy4rE#&TF ziD%LeuKf@YR+3}jGF{`AvsU`=x)Tyg$)YbAIOAPjuikwsxM3D!MvdSvl?xtEcfDZK zSXRz9Pbq4;&Xg->#n)KY8R!4_xQs! z)_D$dpFckRvDIClLHysu Date: Sat, 10 Aug 2019 16:36:33 +0300 Subject: [PATCH 533/864] Fix red draconian Tiamat tile (12043) In mon-data.h, the colour of red draconians is LIGHTRED, not RED, since 54374eb4. Because tilepick.cc:tileidx_monster_base() had no matching colour for red draconian Tiamat, it returned a tile with offset 0, the black draconian Tiamat tile, instead. --- crawl-ref/source/tilepick.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc index d1770344f608..38c19ebc9f0c 100644 --- a/crawl-ref/source/tilepick.cc +++ b/crawl-ref/source/tilepick.cc @@ -1462,7 +1462,7 @@ tileidx_t tileidx_monster_base(int type, bool in_water, int colour, int number, case LIGHTMAGENTA: offset = 4; break; case CYAN: offset = 5; break; case MAGENTA: offset = 6; break; - case RED: offset = 7; break; + case LIGHTRED: offset = 7; break; case WHITE: offset = 8; break; } From 2d01d4ab0a7cd92fbdf502c7aa80bf80fc4145f9 Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 11 Aug 2019 11:26:06 -0400 Subject: [PATCH 534/864] Fix some non-working code in `your_talents` I'm still not sure under what natural circumstances this code can get triggered, but it seems to be happening in this megazig character: http://crawl.akrasiac.org/rawdata/malcoda/crash-malcoda-20190811-143529.txt This bit of code for doing backup hotkey assignment for abilities has apparently never worked, but it also is hard to get to, so no one has noticed before. --- crawl-ref/source/ability.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/ability.cc b/crawl-ref/source/ability.cc index 13f5b732a5cf..f4e2d3bf3a50 100644 --- a/crawl-ref/source/ability.cc +++ b/crawl-ref/source/ability.cc @@ -3665,7 +3665,7 @@ vector your_talents(bool check_confused, bool include_unusable) } // Try to find a free hotkey for i, starting from Z. - for (int k = 51; k >= 0; ++k) + for (int k = 51; k >= 0; --k) { const int kkey = index_to_letter(k); bool good_key = true; @@ -3680,7 +3680,7 @@ vector your_talents(bool check_confused, bool include_unusable) if (good_key) { - tal.hotkey = k; + tal.hotkey = kkey; you.ability_letter_table[k] = tal.which; break; } From 3b46b88f1cbd74f30e817c40065ec5502d0a6f29 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Fri, 16 Aug 2019 17:25:39 +0800 Subject: [PATCH 535/864] Prevent widget parent clobbering (12046) If a widget's parent was recreated and reassigned to a shared pointer variable, it was possible for the old instance's destructor to clear the child's parent pointer after the new instance had initialized it: auto parent = make_shared(child); // child->m_parent == parent.get(); parent = make_shared(child); // child->m_parent == parent.nullptr When the second line runs, the first Parent instance is destructed after the second instance is constructed, clobbering the child's m_parent. --- crawl-ref/source/ui.cc | 14 ++++++++++++++ crawl-ref/source/ui.h | 8 +++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 00ac246153d0..5777dccb9f24 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -267,6 +267,20 @@ void Widget::_set_parent(Widget* p) m_parent = p; } +/** + * Unparent a widget. + * + * This function verifies that a widget has the correct parent before orphaning. + * Intended for use in container widget destructors. + * + * @param child The child widget to unparent. + */ +void Widget::_unparent(shared_ptr& child) +{ + if (child->m_parent == this) + child->_set_parent(nullptr); +} + void Widget::_invalidate_sizereq(bool immediate) { for (auto w = this; w; w = w->m_parent) diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index 4231670b3d07..eaed1e0f1156 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -158,6 +158,8 @@ class Widget protected: i4 m_region; + void _unparent(shared_ptr& child); + private: bool cached_sr_valid[2] = { false, false }; SizeReq cached_sr[2]; @@ -231,7 +233,7 @@ class Bin : public Container public: virtual ~Bin() { if (m_child) - m_child->_set_parent(nullptr); + _unparent(m_child); }; virtual bool on_event(const wm_event& event) override; void set_child(shared_ptr child); @@ -273,7 +275,7 @@ class ContainerVec : public Container virtual ~ContainerVec() { for (auto& child : m_children) if (child) - child->_set_parent(nullptr); + _unparent(child); } virtual shared_ptr get_child_at_offset(int x, int y) override; size_t num_children() const { return m_children.size(); } @@ -453,7 +455,7 @@ class Grid : public Container virtual ~Grid() { for (auto& child : m_child_info) if (child.widget) - child.widget->_set_parent(nullptr); + _unparent(child.widget); }; void add_child(shared_ptr child, int x, int y, int w = 1, int h = 1); const int column_flex_grow(int x) const { return m_col_info[x].flex_grow; } From 6aae15eeb0c4b66496a5db990c2e2b1c365118d8 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Fri, 16 Aug 2019 17:31:41 +0800 Subject: [PATCH 536/864] Fix mouse cursor on unselectable items --- crawl-ref/source/menu.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crawl-ref/source/menu.cc b/crawl-ref/source/menu.cc index 2f7f38f76d59..cabb18b06e4d 100644 --- a/crawl-ref/source/menu.cc +++ b/crawl-ref/source/menu.cc @@ -615,6 +615,9 @@ void UIMenu::update_hovered_entry() const auto& entry = item_info[i]; if (entry.heading) continue; + const auto me = m_menu->items[i]; + if (me->hotkeys.size() == 0) + continue; const int w = m_region[2] / m_num_columns; const int entry_x = entry.column * w; const int entry_h = row_heights[entry.row+1] - row_heights[entry.row]; From fe73009c60cffef9c2f4a444806d6c926d1840f1 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 17 Aug 2019 20:29:09 +0800 Subject: [PATCH 537/864] Check bounds for Grid widget row/col growths It's very easy to cause memory corruption if you unconditionally set the growth amount for a column / row, but conditionally add widgets to that column / row. --- crawl-ref/source/ui.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index eaed1e0f1156..ba7277bbfd19 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -458,17 +458,17 @@ class Grid : public Container _unparent(child.widget); }; void add_child(shared_ptr child, int x, int y, int w = 1, int h = 1); - const int column_flex_grow(int x) const { return m_col_info[x].flex_grow; } - const int row_flex_grow(int y) const { return m_row_info[y].flex_grow; } + const int column_flex_grow(int x) const { return m_col_info.at(x).flex_grow; } + const int row_flex_grow(int y) const { return m_row_info.at(y).flex_grow; } int& column_flex_grow(int x) { init_track_info(); - return m_col_info[x].flex_grow; + return m_col_info.at(x).flex_grow; } int& row_flex_grow(int y) { init_track_info(); - return m_row_info[y].flex_grow; + return m_row_info.at(y).flex_grow; } virtual shared_ptr get_child_at_offset(int x, int y) override; From 4167bdcbf352ecfa6da317a9175b48f5ce47de74 Mon Sep 17 00:00:00 2001 From: wjchen Date: Fri, 12 Jul 2019 17:36:25 +0800 Subject: [PATCH 538/864] Allow predefined keyword for search_stashes() Modify StashTracker::search_stashes() to accept an optional predefined keyword. It now directly return search results without asking what to search for when the keyword is specified. --- crawl-ref/source/stash.cc | 52 ++++++++++++++++++++------------------- crawl-ref/source/stash.h | 2 +- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/crawl-ref/source/stash.cc b/crawl-ref/source/stash.cc index b72c8a936d8f..3129406e8376 100644 --- a/crawl-ref/source/stash.cc +++ b/crawl-ref/source/stash.cc @@ -1433,43 +1433,45 @@ static vector _stash_filter_duplicates(vector Date: Tue, 16 Jul 2019 12:55:46 +0800 Subject: [PATCH 539/864] Add _god_from_initial() to travel.cc _god_from_initial(const char god_initial) returns a god_type enum when the initial of a god (i.e., god_initial, case-insensitive) is given. (except for TSO, which is replaced by '1'). If the given letter does not match any god's initial, GOD_NO_GOD will be returned instead. For example: _god_from_initial('a') or _god_from_initial('A') will return GOD_ASHENZARI. This function is later used for allowing players to select an altar for travel by the initial of a god. --- crawl-ref/source/travel.cc | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc index 135b171d3a4d..21cafe4f88a4 100644 --- a/crawl-ref/source/travel.cc +++ b/crawl-ref/source/travel.cc @@ -2214,6 +2214,42 @@ static int _prompt_travel_branch(int prompt_flags) } } +static god_type _god_from_initial(const char god_initial) +{ + switch (toupper_safe(god_initial)) + { + case '1': return GOD_SHINING_ONE; + case 'A': return GOD_ASHENZARI; + case 'B': return GOD_BEOGH; + case 'C': return GOD_CHEIBRIADOS; + case 'D': return GOD_DITHMENOS; + case 'E': return GOD_ELYVILON; + case 'F': return GOD_FEDHAS; + case 'G': return GOD_GOZAG; + case 'H': return GOD_HEPLIAKLQANA; + case 'J': return GOD_JIYVA; + case 'K': return GOD_KIKUBAAQUDGHA; + case 'L': return GOD_LUGONU; + case 'M': return GOD_MAKHLEB; + case 'N': return GOD_NEMELEX_XOBEH; + case 'O': return GOD_OKAWARU; +#if TAG_MAJOR_VERSION == 34 + case 'P': return GOD_PAKELLAS; +#endif + case 'Q': return GOD_QAZLAL; + case 'R': return GOD_RU; + case 'S': return GOD_SIF_MUNA; + case 'T': return GOD_TROG; + case 'U': return GOD_USKAYAW; + case 'V': return GOD_VEHUMET; + case 'W': return GOD_WU_JIAN; + case 'X': return GOD_XOM; + case 'Y': return GOD_YREDELEMNUL; + case 'Z': return GOD_ZIN; + default: return GOD_NO_GOD; + } +} + level_id find_up_level(level_id curr, bool up_branch) { --curr.depth; From f04b0cdf283207d44ca61d7a6d4c04271fd2459b Mon Sep 17 00:00:00 2001 From: wjchen Date: Fri, 12 Jul 2019 17:42:35 +0800 Subject: [PATCH 540/864] Allow using G_ to select altar for travel Pressing _ in G now lists discovered altars, user can then select the altar for travel by entering the initial of a god (except for TSO, which is replaced by 1). Once a god is selected, travelling to the nearest altar is started. Help file is also modified to reflect this change. --- crawl-ref/source/command.cc | 5 ++ crawl-ref/source/command.h | 1 + crawl-ref/source/dat/database/help.txt | 11 +++ crawl-ref/source/travel.cc | 94 ++++++++++++++++++++++++++ 4 files changed, 111 insertions(+) diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc index e4b63b56905f..206930a8742a 100644 --- a/crawl-ref/source/command.cc +++ b/crawl-ref/source/command.cc @@ -606,6 +606,11 @@ void show_interlevel_travel_depth_help() show_specific_help("interlevel-travel.depth.prompt"); } +void show_interlevel_travel_altar_help() +{ + show_specific_help("interlevel-travel.altar.prompt"); +} + void show_stash_search_help() { show_specific_help("stash-search.prompt"); diff --git a/crawl-ref/source/command.h b/crawl-ref/source/command.h index cbb4f3a22d1a..f5147b6a625b 100644 --- a/crawl-ref/source/command.h +++ b/crawl-ref/source/command.h @@ -21,6 +21,7 @@ void show_levelmap_help(); void show_targeting_help(); void show_interlevel_travel_branch_help(); void show_interlevel_travel_depth_help(); +void show_interlevel_travel_altar_help(); void show_stash_search_help(); void show_butchering_help(); void show_skill_menu_help(); diff --git a/crawl-ref/source/dat/database/help.txt b/crawl-ref/source/dat/database/help.txt index 247f2890ae65..3966fc4b51ee 100644 --- a/crawl-ref/source/dat/database/help.txt +++ b/crawl-ref/source/dat/database/help.txt @@ -209,6 +209,7 @@ interlevel-travel.branch.prompt Ctrl-P : Travel to a level in the branch above this one. * : Show available waypoints (if any are set). 0-9 : Go to the numbered waypoint. + _ : Show available altars (if any are discovered). %%%% interlevel-travel.depth.prompt @@ -222,6 +223,16 @@ interlevel-travel.depth.prompt $ : Change default to deepest visited level in this branch. ^ : Change default to the entrance to the current branch. %%%% +interlevel-travel.altar.prompt + +Interlevel Travel (go to an altar): + Use the shortcut letter (the initial of a god, with TSO being replaced by 1) + to select the altar for travel. + + Once you select a god, you will begin travelling to the nearst altar. + + Enter : Repeat last interlevel travel. +%%%% butchering Butchering diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc index 21cafe4f88a4..7ba0bd5ea555 100644 --- a/crawl-ref/source/travel.cc +++ b/crawl-ref/source/travel.cc @@ -73,6 +73,9 @@ enum IntertravelDestination // Repeat last travel ID_REPEAT = -101, + // Altar as target + ID_ALTAR = -102, + // Cancel interlevel travel ID_CANCEL = -1000, }; @@ -2152,6 +2155,8 @@ static int _prompt_travel_branch(int prompt_flags) show_interlevel_travel_branch_help(); redraw_screen(); break; + case '_': + return ID_ALTAR; case '\n': case '\r': return ID_REPEAT; case '<': @@ -2250,6 +2255,92 @@ static god_type _god_from_initial(const char god_initial) } } +static level_pos _prompt_travel_altar() +{ + extern map altars_present; + + if (altars_present.empty()) + return level_pos(); + + level_pos nearest_altars[NUM_GODS]; + const level_id curr = level_id::current(); + + // Populate nearest_altars[] with nearest altars + for (const auto &entry : altars_present) + { + // This is necessary because faded altars (i.e., GOD_ECUMENICAL) + // are also recorded in altars_present + if (entry.second >= NUM_GODS) + continue; + + int dist = level_distance(curr, entry.first.id); + if (dist == -1) + continue; + + level_pos *best = &nearest_altars[entry.second]; + int old_dist = best->id.is_valid() ? level_distance(curr, best->id) : INT_MAX; + + if (dist < old_dist) + *best = entry.first; + } + + while (true) + { + clear_messages(); + + int col = 0; + string line; + string altar_name; + char god_initial; + vector god_list = temple_god_list(); + vector nt_god_list = nontemple_god_list(); + god_list.insert(god_list.end(), nt_god_list.begin(), nt_god_list.end()); + + // list gods in the same order as dgn-overview.cc lists them. + for (const god_type god : god_list) + { + if (!nearest_altars[god].is_valid()) + continue; + + // "The Shining One" is too long to keep the same G menu layout + altar_name = god == GOD_SHINING_ONE ? "TSO" : god_name(god); + god_initial = god == GOD_SHINING_ONE ? '1' : altar_name.at(0); + + if (col == 4) + { + col = 0; + mpr(line); + line = ""; + } + line += make_stringf("(%c) %-14s ", god_initial, altar_name.c_str()); + ++col; + } + if (!line.empty()) + mpr(line); + + mprf(MSGCH_PROMPT, "Go to which altar? (? - help) "); + + int keyin = get_ch(); + switch (keyin) + { + CASE_ESCAPE + return level_pos(); + case '?': + show_interlevel_travel_altar_help(); + redraw_screen(); + break; + case '\n': case '\r': + return level_target; + default: + const level_pos altar_pos = nearest_altars[_god_from_initial(keyin)]; + if (altar_pos.is_valid()) + return altar_pos; + + return level_pos(); + } + } +} + level_id find_up_level(level_id curr, bool up_branch) { --curr.depth; @@ -2493,6 +2584,9 @@ level_pos prompt_translevel_target(int prompt_flags, string& dest_name) if (branch == ID_CANCEL) return target; + if (branch == ID_ALTAR) + return _prompt_travel_altar(); + // If user chose to repeat last travel, return that. if (branch == ID_REPEAT) return level_target; From 8077b2f2433f2ebed590b0e73e7b5877547f9ff4 Mon Sep 17 00:00:00 2001 From: wjchen Date: Fri, 12 Jul 2019 17:56:20 +0800 Subject: [PATCH 541/864] Allow traveling and annotating current level from ^O G, _, $, and ! in dungeon overview are made shortcuts to G, G_, Ctrl+F "shop", and level annotation respectively allowing selection of target for travel and annotating current level from dungeon overview. --- crawl-ref/source/dgn-overview.cc | 68 ++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 8 deletions(-) diff --git a/crawl-ref/source/dgn-overview.cc b/crawl-ref/source/dgn-overview.cc index 678afa4bedc0..87726da9c601 100644 --- a/crawl-ref/source/dgn-overview.cc +++ b/crawl-ref/source/dgn-overview.cc @@ -18,6 +18,7 @@ #include "feature.h" #include "files.h" #include "libutil.h" +#include "macro.h" #include "menu.h" #include "message.h" #include "mon-poly.h" @@ -55,12 +56,13 @@ static void _seen_altar(god_type god, const coord_def& pos); static void _seen_staircase(const coord_def& pos); static void _seen_shop(const coord_def& pos); static void _seen_portal(dungeon_feature_type feat, const coord_def& pos); +static void _process_command(const char keypress); static string _get_branches(bool display); static string _get_altars(bool display); static string _get_shops(bool display); static string _get_portals(); -static string _get_notes(); +static string _get_notes(bool display); static string _print_altars_for_gods(const vector& gods, bool print_unseen, bool display); static const string _get_coloured_level_annotation(level_id li); @@ -219,7 +221,7 @@ string overview_description_string(bool display) disp += _get_altars(display); disp += _get_shops(display); disp += _get_portals(); - disp += _get_notes(); + disp += _get_notes(display); return disp.substr(0, disp.find_last_not_of('\n')+1); } @@ -237,7 +239,7 @@ static string _get_seen_branches(bool display) disp += "\nBranches:"; if (display) { - disp += " (use G to reach them and " + disp += " (press G to reach them and " "?/B for more information)"; } disp += "\n"; @@ -365,7 +367,7 @@ static string _get_altars(bool display) disp += "\nAltars:"; if (display) { - disp += " (use Ctrl-F \"altar\" to reach them and " + disp += " (press _ to reach them and " "?/G for information about gods)"; } disp += "\n"; @@ -468,7 +470,7 @@ static string _get_shops(bool display) { disp +="\nShops:"; if (display) - disp += " (use Ctrl-F \"shop\" to reach them - yellow denotes antique shop)"; + disp += " (press $ to reach them - yellow denotes antique shop)"; disp += "\n"; } last_id.depth = 10000; @@ -531,7 +533,7 @@ static string _get_portals() } // Loop through each branch, printing stored notes. -static string _get_notes() +static string _get_notes(bool display) { string disp; @@ -545,6 +547,9 @@ static string _get_notes() if (disp.empty()) return disp; + + if (display) + return "\nAnnotations: (press ! to annotate current level)\n" + disp; return "\nAnnotations:\n" + disp; } @@ -607,12 +612,59 @@ bool unnotice_feature(const level_pos &pos) || _unnotice_stair(pos); } +class dgn_overview : public formatted_scroller +{ +public: + dgn_overview(const string& text = "") : formatted_scroller(FS_PREWRAPPED_TEXT, text) {}; + +private: + bool process_key(int ch) override + { + // We handle these after exiting dungeon overview window + // to prevent menus from stacking on top of each other. + if (ch == 'G' || ch == '_' || ch == '$' || ch =='!') + return false; + else + return formatted_scroller::process_key(ch); + } +}; + void display_overview() { string disp = overview_description_string(true); linebreak_string(disp, 80); - int flags = FS_PREWRAPPED_TEXT; // TODO: add ANYPRINTABLE - formatted_scroller(flags, disp).show(); + dgn_overview overview(disp); + _process_command(overview.show()); +} + +static void _process_command(const char keypress) +{ + switch (keypress) + { + case 'G': + do_interlevel_travel(); + return; + case '_': + if (!altars_present.empty()) + { + macro_sendkeys_end_add_expanded('_'); + do_interlevel_travel(); + } + else + mpr("Sorry, you haven't seen any altar yet."); + return; + case '$': + if (!shops_present.empty()) + StashTrack.search_stashes("shop"); + else + mpr("Sorry, you haven't seen any shop yet."); + return; + case '!': + annotate_level(); + return; + default: + return; + } } static void _seen_staircase(const coord_def& pos) From d1b266bae679451730d08ed82ec57b21e0462b4d Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 17 Aug 2019 21:50:59 +0800 Subject: [PATCH 542/864] Fix excess padding on webtiles book spell list --- crawl-ref/source/webserver/game_data/static/ui-layouts.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/webserver/game_data/static/ui-layouts.js b/crawl-ref/source/webserver/game_data/static/ui-layouts.js index 242201be0cca..00cf3d6ed7cf 100644 --- a/crawl-ref/source/webserver/game_data/static/ui-layouts.js +++ b/crawl-ref/source/webserver/game_data/static/ui-layouts.js @@ -32,7 +32,8 @@ function ($, comm, client, ui, enums, cr, util, scroller, main, gui, player) { return; } $.each(spellset, function (i, book) { - $container.append(book.label); + if (book.label.trim()) + $container.append(book.label); var $list = $("

A+WeKP%U3Q< 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�hLvQ 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 BuW|qY literal 29212 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 C-^OYH diff --git a/crawl-ref/source/dat/tiles/title_denzi_evil_mage.png b/crawl-ref/source/dat/tiles/title_denzi_evil_mage.png index b454152922f72afe24106888168edde905695185..cb531d8bd04fa9501d48eea0aedc14d0454cced9 100644 GIT binary patch literal 30666 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 B@a6yj literal 35346 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�(~g$uRdXjb4U{W2TQR(W7B^Eh^+*^lF@4P() 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 P00000NkvXXu0mjf>!Hyg diff --git a/crawl-ref/source/dat/tiles/title_denzi_invasion.png b/crawl-ref/source/dat/tiles/title_denzi_invasion.png index 372f8fb66c90f4c82cba59909b6855f6262e932d..833dd19b223d174f546457395f38f360910acb94 100644 GIT binary patch literal 31110 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 z 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 T*9F(800000NkvXXu0mjf{}qFP literal 36236 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

From 611b3b197382754777dd4e47cefc78358e6dff08 Mon Sep 17 00:00:00 2001 From: wjchen Date: Mon, 15 Jul 2019 00:52:25 +0800 Subject: [PATCH 586/864] Ensure stash update on being shafted (minqmay) Currently, if a player discovers an altar and get shafted by a trap at the same time, the altar will appear in dungeon overview but not in stash tracker. This change ensures items, shops, and altars discovered at the moment the player gets shafted are correctly registered. --- crawl-ref/source/player.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 1d9bff7551cb..7ed58e8ff0ff 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -7212,6 +7212,10 @@ bool player::do_shaft() return false; } + // Ensure altars, items, and shops discovered at the moment + // the player gets shafted are correctly registered. + maybe_update_stashes(); + duration[DUR_SHAFT_IMMUNITY] = 1; down_stairs(DNGN_TRAP_SHAFT); From a6a8d0c736cd6e55765078a1ec84fa6507a6751f Mon Sep 17 00:00:00 2001 From: Alex Jurkiewicz Date: Wed, 10 Jul 2019 18:37:39 +1000 Subject: [PATCH 587/864] Document timed_effects / timed_effect_type link --- crawl-ref/source/timed-effects.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crawl-ref/source/timed-effects.cc b/crawl-ref/source/timed-effects.cc index e4fb33040349..35d99b222c9e 100644 --- a/crawl-ref/source/timed-effects.cc +++ b/crawl-ref/source/timed-effects.cc @@ -431,6 +431,8 @@ struct timed_effect bool arena; }; +// If you add an entry to this list, remember to add a matching entry +// to timed_effect_type in timef-effect-type.h! static struct timed_effect timed_effects[] = { { rot_floor_items, 200, 200, true }, From 4bb3bc1208f1514d305fbe93f237e83a37e5080d Mon Sep 17 00:00:00 2001 From: kitchen-ace <68k@quikphix.org> Date: Thu, 5 Sep 2019 18:58:25 -0400 Subject: [PATCH 588/864] Give draconians their own horns tile --- crawl-ref/source/rltiles/dc-player.txt | 1 + .../rltiles/player/mutations/draconian1.png | Bin 0 -> 1407 bytes crawl-ref/source/tiledoll.cc | 2 ++ 3 files changed, 3 insertions(+) create mode 100644 crawl-ref/source/rltiles/player/mutations/draconian1.png diff --git a/crawl-ref/source/rltiles/dc-player.txt b/crawl-ref/source/rltiles/dc-player.txt index bf755171022f..541039ef28f6 100644 --- a/crawl-ref/source/rltiles/dc-player.txt +++ b/crawl-ref/source/rltiles/dc-player.txt @@ -1069,6 +1069,7 @@ cat7 cat8 cat9 cat10 +draconian1 HORNS_DRAC %sdir player/head ## Doll editor tiles, but not randomly picked diff --git a/crawl-ref/source/rltiles/player/mutations/draconian1.png b/crawl-ref/source/rltiles/player/mutations/draconian1.png new file mode 100644 index 0000000000000000000000000000000000000000..68aa70479839541dd9df5be82bb60a4d6f84714d GIT binary patch literal 1407 zcmV-_1%UdAP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+U=K7lH?`~hTl0wj({YD#BsntRc^4y&kuHcrh6vI zW-D*orrLmvCGmeicZc!g&l&!}MJ30O)I67*Bd%0Z;fjXG^EzvaY2Ww7*CX_w?BRaE zFbQfoyLnvWEA0C5f~Cvep6$Vo%a31d`1#vAw??c^RB!shBisYokhOt7jEgk5%6xk=ocTE$%h=L zqsO%Ji%yrF^u;cB7=Fr#_>Rn}tvZa^-7MkE!ey1~$lfs*zC) zA4S`CDJULmJV32usx8EZP9cWklM;2RG->SmpaUr;9&D(Y50-6nF)n;;C}|a%Yyo7t zI7l2ICouD!3+=dN#X~ShrKT-6Yu-w$2bRx~4n6W=hacsrox5}#0iow^-FxYE(7;j}Y3RtqhL1Ap z#9Es&)6|)#O`m1fo7zS7nc6G4f2KwkHQu1sIQyUmv)RK1t>Z)&GZ5oMAa08Q7Bnwr z(J3WfaS7>-t{$_qvS%igCK#Z-wv8UT1SWp!t)oJ^bvz&vhFu z)>&jUD2WVO<`!^#*9igJNb?*t=Q4TRFRjG9Lb%<*kn;h)mt%dZ!>i#}>$jt~qqn2C zqqn2Cqu;}k;8#b%|FFLRvstB;@R{jN0004mX+uL$Nkc;*aB^>EX>4Tx0C=2zkvmAk zKpe)urk1Ky9Lyl%kfAz=1@VQWR-p(LLaorMgL(7?O&XFE7e~Rh;NWAi>fqw6tAnc` z2tGhuT%8nMq{ROvg%&X$9QWh9`#$cz1Gsuw(X5U!K+|nAm52+O?5YrcMHfQgF@+IH zv5YxUOu~13-6O!(yBN#zKlkV8QFE381O(z)#V~E+4dUrd+hDv;%qvAnB|aw}HR*!H zk4%?6eq&s4nPZu}nNH0U^Ta}-jpa60il#<9NgP!*o$|Si$13A3##*_mH1Ek?7|H1? z%S@*^hy)g~1Q7ycR8c}1He$5uq*zGNe%!}D;QB>!$>b_QA;$tL&>*>fus`_St(Bh` z_mU!UAoSumA45QR7iiQR=lj@k8Ye*T8MxA0{z@H~`6Rv8(xOK|?>2C8-O}Ve;Bp7( ze=;Ofa-|?mE}sY9&*+=7K;JFUz2^1S+{ftykfyGZH^9LmFkGPQb)R>4w)gh$nPz`K zskL&wrX60200006VoOIv0RI600RN!9r;`8x010qNS#tmYE+YT{E+YYWr9XB6000Mc zNliru;|T>75Evzix>EoE08B|lK~z}7?a#3dz(5E?Q7em3vOc3Q0-KN~Qcl-I6qoA1 z&XsLxra$u7H7T#EwRF$N2PiYu{q~ueo)Q0W_l}75@ty$y0000Oy8#H|96E$0`lJ8= N002ovPDHLkV1flAouL2# literal 0 HcmV?d00001 diff --git a/crawl-ref/source/tiledoll.cc b/crawl-ref/source/tiledoll.cc index a1cc462717ff..a2b804c81ba9 100644 --- a/crawl-ref/source/tiledoll.cc +++ b/crawl-ref/source/tiledoll.cc @@ -416,6 +416,8 @@ void fill_doll_equipment(dolls_data &result) result.parts[TILEP_PART_HELM] = TILEP_HELM_HORNS_CAT; } } + else if (species_is_draconian(you.species)) + result.parts[TILEP_PART_HELM] = TILEP_HELM_HORNS_DRAC; else switch (you.get_mutation_level(MUT_HORNS)) { From 9a1d66b0e3e1dd8c90db91b06d022c39d6e8f08a Mon Sep 17 00:00:00 2001 From: kitchen-ace <68k@quikphix.org> Date: Thu, 5 Sep 2019 19:52:22 -0400 Subject: [PATCH 589/864] Don't show draconian head with full helms Only really relevant for wearing the mask of the dragon. --- crawl-ref/source/tilepick-p.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crawl-ref/source/tilepick-p.cc b/crawl-ref/source/tilepick-p.cc index efaa58b734a3..d48fc8fbdb74 100644 --- a/crawl-ref/source/tilepick-p.cc +++ b/crawl-ref/source/tilepick-p.cc @@ -978,6 +978,9 @@ void tilep_calc_flags(const dolls_data &doll, int flag[]) if (doll.parts[TILEP_PART_HELM] >= TILEP_HELM_FHELM_OFS) flag[TILEP_PART_BEARD] = TILEP_FLAG_HIDE; + if (doll.parts[TILEP_PART_HELM] >= TILEP_HELM_HELM_OFS) + flag[TILEP_PART_DRCHEAD] = TILEP_FLAG_HIDE; + if (is_player_tile(doll.parts[TILEP_PART_BASE], TILEP_BASE_NAGA)) { flag[TILEP_PART_BOOTS] = flag[TILEP_PART_LEG] = TILEP_FLAG_HIDE; From 2f91b30d3a3efb3c6b60e1ed5ceba2c5334ed6c2 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Tue, 27 Aug 2019 03:10:04 +0800 Subject: [PATCH 590/864] Fix player being off-centre on local tiles --- crawl-ref/source/tilesdl.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/tilesdl.cc b/crawl-ref/source/tilesdl.cc index d6f81cf43915..fdf5d5e8cd59 100644 --- a/crawl-ref/source/tilesdl.cc +++ b/crawl-ref/source/tilesdl.cc @@ -1030,8 +1030,8 @@ void TilesFramework::do_layout() // Expand dungeon region to cover partial tiles, then offset to keep player centred int tile_iw = m_stat_x_divider; int tile_ih = message_y_divider; - int tile_ow = round_up_to_multiple(tile_iw, m_region_tile->dx*2); - int tile_oh = round_up_to_multiple(tile_ih, m_region_tile->dy*2); + int tile_ow = round_up_to_multiple(tile_iw, m_region_tile->dx*2) + m_region_tile->dx; + int tile_oh = round_up_to_multiple(tile_ih, m_region_tile->dy*2) + m_region_tile->dx; m_region_tile->resize_to_fit(tile_ow, tile_oh); m_region_tile->place(-(tile_ow - tile_iw)/2, -(tile_oh - tile_ih)/2, 0); m_region_tile->tile_iw = tile_iw; From e7559507c668c9579e04a39f65d2e5c9dbe80c32 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 26 Aug 2019 23:24:40 +0800 Subject: [PATCH 591/864] Fix trailing empty lines on help screens --- crawl-ref/source/command.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc index a04372c19c48..f5e90ff2c279 100644 --- a/crawl-ref/source/command.cc +++ b/crawl-ref/source/command.cc @@ -567,7 +567,7 @@ int show_keyhelp_menu(const vector &lines, cmd_help.set_more(); for (unsigned i = 0; i < lines.size(); ++i) - cmd_help.add_formatted_string(lines[i], true); + cmd_help.add_formatted_string(lines[i], i < lines.size()-1); cmd_help.show(); @@ -576,7 +576,8 @@ int show_keyhelp_menu(const vector &lines, void show_specific_help(const string &key) { - const string help = getHelpString(key); + string help = getHelpString(key); + trim_string_right(help); vector formatted_lines; for (const string &line : split_string("\n", help, false, true)) formatted_lines.push_back(formatted_string::parse_string(line)); From 56e724e302fbf2d3cae59004e64eb9d548075037 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 26 Aug 2019 23:26:32 +0800 Subject: [PATCH 592/864] Improve local tiles tooltip appearance This commit removes the ability to specify a background colour with render_string(), and switches on the tooltip parameter instead. --- crawl-ref/source/fontwrapper-ft.cc | 27 ++++++++++++--------------- crawl-ref/source/fontwrapper-ft.h | 3 --- crawl-ref/source/tilefont.h | 3 --- crawl-ref/source/tilereg-dgn.cc | 3 +-- crawl-ref/source/tilereg-grid.cc | 2 +- crawl-ref/source/tilereg-msg.cc | 3 +-- crawl-ref/source/tilesdl.cc | 3 +-- 7 files changed, 16 insertions(+), 28 deletions(-) diff --git a/crawl-ref/source/fontwrapper-ft.cc b/crawl-ref/source/fontwrapper-ft.cc index bd3b0d7b0bdb..15f06962268b 100644 --- a/crawl-ref/source/fontwrapper-ft.cc +++ b/crawl-ref/source/fontwrapper-ft.cc @@ -461,18 +461,11 @@ void FTFontWrapper::draw_m_buf(unsigned int x_pos, unsigned int y_pos, glmanager->reset_transform(); } -static void _draw_box(int x_pos, int y_pos, float width, float height, - float box_width, unsigned char box_colour, - unsigned char box_alpha) +static void _draw_box(int x_pos, int y_pos, int width, int height, VColour colour) { unique_ptr buf(GLShapeBuffer::create(false, true)); - GLWPrim rect(x_pos - box_width, y_pos - box_width, - x_pos + width + box_width, y_pos + height + box_width); + GLWPrim rect(x_pos, y_pos, x_pos + width, y_pos + height); - VColour colour(term_colours[box_colour].r, - term_colours[box_colour].g, - term_colours[box_colour].b, - box_alpha); rect.set_col(colour); buf->add(rect); @@ -648,9 +641,7 @@ void FTFontWrapper::render_string(unsigned int px, unsigned int py, const char *text, const coord_def &min_pos, const coord_def &max_pos, - unsigned char font_colour, bool drop_shadow, - unsigned char box_alpha, - unsigned char box_colour, + unsigned char font_colour, unsigned int outline, bool tooltip) { @@ -743,10 +734,16 @@ void FTFontWrapper::render_string(unsigned int px, unsigned int py, else if (sy < min_pos.y) ty -= sy - min_pos.y; - if (box_alpha != 0) - _draw_box(tx, ty, wx, wy, outline, box_colour, box_alpha); + if (tooltip) + { + const VColour border_colour(125, 98, 60); + const VColour bg_colour(4, 2, 4); + _draw_box(tx-outline, ty-outline, wx+2*outline, wy+2*outline, border_colour); + outline -= 2; + _draw_box(tx-outline, ty-outline, wx+2*outline, wy+2*outline, bg_colour); + } - render_textblock(tx, ty, chars, colours, max_cols, max_rows, drop_shadow); + render_textblock(tx, ty, chars, colours, max_cols, max_rows, false); free(chars); free(colours); diff --git a/crawl-ref/source/fontwrapper-ft.h b/crawl-ref/source/fontwrapper-ft.h index 5c96bd0f5bd1..fd930a9d79fb 100644 --- a/crawl-ref/source/fontwrapper-ft.h +++ b/crawl-ref/source/fontwrapper-ft.h @@ -41,9 +41,6 @@ class FTFontWrapper : public FontWrapper const char *text, const coord_def &min_pos, const coord_def &max_pos, unsigned char font_colour, - bool drop_shadow = false, - unsigned char box_alpha = 0, - unsigned char box_colour = 0, unsigned int outline = 0, bool tooltip = false) override; diff --git a/crawl-ref/source/tilefont.h b/crawl-ref/source/tilefont.h index a80b7b171ea3..ea802d0b76a1 100644 --- a/crawl-ref/source/tilefont.h +++ b/crawl-ref/source/tilefont.h @@ -34,9 +34,6 @@ class FontWrapper const char *text, const coord_def &min_pos, const coord_def &max_pos, unsigned char font_colour, - bool drop_shadow = false, - unsigned char box_alpha = 0, - unsigned char box_colour = 0, unsigned int outline = 0, bool tooltip = false) = 0; diff --git a/crawl-ref/source/tilereg-dgn.cc b/crawl-ref/source/tilereg-dgn.cc index e4725be0adf6..7b4ac95b3ecc 100644 --- a/crawl-ref/source/tilereg-dgn.cc +++ b/crawl-ref/source/tilereg-dgn.cc @@ -256,8 +256,7 @@ void DungeonRegion::render() const coord_def min_pos(sx, sy); const coord_def max_pos(ex, ey); - m_tag_font->render_string(pc.x, pc.y, def.text, - min_pos, max_pos, WHITE, false); + m_tag_font->render_string(pc.x, pc.y, def.text, min_pos, max_pos, WHITE); } } diff --git a/crawl-ref/source/tilereg-grid.cc b/crawl-ref/source/tilereg-grid.cc index 218da0c42eec..527dbc01b02a 100644 --- a/crawl-ref/source/tilereg-grid.cc +++ b/crawl-ref/source/tilereg-grid.cc @@ -90,7 +90,7 @@ void GridRegion::draw_desc(const char *desc) const coord_def min_pos(sx, sy - dy); const coord_def max_pos(ex, ey); - m_tag_font->render_string(x, y, desc, min_pos, max_pos, WHITE, false, 200); + m_tag_font->render_string(x, y, desc, min_pos, max_pos, WHITE); } bool GridRegion::place_cursor(MouseEvent &event, unsigned int &item_idx) diff --git a/crawl-ref/source/tilereg-msg.cc b/crawl-ref/source/tilereg-msg.cc index 8aea641b8844..14ccec2101d2 100644 --- a/crawl-ref/source/tilereg-msg.cc +++ b/crawl-ref/source/tilereg-msg.cc @@ -71,8 +71,7 @@ void MessageRegion::render() if (ends_with(text, "..")) text = text.substr(0, text.find_last_of('\n')) + "\n..."; - m_font->render_string(sx + ox, sy + oy, text.c_str(), - min_pos, max_pos, WHITE, false); + m_font->render_string(sx + ox, sy + oy, text.c_str(), min_pos, max_pos, WHITE); return; } diff --git a/crawl-ref/source/tilesdl.cc b/crawl-ref/source/tilesdl.cc index fdf5d5e8cd59..6bd653e7a28e 100644 --- a/crawl-ref/source/tilesdl.cc +++ b/crawl-ref/source/tilesdl.cc @@ -1476,8 +1476,7 @@ void TilesFramework::redraw() FontWrapper *font = m_fonts[m_tip_font].font; font->render_string(m_mouse.x, m_mouse.y - 2, m_tooltip.c_str(), - min_pos, m_windowsz, WHITE, false, 220, BLUE, 5, - true); + min_pos, m_windowsz, LIGHTGREY, 7, true); } wm->swap_buffers(); From 65986e55dbb282e988196f0708d63fc986bf2330 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Tue, 27 Aug 2019 01:28:04 +0800 Subject: [PATCH 593/864] More font rendering refactoring This commit splits render_string() into render_hover_string(), used for rendering labels over dungeon tiles, and render_tooltip(). --- crawl-ref/source/fontwrapper-ft.cc | 156 ++++++++++++----------------- crawl-ref/source/fontwrapper-ft.h | 14 ++- crawl-ref/source/tilefont.h | 14 ++- crawl-ref/source/tilereg-dgn.cc | 5 +- crawl-ref/source/tilereg-grid.cc | 10 +- crawl-ref/source/tilereg-msg.cc | 2 +- crawl-ref/source/tilesdl.cc | 9 +- 7 files changed, 93 insertions(+), 117 deletions(-) diff --git a/crawl-ref/source/fontwrapper-ft.cc b/crawl-ref/source/fontwrapper-ft.cc index 15f06962268b..08e0bcb5d852 100644 --- a/crawl-ref/source/fontwrapper-ft.cc +++ b/crawl-ref/source/fontwrapper-ft.cc @@ -637,92 +637,32 @@ formatted_string FTFontWrapper::split(const formatted_string &str, return ret; } -void FTFontWrapper::render_string(unsigned int px, unsigned int py, - const char *text, +/** + * Render a tooltip around the given position. + * + * @param px the x coordinate + * @param py the y coordinate + * @param text the string to render + * @param min_pos the top-left boundary of the screen + * @param max_pos the bottom-right boundary of the screen + */ +void FTFontWrapper::render_tooltip(unsigned int px, unsigned int py, + const formatted_string &text, const coord_def &min_pos, - const coord_def &max_pos, - unsigned char font_colour, - unsigned int outline, - bool tooltip) + const coord_def &max_pos) { - ASSERT(text); - - // Determine extent of this text - unsigned int max_rows = 1; - unsigned int cols = 0; - unsigned int max_cols = 0; - char32_t c; - for (const char *tp = text; int s = utf8towc(&c, tp); tp += s) - { - int w = wcwidth(c); - if (w != -1) - cols += w; - max_cols = max(cols, max_cols); - - // NOTE: only newlines should be used for tool tips. Don't use EOL. - ASSERT(c != '\r'); - - if (c == '\n') - { - cols = 0; - max_rows++; - } - } - - // Create the text block - char32_t *chars = (char32_t*)malloc(max_rows * max_cols * sizeof(char32_t)); - uint8_t *colours = (uint8_t*)malloc(max_rows * max_cols); - for (unsigned int i = 0; i < max_rows * max_cols; i++) - chars[i] = ' '; - memset(colours, font_colour, max_rows * max_cols); - - // Fill the text block - cols = 0; - unsigned int rows = 0; - for (const char *tp = text; int s = utf8towc(&c, tp); tp += s) - { - int w = wcwidth(c); - if (w > 0) // FIXME: combining characters are silently ignored - { - chars[cols + rows * max_cols] = c; - cols++; - if (w == 2) - chars[cols + rows * max_cols] = ' ', cols++; - } - - if (c == '\n') - { - cols = 0; - rows++; - } - } + int outline = 7; + const int wx = string_width(text); + const int wy = string_height(text); - // Find a suitable location on screen - const int buffer = 5; // additional buffer size from edges + // text starting location + int tx = px - 15, ty = py + 20; - int wx = string_width(text); - int wy = max_rows * char_height(); - - int sx, sy; // box starting location, uses extra buffer - int tx, ty; // text starting location - - if (tooltip) - { - sy = py + outline; - ty = sy + buffer; - tx = px - 20; - sx = tx - buffer; - } - else - { - ty = py - wy - outline; - sy = ty - buffer; - tx = px - wx / 2; - sx = tx - buffer; - } - // box ending position - int ex = tx + wx + buffer; - int ey = ty + wy + buffer; + // box position, before shifting + const int sx = tx - outline; + const int sy = ty - outline; + const int ex = tx + wx + outline; + const int ey = ty + wy + outline; if (ex > max_pos.x) tx += max_pos.x - ex; @@ -734,19 +674,49 @@ void FTFontWrapper::render_string(unsigned int px, unsigned int py, else if (sy < min_pos.y) ty -= sy - min_pos.y; - if (tooltip) - { - const VColour border_colour(125, 98, 60); - const VColour bg_colour(4, 2, 4); - _draw_box(tx-outline, ty-outline, wx+2*outline, wy+2*outline, border_colour); - outline -= 2; - _draw_box(tx-outline, ty-outline, wx+2*outline, wy+2*outline, bg_colour); - } + const VColour border_colour(125, 98, 60); + const VColour bg_colour(4, 2, 4); + _draw_box(tx-outline, ty-outline, wx+2*outline, wy+2*outline, border_colour); + outline -= 2; + _draw_box(tx-outline, ty-outline, wx+2*outline, wy+2*outline, bg_colour); + + render_string(tx, ty, text); +} + +/** + * Render a string at the given position. + * + * @param px the x coordinate + * @param py the y coordinate + * @param text the string to render + * @param font_colour the text colour to use + */ +void FTFontWrapper::render_string(unsigned int px, unsigned int py, + const formatted_string &text) +{ + glmanager->reset_transform(); + FontBuffer m_font_buf(this); + m_font_buf.add(text, px, py); + m_font_buf.draw(); +} - render_textblock(tx, ty, chars, colours, max_cols, max_rows, false); +/** + * Render a string hovering above the given position, centred horizontally. + * + * @param px the x coordinate + * @param py the y coordinate + * @param text the string to render + * @param font_colour the text colour to use + */ +void FTFontWrapper::render_hover_string(unsigned int px, unsigned int py, + const formatted_string &text) +{ + const int wx = string_width(text); + const int wy = string_height(text); + const int ty = py - wy; + const int tx = px - wx / 2; - free(chars); - free(colours); + render_string(tx, ty, text); } /** diff --git a/crawl-ref/source/fontwrapper-ft.h b/crawl-ref/source/fontwrapper-ft.h index fd930a9d79fb..0360164f4d75 100644 --- a/crawl-ref/source/fontwrapper-ft.h +++ b/crawl-ref/source/fontwrapper-ft.h @@ -37,12 +37,16 @@ class FTFontWrapper : public FontWrapper bool drop_shadow = false) override; // render text + background box + virtual void render_tooltip(unsigned int x, unsigned int y, + const formatted_string &text, + const coord_def &min_pos, + const coord_def &max_pos) override; + virtual void render_string(unsigned int x, unsigned int y, - const char *text, const coord_def &min_pos, - const coord_def &max_pos, - unsigned char font_colour, - unsigned int outline = 0, - bool tooltip = false) override; + const formatted_string &text) override; + + virtual void render_hover_string(unsigned int x, unsigned int y, + const formatted_string &text) override; // FontBuffer helper functions virtual void store(FontBuffer &buf, float &x, float &y, diff --git a/crawl-ref/source/tilefont.h b/crawl-ref/source/tilefont.h index ea802d0b76a1..1c6a22e5acba 100644 --- a/crawl-ref/source/tilefont.h +++ b/crawl-ref/source/tilefont.h @@ -30,12 +30,16 @@ class FontWrapper bool drop_shadow = false) = 0; // render text + background box + virtual void render_tooltip(unsigned int x, unsigned int y, + const formatted_string &text, + const coord_def &min_pos, + const coord_def &max_pos) = 0; + virtual void render_string(unsigned int x, unsigned int y, - const char *text, const coord_def &min_pos, - const coord_def &max_pos, - unsigned char font_colour, - unsigned int outline = 0, - bool tooltip = false) = 0; + const formatted_string &text) = 0; + + virtual void render_hover_string(unsigned int x, unsigned int y, + const formatted_string &text) = 0; // FontBuffer helper functions virtual void store(FontBuffer &buf, float &x, float &y, diff --git a/crawl-ref/source/tilereg-dgn.cc b/crawl-ref/source/tilereg-dgn.cc index 7b4ac95b3ecc..38f97d0b278d 100644 --- a/crawl-ref/source/tilereg-dgn.cc +++ b/crawl-ref/source/tilereg-dgn.cc @@ -254,9 +254,8 @@ void DungeonRegion::render() // center this coord, which is at the top left of gc's cell pc.x += dx / 2; - const coord_def min_pos(sx, sy); - const coord_def max_pos(ex, ey); - m_tag_font->render_string(pc.x, pc.y, def.text, min_pos, max_pos, WHITE); + const auto text = formatted_string(def.text, WHITE); + m_tag_font->render_hover_string(pc.x, pc.y, text); } } diff --git a/crawl-ref/source/tilereg-grid.cc b/crawl-ref/source/tilereg-grid.cc index 527dbc01b02a..8b1b5e509170 100644 --- a/crawl-ref/source/tilereg-grid.cc +++ b/crawl-ref/source/tilereg-grid.cc @@ -4,6 +4,7 @@ #include "tilereg-grid.h" +#include "format.h" #include "libutil.h" #include "random.h" #include "tile-inventory-flags.h" @@ -80,17 +81,14 @@ void GridRegion::draw_desc(const char *desc) ASSERT(desc); // Always draw the description in the inventory header. (jpeg) - int x = sx + ox + dx / 2; - int y = sy + oy; + int x = sx + ox; + int y = sy + oy - dx / 2; // ... unless we're using the touch UI, in which case: put at bottom if (tiles.is_using_small_layout()) y = wy; - const coord_def min_pos(sx, sy - dy); - const coord_def max_pos(ex, ey); - - m_tag_font->render_string(x, y, desc, min_pos, max_pos, WHITE); + m_tag_font->render_string(x, y, formatted_string(desc, WHITE)); } bool GridRegion::place_cursor(MouseEvent &event, unsigned int &item_idx) diff --git a/crawl-ref/source/tilereg-msg.cc b/crawl-ref/source/tilereg-msg.cc index 14ccec2101d2..dc8d868e4ac4 100644 --- a/crawl-ref/source/tilereg-msg.cc +++ b/crawl-ref/source/tilereg-msg.cc @@ -71,7 +71,7 @@ void MessageRegion::render() if (ends_with(text, "..")) text = text.substr(0, text.find_last_of('\n')) + "\n..."; - m_font->render_string(sx + ox, sy + oy, text.c_str(), min_pos, max_pos, WHITE); + m_font->render_string(sx + ox, sy + oy, formatted_string(text, WHITE)); return; } diff --git a/crawl-ref/source/tilesdl.cc b/crawl-ref/source/tilesdl.cc index 6bd653e7a28e..e8da601cb540 100644 --- a/crawl-ref/source/tilesdl.cc +++ b/crawl-ref/source/tilesdl.cc @@ -1472,11 +1472,12 @@ void TilesFramework::redraw() // Draw tooltip if (Options.tile_tooltip_ms > 0 && !m_tooltip.empty()) { - const coord_def min_pos(0, 0); + const int buffer = 5; + const coord_def min_pos = coord_def() + buffer; + const coord_def max_pos = m_windowsz - buffer; FontWrapper *font = m_fonts[m_tip_font].font; - - font->render_string(m_mouse.x, m_mouse.y - 2, m_tooltip.c_str(), - min_pos, m_windowsz, LIGHTGREY, 7, true); + font->render_tooltip(m_mouse.x, m_mouse.y, formatted_string(m_tooltip), + min_pos, max_pos); } wm->swap_buffers(); From ac8ac2ac75c025a2467891c009c18e94cad181f7 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Tue, 27 Aug 2019 13:14:35 +0800 Subject: [PATCH 594/864] Fix extra newlines in local tiles tooltip --- crawl-ref/source/tilereg-dgn.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/tilereg-dgn.cc b/crawl-ref/source/tilereg-dgn.cc index 38f97d0b278d..23af3e812757 100644 --- a/crawl-ref/source/tilereg-dgn.cc +++ b/crawl-ref/source/tilereg-dgn.cc @@ -1002,7 +1002,7 @@ bool DungeonRegion::update_tip_text(string &tip) #ifdef WIZARD if (you.wizard) { - if (ret) + if (!tip.empty()) tip += "\n\n"; if (you.see_cell(gc)) @@ -1039,7 +1039,7 @@ bool DungeonRegion::update_tip_text(string &tip) tip += make_stringf("\nFLV: floor: %d (%s) (%d)" "\n wall: %d (%s) (%d)" "\n feat: %d (%s) (%d)" - "\n special: %d\n", + "\n special: %d", env.tile_flv(gc).floor, tile_dngn_name(env.tile_flv(gc).floor), env.tile_flv(gc).floor_idx, From a2d57835b74a1a036f555aa6c6d6f9ad2f317930 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Tue, 27 Aug 2019 13:43:34 +0800 Subject: [PATCH 595/864] Fix deck menu being easily closable --- crawl-ref/source/decks.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/decks.cc b/crawl-ref/source/decks.cc index cb72651dde4a..26b8649e0000 100644 --- a/crawl-ref/source/decks.cc +++ b/crawl-ref/source/decks.cc @@ -523,7 +523,7 @@ static char _deck_hotkey(deck_type deck) static deck_type _choose_deck(const string title = "Draw") { - ToggleableMenu deck_menu(MF_SINGLESELECT | MF_ANYPRINTABLE + ToggleableMenu deck_menu(MF_SINGLESELECT | MF_NO_WRAP_ROWS | MF_TOGGLE_ACTION | MF_ALWAYS_SHOW_MORE); { ToggleableMenuEntry* me = From b99ddf99acf8b64425d6c46bd367f9921d099a50 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Tue, 27 Aug 2019 13:44:09 +0800 Subject: [PATCH 596/864] Make menu colours more consistent --- crawl-ref/source/decks.cc | 6 ------ crawl-ref/source/spl-cast.cc | 3 --- 2 files changed, 9 deletions(-) diff --git a/crawl-ref/source/decks.cc b/crawl-ref/source/decks.cc index 26b8649e0000..32f53396cd9f 100644 --- a/crawl-ref/source/decks.cc +++ b/crawl-ref/source/decks.cc @@ -532,9 +532,6 @@ static deck_type _choose_deck(const string title = "Draw") "Describe which deck? " "Cards available", MEL_TITLE); -#ifdef USE_TILE_LOCAL - me->colour = BLUE; -#endif deck_menu.set_title(me, true, true); } deck_menu.set_tag("deck"); @@ -718,9 +715,6 @@ static void _draw_stack(int to_stack) "Describe which deck? " "Cards available", MEL_TITLE); -#ifdef USE_TILE_LOCAL - me->colour = BLUE; -#endif deck_menu.set_title(me, true, true); } deck_menu.set_tag("deck"); diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc index 5105157e69e7..45524370e961 100644 --- a/crawl-ref/source/spl-cast.cc +++ b/crawl-ref/source/spl-cast.cc @@ -186,9 +186,6 @@ int list_spells(bool toggle_with_I, bool viewing, bool allow_preselect, titlestring + " Type Failure Level ", titlestring + " Power Range Hunger Noise ", MEL_TITLE); -#ifdef USE_TILE_LOCAL - me->colour = BLUE; -#endif spell_menu.set_title(me, true, true); } spell_menu.set_highlighter(nullptr); From 12c97a3ad0d69c72d42e27def2dfd9c3e75785f0 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Tue, 27 Aug 2019 15:32:15 +0800 Subject: [PATCH 597/864] Fix bad FAQ menu entry wrapping --- crawl-ref/source/command.cc | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc index f5e90ff2c279..c1bd2a5ed64b 100644 --- a/crawl-ref/source/command.cc +++ b/crawl-ref/source/command.cc @@ -468,33 +468,14 @@ static void _handle_FAQ() title->colour = YELLOW; FAQmenu.set_title(title); - const int width = get_number_of_cols(); - for (unsigned int i = 0, size = question_keys.size(); i < size; i++) { const char letter = index_to_letter(i); - string question = getFAQ_Question(question_keys[i]); - // Wraparound if the question is longer than fits into a line. - linebreak_string(question, width - 4); - vector fss; - formatted_string::parse_string_to_multiple(question, fss); - - MenuEntry *me; - for (unsigned int j = 0; j < fss.size(); j++) - { - if (j == 0) - { - me = new MenuEntry(question, MEL_ITEM, 1, letter); - me->data = &question_keys[i]; - } - else - { - question = " " + fss[j].tostring(); - me = new MenuEntry(question, MEL_ITEM, 1); - } - FAQmenu.add_entry(me); - } + trim_string_right(question); + MenuEntry *me = new MenuEntry(question, MEL_ITEM, 1, letter); + me->data = &question_keys[i]; + FAQmenu.add_entry(me); } while (true) From bdd17524c8e98561c201b80ef3e85c8f7f1d59a0 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Tue, 27 Aug 2019 15:41:16 +0800 Subject: [PATCH 598/864] Remove dead inscription hints code --- crawl-ref/source/hints.cc | 32 -------------------------------- crawl-ref/source/hints.h | 1 - 2 files changed, 33 deletions(-) diff --git a/crawl-ref/source/hints.cc b/crawl-ref/source/hints.cc index c10f20436024..d4cd67517f58 100644 --- a/crawl-ref/source/hints.cc +++ b/crawl-ref/source/hints.cc @@ -3441,38 +3441,6 @@ string hints_describe_item(const item_def &item) return broken; } -void hints_inscription_info(string prompt) -{ - // Don't print anything if there's not enough space. - if (wherey() >= get_number_of_lines() - 1) - return; - - ostringstream text; - text << "<" << colour_to_str(channel_to_colour(MSGCH_TUTORIAL)) << ">"; - - bool longtext = false; - if (wherey() <= get_number_of_lines() - 8) - { - text << "\n" - "Inscriptions are a powerful concept of Dungeon Crawl.\n" - "You can inscribe items to comment on them \n" - "or to set rules for item interaction. If you are new to Crawl, \n" - "you can safely ignore this feature."; - - longtext = true; - } - - text << "\n" - "(In the main screen, press ?6 for more information.)\n"; - text << ""; - - formatted_string::parse_string(text.str()).display(); - - // Ask a second time, if it's been a longish interruption. - if (longtext && !prompt.empty() && wherey() <= get_number_of_lines() - 2) - formatted_string::parse_string(prompt).display(); -} - // FIXME: With the new targeting system, the hints for interesting monsters // and features ("right-click/press v for more information") are no // longer getting displayed. diff --git a/crawl-ref/source/hints.h b/crawl-ref/source/hints.h index 6ad7c21f9754..bd1886a225dc 100644 --- a/crawl-ref/source/hints.h +++ b/crawl-ref/source/hints.h @@ -181,7 +181,6 @@ string hints_memorise_info(); // Additional information for tutorial players. void check_item_hint(const item_def &item, unsigned int num_old_talents); string hints_describe_item(const item_def &item); -void hints_inscription_info(string prompt); bool hints_pos_interesting(int x, int y); string hints_describe_pos(int x, int y); bool hints_monster_interesting(const monster* mons); From d8832a91ebedcfaacf864a49236267e96c9006ad Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Fri, 6 Sep 2019 02:31:24 +0800 Subject: [PATCH 599/864] Properly cache global state for later rendering Local tiles rendering code should use only the state stored in the view buffer passed to load_dungeon; in particular, it should *not* access env.* whenever a redraw is needed, since this state may have been updated. Tile flavours are unlikely to change, but you never know... --- crawl-ref/source/tilereg-dgn.cc | 10 ---------- crawl-ref/source/tileview.cc | 2 ++ 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/crawl-ref/source/tilereg-dgn.cc b/crawl-ref/source/tilereg-dgn.cc index 23af3e812757..b57200cc36dc 100644 --- a/crawl-ref/source/tilereg-dgn.cc +++ b/crawl-ref/source/tilereg-dgn.cc @@ -121,17 +121,7 @@ void DungeonRegion::pack_buffers() packed_cell tile_cell = packed_cell(vbuf_cell->tile); if (map_bounds(gc)) - { - tile_cell.flv = env.tile_flv(gc); pack_cell_overlays(gc, &tile_cell); - } - else - { - tile_cell.flv.floor = 0; - tile_cell.flv.wall = 0; - tile_cell.flv.special = 0; - tile_cell.flv.feat = 0; - } m_buf_dngn.add(tile_cell, x, y); diff --git a/crawl-ref/source/tileview.cc b/crawl-ref/source/tileview.cc index edd1ac1b6c93..7ab03bef4649 100644 --- a/crawl-ref/source/tileview.cc +++ b/crawl-ref/source/tileview.cc @@ -1497,5 +1497,7 @@ void tile_apply_properties(const coord_def &gc, packed_cell &cell) } } } + + cell.flv = env.tile_flv(gc); } #endif From 2324e3a9aec7c86a998283cf851e4352c932d1e7 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Fri, 6 Sep 2019 06:08:40 +0800 Subject: [PATCH 600/864] Cache map knowledge for later rendering Rendering cell overlays needs access to the state of adjacent cells, in order to properly render waves. Previous code was directly accessing the current simulation state in env.map_knowledge, which caused glitches when viewwindow was exiting early (due to run_dont_draw) and not copying the current tile fg/bg. In general, render code should never access the global game state. This commit copies the current env.map_knowledge for each cell into packed_cell; this structure notably includes cloud_info, item_info, and monster_info structs copied from their corresponding global instances (so they're safely accessible). There are still a few locations where global state is accessed, such as player_in_branch() calls. These are relatively benign, but they should be removed as well. --- crawl-ref/source/map-cell.h | 10 ++ crawl-ref/source/tilecell.cc | 156 ++++++++++++++++++-------------- crawl-ref/source/tilecell.h | 10 +- crawl-ref/source/tiledgnbuf.cc | 6 +- crawl-ref/source/tilereg-dgn.cc | 6 +- crawl-ref/source/tileview.cc | 5 - crawl-ref/source/tileweb.cc | 10 +- crawl-ref/source/tileweb.h | 4 +- crawl-ref/source/view.cc | 4 + crawl-ref/source/viewgeom.cc | 6 ++ crawl-ref/source/viewgeom.h | 7 ++ 11 files changed, 141 insertions(+), 83 deletions(-) diff --git a/crawl-ref/source/map-cell.h b/crawl-ref/source/map-cell.h index 855123f07f5d..6dc1d384845f 100644 --- a/crawl-ref/source/map-cell.h +++ b/crawl-ref/source/map-cell.h @@ -109,6 +109,16 @@ struct map_cell return *this; } + bool operator ==(const map_cell &other) const + { + return memcmp(this, &other, sizeof(map_cell)) == 0; + } + + bool operator !=(const map_cell &other) const + { + return memcmp(this, &other, sizeof(map_cell)) != 0; + } + void clear() { *this = map_cell(); diff --git a/crawl-ref/source/tilecell.cc b/crawl-ref/source/tilecell.cc index ae694f8aa08d..fc7411fd2fa8 100644 --- a/crawl-ref/source/tilecell.cc +++ b/crawl-ref/source/tilecell.cc @@ -2,12 +2,13 @@ #ifdef USE_TILE #include "tilecell.h" -#include "cloud.h" #include "coord.h" #include "coordit.h" -#include "env.h" #include "terrain.h" +#include "tile-flags.h" #include "tiledef-dngn.h" +#include "tiledef-main.h" +#include "viewgeom.h" void packed_cell::clear() { @@ -15,6 +16,7 @@ void packed_cell::clear() fg = 0; bg = 0; cloud = 0; + map_knowledge.clear(); flv.floor_idx = 0; flv.wall_idx = 0; @@ -49,6 +51,7 @@ bool packed_cell::operator ==(const packed_cell &other) const if (fg != other.fg) return false; if (bg != other.bg) return false; if (cloud != other.cloud) return false; + if (map_knowledge != other.map_knowledge) return false; if (is_bloody != other.is_bloody) return false; if (is_silenced != other.is_silenced) return false; @@ -82,12 +85,12 @@ enum wave_type WV_DEEP, }; -static void _add_overlay(int tileidx, packed_cell *cell) +static void _add_overlay(int tileidx, packed_cell& cell) { - cell->dngn_overlay[cell->num_dngn_overlay++] = tileidx; + cell.dngn_overlay[cell.num_dngn_overlay++] = tileidx; } -typedef bool (*map_predicate) (const coord_def&); +typedef bool (*map_predicate) (const coord_def&, crawl_view_buffer& vbuf); static coord_def overlay_directions[] = { @@ -101,15 +104,17 @@ static coord_def overlay_directions[] = coord_def(-1, 1) }; -static void _add_directional_overlays(const coord_def& gc, packed_cell* cell, +static void _add_directional_overlays(const coord_def& gc, crawl_view_buffer& vbuf, tileidx_t tile, map_predicate pred, uint8_t tile_mask = 0xFF) { + auto& cell = vbuf(gc).tile; + uint8_t dir_mask = 0; for (int i = 0; i < 8; ++i) { - if (!pred(gc + overlay_directions[i])) + if (!pred(gc + overlay_directions[i], vbuf)) continue; if (i > 3) @@ -138,11 +143,18 @@ static void _add_directional_overlays(const coord_def& gc, packed_cell* cell, } } -static void _pack_shoal_waves(const coord_def &gc, packed_cell *cell) +static bool _feat_has_ink(coord_def gc, crawl_view_buffer& vbuf) { + return vbuf(gc).tile.map_knowledge.cloud() == CLOUD_INK; +} + +static void _pack_shoal_waves(const coord_def &gc, crawl_view_buffer& vbuf) +{ + auto& cell = vbuf(gc).tile; + // Add wave tiles on floor adjacent to shallow water. - const dungeon_feature_type feat = env.map_knowledge(gc).feat(); - const bool feat_has_ink = (cloud_type_at(coord_def(gc)) == CLOUD_INK); + const auto feat = cell.map_knowledge.feat(); + const bool feat_has_ink = _feat_has_ink(gc, vbuf); if (feat == DNGN_DEEP_WATER && feat_has_ink) { @@ -165,13 +177,17 @@ static void _pack_shoal_waves(const coord_def &gc, packed_cell *cell) for (adjacent_iterator ri(gc, true); ri; ++ri) { - if (!env.map_knowledge(*ri).seen() && !env.map_knowledge(*ri).mapped()) + if (ri->x < 0 || ri->x >= vbuf.size().x || ri->y < 0 || ri->y >= vbuf.size().y) + continue; + const map_cell& adj_knowledge = vbuf(*ri).tile.map_knowledge; + if (!adj_knowledge.seen() && !adj_knowledge.mapped()) continue; - const bool ink = (cloud_type_at(coord_def(*ri)) == CLOUD_INK); + const bool ink = _feat_has_ink(*ri, vbuf); + const auto adj_feat = adj_knowledge.feat(); wave_type wt = WV_NONE; - if (env.map_knowledge(*ri).feat() == DNGN_SHALLOW_WATER) + if (adj_feat == DNGN_SHALLOW_WATER) { // Adjacent shallow water is only interesting for // floor cells. @@ -181,7 +197,7 @@ static void _pack_shoal_waves(const coord_def &gc, packed_cell *cell) if (feat != DNGN_SHALLOW_WATER) wt = WV_SHALLOW; } - else if (env.map_knowledge(*ri).feat() == DNGN_DEEP_WATER) + else if (adj_feat == DNGN_DEEP_WATER) wt = WV_DEEP; else continue; @@ -326,12 +342,12 @@ static void _pack_shoal_waves(const coord_def &gc, packed_cell *cell) } } -static dungeon_feature_type _safe_feat(coord_def gc) +static dungeon_feature_type _safe_feat(coord_def gc, crawl_view_buffer& vbuf) { - if (!map_bounds(gc)) + if (gc.x < 0 || gc.x >= vbuf.size().x || gc.y < 0 || gc.y >= vbuf.size().y) return DNGN_UNSEEN; - return env.map_knowledge(gc).feat(); + return vbuf(gc).tile.map_knowledge.feat(); } static bool _feat_is_mangrove(dungeon_feature_type feat) @@ -339,80 +355,82 @@ static bool _feat_is_mangrove(dungeon_feature_type feat) return feat == DNGN_TREE && player_in_branch(BRANCH_SWAMP); } -static bool _is_seen_land(coord_def gc) +static bool _is_seen_land(coord_def gc, crawl_view_buffer& vbuf) { - const dungeon_feature_type feat = _safe_feat(gc); + const auto feat = _safe_feat(gc, vbuf); return feat != DNGN_UNSEEN && !feat_is_water(feat) && !feat_is_lava(feat) && !_feat_is_mangrove(feat); } -static bool _is_seen_shallow(coord_def gc) +static bool _is_seen_shallow(coord_def gc, crawl_view_buffer& vbuf) { - const dungeon_feature_type feat = _safe_feat(gc); + const auto feat = _safe_feat(gc, vbuf); return feat == DNGN_SHALLOW_WATER || _feat_is_mangrove(feat); } -static void _pack_default_waves(const coord_def &gc, packed_cell *cell) +static void _pack_default_waves(const coord_def &gc, crawl_view_buffer& vbuf) { + auto& cell = vbuf(gc).tile; // Any tile on water with an adjacent solid tile will get an extra // bit of shoreline. - dungeon_feature_type feat = env.map_knowledge(gc).feat(); + auto feat = cell.map_knowledge.feat(); + auto colour = cell.map_knowledge.feat_colour(); // Treat trees in Swamp as though they were shallow water. - if (cell->mangrove_water && feat == DNGN_TREE) + if (cell.mangrove_water && feat == DNGN_TREE) feat = DNGN_SHALLOW_WATER; if (!feat_is_water(feat) && !feat_is_lava(feat)) return; - if (feat == DNGN_DEEP_WATER && !env.grid_colours(gc)) + if (feat == DNGN_DEEP_WATER && colour) { - if (_is_seen_shallow(coord_def(gc.x, gc.y - 1))) + if (_is_seen_shallow(coord_def(gc.x, gc.y - 1), vbuf)) _add_overlay(TILE_DNGN_WAVE_N, cell); - if (_is_seen_shallow(coord_def(gc.x + 1, gc.y - 1))) + if (_is_seen_shallow(coord_def(gc.x + 1, gc.y - 1), vbuf)) _add_overlay(TILE_DNGN_WAVE_NE, cell); - if (_is_seen_shallow(coord_def(gc.x + 1, gc.y))) + if (_is_seen_shallow(coord_def(gc.x + 1, gc.y), vbuf)) _add_overlay(TILE_DNGN_WAVE_E, cell); - if (_is_seen_shallow(coord_def(gc.x + 1, gc.y + 1))) + if (_is_seen_shallow(coord_def(gc.x + 1, gc.y + 1), vbuf)) _add_overlay(TILE_DNGN_WAVE_SE, cell); - if (_is_seen_shallow(coord_def(gc.x, gc.y + 1))) + if (_is_seen_shallow(coord_def(gc.x, gc.y + 1), vbuf)) _add_overlay(TILE_DNGN_WAVE_S, cell); - if (_is_seen_shallow(coord_def(gc.x - 1, gc.y + 1))) + if (_is_seen_shallow(coord_def(gc.x - 1, gc.y + 1), vbuf)) _add_overlay(TILE_DNGN_WAVE_SW, cell); - if (_is_seen_shallow(coord_def(gc.x - 1, gc.y))) + if (_is_seen_shallow(coord_def(gc.x - 1, gc.y), vbuf)) _add_overlay(TILE_DNGN_WAVE_W, cell); - if (_is_seen_shallow(coord_def(gc.x - 1, gc.y - 1))) + if (_is_seen_shallow(coord_def(gc.x - 1, gc.y - 1), vbuf)) _add_overlay(TILE_DNGN_WAVE_NW, cell); } // Sewer water - if (feat == DNGN_DEEP_WATER && env.grid_colours(gc) == GREEN) + if (feat == DNGN_DEEP_WATER && colour == GREEN) { - if (_is_seen_shallow(coord_def(gc.x, gc.y - 1))) + if (_is_seen_shallow(coord_def(gc.x, gc.y - 1), vbuf)) _add_overlay(TILE_MURKY_WAVE_N, cell); - if (_is_seen_shallow(coord_def(gc.x + 1, gc.y - 1))) + if (_is_seen_shallow(coord_def(gc.x + 1, gc.y - 1), vbuf)) _add_overlay(TILE_MURKY_WAVE_NE, cell); - if (_is_seen_shallow(coord_def(gc.x + 1, gc.y))) + if (_is_seen_shallow(coord_def(gc.x + 1, gc.y), vbuf)) _add_overlay(TILE_MURKY_WAVE_E, cell); - if (_is_seen_shallow(coord_def(gc.x + 1, gc.y + 1))) + if (_is_seen_shallow(coord_def(gc.x + 1, gc.y + 1), vbuf)) _add_overlay(TILE_MURKY_WAVE_SE, cell); - if (_is_seen_shallow(coord_def(gc.x, gc.y + 1))) + if (_is_seen_shallow(coord_def(gc.x, gc.y + 1), vbuf)) _add_overlay(TILE_MURKY_WAVE_S, cell); - if (_is_seen_shallow(coord_def(gc.x - 1, gc.y + 1))) + if (_is_seen_shallow(coord_def(gc.x - 1, gc.y + 1), vbuf)) _add_overlay(TILE_MURKY_WAVE_SW, cell); - if (_is_seen_shallow(coord_def(gc.x - 1, gc.y))) + if (_is_seen_shallow(coord_def(gc.x - 1, gc.y), vbuf)) _add_overlay(TILE_MURKY_WAVE_W, cell); - if (_is_seen_shallow(coord_def(gc.x - 1, gc.y - 1))) + if (_is_seen_shallow(coord_def(gc.x - 1, gc.y - 1), vbuf)) _add_overlay(TILE_MURKY_WAVE_NW, cell); } - bool north = _is_seen_land(coord_def(gc.x, gc.y - 1)); - bool west = _is_seen_land(coord_def(gc.x - 1, gc.y)); - bool east = _is_seen_land(coord_def(gc.x + 1, gc.y)); + bool north = _is_seen_land(coord_def(gc.x, gc.y - 1), vbuf); + bool west = _is_seen_land(coord_def(gc.x - 1, gc.y), vbuf); + bool east = _is_seen_land(coord_def(gc.x + 1, gc.y), vbuf); - if (north || west || east && (!env.grid_colours(gc) || env.grid_colours(gc) == LIGHTGREEN)) + if (north || west || east && (colour == BLACK || colour == LIGHTGREEN)) { if (north) _add_overlay(TILE_SHORE_N, cell); @@ -427,71 +445,77 @@ static void _pack_default_waves(const coord_def &gc, packed_cell *cell) } } -static bool _is_seen_wall(coord_def gc) +static bool _is_seen_wall(coord_def gc, crawl_view_buffer& vbuf) { - const dungeon_feature_type feat = _safe_feat(gc); + const auto feat = _safe_feat(gc, vbuf); return (feat_is_opaque(feat) || feat_is_wall(feat)) && feat != DNGN_TREE && feat != DNGN_UNSEEN; } -static void _pack_wall_shadows(const coord_def &gc, packed_cell *cell, +static void _pack_wall_shadows(const coord_def &gc, crawl_view_buffer& vbuf, tileidx_t tile) { - if (_is_seen_wall(gc) || _safe_feat(gc) == DNGN_GRATE) + if (_is_seen_wall(gc, vbuf) || _safe_feat(gc, vbuf) == DNGN_GRATE) return; + auto& cell = vbuf(gc).tile; + bool ne = 0; bool nw = 0; int offset; // orthogonals - if (_is_seen_wall(coord_def(gc.x - 1, gc.y))) + if (_is_seen_wall(coord_def(gc.x - 1, gc.y), vbuf)) { - offset = _is_seen_wall(coord_def(gc.x - 1, gc.y - 1)) ? 0 : 5; + offset = _is_seen_wall(coord_def(gc.x - 1, gc.y - 1), vbuf) ? 0 : 5; _add_overlay(tile + offset, cell); nw = 1; } - if (_is_seen_wall(coord_def(gc.x, gc.y - 1))) + if (_is_seen_wall(coord_def(gc.x, gc.y - 1), vbuf)) { _add_overlay(tile + 2, cell); ne = 1; nw = 1; } - if (_is_seen_wall(coord_def(gc.x + 1, gc.y))) + if (_is_seen_wall(coord_def(gc.x + 1, gc.y), vbuf)) { - offset = _is_seen_wall(coord_def(gc.x + 1, gc.y - 1)) ? 4 : 6; + offset = _is_seen_wall(coord_def(gc.x + 1, gc.y - 1), vbuf) ? 4 : 6; _add_overlay(tile + offset, cell); ne = 1; } // corners - if (nw == 0 && _is_seen_wall(coord_def(gc.x - 1, gc.y - 1))) + if (nw == 0 && _is_seen_wall(coord_def(gc.x - 1, gc.y - 1), vbuf)) _add_overlay(tile + 1, cell); - if (ne == 0 && _is_seen_wall(coord_def(gc.x + 1, gc.y - 1))) + if (ne == 0 && _is_seen_wall(coord_def(gc.x + 1, gc.y - 1), vbuf)) _add_overlay(tile + 3, cell); } -static bool _is_seen_slimy_wall(const coord_def& gc) +static bool _is_seen_slimy_wall(const coord_def& gc, crawl_view_buffer &vbuf) { - const dungeon_feature_type feat = _safe_feat(gc); + const auto feat = _safe_feat(gc, vbuf); return feat == DNGN_SLIMY_WALL; } -void pack_cell_overlays(const coord_def &gc, packed_cell *cell) +void pack_cell_overlays(const coord_def &gc, crawl_view_buffer &vbuf) { - if (env.map_knowledge(gc).feat() == DNGN_UNSEEN) + auto& cell = vbuf(gc).tile; + + cell.num_dngn_overlay = 0; + + if (cell.map_knowledge.feat() == DNGN_UNSEEN) return; // Don't put overlays on unseen tiles if (player_in_branch(BRANCH_SHOALS)) - _pack_shoal_waves(gc, cell); + _pack_shoal_waves(gc, vbuf); else - _pack_default_waves(gc, cell); + _pack_default_waves(gc, vbuf); if (player_in_branch(BRANCH_SLIME) && - env.map_knowledge(gc).feat() != DNGN_SLIMY_WALL) + cell.map_knowledge.feat() != DNGN_SLIMY_WALL) { - _add_directional_overlays(gc, cell, TILE_SLIME_OVERLAY, + _add_directional_overlays(gc, vbuf, TILE_SLIME_OVERLAY, _is_seen_slimy_wall); } else @@ -499,7 +523,7 @@ void pack_cell_overlays(const coord_def &gc, packed_cell *cell) tileidx_t shadow_tile = TILE_DNGN_WALL_SHADOW; if (player_in_branch(BRANCH_CRYPT) || player_in_branch(BRANCH_DEPTHS)) shadow_tile = TILE_DNGN_WALL_SHADOW_DARK; - _pack_wall_shadows(gc, cell, shadow_tile); + _pack_wall_shadows(gc, vbuf, shadow_tile); } } #endif //TILECELL.CC diff --git a/crawl-ref/source/tilecell.h b/crawl-ref/source/tilecell.h index 623ff533d682..cca8f2b728c2 100644 --- a/crawl-ref/source/tilecell.h +++ b/crawl-ref/source/tilecell.h @@ -1,6 +1,8 @@ #ifdef USE_TILE #pragma once +#include "map-cell.h" + enum halo_type { HALO_NONE = 0, @@ -21,6 +23,9 @@ struct packed_cell tile_flavour flv; tileidx_t cloud; + // This is directly copied from env.map_knowledge by viewwindow() + map_cell map_knowledge; + bool is_highlighted_summoner; bool is_bloody; bool is_silenced; @@ -59,6 +64,7 @@ struct packed_cell packed_cell(const packed_cell* c) : num_dngn_overlay(c->num_dngn_overlay), fg(c->fg), bg(c->bg), flv(c->flv), cloud(c->cloud), + map_knowledge(c->map_knowledge), is_highlighted_summoner(c->is_highlighted_summoner), is_bloody(c->is_bloody), is_silenced(c->is_silenced), @@ -83,8 +89,10 @@ struct packed_cell void clear(); }; +class crawl_view_buffer; + // For a given location, pack any waves/ink/wall shadow tiles // that require knowledge of the surrounding env cells. -void pack_cell_overlays(const coord_def &gc, packed_cell *cell); +void pack_cell_overlays(const coord_def &gc, crawl_view_buffer &vbuf); #endif // TILECELL_H diff --git a/crawl-ref/source/tiledgnbuf.cc b/crawl-ref/source/tiledgnbuf.cc index 9d0c034be63e..a7be0803b983 100644 --- a/crawl-ref/source/tiledgnbuf.cc +++ b/crawl-ref/source/tiledgnbuf.cc @@ -40,7 +40,11 @@ void DungeonCellBuffer::add(const packed_cell &cell, int x, int y) const tileidx_t fg_idx = cell.fg & TILE_FLAG_MASK; const bool in_water = _in_water(cell); - const tileidx_t cloud_idx = cell.cloud & TILE_FLAG_MASK; + tileidx_t cloud_idx = cell.cloud & TILE_FLAG_MASK; + + // in the shoals, ink is handled in pack_cell_overlays(): don't overdraw + if (cloud_idx == TILE_CLOUD_INK && player_in_branch(BRANCH_SHOALS)) + cloud_idx = 0; if (fg_idx >= TILEP_MCACHE_START) { diff --git a/crawl-ref/source/tilereg-dgn.cc b/crawl-ref/source/tilereg-dgn.cc index b57200cc36dc..32f9e071cb43 100644 --- a/crawl-ref/source/tilereg-dgn.cc +++ b/crawl-ref/source/tilereg-dgn.cc @@ -119,11 +119,9 @@ void DungeonRegion::pack_buffers() { coord_def gc(x + m_cx_to_gx, y + m_cy_to_gy); - packed_cell tile_cell = packed_cell(vbuf_cell->tile); if (map_bounds(gc)) - pack_cell_overlays(gc, &tile_cell); - - m_buf_dngn.add(tile_cell, x, y); + pack_cell_overlays(coord_def(x, y), m_vbuf); + m_buf_dngn.add(vbuf_cell->tile, x, y); const int fcol = vbuf_cell->flash_colour; if (fcol) diff --git a/crawl-ref/source/tileview.cc b/crawl-ref/source/tileview.cc index 7ab03bef4649..d11d511ebe47 100644 --- a/crawl-ref/source/tileview.cc +++ b/crawl-ref/source/tileview.cc @@ -1037,11 +1037,6 @@ void tile_reset_feat(const coord_def &gc) static void _tile_place_cloud(const coord_def &gc, const cloud_info &cl) { - // In the Shoals, ink is handled differently. (jpeg) - // I'm not sure it is even possible anywhere else, but just to be safe... - if (cl.type == CLOUD_INK && player_in_branch(BRANCH_SHOALS)) - return; - if (you.see_cell(gc)) { const coord_def ep = grid2show(gc); diff --git a/crawl-ref/source/tileweb.cc b/crawl-ref/source/tileweb.cc index b6f282b49aab..04ab9a72336f 100644 --- a/crawl-ref/source/tileweb.cc +++ b/crawl-ref/source/tileweb.cc @@ -75,6 +75,8 @@ TilesFramework::TilesFramework() : _send_lock(false), m_last_ui_state(UI_INIT), m_view_loaded(false), + m_current_view(coord_def(GXM, GYM)), + m_next_view(coord_def(GXM, GYM)), m_next_view_tl(0, 0), m_next_view_br(-1, -1), m_current_flash_colour(BLACK), @@ -85,8 +87,8 @@ TilesFramework::TilesFramework() : { screen_cell_t default_cell; default_cell.tile.bg = TILE_FLAG_UNSEEN; - m_next_view.init(default_cell); - m_current_view.init(default_cell); + m_current_view.fill(default_cell); + m_next_view.fill(default_cell); } TilesFramework::~TilesFramework() @@ -1594,7 +1596,7 @@ void TilesFramework::_send_map(bool force_full) draw_cell(cell, gc, false, m_current_flash_colour); cell->tile.flv = env.tile_flv(gc); - pack_cell_overlays(gc, &(cell->tile)); + pack_cell_overlays(gc, m_next_view); } mark_clean(gc); @@ -1759,7 +1761,7 @@ void TilesFramework::load_dungeon(const crawl_view_buffer &vbuf, *cell = ((const screen_cell_t *) vbuf)[x + vbuf.size().x * y]; cell->tile.flv = env.tile_flv(grid); - pack_cell_overlays(grid, &(cell->tile)); + pack_cell_overlays(grid, m_next_view); mark_clean(grid); // Remove redraw flag mark_dirty(grid); diff --git a/crawl-ref/source/tileweb.h b/crawl-ref/source/tileweb.h index 80cbd04d1716..a6701f583988 100644 --- a/crawl-ref/source/tileweb.h +++ b/crawl-ref/source/tileweb.h @@ -259,10 +259,10 @@ class TilesFramework bool m_view_loaded; bool m_player_on_level; - FixedArray m_current_view; + crawl_view_buffer m_current_view; coord_def m_current_gc; - FixedArray m_next_view; + crawl_view_buffer m_next_view; coord_def m_next_gc; coord_def m_next_view_tl; coord_def m_next_view_br; diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index 3c1c47909354..e8ce87876e7b 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -1501,6 +1501,10 @@ void draw_cell(screen_cell_t *cell, const coord_def &gc, else _draw_outside_los(cell, gc, ep); // in los bounds but not visible +#ifdef USE_TILE + cell->tile.map_knowledge = map_bounds(gc) ? env.map_knowledge(gc) : map_cell(); +#endif + cell->flash_colour = BLACK; // Don't hide important information by recolouring monsters. diff --git a/crawl-ref/source/viewgeom.cc b/crawl-ref/source/viewgeom.cc index 729bffc3d998..4c9866501fb7 100644 --- a/crawl-ref/source/viewgeom.cc +++ b/crawl-ref/source/viewgeom.cc @@ -265,6 +265,12 @@ const crawl_view_buffer &crawl_view_buffer::operator = (const crawl_view_buffer return *this; } +void crawl_view_buffer::fill(const screen_cell_t& value) +{ + for (int i = 0; i < m_size.x * m_size.y; ++i) + m_buffer[i] = value; +} + void crawl_view_buffer::clear() { delete [] m_buffer; diff --git a/crawl-ref/source/viewgeom.h b/crawl-ref/source/viewgeom.h index bf731161ce20..2fb0ad854eab 100644 --- a/crawl-ref/source/viewgeom.h +++ b/crawl-ref/source/viewgeom.h @@ -27,6 +27,13 @@ class crawl_view_buffer operator const screen_cell_t * () const { return m_buffer; } const crawl_view_buffer & operator = (const crawl_view_buffer &rhs); + template + screen_cell_t& operator () (const Indexer &i) + { + return m_buffer[i.y*m_size.x + i.x]; + } + + void fill(const screen_cell_t& value); void clear(); void draw(); private: From 4db8f8041d9c8e485484cfc12d74a479d8a39667 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Fri, 6 Sep 2019 14:46:48 +0800 Subject: [PATCH 601/864] Simplify wave overlay packing code --- crawl-ref/source/tilecell.cc | 55 +++++++++++------------------------- 1 file changed, 17 insertions(+), 38 deletions(-) diff --git a/crawl-ref/source/tilecell.cc b/crawl-ref/source/tilecell.cc index fc7411fd2fa8..44dabb594555 100644 --- a/crawl-ref/source/tilecell.cc +++ b/crawl-ref/source/tilecell.cc @@ -2,6 +2,7 @@ #ifdef USE_TILE #include "tilecell.h" +#include "colour.h" #include "coord.h" #include "coordit.h" #include "terrain.h" @@ -370,6 +371,16 @@ static bool _is_seen_shallow(coord_def gc, crawl_view_buffer& vbuf) return feat == DNGN_SHALLOW_WATER || _feat_is_mangrove(feat); } +static tileidx_t _base_wave_tile(colour_t colour) +{ + switch (colour) + { + case BLACK: return TILE_DNGN_WAVE_N; + case GREEN: return TILE_MURKY_WAVE_N; + default: die("no %s deep water wave tiles", colour_to_str(colour).c_str()); + } +} + static void _pack_default_waves(const coord_def &gc, crawl_view_buffer& vbuf) { auto& cell = vbuf(gc).tile; @@ -385,45 +396,13 @@ static void _pack_default_waves(const coord_def &gc, crawl_view_buffer& vbuf) if (!feat_is_water(feat) && !feat_is_lava(feat)) return; - if (feat == DNGN_DEEP_WATER && colour) - { - if (_is_seen_shallow(coord_def(gc.x, gc.y - 1), vbuf)) - _add_overlay(TILE_DNGN_WAVE_N, cell); - if (_is_seen_shallow(coord_def(gc.x + 1, gc.y - 1), vbuf)) - _add_overlay(TILE_DNGN_WAVE_NE, cell); - if (_is_seen_shallow(coord_def(gc.x + 1, gc.y), vbuf)) - _add_overlay(TILE_DNGN_WAVE_E, cell); - if (_is_seen_shallow(coord_def(gc.x + 1, gc.y + 1), vbuf)) - _add_overlay(TILE_DNGN_WAVE_SE, cell); - if (_is_seen_shallow(coord_def(gc.x, gc.y + 1), vbuf)) - _add_overlay(TILE_DNGN_WAVE_S, cell); - if (_is_seen_shallow(coord_def(gc.x - 1, gc.y + 1), vbuf)) - _add_overlay(TILE_DNGN_WAVE_SW, cell); - if (_is_seen_shallow(coord_def(gc.x - 1, gc.y), vbuf)) - _add_overlay(TILE_DNGN_WAVE_W, cell); - if (_is_seen_shallow(coord_def(gc.x - 1, gc.y - 1), vbuf)) - _add_overlay(TILE_DNGN_WAVE_NW, cell); - } - - // Sewer water - if (feat == DNGN_DEEP_WATER && colour == GREEN) + if (feat == DNGN_DEEP_WATER && (colour == BLACK || colour == GREEN)) { - if (_is_seen_shallow(coord_def(gc.x, gc.y - 1), vbuf)) - _add_overlay(TILE_MURKY_WAVE_N, cell); - if (_is_seen_shallow(coord_def(gc.x + 1, gc.y - 1), vbuf)) - _add_overlay(TILE_MURKY_WAVE_NE, cell); - if (_is_seen_shallow(coord_def(gc.x + 1, gc.y), vbuf)) - _add_overlay(TILE_MURKY_WAVE_E, cell); - if (_is_seen_shallow(coord_def(gc.x + 1, gc.y + 1), vbuf)) - _add_overlay(TILE_MURKY_WAVE_SE, cell); - if (_is_seen_shallow(coord_def(gc.x, gc.y + 1), vbuf)) - _add_overlay(TILE_MURKY_WAVE_S, cell); - if (_is_seen_shallow(coord_def(gc.x - 1, gc.y + 1), vbuf)) - _add_overlay(TILE_MURKY_WAVE_SW, cell); - if (_is_seen_shallow(coord_def(gc.x - 1, gc.y), vbuf)) - _add_overlay(TILE_MURKY_WAVE_W, cell); - if (_is_seen_shallow(coord_def(gc.x - 1, gc.y - 1), vbuf)) - _add_overlay(TILE_MURKY_WAVE_NW, cell); + // +7 and -- reverse the iteration order + int tile = _base_wave_tile(colour) + 7; + for (adjacent_iterator ai(gc); ai; ++ai, --tile) + if (_is_seen_shallow(*ai, vbuf)) + _add_overlay(tile, cell); } bool north = _is_seen_land(coord_def(gc.x, gc.y - 1), vbuf); From f216e904300505c838bcd0ea3f1b0cb64ab8aef4 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Fri, 6 Sep 2019 06:12:11 +0800 Subject: [PATCH 602/864] Fix rest_delay = -1 option --- crawl-ref/source/view.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index e8ce87876e7b..c0efc9e13dfa 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -1418,6 +1418,8 @@ void viewwindow(bool show_updates, bool tiles_only, animation *a) bool run_dont_draw = you.running && Options.travel_delay < 0 && (!you.running.is_explore() || Options.explore_delay < 0); + if (you.running && you.running.is_rest()) + run_dont_draw = Options.rest_delay == -1; if (run_dont_draw || you.asleep()) { From ef970caa618cb9f89bca8ef4e72e7939b08232c1 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Fri, 6 Sep 2019 14:42:16 +0800 Subject: [PATCH 603/864] Always clear tile flavour when destroying walls (kitchen_ace, 12053) It's not clear to me why the tile flavour was only cleared if the terrain had been transformed; in any case, this function is only ever called from destroy_wall(), so this should be safe. --- crawl-ref/source/terrain.cc | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/crawl-ref/source/terrain.cc b/crawl-ref/source/terrain.cc index 0b84466b9ca3..86f394396c7c 100644 --- a/crawl-ref/source/terrain.cc +++ b/crawl-ref/source/terrain.cc @@ -2114,12 +2114,10 @@ static dungeon_feature_type _destroyed_feat_type() static bool _revert_terrain_to_floor(coord_def pos) { dungeon_feature_type newfeat = _destroyed_feat_type(); - bool found_marker = false; for (map_marker *marker : env.markers.get_markers_at(pos)) { if (marker->get_type() == MAT_TERRAIN_CHANGE) { - found_marker = true; map_terrain_change_marker* tmarker = dynamic_cast(marker); @@ -2151,11 +2149,8 @@ static bool _revert_terrain_to_floor(coord_def pos) grd(pos) = newfeat; set_terrain_changed(pos); - if (found_marker) - { - tile_clear_flavour(pos); - tile_init_flavour(pos); - } + tile_clear_flavour(pos); + tile_init_flavour(pos); return true; } From a4a55ebecdff13dc0a209064fb807482278844ce Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 7 Sep 2019 13:40:10 +0800 Subject: [PATCH 604/864] Fix border between mapped and unmapped water tiles The idea here is that wave borders against the edge of LOS should not be added if the adjacent out-of-LOS terrain type is unknown. This is relevant when using magic mapping, which does not reveal the depth of water, showing all water as shallow. This caused deep water on the edge of LOS to incorrectly have wave borders on that edge. --- crawl-ref/source/tilecell.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crawl-ref/source/tilecell.cc b/crawl-ref/source/tilecell.cc index 44dabb594555..89114ed0914a 100644 --- a/crawl-ref/source/tilecell.cc +++ b/crawl-ref/source/tilecell.cc @@ -368,6 +368,9 @@ static bool _is_seen_shallow(coord_def gc, crawl_view_buffer& vbuf) { const auto feat = _safe_feat(gc, vbuf); + if (!vbuf(gc).tile.map_knowledge.seen()) + return false; + return feat == DNGN_SHALLOW_WATER || _feat_is_mangrove(feat); } From ff1bdec7c25336f36fab040193b664fee1490697 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 7 Sep 2019 14:05:01 +0800 Subject: [PATCH 605/864] Fix magic mapping water colour in sewer --- crawl-ref/source/view.cc | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index c0efc9e13dfa..860be2d57eda 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -579,6 +579,13 @@ static const FixedArray& _tile_difficulties(bool random) return cache; } +static colour_t _feat_default_map_colour(dungeon_feature_type feat) +{ + if (player_in_branch(BRANCH_SEWER) && feat_is_water(feat)) + return feat == DNGN_DEEP_WATER ? GREEN : LIGHTGREEN; + return BLACK; +} + // Returns true if it succeeded. bool magic_mapping(int map_radius, int proportion, bool suppress_msg, bool force, bool deterministic, @@ -677,12 +684,16 @@ bool magic_mapping(int map_radius, int proportion, bool suppress_msg, { if (wizard_map) { - knowledge.set_feature(grd(pos), 0, + knowledge.set_feature(feat, _feat_default_map_colour(feat), feat_is_trap(grd(pos)) ? get_trap_type(pos) : TRAP_UNASSIGNED); } else if (!knowledge.feat()) - knowledge.set_feature(magic_map_base_feat(grd(pos))); + { + auto base_feat = magic_map_base_feat(feat); + auto colour = _feat_default_map_colour(base_feat); + knowledge.set_feature(base_feat, colour); + } if (emphasise(pos)) knowledge.flags |= MAP_EMPHASIZE; From de3ff83e2e22833ea537f941102f100877ae75de Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 7 Sep 2019 14:27:14 +0800 Subject: [PATCH 606/864] Remove unused headers --- crawl-ref/source/tiledgnbuf.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/crawl-ref/source/tiledgnbuf.cc b/crawl-ref/source/tiledgnbuf.cc index a7be0803b983..d57992373b80 100644 --- a/crawl-ref/source/tiledgnbuf.cc +++ b/crawl-ref/source/tiledgnbuf.cc @@ -2,8 +2,6 @@ #ifdef USE_TILE_LOCAL #include "tiledgnbuf.h" -#include "env.h" -#include "player.h" #include "tile-flags.h" #include "tiledef-dngn.h" #include "tiledef-icons.h" From 9501b9e7a0087b7cf09d06bf33f35d1313582275 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 7 Sep 2019 17:16:03 +0800 Subject: [PATCH 607/864] Factor out describe_monsters_condensed() helper function --- crawl-ref/source/view.cc | 61 +++++++++++++++++++++++++--------------- crawl-ref/source/view.h | 2 ++ 2 files changed, 40 insertions(+), 23 deletions(-) diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index 860be2d57eda..eb2a266eb882 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -202,7 +202,7 @@ static string _desc_mons_type_map(map types) message += ", "; ++count; } - return make_stringf("%s come into view.", message.c_str()); + return message; } static monster_type _mons_genus_keep_uniques(monster_type mc) @@ -270,7 +270,7 @@ static bool _is_weapon_worth_listing(const item_def *wpn) /// Return a warning for the player about newly-seen monsters, as appropriate. static string _monster_headsup(const vector &monsters, - map &types, + const map &types, bool divine) { string warning_msg = ""; @@ -299,7 +299,7 @@ static string _monster_headsup(const vector &monsters, monname = mon->pronoun(PRONOUN_SUBJECTIVE); else if (mon->type == MONS_DANCING_WEAPON) monname = "There"; - else if (types[mon->type] == 1) + else if (types.at(mon->type) == 1) monname = mon->full_name(DESC_THE); else monname = mon->full_name(DESC_A); @@ -341,7 +341,7 @@ static string _monster_headsup(const vector &monsters, /// Let Ash/Zin warn the player about newly-seen monsters, as appropriate. static void _divine_headsup(const vector &monsters, - map &types) + const map &types) { const string warnings = _monster_headsup(monsters, types, true); if (!warnings.size()) @@ -357,7 +357,7 @@ static void _divine_headsup(const vector &monsters, } static void _secular_headsup(const vector &monsters, - map &types) + const map &types) { const string warnings = _monster_headsup(monsters, types, false); if (!warnings.size()) @@ -365,16 +365,7 @@ static void _secular_headsup(const vector &monsters, mprf(MSGCH_MONSTER_WARNING, "%s", warnings.c_str()); } -/** - * Handle printing "foo comes into view" messages for newly appeared monsters. - * Also let Ash/Zin warn the player about newly-seen monsters, as appropriate. - * - * @param msgs A list of individual 'comes into view' messages; e.g. - * "the goblin comes into view.", "Mara opens the gate." - * @param monsters A list of monsters that just became visible. - */ -static void _handle_comes_into_view(const vector &msgs, - const vector monsters) +static map _count_monster_types(const vector& monsters) { const unsigned int max_msgs = 4; @@ -387,17 +378,41 @@ static void _handle_comes_into_view(const vector &msgs, genera[_mons_genus_keep_uniques(type)]++; } - unsigned int size = monsters.size(); - if (size == 1) + while (types.size() > max_msgs && !genera.empty()) + _genus_factoring(types, genera); + + return types; +} + +/** + * Return a string listing monsters in a human readable form. + * E.g. "a hydra and 2 liches". + * + * @param monsters A list of monsters that just became visible. + */ +string describe_monsters_condensed(const vector& monsters) +{ + return _desc_mons_type_map(_count_monster_types(monsters)); +} + +/** + * Handle printing "foo comes into view" messages for newly appeared monsters. + * Also let Ash/Zin warn the player about newly-seen monsters, as appropriate. + * + * @param msgs A list of individual 'comes into view' messages; e.g. + * "the goblin comes into view.", "Mara opens the gate." + * @param monsters A list of monsters that just became visible. + */ +static void _handle_comes_into_view(const vector &msgs, + const vector monsters) +{ + if (monsters.size() == 1) mprf(MSGCH_MONSTER_WARNING, "%s", msgs[0].c_str()); else - { - while (types.size() > max_msgs && !genera.empty()) - _genus_factoring(types, genera); - mprf(MSGCH_MONSTER_WARNING, "%s", - _desc_mons_type_map(types).c_str()); - } + mprf(MSGCH_MONSTER_WARNING, "%s come into view.", + describe_monsters_condensed(monsters).c_str()); + const auto& types = _count_monster_types(monsters); _divine_headsup(monsters, types); _secular_headsup(monsters, types); } diff --git a/crawl-ref/source/view.h b/crawl-ref/source/view.h index f447b5a68977..2f2d6aa155a3 100644 --- a/crawl-ref/source/view.h +++ b/crawl-ref/source/view.h @@ -13,6 +13,8 @@ bool mon_enemies_around(const monster* mons); void seen_monsters_react(int stealth = player_stealth()); +string describe_monsters_condensed(const vector& monsters); + bool magic_mapping(int map_radius, int proportion, bool suppress_msg, bool force = false, bool deterministic = false, coord_def origin = coord_def(-1, -1)); From fb3efd073d7df51369fcb7dd9449ce625ac4e44d Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 7 Sep 2019 17:19:30 +0800 Subject: [PATCH 608/864] Add all autoexcludes simultaneously This fixes two bugs; autoexclude spam when encountering multiple monsters that require autoexcludes, and autoexplore not showing the correct region of the map before forcing a more prompt. Monsters now no longer force a more prompt if they awaken immediately. This commit also slightly improves maybe_remove_autoexclusion(): the ballistomycete case is already handled in _need_auto_exclude(). --- crawl-ref/source/delay.cc | 1 - crawl-ref/source/exclude.cc | 68 +++++++++++++++-------------------- crawl-ref/source/exclude.h | 3 +- crawl-ref/source/main.cc | 2 ++ crawl-ref/source/mon-behv.cc | 11 ------ crawl-ref/source/mon-death.cc | 4 --- crawl-ref/source/mon-poly.cc | 3 -- crawl-ref/source/state.cc | 1 - 8 files changed, 32 insertions(+), 61 deletions(-) diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc index a6f683c4276e..71926a2761c8 100644 --- a/crawl-ref/source/delay.cc +++ b/crawl-ref/source/delay.cc @@ -1205,7 +1205,6 @@ static inline bool _monster_warning(activity_interrupt ai, text += make_stringf(" (%s)", short_ghost_description(mon).c_str()); } - set_auto_exclude(mon); if (at.context == SC_DOOR) text += " opens the door."; diff --git a/crawl-ref/source/exclude.cc b/crawl-ref/source/exclude.cc index d5e7509b3ac3..94cc6d5a8311 100644 --- a/crawl-ref/source/exclude.cc +++ b/crawl-ref/source/exclude.cc @@ -81,48 +81,40 @@ static int _get_full_exclusion_radius() + (you.species == SP_BARACHI ? 1 : 0); } -// If the monster is in the auto_exclude list, automatically set an -// exclusion. -void set_auto_exclude(const monster* mon) +/** + * Adds auto-exclusions for any monsters in LOS that need them. + */ +void add_auto_excludes() { - if (!is_map_persistent()) - return; - - // Something of a speed hack, but some vaults have a TON of plants. - if (mon->type == MONS_PLANT) + if (!is_map_persistent() || !map_bounds(you.pos())) return; - if (_need_auto_exclude(mon) && !is_exclude_root(mon->pos())) + vector mons; + for (radius_iterator ri(you.pos(), LOS_DEFAULT); ri; ++ri) { - int rad = _get_full_exclusion_radius(); - if (mon->type == MONS_HYPERACTIVE_BALLISTOMYCETE) - rad = 2; - set_exclude(mon->pos(), rad, true); - // FIXME: If this happens for several monsters in the same turn - // (as is possible for some vaults), this could be really - // annoying. (jpeg) - mprf(MSGCH_WARN, - "Marking area around %s as unsafe for travelling.", - mon->name(DESC_THE).c_str()); + monster *mon = monster_at(*ri); + if (!mon) + continue; + // Something of a speed hack, but some vaults have a TON of plants. + if (mon->type == MONS_PLANT) + continue; + if (_need_auto_exclude(mon) && !is_exclude_root(*ri)) + { + int radius = _get_full_exclusion_radius(); + if (mon->type == MONS_HYPERACTIVE_BALLISTOMYCETE) + radius = 2; -#ifdef USE_TILE - viewwindow(); -#endif - learned_something_new(HINT_AUTO_EXCLUSION, mon->pos()); + set_exclude(*ri, radius, true); + mons.emplace_back(mon); + } } -} -// Clear auto exclusion if the monster is killed or wakes up with the -// player in sight. If sleepy is true, stationary monsters are ignored. -void remove_auto_exclude(const monster* mon, bool sleepy) -{ - if (_need_auto_exclude(mon, sleepy)) - { - del_exclude(mon->pos()); -#ifdef USE_TILE - viewwindow(); -#endif - } + if (mons.empty()) + return; + + mprf(MSGCH_WARN, "Marking area around %s as unsafe for travelling.", + describe_monsters_condensed(mons).c_str()); + learned_something_new(HINT_AUTO_EXCLUSION); } travel_exclude::travel_exclude(const coord_def &p, int r, @@ -556,10 +548,8 @@ void maybe_remove_autoexclusion(const coord_def &p) string desc = exc->desc; bool cloudy_exc = ends_with(desc, "cloud"); if ((!m || !you.can_see(*m) - || m->attitude != ATT_HOSTILE - && m->type != MONS_HYPERACTIVE_BALLISTOMYCETE - || strcmp(mons_type_name(m->type, DESC_PLAIN).c_str(), - exc->desc.c_str()) != 0) + || !_need_auto_exclude(m) + || mons_type_name(m->type, DESC_PLAIN) != desc) && !cloudy_exc) { del_exclude(p); diff --git a/crawl-ref/source/exclude.h b/crawl-ref/source/exclude.h index f292d63fa812..915351af06b2 100644 --- a/crawl-ref/source/exclude.h +++ b/crawl-ref/source/exclude.h @@ -2,8 +2,7 @@ #include "los-def.h" -void set_auto_exclude(const monster* mon); -void remove_auto_exclude(const monster* mon, bool sleepy = false); +void add_auto_excludes(); void init_exclusion_los(); void update_exclusion_los(vector changed); diff --git a/crawl-ref/source/main.cc b/crawl-ref/source/main.cc index f63a284a0302..5fbc87e5414e 100644 --- a/crawl-ref/source/main.cc +++ b/crawl-ref/source/main.cc @@ -2289,6 +2289,8 @@ void world_reacts() wu_jian_end_of_turn_effects(); + add_auto_excludes(); + viewwindow(); if (you.cannot_act() && any_messages() diff --git a/crawl-ref/source/mon-behv.cc b/crawl-ref/source/mon-behv.cc index 8c92ad07b6e2..8f15108e0952 100644 --- a/crawl-ref/source/mon-behv.cc +++ b/crawl-ref/source/mon-behv.cc @@ -1055,13 +1055,8 @@ void behaviour_event(monster* mon, mon_event_type event, const actor *src, #endif // Assumes disturbed by noise... if (mon->asleep()) - { mon->behaviour = BEH_WANDER; - if (you.can_see(*mon)) - remove_auto_exclude(mon, true); - } - // A bit of code to make Projected Noise actually do // something again. Basically, dumb monsters and // monsters who aren't otherwise occupied will at @@ -1105,9 +1100,6 @@ void behaviour_event(monster* mon, mon_event_type event, const actor *src, mon->foe = src_idx; - if (mon->asleep() && you.can_see(*mon)) - remove_auto_exclude(mon, true); - // If the monster can't reach its target and can't attack it // either, retreat. try_pathfind(mon); @@ -1186,9 +1178,6 @@ void behaviour_event(monster* mon, mon_event_type event, const actor *src, break; } - if (mon->asleep() && you.can_see(*mon)) - remove_auto_exclude(mon, true); - // Will alert monster to and turn them // against them, unless they have a current foe. // It won't turn friends hostile either. diff --git a/crawl-ref/source/mon-death.cc b/crawl-ref/source/mon-death.cc index b45bc725eed8..697de541d053 100644 --- a/crawl-ref/source/mon-death.cc +++ b/crawl-ref/source/mon-death.cc @@ -1911,10 +1911,6 @@ item_def* monster_die(monster& mons, killer_type killer, // Uniques leave notes and milestones, so this information is already leaked. remove_unique_annotation(&mons); - // Clear auto exclusion now the monster is killed - if we know about it. - if (you.see_cell(mons.pos()) || wizard || mons_is_unique(mons.type)) - remove_auto_exclude(&mons); - int duration = 0; const bool summoned = mons.is_summoned(&duration); const int monster_killed = mons.mindex(); diff --git a/crawl-ref/source/mon-poly.cc b/crawl-ref/source/mon-poly.cc index 5e0cef9941ca..c019f1629896 100644 --- a/crawl-ref/source/mon-poly.cc +++ b/crawl-ref/source/mon-poly.cc @@ -624,9 +624,6 @@ void slimify_monster(monster* mon) void seen_monster(monster* mons) { - // If the monster is in the auto_exclude list, automatically - // set an exclusion. - set_auto_exclude(mons); set_unique_annotation(mons); // id equipment (do this every time we see them, it may have changed) diff --git a/crawl-ref/source/state.cc b/crawl-ref/source/state.cc index 414db6e0f35c..211ee0181b35 100644 --- a/crawl-ref/source/state.cc +++ b/crawl-ref/source/state.cc @@ -236,7 +236,6 @@ bool interrupt_cmd_repeat(activity_interrupt ai, if (at.context == SC_NEWLY_SEEN) { monster_info mi(mon); - set_auto_exclude(mon); mprf(MSGCH_WARN, "%s comes into view.", get_monster_equipment_desc(mi, DESC_WEAPON).c_str()); From e11a5d91ad76468178e2858b6d67ac70b61316b2 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 9 Sep 2019 23:10:25 +0800 Subject: [PATCH 609/864] Fix headsup crashloop with >4 monster types (nikopol, 12059) Headsups needed access to the number of monsters of each type to determine the appropriate grammar, but used a map of pre-condensed monster types. --- crawl-ref/source/view.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index eb2a266eb882..39f22b7c760c 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -365,10 +365,9 @@ static void _secular_headsup(const vector &monsters, mprf(MSGCH_MONSTER_WARNING, "%s", warnings.c_str()); } -static map _count_monster_types(const vector& monsters) +static map _count_monster_types(const vector& monsters, + const unsigned int max_types = UINT_MAX) { - const unsigned int max_msgs = 4; - map types; map genera; // This is the plural for genus! for (const monster *mon : monsters) @@ -378,7 +377,7 @@ static map _count_monster_types(const vector& monst genera[_mons_genus_keep_uniques(type)]++; } - while (types.size() > max_msgs && !genera.empty()) + while (types.size() > max_types && !genera.empty()) _genus_factoring(types, genera); return types; @@ -392,7 +391,7 @@ static map _count_monster_types(const vector& monst */ string describe_monsters_condensed(const vector& monsters) { - return _desc_mons_type_map(_count_monster_types(monsters)); + return _desc_mons_type_map(_count_monster_types(monsters), 4); } /** From 1ff6aac338ce2360cd713f78e2967fa91b83fe2e Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 9 Sep 2019 23:18:22 +0800 Subject: [PATCH 610/864] Fix bad comma --- crawl-ref/source/view.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index 39f22b7c760c..76272b19ee5c 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -391,7 +391,7 @@ static map _count_monster_types(const vector& monst */ string describe_monsters_condensed(const vector& monsters) { - return _desc_mons_type_map(_count_monster_types(monsters), 4); + return _desc_mons_type_map(_count_monster_types(monsters, 4)); } /** From eaf2f253700b42110b99f06bbde2794d429b984e Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 11 Sep 2019 20:06:02 -0400 Subject: [PATCH 611/864] Limit repeats via 0 somewhat for online play This implements two changes for DGAMELAUNCH builds: * it disallows using CMD_REST at all with 0. (If someone comes up with an actual use-case for this I can reconsider.) * After 100 repeats, it throttles repeats by sleeping for 0.5 seconds. This (at least on my local device) brings cpu use back to what normal play would be like. An alternative would be to disable this altogether, but I prefer the throttling approach as it keeps the features more similar between online and offline. --- crawl-ref/source/main.cc | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/main.cc b/crawl-ref/source/main.cc index 5fbc87e5414e..4f15747b46ab 100644 --- a/crawl-ref/source/main.cc +++ b/crawl-ref/source/main.cc @@ -18,6 +18,9 @@ #include // pair #include #include +#ifdef DGAMELAUNCH +# include +#endif #ifndef TARGET_OS_WINDOWS # ifndef __ANDROID__ @@ -763,6 +766,7 @@ static bool _cmd_is_repeatable(command_type cmd, bool is_again = false) return false; // Multi-turn commands + case CMD_REST: case CMD_PICKUP: case CMD_DROP: case CMD_DROP_LAST: @@ -838,7 +842,6 @@ static bool _cmd_is_repeatable(command_type cmd, bool is_again = false) return _cmd_is_repeatable(crawl_state.prev_cmd, true); - case CMD_REST: case CMD_WAIT: case CMD_SAFE_WAIT: case CMD_SAFE_MOVE_LEFT: @@ -2723,6 +2726,12 @@ static void _do_cmd_repeat() for (; i < count && crawl_state.is_repeating_cmd(); ++i) { last_repeat_turn = you.num_turns; +#ifdef DGAMELAUNCH + if (i == 100) + mpr("Throttling repeat for the sake of the server..."); + if (i >= 100) + usleep(500000); +#endif _run_input_with_keys(repeat_keys); _check_cmd_repeat(last_repeat_turn); } From 751f86b5a9bea3df7cec7a0b06b7ec315bff43e0 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Fri, 13 Sep 2019 01:40:00 +0800 Subject: [PATCH 612/864] Fix webtiles rendering using outdated map_knowledge (Artagas, 12064) --- crawl-ref/source/tileweb.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/crawl-ref/source/tileweb.cc b/crawl-ref/source/tileweb.cc index 04ab9a72336f..1e71f7ce0fec 100644 --- a/crawl-ref/source/tileweb.cc +++ b/crawl-ref/source/tileweb.cc @@ -1744,6 +1744,16 @@ void TilesFramework::load_dungeon(const crawl_view_buffer &vbuf, mark_for_redraw(coord_def(x, y)); } + // re-cache the map knowledge for the whole map, not just the updated portion + // fixes render bugs for out-of-LOS when transitioning levels in shoals/slime + for (int y = 0; y < GYM; y++) + for (int x = 0; x < GXM; x++) + { + const coord_def gc(x, y); + screen_cell_t *cell = &m_next_view(gc); + cell->tile.map_knowledge = map_bounds(gc) ? env.map_knowledge(gc) : map_cell(); + } + m_next_view_tl = view2grid(coord_def(1, 1)); m_next_view_br = view2grid(crawl_view.viewsz); From e2a249a6fdac5ba7cd3c2106dace8c835fad38f3 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 12 Sep 2019 22:24:59 -0400 Subject: [PATCH 613/864] Remove throttling notification It's crashing for ., not sure why. Remove for now. --- crawl-ref/source/main.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/crawl-ref/source/main.cc b/crawl-ref/source/main.cc index 4f15747b46ab..a28b99cf0f8f 100644 --- a/crawl-ref/source/main.cc +++ b/crawl-ref/source/main.cc @@ -2727,8 +2727,6 @@ static void _do_cmd_repeat() { last_repeat_turn = you.num_turns; #ifdef DGAMELAUNCH - if (i == 100) - mpr("Throttling repeat for the sake of the server..."); if (i >= 100) usleep(500000); #endif From 92e081b058a4e3b3ee9274d88762b2f2d5f4e38b Mon Sep 17 00:00:00 2001 From: Umer Shaikh Date: Mon, 9 Sep 2019 19:15:51 -0500 Subject: [PATCH 614/864] Change gauntlet teleportation message (bugfix) On entering the gauntlet the current message misleadingly suggests no one can teleport, but the restriction is on the player only. --- crawl-ref/source/stairs.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/stairs.cc b/crawl-ref/source/stairs.cc index 22fe69f8b6b1..af59784983e6 100644 --- a/crawl-ref/source/stairs.cc +++ b/crawl-ref/source/stairs.cc @@ -414,7 +414,7 @@ static void _gauntlet_effect() if (you.species == SP_FORMICID) return; - mprf(MSGCH_WARN, "The nature of this place prevents teleportation."); + mprf(MSGCH_WARN, "The nature of this place prevents you from teleporting."); if (you.has_mutation(MUT_TELEPORT, true) || you.wearing(EQ_RINGS, RING_TELEPORTATION, true) From e4662a2d141caf7e06b714447d6b4f3d21172260 Mon Sep 17 00:00:00 2001 From: theJollySin Date: Sun, 8 Sep 2019 16:01:13 -0400 Subject: [PATCH 615/864] #1125 spellbooks are no longer 'r'ead --- crawl-ref/docs/crawl_manual.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/docs/crawl_manual.rst b/crawl-ref/docs/crawl_manual.rst index 52d8ac756873..2821be332a6d 100644 --- a/crawl-ref/docs/crawl_manual.rst +++ b/crawl-ref/docs/crawl_manual.rst @@ -667,7 +667,7 @@ adventures, how they are displayed, and what commands there are to use them: = rings (use 'P'ut on and 'R'emove) " amulets (use 'P'ut on and 'R'emove) \| staves (use 'w'ield) -: spellbooks (use 'r'ead and 'M'emorise and 'z'ap) +: spellbooks (use 'M'emorise and 'z'ap) } miscellaneous (use 'V' for evoking from the inventory) $ gold (use 'g' to pick up) ======= ============= ================================================ @@ -2550,7 +2550,7 @@ e synonymous to y. r - Read a scroll or book. + Read a scroll. M Memorise a spell from a book. From b7544fd237a2ed3719f252de216f024b95136a84 Mon Sep 17 00:00:00 2001 From: Nikolai Lavsky <3328424+nlavsky@users.noreply.github.com> Date: Thu, 15 Aug 2019 15:33:13 +0300 Subject: [PATCH 616/864] Upgrade Wyrmbane's tile according to its enchantment As a followup to 1cd5daa3, this commit adds code to upgrade Wyrmbane's tile as the lance grows more powerful. --- crawl-ref/source/rltiles/dc-item.txt | 5 +++++ crawl-ref/source/tilepick.cc | 18 +++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/rltiles/dc-item.txt b/crawl-ref/source/rltiles/dc-item.txt index 01004694e31c..c48d333d6320 100644 --- a/crawl-ref/source/rltiles/dc-item.txt +++ b/crawl-ref/source/rltiles/dc-item.txt @@ -14,6 +14,11 @@ ##### Artefacts (fixed and unrandart) %include dc-unrand.txt +urand_wyrmbane1 UNRAND_WYRMBANE1 +urand_wyrmbane2 UNRAND_WYRMBANE2 +urand_wyrmbane3 UNRAND_WYRMBANE3 +urand_wyrmbane4 UNRAND_WYRMBANE4 + #####NORMAL %sdir item/weapon %rim 0 diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc index 38ebe76c397e..c5ca6a732c6f 100644 --- a/crawl-ref/source/tilepick.cc +++ b/crawl-ref/source/tilepick.cc @@ -2073,6 +2073,20 @@ static tileidx_t _tileidx_unrand_artefact(int idx) return tile ? tile : TILE_TODO; } +static tileidx_t _tileidx_wyrmbane(int plus) +{ + if (plus < 10) + return TILE_UNRAND_WYRMBANE; + else if (plus < 12) + return TILE_UNRAND_WYRMBANE1; + else if (plus < 15) + return TILE_UNRAND_WYRMBANE2; + else if (plus < 18) + return TILE_UNRAND_WYRMBANE3; + else + return TILE_UNRAND_WYRMBANE4; +} + static tileidx_t _tileidx_weapon_base(const item_def &item) { switch (item.sub_type) @@ -2574,7 +2588,9 @@ tileidx_t tileidx_item(const item_def &item) switch (clas) { case OBJ_WEAPONS: - if (is_unrandom_artefact(item) && !is_randapp_artefact(item)) + if (is_unrandom_artefact(item, UNRAND_WYRMBANE)) + return _tileidx_wyrmbane(item.plus); + else if (is_unrandom_artefact(item) && !is_randapp_artefact(item)) return _tileidx_unrand_artefact(find_unrandart_index(item)); else return _tileidx_weapon(item); From 15dcb325b99e2be13ca66fda25a325415f1cb637 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Wed, 18 Sep 2019 21:25:18 +0800 Subject: [PATCH 617/864] Fix UI cutoffs not being cleared properly (vt, 12061) UI cutoffs prevent any any UI layers with index <= the cutoff index from being displayed. If there's no cutoff, the cutoff index should be -1; the old value of 0 was causing the lowest UI layer to not be unhidden. --- crawl-ref/source/tileweb.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/tileweb.cc b/crawl-ref/source/tileweb.cc index 1e71f7ce0fec..dbd6bd24e706 100644 --- a/crawl-ref/source/tileweb.cc +++ b/crawl-ref/source/tileweb.cc @@ -710,7 +710,7 @@ void TilesFramework::push_ui_cutoff() void TilesFramework::pop_ui_cutoff() { m_ui_cutoff_stack.pop_back(); - int cutoff = m_ui_cutoff_stack.empty() ? 0 : m_ui_cutoff_stack.back(); + int cutoff = m_ui_cutoff_stack.empty() ? -1 : m_ui_cutoff_stack.back(); send_message("{\"msg\":\"ui_cutoff\",\"cutoff\":%d}", cutoff); } From f19a5e4d30c2a2af871936e9ab170447c67669bf Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sun, 15 Sep 2019 01:11:52 +0800 Subject: [PATCH 618/864] Tidy up tilesdl font members --- crawl-ref/source/tilesdl.cc | 37 ++++++++++++++----------------------- crawl-ref/source/tilesdl.h | 13 +++++++------ 2 files changed, 21 insertions(+), 29 deletions(-) diff --git a/crawl-ref/source/tilesdl.cc b/crawl-ref/source/tilesdl.cc index e8da601cb540..592ed8d6779b 100644 --- a/crawl-ref/source/tilesdl.cc +++ b/crawl-ref/source/tilesdl.cc @@ -164,10 +164,6 @@ TilesFramework::TilesFramework() : m_fullscreen(false), m_need_redraw(false), m_active_layer(LAYER_CRT), - m_crt_font(-1), - m_msg_font(-1), - m_tip_font(-1), - m_lbl_font(-1), m_mouse(-1, -1), m_last_tick_moved(0), m_last_tick_redraw(0) @@ -181,8 +177,7 @@ TilesFramework::~TilesFramework() bool TilesFramework::fonts_initialized() { // TODO should in principle check the m_fonts vector as well - return !(m_crt_font == -1 || m_msg_font == -1 - || m_tip_font == -1 || m_lbl_font == -1); + return m_crt_font && m_msg_font && m_stat_font && m_tip_font && m_lbl_font; } static void _init_consoles() @@ -288,7 +283,7 @@ void TilesFramework::shutdown() void TilesFramework::draw_doll_edit() { - DollEditRegion reg(m_image, m_fonts[m_msg_font].font); + DollEditRegion reg(m_image, m_msg_font); reg.run(); } @@ -398,20 +393,18 @@ bool TilesFramework::initialise() Options.tile_font_crt_size, true); m_msg_font = load_font(Options.tile_font_msg_file.c_str(), Options.tile_font_msg_size, true); - int stat_font = load_font(Options.tile_font_stat_file.c_str(), + m_stat_font = load_font(Options.tile_font_stat_file.c_str(), Options.tile_font_stat_size, true); m_tip_font = load_font(Options.tile_font_tip_file.c_str(), Options.tile_font_tip_size, true); m_lbl_font = load_font(Options.tile_font_lbl_file.c_str(), Options.tile_font_lbl_size, true); - if (!fonts_initialized() || stat_font == -1) + if (!fonts_initialized()) return false; - if (tiles.is_using_small_layout()) - m_init = TileRegionInit(m_image, m_fonts[m_crt_font].font, TILE_X, TILE_Y); - else - m_init = TileRegionInit(m_image, m_fonts[m_lbl_font].font, TILE_X, TILE_Y); + const auto font = tiles.is_using_small_layout() ? m_crt_font : m_lbl_font; + m_init = TileRegionInit(m_image, font, TILE_X, TILE_Y); m_region_tile = new DungeonRegion(m_init); m_region_tab = new TabbedRegion(m_init); m_region_inv = new InventoryRegion(m_init); @@ -458,10 +451,9 @@ bool TilesFramework::initialise() m_region_tab->activate_tab(TAB_ITEM); #endif - m_region_msg = new MessageRegion(m_fonts[m_msg_font].font); - m_region_stat = new StatRegion(m_fonts[stat_font].font); - m_fonts[stat_font].font->char_width(); - m_region_crt = new CRTRegion(m_fonts[m_crt_font].font); + m_region_msg = new MessageRegion(m_msg_font); + m_region_stat = new StatRegion(m_stat_font); + m_region_crt = new CRTRegion(m_crt_font); m_layers[LAYER_NORMAL].m_regions.push_back(m_region_tile); m_layers[LAYER_NORMAL].m_regions.push_back(m_region_msg); @@ -484,14 +476,14 @@ void TilesFramework::reconfigure_fonts() finfo.font->configure_font(); } -int TilesFramework::load_font(const char *font_file, int font_size, +FontWrapper* TilesFramework::load_font(const char *font_file, int font_size, bool default_on_fail) { for (unsigned int i = 0; i < m_fonts.size(); i++) { font_info &finfo = m_fonts[i]; if (finfo.name == font_file && finfo.size == font_size) - return i; + return finfo.font; } FontWrapper *font = FontWrapper::create(); @@ -509,7 +501,7 @@ int TilesFramework::load_font(const char *font_file, int font_size, return load_font(MONOSPACED_FONT, 12, false); } else - return -1; + return nullptr; } font_info finfo; @@ -518,7 +510,7 @@ int TilesFramework::load_font(const char *font_file, int font_size, finfo.size = font_size; m_fonts.push_back(finfo); - return m_fonts.size() - 1; + return font; } void TilesFramework::load_dungeon(const crawl_view_buffer &vbuf, const coord_def &gc) @@ -1475,8 +1467,7 @@ void TilesFramework::redraw() const int buffer = 5; const coord_def min_pos = coord_def() + buffer; const coord_def max_pos = m_windowsz - buffer; - FontWrapper *font = m_fonts[m_tip_font].font; - font->render_tooltip(m_mouse.x, m_mouse.y, formatted_string(m_tooltip), + m_tip_font->render_tooltip(m_mouse.x, m_mouse.y, formatted_string(m_tooltip), min_pos, max_pos); } wm->swap_buffers(); diff --git a/crawl-ref/source/tilesdl.h b/crawl-ref/source/tilesdl.h index aea7016972fc..99115c30a71a 100644 --- a/crawl-ref/source/tilesdl.h +++ b/crawl-ref/source/tilesdl.h @@ -147,13 +147,13 @@ class TilesFramework bool is_fullscreen() { return m_fullscreen; } bool fonts_initialized(); - FontWrapper* get_crt_font() { return m_fonts.at(m_crt_font).font; } + FontWrapper* get_crt_font() const { return m_crt_font; } CRTRegion* get_crt() { return m_region_crt; } const ImageManager* get_image_manager() { return m_image; } int to_lines(int num_tiles, int tile_height = TILE_Y); protected: void reconfigure_fonts(); - int load_font(const char *font_file, int font_size, + FontWrapper* load_font(const char *font_file, int font_size, bool default_on_fail); int handle_mouse(MouseEvent &event); @@ -222,10 +222,11 @@ class TilesFramework FontWrapper *font; }; vector m_fonts; - int m_crt_font; - int m_msg_font; - int m_tip_font; - int m_lbl_font; + FontWrapper* m_crt_font = nullptr; + FontWrapper* m_msg_font = nullptr; + FontWrapper* m_stat_font = nullptr; + FontWrapper* m_tip_font = nullptr; + FontWrapper* m_lbl_font = nullptr; int m_tab_margin; int m_stat_col; From 94eeae6f7e1c1bdbcd85be113b6bb43b6f2f2861 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sun, 15 Sep 2019 01:12:16 +0800 Subject: [PATCH 619/864] Add remaining tilesdl font getters --- crawl-ref/source/tilesdl.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crawl-ref/source/tilesdl.h b/crawl-ref/source/tilesdl.h index 99115c30a71a..fa8763d1692e 100644 --- a/crawl-ref/source/tilesdl.h +++ b/crawl-ref/source/tilesdl.h @@ -147,8 +147,15 @@ class TilesFramework bool is_fullscreen() { return m_fullscreen; } bool fonts_initialized(); + FontWrapper* get_crt_font() const { return m_crt_font; } + FontWrapper* get_msg_font() const { return m_msg_font; } + FontWrapper* get_stat_font() const { return m_stat_font; } + FontWrapper* get_tip_font() const { return m_tip_font; } + FontWrapper* get_lbl_font() const { return m_lbl_font; } + CRTRegion* get_crt() { return m_region_crt; } + const ImageManager* get_image_manager() { return m_image; } int to_lines(int num_tiles, int tile_height = TILE_Y); protected: From 3dea98854c5d854a17b8bf967a971791a0a32677 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 16 Sep 2019 17:44:25 +0800 Subject: [PATCH 620/864] Fix tooltips freezing local tiles window The previous implementation added a tooltip timer before blocking for the next SDL event, and removed it before returning. If resize or move events were received, however, the function would return early, and the timer would never be removed and would instead timeout periodically. Subsequent move events would add additional timers, leading to a flood of timeouts clogging up the event loop. This new implementation only ever adds a timer when the mouse is moved, and timers only fire once. remove_timer() is also changed to take an int& for convenience. --- crawl-ref/source/tilesdl.cc | 41 ++++++++------------------- crawl-ref/source/tilesdl.h | 3 +- crawl-ref/source/windowmanager-sdl.cc | 8 ++++-- crawl-ref/source/windowmanager-sdl.h | 2 +- crawl-ref/source/windowmanager.h | 2 +- 5 files changed, 22 insertions(+), 34 deletions(-) diff --git a/crawl-ref/source/tilesdl.cc b/crawl-ref/source/tilesdl.cc index 592ed8d6779b..e7ae21d08274 100644 --- a/crawl-ref/source/tilesdl.cc +++ b/crawl-ref/source/tilesdl.cc @@ -165,7 +165,6 @@ TilesFramework::TilesFramework() : m_need_redraw(false), m_active_layer(LAYER_CRT), m_mouse(-1, -1), - m_last_tick_moved(0), m_last_tick_redraw(0) { } @@ -617,8 +616,7 @@ static unsigned int _timer_callback(unsigned int ticks, void *param) // force the event loop to break wm->raise_custom_event(); - unsigned int res = Options.tile_tooltip_ms; - return res; + return 0; } int TilesFramework::getch_ck() @@ -635,8 +633,6 @@ int TilesFramework::getch_ck() const unsigned int ticks_per_screen_redraw = Options.tile_update_rate; - unsigned int res = Options.tile_tooltip_ms; - unsigned int timer_id = wm->set_timer(res, &_timer_callback); m_tooltip.clear(); m_region_msg->alt_text().clear(); @@ -707,11 +703,13 @@ int TilesFramework::getch_ck() // If you hit a key, disable tooltips until the mouse // is moved again. - m_last_tick_moved = UINT_MAX; + m_show_tooltip = false; + wm->remove_timer(m_tooltip_timer_id); break; case WME_KEYUP: - m_last_tick_moved = UINT_MAX; + m_show_tooltip = false; + wm->remove_timer(m_tooltip_timer_id); break; case WME_MOUSEMOTION: @@ -727,11 +725,6 @@ int TilesFramework::getch_ck() continue; // Record mouse pos for tooltip timer - if (m_mouse.x != (int)event.mouse_event.px - || m_mouse.y != (int)event.mouse_event.py) - { - m_last_tick_moved = ticks; - } m_mouse.x = event.mouse_event.px; m_mouse.y = event.mouse_event.py; @@ -768,21 +761,16 @@ int TilesFramework::getch_ck() prev_msg_alt_text = m_region_msg->alt_text(); set_need_redraw(); } + + wm->remove_timer(m_tooltip_timer_id); + m_tooltip_timer_id = wm->set_timer(Options.tile_tooltip_ms, &_timer_callback); + m_show_tooltip = false; } break; case WME_MOUSEBUTTONUP: - { - key = handle_mouse(event.mouse_event); - m_last_tick_moved = UINT_MAX; - } - break; - case WME_MOUSEBUTTONDOWN: - { - key = handle_mouse(event.mouse_event); - m_last_tick_moved = UINT_MAX; - } + key = handle_mouse(event.mouse_event); break; case WME_QUIT: @@ -812,17 +800,14 @@ int TilesFramework::getch_ck() case WME_CUSTOMEVENT: default: // This is only used to refresh the tooltip. + m_show_tooltip = true; break; } } if (!mouse_target_mode) { - const bool timeout = (ticks > m_last_tick_moved - && (ticks - m_last_tick_moved - > (unsigned int)Options.tile_tooltip_ms)); - - if (timeout) + if (m_show_tooltip) { tiles.clear_text_tags(TAG_CELL_DESC); if (Options.tile_tooltip_ms > 0 && m_tooltip.empty()) @@ -860,8 +845,6 @@ int TilesFramework::getch_ck() // We got some input, so we'll probably have to redraw something. set_need_redraw(); - wm->remove_timer(timer_id); - return key; } diff --git a/crawl-ref/source/tilesdl.h b/crawl-ref/source/tilesdl.h index fa8763d1692e..aee4a293dadd 100644 --- a/crawl-ref/source/tilesdl.h +++ b/crawl-ref/source/tilesdl.h @@ -253,10 +253,11 @@ class TilesFramework // Mouse state. coord_def m_mouse; - unsigned int m_last_tick_moved; unsigned int m_last_tick_redraw; string m_tooltip; + bool m_show_tooltip = false; + unsigned int m_tooltip_timer_id = 0; int m_screen_width; int m_screen_height; diff --git a/crawl-ref/source/windowmanager-sdl.cc b/crawl-ref/source/windowmanager-sdl.cc index 3045e74d2810..dcdc0d90ecf6 100644 --- a/crawl-ref/source/windowmanager-sdl.cc +++ b/crawl-ref/source/windowmanager-sdl.cc @@ -934,9 +934,13 @@ unsigned int SDLWrapper::set_timer(unsigned int interval, return SDL_AddTimer(interval, callback, nullptr); } -void SDLWrapper::remove_timer(unsigned int timer_id) +void SDLWrapper::remove_timer(unsigned int& timer_id) { - SDL_RemoveTimer(timer_id); + if (timer_id) + { + SDL_RemoveTimer(timer_id); + timer_id = 0; + } } int SDLWrapper::raise_custom_event() diff --git a/crawl-ref/source/windowmanager-sdl.h b/crawl-ref/source/windowmanager-sdl.h index 21fe18dc2f51..2da07c5b1076 100644 --- a/crawl-ref/source/windowmanager-sdl.h +++ b/crawl-ref/source/windowmanager-sdl.h @@ -38,7 +38,7 @@ class SDLWrapper : public WindowManager // System time functions virtual unsigned int set_timer(unsigned int interval, wm_timer_callback callback) override; - virtual void remove_timer(unsigned int timer_id) override; + virtual void remove_timer(unsigned int& timer_id) override; virtual unsigned int get_ticks() const override; virtual void delay(unsigned int ms) override; diff --git a/crawl-ref/source/windowmanager.h b/crawl-ref/source/windowmanager.h index 1af2b78dcccf..ddc1ecb959c6 100644 --- a/crawl-ref/source/windowmanager.h +++ b/crawl-ref/source/windowmanager.h @@ -160,7 +160,7 @@ class WindowManager // System time functions virtual unsigned int set_timer(unsigned int interval, wm_timer_callback callback) = 0; - virtual void remove_timer(unsigned int timer_id) = 0; + virtual void remove_timer(unsigned int& timer_id) = 0; virtual unsigned int get_ticks() const = 0; virtual void delay(unsigned int ms) = 0; From e6ffb7a55fa16aead7a29c41ff2ef3907796dba9 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 16 Sep 2019 18:32:46 +0800 Subject: [PATCH 621/864] Fix menu items being unnecessarily ellipsized The menu already ellipsizes menu items as needed based on screen size. --- crawl-ref/source/invent.cc | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/crawl-ref/source/invent.cc b/crawl-ref/source/invent.cc index 5fccbd413b00..1d2cc7f3e1dc 100644 --- a/crawl-ref/source/invent.cc +++ b/crawl-ref/source/invent.cc @@ -226,12 +226,7 @@ string InvEntry::get_text(bool need_cursor) const tstr << "(" << glyph_to_tagstr(get_item_glyph(*item)) << ")" << " "; tstr << text; - const string str = tstr.str(); - - if (printed_width(str) > get_number_of_cols()) - return chop_tagged_string(str, get_number_of_cols() - 2) + ".."; - else - return str; + return tstr.str(); } void get_class_hotkeys(const int type, vector &glyphs) From 3da5d4e088fbd54146bd7e5ed90dbafaddf0d5f0 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 16 Sep 2019 18:34:13 +0800 Subject: [PATCH 622/864] Allow querying current scissor without UI layout Widgets may query the current scissor region to reduce render calls, e.g. by not rendering children or other elements that are not visible. During a regular layout and render cycle, the UI framework pushes a scissor region of the entire screen, so this works fine. When doing ad-hoc rendering (while we transition to full use of the UI framework), this is not the case, which caused crashes. --- crawl-ref/source/ui.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 5777dccb9f24..5b51ccb33ca7 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -1658,7 +1658,9 @@ void pop_scissor() i4 get_scissor() { - return scissor_stack.top(); + if (scissor_stack.size() > 0) + return scissor_stack.top(); + return {0, 0, INT_MAX, INT_MAX}; } #ifndef USE_TILE_LOCAL From d29bdeb3b0834b64560ec50f76408d2ee47b17a7 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 16 Sep 2019 18:37:14 +0800 Subject: [PATCH 623/864] Fix layout error for empty ellipsizable text widget m_wrapped_lines being empty caused the size request calculation to yield a natural size (0 lines) smaller than the minimum size (1 line), causing assertion failures. --- crawl-ref/source/ui.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 5b51ccb33ca7..148ad3178dda 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -517,6 +517,8 @@ void Text::wrap_text_to_size(int width, int height) last_line += formatted_string(".."); m_wrapped_lines.resize(height); } + if (m_wrapped_lines.empty()) + m_wrapped_lines.emplace_back(""); #endif } From f0453101f845dcbc30c363a93acc52530a681ec3 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 14 Sep 2019 19:34:42 +0800 Subject: [PATCH 624/864] Remove probably-no-longer-needed kludge The handle_terminal_resize() call in startup.cc (added in e03bc23d4eded) seems to no longer be required, since the code to determine the HUD size based on species (added in the same commit) is no longer present, and thus the HUD should not need to be resized any more. This permits some minor simplification of handle_terminal_resize(). --- crawl-ref/source/libw32c.cc | 2 +- crawl-ref/source/startup.cc | 3 --- crawl-ref/source/view.cc | 5 ++--- crawl-ref/source/view.h | 2 +- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/crawl-ref/source/libw32c.cc b/crawl-ref/source/libw32c.cc index 0818e597e781..f5ff5c5b712f 100644 --- a/crawl-ref/source/libw32c.cc +++ b/crawl-ref/source/libw32c.cc @@ -324,7 +324,7 @@ static void set_w32_screen_size() static void w32_handle_resize_event() { if (crawl_state.waiting_for_command) - handle_terminal_resize(true); + handle_terminal_resize(); else crawl_state.terminal_resized = true; } diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index 8229cc634fde..da6ca0125fb0 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -279,9 +279,6 @@ static void _post_init(bool newc) level_id old_level; old_level.branch = NUM_BRANCHES; - handle_terminal_resize(false); // resize HUD now that we know player - // species and game mode - load_level(you.entering_level ? you.transit_stair : DNGN_STONE_STAIRS_DOWN_I, you.entering_level ? LOAD_ENTER_LEVEL : newc ? LOAD_START_GAME : LOAD_RESTART_GAME, diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index 76272b19ee5c..a2e88336d312 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -1739,7 +1739,7 @@ void reset_show_terrain() //////////////////////////////////////////////////////////////////////////// // Term resize handling (generic). -void handle_terminal_resize(bool redraw) +void handle_terminal_resize() { crawl_state.terminal_resized = false; @@ -1748,6 +1748,5 @@ void handle_terminal_resize(bool redraw) else crawl_view.init_geometry(); - if (redraw) - redraw_screen(); + redraw_screen(); } diff --git a/crawl-ref/source/view.h b/crawl-ref/source/view.h index 2f2d6aa155a3..5d5c9ecbdaac 100644 --- a/crawl-ref/source/view.h +++ b/crawl-ref/source/view.h @@ -80,4 +80,4 @@ void flush_comes_into_view(); void toggle_show_terrain(); void reset_show_terrain(); -void handle_terminal_resize(bool redraw = true); +void handle_terminal_resize(); From 5f7070a834a50dfee9e33e97a7e8b3ce55992beb Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sun, 15 Sep 2019 01:14:58 +0800 Subject: [PATCH 625/864] Add per-text-widget fonts --- crawl-ref/source/ui.cc | 46 +++++++++++++++++++++++++++--------------- crawl-ref/source/ui.h | 5 ++++- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 148ad3178dda..60c6fe8fbe02 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -455,6 +455,13 @@ void Box::_allocate_region() } } +Text::Text() +{ +#ifdef USE_TILE_LOCAL + set_font(tiles.get_crt_font()); +#endif +} + void Text::set_text(const formatted_string &fs) { m_text.clear(); @@ -465,6 +472,15 @@ void Text::set_text(const formatted_string &fs) _queue_allocation(); } +#ifdef USE_TILE_LOCAL +void Text::set_font(FontWrapper *font) +{ + ASSERT(font); + m_font = font; + _queue_allocation(); +} +#endif + void Text::set_highlight_pattern(string pattern, bool line) { hl_pat = pattern; @@ -483,7 +499,7 @@ void Text::wrap_text_to_size(int width, int height) #ifdef USE_TILE_LOCAL if (wrap_text || ellipsize) - m_text_wrapped = tiles.get_crt_font()->split(m_text, width, height); + m_text_wrapped = m_font->split(m_text, width, height); else m_text_wrapped = m_text; @@ -545,7 +561,7 @@ void Text::_render() wrap_text_to_size(m_region[2], m_region[3]); #ifdef USE_TILE_LOCAL - const int dev_line_height = tiles.get_crt_font()->char_height(false); + const int dev_line_height = m_font->char_height(false); const int line_min_pos = display_density.logical_to_device( region[1] - m_region[1]); const int line_max_pos = display_density.logical_to_device( @@ -609,7 +625,6 @@ void Text::_render() size_t lacc = 0; // the start char of the current op relative to region size_t line = 0; // the line we are at relative to the region - FontWrapper *font = tiles.get_crt_font(); bool inside = false; // Iterate over formatted_string op slices, looking for highlight // sequences. Highlight sequences may span multiple op slices, hence @@ -637,13 +652,13 @@ void Text::_render() string line_before_op = full_text.substr(op_line_start, begin_idx + lacc - op_line_start); // pixel positions for the current op - size_t op_x = font->string_width(line_before_op.c_str()); + size_t op_x = m_font->string_width(line_before_op.c_str()); const size_t op_y = - font->string_height(line_before_op.c_str(), false) + m_font->string_height(line_before_op.c_str(), false) - dev_line_height; // positions in device pixels to highlight relative to current op - size_t sx = 0, ex = font->string_width(op.text.c_str()); + size_t sx = 0, ex = m_font->string_width(op.text.c_str()); size_t sy = 0, ey = dev_line_height; bool started = false; // does the highlight start in the current op? @@ -659,16 +674,16 @@ void Text::_render() op_x = 0; // start position is somewhere in the current op const string before = full_text.substr(begin_idx + lacc, start); - sx = font->string_width(before.c_str()); - sy = font->string_height(before.c_str(), false) + sx = m_font->string_width(before.c_str()); + sy = m_font->string_height(before.c_str(), false) - dev_line_height; started = true; } if (end <= oplen) // assume end is unsigned and so >=0 { const string to_end = full_text.substr(begin_idx + lacc, end); - ex = font->string_width(to_end.c_str()); - ey = font->string_height(to_end.c_str(), false); + ex = m_font->string_width(to_end.c_str()); + ey = m_font->string_height(to_end.c_str(), false); ended = true; } @@ -715,7 +730,7 @@ void Text::_render() else { lacc += oplen; - line += font->string_height(op.text.c_str(), false) + line += m_font->string_height(op.text.c_str(), false) - dev_line_height; } } @@ -724,7 +739,7 @@ void Text::_render() // XXX: should be moved into a new function render_formatted_string() // in FTFontWrapper, that, like render_textblock(), would automatically // handle swapping atlas glyphs as necessary. - FontBuffer m_font_buf(tiles.get_crt_font()); + FontBuffer m_font_buf(m_font); m_font_buf.add(slice, m_region[0], m_region[1] + display_density.device_to_logical(dev_line_height * line_off)); m_font_buf.draw(); @@ -790,10 +805,9 @@ void Text::_render() SizeReq Text::_get_preferred_size(Direction dim, int prosp_width) { #ifdef USE_TILE_LOCAL - FontWrapper *font = tiles.get_crt_font(); if (!dim) { - int w = font->string_width(m_text); + int w = m_font->string_width(m_text); // XXX: should be width of '..', unless string itself is shorter than '..' static constexpr int min_ellipsized_width = 0; static constexpr int min_wrapped_width = 0; // XXX: should be width of longest word @@ -802,8 +816,8 @@ SizeReq Text::_get_preferred_size(Direction dim, int prosp_width) else { wrap_text_to_size(prosp_width, 0); - int height = font->string_height(m_text_wrapped); - return { ellipsize ? (int)font->char_height() : height, height }; + int height = m_font->string_height(m_text_wrapped); + return { ellipsize ? (int)m_font->char_height() : height, height }; } #else if (!dim) diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index ba7277bbfd19..9d5f3d313fab 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -354,7 +354,7 @@ class Box : public ContainerVec class Text : public Widget { public: - Text() {} + Text(); Text(string text) : Text() { set_text(formatted_string(text)); @@ -371,6 +371,8 @@ class Text : public Widget set_text(formatted_string(text)); }; + void set_font(FontWrapper *font); + const formatted_string& get_text() { return m_text; }; void set_highlight_pattern(string pattern, bool hl_line = false); @@ -390,6 +392,7 @@ class Text : public Widget vector m_brkpts; formatted_string m_text_wrapped; ShapeBuffer m_hl_buf; + FontWrapper *m_font; #else vector m_wrapped_lines; #endif From 290c21e5aa2d77bef0076a0fcbfb3f053d1365ef Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Thu, 12 Sep 2019 21:32:20 +0800 Subject: [PATCH 626/864] Replace line_reader use with cancellable_get_line --- crawl-ref/source/main.cc | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/crawl-ref/source/main.cc b/crawl-ref/source/main.cc index a28b99cf0f8f..c9329f174a53 100644 --- a/crawl-ref/source/main.cc +++ b/crawl-ref/source/main.cc @@ -2555,16 +2555,10 @@ static void _safe_move_player(coord_def move) static int _get_num_and_char(const char* prompt, char* buf, int buf_len) { if (prompt != nullptr) - mprf(MSGCH_PROMPT, "%s", prompt); - - line_reader reader(buf, buf_len); - - reader.set_keyproc(keyfun_num_and_char); -#ifdef USE_TILE_WEB - reader.set_tag("repeat"); -#endif - - return reader.read_line(true); + msgwin_prompt(prompt); + auto ret = cancellable_get_line(buf, buf_len, nullptr, keyfun_num_and_char, "", "repeat"); + msgwin_reply(buf); + return ret; } static void _cancel_cmd_repeat() From 0d56a851f414ffaff23f73bb3ea24fe8a024fdab Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Thu, 12 Sep 2019 21:15:40 +0800 Subject: [PATCH 627/864] Don't prewrap level builder logs Pre-wrapping to a given screen-width should be avoided in general because the screen can be resized. In addition, the GOTO_CRT region size is not a well-defined concept on local tiles. --- crawl-ref/source/dbg-util.cc | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/crawl-ref/source/dbg-util.cc b/crawl-ref/source/dbg-util.cc index 72f40baa724a..b1cc31279e99 100644 --- a/crawl-ref/source/dbg-util.cc +++ b/crawl-ref/source/dbg-util.cc @@ -134,28 +134,12 @@ void debug_show_builder_logs() mprf("No builder logs are saved for %s.", cur_level.c_str()); return; } - const string &props_text = log_table[cur_level].get_string(); - stringstream st(props_text); - string text; - formatted_string lines; - - while (getline(st, text)) - { - linebreak_string(text, cgetsize(GOTO_CRT).x - 1); - vector parts; - formatted_string::parse_string_to_multiple(text, parts, 80); - for (unsigned int j = 0; j < parts.size(); ++j) - { - if (!lines.empty()) - lines.add_glyph('\n'); - lines += parts[j]; - } - } - - formatted_scroller hist(FS_PREWRAPPED_TEXT); - hist.set_more(); - hist.add_formatted_string(lines, !lines.empty()); - hist.show(); + string props_text = log_table[cur_level].get_string(); + auto log = formatted_string::parse_string(trim_string_right(props_text)); + formatted_scroller log_scroller; + log_scroller.set_more(); + log_scroller.add_formatted_string(log, false); + log_scroller.show(); } string debug_coord_str(const coord_def &pos) From 346d5769329ad77b248813f4eabd8e7ef8410f24 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 19 Sep 2019 20:04:55 -0400 Subject: [PATCH 628/864] Fix some issues with singing sword revealed in arena (p0a) The `get_tension` check is not well-defined without a player, and also isn't used for monster attackers. Also, the singing sword was shouting at the player's location, not the attacker (which caused another crash in arena). --- crawl-ref/source/art-func.h | 10 +++++----- crawl-ref/source/shout.cc | 8 +++++--- crawl-ref/source/shout.h | 2 +- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/crawl-ref/source/art-func.h b/crawl-ref/source/art-func.h index a60ed410a6c2..521119f0eec6 100644 --- a/crawl-ref/source/art-func.h +++ b/crawl-ref/source/art-func.h @@ -371,20 +371,20 @@ static void _SINGING_SWORD_melee_effects(item_def* weapon, actor* attacker, actor* defender, bool mondied, int dam) { - int tension = get_tension(GOD_NO_GOD); int tier; if (attacker->is_player()) - tier = max(1, min(4, 1 + tension / 20)); + tier = max(1, min(4, 1 + get_tension(GOD_NO_GOD) / 20)); // Don't base the sword on player state when the player isn't wielding it. else tier = 1; - dprf(DIAG_COMBAT, "Singing sword tension: %d, tier: %d", tension, tier); - if (silenced(attacker->pos())) tier = 0; + dprf(DIAG_COMBAT, "Singing sword tension: %d, tier: %d", + attacker->is_player() ? get_tension(GOD_NO_GOD) : -1, tier); + // Not as spammy at low tension. Max chance reached at tier 3, allowing // tier 0 to have a high chance so that the sword is likely to express its // unhappiness with being silenced. @@ -398,7 +398,7 @@ static void _SINGING_SWORD_melee_effects(item_def* weapon, actor* attacker, const int loudness[] = {0, 0, 20, 30, 40}; - item_noise(*weapon, msg, loudness[tier]); + item_noise(*weapon, *attacker, msg, loudness[tier]); if (tier < 1) return; // Can't cast when silenced. diff --git a/crawl-ref/source/shout.cc b/crawl-ref/source/shout.cc index 53c0281aa147..938ea77f55c2 100644 --- a/crawl-ref/source/shout.cc +++ b/crawl-ref/source/shout.cc @@ -337,8 +337,10 @@ bool check_awaken(monster* mons, int stealth) return false; } -void item_noise(const item_def &item, string msg, int loudness) +void item_noise(const item_def &item, actor &act, string msg, int loudness) { + // TODO: messaging for cases where act != you. (This doesn't come up right + // now.) if (is_unrandom_artefact(item)) { // "Your Singing Sword" sounds disrespectful @@ -412,7 +414,7 @@ void item_noise(const item_def &item, string msg, int loudness) mprf(channel, "%s", msg.c_str()); if (channel != MSGCH_TALK_VISUAL) - noisy(loudness, you.pos()); + noisy(loudness, act.pos()); } // TODO: Let artefacts besides weapons generate noise. @@ -439,7 +441,7 @@ void noisy_equipment() if (msg.empty()) msg = getSpeakString("noisy weapon"); - item_noise(*weapon, msg, 20); + item_noise(*weapon, you, msg, 20); } // Berserking monsters cannot be ordered around. diff --git a/crawl-ref/source/shout.h b/crawl-ref/source/shout.h index b23ffa09f0d0..8a6e04a8412e 100644 --- a/crawl-ref/source/shout.h +++ b/crawl-ref/source/shout.h @@ -11,7 +11,7 @@ bool fake_noisy(int loudness, const coord_def& where); void yell(const actor* mon = nullptr); void issue_orders(); -void item_noise(const item_def& item, string msg, int loudness = 25); +void item_noise(const item_def& item, actor &act, string msg, int loudness = 25); void noisy_equipment(); void check_monsters_sense(sense_type sense, int range, const coord_def& where); From 5ea6cb6c5ad6899a0daf199bdbe6f3eb2bff0790 Mon Sep 17 00:00:00 2001 From: Nikolai Lavsky <3328424+nlavsky@users.noreply.github.com> Date: Wed, 11 Sep 2019 14:12:04 +0300 Subject: [PATCH 629/864] Fix HP of summons created via the Phantom Mirror spell Because of an incorrect formula added in a559921a, Mara and rakshasa clones had 200% hp of their original instead of 50%. Regular monsters copied via `cast_phantom_mirror()` had 286% hp and max hp instead of 35%. --- crawl-ref/source/mon-cast.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/mon-cast.cc b/crawl-ref/source/mon-cast.cc index 8378a1e1f5ff..54299ef1e353 100644 --- a/crawl-ref/source/mon-cast.cc +++ b/crawl-ref/source/mon-cast.cc @@ -3196,8 +3196,8 @@ monster* cast_phantom_mirror(monster* mons, monster* targ, int hp_perc, int summ mirror->mark_summoned(5, true, summ_type); mirror->add_ench(ENCH_PHANTOM_MIRROR); mirror->summoner = mons->mid; - mirror->hit_points = mirror->hit_points * 100 / hp_perc; - mirror->max_hit_points = mirror->max_hit_points * 100 / hp_perc; + mirror->hit_points = mirror->hit_points * hp_perc / 100; + mirror->max_hit_points = mirror->max_hit_points * hp_perc / 100; // Sometimes swap the two monsters, so as to disguise the original and the // copy. From c6fd4e61657c468868a7e22272abb3d390f07c1c Mon Sep 17 00:00:00 2001 From: Alex Jurkiewicz Date: Wed, 10 Jul 2019 12:09:24 +1000 Subject: [PATCH 630/864] Default show_more to false in debug builds Debug builds unsurprisingly spew large numbers of messages, so repeatedly showing a more prompt is very inconvenient. --- crawl-ref/source/initfile.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index a6855db89d71..5723859942f6 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -194,7 +194,11 @@ const vector game_options::build_options_list() new BoolGameOption(SIMPLE_NAME(note_chat_messages), false), new BoolGameOption(SIMPLE_NAME(note_dgl_messages), true), new BoolGameOption(SIMPLE_NAME(clear_messages), false), +#ifdef DEBUG + new BoolGameOption(SIMPLE_NAME(show_more), false), +#else new BoolGameOption(SIMPLE_NAME(show_more), !USING_TOUCH), +#endif new BoolGameOption(SIMPLE_NAME(small_more), false), new BoolGameOption(SIMPLE_NAME(pickup_thrown), true), new BoolGameOption(SIMPLE_NAME(show_travel_trail), USING_DGL), From 0d320154d2f566cffe38ce03336ddea31252bd26 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Thu, 19 Sep 2019 02:43:27 +0800 Subject: [PATCH 631/864] Remove useless textcolour calls --- crawl-ref/source/end.cc | 1 - crawl-ref/source/hints.cc | 6 ------ crawl-ref/source/main.cc | 2 -- crawl-ref/source/menu.cc | 5 ----- crawl-ref/source/output.cc | 1 - crawl-ref/source/startup.cc | 1 - 6 files changed, 16 deletions(-) diff --git a/crawl-ref/source/end.cc b/crawl-ref/source/end.cc index 2d794c3515ea..8839dae2d3b8 100644 --- a/crawl-ref/source/end.cc +++ b/crawl-ref/source/end.cc @@ -443,7 +443,6 @@ NORETURN void end_game(scorefile_entry &se) if (!crawl_state.disables[DIS_CONFIRMATIONS]) display_inventory(); - textcolour(LIGHTGREY); clua.save_persist(); diff --git a/crawl-ref/source/hints.cc b/crawl-ref/source/hints.cc index d4cd67517f58..2954db3dd13b 100644 --- a/crawl-ref/source/hints.cc +++ b/crawl-ref/source/hints.cc @@ -2730,7 +2730,6 @@ formatted_string hints_abilities_info() // aptitude information. string hints_skills_info() { - textcolour(channel_to_colour(MSGCH_TUTORIAL)); ostringstream text; text << "<" << colour_to_str(channel_to_colour(MSGCH_TUTORIAL)) << ">"; string broken = "This screen shows the skill set of your character. " @@ -2749,7 +2748,6 @@ string hints_skills_info() string hints_skill_training_info() { - textcolour(channel_to_colour(MSGCH_TUTORIAL)); ostringstream text; text << "<" << colour_to_str(channel_to_colour(MSGCH_TUTORIAL)) << ">"; string broken = "The training percentage (in brown) " @@ -2765,7 +2763,6 @@ string hints_skill_training_info() string hints_skill_costs_info() { - textcolour(channel_to_colour(MSGCH_TUTORIAL)); ostringstream text; text << "<" << colour_to_str(channel_to_colour(MSGCH_TUTORIAL)) << ">"; string broken = "The training cost (in cyan) " @@ -2780,7 +2777,6 @@ string hints_skill_costs_info() string hints_skill_targets_info() { - textcolour(channel_to_colour(MSGCH_TUTORIAL)); ostringstream text; text << "<" << colour_to_str(channel_to_colour(MSGCH_TUTORIAL)) << ">"; string broken = "Press the letter of a skill to set a training target. " @@ -2794,7 +2790,6 @@ string hints_skill_targets_info() string hints_skills_description_info() { - textcolour(channel_to_colour(MSGCH_TUTORIAL)); ostringstream text; text << "<" << colour_to_str(channel_to_colour(MSGCH_TUTORIAL)) << ">"; string broken = "This screen shows the skill set of your character. " @@ -2841,7 +2836,6 @@ string hints_memorise_info() { // TODO: this should probably be in z or I, but adding it to the memorise // menu was easier for the moment. - //textcolour(channel_to_colour(MSGCH_TUTORIAL)); ostringstream text; vector cmd; text << "<" << colour_to_str(channel_to_colour(MSGCH_TUTORIAL)) << ">"; diff --git a/crawl-ref/source/main.cc b/crawl-ref/source/main.cc index c9329f174a53..865af776ca5f 100644 --- a/crawl-ref/source/main.cc +++ b/crawl-ref/source/main.cc @@ -2073,8 +2073,6 @@ static void _prep_input() you.time_taken = player_speed(); you.shield_blocks = 0; // no blocks this round - textcolour(LIGHTGREY); - you.redraw_status_lights = true; print_stats(); diff --git a/crawl-ref/source/menu.cc b/crawl-ref/source/menu.cc index cabb18b06e4d..e63871aa95a7 100644 --- a/crawl-ref/source/menu.cc +++ b/crawl-ref/source/menu.cc @@ -2842,10 +2842,6 @@ void PrecisionMenu::draw_menu() { for (MenuObject *obj : m_attached_objects) obj->render(); - // Render everything else here - - // Reset textcolour just in case - textcolour(LIGHTGRAY); } MenuItem::MenuItem(): m_min_coord(0,0), m_max_coord(0,0), m_selected(false), @@ -3345,7 +3341,6 @@ void FormattedTextItem::render() { m_font_buf.clear(); // FIXME: m_fg_colour doesn't work here while it works in console. - textcolour(m_fg_colour); m_font_buf.add(formatted_string::parse_string(m_render_text, m_fg_colour), m_min_coord.x, m_min_coord.y + get_vertical_offset()); diff --git a/crawl-ref/source/output.cc b/crawl-ref/source/output.cc index a422ec4af03a..545fcba50fae 100644 --- a/crawl-ref/source/output.cc +++ b/crawl-ref/source/output.cc @@ -1417,7 +1417,6 @@ void print_stats() you.redraw_status_lights = false; _print_status_lights(11 + yhack); } - textcolour(LIGHTGREY); #ifdef USE_TILE_LOCAL if (has_changed) diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index da6ca0125fb0..a72401c6d4e8 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -349,7 +349,6 @@ static void _post_init(bool newc) // This just puts the view up for the first turn. you.redraw_title = true; - textcolour(LIGHTGREY); you.redraw_status_lights = true; print_stats(); viewwindow(); From 2190daeb1e8321668c1368ec5e4d3e3036e096e2 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Thu, 19 Sep 2019 03:04:25 +0800 Subject: [PATCH 632/864] Remove unused player name error messages --- crawl-ref/source/ghost.cc | 2 +- crawl-ref/source/ng-input.cc | 19 ++----------------- crawl-ref/source/ng-input.h | 2 +- 3 files changed, 4 insertions(+), 19 deletions(-) diff --git a/crawl-ref/source/ghost.cc b/crawl-ref/source/ghost.cc index 734172071ef0..503417631d78 100644 --- a/crawl-ref/source/ghost.cc +++ b/crawl-ref/source/ghost.cc @@ -780,7 +780,7 @@ bool debug_check_ghost(const ghost_demon &ghost) return false; // Name validation. - if (!validate_player_name(ghost.name, false)) + if (!validate_player_name(ghost.name)) return false; // Many combining characters can come per every letter, but if there's // that much, it's probably a maliciously forged ghost of some kind. diff --git a/crawl-ref/source/ng-input.cc b/crawl-ref/source/ng-input.cc index da7263a8a329..9e12304f40c0 100644 --- a/crawl-ref/source/ng-input.cc +++ b/crawl-ref/source/ng-input.cc @@ -64,10 +64,10 @@ bool is_good_name(const string& name, bool blankOK) // Disallow names that would result in a save named just ".cs". if (strip_filename_unsafe_chars(name).empty()) return blankOK && name.empty(); - return validate_player_name(name, false); + return validate_player_name(name); } -bool validate_player_name(const string &name, bool verbose) +bool validate_player_name(const string &name) { #if defined(TARGET_OS_WINDOWS) // Quick check for CON -- blows up real good under DOS/Windows. @@ -76,18 +76,12 @@ bool validate_player_name(const string &name, bool verbose) || strcasecmp(name.c_str(), "prn") == 0 || strnicmp(name.c_str(), "LPT", 3) == 0) { - if (verbose) - cprintf("\nSorry, that name gives your OS a headache.\n"); return false; } #endif if (strwidth(name) > MAX_NAME_LENGTH) - { - if (verbose) - cprintf("\nThat name is too long.\n"); return false; - } char32_t c; for (const char *str = name.c_str(); int l = utf8towc(&c, str); str += l) @@ -95,16 +89,7 @@ bool validate_player_name(const string &name, bool verbose) // The technical reasons are gone, but enforcing some sanity doesn't // hurt. if (!iswalnum(c) && c != '-' && c != '.' && c != '_' && c != ' ') - { - if (verbose) - { - cprintf("\n" - "Alpha-numerics, spaces, hyphens, periods " - "and underscores only, please." - "\n"); - } return false; - } } return true; diff --git a/crawl-ref/source/ng-input.h b/crawl-ref/source/ng-input.h index 5b1023853ae3..4fbcbb34a78b 100644 --- a/crawl-ref/source/ng-input.h +++ b/crawl-ref/source/ng-input.h @@ -3,6 +3,6 @@ struct newgame_def; string opening_screen(); -bool validate_player_name(const string &name, bool verbose); +bool validate_player_name(const string &name); bool is_good_name(const string &name, bool blankOK); void enter_player_name(newgame_def& ng); From 79b4920dd900dc6c934e74397ebf4c44e62ca07d Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Thu, 19 Sep 2019 03:09:24 +0800 Subject: [PATCH 633/864] Remove support for yesno outside the messge window --- crawl-ref/source/prompt.cc | 16 ++++------------ crawl-ref/source/prompt.h | 3 +-- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/crawl-ref/source/prompt.cc b/crawl-ref/source/prompt.cc index a22337ceb84e..4c00815c49a6 100644 --- a/crawl-ref/source/prompt.cc +++ b/crawl-ref/source/prompt.cc @@ -50,9 +50,8 @@ bool yes_or_no(const char* fmt, ...) // -- idea borrowed from Nethack bool yesno(const char *str, bool allow_lowercase, int default_answer, bool clear_after, bool interrupt_delays, bool noprompt, - const explicit_keymap *map, GotoRegion region) + const explicit_keymap *map) { - bool message = (region == GOTO_MSG); if (interrupt_delays && !crawl_state.is_repeating_cmd()) interrupt_activity(activity_interrupt::force); @@ -104,12 +103,7 @@ bool yesno(const char *str, bool allow_lowercase, int default_answer, bool clear else { if (!noprompt) - { - if (message) - mprf(MSGCH_PROMPT, "%s", prompt.c_str()); - else - cprintf("%s", prompt.c_str()); - } + mprf(MSGCH_PROMPT, "%s", prompt.c_str()); tmp = ui::getch(KMC_CONFIRM); } @@ -140,7 +134,7 @@ bool yesno(const char *str, bool allow_lowercase, int default_answer, bool clear tmp = toupper_safe(tmp); } - if (clear_after && message) + if (clear_after) clear_messages(); if (tmp == 'N') @@ -156,10 +150,8 @@ bool yesno(const char *str, bool allow_lowercase, int default_answer, bool clear upper ? "Uppercase " : ""); if (use_popup && status) // redundant, but will quiet a warning status->text = pr; - else if (message) - mpr(pr); else - cprintf("%s\n", pr.c_str()); + mpr(pr); } } } diff --git a/crawl-ref/source/prompt.h b/crawl-ref/source/prompt.h index 77e1b1d97b9d..f8b49d96d968 100644 --- a/crawl-ref/source/prompt.h +++ b/crawl-ref/source/prompt.h @@ -10,8 +10,7 @@ typedef map explicit_keymap; bool yesno(const char * str, bool allow_lowercase, int default_answer, bool clear_after = true, bool interrupt_delays = true, bool noprompt = false, - const explicit_keymap *map = nullptr, - GotoRegion = GOTO_MSG); + const explicit_keymap *map = nullptr); int yesnoquit(const char* str, bool safe = true, int default_answer = 0, bool allow_all = false, bool clear_after = true, From 7c97eb6acf3b0a9ab622b14dfeb144cee90ac2ed Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 14 Sep 2019 21:21:14 +0800 Subject: [PATCH 634/864] Remove explicit cursor positioning --- crawl-ref/source/god-abil.cc | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/crawl-ref/source/god-abil.cc b/crawl-ref/source/god-abil.cc index a4818149566a..6bdbe2ebe298 100644 --- a/crawl-ref/source/god-abil.cc +++ b/crawl-ref/source/god-abil.cc @@ -2633,12 +2633,11 @@ spret fedhas_sunlight(bool fail) process_sunlights(false); } -#ifndef USE_TILE_LOCAL - // Move the cursor out of the way (it looks weird). - coord_def temp = grid2view(base); - cgotoxy(temp.x, temp.y, GOTO_DNGN); -#endif - scaled_delay(200); + { + // hide the cursor (it looks weird). + cursor_control con(false); + scaled_delay(200); + } if (revealed_count) { From cb9520c128e9ffc613338e6710c04e2d794ed712 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Thu, 19 Sep 2019 04:36:47 +0800 Subject: [PATCH 635/864] Remove cprintf calls that do nothing --- crawl-ref/source/hints.cc | 1 - crawl-ref/source/newgame.cc | 3 --- 2 files changed, 4 deletions(-) diff --git a/crawl-ref/source/hints.cc b/crawl-ref/source/hints.cc index 2954db3dd13b..e27713f7fe13 100644 --- a/crawl-ref/source/hints.cc +++ b/crawl-ref/source/hints.cc @@ -220,7 +220,6 @@ void pick_hints(newgame_def& choice) #endif game_ended(game_exit::abort); case 'X': - cprintf("\nGoodbye!"); #ifdef USE_TILE_WEB tiles.send_exit_reason("cancel"); #endif diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index f4465812f00b..6f64bc603dde 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -1438,7 +1438,6 @@ bool UINewGameMenu::on_event(const wm_event& ev) { case 'X': case CONTROL('Q'): - cprintf("\nGoodbye!"); #ifdef USE_TILE_WEB tiles.send_exit_reason("cancel"); #endif @@ -1935,7 +1934,6 @@ static bool _prompt_weapon(const newgame_def& ng, newgame_def& ng_choice, { case 'X': case CONTROL('Q'): - cprintf("\nGoodbye!"); #ifdef USE_TILE_WEB tiles.send_exit_reason("cancel"); #endif @@ -2372,7 +2370,6 @@ static void _prompt_gamemode_map(newgame_def& ng, newgame_def& ng_choice, { case 'X': case CONTROL('Q'): - cprintf("\nGoodbye!"); #ifdef USE_TILE_WEB tiles.send_exit_reason("cancel"); #endif From b70a11d81136ab5927ab341212b76a286afdad8e Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Fri, 20 Sep 2019 20:49:28 +0800 Subject: [PATCH 636/864] Fix monster list position when re-running arena The call to expand_mlist() assumes that the monster list has its initial position and size; this is not the case if you run arena mode more than once without quitting the game in between. After this fix, the UI is still broken if you run arena then a regular game. I tried using an unwind_var, but that caused crashes, and a better fix is in the works anyway (using the widget toolkit). --- crawl-ref/source/arena.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/source/arena.cc b/crawl-ref/source/arena.cc index 132a6413bb6a..8dd57338e124 100644 --- a/crawl-ref/source/arena.cc +++ b/crawl-ref/source/arena.cc @@ -985,6 +985,7 @@ namespace arena // Set various options from the arena spec's tags parse_monster_spec(); // may throw an arena_error + crawl_view.init_geometry(); expand_mlist(5); for (monster_type i = MONS_0; i < NUM_MONSTERS; ++i) From e7cd8ce796b272c5c7c075e1410cb39438b0f1ac Mon Sep 17 00:00:00 2001 From: Nikolai Lavsky <3328424+nlavsky@users.noreply.github.com> Date: Mon, 23 Sep 2019 02:51:27 +0300 Subject: [PATCH 637/864] Fix a crash when cloning an almost dead monster (geekosaur) A copy created via rakshasa's Phantom Mirror has only 35% of the target's hp and max hp. If the original monster is almost dead (1-2 HP), its copy will have 0 hp, which crashes the game. Fix this by giving cloned monsters at least 1 hp. Also, it allows rakshasas to clone lurking horrors, who always spawn with only 1 hp. --- crawl-ref/source/mon-cast.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/mon-cast.cc b/crawl-ref/source/mon-cast.cc index 54299ef1e353..47971ed6459f 100644 --- a/crawl-ref/source/mon-cast.cc +++ b/crawl-ref/source/mon-cast.cc @@ -3196,8 +3196,8 @@ monster* cast_phantom_mirror(monster* mons, monster* targ, int hp_perc, int summ mirror->mark_summoned(5, true, summ_type); mirror->add_ench(ENCH_PHANTOM_MIRROR); mirror->summoner = mons->mid; - mirror->hit_points = mirror->hit_points * hp_perc / 100; - mirror->max_hit_points = mirror->max_hit_points * hp_perc / 100; + mirror->hit_points = max(mirror->hit_points * hp_perc / 100, 1); + mirror->max_hit_points = max(mirror->max_hit_points * hp_perc / 100, 1); // Sometimes swap the two monsters, so as to disguise the original and the // copy. From 3ea5ddb52caf3a66e4f92f90f056132a344c65e3 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 23 Sep 2019 22:47:37 +0800 Subject: [PATCH 638/864] Remove support for multi-key macro binds Apparently it was previously possible, for some definitions of the word 'possible', to have multi-key macro binds; e.g. 'ab' -> foo. I couldn't actually get any of these to trigger, however, even when using xdotool to quickly deliver keypress events. This commit simplifies the complicated macro expansion code that resulted. Saved macros that have multi-key binds are silently truncated to the first character. This commit also slightly refactors filtering of empty macros. --- crawl-ref/source/macro.cc | 115 ++++++++++---------------------------- 1 file changed, 28 insertions(+), 87 deletions(-) diff --git a/crawl-ref/source/macro.cc b/crawl-ref/source/macro.cc index a5710515610a..e11f95a526d9 100644 --- a/crawl-ref/source/macro.cc +++ b/crawl-ref/source/macro.cc @@ -52,7 +52,7 @@ #include "version.h" typedef deque keybuf; -typedef map macromap; +typedef map macromap; static macromap Keymaps[KMC_CONTEXT_COUNT]; static macromap Macros; @@ -391,15 +391,16 @@ static string vtostr(const keyseq &seq) /* * Add a macro (surprise, surprise). */ -static void macro_add(macromap &mapref, keyseq key, keyseq action) +static void macro_add(macromap &mapref, int key, keyseq action) { - mapref[key] = action; + if (!action.empty()) + mapref[key] = action; } /* * Remove a macro. */ -static bool macro_del(macromap &mapref, keyseq key) +static bool macro_del(macromap &mapref, int key) { return mapref.erase(key) != 0; } @@ -493,57 +494,17 @@ void macro_buf_add_cmd(command_type cmd, bool reverse) } /* - * Adds keypresses from a sequence into the internal keybuffer. Does some - * O(N^2) analysis to the sequence to apply keymaps. + * Adds keys from a sequence to the end of the internal keybuffer. + * Each key is expanded/converted with the given keymap. */ static void macro_buf_add_long(keyseq actions, macromap &keymap = Keymaps[KMC_DEFAULT]) { - keyseq tmp; - - // debug << "Adding: " << vtostr(actions) << endl; - // debug.flush(); - - // Check whether any subsequences of the sequence are macros. - // The matching starts from as early as possible, and is - // as long as possible given the first constraint. I.e from - // the sequence "abcdef" and macros "ab", "bcde" and "de" - // "ab" and "de" are recognised as macros. - - while (!actions.empty()) + for (const auto key : actions) { - tmp = actions; - - while (!tmp.empty()) - { - auto subst = keymap.find(tmp); - // Found a macro. Add the expansion (action) of the - // macro into the buffer. - if (subst != keymap.end() && !subst->second.empty()) - { - macro_buf_add(subst->second, false, false); - break; - } - - // Didn't find a macro. Remove a key from the end - // of the sequence, and try again. - tmp.pop_back(); - } - - if (tmp.empty()) - { - // Didn't find a macro. Add the first keypress of the sequence - // into the buffer, remove it from the sequence, and try again. - macro_buf_add(actions.front(), false, false); - actions.pop_front(); - } - else - { - // Found a macro, which has already been added above. Now just - // remove the macroed keys from the sequence. - for (unsigned int i = 0; i < tmp.size(); i++) - actions.pop_front(); - } + const auto subst = keymap.find(key); + const auto out = subst == keymap.end() ? keyseq({key}) : subst->second; + macro_buf_add(out, false, false); } } @@ -596,29 +557,15 @@ static void macro_buf_apply_command_macro() if (macro_keys_left > 0 || expanded_keys_left > 0) return; - keyseq tmp = Buffer; - - // find the longest match from the start of the buffer and replace it - while (!tmp.empty()) + const auto expansion = Macros.find(Buffer.front()); + if (expansion != Macros.end()) { - auto expansion = Macros.find(tmp); - - if (expansion != Macros.end() && !expansion->second.empty()) - { - const keyseq &result = expansion->second; - - // Found macro, remove match from front: - for (unsigned int i = 0; i < tmp.size(); i++) - Buffer.pop_front(); - - macro_keys_left = result.size(); + const keyseq &result = expansion->second; - macro_buf_add(result, true, true); - - break; - } - - tmp.pop_back(); + // Found macro, remove match from front: + Buffer.pop_front(); + macro_keys_left = result.size(); + macro_buf_add(result, true, true); } } @@ -675,7 +622,7 @@ static void write_map(FILE *f, const macromap &mp, const char *key) if (entry.second.size()) { fprintf(f, "%s%s\nA:%s\n\n", OUTS(key), - OUTS(vtostr(entry.first)), OUTS(vtostr(entry.second))); + OUTS(vtostr({entry.first})), OUTS(vtostr(entry.second))); } } } @@ -803,14 +750,8 @@ int getch_with_command_macros() _macro_inject_sent_keys(); if (Buffer.empty()) - { - // Read some keys... - keyseq keys = _getch_mul(); - // ... and add them into the buffer (apply keymaps) - macro_buf_add_long(keys); - } + macro_buf_add_long(_getch_mul()); - // Apply longest matching macro at front of buffer: macro_buf_apply_command_macro(); return macro_buf_get(); @@ -1015,15 +956,14 @@ void macro_add_query() macro_type.c_str()); msgwin_prompt(trigger_prompt); - keyseq key; mouse_control mc(MOUSE_MODE_MACRO); - key = _getch_mul(); - string key_str = vtostr(key); + int key = m_getch(); + string key_str = vtostr({key}); key_str = replace_all(key_str, "<", "<<"); - msgwin_reply(vtostr(key)); + msgwin_reply(vtostr({key})); - if (mapref.count(key) && !mapref[key].empty()) + if (mapref.count(key)) { string action_str = vtostr(mapref[key]); action_str = replace_all(action_str, "<", "<<"); @@ -1126,7 +1066,8 @@ static void _read_macros_from(const char* filename) else if (s.substr(0, 2) == "A:") { action = parse_keyseq(s.substr(2)); - macro_add((keymap ? Keymaps[keymc] : Macros), key, action); + if (!key.empty()) + macro_add((keymap ? Keymaps[keymc] : Macros), key.front(), action); } } } @@ -1189,10 +1130,10 @@ string read_rc_file_macro(const string& field) keyseq key = parse_keyseq(macro_key_string); - keyseq action = parse_keyseq(action_string); - macro_add((keymap ? Keymaps[keymc] : Macros), key, action); + if (!key.empty()) + macro_add((keymap ? Keymaps[keymc] : Macros), key.front(), action); // If we didn't save here, macros in rc files would be saved iff you also // changed another macro with cntrl-D and saved at the exit prompt. From 5a8975c3e2236cd5aa0d3cf1738ccfdd360a4ab3 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 23 Sep 2019 02:12:53 +0800 Subject: [PATCH 639/864] Simplify macro code This makes the difference between getchm and getch_with_command_macros slightly clearer. --- crawl-ref/source/macro.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/macro.cc b/crawl-ref/source/macro.cc index e11f95a526d9..45c6dd1384ec 100644 --- a/crawl-ref/source/macro.cc +++ b/crawl-ref/source/macro.cc @@ -714,8 +714,7 @@ int getchm(KeymapContext mc, int (*rgetch)()) return a; // Read some keys... - keyseq keys = _getch_mul(rgetch); - macro_buf_add_with_keymap(keys, mc); + macro_buf_add_with_keymap(_getch_mul(rgetch), mc); return macro_buf_get(); } @@ -750,7 +749,7 @@ int getch_with_command_macros() _macro_inject_sent_keys(); if (Buffer.empty()) - macro_buf_add_long(_getch_mul()); + macro_buf_add_with_keymap(_getch_mul(), KMC_DEFAULT); macro_buf_apply_command_macro(); From 678ee33c32bb4efb2fda34a8b44ce857352add0c Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Tue, 24 Sep 2019 00:24:30 +0800 Subject: [PATCH 640/864] Refactor _getch_mul() -> _getch_single() While you could theoretically have multiple keys returned from _getch_mul, in practice I never managed to make it happen, and it's preferable for the code paths through the macro system to be as simple as possible. --- crawl-ref/source/macro.cc | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/crawl-ref/source/macro.cc b/crawl-ref/source/macro.cc index 45c6dd1384ec..55c5e82c2681 100644 --- a/crawl-ref/source/macro.cc +++ b/crawl-ref/source/macro.cc @@ -666,11 +666,8 @@ void macro_save() * Reads as many keypresses as are available (waiting for at least one), * and returns them as a single keyseq. */ -static keyseq _getch_mul(int (*rgetch)() = nullptr) +static int _getch_single(int (*rgetch)() = nullptr) { - keyseq keys; - int a; - // Something's gone wrong with replaying keys if crawl needs to // get new keys from the user. if (crawl_state.is_replaying_keys()) @@ -683,17 +680,16 @@ static keyseq _getch_mul(int (*rgetch)() = nullptr) if (!rgetch) rgetch = m_getch; - // The a == 0 test is legacy code that I don't dare to remove. I + // The key == 0 test is legacy code that I don't dare to remove. I // have a vague recollection of it being a kludge for conio support. + int key; do { - a = rgetch(); - if (a != CK_NO_KEY) - keys.push_back(a); + key = rgetch(); } - while (keys.size() == 0 || ((kbhit() || a == 0) && a != CK_REDRAW)); + while (key == 0 || key == CK_NO_KEY); - return keys; + return key; } /* @@ -713,8 +709,8 @@ int getchm(KeymapContext mc, int (*rgetch)()) if ((a = macro_buf_get()) != -1) return a; - // Read some keys... - macro_buf_add_with_keymap(_getch_mul(rgetch), mc); + // Read a key... + macro_buf_add_with_keymap({_getch_single(rgetch)}, mc); return macro_buf_get(); } @@ -749,7 +745,7 @@ int getch_with_command_macros() _macro_inject_sent_keys(); if (Buffer.empty()) - macro_buf_add_with_keymap(_getch_mul(), KMC_DEFAULT); + macro_buf_add_with_keymap({_getch_single()}, KMC_DEFAULT); macro_buf_apply_command_macro(); From 049a78546b28e77ec9647cdfd40840a8451f18ad Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Tue, 24 Sep 2019 01:04:06 +0800 Subject: [PATCH 641/864] Simplify macro_buf_add_with_keymap We only ever add a single key at a time to the macro buffer; better to enforce that. This also asserts in remap_key() that the macro buffer is empty before remapping a key; this must be the case because ui::pump_events() first tries to get a key from the macro buf, and only remaps a new key if there is no macro key available. --- crawl-ref/source/macro.cc | 10 +++++----- crawl-ref/source/macro.h | 2 +- crawl-ref/source/ui.cc | 7 ++++--- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/crawl-ref/source/macro.cc b/crawl-ref/source/macro.cc index 55c5e82c2681..fd4c5c7345c6 100644 --- a/crawl-ref/source/macro.cc +++ b/crawl-ref/source/macro.cc @@ -710,16 +710,16 @@ int getchm(KeymapContext mc, int (*rgetch)()) return a; // Read a key... - macro_buf_add_with_keymap({_getch_single(rgetch)}, mc); + macro_buf_add_with_keymap(_getch_single(rgetch), mc); return macro_buf_get(); } -void macro_buf_add_with_keymap(keyseq keys, KeymapContext mc) +void macro_buf_add_with_keymap(int key, KeymapContext mc) { if (mc == KMC_NONE) - macro_buf_add(keys, false, false); + macro_buf_add({key}, false, false); else - macro_buf_add_long(keys, Keymaps[mc]); + macro_buf_add_long({key}, Keymaps[mc]); } /** @@ -745,7 +745,7 @@ int getch_with_command_macros() _macro_inject_sent_keys(); if (Buffer.empty()) - macro_buf_add_with_keymap({_getch_single()}, KMC_DEFAULT); + macro_buf_add_with_keymap(_getch_single(), KMC_DEFAULT); macro_buf_apply_command_macro(); diff --git a/crawl-ref/source/macro.h b/crawl-ref/source/macro.h index 7c0eb340f4be..3579ce6674c9 100644 --- a/crawl-ref/source/macro.h +++ b/crawl-ref/source/macro.h @@ -69,7 +69,7 @@ void macro_buf_add(const keyseq &actions, int macro_buf_get(); void macro_buf_add_cmd(command_type cmd, bool reverse = false); -void macro_buf_add_with_keymap(keyseq keys, KeymapContext mc); +void macro_buf_add_with_keymap(int key, KeymapContext mc); void process_command_on_record(command_type cmd); diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 60c6fe8fbe02..295160f64eaf 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -1745,9 +1745,10 @@ void resize(int w, int h) static void remap_key(wm_event &event) { - keyseq keys = {event.key.keysym.sym}; - KeymapContext km = ui_root.keymap_stack.size() > 0 ? ui_root.keymap_stack[0] : KMC_NONE; - macro_buf_add_with_keymap(keys, km); + const auto keymap = ui_root.keymap_stack.size() > 0 ? + ui_root.keymap_stack[0] : KMC_NONE; + ASSERT(get_macro_buf_size() == 0); + macro_buf_add_with_keymap(event.key.keysym.sym, keymap); event.key.keysym.sym = macro_buf_get(); ASSERT(event.key.keysym.sym != -1); } From 0e779d289c517aeb1bab0ed4e172b85274d776cf Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Wed, 25 Sep 2019 23:43:13 +0800 Subject: [PATCH 642/864] Fix some compile warnings (geekosaur) Returning std::move() here is fine because the parameter is an rvalue reference, so RVO is not relevant, and a move() call is required to prevent a copy. --- crawl-ref/source/initfile.cc | 2 ++ crawl-ref/source/libutil.cc | 2 +- crawl-ref/source/macro.cc | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index 5723859942f6..728b4f2d2353 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -110,11 +110,13 @@ static bool _first_greater(const pair &l, const pair &r) const vector game_options::build_options_list() { +#ifndef DEBUG const bool USING_TOUCH = #if defined(TOUCH_UI) true; #else false; +#endif #endif const bool USING_DGL = #if defined(DGAMELAUNCH) diff --git a/crawl-ref/source/libutil.cc b/crawl-ref/source/libutil.cc index e224154cb2de..64a8426e3881 100644 --- a/crawl-ref/source/libutil.cc +++ b/crawl-ref/source/libutil.cc @@ -473,7 +473,7 @@ string unwrap_desc(string&& desc) string tag = desc.substr(1, pos - 1); desc.erase(0, pos + 1); if (tag == "nowrap") - return desc; + return move(desc); else if (desc.empty()) return ""; } diff --git a/crawl-ref/source/macro.cc b/crawl-ref/source/macro.cc index fd4c5c7345c6..fe2f1d55dc69 100644 --- a/crawl-ref/source/macro.cc +++ b/crawl-ref/source/macro.cc @@ -717,9 +717,9 @@ int getchm(KeymapContext mc, int (*rgetch)()) void macro_buf_add_with_keymap(int key, KeymapContext mc) { if (mc == KMC_NONE) - macro_buf_add({key}, false, false); + macro_buf_add(keyseq(key), false, false); else - macro_buf_add_long({key}, Keymaps[mc]); + macro_buf_add_long(keyseq(key), Keymaps[mc]); } /** From 0627d6e13b0d86d7b259a824856c2ef2b757e524 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Wed, 25 Sep 2019 01:40:45 +0800 Subject: [PATCH 643/864] Remove unused and rename used fs_op members --- crawl-ref/source/fontwrapper-ft.cc | 2 +- crawl-ref/source/format.cc | 10 +++++----- crawl-ref/source/format.h | 9 +++------ 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/crawl-ref/source/fontwrapper-ft.cc b/crawl-ref/source/fontwrapper-ft.cc index 08e0bcb5d852..5539b1da872e 100644 --- a/crawl-ref/source/fontwrapper-ft.cc +++ b/crawl-ref/source/fontwrapper-ft.cc @@ -795,7 +795,7 @@ void FTFontWrapper::store(FontBuffer &buf, float &x, float &y, { case FSOP_COLOUR: // Only foreground colors for now... - colour = op.x & 0xF; + colour = op.colour & 0xF; break; case FSOP_TEXT: store(buf, x, y, op.text, term_colours[colour], orig_x); diff --git a/crawl-ref/source/format.cc b/crawl-ref/source/format.cc index 375d54f5399b..1c5b9fccdd5b 100644 --- a/crawl-ref/source/format.cc +++ b/crawl-ref/source/format.cc @@ -273,7 +273,7 @@ string formatted_string::html_dump() const break; case FSOP_COLOUR: s += ""; break; } @@ -372,7 +372,7 @@ string formatted_string::to_colour_string() const else if (ops[i] == FSOP_COLOUR) { st += "<"; - st += colour_to_str(ops[i].x); + st += colour_to_str(ops[i].colour); st += ">"; } } @@ -399,7 +399,7 @@ int formatted_string::find_last_colour() const { for (int i = ops.size() - 1; i >= 0; --i) if (ops[i].type == FSOP_COLOUR) - return ops[i].x; + return ops[i].colour; } return LIGHTGREY; } @@ -532,9 +532,9 @@ void formatted_string::fs_op::display() const { case FSOP_COLOUR: #ifndef USE_TILE_LOCAL - if (x < NUM_TERM_COLOURS) + if (colour < NUM_TERM_COLOURS) #endif - ::textcolour(x); + ::textcolour(colour); break; case FSOP_TEXT: ::cprintf("%s", text.c_str()); diff --git a/crawl-ref/source/format.h b/crawl-ref/source/format.h index 3ac43d7023a8..cca8f03c9b08 100644 --- a/crawl-ref/source/format.h +++ b/crawl-ref/source/format.h @@ -68,17 +68,14 @@ class formatted_string struct fs_op { fs_op_type type; - int x, y; - bool relative; + int colour; string text; - fs_op(int colour) - : type(FSOP_COLOUR), x(colour), y(-1), relative(false), text() + fs_op(int _colour) : type(FSOP_COLOUR), colour(_colour), text() { } - fs_op(const string &s) - : type(FSOP_TEXT), x(-1), y(-1), relative(false), text(s) + fs_op(const string &s) : type(FSOP_TEXT), colour(-1), text(s) { } From 6ad10583fd2fffbe245b71d05ff9cb926e18672a Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Wed, 25 Sep 2019 02:13:00 +0800 Subject: [PATCH 644/864] Remove some formatted_string functions Spell range strings don't use colour codes any more. As for explore discoveries, it's simpler to parse the tagged string and then use the dedicated width() method. --- crawl-ref/source/format.cc | 51 ------------------------------------ crawl-ref/source/format.h | 3 --- crawl-ref/source/spl-cast.cc | 2 +- crawl-ref/source/travel.cc | 6 ++--- 4 files changed, 4 insertions(+), 58 deletions(-) diff --git a/crawl-ref/source/format.cc b/crawl-ref/source/format.cc index 1c5b9fccdd5b..ca4aa0f819d4 100644 --- a/crawl-ref/source/format.cc +++ b/crawl-ref/source/format.cc @@ -589,54 +589,3 @@ int count_linebreaks(const formatted_string& fs) } return count; } - -/** - * How long are the tags in the string? - * - * This function assumes that every character making up the tag is one char - * long. This shouldn't break as long as nobody uses non-ASCII characters - * in the tag. It also can't handle nested tags, but that shouldn't be an issue. - * - * @param s the string with the tags. - * @return the length of the tags, including the angle brackets. - */ -int tagged_string_tag_length(const string& s) -{ - int len = 0; - bool in_tag = false; - char prev_char = '\0'; - for (char ch : s) - { - if (in_tag) - { - if (ch == '<' && prev_char == '<') // "<<" sequence - { - in_tag = false; - len--; // Correct for len being incremented last time - } - else if (ch == '>') - in_tag = false; - } - else if (ch == '<') - in_tag = true; - - if (in_tag) - len++; - prev_char = ch; - } - - ASSERT(len >= 0); - return len; -} - -/** - * How long will this string be when printed? - * - * @param string str - * @return how much the user will see -- counting combining characters together, - * not including tags, etc. - */ -int printed_width(const string& str) -{ - return strwidth(str) - tagged_string_tag_length(str); -} diff --git a/crawl-ref/source/format.h b/crawl-ref/source/format.h index cca8f03c9b08..1c0f394ed2cb 100644 --- a/crawl-ref/source/format.h +++ b/crawl-ref/source/format.h @@ -92,7 +92,4 @@ class formatted_string int count_linebreaks(const formatted_string& fs); -int tagged_string_tag_length(const string& s); -int printed_width(const string& s); - void display_tagged_block(const string& s); diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc index 45524370e961..d430d958d796 100644 --- a/crawl-ref/source/spl-cast.cc +++ b/crawl-ref/source/spl-cast.cc @@ -159,7 +159,7 @@ static string _spell_extra_description(spell_type spell, bool viewing) const string rangestring = spell_range_string(spell); desc << chop_string(spell_power_string(spell), 13) - << chop_string(rangestring, 9 + tagged_string_tag_length(rangestring)) + << chop_string(rangestring, 9) << chop_string(spell_hunger_string(spell), 8) << chop_string(spell_noise_string(spell, 10), 14); diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc index e25fa01fd844..e1c1b92658ea 100644 --- a/crawl-ref/source/travel.cc +++ b/crawl-ref/source/travel.cc @@ -4781,10 +4781,10 @@ template void explore_discoveries::say_any( return; } - const string message = "Found " + - comma_separated_line(coll.begin(), coll.end()) + "."; + const auto message = formatted_string::parse_string("Found " + + comma_separated_line(coll.begin(), coll.end()) + "."); - if (printed_width(message) >= get_number_of_cols()) + if (message.width() >= get_number_of_cols()) mprf("Found %s %s.", number_in_words(size).c_str(), category); else mpr(message); From eb4d282544913c1e9eda75049dc48c41b4da9e8a Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Wed, 25 Sep 2019 02:22:39 +0800 Subject: [PATCH 645/864] Reduce unnecessary text widget allocations --- crawl-ref/source/format.cc | 6 ++++++ crawl-ref/source/format.h | 1 + crawl-ref/source/ui.cc | 2 ++ 3 files changed, 9 insertions(+) diff --git a/crawl-ref/source/format.cc b/crawl-ref/source/format.cc index ca4aa0f819d4..f68da416138b 100644 --- a/crawl-ref/source/format.cc +++ b/crawl-ref/source/format.cc @@ -286,6 +286,12 @@ bool formatted_string::operator < (const formatted_string &other) const return string(*this) < string(other); } +bool formatted_string::operator == (const formatted_string &other) const +{ + // May produce false negative in some cases, e.g. duplicated colour ops + return ops == other.ops; +} + const formatted_string & formatted_string::operator += (const formatted_string &other) { diff --git a/crawl-ref/source/format.h b/crawl-ref/source/format.h index 1c0f394ed2cb..8cef8616ee9c 100644 --- a/crawl-ref/source/format.h +++ b/crawl-ref/source/format.h @@ -44,6 +44,7 @@ class formatted_string string html_dump() const; bool operator < (const formatted_string &other) const; + bool operator == (const formatted_string &other) const; const formatted_string &operator += (const formatted_string &other); char &operator [] (size_t idx); diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 295160f64eaf..ef6bac9227ef 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -464,6 +464,8 @@ Text::Text() void Text::set_text(const formatted_string &fs) { + if (fs == m_text) + return; m_text.clear(); m_text += fs; _invalidate_sizereq(); From 0b1efcbfd730743143c2d10326fec57868ef409a Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Wed, 25 Sep 2019 23:52:45 +0800 Subject: [PATCH 646/864] Revert "Fix some compile warnings (geekosaur)" This reverts commit 0e779d289c517aeb1bab0ed4e172b85274d776cf. --- crawl-ref/source/initfile.cc | 2 -- crawl-ref/source/libutil.cc | 2 +- crawl-ref/source/macro.cc | 4 ++-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index 728b4f2d2353..5723859942f6 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -110,13 +110,11 @@ static bool _first_greater(const pair &l, const pair &r) const vector game_options::build_options_list() { -#ifndef DEBUG const bool USING_TOUCH = #if defined(TOUCH_UI) true; #else false; -#endif #endif const bool USING_DGL = #if defined(DGAMELAUNCH) diff --git a/crawl-ref/source/libutil.cc b/crawl-ref/source/libutil.cc index 64a8426e3881..e224154cb2de 100644 --- a/crawl-ref/source/libutil.cc +++ b/crawl-ref/source/libutil.cc @@ -473,7 +473,7 @@ string unwrap_desc(string&& desc) string tag = desc.substr(1, pos - 1); desc.erase(0, pos + 1); if (tag == "nowrap") - return move(desc); + return desc; else if (desc.empty()) return ""; } diff --git a/crawl-ref/source/macro.cc b/crawl-ref/source/macro.cc index fe2f1d55dc69..fd4c5c7345c6 100644 --- a/crawl-ref/source/macro.cc +++ b/crawl-ref/source/macro.cc @@ -717,9 +717,9 @@ int getchm(KeymapContext mc, int (*rgetch)()) void macro_buf_add_with_keymap(int key, KeymapContext mc) { if (mc == KMC_NONE) - macro_buf_add(keyseq(key), false, false); + macro_buf_add({key}, false, false); else - macro_buf_add_long(keyseq(key), Keymaps[mc]); + macro_buf_add_long({key}, Keymaps[mc]); } /** From d158fba778ae8e4ac9b71ca3e5de23057a561ada Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Wed, 25 Sep 2019 23:43:13 +0800 Subject: [PATCH 647/864] Fix some compile warnings (geekosaur) Returning std::move() here is fine because the parameter is an rvalue reference, so RVO is not relevant, and a move() call is required to prevent a copy. --- crawl-ref/source/initfile.cc | 2 ++ crawl-ref/source/libutil.cc | 2 +- crawl-ref/source/macro.cc | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index 5723859942f6..728b4f2d2353 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -110,11 +110,13 @@ static bool _first_greater(const pair &l, const pair &r) const vector game_options::build_options_list() { +#ifndef DEBUG const bool USING_TOUCH = #if defined(TOUCH_UI) true; #else false; +#endif #endif const bool USING_DGL = #if defined(DGAMELAUNCH) diff --git a/crawl-ref/source/libutil.cc b/crawl-ref/source/libutil.cc index e224154cb2de..64a8426e3881 100644 --- a/crawl-ref/source/libutil.cc +++ b/crawl-ref/source/libutil.cc @@ -473,7 +473,7 @@ string unwrap_desc(string&& desc) string tag = desc.substr(1, pos - 1); desc.erase(0, pos + 1); if (tag == "nowrap") - return desc; + return move(desc); else if (desc.empty()) return ""; } diff --git a/crawl-ref/source/macro.cc b/crawl-ref/source/macro.cc index fd4c5c7345c6..cc79b47ac515 100644 --- a/crawl-ref/source/macro.cc +++ b/crawl-ref/source/macro.cc @@ -717,9 +717,9 @@ int getchm(KeymapContext mc, int (*rgetch)()) void macro_buf_add_with_keymap(int key, KeymapContext mc) { if (mc == KMC_NONE) - macro_buf_add({key}, false, false); + macro_buf_add(keyseq({key}), false, false); else - macro_buf_add_long({key}, Keymaps[mc]); + macro_buf_add_long(keyseq({key}), Keymaps[mc]); } /** From 4b16227417ee42ebb3bc19de8af493073a10fa9c Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Thu, 26 Sep 2019 00:58:39 +0800 Subject: [PATCH 648/864] More refactoring of formatted_string code --- crawl-ref/source/format.cc | 14 +++++++------- crawl-ref/source/format.h | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/crawl-ref/source/format.cc b/crawl-ref/source/format.cc index f68da416138b..86f500c05dfe 100644 --- a/crawl-ref/source/format.cc +++ b/crawl-ref/source/format.cc @@ -236,7 +236,7 @@ formatted_string::operator string() const { string s; for (const fs_op &op : ops) - if (op == FSOP_TEXT) + if (op.type == FSOP_TEXT) s += op.text; return s; @@ -304,7 +304,7 @@ int formatted_string::width() const // Just add up the individual string lengths. int len = 0; for (const fs_op &op : ops) - if (op == FSOP_TEXT) + if (op.type == FSOP_TEXT) len += strwidth(op.text); return len; } @@ -325,7 +325,7 @@ char &formatted_string::operator [] (size_t idx) int size = ops.size(); for (int i = 0; i < size; ++i) { - if (ops[i] != FSOP_TEXT) + if (ops[i].type != FSOP_TEXT) continue; size_t len = ops[i].text.length(); @@ -347,7 +347,7 @@ string formatted_string::tostring(int s, int e) const for (int i = s; i <= e && i < size; ++i) { - if (ops[i] == FSOP_TEXT) + if (ops[i].type == FSOP_TEXT) st += ops[i].text; } return st; @@ -359,7 +359,7 @@ string formatted_string::to_colour_string() const const int size = ops.size(); for (int i = 0; i < size; ++i) { - if (ops[i] == FSOP_TEXT) + if (ops[i].type == FSOP_TEXT) { // gotta double up those '<' chars ... size_t start = st.size(); @@ -375,7 +375,7 @@ string formatted_string::to_colour_string() const start = left_angle + 2; } } - else if (ops[i] == FSOP_COLOUR) + else if (ops[i].type == FSOP_COLOUR) { st += "<"; st += colour_to_str(ops[i].colour); @@ -503,7 +503,7 @@ void formatted_string::add_glyph(cglyph_t g) void formatted_string::textcolour(int colour) { - if (!ops.empty() && ops[ ops.size() - 1 ].type == FSOP_COLOUR) + if (!ops.empty() && ops.back().type == FSOP_COLOUR) ops.pop_back(); ops.emplace_back(colour); diff --git a/crawl-ref/source/format.h b/crawl-ref/source/format.h index 8cef8616ee9c..a3d49be44d1a 100644 --- a/crawl-ref/source/format.h +++ b/crawl-ref/source/format.h @@ -80,9 +80,9 @@ class formatted_string { } - operator fs_op_type () const + bool operator == (const fs_op &other) const { - return type; + return type == other.type && colour == other.colour && text == other.text; } void display() const; }; From 46ecf6da75442dd82ba7ddf155c9039f77e43ef7 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Thu, 26 Sep 2019 01:05:28 +0800 Subject: [PATCH 649/864] Remove unused function chop_tagged_string() --- crawl-ref/source/unicode.cc | 54 ------------------------------------- crawl-ref/source/unicode.h | 2 -- 2 files changed, 56 deletions(-) diff --git a/crawl-ref/source/unicode.cc b/crawl-ref/source/unicode.cc index b167395ae880..efe375d0b39e 100644 --- a/crawl-ref/source/unicode.cc +++ b/crawl-ref/source/unicode.cc @@ -557,57 +557,3 @@ string chop_string(const string &s, int width, bool spaces) { return chop_string(s.c_str(), width, spaces); } - -string chop_tagged_string(const char *s, int width, bool spaces) -{ - const char * const s0 = s; - bool in_tag = false; // are we in a tag - bool tag_first = false; // is this the first character of a tag? - char32_t c; - - while (int clen = utf8towc(&c, s)) - { - bool visible = true; - - if (in_tag) - { - if (c == '>') - in_tag = false; - - // << is an escape for <, not a tag. Count the second < as visible. - if (c == '<' && tag_first) - in_tag = false; - else - visible = false; - tag_first = false; - } - else if (c == '<') - { - in_tag = true; - tag_first = true; - visible = false; - } - - if (visible) - { - const int cw = wcwidth(c); - // Due to combining chars, we can't stop at merely reaching the - // target width, the next character needs to exceed it. - if (cw > width) // note: a CJK character might leave one space left - break; - if (cw >= 0) // should we assert on control chars instead? - width -= cw; - } - - s += clen; - } - - if (spaces && width) - return string(s0, s - s0) + string(width, ' '); - return string(s0, s - s0);; -} - -string chop_tagged_string(const string &s, int width, bool spaces) -{ - return chop_tagged_string(s.c_str(), width, spaces); -} diff --git a/crawl-ref/source/unicode.h b/crawl-ref/source/unicode.h index a451fb8c56a3..8c423eb00073 100644 --- a/crawl-ref/source/unicode.h +++ b/crawl-ref/source/unicode.h @@ -9,8 +9,6 @@ int strwidth(const char *s); int strwidth(const string &s); string chop_string(const char *s, int width, bool spaces = true); string chop_string(const string &s, int width, bool spaces = true); -string chop_tagged_string(const char *s, int width, bool spaces = true); -string chop_tagged_string(const string &s, int width, bool spaces = true); int wctoutf8(char *d, char32_t s); int utf8towc(char32_t *d, const char *s); From 3936067ed8308d75ba640535f88932e3b5870e0b Mon Sep 17 00:00:00 2001 From: kitchen-ace <47063032+kitchen-ace@users.noreply.github.com> Date: Thu, 26 Sep 2019 03:14:35 -0400 Subject: [PATCH 650/864] A meagre spelling correction for AUS english (#1157) --- crawl-ref/source/spl-goditem.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/spl-goditem.cc b/crawl-ref/source/spl-goditem.cc index 97d229919d95..d8250b3130b7 100644 --- a/crawl-ref/source/spl-goditem.cc +++ b/crawl-ref/source/spl-goditem.cc @@ -199,7 +199,7 @@ static spret _try_to_pacify(monster &mon, int healed, int pow, if (_pacification_sides(mon.type, pow) < mon_hp) { // monster avg hp too high to ever be pacified with your invo skill. - mprf("%s would be completely unfazed by your meager offer of peace.", + mprf("%s would be completely unfazed by your meagre offer of peace.", mon.name(DESC_THE).c_str()); return spret::abort; } From 80d7c3d5c14ee4473920a087932203a28c2f47fe Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 26 Sep 2019 18:26:26 -0400 Subject: [PATCH 651/864] Fix ungenerated branches in wizmode + pregen (12071) These were falling through the cracks of _branch_pregenerates, but not generating as part of the generation order. This commit just moves you directly to them without any pregeneration (which needless to say will break the seed, but if you're doing this you probably don't care). --- crawl-ref/source/files.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 2d34ee0c907f..49c42db521f1 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1580,6 +1580,8 @@ static bool _branch_pregenerates(branch_type b) { if (!you.deterministic_levelgen) return false; + if (!brentry[b].is_valid() && is_random_subbranch(b)) + return false; return count(branch_generation_order.begin(), branch_generation_order.end(), b) > 0; } @@ -1597,7 +1599,10 @@ static bool _branch_pregenerates(branch_type b) */ bool pregen_dungeon(const level_id &stopping_point) { - if (stopping_point.is_valid()) + // TODO: the is_valid() check here doesn't look quite right to me, but so + // far I can't get it to break anything... + if (stopping_point.is_valid() + || is_random_subbranch(stopping_point.branch) && you.wizard) { if (you.save->has_chunk(stopping_point.describe())) return false; From ff19f33cdb307ee293f482599b5ef405d14dd0cd Mon Sep 17 00:00:00 2001 From: Alex Jurkiewicz Date: Thu, 26 Sep 2019 20:28:57 +1000 Subject: [PATCH 652/864] Mark trove portals as single-use Fixes #1126. --- crawl-ref/source/dat/descript/features.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/dat/descript/features.txt b/crawl-ref/source/dat/descript/features.txt index 8f0b243fd0fb..23a977c31f4c 100644 --- a/crawl-ref/source/dat/descript/features.txt +++ b/crawl-ref/source/dat/descript/features.txt @@ -704,7 +704,8 @@ A passage leading to a sewer. It is gradually rusting away. %%%% A portal to a secret trove of treasure -A portal leading to a treasure trove. +A portal leading to a treasure trove. This portal is unstable and will collapse +after a single use. %%%% A dark tunnel From 406b842e22407ec0619b963c7bc17f570cc03b27 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Thu, 26 Sep 2019 01:46:18 +0800 Subject: [PATCH 653/864] Add ui_render() --- crawl-ref/source/ui.cc | 6 ++++++ crawl-ref/source/ui.h | 1 + 2 files changed, 7 insertions(+) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index ef6bac9227ef..74a5f6941286 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -1762,6 +1762,12 @@ void ui_force_render() ui_root.render(); } +void ui_render() +{ + ui_root.layout(); + ui_root.render(); +} + void pump_events(int wait_event_timeout) { int macro_key = macro_buf_get(); diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index 9d5f3d313fab..71b1647a4e81 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -619,6 +619,7 @@ void run_layout(shared_ptr root, const bool& done); bool has_layout(); int getch(KeymapContext km = KMC_DEFAULT); void ui_force_render(); +void ui_render(); void ui_delay(unsigned int ms); void push_scissor(i4 scissor); From 2a432842a155606db3bc9c9b11138b7db3e80914 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sun, 12 Aug 2018 19:48:42 +0800 Subject: [PATCH 654/864] Fix invalid read during program shutdown Invalid memory accesses were caused by the Slot destructor freeing slots, which freed shared_ptrs, which caused remove_by_target() to access handlers, which was already partially destroyed. --- crawl-ref/source/ui.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index 71b1647a4e81..8f3e1f993396 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -55,6 +55,7 @@ template class Slot { public: + ~Slot() { alive = false; } typedef function HandlerSig; typedef multimap HandlerMap; bool emit(Target *target, Args&... args) @@ -75,9 +76,11 @@ class Slot } void remove_by_target(Target *target) { - handlers.erase(target); + if (alive) + handlers.erase(target); } protected: + bool alive {true}; HandlerMap handlers; }; From 01783e0825e07d1a04615fa7eaf261e64636933c Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 23 Jun 2018 13:45:01 +0800 Subject: [PATCH 655/864] Add UIGrid stretch_h, stretch_v --- crawl-ref/source/ui.cc | 21 +++++++++++++++++---- crawl-ref/source/ui.h | 2 ++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 74a5f6941286..0252664c0cb8 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -1189,20 +1189,33 @@ void Grid::layout_track(Direction dim, SizeReq sr, int size) for (size_t i = 0; i < infos.size(); ++i) infos[i].size = infos[i].sr.min; + const bool stretch = dim ? stretch_v : stretch_h; + bool stretching = false; + while (true) { int sum_flex_grow = 0, sum_taken = 0; for (const auto& info : infos) sum_flex_grow += info.size < info.sr.nat ? info.flex_grow : 0; if (!sum_flex_grow) - break; + { + if (!stretch) + break; + stretching = true; + for (const auto& info : infos) + sum_flex_grow += info.flex_grow; + if (!sum_flex_grow) + break; + } for (size_t i = 0; i < infos.size(); ++i) { - float efg = infos[i].size < infos[i].sr.nat ? infos[i].flex_grow : 0; + float efg = (infos[i].size < infos[i].sr.nat || stretching) + ? infos[i].flex_grow : 0; int tr_extra = extra * efg / sum_flex_grow; - ASSERT(infos[i].size <= infos[i].sr.nat); - int taken = min(tr_extra, infos[i].sr.nat - infos[i].size); + ASSERT(stretching || infos[i].size <= infos[i].sr.nat); + int taken = stretching ? tr_extra + : min(tr_extra, infos[i].sr.nat - infos[i].size); infos[i].size += taken; sum_taken += taken; } diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index 8f3e1f993396..b4055443acca 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -482,6 +482,8 @@ class Grid : public Container virtual SizeReq _get_preferred_size(Direction dim, int prosp_width) override; virtual void _allocate_region() override; + bool stretch_h = false, stretch_v = false; + protected: i4 get_tracks_region(int x, int y, int w, int h) const { From 4d30056526921b95583e764dec902b65bea1ea09 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 2 Jul 2018 08:15:02 +0800 Subject: [PATCH 656/864] Remove black background from high scores tile This tile is still in need of work; apart from anything else, it fills its entire 32x32 region, which makes it visually inconsistent with the other main menu entry tiles. --- .../source/rltiles/gui/startup/high_scores.png | Bin 800 -> 832 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/crawl-ref/source/rltiles/gui/startup/high_scores.png b/crawl-ref/source/rltiles/gui/startup/high_scores.png index 4ceef49fc7a4a8dc4b1c24b283ae619f2ff64da6..b0422b105e0ea2936c1bde2d8989a443820a5f03 100644 GIT binary patch delta 809 zcmV+^1J?YY2EYc8B!59rOjJcja7> z|Nnr%z+nIX|LV$Tw~-m3pis=B9Ar-oWls&(tSQT&8q1*@(WfKe0C2znU|~!Nd0!B> zkQser6XLix|Nnvi0DzzXQ0>!#*{>|Slo`I48oibprh^vFq<Gm-?cN| zv@*k*8M%@fd0!9f&U7>>2Z3b~pnesddlWJ!26S5w;kGceju@|p44-@zXHgC3#8!S} z5n@dWmUa`Fc@&s<6r_YAjc*fZQ4M!q5be{0%Agv`pc}Q17|x^~dSDRj(R;|A8oZYz z?b3hDq8mtp!NU&00DGTPE!Ct=GbNc00FH@ zL_t(I%YBgvQ`A5Zg)>K{rzcsGbp>`6Vb_Zr@B83J!GD88K|nba!Q=n`0H-^%ShbbV zRY^_yd+GN&iK3nw`Sx{pB#EjjacQDdnx+-}lXL2KdZJWPKEowRyLt8_`Ki9Ra)Y$} zr`7r8PXF$ed!%`@)oguFmCEx{L9Wzc$5ZEAMM(ed!Ld8q->zKK&Er<$t=Ssc_R?yHYBs)oOhftQoFfy;L!QIGB$^D=*6h%+UNEzPN1I4i$Jrjt7T+O<1r!P~xs5h^kTIML%vLY^+!T$dOyU^e!qQp!WM>8-P zqLF%OSu;oZOlam{?o4<=Ur^6CG;?7dy_WWls%fQ4MHO4RBZw zbXyO1UJ!X-4|!h@dSDQJV-tR45r6lq{hD00EszL_t(|+I5eIa@0T!h8Gq% zSZe5P2?r#K>E%q1jv7kN3kV1xdH{!e{}(`#ZJ03Ye}Cp|S>JbBt@}S~Umx9Ht6g8} zR0=H1vWNdp$^9swiI|^}>UwqZ^KE_9y-4{3%GF<^**odVx$F5e%Hd=*8SNK19A*XS z?wyral2!7N|Gqw(z8pF3`jUpVjOow258uDNXXcL=&ty4ISp)ZI&!(&}olaK>DZCo* z+LE7O9Dl>jg&kY-f^i57xVvY9aSRXoc3|b*4%}qDU>w7(aZBOhll6je^tX#{-RDc% zZu0rfOEM0AzF^}R9^d^Z(4het2M+}|WmvpqgB$z6HZ~4^F0ye9=dX#d(%OdyY&?cz zC)hZJ8&5@`);_hFj7NVG8jfLkNrl!vI3VNT3xA;YKFyM?J+pz0LjdURvv^g6&fdO} zj6=YJ+xuJq$DcZT-%e64RWT;x(O*98m2Y}!TD~(k4 ziQchbDYU6S&a{(=i0sb~c&{vGnC`hmiX#5}k!jHrST_y|w0000 Date: Mon, 2 Jul 2018 20:10:41 +0800 Subject: [PATCH 657/864] Add text widget background colour (console-only) --- crawl-ref/source/ui.cc | 18 ++++++++++++++---- crawl-ref/source/ui.h | 5 +++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 0252664c0cb8..9a0400a50c39 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -56,7 +56,7 @@ static inline bool pos_in_rect(i2 pos, i4 rect) } #ifndef USE_TILE_LOCAL -static void clear_text_region(i4 region); +static void clear_text_region(i4 region, COLOURS bg); #endif // must be before ui_root declaration for correct destruction order @@ -750,6 +750,8 @@ void Text::_render() vector highlights; int begin_idx = 0; + clear_text_region(m_region, m_bg_colour); + if (!hl_pat.empty()) { for (int i = 0; i < region[1]-m_region[1]; i++) @@ -851,6 +853,14 @@ void Text::_allocate_region() wrap_text_to_size(m_region[2], m_region[3]); } +#ifndef USE_TILE_LOCAL +void Text::set_bg_colour(COLOURS colour) +{ + m_bg_colour = colour; + _expose(); +} +#endif + void Image::set_tile(tile_def tile) { #ifdef USE_TILE_LOCAL @@ -1582,7 +1592,7 @@ void UIRoot::render() m_dirty_region = aabb_intersect(m_dirty_region, m_region); textcolour(LIGHTGREY); textbackground(BLACK); - clear_text_region(m_dirty_region); + clear_text_region(m_dirty_region, BLACK); #endif push_scissor(m_region); @@ -1695,14 +1705,14 @@ i4 get_scissor() } #ifndef USE_TILE_LOCAL -static void clear_text_region(i4 region) +static void clear_text_region(i4 region, COLOURS bg) { if (scissor_stack.size() > 0) region = aabb_intersect(region, scissor_stack.top()); if (region[2] <= 0 || region[3] <= 0) return; textcolour(LIGHTGREY); - textbackground(BLACK); + textbackground(bg); for (int y=region[1]; y < region[1]+region[3]; y++) { cgotoxy(region[0]+1, y+1); diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index b4055443acca..bd77234a2c97 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -386,6 +386,10 @@ class Text : public Widget bool wrap_text = false; bool ellipsize = false; +#ifndef USE_TILE_LOCAL + void set_bg_colour(COLOURS colour); +#endif + protected: void wrap_text_to_size(int width, int height); @@ -398,6 +402,7 @@ class Text : public Widget FontWrapper *m_font; #else vector m_wrapped_lines; + COLOURS m_bg_colour = BLACK; #endif i2 m_wrapped_size = { -1, -1 }; string hl_pat; From 0428708d7b8d51ea25ec69d37de207c058b2e831 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 23 Jun 2018 12:42:52 +0800 Subject: [PATCH 658/864] Add UI widget input focus --- crawl-ref/source/arena.cc | 5 +- crawl-ref/source/end.cc | 7 +- crawl-ref/source/hints.cc | 5 +- crawl-ref/source/menu.cc | 5 +- crawl-ref/source/scroller.cc | 6 +- crawl-ref/source/ui.cc | 173 ++++++++++++++++++++----------- crawl-ref/source/ui.h | 15 ++- crawl-ref/source/windowmanager.h | 2 + 8 files changed, 137 insertions(+), 81 deletions(-) diff --git a/crawl-ref/source/arena.cc b/crawl-ref/source/arena.cc index 8dd57338e124..90088f42f74a 100644 --- a/crawl-ref/source/arena.cc +++ b/crawl-ref/source/arena.cc @@ -1482,8 +1482,9 @@ static void _choose_arena_teams(newgame_def& choice, bool done = false; bool cancel = false; auto prompt_ui = make_shared(); + auto popup = make_shared(prompt_ui); - prompt_ui->on(Widget::slots.event, [&](wm_event ev) { + popup->on(Widget::slots.event, [&](wm_event ev) { if (ev.type != WME_KEYDOWN) return false; int key = ev.key.keysym.sym; @@ -1499,7 +1500,7 @@ static void _choose_arena_teams(newgame_def& choice, return done = true; }); - auto popup = make_shared(prompt_ui); + ui::set_focused_widget(popup.get()); ui::push_layout(move(popup)); while (!done && !crawl_state.seen_hups) { diff --git a/crawl-ref/source/end.cc b/crawl-ref/source/end.cc index 8839dae2d3b8..15c077af93fd 100644 --- a/crawl-ref/source/end.cc +++ b/crawl-ref/source/end.cc @@ -476,15 +476,14 @@ NORETURN void end_game(scorefile_entry &se) morgue_directory().c_str()); #endif + mouse_control mc(MOUSE_MODE_MORE); auto prompt_ui = make_shared(formatted_string::parse_string(goodbye_msg)); + auto popup = make_shared(prompt_ui); bool done = false; - prompt_ui->on(Widget::slots.event, [&](wm_event ev) { + popup->on(Widget::slots.event, [&](wm_event ev) { return done = ev.type == WME_KEYDOWN; }); - mouse_control mc(MOUSE_MODE_MORE); - auto popup = make_shared(prompt_ui); - if (!crawl_state.seen_hups && !crawl_state.disables[DIS_CONFIRMATIONS]) ui::run_layout(move(popup), done); diff --git a/crawl-ref/source/hints.cc b/crawl-ref/source/hints.cc index e27713f7fe13..0306e0b0f387 100644 --- a/crawl-ref/source/hints.cc +++ b/crawl-ref/source/hints.cc @@ -175,10 +175,11 @@ void pick_hints(newgame_def& choice) "\n* - Random hints mode character" ""; auto prompt_ui = make_shared(formatted_string::parse_string(prompt)); + auto popup = make_shared(prompt_ui); bool done = false; int keyn; - prompt_ui->on(Widget::slots.event, [&](wm_event ev) { + popup->on(Widget::slots.event, [&](wm_event ev) { if (ev.type != WME_KEYDOWN) return false; keyn = ev.key.keysym.sym; @@ -208,8 +209,6 @@ void pick_hints(newgame_def& choice) return true; } }); - - auto popup = make_shared(prompt_ui); ui::run_layout(move(popup), done); switch (keyn) diff --git a/crawl-ref/source/menu.cc b/crawl-ref/source/menu.cc index e63871aa95a7..f1b9796b95ad 100644 --- a/crawl-ref/source/menu.cc +++ b/crawl-ref/source/menu.cc @@ -703,7 +703,7 @@ bool UIMenu::on_event(const wm_event& event) wm_event ev = {0}; ev.type = WME_KEYDOWN; ev.key.keysym.sym = key; - on_event(ev); + m_menu->m_ui.popup->on_event(ev); } return true; @@ -1002,7 +1002,7 @@ void Menu::do_menu() bool done = false; m_ui.popup = make_shared(m_ui.vbox, this); - m_ui.menu->on(Widget::slots.event, [this, &done](wm_event ev) { + m_ui.popup->on(Widget::slots.event, [this, &done](wm_event ev) { if (ev.type != WME_KEYDOWN) return false; if (m_filter) @@ -1035,6 +1035,7 @@ void Menu::do_menu() update_menu(); ui::push_layout(m_ui.popup, m_kmc); + ui::set_focused_widget(m_ui.popup.get()); #ifdef USE_TILE_WEB tiles.push_menu(this); diff --git a/crawl-ref/source/scroller.cc b/crawl-ref/source/scroller.cc index 0f163ec536a1..9438ac580462 100644 --- a/crawl-ref/source/scroller.cc +++ b/crawl-ref/source/scroller.cc @@ -115,7 +115,7 @@ int formatted_scroller::show() m_contents_dirty = false; bool done = false; - popup->on(Widget::slots.event, [&done, &vbox, &text, this](wm_event ev) { + popup->on(Widget::slots.event, [&done, &text, this](wm_event ev) { if (ev.type != WME_KEYDOWN) return false; // allow default event handling m_lastch = ev.key.keysym.sym; @@ -138,11 +138,11 @@ int formatted_scroller::show() } if (done) return true; - if (vbox->on_event(ev)) + if (m_scroller->on_event(ev)) return true; if (m_flags & FS_EASY_EXIT) return done = true; - return false; + return true; }); #ifdef USE_TILE_WEB diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 9a0400a50c39..45a91412ba82 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -73,6 +73,14 @@ static struct UIRoot }; size_t num_children() const { return m_root.num_children(); }; + bool widget_is_in_layout(const Widget* w) + { + for (; w; w = w->_get_parent()) + if (w == &m_root) + return true; + return false; + } + void resize(int w, int h); void layout(); void render(); @@ -94,6 +102,8 @@ static struct UIRoot vector keymap_stack; vector cutoff_stack; + Widget* focused_widget = nullptr; + protected: int m_w, m_h; i4 m_region; @@ -106,27 +116,17 @@ static stack scissor_stack; struct Widget::slots Widget::slots = {}; -bool Widget::on_event(const wm_event& event) +Widget::~Widget() { - return Widget::slots.event.emit(this, event); + Widget::slots.event.remove_by_target(this); + if (get_focused_widget() == this) + set_focused_widget(nullptr); + _set_parent(nullptr); } -static inline bool _maybe_propagate_event(wm_event event, shared_ptr &child) +bool Widget::on_event(const wm_event& event) { -#ifdef USE_TILE_LOCAL - /* WME_MOUSELEAVE is conspicuously absent because it is emitted - * only on widgets that the cursor just left */ - if (event.type == WME_MOUSEMOTION - || event.type == WME_MOUSEENTER - || event.type == WME_MOUSEBUTTONDOWN - || event.type == WME_MOUSEBUTTONUP) - { - i2 pos = {(int)event.mouse_event.px, (int)event.mouse_event.py}; - if (!pos_in_rect(pos, child->get_region())) - return false; - } -#endif - return child->on_event(event); + return Widget::slots.event.emit(this, event); } shared_ptr ContainerVec::get_child_at_offset(int x, int y) @@ -142,25 +142,6 @@ shared_ptr ContainerVec::get_child_at_offset(int x, int y) return nullptr; } -bool Container::on_event(const wm_event& event) -{ - if (Widget::on_event(event)) - return true; - for (shared_ptr &child : *this) - if (_maybe_propagate_event(event, child)) - return true; - return false; -} - -bool Bin::on_event(const wm_event& event) -{ - if (Widget::on_event(event)) - return true; - if (_maybe_propagate_event(event, m_child)) - return true; - return false; -} - shared_ptr Bin::get_child_at_offset(int x, int y) { bool inside = (x > m_region[0] && x < m_region[0] + m_region[2]) @@ -906,19 +887,31 @@ SizeReq Image::_get_preferred_size(Direction dim, int prosp_width) void Stack::add_child(shared_ptr child) { + bool adjust_focus = ui_root.widget_is_in_layout(get_focused_widget()); + + if (adjust_focus) + set_focused_widget(nullptr); + Widget* child_ui = child.get(); child->_set_parent(this); m_children.push_back(move(child)); _invalidate_sizereq(); _queue_allocation(); + if (adjust_focus || ui_root.num_children() == 0) + set_focused_widget(child_ui); } void Stack::pop_child() { if (!m_children.size()) return; + bool adjust_focus = ui_root.widget_is_in_layout(m_children.back().get()); + if (adjust_focus) + set_focused_widget(nullptr); m_children.pop_back(); _invalidate_sizereq(); _queue_allocation(); + if (adjust_focus && !m_children.empty()) + set_focused_widget(m_children.front().get()); } shared_ptr Stack::get_child_at_offset(int x, int y) @@ -962,17 +955,11 @@ void Stack::_allocate_region() } } -bool Stack::on_event(const wm_event& event) -{ - if (Widget::on_event(event)) - return true; - if (m_children.size() > 0 &&_maybe_propagate_event(event, m_children.back())) - return true; - return false; -} - void Switcher::add_child(shared_ptr child) { + // TODO XXX: if there's a focused widget + // - it must be in the current top child + // - unfocus it before we child->_set_parent(this); m_children.push_back(move(child)); _invalidate_sizereq(); @@ -981,6 +968,8 @@ void Switcher::add_child(shared_ptr child) int& Switcher::current() { + // TODO XXX: we need to update the focused widget + // so we need an API change _expose(); return m_current; } @@ -1018,16 +1007,6 @@ void Switcher::_allocate_region() } } -bool Switcher::on_event(const wm_event& event) -{ - if (Widget::on_event(event)) - return true; - m_current = max(0, min(m_current, (int)m_children.size())); - if (m_children.size() > 0 &&_maybe_propagate_event(event, m_children[m_current])) - return true; - return false; -} - shared_ptr Grid::get_child_at_offset(int x, int y) { int lx = x - m_region[0]; @@ -1633,6 +1612,7 @@ void UIRoot::send_mouse_enter_leave_events(int mx, int my) current = current->get_child_at_offset(mx, my); } + size_t new_hover_path_size = hover_path.size(); size_t sz = max(prev_hover_path.size(), hover_path.size()); prev_hover_path.resize(sz, nullptr); hover_path.resize(sz, nullptr); @@ -1652,24 +1632,63 @@ void UIRoot::send_mouse_enter_leave_events(int mx, int my) { ev.type = WME_MOUSELEAVE; if (!event_filter || !event_filter(ev)) - prev_hover_path[diff]->on_event(ev); + for (size_t i = sz; i > diff; --i) + { + if (!prev_hover_path[i-1]) + continue; + prev_hover_path[i-1]->on_event(ev); + } } if (hover_path[diff]) { ev.type = WME_MOUSEENTER; if (!event_filter || !event_filter(ev)) - hover_path[diff]->on_event(ev); + for (size_t i = diff; i < sz; ++i) + { + if (!hover_path[i]) + break; + hover_path[i]->on_event(ev); + } } } prev_hover_path = move(hover_path); + prev_hover_path.resize(new_hover_path_size); } bool UIRoot::on_event(const wm_event& event) { if (event_filter && event_filter(event)) return true; - return m_root.on_event(event); + + switch (event.type) + { + case WME_MOUSEBUTTONDOWN: + case WME_MOUSEBUTTONUP: + case WME_MOUSEMOTION: + case WME_MOUSEWHEEL: + for (auto w = prev_hover_path.rbegin(); w != prev_hover_path.rend(); ++w) + if ((*w)->on_event(event)) + return true; + break; + case WME_MOUSEENTER: + case WME_MOUSELEAVE: + die("unreachable"); + break; + default: + size_t layer_idx = m_root.num_children(); + if (!layer_idx) + return false; + Widget* layer_root = m_root.get_child(layer_idx-1).get(); + if (layer_root->on_event(event)) + return true; + for (Widget* w = focused_widget; w && w != layer_root; w = w->_get_parent()) + if (w->on_event(event)) + return true; + break; + } + + return false; } void push_scissor(i4 scissor) @@ -2119,4 +2138,42 @@ formatted_string progress_popup::get_progress_string(unsigned int len) return formatted_string::parse_string(bar); } +void set_focused_widget(Widget* w) +{ + static bool sent_focusout; + static Widget* new_focus; + + if (w == ui_root.focused_widget) + return; + + new_focus = w; + + if (ui_root.focused_widget && !sent_focusout) + { + sent_focusout = true; + wm_event ev = {0}; + ev.type = WME_FOCUSOUT; + ui_root.focused_widget->on_event(ev); + } + + if (new_focus != w) + return; + + ui_root.focused_widget = new_focus; + + sent_focusout = false; + + if (new_focus) + { + wm_event ev = {0}; + ev.type = WME_FOCUSIN; + new_focus->on_event(ev); + } +} + +Widget* get_focused_widget() +{ + return ui_root.focused_widget; +} + } diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index bd77234a2c97..46558af32a46 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -100,10 +100,7 @@ class Widget VERT, }; - virtual ~Widget() { - Widget::slots.event.remove_by_target(this); - _set_parent(nullptr); - } + virtual ~Widget(); i4 margin = {0,0,0,0}; int flex_grow = 1; @@ -118,6 +115,7 @@ class Widget virtual SizeReq _get_preferred_size(Direction dim, int prosp_width); virtual void _allocate_region(); void _set_parent(Widget* p); + Widget* _get_parent() const { return m_parent; }; void _invalidate_sizereq(bool immediate = true); void _queue_allocation(bool immediate = true); void set_allocation_needed() { alloc_queued = true; }; @@ -154,6 +152,7 @@ class Widget Slot event; } slots; + // XXX: add documentation virtual shared_ptr get_child_at_offset(int x, int y) { return nullptr; }; @@ -224,8 +223,6 @@ class Container : public Widget iter_impl *it; }; - virtual bool on_event(const wm_event& event) override; - public: virtual iterator begin() = 0; virtual iterator end() = 0; @@ -238,7 +235,6 @@ class Bin : public Container if (m_child) _unparent(m_child); }; - virtual bool on_event(const wm_event& event) override; void set_child(shared_ptr child); virtual shared_ptr get_child() { return m_child; }; virtual shared_ptr get_child_at_offset(int x, int y) override; @@ -441,7 +437,6 @@ class Stack : public ContainerVec virtual void _render() override; virtual SizeReq _get_preferred_size(Direction dim, int prosp_width) override; virtual void _allocate_region() override; - virtual bool on_event(const wm_event& event) override; }; class Switcher : public ContainerVec @@ -454,7 +449,6 @@ class Switcher : public ContainerVec virtual void _render() override; virtual SizeReq _get_preferred_size(Direction dim, int prosp_width) override; virtual void _allocate_region() override; - virtual bool on_event(const wm_event& event) override; protected: int m_current; @@ -636,6 +630,9 @@ void push_scissor(i4 scissor); void pop_scissor(); i4 get_scissor(); +void set_focused_widget(Widget* w); +Widget* get_focused_widget(); + // XXX: this is a hack used to ensure that when switching to a // layout-based UI, the starting window size is correct. This is necessary // because there's no way to query TilesFramework for the current screen size diff --git a/crawl-ref/source/windowmanager.h b/crawl-ref/source/windowmanager.h index ddc1ecb959c6..032927f721c2 100644 --- a/crawl-ref/source/windowmanager.h +++ b/crawl-ref/source/windowmanager.h @@ -22,6 +22,8 @@ enum wm_event_type WME_RESIZE, WME_EXPOSE, WME_MOVE, + WME_FOCUSIN, + WME_FOCUSOUT, WME_NUMEVENTS = 15 }; From b86fa12273cda752f3db7d70c6225d3a92897e9e Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Wed, 15 Aug 2018 20:11:55 +0800 Subject: [PATCH 659/864] Add add_event_filter() --- crawl-ref/source/ui.cc | 22 +++++++++++++++++++--- crawl-ref/source/ui.h | 25 ++++++++++++++++++++++--- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 45a91412ba82..93df9b097416 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -1371,7 +1371,7 @@ bool Scroller::on_event(const wm_event& event) return false; } -Popup::Popup(shared_ptr child) +Layout::Layout(shared_ptr child) { #ifdef USE_TILE_LOCAL m_depth = ui_root.num_children(); @@ -1381,6 +1381,21 @@ Popup::Popup(shared_ptr child) expand_h = expand_v = true; } +void Layout::_render() +{ + m_child->render(); +} + +SizeReq Layout::_get_preferred_size(Direction dim, int prosp_width) +{ + return m_child->get_preferred_size(dim, prosp_width); +} + +void Layout::_allocate_region() +{ + m_child->allocate_region(m_region); +} + void Popup::_render() { #ifdef USE_TILE_LOCAL @@ -1680,9 +1695,10 @@ bool UIRoot::on_event(const wm_event& event) if (!layer_idx) return false; Widget* layer_root = m_root.get_child(layer_idx-1).get(); - if (layer_root->on_event(event)) + Layout* layout = dynamic_cast(layer_root); + if (layout && layout->event_filters.emit(layout, event)) return true; - for (Widget* w = focused_widget; w && w != layer_root; w = w->_get_parent()) + for (Widget* w = focused_widget; w; w = w->_get_parent()) if (w->on_event(event)) return true; break; diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index 46558af32a46..e41c9dfa70f3 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -564,10 +564,30 @@ class Scroller : public Bin #endif }; -class Popup : public Bin +class Layout : public Bin { + friend struct UIRoot; public: - Popup(shared_ptr child); + Layout(shared_ptr child); + virtual void _render() override; + virtual SizeReq _get_preferred_size(Direction dim, int prosp_width) override; + virtual void _allocate_region() override; + + void add_event_filter(function handler) + { + event_filters.on(this, handler); + } +protected: +#ifdef USE_TILE_LOCAL + int m_depth; +#endif + Slot event_filters; +}; + +class Popup : public Layout +{ +public: + Popup(shared_ptr child) : Layout(move(child)) {}; virtual void _render() override; virtual SizeReq _get_preferred_size(Direction dim, int prosp_width) override; virtual void _allocate_region() override; @@ -577,7 +597,6 @@ class Popup : public Bin protected: #ifdef USE_TILE_LOCAL ShapeBuffer m_buf; - int m_depth; static constexpr int m_depth_indent = 20; static constexpr int m_base_margin = 50; static constexpr int m_padding = 23; From f253313b81aa63026fab195a1033cb57a387ae1a Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 20 Aug 2018 21:40:04 +0800 Subject: [PATCH 660/864] Add per-layer focus --- crawl-ref/source/ui.cc | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 93df9b097416..ec03000718f7 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -101,8 +101,7 @@ static struct UIRoot bool needs_paint; vector keymap_stack; vector cutoff_stack; - - Widget* focused_widget = nullptr; + vector focus_stack; protected: int m_w, m_h; @@ -119,7 +118,7 @@ struct Widget::slots Widget::slots = {}; Widget::~Widget() { Widget::slots.event.remove_by_target(this); - if (get_focused_widget() == this) + if (m_parent && get_focused_widget() == this) set_focused_widget(nullptr); _set_parent(nullptr); } @@ -887,31 +886,19 @@ SizeReq Image::_get_preferred_size(Direction dim, int prosp_width) void Stack::add_child(shared_ptr child) { - bool adjust_focus = ui_root.widget_is_in_layout(get_focused_widget()); - - if (adjust_focus) - set_focused_widget(nullptr); - Widget* child_ui = child.get(); child->_set_parent(this); m_children.push_back(move(child)); _invalidate_sizereq(); _queue_allocation(); - if (adjust_focus || ui_root.num_children() == 0) - set_focused_widget(child_ui); } void Stack::pop_child() { if (!m_children.size()) return; - bool adjust_focus = ui_root.widget_is_in_layout(m_children.back().get()); - if (adjust_focus) - set_focused_widget(nullptr); m_children.pop_back(); _invalidate_sizereq(); _queue_allocation(); - if (adjust_focus && !m_children.empty()) - set_focused_widget(m_children.front().get()); } shared_ptr Stack::get_child_at_offset(int x, int y) @@ -1496,6 +1483,10 @@ SizeReq Dungeon::_get_preferred_size(Direction dim, int prosp_width) void UIRoot::push_child(shared_ptr ch, KeymapContext km) { + if (auto popup = dynamic_cast(ch.get())) + focus_stack.push_back(popup->get_child().get()); + else + focus_stack.push_back(ch.get()); m_root.add_child(move(ch)); m_needs_layout = true; keymap_stack.push_back(km); @@ -1513,6 +1504,7 @@ void UIRoot::pop_child() m_root.pop_child(); m_needs_layout = true; keymap_stack.pop_back(); + focus_stack.pop_back(); #ifndef USE_TILE_LOCAL if (m_root.num_children() == 0) clrscr(); @@ -1698,7 +1690,7 @@ bool UIRoot::on_event(const wm_event& event) Layout* layout = dynamic_cast(layer_root); if (layout && layout->event_filters.emit(layout, event)) return true; - for (Widget* w = focused_widget; w; w = w->_get_parent()) + for (Widget* w = focus_stack.back(); w; w = w->_get_parent()) if (w->on_event(event)) return true; break; @@ -2159,23 +2151,28 @@ void set_focused_widget(Widget* w) static bool sent_focusout; static Widget* new_focus; - if (w == ui_root.focused_widget) + if (!ui_root.num_children()) + return; + + auto current_focus = ui_root.focus_stack.back(); + + if (w == current_focus) return; new_focus = w; - if (ui_root.focused_widget && !sent_focusout) + if (current_focus && !sent_focusout) { sent_focusout = true; wm_event ev = {0}; ev.type = WME_FOCUSOUT; - ui_root.focused_widget->on_event(ev); + current_focus->on_event(ev); } if (new_focus != w) return; - ui_root.focused_widget = new_focus; + ui_root.focus_stack.back() = new_focus; sent_focusout = false; @@ -2189,7 +2186,7 @@ void set_focused_widget(Widget* w) Widget* get_focused_widget() { - return ui_root.focused_widget; + return ui_root.focus_stack.empty() ? nullptr : ui_root.focus_stack.back(); } } From 72f1adce67d3447478acc920754e8f83e621a510 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 23 Jun 2018 12:52:56 +0800 Subject: [PATCH 661/864] Add debug drawing --- crawl-ref/source/ui.cc | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index ec03000718f7..96b7618f5412 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -99,6 +99,7 @@ static struct UIRoot void send_mouse_enter_leave_events(int mx, int my); bool needs_paint; + bool debug_draw = false; vector keymap_stack; vector cutoff_stack; vector focus_stack; @@ -1587,6 +1588,25 @@ void UIRoot::render() ASSERT(cutoff <= static_cast(m_root.num_children())); for (int i = cutoff; i < static_cast(m_root.num_children()); i++) m_root.get_child(i)->render(); + if (debug_draw) + { + LineBuffer lb; + size_t i = 0; + for (const auto& w : prev_hover_path) + { + i4 r = w->get_region(); + i++; + VColour lc; + lc = i == prev_hover_path.size() ? + VColour(255, 100, 0, 100) : VColour(0, 50 + i*40, 0, 100); + lb.add_square(r[0]+1, r[1]+1, r[0]+r[2], r[1]+r[3], lc); + } + if (auto w = get_focused_widget()) { + i4 r = w->get_region(); + lb.add_square(r[0]+1, r[1]+1, r[0]+r[2], r[1]+r[3], VColour(128,31,239,255)); + } + lb.draw(); + } #else // Render only the top of the UI stack on console if (m_root.num_children() > 0) @@ -1668,11 +1688,24 @@ bool UIRoot::on_event(const wm_event& event) if (event_filter && event_filter(event)) return true; + if (event.type == WME_KEYDOWN && event.key.keysym.sym == CK_INSERT) + { + ui_root.debug_draw = !ui_root.debug_draw; + ui_root.queue_layout(); + ui_root.expose_region({0,0,INT_MAX,INT_MAX}); + return true; + } + switch (event.type) { case WME_MOUSEBUTTONDOWN: case WME_MOUSEBUTTONUP: case WME_MOUSEMOTION: + if (ui_root.debug_draw) + { + ui_root.queue_layout(); + ui_root.expose_region({0,0,INT_MAX,INT_MAX}); + } case WME_MOUSEWHEEL: for (auto w = prev_hover_path.rbegin(); w != prev_hover_path.rend(); ++w) if ((*w)->on_event(event)) From 7134dd49da74b04e3130e2b476b7f8b5b2469e2b Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Tue, 3 Jul 2018 08:09:32 +0800 Subject: [PATCH 662/864] Add OuterMenu, MenuButton widgets --- crawl-ref/source/MSVC/crawl.vcxproj | 2 + crawl-ref/source/Makefile.obj | 1 + crawl-ref/source/outer-menu.cc | 291 ++++++++++++++++++++++++++++ crawl-ref/source/outer-menu.h | 78 ++++++++ 4 files changed, 372 insertions(+) create mode 100644 crawl-ref/source/outer-menu.cc create mode 100644 crawl-ref/source/outer-menu.h diff --git a/crawl-ref/source/MSVC/crawl.vcxproj b/crawl-ref/source/MSVC/crawl.vcxproj index 355cd1ea661c..6431485ac605 100644 --- a/crawl-ref/source/MSVC/crawl.vcxproj +++ b/crawl-ref/source/MSVC/crawl.vcxproj @@ -687,6 +687,7 @@ perl.exe "util/gen-cflg.pl" compflag.h "<UNKNOWN>" "<UNKNOWN>" + @@ -1085,6 +1086,7 @@ perl.exe "util/gen-cflg.pl" compflag.h "<UNKNOWN>" "<UNKNOWN>" + diff --git a/crawl-ref/source/Makefile.obj b/crawl-ref/source/Makefile.obj index 9944d3f3b9d8..75f74a62e18e 100644 --- a/crawl-ref/source/Makefile.obj +++ b/crawl-ref/source/Makefile.obj @@ -175,6 +175,7 @@ ng-wanderer.o \ notes.o \ orb.o \ ouch.o \ +outer-menu.o \ output.o \ package.o \ pattern.o \ diff --git a/crawl-ref/source/outer-menu.cc b/crawl-ref/source/outer-menu.cc new file mode 100644 index 000000000000..f3e5883b2390 --- /dev/null +++ b/crawl-ref/source/outer-menu.cc @@ -0,0 +1,291 @@ +/** + * @file + * @brief Menu button used in non-game menus +**/ + +#include "AppHdr.h" + +#include "cio.h" +#include "outer-menu.h" +#include "tileweb.h" + +using namespace ui; + +bool MenuButton::focus_on_mouse = false; + +void MenuButton::_render() +{ +#ifdef USE_TILE_LOCAL + m_buf.draw(); + m_line_buf.draw(); +#endif + m_child->render(); +} + +SizeReq MenuButton::_get_preferred_size(Direction dim, int prosp_width) +{ + return m_child->get_preferred_size(dim, prosp_width); +} + +void MenuButton::_allocate_region() +{ + m_child->allocate_region(m_region); +#ifdef USE_TILE_LOCAL + m_buf.clear(); + m_line_buf.clear(); + if (focused) + { + const VColour bg = active ? + VColour(0, 0, 0, 255) : VColour(255, 255, 255, 25); + m_buf.add(m_region[0], m_region[1], + m_region[0]+m_region[2], m_region[1]+m_region[3], bg); + const VColour mouse_colour = active ? + VColour(34, 34, 34, 255) : term_colours[highlight_colour]; + m_line_buf.add_square(m_region[0]+1, m_region[1]+1, + m_region[0]+m_region[2], m_region[1]+m_region[3], mouse_colour); + } +#endif +} + +bool MenuButton::on_event(const wm_event& event) +{ + if (Bin::on_event(event)) + return true; + + bool old_focused = focused, old_active = active; + + if (event.type == WME_MOUSEENTER && focus_on_mouse) + ui::set_focused_widget(this); + if (event.type == WME_MOUSEMOTION) + ui::set_focused_widget(this); + + if (event.type == WME_FOCUSIN) + focused = true; + if (event.type == WME_FOCUSOUT) + focused = false; + +#ifdef USE_TILE_LOCAL + if (event.type == WME_MOUSEENTER) + wm->set_mouse_cursor(MOUSE_CURSOR_POINTER); + if (event.type == WME_MOUSELEAVE) + wm->set_mouse_cursor(MOUSE_CURSOR_ARROW); +#endif + + if (event.type == WME_MOUSEBUTTONDOWN && event.mouse_event.button == MouseEvent::LEFT) + active = true; + if (event.type == WME_MOUSEBUTTONUP && event.mouse_event.button == MouseEvent::LEFT) + active = false; + + if (old_focused != focused || old_active != active) + _queue_allocation(); + + return old_active != active; +} + +OuterMenu::OuterMenu(bool can_shrink, int width, int height) +{ + m_grid = make_shared(); + m_grid->stretch_h = true; + + m_grid->on(Widget::slots.event, [this](wm_event ev){ + return this->scroller_event_hook(ev); + }); + + if (can_shrink) + { + auto scroller = make_shared(); + scroller->set_child(m_grid); + m_root = move(scroller); + } + else + m_root = m_grid; + + m_root->_set_parent(this); + + m_width = width; + m_height = height; + m_buttons.resize(width * height, nullptr); +} + +void OuterMenu::_render() +{ + m_root->render(); +} + +SizeReq OuterMenu::_get_preferred_size(Direction dim, int prosp_width) +{ + return m_root->get_preferred_size(dim, prosp_width); +} + +void OuterMenu::_allocate_region() +{ + if (!have_allocated && on_button_activated) + { + have_allocated = true; + Layout *layout = nullptr; + for (Widget *w = _get_parent(); w && !layout; w = w->_get_parent()) + layout = dynamic_cast(w); + ASSERT(layout); + layout->add_event_filter([this](wm_event ev) { + if (ev.type != WME_KEYDOWN) + return false; + for (const auto& btn : this->m_buttons) + if (btn && ev.key.keysym.sym == btn->hotkey) + { + this->on_button_activated(btn->id); + return true; + } + return false; + }); + if (m_initial_focus) + scroll_button_into_view(m_initial_focus); + } + m_root->allocate_region(m_region); +} + +bool OuterMenu::on_event(const wm_event& event) +{ + return Widget::on_event(event); +} + +void OuterMenu::add_label(shared_ptr label, int x, int y) +{ + ASSERT(x >= 0 && x < m_width); + ASSERT(y >= 0 && y < m_height); + ASSERT(m_buttons[y*m_width + x] == nullptr); + m_grid->add_child(move(label), x, y); +} + +void OuterMenu::add_button(shared_ptr btn, int x, int y) +{ + ASSERT(x >= 0 && x < m_width); + ASSERT(y >= 0 && y < m_height); + + MenuButton*& item = m_buttons[y*m_width + x]; + ASSERT(item == nullptr); + item = btn.get(); + + const int btn_id = btn->id; + btn->on(Widget::slots.event, [btn_id, this, x, y](const wm_event& ev) { + if (on_button_activated) + if ((ev.type == WME_MOUSEBUTTONUP + && ev.mouse_event.button == MouseEvent::LEFT) + || (ev.type == WME_KEYDOWN && ev.key.keysym.sym == CK_ENTER)) + { + this->on_button_activated(btn_id); + return ev.type == WME_KEYDOWN; // button needs to catch clicks + } +#ifndef USE_TILE_LOCAL + if (ev.type == WME_FOCUSIN || ev.type == WME_FOCUSOUT) + { + auto btn2 = this->m_buttons[y*this->m_width+x]; + if (auto tw = dynamic_cast(btn2->get_child().get())) + tw->set_bg_colour(ev.type == WME_FOCUSIN ? LIGHTGREY : BLACK); + } +#endif + return false; + }); + + m_grid->add_child(move(btn), x, y); +} + +void OuterMenu::scroll_button_into_view(MenuButton *btn) +{ + ui::set_focused_widget(btn); + Widget* gp = btn->_get_parent()->_get_parent(); + Scroller* scroller = dynamic_cast(gp); + if (!scroller) + return; + i4 btn_reg = btn->get_region(), scr_reg = scroller->get_region(); + +#ifdef USE_TILE_LOCAL + constexpr int shade_height = 12; +#else + constexpr int shade_height = 0; +#endif + + const int btn_top = btn_reg[1], btn_bot = btn_top + btn_reg[3], + scr_top = scr_reg[1] + shade_height, + scr_bot = scr_reg[1] + scr_reg[3] - shade_height; + const int delta = btn_top < scr_top ? btn_top - scr_top : + btn_bot > scr_bot ? btn_bot - scr_bot : 0; + scroller->set_scroll(scroller->get_scroll() + delta); +} + +bool OuterMenu::move_button_focus(int fx, int fy, int dx, int dy) +{ + MenuButton* btn = nullptr; + int nx, ny; + for (nx = fx+dx, ny = fy+dy; + nx >= 0 && nx < m_width && ny >= 0 && ny < m_height; + nx += dx, ny += dy) + { + if (m_buttons[ny*m_width + nx]) + { + btn = m_buttons[ny*m_width + nx]; + break; + } + } + + if (btn) + scroll_button_into_view(btn); + else + { + int idx = dx == 0 ? 1+dy : 2-dx; // dx,dy --> CSS direction index + if (auto linked = linked_menus[idx].lock()) + { + int lfx = dx == 0 ? min(fx, linked->m_width-1) : dx < 0 ? linked->m_width : -1; + int lfy = dy == 0 ? min(fy, linked->m_height-1) : dy < 0 ? linked->m_height : -1; + return linked->move_button_focus(lfx, lfy, dx, dy); + } + } + return btn != nullptr; +} + +bool OuterMenu::scroller_event_hook(const wm_event& ev) +{ + MenuButton::focus_on_mouse = ev.type == WME_MOUSEWHEEL + || ev.type == WME_KEYDOWN && ev.key.keysym.sym == CK_PGDN + || ev.type == WME_KEYDOWN && ev.key.keysym.sym == CK_PGUP; + + if (ev.type != WME_KEYDOWN) + return false; + int key = ev.key.keysym.sym; + + if (key == CK_DOWN || key == CK_UP || key == CK_LEFT || key == CK_RIGHT) + { + const int dx = key == CK_LEFT ? -1 : key == CK_RIGHT ? 1 : 0; + const int dy = key == CK_UP ? -1 : key == CK_DOWN ? 1 : 0; + ASSERT((dx == 0) != (dy == 0)); + + const Widget* focus = ui::get_focused_widget(); + int fx = -1, fy = -1; + for (int x = 0; x < m_width; x++) + for (int y = 0; y < m_height; y++) + if (focus == m_buttons[y*m_width + x]) + { + fx = x; + fy = y; + break; + } + ASSERT(fx >= 0 && fy >= 0); + + return move_button_focus(fx, fy, dx, dy); + } + + return false; +} + +MenuButton* OuterMenu::get_button(int x, int y) +{ + ASSERT(x >= 0 && x < m_width); + ASSERT(y >= 0 && y < m_height); + return m_buttons[y*m_width + x]; +} + +MenuButton* OuterMenu::get_button_by_id(int id) +{ + auto it = find_if(m_buttons.begin(), m_buttons.end(), + [id](MenuButton*& btn) { return btn && btn->id == id; }); + return it == m_buttons.end() ? nullptr : *it; +} diff --git a/crawl-ref/source/outer-menu.h b/crawl-ref/source/outer-menu.h new file mode 100644 index 000000000000..618ae9eb0423 --- /dev/null +++ b/crawl-ref/source/outer-menu.h @@ -0,0 +1,78 @@ +/** + * @file + * @brief Menu button used in non-game menus +**/ + +#pragma once + +#include "ui.h" +#include "tilefont.h" + +class MenuButton : public ui::Bin +{ + friend class OuterMenu; +public: + MenuButton() {}; + + virtual void _render() override; + virtual ui::SizeReq _get_preferred_size(ui::Widget::Direction, int) override; + virtual void _allocate_region() override; + virtual bool on_event(const wm_event& event) override; + + int id = 0; + int hotkey = 0; + COLOURS highlight_colour = LIGHTGREY; + +protected: + bool focused = false; + bool active = false; +#ifdef USE_TILE_LOCAL + ShapeBuffer m_buf; + LineBuffer m_line_buf; +#endif + static bool focus_on_mouse; +}; + +class OuterMenu : public ui::Widget +{ +public: + OuterMenu(bool can_shrink, int width, int height); + + virtual void _render() override; + virtual ui::SizeReq _get_preferred_size(ui::Widget::Direction, int) override; + virtual void _allocate_region() override; + virtual bool on_event(const wm_event& event) override; + + virtual shared_ptr get_child_at_offset(int x, int y) override { + return m_root; + } + + void add_button(shared_ptr btn, int x, int y); + void add_label(shared_ptr label, int x, int y); + MenuButton* get_button(int x, int y); + MenuButton* get_button_by_id(int id); + const vector& get_buttons() { return m_buttons; }; + void set_initial_focus(MenuButton *btn) { + ASSERT(!have_allocated); + m_initial_focus = btn; + }; + + void scroll_button_into_view(MenuButton *btn); + + function on_button_activated; + + weak_ptr linked_menus[4]; + +protected: + bool scroller_event_hook(const wm_event& ev); + bool move_button_focus(int fx, int fy, int dx, int dy); + + shared_ptr m_grid; + shared_ptr m_root; + vector m_buttons; + int m_width; + int m_height; + MenuButton* m_initial_focus {nullptr}; + + bool have_allocated {false}; +}; From 99709490d101e04d283636fa73c42cd6c939f160 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sun, 19 Aug 2018 13:17:09 +0800 Subject: [PATCH 663/864] Add descriptions to outer menu buttons --- crawl-ref/source/outer-menu.cc | 11 +++++++++++ crawl-ref/source/outer-menu.h | 3 +++ 2 files changed, 14 insertions(+) diff --git a/crawl-ref/source/outer-menu.cc b/crawl-ref/source/outer-menu.cc index f3e5883b2390..018aa68cce90 100644 --- a/crawl-ref/source/outer-menu.cc +++ b/crawl-ref/source/outer-menu.cc @@ -105,6 +105,7 @@ OuterMenu::OuterMenu(bool can_shrink, int width, int height) m_width = width; m_height = height; m_buttons.resize(width * height, nullptr); + m_description_indexes.resize(width * height, -1); } void OuterMenu::_render() @@ -175,6 +176,8 @@ void OuterMenu::add_button(shared_ptr btn, int x, int y) this->on_button_activated(btn_id); return ev.type == WME_KEYDOWN; // button needs to catch clicks } + if (ev.type == WME_FOCUSIN && m_description_indexes[y*this->m_width+x] != -1) + descriptions->current() = m_description_indexes[y*this->m_width+x]; #ifndef USE_TILE_LOCAL if (ev.type == WME_FOCUSIN || ev.type == WME_FOCUSOUT) { @@ -186,6 +189,14 @@ void OuterMenu::add_button(shared_ptr btn, int x, int y) return false; }); + if (descriptions) + { + auto desc_text = make_shared(formatted_string(btn->description, WHITE)); + desc_text->wrap_text = true; + descriptions->add_child(move(desc_text)); + m_description_indexes[y*m_width + x] = descriptions->num_children()-1; + } + m_grid->add_child(move(btn), x, y); } diff --git a/crawl-ref/source/outer-menu.h b/crawl-ref/source/outer-menu.h index 618ae9eb0423..2ca38392ef36 100644 --- a/crawl-ref/source/outer-menu.h +++ b/crawl-ref/source/outer-menu.h @@ -22,6 +22,7 @@ class MenuButton : public ui::Bin int id = 0; int hotkey = 0; COLOURS highlight_colour = LIGHTGREY; + string description; protected: bool focused = false; @@ -62,6 +63,7 @@ class OuterMenu : public ui::Widget function on_button_activated; weak_ptr linked_menus[4]; + shared_ptr descriptions; protected: bool scroller_event_hook(const wm_event& ev); @@ -70,6 +72,7 @@ class OuterMenu : public ui::Widget shared_ptr m_grid; shared_ptr m_root; vector m_buttons; + vector m_description_indexes; int m_width; int m_height; MenuButton* m_initial_focus {nullptr}; From 1274d92874ecadc1a6642c94cd6905fda4643d19 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sun, 26 Aug 2018 14:20:48 +0800 Subject: [PATCH 664/864] Add PlayerDoll widget --- crawl-ref/source/ui.cc | 120 +++++++++++++++++++++++++++++++++++++++++ crawl-ref/source/ui.h | 20 +++++++ 2 files changed, 140 insertions(+) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 96b7618f5412..33145db9807a 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -24,6 +24,11 @@ # include "view.h" # include "stringutil.h" #endif +#ifdef USE_TILE_LOCAL +# include "tilepick.h" +# include "tilepick-p.h" +# include "tile-player-flag-cut.h" +#endif namespace ui { @@ -1480,6 +1485,121 @@ SizeReq Dungeon::_get_preferred_size(Direction dim, int prosp_width) int sz = (dim ? height : width)*32; return {sz, sz}; } + +PlayerDoll::PlayerDoll(dolls_data doll) +{ + m_save_doll = doll; + for (int i = 0; i < TEX_MAX; i++) + m_tile_buf[i].set_tex(&tiles.get_image_manager()->m_textures[i]); + _pack_doll(); +} + +PlayerDoll::~PlayerDoll() +{ + for (int t = 0; t < TEX_MAX; t++) + m_tile_buf[t].clear(); +} + +void PlayerDoll::_pack_doll() +{ + m_tiles.clear(); + // FIXME: Implement this logic in one place in e.g. pack_doll_buf(). + int p_order[TILEP_PART_MAX] = + { + TILEP_PART_SHADOW, // 0 + TILEP_PART_HALO, + TILEP_PART_ENCH, + TILEP_PART_DRCWING, + TILEP_PART_CLOAK, + TILEP_PART_BASE, // 5 + TILEP_PART_BOOTS, + TILEP_PART_LEG, + TILEP_PART_BODY, + TILEP_PART_ARM, + TILEP_PART_HAIR, + TILEP_PART_BEARD, + TILEP_PART_DRCHEAD, // 15 + TILEP_PART_HELM, + TILEP_PART_HAND1, // 10 + TILEP_PART_HAND2, + }; + + int flags[TILEP_PART_MAX]; + tilep_calc_flags(m_save_doll, flags); + + // For skirts, boots go under the leg armour. For pants, they go over. + if (m_save_doll.parts[TILEP_PART_LEG] < TILEP_LEG_SKIRT_OFS) + { + p_order[6] = TILEP_PART_BOOTS; + p_order[7] = TILEP_PART_LEG; + } + + // Special case bardings from being cut off. + bool is_naga = (m_save_doll.parts[TILEP_PART_BASE] == TILEP_BASE_NAGA + || m_save_doll.parts[TILEP_PART_BASE] == TILEP_BASE_NAGA + 1); + if (m_save_doll.parts[TILEP_PART_BOOTS] >= TILEP_BOOTS_NAGA_BARDING + && m_save_doll.parts[TILEP_PART_BOOTS] <= TILEP_BOOTS_NAGA_BARDING_RED) + { + flags[TILEP_PART_BOOTS] = is_naga ? TILEP_FLAG_NORMAL : TILEP_FLAG_HIDE; + } + + bool is_cent = (m_save_doll.parts[TILEP_PART_BASE] == TILEP_BASE_CENTAUR + || m_save_doll.parts[TILEP_PART_BASE] == TILEP_BASE_CENTAUR + 1); + if (m_save_doll.parts[TILEP_PART_BOOTS] >= TILEP_BOOTS_CENTAUR_BARDING + && m_save_doll.parts[TILEP_PART_BOOTS] <= TILEP_BOOTS_CENTAUR_BARDING_RED) + { + flags[TILEP_PART_BOOTS] = is_cent ? TILEP_FLAG_NORMAL : TILEP_FLAG_HIDE; + } + + for (int i = 0; i < TILEP_PART_MAX; ++i) + { + const int p = p_order[i]; + const tileidx_t idx = m_save_doll.parts[p]; + if (idx == 0 || idx == TILEP_SHOW_EQUIP || flags[p] == TILEP_FLAG_HIDE) + continue; + + ASSERT_RANGE(idx, TILE_MAIN_MAX, TILEP_PLAYER_MAX); + + int ymax = TILE_Y; + + if (flags[p] == TILEP_FLAG_CUT_CENTAUR + || flags[p] == TILEP_FLAG_CUT_NAGA) + { + ymax = 18; + } + + m_tiles.emplace_back(idx, TEX_PLAYER, ymax); + } +} + +void PlayerDoll::_render() +{ + for (int i = 0; i < TEX_MAX; i++) + m_tile_buf[i].draw(); +} + +SizeReq PlayerDoll::_get_preferred_size(Direction dim, int prosp_width) +{ + return { TILE_Y, TILE_Y }; +} + +void PlayerDoll::_allocate_region() +{ + for (int t = 0; t < TEX_MAX; t++) + m_tile_buf[t].clear(); + for (const tile_def &tdef : m_tiles) + { + int tile = tdef.tile; + TextureID tex = tdef.tex; + m_tile_buf[tex].add_unscaled(tile, m_region[0], m_region[1], tdef.ymax); + } +} + +bool PlayerDoll::on_event(const wm_event& event) +{ + return false; +} + #endif void UIRoot::push_child(shared_ptr ch, KeymapContext km) diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index e41c9dfa70f3..2f34d82d6872 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -16,6 +16,7 @@ #include "unwind.h" #include "windowmanager.h" #ifdef USE_TILE_LOCAL +# include "tiledoll.h" # include "tilesdl.h" # include "tilebuf.h" # include "tiledgnbuf.h" @@ -620,6 +621,25 @@ class Dungeon : public Widget DungeonCellBuffer m_buf; bool m_dirty; }; + +class PlayerDoll : public Widget +{ +public: + PlayerDoll(dolls_data doll); + virtual ~PlayerDoll(); + + virtual void _render() override; + virtual SizeReq _get_preferred_size(Direction dim, int prosp_width) override; + virtual void _allocate_region() override; + virtual bool on_event(const wm_event& event) override; + +protected: + void _pack_doll(); + dolls_data m_save_doll; + + vector m_tiles; + FixedVector m_tile_buf; +}; #endif #ifdef USE_TILE From 87535eea1a6c50f0f69953fa2b74f0cd1b7bff21 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sun, 2 Sep 2018 23:25:39 +0800 Subject: [PATCH 665/864] Add species/background newgame doll generator This adds a helper function to generate dolls for character combos. This is done in a rather ugly fashion by (partially) generating the new game character. A small segment of the character setup code in _setup_generic() that's relevant to initial equipment is duplicated, with some minor changes; this code modifies the global `you` variable, and fill_doll_equipment() is then called to generate the doll corresponding to the character in `you`. Regarding the modified character generation code, everything after give_items_skills() is removed, since that's what determines a player's starting equipment, and thus the doll appearance. An exception is the item colour randomization. Separately, _unfocus_stats() was not included, since I'm reasonably sure that this has no effect on initial item generation, and I didn't want to make it non-static. --- crawl-ref/source/ng-setup.cc | 4 ++-- crawl-ref/source/ng-setup.h | 2 ++ crawl-ref/source/tiledoll.cc | 35 +++++++++++++++++++++++++++++++++++ crawl-ref/source/tiledoll.h | 4 ++++ 4 files changed, 43 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/ng-setup.cc b/crawl-ref/source/ng-setup.cc index 4cdab13271a5..a20bece65d1b 100644 --- a/crawl-ref/source/ng-setup.cc +++ b/crawl-ref/source/ng-setup.cc @@ -232,7 +232,7 @@ static void _give_ammo(weapon_type weapon, int plus) } } -static void _give_items_skills(const newgame_def& ng) +void give_items_skills(const newgame_def& ng) { create_wanderer(); @@ -505,7 +505,7 @@ static void _setup_generic(const newgame_def& ng) give_basic_mutations(you.species); // This function depends on stats and mutations being finalised. - _give_items_skills(ng); + give_items_skills(ng); roll_demonspawn_mutations(); diff --git a/crawl-ref/source/ng-setup.h b/crawl-ref/source/ng-setup.h index d138c3bae5bd..10950e8b6172 100644 --- a/crawl-ref/source/ng-setup.h +++ b/crawl-ref/source/ng-setup.h @@ -16,3 +16,5 @@ item_def* newgame_make_item(object_class_type base, struct newgame_def; void setup_game(const newgame_def& ng); void initial_dungeon_setup(); + +void give_items_skills(const newgame_def& ng); diff --git a/crawl-ref/source/tiledoll.cc b/crawl-ref/source/tiledoll.cc index a2b804c81ba9..7eed413223c0 100644 --- a/crawl-ref/source/tiledoll.cc +++ b/crawl-ref/source/tiledoll.cc @@ -7,7 +7,11 @@ #include #include "files.h" +#include "jobs.h" +#include "makeitem.h" #include "mon-info.h" +#include "newgame.h" +#include "ng-setup.h" #include "options.h" #include "syscalls.h" #include "tile-player-flag-cut.h" @@ -19,6 +23,7 @@ #include "tilepick.h" #include "tilepick-p.h" #include "transform.h" +#include "unwind.h" dolls_data::dolls_data() { @@ -499,6 +504,36 @@ void fill_doll_equipment(dolls_data &result) result.parts[i] = 0; } +void fill_doll_for_newgame(dolls_data &result, const newgame_def& ng) +{ + for (int j = 0; j < TILEP_PART_MAX; j++) + result.parts[j] = TILEP_SHOW_EQUIP; + + unwind_var unwind_you(you); + you = player(); + + // The following is part of the new game setup code from _setup_generic() + you.your_name = ng.name; + you.species = ng.species; + you.char_class = ng.job; + you.chr_class_name = get_job_name(you.char_class); + + species_stat_init(you.species); + update_vision_range(); + job_stat_init(you.char_class); + give_basic_mutations(you.species); + give_items_skills(ng); + + for (int i = 0; i < ENDOFPACK; ++i) + { + auto &item = you.inv[i]; + if (item.defined()) + item_colour(item); + } + + fill_doll_equipment(result); +} + // Writes equipment information into per-character doll file. void save_doll_file(writer &dollf) { diff --git a/crawl-ref/source/tiledoll.h b/crawl-ref/source/tiledoll.h index 309215f91315..9a64d01ee61c 100644 --- a/crawl-ref/source/tiledoll.h +++ b/crawl-ref/source/tiledoll.h @@ -3,6 +3,8 @@ #include "tile-player-flags.h" +struct newgame_def; + struct dolls_data { dolls_data(); @@ -32,6 +34,8 @@ void fill_doll_equipment(dolls_data &result); void create_random_doll(dolls_data &result); void save_doll_file(writer &dollf); +void fill_doll_for_newgame(dolls_data &result, const newgame_def& ng); + // Saves player doll definitions into dolls.txt. // Returns true if successful, else false. bool save_doll_data(int mode, int num, const dolls_data* dolls); From 3169f2527eb666952024c92eea1945fa00c2665b Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 18 Aug 2018 21:20:40 +0800 Subject: [PATCH 666/864] Convert startup menu to new UI framework --- crawl-ref/source/arena.cc | 1 - crawl-ref/source/ng-input.cc | 4 +- crawl-ref/source/ng-input.h | 3 +- crawl-ref/source/startup.cc | 870 ++++++++++++++--------------------- 4 files changed, 354 insertions(+), 524 deletions(-) diff --git a/crawl-ref/source/arena.cc b/crawl-ref/source/arena.cc index 90088f42f74a..0cbcd4786c87 100644 --- a/crawl-ref/source/arena.cc +++ b/crawl-ref/source/arena.cc @@ -1500,7 +1500,6 @@ static void _choose_arena_teams(newgame_def& choice, return done = true; }); - ui::set_focused_widget(popup.get()); ui::push_layout(move(popup)); while (!done && !crawl_state.seen_hups) { diff --git a/crawl-ref/source/ng-input.cc b/crawl-ref/source/ng-input.cc index 9e12304f40c0..9c14ceb2647f 100644 --- a/crawl-ref/source/ng-input.cc +++ b/crawl-ref/source/ng-input.cc @@ -17,7 +17,7 @@ #include "version.h" // Eventually, this should be something more grand. {dlb} -string opening_screen() +formatted_string opening_screen() { string msg = "Hello, welcome to " CRAWL " " + string(Version::Long) + "!\n" @@ -55,7 +55,7 @@ string opening_screen() msg += "\n"; - return msg; + return formatted_string::parse_string(msg); } bool is_good_name(const string& name, bool blankOK) diff --git a/crawl-ref/source/ng-input.h b/crawl-ref/source/ng-input.h index 4fbcbb34a78b..217f15857653 100644 --- a/crawl-ref/source/ng-input.h +++ b/crawl-ref/source/ng-input.h @@ -1,8 +1,9 @@ #pragma once struct newgame_def; +class formatted_string; -string opening_screen(); +formatted_string opening_screen(); bool validate_player_name(const string &name); bool is_good_name(const string &name, bool blankOK); void enter_player_name(newgame_def& ng); diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index a72401c6d4e8..f8b88d69263e 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -34,6 +34,7 @@ #include "macro.h" #include "maps.h" #include "menu.h" +#include "outer-menu.h" #include "message.h" #include "misc.h" #include "mon-cast.h" @@ -198,7 +199,7 @@ static void _initialize() #endif } - mpr(opening_screen().c_str()); + mpr(opening_screen().tostring().c_str()); } /** KILL_RESETs all monsters in LOS. @@ -365,220 +366,142 @@ static void _post_init(bool newc) } #ifndef DGAMELAUNCH -/** - * Helper for show_startup_menu() - * constructs the game modes section - */ -static void _construct_game_modes_menu(MenuScroller* menu) -{ -#ifdef USE_TILE_LOCAL - TextTileItem* tmp = nullptr; -#else - TextItem* tmp = nullptr; -#endif - string text; -#ifdef USE_TILE_LOCAL - tmp = new TextTileItem(); - tmp->add_tile(tile_def(tileidx_gametype(GAME_TYPE_NORMAL), TEX_GUI)); -#else - tmp = new TextItem(); -#endif - text = "Dungeon Crawl"; - if (Options.seed_from_rc) - text += make_stringf(" (custom seed %" PRIu64 ")", Options.seed_from_rc); - tmp->set_text(text); - tmp->set_fg_colour(WHITE); - tmp->set_highlight_colour(LIGHTGREY); - tmp->set_id(GAME_TYPE_NORMAL); - // Scroller does not care about x-coordinates and only cares about - // item height obtained from max.y - min.y - tmp->set_bounds(coord_def(1, 1), coord_def(1, 2)); - if (Options.seed_from_rc) - { - tmp->set_description_text( - "Dungeon Crawl: The main game. " - "(Your options file has selected a custom seed.)"); - } - else - { - tmp->set_description_text( - "Dungeon Crawl: The main game: full of monsters, " - "items, gods and danger!"); - } - menu->attach_item(tmp); - tmp->set_visible(true); +struct game_modes_menu_item +{ + game_type id; + const char *label; + const char *description; +}; -#ifdef USE_TILE_LOCAL - tmp = new TextTileItem(); - tmp->add_tile(tile_def(tileidx_gametype(GAME_TYPE_NORMAL), TEX_GUI)); -#else - tmp = new TextItem(); -#endif - text = "Choose game seed"; - tmp->set_text(text); - tmp->set_fg_colour(WHITE); - tmp->set_highlight_colour(LIGHTGREY); - tmp->set_id(GAME_TYPE_CUSTOM_SEED); - tmp->set_bounds(coord_def(1, 1), coord_def(1, 2)); - tmp->set_description_text("Play with a chosen custom dungeon seed."); - menu->attach_item(tmp); - tmp->set_visible(true); +static const game_modes_menu_item entries[] = +{ + {GAME_TYPE_NORMAL, "Dungeon Crawl", + "Dungeon Crawl: The main game: full of monsters, items, " + "gods and danger!" }, + {GAME_TYPE_CUSTOM_SEED, "Choose Game Seed", + "Play with a chosen custom dungeon seed." }, + {GAME_TYPE_TUTORIAL, "Tutorial for Dungeon Crawl", + "Tutorial that covers the basics of Dungeon Crawl survival." }, + {GAME_TYPE_HINTS, "Hints Mode for Dungeon Crawl", + "A mostly normal game that provides more advanced hints " + "than the tutorial."}, + {GAME_TYPE_SPRINT, "Dungeon Sprint", + "Hard, fixed single level game mode." }, + {GAME_TYPE_INSTRUCTIONS, "Instructions", "Help menu." }, + {GAME_TYPE_ARENA, "The Arena", + "Pit computer controlled teams versus each other!" }, + {GAME_TYPE_HIGH_SCORES, "High Scores", + "View the high score list." }, +}; -#ifdef USE_TILE_LOCAL - tmp = new TextTileItem(); - tmp->add_tile(tile_def(tileidx_gametype(GAME_TYPE_TUTORIAL), TEX_GUI)); -#else - tmp = new TextItem(); -#endif - text = "Tutorial for Dungeon Crawl"; - tmp->set_text(text); - tmp->set_fg_colour(WHITE); - tmp->set_highlight_colour(LIGHTGREY); - tmp->set_id(GAME_TYPE_TUTORIAL); - // Scroller does not care about x-coordinates and only cares about - // item height obtained from max.y - min.y - tmp->set_bounds(coord_def(1, 1), coord_def(1, 2)); - tmp->set_description_text("Tutorial that covers the basics of " - "Dungeon Crawl survival."); - menu->attach_item(tmp); - tmp->set_visible(true); +static void _construct_game_modes_menu(shared_ptr& container) +{ + for (unsigned int i = 0; i < ARRAYSZ(entries); ++i) + { + const auto& entry = entries[i]; + auto label = make_shared(); #ifdef USE_TILE_LOCAL - tmp = new TextTileItem(); - tmp->add_tile(tile_def(tileidx_gametype(GAME_TYPE_HINTS), TEX_GUI)); -#else - tmp = new TextItem(); + auto hbox = make_shared(Box::HORZ); + hbox->align_items = Widget::Align::CENTER; + auto tile = make_shared(); + tile->set_tile(tile_def(tileidx_gametype(entry.id), TEX_GUI)); + tile->set_margin_for_sdl({0, 6, 0, 0}); + hbox->add_child(move(tile)); + hbox->add_child(label); #endif - text = "Hints Mode for Dungeon Crawl"; - tmp->set_text(text); - tmp->set_fg_colour(WHITE); - tmp->set_highlight_colour(LIGHTGREY); - tmp->set_id(GAME_TYPE_HINTS); - // Scroller does not care about x-coordinates and only cares about - // item height obtained from max.y - min.y - tmp->set_bounds(coord_def(1, 1), coord_def(1, 2)); - tmp->set_description_text("A mostly normal game that provides more " - "advanced hints than the tutorial."); - menu->attach_item(tmp); - tmp->set_visible(true); -#ifdef USE_TILE_LOCAL - tmp = new TextTileItem(); - tmp->add_tile(tile_def(tileidx_gametype(GAME_TYPE_SPRINT), TEX_GUI)); -#else - tmp = new TextItem(); -#endif - text = "Dungeon Sprint"; - tmp->set_text(text); - tmp->set_fg_colour(WHITE); - tmp->set_highlight_colour(LIGHTGREY); - tmp->set_id(GAME_TYPE_SPRINT); - // Scroller does not care about x-coordinates and only cares about - // item height obtained from max.y - min.y - tmp->set_bounds(coord_def(1, 1), coord_def(1, 2)); - tmp->set_description_text("Hard, fixed single level game mode."); - menu->attach_item(tmp); - tmp->set_visible(true); + label->set_text(formatted_string(entry.label, WHITE)); + auto btn = make_shared(); #ifdef USE_TILE_LOCAL - tmp = new TextTileItem(); - tmp->add_tile(tile_def(tileidx_gametype(GAME_TYPE_INSTRUCTIONS), TEX_GUI)); + hbox->set_margin_for_sdl({2,10,2,2}); + btn->set_child(move(hbox)); #else - tmp = new TextItem(); + btn->set_child(move(label)); #endif - text = "Instructions"; - tmp->set_text(text); - tmp->set_fg_colour(WHITE); - tmp->set_highlight_colour(LIGHTGREY); - tmp->set_id(GAME_TYPE_INSTRUCTIONS); - // Scroller does not care about x-coordinates and only cares about - // item height obtained from max.y - min.y - tmp->set_bounds(coord_def(1, 1), coord_def(1, 2)); - tmp->set_description_text("Help menu."); - menu->attach_item(tmp); - tmp->set_visible(true); + btn->id = entry.id; + btn->description = entry.description; + btn->highlight_colour = LIGHTGREY; + container->add_button(move(btn), 0, i); + } +} -#ifdef USE_TILE_LOCAL - tmp = new TextTileItem(); - tmp->add_tile(tile_def(tileidx_gametype(GAME_TYPE_ARENA), TEX_GUI)); -#else - tmp = new TextItem(); -#endif - text = "The Arena"; - tmp->set_text(text); - tmp->set_fg_colour(WHITE); - tmp->set_highlight_colour(LIGHTGREY); - tmp->set_id(GAME_TYPE_ARENA); - // Scroller does not care about x-coordinates and only cares about - // item height obtained from max.y - min.y - tmp->set_bounds(coord_def(1, 1), coord_def(1, 2)); - tmp->set_description_text("Pit computer controlled teams versus each other!"); - menu->attach_item(tmp); - tmp->set_visible(true); +static shared_ptr _make_newgame_button(shared_ptr& container, int num_chars) +{ + auto label = make_shared(formatted_string("New Game", WHITE)); #ifdef USE_TILE_LOCAL - tmp = new TextTileItem(); - tmp->add_tile(tile_def(tileidx_gametype(GAME_TYPE_HIGH_SCORES), TEX_GUI)); -#else - tmp = new TextItem(); + auto hbox = make_shared(Box::HORZ); + hbox->align_items = Widget::Align::CENTER; + hbox->add_child(label); + label->set_margin_for_sdl({0,0,0,TILE_Y+6}); + hbox->min_size() = { 0, TILE_Y }; #endif - text = "High Scores"; - tmp->set_text(text); - tmp->set_fg_colour(WHITE); - tmp->set_highlight_colour(LIGHTGREY); - tmp->set_id(GAME_TYPE_HIGH_SCORES); - // Scroller does not care about x-coordinates and only cares about - // item height obtained from max.y - min.y - tmp->set_bounds(coord_def(1, 1), coord_def(1, 2)); - tmp->set_description_text("View the high score list."); - menu->attach_item(tmp); - tmp->set_visible(true); -} -static void _add_newgame_button(MenuScroller* menu, int num_chars) -{ - // XXX: duplicates a lot of _construct_save_games_menu code. not ideal. + auto btn = make_shared(); #ifdef USE_TILE_LOCAL - SaveMenuItem* tmp = new SaveMenuItem(); + btn->set_child(move(hbox)); #else - TextItem* tmp = new TextItem(); + btn->set_child(move(label)); #endif - tmp->set_text("New Game"); - tmp->set_bounds(coord_def(1, 1), coord_def(1, 2)); - tmp->set_fg_colour(WHITE); - tmp->set_highlight_colour(LIGHTGREY); - // unique id - tmp->set_id(NUM_GAME_TYPE + num_chars); - menu->attach_item(tmp); - tmp->set_visible(true); + btn->get_child()->set_margin_for_sdl({2,10,2,2}); + btn->id = NUM_GAME_TYPE + num_chars; + btn->highlight_colour = LIGHTGREY; + return btn; } -static void _construct_save_games_menu(MenuScroller* menu, +static void _construct_save_games_menu(shared_ptr& container, const vector& chars) { for (unsigned int i = 0; i < chars.size(); ++i) { + auto hbox = make_shared(Box::HORZ); + hbox->align_items = Widget::Align::CENTER; + #ifdef USE_TILE_LOCAL - SaveMenuItem* tmp = new SaveMenuItem(); + auto tile = make_shared(chars.at(i).doll); + tile->set_margin_for_sdl({0, 6, 0, 0}); + hbox->add_child(move(tile)); +#endif + + const COLOURS bg = chars.at(i).save_loadable ? WHITE : RED; + auto text = chars.at(i).short_desc(); + bool wiz = strip_suffix(text, " (WIZ)"); + auto label = make_shared(formatted_string( text, bg)); + label->ellipsize = true; +#ifdef USE_TILE_LOCAL + label->max_size() = { INT_MAX, (int)tiles.get_crt_font()->char_height() }; #else - TextItem* tmp = new TextItem(); + label->max_size() = { INT_MAX, 1 }; #endif - tmp->set_text(chars.at(i).short_desc()); - tmp->set_bounds(coord_def(1, 1), coord_def(1, 2)); - tmp->set_fg_colour(chars.at(i).save_loadable ? WHITE : RED); - tmp->set_highlight_colour(LIGHTGREY); - // unique id - tmp->set_id(NUM_GAME_TYPE + i); + hbox->add_child(label); + + if (wiz) + { + const COLOURS wiz_bg = chars.at(i).save_loadable ? LIGHTMAGENTA : RED; + auto wiz_text = formatted_string(" (WIZ)", wiz_bg); + hbox->add_child(make_shared(wiz_text)); + } + + auto btn = make_shared(); #ifdef USE_TILE_LOCAL - tmp->set_doll(chars.at(i).doll); + btn->set_child(move(hbox)); +#else + btn->set_child(move(label)); #endif - menu->attach_item(tmp); - tmp->set_visible(true); + btn->get_child()->set_margin_for_sdl({2,10,2,2}); + btn->id = NUM_GAME_TYPE + i; + btn->highlight_colour = LIGHTGREY; + container->add_button(move(btn), 0, i); } if (!chars.empty()) - _add_newgame_button(menu, chars.size()); + { + auto btn = _make_newgame_button(container, chars.size()); + container->add_button(move(btn), 0, (int)chars.size()); + } } // Should probably use some find invocation instead. @@ -597,12 +520,6 @@ static bool _game_defined(const newgame_def& ng) && ng.job != JOB_UNKNOWN; } -static const int SCROLLER_MARGIN_X = 18; -static const int NAME_START_Y = 5; -static const int GAME_MODES_START_Y = 7; -static const int NUM_HELP_LINES = 3; -static const int NUM_MISC_LINES = 5; - // TODO: should be game_type. Also, does this really need to be static? // maybe part of crawl_state? static int startup_menu_game_type = GAME_TYPE_UNSPECIFIED; @@ -614,315 +531,275 @@ class UIStartupMenu : public Widget chars = find_all_saved_characters(); num_saves = chars.size(); input_string = crawl_state.default_startup_name; + + m_root = make_shared(Box::VERT); + m_root->_set_parent(this); + m_root->align_items = Widget::Align::STRETCH; + + m_root->add_child(make_shared(opening_screen())); + + auto grid = make_shared(); + grid->set_margin_for_crt({1, 0, 2, 0}); + + // If the game filled in a complete name, the user will + // usually want to enter a new name instead of adding + // to the current one. + full_name = !input_string.empty(); + input_text = make_shared(); + input_text->set_text(formatted_string(input_string, WHITE)); + input_text->set_margin_for_crt({0, 0, 1, 0}); + + auto name_prompt = make_shared("Enter your name:"); + name_prompt->set_margin_for_crt({0, 1, 1, 0}); +#ifdef USE_TILE_LOCAL + name_prompt->min_size() = { 0, TILE_Y + 2 }; +#endif + input_text->set_margin_for_sdl({0, 0, 10, 10}); + grid->add_child(move(name_prompt), 0, 0); + grid->add_child(input_text, 1, 0); + + descriptions = make_shared(); + + auto mode_prompt = make_shared("Choices:"); + mode_prompt->set_margin_for_crt({0, 1, 1, 0}); +#ifdef USE_TILE_LOCAL + mode_prompt->min_size() = { 0, TILE_Y + 2 }; +#endif + game_modes_menu = make_shared(true, 1, ARRAYSZ(entries)); + game_modes_menu->set_margin_for_sdl({0, 0, 10, 10}); + game_modes_menu->set_margin_for_crt({0, 0, 1, 0}); + game_modes_menu->descriptions = descriptions; + _construct_game_modes_menu(game_modes_menu); + +#ifdef USE_TILE_LOCAL + game_modes_menu->min_size() = { 0, TILE_Y*3 }; +#else + game_modes_menu->min_size() = { 0, 2 }; +#endif + + grid->add_child(move(mode_prompt), 0, 1); + grid->add_child(game_modes_menu, 1, 1); + + save_games_menu = make_shared(num_saves > 1, 1, num_saves + 1); + if (num_saves > 0) + { + auto save_prompt = make_shared("Saved games:"); + save_prompt->set_margin_for_crt({0, 1, 1, 0}); + save_games_menu->set_margin_for_sdl({0, 0, 10, 10}); +#ifdef USE_TILE_LOCAL + save_prompt->min_size() = { 0, TILE_Y + 2 }; + save_games_menu->min_size() = { 0, TILE_Y * min(num_saves, 3) }; +#else + save_games_menu->min_size() = { 0, 2 }; +#endif + save_games_menu->descriptions = descriptions; + + _construct_save_games_menu(save_games_menu, chars); + grid->add_child(move(save_prompt), 0, 2); + grid->add_child(save_games_menu, 1, 2); + + game_modes_menu->linked_menus[2] = save_games_menu; + save_games_menu->linked_menus[0] = game_modes_menu; + + grid->row_flex_grow(1) = 1000; + grid->row_flex_grow(2) = 1; + } + + game_modes_menu->on_button_activated = + save_games_menu->on_button_activated = + [this](int id) { this->menu_item_activated(id); }; + + for (auto &w : game_modes_menu->get_buttons()) + { + w->on(Widget::slots.event, [w, this](wm_event ev) { + return this->button_event_hook(ev, w); + }); + } + for (auto &w : save_games_menu->get_buttons()) + { + w->on(Widget::slots.event, [w, this](wm_event ev) { + return this->button_event_hook(ev, w); + }); + } + + grid->column_flex_grow(0) = 1; + grid->column_flex_grow(1) = 10; + + m_root->add_child(move(grid)); + + string text = "Use the up/down keys to select the type of game or load a " + "character."; +#ifdef USE_TILE_LOCAL + if (tiles.is_using_small_layout()) + text += " "; + else +#endif + text += "\n"; + text += "You can type your name; if you leave it blank you will be " + "asked later.\n" + "Press Enter to start"; + // TODO: this should include a description of that character. + if (_game_defined(defaults)) + text += ", Tab to repeat the last game's choice"; + text += ".\n"; + if (recent_error_messages()) + text += "Errors during initialization; press ctrl-p to view the full log.\n"; + m_root->add_child(make_shared(text)); + + descriptions->set_margin_for_crt({1, 0, 0, 0}); + m_root->add_child(descriptions); }; virtual void _render() override; virtual SizeReq _get_preferred_size(Direction dim, int prosp_width) override; virtual void _allocate_region() override; - virtual bool on_event(const wm_event& event) override; - PrecisionMenu menu; + bool has_allocated = false; + bool done; bool end_game; + virtual shared_ptr get_child_at_offset(int x, int y) override { + return m_root; + } + private: newgame_def& ng_choice; const newgame_def &defaults; string input_string; bool full_name; - TextItem *input_text; vector chars; int num_saves; - MenuScroller *game_modes, *save_games; - MenuDescriptor *descriptor; -}; -SizeReq UIStartupMenu::_get_preferred_size(Direction dim, int prosp_width) -{ -#ifdef USE_TILE_LOCAL - SizeReq ret; - if (!dim) - ret = { 80, 90 }; // seems to work well empirically - else + bool button_event_hook(const wm_event& ev, MenuButton* btn) { - // duplicate of calculations below in _allocate_region() - const int save_lines = num_saves + (num_saves ? 1 : 0); // add 1 for New Game - const int help_start = GAME_MODES_START_Y + num_to_lines(save_lines + NUM_GAME_TYPE) + 2; - const int help_end = help_start + NUM_HELP_LINES + 1; - ret = { 20, help_end }; + if (ev.type == WME_FOCUSIN) + { + startup_menu_game_type = btn->id; + switch (startup_menu_game_type) + { + case GAME_TYPE_ARENA: + input_string = ""; + break; + case GAME_TYPE_NORMAL: + case GAME_TYPE_CUSTOM_SEED: + case GAME_TYPE_TUTORIAL: + case GAME_TYPE_SPRINT: + case GAME_TYPE_HINTS: + // If a game type is chosen, the user expects + // to start a new game. Just blanking the name + // it it clashes for now. + if (_find_save(chars, input_string) != -1) + input_string = ""; + break; + case GAME_TYPE_HIGH_SCORES: + break; + + case GAME_TYPE_INSTRUCTIONS: + break; + + default: + int save_number = startup_menu_game_type - NUM_GAME_TYPE; + if (save_number < num_saves) + input_string = chars.at(save_number).name; + else // new game + input_string = ""; + full_name = true; + break; + } + input_text->set_text(formatted_string(input_string, WHITE)); + } + return false; } - const FontWrapper* font = tiles.get_crt_font(); - const int f = !dim ? font->char_width() : font->char_height(); - ret.min *= f; - ret.nat *= f; + void on_show(); + void menu_item_activated(int id); - return ret; -#else - if (!dim) - return { 80, 80 }; - else - return { 24, 24 }; -#endif + shared_ptr m_root; + shared_ptr input_text; + shared_ptr descriptions; + shared_ptr game_modes_menu; + shared_ptr save_games_menu; +}; + +SizeReq UIStartupMenu::_get_preferred_size(Direction dim, int prosp_width) +{ + return m_root->get_preferred_size(dim, prosp_width); } void UIStartupMenu::_render() { -#ifdef USE_TILE_LOCAL - GLW_3VF t = {(float)m_region[0], (float)m_region[1], 0}, s = {1, 1, 1}; - glmanager->set_transform(t, s); -#endif - ui::push_scissor(m_region); - menu.draw_menu(); - ui::pop_scissor(); -#ifdef USE_TILE_LOCAL - glmanager->reset_transform(); -#endif + m_root->render(); } void UIStartupMenu::_allocate_region() { - menu.clear(); - -#ifdef USE_TILE_LOCAL - const FontWrapper* font = tiles.get_crt_font(); - const int max_col = m_region[2]/font->char_width(); - const int max_line = m_region[3]/font->char_height(); -#else - const int max_col = m_region[2], max_line = m_region[3]; -#endif + m_root->allocate_region(m_region); - const int num_modes = NUM_GAME_TYPE; - - int save_lines = num_saves + (num_saves ? 1 : 0); // add 1 for New Game - const int help_start = min(GAME_MODES_START_Y + num_to_lines(save_lines + num_modes) + 2, - max_line - NUM_MISC_LINES + 1); - const int help_end = help_start + NUM_HELP_LINES + 1; - - const int game_mode_bottom = GAME_MODES_START_Y + num_to_lines(num_modes); - const int game_save_top = help_start - 2 - num_to_lines(min(2, save_lines)); - const int save_games_start_y = min(game_mode_bottom, game_save_top); - - menu.set_select_type(PrecisionMenu::PRECISION_SINGLESELECT); - MenuFreeform* freeform = new MenuFreeform(); - freeform->init(coord_def(1, 1), coord_def(max_col, max_line), "freeform"); - // This freeform will only containt unfocusable texts - freeform->allow_focus(false); - game_modes = new MenuScroller(); - game_modes->init(coord_def(SCROLLER_MARGIN_X, GAME_MODES_START_Y), - coord_def(max_col, save_games_start_y), - "game modes"); - - save_games = new MenuScroller(); - save_games->init(coord_def(SCROLLER_MARGIN_X, save_games_start_y), - coord_def(max_col, help_start - 1), - "save games"); - _construct_game_modes_menu(game_modes); - _construct_save_games_menu(save_games, chars); - - NoSelectTextItem* tmp = new NoSelectTextItem(); - tmp->set_text("Enter your name:"); - tmp->set_bounds(coord_def(1, NAME_START_Y), - coord_def(SCROLLER_MARGIN_X, NAME_START_Y + 1)); - freeform->attach_item(tmp); - tmp->set_visible(true); - - tmp = new NoSelectTextItem(); - tmp->set_text("Choices:"); - tmp->set_bounds(coord_def(1, GAME_MODES_START_Y), - coord_def(SCROLLER_MARGIN_X, GAME_MODES_START_Y + 1)); - freeform->attach_item(tmp); - tmp->set_visible(true); - - if (num_saves) + if (!has_allocated) { - tmp = new NoSelectTextItem(); - tmp->set_text("Saved games:"); - tmp->set_bounds(coord_def(1, save_games_start_y), - coord_def(SCROLLER_MARGIN_X, save_games_start_y + 1)); - freeform->attach_item(tmp); - tmp->set_visible(true); + has_allocated = true; + on_show(); } +} - tmp = new NoSelectTextItem(); - - string text = "Use the up/down keys to select the type of game or load a " - "character."; -#ifdef USE_TILE_LOCAL - if (tiles.is_using_small_layout()) - text += " "; - else -#endif - text += "\n"; - text += "You can type your name; if you leave it blank you will be " - "asked later.\n" - "Press Enter to start"; - // TODO: this should include a description of that character. - if (_game_defined(defaults)) - text += ", Tab to repeat the last game's choice"; - text += ".\n"; - tmp->set_text(text); - tmp->set_bounds(coord_def(1, help_start), coord_def(max_col - 1, help_end)); - freeform->attach_item(tmp); - tmp->set_visible(true); - - menu.attach_object(freeform); - menu.attach_object(game_modes); - menu.attach_object(save_games); - - descriptor = new MenuDescriptor(&menu); - descriptor->init(coord_def(1, help_end), coord_def(max_col, help_end + 1), - "descriptor"); - menu.attach_object(descriptor); - -#ifdef USE_TILE_LOCAL - // Black and White highlighter looks kinda bad on tiles - BoxMenuHighlighter* highlighter = new BoxMenuHighlighter(&menu); -#else - BlackWhiteHighlighter* highlighter = new BlackWhiteHighlighter(&menu); -#endif - highlighter->init(coord_def(-1, -1), coord_def(-1, -1), "highlighter"); - menu.attach_object(highlighter); - - freeform->set_visible(true); - game_modes->set_visible(true); - save_games->set_visible(true); - descriptor->set_visible(true); - highlighter->set_visible(true); - - // Draw legal info etc - auto intro_text = new FormattedTextItem(); - intro_text->set_text(opening_screen()); - intro_text->set_bounds(coord_def(1, 1), coord_def(max_col, 5)); - intro_text->set_visible(true); - freeform->attach_item(intro_text); - - input_text = new TextItem(); - input_text->set_text(input_string); - input_text->set_fg_colour(WHITE); - input_text->set_bounds(coord_def(SCROLLER_MARGIN_X, NAME_START_Y), - coord_def(max_col, NAME_START_Y+1)); - input_text->set_visible(true); - freeform->attach_item(input_text); - - // If the game filled in a complete name, the user will - // usually want to enter a new name instead of adding - // to the current one. - full_name = !input_string.empty(); - +void UIStartupMenu::on_show() +{ int save = _find_save(chars, input_string); // don't use non-enum game_type values across restarts, as the list of // saves may have changed on restart. if (startup_menu_game_type >= NUM_GAME_TYPE) startup_menu_game_type = GAME_TYPE_UNSPECIFIED; + int id; if (startup_menu_game_type != GAME_TYPE_UNSPECIFIED) - { - menu.set_active_object(game_modes); - game_modes->set_active_item(startup_menu_game_type); - } + id = startup_menu_game_type; else if (save != -1) { - menu.set_active_object(save_games); // save game id is offset by NUM_GAME_TYPE - save_games->set_active_item(NUM_GAME_TYPE + save); + id = NUM_GAME_TYPE + save; } else if (defaults.type != NUM_GAME_TYPE) - { - menu.set_active_object(game_modes); - game_modes->set_active_item(defaults.type); - } + id = defaults.type; else if (!chars.empty()) - { - menu.set_active_object(save_games); - save_games->activate_first_item(); - } + id = NUM_GAME_TYPE + 0; else - { - menu.set_active_object(game_modes); - game_modes->activate_first_item(); - } - - descriptor->render(); - if (recent_error_messages()) - { - descriptor->override_description( - "Errors during initialization; press ctrl-p to view the full log."); - } - else - descriptor->override_description(crawl_state.last_game_exit.message); - -} - -bool UIStartupMenu::on_event(const wm_event& ev) -{ -#ifdef USE_TILE_LOCAL - if (ev.type == WME_MOUSEMOTION - || ev.type == WME_MOUSEBUTTONDOWN - || ev.type == WME_MOUSEWHEEL) - { - MouseEvent mouse_ev = ev.mouse_event; - mouse_ev.px -= m_region[0]; - mouse_ev.py -= m_region[1]; - - int key = menu.handle_mouse(mouse_ev); - if (key && key != CK_NO_KEY) + id = 0; + + if (auto focus = game_modes_menu->get_button_by_id(id)) + game_modes_menu->scroll_button_into_view(focus); + else if (auto focus2 = save_games_menu->get_button_by_id(id)) + save_games_menu->scroll_button_into_view(focus2); + + Layout *layout = nullptr; + for (Widget *w = _get_parent(); w && !layout; w = w->_get_parent()) + layout = dynamic_cast(w); + ASSERT(layout); + layout->add_event_filter([this](wm_event ev) { + if (ev.type != WME_KEYDOWN) + return false; + int keyn = ev.key.keysym.sym; + + if (key_is_escape(keyn) || keyn == CK_MOUSE_CMD) { - wm_event fake_key = {0}; - fake_key.type = WME_KEYDOWN; - fake_key.key.keysym.sym = key; - on_event(fake_key); + // End the game + return done = end_game = true; + } + else if (keyn == '\t' && _game_defined(defaults)) + { + ng_choice = defaults; + return done = true; + } + else if (keyn == '?') + { + menu_item_activated(GAME_TYPE_INSTRUCTIONS); + return true; + } + else if (keyn == CONTROL('P')) + { + replay_messages_during_startup(); + return true; } - if (ev.type == WME_MOUSEMOTION) - _expose(); - return true; - } -#endif - - if (ev.type != WME_KEYDOWN) - return false; - int keyn = ev.key.keysym.sym; - - // XXX: these keys are effectively broken on the main menu; there's a new - // menu implementation on the way, but until it's ready, disable them - if (keyn == CK_PGUP || keyn == CK_PGDN) - return true; - - _expose(); - - if (key_is_escape(keyn) || keyn == CK_MOUSE_CMD) - { - // End the game - return done = end_game = true; - } - else if (keyn == '\t' && _game_defined(defaults)) - { - ng_choice = defaults; - return done = true; - } - else if (keyn == '?') - { - show_help(); - - // If we had a save selected, reset type so that the save - // will continue to be selected when we restart the menu. - MenuItem *active = menu.get_active_item(); - if (active && active->get_id() >= NUM_GAME_TYPE) - startup_menu_game_type = GAME_TYPE_UNSPECIFIED; - - return true; - } - else if (keyn == CONTROL('P')) - { - replay_messages_during_startup(); - MenuItem *active = menu.get_active_item(); - if (active && active->get_id() >= NUM_GAME_TYPE) - startup_menu_game_type = GAME_TYPE_UNSPECIFIED; - return true; - } - - if (!menu.process_key(keyn)) - { // handle the non-action keys by hand to poll input // Only consider alphanumeric keys and -_ . bool changed_name = false; @@ -952,6 +829,10 @@ bool UIStartupMenu::on_event(const wm_event& ev) full_name = false; } } + else + return false; + + input_text->set_text(formatted_string(input_string, WHITE)); // Depending on whether the current name occurs // in the saved games, update the active object. @@ -961,65 +842,16 @@ bool UIStartupMenu::on_event(const wm_event& ev) if (changed_name) { int i = _find_save(chars, input_string); - if (i == -1) - menu.set_active_object(game_modes); - else - { - menu.set_active_object(save_games); - // save game ID is offset by NUM_GAME_TYPE - save_games->set_active_item(NUM_GAME_TYPE + i); - } + auto menu = i == -1 ? game_modes_menu : save_games_menu; + auto btn = menu->get_button(0, i == -1 ? 0 : i); + menu->scroll_button_into_view(btn); } - else - { - // Menu might have changed selection -- sync name. - // TODO: the mapping from menu item to game_type is alarmingly - // brittle here - startup_menu_game_type = menu.get_active_item()->get_id(); - switch (startup_menu_game_type) - { - case GAME_TYPE_ARENA: - input_string = ""; - break; - case GAME_TYPE_NORMAL: - case GAME_TYPE_CUSTOM_SEED: - case GAME_TYPE_TUTORIAL: - case GAME_TYPE_SPRINT: - case GAME_TYPE_HINTS: - // If a game type is chosen, the user expects - // to start a new game. Just blanking the name - // it it clashes for now. - if (_find_save(chars, input_string) != -1) - input_string = ""; - break; - case GAME_TYPE_HIGH_SCORES: - break; - - case GAME_TYPE_INSTRUCTIONS: - break; - - default: - int save_number = startup_menu_game_type - NUM_GAME_TYPE; - if (save_number < num_saves) - input_string = chars.at(save_number).name; - else // new game - input_string = ""; - full_name = true; - break; - } - } - input_text->set_text(input_string); - } - // we had a significant action! - vector selected = menu.get_selected_items(); - menu.clear_selections(); - if (selected.empty()) - { - // Uninteresting action, poll a new key return true; - } + }); +} - int id = selected.at(0)->get_id(); +void UIStartupMenu::menu_item_activated(int id) +{ switch (id) { case GAME_TYPE_NORMAL: @@ -1028,32 +860,29 @@ bool UIStartupMenu::on_event(const wm_event& ev) case GAME_TYPE_SPRINT: case GAME_TYPE_HINTS: trim_string(input_string); + // XXX: is it ever not a good name? if (is_good_name(input_string, true)) { ng_choice.type = static_cast(id); ng_choice.name = input_string; - return done = true; - } - else - { - // bad name - descriptor->override_description("That's a silly name."); - // Don't make the next key re-enter the game. - menu.clear_selections(); + done = true; } - return true; + return; case GAME_TYPE_ARENA: ng_choice.type = GAME_TYPE_ARENA; - return done = true; + done = true; + return; case GAME_TYPE_INSTRUCTIONS: - show_help(); - return true; - case GAME_TYPE_HIGH_SCORES: - show_hiscore_table(); - return true; + { + if (id == GAME_TYPE_INSTRUCTIONS) + show_help(); + else + show_hiscore_table(); + } + return; default: // It was a savegame instead @@ -1071,7 +900,8 @@ bool UIStartupMenu::on_event(const wm_event& ev) ng_choice.type = GAME_TYPE_NORMAL; ng_choice.filename = ""; // ? } - return done = true; + done = true; + return; } } From 20abbd21e03e42a9c9e3f6a641339800c5a6eb0e Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 18 Aug 2018 21:27:46 +0800 Subject: [PATCH 667/864] convert hints menu to new UI framework --- crawl-ref/source/hints.cc | 112 ++++++++++++++++++++++++++++++-------- 1 file changed, 90 insertions(+), 22 deletions(-) diff --git a/crawl-ref/source/hints.cc b/crawl-ref/source/hints.cc index 0306e0b0f387..072eeac8c8be 100644 --- a/crawl-ref/source/hints.cc +++ b/crawl-ref/source/hints.cc @@ -29,6 +29,7 @@ #include "macro.h" #include "message.h" #include "mutation.h" +#include "outer-menu.h" #include "nearby-danger.h" #include "options.h" #include "output.h" @@ -40,6 +41,7 @@ #include "state.h" #include "stringutil.h" #include "terrain.h" +#include "tilepick-p.h" #include "travel.h" #include "viewchar.h" #include "viewgeom.h" @@ -157,27 +159,103 @@ static string _print_hints_menu(hints_types type) break; } - return make_stringf("%c - %s %s %s\n", + return make_stringf("%c - %s %s %s", letter, species_name(_get_hints_species(type)).c_str(), get_job_name(_get_hints_job(type)), desc); } +static void _fill_newgame_choice_for_hints(newgame_def& choice, hints_types type) +{ + choice.species = _get_hints_species(type); + choice.job = _get_hints_job(type); + // easiest choice for fighters + choice.weapon = choice.job == JOB_HUNTER ? WPN_SHORTBOW + : WPN_HAND_AXE; +} + // Hints mode selection screen and choice. void pick_hints(newgame_def& choice) { string prompt = "You must be new here indeed!" "\n\n" - "You can be:" - "\n"; - for (int i = 0; i < HINT_TYPES_NUM; i++) - prompt += _print_hints_menu((hints_types)i); - prompt += "\nEsc - Quit" - "\n* - Random hints mode character" - ""; + "You can be:"; auto prompt_ui = make_shared(formatted_string::parse_string(prompt)); - auto popup = make_shared(prompt_ui); + + auto vbox = make_shared(Box::VERT); + vbox->align_items = Widget::Align::STRETCH; + vbox->add_child(prompt_ui); + + auto main_items = make_shared(true, 1, 3); + main_items->set_margin_for_sdl({15, 0, 15, 0}); + main_items->set_margin_for_crt({1, 0, 1, 0}); + vbox->add_child(main_items); + + for (int i = 0; i < 3; i++) + { + auto label = make_shared(); + label->set_text(_print_hints_menu(static_cast(i))); + +#ifdef USE_TILE_LOCAL + auto hbox = make_shared(Box::HORZ); + hbox->align_items = Widget::Align::CENTER; + dolls_data doll; + newgame_def tng = choice; + _fill_newgame_choice_for_hints(tng, static_cast(i)); + fill_doll_for_newgame(doll, tng); + auto tile = make_shared(doll); + tile->set_margin_for_sdl({0, 6, 0, 0}); + hbox->add_child(move(tile)); + hbox->add_child(label); +#endif + + auto btn = make_shared(); +#ifdef USE_TILE_LOCAL + hbox->set_margin_for_sdl({4,8,4,8}); + btn->set_child(move(hbox)); +#else + btn->set_child(move(label)); +#endif + btn->id = i; + btn->hotkey = 'a' + i; + + if (i == 0) + main_items->set_initial_focus(btn.get()); + + main_items->add_button(btn, 0, i); + } + + auto sub_items = make_shared(false, 1, 2); + vbox->add_child(sub_items); bool done = false; + auto menu_item_activated = [&](int id) { + Hints.hints_type = id - 'a'; + _fill_newgame_choice_for_hints(choice, + static_cast(id - 'a')); + done = true; + }; + + main_items->on_button_activated = menu_item_activated; + sub_items->on_button_activated = menu_item_activated; + main_items->linked_menus[2] = sub_items; + sub_items->linked_menus[0] = main_items; + + { + auto label = make_shared(formatted_string("Esc - Quit", BROWN)); + auto btn = make_shared(); + btn->set_child(move(label)); + btn->hotkey = CK_ESCAPE; + sub_items->add_button(btn, 0, 0); + } + { + auto label = make_shared(formatted_string(" * - Random hints mode character", BROWN)); + auto btn = make_shared(); + btn->set_child(move(label)); + sub_items->add_button(btn, 0, 1); + } + + auto popup = make_shared(vbox); + int keyn; popup->on(Widget::slots.event, [&](wm_event ev) { if (ev.type != WME_KEYDOWN) @@ -186,19 +264,9 @@ void pick_hints(newgame_def& choice) // Random choice. if (keyn == '*' || keyn == '+' || keyn == '!' || keyn == '#') - keyn = 'a' + random2(HINT_TYPES_NUM); - - // Choose character for hints mode game and set starting values. - if (keyn >= 'a' && keyn <= 'a' + HINT_TYPES_NUM - 1) { - Hints.hints_type = keyn - 'a'; - choice.species = _get_hints_species(Hints.hints_type); - choice.job = _get_hints_job(Hints.hints_type); - // easiest choice for fighters - choice.weapon = choice.job == JOB_HUNTER ? WPN_SHORTBOW - : WPN_HAND_AXE; - - return done = true; + ev.key.keysym.sym = 'a' + random2(HINT_TYPES_NUM); + return false; } switch (keyn) @@ -206,7 +274,7 @@ void pick_hints(newgame_def& choice) case 'X': CASE_ESCAPE return done = true; default: - return true; + return false; } }); ui::run_layout(move(popup), done); From ded90f589afacd5e5994d25ce6c93ad133823f11 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 18 Aug 2018 21:29:39 +0800 Subject: [PATCH 668/864] Convert hiscores menu to new UI framework --- crawl-ref/source/hints.cc | 37 ++--- crawl-ref/source/hiscores.cc | 259 ++++++++++++++--------------------- 2 files changed, 120 insertions(+), 176 deletions(-) diff --git a/crawl-ref/source/hints.cc b/crawl-ref/source/hints.cc index 072eeac8c8be..6f81727e6756 100644 --- a/crawl-ref/source/hints.cc +++ b/crawl-ref/source/hints.cc @@ -227,11 +227,19 @@ void pick_hints(newgame_def& choice) auto sub_items = make_shared(false, 1, 2); vbox->add_child(sub_items); + int keyn; bool done = false; auto menu_item_activated = [&](int id) { - Hints.hints_type = id - 'a'; - _fill_newgame_choice_for_hints(choice, - static_cast(id - 'a')); + if (id == CK_ESCAPE) + { + keyn = CK_ESCAPE; + done = true; + return; + } + else if (id == '*') + id = random2(HINT_TYPES_NUM); + Hints.hints_type = id; + _fill_newgame_choice_for_hints(choice, static_cast(id)); done = true; }; @@ -245,37 +253,30 @@ void pick_hints(newgame_def& choice) auto btn = make_shared(); btn->set_child(move(label)); btn->hotkey = CK_ESCAPE; + btn->id = CK_ESCAPE; sub_items->add_button(btn, 0, 0); } { auto label = make_shared(formatted_string(" * - Random hints mode character", BROWN)); auto btn = make_shared(); btn->set_child(move(label)); + btn->hotkey = '*'; + btn->id = '*'; sub_items->add_button(btn, 0, 1); } auto popup = make_shared(vbox); - int keyn; popup->on(Widget::slots.event, [&](wm_event ev) { if (ev.type != WME_KEYDOWN) return false; keyn = ev.key.keysym.sym; - + if (keyn == 'X') + return done = true; // Random choice. - if (keyn == '*' || keyn == '+' || keyn == '!' || keyn == '#') - { - ev.key.keysym.sym = 'a' + random2(HINT_TYPES_NUM); - return false; - } - - switch (keyn) - { - case 'X': CASE_ESCAPE - return done = true; - default: - return false; - } + if (keyn == '+' || keyn == '!' || keyn == '#') + ev.key.keysym.sym = '*'; + return false; }); ui::run_layout(move(popup), done); diff --git a/crawl-ref/source/hiscores.cc b/crawl-ref/source/hiscores.cc index 845f6e3f1849..eadb6247e552 100644 --- a/crawl-ref/source/hiscores.cc +++ b/crawl-ref/source/hiscores.cc @@ -57,6 +57,7 @@ #endif #include "unwind.h" #include "version.h" +#include "outer-menu.h" using namespace ui; @@ -328,45 +329,6 @@ string hiscores_print_list(int display_count, int format, int newest_entry) return ret; } -static void _add_hiscore_row(MenuScroller* scroller, scorefile_entry& se, int id) -{ - TextItem* tmp = nullptr; - tmp = new TextItem(); - - tmp->set_fg_colour(WHITE); - tmp->set_highlight_colour(WHITE); - - tmp->set_text(hiscores_format_single(se)); - tmp->set_description_text(hiscores_format_single_long(se, true)); - tmp->set_id(id); - tmp->set_bounds(coord_def(1,1), coord_def(1,2)); - - scroller->attach_item(tmp); - tmp->set_visible(true); -} - -static void _construct_hiscore_table(MenuScroller* scroller) -{ - FILE *scores = _hs_open("r", _score_file_name()); - - if (scores == nullptr) - return; - - int i; - // read highscore file - for (i = 0; i < SCORE_FILE_ENTRIES; i++) - { - hs_list[i].reset(new scorefile_entry); - if (_hs_read(scores, *hs_list[i]) == false) - break; - } - - _hs_close(scores, _score_file_name()); - - for (int j=0; j get_child_at_offset(int x, int y) override { + return static_pointer_cast(m_root); + } virtual void _render() override; virtual SizeReq _get_preferred_size(Direction dim, int prosp_width) override; virtual void _allocate_region() override; virtual bool on_event(const wm_event& event) override; - bool done; + void on_show(); + + bool done = false; + private: - PrecisionMenu menu; + void _construct_hiscore_table(); + void _add_hiscore_row(scorefile_entry& se, int id); + + Widget* initial_focus = nullptr; + bool have_allocated {false}; + + shared_ptr m_root; + shared_ptr m_description; + shared_ptr m_score_entries; }; -void UIHiscoresMenu::_render() -{ -#ifdef USE_TILE_LOCAL - GLW_3VF t = {(float)m_region[0], (float)m_region[1], 0}, s = {1, 1, 1}; - glmanager->set_transform(t, s); -#endif - menu.draw_menu(); -#ifdef USE_TILE_LOCAL - glmanager->reset_transform(); -#endif -} +static int nhsr; -SizeReq UIHiscoresMenu::_get_preferred_size(Direction dim, int prosp_width) +UIHiscoresMenu::UIHiscoresMenu() { - SizeReq ret; - if (!dim) - ret = { 80, 100 }; - else - ret = { 10, 10 }; -#ifdef USE_TILE_LOCAL - const FontWrapper* font = tiles.get_crt_font(); - const int f = !dim ? font->char_width() : font->char_height(); - ret.min *= f; - ret.nat *= f; -#endif - return ret; -} + m_root = make_shared(Widget::VERT); + m_root->_set_parent(this); -void UIHiscoresMenu::_allocate_region() -{ - menu.clear(); + auto title = make_shared(formatted_string( + "Dungeon Crawl Stone Soup: High Scores", YELLOW)); + title->align_self = Widget::CENTER; + title->set_margin_for_sdl({0, 0, 20, 0}); + m_description = make_shared(string(9, '\n')); -#ifdef USE_TILE_LOCAL - const FontWrapper* font = tiles.get_crt_font(); - const int max_col = m_region[2]/font->char_width(); - const int max_line = m_region[3]/font->char_height(); -#else - const int max_col = m_region[2] - 1, max_line = m_region[3] - 1; -#endif + m_score_entries= make_shared(true, 1, 100); + nhsr = 0; + _construct_hiscore_table(); - const int scores_col_start = 1; - const int descriptor_col_start = 1; - const int scores_row_start = 10; - const int scores_col_end = max_col; - const int scores_row_end = max_line+1; + m_root->add_child(move(title)); + m_root->add_child(m_description); + m_root->add_child(m_score_entries); +} - menu.set_select_type(PrecisionMenu::PRECISION_SINGLESELECT); +void UIHiscoresMenu::_construct_hiscore_table() +{ + FILE *scores = _hs_open("r", _score_file_name()); - MenuScroller* score_entries = new MenuScroller(); + if (scores == nullptr) + return; - score_entries->init(coord_def(scores_col_start, scores_row_start), - coord_def(scores_col_end, scores_row_end), "score entries"); + int i; + // read highscore file + for (i = 0; i < SCORE_FILE_ENTRIES; i++) + { + hs_list[i].reset(new scorefile_entry); + if (_hs_read(scores, *hs_list[i]) == false) + break; + } - _construct_hiscore_table(score_entries); + _hs_close(scores, _score_file_name()); - MenuDescriptor* descriptor = new MenuDescriptor(&menu); - descriptor->init(coord_def(descriptor_col_start, 1), - coord_def(max_col+1, scores_row_start - 1), - "descriptor"); + for (int j=0; jinit(coord_def(-1,-1), coord_def(-1,-1), "highlighter"); +void UIHiscoresMenu::_add_hiscore_row(scorefile_entry& se, int id) +{ + auto tmp = make_shared(); - MenuFreeform* freeform = new MenuFreeform(); - freeform->init(coord_def(1, 1), coord_def(max_col, max_line), "freeform"); - // This freeform will only contain unfocusable texts - freeform->allow_focus(false); - freeform->set_visible(true); + tmp->set_text(formatted_string(hiscores_format_single(se))); + auto btn = make_shared(); + tmp->set_margin_for_sdl({2,2,2,2}); + btn->set_child(move(tmp)); + btn->on(Widget::slots.event, [this, id, se](wm_event ev) { + if (ev.type == WME_MOUSEBUTTONUP && ev.mouse_event.button == MouseEvent::LEFT + || ev.type == WME_KEYDOWN && ev.key.keysym.sym == CK_ENTER) + { + _show_morgue(*hs_list[id]); + return true; + } + if (ev.type == WME_FOCUSIN) + { + formatted_string desc(hiscores_format_single_long(se, true)); + desc.cprintf(string(max(0, 9-count_linebreaks(desc)), '\n')); + m_description->set_text(move(desc)); + } + return false; + }); - score_entries->set_visible(true); - descriptor->set_visible(true); - highlighter->set_visible(true); + if (!initial_focus) + initial_focus = btn.get(); + m_score_entries->add_button(move(btn), 0, nhsr++); +} - menu.attach_object(freeform); - menu.attach_object(score_entries); - menu.attach_object(descriptor); - menu.attach_object(highlighter); +void UIHiscoresMenu::_render() +{ + m_root->render(); +} - menu.set_active_object(score_entries); - score_entries->set_active_item((MenuItem*) nullptr); - score_entries->activate_first_item(); +void UIHiscoresMenu::on_show() +{ + ui::set_focused_widget(initial_focus); +} - enable_smart_cursor(false); +SizeReq UIHiscoresMenu::_get_preferred_size(Direction dim, int prosp_width) +{ + return m_root->get_preferred_size(dim, prosp_width); } -bool UIHiscoresMenu::on_event(const wm_event& ev) +void UIHiscoresMenu::_allocate_region() { -#ifdef USE_TILE_LOCAL - if (ev.type == WME_MOUSEMOTION - || ev.type == WME_MOUSEBUTTONDOWN - || ev.type == WME_MOUSEWHEEL) + if (!have_allocated) { - MouseEvent mouse_ev = ev.mouse_event; - mouse_ev.px -= m_region[0]; - mouse_ev.py -= m_region[1]; - - int key = menu.handle_mouse(mouse_ev); - if (key && key != CK_NO_KEY) - { - wm_event fake_key = {0}; - fake_key.type = WME_KEYDOWN; - fake_key.key.keysym.sym = key; - on_event(fake_key); - } - - if (ev.type == WME_MOUSEMOTION) - _expose(); - return true; + have_allocated = true; + on_show(); } -#endif + m_root->allocate_region(m_region); +} +bool UIHiscoresMenu::on_event(const wm_event& ev) +{ if (ev.type != WME_KEYDOWN) return false; - int keyn = ev.key.keysym.sym; - - if (key_is_escape(keyn) || keyn == CK_MOUSE_CMD) + int key = ev.key.keysym.sym; + if (key_is_escape(key) || key == CK_MOUSE_CMD) return done = true; - - if (menu.process_key(keyn)) - { - menu.clear_selections(); - _show_morgue(*hs_list[menu.get_active_item()->get_id()]); - } - _expose(); - return true; } void show_hiscore_table() { unwind_var sprintmap(crawl_state.map, crawl_state.sprint_map); - - auto vbox = make_shared(Widget::VERT); - auto title = make_shared(formatted_string("Dungeon Crawl Stone Soup: High Scores", YELLOW)); - title->align_self = Widget::CENTER; - title->set_margin_for_sdl({0, 0, 20, 0}); - auto hiscore_ui = make_shared(); - vbox->add_child(move(title)); - vbox->add_child(hiscore_ui); - auto popup = make_shared(move(vbox)); - bool smart_cursor_enabled = is_smart_cursor_enabled(); + auto hiscore_ui = make_shared(); + auto popup = make_shared(hiscore_ui); ui::run_layout(move(popup), hiscore_ui->done); // Go back to the menu and return the smart cursor to its previous state From 9f778ef7993ea4a3b5ad60bc8e9a2fc804e94ac9 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 18 Aug 2018 21:38:41 +0800 Subject: [PATCH 669/864] Fix ui::Image widget using uninitialized data --- crawl-ref/source/ui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index 2f34d82d6872..17c42708d39a 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -419,7 +419,7 @@ class Image : public Widget protected: tile_def m_tile = {TILEG_ERROR, TEX_GUI}; - int m_tw, m_th; + int m_tw {0}, m_th {0}; #ifdef USE_TILE_LOCAL GenericTexture m_img; From b661a63e8a1073d44a45d1786a441040e94d3554 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 18 Aug 2018 21:45:06 +0800 Subject: [PATCH 670/864] Convert newgame menus to new UI framework --- crawl-ref/source/newgame.cc | 1690 +++++++---------- crawl-ref/source/newgame.h | 6 +- crawl-ref/source/rltiles/dc-gui.txt | 3 + .../source/rltiles/gui/tutorial/combat.png | Bin 0 -> 1448 bytes .../source/rltiles/gui/tutorial/movement.png | Bin 0 -> 2189 bytes crawl-ref/source/util/species-gen.py | 6 +- 6 files changed, 679 insertions(+), 1026 deletions(-) create mode 100644 crawl-ref/source/rltiles/gui/tutorial/combat.png create mode 100644 crawl-ref/source/rltiles/gui/tutorial/movement.png diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 6f64bc603dde..1eeb4309d4a3 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -34,9 +34,12 @@ #include "tilereg-crt.h" #include "tilepick.h" #include "tilefont.h" +#include "tiledef-main.h" +#include "tiledef-feat.h" #endif #include "version.h" #include "ui.h" +#include "outer-menu.h" using namespace ui; @@ -529,6 +532,22 @@ static void _choose_char(newgame_def& ng, newgame_def& choice, } } +static void _add_menu_sub_item(shared_ptr& menu, int x, int y, const string& text, const string& description, char letter, int id) +{ + auto tmp = make_shared(); + tmp->set_text(formatted_string(text, BROWN)); + tmp->set_margin_for_sdl({4,8,4,8}); + tmp->set_margin_for_crt({0,2,0,0}); + + auto btn = make_shared(); + btn->set_child(move(tmp)); + btn->id = id; + btn->description = description; + btn->hotkey = letter; + btn->highlight_colour = STARTUP_HIGHLIGHT_CONTROL; + menu->add_button(move(btn), x, y); +} + #ifndef DGAMELAUNCH /** * Attempt to generate a random name for a character that doesn't collide with @@ -737,6 +756,7 @@ static void _choose_seed(newgame_def& ng, newgame_def& choice, auto popup = make_shared(box); ui::push_layout(move(popup)); + ui::set_focused_widget(prompt_ui.get()); while (!done && !crawl_state.seen_hups) { formatted_string prompt; @@ -880,290 +900,12 @@ static void _mark_fully_random(newgame_def& ng, newgame_def& ng_choice, } } - -/** - * Helper function for _choose_species - * Constructs the menu screen - */ -static const int COLUMN_WIDTH = 35; -static const int X_MARGIN = 4; -static const int CHAR_DESC_START_Y = 16; -static const int CHAR_DESC_HEIGHT = 3; -static const int SPECIAL_KEYS_START_Y = CHAR_DESC_START_Y - + CHAR_DESC_HEIGHT + 1; - -static void _add_choice_menu_options(int choice_type, - const newgame_def& ng, - const newgame_def& defaults, - MenuFreeform* menu) -{ - string choice_name = choice_type == C_JOB ? "background" : "species"; - string other_choice_name = choice_type == C_JOB ? "species" : "background"; - - // Add all the special button entries - TextItem* tmp = new TextItem(); - if (choice_type == C_SPECIES) - tmp->set_text("+ - Recommended species"); - else - tmp->set_text("+ - Recommended background"); - coord_def min_coord = coord_def(X_MARGIN, SPECIAL_KEYS_START_Y); - coord_def max_coord = coord_def(min_coord.x + tmp->get_text().size(), - min_coord.y + 1); - tmp->set_bounds(min_coord, max_coord); - tmp->set_fg_colour(BROWN); - tmp->add_hotkey('+'); - // If the player has species chosen, use VIABLE, otherwise use RANDOM - if ((choice_type == C_SPECIES && ng.job != JOB_UNKNOWN) - || (choice_type == C_JOB && ng.species != SP_UNKNOWN)) - { - tmp->set_id(M_VIABLE); - } - else - tmp->set_id(M_RANDOM); - tmp->set_highlight_colour(STARTUP_HIGHLIGHT_CONTROL); - tmp->set_description_text("Picks a random recommended " + other_choice_name + " based on your current " + choice_name + " choice."); - menu->attach_item(tmp); - tmp->set_visible(true); - - tmp = new TextItem(); - tmp->set_text("# - Recommended character"); - min_coord.x = X_MARGIN; - min_coord.y = SPECIAL_KEYS_START_Y + 1; - max_coord.x = min_coord.x + tmp->get_text().size(); - max_coord.y = min_coord.y + 1; - tmp->set_bounds(min_coord, max_coord); - tmp->set_fg_colour(BROWN); - tmp->add_hotkey('#'); - tmp->set_id(M_VIABLE_CHAR); - tmp->set_highlight_colour(STARTUP_HIGHLIGHT_CONTROL); - tmp->set_description_text("Shuffles through random recommended character combinations " - "until you accept one."); - menu->attach_item(tmp); - tmp->set_visible(true); - - tmp = new TextItem(); - tmp->set_text("% - List aptitudes"); - min_coord.x = X_MARGIN; - min_coord.y = SPECIAL_KEYS_START_Y + 2; - max_coord.x = min_coord.x + tmp->get_text().size(); - max_coord.y = min_coord.y + 1; - tmp->set_bounds(min_coord, max_coord); - tmp->set_fg_colour(BROWN); - tmp->add_hotkey('%'); - tmp->set_id(M_APTITUDES); - tmp->set_highlight_colour(STARTUP_HIGHLIGHT_CONTROL); - tmp->set_description_text("Lists the numerical skill train aptitudes for all races."); - menu->attach_item(tmp); - tmp->set_visible(true); - - tmp = new TextItem(); - tmp->set_text("? - Help"); - min_coord.x = X_MARGIN; - min_coord.y = SPECIAL_KEYS_START_Y + 3; - max_coord.x = min_coord.x + tmp->get_text().size(); - max_coord.y = min_coord.y + 1; - tmp->set_bounds(min_coord, max_coord); - tmp->set_fg_colour(BROWN); - tmp->add_hotkey('?'); - tmp->set_id(M_HELP); - tmp->set_highlight_colour(STARTUP_HIGHLIGHT_CONTROL); - tmp->set_description_text("Opens the help screen."); - menu->attach_item(tmp); - tmp->set_visible(true); - - tmp = new TextItem(); - tmp->set_text("* - Random " + choice_name); - min_coord.x = X_MARGIN + COLUMN_WIDTH; - min_coord.y = SPECIAL_KEYS_START_Y; - max_coord.x = min_coord.x + tmp->get_text().size(); - max_coord.y = min_coord.y + 1; - tmp->set_bounds(min_coord, max_coord); - tmp->set_fg_colour(BROWN); - tmp->add_hotkey('*'); - tmp->set_id(M_RANDOM); - tmp->set_highlight_colour(STARTUP_HIGHLIGHT_CONTROL); - tmp->set_description_text("Picks a random " + choice_name + "."); - menu->attach_item(tmp); - tmp->set_visible(true); - - tmp = new TextItem(); - tmp->set_text("! - Random character"); - min_coord.x = X_MARGIN + COLUMN_WIDTH; - min_coord.y = SPECIAL_KEYS_START_Y + 1; - max_coord.x = min_coord.x + tmp->get_text().size(); - max_coord.y = min_coord.y + 1; - tmp->set_bounds(min_coord, max_coord); - tmp->set_fg_colour(BROWN); - tmp->add_hotkey('!'); - tmp->set_id(M_RANDOM_CHAR); - tmp->set_highlight_colour(STARTUP_HIGHLIGHT_CONTROL); - tmp->set_description_text("Shuffles through random character combinations " - "until you accept one."); - menu->attach_item(tmp); - tmp->set_visible(true); - - tmp = new TextItem(); - if ((choice_type == C_JOB && ng.species != SP_UNKNOWN) - || (choice_type == C_SPECIES && ng.job != JOB_UNKNOWN)) - { - tmp->set_text("Space - Change " + other_choice_name); - tmp->set_description_text("Lets you change your " + other_choice_name + - " choice."); - } - else - { - tmp->set_text("Space - Pick " + other_choice_name + " first"); - tmp->set_description_text("Lets you pick your " + other_choice_name + - " first."); - } - // Adjust the end marker to align the - because Space text is longer by 4 - min_coord.x = X_MARGIN + COLUMN_WIDTH - 4; - min_coord.y = SPECIAL_KEYS_START_Y + 2; - max_coord.x = min_coord.x + tmp->get_text().size(); - max_coord.y = min_coord.y + 1; - tmp->set_bounds(min_coord, max_coord); - tmp->set_fg_colour(BROWN); - tmp->add_hotkey(' '); - tmp->set_id(M_ABORT); - tmp->set_highlight_colour(STARTUP_HIGHLIGHT_CONTROL); - menu->attach_item(tmp); - tmp->set_visible(true); - - if (_char_defined(defaults)) - { - tmp = new TextItem(); - tmp->set_text("Tab - " + _char_description(defaults)); - // Adjust the end marker to align the - because Tab text is longer by 2 - min_coord.x = X_MARGIN + COLUMN_WIDTH - 2; - min_coord.y = SPECIAL_KEYS_START_Y + 3; - max_coord.x = min_coord.x + tmp->get_text().size(); - max_coord.y = min_coord.y + 1; - tmp->set_bounds(min_coord, max_coord); - tmp->set_fg_colour(BROWN); - tmp->add_hotkey('\t'); - tmp->set_id(M_DEFAULT_CHOICE); - tmp->set_highlight_colour(STARTUP_HIGHLIGHT_CONTROL); - tmp->set_description_text("Play a new game with your previous choice."); - menu->attach_item(tmp); - tmp->set_visible(true); - } -} - -static void _add_group_title(MenuFreeform* menu, - const char* name, - coord_def position, - int width) -{ - TextItem* tmp = new NoSelectTextItem(); - string text; - tmp->set_text(name); - tmp->set_fg_colour(LIGHTBLUE); - coord_def min_coord(2 + position.x, 3 + position.y); - coord_def max_coord(min_coord.x + width, min_coord.y + 1); - tmp->set_bounds(min_coord, max_coord); - menu->attach_item(tmp); - tmp->set_visible(true); -} - -static void _attach_group_item(MenuFreeform* menu, - menu_letter &letter, - int id, - int item_status, - string item_name, - bool is_active_item, - coord_def min_coord, - coord_def max_coord) - -{ - TextItem* tmp = new TextItem(); - - if (item_status == ITEM_STATUS_UNKNOWN) - { - tmp->set_fg_colour(LIGHTGRAY); - tmp->set_highlight_colour(STARTUP_HIGHLIGHT_NORMAL); - } - else if (item_status == ITEM_STATUS_RESTRICTED) - { - tmp->set_fg_colour(DARKGRAY); - tmp->set_highlight_colour(STARTUP_HIGHLIGHT_BAD); - } - else - { - tmp->set_fg_colour(WHITE); - tmp->set_highlight_colour(STARTUP_HIGHLIGHT_GOOD); - } - - string text; - text += letter; - text += " - "; - text += item_name; - tmp->set_text(text); - tmp->set_bounds(min_coord, max_coord); - tmp->add_hotkey(letter); - tmp->set_id(id); - tmp->set_description_text(unwrap_desc(getGameStartDescription(item_name))); - menu->attach_item(tmp); - tmp->set_visible(true); - if (is_active_item) - menu->set_active_item(tmp); -} - -void species_group::attach(const newgame_def& ng, const newgame_def& defaults, - MenuFreeform* menu, menu_letter &letter) -{ - _add_group_title(menu, name, position, width); - - coord_def min_coord(2 + position.x, 3 + position.y); - coord_def max_coord(min_coord.x + width, min_coord.y + 1); - - for (species_type &this_species : species_list) - { - if (this_species == SP_UNKNOWN) - break; - - if (ng.job == JOB_UNKNOWN && !is_starting_species(this_species)) - continue; - - if (ng.job != JOB_UNKNOWN - && species_allowed(ng.job, this_species) == CC_BANNED) - { - continue; - } - - int item_status; - if (ng.job == JOB_UNKNOWN) - item_status = ITEM_STATUS_UNKNOWN; - else if (species_allowed(ng.job, this_species) == CC_RESTRICTED) - item_status = ITEM_STATUS_RESTRICTED; - else - item_status = ITEM_STATUS_ALLOWED; - - const bool is_active_item = defaults.species == this_species; - - ++min_coord.y; - ++max_coord.y; - - _attach_group_item( - menu, - letter, - this_species, - item_status, - species_name(this_species), - is_active_item, - min_coord, - max_coord - ); - - ++letter; - } -} +class UINewGameMenu; static void _construct_species_menu(const newgame_def& ng, const newgame_def& defaults, - MenuFreeform* menu) + UINewGameMenu* ng_menu) { - ASSERT(menu != nullptr); - menu_letter letter = 'a'; // Add entries for any species groups with at least one playable species. for (species_group& group : species_groups) @@ -1176,87 +918,37 @@ static void _construct_species_menu(const newgame_def& ng, ) ) { - group.attach(ng, defaults, menu, letter); + group.attach(ng, defaults, ng_menu, letter); } } - - _add_choice_menu_options(C_SPECIES, ng, defaults, menu); -} - -void job_group::attach(const newgame_def& ng, const newgame_def& defaults, - MenuFreeform* menu, menu_letter &letter) -{ - _add_group_title(menu, name, position, width); - - coord_def min_coord(2 + position.x, 3 + position.y); - coord_def max_coord(min_coord.x + width, min_coord.y + 1); - - for (job_type &job : jobs) - { - if (job == JOB_UNKNOWN) - break; - - if (ng.species != SP_UNKNOWN - && job_allowed(ng.species, job) == CC_BANNED) - { - continue; - } - - int item_status; - if (ng.species == SP_UNKNOWN) - item_status = ITEM_STATUS_UNKNOWN; - else if (job_allowed(ng.species, job) == CC_RESTRICTED) - item_status = ITEM_STATUS_RESTRICTED; - else - item_status = ITEM_STATUS_ALLOWED; - - string job_name = get_job_name(job); - const bool is_active_item = defaults.job == job; - - ++min_coord.y; - ++max_coord.y; - - _attach_group_item( - menu, - letter, - job, - item_status, - job_name, - is_active_item, - min_coord, - max_coord - ); - - ++letter; - } } static job_group jobs_order[] = { { "Warrior", - coord_def(0, 0), 15, + coord_def(0, 0), 20, { JOB_FIGHTER, JOB_GLADIATOR, JOB_MONK, JOB_HUNTER, JOB_ASSASSIN } }, { "Adventurer", - coord_def(0, 7), 15, + coord_def(0, 7), 20, { JOB_ARTIFICER, JOB_WANDERER } }, { "Zealot", - coord_def(15, 0), 20, + coord_def(1, 0), 25, { JOB_BERSERKER, JOB_ABYSSAL_KNIGHT, JOB_CHAOS_KNIGHT } }, { "Warrior-mage", - coord_def(35, 0), 21, + coord_def(1, 5), 26, { JOB_SKALD, JOB_TRANSMUTER, JOB_WARPER, JOB_ARCANE_MARKSMAN, JOB_ENCHANTER } }, { "Mage", - coord_def(56, 0), 22, + coord_def(2, 0), 22, { JOB_WIZARD, JOB_CONJURER, JOB_SUMMONER, JOB_NECROMANCER, JOB_FIRE_ELEMENTALIST, JOB_ICE_ELEMENTALIST, JOB_AIR_ELEMENTALIST, JOB_EARTH_ELEMENTALIST, JOB_VENOM_MAGE } @@ -1269,7 +961,7 @@ static job_group jobs_order[] = */ static void _construct_backgrounds_menu(const newgame_def& ng, const newgame_def& defaults, - MenuFreeform* menu) + UINewGameMenu* ng_menu) { menu_letter letter = 'a'; // Add entries for any job groups with at least one playable background. @@ -1279,159 +971,275 @@ static void _construct_backgrounds_menu(const newgame_def& ng, || any_of(begin(group.jobs), end(group.jobs), [&ng](job_type job) { return job_allowed(ng.species, job) != CC_BANNED; })) { - group.attach(ng, defaults, menu, letter); + group.attach(ng, defaults, ng_menu, letter); } } - - _add_choice_menu_options(C_JOB, ng, defaults, menu); } class UINewGameMenu : public Widget { public: - UINewGameMenu(int _choice_type, newgame_def& _ng, newgame_def& _ng_choice, const newgame_def& _defaults) : done(false), end_game(false), cancel(false), choice_type(_choice_type), ng(_ng), ng_choice(_ng_choice), defaults(_defaults) {}; + UINewGameMenu(int _choice_type, newgame_def& _ng, newgame_def& _ng_choice, const newgame_def& _defaults) : m_choice_type(_choice_type), m_ng(_ng), m_ng_choice(_ng_choice), m_defaults(_defaults) + { + m_vbox = make_shared(Box::VERT); + m_vbox->_set_parent(this); + m_vbox->align_items = Widget::Align::STRETCH; + + formatted_string welcome; + welcome.textcolour(BROWN); + welcome.cprintf("%s", _welcome(m_ng).c_str()); + welcome.textcolour(YELLOW); + welcome.cprintf(" Please select your "); + welcome.cprintf(m_choice_type == C_JOB ? "background." : "species."); + m_vbox->add_child(make_shared(welcome)); + + descriptions = make_shared(); + + m_main_items = make_shared(true, 3, 20); + m_main_items->set_margin_for_crt({1, 0, 1, 0}); + m_main_items->set_margin_for_sdl({15, 0, 15, 0}); + m_main_items->descriptions = descriptions; + m_vbox->add_child(m_main_items); + +#ifndef USE_TILE_LOCAL + m_vbox->expand_h = true; + max_size() = { 80, INT_MAX }; +#endif + + descriptions->set_margin_for_crt({1, 0, 1, 0}); + descriptions->set_margin_for_sdl({0, 0, 15, 0}); + descriptions->current() = -1; + descriptions->shrink_h = true; + m_vbox->add_child(descriptions); + + if (m_choice_type == C_JOB) + _construct_backgrounds_menu(m_ng, m_defaults, this); + else + _construct_species_menu(m_ng, m_defaults, this); + + m_sub_items = make_shared(false, 2, 4); + m_sub_items->descriptions = descriptions; + m_vbox->add_child(m_sub_items); + _add_choice_menu_options(m_choice_type, m_ng, m_defaults); + + m_main_items->linked_menus[2] = m_sub_items; + m_sub_items->linked_menus[0] = m_main_items; + + m_main_items->on_button_activated = m_sub_items->on_button_activated = + [this](int id) { this->menu_item_activated(id); }; + + for (auto &w : m_main_items->get_buttons()) + { + w->on(Widget::slots.event, [w, this](wm_event ev) { + return this->button_event_hook(ev, w); + }); + } + for (auto &w : m_sub_items->get_buttons()) + { + w->on(Widget::slots.event, [w, this](wm_event ev) { + return this->button_event_hook(ev, w); + }); + } + }; + + virtual shared_ptr get_child_at_offset(int x, int y) override { + return static_pointer_cast(m_vbox); + } virtual void _render() override; virtual SizeReq _get_preferred_size(Direction dim, int prosp_width) override; virtual void _allocate_region() override; virtual bool on_event(const wm_event& event) override; - bool done; - bool end_game; - bool cancel; -private: - PrecisionMenu menu; + void menu_item_activated(int id); - int choice_type; - newgame_def& ng; - newgame_def& ng_choice; - const newgame_def& defaults; -}; + bool done = false; + bool end_game = false; + bool cancel = false; -void UINewGameMenu::_render() -{ -#ifdef USE_TILE_LOCAL - GLW_3VF t = {(float)m_region[0], (float)m_region[1], 0}, s = {1, 1, 1}; - glmanager->set_transform(t, s); -#endif - menu.draw_menu(); -#ifdef USE_TILE_LOCAL - glmanager->reset_transform(); -#endif -} +protected: + friend struct job_group; + friend struct species_group; + void _add_group_item(menu_letter &letter, + int id, + int item_status, + string item_name, + bool is_active_item, + coord_def position) -SizeReq UINewGameMenu::_get_preferred_size(Direction dim, int prosp_width) -{ - SizeReq ret; - if (!dim) - ret = { 80, 80 }; - else - ret = { 24, 24 }; -#ifdef USE_TILE_LOCAL - const FontWrapper* font = tiles.get_crt_font(); - const int f = !dim ? font->char_width() : font->char_height(); - ret.min *= f; - ret.nat *= f; -#endif - return ret; -} + { + auto label = make_shared(); -void UINewGameMenu::_allocate_region() -{ - menu.clear(); + COLOURS fg, hl; -#ifdef USE_TILE_LOCAL - const FontWrapper* font = tiles.get_crt_font(); - const int num_cols = m_region[2]/font->char_width(); - const int num_lines = m_region[3]/font->char_height(); -#else - const int num_cols = m_region[2], num_lines = m_region[3]; -#endif + if (item_status == ITEM_STATUS_UNKNOWN) + { + fg = LIGHTGRAY; + hl = STARTUP_HIGHLIGHT_NORMAL; + } + else if (item_status == ITEM_STATUS_RESTRICTED) + { + fg = DARKGRAY; + hl = STARTUP_HIGHLIGHT_BAD; + } + else + { + fg = WHITE; + hl = STARTUP_HIGHLIGHT_GOOD; + } - menu.set_select_type(PrecisionMenu::PRECISION_SINGLESELECT); - MenuFreeform* freeform = new MenuFreeform(); - freeform->init(coord_def(0,0), coord_def(num_cols + 1, num_lines + 1), "freeform"); - menu.attach_object(freeform); - menu.set_active_object(freeform); + string text; + text += letter; + text += " - "; + text += item_name; + label->set_text(formatted_string(text, fg)); - auto welcome_text = new FormattedTextItem(); - formatted_string welcome; - welcome.textcolour(BROWN); - welcome.cprintf("%s", _welcome(ng).c_str()); + string desc = unwrap_desc(getGameStartDescription(item_name)); + trim_string(desc); - welcome.textcolour(YELLOW); - if (choice_type == C_JOB) - { - welcome.cprintf(" Please select your background."); - _construct_backgrounds_menu(ng, defaults, freeform); + auto btn = make_shared(); + label->set_margin_for_sdl({2,2,2,2}); + btn->set_child(move(label)); + btn->id = id; + btn->description = desc; + btn->hotkey = letter; + btn->highlight_colour = hl; + btn->set_margin_for_crt({0,1,0,0}); + + m_main_items->add_button(btn, position.x, position.y); + + if (is_active_item || position == coord_def(0, 1)) + m_main_items->set_initial_focus(btn.get()); } - else + + void _add_group_title(const char* name, coord_def position) { - welcome.cprintf(" Please select your species."); - _construct_species_menu(ng, defaults, freeform); + auto text = make_shared(formatted_string(name, LIGHTBLUE)); + text->set_margin_for_sdl({7, 0, 7, 32+2+6}); + m_main_items->add_label(move(text), position.x, position.y); } - welcome_text->set_text(welcome.to_colour_string()); - welcome_text->set_bounds(coord_def(1, 1), coord_def(num_cols+1, 2)); - welcome_text->set_visible(true); - welcome_text->allow_highlight(false); - freeform->attach_item(welcome_text); - - MenuDescriptor* descriptor = new MenuDescriptor(&menu); - descriptor->init( - coord_def(X_MARGIN, CHAR_DESC_START_Y), - coord_def(num_cols, CHAR_DESC_START_Y + CHAR_DESC_HEIGHT), - "descriptor" - ); - menu.attach_object(descriptor); - - BoxMenuHighlighter* highlighter = new BoxMenuHighlighter(&menu); - highlighter->init(coord_def(0,0), coord_def(0,0), "highlighter"); - menu.attach_object(highlighter); - - // Did we have a previous background? - if (menu.get_active_item() == nullptr) - freeform->activate_first_item(); - - freeform->set_visible(true); - descriptor->set_visible(true); - highlighter->set_visible(true); -} + void _add_choice_menu_option(int x, int y, const string& text, char letter, + int id, const string& desc) + { + _add_menu_sub_item(m_sub_items, x, y, text, desc, letter, id); + } -bool UINewGameMenu::on_event(const wm_event& ev) -{ -#ifdef USE_TILE_LOCAL - if (ev.type == WME_MOUSEMOTION - || ev.type == WME_MOUSEBUTTONDOWN - || ev.type == WME_MOUSEWHEEL) + void _add_choice_menu_options(int choice_type, + const newgame_def& ng, + const newgame_def& defaults) { - MouseEvent mouse_ev = ev.mouse_event; - mouse_ev.px -= m_region[0]; - mouse_ev.py -= m_region[1]; + string choice_name = choice_type == C_JOB ? "background" : "species"; + string other_choice_name = choice_type == C_JOB ? "species" : "background"; + + string text, desc; - int key = menu.handle_mouse(mouse_ev); - if (key && key != CK_NO_KEY) + if (choice_type == C_SPECIES) + text = "+ - Recommended species"; + else + text = "+ - Recommended background"; + + int id; + // If the player has species chosen, use VIABLE, otherwise use RANDOM + if ((choice_type == C_SPECIES && ng.job != JOB_UNKNOWN) + || (choice_type == C_JOB && ng.species != SP_UNKNOWN)) { - wm_event fake_key = {0}; - fake_key.type = WME_KEYDOWN; - fake_key.key.keysym.sym = key; - on_event(fake_key); + id = M_VIABLE; } + else + id = M_RANDOM; + desc = "Picks a random recommended " + other_choice_name + " based on your current " + choice_name + " choice."; - if (ev.type == WME_MOUSEMOTION) - _expose(); - return true; + _add_choice_menu_option(0, 0, + text, '+', id, desc); + + _add_choice_menu_option(0, 1, + "# - Recommended character", '#', M_VIABLE_CHAR, + "Shuffles through random recommended character combinations " + "until you accept one."); + + _add_choice_menu_option(0, 2, + "% - List aptitudes", '%', M_APTITUDES, + "Lists the numerical skill train aptitudes for all races."); + + _add_choice_menu_option(0, 3, + "? - Help", '?', M_HELP, + "Opens the help screen."); + + _add_choice_menu_option(1, 0, + " * - Random " + choice_name, '*', M_RANDOM, + "Picks a random " + choice_name + "."); + + _add_choice_menu_option(1, 1, + " ! - Random character", '!', M_RANDOM_CHAR, + "Shuffles through random character combinations " + "until you accept one."); + + if ((choice_type == C_JOB && ng.species != SP_UNKNOWN) + || (choice_type == C_SPECIES && ng.job != JOB_UNKNOWN)) + { + text = "Space - Change " + other_choice_name; + desc = "Lets you change your " + other_choice_name + " choice."; + } + else + { + text = "Space - Pick " + other_choice_name + " first"; + desc = "Lets you pick your " + other_choice_name + " first."; + } + _add_choice_menu_option(1, 2, + text, ' ', M_ABORT, desc); + + if (_char_defined(defaults)) + { + _add_choice_menu_option(1, 3, + " Tab - " + _char_description(defaults), '\t', M_DEFAULT_CHOICE, + "Play a new game with your previous choice."); + } } -#endif +private: + bool button_event_hook(const wm_event& ev, MenuButton* btn) + { + if (ev.type == WME_KEYDOWN) + return on_event(ev); + return false; + } + + int m_choice_type; + newgame_def& m_ng; + newgame_def& m_ng_choice; + const newgame_def& m_defaults; + + shared_ptr m_vbox; + shared_ptr m_main_items; + shared_ptr m_sub_items; + shared_ptr description; + shared_ptr descriptions; +}; + +void UINewGameMenu::_render() +{ + m_vbox->render(); +} + +SizeReq UINewGameMenu::_get_preferred_size(Direction dim, int prosp_width) +{ + return m_vbox->get_preferred_size(dim, prosp_width); +} + +void UINewGameMenu::_allocate_region() +{ + m_vbox->allocate_region(m_region); +} + +bool UINewGameMenu::on_event(const wm_event& ev) +{ if (ev.type != WME_KEYDOWN) return false; int keyn = ev.key.keysym.sym; - _expose(); - // First process all the menu entries available - if (!menu.process_key(keyn)) + if (keyn != CK_ENTER) { // Process all the other keys that are not assigned to the menu switch (keyn) @@ -1446,108 +1254,180 @@ bool UINewGameMenu::on_event(const wm_event& ev) case CK_MOUSE_CMD: return done = cancel = true; case CK_BKSP: - if (choice_type == C_JOB) - ng_choice.job = JOB_UNKNOWN; + if (m_choice_type == C_JOB) + m_ng_choice.job = JOB_UNKNOWN; else - ng_choice.species = SP_UNKNOWN; + m_ng_choice.species = SP_UNKNOWN; return done = true; default: - // if we get this far, we did not get a significant selection - // from the menu, nor did we get an escape character - // continue the while loop from the beginning and poll a new key - return true; + break; } } - // We have had a significant input key event - // construct the return vector - vector selection = menu.get_selected_items(); - menu.clear_selections(); - if (!selection.empty()) - { - // we have a selection! - // we only care about the first selection (there should be only one) - int selection_key = selection.at(0)->get_id(); - bool viable = false; - switch (selection_key) + return false; +} + +void UINewGameMenu::menu_item_activated(int id) +{ + bool viable = false; + switch (id) + { + case M_VIABLE_CHAR: + viable = true; + // intentional fall-through + case M_RANDOM_CHAR: + _mark_fully_random(m_ng, m_ng_choice, viable); + done = true; + return; + case M_DEFAULT_CHOICE: + if (_char_defined(m_defaults)) { - case M_VIABLE_CHAR: - viable = true; - // intentional fall-through - case M_RANDOM_CHAR: - _mark_fully_random(ng, ng_choice, viable); - return done = true; - case M_DEFAULT_CHOICE: - if (_char_defined(defaults)) - { - _set_default_choice(ng, ng_choice, defaults); - return done = true; - } - else - { - // ignore default because we don't have previous start options - return true; - } - case M_ABORT: - ng.species = ng_choice.species = SP_UNKNOWN; - ng.job = ng_choice.job = JOB_UNKNOWN; - return done = true; - case M_HELP: - // access to the help files - if (choice_type == C_JOB) - show_help('2'); - else - show_help('1'); - return true; - case M_APTITUDES: - show_help('%', _highlight_pattern(ng)); - return true; - case M_VIABLE: - if (choice_type == C_JOB) - ng_choice.job = JOB_VIABLE; - else - ng_choice.species = SP_VIABLE; - return done = true; - case M_RANDOM: - if (choice_type == C_JOB) - ng_choice.job = JOB_RANDOM; - else - ng_choice.species = SP_RANDOM; - return done = true; - default: - // we have a selection - if (choice_type == C_JOB) + _set_default_choice(m_ng, m_ng_choice, m_defaults); + done = true; + } + // ignore default because we don't have previous start options + return; + case M_ABORT: + m_ng.species = m_ng_choice.species = SP_UNKNOWN; + m_ng.job = m_ng_choice.job = JOB_UNKNOWN; + done = true; + return; + case M_HELP: + show_help(m_choice_type == C_JOB ? '2' : '1'); + return; + case M_APTITUDES: + show_help('%', _highlight_pattern(m_ng)); + return; + case M_VIABLE: + if (m_choice_type == C_JOB) + m_ng_choice.job = JOB_VIABLE; + else + m_ng_choice.species = SP_VIABLE; + done = true; + return; + case M_RANDOM: + if (m_choice_type == C_JOB) + m_ng_choice.job = JOB_RANDOM; + else + m_ng_choice.species = SP_RANDOM; + done = true; + return; + default: + // we have a selection + if (m_choice_type == C_JOB) + { + job_type job = static_cast (id); + if (m_ng.species == SP_UNKNOWN + || job_allowed(m_ng.species, job) != CC_BANNED) { - job_type job = static_cast (selection_key); - if (ng.species == SP_UNKNOWN - || job_allowed(ng.species, job) != CC_BANNED) - { - ng_choice.job = job; - return done = true; - } - else - { - selection.at(0)->select(false); - return true; - } + m_ng_choice.job = job; + done = true; } - else + } + else + { + species_type species = static_cast (id); + if (m_ng.job == JOB_UNKNOWN + || species_allowed(m_ng.job, species) != CC_BANNED) { - species_type species = static_cast (selection_key); - if (ng.job == JOB_UNKNOWN - || species_allowed(ng.job, species) != CC_BANNED) - { - ng_choice.species = species; - return done = true; - } - else - return true; + m_ng_choice.species = species; + done = true; } } + return; + } +} + +void job_group::attach(const newgame_def& ng, const newgame_def& defaults, + UINewGameMenu* ng_menu, menu_letter &letter) +{ + ng_menu->_add_group_title(name, position); + + coord_def pos(position); + + for (job_type &job : jobs) + { + if (job == JOB_UNKNOWN) + break; + + if (ng.species != SP_UNKNOWN + && job_allowed(ng.species, job) == CC_BANNED) + { + continue; + } + + int item_status; + if (ng.species == SP_UNKNOWN) + item_status = ITEM_STATUS_UNKNOWN; + else if (job_allowed(ng.species, job) == CC_RESTRICTED) + item_status = ITEM_STATUS_RESTRICTED; + else + item_status = ITEM_STATUS_ALLOWED; + + const bool is_active_item = defaults.job == job; + + ++pos.y; + + ng_menu->_add_group_item( + letter, + job, + item_status, + get_job_name(job), + is_active_item, + pos + ); + + ++letter; } - return true; } +void species_group::attach(const newgame_def& ng, const newgame_def& defaults, + UINewGameMenu* ng_menu, menu_letter &letter) +{ + ng_menu->_add_group_title(name, position); + + coord_def pos(position); + + for (species_type &this_species : species_list) + { + if (this_species == SP_UNKNOWN) + break; + + if (ng.job == JOB_UNKNOWN && !is_starting_species(this_species)) + continue; + + if (ng.job != JOB_UNKNOWN + && species_allowed(ng.job, this_species) == CC_BANNED) + { + continue; + } + + int item_status; + if (ng.job == JOB_UNKNOWN) + item_status = ITEM_STATUS_UNKNOWN; + else if (species_allowed(ng.job, this_species) == CC_RESTRICTED) + item_status = ITEM_STATUS_RESTRICTED; + else + item_status = ITEM_STATUS_ALLOWED; + + const bool is_active_item = defaults.species == this_species; + + ++pos.y; + + ng_menu->_add_group_item( + letter, + this_species, + item_status, + species_name(this_species), + is_active_item, + pos + ); + + ++letter; + } +} + + /** * Prompt for job or species menu * Saves the choice to ng_choice, doesn't resolve random choices. @@ -1561,7 +1441,11 @@ static void _prompt_choice(int choice_type, newgame_def& ng, newgame_def& ng_cho auto newgame_ui = make_shared(choice_type, ng, ng_choice, defaults); auto popup = make_shared(newgame_ui); - ui::run_layout(move(popup), newgame_ui->done); + ui::push_layout(move(popup)); + ui::set_focused_widget(newgame_ui.get()); + while (!newgame_ui->done) + ui::pump_events(); + ui::pop_layout(); if (newgame_ui->end_game) end(0); @@ -1582,46 +1466,34 @@ static weapon_type _fixup_weapon(weapon_type wp, return WPN_UNKNOWN; } -static const int WEAPON_COLUMN_WIDTH = 40; static void _construct_weapon_menu(const newgame_def& ng, const weapon_type& defweapon, const vector& weapons, - MenuFreeform* menu) + shared_ptr& main_items, + shared_ptr& sub_items) { -#ifdef USE_TILE_LOCAL - static const int ITEMS_START_Y = 4; -#else - static const int ITEMS_START_Y = 5; -#endif string text; const char *thrown_name = nullptr; - coord_def min_coord(0,0); - coord_def max_coord(0,0); for (unsigned int i = 0; i < weapons.size(); ++i) { weapon_type wpn_type = weapons[i].first; char_choice_restriction wpn_restriction = weapons[i].second; + + auto label = make_shared(); + #ifdef USE_TILE_LOCAL - TextTileItem *tmp = new TextTileItem(); -#else - TextItem *tmp = new TextItem(); + auto hbox = make_shared(Box::HORZ); + hbox->align_items = Widget::Align::CENTER; + auto tile_stack = make_shared(); + tile_stack->set_margin_for_sdl({0, 6, 0, 0}); + hbox->add_child(tile_stack); + hbox->add_child(label); #endif + text.clear(); - if (wpn_restriction == CC_UNRESTRICTED) - { - tmp->set_fg_colour(WHITE); - tmp->set_highlight_colour(STARTUP_HIGHLIGHT_GOOD); - } - else - { - tmp->set_fg_colour(DARKGRAY); - tmp->set_highlight_colour(STARTUP_HIGHLIGHT_BAD); - } const char letter = 'a' + i; - tmp->add_hotkey(letter); - tmp->set_id(wpn_type); text += make_stringf(" %c - ", letter); switch (wpn_type) @@ -1629,34 +1501,38 @@ static void _construct_weapon_menu(const newgame_def& ng, case WPN_UNARMED: text += species_has_claws(ng.species) ? "claws" : "unarmed"; #ifdef USE_TILE_LOCAL - tmp->add_tile(tile_def(DNGN_UNSEEN, TEX_DEFAULT)); + tile_stack->min_size() = { TILE_Y, TILE_Y }; #endif break; case WPN_THROWN: // We don't support choosing among multiple thrown weapons. ASSERT(!thrown_name); #ifdef USE_TILE_LOCAL - tmp->add_tile(tile_def(TILE_MI_THROWING_NET, TEX_DEFAULT)); + tile_stack->add_child(make_shared( + tile_def(TILE_MI_THROWING_NET, TEX_DEFAULT))); #endif if (species_can_throw_large_rocks(ng.species)) { thrown_name = "large rocks"; #ifdef USE_TILE_LOCAL - tmp->add_tile(tile_def(TILE_MI_LARGE_ROCK, TEX_DEFAULT)); + tile_stack->add_child(make_shared( + tile_def(TILE_MI_LARGE_ROCK, TEX_DEFAULT))); #endif } else if (species_size(ng.species, PSIZE_TORSO) <= SIZE_SMALL) { thrown_name = "boomerangs"; #ifdef USE_TILE_LOCAL - tmp->add_tile(tile_def(TILE_MI_BOOMERANG, TEX_DEFAULT)); + tile_stack->add_child(make_shared( + tile_def(TILE_MI_BOOMERANG, TEX_DEFAULT))); #endif } else { thrown_name = "javelins"; #ifdef USE_TILE_LOCAL - tmp->add_tile(tile_def(TILE_MI_JAVELIN, TEX_DEFAULT)); + tile_stack->add_child(make_shared( + tile_def(TILE_MI_JAVELIN, TEX_DEFAULT))); #endif } text += thrown_name; @@ -1668,7 +1544,8 @@ static void _construct_weapon_menu(const newgame_def& ng, item_def dummy; dummy.base_type = OBJ_WEAPONS; dummy.sub_type = wpn_type; - tmp->add_tile(tile_def(tileidx_item(dummy), TEX_DEFAULT)); + tile_stack->add_child(make_shared( + tile_def(tileidx_item(dummy), TEX_DEFAULT))); #endif if (is_ranged_weapon_type(wpn_type)) { @@ -1679,106 +1556,44 @@ static void _construct_weapon_menu(const newgame_def& ng, } break; } - // Fill to column width to give extra padding for the highlight - text.append(WEAPON_COLUMN_WIDTH - text.size() - 1 , ' '); - tmp->set_text(text); + label->set_text(formatted_string(text, + wpn_restriction == CC_UNRESTRICTED ? WHITE : LIGHTGREY)); - min_coord.x = X_MARGIN; - min_coord.y = ITEMS_START_Y + i; - max_coord.x = min_coord.x + text.size(); + auto btn = make_shared(); #ifdef USE_TILE_LOCAL - const int cw = tiles.get_crt_font()->char_width(); - max_coord.x += (TILE_Y+cw-1)/cw; + hbox->set_margin_for_sdl({2,10,2,2}); + btn->set_child(move(hbox)); +#else + btn->set_child(move(label)); #endif - max_coord.y = min_coord.y + 1; - tmp->set_bounds(min_coord, max_coord); + btn->id = wpn_type; + btn->hotkey = letter; + + if (wpn_restriction == CC_UNRESTRICTED) + btn->highlight_colour = STARTUP_HIGHLIGHT_GOOD; + else + btn->highlight_colour = STARTUP_HIGHLIGHT_BAD; - menu->attach_item(tmp); - tmp->set_visible(true); // Is this item our default weapon? - if (wpn_type == defweapon) - menu->set_active_item(tmp); + if (wpn_type == defweapon || (defweapon == WPN_UNKNOWN && i == 0)) + main_items->set_initial_focus(btn.get()); + main_items->add_button(move(btn), 0, i); } - // Add all the special button entries - TextItem *tmp = new TextItem(); - tmp->set_text("+ - Recommended random choice"); - min_coord.x = X_MARGIN; - min_coord.y = SPECIAL_KEYS_START_Y; - max_coord.x = min_coord.x + tmp->get_text().size(); - max_coord.y = min_coord.y + 1; - tmp->set_bounds(min_coord, max_coord); - tmp->set_fg_colour(BROWN); - tmp->add_hotkey('+'); - tmp->set_id(M_VIABLE); - tmp->set_highlight_colour(STARTUP_HIGHLIGHT_CONTROL); - tmp->set_description_text("Picks a random recommended weapon"); - menu->attach_item(tmp); - tmp->set_visible(true); - - tmp = new TextItem(); - tmp->set_text("% - List aptitudes"); - min_coord.x = X_MARGIN; - min_coord.y = SPECIAL_KEYS_START_Y + 1; - max_coord.x = min_coord.x + tmp->get_text().size(); - max_coord.y = min_coord.y + 1; - tmp->set_bounds(min_coord, max_coord); - tmp->set_fg_colour(BROWN); - tmp->add_hotkey('%'); - tmp->set_id(M_APTITUDES); - tmp->set_highlight_colour(STARTUP_HIGHLIGHT_CONTROL); - tmp->set_description_text("Lists the numerical skill train aptitudes for all races"); - menu->attach_item(tmp); - tmp->set_visible(true); - - tmp = new TextItem(); - tmp->set_text("? - Help"); - min_coord.x = X_MARGIN; - min_coord.y = SPECIAL_KEYS_START_Y + 2; - max_coord.x = min_coord.x + tmp->get_text().size(); - max_coord.y = min_coord.y + 1; - tmp->set_bounds(min_coord, max_coord); - tmp->set_fg_colour(BROWN); - tmp->add_hotkey('?'); - tmp->set_id(M_HELP); - tmp->set_highlight_colour(STARTUP_HIGHLIGHT_CONTROL); - tmp->set_description_text("Opens the help screen"); - menu->attach_item(tmp); - tmp->set_visible(true); - - tmp = new TextItem(); - tmp->set_text("* - Random weapon"); - min_coord.x = X_MARGIN + COLUMN_WIDTH; - min_coord.y = SPECIAL_KEYS_START_Y; - max_coord.x = min_coord.x + tmp->get_text().size(); - max_coord.y = min_coord.y + 1; - tmp->set_bounds(min_coord, max_coord); - tmp->set_fg_colour(BROWN); - tmp->add_hotkey('*'); - tmp->set_id(WPN_RANDOM); - tmp->set_highlight_colour(STARTUP_HIGHLIGHT_CONTROL); - tmp->set_description_text("Picks a random weapon"); - menu->attach_item(tmp); - tmp->set_visible(true); - // Adjust the end marker to align the - because Bksp text is longer by 3 - tmp = new TextItem(); - tmp->set_text("Bksp - Return to character menu"); - tmp->set_description_text("Lets you return back to Character choice menu"); - min_coord.x = X_MARGIN + COLUMN_WIDTH - 3; - min_coord.y = SPECIAL_KEYS_START_Y + 1; - max_coord.x = min_coord.x + tmp->get_text().size(); - max_coord.y = min_coord.y + 1; - tmp->set_bounds(min_coord, max_coord); - tmp->set_fg_colour(BROWN); - tmp->add_hotkey(CK_BKSP); - tmp->set_id(M_ABORT); - tmp->set_highlight_colour(STARTUP_HIGHLIGHT_CONTROL); - menu->attach_item(tmp); - tmp->set_visible(true); + _add_menu_sub_item(sub_items, 0, 0, "+ - Recommended random choice", + "Picks a random recommended weapon", '+', M_VIABLE); + _add_menu_sub_item(sub_items, 0, 1, "% - List aptitudes", + "Lists the numerical skill train aptitudes for all races", '%', + M_APTITUDES); + _add_menu_sub_item(sub_items, 0, 2, "? - Help", + "Opens the help screen", '?', M_HELP); + _add_menu_sub_item(sub_items, 1, 0, "* - Random weapon", + "Picks a random weapon", '*', WPN_RANDOM); + _add_menu_sub_item(sub_items, 1, 1, "Bksp - Return to character menu", + "Lets you return back to Character choice menu", CK_BKSP, M_ABORT); if (defweapon != WPN_UNKNOWN) { - text.clear(); text = "Tab - "; ASSERT(defweapon != WPN_THROWN || thrown_name); @@ -1788,94 +1603,11 @@ static void _construct_weapon_menu(const newgame_def& ng, defweapon == WPN_THROWN ? thrown_name : weapon_base_name(defweapon); - // Adjust the end marker to aling the - because - // Tab text is longer by 2 - tmp = new TextItem(); - tmp->set_text(text); - min_coord.x = X_MARGIN + COLUMN_WIDTH - 2; - min_coord.y = SPECIAL_KEYS_START_Y + 2; - max_coord.x = min_coord.x + tmp->get_text().size(); - max_coord.y = min_coord.y + 1; - tmp->set_bounds(min_coord, max_coord); - tmp->set_fg_colour(BROWN); - tmp->add_hotkey('\t'); - tmp->set_id(M_DEFAULT_CHOICE); - tmp->set_highlight_colour(STARTUP_HIGHLIGHT_CONTROL); - tmp->set_description_text("Select your old weapon"); - menu->attach_item(tmp); - tmp->set_visible(true); + _add_menu_sub_item(sub_items, 1, 2, text, + "Select your old weapon", '\t', M_DEFAULT_CHOICE); } } -class UIPrecisionMenuWrapper : public Widget -{ -public: - UIPrecisionMenuWrapper(int _w, int _h, PrecisionMenu &_menu) : w(_w), h(_h), menu(_menu) {}; - - virtual void _render() override; - virtual SizeReq _get_preferred_size(Direction dim, int prosp_width) override; - virtual bool on_event(const wm_event& event) override; -private: - int w, h; - PrecisionMenu& menu; -}; - -SizeReq UIPrecisionMenuWrapper::_get_preferred_size(Direction dim, int prosp_width) -{ - SizeReq ret; - if (!dim) - ret = { w, w }; - else - ret = { h, h }; -#ifdef USE_TILE_LOCAL - const FontWrapper* font = tiles.get_crt_font(); - const int f = !dim ? font->char_width() : font->char_height(); - ret.min *= f; - ret.nat *= f; -#endif - return ret; -} - -void UIPrecisionMenuWrapper::_render() -{ -#ifdef USE_TILE_LOCAL - GLW_3VF t = {(float)m_region[0], (float)m_region[1], 0}, s = {1, 1, 1}; - glmanager->set_transform(t, s); -#endif - menu.draw_menu(); -#ifdef USE_TILE_LOCAL - glmanager->reset_transform(); -#endif -} - -bool UIPrecisionMenuWrapper::on_event(const wm_event& ev) -{ -#ifdef USE_TILE_LOCAL - if (ev.type == WME_MOUSEMOTION - || ev.type == WME_MOUSEBUTTONDOWN - || ev.type == WME_MOUSEWHEEL) - { - MouseEvent mouse_ev = ev.mouse_event; - mouse_ev.px -= m_region[0]; - mouse_ev.py -= m_region[1]; - - int key = menu.handle_mouse(mouse_ev); - if (key && key != CK_NO_KEY) - { - wm_event fake_key = {0}; - fake_key.type = WME_KEYDOWN; - fake_key.key.keysym.sym = key; - on_event(fake_key); - } - - if (ev.type == WME_MOUSEMOTION) - _expose(); - return true; - } -#endif - return Widget::on_event(ev); -} - /** * Returns false if user escapes */ @@ -1883,55 +1615,78 @@ static bool _prompt_weapon(const newgame_def& ng, newgame_def& ng_choice, const newgame_def& defaults, const vector& weapons) { - const int ui_w = 80, ui_h = 24; - PrecisionMenu menu; - menu.set_select_type(PrecisionMenu::PRECISION_SINGLESELECT); - MenuFreeform* freeform = new MenuFreeform(); - freeform->init(coord_def(1,1), coord_def(ui_w+1, ui_h+1), "freeform"); - menu.attach_object(freeform); - menu.set_active_object(freeform); - weapon_type defweapon = _fixup_weapon(defaults.weapon, weapons); - _construct_weapon_menu(ng, defweapon, weapons, freeform); - - BoxMenuHighlighter* highlighter = new BoxMenuHighlighter(&menu); - highlighter->init(coord_def(0,0), coord_def(0,0), "highlighter"); - menu.attach_object(highlighter); - - // Did we have a previous weapon? - if (menu.get_active_item() == nullptr) - freeform->activate_first_item(); - - auto welcome_text = new FormattedTextItem(); formatted_string welcome; welcome.textcolour(BROWN); welcome.cprintf("%s\n", _welcome(ng).c_str()); welcome.textcolour(CYAN); - welcome.cprintf("\nYou have a choice of weapons: "); - welcome_text->set_text(welcome.to_colour_string()); - welcome_text->set_bounds(coord_def(1, 1), coord_def(ui_w+1, 5)); - welcome_text->set_visible(true); - welcome_text->allow_highlight(false); - freeform->attach_item(welcome_text); + welcome.cprintf("\nYou have a choice of weapons:"); + + auto vbox = make_shared(Box::VERT); + vbox->align_items = Widget::Align::STRETCH; + vbox->add_child(make_shared(welcome)); - freeform->set_visible(true); - highlighter->set_visible(true); + auto main_items = make_shared(true, 1, weapons.size()); + main_items->set_margin_for_sdl({15, 0, 15, 0}); + main_items->set_margin_for_crt({1, 0, 1, 0}); + vbox->add_child(main_items); + + auto sub_items = make_shared(false, 2, 3); + vbox->add_child(sub_items); + + main_items->linked_menus[2] = sub_items; + sub_items->linked_menus[0] = main_items; + + _construct_weapon_menu(ng, defweapon, weapons, main_items, sub_items); bool done = false, ret = false; - auto prompt_ui = make_shared(ui_w, ui_h, menu); - prompt_ui->on(Widget::slots.event, [&](wm_event ev) { + + auto menu_item_activated = [&](int id) { + switch (id) + { + case M_ABORT: + ret = false; + done = true; + return; + case M_APTITUDES: + show_help('%', _highlight_pattern(ng)); + return; + case M_HELP: + show_help('?'); + return; + case M_DEFAULT_CHOICE: + if (defweapon != WPN_UNKNOWN) + { + ng_choice.weapon = defweapon; + break; + } + // No default weapon defined. + // This case should never happen in those cases but just in case + return; + case M_VIABLE: + ng_choice.weapon = WPN_VIABLE; + break; + case M_RANDOM: + ng_choice.weapon = WPN_RANDOM; + break; + default: + ng_choice.weapon = static_cast (id); + break; + } + ret = done = true; + }; + main_items->on_button_activated = menu_item_activated; + sub_items->on_button_activated = menu_item_activated; + + auto popup = make_shared(vbox); + popup->add_event_filter([&](wm_event ev) { if (ev.type != WME_KEYDOWN) return false; - int keyn = ev.key.keysym.sym; - prompt_ui->_expose(); + int key = ev.key.keysym.sym; - // First process menu entries - if (!menu.process_key(keyn)) + switch (key) { - // Process all the keys that are not attached to items - switch (keyn) - { case 'X': case CONTROL('Q'): #ifdef USE_TILE_WEB @@ -1945,65 +1700,11 @@ static bool _prompt_weapon(const newgame_def& ng, newgame_def& ng_choice, ret = false; return done = true; default: - // if we get this far, we did not get a significant selection - // from the menu, nor did we get an escape character - // continue the while loop from the beginning and poll a new key - return true; - } - } - // We have a significant key input! - // Construct selection vector - vector selection = menu.get_selected_items(); - menu.clear_selections(); - // There should only be one selection, otherwise something broke - if (selection.size() != 1) - { - // poll a new key - return true; - } - - // Get the stored id from the selection - int selection_ID = selection.at(0)->get_id(); - switch (selection_ID) - { - case M_ABORT: - ret = false; - return done = true; - case M_APTITUDES: - show_help('%', _highlight_pattern(ng)); - return true; - case M_HELP: - show_help('G', "weapons"); - return true; - case M_DEFAULT_CHOICE: - if (defweapon != WPN_UNKNOWN) - { - ng_choice.weapon = defweapon; - ret = true; - return done = true; - } - // No default weapon defined. - // This case should never happen in those cases but just in case - return true; - case M_VIABLE: - ng_choice.weapon = WPN_VIABLE; - ret = true; - return done = true; - case M_RANDOM: - ng_choice.weapon = WPN_RANDOM; - ret = true; - return done = true; - default: - // We got an item selection - ng_choice.weapon = static_cast (selection_ID); - ret = true; - return done = true; + break; } - return true; + return false; }); - - auto popup = make_shared(prompt_ui); ui::run_layout(move(popup), done); return ret; } @@ -2148,58 +1849,91 @@ static bool _choose_weapon(newgame_def& ng, newgame_def& ng_choice, return true; } +#ifdef USE_TILE_LOCAL +static tile_def tile_for_map_name(string name) +{ + if (starts_with(name, "Lesson ")) + { + const int i = name[7]-'1'; + ASSERT_RANGE(i, 0, 5); + constexpr tileidx_t tutorial_tiles[5] = { + TILEG_TUT_MOVEMENT, + TILEG_TUT_COMBAT, + TILEG_CMD_DISPLAY_INVENTORY, + TILEG_CMD_CAST_SPELL, + TILEG_CMD_USE_ABILITY, + }; + return tile_def(tutorial_tiles[i], TEX_GUI); + } + + if (name == "Sprint I: \"Red Sonja\"") + return tile_def(TILEP_MONS_SONJA, TEX_PLAYER); + if (name == "Sprint II: \"The Violet Keep of Menkaure\"") + return tile_def(TILEP_MONS_MENKAURE, TEX_PLAYER); + if (name == "Sprint III: \"The Ten Rune Challenge\"") + return tile_def(TILE_MISC_RUNE_OF_ZOT, TEX_DEFAULT); + if (name == "Sprint IV: \"Fedhas' Mad Dash\"") + return tile_def(TILE_DNGN_ALTAR_FEDHAS, TEX_FEAT); + if (name == "Sprint V: \"Ziggurat Sprint\"") + return tile_def(TILE_DNGN_PORTAL_ZIGGURAT, TEX_FEAT); + if (name == "Sprint VI: \"Thunderdome\"") + return tile_def(TILE_GOLD16, TEX_DEFAULT); + if (name == "Sprint VII: \"The Pits\"") + return tile_def(TILE_WALL_CRYPT_METAL + 2, TEX_WALL); + if (name == "Sprint VIII: \"Arena of Blood\"") + return tile_def(TILE_UNRAND_WOE, TEX_DEFAULT); + if (name == "Sprint IX: \"|||||||||||||||||||||||||||||\"") + return tile_def(TILE_WALL_LAB_METAL + 2, TEX_WALL); + return tile_def(0, TEX_GUI); +} +#endif + static void _construct_gamemode_map_menu(const mapref_vector& maps, const newgame_def& defaults, - MenuFreeform* menu) + shared_ptr& main_items, + shared_ptr& sub_items) { - static const int ITEMS_START_Y = 5; - static const int MENU_COLUMN_WIDTH = get_number_of_cols(); - TextItem* tmp = nullptr; string text; - coord_def min_coord(0,0); - coord_def max_coord(0,0); - bool activate_next = false; - - unsigned int padding_width = 0; - for (int i = 0; i < static_cast (maps.size()); i++) - { - padding_width = max(padding_width, - strwidth(maps.at(i)->desc_or_name())); - } - padding_width += 4; // Count the letter and " - " - padding_width = min(padding_width, MENU_COLUMN_WIDTH - 1); + bool activate_next = defaults.map == ""; for (int i = 0; i < static_cast (maps.size()); i++) { - tmp = new TextItem(); - text.clear(); - - tmp->set_fg_colour(LIGHTGREY); - tmp->set_highlight_colour(STARTUP_HIGHLIGHT_GOOD); + auto label = make_shared(); const char letter = 'a' + i; + + const string map_name = maps[i]->desc_or_name(); + text = " "; text += letter; text += " - "; + text += map_name; - text += maps[i]->desc_or_name(); - text = chop_string(text, padding_width); - - tmp->set_text(text); - tmp->add_hotkey(letter); - tmp->set_id(i); // ID corresponds to location in vector +#ifdef USE_TILE_LOCAL + auto hbox = make_shared(Box::HORZ); + hbox->align_items = Widget::Align::CENTER; + auto tile = make_shared(); + tile->set_tile(tile_for_map_name(map_name)); + tile->set_margin_for_sdl({0, 6, 0, 0}); + hbox->add_child(move(tile)); + hbox->add_child(label); +#endif - min_coord.x = X_MARGIN; - min_coord.y = ITEMS_START_Y + i; - max_coord.x = min_coord.x + text.size(); - max_coord.y = min_coord.y + 1; - tmp->set_bounds(min_coord, max_coord); + label->set_text(formatted_string(text, LIGHTGREY)); - menu->attach_item(tmp); - tmp->set_visible(true); + auto btn = make_shared(); +#ifdef USE_TILE_LOCAL + hbox->set_margin_for_sdl({2,10,2,2}); + btn->set_child(move(hbox)); +#else + btn->set_child(move(label)); +#endif + btn->id = i; // ID corresponds to location in vector + btn->hotkey = letter; + main_items->add_button(btn, 0, i); if (activate_next) { - menu->set_active_item(tmp); + main_items->set_initial_focus(btn.get()); activate_next = false; } // Is this item our default map? @@ -2208,57 +1942,20 @@ static void _construct_gamemode_map_menu(const mapref_vector& maps, if (crawl_state.last_game_exit.exit_reason == game_exit::win) activate_next = true; else - menu->set_active_item(tmp); + main_items->set_initial_focus(btn.get()); } } // Don't overwhelm new players with aptitudes or the full list of commands! if (!crawl_state.game_is_tutorial()) { - tmp = new TextItem(); - tmp->set_text("% - List aptitudes"); - min_coord.x = X_MARGIN; - min_coord.y = SPECIAL_KEYS_START_Y + 1; - max_coord.x = min_coord.x + tmp->get_text().size(); - max_coord.y = min_coord.y + 1; - tmp->set_bounds(min_coord, max_coord); - tmp->set_fg_colour(BROWN); - tmp->add_hotkey('%'); - tmp->set_id(M_APTITUDES); - tmp->set_highlight_colour(STARTUP_HIGHLIGHT_NORMAL); - tmp->set_description_text("Lists the numerical skill train aptitudes for all races"); - menu->attach_item(tmp); - tmp->set_visible(true); - - tmp = new TextItem(); - tmp->set_text("? - Help"); - min_coord.x = X_MARGIN; - min_coord.y = SPECIAL_KEYS_START_Y + 2; - max_coord.x = min_coord.x + tmp->get_text().size(); - max_coord.y = min_coord.y + 1; - tmp->set_bounds(min_coord, max_coord); - tmp->set_fg_colour(BROWN); - tmp->add_hotkey('?'); - tmp->set_id(M_HELP); - tmp->set_highlight_colour(STARTUP_HIGHLIGHT_NORMAL); - tmp->set_description_text("Opens the help screen"); - menu->attach_item(tmp); - tmp->set_visible(true); - - tmp = new TextItem(); - tmp->set_text("* - Random map"); - min_coord.x = X_MARGIN + COLUMN_WIDTH; - min_coord.y = SPECIAL_KEYS_START_Y + 1; - max_coord.x = min_coord.x + tmp->get_text().size(); - max_coord.y = min_coord.y + 1; - tmp->set_bounds(min_coord, max_coord); - tmp->set_fg_colour(BROWN); - tmp->add_hotkey('*'); - tmp->set_id(M_RANDOM); - tmp->set_highlight_colour(STARTUP_HIGHLIGHT_NORMAL); - tmp->set_description_text("Picks a random sprint map"); - menu->attach_item(tmp); - tmp->set_visible(true); + _add_menu_sub_item(sub_items, 0, 0, "% - List aptitudes", + "Lists the numerical skill train aptitudes for all races", + '%', M_APTITUDES); + _add_menu_sub_item(sub_items, 0, 1, "? - Help", + "Opens the help screen", '?', M_HELP); + _add_menu_sub_item(sub_items, 1, 0, "* - Random map", + "Picks a random sprint map", '*', M_RANDOM); } // TODO: let players escape back to first screen menu @@ -2266,42 +1963,22 @@ static void _construct_gamemode_map_menu(const mapref_vector& maps, //tmp = new TextItem(); //tmp->set_text("Bksp - Return to character menu"); //tmp->set_description_text("Lets you return back to Character choice menu"); - //min_coord.x = X_MARGIN + COLUMN_WIDTH - 3; - //min_coord.y = SPECIAL_KEYS_START_Y + 1; - //max_coord.x = min_coord.x + tmp->get_text().size(); - //max_coord.y = min_coord.y + 1; - //tmp->set_bounds(min_coord, max_coord); //tmp->set_fg_colour(BROWN); //tmp->add_hotkey(CK_BKSP); //tmp->set_id(M_ABORT); //tmp->set_highlight_colour(LIGHTGRAY); //menu->attach_item(tmp); - //tmp->set_visible(true); // Only add tab entry if we have a previous map choice if (crawl_state.game_is_sprint() && !defaults.map.empty() && defaults.type == GAME_TYPE_SPRINT && _char_defined(defaults)) { - tmp = new TextItem(); text.clear(); text += "Tab - "; text += defaults.map; - - // Adjust the end marker to align the - because - // Tab text is longer by 2 - tmp->set_text(text); - min_coord.x = X_MARGIN + COLUMN_WIDTH - 2; - min_coord.y = SPECIAL_KEYS_START_Y + 2; - max_coord.x = min_coord.x + tmp->get_text().size(); - max_coord.y = min_coord.y + 1; - tmp->set_bounds(min_coord, max_coord); - tmp->set_fg_colour(BROWN); - tmp->add_hotkey('\t'); - tmp->set_id(M_DEFAULT_CHOICE); - tmp->set_highlight_colour(STARTUP_HIGHLIGHT_NORMAL); - tmp->set_description_text("Select your previous sprint map and character"); - menu->attach_item(tmp); - tmp->set_visible(true); + _add_menu_sub_item(sub_items, 1, 1, text, + "Select your previous sprint map and character", '\t', + M_DEFAULT_CHOICE); } } @@ -2316,26 +1993,6 @@ static void _prompt_gamemode_map(newgame_def& ng, newgame_def& ng_choice, const newgame_def& defaults, mapref_vector maps) { - const int ui_w = 53, ui_h = 24; - PrecisionMenu menu; - menu.set_select_type(PrecisionMenu::PRECISION_SINGLESELECT); - MenuFreeform* freeform = new MenuFreeform(); - freeform->init(coord_def(1,1), coord_def(ui_w+1, ui_h+1), "freeform"); - menu.attach_object(freeform); - menu.set_active_object(freeform); - - sort(maps.begin(), maps.end(), _cmp_map_by_order); - _construct_gamemode_map_menu(maps, defaults, freeform); - - BoxMenuHighlighter* highlighter = new BoxMenuHighlighter(&menu); - highlighter->init(coord_def(0,0), coord_def(0,0), "highlighter"); - menu.attach_object(highlighter); - - // Did we have a previous sprint map? - if (menu.get_active_item() == nullptr) - freeform->activate_first_item(); - - auto welcome_text = new FormattedTextItem(); formatted_string welcome; welcome.textcolour(BROWN); welcome.cprintf("%s\n", _welcome(ng).c_str()); @@ -2343,31 +2000,66 @@ static void _prompt_gamemode_map(newgame_def& ng, newgame_def& ng_choice, welcome.cprintf("Custom seed: %" PRIu64 "\n", Options.seed_from_rc); welcome.textcolour(CYAN); - welcome.cprintf("\nYou have a choice of %s:\n\n", + welcome.cprintf("\nYou have a choice of %s:", ng_choice.type == GAME_TYPE_TUTORIAL ? "lessons" : "maps"); - welcome_text->set_text(welcome.to_colour_string()); - welcome_text->set_bounds(coord_def(1, 1), coord_def(ui_w+1, 5)); - welcome_text->set_visible(true); - welcome_text->allow_highlight(false); - freeform->attach_item(welcome_text); - freeform->set_visible(true); - highlighter->set_visible(true); + auto vbox = make_shared(Box::VERT); + vbox->align_items = Widget::Align::STRETCH; + vbox->add_child(make_shared(welcome)); + + auto main_items = make_shared(true, 1, maps.size()); + main_items->set_margin_for_sdl({15, 0, 15, 0}); + main_items->set_margin_for_crt({1, 0, 1, 0}); + vbox->add_child(main_items); + + auto sub_items = make_shared(false, 2, 2); + vbox->add_child(sub_items); + + main_items->linked_menus[2] = sub_items; + sub_items->linked_menus[0] = main_items; + + sort(maps.begin(), maps.end(), _cmp_map_by_order); + _construct_gamemode_map_menu(maps, defaults, main_items, sub_items); bool done = false, cancel = false; - auto prompt_ui = make_shared(ui_w, ui_h, menu); - prompt_ui->on(Widget::slots.event, [&](wm_event ev) { + + auto menu_item_activated = [&](int id) { + switch (id) + { + case M_ABORT: + // TODO: fix + break; + case M_APTITUDES: + show_help('%', _highlight_pattern(ng)); + return; + case M_HELP: + show_help('?'); + return; + case M_DEFAULT_CHOICE: + _set_default_choice(ng, ng_choice, defaults); + break; + case M_RANDOM: + // FIXME setting this to "random" is broken + ng_choice.map.clear(); + break; + default: + // We got an item selection + ng_choice.map = maps.at(id)->name; + break; + } + done = true; + }; + main_items->on_button_activated = menu_item_activated; + sub_items->on_button_activated = menu_item_activated; + + auto popup = make_shared(vbox); + popup->add_event_filter([&](wm_event ev) { if (ev.type != WME_KEYDOWN) return false; int keyn = ev.key.keysym.sym; - prompt_ui->_expose(); - // First process menu entries - if (!menu.process_key(keyn)) + switch (keyn) { - // Process all the keys that are not attached to items - switch (keyn) - { case 'X': case CONTROL('Q'): #ifdef USE_TILE_WEB @@ -2381,53 +2073,11 @@ static void _prompt_gamemode_map(newgame_def& ng, newgame_def& ng_choice, case ' ': return done = true; default: - // if we get this far, we did not get a significant selection - // from the menu, nor did we get an escape character - // continue the while loop from the beginning and poll a new key - return true; - } - } - // We have a significant key input! - // Construct selection vector - vector selection = menu.get_selected_items(); - menu.clear_selections(); - // There should only be one selection, otherwise something broke - if (selection.size() != 1) - { - // poll a new key - return true; - } - - // Get the stored id from the selection - int selection_ID = selection.at(0)->get_id(); - switch (selection_ID) - { - case M_ABORT: - // TODO: fix - return done = true; - case M_APTITUDES: - show_help('%', _highlight_pattern(ng)); - return true; - case M_HELP: - show_help('6'); - return true; - case M_DEFAULT_CHOICE: - _set_default_choice(ng, ng_choice, defaults); - return done = true; - case M_RANDOM: - // FIXME setting this to "random" is broken - ng_choice.map.clear(); - return done = true; - default: - // We got an item selection - ng_choice.map = maps.at(selection_ID)->name; - return done = true; + break; } - return true; + return false; }); - - auto popup = make_shared(prompt_ui); ui::run_layout(move(popup), done); if (cancel || crawl_state.seen_hups) diff --git a/crawl-ref/source/newgame.h b/crawl-ref/source/newgame.h index 46e7452bcc00..5d576635933b 100644 --- a/crawl-ref/source/newgame.h +++ b/crawl-ref/source/newgame.h @@ -8,7 +8,7 @@ #include "job-type.h" #include "species-type.h" -class MenuFreeform; +class UINewGameMenu; struct menu_letter; struct newgame_def; @@ -29,7 +29,7 @@ struct job_group /// A method to attach the group to a freeform. void attach(const newgame_def& ng, const newgame_def& defaults, - MenuFreeform* menu, menu_letter &letter); + UINewGameMenu* menu, menu_letter &letter); }; struct species_group @@ -41,5 +41,5 @@ struct species_group /// A method to attach the group to a freeform. void attach(const newgame_def& ng, const newgame_def& defaults, - MenuFreeform* menu, menu_letter &letter); + UINewGameMenu* menu, menu_letter &letter); }; diff --git a/crawl-ref/source/rltiles/dc-gui.txt b/crawl-ref/source/rltiles/dc-gui.txt index c589e17768ff..43b8b6e4005a 100644 --- a/crawl-ref/source/rltiles/dc-gui.txt +++ b/crawl-ref/source/rltiles/dc-gui.txt @@ -164,3 +164,6 @@ misc/error ERROR prompt_yes PROMPT_YES prompt_no PROMPT_NO + +tutorial/movement.png TUT_MOVEMENT +tutorial/combat.png TUT_COMBAT diff --git a/crawl-ref/source/rltiles/gui/tutorial/combat.png b/crawl-ref/source/rltiles/gui/tutorial/combat.png new file mode 100644 index 0000000000000000000000000000000000000000..7831a14912e89069ac4153670e08a0be2178b0ef GIT binary patch literal 1448 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 P00000NkvXXu0mjfJ7)u4 literal 0 HcmV?d00001 diff --git a/crawl-ref/source/util/species-gen.py b/crawl-ref/source/util/species-gen.py index 4df4a115c0a1..a4b103afc1e7 100755 --- a/crawl-ref/source/util/species-gen.py +++ b/crawl-ref/source/util/species-gen.py @@ -152,9 +152,9 @@ def from_yaml(self, s): SpeciesGroupEntry = collections.namedtuple('SpeciesGroupEntry', ['priority', 'enum']) SPECIES_GROUPS_TEMPLATE = { - 'Simple': SpeciesGroup('coord_def(0, 0)', '20', []), - 'Intermediate': SpeciesGroup('coord_def(25, 0)', '20', []), - 'Advanced': SpeciesGroup('coord_def(50, 0)', '20', []), + 'Simple': SpeciesGroup('coord_def(0, 0)', '50', []), + 'Intermediate': SpeciesGroup('coord_def(1, 0)', '20', []), + 'Advanced': SpeciesGroup('coord_def(2, 0)', '20', []), } SPECIES_GROUP_TEMPLATE = """ {{ From 23a394210770d58c132561ec7d5ce0e8c9c49642 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 18 Aug 2018 22:38:33 +0800 Subject: [PATCH 671/864] Add species/job tiles (CanOfWorms) --- crawl-ref/source/newgame.cc | 27 ++- crawl-ref/source/rltiles/dc-gui.txt | 187 ++++++++++++++++++ .../source/rltiles/gui/backgrounds/AE.png | Bin 0 -> 161 bytes .../source/rltiles/gui/backgrounds/AK.png | Bin 0 -> 203 bytes .../source/rltiles/gui/backgrounds/AM.png | Bin 0 -> 198 bytes .../source/rltiles/gui/backgrounds/Ar.png | Bin 0 -> 156 bytes .../source/rltiles/gui/backgrounds/As.png | Bin 0 -> 168 bytes .../source/rltiles/gui/backgrounds/Be.png | Bin 0 -> 169 bytes .../source/rltiles/gui/backgrounds/CK.png | Bin 0 -> 1021 bytes .../source/rltiles/gui/backgrounds/Cj.png | Bin 0 -> 187 bytes .../source/rltiles/gui/backgrounds/EE.png | Bin 0 -> 134 bytes .../source/rltiles/gui/backgrounds/En.png | Bin 0 -> 166 bytes .../source/rltiles/gui/backgrounds/FE.png | Bin 0 -> 190 bytes .../source/rltiles/gui/backgrounds/Fi.png | Bin 0 -> 164 bytes .../source/rltiles/gui/backgrounds/Gl.png | Bin 0 -> 161 bytes .../source/rltiles/gui/backgrounds/Hu.png | Bin 0 -> 169 bytes .../source/rltiles/gui/backgrounds/IE.png | Bin 0 -> 139 bytes .../source/rltiles/gui/backgrounds/Mo.png | Bin 0 -> 157 bytes .../source/rltiles/gui/backgrounds/Ne.png | Bin 0 -> 170 bytes .../source/rltiles/gui/backgrounds/Sk.png | Bin 0 -> 154 bytes .../source/rltiles/gui/backgrounds/Su.png | Bin 0 -> 196 bytes .../source/rltiles/gui/backgrounds/Tm.png | Bin 0 -> 220 bytes .../source/rltiles/gui/backgrounds/VM.png | Bin 0 -> 212 bytes .../source/rltiles/gui/backgrounds/Wn.png | Bin 0 -> 967 bytes .../source/rltiles/gui/backgrounds/Wr.png | Bin 0 -> 154 bytes .../source/rltiles/gui/backgrounds/Wz.png | Bin 0 -> 201 bytes .../rltiles/gui/backgrounds/disabled-fg.png | 1 + .../rltiles/gui/backgrounds/enabled-fg.png | 1 + crawl-ref/source/tilepick.cc | 132 +++++++++++++ crawl-ref/source/tilepick.h | 4 + 30 files changed, 351 insertions(+), 1 deletion(-) create mode 100644 crawl-ref/source/rltiles/gui/backgrounds/AE.png create mode 100644 crawl-ref/source/rltiles/gui/backgrounds/AK.png create mode 100644 crawl-ref/source/rltiles/gui/backgrounds/AM.png create mode 100644 crawl-ref/source/rltiles/gui/backgrounds/Ar.png create mode 100644 crawl-ref/source/rltiles/gui/backgrounds/As.png create mode 100644 crawl-ref/source/rltiles/gui/backgrounds/Be.png create mode 100644 crawl-ref/source/rltiles/gui/backgrounds/CK.png create mode 100644 crawl-ref/source/rltiles/gui/backgrounds/Cj.png create mode 100644 crawl-ref/source/rltiles/gui/backgrounds/EE.png create mode 100644 crawl-ref/source/rltiles/gui/backgrounds/En.png create mode 100644 crawl-ref/source/rltiles/gui/backgrounds/FE.png create mode 100644 crawl-ref/source/rltiles/gui/backgrounds/Fi.png create mode 100644 crawl-ref/source/rltiles/gui/backgrounds/Gl.png create mode 100644 crawl-ref/source/rltiles/gui/backgrounds/Hu.png create mode 100644 crawl-ref/source/rltiles/gui/backgrounds/IE.png create mode 100644 crawl-ref/source/rltiles/gui/backgrounds/Mo.png create mode 100644 crawl-ref/source/rltiles/gui/backgrounds/Ne.png create mode 100644 crawl-ref/source/rltiles/gui/backgrounds/Sk.png create mode 100644 crawl-ref/source/rltiles/gui/backgrounds/Su.png create mode 100644 crawl-ref/source/rltiles/gui/backgrounds/Tm.png create mode 100644 crawl-ref/source/rltiles/gui/backgrounds/VM.png create mode 100644 crawl-ref/source/rltiles/gui/backgrounds/Wn.png create mode 100644 crawl-ref/source/rltiles/gui/backgrounds/Wr.png create mode 100644 crawl-ref/source/rltiles/gui/backgrounds/Wz.png create mode 120000 crawl-ref/source/rltiles/gui/backgrounds/disabled-fg.png create mode 120000 crawl-ref/source/rltiles/gui/backgrounds/enabled-fg.png diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 1eeb4309d4a3..42bad1d93224 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -1064,12 +1064,25 @@ class UINewGameMenu : public Widget int id, int item_status, string item_name, +#ifdef USE_TILE_LOCAL + tile_def item_tile, +#endif bool is_active_item, coord_def position) { auto label = make_shared(); +#ifdef USE_TILE_LOCAL + auto hbox = make_shared(Box::HORZ); + hbox->align_items = Widget::Align::CENTER; + auto tile = make_shared(); + tile->set_tile(item_tile); + tile->set_margin_for_sdl({0, 6, 0, 0}); + hbox->add_child(move(tile)); + hbox->add_child(label); +#endif + COLOURS fg, hl; if (item_status == ITEM_STATUS_UNKNOWN) @@ -1098,8 +1111,12 @@ class UINewGameMenu : public Widget trim_string(desc); auto btn = make_shared(); - label->set_margin_for_sdl({2,2,2,2}); +#ifdef USE_TILE_LOCAL + hbox->set_margin_for_sdl({2,10,2,2}); + btn->set_child(move(hbox)); +#else btn->set_child(move(label)); +#endif btn->id = id; btn->description = desc; btn->hotkey = letter; @@ -1373,6 +1390,10 @@ void job_group::attach(const newgame_def& ng, const newgame_def& defaults, job, item_status, get_job_name(job), +#ifdef USE_TILE_LOCAL + tile_def(tileidx_player_job(job, + item_status != ITEM_STATUS_RESTRICTED), TEX_GUI), +#endif is_active_item, pos ); @@ -1419,6 +1440,10 @@ void species_group::attach(const newgame_def& ng, const newgame_def& defaults, this_species, item_status, species_name(this_species), +#ifdef USE_TILE_LOCAL + tile_def(tileidx_player_species(this_species, + item_status != ITEM_STATUS_RESTRICTED), TEX_GUI), +#endif is_active_item, pos ); diff --git a/crawl-ref/source/rltiles/dc-gui.txt b/crawl-ref/source/rltiles/dc-gui.txt index 43b8b6e4005a..7d420b3b895e 100644 --- a/crawl-ref/source/rltiles/dc-gui.txt +++ b/crawl-ref/source/rltiles/dc-gui.txt @@ -167,3 +167,190 @@ prompt_no PROMPT_NO tutorial/movement.png TUT_MOVEMENT tutorial/combat.png TUT_COMBAT + +%texture backgrounds/enabled-fg +backgrounds/Fi.png JOB_RECOMMENDED_FIGHTER +backgrounds/Gl.png JOB_RECOMMENDED_GLADIATOR +backgrounds/Mo.png JOB_RECOMMENDED_MONK +backgrounds/Hu.png JOB_RECOMMENDED_HUNTER +backgrounds/As.png JOB_RECOMMENDED_ASSASSIN +backgrounds/Ar.png JOB_RECOMMENDED_ARTIFICER +backgrounds/Wn.png JOB_RECOMMENDED_WANDERER +backgrounds/Be.png JOB_RECOMMENDED_BERSERKER +backgrounds/AK.png JOB_RECOMMENDED_ABYSSAL_KNIGHT +backgrounds/CK.png JOB_RECOMMENDED_CHAOS_KNIGHT +backgrounds/Sk.png JOB_RECOMMENDED_SKALD +backgrounds/Tm.png JOB_RECOMMENDED_TRANSMUTER +backgrounds/AM.png JOB_RECOMMENDED_ARCANE_MARKSMAN +backgrounds/Wr.png JOB_RECOMMENDED_WARPER +backgrounds/En.png JOB_RECOMMENDED_ENCHANTER +backgrounds/Wz.png JOB_RECOMMENDED_WIZARD +backgrounds/Cj.png JOB_RECOMMENDED_CONJURER +backgrounds/Su.png JOB_RECOMMENDED_SUMMONER +backgrounds/Ne.png JOB_RECOMMENDED_NECROMANCER +backgrounds/FE.png JOB_RECOMMENDED_FIRE_ELEMENTALIST +backgrounds/IE.png JOB_RECOMMENDED_ICE_ELEMENTALIST +backgrounds/AE.png JOB_RECOMMENDED_AIR_ELEMENTALIST +backgrounds/EE.png JOB_RECOMMENDED_EARTH_ELEMENTALIST +backgrounds/VM.png JOB_RECOMMENDED_VENOM_MAGE +%syn LAST_RECOMMENDED_JOB + +%texture backgrounds/disabled-fg +backgrounds/Fi.png JOB_FIGHTER +backgrounds/Gl.png JOB_GLADIATOR +backgrounds/Mo.png JOB_MONK +backgrounds/Hu.png JOB_HUNTER +backgrounds/As.png JOB_ASSASSIN +backgrounds/Ar.png JOB_ARTIFICER +backgrounds/Wn.png JOB_WANDERER +backgrounds/Be.png JOB_BERSERKER +backgrounds/AK.png JOB_ABYSSAL_KNIGHT +backgrounds/CK.png JOB_CHAOS_KNIGHT +backgrounds/Sk.png JOB_SKALD +backgrounds/Tm.png JOB_TRANSMUTER +backgrounds/AM.png JOB_ARCANE_MARKSMAN +backgrounds/Wr.png JOB_WARPER +backgrounds/En.png JOB_ENCHANTER +backgrounds/Wz.png JOB_WIZARD +backgrounds/Cj.png JOB_CONJURER +backgrounds/Su.png JOB_SUMMONER +backgrounds/Ne.png JOB_NECROMANCER +backgrounds/FE.png JOB_FIRE_ELEMENTALIST +backgrounds/IE.png JOB_ICE_ELEMENTALIST +backgrounds/AE.png JOB_AIR_ELEMENTALIST +backgrounds/EE.png JOB_EARTH_ELEMENTALIST +backgrounds/VM.png JOB_VENOM_MAGE +%syn LAST_JOB + + +%texture none +../player/felids/cat3.png SP_RECOMMENDED_FELID +%start +%compose ../player/base/centaur_lightgrey_f.png +%compose ../player/body/animal_skin.png +%finish SP_RECOMMENDED_CENTAUR +%start +%compose ../player/base/deep_dwarf_m.png +%compose ../player/body/animal_skin.png +%finish SP_RECOMMENDED_DEEP_DWARF +%start +%compose ../player/base/deep_elf_f.png +%compose ../player/body/animal_skin.png +%finish SP_RECOMMENDED_DEEP_ELF +%start +%compose ../player/base/demigod_f.png +%compose ../player/body/animal_skin.png +%finish SP_RECOMMENDED_DEMIGOD +%start +%compose ../player/base/demonspawn_pink.png +%compose ../player/body/animal_skin.png +%finish SP_RECOMMENDED_DEMONSP_RECOMMENDEDAWN +%start +%compose ../player/base/draconian_f.png +%compose ../player/body/animal_skin.png +%finish SP_RECOMMENDED_BASE_DRACONIAN +%start +%compose ../player/base/formicid.png +%compose ../player/body/animal_skin.png +%finish SP_RECOMMENDED_FORMICID +%start +%compose ../player/base/frog_m.png +%compose ../player/body/animal_skin.png +%finish SP_RECOMMENDED_BARACHI +%start +%compose ../player/base/gargoyle_m.png +%compose ../player/body/animal_skin.png +%finish SP_RECOMMENDED_GARGOYLE +%start +%compose ../player/base/ghoul_m.png +%compose ../player/body/animal_skin.png +%finish SP_RECOMMENDED_GHOUL +%start +%compose ../player/base/gnoll_m.png +%compose ../player/body/animal_skin.png +%finish SP_RECOMMENDED_GNOLL +%start +%compose ../player/base/halfling_m.png +%compose ../player/body/animal_skin.png +%finish SP_RECOMMENDED_HALFLING +%start +%compose ../player/base/human_f.png +%compose ../player/body/animal_skin.png +%finish SP_RECOMMENDED_HuMAN +%start +%compose ../player/base/kobold_m.png +%compose ../player/body/animal_skin.png +%finish SP_RECOMMENDED_KOBOLD +%start +%compose ../player/base/merfolk_water_f.png +%compose ../player/body/animal_skin.png +%finish SP_RECOMMENDED_MERFOLK +%start +%compose ../player/base/minotaur_m.png +%compose ../player/body/animal_skin.png +%finish SP_RECOMMENDED_MINOTAUR +../player/base/mummy_m.png SP_RECOMMENDED_MUMMY +%start +%compose ../player/base/naga_f.png +%compose ../player/body/animal_skin.png +%finish SP_RECOMMENDED_NAGA +../player/base/octopode1.png SP_RECOMMENDED_OCTOPODE +%start +%compose ../player/base/ogre_m.png +%compose ../player/body/animal_skin.png +%finish SP_RECOMMENDED_OGRE +%start +%compose ../player/base/orc_f.png +%compose ../player/body/animal_skin.png +%finish SP_RECOMMENDED_HILL_ORC +%start +%compose ../player/base/spriggan_m.png +%compose ../player/body/animal_skin.png +%finish SP_RECOMMENDED_SP_RECOMMENDEDRIGGAN +%start +%compose ../player/base/tengu_winged_f.png +%compose ../player/body/animal_skin.png +%finish SP_RECOMMENDED_TENGU +%start +%compose ../player/base/troll_f.png +%compose ../player/body/animal_skin.png +%finish SP_RECOMMENDED_TROLL +%start +%compose ../player/base/vampire_f.png +%compose ../player/body/animal_skin.png +%finish SP_RECOMMENDED_VAMPIRE +%start +%compose ../player/base/vine_stalker_f.png +%compose ../player/body/animal_skin.png +%finish SP_RECOMMENDED_VINE_STALKER +%syn LAST_RECOMMENDED_SPECIES + +%texture backgrounds/disabled-fg +../player/felids/cat3.png SP_FELID +../player/base/centaur_lightgrey_f.png SP_CENTAUR +../player/base/deep_dwarf_m.png SP_DEEP_DWARF +../player/base/deep_elf_f.png SP_DEEP_ELF +../player/base/demigod_f.png SP_DEMIGOD +../player/base/demonspawn_pink.png SP_DEMONSPAWN +../player/base/draconian_f.png SP_DRACONIAN +../player/base/formicid.png SP_FORMICID +../player/base/frog_m.png SP_BARACHI +../player/base/gargoyle_m.png SP_GARGOYLE +../player/base/ghoul_m.png SP_GHOUL +../player/base/gnoll_m.png SP_GNOLL +../player/base/halfling_m.png SP_HALFLING +../player/base/human_f.png SP_HUMAN +../player/base/kobold_m.png SP_KOBOLD +../player/base/merfolk_water_f.png SP_MERFOLK +../player/base/minotaur_m.png SP_MINOTAUR +../player/base/mummy_m.png SP_MUMMY +../player/base/naga_f.png SP_NAGA +../player/base/octopode1.png SP_OCTOPODE +../player/base/ogre_m.png SP_OGRE +../player/base/orc_f.png SP_HILL_ORC +../player/base/spriggan_m.png SP_SPRIGGAN +../player/base/tengu_wingless_f.png SP_TENGU +../player/base/troll_f.png SP_TROLL +../player/base/vampire_f.png SP_VAMPIRE +../player/base/vine_stalker_f.png SP_VINE_STALKER +%syn LAST_SPECIES diff --git a/crawl-ref/source/rltiles/gui/backgrounds/AE.png b/crawl-ref/source/rltiles/gui/backgrounds/AE.png new file mode 100644 index 0000000000000000000000000000000000000000..8dbc6c30f11ab9efdec9e526d55cd560d48f43b2 GIT binary patch literal 161 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyJOMr-u0Z-f3|JhnUIFAYmjw9* zGq@aVV%YN&$aVB|aSW+oOqSTzFtJmTqrkg4WoAKkI@{}I8*Pl^DxKc7YaGsH=#jHv xAGC6e;MBRz9Q7NU@z0bjENDdKGSm$CQbX4g)jZ492SelF{r5}E)q&rh}h literal 0 HcmV?d00001 diff --git a/crawl-ref/source/rltiles/gui/backgrounds/Ar.png b/crawl-ref/source/rltiles/gui/backgrounds/Ar.png new file mode 100644 index 0000000000000000000000000000000000000000..69a3106c44741982b22616ea225edb6286485c7a GIT binary patch literal 156 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyYymzYu0Z<#|Nl#G&c6#}F_r}R z1v5B2yO9P`<>}%WQo)!kv8Z992W!ubr2;BtXE~Z0{`QDeHcb@VZ^I!F!mx0|DIo*K zRnwi=oepu%XW|f^Zqwv^gOORkU$W(}6a&LD2Zn&HspqwT<}rA>`njxgN@xNA1s5)S literal 0 HcmV?d00001 diff --git a/crawl-ref/source/rltiles/gui/backgrounds/As.png b/crawl-ref/source/rltiles/gui/backgrounds/As.png new file mode 100644 index 0000000000000000000000000000000000000000..0aa9d37a499af5b939ffb8ca1b2f7f738a32801c GIT binary patch literal 168 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyJOMr-u0Z-f3|JhnUIFAYmjw9* zGq@aVV%YN&$o24aaSW+oOkQ9l!Fr~JWyVay9~n#m49SUF4a{634VoIgD;qeqn3m7D zAY$P3^#E@|%7IrL3arVA3?=H1!W*r394vD1DK+3?5L?LDC^g+Q5@;rar>mdKI;Vst E0B5H(*Z=?k literal 0 HcmV?d00001 diff --git a/crawl-ref/source/rltiles/gui/backgrounds/Be.png b/crawl-ref/source/rltiles/gui/backgrounds/Be.png new file mode 100644 index 0000000000000000000000000000000000000000..7533f54023e3ff77f4a22d6d57af8f4f2f1e4a9d GIT binary patch literal 169 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyJOMr-u0Z-f3|JhnUIFAYmjw9* zGn5_7FL==b zaB^>EX>4U6ba`-PAZ2)IW&i+q+U=HGaw97YhTmDmECERf!E(4(%?{4;&rf&z5~rOw zC#h5OFi>vVLP$cNz;@%G-_!jFx zM!_h%(84h*hy0=+uOkedOprb-kgFTMcWmX5v*$Mv4Y~TbZRhyR+0&e3-(3k2X^8u# zb{Fnq28tC~l5JT;H+&TDw)KpjeDRHf@4oqp-Y653_(_4fqe7Dgb&QP~VhlXkFfuom zO_szsa}zHlVRf2plBG)$mc~Owf)l>RLYv>b`D>Kmxf4{GV2rTj!|py)c%{$TJaR;Y z-P4gP#KpWg&`P7MC)5Ch=D|(31Yi2KxjV1|g1V(SVS~lj-9%No)s}1pAkb5cdwr4h zMUA&A3Gl55h6D(FBvFdwjoFBTZ~~x$$XNnc5Fl0V2$F+H1e=69f^V!b+H_fYm*c2_ zk4h8+n=A#eLQvF?g@hU^DjHNZs%g@!#YKrBYK+n1I&;Ouf~iF_OO~x9Ng-*9$x=!= zmCRXiBsIruIpv&7fzJ|L(Sp?l8l_aOQbW}mtJPF|UUNF$FjQEO9Xm^$OMnP#5lO6{Qfu780V9n^Ruwe;*t4N|jZXfr|U zp3%hfR$+aiF1=Eck>3V|27#mr~MsZd6cy4ZB`#Zd&pFo<>1mEDcp%iJ7t{TVlY zg`8XHet;aiArIV6sP%OdwvE_+3Rh0O;PhdBq{68n*}T7ecl>MU|20&{1juu(nbzy9 z3-aaLxjFaUcrIbMXId3Msw;?ksW`ujmf)Csv&?-zJG(RYJU2(sm)EBm{CbWKb7uf% zb#Hh)@q7}&Zf6&4-`t+LFX!f+OZR2k2f4>t_gw9R^1CmJV{|`sLQV{QSa#>pENt$U z_wlWm+-~or=st_=p>-hAdd8j}4dOAPO=4;o;3kUZnu94Rb-6j6A zxpyb@@9)|lWoY96QN}g#FFE(6kLGR#kpKVylSxEDR9M69l)(EgY?9OlwUhYDb00000NkvXXu0mjfHd^qQ literal 0 HcmV?d00001 diff --git a/crawl-ref/source/rltiles/gui/backgrounds/Cj.png b/crawl-ref/source/rltiles/gui/backgrounds/Cj.png new file mode 100644 index 0000000000000000000000000000000000000000..4da2a36551381d8b17f8afa68c59f19fad9a84e2 GIT binary patch literal 187 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy`~f~8u0Z-f66kljmjM)FDGBlm zW^kEwFk2+j0>}^dba4!+xOKPBk*~o(fQkF*|NLtqRlcCs_gY(ssC0x_yh0DFWM_QYtP5UM{8w#b(tCc(e XZ5Xe*nHHD>tzhtU^>bP0l+XkK4S+|- literal 0 HcmV?d00001 diff --git a/crawl-ref/source/rltiles/gui/backgrounds/EE.png b/crawl-ref/source/rltiles/gui/backgrounds/EE.png new file mode 100644 index 0000000000000000000000000000000000000000..e29f23a631f7da276d245d59e424a113306eb673 GIT binary patch literal 134 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnL3?x0byx0z;*aCb)T!Hle|NocXoPQU{Vk`;r z3ubV5b|VeQ(ere14B@z*oS-1~p`JnLlYK+WUwMVV|NI^`584IopBQqs=tLMsNZ(-C d5O{=VQj Wnbu8JcHaTCfx*+&&t;ucLK6V3rA4~{ literal 0 HcmV?d00001 diff --git a/crawl-ref/source/rltiles/gui/backgrounds/Fi.png b/crawl-ref/source/rltiles/gui/backgrounds/Fi.png new file mode 100644 index 0000000000000000000000000000000000000000..a92a8e78902cb5f8ef0f9a7bb9f857f39e46ff7b GIT binary patch literal 164 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyJOMr-u0Z-f3|JhnUIFAYmjw9* zGq@aVV%YN&q}tQPF{FYqS)#8&l0zf#01vCh(}xVxZR$jOPH;(V)JSj&JJ52NjYYwq zv1!RnrnDI%dG1ak2EmIMIM{p`L)hGStr-~HKQOT>^e$fyG>^g4)z4*}Q$iB}E*3D7 literal 0 HcmV?d00001 diff --git a/crawl-ref/source/rltiles/gui/backgrounds/Gl.png b/crawl-ref/source/rltiles/gui/backgrounds/Gl.png new file mode 100644 index 0000000000000000000000000000000000000000..df82851d69228cbedc97534a7cb22c4ab71dddca GIT binary patch literal 161 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy`~f~8u0Z-f66kljmjM)FDGBlm zX2_p(FrMdwC6I6H>EaktaqH>XoxBVNJck|Z@6U>$c||#a?cKyesaS vx-D`&+r=8re%$I(tN(_7v3#||oO8^F_Az>DJF8p;8pPn~>gTe~DWM4f@-#X) literal 0 HcmV?d00001 diff --git a/crawl-ref/source/rltiles/gui/backgrounds/Hu.png b/crawl-ref/source/rltiles/gui/backgrounds/Hu.png new file mode 100644 index 0000000000000000000000000000000000000000..32dcf3b96ffefae30542675ed8fb69c971e072ca GIT binary patch literal 169 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnL3?x0byx0z;*aCb)T!Hle|NocXoPQU{Vk`;r z3ubV5b|VeQ3G{Sv4B@z*oN$0&#=+&UqCg>wN5P(qgoK2Ztea*$YG7H+<54Bq@qyjT zK$lJEO_M{@c43c*%}ktzX$pylIaItHjxZl%=5aW3fI%oNAw_|O;n7|G9Q)2+Gk}IO Nc)I$ztaD0e0szH>G&BGJ literal 0 HcmV?d00001 diff --git a/crawl-ref/source/rltiles/gui/backgrounds/IE.png b/crawl-ref/source/rltiles/gui/backgrounds/IE.png new file mode 100644 index 0000000000000000000000000000000000000000..d3639dfb8a7e9c9fd5fc40f29e64f8e556c1acbf GIT binary patch literal 139 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnL3?x0byx0z;*aCb)T!Hle|NocXoPQU{Vk`;r z3ubV5b|VeQG4^zE4B@z*oN$0&LOOus8MDE)rQlh^5PeryHgV2L z84edk7x5qIZ~fbxvEu7*DTAx$UC-Y=Tz@`p_0Ag$7*ZF`71;qakipZ{&t;ucLK6VB CQ#kDa literal 0 HcmV?d00001 diff --git a/crawl-ref/source/rltiles/gui/backgrounds/Ne.png b/crawl-ref/source/rltiles/gui/backgrounds/Ne.png new file mode 100644 index 0000000000000000000000000000000000000000..527e8c62bb10ad2cab5ba29f7292b3276d766318 GIT binary patch literal 170 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyJOMr-u0Z-f3|JhnUIFAYmjw9* zGq_ADNZPX<$o2AcaSW+oynFs2o2wxY%Z1GI|Nnn}%o*#tqvW#l=FB5La$6FYFZKEV z<@;$lzJkm|j!2KwkuQwqe6(c#e|@%f%L(7CEjrV9Og}AFVdQ I&MBb@03hr?1ONa4 literal 0 HcmV?d00001 diff --git a/crawl-ref/source/rltiles/gui/backgrounds/Sk.png b/crawl-ref/source/rltiles/gui/backgrounds/Sk.png new file mode 100644 index 0000000000000000000000000000000000000000..1212f7c570aa0ba3fc1c5c00389de94af47df90d GIT binary patch literal 154 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnL3?x0byx0z;*aCb)T!Hle|NocXoPQU{Vk`;r z3ubV5b|VeQaq@I=4B@z*oN$2uNj(GSZ+i!&MqUpK14d3(F$KjMCXWpo44iz73W_%v xg_(sD^dgwnu;{Q|V>4sO5xEht;o}bmhW0k@;I)RomjF#;@O1TaS?83{1OT-_DlGs2 literal 0 HcmV?d00001 diff --git a/crawl-ref/source/rltiles/gui/backgrounds/Su.png b/crawl-ref/source/rltiles/gui/backgrounds/Su.png new file mode 100644 index 0000000000000000000000000000000000000000..7eae07a58565b5e219ae8c0c358b69a206b9fe19 GIT binary patch literal 196 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy5&=FTu0Z-fHlSQLHy$X*UJ~RN z%wX(NHtFD{0=DJ9fkGjkE{-7;j87+Q@_qkDwJ#3Js~mnG-M?+tt6H5m zQ?4FfrZ4C4zEr^Vm(Hd0i)PjOJ+Vo&X|7x=Q5bYRq4oCx|Hgm(e?-=NKe*tNr?&Z# x&MgbIr_T0jxaTft*PW>Oy}n@M<`<|(`V)p<5 literal 0 HcmV?d00001 diff --git a/crawl-ref/source/rltiles/gui/backgrounds/VM.png b/crawl-ref/source/rltiles/gui/backgrounds/VM.png new file mode 100644 index 0000000000000000000000000000000000000000..acb5a8fd20997860697366ad1aaa32f0faabab7e GIT binary patch literal 212 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyq5(c3u0Z-f2Jkqa%L0^OD+%%o zW^jotn{=>i$MzhcNQS42V@L(#-QJ5_%!V8X9z}lsKi}rY1iLdu2H#2!wl}PNnrZQ3 ze{)8+<&Lo1yPo}iCs|k6xI#(ir&8%;nSiGr_x5ae5?P#b;QS4 zaB^>EX>4U6ba`-PAZ2)IW&i+q+U=HYaw91WhW~SlIRcUpg5&U6H8v@gyC` zo_K0&s|LzV2ZX*JLC1}MeoprTjZ%y*sHK==^k^Z6%mpvWzqN6U`yBbOJui)pC%MxF z#wZwNpR{nS$}xYDkJk~3P8LYtZIG)OzBO#+m}k$wc+~RM##=bYZ_b|P9D8&nM5H0^ zLG32oMGXWivLxHKh;H~P-fim{J^A7r1>b%16}?d=Ch?O3bw`CJ4eA&hHTW2Kuwi6w zEZbZXW5eZKC>I-dl^JcG6g5^#SWr8xomb=}3CGbd}vw7r* z2+`A#EBM8{IM7O?tS7_(gyz9bw*+7MwYeLx0)o1wIU&H}>#m|Iz15a%1t5@9jC*~N z^+k=hDhaTyaE1g3d?Znda+6qBWt zaw?g#;7DqY*>cJ`mjat5xS|ES3nWUZT&0GpHCC&s=2{xcr-i01HfyQnRyud-p=*!b zdg{5CK?9}aMi@Hcu#rX{Wun%m%rJGvX*10{%az(e^+SJx8XeSlBemr0N)5ASOVOr+ z);*((8HjNp5Vu7D1x(d#~Q^;yr{3O?=cCo;Q{yMZ0M z-MnM!o|^ZgJ4@V2-o8w@`^?O<`EuVue!J*C7T)jGl>1!|E~n(EujfO1)}yluz8koE zjX&=d-8*If$;I~Z#(Dgpyf{anGJ5=Sd0~!T;LRVbqyMj>iGOu6K0*Hio?ntBvf>cL z0001XNklI}X4g3_~&M{jZ#^47AF}D5~l=Lu`VB7(P#s pP%utknU3~%Kz#Eq;!(>3D)+nHMP?Y}D7^IeeL?BI=`7u2 ZoJ}`boxlBm$_liA!PC{xWt~$(69D%OR44!d literal 0 HcmV?d00001 diff --git a/crawl-ref/source/rltiles/gui/backgrounds/disabled-fg.png b/crawl-ref/source/rltiles/gui/backgrounds/disabled-fg.png new file mode 120000 index 000000000000..4ee40ba36250 --- /dev/null +++ b/crawl-ref/source/rltiles/gui/backgrounds/disabled-fg.png @@ -0,0 +1 @@ +../skills/disabled-fg.png \ No newline at end of file diff --git a/crawl-ref/source/rltiles/gui/backgrounds/enabled-fg.png b/crawl-ref/source/rltiles/gui/backgrounds/enabled-fg.png new file mode 120000 index 000000000000..eb67c0b15e59 --- /dev/null +++ b/crawl-ref/source/rltiles/gui/backgrounds/enabled-fg.png @@ -0,0 +1 @@ +../skills/enabled-fg.png \ No newline at end of file diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc index c5ca6a732c6f..fe3b1886c4db 100644 --- a/crawl-ref/source/tilepick.cc +++ b/crawl-ref/source/tilepick.cc @@ -3744,6 +3744,138 @@ tileidx_t tileidx_branch(const branch_type br) } } +static tileidx_t _tileidx_player_job_base(const job_type job) +{ + switch (job) + { + case JOB_FIGHTER: + return TILEG_JOB_FIGHTER; + case JOB_WIZARD: + return TILEG_JOB_WIZARD; + case JOB_GLADIATOR: + return TILEG_JOB_GLADIATOR; + case JOB_NECROMANCER: + return TILEG_JOB_NECROMANCER; + case JOB_ASSASSIN: + return TILEG_JOB_ASSASSIN; + case JOB_BERSERKER: + return TILEG_JOB_BERSERKER; + case JOB_HUNTER: + return TILEG_JOB_HUNTER; + case JOB_CONJURER: + return TILEG_JOB_CONJURER; + case JOB_ENCHANTER: + return TILEG_JOB_ENCHANTER; + case JOB_FIRE_ELEMENTALIST: + return TILEG_JOB_FIRE_ELEMENTALIST; + case JOB_ICE_ELEMENTALIST: + return TILEG_JOB_ICE_ELEMENTALIST; + case JOB_SUMMONER: + return TILEG_JOB_SUMMONER; + case JOB_AIR_ELEMENTALIST: + return TILEG_JOB_AIR_ELEMENTALIST; + case JOB_EARTH_ELEMENTALIST: + return TILEG_JOB_EARTH_ELEMENTALIST; + case JOB_SKALD: + return TILEG_JOB_SKALD; + case JOB_VENOM_MAGE: + return TILEG_JOB_VENOM_MAGE; + case JOB_CHAOS_KNIGHT: + return TILEG_JOB_CHAOS_KNIGHT; + case JOB_TRANSMUTER: + return TILEG_JOB_TRANSMUTER; + case JOB_MONK: + return TILEG_JOB_MONK; + case JOB_WARPER: + return TILEG_JOB_WARPER; + case JOB_WANDERER: + return TILEG_JOB_WANDERER; + case JOB_ARTIFICER: + return TILEG_JOB_ARTIFICER; + case JOB_ARCANE_MARKSMAN: + return TILEG_JOB_ARCANE_MARKSMAN; + case JOB_ABYSSAL_KNIGHT: + return TILEG_JOB_ABYSSAL_KNIGHT; + default: + return TILEG_ERROR; + } +} + +static tileidx_t _tileidx_player_species_base(const species_type species) +{ + switch (species) + { + case SP_HUMAN: + return TILEG_SP_HUMAN; + case SP_DEEP_ELF: + return TILEG_SP_DEEP_ELF; + case SP_HALFLING: + return TILEG_SP_HALFLING; + case SP_HILL_ORC: + return TILEG_SP_HILL_ORC; + case SP_KOBOLD: + return TILEG_SP_KOBOLD; + case SP_MUMMY: + return TILEG_SP_MUMMY; + case SP_NAGA: + return TILEG_SP_NAGA; + case SP_OGRE: + return TILEG_SP_OGRE; + case SP_TROLL: + return TILEG_SP_TROLL; + case SP_BASE_DRACONIAN: + return TILEG_SP_DRACONIAN; + case SP_CENTAUR: + return TILEG_SP_CENTAUR; + case SP_DEMIGOD: + return TILEG_SP_DEMIGOD; + case SP_SPRIGGAN: + return TILEG_SP_SPRIGGAN; + case SP_MINOTAUR: + return TILEG_SP_MINOTAUR; + case SP_DEMONSPAWN: + return TILEG_SP_DEMONSPAWN; + case SP_GHOUL: + return TILEG_SP_GHOUL; + case SP_TENGU: + return TILEG_SP_TENGU; + case SP_MERFOLK: + return TILEG_SP_MERFOLK; + case SP_VAMPIRE: + return TILEG_SP_VAMPIRE; + case SP_DEEP_DWARF: + return TILEG_SP_DEEP_DWARF; + case SP_FELID: + return TILEG_SP_FELID; + case SP_OCTOPODE: + return TILEG_SP_OCTOPODE; + case SP_GARGOYLE: + return TILEG_SP_GARGOYLE; + case SP_FORMICID: + return TILEG_SP_FORMICID; + case SP_VINE_STALKER: + return TILEG_SP_VINE_STALKER; + case SP_BARACHI: + return TILEG_SP_BARACHI; + case SP_GNOLL: + return TILEG_SP_GNOLL; + default: + return TILEP_ERROR; + } +} + +tileidx_t tileidx_player_species(const species_type species, bool recommended) +{ + tileidx_t off = recommended ? -TILEG_LAST_SPECIES+TILEG_LAST_RECOMMENDED_SPECIES: 0; + return _tileidx_player_species_base(species) + off; +} + +tileidx_t tileidx_player_job(const job_type job, bool recommended) +{ + tileidx_t off = recommended ? -TILEG_LAST_JOB+TILEG_LAST_RECOMMENDED_JOB: 0; + return _tileidx_player_job_base(job) + off; +} + tileidx_t tileidx_known_brand(const item_def &item) { if (!item_type_known(item)) diff --git a/crawl-ref/source/tilepick.h b/crawl-ref/source/tilepick.h index d825552f90b2..72c14628caf7 100644 --- a/crawl-ref/source/tilepick.h +++ b/crawl-ref/source/tilepick.h @@ -10,6 +10,8 @@ #include "game-type.h" #include "trap-type.h" #include "tiledef_defines.h" +#include "job-type.h" +#include "species-type.h" #define TILE_NUM_KEY "tile_num" @@ -53,6 +55,8 @@ tileidx_t tileidx_command(const command_type cmd); tileidx_t tileidx_gametype(const game_type gtype); tileidx_t tileidx_ability(const ability_type ability); tileidx_t tileidx_branch(const branch_type br); +tileidx_t tileidx_player_job(const job_type job, bool recommended); +tileidx_t tileidx_player_species(const species_type species, bool recommended); tileidx_t tileidx_known_brand(const item_def &item); tileidx_t tileidx_corpse_brand(const item_def &item); From efe2a7dc0dcb6ab03c99f7d8ac73a2a764ca5913 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Tue, 11 Sep 2018 20:42:22 +0800 Subject: [PATCH 672/864] Let Box widgets stretch children on main axis --- crawl-ref/source/ui.cc | 12 +++++++++++- crawl-ref/source/ui.h | 8 +------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 33145db9807a..08e8a1172162 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -311,6 +311,8 @@ vector Box::layout_main_axis(vector& ch_psz, int main_sz) { ch_sz[i] = ch_psz[i].min; extra -= ch_psz[i].min; + if (justify_items == Align::STRETCH) + ch_psz[i].nat = INT_MAX; } ASSERT(extra >= 0); @@ -406,7 +408,15 @@ void Box::_allocate_region() ASSERT(extra_main_space >= 0); // main axis offset - int mo = extra_main_space*(justify_items - Box::Justify::START)/2; + int mo; + switch (justify_items) + { + case Widget::START: mo = 0; break; + case Widget::CENTER: mo = extra_main_space/2; break; + case Widget::END: mo = extra_main_space; break; + case Widget::STRETCH: mo = 0; break; + default: ASSERT(0); + } int ho = m_region[0] + (horz ? mo : 0); int vo = m_region[1] + (!horz ? mo : 0); diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index 17c42708d39a..a9c2e33331a7 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -316,12 +316,6 @@ class ContainerVec : public Container class Box : public ContainerVec { public: - enum Justify { - START = 0, - CENTER, - END, - }; - enum Expand { NONE = 0x0, EXPAND_H = 0x1, @@ -339,7 +333,7 @@ class Box : public ContainerVec virtual ~Box() {} void add_child(shared_ptr child); bool horz; - Justify justify_items = START; + Widget::Align justify_items = START; Widget::Align align_items = UNSET; virtual void _render() override; From 94e85a77e34ccbd14ddc35768c43970236b91b2a Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sun, 19 Aug 2018 15:22:11 +0800 Subject: [PATCH 673/864] Add species attributes to starting weapon menu (VeryAngryFelid) --- crawl-ref/source/newgame.cc | 134 ++++++++++++++++++++++-------------- 1 file changed, 83 insertions(+), 51 deletions(-) diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 42bad1d93224..589e4f47e3d8 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -27,6 +27,7 @@ #include "ng-restr.h" #include "options.h" #include "prompt.h" +#include "skills.h" #include "species-groups.h" #include "state.h" #include "stringutil.h" @@ -1497,81 +1498,62 @@ static void _construct_weapon_menu(const newgame_def& ng, shared_ptr& main_items, shared_ptr& sub_items) { - string text; - const char *thrown_name = nullptr; + struct weapon_menu_item { + skill_type skill; + string label; + tileidx_t tile; + weapon_menu_item(skill_type _skill, string _label, tileidx_t _tile) + : skill(move(_skill)), label(move(_label)), tile(move(_tile)) {}; + weapon_menu_item(skill_type _skill, string _label) + : skill(move(_skill)), label(move(_label)) {}; + }; + vector choices; + + string thrown_name; for (unsigned int i = 0; i < weapons.size(); ++i) { weapon_type wpn_type = weapons[i].first; - char_choice_restriction wpn_restriction = weapons[i].second; - - auto label = make_shared(); - -#ifdef USE_TILE_LOCAL - auto hbox = make_shared(Box::HORZ); - hbox->align_items = Widget::Align::CENTER; - auto tile_stack = make_shared(); - tile_stack->set_margin_for_sdl({0, 6, 0, 0}); - hbox->add_child(tile_stack); - hbox->add_child(label); -#endif - - text.clear(); - - const char letter = 'a' + i; - text += make_stringf(" %c - ", letter); switch (wpn_type) { case WPN_UNARMED: - text += species_has_claws(ng.species) ? "claws" : "unarmed"; -#ifdef USE_TILE_LOCAL - tile_stack->min_size() = { TILE_Y, TILE_Y }; -#endif + choices.emplace_back(SK_UNARMED_COMBAT, species_has_claws(ng.species) ? "claws" : "unarmed"); break; case WPN_THROWN: + { // We don't support choosing among multiple thrown weapons. - ASSERT(!thrown_name); -#ifdef USE_TILE_LOCAL - tile_stack->add_child(make_shared( - tile_def(TILE_MI_THROWING_NET, TEX_DEFAULT))); -#endif + tileidx_t tile = 0; if (species_can_throw_large_rocks(ng.species)) { thrown_name = "large rocks"; -#ifdef USE_TILE_LOCAL - tile_stack->add_child(make_shared( - tile_def(TILE_MI_LARGE_ROCK, TEX_DEFAULT))); +#ifdef USE_TILE + tile = TILE_MI_LARGE_ROCK; #endif } else if (species_size(ng.species, PSIZE_TORSO) <= SIZE_SMALL) { thrown_name = "boomerangs"; -#ifdef USE_TILE_LOCAL - tile_stack->add_child(make_shared( - tile_def(TILE_MI_BOOMERANG, TEX_DEFAULT))); +#ifdef USE_TILE + tile = TILE_MI_BOOMERANG; #endif } else { thrown_name = "javelins"; -#ifdef USE_TILE_LOCAL - tile_stack->add_child(make_shared( - tile_def(TILE_MI_JAVELIN, TEX_DEFAULT))); +#ifdef USE_TILE + tile = TILE_MI_JAVELIN; #endif } - text += thrown_name; - text += " and throwing nets"; + choices.emplace_back(SK_THROWING, + thrown_name + " and throwing nets", tile); break; + } default: - text += weapon_base_name(wpn_type); -#ifdef USE_TILE_LOCAL + string text = weapon_base_name(wpn_type); item_def dummy; dummy.base_type = OBJ_WEAPONS; dummy.sub_type = wpn_type; - tile_stack->add_child(make_shared( - tile_def(tileidx_item(dummy), TEX_DEFAULT))); -#endif if (is_ranged_weapon_type(wpn_type)) { text += " and "; @@ -1579,18 +1561,68 @@ static void _construct_weapon_menu(const newgame_def& ng, : ammo_name(wpn_type); text += "s"; } + choices.emplace_back(item_attack_skill(dummy), text +#ifdef USE_TILE_LOCAL + , tileidx_item(dummy) +#endif + ); break; } + } + + int max_text_width = 0; + for (const auto& choice : choices) + max_text_width = max(max_text_width, strwidth(choice.label)); + + for (unsigned int i = 0; i < weapons.size(); ++i) + { + const auto& choice = choices[i]; + + auto hbox = make_shared(Box::HORZ); + hbox->align_items = Widget::Align::CENTER; + hbox->set_margin_for_sdl({2,10,2,2}); + +#ifdef USE_TILE + auto tile_stack = make_shared(); + tile_stack->set_margin_for_sdl({0, 6, 0, 0}); + tile_stack->flex_grow = 0; + hbox->add_child(tile_stack); + + if (choice.skill == SK_THROWING) + { + tile_stack->add_child(make_shared( + tile_def(TILE_MI_THROWING_NET, TEX_DEFAULT))); + } + if (choice.skill == SK_UNARMED_COMBAT) + tile_stack->min_size() = { TILE_Y, TILE_Y }; + else + tile_stack->add_child(make_shared( + tile_def(choice.tile, TEX_DEFAULT))); +#endif + + auto label = make_shared(); + hbox->add_child(label); + + const char letter = 'a' + i; + + string text = make_stringf(" %c - %s", letter, + chop_string(choice.label, max_text_width, true).c_str() + ); + + weapon_type wpn_type = weapons[i].first; + char_choice_restriction wpn_restriction = weapons[i].second; label->set_text(formatted_string(text, wpn_restriction == CC_UNRESTRICTED ? WHITE : LIGHTGREY)); + hbox->justify_items = Widget::Align::STRETCH; + string apt_text = make_stringf("(%+d apt)", + species_apt(choice.skill, ng.species)); + auto suffix = make_shared(formatted_string(apt_text, + wpn_restriction == CC_UNRESTRICTED ? WHITE : LIGHTGREY)); + hbox->add_child(suffix); + auto btn = make_shared(); -#ifdef USE_TILE_LOCAL - hbox->set_margin_for_sdl({2,10,2,2}); btn->set_child(move(hbox)); -#else - btn->set_child(move(label)); -#endif btn->id = wpn_type; btn->hotkey = letter; @@ -1619,9 +1651,9 @@ static void _construct_weapon_menu(const newgame_def& ng, if (defweapon != WPN_UNKNOWN) { - text = "Tab - "; + string text = "Tab - "; - ASSERT(defweapon != WPN_THROWN || thrown_name); + ASSERT(defweapon != WPN_THROWN || thrown_name != ""); text += defweapon == WPN_RANDOM ? "Random" : defweapon == WPN_VIABLE ? "Recommended" : defweapon == WPN_UNARMED ? "unarmed" : From 77bbe519b12700bf0a8b80ddfc5ae987bb4385d2 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sun, 19 Aug 2018 15:23:41 +0800 Subject: [PATCH 674/864] Respect popup child widget's preferred size --- crawl-ref/source/ui.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 08e8a1172162..da49e6976e61 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -1462,6 +1462,11 @@ void Popup::_allocate_region() region[0] + region[2] + m_padding - 3, region[1] + region[3] + m_padding - 3, VColour(4, 2, 4)); +#else + SizeReq hsr = m_child->get_preferred_size(HORZ, -1); + region[2] = max(hsr.min, min(region[2], hsr.nat)); + SizeReq vsr = m_child->get_preferred_size(VERT, region[2]); + region[3] = max(vsr.min, min(region[3], vsr.nat)); #endif m_child->allocate_region(region); } From e13cadf35d0b9c1cd7a3a464fff794107e83268d Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 25 Aug 2018 18:11:42 +0800 Subject: [PATCH 675/864] Add operator[] accessor for container widgets --- crawl-ref/source/ui.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index a9c2e33331a7..9bc7cd04ebce 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -279,6 +279,8 @@ class ContainerVec : public Container } virtual shared_ptr get_child_at_offset(int x, int y) override; size_t num_children() const { return m_children.size(); } + shared_ptr& operator[](size_t pos) { return m_children[pos]; }; + const shared_ptr& operator[](size_t pos) const { return m_children[pos]; }; private: typedef Container::iterator I; From bbc46fc816331aa7d44145486e320df9b5652eaa Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 15 Sep 2018 23:37:11 +0800 Subject: [PATCH 676/864] Make send_doll() public --- crawl-ref/source/tileweb.cc | 12 ++++++------ crawl-ref/source/tileweb.h | 4 +++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/crawl-ref/source/tileweb.cc b/crawl-ref/source/tileweb.cc index dbd6bd24e706..e0c079201894 100644 --- a/crawl-ref/source/tileweb.cc +++ b/crawl-ref/source/tileweb.cc @@ -1098,7 +1098,7 @@ void TilesFramework::_send_item(item_info& current, const item_info& next, } } -static void _send_doll(const dolls_data &doll, bool submerged, bool ghost) +void TilesFramework::send_doll(const dolls_data &doll, bool submerged, bool ghost) { // Ordered from back to front. // FIXME: Implement this logic in one place in e.g. pack_doll_buf(). @@ -1192,17 +1192,17 @@ static void _send_doll(const dolls_data &doll, bool submerged, bool ghost) tiles.json_close_array(); } -void TilesFramework::send_mcache(mcache_entry *entry, bool submerged, bool send_doll) +void TilesFramework::send_mcache(mcache_entry *entry, bool submerged, bool send) { bool trans = entry->transparent(); - if (trans && send_doll) + if (trans && send) tiles.json_write_int("trans", 1); const dolls_data *doll = entry->doll(); - if (send_doll) + if (send) { if (doll) - _send_doll(*doll, submerged, trans); + send_doll(*doll, submerged, trans); else { tiles.json_write_comma(); @@ -1425,7 +1425,7 @@ void TilesFramework::_send_cell(const coord_def &gc, } if (fg_changed || player_doll_changed) { - _send_doll(last_player_doll, in_water, false); + send_doll(last_player_doll, in_water, false); if (Options.tile_use_monster != MONS_0) { monster_info minfo(MONS_PLAYER, MONS_PLAYER); diff --git a/crawl-ref/source/tileweb.h b/crawl-ref/source/tileweb.h index a6701f583988..ec59d96380e0 100644 --- a/crawl-ref/source/tileweb.h +++ b/crawl-ref/source/tileweb.h @@ -205,11 +205,13 @@ class TilesFramework void update_input_mode(mouse_mode mode); void send_mcache(mcache_entry *entry, bool submerged, - bool send_doll = true); + bool send = true); void write_tileidx(tileidx_t t); void zoom_dungeon(bool in); + void send_doll(const dolls_data &doll, bool submerged, bool ghost); + protected: int m_sock; int m_max_msg_size; From 41769e37c51a76561d4fc03ce0f87fcb87e65cfa Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 25 Aug 2018 18:02:50 +0800 Subject: [PATCH 677/864] Add HTML newgame menus, more tiles --- crawl-ref/source/newgame.cc | 177 +++++++++++++++--- crawl-ref/source/outer-menu.cc | 121 ++++++++++++ crawl-ref/source/outer-menu.h | 12 ++ crawl-ref/source/tileweb.cc | 9 + crawl-ref/source/ui.cc | 4 +- crawl-ref/source/ui.h | 1 + .../webserver/game_data/static/style.css | 99 ++++++++++ .../webserver/game_data/static/ui-layouts.js | 127 +++++++++++++ .../webserver/game_data/templates/game.html | 13 ++ 9 files changed, 531 insertions(+), 32 deletions(-) diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 589e4f47e3d8..4de59552e768 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -31,9 +31,10 @@ #include "species-groups.h" #include "state.h" #include "stringutil.h" -#ifdef USE_TILE_LOCAL +#ifdef USE_TILE #include "tilereg-crt.h" #include "tilepick.h" +#include "tilepick-p.h" #include "tilefont.h" #include "tiledef-main.h" #include "tiledef-feat.h" @@ -380,25 +381,49 @@ static bool _reroll_random(newgame_def& ng) string specs = chop_string(species_name(ng.species), 79, false); formatted_string prompt; - prompt.cprintf("You are a%s %s %s.\n", + prompt.cprintf("You are a%s %s %s.", (is_vowel(specs[0])) ? "n" : "", specs.c_str(), get_job_name(ng.job)); - prompt.cprintf("\nDo you want to play this combination? (ynq) [y]"); - auto prompt_ui = make_shared(); - prompt_ui->set_text(prompt); + auto title_hbox = make_shared(Widget::HORZ); +#ifdef USE_TILE + dolls_data doll; + fill_doll_for_newgame(doll, ng); +#ifdef USE_TILE_LOCAL + auto tile = make_shared(doll); + tile->set_margin_for_sdl({0, 10, 0, 0}); + title_hbox->add_child(move(tile)); +#endif +#endif + title_hbox->add_child(make_shared(prompt)); + title_hbox->align_items = Widget::CENTER; + title_hbox->set_margin_for_sdl({0, 0, 20, 0}); + title_hbox->set_margin_for_crt({0, 0, 1, 0}); + + auto vbox = make_shared(Box::VERT); + vbox->add_child(move(title_hbox)); + vbox->add_child(make_shared("Do you want to play this combination? [Y/n/q]")); + auto popup = make_shared(move(vbox)); bool done = false; char c; - prompt_ui->on(Widget::slots.event, [&](wm_event ev) { + popup->on(Widget::slots.event, [&](wm_event ev) { if (ev.type != WME_KEYDOWN) return false; c = ev.key.keysym.sym; return done = true; }); - auto popup = make_shared(prompt_ui); +#ifdef USE_TILE_WEB + tiles.json_open_object(); + tiles.json_write_string("prompt", prompt.to_colour_string()); + tiles.send_doll(doll, false, false); + tiles.push_ui_layout("newgame-random-combo", 0); +#endif ui::run_layout(move(popup), done); +#ifdef USE_TILE_WEB + tiles.pop_ui_layout(); +#endif if (key_is_escape(c) || toalower(c) == 'q' || crawl_state.seen_hups) game_ended(game_exit::abort); @@ -581,8 +606,36 @@ static void _choose_name(newgame_def& ng, newgame_def& choice) bool good_name = true; bool cancel = false; + string specs = chop_string(species_name(ng.species), 79, false); + + formatted_string title; + title.cprintf("You are a%s %s %s.", + (is_vowel(specs[0])) ? "n" : "", specs.c_str(), + get_job_name(ng.job)); + + auto title_hbox = make_shared(Widget::HORZ); +#ifdef USE_TILE + dolls_data doll; + fill_doll_for_newgame(doll, ng); +#ifdef USE_TILE_LOCAL + auto tile = make_shared(doll); + tile->set_margin_for_sdl({0, 10, 0, 0}); + title_hbox->add_child(move(tile)); +#endif +#endif + title_hbox->add_child(make_shared(title)); + title_hbox->align_items = Widget::CENTER; + title_hbox->set_margin_for_sdl({0, 0, 20, 0}); + title_hbox->set_margin_for_crt({0, 0, 1, 0}); + + auto vbox = make_shared(Box::VERT); + vbox->add_child(move(title_hbox)); auto prompt_ui = make_shared(); - prompt_ui->on(Widget::slots.event, [&](wm_event ev) { + vbox->add_child(prompt_ui); + + auto popup = make_shared(move(vbox)); + + popup->on(Widget::slots.event, [&](wm_event ev) { if (ev.type != WME_KEYDOWN) return false; int key = ev.key.keysym.sym; @@ -621,17 +674,12 @@ static void _choose_name(newgame_def& ng, newgame_def& choice) return true; }); - auto popup = make_shared(prompt_ui); ui::push_layout(move(popup)); while (!done && !crawl_state.seen_hups) { formatted_string prompt; - string specs = chop_string(species_name(ng.species), 79, false); - prompt.cprintf("You are a%s %s %s.\n", - (is_vowel(specs[0])) ? "n" : "", specs.c_str(), - get_job_name(ng.job)); prompt.textcolour(CYAN); - prompt.cprintf("\nWhat is your name today? "); + prompt.cprintf("What is your name today? "); prompt.textcolour(LIGHTGREY); prompt.cprintf("%s", buf); prompt.cprintf("\n\nLeave blank for a random name, or use Escape to cancel this character.\n\n"); @@ -822,7 +870,6 @@ bool choose_game(newgame_def& ng, newgame_def& choice, const newgame_def& defaults) { #ifdef USE_TILE_WEB - tiles_crt_popup show_as_popup; tiles.set_ui_state(UI_CRT); #endif @@ -986,7 +1033,6 @@ class UINewGameMenu : public Widget m_vbox->_set_parent(this); m_vbox->align_items = Widget::Align::STRETCH; - formatted_string welcome; welcome.textcolour(BROWN); welcome.cprintf("%s", _welcome(m_ng).c_str()); welcome.textcolour(YELLOW); @@ -997,6 +1043,8 @@ class UINewGameMenu : public Widget descriptions = make_shared(); m_main_items = make_shared(true, 3, 20); + m_main_items->menu_id = m_choice_type == C_JOB ? + "background-main" : "species-main"; m_main_items->set_margin_for_crt({1, 0, 1, 0}); m_main_items->set_margin_for_sdl({15, 0, 15, 0}); m_main_items->descriptions = descriptions; @@ -1019,6 +1067,8 @@ class UINewGameMenu : public Widget _construct_species_menu(m_ng, m_defaults, this); m_sub_items = make_shared(false, 2, 4); + m_sub_items->menu_id = m_choice_type == C_JOB ? + "background-sub" : "species-sub"; m_sub_items->descriptions = descriptions; m_vbox->add_child(m_sub_items); _add_choice_menu_options(m_choice_type, m_ng, m_defaults); @@ -1052,6 +1102,10 @@ class UINewGameMenu : public Widget virtual void _allocate_region() override; virtual bool on_event(const wm_event& event) override; +#ifdef USE_TILE_WEB + void serialize(); +#endif + void menu_item_activated(int id); bool done = false; @@ -1065,7 +1119,7 @@ class UINewGameMenu : public Widget int id, int item_status, string item_name, -#ifdef USE_TILE_LOCAL +#ifdef USE_TILE tile_def item_tile, #endif bool is_active_item, @@ -1074,7 +1128,7 @@ class UINewGameMenu : public Widget { auto label = make_shared(); -#ifdef USE_TILE_LOCAL +#ifdef USE_TILE auto hbox = make_shared(Box::HORZ); hbox->align_items = Widget::Align::CENTER; auto tile = make_shared(); @@ -1112,7 +1166,7 @@ class UINewGameMenu : public Widget trim_string(desc); auto btn = make_shared(); -#ifdef USE_TILE_LOCAL +#ifdef USE_TILE hbox->set_margin_for_sdl({2,10,2,2}); btn->set_child(move(hbox)); #else @@ -1223,6 +1277,7 @@ class UINewGameMenu : public Widget return false; } + formatted_string welcome; int m_choice_type; newgame_def& m_ng; newgame_def& m_ng_choice; @@ -1285,6 +1340,16 @@ bool UINewGameMenu::on_event(const wm_event& ev) return false; } + +#ifdef USE_TILE_WEB +void UINewGameMenu::serialize() +{ + tiles.json_write_string("title", welcome.to_colour_string()); + m_main_items->serialize("main-items"); + m_sub_items->serialize("sub-items"); +} +#endif + void UINewGameMenu::menu_item_activated(int id) { bool viable = false; @@ -1391,7 +1456,7 @@ void job_group::attach(const newgame_def& ng, const newgame_def& defaults, job, item_status, get_job_name(job), -#ifdef USE_TILE_LOCAL +#ifdef USE_TILE tile_def(tileidx_player_job(job, item_status != ITEM_STATUS_RESTRICTED), TEX_GUI), #endif @@ -1441,7 +1506,7 @@ void species_group::attach(const newgame_def& ng, const newgame_def& defaults, this_species, item_status, species_name(this_species), -#ifdef USE_TILE_LOCAL +#ifdef USE_TILE tile_def(tileidx_player_species(this_species, item_status != ITEM_STATUS_RESTRICTED), TEX_GUI), #endif @@ -1467,12 +1532,22 @@ static void _prompt_choice(int choice_type, newgame_def& ng, newgame_def& ng_cho auto newgame_ui = make_shared(choice_type, ng, ng_choice, defaults); auto popup = make_shared(newgame_ui); +#ifdef USE_TILE_WEB + tiles.json_open_object(); + newgame_ui->serialize(); + tiles.push_ui_layout("newgame-choice", 1); +#endif + ui::push_layout(move(popup)); ui::set_focused_widget(newgame_ui.get()); while (!newgame_ui->done) ui::pump_events(); ui::pop_layout(); +#ifdef USE_TILE_WEB + tiles.pop_ui_layout(); +#endif + if (newgame_ui->end_game) end(0); if (newgame_ui->cancel || crawl_state.seen_hups) @@ -1562,7 +1637,7 @@ static void _construct_weapon_menu(const newgame_def& ng, text += "s"; } choices.emplace_back(item_attack_skill(dummy), text -#ifdef USE_TILE_LOCAL +#ifdef USE_TILE , tileidx_item(dummy) #endif ); @@ -1674,22 +1749,36 @@ static bool _prompt_weapon(const newgame_def& ng, newgame_def& ng_choice, { weapon_type defweapon = _fixup_weapon(defaults.weapon, weapons); - formatted_string welcome; - welcome.textcolour(BROWN); - welcome.cprintf("%s\n", _welcome(ng).c_str()); - welcome.textcolour(CYAN); - welcome.cprintf("\nYou have a choice of weapons:"); + auto title_hbox = make_shared(Widget::HORZ); +#ifdef USE_TILE + dolls_data doll; + fill_doll_for_newgame(doll, ng); +#ifdef USE_TILE_LOCAL + auto tile = make_shared(doll); + tile->set_margin_for_sdl({0, 10, 0, 0}); + title_hbox->add_child(move(tile)); +#endif +#endif + auto title = make_shared(formatted_string(_welcome(ng), BROWN)); + title_hbox->add_child(title); + title_hbox->align_items = Widget::CENTER; + title_hbox->set_margin_for_sdl({0, 0, 20, 0}); + title_hbox->set_margin_for_crt({0, 0, 1, 0}); auto vbox = make_shared(Box::VERT); vbox->align_items = Widget::Align::STRETCH; - vbox->add_child(make_shared(welcome)); + vbox->add_child(title_hbox); + auto prompt = make_shared(formatted_string("You have a choice of weapons.", CYAN)); + vbox->add_child(prompt); auto main_items = make_shared(true, 1, weapons.size()); + main_items->menu_id = "weapon-main"; main_items->set_margin_for_sdl({15, 0, 15, 0}); main_items->set_margin_for_crt({1, 0, 1, 0}); vbox->add_child(main_items); auto sub_items = make_shared(false, 2, 3); + sub_items->menu_id = "weapon-sub"; vbox->add_child(sub_items); main_items->linked_menus[2] = sub_items; @@ -1762,7 +1851,21 @@ static bool _prompt_weapon(const newgame_def& ng, newgame_def& ng_choice, return false; }); + +#ifdef USE_TILE_WEB + tiles.json_open_object(); + tiles.json_write_string("title", title->get_text().to_colour_string()); + tiles.json_write_string("prompt", prompt->get_text().to_colour_string()); + main_items->serialize("main-items"); + sub_items->serialize("sub-items"); + tiles.send_doll(doll, false, false); + tiles.push_ui_layout("newgame-choice", 1); +#endif ui::run_layout(move(popup), done); +#ifdef USE_TILE_WEB + tiles.pop_ui_layout(); +#endif + return ret; } @@ -1906,7 +2009,7 @@ static bool _choose_weapon(newgame_def& ng, newgame_def& ng_choice, return true; } -#ifdef USE_TILE_LOCAL +#ifdef USE_TILE static tile_def tile_for_map_name(string name) { if (starts_with(name, "Lesson ")) @@ -1965,7 +2068,7 @@ static void _construct_gamemode_map_menu(const mapref_vector& maps, text += " - "; text += map_name; -#ifdef USE_TILE_LOCAL +#ifdef USE_TILE auto hbox = make_shared(Box::HORZ); hbox->align_items = Widget::Align::CENTER; auto tile = make_shared(); @@ -1978,7 +2081,7 @@ static void _construct_gamemode_map_menu(const mapref_vector& maps, label->set_text(formatted_string(text, LIGHTGREY)); auto btn = make_shared(); -#ifdef USE_TILE_LOCAL +#ifdef USE_TILE hbox->set_margin_for_sdl({2,10,2,2}); btn->set_child(move(hbox)); #else @@ -2065,11 +2168,13 @@ static void _prompt_gamemode_map(newgame_def& ng, newgame_def& ng_choice, vbox->add_child(make_shared(welcome)); auto main_items = make_shared(true, 1, maps.size()); + main_items->menu_id = "map-main"; main_items->set_margin_for_sdl({15, 0, 15, 0}); main_items->set_margin_for_crt({1, 0, 1, 0}); vbox->add_child(main_items); auto sub_items = make_shared(false, 2, 2); + sub_items->menu_id = "map-sub"; vbox->add_child(sub_items); main_items->linked_menus[2] = sub_items; @@ -2135,7 +2240,17 @@ static void _prompt_gamemode_map(newgame_def& ng, newgame_def& ng_choice, return false; }); +#ifdef USE_TILE_WEB + tiles.json_open_object(); + tiles.json_write_string("title", welcome.to_colour_string()); + main_items->serialize("main-items"); + sub_items->serialize("sub-items"); + tiles.push_ui_layout("newgame-choice", 1); +#endif ui::run_layout(move(popup), done); +#ifdef USE_TILE_WEB + tiles.pop_ui_layout(); +#endif if (cancel || crawl_state.seen_hups) game_ended(game_exit::abort); diff --git a/crawl-ref/source/outer-menu.cc b/crawl-ref/source/outer-menu.cc index 018aa68cce90..56d37bb68a76 100644 --- a/crawl-ref/source/outer-menu.cc +++ b/crawl-ref/source/outer-menu.cc @@ -5,9 +5,12 @@ #include "AppHdr.h" +#include + #include "cio.h" #include "outer-menu.h" #include "tileweb.h" +#include "unwind.h" using namespace ui; @@ -82,6 +85,49 @@ bool MenuButton::on_event(const wm_event& event) return old_active != active; } +#ifdef USE_TILE_WEB +static void serialize_image(const Image* image) +{ + tile_def tile = image->get_tile(); + tiles.json_open_object(); + tiles.json_write_int("t", tile.tile); + tiles.json_write_int("tex", tile.tex); + if (tile.ymax != TILE_Y) + tiles.json_write_int("ymax", tile.ymax); + tiles.json_close_object(); +} + +void MenuButton::serialize() +{ + tiles.json_write_string("description", description); + tiles.json_write_int("hotkey", hotkey); + tiles.json_write_int("highlight_colour", highlight_colour); + if (auto text = dynamic_cast(m_child.get())) + tiles.json_write_string("label", text->get_text().to_colour_string()); + else if (auto box = dynamic_cast(m_child.get())) + { + if (box->num_children() <= 1) + return; + tiles.json_open_array("tile"); + if (auto tile = dynamic_cast((*box)[0].get())) + serialize_image(tile); + else if (auto tilestack = dynamic_cast(((*box)[0].get()))) + { + for (const auto it : *tilestack) + if (auto t = dynamic_cast(it.get())) + serialize_image(t); + } + tiles.json_close_array(); + + tiles.json_open_array("labels"); + for (size_t i = 1; i < box->num_children(); i++) + if (auto text2 = dynamic_cast((*box)[i].get())) + tiles.json_write_string(text2->get_text().to_colour_string()); + tiles.json_close_array(); + } +} +#endif + OuterMenu::OuterMenu(bool can_shrink, int width, int height) { m_grid = make_shared(); @@ -108,6 +154,17 @@ OuterMenu::OuterMenu(bool can_shrink, int width, int height) m_description_indexes.resize(width * height, -1); } +#ifdef USE_TILE_WEB +static bool from_client {false}; +static unordered_map open_menus; + +OuterMenu::~OuterMenu() +{ + if (menu_id) + open_menus.erase(string(menu_id)); +} +#endif + void OuterMenu::_render() { m_root->render(); @@ -138,6 +195,10 @@ void OuterMenu::_allocate_region() } return false; }); +#ifdef USE_TILE_WEB + if (menu_id) + open_menus.emplace(menu_id, this); +#endif if (m_initial_focus) scroll_button_into_view(m_initial_focus); } @@ -154,6 +215,7 @@ void OuterMenu::add_label(shared_ptr label, int x, int y) ASSERT(x >= 0 && x < m_width); ASSERT(y >= 0 && y < m_height); ASSERT(m_buttons[y*m_width + x] == nullptr); + m_labels.emplace_back(label->get_text(), coord_def(x, y)); m_grid->add_child(move(label), x, y); } @@ -203,6 +265,18 @@ void OuterMenu::add_button(shared_ptr btn, int x, int y) void OuterMenu::scroll_button_into_view(MenuButton *btn) { ui::set_focused_widget(btn); + +#ifdef USE_TILE_WEB + if (menu_id) + { + tiles.json_open_object(); + tiles.json_write_bool("from_client", from_client); + tiles.json_write_string("menu_id", menu_id); + tiles.json_write_int("button_focus", btn->hotkey); + tiles.ui_state_change("newgame-choice", 0); + } +#endif + Widget* gp = btn->_get_parent()->_get_parent(); Scroller* scroller = dynamic_cast(gp); if (!scroller) @@ -300,3 +374,50 @@ MenuButton* OuterMenu::get_button_by_id(int id) [id](MenuButton*& btn) { return btn && btn->id == id; }); return it == m_buttons.end() ? nullptr : *it; } + +#ifdef USE_TILE_WEB +void OuterMenu::serialize(string name) +{ + tiles.json_open_object(name); + tiles.json_write_string("menu_id", menu_id); + tiles.json_write_int("width", m_width); + tiles.json_write_int("height", m_height); + tiles.json_open_array("buttons"); + for (size_t i = 0; i < m_buttons.size(); i++) + { + if (!m_buttons[i]) + continue; + tiles.json_open_object(); + tiles.json_write_int("x", i % m_width); + tiles.json_write_int("y", i / m_width); + m_buttons[i]->serialize(); + tiles.json_close_object(); + } + tiles.json_close_array(); + tiles.json_open_array("labels"); + for (auto label : m_labels) + { + tiles.json_open_object(); + tiles.json_write_int("x", label.second.x); + tiles.json_write_int("y", label.second.y); + tiles.json_write_string("label", label.first.to_colour_string()); + tiles.json_close_object(); + } + tiles.json_close_array(); + tiles.json_close_object(); +} + +void OuterMenu::recv_outer_menu_focus(const char *menu_id, int hotkey) +{ + auto open_menu = open_menus.find(menu_id); + if (open_menu == open_menus.end()) + return; + + unwind_bool tmp(from_client, true); + + auto menu = open_menu->second; + for (auto btn : menu->m_buttons) + if (btn && btn->hotkey == hotkey) + menu->scroll_button_into_view(btn); +} +#endif diff --git a/crawl-ref/source/outer-menu.h b/crawl-ref/source/outer-menu.h index 2ca38392ef36..bf86e197ec94 100644 --- a/crawl-ref/source/outer-menu.h +++ b/crawl-ref/source/outer-menu.h @@ -24,6 +24,10 @@ class MenuButton : public ui::Bin COLOURS highlight_colour = LIGHTGREY; string description; +#ifdef USE_TILE_WEB + void serialize(); +#endif + protected: bool focused = false; bool active = false; @@ -39,6 +43,12 @@ class OuterMenu : public ui::Widget public: OuterMenu(bool can_shrink, int width, int height); +#ifdef USE_TILE_WEB + ~OuterMenu(); + void serialize(string name); + static void recv_outer_menu_focus(const char *menu_id, int hotkey); +#endif + virtual void _render() override; virtual ui::SizeReq _get_preferred_size(ui::Widget::Direction, int) override; virtual void _allocate_region() override; @@ -64,6 +74,7 @@ class OuterMenu : public ui::Widget weak_ptr linked_menus[4]; shared_ptr descriptions; + const char *menu_id {nullptr}; protected: bool scroller_event_hook(const wm_event& ev); @@ -72,6 +83,7 @@ class OuterMenu : public ui::Widget shared_ptr m_grid; shared_ptr m_root; vector m_buttons; + vector> m_labels; vector m_description_indexes; int m_width; int m_height; diff --git a/crawl-ref/source/tileweb.cc b/crawl-ref/source/tileweb.cc index e0c079201894..4be36b68686a 100644 --- a/crawl-ref/source/tileweb.cc +++ b/crawl-ref/source/tileweb.cc @@ -27,6 +27,7 @@ #include "libutil.h" #include "map-knowledge.h" #include "menu.h" +#include "outer-menu.h" #include "message.h" #include "mon-util.h" #include "notes.h" @@ -431,6 +432,14 @@ wint_t TilesFramework::_handle_control_message(sockaddr_un addr, string data) scroll.check(JSON_NUMBER); recv_formatted_scroller_scroll((int)scroll->number_); } + else if (msgtype == "outer_menu_focus") + { + JsonWrapper menu_id = json_find_member(obj.node, "menu_id"); + JsonWrapper hotkey = json_find_member(obj.node, "hotkey"); + menu_id.check(JSON_STRING); + hotkey.check(JSON_NUMBER); + OuterMenu::recv_outer_menu_focus(menu_id->string_, (int)hotkey->number_); + } return c; } diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index da49e6976e61..6769e275103d 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -859,13 +859,15 @@ void Text::set_bg_colour(COLOURS colour) void Image::set_tile(tile_def tile) { -#ifdef USE_TILE_LOCAL +#ifdef USE_TILE m_tile = tile; +#ifdef USE_TILE_LOCAL const tile_info &ti = tiles.get_image_manager()->tile_def_info(m_tile); m_tw = ti.width; m_th = ti.height; _invalidate_sizereq(); #endif +#endif } void Image::_render() diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index 9bc7cd04ebce..870ad2daf2e3 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -409,6 +409,7 @@ class Image : public Widget Image(tile_def tile) { set_tile(tile); }; virtual ~Image() {} void set_tile(tile_def tile); + tile_def get_tile() const { return m_tile; }; virtual void _render() override; virtual SizeReq _get_preferred_size(Direction dim, int prosp_width) override; diff --git a/crawl-ref/source/webserver/game_data/static/style.css b/crawl-ref/source/webserver/game_data/static/style.css index d317b290611b..09c74a50633c 100644 --- a/crawl-ref/source/webserver/game_data/static/style.css +++ b/crawl-ref/source/webserver/game_data/static/style.css @@ -1036,3 +1036,102 @@ body { #ui-stack:not([data-display-mode="tiles"]) .glyph-mode-hidden { display: none !important; } + +.newgame-choice { + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; +} + +.newgame-choice .header +{ + margin-bottom: 15px; + white-space: pre; + display: flex; + align-items: center; + flex: 1 0 auto; +} + +.newgame-choice .header > canvas +{ + margin-right: 10px; +} + +.newgame-choice > .body { + flex: 1 1 auto; + min-height: 0; + display: flex; + flex-direction: column; +} + +.newgame-choice .grid +{ + display: grid; + list-style: none; + min-height: 0; + flex: 1 1 auto; +} +.newgame-choice .sub-items +{ + flex: 1 0 auto; +} + +.newgame-choice .grid .button { + background: black; + white-space: pre; + padding: 1px; + border: 1px solid rgba(255, 255, 255, 0.001); +} + +.newgame-choice .grid .button.selected +{ + background: black; + border: 1px solid #222; +} + +.newgame-choice .grid .button.selected.hlc-7 { border: 1px solid #babdb6; } /* lightgrey */ +.newgame-choice .grid .button.selected.hlc-1 { border: 1px solid #204a87; } /* blue */ +.newgame-choice .grid .button.selected.hlc-2 { border: 1px solid #4e9a06; } /* green */ + +.newgame-choice .grid .button.selected:hover { + cursor: pointer; +} + +.newgame-choice .grid .button:active +{ + background: black; + border: 1px solid #222 !important; +} + +.newgame-choice .grid .button +{ + display: flex; + align-items: center; + padding-right: 1em; +} + +.newgame-choice .grid .button > span +{ + margin-left: 6px; +} + +#ui-stack[data-display-mode="tiles"] .newgame-choice .grid .label { + align-self: end; + margin-bottom: 0.75em; + margin-left: 2px; +} + +#ui-stack[data-display-mode="tiles"] .newgame-choice .grid .label::before { + content: " "; + display: inline-block; + margin-left: 32px; +} + +.newgame-choice .descriptions +{ + margin: 15px 0; + max-width: 70ch; + flex: 1 0 auto; +} diff --git a/crawl-ref/source/webserver/game_data/static/ui-layouts.js b/crawl-ref/source/webserver/game_data/static/ui-layouts.js index 00cf3d6ed7cf..f269eaac267c 100644 --- a/crawl-ref/source/webserver/game_data/static/ui-layouts.js +++ b/crawl-ref/source/webserver/game_data/static/ui-layouts.js @@ -717,6 +717,130 @@ function ($, comm, client, ui, enums, cr, util, scroller, main, gui, player) { $popup.children(".body")[0].textContent = msg.text; } + function focus_button($button) + { + var $popup = $button.closest(".newgame-choice"); + var menu_id = $button.closest("[menu_id]").attr("menu_id"); + $popup.find(".button.selected").removeClass("selected"); + $button.addClass("selected"); + var $scr = $button.closest(".simplebar-scroll-content"); + if ($scr.length === 1) + { + var br = $button[0].getBoundingClientRect(); + var gr = $scr.parent()[0].getBoundingClientRect(); + console.log(br.bottom, gr.bottom); + var delta = br.top < gr.top ? br.top - gr.top : + br.bottom > gr.bottom ? br.bottom - gr.bottom : 0; + console.log("delta: ", delta); + $scr[0].scrollTop += delta; + } + + var $descriptions = $popup.find(".descriptions"); + paneset_cycle($descriptions, $button.attr("data-description-index")); + comm.send_message("outer_menu_focus", { + hotkey: parseInt($button.attr("data-hotkey"), 10), + menu_id: menu_id, + }); + } + + function newgame_choice(msg) + { + var $popup = $(".templates > .newgame-choice").clone(); + if (msg.doll) + { + var $canvas = $(""); + var $title = $(""); + var $prompt = $("
"); + $popup.children(".header").append($canvas).append($title).after($prompt); + $title.html(util.formatted_string_to_html(msg.title)); + $prompt.html(util.formatted_string_to_html(msg.prompt)); + var renderer = new cr.DungeonCellRenderer(); + util.init_canvas($canvas[0], renderer.cell_width, renderer.cell_height); + renderer.init($canvas[0]); + $.each(msg.doll, function (i, doll_part) { + renderer.draw_player(doll_part[0], 0, 0, 0, 0, doll_part[1]); + }); + } + else + $popup.children(".header").html(util.formatted_string_to_html(msg.title)); + var renderer = new cr.DungeonCellRenderer(); + var $descriptions = $popup.find(".descriptions"); + + function build_item_grid(data, $container, fat) + { + $container.attr("menu_id", data.menu_id); + $.each(data.buttons, function (i, button) { + var $button = $("
"); + if ((button.tile || []).length > 0 || fat) + { + var $canvas = $(""); + util.init_canvas($canvas[0], renderer.cell_width, renderer.cell_height); + renderer.init($canvas[0]); + + $.each(button.tile || [], function (_, tile) { + renderer.draw_from_texture(tile.t, 0, 0, tile.tex, 0, 0, tile.ymax, false); + }); + $button.append($canvas); + } + $.each(button.labels || [button.label], function (i, label) { + var $lbl = $(util.formatted_string_to_html(label)).css("flex-grow", "1"); + $button.append($lbl); + }); + $button.attr("style", "grid-row:"+(button.y+1)+"; grid-column:"+(button.x+1)+";"); + $descriptions.append(" " + button.description + ""); + $button.attr("data-description-index", $descriptions.children().length - 1); + $button.attr("data-hotkey", button.hotkey); + $button.addClass("hlc-" + button.highlight_colour); + $container.append($button); + + $button.on("click", function () { + comm.send_message("key", { keycode: button.hotkey }); + }).on('hover', function () { focus_button($(this)) }); + }); + $.each(data.labels, function (i, button) { + var $button = $("
"); + $button.append(util.formatted_string_to_html(button.label)); + $button.attr("style", "grid-row:"+(button.y+1)+"; grid-column:"+(button.x+1)+";"); + $container.append($button); + }); + } + + var $main = $popup.find(".main-items"); + build_item_grid(msg["main-items"], $main, true); + build_item_grid(msg["sub-items"], $popup.find(".sub-items")); + scroller($main.parent()[0]); + focus_button($popup.find(".main-items").eq(0)); + + return $popup; + } + + function newgame_choice_update(msg) + { + if (!client.is_watching() && msg.from_client) + return; + var $popup = ui.top_popup(); + if (!$popup || !$popup.hasClass("newgame-choice")) + return; + focus_button($popup.find("[data-hotkey='"+msg.button_focus+"']")); + } + + function newgame_random_combo(msg) + { + var $popup = $(".templates > .describe-generic").clone(); + $popup.find(".header > span").html(util.formatted_string_to_html(msg.prompt)); + $popup.find(".body").html("Do you want to play this combination? [Y/n/q]"); + + var $canvas = $popup.find(".header > canvas"); + var renderer = new cr.DungeonCellRenderer(); + util.init_canvas($canvas[0], renderer.cell_width, renderer.cell_height); + renderer.init($canvas[0]); + $.each(msg.doll, function (i, doll_part) { + renderer.draw_player(doll_part[0], 0, 0, 0, 0, doll_part[1]); + }); + + return $popup; + } + var ui_handlers = { "describe-generic" : describe_generic, "describe-feature-wide" : describe_feature_wide, @@ -730,6 +854,8 @@ function ($, comm, client, ui, enums, cr, util, scroller, main, gui, player) { "formatted-scroller" : formatted_scroller, "progress-bar" : progress_bar, "msgwin-get-line" : msgwin_get_line, + "newgame-choice": newgame_choice, + "newgame-random-combo": newgame_random_combo, }; function register_ui_handlers(dict) @@ -766,6 +892,7 @@ function ($, comm, client, ui, enums, cr, util, scroller, main, gui, player) { "formatted-scroller" : formatted_scroller_update, "msgwin-get-line" : msgwin_get_line_update, "progress-bar" : progress_bar_update, + "newgame-choice" : newgame_choice_update, }; var handler = ui_handlers[msg.type]; if (handler) diff --git a/crawl-ref/source/webserver/game_data/templates/game.html b/crawl-ref/source/webserver/game_data/templates/game.html index f25a16c0b4e4..71906b3e5a42 100644 --- a/crawl-ref/source/webserver/game_data/templates/game.html +++ b/crawl-ref/source/webserver/game_data/templates/game.html @@ -293,6 +293,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
From a0fde063d1cab824bdd69a1528a59943109ec5bb Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 25 Aug 2018 23:12:43 +0800 Subject: [PATCH 678/864] Add pgup/pgdn/home/end support to OuterMenu --- crawl-ref/source/outer-menu.cc | 23 ++++++++++++++--------- crawl-ref/source/outer-menu.h | 2 +- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/crawl-ref/source/outer-menu.cc b/crawl-ref/source/outer-menu.cc index 56d37bb68a76..81355054d911 100644 --- a/crawl-ref/source/outer-menu.cc +++ b/crawl-ref/source/outer-menu.cc @@ -297,7 +297,7 @@ void OuterMenu::scroll_button_into_view(MenuButton *btn) scroller->set_scroll(scroller->get_scroll() + delta); } -bool OuterMenu::move_button_focus(int fx, int fy, int dx, int dy) +bool OuterMenu::move_button_focus(int fx, int fy, int dx, int dy, int limit) { MenuButton* btn = nullptr; int nx, ny; @@ -308,7 +308,8 @@ bool OuterMenu::move_button_focus(int fx, int fy, int dx, int dy) if (m_buttons[ny*m_width + nx]) { btn = m_buttons[ny*m_width + nx]; - break; + if (--limit == 0) + break; } } @@ -321,7 +322,7 @@ bool OuterMenu::move_button_focus(int fx, int fy, int dx, int dy) { int lfx = dx == 0 ? min(fx, linked->m_width-1) : dx < 0 ? linked->m_width : -1; int lfy = dy == 0 ? min(fy, linked->m_height-1) : dy < 0 ? linked->m_height : -1; - return linked->move_button_focus(lfx, lfy, dx, dy); + return linked->move_button_focus(lfx, lfy, dx, dy, 1); } } return btn != nullptr; @@ -329,18 +330,18 @@ bool OuterMenu::move_button_focus(int fx, int fy, int dx, int dy) bool OuterMenu::scroller_event_hook(const wm_event& ev) { - MenuButton::focus_on_mouse = ev.type == WME_MOUSEWHEEL - || ev.type == WME_KEYDOWN && ev.key.keysym.sym == CK_PGDN - || ev.type == WME_KEYDOWN && ev.key.keysym.sym == CK_PGUP; + MenuButton::focus_on_mouse = ev.type == WME_MOUSEWHEEL; if (ev.type != WME_KEYDOWN) return false; int key = ev.key.keysym.sym; - if (key == CK_DOWN || key == CK_UP || key == CK_LEFT || key == CK_RIGHT) + if (key == CK_DOWN || key == CK_UP || key == CK_LEFT || key == CK_RIGHT + || key == CK_HOME || key == CK_END || key == CK_PGUP || key == CK_PGDN) { const int dx = key == CK_LEFT ? -1 : key == CK_RIGHT ? 1 : 0; - const int dy = key == CK_UP ? -1 : key == CK_DOWN ? 1 : 0; + const int dy = key == CK_UP || key == CK_PGUP || key == CK_HOME ? -1 + : key == CK_DOWN || key == CK_PGDN || key == CK_END ? 1 : 0; ASSERT((dx == 0) != (dy == 0)); const Widget* focus = ui::get_focused_widget(); @@ -355,7 +356,11 @@ bool OuterMenu::scroller_event_hook(const wm_event& ev) } ASSERT(fx >= 0 && fy >= 0); - return move_button_focus(fx, fy, dx, dy); + const int pagesz = m_root->get_region()[3] / focus->get_region()[3] - 1; + const int limit = (key == CK_HOME || key == CK_END) ? INT_MAX + : (key == CK_PGUP || key == CK_PGDN) ? pagesz : 1; + + return move_button_focus(fx, fy, dx, dy, limit); } return false; diff --git a/crawl-ref/source/outer-menu.h b/crawl-ref/source/outer-menu.h index bf86e197ec94..27fad991d4f6 100644 --- a/crawl-ref/source/outer-menu.h +++ b/crawl-ref/source/outer-menu.h @@ -78,7 +78,7 @@ class OuterMenu : public ui::Widget protected: bool scroller_event_hook(const wm_event& ev); - bool move_button_focus(int fx, int fy, int dx, int dy); + bool move_button_focus(int fx, int fy, int dx, int dy, int limit); shared_ptr m_grid; shared_ptr m_root; From 94b374d74164605fd7ecf6332b9eb5dd9b094f52 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sun, 26 Aug 2018 23:35:42 +0800 Subject: [PATCH 679/864] Add tile to game-over screen --- crawl-ref/source/end.cc | 48 ++++++++++++++++--- .../webserver/game_data/static/style.css | 34 +++++++++++++ .../webserver/game_data/static/ui-layouts.js | 20 ++++++++ .../webserver/game_data/templates/game.html | 7 +++ 4 files changed, 103 insertions(+), 6 deletions(-) diff --git a/crawl-ref/source/end.cc b/crawl-ref/source/end.cc index 15c077af93fd..76ed25137ab7 100644 --- a/crawl-ref/source/end.cc +++ b/crawl-ref/source/end.cc @@ -35,6 +35,7 @@ #include "view.h" #include "xom.h" #include "ui.h" +#include "tiledef-feat.h" #ifdef __ANDROID__ #include @@ -450,13 +451,29 @@ NORETURN void end_game(scorefile_entry &se) if (crawl_state.unsaved_macros && yesno("Save macros?", true, 'n')) macro_save(); -#ifdef USE_TILE_WEB - tiles_crt_popup show_as_popup; + auto title_hbox = make_shared(Widget::HORZ); +#ifdef USE_TILE + tile_def death_tile(TILEG_ERROR, TEX_GUI); + if (death_type == KILLED_BY_LEAVING || death_type == KILLED_BY_WINNING) + death_tile = tile_def(TILE_DNGN_EXIT_DUNGEON, TEX_FEAT); + else + death_tile = tile_def(TILE_DNGN_GRAVESTONE+1, TEX_FEAT); + + auto tile = make_shared(death_tile); + tile->set_margin_for_sdl({0, 10, 0, 0}); + title_hbox->add_child(move(tile)); #endif + string goodbye_title = make_stringf("Goodbye, %s.", you.your_name.c_str()); + title_hbox->add_child(make_shared(goodbye_title)); + title_hbox->align_items = Widget::CENTER; + title_hbox->set_margin_for_sdl({0, 0, 20, 0}); + title_hbox->set_margin_for_crt({0, 0, 1, 0}); + + auto vbox = make_shared(Box::VERT); + vbox->add_child(move(title_hbox)); string goodbye_msg; - goodbye_msg += make_stringf("Goodbye, %s.", you.your_name.c_str()); - goodbye_msg += "\n\n "; // Space padding where # would go in list format + goodbye_msg += " "; // Space padding where # would go in list format string hiscore = hiscores_format_single_long(se, true); @@ -477,16 +494,35 @@ NORETURN void end_game(scorefile_entry &se) #endif mouse_control mc(MOUSE_MODE_MORE); - auto prompt_ui = make_shared(formatted_string::parse_string(goodbye_msg)); - auto popup = make_shared(prompt_ui); + + auto goodbye_txt = make_shared(formatted_string::parse_string(goodbye_msg)); + vbox->add_child(goodbye_txt); + auto popup = make_shared(move(vbox)); bool done = false; popup->on(Widget::slots.event, [&](wm_event ev) { return done = ev.type == WME_KEYDOWN; }); if (!crawl_state.seen_hups && !crawl_state.disables[DIS_CONFIRMATIONS]) + { +#ifdef USE_TILE_WEB + tiles.json_open_object(); + tiles.json_open_object("tile"); + tiles.json_write_int("t", death_tile.tile); + tiles.json_write_int("tex", death_tile.tex); + tiles.json_close_object(); + tiles.json_write_string("title", goodbye_title); + tiles.json_write_string("body", goodbye_msg); + tiles.push_ui_layout("game-over", 0); +#endif + ui::run_layout(move(popup), done); +#ifdef USE_TILE_WEB + tiles.pop_ui_layout(); +#endif + } + #ifdef USE_TILE_WEB tiles.send_exit_reason(reason, hiscore); #endif diff --git a/crawl-ref/source/webserver/game_data/static/style.css b/crawl-ref/source/webserver/game_data/static/style.css index 09c74a50633c..f80d62e258f6 100644 --- a/crawl-ref/source/webserver/game_data/static/style.css +++ b/crawl-ref/source/webserver/game_data/static/style.css @@ -1135,3 +1135,37 @@ body { max-width: 70ch; flex: 1 0 auto; } + +.game-over { + max-width: 80ch; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + width: 100%; /* for IE11 */ + max-height: inherit; +} +.game-over > .header { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + margin-bottom: 20px; + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; +} +.game-over > .header > canvas { + margin-right: 10px; +} +.game-over > .body { + -webkit-box-flex: 1; + -ms-flex: 1 1 auto; + flex: 1 1 auto; + white-space: pre-wrap; +} diff --git a/crawl-ref/source/webserver/game_data/static/ui-layouts.js b/crawl-ref/source/webserver/game_data/static/ui-layouts.js index f269eaac267c..79b4da81b21f 100644 --- a/crawl-ref/source/webserver/game_data/static/ui-layouts.js +++ b/crawl-ref/source/webserver/game_data/static/ui-layouts.js @@ -841,6 +841,25 @@ function ($, comm, client, ui, enums, cr, util, scroller, main, gui, player) { return $popup; } + function game_over(desc) + { + var $popup = $(".templates > .game-over").clone(); + $popup.find(".header > span").html(desc.title); + $popup.children(".body").html(fmt_body_txt(desc.body)); + var s = scroller($popup.children(".body")[0]); + $popup.on("keydown keypress", function (event) { + scroller_handle_key(s, event); + }); + + var canvas = $popup.find(".header > canvas"); + var renderer = new cr.DungeonCellRenderer(); + util.init_canvas(canvas[0], renderer.cell_width, renderer.cell_height); + renderer.init(canvas[0]); + renderer.draw_from_texture(desc.tile.t, 0, 0, desc.tile.tex, 0, 0, desc.tile.ymax, false); + + return $popup; + } + var ui_handlers = { "describe-generic" : describe_generic, "describe-feature-wide" : describe_feature_wide, @@ -856,6 +875,7 @@ function ($, comm, client, ui, enums, cr, util, scroller, main, gui, player) { "msgwin-get-line" : msgwin_get_line, "newgame-choice": newgame_choice, "newgame-random-combo": newgame_random_combo, + "game-over" : game_over, }; function register_ui_handlers(dict) diff --git a/crawl-ref/source/webserver/game_data/templates/game.html b/crawl-ref/source/webserver/game_data/templates/game.html index 71906b3e5a42..e6e44d0e0b78 100644 --- a/crawl-ref/source/webserver/game_data/templates/game.html +++ b/crawl-ref/source/webserver/game_data/templates/game.html @@ -306,6 +306,13 @@
+
+
+ + +
+
+
From ba565db48d1cb518f664b824f198a0fb634cd534 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Thu, 6 Sep 2018 22:14:12 +0800 Subject: [PATCH 680/864] Fix Switcher widget handling mouse events incorrectly --- crawl-ref/source/ui.cc | 12 ++++++++++++ crawl-ref/source/ui.h | 1 + 2 files changed, 13 insertions(+) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 6769e275103d..d3f0cae3f9df 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -1012,6 +1012,18 @@ void Switcher::_allocate_region() } } +shared_ptr Switcher::get_child_at_offset(int x, int y) +{ + if (m_children.size() == 0) + return nullptr; + + int c = max(0, min(m_current, (int)m_children.size())); + const auto region = m_children[c]->get_region(); + bool inside = (x > region[0] && x < region[0] + region[2]) + && (y > region[1] && y < region[1] + region[3]); + return inside ? m_children[c] : nullptr; +} + shared_ptr Grid::get_child_at_offset(int x, int y) { int lx = x - m_region[0]; diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index 870ad2daf2e3..c767eba523c7 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -447,6 +447,7 @@ class Switcher : public ContainerVec virtual void _render() override; virtual SizeReq _get_preferred_size(Direction dim, int prosp_width) override; virtual void _allocate_region() override; + virtual shared_ptr get_child_at_offset(int x, int y) override; protected: int m_current; From 6919a330b2d4194c55c832a63363c79bbf167e7c Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Thu, 6 Sep 2018 22:14:26 +0800 Subject: [PATCH 681/864] Add enable_shared_from_this to Widget --- crawl-ref/source/ui.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index c767eba523c7..b14f6f03655c 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -85,7 +85,7 @@ class Slot HandlerMap handlers; }; -class Widget +class Widget : public enable_shared_from_this { public: enum Align { @@ -117,6 +117,9 @@ class Widget virtual void _allocate_region(); void _set_parent(Widget* p); Widget* _get_parent() const { return m_parent; }; + shared_ptr get_shared() { + return shared_from_this(); + }; void _invalidate_sizereq(bool immediate = true); void _queue_allocation(bool immediate = true); void set_allocation_needed() { alloc_queued = true; }; From 5dd181b81525fbac6ff5a0fd13a0c937439c8c54 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 8 Sep 2018 12:37:20 +0800 Subject: [PATCH 682/864] Add alignment options to Switcher widget --- crawl-ref/source/ui.cc | 23 +++++++++++++++++++++++ crawl-ref/source/ui.h | 2 ++ 2 files changed, 25 insertions(+) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index d3f0cae3f9df..89843fe1f2a0 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -1008,6 +1008,29 @@ void Switcher::_allocate_region() cr[2] = min(max(pw.min, m_region[2]), pw.nat); SizeReq ph = child->get_preferred_size(Widget::VERT, cr[2]); cr[3] = min(max(ph.min, m_region[3]), ph.nat); + int xo, yo; + switch (align_x) + { + case Widget::START: xo = 0; break; + case Widget::CENTER: xo = (m_region[2] - cr[2])/2; break; + case Widget::END: xo = m_region[2] - cr[2]; break; + case Widget::STRETCH: xo = 0; break; + default: ASSERT(0); + } + switch (align_y) + { + case Widget::START: yo = 0; break; + case Widget::CENTER: yo = (m_region[3] - cr[3])/2; break; + case Widget::END: yo = m_region[3] - cr[3]; break; + case Widget::STRETCH: yo = 0; break; + default: ASSERT(0); + } + cr[2] += xo; + cr[3] += yo; + if (align_x == Widget::STRETCH) + cr[2] = m_region[2]; + if (align_y == Widget::STRETCH) + cr[3] = m_region[3]; child->allocate_region(cr); } } diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index b14f6f03655c..eb826cb88633 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -447,6 +447,8 @@ class Switcher : public ContainerVec void add_child(shared_ptr child); int& current(); + Widget::Align align_x = START, align_y = START; + virtual void _render() override; virtual SizeReq _get_preferred_size(Direction dim, int prosp_width) override; virtual void _allocate_region() override; From bb89a6cd1e7677388f66bc31ffeaa29f0fb071bc Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 8 Sep 2018 13:53:56 +0800 Subject: [PATCH 683/864] Improve newgame name choice prompt --- crawl-ref/source/newgame.cc | 88 +++++++++++++++++++++++++--------- crawl-ref/source/outer-menu.cc | 5 +- 2 files changed, 70 insertions(+), 23 deletions(-) diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 4de59552e768..6c9b0d33c1c4 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -633,37 +633,83 @@ static void _choose_name(newgame_def& ng, newgame_def& choice) auto prompt_ui = make_shared(); vbox->add_child(prompt_ui); - auto popup = make_shared(move(vbox)); + auto sub_items = make_shared(false, 3, 1); + vbox->add_child(sub_items); - popup->on(Widget::slots.event, [&](wm_event ev) { - if (ev.type != WME_KEYDOWN) - return false; - int key = ev.key.keysym.sym; + _add_menu_sub_item(sub_items, 0, 0, + "Esc - Quit", "", CK_ESCAPE, CK_ESCAPE); + _add_menu_sub_item(sub_items, 1, 0, + "* - Random name", "", '*', '*'); - if (!overwrite_prompt) - { - key = reader.putkey(key); - good_name = is_good_name(buf, true); - if (key != -1) - { - if (key_is_escape(key)) - return done = cancel = true; + auto ok_switcher = make_shared(); + ok_switcher->align_y = Widget::STRETCH; + { + auto tmp = make_shared(); + tmp->set_text(formatted_string("Enter - Begin!", BROWN)); + + auto btn = make_shared(); + tmp->set_margin_for_sdl({4,8,4,8}); + tmp->set_margin_for_crt({0,2,0,0}); + btn->set_child(move(tmp)); + btn->id = CK_ENTER; + btn->description = ""; + btn->hotkey = CK_ENTER; + btn->highlight_colour = STARTUP_HIGHLIGHT_CONTROL; + + auto err = make_shared( + formatted_string("That's a silly name!", LIGHTRED)); + err->set_margin_for_sdl({0,0,0,10}); + auto box = make_shared(Box::HORZ); + box->align_items = Widget::CENTER; + box->add_child(err); + + ok_switcher->add_child(btn); + ok_switcher->add_child(box); + sub_items->add_button(btn, 2, 0); + } + auto popup = make_shared(move(vbox)); + + sub_items->on_button_activated = [&](int id) { + switch (id) + { + case '*': + reader.putkey(CK_END); + reader.putkey(CONTROL('U')); + for (char ch : _random_name()) + reader.putkey(ch); + return; + case CK_ENTER: choice.name = buf; trim_string(choice.name); - if (choice.name.empty()) choice.name = _random_name(); - if (good_name) { ng.name = choice.name; ng.filename = get_save_filename(choice.name); overwrite_prompt = save_exists(ng.filename); if (!overwrite_prompt) - return done = true; + done = true; } - } + return; + case CK_ESCAPE: + done = cancel = true; + return; + } + + }; + + popup->on(Widget::slots.event, [&](wm_event ev) { + if (ev.type != WME_KEYDOWN) + return false; + int key = ev.key.keysym.sym; + + if (!overwrite_prompt) + { + key = reader.putkey(key); + good_name = is_good_name(buf, true); + ok_switcher->current() = good_name ? 0 : 1; } else { @@ -675,18 +721,16 @@ static void _choose_name(newgame_def& ng, newgame_def& choice) }); ui::push_layout(move(popup)); + ui::set_focused_widget(sub_items.get()); while (!done && !crawl_state.seen_hups) { formatted_string prompt; prompt.textcolour(CYAN); prompt.cprintf("What is your name today? "); prompt.textcolour(LIGHTGREY); - prompt.cprintf("%s", buf); - prompt.cprintf("\n\nLeave blank for a random name, or use Escape to cancel this character.\n\n"); + prompt.cprintf("%s\n", buf); prompt.textcolour(LIGHTRED); - if (!good_name) - prompt.cprintf("That's a silly name!"); - else if (overwrite_prompt) + if (overwrite_prompt) prompt.cprintf("You have an existing game under this name; really overwrite? [Y/n]"); prompt_ui->set_text(prompt); diff --git a/crawl-ref/source/outer-menu.cc b/crawl-ref/source/outer-menu.cc index 81355054d911..11e4069ba34f 100644 --- a/crawl-ref/source/outer-menu.cc +++ b/crawl-ref/source/outer-menu.cc @@ -259,7 +259,10 @@ void OuterMenu::add_button(shared_ptr btn, int x, int y) m_description_indexes[y*m_width + x] = descriptions->num_children()-1; } - m_grid->add_child(move(btn), x, y); + Widget *r; + for (Widget *p = btn.get(); p; p = p->_get_parent()) + r = p; + m_grid->add_child(r->get_shared(), x, y); } void OuterMenu::scroll_button_into_view(MenuButton *btn) From cd35390ea8b367433948a6d0dc287c08726ee8e8 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 26 Jan 2019 14:19:48 +0800 Subject: [PATCH 684/864] Improve end-game hiscore list appearance --- crawl-ref/source/end.cc | 43 ++++++++++++++++++++++++++++-------- crawl-ref/source/hiscores.cc | 3 ++- crawl-ref/source/hiscores.h | 3 +-- crawl-ref/source/ui.cc | 2 +- crawl-ref/source/ui.h | 2 ++ 5 files changed, 40 insertions(+), 13 deletions(-) diff --git a/crawl-ref/source/end.cc b/crawl-ref/source/end.cc index 76ed25137ab7..7502c1dfd495 100644 --- a/crawl-ref/source/end.cc +++ b/crawl-ref/source/end.cc @@ -291,6 +291,19 @@ static string _exit_type_to_string(game_exit e) return "BUGGY EXIT TYPE"; } +class HiscoreScroller : public Scroller +{ +public: + virtual void _allocate_region(); + int scroll_target = 0; +}; + +void HiscoreScroller::_allocate_region() +{ + m_scroll = scroll_target - m_region[3]/2; + Scroller::_allocate_region(); +} + NORETURN void end_game(scorefile_entry &se) { //Update states @@ -477,26 +490,38 @@ NORETURN void end_game(scorefile_entry &se) string hiscore = hiscores_format_single_long(se, true); - const int desc_lines = count_occurrences(hiscore, "\n") + 1; - goodbye_msg += hiscore; goodbye_msg += make_stringf("\nBest Crawlers - %s\n", crawl_state.game_type_name().c_str()); - // "- 5" gives us an extra line in case the description wraps on a line. - goodbye_msg += hiscores_print_list(get_number_of_lines() - desc_lines - 5, - SCORE_TERSE, hiscore_index); - -#ifndef DGAMELAUNCH - goodbye_msg += make_stringf("\nYou can find your morgue file in the '%s' directory.", - morgue_directory().c_str()); +#ifdef USE_TILE_LOCAL + const int line_height = tiles.get_crt_font()->char_height(); +#else + const int line_height = 1; #endif + int start; + int num_lines = 100; + string hiscores = hiscores_print_list(num_lines, SCORE_TERSE, hiscore_index, start); + auto scroller = make_shared(); + auto hiscores_txt = make_shared(formatted_string::parse_string(hiscores)); + scroller->set_child(hiscores_txt); + scroller->set_scrollbar_visible(false); + scroller->scroll_target = (hiscore_index - start)*line_height + (line_height/2); + mouse_control mc(MOUSE_MODE_MORE); auto goodbye_txt = make_shared(formatted_string::parse_string(goodbye_msg)); vbox->add_child(goodbye_txt); + vbox->add_child(scroller); + +#ifndef DGAMELAUNCH + string morgue_dir = make_stringf("\nYou can find your morgue file in the '%s' directory.", + morgue_directory().c_str()); + vbox->add_child(make_shared(formatted_string::parse_string(morgue_dir))); +#endif + auto popup = make_shared(move(vbox)); bool done = false; popup->on(Widget::slots.event, [&](wm_event ev) { diff --git a/crawl-ref/source/hiscores.cc b/crawl-ref/source/hiscores.cc index eadb6247e552..52af29c14a45 100644 --- a/crawl-ref/source/hiscores.cc +++ b/crawl-ref/source/hiscores.cc @@ -284,7 +284,7 @@ void hiscores_print_all(int display_count, int format) // Displays high scores using curses. For output to the console, use // hiscores_print_all. -string hiscores_print_list(int display_count, int format, int newest_entry) +string hiscores_print_list(int display_count, int format, int newest_entry, int& start_out) { unwind_bool scorefile_display(crawl_state.updating_scores, true); string ret; @@ -326,6 +326,7 @@ string hiscores_print_list(int display_count, int format, int newest_entry) ret += ""; } + start_out = start; return ret; } diff --git a/crawl-ref/source/hiscores.h b/crawl-ref/source/hiscores.h index f24102cef5de..936e5b38bf5e 100644 --- a/crawl-ref/source/hiscores.h +++ b/crawl-ref/source/hiscores.h @@ -16,8 +16,7 @@ void logfile_new_entry(const scorefile_entry &se); void hiscores_read_to_memory(); -string hiscores_print_list(int display_count = -1, int format = SCORE_TERSE, - int newest_entry = -1); +string hiscores_print_list(int display_count, int format, int newest_entry, int& start_out); void hiscores_print_all(int display_count = -1, int format = SCORE_TERSE); void show_hiscore_table(); diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 89843fe1f2a0..ae61534eddbe 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -1343,7 +1343,7 @@ void Scroller::_allocate_region() rect.set_col(col_a, col_b); m_shade_buf.add_primitive(rect); } - if (ch_reg[3] > m_region[3]) { + if (ch_reg[3] > m_region[3] && m_scrolbar_visible) { const int x = m_region[0]+m_region[2]; const float h_percent = m_region[3] / (float)ch_reg[3]; const int h = m_region[3]*min(max(0.05f, h_percent), 1.0f); diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index eb826cb88633..b801f6db45eb 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -556,12 +556,14 @@ class Scroller : public Bin virtual void set_scroll(int y); int get_scroll() const { return m_scroll; }; + void set_scrollbar_visible(bool vis) { m_scrolbar_visible = vis; }; virtual void _render() override; virtual SizeReq _get_preferred_size(Direction dim, int prosp_width) override; virtual void _allocate_region() override; virtual bool on_event(const wm_event& event) override; protected: int m_scroll = 0; + bool m_scrolbar_visible = true; #ifdef USE_TILE_LOCAL VertBuffer m_shade_buf = VertBuffer(false, true); ShapeBuffer m_scrollbar_buf; From 3e190a46ec0fbe505143977dd40f1c45f51eeb48 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Fri, 27 Sep 2019 02:24:37 +0800 Subject: [PATCH 685/864] Remove unused menu code --- crawl-ref/source/menu.cc | 731 --------------------------------------- crawl-ref/source/menu.h | 170 --------- 2 files changed, 901 deletions(-) diff --git a/crawl-ref/source/menu.cc b/crawl-ref/source/menu.cc index f1b9796b95ad..9283ddf62e4e 100644 --- a/crawl-ref/source/menu.cc +++ b/crawl-ref/source/menu.cc @@ -3427,102 +3427,6 @@ void TextTileItem::render() for (int i = 0; i < TEX_MAX; i++) m_tile_buf[i].draw(); } - -SaveMenuItem::SaveMenuItem() -{ -} - -SaveMenuItem::~SaveMenuItem() -{ - for (int t = 0; t < TEX_MAX; t++) - m_tile_buf[t].clear(); -} - -void SaveMenuItem::render() -{ - if (!m_visible) - return; - - TextTileItem::render(); -} - -void SaveMenuItem::set_doll(dolls_data doll) -{ - m_save_doll = doll; - _pack_doll(); -} - -void SaveMenuItem::_pack_doll() -{ - m_tiles.clear(); - // FIXME: Implement this logic in one place in e.g. pack_doll_buf(). - int p_order[TILEP_PART_MAX] = - { - TILEP_PART_SHADOW, // 0 - TILEP_PART_HALO, - TILEP_PART_ENCH, - TILEP_PART_DRCWING, - TILEP_PART_CLOAK, - TILEP_PART_BASE, // 5 - TILEP_PART_BOOTS, - TILEP_PART_LEG, - TILEP_PART_BODY, - TILEP_PART_ARM, - TILEP_PART_HAIR, - TILEP_PART_BEARD, - TILEP_PART_DRCHEAD, // 15 - TILEP_PART_HELM, - TILEP_PART_HAND1, // 10 - TILEP_PART_HAND2, - }; - - int flags[TILEP_PART_MAX]; - tilep_calc_flags(m_save_doll, flags); - - // For skirts, boots go under the leg armour. For pants, they go over. - if (m_save_doll.parts[TILEP_PART_LEG] < TILEP_LEG_SKIRT_OFS) - { - p_order[6] = TILEP_PART_BOOTS; - p_order[7] = TILEP_PART_LEG; - } - - // Special case bardings from being cut off. - bool is_naga = (m_save_doll.parts[TILEP_PART_BASE] == TILEP_BASE_NAGA - || m_save_doll.parts[TILEP_PART_BASE] == TILEP_BASE_NAGA + 1); - if (m_save_doll.parts[TILEP_PART_BOOTS] >= TILEP_BOOTS_NAGA_BARDING - && m_save_doll.parts[TILEP_PART_BOOTS] <= TILEP_BOOTS_NAGA_BARDING_RED) - { - flags[TILEP_PART_BOOTS] = is_naga ? TILEP_FLAG_NORMAL : TILEP_FLAG_HIDE; - } - - bool is_cent = (m_save_doll.parts[TILEP_PART_BASE] == TILEP_BASE_CENTAUR - || m_save_doll.parts[TILEP_PART_BASE] == TILEP_BASE_CENTAUR + 1); - if (m_save_doll.parts[TILEP_PART_BOOTS] >= TILEP_BOOTS_CENTAUR_BARDING - && m_save_doll.parts[TILEP_PART_BOOTS] <= TILEP_BOOTS_CENTAUR_BARDING_RED) - { - flags[TILEP_PART_BOOTS] = is_cent ? TILEP_FLAG_NORMAL : TILEP_FLAG_HIDE; - } - - for (int i = 0; i < TILEP_PART_MAX; ++i) - { - const int p = p_order[i]; - const tileidx_t idx = m_save_doll.parts[p]; - if (idx == 0 || idx == TILEP_SHOW_EQUIP || flags[p] == TILEP_FLAG_HIDE) - continue; - - ASSERT_RANGE(idx, TILE_MAIN_MAX, TILEP_PLAYER_MAX); - - int ymax = TILE_Y; - - if (flags[p] == TILEP_FLAG_CUT_CENTAUR - || flags[p] == TILEP_FLAG_CUT_NAGA) - { - ymax = 18; - } - - m_tiles.emplace_back(idx, TEX_PLAYER, ymax); - } -} #endif MenuObject::MenuObject() : m_dirty(false), m_allow_focus(true), m_min_coord(0,0), @@ -4120,582 +4024,6 @@ MenuItem* MenuFreeform::_find_item_by_direction(const MenuItem* start, return closest; } -MenuScroller::MenuScroller(): m_topmost_visible(0), m_currently_active(0), - m_items_shown(0) -{ -#ifdef USE_TILE_LOCAL - m_arrow_up = new TextTileItem(); - m_arrow_down = new TextTileItem(); - m_arrow_up->add_tile(tile_def(TILE_MI_ARROW0, TEX_DEFAULT)); - m_arrow_down->add_tile(tile_def(TILE_MI_ARROW4, TEX_DEFAULT)); -#endif -} - -MenuScroller::~MenuScroller() -{ -#ifdef USE_TILE_LOCAL - delete m_arrow_up; - delete m_arrow_down; -#endif - deleteAll(m_entries); -} - -MenuObject::InputReturnValue MenuScroller::process_input(int key) -{ - if (!m_allow_focus || !m_visible) - return INPUT_NO_ACTION; - - if (m_currently_active < 0) - { - if (m_entries.empty()) - { - // nothing to process - return MenuObject::INPUT_NO_ACTION; - } - else - { - // pick the first item possible - for (unsigned int i = 0; i < m_entries.size(); ++i) - { - if (m_entries.at(i)->can_be_highlighted()) - { - _set_active_item_by_index(i); - break; - } - } - } - } - - MenuItem* find_entry = nullptr; - switch (key) - { - case CK_ENTER: - if (m_currently_active < 0) - return MenuObject::INPUT_NO_ACTION; - - select_item(m_currently_active); - if (get_active_item()->selected()) - return MenuObject::INPUT_SELECTED; - else - return MenuObject::INPUT_DESELECTED; - break; - case CK_UP: - case CONTROL('K'): - case CONTROL('P'): - find_entry = _find_item_by_direction(m_currently_active, UP); - if (find_entry != nullptr) - { - set_active_item(find_entry); - return MenuObject::INPUT_ACTIVE_CHANGED; - } - else - return MenuObject::INPUT_FOCUS_RELEASE_UP; - break; - case CK_DOWN: - case CONTROL('J'): - case CONTROL('N'): - find_entry = _find_item_by_direction(m_currently_active, DOWN); - if (find_entry != nullptr) - { - set_active_item(find_entry); - return MenuObject::INPUT_ACTIVE_CHANGED; - } - else - return MenuObject::INPUT_FOCUS_RELEASE_DOWN; - break; - case CK_LEFT: - return MenuObject::INPUT_FOCUS_RELEASE_LEFT; - case CK_RIGHT: - return MenuObject::INPUT_FOCUS_RELEASE_RIGHT; - case CK_PGUP: - if (m_currently_active != m_topmost_visible) - { - set_active_item(m_topmost_visible); - return MenuObject::INPUT_ACTIVE_CHANGED; - } - else - { - if (m_currently_active == 0) - return MenuObject::INPUT_FOCUS_RELEASE_UP; - else - { - int new_active = m_currently_active - m_items_shown; - if (new_active < 0) - new_active = 0; - set_active_item(new_active); - return MenuObject::INPUT_ACTIVE_CHANGED; - } - } - case CK_PGDN: - { - int last_item_visible = m_topmost_visible + m_items_shown - 1; - int last_menu_item = m_entries.size() - 1; - if (last_item_visible > m_currently_active) - { - set_active_item(last_item_visible); - return MenuObject::INPUT_ACTIVE_CHANGED; - } - else if (m_currently_active == last_menu_item) - return MenuObject::INPUT_FOCUS_RELEASE_DOWN; - else - { - int new_active = m_currently_active + m_items_shown - 1; - if (new_active > last_menu_item) - new_active = last_menu_item; - set_active_item(new_active); - return MenuObject::INPUT_ACTIVE_CHANGED; - } - } - default: - find_entry = select_item_by_hotkey(key); - if (find_entry != nullptr) - { - if (find_entry->selected()) - return MenuObject::INPUT_SELECTED; - else - return MenuObject::INPUT_DESELECTED; - } - break; - } - return MenuObject::INPUT_NO_ACTION; -} - -#ifdef USE_TILE_LOCAL -MenuObject::InputReturnValue MenuScroller::handle_mouse(const MouseEvent &me) -{ - if (!m_allow_focus || !m_visible) - return INPUT_NO_ACTION; - - if (!_is_mouse_in_bounds(coord_def(me.px, me.py))) - { - if (m_currently_active >= 0) - { - _set_active_item_by_index(-1); - return INPUT_FOCUS_LOST; - } - else - return INPUT_NO_ACTION; - } - - MenuItem* find_item = nullptr; - - if (me.event == MouseEvent::MOVE) - { - find_item = _find_item_by_mouse_coords(coord_def(me.px, me.py)); - if (find_item == nullptr) - { - if (m_currently_active >= 0) - { - // Do not signal on cleared active events - _set_active_item_by_index(-1); - return INPUT_NO_ACTION; - } - } - else - { - if (m_currently_active >= 0) - { - // prevent excess _place_item calls if the mouse over is already - // active - if (find_item != m_entries.at(m_currently_active)) - { - set_active_item(find_item); - return INPUT_ACTIVE_CHANGED; - } - else - return INPUT_NO_ACTION; - } - else - { - set_active_item(find_item); - return INPUT_ACTIVE_CHANGED; - } - - } - return INPUT_NO_ACTION; - } - - if (me.event == MouseEvent::PRESS && me.button == MouseEvent::LEFT) - { - find_item = _find_item_by_mouse_coords(coord_def(me.px, - me.py)); - if (find_item != nullptr) - { - select_item(find_item); - if (find_item->selected()) - return INPUT_SELECTED; - else - return INPUT_DESELECTED; - } - else - { - // handle clicking on the scrollbar (top half of region => scroll up) - if (static_cast(me.py)-m_min_coord.y > (m_max_coord.y-m_min_coord.y)/2) - return process_input(CK_DOWN); - else - return process_input(CK_UP); - } - } - else if (me.event == MouseEvent::PRESS && me.button == MouseEvent::RIGHT) - return INPUT_END_MENU_ABORT; - // all the other Mouse Events are uninteresting and are ignored - return INPUT_NO_ACTION; -} -#endif - -void MenuScroller::render() -{ - if (!m_visible) - return; - - if (m_dirty) - _place_items(); - - for (MenuItem *item : m_entries) - item->render(); - -#ifdef USE_TILE_LOCAL - // draw scrollbar - m_arrow_up->render(); - m_arrow_down->render(); -#endif -} - -MenuItem* MenuScroller::get_active_item() -{ - if (m_currently_active >= 0 - && m_currently_active < static_cast (m_entries.size())) - { - return m_entries.at(m_currently_active); - } - return nullptr; -} - -void MenuScroller::set_active_item(int ID) -{ - if (m_currently_active >= 0) - { - if (m_entries.at(m_currently_active)->get_id() == ID) - { - // prevent useless _place_items - return; - } - } - - auto it = find_if(m_entries.begin(), m_entries.end(), - bind(_id_comparison, placeholders::_1, ID)); - if (it != m_entries.end()) - { - set_active_item(*it); - return; - } - m_currently_active = 0; - m_dirty = true; - return; -} - -void MenuScroller::_set_active_item_by_index(int index) -{ - // prevent useless _place_items - if (index == m_currently_active) - return; - - if (index >= 0 && index < static_cast (m_entries.size())) - { - m_currently_active = index; - if (m_currently_active < m_topmost_visible) - m_topmost_visible = m_currently_active; - } - else - m_currently_active = -1; - m_dirty = true; -} - -void MenuScroller::set_active_item(MenuItem* item) -{ - if (item == nullptr) - { - _set_active_item_by_index(-1); - return; - } - - for (int i = 0; i < static_cast (m_entries.size()); ++i) - { - if (item == m_entries.at(i)) - { - _set_active_item_by_index(i); - return; - } - } - _set_active_item_by_index(-1); -} - -void MenuScroller::activate_first_item() -{ - if (!m_entries.empty()) - { - // find the first activeable item - for (int i = 0; i < static_cast (m_entries.size()); ++i) - { - if (m_entries.at(i)->can_be_highlighted()) - { - _set_active_item_by_index(i); - break; // escape loop - } - } - } -} - -void MenuScroller::activate_last_item() -{ - if (!m_entries.empty()) - { - // find the last activeable item - for (int i = m_entries.size() -1; i >= 0; --i) - { - if (m_entries.at(i)->can_be_highlighted()) - { - _set_active_item_by_index(i); - break; // escape loop - } - } - } -} - -bool MenuScroller::select_item(int index) -{ - if (index >= 0 && index < static_cast (m_entries.size())) - { - // Flip the flag - m_entries.at(index)->select(!m_entries.at(index)->selected()); - return m_entries.at(index)->selected(); - } - return false; -} - -bool MenuScroller::select_item(MenuItem* item) -{ - ASSERT(item != nullptr); - // Is the item in the menu? - for (int i = 0; i < static_cast (m_entries.size()); ++i) - { - if (item == m_entries.at(i)) - return select_item(i); - } - return false; -} - -bool MenuScroller::attach_item(MenuItem* item) -{ - // _place_entries controls visibility, hide it until it's processed - item->set_visible(false); - m_entries.push_back(item); - m_dirty = true; - return true; -} - -/** - * Changes the bounds of the items that are to be visible - * preserves user set item heigth - * does not preserve width - */ -void MenuScroller::_place_items() -{ - m_dirty = false; - m_items_shown = 0; - - int item_height = 0; - int space_used = 0; - int one_past_last = 0; - const int space_available = m_max_coord.y - m_min_coord.y; - coord_def min_coord(0,0); - coord_def max_coord(0,0); - - // Hide all the items - for (MenuItem *item : m_entries) - { - item->set_visible(false); - item->allow_highlight(false); - } - - // calculate how many entries we can fit - for (one_past_last = m_topmost_visible; - one_past_last < static_cast (m_entries.size()); - ++one_past_last) - { - space_used += m_entries.at(one_past_last)->get_max_coord().y - - m_entries.at(one_past_last)->get_min_coord().y; - if (space_used > space_available) - { - if (m_currently_active < 0) - break; // all space allocated - if (one_past_last > m_currently_active) - break; // we included our active one, ok! - else - { - // active one didn't fit, chop the first one and run the loop - // again - ++m_topmost_visible; - one_past_last = m_topmost_visible - 1; - space_used = 0; - continue; - } - } - } - - space_used = 0; - int work_index = 0; - - for (work_index = m_topmost_visible; work_index < one_past_last; - ++work_index) - { - min_coord = m_entries.at(work_index)->get_min_coord(); - max_coord = m_entries.at(work_index)->get_max_coord(); - item_height = max_coord.y - min_coord.y; - - min_coord.y = m_min_coord.y + space_used; - max_coord.y = min_coord.y + item_height; - min_coord.x = m_min_coord.x; - max_coord.x = m_max_coord.x; -#ifdef USE_TILE_LOCAL - // reserve one tile space for scrollbar - max_coord.x -= 32; -#endif - m_entries.at(work_index)->set_bounds_no_multiply(min_coord, max_coord); - m_entries.at(work_index)->set_visible(true); - m_entries.at(work_index)->allow_highlight(true); - space_used += item_height; - ++m_items_shown; - } - -#ifdef USE_TILE_LOCAL - // arrows - m_arrow_down->set_bounds_no_multiply(coord_def(m_max_coord.x-32,m_max_coord.y-32),coord_def(m_max_coord.x,m_max_coord.y)); - m_arrow_down->set_visible(m_topmost_visible + m_items_shown < (int)m_entries.size()); - - m_arrow_up->set_bounds_no_multiply(coord_def(m_max_coord.x-32,m_min_coord.y),coord_def(m_max_coord.x,m_min_coord.y+32)); - m_arrow_up->set_visible(m_topmost_visible>0); -#endif -} - -MenuItem* MenuScroller::_find_item_by_direction(int start_index, - MenuObject::Direction dir) -{ - MenuItem* find_item = nullptr; - switch (dir) - { - case UP: - if ((start_index - 1) >= 0) - find_item = m_entries.at(start_index - 1); - break; - case DOWN: - if ((start_index + 1) < static_cast (m_entries.size())) - find_item = m_entries.at(start_index + 1); - break; - default: - break; - } - return find_item; -} - -MenuDescriptor::MenuDescriptor(PrecisionMenu* parent): m_parent(parent), - m_active_item(nullptr), override_text("") -{ - ASSERT(m_parent != nullptr); -} - -MenuDescriptor::~MenuDescriptor() -{ -} - -vector MenuDescriptor::get_selected_items() -{ - vector ret_val; - return ret_val; -} - -void MenuDescriptor::init(const coord_def& min_coord, const coord_def& max_coord, - const string& name) -{ - MenuObject::init(min_coord, max_coord, name); - m_desc_item.set_bounds(min_coord, max_coord); - m_desc_item.set_fg_colour(WHITE); - m_desc_item.set_visible(true); -} - -MenuObject::InputReturnValue MenuDescriptor::process_input(int key) -{ - // just in case we somehow end up processing input of this item - return MenuObject::INPUT_NO_ACTION; -} - -#ifdef USE_TILE_LOCAL -MenuObject::InputReturnValue MenuDescriptor::handle_mouse(const MouseEvent &me) -{ - if (me.event == MouseEvent::PRESS && me.button == MouseEvent::RIGHT) - return INPUT_END_MENU_ABORT; - // we have nothing interesting to do on mouse events because render() - // always checks if the active has changed override for things like - // tooltips - return INPUT_NO_ACTION; -} -#endif - -void MenuDescriptor::render() -{ - if (!m_visible) - return; - - _place_items(); - - m_desc_item.render(); -} - -/** - * This allows an arbitrary string to show up in the descriptor, temporarily - * overriding whatever is there. The override will last until the descriptor - * next changes. Empty strings are not used. - * - * @param t a string to show in the MenuDescriptor. The empty string will clear - * any existing override. - */ -void MenuDescriptor::override_description(const string &t) -{ - override_text = t; - render(); -} - - -void MenuDescriptor::_place_items() -{ - MenuItem* tmp = m_parent->get_active_item(); - if (tmp != m_active_item) - { - // the active item has changed -- update - m_active_item = tmp; - override_text = ""; -#ifndef USE_TILE_LOCAL - textcolour(BLACK); - textbackground(BLACK); - for (int i = 0; i < m_desc_item.get_max_coord().y - - m_desc_item.get_min_coord().y; ++i) - { - cgotoxy(m_desc_item.get_min_coord().x, - m_desc_item.get_min_coord().y + i); - clear_to_end_of_line(); - } - textcolour(LIGHTGRAY); -#endif - - if (tmp == nullptr) - m_desc_item.set_text(""); - else - m_desc_item.set_text(m_active_item->get_description_text()); - } - else if (override_text.size() > 0) - m_desc_item.set_text(override_text); -} - BoxMenuHighlighter::BoxMenuHighlighter(PrecisionMenu *parent): m_parent(parent), m_active_item(nullptr) { @@ -4780,62 +4108,3 @@ void BoxMenuHighlighter::_place_items() #endif m_active_item = tmp; } - -BlackWhiteHighlighter::BlackWhiteHighlighter(PrecisionMenu* parent): - BoxMenuHighlighter(parent) -{ - ASSERT(m_parent != nullptr); -} - -BlackWhiteHighlighter::~BlackWhiteHighlighter() -{ -} - -void BlackWhiteHighlighter::render() -{ - if (!m_visible) - return; - - _place_items(); - - if (m_active_item != nullptr) - { -#ifdef USE_TILE_LOCAL - m_shape_buf.draw(); -#endif - m_active_item->render(); - } -} - -void BlackWhiteHighlighter::_place_items() -{ - MenuItem* tmp = m_parent->get_active_item(); - if (tmp == m_active_item) - return; - -#ifdef USE_TILE_LOCAL - m_shape_buf.clear(); -#endif - // we had an active item before - if (m_active_item != nullptr) - { - // clear the highlight trickery - m_active_item->set_fg_colour(m_old_fg_colour); - m_active_item->set_bg_colour(m_old_bg_colour); - // redraw the old item - m_active_item->render(); - } - if (tmp != nullptr) - { -#ifdef USE_TILE_LOCAL - m_shape_buf.add(tmp->get_min_coord().x, tmp->get_min_coord().y, - tmp->get_max_coord().x, tmp->get_max_coord().y, - term_colours[LIGHTGRAY]); -#endif - m_old_bg_colour = tmp->get_bg_colour(); - m_old_fg_colour = tmp->get_fg_colour(); - tmp->set_bg_colour(LIGHTGRAY); - tmp->set_fg_colour(BLACK); - } - m_active_item = tmp; -} diff --git a/crawl-ref/source/menu.h b/crawl-ref/source/menu.h index b82eddcc8ba0..fb006dac0051 100644 --- a/crawl-ref/source/menu.h +++ b/crawl-ref/source/menu.h @@ -707,27 +707,6 @@ class TextTileItem : public TextItem vector m_tiles; FixedVector m_tile_buf; }; - -/** - * Specialization of TextTileItem that knows how to pack a player doll - * TODO: reform _pack_doll() since it currently holds duplicate code from - * tilereg.cc pack_doll_buf() - */ -class SaveMenuItem : public TextTileItem -{ -public: - friend class TilesFramework; - SaveMenuItem(); - virtual ~SaveMenuItem(); - - virtual void render() override; - - void set_doll(dolls_data doll); - -protected: - void _pack_doll(); - dolls_data m_save_doll; -}; #endif class PrecisionMenu; @@ -865,137 +844,6 @@ class MenuFreeform : public MenuObject MenuItem* m_default_item; }; -/** - * Container that can hold any number of objects in a scroll list style. - * Only certain number of items are visible at the same time. - * Navigating the list works with ARROW_UP and ARROW_DOWN keys. - * Eventually it should also support scrollbars. - */ -class MenuScroller : public MenuObject -{ -public: - MenuScroller(); - virtual ~MenuScroller(); - - virtual InputReturnValue process_input(int key) override; -#ifdef USE_TILE_LOCAL - virtual InputReturnValue handle_mouse(const MouseEvent& me) override; -#endif - virtual void render() override; - virtual MenuItem* get_active_item() override; - virtual void set_active_item(int ID) override; - virtual void set_active_item(MenuItem* item) override; - virtual void activate_first_item() override; - virtual void activate_last_item() override; - - virtual bool select_item(int index) override; - virtual bool select_item(MenuItem* item) override; - virtual bool attach_item(MenuItem* item) override; -protected: - virtual void _place_items() override; - virtual void _set_active_item_by_index(int index); - virtual MenuItem* _find_item_by_direction(int start_index, - MenuObject::Direction dir); - virtual MenuItem* _find_item_by_direction( - const MenuItem* start, MenuObject::Direction dir) override - { - return nullptr; - } - - int m_topmost_visible; - int m_currently_active; - int m_items_shown; - -#ifdef USE_TILE_LOCAL - TextTileItem *m_arrow_up; - TextTileItem *m_arrow_down; -#endif -}; - -/** - * Base class for various descriptor and highlighter objects. - * These should probably be attached last to the menu to be rendered last. - */ -class MenuDescriptor : public MenuObject -{ -public: - MenuDescriptor(PrecisionMenu* parent); - virtual ~MenuDescriptor(); - - void init(const coord_def& min_coord, const coord_def& max_coord, - const string& name); - - virtual InputReturnValue process_input(int key) override; -#ifdef USE_TILE_LOCAL - virtual InputReturnValue handle_mouse(const MouseEvent& me) override; -#endif - virtual void render() override; - - // these are not used, clear them - virtual vector get_selected_items() override; - virtual MenuItem* get_active_item() override { return nullptr; } - virtual bool attach_item(MenuItem* item) override { return false; } - virtual void set_active_item(int index) override {} - virtual void set_active_item(MenuItem* item) override {} - virtual void activate_first_item() override {} - virtual void activate_last_item() override {} - - virtual bool select_item(int index) override { return false; } - virtual bool select_item(MenuItem* item) override { return false;} - virtual MenuItem* select_item_by_hotkey(int key) override - { - return nullptr; - } - virtual void clear_selections() override {} - - // Do not allow focus - virtual void allow_focus(bool toggle) override {} - virtual bool can_be_focused() override { return false; } - - void override_description(const string &t); - -protected: - virtual void _place_items() override; - virtual MenuItem* _find_item_by_mouse_coords(const coord_def& pos) override - { - return nullptr; - } - virtual MenuItem* _find_item_by_direction( - const MenuItem* start, MenuObject::Direction dir) override - { - return nullptr; - } - - // Used to pull out currently active item - PrecisionMenu* m_parent; - MenuItem* m_active_item; - NoSelectTextItem m_desc_item; - string override_text; -}; - -/** - * Class for mouse over tooltips, does nothing if USE_TILE_LOCAL is not defined - * TODO: actually implement render() and _place_items() - */ -class MenuTooltip : public MenuDescriptor -{ -public: - MenuTooltip(PrecisionMenu* parent); - virtual ~MenuTooltip(); - -#ifdef USE_TILE_LOCAL - virtual InputReturnValue handle_mouse(const MouseEvent& me) override; -#endif - virtual void render() override; -protected: - virtual void _place_items() override; - -#ifdef USE_TILE_LOCAL - ShapeBuffer m_background; - FontBuffer m_font_buf; -#endif -}; - /** * Highlighter object. * TILES: It will create a colored rectangle around the currently active item. @@ -1059,24 +907,6 @@ class BoxMenuHighlighter : public MenuObject #endif }; -class BlackWhiteHighlighter : public BoxMenuHighlighter -{ -public: - BlackWhiteHighlighter(PrecisionMenu* parent); - virtual ~BlackWhiteHighlighter(); - - virtual void render() override; -protected: - virtual void _place_items() override; - -#ifdef USE_TILE_LOCAL - // Tiles does not seem to support background colors - ShapeBuffer m_shape_buf; -#endif - COLOURS m_old_bg_colour; - COLOURS m_old_fg_colour; -}; - /** * Inheritable root node of a menu that holds MenuObjects. * It is always full screen. From 1fcc531f06e7f23d45bbd8e4764700dac503a615 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Fri, 27 Sep 2019 02:48:05 +0800 Subject: [PATCH 686/864] Refactor MenuFreeform methods with find_if() --- crawl-ref/source/menu.cc | 68 ++++++++++------------------------------ crawl-ref/source/menu.h | 2 +- 2 files changed, 18 insertions(+), 52 deletions(-) diff --git a/crawl-ref/source/menu.cc b/crawl-ref/source/menu.cc index 9283ddf62e4e..257bdb2acbe7 100644 --- a/crawl-ref/source/menu.cc +++ b/crawl-ref/source/menu.cc @@ -3709,7 +3709,7 @@ MenuObject::InputReturnValue MenuFreeform::handle_mouse(const MouseEvent& me) { if (m_active_item != nullptr) { - _set_active_item_by_index(-1); + _set_active_item(nullptr); return INPUT_FOCUS_LOST; } else @@ -3726,7 +3726,7 @@ MenuObject::InputReturnValue MenuFreeform::handle_mouse(const MouseEvent& me) { if (m_active_item != nullptr) { - _set_active_item_by_index(-1); + _set_active_item(nullptr); return INPUT_NO_ACTION; } } @@ -3787,21 +3787,14 @@ MenuItem* MenuFreeform::get_active_item() return m_active_item; } -// Predicate for std::find_if -static bool _id_comparison(MenuItem* item, int ID) -{ - return item->get_id() == ID; -} - /** * Sets item by ID * Clears active item if ID not found */ -void MenuFreeform ::set_active_item(int ID) +void MenuFreeform::set_active_item(int ID) { auto it = find_if(m_entries.begin(), m_entries.end(), - bind(_id_comparison, placeholders::_1, ID)); - + [=](const MenuItem* item) { return item->get_id() == ID; }); m_active_item = (it != m_entries.end()) ? *it : nullptr; m_dirty = true; } @@ -3810,61 +3803,34 @@ void MenuFreeform ::set_active_item(int ID) * Sets active item based on index * This function is for internal use if object does not have ID set */ -void MenuFreeform::_set_active_item_by_index(int index) +void MenuFreeform::_set_active_item(MenuItem* item) { - if (index >= 0 && index < static_cast (m_entries.size())) - { - if (m_entries.at(index)->can_be_highlighted()) - { - m_active_item = m_entries.at(index); - m_dirty = true; - return; - } - } - // Clear active selection - m_active_item = nullptr; + ASSERT(!item || item->can_be_highlighted()); + m_active_item = item; m_dirty = true; } void MenuFreeform::set_active_item(MenuItem* item) { - // Does item exist in the menu? - auto it = find(m_entries.begin(), m_entries.end(), item); - m_active_item = (it != end(m_entries) && item->can_be_highlighted()) - ? item : nullptr; + bool present = find(m_entries.begin(), m_entries.end(), item) != m_entries.end(); + m_active_item = (present && item->can_be_highlighted()) ? item : nullptr; m_dirty = true; } void MenuFreeform::activate_first_item() { - if (!m_entries.empty()) - { - // find the first activeable item - for (int i = 0; i < static_cast (m_entries.size()); ++i) - { - if (m_entries.at(i)->can_be_highlighted()) - { - _set_active_item_by_index(i); - break; // escape loop - } - } - } + auto el = find_if(m_entries.begin(), m_entries.end(), + [=](const MenuItem* item) { return item->can_be_highlighted(); }); + if (el != m_entries.end()) + _set_active_item(*el); } void MenuFreeform::activate_last_item() { - if (!m_entries.empty()) - { - // find the last activeable item - for (int i = m_entries.size() -1; i >= 0; --i) - { - if (m_entries.at(i)->can_be_highlighted()) - { - _set_active_item_by_index(i); - break; // escape loop - } - } - } + auto el = find_if(m_entries.rbegin(), m_entries.rend(), + [=](const MenuItem* item) { return item->can_be_highlighted(); }); + if (el != m_entries.rend()) + _set_active_item(*el); } bool MenuFreeform::select_item(int index) diff --git a/crawl-ref/source/menu.h b/crawl-ref/source/menu.h index fb006dac0051..500127b47a3c 100644 --- a/crawl-ref/source/menu.h +++ b/crawl-ref/source/menu.h @@ -835,7 +835,7 @@ class MenuFreeform : public MenuObject protected: virtual void _place_items() override; - virtual void _set_active_item_by_index(int index); + virtual void _set_active_item(MenuItem *item); virtual MenuItem* _find_item_by_direction( const MenuItem* start, MenuObject::Direction dir) override; From 17bb1006d4bcbabf22586ef7bc83287b23406b99 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Fri, 27 Sep 2019 19:26:39 +0800 Subject: [PATCH 687/864] Refactor identical colourpair remapping code --- crawl-ref/source/libunix.cc | 114 +++++++++++++++++------------------- 1 file changed, 54 insertions(+), 60 deletions(-) diff --git a/crawl-ref/source/libunix.cc b/crawl-ref/source/libunix.cc index fc4f5ae21697..ecc9f38959f2 100644 --- a/crawl-ref/source/libunix.cc +++ b/crawl-ref/source/libunix.cc @@ -1135,9 +1135,6 @@ static bool curs_color_combo_has_pair(short fg, short bg) static void curs_adjust_color_pair_to_non_identical(short &fg, short &bg, bool adjust_background) { - // The color to assign. - short non_conflicting_color = adjust_background ? bg : fg; - // The default colors. short fg_default = translate_colour(FG_COL_DEFAULT); short bg_default = translate_colour(BG_COL_DEFAULT); @@ -1164,76 +1161,73 @@ static void curs_adjust_color_pair_to_non_identical(short &fg, short &bg, } } - // Got the adjusted colors -- resolve any conflict. - if (fg_to_compare == bg_to_compare) - { - // Choose terminal's current default colors as the default failsafe. - short failsafe_col = adjust_background ? fg_default : bg_default; + if (fg_to_compare != bg_to_compare) + return; // colours look different; no need to adjust - if (!adjust_background && fg_to_compare == bg_default_to_compare) + // Choose terminal's current default colors as the default failsafe. + short failsafe_col = adjust_background ? fg_default : bg_default; + + if (!adjust_background && fg_to_compare == bg_default_to_compare) + { + /* + * Replacing the *foreground* color with a secondary failsafe. + * + * In general, use black as a failsafe for non-black backgrounds + * and white as a failsafe for black backgrounds. Black tends to + * look good on any visible background. + * + * However, for black and white *default* background colours, + * mitigate information contrast issues with bright black + * foregrounds by using blue as a special-case failsafe color. + */ + switch (bg_default_to_compare) { - /* - * Replacing the *foreground* color with a secondary failsafe. - * - * In general, use black as a failsafe for non-black backgrounds - * and white as a failsafe for black backgrounds. Black tends to - * look good on any visible background. - * - * However, for black and white *default* background colours, - * mitigate information contrast issues with bright black - * foregrounds by using blue as a special-case failsafe color. - */ - switch (bg_default_to_compare) + case COLOR_BLACK: + if (fg_default_to_compare == COLOR_WHITE + || fg_default_to_compare == COLOR_BLACK) { - case COLOR_BLACK: - if (fg_default_to_compare == COLOR_WHITE - || fg_default_to_compare == COLOR_BLACK) - { - failsafe_col = COLOR_BLUE; - } - else - failsafe_col = COLOR_WHITE; - break; - case COLOR_WHITE: - if (fg_default_to_compare == COLOR_WHITE - || fg_default_to_compare == COLOR_BLACK) - { - failsafe_col = COLOR_BLUE; - } - else - failsafe_col = COLOR_BLACK; - break; - default: - failsafe_col = COLOR_BLACK; - break; + failsafe_col = COLOR_BLUE; } - } - else if (adjust_background && bg_to_compare == fg_default_to_compare) - { - /* - * Replacing the *background* color with a secondary failsafe. - * - * Don't bother special-casing bright black: - * - The information contrast issue is not as prevalent for - * backgrounds as foregrounds. - * - A visible bright-black-on-black glyph actively changing into - * black-on-blue when reversed looks much worse than a change to - * black-on-white. - */ - if (fg_default_to_compare == COLOR_BLACK) + else failsafe_col = COLOR_WHITE; + break; + case COLOR_WHITE: + if (fg_default_to_compare == COLOR_WHITE + || fg_default_to_compare == COLOR_BLACK) + { + failsafe_col = COLOR_BLUE; + } else failsafe_col = COLOR_BLACK; + break; + default: + failsafe_col = COLOR_BLACK; + break; } - - non_conflicting_color = failsafe_col; + } + else if (adjust_background && bg_to_compare == fg_default_to_compare) + { + /* + * Replacing the *background* color with a secondary failsafe. + * + * Don't bother special-casing bright black: + * - The information contrast issue is not as prevalent for + * backgrounds as foregrounds. + * - A visible bright-black-on-black glyph actively changing into + * black-on-blue when reversed looks much worse than a change to + * black-on-white. + */ + if (fg_default_to_compare == COLOR_BLACK) + failsafe_col = COLOR_WHITE; + else + failsafe_col = COLOR_BLACK; } // Update the appropriate color in the pair. if (adjust_background) - bg = non_conflicting_color; + bg = failsafe_col; else - fg = non_conflicting_color; + fg = failsafe_col; } // see declaration From db4295c90eb7bd6fec6a1a224023c38eb242f213 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Fri, 27 Sep 2019 20:44:20 +0800 Subject: [PATCH 688/864] Fix broken win32 console text colouring API Crawl code assumes that the terminal text and background colours can be updated independently; the win32 console backend, however, was setting the background colour from the high bits of the provided text colour. This resulted in a textcolour() call followed by a textbackground() call to function normally, but the reverse would not. --- crawl-ref/source/libw32c.cc | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/crawl-ref/source/libw32c.cc b/crawl-ref/source/libw32c.cc index f5ff5c5b712f..73952c0f17d5 100644 --- a/crawl-ref/source/libw32c.cc +++ b/crawl-ref/source/libw32c.cc @@ -122,6 +122,12 @@ static DWORD crawlColorData[16] = }; */ +/** @brief The current foreground @em colour. */ +static COLOURS FG_COL = LIGHTGREY; + +/** @brief The current background @em colour. */ +static COLOURS BG_COL = BLACK; + void writeChar(char32_t c) { if (c == '\t') @@ -553,25 +559,23 @@ void gotoxy_sys(int x, int y) } } -void textcolour(int c) +static void update_text_colours() { - // change current colour used to stamp chars - short fg = c & 0xF; - short bg = (c >> 4) & 0xF; - short macro_fg = Options.colour[fg]; - short macro_bg = Options.colour[bg]; + short macro_fg = Options.colour[FG_COL]; + short macro_bg = Options.colour[BG_COL]; + current_colour = (macro_bg << 4) | macro_fg; +} - current_colour = macro_fg | (macro_bg << 4); +void textcolour(int c) +{ + FG_COL = static_cast(c & 0xF); + update_text_colours(); } void textbackground(int c) { - // change current background colour used to stamp chars - // parameter does NOT come bitshifted by four - short bg = c & 0xF; - short macro_bg = Options.colour[bg]; - - current_colour = current_colour | (macro_bg << 4); + BG_COL = static_cast(c & 0xF); + update_text_colours(); } static void cprintf_aux(const char *s) From 40b4c6130089b08bb32c9d453dad5093658186d3 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Fri, 27 Sep 2019 20:49:59 +0800 Subject: [PATCH 689/864] Add rudimentary win32 console colour adjustment libunix.cc will adjust the foreground colour when both foreground and background are indistinguishable. This commit ports a much-reduced version of that functionality to win32 console, primarily so that the main menu will be readable. --- crawl-ref/source/libw32c.cc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/crawl-ref/source/libw32c.cc b/crawl-ref/source/libw32c.cc index 73952c0f17d5..2ea387b55a4c 100644 --- a/crawl-ref/source/libw32c.cc +++ b/crawl-ref/source/libw32c.cc @@ -128,6 +128,9 @@ static COLOURS FG_COL = LIGHTGREY; /** @brief The current background @em colour. */ static COLOURS BG_COL = BLACK; +/** @brief The default background @em colour. */ +static COLOURS BG_COL_DEFAULT = BLACK; + void writeChar(char32_t c) { if (c == '\t') @@ -559,10 +562,21 @@ void gotoxy_sys(int x, int y) } } +// Hacked-up version of corresponding function in libunix.cc +static void adjust_color_pair_to_non_identical(short &fg, short &bg) +{ + // ignore brighness when comparing visually + if ((fg & ~COLFLAG_CURSES_BRIGHTEN) != bg) + return; // colours look different; no need to adjust + fg &= ~COLFLAG_CURSES_BRIGHTEN; + fg = fg == BG_COL_DEFAULT ? WHITE : BG_COL_DEFAULT;; +} + static void update_text_colours() { short macro_fg = Options.colour[FG_COL]; short macro_bg = Options.colour[BG_COL]; + adjust_color_pair_to_non_identical(macro_fg, macro_bg); current_colour = (macro_bg << 4) | macro_fg; } From 39a19ac0f18e8e0a5043e9525be0d49292617049 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Fri, 27 Sep 2019 22:45:37 +0800 Subject: [PATCH 690/864] Remove unused smart cursor interface This also fixes a bug on win32 console where the mouse cursor was visible on the main menu. --- crawl-ref/source/cio.h | 5 +---- crawl-ref/source/hiscores.cc | 5 ----- crawl-ref/source/libconsole.h | 2 -- crawl-ref/source/libgui.cc | 9 --------- crawl-ref/source/libunix.cc | 9 --------- crawl-ref/source/libw32c.cc | 32 ++++---------------------------- 6 files changed, 5 insertions(+), 57 deletions(-) diff --git a/crawl-ref/source/cio.h b/crawl-ref/source/cio.h index 34eeae010291..d241c4b79b13 100644 --- a/crawl-ref/source/cio.h +++ b/crawl-ref/source/cio.h @@ -224,19 +224,16 @@ class cursor_control { public: cursor_control(bool cursor_enabled) - : cstate(is_cursor_enabled()), smartcstate(is_smart_cursor_enabled()) + : cstate(is_cursor_enabled()) { - enable_smart_cursor(false); set_cursor_enabled(cursor_enabled); } ~cursor_control() { set_cursor_enabled(cstate); - enable_smart_cursor(smartcstate); } private: bool cstate; - bool smartcstate; }; enum edit_mode diff --git a/crawl-ref/source/hiscores.cc b/crawl-ref/source/hiscores.cc index 52af29c14a45..f9876a1fc287 100644 --- a/crawl-ref/source/hiscores.cc +++ b/crawl-ref/source/hiscores.cc @@ -516,14 +516,9 @@ bool UIHiscoresMenu::on_event(const wm_event& ev) void show_hiscore_table() { unwind_var sprintmap(crawl_state.map, crawl_state.sprint_map); - bool smart_cursor_enabled = is_smart_cursor_enabled(); - auto hiscore_ui = make_shared(); auto popup = make_shared(hiscore_ui); ui::run_layout(move(popup), hiscore_ui->done); - - // Go back to the menu and return the smart cursor to its previous state - enable_smart_cursor(smart_cursor_enabled); } // Trying to supply an appropriate verb for the attack type. -- bwr diff --git a/crawl-ref/source/libconsole.h b/crawl-ref/source/libconsole.h index 61578301ec76..137658a2f792 100644 --- a/crawl-ref/source/libconsole.h +++ b/crawl-ref/source/libconsole.h @@ -31,8 +31,6 @@ void update_screen(); void set_cursor_enabled(bool enabled); bool is_cursor_enabled(); -void enable_smart_cursor(bool cursor); -bool is_smart_cursor_enabled(); void set_mouse_enabled(bool enabled); static inline void put_colour_ch(int colour, unsigned ch) diff --git a/crawl-ref/source/libgui.cc b/crawl-ref/source/libgui.cc index a7cdfb8fbfb0..f51f0a81cbcc 100644 --- a/crawl-ref/source/libgui.cc +++ b/crawl-ref/source/libgui.cc @@ -113,15 +113,6 @@ bool is_cursor_enabled() return false; } -bool is_smart_cursor_enabled() -{ - return false; -} - -void enable_smart_cursor(bool /*cursor*/) -{ -} - int wherex() { return TextRegion::wherex(); diff --git a/crawl-ref/source/libunix.cc b/crawl-ref/source/libunix.cc index ecc9f38959f2..97c99f42262b 100644 --- a/crawl-ref/source/libunix.cc +++ b/crawl-ref/source/libunix.cc @@ -884,15 +884,6 @@ bool is_cursor_enabled() return cursor_is_enabled; } -bool is_smart_cursor_enabled() -{ - return false; -} - -void enable_smart_cursor(bool /*cursor*/) -{ -} - static inline unsigned get_brand(int col) { return (col & COLFLAG_FRIENDLY_MONSTER) ? Options.friend_brand : diff --git a/crawl-ref/source/libw32c.cc b/crawl-ref/source/libw32c.cc index 2ea387b55a4c..3d2023834a80 100644 --- a/crawl-ref/source/libw32c.cc +++ b/crawl-ref/source/libw32c.cc @@ -90,13 +90,10 @@ static COORD screensize; static unsigned InputCP, OutputCP; static const unsigned PREFERRED_CODEPAGE = 437; -static bool w32_smart_cursor = true; - // we can do straight translation of DOS colour to win32 console colour. #define WIN32COLOR(col) (WORD)(col) static void writeChar(char32_t c); static void bFlush(); -static void _setcursortype_internal(bool curstype); // [ds] Unused for portability reasons /* @@ -190,16 +187,6 @@ void writeChar(char32_t c) cx = screensize.X - 1; } -void enable_smart_cursor(bool cursor) -{ - w32_smart_cursor = cursor; -} - -bool is_smart_cursor_enabled() -{ - return w32_smart_cursor; -} - void bFlush() { COORD source; @@ -402,8 +389,8 @@ void console_startup() // initialise text colour textcolour(DARKGREY); - // initialise cursor to NONE. - _setcursortype_internal(false); + cursor_is_enabled = true; // ensure cursor is set regardless of actual state + set_cursor_enabled(false); crawl_state.terminal_resize_handler = w32_term_resizer; crawl_state.terminal_resize_check = w32_check_screen_resize; @@ -441,7 +428,7 @@ void console_shutdown() _set_string_input(true); // set cursor and normal textcolour - _setcursortype_internal(true); + set_cursor_enabled(true); textcolour(DARKGREY); inbuf = nullptr; @@ -463,18 +450,12 @@ void console_shutdown() } } -void set_cursor_enabled(bool enabled) -{ - if (!w32_smart_cursor) - _setcursortype_internal(enabled); -} - bool is_cursor_enabled() { return cursor_is_enabled; } -static void _setcursortype_internal(bool curstype) +void set_cursor_enabled(bool curstype) { CONSOLE_CURSOR_INFO cci; @@ -812,8 +793,6 @@ int getch_ck() } const bool oldValue = cursor_is_enabled; - if (w32_smart_cursor) - _setcursortype_internal(true); bool waiting_for_event = true; while (waiting_for_event) @@ -858,9 +837,6 @@ int getch_ck() } } - if (w32_smart_cursor) - _setcursortype_internal(oldValue); - return key; } From bbc889713799746a40393f7d7dc93f8a1a3e3eb2 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 28 Sep 2019 03:10:14 +0800 Subject: [PATCH 691/864] More dead code removal --- crawl-ref/source/command.cc | 37 +------------------------------------ crawl-ref/source/command.h | 3 +-- 2 files changed, 2 insertions(+), 38 deletions(-) diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc index c1bd2a5ed64b..69e5008e8e7d 100644 --- a/crawl-ref/source/command.cc +++ b/crawl-ref/source/command.cc @@ -503,44 +503,9 @@ static void _handle_FAQ() return; } -/////////////////////////////////////////////////////////////////////////// -// Manual menu highlighter. - -class help_highlighter : public MenuHighlighter -{ -public: - help_highlighter(string = ""); - int entry_colour(const MenuEntry *entry) const override; -private: - text_pattern pattern; - string get_species_key() const; -}; - -help_highlighter::help_highlighter(string highlight_string) : - pattern(highlight_string.empty() ? get_species_key() : highlight_string) -{ -} - -int help_highlighter::entry_colour(const MenuEntry *entry) const -{ - return !pattern.empty() && pattern.matches(entry->text) ? WHITE : -1; -} - -// To highlight species in aptitudes list. ('?%') -string help_highlighter::get_species_key() const -{ - string result = species_name(you.species); - // The table doesn't repeat the word "Draconian". - if (you.species != SP_BASE_DRACONIAN && species_is_draconian(you.species)) - strip_tag(result, "Draconian"); - - result += " "; - return result; -} //////////////////////////////////////////////////////////////////////////// -int show_keyhelp_menu(const vector &lines, - int hotkey, string highlight_string) +int show_keyhelp_menu(const vector &lines) { int flags = FS_PREWRAPPED_TEXT | FS_EASY_EXIT; formatted_scroller cmd_help(flags); diff --git a/crawl-ref/source/command.h b/crawl-ref/source/command.h index f5147b6a625b..c858157a44e0 100644 --- a/crawl-ref/source/command.h +++ b/crawl-ref/source/command.h @@ -29,8 +29,7 @@ void show_spell_library_help(); void show_help(int section = CK_HOME, string highlight_string = ""); -int show_keyhelp_menu(const vector &lines, - int hotkey = 0, string highlight_string = ""); +int show_keyhelp_menu(const vector &lines); // XXX: Actually defined in main.cc; we may want to move this to command.cc. void process_command(command_type cmd); From 53c33f0441d64df96e7638634e11b3316194aa97 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 28 Sep 2019 14:04:42 +0800 Subject: [PATCH 692/864] Fix webtiles newgame menu background colour --- crawl-ref/source/webserver/game_data/static/style.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/webserver/game_data/static/style.css b/crawl-ref/source/webserver/game_data/static/style.css index f80d62e258f6..df584e393541 100644 --- a/crawl-ref/source/webserver/game_data/static/style.css +++ b/crawl-ref/source/webserver/game_data/static/style.css @@ -1079,7 +1079,7 @@ body { } .newgame-choice .grid .button { - background: black; + background: #040204; white-space: pre; padding: 1px; border: 1px solid rgba(255, 255, 255, 0.001); From d18775d16a6a1777a66fddcb0f22e0709b1e6bf6 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 28 Sep 2019 14:05:04 +0800 Subject: [PATCH 693/864] Reduce webtiles newgame menu height (12074, kitchen_ace) This attempts to fit the entire menu in without needing to scroll; it only takes effect on windows less than 780px high though. --- .../source/webserver/game_data/static/style.css | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/crawl-ref/source/webserver/game_data/static/style.css b/crawl-ref/source/webserver/game_data/static/style.css index df584e393541..9c5ccf33554e 100644 --- a/crawl-ref/source/webserver/game_data/static/style.css +++ b/crawl-ref/source/webserver/game_data/static/style.css @@ -1085,6 +1085,19 @@ body { border: 1px solid rgba(255, 255, 255, 0.001); } +@media screen and (max-height: 780px) { + .newgame-choice .grid .button canvas { + margin: -1px 0; + } + .ui-popup-outer { + margin: 20px; + max-height: calc(100vh - 40px); + } + .ui-popup-inner { + max-height: calc(100vh - 40px - 46px); + } +} + .newgame-choice .grid .button.selected { background: black; From 8e49684493dd1e23c8c1895dc7ea41949897b6d1 Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 28 Sep 2019 12:13:11 -0400 Subject: [PATCH 694/864] Use MenuButton highlight color in local console This does not fix 12076; I think the dynamic_cast is not working at all for webtiles console. --- crawl-ref/source/outer-menu.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/outer-menu.cc b/crawl-ref/source/outer-menu.cc index 11e4069ba34f..ca9fec0f3221 100644 --- a/crawl-ref/source/outer-menu.cc +++ b/crawl-ref/source/outer-menu.cc @@ -245,7 +245,10 @@ void OuterMenu::add_button(shared_ptr btn, int x, int y) { auto btn2 = this->m_buttons[y*this->m_width+x]; if (auto tw = dynamic_cast(btn2->get_child().get())) - tw->set_bg_colour(ev.type == WME_FOCUSIN ? LIGHTGREY : BLACK); + { + tw->set_bg_colour(ev.type == WME_FOCUSIN + ? btn2->highlight_colour : BLACK); + } } #endif return false; From 60d090ba07fcda14107de89f700314220a8d6c13 Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 28 Sep 2019 13:10:22 -0400 Subject: [PATCH 695/864] Fix a shadowed variable warning in webtiles --- crawl-ref/source/tileweb.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/tileweb.cc b/crawl-ref/source/tileweb.cc index 4be36b68686a..499555cc254d 100644 --- a/crawl-ref/source/tileweb.cc +++ b/crawl-ref/source/tileweb.cc @@ -1758,9 +1758,9 @@ void TilesFramework::load_dungeon(const crawl_view_buffer &vbuf, for (int y = 0; y < GYM; y++) for (int x = 0; x < GXM; x++) { - const coord_def gc(x, y); - screen_cell_t *cell = &m_next_view(gc); - cell->tile.map_knowledge = map_bounds(gc) ? env.map_knowledge(gc) : map_cell(); + const coord_def cache_gc(x, y); + screen_cell_t *cell = &m_next_view(cache_gc); + cell->tile.map_knowledge = map_bounds(cache_gc) ? env.map_knowledge(cache_gc) : map_cell(); } m_next_view_tl = view2grid(coord_def(1, 1)); From 5a66b1aa3b36288c156b74d8d8b76aeb32e7a712 Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 28 Sep 2019 17:09:28 -0400 Subject: [PATCH 696/864] Fix(ish) for menu highlighting issues in webtiles console The problem was that webtiles console, because it can be showing complex menu items via a browser client, has a different menu structure than regular console, so the assumption that it contained a single Text child was incorrect. This fairly hacky solution also tries setting the background color of any label in position 1 in case the button is a container. There should probably be something more general here, perhaps highlighting every Text contained in the button widget (Which would get both of the currently-used cases as special cases), but I'll leave that for aidanh. --- crawl-ref/source/outer-menu.cc | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/crawl-ref/source/outer-menu.cc b/crawl-ref/source/outer-menu.cc index ca9fec0f3221..88bcfdd6a9a3 100644 --- a/crawl-ref/source/outer-menu.cc +++ b/crawl-ref/source/outer-menu.cc @@ -244,7 +244,22 @@ void OuterMenu::add_button(shared_ptr btn, int x, int y) if (ev.type == WME_FOCUSIN || ev.type == WME_FOCUSOUT) { auto btn2 = this->m_buttons[y*this->m_width+x]; +#ifdef USE_TILE_WEB + Text* tw = dynamic_cast(btn2->get_child().get()); + if (!tw) + { + // TODO: very hacky: the label might be in position 1 of a Box. + // is there a more elegant way of doing this? Maybe do it for + // every label in the widget? + auto tw_cont = dynamic_cast( + btn2->get_child().get()); + if (tw_cont && tw_cont->num_children() > 1) + tw = dynamic_cast((*tw_cont)[1].get()); + } + if (tw) +#else if (auto tw = dynamic_cast(btn2->get_child().get())) +#endif { tw->set_bg_colour(ev.type == WME_FOCUSIN ? btn2->highlight_colour : BLACK); From 7b85b324446eb60f827c4ef41274b48620f6a304 Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 28 Sep 2019 18:07:42 -0400 Subject: [PATCH 697/864] Slightly improve console MenuButton highlighting code This now handles another bug by generalizing slightly from 5a66b1aa3b36: the weapon selection menu wasn't highlighting correctly in local console because those buttons on console consist of a bin with two Texts. The new version finds the first Text child (if any) and does the highlighting on it, and because of this also does away with the #ifdefs. --- crawl-ref/source/outer-menu.cc | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/crawl-ref/source/outer-menu.cc b/crawl-ref/source/outer-menu.cc index 88bcfdd6a9a3..0ab58fab5897 100644 --- a/crawl-ref/source/outer-menu.cc +++ b/crawl-ref/source/outer-menu.cc @@ -244,22 +244,25 @@ void OuterMenu::add_button(shared_ptr btn, int x, int y) if (ev.type == WME_FOCUSIN || ev.type == WME_FOCUSOUT) { auto btn2 = this->m_buttons[y*this->m_width+x]; -#ifdef USE_TILE_WEB Text* tw = dynamic_cast(btn2->get_child().get()); if (!tw) { - // TODO: very hacky: the label might be in position 1 of a Box. - // is there a more elegant way of doing this? Maybe do it for - // every label in the widget? + // TODO: very hacky: if the child is a container, + // find the first label in a container. + // This handles several cases: webtiles menus on console, + // weapon select on local console. Is there a more elegant way + // of doing this? Maybe do it for every label in the widget? auto tw_cont = dynamic_cast( btn2->get_child().get()); - if (tw_cont && tw_cont->num_children() > 1) - tw = dynamic_cast((*tw_cont)[1].get()); + if (tw_cont) + for (auto it = tw_cont->begin(); it != tw_cont->end(); ++it) + { + tw = dynamic_cast((*it).get()); + if (tw) + break; + } } if (tw) -#else - if (auto tw = dynamic_cast(btn2->get_child().get())) -#endif { tw->set_bg_colour(ev.type == WME_FOCUSIN ? btn2->highlight_colour : BLACK); From 6234c29d7a08c1544ce91ab522567c66da721a50 Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 28 Sep 2019 18:27:05 -0400 Subject: [PATCH 698/864] Address an uninitialized variable This *might* be the windows crash, not sure. In any case, tileidx_t is uint64_t and so needs to be initialized to something. --- crawl-ref/source/newgame.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 6c9b0d33c1c4..2dff68cc34a1 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -1624,7 +1624,7 @@ static void _construct_weapon_menu(const newgame_def& ng, weapon_menu_item(skill_type _skill, string _label, tileidx_t _tile) : skill(move(_skill)), label(move(_label)), tile(move(_tile)) {}; weapon_menu_item(skill_type _skill, string _label) - : skill(move(_skill)), label(move(_label)) {}; + : skill(move(_skill)), label(move(_label)), tile(0) {}; }; vector choices; From aeb99fb3f2b467c414b025b8fb6b548d431191b7 Mon Sep 17 00:00:00 2001 From: advil Date: Sat, 28 Sep 2019 18:41:54 -0400 Subject: [PATCH 699/864] Fix another webtiles console menu glitch These values were being interpreted as characters when rendering console, and are apparently unused for webtiles browser. So, just set them to 0. --- crawl-ref/source/newgame.cc | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 2dff68cc34a1..c95897315487 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -1713,10 +1713,22 @@ static void _construct_weapon_menu(const newgame_def& ng, tile_def(TILE_MI_THROWING_NET, TEX_DEFAULT))); } if (choice.skill == SK_UNARMED_COMBAT) - tile_stack->min_size() = { TILE_Y, TILE_Y }; + { + tile_stack->min_size() = +#ifdef USE_TILE_WEB + // these dimensions are apparently unused for + // webtiles, we do this so they're not interpreted + // as characters for webtiles console. + { 0,0 }; +#else + { TILE_Y, TILE_Y }; +#endif + } else + { tile_stack->add_child(make_shared( tile_def(choice.tile, TEX_DEFAULT))); + } #endif auto label = make_shared(); From d2de06d31dec79aec87c83e8190145f21aaeee59 Mon Sep 17 00:00:00 2001 From: Kyle Rawlins Date: Sun, 29 Sep 2019 09:20:59 -0400 Subject: [PATCH 700/864] tweak windows install instructions --- crawl-ref/INSTALL.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/INSTALL.txt b/crawl-ref/INSTALL.txt index f8de8d639266..a847faf77871 100644 --- a/crawl-ref/INSTALL.txt +++ b/crawl-ref/INSTALL.txt @@ -313,7 +313,7 @@ from within the MSYS2 Shell. * To install PyYAML, you can install it from Pip/PyPA: pacman -S mingw64/mingw-w64-x86_64-python2-pip - pip install pyyaml + pip2 install pyyaml You can verify PyYAML is installed by running `python -m yaml`, which should give an error like "'yaml' is a package and cannot be directly imported" From 6ba659e1adfd795c8775bd8c3d587e6c7a73e7d2 Mon Sep 17 00:00:00 2001 From: Kyle Rawlins Date: Sun, 29 Sep 2019 09:36:27 -0400 Subject: [PATCH 701/864] Tweak windows install instructions again [skip ci] --- crawl-ref/INSTALL.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/INSTALL.txt b/crawl-ref/INSTALL.txt index a847faf77871..b8a4a46b7585 100644 --- a/crawl-ref/INSTALL.txt +++ b/crawl-ref/INSTALL.txt @@ -312,8 +312,8 @@ from within the MSYS2 Shell. * To install PyYAML, you can install it from Pip/PyPA: - pacman -S mingw64/mingw-w64-x86_64-python2-pip - pip2 install pyyaml + pacman -S mingw64/mingw-w64-x86_64-python3-pip + pip install pyyaml You can verify PyYAML is installed by running `python -m yaml`, which should give an error like "'yaml' is a package and cannot be directly imported" From 0f4390f660a2bd0de6f0b1ff49c8c7722a79b15f Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 29 Sep 2019 09:53:13 -0400 Subject: [PATCH 702/864] Replace some symbolic links with copies In order to fix windows builds. --- .../rltiles/gui/backgrounds/disabled-fg.png | Bin 25 -> 729 bytes .../rltiles/gui/backgrounds/enabled-fg.png | Bin 24 -> 1105 bytes 2 files changed, 0 insertions(+), 0 deletions(-) mode change 120000 => 100644 crawl-ref/source/rltiles/gui/backgrounds/disabled-fg.png mode change 120000 => 100644 crawl-ref/source/rltiles/gui/backgrounds/enabled-fg.png diff --git a/crawl-ref/source/rltiles/gui/backgrounds/disabled-fg.png b/crawl-ref/source/rltiles/gui/backgrounds/disabled-fg.png deleted file mode 120000 index 4ee40ba36250..000000000000 --- a/crawl-ref/source/rltiles/gui/backgrounds/disabled-fg.png +++ /dev/null @@ -1 +0,0 @@ -../skills/disabled-fg.png \ No newline at end of file diff --git a/crawl-ref/source/rltiles/gui/backgrounds/disabled-fg.png b/crawl-ref/source/rltiles/gui/backgrounds/disabled-fg.png new file mode 100644 index 0000000000000000000000000000000000000000..42679d2bb46bf8153d90fabaab62022c599706ce GIT binary patch literal 729 zcmW+!+fUPQ6#lig(v^#)wq}4K9hPKN9xRthj0tTWr45&q(Q$i%D(Hq1g8Tv7GR(SQ zGM7OBdDs{(Fz^Ba*`OTL`s%;X#(OO5tkKf! z23Jn2Z}0Oq0Pv9N7Ik|G`VNB5hy_S$piKOId`SQL^E&$kdnl9E}?!M)Paudcnvx!O|m>4UaxX6 zwuqN6sxH)(mLGk9(l)*~IaiF8&* zeCm56>R+6^{sO0l&4UN{KBhC&mL~Q|ebz;(8`b89oHOVg8AJ3BH+6yMjxYh$99?2P zY|sIz6^)O&IEK<74RW&PBPO^J9vd=Q%=!_DV@@&7IA_L&`KD@{&txFUHkh@~R*1y6 zt0=v=Ijy9bE{Jw?0&XSqc0k{f%;i9U8=`qm%S56*n`Hqu@stcK#0WeL^R%z)iwq2U zizB#~kP@{+tu zjf5qKEQb7mi`Bt+(BJ7RB36>6!Jdf?MhQjRL{d+m^dl)@Z93b#a92+}wDzlB?~zNx kG|1-RD{P8mNj{BHW9`Yg?eXl7Mk|9rZEANvllnvd0NK0f1poj5 literal 0 HcmV?d00001 diff --git a/crawl-ref/source/rltiles/gui/backgrounds/enabled-fg.png b/crawl-ref/source/rltiles/gui/backgrounds/enabled-fg.png deleted file mode 120000 index eb67c0b15e59..000000000000 --- a/crawl-ref/source/rltiles/gui/backgrounds/enabled-fg.png +++ /dev/null @@ -1 +0,0 @@ -../skills/enabled-fg.png \ No newline at end of file diff --git a/crawl-ref/source/rltiles/gui/backgrounds/enabled-fg.png b/crawl-ref/source/rltiles/gui/backgrounds/enabled-fg.png new file mode 100644 index 0000000000000000000000000000000000000000..6a9af475ef415a851d22ea4b0c84083a7fe69a1c GIT binary patch literal 1105 zcmWmCc}&{{6bJAY#&8TYq5(#NXk?4?SXj_y;xwWh>zo70;zWTRafx$)nqlTK93o~J z1jx8Tk*(ayR@y>adj9yeztW3d^e(@y{7P9Vy^*$*wqX4&`MmFYdH=q5x8ht`T1s{b z27^h%oi46K`^!)3nM5>;$J<0`JMjJKsv8*0!55wu7Be`Mg)WmDai5kXBdPoLoxr%? zE1SSz5{^}zJzvs6q<5jF8QmmiH<{T(X7x~5y(DJu47+!h-8aMOqoRO58ZbcR4$!!G zDuAZ}cshum1MqX;;2dv|$@`1NA7Vm7EZz_cdVpd>4>%BkEg*0O!)$1nyD-cZ4FjSP zKs*A9M*-33yl4~@jm?Y4K8ZDp^0Zj1vwSy`7L>r%uawK}A$4ynx{vpQrphupRyUqiX%YaZpAOZmj3 zw0l%`uWH?^wtLmhCH2Xv5&5&g?wDRvZvK2-Gk=3opDw?5)Ef}?JN1vd=(RI{LbR!(y*oiuK zV$Mj+8H>3iF?THHjm0*1cjNK+;W~tYJ`?uJCuPN~LT1J#be_T$7oE>Kl*IoX`)X;r zApfq7=o>sgy!0RGUbG`V4V0I^ZD`0BPPb{ zxo|uQdoqKN;jZ?3_y2gX0eeeOGl|5*|D|-6d|nsoxDediGy2rY_p2sa2o2f(TnvNv z))$3GwC>~ Date: Sun, 29 Sep 2019 10:08:39 -0400 Subject: [PATCH 703/864] just one more windows install instructions tweak This incorporates both solutions from #1134. Thanks to amcmullan and Goratrix for figuring this out; as of Feb or so, msys2 makes python 3 the default python version for everything. Resolves #1134 [skip ci] --- crawl-ref/INSTALL.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crawl-ref/INSTALL.txt b/crawl-ref/INSTALL.txt index b8a4a46b7585..7016eab94f7f 100644 --- a/crawl-ref/INSTALL.txt +++ b/crawl-ref/INSTALL.txt @@ -310,10 +310,14 @@ from within the MSYS2 Shell. After the packages are installed and gcc runs, you're ready to build crawl! -* To install PyYAML, you can install it from Pip/PyPA: +* To install PyYAML, you can install it from either pacman or from Pip/PyPA: pacman -S mingw64/mingw-w64-x86_64-python3-pip pip install pyyaml + + OR + + pacman -S mingw-w64-x86_64-python3-yaml You can verify PyYAML is installed by running `python -m yaml`, which should give an error like "'yaml' is a package and cannot be directly imported" From b6411803c1cc08ac3c05ddab2346746a002484da Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 29 Sep 2019 10:39:59 -0400 Subject: [PATCH 704/864] Fix a crash with full pregen This was introduced in 80d7c3d5c --- crawl-ref/source/files.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 49c42db521f1..6b3377b773b7 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1580,7 +1580,7 @@ static bool _branch_pregenerates(branch_type b) { if (!you.deterministic_levelgen) return false; - if (!brentry[b].is_valid() && is_random_subbranch(b)) + if (b == NUM_BRANCHES || !brentry[b].is_valid() && is_random_subbranch(b)) return false; return count(branch_generation_order.begin(), branch_generation_order.end(), b) > 0; @@ -1602,7 +1602,8 @@ bool pregen_dungeon(const level_id &stopping_point) // TODO: the is_valid() check here doesn't look quite right to me, but so // far I can't get it to break anything... if (stopping_point.is_valid() - || is_random_subbranch(stopping_point.branch) && you.wizard) + || stopping_point.branch != NUM_BRANCHES && + is_random_subbranch(stopping_point.branch) && you.wizard) { if (you.save->has_chunk(stopping_point.describe())) return false; From aa951a354a797873b5945c4be3cad55902315313 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 30 Sep 2019 01:34:01 +0800 Subject: [PATCH 705/864] Fix hiscores not showing in webtiles (12077, Ge0ff) Console viewers will still get a view that adjusts to their screen size; webtiles viewers get a hardcoded size of eleven lines, which IIRC was the typical size before. --- crawl-ref/source/end.cc | 3 ++- crawl-ref/source/webserver/game_data/static/ui-layouts.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/end.cc b/crawl-ref/source/end.cc index 7502c1dfd495..d2b7b0ec06ea 100644 --- a/crawl-ref/source/end.cc +++ b/crawl-ref/source/end.cc @@ -537,7 +537,8 @@ NORETURN void end_game(scorefile_entry &se) tiles.json_write_int("tex", death_tile.tex); tiles.json_close_object(); tiles.json_write_string("title", goodbye_title); - tiles.json_write_string("body", goodbye_msg); + tiles.json_write_string("body", goodbye_msg + + hiscores_print_list(11, SCORE_TERSE, hiscore_index, start)); tiles.push_ui_layout("game-over", 0); #endif diff --git a/crawl-ref/source/webserver/game_data/static/ui-layouts.js b/crawl-ref/source/webserver/game_data/static/ui-layouts.js index 79b4da81b21f..d8d9c28b2987 100644 --- a/crawl-ref/source/webserver/game_data/static/ui-layouts.js +++ b/crawl-ref/source/webserver/game_data/static/ui-layouts.js @@ -845,7 +845,7 @@ function ($, comm, client, ui, enums, cr, util, scroller, main, gui, player) { { var $popup = $(".templates > .game-over").clone(); $popup.find(".header > span").html(desc.title); - $popup.children(".body").html(fmt_body_txt(desc.body)); + $popup.children(".body").html(fmt_body_txt(util.formatted_string_to_html(desc.body))); var s = scroller($popup.children(".body")[0]); $popup.on("keydown keypress", function (event) { scroller_handle_key(s, event); From 2bac2fb1508e7f9dfedfb33c43729b3000a01068 Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 29 Sep 2019 14:18:58 -0400 Subject: [PATCH 706/864] Restore centering for the progress popup in console --- crawl-ref/source/ui.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index ae61534eddbe..cf52ad53fa36 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -2269,6 +2269,13 @@ progress_popup::progress_popup(string title, int width) { auto container = make_shared(Widget::VERT); container->align_items = Widget::CENTER; +#ifndef USE_TILE_LOCAL + // Center the popup in console. + // if webtiles browser ever uses this property, then this will probably + // look bad there and need another solution. But right now, webtiles ignores + // expand_h. + container->expand_h = true; +#endif formatted_string bar_string = get_progress_string(bar_width); progress_bar = make_shared(bar_string); auto title_text = make_shared(title); From 5bd470a27781bd0cf3bb871f81988312320f95c6 Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 29 Sep 2019 14:19:56 -0400 Subject: [PATCH 707/864] Don't clear player name when selecting arena (12075) I agree that this behavior is unintuitive given the menu structure (especially when navigating with keyboard), even though arena doesn't use player name. --- crawl-ref/source/startup.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index f8b88d69263e..38a35a07255f 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -678,7 +678,6 @@ class UIStartupMenu : public Widget switch (startup_menu_game_type) { case GAME_TYPE_ARENA: - input_string = ""; break; case GAME_TYPE_NORMAL: case GAME_TYPE_CUSTOM_SEED: From 964def8651a8cb75d401faa579b1fbd7d8effcb0 Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 29 Sep 2019 15:36:00 -0400 Subject: [PATCH 708/864] Fix a compiler warning (shadowed variable) --- crawl-ref/source/ui.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index cf52ad53fa36..1083748a0237 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -1892,8 +1892,8 @@ bool UIRoot::on_event(const wm_event& event) if (!layer_idx) return false; Widget* layer_root = m_root.get_child(layer_idx-1).get(); - Layout* layout = dynamic_cast(layer_root); - if (layout && layout->event_filters.emit(layout, event)) + Layout* layout_root = dynamic_cast(layer_root); + if (layout_root && layout_root->event_filters.emit(layout_root, event)) return true; for (Widget* w = focus_stack.back(); w; w = w->_get_parent()) if (w->on_event(event)) From f68d91829209692bd1d443b8ff005d25cc5d4677 Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 29 Sep 2019 15:36:51 -0400 Subject: [PATCH 709/864] checkwhite [skip ci] --- crawl-ref/INSTALL.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/INSTALL.txt b/crawl-ref/INSTALL.txt index 7016eab94f7f..62ec004b8219 100644 --- a/crawl-ref/INSTALL.txt +++ b/crawl-ref/INSTALL.txt @@ -314,9 +314,9 @@ from within the MSYS2 Shell. pacman -S mingw64/mingw-w64-x86_64-python3-pip pip install pyyaml - + OR - + pacman -S mingw-w64-x86_64-python3-yaml You can verify PyYAML is installed by running `python -m yaml`, which should From bfea814871e4f2f8030fa56f521890b07a13bfbb Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 29 Sep 2019 16:46:00 -0400 Subject: [PATCH 710/864] Apply some brute-force output debugging to the problem --- crawl-ref/source/newgame.cc | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index c95897315487..835eb48aa7da 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -1630,8 +1630,15 @@ static void _construct_weapon_menu(const newgame_def& ng, string thrown_name; +#ifdef USE_TILE_LOCAL + mpr("test 3.1"); +#endif + for (unsigned int i = 0; i < weapons.size(); ++i) { +#ifdef USE_TILE_LOCAL + mprf("test 3.2 loop %d", i); +#endif weapon_type wpn_type = weapons[i].first; switch (wpn_type) @@ -1693,6 +1700,10 @@ static void _construct_weapon_menu(const newgame_def& ng, for (const auto& choice : choices) max_text_width = max(max_text_width, strwidth(choice.label)); +#ifdef USE_TILE_LOCAL + mpr("test 3.3"); +#endif + for (unsigned int i = 0; i < weapons.size(); ++i) { const auto& choice = choices[i]; @@ -1768,6 +1779,10 @@ static void _construct_weapon_menu(const newgame_def& ng, main_items->add_button(move(btn), 0, i); } +#ifdef USE_TILE_LOCAL + mpr("test 3.4"); +#endif + _add_menu_sub_item(sub_items, 0, 0, "+ - Recommended random choice", "Picks a random recommended weapon", '+', M_VIABLE); _add_menu_sub_item(sub_items, 0, 1, "% - List aptitudes", @@ -1806,6 +1821,9 @@ static bool _prompt_weapon(const newgame_def& ng, newgame_def& ng_choice, weapon_type defweapon = _fixup_weapon(defaults.weapon, weapons); auto title_hbox = make_shared(Widget::HORZ); +#ifdef USE_TILE_LOCAL + mpr("test 1"); +#endif #ifdef USE_TILE dolls_data doll; fill_doll_for_newgame(doll, ng); @@ -1814,6 +1832,9 @@ static bool _prompt_weapon(const newgame_def& ng, newgame_def& ng_choice, tile->set_margin_for_sdl({0, 10, 0, 0}); title_hbox->add_child(move(tile)); #endif +#endif +#ifdef USE_TILE_LOCAL + mpr("test 2"); #endif auto title = make_shared(formatted_string(_welcome(ng), BROWN)); title_hbox->add_child(title); @@ -1840,8 +1861,16 @@ static bool _prompt_weapon(const newgame_def& ng, newgame_def& ng_choice, main_items->linked_menus[2] = sub_items; sub_items->linked_menus[0] = main_items; +#ifdef USE_TILE_LOCAL + mpr("test 3"); +#endif + _construct_weapon_menu(ng, defweapon, weapons, main_items, sub_items); +#ifdef USE_TILE_LOCAL + mpr("test 4"); +#endif + bool done = false, ret = false; auto menu_item_activated = [&](int id) { @@ -1881,6 +1910,10 @@ static bool _prompt_weapon(const newgame_def& ng, newgame_def& ng_choice, main_items->on_button_activated = menu_item_activated; sub_items->on_button_activated = menu_item_activated; +#ifdef USE_TILE_LOCAL + mpr("test 5"); +#endif + auto popup = make_shared(vbox); popup->add_event_filter([&](wm_event ev) { if (ev.type != WME_KEYDOWN) From 40886de7c53b5aa264553e477248096be093737e Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 29 Sep 2019 17:09:38 -0400 Subject: [PATCH 711/864] More public bisection (The reason that I'm doing this bisection in trunk like this is that we are chasing a crash that only replicates on the windows tile builds done by CDO.) --- crawl-ref/source/newgame.cc | 36 ++++++------------------------------ 1 file changed, 6 insertions(+), 30 deletions(-) diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 835eb48aa7da..9b9c79b7d062 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -1630,15 +1630,8 @@ static void _construct_weapon_menu(const newgame_def& ng, string thrown_name; -#ifdef USE_TILE_LOCAL - mpr("test 3.1"); -#endif - for (unsigned int i = 0; i < weapons.size(); ++i) { -#ifdef USE_TILE_LOCAL - mprf("test 3.2 loop %d", i); -#endif weapon_type wpn_type = weapons[i].first; switch (wpn_type) @@ -1700,10 +1693,6 @@ static void _construct_weapon_menu(const newgame_def& ng, for (const auto& choice : choices) max_text_width = max(max_text_width, strwidth(choice.label)); -#ifdef USE_TILE_LOCAL - mpr("test 3.3"); -#endif - for (unsigned int i = 0; i < weapons.size(); ++i) { const auto& choice = choices[i]; @@ -1779,10 +1768,6 @@ static void _construct_weapon_menu(const newgame_def& ng, main_items->add_button(move(btn), 0, i); } -#ifdef USE_TILE_LOCAL - mpr("test 3.4"); -#endif - _add_menu_sub_item(sub_items, 0, 0, "+ - Recommended random choice", "Picks a random recommended weapon", '+', M_VIABLE); _add_menu_sub_item(sub_items, 0, 1, "% - List aptitudes", @@ -1826,15 +1811,18 @@ static bool _prompt_weapon(const newgame_def& ng, newgame_def& ng_choice, #endif #ifdef USE_TILE dolls_data doll; +#ifdef USE_TILE_LOCAL + mpr("test 2"); +#endif fill_doll_for_newgame(doll, ng); #ifdef USE_TILE_LOCAL + mpr("test 3"); auto tile = make_shared(doll); + mpr("test 4"); tile->set_margin_for_sdl({0, 10, 0, 0}); + mpr("test 5"); title_hbox->add_child(move(tile)); #endif -#endif -#ifdef USE_TILE_LOCAL - mpr("test 2"); #endif auto title = make_shared(formatted_string(_welcome(ng), BROWN)); title_hbox->add_child(title); @@ -1861,16 +1849,8 @@ static bool _prompt_weapon(const newgame_def& ng, newgame_def& ng_choice, main_items->linked_menus[2] = sub_items; sub_items->linked_menus[0] = main_items; -#ifdef USE_TILE_LOCAL - mpr("test 3"); -#endif - _construct_weapon_menu(ng, defweapon, weapons, main_items, sub_items); -#ifdef USE_TILE_LOCAL - mpr("test 4"); -#endif - bool done = false, ret = false; auto menu_item_activated = [&](int id) { @@ -1910,10 +1890,6 @@ static bool _prompt_weapon(const newgame_def& ng, newgame_def& ng_choice, main_items->on_button_activated = menu_item_activated; sub_items->on_button_activated = menu_item_activated; -#ifdef USE_TILE_LOCAL - mpr("test 5"); -#endif - auto popup = make_shared(vbox); popup->add_event_filter([&](wm_event ev) { if (ev.type != WME_KEYDOWN) From 0b739ee41d2de5640f224a51a082f329e104b24c Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 29 Sep 2019 17:47:54 -0400 Subject: [PATCH 712/864] One more batch of debug code see 40886de7c. --- crawl-ref/source/newgame.cc | 9 --------- crawl-ref/source/tiledoll.cc | 10 ++++++++++ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 9b9c79b7d062..c95897315487 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -1806,21 +1806,12 @@ static bool _prompt_weapon(const newgame_def& ng, newgame_def& ng_choice, weapon_type defweapon = _fixup_weapon(defaults.weapon, weapons); auto title_hbox = make_shared(Widget::HORZ); -#ifdef USE_TILE_LOCAL - mpr("test 1"); -#endif #ifdef USE_TILE dolls_data doll; -#ifdef USE_TILE_LOCAL - mpr("test 2"); -#endif fill_doll_for_newgame(doll, ng); #ifdef USE_TILE_LOCAL - mpr("test 3"); auto tile = make_shared(doll); - mpr("test 4"); tile->set_margin_for_sdl({0, 10, 0, 0}); - mpr("test 5"); title_hbox->add_child(move(tile)); #endif #endif diff --git a/crawl-ref/source/tiledoll.cc b/crawl-ref/source/tiledoll.cc index 7eed413223c0..972283efb90f 100644 --- a/crawl-ref/source/tiledoll.cc +++ b/crawl-ref/source/tiledoll.cc @@ -506,23 +506,32 @@ void fill_doll_equipment(dolls_data &result) void fill_doll_for_newgame(dolls_data &result, const newgame_def& ng) { + mpr("test 1"); for (int j = 0; j < TILEP_PART_MAX; j++) result.parts[j] = TILEP_SHOW_EQUIP; + mpr("test 2"); unwind_var unwind_you(you); you = player(); + mpr("test 3"); // The following is part of the new game setup code from _setup_generic() you.your_name = ng.name; you.species = ng.species; you.char_class = ng.job; you.chr_class_name = get_job_name(you.char_class); + mpr("test 4"); species_stat_init(you.species); + mpr("test 5"); update_vision_range(); + mpr("test 6"); job_stat_init(you.char_class); + mpr("test 7"); give_basic_mutations(you.species); + mpr("test 8"); give_items_skills(ng); + mpr("test 9"); for (int i = 0; i < ENDOFPACK; ++i) { @@ -530,6 +539,7 @@ void fill_doll_for_newgame(dolls_data &result, const newgame_def& ng) if (item.defined()) item_colour(item); } + mpr("test 10"); fill_doll_equipment(result); } From 2d0fce64a1130ec2f6c9c1e98e739cf328d54304 Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 29 Sep 2019 19:48:04 -0400 Subject: [PATCH 713/864] Don't generate unknown weapons for weapon selection I'm not sure if this is causing the windows crash (which is happening somewhere in give_items_skills), but it is definitely an odd thing that this code is doing when used before weapon selection. --- crawl-ref/source/ng-setup.cc | 4 +++- crawl-ref/source/tiledoll.cc | 10 ---------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/crawl-ref/source/ng-setup.cc b/crawl-ref/source/ng-setup.cc index a20bece65d1b..55cf6279f709 100644 --- a/crawl-ref/source/ng-setup.cc +++ b/crawl-ref/source/ng-setup.cc @@ -98,7 +98,9 @@ item_def* newgame_make_item(object_class_type base, return nullptr; // not an actual item - if (sub_type == WPN_UNARMED) + // the WPN_UNKNOWN case is used when generating a paper doll during + // character creation + if (sub_type == WPN_UNARMED || sub_type == WPN_UNKNOWN) return nullptr; int slot; diff --git a/crawl-ref/source/tiledoll.cc b/crawl-ref/source/tiledoll.cc index 972283efb90f..7eed413223c0 100644 --- a/crawl-ref/source/tiledoll.cc +++ b/crawl-ref/source/tiledoll.cc @@ -506,32 +506,23 @@ void fill_doll_equipment(dolls_data &result) void fill_doll_for_newgame(dolls_data &result, const newgame_def& ng) { - mpr("test 1"); for (int j = 0; j < TILEP_PART_MAX; j++) result.parts[j] = TILEP_SHOW_EQUIP; - mpr("test 2"); unwind_var unwind_you(you); you = player(); - mpr("test 3"); // The following is part of the new game setup code from _setup_generic() you.your_name = ng.name; you.species = ng.species; you.char_class = ng.job; you.chr_class_name = get_job_name(you.char_class); - mpr("test 4"); species_stat_init(you.species); - mpr("test 5"); update_vision_range(); - mpr("test 6"); job_stat_init(you.char_class); - mpr("test 7"); give_basic_mutations(you.species); - mpr("test 8"); give_items_skills(ng); - mpr("test 9"); for (int i = 0; i < ENDOFPACK; ++i) { @@ -539,7 +530,6 @@ void fill_doll_for_newgame(dolls_data &result, const newgame_def& ng) if (item.defined()) item_colour(item); } - mpr("test 10"); fill_doll_equipment(result); } From 5a4ac4e04deb3cdce48cbfb290c73101eb228595 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 30 Sep 2019 13:10:21 +0800 Subject: [PATCH 714/864] Remove debug logging --- crawl-ref/source/webserver/game_data/static/ui-layouts.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/crawl-ref/source/webserver/game_data/static/ui-layouts.js b/crawl-ref/source/webserver/game_data/static/ui-layouts.js index d8d9c28b2987..0768ac077ce9 100644 --- a/crawl-ref/source/webserver/game_data/static/ui-layouts.js +++ b/crawl-ref/source/webserver/game_data/static/ui-layouts.js @@ -728,10 +728,8 @@ function ($, comm, client, ui, enums, cr, util, scroller, main, gui, player) { { var br = $button[0].getBoundingClientRect(); var gr = $scr.parent()[0].getBoundingClientRect(); - console.log(br.bottom, gr.bottom); var delta = br.top < gr.top ? br.top - gr.top : br.bottom > gr.bottom ? br.bottom - gr.bottom : 0; - console.log("delta: ", delta); $scr[0].scrollTop += delta; } From 828224901cbf6b97e4ed6c0458f63b2130d9a7b0 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 30 Sep 2019 13:16:05 +0800 Subject: [PATCH 715/864] Refactor memorise menu entry colour code --- crawl-ref/source/spl-book.cc | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/crawl-ref/source/spl-book.cc b/crawl-ref/source/spl-book.cc index cc785cdb1f9c..490b8ab7b722 100644 --- a/crawl-ref/source/spl-book.cc +++ b/crawl-ref/source/spl-book.cc @@ -693,6 +693,19 @@ class SpellLibraryMenu : public Menu return true; } + colour_t entry_colour(const sortable_spell& entry) + { + if (vehumet_is_offering(entry.spell)) + return LIGHTBLUE; + else + { + bool transient = false; + bool memcheck = true; + return spell_highlight_by_utility(entry.spell, COL_UNKNOWN, + transient, memcheck); + } + } + // Update the list of spells. If show_hidden is true, show only hidden // ones; otherwise, show only non-hidden ones. void update_entries() @@ -719,20 +732,9 @@ class SpellLibraryMenu : public Menu if (spell_hidden != show_hidden) continue; - ostringstream desc; - - int colour = LIGHTGRAY; - if (vehumet_is_offering(spell.spell)) - colour = LIGHTBLUE; - else - { - bool transient = false; - bool memcheck = true; - colour = spell_highlight_by_utility(spell.spell, COL_UNKNOWN, - transient, memcheck); - } - + const int colour = entry_colour(spell); + ostringstream desc; desc << "<" << colour_to_str(colour) << ">"; desc << left; @@ -746,10 +748,9 @@ class SpellLibraryMenu : public Menu if (!you.divine_exegesis) { - colour = spell.fail_rate_colour; - desc << "<" << colour_to_str(colour) << ">"; + desc << "<" << colour_to_str(spell.fail_rate_colour) << ">"; desc << chop_string(failure_rate_to_string(spell.raw_fail), 12); - desc << ""; + desc << ""; } desc << spell.difficulty; From 2d00395b2e96742cf76bddf93e7ad466e9ce0720 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 30 Sep 2019 13:16:28 +0800 Subject: [PATCH 716/864] Fix memorise menu entry letter colour Previously, the entry letter was always lightgrey; now it is darkgrey if the spell is not castable, etc. --- crawl-ref/source/spl-book.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/source/spl-book.cc b/crawl-ref/source/spl-book.cc index 490b8ab7b722..b8f6a8e23ea8 100644 --- a/crawl-ref/source/spl-book.cc +++ b/crawl-ref/source/spl-book.cc @@ -765,6 +765,7 @@ class SpellLibraryMenu : public Menu // But do increment hotkeys anyway, to keep the hotkeys consistent. ++hotkey; + me->colour = colour; #ifdef USE_TILE me->add_tile(tile_def(tileidx_spell(spell.spell), TEX_GUI)); #endif From bbc45b03fdac14704f31d30ea753f3c2061ebdc3 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 30 Sep 2019 14:20:08 +0800 Subject: [PATCH 717/864] Fix newgame menu highlight width on remote console On TILEWEB=y console games, the text widget was not expanding to take the full width of the box it was contained in. When its background colour was changed, only the section of the menu button with letters changed colour. This isn't a problem in pure console builds because in that case the text widget is the direct child of the MenuButton widget and so takes its full size. --- crawl-ref/source/newgame.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index c95897315487..49cc1e856811 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -1175,9 +1175,11 @@ class UINewGameMenu : public Widget #ifdef USE_TILE auto hbox = make_shared(Box::HORZ); hbox->align_items = Widget::Align::CENTER; + hbox->justify_items = Widget::Align::STRETCH; auto tile = make_shared(); tile->set_tile(item_tile); tile->set_margin_for_sdl({0, 6, 0, 0}); + tile->flex_grow = 0; hbox->add_child(move(tile)); hbox->add_child(label); #endif From 5fed5919c2cdb4e4bde5e9e0becc83c127bdcf45 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 30 Sep 2019 21:45:43 +0800 Subject: [PATCH 718/864] Reduce popup padding on small screens (alexjurkiewicz) --- crawl-ref/source/ui.cc | 15 ++++++++++++--- crawl-ref/source/ui.h | 3 ++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 1083748a0237..ce34723d4fb9 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -1457,7 +1457,7 @@ SizeReq Popup::_get_preferred_size(Direction dim, int prosp_width) #endif SizeReq sr = m_child->get_preferred_size(dim, prosp_width); #ifdef USE_TILE_LOCAL - constexpr int pad = m_base_margin + m_padding; + const int pad = base_margin() + m_padding; return { 0, sr.nat + 2*pad + (dim ? m_depth*m_depth_indent*(!m_centred) : 0) }; @@ -1474,7 +1474,7 @@ void Popup::_allocate_region() m_buf.add(m_region[0], m_region[1], m_region[0] + m_region[2], m_region[1] + m_region[3], VColour(0, 0, 0, 150)); - constexpr int pad = m_base_margin + m_padding; + const int pad = base_margin() + m_padding; region[2] -= 2*pad; region[3] -= 2*pad + m_depth*m_depth_indent*(!m_centred); @@ -1511,7 +1511,7 @@ void Popup::_allocate_region() i2 Popup::get_max_child_size() { #ifdef USE_TILE_LOCAL - constexpr int pad = m_base_margin + m_padding; + const int pad = base_margin() + m_padding; return { (m_region[2] - 2*pad) & ~0x1, (m_region[3] - 2*pad - m_depth*m_depth_indent) & ~0x1, @@ -1522,6 +1522,15 @@ i2 Popup::get_max_child_size() } #ifdef USE_TILE_LOCAL +int Popup::base_margin() +{ + const int screen_small = 800, screen_large = 1000; + const int margin_small = 10, margin_large = 50; + const int clipped = max(screen_small, min(screen_large, m_region[3])); + return margin_small + (clipped-screen_small) + *(margin_large-margin_small)/(screen_large-screen_small); +} + void Dungeon::_render() { #ifdef USE_TILE_LOCAL diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index b801f6db45eb..070a1d740411 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -604,8 +604,9 @@ class Popup : public Layout #ifdef USE_TILE_LOCAL ShapeBuffer m_buf; static constexpr int m_depth_indent = 20; - static constexpr int m_base_margin = 50; static constexpr int m_padding = 23; + + int base_margin(); #endif bool m_centred{!crawl_state.need_save}; }; From 261a0b24175b1040f75d508293e6f9bf808a0718 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 30 Sep 2019 12:32:32 -0400 Subject: [PATCH 719/864] Main menu improvements and streamlining * move info about rc file off main screen -- without linewrapping this doesn't work well on either console or tiles. * don't explain arrow keys and enter * use some of the reclaimed space to improve description of [tab], add description of [ctrl-p]. This latter is mainly just so players know where to find the rc file info. Eventually the canonical place to find the rc file should be an about screen, not the startup log. --- crawl-ref/source/newgame.cc | 7 +++-- crawl-ref/source/newgame.h | 2 ++ crawl-ref/source/ng-input.cc | 16 ++++++---- crawl-ref/source/ng-input.h | 1 + crawl-ref/source/player-save-info.h | 1 + crawl-ref/source/player.cc | 8 +++++ crawl-ref/source/startup.cc | 49 ++++++++++++++++++----------- 7 files changed, 56 insertions(+), 28 deletions(-) diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 49cc1e856811..a9d80256a274 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -135,7 +135,7 @@ static bool _char_defined(const newgame_def& ng) return ng.species != SP_UNKNOWN && ng.job != JOB_UNKNOWN; } -static string _char_description(const newgame_def& ng) +string newgame_char_description(const newgame_def& ng) { if (_is_random_viable_choice(ng)) return "Recommended character"; @@ -370,7 +370,7 @@ static void _choose_species_job(newgame_def& ng, newgame_def& ng_choice, // Either an invalid combination was passed in through options, // or we messed up. end(1, false, "Incompatible species and background (%s) selected.", - _char_description(ng).c_str()); + newgame_char_description(ng).c_str()); } } @@ -1310,7 +1310,8 @@ class UINewGameMenu : public Widget if (_char_defined(defaults)) { _add_choice_menu_option(1, 3, - " Tab - " + _char_description(defaults), '\t', M_DEFAULT_CHOICE, + " Tab - " + newgame_char_description(defaults), '\t', + M_DEFAULT_CHOICE, "Play a new game with your previous choice."); } } diff --git a/crawl-ref/source/newgame.h b/crawl-ref/source/newgame.h index 5d576635933b..627dcf207a92 100644 --- a/crawl-ref/source/newgame.h +++ b/crawl-ref/source/newgame.h @@ -12,6 +12,8 @@ class UINewGameMenu; struct menu_letter; struct newgame_def; +string newgame_char_description(const newgame_def& ng); + void choose_tutorial_character(newgame_def& ng_choice); bool choose_game(newgame_def& ng, newgame_def& choice, diff --git a/crawl-ref/source/ng-input.cc b/crawl-ref/source/ng-input.cc index 9c14ceb2647f..efeed5d454e2 100644 --- a/crawl-ref/source/ng-input.cc +++ b/crawl-ref/source/ng-input.cc @@ -21,15 +21,19 @@ formatted_string opening_screen() { string msg = "Hello, welcome to " CRAWL " " + string(Version::Long) + "!\n" - "(c) Copyright 1997-2002 Linley Henzell, 2002-2019 Crawl DevTeam\n" - "Read the instructions for legal details. "; + "(c) Copyright 1997-2002 Linley Henzell, 2002-2019 Crawl DevTeam"; + return formatted_string::parse_string(msg); +} +formatted_string options_read_status() +{ + string msg; FileLineInput f(Options.filename.c_str()); if (!f.error()) { - msg += "(Options read from "; + msg += "Options read from \""; #ifdef DGAMELAUNCH // For dgl installs, show only the last segment of the .crawlrc // file name so that we don't leak details of the directory @@ -38,11 +42,11 @@ formatted_string opening_screen() #else msg += Options.filename; #endif - msg += ".)"; + msg += "\"."; } else { - msg += "(Options file "; + msg += "Options file "; if (!Options.filename.empty()) { msg += make_stringf("\"%s\" is not readable", @@ -50,7 +54,7 @@ formatted_string opening_screen() } else msg += "not found"; - msg += "; using defaults.)"; + msg += "; using defaults."; } msg += "\n"; diff --git a/crawl-ref/source/ng-input.h b/crawl-ref/source/ng-input.h index 217f15857653..b7dbb79af8ec 100644 --- a/crawl-ref/source/ng-input.h +++ b/crawl-ref/source/ng-input.h @@ -4,6 +4,7 @@ struct newgame_def; class formatted_string; formatted_string opening_screen(); +formatted_string options_read_status(); bool validate_player_name(const string &name); bool is_good_name(const string &name, bool blankOK); void enter_player_name(newgame_def& ng); diff --git a/crawl-ref/source/player-save-info.h b/crawl-ref/source/player-save-info.h index 447b042e2d07..df5cf3a754ec 100644 --- a/crawl-ref/source/player-save-info.h +++ b/crawl-ref/source/player-save-info.h @@ -37,4 +37,5 @@ struct player_save_info player_save_info& operator=(const player& rhs); bool operator<(const player_save_info& rhs) const; string short_desc() const; + string really_short_desc() const; }; diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 7ed58e8ff0ff..512c80ad5f7c 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -5228,6 +5228,14 @@ bool player_save_info::operator<(const player_save_info& rhs) const || (experience_level == rhs.experience_level && name < rhs.name); } +string player_save_info::really_short_desc() const +{ + ostringstream desc; + desc << name << " the " << species_name << ' ' << class_name; + + return desc.str(); +} + string player_save_info::short_desc() const { ostringstream desc; diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index 38a35a07255f..5b5133a46214 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -200,6 +200,7 @@ static void _initialize() } mpr(opening_screen().tostring().c_str()); + mpr(options_read_status().tostring().c_str()); } /** KILL_RESETs all monsters in LOS. @@ -536,10 +537,12 @@ class UIStartupMenu : public Widget m_root->_set_parent(this); m_root->align_items = Widget::Align::STRETCH; - m_root->add_child(make_shared(opening_screen())); + formatted_string about = opening_screen(); + + m_root->add_child(make_shared(about)); auto grid = make_shared(); - grid->set_margin_for_crt({1, 0, 2, 0}); + grid->set_margin_for_crt({1, 0, 1, 0}); // If the game filled in a complete name, the user will // usually want to enter a new name instead of adding @@ -627,26 +630,34 @@ class UIStartupMenu : public Widget m_root->add_child(move(grid)); - string text = "Use the up/down keys to select the type of game or load a " - "character."; -#ifdef USE_TILE_LOCAL - if (tiles.is_using_small_layout()) - text += " "; - else -#endif - text += "\n"; - text += "You can type your name; if you leave it blank you will be " - "asked later.\n" - "Press Enter to start"; - // TODO: this should include a description of that character. - if (_game_defined(defaults)) - text += ", Tab to repeat the last game's choice"; - text += ".\n"; + string instructions_text; + // TODO: these can overflow on console 80x24 and won't line-wrap, is + // there any good solution to this? e.g. + // `long name long name the Vine Stalker Earth Elementalist` + if (defaults.name.size() > 0 && _find_save(chars, defaults.name) != -1) + { + auto save = _find_save(chars, defaults.name); + instructions_text += + "[tab] quick-load last game: " + + chars[save].really_short_desc() + "\n"; + } + else if (_game_defined(defaults)) + { + instructions_text += + "[tab] quick-start last combo: " + + defaults.name + " the " + + newgame_char_description(defaults) + "\n"; + } + instructions_text += + "[ctrl-p] view rc file information and log"; if (recent_error_messages()) - text += "Errors during initialization; press ctrl-p to view the full log.\n"; - m_root->add_child(make_shared(text)); + instructions_text += " (Errors during initialization!)"; + + m_root->add_child(make_shared( + formatted_string::parse_string(instructions_text))); descriptions->set_margin_for_crt({1, 0, 0, 0}); + descriptions->set_margin_for_sdl({10, 0, 0, 0}); m_root->add_child(descriptions); }; From 3c9d5f24f3903777b127221292c7a731693e890d Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 30 Sep 2019 12:59:04 -0400 Subject: [PATCH 720/864] Remove full_name logic from main menu These features were supposed to make typing the player name easier, but they're very hard to predict from standard text box behavior, and also buggy with names that are a partial match to another name. In addition, the behavior pre-0.24 that this logic is based on seems to have been fairly broken; at least I can't figure out the pattern from the UI in older versions for when `full_name` is set to true. Should replace this with some more of the standard text editing shortcuts, e.g. ctrl-u. --- crawl-ref/source/startup.cc | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index 5b5133a46214..8de3a854a10c 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -547,7 +547,6 @@ class UIStartupMenu : public Widget // If the game filled in a complete name, the user will // usually want to enter a new name instead of adding // to the current one. - full_name = !input_string.empty(); input_text = make_shared(); input_text->set_text(formatted_string(input_string, WHITE)); input_text->set_margin_for_crt({0, 0, 1, 0}); @@ -677,7 +676,6 @@ class UIStartupMenu : public Widget newgame_def& ng_choice; const newgame_def &defaults; string input_string; - bool full_name; vector chars; int num_saves; @@ -713,7 +711,6 @@ class UIStartupMenu : public Widget input_string = chars.at(save_number).name; else // new game input_string = ""; - full_name = true; break; } input_text->set_text(formatted_string(input_string, WHITE)); @@ -816,11 +813,6 @@ void UIStartupMenu::on_show() if (iswalnum(keyn) || keyn == '-' || keyn == '.' || keyn == '_' || keyn == ' ') { - if (full_name) - { - full_name = false; - input_string = ""; - } if (strwidth(input_string) < MAX_NAME_LENGTH) { input_string += stringize_glyph(keyn); @@ -831,12 +823,8 @@ void UIStartupMenu::on_show() { if (!input_string.empty()) { - if (full_name) - input_string = ""; - else - input_string.erase(input_string.size() - 1); + input_string.erase(input_string.size() - 1); changed_name = true; - full_name = false; } } else From be6272a8903aeb34d85a2c0835e73353ac6ace44 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Mon, 30 Sep 2019 14:21:07 -0500 Subject: [PATCH 721/864] Use no_tele_into in a Bazaar map (wizard44) The water (or lava) areas outside of the central area with shops needs `no_tele_into` in order to prevent teleports from stranding players who are amphibious or flying. --- crawl-ref/source/dat/des/portals/bazaar.des | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/source/dat/des/portals/bazaar.des b/crawl-ref/source/dat/des/portals/bazaar.des index 479f184e2bd0..8eff5f73cf41 100644 --- a/crawl-ref/source/dat/des/portals/bazaar.des +++ b/crawl-ref/source/dat/des/portals/bazaar.des @@ -554,6 +554,7 @@ NAME: bazaar_minmay_generic_island TAGS: no_rotate ORIENT: encompass WEIGHT: 20 +KPROP: w = no_tele_into SUBST: w : wl SHUFFLE: Aa/Bb/Cc/Dd, Cc/Ee, Dd/Ff COLOUR: EeFf = yellow From f1a930fc54b257e9c9e593e2ec711ec7bdc34ddb Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 30 Sep 2019 15:37:26 -0400 Subject: [PATCH 722/864] Don't pull abyss terrain from the vestibule The issue is that if the player hasn't visited the vestibule, a level excursion there will trigger asserts regarding the up stairs, which haven't been set up yet. This could be made conditional on having visited the vestibule, but even for the abyss I'd rather avoid dependencies on level traversal order. --- crawl-ref/source/abyss.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/abyss.cc b/crawl-ref/source/abyss.cc index f263ef16839e..3bddb0e13b4e 100644 --- a/crawl-ref/source/abyss.cc +++ b/crawl-ref/source/abyss.cc @@ -1062,8 +1062,11 @@ static level_id _get_random_level() vector levels; for (branch_iterator it; it; ++it) { - if (it->id == BRANCH_ABYSS || it->id == BRANCH_SHOALS) + if (it->id == BRANCH_VESTIBULE || it->id == BRANCH_ABYSS + || it->id == BRANCH_SHOALS) + { continue; + } for (int j = 1; j <= brdepth[it->id]; ++j) { const level_id id(it->id, j); From 2f2aade273a4c368969f5d5b25d6ba56c9539575 Mon Sep 17 00:00:00 2001 From: olowin Date: Tue, 16 Apr 2019 17:18:55 -0400 Subject: [PATCH 723/864] The unrand staff of Battle A staff of conjuration with. It will automatically spawn a battlesphere when monsters are in sight and automatically dismisses the battlesphere on unwield. Trog hates it; using it to spawn a battlesphere is as bad as casting a spell in Trog's eyes. Unlike an evokable this is real magic. [Committer's note: Squashed and rebased; made the staff battlesphere have the same spellpower as the player's (to avoid weird re-casting incentives); removed +4 SH, it is one-handed on normal species. Closes #1040] --- crawl-ref/source/art-data.txt | 9 +++++++++ crawl-ref/source/art-func.h | 19 +++++++++++++++++++ crawl-ref/source/dat/descript/unrand.txt | 9 +++++++++ crawl-ref/source/god-item.cc | 11 ++++++++++- crawl-ref/source/god-item.h | 1 + crawl-ref/source/player-equip.cc | 2 ++ crawl-ref/source/player.cc | 3 +++ 7 files changed, 53 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/art-data.txt b/crawl-ref/source/art-data.txt index d43375735ffa..f3af462e2c2a 100644 --- a/crawl-ref/source/art-data.txt +++ b/crawl-ref/source/art-data.txt @@ -1372,6 +1372,15 @@ TILE: urand_rift TILE_EQ: rift BRAND: SPWPN_DISTORTION +ENUM: BATTLE +NAME: staff of Battle +OBJ: OBJ_WEAPONS/WPN_STAFF +PLUS: +0 +COLOUR: ETC_MAGIC +#TILE: urand_staff_of_battle +#TILE_EQ: battle +VALUE: 800 + # This entry must always be last. ENUM: DUMMY2 NAME: DUMMY UNRANDART 2 diff --git a/crawl-ref/source/art-func.h b/crawl-ref/source/art-func.h index 521119f0eec6..027957d6469e 100644 --- a/crawl-ref/source/art-func.h +++ b/crawl-ref/source/art-func.h @@ -1432,3 +1432,22 @@ static void _ZHOR_world_reacts(item_def *item) cast_englaciation(30, false); } } + +//////////////////////////////////////////////////// + +// XXX: Staff of Battle giving a boost to conjuration spells is hardcoded in +// player_spec_conj(). + +static void _BATTLE_unequip(item_def *item, bool *show_msgs) +{ + end_battlesphere(find_battlesphere(&you), false); +} + +static void _BATTLE_world_reacts(item_def *item) +{ + if (!find_battlesphere(&you) && there_are_monsters_nearby(true, true, false)) + { + your_spells(SPELL_BATTLESPHERE, 0, false); + did_god_conduct(DID_SPELL_CASTING, 1); + } +} diff --git a/crawl-ref/source/dat/descript/unrand.txt b/crawl-ref/source/dat/descript/unrand.txt index 12e83ee3f401..9837b2734774 100644 --- a/crawl-ref/source/dat/descript/unrand.txt +++ b/crawl-ref/source/dat/descript/unrand.txt @@ -687,3 +687,12 @@ A small wrinkle in the very fabric of reality, magically bound to a shaft by some mad acolyte of Lugonu. It possesses an unusually large reach that teleports its attack directly to its victim. %%%% +staff of Battle + +A tubular staff encased in vividly coloured scales, the handiwork of a +long-forgotten mage. It was stolen by the wizard Iskenderun who used it for a +time before unlocking its secrets. The staff increases the power of its +wielder's conjuration magic and, when its wielder is in danger, the staff will +conjure a battlesphere to provide support. The strength of the battlesphere +depends on the wielder's skill with Charms and Conjurations. +%%%% diff --git a/crawl-ref/source/god-item.cc b/crawl-ref/source/god-item.cc index 84b708d2bdbe..0f0b24be73b5 100644 --- a/crawl-ref/source/god-item.cc +++ b/crawl-ref/source/god-item.cc @@ -362,6 +362,14 @@ bool is_channeling_item(const item_def& item, bool calc_unid) && item.sub_type == MISC_CRYSTAL_BALL_OF_ENERGY; } +bool is_wizardly_item(const item_def& item, bool calc_unid) +{ + if (is_unrandom_artefact(item, UNRAND_BATTLE)) + return true; + + return false; +} + bool is_corpse_violating_spell(spell_type spell) { spell_flags flags = get_spell_flags(spell); @@ -433,8 +441,9 @@ vector item_conducts(const item_def &item) if (item_is_spellbook(item)) conducts.push_back(DID_SPELL_MEMORISE); - if (item.sub_type == BOOK_MANUAL && item_type_known(item) + if ((item.sub_type == BOOK_MANUAL && item_type_known(item) && is_magic_skill((skill_type)item.plus)) + || is_wizardly_item(item)) { conducts.push_back(DID_SPELL_PRACTISE); } diff --git a/crawl-ref/source/god-item.h b/crawl-ref/source/god-item.h index af3fc81f0131..5bf4917c14e2 100644 --- a/crawl-ref/source/god-item.h +++ b/crawl-ref/source/god-item.h @@ -11,6 +11,7 @@ bool is_evil_item(const item_def& item, bool calc_unid = true); bool is_unclean_item(const item_def& item, bool calc_unid = true); bool is_chaotic_item(const item_def& item, bool calc_unid = true); bool is_hasty_item(const item_def& item, bool calc_unid = true); +bool is_wizardly_item(const item_def& item, bool calc_unid = true); bool is_channeling_item(const item_def& item, bool calc_unid = true); bool is_corpse_violating_spell(spell_type spell); bool is_evil_spell(spell_type spell); diff --git a/crawl-ref/source/player-equip.cc b/crawl-ref/source/player-equip.cc index 23923c7c0390..d64a29c9c2ba 100644 --- a/crawl-ref/source/player-equip.cc +++ b/crawl-ref/source/player-equip.cc @@ -398,6 +398,8 @@ static void _equip_use_warning(const item_def& item) mpr("You really shouldn't be using a chaotic item like this."); else if (is_hasty_item(item) && you_worship(GOD_CHEIBRIADOS)) mpr("You really shouldn't be using a hasty item like this."); + else if (is_wizardly_item(item) && you_worship(GOD_TROG)) + mpr("You really shouldn't be using a wizardly item like this."); #if TAG_MAJOR_VERSION == 34 else if (is_channeling_item(item) && you_worship(GOD_PAKELLAS)) mpr("You really shouldn't be trying to channel magic like this."); diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 512c80ad5f7c..8e4fc8d7453f 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -1738,6 +1738,9 @@ int player_spec_conj() // Staves sc += you.wearing(EQ_STAFF, STAFF_CONJURATION); + if (player_equip_unrand(UNRAND_BATTLE)) + sc++; + return sc; } From 0e0b6798f16925d109c157667c4d58ef1a25cfde Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Tue, 1 Oct 2019 00:33:41 -0400 Subject: [PATCH 724/864] Tiles for the staff of Battle (CanOfWorms) --- crawl-ref/source/art-data.txt | 4 ++-- crawl-ref/source/rltiles/dc-player.txt | 1 + .../weapon/artefact/urand_staff_of_battle.png | Bin 0 -> 1154 bytes .../player/hand1/artefact/battle_staff.png | Bin 0 -> 1071 bytes 4 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 crawl-ref/source/rltiles/item/weapon/artefact/urand_staff_of_battle.png create mode 100644 crawl-ref/source/rltiles/player/hand1/artefact/battle_staff.png diff --git a/crawl-ref/source/art-data.txt b/crawl-ref/source/art-data.txt index f3af462e2c2a..633ffe064e49 100644 --- a/crawl-ref/source/art-data.txt +++ b/crawl-ref/source/art-data.txt @@ -1377,8 +1377,8 @@ NAME: staff of Battle OBJ: OBJ_WEAPONS/WPN_STAFF PLUS: +0 COLOUR: ETC_MAGIC -#TILE: urand_staff_of_battle -#TILE_EQ: battle +TILE: urand_staff_of_battle +TILE_EQ: battle_staff VALUE: 800 # This entry must always be last. diff --git a/crawl-ref/source/rltiles/dc-player.txt b/crawl-ref/source/rltiles/dc-player.txt index 541039ef28f6..471025037e8e 100644 --- a/crawl-ref/source/rltiles/dc-player.txt +++ b/crawl-ref/source/rltiles/dc-player.txt @@ -546,6 +546,7 @@ asmodeus ASMODEUS dispater DISPATER olgreb OLGREB order ORDER +battle_staff BATTLE_STAFF ## axes axe_trog AXE_TROG arga ARGA diff --git a/crawl-ref/source/rltiles/item/weapon/artefact/urand_staff_of_battle.png b/crawl-ref/source/rltiles/item/weapon/artefact/urand_staff_of_battle.png new file mode 100644 index 0000000000000000000000000000000000000000..7d139744116990e18b563316630f1e52eacadeb7 GIT binary patch literal 1154 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy>?NMQuI!Jw7@1`(MQyIT0ENU$ zTq8j(_xa`Llm7e=;&Mg0$iVCN8ax zHP^D1y#T7ms}LdS?Hy56HEq$B{Rp8^)@TR}TnHT5YT^X6oiWMV-G!lpRn`NFMGaQZZ-gWM95k1CExtEFYMbnrqzq-^Tx^bCyG_jaclL+2=&ooc`p` zIK#;xys2T+x*+a3Ri38~{}w1v%y{)rXpe`(ebzbLcjBsD1eS7MoLSb&QFv`hweaHI ztR0&S8}HuKwOAU?qFwx|J}$^5St!K9B)@M#l*@ur-g~tXJL|W+$X?BoX5G;-C4ctA zEweuFvD@iu`Rq>ogXUy;p+2ka6*p?-`gd(h=~-QzGUsUgMQOeM`)r5z=N7$tcixS& jpJDaG+SNrY^S?6xI?Sb>ba=rPP+)ty`njxgN@xNA)TyRX literal 0 HcmV?d00001 diff --git a/crawl-ref/source/rltiles/player/hand1/artefact/battle_staff.png b/crawl-ref/source/rltiles/player/hand1/artefact/battle_staff.png new file mode 100644 index 0000000000000000000000000000000000000000..de2af128dbb5c4f3b7baca21e2770e5cd7608bf4 GIT binary patch literal 1071 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy>?NMQuI!Jw7@1{EWx8hP1BJv( zTq8j(_xa`Llm7e=;&Mg0$iVCN8ax zHP^D1y#T7ms}LdS?Hy56HEq$B{Rp8^)@TR}TnHT5YT^X6oiWMV-G!lpRn`N)jKE((& Date: Thu, 18 Jul 2019 22:06:29 +0300 Subject: [PATCH 725/864] Distinguish flammable and non-flammable trees Even though Summon Forest's trees cannot be burned since 0a4d0e94, their description still mentioned that mechanic. Fix this and add a way to distinguish summoned trees from regular ones in the x-mode. Also, update a comment: trees cannot be disintegrated since 85f13f00. --- crawl-ref/source/beam.cc | 2 +- crawl-ref/source/dat/descript/features.txt | 6 ++---- crawl-ref/source/describe.cc | 10 ++++++++++ crawl-ref/source/directn.cc | 2 ++ 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc index 04d9c8127969..dd3436f73fe0 100644 --- a/crawl-ref/source/beam.cc +++ b/crawl-ref/source/beam.cc @@ -2622,7 +2622,7 @@ bool bolt::can_affect_wall(const coord_def& p, bool map_knowledge) const return true; } - // Temporary trees (from Summon Forest) can't be burned/distintegrated. + // Temporary trees (from Summon Forest) can't be burned. if (feat_is_tree(wall) && is_temp_terrain(p)) return false; diff --git a/crawl-ref/source/dat/descript/features.txt b/crawl-ref/source/dat/descript/features.txt index 23a977c31f4c..cce6b8af79ce 100644 --- a/crawl-ref/source/dat/descript/features.txt +++ b/crawl-ref/source/dat/descript/features.txt @@ -242,15 +242,13 @@ A tree A large tree. While in most places the dim light of the dungeon is not bright enough to sustain large plants, there are spots where, with the grace of -Fedhas, trees as big as those on the surface can grow underground. It is -susceptible to bolts of lightning and to sufficiently intense sources of fire. +Fedhas, trees as big as those on the surface can grow underground. %%%% An awoken tree A large tree that has been enchanted to grant it some limited motility, allowing it to lash out out at any adjacent enemies of the creature who awoke -it. It is susceptible to bolts of lightning and to sufficiently intense sources -of fire. +it. %%%% An abandoned shop diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index e05acfb559a8..f086cef30e5b 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -2198,6 +2198,7 @@ void get_feature_desc(const coord_def &pos, describe_info &inf, bool include_ext string desc = feature_description_at(pos, false, DESC_A, false); string db_name = feat == DNGN_ENTER_SHOP ? "a shop" : desc; + strip_suffix(db_name, " (summoned)"); string long_desc = getLongDescription(db_name); inf.title = uppercase_first(desc); @@ -2236,6 +2237,15 @@ void get_feature_desc(const coord_def &pos, describe_info &inf, bool include_ext command_to_string(CMD_GO_DOWNSTAIRS).c_str()); } + // mention that permanent trees are usually flammable + // (expect for autumnal trees in Wucad Mu's Monastery) + if (feat_is_tree(feat) && !is_temp_terrain(pos) + && env.markers.property_at(pos, MAT_ANY, "veto_fire") != "veto") + { + long_desc += "\nIt is susceptible to bolts of lightning"; + long_desc += " and to sufficiently intense sources of fire."; + } + inf.body << long_desc; if (include_extra) diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc index 1e39d76b91fd..6e8c46f5ddb6 100644 --- a/crawl-ref/source/directn.cc +++ b/crawl-ref/source/directn.cc @@ -2991,6 +2991,8 @@ string feature_description_at(const coord_def& where, bool covering, desc += "awoken "; desc += grid == grd(where) ? raw_feature_description(where) : _base_feature_desc(grid, trap); + if (is_temp_terrain(where)) + desc += " (summoned)"; desc += covering_description; return thing_do_grammar(dtype, add_stop, false, desc); } From ac2e79e1c78872d860cfef5df23183f7ebce17e1 Mon Sep 17 00:00:00 2001 From: Nikolai Lavsky <3328424+nlavsky@users.noreply.github.com> Date: Thu, 26 Sep 2019 21:46:36 +0300 Subject: [PATCH 726/864] Add descriptions for awoken autumnal and dead trees Use the same description as for regular awoken trees. --- crawl-ref/source/dat/descript/features.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crawl-ref/source/dat/descript/features.txt b/crawl-ref/source/dat/descript/features.txt index cce6b8af79ce..6da2175fbdd8 100644 --- a/crawl-ref/source/dat/descript/features.txt +++ b/crawl-ref/source/dat/descript/features.txt @@ -250,6 +250,14 @@ A large tree that has been enchanted to grant it some limited motility, allowing it to lash out out at any adjacent enemies of the creature who awoke it. %%%% +An awoken autumnal tree + + +%%%% +An awoken dead tree + + +%%%% An abandoned shop A shop that has been abandoned. From 011b83addebfeb79255188463b9de43ee423884c Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Sat, 10 Aug 2019 19:36:11 +0100 Subject: [PATCH 727/864] Let Trog and Okawaru gift regular boomerangs and javelins Previously, when tomahawks and javelins had no innate special properties and each had about 5 different brands, it made sense that Trog and Okawaru should always gift branded tomahawks and javelins. However, there are now only two different types of javelin: plain and silver; and three different types of boomerang: plain, silver and dispersal. This behaviour led to all such ammo gifts being silver javelins, or silver or dispersal boomerangs, which seems a little unbalanced. Additionally, new javelins are equivalent to branded penetration javelins previously, and likewise with boomerangs and tomahawks of returning, so this behaviour no longer makes sense. As such, Trog and Okawaru now gift regular boomerangs and javelins, with these having weight 120. This means the chance of a javelin gift giving silver javelins is reduced from 100% to 43%, and the chance of a boomerang gift being branded is reduced from 100% to 33%. This commit preserves Trog and Okawaru only gifting curare/datura/atropa-tipped darts and not poisoned darts, and also preserves the behaviour of ISPEC_GOOD_ITEM always producing branded missiles, so as to not affect dungeon generation in any way. [Closes #1131] --- crawl-ref/source/makeitem.cc | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/crawl-ref/source/makeitem.cc b/crawl-ref/source/makeitem.cc index d9b2c2989af0..6a147a1cad5b 100644 --- a/crawl-ref/source/makeitem.cc +++ b/crawl-ref/source/makeitem.cc @@ -495,8 +495,6 @@ static void _generate_weapon_item(item_def& item, bool allow_uniques, } } -// Current list is based on dpeg's original post to the Wiki, found at the -// page: . // Remember to update the code in is_missile_brand_ok if adding or altering // brands that are applied to missiles. {due} static special_missile_type _determine_missile_brand(const item_def& item, @@ -506,11 +504,17 @@ static special_missile_type _determine_missile_brand(const item_def& item, if (item.brand != 0) return static_cast(item.brand); - const bool force_good = item_level >= ISPEC_GIFT; special_missile_type rc = SPMSL_NORMAL; - // "Normal weight" of SPMSL_NORMAL. - int nw = force_good ? 0 : random2(2000 - 55 * item_level); + // Weight of SPMSL_NORMAL + // Gifts from Trog/Oka can be unbranded boomerangs/javelins + // but not poisoned darts + int nw = item_level >= ISPEC_GOOD_ITEM ? 0 : + item_level == ISPEC_GIFT ? 120 + : random2(2000 - 55 * item_level); + + // Weight of SPMSL_POISONED + int pw = item_level >= ISPEC_GIFT ? 0 : random2(2000 - 55 * item_level); switch (item.sub_type) { @@ -532,7 +536,7 @@ static special_missile_type _determine_missile_brand(const item_def& item, rc = random_choose_weighted(60, SPMSL_BLINDING, 20, SPMSL_FRENZY, - nw, SPMSL_POISONED); + pw, SPMSL_POISONED); break; case MI_JAVELIN: rc = random_choose_weighted(90, SPMSL_SILVER, From 3ed16d2262f82fa50abee221417f13f2c66532b9 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Tue, 1 Oct 2019 01:23:07 +0800 Subject: [PATCH 728/864] Refactor curses colour and attr munging --- crawl-ref/source/libunix.cc | 168 ++++++++++++++++-------------------- 1 file changed, 72 insertions(+), 96 deletions(-) diff --git a/crawl-ref/source/libunix.cc b/crawl-ref/source/libunix.cc index 97c99f42262b..fa0a888be5c9 100644 --- a/crawl-ref/source/libunix.cc +++ b/crawl-ref/source/libunix.cc @@ -73,13 +73,15 @@ static COLOURS BG_COL = BLACK; /** @brief The default background @em colour. */ static COLOURS BG_COL_DEFAULT = BLACK; +struct curses_style +{ + attr_t attr; + short color_pair; +}; + /** * @brief Get curses attributes for the current internal color combination. * - * @param attr - * The destination for the resulting character attributes. - * @param color_pair - * The destination for the resulting color pair index. * @param fg * The internal colour for the foreground. * @param bg @@ -87,33 +89,33 @@ static COLOURS BG_COL_DEFAULT = BLACK; * @param adjust_background * Determines which color in the pair is adjusted if adjustment is necessary. * True chooses the background, while false chooses the foreground. + * + * @return + * Returns the character attributes and colour pair index. */ -static void curs_attr(attr_t &attr, short &color_pair, COLOURS fg, COLOURS bg, - bool adjust_background = false); +static curses_style curs_attr(COLOURS fg, COLOURS bg, bool adjust_background = false); /** * @brief Change the foreground colour and returns the resulting curses info. * - * @param attr - * The destination for the resulting character attributes. - * @param color_pair - * The destination for the resulting color pair index. * @param col * An internal color with attached brand. + * + * @return + * Returns the character attributes and colour pair index. */ -static void curs_attr_bg(attr_t &attr, short &color_pair, int col); +static curses_style curs_attr_bg(int col); /** * @brief Change the background colour and returns the resulting curses info. * - * @param attr - * The destination for the resulting character attributes. - * @param color_pair - * The destination for the resulting color pair index. * @param col * An internal color with attached brand. + * + * @return + * Returns the character attributes and colour pair index. */ -static void curs_attr_fg(attr_t &attr, short &color_pair, int col); +static curses_style curs_attr_fg(int col); /** * @brief Get curses attributes for the passed internal color combination. @@ -121,19 +123,17 @@ static void curs_attr_fg(attr_t &attr, short &color_pair, int col); * Performs colour mapping for both default colours as well as the color map. * Additionally, this function takes into consideration a passed brand. * - * @param attr - * The destination for the resulting character attributes. - * @param color_pair - * The destination for the resulting color pair index. * @param fg * The internal colour for the foreground. * @param bg * The internal colour for the background. * @param brand * Internal color branding information. + * + * @return + * Returns the character attributes and colour pair index. */ -static void curs_attr_mapped(attr_t &attr, short &color_pair, COLOURS fg, - COLOURS bg, int brand); +static curses_style curs_attr_mapped(COLOURS fg, COLOURS bg, int brand); /** * @brief Returns a curses color pair index for the passed fg/bg combo. @@ -264,17 +264,15 @@ static void flip_colour(cchar_t &ch); * resulting color combination may not be a strict color swap, but one that * is guaranteed to be visible. * - * @param attr_flipped - * The location to store the resulting character attributes. - * @param color_pair_flipped - * The location to store the resulting color pair. - * @param attr_original + * @param attr * The character attributes to flip. - * @param color_pair_original + * @param color * The color pair to flip. + * + * @return + * Returns the flipped character attributes and colour pair index. */ -static void flip_colour(attr_t &attr_flipped, short &color_pair_flipped, - attr_t attr_original, short color_pair_original); +static curses_style flip_colour(curses_style style); /** * @brief Translate internal colours to flagged curses colors. @@ -305,7 +303,7 @@ static void write_char_at(int y, int x, const cchar_t &ch); static bool cursor_is_enabled = true; -static unsigned int convert_to_curses_attr(int chattr) +static unsigned int convert_to_curses_style(int chattr) { switch (chattr & CHATTR_ATTRMASK) { @@ -898,11 +896,11 @@ static inline unsigned get_brand(int col) } // see declaration -static void curs_attr(attr_t &attr, short &color_pair, COLOURS fg, COLOURS bg, - bool adjust_background) +static curses_style curs_attr(COLOURS fg, COLOURS bg, bool adjust_background) { - attr_t flags = 0; - short temp_color_pair = 0; + curses_style style; + style.attr = 0; + style.color_pair = 0; bool monochrome_output_requested = curs_palette_size() == 0; // Convert over to curses colors. @@ -916,10 +914,10 @@ static void curs_attr(attr_t &attr, short &color_pair, COLOURS fg, COLOURS bg, if (!monochrome_output_requested) { // Grab the color pair. - temp_color_pair = curs_calc_pair_safe(fg_curses, bg_curses); + style.color_pair = curs_calc_pair_safe(fg_curses, bg_curses); // Request decolorize if the pair doesn't actually exist. - if (temp_color_pair == 0 + if (style.color_pair == 0 && !curs_color_combo_has_pair(fg_curses, bg_curses)) { monochrome_output_requested = true; @@ -934,7 +932,7 @@ static void curs_attr(attr_t &attr, short &color_pair, COLOURS fg, COLOURS bg, && (Options.bold_brightens_foreground || Options.best_effort_brighten_foreground)) { - flags |= WA_BOLD; + style.attr |= WA_BOLD; } // curses typically uses WA_BLINK to give bright background colour, @@ -943,7 +941,7 @@ static void curs_attr(attr_t &attr, short &color_pair, COLOURS fg, COLOURS bg, && (Options.blink_brightens_background || Options.best_effort_brighten_background)) { - flags |= WA_BLINK; + style.attr |= WA_BLINK; } } @@ -951,46 +949,41 @@ static void curs_attr(attr_t &attr, short &color_pair, COLOURS fg, COLOURS bg, { // Decolorize the output if necessary. if (curs_palette_size() != 0) - temp_color_pair = curs_calc_pair_safe(COLOR_WHITE, COLOR_BLACK); + style.color_pair = curs_calc_pair_safe(COLOR_WHITE, COLOR_BLACK); // Do the best we can for backgrounds with monochrome output. if (bg_curses != COLOR_BLACK) - flags |= WA_REVERSE; + style.attr |= WA_REVERSE; } - // Got everything we need -- write out the results. - color_pair = temp_color_pair; - attr = flags; + return style; } // see declaration -static void curs_attr_bg(attr_t &attr, short &color_pair, int col) +static curses_style curs_attr_bg(int col) { BG_COL = static_cast(col & 0x00ff); - curs_attr_mapped(attr, color_pair, FG_COL, BG_COL, get_brand(col)); + return curs_attr_mapped(FG_COL, BG_COL, get_brand(col)); } // see declaration -static void curs_attr_fg(attr_t &attr, short &color_pair, int col) +static curses_style curs_attr_fg(int col) { FG_COL = static_cast(col & 0x00ff); - curs_attr_mapped(attr, color_pair, FG_COL, BG_COL, get_brand(col)); + return curs_attr_mapped(FG_COL, BG_COL, get_brand(col)); } // see declaration -static void curs_attr_mapped(attr_t &attr, short &color_pair, COLOURS fg, - COLOURS bg, int brand) +static curses_style curs_attr_mapped(COLOURS fg, COLOURS bg, int brand) { COLOURS fg_mod = fg; COLOURS bg_mod = bg; attr_t flags = 0; - attr_t temp_attr = 0; - short temp_color_pair = 0; // calculate which curses flags we need... if (brand != CHATTR_NORMAL) { - flags |= convert_to_curses_attr(brand); + flags |= convert_to_curses_style(brand); // Allow highlights to override the current background color. if ((brand & CHATTR_ATTRMASK) == CHATTR_HILITE) @@ -1014,16 +1007,14 @@ static void curs_attr_mapped(attr_t &attr, short &color_pair, COLOURS fg, bg_mod = BLACK; // Done with color mapping; get the resulting attributes. - curs_attr(temp_attr, temp_color_pair, fg_mod, bg_mod); - temp_attr |= flags; + curses_style ret = curs_attr(fg_mod, bg_mod); + ret.attr |= flags; // Reverse color manually to ensure correct brightening attrs. if ((brand & CHATTR_ATTRMASK) == CHATTR_REVERSE) - flip_colour(temp_attr, temp_color_pair, temp_attr, temp_color_pair); + return flip_colour(ret); - // Write out the results. - color_pair = temp_color_pair; - attr = temp_attr; + return ret; } // see declaration @@ -1364,10 +1355,8 @@ static COLOURS curses_color_to_internal_colour(short col) void textcolour(int col) { - attr_t attr = 0; - short color_pair = 0; - curs_attr_fg(attr, color_pair, col); - attr_set(attr, color_pair, nullptr); + const auto style = curs_attr_fg(col); + attr_set(style.attr, style.color_pair, nullptr); #ifdef USE_TILE_WEB tiles.textcolour(col); @@ -1376,10 +1365,8 @@ void textcolour(int col) void textbackground(int col) { - attr_t attr = 0; - short color_pair = 0; - curs_attr_bg(attr, color_pair, col); - attr_set(attr, color_pair, nullptr); + const auto style = curs_attr_bg(col); + attr_set(style.attr, style.color_pair, nullptr); #ifdef USE_TILE_WEB tiles.textbackground(col); @@ -1445,28 +1432,24 @@ static void flip_colour(cchar_t &ch) wch = new wchar_t[chars_to_allocate]; // Good to go. Grab the color / attr info. - getcchar(&ch, wch, &attr, &color_pair, nullptr); - - // Pass along to the more generic function for the heavy lifting. - flip_colour(attr, color_pair, attr, color_pair); + curses_style style; + getcchar(&ch, wch, &style.attr, &style.color_pair, nullptr); + style = flip_colour(style); // Assign the new, reversed info and clean up. - setcchar(&ch, wch, attr, color_pair, nullptr); + setcchar(&ch, wch, style.attr, style.color_pair, nullptr); if (chars_to_allocate > 0) delete [] wch; } // see declaration -void flip_colour(attr_t &attr_flipped, short &color_pair_flipped, - attr_t attr_original, short color_pair_original) +static curses_style flip_colour(curses_style style) { short fg = COLOR_WHITE; short bg = COLOR_BLACK; - attr_t temp_attr = attr_original; - short temp_color_pair = color_pair_original; - if (color_pair_original != 0) - pair_content(color_pair_original, &fg, &bg); + if (style.color_pair != 0) + pair_content(style.color_pair, &fg, &bg); else { // Default pair; use the current default colors. @@ -1480,22 +1463,21 @@ void flip_colour(attr_t &attr_flipped, short &color_pair_flipped, if (!curs_can_use_extended_colors()) { // Check if these were brightened colours. - if (temp_attr & WA_BOLD) + if (style.attr & WA_BOLD) fg |= COLFLAG_CURSES_BRIGHTEN; - if (temp_attr & WA_BLINK) + if (style.attr & WA_BLINK) bg |= COLFLAG_CURSES_BRIGHTEN; - temp_attr &= ~(WA_BOLD | WA_BLINK); + style.attr &= ~(WA_BOLD | WA_BLINK); } if (!need_attribute_only_flip) { // Perform a flip using the inverse color pair, preferring to adjust // the background color in case of a conflict. - attr_t brightness_attr; - curs_attr(brightness_attr, temp_color_pair, - curses_color_to_internal_colour(bg), - curses_color_to_internal_colour(fg), true); - temp_attr |= brightness_attr; + const auto out = curs_attr(curses_color_to_internal_colour(bg), + curses_color_to_internal_colour(fg), true); + style.color_pair = out.color_pair; + style.attr |= out.attr; } else { @@ -1508,26 +1490,20 @@ void flip_colour(attr_t &attr_flipped, short &color_pair_flipped, && (Options.blink_brightens_background || Options.best_effort_brighten_background)) { - temp_attr |= WA_BLINK; + style.attr |= WA_BLINK; } if ((bg & COLFLAG_CURSES_BRIGHTEN) && (Options.bold_brightens_foreground || Options.best_effort_brighten_foreground)) { - temp_attr |= WA_BOLD; + style.attr |= WA_BOLD; } } - // Toggle the reverse video bit. - if (temp_attr & WA_REVERSE) - temp_attr &= ~WA_REVERSE; - else - temp_attr |= WA_REVERSE; + style.attr ^= WA_REVERSE; } - // Write out the results. - color_pair_flipped = temp_color_pair; - attr_flipped = temp_attr; + return style; } void fakecursorxy(int x, int y) From 6844edd79dc0e33c6d30a07fb60e10bb4ca7959c Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Tue, 1 Oct 2019 02:57:31 +0800 Subject: [PATCH 729/864] Fix difficult-to-read main menu labels on console (advil) Menu labels previously relied on libunix.cc's adjustment of identical foreground and background colours, which didn't work properly with allow_extended_colours = true, since white and lightgrey are not identical. This commit manually adjusts all button label colours on focus change, both foreground and background. This fixes a bug on the weapon selection menu on console where the background did not extend under the listed aptitudes, due to them being in a separate text widget. It also cleans up the hacky code that was previously used to recolour the buttons. You can specify the foreground colour to use when focused; the default is black. This code assumes that all text widgets have a single colour, and will not correctly restore multi-coloured text on unfocus. --- crawl-ref/source/outer-menu.cc | 63 ++++++++++++++++++---------------- crawl-ref/source/outer-menu.h | 10 +++++- 2 files changed, 43 insertions(+), 30 deletions(-) diff --git a/crawl-ref/source/outer-menu.cc b/crawl-ref/source/outer-menu.cc index 0ab58fab5897..9125c8d6cbc4 100644 --- a/crawl-ref/source/outer-menu.cc +++ b/crawl-ref/source/outer-menu.cc @@ -50,6 +50,35 @@ void MenuButton::_allocate_region() #endif } +#ifndef USE_TILE_LOCAL +void MenuButton::recolour_descendants(const shared_ptr& node) +{ + auto tw = dynamic_pointer_cast(node); + if (tw) + { + if (focused) + { + // keep the original colour so we can restore it on unfocus + const auto& first_op = tw->get_text().ops[0]; + fg_normal = first_op.type == FSOP_COLOUR ? first_op.colour : LIGHTGREY; + } + + const colour_t fg = focused ? fg_highlight : fg_normal; + const colour_t bg = focused ? highlight_colour : BLACK; + formatted_string new_contents; + new_contents.textcolour(fg); + new_contents.cprintf("%s", tw->get_text().tostring().c_str()); + tw->set_text(move(new_contents)); + tw->set_bg_colour(static_cast(bg)); + return; + } + auto container = dynamic_pointer_cast(node); + if (container) + for (auto it = container->begin(); it != container->end(); ++it) + recolour_descendants(*it); +} +#endif + bool MenuButton::on_event(const wm_event& event) { if (Bin::on_event(event)) @@ -67,6 +96,11 @@ bool MenuButton::on_event(const wm_event& event) if (event.type == WME_FOCUSOUT) focused = false; +#ifndef USE_TILE_LOCAL + if (event.type == WME_FOCUSIN || event.type == WME_FOCUSOUT) + recolour_descendants(shared_from_this()); +#endif + #ifdef USE_TILE_LOCAL if (event.type == WME_MOUSEENTER) wm->set_mouse_cursor(MOUSE_CURSOR_POINTER); @@ -240,35 +274,6 @@ void OuterMenu::add_button(shared_ptr btn, int x, int y) } if (ev.type == WME_FOCUSIN && m_description_indexes[y*this->m_width+x] != -1) descriptions->current() = m_description_indexes[y*this->m_width+x]; -#ifndef USE_TILE_LOCAL - if (ev.type == WME_FOCUSIN || ev.type == WME_FOCUSOUT) - { - auto btn2 = this->m_buttons[y*this->m_width+x]; - Text* tw = dynamic_cast(btn2->get_child().get()); - if (!tw) - { - // TODO: very hacky: if the child is a container, - // find the first label in a container. - // This handles several cases: webtiles menus on console, - // weapon select on local console. Is there a more elegant way - // of doing this? Maybe do it for every label in the widget? - auto tw_cont = dynamic_cast( - btn2->get_child().get()); - if (tw_cont) - for (auto it = tw_cont->begin(); it != tw_cont->end(); ++it) - { - tw = dynamic_cast((*it).get()); - if (tw) - break; - } - } - if (tw) - { - tw->set_bg_colour(ev.type == WME_FOCUSIN - ? btn2->highlight_colour : BLACK); - } - } -#endif return false; }); diff --git a/crawl-ref/source/outer-menu.h b/crawl-ref/source/outer-menu.h index 27fad991d4f6..44e45ae86d2d 100644 --- a/crawl-ref/source/outer-menu.h +++ b/crawl-ref/source/outer-menu.h @@ -21,7 +21,10 @@ class MenuButton : public ui::Bin int id = 0; int hotkey = 0; - COLOURS highlight_colour = LIGHTGREY; + colour_t highlight_colour = LIGHTGREY; +#ifndef USE_TILE_LOCAL + colour_t fg_highlight = BLACK; +#endif string description; #ifdef USE_TILE_WEB @@ -36,6 +39,11 @@ class MenuButton : public ui::Bin LineBuffer m_line_buf; #endif static bool focus_on_mouse; + +#ifndef USE_TILE_LOCAL + void recolour_descendants(const shared_ptr& node); + colour_t fg_normal = LIGHTGREY; +#endif }; class OuterMenu : public ui::Widget From 940da449663301c2fc83f1eff7a0aa1f5e4f76df Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Tue, 1 Oct 2019 13:19:57 +0800 Subject: [PATCH 730/864] Tidy up some duplication and incorrect naming --- crawl-ref/source/newgame.cc | 17 ++++++++--------- crawl-ref/source/startup.cc | 4 ++-- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index a9d80256a274..385d52460ad6 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -1745,25 +1745,24 @@ static void _construct_weapon_menu(const newgame_def& ng, weapon_type wpn_type = weapons[i].first; char_choice_restriction wpn_restriction = weapons[i].second; - label->set_text(formatted_string(text, - wpn_restriction == CC_UNRESTRICTED ? WHITE : LIGHTGREY)); + + const auto fg = wpn_restriction == CC_UNRESTRICTED ? WHITE : LIGHTGREY; + const auto bg = wpn_restriction == CC_UNRESTRICTED ? + STARTUP_HIGHLIGHT_GOOD : STARTUP_HIGHLIGHT_BAD; + + label->set_text(formatted_string(text, fg)); hbox->justify_items = Widget::Align::STRETCH; string apt_text = make_stringf("(%+d apt)", species_apt(choice.skill, ng.species)); - auto suffix = make_shared(formatted_string(apt_text, - wpn_restriction == CC_UNRESTRICTED ? WHITE : LIGHTGREY)); + auto suffix = make_shared(formatted_string(apt_text, fg)); hbox->add_child(suffix); auto btn = make_shared(); btn->set_child(move(hbox)); btn->id = wpn_type; btn->hotkey = letter; - - if (wpn_restriction == CC_UNRESTRICTED) - btn->highlight_colour = STARTUP_HIGHLIGHT_GOOD; - else - btn->highlight_colour = STARTUP_HIGHLIGHT_BAD; + btn->highlight_colour = bg; // Is this item our default weapon? if (wpn_type == defweapon || (defweapon == WPN_UNKNOWN && i == 0)) diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index 8de3a854a10c..86410510a85e 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -467,10 +467,10 @@ static void _construct_save_games_menu(shared_ptr& container, hbox->add_child(move(tile)); #endif - const COLOURS bg = chars.at(i).save_loadable ? WHITE : RED; + const COLOURS fg = chars.at(i).save_loadable ? WHITE : RED; auto text = chars.at(i).short_desc(); bool wiz = strip_suffix(text, " (WIZ)"); - auto label = make_shared(formatted_string( text, bg)); + auto label = make_shared(formatted_string(text, fg)); label->ellipsize = true; #ifdef USE_TILE_LOCAL label->max_size() = { INT_MAX, (int)tiles.get_crt_font()->char_height() }; From ca5e8cfc3fefe3fa4949d6aed9f72ba5968e823c Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Tue, 1 Oct 2019 16:41:08 +0800 Subject: [PATCH 731/864] Use quads for line drawing (advil) Line drawing with GL_LINES seems to be subject to a number of rendering bugs and limitations that vary by OS and driver. This commit renders all lines with a single quad. This removes support for arbitrary lines that are not horizontal or vertical, but we don't currently draw any such lines. --- crawl-ref/source/menu.cc | 2 +- crawl-ref/source/tilebuf.cc | 14 ++++++++------ crawl-ref/source/tilebuf.h | 3 ++- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/crawl-ref/source/menu.cc b/crawl-ref/source/menu.cc index 257bdb2acbe7..e88cc8234e81 100644 --- a/crawl-ref/source/menu.cc +++ b/crawl-ref/source/menu.cc @@ -744,7 +744,7 @@ void UIMenu::pack_buffers() int line_y = entry.y + (i == 0 ? 0 : 5) + item_pad; if (i < (int)item_info.size()-1 && !item_info[i+1].heading) { - m_div_line_buf.add(entry.x, line_y, + m_div_line_buf.add_square(entry.x, line_y, entry.x+m_num_columns*col_width, line_y, header_div_colour); } m_text_buf.add(split, entry.x, line_y+3); diff --git a/crawl-ref/source/tilebuf.cc b/crawl-ref/source/tilebuf.cc index 30b75f24b6e1..df4e63e87936 100644 --- a/crawl-ref/source/tilebuf.cc +++ b/crawl-ref/source/tilebuf.cc @@ -302,7 +302,7 @@ void ShapeBuffer::add(float pos_sx, float pos_sy, float pos_ex, float pos_ey, ///////////////////////////////////////////////////////////////////////////// // LineBuffer -LineBuffer::LineBuffer() : VertBuffer(false, true, nullptr, GLW_LINES) +LineBuffer::LineBuffer() : VertBuffer(false, true, nullptr) { m_state.array_colour = true; } @@ -320,11 +320,13 @@ void LineBuffer::add_square(float sx, float sy, float ex, float ey, { GLW_3VF scale; glmanager->get_transform(nullptr, &scale); - float dx = 1.0/scale.x, dy = 1.0/scale.y; - add(sx-dx, sy, ex-dx, sy, col); - add(ex, sy-dy, ex, ey-dy, col); - add(ex, ey, sx, ey, col); - add(sx, ey, sx, sy, col); + const float dx = 1.0/scale.x, dy = 1.0/scale.y; + const float tx = dx, ty = dy; + + add(sx-dx, sy-ty, ex-dx, sy, col); + add(ex-tx, sy-dy, ex, ey-dy, col); + add(ex, ey-ty, sx, ey, col); + add(sx-tx, ey, sx, sy, col); } #endif diff --git a/crawl-ref/source/tilebuf.h b/crawl-ref/source/tilebuf.h index 6b78e04027b6..f4a256613c2e 100644 --- a/crawl-ref/source/tilebuf.h +++ b/crawl-ref/source/tilebuf.h @@ -114,6 +114,7 @@ class LineBuffer : public VertBuffer { public: LineBuffer(); - void add(float sx, float sy, float ex, float ey, const VColour &c); void add_square(float sx, float sy, float ex, float ey, const VColour &c); +private: + void add(float sx, float sy, float ex, float ey, const VColour &c); }; From 323ad4e9fb1dbb588b479de76b9c62a829cc0646 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Wed, 2 Oct 2019 02:55:26 +0800 Subject: [PATCH 732/864] Fix clinging monsters breaking autoexplore (shalmezad, 11924) Clinging monsters in vaults could pathfind their way through the runed door, and were therefore marked as not safe, preventing autoexplore. This was caused by mons_traversable() sidestepping checks for runed cells and uninhabitable cells in mons_can_traverse() if the monster can cling. I've just hoisted them out here. In addition, cell_can_cling_to() only checks physical location, and so couldn't check whether a feature is passable by a given monster. Last but not least, the call to cell_is_clingable() previously passed the wrong parameter. --- crawl-ref/source/mon-pathfind.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/mon-pathfind.cc b/crawl-ref/source/mon-pathfind.cc index 0da20a350714..cc25a6f13acb 100644 --- a/crawl-ref/source/mon-pathfind.cc +++ b/crawl-ref/source/mon-pathfind.cc @@ -433,9 +433,15 @@ bool monster_pathfind::traversable(const coord_def& p) // its preferred habit and capability of flight or opening doors. bool monster_pathfind::mons_traversable(const coord_def& p) { + if (cell_is_runed(p)) + return false; + if (!mons->is_habitable(p)) + return false; + return mons_can_traverse(*mons, p, traverse_in_sight) || mons->can_cling_to_walls() - && cell_is_clingable(pos) + && cell_is_clingable(p) + && mons->can_pass_through_feat(grd(p)) && cell_can_cling_to(pos, p); } From 4e6fe308c7ef87bfb44936b5ca61f59bea701585 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Wed, 2 Oct 2019 03:53:01 +0800 Subject: [PATCH 733/864] Fix sealed-off sensed monsters stopping travel (gammafunk) Sensed monsters were handled with a separate check that did not take into account whether they were reachable. The new way uses the list of monsters returned by get_nearby_monsters, which does test reachability. --- crawl-ref/source/nearby-danger.cc | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/crawl-ref/source/nearby-danger.cc b/crawl-ref/source/nearby-danger.cc index bd438dee0bbb..d883c0cb832a 100644 --- a/crawl-ref/source/nearby-danger.cc +++ b/crawl-ref/source/nearby-danger.cc @@ -214,15 +214,6 @@ vector get_nearby_monsters(bool want_move, return mons; } -static bool _exposed_monsters_nearby(bool want_move) -{ - const int radius = want_move ? 2 : 1; - for (radius_iterator ri(you.pos(), radius, C_SQUARE, LOS_DEFAULT); ri; ++ri) - if (env.map_knowledge(*ri).flags & MAP_INVISIBLE_MONSTER) - return true; - return false; -} - bool i_feel_safe(bool announce, bool want_move, bool just_monsters, bool check_dist, int range) { @@ -286,10 +277,19 @@ bool i_feel_safe(bool announce, bool want_move, bool just_monsters, } // Monster check. - vector visible = - get_nearby_monsters(want_move, !announce, true, true, true, + vector monsters = + get_nearby_monsters(want_move, !announce, true, true, false, check_dist, range); + vector visible; + copy_if(monsters.begin(), monsters.end(), back_inserter(visible), + [](const monster *mon){ return mon->visible_to(&you); }); + + const bool sensed_monster = any_of(monsters.begin(), monsters.end(), + [](const monster *mon){ + return env.map_knowledge(mon->pos()).flags & MAP_INVISIBLE_MONSTER; + }); + // Announce the presence of monsters (Eidolos). string msg; if (visible.size() == 1) @@ -299,7 +299,7 @@ bool i_feel_safe(bool announce, bool want_move, bool just_monsters, } else if (visible.size() > 1) msg = "There are monsters nearby!"; - else if (_exposed_monsters_nearby(want_move)) + else if (sensed_monster) msg = "There is a strange disturbance nearby!"; else return true; From 6aba9404ae88ed53487653519ac96ecb1d25da77 Mon Sep 17 00:00:00 2001 From: srvanmeter87 Date: Mon, 12 Aug 2019 07:12:10 -0400 Subject: [PATCH 734/864] Rephrase MP-powered wands player alert (#984) [Committer's note: Closes #984, #1133, #1143] --- crawl-ref/source/mutation-data.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/mutation-data.h b/crawl-ref/source/mutation-data.h index 5f87b1aaa1ae..00d30d730c15 100644 --- a/crawl-ref/source/mutation-data.h +++ b/crawl-ref/source/mutation-data.h @@ -1833,8 +1833,8 @@ static const mutation_def mut_data[] = "MP-powered wands", {"You expend magic power (3 MP) to strengthen your wands.", "", ""}, - {"You feel your magical essence link to your wands.", "", ""}, - {"Your magical essence is no longer linked to your wands.", "", ""}, + {"You feel your magical essence link to the dungeon's wands.", "", ""}, + {"Your magical essence longer links to wands of the dungeon.", "", ""}, }, { MUT_UNSKILLED, 0, 3, mutflag::bad, false, From 26e86663625bfda8737f3846fb1d710e9613cf10 Mon Sep 17 00:00:00 2001 From: theJollySin Date: Thu, 19 Sep 2019 20:40:20 -0400 Subject: [PATCH 735/864] An assortment of item and location quotations [Committer's note: Closes #1153. Squashed and revised the PR.] --- crawl-ref/source/dat/descript/quotes.txt | 39 +++++++++++++++++------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/crawl-ref/source/dat/descript/quotes.txt b/crawl-ref/source/dat/descript/quotes.txt index d427e0a74a2d..4dde8f9da541 100644 --- a/crawl-ref/source/dat/descript/quotes.txt +++ b/crawl-ref/source/dat/descript/quotes.txt @@ -238,7 +238,8 @@ A staircase to the Shoals %%%% A staircase to the Tomb - +“A tomb now suffices him for whom the world was not enough.” + -Alexander the Great's epitaph %%%% A stormy altar of Qazlal @@ -1512,7 +1513,9 @@ hand axe %%%% hand crossbow - +“Energy may be likened to the bending of a crossbow; + decision, to the releasing of a trigger.” + -Sun Tzu %%%% harpy @@ -1806,7 +1809,8 @@ hee most desireth.” %%%% manual - +“Manuals have their uses... but they are not to be confused with living.” + -Robert Fulghum %%%% merfolk @@ -2338,15 +2342,20 @@ see rightly; what is essential is invisible to the eye.” %%%% ring of slaying - +“Life is too short to occupy oneself with the slaying of the slain more than + once.” + -Thomas Huxley %%%% ring of strength - +“That which does not kill us makes us stronger.” + -Friedrich Nietzsche %%%% ring of stealth - +“No one ever approaches perfection except by stealth, and unknown to + themselves.” + -William Hazlitt %%%% ring of teleportation @@ -2414,7 +2423,8 @@ scroll of acquirement %%%% scroll of amnesia - +“But revenge is hollow. I'd prefer amnesia.” + -Tera Lynn Childs %%%% scroll of blinking @@ -2434,7 +2444,9 @@ scroll of enchant weapon %%%% scroll of fear - +“We can easily forgive a child who is afraid of the dark; +the real tragedy of life is when men are afraid of the light.” + -Plato %%%% scroll of fog @@ -2442,7 +2454,9 @@ scroll of fog %%%% scroll of holy word - +“However many holy words you read, however many you speak, +what good will they do you if you do not act on upon them?” + -Gautama Buddha %%%% scroll of identify @@ -2483,7 +2497,9 @@ scroll of silence %%%% scroll of summoning - +“When thou attended gloriously from heaven , Shalt in the sky appear, and from + thee send Thy summoning archangels to proclaim Thy dread tribunal.” + -John Milton %%%% scroll of teleportation @@ -2579,7 +2595,8 @@ shapeshifter %%%% shield - +“...for the shield may be as important for victory, as the sword or spear.” + -Charles Darwin, “The Origin of Species”. 1859. %%%% shortbow From 463e12031983a7015043a87cb737adc6c8a00811 Mon Sep 17 00:00:00 2001 From: theJollySin Date: Sat, 21 Sep 2019 16:41:59 -0400 Subject: [PATCH 736/864] Clean up Paradise Lost quote citations --- crawl-ref/source/dat/descript/quotes.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crawl-ref/source/dat/descript/quotes.txt b/crawl-ref/source/dat/descript/quotes.txt index 4dde8f9da541..a168571b9924 100644 --- a/crawl-ref/source/dat/descript/quotes.txt +++ b/crawl-ref/source/dat/descript/quotes.txt @@ -1540,7 +1540,7 @@ hell hound If aught disturbed their noise, into her womb, And kennel there; yet there still barked and howled Within unseen.” - -John Milton, _Paradise Lost_, Book II, l. 653-659. 1667. + -John Milton, _Paradise Lost_, Book II, 1667. %%%% hell knight @@ -1630,7 +1630,7 @@ insubstantial wisp Misleads th' amaz'd Night-wanderer from his way To Boggs and Mires, and oft through Pond or Poole, There swallow'd up and lost, from succour farr.” - -John Milton, _Paradise Lost_ + -John Milton, _Paradise Lost_, Book IX, 1667. %%%% Iskenderun's Battlesphere spell @@ -2054,7 +2054,7 @@ pandemonium lord A solemn Councel forthwith to be held At Pandaemonium, the high Capital Of Satan and his Peers...” - -John Milton, _Paradise Lost_, Book I, l. 752-7. 1667. + -John Milton, _Paradise Lost_, Book I, 1667. %%%% Passwall spell @@ -2497,9 +2497,9 @@ scroll of silence %%%% scroll of summoning -“When thou attended gloriously from heaven , Shalt in the sky appear, and from +“When thou attended gloriously from heaven, Shalt in the sky appear, and from thee send Thy summoning archangels to proclaim Thy dread tribunal.” - -John Milton + -John Milton, _Paradise Lost_, Book III, 1667. %%%% scroll of teleportation From ebba34edf6e2f9acf708a7de90d351237e0ced17 Mon Sep 17 00:00:00 2001 From: theJollySin Date: Tue, 1 Oct 2019 20:22:40 -0400 Subject: [PATCH 737/864] Add more random uselessness messages [Committer's note: Closes #1161. Removed messages that suggested some in-game happening or portal vault. Random uselessness is for flavor, we don't want it to intentionally confuse. Squashed and re-organized the PR into this and the next two commits.] --- crawl-ref/source/dat/database/miscname.txt | 70 +++++++++++++++++++++- 1 file changed, 67 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/dat/database/miscname.txt b/crawl-ref/source/dat/database/miscname.txt index 929c4044c808..dc27c61102ee 100644 --- a/crawl-ref/source/dat/database/miscname.txt +++ b/crawl-ref/source/dat/database/miscname.txt @@ -19,6 +19,10 @@ dull faint +gleaming + +luminous + mottled pale @@ -112,31 +116,65 @@ glowing_colour_name # random uselessness: "You smell XXX." smell_name +a campfire + +a dewy forest on a spring morning + baking bread +bat guano + burning hair +cherry blossoms + +clean mountain air + coffee dragon dung fire and brimstone +halfling feet + +honeysuckles + +lavender + +leather and polished metal + +meat roasting over an open fire + mustard pepper +pipe weed + +roast spriggan + +rotten fruit + +rotten potatoes + salt something weird sulphur +sweaty leather boots + tea -the scent of fear +the stench of fear + +wet warg wet wool + +wet yak %%%% # This doesn't necessarily have to make sense. For example, a name of a # fruit or an insect will work here. @@ -144,23 +182,45 @@ _roaring_animal_name_ albino dragon +centaur + +dwarf + dragon eggplant frog +gnoll + +grizzly bear + human +komodo dragon + +kobold + millipede +ogre + +orc + pill bug +polar bear + slug +troll + wumpus yak + +yaktaur %%%% # random uselessness: "You hear XXX." sound_name @@ -177,19 +237,23 @@ a very strange noise indeed a voice calling someone else's name +a witch cackle + roaring flames snatches of song -the distant roaring of an enraged @_roaring_animal_name_@ the chiming of a distant gong +the distant roaring of an enraged @_roaring_animal_name_@ + +the ringing of an enormous bell + the sound of one hand clapping the tinkle of a tiny bell -the ringing of an enormous bell whispers in an ancient language From 7e681d2d235920210b849ac40f81a1a6a219e564 Mon Sep 17 00:00:00 2001 From: theJollySin Date: Tue, 1 Oct 2019 20:07:02 -0400 Subject: [PATCH 738/864] Vary orb descriptors in the welcome text --- crawl-ref/source/dat/database/miscname.txt | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/dat/database/miscname.txt b/crawl-ref/source/dat/database/miscname.txt index dc27c61102ee..fbee315a0823 100644 --- a/crawl-ref/source/dat/database/miscname.txt +++ b/crawl-ref/source/dat/database/miscname.txt @@ -320,13 +320,26 @@ Seething terrors besiege your sanity! Lucidity slithers from your feeble grasp. %%%% +# How great is the Orb of Zot? +_great_adj_ + +awesome + +fabled + +fabulous + +legendary + +transcendent +%%%% welcome_spam Will you prevail where others failed? Will you find the Orb of Zot? -The bosom of this dungeon contains the fabled artefact, the Orb of Zot. +The bosom of this dungeon contains the @_great_adj_@ artefact, the Orb of Zot. -Will you be the one to retrieve the fabulous Orb of Zot from the depths? +Will you be the one to retrieve the @_great_adj_@ Orb of Zot from the depths? It is said that the Orb of Zot exists deep within this dungeon. %%%% From 8abc0672763f909576597b824e095118da2cb5f2 Mon Sep 17 00:00:00 2001 From: theJollySin Date: Tue, 1 Oct 2019 20:07:38 -0400 Subject: [PATCH 739/864] Add more flavour to the Halloween welcome spam --- crawl-ref/source/dat/database/miscname.txt | 28 ++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/dat/database/miscname.txt b/crawl-ref/source/dat/database/miscname.txt index fbee315a0823..24c219f6efdc 100644 --- a/crawl-ref/source/dat/database/miscname.txt +++ b/crawl-ref/source/dat/database/miscname.txt @@ -343,6 +343,30 @@ Will you be the one to retrieve the @_great_adj_@ Orb of Zot from the depths? It is said that the Orb of Zot exists deep within this dungeon. %%%% +# things that surround us on Halloween +_halloween_things_ + +demonic hallucinations + +disembodied spirits + +ghosts and spectres + +grim specetres + +horrible apparitions +%%%% +# things you don't want a witch to turn you into +_lowly_ + +newt + +slug + +toad + +worm +%%%% welcome_spam Halloween @welcome_spam@ Be careful! Halloween tonight. @@ -351,9 +375,9 @@ The monsters here aren't big trick-or-treat fans. If they won't give you the Orb A terrible geas has sent you after the Orb of Zot. What a horrible night to have a curse! -As you descend in search of the Orb, ghosts and spectres flock about you. This place is haunted! +As you descend in search of the Orb, @_halloween_things_@ flock about you. This place is haunted! -You hear a witch cackle, and suddenly arrive in the dungeon. If you don't find the Orb of Zot, you'll turn into a toad! +You hear a witch cackle, and suddenly arrive in the dungeon. If you don't find the Orb of Zot, you'll turn into a @_lowly_@! %%%% hell_effect_quiet From f6d4cf8133645657a12f30876c19a1e0f73b11ef Mon Sep 17 00:00:00 2001 From: NormalPerson7 Date: Sat, 26 Jan 2019 21:55:07 +0000 Subject: [PATCH 740/864] Remove troves asking for scrolls of identify Beyond the early game, once almost all the potions and scrolls in the game are identified, scrolls of identify become a convenience tool more than anything else; it is simply easier and faster for the player to identify this unknown ring on the floor using a scroll than to find something to drop, pick the ring up, put it on, decide it's useless, drop it, and pick up the other thing. This especially applies when the player has 5+ spare identify scrolls in their inventory, which is fairly common around the time of Vaults and Depths. Troves asking for identify scrolls encourages players to employ the tedious second behaviour, and to some extent take risks with wear-identifying artefacts, in order to horde the scrolls and eventually enter the trove. Additionally, being reduced to 0 identify scrolls by a trove hardly makes a significant difference to the strength of a character - rather it simply means once again that the tedious wear-identification process is required. Note that the wear-identification of artefacts that is encouraged by this isn't particularly dangerous beyond the early game anyway. The only bad effects are *Drain and *Contam, where *Drain is unlikely to have a significant impact, and *Contam may cause 1 malmutate before wearing off that the player can probably eliminate by using a mutation potion. Hence, remove troves asking for scrolls of identify, because they encouraged tedious behaviour instead of meaningful decision making. --- crawl-ref/source/dat/des/portals/trove.des | 1 - 1 file changed, 1 deletion(-) diff --git a/crawl-ref/source/dat/des/portals/trove.des b/crawl-ref/source/dat/des/portals/trove.des index dc9875e0f878..c9e03e7f2b69 100644 --- a/crawl-ref/source/dat/des/portals/trove.des +++ b/crawl-ref/source/dat/des/portals/trove.des @@ -97,7 +97,6 @@ function trove.get_trove_item(e, value, base_item) -- currently 20% armour, 15% weapon, 50% consumable, 15% miscellaneous local prices = { {base="scroll", type="acquirement", quant=2}, - {base="scroll", type="identify", quant=12+d(4)+d(4)+d(4)}, {base="miscellaneous", type="rune of Zot", quant=3, name="slimy rune of Zot"}, {base="miscellaneous", type="rune of Zot", quant=11, name="abyssal rune of Zot"}, {base="miscellaneous", type="horn of Geryon"} } From 42da65fd27e7e32d0deeb2066a8398ad66e5a0c4 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Tue, 1 Oct 2019 21:14:57 -0400 Subject: [PATCH 741/864] De-randomize Golden Eye confusion spellpower This random power is a legacy dating back to their creation. The commit log doesn't describe why Confusion Gaze should work this way instead of with a normal confuse spellpower and a normal MR check. Now that monster spell success chance is displayed, this randomization had the side effect of making the success chance display wrong. Confusion Gaze was the last monster spell with monster spellpower randomization; this commit cleans up some of the code, but there is a larger refactor possible that is left undone. Closes #1160 --- crawl-ref/source/describe-spells.cc | 2 +- crawl-ref/source/describe.cc | 2 +- crawl-ref/source/mon-cast.cc | 17 +++++------------ crawl-ref/source/mon-cast.h | 2 +- crawl-ref/source/util/monster/monster-main.cc | 2 +- 5 files changed, 9 insertions(+), 16 deletions(-) diff --git a/crawl-ref/source/describe-spells.cc b/crawl-ref/source/describe-spells.cc index 56006d3e91c5..369368f4e777 100644 --- a/crawl-ref/source/describe-spells.cc +++ b/crawl-ref/source/describe-spells.cc @@ -469,7 +469,7 @@ vector> map_chars_to_spells(const spellset &spells, static string _range_string(const spell_type &spell, const monster_info *mon_owner, int hd) { auto flags = get_spell_flags(spell); - int pow = mons_power_for_hd(spell, hd, false); + int pow = mons_power_for_hd(spell, hd); int range = spell_range(spell, pow, false); const bool has_range = mon_owner && range > 0 diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index f086cef30e5b..436d50b56436 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -2911,7 +2911,7 @@ string get_skill_description(skill_type skill, bool need_title) static int _hex_pow(const spell_type spell, const int hd) { const int cap = 200; - const int pow = mons_power_for_hd(spell, hd, false) / ENCH_POW_FACTOR; + const int pow = mons_power_for_hd(spell, hd) / ENCH_POW_FACTOR; return min(cap, pow); } diff --git a/crawl-ref/source/mon-cast.cc b/crawl-ref/source/mon-cast.cc index 47971ed6459f..43a83f5dc5b9 100644 --- a/crawl-ref/source/mon-cast.cc +++ b/crawl-ref/source/mon-cast.cc @@ -1048,16 +1048,13 @@ static bool _set_hex_target(monster* caster, bolt& pbolt) * What value do monsters multiply their hd with to get spellpower, for the * given spell? * - * XXX: everything except SPELL_CONFUSION_GAZE could be trivially exported to - * data. + * XXX: everything could be trivially exported to data. * * @param spell The spell in question. - * @param random Whether to randomize powers for weird spells. - * If false, the average value is used. * @return A multiplier to HD for spellpower. * Value may exceed 200. */ -static int _mons_power_hd_factor(spell_type spell, bool random) +static int _mons_power_hd_factor(spell_type spell) { const mons_spell_logic* logic = map_find(spell_to_logic, spell); if (logic && logic->power_hd_factor) @@ -1066,9 +1063,7 @@ static int _mons_power_hd_factor(spell_type spell, bool random) switch (spell) { case SPELL_CONFUSION_GAZE: - if (random) - return 5 * (2 + random2(3)) * ENCH_POW_FACTOR; - return 5 * (2 + 1) * ENCH_POW_FACTOR; + return 8 * ENCH_POW_FACTOR; case SPELL_CAUSE_FEAR: return 18 * ENCH_POW_FACTOR; @@ -1116,13 +1111,11 @@ static int _mons_power_hd_factor(spell_type spell, bool random) * * @param spell The spell in question. * @param hd The spell_hd of the given monster. - * @param random Whether to randomize powers for weird spells. - * If false, the average value is used. * @return A spellpower value for the spell. */ -int mons_power_for_hd(spell_type spell, int hd, bool random) +int mons_power_for_hd(spell_type spell, int hd) { - const int power = hd * _mons_power_hd_factor(spell, random); + const int power = hd * _mons_power_hd_factor(spell); if (spell == SPELL_PAIN) return max(50 * ENCH_POW_FACTOR, power); return power; diff --git a/crawl-ref/source/mon-cast.h b/crawl-ref/source/mon-cast.h index f608e154703d..660b6d08f6a5 100644 --- a/crawl-ref/source/mon-cast.h +++ b/crawl-ref/source/mon-cast.h @@ -27,7 +27,7 @@ void flay(const monster &caster, actor &defender, int damage); bool handle_mon_spell(monster* mons); static const int ENCH_POW_FACTOR = 3; -int mons_power_for_hd(spell_type spell, int hd, bool random = true); +int mons_power_for_hd(spell_type spell, int hd); int mons_spellpower(const monster &mons, spell_type spell); int mons_spell_range_for_hd(spell_type spell, int hd); bolt mons_spell_beam(const monster* mons, spell_type spell_cast, int power, diff --git a/crawl-ref/source/util/monster/monster-main.cc b/crawl-ref/source/util/monster/monster-main.cc index 14a63b142a95..1b246386f164 100644 --- a/crawl-ref/source/util/monster/monster-main.cc +++ b/crawl-ref/source/util/monster/monster-main.cc @@ -346,7 +346,7 @@ static string mons_human_readable_spell_damage_string(monster* monster, spell_type sp) { bolt spell_beam = mons_spell_beam( - monster, sp, mons_power_for_hd(sp, monster->spell_hd(sp), false), true); + monster, sp, mons_power_for_hd(sp, monster->spell_hd(sp)), true); switch (sp) { case SPELL_PORTAL_PROJECTILE: From 3348362083ca7e9968c8929f581d998b843b2a2e Mon Sep 17 00:00:00 2001 From: Richard Wardin Date: Tue, 1 Oct 2019 19:30:23 -0400 Subject: [PATCH 742/864] Fix being able to pick out barbs while incapacitated (12065) Carefully pulling out barbs now requires that you can move (not paralyzed or petrified), aren't confused, and aren't asleep. [Committer's note: Closes #1162. Tweaked berserk message.] --- crawl-ref/source/player-reacts.cc | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/player-reacts.cc b/crawl-ref/source/player-reacts.cc index 1cd4aabd55eb..0b35f872090c 100644 --- a/crawl-ref/source/player-reacts.cc +++ b/crawl-ref/source/player-reacts.cc @@ -829,8 +829,15 @@ static void _decrement_durations() doom_howl(min(delay, you.duration[DUR_DOOM_HOWL])); dec_elixir_player(delay); - extract_manticore_spikes("You carefully extract the barbed spikes from " - "your body."); + + if (!you.cannot_move() + && !you.confused() + && !you.asleep()) + { + extract_manticore_spikes( + make_stringf("You %s the barbed spikes from your body.", + you.berserk() ? "rip and tear" : "carefully extract").c_str()); + } if (!env.sunlight.empty()) process_sunlights(); From 0b10f196a578c2a7ba9ec61cf6894d4001ce00f4 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Sun, 8 Sep 2019 23:48:54 -0500 Subject: [PATCH 743/864] Fedhas rework part 1: piety gain Fedhas is a plant-themed god originally intended to support range combat. The god gives you plant allies that you can move and fire through allows you to create water to impede monster movement. Unfortunately the current design gives access to too many allies that are strong enough to carry the player through much of the game. These are either permanent or long-lived yet are stationary or have movement limitations, things that together encourage the player to lure monsters to specific locations. As a result, Fedhas has a tedious play-style, and this is reflected in the god's usage rate among players. This commit is the first in a set that rework the god but in a way that retains some of idea of supporting ranged combat. New Fedhas will use only summoned allies and will allow less unfettered use of allies in general. A github wiki page describing remaining and potential issues with the rework is available here: https://github.com/crawl/crawl/wiki/Fedhas-Rework Part 1 removes Fedhas' appreciation of corpse decay as well as the Fungal Bloom ability. I haven't touched the corpse violation, necromancy conducts, and species restrictions for now, although those all need addressing. --- crawl-ref/source/ability-type.h | 1 - crawl-ref/source/ability.cc | 6 - crawl-ref/source/conduct-type.h | 1 - crawl-ref/source/dat/descript/ability.txt | 8 - crawl-ref/source/dat/descript/gods.txt | 8 +- crawl-ref/source/files.cc | 45 --- crawl-ref/source/god-abil.cc | 362 ------------------ crawl-ref/source/god-abil.h | 1 - crawl-ref/source/god-conduct.cc | 15 +- crawl-ref/source/religion.cc | 1 - crawl-ref/source/rltiles/dc-invocations.txt | 1 - .../gui/invocations/fedhas_fungal_bloom.png | Bin 869 -> 0 bytes crawl-ref/source/rot.cc | 4 - crawl-ref/source/tilepick.cc | 2 - 14 files changed, 11 insertions(+), 444 deletions(-) delete mode 100644 crawl-ref/source/rltiles/gui/invocations/fedhas_fungal_bloom.png diff --git a/crawl-ref/source/ability-type.h b/crawl-ref/source/ability-type.h index f46a4b4d81ee..1b46b002f927 100644 --- a/crawl-ref/source/ability-type.h +++ b/crawl-ref/source/ability-type.h @@ -178,7 +178,6 @@ enum ability_type ABIL_FEDHAS_PLANT_RING, ABIL_FEDHAS_SPAWN_SPORES, ABIL_FEDHAS_EVOLUTION, - ABIL_FEDHAS_FUNGAL_BLOOM, // Cheibriados ABIL_CHEIBRIADOS_TIME_STEP = 1151, ABIL_CHEIBRIADOS_TIME_BEND, diff --git a/crawl-ref/source/ability.cc b/crawl-ref/source/ability.cc index f4e2d3bf3a50..f41911efe7de 100644 --- a/crawl-ref/source/ability.cc +++ b/crawl-ref/source/ability.cc @@ -514,8 +514,6 @@ static const ability_def Ability_List[] = 0, 0, 0, 15, {fail_basis::invo}, abflag::none }, // Fedhas - { ABIL_FEDHAS_FUNGAL_BLOOM, "Fungal Bloom", - 0, 0, 0, 0, {fail_basis::invo}, abflag::none }, { ABIL_FEDHAS_SUNLIGHT, "Sunlight", 2, 0, 50, 0, {fail_basis::invo, 30, 6, 20}, abflag::none }, { ABIL_FEDHAS_EVOLUTION, "Evolution", @@ -2864,10 +2862,6 @@ static spret _do_ability(const ability_def& abil, bool fail) end_recall(); break; - case ABIL_FEDHAS_FUNGAL_BLOOM: - fedhas_fungal_bloom(); - return spret::success; - case ABIL_FEDHAS_SUNLIGHT: return fedhas_sunlight(fail); diff --git a/crawl-ref/source/conduct-type.h b/crawl-ref/source/conduct-type.h index f52462dbbb0b..e78c855984b8 100644 --- a/crawl-ref/source/conduct-type.h +++ b/crawl-ref/source/conduct-type.h @@ -35,7 +35,6 @@ enum conduct_type DID_HASTY, // Cheibriados DID_CORPSE_VIOLATION, // Fedhas (Necromancy involving // corpses/chunks). - DID_ROT_CARRION, // Fedhas (a corpse rotted) DID_SOULED_FRIEND_DIED, // Zin DID_ATTACK_IN_SANCTUARY, // Zin DID_KILL_NONLIVING, diff --git a/crawl-ref/source/dat/descript/ability.txt b/crawl-ref/source/dat/descript/ability.txt index 947336f135b2..584089fff82f 100644 --- a/crawl-ref/source/dat/descript/ability.txt +++ b/crawl-ref/source/dat/descript/ability.txt @@ -481,14 +481,6 @@ Bring an orc corpse back to life. The orc will be an ally, even if it was not already one before it died. %%%% # Fedhas -Fungal Bloom ability - -Call up Fedhas to accelerate the natural process of decay, transforming all -corpses nearby into fast-growing, short-lived toadstools. Zombies, ghouls, -and necrophages are considered walking corpses, and are affected accordingly; -zombies rot into skeletons, and ghouls and necrophages rot away entirely, -granting no experience. -%%%% Sunlight ability Calls sunlight down over a small area of the dungeon. Monsters illuminated by diff --git a/crawl-ref/source/dat/descript/gods.txt b/crawl-ref/source/dat/descript/gods.txt index 23fdc3888080..bfaea933b3e8 100644 --- a/crawl-ref/source/dat/descript/gods.txt +++ b/crawl-ref/source/dat/descript/gods.txt @@ -44,11 +44,9 @@ followers can convert to the Shining One or Zin while keeping some piety. %%%% Fedhas -The god of plant and fungal life, Fedhas Madash demands that followers -encourage the decomposition of corpses. Fedhas also forbids followers from -harming any species under Fedhas' protection, and from using any necromantic -effects that interfere with corpses. In return Fedhas grants a number of -abilities that promote the growth of plants and fungi. These abilities may +Fedhas is the god of plant and fungal life. Followers are forbidden from +harming any species under Fedhas' protection. In return Fedhas grants a number +of abilities that promote the growth of plants and fungi. These abilities may incidentally prove useful to adventurers. %%%% Gozag diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 6b3377b773b7..4d1173934dc7 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -29,7 +29,6 @@ #include "act-iter.h" #include "areas.h" #include "branch.h" -#include "butcher.h" // for fedhas_rot_all_corpses #include "chardump.h" #include "cloud.h" #include "coordit.h" @@ -45,7 +44,6 @@ #include "food.h" //for HUNGER_MAXIMUM #include "ghost.h" #include "god-abil.h" -#include "god-conduct.h" // for fedhas_rot_all_corpses #include "god-companions.h" #include "god-passive.h" #include "hints.h" @@ -70,7 +68,6 @@ #include "species.h" #include "spl-summoning.h" #include "stairs.h" -#include "stash.h" // for fedhas_rot_all_corpses #include "state.h" #include "stringutil.h" #include "syscalls.h" @@ -1130,45 +1127,6 @@ static void _do_lost_items() item_was_lost(item); } -/// Rot all corpses remaining on the level, giving Fedhas piety for doing so. -static void _fedhas_rot_all_corpses(const level_id& old_level) -{ - bool messaged = false; - for (size_t mitm_index = 0; mitm_index < mitm.size(); ++mitm_index) - { - item_def &item = mitm[mitm_index]; - if (!item.defined() - || !item.is_type(OBJ_CORPSES, CORPSE_BODY) - || item.props.exists(CORPSE_NEVER_DECAYS)) - { - continue; - } - - if (mons_skeleton(item.mon_type)) - ASSERT(turn_corpse_into_skeleton(item)); - else - { - item_was_destroyed(item); - destroy_item(mitm_index); - } - - if (!messaged) - { - simple_god_message("'s fungi set to work."); - messaged = true; - } - - const int piety = x_chance_in_y(2, 5) ? 2 : 1; // match fungal_bloom() - // XXX: deduplicate above ^ - did_god_conduct(DID_ROT_CARRION, piety); - } - - // assumption: CORPSE_NEVER_DECAYS is never set for seen corpses - LevelStashes *ls = StashTrack.find_level(old_level); - if (ls) // assert? - ls->rot_all_corpses(); -} - /** * Perform cleanup when leaving a level. * @@ -1187,9 +1145,6 @@ static bool _leave_level(dungeon_feature_type stair_taken, { bool popped = false; - if (you.religion == GOD_FEDHAS) - _fedhas_rot_all_corpses(old_level); - if (!you.level_stack.empty() && you.level_stack.back().id == level_id::current()) { diff --git a/crawl-ref/source/god-abil.cc b/crawl-ref/source/god-abil.cc index 6bdbe2ebe298..f971fe25c8d7 100644 --- a/crawl-ref/source/god-abil.cc +++ b/crawl-ref/source/god-abil.cc @@ -2173,368 +2173,6 @@ void collect_radius_points(vector > &radius_points, } } -static int _mushroom_prob(item_def & corpse) -{ - int low_threshold = 5; - int high_threshold = FRESHEST_CORPSE - 5; - - // Expect this many trials over a corpse's lifetime since this function - // is called once for every 10 units of rot_time. - int step_size = 10; - float total_trials = (high_threshold - low_threshold) / step_size; - - // Chance of producing no mushrooms (not really because of weight_factor - // below). - float p_failure = 0.5f; - - float trial_prob_f = 1 - powf(p_failure, 1.0f / total_trials); - - // The chance of producing mushrooms depends on the corpse capacity. - // Take humans as the base factor here. - float weight_factor = (float) max_corpse_chunks(corpse.mon_type) / - (float) max_corpse_chunks(MONS_HUMAN); - - trial_prob_f *= weight_factor; - - int trial_prob = static_cast(100 * trial_prob_f); - - return trial_prob; -} - -static bool _mushroom_spawn_message(int seen_targets, int seen_corpses) -{ - if (seen_targets <= 0) - return false; - - string what = seen_targets > 1 ? "Some toadstools" - : "A toadstool"; - string where = seen_corpses > 1 ? "nearby corpses" : - seen_corpses == 1 ? "a nearby corpse" - : "the ground"; - mprf("%s grow%s from %s.", - what.c_str(), seen_targets > 1 ? "" : "s", where.c_str()); - - return true; -} - -// Place a partial ring of toadstools around the given corpse. Returns -// the number of mushrooms spawned. A return of 0 indicates no -// mushrooms were placed -> some sort of failure mode was reached. -static int _mushroom_ring(item_def &corpse, int & seen_count) -{ - // minimum number of mushrooms spawned on a given ring - unsigned min_spawn = 2; - - seen_count = 0; - - vector > radius_points; - - collect_radius_points(radius_points, corpse.pos, LOS_SOLID); - - // So what we have done so far is collect the set of points at each radius - // reachable from the origin with (somewhat constrained) 8 connectivity, - // now we will choose one of those radii and spawn mushrooms at some - // of the points along it. - int chosen_idx = random2(LOS_RADIUS); - - unsigned max_size = 0; - for (unsigned i = 0; i < LOS_RADIUS; ++i) - { - if (radius_points[i].size() >= max_size) - { - max_size = radius_points[i].size(); - chosen_idx = i; - } - } - - chosen_idx = random2(chosen_idx + 1); - - // Not enough valid points? - if (radius_points[chosen_idx].size() < min_spawn) - return 0; - - mgen_data temp(MONS_TOADSTOOL, BEH_GOOD_NEUTRAL, coord_def(), MHITNOT, - MG_FORCE_PLACE); - temp.set_col(corpse.get_colour()); - - float target_arc_len = 2 * sqrtf(2.0f); - - int n_arcs = static_cast (ceilf(2 * PI * (chosen_idx + 1) - / target_arc_len)); - - int spawned_count = place_ring(radius_points[chosen_idx], corpse.pos, temp, - n_arcs, 1, seen_count); - - return spawned_count; -} - -// Try to spawn 'target_count' mushrooms around the position of -// 'corpse'. Returns the number of mushrooms actually spawned. -// Mushrooms radiate outwards from the corpse following bfs with -// 8-connectivity. Could change the expansion pattern by using a -// priority queue for sequencing (priority = distance from origin under -// some metric). -static int _spawn_corpse_mushrooms(item_def& corpse, - int target_count, - int& seen_targets) - -{ - seen_targets = 0; - if (target_count == 0) - return 0; - - int placed_targets = 0; - - queue fringe; - set visited_indices; - - // Slight chance of spawning a ring of mushrooms around the corpse (and - // skeletonising it) if the corpse square is unoccupied. - if (!actor_at(corpse.pos) && one_chance_in(100)) - { - int ring_seen; - // It's possible no reasonable ring can be found, in that case we'll - // give up and just place a toadstool on top of the corpse (probably). - int res = _mushroom_ring(corpse, ring_seen); - - if (res) - { - corpse.freshness = 0; - - if (you.see_cell(corpse.pos)) - mpr("A ring of toadstools grows before your very eyes."); - else if (ring_seen > 1) - mpr("Some toadstools grow in a peculiar arc."); - else if (ring_seen > 0) - mpr("A toadstool grows."); - - seen_targets = -1; - - return res; - } - } - - visited_indices.insert(X_WIDTH * corpse.pos.y + corpse.pos.x); - fringe.push(corpse.pos); - - while (!fringe.empty()) - { - coord_def current = fringe.front(); - - fringe.pop(); - - monster* mons = monster_at(current); - - bool player_occupant = you.pos() == current; - - // Is this square occupied by a non mushroom? - if (mons && mons->mons_species() != MONS_TOADSTOOL - || player_occupant && !you_worship(GOD_FEDHAS) - || !can_spawn_mushrooms(current)) - { - continue; - } - - if (!mons) - { - monster *mushroom = create_monster( - mgen_data(MONS_TOADSTOOL, - BEH_GOOD_NEUTRAL, - current, - MHITNOT, - MG_FORCE_PLACE).set_col(corpse.get_colour()), - false); - - if (mushroom) - { - // Going to explicitly override the die-off timer in - // this case since, we're creating a lot of toadstools - // at once that should die off quickly. - coord_def offset = corpse.pos - current; - - int dist = static_cast(sqrtf(offset.abs()) + 0.5); - - // Trying a longer base duration... - int time_left = random2(8) + dist * 8 + 8; - - time_left *= 10; - - mon_enchant temp_en(ENCH_SLOWLY_DYING, 1, 0, time_left); - mushroom->update_ench(temp_en); - - placed_targets++; - if (current == you.pos()) - { - mprf("A toadstool grows %s.", - player_has_feet() ? "at your feet" : "before you"); - current = mushroom->pos(); - } - else if (you.see_cell(current)) - seen_targets++; - } - else - continue; - } - - // We're done here if we placed the desired number of mushrooms. - if (placed_targets == target_count) - break; - - for (fair_adjacent_iterator ai(current); ai; ++ai) - { - if (in_bounds(*ai) && mons_class_can_pass(MONS_TOADSTOOL, grd(*ai))) - { - const int index = ai->x + ai->y * X_WIDTH; - if (visited_indices.insert(index).second) - fringe.push(*ai); // Not previously visited. - } - } - } - - return placed_targets; -} - -// Turns corpses in LOS into skeletons and grows toadstools on them. -// Can also turn zombies into skeletons and destroy ghoul-type monsters. -// Returns the number of corpses consumed. -int fedhas_fungal_bloom() -{ - int seen_mushrooms = 0; - int seen_corpses = 0; - int processed_count = 0; - bool kills = false; - - for (radius_iterator i(you.pos(), LOS_NO_TRANS); i; ++i) - { - monster* target = monster_at(*i); - if (!can_spawn_mushrooms(*i)) - continue; - - if (target && target->type != MONS_TOADSTOOL) - { - bool piety = !target->is_summoned(); - switch (mons_genus(target->mons_species())) - { - case MONS_ZOMBIE: - // Maybe turn a zombie into a skeleton. - if (mons_skeleton(mons_zombie_base(*target))) - { - simple_monster_message(*target, "'s flesh rots away."); - - downgrade_zombie_to_skeleton(target); - - behaviour_event(target, ME_ALERT, &you); - - if (piety) - processed_count++; - - continue; - } - // Else fall through and destroy the zombie. - // Ghoul-type monsters are always destroyed. - case MONS_GHOUL: - { - simple_monster_message(*target, " rots away and dies."); - - kills = true; - - const coord_def pos = target->pos(); - const int colour = target->colour; - const item_def* corpse = monster_die(*target, KILL_MISC, - NON_MONSTER, true); - - // If a corpse didn't drop, create a toadstool. - // If one did drop, we will create toadstools from it as usual - // later on. - // Give neither piety nor toadstools for summoned creatures. - // Assumes that summoned creatures do not drop corpses (hence - // will not give piety in the next loop). - if (!corpse && piety) - { - if (create_monster( - mgen_data(MONS_TOADSTOOL, - BEH_GOOD_NEUTRAL, - pos, - MHITNOT, - MG_FORCE_PLACE).set_col(colour) - .set_summoned(&you, 0, 0), - false)) - { - seen_mushrooms++; - } - - processed_count++; - continue; - } - - // Verify that summoned creatures do not drop a corpse. - ASSERT(!corpse || piety); - - break; - } - - default: - continue; - } - } - - for (stack_iterator j(*i); j; ++j) - { - bool corpse_on_pos = false; - - if (j->is_type(OBJ_CORPSES, CORPSE_BODY)) - { - corpse_on_pos = true; - - const int trial_prob = _mushroom_prob(*j); - const int target_count = 1 + binomial(20, trial_prob); - int seen_per; - _spawn_corpse_mushrooms(*j, target_count, seen_per); - - // Either turn this corpse into a skeleton or destroy it. - if (mons_skeleton(j->mon_type)) - turn_corpse_into_skeleton(*j); - else - { - item_was_destroyed(*j); - destroy_item(j->index()); - } - - seen_mushrooms += seen_per; - - processed_count++; - } - - if (corpse_on_pos && you.see_cell(*i)) - seen_corpses++; - } - } - - if (seen_mushrooms > 0) - _mushroom_spawn_message(seen_mushrooms, seen_corpses); - - if (kills) - mpr("That felt like a moral victory."); - - if (processed_count) - { - simple_god_message(" appreciates your contribution to the " - "ecosystem."); - // Doubling the expected value per sacrifice to approximate the - // extra piety gain blood god worshipers get for the initial kill. - // -cao - - int piety_gain = 0; - for (int i = 0; i < processed_count * 2; ++i) - piety_gain += random2(15); // avg 1.4 piety per corpse - gain_piety(piety_gain, 10); - } - else - canned_msg(MSG_NOTHING_HAPPENS); - - return processed_count; -} - static bool _create_plant(coord_def& target, int hp_adjust = 0) { if (actor_at(target) || !mons_class_can_pass(MONS_PLANT, grd(target))) diff --git a/crawl-ref/source/god-abil.h b/crawl-ref/source/god-abil.h index 1f7b559af160..a040adb06a75 100644 --- a/crawl-ref/source/god-abil.h +++ b/crawl-ref/source/god-abil.h @@ -117,7 +117,6 @@ int place_ring(vector& ring_points, // (walls/statues). void collect_radius_points(vector > &radius_points, const coord_def &origin, los_type los); -int fedhas_fungal_bloom(); spret fedhas_sunlight(bool fail = false); void process_sunlights(bool future = false); bool prioritise_adjacent(const coord_def& target, vector& candidates); diff --git a/crawl-ref/source/god-conduct.cc b/crawl-ref/source/god-conduct.cc index 61fc46f0c792..23cfb23143ba 100644 --- a/crawl-ref/source/god-conduct.cc +++ b/crawl-ref/source/god-conduct.cc @@ -63,10 +63,9 @@ static const char *conducts[] = "Spell Cast", "Spell Practise", "Cannibalism", "Eat Souled Being", "Deliberate Mutation", "Cause Glowing", "Use Unclean", "Use Chaos", "Desecrate Orcish Remains", "Kill Slime", "Kill Plant", "Was Hasty", - "Corpse Violation", "Carrion Rot", "Souled Friend Died", - "Attack In Sanctuary", "Kill Artificial", "Exploration", - "Desecrate Holy Remains", "Seen Monster", "Sacrificed Love", "Channel", - "Hurt Foe", + "Corpse Violation", "Souled Friend Died", "Attack In Sanctuary", + "Kill Artificial", "Exploration", "Desecrate Holy Remains", "Seen Monster", + "Sacrificed Love", "Channel", "Hurt Foe", }; COMPILE_CHECK(ARRAYSZ(conducts) == NUM_CONDUCTS); @@ -835,9 +834,11 @@ static like_map divine_likes[] = like_map(), // GOD_FEDHAS, { - { DID_ROT_CARRION, { - "corpses rot away", false, 0, 0, 0, " appreciates ongoing decay." - } }, + { DID_KILL_LIVING, KILL_LIVING_RESPONSE }, + { DID_KILL_UNDEAD, KILL_UNDEAD_RESPONSE }, + { DID_KILL_DEMON, KILL_DEMON_RESPONSE }, + { DID_KILL_HOLY, KILL_HOLY_RESPONSE }, + { DID_KILL_NONLIVING, KILL_NONLIVING_RESPONSE }, }, // GOD_CHEIBRIADOS, { diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index 0d0e83733870..d7797687cce4 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -263,7 +263,6 @@ const vector god_powers[NUM_GODS] = // Fedhas { - { 0, ABIL_FEDHAS_FUNGAL_BLOOM, "turn corpses into toadstools" }, { 1, ABIL_FEDHAS_SUNLIGHT, "call sunshine" }, { 2, ABIL_FEDHAS_EVOLUTION, "induce evolution" }, { 3, ABIL_FEDHAS_PLANT_RING, "cause a ring of plants to grow" }, diff --git a/crawl-ref/source/rltiles/dc-invocations.txt b/crawl-ref/source/rltiles/dc-invocations.txt index 80d042ecf3a0..1c7a2f187ca8 100644 --- a/crawl-ref/source/rltiles/dc-invocations.txt +++ b/crawl-ref/source/rltiles/dc-invocations.txt @@ -20,7 +20,6 @@ elyvilon_greater_healing ABILITY_ELYVILON_GREATER_HEALING elyvilon_lesser_healing ABILITY_ELYVILON_LESSER_HEALING elyvilon_purification ABILITY_ELYVILON_PURIFICATION elyvilon_heal_other ABILITY_ELYVILON_HEAL_OTHER -fedhas_fungal_bloom ABILITY_FEDHAS_FUNGAL_BLOOM fedhas_evolution ABILITY_FEDHAS_EVOLUTION fedhas_plant_ring ABILITY_FEDHAS_PLANT_RING fedhas_rain ABILITY_FEDHAS_RAIN diff --git a/crawl-ref/source/rltiles/gui/invocations/fedhas_fungal_bloom.png b/crawl-ref/source/rltiles/gui/invocations/fedhas_fungal_bloom.png deleted file mode 100644 index 7d911410a44a2c47076c4cff25578df16028b8ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 869 zcmV-r1DgDaP)Px&A4x<(R9FecRxxN(Q53x?jZi2hn~UJ0bGmeqPy#|6L>I?EBT`T#g@DjSa3}~8 zFa)|(>0m0gB8X6N2?!m6OEV;!s5ps`MKTB#T8!`95xD)(&BnJM z^iHKx!L9M@K@Xr0CYpv+$ln}+x1Y2JPO{;i+;=BetyV)MhK>0**}5{Fq*|;>s0ZSn zt1nY`{>Qt{_~R<@`NP>BXPhkKRL5I^W3GM80ITxxQ%5l0J_~w;*Q^en#dJNxn-TdU zvcccI4+CL`KF~q%+D&Nvaq&`TXa@<~*6nuHDUtv@5R_x%Ikmn7xNRS`##@D&F!&fU z$Gm!3LZw88!C{v>NYJ+N2*wf!W*r1%SxJ=kAUO9ac?6LJm?2282ka~m%wEHfgm5$@ z#b;^5bCDHr-PNz1oRoB;5Fr^>mq(yqDR>jQK0c6rKA+cMua}oq-q_rfbULlN{X>#p*4O3S z%#3_HI1u<^z*ebLYrtwzszhC3cmWQ9%mx!pe$*?;ak~r2DMK zaC4wId%$+Oo=nP`=>cRx5SAK#4;B_QQ`#V9X-R&qt}1yumaX#$ycGa22FeK#1P1Wd z)|T)%utu4&e!94*ek6y+^<|B?yamw3{x@{}lii)0>ls2ijk|vFU~SG&rvXw)AJaQS z8+`bT9h?7#z#kz%XG(%|4GADf01+Iz?K4g%f#EGE7K{3JLTPwDdwY8(&c6?Id~g86 z#8>>FP1l2OxRI>v5*nuwThyA_x`4b*=yJB-kS;r4GA^5MZz2M|Alx5Ekbbs2Q37`0 vxO(J^D4WfW+*dRX@2^XD?ZqW>YJPtJBN6$2pxdpd00000NkvXXu0mjf*cF;< diff --git a/crawl-ref/source/rot.cc b/crawl-ref/source/rot.cc index 1a3b5ed31889..7eb79b163531 100644 --- a/crawl-ref/source/rot.cc +++ b/crawl-ref/source/rot.cc @@ -204,11 +204,7 @@ static void _rot_corpse(item_def &it, int mitm_index, int rot_time) destroy_item(mitm_index); } else - { turn_corpse_into_skeleton(it); - const int piety = x_chance_in_y(2, 5) ? 2 : 1; // match fungal_bloom() - did_god_conduct(DID_ROT_CARRION, piety); - } } /** diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc index fe3b1886c4db..a731287ba835 100644 --- a/crawl-ref/source/tilepick.cc +++ b/crawl-ref/source/tilepick.cc @@ -3529,8 +3529,6 @@ tileidx_t tileidx_ability(const ability_type ability) case ABIL_JIYVA_CURE_BAD_MUTATION: return TILEG_ABILITY_JIYVA_CURE_BAD_MUTATIONS; // Fedhas - case ABIL_FEDHAS_FUNGAL_BLOOM: - return TILEG_ABILITY_FEDHAS_FUNGAL_BLOOM; case ABIL_FEDHAS_SUNLIGHT: return TILEG_ABILITY_FEDHAS_SUNLIGHT; case ABIL_FEDHAS_RAIN: From 95636025921a8a96de4a2994fb2b95e81c65ed69 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Mon, 9 Sep 2019 00:30:55 -0500 Subject: [PATCH 744/864] Fedhas rework part 2: Wall of Briars ability A 2* ability that encircles the player with summoned briar patches. The player can fire through these plants, and the briars damage monsters that attack them. Monster AI is changed so that hostile monsters always try to attack briars that are friendly to the player. Only floor or shallow water tiles that have no monsters are viable summon locations. The briar patches' HP scale with Invocations by adding 1 HD with each level of this skill. --- crawl-ref/source/ability-type.h | 1 + crawl-ref/source/ability.cc | 8 +++ crawl-ref/source/dat/descript/ability.txt | 5 ++ crawl-ref/source/mon-act.cc | 1 + crawl-ref/source/religion.cc | 1 + crawl-ref/source/rltiles/dc-invocations.txt | 1 + .../gui/invocations/fedhas_wall_of_briars.png | Bin 0 -> 329 bytes crawl-ref/source/spl-summoning.cc | 51 ++++++++++++++++++ crawl-ref/source/spl-summoning.h | 2 + crawl-ref/source/tilepick.cc | 2 + 10 files changed, 72 insertions(+) create mode 100644 crawl-ref/source/rltiles/gui/invocations/fedhas_wall_of_briars.png diff --git a/crawl-ref/source/ability-type.h b/crawl-ref/source/ability-type.h index 1b46b002f927..116fe7be98f7 100644 --- a/crawl-ref/source/ability-type.h +++ b/crawl-ref/source/ability-type.h @@ -178,6 +178,7 @@ enum ability_type ABIL_FEDHAS_PLANT_RING, ABIL_FEDHAS_SPAWN_SPORES, ABIL_FEDHAS_EVOLUTION, + ABIL_FEDHAS_WALL_OF_BRIARS, // Cheibriados ABIL_CHEIBRIADOS_TIME_STEP = 1151, ABIL_CHEIBRIADOS_TIME_BEND, diff --git a/crawl-ref/source/ability.cc b/crawl-ref/source/ability.cc index f41911efe7de..ea38d0185258 100644 --- a/crawl-ref/source/ability.cc +++ b/crawl-ref/source/ability.cc @@ -524,6 +524,8 @@ static const ability_def Ability_List[] = 4, 0, 100, 1, {fail_basis::invo, 60, 4, 25}, abflag::none }, { ABIL_FEDHAS_RAIN, "Rain", 4, 0, 150, 4, {fail_basis::invo, 70, 4, 25}, abflag::none }, + { ABIL_FEDHAS_WALL_OF_BRIARS, "Wall of Briars", + 3, 0, 50, 2, {fail_basis::invo, 30, 6, 20}, abflag::none}, // Cheibriados { ABIL_CHEIBRIADOS_TIME_BEND, "Bend Time", @@ -2871,6 +2873,12 @@ static spret _do_ability(const ability_def& abil, bool fail) return spret::abort; break; + case ABIL_FEDHAS_WALL_OF_BRIARS: + fail_check(); + if (!fedhas_wall_of_briars()) + return spret::abort; + break; + case ABIL_FEDHAS_RAIN: fail_check(); if (!fedhas_rain(you.pos())) diff --git a/crawl-ref/source/dat/descript/ability.txt b/crawl-ref/source/dat/descript/ability.txt index 584089fff82f..d285b42fc1ee 100644 --- a/crawl-ref/source/dat/descript/ability.txt +++ b/crawl-ref/source/dat/descript/ability.txt @@ -481,6 +481,11 @@ Bring an orc corpse back to life. The orc will be an ally, even if it was not already one before it died. %%%% # Fedhas +Wall of Briars ability + +Grow short-lived briar patches around you. Monsters attacking these briars will +be damaged by sharp thorns. Invocations skill increases the briars' health. +%%%% Sunlight ability Calls sunlight down over a small area of the dungeon. Monsters illuminated by diff --git a/crawl-ref/source/mon-act.cc b/crawl-ref/source/mon-act.cc index 0b9915c93d06..bded8b1ebb62 100644 --- a/crawl-ref/source/mon-act.cc +++ b/crawl-ref/source/mon-act.cc @@ -2990,6 +2990,7 @@ static bool _may_cutdown(monster* mons, monster* targ) // (but don't try to attack briars unless their damage will be insignificant) return mons_is_firewood(*targ) && (targ->type != MONS_BRIAR_PATCH + || (targ->friendly() && !mons_aligned(mons, targ)) || mons->type == MONS_THORN_HUNTER || mons->armour_class() * mons->hit_points >= 400); } diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index d7797687cce4..53452c356cc6 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -264,6 +264,7 @@ const vector god_powers[NUM_GODS] = // Fedhas { { 1, ABIL_FEDHAS_SUNLIGHT, "call sunshine" }, + { 2, ABIL_FEDHAS_WALL_OF_BRIARS, "encircle yourself with summoned briar patches"}, { 2, ABIL_FEDHAS_EVOLUTION, "induce evolution" }, { 3, ABIL_FEDHAS_PLANT_RING, "cause a ring of plants to grow" }, { 4, ABIL_FEDHAS_SPAWN_SPORES, "spawn explosive spores" }, diff --git a/crawl-ref/source/rltiles/dc-invocations.txt b/crawl-ref/source/rltiles/dc-invocations.txt index 1c7a2f187ca8..dfef4a21b587 100644 --- a/crawl-ref/source/rltiles/dc-invocations.txt +++ b/crawl-ref/source/rltiles/dc-invocations.txt @@ -25,6 +25,7 @@ fedhas_plant_ring ABILITY_FEDHAS_PLANT_RING fedhas_rain ABILITY_FEDHAS_RAIN fedhas_spawn_spores ABILITY_FEDHAS_SPAWN_SPORES fedhas_sunlight ABILITY_FEDHAS_SUNLIGHT +fedhas_wall_of_briars ABILITY_FEDHAS_WALL_OF_BRIARS gozag_potion_petition ABILITY_GOZAG_POTION_PETITION gozag_call_merchant ABILITY_GOZAG_CALL_MERCHANT gozag_bribe_branch ABILITY_GOZAG_BRIBE_BRANCH diff --git a/crawl-ref/source/rltiles/gui/invocations/fedhas_wall_of_briars.png b/crawl-ref/source/rltiles/gui/invocations/fedhas_wall_of_briars.png new file mode 100644 index 0000000000000000000000000000000000000000..ef367f50a4110b1884c2e4fdad66580eea7f6f36 GIT binary patch literal 329 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyiUB?$u0R?Hcua+4(nJgl3>+LB z61w;%Oqj6kr0`^|3cYKixm_3g25?K`XY4mno;c(-g9TD6~J5zGApGgl=Q?_?C+ z+#spYvLrFz!N)%-Kw2T-t74c>HA7@@l59xRlZuIJm{|5OvBicb6xK(s-8?nH)8;oz zhu4G!%RQa0JFHN adjacent; + for (adjacent_iterator adj_it(you.pos()); adj_it; ++adj_it) + { + if (monster_habitable_grid(MONS_BRIAR_PATCH, env.grid(*adj_it)) + && !actor_at(*adj_it)) + { + adjacent.push_back(*adj_it); + } + } + + // Don't prompt if we can't do anything. + if (adjacent.empty()) + { + mpr("No empty adjacent squares."); + return false; + } + + int created_count = 0; + for (auto p : adjacent) + { + if (_create_briar_patch(p)) + created_count++; + } + + if (!created_count) + canned_msg(MSG_NOTHING_HAPPENS); + + return created_count; +} diff --git a/crawl-ref/source/spl-summoning.h b/crawl-ref/source/spl-summoning.h index 4adf0329a209..f9d0c9b8c066 100644 --- a/crawl-ref/source/spl-summoning.h +++ b/crawl-ref/source/spl-summoning.h @@ -125,3 +125,5 @@ void summoned_monster(const monster* mons, const actor* caster, bool summons_are_capped(spell_type spell); int summons_limit(spell_type spell); int count_summons(const actor *summoner, spell_type spell); + +bool fedhas_wall_of_briars(); diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc index a731287ba835..865e3c25f2e8 100644 --- a/crawl-ref/source/tilepick.cc +++ b/crawl-ref/source/tilepick.cc @@ -3529,6 +3529,8 @@ tileidx_t tileidx_ability(const ability_type ability) case ABIL_JIYVA_CURE_BAD_MUTATION: return TILEG_ABILITY_JIYVA_CURE_BAD_MUTATIONS; // Fedhas + case ABIL_FEDHAS_WALL_OF_BRIARS: + return TILEG_ABILITY_FEDHAS_WALL_OF_BRIARS; case ABIL_FEDHAS_SUNLIGHT: return TILEG_ABILITY_FEDHAS_SUNLIGHT; case ABIL_FEDHAS_RAIN: From 1d64b78cf4984becb95c8a06c3bb02473155b85e Mon Sep 17 00:00:00 2001 From: gammafunk Date: Mon, 9 Sep 2019 01:05:46 -0500 Subject: [PATCH 745/864] Fedhas rework part 3: remove Sunlight Sunlight is a pretty tedious to use ability that strongly overlaps with TSO. Removing shallow and deep water when flight is extensively available is also not especially interesting. This adds a minor version tag to handle save compatibility, since we're removing a member of the global env that maps sunlight-affected squares. --- crawl-ref/source/ability-type.h | 3 +- crawl-ref/source/ability.cc | 5 - crawl-ref/source/areas.cc | 7 - crawl-ref/source/dat/descript/ability.txt | 7 - crawl-ref/source/dungeon.cc | 1 - crawl-ref/source/env.h | 1 - crawl-ref/source/god-abil.cc | 155 ------------------ crawl-ref/source/god-abil.h | 2 - crawl-ref/source/player-reacts.cc | 3 - crawl-ref/source/religion.cc | 1 - crawl-ref/source/rltiles/dc-invocations.txt | 1 - .../gui/invocations/fedhas_sunlight.png | Bin 356 -> 0 bytes crawl-ref/source/stairs.cc | 2 - crawl-ref/source/tag-version.h | 1 + crawl-ref/source/tags.cc | 23 ++- crawl-ref/source/tilepick.cc | 2 - 16 files changed, 12 insertions(+), 202 deletions(-) delete mode 100644 crawl-ref/source/rltiles/gui/invocations/fedhas_sunlight.png diff --git a/crawl-ref/source/ability-type.h b/crawl-ref/source/ability-type.h index 116fe7be98f7..2969342edf2e 100644 --- a/crawl-ref/source/ability-type.h +++ b/crawl-ref/source/ability-type.h @@ -173,12 +173,11 @@ enum ability_type ABIL_JIYVA_SLIMIFY, ABIL_JIYVA_CURE_BAD_MUTATION, // Fedhas - ABIL_FEDHAS_SUNLIGHT = 1140, + ABIL_FEDHAS_WALL_OF_BRIARS = 1140, ABIL_FEDHAS_RAIN, ABIL_FEDHAS_PLANT_RING, ABIL_FEDHAS_SPAWN_SPORES, ABIL_FEDHAS_EVOLUTION, - ABIL_FEDHAS_WALL_OF_BRIARS, // Cheibriados ABIL_CHEIBRIADOS_TIME_STEP = 1151, ABIL_CHEIBRIADOS_TIME_BEND, diff --git a/crawl-ref/source/ability.cc b/crawl-ref/source/ability.cc index ea38d0185258..f681cec0e7aa 100644 --- a/crawl-ref/source/ability.cc +++ b/crawl-ref/source/ability.cc @@ -514,8 +514,6 @@ static const ability_def Ability_List[] = 0, 0, 0, 15, {fail_basis::invo}, abflag::none }, // Fedhas - { ABIL_FEDHAS_SUNLIGHT, "Sunlight", - 2, 0, 50, 0, {fail_basis::invo, 30, 6, 20}, abflag::none }, { ABIL_FEDHAS_EVOLUTION, "Evolution", 2, 0, 0, 0, {fail_basis::invo, 30, 6, 20}, abflag::rations_or_piety }, { ABIL_FEDHAS_PLANT_RING, "Growth", @@ -2864,9 +2862,6 @@ static spret _do_ability(const ability_def& abil, bool fail) end_recall(); break; - case ABIL_FEDHAS_SUNLIGHT: - return fedhas_sunlight(fail); - case ABIL_FEDHAS_PLANT_RING: fail_check(); if (!fedhas_plant_ring_from_rations()) diff --git a/crawl-ref/source/areas.cc b/crawl-ref/source/areas.cc index 3910ffcd770b..b3248f4a3fbf 100644 --- a/crawl-ref/source/areas.cc +++ b/crawl-ref/source/areas.cc @@ -199,13 +199,6 @@ static void _update_agrid() no_areas = false; } - if (!env.sunlight.empty()) - { - for (const auto &entry : env.sunlight) - _set_agrid_flag(entry.first, areaprop::halo); - no_areas = false; - } - // TODO: update sanctuary here. _agrid_valid = true; diff --git a/crawl-ref/source/dat/descript/ability.txt b/crawl-ref/source/dat/descript/ability.txt index d285b42fc1ee..294a4b3243c7 100644 --- a/crawl-ref/source/dat/descript/ability.txt +++ b/crawl-ref/source/dat/descript/ability.txt @@ -486,13 +486,6 @@ Wall of Briars ability Grow short-lived briar patches around you. Monsters attacking these briars will be damaged by sharp thorns. Invocations skill increases the briars' health. %%%% -Sunlight ability - -Calls sunlight down over a small area of the dungeon. Monsters illuminated by -the light will be easier to hit. Water affected by the sunlight will evaporate. -In particular, deep water will become shallow water, and shallow water will dry -up completely, revealing the dungeon floor. -%%%% Growth ability Uses food to grow a ring of plants around yourself. If a complete ring cannot diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 1511b363229b..4ddfc1df72dc 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -1339,7 +1339,6 @@ void dgn_reset_level(bool enable_random_maps) env.spawn_random_rate = 0; env.density = 0; env.forest_awoken_until = 0; - env.sunlight.clear(); env.floor_colour = BLACK; env.rock_colour = BLACK; diff --git a/crawl-ref/source/env.h b/crawl-ref/source/env.h index 140e6678c67b..d3604384113d 100644 --- a/crawl-ref/source/env.h +++ b/crawl-ref/source/env.h @@ -107,7 +107,6 @@ struct crawl_environment int forest_awoken_until; int density; int absdepth0; - vector > sunlight; // Remaining fields not marshalled: diff --git a/crawl-ref/source/god-abil.cc b/crawl-ref/source/god-abil.cc index f971fe25c8d7..8d040ebfac3c 100644 --- a/crawl-ref/source/god-abil.cc +++ b/crawl-ref/source/god-abil.cc @@ -2210,161 +2210,6 @@ static bool _create_plant(coord_def& target, int hp_adjust = 0) return false; } -#define SUNLIGHT_DURATION 80 - -spret fedhas_sunlight(bool fail) -{ - dist spelld; - - bolt temp_bolt; - temp_bolt.colour = YELLOW; - - targeter_smite tgt(&you, LOS_RADIUS, 0, 1); - direction_chooser_args args; - args.restricts = DIR_TARGET; - args.mode = TARG_HOSTILE_SUBMERGED; - args.range = LOS_RADIUS; - args.needs_path = false; - args.top_prompt = "Select sunlight destination."; - args.hitfunc = &tgt; - direction(spelld, args); - - if (!spelld.isValid) - return spret::abort; - - fail_check(); - - const coord_def base = spelld.target; - - int revealed_count = 0; - - for (adjacent_iterator ai(base, false); ai; ++ai) - { - if (!in_bounds(*ai) || cell_is_solid(*ai)) - continue; - - for (size_t i = 0; i < env.sunlight.size(); ++i) - if (env.sunlight[i].first == *ai) - { - erase_any(env.sunlight, i); - break; - } - const int expiry = you.elapsed_time + SUNLIGHT_DURATION; - env.sunlight.emplace_back(*ai, expiry); - - temp_bolt.explosion_draw_cell(*ai); - - monster *victim = monster_at(*ai); - if (victim && you.see_cell(*ai) && !victim->visible_to(&you)) - { - // Like entering/exiting angel halos, flipping autopickup would - // be probably too much hassle. - revealed_count++; - } - - if (victim) - behaviour_event(victim, ME_ALERT, &you); - } - - { - unwind_var no_time(you.time_taken, 0); - process_sunlights(false); - } - - { - // hide the cursor (it looks weird). - cursor_control con(false); - scaled_delay(200); - } - - if (revealed_count) - { - mprf("In the bright light, you notice %s.", revealed_count == 1 ? - "an invisible shape" : "some invisible shapes"); - } - - return spret::success; -} - -void process_sunlights(bool future) -{ - int time_cap = future ? INT_MAX - SUNLIGHT_DURATION : you.elapsed_time; - - int evap_count = 0; - - for (int i = env.sunlight.size() - 1; i >= 0; --i) - { - coord_def c = env.sunlight[i].first; - int until = env.sunlight[i].second; - - if (until <= time_cap) - erase_any(env.sunlight, i); - - until = min(until, time_cap); - int from = you.elapsed_time - you.time_taken; - - // Deterministic roll, to guarantee evaporation when shined long enough. - struct { level_id place; coord_def coord; int64_t game_start; } to_hash; - to_hash.place = level_id::current(); - to_hash.coord = c; - to_hash.game_start = you.birth_time; - int h = hash32(&to_hash, sizeof(to_hash)) % SUNLIGHT_DURATION; - - if ((from + h) / SUNLIGHT_DURATION == (until + h) / SUNLIGHT_DURATION) - continue; - - // Anything further on goes only on a successful evaporation roll, at - // most once peer coord per invocation. - - // If this is a water square we will evaporate it. - dungeon_feature_type ftype = grd(c); - dungeon_feature_type orig_type = ftype; - - switch (ftype) - { - case DNGN_SHALLOW_WATER: - ftype = DNGN_FLOOR; - break; - - case DNGN_DEEP_WATER: - ftype = DNGN_SHALLOW_WATER; - break; - - default: - break; - } - - if (orig_type != ftype) - { - dungeon_terrain_changed(c, ftype); - - if (you.see_cell(c)) - evap_count++; - - // This is a little awkward but if we evaporated all the way to - // the dungeon floor that may have given a monster - // ENCH_AQUATIC_LAND, and if that happened the player should get - // credit if the monster dies. The enchantment is inflicted via - // the dungeon_terrain_changed call chain and that doesn't keep - // track of what caused the terrain change. -cao - monster* mons = monster_at(c); - if (mons && ftype == DNGN_FLOOR - && mons->has_ench(ENCH_AQUATIC_LAND)) - { - mon_enchant temp = mons->get_ench(ENCH_AQUATIC_LAND); - temp.who = KC_YOU; - temp.source = MID_PLAYER; - mons->add_ench(temp); - } - } - } - - if (evap_count) - mpr("Some water evaporates in the bright sunlight."); - - invalidate_agrid(true); -} - template static bool less_second(const T & left, const T & right) { diff --git a/crawl-ref/source/god-abil.h b/crawl-ref/source/god-abil.h index a040adb06a75..b1bb58ae87c6 100644 --- a/crawl-ref/source/god-abil.h +++ b/crawl-ref/source/god-abil.h @@ -117,8 +117,6 @@ int place_ring(vector& ring_points, // (walls/statues). void collect_radius_points(vector > &radius_points, const coord_def &origin, los_type los); -spret fedhas_sunlight(bool fail = false); -void process_sunlights(bool future = false); bool prioritise_adjacent(const coord_def& target, vector& candidates); bool fedhas_plant_ring_from_rations(); int fedhas_rain(const coord_def &target); diff --git a/crawl-ref/source/player-reacts.cc b/crawl-ref/source/player-reacts.cc index 0b35f872090c..07665f00a7fc 100644 --- a/crawl-ref/source/player-reacts.cc +++ b/crawl-ref/source/player-reacts.cc @@ -839,9 +839,6 @@ static void _decrement_durations() you.berserk() ? "rip and tear" : "carefully extract").c_str()); } - if (!env.sunlight.empty()) - process_sunlights(); - if (!you.duration[DUR_ANCESTOR_DELAY] && in_good_standing(GOD_HEPLIAKLQANA) && hepliaklqana_ancestor() == MID_NOBODY) diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index 53452c356cc6..fd6d54344d12 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -263,7 +263,6 @@ const vector god_powers[NUM_GODS] = // Fedhas { - { 1, ABIL_FEDHAS_SUNLIGHT, "call sunshine" }, { 2, ABIL_FEDHAS_WALL_OF_BRIARS, "encircle yourself with summoned briar patches"}, { 2, ABIL_FEDHAS_EVOLUTION, "induce evolution" }, { 3, ABIL_FEDHAS_PLANT_RING, "cause a ring of plants to grow" }, diff --git a/crawl-ref/source/rltiles/dc-invocations.txt b/crawl-ref/source/rltiles/dc-invocations.txt index dfef4a21b587..395b54b2adbf 100644 --- a/crawl-ref/source/rltiles/dc-invocations.txt +++ b/crawl-ref/source/rltiles/dc-invocations.txt @@ -24,7 +24,6 @@ fedhas_evolution ABILITY_FEDHAS_EVOLUTION fedhas_plant_ring ABILITY_FEDHAS_PLANT_RING fedhas_rain ABILITY_FEDHAS_RAIN fedhas_spawn_spores ABILITY_FEDHAS_SPAWN_SPORES -fedhas_sunlight ABILITY_FEDHAS_SUNLIGHT fedhas_wall_of_briars ABILITY_FEDHAS_WALL_OF_BRIARS gozag_potion_petition ABILITY_GOZAG_POTION_PETITION gozag_call_merchant ABILITY_GOZAG_CALL_MERCHANT diff --git a/crawl-ref/source/rltiles/gui/invocations/fedhas_sunlight.png b/crawl-ref/source/rltiles/gui/invocations/fedhas_sunlight.png deleted file mode 100644 index cb7cab270477e747e36c55d732b3a5da2de44968..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy1_3@Hu0R?H*kt*6Ooe39L<|fJ z92^`Hy7CcARfPz$57DGX9lle)pLfWE`6Nhp6&~@1zF~sFlNUUzw;?-nS4EF yfBm~{E$8Lh4=-eBvSMGbzVVIh+s|KF3q0+Q&*kAbzmQ826j+|FelF{r5}E+Lj)r#t diff --git a/crawl-ref/source/stairs.cc b/crawl-ref/source/stairs.cc index af59784983e6..fe95b87f54e4 100644 --- a/crawl-ref/source/stairs.cc +++ b/crawl-ref/source/stairs.cc @@ -222,8 +222,6 @@ static void _clear_prisms() void leaving_level_now(dungeon_feature_type stair_used) { - process_sunlights(true); - if (stair_used == DNGN_EXIT_ZIGGURAT) { if (you.depth == 27) diff --git a/crawl-ref/source/tag-version.h b/crawl-ref/source/tag-version.h index a9530484646b..6142b8c038a0 100644 --- a/crawl-ref/source/tag-version.h +++ b/crawl-ref/source/tag-version.h @@ -235,6 +235,7 @@ enum tag_minor_version TAG_MINOR_SINGULAR_THEY, // Add singular they pronouns TAG_MINOR_ABYSS_UNIQUE_VAULTS, // Separate abyss vault tracking from main dungeon TAG_MINOR_INCREMENTAL_PREGEN, // save tracks whether the game is an incremental pregen game + TAG_MINOR_NO_SUNLIGHT, // Removal of Fedhas' Sunlight #endif NUM_TAG_MINORS, TAG_MINOR_VERSION = NUM_TAG_MINORS - 1 diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index 600d48e5cdcd..c87c1d23a82b 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -4457,13 +4457,6 @@ static void tag_construct_level(writer &th) marshallInt(th, env.forest_awoken_until); marshall_level_vault_data(th); marshallInt(th, env.density); - - marshallShort(th, env.sunlight.size()); - for (const auto &sunspot : env.sunlight) - { - marshallCoord(th, sunspot.first); - marshallInt(th, sunspot.second); - } } void marshallItem(writer &th, const item_def &item, bool iinfo) @@ -6055,15 +6048,19 @@ static void tag_read_level(reader &th) env.forest_awoken_until = unmarshallInt(th); unmarshall_level_vault_data(th); env.density = unmarshallInt(th); +#if TAG_MAJOR_VERSION == 34 - int num_lights = unmarshallShort(th); - ASSERT(num_lights >= 0); - env.sunlight.clear(); - while (num_lights-- > 0) + if (th.getMinorVersion() < TAG_MINOR_NO_SUNLIGHT) { - coord_def c = unmarshallCoord(th); - env.sunlight.emplace_back(c, unmarshallInt(th)); + int num_lights = unmarshallShort(th); + ASSERT(num_lights >= 0); + while (num_lights-- > 0) + { + unmarshallCoord(th); + unmarshallInt(th); + } } +#endif } #if TAG_MAJOR_VERSION == 34 diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc index 865e3c25f2e8..4b78ad6fce5a 100644 --- a/crawl-ref/source/tilepick.cc +++ b/crawl-ref/source/tilepick.cc @@ -3531,8 +3531,6 @@ tileidx_t tileidx_ability(const ability_type ability) // Fedhas case ABIL_FEDHAS_WALL_OF_BRIARS: return TILEG_ABILITY_FEDHAS_WALL_OF_BRIARS; - case ABIL_FEDHAS_SUNLIGHT: - return TILEG_ABILITY_FEDHAS_SUNLIGHT; case ABIL_FEDHAS_RAIN: return TILEG_ABILITY_FEDHAS_RAIN; case ABIL_FEDHAS_PLANT_RING: From 6ba74d58385ecf15052e41c5ba8932d09894e5ee Mon Sep 17 00:00:00 2001 From: gammafunk Date: Mon, 9 Sep 2019 21:49:15 -0500 Subject: [PATCH 746/864] Fedhas rework part 4: remove Growth Fedhas will use summons to create all allies instead of creating permanent ones using actual plant monsters as intermediaries. Hence Growth, also referred to as using the descriptor `RING_OF_PLANTS` in the source, is no longer necessary. --- crawl-ref/source/ability-type.h | 1 - crawl-ref/source/ability.cc | 8 - crawl-ref/source/dat/descript/ability.txt | 7 - crawl-ref/source/god-abil.cc | 142 ------------------ crawl-ref/source/god-abil.h | 1 - crawl-ref/source/religion.cc | 1 - crawl-ref/source/rltiles/dc-invocations.txt | 1 - .../gui/invocations/fedhas_plant_ring.png | Bin 329 -> 0 bytes crawl-ref/source/tilepick.cc | 2 - 9 files changed, 163 deletions(-) delete mode 100644 crawl-ref/source/rltiles/gui/invocations/fedhas_plant_ring.png diff --git a/crawl-ref/source/ability-type.h b/crawl-ref/source/ability-type.h index 2969342edf2e..68953c1ee1b4 100644 --- a/crawl-ref/source/ability-type.h +++ b/crawl-ref/source/ability-type.h @@ -175,7 +175,6 @@ enum ability_type // Fedhas ABIL_FEDHAS_WALL_OF_BRIARS = 1140, ABIL_FEDHAS_RAIN, - ABIL_FEDHAS_PLANT_RING, ABIL_FEDHAS_SPAWN_SPORES, ABIL_FEDHAS_EVOLUTION, // Cheibriados diff --git a/crawl-ref/source/ability.cc b/crawl-ref/source/ability.cc index f681cec0e7aa..cb1dbd1b3a78 100644 --- a/crawl-ref/source/ability.cc +++ b/crawl-ref/source/ability.cc @@ -516,8 +516,6 @@ static const ability_def Ability_List[] = // Fedhas { ABIL_FEDHAS_EVOLUTION, "Evolution", 2, 0, 0, 0, {fail_basis::invo, 30, 6, 20}, abflag::rations_or_piety }, - { ABIL_FEDHAS_PLANT_RING, "Growth", - 2, 0, 0, 0, {fail_basis::invo, 40, 5, 20}, abflag::rations }, { ABIL_FEDHAS_SPAWN_SPORES, "Reproduction", 4, 0, 100, 1, {fail_basis::invo, 60, 4, 25}, abflag::none }, { ABIL_FEDHAS_RAIN, "Rain", @@ -2862,12 +2860,6 @@ static spret _do_ability(const ability_def& abil, bool fail) end_recall(); break; - case ABIL_FEDHAS_PLANT_RING: - fail_check(); - if (!fedhas_plant_ring_from_rations()) - return spret::abort; - break; - case ABIL_FEDHAS_WALL_OF_BRIARS: fail_check(); if (!fedhas_wall_of_briars()) diff --git a/crawl-ref/source/dat/descript/ability.txt b/crawl-ref/source/dat/descript/ability.txt index 294a4b3243c7..d4c4b695fcac 100644 --- a/crawl-ref/source/dat/descript/ability.txt +++ b/crawl-ref/source/dat/descript/ability.txt @@ -486,13 +486,6 @@ Wall of Briars ability Grow short-lived briar patches around you. Monsters attacking these briars will be damaged by sharp thorns. Invocations skill increases the briars' health. %%%% -Growth ability - -Uses food to grow a ring of plants around yourself. If a complete ring cannot -be formed (because you do not have enough food), plants will grow on squares -adjacent to you that are close to monsters. The plants you create gain bonus -health proportional to your Invocations skill. -%%%% Rain ability Causes rain to fall around you, turning the dungeon floor into shallow water diff --git a/crawl-ref/source/god-abil.cc b/crawl-ref/source/god-abil.cc index 8d040ebfac3c..08e43723516e 100644 --- a/crawl-ref/source/god-abil.cc +++ b/crawl-ref/source/god-abil.cc @@ -2173,43 +2173,6 @@ void collect_radius_points(vector > &radius_points, } } -static bool _create_plant(coord_def& target, int hp_adjust = 0) -{ - if (actor_at(target) || !mons_class_can_pass(MONS_PLANT, grd(target))) - return 0; - - if (monster *plant = create_monster(mgen_data(MONS_PLANT, - BEH_FRIENDLY, - target, - MHITNOT, - MG_FORCE_PLACE, - GOD_FEDHAS) - .set_summoned(&you, 0, 0))) - { - plant->flags |= MF_NO_REWARD; - plant->flags |= MF_ATT_CHANGE_ATTEMPT; - - mons_make_god_gift(*plant, GOD_FEDHAS); - - plant->max_hit_points += hp_adjust; - plant->hit_points += hp_adjust; - - if (you.see_cell(target)) - { - if (hp_adjust) - { - mprf("A plant, strengthened by %s, grows up from the ground.", - god_name(GOD_FEDHAS).c_str()); - } - else - mpr("A plant grows up from the ground."); - } - return true; - } - - return false; -} - template static bool less_second(const T & left, const T & right) { @@ -2416,111 +2379,6 @@ static void _decrease_amount(vector >& available, int amount) mpr("A ration is consumed!"); } -// Create a ring or partial ring around the caster. The user is -// prompted to select a stack of rations, and then plants are placed on open -// squares adjacent to the user. Of course, two rations are -// consumed per plant, so a complete ring may not be formed. -bool fedhas_plant_ring_from_rations() -{ - // How many rations is available? - vector > collected_rations; - int total_rations = _collect_rations(collected_rations); - - // How many adjacent open spaces are there? - vector adjacent; - for (adjacent_iterator adj_it(you.pos()); adj_it; ++adj_it) - { - if (monster_habitable_grid(MONS_PLANT, env.grid(*adj_it)) - && !actor_at(*adj_it)) - { - adjacent.push_back(*adj_it); - } - } - - const int max_use = min(total_rations/2, static_cast(adjacent.size())); - - // Don't prompt if we can't do anything (due to having no rations or - // no squares to place plants on). - if (max_use == 0) - { - if (adjacent.empty()) - mpr("No empty adjacent squares."); - else - mpr("Not enough rations available."); - - return false; - } - - prioritise_adjacent(you.pos(), adjacent); - - // Screwing around with display code I don't really understand. -cao - targeter_smite range(&you, 1); - range_view_annotator show_range(&range); - - for (int i = 0; i < max_use; ++i) - { -#ifndef USE_TILE_LOCAL - coord_def temp = grid2view(adjacent[i]); - cgotoxy(temp.x, temp.y, GOTO_DNGN); - put_colour_ch(GREEN, '1' + i); -#endif -#ifdef USE_TILE - tiles.add_overlay(adjacent[i], TILE_INDICATOR + i); -#endif - } - - // And how many plants does the user want to create? - int target_count; - if (!_prompt_amount(max_use, target_count, - "How many plants will you create?")) - { - // User cancelled at the prompt. - return false; - } - - const int hp_adjust = you.skill(SK_INVOCATIONS, 10); - - // The user entered a number, remove all number overlays which - // are higher than that number. -#ifndef USE_TILE_LOCAL - unsigned not_used = adjacent.size() - unsigned(target_count); - for (unsigned i = adjacent.size() - not_used; i < adjacent.size(); i++) - view_update_at(adjacent[i]); -#endif -#ifdef USE_TILE - // For tiles we have to clear all overlays and redraw the ones - // we want. - tiles.clear_overlays(); - for (int i = 0; i < target_count; ++i) - tiles.add_overlay(adjacent[i], TILE_INDICATOR + i); -#endif - - int created_count = 0; - for (int i = 0; i < target_count; ++i) - { - if (_create_plant(adjacent[i], hp_adjust)) - created_count++; - - // Clear the overlay and draw the plant we just placed. - // This is somewhat more complicated in tiles. - view_update_at(adjacent[i]); -#ifdef USE_TILE - tiles.clear_overlays(); - for (int j = i + 1; j < target_count; ++j) - tiles.add_overlay(adjacent[j], TILE_INDICATOR + j); - viewwindow(false); -#endif - scaled_delay(200); - } - - if (created_count) - _decrease_amount(collected_rations, 2 * created_count); - else - canned_msg(MSG_NOTHING_HAPPENS); - - return created_count; -} - // Create a circle of water around the target, with a radius of // approximately 2. This turns normal floor tiles into shallow water // and turns (unoccupied) shallow water into deep water. There is a diff --git a/crawl-ref/source/god-abil.h b/crawl-ref/source/god-abil.h index b1bb58ae87c6..0914bd7dfdf6 100644 --- a/crawl-ref/source/god-abil.h +++ b/crawl-ref/source/god-abil.h @@ -118,7 +118,6 @@ int place_ring(vector& ring_points, void collect_radius_points(vector > &radius_points, const coord_def &origin, los_type los); bool prioritise_adjacent(const coord_def& target, vector& candidates); -bool fedhas_plant_ring_from_rations(); int fedhas_rain(const coord_def &target); int count_corpses_in_los(vector *positions); int fedhas_check_corpse_spores(bool quiet = false); diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index fd6d54344d12..16a29377f784 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -265,7 +265,6 @@ const vector god_powers[NUM_GODS] = { { 2, ABIL_FEDHAS_WALL_OF_BRIARS, "encircle yourself with summoned briar patches"}, { 2, ABIL_FEDHAS_EVOLUTION, "induce evolution" }, - { 3, ABIL_FEDHAS_PLANT_RING, "cause a ring of plants to grow" }, { 4, ABIL_FEDHAS_SPAWN_SPORES, "spawn explosive spores" }, { 5, ABIL_FEDHAS_RAIN, "control the weather" }, }, diff --git a/crawl-ref/source/rltiles/dc-invocations.txt b/crawl-ref/source/rltiles/dc-invocations.txt index 395b54b2adbf..0fd015b5bd3a 100644 --- a/crawl-ref/source/rltiles/dc-invocations.txt +++ b/crawl-ref/source/rltiles/dc-invocations.txt @@ -21,7 +21,6 @@ elyvilon_lesser_healing ABILITY_ELYVILON_LESSER_HEALING elyvilon_purification ABILITY_ELYVILON_PURIFICATION elyvilon_heal_other ABILITY_ELYVILON_HEAL_OTHER fedhas_evolution ABILITY_FEDHAS_EVOLUTION -fedhas_plant_ring ABILITY_FEDHAS_PLANT_RING fedhas_rain ABILITY_FEDHAS_RAIN fedhas_spawn_spores ABILITY_FEDHAS_SPAWN_SPORES fedhas_wall_of_briars ABILITY_FEDHAS_WALL_OF_BRIARS diff --git a/crawl-ref/source/rltiles/gui/invocations/fedhas_plant_ring.png b/crawl-ref/source/rltiles/gui/invocations/fedhas_plant_ring.png deleted file mode 100644 index ef367f50a4110b1884c2e4fdad66580eea7f6f36..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 329 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyiUB?$u0R?Hcua+4(nJgl3>+LB z61w;%Oqj6kr0`^|3cYKixm_3g25?K`XY4mno;c(-g9TD6~J5zGApGgl=Q?_?C+ z+#spYvLrFz!N)%-Kw2T-t74c>HA7@@l59xRlZuIJm{|5OvBicb6xK(s-8?nH)8;oz zhu4G!%RQa0JFHN Date: Mon, 9 Sep 2019 23:27:31 -0500 Subject: [PATCH 747/864] Fedhas rework part 5: remove Evolution As per the Fungal Bloom and Growth ability removals, we don't use plants as intermediaries for creating allies. New abilities to create some of these monsters as summons directly will be added in future commits. --- crawl-ref/source/ability-type.h | 1 - crawl-ref/source/ability.cc | 7 - crawl-ref/source/dat/descript/ability.txt | 8 - crawl-ref/source/directn.cc | 7 +- crawl-ref/source/god-abil.cc | 265 ------------------ crawl-ref/source/god-abil.h | 3 - crawl-ref/source/religion.cc | 1 - crawl-ref/source/rltiles/dc-invocations.txt | 1 - .../gui/invocations/fedhas_evolution.png | Bin 364 -> 0 bytes crawl-ref/source/targ-mode-type.h | 1 - crawl-ref/source/tilepick.cc | 2 - 11 files changed, 1 insertion(+), 295 deletions(-) delete mode 100644 crawl-ref/source/rltiles/gui/invocations/fedhas_evolution.png diff --git a/crawl-ref/source/ability-type.h b/crawl-ref/source/ability-type.h index 68953c1ee1b4..e0eb7b7b4ad0 100644 --- a/crawl-ref/source/ability-type.h +++ b/crawl-ref/source/ability-type.h @@ -176,7 +176,6 @@ enum ability_type ABIL_FEDHAS_WALL_OF_BRIARS = 1140, ABIL_FEDHAS_RAIN, ABIL_FEDHAS_SPAWN_SPORES, - ABIL_FEDHAS_EVOLUTION, // Cheibriados ABIL_CHEIBRIADOS_TIME_STEP = 1151, ABIL_CHEIBRIADOS_TIME_BEND, diff --git a/crawl-ref/source/ability.cc b/crawl-ref/source/ability.cc index cb1dbd1b3a78..771782ff4851 100644 --- a/crawl-ref/source/ability.cc +++ b/crawl-ref/source/ability.cc @@ -514,8 +514,6 @@ static const ability_def Ability_List[] = 0, 0, 0, 15, {fail_basis::invo}, abflag::none }, // Fedhas - { ABIL_FEDHAS_EVOLUTION, "Evolution", - 2, 0, 0, 0, {fail_basis::invo, 30, 6, 20}, abflag::rations_or_piety }, { ABIL_FEDHAS_SPAWN_SPORES, "Reproduction", 4, 0, 100, 1, {fail_basis::invo, 60, 4, 25}, abflag::none }, { ABIL_FEDHAS_RAIN, "Rain", @@ -1571,8 +1569,6 @@ static bool _check_ability_possible(const ability_def& abil, bool quiet = false) } return true; - case ABIL_FEDHAS_EVOLUTION: - return fedhas_check_evolve_flora(quiet); case ABIL_FEDHAS_SPAWN_SPORES: { @@ -2883,9 +2879,6 @@ static spret _do_ability(const ability_def& abil, bool fail) break; } - case ABIL_FEDHAS_EVOLUTION: - return fedhas_evolve_flora(fail); - case ABIL_TRAN_BAT: { if (_player_cancels_vampire_bat_transformation()) diff --git a/crawl-ref/source/dat/descript/ability.txt b/crawl-ref/source/dat/descript/ability.txt index d4c4b695fcac..1b54975d2e90 100644 --- a/crawl-ref/source/dat/descript/ability.txt +++ b/crawl-ref/source/dat/descript/ability.txt @@ -498,14 +498,6 @@ Reproduction ability Creates ballistomycete spores from corpses in your line of sight. The spores will explode, causing damage to you or your enemies. %%%% -Evolution ability - -Turns plants and fungi into stronger species. Upgraded plants gain a bonus to attack -accuracy proportional to the user's Invocations skill, and oklob plants are -more likely to spit acid at higher Invocations. - -Upgrading fungi requires piety, while upgrading plants requires food. -%%%% # Cheibriados Bend Time ability diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc index 6e8c46f5ddb6..18412e164d67 100644 --- a/crawl-ref/source/directn.cc +++ b/crawl-ref/source/directn.cc @@ -2271,11 +2271,8 @@ static bool _mons_is_valid_target(const monster* mon, targ_mode_type mode, int range) { // Monsters that are no threat to you don't count as monsters. - if (mode != TARG_EVOLVABLE_PLANTS - && !mons_is_threatening(*mon)) - { + if (!mons_is_threatening(*mon)) return false; - } // Don't target submerged monsters. if (mode != TARG_HOSTILE_SUBMERGED && mon->submerged()) @@ -2313,8 +2310,6 @@ static bool _want_target_monster(const monster *mon, targ_mode_type mode, return true; return !mon->wont_attack() && !mon->neutral() && unpacifiable_reason(*mon).empty(); - case TARG_EVOLVABLE_PLANTS: - return mons_is_evolvable(mon); case TARG_BEOGH_GIFTABLE: return beogh_can_gift_items_to(mon); case TARG_MOVABLE_OBJECT: diff --git a/crawl-ref/source/god-abil.cc b/crawl-ref/source/god-abil.cc index 08e43723516e..fa3f0b62dfad 100644 --- a/crawl-ref/source/god-abil.cc +++ b/crawl-ref/source/god-abil.cc @@ -2311,74 +2311,6 @@ bool prioritise_adjacent(const coord_def &target, vector& candidates) return true; } -static bool _prompt_amount(int max, int& selected, const string& prompt) -{ - selected = max; - while (true) - { - msg::streams(MSGCH_PROMPT) << prompt << " (" << max << " max) " << endl; - - const int keyin = get_ch(); - - // Cancel - if (key_is_escape(keyin) || keyin == ' ' || keyin == '0') - { - canned_msg(MSG_OK); - return false; - } - - // Default is max - if (keyin == '\n' || keyin == '\r') - { - selected = max; - return true; - } - - // Otherwise they should enter a digit - if (isadigit(keyin)) - { - selected = keyin - '0'; - if (selected > 0 && selected <= max) - return true; - } - // else they entered some garbage? - } - - return false; -} - -static int _collect_rations(vector >& available_rations) -{ - int total = 0; - - for (int i = 0; i < ENDOFPACK; i++) - { - if (you.inv[i].defined() && you.inv[i].is_type(OBJ_FOOD, FOOD_RATION)) - { - total += you.inv[i].quantity; - available_rations.emplace_back(you.inv[i].quantity, i); - } - } - sort(available_rations.begin(), available_rations.end()); - - return total; -} - -static void _decrease_amount(vector >& available, int amount) -{ - const int total_decrease = amount; - for (const auto &avail : available) - { - const int decrease_amount = min(avail.first, amount); - amount -= decrease_amount; - dec_inv_item_quantity(avail.second, decrease_amount); - } - if (total_decrease > 1) - mprf("%d rations are consumed!", total_decrease); - else - mpr("A ration is consumed!"); -} - // Create a circle of water around the target, with a radius of // approximately 2. This turns normal floor tiles into shallow water // and turns (unoccupied) shallow water into deep water. There is a @@ -2588,203 +2520,6 @@ int fedhas_corpse_spores(beh_type attitude) return count; } - -struct monster_conversion -{ - monster_type new_type; - int piety_cost; - int ration_cost; -}; - -static const map conversions = -{ - { MONS_PLANT, { MONS_OKLOB_PLANT, 0, 2 } }, - { MONS_BUSH, { MONS_OKLOB_PLANT, 0, 2 } }, - { MONS_BURNING_BUSH, { MONS_OKLOB_PLANT, 0, 2 } }, - { MONS_OKLOB_SAPLING, { MONS_OKLOB_PLANT, 4, 0 } }, - { MONS_FUNGUS, { MONS_WANDERING_MUSHROOM, 3, 0 } }, - { MONS_TOADSTOOL, { MONS_WANDERING_MUSHROOM, 3, 0 } }, - { MONS_BALLISTOMYCETE, { MONS_HYPERACTIVE_BALLISTOMYCETE, 4, 0 } }, -}; - -bool mons_is_evolvable(const monster* mon) -{ - return conversions.count(mon->type) && !mon->has_ench(ENCH_PETRIFIED); -} - -bool fedhas_check_evolve_flora(bool quiet) -{ - for (monster_near_iterator mi(&you, LOS_NO_TRANS); mi; ++mi) - if (mons_is_evolvable(*mi)) - return true; - - if (!quiet) - mpr("No evolvable flora in sight."); - return false; -} - -static vector _evolution_name(const monster_info& mon) -{ - auto conv = map_find(conversions, mon.type); - if (conv && !mon.has_trivial_ench(ENCH_PETRIFIED)) - return { "can evolve into " + mons_type_name(conv->new_type, DESC_A) }; - else - return { "cannot be evolved" }; -} - -spret fedhas_evolve_flora(bool fail) -{ - dist spelld; - - direction_chooser_args args; - args.restricts = DIR_TARGET; - args.mode = TARG_EVOLVABLE_PLANTS; - args.range = LOS_RADIUS; - args.needs_path = false; - args.self = confirm_prompt_type::cancel; - args.show_floor_desc = true; - args.top_prompt = "Select plant or fungus to evolve."; - args.get_desc_func = _evolution_name; - - direction(spelld, args); - - if (!spelld.isValid) - { - // Check for user cancel. - canned_msg(MSG_OK); - return spret::abort; - } - - monster* const plant = monster_at(spelld.target); - - if (!plant) - { - if (feat_is_tree(env.grid(spelld.target))) - mpr("The tree has already reached the pinnacle of evolution."); - else - mpr("You must target a plant or fungus."); - return spret::abort; - } - - if (!mons_is_evolvable(plant)) - { - if (plant->type == MONS_BALLISTOMYCETE_SPORE) - mpr("You can evolve only complete plants, not seeds."); - else if (!mons_is_plant(*plant)) - mpr("Only plants or fungi may be evolved."); - else if (plant->has_ench(ENCH_PETRIFIED)) - mpr("Stone cannot grow or evolve."); - else - { - simple_monster_message(*plant, " has already reached the pinnacle" - " of evolution."); - } - - return spret::abort; - } - auto upgrade_ptr = map_find(conversions, plant->type); - ASSERT(upgrade_ptr); - monster_conversion upgrade = *upgrade_ptr; - - vector > collected_rations; - if (upgrade.ration_cost) - { - const int total_rations = _collect_rations(collected_rations); - - if (total_rations < upgrade.ration_cost) - { - mpr("Not enough rations available."); - return spret::abort; - } - } - - if (upgrade.piety_cost && upgrade.piety_cost > you.piety) - { - mpr("Not enough piety available."); - return spret::abort; - } - - fail_check(); - - switch (upgrade.new_type) - { - case MONS_OKLOB_PLANT: - { - if (plant->type == MONS_OKLOB_SAPLING) - simple_monster_message(*plant, " appears stronger."); - else - { - string evolve_desc = " can now spit acid"; - const int skill = you.skill(SK_INVOCATIONS); - if (skill >= 20) - evolve_desc += " continuously"; - else if (skill >= 15) - evolve_desc += " quickly"; - else if (skill >= 10) - evolve_desc += " rather quickly"; - else if (skill >= 5) - evolve_desc += " somewhat quickly"; - evolve_desc += "."; - - simple_monster_message(*plant, evolve_desc.c_str()); - } - break; - } - - case MONS_WANDERING_MUSHROOM: - simple_monster_message(*plant, " can now pick up its mycelia and move."); - break; - - case MONS_HYPERACTIVE_BALLISTOMYCETE: - simple_monster_message(*plant, " appears agitated."); - env.level_state |= LSTATE_GLOW_MOLD; - break; - - default: - break; - } - - plant->upgrade_type(upgrade.new_type, true, true); - - plant->flags |= MF_NO_REWARD; - plant->flags |= MF_ATT_CHANGE_ATTEMPT; - - mons_make_god_gift(*plant, GOD_FEDHAS); - - plant->attitude = ATT_FRIENDLY; - - behaviour_event(plant, ME_ALERT); - mons_att_changed(plant); - - // Try to remove slowly dying in case we are upgrading a - // toadstool, and spore production in case we are upgrading a - // ballistomycete. - plant->del_ench(ENCH_SLOWLY_DYING); - plant->del_ench(ENCH_SPORE_PRODUCTION); - - if (plant->type == MONS_HYPERACTIVE_BALLISTOMYCETE) - plant->add_ench(ENCH_EXPLODING); - else if (plant->type == MONS_OKLOB_PLANT) - { - // frequency will be set by set_hit_dice below - plant->spells = { { SPELL_SPIT_ACID, 0, MON_SPELL_NATURAL } }; - } - - plant->set_hit_dice(plant->get_experience_level() - + you.skill_rdiv(SK_INVOCATIONS)); - - if (upgrade.ration_cost) - _decrease_amount(collected_rations, upgrade.ration_cost); - - if (upgrade.piety_cost) - { - lose_piety(upgrade.piety_cost); - mpr("Your piety has decreased."); - } - - return spret::success; -} - static bool _lugonu_warp_monster(monster& mon, int pow) { if (coinflip()) diff --git a/crawl-ref/source/god-abil.h b/crawl-ref/source/god-abil.h index 0914bd7dfdf6..0634e265db9e 100644 --- a/crawl-ref/source/god-abil.h +++ b/crawl-ref/source/god-abil.h @@ -122,9 +122,6 @@ int fedhas_rain(const coord_def &target); int count_corpses_in_los(vector *positions); int fedhas_check_corpse_spores(bool quiet = false); int fedhas_corpse_spores(beh_type attitude = BEH_FRIENDLY); -bool mons_is_evolvable(const monster* mon); -bool fedhas_check_evolve_flora(bool quiet); -spret fedhas_evolve_flora(bool fail); void lugonu_bend_space(); diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index 16a29377f784..6a927ffdfdff 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -264,7 +264,6 @@ const vector god_powers[NUM_GODS] = // Fedhas { { 2, ABIL_FEDHAS_WALL_OF_BRIARS, "encircle yourself with summoned briar patches"}, - { 2, ABIL_FEDHAS_EVOLUTION, "induce evolution" }, { 4, ABIL_FEDHAS_SPAWN_SPORES, "spawn explosive spores" }, { 5, ABIL_FEDHAS_RAIN, "control the weather" }, }, diff --git a/crawl-ref/source/rltiles/dc-invocations.txt b/crawl-ref/source/rltiles/dc-invocations.txt index 0fd015b5bd3a..bbd610412557 100644 --- a/crawl-ref/source/rltiles/dc-invocations.txt +++ b/crawl-ref/source/rltiles/dc-invocations.txt @@ -20,7 +20,6 @@ elyvilon_greater_healing ABILITY_ELYVILON_GREATER_HEALING elyvilon_lesser_healing ABILITY_ELYVILON_LESSER_HEALING elyvilon_purification ABILITY_ELYVILON_PURIFICATION elyvilon_heal_other ABILITY_ELYVILON_HEAL_OTHER -fedhas_evolution ABILITY_FEDHAS_EVOLUTION fedhas_rain ABILITY_FEDHAS_RAIN fedhas_spawn_spores ABILITY_FEDHAS_SPAWN_SPORES fedhas_wall_of_briars ABILITY_FEDHAS_WALL_OF_BRIARS diff --git a/crawl-ref/source/rltiles/gui/invocations/fedhas_evolution.png b/crawl-ref/source/rltiles/gui/invocations/fedhas_evolution.png deleted file mode 100644 index ada89e16ec5dfd5a724e8fcaa548b2489cc46cdf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 364 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyx&b~Ru0R?Hcua+4(nJ(keGLo@ z92^{6*((#e_=Q>)#=%?6@O1wr%AV_D&6BeSSgZo<(vs; zqrY0&H_rUy^=A&Atm~Y8@vXSU`PL5x2RrZ9t$DU5%(!AEE8CP!*LF=4`ZRfi)!Yeg zjjU%P>QzF_Y{CmX`!}dA=VE$rJ==-%7r&{RgR4uqxlYzjwI3DB9j7mUq}0%)U47tP zqJ;K?@`z5MU<0)|bCZG(JaNqEm}3;>+Wc4Rt(9uTo>gmW^ec90v?S>t5ec?Z<%m8L zy(rPzBKo@0+w)7rL;CdpsdW7CzI0%&ff4sfGpl*;Js;}Zc@*))TAp~o4GJ_*S3j3^ HP6 Date: Tue, 10 Sep 2019 01:23:24 -0500 Subject: [PATCH 748/864] Fedhas rework part 6: simplify ballistomycetes Ballistomycetes (ballistos) are complicated monsters that grow based on interactions with the spore monsters. Spores leave mold as they move, which can give rise to the production of new ballistos. This set of behaviors fell into the realm of "complexity for the sake of complexity". One had to wait a while for this "reproduction" to play out, only to get a few more ballisto spores. Now that we're putting stronger limits on ally usage through use of summons, it's a good time to simplify the way ballistos and their spores work. This commit removes the reproduction aspect of ballistos, removes mold itself, and simplifies ballistos down to one type of monster. Additionally, ballistos now have a Sporulate natural ability they occasionally use to create a single spore as a short-lived summon. The spore will seek after the ballisto's target and explode upon hit, still producing the damaging explosion that applies confusion to living targets. A subsequent commit will make a Fedhas active ability to let the player to create a ballisto summon, and this will replace Fedhas' Reproduction. --- crawl-ref/source/beam.cc | 37 ----- crawl-ref/source/directn.cc | 11 +- crawl-ref/source/enchant-type.h | 2 +- crawl-ref/source/fprop.cc | 19 --- crawl-ref/source/fprop.h | 5 +- crawl-ref/source/level-state-type.h | 2 + crawl-ref/source/main.cc | 49 ------- crawl-ref/source/map-cell.h | 2 - crawl-ref/source/mgen-data.h | 2 +- crawl-ref/source/mon-act.cc | 57 -------- crawl-ref/source/mon-cast.cc | 14 ++ crawl-ref/source/mon-data.h | 23 +--- crawl-ref/source/mon-death.cc | 129 ------------------ crawl-ref/source/mon-ench.cc | 68 --------- crawl-ref/source/mon-spell.h | 6 + crawl-ref/source/rltiles/dc-mon.txt | 4 +- .../fungi_plants/active_ballistomycete.png | Bin 1263 -> 0 bytes .../mon/fungi_plants/ballistomycete.png | Bin 973 -> 1129 bytes .../hyperactive_ballistomycete.png | Bin 1129 -> 0 bytes crawl-ref/source/show.cc | 7 - crawl-ref/source/showsymb.cc | 2 - crawl-ref/source/spell-type.h | 1 + crawl-ref/source/spl-data.h | 11 ++ crawl-ref/source/stairs.cc | 14 -- crawl-ref/source/terrain.cc | 17 +-- crawl-ref/source/tilecell.cc | 4 - crawl-ref/source/tilecell.h | 12 +- crawl-ref/source/tiledgnbuf.cc | 10 -- crawl-ref/source/tileview.cc | 7 +- crawl-ref/source/tileweb.cc | 12 +- crawl-ref/source/timed-effects.cc | 4 - 31 files changed, 57 insertions(+), 474 deletions(-) delete mode 100644 crawl-ref/source/rltiles/mon/fungi_plants/active_ballistomycete.png delete mode 100644 crawl-ref/source/rltiles/mon/fungi_plants/hyperactive_ballistomycete.png diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc index dd3436f73fe0..e67237a24477 100644 --- a/crawl-ref/source/beam.cc +++ b/crawl-ref/source/beam.cc @@ -2555,43 +2555,6 @@ void bolt::affect_ground() if (is_tracer) return; - // Spore explosions might spawn a fungus. The spore explosion - // covers 21 tiles in open space, so the expected number of spores - // produced is the x in x_chance_in_y() in the conditional below. - if (is_explosion && flavour == BEAM_SPORE - && agent() && !agent()->is_summoned()) - { - if (env.grid(pos()) == DNGN_FLOOR) - env.pgrid(pos()) |= FPROP_MOLD; - - if (x_chance_in_y(2, 21) - && mons_class_can_pass(MONS_BALLISTOMYCETE, env.grid(pos())) - && !actor_at(pos())) - { - beh_type beh = attitude_creation_behavior(attitude); - // A friendly spore or hyperactive can exist only with Fedhas - // in which case the inactive ballistos spawned should be - // good_neutral to avoid hidden piety costs of Fedhas abilities - if (beh == BEH_FRIENDLY) - beh = BEH_GOOD_NEUTRAL; - - const god_type god = agent()->deity(); - - if (create_monster(mgen_data(MONS_BALLISTOMYCETE, - beh, - pos(), - MHITNOT, - MG_FORCE_PLACE, - god))) - { - remove_mold(pos()); - if (you.see_cell(pos())) - mpr("A fungus suddenly grows."); - - } - } - } - affect_place_clouds(); } diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc index 18412e164d67..761eceea8b40 100644 --- a/crawl-ref/source/directn.cc +++ b/crawl-ref/source/directn.cc @@ -2878,15 +2878,8 @@ string feature_description_at(const coord_def& where, bool covering, string covering_description = ""; - if (covering && you.see_cell(where)) - { - if (is_bloodcovered(where)) - covering_description = ", spattered with blood"; - else if (glowing_mold(where)) - covering_description = ", covered with glowing mould"; - else if (is_moldy(where)) - covering_description = ", covered with mould"; - } + if (covering && you.see_cell(where) && is_bloodcovered(where)) + covering_description = ", spattered with blood"; // FIXME: remove desc markers completely; only Zin walls are left. // They suffer, among other problems, from an information leak. diff --git a/crawl-ref/source/enchant-type.h b/crawl-ref/source/enchant-type.h index 749ce1c83652..04572d75d7be 100644 --- a/crawl-ref/source/enchant-type.h +++ b/crawl-ref/source/enchant-type.h @@ -49,8 +49,8 @@ enum enchant_type ENCH_EAT_ITEMS, #endif ENCH_AQUATIC_LAND, // Water monsters lose hp while on land. - ENCH_SPORE_PRODUCTION, #if TAG_MAJOR_VERSION == 34 + ENCH_SPORE_PRODUCTION, ENCH_SLOUCH, #endif ENCH_SWIFT, diff --git a/crawl-ref/source/fprop.cc b/crawl-ref/source/fprop.cc index 713b6820912e..e11a3788b239 100644 --- a/crawl-ref/source/fprop.cc +++ b/crawl-ref/source/fprop.cc @@ -32,31 +32,12 @@ bool is_tide_immune(const coord_def &p) return bool(env.pgrid(p) & FPROP_NO_TIDE); } -bool is_moldy(const coord_def & p) -{ - return env.pgrid(p) & FPROP_MOLD - || env.pgrid(p) & FPROP_GLOW_MOLD; -} - -bool glowing_mold(const coord_def & p) -{ - return bool(env.pgrid(p) & FPROP_GLOW_MOLD); -} - -void remove_mold(const coord_def & p) -{ - env.pgrid(p) &= ~FPROP_MOLD; - env.pgrid(p) &= ~FPROP_GLOW_MOLD; -} - feature_property_type str_to_fprop(const string &str) { if (str == "bloody") return FPROP_BLOODY; if (str == "highlight") return FPROP_HIGHLIGHT; - if (str == "mold") - return FPROP_MOLD; if (str == "no_cloud_gen") return FPROP_NO_CLOUD_GEN; if (str == "no_tele_into") diff --git a/crawl-ref/source/fprop.h b/crawl-ref/source/fprop.h index 0c0a50b846b4..156517353272 100644 --- a/crawl-ref/source/fprop.h +++ b/crawl-ref/source/fprop.h @@ -20,8 +20,10 @@ enum feature_property_type // Squares that the tide should not affect. FPROP_NO_TIDE = (1 << 10), FPROP_NO_SUBMERGE = (1 << 11), +#if TAG_MAJOR_VERSION == 34 FPROP_MOLD = (1 << 12), FPROP_GLOW_MOLD = (1 << 13), +#endif // Immune to spawning jellies and off-level eating. FPROP_NO_JIYVA = (1 << 14), // Permanent, unlike map memory. @@ -36,8 +38,5 @@ DEF_BITFIELD(terrain_property_t, feature_property_type); bool is_sanctuary(const coord_def& p); bool is_bloodcovered(const coord_def& p); bool is_tide_immune(const coord_def &p); -bool is_moldy(const coord_def & p); -bool glowing_mold(const coord_def & p); -void remove_mold(const coord_def & p); feature_property_type str_to_fprop(const string &str); char blood_rotation(const coord_def & p); diff --git a/crawl-ref/source/level-state-type.h b/crawl-ref/source/level-state-type.h index 6012f094b25e..8704b95be267 100644 --- a/crawl-ref/source/level-state-type.h +++ b/crawl-ref/source/level-state-type.h @@ -6,7 +6,9 @@ enum level_state_type LSTATE_NONE = 0, LSTATE_GOLUBRIA = (1 << 0), // A Golubria trap exists. +#if TAG_MAJOR_VERSION == 34 LSTATE_GLOW_MOLD = (1 << 1), // Any glowing mold exists. +#endif LSTATE_DELETED = (1 << 2), // The level won't be saved. LSTATE_BEOGH = (1 << 3), // Possibly an orcish priest around. LSTATE_SLIMY_WALL = (1 << 4), // Any slime walls exist. diff --git a/crawl-ref/source/main.cc b/crawl-ref/source/main.cc index 865af776ca5f..526e387d473c 100644 --- a/crawl-ref/source/main.cc +++ b/crawl-ref/source/main.cc @@ -2127,53 +2127,6 @@ static void _check_trapped() } } -static void _update_mold_state(const coord_def & pos) -{ - if (coinflip()) - { - // Doing a weird little state thing with the two mold - // fprops. 'glowing' mold should turn back to normal after - // a couple display update (i.e. after the player makes their - // next move), since we happen to have two bits dedicated to - // mold now we may as well use them? -cao - if (env.pgrid(pos) & FPROP_MOLD) - env.pgrid(pos) &= ~FPROP_MOLD; - else - { - env.pgrid(pos) |= FPROP_MOLD; - env.pgrid(pos) &= ~FPROP_GLOW_MOLD; - } - } -} - -static void _update_mold() -{ - env.level_state &= ~LSTATE_GLOW_MOLD; // we'll restore it if any - - for (rectangle_iterator ri(0); ri; ++ri) - { - if (glowing_mold(*ri)) - { - _update_mold_state(*ri); - env.level_state |= LSTATE_GLOW_MOLD; - } - } - for (monster_iterator mon_it; mon_it; ++mon_it) - { - if (mon_it->type == MONS_HYPERACTIVE_BALLISTOMYCETE) - { - for (radius_iterator rad_it(mon_it->pos(), 2, C_SQUARE); - rad_it; ++rad_it) - { - // Matche the blast of a radius 2 explosion. - env.pgrid(*rad_it) |= FPROP_MOLD; - env.pgrid(*rad_it) |= FPROP_GLOW_MOLD; - } - env.level_state |= LSTATE_GLOW_MOLD; - } - } -} - static void _update_golubria_traps() { vector traps = find_golubria_on_level(); @@ -2279,8 +2232,6 @@ void world_reacts() handle_time(); manage_clouds(); - if (env.level_state & LSTATE_GLOW_MOLD) - _update_mold(); if (env.level_state & LSTATE_GOLUBRIA) _update_golubria_traps(); if (env.level_state & LSTATE_STILL_WINDS) diff --git a/crawl-ref/source/map-cell.h b/crawl-ref/source/map-cell.h index 6dc1d384845f..6eb08e1e8346 100644 --- a/crawl-ref/source/map-cell.h +++ b/crawl-ref/source/map-cell.h @@ -23,8 +23,6 @@ /* these flags require more space to serialize: put infrequently used ones there */ #define MAP_EXCLUDED_STAIRS 0x10000 -#define MAP_MOLDY 0x20000 -#define MAP_GLOWING_MOLDY 0x40000 #define MAP_SANCTUARY_1 0x80000 #define MAP_SANCTUARY_2 0x100000 #define MAP_WITHHELD 0x200000 diff --git a/crawl-ref/source/mgen-data.h b/crawl-ref/source/mgen-data.h index 7081140e94af..8828c5ed731a 100644 --- a/crawl-ref/source/mgen-data.h +++ b/crawl-ref/source/mgen-data.h @@ -172,7 +172,7 @@ struct mgen_data ASSERT(summon_type == 0 || abjuration_dur >= 1 && abjuration_dur <= 6 || cls == MONS_BALL_LIGHTNING || cls == MONS_ORB_OF_DESTRUCTION - || cls == MONS_BATTLESPHERE + || cls == MONS_BATTLESPHERE || cls == MONS_BALLISTOMYCETE_SPORE || summon_type == SPELL_STICKS_TO_SNAKES || summon_type == SPELL_DEATH_CHANNEL || summon_type == SPELL_BIND_SOULS diff --git a/crawl-ref/source/mon-act.cc b/crawl-ref/source/mon-act.cc index bded8b1ebb62..3ebf8816109c 100644 --- a/crawl-ref/source/mon-act.cc +++ b/crawl-ref/source/mon-act.cc @@ -3095,60 +3095,6 @@ static void _jelly_grows(monster& mons) _jelly_divide(mons); } -/** - * Possibly place mold & ballistomycetes in ballistomycete spores' wake. - * - * @param mons The ballistomycete spore in question. - * @param position Its last location. (Where to place the ballistomycete.) - */ -static void _ballisto_on_move(monster& mons, const coord_def& position) -{ - if (mons.type != MONS_BALLISTOMYCETE_SPORE - || mons.is_summoned()) - { - return; - } - - // place mold under the spore's current tile, if there isn't any now. - const dungeon_feature_type current_ftype = env.grid(mons.pos()); - if (current_ftype == DNGN_FLOOR) - env.pgrid(mons.pos()) |= FPROP_MOLD; - - if (mons.spore_cooldown > 0) - { - mons.spore_cooldown--; - return; - } - - if (!one_chance_in(4)) - return; - - // Try to make a ballistomycete. - beh_type attitude = attitude_creation_behavior(mons.attitude); - // Make Fedhas ballistos neutral, so as not to inflict extra piety loss. - if (mons_is_god_gift(mons, GOD_FEDHAS)) - attitude = BEH_GOOD_NEUTRAL; - - monster *plant = create_monster(mgen_data(MONS_BALLISTOMYCETE, attitude, - position, MHITNOT, - MG_FORCE_PLACE)); - - if (!plant) - return; - - // Don't leave mold on squares we place ballistos on - remove_mold(position); - - if (you.can_see(*plant)) - { - mprf("%s grows in the wake of %s.", - plant->name(DESC_A).c_str(), mons.name(DESC_THE).c_str()); - } - - // reset the cooldown. - mons.spore_cooldown = 40; -} - bool monster_swaps_places(monster* mon, const coord_def& delta, bool takes_time, bool apply_effects) { @@ -3311,12 +3257,9 @@ static bool _do_move_monster(monster& mons, const coord_def& delta) mons.seen_context = SC_NONSWIMMER_SURFACES_FROM_DEEP; } - coord_def old_pos = mons.pos(); - mons.move_to_pos(f, false); mons.check_clinging(true); - _ballisto_on_move(mons, old_pos); // Let go of all constrictees; only stop *being* constricted if we are now // too far away (done in move_to_pos above). diff --git a/crawl-ref/source/mon-cast.cc b/crawl-ref/source/mon-cast.cc index 43a83f5dc5b9..cf9e617103b8 100644 --- a/crawl-ref/source/mon-cast.cc +++ b/crawl-ref/source/mon-cast.cc @@ -1912,6 +1912,7 @@ bool setup_mons_cast(const monster* mons, bolt &pbolt, spell_type spell_cast, case SPELL_GREATER_SERVANT_MAKHLEB: case SPELL_BIND_SOULS: case SPELL_DREAM_DUST: + case SPELL_SPORULATE: pbolt.range = 0; pbolt.glyph = 0; return true; @@ -6879,6 +6880,19 @@ void mons_cast(monster* mons, bolt pbolt, spell_type spell_cast, _mons_upheaval(*mons, *foe); return; + case SPELL_SPORULATE: + { + mgen_data spored (MONS_BALLISTOMYCETE_SPORE, + mons->friendly() ? BEH_FRIENDLY : BEH_HOSTILE, mons->pos(), + mons->foe); + spored.set_summoned(mons, 0, SPELL_SPORULATE); + + if (monster *spore = create_monster(spored)) + spore->add_ench(ENCH_SHORT_LIVED); + + return; + } + } if (spell_is_direct_explosion(spell_cast)) diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h index cba6c89e5216..986ae2671cf0 100644 --- a/crawl-ref/source/mon-data.h +++ b/crawl-ref/source/mon-data.h @@ -278,6 +278,7 @@ static monsterentry mondata[] = AXED_MON(MONS_DRACONIAN_ZEALOT) AXED_MON(MONS_HILL_GIANT) AXED_MON(MONS_BULTUNGIN) + AXED_MON(MONS_HYPERACTIVE_BALLISTOMYCETE) #endif // Used for genus monsters (which are used for grouping monsters by how they @@ -3974,29 +3975,15 @@ DUMMY(MONS_MERGED_SLIME_CREATURE, 'J', LIGHTGREEN, "merged slime creature", { MONS_BALLISTOMYCETE, 'P', MAGENTA, "ballistomycete", - M_NOT_DANGEROUS | M_STATIONARY, + M_STATIONARY, MR_RES_POISON, 10, MONS_FUNGUS, MONS_BALLISTOMYCETE, MH_PLANT, MAG_IMMUNE, { AT_NO_ATK, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, 4, 260, - 1, 0, MST_NO_SPELLS, CE_NOCORPSE, S_SILENT, - I_BRAINLESS, HT_LAND, 0, DEFAULT_ENERGY, - MONUSE_NOTHING, SIZE_TINY, MON_SHAPE_FUNGUS, - {TILEP_MONS_BALLISTOMYCETE_INACTIVE}, TILE_ERROR -}, - -{ - MONS_HYPERACTIVE_BALLISTOMYCETE, 'P', LIGHTRED, "hyperactive ballistomycete", - M_NO_EXP_GAIN | M_STATIONARY | M_NO_POLY_TO, - MR_RES_POISON, - 10, MONS_FUNGUS, MONS_BALLISTOMYCETE, MH_PLANT, MAG_IMMUNE, - { AT_NO_ATK, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, - // expected explosion damage: 25, expected HP: 60 - 6, 600, - 1, 0, MST_NO_SPELLS, CE_NOCORPSE, S_SILENT, - I_BRAINLESS, HT_LAND, 0, DEFAULT_ENERGY, + 1, 0, MST_BALLISTOMYCETE, CE_NOCORPSE, S_SILENT, + I_BRAINLESS, HT_LAND, 10, DEFAULT_ENERGY, MONUSE_NOTHING, SIZE_TINY, MON_SHAPE_FUNGUS, - {TILEP_MONS_HYPERACTIVE_BALLISTOMYCETE}, TILE_ERROR + {TILEP_MONS_BALLISTOMYCETE}, TILE_ERROR }, { diff --git a/crawl-ref/source/mon-death.cc b/crawl-ref/source/mon-death.cc index 697de541d053..300d59e21c94 100644 --- a/crawl-ref/source/mon-death.cc +++ b/crawl-ref/source/mon-death.cc @@ -1057,128 +1057,6 @@ static void _search_dungeon(const coord_def & start, } } -static bool _ballisto_at(const coord_def & target) -{ - monster* mons = monster_at(target); - return mons && mons->type == MONS_BALLISTOMYCETE - && mons->alive(); -} - -static bool _mold_connected(const coord_def & target) -{ - return is_moldy(target) || _ballisto_at(target); -} - -// If 'monster' is a ballistomycete or spore, activate some number of -// ballistomycetes on the level. -static void _activate_ballistomycetes(monster* mons, const coord_def& origin, - bool player_kill) -{ - if (!mons || mons->is_summoned() - || mons->mons_species() != MONS_BALLISTOMYCETE - && mons->type != MONS_BALLISTOMYCETE_SPORE) - { - return; - } - - // If a spore or inactive ballisto died we will only activate one - // other ballisto. If it was an active ballisto we will distribute - // its count to others on the level. - int activation_count = 1; - if (mons->type == MONS_BALLISTOMYCETE) - activation_count += mons->ballisto_activity; - if (mons->type == MONS_HYPERACTIVE_BALLISTOMYCETE) - activation_count = 0; - - int non_activable_count = 0; - int ballisto_count = 0; - - for (monster_iterator mi; mi; ++mi) - { - if (mi->mindex() != mons->mindex() && mi->alive()) - { - if (mi->type == MONS_BALLISTOMYCETE) - ballisto_count++; - else if (mi->type == MONS_BALLISTOMYCETE_SPORE - || mi->type == MONS_HYPERACTIVE_BALLISTOMYCETE) - { - non_activable_count++; - } - } - } - - bool exhaustive = true; - bool (*valid_target)(const coord_def &) = _ballisto_at; - bool (*connecting_square) (const coord_def &) = _mold_connected; - - set visited; - vector::iterator > candidates; - - _search_dungeon(origin, valid_target, connecting_square, visited, - candidates, exhaustive); - - if (candidates.empty()) - { - if (non_activable_count == 0 - && ballisto_count == 0 - && mons->attitude == ATT_HOSTILE) - { - if (player_kill) - mpr("The fungal colony is destroyed."); - - // Get rid of the mold, so it'll be more useful when new fungi - // spawn. - for (rectangle_iterator ri(1); ri; ++ri) - remove_mold(*ri); - } - - return; - } - - // A (very) soft cap on colony growth, no activations if there are - // already a lot of ballistos on level. - if (candidates.size() > 25) - return; - - shuffle_array(candidates); - - int index = 0; - - for (int i = 0; i < activation_count; ++i) - { - index = i % candidates.size(); - - monster* spawner = monster_at(candidates[index]->pos); - - // This may be the players position, in which case we don't - // have to mess with spore production on anything - if (spawner) - { - spawner->ballisto_activity++; - - // Change color and start the spore production timer if we - // are moving from 0 to 1. - if (spawner->ballisto_activity == 1) - { - spawner->colour = LIGHTMAGENTA; - // Reset the spore production timer. - spawner->del_ench(ENCH_SPORE_PRODUCTION, false); - spawner->add_ench(ENCH_SPORE_PRODUCTION); - } - } - - const position_node* thread = &(*candidates[index]); - while (thread) - { - if (!one_chance_in(3)) - env.pgrid(thread->pos) |= FPROP_GLOW_MOLD; - - thread = thread->last; - } - env.level_state |= LSTATE_GLOW_MOLD; - } -} - static void _setup_base_explosion(bolt & beam, const monster& origin) { beam.is_tracer = false; @@ -1404,7 +1282,6 @@ static bool _explode_monster(monster* mons, killer_type killer, else beam.explode(); - _activate_ballistomycetes(mons, beam.target, YOU_KILL(beam.killer())); // Monster died in explosion, so don't re-attach it to the grid. return true; } @@ -2629,12 +2506,6 @@ item_def* monster_die(monster& mons, killer_type killer, _make_derived_undead(&mons, !death_message, false); } - if (mons.mons_species() == MONS_BALLISTOMYCETE) - { - _activate_ballistomycetes(&mons, mons.pos(), - YOU_KILL(killer) || pet_kill); - } - if (!wizard && !submerged && !was_banished) { _monster_die_cloud(&mons, !fake_abjure && !timeout && !mons_reset, diff --git a/crawl-ref/source/mon-ench.cc b/crawl-ref/source/mon-ench.cc index c72b332a7dcb..55db95729783 100644 --- a/crawl-ref/source/mon-ench.cc +++ b/crawl-ref/source/mon-ench.cc @@ -1541,69 +1541,6 @@ void monster::apply_enchantment(const mon_enchant &me) } break; - case ENCH_SPORE_PRODUCTION: - // Reduce the timer, if that means we lose the enchantment then - // spawn a spore and re-add the enchantment. - if (decay_enchantment(en)) - { - bool re_add = true; - - for (fair_adjacent_iterator ai(pos()); ai; ++ai) - { - if (mons_class_can_pass(MONS_BALLISTOMYCETE_SPORE, grd(*ai)) - && !actor_at(*ai)) - { - beh_type plant_attitude = SAME_ATTITUDE(this); - - if (monster *plant = create_monster(mgen_data(MONS_BALLISTOMYCETE_SPORE, - plant_attitude, - *ai, - MHITNOT, - MG_FORCE_PLACE))) - { - if (mons_is_god_gift(*this, GOD_FEDHAS)) - { - plant->flags |= MF_NO_REWARD; - - if (plant_attitude == BEH_FRIENDLY) - { - plant->flags |= MF_ATT_CHANGE_ATTEMPT; - - mons_make_god_gift(*plant, GOD_FEDHAS); - } - } - - plant->behaviour = BEH_WANDER; - plant->spore_cooldown = 20; - - if (you.see_cell(*ai) && you.see_cell(pos())) - mpr("A ballistomycete spawns a ballistomycete spore."); - - // Decrease the count and maybe become inactive - // again. - if (ballisto_activity) - { - ballisto_activity--; - if (ballisto_activity == 0) - { - colour = MAGENTA; - del_ench(ENCH_SPORE_PRODUCTION); - re_add = false; - } - } - - } - break; - } - } - // Re-add the enchantment (this resets the spore production - // timer). - if (re_add) - add_ench(ENCH_SPORE_PRODUCTION); - } - - break; - case ENCH_EXPLODING: { // Reduce the timer, if that means we lose the enchantment then @@ -2307,11 +2244,6 @@ int mon_enchant::calc_duration(const monster* mons, return (2 * FRESHEST_CORPSE + random2(10)) * dur; } - case ENCH_SPORE_PRODUCTION: - // This is used as a simple timer, when the enchantment runs out - // the monster will create a ballistomycete spore. - return random_range(475, 525) * 10; - case ENCH_EXPLODING: return random_range(3, 7) * 10; diff --git a/crawl-ref/source/mon-spell.h b/crawl-ref/source/mon-spell.h index 3afb28ba9138..c59f8388e42d 100644 --- a/crawl-ref/source/mon-spell.h +++ b/crawl-ref/source/mon-spell.h @@ -1205,6 +1205,12 @@ static const mon_spellbook mspell_list[] = } }, + { MST_BALLISTOMYCETE, + { + { SPELL_SPORULATE, 67, MON_SPELL_NATURAL }, + } + }, + // ('Q') Tengu. { MST_TENGU_CONJURER_I, { diff --git a/crawl-ref/source/rltiles/dc-mon.txt b/crawl-ref/source/rltiles/dc-mon.txt index 09f0dd08f034..434e12efe5e0 100644 --- a/crawl-ref/source/rltiles/dc-mon.txt +++ b/crawl-ref/source/rltiles/dc-mon.txt @@ -938,9 +938,7 @@ fungus6 fungus7 fungus8 fungus9 -ballistomycete MONS_BALLISTOMYCETE_INACTIVE -active_ballistomycete -hyperactive_ballistomycete MONS_HYPERACTIVE_BALLISTOMYCETE +ballistomycete MONS_BALLISTOMYCETE wandering_mushroom MONS_WANDERING_MUSHROOM deathcap MONS_DEATHCAP %rim 1 diff --git a/crawl-ref/source/rltiles/mon/fungi_plants/active_ballistomycete.png b/crawl-ref/source/rltiles/mon/fungi_plants/active_ballistomycete.png deleted file mode 100644 index fcd5331784167e627a8180a043acafb49355cca7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1263 zcmd5+{WIGK9RAEpy{uK;vKDPeuV~G7Ue>FZrBq5usS*)g(lE0nh!mwnBm}vZR3aiF z5sBB)lvAR^%*yG8YfZVe^Zw4cmCnAYNZn2|{V(?1^K#Gc&pkz9p@E0YZOj4S5H`pk zx1VWVj3f{UQBhGu ztP>IIMIw=I1bdUMfczyyM@LgA6e^V(A0MBPkdT;|n3R-6CwkF|*c3ZR!9eOhV=gcl zjI8s(WHPfofaM7+7K`l#Y&JV5CnuMV<)DE>!sg}W zfuJN1gh3z_3QJ2%MI4fdLl=oeWt^L04-n%)oR=)YLj^ZRCX>lC;^cC z8Y$2uqTd%Mx5zWvQ$bCD&IV3zudMH(qCXz`A1a@8)cx8~_ge`JCd1(155u=$3o8Xe^CDP~z#P&?w+d9c=SpTL{~Y zu&n~E5VWPBEeCBIXxm|@0(PXZQwcjAu=5CXHK3~n-A|wwo9ZQ|dYP%d&RpO4ph9r*4hX&x!^-7J6}5Hs!%wGX7M7OR*8ko@G+N!; zy>|=4_KW*_bj14m;Th9x5ta0@AL?>oyYo(Tzd+O+K9Ns9!{JqiSMn{}?GrcWe)N#G z(Y72C)xyHtCpRyA);IEVlE$i|d3_^W`PG|wYmEtLVlGCEL$G1ssRssJ3{R!fyBFIc z*R7`KS}ds((Y-a+E^-?i)XnFSXPepo{*@o&$0yz(~b&~^_De5zvY z{W4rYiaHoEhDSEDq_pr}6)isWif5W`LwBO`;sU}R=yGMP*k#g9cHWZ6R&4t_dfqCbbj zDewj^m&@}3zAy0ke1SkvSXfxZA_%F3;^N}l>RyLZCbp%FD|uLZPCfLV^d0 zL{eEFDh4>EruNNO(dbzo_JqLRqgG9GaS$UtC&V zeY>T5x3~Y{P(MG2SpYCb5rV%Zai&?)Ro=KeQhPi#Xo{!a#N}KOqEh1-=;IE*x~f=C z5=f5f2x}tQd*d-!dp%{OJ&5x4mT6$&uKv?&#Yn?N;o5-Y&si%cv55$!@i3KPt_N(H zqT0RU_Yr1?u@6fZCMQ=P`S0o#W0}lbnlpR7qT2HxgAOOOlO;&w>Gh#u_Rw0OHiM>~ z4um!)yAj`6DBp1~s zh@?a7_0bnLuRQI>8q=|=Hmf_As?AfC15sF`q+x!3O4g@4+>aNGWp?9TL>D^~(uUeS zDO#X8r}*l*vgK4jq=Paw4Pj@?-=?HgStWZ-AQ{(Nn%%6qZf40=*=G6|e7%jycV*PP zw+He@2T5II-QA|9UW`O=u%xT9{bM9>y=d|aPfMgp`@h-y9q%=rs<8L>Rwg<($Pph@ z?aw+C3SNHOXqW5G_s*U4yF0}vvF1owTwu=%+BCN~9ZSfeb z?4r^1iiGeKjIZ?!|B`Mw4wGu(E3>Y|XZ;0w|FhFA=%LLq&t&?z uU>dNYeO;J=YklY&rH$S{JC1GY?is+fc?^ASSZ?w8FbE-$!B22WxBml;y1bkK delta 962 zcmV;z13mod2+aqO8Gi-<0047(dh`GQ1C&WbK~#9!)tBE(lVKFcA0niSF1zh2D7+J* z)G`Cna@dt@6P&q=?A@H3Vm6&~>NLxg6rF;tv3@wCFiT4^Ny~*|M)e0o7f}#hbX5>_ z)#;q~@z^_fw`qGRI`HB3-OcxV&i6derug3rn13SbEtd2me}BUS5G^Qn(IQ|$5fDEu zV5$Z&3kV|`bH)q%N(A&HcN_vH6=`6;Nx*akiWf_I5$^$GO@LA?#a9{yJPim~MbWsM z3?MC%2R5DpB4c3_J2MmCFS~tsM!;gLfY)eX%`4!U=ePI^G_>p#aK+3f0 zP`n#sXd`hZ(MZIKMl6VCDRuaajHQbQS~2&>EhLWkaS}~v$U|Z*tYZY3Jt^S63nQ`c z@zmufGLB>=HE<2PpZ8+!ZM1mQy;ewn3SrG2P#pBEk$+L>@g1qs6?dTXd)URJvjSpv z?5Lgu2o~2jLotvr$H0cn`X=5ZyOS>8B;{HsN551@;;F|UuaQgVvY4Z2rW0bBN$28LV}6nGfoy?zY#Sk z2U9I$`hNl<6!buR`YNoh-h{=)uxh66umEQs!K0>5C5~JcNlW^Y25hi0I}XdpRHPZ^ zCW0{9)c|8XcIa+60k=mRpwnZ5TOp776vB7|DofK*bs7_)p!yzZJ_U{TBQO%I2T!F5 z$%m@4L#YIRARmyANK9;@fQ^uWpv?r8ru=oX!GDyW4GxDRl`wC9nfSwk^73*}6a@wb z2Egz4tMv8tK~GN)IGs)~o6V`jKOuWW1_gzMg=&`_9UU76+S}XdGe%GNEz*e;AloxG zP+eUOgM)(*2n04JP+MC|;_3v7ii))2-;g{ZYn$N8G=ia_A)bI5huiHYaXkZH5W6s_ zpntTq6o!X~ArgtO0g8k2Cuj;}fQ)D_n#+b6@cDcYi^ZU;t4q%Sy(dn=sN(TQqfrQl z!z4sea0K+E?%4og_%CEtFcb>W0%{GgI4vbFVnPIl8X&l1{@dkpslqJIPyWs~RGd4m zsHk93hK2Q}P$FdQ$oTj%Hk*wuAocw71UoDiO9ED_l??LwBO`;sU}R=yGMP*k#g9cHWZ6R&4t_dfqCbbj zDewj^m&@}3zAy0ke1SkvSXfxZA_%F3;^N}l>RyLZCbp%FD|uLZPCfLV^d0 zL{eEFDh4>EruNNO(dbzo_JqLRqgG9GaS$UtC&V zeY>T5x3~Y{P(MG2SpYCb5rV%Zai&?)Ro=KeQhPi#Xo{!a#N}KOqEh1-=;IE*x~f=C z5=f5f2x}tQd*d-!dp%{OJ&5x4mT6$&uKv?&#Yn?N;o5-Y&si%cv55$!@i3KPt_N(H zqT0RU_Yr1?u@6fZCMQ=P`S0o#W0}lbnlpR7qT2HxgAOOOlO;&w>Gh#u_Rw0OHiM>~ z4um!)yAj`6DBp1~s zh@?a7_0bnLuRQI>8q=|=Hmf_As?AfC15sF`q+x!3O4g@4+>aNGWp?9TL>D^~(uUeS zDO#X8r}*l*vgK4jq=Paw4Pj@?-=?HgStWZ-AQ{(Nn%%6qZf40=*=G6|e7%jycV*PP zw+He@2T5II-QA|9UW`O=u%xT9{bM9>y=d|aPfMgp`@h-y9q%=rs<8L>Rwg<($Pph@ z?aw+C3SNHOXqW5G_s*U4yF0}vvF1owTwu=%+BCN~9ZSfeb z?4r^1iiGeKjIZ?!|B`Mw4wGu(E3>Y|XZ;0w|FhFA=%LLq&t&?z uU>dNYeO;J=YklY&rH$S{JC1GY?is+fc?^ASSZ?w8FbE-$!B22WxBml;y1bkK diff --git a/crawl-ref/source/show.cc b/crawl-ref/source/show.cc index 9b881d0cdff0..3dbe1241d84a 100644 --- a/crawl-ref/source/show.cc +++ b/crawl-ref/source/show.cc @@ -167,13 +167,6 @@ static void _update_feat_at(const coord_def &gp) if (is_bloodcovered(gp)) env.map_knowledge(gp).flags |= MAP_BLOODY; - if (is_moldy(gp)) - { - env.map_knowledge(gp).flags |= MAP_MOLDY; - if (glowing_mold(gp)) - env.map_knowledge(gp).flags |= MAP_GLOWING_MOLDY; - } - if (env.level_state & LSTATE_SLIMY_WALL && slime_wall_neighbour(gp)) env.map_knowledge(gp).flags |= MAP_CORRODING; diff --git a/crawl-ref/source/showsymb.cc b/crawl-ref/source/showsymb.cc index 56ea37319886..8fee4762eb28 100644 --- a/crawl-ref/source/showsymb.cc +++ b/crawl-ref/source/showsymb.cc @@ -78,8 +78,6 @@ static unsigned short _cell_feat_show_colour(const map_cell& cell, } else if (cell.flags & MAP_BLOODY && !norecolour) colour = RED; - else if (cell.flags & MAP_MOLDY && !norecolour) - colour = (cell.flags & MAP_GLOWING_MOLDY) ? LIGHTRED : LIGHTGREEN; else if (cell.flags & MAP_CORRODING && !norecolour && !feat_is_wall(feat) && !feat_is_lava(feat) && !feat_is_water(feat)) diff --git a/crawl-ref/source/spell-type.h b/crawl-ref/source/spell-type.h index 3bba2aeed2f4..a3e6d3f7ffe9 100644 --- a/crawl-ref/source/spell-type.h +++ b/crawl-ref/source/spell-type.h @@ -463,5 +463,6 @@ enum spell_type : int SPELL_GRASPING_ROOTS, SPELL_SONIC_WAVE, SPELL_THROW_PIE, + SPELL_SPORULATE, NUM_SPELLS }; diff --git a/crawl-ref/source/spl-data.h b/crawl-ref/source/spl-data.h index b4ce58c2ae8c..955d06ab9139 100644 --- a/crawl-ref/source/spl-data.h +++ b/crawl-ref/source/spl-data.h @@ -4013,6 +4013,17 @@ static const struct spell_desc spelldata[] = TILEG_GENERIC_MONSTER_SPELL, }, +{ + SPELL_SPORULATE, "Sporulate", + spschool::conjuration | spschool::earth, + spflag::monster | spflag::selfench, + 5, + 200, + -1, -1, + 5, 0, + TILEG_GENERIC_MONSTER_SPELL, +}, + { SPELL_NO_SPELL, "nonexistent spell", spschool::none, diff --git a/crawl-ref/source/stairs.cc b/crawl-ref/source/stairs.cc index fe95b87f54e4..bdb96726067b 100644 --- a/crawl-ref/source/stairs.cc +++ b/crawl-ref/source/stairs.cc @@ -1071,18 +1071,6 @@ void down_stairs(dungeon_feature_type force_stair, bool force_known_shaft, bool take_stairs(force_stair, false, force_known_shaft, update_travel_cache); } -static bool _any_glowing_mold() -{ - for (rectangle_iterator ri(0); ri; ++ri) - if (glowing_mold(*ri)) - return true; - for (monster_iterator mon_it; mon_it; ++mon_it) - if (mon_it->type == MONS_HYPERACTIVE_BALLISTOMYCETE) - return true; - - return false; -} - static void _update_level_state() { env.level_state = 0; @@ -1091,8 +1079,6 @@ static void _update_level_state() if (!golub.empty()) env.level_state |= LSTATE_GOLUBRIA; - if (_any_glowing_mold()) - env.level_state |= LSTATE_GLOW_MOLD; for (monster_iterator mon_it; mon_it; ++mon_it) { if (mons_allows_beogh(**mon_it)) diff --git a/crawl-ref/source/terrain.cc b/crawl-ref/source/terrain.cc index 86f394396c7c..b5741e714b2d 100644 --- a/crawl-ref/source/terrain.cc +++ b/crawl-ref/source/terrain.cc @@ -1158,28 +1158,22 @@ static bool _dgn_check_terrain_monsters(const coord_def &pos) return false; } -// Clear blood or mold off of terrain that shouldn't have it. Also clear -// of blood if a bloody wall has been dug out and replaced by a floor, -// or if a bloody floor has been replaced by a wall. +// Clear blood or off of terrain that shouldn't have it. Also clear of blood if +// a bloody wall has been dug out and replaced by a floor, or if a bloody floor +// has been replaced by a wall. static void _dgn_check_terrain_covering(const coord_def &pos, dungeon_feature_type old_feat, dungeon_feature_type new_feat) { - if (!testbits(env.pgrid(pos), FPROP_BLOODY) - && !is_moldy(pos)) - { + if (!testbits(env.pgrid(pos), FPROP_BLOODY)) return; - } if (new_feat == DNGN_UNSEEN) { // Caller has already changed the grid, and old_feat is actually // the new feat. if (old_feat != DNGN_FLOOR && !feat_is_solid(old_feat)) - { env.pgrid(pos) &= ~(FPROP_BLOODY); - remove_mold(pos); - } } else { @@ -1188,7 +1182,6 @@ static void _dgn_check_terrain_covering(const coord_def &pos, || feat_is_critical(new_feat)) { env.pgrid(pos) &= ~(FPROP_BLOODY); - remove_mold(pos); } } } @@ -1858,8 +1851,6 @@ void destroy_wall(const coord_def& p) if (is_bloodcovered(p)) env.pgrid(p) &= ~(FPROP_BLOODY); - remove_mold(p); - _revert_terrain_to_floor(p); env.level_map_mask(p) |= MMT_TURNED_TO_FLOOR; } diff --git a/crawl-ref/source/tilecell.cc b/crawl-ref/source/tilecell.cc index 89114ed0914a..169cb6677d48 100644 --- a/crawl-ref/source/tilecell.cc +++ b/crawl-ref/source/tilecell.cc @@ -31,8 +31,6 @@ void packed_cell::clear() is_bloody = false; is_silenced = false; halo = HALO_NONE; - is_moldy = false; - glowing_mold = false; is_sanctuary = false; is_liquefied = false; mangrove_water = false; @@ -57,8 +55,6 @@ bool packed_cell::operator ==(const packed_cell &other) const if (is_bloody != other.is_bloody) return false; if (is_silenced != other.is_silenced) return false; if (halo != other.halo) return false; - if (is_moldy != other.is_moldy) return false; - if (glowing_mold != other.glowing_mold) return false; if (is_sanctuary != other.is_sanctuary) return false; if (is_liquefied != other.is_liquefied) return false; if (mangrove_water != other.mangrove_water) return false; diff --git a/crawl-ref/source/tilecell.h b/crawl-ref/source/tilecell.h index cca8f2b728c2..4009d15041b7 100644 --- a/crawl-ref/source/tilecell.h +++ b/crawl-ref/source/tilecell.h @@ -30,8 +30,6 @@ struct packed_cell bool is_bloody; bool is_silenced; char halo; - bool is_moldy; - bool glowing_mold; bool is_sanctuary; bool is_liquefied; bool mangrove_water; @@ -51,10 +49,10 @@ struct packed_cell packed_cell() : num_dngn_overlay(0), fg(0), bg(0), cloud(0), is_highlighted_summoner(false), is_bloody(false), - is_silenced(false), halo(HALO_NONE), is_moldy(false), - glowing_mold(false), is_sanctuary(false), is_liquefied(false), - mangrove_water(false), awakened_forest(false), orb_glow(0), - blood_rotation(0), old_blood(false), travel_trail(0), + is_silenced(false), halo(HALO_NONE), is_sanctuary(false), + is_liquefied(false), mangrove_water(false), + awakened_forest(false), orb_glow(0), blood_rotation(0), + old_blood(false), travel_trail(0), quad_glow(false), disjunct(false) #if TAG_MAJOR_VERSION == 34 , heat_aura(false) @@ -69,8 +67,6 @@ struct packed_cell is_bloody(c->is_bloody), is_silenced(c->is_silenced), halo(c->halo), - is_moldy(c->is_moldy), - glowing_mold(c->glowing_mold), is_sanctuary(c->is_sanctuary), is_liquefied(c->is_liquefied), mangrove_water(c->mangrove_water), diff --git a/crawl-ref/source/tiledgnbuf.cc b/crawl-ref/source/tiledgnbuf.cc index d57992373b80..8a3a35a8f019 100644 --- a/crawl-ref/source/tiledgnbuf.cc +++ b/crawl-ref/source/tiledgnbuf.cc @@ -230,16 +230,6 @@ void DungeonCellBuffer::add_blood_overlay(int x, int y, const packed_cell &cell, const int offset = cell.flv.special % tile_dngn_count(basetile); m_buf_feat.add(basetile + offset, x, y); } - else if (cell.is_moldy) - { - int offset = cell.flv.special % tile_dngn_count(TILE_MOLD); - m_buf_feat.add(TILE_MOLD + offset, x, y); - } - else if (cell.glowing_mold) - { - int offset = cell.flv.special % tile_dngn_count(TILE_GLOWING_MOLD); - m_buf_feat.add(TILE_GLOWING_MOLD + offset, x, y); - } } void DungeonCellBuffer::pack_background(int x, int y, const packed_cell &cell) diff --git a/crawl-ref/source/tileview.cc b/crawl-ref/source/tileview.cc index d11d511ebe47..0a3bc5ba65ae 100644 --- a/crawl-ref/source/tileview.cc +++ b/crawl-ref/source/tileview.cc @@ -1431,15 +1431,10 @@ void tile_apply_properties(const coord_def &gc, packed_cell &cell) print_blood = false; } - // Mold has the same restrictions as blood but takes precedence. if (print_blood) { - if (mc.flags & MAP_GLOWING_MOLDY) - cell.glowing_mold = true; - else if (mc.flags & MAP_MOLDY) - cell.is_moldy = true; // Corpses have a blood puddle of their own. - else if (mc.flags & MAP_BLOODY && !_top_item_is_corpse(mc)) + if (mc.flags & MAP_BLOODY && !_top_item_is_corpse(mc)) { cell.is_bloody = true; cell.blood_rotation = blood_rotation(gc); diff --git a/crawl-ref/source/tileweb.cc b/crawl-ref/source/tileweb.cc index 499555cc254d..4fe2dab511c5 100644 --- a/crawl-ref/source/tileweb.cc +++ b/crawl-ref/source/tileweb.cc @@ -1243,12 +1243,10 @@ static bool _needs_flavour(const packed_cell &cell) tileidx_t bg_idx = cell.bg & TILE_FLAG_MASK; if (bg_idx >= TILE_DNGN_FIRST_TRANSPARENT) return true; // Needs flv.floor - if (cell.is_liquefied || cell.is_bloody || - cell.is_moldy || cell.glowing_mold) - { + if (cell.is_liquefied || cell.is_bloody) return true; // Needs flv.special - } return false; + } static inline unsigned _get_brand(int col) @@ -1361,12 +1359,6 @@ void TilesFramework::_send_cell(const coord_def &gc, next_pc.is_highlighted_summoner); } - if (next_pc.is_moldy != current_pc.is_moldy) - json_write_bool("moldy", next_pc.is_moldy); - - if (next_pc.glowing_mold != current_pc.glowing_mold) - json_write_bool("glowing_mold", next_pc.glowing_mold); - if (next_pc.is_sanctuary != current_pc.is_sanctuary) json_write_bool("sanctuary", next_pc.is_sanctuary); diff --git a/crawl-ref/source/timed-effects.cc b/crawl-ref/source/timed-effects.cc index 35d99b222c9e..83ce6975b7b0 100644 --- a/crawl-ref/source/timed-effects.cc +++ b/crawl-ref/source/timed-effects.cc @@ -697,10 +697,6 @@ static void _catchup_monster_moves(monster* mon, int turns) return; } - // Don't shift ballistomycete spores since that would disrupt their trail. - if (mon->type == MONS_BALLISTOMYCETE_SPORE) - return; - // special movement code for ioods if (mons_is_projectile(*mon)) { From 7ac76a7cd56005030e99e6eded4b7f75a6c873b3 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Wed, 11 Sep 2019 04:24:18 -0500 Subject: [PATCH 749/864] Fedhas rework part 7: rework Reproduction This commit replaces Fedhas' Reproduction with Grow Ballistomycete, an ability that creates a summoned ballistomycete at any smite-targeted location within radius 2 at a cost of 5 piety. Ballistomycetes have been simplified in the previous commit and now use their Sporulate ability to create spores that try to reach their target in order to explode. The explosion radius has been reduced to 1, so this combined with more flexibility in positioning will make it easier for players to avoid the explosion. If explosion avoidance ends up still being too big an issue, we could have a Fedhas passively protect players from the explosion to some degree. Ballistomycetes get increased HD and duration with Invocations, gaining 1 HD per level of the skill. The only effect of this HD increase at present is more HP. We probably don't want to increase the usage rate of Sporulat like we do for Oklob Plant's spit acid, since rapidly creating too many spores will create...a lot of explosions. Fedhas wrath places spores around corpses using some of the same functions that were previously used for Reproduction. Hence these have been moved to god-wrath.cc. It would probably be best to simplify this wrath by creating durably summoned ballistomycetes instead, but I'm not doing that for now. --- crawl-ref/source/ability-type.h | 2 +- crawl-ref/source/ability.cc | 36 +- crawl-ref/source/dat/descript/ability.txt | 11 +- crawl-ref/source/god-abil.cc | 390 ------------------ crawl-ref/source/god-abil.h | 15 - crawl-ref/source/god-wrath.cc | 373 ++++++++++++++++- crawl-ref/source/mon-death.cc | 2 +- crawl-ref/source/religion.cc | 2 +- crawl-ref/source/rltiles/dc-invocations.txt | 2 +- ...res.png => fedhas_grow_ballistomycete.png} | Bin crawl-ref/source/spl-summoning.cc | 57 +++ crawl-ref/source/spl-summoning.h | 1 + crawl-ref/source/tilepick.cc | 4 +- 13 files changed, 438 insertions(+), 457 deletions(-) rename crawl-ref/source/rltiles/gui/invocations/{fedhas_spawn_spores.png => fedhas_grow_ballistomycete.png} (100%) diff --git a/crawl-ref/source/ability-type.h b/crawl-ref/source/ability-type.h index e0eb7b7b4ad0..dac478debfff 100644 --- a/crawl-ref/source/ability-type.h +++ b/crawl-ref/source/ability-type.h @@ -175,7 +175,7 @@ enum ability_type // Fedhas ABIL_FEDHAS_WALL_OF_BRIARS = 1140, ABIL_FEDHAS_RAIN, - ABIL_FEDHAS_SPAWN_SPORES, + ABIL_FEDHAS_GROW_BALLISTOMYCETE, // Cheibriados ABIL_CHEIBRIADOS_TIME_STEP = 1151, ABIL_CHEIBRIADOS_TIME_BEND, diff --git a/crawl-ref/source/ability.cc b/crawl-ref/source/ability.cc index 771782ff4851..91914df9f1d3 100644 --- a/crawl-ref/source/ability.cc +++ b/crawl-ref/source/ability.cc @@ -514,12 +514,12 @@ static const ability_def Ability_List[] = 0, 0, 0, 15, {fail_basis::invo}, abflag::none }, // Fedhas - { ABIL_FEDHAS_SPAWN_SPORES, "Reproduction", - 4, 0, 100, 1, {fail_basis::invo, 60, 4, 25}, abflag::none }, { ABIL_FEDHAS_RAIN, "Rain", 4, 0, 150, 4, {fail_basis::invo, 70, 4, 25}, abflag::none }, { ABIL_FEDHAS_WALL_OF_BRIARS, "Wall of Briars", 3, 0, 50, 2, {fail_basis::invo, 30, 6, 20}, abflag::none}, + { ABIL_FEDHAS_GROW_BALLISTOMYCETE, "Grow Ballistomycete", + 4, 0, 100, 4, {fail_basis::invo, 60, 4, 25}, abflag::none }, // Cheibriados { ABIL_CHEIBRIADOS_TIME_BEND, "Bend Time", @@ -1570,23 +1570,6 @@ static bool _check_ability_possible(const ability_def& abil, bool quiet = false) return true; - case ABIL_FEDHAS_SPAWN_SPORES: - { - const int retval = fedhas_check_corpse_spores(quiet); - if (retval <= 0) - { - if (!quiet) - { - if (retval == 0) - mpr("No corpses are in range."); - else - canned_msg(MSG_OK); - } - return false; - } - return true; - } - case ABIL_SPIT_POISON: case ABIL_BREATHE_FIRE: case ABIL_BREATHE_FROST: @@ -2862,6 +2845,13 @@ static spret _do_ability(const ability_def& abil, bool fail) return spret::abort; break; + case ABIL_FEDHAS_GROW_BALLISTOMYCETE: + { + return fedhas_grow_ballistomycete(fail); + + break; + } + case ABIL_FEDHAS_RAIN: fail_check(); if (!fedhas_rain(you.pos())) @@ -2871,14 +2861,6 @@ static spret _do_ability(const ability_def& abil, bool fail) } break; - case ABIL_FEDHAS_SPAWN_SPORES: - { - fail_check(); - const int num = fedhas_corpse_spores(); - ASSERT(num > 0); - break; - } - case ABIL_TRAN_BAT: { if (_player_cancels_vampire_bat_transformation()) diff --git a/crawl-ref/source/dat/descript/ability.txt b/crawl-ref/source/dat/descript/ability.txt index 1b54975d2e90..656a3c66232b 100644 --- a/crawl-ref/source/dat/descript/ability.txt +++ b/crawl-ref/source/dat/descript/ability.txt @@ -486,6 +486,12 @@ Wall of Briars ability Grow short-lived briar patches around you. Monsters attacking these briars will be damaged by sharp thorns. Invocations skill increases the briars' health. %%%% +Grow Ballistomycete ability + +Grow a short-lived Ballistomycete at the location you choose. A Ballistomycete +occasionally release spores that quickly seek out foes and violently explode, +damaging and confusing all living things caught in the blast. +%%%% Rain ability Causes rain to fall around you, turning the dungeon floor into shallow water @@ -493,11 +499,6 @@ and shallow water into deep water. This may also allow plants and mushrooms to grow in areas that are not directly drenched. Invocations skill increases the number of rain-clouds created. %%%% -Reproduction ability - -Creates ballistomycete spores from corpses in your line of sight. The spores will -explode, causing damage to you or your enemies. -%%%% # Cheibriados Bend Time ability diff --git a/crawl-ref/source/god-abil.cc b/crawl-ref/source/god-abil.cc index fa3f0b62dfad..35cbe8d7585b 100644 --- a/crawl-ref/source/god-abil.cc +++ b/crawl-ref/source/god-abil.cc @@ -9,7 +9,6 @@ #include #include -#include #include #include "act-iter.h" @@ -17,7 +16,6 @@ #include "attitude-change.h" #include "bloodspatter.h" #include "branch.h" -#include "butcher.h" #include "chardump.h" #include "cloud.h" #include "colour.h" @@ -2035,282 +2033,6 @@ bool fedhas_passthrough(const monster_info* target) || target->attitude != ATT_HOSTILE); } -// Basically we want to break a circle into n_arcs equal sized arcs and find -// out which arc the input point pos falls on. -static int _arc_decomposition(const coord_def & pos, int n_arcs) -{ - float theta = atan2((float)pos.y, (float)pos.x); - - if (pos.x == 0 && pos.y != 0) - theta = pos.y > 0 ? PI / 2 : -PI / 2; - - if (theta < 0) - theta += 2 * PI; - - float arc_angle = 2 * PI / n_arcs; - - theta += arc_angle / 2.0f; - - if (theta >= 2 * PI) - theta -= 2 * PI; - - return static_cast (theta / arc_angle); -} - -int place_ring(vector &ring_points, - const coord_def &origin, - mgen_data prototype, - int n_arcs, - int arc_occupancy, - int &seen_count) -{ - shuffle_array(ring_points); - - int target_amount = ring_points.size(); - int spawned_count = 0; - seen_count = 0; - - vector arc_counts(n_arcs, arc_occupancy); - - for (unsigned i = 0; - spawned_count < target_amount && i < ring_points.size(); - i++) - { - int direction = _arc_decomposition(ring_points.at(i) - - origin, n_arcs); - - if (arc_counts[direction]-- <= 0) - continue; - - prototype.pos = ring_points.at(i); - - if (create_monster(prototype, false)) - { - spawned_count++; - if (you.see_cell(ring_points.at(i))) - seen_count++; - } - } - - return spawned_count; -} - -// Collect lists of points that are within LOS (under the given env map), -// unoccupied, and not solid (walls/statues). -void collect_radius_points(vector > &radius_points, - const coord_def &origin, los_type los) -{ - radius_points.clear(); - radius_points.resize(LOS_RADIUS); - - // Just want to associate a point with a distance here for convenience. - typedef pair coord_dist; - - // Using a priority queue because squares don't make very good circles at - // larger radii. We will visit points in order of increasing euclidean - // distance from the origin (not path distance). We want a min queue - // based on the distance, so we use greater_second as the comparator. - priority_queue, - greater_second > fringe; - - fringe.push(coord_dist(origin, 0)); - - set visited_indices; - - int current_r = 1; - int current_thresh = current_r * (current_r + 1); - - int max_distance = LOS_RADIUS * LOS_RADIUS + 1; - - while (!fringe.empty()) - { - coord_dist current = fringe.top(); - // We're done here once we hit a point that is farther away from the - // origin than our maximum permissible radius. - if (current.second > max_distance) - break; - - fringe.pop(); - - int idx = current.first.x + current.first.y * X_WIDTH; - if (!visited_indices.insert(idx).second) - continue; - - while (current.second > current_thresh) - { - current_r++; - current_thresh = current_r * (current_r + 1); - } - - // We don't include radius 0. This is also a good place to check if - // the squares are already occupied since we want to search past - // occupied squares but don't want to consider them valid targets. - if (current.second && !actor_at(current.first)) - radius_points[current_r - 1].push_back(current.first); - - for (adjacent_iterator i(current.first); i; ++i) - { - coord_dist temp(*i, current.second); - - // If the grid is out of LOS, skip it. - if (!cell_see_cell(origin, temp.first, los)) - continue; - - coord_def local = temp.first - origin; - - temp.second = local.abs(); - - idx = temp.first.x + temp.first.y * X_WIDTH; - - if (!visited_indices.count(idx) - && in_bounds(temp.first) - && !cell_is_solid(temp.first)) - { - fringe.push(temp); - } - } - - } -} - -template -static bool less_second(const T & left, const T & right) -{ - return left.second < right.second; -} - -typedef pair point_distance; - -// Find the distance from origin to each of the targets, those results -// are stored in distances (which is the same size as targets). Exclusion -// is a set of points which are considered disconnected for the search. -static void _path_distance(const coord_def& origin, - const vector& targets, - set exclusion, - vector& distances) -{ - queue fringe; - fringe.push(point_distance(origin,0)); - distances.clear(); - distances.resize(targets.size(), INT_MAX); - - while (!fringe.empty()) - { - point_distance current = fringe.front(); - fringe.pop(); - - // did we hit a target? - for (unsigned i = 0; i < targets.size(); ++i) - { - if (current.first == targets[i]) - { - distances[i] = current.second; - break; - } - } - - for (adjacent_iterator adj_it(current.first); adj_it; ++adj_it) - { - int idx = adj_it->x + adj_it->y * X_WIDTH; - if (you.see_cell(*adj_it) - && !feat_is_solid(env.grid(*adj_it)) - && *adj_it != you.pos() - && exclusion.insert(idx).second) - { - monster* temp = monster_at(*adj_it); - if (!temp || (temp->attitude == ATT_HOSTILE - && !temp->is_stationary())) - { - fringe.push(point_distance(*adj_it, current.second+1)); - } - } - } - } -} - -// Find the minimum distance from each point of origin to one of the targets -// The distance is stored in 'distances', which is the same size as origins. -static void _point_point_distance(const vector& origins, - const vector& targets, - vector& distances) -{ - distances.clear(); - distances.resize(origins.size(), INT_MAX); - - // Consider all points of origin as blocked (you can search outward - // from one, but you can't form a path across a different one). - set base_exclusions; - for (coord_def c : origins) - { - int idx = c.x + c.y * X_WIDTH; - base_exclusions.insert(idx); - } - - vector current_distances; - for (unsigned i = 0; i < origins.size(); ++i) - { - // Find the distance from the point of origin to each of the targets. - _path_distance(origins[i], targets, base_exclusions, - current_distances); - - // Find the smallest of those distances - int min_dist = current_distances[0]; - for (unsigned j = 1; j < current_distances.size(); ++j) - if (current_distances[j] < min_dist) - min_dist = current_distances[j]; - - distances[i] = min_dist; - } -} - -// So the idea is we want to decide which adjacent tiles are in the most 'danger' -// We claim danger is proportional to the minimum distances from the point to a -// (hostile) monster. This function carries out at most 7 searches to calculate -// the distances in question. -bool prioritise_adjacent(const coord_def &target, vector& candidates) -{ - radius_iterator los_it(target, LOS_NO_TRANS, true); - - vector mons_positions; - // collect hostile monster positions in LOS - for (; los_it; ++los_it) - { - monster* hostile = monster_at(*los_it); - - if (hostile && hostile->attitude == ATT_HOSTILE - && you.can_see(*hostile)) - { - mons_positions.push_back(hostile->pos()); - } - } - - if (mons_positions.empty()) - { - shuffle_array(candidates); - return true; - } - - vector distances; - - _point_point_distance(candidates, mons_positions, distances); - - vector possible_moves(candidates.size()); - - for (unsigned i = 0; i < possible_moves.size(); ++i) - { - possible_moves[i].first = candidates[i]; - possible_moves[i].second = distances[i]; - } - - sort(possible_moves.begin(), possible_moves.end(), - less_second); - - for (unsigned i = 0; i < candidates.size(); ++i) - candidates[i] = possible_moves[i].first; - - return true; -} - // Create a circle of water around the target, with a radius of // approximately 2. This turns normal floor tiles into shallow water // and turns (unoccupied) shallow water into deep water. There is a @@ -2408,118 +2130,6 @@ int fedhas_rain(const coord_def &target) return processed_count; } - -int count_corpses_in_los(vector *positions) -{ - int count = 0; - - for (radius_iterator rad(you.pos(), LOS_NO_TRANS, true); rad; - ++rad) - { - if (actor_at(*rad)) - continue; - - for (stack_iterator stack_it(*rad); stack_it; ++stack_it) - { - if (stack_it->is_type(OBJ_CORPSES, CORPSE_BODY)) - { - if (positions) - positions->push_back(stack_it); - count++; - break; - } - } - } - - return count; -} - -int fedhas_check_corpse_spores(bool quiet) -{ - vector positions; - int count = count_corpses_in_los(&positions); - - if (quiet || count == 0) - return count; - - viewwindow(false); - for (const stack_iterator &si : positions) - { -#ifndef USE_TILE_LOCAL - coord_def temp = grid2view(si->pos); - cgotoxy(temp.x, temp.y, GOTO_DNGN); - - unsigned colour = GREEN | COLFLAG_FRIENDLY_MONSTER; - colour = real_colour(colour); - - unsigned character = mons_char(MONS_BALLISTOMYCETE_SPORE); - put_colour_ch(colour, character); -#endif -#ifdef USE_TILE - tiles.add_overlay(si->pos, TILE_SPORE_OVERLAY); -#endif - } - - if (yesnoquit("Will you create these spores?", true, 'y') <= 0) - { - viewwindow(false); - return -1; - } - - return count; -} - -// Destroy corpses in the player's LOS (first corpse on a stack only) -// and make 1 ballistomycete spore per corpse. Spores are given the input as -// their starting behavior; the function returns the number of corpses -// processed. -int fedhas_corpse_spores(beh_type attitude) -{ - vector positions; - int count = count_corpses_in_los(&positions); - ASSERT(attitude != BEH_FRIENDLY || count > 0); - - if (count == 0) - return count; - - for (const stack_iterator &si : positions) - { - count++; - - if (monster *plant = create_monster(mgen_data(MONS_BALLISTOMYCETE_SPORE, - attitude, - si->pos, - MHITNOT, - MG_FORCE_PLACE, - GOD_FEDHAS) - .set_summoned(&you, 0, 0))) - { - plant->flags |= MF_NO_REWARD; - - if (attitude == BEH_FRIENDLY) - { - plant->flags |= MF_ATT_CHANGE_ATTEMPT; - - mons_make_god_gift(*plant, GOD_FEDHAS); - - plant->behaviour = BEH_WANDER; - plant->foe = MHITNOT; - } - } - - if (mons_skeleton(si->mon_type)) - turn_corpse_into_skeleton(*si); - else - { - item_was_destroyed(*si); - destroy_item(si->index()); - } - } - - viewwindow(false); - - return count; -} static bool _lugonu_warp_monster(monster& mon, int pow) { if (coinflip()) diff --git a/crawl-ref/source/god-abil.h b/crawl-ref/source/god-abil.h index 0634e265db9e..6a0e9e81bcfa 100644 --- a/crawl-ref/source/god-abil.h +++ b/crawl-ref/source/god-abil.h @@ -106,22 +106,7 @@ bool kiku_gift_necronomicon(); bool fedhas_passthrough_class(const monster_type mc); bool fedhas_passthrough(const monster* target); bool fedhas_passthrough(const monster_info* target); -struct mgen_data; -int place_ring(vector& ring_points, - const coord_def& origin, - mgen_data prototype, - int n_arcs, - int arc_occupancy, - int& seen_count); -// Collect lists of points that are within LOS, unoccupied, and not solid -// (walls/statues). -void collect_radius_points(vector > &radius_points, - const coord_def &origin, los_type los); -bool prioritise_adjacent(const coord_def& target, vector& candidates); int fedhas_rain(const coord_def &target); -int count_corpses_in_los(vector *positions); -int fedhas_check_corpse_spores(bool quiet = false); -int fedhas_corpse_spores(beh_type attitude = BEH_FRIENDLY); void lugonu_bend_space(); diff --git a/crawl-ref/source/god-wrath.cc b/crawl-ref/source/god-wrath.cc index c8906b642d0e..4ab2fb812f0a 100644 --- a/crawl-ref/source/god-wrath.cc +++ b/crawl-ref/source/god-wrath.cc @@ -7,11 +7,14 @@ #include "god-wrath.h" +#include +#include #include #include "areas.h" #include "artefact.h" #include "attitude-change.h" +#include "butcher.h" #include "cleansing-flame-source-type.h" #include "coordit.h" #include "database.h" @@ -26,6 +29,7 @@ #include "item-prop.h" #include "item-status-flag-type.h" #include "items.h" +#include "losglobal.h" #include "makeitem.h" #include "message.h" #include "misc.h" @@ -611,6 +615,31 @@ static bool _makhleb_retribution() return _makhleb_summon_servants(); } +static int _count_corpses_in_los(vector *positions) +{ + int count = 0; + + for (radius_iterator rad(you.pos(), LOS_NO_TRANS, true); rad; + ++rad) + { + if (actor_at(*rad)) + continue; + + for (stack_iterator stack_it(*rad); stack_it; ++stack_it) + { + if (stack_it->is_type(OBJ_CORPSES, CORPSE_BODY)) + { + if (positions) + positions->push_back(stack_it); + count++; + break; + } + } + } + + return count; +} + static bool _kikubaaqudgha_retribution() { // death/necromancy theme @@ -619,7 +648,7 @@ static bool _kikubaaqudgha_retribution() god_speaks(god, coinflip() ? "You hear Kikubaaqudgha cackling." : "Kikubaaqudgha's malice focuses upon you."); - if (!count_corpses_in_los(nullptr) || random2(you.experience_level) > 4) + if (!_count_corpses_in_los(nullptr) || random2(you.experience_level) > 4) { // Either zombies, or corpse rot + skeletons. kiku_receive_corpses(you.experience_level * 4); @@ -1303,6 +1332,280 @@ static void _fedhas_elemental_miscast() _god_wrath_name(god)); } +// Collect lists of points that are within LOS (under the given env map), +// unoccupied, and not solid (walls/statues). +static void _collect_radius_points(vector > &radius_points, + const coord_def &origin, los_type los) +{ + radius_points.clear(); + radius_points.resize(LOS_RADIUS); + + // Just want to associate a point with a distance here for convenience. + typedef pair coord_dist; + + // Using a priority queue because squares don't make very good circles at + // larger radii. We will visit points in order of increasing euclidean + // distance from the origin (not path distance). We want a min queue + // based on the distance, so we use greater_second as the comparator. + priority_queue, + greater_second > fringe; + + fringe.push(coord_dist(origin, 0)); + + set visited_indices; + + int current_r = 1; + int current_thresh = current_r * (current_r + 1); + + int max_distance = LOS_RADIUS * LOS_RADIUS + 1; + + while (!fringe.empty()) + { + coord_dist current = fringe.top(); + // We're done here once we hit a point that is farther away from the + // origin than our maximum permissible radius. + if (current.second > max_distance) + break; + + fringe.pop(); + + int idx = current.first.x + current.first.y * X_WIDTH; + if (!visited_indices.insert(idx).second) + continue; + + while (current.second > current_thresh) + { + current_r++; + current_thresh = current_r * (current_r + 1); + } + + // We don't include radius 0. This is also a good place to check if + // the squares are already occupied since we want to search past + // occupied squares but don't want to consider them valid targets. + if (current.second && !actor_at(current.first)) + radius_points[current_r - 1].push_back(current.first); + + for (adjacent_iterator i(current.first); i; ++i) + { + coord_dist temp(*i, current.second); + + // If the grid is out of LOS, skip it. + if (!cell_see_cell(origin, temp.first, los)) + continue; + + coord_def local = temp.first - origin; + + temp.second = local.abs(); + + idx = temp.first.x + temp.first.y * X_WIDTH; + + if (!visited_indices.count(idx) + && in_bounds(temp.first) + && !cell_is_solid(temp.first)) + { + fringe.push(temp); + } + } + + } +} + +// Basically we want to break a circle into n_arcs equal sized arcs and find +// out which arc the input point pos falls on. +static int _arc_decomposition(const coord_def & pos, int n_arcs) +{ + float theta = atan2((float)pos.y, (float)pos.x); + + if (pos.x == 0 && pos.y != 0) + theta = pos.y > 0 ? PI / 2 : -PI / 2; + + if (theta < 0) + theta += 2 * PI; + + float arc_angle = 2 * PI / n_arcs; + + theta += arc_angle / 2.0f; + + if (theta >= 2 * PI) + theta -= 2 * PI; + + return static_cast (theta / arc_angle); +} + +static int _place_ring(vector &ring_points, + const coord_def &origin, mgen_data prototype, + int n_arcs, int arc_occupancy, int &seen_count) +{ + shuffle_array(ring_points); + + int target_amount = ring_points.size(); + int spawned_count = 0; + seen_count = 0; + + vector arc_counts(n_arcs, arc_occupancy); + + for (unsigned i = 0; + spawned_count < target_amount && i < ring_points.size(); + i++) + { + int direction = _arc_decomposition(ring_points.at(i) + - origin, n_arcs); + + if (arc_counts[direction]-- <= 0) + continue; + + prototype.pos = ring_points.at(i); + + if (create_monster(prototype, false)) + { + spawned_count++; + if (you.see_cell(ring_points.at(i))) + seen_count++; + } + } + + return spawned_count; +} + +template +static bool less_second(const T & left, const T & right) +{ + return left.second < right.second; +} + +typedef pair point_distance; + +// Find the distance from origin to each of the targets, those results +// are stored in distances (which is the same size as targets). Exclusion +// is a set of points which are considered disconnected for the search. +static void _path_distance(const coord_def& origin, + const vector& targets, + set exclusion, + vector& distances) +{ + queue fringe; + fringe.push(point_distance(origin,0)); + distances.clear(); + distances.resize(targets.size(), INT_MAX); + + while (!fringe.empty()) + { + point_distance current = fringe.front(); + fringe.pop(); + + // did we hit a target? + for (unsigned i = 0; i < targets.size(); ++i) + { + if (current.first == targets[i]) + { + distances[i] = current.second; + break; + } + } + + for (adjacent_iterator adj_it(current.first); adj_it; ++adj_it) + { + int idx = adj_it->x + adj_it->y * X_WIDTH; + if (you.see_cell(*adj_it) + && !feat_is_solid(env.grid(*adj_it)) + && *adj_it != you.pos() + && exclusion.insert(idx).second) + { + monster* temp = monster_at(*adj_it); + if (!temp || (temp->attitude == ATT_HOSTILE + && !temp->is_stationary())) + { + fringe.push(point_distance(*adj_it, current.second+1)); + } + } + } + } +} + +// Find the minimum distance from each point of origin to one of the targets +// The distance is stored in 'distances', which is the same size as origins. +static void _point_point_distance(const vector& origins, + const vector& targets, + vector& distances) +{ + distances.clear(); + distances.resize(origins.size(), INT_MAX); + + // Consider all points of origin as blocked (you can search outward + // from one, but you can't form a path across a different one). + set base_exclusions; + for (coord_def c : origins) + { + int idx = c.x + c.y * X_WIDTH; + base_exclusions.insert(idx); + } + + vector current_distances; + for (unsigned i = 0; i < origins.size(); ++i) + { + // Find the distance from the point of origin to each of the targets. + _path_distance(origins[i], targets, base_exclusions, + current_distances); + + // Find the smallest of those distances + int min_dist = current_distances[0]; + for (unsigned j = 1; j < current_distances.size(); ++j) + if (current_distances[j] < min_dist) + min_dist = current_distances[j]; + + distances[i] = min_dist; + } +} + +// So the idea is we want to decide which adjacent tiles are in the most +// 'danger' We claim danger is proportional to the minimum distances from the +// point to a (hostile) monster. This function carries out at most 7 searches +// to calculate the distances in question. +static bool _prioritise_adjacent(const coord_def &target, + vector& candidates) +{ + radius_iterator los_it(target, LOS_NO_TRANS, true); + + vector mons_positions; + // collect hostile monster positions in LOS + for (; los_it; ++los_it) + { + monster* hostile = monster_at(*los_it); + + if (hostile && hostile->attitude == ATT_HOSTILE + && you.can_see(*hostile)) + { + mons_positions.push_back(hostile->pos()); + } + } + + if (mons_positions.empty()) + { + shuffle_array(candidates); + return true; + } + + vector distances; + + _point_point_distance(candidates, mons_positions, distances); + + vector possible_moves(candidates.size()); + + for (unsigned i = 0; i < possible_moves.size(); ++i) + { + possible_moves[i].first = candidates[i]; + possible_moves[i].second = distances[i]; + } + + sort(possible_moves.begin(), possible_moves.end(), + less_second); + + for (unsigned i = 0; i < candidates.size(); ++i) + candidates[i] = possible_moves[i].first; + + return true; +} + /** * Summon Fedhas's oklobs & mushrooms around the player. * @@ -1316,7 +1619,7 @@ static bool _fedhas_summon_plants() // We are going to spawn some oklobs but first we need to find // out a little about the situation. vector > radius_points; - collect_radius_points(radius_points, you.pos(), LOS_NO_TRANS); + _collect_radius_points(radius_points, you.pos(), LOS_NO_TRANS); int max_idx = 3; unsigned max_points = radius_points[max_idx].size(); @@ -1340,22 +1643,16 @@ static bool _fedhas_summon_plants() temp.cls = MONS_PLANT; - place_ring(radius_points[0], - you.pos(), - temp, - 1, radius_points[0].size(), - seen_count); + _place_ring(radius_points[0], you.pos(), temp, 1, + radius_points[0].size(), seen_count); if (seen_count > 0) success = true; temp.cls = MONS_OKLOB_PLANT; - place_ring(radius_points[max_idx], - you.pos(), - temp, - random_range(3, 8), 1, - seen_count); + _place_ring(radius_points[max_idx], you.pos(), temp, + random_range(3, 8), 1, seen_count); if (seen_count > 0) success = true; @@ -1366,7 +1663,7 @@ static bool _fedhas_summon_plants() { unsigned target_count = random_range(2, 8); if (target_count < radius_points[0].size()) - prioritise_adjacent(you.pos(), radius_points[0]); + _prioritise_adjacent(you.pos(), radius_points[0]); else target_count = radius_points[0].size(); @@ -1391,6 +1688,54 @@ static bool _fedhas_summon_plants() return true; } +static int _fedhas_corpse_spores(beh_type attitude) +{ + vector positions; + int count = _count_corpses_in_los(&positions); + ASSERT(attitude != BEH_FRIENDLY || count > 0); + + if (count == 0) + return count; + + for (const stack_iterator &si : positions) + { + count++; + + if (monster *plant = create_monster(mgen_data(MONS_BALLISTOMYCETE_SPORE, + attitude, + si->pos, + MHITNOT, + MG_FORCE_PLACE, + GOD_FEDHAS) + .set_summoned(&you, 0, 0))) + { + plant->flags |= MF_NO_REWARD; + + if (attitude == BEH_FRIENDLY) + { + plant->flags |= MF_ATT_CHANGE_ATTEMPT; + + mons_make_god_gift(*plant, GOD_FEDHAS); + + plant->behaviour = BEH_WANDER; + plant->foe = MHITNOT; + } + } + + if (mons_skeleton(si->mon_type)) + turn_corpse_into_skeleton(*si); + else + { + item_was_destroyed(*si); + destroy_item(si->index()); + } + } + + viewwindow(false); + + return count; +} + /** * Call down the wrath of Fedhas upon the player! * @@ -1411,7 +1756,7 @@ static bool _fedhas_retribution() case 0: // Try and spawn some hostile ballistomycete spores, if none are created // fall through to the elemental miscast effects. - if (fedhas_corpse_spores(BEH_HOSTILE)) + if (_fedhas_corpse_spores(BEH_HOSTILE)) { simple_god_message(" produces spores.", god); return true; diff --git a/crawl-ref/source/mon-death.cc b/crawl-ref/source/mon-death.cc index 300d59e21c94..3b8dbfb7fb5b 100644 --- a/crawl-ref/source/mon-death.cc +++ b/crawl-ref/source/mon-death.cc @@ -1087,7 +1087,7 @@ void setup_spore_explosion(bolt & beam, const monster& origin) beam.damage = dice_def(3, 15); beam.name = "explosion of spores"; beam.colour = LIGHTGREY; - beam.ex_size = 2; + beam.ex_size = 1; } static void _setup_lightning_explosion(bolt & beam, const monster& origin) diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index 6a927ffdfdff..553ed5e152f1 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -264,7 +264,7 @@ const vector god_powers[NUM_GODS] = // Fedhas { { 2, ABIL_FEDHAS_WALL_OF_BRIARS, "encircle yourself with summoned briar patches"}, - { 4, ABIL_FEDHAS_SPAWN_SPORES, "spawn explosive spores" }, + { 3, ABIL_FEDHAS_GROW_BALLISTOMYCETE, "grow a ballistomycete" }, { 5, ABIL_FEDHAS_RAIN, "control the weather" }, }, diff --git a/crawl-ref/source/rltiles/dc-invocations.txt b/crawl-ref/source/rltiles/dc-invocations.txt index bbd610412557..879b3a79ba03 100644 --- a/crawl-ref/source/rltiles/dc-invocations.txt +++ b/crawl-ref/source/rltiles/dc-invocations.txt @@ -21,8 +21,8 @@ elyvilon_lesser_healing ABILITY_ELYVILON_LESSER_HEALING elyvilon_purification ABILITY_ELYVILON_PURIFICATION elyvilon_heal_other ABILITY_ELYVILON_HEAL_OTHER fedhas_rain ABILITY_FEDHAS_RAIN -fedhas_spawn_spores ABILITY_FEDHAS_SPAWN_SPORES fedhas_wall_of_briars ABILITY_FEDHAS_WALL_OF_BRIARS +fedhas_grow_ballistomycete ABILITY_FEDHAS_GROW_BALLISTOMYCETE gozag_potion_petition ABILITY_GOZAG_POTION_PETITION gozag_call_merchant ABILITY_GOZAG_CALL_MERCHANT gozag_bribe_branch ABILITY_GOZAG_BRIBE_BRANCH diff --git a/crawl-ref/source/rltiles/gui/invocations/fedhas_spawn_spores.png b/crawl-ref/source/rltiles/gui/invocations/fedhas_grow_ballistomycete.png similarity index 100% rename from crawl-ref/source/rltiles/gui/invocations/fedhas_spawn_spores.png rename to crawl-ref/source/rltiles/gui/invocations/fedhas_grow_ballistomycete.png diff --git a/crawl-ref/source/spl-summoning.cc b/crawl-ref/source/spl-summoning.cc index cbc347eff988..39fb2797f1ed 100644 --- a/crawl-ref/source/spl-summoning.cc +++ b/crawl-ref/source/spl-summoning.cc @@ -3524,3 +3524,60 @@ bool fedhas_wall_of_briars() return created_count; } + +spret fedhas_grow_ballistomycete(bool fail) +{ + dist spd; + bolt beam; + beam.range = 2; + direction_chooser_args args; + args.restricts = DIR_TARGET; + args.mode = TARG_HOSTILE; + args.needs_path = false; + if (!spell_direction(spd, beam, &args)) + return spret::abort; + + if (grid_distance(beam.target, you.pos()) > 2 || !in_bounds(beam.target)) + { + mpr("That's too far away."); + return spret::abort; + } + + if (!monster_habitable_grid(MONS_BALLISTOMYCETE, grd(beam.target))) + { + mpr("You can't grow a ballistomycete there."); + return spret::abort; + } + + monster* mons = monster_at(beam.target); + if (mons) + { + if (you.can_see(*mons)) + { + mpr("That space is already occupied."); + return spret::abort; + } + + fail_check(); + + // invisible monster + mpr("Something you can't see occupies that space!"); + return spret::success; + } + + fail_check(); + + mgen_data mgen(MONS_BALLISTOMYCETE, BEH_FRIENDLY, beam.target, MHITYOU, + MG_FORCE_BEH | MG_FORCE_PLACE | MG_AUTOFOE); + mgen.hd = mons_class_hit_dice(MONS_BALLISTOMYCETE) + + you.skill_rdiv(SK_INVOCATIONS); + mgen.set_summoned(&you, 3 + you.skill_rdiv(SK_INVOCATIONS, 1, 5), + SPELL_NO_SPELL); + + if (create_monster(mgen)) + mpr("A ballistomycete grows from the ground."); + else + canned_msg(MSG_NOTHING_HAPPENS); + + return spret::success; +} diff --git a/crawl-ref/source/spl-summoning.h b/crawl-ref/source/spl-summoning.h index f9d0c9b8c066..9c2c6dc56f14 100644 --- a/crawl-ref/source/spl-summoning.h +++ b/crawl-ref/source/spl-summoning.h @@ -127,3 +127,4 @@ int summons_limit(spell_type spell); int count_summons(const actor *summoner, spell_type spell); bool fedhas_wall_of_briars(); +spret fedhas_grow_ballistomycete(bool fail); diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc index cf711c638ac2..88b5e553f308 100644 --- a/crawl-ref/source/tilepick.cc +++ b/crawl-ref/source/tilepick.cc @@ -3533,8 +3533,8 @@ tileidx_t tileidx_ability(const ability_type ability) return TILEG_ABILITY_FEDHAS_WALL_OF_BRIARS; case ABIL_FEDHAS_RAIN: return TILEG_ABILITY_FEDHAS_RAIN; - case ABIL_FEDHAS_SPAWN_SPORES: - return TILEG_ABILITY_FEDHAS_SPAWN_SPORES; + case ABIL_FEDHAS_GROW_BALLISTOMYCETE: + return TILEG_ABILITY_FEDHAS_GROW_BALLISTOMYCETE; // Cheibriados case ABIL_CHEIBRIADOS_TIME_STEP: return TILEG_ABILITY_CHEIBRIADOS_TIME_STEP; From 8f1ea3d74cbb67684927e027e7158e1a9c5cfdd6 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Wed, 11 Sep 2019 05:25:11 -0500 Subject: [PATCH 750/864] Fedhas rework part 8: remove Rain Part of what Rain does is allow creation of plants, but this is no longer relevant, since the other Fedhas ally creation abilities don't need plant intermediaries. The other prominent aspect of Rain is permanent creation of deep water, but this leads to a lot of luring. The new Wall of Briars ability provides some instantaneous limitation of monster movement, but in a way that doesn't make permanent terrain changes and hence less encourages luring. --- crawl-ref/source/ability-type.h | 1 - crawl-ref/source/ability.cc | 12 --- crawl-ref/source/dat/descript/ability.txt | 7 -- crawl-ref/source/god-abil.cc | 97 ------------------ crawl-ref/source/religion.cc | 1 - crawl-ref/source/rltiles/dc-invocations.txt | 1 - .../rltiles/gui/invocations/fedhas_rain.png | Bin 390 -> 0 bytes crawl-ref/source/tilepick.cc | 2 - 8 files changed, 121 deletions(-) delete mode 100644 crawl-ref/source/rltiles/gui/invocations/fedhas_rain.png diff --git a/crawl-ref/source/ability-type.h b/crawl-ref/source/ability-type.h index dac478debfff..d3c5e73a1253 100644 --- a/crawl-ref/source/ability-type.h +++ b/crawl-ref/source/ability-type.h @@ -174,7 +174,6 @@ enum ability_type ABIL_JIYVA_CURE_BAD_MUTATION, // Fedhas ABIL_FEDHAS_WALL_OF_BRIARS = 1140, - ABIL_FEDHAS_RAIN, ABIL_FEDHAS_GROW_BALLISTOMYCETE, // Cheibriados ABIL_CHEIBRIADOS_TIME_STEP = 1151, diff --git a/crawl-ref/source/ability.cc b/crawl-ref/source/ability.cc index 91914df9f1d3..f5d766c6a7a6 100644 --- a/crawl-ref/source/ability.cc +++ b/crawl-ref/source/ability.cc @@ -514,8 +514,6 @@ static const ability_def Ability_List[] = 0, 0, 0, 15, {fail_basis::invo}, abflag::none }, // Fedhas - { ABIL_FEDHAS_RAIN, "Rain", - 4, 0, 150, 4, {fail_basis::invo, 70, 4, 25}, abflag::none }, { ABIL_FEDHAS_WALL_OF_BRIARS, "Wall of Briars", 3, 0, 50, 2, {fail_basis::invo, 30, 6, 20}, abflag::none}, { ABIL_FEDHAS_GROW_BALLISTOMYCETE, "Grow Ballistomycete", @@ -1569,7 +1567,6 @@ static bool _check_ability_possible(const ability_def& abil, bool quiet = false) } return true; - case ABIL_SPIT_POISON: case ABIL_BREATHE_FIRE: case ABIL_BREATHE_FROST: @@ -2852,15 +2849,6 @@ static spret _do_ability(const ability_def& abil, bool fail) break; } - case ABIL_FEDHAS_RAIN: - fail_check(); - if (!fedhas_rain(you.pos())) - { - canned_msg(MSG_NOTHING_HAPPENS); - return spret::abort; - } - break; - case ABIL_TRAN_BAT: { if (_player_cancels_vampire_bat_transformation()) diff --git a/crawl-ref/source/dat/descript/ability.txt b/crawl-ref/source/dat/descript/ability.txt index 656a3c66232b..2d028bb91d39 100644 --- a/crawl-ref/source/dat/descript/ability.txt +++ b/crawl-ref/source/dat/descript/ability.txt @@ -492,13 +492,6 @@ Grow a short-lived Ballistomycete at the location you choose. A Ballistomycete occasionally release spores that quickly seek out foes and violently explode, damaging and confusing all living things caught in the blast. %%%% -Rain ability - -Causes rain to fall around you, turning the dungeon floor into shallow water -and shallow water into deep water. This may also allow plants and mushrooms to -grow in areas that are not directly drenched. Invocations skill increases the -number of rain-clouds created. -%%%% # Cheibriados Bend Time ability diff --git a/crawl-ref/source/god-abil.cc b/crawl-ref/source/god-abil.cc index 35cbe8d7585b..514d007087e2 100644 --- a/crawl-ref/source/god-abil.cc +++ b/crawl-ref/source/god-abil.cc @@ -2033,103 +2033,6 @@ bool fedhas_passthrough(const monster_info* target) || target->attitude != ATT_HOSTILE); } -// Create a circle of water around the target, with a radius of -// approximately 2. This turns normal floor tiles into shallow water -// and turns (unoccupied) shallow water into deep water. There is a -// chance of spawning plants or fungus on unoccupied dry floor tiles -// outside of the rainfall area. Return the number of plants/fungi -// created. -int fedhas_rain(const coord_def &target) -{ - int spawned_count = 0; - int processed_count = 0; - - for (radius_iterator rad(target, LOS_NO_TRANS, true); rad; ++rad) - { - int rain_thresh = 2; - coord_def local = *rad - target; - - dungeon_feature_type ftype = grd(*rad); - - if (local.rdist() > rain_thresh) - { - // Maybe spawn a plant on (dry, open) squares that are in - // LOS but outside the rainfall area. In open space, there - // are 225 squares in LOS, and we are going to drop water on - // 25 of those, so if we want x plants to spawn on - // average in open space, the trial probability should be - // x/200. - if (x_chance_in_y(5, 200) - && !actor_at(*rad) - && ftype == DNGN_FLOOR) - { - if (create_monster(mgen_data( - random_choose(MONS_PLANT, MONS_FUNGUS), - BEH_GOOD_NEUTRAL, - *rad, - MHITNOT, - MG_FORCE_PLACE, - GOD_FEDHAS) - .set_summoned(&you, 0, 0))) - { - spawned_count++; - } - - processed_count++; - } - - continue; - } - - // Turn regular floor squares only into shallow water. - if (ftype == DNGN_FLOOR) - { - dungeon_terrain_changed(*rad, DNGN_SHALLOW_WATER); - - processed_count++; - } - // We can also turn shallow water into deep water, but we're - // just going to skip cases where there is something on the - // shallow water. Destroying items will probably be annoying, - // and insta-killing monsters is clearly out of the question. - else if (!actor_at(*rad) - && igrd(*rad) == NON_ITEM - && ftype == DNGN_SHALLOW_WATER) - { - dungeon_terrain_changed(*rad, DNGN_DEEP_WATER); - - processed_count++; - } - - if (!feat_is_solid(ftype)) - { - // Maybe place a raincloud. - // - // The rainfall area is 24 (5*5 - 1 (center)); - // the expected number of clouds generated by a fixed chance - // per tile is 24 * p = expected. Say an Invocations skill - // of 27 gives expected 6 clouds. - int max_expected = 6; - int expected = you.skill_rdiv(SK_INVOCATIONS, max_expected, 27); - - if (x_chance_in_y(expected, 24)) - { - place_cloud(CLOUD_RAIN, *rad, 10, &you); - - processed_count++; - } - } - } - - if (spawned_count > 0) - { - mprf("%s grow%s in the rain.", - (spawned_count > 1 ? "Some plants" : "A plant"), - (spawned_count > 1 ? "" : "s")); - } - - return processed_count; -} static bool _lugonu_warp_monster(monster& mon, int pow) { if (coinflip()) diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index 553ed5e152f1..03df3b0346ed 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -265,7 +265,6 @@ const vector god_powers[NUM_GODS] = { { 2, ABIL_FEDHAS_WALL_OF_BRIARS, "encircle yourself with summoned briar patches"}, { 3, ABIL_FEDHAS_GROW_BALLISTOMYCETE, "grow a ballistomycete" }, - { 5, ABIL_FEDHAS_RAIN, "control the weather" }, }, // Cheibriados diff --git a/crawl-ref/source/rltiles/dc-invocations.txt b/crawl-ref/source/rltiles/dc-invocations.txt index 879b3a79ba03..b6764dbec3d8 100644 --- a/crawl-ref/source/rltiles/dc-invocations.txt +++ b/crawl-ref/source/rltiles/dc-invocations.txt @@ -20,7 +20,6 @@ elyvilon_greater_healing ABILITY_ELYVILON_GREATER_HEALING elyvilon_lesser_healing ABILITY_ELYVILON_LESSER_HEALING elyvilon_purification ABILITY_ELYVILON_PURIFICATION elyvilon_heal_other ABILITY_ELYVILON_HEAL_OTHER -fedhas_rain ABILITY_FEDHAS_RAIN fedhas_wall_of_briars ABILITY_FEDHAS_WALL_OF_BRIARS fedhas_grow_ballistomycete ABILITY_FEDHAS_GROW_BALLISTOMYCETE gozag_potion_petition ABILITY_GOZAG_POTION_PETITION diff --git a/crawl-ref/source/rltiles/gui/invocations/fedhas_rain.png b/crawl-ref/source/rltiles/gui/invocations/fedhas_rain.png deleted file mode 100644 index 83c0a45eba3b5bbaa5ae813d670d0a56763e36b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 390 zcmV;10eSw3P)>gE{M39iZ@rJ kw)`q&PV`!BhwxSY0fsdU4}wNK9{>OV07*qoM6N<$g2#EKrT_o{ diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc index 88b5e553f308..da0b501cc3ad 100644 --- a/crawl-ref/source/tilepick.cc +++ b/crawl-ref/source/tilepick.cc @@ -3531,8 +3531,6 @@ tileidx_t tileidx_ability(const ability_type ability) // Fedhas case ABIL_FEDHAS_WALL_OF_BRIARS: return TILEG_ABILITY_FEDHAS_WALL_OF_BRIARS; - case ABIL_FEDHAS_RAIN: - return TILEG_ABILITY_FEDHAS_RAIN; case ABIL_FEDHAS_GROW_BALLISTOMYCETE: return TILEG_ABILITY_FEDHAS_GROW_BALLISTOMYCETE; // Cheibriados From 286ebac72db5281c2ca387bddb81a7361e2c612b Mon Sep 17 00:00:00 2001 From: gammafunk Date: Wed, 11 Sep 2019 13:51:00 -0500 Subject: [PATCH 751/864] Fedhas rework part 9: Overgrow ability A 4* ability that transforms any (non-permarock) walls, trees, doors, or diggable solid features in a 3x3 smite-targeted area into plant allies at a cost of 12 piety. The created monster is a summon, but the wall is permanently destroyed. This commit implements a targeter UI that only shows cells as affected if they contain a wall that's a valid target for Overgrow. To be affected, a wall must be in LOS and not blocked by a feature that blocks translocations (e.g. clear walls). Open doors won't be affect if they contain a monster, and if it turns out there was an invisible monster in the open door, the ability will fail but still use piety. Currently the set of possible plant allies is weighted towards oklob saplings, wandering mushrooms, and burning bushes, with lower chances for ballistomycetes and oklob plants. The plant HD is increased by 1 with each level of Invocations, which for oklob saplings, burning bushes, and oklob plants will give more damage per use of their abilities, and oklob plants will get an increase in their "spit" rate. All monsters will get increased HP and summon duration with Invocations. --- crawl-ref/source/ability-type.h | 1 + crawl-ref/source/ability.cc | 12 +++ crawl-ref/source/beam.h | 1 + crawl-ref/source/dat/descript/ability.txt | 5 ++ crawl-ref/source/religion.cc | 1 + crawl-ref/source/rltiles/dc-invocations.txt | 1 + .../gui/invocations/fedhas_overgrow.png | Bin 0 -> 364 bytes crawl-ref/source/spl-summoning.cc | 55 ++++++++++++++ crawl-ref/source/spl-summoning.h | 1 + crawl-ref/source/target.cc | 71 ++++++++++++++++++ crawl-ref/source/target.h | 12 +++ crawl-ref/source/tilepick.cc | 2 + 12 files changed, 162 insertions(+) create mode 100644 crawl-ref/source/rltiles/gui/invocations/fedhas_overgrow.png diff --git a/crawl-ref/source/ability-type.h b/crawl-ref/source/ability-type.h index d3c5e73a1253..3370b93ac1e2 100644 --- a/crawl-ref/source/ability-type.h +++ b/crawl-ref/source/ability-type.h @@ -175,6 +175,7 @@ enum ability_type // Fedhas ABIL_FEDHAS_WALL_OF_BRIARS = 1140, ABIL_FEDHAS_GROW_BALLISTOMYCETE, + ABIL_FEDHAS_OVERGROW, // Cheibriados ABIL_CHEIBRIADOS_TIME_STEP = 1151, ABIL_CHEIBRIADOS_TIME_BEND, diff --git a/crawl-ref/source/ability.cc b/crawl-ref/source/ability.cc index f5d766c6a7a6..fb69eee8eea4 100644 --- a/crawl-ref/source/ability.cc +++ b/crawl-ref/source/ability.cc @@ -518,6 +518,8 @@ static const ability_def Ability_List[] = 3, 0, 50, 2, {fail_basis::invo, 30, 6, 20}, abflag::none}, { ABIL_FEDHAS_GROW_BALLISTOMYCETE, "Grow Ballistomycete", 4, 0, 100, 4, {fail_basis::invo, 60, 4, 25}, abflag::none }, + { ABIL_FEDHAS_OVERGROW, "Overgrow", + 8, 0, 200, 12, {fail_basis::invo, 70, 5, 20}, abflag::none}, // Cheibriados { ABIL_CHEIBRIADOS_TIME_BEND, "Bend Time", @@ -2849,6 +2851,16 @@ static spret _do_ability(const ability_def& abil, bool fail) break; } + case ABIL_FEDHAS_OVERGROW: + { + fail_check(); + + if (!fedhas_overgrow()) + return spret::abort; + + break; + } + case ABIL_TRAN_BAT: { if (_player_cancels_vampire_bat_transformation()) diff --git a/crawl-ref/source/beam.h b/crawl-ref/source/beam.h index 10b443565317..5dc1dfe2d967 100644 --- a/crawl-ref/source/beam.h +++ b/crawl-ref/source/beam.h @@ -245,6 +245,7 @@ struct bolt private: void affect_wall(); void digging_wall_effect(); + void growth_wall_effect(); void burn_wall_effect(); void affect_ground(); void affect_place_clouds(); diff --git a/crawl-ref/source/dat/descript/ability.txt b/crawl-ref/source/dat/descript/ability.txt index 2d028bb91d39..a24dd70557d3 100644 --- a/crawl-ref/source/dat/descript/ability.txt +++ b/crawl-ref/source/dat/descript/ability.txt @@ -492,6 +492,11 @@ Grow a short-lived Ballistomycete at the location you choose. A Ballistomycete occasionally release spores that quickly seek out foes and violently explode, damaging and confusing all living things caught in the blast. %%%% +Overgrow ability + +Permanently destroy wall-like structures, growing a short-lived plant ally in +its place. Even a tree will give its life to support the will of Fedhas. +%%%% # Cheibriados Bend Time ability diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index 03df3b0346ed..9d9c622e4f6f 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -265,6 +265,7 @@ const vector god_powers[NUM_GODS] = { { 2, ABIL_FEDHAS_WALL_OF_BRIARS, "encircle yourself with summoned briar patches"}, { 3, ABIL_FEDHAS_GROW_BALLISTOMYCETE, "grow a ballistomycete" }, + { 4, ABIL_FEDHAS_OVERGROW, "transform dungeon walls and trees into plant allies"}, }, // Cheibriados diff --git a/crawl-ref/source/rltiles/dc-invocations.txt b/crawl-ref/source/rltiles/dc-invocations.txt index b6764dbec3d8..90b80e35b09b 100644 --- a/crawl-ref/source/rltiles/dc-invocations.txt +++ b/crawl-ref/source/rltiles/dc-invocations.txt @@ -22,6 +22,7 @@ elyvilon_purification ABILITY_ELYVILON_PURIFICATION elyvilon_heal_other ABILITY_ELYVILON_HEAL_OTHER fedhas_wall_of_briars ABILITY_FEDHAS_WALL_OF_BRIARS fedhas_grow_ballistomycete ABILITY_FEDHAS_GROW_BALLISTOMYCETE +fedhas_overgrow ABILITY_FEDHAS_OVERGROW gozag_potion_petition ABILITY_GOZAG_POTION_PETITION gozag_call_merchant ABILITY_GOZAG_CALL_MERCHANT gozag_bribe_branch ABILITY_GOZAG_BRIBE_BRANCH diff --git a/crawl-ref/source/rltiles/gui/invocations/fedhas_overgrow.png b/crawl-ref/source/rltiles/gui/invocations/fedhas_overgrow.png new file mode 100644 index 0000000000000000000000000000000000000000..ada89e16ec5dfd5a724e8fcaa548b2489cc46cdf GIT binary patch literal 364 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyx&b~Ru0R?Hcua+4(nJ(keGLo@ z92^{6*((#e_=Q>)#=%?6@O1wr%AV_D&6BeSSgZo<(vs; zqrY0&H_rUy^=A&Atm~Y8@vXSU`PL5x2RrZ9t$DU5%(!AEE8CP!*LF=4`ZRfi)!Yeg zjjU%P>QzF_Y{CmX`!}dA=VE$rJ==-%7r&{RgR4uqxlYzjwI3DB9j7mUq}0%)U47tP zqJ;K?@`z5MU<0)|bCZG(JaNqEm}3;>+Wc4Rt(9uTo>gmW^ec90v?S>t5ec?Z<%m8L zy(rPzBKo@0+w)7rL;CdpsdW7CzI0%&ff4sfGpl*;Js;}Zc@*))TAp~o4GJ_*S3j3^ HP6name(DESC_A).c_str()); + } + // XXX: Maybe try to make this revert the terrain if a monster isn't placed. + else + mprf("%s falls apart, but nothing grows.", what.c_str()); +} + +bool fedhas_overgrow() +{ + targeter_overgrow tgt; + direction_chooser_args args; + args.hitfunc = &tgt; + args.restricts = DIR_TARGET; + args.mode = TARG_ANY; + args.range = LOS_RADIUS; + args.just_looking = false; + args.needs_path = false; + args.top_prompt = "Aiming: Overgrow"; + dist sdirect; + direction(sdirect, args); + if (!sdirect.isValid) + return false; + + for (auto site : tgt.affected_positions) + _overgrow_wall(site); + + return true; +} + spret fedhas_grow_ballistomycete(bool fail) { dist spd; diff --git a/crawl-ref/source/spl-summoning.h b/crawl-ref/source/spl-summoning.h index 9c2c6dc56f14..c1dd5f0029ae 100644 --- a/crawl-ref/source/spl-summoning.h +++ b/crawl-ref/source/spl-summoning.h @@ -128,3 +128,4 @@ int count_summons(const actor *summoner, spell_type spell); bool fedhas_wall_of_briars(); spret fedhas_grow_ballistomycete(bool fail); +bool fedhas_overgrow(); diff --git a/crawl-ref/source/target.cc b/crawl-ref/source/target.cc index 8993f33a982a..470e2cedc0fc 100644 --- a/crawl-ref/source/target.cc +++ b/crawl-ref/source/target.cc @@ -1604,3 +1604,74 @@ aff_type targeter_monster_sequence::is_affected(coord_def loc) return on_path ? AFF_TRACER : AFF_NO; } + +targeter_overgrow::targeter_overgrow() +{ + agent = &you; + origin = you.pos(); +} + +bool targeter_overgrow::overgrow_affects_pos(const coord_def &p) +{ + if (env.markers.property_at(p, MAT_ANY, "veto_shatter") == "veto") + return false; + + const dungeon_feature_type feat = grd(p); + if (feat_is_open_door(feat)) + { + const monster* const mons = monster_at(p); + if (mons && agent && agent->can_see(*mons)) + return false; + + return true; + } + + return feat_is_diggable(feat) + || feat_is_closed_door(feat) + || feat_is_tree(feat) + || (feat_is_wall(feat) && !feat_is_permarock(feat)); +} + +aff_type targeter_overgrow::is_affected(coord_def loc) +{ + if (affected_positions.count(loc)) + return AFF_YES; + + return AFF_NO; +} + +bool targeter_overgrow::valid_aim(coord_def a) +{ + if (a != origin && !cell_see_cell(origin, a, LOS_NO_TRANS)) + { + if (agent && agent->see_cell(a)) + return notify_fail("There's something in the way."); + return notify_fail("You cannot see that place."); + } + + if (!overgrow_affects_pos(a)) + return notify_fail("You cannot grow anything here."); + + return true; +} + +bool targeter_overgrow::set_aim(coord_def a) +{ + affected_positions.clear(); + + if (!targeter::set_aim(a)) + return false; + + if (overgrow_affects_pos(a)) + affected_positions.insert(a); + else + return false; + + for (adjacent_iterator ai(a, true); ai; ++ai) + { + if (overgrow_affects_pos(*ai) && you.see_cell_no_trans(*ai)) + affected_positions.insert(*ai); + } + + return affected_positions.size(); +} diff --git a/crawl-ref/source/target.h b/crawl-ref/source/target.h index 30ba48af1be1..6c0f6acd172f 100644 --- a/crawl-ref/source/target.h +++ b/crawl-ref/source/target.h @@ -324,3 +324,15 @@ class targeter_dig : public targeter_beam private: map aim_test_cache; }; + +class targeter_overgrow: public targeter +{ +public: + targeter_overgrow(); + bool valid_aim(coord_def a) override; + aff_type is_affected(coord_def loc) override; + bool set_aim(coord_def a) override; + set affected_positions; +private: + bool overgrow_affects_pos(const coord_def &p); +}; diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc index da0b501cc3ad..3cf35c47d44f 100644 --- a/crawl-ref/source/tilepick.cc +++ b/crawl-ref/source/tilepick.cc @@ -3533,6 +3533,8 @@ tileidx_t tileidx_ability(const ability_type ability) return TILEG_ABILITY_FEDHAS_WALL_OF_BRIARS; case ABIL_FEDHAS_GROW_BALLISTOMYCETE: return TILEG_ABILITY_FEDHAS_GROW_BALLISTOMYCETE; + case ABIL_FEDHAS_OVERGROW: + return TILEG_ABILITY_FEDHAS_OVERGROW; // Cheibriados case ABIL_CHEIBRIADOS_TIME_STEP: return TILEG_ABILITY_CHEIBRIADOS_TIME_STEP; From dacd3b15afd9e130b45fe72556c301713cb0771d Mon Sep 17 00:00:00 2001 From: gammafunk Date: Wed, 11 Sep 2019 13:52:48 -0500 Subject: [PATCH 752/864] Fedhas rework part 10: Grow Oklob ability A 5* ability to summon an oklob plant at a smite-targeted location within radius 2 for a cost of 6 piety. The HD of the oklob is increased by 1 for each level of Invocations skill, which increases its summon duration, its HP, the damage from its Spit Acid ability, as well as the frequency with which it uses Spit Acid. These aspects are all done in the same way as Fedhas' previous Evolution ability had Invocations influence oklobs. This is not an especially creative ability, but it's fun to play with strong stationary allies. At a cost of 6 piety, a player at 6* could make quite a few oklobs, so it's still possible to make a large group for a single fight on e.g. Zot:5. --- crawl-ref/source/ability-type.h | 1 + crawl-ref/source/ability.cc | 9 +++ crawl-ref/source/dat/descript/ability.txt | 4 ++ crawl-ref/source/religion.cc | 1 + crawl-ref/source/rltiles/dc-invocations.txt | 1 + .../gui/invocations/fedhas_grow_oklob.png | Bin 0 -> 364 bytes crawl-ref/source/spl-summoning.cc | 58 ++++++++++++++++++ crawl-ref/source/spl-summoning.h | 1 + crawl-ref/source/tilepick.cc | 2 + 9 files changed, 77 insertions(+) create mode 100644 crawl-ref/source/rltiles/gui/invocations/fedhas_grow_oklob.png diff --git a/crawl-ref/source/ability-type.h b/crawl-ref/source/ability-type.h index 3370b93ac1e2..c8c0dbac1d0f 100644 --- a/crawl-ref/source/ability-type.h +++ b/crawl-ref/source/ability-type.h @@ -176,6 +176,7 @@ enum ability_type ABIL_FEDHAS_WALL_OF_BRIARS = 1140, ABIL_FEDHAS_GROW_BALLISTOMYCETE, ABIL_FEDHAS_OVERGROW, + ABIL_FEDHAS_GROW_OKLOB, // Cheibriados ABIL_CHEIBRIADOS_TIME_STEP = 1151, ABIL_CHEIBRIADOS_TIME_BEND, diff --git a/crawl-ref/source/ability.cc b/crawl-ref/source/ability.cc index fb69eee8eea4..3f4f07b64811 100644 --- a/crawl-ref/source/ability.cc +++ b/crawl-ref/source/ability.cc @@ -520,6 +520,8 @@ static const ability_def Ability_List[] = 4, 0, 100, 4, {fail_basis::invo, 60, 4, 25}, abflag::none }, { ABIL_FEDHAS_OVERGROW, "Overgrow", 8, 0, 200, 12, {fail_basis::invo, 70, 5, 20}, abflag::none}, + { ABIL_FEDHAS_GROW_OKLOB, "Grow Oklob", + 6, 0, 150, 6, {fail_basis::invo, 80, 4, 25}, abflag::none }, // Cheibriados { ABIL_CHEIBRIADOS_TIME_BEND, "Bend Time", @@ -2861,6 +2863,13 @@ static spret _do_ability(const ability_def& abil, bool fail) break; } + case ABIL_FEDHAS_GROW_OKLOB: + { + return fedhas_grow_oklob(fail); + + break; + } + case ABIL_TRAN_BAT: { if (_player_cancels_vampire_bat_transformation()) diff --git a/crawl-ref/source/dat/descript/ability.txt b/crawl-ref/source/dat/descript/ability.txt index a24dd70557d3..bbc05e235418 100644 --- a/crawl-ref/source/dat/descript/ability.txt +++ b/crawl-ref/source/dat/descript/ability.txt @@ -497,6 +497,10 @@ Overgrow ability Permanently destroy wall-like structures, growing a short-lived plant ally in its place. Even a tree will give its life to support the will of Fedhas. %%%% +Grow Oklob ability + +Grow a short-lived oklob plant at the location you choose. These dangerous plants spray corrosive vitriol at your foes. +%%%% # Cheibriados Bend Time ability diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index 9d9c622e4f6f..ec33a3b6eb9c 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -266,6 +266,7 @@ const vector god_powers[NUM_GODS] = { 2, ABIL_FEDHAS_WALL_OF_BRIARS, "encircle yourself with summoned briar patches"}, { 3, ABIL_FEDHAS_GROW_BALLISTOMYCETE, "grow a ballistomycete" }, { 4, ABIL_FEDHAS_OVERGROW, "transform dungeon walls and trees into plant allies"}, + { 5, ABIL_FEDHAS_GROW_OKLOB, "grow an oklob plant" }, }, // Cheibriados diff --git a/crawl-ref/source/rltiles/dc-invocations.txt b/crawl-ref/source/rltiles/dc-invocations.txt index 90b80e35b09b..e3beb26903a6 100644 --- a/crawl-ref/source/rltiles/dc-invocations.txt +++ b/crawl-ref/source/rltiles/dc-invocations.txt @@ -23,6 +23,7 @@ elyvilon_heal_other ABILITY_ELYVILON_HEAL_OTHER fedhas_wall_of_briars ABILITY_FEDHAS_WALL_OF_BRIARS fedhas_grow_ballistomycete ABILITY_FEDHAS_GROW_BALLISTOMYCETE fedhas_overgrow ABILITY_FEDHAS_OVERGROW +fedhas_grow_oklob ABILITY_FEDHAS_GROW_OKLOB gozag_potion_petition ABILITY_GOZAG_POTION_PETITION gozag_call_merchant ABILITY_GOZAG_CALL_MERCHANT gozag_bribe_branch ABILITY_GOZAG_BRIBE_BRANCH diff --git a/crawl-ref/source/rltiles/gui/invocations/fedhas_grow_oklob.png b/crawl-ref/source/rltiles/gui/invocations/fedhas_grow_oklob.png new file mode 100644 index 0000000000000000000000000000000000000000..ada89e16ec5dfd5a724e8fcaa548b2489cc46cdf GIT binary patch literal 364 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyx&b~Ru0R?Hcua+4(nJ(keGLo@ z92^{6*((#e_=Q>)#=%?6@O1wr%AV_D&6BeSSgZo<(vs; zqrY0&H_rUy^=A&Atm~Y8@vXSU`PL5x2RrZ9t$DU5%(!AEE8CP!*LF=4`ZRfi)!Yeg zjjU%P>QzF_Y{CmX`!}dA=VE$rJ==-%7r&{RgR4uqxlYzjwI3DB9j7mUq}0%)U47tP zqJ;K?@`z5MU<0)|bCZG(JaNqEm}3;>+Wc4Rt(9uTo>gmW^ec90v?S>t5ec?Z<%m8L zy(rPzBKo@0+w)7rL;CdpsdW7CzI0%&ff4sfGpl*;Js;}Zc@*))TAp~o4GJ_*S3j3^ HP6 2 || !in_bounds(beam.target)) + { + mpr("That's too far away."); + return spret::abort; + } + + if (!monster_habitable_grid(MONS_OKLOB_PLANT, grd(beam.target))) + { + mpr("You can't grow an oklob plant there."); + return spret::abort; + } + + monster* mons = monster_at(beam.target); + if (mons) + { + if (you.can_see(*mons)) + { + mpr("That space is already occupied."); + return spret::abort; + } + + fail_check(); + + // invisible monster + mpr("Something you can't see is occupying that space!"); + return spret::success; + } + + fail_check(); + + mgen_data mgen(MONS_OKLOB_PLANT, BEH_FRIENDLY, beam.target, MHITYOU, + MG_FORCE_BEH | MG_FORCE_PLACE | MG_AUTOFOE); + mgen.hd = mons_class_hit_dice(MONS_OKLOB_PLANT) + + you.skill_rdiv(SK_INVOCATIONS); + mgen.set_summoned(&you, 3 + you.skill_rdiv(SK_INVOCATIONS, 1, 5), + SPELL_NO_SPELL); + + if (create_monster(mgen)) + mpr("An oklob plant grows from the ground."); + else + canned_msg(MSG_NOTHING_HAPPENS); + + return spret::success; + +} diff --git a/crawl-ref/source/spl-summoning.h b/crawl-ref/source/spl-summoning.h index c1dd5f0029ae..3169317a39ae 100644 --- a/crawl-ref/source/spl-summoning.h +++ b/crawl-ref/source/spl-summoning.h @@ -129,3 +129,4 @@ int count_summons(const actor *summoner, spell_type spell); bool fedhas_wall_of_briars(); spret fedhas_grow_ballistomycete(bool fail); bool fedhas_overgrow(); +spret fedhas_grow_oklob(bool fail); diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc index 3cf35c47d44f..870975d2f250 100644 --- a/crawl-ref/source/tilepick.cc +++ b/crawl-ref/source/tilepick.cc @@ -3535,6 +3535,8 @@ tileidx_t tileidx_ability(const ability_type ability) return TILEG_ABILITY_FEDHAS_GROW_BALLISTOMYCETE; case ABIL_FEDHAS_OVERGROW: return TILEG_ABILITY_FEDHAS_OVERGROW; + case ABIL_FEDHAS_GROW_OKLOB: + return TILEG_ABILITY_FEDHAS_GROW_OKLOB; // Cheibriados case ABIL_CHEIBRIADOS_TIME_STEP: return TILEG_ABILITY_CHEIBRIADOS_TIME_STEP; From 27a75b7c532aff596d938667878326367cc1864d Mon Sep 17 00:00:00 2001 From: gammafunk Date: Wed, 11 Sep 2019 13:53:18 -0500 Subject: [PATCH 753/864] Fedhas rework part 11: simplify conducts Fedhas used to care about corpse-violating spells or items, a minor conduct thematically connected to how piety was gained for this god. Now that Fedhas appreciates kills, this conduct doesn't make thematic sense. It was also too minor a conduct, so the two best options are removing it or expanding it to a more significant set of conducts thematically connected to the current god. One option is making Fedhas hate all of necromancy. This is similar to the removed no-fire-magic conduct for Dith, but it affects a much larger number of spells in a school that's one of the strongest. Unfortunately, the reasons for current Fedhas hating necromancy are a bit tough to justify. Something about necromancy disrupting the natural cycle of life and death in nature is a bit sketchy when so many other things could do this. Another option is to make Fedhas a good god, which introduces some gameplay changes as well as an even more pervasive set of conducts. Unfortunately, Fedhas is a god that's significantly stronger early on relative to how strong they are later in the game. Since being a good god would remove any wrath effects at all for most god swaps and even allow retaining piety for switches to the good gods that are stronger than Fedhas later on, this opens up a lot of no-brainer god switches. In the end, I wasn't satisfied with either option, so for now I'm simply removing Fedhas' conducts related to undead worhsipers and corpse violation without replacement. This means that ghouls, mummies, vampires and those unblessed with the mighty lich form can now worship Fedhas. I'm open to re-adding something like the no-necromancy/undead conduct or another interesting conduct if details can be properly hashed out. Fedhas also had a minor conduct related to letting a permanent ally die which I've also removed. Fedhas no longer makes permanent allies, so this conduct no longer makes sense. Fedhas still gives penance if you kill an actual plant or a summoned ally, of course. --- crawl-ref/source/art-data.txt | 2 +- crawl-ref/source/art-func.h | 3 --- crawl-ref/source/artefact.h | 2 +- crawl-ref/source/conduct-type.h | 4 --- crawl-ref/source/god-conduct.cc | 40 +++++---------------------- crawl-ref/source/god-item.cc | 45 ------------------------------- crawl-ref/source/god-item.h | 2 -- crawl-ref/source/mon-death.cc | 15 ----------- crawl-ref/source/mon-place.cc | 11 -------- crawl-ref/source/monster.cc | 10 ------- crawl-ref/source/monster.h | 1 - crawl-ref/source/player-equip.cc | 2 -- crawl-ref/source/religion.cc | 6 +---- crawl-ref/source/spl-cast.cc | 3 --- crawl-ref/source/spl-cast.h | 2 +- crawl-ref/source/spl-data.h | 16 +++++------ crawl-ref/source/util/art-data.pl | 5 ++-- 17 files changed, 19 insertions(+), 150 deletions(-) diff --git a/crawl-ref/source/art-data.txt b/crawl-ref/source/art-data.txt index 633ffe064e49..f505a72dfa48 100644 --- a/crawl-ref/source/art-data.txt +++ b/crawl-ref/source/art-data.txt @@ -282,7 +282,7 @@ TILE_EQ: zonguldrok BRAND: SPWPN_REAPING FB_BRAND: SPWPN_PAIN VALUE: 800 -BOOL: evil, corpse_violating +BOOL: evil NAME: sword of Cerebov APPEAR: great serpentine sword diff --git a/crawl-ref/source/art-func.h b/crawl-ref/source/art-func.h index 027957d6469e..5b062d0fe27d 100644 --- a/crawl-ref/source/art-func.h +++ b/crawl-ref/source/art-func.h @@ -559,10 +559,7 @@ static void _ZONGULDROK_melee_effects(item_def* weapon, actor* attacker, actor* defender, bool mondied, int dam) { if (attacker->is_player()) - { did_god_conduct(DID_EVIL, 3); - did_god_conduct(DID_CORPSE_VIOLATION, 3); - } } /////////////////////////////////////////////////// diff --git a/crawl-ref/source/artefact.h b/crawl-ref/source/artefact.h index 97188487ad20..92f3acf8bb0e 100644 --- a/crawl-ref/source/artefact.h +++ b/crawl-ref/source/artefact.h @@ -28,7 +28,7 @@ enum unrand_flag_type UNRAND_FLAG_EVIL = 0x08, UNRAND_FLAG_UNCLEAN = 0x10, UNRAND_FLAG_CHAOTIC = 0x20, - UNRAND_FLAG_CORPSE_VIOLATING = 0x40, + // = 0x40, // was UNRAND_FLAG_CORPSE_VIOLATING UNRAND_FLAG_NOGEN = 0x80, UNRAND_FLAG_RANDAPP =0x100, UNRAND_FLAG_UNIDED =0x200, diff --git a/crawl-ref/source/conduct-type.h b/crawl-ref/source/conduct-type.h index e78c855984b8..8cbc5c3ae224 100644 --- a/crawl-ref/source/conduct-type.h +++ b/crawl-ref/source/conduct-type.h @@ -8,7 +8,6 @@ enum conduct_type DID_ATTACK_HOLY, DID_ATTACK_NEUTRAL, DID_ATTACK_FRIEND, - DID_FRIEND_DIED, DID_KILL_LIVING, DID_KILL_UNDEAD, DID_KILL_DEMON, @@ -33,9 +32,6 @@ enum conduct_type DID_KILL_SLIME, // Jiyva DID_KILL_PLANT, // Fedhas DID_HASTY, // Cheibriados - DID_CORPSE_VIOLATION, // Fedhas (Necromancy involving - // corpses/chunks). - DID_SOULED_FRIEND_DIED, // Zin DID_ATTACK_IN_SANCTUARY, // Zin DID_KILL_NONLIVING, DID_EXPLORATION, // Ashenzari, wrath timers diff --git a/crawl-ref/source/god-conduct.cc b/crawl-ref/source/god-conduct.cc index 23cfb23143ba..0ab535e90029 100644 --- a/crawl-ref/source/god-conduct.cc +++ b/crawl-ref/source/god-conduct.cc @@ -57,13 +57,12 @@ static const char *conducts[] = { "", "Evil", "Holy", "Attack Holy", "Attack Neutral", "Attack Friend", - "Friend Died", "Kill Living", "Kill Undead", "Kill Demon", - "Kill Natural Evil", "Kill Unclean", "Kill Chaotic", "Kill Wizard", - "Kill Priest", "Kill Holy", "Kill Fast", "Banishment", "Spell Memorise", - "Spell Cast", "Spell Practise", "Cannibalism", "Eat Souled Being", - "Deliberate Mutation", "Cause Glowing", "Use Unclean", "Use Chaos", - "Desecrate Orcish Remains", "Kill Slime", "Kill Plant", "Was Hasty", - "Corpse Violation", "Souled Friend Died", "Attack In Sanctuary", + "Kill Living", "Kill Undead", "Kill Demon", "Kill Natural Evil", + "Kill Unclean", "Kill Chaotic", "Kill Wizard", "Kill Priest", "Kill Holy", + "Kill Fast", "Banishment", "Spell Memorise", "Spell Cast", + "Spell Practise", "Cannibalism", "Eat Souled Being", "Deliberate Mutation", + "Cause Glowing", "Use Unclean", "Use Chaos", "Desecrate Orcish Remains", + "Kill Slime", "Kill Plant", "Was Hasty", "Attack In Sanctuary", "Kill Artificial", "Exploration", "Desecrate Holy Remains", "Seen Monster", "Sacrificed Love", "Channel", "Hurt Foe", }; @@ -257,20 +256,6 @@ static dislike_response _on_attack_friend(const char* desc) }; } -/// Fedhas's response to a friend(ly plant) dying. -static dislike_response _on_fedhas_friend_death(const char* desc) -{ - return - { - desc, false, - 1, 0, nullptr, nullptr, [] (const monster* victim) -> bool { - // ballistomycetes are penalized separately. - return victim && fedhas_protects(*victim) - && victim->mons_species() != MONS_BALLISTOMYCETE; - } - }; -} - typedef map peeve_map; /// a per-god map of conducts to that god's angry reaction to those conducts. @@ -417,18 +402,11 @@ static peeve_map divine_peeves[] = }, // GOD_FEDHAS, { - { DID_CORPSE_VIOLATION, { - "you use necromancy on corpses, chunks or skeletons", true, - 1, 1, " forgives your inadvertent necromancy, just this once." - } }, { DID_KILL_PLANT, { "you destroy plants", false, 1, 0 } }, { DID_ATTACK_FRIEND, _on_attack_friend(nullptr) }, - - { DID_FRIEND_DIED, _on_fedhas_friend_death("allied flora die") }, - { DID_SOULED_FRIEND_DIED, _on_fedhas_friend_death(nullptr) }, }, // GOD_CHEIBRIADOS, { @@ -1197,11 +1175,5 @@ bool god_punishes_spell(spell_type spell, god_type god) if (map_find(divine_peeves[god], DID_HASTY) && spell == SPELL_SWIFTNESS) return true; - if (map_find(divine_peeves[god], DID_CORPSE_VIOLATION) - && is_corpse_violating_spell(spell)) - { - return true; - } - return false; } diff --git a/crawl-ref/source/god-item.cc b/crawl-ref/source/god-item.cc index 0f0b24be73b5..e5c8bc991018 100644 --- a/crawl-ref/source/god-item.cc +++ b/crawl-ref/source/god-item.cc @@ -125,41 +125,6 @@ bool is_potentially_evil_item(const item_def& item, bool calc_unid) return false; } -// This is a subset of is_evil_item(). -bool is_corpse_violating_item(const item_def& item, bool calc_unid) -{ - bool retval = false; - - if (is_unrandom_artefact(item)) - { - const unrandart_entry* entry = get_unrand_entry(item.unrand_idx); - - if (entry->flags & UNRAND_FLAG_CORPSE_VIOLATING) - return true; - } - - if (item.base_type == OBJ_WEAPONS - && (calc_unid || item_brand_known(item)) - && get_weapon_brand(item) == SPWPN_REAPING) - { - return true; - } - - if (!calc_unid && !item_type_known(item)) - return false; - - switch (item.base_type) - { - case OBJ_BOOKS: - retval = _is_book_type(item, is_corpse_violating_spell); - break; - default: - break; - } - - return retval; -} - /** * Do good gods always hate use of this item? * @@ -370,13 +335,6 @@ bool is_wizardly_item(const item_def& item, bool calc_unid) return false; } -bool is_corpse_violating_spell(spell_type spell) -{ - spell_flags flags = get_spell_flags(spell); - - return testbits(flags, spflag::corpse_violating); -} - /** * Do the good gods hate use of this spell? * @@ -448,9 +406,6 @@ vector item_conducts(const item_def &item) conducts.push_back(DID_SPELL_PRACTISE); } - if (is_corpse_violating_item(item, false)) - conducts.push_back(DID_CORPSE_VIOLATION); - if (_is_potentially_hasty_item(item) || is_hasty_item(item, false)) conducts.push_back(DID_HASTY); diff --git a/crawl-ref/source/god-item.h b/crawl-ref/source/god-item.h index 5bf4917c14e2..3c4eee816ff3 100644 --- a/crawl-ref/source/god-item.h +++ b/crawl-ref/source/god-item.h @@ -6,14 +6,12 @@ bool is_holy_item(const item_def& item, bool calc_unid = true); bool is_potentially_evil_item(const item_def& item, bool calc_unid = true); -bool is_corpse_violating_item(const item_def& item, bool calc_unid = true); bool is_evil_item(const item_def& item, bool calc_unid = true); bool is_unclean_item(const item_def& item, bool calc_unid = true); bool is_chaotic_item(const item_def& item, bool calc_unid = true); bool is_hasty_item(const item_def& item, bool calc_unid = true); bool is_wizardly_item(const item_def& item, bool calc_unid = true); bool is_channeling_item(const item_def& item, bool calc_unid = true); -bool is_corpse_violating_spell(spell_type spell); bool is_evil_spell(spell_type spell); bool is_unclean_spell(spell_type spell); bool is_chaotic_spell(spell_type spell); diff --git a/crawl-ref/source/mon-death.cc b/crawl-ref/source/mon-death.cc index 3b8dbfb7fb5b..54edfb3b00a7 100644 --- a/crawl-ref/source/mon-death.cc +++ b/crawl-ref/source/mon-death.cc @@ -2216,21 +2216,6 @@ item_def* monster_die(monster& mons, killer_type killer, _fire_kill_conducts(mons, killer, killer_index, gives_player_xp); - // Kill conducts do not assess piety loss for friends - // killed by other monsters. - if (mons.friendly()) - { - const bool sentient = mons_class_intel(mons.type) >= I_HUMAN; - // plant HD aren't very meaningful. (fedhas hack) - const int severity = mons.holiness() & MH_PLANT ? - 1 : - 1 + (mons.get_experience_level() / 4); - - did_god_conduct(sentient ? DID_SOULED_FRIEND_DIED - : DID_FRIEND_DIED, - severity, true, &mons); - } - // Trying to prevent summoning abuse here, so we're trying to // prevent summoned creatures from being done_good kills. Only // affects creatures which were friendly when summoned. diff --git a/crawl-ref/source/mon-place.cc b/crawl-ref/source/mon-place.cc index 3e336bd00c21..bd83bca86ba5 100644 --- a/crawl-ref/source/mon-place.cc +++ b/crawl-ref/source/mon-place.cc @@ -2833,13 +2833,6 @@ conduct_type player_will_anger_monster(const monster &mon) if (is_good_god(you.religion) && mon.evil()) return DID_EVIL; - if (you_worship(GOD_FEDHAS) - && ((mon.holiness() & MH_UNDEAD && !mon.is_insubstantial()) - || mon.has_corpse_violating_spell())) - { - return DID_CORPSE_VIOLATION; - } - if (is_evil_god(you.religion) && mon.is_holy()) return DID_HOLY; @@ -2888,10 +2881,6 @@ bool player_angers_monster(monster* mon, bool real) mprf("%s %s enraged by your holy aura!", mname.c_str(), vcomplex.c_str()); break; - case DID_CORPSE_VIOLATION: - mprf("%s %s revulsed by your support of nature!", - mname.c_str(), vcomplex.c_str()); - break; case DID_HOLY: mprf("%s %s enraged by your evilness!", mname.c_str(), vcomplex.c_str()); diff --git a/crawl-ref/source/monster.cc b/crawl-ref/source/monster.cc index ca868829c3eb..e87e4eaf15b6 100644 --- a/crawl-ref/source/monster.cc +++ b/crawl-ref/source/monster.cc @@ -639,11 +639,6 @@ bool monster::could_wield(const item_def &item, bool ignore_brand, if ((is_holy() || is_good_god(god)) && is_evil_item(item)) return false; - // Monsters that are gifts/worshippers of Fedhas won't use - // corpse-violating weapons. - if (god == GOD_FEDHAS && is_corpse_violating_item(item)) - return false; - // Monsters that are gifts/worshippers of Zin won't use unclean // weapons. if (god == GOD_ZIN && is_unclean_item(item)) @@ -2932,11 +2927,6 @@ bool monster::has_chaotic_spell() const return search_spells(is_chaotic_spell); } -bool monster::has_corpse_violating_spell() const -{ - return search_spells(is_corpse_violating_spell); -} - bool monster::has_attack_flavour(int flavour) const { for (int i = 0; i < 4; ++i) diff --git a/crawl-ref/source/monster.h b/crawl-ref/source/monster.h index db18e2f3e80e..c31d3bbfe453 100644 --- a/crawl-ref/source/monster.h +++ b/crawl-ref/source/monster.h @@ -447,7 +447,6 @@ class monster : public actor mon_spell_slot_flags spell_slot_flags(spell_type spell) const; bool has_unclean_spell() const; bool has_chaotic_spell() const; - bool has_corpse_violating_spell() const; bool has_attack_flavour(int flavour) const; bool has_damage_type(int dam_type); diff --git a/crawl-ref/source/player-equip.cc b/crawl-ref/source/player-equip.cc index d64a29c9c2ba..4b8c957651bd 100644 --- a/crawl-ref/source/player-equip.cc +++ b/crawl-ref/source/player-equip.cc @@ -388,8 +388,6 @@ static void _equip_use_warning(const item_def& item) { if (is_holy_item(item) && you_worship(GOD_YREDELEMNUL)) mpr("You really shouldn't be using a holy item like this."); - else if (is_corpse_violating_item(item) && you_worship(GOD_FEDHAS)) - mpr("You really shouldn't be using a corpse-violating item like this."); else if (is_evil_item(item) && is_good_god(you.religion)) mpr("You really shouldn't be using an evil item like this."); else if (is_unclean_item(item) && you_worship(GOD_ZIN)) diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index ec33a3b6eb9c..535fa83d924b 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -3070,7 +3070,7 @@ static bool _transformed_player_can_join_god(god_type which_god) switch (you.form) { case transformation::lich: - return !(is_good_god(which_god) || which_god == GOD_FEDHAS); + return !is_good_god(which_god); case transformation::statue: case transformation::wisp: return !(which_god == GOD_YREDELEMNUL); @@ -3123,10 +3123,6 @@ bool player_can_join_god(god_type which_god) if (which_god == GOD_BEOGH && !species_is_orcish(you.species)) return false; - // Fedhas hates undead, but will accept demonspawn. - if (which_god == GOD_FEDHAS && you.undead_state()) - return false; - if (which_god == GOD_GOZAG && you.gold < gozag_service_fee()) return false; diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc index d430d958d796..e8b8d25257ee 100644 --- a/crawl-ref/source/spl-cast.cc +++ b/crawl-ref/source/spl-cast.cc @@ -898,9 +898,6 @@ static void _spellcasting_god_conduct(spell_type spell) if (is_chaotic_spell(spell)) did_god_conduct(DID_CHAOS, conduct_level); - if (is_corpse_violating_spell(spell)) - did_god_conduct(DID_CORPSE_VIOLATION, conduct_level); - // not is_hasty_spell since the other ones handle the conduct themselves. if (spell == SPELL_SWIFTNESS) did_god_conduct(DID_HASTY, conduct_level); diff --git a/crawl-ref/source/spl-cast.h b/crawl-ref/source/spl-cast.h index 120daef571e5..054fefa4a1d6 100644 --- a/crawl-ref/source/spl-cast.h +++ b/crawl-ref/source/spl-cast.h @@ -35,7 +35,7 @@ enum class spflag needs_tracer = 0x00080000, // monster casting needs tracer noisy = 0x00100000, // makes noise, even if innate testing = 0x00200000, // a testing/debugging spell - corpse_violating = 0x00400000, // Conduct violation for Fedhas + // 0x00400000, // was spflag::corpse_violating // 0x00800000, // was SPFLAG_ALLOW_SELF utility = 0x01000000, // usable no matter what foe is no_ghost = 0x02000000, // ghosts can't get this spell diff --git a/crawl-ref/source/spl-data.h b/crawl-ref/source/spl-data.h index 955d06ab9139..f4b65008744d 100644 --- a/crawl-ref/source/spl-data.h +++ b/crawl-ref/source/spl-data.h @@ -626,7 +626,7 @@ static const struct spell_desc spelldata[] = { SPELL_ANIMATE_DEAD, "Animate Dead", spschool::necromancy, - spflag::area | spflag::neutral | spflag::corpse_violating | spflag::utility, + spflag::area | spflag::neutral | spflag::utility, 4, 0, -1, -1, @@ -661,7 +661,7 @@ static const struct spell_desc spelldata[] = { SPELL_ANIMATE_SKELETON, "Animate Skeleton", spschool::necromancy, - spflag::corpse_violating | spflag::utility, + spflag::utility, 1, 0, -1, -1, @@ -832,7 +832,7 @@ static const struct spell_desc spelldata[] = { SPELL_FULSOME_DISTILLATION, "Fulsome Distillation", spschool::transmutation | spschool::necromancy, - spflag::corpse_violating, + spflag::none, 1, 0, -1, -1, @@ -855,8 +855,7 @@ static const struct spell_desc spelldata[] = { SPELL_TWISTED_RESURRECTION, "Twisted Resurrection", spschool::necromancy, - spflag::chaotic | spflag::corpse_violating | spflag::utility - | spflag::monster, + spflag::chaotic | spflag::utility | spflag::monster, 5, 200, -1, -1, @@ -1236,7 +1235,7 @@ static const struct spell_desc spelldata[] = { SPELL_NECROMUTATION, "Necromutation", spschool::transmutation | spschool::necromancy, - spflag::helpful | spflag::corpse_violating | spflag::chaotic, + spflag::helpful | spflag::chaotic, 8, 200, -1, -1, @@ -1600,7 +1599,7 @@ static const struct spell_desc spelldata[] = { SPELL_SIMULACRUM, "Simulacrum", spschool::ice | spschool::necromancy, - spflag::corpse_violating, + spflag::none, 6, 200, -1, -1, @@ -3691,8 +3690,7 @@ static const struct spell_desc spelldata[] = { SPELL_CIGOTUVIS_EMBRACE, "Cigotuvi's Embrace", spschool::necromancy, - spflag::chaotic | spflag::corpse_violating | spflag::utility - | spflag::no_ghost, + spflag::chaotic | spflag::utility | spflag::no_ghost, 5, 200, -1, -1, diff --git a/crawl-ref/source/util/art-data.pl b/crawl-ref/source/util/art-data.pl index 581f164b6e0f..b8412a1fd81d 100755 --- a/crawl-ref/source/util/art-data.pl +++ b/crawl-ref/source/util/art-data.pl @@ -28,7 +28,6 @@ CLARITY => "bool", COLD => "num", COLOUR => "enum", - CORPSE_VIOLATING => "bool", CORRODE => "bool", CURSE => "bool", DEX => "num", @@ -256,8 +255,8 @@ sub finish_art my $flags = ""; my $flag; - foreach $flag ("SPECIAL", "HOLY", "EVIL", "CHAOTIC", - "CORPSE_VIOLATING", "NOGEN", "RANDAPP", "UNIDED", "SKIP_EGO") + foreach $flag ("SPECIAL", "HOLY", "EVIL", "CHAOTIC", "NOGEN", "RANDAPP", + "UNIDED", "SKIP_EGO") { if ($artefact->{$flag}) { From a1bddc09a483f4bf5fe2d0dc4746abbff539f8b4 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Fri, 20 Sep 2019 12:24:12 -0500 Subject: [PATCH 754/864] Rework damage of ballistomycete spores Currently the spore damage is fixed at 3d15, which is pretty high when the 3* Grow Ballistomycete becomes available. This commit incorporates Invocations skill into the spore explosion damage and decreases the initial damage. The new explosion damage is 3d(5 + spore HD), with spore HD ranging from 1 at 0 Invocations to 28 at Invocations 27. Hence the max damage at 27 Invocations is 3d33, which is very similar to max spell-power Fireball. --- crawl-ref/source/mon-cast.cc | 9 ++++++--- crawl-ref/source/mon-death.cc | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/mon-cast.cc b/crawl-ref/source/mon-cast.cc index cf9e617103b8..6e5e259bd0f9 100644 --- a/crawl-ref/source/mon-cast.cc +++ b/crawl-ref/source/mon-cast.cc @@ -6882,12 +6882,15 @@ void mons_cast(monster* mons, bolt pbolt, spell_type spell_cast, case SPELL_SPORULATE: { - mgen_data spored (MONS_BALLISTOMYCETE_SPORE, + mgen_data mgen (MONS_BALLISTOMYCETE_SPORE, mons->friendly() ? BEH_FRIENDLY : BEH_HOSTILE, mons->pos(), mons->foe); - spored.set_summoned(mons, 0, SPELL_SPORULATE); + mgen.set_summoned(mons, 0, SPELL_SPORULATE); + // Add 1HD to the spore for each additional HD the spawner has. + mgen.hd = mons_class_hit_dice(MONS_BALLISTOMYCETE_SPORE) + + max(0, mons->spell_hd() - mons_class_hit_dice(mons->type)); - if (monster *spore = create_monster(spored)) + if (monster* const spore = create_monster(mgen)) spore->add_ench(ENCH_SHORT_LIVED); return; diff --git a/crawl-ref/source/mon-death.cc b/crawl-ref/source/mon-death.cc index 54edfb3b00a7..5d496517eb6f 100644 --- a/crawl-ref/source/mon-death.cc +++ b/crawl-ref/source/mon-death.cc @@ -1084,7 +1084,7 @@ void setup_spore_explosion(bolt & beam, const monster& origin) { _setup_base_explosion(beam, origin); beam.flavour = BEAM_SPORE; - beam.damage = dice_def(3, 15); + beam.damage = dice_def(3, 5 + origin.get_hit_dice()); beam.name = "explosion of spores"; beam.colour = LIGHTGREY; beam.ex_size = 1; From bab67b8a05707d9a64d4db65cde38b51fce355e1 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Tue, 1 Oct 2019 18:10:20 -0500 Subject: [PATCH 755/864] Remove an unused function for Dithmenos conducts Since Dith no longer cares about sources of fire, this function is unused. A similar function that tests for fiery monsters by monster class is still necessary for resistance checks. --- crawl-ref/source/mon-util.cc | 19 ------------------- crawl-ref/source/mon-util.h | 1 - 2 files changed, 20 deletions(-) diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index d90efbb6ffee..30c18f644c8d 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -832,25 +832,6 @@ bool cheibriados_thinks_mons_is_fast(const monster& mon) return cheibriados_monster_player_speed_delta(mon) > 0; } -// Dithmenos also hates fire users, flaming weapons, and generally fiery beings. -bool mons_is_fiery(const monster& mon) -{ - if (mons_genus(mon.type) == MONS_DRACONIAN - && draco_or_demonspawn_subspecies(mon) == MONS_RED_DRACONIAN) - { - return true; - } - if (mons_genus(mon.type) == MONS_DANCING_WEAPON - && mon.weapon() && mon.weapon()->brand == SPWPN_FLAMING) - { - return true; - } - return mon.has_attack_flavour(AF_FIRE) - || mon.has_attack_flavour(AF_PURE_FIRE) - || mon.has_attack_flavour(AF_STICKY_FLAME) - || mon.has_spell_of_type(spschool::fire); -} - bool mons_is_projectile(monster_type mc) { return mons_class_flag(mc, M_PROJECTILE); diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h index ec1358b63e13..db8bf77a03c9 100644 --- a/crawl-ref/source/mon-util.h +++ b/crawl-ref/source/mon-util.h @@ -413,7 +413,6 @@ bool herd_monster(const monster& mon); int cheibriados_monster_player_speed_delta(const monster& mon); bool cheibriados_thinks_mons_is_fast(const monster& mon); -bool mons_is_fiery(const monster& mon); bool mons_is_projectile(monster_type mc); bool mons_is_projectile(const monster& mon); bool mons_can_cling_to_walls(const monster& mon); From bfa02ace7b0344c25e6f2ac9491636ff137fe48b Mon Sep 17 00:00:00 2001 From: EC2 Default User Date: Mon, 15 Jul 2019 05:29:54 +0000 Subject: [PATCH 756/864] Fix wizdump loading when rotted or Gozag follower. Recognize "HP:" and "MP:" as mourge line starts. Recognize Gozag which doesn't have a piety meter, causing the God line to only have 8 fields. --- crawl-ref/source/wiz-dump.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/wiz-dump.cc b/crawl-ref/source/wiz-dump.cc index a9fd821ba6e1..ff01c367efe2 100644 --- a/crawl-ref/source/wiz-dump.cc +++ b/crawl-ref/source/wiz-dump.cc @@ -369,7 +369,7 @@ bool chardump_parser::_check_stats1(const vector &tokens) { size_t size = tokens.size(); // Health: 248/248 AC: 44 Str: 35 XL: 26 Next: 58% - if (size <= 7 || (tokens[0] != "HP" && tokens[0] != "Health:")) + if (size <= 7 || (tokens[0] != "HP" && tokens[0] != "HP:"&& tokens[0] != "Health:")) return false; bool found = false; @@ -396,7 +396,7 @@ bool chardump_parser::_check_stats2(const vector &tokens) { size_t size = tokens.size(); // Magic: 36/36 EV: 31 Int: 17 God: Cheibriados [****..] - if (size <= 8 || (tokens[0] != "MP" && tokens[0] != "Magic:")) + if (size <= 7 || (tokens[0] != "MP" && tokens[0] != "MP:" && tokens[0] != "Magic:")) return false; bool found = false; @@ -423,6 +423,8 @@ bool chardump_parser::_check_stats2(const vector &tokens) join_religion(god); } + if (god == GOD_GOZAG) + continue; string piety = tokens[k+2]; int piety_levels = std::count(piety.begin(), piety.end(), '*'); wizard_set_piety_to(piety_levels > 0 From 74cc3aede520f2e9454f868abdca2315e1248348 Mon Sep 17 00:00:00 2001 From: Nikolai Lavsky <3328424+nlavsky@users.noreply.github.com> Date: Fri, 14 Jun 2019 14:09:14 +0300 Subject: [PATCH 757/864] Fix display of detected gold on the minimap (11950) Currently, there are several Gold Sense-related bugs: * on webtiles, detected gold is not displayed on the minimap; * on local tiles, it disappears from the minimap after reloading the game and after reentering a floor; * on console, it's not possible to scroll the map in the X mode to see all detected piles of gold on a new level. This happens because now update_item_at() runs more than once for each pile of gold. Prior to 063869c, the gold detection code from files.cc:_count_gold(), which contains update_item_at(), run only once for each new level. After that commit and after 4488db6, the gold detection code, which is now in god-passive.cc:gozag_detect_level_gold(), runs twice when the player enters a new floor. First, it runs as a delayed action, then it runs for counting the generated gold (both calls come from files.cc:load_level()). When it's called the first time, gozag_detect_level_gold() sets the MAP_DETECTED_ITEM flag for each pile of gold, so they would appear on the minimap. When gozag_detect_level_gold() called after that, clear_item() removes this flag from the piles, and, since env.map_knowledge() already knows about those piles, gozag_detect_level_gold() won't set the flag again. The code path is god-passive.cc:gozag_detect_level_gold() -> show.cc:update_item_at() -> map-cell.h:set_item() -> map-cell.h:clear_item(). Unlike webtiles, local tiles update the minimap only after the first call, so detected gold appears on the minimap, but only until a current level is reloaded. This commit makes it safe to call gozag_detect_level_gold() multiple times: update_item_at() will be called only for undetected piles of gold. Also, force update of the minimap so piles of gold generated in new Abyss regions are displayed too. --- crawl-ref/source/god-passive.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/god-passive.cc b/crawl-ref/source/god-passive.cc index 06090f0bbece..3337a19d5cdf 100644 --- a/crawl-ref/source/god-passive.cc +++ b/crawl-ref/source/god-passive.cc @@ -1096,13 +1096,19 @@ void gozag_detect_level_gold(bool count) || env.map_knowledge(pos).item()->base_type != OBJ_GOLD) { detected = true; + update_item_at(pos, true); } - update_item_at(pos, true); // the pile can still remain undetected if it is not in // you.visible_igrd, for example if it is under deep water and the // player will not be able to see it. if (detected && env.map_knowledge(pos).item()) + { env.map_knowledge(pos).flags |= MAP_DETECTED_ITEM; +#ifdef USE_TILE + // force an update for gold generated during Abyss shifts + tiles.update_minimap(pos); +#endif + } } } } From f4813fd24d8b2797c155dabd379b5b2da6d25a5b Mon Sep 17 00:00:00 2001 From: gammafunk Date: Wed, 2 Oct 2019 14:38:40 -0500 Subject: [PATCH 758/864] Update the descriptions for Sif Muna (Goratrix) The god and god power descriptions were still based on the previous iteration of Sif. [skip ci] --- crawl-ref/source/dat/descript/gods.txt | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/crawl-ref/source/dat/descript/gods.txt b/crawl-ref/source/dat/descript/gods.txt index bfaea933b3e8..8897a61021e0 100644 --- a/crawl-ref/source/dat/descript/gods.txt +++ b/crawl-ref/source/dat/descript/gods.txt @@ -151,10 +151,10 @@ foes. Sif Muna Sif Muna the Loreminder is a contemplative but powerful deity, served by those -who seek magical knowledge. The Loreminder appreciates followers who triumph -over their foes and especially the training of spellcasting skills in order to -do so. The faithful can expect to receive a supply of spellbooks taken directly -from Sif Muna's legendary library. +who seek magical knowledge. Followers who triumph over their foes can call upon +the Loreminder for magical power and the ability to cast spells beyond their +magical training. The devout are rewarded with a supply of spellbooks taken +directly from Sif Muna's legendary library. %%%% the Shining One @@ -391,11 +391,10 @@ Ru's sacrificants increases in strength with more piety from more sacrifices. %%%% Sif Muna powers -Sif Muna will grant followers divine energy, allowing them to occasionally cast -spells even with insufficient reserves of magic. Eventually worshippers will -gain the ability to rapidly restore their magical energy, and to forget spells -at will, so as to learn new ones. Sif Muna protects spellcasters against the -negative effects of miscasting spells. Over time, followers will receive +Sif Muna grants followers the ability to rapidly restore their magical energy, +and to forget spells at will, so as to learn new ones. Worshipers can call upon +the Loreminder to help cast any spell they've discovered, even if it's well +beyond their current magical training. Over time, devout followers will receive spellbooks containing a vast range of spells. %%%% the Shining One powers From ca426f56c8b62abadc918dafea5d174735114f57 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Wed, 2 Oct 2019 14:40:21 -0500 Subject: [PATCH 759/864] =?UTF-8?q?Update=20descriptions=20for=20Fedhas=20?= =?UTF-8?q?(Snack=20=E2=91=A8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update descriptions for the god and the general description of its powers, and update the descriptions for all ability to mention the affects of Invocations training. [skip ci] --- crawl-ref/source/dat/descript/ability.txt | 16 ++++++++++++---- crawl-ref/source/dat/descript/gods.txt | 14 +++++++------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/crawl-ref/source/dat/descript/ability.txt b/crawl-ref/source/dat/descript/ability.txt index bbc05e235418..98035fa94827 100644 --- a/crawl-ref/source/dat/descript/ability.txt +++ b/crawl-ref/source/dat/descript/ability.txt @@ -488,18 +488,26 @@ be damaged by sharp thorns. Invocations skill increases the briars' health. %%%% Grow Ballistomycete ability -Grow a short-lived Ballistomycete at the location you choose. A Ballistomycete +Grow a short-lived ballistomycete at the location you choose. A Ballistomycete occasionally release spores that quickly seek out foes and violently explode, damaging and confusing all living things caught in the blast. + +Invocations skill increases the health and duration of the ballistomycete as +well as the damage of its exploding spores. %%%% Overgrow ability -Permanently destroy wall-like structures, growing a short-lived plant ally in -its place. Even a tree will give its life to support the will of Fedhas. +Permanently destroy a wall-like structure, growing a short-lived plant ally in +its place. Even a tree will give its life to support the will of Fedhas, and +only truly indestructible walls are immune to this power. %%%% Grow Oklob ability -Grow a short-lived oklob plant at the location you choose. These dangerous plants spray corrosive vitriol at your foes. +Grow a short-lived oklob plant at the location you choose. These dangerous +plants spray corrosive vitriol at your foes. + +Invocations skill increases the health and duration of the oklob as well as the +frequency with which it sprays its acid. %%%% # Cheibriados Bend Time ability diff --git a/crawl-ref/source/dat/descript/gods.txt b/crawl-ref/source/dat/descript/gods.txt index 8897a61021e0..5fde8b176b2e 100644 --- a/crawl-ref/source/dat/descript/gods.txt +++ b/crawl-ref/source/dat/descript/gods.txt @@ -265,13 +265,13 @@ upon Elyvilon for protection. Fedhas powers Plants and fungi will not attack Fedhas' worshippers without provocation. -Corpses on different levels will rot away; followers can also induce this decay -directly to create fungi. Fedhas' worshippers may walk through plants or fungi, -and even fire missiles or spells through them without causing harm. Fedhas -grants the ability to promote plants and fungi into stronger species. Followers -can eventually grow a wall of plants and create explosive spores from corpses. -They are also granted some control over the weather, being able to call -sunlight and eventually rainstorms. +Worshippers may walk through plants or fungi, and even fire missiles or spells +through them without causing harm. Fedhas grants powers to temporarily grow a +menagerie of plant allies whose strength and duration increase with Invocations +skill. Worshipers may grow a protective wall of briar patches as well as +ballistomycetes that fire damaging spores whose explosions confuse living +creatures. Devout followers can overgrow a stretch of solid terrain with a +cluster of plant allies or even summon a mighty oklob plant. %%%% Gozag powers From f1eb651baa9d281247697378f312934a530e9b0f Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Thu, 3 Oct 2019 19:26:32 +0800 Subject: [PATCH 760/864] Fix startup menu spacing issues This fixes a bug where there was no margin between the header text and the name entry row. This also replaces some conditional minimum heights with proper margins. --- crawl-ref/source/startup.cc | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index 86410510a85e..79855286494f 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -537,12 +537,14 @@ class UIStartupMenu : public Widget m_root->_set_parent(this); m_root->align_items = Widget::Align::STRETCH; - formatted_string about = opening_screen(); + auto about = make_shared(opening_screen()); + about->set_margin_for_crt({0, 0, 1, 0}); + about->set_margin_for_sdl({0, 0, 10, 0}); - m_root->add_child(make_shared(about)); + m_root->add_child(move(about)); auto grid = make_shared(); - grid->set_margin_for_crt({1, 0, 1, 0}); + grid->set_margin_for_crt({0, 0, 1, 0}); // If the game filled in a complete name, the user will // usually want to enter a new name instead of adding @@ -553,9 +555,7 @@ class UIStartupMenu : public Widget auto name_prompt = make_shared("Enter your name:"); name_prompt->set_margin_for_crt({0, 1, 1, 0}); -#ifdef USE_TILE_LOCAL - name_prompt->min_size() = { 0, TILE_Y + 2 }; -#endif + name_prompt->set_margin_for_sdl({0, 0, 10, 0}); input_text->set_margin_for_sdl({0, 0, 10, 10}); grid->add_child(move(name_prompt), 0, 0); grid->add_child(input_text, 1, 0); @@ -564,9 +564,7 @@ class UIStartupMenu : public Widget auto mode_prompt = make_shared("Choices:"); mode_prompt->set_margin_for_crt({0, 1, 1, 0}); -#ifdef USE_TILE_LOCAL - mode_prompt->min_size() = { 0, TILE_Y + 2 }; -#endif + mode_prompt->set_margin_for_sdl({0, 0, 10, 0}); game_modes_menu = make_shared(true, 1, ARRAYSZ(entries)); game_modes_menu->set_margin_for_sdl({0, 0, 10, 10}); game_modes_menu->set_margin_for_crt({0, 0, 1, 0}); @@ -587,6 +585,7 @@ class UIStartupMenu : public Widget { auto save_prompt = make_shared("Saved games:"); save_prompt->set_margin_for_crt({0, 1, 1, 0}); + save_prompt->set_margin_for_sdl({0, 0, 10, 0}); save_games_menu->set_margin_for_sdl({0, 0, 10, 10}); #ifdef USE_TILE_LOCAL save_prompt->min_size() = { 0, TILE_Y + 2 }; From f64bd74572e4526b8c68054500d24359c89ad20d Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Thu, 3 Oct 2019 19:29:35 +0800 Subject: [PATCH 761/864] Simplify code --- crawl-ref/source/startup.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index 79855286494f..6529f5f2858c 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -546,17 +546,17 @@ class UIStartupMenu : public Widget auto grid = make_shared(); grid->set_margin_for_crt({0, 0, 1, 0}); + auto name_prompt = make_shared("Enter your name:"); + name_prompt->set_margin_for_crt({0, 1, 1, 0}); + name_prompt->set_margin_for_sdl({0, 0, 10, 0}); + // If the game filled in a complete name, the user will // usually want to enter a new name instead of adding // to the current one. - input_text = make_shared(); - input_text->set_text(formatted_string(input_string, WHITE)); + input_text = make_shared(formatted_string(input_string, WHITE)); input_text->set_margin_for_crt({0, 0, 1, 0}); - - auto name_prompt = make_shared("Enter your name:"); - name_prompt->set_margin_for_crt({0, 1, 1, 0}); - name_prompt->set_margin_for_sdl({0, 0, 10, 0}); input_text->set_margin_for_sdl({0, 0, 10, 10}); + grid->add_child(move(name_prompt), 0, 0); grid->add_child(input_text, 1, 0); From 0be37ba3bdd624fa9bbb1f7baf402f37de906ed4 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Thu, 3 Oct 2019 19:53:25 +0800 Subject: [PATCH 762/864] Fix off-by-one error in mouse hover handling --- crawl-ref/source/ui.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index ce34723d4fb9..31f8bb266f61 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -1042,8 +1042,8 @@ shared_ptr Switcher::get_child_at_offset(int x, int y) int c = max(0, min(m_current, (int)m_children.size())); const auto region = m_children[c]->get_region(); - bool inside = (x > region[0] && x < region[0] + region[2]) - && (y > region[1] && y < region[1] + region[3]); + bool inside = (x >= region[0] && x < region[0] + region[2]) + && (y >= region[1] && y < region[1] + region[3]); return inside ? m_children[c] : nullptr; } From fb0ce180c5f53ef4ac0585ca9e0d4c0ee745e31d Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Thu, 3 Oct 2019 19:53:41 +0800 Subject: [PATCH 763/864] Add widget margin debug drawing --- crawl-ref/source/ui.cc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 31f8bb266f61..86cace98d5a9 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -1772,6 +1772,7 @@ void UIRoot::render() if (debug_draw) { LineBuffer lb; + ShapeBuffer sb; size_t i = 0; for (const auto& w : prev_hover_path) { @@ -1782,11 +1783,24 @@ void UIRoot::render() VColour(255, 100, 0, 100) : VColour(0, 50 + i*40, 0, 100); lb.add_square(r[0]+1, r[1]+1, r[0]+r[2], r[1]+r[3], lc); } + if (!prev_hover_path.empty()) + { + const auto& hovered_widget = prev_hover_path.back(); + i4 r = hovered_widget->get_region(); + i4 m = hovered_widget->margin; + + VColour lc = VColour(0, 0, 100, 100); + sb.add(r[0], r[1]-m[0], r[0]+r[2], r[1], lc); + sb.add(r[0]+r[2], r[1], r[0]+r[2]+m[1], r[1]+r[3], lc); + sb.add(r[0], r[1]+r[3], r[0]+r[2], r[1]+r[3]+m[2], lc); + sb.add(r[0]-m[3], r[1], r[0], r[1]+r[3], lc); + } if (auto w = get_focused_widget()) { i4 r = w->get_region(); lb.add_square(r[0]+1, r[1]+1, r[0]+r[2], r[1]+r[3], VColour(128,31,239,255)); } lb.draw(); + sb.draw(); } #else // Render only the top of the UI stack on console From 98f196556d9378d8ed5e010b9fdeeb8714ea3e0c Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Thu, 3 Oct 2019 22:45:37 +0800 Subject: [PATCH 764/864] Don't include debug drawing in release builds --- crawl-ref/source/ui.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 86cace98d5a9..cc6bc1dc69d2 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -104,7 +104,9 @@ static struct UIRoot void send_mouse_enter_leave_events(int mx, int my); bool needs_paint; +#ifdef DEBUG bool debug_draw = false; +#endif vector keymap_stack; vector cutoff_stack; vector focus_stack; @@ -1769,6 +1771,7 @@ void UIRoot::render() ASSERT(cutoff <= static_cast(m_root.num_children())); for (int i = cutoff; i < static_cast(m_root.num_children()); i++) m_root.get_child(i)->render(); +#ifdef DEBUG if (debug_draw) { LineBuffer lb; @@ -1802,6 +1805,7 @@ void UIRoot::render() lb.draw(); sb.draw(); } +#endif #else // Render only the top of the UI stack on console if (m_root.num_children() > 0) @@ -1883,6 +1887,7 @@ bool UIRoot::on_event(const wm_event& event) if (event_filter && event_filter(event)) return true; +#ifdef DEBUG if (event.type == WME_KEYDOWN && event.key.keysym.sym == CK_INSERT) { ui_root.debug_draw = !ui_root.debug_draw; @@ -1890,17 +1895,20 @@ bool UIRoot::on_event(const wm_event& event) ui_root.expose_region({0,0,INT_MAX,INT_MAX}); return true; } +#endif switch (event.type) { case WME_MOUSEBUTTONDOWN: case WME_MOUSEBUTTONUP: case WME_MOUSEMOTION: +#ifdef DEBUG if (ui_root.debug_draw) { ui_root.queue_layout(); ui_root.expose_region({0,0,INT_MAX,INT_MAX}); } +#endif case WME_MOUSEWHEEL: for (auto w = prev_hover_path.rbegin(); w != prev_hover_path.rend(); ++w) if ((*w)->on_event(event)) From dea222dd76d475a242414d06d641f737b4a55667 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Wed, 2 Oct 2019 01:36:32 +0800 Subject: [PATCH 765/864] Refactor and improve UI widget iterators This removes the honestly quite hacky container iterator implementation which deferred at runtime to a heap-allocated implementation class. Instead, each container type gets their own iterator. If you have a base class pointer and you want to iterate over it, the new foreach() helper function does that. It's a little ugly, but much better than before, especially since iterating over a derived type is the common case. --- crawl-ref/source/outer-menu.cc | 7 +- crawl-ref/source/ui.h | 180 +++++++++++++-------------------- 2 files changed, 75 insertions(+), 112 deletions(-) diff --git a/crawl-ref/source/outer-menu.cc b/crawl-ref/source/outer-menu.cc index 9125c8d6cbc4..d78c316d5fa2 100644 --- a/crawl-ref/source/outer-menu.cc +++ b/crawl-ref/source/outer-menu.cc @@ -74,8 +74,11 @@ void MenuButton::recolour_descendants(const shared_ptr& node) } auto container = dynamic_pointer_cast(node); if (container) - for (auto it = container->begin(); it != container->end(); ++it) - recolour_descendants(*it); + { + container->foreach([this](shared_ptr& child) { + recolour_descendants(child); + }); + } } #endif diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index 070a1d740411..ed2b29130ec9 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -177,59 +177,9 @@ class Widget : public enable_shared_from_this class Container : public Widget { -protected: - class iter_impl - { - public: - virtual ~iter_impl() {}; - virtual void operator++() = 0; - virtual shared_ptr& operator*() = 0; - virtual iter_impl* clone() const = 0; - virtual bool equal(iter_impl &other) const = 0; - }; - public: virtual ~Container() {} - class iterator : public std::iterator> - { - public: - iterator(iter_impl *_it) : it(_it) {}; - ~iterator() { delete it; it = nullptr; }; - iterator(const iterator& other) : it(other.it->clone()) {}; - iterator& operator=(const iterator& other) - { - if (it != other.it) - { - delete it; - it = other.it->clone(); - } - return *this; - } - iterator& operator=(iterator&& other) - { - if (it != other.it) - { - delete it; - it = other.it; - other.it = nullptr; - } - return *this; - } - - void operator++() { ++(*it); }; - bool operator==(const iterator& other) const - { - return typeid(it) == typeid(other.it) && it->equal(*other.it); - }; - bool operator!=(const iterator& other) const { return !(*this == other); } - shared_ptr& operator*() { return **it; }; - protected: - iter_impl *it; - }; - -public: - virtual iterator begin() = 0; - virtual iterator end() = 0; + virtual void foreach(function&)> f) = 0; }; class Bin : public Container @@ -243,31 +193,35 @@ class Bin : public Container virtual shared_ptr get_child() { return m_child; }; virtual shared_ptr get_child_at_offset(int x, int y) override; -private: - typedef Container::iterator I; - - class iter_impl_bin : public iter_impl +protected: + class iterator { - private: - typedef shared_ptr C; public: - explicit iter_impl_bin (C& _c, bool _state) : c(_c), state(_state) {}; - protected: - virtual void operator++() override { state = true; }; - virtual shared_ptr& operator*() override { return c; }; - virtual iter_impl_bin* clone() const override { return new iter_impl_bin(c, state); }; - virtual bool equal (iter_impl &_other) const override { - iter_impl_bin &other = static_cast(_other); - return c == other.c && state == other.state; - }; + typedef shared_ptr value_type; + typedef ptrdiff_t distance; + typedef shared_ptr* pointer; + typedef shared_ptr& reference; + typedef input_iterator_tag iterator_category; - C& c; + value_type c; bool state; + + iterator(value_type& _c, bool _state) : c(_c), state(_state) {}; + void operator++ () { state = true; }; + value_type& operator* () { return c; }; + bool operator== (const iterator& other) { return c == other.c && state == other.state; } + bool operator!= (const iterator& other) { return !(*this == other); } }; public: - virtual I begin() override { return I(new iter_impl_bin(m_child, false)); } - virtual I end() override { return I(new iter_impl_bin(m_child, true)); } + iterator begin() { return iterator(m_child, false); } + iterator end() { return iterator(m_child, true); } + virtual void foreach(function&)> f) override + { + for (auto& child : *this) + f(child); + } + protected: shared_ptr m_child; }; @@ -284,31 +238,36 @@ class ContainerVec : public Container size_t num_children() const { return m_children.size(); } shared_ptr& operator[](size_t pos) { return m_children[pos]; }; const shared_ptr& operator[](size_t pos) const { return m_children[pos]; }; -private: - typedef Container::iterator I; - class iter_impl_vec : public iter_impl +protected: + class iterator { - private: - typedef vector> C; public: - explicit iter_impl_vec (C& _c, C::iterator _it) : c(_c), it(_it) {}; - protected: - virtual void operator++() override { ++it; }; - virtual shared_ptr& operator*() override { return *it; }; - virtual iter_impl_vec* clone() const override { return new iter_impl_vec(c, it); }; - virtual bool equal (iter_impl &_other) const override { - iter_impl_vec &other = static_cast(_other); - return c == other.c && it == other.it; - }; - - C& c; - C::iterator it; + typedef shared_ptr value_type; + typedef ptrdiff_t distance; + typedef shared_ptr* pointer; + typedef shared_ptr& reference; + typedef input_iterator_tag iterator_category; + + vector& c; + vector::iterator it; + + iterator(vector& _c, vector::iterator _it) : c(_c), it(_it) {}; + void operator++ () { ++it; }; + value_type& operator* () { return *it; }; + bool operator== (const iterator& other) { return c == other.c && it == other.it; } + bool operator!= (const iterator& other) { return !(*this == other); } }; public: - virtual I begin() override { return I(new iter_impl_vec(m_children, m_children.begin())); } - virtual I end() override { return I(new iter_impl_vec(m_children, m_children.end())); } + iterator begin() { return iterator(m_children, m_children.begin()); } + iterator end() { return iterator(m_children, m_children.end()); } + virtual void foreach(function&)> f) override + { + for (auto& child : *this) + f(child); + } + protected: vector> m_children; }; @@ -520,33 +479,34 @@ class Grid : public Container void init_track_info(); bool m_track_info_dirty = false; -private: - typedef Container::iterator I; - - class iter_impl_grid : public iter_impl +protected: + class iterator { - private: - typedef vector C; public: - explicit iter_impl_grid (C& _c, C::iterator _it) : c(_c), it(_it) {}; - protected: - virtual void operator++() override { ++it; }; - virtual shared_ptr& operator*() override { return it->widget; }; - virtual iter_impl_grid* clone() const override { - return new iter_impl_grid(c, it); - }; - virtual bool equal (iter_impl &_other) const override { - iter_impl_grid &other = static_cast(_other); - return c == other.c && it == other.it; - }; - - C& c; - C::iterator it; + typedef shared_ptr value_type; + typedef ptrdiff_t distance; + typedef shared_ptr* pointer; + typedef shared_ptr& reference; + typedef input_iterator_tag iterator_category; + + vector& c; + vector::iterator it; + + iterator(vector& _c, vector::iterator _it) : c(_c), it(_it) {}; + void operator++ () { ++it; }; + value_type& operator* () { return it->widget; }; + bool operator== (const iterator& other) { return c == other.c && it == other.it; } + bool operator!= (const iterator& other) { return !(*this == other); } }; public: - virtual I begin() override { return I(new iter_impl_grid(m_child_info, m_child_info.begin())); } - virtual I end() override { return I(new iter_impl_grid(m_child_info, m_child_info.end())); } + iterator begin() { return iterator(m_child_info, m_child_info.begin()); } + iterator end() { return iterator(m_child_info, m_child_info.end()); } + virtual void foreach(function&)> f) override + { + for (auto& child : *this) + f(child); + } }; class Scroller : public Bin From 368c1644f80558c7481b449c14e40579c0494896 Mon Sep 17 00:00:00 2001 From: Umer Shaikh Date: Thu, 3 Oct 2019 13:04:11 -0500 Subject: [PATCH 766/864] Clean up a function Change the function is_habitable_feat to an equivalent formulation which is simpler and idiomatic. --- crawl-ref/source/player-act.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/player-act.cc b/crawl-ref/source/player-act.cc index ca1da670a6c2..8fd2e3843a27 100644 --- a/crawl-ref/source/player-act.cc +++ b/crawl-ref/source/player-act.cc @@ -169,10 +169,8 @@ bool player::can_pass_through_feat(dungeon_feature_type grid) const bool player::is_habitable_feat(dungeon_feature_type actual_grid) const { - if (!can_pass_through_feat(actual_grid)) - return false; - - return !is_feat_dangerous(actual_grid); + return can_pass_through_feat(actual_grid) + && !is_feat_dangerous(actual_grid); } size_type player::body_size(size_part_type psize, bool base) const From ad1f87bc892426752013bbea60264bd629eacb64 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 7 Oct 2019 02:15:13 +0800 Subject: [PATCH 767/864] Fix empty high scores menu (Goratrix, 12080) The reported bug was caused by there being no focused UI widget, so the escape key was never handled. I really need to revisit that whole focus system... I also added in a placeholder text label for when there are no highscores, explicitly stating the fact. --- crawl-ref/source/hiscores.cc | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/hiscores.cc b/crawl-ref/source/hiscores.cc index f9876a1fc287..a5c30fe101de 100644 --- a/crawl-ref/source/hiscores.cc +++ b/crawl-ref/source/hiscores.cc @@ -423,8 +423,17 @@ UIHiscoresMenu::UIHiscoresMenu() _construct_hiscore_table(); m_root->add_child(move(title)); - m_root->add_child(m_description); - m_root->add_child(m_score_entries); + if (initial_focus) + { + m_root->add_child(m_description); + m_root->add_child(m_score_entries); + } + else + { + auto placeholder = formatted_string("No high sscores yet...", DARKGRAY); + m_root->add_child(make_shared(placeholder)); + initial_focus = this; + } } void UIHiscoresMenu::_construct_hiscore_table() From 643f6c6e1a8e2f26cc5f9b5c1214b034e9db03a9 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 7 Oct 2019 02:23:58 +0800 Subject: [PATCH 768/864] Fix main menus not handling app quit (Goratrix, 12080) --- crawl-ref/source/newgame.cc | 2 +- crawl-ref/source/startup.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 385d52460ad6..05ff394c8132 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -1587,7 +1587,7 @@ static void _prompt_choice(int choice_type, newgame_def& ng, newgame_def& ng_cho ui::push_layout(move(popup)); ui::set_focused_widget(newgame_ui.get()); - while (!newgame_ui->done) + while (!newgame_ui->done && !crawl_state.seen_hups) ui::pump_events(); ui::pop_layout(); diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index 6529f5f2858c..9c2759e5ae7d 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -922,7 +922,7 @@ static void _show_startup_menu(newgame_def& ng_choice, ui::run_layout(move(popup), startup_ui->done); - if (startup_ui->end_game) + if (startup_ui->end_game || crawl_state.seen_hups) { #ifdef USE_TILE_WEB tiles.send_exit_reason("cancel"); From bb1ff42f1e003f895a794363cefb98d6fea12cac Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 7 Oct 2019 03:37:01 +0800 Subject: [PATCH 769/864] Fix invalid read causing map-view crash (jackofblades, 12069) --- crawl-ref/source/tilecell.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crawl-ref/source/tilecell.cc b/crawl-ref/source/tilecell.cc index 169cb6677d48..c494c3a1033c 100644 --- a/crawl-ref/source/tilecell.cc +++ b/crawl-ref/source/tilecell.cc @@ -400,8 +400,12 @@ static void _pack_default_waves(const coord_def &gc, crawl_view_buffer& vbuf) // +7 and -- reverse the iteration order int tile = _base_wave_tile(colour) + 7; for (adjacent_iterator ai(gc); ai; ++ai, --tile) + { + if (ai->x < 0 || ai->x >= vbuf.size().x || ai->y < 0 || ai->y >= vbuf.size().y) + continue; if (_is_seen_shallow(*ai, vbuf)) _add_overlay(tile, cell); + } } bool north = _is_seen_land(coord_def(gc.x, gc.y - 1), vbuf); From 3be9bf80fb2e9c14ae8981a6e4702dffbaf7a825 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 7 Oct 2019 03:52:53 +0800 Subject: [PATCH 770/864] Add keybind to clear player name (kitchen_ace, 12084) Using backspace to clear is not the best choice because a) it's kind of weird for backspace to delete everything, and b) difficult to determine when to delete everything and when to delete just one letter. --- crawl-ref/source/startup.cc | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index 9c2759e5ae7d..0983ed544db2 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -783,7 +783,8 @@ void UIStartupMenu::on_show() layout->add_event_filter([this](wm_event ev) { if (ev.type != WME_KEYDOWN) return false; - int keyn = ev.key.keysym.sym; + const int keyn = ev.key.keysym.sym; + bool changed_name = false; if (key_is_escape(keyn) || keyn == CK_MOUSE_CMD) { @@ -805,10 +806,14 @@ void UIStartupMenu::on_show() replay_messages_during_startup(); return true; } + else if (keyn == CONTROL('U')) + { + input_string = ""; + changed_name = true; + } // handle the non-action keys by hand to poll input // Only consider alphanumeric keys and -_ . - bool changed_name = false; if (iswalnum(keyn) || keyn == '-' || keyn == '.' || keyn == '_' || keyn == ' ') { @@ -826,7 +831,8 @@ void UIStartupMenu::on_show() changed_name = true; } } - else + + if (!changed_name) return false; input_text->set_text(formatted_string(input_string, WHITE)); @@ -836,13 +842,10 @@ void UIStartupMenu::on_show() // We want enter to start a new game if no character // with the given name exists, or load the corresponding // game. - if (changed_name) - { - int i = _find_save(chars, input_string); - auto menu = i == -1 ? game_modes_menu : save_games_menu; - auto btn = menu->get_button(0, i == -1 ? 0 : i); - menu->scroll_button_into_view(btn); - } + int i = _find_save(chars, input_string); + auto menu = i == -1 ? game_modes_menu : save_games_menu; + auto btn = menu->get_button(0, i == -1 ? 0 : i); + menu->scroll_button_into_view(btn); return true; }); } From f26d6114a74a4836ae6db458d039bf2b1940515e Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 7 Oct 2019 05:05:29 +0800 Subject: [PATCH 771/864] Fix dungeon feature quotes not visible (Vaamat, 12032) --- crawl-ref/source/describe.cc | 26 ++++++++++++++----- .../webserver/game_data/static/style.css | 1 + .../webserver/game_data/static/ui-layouts.js | 7 ++++- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index 436d50b56436..53425d16704c 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -2261,7 +2261,7 @@ void get_feature_desc(const coord_def &pos, describe_info &inf, bool include_ext void describe_feature_wide(const coord_def& pos) { typedef struct { - string title, body; + string title, body, quote; tile_def tile; } feat_info; @@ -2270,7 +2270,7 @@ void describe_feature_wide(const coord_def& pos) { describe_info inf; get_feature_desc(pos, inf, false); - feat_info f = { "", "", tile_def(TILEG_TODO, TEX_GUI)}; + feat_info f = { "", "", "", tile_def(TILEG_TODO, TEX_GUI)}; f.title = inf.title; f.body = trimmed_string(inf.body.str()); #ifdef USE_TILE @@ -2278,12 +2278,13 @@ void describe_feature_wide(const coord_def& pos) apply_variations(env.tile_flv(pos), &tile, pos); f.tile = tile_def(tile, get_dngn_tex(tile)); #endif + f.quote = trimmed_string(inf.quote); feats.emplace_back(f); } auto extra_descs = _get_feature_extra_descs(pos); for (const auto &desc : extra_descs) { - feat_info f = { "", "", tile_def(TILEG_TODO, TEX_GUI)}; + feat_info f = { "", "", "", tile_def(TILEG_TODO, TEX_GUI)}; f.title = desc.first; f.body = trimmed_string(desc.second); #ifdef USE_TILE @@ -2303,7 +2304,7 @@ void describe_feature_wide(const coord_def& pos) string hint_text = trimmed_string(hints_describe_pos(pos.x, pos.y)); if (!hint_text.empty()) { - feat_info f = { "", "", tile_def(TILEG_TODO, TEX_GUI)}; + feat_info f = { "", "", "", tile_def(TILEG_TODO, TEX_GUI)}; f.title = "Hints."; f.body = hint_text; f.tile = tile_def(TILEG_STARTUP_HINTS, TEX_GUI); @@ -2328,7 +2329,8 @@ void describe_feature_wide(const coord_def& pos) title_hbox->add_child(move(title)); title_hbox->align_items = Widget::CENTER; - bool has_desc = feat.body != feat.title && feat.body != ""; + const bool has_desc = feat.body != feat.title && feat.body != ""; + if (has_desc || &feat != &feats.back()) { title_hbox->set_margin_for_crt({0, 0, 1, 0}); @@ -2338,9 +2340,18 @@ void describe_feature_wide(const coord_def& pos) if (has_desc) { - auto text = make_shared(formatted_string::parse_string(feat.body)); + formatted_string desc_text = formatted_string::parse_string(feat.body); + if (!feat.quote.empty()) + { + desc_text.cprintf("\n\n"); + desc_text += formatted_string::parse_string(feat.quote); + } + auto text = make_shared(desc_text); if (&feat != &feats.back()) + { text->set_margin_for_sdl({0, 0, 20, 0}); + text->set_margin_for_crt({0, 0, 1, 0}); + } text->wrap_text = true; vbox->add_child(text); } @@ -2367,7 +2378,8 @@ void describe_feature_wide(const coord_def& pos) { tiles.json_open_object(); tiles.json_write_string("title", feat.title); - tiles.json_write_string("body", feat.body); + tiles.json_write_string("body", trimmed_string(feat.body)); + tiles.json_write_string("quote", trimmed_string(feat.quote)); tiles.json_open_object("tile"); tiles.json_write_int("t", feat.tile.tile); tiles.json_write_int("tex", feat.tile.tex); diff --git a/crawl-ref/source/webserver/game_data/static/style.css b/crawl-ref/source/webserver/game_data/static/style.css index 9c5ccf33554e..1b224dcd7fc9 100644 --- a/crawl-ref/source/webserver/game_data/static/style.css +++ b/crawl-ref/source/webserver/game_data/static/style.css @@ -591,6 +591,7 @@ body { .describe-feature-feat > .body { margin-top: 15px; font-size: 0.9em; + white-space: pre-wrap; } .describe-item { diff --git a/crawl-ref/source/webserver/game_data/static/ui-layouts.js b/crawl-ref/source/webserver/game_data/static/ui-layouts.js index 0768ac077ce9..74e00a5b7bcb 100644 --- a/crawl-ref/source/webserver/game_data/static/ui-layouts.js +++ b/crawl-ref/source/webserver/game_data/static/ui-layouts.js @@ -134,7 +134,12 @@ function ($, comm, client, ui, enums, cr, util, scroller, main, gui, player) { var $feat = $feat_tmpl.clone().removeClass("hidden").addClass("describe-feature-feat"); $feat.find(".header > span").html(feat.title); if (feat.body != feat.title) - $feat.find(".body").html(feat.body); + { + var text = feat.body; + if (feat.quote) + text += "\n\n" + feat.quote; + $feat.find(".body").html(text); + } else $feat.find(".body").remove(); From b0425b2895e223f5fcb4d29784c25a1601defae5 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 3 Oct 2019 16:10:57 -0400 Subject: [PATCH 772/864] Remove an ifdef related to seed selection This never really worked right anyways, and gave errors on CPO --- crawl-ref/source/initfile.cc | 8 -------- 1 file changed, 8 deletions(-) diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index 728b4f2d2353..3bb7b92ba922 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -3441,13 +3441,6 @@ void game_options::read_option_line(const string &str, bool runscript) } else if (key == "game_seed") { -#ifdef DGAMELAUNCH - // try to avoid confusing online players who put this in their rc - // file. N.b. it is still possible to use the -seed CLO. - report_error("Your rc file specifies a game seed, but this build of " - "crawl does not support seed selection. I will " - "choose a seed randomly."); -#else // special handling because of the large type. uint64_t tmp_seed = 0; if (sscanf(field.c_str(), "%" SCNu64, &tmp_seed)) @@ -3457,7 +3450,6 @@ void game_options::read_option_line(const string &str, bool runscript) if (!seed_from_rc) seed_from_rc = tmp_seed; } -#endif } else if (key == "pregen_dungeon") { From 8ac54030cd558dd06d84f74a128ef2be078f65a5 Mon Sep 17 00:00:00 2001 From: advil Date: Sun, 6 Oct 2019 17:35:14 -0400 Subject: [PATCH 773/864] Add an explicit bounds check to crawl_view_buffer () This is what was crashing in #1166 / mantis 12069, but because it was triggered by an invalid memory access, whether there was a crash was very system/build-specific. This makes a similar out of bounds error explicit in the future. --- crawl-ref/source/viewgeom.h | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/source/viewgeom.h b/crawl-ref/source/viewgeom.h index 2fb0ad854eab..a9b141b9e252 100644 --- a/crawl-ref/source/viewgeom.h +++ b/crawl-ref/source/viewgeom.h @@ -30,6 +30,7 @@ class crawl_view_buffer template screen_cell_t& operator () (const Indexer &i) { + ASSERT(i.x >= 0 && i.y >= 0 && i.x < m_size.x && i.y < m_size.y); return m_buffer[i.y*m_size.x + i.x]; } From 30414c0b45929f4660c08271024862c59e77f5b8 Mon Sep 17 00:00:00 2001 From: "S. Mark" Date: Sun, 6 Oct 2019 17:49:23 -0400 Subject: [PATCH 774/864] Fix typo. --- crawl-ref/source/hiscores.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/hiscores.cc b/crawl-ref/source/hiscores.cc index a5c30fe101de..b8d544a8d415 100644 --- a/crawl-ref/source/hiscores.cc +++ b/crawl-ref/source/hiscores.cc @@ -430,7 +430,7 @@ UIHiscoresMenu::UIHiscoresMenu() } else { - auto placeholder = formatted_string("No high sscores yet...", DARKGRAY); + auto placeholder = formatted_string("No high scores yet...", DARKGRAY); m_root->add_child(make_shared(placeholder)); initial_focus = this; } From 74da537585e1764b12bd2122af22aea03c003cc2 Mon Sep 17 00:00:00 2001 From: "S. Mark" Date: Sun, 6 Oct 2019 17:51:03 -0400 Subject: [PATCH 775/864] Update mailmap. [skip ci] --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index 5cdf0f857a52..23cc5d25e731 100644 --- a/.mailmap +++ b/.mailmap @@ -62,6 +62,7 @@ Sage Sage gammafunk wheals +wheals reaverb reaverb N78291 From 36f0aeb8430749ccd43896d40b76231713a0a36b Mon Sep 17 00:00:00 2001 From: theJollySin Date: Sat, 5 Oct 2019 19:56:05 -0400 Subject: [PATCH 776/864] Remove ill-fitting confusion text (1583) This visual doesn't work for monsters with 0 or 1 eyes [skip ci] --- crawl-ref/source/dat/database/monspeak.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/crawl-ref/source/dat/database/monspeak.txt b/crawl-ref/source/dat/database/monspeak.txt index 65472c2794f2..f1ba72545ff0 100644 --- a/crawl-ref/source/dat/database/monspeak.txt +++ b/crawl-ref/source/dat/database/monspeak.txt @@ -639,8 +639,6 @@ VISUAL:@The_monster@ ponders the situation. @The_monster@ says, "Why is everything spinning?" @The_monster@ screams, "I'll kill you anyway!" - -VISUAL:@The_monster@ covers @possessive@ eyes. %%%% _confused_humanoid_rare_ From 3fb7a4b9a410c897890856214360f7ba84568dfa Mon Sep 17 00:00:00 2001 From: John Stilley <1831479+theJollySin@users.noreply.github.com> Date: Mon, 7 Oct 2019 21:12:56 -0400 Subject: [PATCH 777/864] Improving redundant working on flight dangers (#1174) --- crawl-ref/source/dat/descript/status.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/dat/descript/status.txt b/crawl-ref/source/dat/descript/status.txt index 09604e473068..3bf61b8c7003 100644 --- a/crawl-ref/source/dat/descript/status.txt +++ b/crawl-ref/source/dat/descript/status.txt @@ -36,8 +36,8 @@ teleportation. Fly status You fly above the ground, and are able to cross water and lava or fight above -shallow water without penalties. Most types of flight will time out – be sure -you're not above deadly liquids when that happens! +shallow water without penalties. Most types of flight will time out – be +careful what you are above when that happens! %%%% Agi status From 048a31fd0b46c03123e7e19bc432d8f03200e565 Mon Sep 17 00:00:00 2001 From: John Stilley <1831479+theJollySin@users.noreply.github.com> Date: Mon, 7 Oct 2019 21:15:48 -0400 Subject: [PATCH 778/864] Put an oklob in the tile for Fedhas's oklob ability (#1173) --- .../gui/invocations/fedhas_grow_oklob.png | Bin 364 -> 416 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/crawl-ref/source/rltiles/gui/invocations/fedhas_grow_oklob.png b/crawl-ref/source/rltiles/gui/invocations/fedhas_grow_oklob.png index ada89e16ec5dfd5a724e8fcaa548b2489cc46cdf..ecbf69e1bfac9d20549dc9c79b3cb42cf1eb6079 100644 GIT binary patch delta 375 zcmaFEw19bnge(g)0|P^2NcwRgr4`^4;;O*v3uN+`3dy92Otg@zS2%aN1t`E+666=m z;PC858ivL>4nJa0`PlBg3pY5H=O_QzZt4C-db>aW-V zh2DF*IEHAPZ@qM|>#%|V+XEX1ec|2g2fLN4HNFTvzj9md%Y|sJ-wD}Xe3f&)sQn1A zj>=uYVpT7YWLNJxr{u2R(y)z(xVHAmKg>2S^vG;Z{rQ@Y;qL+YD29)})tilYm^-~Q zE=W%>iP&k@z|P@pb$EuOlaz$Ry=*6*ivo8a6kRJlDcid=RN(NBJIYZij*hL{RxaY1 zwJ?vXsl(*FjqrqnK{GQGPRufrhRh7F`~~ z&u0ASd&w;SjVgQgf8D8hxzg6k{8=_{m%ftiHnW!R`)b;5R(^l|v#@&qA^X!tfmyNf SB6ESBXYh3Ob6Mw<&;$ULXN)EQ delta 349 zcmV-j0iyn(1MC8j7=H)@0000)q>9D>001peOjJbx0000001Pz}9A*?C1x+w8FhD>+ zMF)9ciVkxPqL7e~w#iMyFyq9;#N2K4!bdi+00001bW%=J06^y0W&i*H?MXyIRCwBr zkP8ljFbqS7(@%h|_do8OFw~a9v?rvh%bOi|{mFY~8--;e-hTcx0MMQTuENZzX_;{y5m#5+)fPyP~!0urfE8urni4s#V zCY+sOQ^4dwXjX`vGFnB0{VMG`C0M+wt$Z(dx+sKVFT@m6Iwc5O%v+*iJ2+d{BJIzl v7gUZf{v?R_OVYrdFft3tHaec~N#QR(NOBBaImqA(00000NkvXXu0mjf8f1}J From 92173c342a76eed1107d9a736aa48f164aff612e Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 7 Oct 2019 20:59:35 +0800 Subject: [PATCH 779/864] Add tile for sprint monster spell --- crawl-ref/source/rltiles/dc-spells.txt | 1 + .../source/rltiles/gui/spells/monster/sprint.png | Bin 0 -> 2936 bytes crawl-ref/source/spl-data.h | 2 +- 3 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 crawl-ref/source/rltiles/gui/spells/monster/sprint.png diff --git a/crawl-ref/source/rltiles/dc-spells.txt b/crawl-ref/source/rltiles/dc-spells.txt index 1b816f747581..4911525e1533 100644 --- a/crawl-ref/source/rltiles/dc-spells.txt +++ b/crawl-ref/source/rltiles/dc-spells.txt @@ -203,6 +203,7 @@ sleep SLEEP spectral_cloud SPECTRAL_CLOUD spit_acid SPIT_ACID spit_poison SPIT_POISON +sprint SPRINT steam_ball STEAM_BALL sticky_flame_range STICKY_FLAME_RANGE summon_drakes SUMMON_DRAKES diff --git a/crawl-ref/source/rltiles/gui/spells/monster/sprint.png b/crawl-ref/source/rltiles/gui/spells/monster/sprint.png new file mode 100644 index 0000000000000000000000000000000000000000..f534a185167fda7497ec31c7c658f04c1b8f2ca7 GIT binary patch literal 2936 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 Date: Tue, 8 Oct 2019 14:00:12 +0800 Subject: [PATCH 780/864] Fix grow oklob tile colour space reduction Unfortunately the previous iteration of the grow oklob ability tile had been saved with an unintentionally reduced colour set, due to the PNG being in indexed mode. --- .../gui/invocations/fedhas_grow_oklob.png | Bin 416 -> 3618 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/crawl-ref/source/rltiles/gui/invocations/fedhas_grow_oklob.png b/crawl-ref/source/rltiles/gui/invocations/fedhas_grow_oklob.png index ecbf69e1bfac9d20549dc9c79b3cb42cf1eb6079..895be9f5d9ad48afadd11c432a56b51ce231b9fe 100644 GIT binary patch literal 3618 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 From 601f8f6d224221fc0d96621164ce067c169f8c4f Mon Sep 17 00:00:00 2001 From: kitchen-ace <68k@quikphix.org> Date: Tue, 8 Oct 2019 07:22:39 -0400 Subject: [PATCH 781/864] Use felid blade hands tile with mons:natasha If the player has tile_player_tile = mons:natasha, show the felid version of blade hands. It's still not perfect (and doesn't match with many of the other felid tiles) but looks much better than the human blade hands tile. --- crawl-ref/source/tiledoll.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/tiledoll.cc b/crawl-ref/source/tiledoll.cc index 7eed413223c0..25516d2451a3 100644 --- a/crawl-ref/source/tiledoll.cc +++ b/crawl-ref/source/tiledoll.cc @@ -354,7 +354,8 @@ void fill_doll_equipment(dolls_data &result) { if (is_player_tile(result.parts[TILEP_PART_BASE], TILEP_BASE_OCTOPODE)) result.parts[TILEP_PART_HAND1] = TILEP_HAND1_BLADEHAND_OP; - else if (is_player_tile(result.parts[TILEP_PART_BASE], TILEP_BASE_FELID)) + else if (is_player_tile(result.parts[TILEP_PART_BASE], TILEP_BASE_FELID) + || Options.tile_use_monster == MONS_NATASHA) result.parts[TILEP_PART_HAND1] = TILEP_HAND1_BLADEHAND_FE; else result.parts[TILEP_PART_HAND1] = TILEP_HAND1_BLADEHAND; } @@ -371,7 +372,8 @@ void fill_doll_equipment(dolls_data &result) { if (is_player_tile(result.parts[TILEP_PART_BASE], TILEP_BASE_OCTOPODE)) result.parts[TILEP_PART_HAND2] = TILEP_HAND1_BLADEHAND_OP; - else if (is_player_tile(result.parts[TILEP_PART_BASE], TILEP_BASE_FELID)) + else if (is_player_tile(result.parts[TILEP_PART_BASE], TILEP_BASE_FELID) + || Options.tile_use_monster == MONS_NATASHA) result.parts[TILEP_PART_HAND2] = TILEP_HAND1_BLADEHAND_FE; else result.parts[TILEP_PART_HAND2] = TILEP_HAND1_BLADEHAND; } From 4d0d9f21365808d595b9f7b7c244fc548cb9981b Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Tue, 8 Oct 2019 22:17:46 -0400 Subject: [PATCH 782/864] Give monsters the player airstrike damage formula Commit a0cb8612 simplified airstrike damage for players; monster airstrike damage was previously a hack that gave a simplified damage formula and also reduced variance to work around the old formula's long tail. The new airstrike damage formula does not have the high-variance long tail and is appropriate for monsters to use. --- crawl-ref/source/mon-cast.cc | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/crawl-ref/source/mon-cast.cc b/crawl-ref/source/mon-cast.cc index 6e5e259bd0f9..8ab9e0d053a1 100644 --- a/crawl-ref/source/mon-cast.cc +++ b/crawl-ref/source/mon-cast.cc @@ -5801,7 +5801,6 @@ void mons_cast(monster* mons, bolt pbolt, spell_type spell_cast, case SPELL_AIRSTRIKE: { - // Damage averages 14 for 5HD, 18 for 10HD, 28 for 20HD, +50% if flying. if (foe->is_player()) { if (you.airborne()) @@ -5817,12 +5816,10 @@ void mons_cast(monster* mons, bolt pbolt, spell_type spell_cast, pbolt.flavour = BEAM_AIR; - int damage_taken = 10 + 2 * mons->get_hit_dice(); + int damage_taken = 8 + random2(2 + div_rand_round(splpow, 7)); damage_taken = foe->beam_resists(pbolt, damage_taken, false); - // Previous method of damage calculation (in line with player - // airstrike) had absurd variance. - damage_taken = foe->apply_ac(random2avg(damage_taken, 3)); + damage_taken = foe->apply_ac(damage_taken); foe->hurt(mons, damage_taken, BEAM_MISSILE, KILLED_BY_BEAM, "", "by the air"); return; From aa6b62e8fba2dcd85857461615a66f7ce1111ed5 Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Tue, 8 Oct 2019 22:27:54 -0400 Subject: [PATCH 783/864] Add attack strength punctuation to waterstrike and airstrike These (and everything else in mon-cast.cc that does damage in mon-cast.cc instead of via beam.cc) were missed when attack strength punctuation was added to spells. --- crawl-ref/source/mon-cast.cc | 40 +++++++++++++++++------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/crawl-ref/source/mon-cast.cc b/crawl-ref/source/mon-cast.cc index 8ab9e0d053a1..3001b6dfce7a 100644 --- a/crawl-ref/source/mon-cast.cc +++ b/crawl-ref/source/mon-cast.cc @@ -14,6 +14,7 @@ #include "act-iter.h" #include "areas.h" +#include "attack.h" #include "bloodspatter.h" #include "branch.h" #include "cleansing-flame-source-type.h" @@ -5780,20 +5781,20 @@ void mons_cast(monster* mons, bolt pbolt, spell_type spell_cast, case SPELL_WATERSTRIKE: { - if (you.can_see(*foe)) - { - if (foe->airborne()) - mprf("The water rises up and strikes %s!", foe->name(DESC_THE).c_str()); - else - mprf("The water swirls and strikes %s!", foe->name(DESC_THE).c_str()); - } - pbolt.flavour = BEAM_WATER; int damage_taken = waterstrike_damage(*mons).roll(); damage_taken = foe->beam_resists(pbolt, damage_taken, false); damage_taken = foe->apply_ac(damage_taken); + if (you.can_see(*foe)) + { + mprf("The water %s and strikes %s%s", + foe->airborne() ? "rises up" : "swirls", + foe->name(DESC_THE).c_str(), + attack_strength_punctuation(damage_taken).c_str()); + } + foe->hurt(mons, damage_taken, BEAM_MISSILE, KILLED_BY_BEAM, "", "by the raging water"); return; @@ -5801,25 +5802,22 @@ void mons_cast(monster* mons, bolt pbolt, spell_type spell_cast, case SPELL_AIRSTRIKE: { - if (foe->is_player()) - { - if (you.airborne()) - mpr("The air twists around and violently strikes you in flight!"); - else - mpr("The air twists around and strikes you!"); - } - else - { - simple_monster_message(*foe->as_monster(), - " is struck by the twisting air!"); - } - pbolt.flavour = BEAM_AIR; int damage_taken = 8 + random2(2 + div_rand_round(splpow, 7)); damage_taken = foe->beam_resists(pbolt, damage_taken, false); damage_taken = foe->apply_ac(damage_taken); + + if (you.can_see(*foe)) + { + mprf("The air twists around and %sstrikes %s%s%s", + foe->airborne() ? "violently " : "", + foe->name(DESC_THE).c_str(), + foe->airborne() ? " in flight" : "", + attack_strength_punctuation(damage_taken).c_str()); + } + foe->hurt(mons, damage_taken, BEAM_MISSILE, KILLED_BY_BEAM, "", "by the air"); return; From 06d714f949a5eb164380b737ef74258be2e5ae6c Mon Sep 17 00:00:00 2001 From: "Edgar A. Bering IV" Date: Tue, 8 Oct 2019 22:51:48 -0400 Subject: [PATCH 784/864] Add new airstrike formula to monster (minmay) --- crawl-ref/source/util/monster/monster-main.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/util/monster/monster-main.cc b/crawl-ref/source/util/monster/monster-main.cc index 1b246386f164..c58cb3d159f7 100644 --- a/crawl-ref/source/util/monster/monster-main.cc +++ b/crawl-ref/source/util/monster/monster-main.cc @@ -287,7 +287,8 @@ static string mi_calc_smiting_damage(monster* mons) { return "7-17"; } static string mi_calc_airstrike_damage(monster* mons) { - return make_stringf("0-%d", 10 + 2 * mons->get_experience_level()); + int pow = 12 * mons->get_experience_level(); + return make_stringf("8-%d", 2 + ( 6 + pow ) / 7); } static string mi_calc_glaciate_damage(monster* mons) From 2b6660483afe974111885e8e479be8f16076e109 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Wed, 9 Oct 2019 01:10:18 -0500 Subject: [PATCH 785/864] Fix use of Slimify on derived undead (CanOfWorms) The monster polymorph code had a special consideration (i.e. a hack) for derived undead that have the shapeshifter enchantment. This hack involved having the polymorph target check look at the monster type of the original type the undead monster derived from instead of the current type. A byproduct of this hack was that derived undead that got Slimified wouldn't polymorph into a death ooze yet would be converted to a neutral monster. Derived undead with the shapeshifter enchant shouldn't exist since undead are not normally able to polymorph. Hence this commit removes the hack to allow Slimify to work properly. Any derived undead that attempts to shift simply generate the "...looks momentarily different" message. --- crawl-ref/source/mon-poly.cc | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/crawl-ref/source/mon-poly.cc b/crawl-ref/source/mon-poly.cc index c019f1629896..d07f5523d468 100644 --- a/crawl-ref/source/mon-poly.cc +++ b/crawl-ref/source/mon-poly.cc @@ -103,13 +103,6 @@ void monster_drop_things(monster* mons, static bool _valid_morph(monster* mons, monster_type new_mclass) { - const dungeon_feature_type current_tile = grd(mons->pos()); - - monster_type old_mclass = mons->type; - if (mons_class_is_zombified(old_mclass)) - old_mclass = mons->base_monster; - // don't force spectral shapeshifters to become natural|undead mons only - // Shapeshifters cannot polymorph into glowing shapeshifters or // vice versa. if ((new_mclass == MONS_GLOWING_SHAPESHIFTER @@ -130,7 +123,7 @@ static bool _valid_morph(monster* mons, monster_type new_mclass) } // Various inappropriate polymorph targets. - if ( !(mons_class_holiness(new_mclass) & mons_class_holiness(old_mclass)) + if ( !(mons_class_holiness(new_mclass) & mons_class_holiness(mons->type)) // normally holiness just needs to overlap, but we don't want // shapeshifters to become demons || mons->is_shapeshifter() && !(mons_class_holiness(new_mclass) & MH_NATURAL) @@ -145,7 +138,7 @@ static bool _valid_morph(monster* mons, monster_type new_mclass) // 'morph targets are _always_ "base" classes, not derived ones. || new_mclass != mons_species(new_mclass) - || new_mclass == mons_species(old_mclass) + || new_mclass == mons_species(mons->type) // They act as separate polymorph classes on their own. || mons_class_is_zombified(new_mclass) @@ -167,7 +160,7 @@ static bool _valid_morph(monster* mons, monster_type new_mclass) } // Determine if the monster is happy on current tile. - return monster_habitable_grid(new_mclass, current_tile); + return monster_habitable_grid(new_mclass, grd(mons->pos())); } static bool _is_poly_power_unsuitable(poly_power_type power, From 35933f458584900b923160a3eefd11ac3cdde9a5 Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 9 Oct 2019 10:58:42 -0400 Subject: [PATCH 786/864] Don't let overgrow target out of bounds This directly provides bounds information, but that is the same as the dig and passwall targeters. The alternative (to avoid a crash) would be letting the targeter work, but the spell fail, which seems worse. --- crawl-ref/source/target.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crawl-ref/source/target.cc b/crawl-ref/source/target.cc index 470e2cedc0fc..aed12a20b8fd 100644 --- a/crawl-ref/source/target.cc +++ b/crawl-ref/source/target.cc @@ -1613,6 +1613,8 @@ targeter_overgrow::targeter_overgrow() bool targeter_overgrow::overgrow_affects_pos(const coord_def &p) { + if (!in_bounds(p)) + return false; if (env.markers.property_at(p, MAT_ANY, "veto_shatter") == "veto") return false; From 2df86a587e0e5113ec3dc765c137d719f9a10980 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Tue, 8 Oct 2019 20:55:50 +0800 Subject: [PATCH 787/864] Add widget visibility Non-visible widgets don't get rendered or allocated and have a size request of zero. --- crawl-ref/source/menu.cc | 59 +++++++++------------------------------- crawl-ref/source/ui.cc | 17 +++++++++++- crawl-ref/source/ui.h | 4 +++ 3 files changed, 33 insertions(+), 47 deletions(-) diff --git a/crawl-ref/source/menu.cc b/crawl-ref/source/menu.cc index e88cc8234e81..c49b9c63a739 100644 --- a/crawl-ref/source/menu.cc +++ b/crawl-ref/source/menu.cc @@ -100,7 +100,7 @@ class UIMenu : public Widget void update_item(int index); void update_items(); - void get_visible_item_range(int *vis_min, int *vis_max); + void is_visible_item_range(int *vis_min, int *vis_max); void get_item_region(int index, int *y1, int *y2); #ifndef USE_TILE_LOCAL @@ -174,7 +174,7 @@ void UIMenu::update_items() #endif } -void UIMenu::get_visible_item_range(int *vis_min, int *vis_max) +void UIMenu::is_visible_item_range(int *vis_min, int *vis_max) { const int viewport_height = m_menu->m_ui.scroller->get_region()[3]; const int scroll = m_menu->m_ui.scroller->get_scroll(); @@ -395,7 +395,7 @@ void UIMenu::_render() #else int vis_min, vis_max; - get_visible_item_range(&vis_min, &vis_max); + is_visible_item_range(&vis_min, &vis_max); const int scroll = m_menu->m_ui.scroller->get_scroll(); for (int i = vis_min; i < vis_max; i++) @@ -470,37 +470,6 @@ class UIMenuMore : public Text }; }; -class UIShowHide : public Bin -{ -public: - UIShowHide() : Bin() {}; - virtual ~UIShowHide() {}; - virtual SizeReq _get_preferred_size(Direction dim, int prosp_width) override - { - if (!m_visible) - return { 0, 0 }; - return m_child->get_preferred_size(dim, prosp_width); - } - virtual void _allocate_region() override - { - if (m_visible) - m_child->allocate_region(m_region); - } - virtual void _render() override - { - if (m_visible) - m_child->render(); - } - bool get_visible() const { return m_visible; } - void set_visible(bool visible) - { - m_visible = visible; - _invalidate_sizereq(); - } -protected: - bool m_visible = false; -}; - class UIMenuPopup : public ui::Popup { public: @@ -527,7 +496,7 @@ void UIMenuPopup::_allocate_region() m_menu->m_ui.menu->do_layout(menu_w, 1); int m_height = m_menu->m_ui.menu->m_height; - int more_height = m_menu->m_ui.more_bin->get_region()[3]; + int more_height = m_menu->m_ui.more->get_region()[3]; // switch number of columns int num_cols = m_menu->m_ui.menu->get_num_columns(); if (m_menu->m_ui.menu->m_draw_tiles && m_menu->is_set(MF_USE_TWO_COLUMNS) @@ -551,17 +520,17 @@ void UIMenuPopup::_allocate_region() && !m_menu->m_ui.more->get_text().ops.empty(); if (can_toggle_more) { - bool more_visible = m_menu->m_ui.more_bin->get_visible(); + bool more_visible = m_menu->m_ui.more->is_visible(); if (more_visible ? menu_height <= max_height : menu_height > max_height) { - m_menu->m_ui.more_bin->set_visible(!more_visible); + m_menu->m_ui.more->set_visible(!more_visible); _invalidate_sizereq(); - m_menu->m_ui.more_bin->_queue_allocation(); + m_menu->m_ui.more->_queue_allocation(); throw RestartAllocation(); } } - if (m_menu->m_keyhelp_more && m_menu->m_ui.more_bin->get_visible()) + if (m_menu->m_keyhelp_more && m_menu->m_ui.more->is_visible()) { int scroll = m_menu->m_ui.scroller->get_scroll(); int scroll_percent = scroll*100/(menu_height-viewport_height); @@ -608,7 +577,7 @@ void UIMenu::update_hovered_entry() const int x = m_mouse_x - m_region[0], y = m_mouse_y - m_region[1]; int vis_min, vis_max; - get_visible_item_range(&vis_min, &vis_max); + is_visible_item_range(&vis_min, &vis_max); for (int i = vis_min; i < vis_max; ++i) { @@ -727,7 +696,7 @@ void UIMenu::pack_buffers() const int col_width = m_region[2] / m_num_columns; int vis_min, vis_max; - get_visible_item_range(&vis_min, &vis_max); + is_visible_item_range(&vis_min, &vis_max); for (int i = vis_min; i < vis_max; ++i) { @@ -828,7 +797,6 @@ Menu::Menu(int _flags, const string& tagname, KeymapContext kmc) m_ui.scroller = make_shared(); m_ui.title = make_shared(); m_ui.more = make_shared(); - m_ui.more_bin = make_shared(); m_ui.vbox = make_shared(Widget::VERT); m_ui.vbox->align_items = Widget::STRETCH; @@ -844,8 +812,7 @@ Menu::Menu(int _flags, const string& tagname, KeymapContext kmc) scroller_wrap->add_child(m_ui.scroller); m_ui.vbox->add_child(scroller_wrap); #endif - m_ui.vbox->add_child(m_ui.more_bin); - m_ui.more_bin->set_child(m_ui.more); + m_ui.vbox->add_child(m_ui.more); m_ui.scroller->set_child(m_ui.menu); set_flags(flags); @@ -1030,7 +997,7 @@ void Menu::do_menu() return false; }; m_ui.title->on(Widget::slots.event, menu_wrap_click); - m_ui.more_bin->on(Widget::slots.event, menu_wrap_click); + m_ui.more->on(Widget::slots.event, menu_wrap_click); #endif update_menu(); @@ -1914,7 +1881,7 @@ void Menu::update_more() #ifdef USE_TILE_LOCAL show_more = show_more && !m_keyhelp_more; #endif - m_ui.more_bin->set_visible(show_more); + m_ui.more->set_visible(show_more); #ifdef USE_TILE_WEB if (!alive) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index cc6bc1dc69d2..34a505c76ec4 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -165,13 +165,17 @@ void Bin::set_child(shared_ptr child) void Widget::render() { - _render(); + if (m_visible) + _render(); } SizeReq Widget::get_preferred_size(Direction dim, int prosp_width) { ASSERT((dim == HORZ) == (prosp_width == -1)); + if (!m_visible) + return { 0, 0 }; + if (cached_sr_valid[dim] && (!dim || cached_sr_pw == prosp_width)) return cached_sr[dim]; @@ -212,6 +216,9 @@ SizeReq Widget::get_preferred_size(Direction dim, int prosp_width) void Widget::allocate_region(i4 region) { + if (!m_visible) + return; + i4 new_region = { region[0] + margin[3], region[1] + margin[0], @@ -290,6 +297,14 @@ void Widget::_expose() ui_root.expose_region(m_region); } +void Widget::set_visible(bool visible) +{ + if (m_visible == visible) + return; + m_visible = visible; + _invalidate_sizereq(); +} + void Box::add_child(shared_ptr child) { child->_set_parent(this); diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index ed2b29130ec9..47c984da3fbd 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -125,6 +125,9 @@ class Widget : public enable_shared_from_this void set_allocation_needed() { alloc_queued = true; }; void _expose(); + bool is_visible() const { return m_visible; } + void set_visible(bool); + // Wrapper functions which handle common behavior // - margins // - caching @@ -171,6 +174,7 @@ class Widget : public enable_shared_from_this SizeReq cached_sr[2]; int cached_sr_pw; bool alloc_queued = false; + bool m_visible = true; Widget* m_parent = nullptr; i2 m_min_size = { 0, 0 }, m_max_size = { INT_MAX, INT_MAX }; }; From 5029d81fa4387dc3a30654219042763be9064a64 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Tue, 8 Oct 2019 22:10:53 +0800 Subject: [PATCH 788/864] Add ui::Size helper class --- crawl-ref/source/command.cc | 2 +- crawl-ref/source/decks.cc | 2 +- crawl-ref/source/describe-god.cc | 2 +- crawl-ref/source/describe.cc | 10 ++++---- crawl-ref/source/hints.cc | 4 ++-- crawl-ref/source/loading-screen.cc | 2 +- crawl-ref/source/menu.cc | 8 +++---- crawl-ref/source/mutation.cc | 2 +- crawl-ref/source/newgame.cc | 4 ++-- crawl-ref/source/scroller.cc | 2 +- crawl-ref/source/spl-book.cc | 2 +- crawl-ref/source/startup.cc | 16 ++++++------- crawl-ref/source/ui.cc | 27 +++++++++++----------- crawl-ref/source/ui.h | 37 +++++++++++++++++++++++++----- 14 files changed, 73 insertions(+), 47 deletions(-) diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc index 69e5008e8e7d..65bc81646777 100644 --- a/crawl-ref/source/command.cc +++ b/crawl-ref/source/command.cc @@ -210,7 +210,7 @@ static void _print_version() auto vbox = make_shared(Widget::VERT); #ifdef USE_TILE_LOCAL - vbox->max_size()[0] = tiles.get_crt_font()->char_width()*80; + vbox->max_size().width = tiles.get_crt_font()->char_width()*80; #endif auto title_hbox = make_shared(Widget::HORZ); diff --git a/crawl-ref/source/decks.cc b/crawl-ref/source/decks.cc index 32f53396cd9f..76bc402233cc 100644 --- a/crawl-ref/source/decks.cc +++ b/crawl-ref/source/decks.cc @@ -431,7 +431,7 @@ static void _describe_cards(CrawlVector& cards) } #ifdef USE_TILE_LOCAL - vbox->max_size()[0] = tiles.get_crt_font()->char_width()*80; + vbox->max_size().width = tiles.get_crt_font()->char_width()*80; #endif scroller->set_child(move(vbox)); diff --git a/crawl-ref/source/describe-god.cc b/crawl-ref/source/describe-god.cc index 463bff701997..92f02389456f 100644 --- a/crawl-ref/source/describe-god.cc +++ b/crawl-ref/source/describe-god.cc @@ -1163,7 +1163,7 @@ static void build_partial_god_ui(god_type which_god, shared_ptr& popu desc_sw->set_margin_for_crt({1, 0, 1, 0}); desc_sw->expand_h = false; #ifdef USE_TILE_LOCAL - desc_sw->max_size()[0] = tiles.get_crt_font()->char_width()*80; + desc_sw->max_size().width = tiles.get_crt_font()->char_width()*80; #endif vbox->add_child(desc_sw); diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index 53425d16704c..62c2a0e05f2f 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -153,7 +153,7 @@ int show_description(const describe_info &inf, const tile_def *tile) switcher->current() = 0; switcher->expand_h = false; #ifdef USE_TILE_LOCAL - switcher->max_size()[0] = tiles.get_crt_font()->char_width()*80; + switcher->max_size().width = tiles.get_crt_font()->char_width()*80; #endif vbox->add_child(switcher); @@ -2357,7 +2357,7 @@ void describe_feature_wide(const coord_def& pos) } } #ifdef USE_TILE_LOCAL - vbox->max_size()[0] = tiles.get_crt_font()->char_width()*80; + vbox->max_size().width = tiles.get_crt_font()->char_width()*80; #endif scroller->set_child(move(vbox)); @@ -2729,7 +2729,7 @@ bool describe_item(item_def &item, function fixup_desc) } #ifdef USE_TILE_LOCAL - vbox->max_size()[0] = tiles.get_crt_font()->char_width()*80; + vbox->max_size().width = tiles.get_crt_font()->char_width()*80; #endif auto popup = make_shared(move(vbox)); @@ -3174,7 +3174,7 @@ void describe_spell(spell_type spell, const monster_info *mon_owner, auto vbox = make_shared(Widget::VERT); #ifdef USE_TILE_LOCAL - vbox->max_size()[0] = tiles.get_crt_font()->char_width()*80; + vbox->max_size().width = tiles.get_crt_font()->char_width()*80; #endif auto title_hbox = make_shared(Widget::HORZ); @@ -4610,7 +4610,7 @@ int describe_monsters(const monster_info &mi, bool force_seen, vbox->add_child(more_sw); #ifdef USE_TILE_LOCAL - vbox->max_size()[0] = tiles.get_crt_font()->char_width()*80; + vbox->max_size().width = tiles.get_crt_font()->char_width()*80; #endif auto popup = make_shared(move(vbox)); diff --git a/crawl-ref/source/hints.cc b/crawl-ref/source/hints.cc index 6f81727e6756..27f875bf4431 100644 --- a/crawl-ref/source/hints.cc +++ b/crawl-ref/source/hints.cc @@ -418,9 +418,9 @@ void hints_starting_screen() auto prompt_ui = make_shared(formatted_string::parse_string(text)); prompt_ui->wrap_text = true; #ifdef USE_TILE_LOCAL - prompt_ui->max_size()[0] = 800; + prompt_ui->max_size().width = 800; #else - prompt_ui->max_size()[0] = 80; + prompt_ui->max_size().width = 80; #endif bool done = false; diff --git a/crawl-ref/source/loading-screen.cc b/crawl-ref/source/loading-screen.cc index 28e511d3c545..463f2d471341 100644 --- a/crawl-ref/source/loading-screen.cc +++ b/crawl-ref/source/loading-screen.cc @@ -71,7 +71,7 @@ void loading_screen_open() vbox->add_child(move(splash)); vbox->add_child(loading_text); FontWrapper *font = tiles.get_crt_font(); - vbox->min_size()[0] = font->string_width(load_complete_msg.c_str()); + vbox->min_size().width = font->string_width(load_complete_msg.c_str()); popup = make_shared(move(vbox)); ui::push_layout(popup); } diff --git a/crawl-ref/source/menu.cc b/crawl-ref/source/menu.cc index c49b9c63a739..e1e011695b11 100644 --- a/crawl-ref/source/menu.cc +++ b/crawl-ref/source/menu.cc @@ -465,7 +465,7 @@ class UIMenuMore : public Text m_text.clear(); m_text += fs; _expose(); - m_wrapped_size = { -1, -1 }; + m_wrapped_size = Size(-1); wrap_text_to_size(m_region[2], m_region[3]); }; }; @@ -486,9 +486,9 @@ void UIMenuPopup::_allocate_region() { Popup::_allocate_region(); - int max_height = m_menu->m_ui.popup->get_max_child_size()[1]; + int max_height = m_menu->m_ui.popup->get_max_child_size().height; max_height -= m_menu->m_ui.title->get_region()[3]; - max_height -= m_menu->m_ui.title->margin[2]; + max_height -= m_menu->m_ui.title->get_margin()[2]; int viewport_height = m_menu->m_ui.scroller->get_region()[3]; #ifdef USE_TILE_LOCAL @@ -550,7 +550,7 @@ void UIMenuPopup::_allocate_region() #else const int max_viewport_height = 52; #endif - m_menu->m_ui.scroller->max_size() = { INT_MAX, max_viewport_height }; + m_menu->m_ui.scroller->max_size().height = max_viewport_height; if (max_viewport_height < viewport_height) { m_menu->m_ui.scroller->_invalidate_sizereq(); diff --git a/crawl-ref/source/mutation.cc b/crawl-ref/source/mutation.cc index 7d6556dcbcab..2471f1249e64 100644 --- a/crawl-ref/source/mutation.cc +++ b/crawl-ref/source/mutation.cc @@ -868,7 +868,7 @@ void display_mutations() switcher->set_margin_for_crt({1, 0, 0, 0}); switcher->expand_h = false; #ifdef USE_TILE_LOCAL - switcher->max_size()[0] = tiles.get_crt_font()->char_width()*80; + switcher->max_size().width = tiles.get_crt_font()->char_width()*80; #endif vbox->add_child(switcher); diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 05ff394c8132..62452e00a0f1 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -1722,9 +1722,9 @@ static void _construct_weapon_menu(const newgame_def& ng, // these dimensions are apparently unused for // webtiles, we do this so they're not interpreted // as characters for webtiles console. - { 0,0 }; + 0; #else - { TILE_Y, TILE_Y }; + TILE_Y; #endif } else diff --git a/crawl-ref/source/scroller.cc b/crawl-ref/source/scroller.cc index 9438ac580462..8289dd99f343 100644 --- a/crawl-ref/source/scroller.cc +++ b/crawl-ref/source/scroller.cc @@ -86,7 +86,7 @@ int formatted_scroller::show() #ifdef USE_TILE_LOCAL if (!(m_flags & FS_PREWRAPPED_TEXT)) - vbox->max_size()[0] = tiles.get_crt_font()->char_width()*80; + vbox->max_size().width = tiles.get_crt_font()->char_width()*80; #endif m_scroller = make_shared(*this); diff --git a/crawl-ref/source/spl-book.cc b/crawl-ref/source/spl-book.cc index b8f6a8e23ea8..a1ad18a948d7 100644 --- a/crawl-ref/source/spl-book.cc +++ b/crawl-ref/source/spl-book.cc @@ -805,7 +805,7 @@ class SpellLibraryMenu : public Menu #ifdef USE_TILE_LOCAL FontWrapper *font = tiles.get_crt_font(); int title_width = font->string_width(calc_title()); - m_ui.vbox->min_size() = {38 + title_width + 10, 0}; + m_ui.vbox->min_size().width = 38 + title_width + 10; #endif m_ui.scroller->expand_v = true; // TODO: doesn't work on webtiles diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index 0983ed544db2..9d4f2ed8ec39 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -438,7 +438,7 @@ static shared_ptr _make_newgame_button(shared_ptr& contai hbox->align_items = Widget::Align::CENTER; hbox->add_child(label); label->set_margin_for_sdl({0,0,0,TILE_Y+6}); - hbox->min_size() = { 0, TILE_Y }; + hbox->min_size().height = TILE_Y; #endif auto btn = make_shared(); @@ -473,9 +473,9 @@ static void _construct_save_games_menu(shared_ptr& container, auto label = make_shared(formatted_string(text, fg)); label->ellipsize = true; #ifdef USE_TILE_LOCAL - label->max_size() = { INT_MAX, (int)tiles.get_crt_font()->char_height() }; + label->max_size().height = tiles.get_crt_font()->char_height(); #else - label->max_size() = { INT_MAX, 1 }; + label->max_size().height = 1; #endif hbox->add_child(label); @@ -572,9 +572,9 @@ class UIStartupMenu : public Widget _construct_game_modes_menu(game_modes_menu); #ifdef USE_TILE_LOCAL - game_modes_menu->min_size() = { 0, TILE_Y*3 }; + game_modes_menu->min_size().height = TILE_Y*3; #else - game_modes_menu->min_size() = { 0, 2 }; + game_modes_menu->min_size().height = 2; #endif grid->add_child(move(mode_prompt), 0, 1); @@ -588,10 +588,10 @@ class UIStartupMenu : public Widget save_prompt->set_margin_for_sdl({0, 0, 10, 0}); save_games_menu->set_margin_for_sdl({0, 0, 10, 10}); #ifdef USE_TILE_LOCAL - save_prompt->min_size() = { 0, TILE_Y + 2 }; - save_games_menu->min_size() = { 0, TILE_Y * min(num_saves, 3) }; + save_prompt->min_size().height = TILE_Y + 2; + save_games_menu->min_size().height = TILE_Y * min(num_saves, 3); #else - save_games_menu->min_size() = { 0, 2 }; + save_games_menu->min_size().height = 2; #endif save_games_menu->descriptions = descriptions; diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 34a505c76ec4..26118772ad98 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -194,9 +194,12 @@ SizeReq Widget::get_preferred_size(Direction dim, int prosp_width) else if (shrink) ret.nat = ret.min; - ASSERT(m_min_size[dim] <= m_max_size[dim]); - ret.min = max(ret.min, m_min_size[dim]); - ret.nat = min(ret.nat, max(m_max_size[dim], ret.min)); + int& min_size = dim ? m_min_size.height : m_min_size.width; + int& max_size = dim ? m_max_size.height : m_max_size.width; + + ASSERT(min_size <= max_size); + ret.min = max(ret.min, min_size); + ret.nat = min(ret.nat, max(max_size, ret.min)); ret.nat = max(ret.nat, ret.min); ASSERT(ret.min <= ret.nat); @@ -483,7 +486,7 @@ void Text::set_text(const formatted_string &fs) m_text += fs; _invalidate_sizereq(); _expose(); - m_wrapped_size = { -1, -1 }; + m_wrapped_size = Size(-1); _queue_allocation(); } @@ -505,7 +508,7 @@ void Text::set_highlight_pattern(string pattern, bool line) void Text::wrap_text_to_size(int width, int height) { - i2 wrapped_size = { width, height }; + Size wrapped_size = { width, height }; if (m_wrapped_size == wrapped_size) return; m_wrapped_size = wrapped_size; @@ -1525,17 +1528,15 @@ void Popup::_allocate_region() m_child->allocate_region(region); } -i2 Popup::get_max_child_size() +Size Popup::get_max_child_size() { + Size max_child_size = Size(m_region[2], m_region[3]); #ifdef USE_TILE_LOCAL const int pad = base_margin() + m_padding; - return { - (m_region[2] - 2*pad) & ~0x1, - (m_region[3] - 2*pad - m_depth*m_depth_indent) & ~0x1, - }; -#else - return { m_region[2], m_region[3] }; + max_child_size.width = (max_child_size.width - 2*pad) & ~0x1; + max_child_size.height = (max_child_size.height - 2*pad - m_depth*m_depth_indent) & ~0x1; #endif + return max_child_size; } #ifdef USE_TILE_LOCAL @@ -1805,7 +1806,7 @@ void UIRoot::render() { const auto& hovered_widget = prev_hover_path.back(); i4 r = hovered_widget->get_region(); - i4 m = hovered_widget->margin; + i4 m = hovered_widget->get_margin(); VColour lc = VColour(0, 0, 100, 100); sb.add(r[0], r[1]-m[0], r[0]+r[2], r[1], lc); diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index 47c984da3fbd..fe20c9fa51ac 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -48,6 +48,26 @@ struct SizeReq int min, nat; }; +class Size +{ +public: + constexpr Size() : width(0), height(0) {}; + constexpr Size(int v) : width(v), height(v) {}; + constexpr Size(int w, int h) : width(w), height(h) {}; + + constexpr bool operator <= (const Size& other) const + { + return width <= other.width && height <= other.height; + } + + constexpr bool operator == (const Size& other) const + { + return width == other.width && height == other.height; + } + + int width, height; +}; + struct RestartAllocation {}; template class Slot; @@ -103,14 +123,13 @@ class Widget : public enable_shared_from_this virtual ~Widget(); - i4 margin = {0,0,0,0}; int flex_grow = 1; Align align_self = UNSET; bool expand_h = false, expand_v = false; bool shrink_h = false, shrink_v = false; const i4 get_region() const { return m_region; } - i2& min_size() { _invalidate_sizereq(); return m_min_size; } - i2& max_size() { _invalidate_sizereq(); return m_max_size; } + Size& min_size() { _invalidate_sizereq(); return m_min_size; } + Size& max_size() { _invalidate_sizereq(); return m_max_size; } virtual void _render() = 0; virtual SizeReq _get_preferred_size(Direction dim, int prosp_width); @@ -135,6 +154,9 @@ class Widget : public enable_shared_from_this SizeReq get_preferred_size(Direction dim, int prosp_width); void allocate_region(i4 region); + i4 get_margin() const { + return margin; + } void set_margin_for_crt(i4 _margin) { #ifndef USE_TILE_LOCAL @@ -166,6 +188,7 @@ class Widget : public enable_shared_from_this protected: i4 m_region; + i4 margin = {0, 0, 0, 0}; void _unparent(shared_ptr& child); @@ -176,7 +199,9 @@ class Widget : public enable_shared_from_this bool alloc_queued = false; bool m_visible = true; Widget* m_parent = nullptr; - i2 m_min_size = { 0, 0 }, m_max_size = { INT_MAX, INT_MAX }; + + Size m_min_size = { 0 }; + Size m_max_size = { INT_MAX }; }; class Container : public Widget @@ -363,7 +388,7 @@ class Text : public Widget vector m_wrapped_lines; COLOURS m_bg_colour = BLACK; #endif - i2 m_wrapped_size = { -1, -1 }; + Size m_wrapped_size = { -1 }; string hl_pat; bool hl_line; }; @@ -562,7 +587,7 @@ class Popup : public Layout virtual SizeReq _get_preferred_size(Direction dim, int prosp_width) override; virtual void _allocate_region() override; - i2 get_max_child_size(); + Size get_max_child_size(); protected: #ifdef USE_TILE_LOCAL From aeaa904cbbda02a47561807e2111e6021c74264d Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Tue, 8 Oct 2019 23:25:58 +0800 Subject: [PATCH 789/864] Add ui::Margin helper class This makes margin member accesses clearer, by allowing/forcing the use of symbolic names (top/left/etc) rather than array indices. Also adds several Margin() constructors, based on CSS notation; parameters are now forwarded by the set_margin_for_* helpers. Those helpers also now invalidate their size request, so updating margins live should also work. --- crawl-ref/source/command.cc | 7 ++-- crawl-ref/source/decks.cc | 7 ++-- crawl-ref/source/describe-god.cc | 7 ++-- crawl-ref/source/describe.cc | 54 +++++++++++++-------------- crawl-ref/source/end.cc | 6 +-- crawl-ref/source/hints.cc | 8 ++-- crawl-ref/source/hiscores.cc | 4 +- crawl-ref/source/loading-screen.cc | 2 +- crawl-ref/source/menu.cc | 10 ++--- crawl-ref/source/mutation.cc | 8 ++-- crawl-ref/source/newgame.cc | 60 +++++++++++++++--------------- crawl-ref/source/scroller.cc | 8 ++-- crawl-ref/source/startup.cc | 44 +++++++++++----------- crawl-ref/source/tilereg-doll.cc | 2 +- crawl-ref/source/ui.cc | 22 +++++------ crawl-ref/source/ui.h | 34 +++++++++++++---- 16 files changed, 147 insertions(+), 136 deletions(-) diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc index 65bc81646777..fa9eba3beebf 100644 --- a/crawl-ref/source/command.cc +++ b/crawl-ref/source/command.cc @@ -221,13 +221,12 @@ static void _print_version() #endif auto title = make_shared(formatted_string::parse_string(info)); - title->set_margin_for_crt({0, 0, 0, 0}); - title->set_margin_for_sdl({0, 0, 0, 10}); + title->set_margin_for_sdl(0, 0, 0, 10); title_hbox->add_child(move(title)); title_hbox->align_items = Widget::CENTER; - title_hbox->set_margin_for_crt({0, 0, 1, 0}); - title_hbox->set_margin_for_sdl({0, 0, 20, 0}); + title_hbox->set_margin_for_crt(0, 0, 1, 0); + title_hbox->set_margin_for_sdl(0, 0, 20, 0); vbox->add_child(move(title_hbox)); auto scroller = make_shared(); diff --git a/crawl-ref/source/decks.cc b/crawl-ref/source/decks.cc index 76bc402233cc..30877f3ac79f 100644 --- a/crawl-ref/source/decks.cc +++ b/crawl-ref/source/decks.cc @@ -409,12 +409,11 @@ static void _describe_cards(CrawlVector& cards) title_hbox->add_child(move(icon)); #endif auto title = make_shared(formatted_string(name, WHITE)); - title->set_margin_for_crt({0, 0, 0, 0}); - title->set_margin_for_sdl({0, 0, 0, 10}); + title->set_margin_for_sdl(0, 0, 0, 10); title_hbox->add_child(move(title)); title_hbox->align_items = Widget::CENTER; - title_hbox->set_margin_for_crt({first ? 0 : 1, 0, 1, 0}); - title_hbox->set_margin_for_sdl({first ? 0 : 20, 0, 20, 0}); + title_hbox->set_margin_for_crt(first ? 0 : 1, 0); + title_hbox->set_margin_for_sdl(first ? 0 : 20, 0); vbox->add_child(move(title_hbox)); auto text = make_shared(desc); diff --git a/crawl-ref/source/describe-god.cc b/crawl-ref/source/describe-god.cc index 92f02389456f..31f90ba8b247 100644 --- a/crawl-ref/source/describe-god.cc +++ b/crawl-ref/source/describe-god.cc @@ -1100,8 +1100,7 @@ static void build_partial_god_ui(god_type which_god, shared_ptr& popu #endif auto title = make_shared(topline.trim()); - title->set_margin_for_crt({0, 0, 0, 0}); - title->set_margin_for_sdl({0, 0, 0, 16}); + title->set_margin_for_sdl(0, 0, 0, 16); title_hbox->add_child(move(title)); title_hbox->align_items = Widget::CENTER; @@ -1159,8 +1158,8 @@ static void build_partial_god_ui(god_type which_god, shared_ptr& popu formatted_string::parse_string(mores[mores_index][i]))); } - desc_sw->set_margin_for_sdl({20, 0, 20, 0}); - desc_sw->set_margin_for_crt({1, 0, 1, 0}); + desc_sw->set_margin_for_sdl(20, 0); + desc_sw->set_margin_for_crt(1, 0); desc_sw->expand_h = false; #ifdef USE_TILE_LOCAL desc_sw->max_size().width = tiles.get_crt_font()->char_width()*80; diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index 62c2a0e05f2f..9605017a1548 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -118,7 +118,7 @@ int show_description(const describe_info &inf, const tile_def *tile) { auto icon = make_shared(); icon->set_tile(*tile); - icon->set_margin_for_sdl({0, 10, 0, 0}); + icon->set_margin_for_sdl(0, 10, 0, 0); title_hbox->add_child(move(icon)); } #endif @@ -127,8 +127,8 @@ int show_description(const describe_info &inf, const tile_def *tile) title_hbox->add_child(move(title)); title_hbox->align_items = Widget::CENTER; - title_hbox->set_margin_for_sdl({0, 0, 20, 0}); - title_hbox->set_margin_for_crt({0, 0, 1, 0}); + title_hbox->set_margin_for_sdl(0, 0, 20, 0); + title_hbox->set_margin_for_crt(0, 0, 1, 0); vbox->add_child(move(title_hbox)); } @@ -160,8 +160,8 @@ int show_description(const describe_info &inf, const tile_def *tile) if (!inf.quote.empty()) { auto footer = make_shared(_toggle_message); - footer->set_margin_for_sdl({20, 0, 0, 0}); - footer->set_margin_for_crt({1, 0, 0, 0}); + footer->set_margin_for_sdl(20, 0, 0, 0); + footer->set_margin_for_crt(1, 0, 0, 0); vbox->add_child(move(footer)); } @@ -2324,8 +2324,7 @@ void describe_feature_wide(const coord_def& pos) title_hbox->add_child(move(icon)); #endif auto title = make_shared(feat.title); - title->set_margin_for_crt({0, 0, 0, 0}); - title->set_margin_for_sdl({0, 0, 0, 10}); + title->set_margin_for_sdl(0, 0, 0, 10); title_hbox->add_child(move(title)); title_hbox->align_items = Widget::CENTER; @@ -2333,8 +2332,8 @@ void describe_feature_wide(const coord_def& pos) if (has_desc || &feat != &feats.back()) { - title_hbox->set_margin_for_crt({0, 0, 1, 0}); - title_hbox->set_margin_for_sdl({0, 0, 20, 0}); + title_hbox->set_margin_for_crt(0, 0, 1, 0); + title_hbox->set_margin_for_sdl(0, 0, 20, 0); } vbox->add_child(move(title_hbox)); @@ -2349,8 +2348,8 @@ void describe_feature_wide(const coord_def& pos) auto text = make_shared(desc_text); if (&feat != &feats.back()) { - text->set_margin_for_sdl({0, 0, 20, 0}); - text->set_margin_for_crt({0, 0, 1, 0}); + text->set_margin_for_sdl(0, 0, 20, 0); + text->set_margin_for_crt(0, 0, 1, 0); } text->wrap_text = true; vbox->add_child(text); @@ -2700,13 +2699,12 @@ bool describe_item(item_def &item, function fixup_desc) #endif auto title = make_shared(name); - title->set_margin_for_crt({0, 0, 0, 0}); - title->set_margin_for_sdl({0, 0, 0, 10}); + title->set_margin_for_sdl(0, 0, 0, 10); title_hbox->add_child(move(title)); title_hbox->align_items = Widget::CENTER; - title_hbox->set_margin_for_crt({0, 0, 1, 0}); - title_hbox->set_margin_for_sdl({0, 0, 20, 0}); + title_hbox->set_margin_for_crt(0, 0, 1, 0); + title_hbox->set_margin_for_sdl(0, 0, 20, 0); vbox->add_child(move(title_hbox)); auto scroller = make_shared(); @@ -2723,8 +2721,8 @@ bool describe_item(item_def &item, function fixup_desc) footer_text += formatted_string(_actions_desc(actions, item)); auto footer = make_shared(); footer->set_text(footer_text); - footer->set_margin_for_crt({1, 0, 0, 0}); - footer->set_margin_for_sdl({20, 0, 0, 0}); + footer->set_margin_for_crt(1, 0, 0, 0); + footer->set_margin_for_sdl(20, 0, 0, 0); vbox->add_child(move(footer)); } @@ -3189,13 +3187,12 @@ void describe_spell(spell_type spell, const monster_info *mon_owner, auto title = make_shared(); title->set_text(formatted_string(spl_title)); - title->set_margin_for_crt({0, 0, 0, 0}); - title->set_margin_for_sdl({0, 0, 0, 10}); + title->set_margin_for_sdl(0, 0, 0, 10); title_hbox->add_child(move(title)); title_hbox->align_items = Widget::CENTER; - title_hbox->set_margin_for_crt({0, 0, 1, 0}); - title_hbox->set_margin_for_sdl({0, 0, 20, 0}); + title_hbox->set_margin_for_crt(0, 0, 1, 0); + title_hbox->set_margin_for_sdl(0, 0, 20, 0); vbox->add_child(move(title_hbox)); auto scroller = make_shared(); @@ -3209,8 +3206,8 @@ void describe_spell(spell_type spell, const monster_info *mon_owner, { auto more = make_shared(); more->set_text(formatted_string("(M)emorise this spell.", CYAN)); - more->set_margin_for_crt({1, 0, 0, 0}); - more->set_margin_for_sdl({20, 0, 0, 0}); + more->set_margin_for_crt(1, 0, 0, 0); + more->set_margin_for_sdl(20, 0, 0, 0); vbox->add_child(move(more)); } @@ -4556,13 +4553,12 @@ int describe_monsters(const monster_info &mi, bool force_seen, auto title = make_shared(); title->set_text(formatted_string(inf.title)); - title->set_margin_for_crt({0, 0, 0, 0}); - title->set_margin_for_sdl({0, 0, 0, 10}); + title->set_margin_for_sdl(0, 0, 0, 10); title_hbox->add_child(move(title)); title_hbox->align_items = Widget::CENTER; - title_hbox->set_margin_for_crt({0, 0, 1, 0}); - title_hbox->set_margin_for_sdl({0, 0, 20, 0}); + title_hbox->set_margin_for_crt(0, 0, 1, 0); + title_hbox->set_margin_for_sdl(0, 0, 20, 0); vbox->add_child(move(title_hbox)); desc += formatted_string(inf.body.str()); @@ -4602,8 +4598,8 @@ int describe_monsters(const monster_info &mi, bool force_seen, formatted_string::parse_string(mores[i]))); } - more_sw->set_margin_for_sdl({20, 0, 0, 0}); - more_sw->set_margin_for_crt({1, 0, 0, 0}); + more_sw->set_margin_for_sdl(20, 0, 0, 0); + more_sw->set_margin_for_crt(1, 0, 0, 0); desc_sw->expand_h = false; vbox->add_child(desc_sw); if (!inf.quote.empty()) diff --git a/crawl-ref/source/end.cc b/crawl-ref/source/end.cc index d2b7b0ec06ea..ebda1db814c5 100644 --- a/crawl-ref/source/end.cc +++ b/crawl-ref/source/end.cc @@ -473,14 +473,14 @@ NORETURN void end_game(scorefile_entry &se) death_tile = tile_def(TILE_DNGN_GRAVESTONE+1, TEX_FEAT); auto tile = make_shared(death_tile); - tile->set_margin_for_sdl({0, 10, 0, 0}); + tile->set_margin_for_sdl(0, 10, 0, 0); title_hbox->add_child(move(tile)); #endif string goodbye_title = make_stringf("Goodbye, %s.", you.your_name.c_str()); title_hbox->add_child(make_shared(goodbye_title)); title_hbox->align_items = Widget::CENTER; - title_hbox->set_margin_for_sdl({0, 0, 20, 0}); - title_hbox->set_margin_for_crt({0, 0, 1, 0}); + title_hbox->set_margin_for_sdl(0, 0, 20, 0); + title_hbox->set_margin_for_crt(0, 0, 1, 0); auto vbox = make_shared(Box::VERT); vbox->add_child(move(title_hbox)); diff --git a/crawl-ref/source/hints.cc b/crawl-ref/source/hints.cc index 27f875bf4431..ae2c30224704 100644 --- a/crawl-ref/source/hints.cc +++ b/crawl-ref/source/hints.cc @@ -186,8 +186,8 @@ void pick_hints(newgame_def& choice) vbox->add_child(prompt_ui); auto main_items = make_shared(true, 1, 3); - main_items->set_margin_for_sdl({15, 0, 15, 0}); - main_items->set_margin_for_crt({1, 0, 1, 0}); + main_items->set_margin_for_sdl(15, 0); + main_items->set_margin_for_crt(1, 0); vbox->add_child(main_items); for (int i = 0; i < 3; i++) @@ -203,14 +203,14 @@ void pick_hints(newgame_def& choice) _fill_newgame_choice_for_hints(tng, static_cast(i)); fill_doll_for_newgame(doll, tng); auto tile = make_shared(doll); - tile->set_margin_for_sdl({0, 6, 0, 0}); + tile->set_margin_for_sdl(0, 6, 0, 0); hbox->add_child(move(tile)); hbox->add_child(label); #endif auto btn = make_shared(); #ifdef USE_TILE_LOCAL - hbox->set_margin_for_sdl({4,8,4,8}); + hbox->set_margin_for_sdl(4,8); btn->set_child(move(hbox)); #else btn->set_child(move(label)); diff --git a/crawl-ref/source/hiscores.cc b/crawl-ref/source/hiscores.cc index b8d544a8d415..170540303ccb 100644 --- a/crawl-ref/source/hiscores.cc +++ b/crawl-ref/source/hiscores.cc @@ -415,7 +415,7 @@ UIHiscoresMenu::UIHiscoresMenu() auto title = make_shared(formatted_string( "Dungeon Crawl Stone Soup: High Scores", YELLOW)); title->align_self = Widget::CENTER; - title->set_margin_for_sdl({0, 0, 20, 0}); + title->set_margin_for_sdl(0, 0, 20, 0); m_description = make_shared(string(9, '\n')); m_score_entries= make_shared(true, 1, 100); @@ -464,7 +464,7 @@ void UIHiscoresMenu::_add_hiscore_row(scorefile_entry& se, int id) tmp->set_text(formatted_string(hiscores_format_single(se))); auto btn = make_shared(); - tmp->set_margin_for_sdl({2,2,2,2}); + tmp->set_margin_for_sdl(2); btn->set_child(move(tmp)); btn->on(Widget::slots.event, [this, id, se](wm_event ev) { if (ev.type == WME_MOUSEBUTTONUP && ev.mouse_event.button == MouseEvent::LEFT diff --git a/crawl-ref/source/loading-screen.cc b/crawl-ref/source/loading-screen.cc index 463f2d471341..a04c944af029 100644 --- a/crawl-ref/source/loading-screen.cc +++ b/crawl-ref/source/loading-screen.cc @@ -65,7 +65,7 @@ void loading_screen_open() { auto splash = make_shared(_get_title_image()); loading_text = make_shared(); - loading_text->set_margin_for_sdl({15, 0, 0, 0}); + loading_text->set_margin_for_sdl(15, 0, 0, 0); auto vbox = make_shared(Widget::VERT); vbox->align_items = Widget::CENTER; vbox->add_child(move(splash)); diff --git a/crawl-ref/source/menu.cc b/crawl-ref/source/menu.cc index e1e011695b11..1fa18e25e84c 100644 --- a/crawl-ref/source/menu.cc +++ b/crawl-ref/source/menu.cc @@ -488,7 +488,7 @@ void UIMenuPopup::_allocate_region() int max_height = m_menu->m_ui.popup->get_max_child_size().height; max_height -= m_menu->m_ui.title->get_region()[3]; - max_height -= m_menu->m_ui.title->get_margin()[2]; + max_height -= m_menu->m_ui.title->get_margin().bottom; int viewport_height = m_menu->m_ui.scroller->get_region()[3]; #ifdef USE_TILE_LOCAL @@ -800,8 +800,8 @@ Menu::Menu(int _flags, const string& tagname, KeymapContext kmc) m_ui.vbox = make_shared(Widget::VERT); m_ui.vbox->align_items = Widget::STRETCH; - m_ui.title->set_margin_for_sdl({0, 0, 10, 0}); - m_ui.more->set_margin_for_sdl({10, 0, 0, 0}); + m_ui.title->set_margin_for_sdl(0, 0, 10, 0); + m_ui.more->set_margin_for_sdl(10, 0, 0, 0); m_ui.vbox->add_child(m_ui.title); #ifdef USE_TILE_LOCAL @@ -1949,8 +1949,8 @@ void Menu::update_title() } #ifdef USE_TILE_LOCAL - m_ui.title->set_margin_for_sdl({0, 0, 10, - UIMenu::item_pad + (m_indent_title ? 38 : 0)}); + m_ui.title->set_margin_for_sdl(0, 0, 10, + UIMenu::item_pad + (m_indent_title ? 38 : 0)); #endif m_ui.title->set_text(fs); #ifdef USE_TILE_WEB diff --git a/crawl-ref/source/mutation.cc b/crawl-ref/source/mutation.cc index 2471f1249e64..408041dbf312 100644 --- a/crawl-ref/source/mutation.cc +++ b/crawl-ref/source/mutation.cc @@ -864,8 +864,8 @@ void display_mutations() } switcher->current() = 0; - switcher->set_margin_for_sdl({20, 0, 0, 0}); - switcher->set_margin_for_crt({1, 0, 0, 0}); + switcher->set_margin_for_sdl(20, 0, 0, 0); + switcher->set_margin_for_crt(1, 0, 0, 0); switcher->expand_h = false; #ifdef USE_TILE_LOCAL switcher->max_size().width = tiles.get_crt_font()->char_width()*80; @@ -873,8 +873,8 @@ void display_mutations() vbox->add_child(switcher); auto bottom = make_shared(_vampire_Ascreen_footer(true)); - bottom->set_margin_for_sdl({20, 0, 0, 0}); - bottom->set_margin_for_crt({1, 0, 0, 0}); + bottom->set_margin_for_sdl(20, 0, 0, 0); + bottom->set_margin_for_crt(1, 0, 0, 0); if (you.species == SP_VAMPIRE) vbox->add_child(bottom); diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 62452e00a0f1..09b744622265 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -391,14 +391,14 @@ static bool _reroll_random(newgame_def& ng) fill_doll_for_newgame(doll, ng); #ifdef USE_TILE_LOCAL auto tile = make_shared(doll); - tile->set_margin_for_sdl({0, 10, 0, 0}); + tile->set_margin_for_sdl(0, 10, 0, 0); title_hbox->add_child(move(tile)); #endif #endif title_hbox->add_child(make_shared(prompt)); title_hbox->align_items = Widget::CENTER; - title_hbox->set_margin_for_sdl({0, 0, 20, 0}); - title_hbox->set_margin_for_crt({0, 0, 1, 0}); + title_hbox->set_margin_for_sdl(0, 0, 20, 0); + title_hbox->set_margin_for_crt(0, 0, 1, 0); auto vbox = make_shared(Box::VERT); vbox->add_child(move(title_hbox)); @@ -562,8 +562,8 @@ static void _add_menu_sub_item(shared_ptr& menu, int x, int y, const { auto tmp = make_shared(); tmp->set_text(formatted_string(text, BROWN)); - tmp->set_margin_for_sdl({4,8,4,8}); - tmp->set_margin_for_crt({0,2,0,0}); + tmp->set_margin_for_sdl(4,8); + tmp->set_margin_for_crt(0, 2, 0, 0); auto btn = make_shared(); btn->set_child(move(tmp)); @@ -619,14 +619,14 @@ static void _choose_name(newgame_def& ng, newgame_def& choice) fill_doll_for_newgame(doll, ng); #ifdef USE_TILE_LOCAL auto tile = make_shared(doll); - tile->set_margin_for_sdl({0, 10, 0, 0}); + tile->set_margin_for_sdl(0, 10, 0, 0); title_hbox->add_child(move(tile)); #endif #endif title_hbox->add_child(make_shared(title)); title_hbox->align_items = Widget::CENTER; - title_hbox->set_margin_for_sdl({0, 0, 20, 0}); - title_hbox->set_margin_for_crt({0, 0, 1, 0}); + title_hbox->set_margin_for_sdl(0, 0, 20, 0); + title_hbox->set_margin_for_crt(0, 0, 1, 0); auto vbox = make_shared(Box::VERT); vbox->add_child(move(title_hbox)); @@ -648,8 +648,8 @@ static void _choose_name(newgame_def& ng, newgame_def& choice) tmp->set_text(formatted_string("Enter - Begin!", BROWN)); auto btn = make_shared(); - tmp->set_margin_for_sdl({4,8,4,8}); - tmp->set_margin_for_crt({0,2,0,0}); + tmp->set_margin_for_sdl(4,8); + tmp->set_margin_for_crt(0, 2, 0, 0); btn->set_child(move(tmp)); btn->id = CK_ENTER; btn->description = ""; @@ -658,7 +658,7 @@ static void _choose_name(newgame_def& ng, newgame_def& choice) auto err = make_shared( formatted_string("That's a silly name!", LIGHTRED)); - err->set_margin_for_sdl({0,0,0,10}); + err->set_margin_for_sdl(0, 0, 0, 10); auto box = make_shared(Box::HORZ); box->align_items = Widget::CENTER; box->add_child(err); @@ -1089,8 +1089,8 @@ class UINewGameMenu : public Widget m_main_items = make_shared(true, 3, 20); m_main_items->menu_id = m_choice_type == C_JOB ? "background-main" : "species-main"; - m_main_items->set_margin_for_crt({1, 0, 1, 0}); - m_main_items->set_margin_for_sdl({15, 0, 15, 0}); + m_main_items->set_margin_for_crt(1, 0); + m_main_items->set_margin_for_sdl(15, 0); m_main_items->descriptions = descriptions; m_vbox->add_child(m_main_items); @@ -1099,8 +1099,8 @@ class UINewGameMenu : public Widget max_size() = { 80, INT_MAX }; #endif - descriptions->set_margin_for_crt({1, 0, 1, 0}); - descriptions->set_margin_for_sdl({0, 0, 15, 0}); + descriptions->set_margin_for_crt(1, 0); + descriptions->set_margin_for_sdl(0, 0, 15, 0); descriptions->current() = -1; descriptions->shrink_h = true; m_vbox->add_child(descriptions); @@ -1178,7 +1178,7 @@ class UINewGameMenu : public Widget hbox->justify_items = Widget::Align::STRETCH; auto tile = make_shared(); tile->set_tile(item_tile); - tile->set_margin_for_sdl({0, 6, 0, 0}); + tile->set_margin_for_sdl(0, 6, 0, 0); tile->flex_grow = 0; hbox->add_child(move(tile)); hbox->add_child(label); @@ -1213,7 +1213,7 @@ class UINewGameMenu : public Widget auto btn = make_shared(); #ifdef USE_TILE - hbox->set_margin_for_sdl({2,10,2,2}); + hbox->set_margin_for_sdl(2, 10, 2, 2); btn->set_child(move(hbox)); #else btn->set_child(move(label)); @@ -1222,7 +1222,7 @@ class UINewGameMenu : public Widget btn->description = desc; btn->hotkey = letter; btn->highlight_colour = hl; - btn->set_margin_for_crt({0,1,0,0}); + btn->set_margin_for_crt(0, 1, 0, 0); m_main_items->add_button(btn, position.x, position.y); @@ -1233,7 +1233,7 @@ class UINewGameMenu : public Widget void _add_group_title(const char* name, coord_def position) { auto text = make_shared(formatted_string(name, LIGHTBLUE)); - text->set_margin_for_sdl({7, 0, 7, 32+2+6}); + text->set_margin_for_sdl(7, 0, 7, 32+2+6); m_main_items->add_label(move(text), position.x, position.y); } @@ -1702,11 +1702,11 @@ static void _construct_weapon_menu(const newgame_def& ng, auto hbox = make_shared(Box::HORZ); hbox->align_items = Widget::Align::CENTER; - hbox->set_margin_for_sdl({2,10,2,2}); + hbox->set_margin_for_sdl(2, 10, 2, 2); #ifdef USE_TILE auto tile_stack = make_shared(); - tile_stack->set_margin_for_sdl({0, 6, 0, 0}); + tile_stack->set_margin_for_sdl(0, 6, 0, 0); tile_stack->flex_grow = 0; hbox->add_child(tile_stack); @@ -1813,15 +1813,15 @@ static bool _prompt_weapon(const newgame_def& ng, newgame_def& ng_choice, fill_doll_for_newgame(doll, ng); #ifdef USE_TILE_LOCAL auto tile = make_shared(doll); - tile->set_margin_for_sdl({0, 10, 0, 0}); + tile->set_margin_for_sdl(0, 10, 0, 0); title_hbox->add_child(move(tile)); #endif #endif auto title = make_shared(formatted_string(_welcome(ng), BROWN)); title_hbox->add_child(title); title_hbox->align_items = Widget::CENTER; - title_hbox->set_margin_for_sdl({0, 0, 20, 0}); - title_hbox->set_margin_for_crt({0, 0, 1, 0}); + title_hbox->set_margin_for_sdl(0, 0, 20, 0); + title_hbox->set_margin_for_crt(0, 0, 1, 0); auto vbox = make_shared(Box::VERT); vbox->align_items = Widget::Align::STRETCH; @@ -1831,8 +1831,8 @@ static bool _prompt_weapon(const newgame_def& ng, newgame_def& ng_choice, auto main_items = make_shared(true, 1, weapons.size()); main_items->menu_id = "weapon-main"; - main_items->set_margin_for_sdl({15, 0, 15, 0}); - main_items->set_margin_for_crt({1, 0, 1, 0}); + main_items->set_margin_for_sdl(15, 0); + main_items->set_margin_for_crt(1, 0); vbox->add_child(main_items); auto sub_items = make_shared(false, 2, 3); @@ -2131,7 +2131,7 @@ static void _construct_gamemode_map_menu(const mapref_vector& maps, hbox->align_items = Widget::Align::CENTER; auto tile = make_shared(); tile->set_tile(tile_for_map_name(map_name)); - tile->set_margin_for_sdl({0, 6, 0, 0}); + tile->set_margin_for_sdl(0, 6, 0, 0); hbox->add_child(move(tile)); hbox->add_child(label); #endif @@ -2140,7 +2140,7 @@ static void _construct_gamemode_map_menu(const mapref_vector& maps, auto btn = make_shared(); #ifdef USE_TILE - hbox->set_margin_for_sdl({2,10,2,2}); + hbox->set_margin_for_sdl(2, 10, 2, 2); btn->set_child(move(hbox)); #else btn->set_child(move(label)); @@ -2227,8 +2227,8 @@ static void _prompt_gamemode_map(newgame_def& ng, newgame_def& ng_choice, auto main_items = make_shared(true, 1, maps.size()); main_items->menu_id = "map-main"; - main_items->set_margin_for_sdl({15, 0, 15, 0}); - main_items->set_margin_for_crt({1, 0, 1, 0}); + main_items->set_margin_for_sdl(15, 0); + main_items->set_margin_for_crt(1, 0); vbox->add_child(main_items); auto sub_items = make_shared(false, 2, 2); diff --git a/crawl-ref/source/scroller.cc b/crawl-ref/source/scroller.cc index 8289dd99f343..c6c890939014 100644 --- a/crawl-ref/source/scroller.cc +++ b/crawl-ref/source/scroller.cc @@ -76,8 +76,8 @@ int formatted_scroller::show() { shared_ptr title = make_shared(); title->set_text(m_title); - title->set_margin_for_crt({0, 0, 1, 0}); - title->set_margin_for_sdl({0, 0, 20, 0}); + title->set_margin_for_crt(0, 0, 1, 0); + title->set_margin_for_sdl(0, 0, 20, 0); #ifdef USE_TILE_LOCAL title->align_self = Widget::Align::CENTER; #endif @@ -106,8 +106,8 @@ int formatted_scroller::show() shared_ptr more = make_shared(); more = make_shared(); more->set_text(m_more); - more->set_margin_for_crt({1, 0, 0, 0}); - more->set_margin_for_sdl({20, 0, 0, 0}); + more->set_margin_for_crt(1, 0, 0, 0); + more->set_margin_for_sdl(20, 0, 0, 0); vbox->add_child(move(more)); } diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index 9d4f2ed8ec39..63a5acbc0b0f 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -408,7 +408,7 @@ static void _construct_game_modes_menu(shared_ptr& container) hbox->align_items = Widget::Align::CENTER; auto tile = make_shared(); tile->set_tile(tile_def(tileidx_gametype(entry.id), TEX_GUI)); - tile->set_margin_for_sdl({0, 6, 0, 0}); + tile->set_margin_for_sdl(0, 6, 0, 0); hbox->add_child(move(tile)); hbox->add_child(label); #endif @@ -417,7 +417,7 @@ static void _construct_game_modes_menu(shared_ptr& container) auto btn = make_shared(); #ifdef USE_TILE_LOCAL - hbox->set_margin_for_sdl({2,10,2,2}); + hbox->set_margin_for_sdl(2, 10, 2, 2); btn->set_child(move(hbox)); #else btn->set_child(move(label)); @@ -437,7 +437,7 @@ static shared_ptr _make_newgame_button(shared_ptr& contai auto hbox = make_shared(Box::HORZ); hbox->align_items = Widget::Align::CENTER; hbox->add_child(label); - label->set_margin_for_sdl({0,0,0,TILE_Y+6}); + label->set_margin_for_sdl(0,0,0,TILE_Y+6); hbox->min_size().height = TILE_Y; #endif @@ -447,7 +447,7 @@ static shared_ptr _make_newgame_button(shared_ptr& contai #else btn->set_child(move(label)); #endif - btn->get_child()->set_margin_for_sdl({2,10,2,2}); + btn->get_child()->set_margin_for_sdl(2, 10, 2, 2); btn->id = NUM_GAME_TYPE + num_chars; btn->highlight_colour = LIGHTGREY; return btn; @@ -463,7 +463,7 @@ static void _construct_save_games_menu(shared_ptr& container, #ifdef USE_TILE_LOCAL auto tile = make_shared(chars.at(i).doll); - tile->set_margin_for_sdl({0, 6, 0, 0}); + tile->set_margin_for_sdl(0, 6, 0, 0); hbox->add_child(move(tile)); #endif @@ -492,7 +492,7 @@ static void _construct_save_games_menu(shared_ptr& container, #else btn->set_child(move(label)); #endif - btn->get_child()->set_margin_for_sdl({2,10,2,2}); + btn->get_child()->set_margin_for_sdl(2, 10, 2, 2); btn->id = NUM_GAME_TYPE + i; btn->highlight_colour = LIGHTGREY; container->add_button(move(btn), 0, i); @@ -538,24 +538,24 @@ class UIStartupMenu : public Widget m_root->align_items = Widget::Align::STRETCH; auto about = make_shared(opening_screen()); - about->set_margin_for_crt({0, 0, 1, 0}); - about->set_margin_for_sdl({0, 0, 10, 0}); + about->set_margin_for_crt(0, 0, 1, 0); + about->set_margin_for_sdl(0, 0, 10, 0); m_root->add_child(move(about)); auto grid = make_shared(); - grid->set_margin_for_crt({0, 0, 1, 0}); + grid->set_margin_for_crt(0, 0, 1, 0); auto name_prompt = make_shared("Enter your name:"); - name_prompt->set_margin_for_crt({0, 1, 1, 0}); - name_prompt->set_margin_for_sdl({0, 0, 10, 0}); + name_prompt->set_margin_for_crt(0, 1, 1, 0); + name_prompt->set_margin_for_sdl(0, 0, 10, 0); // If the game filled in a complete name, the user will // usually want to enter a new name instead of adding // to the current one. input_text = make_shared(formatted_string(input_string, WHITE)); - input_text->set_margin_for_crt({0, 0, 1, 0}); - input_text->set_margin_for_sdl({0, 0, 10, 10}); + input_text->set_margin_for_crt(0, 0, 1, 0); + input_text->set_margin_for_sdl(0, 0, 10, 10); grid->add_child(move(name_prompt), 0, 0); grid->add_child(input_text, 1, 0); @@ -563,11 +563,11 @@ class UIStartupMenu : public Widget descriptions = make_shared(); auto mode_prompt = make_shared("Choices:"); - mode_prompt->set_margin_for_crt({0, 1, 1, 0}); - mode_prompt->set_margin_for_sdl({0, 0, 10, 0}); + mode_prompt->set_margin_for_crt(0, 1, 1, 0); + mode_prompt->set_margin_for_sdl(0, 0, 10, 0); game_modes_menu = make_shared(true, 1, ARRAYSZ(entries)); - game_modes_menu->set_margin_for_sdl({0, 0, 10, 10}); - game_modes_menu->set_margin_for_crt({0, 0, 1, 0}); + game_modes_menu->set_margin_for_sdl(0, 0, 10, 10); + game_modes_menu->set_margin_for_crt(0, 0, 1, 0); game_modes_menu->descriptions = descriptions; _construct_game_modes_menu(game_modes_menu); @@ -584,9 +584,9 @@ class UIStartupMenu : public Widget if (num_saves > 0) { auto save_prompt = make_shared("Saved games:"); - save_prompt->set_margin_for_crt({0, 1, 1, 0}); - save_prompt->set_margin_for_sdl({0, 0, 10, 0}); - save_games_menu->set_margin_for_sdl({0, 0, 10, 10}); + save_prompt->set_margin_for_crt(0, 1, 1, 0); + save_prompt->set_margin_for_sdl(0, 0, 10, 0); + save_games_menu->set_margin_for_sdl(0, 0, 10, 10); #ifdef USE_TILE_LOCAL save_prompt->min_size().height = TILE_Y + 2; save_games_menu->min_size().height = TILE_Y * min(num_saves, 3); @@ -654,8 +654,8 @@ class UIStartupMenu : public Widget m_root->add_child(make_shared( formatted_string::parse_string(instructions_text))); - descriptions->set_margin_for_crt({1, 0, 0, 0}); - descriptions->set_margin_for_sdl({10, 0, 0, 0}); + descriptions->set_margin_for_crt(1, 0, 0, 0); + descriptions->set_margin_for_sdl(10, 0, 0, 0); m_root->add_child(descriptions); }; diff --git a/crawl-ref/source/tilereg-doll.cc b/crawl-ref/source/tilereg-doll.cc index 7f89294af086..6a8db968c9f2 100644 --- a/crawl-ref/source/tilereg-doll.cc +++ b/crawl-ref/source/tilereg-doll.cc @@ -389,7 +389,7 @@ void DollEditRegion::run() auto vbox = make_shared(Widget::VERT); auto title = make_shared(formatted_string("Doll Editor", YELLOW)); title->align_self = Widget::CENTER; - title->set_margin_for_sdl({0, 0, 20, 0}); + title->set_margin_for_sdl(0, 0, 20, 0); vbox->add_child(move(title)); vbox->add_child(doll_ui); auto popup = make_shared(move(vbox)); diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 26118772ad98..143442fe777d 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -179,7 +179,7 @@ SizeReq Widget::get_preferred_size(Direction dim, int prosp_width) if (cached_sr_valid[dim] && (!dim || cached_sr_pw == prosp_width)) return cached_sr[dim]; - prosp_width = dim ? prosp_width - margin[1] - margin[3] : prosp_width; + prosp_width = dim ? prosp_width - margin.right - margin.left : prosp_width; SizeReq ret = _get_preferred_size(dim, prosp_width); ASSERT(ret.min <= ret.nat); @@ -203,7 +203,7 @@ SizeReq Widget::get_preferred_size(Direction dim, int prosp_width) ret.nat = max(ret.nat, ret.min); ASSERT(ret.min <= ret.nat); - int m = margin[1-dim] + margin[3-dim]; + const int m = dim ? margin.top + margin.bottom : margin.left + margin.right; ret.min += m; ret.nat += m; @@ -223,10 +223,10 @@ void Widget::allocate_region(i4 region) return; i4 new_region = { - region[0] + margin[3], - region[1] + margin[0], - region[2] - margin[3] - margin[1], - region[3] - margin[0] - margin[2], + region[0] + margin.left, + region[1] + margin.top, + region[2] - margin.left - margin.right, + region[3] - margin.top - margin.bottom, }; if (m_region == new_region && !alloc_queued) @@ -1806,13 +1806,13 @@ void UIRoot::render() { const auto& hovered_widget = prev_hover_path.back(); i4 r = hovered_widget->get_region(); - i4 m = hovered_widget->get_margin(); + const Margin m = hovered_widget->get_margin(); VColour lc = VColour(0, 0, 100, 100); - sb.add(r[0], r[1]-m[0], r[0]+r[2], r[1], lc); - sb.add(r[0]+r[2], r[1], r[0]+r[2]+m[1], r[1]+r[3], lc); - sb.add(r[0], r[1]+r[3], r[0]+r[2], r[1]+r[3]+m[2], lc); - sb.add(r[0]-m[3], r[1], r[0], r[1]+r[3], lc); + sb.add(r[0], r[1]-m.top, r[0]+r[2], r[1], lc); + sb.add(r[0]+r[2], r[1], r[0]+r[2]+m.right, r[1]+r[3], lc); + sb.add(r[0], r[1]+r[3], r[0]+r[2], r[1]+r[3]+m.bottom, lc); + sb.add(r[0]-m.left, r[1], r[0], r[1]+r[3], lc); } if (auto w = get_focused_widget()) { i4 r = w->get_region(); diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index fe20c9fa51ac..ca5094f44ed6 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -48,6 +48,18 @@ struct SizeReq int min, nat; }; +class Margin +{ +public: + constexpr Margin() : top(0), right(0), bottom(0), left(0) {}; + constexpr Margin(int v) : top(v), right(v), bottom(v), left(v) {}; + constexpr Margin(int v, int h) : top(v), right(h), bottom(v), left(h) {}; + constexpr Margin(int t, int lr, int b) : top(t), right(lr), bottom(b), left(lr) {}; + constexpr Margin(int t, int r, int b, int l) : top(t), right(r), bottom(b), left(l) {}; + + int top, right, bottom, left; +}; + class Size { public: @@ -154,21 +166,27 @@ class Widget : public enable_shared_from_this SizeReq get_preferred_size(Direction dim, int prosp_width); void allocate_region(i4 region); - i4 get_margin() const { + Margin get_margin() const { return margin; } - void set_margin_for_crt(i4 _margin) + + template + void set_margin_for_crt(Args&&... args) { #ifndef USE_TILE_LOCAL - margin = _margin; + margin = Margin(forward(args)...); + _invalidate_sizereq(); #endif - }; - void set_margin_for_sdl(i4 _margin) + } + + template + void set_margin_for_sdl(Args&&... args) { #ifdef USE_TILE_LOCAL - margin = _margin; + margin = Margin(forward(args)...); + _invalidate_sizereq(); #endif - }; + } virtual bool on_event(const wm_event& event); @@ -188,7 +206,7 @@ class Widget : public enable_shared_from_this protected: i4 m_region; - i4 margin = {0, 0, 0, 0}; + Margin margin = { 0 }; void _unparent(shared_ptr& child); From 87254cb62dffc603f633880ed5915787bc295c2b Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Wed, 9 Oct 2019 00:22:22 +0800 Subject: [PATCH 790/864] Add ui::Region helper class --- crawl-ref/source/end.cc | 2 +- crawl-ref/source/loading-screen.cc | 6 +- crawl-ref/source/menu.cc | 50 ++--- crawl-ref/source/outer-menu.cc | 17 +- crawl-ref/source/skill-menu.cc | 9 +- crawl-ref/source/tilereg-doll.cc | 4 +- crawl-ref/source/ui.cc | 322 ++++++++++++++--------------- crawl-ref/source/ui.h | 47 ++++- 8 files changed, 240 insertions(+), 217 deletions(-) diff --git a/crawl-ref/source/end.cc b/crawl-ref/source/end.cc index ebda1db814c5..53a3eb1441c8 100644 --- a/crawl-ref/source/end.cc +++ b/crawl-ref/source/end.cc @@ -300,7 +300,7 @@ class HiscoreScroller : public Scroller void HiscoreScroller::_allocate_region() { - m_scroll = scroll_target - m_region[3]/2; + m_scroll = scroll_target - m_region.height/2; Scroller::_allocate_region(); } diff --git a/crawl-ref/source/loading-screen.cc b/crawl-ref/source/loading-screen.cc index a04c944af029..163d378d2a62 100644 --- a/crawl-ref/source/loading-screen.cc +++ b/crawl-ref/source/loading-screen.cc @@ -30,8 +30,8 @@ class UIShrinkableImage : public Widget void UIShrinkableImage::_render() { int iw = m_img.orig_width()*scale, ih = m_img.orig_height()*scale; - int dx = (m_region[2]-iw)/2, dy = (m_region[3]-ih)/2; - int x = m_region[0] + dx, y = m_region[1] + dy; + int dx = (m_region.width-iw)/2, dy = (m_region.height-ih)/2; + int x = m_region.x + dx, y = m_region.y + dy; GLWPrim rect(x, y, x+iw, y+ih); rect.set_tex(0, 0, (float)m_img.orig_width()/m_img.width(), (float)m_img.orig_height()/m_img.height()); @@ -48,7 +48,7 @@ SizeReq UIShrinkableImage::_get_preferred_size(Direction dim, int prosp_width) void UIShrinkableImage::_allocate_region() { float iw = m_img.orig_width(), ih = m_img.orig_height(); - scale = min({1.0f, m_region[2]/iw, m_region[3]/ih}); + scale = min({1.0f, m_region.width/iw, m_region.height/ih}); } static shared_ptr loading_text; diff --git a/crawl-ref/source/menu.cc b/crawl-ref/source/menu.cc index 1fa18e25e84c..d4218bcf6eef 100644 --- a/crawl-ref/source/menu.cc +++ b/crawl-ref/source/menu.cc @@ -176,7 +176,7 @@ void UIMenu::update_items() void UIMenu::is_visible_item_range(int *vis_min, int *vis_max) { - const int viewport_height = m_menu->m_ui.scroller->get_region()[3]; + const int viewport_height = m_menu->m_ui.scroller->get_region().height; const int scroll = m_menu->m_ui.scroller->get_scroll(); #ifdef USE_TILE_LOCAL @@ -381,7 +381,7 @@ int UIMenu::get_max_viewport_height() void UIMenu::_render() { #ifdef USE_TILE_LOCAL - GLW_3VF t = {(float)m_region[0], (float)m_region[1], 0}, s = {1, 1, 1}; + GLW_3VF t = {(float)m_region.x, (float)m_region.y, 0}, s = {1, 1, 1}; glmanager->set_transform(t, s); m_shape_buf.draw(); @@ -402,7 +402,7 @@ void UIMenu::_render() { const MenuEntry *me = m_menu->items[i]; int y = i - vis_min + 1; - cgotoxy(m_region[0]+1, m_region[1]+scroll+y); + cgotoxy(m_region.x+1, m_region.y+scroll+y); const int col = m_menu->item_colour(me); textcolour(col); const bool needs_cursor = (m_menu->get_cursor() == i && m_menu->is_set(MF_MULTISELECT)); @@ -411,12 +411,12 @@ void UIMenu::_render() { formatted_string s = formatted_string::parse_string( me->get_text(needs_cursor), col); - s.chop(m_region[2]).display(); + s.chop(m_region.width).display(); } else { string text = me->get_text(needs_cursor); - text = chop_string(text, m_region[2]); + text = chop_string(text, m_region.width); cprintf("%s", text.c_str()); } } @@ -466,7 +466,7 @@ class UIMenuMore : public Text m_text += fs; _expose(); m_wrapped_size = Size(-1); - wrap_text_to_size(m_region[2], m_region[3]); + wrap_text_to_size(m_region.width, m_region.height); }; }; @@ -487,16 +487,16 @@ void UIMenuPopup::_allocate_region() Popup::_allocate_region(); int max_height = m_menu->m_ui.popup->get_max_child_size().height; - max_height -= m_menu->m_ui.title->get_region()[3]; + max_height -= m_menu->m_ui.title->get_region().height; max_height -= m_menu->m_ui.title->get_margin().bottom; - int viewport_height = m_menu->m_ui.scroller->get_region()[3]; + int viewport_height = m_menu->m_ui.scroller->get_region().height; #ifdef USE_TILE_LOCAL - int menu_w = m_menu->m_ui.menu->get_region()[2]; + int menu_w = m_menu->m_ui.menu->get_region().width; m_menu->m_ui.menu->do_layout(menu_w, 1); int m_height = m_menu->m_ui.menu->m_height; - int more_height = m_menu->m_ui.more->get_region()[3]; + int more_height = m_menu->m_ui.more->get_region().height; // switch number of columns int num_cols = m_menu->m_ui.menu->get_num_columns(); if (m_menu->m_ui.menu->m_draw_tiles && m_menu->is_set(MF_USE_TWO_COLUMNS) @@ -513,7 +513,7 @@ void UIMenuPopup::_allocate_region() #endif #ifndef USE_TILE_LOCAL - int menu_height = m_menu->m_ui.menu->get_region()[3]; + int menu_height = m_menu->m_ui.menu->get_region().height; // change more visibility bool can_toggle_more = !m_menu->is_set(MF_ALWAYS_SHOW_MORE) @@ -565,7 +565,7 @@ void UIMenu::_allocate_region() // XXX: is this needed? m_height = m_menu->items.size(); #else - do_layout(m_region[2], m_num_columns); + do_layout(m_region.width, m_num_columns); update_hovered_entry(); pack_buffers(); #endif @@ -574,8 +574,8 @@ void UIMenu::_allocate_region() #ifdef USE_TILE_LOCAL void UIMenu::update_hovered_entry() { - const int x = m_mouse_x - m_region[0], - y = m_mouse_y - m_region[1]; + const int x = m_mouse_x - m_region.x, + y = m_mouse_y - m_region.y; int vis_min, vis_max; is_visible_item_range(&vis_min, &vis_max); @@ -587,7 +587,7 @@ void UIMenu::update_hovered_entry() const auto me = m_menu->items[i]; if (me->hotkeys.size() == 0) continue; - const int w = m_region[2] / m_num_columns; + const int w = m_region.width / m_num_columns; const int entry_x = entry.column * w; const int entry_h = row_heights[entry.row+1] - row_heights[entry.row]; if (x >= entry_x && x < entry_x+w && y >= entry.y && y < entry.y+entry_h) @@ -620,7 +620,7 @@ bool UIMenu::on_event(const wm_event& event) if (event.type == WME_MOUSEENTER) { - do_layout(m_region[2], m_num_columns); + do_layout(m_region.width, m_num_columns); update_hovered_entry(); pack_buffers(); _expose(); @@ -634,7 +634,7 @@ bool UIMenu::on_event(const wm_event& event) m_mouse_y = -1; m_mouse_pressed = false; m_mouse_idx = -1; - do_layout(m_region[2], m_num_columns); + do_layout(m_region.width, m_num_columns); pack_buffers(); _expose(); return false; @@ -642,7 +642,7 @@ bool UIMenu::on_event(const wm_event& event) if (event.type == WME_MOUSEMOTION) { - do_layout(m_region[2], m_num_columns); + do_layout(m_region.width, m_num_columns); update_hovered_entry(); pack_buffers(); _expose(); @@ -693,7 +693,7 @@ void UIMenu::pack_buffers() if (!item_info.size()) return; - const int col_width = m_region[2] / m_num_columns; + const int col_width = m_region.width / m_num_columns; int vis_min, vis_max; is_visible_item_range(&vis_min, &vis_max); @@ -708,7 +708,7 @@ void UIMenu::pack_buffers() if (entry.heading) { - formatted_string split = m_font_entry->split(entry.text, m_region[2], entry_h); + formatted_string split = m_font_entry->split(entry.text, m_region.width, entry_h); // see corresponding section in do_layout() int line_y = entry.y + (i == 0 ? 0 : 5) + item_pad; if (i < (int)item_info.size()-1 && !item_info[i+1].heading) @@ -1962,16 +1962,16 @@ bool Menu::in_page(int index) const { int y1, y2; m_ui.menu->get_item_region(index, &y1, &y2); - int vph = m_ui.menu->get_region()[3]; + int vph = m_ui.menu->get_region().height; int vpy = m_ui.scroller->get_scroll(); return (vpy < y1 && y1 < vpy+vph) || (vpy < y2 && y2 < vpy+vph); } bool Menu::page_down() { - int dy = m_ui.scroller->get_region()[3]; + int dy = m_ui.scroller->get_region().height; int y = m_ui.scroller->get_scroll(); - bool at_bottom = y+dy >= m_ui.menu->get_region()[3]; + bool at_bottom = y+dy >= m_ui.menu->get_region().height; m_ui.scroller->set_scroll(y+dy); #ifndef USE_TILE_LOCAL if (!at_bottom) @@ -1982,7 +1982,7 @@ bool Menu::page_down() bool Menu::page_up() { - int dy = m_ui.scroller->get_region()[3]; + int dy = m_ui.scroller->get_region().height; int y = m_ui.scroller->get_scroll(); m_ui.scroller->set_scroll(y-dy); #ifndef USE_TILE_LOCAL @@ -2021,7 +2021,7 @@ bool Menu::line_up() m_ui.menu->get_item_region(index-1, &y, nullptr); m_ui.scroller->set_scroll(y); #ifndef USE_TILE_LOCAL - int dy = m_ui.scroller->get_region()[3]; + int dy = m_ui.scroller->get_region().height; m_ui.menu->set_showable_height(y+dy); #endif return true; diff --git a/crawl-ref/source/outer-menu.cc b/crawl-ref/source/outer-menu.cc index d78c316d5fa2..d9a116f77f10 100644 --- a/crawl-ref/source/outer-menu.cc +++ b/crawl-ref/source/outer-menu.cc @@ -40,12 +40,11 @@ void MenuButton::_allocate_region() { const VColour bg = active ? VColour(0, 0, 0, 255) : VColour(255, 255, 255, 25); - m_buf.add(m_region[0], m_region[1], - m_region[0]+m_region[2], m_region[1]+m_region[3], bg); + m_buf.add(m_region.x, m_region.y, m_region.ex(), m_region.ey(), bg); const VColour mouse_colour = active ? VColour(34, 34, 34, 255) : term_colours[highlight_colour]; - m_line_buf.add_square(m_region[0]+1, m_region[1]+1, - m_region[0]+m_region[2], m_region[1]+m_region[3], mouse_colour); + m_line_buf.add_square(m_region.x+1, m_region.y+1, + m_region.ex(), m_region.ey(), mouse_colour); } #endif } @@ -313,7 +312,7 @@ void OuterMenu::scroll_button_into_view(MenuButton *btn) Scroller* scroller = dynamic_cast(gp); if (!scroller) return; - i4 btn_reg = btn->get_region(), scr_reg = scroller->get_region(); + const auto btn_reg = btn->get_region(), scr_reg = scroller->get_region(); #ifdef USE_TILE_LOCAL constexpr int shade_height = 12; @@ -321,9 +320,9 @@ void OuterMenu::scroll_button_into_view(MenuButton *btn) constexpr int shade_height = 0; #endif - const int btn_top = btn_reg[1], btn_bot = btn_top + btn_reg[3], - scr_top = scr_reg[1] + shade_height, - scr_bot = scr_reg[1] + scr_reg[3] - shade_height; + const int btn_top = btn_reg.y, btn_bot = btn_top + btn_reg.height, + scr_top = scr_reg.y + shade_height, + scr_bot = scr_reg.y + scr_reg.height - shade_height; const int delta = btn_top < scr_top ? btn_top - scr_top : btn_bot > scr_bot ? btn_bot - scr_bot : 0; scroller->set_scroll(scroller->get_scroll() + delta); @@ -388,7 +387,7 @@ bool OuterMenu::scroller_event_hook(const wm_event& ev) } ASSERT(fx >= 0 && fy >= 0); - const int pagesz = m_root->get_region()[3] / focus->get_region()[3] - 1; + const int pagesz = m_root->get_region().height / focus->get_region().height - 1; const int limit = (key == CK_HOME || key == CK_END) ? INT_MAX : (key == CK_PGUP || key == CK_PGDN) ? pagesz : 1; diff --git a/crawl-ref/source/skill-menu.cc b/crawl-ref/source/skill-menu.cc index e4de27cded3f..ca1c7ae0c644 100644 --- a/crawl-ref/source/skill-menu.cc +++ b/crawl-ref/source/skill-menu.cc @@ -1774,14 +1774,13 @@ SizeReq UISkillMenu::_get_preferred_size(Direction dim, int prosp_width) void UISkillMenu::_allocate_region() { skm.exit(true); - int height = m_region[3]; - skm.init(flag, height); + skm.init(flag, m_region.height); } void UISkillMenu::_render() { #ifdef USE_TILE_LOCAL - GLW_3VF t = {(float)m_region[0], (float)m_region[1], 0}, s = {1, 1, 1}; + GLW_3VF t = {(float)m_region.x, (float)m_region.y, 0}, s = {1, 1, 1}; glmanager->set_transform(t, s); #endif skm.draw_menu(); @@ -1801,8 +1800,8 @@ bool UISkillMenu::on_event(const wm_event& ev) } MouseEvent mouse_ev = ev.mouse_event; - mouse_ev.px -= m_region[0]; - mouse_ev.py -= m_region[1]; + mouse_ev.px -= m_region.x; + mouse_ev.py -= m_region.y; int key = skm.handle_mouse(mouse_ev); if (key && key != CK_NO_KEY) diff --git a/crawl-ref/source/tilereg-doll.cc b/crawl-ref/source/tilereg-doll.cc index 6a8db968c9f2..37892429d0ff 100644 --- a/crawl-ref/source/tilereg-doll.cc +++ b/crawl-ref/source/tilereg-doll.cc @@ -352,8 +352,8 @@ void UIDollEditor::_render() void UIDollEditor::_allocate_region() { - reg->sx = m_region[0]; - reg->sy = m_region[1]; + reg->sx = m_region.x; + reg->sy = m_region.y; } void DollEditRegion::run() diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 143442fe777d..753c2650ece6 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -32,36 +32,31 @@ namespace ui { -static i4 aabb_intersect(i4 a, i4 b) +static Region aabb_intersect(Region a, Region b) { - a[2] += a[0]; a[3] += a[1]; - b[2] += b[0]; b[3] += b[1]; - i4 i = { max(a[0], b[0]), max(a[1], b[1]), min(a[2], b[2]), min(a[3], b[3]) }; - i[2] -= i[0]; i[3] -= i[1]; + Region i = { max(a.x, b.x), max(a.y, b.y), min(a.ex(), b.ex()), min(a.ey(), b.ey()) }; + i.width -= i.x; i.height -= i.y; return i; } -static i4 aabb_union(i4 a, i4 b) +static Region aabb_union(Region a, Region b) { - a[2] += a[0]; a[3] += a[1]; - b[2] += b[0]; b[3] += b[1]; - i4 i = { min(a[0], b[0]), min(a[1], b[1]), max(a[2], b[2]), max(a[3], b[3]) }; - i[2] -= i[0]; i[3] -= i[1]; + Region i = { min(a.x, b.x), min(a.y, b.y), max(a.ex(), b.ex()), max(a.ey(), b.ey()) }; + i.width -= i.x; i.height -= i.y; return i; } - -static inline bool pos_in_rect(i2 pos, i4 rect) +static inline bool pos_in_rect(i2 pos, Region rect) { - if (pos[0] < rect[0] || pos[0] >= rect[0]+rect[2]) + if (pos[0] < rect.x || pos[0] >= rect.ex()) return false; - if (pos[1] < rect[1] || pos[1] >= rect[1]+rect[3]) + if (pos[1] < rect.y || pos[1] >= rect.ey()) return false; return true; } #ifndef USE_TILE_LOCAL -static void clear_text_region(i4 region, COLOURS bg); +static void clear_text_region(Region region, COLOURS bg); #endif // must be before ui_root declaration for correct destruction order @@ -92,10 +87,10 @@ static struct UIRoot bool on_event(const wm_event& event); void queue_layout() { m_needs_layout = true; }; - void expose_region(i4 r) { - if (r[2] == 0 || r[3] == 0) + void expose_region(Region r) { + if (r.empty()) return; - if (m_dirty_region[2] == 0) + if (m_dirty_region.empty()) m_dirty_region = r; else m_dirty_region = aabb_union(m_dirty_region, r); @@ -113,13 +108,13 @@ static struct UIRoot protected: int m_w, m_h; - i4 m_region; - i4 m_dirty_region{0, 0, 0, 0}; + Region m_region; + Region m_dirty_region; Stack m_root; bool m_needs_layout{false}; } ui_root; -static stack scissor_stack; +static stack scissor_stack; struct Widget::slots Widget::slots = {}; @@ -140,9 +135,9 @@ shared_ptr ContainerVec::get_child_at_offset(int x, int y) { for (shared_ptr& child : m_children) { - const i4 region = child->get_region(); - bool inside = (x >= region[0] && x < region[0] + region[2]) - && (y >= region[1] && y < region[1] + region[3]); + const Region region = child->get_region(); + bool inside = (x >= region.x && x < region.x + region.width) + && (y >= region.y && y < region.y + region.height); if (inside) return child; } @@ -151,8 +146,8 @@ shared_ptr ContainerVec::get_child_at_offset(int x, int y) shared_ptr Bin::get_child_at_offset(int x, int y) { - bool inside = (x > m_region[0] && x < m_region[0] + m_region[2]) - && (y > m_region[1] && y < m_region[1] + m_region[3]); + bool inside = (x > m_region.x && x < m_region.x + m_region.width) + && (y > m_region.y && y < m_region.y + m_region.height); return inside ? m_child : nullptr; } @@ -217,16 +212,16 @@ SizeReq Widget::get_preferred_size(Direction dim, int prosp_width) return ret; } -void Widget::allocate_region(i4 region) +void Widget::allocate_region(Region region) { if (!m_visible) return; - i4 new_region = { - region[0] + margin.left, - region[1] + margin.top, - region[2] - margin.left - margin.right, - region[3] - margin.top - margin.bottom, + Region new_region = { + region.x + margin.left, + region.y + margin.top, + region.width - margin.left - margin.right, + region.height - margin.top - margin.bottom, }; if (m_region == new_region && !alloc_queued) @@ -236,8 +231,8 @@ void Widget::allocate_region(i4 region) m_region = new_region; alloc_queued = false; - ASSERT(m_region[2] >= 0); - ASSERT(m_region[3] >= 0); + ASSERT(m_region.width >= 0); + ASSERT(m_region.height >= 0); _allocate_region(); } @@ -414,17 +409,17 @@ void Box::_allocate_region() sr[i] = m_children[i]->get_preferred_size(Widget::HORZ, -1); // Get actual widths - vector cw = horz ? layout_main_axis(sr, m_region[2]) : layout_cross_axis(sr, m_region[2]); + vector cw = horz ? layout_main_axis(sr, m_region.width) : layout_cross_axis(sr, m_region.width); // Get preferred heights for (size_t i = 0; i < m_children.size(); i++) sr[i] = m_children[i]->get_preferred_size(Widget::VERT, cw[i]); // Get actual heights - vector ch = horz ? layout_cross_axis(sr, m_region[3]) : layout_main_axis(sr, m_region[3]); + vector ch = horz ? layout_cross_axis(sr, m_region.height) : layout_main_axis(sr, m_region.height); auto const &m = horz ? cw : ch; - int extra_main_space = m_region[horz ? 2 : 3] - accumulate(m.begin(), m.end(), 0); + int extra_main_space = (horz ? m_region.width : m_region.height) - accumulate(m.begin(), m.end(), 0); ASSERT(extra_main_space >= 0); // main axis offset @@ -437,15 +432,14 @@ void Box::_allocate_region() case Widget::STRETCH: mo = 0; break; default: ASSERT(0); } - int ho = m_region[0] + (horz ? mo : 0); - int vo = m_region[1] + (!horz ? mo : 0); + int ho = m_region.x + (horz ? mo : 0); + int vo = m_region.y + (!horz ? mo : 0); - i4 cr = {ho, vo, 0, 0}; + Region cr = {ho, vo, 0, 0}; for (size_t i = 0; i < m_children.size(); i++) { // cross axis offset - int extra_cross_space = horz ? m_region[3] - ch[i] : m_region[2] - cw[i]; - int xp = horz ? 1 : 0, xs = xp + 2; + int extra_cross_space = horz ? m_region.height - ch[i] : m_region.width - cw[i]; auto const& child = m_children[i]; Align child_align = child->align_self ? child->align_self @@ -460,14 +454,20 @@ void Box::_allocate_region() case Widget::STRETCH: xo = 0; break; default: ASSERT(0); } - cr[xp] = (horz ? vo : ho) + xo; - cr[2] = cw[i]; - cr[3] = ch[i]; + int& cr_cross_offset = horz ? cr.y : cr.x; + int& cr_cross_size = horz ? cr.height : cr.width; + + cr_cross_offset = (horz ? vo : ho) + xo; + cr.width = cw[i]; + cr.height = ch[i]; if (child_align == STRETCH) - cr[xs] = (horz ? ch : cw)[i]; + cr_cross_size = (horz ? ch : cw)[i]; m_children[i]->allocate_region(cr); - cr[horz ? 0 : 1] += cr[horz ? 2 : 3]; + + int& cr_main_offset = horz ? cr.x : cr.y; + int& cr_main_size = horz ? cr.width : cr.height; + cr_main_offset += cr_main_size; } } @@ -570,20 +570,20 @@ static vector _find_highlights(const string& haystack, const string& nee void Text::_render() { - i4 region = m_region; + Region region = m_region; if (scissor_stack.size() > 0) region = aabb_intersect(region, scissor_stack.top()); - if (region[2] <= 0 || region[3] <= 0) + if (region.width <= 0 || region.height <= 0) return; - wrap_text_to_size(m_region[2], m_region[3]); + wrap_text_to_size(m_region.width, m_region.height); #ifdef USE_TILE_LOCAL const int dev_line_height = m_font->char_height(false); const int line_min_pos = display_density.logical_to_device( - region[1] - m_region[1]); + region.y - m_region.y); const int line_max_pos = display_density.logical_to_device( - region[1] + region[3] - m_region[1]); + region.y + region.height - m_region.y); const int line_min = line_min_pos / dev_line_height; const int line_max = line_max_pos / dev_line_height; @@ -637,8 +637,8 @@ void Text::_render() vector highlights = _find_highlights(full_text, hl_pat, begin_idx, end_idx); - int ox = m_region[0]; - const int oy = display_density.logical_to_device(m_region[1]) + + int ox = m_region.x; + const int oy = display_density.logical_to_device(m_region.y) + dev_line_height * line_off; size_t lacc = 0; // the start char of the current op relative to region size_t line = 0; // the line we are at relative to the region @@ -719,9 +719,9 @@ void Text::_render() if (hl_line) { block_lines.insert(y); - m_hl_buf.add(region[0], + m_hl_buf.add(region.x, display_density.device_to_logical(y), - region[0] + region[2], + region.x + region.width, display_density.device_to_logical(y + dev_line_height), VColour(255, 255, 0, 50)); @@ -758,7 +758,7 @@ void Text::_render() // in FTFontWrapper, that, like render_textblock(), would automatically // handle swapping atlas glyphs as necessary. FontBuffer m_font_buf(m_font); - m_font_buf.add(slice, m_region[0], m_region[1] + + m_font_buf.add(slice, m_region.x, m_region.y + display_density.device_to_logical(dev_line_height * line_off)); m_font_buf.draw(); #else @@ -770,19 +770,19 @@ void Text::_render() if (!hl_pat.empty()) { - for (int i = 0; i < region[1]-m_region[1]; i++) + for (int i = 0; i < region.y-m_region.y; i++) begin_idx += m_wrapped_lines[i].tostring().size()+1; int end_idx = begin_idx; - for (int i = region[1]-m_region[1]; i < region[1]-m_region[1]+region[3]; i++) + for (int i = region.y-m_region.y; i < region.y-m_region.y+region.height; i++) end_idx += m_wrapped_lines[i].tostring().size()+1; highlights = _find_highlights(m_text.tostring(), hl_pat, begin_idx, end_idx); } unsigned int hl_idx = 0; - for (size_t i = 0; i < min(lines.size(), (size_t)region[3]); i++) + for (size_t i = 0; i < min(lines.size(), (size_t)region.height); i++) { - cgotoxy(region[0]+1, region[1]+1+i); - formatted_string line = lines[i+region[1]-m_region[1]]; + cgotoxy(region.x+1, region.y+1+i); + formatted_string line = lines[i+region.y-m_region.y]; int end_idx = begin_idx + line.tostring().size(); // convert highlights on this line to a list of line cuts @@ -815,7 +815,7 @@ void Text::_render() else out += slice; } - out.chop(region[2]).display(0); + out.chop(region.width).display(0); begin_idx = end_idx + 1; // +1 is for the newline } @@ -866,7 +866,7 @@ SizeReq Text::_get_preferred_size(Direction dim, int prosp_width) void Text::_allocate_region() { - wrap_text_to_size(m_region[2], m_region[3]); + wrap_text_to_size(m_region.width, m_region.height); } #ifndef USE_TILE_LOCAL @@ -897,8 +897,8 @@ void Image::_render() TileBuffer tb; tb.set_tex(&tiles.get_image_manager()->m_textures[m_tile.tex]); - for (int y = m_region[1]; y < m_region[1]+m_region[3]; y+=m_th) - for (int x = m_region[0]; x < m_region[0]+m_region[2]; x+=m_tw) + for (int y = m_region.y; y < m_region.y+m_region.height; y+=m_th) + for (int x = m_region.x; x < m_region.x+m_region.width; x+=m_tw) tb.add(m_tile.tile, x, y, 0, 0, false, m_th, 1.0, 1.0); tb.draw(); @@ -943,9 +943,9 @@ shared_ptr Stack::get_child_at_offset(int x, int y) { if (m_children.size() == 0) return nullptr; - const i4 region = m_children.back()->get_region(); - bool inside = (x > region[0] && x < region[0] + region[2]) - && (y > region[1] && y < region[1] + region[3]); + const Region region = m_children.back()->get_region(); + bool inside = (x > region.x && x < region.x + region.width) + && (y > region.y && y < region.y + region.height); return inside ? m_children.back() : nullptr; } @@ -971,11 +971,11 @@ void Stack::_allocate_region() { for (auto const& child : m_children) { - i4 cr = m_region; + Region cr = m_region; SizeReq pw = child->get_preferred_size(Widget::HORZ, -1); - cr[2] = min(max(pw.min, m_region[2]), pw.nat); - SizeReq ph = child->get_preferred_size(Widget::VERT, cr[2]); - cr[3] = min(max(ph.min, m_region[3]), ph.nat); + cr.width = min(max(pw.min, m_region.width), pw.nat); + SizeReq ph = child->get_preferred_size(Widget::VERT, cr.width); + cr.height = min(max(ph.min, m_region.height), ph.nat); child->allocate_region(cr); } } @@ -1023,34 +1023,34 @@ void Switcher::_allocate_region() { for (auto const& child : m_children) { - i4 cr = m_region; + Region cr = m_region; SizeReq pw = child->get_preferred_size(Widget::HORZ, -1); - cr[2] = min(max(pw.min, m_region[2]), pw.nat); - SizeReq ph = child->get_preferred_size(Widget::VERT, cr[2]); - cr[3] = min(max(ph.min, m_region[3]), ph.nat); + cr.width = min(max(pw.min, m_region.width), pw.nat); + SizeReq ph = child->get_preferred_size(Widget::VERT, cr.width); + cr.height = min(max(ph.min, m_region.height), ph.nat); int xo, yo; switch (align_x) { case Widget::START: xo = 0; break; - case Widget::CENTER: xo = (m_region[2] - cr[2])/2; break; - case Widget::END: xo = m_region[2] - cr[2]; break; + case Widget::CENTER: xo = (m_region.width - cr.width)/2; break; + case Widget::END: xo = m_region.width - cr.width; break; case Widget::STRETCH: xo = 0; break; default: ASSERT(0); } switch (align_y) { case Widget::START: yo = 0; break; - case Widget::CENTER: yo = (m_region[3] - cr[3])/2; break; - case Widget::END: yo = m_region[3] - cr[3]; break; + case Widget::CENTER: yo = (m_region.height - cr.height)/2; break; + case Widget::END: yo = m_region.height - cr.height; break; case Widget::STRETCH: yo = 0; break; default: ASSERT(0); } - cr[2] += xo; - cr[3] += yo; + cr.width += xo; + cr.height += yo; if (align_x == Widget::STRETCH) - cr[2] = m_region[2]; + cr.width = m_region.width; if (align_y == Widget::STRETCH) - cr[3] = m_region[3]; + cr.height = m_region.height; child->allocate_region(cr); } } @@ -1062,15 +1062,15 @@ shared_ptr Switcher::get_child_at_offset(int x, int y) int c = max(0, min(m_current, (int)m_children.size())); const auto region = m_children[c]->get_region(); - bool inside = (x >= region[0] && x < region[0] + region[2]) - && (y >= region[1] && y < region[1] + region[3]); + bool inside = (x >= region.x && x < region.x + region.width) + && (y >= region.y && y < region.y + region.height); return inside ? m_children[c] : nullptr; } shared_ptr Grid::get_child_at_offset(int x, int y) { - int lx = x - m_region[0]; - int ly = y - m_region[1]; + int lx = x - m_region.x; + int ly = y - m_region.y; int row = -1, col = -1; for (int i = 0; i < (int)m_col_info.size(); i++) { @@ -1136,16 +1136,16 @@ void Grid::init_track_info() void Grid::_render() { // Find the visible rows - i4 scissor = get_scissor(); + const auto scissor = get_scissor(); int row_min = 0, row_max = m_row_info.size()-1, i = 0; for (; i < (int)m_row_info.size(); i++) - if (m_row_info[i].offset+m_row_info[i].size+m_region[1] >= scissor[1]) + if (m_row_info[i].offset+m_row_info[i].size+m_region.y >= scissor.y) { row_min = i; break; } for (; i < (int)m_row_info.size(); i++) - if (m_row_info[i].offset+m_region[1] >= scissor[1]+scissor[3]) + if (m_row_info[i].offset+m_region.y >= scissor.ey()) { row_max = i-1; break; @@ -1170,7 +1170,7 @@ void Grid::compute_track_sizereqs(Direction dim) { auto& cp = m_child_info[i].pos, cs = m_child_info[i].span; // if merging horizontally, need to find (possibly multi-col) width - int prosp_width = dim ? get_tracks_region(cp[0], cp[1], cs[0], cs[1])[2] : -1; + int prosp_width = dim ? get_tracks_region(cp[0], cp[1], cs[0], cs[1]).width : -1; const SizeReq c = m_child_info[i].widget->get_preferred_size(dim, prosp_width); // NOTE: items spanning multiple rows/cols don't contribute! @@ -1277,17 +1277,17 @@ void Grid::layout_track(Direction dim, SizeReq sr, int size) void Grid::_allocate_region() { // Use of _-prefixed member function is necessary here - SizeReq h_sr = _get_preferred_size(Widget::VERT, m_region[2]); + SizeReq h_sr = _get_preferred_size(Widget::VERT, m_region.width); - layout_track(Widget::VERT, h_sr, m_region[3]); + layout_track(Widget::VERT, h_sr, m_region.height); set_track_offsets(m_row_info); for (size_t i = 0; i < m_child_info.size(); i++) { auto& cp = m_child_info[i].pos, cs = m_child_info[i].span; - i4 cell_reg = get_tracks_region(cp[0], cp[1], cs[0], cs[1]); - cell_reg[0] += m_region[0]; - cell_reg[1] += m_region[1]; + Region cell_reg = get_tracks_region(cp[0], cp[1], cs[0], cs[1]); + cell_reg.x += m_region.x; + cell_reg.y += m_region.y; m_child_info[i].widget->allocate_region(cell_reg); } } @@ -1338,38 +1338,38 @@ SizeReq Scroller::_get_preferred_size(Direction dim, int prosp_width) void Scroller::_allocate_region() { - SizeReq sr = m_child->get_preferred_size(Widget::VERT, m_region[2]); - m_scroll = max(0, min(m_scroll, sr.nat-m_region[3])); - i4 ch_reg = {m_region[0], m_region[1]-m_scroll, m_region[2], sr.nat}; + SizeReq sr = m_child->get_preferred_size(Widget::VERT, m_region.width); + m_scroll = max(0, min(m_scroll, sr.nat-m_region.height)); + Region ch_reg = {m_region.x, m_region.y-m_scroll, m_region.width, sr.nat}; m_child->allocate_region(ch_reg); #ifdef USE_TILE_LOCAL int shade_height = 12, ds = 4; - int shade_top = min({m_scroll/ds, shade_height, m_region[3]/2}); - int shade_bot = min({(sr.nat-m_region[3]-m_scroll)/ds, shade_height, m_region[3]/2}); + int shade_top = min({m_scroll/ds, shade_height, m_region.height/2}); + int shade_bot = min({(sr.nat-m_region.height-m_scroll)/ds, shade_height, m_region.height/2}); VColour col_a(4,2,4,0), col_b(4,2,4,200); m_shade_buf.clear(); m_scrollbar_buf.clear(); { - GLWPrim rect(m_region[0], m_region[1]+shade_top-shade_height, - m_region[0]+m_region[2], m_region[1]+shade_top); + GLWPrim rect(m_region.x, m_region.y+shade_top-shade_height, + m_region.x+m_region.width, m_region.y+shade_top); rect.set_col(col_b, col_a); m_shade_buf.add_primitive(rect); } { - GLWPrim rect(m_region[0], m_region[1]+m_region[3]-shade_bot, - m_region[0]+m_region[2], m_region[1]+m_region[3]-shade_bot+shade_height); + GLWPrim rect(m_region.x, m_region.y+m_region.height-shade_bot, + m_region.x+m_region.width, m_region.y+m_region.height-shade_bot+shade_height); rect.set_col(col_a, col_b); m_shade_buf.add_primitive(rect); } - if (ch_reg[3] > m_region[3] && m_scrolbar_visible) { - const int x = m_region[0]+m_region[2]; - const float h_percent = m_region[3] / (float)ch_reg[3]; - const int h = m_region[3]*min(max(0.05f, h_percent), 1.0f); - const float scroll_percent = m_scroll/(float)(ch_reg[3]-m_region[3]); - const int y = m_region[1] + (m_region[3]-h)*scroll_percent; - GLWPrim bg_rect(x+10, m_region[1], x+12, m_region[1]+m_region[3]); + if (ch_reg.height > m_region.height && m_scrolbar_visible) { + const int x = m_region.x+m_region.width; + const float h_percent = m_region.height / (float)ch_reg.height; + const int h = m_region.height*min(max(0.05f, h_percent), 1.0f); + const float scroll_percent = m_scroll/(float)(ch_reg.height-m_region.height); + const int y = m_region.y + (m_region.height-h)*scroll_percent; + GLWPrim bg_rect(x+10, m_region.y, x+12, m_region.y+m_region.height); bg_rect.set_col(VColour(41,41,41)); m_scrollbar_buf.add_primitive(bg_rect); GLWPrim fg_rect(x+10, y, x+12, y+h); @@ -1394,11 +1394,11 @@ bool Scroller::on_event(const wm_event& event) switch (event.key.keysym.sym) { case ' ': case '+': case CK_PGDN: case '>': case '\'': - delta = m_region[3]; + delta = m_region.height; break; case '-': case CK_PGUP: case '<': case ';': - delta = -m_region[3]; + delta = -m_region.height; break; case CK_UP: @@ -1488,49 +1488,49 @@ SizeReq Popup::_get_preferred_size(Direction dim, int prosp_width) void Popup::_allocate_region() { - i4 region = m_region; + Region region = m_region; #ifdef USE_TILE_LOCAL m_buf.clear(); - m_buf.add(m_region[0], m_region[1], - m_region[0] + m_region[2], m_region[1] + m_region[3], + m_buf.add(m_region.x, m_region.y, + m_region.x + m_region.width, m_region.y + m_region.height, VColour(0, 0, 0, 150)); const int pad = base_margin() + m_padding; - region[2] -= 2*pad; - region[3] -= 2*pad + m_depth*m_depth_indent*(!m_centred); + region.width -= 2*pad; + region.height -= 2*pad + m_depth*m_depth_indent*(!m_centred); SizeReq hsr = m_child->get_preferred_size(HORZ, -1); - region[2] = max(hsr.min, min(region[2], hsr.nat)); - SizeReq vsr = m_child->get_preferred_size(VERT, region[2]); - region[3] = max(vsr.min, min(region[3], vsr.nat)); + region.width = max(hsr.min, min(region.width, hsr.nat)); + SizeReq vsr = m_child->get_preferred_size(VERT, region.width); + region.height = max(vsr.min, min(region.height, vsr.nat)); - region[0] += pad + (m_region[2]-2*pad-region[2])/2; - region[1] += pad + (m_centred ? (m_region[3]-2*pad-region[3])/2 + region.x += pad + (m_region.width-2*pad-region.width)/2; + region.y += pad + (m_centred ? (m_region.height-2*pad-region.height)/2 : m_depth*m_depth_indent); - m_buf.add(region[0] - m_padding, region[1] - m_padding, - region[0] + region[2] + m_padding, - region[1] + region[3] + m_padding, + m_buf.add(region.x - m_padding, region.y - m_padding, + region.x + region.width + m_padding, + region.y + region.height + m_padding, VColour(125, 98, 60)); - m_buf.add(region[0] - m_padding + 2, region[1] - m_padding + 2, - region[0] + region[2] + m_padding - 2, - region[1] + region[3] + m_padding - 2, + m_buf.add(region.x - m_padding + 2, region.y - m_padding + 2, + region.x + region.width + m_padding - 2, + region.y + region.height + m_padding - 2, VColour(0, 0, 0)); - m_buf.add(region[0] - m_padding + 3, region[1] - m_padding + 3, - region[0] + region[2] + m_padding - 3, - region[1] + region[3] + m_padding - 3, + m_buf.add(region.x - m_padding + 3, region.y - m_padding + 3, + region.x + region.width + m_padding - 3, + region.y + region.height + m_padding - 3, VColour(4, 2, 4)); #else SizeReq hsr = m_child->get_preferred_size(HORZ, -1); - region[2] = max(hsr.min, min(region[2], hsr.nat)); - SizeReq vsr = m_child->get_preferred_size(VERT, region[2]); - region[3] = max(vsr.min, min(region[3], vsr.nat)); + region.width = max(hsr.min, min(region.width, hsr.nat)); + SizeReq vsr = m_child->get_preferred_size(VERT, region.width); + region.height = max(vsr.min, min(region.height, vsr.nat)); #endif m_child->allocate_region(region); } Size Popup::get_max_child_size() { - Size max_child_size = Size(m_region[2], m_region[3]); + Size max_child_size = Size(m_region.width, m_region.height); #ifdef USE_TILE_LOCAL const int pad = base_margin() + m_padding; max_child_size.width = (max_child_size.width - 2*pad) & ~0x1; @@ -1544,7 +1544,7 @@ int Popup::base_margin() { const int screen_small = 800, screen_large = 1000; const int margin_small = 10, margin_large = 50; - const int clipped = max(screen_small, min(screen_large, m_region[3])); + const int clipped = max(screen_small, min(screen_large, m_region.height)); return margin_small + (clipped-screen_small) *(margin_large-margin_small)/(screen_large-screen_small); } @@ -1552,7 +1552,7 @@ int Popup::base_margin() void Dungeon::_render() { #ifdef USE_TILE_LOCAL - GLW_3VF t = {(float)m_region[0], (float)m_region[1], 0}, s = {32, 32, 1}; + GLW_3VF t = {(float)m_region.x, (float)m_region.y, 0}, s = {32, 32, 1}; glmanager->set_transform(t, s); m_buf.draw(); glmanager->reset_transform(); @@ -1670,7 +1670,7 @@ void PlayerDoll::_allocate_region() { int tile = tdef.tile; TextureID tex = tdef.tex; - m_tile_buf[tex].add_unscaled(tile, m_region[0], m_region[1], tdef.ymax); + m_tile_buf[tex].add_unscaled(tile, m_region.x, m_region.y, tdef.ymax); } } @@ -1795,28 +1795,28 @@ void UIRoot::render() size_t i = 0; for (const auto& w : prev_hover_path) { - i4 r = w->get_region(); + const auto r = w->get_region(); i++; VColour lc; lc = i == prev_hover_path.size() ? VColour(255, 100, 0, 100) : VColour(0, 50 + i*40, 0, 100); - lb.add_square(r[0]+1, r[1]+1, r[0]+r[2], r[1]+r[3], lc); + lb.add_square(r.x+1, r.y+1, r.ex(), r.ey(), lc); } if (!prev_hover_path.empty()) { const auto& hovered_widget = prev_hover_path.back(); - i4 r = hovered_widget->get_region(); + Region r = hovered_widget->get_region(); const Margin m = hovered_widget->get_margin(); VColour lc = VColour(0, 0, 100, 100); - sb.add(r[0], r[1]-m.top, r[0]+r[2], r[1], lc); - sb.add(r[0]+r[2], r[1], r[0]+r[2]+m.right, r[1]+r[3], lc); - sb.add(r[0], r[1]+r[3], r[0]+r[2], r[1]+r[3]+m.bottom, lc); - sb.add(r[0]-m.left, r[1], r[0], r[1]+r[3], lc); + sb.add(r.x, r.y-m.top, r.ex(), r.y, lc); + sb.add(r.ex(), r.y, r.ex()+m.right, r.ey(), lc); + sb.add(r.x, r.ey(), r.ex(), r.ey()+m.bottom, lc); + sb.add(r.x-m.left, r.y, r.x, r.ey(), lc); } if (auto w = get_focused_widget()) { - i4 r = w->get_region(); - lb.add_square(r[0]+1, r[1]+1, r[0]+r[2], r[1]+r[3], VColour(128,31,239,255)); + Region r = w->get_region(); + lb.add_square(r.x+1, r.y+1, r.ex(), r.ey(), VColour(128,31,239,255)); } lb.draw(); sb.draw(); @@ -1951,13 +1951,13 @@ bool UIRoot::on_event(const wm_event& event) return false; } -void push_scissor(i4 scissor) +void push_scissor(Region scissor) { if (scissor_stack.size() > 0) scissor = aabb_intersect(scissor, scissor_stack.top()); scissor_stack.push(scissor); #ifdef USE_TILE_LOCAL - glmanager->set_scissor(scissor[0], scissor[1], scissor[2], scissor[3]); + glmanager->set_scissor(scissor.x, scissor.y, scissor.width, scissor.height); #endif } @@ -1968,15 +1968,15 @@ void pop_scissor() #ifdef USE_TILE_LOCAL if (scissor_stack.size() > 0) { - i4 scissor = scissor_stack.top(); - glmanager->set_scissor(scissor[0], scissor[1], scissor[2], scissor[3]); + Region scissor = scissor_stack.top(); + glmanager->set_scissor(scissor.x, scissor.y, scissor.width, scissor.height); } else glmanager->reset_scissor(); #endif } -i4 get_scissor() +Region get_scissor() { if (scissor_stack.size() > 0) return scissor_stack.top(); @@ -1984,18 +1984,18 @@ i4 get_scissor() } #ifndef USE_TILE_LOCAL -static void clear_text_region(i4 region, COLOURS bg) +static void clear_text_region(Region region, COLOURS bg) { if (scissor_stack.size() > 0) region = aabb_intersect(region, scissor_stack.top()); - if (region[2] <= 0 || region[3] <= 0) + if (region.width <= 0 || region.height <= 0) return; textcolour(LIGHTGREY); textbackground(bg); - for (int y=region[1]; y < region[1]+region[3]; y++) + for (int y=region.y; y < region.y+region.height; y++) { - cgotoxy(region[0]+1, y+1); - cprintf("%*s", region[2], ""); + cgotoxy(region.x+1, y+1); + cprintf("%*s", region.width, ""); } } #endif diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index ca5094f44ed6..dd2ed66bfcc1 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -60,6 +60,29 @@ class Margin int top, right, bottom, left; }; +class Region +{ +public: + constexpr Region() : x(0), y(0), width(0), height(0) {}; + constexpr Region(int _x, int _y, int _width, int _height) : x(_x), y(_y), width(_width), height(_height) {}; + + constexpr bool operator == (const Region& other) const + { + return x == other.x && y == other.y + && width == other.width && height == other.height; + } + + constexpr bool empty() const + { + return width == 0 || height == 0; + } + + constexpr int ex() const { return x + width; } + constexpr int ey() const { return y + height; } + + int x, y, width, height; +}; + class Size { public: @@ -139,7 +162,8 @@ class Widget : public enable_shared_from_this Align align_self = UNSET; bool expand_h = false, expand_v = false; bool shrink_h = false, shrink_v = false; - const i4 get_region() const { return m_region; } + Region get_region() const { return m_region; } + Size& min_size() { _invalidate_sizereq(); return m_min_size; } Size& max_size() { _invalidate_sizereq(); return m_max_size; } @@ -164,7 +188,7 @@ class Widget : public enable_shared_from_this // - caching void render(); SizeReq get_preferred_size(Direction dim, int prosp_width); - void allocate_region(i4 region); + void allocate_region(Region region); Margin get_margin() const { return margin; @@ -205,7 +229,7 @@ class Widget : public enable_shared_from_this }; protected: - i4 m_region; + Region m_region; Margin margin = { 0 }; void _unparent(shared_ptr& child); @@ -494,13 +518,14 @@ class Grid : public Container bool stretch_h = false, stretch_v = false; protected: - i4 get_tracks_region(int x, int y, int w, int h) const + Region get_tracks_region(int x, int y, int w, int h) const { - return { - m_col_info[x].offset, m_row_info[y].offset, - m_col_info[x+w-1].size + m_col_info[x+w-1].offset - m_col_info[x].offset, - m_row_info[y+h-1].size + m_row_info[y+h-1].offset - m_row_info[y].offset, - }; + Region track_region; + track_region.x = m_col_info[x].offset; + track_region.y = m_row_info[y].offset; + track_region.width = m_col_info[x+w-1].size + m_col_info[x+w-1].offset - m_col_info[x].offset; + track_region.height = m_row_info[y+h-1].size + m_row_info[y+h-1].offset - m_row_info[y].offset; + return track_region; } struct track_info { @@ -678,9 +703,9 @@ void ui_force_render(); void ui_render(); void ui_delay(unsigned int ms); -void push_scissor(i4 scissor); +void push_scissor(Region scissor); void pop_scissor(); -i4 get_scissor(); +Region get_scissor(); void set_focused_widget(Widget* w); Widget* get_focused_widget(); From 9d7ac8f86203d2c3d2fc30b181fe8445952d3a81 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Wed, 9 Oct 2019 00:32:21 +0800 Subject: [PATCH 791/864] Clean up headers --- crawl-ref/source/ui.cc | 12 +++++------- crawl-ref/source/ui.h | 6 +++--- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 753c2650ece6..53954c422b3b 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -12,22 +12,20 @@ #include "ui.h" #include "cio.h" #include "macro.h" -# include "state.h" +#include "state.h" #include "tileweb.h" #ifdef USE_TILE_LOCAL # include "glwrapper.h" # include "tilebuf.h" +# include "tilepick.h" +# include "tilepick-p.h" +# include "tile-player-flag-cut.h" #else # include # include "output.h" -# include "view.h" # include "stringutil.h" -#endif -#ifdef USE_TILE_LOCAL -# include "tilepick.h" -# include "tilepick-p.h" -# include "tile-player-flag-cut.h" +# include "view.h" #endif namespace ui { diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index dd2ed66bfcc1..8c5c09113937 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -11,15 +11,15 @@ #include "format.h" #include "KeymapContext.h" #include "state.h" -#include "tilefont.h" #include "tiledef-gui.h" +#include "tilefont.h" #include "unwind.h" #include "windowmanager.h" #ifdef USE_TILE_LOCAL -# include "tiledoll.h" -# include "tilesdl.h" # include "tilebuf.h" # include "tiledgnbuf.h" +# include "tiledoll.h" +# include "tilesdl.h" #endif #ifdef USE_TILE_WEB # include "tileweb.h" From cb6844083c62d2733696ed0fd785fc163e8ea35b Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Wed, 9 Oct 2019 00:35:56 +0800 Subject: [PATCH 792/864] Remove use of ui::i2 --- crawl-ref/source/ui.cc | 36 +++++++++++++++++++----------------- crawl-ref/source/ui.h | 6 ++++-- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 53954c422b3b..ff48719d8a91 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -44,11 +44,11 @@ static Region aabb_union(Region a, Region b) return i; } -static inline bool pos_in_rect(i2 pos, Region rect) +static inline bool pos_in_rect(int x, int y, Region rect) { - if (pos[0] < rect.x || pos[0] >= rect.ex()) + if (x < rect.x || x >= rect.ex()) return false; - if (pos[1] < rect.y || pos[1] >= rect.ey()) + if (y < rect.y || y >= rect.ey()) return false; return true; } @@ -1092,9 +1092,9 @@ shared_ptr Grid::get_child_at_offset(int x, int y) return nullptr; for (auto& child : m_child_info) { - if (child.pos[0] <= col && col < child.pos[0] + child.span[0]) - if (child.pos[1] <= row && row < child.pos[1] + child.span[1]) - if (pos_in_rect({x, y}, child.widget->get_region())) + if (child.pos.x <= col && col < child.pos.x + child.span.width) + if (child.pos.y <= row && row < child.pos.y + child.span.height) + if (pos_in_rect(x, y, child.widget->get_region())) return child.widget; } return nullptr; @@ -1119,15 +1119,15 @@ void Grid::init_track_info() int n_rows = 0, n_cols = 0; for (auto info : m_child_info) { - n_rows = max(n_rows, info.pos[1]+info.span[1]); - n_cols = max(n_cols, info.pos[0]+info.span[0]); + n_rows = max(n_rows, info.pos.y+info.span.height); + n_cols = max(n_cols, info.pos.x+info.span.width); } m_row_info.resize(n_rows); m_col_info.resize(n_cols); sort(m_child_info.begin(), m_child_info.end(), [](const child_info& a, const child_info& b) { - return a.pos[1] < b.pos[1]; + return a.pos.y < b.pos.y; }); } @@ -1151,8 +1151,8 @@ void Grid::_render() for (auto const& child : m_child_info) { - if (child.pos[1] < row_min) continue; - if (child.pos[1] > row_max) break; + if (child.pos.y < row_min) continue; + if (child.pos.y > row_max) break; child.widget->render(); } } @@ -1166,15 +1166,16 @@ void Grid::compute_track_sizereqs(Direction dim) t.sr = {0, 0}; for (size_t i = 0; i < m_child_info.size(); i++) { - auto& cp = m_child_info[i].pos, cs = m_child_info[i].span; + auto& cp = m_child_info[i].pos; + auto& cs = m_child_info[i].span; // if merging horizontally, need to find (possibly multi-col) width - int prosp_width = dim ? get_tracks_region(cp[0], cp[1], cs[0], cs[1]).width : -1; + int prosp_width = dim ? get_tracks_region(cp.x, cp.y, cs.width, cs.height).width : -1; const SizeReq c = m_child_info[i].widget->get_preferred_size(dim, prosp_width); // NOTE: items spanning multiple rows/cols don't contribute! - if (cs[0] == 1 && cs[1] == 1) + if (cs.width == 1 && cs.height == 1) { - auto& s = track[cp[dim]].sr; + auto& s = track[dim ? cp.y : cp.x].sr; s.min = max(s.min, c.min); s.nat = max(s.nat, c.nat); } @@ -1282,8 +1283,9 @@ void Grid::_allocate_region() for (size_t i = 0; i < m_child_info.size(); i++) { - auto& cp = m_child_info[i].pos, cs = m_child_info[i].span; - Region cell_reg = get_tracks_region(cp[0], cp[1], cs[0], cs[1]); + auto& cp = m_child_info[i].pos; + auto& cs = m_child_info[i].span; + Region cell_reg = get_tracks_region(cp.x, cp.y, cs.width, cs.height); cell_reg.x += m_region.x; cell_reg.y += m_region.y; m_child_info[i].widget->allocate_region(cell_reg); diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index 8c5c09113937..1f7b1da9eedb 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -538,8 +538,10 @@ class Grid : public Container vector m_row_info; struct child_info { - i2 pos; - i2 span; + struct { + int x, y; + } pos; + Size span; shared_ptr widget; inline bool operator==(const child_info& rhs) const { return widget == rhs.widget; } }; From 1ec443c8e56f7af3761c47165c94a216e5f4286e Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Wed, 9 Oct 2019 00:36:10 +0800 Subject: [PATCH 793/864] Remove ui::vec utility array --- crawl-ref/source/ui.h | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index 1f7b1da9eedb..e61cfefd4faf 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -27,22 +27,6 @@ namespace ui { -// This is used instead of std::array because travis uses older versions of GCC -// and Clang that demand braces around initializer lists everywhere. -template -struct vec { - int items[N]; - template vec (Ts... l) : items{l...} {} - const int& operator[](int index) const { return items[index]; } - int& operator[](int index) { return items[index]; } - inline bool operator==(const vec& rhs) { - return equal(begin(items), end(items), begin(rhs.items)); - } - inline bool operator!=(const vec& rhs) { return !(*this == rhs); } -}; -using i2 = vec<2>; -using i4 = vec<4>; - struct SizeReq { int min, nat; From d9e12f686b69104ddfa5c981d342954dca1b3ab8 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Wed, 9 Oct 2019 00:41:13 +0800 Subject: [PATCH 794/864] Make RestartAllocation private to ui.cc --- crawl-ref/source/menu.cc | 6 +++--- crawl-ref/source/ui.cc | 7 +++++++ crawl-ref/source/ui.h | 3 +-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/crawl-ref/source/menu.cc b/crawl-ref/source/menu.cc index d4218bcf6eef..2aeb99febd05 100644 --- a/crawl-ref/source/menu.cc +++ b/crawl-ref/source/menu.cc @@ -506,7 +506,7 @@ void UIMenuPopup::_allocate_region() || (num_cols == 2 && m_height+more_height <= max_height)) { m_menu->m_ui.menu->set_num_columns(3 - num_cols); - throw RestartAllocation(); + ui::restart_layout(); } } m_menu->m_ui.menu->do_layout(menu_w, num_cols); @@ -526,7 +526,7 @@ void UIMenuPopup::_allocate_region() m_menu->m_ui.more->set_visible(!more_visible); _invalidate_sizereq(); m_menu->m_ui.more->_queue_allocation(); - throw RestartAllocation(); + ui::restart_layout(); } } @@ -555,7 +555,7 @@ void UIMenuPopup::_allocate_region() { m_menu->m_ui.scroller->_invalidate_sizereq(); m_menu->m_ui.scroller->_queue_allocation(); - throw RestartAllocation(); + ui::restart_layout(); } } diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index ff48719d8a91..5240807ab353 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -104,6 +104,8 @@ static struct UIRoot vector cutoff_stack; vector focus_stack; + struct RestartAllocation {}; + protected: int m_w, m_h; Region m_region; @@ -2225,6 +2227,11 @@ bool has_layout() return ui_root.num_children() > 0; } +NORETURN void restart_layout() +{ + throw UIRoot::RestartAllocation(); +} + int getch(KeymapContext km) { // getch() can be called when there are no widget layouts, i.e. diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index e61cfefd4faf..b837a9ab1033 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -87,8 +87,6 @@ class Size int width, height; }; -struct RestartAllocation {}; - template class Slot; template @@ -684,6 +682,7 @@ shared_ptr top_layout(); void pump_events(int wait_event_timeout = INT_MAX); void run_layout(shared_ptr root, const bool& done); bool has_layout(); +NORETURN void restart_layout(); int getch(KeymapContext km = KMC_DEFAULT); void ui_force_render(); void ui_render(); From c303d0022931d1e0cfe5fa2cf27e99d33cefa53c Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Wed, 9 Oct 2019 00:58:08 +0800 Subject: [PATCH 795/864] Improve Box widget alignment property names "main" means alignment along the main axis, while "cross" means alignment along the cross axis. E.g. for a horizontal box, the main axis is horizontal and the cross axis is vertical. --- crawl-ref/source/command.cc | 2 +- crawl-ref/source/decks.cc | 2 +- crawl-ref/source/describe-god.cc | 2 +- crawl-ref/source/describe.cc | 10 +++++----- crawl-ref/source/end.cc | 2 +- crawl-ref/source/hints.cc | 4 ++-- crawl-ref/source/loading-screen.cc | 2 +- crawl-ref/source/menu.cc | 4 ++-- crawl-ref/source/newgame.cc | 24 ++++++++++++------------ crawl-ref/source/startup.cc | 8 ++++---- crawl-ref/source/ui.cc | 10 +++++----- crawl-ref/source/ui.h | 5 ++--- 12 files changed, 37 insertions(+), 38 deletions(-) diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc index fa9eba3beebf..2765fedaf423 100644 --- a/crawl-ref/source/command.cc +++ b/crawl-ref/source/command.cc @@ -224,7 +224,7 @@ static void _print_version() title->set_margin_for_sdl(0, 0, 0, 10); title_hbox->add_child(move(title)); - title_hbox->align_items = Widget::CENTER; + title_hbox->align_cross = Widget::CENTER; title_hbox->set_margin_for_crt(0, 0, 1, 0); title_hbox->set_margin_for_sdl(0, 0, 20, 0); vbox->add_child(move(title_hbox)); diff --git a/crawl-ref/source/decks.cc b/crawl-ref/source/decks.cc index 30877f3ac79f..72fcd0f15442 100644 --- a/crawl-ref/source/decks.cc +++ b/crawl-ref/source/decks.cc @@ -411,7 +411,7 @@ static void _describe_cards(CrawlVector& cards) auto title = make_shared(formatted_string(name, WHITE)); title->set_margin_for_sdl(0, 0, 0, 10); title_hbox->add_child(move(title)); - title_hbox->align_items = Widget::CENTER; + title_hbox->align_cross = Widget::CENTER; title_hbox->set_margin_for_crt(first ? 0 : 1, 0); title_hbox->set_margin_for_sdl(first ? 0 : 20, 0); vbox->add_child(move(title_hbox)); diff --git a/crawl-ref/source/describe-god.cc b/crawl-ref/source/describe-god.cc index 31f90ba8b247..b8f451514449 100644 --- a/crawl-ref/source/describe-god.cc +++ b/crawl-ref/source/describe-god.cc @@ -1103,7 +1103,7 @@ static void build_partial_god_ui(god_type which_god, shared_ptr& popu title->set_margin_for_sdl(0, 0, 0, 16); title_hbox->add_child(move(title)); - title_hbox->align_items = Widget::CENTER; + title_hbox->align_cross = Widget::CENTER; title_hbox->align_self = Widget::CENTER; vbox->add_child(move(title_hbox)); diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index 9605017a1548..831c6fdb0008 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -126,7 +126,7 @@ int show_description(const describe_info &inf, const tile_def *tile) auto title = make_shared(inf.title); title_hbox->add_child(move(title)); - title_hbox->align_items = Widget::CENTER; + title_hbox->align_cross = Widget::CENTER; title_hbox->set_margin_for_sdl(0, 0, 20, 0); title_hbox->set_margin_for_crt(0, 0, 1, 0); vbox->add_child(move(title_hbox)); @@ -2326,7 +2326,7 @@ void describe_feature_wide(const coord_def& pos) auto title = make_shared(feat.title); title->set_margin_for_sdl(0, 0, 0, 10); title_hbox->add_child(move(title)); - title_hbox->align_items = Widget::CENTER; + title_hbox->align_cross = Widget::CENTER; const bool has_desc = feat.body != feat.title && feat.body != ""; @@ -2702,7 +2702,7 @@ bool describe_item(item_def &item, function fixup_desc) title->set_margin_for_sdl(0, 0, 0, 10); title_hbox->add_child(move(title)); - title_hbox->align_items = Widget::CENTER; + title_hbox->align_cross = Widget::CENTER; title_hbox->set_margin_for_crt(0, 0, 1, 0); title_hbox->set_margin_for_sdl(0, 0, 20, 0); vbox->add_child(move(title_hbox)); @@ -3190,7 +3190,7 @@ void describe_spell(spell_type spell, const monster_info *mon_owner, title->set_margin_for_sdl(0, 0, 0, 10); title_hbox->add_child(move(title)); - title_hbox->align_items = Widget::CENTER; + title_hbox->align_cross = Widget::CENTER; title_hbox->set_margin_for_crt(0, 0, 1, 0); title_hbox->set_margin_for_sdl(0, 0, 20, 0); vbox->add_child(move(title_hbox)); @@ -4556,7 +4556,7 @@ int describe_monsters(const monster_info &mi, bool force_seen, title->set_margin_for_sdl(0, 0, 0, 10); title_hbox->add_child(move(title)); - title_hbox->align_items = Widget::CENTER; + title_hbox->align_cross = Widget::CENTER; title_hbox->set_margin_for_crt(0, 0, 1, 0); title_hbox->set_margin_for_sdl(0, 0, 20, 0); vbox->add_child(move(title_hbox)); diff --git a/crawl-ref/source/end.cc b/crawl-ref/source/end.cc index 53a3eb1441c8..e298f3e22c5e 100644 --- a/crawl-ref/source/end.cc +++ b/crawl-ref/source/end.cc @@ -478,7 +478,7 @@ NORETURN void end_game(scorefile_entry &se) #endif string goodbye_title = make_stringf("Goodbye, %s.", you.your_name.c_str()); title_hbox->add_child(make_shared(goodbye_title)); - title_hbox->align_items = Widget::CENTER; + title_hbox->align_cross = Widget::CENTER; title_hbox->set_margin_for_sdl(0, 0, 20, 0); title_hbox->set_margin_for_crt(0, 0, 1, 0); diff --git a/crawl-ref/source/hints.cc b/crawl-ref/source/hints.cc index ae2c30224704..89ac8f5f6214 100644 --- a/crawl-ref/source/hints.cc +++ b/crawl-ref/source/hints.cc @@ -182,7 +182,7 @@ void pick_hints(newgame_def& choice) auto prompt_ui = make_shared(formatted_string::parse_string(prompt)); auto vbox = make_shared(Box::VERT); - vbox->align_items = Widget::Align::STRETCH; + vbox->align_cross = Widget::Align::STRETCH; vbox->add_child(prompt_ui); auto main_items = make_shared(true, 1, 3); @@ -197,7 +197,7 @@ void pick_hints(newgame_def& choice) #ifdef USE_TILE_LOCAL auto hbox = make_shared(Box::HORZ); - hbox->align_items = Widget::Align::CENTER; + hbox->align_cross = Widget::Align::CENTER; dolls_data doll; newgame_def tng = choice; _fill_newgame_choice_for_hints(tng, static_cast(i)); diff --git a/crawl-ref/source/loading-screen.cc b/crawl-ref/source/loading-screen.cc index 163d378d2a62..1d6231503b4f 100644 --- a/crawl-ref/source/loading-screen.cc +++ b/crawl-ref/source/loading-screen.cc @@ -67,7 +67,7 @@ void loading_screen_open() loading_text = make_shared(); loading_text->set_margin_for_sdl(15, 0, 0, 0); auto vbox = make_shared(Widget::VERT); - vbox->align_items = Widget::CENTER; + vbox->align_cross = Widget::CENTER; vbox->add_child(move(splash)); vbox->add_child(loading_text); FontWrapper *font = tiles.get_crt_font(); diff --git a/crawl-ref/source/menu.cc b/crawl-ref/source/menu.cc index 2aeb99febd05..a53a6eb9d407 100644 --- a/crawl-ref/source/menu.cc +++ b/crawl-ref/source/menu.cc @@ -798,7 +798,7 @@ Menu::Menu(int _flags, const string& tagname, KeymapContext kmc) m_ui.title = make_shared(); m_ui.more = make_shared(); m_ui.vbox = make_shared(Widget::VERT); - m_ui.vbox->align_items = Widget::STRETCH; + m_ui.vbox->align_cross = Widget::STRETCH; m_ui.title->set_margin_for_sdl(0, 0, 10, 0); m_ui.more->set_margin_for_sdl(10, 0, 0, 0); @@ -808,7 +808,7 @@ Menu::Menu(int _flags, const string& tagname, KeymapContext kmc) m_ui.vbox->add_child(m_ui.scroller); #else auto scroller_wrap = make_shared(Widget::VERT, Box::Expand::EXPAND_V); - scroller_wrap->align_items = Widget::STRETCH; + scroller_wrap->align_cross = Widget::STRETCH; scroller_wrap->add_child(m_ui.scroller); m_ui.vbox->add_child(scroller_wrap); #endif diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 09b744622265..ba504a4f5f51 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -396,7 +396,7 @@ static bool _reroll_random(newgame_def& ng) #endif #endif title_hbox->add_child(make_shared(prompt)); - title_hbox->align_items = Widget::CENTER; + title_hbox->align_cross = Widget::CENTER; title_hbox->set_margin_for_sdl(0, 0, 20, 0); title_hbox->set_margin_for_crt(0, 0, 1, 0); @@ -624,7 +624,7 @@ static void _choose_name(newgame_def& ng, newgame_def& choice) #endif #endif title_hbox->add_child(make_shared(title)); - title_hbox->align_items = Widget::CENTER; + title_hbox->align_cross = Widget::CENTER; title_hbox->set_margin_for_sdl(0, 0, 20, 0); title_hbox->set_margin_for_crt(0, 0, 1, 0); @@ -660,7 +660,7 @@ static void _choose_name(newgame_def& ng, newgame_def& choice) formatted_string("That's a silly name!", LIGHTRED)); err->set_margin_for_sdl(0, 0, 0, 10); auto box = make_shared(Box::HORZ); - box->align_items = Widget::CENTER; + box->align_cross = Widget::CENTER; box->add_child(err); ok_switcher->add_child(btn); @@ -1075,7 +1075,7 @@ class UINewGameMenu : public Widget { m_vbox = make_shared(Box::VERT); m_vbox->_set_parent(this); - m_vbox->align_items = Widget::Align::STRETCH; + m_vbox->align_cross = Widget::Align::STRETCH; welcome.textcolour(BROWN); welcome.cprintf("%s", _welcome(m_ng).c_str()); @@ -1174,8 +1174,8 @@ class UINewGameMenu : public Widget #ifdef USE_TILE auto hbox = make_shared(Box::HORZ); - hbox->align_items = Widget::Align::CENTER; - hbox->justify_items = Widget::Align::STRETCH; + hbox->align_cross = Widget::Align::CENTER; + hbox->align_main = Widget::Align::STRETCH; auto tile = make_shared(); tile->set_tile(item_tile); tile->set_margin_for_sdl(0, 6, 0, 0); @@ -1701,7 +1701,7 @@ static void _construct_weapon_menu(const newgame_def& ng, const auto& choice = choices[i]; auto hbox = make_shared(Box::HORZ); - hbox->align_items = Widget::Align::CENTER; + hbox->align_cross = Widget::Align::CENTER; hbox->set_margin_for_sdl(2, 10, 2, 2); #ifdef USE_TILE @@ -1752,7 +1752,7 @@ static void _construct_weapon_menu(const newgame_def& ng, label->set_text(formatted_string(text, fg)); - hbox->justify_items = Widget::Align::STRETCH; + hbox->align_main = Widget::Align::STRETCH; string apt_text = make_stringf("(%+d apt)", species_apt(choice.skill, ng.species)); auto suffix = make_shared(formatted_string(apt_text, fg)); @@ -1819,12 +1819,12 @@ static bool _prompt_weapon(const newgame_def& ng, newgame_def& ng_choice, #endif auto title = make_shared(formatted_string(_welcome(ng), BROWN)); title_hbox->add_child(title); - title_hbox->align_items = Widget::CENTER; + title_hbox->align_cross = Widget::CENTER; title_hbox->set_margin_for_sdl(0, 0, 20, 0); title_hbox->set_margin_for_crt(0, 0, 1, 0); auto vbox = make_shared(Box::VERT); - vbox->align_items = Widget::Align::STRETCH; + vbox->align_cross = Widget::Align::STRETCH; vbox->add_child(title_hbox); auto prompt = make_shared(formatted_string("You have a choice of weapons.", CYAN)); vbox->add_child(prompt); @@ -2128,7 +2128,7 @@ static void _construct_gamemode_map_menu(const mapref_vector& maps, #ifdef USE_TILE auto hbox = make_shared(Box::HORZ); - hbox->align_items = Widget::Align::CENTER; + hbox->align_cross = Widget::Align::CENTER; auto tile = make_shared(); tile->set_tile(tile_for_map_name(map_name)); tile->set_margin_for_sdl(0, 6, 0, 0); @@ -2222,7 +2222,7 @@ static void _prompt_gamemode_map(newgame_def& ng, newgame_def& ng_choice, ng_choice.type == GAME_TYPE_TUTORIAL ? "lessons" : "maps"); auto vbox = make_shared(Box::VERT); - vbox->align_items = Widget::Align::STRETCH; + vbox->align_cross = Widget::Align::STRETCH; vbox->add_child(make_shared(welcome)); auto main_items = make_shared(true, 1, maps.size()); diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index 63a5acbc0b0f..92628acd8201 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -405,7 +405,7 @@ static void _construct_game_modes_menu(shared_ptr& container) #ifdef USE_TILE_LOCAL auto hbox = make_shared(Box::HORZ); - hbox->align_items = Widget::Align::CENTER; + hbox->align_cross = Widget::Align::CENTER; auto tile = make_shared(); tile->set_tile(tile_def(tileidx_gametype(entry.id), TEX_GUI)); tile->set_margin_for_sdl(0, 6, 0, 0); @@ -435,7 +435,7 @@ static shared_ptr _make_newgame_button(shared_ptr& contai #ifdef USE_TILE_LOCAL auto hbox = make_shared(Box::HORZ); - hbox->align_items = Widget::Align::CENTER; + hbox->align_cross = Widget::Align::CENTER; hbox->add_child(label); label->set_margin_for_sdl(0,0,0,TILE_Y+6); hbox->min_size().height = TILE_Y; @@ -459,7 +459,7 @@ static void _construct_save_games_menu(shared_ptr& container, for (unsigned int i = 0; i < chars.size(); ++i) { auto hbox = make_shared(Box::HORZ); - hbox->align_items = Widget::Align::CENTER; + hbox->align_cross = Widget::Align::CENTER; #ifdef USE_TILE_LOCAL auto tile = make_shared(chars.at(i).doll); @@ -535,7 +535,7 @@ class UIStartupMenu : public Widget m_root = make_shared(Box::VERT); m_root->_set_parent(this); - m_root->align_items = Widget::Align::STRETCH; + m_root->align_cross = Widget::Align::STRETCH; auto about = make_shared(opening_screen()); about->set_margin_for_crt(0, 0, 1, 0); diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 5240807ab353..7817dacba40e 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -326,7 +326,7 @@ vector Box::layout_main_axis(vector& ch_psz, int main_sz) { ch_sz[i] = ch_psz[i].min; extra -= ch_psz[i].min; - if (justify_items == Align::STRETCH) + if (align_main == Align::STRETCH) ch_psz[i].nat = INT_MAX; } ASSERT(extra >= 0); @@ -364,7 +364,7 @@ vector Box::layout_cross_axis(vector& ch_psz, int cross_sz) auto const& child = m_children[i]; // find the child's size on the cross axis bool stretch = child->align_self == STRETCH ? true - : align_items == STRETCH; + : align_cross == STRETCH; ch_sz[i] = stretch ? cross_sz : min(max(ch_psz[i].min, cross_sz), ch_psz[i].nat); } @@ -424,7 +424,7 @@ void Box::_allocate_region() // main axis offset int mo; - switch (justify_items) + switch (align_main) { case Widget::START: mo = 0; break; case Widget::CENTER: mo = extra_main_space/2; break; @@ -443,7 +443,7 @@ void Box::_allocate_region() auto const& child = m_children[i]; Align child_align = child->align_self ? child->align_self - : align_items ? align_items + : align_cross ? align_cross : Align::START; int xo; switch (child_align) @@ -2322,7 +2322,7 @@ progress_popup::progress_popup(string title, int width) : position(0), bar_width(width), no_more(crawl_state.show_more_prompt, false) { auto container = make_shared(Widget::VERT); - container->align_items = Widget::CENTER; + container->align_cross = Widget::CENTER; #ifndef USE_TILE_LOCAL // Center the popup in console. // if webtiles browser ever uses this property, then this will probably diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index b837a9ab1033..35efe7756475 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -328,7 +328,6 @@ class ContainerVec : public Container // Box widget: similar to the CSS flexbox (without wrapping) // - Lays its children out in either a row or a column // - Extra space is allocated according to each child's flex_grow property -// - align and justify properties work like flexbox's class Box : public ContainerVec { @@ -350,8 +349,8 @@ class Box : public ContainerVec virtual ~Box() {} void add_child(shared_ptr child); bool horz; - Widget::Align justify_items = START; - Widget::Align align_items = UNSET; + Widget::Align align_main = START; + Widget::Align align_cross = UNSET; virtual void _render() override; virtual SizeReq _get_preferred_size(Direction dim, int prosp_width) override; From 83d332edcdc2d2d6db69c07cf36c1011521a775c Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Wed, 9 Oct 2019 01:10:45 +0800 Subject: [PATCH 796/864] Make ui::Box member private --- crawl-ref/source/ui.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index 35efe7756475..dfbfc074d923 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -348,7 +348,6 @@ class Box : public ContainerVec }; virtual ~Box() {} void add_child(shared_ptr child); - bool horz; Widget::Align align_main = START; Widget::Align align_cross = UNSET; @@ -357,6 +356,8 @@ class Box : public ContainerVec virtual void _allocate_region() override; protected: + bool horz; + vector layout_main_axis(vector& ch_psz, int main_sz); vector layout_cross_axis(vector& ch_psz, int cross_sz); }; From 6c541cf830b7ba0bb96ee2cf2fa39f8b5ed614d1 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Wed, 9 Oct 2019 01:19:36 +0800 Subject: [PATCH 797/864] Remove ui::Widget align_self property This only did anything inside a box widget, and was confusingly named (does it refer to main- or cross-axis alignment?). It seems to be unnecessary, although relying on the parent stretch property is probably slightly brittle. IIRC Flutter allows the parent to store a small amount of data on child widgets; perhaps adding a Box::set_child_cross_alignment() that utilizes this method will work well. --- crawl-ref/source/describe-god.cc | 3 ++- crawl-ref/source/hiscores.cc | 2 +- crawl-ref/source/mutation.cc | 2 +- crawl-ref/source/scroller.cc | 6 +++--- crawl-ref/source/tilereg-doll.cc | 2 +- crawl-ref/source/ui.cc | 10 ++-------- crawl-ref/source/ui.h | 6 ++---- 7 files changed, 12 insertions(+), 19 deletions(-) diff --git a/crawl-ref/source/describe-god.cc b/crawl-ref/source/describe-god.cc index b8f451514449..4741f21d8b9d 100644 --- a/crawl-ref/source/describe-god.cc +++ b/crawl-ref/source/describe-god.cc @@ -1090,6 +1090,7 @@ static void build_partial_god_ui(god_type which_god, shared_ptr& popu topline += formatted_string(uppercase_first(god_name(which_god, true))); auto vbox = make_shared(Widget::VERT); + vbox->align_cross = Widget::STRETCH; auto title_hbox = make_shared(Widget::HORZ); #ifdef USE_TILE @@ -1103,8 +1104,8 @@ static void build_partial_god_ui(god_type which_god, shared_ptr& popu title->set_margin_for_sdl(0, 0, 0, 16); title_hbox->add_child(move(title)); + title_hbox->align_main = Widget::CENTER; title_hbox->align_cross = Widget::CENTER; - title_hbox->align_self = Widget::CENTER; vbox->add_child(move(title_hbox)); desc_sw = make_shared(); diff --git a/crawl-ref/source/hiscores.cc b/crawl-ref/source/hiscores.cc index 170540303ccb..5f993f80edc9 100644 --- a/crawl-ref/source/hiscores.cc +++ b/crawl-ref/source/hiscores.cc @@ -411,10 +411,10 @@ UIHiscoresMenu::UIHiscoresMenu() { m_root = make_shared(Widget::VERT); m_root->_set_parent(this); + m_root->align_cross = Widget::CENTER; auto title = make_shared(formatted_string( "Dungeon Crawl Stone Soup: High Scores", YELLOW)); - title->align_self = Widget::CENTER; title->set_margin_for_sdl(0, 0, 20, 0); m_description = make_shared(string(9, '\n')); diff --git a/crawl-ref/source/mutation.cc b/crawl-ref/source/mutation.cc index 408041dbf312..6610749fd70f 100644 --- a/crawl-ref/source/mutation.cc +++ b/crawl-ref/source/mutation.cc @@ -843,10 +843,10 @@ void display_mutations() trim_string_right(mutation_s); auto vbox = make_shared(Widget::VERT); + vbox->align_cross = Widget::CENTER; const char *title_text = "Innate Abilities, Weirdness & Mutations"; auto title = make_shared(formatted_string(title_text, WHITE)); - title->align_self = Widget::CENTER; vbox->add_child(move(title)); auto switcher = make_shared(); diff --git a/crawl-ref/source/scroller.cc b/crawl-ref/source/scroller.cc index c6c890939014..eaf8ad48dd6d 100644 --- a/crawl-ref/source/scroller.cc +++ b/crawl-ref/source/scroller.cc @@ -71,6 +71,9 @@ void formatted_scroller::scroll_to_end() int formatted_scroller::show() { auto vbox = make_shared(Widget::VERT); +#ifdef USE_TILE_LOCAL + vbox->align_cross = Widget::Align::CENTER; +#endif if (!m_title.empty()) { @@ -78,9 +81,6 @@ int formatted_scroller::show() title->set_text(m_title); title->set_margin_for_crt(0, 0, 1, 0); title->set_margin_for_sdl(0, 0, 20, 0); -#ifdef USE_TILE_LOCAL - title->align_self = Widget::Align::CENTER; -#endif vbox->add_child(move(title)); } diff --git a/crawl-ref/source/tilereg-doll.cc b/crawl-ref/source/tilereg-doll.cc index 37892429d0ff..93d3ec46c604 100644 --- a/crawl-ref/source/tilereg-doll.cc +++ b/crawl-ref/source/tilereg-doll.cc @@ -387,8 +387,8 @@ void DollEditRegion::run() auto doll_ui = make_shared(this); auto vbox = make_shared(Widget::VERT); + vbox->align_cross = Widget::CENTER; auto title = make_shared(formatted_string("Doll Editor", YELLOW)); - title->align_self = Widget::CENTER; title->set_margin_for_sdl(0, 0, 20, 0); vbox->add_child(move(title)); vbox->add_child(doll_ui); diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 7817dacba40e..c87842dcc5bf 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -361,10 +361,7 @@ vector Box::layout_cross_axis(vector& ch_psz, int cross_sz) for (size_t i = 0; i < m_children.size(); i++) { - auto const& child = m_children[i]; - // find the child's size on the cross axis - bool stretch = child->align_self == STRETCH ? true - : align_cross == STRETCH; + const bool stretch = align_cross == STRETCH; ch_sz[i] = stretch ? cross_sz : min(max(ch_psz[i].min, cross_sz), ch_psz[i].nat); } @@ -441,10 +438,7 @@ void Box::_allocate_region() // cross axis offset int extra_cross_space = horz ? m_region.height - ch[i] : m_region.width - cw[i]; - auto const& child = m_children[i]; - Align child_align = child->align_self ? child->align_self - : align_cross ? align_cross - : Align::START; + const Align child_align = align_cross; int xo; switch (child_align) { diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index dfbfc074d923..f2bcc34302dc 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -126,8 +126,7 @@ class Widget : public enable_shared_from_this { public: enum Align { - UNSET = 0, - START, + START = 0, END, CENTER, STRETCH, @@ -141,7 +140,6 @@ class Widget : public enable_shared_from_this virtual ~Widget(); int flex_grow = 1; - Align align_self = UNSET; bool expand_h = false, expand_v = false; bool shrink_h = false, shrink_v = false; Region get_region() const { return m_region; } @@ -349,7 +347,7 @@ class Box : public ContainerVec virtual ~Box() {} void add_child(shared_ptr child); Widget::Align align_main = START; - Widget::Align align_cross = UNSET; + Widget::Align align_cross = START; virtual void _render() override; virtual SizeReq _get_preferred_size(Direction dim, int prosp_width) override; From 6733c4489b7f62fc4a5df06376e5f7b8a546c7c9 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Wed, 9 Oct 2019 01:33:12 +0800 Subject: [PATCH 798/864] Make text widget members private We also add size request invalidation, just in case someone is doing something interesting... --- crawl-ref/source/command.cc | 2 +- crawl-ref/source/decks.cc | 2 +- crawl-ref/source/describe-god.cc | 2 +- crawl-ref/source/describe.cc | 10 +++++----- crawl-ref/source/hints.cc | 2 +- crawl-ref/source/mutation.cc | 2 +- crawl-ref/source/outer-menu.cc | 2 +- crawl-ref/source/scroller.cc | 2 +- crawl-ref/source/startup.cc | 2 +- crawl-ref/source/ui.h | 22 +++++++++++++++++++--- 10 files changed, 32 insertions(+), 16 deletions(-) diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc index 2765fedaf423..82c071755b4c 100644 --- a/crawl-ref/source/command.cc +++ b/crawl-ref/source/command.cc @@ -232,7 +232,7 @@ static void _print_version() auto scroller = make_shared(); auto content = formatted_string::parse_string(feats + "\n\n" + changes); auto text = make_shared(move(content)); - text->wrap_text = true; + text->set_wrap_text(true); scroller->set_child(move(text)); vbox->add_child(scroller); diff --git a/crawl-ref/source/decks.cc b/crawl-ref/source/decks.cc index 72fcd0f15442..c6c2319496cf 100644 --- a/crawl-ref/source/decks.cc +++ b/crawl-ref/source/decks.cc @@ -417,7 +417,7 @@ static void _describe_cards(CrawlVector& cards) vbox->add_child(move(title_hbox)); auto text = make_shared(desc); - text->wrap_text = true; + text->set_wrap_text(true); vbox->add_child(move(text)); #ifdef USE_TILE_WEB diff --git a/crawl-ref/source/describe-god.cc b/crawl-ref/source/describe-god.cc index 4741f21d8b9d..86a5afdc9a64 100644 --- a/crawl-ref/source/describe-god.cc +++ b/crawl-ref/source/describe-god.cc @@ -1151,7 +1151,7 @@ static void build_partial_god_ui(god_type which_god, shared_ptr& popu auto scroller = make_shared(); auto text = make_shared(desc.trim()); - text->wrap_text = true; + text->set_wrap_text(true); scroller->set_child(text); desc_sw->add_child(move(scroller)); diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index 831c6fdb0008..d005b780f777 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -145,7 +145,7 @@ int show_description(const describe_info &inf, const tile_def *tile) auto scroller = make_shared(); auto fs = formatted_string::parse_string(trimmed_string(desc)); auto text = make_shared(fs); - text->wrap_text = true; + text->set_wrap_text(true); scroller->set_child(text); switcher->add_child(move(scroller)); } @@ -2351,7 +2351,7 @@ void describe_feature_wide(const coord_def& pos) text->set_margin_for_sdl(0, 0, 20, 0); text->set_margin_for_crt(0, 0, 1, 0); } - text->wrap_text = true; + text->set_wrap_text(true); vbox->add_child(text); } } @@ -2709,7 +2709,7 @@ bool describe_item(item_def &item, function fixup_desc) auto scroller = make_shared(); auto text = make_shared(fs_desc.trim()); - text->wrap_text = true; + text->set_wrap_text(true); scroller->set_child(text); vbox->add_child(scroller); @@ -3198,7 +3198,7 @@ void describe_spell(spell_type spell, const monster_info *mon_owner, auto scroller = make_shared(); auto text = make_shared(); text->set_text(formatted_string::parse_string(desc)); - text->wrap_text = true; + text->set_wrap_text(true); scroller->set_child(move(text)); vbox->add_child(scroller); @@ -4590,7 +4590,7 @@ int describe_monsters(const monster_info &mi, bool force_seen, const formatted_string *content[2] = { &desc, "e }; auto scroller = make_shared(); auto text = make_shared(content[i]->trim()); - text->wrap_text = true; + text->set_wrap_text(true); scroller->set_child(text); desc_sw->add_child(move(scroller)); diff --git a/crawl-ref/source/hints.cc b/crawl-ref/source/hints.cc index 89ac8f5f6214..88434fe6544d 100644 --- a/crawl-ref/source/hints.cc +++ b/crawl-ref/source/hints.cc @@ -416,7 +416,7 @@ void hints_starting_screen() trim_string(text); auto prompt_ui = make_shared(formatted_string::parse_string(text)); - prompt_ui->wrap_text = true; + prompt_ui->set_wrap_text(true); #ifdef USE_TILE_LOCAL prompt_ui->max_size().width = 800; #else diff --git a/crawl-ref/source/mutation.cc b/crawl-ref/source/mutation.cc index 6610749fd70f..761c9a7a79ba 100644 --- a/crawl-ref/source/mutation.cc +++ b/crawl-ref/source/mutation.cc @@ -858,7 +858,7 @@ void display_mutations() auto scroller = make_shared(); auto text = make_shared(formatted_string::parse_string( descs[static_cast(i)])); - text->wrap_text = true; + text->set_wrap_text(true); scroller->set_child(text); switcher->add_child(move(scroller)); } diff --git a/crawl-ref/source/outer-menu.cc b/crawl-ref/source/outer-menu.cc index d9a116f77f10..2e6ce829abf8 100644 --- a/crawl-ref/source/outer-menu.cc +++ b/crawl-ref/source/outer-menu.cc @@ -282,7 +282,7 @@ void OuterMenu::add_button(shared_ptr btn, int x, int y) if (descriptions) { auto desc_text = make_shared(formatted_string(btn->description, WHITE)); - desc_text->wrap_text = true; + desc_text->set_wrap_text(true); descriptions->add_child(move(desc_text)); m_description_indexes[y*m_width + x] = descriptions->num_children()-1; } diff --git a/crawl-ref/source/scroller.cc b/crawl-ref/source/scroller.cc index eaf8ad48dd6d..d9423dd3af95 100644 --- a/crawl-ref/source/scroller.cc +++ b/crawl-ref/source/scroller.cc @@ -97,7 +97,7 @@ int formatted_scroller::show() formatted_string c = formatted_string::parse_string(contents.to_colour_string()); text->set_text(c); text->set_highlight_pattern(highlight, true); - text->wrap_text = !(m_flags & FS_PREWRAPPED_TEXT); + text->set_wrap_text(!(m_flags & FS_PREWRAPPED_TEXT)); m_scroller->set_child(text); vbox->add_child(m_scroller); diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index 92628acd8201..ba6304ae8dbb 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -471,7 +471,7 @@ static void _construct_save_games_menu(shared_ptr& container, auto text = chars.at(i).short_desc(); bool wiz = strip_suffix(text, " (WIZ)"); auto label = make_shared(formatted_string(text, fg)); - label->ellipsize = true; + label->set_ellipsize(true); #ifdef USE_TILE_LOCAL label->max_size().height = tiles.get_crt_font()->char_height(); #else diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index f2bcc34302dc..e5a54dde58bc 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -389,16 +389,32 @@ class Text : public Widget virtual SizeReq _get_preferred_size(Direction dim, int prosp_width) override; virtual void _allocate_region() override; - bool wrap_text = false; - bool ellipsize = false; - #ifndef USE_TILE_LOCAL void set_bg_colour(COLOURS colour); #endif + void set_wrap_text(bool _wrap_text) + { + if (wrap_text == _wrap_text) + return; + wrap_text = _wrap_text; + _invalidate_sizereq(); + }; + + void set_ellipsize(bool _ellipsize) + { + if (ellipsize == _ellipsize) + return; + ellipsize = _ellipsize; + _invalidate_sizereq(); + }; + protected: void wrap_text_to_size(int width, int height); + bool wrap_text = false; + bool ellipsize = false; + formatted_string m_text; #ifdef USE_TILE_LOCAL struct brkpt { unsigned int op, line; }; From ad5c9ccc1d3bb7aae20c7d970926c877ea0f62fe Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Wed, 9 Oct 2019 02:43:36 +0800 Subject: [PATCH 799/864] Remove UI_CRT and other UI gunk tiles_crt_popup() shouldn't be necessary, since these UIs don't use any cgotoxy/cprintf calls themselves. I'm not exactly sure of the purpose of the set_ui_state() calls here, but they shouldn't be required either for those UIs to work correctly. In general, we're trying to remove tiles_crt_popup() entirely, as it was an temporary hack used to wrap old-style UIs. As of this commit, the last remaining such UI is the skill menu UI. --- crawl-ref/source/arena.cc | 9 --------- crawl-ref/source/end.cc | 5 ----- crawl-ref/source/lookup-help.cc | 4 ---- crawl-ref/source/newgame.cc | 8 -------- crawl-ref/source/startup.cc | 3 --- crawl-ref/source/tileweb.cc | 3 --- crawl-ref/source/tileweb.h | 1 - 7 files changed, 33 deletions(-) diff --git a/crawl-ref/source/arena.cc b/crawl-ref/source/arena.cc index 0cbcd4786c87..f72a6ad90d1d 100644 --- a/crawl-ref/source/arena.cc +++ b/crawl-ref/source/arena.cc @@ -121,11 +121,6 @@ static void _results_popup(string msg, bool error=false) // TODO: shared code here with end.cc linebreak_string(msg, 79); -#ifdef USE_TILE_WEB - tiles_crt_popup show_as_popup; - tiles.set_ui_state(UI_CRT); -#endif - if (error) { msg = string("Arena error:\n\n") @@ -1468,10 +1463,6 @@ static void _init_arena() static void _choose_arena_teams(newgame_def& choice, const string &default_arena_teams) { -#ifdef USE_TILE_WEB - tiles_crt_popup show_as_popup; -#endif - if (!choice.arena_teams.empty()) return; arena::skipped_arena_ui = false; diff --git a/crawl-ref/source/end.cc b/crawl-ref/source/end.cc index e298f3e22c5e..2366a3ae897a 100644 --- a/crawl-ref/source/end.cc +++ b/crawl-ref/source/end.cc @@ -117,11 +117,6 @@ bool fatal_error_notification(string error_msg) return false; #if (!defined(DGAMELAUNCH)) || defined(DGL_PAUSE_AFTER_ERROR) -#ifdef USE_TILE_WEB - tiles_crt_popup show_as_popup; - tiles.set_ui_state(UI_CRT); -#endif - // TODO: better formatting, maybe use a formatted_scroller? // Escape '<'. // NOTE: This assumes that the error message doesn't contain diff --git a/crawl-ref/source/lookup-help.cc b/crawl-ref/source/lookup-help.cc index e87883ee4260..12c6879066f5 100644 --- a/crawl-ref/source/lookup-help.cc +++ b/crawl-ref/source/lookup-help.cc @@ -1396,10 +1396,6 @@ static int _lookup_prompt() lookup_type_prompts.c_str()); linebreak_string(prompt, 72); -#ifdef USE_TILE_WEB - tiles_crt_popup show_as_popup; - tiles.set_ui_state(UI_CRT); -#endif auto prompt_ui = make_shared(formatted_string::parse_string(prompt)); bool done = false; diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index ba504a4f5f51..c5d1d200fafd 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -913,14 +913,6 @@ static void _choose_seed(newgame_def& ng, newgame_def& choice, bool choose_game(newgame_def& ng, newgame_def& choice, const newgame_def& defaults) { -#ifdef USE_TILE_WEB - tiles.set_ui_state(UI_CRT); -#endif - - clrscr(); - - textcolour(LIGHTGREY); - ng.name = choice.name; ng.type = choice.type; ng.map = choice.map; diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index ba6304ae8dbb..8191d1f8b00a 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -915,11 +915,8 @@ static void _show_startup_menu(newgame_def& ng_choice, #if defined(USE_TILE_LOCAL) && defined(TOUCH_UI) wm->show_keyboard(); -#elif defined(USE_TILE_WEB) - tiles_crt_popup show_as_popup; #endif - auto startup_ui = make_shared(ng_choice, defaults); auto popup = make_shared(startup_ui); diff --git a/crawl-ref/source/tileweb.cc b/crawl-ref/source/tileweb.cc index 4fe2dab511c5..a7d2788a4761 100644 --- a/crawl-ref/source/tileweb.cc +++ b/crawl-ref/source/tileweb.cc @@ -1727,9 +1727,6 @@ void TilesFramework::load_dungeon(const crawl_view_buffer &vbuf, m_view_loaded = true; - if (m_ui_state == UI_CRT) - set_ui_state(UI_NORMAL); - m_next_flash_colour = you.flash_colour; if (m_next_flash_colour == BLACK) m_next_flash_colour = viewmap_flash_colour(); diff --git a/crawl-ref/source/tileweb.h b/crawl-ref/source/tileweb.h index ec59d96380e0..4ac7f4a19c6b 100644 --- a/crawl-ref/source/tileweb.h +++ b/crawl-ref/source/tileweb.h @@ -28,7 +28,6 @@ enum WebtilesUIState { UI_INIT = -1, UI_NORMAL, - UI_CRT, UI_VIEW_MAP, }; From fe114aac19228d2d80e9d150fb7a8076fe46a312 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Thu, 10 Oct 2019 17:56:24 +0800 Subject: [PATCH 800/864] Remove ui_ prefix from namespaced functions --- crawl-ref/source/arena.cc | 8 ++++---- crawl-ref/source/menu.cc | 2 +- crawl-ref/source/scroller.cc | 2 +- crawl-ref/source/ui.cc | 6 +++--- crawl-ref/source/ui.h | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/crawl-ref/source/arena.cc b/crawl-ref/source/arena.cc index f72a6ad90d1d..5caf5e753c62 100644 --- a/crawl-ref/source/arena.cc +++ b/crawl-ref/source/arena.cc @@ -872,7 +872,7 @@ namespace arena do_respawn(faction_a); do_respawn(faction_b); balance_spawners(); - ui_delay(Options.view_delay); + ui::delay(Options.view_delay); clear_messages(); ASSERT(you.pet_target == MHITNOT); } @@ -882,7 +882,7 @@ namespace arena if (contest_cancelled) { mpr("Canceled contest at user request"); - ui_delay(Options.view_delay); + ui::delay(Options.view_delay); clear_messages(); return; } @@ -1070,11 +1070,11 @@ namespace arena do_fight(); if (trials_done < total_trials) - ui_delay(Options.view_delay * 5); + ui::delay(Options.view_delay * 5); } while (!contest_cancelled && trials_done < total_trials); - ui_delay(Options.view_delay * 5); + ui::delay(Options.view_delay * 5); if (total_trials > 0) { diff --git a/crawl-ref/source/menu.cc b/crawl-ref/source/menu.cc index a53a6eb9d407..abbee17dcc1b 100644 --- a/crawl-ref/source/menu.cc +++ b/crawl-ref/source/menu.cc @@ -2081,7 +2081,7 @@ void Menu::webtiles_scroll(int first) { m_ui.scroller->set_scroll(item_y); webtiles_update_scroll_pos(); - ui_force_render(); + ui::force_render(); } } diff --git a/crawl-ref/source/scroller.cc b/crawl-ref/source/scroller.cc index d9423dd3af95..cc55b2364eea 100644 --- a/crawl-ref/source/scroller.cc +++ b/crawl-ref/source/scroller.cc @@ -209,5 +209,5 @@ void recv_formatted_scroller_scroll(int line) // XXX: since the scroll event from webtiles is not delivered by the event // pumping loop in ui::pump_events, the UI system won't automatically draw // any changes for console spectators, so we need to force a redraw here. - ui_force_render(); + ui::force_render(); } diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index c87842dcc5bf..9135723acf28 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -2053,14 +2053,14 @@ static void remap_key(wm_event &event) ASSERT(event.key.keysym.sym != -1); } -void ui_force_render() +void force_render() { ui_root.layout(); ui_root.needs_paint = true; ui_root.render(); } -void ui_render() +void render() { ui_root.layout(); ui_root.render(); @@ -2255,7 +2255,7 @@ int getch(KeymapContext km) return key; } -void ui_delay(unsigned int ms) +void delay(unsigned int ms) { if (crawl_state.disables[DIS_DELAY]) ms = 0; diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index e5a54dde58bc..0a3d79c241a5 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -698,9 +698,9 @@ void run_layout(shared_ptr root, const bool& done); bool has_layout(); NORETURN void restart_layout(); int getch(KeymapContext km = KMC_DEFAULT); -void ui_force_render(); -void ui_render(); -void ui_delay(unsigned int ms); +void force_render(); +void render(); +void delay(unsigned int ms); void push_scissor(Region scissor); void pop_scissor(); From bc6939d5a147dc68cb0c2d55245fbac6f30034e3 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Fri, 11 Oct 2019 00:02:05 +0800 Subject: [PATCH 801/864] Fix minimap stretching on local tiles --- crawl-ref/source/tilesdl.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/tilesdl.cc b/crawl-ref/source/tilesdl.cc index e7ae21d08274..4a9b9aac4458 100644 --- a/crawl-ref/source/tilesdl.cc +++ b/crawl-ref/source/tilesdl.cc @@ -1153,9 +1153,11 @@ void TilesFramework::autosize_minimap() const int vert = (m_statcol_bottom - (m_region_map->sy ? m_region_map->sy : m_statcol_top) - map_margin * 2) / GYM; - m_region_map->dx = m_region_map->dy = min(horiz, vert); + + int sz = min(horiz, vert); if (Options.tile_map_pixels) - m_region_map->dx = min(m_region_map->dx, Options.tile_map_pixels); + sz = min(sz, Options.tile_map_pixels); + m_region_map->dx = m_region_map->dy = sz; } void TilesFramework::place_minimap() From 410b6b9510f48e4105fbf8158e20ef88a122be04 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Fri, 11 Oct 2019 00:48:47 +0800 Subject: [PATCH 802/864] Revert "Remove UI_CRT and other UI gunk" Reverted due to https://crawl.develz.org/mantis/view.php?id=12090 This reverts commit ad5c9ccc1d3bb7aae20c7d970926c877ea0f62fe. --- crawl-ref/source/arena.cc | 9 +++++++++ crawl-ref/source/end.cc | 5 +++++ crawl-ref/source/lookup-help.cc | 4 ++++ crawl-ref/source/newgame.cc | 8 ++++++++ crawl-ref/source/startup.cc | 3 +++ crawl-ref/source/tileweb.cc | 3 +++ crawl-ref/source/tileweb.h | 1 + 7 files changed, 33 insertions(+) diff --git a/crawl-ref/source/arena.cc b/crawl-ref/source/arena.cc index 5caf5e753c62..a02e45d95db4 100644 --- a/crawl-ref/source/arena.cc +++ b/crawl-ref/source/arena.cc @@ -121,6 +121,11 @@ static void _results_popup(string msg, bool error=false) // TODO: shared code here with end.cc linebreak_string(msg, 79); +#ifdef USE_TILE_WEB + tiles_crt_popup show_as_popup; + tiles.set_ui_state(UI_CRT); +#endif + if (error) { msg = string("Arena error:\n\n") @@ -1463,6 +1468,10 @@ static void _init_arena() static void _choose_arena_teams(newgame_def& choice, const string &default_arena_teams) { +#ifdef USE_TILE_WEB + tiles_crt_popup show_as_popup; +#endif + if (!choice.arena_teams.empty()) return; arena::skipped_arena_ui = false; diff --git a/crawl-ref/source/end.cc b/crawl-ref/source/end.cc index 2366a3ae897a..e298f3e22c5e 100644 --- a/crawl-ref/source/end.cc +++ b/crawl-ref/source/end.cc @@ -117,6 +117,11 @@ bool fatal_error_notification(string error_msg) return false; #if (!defined(DGAMELAUNCH)) || defined(DGL_PAUSE_AFTER_ERROR) +#ifdef USE_TILE_WEB + tiles_crt_popup show_as_popup; + tiles.set_ui_state(UI_CRT); +#endif + // TODO: better formatting, maybe use a formatted_scroller? // Escape '<'. // NOTE: This assumes that the error message doesn't contain diff --git a/crawl-ref/source/lookup-help.cc b/crawl-ref/source/lookup-help.cc index 12c6879066f5..e87883ee4260 100644 --- a/crawl-ref/source/lookup-help.cc +++ b/crawl-ref/source/lookup-help.cc @@ -1396,6 +1396,10 @@ static int _lookup_prompt() lookup_type_prompts.c_str()); linebreak_string(prompt, 72); +#ifdef USE_TILE_WEB + tiles_crt_popup show_as_popup; + tiles.set_ui_state(UI_CRT); +#endif auto prompt_ui = make_shared(formatted_string::parse_string(prompt)); bool done = false; diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index c5d1d200fafd..ba504a4f5f51 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -913,6 +913,14 @@ static void _choose_seed(newgame_def& ng, newgame_def& choice, bool choose_game(newgame_def& ng, newgame_def& choice, const newgame_def& defaults) { +#ifdef USE_TILE_WEB + tiles.set_ui_state(UI_CRT); +#endif + + clrscr(); + + textcolour(LIGHTGREY); + ng.name = choice.name; ng.type = choice.type; ng.map = choice.map; diff --git a/crawl-ref/source/startup.cc b/crawl-ref/source/startup.cc index 8191d1f8b00a..ba6304ae8dbb 100644 --- a/crawl-ref/source/startup.cc +++ b/crawl-ref/source/startup.cc @@ -915,8 +915,11 @@ static void _show_startup_menu(newgame_def& ng_choice, #if defined(USE_TILE_LOCAL) && defined(TOUCH_UI) wm->show_keyboard(); +#elif defined(USE_TILE_WEB) + tiles_crt_popup show_as_popup; #endif + auto startup_ui = make_shared(ng_choice, defaults); auto popup = make_shared(startup_ui); diff --git a/crawl-ref/source/tileweb.cc b/crawl-ref/source/tileweb.cc index a7d2788a4761..4fe2dab511c5 100644 --- a/crawl-ref/source/tileweb.cc +++ b/crawl-ref/source/tileweb.cc @@ -1727,6 +1727,9 @@ void TilesFramework::load_dungeon(const crawl_view_buffer &vbuf, m_view_loaded = true; + if (m_ui_state == UI_CRT) + set_ui_state(UI_NORMAL); + m_next_flash_colour = you.flash_colour; if (m_next_flash_colour == BLACK) m_next_flash_colour = viewmap_flash_colour(); diff --git a/crawl-ref/source/tileweb.h b/crawl-ref/source/tileweb.h index 4ac7f4a19c6b..ec59d96380e0 100644 --- a/crawl-ref/source/tileweb.h +++ b/crawl-ref/source/tileweb.h @@ -28,6 +28,7 @@ enum WebtilesUIState { UI_INIT = -1, UI_NORMAL, + UI_CRT, UI_VIEW_MAP, }; From 5730307ebe2f3d3f1d929134a28088463a4829ab Mon Sep 17 00:00:00 2001 From: Nikolai Lavsky <3328424+nlavsky@users.noreply.github.com> Date: Tue, 8 Oct 2019 02:02:23 +0300 Subject: [PATCH 803/864] Indicate damage done by Ignite Poison This commit brings Ignite Poison in line with other damaging spells that use exclamation marks to show the amount of damage done. It is a followup for PR #952 and commits 4a3ee908 and 1f260a4b. --- crawl-ref/source/spl-damage.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/spl-damage.cc b/crawl-ref/source/spl-damage.cc index a1425f0bdb4c..697612f79ab3 100644 --- a/crawl-ref/source/spl-damage.cc +++ b/crawl-ref/source/spl-damage.cc @@ -1457,7 +1457,13 @@ static int _ignite_poison_monsters(coord_def where, int pow, actor *agent) return mons_aligned(mon, agent) ? -1 : 1; return mons_aligned(mon, agent) ? -1 * damage : damage; } - simple_monster_message(*mon, " seems to burn from within!"); + + if (you.see_cell(mon->pos())) + { + mprf("%s seems to burn from within%s", + mon->name(DESC_THE).c_str(), + attack_strength_punctuation(damage).c_str()); + } dprf("Dice: %dd%d; Damage: %d", dam_dice.num, dam_dice.size, damage); From 36a6468e2f62d47cdea03cf23f2699458487d95f Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Fri, 11 Oct 2019 00:29:16 +0800 Subject: [PATCH 804/864] Don't scale when rendering lines (Goratrix, 12085) This bug was caused by line buffer rendering correctness depending on the GL scale being the same when buffer packing and when rendering, which was only required due to the way the local tiles minimap worked. The local tiles minimap has been changed to render the boundary box with no scaling, fixing this weird quirk. --- crawl-ref/source/tilebuf.cc | 6 ++---- crawl-ref/source/tilereg-map.cc | 9 +++++---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/crawl-ref/source/tilebuf.cc b/crawl-ref/source/tilebuf.cc index df4e63e87936..343ad31174fd 100644 --- a/crawl-ref/source/tilebuf.cc +++ b/crawl-ref/source/tilebuf.cc @@ -318,10 +318,8 @@ void LineBuffer::add(float pos_sx, float pos_sy, float pos_ex, float pos_ey, void LineBuffer::add_square(float sx, float sy, float ex, float ey, const VColour &col) { - GLW_3VF scale; - glmanager->get_transform(nullptr, &scale); - const float dx = 1.0/scale.x, dy = 1.0/scale.y; - const float tx = dx, ty = dy; + const float dx = 1, dy = 1; // line thickness + const float tx = 1, ty = 1; // shift used to prevent corner overlap add(sx-dx, sy-ty, ex-dx, sy, col); add(ex-tx, sy-dy, ex, ey-dy, col); diff --git a/crawl-ref/source/tilereg-map.cc b/crawl-ref/source/tilereg-map.cc index c3ec854a1c3f..052be20ea5b0 100644 --- a/crawl-ref/source/tilereg-map.cc +++ b/crawl-ref/source/tilereg-map.cc @@ -86,11 +86,11 @@ void MapRegion::pack_buffers() float pos_sx = (m_win_start.x - m_min_gx); float pos_sy = (m_win_start.y - m_min_gy); - float pos_ex = (m_win_end.x - m_min_gx) - 1 / (float)dx; - float pos_ey = (m_win_end.y - m_min_gy) - 1 / (float)dy; + float pos_ex = (m_win_end.x - m_min_gx); + float pos_ey = (m_win_end.y - m_min_gy); - set_transform(); - m_buf_lines.add_square(pos_sx, pos_sy, pos_ex, pos_ey, + set_transform(true); + m_buf_lines.add_square(pos_sx*dx, pos_sy*dy, pos_ex*dx + 1, pos_ey*dy + 1, Options.tile_window_col); } @@ -111,6 +111,7 @@ void MapRegion::render() set_transform(); glmanager->set_scissor(sx, sy, wx, wy); m_buf_map.draw(); + set_transform(true); m_buf_lines.draw(); glmanager->reset_scissor(); } From ddf7d93d986ef9e3e6d73354cc8413909acb9f20 Mon Sep 17 00:00:00 2001 From: Byrel Mitchell Date: Thu, 10 Oct 2019 14:18:07 -0400 Subject: [PATCH 805/864] Adjust OTR to be more turn length invariant. Changed direct damage to use turn length in auts (instead of 10s of auts) for direct damage, and to scale odds of adding a poison stack linearly between 1 and 20 aut turn lengths (instead of 50% odds regardless of turn length.) This has the same results as previous calculation at 10 aut turns, but eliminates the incentive to 'quick-blade-swing' to add poison stacks rapidly. --- crawl-ref/source/mon-ench.cc | 2 +- crawl-ref/source/player-reacts.cc | 6 +----- crawl-ref/source/spl-damage.cc | 17 ++++++++++------- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/crawl-ref/source/mon-ench.cc b/crawl-ref/source/mon-ench.cc index 55db95729783..afedd0a8b7e4 100644 --- a/crawl-ref/source/mon-ench.cc +++ b/crawl-ref/source/mon-ench.cc @@ -1783,7 +1783,7 @@ void monster::apply_enchantment(const mon_enchant &me) break; case ENCH_TOXIC_RADIANCE: - toxic_radiance_effect(this, 1); + toxic_radiance_effect(this, 10); decay_enchantment(en); break; diff --git a/crawl-ref/source/player-reacts.cc b/crawl-ref/source/player-reacts.cc index 07665f00a7fc..ffacaf2eedef 100644 --- a/crawl-ref/source/player-reacts.cc +++ b/crawl-ref/source/player-reacts.cc @@ -799,11 +799,7 @@ static void _decrement_durations() } if (you.duration[DUR_TOXIC_RADIANCE]) - { - const int ticks = (you.duration[DUR_TOXIC_RADIANCE] / 10) - - ((you.duration[DUR_TOXIC_RADIANCE] - delay) / 10); - toxic_radiance_effect(&you, ticks); - } + toxic_radiance_effect(&you, delay); if (you.duration[DUR_RECITE] && _check_recite()) { diff --git a/crawl-ref/source/spl-damage.cc b/crawl-ref/source/spl-damage.cc index 697612f79ab3..1a18f7fac873 100644 --- a/crawl-ref/source/spl-damage.cc +++ b/crawl-ref/source/spl-damage.cc @@ -2637,7 +2637,7 @@ spret cast_toxic_radiance(actor *agent, int pow, bool fail, bool mon_tracer) mpr("Your toxic radiance grows in intensity."); you.increase_duration(DUR_TOXIC_RADIANCE, 2 + random2(pow/20), 15); - toxic_radiance_effect(&you, 1, true); + toxic_radiance_effect(&you, 10, true); flash_view_delay(UA_PLAYER, GREEN, 300, &hitfunc); @@ -2664,7 +2664,7 @@ spret cast_toxic_radiance(actor *agent, int pow, bool fail, bool mon_tracer) mon_agent->add_ench(mon_enchant(ENCH_TOXIC_RADIANCE, 1, mon_agent, (4 + random2avg(pow/15, 2)) * BASELINE_DELAY)); - toxic_radiance_effect(agent, 1); + toxic_radiance_effect(agent, 10); targeter_los hitfunc(mon_agent, LOS_NO_TRANS); flash_view_delay(UA_MONSTER, GREEN, 300, &hitfunc); @@ -2678,8 +2678,8 @@ spret cast_toxic_radiance(actor *agent, int pow, bool fail, bool mon_tracer) * * @param agent The caster. * @param mult A number to multiply the damage by. - * This is the time taken for the player's action in turns, - * or 1 if the spell was cast this turn. + * This is the time taken for the player's action in auts, + * or 10 if the spell was cast this turn. * @param on_cast Whether the spell was cast this turn. This only matters * if the player cast the spell. If true, we trigger conducts * if the player hurts allies; if false, we don't, to avoid @@ -2705,7 +2705,7 @@ void toxic_radiance_effect(actor* agent, int mult, bool on_cast) if (agent->is_monster() && mons_aligned(agent, *ai)) continue; - int dam = roll_dice(1, 1 + pow / 20) * mult; + int dam = roll_dice(1, 1 + pow / 20) * div_rand_round(mult, BASELINE_DELAY); dam = resist_adjust_damage(*ai, BEAM_POISON, dam); if (ai->is_player()) @@ -2741,8 +2741,11 @@ void toxic_radiance_effect(actor* agent, int mult, bool on_cast) { behaviour_event(ai->as_monster(), ME_ANNOY, agent, agent->pos()); - if (coinflip() || !ai->as_monster()->has_ench(ENCH_POISON)) - poison_monster(ai->as_monster(), agent, 1); + int q = mult / BASELINE_DELAY; + int levels = roll_dice(q, 2) - q + (roll_dice(1, 20) <= (mult % BASELINE_DELAY)); + if (!ai->as_monster()->has_ench(ENCH_POISON)) // Always apply poison to an unpoisoned enemy + levels = max(levels, 1); + poison_monster(ai->as_monster(), agent, levels); } } } From 71cb82dfb872c2f03236f36c3939c09609e15b6c Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Fri, 11 Oct 2019 02:41:39 +0800 Subject: [PATCH 806/864] Fix crash when repeating menu evocations (gammafunk) When repeating the previous command via the ` key, the UI is not fully laid out. The current implementation depends on having the menu more text default to not being visible for the UI to layout correctly. On local tiles this isn't an issue, since scrollers render their own scrollbars, but on console the scroll position is rendered to the more, and the layout error was causing a division by zero in the position calculation. --- crawl-ref/source/menu.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/source/menu.cc b/crawl-ref/source/menu.cc index abbee17dcc1b..cdaa9ca2ea71 100644 --- a/crawl-ref/source/menu.cc +++ b/crawl-ref/source/menu.cc @@ -797,6 +797,7 @@ Menu::Menu(int _flags, const string& tagname, KeymapContext kmc) m_ui.scroller = make_shared(); m_ui.title = make_shared(); m_ui.more = make_shared(); + m_ui.more->set_visible(false); m_ui.vbox = make_shared(Widget::VERT); m_ui.vbox->align_cross = Widget::STRETCH; From b7a8766ae53243a6898185f84eefe655fc3bcad1 Mon Sep 17 00:00:00 2001 From: Byrel Mitchell Date: Thu, 10 Oct 2019 15:03:40 -0400 Subject: [PATCH 807/864] Fixed bug in OTR variance reduction commit This makes it impossible to gain extra OTR duration by breadswinging during the final turn of duration. [Closes #1177] --- crawl-ref/source/player-reacts.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/player-reacts.cc b/crawl-ref/source/player-reacts.cc index ffacaf2eedef..95b99c91a086 100644 --- a/crawl-ref/source/player-reacts.cc +++ b/crawl-ref/source/player-reacts.cc @@ -799,7 +799,7 @@ static void _decrement_durations() } if (you.duration[DUR_TOXIC_RADIANCE]) - toxic_radiance_effect(&you, delay); + toxic_radiance_effect(&you, min(delay, you.duration[DUR_TOXIC_RADIANCE])); if (you.duration[DUR_RECITE] && _check_recite()) { From b57a41df76e4328ffca86b7547762ef1dbaf4408 Mon Sep 17 00:00:00 2001 From: Umer Shaikh Date: Sun, 30 Jun 2019 20:43:25 -0500 Subject: [PATCH 808/864] Allow wielding and wearing from the floor This commit changes wield_weapon and wear_armour to use use_an_item so the player can wield and wear from the floor. It also changes use_an_item so * and - options are allowed to, respectively, view and choose from all items and (if selecting weapons) swap to bare hands. This means * is now available for quaffing and reading as well. The wield weapon menu can now be brought up even if there are no weapons around---indeed, even if there is nothing at all around. The first is because you can wield non-weapons with *. The second is because you always have your bare hands, and I am anticipating a menu where basic stats for weapons are displayed alongside the options (a long-standing feature request). This commit implements * to show all items. This preserves the current ability to wield non-weapons and fulfills a TODO marked in the existing use_an_item code, so that * can be used for reading scrolls and quaffing as well. However, my own feeling is that this is not a usefull bit of UI complexity from the player's side. You cannot quaff non-potions, read non-scrolls, or wear non-wearables anyway. And as far as I know the only practical use for wielding non-weapons is breadswinging, a niche speedrunning tactic. I suggest cutting this and cutting the ability to wield non-weapons. This commit makes wielding or wearing from the floor take the same amount of time as wielding or wearing from your inventory. I think this is the least surprising UI and is consistent with the current behaviour for quaffing and reading from the floor (10 aut). I anticipate this means speedrunners and the hyper-optimal will want to sometimes pick items up by wielding them from the floor (e.g., wielding arrows to pick them up). [ Committer's note: Wielding arrows from the floor to pick them up then switching back to the previously wielded item costs 15 aut and 2 turns. Just picking up the arrows costs 10. Whether turns or aut are used for scoring, just picking up arrows is faster. ] --- crawl-ref/source/food.cc | 3 +- crawl-ref/source/item-use.cc | 374 ++++++++++++++++++++++++++--------- crawl-ref/source/item-use.h | 5 +- 3 files changed, 283 insertions(+), 99 deletions(-) diff --git a/crawl-ref/source/food.cc b/crawl-ref/source/food.cc index 808429f03e4c..5f95fec77390 100644 --- a/crawl-ref/source/food.cc +++ b/crawl-ref/source/food.cc @@ -128,8 +128,7 @@ bool prompt_eat_item(int slot) item_def* item = nullptr; if (slot == -1) { - item = use_an_item(OBJ_FOOD, OPER_EAT, "Eat which item?"); - if (!item) + if (!use_an_item(item, OBJ_FOOD, OPER_EAT, "Eat which item (* to show all)?")) return false; } else diff --git a/crawl-ref/source/item-use.cc b/crawl-ref/source/item-use.cc index e4bfed9b7b2c..b238b3069039 100644 --- a/crawl-ref/source/item-use.cc +++ b/crawl-ref/source/item-use.cc @@ -82,13 +82,16 @@ class UseItemMenu : public InvMenu { - bool is_inventory = true; - - void populate_list(int item_type); + void populate_list(); void populate_menu(); bool process_key(int key) override; + void repopulate_menu(); public: + bool display_all; + bool is_inventory; + int item_type_filter; + vector item_inv; vector item_floor; @@ -97,35 +100,55 @@ class UseItemMenu : public InvMenu // Accepts: // OBJ_POTIONS // OBJ_SCROLLS + // OSEL_WIELD + // OBJ_ARMOUR + // OBJ_FOOD UseItemMenu(int selector, const char* prompt); - void toggle(); + void toggle_display_all(); + void toggle_inv_or_floor(); }; UseItemMenu::UseItemMenu(int item_type, const char* prompt) - : InvMenu(MF_SINGLESELECT) + : InvMenu(MF_SINGLESELECT), display_all(false), is_inventory(true), + item_type_filter(item_type) { set_title(prompt); - populate_list(item_type); + populate_list(); populate_menu(); } -void UseItemMenu::populate_list(int item_type) +void UseItemMenu::populate_list() { // Load inv items first for (const auto &item : you.inv) { - // Populate the vector with filter - if (item.defined() && item_is_selected(item, item_type)) + if (item.defined()) item_inv.push_back(&item); } - // Load floor items + // Load floor items... item_floor = item_list_on_square(you.visible_igrd(you.pos())); - // Filter - erase_if(item_floor, [=](const item_def* item) + // ...only stuff that can go into your inventory though + erase_if(item_floor, [=](const item_def* it) { - return !item_is_selected(*item,item_type); + // Did we get them all...? + return !it->defined() || item_is_stationary(*it) || item_is_orb(*it) + || item_is_spellbook(*it) || it->base_type == OBJ_GOLD + || it->base_type == OBJ_RUNES; }); + + // Filter by type + if (!display_all) + { + erase_if(item_inv, [=](const item_def* item) + { + return !item_is_selected(*item, item_type_filter); + }); + erase_if(item_floor, [=](const item_def* item) + { + return !item_is_selected(*item, item_type_filter); + }); + } } void UseItemMenu::populate_menu() @@ -135,6 +158,14 @@ void UseItemMenu::populate_menu() else if (item_floor.empty()) is_inventory = true; + // Entry for unarmed + if (item_type_filter == OSEL_WIELD) + { + string hands_title = " - unarmed"; + MenuEntry *hands = new MenuEntry (hands_title, MEL_ITEM); + add_entry(hands); + } + if (!item_inv.empty()) { // Only clarify that these are inventory items if there are also floor @@ -193,16 +224,31 @@ void UseItemMenu::populate_menu() } } -void UseItemMenu::toggle() +void UseItemMenu::repopulate_menu() { - is_inventory = !is_inventory; deleteAll(items); populate_menu(); } +void UseItemMenu::toggle_display_all() +{ + display_all = !display_all; + item_inv.clear(); + item_floor.clear(); + populate_list(); + repopulate_menu(); +} + +void UseItemMenu::toggle_inv_or_floor() +{ + is_inventory = !is_inventory; + repopulate_menu(); +} + bool UseItemMenu::process_key(int key) { - if (isadigit(key) || key == '*' || key == '\\' || key == ',') + if (isadigit(key) || key == '*' || key == '\\' || key == ',' + || key == '-' && item_type_filter == OSEL_WIELD) { lastch = key; return false; @@ -221,13 +267,17 @@ static string _weird_sound() } /** - * Prompt use of a consumable from either player inventory or the floor. + * Prompt use of an item from either player inventory or the floor. * * This function generates a menu containing type_expect items based on the * object_class_type to be acted on by another function. First it will list - * items in inventory, then items on the floor. If player cancels out of menu, - * nullptr is returned. + * items in inventory, then items on the floor. If the prompt is cancelled, + * false is returned. If something is successfully choosen, then true is + * returned, and at function exit the parameter target points to the object the + * player chose or to nullptr if the player chose to wield bare hands (this is + * only possible if item_type is OSEL_WIELD). * + * @param target A pointer by reference to indicate the object selected. * @param item_type The object_class_type or OSEL_* of items to list. * @param oper The operation being done to the selected item. * @param prompt The prompt on the menu title @@ -235,23 +285,25 @@ static string _weird_sound() * function. If it returns false, continue the prompt rather * than returning null. * - * @return a pointer to the chosen item, or nullptr if none was chosen. + * @return boolean true if something was chosen, false if the process failed and + * no choice was made */ -item_def* use_an_item(int item_type, operation_types oper, const char* prompt, - function allowcancel) +bool use_an_item(item_def *&target, int item_type, operation_types oper, + const char* prompt, function allowcancel) { - item_def* target = nullptr; - - // First handle things that will return nullptr - - // No selectable items in inv or floor - if (!any_items_of_type(item_type, -1, true)) + // First bail if there's nothing appropriate to choose in inv or on floor + // (if choosing weapons, then bare hands are always a possibility) + if (item_type != OSEL_WIELD && !any_items_of_type(item_type, -1, true)) { mprf(MSGCH_PROMPT, "%s", no_selectables_message(item_type).c_str()); - return nullptr; + return false; } + bool choice_made = false; + item_def *tmp_tgt = nullptr; // We'll change target only if the player + // actually chooses + // Init the menu UseItemMenu menu(item_type, prompt); @@ -262,15 +314,30 @@ item_def* use_an_item(int item_type, operation_types oper, const char* prompt, // Handle inscribed item keys if (isadigit(keyin)) - target = digit_inscription_to_item(keyin, oper); - // TODO: handle * key + { + // This allows you to select stuff by inscription that is not on the + // screen, but only if you couldn't by default use it for that operation + // anyway. It's a bit weird, but it does save a '*' keypress for + // bread-swingers. + tmp_tgt = digit_inscription_to_item(keyin, oper); + if (tmp_tgt) + choice_made = true; + } + else if (keyin == '*') + { + menu.toggle_display_all(); + continue; + } else if (keyin == ',') { if (Options.easy_floor_use && menu.item_floor.size() == 1) - target = const_cast(menu.item_floor[0]); + { + choice_made = true; + tmp_tgt = const_cast(menu.item_floor[0]); + } else { - menu.toggle(); + menu.toggle_inv_or_floor(); continue; } } @@ -279,27 +346,44 @@ item_def* use_an_item(int item_type, operation_types oper, const char* prompt, check_item_knowledge(); continue; } + else if (keyin == '-' && menu.item_type_filter == OSEL_WIELD) + { + choice_made = true; + tmp_tgt = nullptr; + } else if (!sel.empty()) { ASSERT(sel.size() == 1); + choice_made = true; auto ie = dynamic_cast(sel[0]); - target = const_cast(ie->item); + tmp_tgt = const_cast(ie->item); } redraw_screen(); - if (target && !check_warning_inscriptions(*target, oper)) - target = nullptr; - if (target) - return target; + // For weapons and armour this is handled in wield_weapon and + // wear_armour separately from selection + if (item_type != OSEL_WIELD && item_type != OBJ_ARMOUR && choice_made + && tmp_tgt && !check_warning_inscriptions(*tmp_tgt, oper)) + { + choice_made = false; + } + + if (choice_made) + break; else if (allowcancel()) { prompt_failed(PROMPT_ABORT); - return nullptr; + break; } else continue; } + if (choice_made) + target = tmp_tgt; + + ASSERT(!choice_made || target || item_type == OSEL_WIELD); + return choice_made; } static bool _safe_to_remove_or_wear(const item_def &item, bool remove, @@ -408,6 +492,72 @@ bool can_wield(const item_def *weapon, bool say_reason, #undef SAY } +/** + * Helper function for wield_weapon & wear_armour + * @param item item on floor (where the player is standing) + * @param quiet print message or not + * @return boolean can the player move the item into their inventory, or are + * they out of space? + */ +static bool _can_move_item_from_floor_to_inv(const item_def &item) +{ + if (inv_count() < ENDOFPACK) + return true; + if (!is_stackable_item(item)) + { + mpr("You can't carry that many items."); + return false; + } + for (int i = 0; i < ENDOFPACK; ++i) + { + if (items_stack(you.inv[i], item)) + return true; + } + mpr("You can't carry that many items."); + return false; +} + +/** + * Helper function for wield_weapon & wear_armour + * @param to_get item on floor (where the player is standing) to move into + inventory + * @return int -1 if failure due to already full inventory; otherwise, index in + * you.inv where the item ended up + */ +static int _move_item_from_floor_to_inv(const item_def &to_get) +{ + map tmp_l_p = you.last_pickup; // if we need to restore + you.last_pickup.clear(); + + if (!move_item_to_inv(to_get.index(), to_get.quantity, true)) + { + mpr("You can't carry that many items."); + you.last_pickup = tmp_l_p; + } + // Get the slot of the last thing picked up + // TODO: this is a bit hacky---perhaps it's worth making a function like + // move_item_to_inv that returns the slot the item moved into + else + { + ASSERT(you.last_pickup.size() == 1); // Sanity check... + return you.last_pickup.begin()->first; + } + return -1; +} + +/** + * Helper function for wield_weapon & wear_armour + * @param item item on floor (where the player is standing) or in inventory + * @return ret index in you.inv where the item is (either because it was already + * there or just got moved there), or -1 if we tried and failed to + * move the item into inventory + */ +static int _get_item_slot(const item_def &item) +{ + int ret = item.pos == ITEM_IN_INVENTORY + ? item.link : _move_item_from_floor_to_inv(item); + return ret; +} /** * @param auto_wield false if this was initiated by the wield weapon command (w) * true otherwise (e.g. switching between ranged and melee with the @@ -422,59 +572,63 @@ bool wield_weapon(bool auto_wield, int slot, bool show_weff_messages, bool show_unwield_msg, bool show_wield_msg, bool adjust_time_taken) { - if (inv_count() < 1) - { - canned_msg(MSG_NOTHING_CARRIED); - return false; - } - - // Look for conditions like berserking that could prevent wielding + // Abort immediately if there's some condition that could prevent wielding // weapons. if (!can_wield(nullptr, true, false, slot == SLOT_BARE_HANDS)) return false; - int item_slot = 0; // default is 'a' + item_def *to_wield = &you.inv[0]; // default is 'a' + // we'll set this to nullptr to indicate bare hands if (auto_wield) { - if (item_slot == you.equip[EQ_WEAPON] - || you.equip[EQ_WEAPON] == -1 - && !item_is_wieldable(you.inv[item_slot])) + if (to_wield == you.weapon() + || you.equip[EQ_WEAPON] == -1 && !item_is_wieldable(*to_wield)) { - item_slot = 1; // backup is 'b' + to_wield = &you.inv[1]; // backup is 'b' } if (slot != -1) // allow external override - item_slot = slot; + { + if (slot == SLOT_BARE_HANDS) + to_wield = nullptr; + else + to_wield = &you.inv[slot]; + } } - // If the swap slot has a bad (but valid) item in it, - // the swap will be to bare hands. - const bool good_swap = (item_slot == SLOT_BARE_HANDS - || item_is_wieldable(you.inv[item_slot])); - - // Prompt if not using the auto swap command, or if the swap slot - // is empty. - if (item_slot != SLOT_BARE_HANDS - && (!auto_wield || !you.inv[item_slot].defined() || !good_swap)) + if (to_wield) { + // Prompt if not using the auto swap command if (!auto_wield) { - item_slot = prompt_invent_item( - "Wield which item (- for none, * to show all)?", - menu_type::invlist, OSEL_WIELD, - OPER_WIELD, invprompt_flag::no_warning, '-'); + if (!use_an_item(to_wield, OSEL_WIELD, OPER_WIELD, "Wield " + "which item (- for none, * to show all)?")) + { + return false; + } + // We abort if trying to wield from the floor with full inventory. We could + // try something more sophisticated, e.g., drop the currently held weapon, + // but that's surely not always what's wanted, and the problem persists if + // the player's hands are empty. For now, let's stick with simple behaviour + // over trying to guess what the player would like. + if (to_wield && to_wield->pos != ITEM_IN_INVENTORY + && !_can_move_item_from_floor_to_inv(*to_wield)) + { + return false; + } } - else - item_slot = SLOT_BARE_HANDS; + + // If autowielding and the swap slot has a bad or invalid item in it, the + // swap will be to bare hands. + else if (!to_wield->defined() || !item_is_wieldable(*to_wield)) + to_wield = nullptr; } - if (prompt_failed(item_slot)) - return false; - else if (item_slot == you.equip[EQ_WEAPON]) + if (to_wield && to_wield == you.weapon()) { if (Options.equip_unequip) - item_slot = SLOT_BARE_HANDS; + to_wield = nullptr; else { mpr("You are already wielding that!"); @@ -485,7 +639,7 @@ bool wield_weapon(bool auto_wield, int slot, bool show_weff_messages, // Reset the warning counter. you.received_weapon_warning = false; - if (item_slot == SLOT_BARE_HANDS) + if (!to_wield) { if (const item_def* wpn = you.weapon()) { @@ -534,7 +688,9 @@ bool wield_weapon(bool auto_wield, int slot, bool show_weff_messages, return true; } - item_def& new_wpn(you.inv[item_slot]); + // By now we're sure we're swapping to a real weapon, not bare hands + + item_def& new_wpn = *to_wield; // Switching to a launcher while berserk is likely a mistake. if (you.berserk() && is_range_weapon(new_wpn)) @@ -579,6 +735,15 @@ bool wield_weapon(bool auto_wield, int slot, bool show_weff_messages, const unsigned int old_talents = your_talents(false).size(); + // If it's on the ground, pick it up. Once it's picked up, there should be + // no aborting, lest we introduce a way to instantly pick things up + // NB we already made sure there was space for the item + int item_slot = _get_item_slot(new_wpn); + + // At this point new_wpn is potentially not the right thing anymore (the + // thing actually in the player's inventory), that is, in the case where the + // player chose something from the floor. So use item_slot from here on. + // Go ahead and wield the weapon. equip_item(EQ_WEAPON, item_slot, show_weff_messages); @@ -587,10 +752,10 @@ bool wield_weapon(bool auto_wield, int slot, bool show_weff_messages, #ifdef USE_SOUND parse_sound(WIELD_WEAPON_SOUND); #endif - mprf_nocap("%s", new_wpn.name(DESC_INVENTORY_EQUIP).c_str()); + mprf_nocap("%s", you.inv[item_slot].name(DESC_INVENTORY_EQUIP).c_str()); } - check_item_hint(new_wpn, old_talents); + check_item_hint(you.inv[item_slot], old_talents); // Time calculations. if (adjust_time_taken) @@ -1011,31 +1176,41 @@ bool wear_armour(int item) return false; } + item_def *to_wear = nullptr; + if (item == -1) { - item = prompt_invent_item("Wear which item?", menu_type::invlist, - OBJ_ARMOUR, OPER_WEAR, - invprompt_flag::no_warning); - if (prompt_failed(item)) + if (!use_an_item(to_wear, OBJ_ARMOUR, OPER_WEAR, + "Wear which item (* to show all)?")) + { return false; + } + // use_an_item on armour should never return true and leave to_wear + // nullptr + if (to_wear->pos != ITEM_IN_INVENTORY + && !_can_move_item_from_floor_to_inv(*to_wear)) + { + return false; + } } + else + to_wear = &you.inv[item]; - item_def &invitem = you.inv[item]; // First, let's check for any conditions that would make it impossible to // equip the given item - if (!invitem.defined()) + if (!to_wear->defined()) { mpr("You don't have any such object."); return false; } - if (item == you.equip[EQ_WEAPON]) + if (to_wear == you.weapon()) { mpr("You are wielding that object!"); return false; } - if (item_is_worn(item)) + if (to_wear->pos == ITEM_IN_INVENTORY && item_is_worn(to_wear->link)) { if (Options.equip_unequip) // TODO: huh? Why are we inverting the return value? @@ -1047,20 +1222,20 @@ bool wear_armour(int item) } } - if (!_can_equip_armour(invitem)) + if (!_can_equip_armour(*to_wear)) return false; // At this point, we know it's possible to equip this item. However, there // might be reasons it's not advisable. Warn about any dangerous // inscriptions, giving the player an opportunity to bail out. - if (!check_warning_inscriptions(invitem, OPER_WEAR)) + if (!check_warning_inscriptions(*to_wear, OPER_WEAR)) { canned_msg(MSG_OK); return false; } bool swapping = false; - const equipment_type slot = get_armour_slot(invitem); + const equipment_type slot = get_armour_slot(*to_wear); if ((slot == EQ_CLOAK || slot == EQ_HELMET || slot == EQ_GLOVES @@ -1079,12 +1254,20 @@ bool wear_armour(int item) // TODO: It would be nice if we checked this before taking off the item // currently in the slot. But doing so is not quite trivial. Also applies // to jewellery. - if (!_safe_to_remove_or_wear(invitem, false)) + if (!_safe_to_remove_or_wear(*to_wear, false)) return false; - const int delay = armour_equip_delay(invitem); + // If it's on the ground, pick it up. Once it's picked up, there should be + // no aborting + // NB we already made sure there was space for the item + int item_slot = _get_item_slot(*to_wear); + + const int delay = armour_equip_delay(*to_wear); if (delay) - start_delay(delay - (swapping ? 0 : 1), invitem); + { + start_delay(delay - (swapping ? 0 : 1), + you.inv[item_slot]); + } return true; } @@ -2037,9 +2220,7 @@ void drink(item_def* potion) if (!potion) { - potion = use_an_item(OBJ_POTIONS, OPER_QUAFF, "Drink which item?"); - - if (!potion) + if (!use_an_item(potion, OBJ_POTIONS, OPER_QUAFF, "Drink which item (* to show all)?")) return; } @@ -2265,7 +2446,10 @@ static void _brand_weapon(item_def &wpn) static item_def* _choose_target_item_for_scroll(bool scroll_known, object_selector selector, const char* prompt) { - return use_an_item(selector, OPER_ANY, prompt, + item_def *target = nullptr; + bool success = false; + + success = use_an_item(target, selector, OPER_ANY, prompt, [=]() { if (scroll_known @@ -2276,6 +2460,7 @@ static item_def* _choose_target_item_for_scroll(bool scroll_known, object_select } return false; }); + return success ? target : nullptr; } static object_selector _enchant_selector(scroll_type scroll) @@ -2750,8 +2935,7 @@ void read(item_def* scroll) if (!scroll) { - scroll = use_an_item(OBJ_SCROLLS, OPER_READ, "Read which item?"); - if (!scroll) + if (!use_an_item(scroll, OBJ_SCROLLS, OPER_READ, "Read which item (* to show all)?")) return; } diff --git a/crawl-ref/source/item-use.h b/crawl-ref/source/item-use.h index a1dabdf492ca..513ffc76a5ca 100644 --- a/crawl-ref/source/item-use.h +++ b/crawl-ref/source/item-use.h @@ -12,8 +12,9 @@ #include "item-prop-enum.h" #include "operation-types.h" -item_def* use_an_item(int item_type, operation_types oper, const char* prompt, - function allowcancel = [](){ return true; }); +bool use_an_item(item_def *&target, int item_type, operation_types oper, + const char* prompt, + function allowcancel = [](){ return true; }); // Change the lambda to always_true<> when g++ 4.7 support is dropped. bool armour_prompt(const string & mesg, int *index, operation_types oper); From a050431806941786d78922e5fab2ccf870572262 Mon Sep 17 00:00:00 2001 From: Umer Shaikh Date: Tue, 10 Sep 2019 01:08:27 -0500 Subject: [PATCH 809/864] Allow putting on jewellery from the floor This commit extends previous functionality to work with puton_ring (which also handles amulets). Amount of time to perform the action is the same as putting on jewellery from the inventory. [ Closes #1136 ] --- crawl-ref/source/delay.cc | 2 +- crawl-ref/source/delay.h | 4 +- crawl-ref/source/item-use.cc | 106 +++++++++++++++++++---------------- crawl-ref/source/item-use.h | 3 + 4 files changed, 64 insertions(+), 51 deletions(-) diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc index 71926a2761c8..3df59a65328c 100644 --- a/crawl-ref/source/delay.cc +++ b/crawl-ref/source/delay.cc @@ -767,7 +767,7 @@ void JewelleryOnDelay::finish() #ifdef USE_SOUND parse_sound(WEAR_JEWELLERY_SOUND); #endif - puton_ring(jewellery.link, false, false); + puton_ring(jewellery, false, false); } void ArmourOnDelay::finish() diff --git a/crawl-ref/source/delay.h b/crawl-ref/source/delay.h index 2218ead88c22..56547614c2de 100644 --- a/crawl-ref/source/delay.h +++ b/crawl-ref/source/delay.h @@ -271,13 +271,13 @@ class ArmourOffDelay : public Delay class JewelleryOnDelay : public Delay { - item_def& jewellery; + const item_def& jewellery; void tick() override; void finish() override; public: - JewelleryOnDelay(int dur, item_def& item) : + JewelleryOnDelay(int dur, const item_def& item) : Delay(dur), jewellery(item) { } diff --git a/crawl-ref/source/item-use.cc b/crawl-ref/source/item-use.cc index b238b3069039..d8a1f3f6098e 100644 --- a/crawl-ref/source/item-use.cc +++ b/crawl-ref/source/item-use.cc @@ -361,10 +361,11 @@ bool use_an_item(item_def *&target, int item_type, operation_types oper, } redraw_screen(); - // For weapons and armour this is handled in wield_weapon and - // wear_armour separately from selection - if (item_type != OSEL_WIELD && item_type != OBJ_ARMOUR && choice_made - && tmp_tgt && !check_warning_inscriptions(*tmp_tgt, oper)) + // For weapons, armour, and jewellery this is handled in wield_weapon, + // wear_armour, and _puton_item after selection + if (item_type != OSEL_WIELD && item_type != OBJ_ARMOUR + && item_type != OBJ_JEWELLERY && choice_made && tmp_tgt + && !check_warning_inscriptions(*tmp_tgt, oper)) { choice_made = false; } @@ -493,7 +494,7 @@ bool can_wield(const item_def *weapon, bool say_reason, } /** - * Helper function for wield_weapon & wear_armour + * Helper function for wield_weapon, wear_armour, and puton_ring * @param item item on floor (where the player is standing) * @param quiet print message or not * @return boolean can the player move the item into their inventory, or are @@ -518,7 +519,7 @@ static bool _can_move_item_from_floor_to_inv(const item_def &item) } /** - * Helper function for wield_weapon & wear_armour + * Helper function for wield_weapon, wear_armour, and puton_ring * @param to_get item on floor (where the player is standing) to move into inventory * @return int -1 if failure due to already full inventory; otherwise, index in @@ -546,13 +547,13 @@ static int _move_item_from_floor_to_inv(const item_def &to_get) } /** - * Helper function for wield_weapon & wear_armour + * Helper function for wield_weapon, wear_armour, and puton_ring * @param item item on floor (where the player is standing) or in inventory * @return ret index in you.inv where the item is (either because it was already * there or just got moved there), or -1 if we tried and failed to * move the item into inventory */ -static int _get_item_slot(const item_def &item) +static int _get_item_slot_maybe_with_move(const item_def &item) { int ret = item.pos == ITEM_IN_INVENTORY ? item.link : _move_item_from_floor_to_inv(item); @@ -738,7 +739,7 @@ bool wield_weapon(bool auto_wield, int slot, bool show_weff_messages, // If it's on the ground, pick it up. Once it's picked up, there should be // no aborting, lest we introduce a way to instantly pick things up // NB we already made sure there was space for the item - int item_slot = _get_item_slot(new_wpn); + int item_slot = _get_item_slot_maybe_with_move(new_wpn); // At this point new_wpn is potentially not the right thing anymore (the // thing actually in the player's inventory), that is, in the case where the @@ -1260,7 +1261,7 @@ bool wear_armour(int item) // If it's on the ground, pick it up. Once it's picked up, there should be // no aborting // NB we already made sure there was space for the item - int item_slot = _get_item_slot(*to_wear); + int item_slot = _get_item_slot_maybe_with_move(*to_wear); const int delay = armour_equip_delay(*to_wear); if (delay) @@ -1415,7 +1416,7 @@ static const char _ring_slot_key(equipment_type slot) } } -static int _prompt_ring_to_remove(int new_ring) +static int _prompt_ring_to_remove() { const vector ring_types = _current_ring_types(); vector slot_chars; @@ -1622,12 +1623,12 @@ bool safe_to_remove(const item_def &item, bool quiet) } // Assumptions: -// you.inv[ring_slot] is a valid ring. -// EQ_LEFT_RING and EQ_RIGHT_RING are both occupied, and ring_slot is not -// one of the worn rings. +// item is an item in inventory or on the floor where the player is standing +// EQ_LEFT_RING and EQ_RIGHT_RING are both occupied, and item is not +// in one of those slots. // // Does not do amulets. -static bool _swap_rings(int ring_slot) +static bool _swap_rings(const item_def& to_puton) { vector ring_types = _current_ring_types(); const int num_rings = ring_types.size(); @@ -1710,7 +1711,7 @@ static bool _swap_rings(int ring_slot) { // Don't prompt if all the rings are the same. if (!all_same || Options.jewellery_prompt) - unwanted = _prompt_ring_to_remove(ring_slot); + unwanted = _prompt_ring_to_remove(); if (unwanted == EQ_NONE) { @@ -1734,7 +1735,7 @@ static bool _swap_rings(int ring_slot) } // Put on the new ring. - start_delay(1, you.inv[ring_slot]); + start_delay(1, to_puton); return true; } @@ -1797,14 +1798,12 @@ static equipment_type _choose_ring_slot() // Is it possible to put on the given item in a jewellery slot? // Preconditions: -// - item_slot is a valid index into inventory // - item is not already equipped in a jewellery slot -static bool _can_puton_jewellery(int item_slot) +static bool _can_puton_jewellery(const item_def &item) { // TODO: between this function, _puton_item, _swap_rings, and remove_ring, // there's a bit of duplicated work, and sep. of concerns not clear - item_def& item = you.inv[item_slot]; - if (item_slot == you.equip[EQ_WEAPON]) + if (&item == you.weapon()) { mpr("You are wielding that object."); return false; @@ -1871,19 +1870,20 @@ static bool _can_puton_jewellery(int item_slot) } // Put on a particular ring or amulet -static bool _puton_item(int item_slot, bool prompt_slot, +static bool _puton_item(const item_def &item, bool prompt_slot, bool check_for_inscriptions) { - item_def& item = you.inv[item_slot]; + vector current_jewellery = _current_ring_types(); + current_jewellery.push_back(EQ_AMULET); - for (int eq = EQ_FIRST_JEWELLERY; eq <= EQ_LAST_JEWELLERY; eq++) - if (item_slot == you.equip[eq]) + for (auto eq : current_jewellery) + if (&item == you.slot_item(eq, true)) { // "Putting on" an equipped item means taking it off. if (Options.equip_unequip) // TODO: why invert the return value here? failing to remove // a ring is equivalent to successfully putting one on? - return !remove_ring(item_slot); + return !remove_ring(item.link); else { mpr("You're already wearing that object!"); @@ -1891,7 +1891,7 @@ static bool _puton_item(int item_slot, bool prompt_slot, } } - if (!_can_puton_jewellery(item_slot)) + if (!_can_puton_jewellery(item)) return false; // It looks to be possible to equip this item. Before going any further, @@ -1923,7 +1923,7 @@ static bool _puton_item(int item_slot, bool prompt_slot, // No unused ring slots. Swap out a worn ring for the new one. if (need_swap) - return _swap_rings(item_slot); + return _swap_rings(item); } else if (you.slot_item(EQ_AMULET, true)) { @@ -1987,6 +1987,7 @@ static bool _puton_item(int item_slot, bool prompt_slot, const unsigned int old_talents = your_talents(false).size(); // Actually equip the item. + int item_slot = _get_item_slot_maybe_with_move(item); equip_item(hand_used, item_slot); check_item_hint(you.inv[item_slot], old_talents); @@ -2005,38 +2006,47 @@ static bool _puton_item(int item_slot, bool prompt_slot, return true; } -// Put on a ring or amulet. (If slot is -1, first prompt for which item to put on) -bool puton_ring(int slot, bool allow_prompt, bool check_for_inscriptions) +// Put on a ring or amulet. (Most of the work is in _puton_item.) +bool puton_ring(const item_def &to_puton, bool allow_prompt, + bool check_for_inscriptions) { - int item_slot; - - if (inv_count() < 1) - { - canned_msg(MSG_NOTHING_CARRIED); - return false; - } - if (you.berserk()) { canned_msg(MSG_TOO_BERSERK); return false; } - - if (slot != -1) - item_slot = slot; - else + if (!to_puton.defined()) { - item_slot = prompt_invent_item("Put on which piece of jewellery?", - menu_type::invlist, OBJ_JEWELLERY, - OPER_PUTON, invprompt_flag::no_warning); + mpr("You don't have any such object."); + return false; } - - if (prompt_failed(item_slot)) + if (to_puton.pos != ITEM_IN_INVENTORY + && !_can_move_item_from_floor_to_inv(to_puton)) + { return false; + } bool prompt = allow_prompt ? Options.jewellery_prompt : false; + return _puton_item(to_puton, prompt, check_for_inscriptions); +} + +// Wraps version of puton_ring with item_def param. If slot is -1, prompt for +// which item to put on; otherwise, pass on the item in inventory slot +bool puton_ring(int slot, bool allow_prompt, bool check_for_inscriptions) +{ + item_def *to_puton_ptr = nullptr; + if (slot == -1) + { + if (!use_an_item(to_puton_ptr, OBJ_JEWELLERY, OPER_PUTON, + "Put on which piece of jewellery (* to show all)?")) + { + return false; + } + } + else + to_puton_ptr = &you.inv[slot]; - return _puton_item(item_slot, prompt, check_for_inscriptions); + return puton_ring(*to_puton_ptr, allow_prompt, check_for_inscriptions); } // Remove the amulet/ring at given inventory slot (or, if slot is -1, prompt diff --git a/crawl-ref/source/item-use.h b/crawl-ref/source/item-use.h index 513ffc76a5ca..7afb20f1b181 100644 --- a/crawl-ref/source/item-use.h +++ b/crawl-ref/source/item-use.h @@ -30,6 +30,9 @@ bool safe_to_remove(const item_def &item, bool quiet = false); bool puton_ring(int slot = -1, bool allow_prompt = true, bool check_for_inscriptions = true); +bool puton_ring(const item_def &to_puton, bool allow_prompt = true, + bool check_for_inscriptions = true); + void read(item_def* scroll = nullptr); void read_scroll(item_def& scroll); bool player_can_read(); From 0f74319286b5c68362e82b85a1dd7919e4187d37 Mon Sep 17 00:00:00 2001 From: advil Date: Fri, 11 Oct 2019 12:18:19 -0400 Subject: [PATCH 810/864] Don't crash with equip_unequip I think this case just got missed in b57a41d. --- crawl-ref/source/item-use.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/item-use.cc b/crawl-ref/source/item-use.cc index d8a1f3f6098e..a2602f0c1dd6 100644 --- a/crawl-ref/source/item-use.cc +++ b/crawl-ref/source/item-use.cc @@ -1215,7 +1215,7 @@ bool wear_armour(int item) { if (Options.equip_unequip) // TODO: huh? Why are we inverting the return value? - return !takeoff_armour(item); + return !takeoff_armour(to_wear->link); else { mpr("You're already wearing that object!"); From 8421e6d06bd678b96757516e2e3beef81be9fc1e Mon Sep 17 00:00:00 2001 From: gammafunk Date: Sat, 12 Oct 2019 20:12:16 -0500 Subject: [PATCH 811/864] Update ballistomycete descriptions (kitchen-ace) Updates the descriptions for ballistomycete and ballistomycete spores to remove an outdated reference to ballistomycetes growing and to describe the effect of the spore's explosion. Also add a description for the Sporulate ability using the same language. Closes #1183. [skip ci] (cherry picked from commit ac51ba0f9bf8c832e6c8e612d0396af0ab2e4a93) --- crawl-ref/source/dat/descript/monsters.txt | 9 +++++---- crawl-ref/source/dat/descript/spells.txt | 6 ++++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/dat/descript/monsters.txt b/crawl-ref/source/dat/descript/monsters.txt index d7fb69b6c3a1..7d4f572a5321 100644 --- a/crawl-ref/source/dat/descript/monsters.txt +++ b/crawl-ref/source/dat/descript/monsters.txt @@ -575,13 +575,14 @@ A small snake that can augment its bite by constricting small creatures. ballistomycete A lumpy reddish fungus covered in knobbly rhizome growths, growing well in the -dank underground dungeon. When active it will occasionally produce giant -spores, which in turn will give rise to more ballistomycetes. +dank underground dungeon. When it senses a threat, the ballistomycete may +release a deadly floating spore that explodes on its victims. %%%% ballistomycete spore -A deceptively fast, floating ball filled with gas and spores, prone to burst at -the slightest disturbance. +A fast, gas-filled floating spore released by a ballistomycete when it senses a +threat. After seeking out its foe, the spore will explode, damaging anything +caught in the blast and further confusing living creatures. %%%% balrug diff --git a/crawl-ref/source/dat/descript/spells.txt b/crawl-ref/source/dat/descript/spells.txt index 1d055e1017c4..304ed12a4015 100644 --- a/crawl-ref/source/dat/descript/spells.txt +++ b/crawl-ref/source/dat/descript/spells.txt @@ -1272,6 +1272,12 @@ Spit Poison spell %%%% +Sporulate spell + +Releases a fast, gas-filled floating spore. After seeking out its foe, the +spore will explode, damaging anything caught in the blast and further confusing +living creatures. +%%%% Sprint spell Causes the caster to move across terrain more rapidly for a short duration. From 60987f991d38ad88c3507354ef76a2a68f6671ca Mon Sep 17 00:00:00 2001 From: kitchen-ace <68k@quikphix.org> Date: Sat, 12 Oct 2019 14:33:11 -0400 Subject: [PATCH 812/864] Fix showing regen amulets as useless for Vampires Vampires now heal when bloodless as long as no monsters are in LOS. (cherry picked from commit 14d03b10f241238d454734f3dc760932b0e2af5a) --- crawl-ref/source/item-name.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/item-name.cc b/crawl-ref/source/item-name.cc index 76080da73020..827202695a7a 100644 --- a/crawl-ref/source/item-name.cc +++ b/crawl-ref/source/item-name.cc @@ -3585,10 +3585,9 @@ bool is_useless_item(const item_def &item, bool temp) case AMU_REGENERATION: return you.get_mutation_level(MUT_NO_REGENERATION) > 0 || (temp - && you.get_mutation_level(MUT_INHIBITED_REGENERATION) > 0 - && regeneration_is_inhibited()) - || (temp && you.species == SP_VAMPIRE - && !you.vampire_alive); + && (you.get_mutation_level(MUT_INHIBITED_REGENERATION) > 0 + || you.species == SP_VAMPIRE) + && regeneration_is_inhibited()); #if TAG_MAJOR_VERSION == 34 case AMU_MANA_REGENERATION: From fb01ec503c6a130fd1bacddb07ce50f865d5ba4f Mon Sep 17 00:00:00 2001 From: kitchen-ace <68k@quikphix.org> Date: Sat, 12 Oct 2019 15:06:14 -0400 Subject: [PATCH 813/864] Show that bloodless vampires' bite can heal It's not obvious that vampires can heal themselves when they bite something, and that this works only when they're bloodless. Add some messages to the abilities screens. (cherry picked from commit 6559c6c67ac2b321ec53330233fa5a030221e6d7) --- crawl-ref/source/mutation.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/mutation.cc b/crawl-ref/source/mutation.cc index 761c9a7a79ba..c50f0d5fc6c7 100644 --- a/crawl-ref/source/mutation.cc +++ b/crawl-ref/source/mutation.cc @@ -645,6 +645,7 @@ string describe_mutations(bool drop_title) { result += "You do not regenerate when monsters are visible.\n"; result += "You are frail without blood (-20% HP).\n"; + result += "You can heal yourself when you bite living creatures.\n"; } else result += "Your natural rate of healing is unusually fast.\n"; @@ -775,17 +776,19 @@ static string _display_vampire_attributes() string result; - const int lines = 11; + const int lines = 12; string column[lines][3] = { {" ", "Alive ", "Bloodless"}, //Full Bloodless {"Regeneration ", "fast ", "none with monsters in sight"}, - {"HP Modifier ", "none ", "-20%"}, + {"HP modifier ", "none ", "-20%"}, {"Stealth boost ", "none ", "major "}, + {"Heal on bite ", "no ", "yes "}, + {"\nResistances\n" "Poison resistance ", " ", "immune"}, From caac7acfae3e15d57e1812594089c7e93af11b09 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 14 Oct 2019 23:24:52 +0800 Subject: [PATCH 814/864] Fix abyss-gen level excursion milestones (kitchen_ace, 12078) Abyss generation can include parts of other levels, through a level excursion. When including part of a level that the player had never visited, a milestone was erroneously added. (cherry picked from commit e7af4de912368a96ec50a2904c3cfd2b71a8cf51) --- crawl-ref/source/files.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 4d1173934dc7..57bc60ad7620 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1971,8 +1971,11 @@ bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode, // Maybe make a note if we reached a new level. // Don't do so if we are just moving around inside Pan, though. - if (just_created_level && stair_taken != DNGN_TRANSIT_PANDEMONIUM) + if (just_created_level && make_changes + && stair_taken != DNGN_TRANSIT_PANDEMONIUM) + { take_note(Note(NOTE_DUNGEON_LEVEL_CHANGE)); + } // If the player entered the level from a different location than they last // exited it, have monsters lose track of where they are From 3faab67891fac84b7383cce54ab304ffa23d21d0 Mon Sep 17 00:00:00 2001 From: kitchen-ace <68k@quikphix.org> Date: Mon, 7 Oct 2019 03:03:02 -0400 Subject: [PATCH 815/864] Don't stop travel for changes from (un)melding If you are auto-travelling, and you lose stats from armour melding or unmelding, don't stop auto-travel for that reason alone. This is really only relevant for merfolk with artefact boots, but the fix should apply to the general case. (cherry picked from commit 771548fc264c731e52bdfdbd86052877d0fb8177) --- crawl-ref/source/delay.cc | 11 ----------- crawl-ref/source/delay.h | 19 +++++++++++++++++++ crawl-ref/source/player-equip.cc | 4 ++++ 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc index 3df59a65328c..d7c642a494a3 100644 --- a/crawl-ref/source/delay.cc +++ b/crawl-ref/source/delay.cc @@ -80,17 +80,6 @@ #include "view.h" #include "xom.h" -class interrupt_block -{ -public: - interrupt_block() { ++interrupts_blocked; } - ~interrupt_block() { --interrupts_blocked; } - - static bool blocked() { return interrupts_blocked > 0; } -private: - static int interrupts_blocked; -}; - int interrupt_block::interrupts_blocked = 0; static void _xom_check_corpse_waste(); diff --git a/crawl-ref/source/delay.h b/crawl-ref/source/delay.h index 56547614c2de..0b9e33d56e97 100644 --- a/crawl-ref/source/delay.h +++ b/crawl-ref/source/delay.h @@ -13,6 +13,25 @@ #include "operation-types.h" #include "seen-context-type.h" +class interrupt_block +{ +public: + interrupt_block(bool block = true) { + m_block = block; + if (block) + ++interrupts_blocked; + } + ~interrupt_block() { + if (m_block) + --interrupts_blocked; + } + + static bool blocked() { return interrupts_blocked > 0; } +private: + bool m_block; + static int interrupts_blocked; +}; + class monster; struct ait_hp_loss; diff --git a/crawl-ref/source/player-equip.cc b/crawl-ref/source/player-equip.cc index 4b8c957651bd..3b29080e8483 100644 --- a/crawl-ref/source/player-equip.cc +++ b/crawl-ref/source/player-equip.cc @@ -162,6 +162,8 @@ void equip_effect(equipment_type slot, int item_slot, bool unmeld, bool msg) if (msg) _equip_use_warning(item); + const interrupt_block block_unmeld_interrupts(unmeld); + if (slot == EQ_WEAPON) _equip_weapon_effect(item, msg, unmeld); else if (slot >= EQ_CLOAK && slot <= EQ_BODY_ARMOUR) @@ -180,6 +182,8 @@ void unequip_effect(equipment_type slot, int item_slot, bool meld, bool msg) _assert_valid_slot(eq, slot); + const interrupt_block block_meld_interrupts(meld); + if (slot == EQ_WEAPON) _unequip_weapon_effect(item, msg, meld); else if (slot >= EQ_CLOAK && slot <= EQ_BODY_ARMOUR) From ffcf5fe11393a29bc55af09dbdc40fbd9ee954e7 Mon Sep 17 00:00:00 2001 From: mwvdev Date: Sat, 12 Oct 2019 14:56:48 +0200 Subject: [PATCH 816/864] Fix manual typos (cherry picked from commit b6de7aaf3c5b852413723816f7b0e2d04d275a78) --- crawl-ref/docs/crawl_manual.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crawl-ref/docs/crawl_manual.rst b/crawl-ref/docs/crawl_manual.rst index 2821be332a6d..baeda325862e 100644 --- a/crawl-ref/docs/crawl_manual.rst +++ b/crawl-ref/docs/crawl_manual.rst @@ -2042,13 +2042,13 @@ Warpers Warpers specialise in translocation magic, and are experts in traveling long distances and positioning themselves precisely and use this to their advantage in melee or missile combat. They start with a scroll of blinking, the Book of - Spatial Translocations, some dispersal tomahawks, a simple weapon of thier + Spatial Translocations, some dispersal tomahawks, a simple weapon of their choice, and leather armour. Arcane Marksmen Arcane Marksmen are Hunters who use debilitating spells to assist their ranged attacks. They are particularly good at keeping their enemies at a distance. - They begin the game with a the Book of Debilitation, a ranged weapon of their + They begin the game with the Book of Debilitation, a ranged weapon of their choice, and a robe. Enchanters @@ -2254,7 +2254,7 @@ Shields Affects the amount of protection you gain by using a shield, and the degree to which it hinders you. For most races, 5/15/25 skill is enough to mitigate the encumbrance of bucklers/shields/large shields respectively, though larger - races need less skill and and smaller races more. + races need less skill and smaller races more. Invocations Affects your ability to call on your god for aid. Those skilled at Invocations From a05ef93d1c622d88e6de9121abf6fff00c4f53c1 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 14 Oct 2019 16:09:42 -0400 Subject: [PATCH 817/864] Fix seed selection on webtiles Eventually this needs to be rewritten to use a browser text input box. (cherry picked from commit a8c9d54b122a307e71834c01b7345f0af7ca67df) --- crawl-ref/source/newgame.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index ba504a4f5f51..1a600c7d050f 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -760,6 +760,8 @@ static keyfun_action _keyfun_seed_input(int &ch) static void _choose_seed(newgame_def& ng, newgame_def& choice, const newgame_def& defaults) { + tiles_crt_popup show_as_popup; + char buf[21]; // max unsigned 64 bit integer is 20 chars in decimal, // specifically 18446744073709551615 buf[0] = '\0'; From 42a7a381cca29fc132153b41c70ecdd2ec328eec Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 14 Oct 2019 16:25:26 -0400 Subject: [PATCH 818/864] Fix the build on non-webtiles (aidanh) (cherry picked from commit 2fe12d4386d8d399d6b259f6da479d730a690a8a) --- crawl-ref/source/newgame.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 1a600c7d050f..541d0bf077eb 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -760,7 +760,9 @@ static keyfun_action _keyfun_seed_input(int &ch) static void _choose_seed(newgame_def& ng, newgame_def& choice, const newgame_def& defaults) { +#ifdef USE_TILE_WEB tiles_crt_popup show_as_popup; +#endif char buf[21]; // max unsigned 64 bit integer is 20 chars in decimal, // specifically 18446744073709551615 From 656096ae3ffa13a6641e9ff6856c5ca4bebfdae1 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Tue, 15 Oct 2019 00:39:24 +0800 Subject: [PATCH 819/864] rltiles: Allow referencing generated images by enum Wherever image filenames are used, you can now also refer to an already-generated tile by its enum name. The first such matching tile is chosen; there is no support (yet?) for selecting a variation. The motivation for this feature is to reduce duplication and ensure that changes between tiles are synchronized. (cherry picked from commit 8166f019b953866b0e66fb451f708ec35bdc87a2) --- .../rltiles/tool/tile_list_processor.cc | 19 +++++++++++++++++++ .../source/rltiles/tool/tile_list_processor.h | 1 + 2 files changed, 20 insertions(+) diff --git a/crawl-ref/source/rltiles/tool/tile_list_processor.cc b/crawl-ref/source/rltiles/tool/tile_list_processor.cc index 3598600bdce7..7a12fda94ff8 100644 --- a/crawl-ref/source/rltiles/tool/tile_list_processor.cc +++ b/crawl-ref/source/rltiles/tool/tile_list_processor.cc @@ -39,11 +39,30 @@ tile_list_processor::~tile_list_processor() delete m_texture; } +bool tile_list_processor::load_image_from_tile(tile &img, string filename) +{ + if (filename.substr(0, 5) != "enum:") + return false; + const string enumname = filename.substr(5); + + int idx = m_page.find(enumname); + if (idx == -1) + return false; + + img.copy(*m_page.m_tiles[idx]); + for (int i = 0; i < MAX_COLOUR; ++i) + img.add_variation(i, -1); + return true; +} + bool tile_list_processor::load_image(tile &img, const char *filename, bool background) { assert(filename); + if (load_image_from_tile(img, filename)) + return true; + char temp[1024]; const unsigned int num_ext = 3; diff --git a/crawl-ref/source/rltiles/tool/tile_list_processor.h b/crawl-ref/source/rltiles/tool/tile_list_processor.h index 4d937d7b0a39..fdb900738140 100644 --- a/crawl-ref/source/rltiles/tool/tile_list_processor.h +++ b/crawl-ref/source/rltiles/tool/tile_list_processor.h @@ -16,6 +16,7 @@ class tile_list_processor bool process_list(const char *list_file); bool write_data(bool image, bool code); protected: + bool load_image_from_tile(tile &img, string filename); bool load_image(tile &img, const char *filename, bool background = false); bool process_line(char *read_line, const char *list_file, int line); void add_image(tile &img, const char *enumname); From 47935d78e52455291a1b6c4a8036da25f7757c3f Mon Sep 17 00:00:00 2001 From: Nikolai Lavsky <3328424+nlavsky@users.noreply.github.com> Date: Fri, 11 Oct 2019 15:56:50 +0300 Subject: [PATCH 820/864] Refactor the processing of species/job tiles This commit fixes a couple of enum names, removes unnecessary file extensions, and replaces repeating file paths with `%sdir`. (cherry picked from commit 8ac2ca0a91b020a8583ee65b112d933542f3b071) --- crawl-ref/source/rltiles/dc-gui.txt | 274 ++++++++++++++-------------- 1 file changed, 139 insertions(+), 135 deletions(-) diff --git a/crawl-ref/source/rltiles/dc-gui.txt b/crawl-ref/source/rltiles/dc-gui.txt index 7d420b3b895e..46523d5e8afe 100644 --- a/crawl-ref/source/rltiles/dc-gui.txt +++ b/crawl-ref/source/rltiles/dc-gui.txt @@ -165,192 +165,196 @@ misc/error ERROR prompt_yes PROMPT_YES prompt_no PROMPT_NO -tutorial/movement.png TUT_MOVEMENT -tutorial/combat.png TUT_COMBAT +%sdir gui/tutorial +movement TUT_MOVEMENT +combat TUT_COMBAT -%texture backgrounds/enabled-fg -backgrounds/Fi.png JOB_RECOMMENDED_FIGHTER -backgrounds/Gl.png JOB_RECOMMENDED_GLADIATOR -backgrounds/Mo.png JOB_RECOMMENDED_MONK -backgrounds/Hu.png JOB_RECOMMENDED_HUNTER -backgrounds/As.png JOB_RECOMMENDED_ASSASSIN -backgrounds/Ar.png JOB_RECOMMENDED_ARTIFICER -backgrounds/Wn.png JOB_RECOMMENDED_WANDERER -backgrounds/Be.png JOB_RECOMMENDED_BERSERKER -backgrounds/AK.png JOB_RECOMMENDED_ABYSSAL_KNIGHT -backgrounds/CK.png JOB_RECOMMENDED_CHAOS_KNIGHT -backgrounds/Sk.png JOB_RECOMMENDED_SKALD -backgrounds/Tm.png JOB_RECOMMENDED_TRANSMUTER -backgrounds/AM.png JOB_RECOMMENDED_ARCANE_MARKSMAN -backgrounds/Wr.png JOB_RECOMMENDED_WARPER -backgrounds/En.png JOB_RECOMMENDED_ENCHANTER -backgrounds/Wz.png JOB_RECOMMENDED_WIZARD -backgrounds/Cj.png JOB_RECOMMENDED_CONJURER -backgrounds/Su.png JOB_RECOMMENDED_SUMMONER -backgrounds/Ne.png JOB_RECOMMENDED_NECROMANCER -backgrounds/FE.png JOB_RECOMMENDED_FIRE_ELEMENTALIST -backgrounds/IE.png JOB_RECOMMENDED_ICE_ELEMENTALIST -backgrounds/AE.png JOB_RECOMMENDED_AIR_ELEMENTALIST -backgrounds/EE.png JOB_RECOMMENDED_EARTH_ELEMENTALIST -backgrounds/VM.png JOB_RECOMMENDED_VENOM_MAGE +%sdir gui/backgrounds +%texture enabled-fg +Fi JOB_RECOMMENDED_FIGHTER +Gl JOB_RECOMMENDED_GLADIATOR +Mo JOB_RECOMMENDED_MONK +Hu JOB_RECOMMENDED_HUNTER +As JOB_RECOMMENDED_ASSASSIN +Ar JOB_RECOMMENDED_ARTIFICER +Wn JOB_RECOMMENDED_WANDERER +Be JOB_RECOMMENDED_BERSERKER +AK JOB_RECOMMENDED_ABYSSAL_KNIGHT +CK JOB_RECOMMENDED_CHAOS_KNIGHT +Sk JOB_RECOMMENDED_SKALD +Tm JOB_RECOMMENDED_TRANSMUTER +AM JOB_RECOMMENDED_ARCANE_MARKSMAN +Wr JOB_RECOMMENDED_WARPER +En JOB_RECOMMENDED_ENCHANTER +Wz JOB_RECOMMENDED_WIZARD +Cj JOB_RECOMMENDED_CONJURER +Su JOB_RECOMMENDED_SUMMONER +Ne JOB_RECOMMENDED_NECROMANCER +FE JOB_RECOMMENDED_FIRE_ELEMENTALIST +IE JOB_RECOMMENDED_ICE_ELEMENTALIST +AE JOB_RECOMMENDED_AIR_ELEMENTALIST +EE JOB_RECOMMENDED_EARTH_ELEMENTALIST +VM JOB_RECOMMENDED_VENOM_MAGE %syn LAST_RECOMMENDED_JOB -%texture backgrounds/disabled-fg -backgrounds/Fi.png JOB_FIGHTER -backgrounds/Gl.png JOB_GLADIATOR -backgrounds/Mo.png JOB_MONK -backgrounds/Hu.png JOB_HUNTER -backgrounds/As.png JOB_ASSASSIN -backgrounds/Ar.png JOB_ARTIFICER -backgrounds/Wn.png JOB_WANDERER -backgrounds/Be.png JOB_BERSERKER -backgrounds/AK.png JOB_ABYSSAL_KNIGHT -backgrounds/CK.png JOB_CHAOS_KNIGHT -backgrounds/Sk.png JOB_SKALD -backgrounds/Tm.png JOB_TRANSMUTER -backgrounds/AM.png JOB_ARCANE_MARKSMAN -backgrounds/Wr.png JOB_WARPER -backgrounds/En.png JOB_ENCHANTER -backgrounds/Wz.png JOB_WIZARD -backgrounds/Cj.png JOB_CONJURER -backgrounds/Su.png JOB_SUMMONER -backgrounds/Ne.png JOB_NECROMANCER -backgrounds/FE.png JOB_FIRE_ELEMENTALIST -backgrounds/IE.png JOB_ICE_ELEMENTALIST -backgrounds/AE.png JOB_AIR_ELEMENTALIST -backgrounds/EE.png JOB_EARTH_ELEMENTALIST -backgrounds/VM.png JOB_VENOM_MAGE +%texture disabled-fg +Fi JOB_FIGHTER +Gl JOB_GLADIATOR +Mo JOB_MONK +Hu JOB_HUNTER +As JOB_ASSASSIN +Ar JOB_ARTIFICER +Wn JOB_WANDERER +Be JOB_BERSERKER +AK JOB_ABYSSAL_KNIGHT +CK JOB_CHAOS_KNIGHT +Sk JOB_SKALD +Tm JOB_TRANSMUTER +AM JOB_ARCANE_MARKSMAN +Wr JOB_WARPER +En JOB_ENCHANTER +Wz JOB_WIZARD +Cj JOB_CONJURER +Su JOB_SUMMONER +Ne JOB_NECROMANCER +FE JOB_FIRE_ELEMENTALIST +IE JOB_ICE_ELEMENTALIST +AE JOB_AIR_ELEMENTALIST +EE JOB_EARTH_ELEMENTALIST +VM JOB_VENOM_MAGE %syn LAST_JOB - +%sdir player %texture none -../player/felids/cat3.png SP_RECOMMENDED_FELID +felids/cat3 SP_RECOMMENDED_FELID %start -%compose ../player/base/centaur_lightgrey_f.png -%compose ../player/body/animal_skin.png +%compose base/centaur_lightgrey_f +%compose body/animal_skin %finish SP_RECOMMENDED_CENTAUR %start -%compose ../player/base/deep_dwarf_m.png -%compose ../player/body/animal_skin.png +%compose base/deep_dwarf_m +%compose body/animal_skin %finish SP_RECOMMENDED_DEEP_DWARF %start -%compose ../player/base/deep_elf_f.png -%compose ../player/body/animal_skin.png +%compose base/deep_elf_f +%compose body/animal_skin %finish SP_RECOMMENDED_DEEP_ELF %start -%compose ../player/base/demigod_f.png -%compose ../player/body/animal_skin.png +%compose base/demigod_f +%compose body/animal_skin %finish SP_RECOMMENDED_DEMIGOD %start -%compose ../player/base/demonspawn_pink.png -%compose ../player/body/animal_skin.png -%finish SP_RECOMMENDED_DEMONSP_RECOMMENDEDAWN +%compose base/demonspawn_pink +%compose body/animal_skin +%finish SP_RECOMMENDED_DEMONSPAWN %start -%compose ../player/base/draconian_f.png -%compose ../player/body/animal_skin.png +%compose base/draconian_f +%compose body/animal_skin %finish SP_RECOMMENDED_BASE_DRACONIAN %start -%compose ../player/base/formicid.png -%compose ../player/body/animal_skin.png +%compose base/formicid +%compose body/animal_skin %finish SP_RECOMMENDED_FORMICID %start -%compose ../player/base/frog_m.png -%compose ../player/body/animal_skin.png +%compose base/frog_m +%compose body/animal_skin %finish SP_RECOMMENDED_BARACHI %start -%compose ../player/base/gargoyle_m.png -%compose ../player/body/animal_skin.png +%compose base/gargoyle_m +%compose body/animal_skin %finish SP_RECOMMENDED_GARGOYLE %start -%compose ../player/base/ghoul_m.png -%compose ../player/body/animal_skin.png +%compose base/ghoul_m +%compose body/animal_skin %finish SP_RECOMMENDED_GHOUL %start -%compose ../player/base/gnoll_m.png -%compose ../player/body/animal_skin.png +%compose base/gnoll_m +%compose body/animal_skin %finish SP_RECOMMENDED_GNOLL %start -%compose ../player/base/halfling_m.png -%compose ../player/body/animal_skin.png +%compose base/halfling_m +%compose body/animal_skin %finish SP_RECOMMENDED_HALFLING %start -%compose ../player/base/human_f.png -%compose ../player/body/animal_skin.png -%finish SP_RECOMMENDED_HuMAN +%compose base/human_f +%compose body/animal_skin +%finish SP_RECOMMENDED_HUMAN %start -%compose ../player/base/kobold_m.png -%compose ../player/body/animal_skin.png +%compose base/kobold_m +%compose body/animal_skin %finish SP_RECOMMENDED_KOBOLD %start -%compose ../player/base/merfolk_water_f.png -%compose ../player/body/animal_skin.png +%compose base/merfolk_water_f +%compose body/animal_skin %finish SP_RECOMMENDED_MERFOLK %start -%compose ../player/base/minotaur_m.png -%compose ../player/body/animal_skin.png +%compose base/minotaur_m +%compose body/animal_skin %finish SP_RECOMMENDED_MINOTAUR -../player/base/mummy_m.png SP_RECOMMENDED_MUMMY +base/mummy_m SP_RECOMMENDED_MUMMY %start -%compose ../player/base/naga_f.png -%compose ../player/body/animal_skin.png +%compose base/naga_f +%compose body/animal_skin %finish SP_RECOMMENDED_NAGA -../player/base/octopode1.png SP_RECOMMENDED_OCTOPODE +base/octopode1 SP_RECOMMENDED_OCTOPODE %start -%compose ../player/base/ogre_m.png -%compose ../player/body/animal_skin.png +%compose base/ogre_m +%compose body/animal_skin %finish SP_RECOMMENDED_OGRE %start -%compose ../player/base/orc_f.png -%compose ../player/body/animal_skin.png +%compose base/orc_f +%compose body/animal_skin %finish SP_RECOMMENDED_HILL_ORC %start -%compose ../player/base/spriggan_m.png -%compose ../player/body/animal_skin.png -%finish SP_RECOMMENDED_SP_RECOMMENDEDRIGGAN +%compose base/spriggan_m +%compose body/animal_skin +%finish SP_RECOMMENDED_SPRIGGAN %start -%compose ../player/base/tengu_winged_f.png -%compose ../player/body/animal_skin.png +%compose base/tengu_winged_f +%compose body/animal_skin %finish SP_RECOMMENDED_TENGU %start -%compose ../player/base/troll_f.png -%compose ../player/body/animal_skin.png +%compose base/troll_f +%compose body/animal_skin %finish SP_RECOMMENDED_TROLL %start -%compose ../player/base/vampire_f.png -%compose ../player/body/animal_skin.png +%compose base/vampire_f +%compose body/animal_skin %finish SP_RECOMMENDED_VAMPIRE %start -%compose ../player/base/vine_stalker_f.png -%compose ../player/body/animal_skin.png +%compose base/vine_stalker_f +%compose body/animal_skin %finish SP_RECOMMENDED_VINE_STALKER %syn LAST_RECOMMENDED_SPECIES -%texture backgrounds/disabled-fg -../player/felids/cat3.png SP_FELID -../player/base/centaur_lightgrey_f.png SP_CENTAUR -../player/base/deep_dwarf_m.png SP_DEEP_DWARF -../player/base/deep_elf_f.png SP_DEEP_ELF -../player/base/demigod_f.png SP_DEMIGOD -../player/base/demonspawn_pink.png SP_DEMONSPAWN -../player/base/draconian_f.png SP_DRACONIAN -../player/base/formicid.png SP_FORMICID -../player/base/frog_m.png SP_BARACHI -../player/base/gargoyle_m.png SP_GARGOYLE -../player/base/ghoul_m.png SP_GHOUL -../player/base/gnoll_m.png SP_GNOLL -../player/base/halfling_m.png SP_HALFLING -../player/base/human_f.png SP_HUMAN -../player/base/kobold_m.png SP_KOBOLD -../player/base/merfolk_water_f.png SP_MERFOLK -../player/base/minotaur_m.png SP_MINOTAUR -../player/base/mummy_m.png SP_MUMMY -../player/base/naga_f.png SP_NAGA -../player/base/octopode1.png SP_OCTOPODE -../player/base/ogre_m.png SP_OGRE -../player/base/orc_f.png SP_HILL_ORC -../player/base/spriggan_m.png SP_SPRIGGAN -../player/base/tengu_wingless_f.png SP_TENGU -../player/base/troll_f.png SP_TROLL -../player/base/vampire_f.png SP_VAMPIRE -../player/base/vine_stalker_f.png SP_VINE_STALKER +%sdir gui/backgrounds +%texture disabled-fg +%sdir player/base +../felids/cat3 SP_FELID +centaur_lightgrey_f SP_CENTAUR +deep_dwarf_m SP_DEEP_DWARF +deep_elf_f SP_DEEP_ELF +demigod_f SP_DEMIGOD +demonspawn_pink SP_DEMONSPAWN +draconian_f SP_DRACONIAN +formicid SP_FORMICID +frog_m SP_BARACHI +gargoyle_m SP_GARGOYLE +ghoul_m SP_GHOUL +gnoll_m SP_GNOLL +halfling_m SP_HALFLING +human_f SP_HUMAN +kobold_m SP_KOBOLD +merfolk_water_f SP_MERFOLK +minotaur_m SP_MINOTAUR +mummy_m SP_MUMMY +naga_f SP_NAGA +octopode1 SP_OCTOPODE +ogre_m SP_OGRE +orc_f SP_HILL_ORC +spriggan_m SP_SPRIGGAN +tengu_wingless_f SP_TENGU +troll_f SP_TROLL +vampire_f SP_VAMPIRE +vine_stalker_f SP_VINE_STALKER %syn LAST_SPECIES From 726ef2547da468cfad239fce7155339294c9449f Mon Sep 17 00:00:00 2001 From: Nikolai Lavsky <3328424+nlavsky@users.noreply.github.com> Date: Fri, 11 Oct 2019 18:16:50 +0300 Subject: [PATCH 821/864] Add details to the newgame dolls This commit adds hair, claws, and horns to player dolls on the species selection menu. These extra bits are selected according to the default values from `tilep_race_default()` and `fill_doll_equipment()`. (cherry picked from commit 653463b16ece33b9f0f7cfb00c930483d90158d0) --- crawl-ref/source/rltiles/dc-gui.txt | 73 ++++++++++++++++++----------- 1 file changed, 45 insertions(+), 28 deletions(-) diff --git a/crawl-ref/source/rltiles/dc-gui.txt b/crawl-ref/source/rltiles/dc-gui.txt index 46523d5e8afe..6d35521a2abc 100644 --- a/crawl-ref/source/rltiles/dc-gui.txt +++ b/crawl-ref/source/rltiles/dc-gui.txt @@ -230,18 +230,24 @@ felids/cat3 SP_RECOMMENDED_FELID %start %compose base/centaur_lightgrey_f %compose body/animal_skin +%compose hair/short_black +%compose boots/hooves %finish SP_RECOMMENDED_CENTAUR %start %compose base/deep_dwarf_m %compose body/animal_skin +%compose hair/short_white +%compose beard/garibaldi_white %finish SP_RECOMMENDED_DEEP_DWARF %start %compose base/deep_elf_f %compose body/animal_skin +%compose hair/elf_white %finish SP_RECOMMENDED_DEEP_ELF %start %compose base/demigod_f %compose body/animal_skin +%compose hair/short_black %finish SP_RECOMMENDED_DEMIGOD %start %compose base/demonspawn_pink @@ -250,6 +256,7 @@ felids/cat3 SP_RECOMMENDED_FELID %start %compose base/draconian_f %compose body/animal_skin +%compose drchead/drchead_brown %finish SP_RECOMMENDED_BASE_DRACONIAN %start %compose base/formicid @@ -274,10 +281,12 @@ felids/cat3 SP_RECOMMENDED_FELID %start %compose base/halfling_m %compose body/animal_skin +%compose hair/short_black %finish SP_RECOMMENDED_HALFLING %start %compose base/human_f %compose body/animal_skin +%compose hair/short_black %finish SP_RECOMMENDED_HUMAN %start %compose base/kobold_m @@ -286,20 +295,24 @@ felids/cat3 SP_RECOMMENDED_FELID %start %compose base/merfolk_water_f %compose body/animal_skin +%compose hair/green %finish SP_RECOMMENDED_MERFOLK %start %compose base/minotaur_m %compose body/animal_skin +%compose head/horns2 %finish SP_RECOMMENDED_MINOTAUR base/mummy_m SP_RECOMMENDED_MUMMY %start %compose base/naga_f %compose body/animal_skin +%compose hair/part2_red %finish SP_RECOMMENDED_NAGA base/octopode1 SP_RECOMMENDED_OCTOPODE %start %compose base/ogre_m %compose body/animal_skin +%compose hair/short_black %finish SP_RECOMMENDED_OGRE %start %compose base/orc_f @@ -308,18 +321,23 @@ base/octopode1 SP_RECOMMENDED_OCTOPODE %start %compose base/spriggan_m %compose body/animal_skin +%compose beard/medium_green %finish SP_RECOMMENDED_SPRIGGAN %start %compose base/tengu_winged_f %compose body/animal_skin +%compose hair/short_black %finish SP_RECOMMENDED_TENGU %start %compose base/troll_f %compose body/animal_skin +%compose hair/troll +%compose gloves/claws %finish SP_RECOMMENDED_TROLL %start %compose base/vampire_f %compose body/animal_skin +%compose hair/arwen %finish SP_RECOMMENDED_VAMPIRE %start %compose base/vine_stalker_f @@ -329,32 +347,31 @@ base/octopode1 SP_RECOMMENDED_OCTOPODE %sdir gui/backgrounds %texture disabled-fg -%sdir player/base -../felids/cat3 SP_FELID -centaur_lightgrey_f SP_CENTAUR -deep_dwarf_m SP_DEEP_DWARF -deep_elf_f SP_DEEP_ELF -demigod_f SP_DEMIGOD -demonspawn_pink SP_DEMONSPAWN -draconian_f SP_DRACONIAN -formicid SP_FORMICID -frog_m SP_BARACHI -gargoyle_m SP_GARGOYLE -ghoul_m SP_GHOUL -gnoll_m SP_GNOLL -halfling_m SP_HALFLING -human_f SP_HUMAN -kobold_m SP_KOBOLD -merfolk_water_f SP_MERFOLK -minotaur_m SP_MINOTAUR -mummy_m SP_MUMMY -naga_f SP_NAGA -octopode1 SP_OCTOPODE -ogre_m SP_OGRE -orc_f SP_HILL_ORC -spriggan_m SP_SPRIGGAN -tengu_wingless_f SP_TENGU -troll_f SP_TROLL -vampire_f SP_VAMPIRE -vine_stalker_f SP_VINE_STALKER +enum:SP_RECOMMENDED_FELID SP_FELID +enum:SP_RECOMMENDED_CENTAUR SP_CENTAUR +enum:SP_RECOMMENDED_DEEP_DWARF SP_DEEP_DWARF +enum:SP_RECOMMENDED_DEEP_ELF SP_DEEP_ELF +enum:SP_RECOMMENDED_DEMIGOD SP_DEMIGOD +enum:SP_RECOMMENDED_DEMONSPAWN SP_DEMONSPAWN +enum:SP_RECOMMENDED_BASE_DRACONIAN SP_DRACONIAN +enum:SP_RECOMMENDED_FORMICID SP_FORMICID +enum:SP_RECOMMENDED_BARACHI SP_BARACHI +enum:SP_RECOMMENDED_GARGOYLE SP_GARGOYLE +enum:SP_RECOMMENDED_GHOUL SP_GHOUL +enum:SP_RECOMMENDED_GNOLL SP_GNOLL +enum:SP_RECOMMENDED_HALFLING SP_HALFLING +enum:SP_RECOMMENDED_HUMAN SP_HUMAN +enum:SP_RECOMMENDED_KOBOLD SP_KOBOLD +enum:SP_RECOMMENDED_MERFOLK SP_MERFOLK +enum:SP_RECOMMENDED_MINOTAUR SP_MINOTAUR +enum:SP_RECOMMENDED_MUMMY SP_MUMMY +enum:SP_RECOMMENDED_NAGA SP_NAGA +enum:SP_RECOMMENDED_OCTOPODE SP_OCTOPODE +enum:SP_RECOMMENDED_OGRE SP_OGRE +enum:SP_RECOMMENDED_HILL_ORC SP_HILL_ORC +enum:SP_RECOMMENDED_SPRIGGAN SP_SPRIGGAN +enum:SP_RECOMMENDED_TENGU SP_TENGU +enum:SP_RECOMMENDED_TROLL SP_TROLL +enum:SP_RECOMMENDED_VAMPIRE SP_VAMPIRE +enum:SP_RECOMMENDED_VINE_STALKER SP_VINE_STALKER %syn LAST_SPECIES From ff0f5c72dbc828b16955105224cb8314dd4e086f Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sun, 13 Oct 2019 20:28:18 +0800 Subject: [PATCH 822/864] Fix off-by-one error (cherry picked from commit 8ab17b4d2b7dafdb021fed17c8ebc0f09d1c9a65) --- crawl-ref/source/ui.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 9135723acf28..0c246b46e1c2 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -997,7 +997,7 @@ void Switcher::_render() { if (m_children.size() == 0) return; - m_current = max(0, min(m_current, (int)m_children.size())); + m_current = max(0, min(m_current, (int)m_children.size()-1)); m_children[m_current]->render(); } From bd631bd1fb96bf74f77ec9ee3a82ac52179e972d Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sun, 13 Oct 2019 20:29:01 +0800 Subject: [PATCH 823/864] Add ui::Switcher::current_widget() (cherry picked from commit bc5b4a908130be380b4a18ab690fca2f520bc087) --- crawl-ref/source/ui.cc | 8 ++++++++ crawl-ref/source/ui.h | 1 + 2 files changed, 9 insertions(+) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 0c246b46e1c2..86e74e110f9a 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -993,6 +993,14 @@ int& Switcher::current() return m_current; } +shared_ptr Switcher::current_widget() +{ + if (m_children.size() == 0) + return nullptr; + m_current = max(0, min(m_current, (int)m_children.size()-1)); + return m_children[m_current]; +} + void Switcher::_render() { if (m_children.size() == 0) diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index 0a3d79c241a5..c39d68ad82c0 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -472,6 +472,7 @@ class Switcher : public ContainerVec virtual ~Switcher() {}; void add_child(shared_ptr child); int& current(); + shared_ptr current_widget(); Widget::Align align_x = START, align_y = START; From 44672012a7f772405f2ff953f3a2411f415a099a Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sun, 13 Oct 2019 20:37:40 +0800 Subject: [PATCH 824/864] Fix some event forwarding bugs Previously, the UI framework would propagate events from the topmost root widget down to child widgets. The framework has since been changed to propagate events up from a focused widget, inadvertently breaking these event handlers' custom event propagation. (cherry picked from commit c27d5b89ad21ab1e687614b88ab6f4bfd976ac8e) --- crawl-ref/source/command.cc | 9 ++++----- crawl-ref/source/describe-god.cc | 4 ++-- crawl-ref/source/describe.cc | 9 ++++----- crawl-ref/source/mutation.cc | 2 +- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc index 82c071755b4c..e5895e14b92d 100644 --- a/crawl-ref/source/command.cc +++ b/crawl-ref/source/command.cc @@ -239,11 +239,10 @@ static void _print_version() auto popup = make_shared(vbox); bool done = false; - popup->on(Widget::slots.event, [&done, &vbox](wm_event ev) { - if (ev.type != WME_KEYDOWN) - return false; - done = !vbox->on_event(ev); - return true; + popup->on(Widget::slots.event, [&done, &scroller](wm_event ev) { + if (scroller->on_event(ev)) + return true; + return done = ev.type == WME_KEYDOWN; }); #ifdef USE_TILE_WEB diff --git a/crawl-ref/source/describe-god.cc b/crawl-ref/source/describe-god.cc index 86a5afdc9a64..2e22b21844ad 100644 --- a/crawl-ref/source/describe-god.cc +++ b/crawl-ref/source/describe-god.cc @@ -1239,7 +1239,7 @@ void describe_god(god_type which_god) #endif return true; } - return done = !popup->get_child()->on_event(ev); + return done = !desc_sw->current_widget()->on_event(ev); }); #ifdef USE_TILE_WEB @@ -1351,7 +1351,7 @@ bool describe_god_with_join(god_type which_god) // Next, allow child widgets to handle scrolling keys if (keyin != ' ' && keyin != CK_ENTER) - if (popup->get_child()->on_event(ev)) + if (desc_sw->current_widget()->on_event(ev)) return true; if (step == SHOW) diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index d005b780f777..e61b234c857a 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -176,7 +176,7 @@ int show_description(const describe_info &inf, const tile_def *tile) if (!inf.quote.empty() && (lastch == '!' || lastch == CK_MOUSE_CMD || lastch == '^')) switcher->current() = 1 - switcher->current(); else - done = !vbox->on_event(ev); + done = !switcher->current_widget()->on_event(ev); return true; }); @@ -2364,10 +2364,9 @@ void describe_feature_wide(const coord_def& pos) bool done = false; popup->on(Widget::slots.event, [&](wm_event ev) { - if (ev.type != WME_KEYDOWN) - return false; - done = !scroller->on_event(ev); - return true; + if (scroller->on_event(ev)) + return true; + return done = ev.type == WME_KEYDOWN; }); #ifdef USE_TILE_WEB diff --git a/crawl-ref/source/mutation.cc b/crawl-ref/source/mutation.cc index c50f0d5fc6c7..a95f51e8ed5c 100644 --- a/crawl-ref/source/mutation.cc +++ b/crawl-ref/source/mutation.cc @@ -902,7 +902,7 @@ void display_mutations() tiles.ui_state_change("mutations", 0); #endif } else - done = !vbox->on_event(ev); + done = !switcher->current_widget()->on_event(ev); return true; }); From 65f01f3a6f5788cecce68500812078d5f9e4ccd8 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sun, 13 Oct 2019 00:36:52 +0800 Subject: [PATCH 825/864] Fix segfault when delivering mousebutton events The previous code used a reverse iterator that could be invalidated by the hover path changing during event handling, causing a segmentation fault. It may be better to first copy the hover path and then iterate over that; this would matter if an event handler changed something in the hover path. But the semantics of event emission aren't strongly defined at this point; better to wait for a use-case and revisit this then. (cherry picked from commit 2533fd6716c45e76221f03fef3ed8a6809029741) --- crawl-ref/source/ui.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 86e74e110f9a..d56be462ca87 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -1930,9 +1930,11 @@ bool UIRoot::on_event(const wm_event& event) } #endif case WME_MOUSEWHEEL: - for (auto w = prev_hover_path.rbegin(); w != prev_hover_path.rend(); ++w) - if ((*w)->on_event(event)) - return true; + if (!prev_hover_path.empty()) { + for (auto w = prev_hover_path.back(); w; w = w->_get_parent()) + if (w->on_event(event)) + return true; + } break; case WME_MOUSEENTER: case WME_MOUSELEAVE: From 1bb75cea03d5c942b3e44f1df099e4bc1ffa29b3 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Tue, 15 Oct 2019 21:13:19 +0800 Subject: [PATCH 826/864] Don't allow showing messages on arena team choice UI It's always empty. (cherry picked from commit b94451d52d752c47a3f6b11fe95de0be32013b78) --- crawl-ref/source/arena.cc | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/crawl-ref/source/arena.cc b/crawl-ref/source/arena.cc index a02e45d95db4..a4283e62c4f6 100644 --- a/crawl-ref/source/arena.cc +++ b/crawl-ref/source/arena.cc @@ -1487,13 +1487,7 @@ static void _choose_arena_teams(newgame_def& choice, popup->on(Widget::slots.event, [&](wm_event ev) { if (ev.type != WME_KEYDOWN) return false; - int key = ev.key.keysym.sym; - if (key == CONTROL('P')) - { - replay_messages(); - return false; - } - key = reader.putkey(key); + const int key = reader.putkey(ev.key.keysym.sym); if (key == -1) return true; cancel = !!key; From 333a2cbe936b6d891e45238b73dbdacf448e8b3e Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 14 Oct 2019 20:51:45 +0800 Subject: [PATCH 827/864] Factor out Region::contains_point() This commit also fixes a few off-by-one bugs in widget hit testing. (cherry picked from commit f4602a88a1253db68e0bd17228506ec9ca36c23c) --- crawl-ref/source/ui.cc | 32 +++++++------------------------- crawl-ref/source/ui.h | 5 +++++ 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index d56be462ca87..abad092ca7d6 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -44,15 +44,6 @@ static Region aabb_union(Region a, Region b) return i; } -static inline bool pos_in_rect(int x, int y, Region rect) -{ - if (x < rect.x || x >= rect.ex()) - return false; - if (y < rect.y || y >= rect.ey()) - return false; - return true; -} - #ifndef USE_TILE_LOCAL static void clear_text_region(Region region, COLOURS bg); #endif @@ -134,21 +125,16 @@ bool Widget::on_event(const wm_event& event) shared_ptr ContainerVec::get_child_at_offset(int x, int y) { for (shared_ptr& child : m_children) - { - const Region region = child->get_region(); - bool inside = (x >= region.x && x < region.x + region.width) - && (y >= region.y && y < region.y + region.height); - if (inside) + if (child->get_region().contains_point(x, y)) return child; - } return nullptr; } shared_ptr Bin::get_child_at_offset(int x, int y) { - bool inside = (x > m_region.x && x < m_region.x + m_region.width) - && (y > m_region.y && y < m_region.y + m_region.height); - return inside ? m_child : nullptr; + if (m_child && m_child->get_region().contains_point(x, y)) + return m_child; + return nullptr; } void Bin::set_child(shared_ptr child) @@ -937,9 +923,7 @@ shared_ptr Stack::get_child_at_offset(int x, int y) { if (m_children.size() == 0) return nullptr; - const Region region = m_children.back()->get_region(); - bool inside = (x > region.x && x < region.x + region.width) - && (y > region.y && y < region.y + region.height); + bool inside = m_children.back()->get_region().contains_point(x, y); return inside ? m_children.back() : nullptr; } @@ -1063,9 +1047,7 @@ shared_ptr Switcher::get_child_at_offset(int x, int y) return nullptr; int c = max(0, min(m_current, (int)m_children.size())); - const auto region = m_children[c]->get_region(); - bool inside = (x >= region.x && x < region.x + region.width) - && (y >= region.y && y < region.y + region.height); + bool inside = m_children[c]->get_region().contains_point(x, y); return inside ? m_children[c] : nullptr; } @@ -1098,7 +1080,7 @@ shared_ptr Grid::get_child_at_offset(int x, int y) { if (child.pos.x <= col && col < child.pos.x + child.span.width) if (child.pos.y <= row && row < child.pos.y + child.span.height) - if (pos_in_rect(x, y, child.widget->get_region())) + if (child.widget->get_region().contains_point(x, y)) return child.widget; } return nullptr; diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index c39d68ad82c0..a7f5fa5e6eb7 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -64,6 +64,11 @@ class Region constexpr int ex() const { return x + width; } constexpr int ey() const { return y + height; } + constexpr bool contains_point(int _x, int _y) const + { + return _x >= x && _x < ex() && _y >= y && _y < ey(); + } + int x, y, width, height; }; From 7bf1ee157361a2252fe2c05b1caf9b001e03ec2a Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sun, 13 Oct 2019 00:56:50 +0800 Subject: [PATCH 828/864] Add ui::Widget::is_ancestor_of() (cherry picked from commit 6ac5fb96fa393a6fbea0829d14aee8b7cf940c87) --- crawl-ref/source/ui.cc | 14 ++++++++++++++ crawl-ref/source/ui.h | 2 ++ 2 files changed, 16 insertions(+) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index abad092ca7d6..92bf87b4f282 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -232,6 +232,20 @@ void Widget::_allocate_region() { } +/** + * Determine whether a widget contains the given widget. + * + * @param child The other widget. + * @return True if the other widget is a descendant of this widget. + */ +bool Widget::is_ancestor_of(const shared_ptr& other) +{ + for (Widget* w = other.get(); w; w = w->_get_parent()) + if (w == this) + return true; + return false; +} + void Widget::_set_parent(Widget* p) { if (!p) diff --git a/crawl-ref/source/ui.h b/crawl-ref/source/ui.h index a7f5fa5e6eb7..17beef31296a 100644 --- a/crawl-ref/source/ui.h +++ b/crawl-ref/source/ui.h @@ -168,6 +168,8 @@ class Widget : public enable_shared_from_this bool is_visible() const { return m_visible; } void set_visible(bool); + bool is_ancestor_of(const shared_ptr& other); + // Wrapper functions which handle common behavior // - margins // - caching From 473684c3910e0b3f1fda8640724a7b8933f886cb Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Thu, 17 Oct 2019 19:39:19 +0800 Subject: [PATCH 829/864] Disallow focusing widgets not in top layout (advil, 12098) On webtiles, focus events for the species menu buttons were being received after the attributes scroller had opened. On the server side, a callback would then focus the button, even though the menu had already been opened. This fix prevents widgets not in the top layer from being focused. (cherry picked from commit 65d077c5f10d2a24cee635f7ac70771bea176a20) --- crawl-ref/source/ui.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 92bf87b4f282..e41ebe7c7771 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -2417,7 +2417,12 @@ void set_focused_widget(Widget* w) static bool sent_focusout; static Widget* new_focus; - if (!ui_root.num_children()) + const auto top = top_layout(); + + if (!top) + return; + + if (w && !top->is_ancestor_of(w->get_shared())) return; auto current_focus = ui_root.focus_stack.back(); From bde2acd3dd5c423be62812c358535e4c305af0ab Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Thu, 17 Oct 2019 23:30:31 +0800 Subject: [PATCH 830/864] Tidy dc-spells.txt Sorts monster spells. The note for future removal referred to an entry for 'Rearrange the Pieces' that is already gone. (cherry picked from commit a86127ea33c0f7fb1ed673255cf7485357654e5c) --- crawl-ref/source/rltiles/dc-spells.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crawl-ref/source/rltiles/dc-spells.txt b/crawl-ref/source/rltiles/dc-spells.txt index 4911525e1533..1282078311da 100644 --- a/crawl-ref/source/rltiles/dc-spells.txt +++ b/crawl-ref/source/rltiles/dc-spells.txt @@ -174,6 +174,7 @@ generic GENERIC_MONSTER_SPELL air_elementals AIR_ELEMENTALS blink_other BLINK_OTHER brain_feed BRAIN_FEED +call_down_damnation CALL_DOWN_DAMNATION cantrip CANTRIP cold_breath COLD_BREATH earth_elementals EARTH_ELEMENTALS @@ -184,7 +185,6 @@ fire_elementals FIRE_ELEMENTALS ghostly_fireball GHOSTLY_FIREBALL grasping_roots GRASPING_ROOTS haste_other HASTE_OTHER -call_down_damnation CALL_DOWN_DAMNATION ink_cloud INK_CLOUD iron_elementals IRON_ELEMENTALS malmutate MALMUTATE @@ -198,7 +198,6 @@ phantom_mirror PHANTOM_MIRROR polymorph POLYMORPH porkalator PORKALATOR quicksilver_bolt QUICKSILVER_BOLT -# Remove when TAG_MAJOR_VERSION > 34 sleep SLEEP spectral_cloud SPECTRAL_CLOUD spit_acid SPIT_ACID From 112412de01b8972132b8b828eae80ffd972c51bb Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Thu, 17 Oct 2019 23:33:40 +0800 Subject: [PATCH 831/864] Add tiles for a few monster spells 63 to go... as measured by `grep -B7 GENERIC spl-data.h | grep ' SPELL'` (cherry picked from commit 99cdaf76fe6cb502940e847f7b1b606ea2580ccd) --- crawl-ref/source/rltiles/dc-spells.txt | 8 +++++++ .../gui/spells/monster/awaken_vines.png | Bin 0 -> 299 bytes .../gui/spells/monster/create_tentacles.png | Bin 0 -> 251 bytes .../rltiles/gui/spells/monster/seal_doors.png | Bin 0 -> 546 bytes .../gui/spells/monster/sentinel_mark.png | Bin 0 -> 274 bytes .../rltiles/gui/spells/monster/sporulate.png | Bin 0 -> 351 bytes .../gui/spells/monster/strip_resistance.png | Bin 0 -> 230 bytes .../spells/monster/summon_spectral_orcs.png | Bin 0 -> 856 bytes .../gui/spells/monster/wall_of_brambles.png | Bin 0 -> 605 bytes crawl-ref/source/spl-data.h | 20 +++++++++--------- 10 files changed, 18 insertions(+), 10 deletions(-) create mode 100644 crawl-ref/source/rltiles/gui/spells/monster/awaken_vines.png create mode 100644 crawl-ref/source/rltiles/gui/spells/monster/create_tentacles.png create mode 100644 crawl-ref/source/rltiles/gui/spells/monster/seal_doors.png create mode 100644 crawl-ref/source/rltiles/gui/spells/monster/sentinel_mark.png create mode 100644 crawl-ref/source/rltiles/gui/spells/monster/sporulate.png create mode 100644 crawl-ref/source/rltiles/gui/spells/monster/strip_resistance.png create mode 100644 crawl-ref/source/rltiles/gui/spells/monster/summon_spectral_orcs.png create mode 100644 crawl-ref/source/rltiles/gui/spells/monster/wall_of_brambles.png diff --git a/crawl-ref/source/rltiles/dc-spells.txt b/crawl-ref/source/rltiles/dc-spells.txt index 1282078311da..cf3e1190dd4b 100644 --- a/crawl-ref/source/rltiles/dc-spells.txt +++ b/crawl-ref/source/rltiles/dc-spells.txt @@ -172,11 +172,13 @@ bolt_energy ENERGY_BOLT %sdir gui/spells/monster generic GENERIC_MONSTER_SPELL air_elementals AIR_ELEMENTALS +awaken_vines AWAKEN_VINES blink_other BLINK_OTHER brain_feed BRAIN_FEED call_down_damnation CALL_DOWN_DAMNATION cantrip CANTRIP cold_breath COLD_BREATH +create_tentacles CREATE_TENTACLES earth_elementals EARTH_ELEMENTALS fake_mara_summon FAKE_MARA_SUMMON fake_rakshasa_summon FAKE_RAKSHASA_SUMMON @@ -198,23 +200,29 @@ phantom_mirror PHANTOM_MIRROR polymorph POLYMORPH porkalator PORKALATOR quicksilver_bolt QUICKSILVER_BOLT +seal_doors SEAL_DOORS +sentinel_mark SENTINEL_MARK sleep SLEEP spectral_cloud SPECTRAL_CLOUD spit_acid SPIT_ACID spit_poison SPIT_POISON +sporulate SPORULATE sprint SPRINT steam_ball STEAM_BALL sticky_flame_range STICKY_FLAME_RANGE +strip_resistance STRIP_RESISTANCE summon_drakes SUMMON_DRAKES summon_eyeballs SUMMON_EYEBALLS summon_hell_beast SUMMON_HELL_BEAST summon_minor_demon SUMMON_MINOR_DEMON summon_mushrooms SUMMON_MUSHROOMS +summon_spectral_orcs SUMMON_SPECTRAL_ORCS summon_ufetubus SUMMON_UFETUBUS summon_undead SUMMON_UNDEAD summon_vermin SUMMON_VERMIN teleport TELEPORT twisted_resurrection TWISTED_RESURRECTION +wall_of_brambles WALL_OF_BRAMBLES water_elementals WATER_ELEMENTALS %back none diff --git a/crawl-ref/source/rltiles/gui/spells/monster/awaken_vines.png b/crawl-ref/source/rltiles/gui/spells/monster/awaken_vines.png new file mode 100644 index 0000000000000000000000000000000000000000..602abc953ed1b194cd985c3d4e0e084cad832305 GIT binary patch literal 299 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvtpJ}8S0L}mks}i(OaKZP7#KJ> zIIvVQFo!U(_AxBGqP63-5c?JewjB(d*BR1V4*mx!Vk`;r3ubV5b|VeQS?}rM7*fHQ ztiZ&f#H_fWVS}NNfucr&R{+C8)xCR?jV3jOR##RY%~N5VUG(_$vE}N@XDkAFgzk0* z6f)~b*%1Q?cJd*u)AfKfZ%tATM03LTPxIF0G-a@>FVdQ&MBb@0HdyLcK`qY literal 0 HcmV?d00001 diff --git a/crawl-ref/source/rltiles/gui/spells/monster/create_tentacles.png b/crawl-ref/source/rltiles/gui/spells/monster/create_tentacles.png new file mode 100644 index 0000000000000000000000000000000000000000..24b0f3340c268951894fbcf138be05bbc29b444c GIT binary patch literal 251 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfv^#Gp`SN8&+BS(%*m@ok-U|?Y2 z;NbB8^7>Q#MGX!N|F=zCS{7Fy<&o=amw5T49#92iNswPKgTu2MX+Tbsr;B4q1!J-T z6NeJB;(~?^hC&948VOyB4gTGchO-)umXtVacPFMD__|5M8%$6 zUKJn{X1P}8ok554s({$6uzeC&_2-6q)HOzQY9%mk5ehwBl58US^2NizR=o|`#CC34D4TGnvpUXO@geCyGLsz8$ literal 0 HcmV?d00001 diff --git a/crawl-ref/source/rltiles/gui/spells/monster/seal_doors.png b/crawl-ref/source/rltiles/gui/spells/monster/seal_doors.png new file mode 100644 index 0000000000000000000000000000000000000000..db14ea9692267c2e1317261c37d02a87dce4922e GIT binary patch literal 546 zcmV+-0^R+IP)=denQ2T`f;Q6VZQa}I%Y(RlR1Dh=c7+@PN@7q=;5)CgG2~K1dm=G5Fp_JV1IkmKumZT;BYjKOc+i?hdP|j z<}gSm2?1+EntToiWSN8&+BS(%*m@ok-U|?Y2 z;NWntOL)GY(8nVJW%``IpG|ou{K*$6$5;~N7tG-B>_!@pGvCw2F{FYqNr8z&iCJ+$ zgF(Z@jb;uEYz+?r*f*9wDm6Q>@Ce(1M9({acZI)O@yBG9{;~h^hISH0Hnm&kshv7y z!Jv`8*!5Y5g|AC2&x_m%9Mw4*+5w6_nv3dk-sl@BUfBp_aCj$fc8V^Ym0)S4_Li-* z-LfM)lFfwatiEK%Ja28ck9CofH(sW+XjVprILE}s#5%<^-cY^L+OdP3;VeU#6${g? R9H3JfJYD@<);T3K0RR(vV3hy> literal 0 HcmV?d00001 diff --git a/crawl-ref/source/rltiles/gui/spells/monster/sporulate.png b/crawl-ref/source/rltiles/gui/spells/monster/sporulate.png new file mode 100644 index 0000000000000000000000000000000000000000..6b2463512b28039e5eb2bbe302dcf8108372b7a7 GIT binary patch literal 351 zcmV-l0igbgP) z#Ke%0kN^MxFfcG7I|D#KKs6o$v!DRm#usOW06Jd)YE=M{xCzwkL0|v?00DGTPE!Ct z=GbNc0084jL_t(|0b?Kn2qFU^pn$M35-`Cj5DXPCg9=o1wxbA`cdqIvM%H36WA&M4 z6oJm3GslqyDps9Yz18?I!VIh1Yjz(-s4z7)Uv=hmxUsQmG29(Br?&&`TDuggB^W4a zY`i&Q)@ry4Ymk21p6*~XxL<&FRIWJ#RdE>X6?5~B-04-f)^r(H?%E7@y2YwJr;1Ha7sFLpcJ=HAS`-WyD4%m?GisPtoC!t^ xQ{!TS(O`@e4QeTFE^aOVS)*F*+}BS(%*m@ok-U|?Y2 z;NY-FnrlP+y#k>f--Pt-fTD~gL4Lsu4$p3+0XdbPE{-7;j6MAa1(_6hSaKb8pBiYs zNXt-=w`$mATDN0Q!u;8-Gpl1hgv8l@Y`f6+s95A})EE0Z^0v$vm8(-f})F zVU0%Xdc&<7ba=FC4wY~#Hw8Vp`bun4>AtV;73L```<%SINb1q6N3Vn)aUIcHsONIT amO-IBxL9D{Zylf`7(8A5T-G@yGywpGqEqw$ literal 0 HcmV?d00001 diff --git a/crawl-ref/source/rltiles/gui/spells/monster/summon_spectral_orcs.png b/crawl-ref/source/rltiles/gui/spells/monster/summon_spectral_orcs.png new file mode 100644 index 0000000000000000000000000000000000000000..457cea80902d3ce64ae6087f1a6a34a4d88b44fa GIT binary patch literal 856 zcmV-e1E>6nP)Qi)wCc%5(LL~@AS-$ZQEztwr$(?y`JrF*q=E6OI&vLs?NiQC|5;fWOidy zc;k&X@V5e}+X(9Q`jP@-CW4V*h9*ncr~tnK8c7e0SFetPgyei8jyU3o#RM>^Q+EI_ zL1Gc?#M%XX{`)u3ICKmeGf0H$M8dTG6fmJh3yqBh?1Np1EGuAVXAS{cK>(*FWaL^{ zdl7Q(#WbiXkd5quaqL@P4KUm~hERkmIoE-%6W*>bo3fILX#5wbsN zg{I+x>4;SeNSm01$W-_bh*?-njb4+rLO1ZhJd@!(MP6YFY7P=%p$Khip(O}O1r~KZ zPmvexe9kzP;5bQMtpoa@R~1naKxia<1otUn;ZFIf_VNx?3_ZkjS@-%l{&N%XpPztqRs_;HameQ= z^EC1|HUIvdc~WqvcnR5?8c1GNLh#Zg5*L>czB0?}k*ji$FGwJ8K?`cX(`>)LFTF&QkPXwyQR%* z)dvUYy>bMP_uinM-~8VKNUb1(YvI|!{(ketAq!K+g$Em`-P}g*?z&*}aX*~FBKFAV zaX?W0llNGhMP#SEbDTmdfYup<7mvo^=_!tQ`*>lU?uvoT`x)+~;F_<_!2S9L-nWV% z0%88(CueX^XBl*tU0Cu*B)YO!P=~M|u|oK#Xy^V6H-f)S!5eS9p=>Bn6e{>*2sVO` ik4;D~iWtn^Q2+qa7C}b;b{&ZT0000CbfEwZ4*)x>M02dno zVut{7pa3&M02UkoLR?u$ zK>#yG01y@cMPL8|0{{gF0L?@p+yDRo0d!JMQvg8b*k%9#0a{5!K~#7FtU7Whz}n>eMSbpeEo)+nL6P6);2Za{mw3GKnJ|v zV;Hc%dca{V&~xD9(R)!jJ~<`MN_ybI`NgH=>YBBP3R`Bt4cu-T5+Y(qa_i14M7aah zWUb01wr+Ze5{Q8uI1E|IxamnoV(ScO_YiBa7Sx=jFl?a%i992Rh_jlgC3*<8 zCV5C?9Ij Date: Thu, 17 Oct 2019 23:34:35 +0800 Subject: [PATCH 832/864] Remove stray pixels from spell tiles (cherry picked from commit f7f5d9a50ab908b0c02c93668eeeeaba0d3edbd8) --- .../spells/conjuration/fulminant_prism.png | Bin 361 -> 280 bytes .../rltiles/gui/spells/fire/bolt_of_fire.png | Bin 1048 -> 974 bytes .../rltiles/gui/spells/ice/bolt_of_cold.png | Bin 1299 -> 1047 bytes .../source/rltiles/gui/spells/ice/freeze.png | Bin 1131 -> 978 bytes .../gui/spells/ice/ozocubus_armour.png | Bin 338 -> 330 bytes .../gui/spells/ice/ozocubus_refrigeration.png | Bin 1967 -> 1933 bytes .../rltiles/gui/spells/ice/throw_icicle.png | Bin 437 -> 361 bytes .../gui/spells/necromancy/animate_dead.png | Bin 1277 -> 1208 bytes .../spells/necromancy/animate_skeleton.png | Bin 1172 -> 1010 bytes .../spells/poison/olgrebs_toxic_radiance.png | Bin 1732 -> 1313 bytes .../gui/spells/translocation/beckoning.png | Bin 512 -> 262 bytes .../translocation/shroud_of_golubria.png | Bin 360 -> 358 bytes 12 files changed, 0 insertions(+), 0 deletions(-) diff --git a/crawl-ref/source/rltiles/gui/spells/conjuration/fulminant_prism.png b/crawl-ref/source/rltiles/gui/spells/conjuration/fulminant_prism.png index bf1e8083b448fed31bf6a93ff7b2c577ddd27531..51bde8a5729eb9903ae5b22f6e3a07ec31f556ab 100644 GIT binary patch delta 265 zcmV+k0rvjs0+<4j7=Hu<0001iRAqGAHSDEkbAZg=FnTHSm$dg__-eB!RT)k2?4|rj$

VNzlGSS6DUL)itZp3mQ z0OTe+0C^cZb|CAxp##~$-Le5jN^7hdI=FUKF~HKv6@aCMxxe7?2D)-JaJNkEvbhc$ zl8wSGyc)RknL~%|)d)0~4=4ulO@Ds_MxIkkadUBVNpS;Wmoyh5;vN7Qqi0-B9jWa delta 346 zcmbQi^pa_UL_G&H0|SH0lCEPw$}hkt#1%-h263I-X8!X<8IXK>9VA$>H;uunKYi)lwUy}ik>+%;z)ZcLa|G#uy>}2mXyoMjy z#2(DKBlf*Iu14kHo(RmKF+ba%L`2a;y_(`cSUO;C!Qpqo?yWukKc^aNa3LxPn=>E}7C{ zknQNTiX)4KM`%*sjUL6sOHD0S5f_vbL>4o4t2j3#aztFc!Kj(Wyh%Ud$fV*P%TH&g f@41xzy?qbk!r3OvJg%pkfI`C4)z4*}Q$iB}@bQsw diff --git a/crawl-ref/source/rltiles/gui/spells/fire/bolt_of_fire.png b/crawl-ref/source/rltiles/gui/spells/fire/bolt_of_fire.png index d18bd4a0f7eba40afdd8125389432d4ad1a187dd..5329068cfd5ca9f1f20617eec60eca7468ff2881 100644 GIT binary patch delta 963 zcmV;!13dhg2+jwP8Gix*008_L?V|ty00wkYPE!C!0B`_IukPj}000AnNklYLDuZUF-$12ISpKxsL^K$8VQ_ZCrRy(>K z&`TnruMzO_m48go)W10X-9y*^a|pHzS^6?Mwooqu0nHs$lR%ngMpzWa!fpY%dLxql z!m6TI}DCAgi=-WNTO%oM8UIHw49Ib?lOw2tFnEUVM$cf^AUI3FCN>*x%$u zQ5Ns2%i9mBx~rEof-QyJQ;JPmDb7WHtf=5V1B6Z!`ZlQSdZ`% z*zAs?V1J0<@e;bs*h1Xy?K`#541&H;3G6aK68+H`xfcz)c@w|P6Z!8OIqzlkHT1|k zqZXbcTvsLCn6v4>o5_L8iN9`w9l)=%quw`->iuU4oyE!Me@vm6t*oIXX7V;wX97RN zrTo0g-v^_o*b&K9iZ=zFtGHEha%292n+OZU=zmwqIWl^8leZvl9Hpt`ex*I{y2Uip zE_^dqKDp?Qn~Ff637(UyyuBQPc)XMu{r`)dq}%wP-T7i9k57Q>ej&_B1tAVVpeKP# zzgH(qQzB>At@P6P3cEvldEUy>_ms%i5W3WFLznKGOLv=Hy$^>)6*)Znvjx2&yc+bI zAb*9uU3cxdR4;(t0`5?L&H1L+5agVf@99He2XuP*y+ZK}|E$9Ii*Ulw;BeX1-1wjq zv`eqed-O2S>*WAGoZn@UCW}I|toUFal+o?p^nm0i_;g_z>*bn^3*p#mn62#XKq+d~ zeHXd9XD#kDKHFCGIGYnmk)H?uo1lb#06g-19Lt8v*2vr8&>3_IpS6<2M l{|%FYOEH{F$Hp&B5da>u@ghuuYx)2H002ovPDHLkV1l9Y zqzRT-{=#%b+If#}b`N}yZ}(g2kLcjV_qOkSKhN`dKA+EXn}7T#UJ()R6A#kY*QfuM z_V#v7ngExaRiG8S?Rr%trh`Ov0YZov6@&)V)YRmcKmjT-8a@d8XvZ>=VnQaKP%s$GzXH{0!+uOh1(u3D{LCZTIF0~Y za3xjn91`%L)PHzfzpu0ke1ULhOfEyP@O;skzi&HNTFVlke@Bq5(1H(?N8q8t10Gk>1TS-Q9I8=_O02~Okw+`IYAM#> z8(dFu)_-^6Jm?2+(i=8e1-nt3%@XWHCsv{X3+U~4yv%+igYG~JA~=&I_}6FvRf;VV zy)4qtk=3dA9HTN-fc4gGIKhtX;rcDX8;WQ!eg-{)9}qD~g2&z!?I>ZB^2|B9;{j`A zUIgIHQ~^q_UAVV2-Zc8F81yCHFF_0L<9nz{oPYUzQFfUg<@vYJi8ho$9O)A%v+i~s z(KdpI8TiwL4fi9|q0A7 z^P3am&8ikY6g$DQufTb3{y_ql>a66aa4kvjD7J|{ng>qB?|ciM94dbvw9QrpF*zl0 zQ-2t^3e9OYTMWDKA`PZi^g?mGy>?jekMIn{k^K_rdlo#LG&pb+_3%^r5u6wX9E-`= zicJV$xGBh`0@`YUQ}y;fg6?7F0nt@H(S@|v#J>&Kn9-;=uH@-Y8kb2!C=wbF}Ie(s?#Cyb*$?=kp#1xc39C_`5OV diff --git a/crawl-ref/source/rltiles/gui/spells/ice/bolt_of_cold.png b/crawl-ref/source/rltiles/gui/spells/ice/bolt_of_cold.png index 1aee250f13a938d0272c4dee9276af1f75d53198..6c569a9583fed417ea0bcc313738f3d44a03b6d1 100644 GIT binary patch delta 1037 zcmV+o1oHcn3YQ3w8Gix*008_L?V|ty00wkYPE!B?0A&CLP|*6-000BbNklTXL zXuVx;Vjsm z`4TK!R4|)m2jO!$$rg_Tef{I_-TKM*K#z`&ZjOL2ufc%|<_77b@JQSPx*NQ3$EQDt z({Wq2Y}poDq=XvKZmlr$ZQ(fAbN+(co&(X-p#;5+3RqUdByzP~Vylw7nasg<{WW04 z>A2w&yX4A^S$`zEbY^#9dWjvYA)Q`JqQz^F=r#Exns>N(#a%B}_ilH%Hb@=ZP=K?f zhivf}p(hgORB~m0`WZUChE;1scatu%OE0eW-P1{q)DhqU{!gMc=-p?B%O6Y6I?Txp6+{(`;ON$u6Y!6lRAL7nPSyArUsd@ zrQ>{Nf`7u%gU8+hA1dfk@7nE3asp9;h-}ABDp=I$1YQH-iRe1L4{}}88Jr0-4}H(D z>ai`SWDdJ4(QzJ$&Q026(38U#xT)8BXKK;WJCklV*}XA8WE7#;$O$}M+tr}p8d-ar z(np8%fK`(;QxdJ`vg{$zfvndSV1X&Ir%N-ZL4P7$?kpnYomgbqOjmaKe%HU?T6Yj; zBCD?2LsoVfQIaCMo>H9|+;AE_;XvJXFo^*o5@x(|bEVs5!kPEsm&K`9*wP6qxdL9* zIDt^TL>hFK1EBkBq^Ixw{KvUDSLnjN2(dSkRV%B>>A^$$4!lDo=aU@78r7SDA}T7k z8-M8aG9!aEpc7|F6#T59A?yU#des;j=h4)?rT(-|Z(x<=~ca^-d$SbulkE$@F@ns=RRK0{}ALF%jEb!JeVcQt+| z_=ZH1FWDx|{Gj6`X;+YJ-MkaTdxuxJ3}Ek(T8bB0;=C;#!?HJA8nYP!zW0bO?HZDk zYW_J~r7r(=lPoHi%ge%=7S@Kr7zj2d1D9ermyV5Jnj!!Nxer#tXXOC^0000kUkqEw)Y0R^$^WZulYm&yBUGRB0s#d3+g1OVhQ zOLU3muKff?%vE>%hZX?5FCjK5%1p1A@hOm5128X801ki$5C9l}*+go#0Z;%~1E>Jp z0SSN@AQ6xRkPMIoAWJ}2fRuo20NDbX4oCyY4X`C(C15+iYQPSF9RX_ry8w0t><-uy zuonEg+M9<`t>Dg@LzB<*f|7)t7?o3qh7D$kz$-OhK6@C^H3zZv^cMrp#g1Y0Nr{S?4fS z7E@(2m3jDz*=%5T8`-o1<`Bz*%UJ05Y*8tT*~#=3qGg_FyHT{=D%$0WYQ5-KB5I06 zw_=TdjS|Rr4xUtBkh#Qs#pL_3lmiuFgM8y;qMk*DI-UV^eZ*7n+0m*852{{xmufsN$0EUS_gb&1_in+e+l9*aOLdbY2Qw6D z`^9HX`UA&$j`eSge)#KyHZS{l)ptp{iqBmKje{Mv_|^8wJ)Ie+XD)e>pQmf;n;1N@ zqn;**KAWFgCjWiG=s&IhrKF`fZiyM6^{?N#RkVLwF>vdNVpm$3p>)xNqw$01n!%3i zEnGK#cEbM6!OopSk+vll=7m%Q1uqiY>CMT`x|BO>@Ah?{zG@MtGG1(IKUu3e?knjm^yO4$e)74e-RCQw2lc4iiqqft zjvXgq6YGWSKTZuC>pZpJE^6vl^k45i+>cx+6GghB87kSGNKO8@cVnLy ax{Pu{QarZBcU=7R)?%XKboCMG<^Kb{N1pTm diff --git a/crawl-ref/source/rltiles/gui/spells/ice/freeze.png b/crawl-ref/source/rltiles/gui/spells/ice/freeze.png index 60813965481df8eb96dd400bdf1ad231b04c4810..1474bd300e6b82748332192cc9370634f5c5d3bc 100644 GIT binary patch delta 967 zcmV;&133Ka2+{|T8Gix*008_L?V|ty00wkYPE!B?0000`1`q^%hhcxYMpMi`iXqNize4A;uklj$L6I5gG7M zzmwhdNY?r@tbcOL3gWppi2GxZcr<8#!__Crdh3Nh5&3Ba07hko+iG3zj&ry_N(56x z`B`DRUB{k%rDFH})M`#;CN?Bdw%^YB%T9Rcy^q~in?%K#-07#{wE`%=oK<>8-QkBa zSDpfDQF|6NR$lW!>pkb7Q6NG=(d08vxc-s5Uw;pk$$#2QFk2O?nLz=V*Sk`OC18XG z+GTavKK8*UPP_H-tmS89th)&IsrNnq`M2Ml_`s78Lsw($=@lqQS$`SQ1nJA4ehEe# zuYBh9=idGJ+LzzH_5F{Q-1sOodY^v{ZbSONQ-DOw&Ov0O=?6fKI#3OoUa-Nr{=sK1 zdGtl3kAGDM0Zirhw1~Le@2^^<7<=Sn)-O=b?N{H8u_F&`+@H++0o3ov{GR#>Ojd*Y z!ytfCKnLDUn>MLqfuUrUU3pK#6~|+%HTh7jA$#Ew;S4;Oc=*#QAfgG_VI;9D19W4q zy!+ele|Y@kPuE}hKJGKIiQD@(};oN(IIuk`W z9)D5#=O8_O_zNyUqu!XE(3o`5?QQp+$%7$y(DW7jnmwfy2>2Pxs&(Hsa{ncE!v&($ zL?Y_y1+>&E80;eKL1Z0jWi=hTzuvF|vg#7dSuc>z3lLVBIc=!bhS{x&sDr1T%8YW2 z*H>*inpadsq|P9Lw>V5U{?T>@plKqSra)d2nhN6VdJvP8!qdy#UV4GQ5b+k_PY*5t p%78LrcFah)xsXIL|NsB4e+Ej?bi0n$`Zxdp002ovPDHLkV1hU9-}V3i delta 1121 zcmV-n1fKiS2kQus8Gi!+002a!ipBr{0xnQYR7C&)0KfnM00000009610ssI5000C4 z00#g82LJ&H009dC0S*8H3jhKP00IyJ0uccM6afPh0Rt5Q0~rAX9|8m#0tO=j1|$Lo zD*^^E0tX`k2QmW&G6M%N0|zk!2Qvc)HUkJQ0|+t$2sQ%Z4pIdVR|Obf1`J#V4Oj*ZUIqHHN7u~?|WTC&Glw#Zw~)nKp0WvsJkXlQc2(sZ`Tcb~X-xy^mH&3(?+sa@^4se0;PUqL`uqC){r~^}ac7Us00002bW%=J00y7%Xbk`W0qRLaK~#9!t&;gu z(?Ar*;fZ+HXhc*>Jt7_vv?|zwiXxyOR9Me&D1U0JR^?V8URV(f9fDd4aw;j2lgIvG>mnuwOH8odp|B6$pLDBrPZB%4Hb@;K39&j zFrrqrpAKRrHrgRc`+u@G?4$|H_Q)np2`WJ>jXm$`x^tTy7Wr7h z3K=3Ci;eu6eD$c2?Gj@NX-R|!9$&uNeCF5%fhW7rf~W}p_M*MAz-}i$3jhg93-d2e z-A9W=j&9Qk2=kuzfonw&e-2U3&@ud`z7*&=!~!%NFi+2u!TlDRpz~;m=gQ5Y^IGMp z)IczRr)1T-2X{}1)DWYPvUPpt@>%I^Hx8tdHRx2={P6X(vNDmU3CO9E77N>{VFuA{ nhWvi77YiS~j48en{)2u4Pt@_c#x+8O00000NkvXXu0mjf0M@p| diff --git a/crawl-ref/source/rltiles/gui/spells/ice/ozocubus_armour.png b/crawl-ref/source/rltiles/gui/spells/ice/ozocubus_armour.png index a05336acd9649d4db5b21ba9eae3ea65124dfbc0..e33dc5ba5caafe912add04a93df2b1ce0314e0bc 100644 GIT binary patch delta 315 zcmV-B0mS~&0?GoA7=Hu<0001iRAlps@e|00DGTPE!Ct=GbNc007ZRL_t(|0b(Em2qFU^ zpn$M35-JQ&aQ zMBkdBSI<}z`a;I!O>C9~0T_>6TmNOuAZwj`g#dCdZ?o(GX!04LZ|NRkY!hThS>joy z7og0N0CWOE6f^)wK(l~eAWDb4`d=s~@2Qu#ySTfQxC60ExeF0-4*&|CYX&U#oWKA8 N002ovPDHLkV1g-XfZG57 delta 323 zcmV-J0lfao0@4DI7=H)@0000)q>9D>001peOjJbx006)M000006DE8xFfcM^pFluB zMn*kdTn0+2h2-#P|C9{a2^F00002bW%=J00y7%Xbk`W0MbcBK~#9! zt&)L`gD?z3w;DsDW&Ho=&LyhQAPAjqR;dbkI3eNjcRf!}-hbD6CD1N4?EvopD}i|c zw6M)%abF5xcW`Mtu&RMOK;r>uHx4PF*8mhXNNC`SWr491g#*GO$S?~OfICdlHMASt z&nZN(_17B}FH-alff9PZ8owNn3>dN?PO|`!aiikZS0D`(T1^8hf diff --git a/crawl-ref/source/rltiles/gui/spells/ice/ozocubus_refrigeration.png b/crawl-ref/source/rltiles/gui/spells/ice/ozocubus_refrigeration.png index dbf09b176c88ad89196ed18c058265da51f377ec..1e33c4b82a461c39ac056d7d92f006294a3f4d73 100644 GIT binary patch delta 1918 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 diff --git a/crawl-ref/source/rltiles/gui/spells/ice/throw_icicle.png b/crawl-ref/source/rltiles/gui/spells/ice/throw_icicle.png index dd30bf1f9ebf94431c0d06427f365db521aaf9cf..e9b867fe0cfbc02ca46f68d50af88400236c8847 100644 GIT binary patch delta 346 zcmV-g0j2)61L*>g7=Hu<0001iRAPbXFRCobm zAOZ*?10kS*urU%aK@$i@6$ni)wm=pDutf$r2*N-Bd=zOv(tm&tFwMRINE-fOTJ%g1 zyf(3VH%jHM0q!P-H&_e{960V|XAZkQsBi(859YpIC~mgd7{&Rm=O_cy)GG9_LBO>3 zRd7_?{;5A(8x<;S+xN;PPys0q-=j-llnQxj)Q#Z=fm~JBQhNx3#M+A~ zT>=#_X{svj%~Q%Fl|upn75O>aYc?qxvlCGg&L@N-0uFovM8upj$|exRoZuP%4a!&E sunJK5O{2xb#lxk=1BhKZT!@H!02eoac}i<6Bme*a07*qoM6N<$fPKlMIij8p9MzxRt{ z7JGK+{toQDHEmUK>5fw`ukDPVH~s0;k1adp&Oc3LyLQ-e|36U${u&w9j);`l?b}5( zB78IM&Z}d~c$5}| z4`*{Wl>20#bqWYSl8}{;f@AvTD=>rB8gQu&X J%Q~loCICQ{xcLA8 diff --git a/crawl-ref/source/rltiles/gui/spells/necromancy/animate_dead.png b/crawl-ref/source/rltiles/gui/spells/necromancy/animate_dead.png index b27843acd5038cbe1a237620eeb4e14319356475..0236221c2a1fde6624aa2221af862d68f1016594 100644 GIT binary patch delta 1199 zcmV;g1W^0^3AhQ68Gix*008_L?V|ty00wkYPE!CE022TbQNJK!000DSNklYLCD;It}qTe*Vh4LuGsJ8WjZbE1Pt6AV(sS z2ulDE)*zXhLib~X9%o4aA{J*8q3FK=DrEBPsa9p1W~SR+PQvFm1bh{v?1G6*rLwIJ zC%A(|XDm#HM@b-r&rwuqW(onS6wj*zVKT0)UCvZ#HMuDaHAGGals)m#=*KKDU|xYc z5G#=$>RKw8-6^Wrzps&OZFcIvSrDac>rGIA+ z)JE4fiCPb)_NzPJ(Xl-d4_#f_kB|6bX-*kVe2bGWy3B|S6h#d;c!bb4HCrx7=IsAY4`piB@o7sUs~5U0SQ?E zW7jusEi8s#y&-@9qqw}rX?peI5_5A3nCnz*2TTC}_~Q?DuP#-zOSQiXHz>0S3xGe8 zF}4a0grgwKR?o24w|d2Lt6KB_cCeL9Z@m2;e3Fo8$cVKTm)C zeeL=p^!2xg7Z(w$9nA@o(Kb2F9v+$)8D4s>D1S@Av`mihIvw$FaEjFz6pC6K8^8|q zA!zT*uW)XjoM3K4MTK~D%rG^DHOP59=EKqohFJY6v)Lx((J}=_AW+m$%ALLKyWjs> z-`-ofJUhL-p^Zk=$Hn6O5A9lQX$2mW`P=g|TCKB+#Bdom2SqrZ@Hj88FHAgvKOD>0 z?0-hFi0RJjUeQ~1!wkTLEICBz> zz1-f$&`&;i@12|LtJ61-i#l^(%e4qs9t3lJD+WE7Qez|0Y1OIM>!c{YkQetLb3n>r zB96NsGw91zP!K{cXETvva#)|3P#(}OD0uhw=Jw+Jhj%|%(`d2$wBB$}fC;fAG=DkO zLkO&IBUSjZ*tc4jY1i&@CX-BRmE&0tRhku#`fVgeBDLo zdfGZ#@d~b%yMtVGwzeShE7ahiq`gx=IEb|uG-GoOPac)6ph)!9H+Iz4;g^rFucz(l z(_(G+2VkP^VGYOvsi0oMBK)U^5-0-5h+OjT;A~6=F2!&z9UH$iMF3+w^Hz_XN@@TA N002ovPDHLkV1jGaITio_ delta 1268 zcmV8Gi-<0047(dh`GQ1jI>1K~#9!?N{$>T4xl#4ECYvFPDcNwk;B6lL91g&CFlxr}S7*U%Btx4K$P4kPa3C&9B3L6{rL)ZQn`;dQS`!}9F z_uSkM?uN~qmVFo#4(Gk^k8_^$JmQ(cZ<4`E%0D#vEWoE`a9FL241c1q891IQ!Kvhj2 zjhY7{QMfW0D1iW6b8}Gq{*#kg^KQ3zRxW_uUxbJKe0#0>MO5nb`6&0<1K^ zId7?iDVogNnR3trOvZ|=CNh001^-G%s`0m41ffZV$?Y8!dOf6d9mVZ!q*vDv45|GL z(KDX-iHV7S1|ZFsPFoEq6^Rt8YRMw=saOofy*+3L2Y*m0U;OZU%szR7DCfCPWb~}9 zLkWlBs>}=EAgwR?$JwEeYyb?+=BvndyO`pE3WFrtZ2?Ah1dyKqR%$gAAAJMm_dhVT zwJkpN@F8|qd;JWUH)4Puu#8C`Jb#Y6JG+SR7DT)Ekt4NX_6GGA`c<+JHE1mq;ay#Y zpYwrM8-HHXpW^tvdSID!wVv*yviBWk*x`x&1L(~bqQ<+Rx&WoVgaUzS@dWaZH{i+T zpi-XDu|#vpBwD1sMu4XR&}2ZZ*%V6C&9?Z;ojdRu(j-$TzWf0%U%y6=O;@GY>x=NQ zQT>!iqdZHY(R}0eP!LGoqty=$y?x|{&D)pZ{OkDH*e6`*+KEg zpU~UfM3M8xS)D8;sk@&*!n8%Q;Fy6KRTaw;NV!*vrL-iVFnhH0Hk%fvx29;zD09o1&ysOY|wJ? zxPPpNLm^wNSxs}sK!(YG=6%i(Z7LWPZA0cOS+uTXGuR^iaaNcoLk-d&?@QbdU|LlN z1|Vp=trixlRpT8X^m&iphy||cWFQxbAjRZa22%+vZAim$vs^-gYu0|t95tcFj}enf z)e$xjb(E@m`8*oY2z=Zl+OokkdShRJ&3{RW1i<}T?WDwx7!cb0rpa8EiE2b1B#@lZ zoCKDk=FO!g1PP>0(1r}XP6rQ)1w3jjoen_g#tnRN^QP@knaO4eLiKuu_BB?ze(xUE znDE83XE@m1#pcF_u$SR_A(=eA1fI*65%|mJbcq1!3>v21C2G8p&0;njmJdrQmw%J% z+HN$^({(IzUXR62ErI>O_&Dw|u=N}v6J=Jqn#rI`2KMg1lWrMRa%5r`ZD?GSXn>oq8RM6&)HY7r97r^Y-lz2jG(n7ce$7Bmnq^6U#Hn zJQFU^x6|pq{chff7y*xujymoEn{8bg8NsKQF4^Y4Wbn_~D__&6D3SfF*-Pino^`~) z!1me2i@0+BJSMMSNATJ;jMx*MN&?3=#6K#-G=j0MIl6}YyCe%VK}fU4_UDtwe|Odv eTlxQY{QDEnTgdZw!9QdG00007mn;qYF|MeqPZCne*6TmH3c*Nz@Lw!FN&u&{vj z>(i%Ckbmg;^XCw)qoV`KlG4+4_4I6PY$FkoC%UR~`L8AU;~w$ot<@bbSy0`6%`dX`F{ZVn4^k{3Ivsvm+$QCEGsX^DHe>-&`>l0 z(YXs0&!Zlm#M}atysC@T)R{4EYHo({;}a5Ml9B>KLfYEe64TOXcXzN+P*B(nD>DPU zF$M{VgoBG0FG6~(Yonv1(b3VcDa2v1SYS#@N`g#Klu}d2TZ`1xm}EakLY4Xb`}erG zxUXNo0`u+v|Nnt(N-KTJ0ggDJ0MOqD^baCnQR4sx24DbVAlR4;T#Dgbx;1`ji~wz5 V18_!vq}%`i002ovPDHLkV1i$I$d3R3 literal 1172 zcmW;MeK6Yx7zgktQoArJUPDN!mslHFT)jkuS|mzJQsS*_G$q-*#%l@ct#X9+)Jr)N z)J_{a9UacP)`@CKje41udEZ%Yr{<-uShT&dAD?@k=X=lp&poC7TyJenye0r>vwc`R zBrT2_gGMInUYQa=E!f{L$O~E3d74j=K%h{dh6Xem)YSol0gMKGt_50JpsfwMdZ2Fr z1_oeg1V%V8HUR3LqkjZ7?rAnaG_y!b+I&891drU$Kx$5Oc9A9Q&EzcnHhmVFgG{1u&}VS zw6r3Ttf($FHa0{e(bm@X3&fc-Boc{CCV$CfQYaLAdwT~52S-OoCnqN=l}e-0=ybX} z!_%F~Jb(VY2b1{~f^qEPMbFSsrk59!&1SJ!-rnA9UtbP~!{r?b3=9kj2?+}e3+MAA z5Ru1(-(C?2_(EY+R8+J;AP@>;Vq+5$5=0_Va(a4lc6PEvl9G~=nwpw^?b@}htc;9| z%*;%&Se%`mos*N3o12@Lmse0&SXgvKB9Rm$q|%a-5~);LT3T9GR#uLvsJM-&I963v zU0q#MQ&U%0SC43Hl*wdGO-*<2-feDfmdoXBZEfxC?Hvyvc6N4lb#?Xh^gKcI9#JS1 z{r&v|0|SGDgF{0@N~LmibaZlZavCu+Gd(vqJ3G6uu&{_&US3&Q+1%XR+uKvARELL$ zySshv$T^|YdE7ui>7-4)J&7FGI-A7^63@3+m4@C5Fjl@%jqM7zd>+RLOzsUU@@F=3 zitJ(q_|aj#Fnzru##v^qok^U;-)C6ysrS}M=7m2^R^N)ZQpfvNGn-a(C$d@&A{w6+ys`((i5)5BHv-`RJwX<@^cG7UDo=@;e!WyFr3BArEZsBpyKek>DzMm^$ zJ(v4ft0ffUgJ_rMQ9~yRYNu=?6Va|cV5CGjEP3giZBq#gUdP9vSc}OUb?0tgQsk@F zywZ|uJmYxR)5Q|v)!elmog~xscl{lt2{Z#oz%IS;165P;#Dr*iW(&&k@#aJ^Qe@p-IE=k=EU52B8oHT-AT7IX?f@Z^2Y+}{zsG2`X& zq3^pxUP9EaG!j0@l4fvrzOs!rm)f;tPBiPv5A<}IOVBx$a)@01X6IGk0f*F$i*6|S z>3!91R_MeXgUzwA3k=gKO8D*OR^ns-jP0jez9o<7MtLxu;+cT2u8^69VGqp!mD L;<7qC`8WOtR=nHv diff --git a/crawl-ref/source/rltiles/gui/spells/poison/olgrebs_toxic_radiance.png b/crawl-ref/source/rltiles/gui/spells/poison/olgrebs_toxic_radiance.png index bd9897144d90d363163b885bb4ac6e6c7d4b9c1e..252d4113a7663e579bc6553160a88364502c1c79 100644 GIT binary patch delta 1305 zcmV+!1?Kw14WSB<8Gi!+002a!ipBr{0@hGWR7F()0K>(?j*yK20ssUD0xvNx00{yG z4gd)r1qKuV1}*{s5C9KG4FMAb5H$n~Lkc}VJOLK~0~-JaB>);t3>Zrb7D@>P9036% z0tX=h2PXm!Gy*?CJ`6Gd5ikc7NCy)?2OdHTHdhiGI0*|o3V#JG02NXZ5JUt5GXN4e z2p~}jDNza>KnV>i02nU^4Icm*HU}G43>jPq02}}hJOlt0001Wd1~&yAPX#7W5j9sD zM{O7^M+*xi2Mja{2{8v3Fb^$P7(IFzGk6sjQV1Pa4m4#QKVvIhe>qcfA1_b~8$Spc zR05^0T$zaEi_^h{r{$&x&lPJ}+k$5;q4JH3khN01X%g89W67AO;vM z7%4<2J8L9ww>#1OuKoYvruT2C@M^&DlXJl`On@OlVt*b&T^T)B6b>x{9xn+uUl9lz z2o)+7Fh(zLi)5I`Y`*e_|Nr*z|JUUH$IbnppV(fBt!ia`OiE=bElCs%EeZ$~0S+bs z5jYP*bvl#GcHRHQ`Ty=D{LBLyfm5eY1#j`e$_=> zr70&@4}SGk<^*T%9YBymn=xKu(t!T8A-1WhWv` z4ID=YFJ2BEP!K+A6isnBO?59fbsQ{e5Jh?;NOmYFVHh}c5i@BIC`t?}M;SCw8!vSc z5-JD)A^;~u4is7t9IGz1eV00bro5l{{T7y=0z0J*=zm;e9(0d!JMQvg8b*k%9# z0e|^PL_t(|0fdo5pxtT|M)wz9+a5i?+P3XsZQHi(PHWqCuWj3Aa?)dzD^Au{e$a3D zz3@v1Dy_iK4}n5VlSwetV?eUPp@{^@lBK|cNFi`4h7<;MHjwJ=%k=`QQaDZkngsQS zdY)?%N?n0s$vayoz=N$OD;^r^1g@gayMM$LRVA{q2MGQs^n{k8az{_~*#ihAQsyOLqJdEJ?-;yUtDB!LEP?f`;`C-G9o0 zO&M6;Y18Wj-@!nh6WIV*vHMe2nRx~rTQBe1xe9ttM%Zw>4}Dgd1m2IEu49q!R8E*L>#0ToS2Nyxd_BBY@kSbOh1+sE%cvEZJ)wU!UdV18cHl-DY z5)l3>s(oXNHXMBd#w0)Vu5|pDe1D5e6hn!VOA`K`GksDdFNgPkQtXa4A^4}9GaJ)2 z#`nKWaZoS?oNI4eDz(c^PVtl#GFxtvSzcf|&Yw{GXXhP36xY05A~l8{NCVhr_1U$g zh9ikI@n#uFuP8(ynMm{1QurZ;5{wTOkY@pD4(;x#f20CxqOYSocLM;l;1bs%sp?g# P00000NkvXXu0mjfD0b%L delta 1727 zcmV;w20;0t3d9YN8Gi-<0047(dh`GQ28&5VK~#9!?N@DRQ)d*;y_fgi%e}eeCgh7G zB}r*(Nm`PKO@nQ1l-5dHu`O#mIz<#e@C!figSv?hHpGt~Dq}K+unmSd6xpEj$Aq~d z4ma6wIE1kubBw`;OecbWhR>c{Z|3HtsS5iscHz)Bxo_U{oPTqk^PIPy|HN~_<58aZ zkc$^D;@`3(M~>jJ0Ql$0OmfU!Kk`ob`#wp1xF?^_KP3Q}rn;uNrqfKC*Zp3hGk(^S z;!hAtNP^L-aNpAcP+UirYhIe+8rO1wPJ>+gXk42)fzU!PL_l^xT16H10v$>~a?YDK zZ{9QjD(R{?(|_ExmlmLt5G^J_ZB*cE(@?kALS(>;z(Nzjev?i#=bcDMkYXN)ddUH; zr4{JSGQ4vHBGcj>G~J#c>;TB?HDR z0^)bRxjMoF7QzIix5$vfZ8SyzFWJ8)E2UI%D@qf@BMl_oM7>&QAA~ozq^RN$f zWdn9rAevKQq!ehg1oTz`HBEp;9qBPI>Xup18Gt9j^ml3SgsKFbDF;|jH77xC^1$1! zAhyIn(~uwS<5Bc)iX+qKh1tLiB_yU+hqs_1ocEzH7Do4E1jSup#70c0d1f;wLu+O9 z){_7*9Dfi_6d@iIAGgrHst)s4wqW_*xftG7kNl7i(QX5Y=WN8feCU|SV*c(Vx(Hy- z3LBwCI{X6~%#wgsAb_x&g_;}?4x33NMpx2c6b0;F6PYz3Jb$1K`%i7evGqGGb+>u1P@D$rKV5fq#;Xo*f-HdSw#d;Ua#=O;n#d{N{_>r*Qn^ zO_02I!EaEFD4 zksw;fqin%6RW6PCr9L#Qqb%=>V%dotj-20#^>3FkbUcNL{RN6rCwfXt%CBdGn6NF5n*Op@E_7Z!+f|-|~H+T@Iu6Jw?qsYi3 zlvIzccK#&RZ_dIG2)v=E)}A+;^&45IKHK>&2h zeeC~g8`ds?q%-}MIp5^APKfnm1a?j#yH)r)H5w;fuYo9|jE~Uin179EWkkqkC6ZrwfYd)hzF_Wb|2&mW}1 V#FypXYMB54002ovPDHLkV1je#F{S_j diff --git a/crawl-ref/source/rltiles/gui/spells/translocation/beckoning.png b/crawl-ref/source/rltiles/gui/spells/translocation/beckoning.png index 9985cf1a6bfc8f5f4769d5be4333e08580fb506e..60383ebc57f5d77a68d28c5311c9146efcafce91 100644 GIT binary patch delta 246 zcmV=jW{69~!WR8H_+Ge}alZy%3P&!$w*b%WqA?pk8i(4S~fJK=YVU zuco?ob=5oSnCcz%RWHpQdTGQdq@vB_8E6Y4cxW+1oEQwvTlS-HH*qY%lY(xn0A{Y9 wI$SG~-G@IKR6|@{TwOw3f!HO~g^0KZ0E(wlaVi6eVE_OC07*qoM6N<$f~v(~NdN!< delta 498 zcmVxG6 zD}kk~#}j+r_l%>pQh%Xsl{yaH#{n&D+xC;}wfnB?R8>`)eSgGZd7ks(YId5YCibDR z_GIiuK$0Y8yMq!K??U75qA?L}p9^D4MpOYD{P?!fyzA3SZQknvyYG85j#dH*4lo{w zaJ48IAUN&X-Z6=={SdV{0|ZAf03-;#qfGEaxJUrO&ri<4m~14DpMl^K08ZeSk5@Hy z+Fj~`GO!dLt$zfeJLe^sodLdkS6Zk1JOkcm;Qs1q6c=?T|INeY=)KDklmQ740=GrY zE`c3D5@ye_$Gily1cbnBIL5pLzn+2JElIEcxxtKL#SrAo0N?=QL96TUe>8$pKT_r4 zm@EOoclS0Oj(S^!2TPp7OCV-IN;!!TBQ9`?0w`WtmTM}@GKGGvHn^7aTQQ}ZgJWf( zC<@gy&G=f*VX!$+5@gT!9rH8b{0sr-P%g$7(KBH4e@wP?fln2Uyf(I^p?y^yZ`_I07*qoM6N<$f)p&`n*aa+ diff --git a/crawl-ref/source/rltiles/gui/spells/translocation/shroud_of_golubria.png b/crawl-ref/source/rltiles/gui/spells/translocation/shroud_of_golubria.png index 3161765cdb28ead10d97088ac0efa41f6e4cf9ca..614f76ab7b8b698992a219b2789ac217672f7995 100644 GIT binary patch delta 343 zcmV-d0jU1y0_Fmc7=Hu<0001iRAGvB3! zIu~bo_|Dt|$h&ZW=m=DhkO6SD0d<`OJ|F;ISiX~@O)*4|@$h!|!;6QBi~tp7^^bfC zI;Ux$`(*Zo>hk-g`xJ%ieqQDec8dO-B7F0A=k0%K`fdNM0uH3BPa#sj?1R4u+SJ(oYA*CyjQv44Q4Fm)r pS~OZbTs&M_Jb>7x!-a^r2LRTFdPS%40bc+B002ovPDHLkV1fu!jAsA< delta 345 zcmV-f0jB=u0_Xye7=H)@0000)q>9D>001yhOjJbx006)M00000ECWn1Ffc$sKt@JJ zM;T{f7MOs5fPpB$j0QN6kdTr)%d%wN#KgpBfZp8z0007XQchC<2A}X~4FCWD3vd;hoXDX7wFyPKx%;V!5Riud!mX{RVp{(GJl(%<~3kV~-1q4~D8Q5Nur%+TzC4^cc zNYbr{$jaQLaMw(_!Jg{Aq#zMt8le`^{*=NM2BpBscZCupT-7 Date: Sun, 14 Jul 2019 16:07:05 +0800 Subject: [PATCH 833/864] Show whether spells are in library in book description (cherry picked from commit 14bc4967e497162c451b71d99b28acdd13792086) --- crawl-ref/source/describe-spells.cc | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/describe-spells.cc b/crawl-ref/source/describe-spells.cc index 369368f4e777..2b2702b7204c 100644 --- a/crawl-ref/source/describe-spells.cc +++ b/crawl-ref/source/describe-spells.cc @@ -510,7 +510,7 @@ static void _describe_book(const spellbook_contents &book, if (source_item) { description.cprintf( - "\n Spells Type Level"); + "\n Spells Type Level Known"); } description.cprintf("\n"); @@ -580,9 +580,16 @@ static void _describe_book(const spellbook_contents &book, : #endif _spell_schools(spell); - description.cprintf("%s%d\n", + + string known = ""; + if (!mon_owner) { + known = you.spell_library[spell] ? " yes" : " no"; + } + + description.cprintf("%s%d%s\n", chop_string(schools, 30).c_str(), - spell_difficulty(spell)); + spell_difficulty(spell), + known.c_str()); } // are we halfway through a column? From f5082325f299944d4af62dbaabe1901887106668 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Fri, 18 Oct 2019 05:48:29 +0800 Subject: [PATCH 834/864] Add icon to the high scores screen (advil) This also fixes the high score description text being centered in console. (cherry picked from commit 747a2b3c0c11032acd44787dfd412c6bd1b954a4) --- crawl-ref/source/hiscores.cc | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/crawl-ref/source/hiscores.cc b/crawl-ref/source/hiscores.cc index 5f993f80edc9..050a6b3d0878 100644 --- a/crawl-ref/source/hiscores.cc +++ b/crawl-ref/source/hiscores.cc @@ -411,18 +411,33 @@ UIHiscoresMenu::UIHiscoresMenu() { m_root = make_shared(Widget::VERT); m_root->_set_parent(this); - m_root->align_cross = Widget::CENTER; + m_root->align_cross = Widget::STRETCH; + + auto title_hbox = make_shared(Widget::HORZ); + title_hbox->set_margin_for_sdl(0, 0, 20, 0); + title_hbox->set_margin_for_crt(0, 0, 1, 0); + +#ifdef USE_TILE + auto tile = make_shared(); + tile->set_tile(tile_def(TILEG_STARTUP_HIGH_SCORES, TEX_GUI)); + title_hbox->add_child(move(tile)); +#endif auto title = make_shared(formatted_string( "Dungeon Crawl Stone Soup: High Scores", YELLOW)); - title->set_margin_for_sdl(0, 0, 20, 0); + title->set_margin_for_sdl(0, 0, 0, 16); + title_hbox->add_child(move(title)); + + title_hbox->align_main = Widget::CENTER; + title_hbox->align_cross = Widget::CENTER; + m_description = make_shared(string(9, '\n')); m_score_entries= make_shared(true, 1, 100); nhsr = 0; _construct_hiscore_table(); - m_root->add_child(move(title)); + m_root->add_child(move(title_hbox)); if (initial_focus) { m_root->add_child(m_description); From 6b609627ca95002a626810149d23cd546ebd4f72 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Sat, 19 Oct 2019 16:55:45 +0800 Subject: [PATCH 835/864] Fix text bug (Goratrix) The Enter key does not close the popup. (cherry picked from commit 303dd5b1f46c04910b44dc48653dc2e314807cf2) --- crawl-ref/source/message.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crawl-ref/source/message.cc b/crawl-ref/source/message.cc index 90791caf77c3..924d29857c41 100644 --- a/crawl-ref/source/message.cc +++ b/crawl-ref/source/message.cc @@ -2193,8 +2193,7 @@ void replay_messages_during_startup() formatted_scroller hist(FS_PREWRAPPED_TEXT); hist.set_more(); hist.set_more(formatted_string::parse_string( - "Press Esc or Enter to continue, " - "arrows/pgup/pgdn to scroll.")); + "Press Esc to close, arrows/pgup/pgdn to scroll.")); hist.set_title(formatted_string::parse_string(recent_error_messages() ? "Crawl encountered errors during initialization:" : "Initialization log:")); From 8ceb4f952b469985e8be2ace387fed6096b4535c Mon Sep 17 00:00:00 2001 From: kitchen-ace <68k@quikphix.org> Date: Sat, 19 Oct 2019 20:24:11 -0400 Subject: [PATCH 836/864] Prevent torment from killing spriggan riders Torment shouldn't be able to kill spriggan riders or their mounts. (cherry picked from commit 8155909c3ec9ac85055d72da8976ba23e6673c4d) --- crawl-ref/source/monster.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/monster.cc b/crawl-ref/source/monster.cc index e87e4eaf15b6..94d444d72c8a 100644 --- a/crawl-ref/source/monster.cc +++ b/crawl-ref/source/monster.cc @@ -6062,7 +6062,8 @@ void monster::react_to_damage(const actor *oppressor, int damage, { if (hit_points + damage > max_hit_points / 2) damage = max_hit_points / 2 - hit_points; - if (damage > 0 && x_chance_in_y(damage, damage + hit_points)) + if (damage > 0 && x_chance_in_y(damage, damage + hit_points) + && flavour != BEAM_TORMENT_DAMAGE) { bool fly_died = coinflip(); int old_hp = hit_points; From 4fdf8e6efa2a39fd865386ce8d8cf3761e80f2e4 Mon Sep 17 00:00:00 2001 From: kitchen-ace <68k@quikphix.org> Date: Sat, 19 Oct 2019 13:22:41 -0400 Subject: [PATCH 837/864] Draw shields on deep elf knights (cherry picked from commit 099c3e10fadf4f4a5a06f351dba0dedc786912f5) --- crawl-ref/source/tilemcache.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/source/tilemcache.cc b/crawl-ref/source/tilemcache.cc index 1600775f83e6..bad1f6b69ef7 100644 --- a/crawl-ref/source/tilemcache.cc +++ b/crawl-ref/source/tilemcache.cc @@ -824,6 +824,7 @@ bool mcache_monster::get_shield_offset(tileidx_t mon_tile, case TILEP_MONS_ORC_WARRIOR: case TILEP_MONS_ORC_KNIGHT: case TILEP_MONS_ORC_WARLORD: + case TILEP_MONS_DEEP_ELF_KNIGHT: case TILEP_MONS_KIRKE: case TILEP_MONS_DIMME: *ofs_x = 1; From 2ded09cb5a92faec8b6a623af10132cf1f8d9201 Mon Sep 17 00:00:00 2001 From: theJollySin Date: Thu, 17 Oct 2019 19:47:48 -0400 Subject: [PATCH 838/864] Fix Sceptre of Torment inconsistency (12093) (cherry picked from commit 710a5d024973e60732778df8c18eddd38f24a446) --- crawl-ref/source/dat/descript/unrand.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/dat/descript/unrand.txt b/crawl-ref/source/dat/descript/unrand.txt index 9837b2734774..a2c2e5880b5f 100644 --- a/crawl-ref/source/dat/descript/unrand.txt +++ b/crawl-ref/source/dat/descript/unrand.txt @@ -66,7 +66,7 @@ enemies. %%%% sceptre of Torment -An accursed golden sceptre, created by some unknown hellish power. When used in +An accursed bone sceptre, created by some unknown hellish power. When used in combat, it causes agonising pain in all those unfortunate enough to gaze upon it, save for the wielder. %%%% From 1207306da54464c63bf9a8166fba16587a649518 Mon Sep 17 00:00:00 2001 From: theJollySin Date: Thu, 17 Oct 2019 20:04:19 -0400 Subject: [PATCH 839/864] Adjust barehanded attack prompt wording (11907) (cherry picked from commit 883716c04b0ca8447033d002a3d9b5a051e69b5d) --- crawl-ref/source/fight.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc index 3231faa7f0a8..0881e23fd03d 100644 --- a/crawl-ref/source/fight.cc +++ b/crawl-ref/source/fight.cc @@ -635,7 +635,7 @@ bool wielded_weapon_check(item_def *weapon) if (weapon) prompt = "Really attack while wielding " + weapon->name(DESC_YOUR) + "?"; else - prompt = "Really attack barehanded?"; + prompt = "Really attack unarmed?"; if (penance) prompt += " This could place you under penance!"; From 840c9efd86b1352306c600c208e194e852d40d82 Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Mon, 21 Oct 2019 01:44:09 +0800 Subject: [PATCH 840/864] Fix formatted_scroller more text alignment A better fix would be to use the just-removed align_self, but I'd rather not revert that removal, and adding a better implementation would be too disruptive at this point (feature freeze). (cherry picked from commit 6cf4ce537d564c1bec660035dfd98dd1c6821037) --- crawl-ref/source/scroller.cc | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/scroller.cc b/crawl-ref/source/scroller.cc index cc55b2364eea..fef408fb39fb 100644 --- a/crawl-ref/source/scroller.cc +++ b/crawl-ref/source/scroller.cc @@ -71,9 +71,7 @@ void formatted_scroller::scroll_to_end() int formatted_scroller::show() { auto vbox = make_shared(Widget::VERT); -#ifdef USE_TILE_LOCAL - vbox->align_cross = Widget::Align::CENTER; -#endif + vbox->align_cross = Widget::Align::STRETCH; if (!m_title.empty()) { @@ -81,7 +79,12 @@ int formatted_scroller::show() title->set_text(m_title); title->set_margin_for_crt(0, 0, 1, 0); title->set_margin_for_sdl(0, 0, 20, 0); - vbox->add_child(move(title)); + auto title_hbox = make_shared(Widget::HORZ); +#ifdef USE_TILE_LOCAL + title_hbox->align_main = Widget::Align::CENTER; +#endif + title_hbox->add_child(move(title)); + vbox->add_child(move(title_hbox)); } #ifdef USE_TILE_LOCAL From 84173259a63d2344364d7a2da044edaf05c86d92 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Tue, 22 Oct 2019 23:28:56 -0500 Subject: [PATCH 841/864] More updates to the 0.24 changelog (cherry picked from commit 3121d2daec10904cba000f36884aae5d7e3efdce) --- crawl-ref/docs/changelog.txt | 155 +++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) diff --git a/crawl-ref/docs/changelog.txt b/crawl-ref/docs/changelog.txt index ee0ffdef5e80..26c6448cdca4 100644 --- a/crawl-ref/docs/changelog.txt +++ b/crawl-ref/docs/changelog.txt @@ -1,3 +1,158 @@ +Stone Soup 0.24 (up to 6c54e258) +-------------------------------- + +Highlights +---------- +* Vampire species simplified +* Thrown weapons streamlined +* Fedhas reimagined +* Sif Muna reworked + +Branches, Environment +--------------------- +* Incremental pregeneration: + - This mode generates the dungeon in a stable order for all games regardless + of the path taken by the player. + - Games using the same seed will see the same dungeon if they are + incrementally pregenerated without requiring the long initial generation + time of a fully pregenerated game. + - Incremental pregeneration is the default mode for new games. +* A Trove map requiring many uses of digging has been removed. +* Identification scrolls are no longer used as a potential Trove cost. +* Transporters in vaults now correctly place in the Abyss. +* Fog generation in the Desolation of Salt portal now happens far less often + per turn, greatly reducing slowdown from high CPU usage. +* Random traps no longer place under items placed by vaults. + +Character +--------- +* Formicids can now use their dig ability on diggable statues. +* Manticore barbs now can only be picked out if the player can move, isn't + confused, and isn't asleep. +* Net traps now always trigger when the player steps on them. +* Vampiric weapons no longer have a hunger cost upon wield. +* Vampire simplification: Player vampires no longer eat or drink blood, and + have exactly two blood states. + - Alive: Regenerates quickly, normal HP modifier, no undead bonuses, no + batform, can transform and berserk normally. + - Bloodless: No regeneration with monsters in sight, -20% HP, stealth bonus, + undead resistances, batform, no other transformations or berserk. + - Blood states are transitioned by an ability which costs delay; becoming + bloodless incurs no penalty, becoming alive causes a temporary frail + mutation. + - Bat form causes stat drain. + +Gods +---- +* Fedhas reimagined: + - Piety is gained exclusively from kills instead of through corpse decay. + - Fedhas abilities now create plant allies directly as temporary summons + instead of creating permanent allies using plants. All abilities cost + piety instead of food. + - New abilities: + * 2*: Active 'Wall of Briars' ability to surround the player with briar + patches. Hostile monsters will attack briars to reach you, taking + damage. + * 3*: Active 'Grow Ballistomycete' ability to place a ballistomycete at + any location within radius 2. The ballistomycete will fire spores + that seek out foes and make a 1-radius damaging explosion that + additionally confuses living creatures. + * 4*: Active 'Overgrow' ability to destroy any non-permarock walls in a + 3x3 area, replacing them with plant allies, mostly wandering + mushrooms or burning bushes and sometimes ballistomycetes or oklob + plants. + * 5*: Active 'Grow Oklob' ability to place an oklob plant at any location + within radius 2. + - Fedhas no longer hates any necromancy spells, and allows worship by undead + species. + - Removed abilities: Fungal Bloom, Reproduction, Growth, Evolution, Rain. +* Sif Muna reworked: + - Piety gain is exclusively from kills. + - 'Channel Energy' is available at 1* piety instead of 3*. + - 'Forget Spell' is available at 3* piety instead of 4*. + - New 4* 'Divine Exegesis' ability to cast any spell in your library + regardless of skill training. Receives a spell-power bonus based on + Invocations skill of 1.5 times the spell-power received from equivalent + levels of training in the spell's schools. + - The Divine Energy ability and Sif's miscast protection are removed. +* Trog and Okawaru now can gift unbranded boomerangs and javelins. +* Jiyva's Slimify ability now works properly on skeletons, zombies and + simulacra. +* Torment can now trigger Jiyva jelly spawns and Xom butterfly spawns. + +Interface +--------- +* The 'X' key map mode has zoom support, defaulting to 60% zoom. +* Sealed off clinging and sensed monsters no longer stop autoexplore. +* Equipment melding no longer stops autoexplore and autotravel. +* Armour, jewellery, and weapons can be worn/wielded from the floor. +* Summoner monsters are now highlighted when the cursor is over one of its + summons. +* Traps are now shown in the ctrl-x listing and are indexed in the stash + tracker. +* Scarves are now properly shown on player tiles. +* Species and background selection menus now have tiles. +* Updated visual theme for main menu, high scores, and related screens. + +Items +----- +* New unrand: Staff of Battle, a staff of conjuration that spawns a + battlesphere when a hostile monster is in view. +* Unrandart changes: + - The Storm Bow now has a penetration effect. + - Gyre and Gimble now has the protection brand, enchantment of +7, and no + longer has Dex-3. + - Piercer has been removed, its effect having been merged into Storm Bow. +* Weapons with the holy wrath ego can now be cursed. +* Randart rings no longer generate with both rCorr and *Corrode. +* Throwing weapons have been simplified. + - Blowguns are removed, needles are replaced with throwing darts. + - Dart effects scale with Throwing and Stealth skill. + - Darts of sleep, paralysis, confusion are removed. + - Darts of frenzy are renamed datura-tipped darts. + - A new dart brand, atropa is added. Atropa-tipped darts cause brief + confusion and longer-lasting blindness in the target. + - Tomahawks are renamed to boomerangs and always return. + - Javelins always penetrate. + - Steel and silver are merged into a single brand, called silver. Silver + ammunition applies 30% bonus damage to most targets and the old silver + damage bonus to silver-vulnerable targets. + - Poison, returning, penetration, and exploding are no longer available + brands for tomahawks and javelins. + +Lua +--- +* Monster AC, EV, MR, MaxHP, and descriptions are now exposed in the CLua + monster.info class. +* A new function 'defeat_mr()' to determine the chance that a given spell + defeats a monster's magic resistance. +* There is a basic seed explorer available in tests/seed_explorer.lua. + +Monsters +-------- +* Monsters can now use wands of clouds, iceblast, and scattershot. +* Monsters clones created by Mara and rakshasa have the intended reduced HP of + the original monster instead of several times that value. +* A monster having the Dig spell no longer allows it to cast spells out of + LOS. +* Azrael and draconian scorchers can use Call Down Damnation when not at + low HP. +* Player ghosts can be shafted. +* Golden Eyes no longer have randomized spellpower for their gaze. +* Monster airstrike uses the same formula as the player, reducing damage + variance. +* Pikel's slaves no longer drop corpses nor items. + +Spells +------ +* The HP from Death's Door is fixed at time of casting rather than being + updated continuously, hence being subject to changes in spellpower. +* Olgreb's Toxic Radiance now properly triggers ally conducts when cast. +* Olgreb's Toxic Radiance now applies direct damage and poison status in a way + that considers the time of each turn. +* Shroud of Golubria's spellpower is now capped at 50. + + Stone Soup 0.23.2 (20190330) ---------------------------- From fa96c2cf7d334a4378aa956d4a0f12fe46f850b4 Mon Sep 17 00:00:00 2001 From: gammafunk Date: Wed, 23 Oct 2019 00:29:05 -0500 Subject: [PATCH 842/864] Some updated invocations tiles from CanOfWorms Updated tiles for Sif Muna's Divine Exegesis and Fedhas' Wall of Briars, Overgrow, and Grow Oklob abilities. (cherry picked from commit 29a1220a87f6323b60bbebad760f9a34b275385c) --- .../gui/invocations/fedhas_grow_oklob.png | Bin 3618 -> 1167 bytes .../gui/invocations/fedhas_overgrow.png | Bin 364 -> 1203 bytes .../gui/invocations/fedhas_wall_of_briars.png | Bin 329 -> 1146 bytes .../gui/invocations/sif_muna_exegesis.png | Bin 1707 -> 1121 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/crawl-ref/source/rltiles/gui/invocations/fedhas_grow_oklob.png b/crawl-ref/source/rltiles/gui/invocations/fedhas_grow_oklob.png index 895be9f5d9ad48afadd11c432a56b51ce231b9fe..3b919ebb991750dc1d6bfbb71bf0521452215c91 100644 GIT binary patch literal 1167 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 ovDBqvY0^#oP4n9xpa< z+kHDEb0=3+Qcin8|M9&)DtaGtY3LXJlMcu?Ua~ak%#p6bW6eKpB&s)eO4Prb(-3RI zC?HzSb6B!z`w^c8QJpPm4qMM3`>^g8k3ry6zIPX^kAJh<#l?G7lQDEnnQFrg!v#Wq z`)vW;{dPwkz#@i9KG^TQ;tHcfp<0qqN`oCeIBQ-Y1<85@v}^c63-| zRVLBzc|k`T5YRdNIK*iGxyDuw?i6j44MlHRtxou5-dNhae4cv4 zl#2lqE-#rXFZ4!SsBz*!?ZVWKx+!;le6w4^HT|)jtGf7uHR)>?Ds8k4IAM70tgV{o zl;CTUZ!OZ+TJHTBFH;}$dv=4D`{$ECxqjI0W0>qFyL^ejd|=oyFnGH9xvX+MF)9ciVkxPqL7e~ zw#iMyFyq9;#N2K4!bdi+00001bW%=J06^y0W&i*H?MXyIRCwBrkP8ljFbqS7(@%h| z_do8OFw~a9v?rvh%bOi|{mFY~8--;e-U-2Z6l~PaGzo!ECVzJJ32(=L%)!ZiiJQ^w z7dX#_@G!xN-F~d*yjC-KnFR)vvevqm67rLcx0MMQTuENZzX_;{y5m#5+)fPyP~!0urfE8urni4s#VCY+sOQ^4dwXo#FL zT1A8XD(yNYSW3LAt$Z(dx+sKVFT@m6Iwc5O%v+*iJ2+d{BJIzl7gUZf{v?R_OVYrd jFft3tHaec~N#QR(NOBBaImqA(00000NkvXXu0mjfFZ_=# diff --git a/crawl-ref/source/rltiles/gui/invocations/fedhas_wall_of_briars.png b/crawl-ref/source/rltiles/gui/invocations/fedhas_wall_of_briars.png index ef367f50a4110b1884c2e4fdad66580eea7f6f36..0fda4bd1820fd3bd254527f7e3449fb06b57ab08 100644 GIT binary patch literal 1146 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy93=&Q?(RM=#y~cMSA(WJkYY)9 z^mSxl*x1kgCy|wbftew|C&cyt|Nlph9GNg-0#Jd0fq??6uY-ewD|@9(n#f^;#|d40 zcXGe*m+8=%XKxDiOT=~KR;*OKg%v6 zah-`you&Wf^Uq^*uHOh(h*kQ}JLNjp*&r{WNlEpe&ROuS?g>>CO0_y*+wnIcdl%yj z)+?XhS~3S5)JR_9c{Xg@K5?5_Q)WzG(4d-cvsL2~W5(6b5-(ibI!~?g-t6(FOlwAY z$h9|>!cPR}s@)Z?HClhqm9?p<_u49fkJEQQ31DIf{o(lf+|oB|Ps^;(jFXykGb39| z!+qhc*FPd$oy2dgySVLPUv_q6pU~e`{f77Ms0DwuIWN3G{7_>|k>*^E@JW)NPu~?6 u|NKFand1oahv0{T8YNfeZ(DbuxQ6k{M*a);8)Yg$(ctOo=d#Wzp$Py?W3V^? delta 302 zcmV+}0nz^Y2+0DFB!3}LOjJbx0000001Pz}9A*?SFfc$sKwydvkdTnJ$xXz>#Q*>Q zW)c-!00001bW%=J06^y0W&i*H)=5M`RCwB@l7Vi-APhqnzv8n0|KTmbHP=JaPMd{_ zgkMaW_Tx=`?mF*4Y&!l8w6_wfzX+lP-@uuwVsp6x6|;aDAb*6UVQ)Z8PhwCTAW-!o zR!n;USyN&iRD$Gqk*op)yaEPYS732}S*^2`U`agt1c*wIpr=Vf*FdNy)0af=#wI1- z0GUjoi$S=;s4F~hgpugzF^Rfj%JbRxuerpsegvGv4jk=h zZ4rL*QrDk*Rwox#Tq+>^8xVg6T6Q$o+7oz3UyE@E$o1&L>i_@%07*qoM6N<$f>fD< AA^-pY diff --git a/crawl-ref/source/rltiles/gui/invocations/sif_muna_exegesis.png b/crawl-ref/source/rltiles/gui/invocations/sif_muna_exegesis.png index 75d6f75ed54d7105e390d76848977ba04392631c..beca61fe36df42d2f1d5f12c8f228019434a8ab3 100644 GIT binary patch literal 1121 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy93=&Q?(RM=#y~cMSA(WJkYY)9 z^mSxl*x1kgCy|wbftew|C&cyt|Nlph9GNg-0#Jd0fq{dA12gj}2Kx^TSs$dCIzYNd z!Dt8!-w-gX=3fEy9b=NWyUYKj?4OQ;I3+=T!3+-1ZlnP@_dH!3Ln`L%oz%)BpC=7_w+bR*;S+2R?(4NMx# zx>yyKu3%%RJ7mbTfX{d`Q=#*YO`=S*tm4^agguk&8CuT0DLBj7t-@(wT&iH!F_o^);-_9&T?liYxHx*r-#NLP-uKuuYT2?LN>@%uInyUHWlnxW!1heO zhwSWAj4vo04?O;EM)P{V+82k6ww1j5z2TEfWIOA&ef;I(Y3r-ka`%?qxs$v1=azbg hsiIre_Zt`F%NrT-ysgBP7mKY&3;*s6P!Q4U<+hp|rYx-Q6~BmPt0+BIsoH?#`IW&Nwr>{h?1qP<%1! zn-s*qw}2oh^$*)Vv@ewkCEC;=C_c3KgHY&;rt6tIGnr|+v47rW?tJr|@1A?^xo7VM z=((y`mXQC3ECFkK$#7nA@pGN!$;%jYvwjAKwmYb0gKL(K8-kPtb5${A?tlI~wzMrJ6 zwTdBr=Y%%%EaEMQ&o}4FQ^DA)s*}Z>!FI&AHCpoWJAVYgiMm^w@yBxeZBw4|=jG}( zn#+56MEv@^c}Vtsa-TWv>3rz(gqAG_{H2$agB8Ssh<~9*LH6h3{;}Lj5Ca)%8s$lU zE|Q}TTQB2XZKmkYOAHq`)E`S0>-vFGp#Ma(i*kUkSq7_7jEzs)ExGFJ`BBBr7kr<5 zg*K~!e}BFWvk3(#m@tRE3Qbr85o9Pp2HzIgXsLq^1~L?_6d8(Np=K8w=fFJjI<%S1 z!M?(j{>aE*gZa45v?^qWK7tmq8vKr|7Sm<%tA$)+6F+_|Hv&H<86XnbgU?sv0UjaH&M3Y8J)UU&iP;Y>-;kIEBtDt;D6*-@walvTFkq$OvCJKSaWw( z8f^yS7Vy!T#filo^KtRyR}V&hmdTmtuk>9!S#K^5My!_w`fB-B8BUEvtn`EQhqNrc zCx3k?{l>k`ead~!ea?NsT>_Ci%bnxC;Vy6=b6>{xYV#Ue-+LB$7`JEXmTRm^AtP)R z9u{)KHsMiWGV&)32xCG~*nyU<>-!d;FP=Re4r3qYr~6#KE>;1F`>_J_P5xC?ROxV( zDIHdCO*p$HRQI@7^PwV@Pk-f7X%JI8QxmDN)Ikr2v!-^SZ36rJ9o4CB zvQp~OW8QrNS<^ah>kZ8ncT3WfVj8bDDwdk+=!mEohR95gXj6yUZCV=z@80x}^qVrf z4-;E1N1Xc%z`j56?E5a_j6hWRXizZ=+e_rXTlZIQRPHboQR5!l9o(vK%b7rU81-0YFE}uGQ*6~j4f%uZ$Gl- z+>^&k$^Y?q{44S9rJv7dx8LtgUw^MPW83Yv#-7Yuuh&J{uE?2*F$;j@a#;-LApnc7 zUx%kPZns-egnHnShU>qJwiCu~x67J3Hs$~T0@cSyoAAT_WYFq%;Kw&6^xWhUaH{p( zAAVrNj}yJY3$(B&V&gR#K!126Qi5LY<=+L2Z_{>;?Pev60N6cxr3|X}3983aiNd;OJ z07Mvsq*#o>QIeg3B}Y>-B3fZJsRR%u2U*Pry63}L1|mjXJ`G#~^Jk Date: Wed, 23 Oct 2019 16:18:15 +0800 Subject: [PATCH 843/864] Fix loading screen click activating main menu This fix drops mouseup events if the UI layout has been changed since the corresponding (well, previous) mousedown event. This fixes a bug where the loading screen would transition to the main menu on mousedown, and the mouseup event would then activate the button underneath the cursor. I'm not sure this is the best way to fix this. Some alternatives: - have the loading screen transition on mouseup - have the loading screen "swallow" the mouseup event explicitly via some new API - have menu buttons only activate on mouseup if they also received a corresponding mousedown (cherry picked from commit 47823c4faefee8c16e2bbc002f017b4178b1c2a4) --- crawl-ref/source/ui.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index e41ebe7c7771..372f09ed568b 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -103,6 +103,7 @@ static struct UIRoot Region m_dirty_region; Stack m_root; bool m_needs_layout{false}; + bool m_changed_layout_since_click = false; } ui_root; static stack scissor_stack; @@ -1690,6 +1691,7 @@ void UIRoot::push_child(shared_ptr ch, KeymapContext km) m_root.add_child(move(ch)); m_needs_layout = true; keymap_stack.push_back(km); + m_changed_layout_since_click = true; #ifndef USE_TILE_LOCAL if (m_root.num_children() == 1) { @@ -1705,6 +1707,7 @@ void UIRoot::pop_child() m_needs_layout = true; keymap_stack.pop_back(); focus_stack.pop_back(); + m_changed_layout_since_click = true; #ifndef USE_TILE_LOCAL if (m_root.num_children() == 0) clrscr(); @@ -1926,6 +1929,11 @@ bool UIRoot::on_event(const wm_event& event) } #endif case WME_MOUSEWHEEL: + if (event.type == WME_MOUSEBUTTONDOWN) + m_changed_layout_since_click = false; + else if (event.type == WME_MOUSEBUTTONUP) + if (m_changed_layout_since_click) + break; if (!prev_hover_path.empty()) { for (auto w = prev_hover_path.back(); w; w = w->_get_parent()) if (w->on_event(event)) From 51e9afa94300be53221bf75720e5c9404076ea39 Mon Sep 17 00:00:00 2001 From: theJollySin Date: Tue, 22 Oct 2019 20:02:27 -0400 Subject: [PATCH 844/864] Fixed typo in wands mutation (12103) (cherry picked from commit 6afad29e878baea94b95ee9619936732aae7d61b) --- crawl-ref/source/mutation-data.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/mutation-data.h b/crawl-ref/source/mutation-data.h index 00d30d730c15..401aba72458f 100644 --- a/crawl-ref/source/mutation-data.h +++ b/crawl-ref/source/mutation-data.h @@ -1834,7 +1834,7 @@ static const mutation_def mut_data[] = {"You expend magic power (3 MP) to strengthen your wands.", "", ""}, {"You feel your magical essence link to the dungeon's wands.", "", ""}, - {"Your magical essence longer links to wands of the dungeon.", "", ""}, + {"Your magical essence no longer links to wands of the dungeon.", "", ""}, }, { MUT_UNSKILLED, 0, 3, mutflag::bad, false, From 8d94f1b860ec2b53f40bf116c393c0a112712d65 Mon Sep 17 00:00:00 2001 From: advil Date: Mon, 21 Oct 2019 11:15:13 -0400 Subject: [PATCH 845/864] Add seed as a logfile/score entry This is necessary if scoring (or perhaps sequell) is to do anything interesting with seeded games. This commit adds the seed for all game types, since even for normal games the seed is revealed on game end. Milestones do not have this field for any game type. (cherry picked from commit 6c54e258949e810b17e3a18e2f11560b5d425482) --- crawl-ref/source/hiscores.cc | 8 ++++++++ crawl-ref/source/hiscores.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/crawl-ref/source/hiscores.cc b/crawl-ref/source/hiscores.cc index 050a6b3d0878..fa96b6569d5b 100644 --- a/crawl-ref/source/hiscores.cc +++ b/crawl-ref/source/hiscores.cc @@ -797,6 +797,7 @@ void scorefile_entry::init_from(const scorefile_entry &se) zigmax = se.zigmax; scrolls_used = se.scrolls_used; potions_used = se.potions_used; + seed = se.seed; fixup_char_name(); // We could just reset raw_line to "" instead. @@ -1100,6 +1101,8 @@ void scorefile_entry::init_with_fields() scrolls_used = fields->int_field("scrollsused"); potions_used = fields->int_field("potionsused"); + seed = fields->str_field("seed"); + fixup_char_name(); } @@ -1249,6 +1252,8 @@ void scorefile_entry::set_score_fields() const if (!killer_map.empty()) fields->add_field("killermap", "%s", killer_map.c_str()); + fields->add_field("seed", "%s", seed.c_str()); + #ifdef DGL_EXTENDED_LOGFILES const string short_msg = short_kill_message(); fields->add_field("tmsg", "%s", short_msg.c_str()); @@ -1534,6 +1539,7 @@ void scorefile_entry::reset() zigmax = 0; scrolls_used = 0; potions_used = 0; + seed.clear(); } static int _award_modified_experience() @@ -1773,6 +1779,7 @@ void scorefile_entry::init(time_t dt) wiz_mode = (you.wizard || you.suppress_wizard ? 1 : 0); explore_mode = (you.explore ? 1 : 0); + seed = make_stringf("%" PRIu64, crawl_state.seed); } string scorefile_entry::hiscore_line(death_desc_verbosity verbosity) const @@ -1976,6 +1983,7 @@ scorefile_entry::character_description(death_desc_verbosity verbosity) const ASSERT(birth_time); desc += " on "; desc += _hiscore_date_string(birth_time); + // TODO: show seed here? desc = _append_sentence_delimiter(desc, "."); desc += _hiscore_newline_string(); diff --git a/crawl-ref/source/hiscores.h b/crawl-ref/source/hiscores.h index 936e5b38bf5e..081c7dcc60c2 100644 --- a/crawl-ref/source/hiscores.h +++ b/crawl-ref/source/hiscores.h @@ -131,6 +131,8 @@ class scorefile_entry int scrolls_used; // Number of scrolls used. int potions_used; // Number of potions used. + string seed; // Game seed: use string here for simplicity + // even though the seed is really uint64_t mutable unique_ptr fields; From 4422a53305d8dce36412166256d6ee5d46330fcf Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Fri, 18 Oct 2019 03:46:35 +0800 Subject: [PATCH 846/864] Fix tile_menu_icons = false on local tiles ability menu (cherry picked from commit 3d4e485b54e32bcd72b93423cd8ece20fa6c091d) --- crawl-ref/source/menu.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/menu.cc b/crawl-ref/source/menu.cc index cdaa9ca2ea71..4cc2fed3049e 100644 --- a/crawl-ref/source/menu.cc +++ b/crawl-ref/source/menu.cc @@ -1950,8 +1950,9 @@ void Menu::update_title() } #ifdef USE_TILE_LOCAL + const bool tile_indent = m_indent_title && Options.tile_menu_icons; m_ui.title->set_margin_for_sdl(0, 0, 10, - UIMenu::item_pad + (m_indent_title ? 38 : 0)); + UIMenu::item_pad + (tile_indent ? 38 : 0)); #endif m_ui.title->set_text(fs); #ifdef USE_TILE_WEB From cc77c95bd55dc4b1e24f2c4f67061108d665ec1c Mon Sep 17 00:00:00 2001 From: Aidan Holm Date: Fri, 18 Oct 2019 04:09:29 +0800 Subject: [PATCH 847/864] Specify max menu width relative to font size (Siegurt, 12097) (cherry picked from commit 1393849f60c06f46d8d5bdcf1f56acb0d0941cd4) --- crawl-ref/source/menu.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/menu.cc b/crawl-ref/source/menu.cc index 4cc2fed3049e..62fbfb9ec7ca 100644 --- a/crawl-ref/source/menu.cc +++ b/crawl-ref/source/menu.cc @@ -429,7 +429,8 @@ SizeReq UIMenu::_get_preferred_size(Direction dim, int prosp_width) if (!dim) { do_layout(INT_MAX, m_num_columns); - int max_menu_width = min(1400, m_nat_column_width * m_num_columns); + const int em = Options.tile_font_crt_size; + int max_menu_width = min(93*em, m_nat_column_width * m_num_columns); return {0, max_menu_width}; } else From ba7f130744bf1b81989821462d83d48e5cf6c48b Mon Sep 17 00:00:00 2001 From: Umer Shaikh Date: Mon, 14 Oct 2019 17:27:50 -0500 Subject: [PATCH 848/864] Show flay damage in status light It is tactically useful to know how much damage is due to flay. For example, it matters in deciding whether to quaff cancellation or who to attack. This information is already revealed to the player, but not in a convenient way. At the moment the careful player must pay attention to what the sources of damage are as the fight proceeds in order to know this; and, if this is neglected, it is difficult to recover the information from the message log later in the fight. This commit reveals that information more straightforwardly by adding it to the flay status light. I show a number instead of a more coarse-grained indicator. Note that otherwise the conscientious player will still want to keep track manually of damage since they can get better information that way. The damage is displayed as a negative number for consistency with the similar corrosion status light. (cherry picked from commit f18fdeb47fb032eb79fe9f080848187dd3848525) --- crawl-ref/source/status.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crawl-ref/source/status.cc b/crawl-ref/source/status.cc index 5a508860d64c..ddb928fa9ce3 100644 --- a/crawl-ref/source/status.cc +++ b/crawl-ref/source/status.cc @@ -193,6 +193,10 @@ bool fill_status_info(int status, status_info& inf) (-4 * you.props["corrosion_amount"].get_int())); break; + case DUR_FLAYED: + inf.light_text = make_stringf("Flay (%d)", + (-1 * you.props["flay_damage"].get_int())); + case DUR_NO_POTIONS: if (you_foodless()) inf.light_colour = DARKGREY; From cf0c3ad76dec0dae820c75df6c0174464346e71f Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 16 Oct 2019 09:50:18 -0400 Subject: [PATCH 849/864] Revert "Remove support for multi-key macro binds" + associated commits It turns out that multi-key macros were used for keybinds for multi-character sequences sent by some terminals corresponding to special keys. For example, under the VT100 standard, \{27}Ov is sent by numpad 6. Another example: on OS X, option+arrow keys send multi-character escape sequences as well (maybe even outside of terminal). This sequence of commits broke such old macro files, and even worse, tended to break ESC, since nearly all of these sequences are ESC sequences. We'll need to rethink how to simplify this. Some of these simplifications might be independent of the current revert project and could be restored... This reverts commit 049a78546b28e77ec9647cdfd40840a8451f18ad. (Note: also a partial revert of d158fba7, 0b1efcb, 0e779d2) This reverts commit 678ee33c32bb4efb2fda34a8b44ce857352add0c. This reverts commit 5a8975c3e2236cd5aa0d3cf1738ccfdd360a4ab3. This reverts commit 3ea5ddb52caf3a66e4f92f90f056132a344c65e3. (cherry picked from commit 72dcfe03596c23c1c632c9b6aa444db567820120) --- crawl-ref/source/macro.cc | 142 +++++++++++++++++++++++++++----------- crawl-ref/source/macro.h | 2 +- crawl-ref/source/ui.cc | 7 +- 3 files changed, 107 insertions(+), 44 deletions(-) diff --git a/crawl-ref/source/macro.cc b/crawl-ref/source/macro.cc index cc79b47ac515..a5710515610a 100644 --- a/crawl-ref/source/macro.cc +++ b/crawl-ref/source/macro.cc @@ -52,7 +52,7 @@ #include "version.h" typedef deque keybuf; -typedef map macromap; +typedef map macromap; static macromap Keymaps[KMC_CONTEXT_COUNT]; static macromap Macros; @@ -391,16 +391,15 @@ static string vtostr(const keyseq &seq) /* * Add a macro (surprise, surprise). */ -static void macro_add(macromap &mapref, int key, keyseq action) +static void macro_add(macromap &mapref, keyseq key, keyseq action) { - if (!action.empty()) - mapref[key] = action; + mapref[key] = action; } /* * Remove a macro. */ -static bool macro_del(macromap &mapref, int key) +static bool macro_del(macromap &mapref, keyseq key) { return mapref.erase(key) != 0; } @@ -494,17 +493,57 @@ void macro_buf_add_cmd(command_type cmd, bool reverse) } /* - * Adds keys from a sequence to the end of the internal keybuffer. - * Each key is expanded/converted with the given keymap. + * Adds keypresses from a sequence into the internal keybuffer. Does some + * O(N^2) analysis to the sequence to apply keymaps. */ static void macro_buf_add_long(keyseq actions, macromap &keymap = Keymaps[KMC_DEFAULT]) { - for (const auto key : actions) + keyseq tmp; + + // debug << "Adding: " << vtostr(actions) << endl; + // debug.flush(); + + // Check whether any subsequences of the sequence are macros. + // The matching starts from as early as possible, and is + // as long as possible given the first constraint. I.e from + // the sequence "abcdef" and macros "ab", "bcde" and "de" + // "ab" and "de" are recognised as macros. + + while (!actions.empty()) { - const auto subst = keymap.find(key); - const auto out = subst == keymap.end() ? keyseq({key}) : subst->second; - macro_buf_add(out, false, false); + tmp = actions; + + while (!tmp.empty()) + { + auto subst = keymap.find(tmp); + // Found a macro. Add the expansion (action) of the + // macro into the buffer. + if (subst != keymap.end() && !subst->second.empty()) + { + macro_buf_add(subst->second, false, false); + break; + } + + // Didn't find a macro. Remove a key from the end + // of the sequence, and try again. + tmp.pop_back(); + } + + if (tmp.empty()) + { + // Didn't find a macro. Add the first keypress of the sequence + // into the buffer, remove it from the sequence, and try again. + macro_buf_add(actions.front(), false, false); + actions.pop_front(); + } + else + { + // Found a macro, which has already been added above. Now just + // remove the macroed keys from the sequence. + for (unsigned int i = 0; i < tmp.size(); i++) + actions.pop_front(); + } } } @@ -557,15 +596,29 @@ static void macro_buf_apply_command_macro() if (macro_keys_left > 0 || expanded_keys_left > 0) return; - const auto expansion = Macros.find(Buffer.front()); - if (expansion != Macros.end()) + keyseq tmp = Buffer; + + // find the longest match from the start of the buffer and replace it + while (!tmp.empty()) { - const keyseq &result = expansion->second; + auto expansion = Macros.find(tmp); + + if (expansion != Macros.end() && !expansion->second.empty()) + { + const keyseq &result = expansion->second; - // Found macro, remove match from front: - Buffer.pop_front(); - macro_keys_left = result.size(); - macro_buf_add(result, true, true); + // Found macro, remove match from front: + for (unsigned int i = 0; i < tmp.size(); i++) + Buffer.pop_front(); + + macro_keys_left = result.size(); + + macro_buf_add(result, true, true); + + break; + } + + tmp.pop_back(); } } @@ -622,7 +675,7 @@ static void write_map(FILE *f, const macromap &mp, const char *key) if (entry.second.size()) { fprintf(f, "%s%s\nA:%s\n\n", OUTS(key), - OUTS(vtostr({entry.first})), OUTS(vtostr(entry.second))); + OUTS(vtostr(entry.first)), OUTS(vtostr(entry.second))); } } } @@ -666,8 +719,11 @@ void macro_save() * Reads as many keypresses as are available (waiting for at least one), * and returns them as a single keyseq. */ -static int _getch_single(int (*rgetch)() = nullptr) +static keyseq _getch_mul(int (*rgetch)() = nullptr) { + keyseq keys; + int a; + // Something's gone wrong with replaying keys if crawl needs to // get new keys from the user. if (crawl_state.is_replaying_keys()) @@ -680,16 +736,17 @@ static int _getch_single(int (*rgetch)() = nullptr) if (!rgetch) rgetch = m_getch; - // The key == 0 test is legacy code that I don't dare to remove. I + // The a == 0 test is legacy code that I don't dare to remove. I // have a vague recollection of it being a kludge for conio support. - int key; do { - key = rgetch(); + a = rgetch(); + if (a != CK_NO_KEY) + keys.push_back(a); } - while (key == 0 || key == CK_NO_KEY); + while (keys.size() == 0 || ((kbhit() || a == 0) && a != CK_REDRAW)); - return key; + return keys; } /* @@ -709,17 +766,18 @@ int getchm(KeymapContext mc, int (*rgetch)()) if ((a = macro_buf_get()) != -1) return a; - // Read a key... - macro_buf_add_with_keymap(_getch_single(rgetch), mc); + // Read some keys... + keyseq keys = _getch_mul(rgetch); + macro_buf_add_with_keymap(keys, mc); return macro_buf_get(); } -void macro_buf_add_with_keymap(int key, KeymapContext mc) +void macro_buf_add_with_keymap(keyseq keys, KeymapContext mc) { if (mc == KMC_NONE) - macro_buf_add(keyseq({key}), false, false); + macro_buf_add(keys, false, false); else - macro_buf_add_long(keyseq({key}), Keymaps[mc]); + macro_buf_add_long(keys, Keymaps[mc]); } /** @@ -745,8 +803,14 @@ int getch_with_command_macros() _macro_inject_sent_keys(); if (Buffer.empty()) - macro_buf_add_with_keymap(_getch_single(), KMC_DEFAULT); + { + // Read some keys... + keyseq keys = _getch_mul(); + // ... and add them into the buffer (apply keymaps) + macro_buf_add_long(keys); + } + // Apply longest matching macro at front of buffer: macro_buf_apply_command_macro(); return macro_buf_get(); @@ -951,14 +1015,15 @@ void macro_add_query() macro_type.c_str()); msgwin_prompt(trigger_prompt); + keyseq key; mouse_control mc(MOUSE_MODE_MACRO); - int key = m_getch(); - string key_str = vtostr({key}); + key = _getch_mul(); + string key_str = vtostr(key); key_str = replace_all(key_str, "<", "<<"); - msgwin_reply(vtostr({key})); + msgwin_reply(vtostr(key)); - if (mapref.count(key)) + if (mapref.count(key) && !mapref[key].empty()) { string action_str = vtostr(mapref[key]); action_str = replace_all(action_str, "<", "<<"); @@ -1061,8 +1126,7 @@ static void _read_macros_from(const char* filename) else if (s.substr(0, 2) == "A:") { action = parse_keyseq(s.substr(2)); - if (!key.empty()) - macro_add((keymap ? Keymaps[keymc] : Macros), key.front(), action); + macro_add((keymap ? Keymaps[keymc] : Macros), key, action); } } } @@ -1125,10 +1189,10 @@ string read_rc_file_macro(const string& field) keyseq key = parse_keyseq(macro_key_string); + keyseq action = parse_keyseq(action_string); - if (!key.empty()) - macro_add((keymap ? Keymaps[keymc] : Macros), key.front(), action); + macro_add((keymap ? Keymaps[keymc] : Macros), key, action); // If we didn't save here, macros in rc files would be saved iff you also // changed another macro with cntrl-D and saved at the exit prompt. diff --git a/crawl-ref/source/macro.h b/crawl-ref/source/macro.h index 3579ce6674c9..7c0eb340f4be 100644 --- a/crawl-ref/source/macro.h +++ b/crawl-ref/source/macro.h @@ -69,7 +69,7 @@ void macro_buf_add(const keyseq &actions, int macro_buf_get(); void macro_buf_add_cmd(command_type cmd, bool reverse = false); -void macro_buf_add_with_keymap(int key, KeymapContext mc); +void macro_buf_add_with_keymap(keyseq keys, KeymapContext mc); void process_command_on_record(command_type cmd); diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 372f09ed568b..83a9ac116dec 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -2059,10 +2059,9 @@ void resize(int w, int h) static void remap_key(wm_event &event) { - const auto keymap = ui_root.keymap_stack.size() > 0 ? - ui_root.keymap_stack[0] : KMC_NONE; - ASSERT(get_macro_buf_size() == 0); - macro_buf_add_with_keymap(event.key.keysym.sym, keymap); + keyseq keys = {event.key.keysym.sym}; + KeymapContext km = ui_root.keymap_stack.size() > 0 ? ui_root.keymap_stack[0] : KMC_NONE; + macro_buf_add_with_keymap(keys, km); event.key.keysym.sym = macro_buf_get(); ASSERT(event.key.keysym.sym != -1); } From 316ccf478cb6db40e785f02c60eecf8573b6dfac Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 15 Oct 2019 21:33:19 -0400 Subject: [PATCH 850/864] Fix Ru sacrifice delay with faith (12096 / @Wise Wolf) Specific problem and solution found by @Wise Wolf on discord yesterday. (cherry picked from commit dc1bd944b940028749200348b2781e8de0de9dc0) --- crawl-ref/source/god-abil.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/god-abil.cc b/crawl-ref/source/god-abil.cc index 514d007087e2..a64032f20805 100644 --- a/crawl-ref/source/god-abil.cc +++ b/crawl-ref/source/god-abil.cc @@ -4629,7 +4629,7 @@ void ru_reset_sacrifice_timer(bool clear_timer, bool faith_penalty) } } - delay = div_rand_round((delay + added_delay) * (3 + you.faith()), 3); + delay = div_rand_round((delay + added_delay) * (3 - you.faith()), 3); if (crawl_state.game_is_sprint()) delay /= SPRINT_MULTIPLIER; From f54ec44420ca75dcda62c93581b4edba8c629d96 Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 15 Oct 2019 16:09:22 -0400 Subject: [PATCH 851/864] Add a webtiles seed selection popup At first glance, this may appear to be a feature, but it is in fact a bug: the bug is that paste doesn't work for crt-emulated input. Implementing this as an actual textbox is the only way I've found to get this to work in webtiles. This doesn't materially change the implementation of the seed selection ui for console/local tiles; it is just as bad as ever. (cherry picked from commit 74baf033cde2925bc0162ed73ab4f426301930a9) --- crawl-ref/source/newgame.cc | 95 ++++++++++++++----- .../webserver/game_data/static/style.css | 66 +++++++++++++ .../webserver/game_data/static/textinput.js | 57 ++++++++++- .../webserver/game_data/static/ui-layouts.js | 13 +++ .../webserver/game_data/templates/game.html | 7 ++ 5 files changed, 212 insertions(+), 26 deletions(-) diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 541d0bf077eb..a8ae0c0dc5cc 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -760,10 +760,6 @@ static keyfun_action _keyfun_seed_input(int &ch) static void _choose_seed(newgame_def& ng, newgame_def& choice, const newgame_def& defaults) { -#ifdef USE_TILE_WEB - tiles_crt_popup show_as_popup; -#endif - char buf[21]; // max unsigned 64 bit integer is 20 chars in decimal, // specifically 18446744073709551615 buf[0] = '\0'; @@ -806,6 +802,15 @@ static void _choose_seed(newgame_def& ng, newgame_def& choice, char timebuf[9]; strftime(timebuf, sizeof(timebuf), "%Y%m%d", timeinfo); reader.set_text(timebuf); +#ifdef USE_TILE_WEB + // TODO: can this be done more automatically somehow? + tiles.json_open_object(); + tiles.json_write_string("msg", "update_input"); + tiles.json_write_string("input_text", string(timebuf)); + tiles.json_write_bool("select", true); + tiles.json_close_object(); + tiles.finish_message(); +#endif return done = false; } else if (key == '?') @@ -813,6 +818,15 @@ static void _choose_seed(newgame_def& ng, newgame_def& choice, else if (key == '-') { reader.set_text(""); +#ifdef USE_TILE_WEB + // TODO: can this be done more automatically somehow? + tiles.json_open_object(); + tiles.json_write_string("msg", "update_input"); + tiles.json_write_string("input_text", string("")); + tiles.json_write_bool("select", true); + tiles.json_close_object(); + tiles.finish_message(); +#endif return done = false; } #ifdef USE_TILE_LOCAL @@ -850,42 +864,69 @@ static void _choose_seed(newgame_def& ng, newgame_def& choice, pregen_choice->set_text( "Pregenerate the dungeon ([tab] to switch)? Yes | No"); } + const string title_text = make_stringf( + "Play a game with a custom seed for version %s.", + Version::Long); + const string body_text = + "Choose 0 for a random seed. Press [d] for today's daily seed.\n" +#ifdef USE_TILE_LOCAL + "Press [p] to paste a seed from the clipboard (overwriting the\n" + "current value).\n" +#endif + ; + const string prompt_text = "Seed ([-] to clear):"; + const string footer_text = + "The seed will determine the dungeon layout, monsters, and items\n" + "that you discover, relative to this version of crawl. (See the \n" + "manual for more details.)" +#ifdef SEEDING_UNRELIABLE + "Warning: your build of crawl does not support stable seeding!\n" + "Levels may differ from 'official' seeded games." +#endif + ; auto popup = make_shared(box); ui::push_layout(move(popup)); ui::set_focused_widget(prompt_ui.get()); +#ifdef USE_TILE_WEB + // activate seed selection popup + tiles.json_open_object(); + tiles.json_write_string("body", body_text); + tiles.json_write_string("title", title_text); + tiles.json_write_string("footer", footer_text); + tiles.push_ui_layout("seed-selection", 1); + // activate input box. TODO: have this happen automatically on the js side + // when the popup is in place? + tiles.json_open_object(); + tiles.json_write_string("msg", "init_input"); + tiles.json_write_string("type", "seed-selection"); + tiles.json_write_string("prefill", string(buf)); + tiles.json_write_string("prompt", prompt_text); + tiles.json_write_int("maxlen", sizeof(buf) - 1); + tiles.json_write_bool("select_prefill", true); + tiles.json_close_object(); + tiles.finish_message(); +#endif while (!done && !crawl_state.seen_hups) { + // TODO: rewrite with widgets formatted_string prompt; prompt.textcolour(CYAN); - prompt.cprintf("Play a game with a custom seed for version %s.\n\n", - Version::Long); + prompt.cprintf(title_text + "\n\n"); prompt.textcolour(LIGHTGREY); - prompt.cprintf( - "Choose 0 for a random seed. Press [d] for today's daily seed.\n" -#ifdef USE_TILE_LOCAL - "Press [p] to paste a seed from the clipboard (overwriting the\n" - "current value).\n" -#endif - "\n"); - prompt.cprintf("Seed ([-] to clear):"); + prompt.cprintf(body_text + "\n"); + + prompt.cprintf(prompt_text); string seed_text = make_stringf("%-20s", buf); prompt.cprintf("\n%s\n\n", seed_text.c_str()); - prompt.cprintf( - "The seed will determine the dungeon layout, monsters, and items\n" - "that you discover, relative to this version of crawl. (See the \n" - "manual for more details.)\n\n"); -#ifdef SEEDING_UNRELIABLE - prompt.cprintf( - "Warning: your build of crawl does not support stable seeding!\n" - "Levels may differ from 'official' seeded games.\n\n"); -#endif + prompt.cprintf(footer_text + "\n\n"); prompt_ui->set_text(prompt); // yes this appalling, some day we will have real buttons and text // input. The seed highlight doesn't do much on console, but makes // tiles look a lot better. N.b. the newline before the seed above // is really so that an empty seed string won't get multiple highlights. + // TODO: not implemented on the webtiles side. prompt_ui->set_highlight_pattern(seed_text, false); if (show_pregen_toggle) { @@ -897,7 +938,15 @@ static void _choose_seed(newgame_def& ng, newgame_def& choice, ui::pump_events(); } ui::pop_layout(); +#ifdef USE_TILE_WEB + // decomission input box, if it's still around + tiles.json_open_object(); + tiles.json_write_string("msg", "close_input"); + tiles.json_close_object(); + tiles.finish_message(); + tiles.pop_ui_layout(); +#endif string result = reader.get_text(); uint64_t tmp_seed = 0; // TODO: if the user types in a number that exceeds the max value, sscanf diff --git a/crawl-ref/source/webserver/game_data/static/style.css b/crawl-ref/source/webserver/game_data/static/style.css index 1b224dcd7fc9..f355bd144a79 100644 --- a/crawl-ref/source/webserver/game_data/static/style.css +++ b/crawl-ref/source/webserver/game_data/static/style.css @@ -1183,3 +1183,69 @@ body { flex: 1 1 auto; white-space: pre-wrap; } + +.seed-selection { + max-width: 80ch; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + width: 100%; /* for IE11 */ + max-height: inherit; +} + +.seed-selection > .header { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + margin-bottom: 20px; + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; +} + +.seed-selection > .body { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + margin-bottom: 20px; + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; +} + +.seed-selection > .footer { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; +} + +.seed-selection > .seed-input { + line-height: 1.2em; + white-space: pre; + display: -webkit-box; + display: -ms-flexbox; + display: flex; +} + +.seed-selection > .seed-input > span > input { + line-height: 1.2em; + min-width: 20em; /* TODO: this is too wide, but it's a safe value */ + margin-left: 1em; + white-space: pre; +} diff --git a/crawl-ref/source/webserver/game_data/static/textinput.js b/crawl-ref/source/webserver/game_data/static/textinput.js index 99a5846eeafe..16cd81239343 100644 --- a/crawl-ref/source/webserver/game_data/static/textinput.js +++ b/crawl-ref/source/webserver/game_data/static/textinput.js @@ -18,6 +18,8 @@ function ($, comm, client, enums, util, options, ui) { assert(input_data); if (input_data.type == "messages") return $("#messages .game_message input"); + else if (input_data.type == "seed-selection") + return $(".seed-selection .seed-input input"); else //"generic" return $("#input_dialog input"); } @@ -54,6 +56,15 @@ function ($, comm, client, enums, util, options, ui) { prompt = $("#messages .game_message").last(); prompt.append(input); } + else if (input_data.type == "seed-selection") + { + // n.b. called from ui-layouts.js, not from client + var input_div = $(".seed-selection .seed-input").last(); + if (prompt) + input_div.append($("").append(prompt)); + // TODO: what is this class? + input_div.append($("").append(input)); + } else // "generic" { var input_div = $("

"); @@ -91,7 +102,11 @@ function ($, comm, client, enums, util, options, ui) { comm.send_message("key", { keycode: 11 }); } comm.send_message("input", { text: text }); - close_input(); + // seed-selection handles this on its own, because there is first + // a validation step -- the input loop only terminates on abort + // or if there is an actual number to be found. + if (input_data.type != "seed-selection") + close_input(); } input.keydown(function (ev) { @@ -163,6 +178,24 @@ function ($, comm, client, enums, util, options, ui) { return false; } } + else if (input_data.type == "seed-selection") + { + var ch = String.fromCharCode(ev.which); + if (ch == "-" // clear input + || ch == "?" // help + || ch == "d") // daily seed + { + comm.send_message("key", { keycode: ev.which }); + ev.preventDefault(); + return false; + } + // mimic keyfunc on crawl side: prevent non-numbers + if ("0123456789".indexOf(ch) == -1) + { + ev.preventDefault(); + return false; + } + } }); } @@ -210,8 +243,11 @@ function ($, comm, client, enums, util, options, ui) { if (input) { input.blur(); - if (input_data.type == "messages") + if (input_data.type == "messages" + || input_data.type == "seed-selection") + { input.remove(); + } else // "generic" ui.hide_popup(); } @@ -220,9 +256,24 @@ function ($, comm, client, enums, util, options, ui) { input_cleanup(); } + function update_input(msg) + { + if (input_data) + { + var input = find_input(); + if (input) + { + input.val(msg.input_text); + if (msg.select) + input.select(); + } + } + } + comm.register_handlers({ "init_input": init_input, - "close_input": close_input + "close_input": close_input, + "update_input": update_input }); diff --git a/crawl-ref/source/webserver/game_data/static/ui-layouts.js b/crawl-ref/source/webserver/game_data/static/ui-layouts.js index 74e00a5b7bcb..000fd1aa98ca 100644 --- a/crawl-ref/source/webserver/game_data/static/ui-layouts.js +++ b/crawl-ref/source/webserver/game_data/static/ui-layouts.js @@ -863,6 +863,18 @@ function ($, comm, client, ui, enums, cr, util, scroller, main, gui, player) { return $popup; } + function seed_selection(desc) + { + var $popup = $(".templates > .seed-selection").clone(); + $popup.find(".header > span").html(desc.title); + $popup.find(".body > span").html(fmt_body_txt( + util.formatted_string_to_html(desc.body))); + $popup.find(".footer > span").html(fmt_body_txt( + util.formatted_string_to_html(desc.footer))); + // TODO: handle input here? currently handled from c++ side. + return $popup; + } + var ui_handlers = { "describe-generic" : describe_generic, "describe-feature-wide" : describe_feature_wide, @@ -875,6 +887,7 @@ function ($, comm, client, ui, enums, cr, util, scroller, main, gui, player) { "version" : version, "formatted-scroller" : formatted_scroller, "progress-bar" : progress_bar, + "seed-selection" : seed_selection, "msgwin-get-line" : msgwin_get_line, "newgame-choice": newgame_choice, "newgame-random-combo": newgame_random_combo, diff --git a/crawl-ref/source/webserver/game_data/templates/game.html b/crawl-ref/source/webserver/game_data/templates/game.html index e6e44d0e0b78..643f985be007 100644 --- a/crawl-ref/source/webserver/game_data/templates/game.html +++ b/crawl-ref/source/webserver/game_data/templates/game.html @@ -313,6 +313,13 @@
+
+
+
+
+ +
+
From 26507f1701a83c1f8c97595c9cc9b502f6eb48ab Mon Sep 17 00:00:00 2001 From: advil Date: Tue, 15 Oct 2019 16:13:36 -0400 Subject: [PATCH 852/864] Fix a js error in go_lobby Not sure what the conditions are that trigger this, but probably at least game_exit::abort. (cherry picked from commit 83157970ee14af0809710fbc454248e78c0a1020) --- crawl-ref/source/webserver/static/scripts/client.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/webserver/static/scripts/client.js b/crawl-ref/source/webserver/static/scripts/client.js index 216377498351..6f02b909a0b0 100644 --- a/crawl-ref/source/webserver/static/scripts/client.js +++ b/crawl-ref/source/webserver/static/scripts/client.js @@ -871,7 +871,7 @@ function (exports, $, key_conversion, chat, comm) { if (exit_reason) { if (was_watching || normal_exit.indexOf(exit_reason) === -1 - || exit_message.length > 0) + || exit_message && exit_message.length > 0) { show_exit_dialog(exit_reason, exit_message, exit_dump, was_watching ? watching_username : null); From 36a118239d080c8c9b46b20b94410a13c48da30a Mon Sep 17 00:00:00 2001 From: theJollySin Date: Sat, 12 Oct 2019 13:12:59 -0400 Subject: [PATCH 853/864] Misleading text when renouncing religion (8887) (cherry picked from commit b8d28a4aeb7e5db94f6def81c8bd3195f8fdf48f) --- crawl-ref/source/ability.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crawl-ref/source/ability.cc b/crawl-ref/source/ability.cc index 3f4f07b64811..bc83fe7f4668 100644 --- a/crawl-ref/source/ability.cc +++ b/crawl-ref/source/ability.cc @@ -3227,8 +3227,7 @@ static spret _do_ability(const ability_def& abil, bool fail) fail_check(); if (yesno("Really renounce your faith, foregoing its fabulous benefits?", false, 'n') - && yesno("Are you sure you won't change your mind later?", - false, 'n')) + && yesno("Are you sure?", false, 'n')) { excommunication(true); } From 37ad8b309f5d1d69b442bd41b57d4ef4772dbc42 Mon Sep 17 00:00:00 2001 From: Edgar Bering Date: Tue, 15 Oct 2019 07:47:17 -0400 Subject: [PATCH 854/864] Update CREDITS (cherry picked from commit 1381ef2bc469f9e2cb49825ccadf2d71ee4e4752) --- crawl-ref/CREDITS.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crawl-ref/CREDITS.txt b/crawl-ref/CREDITS.txt index c80b1330dfa6..d09461c02c97 100644 --- a/crawl-ref/CREDITS.txt +++ b/crawl-ref/CREDITS.txt @@ -120,11 +120,13 @@ Thom Chiovoloni Anthony Chuah Henry Cipolla + CollinJ Nicholas Connelly Tom Conrad Vitor 'Baconkid' Costa Aaron Curtis Simon Curtis + cut1less Paul Dejean Denzi Lothar Dierkes @@ -141,6 +143,7 @@ Micha Elsner Carl-Oscar Erneholm Erich Erstu + Higor Eurípedes Christopher Evenstar Floodkiller floraline @@ -268,6 +271,7 @@ Terence Reeves Tobias Rehbein Remsleep + Chris Rendle-Short Ryan Riegel RjY rmcneive @@ -303,6 +307,7 @@ Jan 'heftig' Steffens Stenella Timothy Stiles + John Stilley Johan Strandell Ben Striegel Derrick Sund @@ -315,8 +320,10 @@ Jared 'Twinge' Tinney Matt Titus Tommy + Sean VanMeter Mikko Vepsäläinen WanderingBlade + Richard Wardin waylon531 Steven Wheeler Thomas Willem From 99aa94c1fb0be6356019d0c894b79f0a13efe991 Mon Sep 17 00:00:00 2001 From: Edgar Bering Date: Wed, 23 Oct 2019 12:13:51 -0400 Subject: [PATCH 855/864] Correct a changelog entry (pblur) (cherry picked from commit 2ac932518a46594d06ed119aae98ff47c74098be) --- crawl-ref/docs/changelog.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crawl-ref/docs/changelog.txt b/crawl-ref/docs/changelog.txt index 26c6448cdca4..6e2f942831f3 100644 --- a/crawl-ref/docs/changelog.txt +++ b/crawl-ref/docs/changelog.txt @@ -1,4 +1,4 @@ -Stone Soup 0.24 (up to 6c54e258) +Stone Soup 0.24 (up to 6afad29e) -------------------------------- Highlights @@ -115,8 +115,8 @@ Items - Tomahawks are renamed to boomerangs and always return. - Javelins always penetrate. - Steel and silver are merged into a single brand, called silver. Silver - ammunition applies 30% bonus damage to most targets and the old silver - damage bonus to silver-vulnerable targets. + ammunition applies the maximum of vorpal bonus damage and the old silver + damage bonus. - Poison, returning, penetration, and exploding are no longer available brands for tomahawks and javelins. From c52801cf77f3ffa9618117ae3cb664749a57013e Mon Sep 17 00:00:00 2001 From: kitchen-ace <68k@quikphix.org> Date: Tue, 22 Oct 2019 00:01:22 -0400 Subject: [PATCH 856/864] Warn when exploding portal projectiles would hit you 853fe2e fixed this for harming allies, but not yourself. (cherry picked from commit 6843c08e714173f9cc215aee4a832d76f6ef7933) --- crawl-ref/source/throw.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crawl-ref/source/throw.cc b/crawl-ref/source/throw.cc index 1575aa00e5b4..33f1464aec8e 100644 --- a/crawl-ref/source/throw.cc +++ b/crawl-ref/source/throw.cc @@ -854,6 +854,11 @@ bool throw_it(bolt &pbolt, int throw_2, dist *target) monster *am = monster_at(*ai); if (am) cancelled = stop_attack_prompt(am, false, *ai); + else if (*ai == you.pos()) + { + cancelled = !yesno("That is likely to hit you. Continue anyway?", + false, 'n'); + } } } } From 47cfe1e8adccd0e1aa1f10f0bded140ce19cee38 Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 23 Oct 2019 12:42:24 -0400 Subject: [PATCH 857/864] Changelog tweaks (cherry picked from commit 75acf02343f500996e401993075d31bdbd10e182) --- crawl-ref/docs/changelog.txt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/crawl-ref/docs/changelog.txt b/crawl-ref/docs/changelog.txt index 6e2f942831f3..7a302f2b6f61 100644 --- a/crawl-ref/docs/changelog.txt +++ b/crawl-ref/docs/changelog.txt @@ -12,11 +12,13 @@ Branches, Environment --------------------- * Incremental pregeneration: - This mode generates the dungeon in a stable order for all games regardless - of the path taken by the player. + of the path taken by the player, meaning that the behavior of seeds for + online and offline games should now be the same. - Games using the same seed will see the same dungeon if they are incrementally pregenerated without requiring the long initial generation - time of a fully pregenerated game. + time of full pregeneration as introduced in 0.23. - Incremental pregeneration is the default mode for new games. + - Servers can now enable seed selection without heavy CPU cost. * A Trove map requiring many uses of digging has been removed. * Identification scrolls are no longer used as a potential Trove cost. * Transporters in vaults now correctly place in the Abyss. @@ -105,7 +107,7 @@ Items - Piercer has been removed, its effect having been merged into Storm Bow. * Weapons with the holy wrath ego can now be cursed. * Randart rings no longer generate with both rCorr and *Corrode. -* Throwing weapons have been simplified. +* Throwing weapons have been streamlined. - Blowguns are removed, needles are replaced with throwing darts. - Dart effects scale with Throwing and Stealth skill. - Darts of sleep, paralysis, confusion are removed. @@ -126,7 +128,7 @@ Lua monster.info class. * A new function 'defeat_mr()' to determine the chance that a given spell defeats a monster's magic resistance. -* There is a basic seed explorer available in tests/seed_explorer.lua. +* There is a basic seed explorer available in scripts/seed_explorer.lua. Monsters -------- From d9db55ccdc26ce3f17f098005b1c91c2d3fe972d Mon Sep 17 00:00:00 2001 From: gammafunk Date: Wed, 23 Oct 2019 14:30:45 -0500 Subject: [PATCH 858/864] Rework a wizard vault The vault cheibrodos_wizard_tower placed on-average 3 8-tier monsters at Lair depth, which is fairly nasty. This commit reworks the monster and loot placement to better scale with depth, starting with 1.25 monsters at D:7-9. The monster set now includes a possible deep elf annihilator in Dungeon, but only at depths where those are possible 8 spawns, and with a small chance. The monster count in Elf has been increased as well. The vault range is now increased to include D:13-D:$. The loot now has some thematic aux armor, randbooks, and staves mixed in, and the loot scales in count with depth. (cherry picked from commit f0389da217a573edd2dca0ad9c2a8216062f8849) --- crawl-ref/source/dat/des/variable/float.des | 26 ++++++++++++++------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/crawl-ref/source/dat/des/variable/float.des b/crawl-ref/source/dat/des/variable/float.des index d728e10ad11a..e1a101a7bb30 100644 --- a/crawl-ref/source/dat/des/variable/float.des +++ b/crawl-ref/source/dat/des/variable/float.des @@ -3922,18 +3922,28 @@ xx...xx xxxxxx .@. ENDMAP -NAME: cheibrodos_wizards_tower -TAGS: no_item_gen no_monster_gen no_pool_fixup -DEPTH: D:7-12, Elf +NAME: cheibrodos_wizards_tower +TAGS: no_pool_fixup +DEPTH: D:7-, Elf ORIENT: float -: if you.branch() == "Elf" then -MONS: deep elf sorcerer / deep elf annihilator +ITEM: robe good_item / cloak good_item / scarf / pair of boots good_item \ + / pair of gloves good_item / hat good_item +ITEM: randbook w:40 / any magical staff +: if you.in_branch("D") then +MONS: wizard / orc sorcerer, deep elf annihilator +: if you.depth() < 10 then +NSUBST: " = 1 / 1... / ., - = d / *% / %$.. / . +: elseif you.depth() < 13 then +NSUBST: " = 1 / 1. / 2... / ., - = de / |* / %$ / . +: else +NSUBST: " = 1 / 2=1. / 2. / ., - = d / e / |* / %$ / . +: end : else -MONS: wizard / orc sorcerer +MONS: deep elf sorcerer / deep elf annihilator +NSUBST: " = 2=1 / 4=1. / ., - = d / e / 2=|* / *% / %$.. / . : end SHUFFLE: AB / CD / EF -SUBST: A = ., B = W, CDEF = w -NSUBST: " = 2:1 / 2=1., - = 1=*| / 2=*% / 2=%. +SUBST: A = ., B = W, CDEF = w MAP ....@.... ..wwFEFww.. From 86bb9569af751ca7bd0d0cc124d444ef683ed21d Mon Sep 17 00:00:00 2001 From: advil Date: Wed, 23 Oct 2019 20:39:07 -0400 Subject: [PATCH 859/864] Fix mummy death curses from ally kills (12104) This has been broken for a while; it was a mid/mindex confusion. I've also refactored the call so that it will better handle the case where your summon does before the fineff fires. (cherry picked from commit c4661985658596db158e4003f4cb197ee34c891d) --- crawl-ref/source/fineff.cc | 18 +++++++++++------- crawl-ref/source/fineff.h | 5 ++++- crawl-ref/source/mon-death.cc | 5 ++++- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/crawl-ref/source/fineff.cc b/crawl-ref/source/fineff.cc index dacccc8c996e..61010c7e8695 100644 --- a/crawl-ref/source/fineff.cc +++ b/crawl-ref/source/fineff.cc @@ -581,6 +581,17 @@ void make_derived_undead_fineff::fire() } } +const actor *mummy_death_curse_fineff::fixup_attacker(const actor *att) +{ + if (att && att->is_monster() && att->as_monster()->friendly() + && !crawl_state.game_is_arena()) + { + // Mummies are smart enough not to waste curses on summons or allies. + return &you; + } + return att; +} + void mummy_death_curse_fineff::fire() { if (pow <= 0) @@ -615,13 +626,6 @@ void mummy_death_curse_fineff::fire() if (!victim->alive()) return; - // Mummies are smart enough not to waste curses on summons or allies. - if (victim->is_monster() && victim->as_monster()->friendly() - && !crawl_state.game_is_arena()) - { - victim = &you; - } - // Stepped from time? if (!in_bounds(victim->pos())) return; diff --git a/crawl-ref/source/fineff.h b/crawl-ref/source/fineff.h index e369124b5cac..aadb56930726 100644 --- a/crawl-ref/source/fineff.h +++ b/crawl-ref/source/fineff.h @@ -374,9 +374,12 @@ class mummy_death_curse_fineff : public final_effect } protected: mummy_death_curse_fineff(const actor * attack, string _name, killer_type _killer, int _pow) - : final_effect(attack, 0, coord_def()), name(_name), killer(_killer), pow(_pow) + : final_effect(fixup_attacker(attack), 0, coord_def()), name(_name), + killer(_killer), pow(_pow) { } + const actor *fixup_attacker(const actor *att); + string name; killer_type killer; int pow; diff --git a/crawl-ref/source/mon-death.cc b/crawl-ref/source/mon-death.cc index 5d496517eb6f..8d6a0e7004a1 100644 --- a/crawl-ref/source/mon-death.cc +++ b/crawl-ref/source/mon-death.cc @@ -2475,8 +2475,11 @@ item_def* monster_die(monster& mons, killer_type killer, } else if (!mons.is_summoned() && mummy_curse_power(mons.type) > 0) { + // TODO: set attacker better? (Player attacker is handled by checking + // killer when running the fineff.) mummy_death_curse_fineff::schedule( - actor_by_mid(killer_index), + invalid_monster_index(killer_index) + ? nullptr : &menv[killer_index], mons.name(DESC_A), killer, mummy_curse_power(mons.type)); From 03419ebf5fb5abc05c986cca6e9b2b0819a0619f Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 24 Oct 2019 09:13:43 -0400 Subject: [PATCH 860/864] Add vaults to stable version morgues We'll see if players think this is too spammy or too obscure, but for 0.24.0 at least this will be helpful for testing any seed issues that come up. (cherry picked from commit 9c56bcba7025d672565a42afd8ec1305c020d4be) --- crawl-ref/source/initfile.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index 3bb7b92ba922..6d77d2451f28 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -1156,10 +1156,8 @@ void game_options::reset_options() dump_order.clear(); new_dump_fields("header,hiscore,stats,misc,inventory," "skills,spells,overview,mutations,messages," - "screenshot,monlist,kills,notes"); - if (Version::ReleaseType == VER_ALPHA) - new_dump_fields("vaults"); - new_dump_fields("skill_gains,action_counts"); + "screenshot,monlist,kills,notes,vaults", + "skill_gains,action_counts"); // Currently enabled by default for testing in trunk. if (Version::ReleaseType == VER_ALPHA) new_dump_fields("xp_by_level"); From 33656463dde0461357e81c244bf042889c3098fc Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 24 Oct 2019 10:59:31 -0400 Subject: [PATCH 861/864] Fix a gcc warning (cherry picked from commit 72b0ba0336dcb0a97e399f4966f57fcf973b2a24) --- crawl-ref/source/fineff.cc | 6 +++--- crawl-ref/source/fineff.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crawl-ref/source/fineff.cc b/crawl-ref/source/fineff.cc index 61010c7e8695..64700be62546 100644 --- a/crawl-ref/source/fineff.cc +++ b/crawl-ref/source/fineff.cc @@ -581,15 +581,15 @@ void make_derived_undead_fineff::fire() } } -const actor *mummy_death_curse_fineff::fixup_attacker(const actor *att) +const actor *mummy_death_curse_fineff::fixup_attacker(const actor *a) { - if (att && att->is_monster() && att->as_monster()->friendly() + if (a && a->is_monster() && a->as_monster()->friendly() && !crawl_state.game_is_arena()) { // Mummies are smart enough not to waste curses on summons or allies. return &you; } - return att; + return a; } void mummy_death_curse_fineff::fire() diff --git a/crawl-ref/source/fineff.h b/crawl-ref/source/fineff.h index aadb56930726..6dd9a935247f 100644 --- a/crawl-ref/source/fineff.h +++ b/crawl-ref/source/fineff.h @@ -378,7 +378,7 @@ class mummy_death_curse_fineff : public final_effect killer(_killer), pow(_pow) { } - const actor *fixup_attacker(const actor *att); + const actor *fixup_attacker(const actor *a); string name; killer_type killer; From 54606e7572d31cb9608e76dcbdf8097f60c0c247 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 24 Oct 2019 14:13:48 -0400 Subject: [PATCH 862/864] Finalize changelog for 0.24 release --- crawl-ref/docs/changelog.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/docs/changelog.txt b/crawl-ref/docs/changelog.txt index 7a302f2b6f61..e07338fa38a1 100644 --- a/crawl-ref/docs/changelog.txt +++ b/crawl-ref/docs/changelog.txt @@ -1,4 +1,4 @@ -Stone Soup 0.24 (up to 6afad29e) +Stone Soup 0.24 (20191024) -------------------------------- Highlights From a7d21def0a8b0b39c6825b643a3b51f371b73583 Mon Sep 17 00:00:00 2001 From: advil Date: Thu, 24 Oct 2019 14:16:48 -0400 Subject: [PATCH 863/864] Update debian changelog for release --- crawl-ref/source/debian/changelog | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crawl-ref/source/debian/changelog b/crawl-ref/source/debian/changelog index 5bccdd76022b..73b0327a75b3 100644 --- a/crawl-ref/source/debian/changelog +++ b/crawl-ref/source/debian/changelog @@ -1,3 +1,8 @@ +crawl (2:0.24.0-1) UNRELEASED; urgency=low + + * New upstream release. + -- gammafunk Thu, 24 Oct 2019 14:16:07 -0400 + crawl (2:0.23.2-1) UNRELEASED; urgency=low * New upstream release. From 000bc813e3b2b028b65dae395104424073aa982d Mon Sep 17 00:00:00 2001 From: Vladislav Kovun Date: Thu, 31 Oct 2019 18:07:02 +0300 Subject: [PATCH 864/864] Adds a missing file which mysteriously disappeared from this after build. --- crawl-ref/source/Android.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/crawl-ref/source/Android.mk b/crawl-ref/source/Android.mk index 51a87461e89c..2da426698935 100644 --- a/crawl-ref/source/Android.mk +++ b/crawl-ref/source/Android.mk @@ -257,6 +257,7 @@ CRAWLSRC = ability.cc \ notes.cc \ orb.cc \ ouch.cc \ + outer-menu.cc \ output.cc \ package.cc \ pattern.cc \