1 /* 2 Copyright (C) 2014 - 2018 by Chris Beck <render787@gmail.com> 3 Part of the Battle for Wesnoth Project https://www.wesnoth.org/ 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY. 11 12 See the COPYING file for more details. 13 */ 14 15 #pragma once 16 17 #include "display_context.hpp" 18 #include "team.hpp" 19 #include "terrain/type_data.hpp" 20 #include "units/map.hpp" 21 #include "units/id.hpp" 22 23 #include <boost/optional.hpp> 24 #include <set> 25 #include <vector> 26 27 class config; 28 class gamemap; 29 30 namespace events { 31 class mouse_handler; 32 class menu_handler; 33 } 34 35 /** 36 * 37 * Game board class. 38 * 39 * The purpose of this class is to encapsulate some of the core game logic, including the unit map, 40 * the list of teams, and the game map. 41 * 42 * This should eventually become part of the game state object IMO, which should be a child of play_controller. 43 * 44 * I also intend to move the pathfinding module to be housed within this class -- this way, we can implement a 45 * sound pathfinding data structure to speed up path computations for AI, without having to make "update event" 46 * code at all points in the engine which modify the relevant data. 47 * 48 **/ 49 50 class game_board : public display_context 51 { 52 53 std::vector<team> teams_; 54 std::vector<std::string> labels_; 55 56 std::unique_ptr<gamemap> map_; 57 n_unit::id_manager unit_id_manager_; 58 unit_map units_; 59 60 //TODO: Remove these when we have refactored enough to make it possible. 61 friend class play_controller; 62 friend class events::mouse_handler; 63 friend class events::menu_handler; 64 friend class game_state; 65 friend class game_lua_kernel; 66 67 /** 68 * Temporary unit move structs: 69 * 70 * Probably don't remove these friends, this is actually fairly useful. These structs are used by: 71 * - AI 72 * - Whiteboard 73 * - I think certain wml actions 74 * For AI, the ai wants to move two units next to eachother so it can ask for attack calculations. This should not trigger 75 * pathfinding modifications, so the version that directly changes the unit map is probably preferable, although it should be 76 * refactored. 77 * For whiteboard and wml actions, we generally do want pathfinding to be updated, so use the game_board constructors which I 78 * have added to these structs instead. 79 * 80 **/ 81 friend struct temporary_unit_placer; 82 friend struct temporary_unit_mover; 83 friend struct temporary_unit_remover; 84 85 public: unit_id_manager()86 n_unit::id_manager& unit_id_manager() { return unit_id_manager_; } 87 // Constructors, trivial dtor, and const accessors 88 89 game_board(const ter_data_cache & tdata, const config & level); 90 virtual ~game_board(); 91 teams() const92 virtual const std::vector<team>& teams() const override 93 { 94 return teams_; 95 } 96 teams()97 std::vector<team>& teams() 98 { 99 return teams_; 100 } 101 102 using display_context::get_team; // so as not to hide the const version 103 get_team(int i)104 team& get_team(int i) 105 { 106 return teams_.at(i - 1); 107 } 108 map() const109 virtual const gamemap& map() const override 110 { 111 return *map_; 112 } 113 units() const114 virtual const unit_map& units() const override 115 { 116 return units_; 117 } 118 units()119 unit_map& units() 120 { 121 return units_; 122 } 123 hidden_label_categories() const124 virtual const std::vector<std::string>& hidden_label_categories() const override 125 { 126 return labels_; 127 } 128 hidden_label_categories()129 virtual std::vector<std::string>& hidden_label_categories() override 130 { 131 return labels_; 132 } 133 134 // Copy and swap idiom, because we have a scoped pointer. 135 136 game_board(const game_board & other); 137 game_board& operator=(const game_board& other) = delete; 138 139 friend void swap(game_board & one, game_board & other); 140 141 // Saving 142 143 void write_config(config & cfg) const; 144 145 // Manipulators from play_controller 146 147 void new_turn(int pnum); 148 void end_turn(int pnum); 149 void set_all_units_user_end_turn(); 150 151 void heal_all_survivors(); 152 153 void check_victory(bool &, bool &, bool &, bool &, std::set<unsigned> &, bool); 154 155 // Manipulator from playturn 156 157 void side_drop_to (int side_num, team::CONTROLLER ctrl, team::PROXY_CONTROLLER proxy = team::PROXY_CONTROLLER::PROXY_HUMAN); 158 void side_change_controller (int side_num, bool is_local, const std::string& pname = ""); 159 160 // Manipulator from actionwml 161 162 bool try_add_unit_to_recall_list(const map_location& loc, const unit_ptr u); 163 boost::optional<std::string> replace_map (const gamemap & r); 164 void overlay_map (const gamemap & o, const config & cfg, map_location loc); 165 166 bool change_terrain(const map_location &loc, const std::string &t, 167 const std::string & mode, bool replace_if_failed); //used only by lua 168 169 // Global accessor from unit.hpp 170 171 unit_map::iterator find_visible_unit(const map_location &loc, const team& current_team, bool see_all = false); find_visible_unit(const map_location & loc,size_t team,bool see_all=false)172 unit_map::iterator find_visible_unit(const map_location & loc, size_t team, bool see_all = false) { return find_visible_unit(loc, teams_[team], see_all); } 173 bool has_visible_unit (const map_location & loc, const team & team, bool see_all = false) const; has_visible_unit(const map_location & loc,size_t team,bool see_all=false) const174 bool has_visible_unit (const map_location & loc, size_t team, bool see_all = false) const { return has_visible_unit(loc, teams_[team], see_all); } 175 176 unit* get_visible_unit(const map_location &loc, const team ¤t_team, bool see_all = false); //TODO: can this not return a pointer? 177 178 // Wrapped functions from unit_map. These should ultimately provide notification to observers, pathfinding. 179 find_unit(const map_location & loc)180 unit_map::iterator find_unit(const map_location & loc) { return units_.find(loc); } 181 /// Calculates whether a team is defeated 182 bool team_is_defeated(const team& t) const; 183 }; 184 185 void swap(game_board & one, game_board & other); 186 187 188 /** 189 * This object is used to temporary place a unit in the unit map, swapping out 190 * any unit that is already there. On destruction, it restores the unit map to 191 * its original. 192 */ 193 struct temporary_unit_placer 194 { 195 temporary_unit_placer(unit_map& m, const map_location& loc, unit& u); 196 temporary_unit_placer(game_board& m, const map_location& loc, unit& u); 197 virtual ~temporary_unit_placer(); 198 199 private: 200 unit_map& m_; 201 const map_location loc_; 202 unit_ptr temp_; 203 }; 204 205 // Begin Temporary Unit Move Structs 206 // TODO: Fix up the implementations which use game_board 207 208 /** 209 * This object is used to temporary remove a unit from the unit map. 210 * On destruction, it restores the unit map to its original. 211 * unit_map iterators to this unit must not be accessed while the unit is temporarily 212 * removed, otherwise a collision will happen when trying to reinsert the unit. 213 */ 214 struct temporary_unit_remover 215 { 216 temporary_unit_remover(unit_map& m, const map_location& loc); 217 temporary_unit_remover(game_board& m, const map_location& loc); 218 virtual ~temporary_unit_remover(); 219 220 private: 221 unit_map& m_; 222 const map_location loc_; 223 unit_ptr temp_; 224 }; 225 226 227 /** 228 * This object is used to temporary move a unit in the unit map, swapping out 229 * any unit that is already there. On destruction, it restores the unit map to 230 * its original. 231 */ 232 struct temporary_unit_mover 233 { 234 temporary_unit_mover(unit_map& m, const map_location& src, 235 const map_location& dst, int new_moves); 236 temporary_unit_mover(unit_map& m, const map_location& src, 237 const map_location& dst); 238 temporary_unit_mover(game_board& b, const map_location& src, 239 const map_location& dst, int new_moves); 240 temporary_unit_mover(game_board& b, const map_location& src, 241 const map_location& dst); 242 virtual ~temporary_unit_mover(); 243 244 private: 245 unit_map& m_; 246 const map_location src_; 247 const map_location dst_; 248 int old_moves_; 249 unit_ptr temp_; 250 }; 251