summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/state.cc
diff options
context:
space:
mode:
Diffstat (limited to 'crawl-ref/source/state.cc')
-rw-r--r--crawl-ref/source/state.cc235
1 files changed, 235 insertions, 0 deletions
diff --git a/crawl-ref/source/state.cc b/crawl-ref/source/state.cc
new file mode 100644
index 0000000000..a664a3464b
--- /dev/null
+++ b/crawl-ref/source/state.cc
@@ -0,0 +1,235 @@
+/*
+ * File: state.cc
+ * Summary: Game state functions.
+ * Written by: Matthew Cline
+ *
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
+ * Change History (most recent first):
+ *
+ * <1> 09/18/07 MPC Created
+ */
+
+#include "AppHdr.h"
+#include "externs.h"
+
+#include "delay.h"
+#include "direct.h"
+#include "macro.h"
+#include "mon-util.h"
+#include "menu.h" // For print_formatted_paragraph()
+#include "player.h"
+#include "state.h"
+#include "tutorial.h"
+#include "view.h"
+
+game_state::game_state()
+ : mouse_enabled(false), waiting_for_command(false),
+ terminal_resized(false), io_inited(false), need_save(false),
+ saving_game(false), updating_scores(false), seen_hups(0),
+ map_stat_gen(false), unicode_ok(false), glyph2strfn(NULL),
+ multibyte_strlen(NULL), terminal_resize_handler(NULL),
+ terminal_resize_check(NULL), doing_prev_cmd_again(false),
+ prev_cmd(CMD_NO_CMD), repeat_cmd(CMD_NO_CMD), cmd_repeat_count(0),
+ cmd_repeat_goal(0), prev_repetition_turn(0),
+ cmd_repeat_started_unsafe(false), input_line_curr(0)
+{
+ reset_cmd_repeat();
+ reset_cmd_again();
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Repeating commands and doing the previous command over again.
+
+bool game_state::is_replaying_keys() const
+{
+ return (crawl_state.doing_prev_cmd_again
+ || (crawl_state.is_repeating_cmd()
+ && !crawl_state.cmd_repeat_start));
+}
+
+bool game_state::is_repeating_cmd() const
+{
+ ASSERT((cmd_repeat_goal == 0 && cmd_repeat_count == 0
+ && repeat_cmd == CMD_NO_CMD && !cmd_repeat_start)
+ || (cmd_repeat_goal > 0 && cmd_repeat_count <= cmd_repeat_goal
+ && repeat_cmd != CMD_NO_CMD));
+
+ return (repeat_cmd != CMD_NO_CMD);
+}
+
+void game_state::cancel_cmd_repeat(std::string reason)
+{
+ if (!is_repeating_cmd())
+ return;
+
+ if (is_replaying_keys())
+ flush_input_buffer(FLUSH_KEY_REPLAY_CANCEL);
+
+ if (is_processing_macro())
+ flush_input_buffer(FLUSH_ABORT_MACRO);
+
+ reset_cmd_repeat();
+
+ if (reason != "")
+ mpr(reason.c_str());
+}
+
+void game_state::cancel_cmd_again(std::string reason)
+{
+ if (!doing_prev_cmd_again)
+ return;
+
+ flush_input_buffer(FLUSH_KEY_REPLAY_CANCEL);
+
+ if (is_processing_macro())
+ flush_input_buffer(FLUSH_ABORT_MACRO);
+
+ reset_cmd_again();
+
+ if (reason != "")
+ mpr(reason.c_str());
+}
+
+void game_state::cant_cmd_repeat(std::string reason)
+{
+ if (reason == "")
+ reason = "Can't repeat that command.";
+
+ cancel_cmd_repeat(reason);
+}
+
+void game_state::cant_cmd_again(std::string reason)
+{
+ if (reason == "")
+ reason = "Can't redo that command.";
+
+ cancel_cmd_again(reason);
+}
+
+// The mehtod is called to prevent the "no repeating zero turns
+// commands" message that input() generates (in the abscence of
+// cancelling the repeition) for a repeated command that took no
+// turns. A wrapper around cancel_cmd_repeat(), its only purpose it
+// to make it clear why cancel_cmd_repeat() is being called.
+void game_state::zero_turns_taken()
+{
+ ASSERT(!you.turn_is_over);
+ cancel_cmd_repeat();
+}
+
+bool interrupt_cmd_repeat( activity_interrupt_type ai,
+ const activity_interrupt_data &at )
+{
+ if (crawl_state.cmd_repeat_start)
+ return false;
+
+ // If command repitition is being used to immitate the rest command,
+ // then everything interrupts it.
+ if (crawl_state.repeat_cmd == CMD_MOVE_NOWHERE
+ || crawl_state.repeat_cmd == CMD_SEARCH)
+ {
+ return true;
+ }
+
+ if (crawl_state.repeat_cmd == CMD_WIZARD)
+ return false;
+
+ switch (ai)
+ {
+ case AI_STATUE:
+ case AI_HUNGRY:
+ case AI_TELEPORT:
+ case AI_FORCE_INTERRUPT:
+ case AI_HP_LOSS:
+ case AI_MONSTER_ATTACKS:
+ crawl_state.cancel_cmd_repeat("Command repetition interrupted.");
+ return true;
+
+ default:
+ break;
+ }
+
+ if (ai == AI_SEE_MONSTER)
+ {
+ const monsters* mon = static_cast<const monsters*>(at.data);
+ if (!mon->visible())
+ return false;
+
+ if (crawl_state.cmd_repeat_started_unsafe
+ && at.context != "newly seen")
+ {
+ return false;
+ }
+
+ crawl_state.cancel_cmd_repeat();
+
+#ifndef DEBUG_DIAGNOSTICS
+ if (at.context == "newly seen")
+ {
+ std::string text = get_monster_desc(mon, false);
+ text += " comes into view.";
+ print_formatted_paragraph(text, get_number_of_cols(), MSGCH_WARN);
+ }
+
+ if (Options.tutorial_left)
+ {
+ // enforce that this message comes first
+ tutorial_first_monster(*mon);
+ if (get_mons_colour(mon) != mon->colour)
+ learned_something_new(TUT_MONSTER_BRAND);
+ }
+#else
+ formatted_string fs( channel_to_colour(MSGCH_WARN) );
+ fs.cprintf("%s (", mon->name(DESC_PLAIN, true).c_str());
+ fs.add_glyph( mon );
+ fs.cprintf(") in view: (%d,%d), see_grid: %s",
+ mon->x, mon->y,
+ see_grid(mon->x, mon->y)? "yes" : "no");
+ formatted_mpr(fs, MSGCH_WARN);
+#endif
+
+ return true;
+ }
+
+ if (crawl_state.cmd_repeat_started_unsafe)
+ return false;
+
+ if (ai == AI_HIT_MONSTER)
+ {
+ // This check is for when command repetition is used to
+ // whack away at a 0xp monster, since the player feels safe
+ // when the only monsters around are 0xp.
+ const monsters* mon = static_cast<const monsters*>(at.data);
+
+ if (mons_class_flag(mon->type, M_NO_EXP_GAIN)
+ && player_monster_visible(mon))
+ {
+ return false;
+ }
+
+ crawl_state.cancel_cmd_repeat("Command repetition interrupted.");
+ return true;
+ }
+
+ return false;
+}
+
+void game_state::reset_cmd_repeat()
+{
+ repeat_cmd = CMD_NO_CMD;
+ cmd_repeat_count = 0;
+ cmd_repeat_goal = 0;
+ cmd_repeat_start = false;
+ prev_repetition_turn = 0;
+
+ repeat_cmd_keys.clear();
+}
+
+void game_state::reset_cmd_again()
+{
+ doing_prev_cmd_again = false;
+ prev_cmd = CMD_NO_CMD;
+
+ prev_cmd_keys.clear();
+}