1 /*
2 * Copyright (C) 2004-2020 by the Widelands Development Team
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 */
19
20 #include "economy/route.h"
21
22 #include "economy/flag.h"
23 #include "io/fileread.h"
24 #include "io/filewrite.h"
25 #include "logic/editor_game_base.h"
26 #include "map_io/map_object_loader.h"
27 #include "map_io/map_object_saver.h"
28
29 /*
30 ==============================================================================
31
32 Route IMPLEMENTATION
33
34 ==============================================================================
35 */
36
37 namespace Widelands {
Route()38 Route::Route() : totalcost_(0) {
39 }
40
41 /**
42 * Completely clear the route and initialize it
43 * to its totalcost
44 */
init(int32_t totalcost)45 void Route::init(int32_t totalcost) {
46 totalcost_ = totalcost;
47 route_.clear();
48 }
49
50 /**
51 * Return the flag with the given number.
52 * idx == 0 is the start flag, idx == get_nrsteps() is the end flag.
53 * Every route has at least one flag.
54 */
get_flag(EditorGameBase & egbase,std::vector<Flag * >::size_type const idx)55 Flag& Route::get_flag(EditorGameBase& egbase, std::vector<Flag*>::size_type const idx) {
56 assert(idx < route_.size());
57 return *route_[idx].get(egbase);
58 }
59
60 /**
61 * Remove the first count steps from the route.
62 */
trim_start(int32_t count)63 void Route::trim_start(int32_t count) {
64 assert(count < static_cast<int32_t>(route_.size()));
65
66 route_.erase(route_.begin(), route_.begin() + count);
67 }
68
69 /**
70 * Keep the first count steps, truncate the rest.
71 */
truncate(int32_t const count)72 void Route::truncate(int32_t const count) {
73 assert(count < static_cast<int32_t>(route_.size()));
74
75 route_.erase(route_.begin() + count + 1, route_.end());
76 }
77
78 /**
79 * Preliminarily load the route from the given file.
80 * Must call \ref load_pointers after \ref load
81 * \param data the caller must provide and manage this buffer that
82 * stores information for a later call to \ref load_pointers
83 */
load(LoadData & data,FileRead & fr)84 void Route::load(LoadData& data, FileRead& fr) {
85 route_.clear();
86
87 totalcost_ = fr.signed_32();
88 uint32_t nsteps = fr.unsigned_16();
89 for (uint32_t step = 0; step < nsteps; ++step)
90 data.flags.push_back(fr.unsigned_32());
91 }
92
93 /**
94 * load_pointers phase of loading: This is responsible for filling
95 * in the \ref Flag pointers. Must be called after \ref load.
96 */
load_pointers(const LoadData & data,MapObjectLoader & mol)97 void Route::load_pointers(const LoadData& data, MapObjectLoader& mol) {
98 for (uint32_t i = 0; i < data.flags.size(); ++i) {
99 uint32_t const flag_serial = data.flags.size();
100 try {
101 route_.push_back(&mol.get<Flag>(flag_serial));
102 } catch (const WException& e) {
103 throw wexception("Route flag #%u (%u): %s", i, flag_serial, e.what());
104 }
105 }
106 }
107
108 /**
109 * Save the route to the given file.
110 */
save(FileWrite & fw,EditorGameBase & egbase,MapObjectSaver & mos)111 void Route::save(FileWrite& fw, EditorGameBase& egbase, MapObjectSaver& mos) {
112 fw.signed_32(get_totalcost());
113 fw.unsigned_16(route_.size());
114 for (std::vector<ObjectPointer>::size_type idx = 0; idx < route_.size(); ++idx) {
115 Flag& flag = get_flag(egbase, idx);
116 assert(mos.is_object_known(flag));
117 fw.unsigned_32(mos.get_object_file_index(flag));
118 }
119 }
120
121 /**
122 * Insert this node as the very first entry into the Route
123 */
insert_as_first(RoutingNode * node)124 void Route::insert_as_first(RoutingNode* node) {
125 // we are sure that node is a Flag, since it is the only
126 // RoutingNode ever used in the path finder (outside tests)
127 // That's why we can make this cast
128 route_.insert(route_.begin(), static_cast<Flag*>(node));
129 }
130 } // namespace Widelands
131