← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/ai_dna_dump into lp:widelands

 

TiborB has proposed merging lp:~widelands-dev/widelands/ai_dna_dump into lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/ai_dna_dump/+merge/327988

The branch introduces export and load of AI data to/from text files so no recompilation is needed anymore.
It includes also some tweaks to AI and some training, based on discussion on the website
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/ai_dna_dump into lp:widelands.
=== added directory 'data/ai'
=== added file 'data/ai/ai_input_1.wai'
--- data/ai/ai_input_1.wai	1970-01-01 00:00:00 +0000
+++ data/ai/ai_input_1.wai	2017-07-24 20:38:49 +0000
@@ -0,0 +1,379 @@
+# Automatically created by Widelands bzr[] (Debug)
+
+[magic_numbers]
+0="18"
+1="-47"
+2="21"
+3="35"
+4="-7"
+5="-56"
+6="-53"
+7="81"
+8="0"
+9="0"
+10="-55"
+11="22"
+12="-92"
+13="48"
+14="70"
+15="-30"
+16="26"
+17="79"
+18="-63"
+19="-12"
+20="79"
+21="-28"
+22="13"
+23="39"
+24="0"
+25="3"
+26="45"
+27="-33"
+28="53"
+29="51"
+30="-93"
+31="47"
+32="-42"
+33="90"
+34="-72"
+35="52"
+36="-68"
+37="-47"
+38="17"
+39="-72"
+40="51"
+41="51"
+42="-4"
+43="-40"
+44="47"
+45="7"
+46="6"
+47="3"
+48="-64"
+49="-41"
+50="-3"
+51="-55"
+52="62"
+53="0"
+54="57"
+55="-92"
+56="4"
+57="-89"
+58="66"
+59="-44"
+60="-87"
+61="56"
+62="19"
+63="-34"
+64="-20"
+65="24"
+66="-54"
+67="84"
+68="56"
+69="-51"
+70="0"
+71="44"
+72="0"
+73="-2"
+74="-11"
+75="-4"
+76="-96"
+77="-34"
+78="0"
+79="-31"
+80="71"
+81="-98"
+82="-25"
+83="-44"
+84="58"
+85="68"
+86="0"
+87="28"
+88="-54"
+89="23"
+90="21"
+91="53"
+92="80"
+93="0"
+94="-41"
+95="58"
+96="53"
+97="27"
+98="-73"
+99="-65"
+100="14"
+101="-42"
+102="31"
+103="-92"
+104="-62"
+105="86"
+106="-55"
+107="-63"
+108="0"
+109="-40"
+110="77"
+111="0"
+112="-65"
+113="0"
+114="32"
+115="-26"
+116="0"
+117="0"
+118="-70"
+119="74"
+120="85"
+121="0"
+122="52"
+123="48"
+124="-30"
+125="25"
+126="-61"
+127="62"
+128="60"
+129="8"
+130="-52"
+131="46"
+132="100"
+133="-74"
+134="19"
+135="95"
+136="-9"
+137="-100"
+138="36"
+139="-4"
+140="77"
+141="15"
+142="-57"
+143="-82"
+144="-22"
+145="7"
+146="0"
+147="-30"
+148="76"
+149="-47"
+
+[neuron_values]
+0="48"
+1="-85"
+2="-26"
+3="47"
+4="-93"
+5="-9"
+6="-91"
+7="84"
+8="50"
+9="-12"
+10="0"
+11="-59"
+12="-89"
+13="98"
+14="53"
+15="-83"
+16="-91"
+17="-90"
+18="-56"
+19="0"
+20="59"
+21="-13"
+22="52"
+23="-70"
+24="41"
+25="76"
+26="47"
+27="-31"
+28="79"
+29="0"
+30="0"
+31="25"
+32="-59"
+33="0"
+34="-38"
+35="-85"
+36="-60"
+37="-42"
+38="-55"
+39="-70"
+40="-27"
+41="-95"
+42="-87"
+43="-55"
+44="92"
+45="-12"
+46="-21"
+47="-76"
+48="4"
+49="97"
+50="58"
+51="-79"
+52="71"
+53="-90"
+54="-72"
+55="0"
+56="-14"
+57="-94"
+58="-15"
+59="66"
+60="-54"
+61="9"
+62="67"
+63="-47"
+64="-74"
+65="-36"
+66="-39"
+67="51"
+68="0"
+69="-3"
+70="48"
+71="0"
+72="-41"
+73="4"
+74="41"
+75="-46"
+76="18"
+77="0"
+78="51"
+79="-49"
+
+[neuron_functions]
+0="1"
+1="0"
+2="1"
+3="2"
+4="0"
+5="2"
+6="0"
+7="0"
+8="0"
+9="0"
+10="2"
+11="1"
+12="2"
+13="2"
+14="2"
+15="1"
+16="2"
+17="2"
+18="2"
+19="2"
+20="2"
+21="1"
+22="0"
+23="2"
+24="2"
+25="1"
+26="0"
+27="1"
+28="0"
+29="2"
+30="1"
+31="2"
+32="2"
+33="1"
+34="2"
+35="1"
+36="0"
+37="1"
+38="2"
+39="1"
+40="2"
+41="2"
+42="2"
+43="1"
+44="0"
+45="1"
+46="2"
+47="2"
+48="0"
+49="0"
+50="1"
+51="0"
+52="2"
+53="1"
+54="0"
+55="1"
+56="2"
+57="0"
+58="1"
+59="1"
+60="0"
+61="0"
+62="1"
+63="0"
+64="0"
+65="2"
+66="2"
+67="2"
+68="1"
+69="0"
+70="0"
+71="1"
+72="2"
+73="2"
+74="1"
+75="0"
+76="0"
+77="2"
+78="2"
+79="1"
+
+[fneurons]
+0="482938525"
+1="1323289279"
+2="1154975886"
+3="3850610167"
+4="2325197375"
+5="72672609"
+6="3177653318"
+7="2470637805"
+8="1670592797"
+9="906269786"
+10="1526985352"
+11="2815572333"
+12="1173298984"
+13="1885154951"
+14="1523685677"
+15="1175155510"
+16="2863175513"
+17="2956009518"
+18="2788417044"
+19="1123523384"
+20="131413436"
+21="2840577824"
+22="3271016660"
+23="2817506633"
+24="1066463961"
+25="1425037041"
+26="2550820714"
+27="4142541183"
+28="4078712499"
+29="117894310"
+30="2200895127"
+31="3463099423"
+32="3891648480"
+33="2047251290"
+34="4144223227"
+35="1032997214"
+36="263449493"
+37="2279562880"
+38="1161120916"
+39="4153896190"
+40="3464013214"
+41="736468043"
+42="2046764308"
+43="3994786385"
+44="3381673767"
+45="1426202340"
+46="1267797649"
+47="2484017495"
+48="2824408371"
+49="3014148188"
+50="2158737554"
+51="735548966"
+52="2400772218"
+53="2821059969"
+54="757174171"
+55="867489696"
+56="1359489203"
+57="4020366408"
+58="2609642563"
+59="701416851"

=== added file 'data/ai/ai_input_2.wai'
--- data/ai/ai_input_2.wai	1970-01-01 00:00:00 +0000
+++ data/ai/ai_input_2.wai	2017-07-24 20:38:49 +0000
@@ -0,0 +1,379 @@
+# Automatically created by Widelands bzr[] (Debug)
+
+[magic_numbers]
+0="18"
+1="-47"
+2="21"
+3="35"
+4="-7"
+5="-78"
+6="-53"
+7="81"
+8="0"
+9="0"
+10="-55"
+11="22"
+12="-92"
+13="48"
+14="70"
+15="-30"
+16="26"
+17="79"
+18="-63"
+19="-12"
+20="79"
+21="-28"
+22="13"
+23="39"
+24="0"
+25="3"
+26="45"
+27="-33"
+28="53"
+29="51"
+30="-93"
+31="47"
+32="-42"
+33="90"
+34="-72"
+35="52"
+36="-68"
+37="-47"
+38="17"
+39="-72"
+40="51"
+41="51"
+42="-2"
+43="-40"
+44="47"
+45="7"
+46="6"
+47="3"
+48="-64"
+49="-41"
+50="-3"
+51="-55"
+52="62"
+53="0"
+54="57"
+55="-92"
+56="4"
+57="-89"
+58="66"
+59="-44"
+60="-100"
+61="56"
+62="19"
+63="-34"
+64="-20"
+65="24"
+66="-54"
+67="84"
+68="56"
+69="-51"
+70="0"
+71="44"
+72="0"
+73="-2"
+74="-11"
+75="-4"
+76="-96"
+77="-34"
+78="0"
+79="-31"
+80="71"
+81="-98"
+82="-25"
+83="-44"
+84="58"
+85="68"
+86="0"
+87="28"
+88="-54"
+89="23"
+90="21"
+91="53"
+92="80"
+93="0"
+94="-41"
+95="58"
+96="87"
+97="27"
+98="-73"
+99="-65"
+100="14"
+101="-42"
+102="31"
+103="-92"
+104="-62"
+105="89"
+106="-55"
+107="-63"
+108="0"
+109="-40"
+110="77"
+111="0"
+112="-65"
+113="0"
+114="32"
+115="-26"
+116="0"
+117="0"
+118="-70"
+119="74"
+120="85"
+121="0"
+122="52"
+123="48"
+124="-30"
+125="47"
+126="-61"
+127="62"
+128="60"
+129="8"
+130="-52"
+131="46"
+132="100"
+133="-74"
+134="19"
+135="83"
+136="-9"
+137="-100"
+138="36"
+139="-4"
+140="77"
+141="15"
+142="-57"
+143="-82"
+144="-22"
+145="7"
+146="0"
+147="-30"
+148="76"
+149="-47"
+
+[neuron_values]
+0="48"
+1="-85"
+2="-26"
+3="47"
+4="-93"
+5="-9"
+6="-91"
+7="84"
+8="50"
+9="-12"
+10="0"
+11="-59"
+12="-89"
+13="98"
+14="53"
+15="-83"
+16="-91"
+17="-90"
+18="-56"
+19="0"
+20="59"
+21="-13"
+22="52"
+23="-70"
+24="41"
+25="76"
+26="47"
+27="-31"
+28="79"
+29="0"
+30="0"
+31="25"
+32="-59"
+33="0"
+34="-38"
+35="-85"
+36="-60"
+37="-42"
+38="-55"
+39="-70"
+40="-27"
+41="-95"
+42="-87"
+43="-55"
+44="92"
+45="-12"
+46="-21"
+47="-76"
+48="4"
+49="97"
+50="58"
+51="-79"
+52="71"
+53="-90"
+54="-72"
+55="0"
+56="-14"
+57="-94"
+58="-15"
+59="66"
+60="-54"
+61="9"
+62="67"
+63="-47"
+64="-74"
+65="-36"
+66="-39"
+67="51"
+68="0"
+69="-3"
+70="48"
+71="0"
+72="-41"
+73="4"
+74="41"
+75="-46"
+76="18"
+77="0"
+78="51"
+79="-49"
+
+[neuron_functions]
+0="1"
+1="0"
+2="1"
+3="2"
+4="0"
+5="2"
+6="0"
+7="0"
+8="0"
+9="0"
+10="2"
+11="1"
+12="2"
+13="2"
+14="2"
+15="1"
+16="2"
+17="2"
+18="2"
+19="2"
+20="2"
+21="1"
+22="0"
+23="2"
+24="2"
+25="1"
+26="0"
+27="1"
+28="0"
+29="2"
+30="1"
+31="2"
+32="2"
+33="1"
+34="2"
+35="1"
+36="0"
+37="1"
+38="2"
+39="1"
+40="2"
+41="2"
+42="2"
+43="1"
+44="0"
+45="1"
+46="2"
+47="2"
+48="0"
+49="0"
+50="1"
+51="0"
+52="0"
+53="1"
+54="0"
+55="1"
+56="2"
+57="0"
+58="1"
+59="1"
+60="0"
+61="0"
+62="1"
+63="0"
+64="0"
+65="2"
+66="2"
+67="2"
+68="1"
+69="0"
+70="0"
+71="1"
+72="2"
+73="2"
+74="1"
+75="0"
+76="0"
+77="2"
+78="2"
+79="1"
+
+[fneurons]
+0="482938517"
+1="1323297471"
+2="1154975886"
+3="3850610167"
+4="2325197375"
+5="72672609"
+6="3177653318"
+7="2470637805"
+8="1670592797"
+9="906269786"
+10="1526985352"
+11="2815572333"
+12="1173298984"
+13="1884892807"
+14="1523652909"
+15="1175155510"
+16="2863175513"
+17="2953125930"
+18="2788417044"
+19="1122474808"
+20="131413436"
+21="2840577824"
+22="3271016660"
+23="2817441097"
+24="1066463965"
+25="1425037041"
+26="2550820714"
+27="3068799359"
+28="4078712499"
+29="117894310"
+30="2201943703"
+31="3463099423"
+32="3891648480"
+33="2047251290"
+34="4144223227"
+35="1032997214"
+36="263449493"
+37="2279562880"
+38="1161120916"
+39="4153896190"
+40="3464013214"
+41="736468043"
+42="2046764308"
+43="3998980689"
+44="3381673767"
+45="1426202340"
+46="1267797649"
+47="2484017495"
+48="2824408371"
+49="3014148188"
+50="2158737554"
+51="735548966"
+52="2400837754"
+53="2821059969"
+54="757174171"
+55="867489696"
+56="1359489203"
+57="4020366400"
+58="2609642563"
+59="701416851"

=== added file 'data/ai/ai_input_3.wai'
--- data/ai/ai_input_3.wai	1970-01-01 00:00:00 +0000
+++ data/ai/ai_input_3.wai	2017-07-24 20:38:49 +0000
@@ -0,0 +1,379 @@
+# Automatically created by Widelands bzr[] (Debug)
+
+[magic_numbers]
+0="18"
+1="-47"
+2="21"
+3="35"
+4="-7"
+5="-78"
+6="-53"
+7="81"
+8="0"
+9="0"
+10="-55"
+11="22"
+12="-92"
+13="48"
+14="87"
+15="-30"
+16="58"
+17="79"
+18="-63"
+19="-12"
+20="79"
+21="-28"
+22="13"
+23="39"
+24="-22"
+25="3"
+26="45"
+27="-33"
+28="53"
+29="51"
+30="-93"
+31="47"
+32="-42"
+33="90"
+34="-72"
+35="52"
+36="-68"
+37="-47"
+38="17"
+39="-72"
+40="51"
+41="51"
+42="-10"
+43="-40"
+44="47"
+45="7"
+46="6"
+47="3"
+48="-64"
+49="-41"
+50="-3"
+51="-55"
+52="62"
+53="0"
+54="57"
+55="-92"
+56="4"
+57="-89"
+58="66"
+59="-44"
+60="-87"
+61="56"
+62="66"
+63="-34"
+64="-20"
+65="24"
+66="-54"
+67="84"
+68="56"
+69="-51"
+70="-26"
+71="44"
+72="0"
+73="-2"
+74="-11"
+75="-4"
+76="-96"
+77="-34"
+78="-29"
+79="-31"
+80="71"
+81="-98"
+82="-25"
+83="-44"
+84="58"
+85="76"
+86="0"
+87="28"
+88="-4"
+89="23"
+90="21"
+91="53"
+92="80"
+93="0"
+94="-41"
+95="58"
+96="6"
+97="27"
+98="-73"
+99="-65"
+100="14"
+101="-42"
+102="31"
+103="-92"
+104="-62"
+105="89"
+106="-55"
+107="-63"
+108="0"
+109="-40"
+110="77"
+111="0"
+112="-65"
+113="0"
+114="32"
+115="-26"
+116="0"
+117="0"
+118="-70"
+119="74"
+120="85"
+121="0"
+122="52"
+123="48"
+124="-30"
+125="25"
+126="-61"
+127="62"
+128="60"
+129="8"
+130="-52"
+131="88"
+132="100"
+133="-74"
+134="19"
+135="83"
+136="-9"
+137="-100"
+138="36"
+139="-4"
+140="77"
+141="15"
+142="-57"
+143="-82"
+144="16"
+145="7"
+146="0"
+147="-30"
+148="76"
+149="-47"
+
+[neuron_values]
+0="48"
+1="-85"
+2="-26"
+3="47"
+4="-93"
+5="0"
+6="-91"
+7="84"
+8="50"
+9="-12"
+10="0"
+11="-59"
+12="-89"
+13="82"
+14="53"
+15="-83"
+16="-91"
+17="-90"
+18="-56"
+19="0"
+20="59"
+21="-13"
+22="52"
+23="-70"
+24="41"
+25="76"
+26="47"
+27="-31"
+28="79"
+29="0"
+30="0"
+31="25"
+32="-59"
+33="0"
+34="-38"
+35="-85"
+36="-60"
+37="-42"
+38="-55"
+39="-70"
+40="-27"
+41="-95"
+42="-87"
+43="-55"
+44="98"
+45="-12"
+46="-21"
+47="-76"
+48="4"
+49="97"
+50="58"
+51="-79"
+52="71"
+53="-90"
+54="-72"
+55="0"
+56="-14"
+57="-94"
+58="-14"
+59="66"
+60="-54"
+61="9"
+62="67"
+63="-47"
+64="-74"
+65="-36"
+66="-39"
+67="51"
+68="0"
+69="-3"
+70="48"
+71="-28"
+72="-41"
+73="4"
+74="41"
+75="-46"
+76="18"
+77="0"
+78="51"
+79="-49"
+
+[neuron_functions]
+0="1"
+1="0"
+2="1"
+3="2"
+4="0"
+5="2"
+6="0"
+7="0"
+8="0"
+9="0"
+10="2"
+11="1"
+12="2"
+13="2"
+14="2"
+15="1"
+16="2"
+17="2"
+18="2"
+19="2"
+20="2"
+21="1"
+22="0"
+23="2"
+24="2"
+25="1"
+26="0"
+27="1"
+28="0"
+29="2"
+30="1"
+31="2"
+32="2"
+33="1"
+34="2"
+35="1"
+36="0"
+37="1"
+38="2"
+39="1"
+40="2"
+41="2"
+42="2"
+43="1"
+44="0"
+45="1"
+46="2"
+47="2"
+48="0"
+49="0"
+50="1"
+51="0"
+52="0"
+53="1"
+54="0"
+55="1"
+56="2"
+57="0"
+58="1"
+59="1"
+60="0"
+61="0"
+62="1"
+63="0"
+64="0"
+65="2"
+66="2"
+67="2"
+68="1"
+69="0"
+70="0"
+71="1"
+72="2"
+73="2"
+74="1"
+75="1"
+76="0"
+77="2"
+78="2"
+79="1"
+
+[fneurons]
+0="478692225"
+1="1323297471"
+2="1154975886"
+3="3850610167"
+4="2329391679"
+5="22339937"
+6="3177653318"
+7="3544380140"
+8="1670592781"
+9="906335322"
+10="1527247496"
+11="2816088429"
+12="1173298728"
+13="1885089415"
+14="1523652909"
+15="1175155518"
+16="2854786889"
+17="2956025902"
+18="2792611349"
+19="1123523384"
+20="131413949"
+21="2840561442"
+22="3405234388"
+23="2817441033"
+24="529855197"
+25="1425037041"
+26="2552917866"
+27="3068799359"
+28="4078712499"
+29="117861542"
+30="2201943703"
+31="3463099423"
+32="3891648480"
+33="2047251290"
+34="4144223227"
+35="1066551630"
+36="263449493"
+37="2279562880"
+38="1169509524"
+39="4153871614"
+40="3464144286"
+41="736468299"
+42="1509893396"
+43="3994786385"
+44="3381673765"
+45="1963073253"
+46="1267797649"
+47="2215582039"
+48="2824408371"
+49="3014148190"
+50="2158737562"
+51="735516198"
+52="2383995002"
+53="2821059969"
+54="757173147"
+55="867491744"
+56="1360537779"
+57="4020366408"
+58="2609634371"
+59="802080147"

=== added file 'data/ai/ai_input_4.wai'
--- data/ai/ai_input_4.wai	1970-01-01 00:00:00 +0000
+++ data/ai/ai_input_4.wai	2017-07-24 20:38:49 +0000
@@ -0,0 +1,379 @@
+# Automatically created by Widelands bzr[] (Debug)
+
+[magic_numbers]
+0="18"
+1="-47"
+2="21"
+3="35"
+4="-7"
+5="-78"
+6="-53"
+7="81"
+8="0"
+9="0"
+10="-55"
+11="22"
+12="-92"
+13="48"
+14="70"
+15="-30"
+16="26"
+17="79"
+18="-63"
+19="-12"
+20="79"
+21="-28"
+22="13"
+23="39"
+24="0"
+25="3"
+26="45"
+27="-33"
+28="53"
+29="51"
+30="-93"
+31="47"
+32="-42"
+33="90"
+34="-72"
+35="52"
+36="-68"
+37="-47"
+38="17"
+39="-72"
+40="51"
+41="51"
+42="-20"
+43="-40"
+44="47"
+45="7"
+46="6"
+47="3"
+48="-64"
+49="-41"
+50="-3"
+51="-55"
+52="62"
+53="0"
+54="57"
+55="-92"
+56="4"
+57="-89"
+58="66"
+59="-44"
+60="-87"
+61="56"
+62="19"
+63="-34"
+64="-20"
+65="24"
+66="-54"
+67="84"
+68="56"
+69="-51"
+70="0"
+71="44"
+72="0"
+73="-2"
+74="-11"
+75="-4"
+76="-96"
+77="-34"
+78="0"
+79="-31"
+80="71"
+81="-98"
+82="-25"
+83="-44"
+84="58"
+85="68"
+86="0"
+87="28"
+88="-54"
+89="23"
+90="21"
+91="53"
+92="80"
+93="0"
+94="-41"
+95="58"
+96="53"
+97="27"
+98="-73"
+99="-65"
+100="14"
+101="-42"
+102="31"
+103="-92"
+104="-62"
+105="89"
+106="-55"
+107="-63"
+108="0"
+109="-40"
+110="77"
+111="0"
+112="-65"
+113="0"
+114="32"
+115="-26"
+116="0"
+117="0"
+118="-70"
+119="74"
+120="85"
+121="0"
+122="52"
+123="48"
+124="-30"
+125="25"
+126="-61"
+127="62"
+128="60"
+129="8"
+130="-52"
+131="46"
+132="100"
+133="-74"
+134="19"
+135="83"
+136="-9"
+137="-100"
+138="36"
+139="-4"
+140="77"
+141="15"
+142="-57"
+143="-82"
+144="-22"
+145="7"
+146="0"
+147="-30"
+148="76"
+149="-47"
+
+[neuron_values]
+0="48"
+1="-85"
+2="-26"
+3="47"
+4="-93"
+5="-9"
+6="-91"
+7="84"
+8="50"
+9="-12"
+10="0"
+11="-59"
+12="-89"
+13="98"
+14="53"
+15="-83"
+16="-91"
+17="-90"
+18="-56"
+19="0"
+20="59"
+21="-13"
+22="52"
+23="-70"
+24="41"
+25="76"
+26="47"
+27="-31"
+28="79"
+29="0"
+30="0"
+31="25"
+32="-59"
+33="0"
+34="-38"
+35="-85"
+36="-60"
+37="-42"
+38="-55"
+39="-70"
+40="-27"
+41="-95"
+42="-87"
+43="-55"
+44="98"
+45="-12"
+46="-21"
+47="-76"
+48="4"
+49="97"
+50="58"
+51="-79"
+52="71"
+53="-90"
+54="-72"
+55="0"
+56="-14"
+57="-94"
+58="-15"
+59="66"
+60="-54"
+61="9"
+62="67"
+63="-47"
+64="-74"
+65="-36"
+66="-39"
+67="51"
+68="0"
+69="-3"
+70="48"
+71="0"
+72="-41"
+73="4"
+74="41"
+75="-46"
+76="18"
+77="0"
+78="51"
+79="-49"
+
+[neuron_functions]
+0="1"
+1="0"
+2="1"
+3="2"
+4="0"
+5="2"
+6="0"
+7="0"
+8="0"
+9="0"
+10="2"
+11="1"
+12="2"
+13="2"
+14="2"
+15="1"
+16="2"
+17="2"
+18="2"
+19="2"
+20="2"
+21="1"
+22="0"
+23="2"
+24="2"
+25="1"
+26="0"
+27="1"
+28="0"
+29="2"
+30="1"
+31="2"
+32="2"
+33="1"
+34="2"
+35="1"
+36="0"
+37="1"
+38="2"
+39="1"
+40="2"
+41="2"
+42="2"
+43="1"
+44="0"
+45="1"
+46="2"
+47="2"
+48="0"
+49="0"
+50="1"
+51="0"
+52="0"
+53="1"
+54="0"
+55="1"
+56="2"
+57="0"
+58="1"
+59="1"
+60="0"
+61="0"
+62="1"
+63="0"
+64="0"
+65="2"
+66="2"
+67="2"
+68="1"
+69="0"
+70="0"
+71="1"
+72="2"
+73="2"
+74="1"
+75="0"
+76="0"
+77="2"
+78="2"
+79="1"
+
+[fneurons]
+0="482938517"
+1="1323297471"
+2="1154975886"
+3="3850610167"
+4="2325164607"
+5="72672609"
+6="3177653318"
+7="2470637805"
+8="1670592797"
+9="906269776"
+10="1526985352"
+11="2815572333"
+12="1173298984"
+13="1885154951"
+14="1523652909"
+15="1175155510"
+16="2863175513"
+17="2956533806"
+18="2788417044"
+19="1123523384"
+20="131413436"
+21="2840577824"
+22="3271016916"
+23="2817506633"
+24="1066463965"
+25="1425037041"
+26="2550820714"
+27="3068799359"
+28="4078712499"
+29="101117094"
+30="2201943703"
+31="3463099423"
+32="3891648481"
+33="2046989146"
+34="4144223227"
+35="1032997214"
+36="263449493"
+37="2279562880"
+38="1161120916"
+39="4153896190"
+40="3464013214"
+41="736468043"
+42="2046764308"
+43="3994786385"
+44="3381673767"
+45="1426202340"
+46="1267797649"
+47="2484017495"
+48="2824408371"
+49="3014148188"
+50="2158737554"
+51="735548966"
+52="2400772218"
+53="2284189057"
+54="757174171"
+55="867620768"
+56="1359489203"
+57="4020366408"
+58="2609642563"
+59="701416851"

=== modified file 'data/tribes/atlanteans.lua'
--- data/tribes/atlanteans.lua	2017-06-26 19:48:43 +0000
+++ data/tribes/atlanteans.lua	2017-07-24 20:38:49 +0000
@@ -352,7 +352,6 @@
    headquarters = "atlanteans_headquarters",
    port = "atlanteans_port",
    barracks = "atlanteans_barracks",
-   bakery = "atlanteans_bakery",
    ironore = "iron_ore",
    rawlog = "log",
    refinedlog = "planks",

=== modified file 'data/tribes/barbarians.lua'
--- data/tribes/barbarians.lua	2017-06-26 19:48:43 +0000
+++ data/tribes/barbarians.lua	2017-07-24 20:38:49 +0000
@@ -285,7 +285,6 @@
    headquarters = "barbarians_headquarters",
    port = "barbarians_port",
    barracks = "barbarians_barracks",
-   bakery = "barbarians_bakery",
    ironore = "iron_ore",
    rawlog = "log",
    refinedlog = "blackwood",

=== modified file 'data/tribes/empire.lua'
--- data/tribes/empire.lua	2017-06-26 19:48:43 +0000
+++ data/tribes/empire.lua	2017-07-24 20:38:49 +0000
@@ -326,7 +326,6 @@
    headquarters = "empire_headquarters",
    port = "empire_port",
    barracks = "empire_barracks",
-   bakery = "empire_bakery",
    ironore = "iron_ore",
    rawlog = "log",
    refinedlog = "planks",

=== modified file 'src/ai/ai_help_structs.cc'
--- src/ai/ai_help_structs.cc	2017-07-04 11:34:00 +0000
+++ src/ai/ai_help_structs.cc	2017-07-24 20:38:49 +0000
@@ -21,17 +21,19 @@
 
 #include "base/macros.h"
 #include "base/time_string.h"
+#include "logic/ai_dna_handler.h"
 #include "logic/map.h"
 #include "logic/player.h"
 
+namespace Widelands {
+
 // couple of constants for calculation of road interconnections
 constexpr int kRoadNotFound = -1000;
 constexpr int kShortcutWithinSameEconomy = 1000;
 constexpr int kRoadToDifferentEconomy = 10000;
-constexpr int kUpperDefaultMutationLimit = 200;
-constexpr int kLowerDefaultMutationLimit = 150;
-
-namespace Widelands {
+constexpr int kUpperDefaultMutationLimit = 150;
+constexpr int kLowerDefaultMutationLimit = 75;
+constexpr int16_t kPrefNumberProbability = (kAITrainingMode) ? 5 : 100;
 
 // CheckStepRoadAI
 CheckStepRoadAI::CheckStepRoadAI(Player* const pl, uint8_t const mc, bool const oe)
@@ -344,6 +346,7 @@
 	primary_parent = 255;
 	next_neuron_id = 0;
 	performance_change = 0;
+	AiDnaHandler ai_dna_handler();
 }
 
 // Initialization of neuron. Neuron is defined by curve (type) and weight [-kWeightRange,
@@ -472,7 +475,9 @@
                             const uint16_t attackers,
                             const int16_t trained_soldiers,
                             const int16_t latest_attackers,
-                            const uint16_t conq_ws) {
+                            const uint16_t conq_ws,
+                            const uint16_t m_strength,
+                            const uint32_t existing_ps) {
 
 	const int16_t main_bonus =
 	   ((static_cast<int32_t>(land - old_land) > 0 && land > max_e_land * 5 / 6 && attackers > 0 &&
@@ -482,15 +487,21 @@
 
 	const int16_t land_delta_bonus = static_cast<int16_t>(land - old_land) * kLandDeltaMultiplier;
 
+	const uint32_t ps_sites_bonus =
+	   kPSitesRatioMultiplier * existing_ps * existing_ps * existing_ps / 1000 / 1000;
+
 	score = land / kCurrentLandDivider + land_delta_bonus + main_bonus +
 	        attackers * kAttackersMultiplier + ((attackers > 0) ? kAttackBonus : -kAttackBonus) +
-	        trained_soldiers * kTrainedSoldiersScore + +kConqueredWhBonus + conq_ws;
+	        trained_soldiers * kTrainedSoldiersScore + kConqueredWhBonus * conq_ws +
+	        m_strength * kStrengthMultiplier + ps_sites_bonus - 500 * kPSitesRatioMultiplier;
 
-	log(" %2d %s: reviewing AI mngm. data, sc: %5d Pr.p: %d (l: %4d / %4d / %4d, "
-	    "at:%4d(%3d), ts:%4d(%2d), ConqWH:%2d)\n",
+	log(" %2d %s: reviewing AI mngm. data, sc: %5d Pr.p: %d (l:%4d/%s/%4d, "
+	    "at:%4d(%3d),ts:%4d/%2d,cWH:%2d,str:%2d/%4d,ps:%4d/%4d)\n",
 	    pn, gamestring_with_leading_zeros(gametime), score, primary_parent,
-	    land / kCurrentLandDivider, main_bonus, land_delta_bonus, attackers * kAttackersMultiplier,
-	    latest_attackers, trained_soldiers * kTrainedSoldiersScore, trained_soldiers, conq_ws);
+	    land / kCurrentLandDivider, (main_bonus) ? "*" : " ", land_delta_bonus,
+	    attackers * kAttackersMultiplier, latest_attackers, trained_soldiers * kTrainedSoldiersScore,
+	    trained_soldiers, conq_ws, m_strength, m_strength * kStrengthMultiplier, existing_ps,
+	    ps_sites_bonus);
 
 	if (score < -10000 || score > 30000) {
 		log("%2d %s: reviewing AI mngm. data, score too extreme: %4d\n", pn,
@@ -507,403 +518,42 @@
 
 	log("%2d: DNA initialization... \n", pn);
 
-	// AutoSCore_AIDNA_1
-	const std::vector<int16_t> AI_initial_military_numbers_A = {
-	   18,  -42, 21,  59,  -7,  -78,
-	   -22, 81,  48,  0,  //  AutoContent_01_AIDNA_1
-	   -82, 45,  -96, 16,  70,  -30,
-	   33,  79,  -78, -42,  //  AutoContent_02_AIDNA_1
-	   79,  -16, 34,  46,  -22, 0,
-	   45,  -29, 53,  51,  //  AutoContent_03_AIDNA_1
-	   24,  47,  -27, 80,  -86, 46,
-	   -63, -47, 20,  -63,  //  AutoContent_04_AIDNA_1
-	   78,  51,  -11, -77, 20,  38,
-	   6,   37,  -64, -41,  //  AutoContent_05_AIDNA_1
-	   -3,  -55, 62,  0,   64,  -92,
-	   4,   -89, 71,  -18,  //  AutoContent_06_AIDNA_1
-	   -87, 56,  17,  -34, -69, 24,
-	   -57, 84,  40,  -51,  //  AutoContent_07_AIDNA_1
-	   0,   44,  0,   -2,  -11, -4,
-	   -96, -35, -29, -12,  //  AutoContent_08_AIDNA_1
-	   71,  -98, -25, 50,  97,  74,
-	   0,   65,  -60, 23,  //  AutoContent_09_AIDNA_1
-	   38,  53,  74,  0,   -43, 27,
-	   32,  37,  -24, -65,  //  AutoContent_10_AIDNA_1
-	   16,  -42, 19,  -94, -28, 83,
-	   -55, -63, 16,  -41,  //  AutoContent_11_AIDNA_1
-	   28,  -3,  0,   -87, 32,  5,
-	   4,   6,   -20, 62,  //  AutoContent_12_AIDNA_1
-	   85,  0,   58,  48,  -80, -20,
-	   -49, 71,  60,  8,  //  AutoContent_13_AIDNA_1
-	   -52, 59,  100, -74, 0,   -36,
-	   -9,  80,  41,  -67,  //  AutoContent_14_AIDNA_1
-	   0,   15,  -96, -51, -21, 11,
-	   -27, -30, 76,  -47  //  AutoContent_15_AIDNA_1
-	};
-
-	assert(kMagicNumbersSize == AI_initial_military_numbers_A.size());
-
-	const std::vector<int8_t> input_weights_A =
-	   //  0     1     2     3     4     5     6     7     8     9
-	   {
-	      48,  -85, -26, 47,  -93, -22,
-	      -91, 84,  24,  -12,  //  AutoContent_16_AIDNA_1
-	      98,  -59, -89, 76,  81,  95,
-	      -91, -90, -56, -15,  //  AutoContent_17_AIDNA_1
-	      -65, -18, 6,   -65, 41,  38,
-	      47,  -31, 79,  23,  //  AutoContent_18_AIDNA_1
-	      16,  25,  -59, 0,   -38, -85,
-	      -60, -42, 0,   -70,  //  AutoContent_19_AIDNA_1
-	      -78, -86, -87, -55, 92,  -63,
-	      -21, -76, 4,   87,  //  AutoContent_20_AIDNA_1
-	      58,  -40, 71,  -90, -72, 0,
-	      -47, -94, -15, 66,  //  AutoContent_21_AIDNA_1
-	      -32, 9,   67,  -47, -44, -76,
-	      -53, 57,  -31, -47,  //  AutoContent_22_AIDNA_1
-	      0,   -28, -16, 48,  41,  -45,
-	      36,  -8,  51,  -49  //  AutoContent_23_AIDNA_1
-	   };
-	const std::vector<int8_t> input_func_A = {
-	   1, 0, 1, 2, 2, 1,
-	   0, 0, 0, 0,  //  AutoContent_24_AIDNA_1
-	   2, 1, 2, 2, 2, 1,
-	   2, 2, 2, 1,  //  AutoContent_25_AIDNA_1
-	   2, 2, 0, 2, 2, 1,
-	   0, 1, 0, 2,  //  AutoContent_26_AIDNA_1
-	   1, 2, 2, 1, 2, 1,
-	   0, 1, 2, 1,  //  AutoContent_27_AIDNA_1
-	   2, 1, 2, 0, 0, 1,
-	   2, 0, 0, 0,  //  AutoContent_28_AIDNA_1
-	   1, 0, 0, 1, 0, 1,
-	   0, 0, 1, 1,  //  AutoContent_29_AIDNA_1
-	   2, 0, 1, 2, 0, 2,
-	   2, 2, 1, 0,  //  AutoContent_30_AIDNA_1
-	   2, 1, 2, 2, 1, 1,
-	   0, 2, 2, 1  //  AutoContent_31_AIDNA_1
-	};
-	assert(kNeuronPoolSize == input_func_A.size());
-	assert(kNeuronPoolSize == input_weights_A.size());
-
-	const std::vector<uint32_t> f_neurons_A = {
-	   471130763,  1322756799, 1148682382, 2713953719, 194460207,  18113635,
-	   2947490886, 3275944172, 3438582086, 856208494,  //  AutoContent_32_AIDNA_1
-	   1326156684, 986431571,  3465514749, 1962749574, 1523585333, 1376482111,
-	   1223335901, 2962231598, 657710612,  578259960,  //  AutoContent_33_AIDNA_1
-	   1271222963, 2915927856, 3396846486, 1743568169, 2679432920, 410834609,
-	   134904175,  2968201710, 2132567223, 2248461478,  //  AutoContent_34_AIDNA_1
-	   161963959,  3295327519, 670058472,  2013696856, 3608400883, 496651103,
-	   733137541,  2952748738, 3307293853, 3886490843,  //  AutoContent_35_AIDNA_1
-	   3233788172, 715230539,  2583635732, 4271028953, 1217674278, 4043323645,
-	   1857109651, 2181897047, 2825979187, 3081298269,  //  AutoContent_36_AIDNA_1
-	   1277901018, 1255642150, 2384261818, 2866704864, 755617465,  835768208,
-	   1394358417, 4012239945, 2601238115, 3933467106  //  AutoContent_37_AIDNA_1
-	};
-	assert(kFNeuronPoolSize == f_neurons_A.size());
-
-	// AutoSCore_AIDNA_2
-	const std::vector<int16_t> AI_initial_military_numbers_B = {
-	   18,  -42, 21,  59,  -7,  -78,
-	   -22, 81,  48,  0,  //  AutoContent_01_AIDNA_2
-	   -55, 45,  -96, 16,  70,  -30,
-	   33,  79,  -78, -42,  //  AutoContent_02_AIDNA_2
-	   79,  -16, 34,  46,  -22, 0,
-	   45,  -33, 53,  51,  //  AutoContent_03_AIDNA_2
-	   49,  47,  -27, 80,  -86, 46,
-	   -63, -47, 20,  -63,  //  AutoContent_04_AIDNA_2
-	   78,  51,  23,  -77, 20,  38,
-	   6,   37,  -64, -41,  //  AutoContent_05_AIDNA_2
-	   -3,  -55, 62,  0,   64,  -92,
-	   4,   -89, 71,  -18,  //  AutoContent_06_AIDNA_2
-	   -87, 56,  17,  -34, -69, 24,
-	   -57, 84,  40,  -51,  //  AutoContent_07_AIDNA_2
-	   0,   44,  0,   -2,  -11, -4,
-	   -96, -35, -29, -12,  //  AutoContent_08_AIDNA_2
-	   71,  -98, -25, 50,  97,  74,
-	   0,   65,  -60, 23,  //  AutoContent_09_AIDNA_2
-	   38,  53,  74,  0,   -15, 27,
-	   32,  37,  -24, -65,  //  AutoContent_10_AIDNA_2
-	   16,  -42, 19,  -94, -28, 83,
-	   -55, -63, 16,  -41,  //  AutoContent_11_AIDNA_2
-	   28,  -3,  0,   -87, 32,  5,
-	   4,   6,   -20, 62,  //  AutoContent_12_AIDNA_2
-	   85,  0,   58,  48,  -80, -20,
-	   -49, 71,  60,  8,  //  AutoContent_13_AIDNA_2
-	   -52, 59,  100, -74, 0,   -36,
-	   -9,  80,  41,  -67,  //  AutoContent_14_AIDNA_2
-	   0,   15,  -96, -51, -21, 11,
-	   -27, -30, 76,  -47  //  AutoContent_15_AIDNA_2
-	};
-	assert(kMagicNumbersSize == AI_initial_military_numbers_B.size());
-
-	const std::vector<int8_t> input_weights_B = {
-	   48,  -85, -26, 47,  -93, -22,
-	   -91, 84,  50,  -12,  //  AutoContent_16_AIDNA_2
-	   98,  -59, -89, 76,  81,  95,
-	   -91, -90, -56, -15,  //  AutoContent_17_AIDNA_2
-	   -65, -18, 6,   -65, 41,  38,
-	   47,  -31, 79,  23,  //  AutoContent_18_AIDNA_2
-	   16,  25,  -59, 0,   -38, -85,
-	   -60, -42, 0,   -70,  //  AutoContent_19_AIDNA_2
-	   -78, -86, -87, -55, 92,  -63,
-	   -21, -76, 4,   87,  //  AutoContent_20_AIDNA_2
-	   58,  -40, 71,  -90, -72, 0,
-	   -47, -94, -15, 66,  //  AutoContent_21_AIDNA_2
-	   -32, 9,   67,  -47, -44, -76,
-	   -53, 57,  -31, -47,  //  AutoContent_22_AIDNA_2
-	   0,   -28, -16, 48,  41,  -45,
-	   36,  -8,  51,  -49  //  AutoContent_23_AIDNA_2
-	};
-
-	const std::vector<int8_t> input_func_B = {
-	   1, 0, 1, 2, 2, 1,
-	   0, 0, 0, 0,  //  AutoContent_24_AIDNA_2
-	   2, 1, 2, 2, 2, 1,
-	   2, 2, 2, 1,  //  AutoContent_25_AIDNA_2
-	   2, 2, 0, 2, 2, 1,
-	   0, 1, 0, 2,  //  AutoContent_26_AIDNA_2
-	   1, 2, 2, 1, 2, 1,
-	   0, 1, 2, 1,  //  AutoContent_27_AIDNA_2
-	   2, 1, 2, 0, 0, 1,
-	   2, 0, 0, 0,  //  AutoContent_28_AIDNA_2
-	   1, 0, 0, 1, 0, 1,
-	   0, 0, 1, 1,  //  AutoContent_29_AIDNA_2
-	   2, 0, 1, 2, 0, 2,
-	   2, 2, 1, 0,  //  AutoContent_30_AIDNA_2
-	   2, 1, 2, 2, 1, 1,
-	   0, 2, 2, 1  //  AutoContent_31_AIDNA_2
-	};
-	assert(kNeuronPoolSize == input_func_B.size());
-	assert(kNeuronPoolSize == input_weights_B.size());
-
-	const std::vector<uint32_t> f_neurons_B = {
-	   471130763,  1322756799, 1148682382, 2713953719, 194460207,  18113635,
-	   2947490886, 3275944172, 3438582022, 855676014,  //  AutoContent_32_AIDNA_2
-	   1326156684, 986431571,  3465514749, 1962749574, 1523650869, 1376482111,
-	   2347409353, 2962227502, 657710612,  578259960,  //  AutoContent_33_AIDNA_2
-	   1271222963, 2915927856, 3396846486, 1743568169, 2679432920, 410834609,
-	   134904175,  2968201710, 2132567223, 2248461478,  //  AutoContent_34_AIDNA_2
-	   161963959,  3295327519, 670058472,  2013696856, 4145271795, 496651103,
-	   733211269,  2952748738, 1159810205, 3886490843,  //  AutoContent_35_AIDNA_2
-	   3225153820, 732007755,  2583635732, 4271028825, 1217674278, 4043323645,
-	   1857109651, 2249005911, 2825979187, 3081298269,  //  AutoContent_36_AIDNA_2
-	   1277901018, 1255642150, 2384261818, 2866704864, 755617465,  835768208,
-	   1394096273, 4012239945, 2609626723, 3932418530  //  AutoContent_37_AIDNA_2
-	};
-	assert(kFNeuronPoolSize == f_neurons_B.size());
-
-	// AutoSCore_AIDNA_3
-	const std::vector<int16_t> AI_initial_military_numbers_C =
-	   {
-	      18,  -42, 63,  82,  -7,  -78,
-	      -22, 81,  48,  0,  //  AutoContent_01_AIDNA_3
-	      -55, 55,  -96, 16,  70,  -30,
-	      33,  79,  -78, -42,  //  AutoContent_02_AIDNA_3
-	      79,  -16, 34,  46,  0,   0,
-	      0,   -29, 53,  51,  //  AutoContent_03_AIDNA_3
-	      24,  47,  -27, 42,  -86, 46,
-	      -63, -47, 20,  -63,  //  AutoContent_04_AIDNA_3
-	      78,  31,  98,  -73, 20,  38,
-	      44,  37,  -64, -41,  //  AutoContent_05_AIDNA_3
-	      -3,  -55, 67,  0,   64,  -92,
-	      4,   -89, 71,  -60,  //  AutoContent_06_AIDNA_3
-	      -87, 56,  17,  -34, -69, 24,
-	      -57, 50,  40,  -51,  //  AutoContent_07_AIDNA_3
-	      -34, 44,  0,   -2,  -11, -4,
-	      -96, -35, -29, -12,  //  AutoContent_08_AIDNA_3
-	      68,  -98, -25, 50,  97,  74,
-	      0,   65,  -60, 23,  //  AutoContent_09_AIDNA_3
-	      38,  53,  74,  0,   -15, 27,
-	      32,  61,  -24, -65,  //  AutoContent_10_AIDNA_3
-	      16,  -42, 19,  -94, -65, 83,
-	      -55, -63, 16,  -41,  //  AutoContent_11_AIDNA_3
-	      74,  -3,  0,   -87, 32,  5,
-	      4,   6,   -70, 62,  //  AutoContent_12_AIDNA_3
-	      85,  0,   58,  48,  -80, -20,
-	      -49, 71,  60,  8,  //  AutoContent_13_AIDNA_3
-	      -52, 30,  69,  -74, 0,   -36,
-	      -57, 80,  64,  -67,  //  AutoContent_14_AIDNA_3
-	      0,   15,  -96, -51, -21, 0,
-	      -33, -30, 76,  -47  //  AutoContent_15_AIDNA_3
-	   }
-
-	;
-
-	assert(kMagicNumbersSize == AI_initial_military_numbers_C.size());
-
-	const std::vector<int8_t> input_weights_C = {
-	   48,  -85, -26, 47,  -65, -19,
-	   -91, 84,  92,  -12,  //  AutoContent_16_AIDNA_3
-	   78,  -59, -89, 76,  81,  95,
-	   -91, -90, -56, -15,  //  AutoContent_17_AIDNA_3
-	   -65, -18, 6,   -65, 17,  38,
-	   47,  -45, 79,  23,  //  AutoContent_18_AIDNA_3
-	   16,  25,  -59, 36,  -38, -85,
-	   -60, -42, 0,   -70,  //  AutoContent_19_AIDNA_3
-	   -78, -86, -87, -55, 92,  -63,
-	   -21, -76, 4,   87,  //  AutoContent_20_AIDNA_3
-	   58,  -40, 71,  -90, -72, 0,
-	   -47, -94, -15, 95,  //  AutoContent_21_AIDNA_3
-	   -32, 9,   67,  -47, -44, -76,
-	   -53, 57,  -31, -47,  //  AutoContent_22_AIDNA_3
-	   0,   -28, -16, 48,  41,  -45,
-	   36,  -8,  63,  -49  //  AutoContent_23_AIDNA_3
-	};
-	const std::vector<int8_t> input_func_C = {
-	   1, 0, 1, 2, 2, 1,
-	   0, 0, 0, 0,  //  AutoContent_24_AIDNA_3
-	   2, 1, 2, 2, 1, 1,
-	   2, 2, 2, 1,  //  AutoContent_25_AIDNA_3
-	   2, 2, 0, 2, 2, 1,
-	   0, 1, 0, 2,  //  AutoContent_26_AIDNA_3
-	   1, 2, 2, 1, 2, 1,
-	   0, 1, 2, 1,  //  AutoContent_27_AIDNA_3
-	   2, 1, 2, 0, 0, 1,
-	   2, 0, 0, 0,  //  AutoContent_28_AIDNA_3
-	   1, 0, 0, 1, 0, 2,
-	   0, 0, 1, 1,  //  AutoContent_29_AIDNA_3
-	   2, 0, 1, 2, 0, 2,
-	   2, 2, 1, 0,  //  AutoContent_30_AIDNA_3
-	   2, 1, 2, 2, 1, 1,
-	   0, 2, 2, 1  //  AutoContent_31_AIDNA_3
-	};
-	assert(kNeuronPoolSize == input_func_C.size());
-	assert(kNeuronPoolSize == input_weights_C.size());
-
-	const std::vector<uint32_t> f_neurons_C = {
-	   202828425,  1322625717, 1148682382, 2244191679, 194456367,  26493027,
-	   2947491014, 3410163948, 3438582086, 856208494,  //  AutoContent_32_AIDNA_3
-	   1259048860, 986431571,  3457662708, 1954360966, 1523650869, 1376351039,
-	   1223335901, 2997887274, 657657361,  645368312,  //  AutoContent_33_AIDNA_3
-	   1271218867, 2915927856, 3933717470, 2011479337, 2645864080, 408737457,
-	   2282387823, 2968205806, 1597793527, 2248461494,  //  AutoContent_34_AIDNA_3
-	   161963959,  1147843615, 670058474,  2013712728, 4145271795, 496651102,
-	   724812677,  2952748738, 1629834973, 3819381979,  //  AutoContent_35_AIDNA_3
-	   3233788172, 732007755,  2583635734, 4271028825, 1217670182, 4043323645,
-	   1857109659, 2249005911, 2834367795, 3072909661,  //  AutoContent_36_AIDNA_3
-	   1278949528, 1792513063, 2384261690, 2732487136, 755615385,  835767184,
-	   1393834641, 4012239945, 2601238115, 2859725290  //  AutoContent_37_AIDNA_3
-	};
-	assert(kFNeuronPoolSize == f_neurons_C.size());
-
-	// AutoSCore_AIDNA_4
-	const std::vector<int16_t> AI_initial_military_numbers_D = {
-	   18,  -42, 21,  59,  -7,  -78,
-	   -22, 81,  48,  0,  //  AutoContent_01_AIDNA_4
-	   -55, 45,  -96, 16,  70,  -30,
-	   33,  79,  -78, -42,  //  AutoContent_02_AIDNA_4
-	   79,  -16, 34,  46,  -22, 0,
-	   45,  -29, 53,  51,  //  AutoContent_03_AIDNA_4
-	   24,  47,  -27, 80,  -86, 46,
-	   -63, -47, 20,  -63,  //  AutoContent_04_AIDNA_4
-	   78,  51,  -25, -77, 20,  38,
-	   6,   37,  -64, -41,  //  AutoContent_05_AIDNA_4
-	   -3,  -55, 62,  0,   64,  -92,
-	   4,   -89, 71,  -18,  //  AutoContent_06_AIDNA_4
-	   -87, 56,  17,  -34, -69, 24,
-	   -57, 84,  40,  -51,  //  AutoContent_07_AIDNA_4
-	   0,   44,  0,   -2,  -11, -4,
-	   -96, -35, -29, -12,  //  AutoContent_08_AIDNA_4
-	   71,  -98, -25, 50,  97,  74,
-	   0,   65,  -60, 23,  //  AutoContent_09_AIDNA_4
-	   38,  53,  74,  0,   -15, 27,
-	   32,  37,  -24, -65,  //  AutoContent_10_AIDNA_4
-	   16,  -61, 19,  -94, -28, 83,
-	   -55, -63, 16,  -41,  //  AutoContent_11_AIDNA_4
-	   28,  -3,  0,   -87, 32,  5,
-	   4,   6,   -20, 62,  //  AutoContent_12_AIDNA_4
-	   85,  0,   58,  48,  -80, -20,
-	   -49, 71,  60,  8,  //  AutoContent_13_AIDNA_4
-	   -52, 59,  100, -74, 0,   -36,
-	   -9,  80,  41,  -67,  //  AutoContent_14_AIDNA_4
-	   0,   15,  -96, -51, -21, 11,
-	   -27, -30, 76,  -47  //  AutoContent_15_AIDNA_4
-	};
-	assert(kMagicNumbersSize == AI_initial_military_numbers_D.size());
-
-	const std::vector<int8_t> input_weights_D = {
-	   48,  -85, -26, 47,  -93, -22,
-	   -91, 84,  50,  -12,  //  AutoContent_16_AIDNA_4
-	   98,  -59, -89, 76,  81,  95,
-	   -91, -90, -56, -15,  //  AutoContent_17_AIDNA_4
-	   -65, -18, 6,   -65, 41,  38,
-	   47,  -31, 79,  23,  //  AutoContent_18_AIDNA_4
-	   16,  25,  -59, 0,   -38, -85,
-	   -60, -42, 0,   -70,  //  AutoContent_19_AIDNA_4
-	   -78, -86, -87, -55, 92,  -63,
-	   -21, -76, 4,   87,  //  AutoContent_20_AIDNA_4
-	   58,  -40, 71,  -90, -72, 0,
-	   -47, -94, -15, 66,  //  AutoContent_21_AIDNA_4
-	   -32, 9,   67,  -47, -44, -76,
-	   -53, 57,  -31, -47,  //  AutoContent_22_AIDNA_4
-	   0,   -28, -16, 48,  41,  -45,
-	   36,  -8,  63,  -49  //  AutoContent_23_AIDNA_4
-	};
-
-	const std::vector<int8_t> input_func_D = {
-	   1, 0, 1, 2, 2, 1,
-	   0, 0, 0, 0,  //  AutoContent_24_AIDNA_4
-	   2, 1, 2, 2, 2, 1,
-	   2, 2, 2, 1,  //  AutoContent_25_AIDNA_4
-	   2, 2, 0, 2, 2, 1,
-	   0, 1, 0, 2,  //  AutoContent_26_AIDNA_4
-	   1, 2, 2, 1, 2, 1,
-	   0, 1, 2, 1,  //  AutoContent_27_AIDNA_4
-	   2, 1, 2, 0, 0, 1,
-	   2, 0, 0, 0,  //  AutoContent_28_AIDNA_4
-	   1, 0, 0, 1, 0, 1,
-	   0, 0, 1, 1,  //  AutoContent_29_AIDNA_4
-	   2, 0, 1, 2, 0, 2,
-	   2, 2, 1, 0,  //  AutoContent_30_AIDNA_4
-	   2, 1, 2, 2, 1, 1,
-	   0, 2, 2, 1  //  AutoContent_31_AIDNA_4
-	};
-	assert(kNeuronPoolSize == input_func_D.size());
-	assert(kNeuronPoolSize == input_weights_D.size());
-
-	const std::vector<uint32_t> f_neurons_D = {
-	   471130763,  1322756799, 1148682382, 2713953719, 194460175,  18113635,
-	   2947490886, 3275944172, 3438582214, 856208494,  //  AutoContent_32_AIDNA_4
-	   1326156684, 449560659,  3465512701, 1962749574, 1523650869, 1376482111,
-	   2347409353, 2962227502, 657710614,  578259960,  //  AutoContent_33_AIDNA_4
-	   1271222963, 2915927856, 3396846486, 1743568169, 2679432920, 410834611,
-	   134904175,  2968201710, 2132567223, 2248461478,  //  AutoContent_34_AIDNA_4
-	   161963959,  3295327519, 670058472,  2013696856, 3608400883, 496651103,
-	   733137541,  2952748738, 1159810205, 3886490843,  //  AutoContent_35_AIDNA_4
-	   3225153820, 732007755,  2583635732, 4271028825, 1217674278, 4043323645,
-	   1857109651, 2248481623, 3899721011, 3081298269,  //  AutoContent_36_AIDNA_4
-	   1277901016, 1255642150, 2384261818, 2866704864, 755617465,  835768208,
-	   1394358417, 4012239945, 2601238115, 3933467106  //  AutoContent_37_AIDNA_4
-	};
-	assert(kFNeuronPoolSize == f_neurons_D.size());
-
 	primary_parent = std::rand() % 4;
 	const uint8_t parent2 = std::rand() % 4;
 
+	std::vector<int16_t> AI_military_numbers_P1(kMagicNumbersSize);
+	std::vector<int8_t> input_weights_P1(kNeuronPoolSize);
+	std::vector<int8_t> input_func_P1(kNeuronPoolSize);
+	std::vector<uint32_t> f_neurons_P1(kFNeuronPoolSize);
+	ai_dna_handler.fetch_dna(
+	   AI_military_numbers_P1, input_weights_P1, input_func_P1, f_neurons_P1, primary_parent + 1);
+
+	std::vector<int16_t> AI_military_numbers_P2(kMagicNumbersSize);
+	std::vector<int8_t> input_weights_P2(kNeuronPoolSize);
+	std::vector<int8_t> input_func_P2(kNeuronPoolSize);
+	std::vector<uint32_t> f_neurons_P2(kFNeuronPoolSize);
+	ai_dna_handler.fetch_dna(
+	   AI_military_numbers_P2, input_weights_P2, input_func_P2, f_neurons_P2, parent2 + 1);
+
 	log("    ... Primary parent: %d, secondary parent: %d\n", primary_parent, parent2);
 
 	// First setting of military numbers, they go directly to persistent data
 	for (uint16_t i = 0; i < kMagicNumbersSize; i += 1) {
-		// Child inherits DNA with probability 5:1 from main parent
-		uint8_t dna_donor = (std::rand() % kSecondParentProbability > 0) ? primary_parent : parent2;
+		// Child inherits DNA with probability 1/kSecondParentProbability from main parent
+		uint8_t dna_donor = ((std::rand() % kSecondParentProbability) > 0) ? 0 : 1;
 		if (i == kMutationRatePosition) {  // Overwriting
-			dna_donor = primary_parent;
+			dna_donor = 0;
 		}
 
 		switch (dna_donor) {
 		case 0:
-			set_military_number_at(i, AI_initial_military_numbers_A[i]);
+			set_military_number_at(i, AI_military_numbers_P1[i]);
 			break;
 		case 1:
-			set_military_number_at(i, AI_initial_military_numbers_B[i]);
-			break;
-		case 2:
-			set_military_number_at(i, AI_initial_military_numbers_C[i]);
-			break;
-		case 3:
-			set_military_number_at(i, AI_initial_military_numbers_D[i]);
+			set_military_number_at(i, AI_military_numbers_P2[i]);
 			break;
 		default:
-			log("parent %d?\n", dna_donor);
+			log("Invalid dna_donor for military numbers: %d?\n", dna_donor);
 			NEVER_HERE();
 		}
 	}
@@ -913,50 +563,34 @@
 	pd->f_neurons.clear();
 
 	for (uint16_t i = 0; i < kNeuronPoolSize; i += 1) {
-		const uint8_t dna_donor =
-		   (std::rand() % kSecondParentProbability > 0) ? primary_parent : parent2;
+		const uint8_t dna_donor = ((std::rand() % kSecondParentProbability) > 0) ? 0 : 1;
 
 		switch (dna_donor) {
 		case 0:
-			pd->neuron_weights.push_back(input_weights_A[i]);
-			pd->neuron_functs.push_back(input_func_A[i]);
+			pd->neuron_weights.push_back(input_weights_P1[i]);
+			pd->neuron_functs.push_back(input_func_P1[i]);
 			break;
 		case 1:
-			pd->neuron_weights.push_back(input_weights_B[i]);
-			pd->neuron_functs.push_back(input_func_B[i]);
-			break;
-		case 2:
-			pd->neuron_weights.push_back(input_weights_C[i]);
-			pd->neuron_functs.push_back(input_func_C[i]);
-			break;
-		case 3:
-			pd->neuron_weights.push_back(input_weights_D[i]);
-			pd->neuron_functs.push_back(input_func_D[i]);
+			pd->neuron_weights.push_back(input_weights_P2[i]);
+			pd->neuron_functs.push_back(input_func_P2[i]);
 			break;
 		default:
-			log("parent %d?\n", dna_donor);
+			log("Invalid dna_donor for neurons:  %d?\n", dna_donor);
 			NEVER_HERE();
 		}
 	}
 
 	for (uint16_t i = 0; i < kFNeuronPoolSize; i += 1) {
-		const uint8_t dna_donor =
-		   (std::rand() % kSecondParentProbability > 0) ? primary_parent : parent2;
+		const uint8_t dna_donor = (std::rand() % kSecondParentProbability > 0) ? 0 : 1;
 		switch (dna_donor) {
 		case 0:
-			pd->f_neurons.push_back(f_neurons_A[i]);
+			pd->f_neurons.push_back(f_neurons_P1[i]);
 			break;
 		case 1:
-			pd->f_neurons.push_back(f_neurons_B[i]);
-			break;
-		case 2:
-			pd->f_neurons.push_back(f_neurons_C[i]);
-			break;
-		case 3:
-			pd->f_neurons.push_back(f_neurons_D[i]);
+			pd->f_neurons.push_back(f_neurons_P2[i]);
 			break;
 		default:
-			log("parent %d?\n", dna_donor);
+			log("Invalid dna_donor for f-neurons:  %d?\n", dna_donor);
 			NEVER_HERE();
 		}
 	}
@@ -1000,6 +634,11 @@
 		log("%2d: Very weak mode, increasing mutation probability to 1 / %d\n", pn, probability);
 	}
 
+	// Widlcard for ai trainingmode
+	if (kAITrainingMode && std::rand() % 8 == 0) {
+		probability /= 3;
+	}
+
 	assert(probability > 0 && probability <= 201);
 
 	log("%2d: mutating DNA with probability 1 / %3d:\n", pn, probability);
@@ -1010,7 +649,8 @@
 		{
 			// Preferred numbers are ones that will be mutated agressively in full range
 			// [-kWeightRange, kWeightRange]
-			std::set<int32_t> preferred_numbers = {};
+			std::set<int32_t> preferred_numbers = {std::rand() % kMagicNumbersSize *
+			                                       kPrefNumberProbability};
 
 			for (uint16_t i = 0; i < kMagicNumbersSize; i += 1) {
 				if (i == kMutationRatePosition) {  // mutated above
@@ -1035,7 +675,8 @@
 		// Modifying pool of neurons
 		{
 			// Neurons to be mutated more agressively
-			std::set<int32_t> preferred_neurons = {};
+			std::set<int32_t> preferred_neurons = {std::rand() % kNeuronPoolSize *
+			                                       kPrefNumberProbability};
 			for (auto& item : neuron_pool) {
 
 				const MutatingIntensity mutating_intensity =
@@ -1065,7 +706,8 @@
 		// Modifying pool of f-neurons
 		{
 			// FNeurons to be mutated more agressively
-			std::set<int32_t> preferred_f_neurons = {};
+			std::set<int32_t> preferred_f_neurons = {std::rand() % kFNeuronPoolSize *
+			                                         kPrefNumberProbability};
 			for (auto& item : f_neuron_pool) {
 				uint8_t changed_bits = 0;
 				// is this a preferred neuron
@@ -1152,59 +794,8 @@
 	return;
 }
 
-// Print DNA data to console, used for training
-// TODO(tiborb): Once we will have AI dumped into files, this should be removed
-// Also, used only for training
-void ManagementData::dump_data() {
-	// dumping new numbers
-	log("     actual military_numbers (%lu):\n      {", pd->magic_numbers.size());
-	uint16_t itemcounter = 1;
-	uint16_t line_counter = 1;
-	for (const auto& item : pd->magic_numbers) {
-		log(" %3d%s", item, (&item != &pd->magic_numbers.back()) ? ", " : "  ");
-		if (itemcounter % 10 == 0) {
-			log(" //  AutoContent_%02d\n       ", line_counter);
-			line_counter += 1;
-		}
-		++itemcounter;
-	}
-	log("}\n");
-
-	log("     actual neuron setup:\n      ");
-	log("{ ");
-	itemcounter = 1;
-	for (auto& item : neuron_pool) {
-		log(" %3d%s", item.get_weight(), (&item != &neuron_pool.back()) ? ", " : "  ");
-		if (itemcounter % 10 == 0) {
-			log(" //  AutoContent_%02d\n       ", line_counter);
-			line_counter += 1;
-		}
-		++itemcounter;
-	}
-	log("}\n      { ");
-	itemcounter = 1;
-	for (auto& item : neuron_pool) {
-		log(" %3d%s", item.get_type(), (&item != &neuron_pool.back()) ? ", " : "  ");
-		if (itemcounter % 10 == 0) {
-			log(" //  AutoContent_%02d\n       ", line_counter);
-			line_counter += 1;
-		}
-		++itemcounter;
-	}
-	log("}\n");
-
-	log("     actual f-neuron setup:\n      ");
-	log("{ ");
-	itemcounter = 1;
-	for (auto& item : f_neuron_pool) {
-		log(" %8u%s", item.get_int(), (&item != &f_neuron_pool.back()) ? ", " : "  ");
-		if (itemcounter % 10 == 0) {
-			log(" //  AutoContent_%02d\n       ", line_counter);
-			line_counter += 1;
-		}
-		++itemcounter;
-	}
-	log("}\n");
+void ManagementData::dump_data(const PlayerNumber pn) {
+	ai_dna_handler.dump_output(pd, pn);
 }
 
 // Querying military number at a possition

=== modified file 'src/ai/ai_help_structs.h'
--- src/ai/ai_help_structs.h	2017-06-28 19:31:08 +0000
+++ src/ai/ai_help_structs.h	2017-07-24 20:38:49 +0000
@@ -27,6 +27,7 @@
 #include "ai/ai_hints.h"
 #include "economy/flag.h"
 #include "economy/road.h"
+#include "logic/ai_dna_handler.h"
 #include "logic/findnode.h"
 #include "logic/game.h"
 #include "logic/map.h"
@@ -59,7 +60,6 @@
 
 // A building type can have no, one or multiple of these attributes
 enum class BuildingAttribute : uint8_t {
-	kBakery,
 	kRanger,
 	kBuildable,
 	kLumberjack,
@@ -77,7 +77,7 @@
 	kUpgradeSubstitutes,
 	kUpgradeExtends,
 	kLogRefiner,
-	kIronMine
+	kIronMine,
 };
 
 enum class AiType : uint8_t { kVeryWeak, kWeak, kNormal };
@@ -116,13 +116,13 @@
    {0, 17, 25, 32, 38, 44, 49, 53, 58, 62, 66, 70, 74, 78, 81, 84, 88, 91, 94, 97, 100},
 };
 
+// TODO(tiborb): this should be replaced by command line switch
+constexpr bool kAITrainingMode = false;
 constexpr int kMagicNumbersSize = 150;
 constexpr int kNeuronPoolSize = 80;
 constexpr int kFNeuronPoolSize = 60;
 constexpr int kFNeuronBitSize = 32;
 constexpr int kMutationRatePosition = 42;
-// TODO(tiborb): this should be replaced by command line switch
-constexpr bool kAITrainingMode = false;
 
 constexpr uint32_t kNever = std::numeric_limits<uint32_t>::max();
 
@@ -564,7 +564,9 @@
 constexpr int16_t kAttackersMultiplier = 1;
 constexpr int16_t kAttackBonus = 100;
 constexpr int16_t kTrainedSoldiersScore = 250;
-constexpr int16_t kConqueredWhBonus = 500;
+constexpr int16_t kConqueredWhBonus = 300;
+constexpr int16_t kStrengthMultiplier = 30;
+constexpr int16_t kPSitesRatioMultiplier = 1;
 
 struct Neuron {
 	static int clip_weight_to_range(int w) {
@@ -635,9 +637,18 @@
 	void mutate(PlayerNumber = 0);
 	void new_dna_for_persistent(uint8_t, Widelands::AiType);
 	void copy_persistent_to_local();
-	void review(
-	   uint32_t, PlayerNumber, uint32_t, uint32_t, uint32_t, uint16_t, int16_t, int16_t, uint16_t);
-	void dump_data();
+	void review(uint32_t,
+	            PlayerNumber,
+	            uint32_t,
+	            uint32_t,
+	            uint32_t,
+	            uint16_t,
+	            int16_t,
+	            int16_t,
+	            uint16_t,
+	            uint16_t,
+	            uint32_t);
+	void dump_data(PlayerNumber);
 	uint16_t new_neuron_id() {
 		++next_neuron_id;
 		return next_neuron_id - 1;
@@ -657,6 +668,7 @@
 	MutatingIntensity do_mutate(uint8_t, int16_t);
 	int8_t shift_weight_value(int8_t, bool = true);
 	void test_consistency(bool = false);
+	AiDnaHandler ai_dna_handler;
 
 private:
 	int32_t score;
@@ -665,6 +677,7 @@
 	uint16_t next_bi_neuron_id;
 	uint16_t performance_change;
 	Widelands::AiType ai_type;
+	void dump_output(Widelands::Player::AiPersistentState, PlayerNumber);
 };
 
 // this is used to count militarysites by their size

=== modified file 'src/ai/defaultai.cc'
--- src/ai/defaultai.cc	2017-06-28 08:50:42 +0000
+++ src/ai/defaultai.cc	2017-07-24 20:38:49 +0000
@@ -452,12 +452,13 @@
 				};
 				if (!enemy_warehouses.empty())
 					log("Conquered warehouses: %d / %lu\n", conquered_wh, enemy_warehouses.size());
-				management_data.review(gametime, player_number(),
-				                       player_statistics.get_player_land(player_number()),
-				                       player_statistics.get_enemies_max_land(),
-				                       player_statistics.get_old60_player_land(player_number()),
-				                       attackers_count_, soldier_trained_log.count(gametime),
-				                       soldier_attacks_log.count(gametime), conquered_wh);
+				management_data.review(
+				   gametime, player_number(), player_statistics.get_player_land(player_number()),
+				   player_statistics.get_enemies_max_land(),
+				   player_statistics.get_old60_player_land(player_number()), attackers_count_,
+				   soldier_trained_log.count(gametime), soldier_attacks_log.count(gametime),
+				   conquered_wh, player_statistics.get_player_power(player_number()),
+				   count_productionsites_without_buildings());
 				set_taskpool_task_time(
 				   gametime + kManagementUpdateInterval, SchedulerTaskId::kManagementUpdate);
 			}
@@ -530,7 +531,7 @@
 		management_data.copy_persistent_to_local();
 		management_data.mutate(player_number());
 		if (kAITrainingMode) {
-			management_data.dump_data();
+			management_data.dump_data(player_number());
 		}
 
 		management_data.test_consistency(true);
@@ -557,15 +558,13 @@
 			management_data.new_dna_for_persistent(player_number(), type_);
 			management_data.copy_persistent_to_local();
 			management_data.mutate(player_number());
+			management_data.dump_data(player_number());
 
 		} else {
 			management_data.copy_persistent_to_local();
 		}
 
 		management_data.test_consistency(true);
-		if (kAITrainingMode) {
-			management_data.dump_data();
-		}
 
 		log(" %2d: %lu basic buildings in savegame file. %s\n", player_number(),
 		    persistent_data->remaining_basic_buildings.size(),
@@ -713,7 +712,8 @@
 			}
 
 			// here we identify hunters
-			if (bo.outputs.size() == 1 && tribe_->safe_ware_index("meat") == bo.outputs.at(0)) {
+			if (bo.inputs.empty() && bo.outputs.size() == 1 &&
+			    tribe_->safe_ware_index("meat") == bo.outputs.at(0)) {
 				bo.set_is(BuildingAttribute::kHunter);
 			}
 
@@ -728,9 +728,6 @@
 			if (building_index == tribe_->barracks()) {
 				bo.set_is(BuildingAttribute::kBarracks);
 			}
-			if (building_index == tribe_->bakery()) {
-				bo.set_is(BuildingAttribute::kBakery);
-			}
 			// Identify refined log producer
 			if (bo.outputs.size() == 1 && bo.outputs[0] == tribe_->refinedlog()) {
 				bo.set_is(BuildingAttribute::kLogRefiner);
@@ -857,8 +854,10 @@
 	// Also note that the AI assumes that some buildings are unique, if you want to
 	// create e.g. two barracks or bakeries, the impact on the AI must be considered
 	assert(count_buildings_with_attribute(BuildingAttribute::kBarracks) == 1);
-	assert(count_buildings_with_attribute(BuildingAttribute::kBakery) == 1);
 	assert(count_buildings_with_attribute(BuildingAttribute::kLogRefiner) == 1);
+	assert(count_buildings_with_attribute(BuildingAttribute::kWell) == 1);
+	assert(count_buildings_with_attribute(BuildingAttribute::kLumberjack) == 1);
+	assert(count_buildings_with_attribute(BuildingAttribute::kHunter) == 1);
 	assert(count_buildings_with_attribute(BuildingAttribute::kIronMine) >= 1);
 	// If there will be a tribe with more than 3 mines of the same type, just increase the number
 	assert(count_buildings_with_attribute(BuildingAttribute::kIronMine) <= 3);
@@ -2323,16 +2322,16 @@
 					bo.primary_priority += bo.max_needed_preciousness;
 				} else {
 					bo.primary_priority += bo.primary_priority * bo.new_building_overdue *
-					                       std::abs(management_data.get_military_number_at(120)) / 500;
+					                       std::abs(management_data.get_military_number_at(120)) / 25;
 					bo.primary_priority += bo.max_needed_preciousness +
 					                       bo.max_needed_preciousness * bo.new_building_overdue *
 					                          std::abs(management_data.get_military_number_at(70)) /
-					                          1000 +
+					                          100 +
 					                       bo.new_building_overdue *
-					                          std::abs(management_data.get_military_number_at(71)) / 50;
+					                          std::abs(management_data.get_military_number_at(71)) / 10;
 					if (bo.new_building == BuildingNecessity::kForced) {
 						bo.primary_priority += bo.new_building_overdue *
-						                       std::abs(management_data.get_military_number_at(119)) / 50;
+						                       std::abs(management_data.get_military_number_at(119)) / 25;
 					}
 				}
 			} else {
@@ -2351,6 +2350,19 @@
 			bo.new_building = BuildingNecessity::kAllowed;
 			bo.primary_priority = 0;
 		}
+
+		if (kAITrainingMode && bo.type == BuildingObserver::Type::kProductionsite) {
+			log(
+			   "%2d: %-35s(%2d now) %-11s: max prec: %2d/%2d, primary priority: %4d, overdue: %3d\n",
+			   player_number(), bo.name, bo.total_count(),
+			   (bo.new_building == BuildingNecessity::kAllowed ||
+			    bo.new_building == BuildingNecessity::kForced ||
+			    bo.new_building == BuildingNecessity::kNeeded) ?
+			      "needed" :
+			      "not needed",
+			   bo.max_needed_preciousness, bo.max_preciousness, bo.primary_priority,
+			   bo.new_building_overdue);
+		}
 	}
 
 	// first scan all buildable fields for regular buildings
@@ -2450,7 +2462,8 @@
 						prio += 200;
 					}
 
-					prio += -10 + 2 * bf->ground_water;
+					prio += -10 +
+					        std::abs(management_data.get_military_number_at(59) / 50) * bf->ground_water;
 
 				} else if (bo.is(BuildingAttribute::kLumberjack)) {
 
@@ -3820,6 +3833,11 @@
 
 	// Wells handling
 	if (site.bo->is(BuildingAttribute::kWell)) {
+		// Never get bellow target count of wells
+		if (site.bo->total_count() <= site.bo->cnt_target) {
+			return false;
+		}
+
 		if (site.unoccupied_till + 6 * 60 * 1000 < gametime &&
 		    site.site->get_statistics_percent() == 0) {
 			site.bo->last_dismantle_time = gametime;
@@ -4258,19 +4276,17 @@
 
 	BasicEconomyBuildingStatus site_needed_for_economy = BasicEconomyBuildingStatus::kNone;
 	if (gametime > 2 * 60 * 1000 && gametime < 120 * 60 * 1000 && !basic_economy_established) {
-		if (persistent_data->remaining_basic_buildings.count(bo.id)) {
-			if (static_cast<uint32_t>(bo.total_count()) >=
-			    persistent_data->remaining_basic_buildings[bo.id]) {  // exeption for sawmill
-				site_needed_for_economy = BasicEconomyBuildingStatus::kDiscouraged;
-
-			} else if (spots_ < kSpotsTooLittle && bo.type != BuildingObserver::Type::kMine) {
+		if (persistent_data->remaining_basic_buildings.count(bo.id) &&
+		    bo.cnt_under_construction == 0) {
+			assert(persistent_data->remaining_basic_buildings.count(bo.id) > 0);
+			if (spots_ < kSpotsTooLittle && bo.type != BuildingObserver::Type::kMine) {
 				site_needed_for_economy = BasicEconomyBuildingStatus::kNeutral;
 			} else {
 				site_needed_for_economy = BasicEconomyBuildingStatus::kEncouraged;
 			}
 
-		} else if (persistent_data->remaining_basic_buildings.count(bo.id) == 0) {
-			site_needed_for_economy = BasicEconomyBuildingStatus::kNone;
+		} else {
+			site_needed_for_economy = BasicEconomyBuildingStatus::kDiscouraged;
 		}
 	}
 
@@ -4395,7 +4411,7 @@
 				}
 				if (site_needed_for_economy == BasicEconomyBuildingStatus::kEncouraged) {
 					bo.max_needed_preciousness +=
-					   std::abs(management_data.get_military_number_at(144)) / 2;
+					   std::abs(management_data.get_military_number_at(144)) / 10;
 				}
 			}
 
@@ -4496,25 +4512,60 @@
 
 			bo.cnt_target = 1 + static_cast<int32_t>(mines_.size() + productionsites.size()) / 25;
 
-			if (bo.max_needed_preciousness == 0) {
-				return BuildingNecessity::kNotNeeded;
-			} else if (bo.cnt_under_construction + bo.unoccupied_count > 0) {
-				return BuildingNecessity::kForbidden;
-			} else if (bo.total_count() > 0 &&
-			           !(expansion_type.get_expansion_type() == ExpansionMode::kEconomy ||
-			             expansion_type.get_expansion_type() == ExpansionMode::kBoth)) {
-				return BuildingNecessity::kForbidden;
-			} else if (bo.total_count() >= bo.cnt_target) {
-				if (get_stocklevel(bo, gametime) > 1 ||
-				    bo.last_building_built + 10 * 60 * 100 > gametime) {
-					return BuildingNecessity::kForbidden;
-				} else {
-					bo.primary_priority = std::abs(management_data.get_military_number_at(137)) / 2;
-					return BuildingNecessity::kNeeded;
+			if (bo.cnt_under_construction + bo.unoccupied_count > 0) {
+				return BuildingNecessity::kForbidden;
+			}
+
+			int16_t inputs[kFNeuronBitSize] = {0};
+			inputs[0] = (bo.max_needed_preciousness == 0) ? -1 : 0;
+			inputs[1] = (bo.max_needed_preciousness > 0) ? 2 : 0;
+			inputs[2] = (bo.max_needed_preciousness == 0) ? -3 : 0;
+			inputs[3] = (bo.total_count() > 0) ? -1 : 0;
+			inputs[4] = (bo.total_count() > 1) ? -1 : 0;
+			inputs[5] = (bo.total_count() > 0) ? -1 : 0;
+			inputs[6] = (expansion_type.get_expansion_type() == ExpansionMode::kEconomy) ? +1 : 0;
+			inputs[7] = (expansion_type.get_expansion_type() == ExpansionMode::kEconomy) ? +2 : 0;
+			inputs[8] = (expansion_type.get_expansion_type() == ExpansionMode::kEconomy) ? +3 : 0;
+			inputs[9] = (expansion_type.get_expansion_type() == ExpansionMode::kBoth) ? +1 : 0;
+			inputs[10] = (expansion_type.get_expansion_type() == ExpansionMode::kBoth) ? +1 : 0;
+			inputs[11] = (bo.last_building_built + 5 * 60 * 100 > gametime) ? +1 : 0;
+			inputs[12] = (bo.last_building_built + 10 * 60 * 100 > gametime) ? +1 : 0;
+			inputs[13] = (bo.last_building_built + 20 * 60 * 100 > gametime) ? +1 : 0;
+			inputs[14] = (bo.total_count() >= bo.cnt_target) ? -1 : 0;
+			inputs[15] = (bo.total_count() >= bo.cnt_target) ? -2 : 0;
+			inputs[16] = (bo.total_count() < bo.cnt_target) ? -1 : 0;
+			inputs[17] = (bo.total_count() < bo.cnt_target) ? -2 : 0;
+			inputs[18] = +1;
+			inputs[19] = +2;
+			inputs[20] = -1;
+			inputs[21] = -2;
+			inputs[22] = -3;
+			inputs[23] = -4;
+			inputs[24] = -5;
+			inputs[25] = (basic_economy_established) ? 1 : -1;
+			inputs[26] = (basic_economy_established) ? 1 : -1;
+
+			int16_t tmp_score = 0;
+			for (uint8_t i = 0; i < kFNeuronBitSize; ++i) {
+				if (management_data.f_neuron_pool[53].get_position(i)) {
+					tmp_score += inputs[1];
 				}
+			}
+			if (site_needed_for_economy == BasicEconomyBuildingStatus::kEncouraged) {
+				tmp_score += 4;
+			}
+			if (site_needed_for_economy == BasicEconomyBuildingStatus::kDiscouraged) {
+				tmp_score -= 2;
+			}
+
+			if (tmp_score < 0) {
+				return BuildingNecessity::kForbidden;
 			} else {
-				bo.primary_priority = (bo.cnt_target - bo.total_count()) *
-				                      std::abs(management_data.get_military_number_at(111)) / 2;
+				if (bo.max_needed_preciousness <= 0) {
+					bo.max_needed_preciousness = 1;
+				}
+				bo.primary_priority =
+				   1 + tmp_score * std::abs(management_data.get_military_number_at(137));
 				return BuildingNecessity::kNeeded;
 			}
 		} else if (bo.is(BuildingAttribute::kLumberjack)) {
@@ -5011,6 +5062,8 @@
 			inputs[97] = (wood_policy_ == WoodPolicy::kAllowRangers) ? -8 : 0;
 			inputs[98] = (wood_policy_ == WoodPolicy::kAllowRangers) ? -4 : 0;
 			inputs[99] = (wood_policy_ == WoodPolicy::kAllowRangers) ? -1 : 0;
+			inputs[100] = (bo.total_count() == 0) ? 3 : 0;
+			inputs[101] = (bo.total_count() == 0) ? 6 : 0;
 
 			int16_t tmp_score = 0;
 			for (uint8_t i = 0; i < kFNeuronBitSize; ++i) {
@@ -5230,6 +5283,31 @@
 	return count;
 }
 
+// Calculates ratio of building that the player has in comparison to all buildings that are
+// buildable by the player
+// In range 0 - 1000, to avoid floats
+uint32_t DefaultAI::count_productionsites_without_buildings() {
+	uint32_t total = 0;
+	uint32_t existing = 0;
+	if (tribe_ == nullptr) {
+		late_initialization();
+	}
+
+	for (BuildingObserver& bo : buildings_) {
+		if (bo.type == BuildingObserver::Type::kProductionsite &&
+		    bo.is(BuildingAttribute::kBuildable)) {
+			total += 1;
+			if (bo.cnt_built > 0) {
+				existing += 1000;
+			} else if (bo.cnt_under_construction > 0) {
+				existing += 500;
+			}
+		}
+	}
+
+	return existing / total;
+}
+
 // \returns the building observer
 BuildingObserver& DefaultAI::get_building_observer(char const* const name) {
 	if (tribe_ == nullptr) {
@@ -5497,10 +5575,6 @@
 				++fishers_count_;
 			}
 
-			if (bo.is(BuildingAttribute::kBakery)) {
-				++bakeries_count_;
-			}
-
 			for (uint32_t i = 0; i < bo.outputs.size(); ++i)
 				++wares.at(bo.outputs.at(i)).producers;
 
@@ -5637,11 +5711,6 @@
 				--fishers_count_;
 			}
 
-			if (bo.is(BuildingAttribute::kBakery)) {
-				assert(bakeries_count_ > 0);
-				--bakeries_count_;
-			}
-
 		} else if (bo.type == BuildingObserver::Type::kMine) {
 			for (std::list<ProductionSiteObserver>::iterator i = mines_.begin(); i != mines_.end();
 			     ++i) {

=== modified file 'src/ai/defaultai.h'
--- src/ai/defaultai.h	2017-06-27 18:09:15 +0000
+++ src/ai/defaultai.h	2017-07-24 20:38:49 +0000
@@ -219,6 +219,7 @@
 
 	Widelands::EconomyObserver* get_economy_observer(Widelands::Economy&);
 	uint8_t count_buildings_with_attribute(Widelands::BuildingAttribute);
+	uint32_t count_productionsites_without_buildings();
 	Widelands::BuildingObserver& get_building_observer(char const*);
 	bool has_building_observer(char const*);
 	Widelands::BuildingObserver& get_building_observer(Widelands::BuildingAttribute);

=== modified file 'src/helper.cc'
--- src/helper.cc	2017-05-31 21:27:07 +0000
+++ src/helper.cc	2017-07-24 20:38:49 +0000
@@ -53,3 +53,6 @@
 		return result;
 	throw wexception("expected word");
 }
+
+
+

=== modified file 'src/logic/CMakeLists.txt'
--- src/logic/CMakeLists.txt	2017-06-05 07:48:28 +0000
+++ src/logic/CMakeLists.txt	2017-07-24 20:38:49 +0000
@@ -66,6 +66,8 @@
 
 wl_library(logic
   SRCS
+    ai_dna_handler.cc
+    ai_dna_handler.h
     backtrace.cc
     backtrace.h
     cmd_calculate_statistics.cc

=== added file 'src/logic/ai_dna_handler.cc'
--- src/logic/ai_dna_handler.cc	1970-01-01 00:00:00 +0000
+++ src/logic/ai_dna_handler.cc	2017-07-24 20:38:49 +0000
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2002-2017 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#include "logic/ai_dna_handler.h"
+
+#include <cstring>
+#include <ctime>
+#include <memory>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/format.hpp>
+
+#include "base/macros.h"
+#include "base/wexception.h"
+#include "logic/constants.h"
+#include "wui/interactive_base.h"
+
+#define AI_SUFFIX "wai"
+
+namespace Widelands {
+
+AiDnaHandler::AiDnaHandler() {
+	g_fs->ensure_directory_exists(get_base_dir());
+}
+
+// this reads AI file for particular slot (position) and populate numbers into passed vectors
+// slots are numbers  1 - 4 as we have 4 possible input files with AI's DNA
+void AiDnaHandler::fetch_dna(std::vector<int16_t>& military_numbers,
+                             std::vector<int8_t>& input_weights,
+                             std::vector<int8_t>& input_func,
+                             std::vector<uint32_t>& f_neurons,
+                             uint8_t slot) {
+
+	// AI files are in range 1-4
+	assert(slot > 0 && slot < 5);
+
+	std::string full_filename = get_base_dir() + g_fs->file_separator() + "ai_input_" +
+	                            std::to_string(static_cast<int16_t>(slot)) + "." + AI_SUFFIX;
+
+	Profile prof;
+	prof.read(full_filename.c_str(), nullptr, *g_fs);
+	Section& mn = prof.get_safe_section("magic_numbers");
+	for (uint16_t i = 0; i < military_numbers.size(); i++) {
+		int32_t value = mn.get_int(std::to_string(static_cast<int32_t>(i)).c_str());
+		if (value < -100 || value > 100) {
+			throw wexception("Out of range AI data in magic_numbers section: %d\n", i);
+		}
+		military_numbers[i] = static_cast<int16_t>(value);
+	}
+
+	Section& nv = prof.get_safe_section("neuron_values");
+	for (uint16_t i = 0; i < input_weights.size(); i++) {
+		int32_t value = nv.get_int(std::to_string(static_cast<int32_t>(i)).c_str());
+		if (value < -100 || value > 100) {
+			throw wexception("Out of range  AI data in neuron_values section: %d\n", i);
+		}
+		input_weights[i] = static_cast<int8_t>(value);
+	}
+
+	Section& nf = prof.get_safe_section("neuron_functions");
+	for (uint16_t i = 0; i < input_func.size(); i++) {
+		int32_t value = nf.get_int(std::to_string(static_cast<int32_t>(i)).c_str());
+		if (value < 0 || value > 3) {
+			throw wexception("Out of range  AI data in neuron_functions section: %d\n", i);
+		}
+		input_func[i] = static_cast<int8_t>(value);
+	}
+
+	Section& fn = prof.get_safe_section("fneurons");
+	for (uint16_t i = 0; i < f_neurons.size(); i++) {
+		uint32_t value = fn.get_natural(std::to_string(static_cast<int32_t>(i)).c_str());
+
+		f_neurons[i] = value;
+	}
+}
+
+// this generate new file with AI data in home folder - in ai folder
+void AiDnaHandler::dump_output(Widelands::Player::AiPersistentState* pd, uint8_t pn) {
+
+	time_t t;
+	time(&t);
+	struct tm* currenttime = localtime(&t);
+
+	std::string timestamp =
+	   str(boost::format("%d-%02d-%02dT%02d.%02d.%02d") % (1900 + currenttime->tm_year) %
+	       (currenttime->tm_mon + 1) % currenttime->tm_mday % currenttime->tm_hour %
+	       currenttime->tm_min % currenttime->tm_sec);
+
+	std::string full_filename = get_base_dir() + g_fs->file_separator() + timestamp + "_ai_player_" +
+	                            std::to_string(static_cast<int16_t>(pn)) + "." + AI_SUFFIX;
+
+	printf(" %d: AI to be dumped to %s\n", pn, full_filename.c_str());
+
+	Profile prof;
+
+	Section& mn = prof.create_section("magic_numbers");
+	assert(pd->magic_numbers_size == pd->magic_numbers.size());
+	for (uint16_t i = 0; i < pd->magic_numbers_size; ++i) {
+		mn.set_int(std::to_string(static_cast<int32_t>(i)).c_str(), pd->magic_numbers[i]);
+	}
+
+	Section& nv = prof.create_section("neuron_values");
+	assert(pd->neuron_pool_size == pd->neuron_weights.size());
+	for (uint16_t i = 0; i < pd->neuron_pool_size; ++i) {
+		nv.set_int(std::to_string(static_cast<int32_t>(i)).c_str(), pd->neuron_weights[i]);
+	}
+
+	Section& nf = prof.create_section("neuron_functions");
+	assert(pd->neuron_pool_size == pd->neuron_functs.size());
+	for (uint16_t i = 0; i < pd->neuron_pool_size; ++i) {
+		nf.set_int(std::to_string(static_cast<int32_t>(i)).c_str(), pd->neuron_functs[i]);
+	}
+
+	Section& fn = prof.create_section("fneurons");
+	assert(pd->f_neuron_pool_size == pd->f_neurons.size());
+	for (uint16_t i = 0; i < pd->f_neuron_pool_size; ++i) {
+		fn.set_natural(std::to_string(static_cast<int64_t>(i)).c_str(), pd->f_neurons[i]);
+	}
+	prof.write(full_filename.c_str(), false, *g_fs);
+}
+}

=== added file 'src/logic/ai_dna_handler.h'
--- src/logic/ai_dna_handler.h	1970-01-01 00:00:00 +0000
+++ src/logic/ai_dna_handler.h	2017-07-24 20:38:49 +0000
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2007-2017 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#ifndef WL_LOGIC_AI_DUMP_H
+#define WL_LOGIC_AI_DUMP_H
+
+#include <cstring>
+#include <string>
+
+#include <stdint.h>
+
+#include "base/time_string.h"
+#include "logic/game.h"
+#include "logic/player.h"
+
+namespace Widelands {
+
+/**
+ * This handles reading and saving AI DNA to files
+ * - reading when initializing new AI
+ * - saving AI into files (with timestamp and player number) after mutation
+ */
+class AiDnaHandler {
+public:
+	AiDnaHandler();
+
+	static std::string get_base_dir() {
+		return "ai";
+	}
+
+	void fetch_dna(std::vector<int16_t>&,
+	               std::vector<int8_t>&,
+	               std::vector<int8_t>&,
+	               std::vector<uint32_t>&,
+	               uint8_t);
+	void dump_output(Widelands::Player::AiPersistentState* pd, uint8_t);
+};
+}
+#endif  // end of include guard: WL_LOGIC_AI_DUMP_H

=== modified file 'src/logic/map_objects/tribes/tribe_descr.cc'
--- src/logic/map_objects/tribes/tribe_descr.cc	2017-07-04 11:34:00 +0000
+++ src/logic/map_objects/tribes/tribe_descr.cc	2017-07-24 20:38:49 +0000
@@ -244,7 +244,6 @@
 		headquarters_ = add_special_building(table.get_string("headquarters"));
 		port_ = add_special_building(table.get_string("port"));
 		barracks_ = add_special_building(table.get_string("barracks"));
-		bakery_ = add_special_building(table.get_string("bakery"));
 
 		ironore_ = add_special_ware(table.get_string("ironore"));
 		rawlog_ = add_special_ware(table.get_string("rawlog"));
@@ -375,10 +374,6 @@
 	assert(tribes_.building_exists(barracks_));
 	return barracks_;
 }
-DescriptionIndex TribeDescr::bakery() const {
-	assert(tribes_.building_exists(bakery_));
-	return bakery_;
-}
 DescriptionIndex TribeDescr::ironore() const {
 	assert(tribes_.ware_exists(ironore_));
 	return ironore_;

=== modified file 'src/logic/map_objects/tribes/tribe_descr.h'
--- src/logic/map_objects/tribes/tribe_descr.h	2017-06-30 19:31:53 +0000
+++ src/logic/map_objects/tribes/tribe_descr.h	2017-07-24 20:38:49 +0000
@@ -104,7 +104,6 @@
 	DescriptionIndex headquarters() const;
 	DescriptionIndex port() const;
 	DescriptionIndex barracks() const;
-	DescriptionIndex bakery() const;
 	DescriptionIndex ironore() const;
 	DescriptionIndex rawlog() const;
 	DescriptionIndex refinedlog() const;
@@ -193,7 +192,6 @@
 	DescriptionIndex headquarters_;  // The tribe's default headquarters, needed by the editor
 	DescriptionIndex port_;          // The port that this tribe uses
 	DescriptionIndex barracks_;      // The barracks to create soldiers
-	DescriptionIndex bakery_;        // The bakery to prepare bread
 	DescriptionIndex ironore_;       // Iron ore
 	DescriptionIndex rawlog_;        // Simple log
 	DescriptionIndex refinedlog_;    // Refined log, e.g. wood or blackwood

=== modified file 'src/profile/profile.cc'
--- src/profile/profile.cc	2017-07-05 00:26:07 +0000
+++ src/profile/profile.cc	2017-07-24 20:38:49 +0000
@@ -444,6 +444,10 @@
 	set_string(name, std::to_string(value));
 }
 
+void Section::set_natural(char const* const name, uint32_t const value) {
+	set_string(name, std::to_string(static_cast<int64_t>(value)));
+}
+
 void Section::set_string(char const* const name, char const* string) {
 	create_val(name, string).mark_used();
 }

=== modified file 'src/profile/profile.h'
--- src/profile/profile.h	2017-07-02 19:11:13 +0000
+++ src/profile/profile.h	2017-07-24 20:38:49 +0000
@@ -136,6 +136,7 @@
 	char const* get_next_bool(char const* name, bool* value);
 
 	void set_int(char const* name, int32_t value);
+	void set_natural(char const* name, uint32_t value);
 	void set_bool(char const* const name, bool const value) {
 		set_string(name, value ? "true" : "false");
 	}

=== modified file 'src/wlapplication.cc'
--- src/wlapplication.cc	2017-06-20 19:55:32 +0000
+++ src/wlapplication.cc	2017-07-24 20:38:49 +0000
@@ -101,6 +101,8 @@
 // The time in seconds for how long old replays/syncstreams should be kept
 // around, in seconds. Right now this is 4 weeks.
 constexpr double kReplayKeepAroundTime = 4 * 7 * 24 * 60 * 60;
+// Similary we delete AI files older then one week
+constexpr double kAIFilesKeepAroundTime = 7 * 24 * 60 * 60;
 
 /**
  * Shut the hardware down: stop graphics mode, stop sound handler
@@ -182,11 +184,11 @@
 
 // Extracts a long from 'text' into 'val' returning true if all of the string
 // was valid. If not, the content of 'val' is undefined.
-bool to_long(const std::string& text, long* val) {
-	const char* start = text.c_str();
-	char* end;
-	*val = strtol(start, &end, 10);
-	return *end == '\0';
+ bool to_long(const std::string& text, long* val) {
+ const char* start = text.c_str();
+ char* end;
+*val = strtol(start, &end, 10);
+ return *end == '\0';
 }
 
 // Extracts the creation date from 'path' which is expected to
@@ -214,12 +216,13 @@
 
 // Returns true if 'filename' was autogenerated, i.e. if 'extract_creation_day' can return a date
 // and it is old enough to be deleted.
-bool is_autogenerated_and_expired(const std::string& filename) {
+bool is_autogenerated_and_expired(const std::string& filename,
+                                  const double keep_time = kReplayKeepAroundTime) {
 	tm tfile;
 	if (!extract_creation_day(filename, &tfile)) {
 		return false;
 	}
-	return std::difftime(time(nullptr), mktime(&tfile)) > kReplayKeepAroundTime;
+	return std::difftime(time(nullptr), mktime(&tfile)) > keep_time;
 }
 
 }  // namespace
@@ -324,6 +327,7 @@
 	init_language();  // search paths must already be set up
 	changedir_on_mac();
 	cleanup_replays();
+	cleanup_ai_files();
 
 	Section& config = g_options.pull_section("global");
 
@@ -1402,6 +1406,23 @@
 	}
 }
 
+/**
+ * Delete old ai dna files generated during AI initialization
+ */
+void WLApplication::cleanup_ai_files() {
+	for (const std::string& filename :
+	     filter(g_fs->list_directory("ai"),  // NOCOM repace with common defineds
+	                                         // used by both locations (here and ai_dna_handler)
+	            [](const std::string& fn) {
+		            return boost::ends_with(fn, "wai") || boost::contains(fn, "ai_player");
+		         })) {
+		if (is_autogenerated_and_expired(filename, kAIFilesKeepAroundTime)) {
+			log("Deleting generated ai file: %s\n", filename.c_str());
+			g_fs->fs_unlink(filename);
+		}
+	}
+}
+
 bool WLApplication::redirect_output(std::string path) {
 	if (path.empty()) {
 #ifdef _WIN32

=== modified file 'src/wlapplication.h'
--- src/wlapplication.h	2017-07-03 19:24:02 +0000
+++ src/wlapplication.h	2017-07-24 20:38:49 +0000
@@ -214,6 +214,8 @@
 
 	void cleanup_replays();
 
+	void cleanup_ai_files();
+
 	bool redirect_output(std::string path = "");
 
 	// Handle the given pressed key. Returns true when key was


Follow ups