# xelai codetanks bot

a guest
Dec 2nd, 2012
79
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.
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.
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 = []
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):
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