changeset 371:0522468991c1

added flash attacking script.
author "Rex Tsai <chihchun@kalug.linux.org.tw>"
date Tue, 14 Apr 2009 16:59:14 +0800
parents ba1643654e6d
children 9f19fe8d189c
files Ikariam/CitiesRules.pm agent.pl flash-city.yaml flash.pl flash.sh
diffstat 5 files changed, 535 insertions(+), 399 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Ikariam/CitiesRules.pm	Tue Apr 14 16:59:14 2009 +0800
@@ -0,0 +1,423 @@
+#!/usr/bin/perl
+
+package Ikariam::CitiesRules;
+use strict;
+use Data::Dumper;
+
+sub new {
+    my ( $class, $i ) = @_;
+    my $self = {
+        ikariam => $i,
+    };
+    return bless $self, $class;
+}
+
+sub is_attacked {
+    my ($self, $city) = @_;
+
+    return ($self->{'ikariam'}->{'military'}->{attack} > 0 ) ? 1 : 0;
+}
+
+sub is_constructing {
+    my ($self, $city) = @_;
+    return ($city->{construction} > 0 ) ? 1 : 0;
+}
+
+sub is_wall_enough {
+    my ($self, $city) = @_;
+    # http://ikariam.wikia.com/wiki/Wall_Defense
+    # Basic rule - the wall level must equale or large then townHall level.
+    return ($city->{buildings}->{wall} >= $city->{buildings}->{townHall} ?  1 : 0);
+}
+
+sub is_academy_enough {
+    my ($self, $city) = @_;
+    return ($city->{buildings}->{academy} >= 12 ?  1 : 0);
+}
+
+sub is_embassy_enough {
+    my ($self, $city) = @_;
+    return 1;
+    return ($city->{buildings}->{embassy} >= 1 ?  1 : 0);
+    return ($city->{buildings}->{embassy} >= 6 ?  1 : 0);
+}
+
+sub is_museum_enough {
+    my ($self, $city) = @_;
+    return 1 if($city->{buildings}->{museum} >= 8);
+}
+
+sub is_tavern_enough {
+    my ($self, $city) = @_;
+    return 0 if(!defined($city->{buildings}->{tavern}));
+    return ($city->{buildings}->{tavern} >= 12 ? 1 : 0);
+}
+
+sub is_branchOffice_enough {
+    my ($self, $city) = @_;
+    return ($city->{buildings}->{branchOffice} >= 6 ?  1 : 0);
+}
+
+sub is_port_available {
+    my ($self, $city) = @_;
+    return 0 if(!defined($city->{buildings}->{port}));
+    return 1;
+}
+
+sub is_port_enough {
+    my ($self, $city) = @_;
+    return ($city->{buildings}->{port} >= 12 ?  1 : 0);
+}
+
+sub is_space_enough {
+    my ($self, $city) = @_;
+    # The maximum town hall is level 20, then we build new town
+    return 1 if($city->{buildings}->{townHall} >= 15);
+    # TODO 應該以 成長率 * 升級所需時間計算
+    # 6 hours earlier, we upgrade the twonHall.
+    return ($city->{space}->{total} <= ($city->{space}->{occupied} + ($city->{growth}*12)) ?  0 : 1)
+}
+
+sub is_safehouse_enough {
+    my ($self, $city) = @_;
+
+    return 1;
+
+    return 0 if(!defined($city->{buildings}->{safehouse}));
+    return 1 if(($city->{buildings}->{townHall} - $city->{buildings}->{wall}) > 2);
+    return 1 if($city->{buildings}->{townHall} >= 20);
+
+    # build the higgest safehouse.
+    # maybe we should have more then 4 towns, then we consider that we should upgrade safehouse at level 20.
+    # return (($city->{buildings}->{townHall} > $city->{buildings}->{safehouse}) ? 0 : 1) 
+    # return (($city->{buildings}->{townHall} <= ($city->{buildings}->{safehouse} + 4)) ? 0 : 1);
+
+    # Safehouse must be same level as townHall,
+    return (($city->{buildings}->{townHall} >= $city->{buildings}->{safehouse}) ? 0 : 1);
+}
+
+sub is_warehouse_available {
+    my ($self, $city) = @_;
+    return 0 if(!defined($city->{buildings}->{warehouse}));
+    return 1;
+}
+
+sub is_warehouse_more_then_eight {
+    my ($self, $city) = @_;
+    my $cityId = $city->{id};
+    return 0 if(!defined($city->{buildings}->{warehouse}));
+
+    my @locations = @{$city->{locations}};
+    my $count = 0;
+    foreach (3..14) {
+        $count++ if($locations[$_] eq "warehouse");
+        return 1 if($count >= 8);
+    }
+    return 0;
+}
+
+sub is_warehouse_enough {
+    my ($self, $city) = @_;
+
+    return 1;
+    # my @warehouse = (qw/undef undef 0 4 9 16 18 19 20 21 22 23 24 25/);
+    my @warehouse = (qw/undef undef 0 4 9 15 17 18 19 20 21 22 23 24/);
+    my @cities = keys(%{$self->{ikariam}->{cities}});
+    my $nextCities = ($#cities + 1) + 1;
+
+    Carp::carp(sprintf("Required warehouse level %s for next city (%s), current is %s\n", $warehouse[$nextCities], $nextCities, $city->{buildings}->{warehouse}));
+    return 0 if(!defined($city->{buildings}->{warehouse}));
+    return ($city->{buildings}->{warehouse} >= $warehouse[$nextCities]) ? 1 : 0;
+}
+
+
+sub is_warehouse_enougn_for_governorsresidence {
+    my ($self, $city) = @_;
+    return (($city->{buildings}->{warehouse} >= 5) ? 0 : 1);
+
+    my @warehouse = (qw/undef undef 0 4 9 16 18 19 20 21 22 23 24 25/);
+    my @cities = keys(%{$self->{ikariam}->{cities}});
+    my $citiesNumber = $#cities + 1;
+
+    Carp::carp(sprintf("Required warehouse level %s for %s cities, current is %s\n", $warehouse[$citiesNumber], $citiesNumber, $city->{buildings}->{warehouse}));
+    return 0 if(!defined($city->{buildings}->{warehouse}));
+    return ($city->{buildings}->{warehouse} >= $warehouse[$citiesNumber]) ? 1 : 0;
+}
+
+sub is_corruption {
+    my ($self, $city) = @_;
+    return ($city->{corruption} > 0) ? 1 : 0;
+}
+
+sub is_any_corruption {
+    my ($self, $city) = @_;
+
+    foreach (keys(%{$self->{ikariam}->{cities}})) {
+        return 1 if ($self->{ikariam}->{cities}->{$_}->{corruption} > 0);
+    }
+    return 0;
+}
+
+sub is_happiness {
+    my ($self, $city) = @_;
+
+    return ($city->{growth} >= 5 ?  1 : 0) 
+        if($city->{buildings}->{townHall} <= 10);
+
+    return ($city->{growth} >= 2 ?  1 : 0) 
+        if($city->{buildings}->{townHall} <= 15);
+
+    return 1 if($city->{buildings}->{townHall} >= 20);
+}
+
+
+sub is_bacchanal {
+    my ($self, $city) = @_;
+    return ($city->{tavern}->{maxValue} == $city->{tavern}->{iniValue} ? 1 : 0);
+}
+
+sub is_gold_enoughforcargo {
+    my ($self, $city) = @_;
+    my @cargoCost = qw/160 244 396 812 1240 1272 1832 1888 3848 3972 5204 5384 6868 7120 8864 9200 11268 11712 14108 14680 23320 24288 28664 29880 34956 36468 42348 44212 51024 53308 61236 64024 73096 76468 87020 91088 103224 116524 122072 137432 180060 202132 211964 237444 249108 278276 292076 306623 321963 338138 355198 373191 392171 412195 433320 455612 479135 503962 530166 557828 587031 617863 650420 684802 721113 759466 799981 842783 888005 935790 986286 1039654 1096062 1155689 1218724 1285369 1355837 1430353 1509159 1592508 1680670 1773932 1872597 1976989 2087448 2204338 2328045 2458976 2597567 2744276 2899594 3064040 3238163 3422550 3617820 3824635 4043693 4275738 4521561 4782000 5057946 5350345 5660202 5988585 6336630 6705540 7096598 7511164 7950683 8416694 8910828 9434823 9990523 10579889 11205006 11868090 12571498 13317734 14109462 14949514/;
+
+    if($city->{resources}->{gold} >= ($cargoCost[$city->{transporters}->{sum}]*5)) {
+        return 1;
+    } else {
+        return 0;
+    }
+}
+
+sub is_resource_enoghforHall {
+    my ($self, $city) = @_;
+    my @wood = qw/udnef 0 70 98 65 129 236 402 594 849 1176 1586 2101 3208 4937 7171 10139 14537 18420 22896 28047 33934 40623 48017 56511 226044 452088 904176 1808352 3616704 7233408 14466816 28933632/;
+    my @marble = qw/undef 0 0 17 28 66 95 156 243 406 579 799 1348 2124 2951 4409 6461 8187 10176 12466 15082 18055 21381 25116 100464 200928 401856 803712 1607424 3214848 6429696 12859392/;
+
+    my $level = $city->{buildings}->{townHall};
+    if($city->{resources}->{wood} >= $wood[$level] && $city->{resources}->{marble} >= $marble[$level] ) {
+        return 1;
+    }
+    warn(sprintf("Resource is short for build city hall. wood [%d] marble [%d] ", $wood[$level], $marble[$level]));
+    return 0;
+}
+
+sub is_expansion_researched {
+    my ($self, $city) = @_;
+    # $self->{'ikariam'}->
+    return (defined($self->{'ikariam'}->{research}->{1030}) ?  1 : 0);
+}
+
+sub is_foreigncultures_researched {
+    my ($self) = @_;
+    return (defined($self->{'ikariam'}->{research}->{1040}) ?  1 : 0);
+}
+
+sub is_greekfire_researched {
+    my ($self) = @_;
+    return (defined($self->{'ikariam'}->{research}->{1060}) ?  1 : 0);
+}
+
+sub is_paddlewheelengine_researched {
+    my ($self) = @_;
+    return (defined($self->{'ikariam'}->{research}->{1100}) ?  1 : 0);
+}
+
+sub is_conservation_researched {
+    my ($self) = @_;
+    return (defined($self->{'ikariam'}->{research}->{2010}) ?  1 : 0);
+}
+
+sub is_wealth_researched {
+    my ($self) = @_;
+    return (defined($self->{'ikariam'}->{research}->{2030}) ?  1 : 0);
+}
+
+sub is_winepress_researched {
+    my ($self) = @_;
+    return (defined($self->{'ikariam'}->{research}->{2040}) ?  1 : 0);
+}
+
+sub is_paper_researched {
+    my ($self) = @_;
+    return (defined($self->{'ikariam'}->{research}->{3020}) ?  1 : 0);
+}
+
+sub is_espionage_researched {
+    my ($self) = @_;
+    return (defined($self->{'ikariam'}->{research}->{3030}) ?  1 : 0);
+}
+
+sub is_invention_researched {
+    my ($self) = @_;
+    return (defined($self->{'ikariam'}->{research}->{3040}) ?  1 : 0);
+}
+
+sub is_culturalexchange_researched {
+    my ($self) = @_;
+    return (defined($self->{'ikariam'}->{research}->{3060}) ?  1 : 0);
+}
+
+sub is_professionalarmy_researched {
+    my ($self) = @_;
+    return (defined($self->{'ikariam'}->{research}->{4030}) ?  1 : 0);
+}
+
+sub is_drydock_researched {
+    my ($self) = @_;
+    return (defined($self->{'ikariam'}->{research}->{4010}) ?  1 : 0);
+}
+
+sub is_robotics_researched {
+    my ($self) = @_;
+    return (defined($self->{'ikariam'}->{research}->{4110}) ?  1 : 0);
+}
+
+sub is_barracks_available {
+    my ($self, $city) = @_;
+    return 0 if(!defined($city->{buildings}->{barracks}));
+    return 1;
+}
+
+sub is_barracks_level_enough {
+    my ($self, $city) = @_;
+    return 0 if(!defined($city->{buildings}->{barracks}));
+    if($self->is_robotics_researched() eq 1) {
+        return ($city->{buildings}->{barracks} >= 24 ? 1 : 0);
+    }
+
+    if($city->{buildings}->{townHall} >= 10) {
+        # optimum is 5
+        return ($city->{buildings}->{barracks} >= 5 ? 1 : 0);
+    } else {
+        # 方陣兵需要 level 4
+        return ($city->{buildings}->{barracks} >= 4 ? 1 : 0);
+    }
+}
+
+sub is_shipyard_availble {
+    my ($self, $city) = @_;
+    return 0 if(!defined($city->{buildings}->{shipyard}));
+    return 1;
+}
+
+sub is_shipyard_level_enough {
+    my ($self, $city) = @_;
+    return 0 if(!defined($city->{buildings}->{shipyard}));
+    if ($self->is_paddlewheelengine_researched() eq 1) {
+        return ($city->{buildings}->{shipyard} >= 16 ? 1 : 0);
+    } elsif ($self->is_greekfire_researched() eq 1) {
+        return ($city->{buildings}->{shipyard} >= 5 ? 1 : 0);
+    } else {
+        return ($city->{buildings}->{shipyard} >= 3 ? 1 : 0);
+    }
+}
+
+sub is_shipyard_upgrading {
+    my ($self, $city) = @_;
+    return $self->{'ikariam'}->is_shipyard_upgrading($city->{id});
+}
+
+sub is_navy_trainning {
+    my ($self, $city) = @_;
+    return $self->{'ikariam'}->is_navy_trainning($city->{id});
+}
+
+sub train_navy {
+    my ($self, $city) = @_;
+    my $cityId = $city->{id};
+    # TODO, 依照升級比例算 CP 值最高
+    if($self->is_greekfire_researched() eq 1 && $city->{buildings}->{shipyard} >= 5) {
+        # ok, we can build Flamethrower.
+        if(defined($city->{'fleet'}->{Flamethrower}) && ($city->{'fleet'}->{Flamethrower} > 0)
+                && ($city->{'fleet'}->{BallistaShip} / $city->{'fleet'}->{Flamethrower}) <= (1.5/1)) {
+            return 213; # 強弩船
+        } else {
+            return 211; # 噴火船
+        }
+    } else {
+        return 213; # 強弩船
+    }
+}
+
+sub is_barracks_upgrading {
+    my ($self, $city) = @_;
+    return $self->{ikariam}->is_barracks_upgrading($city->{id});
+}
+
+sub is_army_trainning {
+    my ($self, $city) = @_;
+    return $self->{ikariam}->is_army_trainning($city->{id});
+}
+sub train_army {
+    my ($self, $city) = @_;
+    my $cityId = $city->{id};
+
+    # TODO, 依照升級比例算 CP 值最高
+    my $assault = 'Swordsman';
+    my $resistance = 'Phalanx';
+
+    if(($city->{'army'}->{$assault} / $city->{'army'}->{$resistance}) <= (2/1)) {
+        return 302; # Swordsman
+    } else {
+        return 303; # Phalanx
+    }
+}
+
+# navy
+sub is_navyExpenditure_available
+{
+    my ($self, $city) = @_;
+    my $cityId = $city->{id};
+
+    # move this to somewhere else.
+    my $workersRatio = {
+        'citizens' => 0.4,
+        'specialworkers' => 0.3,
+        'woodworkers' => 0.7,
+    };
+
+    my $currentCost = $self->{'ikariam'}->getNavyExpenditure($cityId);
+    my $netincome = $self->{'ikariam'}->getNetIncome($cityId);
+    
+    # 軍費為 兩成 淨收入
+    # 陸軍佔用 0.3
+    # 海軍佔用 0.7
+    my $militaryExpenditure = int($netincome * 0.2 * 0.7);
+
+    if($currentCost < $militaryExpenditure) {
+        printf("Current navy expenditure total=%s, affordable %s\n", $currentCost, $militaryExpenditure);
+        return 1;
+    }
+    return 0;
+}
+
+# army
+sub is_milityExpenditure_available
+{
+    my ($self, $city) = @_;
+    my $cityId = $city->{id};
+
+    # move this to somewhere else.
+    my $workersRatio = {
+        'citizens' => 0.4,
+        'specialworkers' => 0.3,
+        'woodworkers' => 0.7,
+    };
+
+    my $currentCost = $self->{'ikariam'}->getMilityExpenditure($cityId);
+    my $netincome = $self->{'ikariam'}->getNetIncome($cityId);
+    
+    # 軍費為 兩成 淨收入
+    # 陸軍佔用 0.3
+    # 海軍佔用 0.7
+
+    my $militaryExpenditure = int($netincome * 0.2 * 0.3);
+
+    if($currentCost < $militaryExpenditure) {
+        Carp::carp("Current army expenditure total=%s, affordable %s\n", $currentCost, $militaryExpenditure);
+        return 1;
+    }
+    return 0;
+}
+
+1; 
+
--- a/agent.pl	Tue Apr 14 16:57:51 2009 +0800
+++ b/agent.pl	Tue Apr 14 16:59:14 2009 +0800
@@ -2,401 +2,11 @@
 
 use strict;
 use Ikariam;
+use Ikariam::CitiesRules;
 use Data::Dumper;
 use Decision::ParseTree q{ParseTree};
 use YAML qw/LoadFile Dump DumpFile/;
 
-package Ikariam::Cities::Rules;
-use strict;
-use Data::Dumper;
-
-sub new {
-    my ( $class, $i ) = @_;
-    my $self = {
-        ikariam => $i,
-    };
-    return bless $self, $class;
-}
-
-sub is_attacked {
-    my ($self, $city) = @_;
-
-    return ($self->{'ikariam'}->{'military'}->{attack} > 0 ) ? 1 : 0;
-}
-
-sub is_constructing {
-    my ($self, $city) = @_;
-    return ($city->{construction} > 0 ) ? 1 : 0;
-}
-
-sub is_wall_enough {
-    my ($self, $city) = @_;
-    # http://ikariam.wikia.com/wiki/Wall_Defense
-    # Basic rule - the wall level must equale or large then townHall level.
-    return ($city->{buildings}->{wall} >= $city->{buildings}->{townHall} ?  1 : 0);
-}
-
-sub is_academy_enough {
-    my ($self, $city) = @_;
-    return ($city->{buildings}->{academy} >= 12 ?  1 : 0);
-}
-
-sub is_embassy_enough {
-    my ($self, $city) = @_;
-    return 1;
-    return ($city->{buildings}->{embassy} >= 1 ?  1 : 0);
-    return ($city->{buildings}->{embassy} >= 6 ?  1 : 0);
-}
-
-sub is_museum_enough {
-    my ($self, $city) = @_;
-    return 1 if($city->{buildings}->{museum} >= 8);
-}
-
-sub is_tavern_enough {
-    my ($self, $city) = @_;
-    return 0 if(!defined($city->{buildings}->{tavern}));
-    return ($city->{buildings}->{tavern} >= 12 ? 1 : 0);
-}
-
-sub is_branchOffice_enough {
-    my ($self, $city) = @_;
-    return ($city->{buildings}->{branchOffice} >= 6 ?  1 : 0);
-}
-
-sub is_port_enough {
-    my ($self, $city) = @_;
-    return ($city->{buildings}->{port} >= 12 ?  1 : 0);
-}
-
-sub is_space_enough {
-    my ($self, $city) = @_;
-    # The maximum town hall is level 20, then we build new town
-    return 1 if($city->{buildings}->{townHall} >= 15);
-    # TODO 應該以 成長率 * 升級所需時間計算
-    # 6 hours earlier, we upgrade the twonHall.
-    return ($city->{space}->{total} <= ($city->{space}->{occupied} + ($city->{growth}*12)) ?  0 : 1)
-}
-
-sub is_safehouse_enough {
-    my ($self, $city) = @_;
-
-    return 1;
-
-    return 0 if(!defined($city->{buildings}->{safehouse}));
-    return 1 if(($city->{buildings}->{townHall} - $city->{buildings}->{wall}) > 2);
-    return 1 if($city->{buildings}->{townHall} >= 20);
-
-    # build the higgest safehouse.
-    # maybe we should have more then 4 towns, then we consider that we should upgrade safehouse at level 20.
-    # return (($city->{buildings}->{townHall} > $city->{buildings}->{safehouse}) ? 0 : 1) 
-    # return (($city->{buildings}->{townHall} <= ($city->{buildings}->{safehouse} + 4)) ? 0 : 1);
-
-    # Safehouse must be same level as townHall,
-    return (($city->{buildings}->{townHall} >= $city->{buildings}->{safehouse}) ? 0 : 1);
-}
-
-sub is_warehouse_enough {
-    my ($self, $city) = @_;
-
-    return 1;
-    # my @warehouse = (qw/undef undef 0 4 9 16 18 19 20 21 22 23 24 25/);
-    my @warehouse = (qw/undef undef 0 4 9 15 17 18 19 20 21 22 23 24/);
-    my @cities = keys(%{$self->{ikariam}->{cities}});
-    my $nextCities = ($#cities + 1) + 1;
-
-    Carp::carp(sprintf("Required warehouse level %s for next city (%s), current is %s\n", $warehouse[$nextCities], $nextCities, $city->{buildings}->{warehouse}));
-    return 0 if(!defined($city->{buildings}->{warehouse}));
-    return ($city->{buildings}->{warehouse} >= $warehouse[$nextCities]) ? 1 : 0;
-}
-
-
-sub is_warehouse_enougn_for_governorsresidence {
-    my ($self, $city) = @_;
-    return (($city->{buildings}->{warehouse} >= 5) ? 0 : 1);
-
-    my @warehouse = (qw/undef undef 0 4 9 16 18 19 20 21 22 23 24 25/);
-    my @cities = keys(%{$self->{ikariam}->{cities}});
-    my $citiesNumber = $#cities + 1;
-
-    Carp::carp(sprintf("Required warehouse level %s for %s cities, current is %s\n", $warehouse[$citiesNumber], $citiesNumber, $city->{buildings}->{warehouse}));
-    return 0 if(!defined($city->{buildings}->{warehouse}));
-    return ($city->{buildings}->{warehouse} >= $warehouse[$citiesNumber]) ? 1 : 0;
-}
-
-sub is_corruption {
-    my ($self, $city) = @_;
-    return ($city->{corruption} > 0) ? 1 : 0;
-}
-
-sub is_any_corruption {
-    my ($self, $city) = @_;
-
-    foreach (keys(%{$self->{ikariam}->{cities}})) {
-        return 1 if ($self->{ikariam}->{cities}->{$_}->{corruption} > 0);
-    }
-    return 0;
-}
-
-sub is_happiness {
-    my ($self, $city) = @_;
-
-    return ($city->{growth} >= 5 ?  1 : 0) 
-        if($city->{buildings}->{townHall} <= 10);
-
-    return ($city->{growth} >= 2 ?  1 : 0) 
-        if($city->{buildings}->{townHall} <= 15);
-
-    return 1 if($city->{buildings}->{townHall} >= 20);
-}
-
-
-sub is_bacchanal {
-    my ($self, $city) = @_;
-    return ($city->{tavern}->{maxValue} == $city->{tavern}->{iniValue} ? 1 : 0);
-}
-
-sub is_gold_enoughforcargo {
-    my ($self, $city) = @_;
-    my @cargoCost = qw/160 244 396 812 1240 1272 1832 1888 3848 3972 5204 5384 6868 7120 8864 9200 11268 11712 14108 14680 23320 24288 28664 29880 34956 36468 42348 44212 51024 53308 61236 64024 73096 76468 87020 91088 103224 116524 122072 137432 180060 202132 211964 237444 249108 278276 292076 306623 321963 338138 355198 373191 392171 412195 433320 455612 479135 503962 530166 557828 587031 617863 650420 684802 721113 759466 799981 842783 888005 935790 986286 1039654 1096062 1155689 1218724 1285369 1355837 1430353 1509159 1592508 1680670 1773932 1872597 1976989 2087448 2204338 2328045 2458976 2597567 2744276 2899594 3064040 3238163 3422550 3617820 3824635 4043693 4275738 4521561 4782000 5057946 5350345 5660202 5988585 6336630 6705540 7096598 7511164 7950683 8416694 8910828 9434823 9990523 10579889 11205006 11868090 12571498 13317734 14109462 14949514/;
-
-    if($city->{resources}->{gold} >= ($cargoCost[$city->{transporters}->{sum}]*5)) {
-        return 1;
-    } else {
-        return 0;
-    }
-}
-
-sub is_resource_enoghforHall {
-    my ($self, $city) = @_;
-    my @wood = qw/udnef 0 70 98 65 129 236 402 594 849 1176 1586 2101 3208 4937 7171 10139 14537 18420 22896 28047 33934 40623 48017 56511 226044 452088 904176 1808352 3616704 7233408 14466816 28933632/;
-    my @marble = qw/undef 0 0 17 28 66 95 156 243 406 579 799 1348 2124 2951 4409 6461 8187 10176 12466 15082 18055 21381 25116 100464 200928 401856 803712 1607424 3214848 6429696 12859392/;
-
-    my $level = $city->{buildings}->{townHall};
-    if($city->{resources}->{wood} >= $wood[$level] && $city->{resources}->{marble} >= $marble[$level] ) {
-        return 1;
-    }
-    warn(sprintf("Resource is short for build city hall. wood [%d] marble [%d] ", $wood[$level], $marble[$level]));
-    return 0;
-}
-
-sub is_expansion_researched {
-    my ($self, $city) = @_;
-    # $self->{'ikariam'}->
-    return (defined($self->{'ikariam'}->{research}->{1030}) ?  1 : 0);
-}
-
-sub is_foreigncultures_researched {
-    my ($self) = @_;
-    return (defined($self->{'ikariam'}->{research}->{1040}) ?  1 : 0);
-}
-
-sub is_greekfire_researched {
-    my ($self) = @_;
-    return (defined($self->{'ikariam'}->{research}->{1060}) ?  1 : 0);
-}
-
-sub is_paddlewheelengine_researched {
-    my ($self) = @_;
-    return (defined($self->{'ikariam'}->{research}->{1100}) ?  1 : 0);
-}
-
-sub is_conservation_researched {
-    my ($self) = @_;
-    return (defined($self->{'ikariam'}->{research}->{2010}) ?  1 : 0);
-}
-
-sub is_wealth_researched {
-    my ($self) = @_;
-    return (defined($self->{'ikariam'}->{research}->{2030}) ?  1 : 0);
-}
-
-sub is_winepress_researched {
-    my ($self) = @_;
-    return (defined($self->{'ikariam'}->{research}->{2040}) ?  1 : 0);
-}
-
-sub is_paper_researched {
-    my ($self) = @_;
-    return (defined($self->{'ikariam'}->{research}->{3020}) ?  1 : 0);
-}
-
-sub is_espionage_researched {
-    my ($self) = @_;
-    return (defined($self->{'ikariam'}->{research}->{3030}) ?  1 : 0);
-}
-
-sub is_invention_researched {
-    my ($self) = @_;
-    return (defined($self->{'ikariam'}->{research}->{3040}) ?  1 : 0);
-}
-
-sub is_culturalexchange_researched {
-    my ($self) = @_;
-    return (defined($self->{'ikariam'}->{research}->{3060}) ?  1 : 0);
-}
-
-sub is_professionalarmy_researched {
-    my ($self) = @_;
-    return (defined($self->{'ikariam'}->{research}->{4030}) ?  1 : 0);
-}
-
-sub is_drydock_researched {
-    my ($self) = @_;
-    return (defined($self->{'ikariam'}->{research}->{4010}) ?  1 : 0);
-}
-
-sub is_robotics_researched {
-    my ($self) = @_;
-    return (defined($self->{'ikariam'}->{research}->{4110}) ?  1 : 0);
-}
-
-
-sub is_barracks_level_enough {
-    my ($self, $city) = @_;
-    return 0 if(!defined($city->{buildings}->{barracks}));
-    if($self->is_robotics_researched() eq 1) {
-        return ($city->{buildings}->{barracks} >= 24 ? 1 : 0);
-    }
-
-    if($city->{buildings}->{townHall} >= 10) {
-        # optimum is 5
-        return ($city->{buildings}->{barracks} >= 5 ? 1 : 0);
-    } else {
-        # 方陣兵需要 level 4
-        return ($city->{buildings}->{barracks} >= 4 ? 1 : 0);
-    }
-}
-
-sub is_shipyard_availble {
-    my ($self, $city) = @_;
-    return 0 if(!defined($city->{buildings}->{shipyard}));
-    return 1;
-}
-
-sub is_shipyard_level_enough {
-    my ($self, $city) = @_;
-    return 0 if(!defined($city->{buildings}->{shipyard}));
-    if ($self->is_paddlewheelengine_researched() eq 1) {
-        return ($city->{buildings}->{shipyard} >= 16 ? 1 : 0);
-    } elsif ($self->is_greekfire_researched() eq 1) {
-        return ($city->{buildings}->{shipyard} >= 5 ? 1 : 0);
-    } else {
-        return ($city->{buildings}->{shipyard} >= 3 ? 1 : 0);
-    }
-}
-
-sub is_shipyard_upgrading {
-    my ($self, $city) = @_;
-    return $self->{'ikariam'}->is_shipyard_upgrading($city->{id});
-}
-
-sub is_navy_trainning {
-    my ($self, $city) = @_;
-    return $self->{'ikariam'}->is_navy_trainning($city->{id});
-}
-
-sub train_navy {
-    my ($self, $city) = @_;
-    my $cityId = $city->{id};
-    # TODO, 依照升級比例算 CP 值最高
-    if($self->is_greekfire_researched() eq 1 && $city->{buildings}->{shipyard} >= 5) {
-        # ok, we can build Flamethrower.
-        if(defined($city->{'fleet'}->{Flamethrower}) && ($city->{'fleet'}->{Flamethrower} > 0)
-                && ($city->{'fleet'}->{BallistaShip} / $city->{'fleet'}->{Flamethrower}) <= (1.5/1)) {
-            return 213; # 強弩船
-        } else {
-            return 211; # 噴火船
-        }
-    } else {
-        return 213; # 強弩船
-    }
-}
-
-sub is_barracks_upgrading {
-    my ($self, $city) = @_;
-    return $self->{ikariam}->is_barracks_upgrading($city->{id});
-}
-
-sub is_army_trainning {
-    my ($self, $city) = @_;
-    return $self->{ikariam}->is_army_trainning($city->{id});
-}
-sub train_army {
-    my ($self, $city) = @_;
-    my $cityId = $city->{id};
-
-    # TODO, 依照升級比例算 CP 值最高
-    my $assault = 'Swordsman';
-    my $resistance = 'Phalanx';
-
-    if(($city->{'army'}->{$assault} / $city->{'army'}->{$resistance}) <= (2/1)) {
-        return 302; # Swordsman
-    } else {
-        return 303; # Phalanx
-    }
-}
-
-# navy
-sub is_navyExpenditure_available
-{
-    my ($self, $city) = @_;
-    my $cityId = $city->{id};
-
-    # move this to somewhere else.
-    my $workersRatio = {
-        'citizens' => 0.4,
-        'specialworkers' => 0.3,
-        'woodworkers' => 0.7,
-    };
-
-    my $currentCost = $self->{'ikariam'}->getNavyExpenditure($cityId);
-    my $netincome = $self->{'ikariam'}->getNetIncome($cityId);
-    
-    # 軍費為 兩成 淨收入
-    # 陸軍佔用 0.3
-    # 海軍佔用 0.7
-    my $militaryExpenditure = int($netincome * 0.2 * 0.7);
-
-    if($currentCost < $militaryExpenditure) {
-        printf("Current navy expenditure total=%s, affordable %s\n", $currentCost, $militaryExpenditure);
-        return 1;
-    }
-    return 0;
-}
-
-# army
-sub is_milityExpenditure_available
-{
-    my ($self, $city) = @_;
-    my $cityId = $city->{id};
-
-    # move this to somewhere else.
-    my $workersRatio = {
-        'citizens' => 0.4,
-        'specialworkers' => 0.3,
-        'woodworkers' => 0.7,
-    };
-
-    my $currentCost = $self->{'ikariam'}->getMilityExpenditure($cityId);
-    my $netincome = $self->{'ikariam'}->getNetIncome($cityId);
-    
-    # 軍費為 兩成 淨收入
-    # 陸軍佔用 0.3
-    # 海軍佔用 0.7
-
-    my $militaryExpenditure = int($netincome * 0.2 * 0.3);
-
-    if($currentCost < $militaryExpenditure) {
-        Carp::carp("Current army expenditure total=%s, affordable %s\n", $currentCost, $militaryExpenditure);
-        return 1;
-    }
-    return 0;
-}
-
-1; 
-
-
 package main;
 my $verbose = 1;
 
@@ -405,7 +15,7 @@
 my $cities = $i->check;
 
 # Genereic rules for both overall and city level arranagement.
-my $rules = Ikariam::Cities::Rules->new($i);
+my $rules = Ikariam::CitiesRules->new($i);
 # blanace resources, arrange defance 
 my $tree  = LoadFile('overall.yaml');
 my $decision; $decision->{parse_path} = []; $decision->{parse_answer} = undef;
@@ -449,13 +59,15 @@
     DumpFile("military-$cityId-dump.yaml", $cities->{$cityId});
 
     # build and upgrade for cities
-    $tree  = LoadFile('city.yaml');
-    $cities->{$cityId}->{parse_path} = [];
-    $cities->{$cityId}->{parse_answer} = undef;
-    if (my $action = ParseTree($tree, $rules, $cities->{$cityId})) {
-        # printf("%s is suppressed\n", $action);
-        triggerAction($action, $cityId);
-    }
+#    $tree  = LoadFile('city.yaml');
+#    $cities->{$cityId}->{parse_path} = [];
+#    $cities->{$cityId}->{parse_answer} = undef;
+#    if (my $action = ParseTree($tree, $rules, $cities->{$cityId})) {
+#        # printf("%s is suppressed\n", $action);
+#        triggerAction($action, $cityId);
+#    }
+
+    
     DumpFile("city-$cityId-dump.yaml", $cities->{$cityId});
 }
 DumpFile("research-dump.yaml", $i->{'research'});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flash-city.yaml	Tue Apr 14 16:59:14 2009 +0800
@@ -0,0 +1,29 @@
+---
+- is_attacked:
+   0:
+      - is_constructing:
+         0:
+            - is_warehouse_available:
+               0:
+                  - is_conservation_researched:
+                     1: build_warehouse
+            - is_port_available:
+               0: build_port
+            - is_barracks_available:
+               0:
+                  - is_professionalarmy_researched:
+                     1: build_barracks
+            - is_shipyard_availble:
+               0:
+                  - is_professionalarmy_researched:
+                     1: build_shipyard
+            - is_warehouse_more_then_eight:
+               0:
+                  - is_conservation_researched:
+                     1: build_warehouse
+            - is_safehouse_enough:
+               0:
+                  - is_espionage_researched:
+                     1: build_safehouse
+            - is_port_enough:
+               0: build_port
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flash.pl	Tue Apr 14 16:59:14 2009 +0800
@@ -0,0 +1,37 @@
+#!/usr/bin/perl
+
+use strict;
+use Ikariam;
+use Ikariam::CitiesRules;
+use Data::Dumper;
+use Decision::ParseTree q{ParseTree};
+use YAML qw/LoadFile Dump DumpFile/;
+
+package main;
+my $cityId = 95780;
+my $cities = {};
+
+our $i = new Ikariam($::server, $::user, $::pass);
+$i->login;
+$i->changeCity($cityId);
+$cities->{$cityId} = $i->checkCity($cityId);
+
+# Genereic rules for both overall and city level arranagement.
+my $rules = Ikariam::CitiesRules->new($i);
+my $tree  = LoadFile('flash-city.yaml');
+$cities->{$cityId}->{parse_path} = [];
+$cities->{$cityId}->{parse_answer} = undef;
+if (my $action = ParseTree($tree, $rules, $cities->{$cityId})) {
+    triggerAction($action, $cityId);
+}
+
+$i->logout;
+
+sub triggerAction {
+    my ($action, $cityId) = @_;
+
+    my ($func, $param) = split(/_/,$action);
+    printf('$i->%s("%s", %s);'. "\n", $func, $param, $cityId);
+    eval(sprintf('$i->%s("%s", %s);', $func, $param, $cityId));
+    warn $@ if $@;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flash.sh	Tue Apr 14 16:59:14 2009 +0800
@@ -0,0 +1,35 @@
+#!/bin/sh
+# 
+# 跳島戰術
+# • 9000, 20 人 , 1250 木頭 (運 2000 木頭), 至少搬 6250 物資
+# • 時間表與資源
+# Warehouse, 160, 9 min 22 s
+# Trading port, 60, 16m 48s
+# Barracks, 49, 6m 36s
+# (32:46) 陸軍移動
+# Shipyard, 105, 43m 12s
+# (01:15:58) 海軍移動
+# Warehouse, 160, 9 min 22 s
+# Warehouse, 160, 9 min 22 s
+# Warehouse, 160, 9 min 22 s
+# Warehouse, 160, 9 min 22 s
+# Warehouse, 160, 9 min 22 s
+# Warehouse, 160, 9 min 22 s
+# Warehouse, 160, 9 min 22 s
+# Hideout, 113, 24m 00s
+# (2:45:32)
+# Wood: 1927
+
+perl flash.pl
+./at.sh "10 minutes" perl flash.pl
+./at.sh "17 minutes" perl flash.pl
+./at.sh "7 minutes" perl flash.pl
+./at.sh "44 minutes" perl flash.pl
+./at.sh "10 minutes" perl flash.pl
+./at.sh "10 minutes" perl flash.pl
+./at.sh "10 minutes" perl flash.pl
+./at.sh "10 minutes" perl flash.pl
+./at.sh "10 minutes" perl flash.pl
+./at.sh "10 minutes" perl flash.pl
+./at.sh "10 minutes" perl flash.pl
+