вторник, 6 ноября 2012 г.

Стратегия боя в CodeTanks Russian AI Cup 2012 на Pascal

Продолжая все те же темы, связанные с захватывающими соревнованиями, проводимыми компанией MailRu Group, а именно с  "Russian AI Cup 2012 - CodeTanks", решил поделиться стратегией боя на Pascal. Любителям Delphi посвящается сий кусок годного кода. Стратегия не самая лучшая, к победе без доработок не приведет, но это очень хорошая база для старта, особенно начинающим. Более того. эта стратегия способна Вас даже поднять на достойную позицию и даже может помочь пройти в 1й раунд, если повезет





Пишем стратегию для   Russian AI Cup - CodeTanks на Pascal:

unit MyStrategy;

interface

uses
 StrategyControl, TankControl, WorldControl, MoveControl, BonusControl, ShellControl, ObstacleControl, PlayerContextControl, PlayerControl, UnitControl;

type
 TMyStrategy = class(TStrategy)
 public
  procedure Move(me: TTank; world: TWorld; var move: TMove); override;
  function SelectTank(tankIndex: longint; teamSize: longint) : TTankType; override;

 end;

implementation

uses
 Math;

const
  minAngle = pi/6;
  MinAngleToEnemy = pi/180;

procedure MoveToBonus(BA: TBonusArray; k: integer; me: TTank; world: TWorld; var move: TMove);
var
  u: extended;
begin
if k <> length(BA) then
    begin
      u:= me.getangleto(BA[k]);
      if u > minAngle then
      begin
          if u < (pi - minAngle) then
            begin
              move.SetLeftTrackPower(0.75);
              move.SetRightTrackPower(-1.0);
            end
          else
            begin
              move.SetLeftTrackPower(-1.0);
              move.SetRightTrackPower(-1.0);
            end
       end
      else
        if u < -minAngle then
          begin
            if u > (-pi + minAngle) then
              begin
                move.SetLeftTrackPower(-1.0);
                move.SetRightTrackPower(0.75);
              end
            else
              begin
                move.SetLeftTrackPower(-1.0);
                move.SetRightTrackPower(-1.0);
              end
           end
        else
          begin
            move.SetLeftTrackPower(1.0);
            move.SetRightTrackPower(1.0);
          end;   
      end;
end;

function BonusPriority (BA:TBonusArray; me: TTank; world: TWorld; var move: TMove):TBonusType;
begin
  if (me.GetCrewHealth<75) or (me.GetHullDurability<150) then
    begin
      result:=MEDIKIT;
      if (me.GetHullDurability<100) then result:=REPAIR_KIT;
    end
  else Result:=AMMO_CRATE;
end;

procedure ShootToEnemy(TA:TTankArray; t:Integer; me:TTank; world:TWorld; var move:TMove);
begin
 if me.GetTurretAngleTo(TA[t]) > MinAngleToEnemy then Move.SetTurretTurn(1.0)
 else
   if me.GetTurretAngleTo(TA[t]) < -MinAngleToEnemy then Move.SetTurretTurn(-1.0)
    else move.SetFireType(PREMIUM_PREFERRED);
end;

procedure BACKCOMEBACK(Me:TTank; World:TWorld; var move:TMove);
var i:Integer;
 MinDist:extended;
begin
  MinDist:=1e20;
  i:=1;
  if me.getDistanceTo(World.GetHeight, 0)<MinDist then
  begin
    minDist:= me.getDistanceTo(World.GetHeight, 0);
    i:=2;
  end;
  if me.getDistanceTo(0, World.GetWidth)<MinDist then
  begin
    MinDist:= me.getDistanceTo(0, World.GetWidth);
    i:=3;
  end;
  if me.getDistanceTo(World.GetHeight, World.GetWidth) < MinDist then
  begin
    MinDist:=me.getDistanceTo(World.GetHeight, World.GetWidth)  ;
    i:=4;
  end;
 if (World.GetTick<50) then
  case i of
  1: begin
      move.SetLeftTrackPower(0.3);
      move.SetRightTrackPower(-0.7);
     end;
  2: begin
      move.SetLeftTrackPower(-0.7);
      move.SetRightTrackPower(0.3);
     end;
  3: begin
      move.SetLeftTrackPower(-0.7);
      move.SetRightTrackPower(0.3);
     end;
  4: begin
      move.SetLeftTrackPower(0.3);
      move.SetRightTrackPower(-0.7);
     end;
  end
  else
  begin
    move.SetLeftTrackPower(-1.0);
    move.SetRightTrackPower(-1.0);
  end;
end;

procedure TMyStrategy.Move(me: TTank; world: TWorld; var move: TMove);
var
  BA: TBonusArray;
  TA: TTankArray;
  i,TakeThis,k,ShootHim: integer;
  MinDistance,TrueMinAngleToEnemy: extended;
begin
  BA:= World.GetBonuses;
  TA:= World.GetTanks;
  i:= 0;
  k:= 0;
  TakeThis:= length(BA);
  ShootHim:= Length(TA);
  MinDistance:=1500;
  TrueMinAngleToEnemy:=1e20;
  BACKCOMEBACK(me,world,Move);
      while i < length(BA) do
        begin
          if BA[i].GetType = BonusPriority(BA, me, world, move) then
          if me.getDistanceTo(BA[i])<MinDistance then
            begin
              Mindistance:=me.getdistanceto(BA[i]);
              TakeThis:= i;
              break;
            end;
          i:=i+1;
        end;
  MoveToBonus(BA, TakeThis, me, world, move);
  while k < length(TA) do
  begin
   if (me.GetTurretAngleTo(TA[k])< TrueMinAngleToEnemy) and ((TA[k].GetCrewHealth>0) and (TA[k].GetHullDurability>0))  then
    begin
     TrueMinAngleToEnemy:=Abs(me.GetTurretAngleTo(TA[k]));
     ShootHIM:=k;
     break;
    end;
   k:=k+1;
  end;
  ShootToEnemy(TA, ShootHim, me, world, move);
end;
function TMyStrategy.SelectTank(tankIndex: longint; teamSize: longint) : TTankType;
begin
 Result := Medium;
end;

end.


2 комментария:

  1. Имхо, комментариев в коде не хватает. Не все пишут на Pascal'e.
    Что например делает метод BACKCOMEBACK(...) ?

    ОтветитьУдалить
    Ответы
    1. Ну, так есть примеры на других языках :)

      http://majorov.blogspot.ru/search/label/russian%20ai%20cup

      Ну а вообще, это такой способ "ныкаться" по углам. Логика без интеллекта. Едем задом если нет бонусов и ездим за бонусами если они есть. В начала раунда ныкаемся сразу в угол.

      Удалить