Merge lp:~widelands-dev/widelands/bug-1718745-allows-seafaring into lp:widelands
- bug-1718745-allows-seafaring
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 8530 | ||||
Proposed branch: | lp:~widelands-dev/widelands/bug-1718745-allows-seafaring | ||||
Merge into: | lp:widelands | ||||
Diff against target: |
1153 lines (+324/-174) 39 files modified
src/ai/defaultai.cc (+11/-13) src/ai/defaultai.h (+3/-1) src/ai/defaultai_seafaring.cc (+3/-6) src/editor/tools/set_port_space_tool.cc (+2/-2) src/editor/ui_menus/main_menu_save_map.cc (+1/-0) src/logic/map.cc (+66/-50) src/logic/map.h (+21/-9) src/logic/map_objects/tribes/production_program.cc (+2/-2) src/map_io/map_port_spaces_packet.cc (+2/-4) src/map_io/s2map.cc (+24/-38) src/map_io/s2map.h (+2/-1) src/scripting/lua_map.cc (+54/-1) src/scripting/lua_map.h (+3/-0) src/wui/building_statistics_menu.cc (+2/-2) src/wui/fieldaction.cc (+4/-2) test/maps/expedition.wmf/scripting/init.lua (+5/-16) test/maps/expedition.wmf/scripting/test_cancel_when_port_space_was_reached_two_ships.lua (+1/-1) test/maps/expedition.wmf/scripting/test_ship_movement_controls.lua (+1/-1) test/maps/expedition.wmf/scripting/test_starting_wait_a_while_cancel.lua (+1/-1) test/maps/ship_transportation.wmf/scripting/init.lua (+1/-12) test/maps/ship_transportation.wmf/scripting/test_many_ships.lua (+1/-1) test/maps/ship_transportation.wmf/scripting/test_rip_first_port_with_ware_in_portdock.lua (+1/-1) test/maps/ship_transportation.wmf/scripting/test_rip_first_port_with_worker_in_portdock.lua (+1/-1) test/maps/ship_transportation.wmf/scripting/test_rip_portdock_with_worker_and_ware_in_transit.lua (+1/-1) test/maps/ship_transportation.wmf/scripting/test_rip_ports_with_ware_in_transit.lua (+1/-1) test/maps/ship_transportation.wmf/scripting/test_rip_ports_with_worker_in_transit.lua (+1/-1) test/maps/ship_transportation.wmf/scripting/test_rip_second_port_with_ware_in_portdock.lua (+1/-1) test/maps/ship_transportation.wmf/scripting/test_rip_second_port_with_worker_in_portdock.lua (+1/-1) test/maps/ship_transportation.wmf/scripting/test_rip_ship_before_picking_up_transporting_ware.lua (+2/-2) test/maps/ship_transportation.wmf/scripting/test_rip_ship_while_transporting_ware.lua (+2/-2) test/maps/two_ponds.wmf/elemental (+12/-0) test/maps/two_ponds.wmf/objective (+4/-0) test/maps/two_ponds.wmf/player_names (+10/-0) test/maps/two_ponds.wmf/player_position (+5/-0) test/maps/two_ponds.wmf/port_spaces (+9/-0) test/maps/two_ponds.wmf/scripting/init.lua (+6/-0) test/maps/two_ponds.wmf/scripting/test_seafaring.lua (+33/-0) test/maps/two_ponds.wmf/version (+11/-0) test/scripting/stable_save.lua (+13/-0) |
||||
To merge this branch: | bzr merge lp:~widelands-dev/widelands/bug-1718745-allows-seafaring | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
GunChleoc | Needs Resubmitting | ||
Review via email: mp+333233@code.launchpad.net |
Commit message
Split new function cleanup_
- get_allows_
- get_number_
- set_port_space
Description of the change
TiborB (tiborb95) wrote : | # |
GunChleoc (gunchleoc) wrote : | # |
allows_seafaring is already usable by the AI. And now you don't even need a mutable_map - a const map& will do.
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 2766. State: passed. Details: https:/
Appveyor build 2578. State: success. Details: https:/
GunChleoc (gunchleoc) wrote : | # |
New version - I decided to get a bit more fancy with the checks.
It would be good to have a replacement for the Buildcaps check, because it fails once a tree gets in the way. This is why we need the "force" parameter. Maybe check the terrain height in a certain radius?
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 2774. State: failed. Details: https:/
Appveyor build 2586. State: success. Details: https:/
GunChleoc (gunchleoc) wrote : | # |
Well, the solution was staring me right in the face in the S2 map loading code that I had deleted... So, we now have a port space check that ignores immovables.
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 2779. State: errored. Details: https:/
Appveyor build 2591. State: success. Details: https:/
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 2914. State: passed. Details: https:/
Appveyor build 2723. State: success. Details: https:/
TiborB (tiborb95) wrote : | # |
See comment in the code
GunChleoc (gunchleoc) wrote : | # |
I completely removed the probability for the check - we can afford to run the function every 5 seconds.
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 2934. State: failed. Details: https:/
Appveyor build 2743. State: success. Details: https:/
TiborB (tiborb95) wrote : | # |
But this might be too much - if we have 16 players, this could mean 3x per second....
GunChleoc (gunchleoc) wrote : | # |
I have now added a static variable to control the check frequency. So, it's now globally checked every 5 seconds max.
TiborB (tiborb95) wrote : | # |
See comment in diff
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 2936. State: passed. Details: https:/
Appveyor build 2745. State: success. Details: https:/
GunChleoc (gunchleoc) wrote : | # |
Duh - thanks for having my back!
TiborB (tiborb95) wrote : | # |
Also I cannot find an initialization of the variable :)
GunChleoc (gunchleoc) wrote : | # |
Line 8 in the diff: uint32_t DefaultAI:
This has to be initialized in the .cc file - at least that has been my experience with static variables that are not constexpr.
TiborB (tiborb95) wrote : | # |
But why not few lines below inside the constructor of DefaultAI object?
GunChleoc (gunchleoc) wrote : | # |
Because the compiler will not allow initializing it within the constructor.
TiborB (tiborb95) wrote : | # |
Because it is static? Do you mean it is shared among all AIs?
GunChleoc (gunchleoc) wrote : | # |
Exactly, that is what static means - there is only 1 instance of the variable for all objects. This is also the reason why it can't be initialized in the constructor, because there are no individual copies of the variable, and it can be initialized only once.
Since whether a map is seafaring does not depend on which AI is doing the check, having a global check triggered about ever 5 seconds is sufficient. So, it won't cost extra load when we have lots of AIs, because only one of them will check for everybody.
I'm now wondering if that actually works, since seafaring_economy is not static. It does some check for if there is a ship being built somewhere else in the AI code - is this check actually needed now?
TiborB (tiborb95) wrote : | # |
OK, I expected something like this. And this looks like very useful type of variable.
As for seafaring economy, this one can be as well changed into static I think... and/or renamed a bit...
TiborB (tiborb95) wrote : | # |
Maybe you could rename swim_coords and visited_positions to more obvious names. Swim coords are coords reachable from previous ports and visited_positions are the one reachable from current port.
It is not easy to come up with short names, but something like this: previous_
+ 1 comment in diff
GunChleoc (gunchleoc) wrote : | # |
Excellent suggestions, I have implemented them. I also added a simple check for number of port spaces up front, this will speed things up even further on non-seafaring maps.
And ASan found a bug, that's now fixed too :)
TiborB (tiborb95) wrote : | # |
I would rename the variable to reachable_
GunChleoc (gunchleoc) wrote : | # |
Done. Thanks for the review, this branch really would have been a mess without it!
@bunnybot merge
bunnybot (widelandsofficial) wrote : | # |
Error merging this proposal:
Output:
stdout:
stderr:
bzr: ERROR: Parameter 'Merged lp:~widelands-dev/widelands/bug-1718745-allows-seafaring:\nSplit new function cleanup_
GunChleoc (gunchleoc) wrote : | # |
@bunnybot merge
Preview Diff
1 | === modified file 'src/ai/defaultai.cc' |
2 | --- src/ai/defaultai.cc 2017-12-03 08:23:27 +0000 |
3 | +++ src/ai/defaultai.cc 2017-12-11 06:56:51 +0000 |
4 | @@ -82,6 +82,9 @@ |
5 | DefaultAI::WeakImpl DefaultAI::weak_impl; |
6 | DefaultAI::VeryWeakImpl DefaultAI::very_weak_impl; |
7 | |
8 | +uint32_t DefaultAI::last_seafaring_check_ = 0; |
9 | +bool DefaultAI::map_allows_seafaring_ = false; |
10 | + |
11 | /// Constructor of DefaultAI |
12 | DefaultAI::DefaultAI(Game& ggame, PlayerNumber const pid, Widelands::AiType const t) |
13 | : ComputerPlayer(ggame, pid), |
14 | @@ -109,7 +112,6 @@ |
15 | enemysites_check_delay_(30), |
16 | resource_necessity_water_needed_(false), |
17 | highest_nonmil_prio_(0), |
18 | - seafaring_economy(false), |
19 | expedition_ship_(kNoShip) { |
20 | |
21 | // Subscribe to NoteFieldPossession. |
22 | @@ -1951,11 +1953,9 @@ |
23 | |
24 | const Map& map = game().map(); |
25 | |
26 | - if (gametime % 5 == 0) { |
27 | - // TODO(unknown): Counting port spaces is very primitive way for this |
28 | - // there should be better alternative f.e. like map::allows_seafaring() |
29 | - // function but simplier |
30 | - seafaring_economy = map.get_port_spaces().size() >= 2; |
31 | + if (gametime > last_seafaring_check_ + 20000U) { |
32 | + map_allows_seafaring_ = map.allows_seafaring(); |
33 | + last_seafaring_check_ = gametime; |
34 | } |
35 | |
36 | for (int32_t i = 0; i < 4; ++i) |
37 | @@ -2663,7 +2663,7 @@ |
38 | assert(!bo.is(BuildingAttribute::kShipyard)); |
39 | } else if (bo.is(BuildingAttribute::kShipyard)) { |
40 | assert(bo.new_building == BuildingNecessity::kAllowed); |
41 | - if (!seafaring_economy) { |
42 | + if (!map_allows_seafaring_) { |
43 | continue; |
44 | } |
45 | } else { |
46 | @@ -2702,12 +2702,10 @@ |
47 | bf->unowned_mines_spots_nearby) { // not close to mountains |
48 | prio -= std::abs(management_data.get_military_number_at(104)) / 5; |
49 | } |
50 | - } |
51 | - |
52 | - else if (bo.is(BuildingAttribute::kShipyard)) { |
53 | + } else if (bo.is(BuildingAttribute::kShipyard)) { |
54 | // for now AI builds only one shipyard |
55 | assert(bo.total_count() == 0); |
56 | - if (bf->open_water_nearby > 3 && seafaring_economy) { |
57 | + if (bf->open_water_nearby > 3 && map_allows_seafaring_) { |
58 | prio += productionsites.size() * 5 + |
59 | bf->open_water_nearby * |
60 | std::abs(management_data.get_military_number_at(109)) / 10; |
61 | @@ -4253,7 +4251,7 @@ |
62 | return BuildingNecessity::kForbidden; |
63 | } |
64 | |
65 | - if (bo.is(BuildingAttribute::kPort) && !seafaring_economy) { |
66 | + if (bo.is(BuildingAttribute::kPort) && !map_allows_seafaring_) { |
67 | bo.new_building_overdue = 0; |
68 | bo.primary_priority = 0; |
69 | return BuildingNecessity::kForbidden; |
70 | @@ -4331,7 +4329,7 @@ |
71 | } |
72 | |
73 | // Perhaps buildings are not allowed because the map is no seafaring |
74 | - if (purpose == PerfEvaluation::kForConstruction && !seafaring_economy && |
75 | + if (purpose == PerfEvaluation::kForConstruction && !map_allows_seafaring_ && |
76 | bo.is(BuildingAttribute::kNeedsSeafaring)) { |
77 | return BuildingNecessity::kForbidden; |
78 | } |
79 | |
80 | === modified file 'src/ai/defaultai.h' |
81 | --- src/ai/defaultai.h 2017-11-27 21:21:06 +0000 |
82 | +++ src/ai/defaultai.h 2017-12-11 06:56:51 +0000 |
83 | @@ -385,7 +385,9 @@ |
84 | |
85 | // seafaring related |
86 | enum { kReprioritize, kStopShipyard, kStapShipyard }; |
87 | - bool seafaring_economy; // false by default, until first port space is found |
88 | + static uint32_t last_seafaring_check_; |
89 | + // False by default, until Map::allows_seafaring() is true |
90 | + static bool map_allows_seafaring_; |
91 | uint32_t expedition_ship_; |
92 | uint32_t expedition_max_duration; |
93 | std::vector<int16_t> marine_task_queue; |
94 | |
95 | === modified file 'src/ai/defaultai_seafaring.cc' |
96 | --- src/ai/defaultai_seafaring.cc 2017-11-20 07:54:19 +0000 |
97 | +++ src/ai/defaultai_seafaring.cc 2017-12-11 06:56:51 +0000 |
98 | @@ -104,8 +104,7 @@ |
99 | // - build a ship |
100 | // - start preparation for expedition |
101 | bool DefaultAI::marine_main_decisions() { |
102 | - |
103 | - if (!seafaring_economy) { |
104 | + if (!map_allows_seafaring_) { |
105 | set_taskpool_task_time(kNever, SchedulerTaskId::KMarineDecisions); |
106 | return false; |
107 | } |
108 | @@ -226,9 +225,8 @@ |
109 | |
110 | // This identifies ships that are waiting for command |
111 | bool DefaultAI::check_ships(uint32_t const gametime) { |
112 | - |
113 | - if (!seafaring_economy) { |
114 | - set_taskpool_task_time(std::numeric_limits<int32_t>::max(), SchedulerTaskId::kCheckShips); |
115 | + if (!map_allows_seafaring_) { |
116 | + set_taskpool_task_time(kNever, SchedulerTaskId::kCheckShips); |
117 | return false; |
118 | } |
119 | |
120 | @@ -402,7 +400,6 @@ |
121 | if (type == NewShip::kBuilt) { |
122 | marine_task_queue.push_back(kStopShipyard); |
123 | } else { |
124 | - seafaring_economy = true; |
125 | if (ship.state_is_expedition()) { |
126 | if (expedition_ship_ == kNoShip) { |
127 | // OK, this ship is in expedition |
128 | |
129 | === modified file 'src/editor/tools/set_port_space_tool.cc' |
130 | --- src/editor/tools/set_port_space_tool.cc 2017-09-15 19:18:08 +0000 |
131 | +++ src/editor/tools/set_port_space_tool.cc 2017-12-11 06:56:51 +0000 |
132 | @@ -65,7 +65,7 @@ |
133 | do { |
134 | // check if field is valid |
135 | if (port_tool_nodecaps(mr.location(), *map) != NodeCaps::CAPS_NONE) { |
136 | - map->set_port_space(mr.location(), true); |
137 | + map->set_port_space(world, mr.location(), true); |
138 | Area<FCoords> a(mr.location(), 0); |
139 | map->recalc_for_field_area(world, a); |
140 | ++nr; |
141 | @@ -106,7 +106,7 @@ |
142 | do { |
143 | // check if field is valid |
144 | if (port_tool_nodecaps(mr.location(), *map)) { |
145 | - map->set_port_space(mr.location(), false); |
146 | + map->set_port_space(world, mr.location(), false); |
147 | Area<FCoords> a(mr.location(), 0); |
148 | map->recalc_for_field_area(world, a); |
149 | ++nr; |
150 | |
151 | === modified file 'src/editor/ui_menus/main_menu_save_map.cc' |
152 | --- src/editor/ui_menus/main_menu_save_map.cc 2017-11-24 21:34:17 +0000 |
153 | +++ src/editor/ui_menus/main_menu_save_map.cc 2017-12-11 06:56:51 +0000 |
154 | @@ -280,6 +280,7 @@ |
155 | g_fs->create_sub_file_system(tmp_name, binary ? FileSystem::ZIP : FileSystem::DIR)); |
156 | |
157 | // Recompute seafaring tag |
158 | + map->cleanup_port_spaces(egbase.world()); |
159 | if (map->allows_seafaring()) { |
160 | map->add_tag("seafaring"); |
161 | } else { |
162 | |
163 | === modified file 'src/logic/map.cc' |
164 | --- src/logic/map.cc 2017-11-05 19:59:33 +0000 |
165 | +++ src/logic/map.cc 2017-12-11 06:56:51 +0000 |
166 | @@ -546,7 +546,7 @@ |
167 | } |
168 | } |
169 | |
170 | -NodeCaps Map::get_max_nodecaps(const World& world, const FCoords& fc) { |
171 | +NodeCaps Map::get_max_nodecaps(const World& world, const FCoords& fc) const { |
172 | NodeCaps caps = calc_nodecaps_pass1(world, fc, false); |
173 | caps = calc_nodecaps_pass2(world, fc, false, caps); |
174 | return caps; |
175 | @@ -937,7 +937,7 @@ |
176 | f.field->caps = calc_nodecaps_pass1(world, f, true); |
177 | } |
178 | |
179 | -NodeCaps Map::calc_nodecaps_pass1(const World& world, const FCoords& f, bool consider_mobs) { |
180 | +NodeCaps Map::calc_nodecaps_pass1(const World& world, const FCoords& f, bool consider_mobs) const { |
181 | uint8_t caps = CAPS_NONE; |
182 | |
183 | // 1a) Get all the neighbours to make life easier |
184 | @@ -1058,7 +1058,7 @@ |
185 | NodeCaps Map::calc_nodecaps_pass2(const World& world, |
186 | const FCoords& f, |
187 | bool consider_mobs, |
188 | - NodeCaps initcaps) { |
189 | + NodeCaps initcaps) const { |
190 | uint8_t caps = consider_mobs ? f.field->caps : static_cast<uint8_t>(initcaps); |
191 | |
192 | // NOTE This dependency on the bottom-right neighbour is the reason |
193 | @@ -1166,7 +1166,7 @@ |
194 | bool avoidnature, |
195 | bool* ismine, |
196 | bool consider_mobs, |
197 | - NodeCaps initcaps) { |
198 | + NodeCaps initcaps) const { |
199 | if (consider_mobs) { |
200 | if (!(f.field->get_caps() & MOVECAPS_WALK)) |
201 | return BaseImmovable::NONE; |
202 | @@ -1240,7 +1240,7 @@ |
203 | * The array \p dirs must have length \p length, where \p length is |
204 | * the length of the cycle. |
205 | */ |
206 | -bool Map::is_cycle_connected(const FCoords& start, uint32_t length, const WalkingDir* dirs) { |
207 | +bool Map::is_cycle_connected(const FCoords& start, uint32_t length, const WalkingDir* dirs) const { |
208 | FCoords f = start; |
209 | bool prev_walkable = start.field->get_caps() & MOVECAPS_WALK; |
210 | uint32_t alternations = 0; |
211 | @@ -1304,18 +1304,27 @@ |
212 | return portdock; |
213 | } |
214 | |
215 | +bool Map::is_port_space_allowed(const World& world, const FCoords& fc) const { |
216 | + return (get_max_nodecaps(world, fc) & BUILDCAPS_SIZEMASK) == BUILDCAPS_BIG && !find_portdock(fc).empty(); |
217 | +} |
218 | + |
219 | /// \returns true, if Coordinates are in port space list |
220 | bool Map::is_port_space(const Coords& c) const { |
221 | return port_spaces_.count(c); |
222 | } |
223 | |
224 | -/// Set or unset a space as port space |
225 | -void Map::set_port_space(Coords c, bool allowed) { |
226 | - if (allowed) { |
227 | - port_spaces_.insert(c); |
228 | +bool Map::set_port_space(const World& world, const Coords& c, bool set, bool force) { |
229 | + bool success = false; |
230 | + if (set) { |
231 | + success = force || is_port_space_allowed(world, get_fcoords(c)); |
232 | + if (success) { |
233 | + port_spaces_.insert(c); |
234 | + } |
235 | } else { |
236 | port_spaces_.erase(c); |
237 | + success = true; |
238 | } |
239 | + return success; |
240 | } |
241 | |
242 | /** |
243 | @@ -1950,60 +1959,67 @@ |
244 | check_neighbour_heights(n[i], area); |
245 | } |
246 | |
247 | -/* |
248 | -=========== |
249 | -Map::allows_seafaring() |
250 | - |
251 | -This function checks if there are two ports that are reachable |
252 | -for each other - then the map is seafaring. |
253 | -============= |
254 | -*/ |
255 | -bool Map::allows_seafaring() { |
256 | - Map::PortSpacesSet port_spaces = get_port_spaces(); |
257 | - std::vector<Coords> portdocks; |
258 | - std::set<Coords> swim_coords; |
259 | - |
260 | - for (const Coords& c : port_spaces) { |
261 | - std::queue<Coords> q_positions; |
262 | - std::set<Coords> visited_positions; |
263 | +bool Map::allows_seafaring() const { |
264 | + |
265 | + // There need to be at least 2 port spaces for seafaring to make sense |
266 | + if (get_port_spaces().size() < 2) { |
267 | + return false; |
268 | + } |
269 | + |
270 | + std::set<Coords> reachable_from_previous_ports; |
271 | + |
272 | + for (const Coords& c : get_port_spaces()) { |
273 | + std::queue<Coords> positions_to_check; |
274 | + std::set<Coords> reachable_from_current_port; |
275 | FCoords fc = get_fcoords(c); |
276 | - portdocks = find_portdock(fc); |
277 | - |
278 | - /* remove the port space if it is not longer valid port space */ |
279 | - if ((fc.field->get_caps() & BUILDCAPS_SIZEMASK) != BUILDCAPS_BIG || portdocks.empty()) { |
280 | - set_port_space(c, false); |
281 | - continue; |
282 | - } |
283 | - |
284 | - for (const Coords& portdock : portdocks) { |
285 | - visited_positions.insert(portdock); |
286 | - q_positions.push(portdock); |
287 | - } |
288 | - |
289 | - while (!q_positions.empty()) { |
290 | - const Coords& swim_coord = q_positions.front(); |
291 | - q_positions.pop(); |
292 | + |
293 | + // Get portdock slots for this port |
294 | + for (const Coords& portdock : find_portdock(fc)) { |
295 | + reachable_from_current_port.insert(portdock); |
296 | + positions_to_check.push(portdock); |
297 | + } |
298 | + |
299 | + // Pick up all positions that can be reached from the current port |
300 | + while (!positions_to_check.empty()) { |
301 | + // Take a copy, because we'll pop it |
302 | + const Coords current_position = positions_to_check.front(); |
303 | + positions_to_check.pop(); |
304 | + |
305 | + // Found one |
306 | + if (reachable_from_previous_ports.count(current_position) > 0) { |
307 | + return true; |
308 | + } |
309 | + |
310 | + // Adding the neighbors to the list |
311 | for (uint8_t i = 1; i <= 6; ++i) { |
312 | FCoords neighbour; |
313 | - get_neighbour(get_fcoords(swim_coord), i, &neighbour); |
314 | + get_neighbour(get_fcoords(current_position), i, &neighbour); |
315 | if ((neighbour.field->get_caps() & (MOVECAPS_SWIM | MOVECAPS_WALK)) == MOVECAPS_SWIM) { |
316 | - if (visited_positions.count(neighbour) == 0) { |
317 | - visited_positions.insert(neighbour); |
318 | - q_positions.push(neighbour); |
319 | + if (reachable_from_current_port.count(neighbour) == 0) { |
320 | + reachable_from_current_port.insert(neighbour); |
321 | + positions_to_check.push(neighbour); |
322 | } |
323 | } |
324 | } |
325 | } |
326 | |
327 | - for (const Coords& swim_coord : visited_positions) |
328 | - if (swim_coords.count(swim_coord) == 0) |
329 | - swim_coords.insert(swim_coord); |
330 | - else |
331 | - return true; |
332 | + // Couldn't connect to another port, so we add our reachable nodes to the list |
333 | + for (const Coords& reachable_coord : reachable_from_current_port) { |
334 | + reachable_from_previous_ports.insert(reachable_coord); |
335 | + } |
336 | } |
337 | return false; |
338 | } |
339 | |
340 | +void Map::cleanup_port_spaces(const World& world) { |
341 | + for (const Coords& c : get_port_spaces()) { |
342 | + if (!is_port_space_allowed(world, get_fcoords(c))) { |
343 | + set_port_space(world, c, false); |
344 | + continue; |
345 | + } |
346 | + } |
347 | +} |
348 | + |
349 | bool Map::has_artifacts() { |
350 | for (MapIndex i = 0; i < max_index(); ++i) { |
351 | if (upcast(Immovable, immovable, fields_[i].get_immovable())) { |
352 | |
353 | === modified file 'src/logic/map.h' |
354 | --- src/logic/map.h 2017-11-26 14:44:23 +0000 |
355 | +++ src/logic/map.h 2017-12-11 06:56:51 +0000 |
356 | @@ -270,8 +270,8 @@ |
357 | void set_scenario_player_ai(PlayerNumber, const std::string&); |
358 | void set_scenario_player_closeable(PlayerNumber, bool); |
359 | |
360 | - /// \returns the maximum theoretical possible nodecaps (no blocking bobs, etc.) |
361 | - NodeCaps get_max_nodecaps(const World& world, const FCoords&); |
362 | + /// \returns the maximum theoretical possible nodecaps (no blocking bobs, immovables etc.) |
363 | + NodeCaps get_max_nodecaps(const World& world, const FCoords&) const; |
364 | |
365 | BaseImmovable* get_immovable(const Coords&) const; |
366 | uint32_t find_bobs(const Area<FCoords>, |
367 | @@ -438,14 +438,26 @@ |
368 | /// Translate the whole map so that the given point becomes the new origin. |
369 | void set_origin(const Coords&); |
370 | |
371 | - /// Port space specific functions |
372 | + // Port space specific functions |
373 | + |
374 | + /// Checks whether the maximum theoretical possible NodeCap of the field is big, |
375 | + /// and there is room for a port space |
376 | + bool is_port_space_allowed(const World& world, const FCoords& fc) const; |
377 | bool is_port_space(const Coords& c) const; |
378 | - void set_port_space(Coords c, bool allowed); |
379 | + |
380 | + /// If 'set', set the space at 'c' as port space, otherwise unset. |
381 | + /// 'force' sets the port space even if it isn't viable, and is to be used for map loading only. |
382 | + /// Returns whether the port space was set/unset successfully. |
383 | + bool set_port_space(const World& world, const Widelands::Coords& c, bool set, bool force = false); |
384 | const PortSpacesSet& get_port_spaces() const { |
385 | return port_spaces_; |
386 | } |
387 | std::vector<Coords> find_portdock(const Widelands::Coords& c) const; |
388 | - bool allows_seafaring(); |
389 | + |
390 | + /// Check whether there are at least 2 port spaces that can be reached from each other by water |
391 | + bool allows_seafaring() const; |
392 | + /// Remove all port spaces that are not valid (Buildcap < big or not enough space for a portdock). |
393 | + void cleanup_port_spaces(const World& world); |
394 | |
395 | /// Checks whether there are any artifacts on the map |
396 | bool has_artifacts(); |
397 | @@ -458,19 +470,19 @@ |
398 | void recalc_brightness(const FCoords&); |
399 | void recalc_nodecaps_pass1(const World& world, const FCoords&); |
400 | void recalc_nodecaps_pass2(const World& world, const FCoords& f); |
401 | - NodeCaps calc_nodecaps_pass1(const World& world, const FCoords&, bool consider_mobs = true); |
402 | + NodeCaps calc_nodecaps_pass1(const World& world, const FCoords&, bool consider_mobs = true) const; |
403 | NodeCaps calc_nodecaps_pass2(const World& world, |
404 | const FCoords&, |
405 | bool consider_mobs = true, |
406 | - NodeCaps initcaps = CAPS_NONE); |
407 | + NodeCaps initcaps = CAPS_NONE) const; |
408 | void check_neighbour_heights(FCoords, uint32_t& radius); |
409 | int calc_buildsize(const World& world, |
410 | const FCoords& f, |
411 | bool avoidnature, |
412 | bool* ismine = nullptr, |
413 | bool consider_mobs = true, |
414 | - NodeCaps initcaps = CAPS_NONE); |
415 | - bool is_cycle_connected(const FCoords& start, uint32_t length, const WalkingDir* dirs); |
416 | + NodeCaps initcaps = CAPS_NONE) const; |
417 | + bool is_cycle_connected(const FCoords& start, uint32_t length, const WalkingDir* dirs) const; |
418 | template <typename functorT> |
419 | void find_reachable(const Area<FCoords>&, const CheckStep&, functorT&) const; |
420 | template <typename functorT> void find(const Area<FCoords>&, functorT&) const; |
421 | |
422 | === modified file 'src/logic/map_objects/tribes/production_program.cc' |
423 | --- src/logic/map_objects/tribes/production_program.cc 2017-11-24 21:34:17 +0000 |
424 | +++ src/logic/map_objects/tribes/production_program.cc 2017-12-11 06:56:51 +0000 |
425 | @@ -742,9 +742,9 @@ |
426 | void ProductionProgram::ActCheckMap::execute(Game& game, ProductionSite& ps) const { |
427 | switch (feature_) { |
428 | case SEAFARING: { |
429 | - if (game.map().get_port_spaces().size() > 1) |
430 | + if (game.map().allows_seafaring()) { |
431 | return ps.program_step(game, 0); |
432 | - else { |
433 | + } else { |
434 | ps.set_production_result(_("No use for ships on this map!")); |
435 | return ps.program_end(game, Failed); |
436 | } |
437 | |
438 | === modified file 'src/map_io/map_port_spaces_packet.cc' |
439 | --- src/map_io/map_port_spaces_packet.cc 2017-08-19 22:22:20 +0000 |
440 | +++ src/map_io/map_port_spaces_packet.cc 2017-12-11 06:56:51 +0000 |
441 | @@ -51,8 +51,7 @@ |
442 | |
443 | Section& s2 = prof.get_safe_section("port_spaces"); |
444 | for (uint16_t i = 0; i < num; ++i) { |
445 | - map->set_port_space( |
446 | - get_safe_coords(std::to_string(static_cast<unsigned int>(i)), ext, &s2), true); |
447 | + map->set_port_space(egbase.world(), get_safe_coords(std::to_string(static_cast<unsigned int>(i)), ext, &s2), true, true); |
448 | } |
449 | } else { |
450 | throw UnhandledVersionError("MapPortSpacesPacket", packet_version, kCurrentPacketVersion); |
451 | @@ -70,8 +69,7 @@ |
452 | s1.set_int("packet_version", kCurrentPacketVersion); |
453 | |
454 | const Map& map = egbase.map(); |
455 | - const uint16_t num = map.get_port_spaces().size(); |
456 | - s1.set_int("number_of_port_spaces", num); |
457 | + s1.set_int("number_of_port_spaces", map.get_port_spaces().size()); |
458 | |
459 | Section& s2 = prof.create_section("port_spaces"); |
460 | int i = 0; |
461 | |
462 | === modified file 'src/map_io/s2map.cc' |
463 | --- src/map_io/s2map.cc 2017-08-19 13:02:14 +0000 |
464 | +++ src/map_io/s2map.cc 2017-12-11 06:56:51 +0000 |
465 | @@ -392,7 +392,7 @@ |
466 | |
467 | map_.recalc_whole_map(egbase.world()); |
468 | |
469 | - postload_fix_conversion(egbase); |
470 | + postload_set_port_spaces(egbase.world()); |
471 | |
472 | set_state(STATE_LOADED); |
473 | |
474 | @@ -473,8 +473,9 @@ |
475 | for (int16_t x = 0; x < mapwidth; ++x, ++f, ++pc) { |
476 | uint8_t c = *pc; |
477 | // Harbour buildspace & textures - Information taken from: |
478 | - if (c & 0x40) |
479 | - map_.set_port_space(Widelands::Coords(x, y), true); |
480 | + if (c & 0x40) { |
481 | + port_spaces_to_set_.insert(Widelands::Coords(x, y)); |
482 | + } |
483 | f->set_terrain_d(terrain_converter.lookup(worldtype_, c & 0x1f)); |
484 | } |
485 | |
486 | @@ -490,8 +491,9 @@ |
487 | uint8_t c = *pc; |
488 | // Harbour buildspace & textures - Information taken from: |
489 | // http://bazaar.launchpad.net/~xaser/s25rttr/s25edit/view/head:/WLD_reference.txt |
490 | - if (c & 0x40) |
491 | - map_.set_port_space(Widelands::Coords(x, y), true); |
492 | + if (c & 0x40) { |
493 | + port_spaces_to_set_.insert(Widelands::Coords(x, y)); |
494 | + } |
495 | f->set_terrain_r(terrain_converter.lookup(worldtype_, c & 0x1f)); |
496 | } |
497 | |
498 | @@ -1041,41 +1043,25 @@ |
499 | } |
500 | } |
501 | |
502 | -/// Try to fix data, which is incompatible between S2 and Widelands |
503 | -void S2MapLoader::postload_fix_conversion(Widelands::EditorGameBase& egbase) { |
504 | - |
505 | - /* |
506 | - * 1: Try to fix port spaces |
507 | - */ |
508 | - const Widelands::Map::PortSpacesSet ports(map_.get_port_spaces()); |
509 | - const Widelands::World& world = egbase.world(); |
510 | - |
511 | - // Check if port spaces are valid |
512 | - for (const Widelands::Coords& c : ports) { |
513 | - Widelands::FCoords fc = map_.get_fcoords(c); |
514 | - Widelands::NodeCaps nc = map_.get_max_nodecaps(world, fc); |
515 | - if ((nc & Widelands::BUILDCAPS_SIZEMASK) != Widelands::BUILDCAPS_BIG || |
516 | - map_.find_portdock(fc).empty()) { |
517 | - log("Invalid port build space: "); |
518 | - map_.set_port_space(c, false); |
519 | - |
520 | - bool fixed = false; |
521 | +/// Try to fix data which is incompatible between S2 and Widelands. |
522 | +/// This is only the port space locations. |
523 | +void S2MapLoader::postload_set_port_spaces(const Widelands::World& world) { |
524 | + // Set port spaces near desired locations if possible |
525 | + for (const Widelands::Coords& coords : port_spaces_to_set_) { |
526 | + bool was_set = map_.set_port_space(world, coords, true); |
527 | + const Widelands::FCoords fc = map_.get_fcoords(coords); |
528 | + if (!was_set) { |
529 | + // Try to set a port space at alternative location |
530 | Widelands::MapRegion<Widelands::Area<Widelands::FCoords>> mr( |
531 | - map_, Widelands::Area<Widelands::FCoords>(fc, 3)); |
532 | + map_, Widelands::Area<Widelands::FCoords>(fc, 3)); |
533 | do { |
534 | - // Check whether the maximum theoretical possible NodeCap of the field is big + port |
535 | - Widelands::NodeCaps nc2 = |
536 | - map_.get_max_nodecaps(world, const_cast<Widelands::FCoords&>(mr.location())); |
537 | - if ((nc2 & Widelands::BUILDCAPS_SIZEMASK) == Widelands::BUILDCAPS_BIG && |
538 | - (!map_.find_portdock(mr.location()).empty())) { |
539 | - map_.set_port_space(Widelands::Coords(mr.location().x, mr.location().y), true); |
540 | - fixed = true; |
541 | - } |
542 | - } while (mr.advance(map_) && !fixed); |
543 | - if (!fixed) { |
544 | - log("FAILED! No alternative port buildspace for (%i, %i) found!\n", fc.x, fc.y); |
545 | - } else |
546 | - log("Fixed!\n"); |
547 | + was_set = map_.set_port_space(world, Widelands::Coords(mr.location().x, mr.location().y), true); |
548 | + } while (!was_set && mr.advance(map_)); |
549 | + } |
550 | + if (!was_set) { |
551 | + log("FAILED! No port buildspace for (%i, %i) found!\n", fc.x, fc.y); |
552 | + } else { |
553 | + log("SUCCESS! Port buildspace set for (%i, %i) \n", fc.x, fc.y); |
554 | } |
555 | } |
556 | } |
557 | |
558 | === modified file 'src/map_io/s2map.h' |
559 | --- src/map_io/s2map.h 2017-06-24 10:38:19 +0000 |
560 | +++ src/map_io/s2map.h 2017-12-11 06:56:51 +0000 |
561 | @@ -42,10 +42,11 @@ |
562 | private: |
563 | const std::string filename_; |
564 | WorldType worldtype_; |
565 | + std::set<Widelands::Coords> port_spaces_to_set_; |
566 | |
567 | void load_s2mf_header(FileRead&); |
568 | void load_s2mf(Widelands::EditorGameBase&); |
569 | - void postload_fix_conversion(Widelands::EditorGameBase&); |
570 | + void postload_set_port_spaces(const Widelands::World& world); |
571 | }; |
572 | |
573 | #endif // end of include guard: WL_MAP_IO_S2MAP_H |
574 | |
575 | === modified file 'src/scripting/lua_map.cc' |
576 | --- src/scripting/lua_map.cc 2017-11-23 23:32:40 +0000 |
577 | +++ src/scripting/lua_map.cc 2017-12-11 06:56:51 +0000 |
578 | @@ -1138,7 +1138,7 @@ |
579 | |
580 | .. class:: Map |
581 | |
582 | - Access to the map and it's objects. You cannot instantiate this directly, |
583 | + Access to the map and its objects. You cannot instantiate this directly, |
584 | instead access it via :attr:`wl.Game.map`. |
585 | */ |
586 | const char LuaMap::className[] = "Map"; |
587 | @@ -1146,9 +1146,12 @@ |
588 | METHOD(LuaMap, place_immovable), |
589 | METHOD(LuaMap, get_field), |
590 | METHOD(LuaMap, recalculate), |
591 | + METHOD(LuaMap, set_port_space), |
592 | {nullptr, nullptr}, |
593 | }; |
594 | const PropertyType<LuaMap> LuaMap::Properties[] = { |
595 | + PROP_RO(LuaMap, allows_seafaring), |
596 | + PROP_RO(LuaMap, number_of_port_spaces), |
597 | PROP_RO(LuaMap, width), |
598 | PROP_RO(LuaMap, height), |
599 | PROP_RO(LuaMap, player_slots), |
600 | @@ -1167,6 +1170,31 @@ |
601 | ========================================================== |
602 | */ |
603 | /* RST |
604 | + .. attribute:: allows_seafaring |
605 | + |
606 | + (RO) Whether the map currently allows seafaring. This will calculate a path between port spaces, |
607 | + so it's more accurate but less efficient than :any:`number_of_port_spaces`. |
608 | + |
609 | + :returns: True if there are at least two port spaces that can be reached from each other. |
610 | +*/ |
611 | +int LuaMap::get_allows_seafaring(lua_State* L) { |
612 | + lua_pushboolean(L, get_egbase(L).map().allows_seafaring()); |
613 | + return 1; |
614 | +} |
615 | +/* RST |
616 | + .. attribute:: number_of_port_spaces |
617 | + |
618 | + (RO) The amount of port spaces on the map. If this is >= 2, one can assume that the map |
619 | + allows seafaring. This is checked very quickly and is more efficient than :any:`allows_seafaring`, |
620 | + but it won't detect whether the port spaces can be reached from each other, so it's less accurate. |
621 | + |
622 | + :returns: An integer with the number of port spaces. |
623 | +*/ |
624 | +int LuaMap::get_number_of_port_spaces(lua_State* L) { |
625 | + lua_pushuint32(L, get_egbase(L).map().get_port_spaces().size()); |
626 | + return 1; |
627 | +} |
628 | +/* RST |
629 | .. attribute:: width |
630 | |
631 | (RO) The width of the map in fields. |
632 | @@ -1297,6 +1325,31 @@ |
633 | return 0; |
634 | } |
635 | |
636 | +/* RST |
637 | + .. method:: set_port_space(x, y, allowed) |
638 | + |
639 | + Sets whether a port space is allowed at the coordinates (x, y). |
640 | + Returns false if the port space couldn't be set. |
641 | + |
642 | + :arg x: The x coordinate of the port space to set/unset. |
643 | + :type x: :class:`int` |
644 | + :arg y: The y coordinate of the port space to set/unset. |
645 | + :type y: :class:`int` |
646 | + :arg allowed: Whether building a port will be allowed here. |
647 | + :type allowed: :class:`bool` |
648 | + |
649 | + :returns: :const:`true` on success, or :const:`false` otherwise |
650 | + :rtype: :class:`bool` |
651 | +*/ |
652 | +int LuaMap::set_port_space(lua_State* L) { |
653 | + const int x = luaL_checkint32(L, 2); |
654 | + const int y = luaL_checkint32(L, 3); |
655 | + const bool allowed = luaL_checkboolean(L, 4); |
656 | + const bool success = get_egbase(L).mutable_map()->set_port_space(get_egbase(L).world(), Widelands::Coords(x, y), allowed); |
657 | + lua_pushboolean(L, success); |
658 | + return 1; |
659 | +} |
660 | + |
661 | /* |
662 | ========================================================== |
663 | C METHODS |
664 | |
665 | === modified file 'src/scripting/lua_map.h' |
666 | --- src/scripting/lua_map.h 2017-11-28 08:57:52 +0000 |
667 | +++ src/scripting/lua_map.h 2017-12-11 06:56:51 +0000 |
668 | @@ -86,6 +86,8 @@ |
669 | /* |
670 | * Properties |
671 | */ |
672 | + int get_allows_seafaring(lua_State*); |
673 | + int get_number_of_port_spaces(lua_State*); |
674 | int get_width(lua_State*); |
675 | int get_height(lua_State*); |
676 | int get_player_slots(lua_State*); |
677 | @@ -96,6 +98,7 @@ |
678 | int place_immovable(lua_State*); |
679 | int get_field(lua_State*); |
680 | int recalculate(lua_State*); |
681 | + int set_port_space(lua_State*); |
682 | |
683 | /* |
684 | * C methods |
685 | |
686 | === modified file 'src/wui/building_statistics_menu.cc' |
687 | --- src/wui/building_statistics_menu.cc 2017-11-11 10:08:54 +0000 |
688 | +++ src/wui/building_statistics_menu.cc 2017-12-11 06:56:51 +0000 |
689 | @@ -138,8 +138,8 @@ |
690 | g_gr->images().get("images/wui/fieldaction/menu_tab_buildmine.png"), |
691 | tabs_[BuildingTab::Mines], _("Mines")); |
692 | |
693 | - // Hide the ports tab for non-seafaring maps |
694 | - if (iplayer().game().map().get_port_spaces().size() > 1) { |
695 | + // Only show the ports tab for seafaring maps |
696 | + if (iplayer().game().map().allows_seafaring()) { |
697 | tab_panel_.add("building_stats_ports", |
698 | g_gr->images().get("images/wui/fieldaction/menu_tab_buildport.png"), |
699 | tabs_[BuildingTab::Ports], _("Ports")); |
700 | |
701 | === modified file 'src/wui/fieldaction.cc' |
702 | --- src/wui/fieldaction.cc 2017-11-27 08:21:32 +0000 |
703 | +++ src/wui/fieldaction.cc 2017-12-11 06:56:51 +0000 |
704 | @@ -416,11 +416,13 @@ |
705 | // Some building types cannot be built (i.e. construction site) and not |
706 | // allowed buildings. |
707 | if (dynamic_cast<const Game*>(&ibase().egbase())) { |
708 | - if (!building_descr->is_buildable() || !player_->is_building_type_allowed(building_index)) |
709 | + if (!building_descr->is_buildable() || !player_->is_building_type_allowed(building_index)) { |
710 | continue; |
711 | + } |
712 | if (building_descr->needs_seafaring() && |
713 | - ibase().egbase().map().get_port_spaces().size() < 2) |
714 | + !ibase().egbase().map().allows_seafaring()) { |
715 | continue; |
716 | + } |
717 | } else if (!building_descr->is_buildable() && !building_descr->is_enhanced()) |
718 | continue; |
719 | |
720 | |
721 | === modified file 'test/maps/expedition.wmf/scripting/init.lua' |
722 | --- test/maps/expedition.wmf/scripting/init.lua 2017-01-17 20:57:35 +0000 |
723 | +++ test/maps/expedition.wmf/scripting/init.lua 2017-12-11 06:56:51 +0000 |
724 | @@ -2,6 +2,7 @@ |
725 | include "scripting/coroutine.lua" |
726 | include "scripting/infrastructure.lua" |
727 | include "scripting/ui.lua" |
728 | +include "test/scripting/stable_save.lua" |
729 | |
730 | -- This is a test case for bug 1234058: there is constant demand for logs, |
731 | -- so the expedition initially never got any. |
732 | @@ -53,18 +54,6 @@ |
733 | first_ship = nil |
734 | second_ship = nil |
735 | |
736 | --- Save the game so that reloading does not skip |
737 | -function stable_save(safename) |
738 | - local old_speed = game.desired_speed |
739 | - game.desired_speed = 1000 |
740 | - sleep(100) |
741 | - game:save(safename) |
742 | - game.desired_speed = 1000 |
743 | - sleep(2000) -- Give the loaded game a chance to catch up |
744 | - game.desired_speed = old_speed |
745 | - sleep(1000) |
746 | -end |
747 | - |
748 | function click_on_ship(which_ship) |
749 | local mv = wl.ui.MapView() |
750 | for x=0,map.width-1 do |
751 | @@ -211,7 +200,7 @@ |
752 | game.desired_speed = 10 * 1000 |
753 | sleep(10000) |
754 | |
755 | - stable_save("ready_to_sail") |
756 | + stable_save(game, "ready_to_sail") |
757 | |
758 | sleep(10000) |
759 | assert_equal(1, p1:get_workers("barbarians_builder")) |
760 | @@ -255,7 +244,7 @@ |
761 | assert_equal("ccw",expedition_ship.island_explore_direction) |
762 | sleep(6000) |
763 | |
764 | - stable_save("sailing") |
765 | + stable_save(game, "sailing") |
766 | assert_equal(1, p1:get_workers("barbarians_builder")) |
767 | |
768 | cancel_expedition_in_shipwindow(expedition_ship) |
769 | @@ -289,7 +278,7 @@ |
770 | sleep(500) |
771 | assert_equal(1, p1:get_workers("barbarians_builder")) |
772 | |
773 | - stable_save("reached_port_space") |
774 | + stable_save(game, "reached_port_space") |
775 | sleep(5000) |
776 | ships = p1:get_ships() |
777 | --ships table should contain 1-2 items (1-2 ships) |
778 | @@ -342,7 +331,7 @@ |
779 | sleep(500) |
780 | assert_equal(1, p1:get_workers("barbarians_builder")) |
781 | |
782 | - stable_save("port_done") |
783 | + stable_save(game, "port_done") |
784 | game.desired_speed = 25 * 1000 |
785 | |
786 | -- build a lumberjack and see if the ship starts transporting stuff |
787 | |
788 | === modified file 'test/maps/expedition.wmf/scripting/test_cancel_when_port_space_was_reached_two_ships.lua' |
789 | --- test/maps/expedition.wmf/scripting/test_cancel_when_port_space_was_reached_two_ships.lua 2015-11-04 16:48:56 +0000 |
790 | +++ test/maps/expedition.wmf/scripting/test_cancel_when_port_space_was_reached_two_ships.lua 2017-12-11 06:56:51 +0000 |
791 | @@ -27,7 +27,7 @@ |
792 | sleep(500) |
793 | assert_equal(1, p1:get_workers("barbarians_builder")) |
794 | |
795 | - stable_save("reached_port_space") |
796 | + stable_save(game, "reached_port_space") |
797 | assert_equal(1, p1:get_workers("barbarians_builder")) |
798 | |
799 | cancel_expedition_in_shipwindow(expedition_ship) |
800 | |
801 | === modified file 'test/maps/expedition.wmf/scripting/test_ship_movement_controls.lua' |
802 | --- test/maps/expedition.wmf/scripting/test_ship_movement_controls.lua 2015-12-03 21:12:12 +0000 |
803 | +++ test/maps/expedition.wmf/scripting/test_ship_movement_controls.lua 2017-12-11 06:56:51 +0000 |
804 | @@ -105,7 +105,7 @@ |
805 | sleep(500) |
806 | assert_equal("exp_colonizing", ships[1].state) |
807 | sleep(15000) |
808 | - stable_save("port_in_constr") |
809 | + stable_save(game, "port_in_constr") |
810 | |
811 | -- while unfinished yet, removing it |
812 | new_port=map:get_field(16,2).immovable |
813 | |
814 | === modified file 'test/maps/expedition.wmf/scripting/test_starting_wait_a_while_cancel.lua' |
815 | --- test/maps/expedition.wmf/scripting/test_starting_wait_a_while_cancel.lua 2015-10-31 12:11:44 +0000 |
816 | +++ test/maps/expedition.wmf/scripting/test_starting_wait_a_while_cancel.lua 2017-12-11 06:56:51 +0000 |
817 | @@ -6,7 +6,7 @@ |
818 | -- gives the builder enough time to walk over. |
819 | port:start_expedition() |
820 | sleep(50000) |
821 | - stable_save("cancel_in_port") |
822 | + stable_save(game, "cancel_in_port") |
823 | assert_equal(1, p1:get_workers("barbarians_builder")) |
824 | |
825 | port:cancel_expedition() |
826 | |
827 | === modified file 'test/maps/ship_transportation.wmf/scripting/init.lua' |
828 | --- test/maps/ship_transportation.wmf/scripting/init.lua 2016-01-28 05:24:34 +0000 |
829 | +++ test/maps/ship_transportation.wmf/scripting/init.lua 2017-12-11 06:56:51 +0000 |
830 | @@ -1,6 +1,7 @@ |
831 | include "scripting/lunit.lua" |
832 | include "scripting/coroutine.lua" |
833 | include "scripting/infrastructure.lua" |
834 | +include "test/scripting/stable_save.lua" |
835 | |
836 | game = wl.Game() |
837 | map = game.map |
838 | @@ -49,15 +50,3 @@ |
839 | |
840 | ship = p1:place_ship(map:get_field(10, 10)) |
841 | p1.see_all = true |
842 | - |
843 | --- Save the game so that reloading does not skip |
844 | -function stable_save(safename) |
845 | - local old_speed = game.desired_speed |
846 | - game.desired_speed = 1000 |
847 | - sleep(100) |
848 | - game:save(safename) |
849 | - game.desired_speed = 1000 |
850 | - sleep(2000) -- Give the loaded game a chance to catch up |
851 | - game.desired_speed = old_speed |
852 | - sleep(1000) |
853 | -end |
854 | |
855 | === modified file 'test/maps/ship_transportation.wmf/scripting/test_many_ships.lua' |
856 | --- test/maps/ship_transportation.wmf/scripting/test_many_ships.lua 2016-01-31 21:03:15 +0000 |
857 | +++ test/maps/ship_transportation.wmf/scripting/test_many_ships.lua 2017-12-11 06:56:51 +0000 |
858 | @@ -22,7 +22,7 @@ |
859 | sleep(2000) |
860 | end |
861 | |
862 | - stable_save("20_ships") |
863 | + stable_save(game, "20_ships") |
864 | |
865 | i = 0 |
866 | while i < 10 do |
867 | |
868 | === modified file 'test/maps/ship_transportation.wmf/scripting/test_rip_first_port_with_ware_in_portdock.lua' |
869 | --- test/maps/ship_transportation.wmf/scripting/test_rip_first_port_with_ware_in_portdock.lua 2015-11-03 18:52:00 +0000 |
870 | +++ test/maps/ship_transportation.wmf/scripting/test_rip_first_port_with_ware_in_portdock.lua 2017-12-11 06:56:51 +0000 |
871 | @@ -24,7 +24,7 @@ |
872 | |
873 | sleep(100) |
874 | assert_equal(p1:get_wares("blackwood"), 0) |
875 | - stable_save("port1_just_removed") |
876 | + stable_save(game, "port1_just_removed") |
877 | |
878 | sleep(5000) |
879 | |
880 | |
881 | === modified file 'test/maps/ship_transportation.wmf/scripting/test_rip_first_port_with_worker_in_portdock.lua' |
882 | --- test/maps/ship_transportation.wmf/scripting/test_rip_first_port_with_worker_in_portdock.lua 2015-11-03 18:52:00 +0000 |
883 | +++ test/maps/ship_transportation.wmf/scripting/test_rip_first_port_with_worker_in_portdock.lua 2017-12-11 06:56:51 +0000 |
884 | @@ -20,7 +20,7 @@ |
885 | |
886 | southern_port():remove() |
887 | sleep(100) |
888 | - stable_save("port1_just_removed") |
889 | + stable_save(game, "port1_just_removed") |
890 | |
891 | -- Wait till the worker runs to the warehouse. |
892 | while wh:get_workers("barbarians_builder") == 0 do |
893 | |
894 | === modified file 'test/maps/ship_transportation.wmf/scripting/test_rip_portdock_with_worker_and_ware_in_transit.lua' |
895 | --- test/maps/ship_transportation.wmf/scripting/test_rip_portdock_with_worker_and_ware_in_transit.lua 2015-11-21 11:47:05 +0000 |
896 | +++ test/maps/ship_transportation.wmf/scripting/test_rip_portdock_with_worker_and_ware_in_transit.lua 2017-12-11 06:56:51 +0000 |
897 | @@ -29,7 +29,7 @@ |
898 | |
899 | local flag_oversea = northern_port().flag |
900 | |
901 | - stable_save("restored_port") |
902 | + stable_save(game, "restored_port") |
903 | |
904 | -- remove the portdock while the blackwood is in transit. |
905 | north_port_portdock=northern_port().portdock |
906 | |
907 | === modified file 'test/maps/ship_transportation.wmf/scripting/test_rip_ports_with_ware_in_transit.lua' |
908 | --- test/maps/ship_transportation.wmf/scripting/test_rip_ports_with_ware_in_transit.lua 2015-11-03 18:52:00 +0000 |
909 | +++ test/maps/ship_transportation.wmf/scripting/test_rip_ports_with_ware_in_transit.lua 2017-12-11 06:56:51 +0000 |
910 | @@ -28,7 +28,7 @@ |
911 | southern_port():remove() |
912 | sleep(1000) |
913 | |
914 | - stable_save("no_ports") |
915 | + stable_save(game, "no_ports") |
916 | |
917 | -- There are no more ports, therefore also no fleet. The wares on the ship |
918 | -- are not accessible and should therefore not show up in the stock anymore. |
919 | |
920 | === modified file 'test/maps/ship_transportation.wmf/scripting/test_rip_ports_with_worker_in_transit.lua' |
921 | --- test/maps/ship_transportation.wmf/scripting/test_rip_ports_with_worker_in_transit.lua 2015-11-03 18:52:00 +0000 |
922 | +++ test/maps/ship_transportation.wmf/scripting/test_rip_ports_with_worker_in_transit.lua 2017-12-11 06:56:51 +0000 |
923 | @@ -28,7 +28,7 @@ |
924 | southern_port():remove() |
925 | sleep(1000) |
926 | |
927 | - stable_save("no_ports") |
928 | + stable_save(game, "no_ports") |
929 | |
930 | -- There are no more ports, therefore also no fleet. The workers on the ship |
931 | -- are not accessible and should therefore not show up in the stock anymore. |
932 | |
933 | === modified file 'test/maps/ship_transportation.wmf/scripting/test_rip_second_port_with_ware_in_portdock.lua' |
934 | --- test/maps/ship_transportation.wmf/scripting/test_rip_second_port_with_ware_in_portdock.lua 2015-11-03 18:52:00 +0000 |
935 | +++ test/maps/ship_transportation.wmf/scripting/test_rip_second_port_with_ware_in_portdock.lua 2017-12-11 06:56:51 +0000 |
936 | @@ -29,7 +29,7 @@ |
937 | northern_port():remove() |
938 | sleep(100) |
939 | |
940 | - stable_save("ware_in_portdock") |
941 | + stable_save(game, "ware_in_portdock") |
942 | |
943 | --ship has to get to the place of former upper port and then return back to the bottom port |
944 | sleep(30000) |
945 | |
946 | === modified file 'test/maps/ship_transportation.wmf/scripting/test_rip_second_port_with_worker_in_portdock.lua' |
947 | --- test/maps/ship_transportation.wmf/scripting/test_rip_second_port_with_worker_in_portdock.lua 2015-11-21 11:47:05 +0000 |
948 | +++ test/maps/ship_transportation.wmf/scripting/test_rip_second_port_with_worker_in_portdock.lua 2017-12-11 06:56:51 +0000 |
949 | @@ -38,7 +38,7 @@ |
950 | |
951 | sleep(100) |
952 | |
953 | - stable_save("worker_in_portdock") |
954 | + stable_save(game, "worker_in_portdock") |
955 | |
956 | -- Wait till a ship unloads a worked at the souther port |
957 | while (ship:get_workers("builder") == 1) do |
958 | |
959 | === modified file 'test/maps/ship_transportation.wmf/scripting/test_rip_ship_before_picking_up_transporting_ware.lua' |
960 | --- test/maps/ship_transportation.wmf/scripting/test_rip_ship_before_picking_up_transporting_ware.lua 2015-11-03 18:52:00 +0000 |
961 | +++ test/maps/ship_transportation.wmf/scripting/test_rip_ship_before_picking_up_transporting_ware.lua 2017-12-11 06:56:51 +0000 |
962 | @@ -16,10 +16,10 @@ |
963 | sleep(12000) |
964 | |
965 | -- remove the ship while the ware is in transit. |
966 | - stable_save("0_before_removing_ship") |
967 | + stable_save(game, "0_before_removing_ship") |
968 | ship:remove() |
969 | sleep(1000) |
970 | - stable_save("1_no_more_ship") |
971 | + stable_save(game, "1_no_more_ship") |
972 | |
973 | assert_equal(1, p1:get_wares("blackwood")) |
974 | -- It is not in the port (still in the dock) |
975 | |
976 | === modified file 'test/maps/ship_transportation.wmf/scripting/test_rip_ship_while_transporting_ware.lua' |
977 | --- test/maps/ship_transportation.wmf/scripting/test_rip_ship_while_transporting_ware.lua 2015-11-03 18:52:00 +0000 |
978 | +++ test/maps/ship_transportation.wmf/scripting/test_rip_ship_while_transporting_ware.lua 2017-12-11 06:56:51 +0000 |
979 | @@ -18,10 +18,10 @@ |
980 | assert_equal(p1:get_wares("blackwood"), 1) |
981 | |
982 | -- remove the ship while the ware is in transit. |
983 | - stable_save("0_before_removing_ship") |
984 | + stable_save(game, "0_before_removing_ship") |
985 | ship:remove() |
986 | sleep(1000) |
987 | - stable_save("1_no_more_ship") |
988 | + stable_save(game, "1_no_more_ship") |
989 | |
990 | -- No more blackwood. |
991 | assert_equal(p1:get_wares("blackwood"), 0) |
992 | |
993 | === added directory 'test/maps/two_ponds.wmf' |
994 | === added directory 'test/maps/two_ponds.wmf/binary' |
995 | === added file 'test/maps/two_ponds.wmf/binary/heights' |
996 | Binary files test/maps/two_ponds.wmf/binary/heights 1970-01-01 00:00:00 +0000 and test/maps/two_ponds.wmf/binary/heights 2017-12-11 06:56:51 +0000 differ |
997 | === added file 'test/maps/two_ponds.wmf/binary/mapobjects' |
998 | Binary files test/maps/two_ponds.wmf/binary/mapobjects 1970-01-01 00:00:00 +0000 and test/maps/two_ponds.wmf/binary/mapobjects 2017-12-11 06:56:51 +0000 differ |
999 | === added file 'test/maps/two_ponds.wmf/binary/resource' |
1000 | Binary files test/maps/two_ponds.wmf/binary/resource 1970-01-01 00:00:00 +0000 and test/maps/two_ponds.wmf/binary/resource 2017-12-11 06:56:51 +0000 differ |
1001 | === added file 'test/maps/two_ponds.wmf/binary/terrain' |
1002 | Binary files test/maps/two_ponds.wmf/binary/terrain 1970-01-01 00:00:00 +0000 and test/maps/two_ponds.wmf/binary/terrain 2017-12-11 06:56:51 +0000 differ |
1003 | === added file 'test/maps/two_ponds.wmf/elemental' |
1004 | --- test/maps/two_ponds.wmf/elemental 1970-01-01 00:00:00 +0000 |
1005 | +++ test/maps/two_ponds.wmf/elemental 2017-12-11 06:56:51 +0000 |
1006 | @@ -0,0 +1,12 @@ |
1007 | +# Automatically created by Widelands bzr8483[bug-1718745-allows-seafaring] (Release) |
1008 | + |
1009 | +[global] |
1010 | +packet_version="1" |
1011 | +map_w="64" |
1012 | +map_h="64" |
1013 | +nr_players="1" |
1014 | +name="Two Ponds" |
1015 | +author="Unknown" |
1016 | +descr="Test map with 2 bodies of water, with 1 port space each." |
1017 | +hint= |
1018 | +tags= |
1019 | |
1020 | === added file 'test/maps/two_ponds.wmf/minimap.png' |
1021 | Binary files test/maps/two_ponds.wmf/minimap.png 1970-01-01 00:00:00 +0000 and test/maps/two_ponds.wmf/minimap.png 2017-12-11 06:56:51 +0000 differ |
1022 | === added file 'test/maps/two_ponds.wmf/objective' |
1023 | --- test/maps/two_ponds.wmf/objective 1970-01-01 00:00:00 +0000 |
1024 | +++ test/maps/two_ponds.wmf/objective 2017-12-11 06:56:51 +0000 |
1025 | @@ -0,0 +1,4 @@ |
1026 | +# Automatically created by Widelands bzr8483[bug-1718745-allows-seafaring] (Release) |
1027 | + |
1028 | +[global] |
1029 | +packet_version="2" |
1030 | |
1031 | === added file 'test/maps/two_ponds.wmf/player_names' |
1032 | --- test/maps/two_ponds.wmf/player_names 1970-01-01 00:00:00 +0000 |
1033 | +++ test/maps/two_ponds.wmf/player_names 2017-12-11 06:56:51 +0000 |
1034 | @@ -0,0 +1,10 @@ |
1035 | +# Automatically created by Widelands bzr8483[bug-1718745-allows-seafaring] (Release) |
1036 | + |
1037 | +[global] |
1038 | +packet_version="2" |
1039 | + |
1040 | +[player_1] |
1041 | +name="Cluicheadair 1" |
1042 | +tribe="barbarians" |
1043 | +ai= |
1044 | +closeable="false" |
1045 | |
1046 | === added file 'test/maps/two_ponds.wmf/player_position' |
1047 | --- test/maps/two_ponds.wmf/player_position 1970-01-01 00:00:00 +0000 |
1048 | +++ test/maps/two_ponds.wmf/player_position 2017-12-11 06:56:51 +0000 |
1049 | @@ -0,0 +1,5 @@ |
1050 | +# Automatically created by Widelands bzr8483[bug-1718745-allows-seafaring] (Release) |
1051 | + |
1052 | +[global] |
1053 | +packet_version="2" |
1054 | +player_1="5 58" |
1055 | |
1056 | === added file 'test/maps/two_ponds.wmf/port_spaces' |
1057 | --- test/maps/two_ponds.wmf/port_spaces 1970-01-01 00:00:00 +0000 |
1058 | +++ test/maps/two_ponds.wmf/port_spaces 2017-12-11 06:56:51 +0000 |
1059 | @@ -0,0 +1,9 @@ |
1060 | +# Automatically created by Widelands bzr8483[bug-1718745-allows-seafaring] (Release) |
1061 | + |
1062 | +[global] |
1063 | +packet_version="1" |
1064 | +number_of_port_spaces="2" |
1065 | + |
1066 | +[port_spaces] |
1067 | +0="7 2" |
1068 | +1="12 24" |
1069 | |
1070 | === added directory 'test/maps/two_ponds.wmf/scripting' |
1071 | === added file 'test/maps/two_ponds.wmf/scripting/init.lua' |
1072 | --- test/maps/two_ponds.wmf/scripting/init.lua 1970-01-01 00:00:00 +0000 |
1073 | +++ test/maps/two_ponds.wmf/scripting/init.lua 2017-12-11 06:56:51 +0000 |
1074 | @@ -0,0 +1,6 @@ |
1075 | +include "scripting/coroutine.lua" |
1076 | +include "scripting/lunit.lua" |
1077 | +include "test/scripting/stable_save.lua" |
1078 | + |
1079 | +game = wl.Game() |
1080 | +map = game.map |
1081 | |
1082 | === added file 'test/maps/two_ponds.wmf/scripting/test_seafaring.lua' |
1083 | --- test/maps/two_ponds.wmf/scripting/test_seafaring.lua 1970-01-01 00:00:00 +0000 |
1084 | +++ test/maps/two_ponds.wmf/scripting/test_seafaring.lua 2017-12-11 06:56:51 +0000 |
1085 | @@ -0,0 +1,33 @@ |
1086 | +run(function() |
1087 | + -- The map in its initial state has 2 unconnected port spaces, so it should |
1088 | + -- not allow seafaring. One of the port spaces has trees on top of it. |
1089 | + assert_equal(2, map.number_of_port_spaces) |
1090 | + assert_equal(false, map.allows_seafaring) |
1091 | + |
1092 | + -- Now try to add a port space on a medium buildcap, it should fail |
1093 | + assert_equal(false, map:set_port_space(11, 9, true)) |
1094 | + assert_equal(2, map.number_of_port_spaces) |
1095 | + assert_equal(false, map.allows_seafaring) |
1096 | + |
1097 | + -- Now try to add a port space away from water, it should fail |
1098 | + assert_equal(false, map:set_port_space(18, 9, true)) |
1099 | + assert_equal(2, map.number_of_port_spaces) |
1100 | + assert_equal(false, map.allows_seafaring) |
1101 | + |
1102 | + -- Now add a connecting port space - it should succeed and we should have seafaring then |
1103 | + assert_equal(true, map:set_port_space(0, 2, true)) |
1104 | + assert_equal(3, map.number_of_port_spaces) |
1105 | + assert_equal(true, map.allows_seafaring) |
1106 | + |
1107 | + stable_save(game, "port_spaces") |
1108 | + assert_equal(3, map.number_of_port_spaces) |
1109 | + assert_equal(true, map.allows_seafaring) |
1110 | + |
1111 | + -- Remove the port space again |
1112 | + assert_equal(true, map:set_port_space(0, 2, false)) |
1113 | + assert_equal(2, map.number_of_port_spaces) |
1114 | + assert_equal(false, map.allows_seafaring) |
1115 | + |
1116 | + print("# All Tests passed.") |
1117 | + wl.ui.MapView():close() |
1118 | +end) |
1119 | |
1120 | === added file 'test/maps/two_ponds.wmf/version' |
1121 | --- test/maps/two_ponds.wmf/version 1970-01-01 00:00:00 +0000 |
1122 | +++ test/maps/two_ponds.wmf/version 2017-12-11 06:56:51 +0000 |
1123 | @@ -0,0 +1,11 @@ |
1124 | +# Automatically created by Widelands bzr8483[bug-1718745-allows-seafaring] (Release) |
1125 | + |
1126 | +[global] |
1127 | +map_source_url= |
1128 | +map_release= |
1129 | +map_creator_version="bzr8483[bug-1718745-allows-seafaring]" |
1130 | +map_version_major="0" |
1131 | +map_version_minor="1" |
1132 | +map_version_timestamp="1510038973" |
1133 | +packet_version="1" |
1134 | +packet_compatibility="1" |
1135 | |
1136 | === added directory 'test/scripting' |
1137 | === added file 'test/scripting/stable_save.lua' |
1138 | --- test/scripting/stable_save.lua 1970-01-01 00:00:00 +0000 |
1139 | +++ test/scripting/stable_save.lua 2017-12-11 06:56:51 +0000 |
1140 | @@ -0,0 +1,13 @@ |
1141 | +include "scripting/coroutine.lua" |
1142 | + |
1143 | +-- Save the game so that reloading does not skip |
1144 | +function stable_save(game, savename) |
1145 | + local old_speed = game.desired_speed |
1146 | + game.desired_speed = 1000 |
1147 | + sleep(100) |
1148 | + game:save(savename) |
1149 | + game.desired_speed = 1000 |
1150 | + sleep(2000) -- Give the loaded game a chance to catch up |
1151 | + game.desired_speed = old_speed |
1152 | + sleep(1000) |
1153 | +end |
So If I understand correctly, get_allows_ seafaring will be LUA-only, so not usable by AI?