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

Proposed by SirVer
Status: Rejected
Rejected by: SirVer
Proposed branch: lp:~widelands-dev/widelands/find_attack_soldiers
Merge into: lp:widelands
Diff against target: 736 lines (+206/-168)
11 files modified
src/ai/defaultai.cc (+6/-6)
src/logic/map_objects/tribes/militarysite.cc (+68/-86)
src/logic/map_objects/tribes/militarysite.h (+6/-11)
src/logic/map_objects/tribes/production_program.cc (+2/-3)
src/logic/map_objects/tribes/soldier.cc (+6/-0)
src/logic/map_objects/tribes/soldier.h (+58/-5)
src/logic/map_objects/tribes/trainingsite.cc (+2/-5)
src/logic/map_objects/tribes/warehouse.cc (+2/-3)
src/logic/player.cc (+47/-40)
src/map_io/map_buildingdata_packet.cc (+1/-1)
src/wui/soldierlist.cc (+8/-8)
To merge this branch: bzr merge lp:~widelands-dev/widelands/find_attack_soldiers
Reviewer Review Type Date Requested Status
GunChleoc Needs Fixing
SirVer Approve
TiborB Approve
Review via email: mp+245276@code.launchpad.net

Description of the change

This patch was send to me by fk who has difficulties accessing launchpad.

I did some changes to make it compile, but I did not review nor test the changes. So I do not fully know what the code actually does, but it has something to do with better selection of soldiers on attack.

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

Just note that this is based on seafaring-ai branch. So if you merge this...

And one comment about seafaring - few days ago I left seafaring game overnight (big map, had to use speed 1x) and it crashed.

It was not under gdb and it forgot about possibility to load savegame...

So some further testing will be needed.

If somebody wants to help with this...

Revision history for this message
SirVer (sirver) wrote :

> Just note that this is based on seafaring-ai branch. So if you merge this...

My bad. Fixed by rebasing on trunk and push --overwriting.

Revision history for this message
SirVer (sirver) wrote :

I looked at this now. I think sort_soldiers should just be a std::sort with a custom comparator - the current version is fragile. That will make this patch very small.

Is somebody interested in picking up this branch? I think fk does not want to work on it anymore.

review: Needs Fixing
Revision history for this message
Martin Schmidt (martinschmidt) wrote :

Can I just push to this branch or should I use a new one?
I did not change the semnatics but rather replace the sorting by
stable_sort or partial_sort (which returns the k smallest elements but is unstable)

However, I am not sure whether an unstable sorting algorithm can cause desyncts, since the
implementation may change the result. Doing a source code search it seems that Widelands uses both, std::sort and std::stable_sort.

At the moment we need the SoldierPriority structure to distribute the attacking soldiers evenly over all military sites (in case of equal abilities)
I think the most elegant solution would be to enforce the soldiers being sorted by ability in the militarysite itself and allow a soldier to query its position.
This would allow to sort Soldiers instead of SoldierPriority and would solve all kinds of sorting problems:
- find soldiers for attacking/defending/healing (default: strongest)
- drop least suited soldier for upgrading (default: weakest)
- kicking out any soldier (by the player or for replacement/training)

And at least the above operations does not destroy the sorting.
Only new arriving soldiers would need to be inserted.
Possible replacements for std::vector<Soldier>:
- std::deque

However, this would requiere a larger modification of the source code and needs more discussing.

Revision history for this message
fk (fredkuijper) wrote :

@SirVer
Actually I am sorry for introducing this code snippet in this way, I understand that I should have done the merge, testing etcetera myself.

"sort_soldiers should just be a std::sort with a custom comparator"

Indeed, I am new to STL and haven't found a good manual about it yet. It shouldn't take that many lines as in my code.

"I think fk does not want to work on it anymore."

In a certain way you are right, I'm not really the most suitable person to do so. Actually it surprises me that no one has done this before, for an experienced programmer (with STL) it should take half an hour at most, and it is really fun to play the game this way. It is a game changer with benefits for both sides, both human and AI, that gives a more polished game experience. And even with the code in this primitive state it would already function well, I am after all an experienced programmer (but not with STL), there is not much that could go wrong and the test were promising. If I only know how to download the involved branch than I would like do the tests.

Revision history for this message
fk (fredkuijper) wrote :

@Martin
"sorted by ability in the militarysite itself"

That makes sense, for know I could say that both appproaches (mine and yours) will not collide.

Revision history for this message
Martin Schmidt (martinschmidt) wrote :

Your patch was really useful, I just changed the sorting to stl and that's it. I also tried a short game and it really makes a difference seeing soldiers coming from all military builings in range to attack instead of weaking one building totally.
Here is the patch:

=== modified file 'src/logic/player.cc'
--- src/logic/player.cc 2014-12-20 22:03:47 +0000
+++ src/logic/player.cc 2015-02-16 14:32:33 +0000
@@ -100,31 +100,26 @@
  int priority; // (strength + 1) * health - position in building.
 };

+/**
+* Find the strongest players with highest priority
+*/
+bool compare_soldiers(const SoldierPriority& a, const SoldierPriority& b) {
+ return a.priority > b.priority;
+}
+
 void sort_soldiers(std::vector<SoldierPriority>* soldiers,
- uint32_t max = std::numeric_limits<uint32_t>::max()) {
- std::vector<SoldierPriority> temp;
- SoldierPriority soldier;
- uint32_t left = soldiers->size();
-
- while (left) {
- int32_t maxlevel = -1;
- uint32_t pos = 0;
- uint32_t maxpos = 0;
- for (const SoldierPriority& soldier_priority : *soldiers) {
- const int32_t level = soldier_priority.priority;
- if (level > maxlevel) {
- maxlevel = level;
- maxpos = pos;
- soldier.soldier = soldier_priority.soldier;
- soldier.priority = level;
- }
- pos++;
- }
- temp.push_back(soldier);
- soldiers->erase(soldiers->begin() + maxpos);
- left--;
+ uint32_t max = std::numeric_limits<uint32_t>::max()) {
+ if (max >= soldiers->size()) {
+ return;
  }
- soldiers->insert(soldiers->end(), temp.begin(), temp.begin() + std::min<int>(max, temp.size()));
+
+ std::stable_sort(soldiers->begin(), soldiers->end(), compare_soldiers);
+ // Can an unstable sorting algorithm cause desyncts or are the implementations
+ // of std algorithms guaranteed to return the same (possibly non-stable)
+ // sorting? If yes, partial_sort may be favourable
+ // std::partial_sort(soldiers->begin(), soldiers->begin() + max,
+ // soldiers->end(), compare_soldiers);
+ soldiers->resize(max);
 }

 }

Revision history for this message
SirVer (sirver) wrote :

Mars, could you just push and reuse this branch please?

On my phone, will have a closer look from home or tomorrow.

> Am 16.02.2015 um 15:33 schrieb Martin Schmidt <email address hidden>:
>
> Your patch was really useful, I just changed the sorting to stl and that's it. I also tried a short game and it really makes a difference seeing soldiers coming from all military builings in range to attack instead of weaking one building totally.
> Here is the patch:
>
> === modified file 'src/logic/player.cc'
> --- src/logic/player.cc 2014-12-20 22:03:47 +0000
> +++ src/logic/player.cc 2015-02-16 14:32:33 +0000
> @@ -100,31 +100,26 @@
> int priority; // (strength + 1) * health - position in building.
> };
>
> +/**
> +* Find the strongest players with highest priority
> +*/
> +bool compare_soldiers(const SoldierPriority& a, const SoldierPriority& b) {
> + return a.priority > b.priority;
> +}
> +
> void sort_soldiers(std::vector<SoldierPriority>* soldiers,
> - uint32_t max = std::numeric_limits<uint32_t>::max()) {
> - std::vector<SoldierPriority> temp;
> - SoldierPriority soldier;
> - uint32_t left = soldiers->size();
> -
> - while (left) {
> - int32_t maxlevel = -1;
> - uint32_t pos = 0;
> - uint32_t maxpos = 0;
> - for (const SoldierPriority& soldier_priority : *soldiers) {
> - const int32_t level = soldier_priority.priority;
> - if (level > maxlevel) {
> - maxlevel = level;
> - maxpos = pos;
> - soldier.soldier = soldier_priority.soldier;
> - soldier.priority = level;
> - }
> - pos++;
> - }
> - temp.push_back(soldier);
> - soldiers->erase(soldiers->begin() + maxpos);
> - left--;
> + uint32_t max = std::numeric_limits<uint32_t>::max()) {
> + if (max >= soldiers->size()) {
> + return;
> }
> - soldiers->insert(soldiers->end(), temp.begin(), temp.begin() + std::min<int>(max, temp.size()));
> +
> + std::stable_sort(soldiers->begin(), soldiers->end(), compare_soldiers);
> + // Can an unstable sorting algorithm cause desyncts or are the implementations
> + // of std algorithms guaranteed to return the same (possibly non-stable)
> + // sorting? If yes, partial_sort may be favourable
> + // std::partial_sort(soldiers->begin(), soldiers->begin() + max,
> + // soldiers->end(), compare_soldiers);
> + soldiers->resize(max);
> }
>
> }
>
>
> --
> https://code.launchpad.net/~widelands-dev/widelands/find_attack_soldiers/+merge/245276
> You proposed lp:~widelands-dev/widelands/find_attack_soldiers for merging.

Revision history for this message
Martin Schmidt (martinschmidt) wrote :

What is the best way to proceed for establishing the invariant that soldiers in the military building have to be sorted:
- create a bug report / wishlist,
- create a blue print or
- start coding and propose a merge request ?

Revision history for this message
TiborB (tiborb95) wrote :

Generally:

- create a bug report (optional but I recommend this :) )
- start coding and create own branch
- propose merging

2015-02-18 18:09 GMT+01:00 Martin Schmidt <email address hidden>:

> What is the best way to proceed for establishing the invariant that
> soldiers in the military building have to be sorted:
> - create a bug report / wishlist,
> - create a blue print or
> - start coding and propose a merge request ?
> --
>
> https://code.launchpad.net/~widelands-dev/widelands/find_attack_soldiers/+merge/245276
> Your team Widelands Developers is subscribed to branch
> lp:~widelands-dev/widelands/find_attack_soldiers.
>
> _______________________________________________
> Mailing list: https://launchpad.net/~widelands-dev
> Post to : <email address hidden>
> Unsubscribe : https://launchpad.net/~widelands-dev
> More help : https://help.launchpad.net/ListHelp
>

Revision history for this message
SirVer (sirver) wrote :

martin, please ping this merge request when you feel it is ready. Launchpad is not sending notifications for new commits.

Revision history for this message
Martin Schmidt (martinschmidt) wrote :

ok, basic functionality is implemented, but still, a few things have to be done, e.g.
- update military site window when the user changes the soldier preference
(at the moment you have to close and open the window again to see the soldiers in the right ordering)
- make sure healthy soldiers defend when the preference is set for rookies (instead of wounded ones who have lower power and are therefore prefered)

nice to have: when upgrading soldiers/occupying a building send the best soldiers available (according to the preference set)

keeping the soldiers sorted permanently is more difficult than I expected, the soldiercontrol interface does not offer a unified way of storing them, so for military sites they are upcasted from workers each time.

Revision history for this message
SirVer (sirver) wrote :

> - update military site window when the user changes the soldier preference
(at the moment you have to close and open the window again to see the soldiers in the right ordering)

use a Boost::signal for that - i.e. the militarysite has one, and the ui can connect to it to update it whenever something is changed.

> - make sure healthy soldiers defend when the preference is set for rookies (instead of wounded ones who have lower power and are therefore prefered)

How do you want to deal with that? It sounds like you want a different sorting for this.

> nice to have: when upgrading soldiers/occupying a building send the best soldiers available (according to the preference set)

Actually that has been discussed before. It makes for an interesting strategic element when new buildings are not immediately manned with an invincible army. It gives the other player an opportunity to strike. I think this is cool and more dynamic than immediately having the best soldiers at the front.

> keeping the soldiers sorted permanently is more difficult than I expected, the soldiercontrol interface does not offer a unified way of storing them, so for military sites they are upcasted from workers each time.

Why not change that? Remove the soldier control interface and instead make a HasSoldier container that can be owned by a building and handles all soldiers in the building. This gets rid of some inheritance which is usually bad and will solve your case. Just a suggestion of course.

Is this branch ready for review/merging now or do you still want to work on it?

Revision history for this message
TiborB (tiborb95) wrote :

I second SirVer's question: Is this branch ready for review/merging now or do you still want to work on it?

It seems there is some work to do here yet.

Revision history for this message
Martin Schmidt (martinschmidt) wrote :

I guess it is ready to merge.
What is implemented:
 - defend with "strongest", attack with "strongest"
 - drop "weakest", but only unwounded soldiers (because wounded soldiers will heal)
I am quite happy with how it works and feels playing with this branch.

What is missing:
 - the list of soldiers in a militarysite is not updated until the windows of the militarysite is
   closed and opened again (this is neccessary when new soldiers arrive, soldiers return from battle,
   soldiers are drop or the priority (weakest/strongest) for a militarysite is changed.
I tried to implement this, however I have no idea how to do this and give up on this.
But you are right, I should have responeded earlier.

"weak" and "strong" refers to the chosen priority.
For priority weak, weak soldiers are "strong".

Revision history for this message
TiborB (tiborb95) wrote :

" the list of soldiers in a militarysite is not updated until the windows of the militarysite is..." - this would be very useful, but personally I am not able to help with this :(

Revision history for this message
GunChleoc (gunchleoc) wrote :

Can you create a bug report for this, so we can take care of it in a separate branch? I have worked with signals before on the UI and might be able to figure it out, so I would put it on my todo-list.

Revision history for this message
Martin Schmidt (martinschmidt) wrote :

I will create a bug report as soon as this branch is merged.

Revision history for this message
TiborB (tiborb95) wrote :

I looked at the code and run some AI-only game - no problems. I think it can go.

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

Is this waiting only for a volunteer who would merge it to trunk? I can do it....

Revision history for this message
GunChleoc (gunchleoc) wrote :

We still have a reviewer saying "Needs fixing", which is why I didn't merge it yet. Let's wait for SirVer to get back.

Revision history for this message
SirVer (sirver) wrote :

sorry - did not see that.

review: Approve
Revision history for this message
GunChleoc (gunchleoc) wrote :

I just found that this breaks the regression tests. The problem is with test/maps/lua_testsuite.wmf/scripting/test_lua_in_game.lua. The failing test is function militarysite_tests:test_no_space().

review: Needs Fixing
Revision history for this message
Martin Schmidt (martinschmidt) wrote :

ok, thanks, I will look into this

Revision history for this message
bunnybot (widelandsofficial) wrote :

Hi, I am bunnybot (https://github.com/widelands/bunnybot).

I am keeping the source branch lp:~widelands-dev/widelands/find_attack_soldiers mirrored to
  https://github.com/widelands/widelands/tree/_widelands_dev_widelands_find_attack_soldiers

The latest continuous integration build can always be found here:
  https://travis-ci.org/widelands/widelands/branches
Please do not merge without making sure that it passes.

You can give me commands by starting a line with @bunnybot <command>. I understand:
 merge: Merges the source branch into the target branch, closing the pull request.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Travis build 126 has changed state to: failed. Details: https://travis-ci.org/widelands/widelands/builds/99797556.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Travis build 126 has changed state to: failed. Details: https://travis-ci.org/widelands/widelands/builds/99797556.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Travis build 126 has changed state to: failed. Details: https://travis-ci.org/widelands/widelands/builds/99797556.

Revision history for this message
SirVer (sirver) wrote :

I do not feel like going over this and clean it up. I do not understand most of the intentions.

Martin, are you still interested to work on this? Otherwise I will drop this branch in a few days.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Bunnybot encountered an error while working on this merge proposal:

<urlopen error [Errno -2] Name or service not known>

Revision history for this message
bunnybot (widelandsofficial) wrote :

Bunnybot encountered an error while working on this merge proposal:

<urlopen error [Errno -2] Name or service not known>

Revision history for this message
bunnybot (widelandsofficial) wrote :

Bunnybot encountered an error while working on this merge proposal:

<urlopen error [Errno -2] Name or service not known>

Revision history for this message
bunnybot (widelandsofficial) wrote :

Bunnybot encountered an error while working on this merge proposal:

<urlopen error [Errno -2] Name or service not known>

Revision history for this message
Martin Schmidt (martinschmidt) wrote :

> I do not feel like going over this and clean it up. I do not understand most
> of the intentions.
>
> Martin, are you still interested to work on this? Otherwise I will drop this
> branch in a few days.

You can delete this branch, I had too much trouble with it.

Revision history for this message
SirVer (sirver) wrote :

Abandoning this then.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/ai/defaultai.cc'
--- src/ai/defaultai.cc 2016-01-18 19:35:25 +0000
+++ src/ai/defaultai.cc 2016-01-24 08:32:15 +0000
@@ -4342,9 +4342,9 @@
4342 if (ms->economy().warehouses().size()) {4342 if (ms->economy().warehouses().size()) {
4343 uint32_t const j = ms->soldier_capacity();4343 uint32_t const j = ms->soldier_capacity();
43444344
4345 if (MilitarySite::kPrefersRookies != ms->get_soldier_preference()) {4345 if (Soldier::kPrefersRookies != ms->get_soldier_preference()) {
4346 game().send_player_militarysite_set_soldier_preference(4346 game().send_player_militarysite_set_soldier_preference(
4347 *ms, MilitarySite::kPrefersRookies);4347 *ms, Soldier::kPrefersRookies);
4348 } else if (j > 1) {4348 } else if (j > 1) {
4349 game().send_player_change_soldier_capacity(*ms, (j > 2) ? -2 : -1);4349 game().send_player_change_soldier_capacity(*ms, (j > 2) ? -2 : -1);
4350 }4350 }
@@ -4400,9 +4400,9 @@
4400 changed = true;4400 changed = true;
44014401
4402 // and also set preference to Heroes4402 // and also set preference to Heroes
4403 if (MilitarySite::kPrefersHeroes != ms->get_soldier_preference()) {4403 if (Soldier::kPrefersHeroes != ms->get_soldier_preference()) {
4404 game().send_player_militarysite_set_soldier_preference(4404 game().send_player_militarysite_set_soldier_preference(
4405 *ms, MilitarySite::kPrefersHeroes);4405 *ms, Soldier::kPrefersHeroes);
4406 changed = true;4406 changed = true;
4407 }4407 }
44084408
@@ -4411,9 +4411,9 @@
4411 } else { // otherwise decrease soldiers4411 } else { // otherwise decrease soldiers
4412 uint32_t const j = ms->soldier_capacity();4412 uint32_t const j = ms->soldier_capacity();
44134413
4414 if (MilitarySite::kPrefersRookies != ms->get_soldier_preference()) {4414 if (Soldier::kPrefersRookies != ms->get_soldier_preference()) {
4415 game().send_player_militarysite_set_soldier_preference(4415 game().send_player_militarysite_set_soldier_preference(
4416 *ms, MilitarySite::kPrefersRookies);4416 *ms, Soldier::kPrefersRookies);
4417 } else if (j > 1) {4417 } else if (j > 1) {
4418 game().send_player_change_soldier_capacity(*ms, (j > 2) ? -2 : -1);4418 game().send_player_change_soldier_capacity(*ms, (j > 2) ? -2 : -1);
4419 }4419 }
44204420
=== modified file 'src/logic/map_objects/tribes/militarysite.cc'
--- src/logic/map_objects/tribes/militarysite.cc 2016-01-06 19:11:20 +0000
+++ src/logic/map_objects/tribes/militarysite.cc 2016-01-24 08:32:15 +0000
@@ -19,6 +19,7 @@
1919
20#include "logic/map_objects/tribes/militarysite.h"20#include "logic/map_objects/tribes/militarysite.h"
2121
22#include <algorithm>
22#include <clocale>23#include <clocale>
23#include <cstdio>24#include <cstdio>
24#include <memory>25#include <memory>
@@ -88,26 +89,22 @@
88=============================89=============================
89*/90*/
9091
91MilitarySite::MilitarySite(const MilitarySiteDescr & ms_descr) :92MilitarySite::MilitarySite(const MilitarySiteDescr& ms_descr) :
92Building(ms_descr),93Building(ms_descr),
93m_didconquer (false),94m_didconquer(false),
94m_capacity (ms_descr.get_max_number_of_soldiers()),95m_capacity(ms_descr.get_max_number_of_soldiers()),
95m_nexthealtime(0),96m_soldier_preference(ms_descr.m_prefers_heroes_at_start ? Soldier::kPrefersHeroes : Soldier::kPrefersRookies),
96m_soldier_preference(ms_descr.m_prefers_heroes_at_start ? kPrefersHeroes : kPrefersRookies),97m_next_swap_soldiers_time(0),
97m_soldier_upgrade_try(false),98m_soldier_upgrade_try(false),
98m_doing_upgrade_request(false)99m_doing_upgrade_request(false)
99{100{
100 m_next_swap_soldiers_time = 0;
101}101}
102102
103103MilitarySite::~MilitarySite() {
104MilitarySite::~MilitarySite()
105{
106 assert(!m_normal_soldier_request);104 assert(!m_normal_soldier_request);
107 assert(!m_upgrade_soldier_request);105 assert(!m_upgrade_soldier_request);
108}106}
109107
110
111/**108/**
112===============109===============
113Display number of soldiers.110Display number of soldiers.
@@ -275,34 +272,33 @@
275 return 0;272 return 0;
276}273}
277274
278
279/*275/*
280 * Returns the least wanted soldier -- If player prefers zero-level guys,276 * Returns the least wanted soldier that is fully healed
281 * the most trained soldier is the "weakest guy".277 * Wounded soldiers are ignored since they are supposed to be healed
278 * If player prefers rookies guys, the most trained soldier is the "weakest guy".
282 */279 */
283280Soldier* MilitarySite::find_least_suited_soldier() {
284Soldier *281
285MilitarySite::find_least_suited_soldier()282 const std::vector<Soldier*> present = present_soldiers();
286{283 if (present.empty()) {
287 const std::vector<Soldier *> present = present_soldiers();284 return nullptr;
288 const int32_t multiplier = kPrefersHeroes == m_soldier_preference ? -1 : 1;285 }
289 int worst_soldier_level = INT_MIN;286
290 Soldier * worst_soldier = nullptr;287 for (auto rit = present.rbegin(); rit != present.rend(); ++rit) {
291 for (Soldier* sld : present) {288 Soldier* s = (*rit);
292 int this_soldier_level = multiplier * static_cast<int> (sld->get_level(atrTotal));289 if (s->get_current_hitpoints() == s->get_max_hitpoints()) {
293 if (this_soldier_level > worst_soldier_level)290 return s;
294 {
295 worst_soldier_level = this_soldier_level;
296 worst_soldier = sld;
297 }291 }
298 }292 }
299 return worst_soldier;293
294 // if no fully healed soldier is found, return the last soldier
295 // this is the most wounded one
296 return present.back();
300}297}
301298
302
303/*299/*
304 * Kicks out the least wanted soldier -- If player prefers zero-level guys,300 * Kicks out the least wanted soldier -- If player prefers rookies,
305 * the most trained soldier is the "weakest guy".301 * the most trained soldier is the least suited guy.
306 *302 *
307 * Returns false, if there is only one soldier (won't drop last soldier)303 * Returns false, if there is only one soldier (won't drop last soldier)
308 * or the new guy is not better than the weakest one present, in which case304 * or the new guy is not better than the weakest one present, in which case
@@ -314,40 +310,26 @@
314 * arrives.310 * arrives.
315 */311 */
316312
317bool313bool MilitarySite::drop_least_suited_soldier(bool new_soldier_has_arrived, Soldier* newguy) {
318MilitarySite::drop_least_suited_soldier(bool new_soldier_has_arrived, Soldier * newguy)314
319{315 std::vector<Soldier*> present = present_soldiers();
320 const std::vector<Soldier *> present = present_soldiers();316
321317 // respect the minimal soldier capacity
322 // If I have only one soldier, and the new guy is not here yet, I can't release.318 if (!new_soldier_has_arrived && present.size() <= min_soldier_capacity()) {
323 if (new_soldier_has_arrived || 1 < present.size())319 return false;
324 {320 }
325 Soldier * kickoutCandidate = find_least_suited_soldier();321
326322 Soldier* kickoutCandidate = find_least_suited_soldier();
327 // If the arriving guy is worse than worst present, I wont't release.323
328 if (nullptr != newguy && nullptr != kickoutCandidate)324 // If the arriving guy is worse than worst present, do not drop a soldier
329 {325 if (kickoutCandidate != nullptr &&
330 int32_t old_level = kickoutCandidate->get_level(atrTotal);326 (newguy == nullptr ||
331 int32_t new_level = newguy->get_level(atrTotal);327 Soldier::CompareSoldier(m_soldier_preference)(newguy, kickoutCandidate))) {
332 if (kPrefersHeroes == m_soldier_preference && old_level >= new_level)328
333 {329 Game& game = dynamic_cast<Game&>(owner().egbase());
334 return false;330 kickoutCandidate->reset_tasks(game);
335 }331 kickoutCandidate->start_task_leavebuilding(game, true);
336 else332 return true;
337 if (kPrefersRookies == m_soldier_preference && old_level <= new_level)
338 {
339 return false;
340 }
341 }
342
343 // Now I know that the new guy is worthy.
344 if (nullptr != kickoutCandidate)
345 {
346 Game & game = dynamic_cast<Game&>(owner().egbase());
347 kickoutCandidate->reset_tasks(game);
348 kickoutCandidate->start_task_leavebuilding(game, true);
349 return true;
350 }
351 }333 }
352 return false;334 return false;
353}335}
@@ -677,7 +659,6 @@
677 return false;659 return false;
678}660}
679661
680
681/**662/**
682 * \return \c true if the soldier is currently present and idle in the building.663 * \return \c true if the soldier is currently present and idle in the building.
683 */664 */
@@ -689,7 +670,6 @@
689 soldier.get_position() == get_position();670 soldier.get_position() == get_position();
690}671}
691672
692// TODO(sirver): This method should probably return a const reference.
693std::vector<Soldier *> MilitarySite::present_soldiers() const673std::vector<Soldier *> MilitarySite::present_soldiers() const
694{674{
695 std::vector<Soldier *> soldiers;675 std::vector<Soldier *> soldiers;
@@ -701,10 +681,11 @@
701 }681 }
702 }682 }
703 }683 }
684
685 std::sort(soldiers.begin(), soldiers.end(), Soldier::CompareSoldier(m_soldier_preference));
704 return soldiers;686 return soldiers;
705}687}
706688
707// TODO(sirver): This method should probably return a const reference.
708std::vector<Soldier *> MilitarySite::stationed_soldiers() const689std::vector<Soldier *> MilitarySite::stationed_soldiers() const
709{690{
710 std::vector<Soldier *> soldiers;691 std::vector<Soldier *> soldiers;
@@ -934,7 +915,7 @@
934915
935 // feature request 1247384 in launchpad bugs: Conquered buildings tend to916 // feature request 1247384 in launchpad bugs: Conquered buildings tend to
936 // be in a hostile area; typically players want heroes there.917 // be in a hostile area; typically players want heroes there.
937 set_soldier_preference(kPrefersHeroes);918 set_soldier_preference(Soldier::kPrefersHeroes);
938}919}
939920
940/// Calculates whether the military presence is still kept and \returns true if.921/// Calculates whether the military presence is still kept and \returns true if.
@@ -1056,31 +1037,32 @@
1056 * The routine returns true if upgrade request thresholds have changed. This information could be1037 * The routine returns true if upgrade request thresholds have changed. This information could be
1057 * used to decide whether the soldier-Request should be upgraded.1038 * used to decide whether the soldier-Request should be upgraded.
1058 */1039 */
1059bool1040bool MilitarySite::update_upgrade_requirements() {
1060MilitarySite::update_upgrade_requirements()
1061{
1062 int32_t soldier_upgrade_required_min = m_soldier_upgrade_requirements.get_min();1041 int32_t soldier_upgrade_required_min = m_soldier_upgrade_requirements.get_min();
1063 int32_t soldier_upgrade_required_max = m_soldier_upgrade_requirements.get_max();1042 int32_t soldier_upgrade_required_max = m_soldier_upgrade_requirements.get_max();
10641043
1065 if (kPrefersHeroes != m_soldier_preference && kPrefersRookies != m_soldier_preference)1044 if (Soldier::kPrefersHeroes != m_soldier_preference &&
1066 {1045 Soldier::kPrefersRookies != m_soldier_preference) {
1067 log("MilitarySite::swapSoldiers: error: Unknown player preference %d.\n", m_soldier_preference);1046 log("MilitarySite::swapSoldiers: error: Unknown player preference %d.\n",
1047 m_soldier_preference);
1068 m_soldier_upgrade_try = false;1048 m_soldier_upgrade_try = false;
1069 return false;1049 return false;
1070 }1050 }
10711051
1072 // Find the level of the soldier that is currently least-suited.1052 // make sure worst_guy is defined
1073 Soldier * worst_guy = find_least_suited_soldier();1053 Soldier* worst_guy = find_least_suited_soldier();
1054
1074 if (worst_guy == nullptr) {1055 if (worst_guy == nullptr) {
1075 // There could be no soldier in the militarysite right now. No reason to freak out.1056 // There could be no soldier in the militarysite right now
1076 return false;1057 return false;
1077 }1058 }
1059
1078 int32_t wg_level = worst_guy->get_level(atrTotal);1060 int32_t wg_level = worst_guy->get_level(atrTotal);
10791061
1080 // Micro-optimization: I assume that the majority of military sites have only level-zero1062 // Micro-optimization: I assume that the majority of military sites have only level-zero
1081 // soldiers and prefer rookies. Handle them separately.1063 // soldiers and prefer rookies. Handle them separately.
1082 m_soldier_upgrade_try = true;1064 m_soldier_upgrade_try = true;
1083 if (kPrefersRookies == m_soldier_preference) {1065 if (Soldier::kPrefersRookies == m_soldier_preference) {
1084 if (0 == wg_level)1066 if (0 == wg_level)
1085 {1067 {
1086 m_soldier_upgrade_try = false;1068 m_soldier_upgrade_try = false;
@@ -1089,8 +1071,10 @@
1089 }1071 }
10901072
1091 // Now I actually build the new requirements.1073 // Now I actually build the new requirements.
1092 int32_t reqmin = kPrefersHeroes == m_soldier_preference ? 1 + wg_level : 0;1074 int32_t reqmin =
1093 int32_t reqmax = kPrefersHeroes == m_soldier_preference ? SHRT_MAX : wg_level - 1;1075 Soldier::kPrefersHeroes == m_soldier_preference ? 1 + wg_level : 0;
1076 int32_t reqmax =
1077 Soldier::kPrefersHeroes == m_soldier_preference ? SHRT_MAX : wg_level - 1;
10941078
1095 bool maxchanged = reqmax != soldier_upgrade_required_max;1079 bool maxchanged = reqmax != soldier_upgrade_required_max;
1096 bool minchanged = reqmin != soldier_upgrade_required_min;1080 bool minchanged = reqmin != soldier_upgrade_required_min;
@@ -1111,12 +1095,10 @@
11111095
1112// setters1096// setters
11131097
1114void1098void MilitarySite::set_soldier_preference(Soldier::SoldierPreference p) {
1115MilitarySite::set_soldier_preference(MilitarySite::SoldierPreference p)1099 assert(Soldier::kPrefersHeroes == p ||
1116{1100 Soldier::kPrefersRookies == p);
1117 assert(kPrefersHeroes == p || kPrefersRookies == p);
1118 m_soldier_preference = p;1101 m_soldier_preference = p;
1119 m_next_swap_soldiers_time = 0;1102 m_next_swap_soldiers_time = 0;
1120}1103}
1121
1122}1104}
11231105
=== modified file 'src/logic/map_objects/tribes/militarysite.h'
--- src/logic/map_objects/tribes/militarysite.h 2016-01-06 19:11:20 +0000
+++ src/logic/map_objects/tribes/militarysite.h 2016-01-24 08:32:15 +0000
@@ -27,6 +27,7 @@
27#include "logic/map_objects/attackable.h"27#include "logic/map_objects/attackable.h"
28#include "logic/map_objects/tribes/building.h"28#include "logic/map_objects/tribes/building.h"
29#include "logic/map_objects/tribes/requirements.h"29#include "logic/map_objects/tribes/requirements.h"
30#include "logic/map_objects/tribes/soldier.h"
30#include "logic/map_objects/tribes/soldiercontrol.h"31#include "logic/map_objects/tribes/soldiercontrol.h"
31#include "scripting/lua_table.h"32#include "scripting/lua_table.h"
3233
@@ -34,6 +35,7 @@
3435
35class Soldier;36class Soldier;
36class World;37class World;
38class MilitarySite;
3739
38class MilitarySiteDescr : public BuildingDescr {40class MilitarySiteDescr : public BuildingDescr {
39public:41public:
@@ -72,13 +74,6 @@
72 MO_DESCR(MilitarySiteDescr)74 MO_DESCR(MilitarySiteDescr)
7375
74public:76public:
75 // I assume elsewhere, that enum SoldierPreference fits to uint8_t.
76 enum SoldierPreference : uint8_t {
77 kNoPreference,
78 kPrefersRookies,
79 kPrefersHeroes,
80 };
81
82 MilitarySite(const MilitarySiteDescr &);77 MilitarySite(const MilitarySiteDescr &);
83 virtual ~MilitarySite();78 virtual ~MilitarySite();
8479
@@ -122,8 +117,8 @@
122117
123 void update_soldier_request(bool i = false);118 void update_soldier_request(bool i = false);
124119
125 void set_soldier_preference(SoldierPreference);120 void set_soldier_preference(Soldier::SoldierPreference);
126 SoldierPreference get_soldier_preference() const {121 Soldier::SoldierPreference get_soldier_preference() const {
127 return m_soldier_preference;122 return m_soldier_preference;
128 }123 }
129124
@@ -149,7 +144,7 @@
149 void update_normal_soldier_request();144 void update_normal_soldier_request();
150 void update_upgrade_soldier_request();145 void update_upgrade_soldier_request();
151 bool incorporate_upgraded_soldier(EditorGameBase & game, Soldier & s);146 bool incorporate_upgraded_soldier(EditorGameBase & game, Soldier & s);
152 Soldier * find_least_suited_soldier();147 Soldier* find_least_suited_soldier();
153 bool drop_least_suited_soldier(bool new_has_arrived, Soldier * s);148 bool drop_least_suited_soldier(bool new_has_arrived, Soldier * s);
154149
155150
@@ -172,7 +167,7 @@
172 bool stayhome;167 bool stayhome;
173 };168 };
174 std::vector<SoldierJob> m_soldierjobs;169 std::vector<SoldierJob> m_soldierjobs;
175 SoldierPreference m_soldier_preference;170 Soldier::SoldierPreference m_soldier_preference;
176 int32_t m_next_swap_soldiers_time;171 int32_t m_next_swap_soldiers_time;
177 bool m_soldier_upgrade_try; // optimization -- if everybody is zero-level, do not downgrade172 bool m_soldier_upgrade_try; // optimization -- if everybody is zero-level, do not downgrade
178 bool m_doing_upgrade_request;173 bool m_doing_upgrade_request;
179174
=== modified file 'src/logic/map_objects/tribes/production_program.cc'
--- src/logic/map_objects/tribes/production_program.cc 2016-01-24 07:45:11 +0000
+++ src/logic/map_objects/tribes/production_program.cc 2016-01-24 08:32:15 +0000
@@ -1467,9 +1467,8 @@
1467 (Game & game, ProductionSite & ps) const1467 (Game & game, ProductionSite & ps) const
1468{1468{
1469 SoldierControl & ctrl = dynamic_cast<SoldierControl &>(ps);1469 SoldierControl & ctrl = dynamic_cast<SoldierControl &>(ps);
1470 const std::vector<Soldier *> soldiers = ctrl.present_soldiers();1470 const std::vector<Soldier*> soldiers = ctrl.present_soldiers();
1471 const std::vector<Soldier *>::const_iterator soldiers_end =1471 const std::vector<Soldier*>::const_iterator soldiers_end = soldiers.end();
1472 soldiers.end();
1473 std::vector<Soldier *>::const_iterator it = soldiers.begin();1472 std::vector<Soldier *>::const_iterator it = soldiers.begin();
14741473
1475 ps.molog1474 ps.molog
14761475
=== modified file 'src/logic/map_objects/tribes/soldier.cc'
--- src/logic/map_objects/tribes/soldier.cc 2016-01-18 05:12:51 +0000
+++ src/logic/map_objects/tribes/soldier.cc 2016-01-24 08:32:15 +0000
@@ -1605,6 +1605,12 @@
1605 schedule_destroy(game);1605 schedule_destroy(game);
1606}1606}
16071607
1608float Soldier::compute_power() const {
1609 // (MaxAttack+MinAttack)/2)*(100/(100-Defense))*(100/(100-Evade))*CurHP
1610 return ((get_max_attack() + get_max_attack()) / 2.0) * (100.0 / (100.0 - get_defense())) *
1611 (100.0 / (100.0 - get_evade())) * get_current_hitpoints();
1612}
1613
1608/**1614/**
1609 * Accept a Bob if it is a Soldier, is not dead and is running taskAttack or1615 * Accept a Bob if it is a Soldier, is not dead and is running taskAttack or
1610 * taskDefense.1616 * taskDefense.
16111617
=== modified file 'src/logic/map_objects/tribes/soldier.h'
--- src/logic/map_objects/tribes/soldier.h 2016-01-06 19:11:20 +0000
+++ src/logic/map_objects/tribes/soldier.h 2016-01-24 08:32:15 +0000
@@ -30,10 +30,6 @@
3030
31namespace Widelands {31namespace Widelands {
3232
33// Constants used to launch attacks
34#define WEAKEST 0
35#define STRONGEST 1
36
37class EditorGameBase;33class EditorGameBase;
38class Battle;34class Battle;
3935
@@ -159,7 +155,63 @@
159 MO_DESCR(SoldierDescr)155 MO_DESCR(SoldierDescr)
160156
161public:157public:
162 Soldier(const SoldierDescr &);158 Soldier(const SoldierDescr&);
159
160 enum SoldierPreference : uint8_t {
161 kNoPreference, // useful if no ordering is prefered -> ordered by serial
162 kPrefersRookies,
163 kPrefersHeroes,
164 };
165
166 struct CompareSoldier {
167
168 CompareSoldier(const SoldierPreference preference = kPrefersHeroes)
169 : m_preference(preference) {
170 }
171
172 bool operator()(const Soldier* s, const Soldier* t) {
173
174 Serial serial_s = s->serial();
175 Serial serial_t = t->serial();
176
177 if (m_preference == kNoPreference) {
178 return s->serial() < t->serial();
179 }
180
181 // independent of preference, prefer healthy soldiers
182 // percentage of health s > percentage of health t
183 // a1 / a2 > b1 / b2 iff a1*b2 > b1*a2
184 uint32_t health_s = s->get_current_hitpoints() * t->get_max_hitpoints();
185 uint32_t health_t = t->get_current_hitpoints() * s->get_max_hitpoints();
186
187 if (health_s > health_t) {
188 return true;
189 }
190 if (health_t > health_s) {
191 return false;
192 }
193
194 // the serial is added to have some "randomness" in the ordering
195 // in case of equal power, they seem to be selected at random
196 // effect: attacking soldiers are distributed to military sites in range
197 float power_s = s->compute_power() + (serial_s % 5);
198 float power_t = t->compute_power() + (serial_t % 5);
199
200 if (power_s - power_t < 1e-5) {
201 return m_preference == kPrefersRookies;
202 }
203
204 if (power_t - power_s < 1e-5) {
205 return m_preference == kPrefersHeroes;
206 }
207
208 return s->serial() < t->serial();
209 }
210
211 private:
212 const SoldierPreference m_preference;
213 };
214
163215
164 void init(EditorGameBase &) override;216 void init(EditorGameBase &) override;
165 void cleanup(EditorGameBase &) override;217 void cleanup(EditorGameBase &) override;
@@ -245,6 +297,7 @@
245 void move_in_battle_update(Game &, State &);297 void move_in_battle_update(Game &, State &);
246 void die_update(Game &, State &);298 void die_update(Game &, State &);
247 void die_pop(Game &, State &);299 void die_pop(Game &, State &);
300 float compute_power() const;
248301
249 void send_space_signals(Game &);302 void send_space_signals(Game &);
250 bool stay_home();303 bool stay_home();
251304
=== modified file 'src/logic/map_objects/tribes/trainingsite.cc'
--- src/logic/map_objects/tribes/trainingsite.cc 2016-01-18 19:35:25 +0000
+++ src/logic/map_objects/tribes/trainingsite.cc 2016-01-24 08:32:15 +0000
@@ -408,14 +408,11 @@
408 return 0;408 return 0;
409}409}
410410
411411std::vector<Soldier*> TrainingSite::present_soldiers() const {
412std::vector<Soldier *> TrainingSite::present_soldiers() const
413{
414 return m_soldiers;412 return m_soldiers;
415}413}
416414
417std::vector<Soldier *> TrainingSite::stationed_soldiers() const415std::vector<Soldier*> TrainingSite::stationed_soldiers() const {
418{
419 return m_soldiers;416 return m_soldiers;
420}417}
421418
422419
=== modified file 'src/logic/map_objects/tribes/warehouse.cc'
--- src/logic/map_objects/tribes/warehouse.cc 2016-01-08 21:00:39 +0000
+++ src/logic/map_objects/tribes/warehouse.cc 2016-01-24 08:32:15 +0000
@@ -1435,9 +1435,8 @@
1435/*1435/*
1436 * SoldierControl implementations1436 * SoldierControl implementations
1437 */1437 */
1438std::vector<Soldier *> Warehouse::present_soldiers() const1438std::vector<Soldier*> Warehouse::present_soldiers() const {
1439{1439 std::vector<Soldier*> rv;
1440 std::vector<Soldier *> rv;
14411440
1442 DescriptionIndex const soldier_index = owner().tribe().soldier();1441 DescriptionIndex const soldier_index = owner().tribe().soldier();
1443 IncorporatedWorkers::const_iterator sidx = m_incorporated_workers.find(soldier_index);1442 IncorporatedWorkers::const_iterator sidx = m_incorporated_workers.find(soldier_index);
14441443
=== modified file 'src/logic/player.cc'
--- src/logic/player.cc 2016-01-17 09:54:31 +0000
+++ src/logic/player.cc 2016-01-24 08:32:15 +0000
@@ -19,6 +19,7 @@
1919
20#include "logic/player.h"20#include "logic/player.h"
2121
22#include <algorithm>
22#include <memory>23#include <memory>
2324
24#include <boost/bind.hpp>25#include <boost/bind.hpp>
@@ -54,6 +55,7 @@
54#include "sound/sound_handler.h"55#include "sound/sound_handler.h"
55#include "wui/interactive_player.h"56#include "wui/interactive_player.h"
5657
58namespace Widelands {
5759
58namespace {60namespace {
5961
@@ -88,12 +90,8 @@
88 }90 }
89}91}
9092
91
92
93}93}
9494
95namespace Widelands {
96
97const RGBColor Player::Colors[MAX_PLAYERS] = {95const RGBColor Player::Colors[MAX_PLAYERS] = {
98 RGBColor(2, 2, 198), // blue96 RGBColor(2, 2, 198), // blue
99 RGBColor(255, 41, 0), // red97 RGBColor(255, 41, 0), // red
@@ -717,7 +715,7 @@
717{715{
718 if (&imm.owner() == this)716 if (&imm.owner() == this)
719 if (upcast(MilitarySite, milsite, &imm))717 if (upcast(MilitarySite, milsite, &imm))
720 milsite->set_soldier_preference(static_cast<MilitarySite::SoldierPreference>(m_soldier_preference));718 milsite->set_soldier_preference(static_cast<Soldier::SoldierPreference>(m_soldier_preference));
721}719}
722720
723721
@@ -891,57 +889,66 @@
891*/889*/
892890
893/**891/**
894 * Get a list of soldiers that this player can use to attack the892* Return the number of soldiers that can attack the building at the
895 * building at the given flag.893* given flag, limited to \param nr_wanted.
896 *894*
897 * The default attack should just take the first N soldiers of the895* If \param soldiers != NULL it will be filled with soldiers selected
898 * returned array.896* on health and strength while trying to select the soldiers from
899 */897* multiple buildings.
900// TODO(unknown): Perform a meaningful sort on the soldiers array.898*/
901uint32_t Player::find_attack_soldiers899uint32_t
902 (Flag & flag, std::vector<Soldier *> * soldiers, uint32_t nr_wanted)900Player::find_attack_soldiers(Flag& flag, std::vector<Soldier*>* soldiers, uint32_t nr_wanted) {
903{901 std::vector<Soldier*> attackers_all;
904 uint32_t count = 0;902 uint32_t nr_available = 0;
905903
906 if (soldiers)904 if (soldiers)
907 soldiers->clear();905 soldiers->clear();
908906
909 Map & map = egbase().map();907 Map& map = egbase().map();
910 std::vector<BaseImmovable *> flags;908 std::vector<BaseImmovable*> flags;
911909
912 map.find_reachable_immovables_unique910 map.find_reachable_immovables_unique(Area<FCoords>(map.get_fcoords(flag.get_position()), 25),
913 (Area<FCoords>(map.get_fcoords(flag.get_position()), 25),911 flags,
914 flags,912 CheckStepDefault(MOVECAPS_WALK),
915 CheckStepDefault(MOVECAPS_WALK),913 FindFlagOf(FindImmovablePlayerMilitarySite(*this)));
916 FindFlagOf(FindImmovablePlayerMilitarySite(*this)));
917914
918 if (flags.empty())915 if (flags.empty())
919 return 0;916 return 0;
920917
921 for (BaseImmovable * temp_flag : flags) {918 // Count (and if necessary collect) available soldiers.
922 upcast(Flag, attackerflag, temp_flag);919 for (const BaseImmovable* base_immovable : flags) {
923 upcast(MilitarySite, ms, attackerflag->get_building());920 const Flag* attackerflag = static_cast<const Flag*>(base_immovable);
924 std::vector<Soldier *> const present = ms->present_soldiers();921 const MilitarySite* ms = static_cast<MilitarySite*>(attackerflag->get_building());
925 uint32_t const nr_staying = ms->min_soldier_capacity();922 std::vector<Soldier*> present = ms->present_soldiers();
926 uint32_t const nr_present = present.size();923 const uint32_t nr_staying = ms->min_soldier_capacity();
924 const uint32_t nr_present = present.size();
927 if (nr_staying < nr_present) {925 if (nr_staying < nr_present) {
928 uint32_t const nr_taken =926 const uint32_t nr_taken = nr_present - nr_staying;
929 std::min(nr_wanted, nr_present - nr_staying);927
930 if (soldiers)928 if (soldiers) {
931 soldiers->insert929 std::copy_n(present.begin(), nr_taken, std::back_inserter(attackers_all));
932 (soldiers->end(),930 }
933 present.begin(), present.begin() + nr_taken);931
934 count += nr_taken;932 nr_available += nr_taken;
935 nr_wanted -= nr_taken;
936 if (!nr_wanted)
937 break;
938 }933 }
939 }934 }
935 const uint32_t count = std::min(nr_available, nr_wanted);
936 if (soldiers) {
937 // Sort soldiers and remove surplus.
938 soldiers->reserve(count);
939 std::vector<Soldier*>::iterator pos = std::next(attackers_all.begin(), count);
940 // Even if weak soldiers are prefered, strong soldiers should attack
941 // otherwise, wounded soldiers would be send first
942 std::partial_sort(attackers_all.begin(),
943 pos,
944 attackers_all.end(),
945 Soldier::CompareSoldier(Soldier::SoldierPreference::kPrefersHeroes));
946 std::copy(attackers_all.begin(), pos, std::back_inserter(*soldiers));
947 }
940948
941 return count;949 return count;
942}950}
943951
944
945// TODO(unknown): Clean this mess up. The only action we really have right now is952// TODO(unknown): Clean this mess up. The only action we really have right now is
946// to attack, so pretending we have more types is pointless.953// to attack, so pretending we have more types is pointless.
947void Player::enemyflagaction954void Player::enemyflagaction
948955
=== modified file 'src/map_io/map_buildingdata_packet.cc'
--- src/map_io/map_buildingdata_packet.cc 2016-01-18 19:35:25 +0000
+++ src/map_io/map_buildingdata_packet.cc 2016-01-24 08:32:15 +0000
@@ -563,7 +563,7 @@
563 uint16_t reqmin = fr.unsigned_16();563 uint16_t reqmin = fr.unsigned_16();
564 uint16_t reqmax = fr.unsigned_16();564 uint16_t reqmax = fr.unsigned_16();
565 militarysite.m_soldier_upgrade_requirements = RequireAttribute(atrTotal, reqmin, reqmax);565 militarysite.m_soldier_upgrade_requirements = RequireAttribute(atrTotal, reqmin, reqmax);
566 militarysite.m_soldier_preference = static_cast<MilitarySite::SoldierPreference>(fr.unsigned_8());566 militarysite.m_soldier_preference = static_cast<Soldier::SoldierPreference>(fr.unsigned_8());
567 militarysite.m_next_swap_soldiers_time = fr.signed_32();567 militarysite.m_next_swap_soldiers_time = fr.signed_32();
568 militarysite.m_soldier_upgrade_try = 0 != fr.unsigned_8() ? true : false;568 militarysite.m_soldier_upgrade_try = 0 != fr.unsigned_8() ? true : false;
569 militarysite.m_doing_upgrade_request = 0 != fr.unsigned_8() ? true : false;569 militarysite.m_doing_upgrade_request = 0 != fr.unsigned_8() ? true : false;
570570
=== modified file 'src/wui/soldierlist.cc'
--- src/wui/soldierlist.cc 2016-01-17 08:29:59 +0000
+++ src/wui/soldierlist.cc 2016-01-24 08:32:15 +0000
@@ -427,12 +427,12 @@
427 }427 }
428428
429 m_soldier_preference.set_state(0);429 m_soldier_preference.set_state(0);
430 if (ms->get_soldier_preference() == Widelands::MilitarySite::kPrefersHeroes) {430 if (ms->get_soldier_preference() == Widelands::Soldier::kPrefersHeroes) {
431 m_soldier_preference.set_state(1);431 m_soldier_preference.set_state(1);
432 }432 }
433 if (can_act) {433 if (can_act) {
434 m_soldier_preference.changedto.connect434 m_soldier_preference.changedto.connect(
435 (boost::bind(&SoldierList::set_soldier_preference, this, _1));435 boost::bind(&SoldierList::set_soldier_preference, this, _1));
436 } else {436 } else {
437 m_soldier_preference.set_enabled(false);437 m_soldier_preference.set_enabled(false);
438 }438 }
@@ -458,13 +458,13 @@
458 }458 }
459 if (upcast(Widelands::MilitarySite, ms, &m_building)) {459 if (upcast(Widelands::MilitarySite, ms, &m_building)) {
460 switch (ms->get_soldier_preference()) {460 switch (ms->get_soldier_preference()) {
461 case Widelands::MilitarySite::kPrefersRookies:461 case Widelands::Soldier::kPrefersRookies:
462 m_soldier_preference.set_state(0);462 m_soldier_preference.set_state(0);
463 break;463 break;
464 case Widelands::MilitarySite::kPrefersHeroes:464 case Widelands::Soldier::kPrefersHeroes:
465 m_soldier_preference.set_state(1);465 m_soldier_preference.set_state(1);
466 break;466 break;
467 case Widelands::MilitarySite::kNoPreference:467 case Widelands::Soldier::kNoPreference:
468 m_soldier_preference.set_state(-1);468 m_soldier_preference.set_state(-1);
469 break;469 break;
470 }470 }
@@ -506,8 +506,8 @@
506#endif506#endif
507 m_igb.game().send_player_militarysite_set_soldier_preference507 m_igb.game().send_player_militarysite_set_soldier_preference
508 (m_building, changed_to == 0 ?508 (m_building, changed_to == 0 ?
509 Widelands::MilitarySite::kPrefersRookies:509 Widelands::Soldier::kPrefersRookies:
510 Widelands::MilitarySite::kPrefersHeroes);510 Widelands::Soldier::kPrefersHeroes);
511}511}
512512
513UI::Panel * create_soldier_list513UI::Panel * create_soldier_list

Subscribers

People subscribed via source and target branches

to status/vote changes: