Merge lp:~widelands-dev/widelands/bug-1746481 into lp:widelands

Proposed by TiborB
Status: Work in progress
Proposed branch: lp:~widelands-dev/widelands/bug-1746481
Merge into: lp:widelands
Diff against target: 151 lines (+64/-12)
4 files modified
src/ai/ai_help_structs.h (+1/-0)
src/ai/defaultai.cc (+43/-12)
src/ai/defaultai_warfare.cc (+11/-0)
src/main.cc (+9/-0)
To merge this branch: bzr merge lp:~widelands-dev/widelands/bug-1746481
Reviewer Review Type Date Requested Status
Widelands Developers Pending
Review via email: mp+337125@code.launchpad.net

Description of the change

AI now considers a building needed for 'basic economy' finished only if fully occupied.
I left one DEBUG log in the code for a tester (contains word DEBUG).
There is some short gap between a building gets occupied and AI recognizes it. And this can cause inconsistency when a game is saved just during such period. But should not be very frequent....
After testing is done, I will remove NOCOM lines.

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

Continuous integration builds have changed state:

Travis build 3135. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/337068986.
Appveyor build 2942. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_bug_1746481-2942.

Revision history for this message
TiborB (tiborb95) wrote :

Codecheck complains about printfs, but these are only for temporary DEBUG logs and will be removed before merge...

Revision history for this message
R M (weedfreak) wrote :

Testing this the AI was set up with

1: Initializing in the basic economy mode, required buildings:
     97 / empire_tavern               - target 1
     95 / empire_winery               - target 1
     84 / empire_foresters_house      - target 2
    117 / empire_marblemine           - target 1
     83 / empire_lumberjacks_house    - target 2
     90 / empire_sawmill              - target 2
    106 / empire_farm                 - target 1
     89 / empire_stonemasons_house    - target 1
     92 / empire_bakery               - target 1
     94 / empire_vineyard             - target 1

  which it then ignored, it built
     empire_tavern               - 1
     empire_winery               - 1
     empire_foresters_house      - 7
     empire_marblemine           - 0
     empire_lumberjacks_house    - 6
     empire_sawmill              - 3
     empire_farm                 -1
     empire_stonemasons_house    - 2
     empire_bakery               - target 3
     empire_vineyard             - target 2

After an hour it started building training sites despite having no mines
or mills for wheat. Eventually it built a marble mine, but 5 minutes
later it had still not announced the basic economy established. Loading
from a save game did not work as I did not have a zipped save, will try
that next.

Checking the terminal there ws no debug message for the mine so perhaps
I was not patient enough.

Revision history for this message
TiborB (tiborb95) wrote :

Everytime a site is occupied for the first time you should see this DEBUG log: https://bazaar.launchpad.net/~widelands-dev/widelands/bug-1746481/view/head:/src/ai/defaultai.cc#L3706

The problem could had been printf() in my code, I just pushed new branch which uses log() to print these logs. If this still not print these DEBUG logs something must be messed up.

From your prescription, only problem you found was that it built a trainingsite before the basic economy was achieved. Yes, there is genetic algorithm involved there that under some circumstances allows trainingsites before basic economy. This is question of course, if this should be allowed...

Revision history for this message
R M (weedfreak) wrote :

The gap between the building being finished and being recognised seems
to increase with game time, the first few are almost instantaneous as
the worker reaches the buildings flag, later it occurs just after
occupation.

This run the vineyard was not built until after 8 foresters so there was
no shovel left and thus no worker but the message DEBUG: empire_vineyard
first time occupied appeared, incorrectly, after a few minutes.

Loading save games has not, so far produced any problems, but it may
still be a problem later in game when the delay gets greater.

Revision history for this message
TiborB (tiborb95) wrote :

INDEED, I see a problem (in the code) now. I will fix and let you know...

Revision history for this message
R M (weedfreak) wrote :

I am not sure what code problem you have found but further testing shows
no problem later in game with saves, the marble mine does not produce a
debug message after 20 minutes and when a basic economy building is
built but not occupied the AI starts building another of that building,
so that was why there were 3 sawmills, 2 stonemasons, 2 bakeries and 2
vineyards etc. most were started when the worker was on the way.

On 06/02/18 13:12, TiborB wrote:
> INDEED, I see a problem (in the code) now. I will fix and let you know...

Revision history for this message
TiborB (tiborb95) wrote :

I omit to incorporate can_start_working() function to the check altogether, it simply cannot work properly....

Revision history for this message
TiborB (tiborb95) wrote :

Please try once more..

Revision history for this message
R M (weedfreak) wrote :

The woodcutter first occupied debug message is printed twice, most basic
economy buildings are built one more than the basic setting. The marble
mine, which is built twice, does not give a debug message and no message
for basic economy reached is given. The marble mines were the last basic
economy buildings built and I ran the game for an hour afterwards.

To be certain the vineyard was occupied I prohibited foresters for 600
so there was at least one shovel in stock.

Revision history for this message
TiborB (tiborb95) wrote :

Weird, the code look straightforward in this regard... I will have to test it myself.

No save&load was involved I presume.....

Revision history for this message
TiborB (tiborb95) wrote :

I probably know what is going on. The problem is a gap when a building exists and is not occupied yet (scratched from the list)
AI when considering new buildings tests:
- it is on the list of (missing) basic buildings
- none is in construction

I have to rethink this

Revision history for this message
GunChleoc (gunchleoc) wrote :

You probably need 2 lists, one with the buildings to build, and one with the buildings built. The buildings built list can then be checked whether they're occupied and if so, be removed from the second list.

Or you can expand the first list with number of buildings built and only build new buildings if there is a difference. Then remove fro the list if all buildings are occupied.

Regarding printf, that function is insecure and should be replaced with sprintf in all cases - our custom-built log function will do that for you. You also accidentally added a long list of "#include <unistd.h>" to main.cc in the commit that fixed the printf.

Revision history for this message
TiborB (tiborb95) wrote :

Yes, single list will not do. And I have to pay attention to the game saving aspect as well.

I spent a lot of time with another branch - findpath_modification, and if this will be OK now, I can come back to this...

Revision history for this message
GunChleoc (gunchleoc) wrote :

Is this branch ready for review? We should get rid of the extra lines in src/main.cc in any case.

Revision history for this message
TiborB (tiborb95) wrote :

No, I have not touched it since the last discussion. I am still not sure how to approach this. We can cancel this merge proposal....

Revision history for this message
GunChleoc (gunchleoc) wrote :

OK, I have set it back to "Work in Progress"

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/ai/ai_help_structs.h'
--- src/ai/ai_help_structs.h 2017-11-17 07:16:12 +0000
+++ src/ai/ai_help_structs.h 2018-02-06 19:41:40 +0000
@@ -436,6 +436,7 @@
436 uint32_t current_stats;436 uint32_t current_stats;
437437
438 uint32_t basic_amount; // basic amount for basic economy as defined in init.lua438 uint32_t basic_amount; // basic amount for basic economy as defined in init.lua
439 bool never_occupied; //this switches
439440
440 std::vector<Widelands::DescriptionIndex> inputs;441 std::vector<Widelands::DescriptionIndex> inputs;
441 std::vector<Widelands::DescriptionIndex> outputs;442 std::vector<Widelands::DescriptionIndex> outputs;
442443
=== modified file 'src/ai/defaultai.cc'
--- src/ai/defaultai.cc 2018-01-30 11:44:48 +0000
+++ src/ai/defaultai.cc 2018-02-06 19:41:40 +0000
@@ -3702,6 +3702,16 @@
3702 // Get link to productionsite that should be checked3702 // Get link to productionsite that should be checked
3703 ProductionSiteObserver& site = productionsites.front();3703 ProductionSiteObserver& site = productionsites.front();
37043704
3705 if (site.bo->never_occupied && persistent_data->remaining_basic_buildings.count(site.bo->id) > 0 && site.site->can_start_working()) {
3706 log ("DEBUG: %s first time occupied\n", site.bo->name); // NOCOM
3707 if (persistent_data->remaining_basic_buildings[site.bo->id] > 1) {
3708 --persistent_data->remaining_basic_buildings[site.bo->id];
3709 } else {
3710 persistent_data->remaining_basic_buildings.erase(site.bo->id);
3711 }
3712 site.bo->never_occupied = false;
3713 }
3714
3705 // Inform if we are above ai type limit.3715 // Inform if we are above ai type limit.
3706 if (site.bo->total_count() > site.bo->cnt_limit_by_aimode) {3716 if (site.bo->total_count() > site.bo->cnt_limit_by_aimode) {
3707 log("AI check_productionsites: Too many %s: %d, ai limit: %d\n", site.bo->name,3717 log("AI check_productionsites: Too many %s: %d, ai limit: %d\n", site.bo->name,
@@ -4182,6 +4192,16 @@
4182 // Get link to productionsite that should be checked4192 // Get link to productionsite that should be checked
4183 ProductionSiteObserver& site = mines_.front();4193 ProductionSiteObserver& site = mines_.front();
41844194
4195 if (site.bo->never_occupied && persistent_data->remaining_basic_buildings.count(site.bo->id) > 0 && site.site->can_start_working()) {
4196 log ("DEBUG: %s first time occupied\n", site.bo->name); // NOCOM
4197 if (persistent_data->remaining_basic_buildings[site.bo->id] > 1) {
4198 --persistent_data->remaining_basic_buildings[site.bo->id];
4199 } else {
4200 persistent_data->remaining_basic_buildings.erase(site.bo->id);
4201 }
4202 site.bo->never_occupied = false;
4203 }
4204
4185 const bool connected_to_wh = !site.site->get_economy()->warehouses().empty();4205 const bool connected_to_wh = !site.site->get_economy()->warehouses().empty();
41864206
4187 // First we dismantle mines that are marked as such, generally we wait till all wares all gone4207 // First we dismantle mines that are marked as such, generally we wait till all wares all gone
@@ -5748,18 +5768,6 @@
5748 ++bo.cnt_built;5768 ++bo.cnt_built;
5749 const uint32_t gametime = game().get_gametime();5769 const uint32_t gametime = game().get_gametime();
5750 bo.last_building_built = gametime;5770 bo.last_building_built = gametime;
5751 // erase building from remaining_basic_buildings, unless we are loading a saved game
5752 if (!found_on_load && persistent_data->remaining_basic_buildings.count(bo.id) > 0) {
5753 if (persistent_data->remaining_basic_buildings[bo.id] > 1) {
5754 --persistent_data->remaining_basic_buildings[bo.id];
5755 } else {
5756 persistent_data->remaining_basic_buildings.erase(bo.id);
5757 }
5758 }
5759 // Remaining basic buildings map contain either no entry for the building, or the number is
5760 // nonzero
5761 assert(persistent_data->remaining_basic_buildings.count(bo.id) == 0 ||
5762 persistent_data->remaining_basic_buildings[bo.id] > 0);
57635771
5764 if (bo.type == BuildingObserver::Type::kProductionsite) {5772 if (bo.type == BuildingObserver::Type::kProductionsite) {
5765 productionsites.push_back(ProductionSiteObserver());5773 productionsites.push_back(ProductionSiteObserver());
@@ -5786,6 +5794,14 @@
57865794
5787 for (uint32_t i = 0; i < bo.inputs.size(); ++i)5795 for (uint32_t i = 0; i < bo.inputs.size(); ++i)
5788 ++wares.at(bo.inputs.at(i)).consumers;5796 ++wares.at(bo.inputs.at(i)).consumers;
5797
5798 if (!found_on_load) {
5799 // If this is brand new building, setting as never occupied
5800 bo.never_occupied = true;
5801 } else {
5802 // otherwise just find out
5803 bo.never_occupied = !productionsites.back().site->can_start_working();
5804 }
5789 } else if (bo.type == BuildingObserver::Type::kMine) {5805 } else if (bo.type == BuildingObserver::Type::kMine) {
5790 mines_.push_back(ProductionSiteObserver());5806 mines_.push_back(ProductionSiteObserver());
5791 mines_.back().site = &dynamic_cast<ProductionSite&>(b);5807 mines_.back().site = &dynamic_cast<ProductionSite&>(b);
@@ -5810,6 +5826,14 @@
58105826
5811 set_inputs_to_zero(mines_.back());5827 set_inputs_to_zero(mines_.back());
58125828
5829
5830 // If this is brand new building, setting as never occupied
5831 if (!found_on_load) {
5832 bo.never_occupied = false;
5833 } else {
5834 // otherwise just find out
5835 bo.never_occupied = productionsites.back().site->can_start_working();
5836 }
5813 } else if (bo.type == BuildingObserver::Type::kMilitarysite) {5837 } else if (bo.type == BuildingObserver::Type::kMilitarysite) {
5814 militarysites.push_back(MilitarySiteObserver());5838 militarysites.push_back(MilitarySiteObserver());
5815 militarysites.back().site = &dynamic_cast<MilitarySite&>(b);5839 militarysites.back().site = &dynamic_cast<MilitarySite&>(b);
@@ -5829,6 +5853,13 @@
5829 trainingsites.push_back(TrainingSiteObserver());5853 trainingsites.push_back(TrainingSiteObserver());
5830 trainingsites.back().site = &dynamic_cast<TrainingSite&>(b);5854 trainingsites.back().site = &dynamic_cast<TrainingSite&>(b);
5831 trainingsites.back().bo = &bo;5855 trainingsites.back().bo = &bo;
5856 // If this is brand new building, setting as never occupied
5857 if (!found_on_load) {
5858 bo.never_occupied = false;
5859 } else {
5860 // otherwise just find out
5861 bo.never_occupied = productionsites.back().site->can_start_working();
5862 }
58325863
5833 } else if (bo.type == BuildingObserver::Type::kWarehouse) {5864 } else if (bo.type == BuildingObserver::Type::kWarehouse) {
5834 ++numof_warehouses_;5865 ++numof_warehouses_;
58355866
=== modified file 'src/ai/defaultai_warfare.cc'
--- src/ai/defaultai_warfare.cc 2017-11-13 09:10:04 +0000
+++ src/ai/defaultai_warfare.cc 2018-02-06 19:41:40 +0000
@@ -575,6 +575,17 @@
575 TrainingSite* ts = trainingsites.front().site;575 TrainingSite* ts = trainingsites.front().site;
576 TrainingSiteObserver& tso = trainingsites.front();576 TrainingSiteObserver& tso = trainingsites.front();
577577
578 // In case this trainingsite is among basic buildings
579 if (tso.bo->never_occupied && persistent_data->remaining_basic_buildings.count(tso.bo->id) > 0 && tso.site->can_start_working()) {
580 printf ("DEBUG: %s first time occupied - erasing from basic economy list\n", tso.bo->name); //NOCOM
581 if (persistent_data->remaining_basic_buildings[tso.bo->id] > 1) {
582 --persistent_data->remaining_basic_buildings[tso.bo->id];
583 } else {
584 persistent_data->remaining_basic_buildings.erase(tso.bo->id);
585 }
586 tso.bo->never_occupied = false;
587 }
588
578 // Inform if we are above ai type limit.589 // Inform if we are above ai type limit.
579 if (tso.bo->total_count() > tso.bo->cnt_limit_by_aimode) {590 if (tso.bo->total_count() > tso.bo->cnt_limit_by_aimode) {
580 log("AI check_trainingsites: AI player %d: count of %s exceeds an AI limit %d: actual count: "591 log("AI check_trainingsites: AI player %d: count of %s exceeds an AI limit %d: actual count: "
581592
=== modified file 'src/main.cc'
--- src/main.cc 2017-06-16 06:03:23 +0000
+++ src/main.cc 2018-02-06 19:41:40 +0000
@@ -1,3 +1,12 @@
1#include <unistd.h>
2#include <unistd.h>
3#include <unistd.h>
4#include <unistd.h>
5#include <unistd.h>
6#include <unistd.h>
7#include <unistd.h>
8#include <unistd.h>
9#include <unistd.h>
1/*10/*
2 * Copyright (C) 2002-2017 by the Widelands Development Team11 * Copyright (C) 2002-2017 by the Widelands Development Team
3 *12 *

Subscribers

People subscribed via source and target branches

to status/vote changes: