changeset 280:b5897d63f44e

work merged
author "Rex Tsai <chihchun@kalug.linux.org.tw>"
date Tue, 02 Dec 2008 17:20:56 +0800
parents cea21f99e56f (diff) 44099896397c (current diff)
children 0d2c2a379c63
files
diffstat 9 files changed, 402 insertions(+), 64 deletions(-) [+]
line wrap: on
line diff
--- a/Ikariam.pm	Mon Dec 01 15:32:44 2008 +0800
+++ b/Ikariam.pm	Tue Dec 02 17:20:56 2008 +0800
@@ -1,14 +1,29 @@
+
 BEGIN {
     foreach (((getpwuid($<))[7], $ENV{HOME}, $ENV{LOGDIR}, ".")) {
         require "$_/.eagleeye.pm" if (-f "$_/.eagleeye.pm");
     }
 }
 
+package Ikariam::Base;
+use strict;
+require Class::DBI::SQLite;
+use base qw(Class::DBI::SQLite);
+
+sub _db_error {
+    my ($self, %info) = @_;
+    my $msg = delete $info{msg};
+    die($msg);
+# return $self->_carp($msg, %info);
+}
+
+1;
+
 use Class::DBI::AutoLoader (
     dsn       => 'dbi:SQLite:dbname=ikariam.sqlite',
     options   => { RaiseError => 1 },
     tables    => ['cities', 'island', 'user', 'ally', 'report'],
-    use_base  => 'Class::DBI::SQLite',
+    use_base  => 'Ikariam::Base',
     namespace => 'Ikariam',
 );
 
@@ -118,16 +133,23 @@
         debug => undef,
     };
 
-
     # if debug
     LWP::Debug::level('+trace');
 
-    $self->{mech}->cookie_jar(HTTP::Cookies->new(file => "/tmp/ikariam-cookies.txt", autosave => 1));
+    $self->{mech}->cookie_jar(HTTP::Cookies->new(file => "/tmp/ikariam-$server-cookies.txt", autosave => 1, ignore_discard => 1));
     $self->{mech}->default_headers->push_header('Accept-Encoding', 'deflate');
  
     return bless $self, $class;
 }
 
+sub clone
+{
+    my $self = shift;
+    my $copy = bless { %$self }, ref $self;  # copy most fields
+
+    $copy;
+}
+
 sub viewAlly
 {
     my $self = shift;
@@ -626,6 +648,7 @@
 sub plunderCity {
     my $self = shift;
     my $cityId = shift;
+    my $fields = shift;
     my $res = $self->{mech}->get(sprintf("http://%s/index.php?view=plunder&destinationCityId=%d", $self->{server}, $cityId));
 
     my $extractor = Ikariam::Extractor->new(content => $res->content);
@@ -639,10 +662,40 @@
         } else {
             $self->{mech}->submit_form(
                     form_number => 1,
-                    fields      => {
-                           cargo_army_302 => '3', # 劍士
-                    }
-                    );
+                    fields      => $fields);
+        }
+    } else {
+        # put the id in the friends.txt file.
+        Ikariam::Cities->has_a(user => 'Ikariam::User');
+        my $city = Ikariam::Cities->retrieve($cityId);
+        my $sheep = $city->user;
+
+        open(OUT, ">>friends.txt") or Carp::carp("can not open friends.txt");
+        print OUT $sheep->name . "\n";
+        close(OUT);
+        Carp::carp($treaty);
+    }
+}
+
+
+sub blockadeCity {
+    my $self = shift;
+    my $cityId = shift;
+    my $fields = shift;
+    my $res = $self->{mech}->get(sprintf("http://%s/index.php?view=blockade&destinationCityId=%d", $self->{server}, $cityId));
+
+    my $extractor = Ikariam::Extractor->new(content => $res->content);
+    # check peace treaty
+    my $treaty = $extractor->find('//div[@class="warning"]');
+    if(!defined($treaty)) {
+        my @forms = $self->{mech}->forms();
+        if($#forms < 1) {
+            my $city = Ikariam::Cities->retrieve($cityId);
+            $city->delete;
+        } else {
+            $self->{mech}->submit_form(
+                    form_number => 1,
+                    fields      => $fields);
         }
     } else {
         # put the id in the friends.txt file.
--- a/agent.pl	Mon Dec 01 15:32:44 2008 +0800
+++ b/agent.pl	Tue Dec 02 17:20:56 2008 +0800
@@ -21,7 +21,7 @@
 sub is_attacked {
     my ($self, $city) = @_;
 
-    return ($self->{'ikariam'}->{'military'}->{attacks} > 0 ) ? 1 : 0;
+    return ($self->{'ikariam'}->{'military'}->{attack} > 0 ) ? 1 : 0;
 }
 
 sub is_constructing {
@@ -39,6 +39,7 @@
 sub is_academy_enough {
     my ($self, $city) = @_;
     return ($city->{buildings}->{academy} >= 6 ?  1 : 0);
+    return ($city->{buildings}->{academy} >= 16 ?  1 : 0);
 }
 
 sub is_embassy_enough {
@@ -48,6 +49,7 @@
 
 sub is_museum_enough {
     my ($self, $city) = @_;
+    return 1 if($city->{buildings}->{museum} >= 8);
     return ($city->{buildings}->{museum} >= ($city->{buildings}->{tavern}/2) ? 1 : 0);
 }
 
@@ -68,22 +70,21 @@
 sub is_safehouse_enough {
     my ($self, $city) = @_;
     return 0 if(!defined($city->{buildings}->{safehouse}));
+    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) 
-        # if($$city->{buildings}->{townHall} >= 20);
     # return (($city->{buildings}->{townHall} <= ($city->{buildings}->{safehouse} + 4)) ? 0 : 1);
 
     # Safehouse must be same level as townHall,
-    # Maybe one level higher is better.
-    return (($city->{buildings}->{townHall} > $city->{buildings}->{safehouse}) ? 0 : 1);
+    return (($city->{buildings}->{townHall} >= $city->{buildings}->{safehouse}) ? 0 : 1);
 }
 
 sub is_warehouse_enough {
     my ($self, $city) = @_;
     # 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 18 19 20 21 22 23 24 25/);
+    my @warehouse = (qw/undef undef 0 4 9 15 17 19 20 21 22 23 24 25/);
     my @cities = keys(%{$self->{ikariam}->{cities}});
     my $nextCities = ($#cities + 1) + 1;
 
@@ -122,11 +123,12 @@
     my ($self, $city) = @_;
 
     return ($city->{growth} >= 5 ?  1 : 0) 
-        if($city->{buildings}->{townHall} <= 16);
+        if($city->{buildings}->{townHall} <= 10);
+
+    return ($city->{growth} >= 2 ?  1 : 0) 
+        if($city->{buildings}->{townHall} <= 15);
 
     return 1 if($city->{buildings}->{townHall} >= 20);
- 
-    return ($city->{happiness} >= 2 ?  1 : 0);
 }
 
 sub is_tavern_available {
@@ -395,6 +397,8 @@
     $i->buildSpy('spy', $cityId);
     # enlarge the scientist number.
     $i->set("academy", $cityId);
+
+    # Only when you are not happy.
     $i->set("tavern", $cityId);
 
     # build military!
@@ -411,6 +415,7 @@
     $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});
--- a/city.yaml	Mon Dec 01 15:32:44 2008 +0800
+++ b/city.yaml	Tue Dec 02 17:20:56 2008 +0800
@@ -27,7 +27,7 @@
                      0:
                        - is_museum_enough:
                           0:
-                           - is_culturalexchange_resaerched:
+                           - is_culturalexchange_researched:
                               1: build_museum
                        - is_winepress_researched:
                            1:
@@ -37,8 +37,6 @@
                                     - is_bacchanal:
                                        0: set_tavern
                                        1: build_tavern
-                  - is_wall_enough:
-                     0: build_wall
                   - is_shipyard_level_enough:
                      0:
                         - is_professionalarmy_researched:
@@ -51,6 +49,8 @@
                      0:
                         - is_espionage_researched:
                            1: build_safehouse
+                  - is_wall_enough:
+                     0: build_wall
                   - is_academy_enough:
                      0: build_academy
                   # 大使館
@@ -60,7 +60,7 @@
                            1: build_embassy 
                   - is_museum_enough:
                      0:
-                        - is_culturalexchange_resaerched:
+                        - is_culturalexchange_researched:
                            1: build_museum
                   - is_warehouse_enough:
                      0:
--- a/enemy.pl	Mon Dec 01 15:32:44 2008 +0800
+++ b/enemy.pl	Tue Dec 02 17:20:56 2008 +0800
@@ -2,32 +2,112 @@
 use strict;
 use Ikariam;
 use Data::Dumper;
+use YAML qw/LoadFile/;
+use POSIX qw(strftime);
 
 package main;
 my @tradegoodText = qw/NULL 葡萄酒 大理石 水晶 硫磺/;
 my @wonderText = qw/NULL 赫菲斯拓斯的熔爐 蓋亞的神殿 狄奧尼索斯的花園 雅典娜的神殿 赫秘士的神殿 阿瑞斯的要塞 波賽頓的神殿 克羅瑟斯的神殿/;
 
+Ikariam::User->has_many(cities => 'Ikariam::Cities');
+
+sub travelTime {
+    my ($x1, $y1, $x2, $y2, $speed) = @_;
+    $speed = 20 unless(defined($speed));
+    return int( (sqrt((abs($x1 - $x2) * abs($x1 - $x2)) + (abs($y1 - $y2) * abs($y1 - $y2)))+1) * (400/$speed));
+}
+
+sub travelMatrix {
+    my $userName = shift;
+    my @cities = ();
+    if(my $user = Ikariam::User->retrieve(name => $userName)) {
+
+        foreach my $target ($user->cities) {
+            my $island = Ikariam::Island->retrieve($target->island);
+            my $city;
+            $city->{id} = $target->id;
+            $city->{name} = $target->cityname;
+            $city->{island}->{id} = $island->id;
+            $city->{island}->{x} = $island->x;
+            $city->{island}->{y} = $island->y;
+
+            push (@cities, $city);
+        }
+    }
+
+    my $n = $#cities;
+
+    # Print them out.
+    # header
+    printf("Defence\n");
+    printf(" %5s ", undef);
+    for my $y (0..$n) {
+        printf ("%5s ", $cities[$y]->{id});
+    }
+    print "\n";
+
+    # body
+    for my $x (0..$n) {
+        printf(" %5s ", $cities[$x]->{id});
+        my $total = 0;
+        for my $y (0..$n) {
+            my $t = travelTime($cities[$x]->{island}->{x}, $cities[$x]->{island}->{y}, $cities[$y]->{island}->{x}, $cities[$y]->{island}->{y});
+            printf("%5s ", $t);
+            $total += $t;
+        }
+        printf(" %s", $cities[$x]->{name});
+        printf("\n");
+    }
+    printf("\n");
+}
+
+sub myTownToVicim {
+    my $islandId = shift;
+
+    if(my $island = Ikariam::Island->retrieve($islandId)) {
+        my @cities = ();
+        foreach (glob("city-*-dump.yaml")) {
+            my $city = LoadFile($_);
+            $city->{distance} = travelTime($island->x, $island->y, $city->{island}->{x}, $city->{island}->{y}, 20);
+            push (@cities, $city);
+        }
+        @cities = sort { $a->{distance} <=> $b->{distance}; } (@cities);
+
+        my $n = $#cities;
+        for my $x (0..$n) {
+            printf("%s (%d)\t- ", $cities[$x]->{name}, $cities[$x]->{id});
+            printf("Land %3d Ship %3d Catapult %3d Ram %3d\n", 
+                    travelTime($cities[$x]->{island}->{x}, $cities[$x]->{island}->{y}, $island->x, $island->y),
+                    travelTime($cities[$x]->{island}->{x}, $cities[$x]->{island}->{y}, $island->x, $island->y, 8),
+                    travelTime($cities[$x]->{island}->{x}, $cities[$x]->{island}->{y}, $island->x, $island->y, 6),
+                    travelTime($cities[$x]->{island}->{x}, $cities[$x]->{island}->{y}, $island->x, $island->y, 10),
+                  );
+        }
+    }
+}
+
+package main;
+
 if($#ARGV != 0) {
     die("Usage: $0 nickname\n");
 }
 
-# system('perl scores.pl ' . $ARGV[0]);
-
-Ikariam::User->has_many(cities => 'Ikariam::Cities');
 my ($u) = Ikariam::User->search('name' => $ARGV[0]);
 if(defined($u)) {
     foreach my $i (qw/name score trader_score_secondary army_score_main ally/) {
         printf("%s: %s\n", $i, $u->get($i));
     }
+    printf("time: %s\n",  strftime ("%Y-%m-%d %H:%M", localtime($u->get('time'))));
+
+    travelMatrix($ARGV[0]);
+
     printf("\nCities\n");
-    # print Dumper($u->_data_hash);
     foreach my $city ($u->cities) {
         my $island = Ikariam::Island->retrieve($city->island);
         my $capture = $city->citylevel * ($city->citylevel - 1) * $u->trader_score_secondary / 10000;
 
         printf("Name: %s\n", $city->cityname);
-        if(defined($city->status))
-        {
+        if(defined($city->status)) {
             printf("Status: <<<%s>>>\n", $city->status);
         }
         printf("Level: %s\n", $city->citylevel);
@@ -36,9 +116,9 @@
             $island->x, $island->y, $::server, $island->id, $city->cityId);
         printf("Tradegood: %s\n", $tradegoodText[$island->tradegood]);
         printf("Wonder: %s\n", $wonderText[$island->wonder]);
-        printf("capture score: %d\n\n", $capture);
-        # print Dumper($island->_data_hash);
-        # print Dumper($city->_data_hash);
+        printf("Capture: %d\n", $capture);
+        myTownToVicim($island->id);
+        printf("\n");
     }
     print "-"x80 . "\n";
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/enemy_scores.pl	Tue Dec 02 17:20:56 2008 +0800
@@ -0,0 +1,28 @@
+#!/usr/bin/perl
+use strict;
+use Ikariam;
+use Data::Dumper;
+use YAML qw/LoadFile/;
+use POSIX qw(strftime);
+
+package main;
+my @tradegoodText = qw/NULL 葡萄酒 大理石 水晶 硫磺/;
+my @wonderText = qw/NULL 赫菲斯拓斯的熔爐 蓋亞的神殿 狄奧尼索斯的花園 雅典娜的神殿 赫秘士的神殿 阿瑞斯的要塞 波賽頓的神殿 克羅瑟斯的神殿/;
+
+package main;
+
+if($#ARGV != 0) {
+    die("Usage: $0 nickname\n");
+}
+
+my ($u) = Ikariam::User->search('name' => $ARGV[0]);
+if(defined($u)) {
+    foreach my $i (qw/name time score trader_score_secondary army_score_main ally/) {
+        if($i eq "time") {
+            printf("time: %s, ",  strftime ("%Y-%m-%d %H:%M", localtime($u->get('time'))));
+        } else {
+            printf("%s: %s, ", $i, $u->get($i));
+        }
+    }
+    print("\n");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/planner.pl	Tue Dec 02 17:20:56 2008 +0800
@@ -0,0 +1,122 @@
+#!/usr/bin/perl
+use Ikariam;
+use Data::Dumper;
+use Decision::ParseTree q{ParseTree};
+use YAML qw/LoadFile Dump DumpFile/;
+
+Ikariam::Cities->has_a(island => 'Ikariam::Island');
+
+my $army = {
+    "Slinger" => 301,
+    "Swordsman" => 302,
+    "Phalanx" => 303,
+    "Ram" => 307,
+    "Archer" => 313,
+    "Catapult" => 306,
+    "Gunsman" => 304,
+    "Mortar" => 305,
+    "SteamGiant" => 308,
+    "Gyrocopter" => 312,
+    "Bombardier" => 309,
+    "Doctor" => 311,
+    "Cook" => 310,
+};
+
+my $fleet = {
+    "CargoShip" => 201,
+    "Ram-Ship" => 210,
+    "BallistaShip" => 213,
+    "Flamethrower" => 211,
+    "CatapultShip" => 214,
+    "MortarShip" => 215,
+    "PaddleWheel Ram" => 216,
+    "DivingBoat" => 212,
+};
+
+# return minutes.
+sub travelTime {
+    my ($x1, $y1, $x2, $y2, $speed) = @_;
+    $speed = 20 unless(defined($speed));
+    return int( (sqrt((abs($x1 - $x2) * abs($x1 - $x2)) + (abs($y1 - $y2) * abs($y1 - $y2)))+1) * (400/$speed));
+}
+
+package main;
+if($#ARGV < 2) {
+    die("Usage: %s targetCity navyCity armyCity wingman1.. wingman2..\n");
+}
+my $targetCityId = shift(@ARGV);
+my $navyCity = shift(@ARGV);
+my $armyCity = shift(@ARGV);
+my @wingman = @ARGV;
+
+my $targetCity = Ikariam::Cities->retrieve($targetCityId);
+
+
+# NAVY
+my $city = LoadFile(sprintf("city-%s-dump.yaml", $navyCity));
+$city->{distance} = travelTime($targetCity->island->x, $targetCity->island->y, $city->{island}->{x}, $city->{island}->{y}, 8) + 45;
+$city->{type} = "navy";
+push (@cities, $city);
+
+# ARMY
+my $city = LoadFile(sprintf("city-%s-dump.yaml", $armyCity));
+$city->{distance} = travelTime($targetCity->island->x, $targetCity->island->y, $city->{island}->{x}, $city->{island}->{y}, 20) + 5;
+$city->{type} = "army";
+push (@cities, $city);
+
+# wingman, army
+foreach my $cityId (@wingman) {
+    my $city = LoadFile(sprintf("city-%s-dump.yaml", $cityId));
+    $city->{distance} = travelTime($targetCity->island->x, $targetCity->island->y, $city->{island}->{x}, $city->{island}->{y}, 20);
+    push (@cities, $city);
+}
+
+@cities = sort { $a->{distance} <=> $b->{distance}; } (@cities);
+
+
+# print the code.
+print <<EOF;
+#!/usr/bin/perl
+use strict;
+use Ikariam;
+use Data::Dumper;
+package main;
+my \$ikariam = new Ikariam(\$::server, \$::user, \$::pass);
+EOF
+
+printf ("# %s %s [%s:%s]\n", $targetCity->owner, $targetCity->cityname, $targetCity->island->x, $targetCity->island->y);
+printf ("# http://%s/index.php?view=island&id=%d&selectCity=%d\n", $::server, $targetCity->island->id, $targetCity->id);
+
+for(my $i = ($#cities + 1) ; $i-- ; $i < 0 ) {
+
+    if($i ne $#cities) {
+        # TODO, 計算港口速度
+        # 減掉 cities[$i+1]->buliding->port 的速度
+        printf("sleep(%d*60);\n",
+                ($cities[$i+1]->{distance} - $cities[$i]->{distance}));
+    }
+    printf("\n# %s %s %dm\n", $cities[$i]->{name}, $cities[$i]->{type}, $cities[$i]->{distance});
+
+    printf('$ikariam->login;' . "\n");
+    if($cities[$i]->{type} eq "navy") {
+        printf('$ikariam->changeCity(%d);' . "\n", $cities[$i]->{id});
+        printf('$ikariam->blockadeCity(%d, {' . "\n", $targetCity->id);
+        printf('blockadeDuration => 8*60*60,' . "\n");
+        while (my ($k, $v) = each(%{$cities[$i]->{fleet}})) {
+            if($v > 0) {
+                printf("cargo_fleet_%s => %s, # %s \n", $fleet->{$k}, $v, $k);
+            }
+        }
+        printf('});' . "\n", $cities[$i]->{id});
+    } else {
+        printf('$ikariam->changeCity(%d);' . "\n", $cities[$i]->{id});
+        printf('$ikariam->plunderCity(%d, {' . "\n", $targetCity->id);
+        while (my ($k, $v) = each(%{$cities[$i]->{army}})) {
+            if($v > 0) {
+                printf("cargo_army_%s => %s, # %s \n", $army->{$k}, $v, $k);
+            }
+        }
+        printf('});' . "\n", $cities[$i]->{id});
+    }
+    printf('$ikariam->logout;' . "\n");
+}
--- a/scan.pl	Mon Dec 01 15:32:44 2008 +0800
+++ b/scan.pl	Tue Dec 02 17:20:56 2008 +0800
@@ -3,12 +3,31 @@
 use Data::Dumper;
 use Carp;
 use Ikariam;
+use Parallel::ForkManager;
 
 package main;
 
+package Ikariam::Scanner;
+use strict;
+use Carp;
+use Ikariam;
+use Data::Dumper;
+use Error;
+use Parallel::ForkManager;
+
+sub new {
+    my($class, $i) = @_;
+    warn("new scanner");
+    my $self = {
+        ikariam => $i,
+    };
+
+    return bless $self, $class;
+}
+
 sub saveCities
 {
-    my ($island, @cities) = @_;
+    my ($self, $island, @cities) = @_;
 
     if ($#cities == -1) {
         warn ("empty cities list.\n");
@@ -16,7 +35,8 @@
     }
 
     foreach my $h_city (@cities) {
-# Carp::carp(sprintf("checking %s\n", $h_city->{'cityname'}));
+        # Carp::carp(sprintf("checking %s\n", $h_city->{'cityname'}));
+        print(STDERR sprintf("checking cityname %s\n", $h_city->{'cityname'}));
         $h_city->{island} = $island;
         $h_city->{'time'} = time;
         my $c = Ikariam::Cities->retrieve($h_city->{cityId});
@@ -32,59 +52,67 @@
         my $user = Ikariam::User->retrieve($h_city->{'user'});
         next if (defined($user) && defined($user->time) && $user->time gt (time - 30*60));
 
-        saveUser($h_city->{owner});
+        $self->saveUser($h_city->{owner});
     }
 }
 
 sub saveUser
 {
+    my $self = shift;
     my $userName = shift;
     my $users;
 
     foreach my $x (qw/score army_score_main trader_score_secondary/) {
-        $users = $::i->viewScore($x, $userName, 0);
+        my $i = $self->{ikariam}->clone();
+        $users = $i->viewScore($x, $userName, 0);
 
         foreach my $h_user (values(%{$users})) {
-# Carp::carp(sprintf("Saving user %s\n", $h_user->{'name'}));
+            # Carp::carp(sprintf("Saving user %s\n", $h_user->{'name'}));
             $h_user->{'time'} = time;
-
             my $user = Ikariam::User->retrieve($h_user->{'id'});
             if(defined($user)) {
+                # check if the arm score is down
                 foreach (keys(%$h_user)) { $user->set($_ => $h_user->{$_}); }
             } else {
                 $user = Ikariam::User->insert($h_user);
             }
             $user->update();
-            saveAlly($h_user->{allyId});
+            $self->saveAlly($h_user->{allyId});
         }
     }
 }
 
 sub saveAlly
 {
+    my $self = shift;
     my $allyId = shift;
     return unless (defined($allyId) && $allyId ne '0');
 
     # Save for member of ally 
     my $ally = Ikariam::Ally->retrieve($allyId);
     if(!defined($ally) || $ally->time le (time - 30*60*1)) {
-        my $h_ally = $::i->viewAlly($allyId);
+        my $i = $self->{ikariam}->clone();
+        my $h_ally = $i->viewAlly($allyId);
         $h_ally->{'time'} = time;
         if(defined($ally)) {
             foreach (keys(%$h_ally)) { $ally->set($_ => $h_ally->{$_}); }
         } else {
             $ally = Ikariam::Ally->insert($h_ally);
         }
+        $ally->update();
     }
 }
 
 sub saveIslands {
-    my @islands = @_;
+    my ($self, @islands) = @_;
+
+    my $pm = new Parallel::ForkManager(10);
 
     foreach my $h_island (@islands)
     {
-        # printf("checking island %d\n", $h_island->{id});
-
+        my $pid = $pm->start and next;
+        
+        printf("checking island %d\n", $h_island->{id});
         my $island;
         if($island = Ikariam::Island->retrieve($h_island->{id})) {
             foreach my $i (keys(%$h_island)) {
@@ -95,45 +123,47 @@
         }
 
         # scanning the island
-        # 10 minutes cache.
-        if($island->time le (time - 60*10))
-        {
-            my @cities = $::i->viewIsland($h_island->{id});
-            saveCities($h_island->{id}, @cities);
-
+        # 30 minutes cache.
+        if($island->time le (time - 60*30)) {
+            my $i = $self->{ikariam}->clone();
+            my @cities = 
+                $i->viewIsland($h_island->{id});
+            $self->saveCities($h_island->{id}, @cities);
             $island->set('time', time);
         }
         $island->update();
 
+        $pm->finish;
     }
+    $pm->wait_all_children;
 }
 
+1;
+
+package main;
 
 # local $SIG{ALRM} = sub { die "timeout\n" };
 # alarm 3;
 our $i = new Ikariam($::server, $::user, $::pass);
 
+$i->login;
 if($#ARGV == 1) {
-    $i->login;
     my @islands = $i->viewWorldMap($ARGV[0], $ARGV[1]);
-    saveIslands(@islands);
-    $i->logout;
+    # my $s = new Ikariam::Scanner($i);
+    # $s->saveIslands(@islands);
+    new Ikariam::Scanner($i)->saveIslands(@islands);
 } elsif($#ARGV == 0) {
-    $i->login;
     my $island = $ARGV[0];
     my @cities = $i->viewIsland($island);
-    saveCities($island, @cities);
-    $i->logout;
+    new Ikariam::Scanner($i)->saveCities($island, @cities);
 } elsif($#ARGV == -1) {
-    $i->login;
     my $cities = $i->check;
     # random
     foreach my $cityId (keys(%$cities)) {
-# Carp::carp(sprintf("Checking island location [%s:%s]\n", $cities->{$cityId}->{island}->{x},  $cities->{$cityId}->{island}->{y}));
         my @islands = $i->viewWorldMap( $cities->{$cityId}->{island}->{x},  $cities->{$cityId}->{island}->{y});
-        saveIslands(@islands);
+        new Ikariam::Scanner($i)->saveIslands(@islands);
     }
-    $i->logout;
 } else {
     die("Usage: $0\nUsage: $0 x y\n");
 }
+$i->logout;
--- a/sheep.pl	Mon Dec 01 15:32:44 2008 +0800
+++ b/sheep.pl	Tue Dec 02 17:20:56 2008 +0800
@@ -59,6 +59,7 @@
                 unless ($sheep->allyId == '0') {
                     unless (!defined($sheep->allyId) || $sheep->allyId == 0) {
                         my $ally = Ikariam::Ally->retrieve($sheep->allyId);
+                        next if(!defined($ally));
                         next if($ally->score > $myAlly->score);
                     }
                 }
--- a/warfare.pl	Mon Dec 01 15:32:44 2008 +0800
+++ b/warfare.pl	Tue Dec 02 17:20:56 2008 +0800
@@ -40,12 +40,12 @@
 
 sub is_attacked {
     my ($self, $city) = @_;
-    return ($self->{'ikariam'}->{'military'}->{attacks} > 0 ) ? 1 : 0;
+    return ($self->{'ikariam'}->{'military'}->{attack} > 0 ) ? 1 : 0;
 }
 
 sub is_actionPoint_enough {
     my ($self, $city) = @_;
-    return ($city->{actionPoints} > ($city->{maxActionPoints}/2) ) ? 1 : 0;
+    return ($city->{actionPoints} > ($city->{maxActionPoints}/3) ) ? 1 : 0;
 }
 
 sub is_transporters_available {
@@ -64,7 +64,9 @@
 
 sub is_army_available {
     my ($self, $city) = @_;
-    return ($city->{army}->{Swordsman} >= 2 ) ? 1 : 0;
+    # 方陣撞不死
+    # return ($city->{army}->{Swordsman} >= 2 && $city->{army}->{Phalanx} >= 1) ? 1 : 0;
+    return ($city->{army}->{Phalanx} >= 3) ? 1 : 0;
 }
 
 sub locateVictim {
@@ -88,17 +90,20 @@
         # we don't fight with members in same ally.
         next if($sheep->allyId == $user->allyId);
 
-        # we fight for island which ownes differnet trade goods.
-        next if($island->tradegood == $tradegood);
         # Ignore the user in vacation which we can not attack.
         next if($city->status eq 'v');
         unless ($city->status eq 'i') {
+            # we fight for island which ownes differnet trade goods.
+            next CITY if($island->tradegood == $tradegood);
+
             unless (!defined($sheep->allyId) || $sheep->allyId == 0) {
                 my $ally = Ikariam::Ally->retrieve($user->allyId);
                 my $targetAlly = Ikariam::Ally->retrieve($sheep->allyId);
                 # We don't want to piss off the big team.
-                next if($targetAlly->score > $ally->score);
-                # next if(defined($ally) && $ally->members > 10);
+                next CITY if(!defined($ally));
+                next CITY if($ally->score == 0);
+                next CITY if($targetAlly->score > $ally->score);
+                next CITY if(defined($ally) && $ally->members > 12);
             }
         }
 
@@ -108,9 +113,16 @@
         foreach (@{$self->{ikariam}->{'military'}->{'homeland'}}) {
             # counting for both leaving and coming back.
             $c++ if($_->{to} == $city->cityId || $_->{from} == $city->cityId);
+
+            # we don't attack same city twice at same time.
+            next CITY if($_->{to} == $city->cityId);
         }
         # we attack one city maximum 4 times a day.
-        next if($c >= 4);
+        if ($city->status eq 'i') {
+            next CITY if($c >= 6);
+        } else {
+            next CITY if($c >= 4);
+        }
 
         my $capture = $city->citylevel * ($city->citylevel - 1) * $sheep->trader_score_secondary / 10000;
         next if($capture < 1500);
@@ -134,7 +146,12 @@
     my $victim = $self->locateVictim($cityId, $x, $y, $tradegood);
     if(defined($victim)) {
         $self->{ikariam}->changeCity($cityId);
-        $self->{ikariam}->plunderCity($victim);
+        $self->{ikariam}->plunderCity($victim,
+                {
+                    # cargo_army_302 => '2', # 劍士
+                    cargo_army_303 => '3', # 方陣
+                }
+                );
     }
 }
 
@@ -151,6 +168,8 @@
 $i->checkFriends();
 
 foreach my $cityId (keys(%$cities)) {
+    # next if($cityId == 12345);
+
     print Dump($i->{'military'});
     # build and upgrade for cities
     my $tree  = LoadFile('warfare.yaml');