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