view warfare.pl @ 300:5fc26f2af95b

merged.
author "Rex Tsai <chihchun@kalug.linux.org.tw>"
date Sun, 07 Dec 2008 21:13:21 +0800
parents d194ff3edb2f
children 118605b58d09
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'}->{attack} > 0 ) ? 1 : 0;
}

sub is_actionPoint_enough {
    my ($self, $city) = @_;
    return ($city->{actionPoints} > ($city->{maxActionPoints}/3) ) ? 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 && $city->{army}->{Phalanx} >= 1) ? 1 : 0;
    return ($city->{army}->{Phalanx} >= 3) ? 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);

        # 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 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);
            }
        }

        # 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 don't attack same city twice at same time.
            next CITY if($_->{to} == $city->cityId);
        }
        # we attack one city maximum 4 times a day.
        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);

        # {
            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,
                {
                    # cargo_army_302 => '2', # 劍士
                    cargo_army_303 => '2', # 方陣
                }
                );
    }
}

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)) {
    # next if($cityId == 12345);

    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;