1 /**
2  * @file
3  * @brief Game state.
4 **/
5 
6 #pragma once
7 
8 #include <vector>
9 
10 #include "activity-interrupt-type.h"
11 #include "command-type.h"
12 #include "disable-type.h"
13 #include "end.h"
14 #include "game-exit-type.h"
15 #include "game-type.h"
16 #include "player.h"
17 
18 class monster;
19 class mon_acting;
20 class targeter;
21 struct activity_interrupt_data;
22 
23 struct god_act_state
24 {
25 public:
26 
27     god_act_state();
28     void reset();
29 
30     god_type which_god;
31     bool     retribution;
32     int      depth;
33 };
34 
35 // Track various aspects of Crawl game state.
36 struct game_state
37 {
38     vector<string> command_line_arguments;
39 
40     bool game_crashed;      // The game crashed and is now in the process of
41                             // dumping crash info.
42     bool crash_debug_scans_safe; // should the crash handler run various debug
43                                  // scans?
44 
45     bool mouse_enabled;     // True if mouse input is currently relevant.
46 
47     bool waiting_for_command; // True when the game is waiting for a command.
48     bool terminal_resized;   // True if the term was resized and we need to
49                              // take action to handle it.
50     time_t last_winch;       // Time of last resize, for crash dumps.
51 
52     uint64_t seed;
53 
54     bool io_inited;         // Is curses or the equivalent initialised?
55     bool need_save;         // Set to true when game can be saved, false when the game ends.
56     bool game_started;      // Set to true when a game has started.
57     bool saving_game;       // Set to true while in save_game.
58     bool updating_scores;   // Set to true while updating hiscores.
59 #ifndef USE_TILE_LOCAL
60     bool smallterm;         // The terminal has been resized under the min view
61                             // size, and errors need to be displayed
62 #endif
63     const char* no_gdb;     // reason for not running gdb
64 
65     int  seen_hups;         // Set to true if SIGHUP received.
66 
67     bool map_stat_gen;      // Set if we're generating stats on maps.
68     bool map_stat_dump_disconnect; // Set if we dump disconnected maps and exit
69                                    // under mapstat.
70     bool obj_stat_gen;      // Set if we're generating object stats.
71 
72     string force_map;       // Set if we're forcing a specific map to generate.
73 
74     game_type type;
75     game_type last_type;
76     game_ended_condition last_game_exit;
77     bool marked_as_won;
78     bool arena_suspended;   // Set if the arena has been temporarily
79                             // suspended.
80     bool generating_level;
81 
82     bool dump_maps;         // Dump map Lua to stderr on fresh parse.
83     bool test;              // Set if we want to run self-tests and exit.
84     bool test_list;         // Show available tests and exit.
85     bool script;            // Set if we want to run a Lua script and exit.
86     bool build_db;          // Set if we want to rebuild the db and exit.
87     vector<string> tests_selected; // Tests to be run.
88     vector<string> script_args;    // Arguments to scripts.
89 
90     bool throttle;
91     bool bypassed_startup_menu;
92 
93     bool show_more_prompt;  // Set to false to disable --more-- prompts.
94 
95     string sprint_map;      // Sprint map set on command line, if any.
96 
97     string map;             // Map selected in the newgame menu
98 
99     void (*terminal_resize_handler)();
100     void (*terminal_resize_check)();
101 
102     bool            doing_prev_cmd_again;
103     command_type    prev_cmd;
104     deque<int>      prev_cmd_keys;
105 
106     command_type    repeat_cmd;
107     bool            cmd_repeat_start;
108     command_type    prev_repeat_cmd;
109     int             prev_cmd_repeat_goal;
110     bool            cmd_repeat_started_unsafe;
111     int             lua_calls_no_turn;
112     bool            stat_gain_prompt;
113 
114     bool            simulating_xp_gain; // is the skill menu in xp potion mode?
115 
116     bool level_annotation_shown;
117     bool viewport_monster_hp;
118     bool viewport_weapons;
119 
120     bool tiles_disabled; // ignored unless USE_TILE_LOCAL is defined
121     bool title_screen; // ignored unless USE_TILE_LOCAL is defined
122 
123     bool invisible_targeting;
124 
125     // Area beyond which view should be darkened,  0 = disabled.
126     targeter *darken_range;
127 
128     // Monsters to highlight on the screen, 0 = disabled.
129     vector<monster *> *flash_monsters;
130 
131     // Any changes to macros that need to be changed?
132     bool unsaved_macros;
133 
134     FixedBitVector<NUM_DISABLEMENTS> disables;
135 
136     // Version of the last character save.
137     int minor_version;
138 
139     // Git version of the character save. This will be empty unless the
140     // character has been loaded from a previous save.
141     std::string save_rcs_version;
142 
143     string default_startup_name;
144 
145     // Should flushing a nonempty key buffer error or crash? Used for tests.
146     bool nonempty_buffer_flush_errors;
147 
148     string last_builder_error;
149     bool last_builder_error_fatal;
150 
151 protected:
152     void reset_cmd_repeat();
153     void reset_cmd_again();
154 
155     god_act_state         god_act;
156     vector<god_act_state> god_act_stack;
157 
158     monster*          mon_act;
159     vector<monster* > mon_act_stack;
160 
161 public:
162     game_state();
163 
164     void reset_game();
165 
166     void add_startup_error(const string &error);
167 
168     bool is_replaying_keys() const;
169 
170     bool is_repeating_cmd() const;
171 
172     void cancel_cmd_repeat(string reason = "", bool force=false);
173     void cancel_cmd_again(string reason = "", bool force=false);
174     void cancel_cmd_all(string reason = "");
175 
176     void cant_cmd_repeat(string reason = "");
177     void cant_cmd_again(string reason = "");
178     void cant_cmd_any(string reason = "");
179 
180     void zero_turns_taken();
181 
check_term_sizegame_state182     void check_term_size() const
183     {
184         if (terminal_resize_check)
185             (*terminal_resize_check)();
186     }
187 
188     bool     is_god_acting() const;
189     bool     is_god_retribution() const;
190     god_type which_god_acting() const;
191     void     inc_god_acting(bool is_retribution = false);
192     void     inc_god_acting(god_type which_god, bool is_retribution = false);
193     void     dec_god_acting();
194     void     dec_god_acting(god_type which_god);
195     void     clear_god_acting();
196 
197     vector<god_act_state> other_gods_acting() const;
198 
199     bool      is_mon_acting() const;
200     monster* which_mon_acting() const;
201     void      inc_mon_acting(monster* mon);
202     void      dec_mon_acting(monster* mon);
203     void      clear_mon_acting();
204     void      mon_gone(monster* mon);
205 
206     void dump();
207     bool player_is_dead() const;
208 
209     bool game_standard_levelgen() const;
210     bool game_is_valid_type() const;
211     bool game_is_normal() const;
212     bool game_is_tutorial() const;
213     bool game_is_arena() const;
214     bool game_is_sprint() const;
215     bool game_is_hints() const;
216     bool game_is_hints_tutorial() const;
217 
218     // Save subdirectory used for games such as Sprint.
219     string game_type_name() const;
220     string game_savedir_path() const;
221     string game_type_qualifier() const;
222 
223     static string game_type_name_for(game_type gt);
224 
mark_last_game_wongame_state225     inline void mark_last_game_won()
226     {
227         marked_as_won = true;
228     }
229 
230     friend class mon_acting;
231 };
232 
233 #ifdef DEBUG_GLOBALS
234 #define crawl_state (*real_crawl_state)
235 #endif
236 extern game_state crawl_state;
237 
238 class god_acting
239 {
240 public:
241     god_acting(bool is_retribution = false)
242         : god(you.religion)
243     {
244         crawl_state.inc_god_acting(god, is_retribution);
245     }
246     god_acting(god_type who, bool is_retribution = false)
god(who)247         : god(who)
248     {
249         crawl_state.inc_god_acting(god, is_retribution);
250     }
~god_acting()251     ~god_acting()
252     {
253         crawl_state.dec_god_acting(god);
254     }
255 private:
256     god_type god;
257 };
258 
259 class mon_acting
260 {
261 public:
mon_acting(monster * _mon)262     mon_acting(monster* _mon) : mon(_mon)
263     {
264         crawl_state.inc_mon_acting(_mon);
265     }
266 
~mon_acting()267     ~mon_acting()
268     {
269         // Monster might have died in the meantime.
270         if (mon == crawl_state.mon_act)
271             crawl_state.dec_mon_acting(mon);
272     }
273 
274 private:
275     monster* mon;
276 };
277 
278 bool interrupt_cmd_repeat(activity_interrupt ai,
279                           const activity_interrupt_data &at);
280