Merge lp:~widelands-dev/widelands/ai_blocked_fields_tweaks into lp:widelands

Proposed by TiborB
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
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.

To post a comment you must log in.
Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 3294. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/354043229.
Appveyor build 3102. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ai_blocked_fields_tweaks-3102.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 3295. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/354209658.
Appveyor build 3103. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ai_blocked_fields_tweaks-3103.

Revision history for this message
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 ;)

review: Approve
Revision history for this message
TiborB (tiborb95) wrote :

@Gun
How can I use imm->descr().type() to say if an immovable is PlayerImmovable?

Revision history for this message
TiborB (tiborb95) wrote :

Do you mean this:
https://bazaar.launchpad.net/~widelands-dev/widelands/trunk/view/head:/src/logic/map_objects/map_object.h#L58
?

Is it guaranteed that type >= 40 is player immovable?

Revision history for this message
TiborB (tiborb95) wrote :

Got it!
It can go once the CI is green

Revision history for this message
GunChleoc (gunchleoc) wrote :

Please set a commit message on the top of this page.

Revision history for this message
TiborB (tiborb95) wrote :

Sorry, I forgot, done now.....

Revision history for this message
GunChleoc (gunchleoc) wrote :

Great, thanks!

@bunnybot merge

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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
6 bool CheckStepRoadAI::allowed(
7 const Map& map, FCoords start, FCoords end, int32_t, CheckStep::StepId const id) const {
8- uint8_t endcaps = player->get_buildcaps(end);
9+ const uint8_t endcaps = player->get_buildcaps(end);
10
11 // we should not cross fields with road or flags (or any other immovable)
12 if ((map.get_immovable(start)) && !(id == CheckStep::stepFirst)) {
13@@ -83,6 +83,57 @@
14 return true;
15 }
16
17+
18+// CheckStepOwnTerritory
19+CheckStepOwnTerritory::CheckStepOwnTerritory(Player* const pl, uint8_t const mc, bool const oe)
20+ : player(pl), movecaps(mc), open_end(oe) {
21+}
22+
23+// Defines when movement is allowed:
24+// 1. startfield is walkable (or it is the first step)
25+// And endfield either:
26+// 2a. is walkable
27+// 2b. has our PlayerImmovable (building or flag)
28+bool CheckStepOwnTerritory::allowed(
29+ const Map& map, FCoords start, FCoords end, int32_t, CheckStep::StepId const id) const {
30+ const uint8_t endcaps = player->get_buildcaps(end);
31+ const uint8_t startcaps = player->get_buildcaps(start);
32+
33+ // We should not cross fields with road or flags (or any other immovable)
34+ // Or rather we can step on it, but not go on from such field
35+ if ((map.get_immovable(start)) && !(id == CheckStep::stepFirst)) {
36+ return false;
37+ }
38+
39+ // Start field must be walkable
40+ if (!(startcaps & movecaps)) {
41+ return false;
42+ }
43+
44+ // Endfield can not be water
45+ if (endcaps & MOVECAPS_SWIM) {
46+ return false;
47+ }
48+
49+ return true;
50+}
51+
52+// We accept either walkable territory or field with own immovable
53+bool CheckStepOwnTerritory::reachable_dest(const Map& map, const FCoords& dest) const {
54+ const uint8_t endcaps = player->get_buildcaps(dest);
55+ if (BaseImmovable const* const imm = map.get_immovable(dest)) {
56+ if (imm->descr().type() >= MapObjectType::FLAG) {
57+ return true;
58+ } else {
59+ return false;
60+ }
61+ }
62+ if (endcaps & MOVECAPS_WALK) {
63+ return true;
64+ }
65+ return false;
66+}
67+
68 // We are looking for fields we can walk on
69 // and owned by hostile player.
70 FindNodeEnemy::FindNodeEnemy(Player* p, Game& g) : player(p), game(g) {
71@@ -296,7 +347,8 @@
72 }
73
74 EconomyObserver::EconomyObserver(Widelands::Economy& e) : economy(e) {
75- dismantle_grace_time = std::numeric_limits<int32_t>::max();
76+ dismantle_grace_time = std::numeric_limits<uint32_t>::max();
77+ fields_block_last_time = 0;
78 }
79
80 int32_t BuildingObserver::total_count() const {
81
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 Player* player;
87 uint8_t movecaps;
88 bool open_end;
89+
90+};
91+
92+// Used to walk ower own territory, on fields that are walkable (or as given by mc)
93+// plus one step more to a field with own immovable. So that also flags and buildings are
94+// included in resulting list
95+struct CheckStepOwnTerritory {
96+ CheckStepOwnTerritory(Player* const pl, uint8_t const mc, bool const oe);
97+
98+ bool allowed(const Map&, FCoords start, FCoords end, int32_t dir, CheckStep::StepId) const;
99+ bool reachable_dest(const Map&, const FCoords& dest) const;
100+
101+ Player* player;
102+ uint8_t movecaps;
103+ bool open_end;
104 };
105
106 // We are looking for fields we can walk on
107@@ -249,6 +264,11 @@
108 bool accept(const Map&, FCoords) const;
109 };
110
111+// Accepts any field
112+struct FindNodeAcceptAll {
113+ bool accept(const Map&, FCoords) const {return true;};
114+};
115+
116 struct NearFlag {
117 // ordering nearflags by biggest reduction
118 struct CompareShortening {
119@@ -387,7 +407,8 @@
120
121 Widelands::Economy& economy;
122 std::deque<Widelands::Flag const*> flags;
123- int32_t dismantle_grace_time;
124+ uint32_t dismantle_grace_time;
125+ uint32_t fields_block_last_time;
126 };
127
128 struct BuildingObserver {
129
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 for (int32_t i = 0; i < 4; ++i)
135 spots_avail.at(i) = 0;
136
137+ // We calculate owned buildable spots, of course ignoring ones that are blocked
138+ // for now
139 for (std::deque<BuildableField*>::iterator i = buildable_fields.begin();
140- i != buildable_fields.end(); ++i)
141+ i != buildable_fields.end(); ++i) {
142+ if (blocked_fields.is_blocked((*i)->coords)) {
143+ continue;
144+ }
145 ++spots_avail.at((*i)->coords.field->nodecaps() & BUILDCAPS_SIZEMASK);
146+ }
147
148 spots_ = spots_avail.at(BUILDCAPS_SMALL);
149 spots_ += spots_avail.at(BUILDCAPS_MEDIUM);
150@@ -3549,7 +3555,7 @@
151 bool DefaultAI::create_shortcut_road(const Flag& flag,
152 uint16_t checkradius,
153 int16_t min_reduction,
154- int32_t gametime) {
155+ uint32_t gametime) {
156
157 // Increasing the failed_connection_tries counter
158 // At the same time it indicates a time an economy is without a warehouse
159@@ -3561,8 +3567,8 @@
160 // this should not happen, but if the economy has a warehouse and a dismantle
161 // grace time set, we must 'zero' the dismantle grace time
162 if (!flag.get_economy()->warehouses().empty() &&
163- eco->dismantle_grace_time != std::numeric_limits<int32_t>::max()) {
164- eco->dismantle_grace_time = std::numeric_limits<int32_t>::max();
165+ eco->dismantle_grace_time != std::numeric_limits<uint32_t>::max()) {
166+ eco->dismantle_grace_time = std::numeric_limits<uint32_t>::max();
167 }
168
169 // first we deal with situations when this is economy with no warehouses
170@@ -3583,12 +3589,12 @@
171
172 // if we are within grace time, it is OK, just go on
173 if (eco->dismantle_grace_time > gametime &&
174- eco->dismantle_grace_time != std::numeric_limits<int32_t>::max()) {
175+ eco->dismantle_grace_time != std::numeric_limits<uint32_t>::max()) {
176 ;
177
178 // if grace time is not set, this is probably first time without a warehouse and we must
179 // set it
180- } else if (eco->dismantle_grace_time == std::numeric_limits<int32_t>::max()) {
181+ } else if (eco->dismantle_grace_time == std::numeric_limits<uint32_t>::max()) {
182
183 // constructionsites
184 if (upcast(ConstructionSite const, constructionsite, flag.get_building())) {
185@@ -3827,19 +3833,38 @@
186 game().send_player_build_road(player_number(), path);
187 return true;
188 }
189- // if all possible roads skipped
190- if (last_attempt_) {
191- Building* bld = flag.get_building();
192- // first we block the field and vicinity for 15 minutes, probably it is not a good place to
193- // build on
194- MapRegion<Area<FCoords>> mr(map, Area<FCoords>(map.get_fcoords(bld->get_position()), 2));
195- do {
196- blocked_fields.add(mr.location(), game().get_gametime() + 15 * 60 * 1000);
197- } while (mr.advance(map));
198- remove_from_dqueue<Widelands::Flag>(eco->flags, &flag);
199- game().send_player_bulldoze(*const_cast<Flag*>(&flag));
200- dead_ends_check_ = true;
201- return true;
202+ // We can't build a road so let's block the vicinity as an indication this area is not connectible
203+ // Usually we block for 2 minutes, but if it is a last attempt we block for 10 minutes
204+ // Note: we block the vicinity only if this economy (usually a sole flag with a building) is not
205+ // connected to a warehouse
206+ if (flag.get_economy()->warehouses().empty()) {
207+
208+ // blocking only if latest block was less then 60 seconds ago or it is last attempt
209+ if (eco->fields_block_last_time + 60000 < gametime || last_attempt_) {
210+ eco->fields_block_last_time = gametime;
211+
212+ const uint32_t block_time = last_attempt_ ? 10 * 60 * 1000 : 2 * 60 * 1000;
213+
214+ FindNodeAcceptAll buildable_functor;
215+ CheckStepOwnTerritory check_own(player_, MOVECAPS_WALK, true);
216+
217+ // get all flags within radius
218+ std::vector<Coords> reachable_to_block;
219+ map.find_reachable_fields(Area<FCoords>(map.get_fcoords(flag.get_position()), checkradius),
220+ &reachable_to_block, check_own, buildable_functor);
221+
222+ for (auto coords : reachable_to_block) {
223+ blocked_fields.add(coords, game().get_gametime() + block_time);
224+ }
225+ }
226+
227+ // If it last attempt we also destroy the flag (with a building if any attached)
228+ if (last_attempt_) {
229+ remove_from_dqueue<Widelands::Flag>(eco->flags, &flag);
230+ game().send_player_bulldoze(*const_cast<Flag*>(&flag));
231+ dead_ends_check_ = true;
232+ return true;
233+ }
234 }
235 return false;
236 }
237
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 bool create_shortcut_road(const Widelands::Flag&,
243 uint16_t maxcheckradius,
244 int16_t minReduction,
245- const int32_t gametime);
246+ const uint32_t gametime);
247 // trying to identify roads that might be removed
248 bool dispensable_road_test(const Widelands::Road&);
249 bool dismantle_dead_ends();

Subscribers

People subscribed via source and target branches

to status/vote changes: