diff options
-rw-r--r-- | crawl-ref/source/AppHdr.h | 4 | ||||
-rw-r--r-- | crawl-ref/source/acr.cc | 9 | ||||
-rw-r--r-- | crawl-ref/source/chardump.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/command.cc | 6 | ||||
-rw-r--r-- | crawl-ref/source/delay.cc | 7 | ||||
-rw-r--r-- | crawl-ref/source/direct.cc | 9 | ||||
-rw-r--r-- | crawl-ref/source/enum.h | 10 | ||||
-rw-r--r-- | crawl-ref/source/externs.h | 7 | ||||
-rw-r--r-- | crawl-ref/source/files.cc | 5 | ||||
-rw-r--r-- | crawl-ref/source/initfile.cc | 98 | ||||
-rw-r--r-- | crawl-ref/source/items.cc | 68 | ||||
-rw-r--r-- | crawl-ref/source/items.h | 3 | ||||
-rw-r--r-- | crawl-ref/source/shopping.cc | 9 | ||||
-rw-r--r-- | crawl-ref/source/stash.cc | 71 | ||||
-rw-r--r-- | crawl-ref/source/stash.h | 18 | ||||
-rw-r--r-- | crawl-ref/source/stuff.cc | 6 | ||||
-rw-r--r-- | crawl-ref/source/stuff.h | 2 | ||||
-rw-r--r-- | crawl-ref/source/travel.cc | 142 | ||||
-rw-r--r-- | crawl-ref/source/travel.h | 20 | ||||
-rw-r--r-- | crawl-ref/source/view.cc | 2 |
20 files changed, 334 insertions, 164 deletions
diff --git a/crawl-ref/source/AppHdr.h b/crawl-ref/source/AppHdr.h index 0a0efdd9e8..27594ac3a2 100644 --- a/crawl-ref/source/AppHdr.h +++ b/crawl-ref/source/AppHdr.h @@ -52,10 +52,6 @@ # define HASH_CONTAINERS #endif -// Enables stash-tracking: keeps track of items in the dungeon as a convenience -// for the player. -#define STASH_TRACKING - // Uncomment to enable the Crawl Lua bindings. // // #define CLUA_BINDINGS diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc index 9adaefda6a..c52a0724a2 100644 --- a/crawl-ref/source/acr.cc +++ b/crawl-ref/source/acr.cc @@ -1061,13 +1061,10 @@ void process_command( command_type cmd ) { case CMD_DROP: drop(); -#ifdef STASH_TRACKING if (Options.stash_tracking >= STM_DROPPED) stashes.add_stash(); -#endif break; -#ifdef STASH_TRACKING case CMD_SEARCH_STASHES: stashes.search_stashes(); break; @@ -1081,7 +1078,6 @@ void process_command( command_type cmd ) { if (Options.stash_tracking >= STM_EXPLICIT) stashes.no_stash(); break; -#endif case CMD_BUTCHER: butchery(); @@ -1239,13 +1235,14 @@ void process_command( command_type cmd ) { break; case CMD_EXPLORE: + case CMD_EXPLORE_GREEDY: if (you.level_type == LEVEL_LABYRINTH || you.level_type == LEVEL_ABYSS) { mpr("It would help if you knew where you were, first."); break; } // Start exploring - start_explore(); + start_explore(cmd == CMD_EXPLORE_GREEDY); break; case CMD_DISPLAY_MAP: @@ -2407,7 +2404,7 @@ command_type keycode_to_command( keycode_type key ) { case CONTROL('E'): return CMD_FORGET_STASH; case CONTROL('F'): return CMD_SEARCH_STASHES; case CONTROL('G'): return CMD_INTERLEVEL_TRAVEL; - case CONTROL('I'): return CMD_NO_CMD; + case CONTROL('I'): return CMD_EXPLORE_GREEDY; case CONTROL('M'): return CMD_NO_CMD; case CONTROL('O'): return CMD_EXPLORE; case CONTROL('P'): return CMD_REPLAY_MESSAGES; diff --git a/crawl-ref/source/chardump.cc b/crawl-ref/source/chardump.cc index e5d65e183a..0c3b343e66 100644 --- a/crawl-ref/source/chardump.cc +++ b/crawl-ref/source/chardump.cc @@ -987,12 +987,10 @@ static bool write_dump( file_name += fname; -#ifdef STASH_TRACKING std::string stash_file_name; stash_file_name = file_name; stash_file_name += ".lst"; stashes.dump(stash_file_name.c_str(), full_id); -#endif file_name += ".txt"; FILE *handle = fopen(file_name.c_str(), "w"); diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc index baf543036b..0e62d4c811 100644 --- a/crawl-ref/source/command.cc +++ b/crawl-ref/source/command.cc @@ -53,9 +53,7 @@ void quit_game(void) static const char *features[] = { "", -#ifdef STASH_TRACKING "Stash-tracking", -#endif #ifdef CLUA_BINDINGS "Lua", @@ -586,10 +584,8 @@ static int cmdhelp_keyfilter(int keyin) static bool cmdhelp_textfilter(const std::string &tag) { -#ifdef STASH_TRACKING if (tag == "s") return (true); -#endif #ifdef WIZARD if (tag == "wiz") return (true); @@ -1096,11 +1092,9 @@ static const char *command_string( int i ) (i == 453) ? "Ctrl-G : interlevel travel" : (i == 455) ? "Ctrl-O : explore" : -#ifdef STASH_TRACKING (i == 456) ? "Ctrl-S : mark stash" : (i == 457) ? "Ctrl-E : forget stash" : (i == 458) ? "Ctrl-F : search stashes" : -#endif (i == 460) ? "Shift & DIR : long walk" : (i == 465) ? "/ DIR : long walk" : diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc index e473eb685f..204d10f488 100644 --- a/crawl-ref/source/delay.cc +++ b/crawl-ref/source/delay.cc @@ -359,6 +359,13 @@ void handle_delay( void ) switch (delay.type) { case DELAY_AUTOPICKUP: + // Ask the player if they want to stop explore to examine + // the loot, but only if we picked up at least one item + // that the character did not throw. + int estop = (you.running == RMODE_EXPLORE_GREEDY + && delay.parm1)? ES_GREEDY_PICKUP : ES_PICKUP; + if ((Options.explore_stop & estop) && prompt_stop_explore(estop)) + stop_delay(); break; case DELAY_WEAPON_SWAP: diff --git a/crawl-ref/source/direct.cc b/crawl-ref/source/direct.cc index b35f3b3b6d..acbbc1ca0d 100644 --- a/crawl-ref/source/direct.cc +++ b/crawl-ref/source/direct.cc @@ -370,9 +370,7 @@ static void describe_oos_square(int x, int y) if (!in_bounds(x, y) || !is_mapped(x, y)) return; -#ifdef STASH_TRACKING describe_stash(x, y); -#endif describe_feature(x, y, true); } @@ -788,11 +786,8 @@ static bool find_object(int x, int y, int mode) const int item = igrd[x][y]; // The square need not be in LOS if the stash tracker knows this item. return (item != NON_ITEM - && (in_los(x, y) -#ifdef STASH_TRACKING - || (Options.target_oos && is_mapped(x, y) && is_stash(x, y)) -#endif - )); + && (in_los(x, y) + || (Options.target_oos && is_mapped(x, y) && is_stash(x, y)))); } static int next_los(int dir, int los, bool wrap) diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h index fa119020c3..c9cc1f821a 100644 --- a/crawl-ref/source/enum.h +++ b/crawl-ref/source/enum.h @@ -636,6 +636,7 @@ enum command_type CMD_FORGET_STASH, CMD_SEARCH_STASHES, CMD_EXPLORE, + CMD_EXPLORE_GREEDY, CMD_INTERLEVEL_TRAVEL, CMD_FIX_WAYPOINT, @@ -2854,10 +2855,11 @@ enum run_dir_type enum run_mode_type { - RMODE_INTERLEVEL = -3, // Interlevel travel (Ctrl+G) - RMODE_EXPLORE = -2, // Exploring (Ctrl+O) - RMODE_TRAVEL = -1, // Classic or Plain Old travel - RMODE_NOT_RUNNING = 0, // must remain equal to 0 + RMODE_INTERLEVEL = -4, // Interlevel travel (Ctrl+G) + RMODE_EXPLORE_GREEDY = -3, // Explore + grab items (Tab/Ctrl+I) + RMODE_EXPLORE = -2, // Exploring (Ctrl+O) + RMODE_TRAVEL = -1, // Classic or Plain Old travel + RMODE_NOT_RUNNING = 0, // must remain equal to 0 RMODE_CONTINUE, RMODE_START, RMODE_REST_DURATION = 100 diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h index a1cb6da756..01806f710d 100644 --- a/crawl-ref/source/externs.h +++ b/crawl-ref/source/externs.h @@ -309,6 +309,8 @@ public: // Returns true if we're currently resting. bool is_rest() const; + bool is_explore() const; + // Clears run state. void clear(); @@ -845,6 +847,8 @@ public: int explore_stop; // Stop exploring if a previously unseen // item comes into view + int explore_stop_prompt; + std::vector<sound_mapping> sound_mappings; std::vector<colour_mapping> menu_colour_mappings; @@ -942,8 +946,9 @@ private: void set_activity_interrupt(const std::string &activity_name, const std::string &interrupt_names, bool append_interrupts); - void add_dump_fields(const std::string &text); + void new_dump_fields(const std::string &text, bool add = true); void do_kill_map(const std::string &from, const std::string &to); + int read_explore_stop_conditions(const std::string &) const; static const std::string interrupt_prefix; }; diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 037f35f185..a042cbdf48 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1162,8 +1162,6 @@ void save_level(int level_saved, bool was_a_labyrinth, char where_were_you) void save_game(bool leave_game) { - -#ifdef STASH_TRACKING /* Stashes */ std::string stashFile = get_savedir_filename( you.your_name, "", "st" ); FILE *stashf = fopen(stashFile.c_str(), "wb"); @@ -1172,7 +1170,6 @@ void save_game(bool leave_game) fclose(stashf); DO_CHMOD_PRIVATE(stashFile.c_str()); } -#endif #ifdef CLUA_BINDINGS /* lua */ @@ -1383,14 +1380,12 @@ void restore_game(void) fclose(charf); -#ifdef STASH_TRACKING std::string stashFile = get_savedir_filename( you.your_name, "", "st" ); FILE *stashf = fopen(stashFile.c_str(), "rb"); if (stashf) { stashes.load(stashf); fclose(stashf); } -#endif #ifdef CLUA_BINDINGS std::string luaFile = get_savedir_filename( you.your_name, "", "lua" ); diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index 046955401c..19fbf8cae9 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -381,10 +381,26 @@ static unsigned curses_attribute(const std::string &field) return CHATTR_NORMAL; } -void game_options::add_dump_fields(const std::string &text) +void game_options::new_dump_fields(const std::string &text, bool add) { // Easy; chardump.cc has most of the intelligence. - append_vector(dump_order, split_string(",", text, true, true)); + std::vector<std::string> fields = split_string(",", text, true, true); + if (add) + append_vector(dump_order, fields); + else + { + for (int f = 0, size = fields.size(); f < size; ++f) + { + for (int i = 0, dsize = dump_order.size(); i < dsize; ++i) + { + if (dump_order[i] == fields[f]) + { + dump_order.erase( dump_order.begin() + i ); + break; + } + } + } + } } void game_options::reset_startup_options() @@ -605,10 +621,14 @@ void game_options::reset_options() // 10 was the cursor step default on Linux. level_map_cursor_step = 7; -#ifdef STASH_TRACKING stash_tracking = STM_ALL; -#endif + explore_stop = ES_ITEM | ES_STAIR | ES_SHOP | ES_ALTAR; + + // The prompt conditions will be combined into explore_stop after + // reading options. + explore_stop_prompt = ES_GREEDY_PICKUP; + safe_zero_exp = true; target_zero_exp = false; target_wrap = true; @@ -679,7 +699,7 @@ void game_options::reset_options() // Clear vector options. dump_order.clear(); - add_dump_fields("header,stats,misc,inventory,skills," + new_dump_fields("header,stats,misc,inventory,skills," "spells,,mutations,messages,screenshot,kills,notes"); banned_objects.clear(); @@ -1108,6 +1128,8 @@ void game_options::read_options(InitLineInput &il, bool runscript) } #endif + Options.explore_stop |= Options.explore_stop_prompt; + // Validate save_dir check_savedir(save_dir); } @@ -1135,6 +1157,29 @@ void game_options::do_kill_map(const std::string &from, const std::string &to) kill_map[ifrom] = ito; } +int game_options::read_explore_stop_conditions(const std::string &field) const +{ + int conditions = 0; + std::vector<std::string> stops = split_string(",", field); + for (int i = 0, count = stops.size(); i < count; ++i) + { + const std::string &c = stops[i]; + if (c == "item" || c == "items") + conditions |= ES_ITEM; + else if (c == "pickup") + conditions |= ES_PICKUP; + else if (c == "greedy_pickup" || c == "greedy pickup") + conditions |= ES_GREEDY_PICKUP; + else if (c == "shop" || c == "shops") + conditions |= ES_SHOP; + else if (c == "stair" || c == "stairs") + conditions |= ES_STAIR; + else if (c == "altar" || c == "altars") + conditions |= ES_ALTAR; + } + return (conditions); +} + void game_options::read_option_line(const std::string &str, bool runscript) { std::string key = ""; @@ -1145,6 +1190,7 @@ void game_options::read_option_line(const std::string &str, bool runscript) int first_dot = str.find('.'); bool plus_equal = false; + bool minus_equal = false; // all lines with no equal-signs we ignore if (first_equals < 0) @@ -1174,6 +1220,12 @@ void game_options::read_option_line(const std::string &str, bool runscript) key = key.substr(0, key.length() - 1); trim_string(key); } + else if (key.length() && key[key.length() - 1] == '-') + { + minus_equal = true; + key = key.substr(0, key.length() - 1); + trim_string(key); + } tolower_string( trim_string( subkey ) ); @@ -1872,22 +1924,25 @@ void game_options::read_option_line(const std::string &str, bool runscript) } else if (key == "explore_stop") { - explore_stop = ES_NONE; - std::vector<std::string> stops = split_string(",", field); - for (int i = 0, count = stops.size(); i < count; ++i) - { - const std::string &c = stops[i]; - if (c == "item" || c == "items") - explore_stop |= ES_ITEM; - else if (c == "shop" || c == "shops") - explore_stop |= ES_SHOP; - else if (c == "stair" || c == "stairs") - explore_stop |= ES_STAIR; - else if (c == "altar" || c == "altars") - explore_stop |= ES_ALTAR; - } + if (!plus_equal && !minus_equal) + explore_stop = ES_NONE; + + const int new_conditions = read_explore_stop_conditions(field); + if (minus_equal) + explore_stop &= ~new_conditions; + else + explore_stop |= new_conditions; + } + else if (key == "explore_stop_prompt") + { + if (!plus_equal && !minus_equal) + explore_stop_prompt = ES_NONE; + const int new_conditions = read_explore_stop_conditions(field); + if (minus_equal) + explore_stop_prompt &= ~new_conditions; + else + explore_stop_prompt |= new_conditions; } -#ifdef STASH_TRACKING else if (key == "stash_tracking") { stash_tracking = @@ -1901,7 +1956,6 @@ void game_options::read_option_line(const std::string &str, bool runscript) for (int i = 0, count = seg.size(); i < count; ++i) Stash::filter( seg[i] ); } -#endif else if (key == "sound") { std::vector<std::string> seg = split_string(",", field); @@ -1936,7 +1990,7 @@ void game_options::read_option_line(const std::string &str, bool runscript) if (!plus_equal) dump_order.clear(); - add_dump_fields(field); + new_dump_fields(field, !minus_equal); } else if (key == "dump_kill_places") { diff --git a/crawl-ref/source/items.cc b/crawl-ref/source/items.cc index e0313a6ff6..c040288570 100644 --- a/crawl-ref/source/items.cc +++ b/crawl-ref/source/items.cc @@ -2882,47 +2882,63 @@ static void autoinscribe_items() autoinscribe_item( mitm[o] ); o = next; } -} +} -static void autopickup(void) +bool item_needs_autopickup(const item_def &item) { - //David Loewenstern 6/99 - int result, o, next; - bool did_pickup = false; - - if (!Options.autopickup_on || Options.autopickups == 0L) - return; + return (strstr(item.inscription.c_str(), "=g") != 0 + || ((item.flags & ISFLAG_THROWN) && Options.pickup_thrown) + || (((Options.autopickups & (1L << item.base_type)) +#ifdef CLUA_BINDINGS + || clua.callbooleanfn(false, "ch_autopickup", "u", &item) +#endif + ) + && (Options.pickup_dropped || !(item.flags & ISFLAG_DROPPED)) + && !is_banned(item))); +} + +bool can_autopickup() +{ + // [ds] Checking for autopickups == 0 is a bad idea because + // autopickup is still possible with inscriptions and + // pickup_thrown. + if (!Options.autopickup_on) + return (false); if (you.attribute[ATTR_TRANSFORMATION] == TRAN_AIR - && you.duration[DUR_TRANSFORMATION] > 0) - { - return; - } + && you.duration[DUR_TRANSFORMATION] > 0) + return (false); if (player_is_levitating() && !wearing_amulet(AMU_CONTROLLED_FLIGHT)) - return; + return (false); if ( Options.safe_autopickup && !i_feel_safe() ) - return; + return (false); + return (true); +} + +static void autopickup(void) +{ + //David Loewenstern 6/99 + int result, o, next; + bool did_pickup = false; + + if (!can_autopickup()) + return; + o = igrd[you.x_pos][you.y_pos]; + int unthrown = 0; while (o != NON_ITEM) { next = mitm[o].link; - if ( - (strstr(mitm[o].inscription.c_str(), "=g") != 0) || ( - - ((mitm[o].flags & ISFLAG_THROWN) && Options.pickup_thrown) || - ( (Options.autopickups & (1L << mitm[o].base_type) -#ifdef CLUA_BINDINGS - || clua.callbooleanfn(false, "ch_autopickup", "u", &mitm[o]) -#endif - ) - && (Options.pickup_dropped || !(mitm[o].flags & ISFLAG_DROPPED)) - && !is_banned(mitm[o])))) + if (item_needs_autopickup(mitm[o])) { + if (!(mitm[o].flags & ISFLAG_THROWN)) + unthrown++; + mitm[o].flags &= ~(ISFLAG_THROWN | ISFLAG_DROPPED); result = move_item_to_player( o, mitm[o].quantity); @@ -2950,7 +2966,7 @@ static void autopickup(void) if (did_pickup) { you.turn_is_over = true; - start_delay( DELAY_AUTOPICKUP, 1 ); + start_delay( DELAY_AUTOPICKUP, 1, unthrown ); } } diff --git a/crawl-ref/source/items.h b/crawl-ref/source/items.h index 53a779c2b9..f905e024a5 100644 --- a/crawl-ref/source/items.h +++ b/crawl-ref/source/items.h @@ -139,4 +139,7 @@ void origin_set_startequip(item_def &item); void origin_set_unknown(item_def &item); void origin_set_inventory( void (*oset)(item_def &item) ); +bool item_needs_autopickup(const item_def &); +bool can_autopickup(); + #endif diff --git a/crawl-ref/source/shopping.cc b/crawl-ref/source/shopping.cc index 6f80839df1..0a8ae39a88 100644 --- a/crawl-ref/source/shopping.cc +++ b/crawl-ref/source/shopping.cc @@ -137,9 +137,7 @@ char in_a_shop( char shoppy, id_arr id ) snprintf( info, INFO_SIZE, "Welcome to %s!", shop_name(env.shop[shoppy].x, env.shop[shoppy].y) ); -#ifdef STASH_TRACKING ShopInfo &si = stashes.get_shop(env.shop[shoppy].x, env.shop[shoppy].y); -#endif shop_print(info, 20); @@ -161,9 +159,8 @@ char in_a_shop( char shoppy, id_arr id ) clrscr(); itty = igrd[0][5 + shoppy]; -#ifdef STASH_TRACKING si.reset(); -#endif + if (itty == NON_ITEM) { shop_print("I'm sorry, my shop is empty now.", 20); @@ -216,12 +213,10 @@ char in_a_shop( char shoppy, id_arr id ) desc = munge_description(get_item_description(mitm[itty], Options.verbose_dump, true )); -# ifdef STASH_TRACKING si.add_item(mitm[itty], gp_value); -# endif gotoxy(60, i); - textcolor( can_afford ? LIGHTGREEN : LIGHTRED ); + textcolor( can_afford ? LIGHTGREEN : LIGHTRED ); snprintf(st_pass, sizeof(st_pass), "%5d", gp_value); cprintf("%s gold", st_pass); if (mitm[itty].link == NON_ITEM) diff --git a/crawl-ref/source/stash.cc b/crawl-ref/source/stash.cc index b1b027fb3a..02e7ec5125 100644 --- a/crawl-ref/source/stash.cc +++ b/crawl-ref/source/stash.cc @@ -31,8 +31,6 @@ #include <fstream> #include <algorithm> -#ifdef STASH_TRACKING - #define ST_MAJOR_VER ((unsigned char) 4) #define ST_MINOR_VER ((unsigned char) 4) @@ -163,14 +161,22 @@ Stash::Stash(int xp, int yp) : enabled(true), items() bool Stash::are_items_same(const item_def &a, const item_def &b) { - return a.base_type == b.base_type && - a.sub_type == b.sub_type && - a.plus == b.plus && - a.plus2 == b.plus2 && - a.special == b.special && - a.colour == b.colour && - a.flags == b.flags && - a.quantity == b.quantity; + const bool same = a.base_type == b.base_type + && a.sub_type == b.sub_type + && a.plus == b.plus + && a.plus2 == b.plus2 + && a.special == b.special + && a.colour == b.colour + && a.flags == b.flags + && a.quantity == b.quantity; + + // Account for rotting meat when comparing items. + return (same + || (a.base_type == b.base_type + && (a.base_type == OBJ_CORPSES + || (a.base_type == OBJ_FOOD && a.sub_type == FOOD_CHUNK + && b.sub_type == FOOD_CHUNK)) + && a.plus == b.plus)); } void Stash::filter(const std::string &str) @@ -216,6 +222,19 @@ bool Stash::is_filtered(const item_def &item) return false; } +bool Stash::unverified() const +{ + return (!verified); +} + +bool Stash::pickup_eligible() const +{ + for (int i = 0, size = items.size(); i < size; ++i) + if (item_needs_autopickup(items[i])) + return (true); + return (false); +} + void Stash::update() { int objl = igrd[x][y]; @@ -247,9 +266,10 @@ void Stash::update() } // There's something on this square. Take a squint at it. - item_def &item = mitm[objl]; + const item_def &item = mitm[objl]; - if (item.link == NON_ITEM) items.clear(); + if (item.link == NON_ITEM) + items.clear(); // We knew of nothing on this square, so we'll assume this is the // only item here, but mark it as unverified unless we can see nothing @@ -268,7 +288,7 @@ void Stash::update() if (is_filtered(item)) return; - item_def &first = items[0]; + const item_def &first = items[0]; // Compare these items if (!are_items_same(first, item)) { @@ -841,13 +861,19 @@ bool LevelStashes::isBelowPlayer() const Stash *LevelStashes::find_stash(int x, int y) { + return const_cast<Stash *>( + const_cast<const LevelStashes *>(this)->find_stash(x, y) ); +} + +const Stash *LevelStashes::find_stash(int x, int y) const +{ if (x == -1 || y == -1) { x = you.x_pos; y = you.y_pos; } const int abspos = (GXM * y) + x; - c_stashes::iterator st = stashes.find(abspos); + c_stashes::const_iterator st = stashes.find(abspos); return (st == stashes.end()? NULL : &st->second); } @@ -861,6 +887,21 @@ const ShopInfo *LevelStashes::find_shop(int x, int y) const return (NULL); } +bool LevelStashes::shop_needs_visit(int x, int y) const +{ + const ShopInfo *shop = find_shop(x, y); + return (shop && !shop->is_visited()); +} + +bool LevelStashes::needs_visit(int x, int y) const +{ + const Stash *s = find_stash(x, y); + if (s && (s->unverified() || s->pickup_eligible())) + return (true); + + return (shop_needs_visit(x, y)); +} + ShopInfo &LevelStashes::get_shop(int x, int y) { for (unsigned i = 0; i < shops.size(); ++i) @@ -1499,5 +1540,3 @@ void StashTracker::display_search_results( // Global StashTracker stashes; - -#endif diff --git a/crawl-ref/source/stash.h b/crawl-ref/source/stash.h index 727fb656e4..9727102067 100644 --- a/crawl-ref/source/stash.h +++ b/crawl-ref/source/stash.h @@ -10,8 +10,6 @@ #include "shopping.h" #include <string> -#ifdef STASH_TRACKING - #include <iostream> #include <map> #include <vector> @@ -48,6 +46,14 @@ public: bool show_menu(const std::string &place, bool can_travel) const; + // Returns true if this Stash contains items that are eligible for + // autopickup. + bool pickup_eligible() const; + + // Returns true if this Stash is unverified (a visit by the character will + // verify the stash). + bool unverified() const; + bool matches_search(const std::string &prefix, const base_pattern &search, stash_search_result &res) @@ -197,6 +203,7 @@ public: LevelStashes(); Stash *find_stash(int x = -1, int y = -1); + const Stash *find_stash(int x = -1, int y = -1) const; ShopInfo &get_shop(int x, int y); const ShopInfo *find_shop(int x, int y) const; @@ -207,6 +214,11 @@ public: // location if no parameters are supplied. bool update_stash(int x = -1, int y = -1); + // Returns true if the square at (x,y) contains potentially interesting + // swag that merits a personal visit (for EXPLORE_GREEDY). + bool needs_visit(int x, int y) const; + bool shop_needs_visit(int x, int y) const; + // Add stash at (x,y), or player's current location if no parameters are // supplied void add_stash(int x = -1, int y = -1); @@ -315,8 +327,6 @@ extern StashTracker stashes; bool is_stash(int x, int y); void describe_stash(int x, int y); -#endif // STASH_TRACKING - std::string userdef_annotate_item(const char *s, const item_def *item, bool exclusive = false); diff --git a/crawl-ref/source/stuff.cc b/crawl-ref/source/stuff.cc index 9e25382662..0f30d16dc2 100644 --- a/crawl-ref/source/stuff.cc +++ b/crawl-ref/source/stuff.cc @@ -698,11 +698,13 @@ void canned_msg(unsigned char which_message) // jmf: general helper (should be used all over in code) // -- idea borrowed from Nethack -bool yesno( const char *str, bool safe, int safeanswer, bool clear_after ) +bool yesno( const char *str, bool safe, int safeanswer, bool clear_after, + bool interrupt_delays ) { unsigned char tmp; - interrupt_activity( AI_FORCE_INTERRUPT ); + if (interrupt_delays) + interrupt_activity( AI_FORCE_INTERRUPT ); for (;;) { mpr(str, MSGCH_PROMPT); diff --git a/crawl-ref/source/stuff.h b/crawl-ref/source/stuff.h index 2356eeb5d4..7ae7726222 100644 --- a/crawl-ref/source/stuff.h +++ b/crawl-ref/source/stuff.h @@ -60,7 +60,7 @@ void redraw_screen(void); void canned_msg(unsigned char which_message); bool yesno( const char * str, bool safe = true, int safeanswer = 0, - bool clear_after = true ); + bool clear_after = true, bool interrupt_delays = true ); int yesnoquit( const char* str, bool safe = true, int safeanswer = 0, bool clear_after = true ); diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc index 49f1002bbd..84bc069b00 100644 --- a/crawl-ref/source/travel.cc +++ b/crawl-ref/source/travel.cc @@ -15,6 +15,8 @@ #include "clua.h" #include "delay.h" #include "describe.h" +#include "itemname.h" +#include "items.h" #include "misc.h" #include "mon-util.h" #include "player.h" @@ -252,11 +254,12 @@ static bool is_exclude_root(int x, int y) const char *run_mode_name(int runmode) { - return runmode == RMODE_TRAVEL? "travel" : - runmode == RMODE_INTERLEVEL? "intertravel" : - runmode == RMODE_EXPLORE? "explore" : - runmode > 0? "run" : - ""; + return runmode == RMODE_TRAVEL? "travel" : + runmode == RMODE_INTERLEVEL? "intertravel" : + runmode == RMODE_EXPLORE? "explore" : + runmode == RMODE_EXPLORE_GREEDY? "explore_greedy" : + runmode > 0? "run" : + ""; } unsigned char is_waypoint(int x, int y) @@ -267,7 +270,6 @@ unsigned char is_waypoint(int x, int y) return curr_waypoints[x][y]; } -#ifdef STASH_TRACKING inline bool is_stash(LevelStashes *ls, int x, int y) { if (!ls) @@ -275,7 +277,6 @@ inline bool is_stash(LevelStashes *ls, int x, int y) Stash *s = ls->find_stash(x, y); return s && s->enabled; } -#endif void clear_excludes() { @@ -693,10 +694,30 @@ bool is_travelable_stair(unsigned gridc) } } +// Prompts the user to stop explore if necessary for the given +// explore-stop condition, returns true if explore should be stopped. +bool prompt_stop_explore(int es_why) +{ + return (!(Options.explore_stop_prompt & es_why) + || yesno("Stop exploring?", true, 'n', true, false)); +} + +static bool es_say(const char *what) +{ + mprf("Spotted %s.", what); + return (true); +} + #define ES_item (Options.explore_stop & ES_ITEM) -#define ES_shop (Options.explore_stop & ES_SHOP) -#define ES_stair (Options.explore_stop & ES_STAIR) -#define ES_altar (Options.explore_stop & ES_ALTAR) + +#define ES_shop ((Options.explore_stop & ES_SHOP) && \ + es_say("a shop") && prompt_stop_explore(ES_SHOP)) + +#define ES_stair ((Options.explore_stop & ES_STAIR) && \ + es_say("a stair") && prompt_stop_explore(ES_STAIR)) + +#define ES_altar ((Options.explore_stop & ES_ALTAR) && \ + es_say("an altar") && prompt_stop_explore(ES_ALTAR)) /* * Given a square that has just become visible during explore, returns true @@ -704,14 +725,22 @@ bool is_travelable_stair(unsigned gridc) */ static bool is_interesting_square(int x, int y) { - if (ES_item && igrd[x + 1][y + 1] != NON_ITEM) - return true; + if (ES_item && igrd[x + 1][y + 1] != NON_ITEM + && you.running != RMODE_EXPLORE_GREEDY) + { + mprf("Spotted %s.", + item_name( mitm[ igrd[x + 1][y + 1] ], DESC_NOCAP_A )); + if (prompt_stop_explore(ES_ITEM)) + return (true); + } unsigned char grid = grd[x + 1][y + 1]; - return (ES_shop && grid == DNGN_ENTER_SHOP) - || (ES_stair && is_stair(grid)) - || (ES_altar && is_altar(grid) - && you.where_are_you != BRANCH_ECUMENICAL_TEMPLE); + return (grid == DNGN_ENTER_SHOP && you.running != RMODE_EXPLORE_GREEDY + && ES_shop) + || (is_stair(grid) && ES_stair) + || (is_altar(grid) + && you.where_are_you != BRANCH_ECUMENICAL_TEMPLE + && ES_altar); } static void userdef_run_stoprunning_hook(void) @@ -739,9 +768,7 @@ void start_running(void) { userdef_run_startrunning_hook(); - if (you.running == RMODE_TRAVEL - || you.running == RMODE_EXPLORE - || you.running == RMODE_INTERLEVEL) + if (you.running < 0) start_delay( DELAY_TRAVEL, 1 ); } @@ -778,7 +805,7 @@ command_type travel() return CMD_NO_CMD; } - if (Options.explore_stop && you.running == RMODE_EXPLORE) + if (you.running.is_explore()) { // Scan through the shadow map, compare it with the actual map, and if // there are any squares of the shadow map that have just been @@ -801,9 +828,20 @@ command_type travel() copy(env.map, mapshadow); } - if (you.running == RMODE_EXPLORE) + if (you.running.is_explore()) { // Exploring + if (grd[you.x_pos][you.y_pos] == DNGN_ENTER_SHOP + && you.running == RMODE_EXPLORE_GREEDY) + { + LevelStashes *lev = stashes.find_current_level(); + if (lev && lev->shop_needs_visit(you.x_pos, you.y_pos)) + { + stop_running(); + return (CMD_GO_UPSTAIRS); + } + } + you.running.x = 0; find_travel_pos(you.x_pos, you.y_pos, NULL, NULL); // No place to go? @@ -839,8 +877,8 @@ command_type travel() // our travel target, we're on a staircase and should take it. if (you.x_pos == you.running.x && you.y_pos == you.running.y) { - if (runmode == RMODE_EXPLORE) - you.running = RMODE_EXPLORE; // Turn explore back on + if (runmode == RMODE_EXPLORE || runmode == RMODE_EXPLORE_GREEDY) + you.running = runmode; // Turn explore back on // For interlevel travel, we'll want to take the stairs unless // the interlevel travel specified a destination square and @@ -945,6 +983,11 @@ static void fill_exclude_radius(const coord_def &c) } } +static bool is_greed_inducing_square(const LevelStashes *ls, int x, int y) +{ + return (ls && can_autopickup() && ls->needs_visit(x, y)); +} + /* * The travel algorithm is based on the NetHack travel code written by Warwick * Allison - used with his permission. @@ -959,9 +1002,7 @@ void find_travel_pos(int youx, int youy, int dest_x = youx, dest_y = youy; bool floodout = false; unsigned char feature; -#ifdef STASH_TRACKING - LevelStashes *lev = features? stashes.find_current_level() : NULL; -#endif + LevelStashes *lev = stashes.find_current_level(); // Normally we start from the destination and floodfill outwards, looking // for the character's current position. If we're merely trying to populate @@ -1063,19 +1104,29 @@ void find_travel_pos(int youx, int youy, for (int dir = 0; dir < 8; (dir += 2) == 8 && (dir = 1)) { int dx = x + Compass[dir].x, dy = y + Compass[dir].y; - - if (dx <= 0 || dx >= GXM || dy <= 0 || dy >= GYM) continue; + + if (!in_bounds(dx, dy)) + continue; unsigned char envf = env.map[dx - 1][dy - 1]; - if (floodout && you.running == RMODE_EXPLORE - && !is_player_mapped(envf)) + if (floodout && you.running.is_explore() + && (!is_player_mapped(envf) + || (you.running == RMODE_EXPLORE_GREEDY + && is_greed_inducing_square(lev, dx, dy)))) { // Setting running.x and running.y here is evil - this // function should ideally not modify game state in any way. - you.running.x = x; - you.running.y = y; - + if (!is_player_mapped(envf)) + { + you.running.x = x; + you.running.y = y; + } + else + { + you.running.x = dx; + you.running.y = dy; + } return; } @@ -1144,10 +1195,7 @@ void find_travel_pos(int youx, int youy, && feature != DNGN_DEEP_WATER && feature != DNGN_LAVA) || is_waypoint(dx, dy) -#ifdef STASH_TRACKING - || is_stash(lev, dx, dy) -#endif - ) + || is_stash(lev, dx, dy)) && (dx != start_x || dy != start_y)) { coord_def c = { dx, dy }; @@ -2155,14 +2203,19 @@ void start_travel(int x, int y) start_running(); } -void start_explore() +void start_explore(bool grab_items) { - you.running = RMODE_EXPLORE; - if (Options.explore_stop) + you.running = grab_items? RMODE_EXPLORE_GREEDY : RMODE_EXPLORE; + if (you.running == RMODE_EXPLORE_GREEDY + && Options.stash_tracking != STM_ALL) { - // Clone shadow array off map - copy(env.map, mapshadow); + mpr("Explore + pickup is available only if stash_tracking = all"); + you.running = RMODE_EXPLORE; } + + // Clone shadow array off map + copy(env.map, mapshadow); + start_running(); } @@ -3118,6 +3171,11 @@ bool runrest::is_rest() const return (runmode > 0 && !x && !y); } +bool runrest::is_explore() const +{ + return (runmode == RMODE_EXPLORE || runmode == RMODE_EXPLORE_GREEDY); +} + void runrest::rundown() { rest(); diff --git a/crawl-ref/source/travel.h b/crawl-ref/source/travel.h index bd6e4221bc..935840963c 100644 --- a/crawl-ref/source/travel.h +++ b/crawl-ref/source/travel.h @@ -46,11 +46,14 @@ void find_travel_pos(int you_x, int you_y, char *move_x, char *move_y, * Initiates explore - the character runs around the level to map it. Note * that the caller has to ensure that the level is mappable before calling * start_explore. start_explore may lock up the game on unmappable levels. + * If grab_items is true, greedy explore is triggered - in greedy mode, explore + * grabs items that are eligible for autopickup and visits (previously + * unvisited) shops. * * *********************************************************************** * called from: acr * *********************************************************************** */ -void start_explore(); +void start_explore(bool grab_items = false); struct level_pos; void start_translevel_travel(const level_pos &pos); @@ -92,13 +95,15 @@ void arrange_features(std::vector<coord_def> &features); * *********************************************************************** */ extern short point_distance[GXM][GYM]; -enum EXPLORE_STOP +enum explore_stop_type { - ES_NONE = 0, - ES_ITEM = 1, - ES_STAIR = 2, - ES_SHOP = 4, - ES_ALTAR = 8 + ES_NONE = 0x00, + ES_ITEM = 0x01, + ES_PICKUP = 0x02, + ES_GREEDY_PICKUP = 0x04, + ES_STAIR = 0x08, + ES_SHOP = 0x10, + ES_ALTAR = 0x20 }; //////////////////////////////////////////////////////////////////////////// @@ -359,6 +364,7 @@ private: int level_distance(level_id first, level_id second); bool can_travel_interlevel(); +bool prompt_stop_explore(int es_why); extern TravelCache travel_cache; diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index 9d989da86a..87fedccb2c 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -1692,10 +1692,8 @@ bool is_feature(int feature, int x, int y) { case 'F': case 'W': return is_waypoint(x, y); -#ifdef STASH_TRACKING case 'I': return is_stash(x, y); -#endif case '_': switch (grid) { case DNGN_ALTAR_ZIN: |