Merge lp:~widelands-dev/widelands/ai_blocked_fields_tweaks into lp:widelands
- ai_blocked_fields_tweaks
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 8633 |
Proposed branch: | lp:~widelands-dev/widelands/ai_blocked_fields_tweaks |
Merge into: | lp:widelands |
Diff against target: |
249 lines (+121/-23) 4 files modified
src/ai/ai_help_structs.cc (+54/-2) src/ai/ai_help_structs.h (+22/-1) src/ai/defaultai.cc (+44/-19) src/ai/defaultai.h (+1/-1) |
To merge this branch: | bzr merge lp:~widelands-dev/widelands/ai_blocked_fields_tweaks |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
GunChleoc | Approve | ||
Review via email: mp+341483@code.launchpad.net |
Commit message
AI tweak - better identification of unconnectable regions based on walking algorithm. Used to keep AI from wasting attempts to build there something.
Description of the change
This improves behavior related to blocked_fields (list of fields temporarily blocked for construction of new buildable fields). Now it better calculates the region that is temporarily unconnectable and consider these blocked fields more. However, visible difference is quite small.
bunnybot (widelandsofficial) wrote : | # |
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 3295. State: passed. Details: https:/
Appveyor build 3103. State: failed. Details: https:/
GunChleoc (gunchleoc) wrote : | # |
Looks good to me - just some minor nits. Please feel free to merge once you have addressed those to your liking. Don't forget to set the commit message above ;)
TiborB (tiborb95) wrote : | # |
@Gun
How can I use imm->descr().type() to say if an immovable is PlayerImmovable?
TiborB (tiborb95) wrote : | # |
Do you mean this:
https:/
?
Is it guaranteed that type >= 40 is player immovable?
TiborB (tiborb95) wrote : | # |
Got it!
It can go once the CI is green
GunChleoc (gunchleoc) wrote : | # |
Please set a commit message on the top of this page.
TiborB (tiborb95) wrote : | # |
Sorry, I forgot, done now.....
GunChleoc (gunchleoc) wrote : | # |
Great, thanks!
@bunnybot merge
Preview Diff
1 | === modified file 'src/ai/ai_help_structs.cc' | |||
2 | --- src/ai/ai_help_structs.cc 2018-02-16 20:42:21 +0000 | |||
3 | +++ src/ai/ai_help_structs.cc 2018-03-25 16:41:13 +0000 | |||
4 | @@ -42,7 +42,7 @@ | |||
5 | 42 | 42 | ||
6 | 43 | bool CheckStepRoadAI::allowed( | 43 | bool CheckStepRoadAI::allowed( |
7 | 44 | const Map& map, FCoords start, FCoords end, int32_t, CheckStep::StepId const id) const { | 44 | const Map& map, FCoords start, FCoords end, int32_t, CheckStep::StepId const id) const { |
9 | 45 | uint8_t endcaps = player->get_buildcaps(end); | 45 | const uint8_t endcaps = player->get_buildcaps(end); |
10 | 46 | 46 | ||
11 | 47 | // we should not cross fields with road or flags (or any other immovable) | 47 | // we should not cross fields with road or flags (or any other immovable) |
12 | 48 | if ((map.get_immovable(start)) && !(id == CheckStep::stepFirst)) { | 48 | if ((map.get_immovable(start)) && !(id == CheckStep::stepFirst)) { |
13 | @@ -83,6 +83,57 @@ | |||
14 | 83 | return true; | 83 | return true; |
15 | 84 | } | 84 | } |
16 | 85 | 85 | ||
17 | 86 | |||
18 | 87 | // CheckStepOwnTerritory | ||
19 | 88 | CheckStepOwnTerritory::CheckStepOwnTerritory(Player* const pl, uint8_t const mc, bool const oe) | ||
20 | 89 | : player(pl), movecaps(mc), open_end(oe) { | ||
21 | 90 | } | ||
22 | 91 | |||
23 | 92 | // Defines when movement is allowed: | ||
24 | 93 | // 1. startfield is walkable (or it is the first step) | ||
25 | 94 | // And endfield either: | ||
26 | 95 | // 2a. is walkable | ||
27 | 96 | // 2b. has our PlayerImmovable (building or flag) | ||
28 | 97 | bool CheckStepOwnTerritory::allowed( | ||
29 | 98 | const Map& map, FCoords start, FCoords end, int32_t, CheckStep::StepId const id) const { | ||
30 | 99 | const uint8_t endcaps = player->get_buildcaps(end); | ||
31 | 100 | const uint8_t startcaps = player->get_buildcaps(start); | ||
32 | 101 | |||
33 | 102 | // We should not cross fields with road or flags (or any other immovable) | ||
34 | 103 | // Or rather we can step on it, but not go on from such field | ||
35 | 104 | if ((map.get_immovable(start)) && !(id == CheckStep::stepFirst)) { | ||
36 | 105 | return false; | ||
37 | 106 | } | ||
38 | 107 | |||
39 | 108 | // Start field must be walkable | ||
40 | 109 | if (!(startcaps & movecaps)) { | ||
41 | 110 | return false; | ||
42 | 111 | } | ||
43 | 112 | |||
44 | 113 | // Endfield can not be water | ||
45 | 114 | if (endcaps & MOVECAPS_SWIM) { | ||
46 | 115 | return false; | ||
47 | 116 | } | ||
48 | 117 | |||
49 | 118 | return true; | ||
50 | 119 | } | ||
51 | 120 | |||
52 | 121 | // We accept either walkable territory or field with own immovable | ||
53 | 122 | bool CheckStepOwnTerritory::reachable_dest(const Map& map, const FCoords& dest) const { | ||
54 | 123 | const uint8_t endcaps = player->get_buildcaps(dest); | ||
55 | 124 | if (BaseImmovable const* const imm = map.get_immovable(dest)) { | ||
56 | 125 | if (imm->descr().type() >= MapObjectType::FLAG) { | ||
57 | 126 | return true; | ||
58 | 127 | } else { | ||
59 | 128 | return false; | ||
60 | 129 | } | ||
61 | 130 | } | ||
62 | 131 | if (endcaps & MOVECAPS_WALK) { | ||
63 | 132 | return true; | ||
64 | 133 | } | ||
65 | 134 | return false; | ||
66 | 135 | } | ||
67 | 136 | |||
68 | 86 | // We are looking for fields we can walk on | 137 | // We are looking for fields we can walk on |
69 | 87 | // and owned by hostile player. | 138 | // and owned by hostile player. |
70 | 88 | FindNodeEnemy::FindNodeEnemy(Player* p, Game& g) : player(p), game(g) { | 139 | FindNodeEnemy::FindNodeEnemy(Player* p, Game& g) : player(p), game(g) { |
71 | @@ -296,7 +347,8 @@ | |||
72 | 296 | } | 347 | } |
73 | 297 | 348 | ||
74 | 298 | EconomyObserver::EconomyObserver(Widelands::Economy& e) : economy(e) { | 349 | EconomyObserver::EconomyObserver(Widelands::Economy& e) : economy(e) { |
76 | 299 | dismantle_grace_time = std::numeric_limits<int32_t>::max(); | 350 | dismantle_grace_time = std::numeric_limits<uint32_t>::max(); |
77 | 351 | fields_block_last_time = 0; | ||
78 | 300 | } | 352 | } |
79 | 301 | 353 | ||
80 | 302 | int32_t BuildingObserver::total_count() const { | 354 | int32_t BuildingObserver::total_count() const { |
81 | 303 | 355 | ||
82 | === modified file 'src/ai/ai_help_structs.h' | |||
83 | --- src/ai/ai_help_structs.h 2018-03-03 20:46:01 +0000 | |||
84 | +++ src/ai/ai_help_structs.h 2018-03-25 16:41:13 +0000 | |||
85 | @@ -133,6 +133,21 @@ | |||
86 | 133 | Player* player; | 133 | Player* player; |
87 | 134 | uint8_t movecaps; | 134 | uint8_t movecaps; |
88 | 135 | bool open_end; | 135 | bool open_end; |
89 | 136 | |||
90 | 137 | }; | ||
91 | 138 | |||
92 | 139 | // Used to walk ower own territory, on fields that are walkable (or as given by mc) | ||
93 | 140 | // plus one step more to a field with own immovable. So that also flags and buildings are | ||
94 | 141 | // included in resulting list | ||
95 | 142 | struct CheckStepOwnTerritory { | ||
96 | 143 | CheckStepOwnTerritory(Player* const pl, uint8_t const mc, bool const oe); | ||
97 | 144 | |||
98 | 145 | bool allowed(const Map&, FCoords start, FCoords end, int32_t dir, CheckStep::StepId) const; | ||
99 | 146 | bool reachable_dest(const Map&, const FCoords& dest) const; | ||
100 | 147 | |||
101 | 148 | Player* player; | ||
102 | 149 | uint8_t movecaps; | ||
103 | 150 | bool open_end; | ||
104 | 136 | }; | 151 | }; |
105 | 137 | 152 | ||
106 | 138 | // We are looking for fields we can walk on | 153 | // We are looking for fields we can walk on |
107 | @@ -249,6 +264,11 @@ | |||
108 | 249 | bool accept(const Map&, FCoords) const; | 264 | bool accept(const Map&, FCoords) const; |
109 | 250 | }; | 265 | }; |
110 | 251 | 266 | ||
111 | 267 | // Accepts any field | ||
112 | 268 | struct FindNodeAcceptAll { | ||
113 | 269 | bool accept(const Map&, FCoords) const {return true;}; | ||
114 | 270 | }; | ||
115 | 271 | |||
116 | 252 | struct NearFlag { | 272 | struct NearFlag { |
117 | 253 | // ordering nearflags by biggest reduction | 273 | // ordering nearflags by biggest reduction |
118 | 254 | struct CompareShortening { | 274 | struct CompareShortening { |
119 | @@ -387,7 +407,8 @@ | |||
120 | 387 | 407 | ||
121 | 388 | Widelands::Economy& economy; | 408 | Widelands::Economy& economy; |
122 | 389 | std::deque<Widelands::Flag const*> flags; | 409 | std::deque<Widelands::Flag const*> flags; |
124 | 390 | int32_t dismantle_grace_time; | 410 | uint32_t dismantle_grace_time; |
125 | 411 | uint32_t fields_block_last_time; | ||
126 | 391 | }; | 412 | }; |
127 | 392 | 413 | ||
128 | 393 | struct BuildingObserver { | 414 | struct BuildingObserver { |
129 | 394 | 415 | ||
130 | === modified file 'src/ai/defaultai.cc' | |||
131 | --- src/ai/defaultai.cc 2018-03-03 20:46:01 +0000 | |||
132 | +++ src/ai/defaultai.cc 2018-03-25 16:41:13 +0000 | |||
133 | @@ -2069,9 +2069,15 @@ | |||
134 | 2069 | for (int32_t i = 0; i < 4; ++i) | 2069 | for (int32_t i = 0; i < 4; ++i) |
135 | 2070 | spots_avail.at(i) = 0; | 2070 | spots_avail.at(i) = 0; |
136 | 2071 | 2071 | ||
137 | 2072 | // We calculate owned buildable spots, of course ignoring ones that are blocked | ||
138 | 2073 | // for now | ||
139 | 2072 | for (std::deque<BuildableField*>::iterator i = buildable_fields.begin(); | 2074 | for (std::deque<BuildableField*>::iterator i = buildable_fields.begin(); |
141 | 2073 | i != buildable_fields.end(); ++i) | 2075 | i != buildable_fields.end(); ++i) { |
142 | 2076 | if (blocked_fields.is_blocked((*i)->coords)) { | ||
143 | 2077 | continue; | ||
144 | 2078 | } | ||
145 | 2074 | ++spots_avail.at((*i)->coords.field->nodecaps() & BUILDCAPS_SIZEMASK); | 2079 | ++spots_avail.at((*i)->coords.field->nodecaps() & BUILDCAPS_SIZEMASK); |
146 | 2080 | } | ||
147 | 2075 | 2081 | ||
148 | 2076 | spots_ = spots_avail.at(BUILDCAPS_SMALL); | 2082 | spots_ = spots_avail.at(BUILDCAPS_SMALL); |
149 | 2077 | spots_ += spots_avail.at(BUILDCAPS_MEDIUM); | 2083 | spots_ += spots_avail.at(BUILDCAPS_MEDIUM); |
150 | @@ -3549,7 +3555,7 @@ | |||
151 | 3549 | bool DefaultAI::create_shortcut_road(const Flag& flag, | 3555 | bool DefaultAI::create_shortcut_road(const Flag& flag, |
152 | 3550 | uint16_t checkradius, | 3556 | uint16_t checkradius, |
153 | 3551 | int16_t min_reduction, | 3557 | int16_t min_reduction, |
155 | 3552 | int32_t gametime) { | 3558 | uint32_t gametime) { |
156 | 3553 | 3559 | ||
157 | 3554 | // Increasing the failed_connection_tries counter | 3560 | // Increasing the failed_connection_tries counter |
158 | 3555 | // At the same time it indicates a time an economy is without a warehouse | 3561 | // At the same time it indicates a time an economy is without a warehouse |
159 | @@ -3561,8 +3567,8 @@ | |||
160 | 3561 | // this should not happen, but if the economy has a warehouse and a dismantle | 3567 | // this should not happen, but if the economy has a warehouse and a dismantle |
161 | 3562 | // grace time set, we must 'zero' the dismantle grace time | 3568 | // grace time set, we must 'zero' the dismantle grace time |
162 | 3563 | if (!flag.get_economy()->warehouses().empty() && | 3569 | if (!flag.get_economy()->warehouses().empty() && |
165 | 3564 | eco->dismantle_grace_time != std::numeric_limits<int32_t>::max()) { | 3570 | eco->dismantle_grace_time != std::numeric_limits<uint32_t>::max()) { |
166 | 3565 | eco->dismantle_grace_time = std::numeric_limits<int32_t>::max(); | 3571 | eco->dismantle_grace_time = std::numeric_limits<uint32_t>::max(); |
167 | 3566 | } | 3572 | } |
168 | 3567 | 3573 | ||
169 | 3568 | // first we deal with situations when this is economy with no warehouses | 3574 | // first we deal with situations when this is economy with no warehouses |
170 | @@ -3583,12 +3589,12 @@ | |||
171 | 3583 | 3589 | ||
172 | 3584 | // if we are within grace time, it is OK, just go on | 3590 | // if we are within grace time, it is OK, just go on |
173 | 3585 | if (eco->dismantle_grace_time > gametime && | 3591 | if (eco->dismantle_grace_time > gametime && |
175 | 3586 | eco->dismantle_grace_time != std::numeric_limits<int32_t>::max()) { | 3592 | eco->dismantle_grace_time != std::numeric_limits<uint32_t>::max()) { |
176 | 3587 | ; | 3593 | ; |
177 | 3588 | 3594 | ||
178 | 3589 | // if grace time is not set, this is probably first time without a warehouse and we must | 3595 | // if grace time is not set, this is probably first time without a warehouse and we must |
179 | 3590 | // set it | 3596 | // set it |
181 | 3591 | } else if (eco->dismantle_grace_time == std::numeric_limits<int32_t>::max()) { | 3597 | } else if (eco->dismantle_grace_time == std::numeric_limits<uint32_t>::max()) { |
182 | 3592 | 3598 | ||
183 | 3593 | // constructionsites | 3599 | // constructionsites |
184 | 3594 | if (upcast(ConstructionSite const, constructionsite, flag.get_building())) { | 3600 | if (upcast(ConstructionSite const, constructionsite, flag.get_building())) { |
185 | @@ -3827,19 +3833,38 @@ | |||
186 | 3827 | game().send_player_build_road(player_number(), path); | 3833 | game().send_player_build_road(player_number(), path); |
187 | 3828 | return true; | 3834 | return true; |
188 | 3829 | } | 3835 | } |
202 | 3830 | // if all possible roads skipped | 3836 | // We can't build a road so let's block the vicinity as an indication this area is not connectible |
203 | 3831 | if (last_attempt_) { | 3837 | // Usually we block for 2 minutes, but if it is a last attempt we block for 10 minutes |
204 | 3832 | Building* bld = flag.get_building(); | 3838 | // Note: we block the vicinity only if this economy (usually a sole flag with a building) is not |
205 | 3833 | // first we block the field and vicinity for 15 minutes, probably it is not a good place to | 3839 | // connected to a warehouse |
206 | 3834 | // build on | 3840 | if (flag.get_economy()->warehouses().empty()) { |
207 | 3835 | MapRegion<Area<FCoords>> mr(map, Area<FCoords>(map.get_fcoords(bld->get_position()), 2)); | 3841 | |
208 | 3836 | do { | 3842 | // blocking only if latest block was less then 60 seconds ago or it is last attempt |
209 | 3837 | blocked_fields.add(mr.location(), game().get_gametime() + 15 * 60 * 1000); | 3843 | if (eco->fields_block_last_time + 60000 < gametime || last_attempt_) { |
210 | 3838 | } while (mr.advance(map)); | 3844 | eco->fields_block_last_time = gametime; |
211 | 3839 | remove_from_dqueue<Widelands::Flag>(eco->flags, &flag); | 3845 | |
212 | 3840 | game().send_player_bulldoze(*const_cast<Flag*>(&flag)); | 3846 | const uint32_t block_time = last_attempt_ ? 10 * 60 * 1000 : 2 * 60 * 1000; |
213 | 3841 | dead_ends_check_ = true; | 3847 | |
214 | 3842 | return true; | 3848 | FindNodeAcceptAll buildable_functor; |
215 | 3849 | CheckStepOwnTerritory check_own(player_, MOVECAPS_WALK, true); | ||
216 | 3850 | |||
217 | 3851 | // get all flags within radius | ||
218 | 3852 | std::vector<Coords> reachable_to_block; | ||
219 | 3853 | map.find_reachable_fields(Area<FCoords>(map.get_fcoords(flag.get_position()), checkradius), | ||
220 | 3854 | &reachable_to_block, check_own, buildable_functor); | ||
221 | 3855 | |||
222 | 3856 | for (auto coords : reachable_to_block) { | ||
223 | 3857 | blocked_fields.add(coords, game().get_gametime() + block_time); | ||
224 | 3858 | } | ||
225 | 3859 | } | ||
226 | 3860 | |||
227 | 3861 | // If it last attempt we also destroy the flag (with a building if any attached) | ||
228 | 3862 | if (last_attempt_) { | ||
229 | 3863 | remove_from_dqueue<Widelands::Flag>(eco->flags, &flag); | ||
230 | 3864 | game().send_player_bulldoze(*const_cast<Flag*>(&flag)); | ||
231 | 3865 | dead_ends_check_ = true; | ||
232 | 3866 | return true; | ||
233 | 3867 | } | ||
234 | 3843 | } | 3868 | } |
235 | 3844 | return false; | 3869 | return false; |
236 | 3845 | } | 3870 | } |
237 | 3846 | 3871 | ||
238 | === modified file 'src/ai/defaultai.h' | |||
239 | --- src/ai/defaultai.h 2018-02-20 21:11:27 +0000 | |||
240 | +++ src/ai/defaultai.h 2018-03-25 16:41:13 +0000 | |||
241 | @@ -199,7 +199,7 @@ | |||
242 | 199 | bool create_shortcut_road(const Widelands::Flag&, | 199 | bool create_shortcut_road(const Widelands::Flag&, |
243 | 200 | uint16_t maxcheckradius, | 200 | uint16_t maxcheckradius, |
244 | 201 | int16_t minReduction, | 201 | int16_t minReduction, |
246 | 202 | const int32_t gametime); | 202 | const uint32_t gametime); |
247 | 203 | // trying to identify roads that might be removed | 203 | // trying to identify roads that might be removed |
248 | 204 | bool dispensable_road_test(const Widelands::Road&); | 204 | bool dispensable_road_test(const Widelands::Road&); |
249 | 205 | bool dismantle_dead_ends(); | 205 | bool dismantle_dead_ends(); |
Continuous integration builds have changed state:
Travis build 3294. State: failed. Details: https:/ /travis- ci.org/ widelands/ widelands/ builds/ 354043229. /ci.appveyor. com/project/ widelands- dev/widelands/ build/_ widelands_ dev_widelands_ ai_blocked_ fields_ tweaks- 3102.
Appveyor build 3102. State: failed. Details: https:/