view warfare.pl @ 232:978a949602e5

Auto-update Scientists numbers for Academy. Refined the rules for safehouse, the safe house must be same or higher level then Town Hall. Make people very happy, when the townHall is less then 16. Build museum first then tavern THG: changed warfare.pl
author "Rex Tsai <chihchun@kalug.linux.org.tw>"
date Thu, 06 Nov 2008 20:31:05 +0800
parents 31fca1e55ed5
children 64549ddddf4a
line wrap: on
line source

#!/usr/bin/perl
use strict;
use Ikariam;
use Data::Dumper;
use Decision::ParseTree q{ParseTree};
use YAML qw/LoadFile Dump DumpFile/;

package Ikariam::Warfare::Rules;
use strict;
use Data::Dumper;

Ikariam::User->has_many(cities => 'Ikariam::Cities');
Ikariam::Cities->has_a(user => 'Ikariam::User');
Ikariam::Cities->has_a(island => 'Ikariam::Island');
Ikariam::Cities->set_sql(sheeps => qq {
        SELECT cities.cityId
          FROM user, cities 
         WHERE user.id = cities.user 
           AND user.army_score_main = 0
           AND cities.island IN (SELECT island.id FROM island WHERE island.x <= ? AND island.x >= ? AND island.y <= ? AND island.y >= ? )
         ORDER BY cities.citylevel * (cities.citylevel - 1) * user.trader_score_secondary / 10000 DESC
    }
);

Ikariam::Report->set_sql(victim => qq {
        SELECT report.id
          FROM report
         WHERE report.city = ?
           AND report.date >= ?
    } 
);

sub new {
    my ( $class, $i ) = @_;
    my $self = {
        ikariam => $i,
    };
    return bless $self, $class;
}

sub is_attacked {
    my ($self, $city) = @_;
    return ($self->{'ikariam'}->{'military'}->{attacks} > 0 ) ? 1 : 0;
}

sub is_actionPoint_enough {
    my ($self, $city) = @_;
    return ($city->{actionPoints} > ($city->{maxActionPoints}/2) ) ? 1 : 0;
}

sub is_transporters_available {
    my ($self, $city) = @_;
    # we keep 10 transporters for prize
    return ($city->{transporters}->{avail} > 10) ? 1 : 0;
}

sub is_port_available {
    my ($self, $city) = @_;
    foreach(1..2) {
        return 1 if($city->{locations}[$_] eq 'port');
    }
    return 0;
}

sub is_army_available {
    my ($self, $city) = @_;
    return ($city->{army}->{Swordsman} >= 2 ) ? 1 : 0;
}

sub locateVictim {
    my ($self, $city, $x, $y, $tradegood) = @_;

    my $user = Ikariam::User->retrieve('name' => $::user);

    my @cities = Ikariam::Cities->search_sheeps(($x + 6), ($x - 6), ($y + 6), ($y - 6));
CITY: foreach my $city (@cities) {
        my $sheep = $city->user;
        my $island = $city->island;

        # TODO update sheep and island information.

        # we don't fight friends.
        # FIXME: This is very dirty for accessing to $::i directly.
        foreach (keys(%{$::i->{friends}})) {
            next CITY if ($sheep->id == $_);
        }

        # 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') {
            unless (!defined($sheep->allyId) || $sheep->allyId == 0) {
                my $ally = Ikariam::Ally->retrieve($sheep->allyId);
                # Ignore the ally which have more then 10 members. 
                # We don't want to piss off the big team.
                next if(defined($ally) && $ally->members > 10);
            }
        }

        # check if we over-attacked
        my $c = Ikariam::Report->search_victim($city->cityId, time - 24*60*60 - 7*60*60)->count();
        # check the current plunders
        foreach (@{$self->{ikariam}->{'military'}->{'homeland'}}) {
            # counting for both leaving and coming back.
            $c++ if($_->{to} == $city->cityId || $_->{from} == $city->cityId);
        }
        # we attack one city maximum 4 times a day.
        next if($c >= 4);

        my $capture = $city->citylevel * ($city->citylevel - 1) * $sheep->trader_score_secondary / 10000;
        next if($capture < 1500);

        # {
            my $line = sprintf("%d %s [%d,%d] %s (%d) %s Attacked %d", 
                $capture, $city->status, 
                $island->x, $island->y,
                $city->cityname, $city->cityId,
                $sheep->name, $c);
            
            printf("%s\n", $line);
        # }
        return $city->cityId;
    }
    return undef;
}

sub engagement {
    my ($self, $cityId, $x, $y, $tradegood) = @_;
    my $victim = $self->locateVictim($cityId, $x, $y, $tradegood);
    if(defined($victim)) {
        $self->{ikariam}->changeCity($cityId);
        $self->{ikariam}->plunderCity($victim);
    }
}

1;

package main;

our $i = new Ikariam($::server, $::user, $::pass);
our $rules = Ikariam::Warfare::Rules->new($i);

$i->login;
my $cities = $i->check;
$i->checkMilitaryAdvisorCombatReports();
$i->checkFriends();

foreach my $cityId (keys(%$cities)) {
    print Dump($i->{'military'});
    # build and upgrade for cities
    my $tree  = LoadFile('warfare.yaml');
    $cities->{$cityId}->{parse_path} = [];
    $cities->{$cityId}->{parse_answer} = undef;
    if(ParseTree($tree, $rules, $cities->{$cityId}) eq 'engagement') {
        my $island = Ikariam::Island->retrieve($cities->{$cityId}->{island}->{id});
        $rules->engagement($cityId, $island->{x}, $island->{y}, $island->tradegood);
        sleep(30);
        $i->checkMilitaryAdvisorMilitaryMovements();
    }
    print Dump($cities->{$cityId}->{parse_path});
}
DumpFile("warfare-dump.yaml", $cities);

$i->logout;