Guest User

xelai codetanks bot

a guest
Dec 2nd, 2012
77
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. from math import *
  2. from model.FireType import FireType
  3. from model.TankType import TankType
  4. from model.BonusType import BonusType
  5. from model.ShellType import ShellType
  6. from model.Unit import Unit
  7.  
  8.  
  9. # some geometry for simple interset detection
  10. class Vec2D:
  11.     def __init__(self, x, y):
  12.         self.x = x
  13.         self.y = y
  14.        
  15.     def dot(self, vec2d):
  16.         return self.x*vec2d.x + self.y*vec2d.y
  17.     def squaredLength(self):
  18.         return self.x*self.x + self.y*self.y
  19.    
  20. def intr_line_2_circle(origin, direction, center, squaredRadius):
  21.     diff = Vec2D(origin.x - center.x, origin.y - center.y)
  22.     a0 = diff.squaredLength() - squaredRadius
  23.     a1 = direction.dot(diff)
  24.     discr = a1*a1 - a0
  25.     if discr < 0.0:
  26.         return False
  27.     return True
  28.  
  29. def ray_test_unit_angle(origin, angle, u):
  30.     line_origin = Vec2D(origin.x, origin.y)
  31.     line_dir = Vec2D(cos(angle), sin(angle))
  32.     cir_center = Vec2D(u.x, u.y)
  33.     cir_rr = (u.width*u.width)/4
  34.     return intr_line_2_circle(line_origin,line_dir,cir_center,cir_rr)
  35.  
  36. #def ray_test_unit_point(p1, p2, u):
  37. #    line_origin = Vec2D(origin.x, origin.y)
  38. #    line_dir = Vec2D(cos(angle), sin(angle))
  39. #    cir_center = Vec2D(u.x, u.y)
  40. #    cir_rr = (u.width*u.width + u.height*u.height)/2
  41. #    return intr_line_2_circle(line_origin,line_dir,cir_center,cir_rr)
  42.    
  43. def normalize_angle(angle):
  44.     while angle > pi:
  45.         angle -= 2.0 * pi
  46.  
  47.     while angle < -pi:
  48.         angle += 2.0 * pi
  49.     return angle
  50.  
  51.  
  52. class Line2D:
  53.     def __init__(self, a,b,c):
  54.         self.a = a;
  55.         self.b = b;
  56.         self.c = c;
  57.  
  58. def point_in_rect(p, p1,p2):
  59.     eps = 0.000001
  60.     res = (fabs(p.x -min(p1.x, p2.x)) < eps or min(p1.x, p2.x) <= p.x) \
  61.           and (fabs(max(p1.x, p2.x) - p.x) < eps or max(p1.x, p2.x)>=p.x) \
  62.           and (fabs(p.y - min(p1.y, p2.y)) < eps or min(p1.y, p2.y)<=p.y) \
  63.           and (fabs(max(p1.y, p2.y) - p.y) < eps or max(p1.y, p2.y)>=p.y)
  64.     return res
  65.  
  66. def to_line(p1, p2):
  67.     a = p2.y - p1.y
  68.     b = p1.x - p2.x
  69.     return Line2D(a,b, -a*p1.x - b*p1.y)
  70.  
  71. def is_parallel_line(l1,l2):
  72.     return fabs(l1.a*l2.b - l2.a*l1.b) <=0.00001
  73.  
  74. def is_equal_line(l1,l2):
  75.     is_equal = fabs(l1.a*l2.b - l2.a*l1.b) <=0.00001 \
  76.         and fabs(l1.a*l2.c - l2.a*l1.c) <=0.00001 \
  77.         and fabs(l1.b*l2.c - l2.b*l1.c) <=0.00001
  78.     return is_equal
  79.  
  80. def cross_line(l1, l2, p):
  81.     if is_parallel_line(l1,l2): return 2
  82.     if is_equal_line(l1,l2): return 0
  83.  
  84.     p.x = (l2.b * l1.c - l1.b * l2.c) / (l2.a * l1.b - l1.a * l2.b);
  85.     if (l1.b !=0):
  86.         p.y = (- l1.c - l1.a * p.x) / l1.b
  87.     else:
  88.         p.y = (- l2.c - l2.a * p.x) / l2.b
  89.     return 1
  90.  
  91. def cross_segment_line(p1, p2, l, p):
  92.     t = to_line(p1,p2)
  93.     res = cross_line(l,t,p)
  94.  
  95.     if not point_in_rect(p,p1,p2):res = 0
  96.     return res
  97. #======================== end of geometry
  98. def shell_test_path(shell, startPos, endPos):
  99.     #r = 40
  100.     sx = shell.x + shell.x*cos(shell.angle)
  101.     sy = shell.y + shell.y*sin(shell.angle)
  102.     l = to_line(Vec2D(shell.x, shell.y), Vec2D(sx,sy))
  103.     p = Vec2D(0,0)
  104.     res = cross_segment_line(startPos, endPos, l, p)
  105.     print(res, p.x, p.y)
  106.  
  107. ######################################################################
  108. ######################################################################
  109. ######################################################################
  110. def get_dangerous(x, y, enemy_tanks, shells):
  111.     tank_koeff_dangerous = 0.0
  112.     shell_koeff_dangerous = 0.0
  113.     koeff_dist = 0.0
  114.     koeff_angle = 0.0
  115.     max_dist = hypot(1280, 800)
  116.     for t in enemy_tanks:
  117.         koeff_dist=1-(t.get_distance_to(x,y)/max_dist)
  118.         koeff_angle= cos(t.get_turret_angle_to(x,y))
  119.         #koeff_angle= 1
  120.         tank_koeff_dangerous += koeff_dist*koeff_angle*t.crew_health/t.crew_max_health    
  121.    
  122.     for s in shells:
  123.         koeff_dist=1-(s.get_distance_to(x,y)/max_dist)
  124.         koeff_angle=cos(s.get_angle_to(x,y))
  125.         koeff_angle=1
  126.         shell_koeff_dangerous+= koeff_dist*koeff_angle
  127.    
  128.     return tank_koeff_dangerous*shell_koeff_dangerous      
  129.  
  130. def get_usefullness(x,y, bonuses):
  131.     koeff_dist = 0.0
  132.     max_dist = hypot(1280, 800)
  133.     for b in bonuses:
  134.         koeff_dist+=1-(b.get_distance_to(x,y)/max_dist)
  135.     return koeff_dist
  136.    
  137. def get_min_dangerous_for(x, y, r, enemy_tanks, shells):
  138.     test_points = []
  139.     for ang in range(0,360,45):
  140.         tx = x+r*cos(ang*pi/180)
  141.         ty = y+r*sin(ang*pi/180)
  142.         if (tx < 50) or (tx > 1230):tx=x
  143.  
  144.         if (ty < 50) or (ty > 750):ty = y
  145.            
  146.         dangerous = get_dangerous(tx,ty, enemy_tanks, shells)
  147.         test_points.append([tx,ty,dangerous])
  148.        
  149.     test_points = sorted(test_points, key = lambda dangerous:dangerous[2])
  150.     res = [test_points[0]]+[p for p in test_points[1:] if (fabs(test_points[0][0]-p[0]) > 0.0001) and (fabs(test_points[0][1]-p[1]))>0.0001]
  151.  
  152.     #test center point
  153. ##    cnt = 0
  154. ##    test_unit = create_unit(x,y,80,80)
  155. ##    # cnt = 0 k = 1
  156. ##    for s in shells:
  157. ##        for p in res:
  158. ##            if (p[0]-x > 0.00001) and (p[1]-y > 0.00001)
  159. ##        ray_test_unit_angle(s, s.angle,test_unit)
  160. ##    #print("test points = ", test_points )
  161.     #print("res points = ", res )
  162.     return res
  163.  
  164. ######################################################################
  165. ######################################################################
  166. ######################################################################            
  167.    
  168.    
  169.        
  170.    
  171.    
  172. #=================================================================================
  173.  
  174.  
  175.  
  176. # game info
  177. def get_live_enemy_tanks(tanks):
  178.     return [tank for tank in tanks if (tank.crew_health > 0 and tank.hull_durability > 0) and not tank.teammate]
  179.  
  180. def get_dead_tanks(tanks):
  181.     return [tank for tank in tanks if not (tank.crew_health > 0 and tank.hull_durability > 0)]
  182.  
  183. def get_team_tanks(tanks, me_id):
  184.     return [tank for tank in tanks if (tank.crew_health > 0 and tank.hull_durability > 0) and tank.teammate and tank.id != me_id]
  185.  
  186. def get_enemy_shells(shells, name):
  187.     return [shell for shell in shells if shell.player_name != name]
  188.  
  189. def get_bonus_list(bonuses, bonus_type):
  190.     return [b for b in bonuses if b.type == bonus_type]
  191.  
  192. def get_nearest(target_unit, units):
  193.     if (len(units)):
  194.         min_dist_unit = units[0];
  195.         min_dist = target_unit.get_distance_to_unit(min_dist_unit)
  196.         for u in units[1:]:
  197.             dist = target_unit.get_distance_to_unit(u)
  198.             if dist < min_dist:
  199.                 min_dist_unit = u
  200.                 min_dist = dist
  201.         return (min_dist_unit, min_dist)
  202.     else:
  203.         return (None,-1);
  204.  
  205. def test_obstacles(me, target, obstacles):
  206.     angle_to_enemy = me.get_angle_to_unit(target) + me.angle
  207.     for o in obstacles:
  208.         angle_to_obstacle = me.get_angle_to_unit(o) + me.angle        
  209.         if (fabs(angle_to_enemy - angle_to_obstacle) < pi/4):
  210.             dist_to_enemy = me.get_distance_to_unit(target)
  211.             dist_to_obstacle = me.get_distance_to_unit(o)
  212.             if (dist_to_enemy > dist_to_obstacle):
  213.                 #if ray_test_unit_angle(Vec2D(me.x,me.y), 2*pi-angle_to_enemy, o):
  214.                 if ray_test_unit_angle(Vec2D(me.x,me.y), angle_to_enemy, o):
  215.                     return True            
  216.     return False
  217.    
  218. def get_premium_shells(shells):
  219.     return [s for s in shells if s.type == ShellType.PREMIUM]
  220.  
  221. def create_point_unit(x,y):
  222.     return Unit(-1,0,0,x,y,0,0,0,0)
  223.  
  224. def create_unit(x,y,w,h,angle):
  225.     return Unit(-1,w,h,x,y,0,0,angle,0)
  226.  
  227. class Point:
  228.     def __init__(self, x, y):
  229.         self.x = x
  230.         self.y = y
  231.  
  232. class StrategyState:
  233.     CORNER_DEF = 0
  234.     SIMPLE = 1
  235.     MOVE_CORNER = 2
  236.     BONUS_RIDE = 3
  237.     USE_MAP = 4
  238.     IN_DMG_ZONE = 5
  239.    
  240. class MoveType:
  241.     FRONT = 0
  242.     BACK = 1
  243.     TURN = 2
  244.    
  245. def test_point(p, p0, r):
  246.     return p0.get_distance_to_unit(p) < fabs(r)
  247.  
  248.  
  249. ##def write_list_2_file(inputList, w,h, outputFile):  
  250. ##    for i in range(0,w*h):
  251. ##        if i%w==0 and i >= w: outputFile.write("\n");
  252. ##        outputFile.write("%3.2f\t" % inputList[i])
  253. ##    outputFile.write("\n");
  254.        
  255. class MyStrategy:
  256.     def __init__(self):
  257.         self.state = StrategyState.USE_MAP
  258.         self.enemy_list = []
  259.         self.cnt = 5
  260.         self.dange_map = []
  261.         self.tank_map = []
  262.         self.shell_map = []
  263.         self.target = None
  264.         self.dist_target = 0.0
  265.        
  266.         self.needed_bonus = None;
  267.         self.medkit_bonus = None;
  268.         self.repair_bonus = None;
  269.         self.ammo_bonus = None;
  270.         self.point_list = [];
  271.         self.strategy_point = None;
  272.         self.vis_bonuses = [];
  273.         #self.point_list = [];
  274.  
  275.     def get_in_visible_area(self, me, world, eye_angle):
  276.         visible_bonuses = []
  277.         for b in world.bonuses:
  278.             angle_b = me.get_turret_angle_to_unit(b)
  279.            
  280.             if fabs(angle_b) < eye_angle/2:
  281.                 dist_b = me.get_distance_to_unit(b)                
  282.                 if dist_b < self.dist_target:
  283.                     visible_bonuses.append(b)
  284.         return visible_bonuses
  285.                
  286.     def _test_tth(self, me, world, move):
  287.       if (len(self.point_list) > 0):
  288.         destPt = self.point_list[0];
  289.         angleToPt = me.get_angle_to(destPt.x, destPt.y)
  290.         if test_point(destPt, me, 40):        
  291.           self.point_list = self.point_list[1:]
  292.         self.move_to_point(me, destPt, move)
  293.         #print("move by point_list ", [destPt.x, destPt.y])    
  294.       else:
  295.         if not test_point(self.strategy_point, me, 40):
  296.           self.move_to_point(me, self.strategy_point, move)
  297.           #print("move to strategy pt ", [self.strategy_point.x, self.strategy_point.y])
  298.         elif self.target != None:
  299.           move = self.turn_to_point(me, self.target, move)
  300.         ## =============== rotate in corner =========
  301.         #elif self.state == StrategyState.CORNER_DEF:
  302.           #  move = self.turn_to_point(me, create_point_unit(me.x ,world.height/2), move)
  303.                
  304.    
  305.       return move
  306.    
  307.  
  308. ##    def test_bullet_zone(self, me, world, bullets):
  309. ##      
  310. ##        if len(bullets) > 0:
  311. ##            for s in bullets:
  312. ##                shell_angle = s.get_angle_to(me.x, me.y)
  313. ##                me_shell_angle = me.get_angle_to_unit(s)
  314. ##                if fabs(shell_angle) < pi/10:
  315. ##                    if ray_test_unit_angle(Vec2D(s.x, s.y), -s.angle, me):                        
  316. ##                        row,col = get_unit_zone(me,world.width, world.height, self.cnt)
  317. ##                        self.dange_map[int(row*self.cnt+col)]+=3
  318. ##                        #print("pos dist = ", [me.x, me.y, s.x, s.y, dist] )                  
  319. ##                        #print("speed angle= ", [s.speedX, s.speedY, s.angle])
  320.                        
  321.                
  322.     def turn_to_point(self, me, position, move):
  323.         angle = me.get_angle_to(position.x,position.y)        
  324.         if angle < -pi/24:
  325.             move.left_track_power = -1.0
  326.             move.right_track_power = 1.0*me.engine_rear_power_factor
  327.         elif angle > pi/24:
  328.             move.left_track_power = 1.0*me.engine_rear_power_factor
  329.             move.right_track_power = -1.0
  330.         return move
  331.        
  332.     def move_to_point(self, tank, destPoint, move):
  333.         angle_to_point = tank.get_angle_to(destPoint.x, destPoint.y);
  334.        
  335.         if fabs(angle_to_point) < pi/2:
  336.             if fabs(angle_to_point) < pi/4:
  337.                 move.left_track_power = 1;
  338.                 move.right_track_power = cos(fabs(angle_to_point));  
  339.             else:          
  340.                 move.left_track_power = 1*tank.engine_rear_power_factor;
  341.                 move.right_track_power = -1;
  342.                 #print("turn front");
  343.         else:
  344.             if (pi - fabs(angle_to_point)) < pi/4:
  345.                 move.left_track_power = -1;
  346.                 move.right_track_power = -cos(pi-fabs(angle_to_point));
  347.                 #print("move full back = ",  move.left_track_power, move.right_track_power);
  348.             else:    
  349.                 move.left_track_power = -1;
  350.                 move.right_track_power = 1*tank.engine_rear_power_factor;
  351.                
  352.         if (angle_to_point < 0):
  353.             swp = move.left_track_power;
  354.             move.left_track_power = move.right_track_power;
  355.             move.right_track_power = swp;
  356.         #print("move ", [move.left_track_power,move.right_track_power, angle_to_point])
  357.         return move;
  358.  
  359.        
  360.        
  361.     def select_target(self, me, world):
  362.         self.target, self.dist_target = None, 0.0
  363.         open_candidates = []
  364.         dead_tanks = get_dead_tanks(world.tanks)
  365.         team_tanks = get_team_tanks(world.tanks, me.id)
  366.         obstacles = world.bonuses + dead_tanks + team_tanks + world.obstacles
  367.        
  368.        
  369.         for t in self.enemy_list:
  370.             if not test_obstacles(me, t, obstacles):
  371.                 open_candidates.append(t)
  372.         #print("enemy = {0} {1} {2}".format(world.tick, me.id, self.enemy_list))        
  373.         #print("open can = {0}".format(open_candidates))        
  374.         turret_candidates = []
  375.         for t in open_candidates:
  376.             angle_turret_target = t.get_turret_angle_to_unit(me)
  377.             if fabs(angle_turret_target) < pi/12:
  378.                 turret_candidates.append(t)
  379.         if (len(turret_candidates) > 0):
  380.             self.target, self.dist_target = get_nearest(me, turret_candidates)
  381.             if self.dist_target > 700:
  382.                 self.target, self.dist_target = get_nearest(me, open_candidates)                
  383.         else:
  384.             self.target, self.dist_target = get_nearest(me, open_candidates)
  385.  
  386.     def strategy_attack(self, me, world, move):
  387.         #self.select_target(me, world.tanks)
  388.         self.select_target(me, world)
  389.         if (self.target != None):
  390.             turret_angle = me.get_turret_angle_to_unit(self.target)
  391.             if turret_angle > pi/180:
  392.                 move.turret_turn = 1
  393.             elif turret_angle < -pi/180:
  394.                 move.turret_turn = -1
  395.             else:
  396.                 if (self.dist_target < 450):
  397.                     move.fire_type = FireType.PREMIUM_PREFERRED
  398.                 else:
  399.                     move.fire_type = FireType.REGULAR
  400.                
  401.                
  402.     def get_bonus_info(self, tank, bonuses):
  403.    
  404.         medkit_list = get_bonus_list(bonuses, BonusType.MEDIKIT)
  405.         self.medkit_bonus, dist_medkit = get_nearest(tank,medkit_list)
  406.        
  407.         repair_list = get_bonus_list(bonuses, BonusType.REPAIR_KIT)
  408.         self.repair_bonus, dist_repair = get_nearest(tank,repair_list)
  409.  
  410.         ammo_list = get_bonus_list(bonuses, BonusType.AMMO_CRATE)
  411.         self.ammo_bonus, dist_ammo = get_nearest(tank,ammo_list)
  412.  
  413.     def strategy_bonus(self, me, world):
  414.         self.get_bonus_info(me, world.bonuses)
  415.        
  416.         needed_bonus = None
  417.         if (me.crew_health/me.crew_max_health) < 0.6:
  418.             needed_bonus = self.medkit_bonus
  419.         elif (me.hull_durability/me.hull_max_durability) < 0.5:
  420.             needed_bonus = self.repair_bonus
  421.         else:
  422.             needed_bonus = self.ammo_bonus
  423.            
  424.         if (needed_bonus == None and self.medkit_bonus != None):
  425.             needed_bonus = self.medkit_bonus    
  426.         self.point_list = []
  427.         if needed_bonus != None:
  428.             enemy_shells = get_enemy_shells(world.shells, me.player_name)
  429.             dist_bonus = me.get_distance_to_unit(needed_bonus)
  430.             me_danger = get_dangerous(me.x, me.y, self.enemy_list, enemy_shells)
  431.             bonus_danger = get_dangerous(needed_bonus.x, needed_bonus.y, self.enemy_list, enemy_shells)
  432.            
  433.             if ( dist_bonus < 250 or (needed_bonus.type == BonusType.MEDIKIT and (bonus_danger - me_danger < 0.5))) :
  434.                 self.point_list = [needed_bonus]    
  435.            
  436.             elif (dist_bonus < 550):
  437.                
  438.                 #print("bonus info", bonus_danger, me_danger)
  439.                 if bonus_danger - me_danger < 0.3:
  440.                     self.point_list = [needed_bonus]
  441.                    
  442.                              
  443.            
  444.            
  445.          
  446.        
  447.  
  448.     def select_strategy_point(self, me, world):
  449.         if len(self.enemy_list)>3:
  450.            
  451.             corner_points = [create_point_unit(100,100), create_point_unit(world.width-100,100),
  452.                              create_point_unit(100,world.height-100), create_point_unit(world.width-100,world.height-100)]
  453.             cp, cp_dist = get_nearest(me, corner_points)
  454.             self.strategy_point = cp
  455.         else:
  456.         #print("cp ", [cp.x, cp.y])
  457.            
  458.             enemy_shells = get_enemy_shells(world.shells, me.player_name)
  459.             if self.state == StrategyState.USE_MAP or self.state == StrategyState.IN_DMG_ZONE:
  460.                 dange_points = get_min_dangerous_for(me.x, me.y, 100, self.enemy_list, enemy_shells)
  461.            
  462.                 dange_points = get_min_dangerous_for(dange_points[0][0], dange_points[0][1], 100, self.enemy_list, enemy_shells)
  463.  
  464.                
  465.                 dange_points = get_min_dangerous_for(dange_points[0][0], dange_points[0][1], 100, self.enemy_list, enemy_shells)
  466.                 #get_next_dangerous
  467.                 usefullness = []
  468.                 for p in dange_points:
  469.                     usefullness.append(get_usefullness(p[0], p[1], world.bonuses))
  470.  
  471.                 #if world.tick%10==0:
  472.     ##            print("tick info ==== ", world.tick )
  473.     ##            print( me.x, me.y )
  474.     ##            print( list(zip(dange_points, usefullness)))
  475.                 self.strategy_point = create_point_unit(dange_points[0][0],dange_points[0][1])
  476.                 if len(dange_points)>1:      
  477.                     if (usefullness[0] < usefullness[1]):
  478.                         self.strategy_point = create_point_unit(dange_points[1][0],dange_points[1][1])
  479.  
  480. ##    ##            if test_point(self.strategy_point, me, 40):
  481. ##                    for es in enemy_shells:
  482. ##                        if ray_test_unit_angle(Vec2D(es.x, es.y), es.angle, me):
  483. ##                            shell_test_path(es, Vec2D(me.x, me.y), self.strategy_point)
  484. ##                            if world.tick%10==0:
  485. ##                                print("alarm", world.tick, [self.strategy_point.x, self.strategy_point.y], [me.speedX, me.speedY])
  486.                
  487.            
  488.  
  489.            
  490.     def move(self, me, world, move):
  491.         self.enemy_list = get_live_enemy_tanks(world.tanks)
  492.        
  493.         self.state = StrategyState.USE_MAP
  494.      
  495.        
  496.         enemy_shells = get_enemy_shells(world.shells, me.player_name)
  497.  
  498.      
  499.         self.strategy_bonus(me, world)      
  500.         self.select_strategy_point(me, world)
  501. ##        if (len(enemy_shells) > 0 and world.tick%5==0):
  502. ##            print([enemy_shells[0].id, world.tick])
  503. ##            a = open("log.txt", "a")
  504. ##            a.write("=============== Tick {0} =============== \n".format(world.tick))
  505. ##            write_list_2_file(self.dange_map.field, ws,hs, a)
  506. ##            a.write("=============== SP [{0}, {1}] [{2}, {3}]=============== \n".format(self.strategy_point.x, self.strategy_point.y, me.x, me.y))
  507. ##            a.close()
  508.      
  509.         move = self._test_tth(me, world, move)
  510.         self.strategy_attack(me, world, move)
  511.        
  512.  
  513.     def select_tank(self, tank_index, team_size):
  514.         return TankType.MEDIUM
RAW Paste Data