Advertisement
s-a--m

CodeTanks 2012 faceless

Dec 3rd, 2012
433
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 120.92 KB | None | 0 0
  1. import static java.lang.StrictMath.PI;
  2. //import java.util.logging.Logger;
  3. import model.Bonus;
  4. import model.BonusType;
  5. import model.FireType;
  6. import model.Move;
  7. //import model.Obstacle;
  8. import model.Obstacle;
  9. import model.Shell;
  10. import model.ShellType;
  11. import model.Tank;
  12. import model.TankType;
  13. import model.World;
  14.  
  15. public final class MyStrategy implements Strategy {
  16.     private static enum Bound {
  17.         bottom, left, none, right, top
  18.     }
  19.  
  20.     private static enum DriveSE {
  21.         ds_dodge_bomb, ds_drive_bonus, ds_drive_closer, ds_drive_corner, ds_drive_far, ds_drive_strafe, ds_help_rotate_turret, ds_hiding, ds_stick_leader, ds_hunting, ds_resurrect, ds_rotate_to_enemy, ds_stand, ds_died
  22.     }
  23.  
  24.     private static enum helping {
  25.         assist_me_please, no_thanks, resurrect_me_please
  26.     }
  27.  
  28.     private static enum WhyTarget {
  29.         target_me_in_closer_range, help_assist, low_hp, closer_range, target_me, closer_visible, lower_hp, assist_leader, no_target, turned_to_me, last
  30.     }
  31.  
  32.     private static final class Point {
  33.         public double x, y;
  34.     }
  35.  
  36.     private static enum role {
  37.         leader, unit
  38.     }
  39.  
  40.     private static enum Rotate {
  41.         left, none, right
  42.     }
  43.  
  44.     private static final class TankCoords {
  45.         public double Vx, Vy, sinA, cosA, X, Y, H, W, A, Xl, Yl, Xlb, Ylb, Xlf,
  46.                 Ylf, Xb, Yb, Xf, Yf, Xrb, Yrb, Xr, Yr, Xrf, Yrf;
  47.  
  48.         /*
  49.          * lb==l===lf tank! ||======|| b===0====f ==> ||======|| rb==r===rf
  50.          */
  51.         TankCoords(model.Unit tank) {
  52.             X = tank.getX();
  53.             Y = tank.getY();
  54.             H = tank.getHeight();
  55.             W = tank.getWidth();
  56.             A = tank.getAngle();
  57.             sinA = Math.sin(A);
  58.             cosA = Math.cos(A);
  59.             double prjWx = (W / 2) * cosA;
  60.             double prjWy = (W / 2) * sinA;
  61.             double prjHx = (H / 2) * sinA;
  62.             double prjHy = (H / 2) * cosA;
  63.             Xf = X + prjWx;
  64.             Yf = Y + prjWy;
  65.             Xl = X + prjHx;
  66.             Yl = Y - prjHy;
  67.             Xb = X - prjWx;
  68.             Yb = Y - prjWy;
  69.             Xr = X - prjHx;
  70.             Yr = Y + prjHy;
  71.             Xrf = Xf + (Xr - X);
  72.             Yrf = Yf + (Yr - Y);
  73.             Xlf = Xf + (Xl - X);
  74.             Ylf = Yf + (Yl - Y);
  75.             Xlb = Xb + (Xl - X);
  76.             Ylb = Yb + (Yl - Y);
  77.             Xrb = Xb + (Xr - X);
  78.             Yrb = Yb + (Yr - Y);
  79.             Vx = tank.getSpeedX();
  80.             Vy = tank.getSpeedY();
  81.         }
  82.  
  83.         TankCoords(model.Unit tank, double x, double y) {
  84.             X = x;
  85.             Y = y;
  86.             H = tank.getHeight();
  87.             W = tank.getWidth();
  88.             A = tank.getAngle();
  89.             sinA = Math.sin(A);
  90.             cosA = Math.cos(A);
  91.             double prjWx = (W / 2) * cosA;
  92.             double prjWy = (W / 2) * sinA;
  93.             double prjHx = (H / 2) * sinA;
  94.             double prjHy = (H / 2) * cosA;
  95.             Xf = X + prjWx;
  96.             Yf = Y + prjWy;
  97.             Xl = X + prjHx;
  98.             Yl = Y - prjHy;
  99.             Xb = X - prjWx;
  100.             Yb = Y - prjWy;
  101.             Xr = X - prjHx;
  102.             Yr = Y + prjHy;
  103.             Xrf = Xf + (Xr - X);
  104.             Yrf = Yf + (Yr - Y);
  105.             Xlf = Xf + (Xl - X);
  106.             Ylf = Yf + (Yl - Y);
  107.             Xlb = Xb + (Xl - X);
  108.             Ylb = Yb + (Yl - Y);
  109.             Xrb = Xb + (Xr - X);
  110.             Yrb = Yb + (Yr - Y);
  111.             Vx = tank.getSpeedX();
  112.             Vy = tank.getSpeedY();
  113.         }
  114.  
  115.         public double getVelocityAbs() {
  116.             return Math.sqrt(Vx * Vx + Vy * Vy);
  117.         }
  118.  
  119.         public double getVelocityForward() {
  120.             return getVelocityAbs()
  121.                     * Math.cos(getVectorAngle(Vx, cosA, Vy, sinA));
  122.         }
  123.     }
  124.  
  125.     public static int           _can_shoot_time                              = 0;
  126.     public static long[]        _enemy;
  127.     public static long[]        _ids;
  128.     public static int           _team_healthy_tanks                          = 0,_team_premium_count=0;
  129.     public static boolean       _team_ready_for_shoot                        = false;
  130.     public static int           _team_shoots_count                           = 0;
  131.     public static long          _leader_current_enemy_id                     = -1;
  132.     public static boolean       _team_rush                                   = false;
  133.     public static boolean       _team_need_retarget                          = true;
  134.  
  135.     private static final double AIMING__ACCURACY                             = 3;                               // part
  136.                                                                                                                  // enemy
  137.                                                                                                                  // tank
  138.                                                                                                                  // 1/3
  139.                                                                                                                  // more
  140.                                                                                                                  // ->
  141.                                                                                                                  // better
  142.     private static final double AIMING__PREMIUM_EXCEED_LIMIT                 = 2;
  143.     private static final double AIMING__PREMIUM_FIRE_DISTANCE                = 500;
  144.     private static final double AIMING__PREMIUM_FIRE_DISTANCE_MORE           = 900;
  145.     private static final double AIMING__STOP_DRIVE_TO_SHOOT_TIME             = 40;
  146.     private static final double BONUS__AMMO_MAX_DIST_EXTRA_SUPER_LOW_HP      = 200;
  147.     private static final double BONUS__DRIVE_POINT_RADIUS                    = 60;
  148.     private static final double BONUS__HP_DIST_EXTRA_SUPER_LOW_HP            = 300;
  149.     private static final double BONUS__NEED_ARMOR_PRECENT                    = 0.65;
  150.     private static final double BONUS__NEED_ARMOR_PRECENT_EXTRA              = 0.4;
  151.     private static final double BONUS__NEED_ARMOR_PRECENT_EXTRA_SUPER        = 0.2;
  152.     private static final double BONUS__NEED_HEALTH_PRECENT                   = 0.65;
  153.     private static final double BONUS__NEED_HEALTH_PRECENT_EXTRA             = 0.4;
  154.     private static final double BONUS__NEED_HEALTH_PRECENT_EXTRA_SUPER       = 0.2;
  155.     private static final double BULLET__AERO_COEFF_PREMIUM                   = 0.30;
  156.     private static final double BULLET__AERO_COEFF_REGULAR                   = 0.18;
  157.     private static final double BULLET__PREMIUM_DAMAGE                       = 40;
  158.     private static final double BULLET__REGULAR_DAMAGE                       = 25;
  159.     private static final double BULLET__SPEED                                = 23;
  160.     private static final double CONFIG__MY_MAX_ARM                           = 200;
  161.     private static final double CONFIG__MY_MAX_HP                            = 100;
  162.     private static final double CONFIG__MY_WIDTH                             = 90;
  163.     private static final double CONFIG__WORLD_BOUND_WIDTH                    = 5;
  164.     private static final double CONFIG__WORLD_HEIGHT                         = 800;
  165.     private static final double CONFIG__WORLD_WIDTH                          = 1280;
  166.     private static final double CONFIG__BULLET_SIZE                          = 11;
  167.     private static final double CORNER__BOUNDS_WIDTH                         = 45;
  168.     private static final double CORNER__DRIVE_POINT_RADIUS                   = 60;
  169.     private static final double CORNER__MAX_ALLOWED_DISTANCE_TO_BONUS        = 400;
  170.  
  171.     private static final double CORNER__PLAYER_RADAR_RADIUS                  = 700;
  172.     private static final double CORNER__POINT_DIST                           = 80;
  173.     private static final double CORNER__POINT_RADIUS                         = 500;
  174.     private static final int    corners_count                                = 14;                              // dont
  175.                                                                                                                  // change
  176.                                                                                                                  // this
  177.     private static final double DODGE__ACTIVE_DEFENCE_FROM_BOMB_MAX_DISTANCE = 400;
  178.     private static final double DODGE__ACTIVE_DEFENCE_FROM_BOMB_MIN_DISTANCE = 45;
  179.     private static final double DODGE__ADJUST_DRIVE_BACK_COEFF               = 0.75;
  180.     private static final double DODGE__ADJUST_SMALL_VELOCITY                 = 1;
  181.     private static final double DODGE__ADJUST_VELOCITY_COEFF                 = 15;
  182.     private static final double DODGE__MAX_DISTANCE_TO_AVOID_BY_TURNING      = 300;
  183.     private static final double DODGE__MAX_DV_DT_FORWARD                     = 0.15;
  184.     private static final double DODGE__MAX_DV_DT_zBACK                       = -0.75
  185.                                                                                      * DODGE__MAX_DV_DT_FORWARD;
  186.     private static final double DODGE__MIN_ESCAPE_ANGLE                      = PI / 5;
  187.     private static final double DODGE__RICOCHETE_ANGLE                       = PI / 6.2;
  188.     private static final double DODGE__TURN_ANGLE_DELTA                      = 0.5 * PI / 180;
  189.     private static final double DODGE__TURN_DODGE_ANGLE_ACCURACY_DELTA       = PI / 4000;                       // radian
  190.     private static final double DRIVE__ADJUST_MAX_DISTANCE                   = 3000;
  191.     private static final double DRIVE__ADJUST_MIN_DISTANCE                   = 100;
  192.     private static final double DRIVE__ADJUST_TURN_DIFFERENCE_MAX            = 0.75;
  193.     private static final double DRIVE__MAX_DISTANCE_RIDE_ANGLE_INCREASED     = 200;
  194.     private static final double DRIVE__MAX_RIDE_ANGLE                        = PI / 4;
  195.     private static final double DRIVE__MIN_DISTANCE_RIDE_ANGLE_INCREASED     = 100;
  196.     private static final double DRIVE__PATH_POINT_ACCURACY                   = 5;
  197.     private static final double HIDING__DRIVE_POINT_RADIUS                   = 70;
  198.     private static final double HUNT__DRIVE_POINT_RADIUS                     = 70;
  199.     private static final double RANGING__CLOSER_RANGE                        = 250;
  200.     private static final double RANGING__DRIVE_POINT_RADIUS                  = 70;
  201.  
  202.     private static final int    TACTIC__MAX_ENEMIES_TO_DRIVE                 = 2;
  203.     private static final double TEAM__CLOSER_ENEMY_ASSIST_RANGE              = 400;
  204.     private static final double TEAM__HELP_RESURRECT_DISTANCE_TO_BONUS       = 100;
  205.     private static final double TEAM__HELP_RESURRECT_DISTANCE_TO_DEAD_MAX    = 200;
  206.     private static final double TEAM__SHOOT_TIME_DELTA                       = 5;
  207.     public static helping[]     team_help;
  208.     public static role[]        team_roles;
  209.     public static boolean[]     team_shoot_ready;
  210.     public static DriveSE[]     team_state;
  211.     public static WhyTarget[]   team_why_targets;
  212.     private static final double TURNING__ANGLE_ACCURACY                      = 15 * PI / 180;                   // 5
  213.                                                                                                                  // deg
  214.     private static final double TURNING__CLOSER_MAX_DISTANCE                 = 500;
  215.     private static final double TURNING__MIN_TURN_TO_ENEMY_ANGLE             = PI / 5;
  216.     private static final double TURNING__MIN_TURN_TO_ENEMY_ANGLE_ON_DIST     = PI / 2.01;
  217.     public static String        team_1_name                                  = "",
  218.             team_2_name = "";
  219.     public static int           team_1_alive_count                           = 0,
  220.             team_2_alive_count = 0, teams_count = 0,enemy_premium_count=0;
  221.     public static int           _team_leader_corner                          = -1;
  222.     public static double        enemy_sum_hp_arm                             = 0;
  223.  
  224.     private static final double driveCoeff(final double d) {
  225.         if (d <= DRIVE__ADJUST_MIN_DISTANCE)
  226.             return -1;
  227.         else
  228.             return -1 + (d - DRIVE__ADJUST_MIN_DISTANCE) * 2
  229.                     / (DRIVE__ADJUST_MAX_DISTANCE - DRIVE__ADJUST_MIN_DISTANCE);
  230.     }
  231.  
  232.     private static final Bound getBound(final double X, final double Y,
  233.             final double R) {
  234.         if (X < CONFIG__WORLD_BOUND_WIDTH + R)
  235.             return Bound.left;
  236.         else
  237.             if (X > CONFIG__WORLD_WIDTH - CONFIG__WORLD_BOUND_WIDTH - R)
  238.                 return Bound.right;
  239.             else
  240.                 if (Y < CONFIG__WORLD_BOUND_WIDTH + R)
  241.                     return Bound.bottom;
  242.                 else
  243.                     if (Y > CONFIG__WORLD_HEIGHT - CONFIG__WORLD_BOUND_WIDTH
  244.                             - R)
  245.                         return Bound.top;
  246.                     else
  247.                         return Bound.none;
  248.     }
  249.  
  250.     private static final Tank getClosestTankToPoint(Tank[] tanks,
  251.             final double Px, final double Py, final double Radius) {
  252.         int tc = tanks.length;
  253.         double min_radius = Radius;
  254.         int selected_tank = tc;
  255.         for (int i = 0; i < tc; i++) {
  256.             Tank tank = tanks[i];
  257.             if (tank.getCrewHealth() == 0 || tank.getHullDurability() == 0)
  258.                 continue;
  259.             double d = tank.getDistanceTo(Px, Py);
  260.             if (d < min_radius) {
  261.                 d = min_radius;
  262.                 selected_tank = i;
  263.             }
  264.         }
  265.         if (selected_tank < tc)
  266.             return tanks[selected_tank];
  267.         else
  268.             return null;
  269.     }
  270.  
  271.     private static final double getDistancePointToLine(final double PLx,
  272.             final double PLy, final double VLx, final double VLy,
  273.             final double Px, final double Py) {
  274.         double VPLPx = Px - PLx;
  275.         double VPLPy = Py - PLy;
  276.         double D = Math.sqrt(VPLPy * VPLPy + VPLPx * VPLPx);
  277.         double fi = getVectorAngle(VLx, VPLPx, VLy, VPLPy);
  278.         return Math.abs(D * Math.sin(fi));
  279.     }
  280.  
  281.     private static final double getMaxAngleOfUnitOnDist(final double myX,
  282.             final double myY, model.Unit target, final double X, final double Y) {
  283.         double Xb, Yb, Xa, Ya, Xc, Yc, Xd, Yd;
  284.         double a1, a2, a3, a4;
  285.         TankCoords tank_coords = new TankCoords(target, X, Y);
  286.         Xa = tank_coords.Xlf;
  287.         Ya = tank_coords.Ylf;
  288.         Xb = tank_coords.Xrf;
  289.         Yb = tank_coords.Yrf;
  290.         Xd = tank_coords.Xrb;
  291.         Yd = tank_coords.Yrb;
  292.         Xc = tank_coords.Xlb;
  293.         Yc = tank_coords.Ylb;// target corners
  294.         double vx = X - myX;
  295.         double vy = Y - myY;
  296.         double vxa = Xa - myX;
  297.         double vya = Ya - myY;
  298.         double vxb = Xb - myX;
  299.         double vyb = Yb - myY;
  300.         double vxc = Xc - myX;
  301.         double vyc = Yc - myY;
  302.         double vxd = Xd - myX;
  303.         double vyd = Yd - myY;
  304.  
  305.         double ABSva = Math.sqrt(vxa * vxa + vya * vya);
  306.         double ABSvb = Math.sqrt(vxb * vxb + vyb * vyb);
  307.         double ABSvc = Math.sqrt(vxc * vxc + vyc * vyc);
  308.         double ABSvd = Math.sqrt(vxd * vxd + vyd * vyd);
  309.         double ABSv = Math.sqrt(vx * vx + vy * vy);
  310.         double cosa1 = (vx * vxa + vy * vya) / (ABSv * ABSva);
  311.         if (cosa1 > 1 || cosa1 < -1)
  312.             cosa1 = 1;
  313.         a1 = Math.acos(cosa1);
  314.         double cosa2 = (vx * vxb + vy * vyb) / (ABSv * ABSvb);
  315.         if (cosa2 > 1 || cosa2 < -1)
  316.             cosa2 = 1;
  317.         a2 = Math.acos(cosa2);
  318.         double cosa3 = (vx * vxc + vy * vyc) / (ABSv * ABSvc);
  319.         if (cosa3 > 1 || cosa3 < -1)
  320.             cosa3 = 1;
  321.         a3 = Math.acos(cosa3);
  322.         double cosa4 = (vx * vxd + vy * vyd) / (ABSv * ABSvd);
  323.         if (cosa4 > 1 || cosa4 < -1)
  324.             cosa4 = 1;
  325.         a4 = Math.acos(cosa4);
  326.  
  327.         return Math.max(Math.max(a1, a2), Math.max(a3, a4));
  328.     }
  329.  
  330.     private static final double getObjAngleOnDistance(final double dist,
  331.             final double objH) {
  332.         return 2 * Math.atan((objH / 2) / dist);
  333.     }
  334.  
  335.     /**
  336.      * 0..PI/2 from tank vector to line <0 if rotate right >0 if rotate left
  337.      *
  338.      * @param tank
  339.      * @param VLx
  340.      * @param VLy
  341.      * @return
  342.      */
  343.     private static final double getTankAngleToLine(final Tank tank,
  344.             final double VLx, final double VLy) {
  345.         /*
  346.          * ^ VRL | bc==c===ac <---TANK! ||======|| b===0====a ==> -->VT
  347.          * ||======|| bd==d===ad
  348.          */
  349.         double A = tank.getAngle();
  350.         double VTx = Math.cos(A);
  351.         double VTy = Math.sin(A);
  352.         double VRLx = VTy;
  353.         double VRLy = -VTx;// f2->f1
  354.         double fiT = -PI / 2 + getVectorAngle(VRLx, VLx, VRLy, VLy);
  355.         double fiRL = -PI / 2 + getVectorAngle(VTx, VLx, VTy, VLy);
  356.         if (fiRL * fiT < 0) {// check
  357.             return -Math.abs(fiT);
  358.         } else {
  359.             return +Math.abs(fiT);
  360.         }
  361.     }
  362.  
  363.     private static final Rotate getTankOnBoundRotation(final double X,
  364.             final double Y, final double R, final Tank t) {
  365.         Bound b = getBound(X, Y, R);
  366.         double VLx = 0, VLy = 0;
  367.         switch (b) {
  368.         case none:
  369.             return Rotate.none;
  370.  
  371.         case bottom:
  372.         case top:
  373.             VLx = 1;
  374.             VLy = 0;
  375.         break;
  376.         case left:
  377.         case right:
  378.             VLx = 0;
  379.             VLy = 1;
  380.         }
  381.         double a = getTankAngleToLine(t, VLx, VLy);
  382.         if (a < 0)
  383.             return Rotate.right;
  384.         else
  385.             return Rotate.left;
  386.     }
  387.  
  388.     private static final double getVectorAngle(final double vx1,
  389.             final double vx2, final double vy1, final double vy2) {
  390.         double cosa = (vx1 * vx2 + vy1 * vy2)
  391.                 / (Math.sqrt(vx1 * vx1 + vy1 * vy1) * Math.sqrt(vx2 * vx2 + vy2
  392.                         * vy2));
  393.         if (cosa > 1 || cosa < -1)
  394.             cosa = 1;
  395.         return Math.acos(cosa);
  396.     }
  397.  
  398.     /**
  399.      * <0 rotate left from v to v2
  400.      *
  401.      * @param vx
  402.      *            first vector x
  403.      * @param vx2
  404.      *            second vector x
  405.      * @param vy
  406.      *            first vector y
  407.      * @param vy2
  408.      *            second vector y
  409.      * @return angle from v to v2
  410.      */
  411.     private static final double getVectorAngleWithSign(final double vx,
  412.             final double vx2, final double vy, final double vy2) {
  413.         double cosa = (vx * vx2 + vy * vy2)
  414.                 / (Math.sqrt(vx * vx + vy * vy) * Math.sqrt(vx2 * vx2 + vy2
  415.                         * vy2));
  416.         if (cosa > 1 || cosa < -1)
  417.             cosa = 1;
  418.         double fi = Math.acos(cosa);
  419.         double sgn = Math.signum(vx * vy2 - vx2 * vy);
  420.         return fi * sgn;
  421.     }
  422.  
  423.     private static final boolean isBombForTank(final model.Unit me,
  424.             final Shell bomb, final double X, final double Y) {
  425.         double bombX = bomb.getX();
  426.         double bombY = bomb.getY();
  427.         double BTx = X - bombX;
  428.         double BTy = Y - bombY;
  429.         double Bvx = bomb.getSpeedX();
  430.         double Bvy = bomb.getSpeedY();
  431.         double absBT = Math.sqrt(BTx * BTx + BTy * BTy);
  432.         double absBv = Math.sqrt(Bvx * Bvx + Bvy * Bvy);
  433.         double cosa = (BTx * Bvx + BTy * Bvy) / (absBT * absBv);
  434.         if (cosa > 1 || cosa < -1)
  435.             cosa = 1;
  436.         double fi = Math.acos(cosa);
  437.         double dist = me.getDistanceTo(bomb);
  438.         if (fi >= PI / 2 && dist > 60)
  439.             return false;
  440.         /*
  441.          * bc==c===ac tank! ||======|| b===0====a ==> ||======|| bd==d===ad
  442.          */
  443.         TankCoords tc = new TankCoords(me, X, Y);
  444.         double Badx = tc.Xrf - bombX;
  445.         double Bady = tc.Yrf - bombY;
  446.         double Bbcx = tc.Xlb - bombX;
  447.         double Bbcy = tc.Ylb - bombY;
  448.         double Bacx = tc.Xlf - bombX;
  449.         double Bacy = tc.Ylf - bombY;
  450.         double Bbdx = tc.Xrb - bombX;
  451.         double Bbdy = tc.Yrb - bombY;
  452.         double absBad = Math.sqrt(Badx * Badx + Bady * Bady);
  453.         double absBbc = Math.sqrt(Bbcx * Bbcx + Bbcy * Bbcy);
  454.         double absBac = Math.sqrt(Bacx * Bacx + Bacy * Bacy);
  455.         double absBbd = Math.sqrt(Bbdx * Bbdx + Bbdy * Bbdy);
  456.         double cosa1 = (BTx * Badx + BTy * Bady) / (absBT * absBad);
  457.         if (cosa1 > 1 || cosa1 < -1)
  458.             cosa1 = 1;
  459.         double a1 = Math.acos(cosa1);
  460.         double cosa2 = (BTx * Bbcx + BTy * Bbcy) / (absBT * absBbc);
  461.         if (cosa2 > 1 || cosa2 < -1)
  462.             cosa2 = 1;
  463.         double a2 = Math.acos(cosa2);
  464.         double cosa3 = (BTx * Bacx + BTy * Bacy) / (absBT * absBac);
  465.         if (cosa3 > 1 || cosa3 < -1)
  466.             cosa3 = 1;
  467.         double a3 = Math.acos(cosa3);
  468.         double cosa4 = (BTx * Bbdx + BTy * Bbdy) / (absBT * absBbd);
  469.         if (cosa4 > 1 || cosa4 < -1)
  470.             cosa4 = 1;
  471.         double a4 = Math.acos(cosa4);
  472.         double maxa = Math.max(Math.max(a1, a2), Math.max(a3, a4));
  473.         if (maxa >= PI / 2 && dist > 60)
  474.             return false;
  475.         double bullet_angle = getObjAngleOnDistance(dist, bomb.getWidth());
  476.         boolean result = fi <= maxa + bullet_angle;
  477.         return result;
  478.     }
  479.  
  480.     private static final boolean isClearOfTanksSector(Tank me, final double X,
  481.             final double Y, World world, final double Radius) {
  482.         if (isOutWorldPointRadius(X, Y, Radius / 2))
  483.             return false;
  484.         Tank[] tanks = world.getTanks();
  485.         int tc = tanks.length;
  486.         for (int i = 0; i < tc; i++) {
  487.             if (isSameTank(tanks[i], me))
  488.                 continue;
  489.             double tdist = tanks[i].getDistanceTo(X, Y);
  490.             if (tdist < tanks[i].getWidth() / 2 + Radius) {
  491.                 return false;
  492.             }
  493.         }
  494.         Obstacle[] obst = world.getObstacles();
  495.         int oc = obst.length;
  496.         for (int i = 0; i < oc; i++) {
  497.             double tdist = obst[i].getDistanceTo(X, Y);
  498.             if (tdist < obst[i].getWidth() / 2 + Radius) {
  499.                 return false;
  500.             }
  501.         }
  502.         return true;
  503.     }
  504.  
  505.     private static final boolean isClearToDriveSector(final double X,
  506.             final double Y, World world) {
  507.         if (isOutWorldPointRadius(X, Y, 0))
  508.             return false;
  509.         Tank[] tanks = world.getTanks();
  510.         int tc = tanks.length;
  511.         for (int i = 0; i < tc; i++) {
  512.  
  513.             double tdist = tanks[i].getDistanceTo(X, Y);
  514.             if (tdist < 15)
  515.                 continue;
  516.             if (tdist < tanks[i].getWidth() / 2) {
  517.                 return false;
  518.             }
  519.         }
  520.         Obstacle[] obst = world.getObstacles();
  521.         int oc = obst.length;
  522.         for (int i = 0; i < oc; i++) {
  523.             double tdist = obst[i].getDistanceTo(X, Y);
  524.             if (tdist < obst[i].getWidth() / 2) {
  525.                 return false;
  526.             }
  527.         }
  528.         return true;
  529.     }
  530.  
  531.     private static final boolean isOnCorner(final double X, final double Y) {
  532.         if (X < CORNER__BOUNDS_WIDTH
  533.                 || X > CONFIG__WORLD_WIDTH - CORNER__BOUNDS_WIDTH
  534.                 || Y < CORNER__BOUNDS_WIDTH
  535.                 || Y > CONFIG__WORLD_HEIGHT - CORNER__BOUNDS_WIDTH)
  536.             return true;
  537.         return false;
  538.     }
  539.  
  540.     private static final boolean isOutWorldPointRadius(final double X,
  541.             final double Y, final double R) {
  542.         if (X < CONFIG__WORLD_BOUND_WIDTH + R
  543.                 || X > CONFIG__WORLD_WIDTH - CONFIG__WORLD_BOUND_WIDTH - R
  544.                 || Y < CONFIG__WORLD_BOUND_WIDTH + R
  545.                 || Y > CONFIG__WORLD_HEIGHT - CONFIG__WORLD_BOUND_WIDTH - R)
  546.             return true;
  547.         else
  548.             return false;
  549.     }
  550.  
  551.     private static final boolean isSameTank(Tank tank1, Tank tank2) {
  552.         try {
  553.             return tank1.getId() == tank2.getId();
  554.         } catch (Exception e) {
  555.             return false;
  556.         }
  557.     }
  558.  
  559.     private static final boolean wayIsClear(final double dist, final double pX,
  560.             final double pY, final double myX, final double myY, World world) {
  561.         if (dist < 45)
  562.             return true;
  563.         double pvx = pX - myX, pvy = pY - myY;
  564.         double a_target = getObjAngleOnDistance(dist, 110);
  565.         Tank[] tanks = world.getTanks();
  566.         int tc = tanks.length;
  567.         for (int i = 0; i < tc; i++) {
  568.             Tank obj = tanks[i];
  569.             double odist = obj.getDistanceTo(myX, myY);
  570.             if ((odist + 15 >= dist) || (odist < 15))
  571.                 continue;
  572.             double oX = obj.getX() + obj.getSpeedX();
  573.             double oY = obj.getY() + obj.getSpeedY();
  574.             double ovx = oX - myX;
  575.             double ovy = oY - myY;
  576.             double a_OMP = getVectorAngle(pvx, ovx, pvy, ovy);
  577.             double a_obj = getMaxAngleOfUnitOnDist(myX, myY, obj, obj.getX(),
  578.                     obj.getY());
  579.             if (a_OMP <= a_obj + a_target) {
  580.  
  581.                 return false;
  582.             }
  583.         }
  584.         Bonus[] gifts = world.getBonuses();
  585.         tc = gifts.length;
  586.         for (int i = 0; i < tc; i++) {
  587.             Bonus obj = gifts[i];
  588.             double odist = obj.getDistanceTo(myX, myY);
  589.             if ((odist + 15 >= dist) || (odist < 15))
  590.                 continue;
  591.             double oX = obj.getX() + obj.getSpeedX();
  592.             double oY = obj.getY() + obj.getSpeedY();
  593.             double ovx = oX - myX;
  594.             double ovy = oY - myY;
  595.             double a_OMP = getVectorAngle(pvx, ovx, pvy, ovy);
  596.             double a_obj = getMaxAngleOfUnitOnDist(myX, myY, obj, obj.getX(),
  597.                     obj.getY());
  598.             if (a_OMP <= a_obj + a_target) {
  599.  
  600.                 return false;
  601.             }
  602.         }
  603.         Obstacle[] obst = world.getObstacles();
  604.         int oc = obst.length;
  605.         for (int i = 0; i < oc; i++) {
  606.             Obstacle obj = obst[i];
  607.             double odist = obj.getDistanceTo(myX, myY);
  608.             if ((odist + 15 >= dist) || (odist < 15))
  609.                 continue;
  610.             double oX = obj.getX() + obj.getSpeedX();
  611.             double oY = obj.getY() + obj.getSpeedY();
  612.             double ovx = oX - myX;
  613.             double ovy = oY - myY;
  614.             double a_OMP = getVectorAngle(pvx, ovx, pvy, ovy);
  615.             double a_obj = getMaxAngleOfUnitOnDist(myX, myY, obj, obj.getX(),
  616.                     obj.getY());
  617.             if (a_OMP <= a_obj + a_target) {
  618.  
  619.                 return false;
  620.             }
  621.         }
  622.         return true;
  623.     }
  624.  
  625.     private static final boolean wayIsClearForShoot(final double dist,
  626.             final double pX, final double pY, final double myX,
  627.             final double myY, World world) {
  628.         if (dist < 30)
  629.             return true;
  630.         double pvx = pX - myX, pvy = pY - myY;
  631.  
  632.         Tank[] tanks = world.getTanks();
  633.         int tc = tanks.length;
  634.         for (int i = 0; i < tc; i++) {
  635.             Tank obj = tanks[i];
  636.             double odist = obj.getDistanceTo(myX, myY);
  637.             if ((odist + 15 >= dist) || (odist < 15))
  638.                 continue;
  639.             if (obj.getCrewHealth() > 0 && obj.getHullDurability() > 0
  640.                     && !obj.isTeammate())
  641.                 continue;
  642.             double oX = obj.getX() + obj.getSpeedX();
  643.             double oY = obj.getY() + obj.getSpeedY();
  644.             double ovx = oX - myX;
  645.             double ovy = oY - myY;
  646.             double a_OMP = getVectorAngle(pvx, ovx, pvy, ovy);
  647.             double a_obj = getMaxAngleOfUnitOnDist(myX, myY, obj, obj.getX(),
  648.                     obj.getY());
  649.             double a_bullet = getObjAngleOnDistance(odist, CONFIG__BULLET_SIZE);
  650.             if (a_bullet >= a_OMP - a_obj) {
  651.  
  652.                 return false;
  653.             }
  654.         }
  655.         Bonus[] gifts = world.getBonuses();
  656.         tc = gifts.length;
  657.         for (int i = 0; i < tc; i++) {
  658.             Bonus obj = gifts[i];
  659.             double odist = obj.getDistanceTo(myX, myY);
  660.             if ((odist + 15 >= dist) || (odist < 15))
  661.                 continue;
  662.             double oX = obj.getX() + obj.getSpeedX();
  663.             double oY = obj.getY() + obj.getSpeedY();
  664.             double ovx = oX - myX;
  665.             double ovy = oY - myY;
  666.             double a_OMP = getVectorAngle(pvx, ovx, pvy, ovy);
  667.             double a_obj = getMaxAngleOfUnitOnDist(myX, myY, obj, obj.getX(),
  668.                     obj.getY());
  669.             double a_bullet = getObjAngleOnDistance(odist, CONFIG__BULLET_SIZE);
  670.             if (a_bullet >= a_OMP - a_obj) {
  671.  
  672.                 return false;
  673.             }
  674.         }
  675.         Obstacle[] obst = world.getObstacles();
  676.         int oc = obst.length;
  677.         for (int i = 0; i < oc; i++) {
  678.             Obstacle obj = obst[i];
  679.             double odist = obj.getDistanceTo(myX, myY);
  680.             if ((odist + 15 >= dist) || (odist < 15))
  681.                 continue;
  682.             double oX = obj.getX() + obj.getSpeedX();
  683.             double oY = obj.getY() + obj.getSpeedY();
  684.             double ovx = oX - myX;
  685.             double ovy = oY - myY;
  686.             double a_OMP = getVectorAngle(pvx, ovx, pvy, ovy);
  687.             double a_obj = getMaxAngleOfUnitOnDist(myX, myY, obj, obj.getX(),
  688.                     obj.getY());
  689.             double a_bullet = getObjAngleOnDistance(odist, CONFIG__BULLET_SIZE);
  690.             if (a_bullet >= a_OMP - a_obj) {
  691.  
  692.                 return false;
  693.             }
  694.         }
  695.         return true;
  696.     }
  697.  
  698.     private static final boolean wayIsClearForShootObst(final double dist,
  699.             final double pX, final double pY, final double myX,
  700.             final double myY, World world) {
  701.         if (dist < 30)
  702.             return true;
  703.         double pvx = pX - myX, pvy = pY - myY;
  704.  
  705.         Obstacle[] obst = world.getObstacles();
  706.         int oc = obst.length;
  707.         for (int i = 0; i < oc; i++) {
  708.             Obstacle obj = obst[i];
  709.             double odist = obj.getDistanceTo(myX, myY);
  710.             if ((odist + 15 >= dist) || (odist < 15))
  711.                 continue;
  712.             double oX = obj.getX() + obj.getSpeedX();
  713.             double oY = obj.getY() + obj.getSpeedY();
  714.             double ovx = oX - myX;
  715.             double ovy = oY - myY;
  716.             double a_OMP = getVectorAngle(pvx, ovx, pvy, ovy);
  717.             double a_obj = getMaxAngleOfUnitOnDist(myX, myY, obj, obj.getX(),
  718.                     obj.getY());
  719.             double a_bullet = getObjAngleOnDistance(odist, CONFIG__BULLET_SIZE);
  720.             if (a_bullet >= a_OMP - a_obj) {
  721.  
  722.                 return false;
  723.             }
  724.         }
  725.         return true;
  726.     }
  727.  
  728.     private static final boolean wayIsClearForTargeting(model.Unit u_target,
  729.             final double dist, final double pX, final double pY,
  730.             final double myX, final double myY, World world) {
  731.         if (dist < 30)
  732.             return true;
  733.         double pvx = pX - myX, pvy = pY - myY;
  734.  
  735.         Tank[] tanks = world.getTanks();
  736.         int tc = tanks.length;
  737.         for (int i = 0; i < tc; i++) {
  738.             Tank obj = tanks[i];
  739.             double odist = obj.getDistanceTo(myX, myY);
  740.             if ((odist + 15 >= dist) || (odist < 15))
  741.                 continue;
  742.             if (obj.getCrewHealth() == 0 || obj.getHullDurability() == 0)
  743.                 continue;
  744.             double oX = obj.getX() + obj.getSpeedX();
  745.             double oY = obj.getY() + obj.getSpeedY();
  746.             double ovx = oX - myX;
  747.             double ovy = oY - myY;
  748.             double a_OMP = getVectorAngle(pvx, ovx, pvy, ovy);
  749.             double a_obj = getMaxAngleOfUnitOnDist(myX, myY, obj, obj.getX(),
  750.                     obj.getY());
  751.             double a_bullet = getObjAngleOnDistance(odist, CONFIG__BULLET_SIZE);
  752.             if (a_bullet >= a_OMP - a_obj) {
  753.  
  754.                 return false;
  755.             }
  756.         }
  757.         Obstacle[] obst = world.getObstacles();
  758.         int oc = obst.length;
  759.         for (int i = 0; i < oc; i++) {
  760.             Obstacle obj = obst[i];
  761.             double odist = obj.getDistanceTo(myX, myY);
  762.             if ((odist + 15 >= dist) || (odist < 15))
  763.                 continue;
  764.             double oX = obj.getX() + obj.getSpeedX();
  765.             double oY = obj.getY() + obj.getSpeedY();
  766.             double ovx = oX - myX;
  767.             double ovy = oY - myY;
  768.             double a_OMP = getVectorAngle(pvx, ovx, pvy, ovy);
  769.             double a_obj = getMaxAngleOfUnitOnDist(myX, myY, obj, obj.getX(),
  770.                     obj.getY());
  771.             double a_bullet = getObjAngleOnDistance(odist, CONFIG__BULLET_SIZE);
  772.             if (a_bullet >= a_OMP - a_obj) {
  773.  
  774.                 return false;
  775.             }
  776.         }
  777.         return true;
  778.     }
  779.  
  780.     private double  _corner_x                        = 0, _corner_y = 0;
  781.     private Point[] _corners                         = new Point[corners_count];
  782.     private double  _drive_target_H                  = 30;
  783.     private double  _dv_dt_x                         = 0, _dv_dt_y = 0;
  784.     private boolean _enemy_changed                   = true;
  785.     private long    _last_enemy_id                   = -1;
  786.     private int     _enemy_healthy_tanks             = 0;
  787.     private double  _enemy_last_v_x                  = 0, _enemy_last_v_y = 0;
  788.  
  789.     private double  _hp                              = 0, _armor = 0,
  790.             _premium_count = 0;
  791.     private int     _i;
  792.     private boolean _i_can_shoot                     = false;
  793.     public DriveSE  _last_drive_state;
  794.     private double  _last_v_x                        = 0, _last_v_y = 0;
  795.     private double  _next_x                          = 0, _next_y = 0;
  796.     private Point[] _path                            = new Point[4];
  797.     private int     _path_current                    = 0;
  798.     private double  _tik                             = 0;
  799.     private double  _tik_strafe                      = 0;
  800.     private double  _x                               = 0, _y = 0;
  801.     private double  _vx                              = 0, _vy = 0;
  802.     // private double eNX=0,eNY=0,bft=0;//TODO
  803.     private boolean _leader_enemy_teams_counted      = false;
  804.     private boolean b_i_am_do_manevr                 = false;
  805.     private boolean b_i_need_ammo                    = false;
  806.     private boolean b_i_need_armor                   = false;
  807.     private boolean b_i_need_armor_extra             = false;
  808.     private boolean b_i_need_armor_extra_super       = false;
  809.     private boolean b_i_need_health                  = false;
  810.     private boolean b_i_need_health_extra            = false;
  811.     private boolean b_i_need_health_extra_super      = false;
  812.     private boolean b_im_avoiding_bomb               = false;
  813.     private boolean b_im_drive_to_corner             = false;
  814.     @SuppressWarnings("unused")
  815.     private boolean b_im_drive_to_path_point         = false;
  816.     private boolean b_im_escape_for_range            = false;
  817.     private boolean b_im_goto_bonus                  = false;
  818.     private boolean b_im_goto_min_dist               = false;
  819.     private boolean b_im_hiding                      = false;
  820.     private boolean b_im_hunting;
  821.     private boolean b_im_turn_to_enemy               = false;
  822.     private boolean b_im_turning_to_help_turn_turret = false;
  823.     private boolean b_it_is_a_first_tick             = true;
  824.  
  825.     private boolean b_it_is_a_time_to_drive          = false;
  826.  
  827.     private void aiDefineBonusPrioritets() {
  828.         b_i_need_health = CONFIG__MY_MAX_HP * BONUS__NEED_HEALTH_PRECENT > _hp;
  829.         b_i_need_health_extra = CONFIG__MY_MAX_HP
  830.                 * BONUS__NEED_HEALTH_PRECENT_EXTRA > _hp;
  831.         b_i_need_health_extra_super = CONFIG__MY_MAX_HP
  832.                 * BONUS__NEED_HEALTH_PRECENT_EXTRA_SUPER > _hp;
  833.         b_i_need_armor = CONFIG__MY_MAX_ARM * BONUS__NEED_ARMOR_PRECENT > _armor;
  834.         b_i_need_armor_extra = CONFIG__MY_MAX_ARM
  835.                 * BONUS__NEED_ARMOR_PRECENT_EXTRA > _armor;
  836.         b_i_need_armor_extra_super = CONFIG__MY_MAX_ARM
  837.                 * BONUS__NEED_ARMOR_PRECENT_EXTRA_SUPER > _armor;
  838.         b_i_need_ammo = _premium_count < 1;
  839.     }
  840.  
  841.     private boolean aiDodgeBomb(Tank self, World world, Move move) {
  842.         boolean im_do_avoid = false;
  843.  
  844.         Shell killer_bomba = getBulletFlyToTank(world, self);
  845.         if (killer_bomba != null) {
  846.             double distance_to_bomb = self.getDistanceTo(killer_bomba);
  847.             doDodge(killer_bomba, self, move, world);// DODGE!
  848.             im_do_avoid = true;
  849.             MyStrategy.team_state[_i] = DriveSE.ds_dodge_bomb;
  850.             /*
  851.              * dont change current enemy while dodge! but... wtf!
  852.              */
  853.  
  854.             if (distance_to_bomb < DODGE__ACTIVE_DEFENCE_FROM_BOMB_MAX_DISTANCE) {
  855.  
  856.                 double bombNextX = killer_bomba.getX()
  857.                         + killer_bomba.getSpeedX();
  858.                 double bombNextY = killer_bomba.getY()
  859.                         + killer_bomba.getSpeedY();
  860.                 if ((self.getRemainingReloadingTime() == 0)
  861.                         && distance_to_bomb > DODGE__ACTIVE_DEFENCE_FROM_BOMB_MIN_DISTANCE
  862.                         && (Math.abs(self
  863.                                 .getTurretAngleTo(bombNextX, bombNextY)) < getObjAngleOnDistance(
  864.                                 distance_to_bomb, killer_bomba.getHeight()))
  865.                         && wayIsClearForShoot(distance_to_bomb,
  866.                                 killer_bomba.getX(), killer_bomba.getY(), _x,
  867.                                 _y, world)
  868.  
  869.                 ) {
  870.                     move.setFireType(FireType.REGULAR);// kill BOMB!!!
  871.                 }
  872.             }
  873.         }
  874.  
  875.         return im_do_avoid;
  876.     }
  877.  
  878.     private void aiDoResurrectTeammate(World world, Tank me) {
  879.         boolean resurrect_success = false;
  880.         for (int k = 0; k < MyStrategy.team_help.length; k++) {
  881.             if (k == _i)
  882.                 continue;
  883.             if (MyStrategy.team_help[k] == helping.resurrect_me_please) {
  884.                 Tank[] tanks = world.getTanks();
  885.                 for (int j = 0; j < tanks.length; j++) {
  886.                     if (tanks[j].getId() == MyStrategy._ids[k]) {
  887.                         if (me.getDistanceTo(tanks[j]) > TEAM__HELP_RESURRECT_DISTANCE_TO_DEAD_MAX)
  888.                             continue;
  889.                         double died_x = tanks[j].getX();
  890.                         double died_y = tanks[j].getY();
  891.                         Bonus[] bonuses = world.getBonuses();
  892.                         for (int o = 0; o < bonuses.length; o++) {
  893.                             if (tanks[j].getCrewHealth() > 0
  894.                                     && bonuses[o].getType() == BonusType.MEDIKIT)
  895.                                 continue;
  896.                             if (tanks[j].getHullDurability() > 0
  897.                                     && bonuses[o].getType() == BonusType.REPAIR_KIT)
  898.                                 continue;
  899.                             if (bonuses[o].getType() == BonusType.AMMO_CRATE)
  900.                                 continue;
  901.                             double dist = tanks[j].getDistanceTo(bonuses[o]);
  902.                             if (dist < TEAM__HELP_RESURRECT_DISTANCE_TO_BONUS) {
  903.                                 // help
  904.                                 double bonus_x = bonuses[o].getX();
  905.                                 double bonus_y = bonuses[o].getY();
  906.                                 if (!wayIsClear(dist, bonus_x, bonus_y, died_x,
  907.                                         died_y, world))
  908.                                     continue;
  909.                                 double BTx = died_x - bonus_x;
  910.                                 double BTy = died_y - bonus_y;
  911.                                 double norma = Math.sqrt(BTx * BTx + BTy * BTy);
  912.                                 BTx = BTx * 100 / norma;
  913.                                 BTy = BTy * 100 / norma;
  914.                                 double Nx = died_x + BTx;
  915.                                 double Ny = died_y + BTy;
  916.                                 if (isClearOfTanksSector(me, Nx, Ny, world, 10)) {
  917.                                     _path[0].x = Nx;
  918.                                     _path[0].y = Ny;
  919.                                     if (me.getDistanceTo(Nx, Ny) < DRIVE__PATH_POINT_ACCURACY + 15) {
  920.                                         _path[0].x = bonus_x;// nneds angle
  921.                                         _path[0].y = bonus_y;
  922.                                     }
  923.                                     _drive_target_H = 15;
  924.                                     MyStrategy.team_state[_i] = DriveSE.ds_resurrect;
  925.                                     resurrect_success = true;
  926.                                     break;
  927.                                 }
  928.                             }
  929.                         }
  930.                         break;
  931.                     }
  932.                 }
  933.                 break;
  934.             }
  935.         }
  936.         if (!resurrect_success
  937.                 && MyStrategy.team_state[_i] == DriveSE.ds_resurrect)
  938.             MyStrategy.team_state[_i] = DriveSE.ds_stand;
  939.     }
  940.  
  941.     private boolean aiDoShootAndManevr(Tank self, World world,
  942.             final int selected_tank, Move move) {
  943.  
  944.         boolean result_i_am_do_something = false;
  945.         Tank[] all_tanks = world.getTanks();
  946.         if (selected_tank == all_tanks.length || selected_tank == -1)
  947.             return false;
  948.         Tank enemyTank = all_tanks[selected_tank];
  949.         if (_enemy_changed) {
  950.             this._enemy_last_v_x = enemyTank.getSpeedX();
  951.             this._enemy_last_v_y = enemyTank.getSpeedY();
  952.         }
  953.         double enemyDist = self.getDistanceTo(enemyTank);
  954.  
  955.         double Cx = BULLET__AERO_COEFF_REGULAR;
  956.         double d_allowed_premium = AIMING__PREMIUM_FIRE_DISTANCE;
  957.         boolean b_shoot_premium = self.getPremiumShellCount() > 0
  958.                 && enemyDist < d_allowed_premium;
  959.         boolean turned_to_me = MyStrategy.team_why_targets[_i] == WhyTarget.turned_to_me;
  960.         boolean low_hp_enemy = MyStrategy.team_why_targets[_i] == WhyTarget.low_hp;
  961.         if (turned_to_me)
  962.             b_shoot_premium = self.getPremiumShellCount() > 0;
  963.         if (b_shoot_premium)
  964.             Cx = BULLET__AERO_COEFF_PREMIUM;
  965.         double dVdD = Cx * Math.sqrt(enemyDist);
  966.         if (dVdD >= BULLET__SPEED)
  967.             dVdD = BULLET__SPEED - 1;
  968.         double bombFlyTime = enemyDist / (BULLET__SPEED - dVdD);
  969.         double evx = enemyTank.getSpeedX();
  970.         double evy = enemyTank.getSpeedY();
  971.         double dxv = evx * bombFlyTime;
  972.         double dyv = evy * bombFlyTime;
  973.  
  974.         double ax = evx - _enemy_last_v_x;
  975.         double ay = evy - _enemy_last_v_y;
  976.  
  977.         double lastv = Math.sqrt(_enemy_last_v_x * _enemy_last_v_x
  978.                 + _enemy_last_v_y * _enemy_last_v_y);
  979.         double v = Math.sqrt(evx * evx + evy * evy);
  980.         double a = v - lastv;
  981.         double dxa = bombFlyTime * bombFlyTime * ax / 2;
  982.         double dya = bombFlyTime * bombFlyTime * ay / 2;
  983.  
  984.         double S = Math.abs(v * bombFlyTime);
  985.         double Sa = Math.abs(bombFlyTime * bombFlyTime * a / 2);
  986.         double SMALL_DISTANCE = 90;
  987.         boolean start_driving = S < SMALL_DISTANCE && a >= 0;
  988.         boolean stop_driving = S < SMALL_DISTANCE && a < 0;
  989.         boolean decrease_speed = S > SMALL_DISTANCE && a < 0;
  990.         boolean increase_speed = S > SMALL_DISTANCE && a >= 0;
  991.         boolean strafe = start_driving || stop_driving;// drive slowly -> strafe
  992.         _i_can_shoot = increase_speed || start_driving || stop_driving
  993.                 || enemyDist < 650 || turned_to_me || low_hp_enemy;
  994.  
  995.         if (start_driving) {
  996.             dxv /= 3;
  997.             dyv /= 3;
  998.             dxa /= 10;
  999.             dya /= 10;
  1000.         }
  1001.         if (stop_driving) {
  1002.             dxv /= 10;
  1003.             dyv /= 10;
  1004.             dxa /= 10;
  1005.             dya /= 10;
  1006.         }
  1007.         double enemyNextX = enemyTank.getX() + dxv + dxa;
  1008.         double enemyNextY = enemyTank.getY() + dyv + dya;
  1009.         if (!isClearOfTanksSector(enemyTank, enemyNextX, enemyNextY, world, 45)) {
  1010.             enemyNextX = enemyTank.getX() + (dxv + dxa) / 3;
  1011.             enemyNextY = enemyTank.getY() + (dyv + dya) / 3;
  1012.         }
  1013.         // what our target point?
  1014.         boolean way_is_clear_for_shoot = true;
  1015.         TankCoords target = new TankCoords(enemyTank, enemyNextX, enemyNextY);
  1016.         if (turned_to_me) {
  1017.             enemyNextX = target.Xb;
  1018.             enemyNextY = target.Yb;
  1019.             if (self.getDistanceTo(target.Xf, target.Yf) < self.getDistanceTo(
  1020.                     enemyNextX, enemyNextY)) {
  1021.                 enemyNextX = target.Xf;
  1022.                 enemyNextY = target.Yf;
  1023.             }
  1024.         }
  1025.         if (!wayIsClearForShoot(enemyDist, enemyNextX, enemyNextY, _x, _y,
  1026.                 world)) {
  1027.             if (enemyDist > 350) {
  1028.                 way_is_clear_for_shoot = false;
  1029.             } else {
  1030.  
  1031.                 enemyNextX = target.Xf;
  1032.                 enemyNextY = target.Yf;
  1033.                 if (!wayIsClearForShoot(enemyDist, enemyNextX, enemyNextY, _x,
  1034.                         _y, world)) {
  1035.                     enemyNextX = target.Xb;
  1036.                     enemyNextY = target.Yb;
  1037.                     if (!wayIsClearForShoot(enemyDist, enemyNextX, enemyNextY,
  1038.                             _x, _y, world)) {
  1039.                         enemyNextX = target.X;
  1040.                         enemyNextY = target.Y;
  1041.                         way_is_clear_for_shoot = false;
  1042.                     }
  1043.                 }
  1044.             }
  1045.         }
  1046.         // ngc.drawCircle(enemyNextX, enemyNextY,
  1047.         // 45);ngc.drawString(Integer.toString(_i), enemyNextX+_i*10,
  1048.         // enemyNextY);
  1049.         // if(start_driving) ngc.drawString("start", enemyNextX,
  1050.         // enemyNextY);if(stop_driving)ngc.drawString("stop", enemyNextX,
  1051.         // enemyNextY);
  1052.         // if
  1053.         // (self.getRemainingReloadingTime()<self.getReloadingTime()-bombFlyTime
  1054.         // ){ eNX = enemyNextX;eNY = enemyNextY;bft=bombFlyTime;
  1055.         // ngc.setColor("white"); ngc.drawLine(_x, _y, eNX, eNY);
  1056.         // ngc.drawCircle(eNX, eNY, 45); ngc.setColor("red"); }else{
  1057.         // ngc.drawString(Double.toString(bft), eNX, eNY); bft--;
  1058.         // ngc.drawLine(_x, _y, eNX, eNY); ngc.drawCircle(eNX, eNY, 45); }
  1059.  
  1060.         // AI_FIND_SAFE_OF_TARGETING_POINT_ON_MAP
  1061.         b_im_hiding = false;
  1062.         b_im_goto_min_dist = false;
  1063.         double earm = enemyTank.getHullDurability();
  1064.         double ehp = enemyTank.getCrewHealth();
  1065.  
  1066.         if (!b_im_avoiding_bomb
  1067.                 /* && b_it_is_a_time_to_drive */
  1068.                 && (!b_im_goto_bonus && !b_im_drive_to_corner || (MyStrategy._team_rush && !(b_im_goto_bonus && (b_i_need_ammo
  1069.                         || b_i_need_armor || b_i_need_health)))))
  1070.             if (_enemy_healthy_tanks == 1
  1071.                     && enemyTank.getPremiumShellCount() <= self
  1072.                             .getPremiumShellCount()
  1073.                     && _hp * _armor > ehp * earm || MyStrategy._team_rush) {
  1074.                 if (enemyDist > RANGING__CLOSER_RANGE)
  1075.                     b_im_goto_min_dist = aiGotoMinDist(enemyTank, self, world);
  1076.             } else
  1077.                 if (!b_im_hunting && way_is_clear_for_shoot
  1078.                 /* && (_enemy_healthy_tanks >= _team_healthy_tanks) */
  1079.                 /* && (b_i_need_armor || b_i_need_health || enemyDist < 500) */) {
  1080.                     b_im_hiding = aiGotoSafePoint(all_tanks, self, world,
  1081.                             enemyTank);
  1082.                 }
  1083.         double turret_angle_to_enemy = self.getTurretAngleTo(enemyNextX,
  1084.                 enemyNextY);
  1085.         boolean b_im_doing_extra_things = b_im_avoiding_bomb;
  1086.         boolean b_im_driving_for_profit = (b_im_goto_bonus || b_im_hiding
  1087.                 ||  b_im_escape_for_range);
  1088.         boolean b_its_time_to_aim_and_shoot = (self.getRemainingReloadingTime() < AIMING__STOP_DRIVE_TO_SHOOT_TIME
  1089.                 && !((b_i_need_armor_extra || b_i_need_health_extra) && b_im_driving_for_profit));
  1090.         double attack_angle = getMaxAngleOfUnitOnDist(_x, _y, enemyTank,
  1091.                 enemyNextX, enemyNextY);
  1092.         boolean b_my_turret_in_very_wrong_direction = (Math
  1093.                 .abs(turret_angle_to_enemy) > 3 * PI / 180
  1094.                 + Math.abs(attack_angle / AIMING__ACCURACY));
  1095.         b_im_turning_to_help_turn_turret = way_is_clear_for_shoot
  1096.                 && (!b_im_doing_extra_things && (b_its_time_to_aim_and_shoot && b_my_turret_in_very_wrong_direction));
  1097.         if (b_im_turning_to_help_turn_turret) {
  1098.             MyStrategy.team_state[_i] = DriveSE.ds_help_rotate_turret;
  1099.             // ngc.drawString("turn", _x, _y);
  1100.         }
  1101.         // Tank who_targets_my_enemy = getCloserOfTargetingTankEnemy(enemyTank,
  1102.         // world, WORLD_WIDTH);
  1103.         if (turret_angle_to_enemy >= attack_angle / AIMING__ACCURACY) {
  1104.             move.setTurretTurn(1.0);
  1105.             if (b_im_turning_to_help_turn_turret)
  1106.                 doTurnRightMax(move);
  1107.         } else
  1108.             if (turret_angle_to_enemy <= -attack_angle / AIMING__ACCURACY) {
  1109.                 move.setTurretTurn(-1.0);
  1110.                 if (b_im_turning_to_help_turn_turret)
  1111.                     doTurnLeftMax(move);
  1112.             } else
  1113.                 if (way_is_clear_for_shoot && _i_can_shoot) {
  1114.                     b_im_hunting = false;
  1115.                     if (b_shoot_premium)
  1116.                         move.setFireType(FireType.PREMIUM_PREFERRED);
  1117.                     else
  1118.                         move.setFireType(FireType.REGULAR);
  1119.                 }
  1120.         // AI_HUNT
  1121.         if (!way_is_clear_for_shoot
  1122.                 && (self.getRemainingReloadingTime() < AIMING__STOP_DRIVE_TO_SHOOT_TIME)
  1123.                 && !b_im_avoiding_bomb && !b_im_goto_bonus
  1124.                 && !b_im_drive_to_corner && !b_im_goto_min_dist
  1125.                 && !(b_i_need_health_extra_super || b_i_need_armor_extra_super)
  1126.                 && !b_im_turning_to_help_turn_turret)
  1127.             b_im_hunting = aiGotoHunt(self, world, enemyTank, enemyNextX,
  1128.                     enemyNextY);
  1129.         // AI_TURN_TO_ENEMY
  1130.         if (!b_im_avoiding_bomb && !b_im_goto_bonus && !b_im_hiding
  1131.                 && !b_im_goto_min_dist && !b_im_escape_for_range
  1132.                 && !b_im_turning_to_help_turn_turret /* && !b_im_hunting */
  1133.                 && !b_im_drive_to_corner) {
  1134.             b_im_turn_to_enemy = aiTurnToEnemy(self, enemyTank, move);
  1135.         } else
  1136.             b_im_turn_to_enemy = false;
  1137.         _enemy_last_v_x = enemyTank.getSpeedX();
  1138.         _enemy_last_v_y = enemyTank.getSpeedY();
  1139.  
  1140.         result_i_am_do_something = b_im_turn_to_enemy
  1141.                 || b_im_turning_to_help_turn_turret;
  1142.         return result_i_am_do_something;
  1143.     }
  1144.  
  1145.     private boolean aiDrivePath(Tank self, Move move, World world) {
  1146.         boolean result_i_drive = false;
  1147.  
  1148.         if (_path[_path_current].x != -1
  1149.                 && MyStrategy.team_state[_i] != DriveSE.ds_stand) {
  1150.  
  1151.             if (self.getDistanceTo(_path[_path_current].x,
  1152.                     _path[_path_current].y) >= DRIVE__PATH_POINT_ACCURACY
  1153.                     + _drive_target_H / 2) {
  1154.  
  1155.                 driveToPoint(_path[_path_current].x, _path[_path_current].y,
  1156.                         move, self, _drive_target_H, world);
  1157.                 result_i_drive = true;
  1158.             } else {
  1159.                 _path[_path_current].x = -1;
  1160.                 _path_current++;
  1161.                 if (_path_current >= _path.length)
  1162.                     _path_current = 0;
  1163.                 if (_path[_path_current].x == -1) {
  1164.                     // miss path
  1165.                     int s = _path_current;
  1166.                     for (s = _path_current; s < _path.length; s++)
  1167.                         if (_path[s].x != -1) {
  1168.                             _path_current = s;
  1169.                             break;
  1170.                         }
  1171.                     if (s == _path.length)
  1172.                         _path_current = 0;
  1173.                 }
  1174.             }
  1175.         } else {
  1176.             double v = Math.sqrt(_vx * _vx + _vy * _vy);
  1177.             if (v < 10) {
  1178.                 if (_tik_strafe > 50)
  1179.                     _tik_strafe = 0;
  1180.                 if (_tik_strafe <= 20)
  1181.                     doMoveForward(move);
  1182.                 else
  1183.                     doMoveBack(move);
  1184.                 _tik_strafe++;
  1185.             } else
  1186.                 _tik_strafe = 0;
  1187.             MyStrategy.team_state[_i] = DriveSE.ds_drive_strafe;
  1188.         }
  1189.         // ngc.drawCircle(_path[_path_current].x, _path[_path_current].y,
  1190.         // DRIVE__PATH_POINT_ACCURACY + _drive_target_H / 2 - 2);
  1191.         // ngc.drawString(Integer.toString(_i),
  1192.         // _path[_path_current].x+_i*10, _path[_path_current].y);
  1193.         // ngc.drawString(MyStrategy.team_state[_i].toString(),
  1194.         // _x, _y);
  1195.         return result_i_drive;
  1196.     }
  1197.  
  1198.     private boolean aiGotoBonus(World world, Tank self) {
  1199.         boolean i_drive_to_bonus = false;
  1200.  
  1201.         Bonus[] all_bonuses = world.getBonuses();
  1202.         int selected_bonus = all_bonuses.length;
  1203.         double min_dist_to_bonus = 1E50;
  1204.         if ((MyStrategy._team_rush)) {
  1205.             min_dist_to_bonus = 300;
  1206.         }
  1207.         if (b_i_need_health_extra_super || b_i_need_armor_extra_super)
  1208.             min_dist_to_bonus = BONUS__AMMO_MAX_DIST_EXTRA_SUPER_LOW_HP;
  1209.         if (b_i_need_ammo)
  1210.             for (int i = 0; i < all_bonuses.length; i++) {
  1211.                 Bonus bonus = all_bonuses[i];
  1212.                 if (bonus.getType() != BonusType.AMMO_CRATE)
  1213.                     continue;
  1214.                 double dist_to_bonus = self.getDistanceTo(bonus);
  1215.                 double corner_dist = bonus.getDistanceTo(_corner_x, _corner_y);
  1216.                 if ((!b_it_is_a_time_to_drive)
  1217.                         && (corner_dist > (CORNER__MAX_ALLOWED_DISTANCE_TO_BONUS)))
  1218.                     continue;
  1219.                 if (dist_to_bonus < min_dist_to_bonus) {
  1220.                     Tank closest_tank = getClosestTankToPoint(world.getTanks(),
  1221.                             bonus.getX(), bonus.getY(),
  1222.                             CORNER__MAX_ALLOWED_DISTANCE_TO_BONUS);
  1223.                     if (closest_tank != null
  1224.                             && !isSameTank(closest_tank, self)
  1225.                             && (dist_to_bonus > CORNER__MAX_ALLOWED_DISTANCE_TO_BONUS))
  1226.                         continue;
  1227.                     min_dist_to_bonus = dist_to_bonus;
  1228.                     selected_bonus = i;
  1229.                 }
  1230.             }
  1231.         if (b_i_need_armor_extra)
  1232.             min_dist_to_bonus = BONUS__HP_DIST_EXTRA_SUPER_LOW_HP;
  1233.         if (b_i_need_armor || b_i_need_armor_extra
  1234.                 || b_i_need_armor_extra_super)
  1235.             for (int i = 0; i < all_bonuses.length; i++) {
  1236.                 Bonus bonus = all_bonuses[i];
  1237.                 if (bonus.getType() != BonusType.REPAIR_KIT)
  1238.                     continue;
  1239.                 double dist_to_bonus = self.getDistanceTo(bonus);
  1240.                 double corner_dist = bonus.getDistanceTo(_corner_x, _corner_y);
  1241.                 if ((!b_i_need_armor_extra)
  1242.                         && ((!b_it_is_a_time_to_drive) && (corner_dist > (CORNER__MAX_ALLOWED_DISTANCE_TO_BONUS))))
  1243.                     continue;
  1244.                 if (dist_to_bonus < min_dist_to_bonus) {
  1245.                     Tank closest_tank = getClosestTankToPoint(world.getTanks(),
  1246.                             bonus.getX(), bonus.getY(),
  1247.                             CORNER__MAX_ALLOWED_DISTANCE_TO_BONUS);
  1248.                     if (closest_tank != null
  1249.                             && !isSameTank(closest_tank, self)
  1250.                             && (dist_to_bonus > CORNER__MAX_ALLOWED_DISTANCE_TO_BONUS))
  1251.                         continue;
  1252.                     min_dist_to_bonus = dist_to_bonus;
  1253.                     selected_bonus = i;
  1254.                 }
  1255.             }
  1256.         if (b_i_need_health_extra)
  1257.             min_dist_to_bonus = BONUS__HP_DIST_EXTRA_SUPER_LOW_HP;
  1258.         if (b_i_need_health || b_i_need_health_extra
  1259.                 || b_i_need_health_extra_super)
  1260.             for (int i = 0; i < all_bonuses.length; i++) {
  1261.                 Bonus bonus = all_bonuses[i];
  1262.                 if (bonus.getType() != BonusType.MEDIKIT)
  1263.                     continue;
  1264.  
  1265.                 double dist_to_bonus = self.getDistanceTo(bonus);
  1266.                 double corner_dist = bonus.getDistanceTo(_corner_x, _corner_y);
  1267.                 if ((!b_i_need_health_extra)
  1268.                         && ((!b_it_is_a_time_to_drive) && (corner_dist > (CORNER__MAX_ALLOWED_DISTANCE_TO_BONUS))))
  1269.                     continue;
  1270.                 if (dist_to_bonus < min_dist_to_bonus) {
  1271.                     Tank closest_tank = getClosestTankToPoint(world.getTanks(),
  1272.                             bonus.getX(), bonus.getY(),
  1273.                             CORNER__MAX_ALLOWED_DISTANCE_TO_BONUS);
  1274.                     if (closest_tank != null
  1275.                             && !isSameTank(closest_tank, self)
  1276.                             && (dist_to_bonus > CORNER__MAX_ALLOWED_DISTANCE_TO_BONUS))
  1277.                         continue;
  1278.                     min_dist_to_bonus = dist_to_bonus;
  1279.                     selected_bonus = i;
  1280.                 }
  1281.             }
  1282.         if (selected_bonus != all_bonuses.length) {
  1283.             i_drive_to_bonus = true;
  1284.             _drive_target_H = BONUS__DRIVE_POINT_RADIUS;
  1285.             /*
  1286.              * ngc.setColor("red"); if (MyStrategy.team_roles[_i]==role.leader)
  1287.              * ngc.drawCircle(all_bonuses[selected_bonus].getX(),
  1288.              * all_bonuses[selected_bonus].getY(), _drive_target_H);
  1289.              * ngc.drawCircle(all_bonuses[selected_bonus].getX(),
  1290.              * all_bonuses[selected_bonus].getY(), _drive_target_H-2);
  1291.              * ngc.setColor("red");
  1292.              */
  1293.             MyStrategy.team_state[_i] = DriveSE.ds_drive_bonus;
  1294.             createPathToPoint(all_bonuses[selected_bonus].getX(),
  1295.                     all_bonuses[selected_bonus].getY(), world, self);
  1296.         }
  1297.  
  1298.         return i_drive_to_bonus;
  1299.     }
  1300.  
  1301.     private boolean aiGotoHunt(Tank self, World world, Tank enemyTank,
  1302.             final double enemyNextX, final double enemyNextY) {
  1303.         boolean result_i_drive_for_hunt = false;
  1304.  
  1305.         double mdX = -1, mdY = -1;
  1306.         double myAngle = self.getAngle();
  1307.         double max_dist = CONFIG__WORLD_WIDTH;
  1308.         double min_dist_to_enemy = 0;
  1309.         double angle = 30;
  1310.         if (!b_it_is_a_time_to_drive && !MyStrategy._team_rush) {
  1311.             max_dist = 500;
  1312.             angle = 10;
  1313.             // min_dist_to_enemy=700;
  1314.         }
  1315.         for (double dist = CONFIG__MY_WIDTH * 2.5; dist < max_dist; dist = dist
  1316.                 + CONFIG__MY_WIDTH) {
  1317.             double dfi = 0.25 * getObjAngleOnDistance(dist, CONFIG__MY_WIDTH)
  1318.                     * 180 / PI;
  1319.             for (double fi = 0; fi < 360; fi = fi + dfi) {
  1320.                 if (fi > angle && fi < 180 - angle || fi > 180 + angle
  1321.                         && fi < 360 - angle)
  1322.                     continue;
  1323.                 double x = _x + dist * Math.cos((fi + myAngle) * PI / 180);
  1324.                 double y = _y + dist * Math.sin((fi + myAngle) * PI / 180);
  1325.                 if (min_dist_to_enemy > 0
  1326.                         && isEnemiesInPoint(world.getTanks(), x, y,
  1327.                                 min_dist_to_enemy))
  1328.                     continue;
  1329.                 double enemyDist = enemyTank.getDistanceTo(x, y);
  1330.                 if (!isOnCorner(x, y)
  1331.                         && wayIsClearForShoot(enemyDist, enemyNextX,
  1332.                                 enemyNextY, x, y, world)
  1333.                         && isClearToDriveSector(x, y, world)) {
  1334.                     mdX = x;
  1335.                     mdY = y;
  1336.                     result_i_drive_for_hunt = true;
  1337.                     break;
  1338.                 }
  1339.             }
  1340.             if (result_i_drive_for_hunt)
  1341.                 break;
  1342.         }
  1343.         if (result_i_drive_for_hunt) {
  1344.             createPathToPoint(mdX, mdY, world, self); // NO DANGER POINT
  1345.             _drive_target_H = HUNT__DRIVE_POINT_RADIUS;
  1346.             /*
  1347.              * ngc.setColor("yellow"); if
  1348.              * (MyStrategy.team_roles[_i]==role.leader) ngc.drawCircle(mdX, mdY,
  1349.              * _drive_target_H); ngc.drawCircle(mdX, mdY, _drive_target_H-2);
  1350.              * ngc.setColor("red");
  1351.              */
  1352.             MyStrategy.team_state[_i] = DriveSE.ds_hunting;
  1353.         }
  1354.  
  1355.         return result_i_drive_for_hunt;
  1356.     }
  1357.  
  1358.     private boolean aiGotoMinDist(Tank enemyTank, Tank self, World world) {
  1359.         boolean result_i_goto_min_dist = false;
  1360.  
  1361.         // goto_min_dist
  1362.         // double RANGE = RANGING__CLOSER_RANGE;
  1363.         double rmdX = -1, rmdY = -1;
  1364.         TankCoords t_c = new TankCoords(enemyTank);
  1365.         double p1x = t_c.Xr;
  1366.         double p1y = t_c.Yr;
  1367.         double d1 = self.getDistanceTo(p1x, p1y);
  1368.         double p2x = t_c.Xl;
  1369.         double p2y = t_c.Yl;
  1370.         double d2 = self.getDistanceTo(p2x, p2y);
  1371.         if (isOutWorldPointRadius(p1x, p1y, 10)) {
  1372.             d1 = -1;// no p1
  1373.         }
  1374.         if (isOutWorldPointRadius(p2x, p2y, 10)) {
  1375.             d2 = -1;// no p2
  1376.         }
  1377.         if (d1 < d2 && d1 > 0 || d2 < 0 && d1 > 0) {
  1378.             rmdX = p1x;
  1379.             rmdY = p1y;
  1380.             result_i_goto_min_dist = true;
  1381.         }
  1382.         if (d2 < d1 && d2 > 0 || d1 < 0 && d2 > 0) {
  1383.             rmdX = p2x;
  1384.             rmdY = p2y;
  1385.             result_i_goto_min_dist = true;
  1386.         }
  1387.         if (result_i_goto_min_dist) {
  1388.             createPathToPoint(rmdX, rmdY, world, self);
  1389.             _drive_target_H = RANGING__DRIVE_POINT_RADIUS;
  1390.             /*
  1391.              * ngc.setColor("green"); if
  1392.              * (MyStrategy.team_roles[_i]==role.leader) ngc.drawCircle(rmdX,
  1393.              * rmdY, _drive_target_H); ngc.drawCircle(rmdX, rmdY,
  1394.              * _drive_target_H-2); ngc.setColor("red");
  1395.              */
  1396.             MyStrategy.team_state[_i] = DriveSE.ds_drive_closer;
  1397.         }
  1398.  
  1399.         return result_i_goto_min_dist;
  1400.     }
  1401.  
  1402.     private boolean aiGotoSafePoint(Tank[] all_tanks, Tank self, World world,
  1403.             Tank enemyTank) {
  1404.         boolean result_i_goto_safe_point = false;
  1405.  
  1406.         double mdX = -1, mdY = -1;
  1407.         double min_dist = 500;
  1408.         double tc = all_tanks.length;
  1409.  
  1410.         for (int i = 0; i < tc; i++) {
  1411.             Tank ob = all_tanks[i];
  1412.  
  1413.             if (isSameTank(ob, self)
  1414.                     || isSameTank(ob, enemyTank)
  1415.                     || (ob.getCrewHealth() > 0 && ob.getHullDurability() > 0 && !ob
  1416.                             .isTeammate()))
  1417.                 continue;
  1418.             double Tx = ob.getX();
  1419.             double Ty = ob.getY();
  1420.             double ETx = Tx - enemyTank.getX();
  1421.             double ETy = Ty - enemyTank.getY();
  1422.             double normaTE = Math.sqrt(ETx * ETx + ETy * ETy);
  1423.             double x = Tx + ob.getWidth() * ETx / normaTE;
  1424.             double y = Ty + ob.getWidth() * ETy / normaTE;
  1425.             double dist = self.getDistanceTo(x, y);
  1426.             if (dist < min_dist && isClearOfTanksSector(self, x, y, world, 0)) {
  1427.                 min_dist = dist;
  1428.                 mdX = x;
  1429.                 mdY = y;
  1430.                 result_i_goto_safe_point = true;
  1431.             }
  1432.         }
  1433.         Obstacle[] obst = world.getObstacles();
  1434.         int oc = obst.length;
  1435.         if (min_dist == 500)
  1436.             min_dist = 2000;
  1437.         for (int i = 0; i < oc; i++) {
  1438.  
  1439.             Obstacle ob = obst[i];
  1440.  
  1441.             double Tx = ob.getX();
  1442.             double Ty = ob.getY();
  1443.             double ETx = Tx - enemyTank.getX();
  1444.             double ETy = Ty - enemyTank.getY();
  1445.             double normaTE = Math.sqrt(ETx * ETx + ETy * ETy);
  1446.             double hide_dist = Math.sqrt(ob.getWidth() * ob.getWidth()
  1447.                     + ob.getHeight() * ob.getHeight())
  1448.                     + (_i + 1) * self.getWidth() * 2;
  1449.             double x = Tx + hide_dist * ETx / normaTE;
  1450.             double y = Ty + hide_dist * ETy / normaTE;
  1451.             double dist = self.getDistanceTo(x, y);
  1452.             if (dist < min_dist && isClearOfTanksSector(self, x, y, world, 0)) {
  1453.                 min_dist = dist;
  1454.                 mdX = x;
  1455.                 mdY = y;
  1456.                 result_i_goto_safe_point = true;
  1457.             }
  1458.         }
  1459.         if (result_i_goto_safe_point) {
  1460.             createPathToPoint(mdX, mdY, world, self); // NO DANGER POINT
  1461.             _drive_target_H = HIDING__DRIVE_POINT_RADIUS;
  1462.             /*
  1463.              * ngc.setColor("blue"); if (MyStrategy.team_roles[_i]==role.leader)
  1464.              * ngc.drawCircle(mdX, mdY, _drive_target_H); ngc.drawCircle(mdX,
  1465.              * mdY, _drive_target_H-2); ngc.setColor("red");
  1466.              */
  1467.             MyStrategy.team_state[_i] = DriveSE.ds_hiding;
  1468.         }
  1469.  
  1470.         return result_i_goto_safe_point;
  1471.     }
  1472.  
  1473.     private boolean isEnemiesInPoint(Tank[] at, double px, double py, double r) {
  1474.         boolean result = false;
  1475.         for (int i = 0; i < at.length; i++) {
  1476.             Tank t = at[i];
  1477.             if (t.isTeammate() || !isTankAlive(t))
  1478.                 continue;
  1479.             if (t.getDistanceTo(px, py) < r + t.getWidth() / 2)
  1480.                 return false;
  1481.         }
  1482.         return result;
  1483.  
  1484.     }
  1485.  
  1486.     private void aiDriveTeammate(Tank self, World world) {
  1487.         Tank[] at = world.getTanks();
  1488.         int tc = at.length;
  1489.         double max_distance_allowed = 400;
  1490.         double current_max_distance = 2000;
  1491.         double min_distance_allowed = 150;
  1492.         int selected_tank = tc;
  1493.         // try find closer
  1494.         for (int i = 0; i < tc; i++) {
  1495.             Tank t = at[i];
  1496.             if (!t.isTeammate() || !isTankAlive(t))
  1497.                 continue;
  1498.             double d = self.getDistanceTo(t);
  1499.             if (d < max_distance_allowed && d > 15) {
  1500.                 selected_tank = i;
  1501.                 max_distance_allowed = d;
  1502.             }
  1503.         }
  1504.         if (selected_tank == tc) {// closer not finded
  1505.             for (int i = 0; i < tc; i++) {
  1506.                 Tank t = at[i];
  1507.                 if (!t.isTeammate() || !isTankAlive(t))
  1508.                     continue;
  1509.                 double d = self.getDistanceTo(t);
  1510.                 // find closer of ranged
  1511.                 if (d < current_max_distance && d > 15) {
  1512.                     current_max_distance = d;
  1513.                     selected_tank = i;
  1514.                 }
  1515.             }
  1516.             if (selected_tank != tc) {
  1517.                 // finded
  1518.                 createPathToPoint(at[selected_tank].getX(),
  1519.                         at[selected_tank].getY(), world, self);
  1520.                 _drive_target_H = 20;
  1521.                 MyStrategy.team_state[_i] = DriveSE.ds_drive_corner;
  1522.                 b_im_drive_to_corner = true;
  1523.                 _corner_x = at[selected_tank].getX();
  1524.                 _corner_y = at[selected_tank].getY();
  1525.             }
  1526.         } else
  1527.             if (max_distance_allowed < min_distance_allowed) {// closer finded!
  1528.                 // drive from it!
  1529.  
  1530.                 TankCoords _t = new TankCoords(self);
  1531.  
  1532.                 double p1x = _t.X + _t.W * 2 * _t.cosA;
  1533.                 double p1y = _t.Y + _t.W * 2 * _t.sinA;
  1534.                 double p2x = _t.X - _t.W * 2 * _t.cosA;
  1535.                 double p2y = _t.Y - _t.W * 2 * _t.sinA;
  1536.                 double px = _t.X, py = _t.Y;
  1537.                 boolean point_finded = false;
  1538.                 double d1 = at[selected_tank].getDistanceTo(p1x, p1y);
  1539.                 double d2 = at[selected_tank].getDistanceTo(p2x, p2y);
  1540.                 if (d1 > d2) {
  1541.                     if (isClearToDriveSector(p1x, p1y, world)) {
  1542.                         px = p1x;
  1543.                         py = p1y;
  1544.                         point_finded = true;
  1545.                     }
  1546.                 } else
  1547.                     if (isClearToDriveSector(p2x, p2y, world)) {
  1548.                         px = p2x;
  1549.                         py = p2y;
  1550.                         point_finded = true;
  1551.                     }
  1552.                 if (point_finded) {
  1553.                     // go far
  1554.                     // ngc.drawCircle(px, py, 45);
  1555.                     createPathToPoint(px, py, world, self);
  1556.                     _drive_target_H = 30;
  1557.                     MyStrategy.team_state[_i] = DriveSE.ds_drive_corner;
  1558.                     b_im_drive_to_corner = true;
  1559.                     _corner_x = px;
  1560.                     _corner_y = py;
  1561.  
  1562.                 }
  1563.             }
  1564.     }
  1565.  
  1566.     private boolean aiHideInCorner(Tank self, World world) {
  1567.         boolean i_drive_to_hide_in_corner = false;
  1568.         double minimum_distance = CONFIG__WORLD_WIDTH;// don't go to diagonal
  1569.         if (MyStrategy.team_roles[_i] == role.leader)
  1570.             _team_leader_corner = _corners.length;
  1571.         int selected_corner = _corners.length;
  1572.  
  1573.         for (int i = 0; i < _corners.length; i++) {
  1574.             double x = _corners[i].x;
  1575.             double y = _corners[i].y;
  1576.             // ngc.drawCircle(x, y, CORNER__POINT_RADIUS);
  1577.             double dist = self.getDistanceTo(x, y);
  1578.             if (dist < minimum_distance) {
  1579.                 if (isEnemiesInPoint(world.getTanks(), x, y,
  1580.                         CORNER__PLAYER_RADAR_RADIUS))
  1581.                     continue;// skip stupid corner;
  1582.                 minimum_distance = dist;
  1583.                 selected_corner = i;
  1584.             }
  1585.         }
  1586.         if (MyStrategy.team_roles[_i] != role.leader && _team_healthy_tanks > 1)
  1587.             ;// selected_corner = _team_leader_corner;// leader choose corner
  1588.         else
  1589.             _team_leader_corner = selected_corner;
  1590.         if (selected_corner != _corners.length) {
  1591.             _corner_x = _corners[selected_corner].x;
  1592.             _corner_y = _corners[selected_corner].y;
  1593.             if (self.getDistanceTo(_corner_x, _corner_y) > CORNER__POINT_RADIUS) {
  1594.                 createPathToPoint(_corner_x, _corner_y, world, self);
  1595.                 _drive_target_H = CORNER__DRIVE_POINT_RADIUS;
  1596.                 // ngc.setColor("blue");
  1597.                 /*
  1598.                  * if (MyStrategy.team_roles[_i]==role.leader)
  1599.                  * ngc.drawCircle(_corner_x, _corner_y, _drive_target_H);
  1600.                  * ngc.drawCircle(_corner_x, _corner_y, _drive_target_H-2);
  1601.                  * ngc.setColor("red");
  1602.                  */
  1603.                 i_drive_to_hide_in_corner = true;
  1604.                 MyStrategy.team_state[_i] = DriveSE.ds_drive_corner;
  1605.             }
  1606.         }
  1607.         return i_drive_to_hide_in_corner;
  1608.     }
  1609.  
  1610.     private static final int countEnemyTeams(Tank[] at) {
  1611.         int count = 6;
  1612.         for (int i = 0; i < at.length; i++) {
  1613.             Tank t = at[i];
  1614.             if (t.isTeammate())
  1615.                 continue;
  1616.             if (t.getTeammateIndex() == 2) {
  1617.                 count = 1;
  1618.                 break;
  1619.             }
  1620.             if (t.getTeammateIndex() == 1) {
  1621.                 count = 2;
  1622.                 break;
  1623.             }
  1624.         }
  1625.         if (count == 2) {
  1626.             for (int i = 0; i < at.length; i++) {
  1627.                 Tank t = at[i];
  1628.                 if (t.isTeammate())
  1629.                     continue;
  1630.                 String n = t.getPlayerName();
  1631.                 if (MyStrategy.team_1_name.equals("")) {
  1632.                     MyStrategy.team_1_name = n;
  1633.                 } else {
  1634.                     if (!n.equals(MyStrategy.team_1_name))
  1635.                         if (MyStrategy.team_2_name.equals("")) {
  1636.                             MyStrategy.team_2_name = n;
  1637.                             break;
  1638.                         }
  1639.                 }
  1640.             }
  1641.         }
  1642.         return count;
  1643.     }
  1644.  
  1645.     private void leaderDoCountEnemyTeamAlive(Tank[] at) {// first should run
  1646.                                                          // countEnemyTeams
  1647.         MyStrategy.team_1_alive_count = 0;
  1648.         MyStrategy.team_2_alive_count = 0;
  1649.         MyStrategy.enemy_premium_count = 0;
  1650.         for (int i = 0; i < at.length; i++) {
  1651.             Tank t = at[i];
  1652.             if (t.isTeammate())
  1653.                 continue;
  1654.             double hpp = 100 * t.getCrewHealth() / t.getCrewMaxHealth();
  1655.             double armp = 100 * t.getHullDurability()
  1656.                     / t.getHullMaxDurability();
  1657.             if (hpp * armp == 0 || hpp < 50 || armp < 50)
  1658.                 continue;
  1659.             String n = t.getPlayerName();
  1660.             if (n.equals(MyStrategy.team_1_name)) {
  1661.                 MyStrategy.team_1_alive_count++;MyStrategy.enemy_premium_count+=t.getPremiumShellCount();
  1662.             } else {
  1663.                 MyStrategy.team_2_alive_count++;MyStrategy.enemy_premium_count+=t.getPremiumShellCount();
  1664.             }
  1665.         }
  1666.     }
  1667.  
  1668.     private boolean isMyEnemyVisible(World world, Tank self) {
  1669.         boolean result = true;
  1670.         Tank[] all_tanks = world.getTanks();
  1671.         int tc = all_tanks.length;
  1672.         for (int i = 0; i < tc; ++i) {
  1673.             Tank tank = all_tanks[i];
  1674.             if (tank.isTeammate())
  1675.                 continue;
  1676.             if (MyStrategy._enemy[_i] == -1) {
  1677.                 return false;
  1678.             } else {
  1679.                 if (tank.getId() == MyStrategy._enemy[_i]) {
  1680.                     if (!isTankAlive(tank)) {
  1681.                         return false;
  1682.                     } else {
  1683.                         return true;
  1684.                     }
  1685.                 }
  1686.             }
  1687.         }
  1688.         return result;
  1689.     }
  1690.  
  1691.     private int aiSelectEnemy(Tank self, World world) {
  1692.         Tank[] all_tanks = world.getTanks();
  1693.         int tc = all_tanks.length;
  1694.  
  1695.         int result_selected_tank = tc;
  1696.         /*
  1697.          * check if need assist
  1698.          */
  1699.         int teamI = 0;
  1700.         switch (MyStrategy.team_why_targets[_i]) {
  1701.         case closer_range:
  1702.         case target_me_in_closer_range:
  1703.             MyStrategy.team_help[_i] = helping.assist_me_please;
  1704.  
  1705.         break;
  1706.         default:
  1707.             MyStrategy.team_help[_i] = helping.no_thanks;
  1708.             if (MyStrategy.team_roles[_i] == role.leader) {
  1709.                 teamI = whoNeedsHelpInTeam();
  1710.                 if (teamI == _i && !isTeamAssistSameTarget())
  1711.                     ;// MyStrategy.team_help[_i] = helping.assist_me_please;
  1712.             }
  1713.         break;
  1714.         }
  1715.         teamI = whoNeedsHelpInTeam();
  1716.         if (teamI != _i&& MyStrategy._team_rush) {
  1717.             long newI = MyStrategy._enemy[teamI];
  1718.             long myI = MyStrategy._enemy[_i];
  1719.             if (myI != newI ) {
  1720.                 MyStrategy._enemy[_i] = newI;// TODO assist
  1721.                 if (MyStrategy.team_roles[_i] == role.leader)
  1722.                     MyStrategy.team_why_targets[_i] = WhyTarget.help_assist;
  1723.                 else
  1724.                     MyStrategy.team_why_targets[_i] = WhyTarget.assist_leader;
  1725.             }
  1726.         }
  1727.  
  1728.         /*
  1729.          * MyStrategy._enemy[_i] must be defined
  1730.          */
  1731.         double min_distance_to_enemy = 2000;
  1732.         for (int i = 0; i < tc; ++i) {
  1733.             Tank tank = all_tanks[i];
  1734.             if (tank.isTeammate())
  1735.                 continue;
  1736.             if (MyStrategy._enemy[_i] == -1) {
  1737.                 double d = tank.getDistanceTo(self);
  1738.                 if (d < min_distance_to_enemy
  1739.                         && wayIsClearForShoot(d, _next_x, _next_y, tank.getX(),
  1740.                                 tank.getY(), world)) {
  1741.                     if (tank.getCrewHealth() == 0
  1742.                             || tank.getHullDurability() == 0)
  1743.                         continue;
  1744.                     result_selected_tank = i;
  1745.                     min_distance_to_enemy = d;// minimize distance
  1746.                     MyStrategy.team_why_targets[_i] = WhyTarget.closer_visible;
  1747.                 }
  1748.             } else {
  1749.                 if (tank.getId() == MyStrategy._enemy[_i]) {
  1750.                     if (tank.getCrewHealth() == 0
  1751.                             || tank.getHullDurability() == 0) {
  1752.                         MyStrategy._enemy[_i] = -1;
  1753.                     } else {
  1754.                         result_selected_tank = i;
  1755.                         MyStrategy.team_why_targets[_i] = WhyTarget.last;
  1756.                         break;
  1757.                     }
  1758.                 }
  1759.             }
  1760.         }
  1761.         if (result_selected_tank == all_tanks.length) {
  1762.             double max_distance_to_enemy = 2000;
  1763.             for (int i = 0; i < all_tanks.length; i++) {
  1764.                 Tank tank = all_tanks[i];
  1765.                 if (tank.isTeammate() || !isTankAlive(tank))
  1766.                     continue;
  1767.                 double d = tank.getDistanceTo(self);
  1768.                 if (d < max_distance_to_enemy) {
  1769.                     max_distance_to_enemy = d;
  1770.                     MyStrategy._enemy[_i] = tank.getId();
  1771.                     MyStrategy.team_why_targets[_i] = WhyTarget.closer_range;
  1772.                 }
  1773.             }
  1774.         }
  1775.         /*
  1776.          * check if enemy changed
  1777.          */
  1778.         if (MyStrategy._enemy[_i] != _last_enemy_id) {
  1779.             _last_enemy_id = MyStrategy._enemy[_i];
  1780.             _enemy_changed = true;
  1781.         } else {
  1782.             _enemy_changed = false;
  1783.         }
  1784.  
  1785.         return result_selected_tank;
  1786.     }
  1787.  
  1788.     private void aiSpotLowHPEnemy(Tank self, World world) {
  1789.         double minimum_distance = 2000;// find closer!
  1790.         double myDamage;
  1791.         Tank[] all_tanks = world.getTanks();
  1792.         for (int i = 0; i < all_tanks.length; i++) {
  1793.             Tank tank = all_tanks[i];
  1794.             if (tank.isTeammate() || !isTankAlive(tank))
  1795.                 continue;
  1796.             double d = tank.getDistanceTo(self);
  1797.             if (_premium_count > 0 && d < AIMING__PREMIUM_FIRE_DISTANCE
  1798.                     || _premium_count >= AIMING__PREMIUM_EXCEED_LIMIT
  1799.                     && d < AIMING__PREMIUM_FIRE_DISTANCE_MORE)
  1800.                 myDamage = BULLET__PREMIUM_DAMAGE;
  1801.             else
  1802.                 myDamage = BULLET__REGULAR_DAMAGE;
  1803.             if ((tank.getCrewHealth() <= myDamage || tank.getHullDurability() <= myDamage)
  1804.                     && d < minimum_distance
  1805.                     && (getBulletFlyToTank(world, tank) == null)) {
  1806.                 minimum_distance = d;
  1807.                 MyStrategy._enemy[_i] = tank.getId();
  1808.                 MyStrategy.team_why_targets[_i] = WhyTarget.low_hp;
  1809.             }
  1810.         }
  1811.     }
  1812.  
  1813.     private void aiSpotLowerHPEnemy(Tank self, World world) {
  1814.         double minimum_distance = 2000;// find closer!
  1815.         Tank[] all_tanks = world.getTanks();
  1816.         /*
  1817.          * and no visible enemies
  1818.          */
  1819.         // no visible tanks -> select somebody other with minimum hp!
  1820.         for (int i = 0; i < all_tanks.length; i++) {
  1821.             Tank tank = all_tanks[i];
  1822.             if (tank.isTeammate() || !isTankAlive(tank))
  1823.                 continue;
  1824.             double hp = 100 * tank.getCrewHealth() / tank.getCrewMaxHealth();
  1825.             double arm = 100 * tank.getHullDurability()
  1826.                     / tank.getHullMaxDurability();
  1827.             double d = tank.getDistanceTo(self);
  1828.             if (d < minimum_distance && (hp < 60 || arm < 60)) {
  1829.                 minimum_distance = d;
  1830.                 MyStrategy._enemy[_i] = tank.getId();
  1831.                 MyStrategy.team_why_targets[_i] = WhyTarget.lower_hp;
  1832.             }
  1833.         }
  1834.     }
  1835.  
  1836.     private static final boolean isTankAlive(Tank t) {
  1837.         return t.getCrewHealth() > 0 && t.getHullDurability() > 0;
  1838.     }
  1839.  
  1840.     private void aiSpotCloserVisible(Tank self, World world) {
  1841.         Tank[] all_tanks = world.getTanks();
  1842.         double max_distance_to_enemy = 2000;
  1843.         // check distance to current enemy
  1844.         if (MyStrategy._enemy[_i] != -1)
  1845.             for (int i = 0; i < all_tanks.length; i++) {
  1846.                 Tank tank = all_tanks[i];
  1847.                 if (tank.isTeammate() || !isTankAlive(tank))
  1848.                     continue;
  1849.                 if (MyStrategy._enemy[_i] == tank.getId()) {
  1850.                     max_distance_to_enemy = tank.getDistanceTo(self);
  1851.                     break;
  1852.                 }
  1853.             }
  1854.         // find closer visible
  1855.         for (int i = 0; i < all_tanks.length; i++) {
  1856.             Tank tank = all_tanks[i];
  1857.             if (tank.isTeammate() || !isTankAlive(tank))
  1858.                 continue;
  1859.             double d = tank.getDistanceTo(self);
  1860.             if (d < max_distance_to_enemy
  1861.                     && wayIsClearForShoot(d, tank.getX(), tank.getY(),
  1862.                             self.getX(), self.getY(), world)) {
  1863.                 max_distance_to_enemy = d;
  1864.                 MyStrategy._enemy[_i] = tank.getId();
  1865.                 MyStrategy.team_why_targets[_i] = WhyTarget.closer_visible;
  1866.             }
  1867.         }
  1868.     }
  1869.  
  1870.     private void aiSpotCloserEnemy(Tank self, World world) {
  1871.         double max_distance_to_enemy = 450;
  1872.         if (!isMyEnemyVisible(world, self)) {
  1873.             max_distance_to_enemy = 2000;
  1874.         }
  1875.         Tank[] all_tanks = world.getTanks();
  1876.         for (int i = 0; i < all_tanks.length; i++) {
  1877.             Tank tank = all_tanks[i];
  1878.             if (tank.isTeammate() || !isTankAlive(tank))
  1879.                 continue;
  1880.             double d = tank.getDistanceTo(self);
  1881.             if (d < max_distance_to_enemy
  1882.                     && wayIsClearForShoot(d, tank.getX(), tank.getY(),
  1883.                             self.getX(), self.getY(), world)) {
  1884.                 max_distance_to_enemy = d;
  1885.                 MyStrategy._enemy[_i] = tank.getId();
  1886.                 MyStrategy.team_why_targets[_i] = WhyTarget.closer_range;
  1887.             }
  1888.         }
  1889.     }
  1890.  
  1891.     private void aiSpotTargetingMeEnemy(Tank self, World world) {
  1892.  
  1893.         double max_distance_to_enemy = TEAM__CLOSER_ENEMY_ASSIST_RANGE;
  1894.         /*
  1895.          * find targeting enemy if my enemy not shooting me or far than other
  1896.          * targeting get distance of current enemy if he targets me
  1897.          */
  1898.         if (MyStrategy._enemy[_i] != -1) {
  1899.             Tank[] all_tanks = world.getTanks();
  1900.             for (int i = 0; i < all_tanks.length; i++) {
  1901.                 Tank tank = all_tanks[i];
  1902.                 if (tank.isTeammate() || !isTankAlive(tank))
  1903.                     continue;
  1904.                 if (MyStrategy._enemy[_i] == tank.getId()) {
  1905.                     double a = Math.abs(tank.getTurretAngleTo(self));
  1906.                     double d = tank.getDistanceTo(self);
  1907.                     double maxa_ = getObjAngleOnDistance(d, CONFIG__MY_WIDTH);
  1908.                     if (a < maxa_
  1909.                             && wayIsClearForTargeting(self, d, _next_x,
  1910.                                     _next_y, tank.getX(), tank.getY(), world)
  1911.                             && d < max_distance_to_enemy)
  1912.                         max_distance_to_enemy = d; //
  1913.                 }
  1914.             }
  1915.         }
  1916.         /*
  1917.          * select other targeting
  1918.          */
  1919.         Tank targeting_tank = getCloserOfTargetingTankEnemy(self, world,
  1920.                 max_distance_to_enemy);
  1921.         if (targeting_tank != null) {
  1922.             max_distance_to_enemy = self.getDistanceTo(targeting_tank);
  1923.             MyStrategy._enemy[_i] = targeting_tank.getId();
  1924.             MyStrategy.team_why_targets[_i] = WhyTarget.target_me;
  1925.         }
  1926.         if (max_distance_to_enemy < TEAM__CLOSER_ENEMY_ASSIST_RANGE) {
  1927.             MyStrategy.team_why_targets[_i] = WhyTarget.target_me_in_closer_range;
  1928.         }
  1929.     }
  1930.  
  1931.     private static final boolean is_angle_sharp(final double alfa) {
  1932.         double a = Math.abs(alfa);
  1933.         if (a > PI / 5 && a < (PI - PI / 5))
  1934.             return false;
  1935.         return true;
  1936.     }
  1937.  
  1938.     private void aiSpotRotatedToMeEnemy(Tank self, World world) {
  1939.         double max_distance_to_enemy = 2000;
  1940.         Tank[] all_tanks = world.getTanks();
  1941.         for (int i = 0; i < all_tanks.length; i++) {
  1942.             Tank tank = all_tanks[i];
  1943.             if (tank.isTeammate() || !isTankAlive(tank))
  1944.                 continue;
  1945.             double a = tank.getAngleTo(self);
  1946.             double d = tank.getDistanceTo(self);
  1947.             if (is_angle_sharp(a)
  1948.                     && d < max_distance_to_enemy
  1949.                     && wayIsClearForShootObst(d, tank.getX(), tank.getY(),
  1950.                             self.getX(), self.getY(), world)) {
  1951.                 max_distance_to_enemy = d;
  1952.                 MyStrategy._enemy[_i] = tank.getId();
  1953.                 MyStrategy.team_why_targets[_i] = WhyTarget.turned_to_me;
  1954.             }
  1955.  
  1956.         }
  1957.     }
  1958.  
  1959.     private boolean aiTurnToEnemy(Tank self, Tank enemyTank, Move move) {
  1960.         boolean result_im_turn = false;
  1961.  
  1962.         double angle_to_enemy = self.getAngleTo(enemyTank);
  1963.         double turn_angle;
  1964.         double enemyDist = self.getDistanceTo(enemyTank);
  1965.         if (enemyDist < TURNING__CLOSER_MAX_DISTANCE)
  1966.             turn_angle = TURNING__MIN_TURN_TO_ENEMY_ANGLE;
  1967.         else
  1968.             turn_angle = TURNING__MIN_TURN_TO_ENEMY_ANGLE_ON_DIST;
  1969.         if ((angle_to_enemy > 0 && angle_to_enemy > turn_angle)
  1970.                 || (angle_to_enemy < 0 && angle_to_enemy > -turn_angle
  1971.                         + TURNING__ANGLE_ACCURACY)
  1972.  
  1973.         ) {
  1974.             doTurnRightMax(move);
  1975.             result_im_turn = true;
  1976.         } else
  1977.             if ((angle_to_enemy > 0 && angle_to_enemy < turn_angle
  1978.                     - TURNING__ANGLE_ACCURACY)
  1979.                     || (angle_to_enemy < 0 && angle_to_enemy < -turn_angle)) {
  1980.                 doTurnLeftMax(move);
  1981.                 result_im_turn = true;
  1982.             }
  1983.  
  1984.         if (result_im_turn)
  1985.             MyStrategy.team_state[_i] = DriveSE.ds_rotate_to_enemy;
  1986.         // ngc.drawString("rotate", _x, _y);
  1987.         return result_im_turn;
  1988.     }
  1989.  
  1990.     private void createPathToPoint(final double pX, final double pY,
  1991.             World world, Tank self) {
  1992.         double myX = self.getX();
  1993.         double myY = self.getY();
  1994.         double vx = pX - myX;
  1995.         double vy = pY - myY;
  1996.         double dist = self.getDistanceTo(pX, pY);
  1997.         Tank[] tanks = world.getTanks();
  1998.         int tc = tanks.length;
  1999.         double min_dist = 2000;
  2000.         boolean sectorFinded = false;
  2001.         double distance = 80;
  2002.         double newPx = -1, newPy = -1;
  2003.         for (int i = 0; i < tc; i++) {
  2004.             double tdist = self.getDistanceTo(tanks[i]);
  2005.             if (tdist >= dist - 15 || tdist < 15)
  2006.                 continue;
  2007.             double gamma = getObjAngleOnDistance(tdist - CONFIG__MY_WIDTH / 2,
  2008.                     CONFIG__MY_WIDTH / 2);
  2009.             double tX = tanks[i].getX();
  2010.             double tY = tanks[i].getY();
  2011.             double fi = getMaxAngleOfUnitOnDist(myX, myY, tanks[i], tX, tY);
  2012.             double vxt = tX - myX;
  2013.             double vyt = tY - myY;
  2014.             double alfa = getVectorAngle(vx, vxt, vy, vyt);
  2015.             if (alfa - fi <= gamma && tdist < min_dist) {
  2016.                 double tank_dist = self.getDistanceTo(tanks[i]);
  2017.                 double newPointDist = tank_dist - distance;
  2018.                 double VTx = tX - myX;
  2019.                 double VTy = tY - myY;
  2020.                 double sgn_alfa = getVectorAngleWithSign(vx, VTx, vy, VTy);
  2021.                 double normaVT = Math.sqrt(VTx * VTx + VTy * VTy);
  2022.                 double newPointVx = VTx * newPointDist / normaVT;
  2023.                 double newPointVy = VTy * newPointDist / normaVT;
  2024.                 double newPointX = myX + newPointVx;
  2025.                 double newPointY = myY + newPointVy;
  2026.                 // left vector
  2027.                 double ortoLeftX = VTy * distance / normaVT;
  2028.                 double ortoLeftY = -VTx * distance / normaVT;
  2029.                 // right vector
  2030.                 double ortoRightX = -VTy * distance / normaVT;
  2031.                 double ortoRightY = VTx * distance / normaVT;
  2032.                 // left point
  2033.                 double leftPointX = newPointX + ortoLeftX;
  2034.                 double leftPointY = newPointY + ortoLeftY;
  2035.                 // right point
  2036.                 double rightPointX = newPointX + ortoRightX;
  2037.                 double rightPointY = newPointY + ortoRightY;
  2038.                 if (sgn_alfa > 0
  2039.                         && isClearOfTanksSector(self, leftPointX, leftPointY,
  2040.                                 world, 0)) {
  2041.                     newPx = leftPointX;
  2042.                     newPy = leftPointY;
  2043.                     sectorFinded = true;
  2044.                 } else
  2045.                     if (isClearOfTanksSector(self, rightPointX, rightPointY,
  2046.                             world, 0)) {
  2047.                         newPx = rightPointX;
  2048.                         newPy = rightPointY;
  2049.                         sectorFinded = true;
  2050.                     }
  2051.                 if (sectorFinded) {
  2052.                     _path[0].x = newPx;
  2053.                     _path[0].y = newPy;
  2054.                     min_dist = tdist;
  2055.                 }
  2056.             }
  2057.         }
  2058.         Obstacle[] obst = world.getObstacles();
  2059.         int oc = obst.length;
  2060.         distance = 150;// TODO 150
  2061.         newPx = -1;// TODO sector2_finded=false;
  2062.         newPy = -1;
  2063.         boolean sector2Finded = false;
  2064.         for (int i = 0; i < oc; i++) {
  2065.             double tdist = self.getDistanceTo(obst[i]);
  2066.             if (tdist >= dist - 15 || tdist < 15)
  2067.                 continue;
  2068.             double gamma = getObjAngleOnDistance(tdist - CONFIG__MY_WIDTH / 2,
  2069.                     CONFIG__MY_WIDTH / 2);
  2070.             double tX = obst[i].getX();
  2071.             double tY = obst[i].getY();
  2072.             double fi = getMaxAngleOfUnitOnDist(myX, myY, obst[i], tX, tY);
  2073.             double vxt = tX - myX;
  2074.             double vyt = tY - myY;
  2075.             double alfa = getVectorAngle(vx, vxt, vy, vyt);
  2076.             if (alfa - fi <= gamma && tdist < min_dist) {
  2077.                 double tank_dist = self.getDistanceTo(obst[i]);
  2078.                 double newPointDist = tank_dist - distance;
  2079.                 double VTx = tX - myX;
  2080.                 double VTy = tY - myY;
  2081.                 double sgn_alfa = getVectorAngleWithSign(vx, VTx, vy, VTy);
  2082.                 double normaVT = Math.sqrt(VTx * VTx + VTy * VTy);
  2083.                 double newPointVx = VTx * newPointDist / normaVT;
  2084.                 double newPointVy = VTy * newPointDist / normaVT;
  2085.                 double newPointX = myX + newPointVx;
  2086.                 double newPointY = myY + newPointVy;
  2087.                 // left vector
  2088.                 double ortoLeftX = VTy * distance / normaVT;
  2089.                 double ortoLeftY = -VTx * distance / normaVT;
  2090.                 // right vector
  2091.                 double ortoRightX = -VTy * distance / normaVT;
  2092.                 double ortoRightY = VTx * distance / normaVT;
  2093.                 // left point
  2094.                 double leftPointX = newPointX + ortoLeftX;
  2095.                 double leftPointY = newPointY + ortoLeftY;
  2096.                 // right point
  2097.                 double rightPointX = newPointX + ortoRightX;
  2098.                 double rightPointY = newPointY + ortoRightY;
  2099.                 if (sgn_alfa > 0
  2100.                         && isClearOfTanksSector(self, leftPointX, leftPointY,
  2101.                                 world, 0)) {
  2102.                     newPx = leftPointX;
  2103.                     newPy = leftPointY;
  2104.                     sector2Finded = true;
  2105.                 } else
  2106.                     if (isClearOfTanksSector(self, rightPointX, rightPointY,
  2107.                             world, 0)) {
  2108.                         newPx = rightPointX;
  2109.                         newPy = rightPointY;
  2110.                         sector2Finded = true;
  2111.                     }
  2112.                 if (sector2Finded) {
  2113.                     _path[0].x = newPx;
  2114.                     _path[0].y = newPy;
  2115.                     min_dist = tdist;
  2116.                 }
  2117.             }
  2118.         }
  2119.  
  2120.         if (!(sectorFinded || sector2Finded)) {
  2121.             _path[0].x = pX;
  2122.             _path[0].y = pY;
  2123.         }
  2124.     }
  2125.  
  2126.     private void doCalcCoordinates(Tank self, World world) {
  2127.         _hp = self.getCrewHealth();
  2128.         _armor = self.getHullDurability();
  2129.         _x = self.getX();
  2130.         _y = self.getY();
  2131.         _vx = self.getSpeedX();
  2132.         _vy = self.getSpeedY();
  2133.         _dv_dt_x = _vx - _last_v_x;
  2134.         _dv_dt_y = _vy - _last_v_y;
  2135.         _last_v_x = _vx;
  2136.         _last_v_y = _vy;
  2137.         _next_x = _x + _vx + _dv_dt_x;
  2138.         _next_y = _y + _vy + _dv_dt_y;
  2139.         _premium_count = self.getPremiumShellCount();
  2140.         _tik = world.getTick();
  2141.         doCountHealthyTanks(world.getTanks());
  2142.  
  2143.         MyStrategy.team_shoot_ready[_i] = self.getRemainingReloadingTime() == 0;
  2144.         if (self.getRemainingReloadingTime() == self.getReloadingTime() - 1)
  2145.             MyStrategy._team_shoots_count++;// shoot happens :)
  2146.         if (!(MyStrategy.team_state[_i] == DriveSE.ds_resurrect))
  2147.             MyStrategy.team_state[_i] = DriveSE.ds_stand;
  2148.         if (MyStrategy.team_roles[_i] == role.leader) {
  2149.             if (!_leader_enemy_teams_counted) {
  2150.                 teams_count = countEnemyTeams(world.getTanks());
  2151.                 _leader_enemy_teams_counted = true;
  2152.             }
  2153.             leaderDoCountEnemyTeamAlive(world.getTanks());
  2154.             MyStrategy._can_shoot_time++;
  2155.             doCountHealthyTeamTanks(world.getTanks());
  2156.  
  2157.             if (MyStrategy.team_1_alive_count < 2
  2158.                     && MyStrategy.team_2_alive_count < 2
  2159.                     && MyStrategy._team_healthy_tanks > 1
  2160.                     || MyStrategy._team_healthy_tanks > MyStrategy.team_1_alive_count
  2161.                             + MyStrategy.team_2_alive_count)
  2162.                 MyStrategy._team_rush = true;
  2163.             else
  2164.                 MyStrategy._team_rush = false;
  2165.             if (!MyStrategy._team_rush) {
  2166.                 MyStrategy._team_rush = isEnemiesInPoint(world.getTanks(),
  2167.                         self.getX(), self.getY(), 400)||
  2168.                         (MyStrategy._team_premium_count>MyStrategy.enemy_premium_count&&MyStrategy._team_healthy_tanks >= MyStrategy.team_1_alive_count
  2169.                                 + MyStrategy.team_2_alive_count);
  2170.             }
  2171.             MyStrategy._team_ready_for_shoot = true;
  2172.             if (MyStrategy._team_shoots_count >= MyStrategy._team_healthy_tanks) {
  2173.                 MyStrategy._team_shoots_count = 0;
  2174.                 // N shoots happend - > wait for other reloading
  2175.             }
  2176.             if (MyStrategy._team_shoots_count == 0) {
  2177.                 for (int o = 0; o < MyStrategy.team_shoot_ready.length; o++) {
  2178.                     if (MyStrategy.team_shoot_ready[o] != true) {
  2179.                         MyStrategy._team_ready_for_shoot = false;
  2180.                         break;
  2181.                     }
  2182.                 }
  2183.             }
  2184.             if (MyStrategy._can_shoot_time > MyStrategy._team_healthy_tanks
  2185.                     * TEAM__SHOOT_TIME_DELTA)
  2186.                 MyStrategy._can_shoot_time = 0;
  2187.         }
  2188.         if (_hp * _armor == 0) {
  2189.             if (MyStrategy.team_roles[_i] == role.leader) {
  2190.                 MyStrategy.team_roles[_i] = role.unit;
  2191.                 MyStrategy.team_roles[teamGetFirstAliveMemberIndex()] = role.leader;
  2192.             }
  2193.             MyStrategy.team_shoot_ready[_i] = true;
  2194.             MyStrategy.team_state[_i] = DriveSE.ds_died;
  2195.             double died_x = _x;
  2196.             double died_y = _y;
  2197.             boolean sector_finded = false;
  2198.             Bonus[] bonuses = world.getBonuses();
  2199.             for (int o = 0; o < bonuses.length; o++) {
  2200.                 if (_hp > 0 && bonuses[o].getType() == BonusType.MEDIKIT)
  2201.                     continue;
  2202.                 if (_armor > 0 && bonuses[o].getType() == BonusType.REPAIR_KIT)
  2203.                     continue;
  2204.                 if (bonuses[o].getType() == BonusType.AMMO_CRATE)
  2205.                     continue;
  2206.                 double dist = self.getDistanceTo(bonuses[o]);
  2207.                 if (dist < TEAM__HELP_RESURRECT_DISTANCE_TO_BONUS) {
  2208.                     // help
  2209.                     double bonus_x = bonuses[o].getX();
  2210.                     double bonus_y = bonuses[o].getY();
  2211.                     if (!wayIsClear(dist, bonus_x, bonus_y, died_x, died_y,
  2212.                             world))
  2213.                         continue;
  2214.                     double BTx = died_x - bonus_x;
  2215.                     double BTy = died_y - bonus_y;
  2216.                     double norma = Math.sqrt(BTx * BTx + BTy * BTy);
  2217.                     BTx = BTx * 90 / norma;
  2218.                     BTy = BTy * 90 / norma;
  2219.                     double Nx = died_x + BTx;
  2220.                     double Ny = died_y + BTy;
  2221.                     if (!isOutWorldPointRadius(Nx, Ny, 20)) {
  2222.                         sector_finded = true;
  2223.                         break;
  2224.  
  2225.                     }
  2226.  
  2227.                 }
  2228.             }
  2229.             if (sector_finded)
  2230.                 MyStrategy.team_help[_i] = helping.resurrect_me_please;
  2231.             else
  2232.                 MyStrategy.team_help[_i] = helping.no_thanks;
  2233.         }
  2234.  
  2235.         else
  2236.             if (MyStrategy.team_help[_i] == helping.resurrect_me_please)
  2237.                 MyStrategy.team_help[_i] = helping.no_thanks;
  2238.         /*
  2239.          * else{ if (MyStrategy.team_roles[_i] == role.leader)
  2240.          * MyStrategy.team_help[_i] = helping.assist_me_please; }
  2241.          */
  2242.         if (MyStrategy._team_healthy_tanks > 1)
  2243.             _i_can_shoot = MyStrategy._can_shoot_time > TEAM__SHOOT_TIME_DELTA
  2244.                     * _i
  2245.                     && MyStrategy._can_shoot_time < TEAM__SHOOT_TIME_DELTA
  2246.                             * (_i + 1);
  2247.         else
  2248.             _i_can_shoot = true;
  2249.  
  2250.         MyStrategy._team_ready_for_shoot = true;
  2251.         _i_can_shoot = MyStrategy._team_ready_for_shoot && _i_can_shoot;
  2252.  
  2253.     }
  2254.  
  2255.     private void doCatchBomb(Move move, double fi, Tank tank, Shell bomb) {
  2256.         /*
  2257.          * bc==c===ac tank! ||======|| b===0====a ==> ||======|| bd==d===ad
  2258.          */
  2259.         double BVx = bomb.getSpeedX();
  2260.         double BVy = bomb.getSpeedY();
  2261.         double myVx = tank.getSpeedX();
  2262.         double myVy = tank.getSpeedY();
  2263.         double myV = Math.sqrt(myVx * myVx + myVy * myVy);
  2264.         if (myV > DODGE__ADJUST_SMALL_VELOCITY) {
  2265.             double BmyVa = PI / 2 - getVectorAngle(BVx, myVx, BVy, myVy);
  2266.             if (BmyVa > 0)
  2267.                 doMoveBack(move);
  2268.             else
  2269.                 doMoveForward(move);
  2270.         } else {
  2271.             double A = tank.getAngle();
  2272.             double tVx = Math.cos(A);
  2273.             double tVy = Math.sin(A);
  2274.             double BTa = PI / 2 - getVectorAngle(BVx, tVx, BVy, tVy);
  2275.             if (BTa > 0)
  2276.                 doMoveBack(move);
  2277.             else
  2278.                 doMoveForward(move);
  2279.         }
  2280.     }
  2281.  
  2282.     private void doCountHealthyTanks(Tank[] all_tanks) {
  2283.  
  2284.         _enemy_healthy_tanks = 0;
  2285.         for (int i = 0; i < all_tanks.length; ++i) {
  2286.             Tank tank = all_tanks[i];
  2287.  
  2288.             if (tank.isTeammate())
  2289.                 continue;
  2290.             if (tank.getCrewHealth() > 0 && tank.getHullDurability() > 0)
  2291.                 _enemy_healthy_tanks++;
  2292.         }
  2293.     }
  2294.  
  2295.     private void doCountHealthyTeamTanks(Tank[] all_tanks) {
  2296.         MyStrategy._team_healthy_tanks = 0;
  2297.         MyStrategy._team_premium_count = 0;
  2298.         for (int i = 0; i < all_tanks.length; ++i) {
  2299.             if (all_tanks[i].isTeammate()
  2300.                     && (all_tanks[i].getCrewHealth() > 0/*
  2301.                                                          * CONFIG__MY_MAX_HP
  2302.                                                          * BONUS__NEED_HEALTH_PRECENT_EXTRA_SUPER
  2303.                                                          */&& all_tanks[i]
  2304.                             .getHullDurability() > 0/*
  2305.                                                      * CONFIG__MY_MAX_ARM
  2306.                                                      * BONUS__NEED_ARMOR_PRECENT_EXTRA_SUPER
  2307.                                                      */)) {
  2308.                 MyStrategy._team_healthy_tanks++;MyStrategy._team_premium_count+=all_tanks[i].getPremiumShellCount();
  2309.             }
  2310.         }
  2311.     }
  2312.  
  2313.     private void doDodge(Shell bomb, Tank me, Move move, World world) {
  2314.         double H = 10;
  2315.         double Bx = bomb.getX();
  2316.         double By = bomb.getY();
  2317.         double BVx = bomb.getSpeedX();
  2318.         double BVy = bomb.getSpeedY();
  2319.         double Tx = me.getX();
  2320.         double Ty = me.getY();
  2321.         double DIST = getDistancePointToLine(Bx, By, BVx, BVy, Tx, Ty);
  2322.         double BD = bomb.getHeight() / 2;
  2323.         double D = Math.abs(DIST - BD);
  2324.         double fi = getTankAngleToLine(me, BVx, BVy);
  2325.         double bomb_dist = me.getDistanceTo(bomb);
  2326.         double myX = me.getX();
  2327.         double myY = me.getY();
  2328.  
  2329.         if (isOnCorner(myX, myY)) {
  2330.             doDodgeEscape(move, fi, me, bomb, world);
  2331.         } else {
  2332.             if (Math.abs(fi) > DODGE__RICOCHETE_ANGLE + DODGE__TURN_ANGLE_DELTA) {
  2333.                 if (D > H
  2334.                         && bomb_dist < DODGE__MAX_DISTANCE_TO_AVOID_BY_TURNING
  2335.                         && Math.abs(fi) < DODGE__MIN_ESCAPE_ANGLE) {
  2336.                     doTurnDodge(move, fi);
  2337.                 } else {
  2338.                     doDodgeEscape(move, fi, me, bomb, world);
  2339.                 }
  2340.             } else {
  2341.                 if (Math.abs(fi) > DODGE__RICOCHETE_ANGLE) {
  2342.                     doTurnDodge(move, fi);
  2343.                 } else {
  2344.  
  2345.                     /*
  2346.                      * some mathematics...
  2347.                      */
  2348.  
  2349.                     double BV = Math.sqrt(BVx * BVx + BVy * BVy);
  2350.                     double b_fly_t = bomb_dist / BV;
  2351.                     TankCoords t_c = new TankCoords(me);
  2352.                     double TVx = t_c.cosA;
  2353.                     double TVy = t_c.sinA;
  2354.                     double fi_TB = getVectorAngle(TVx, BVx, TVy, BVy);
  2355.                     boolean bomb_from_forward = (fi_TB > PI / 2);
  2356.  
  2357.                     double my_velocity = t_c.getVelocityForward();
  2358.                     double my_dV_dt;
  2359.                     double left_corner_x, left_corner_y, right_corner_x, right_corner_y;
  2360.                     if (bomb_from_forward) {
  2361.                         my_dV_dt = DODGE__MAX_DV_DT_FORWARD;
  2362.                         left_corner_x = t_c.Xlf;
  2363.                         left_corner_y = t_c.Ylf;
  2364.                         right_corner_x = t_c.Xrf;
  2365.                         right_corner_y = t_c.Yrf;
  2366.                     } else {
  2367.                         my_dV_dt = DODGE__MAX_DV_DT_zBACK;
  2368.                         left_corner_x = t_c.Xrb;
  2369.                         left_corner_y = t_c.Yrb;
  2370.                         right_corner_x = t_c.Xlb;
  2371.                         right_corner_y = t_c.Ylb;
  2372.                     }
  2373.                     boolean bomb_from_left_side = fi > 0;
  2374.                     boolean bomb_from_right_side = !bomb_from_left_side;
  2375.                     double dist_to_drive = my_velocity * b_fly_t + my_dV_dt
  2376.                             * b_fly_t * b_fly_t / 2;
  2377.                     double my_corner_x, my_corner_y;
  2378.                     if (bomb_from_left_side) {
  2379.                         my_corner_x = left_corner_x + TVx * dist_to_drive;
  2380.                         my_corner_y = left_corner_y + TVy * dist_to_drive;
  2381.                     } else {
  2382.                         my_corner_x = right_corner_x + TVx * dist_to_drive;
  2383.                         my_corner_y = right_corner_y + TVy * dist_to_drive;
  2384.                     }
  2385.                     double BVCx = my_corner_x - Bx;
  2386.                     double BVCy = my_corner_y - By;
  2387.  
  2388.                     double bullet_angle_to_corner = getVectorAngleWithSign(BVx,
  2389.                             BVCx, BVy, BVCy);
  2390.  
  2391.                     boolean corner_in_left_side_of_bullet = (bullet_angle_to_corner < 0);
  2392.                     boolean corner_in_right_side_of_bullet = !corner_in_left_side_of_bullet;
  2393.  
  2394.                     boolean i_can_catch_this_bomb = ((bomb_from_left_side && corner_in_left_side_of_bullet) || (bomb_from_right_side && corner_in_right_side_of_bullet));
  2395.                     /*
  2396.                      * mathematics ends! ^_^
  2397.                      */
  2398.                     if (
  2399.  
  2400.                     bomb.getType() != ShellType.PREMIUM
  2401.                             && i_can_catch_this_bomb
  2402.  
  2403.                     )
  2404.                         doCatchBomb(move, fi, me, bomb);
  2405.                     else
  2406.                         if (Math.abs(fi) > DODGE__MIN_ESCAPE_ANGLE) {
  2407.                             doDodgeEscape(move, fi, me, bomb, world);
  2408.                         } else {
  2409.                             doTurnToDodgeEscape(move, fi);
  2410.                         }
  2411.                 }
  2412.             }
  2413.         }
  2414.     }
  2415.  
  2416.     private void doDodgeEscape(Move move, final double fi, Tank tank,
  2417.             Shell bomb, World world) {
  2418.         /*
  2419.          * bc==c===ac tank! ||======|| b===0====a ==> ||======|| bd==d===ad
  2420.          */
  2421.         TankCoords tank_coords = new TankCoords(tank);
  2422.         double W = tank_coords.W;
  2423.         double tVx = tank_coords.cosA;
  2424.         double tVy = tank_coords.sinA;
  2425.         double Xa = tank_coords.Xf;
  2426.         double Ya = tank_coords.Yf;
  2427.         double Xb = tank_coords.Xb;
  2428.         double Yb = tank_coords.Yb;
  2429.         double dVx = tank.getSpeedX();
  2430.         double dVy = tank.getSpeedY();
  2431.         double dVa = getVectorAngle(dVx, tVx, dVy, tVy);
  2432.         double dV = Math.sqrt(dVx * dVx + dVy * dVy) * Math.cos(dVa);
  2433.         double Da = DODGE__ADJUST_VELOCITY_COEFF
  2434.                 * dV
  2435.                 + getDistancePointToLine(bomb.getX(), bomb.getY(),
  2436.                         bomb.getSpeedX(), bomb.getSpeedY(), Xa, Ya);
  2437.         double Db = DODGE__ADJUST_DRIVE_BACK_COEFF
  2438.                 * getDistancePointToLine(bomb.getX(), bomb.getY(),
  2439.                         bomb.getSpeedX(), bomb.getSpeedY(), Xb, Yb);
  2440.  
  2441.         if (Da > Db) {
  2442.             double nextx = Xa + (W / 5) * tVx;
  2443.             double nexty = Ya + (W / 5) * tVy;
  2444.             if (isClearToDriveSector(nextx, nexty, world))
  2445.                 doMoveForward(move);
  2446.             else {
  2447.  
  2448.                 doMoveBack(move);
  2449.                
  2450.             }
  2451.         } else {
  2452.             double nextx = Xb - (W / 5) * tVx;
  2453.             double nexty = Yb - (W / 5) * tVy;
  2454.             if (isClearToDriveSector(nextx, nexty, world))
  2455.                 doMoveBack(move);
  2456.             else {
  2457.  
  2458.                 doMoveForward(move);
  2459.                
  2460.             }
  2461.         }
  2462.  
  2463.     }
  2464.  
  2465.     private void doDriveRoundLeftBack(Move move, final double d) {
  2466.         move.setRightTrackPower(-1);
  2467.         if (d < DRIVE__ADJUST_MIN_DISTANCE)
  2468.             move.setLeftTrackPower(DRIVE__ADJUST_TURN_DIFFERENCE_MAX);
  2469.         else
  2470.             move.setLeftTrackPower(-driveCoeff(d)/**
  2471.              *
  2472.              *
  2473.              *
  2474.              *
  2475.              *
  2476.              *
  2477.              *
  2478.              *
  2479.              *
  2480.              *
  2481.              *
  2482.              *
  2483.              *
  2484.              *
  2485.              *
  2486.              *
  2487.              *
  2488.              *
  2489.              *
  2490.              *
  2491.              *
  2492.              *
  2493.              *
  2494.              *
  2495.              *
  2496.              *
  2497.              *
  2498.              *
  2499.              *
  2500.              *
  2501.              *
  2502.              * DRIVE_ADJUST_TURN_DIFFERENCE_MAX
  2503.              */
  2504.             );
  2505.     }
  2506.  
  2507.     private void doDriveRoundLeftForward(Move move, final double d) {
  2508.         move.setRightTrackPower(1);
  2509.         if (d < DRIVE__ADJUST_MIN_DISTANCE)
  2510.             move.setLeftTrackPower(-1);
  2511.         else
  2512.             move.setLeftTrackPower(driveCoeff(d));
  2513.     }
  2514.  
  2515.     private void doDriveRoundRightBack(Move move, final double d) {
  2516.         move.setLeftTrackPower(-1);
  2517.         if (d < DRIVE__ADJUST_MIN_DISTANCE)
  2518.             move.setRightTrackPower(DRIVE__ADJUST_TURN_DIFFERENCE_MAX);
  2519.         else
  2520.             move.setRightTrackPower(-driveCoeff(d)/**
  2521.              *
  2522.              *
  2523.              *
  2524.              *
  2525.              *
  2526.              *
  2527.              *
  2528.              *
  2529.              *
  2530.              *
  2531.              *
  2532.              *
  2533.              *
  2534.              *
  2535.              *
  2536.              *
  2537.              *
  2538.              *
  2539.              *
  2540.              *
  2541.              *
  2542.              *
  2543.              *
  2544.              *
  2545.              *
  2546.              *
  2547.              *
  2548.              *
  2549.              *
  2550.              *
  2551.              *
  2552.              * DRIVE_ADJUST_TURN_DIFFERENCE_MAX
  2553.              */
  2554.             );
  2555.     }
  2556.  
  2557.     private void doDriveRoundRightForward(Move move, final double d) {
  2558.         move.setLeftTrackPower(1);
  2559.         if (d < DRIVE__ADJUST_MIN_DISTANCE)
  2560.             move.setRightTrackPower(-1);
  2561.         else
  2562.             move.setRightTrackPower(driveCoeff(d));
  2563.     }
  2564.  
  2565.     private void doMoveBack(Move move) {
  2566.         move.setLeftTrackPower(-1);
  2567.         move.setRightTrackPower(-1);
  2568.     }
  2569.  
  2570.     private void doMoveForward(Move move) {
  2571.         move.setLeftTrackPower(1);
  2572.         move.setRightTrackPower(1);
  2573.     }
  2574.  
  2575.     private void doTurnDodge(Move move, final double fi) {
  2576.         if (fi > DODGE__TURN_DODGE_ANGLE_ACCURACY_DELTA)
  2577.             doTurnLeftMax(move);
  2578.         else
  2579.             if (fi < -DODGE__TURN_DODGE_ANGLE_ACCURACY_DELTA)
  2580.                 doTurnRightMax(move);
  2581.     }
  2582.  
  2583.     private void doTurnLeftBackZero(Move move) {
  2584.         move.setLeftTrackPower(-1);
  2585.         move.setRightTrackPower(0);
  2586.     }
  2587.  
  2588.     private void doTurnLeftForwardZero(Move move) {
  2589.         move.setLeftTrackPower(0);
  2590.         move.setRightTrackPower(1);
  2591.     }
  2592.  
  2593.     private void doTurnLeftMax(Move move) {
  2594.         move.setLeftTrackPower(-1);
  2595.         move.setRightTrackPower(1);
  2596.     }
  2597.  
  2598.     private void doTurnRightBackZero(Move move) {
  2599.         move.setLeftTrackPower(0);
  2600.         move.setRightTrackPower(-1);
  2601.     }
  2602.  
  2603.     private void doTurnRightForwardZero(Move move) {
  2604.         move.setLeftTrackPower(1);
  2605.         move.setRightTrackPower(0);
  2606.     }
  2607.  
  2608.     private void doTurnRightMax(Move move) {
  2609.         move.setLeftTrackPower(1);
  2610.         move.setRightTrackPower(-1);
  2611.     }
  2612.  
  2613.     private void doTurnToDodgeEscape(Move move, final double fi) {
  2614.         if (fi > 0)
  2615.             doTurnRightMax(move);
  2616.         else
  2617.             doTurnLeftMax(move);
  2618.     }
  2619.  
  2620.     private void driveToPoint(final double pX, final double pY, Move move,
  2621.             Tank me, final double objH, World world) {
  2622.         double angleToPoint = me.getAngleTo(pX, pY);
  2623.         TankCoords t_c = new TankCoords(me);
  2624.         double myForwardX = t_c.Xf;
  2625.         double myForwardY = t_c.Yf;
  2626.         double myBackX = t_c.Xb;
  2627.         double myBackY = t_c.Yb;
  2628.  
  2629.         boolean isForwardClear = !isOutWorldPointRadius(myForwardX, myForwardY,
  2630.                 20);
  2631.         boolean isBackClear = !isOutWorldPointRadius(myBackX, myBackY, 20);
  2632.  
  2633.         double distp = me.getDistanceTo(pX, pY);
  2634.         double obj_angle = getObjAngleOnDistance(distp, objH);
  2635.         double ride_angle;
  2636.         if (distp <= DRIVE__MIN_DISTANCE_RIDE_ANGLE_INCREASED)
  2637.             ride_angle = obj_angle;
  2638.         else
  2639.             if (distp <= DRIVE__MAX_DISTANCE_RIDE_ANGLE_INCREASED)
  2640.                 ride_angle = obj_angle
  2641.                         + (distp - DRIVE__MIN_DISTANCE_RIDE_ANGLE_INCREASED)
  2642.                         * (DRIVE__MAX_RIDE_ANGLE - obj_angle)
  2643.                         / (DRIVE__MAX_DISTANCE_RIDE_ANGLE_INCREASED - DRIVE__MIN_DISTANCE_RIDE_ANGLE_INCREASED);
  2644.             else
  2645.                 ride_angle = DRIVE__MAX_RIDE_ANGLE;
  2646.         double fi_forward = PI / 2;
  2647.         Rotate r = Rotate.none;
  2648.         if ((angleToPoint > fi_forward) || (angleToPoint < -fi_forward)) {
  2649.             if (!isBackClear)
  2650.                 r = getTankOnBoundRotation(myBackX, myBackY, 100, me);
  2651.         } else
  2652.             if (!isForwardClear)
  2653.                 r = getTankOnBoundRotation(myForwardX, myForwardY, 100, me);
  2654.         switch (r) {
  2655.         case left:
  2656.             if (!isBackClear)
  2657.                 doTurnLeftForwardZero(move);
  2658.             if (!isForwardClear)
  2659.                 doTurnLeftBackZero(move);
  2660.         break;
  2661.         case right:
  2662.             if (!isBackClear)
  2663.                 doTurnRightForwardZero(move);
  2664.             if (!isForwardClear)
  2665.                 doTurnRightBackZero(move);
  2666.         break;
  2667.         case none:
  2668.  
  2669.             if (angleToPoint > ride_angle && angleToPoint < PI - ride_angle
  2670.             // || !(isForwardClear && isBackClear)
  2671.             ) {
  2672.  
  2673.                 // turn!
  2674.                 // on right side
  2675.                 if (angleToPoint > fi_forward) {
  2676.                     // move back
  2677.                     doDriveRoundRightBack(move, distp);
  2678.                 } else {
  2679.                     // move forward
  2680.                     doDriveRoundRightForward(move, distp);
  2681.                 }
  2682.             } else
  2683.                 if ((angleToPoint < -ride_angle)
  2684.                         && (angleToPoint > -PI + ride_angle)) {
  2685.                     // turn!
  2686.                     // on left side
  2687.                     if (angleToPoint < -fi_forward) {
  2688.                         // move back
  2689.                         doDriveRoundLeftBack(move, distp);
  2690.                     } else {
  2691.                         // move forward
  2692.                         doDriveRoundLeftForward(move, distp);
  2693.                     }
  2694.                 } else {
  2695.                     // move!
  2696.                     // log.info("move!!");
  2697.                     if ((angleToPoint > fi_forward)
  2698.                             || (angleToPoint < -fi_forward)) {
  2699.                         // move back
  2700.                         doMoveBack(move);
  2701.                     } else {
  2702.                         // move forward
  2703.                         doMoveForward(move);
  2704.                     }
  2705.                 }
  2706.         }
  2707.     }
  2708.  
  2709.     private Shell getBulletFlyToTank(World world, Tank self) {
  2710.         double min_distance = 2000;
  2711.         Shell[] bombs = world.getShells();
  2712.         int selected_bomb = bombs.length;
  2713.         int countBombs = bombs.length;
  2714.         for (int j = 0; j < countBombs; j++) {
  2715.             // if (bombs[j].getPlayerName().equals(self.getPlayerName()))
  2716.             // continue;
  2717.             double distance_to_bomb = self.getDistanceTo(bombs[j]);
  2718.             // double bomb_Vx = bombs[j].getSpeedX();
  2719.             // double bomb_Vy = bombs[j].getSpeedY();
  2720.             // double bomb_speed = Math
  2721.             // .sqrt(bomb_Vx * bomb_Vx + bomb_Vy * bomb_Vy);
  2722.             // double time_bomb_to_fly = distance_to_bomb / bomb_speed;
  2723.             double myNextX = self.getX();// + self.getSpeedX() *
  2724.                                          // time_bomb_to_fly
  2725.             // + 0.5 * time_bomb_to_fly * time_bomb_to_fly * _dv_dt_x;
  2726.             double myNextY = self.getY();// + self.getSpeedY() *
  2727.                                          // time_bomb_to_fly
  2728.             // + 0.5 * time_bomb_to_fly * time_bomb_to_fly * _dv_dt_y;
  2729.  
  2730.             if ((distance_to_bomb < min_distance)
  2731.                     && isBombForTank(self, bombs[j], myNextX, myNextY)) {
  2732.                 min_distance = distance_to_bomb;
  2733.                 selected_bomb = j;
  2734.             }
  2735.         }
  2736.         if (selected_bomb != bombs.length)
  2737.             return bombs[selected_bomb];
  2738.         else
  2739.             return null;
  2740.     }
  2741.  
  2742.     private Tank getCloserOfTargetingTankEnemy(Tank self, World world,
  2743.             final double max_distance_to_enemy) {
  2744.         Tank[] all_tanks = world.getTanks();
  2745.         double d_max = max_distance_to_enemy;
  2746.         int selected_tank = all_tanks.length;
  2747.         for (int i = 0; i < all_tanks.length; ++i) {
  2748.             Tank tank = all_tanks[i];
  2749.             if (tank.isTeammate() || !isTankAlive(tank))
  2750.                 continue;
  2751.  
  2752.             double a = Math.abs(tank.getTurretAngleTo(self));
  2753.             double d = tank.getDistanceTo(self);
  2754.             double maxa_ = getObjAngleOnDistance(d, CONFIG__MY_WIDTH);
  2755.             if (a < maxa_ && d < d_max) {
  2756.                 d_max = d;// find closer!
  2757.                 selected_tank = i;
  2758.             }
  2759.  
  2760.         }
  2761.         if (selected_tank != all_tanks.length)
  2762.             return all_tanks[selected_tank];
  2763.         else
  2764.             return null;
  2765.     }
  2766.  
  2767.     private void initPathArr() {
  2768.         for (int l = 0; l < this._path.length; l++) {
  2769.             this._path[l] = new Point();
  2770.             this._path[l].x = -1;
  2771.         }
  2772.         for (int l = 0; l < _corners.length; l++) {
  2773.             this._corners[l] = new Point();
  2774.         }
  2775.         // bottom right
  2776.         this._corners[0].x = CONFIG__WORLD_WIDTH - 2 * CORNER__POINT_DIST;
  2777.         this._corners[0].y = CONFIG__WORLD_HEIGHT - CORNER__POINT_DIST;
  2778.         // bottom left
  2779.         this._corners[1].x = 2 * CORNER__POINT_DIST;
  2780.         this._corners[1].y = CONFIG__WORLD_HEIGHT - CORNER__POINT_DIST;
  2781.         // bottom 1
  2782.         this._corners[2].x = CONFIG__WORLD_WIDTH - 4 * CORNER__POINT_DIST;
  2783.         this._corners[2].y = CONFIG__WORLD_HEIGHT - CORNER__POINT_DIST;
  2784.         // bottom 2
  2785.         this._corners[3].x = 4 * CORNER__POINT_DIST;// 4
  2786.         this._corners[3].y = CONFIG__WORLD_HEIGHT - CORNER__POINT_DIST;
  2787.         // bottom 3
  2788.         this._corners[4].x = 6 * CORNER__POINT_DIST;// 6
  2789.         this._corners[4].y = CONFIG__WORLD_HEIGHT - CORNER__POINT_DIST;
  2790.  
  2791.         // top right
  2792.         this._corners[5].x = CONFIG__WORLD_WIDTH - 2 * CORNER__POINT_DIST;
  2793.         this._corners[5].y = CORNER__POINT_DIST;
  2794.  
  2795.         // top left
  2796.         this._corners[6].x = 2 * CORNER__POINT_DIST;
  2797.         this._corners[6].y = CORNER__POINT_DIST;
  2798.  
  2799.         // top 1
  2800.         this._corners[7].x = CONFIG__WORLD_WIDTH - 4 * CORNER__POINT_DIST;
  2801.         this._corners[7].y = CORNER__POINT_DIST;
  2802.  
  2803.         // top 2
  2804.         this._corners[8].x = 4 * CORNER__POINT_DIST;// 4
  2805.         this._corners[8].y = CORNER__POINT_DIST;
  2806.         // top 3
  2807.         this._corners[9].x = 6 * CORNER__POINT_DIST;// 6
  2808.         this._corners[9].y = CORNER__POINT_DIST;
  2809.  
  2810.         // right up1
  2811.         this._corners[10].x = CONFIG__WORLD_WIDTH - CORNER__POINT_DIST;
  2812.         this._corners[10].y = 3 * CORNER__POINT_DIST;
  2813.  
  2814.         // right down2
  2815.         this._corners[11].x = CONFIG__WORLD_WIDTH - CORNER__POINT_DIST;
  2816.         this._corners[11].y = CONFIG__WORLD_HEIGHT - 3 * CORNER__POINT_DIST;
  2817.  
  2818.         // left up1
  2819.         this._corners[12].x = CORNER__POINT_DIST;
  2820.         this._corners[12].y = 3 * CORNER__POINT_DIST;
  2821.  
  2822.         // left down2
  2823.         this._corners[13].x = CORNER__POINT_DIST;
  2824.         this._corners[13].y = CONFIG__WORLD_HEIGHT - 3 * CORNER__POINT_DIST;
  2825.     }
  2826.  
  2827.     private boolean isTeamAssistSameTarget() {
  2828.         long target = MyStrategy._enemy[_i];
  2829.         if (target == -1)
  2830.             return false;
  2831.         for (int k = 0; k < MyStrategy._enemy.length; k++) {
  2832.             if (MyStrategy._enemy[k] != target)
  2833.                 return false;
  2834.         }
  2835.         return true;
  2836.     }
  2837.  
  2838.     private int teamGetFirstAliveMemberIndex() {
  2839.         for (int k = 0; k < MyStrategy.team_state.length; k++) {
  2840.             if (MyStrategy.team_state[k] != DriveSE.ds_died)
  2841.                 return k;
  2842.         }
  2843.         return -1;
  2844.     }
  2845.  
  2846.     @Override
  2847.     public void move(Tank self, World world, Move move) {
  2848.         // ngc.update(world);
  2849.         doCalcCoordinates(self, world);
  2850.         if (_hp * _armor == 0)
  2851.             return;
  2852.         if (b_it_is_a_first_tick) {
  2853.             b_it_is_a_first_tick = _tik < 100;
  2854.             MyStrategy._ids[_i] = self.getId();
  2855.         }
  2856.         b_im_avoiding_bomb = aiDodgeBomb(self, world, move);
  2857.         if (!b_it_is_a_time_to_drive) {
  2858.             b_it_is_a_time_to_drive = _enemy_healthy_tanks <= TACTIC__MAX_ENEMIES_TO_DRIVE;
  2859.             if (!(b_im_avoiding_bomb || MyStrategy.team_state[_i] == DriveSE.ds_resurrect))
  2860.                 b_im_drive_to_corner = aiHideInCorner(self, world);
  2861.         } else
  2862.             b_im_drive_to_corner = false;
  2863.         if (!MyStrategy._team_rush)
  2864.             aiDriveTeammate(self, world);
  2865.         aiDefineBonusPrioritets();
  2866.         if (!(b_im_avoiding_bomb))
  2867.             b_im_goto_bonus = aiGotoBonus(world, self);
  2868.         else
  2869.             b_im_goto_bonus = false;
  2870.  
  2871.         aiSpotRotatedToMeEnemy(self, world);// can change MyEnemy variable
  2872.         aiSpotLowerHPEnemy(self, world);// can change MyEnemy variable
  2873.         aiSpotLowHPEnemy(self, world);// can change MyEnemy variable
  2874.         aiSpotTargetingMeEnemy(self, world);// can change MyEnemy variable
  2875.         aiSpotCloserVisible(self, world);// can change MyEnemy variable
  2876.         aiSpotCloserEnemy(self, world);// can change MyEnemy variable
  2877.  
  2878.         int selected_tank = aiSelectEnemy(self, world);
  2879.  
  2880.         b_i_am_do_manevr = aiDoShootAndManevr(self, world, selected_tank, move);
  2881.         aiDoResurrectTeammate(world, self);
  2882.  
  2883.         if (!b_im_avoiding_bomb
  2884.                 && (!b_i_am_do_manevr || MyStrategy.team_state[_i] == DriveSE.ds_resurrect))
  2885.             b_im_drive_to_path_point = aiDrivePath(self, move, world);
  2886.         else
  2887.             b_im_drive_to_path_point = false;
  2888.         _last_drive_state = MyStrategy.team_state[_i];
  2889.         /*
  2890.          * if (MyStrategy.team_help[_i] == helping.assist_me_please)
  2891.          * ngc.drawString("assist", _x-30, _y-30);
  2892.          * ngc.drawString(MyStrategy.team_why_targets[_i].toString(), _x-10,
  2893.          * _y-10);
  2894.          */
  2895.  
  2896.     }
  2897.  
  2898.     // public static NetGraphClient ngc;
  2899.     @Override
  2900.     public TankType selectTank(int tankIndex, int teamSize) {
  2901.         // ngc = new NetGraphClient("localhost", 8888);
  2902.         initPathArr();
  2903.  
  2904.         _i = tankIndex;
  2905.         if (MyStrategy.team_state == null) {
  2906.             MyStrategy.team_state = new DriveSE[teamSize];
  2907.             MyStrategy.team_why_targets = new WhyTarget[teamSize];
  2908.             MyStrategy.team_help = new helping[teamSize];
  2909.             MyStrategy.team_roles = new role[teamSize];
  2910.             MyStrategy.team_shoot_ready = new boolean[teamSize];
  2911.  
  2912.             MyStrategy._enemy = new long[teamSize];
  2913.             for (int i = 0; i < MyStrategy._enemy.length; i++)
  2914.                 MyStrategy._enemy[i] = -1;
  2915.             for (int i = 0; i < MyStrategy.team_why_targets.length; i++)
  2916.                 MyStrategy.team_why_targets[i] = WhyTarget.no_target;;
  2917.             MyStrategy._ids = new long[teamSize];
  2918.  
  2919.             MyStrategy.team_roles[_i] = role.leader;
  2920.         } else {
  2921.             MyStrategy.team_roles[_i] = role.unit;
  2922.         }
  2923.  
  2924.         return TankType.MEDIUM;
  2925.     }
  2926.  
  2927.     private int whoNeedsHelpInTeam() {
  2928.         for (int k = 0; k < MyStrategy.team_help.length; k++)
  2929.             if (MyStrategy.team_help[k] == helping.assist_me_please)
  2930.                 return k;
  2931.         return _i;
  2932.     }
  2933.  
  2934. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement