# RAIC 2012 Mr.Smile v90

a guest
Dec 2nd, 2012
3,715
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
1. #include "MyStrategy.h"
2.
3. #define _USE_MATH_DEFINES
4. #include <cmath>
5. #include <climits>
6. #include <cstring>
7. #include <limits>
8. #include <algorithm>
9. #include <list>
10. #include <map>
11.
12. #include <iostream>  // DEBUG
13. #include <iomanip>  // DEBUG
14. #include <ctime>  // DEBUG
15.
16. using namespace model;
17. using namespace std;
18.
19.
20.
21. inline double sqr(double x)
22. {
23.     return x * x;
24. }
25.
26. inline double rem(double x, double y)
27. {
28.     x /= y;  return y * (x - floor(x));
29. }
30.
31.
32. struct Vec2D
33. {
34.     double x, y;
35.
36.     Vec2D()
37.     {
38.     }
39.
40.     Vec2D(const Vec2D &v) : x(v.x), y(v.y)
41.     {
42.     }
43.
44.     Vec2D(double x_, double y_) : x(x_), y(y_)
45.     {
46.     }
47.
48.     Vec2D &operator = (const Vec2D &v)
49.     {
50.         x = v.x;  y = v.y;  return *this;
51.     }
52.
53.     Vec2D operator + (const Vec2D &v) const
54.     {
55.         return Vec2D(x + v.x, y + v.y);
56.     }
57.
58.     Vec2D &operator += (const Vec2D &v)
59.     {
60.         x += v.x;  y += v.y;  return *this;
61.     }
62.
63.     Vec2D operator - (const Vec2D &v) const
64.     {
65.         return Vec2D(x - v.x, y - v.y);
66.     }
67.
68.     Vec2D &operator -= (const Vec2D &v)
69.     {
70.         x -= v.x;  y -= v.y;  return *this;
71.     }
72.
73.     Vec2D operator - () const
74.     {
75.         return Vec2D(-x, -y);
76.     }
77.
78.     Vec2D operator * (double a) const
79.     {
80.         return Vec2D(a * x, a * y);
81.     }
82.
83.     Vec2D &operator *= (double a)
84.     {
85.         x *= a;  y *= a;  return *this;
86.     }
87.
88.     double operator * (const Vec2D &v) const
89.     {
90.         return x * v.x + y * v.y;
91.     }
92.
93.     Vec2D operator / (double a) const
94.     {
95.         return (*this) * (1 / a);
96.     }
97.
98.     Vec2D operator /= (double a)
99.     {
100.         return (*this) *= (1 / a);
101.     }
102.
103.     Vec2D operator ~ () const
104.     {
105.         return Vec2D(y, -x);
106.     }
107.
108.     double operator % (const Vec2D &v) const
109.     {
110.         return *this * ~v;
111.     }
112.
113.     double sqr() const
114.     {
115.         return x * x + y * y;
116.     }
117.
118.     double len() const
119.     {
120.         return std::sqrt(x * x + y * y);
121.     }
122. };
123.
124. inline Vec2D operator * (double a, const Vec2D &v)
125. {
126.     return v * a;
127. }
128.
129. inline Vec2D normalize(const Vec2D &v)
130. {
131.     return v / v.len();
132. }
133.
134. inline Vec2D sincos(double angle)
135. {
136.     return Vec2D(cos(angle), sin(angle));
137. }
138.
139. inline Vec2D conj(const Vec2D &v)
140. {
141.     return Vec2D(v.x, -v.y);
142. }
143.
144.
146. {
147.     Vec2D pos, dir;
148.     double half_w, half_h;
149.
151.     {
152.     }
153.
154.     Quad(const Vec2D &pos_, const Vec2D &dir_, double hw, double hh) :
155.         pos(pos_), dir(dir_), half_w(hw), half_h(hh)
156.     {
157.     }
158.
159.     Quad(const Unit &unit) : pos(unit.x(), unit.y()),
160.         dir(sincos(unit.angle())), half_w(unit.width() / 2), half_h(unit.height() / 2)
161.     {
162.     }
163.
164.     Quad(const Vec2D &start, const Vec2D &delta, double size) : half_h(size / 2)
165.     {
166.         dir = delta / 2;  half_w = dir.len();  pos = start + dir;  dir /= half_w;
167.     }
168.
169.     Quad move(const Vec2D &pt) const
170.     {
171.         return Quad(pt, dir, half_w, half_h);
172.     }
173.
174.     bool checkPoint(const Vec2D &pt, double rad = 0) const
175.     {
176.         Vec2D dr = pt - pos;
177.         return abs(dr * dir) < half_w + rad && abs(dr % dir) < half_h + rad;
178.     }
179.
180.     bool cross(const Quad &q) const
181.     {
182.         Vec2D dr = pos - q.pos;
183.         //if(dr.sqr() > sqr(half_w + half_h + q.half_w + q.half_h))return false;
184.
185.         double dot = abs(dir * q.dir), cross = abs(dir % q.dir);
186.         if(!(abs(dr * dir) < half_w + q.half_w * dot + q.half_h * cross))return false;
187.         if(!(abs(dr % dir) < half_h + q.half_h * dot + q.half_w * cross))return false;
188.         if(!(abs(dr * q.dir) < q.half_w + half_w * dot + half_h * cross))return false;
189.         if(!(abs(dr % q.dir) < q.half_h + half_h * dot + half_w * cross))return false;
190.         return true;
191.     }
192.
193.     void crossRange(const Quad &q, const Vec2D &delta, double &t_min, double &t_max) const
194.     {
195.         Vec2D dr = pos - q.pos;
196.         double center1 = dr * dir, center2 = dr % dir;
197.         double center3 = dr * q.dir, center4 = dr % q.dir;
198.         double dot = abs(dir * q.dir), cross = abs(dir % q.dir);
199.         double delta1 = half_w + q.half_w * dot + q.half_h * cross;
200.         double delta2 = half_h + q.half_h * dot + q.half_w * cross;
201.         double delta3 = q.half_w + half_w * dot + half_h * cross;
202.         double delta4 = q.half_h + half_h * dot + half_w * cross;
203.
204.         double mul1 = 1 / (delta * dir), mul2 = 1 / (delta % dir);
205.         double mul3 = 1 / (delta * q.dir), mul4 = 1 / (delta % q.dir);
206.         if(mul1 < 0)delta1 = -delta1;  if(mul2 < 0)delta2 = -delta2;
207.         if(mul3 < 0)delta3 = -delta3;  if(mul4 < 0)delta4 = -delta4;
208.         t_min = max(max((center1 - delta1) * mul1, (center2 - delta2) * mul2),
209.                     max((center3 - delta3) * mul3, (center4 - delta4) * mul4));
210.         t_max = min(min((center1 + delta1) * mul1, (center2 + delta2) * mul2),
211.                     min((center3 + delta3) * mul3, (center4 + delta4) * mul4));
212.     }
213.
214.     void crossLine(const Vec2D &start, const Vec2D &delta, double &t_min, double &t_max) const
215.     {
216.         Vec2D dr = pos - start;
217.         double center1 = dr * dir, center2 = dr % dir;
218.         double delta1 = half_w, delta2 = half_h;
219.
220.         double mul1 = 1 / (delta * dir), mul2 = 1 / (delta % dir);
221.         if(mul1 < 0)delta1 = -delta1;  if(mul2 < 0)delta2 = -delta2;
222.         t_min = max((center1 - delta1) * mul1, (center2 - delta2) * mul2);
223.         t_max = min((center1 + delta1) * mul1, (center2 + delta2) * mul2);
224.     }
225. };
226.
227.
228.
229. struct GlobalParams
230. {
231.     double crew_danger_att, hull_danger_att, ang_spd_account;
232.     double medkit_score, repkit_score, ammo_score;
235.     double tg_prem_danger, tg_ang_att, tg_base_score;
236.     double tg_prem_bonus, tg_prem_offs, tg_fire_thr;
238.     double team_force, team_dist;
240.     double prem_danger, hit_danger;
241.
242. #ifdef OPTIMIZING
243.
244.     GlobalParams()
245.     {
246.         static const unsigned long long flag = 0x0123456789ABCDEF;
247.
248.         unsigned long long buf;
250.         if(buf == flag)
251.         {
254.             if(buf == flag)return;
255.         }
256.         cout << "Invalid input!!!" << endl;  exit(-1);
257.     }
258.
259. #else
260.
261.     GlobalParams()
262.     {
263.         /*crew_danger_att = 0.4;
264.         hull_danger_att = 0.3;
265.         ang_spd_account = 0.1;
266.         medkit_score = 2.5;
267.         repkit_score = 0.4;
268.         ammo_score = 0.2;
269.         obst_danger = 30;
271.         rot_bonus = 10;
272.         tg_border = 8;
274.         tg_prem_danger = 0;
275.         tg_ang_att = 0.07;
276.         tg_base_score = 0.8;
277.         tg_prem_bonus = 3;
278.         tg_prem_offs = 2;
279.         tg_fire_thr = 0.25;
280.         aggr_factor = 1.2;
282.         team_force = 0.08;
283.         team_dist = 250;
284.         dng_ang_att = 6;
286.         prem_danger = 0.5;
287.         hit_danger = 4000;*/
288.
289.         /*crew_danger_att = 0.7;
290.         hull_danger_att = 0.15;
291.         ang_spd_account = 0.5;
292.         medkit_score = 5;
293.         repkit_score = 0.3;
294.         ammo_score = 1;
295.         obst_danger = 8;
297.         rot_bonus = 2;
298.         tg_border = 8;
300.         tg_prem_danger = 0.04;
301.         tg_ang_att = 0.01;
302.         tg_base_score = 1;
303.         tg_prem_bonus = 20;
304.         tg_prem_offs = 10;
305.         tg_fire_thr = 0.3;
306.         aggr_factor = 0.2;
308.         team_force = 0.08;
309.         team_dist = 200;
310.         dng_ang_att = 20;
312.         prem_danger = 0.1;
313.         hit_danger = 200;*/
314.
315.         crew_danger_att = 0.7;
316.         hull_danger_att = 0.15;
317.         ang_spd_account = 0.5;
318.         medkit_score = 5;
319.         repkit_score = 0.3;
320.         ammo_score = 1;
321.         obst_danger = 8;
323.         rot_bonus = 2;
324.         tg_border = 8;
326.         tg_prem_danger = 0.04;
327.         tg_ang_att = 0.01;
328.         tg_base_score = 1;
329.         tg_prem_bonus = 20;
330.         tg_prem_offs = 10;
331.         tg_fire_thr = 0.3;
332.         aggr_factor = 2;
334.         team_force = 0.08;
335.         team_dist = 200;
336.         dng_ang_att = 20;
338.         prem_danger = 0.1;
339.         hit_danger = 200;
340.     }
341.
342. #endif
343.
344. };
345.
346. const GlobalParams prm;
347.
348.
349.
350. struct ShellInfo
351. {
352.     double frict, v0, mul, range, score;
353.     FireType fire;
354.
355.     ShellInfo(double frict_, double v0_, FireType fire_, double score_) :
356.         frict(frict_), v0(v0_), mul(1 / log(1 - frict_)), range(v0_ / frict_), score(score_), fire(fire_)
357.     {
358.     }
359. };
360.
361. const ShellInfo shell_info[] =
362. {
363.     ShellInfo(0.005, 50 / 3.0, REGULAR_FIRE, 10),
364.     ShellInfo(0.010, 40 / 3.0, PREMIUM_FIRE, 20)
365. };
366.
367.
368.
369. inline double crew_danger(const Tank &tank)
370. {
371.     return 1 - prm.crew_danger_att * tank.crew_health() / tank.crew_max_health();
372. }
373.
374. inline double hull_danger(const Tank &tank)
375. {
376.     return 1 - prm.hull_danger_att * tank.hull_durability() / tank.hull_max_durability();
377. }
378.
379. struct FriendRef
380. {
381.     Vec2D pos, turret;
382.     double ang_spd, gun_len, gun_angle;
384.     long long id;  int prev_dir;
385.
386.     FriendRef(const Tank &tank, size_t index, int prev) : pos(tank.x(), tank.y()),
387.         ang_spd(tank.angular_speed()), gun_len(tank.virtual_gun_length()),
388.         gun_angle(tank.angle() + tank.turret_relative_angle()),
389.         danger(max(crew_danger(tank), hull_danger(tank))),
391.         id(tank.id()), prev_dir(prev)
392.     {
393.         turret = sincos(gun_angle);
394.     }
395. };
396.
397.
398. struct BonusRef
399. {
400.     Vec2D pos;
401.     BonusType type;
402.
403.     static void calcScore(const Tank &tank, double score[3])
404.     {
405.         score[MEDIKIT] = prm.medkit_score * crew_danger(tank) *
406.             min(1.0, (tank.crew_max_health() - tank.crew_health()) / 35.0);
407.         score[REPAIR_KIT] = prm.repkit_score * hull_danger(tank) *
408.             min(1.0, (tank.hull_max_durability() - tank.hull_durability()) / 50.0);
409.         score[AMMO_CRATE] = prm.ammo_score;
410.     }
411.
412.     BonusRef(const Bonus &bonus) : pos(bonus.x(), bonus.y()), type(bonus.type())
413.     {
414.     }
415. };
416.
417.
418. struct Action
419. {
420.     double force, moment;
421.
422.     Action()
423.     {
424.     }
425.
426.     Action(const Tank &tank, double move_l, double move_r)
427.     {
428.         if(move_l < 0)move_l *= tank.engine_rear_power_factor();
429.         if(move_r < 0)move_r *= tank.engine_rear_power_factor();
430.         double mul = 0.04947917 * (1 + tank.crew_health() / double(tank.crew_max_health()));
431.         force = (move_l + move_r) * mul;  moment = 0.004229904 * (move_l - move_r) * mul;
432.     }
433. };
434.
435. struct State : public Quad
436. {
437.     double angle, ang_spd;
438.     Vec2D spd;
439.
440.     State()
441.     {
442.     }
443.
444.     State(const Unit &unit) : Quad(unit),
445.         angle(unit.angle()), ang_spd(unit.angular_speed()),
446.         spd(unit.speed_x(), unit.speed_y())
447.     {
448.     }
449.
450.     void bounce(const Vec2D &r, const Vec2D &norm, double depth)
451.     {
452.         double rt = r % norm, ri = rt / 975, w = 1 / (1 + rt * ri);
453.         double pr = -1.325 * min(0.0, spd * norm + 0.51 * rt * ang_spd) * w;
454.         double pp = 0.8 * max(0.0, depth - 0.01) * w;
455.         spd += pr * norm;  ang_spd += pr * ri;
456.         pos += pp * norm;  angle += pp * ri;
457.     }
458.
459.     void checkBounds(const Vec2D &size)
460.     {
461.         double w = size.x / 2, h = size.y / 2;
462.         Vec2D rw = half_w * dir, rh = half_h * ~dir;
463.         Vec2D r1 = rw + rh, r2 = rw - rh;
464.
465.         double depth = abs(pos.x - w) + max(abs(r1.x), abs(r2.x)) - w;
466.         if(depth > 0)
467.         {
468.             Vec2D norm(pos.x < w ? 1 : -1, 0);
469.             Vec2D &r = abs(r1.x) > abs(r2.x) ? r1 : r2;
470.             bounce((r.x < 0 ? norm.x : -norm.x) * r, norm, depth);
471.         }
472.         depth = abs(pos.y - h) + max(abs(r1.y), abs(r2.y)) - h;
473.         if(depth > 0)
474.         {
475.             Vec2D norm(0, pos.y < h ? 1 : -1);
476.             Vec2D &r = abs(r1.y) > abs(r2.y) ? r1 : r2;
477.             bounce((r.y < 0 ? norm.y : -norm.y) * r, norm, depth);
478.         }
479.     }
480.
481.     void advance(const Action &act, const Vec2D &size)
482.     {
483.         spd += act.force * dir - 0.05 * spd;
484.         ang_spd += act.moment - 0.02051282 * ang_spd;
485.
486.         checkBounds(size);
487.         pos += spd;  dir = sincos(angle += ang_spd);
488.     }
489. };
490.
491.
492. struct ShellRef : public Quad
493. {
494.     Vec2D spd;
495.     double frict, score;
496.
497.     ShellRef()
498.     {
499.     }
500.
501.     ShellRef(const Vec2D &pos, const Vec2D &dir, double gun_len, ShellType type) :
502.         Quad(pos + dir * gun_len, dir, 11.25, 3.75), spd(shell_info[type].v0 * dir),
503.         frict(shell_info[type].frict), score(shell_info[type].score)
504.
505.     {
506.     }
507.
508.     ShellRef(const Shell &shell) : Quad(shell), spd(shell.speed_x(), shell.speed_y()),
509.         frict(shell_info[shell.type()].frict), score(shell_info[shell.type()].score)
510.     {
511.     }
512.
514.     {
515.         spd -= frict * spd;  pos += spd;
516.     }
517. };
518.
519.
520. struct TankInfo
521. {
522.     double force, moment, damp, rot_damp;
523.
524.     TankInfo(double force_, double moment_, double damp_, double rot_damp_) :
525.         force(force_), moment(moment_), damp(damp_), rot_damp(rot_damp_)
526.     {
527.     }
528. };
529.
530. const TankInfo tank_info[] =
531. {
532.     TankInfo(0.19791669, 0.00020929222, 1.0 / 20, 0.02051282),  // MEDIUM
533.     TankInfo(0.11510416, 0.00008385862, 1.0 / 40, 0.01441441),  // HEAVY
534.     TankInfo(0.08950617, 0.00006365248, 1.0 / 30, 0.01394335)   // TANK_DESTROYER
535. };
536.
537.
538. struct ScoreElem
539. {
540.     double pos, val;
541.
542.     ScoreElem()
543.     {
544.     }
545.
546.     ScoreElem(double pos_, double val_) : pos(pos_), val(val_)
547.     {
548.     }
549. };
550.
551. struct ScoreRange : public list<ScoreElem>
552. {
553.     ScoreRange()
554.     {
555.         push_back(ScoreElem(-numeric_limits<double>::infinity(), 0));
556.         push_back(ScoreElem(numeric_limits<double>::infinity(), 0));
557.     }
558.
559.     static double timeMerge(double prev, double cur)
560.     {
561.         return prev == 0 ? cur : prev;
562.     }
563.
564.     static double addMerge(double prev, double cur)
565.     {
566.         return prev + cur;
567.     }
568.
569.     template<double (*func)(double, double), typename Iter> void merge(Iter beg, Iter end)
570.     {
571.         iterator ptr = begin();
572.         double prev = 0, cur = 0, res = 0;  ++ptr;
573.         for(; beg != end; ++beg)
574.         {
575.             while(ptr->pos < beg->pos)
576.             {
577.                 double val = func(prev = ptr->val, cur);
578.                 iterator old = ptr++;
579.                 if(val == res)erase(old);
580.                 else old->val = res = val;
581.             }
582.             cur = beg->val;
583.             if(ptr->pos == beg->pos)
584.             {
585.                 double val = func(prev = ptr->val, cur);
586.                 iterator old = ptr++;
587.                 if(val == res)erase(old);
588.                 else old->val = res = val;
589.             }
590.             else
591.             {
592.                 double val = func(prev, cur);
593.                 if(val != res)insert(ptr, ScoreElem(beg->pos, res = val));
594.             }
595.         }
596.     }
597.
598.     void merge(ScoreElem *elem, size_t n)
599.     {
600.         merge<timeMerge>(elem, elem + n);
601.     }
602.
604.     {
605.         const_iterator first = rng.begin(), last = rng.end();
607.     }
608.
609.     double integrate() const
610.     {
611.         const_iterator ptr = begin(), last = end();  if(++ptr == --last)return 0;
612.         for(double res = 0;;)
613.         {
614.             const_iterator old = ptr;  if(++ptr == last)return res;
615.             res += sqrt(sqrt(old->val)) * (ptr->pos - old->pos);
616.         }
617.     }
618.
619.     void print() const
620.     {
621.         const_iterator ptr = begin(), last = end();  cout << ptr->val;
622.         for(++ptr, --last; ptr != last; ++ptr)cout << " (" << ptr->pos << ") " << ptr->val;
623.         cout << endl;
624.     }
625. };
626.
627.
628. struct Target
629. {
630.     struct Prediction
631.     {
632.         Vec2D pos, delta, dir;
633.         double min, max;
634.     };
635.
636.
637.     static const int max_pred = 256;
638.     static const double dmul;
639.
640.
641.     double half_w, half_h;
642.     vector<Prediction> pred;
643.     double delta_min, delta_max;
644.     ScoreRange base_range;
645.     double score_offset;
646.
647.     Vec2D turret;
648.     double gun_len, score_mul;
651.
652.     Target(const Tank &tank, size_t index) :
653.         half_w(tank.width() / 2 - prm.tg_border),
654.         half_h(tank.height() / 2 - prm.tg_border),
655.         turret(sincos(tank.angle() + tank.turret_relative_angle())),
656.         gun_len(tank.virtual_gun_length()),
657.         score_mul(sqr(max(crew_danger(tank), hull_danger(tank)))),
660.     {
661.     }
662.
663.     void generate(const Tank &tank);
664.     void calcRange(ShellRef shell, int step, int total, ScoreRange &range) const;
665.
666.     void processShell(const ShellRef &shell)
667.     {
668.         ScoreRange range;  calcRange(shell, 0, max_pred, range);  base_range.add(range);
669.     }
670.
671.     void updateBase()
672.     {
673.         score_offset = sqr(sqr(base_range.integrate() / (delta_max - delta_min)));
674.     }
675.
676.     double calcScore(const ShellRef &shell, int step, int total) const
677.     {
678.         ScoreRange range;  calcRange(shell, step, total, range);  range.add(base_range);
679.         return sqr(sqr(range.integrate() / (delta_max - delta_min))) - score_offset;
680.     }
681. };
682.
683. const double Target::dmul = exp(-1 / prm.tg_lookahead);
684.
685.
686. struct GunMove
687. {
688.     double gun_move;
689.     FireType fire_type;
690. };
691.
692. struct DangerField
693. {
694.     static const double h, dmul, max_bonus;
695.
696.     static int cur_tick;
697.     static vector<Target> target;
698.     static vector<FriendRef> fref;
699.     static vector<ShellRef> sref;
700.     static vector<Vec2D> shell_pos;
701.     static vector<BonusRef> bref;
703.     static size_t block_count;
704.
705.     static Vec2D size, offset;
706.     static size_t width, height;
707.
708.
710.     vector<double> danger;
711.     double min_danger;
712.
713.     vector<Action> act;
714.     double bonus_score[3];
715.     double tg_angle, gun_spd;
716.     int fire_time;
717.
718.     double gun_spd_p, gun_spd_n, gun_move;
719.     FireType fire_type;
720.
721.
722.     static void init(const World &world);
723.     DangerField(const World &world, const Tank &tank);
724.
725.     static bool checkRay(const Vec2D &start, const Vec2D &delta, size_t skip1, size_t skip2 = -1);
726.     static double checkRay(const ShellRef &shell, size_t skip1, size_t skip2 = -1);
727.     void blur();
728.
729.     double sampleDanger(const Vec2D &pos);
730.     double hitDanger(const State &state, size_t index, int step);
731.     double samplePhys(State state, size_t index, const size_t *max_act,
732.         double mul, double sum, vector<bool> flag, double best, int step = 0);
733.     size_t samplePhys(const Tank &tank, const double move[][2], const size_t *max_move);
734.     double checkTarget(const Target &tank, double angle, double &best_angle, GunMove &res, double best);
735.
736.     void print();
737. };
738.
739. const double DangerField::h = 16;  // blur() dependent
740. const double DangerField::dmul = exp(-1 / prm.phys_lookahead);
741. const double DangerField::max_bonus = prm.medkit_score + prm.repkit_score + prm.ammo_score;
742.
743. int DangerField::cur_tick = -1;
744. vector<Target> DangerField::target;
745. vector<FriendRef> DangerField::fref;
746. vector<ShellRef> DangerField::sref;
747. vector<Vec2D> DangerField::shell_pos;
748. vector<BonusRef> DangerField::bref;
750. size_t DangerField::block_count;
751.
752. Vec2D DangerField::size, DangerField::offset;
753. size_t DangerField::width, DangerField::height;
754.
755.
756. inline double shellFlyTime(double dist, ShellType type)
757. {
758.     if(!(dist < shell_info[type].range))return numeric_limits<double>::infinity();
759.     return shell_info[type].mul * log(1 - dist / shell_info[type].range);
760. }
761.
762. void DangerField::init(const World &world)
763. {
764.     if(world.tick() == cur_tick)return;
765.     //cout << cur_tick << endl;
766.     cur_tick = world.tick();
767.
768.     size = Vec2D(world.width(), world.height());
769.     width = size_t(floor(size.x / h + 0.5)) + 6;
770.     height = size_t(floor(size.y / h + 0.5)) + 6;
771.     offset = (size - Vec2D(width - 1, height - 1) * h) / 2;
772.
773.     vector<Tank> tanks = world.tanks();
774.     vector<Shell> shells = world.shells();
775.     vector<Bonus> bonuses = world.bonuses();
776.     vector<Obstacle> obstacles = world.obstacles();
777.
779.     for(vector<Obstacle>::iterator ptr = obstacles.begin(); ptr != obstacles.end(); ++ptr)
781.
782.     map<long long, int> prev_dir;
783.     for(vector<FriendRef>::iterator ptr = fref.begin(); ptr != fref.end(); ++ptr)
784.         prev_dir[ptr->id] = ptr->prev_dir;
785.
786.     target.clear();  fref.clear();
787.     for(vector<Tank>::iterator ptr = tanks.begin(); ptr != tanks.end(); ++ptr)
788.     {
789.         if(ptr->crew_health() && ptr->hull_durability())
793.     }
795.
796.     sref.clear();  shell_pos.clear();
797.     for(vector<Shell>::iterator ptr = shells.begin(); ptr != shells.end(); ++ptr)
798.     {
799.         sref.push_back(*ptr);  shell_pos.push_back(sref[sref.size() - 1].pos);
800.     }
801.
802.     bref.clear();
803.     for(vector<Bonus>::iterator ptr = bonuses.begin(); ptr != bonuses.end(); ++ptr)
804.     {
806.     }
807.
808.     size_t index = 0;
809.     for(vector<Tank>::iterator ptr = tanks.begin(); ptr != tanks.end(); ++ptr)
810.         if(!ptr->teammate() && ptr->crew_health() && ptr->hull_durability())
811.             target[index++].generate(*ptr);
812.
813.     for(size_t i = 0; i < target.size(); i++)
814.     {
815.         double mul = 0;
816.         for(size_t j = 0; j < fref.size(); j++)
817.         {
818.             Vec2D delta = target[i].pred[0].pos - fref[j].pos;
819.             double dist = delta.len(), cos_turret = target[i].turret * delta / dist;
820.
821.             double val = 1 - dist / shell_info[REGULAR].range;
822.             if(target[i].premium)val = max(val, (prm.tg_prem_danger + 1) * (1 - dist / shell_info[PREMIUM].range));
823.             val *= exp(-prm.tg_ang_att * (1 + cos_turret)) * fref[j].danger;  mul = max(mul, val);
824.         }
825.         target[i].score_mul *= mul + prm.tg_base_score;
826.
827.         for(size_t j = 0; j < sref.size(); j++)target[i].processShell(sref[j]);
828.         target[i].updateBase();
829.     }
830. }
831.
832. DangerField::DangerField(const World &world, const Tank &tank) : gun_move(0), fire_type(NONE)
833. {
834.     init(world);
835.     for(cur = 0;; cur++)
836.         if(cur >= fref.size())
837.         {
838.             cur = -1;  return;
839.         }
840.         else if(fref[cur].id == tank.id())break;
842.
843.     danger.resize(width * height);  vector<double> aggr(width * height);
844.
846.     double aggr_mul = prm.aggr_factor * exp(-fire_time / prm.aggr_lookahead) * fref.size() / target.size();
847.     for(size_t j = 0, k = 0; j < height; j++)for(size_t i = 0; i < width; i++, k++)
848.     {
849.         Vec2D start = offset + Vec2D(i, j) * h;
850.         if(!(start.x > 0 && start.x < size.x && start.y > 0 && start.y < size.y))
851.         {
852.             danger[k] = prm.obst_danger;  continue;
853.         }
854.
855.         for(size_t i = 0; i < block_count; i++)
857.             {
858.                 danger[k] += prm.obst_danger;  break;
859.             }
860.
861.         for(size_t i = 0; i < fref.size(); i++)if(i != cur)
862.             danger[k] += prm.team_force * sqr(2 / (1 + (fref[i].pos - start).sqr() / sqr(prm.team_dist)) - 1);
863.
864.         for(vector<Target>::iterator ptr = target.begin(); ptr != target.end(); ++ptr)
865.         {
866.             Vec2D delta = ptr->pred[0].pos - start;
868.             double dist = delta.len(), w = exp(-prm.dng_ang_att * (1 + ptr->turret * delta / dist));
869.
870.             dist = max(0.0, dist - ptr->gun_len);
871.             w *= sqr(sqr(1 - dist / shell_info[REGULAR].range));
872.             double time = ptr->fire_time + shellFlyTime(dist, REGULAR);
873.             danger[k] += w * exp(-time / prm.dng_lookahead) * fref[cur].danger * (ptr->premium ? prm.prem_danger + 1 : 1);
874.             aggr[k] = max(aggr[k], (1 - dist / shell_info[REGULAR].range) * ptr->score_mul * aggr_mul);
875.         }
876.     }
877.
878.     blur();  min_danger = prm.obst_danger;
879.     for(size_t k = 0; k < width * height; k++)min_danger = min(min_danger, danger[k] -= aggr[k]);
880.     //if(!cur)print();
881.
882.     double best_target = 0;
883.     gun_spd_p = max(1e-9, tank.turret_turn_speed() + prm.ang_spd_account * tank.angular_speed());
884.     gun_spd_n = max(1e-9, tank.turret_turn_speed() - prm.ang_spd_account * tank.angular_speed());
885.     for(vector<Target>::iterator ptr = target.begin(); ptr != target.end(); ++ptr)
886.     {
887.         Vec2D delta = ptr->pred[0].pos - fref[cur].pos;  GunMove res;
888.         double angle = atan2(delta.y, delta.x), next = angle, da = M_PI / 18;
889.         double best = checkTarget(*ptr, angle, next, res, 0), cur;
890.         for(int i = 0; i < 4; i++)
891.         {
892.             best = checkTarget(*ptr, angle - da, next, res, best);
893.             best = checkTarget(*ptr, angle + da, next, res, best);
894.             best = checkTarget(*ptr, angle - 3 * da, next, res, best);
895.             best = checkTarget(*ptr, angle + 3 * da, next, res, best);
896.             angle = next;  da /= 2;
897.         }
898.         if(!fire_time)best = checkTarget(*ptr, fref[cur].gun_angle, next, res, best);
899.         //if(best != 0 && res.fire_type)cout << "Firing, score: " << best << endl;
900.         best *= ptr->score_mul;
901.
902.         if(!(best > best_target))continue;  best_target = best;
903.         gun_move = res.gun_move;  fire_type = res.fire_type;
904.     }
905. }
906.
907. bool DangerField::checkRay(const Vec2D &start, const Vec2D &delta, size_t skip1, size_t skip2)
908. {
910.     size_t list[] = {min(skip1, skip2), max(skip1, skip2), -1}, *skip = list;
911.     for(size_t i = 0; i < quad.size(); i++)
912.         if(i == *skip)skip++;
914.     return true;
915. }
916.
917. double DangerField::checkRay(const ShellRef &shell, size_t skip1, size_t skip2)
918. {
919.     double res = numeric_limits<double>::infinity();
920.     size_t list[] = {min(skip1, skip2), max(skip1, skip2), -1}, *skip = list;
921.     for(size_t i = 0; i < quad.size(); i++)
922.         if(i != *skip)
923.         {
924.             double t_min, t_max;
926.             if(t_min < t_max && t_max > 0)res = min(res, t_min);
927.         }
928.         else skip++;
929.     return max(0.0, res);
930. }
931.
932. void DangerField::blur()  // blur radius ~ 3.5 * h
933. {
934.     vector<double> buffer(danger.size() + 3 * width);
935.
936.     size_t offs = 2 * width + 2, k = 0;
937.     for(; k < 5 * width + 1; k++)buffer[k] = prm.obst_danger;
938.     for(; k < danger.size() - width - 1; k++)
939.     {
940.         size_t pos = k - offs;
941.         buffer[k] = (danger[pos] + danger[pos + 1] + danger[pos + 2] + danger[pos + 3] + danger[pos + 4]) / 5;
942.     }
943.     for(; k < danger.size() + 3 * width; k++)buffer[k] = prm.obst_danger;
944.
945.     for(k = width + 1; k < danger.size() - width - 1; k++)
946.     {
947.         size_t pos = k;  double res = buffer[k];
948.         pos += width;  res += buffer[pos];
949.         pos += width;  res += buffer[pos];
950.         pos += width;  res += buffer[pos];
951.         pos += width;  res += buffer[pos];
952.         buffer[k] = res / 5;
953.     }
954.
955.     static const double w1 = 0.8, w2 = 0.3;
956.     static const double c0 = 1 / (29 + 8 * (w1 + w2)), c1 = w1 * c0, c2 = w2 * c0;
957.     static const double cc = 25 * c0, ch = 2 * c0 + 4 * (c1 + c2);
958.
959.     for(k = 0; k < 3 * width + 2; k++)
960.     {
961.         buffer[k] = cc * buffer[k] + ch * prm.obst_danger + c0 * (danger[k + 3 * width] + danger[k + 3]) +
962.             c1 * (danger[k + 3 * width - 1] + danger[k + 3 * width + 1] + danger[k + width - 3] + danger[k + width + 3]) +
963.             c2 * (danger[k + 3 * width - 2] + danger[k + 3 * width + 2] + danger[k + 2 * width - 3] + danger[k + 2 * width + 3]);
964.     }
965.     for(; k < danger.size() - 3 * width - 2; k++)
966.     {
967.         buffer[k] = cc * buffer[k] + c0 * (danger[k - 3 * width] + danger[k + 3 * width] + danger[k - 3] + danger[k + 3]) +
968.             c1 * (danger[k - 3 * width - 1] + danger[k - 3 * width + 1] + danger[k + 3 * width - 1] + danger[k + 3 * width + 1] +
969.                 danger[k - width - 3] + danger[k - width + 3] + danger[k + width - 3] + danger[k + width + 3]) +
970.             c2 * (danger[k - 3 * width - 2] + danger[k - 3 * width + 2] + danger[k + 3 * width - 2] + danger[k + 3 * width + 2] +
971.                 danger[k - 2 * width - 3] + danger[k - 2 * width + 3] + danger[k + 2 * width - 3] + danger[k + 2 * width + 3]);
972.     }
973.     for(; k < danger.size(); k++)
974.     {
975.         buffer[k] = cc * buffer[k] + ch * prm.obst_danger + c0 * (danger[k - 3 * width] + danger[k - 3]) +
976.             c1 * (danger[k - 3 * width - 1] + danger[k - 3 * width + 1] + danger[k - width - 3] + danger[k - width + 3]) +
977.             c2 * (danger[k - 3 * width - 2] + danger[k - 3 * width + 2] + danger[k - 2 * width - 3] + danger[k - 2 * width + 3]);
978.     }
979.
980.     buffer.resize(danger.size());  danger.swap(buffer);
981. }
982.
983. double DangerField::sampleDanger(const Vec2D &pos)
984. {
985.     Vec2D index = (pos - offset) / h;
986.     size_t i = size_t(floor(index.x)), j = size_t(floor(index.y));
987.     if(i >= width - 1 || j >= height - 1)return prm.obst_danger;
988.
989.     index -= Vec2D(i, j);  size_t k = i + j * width;
990.     double up = danger[k] + (danger[k + 1] - danger[k]) * index.x;  k += width;
991.     double dn = danger[k] + (danger[k + 1] - danger[k]) * index.x;
992.     return up + (dn - up) * index.y;
993. }
994.
995. double DangerField::hitDanger(const State &state, size_t index, int step)
996. {
997.     size_t pindex = step * sref.size() + index;
998.     if(!checkRay(shell_pos[pindex], shell_pos[pindex] - shell_pos[index], quad_index))return 0;
999.
1000.     double dot = sref[index].dir * state.dir, cross = sref[index].dir % state.dir;
1001.     double w = dot > 0 ? -state.half_w : state.half_w, h = cross > 0 ? -state.half_h : state.half_h;
1002.     double offs = (state.pos + w * state.dir + h * ~state.dir - shell_pos[pindex]) % sref[index].dir;
1003.     if(dot * cross > 0)offs = -offs;
1004.
1005.     static const double back = 1 / 1.0, side = 1 / 1.5, front = 1 / 1.75;
1006.
1007.     double mul = prm.hit_danger * prm.obst_danger * sref[index].score;
1008.     mul *= (shell_pos[pindex] - shell_pos[pindex - sref.size()]).len();
1009.     if(offs < -sref[index].half_h)return side * mul * sqr(cross);
1010.     if(offs > sref[index].half_h)return (dot > 0 ? back : front) * mul * sqr(dot);
1011.     return (dot > 0 ? back : side) * mul;
1012. }
1013.
1014. double DangerField::samplePhys(State state, size_t index, const size_t *max_act,
1015.     double mul, double sum, vector<bool> flag, double best, int step)
1016. {
1017.     for(step++;; step++)
1018.     {
1019.         state.advance(act[index], size);  double dng = sampleDanger(state.pos);
1020.         //if(!index && !(state.spd.sqr() > sqr(0.05 * h)) || !(mul > 1e-3))return min(best, sum + dng * mul);
1021.         if(!index && step > 64 || !(mul > 1e-3))return min(best, sum + dng * mul);  // TODO: shell stop
1022.         sum += dng * mul * (1 - dmul);
1023.
1024.         if(step >= fire_time && flag[0] &&
1025.             abs(rem(state.angle - tg_angle + M_PI, 2 * M_PI) - M_PI) < step * gun_spd)
1026.         {
1027.             sum -= prm.rot_bonus * mul;  flag[0] = false;
1028.         }
1029.
1030.         size_t fpos = 1;
1031.         for(size_t j = 0; j < bref.size(); j++)
1032.             if(flag[fpos + j] && state.checkPoint(bref[j].pos))
1033.             {
1034.                 sum -= bonus_score[bref[j].type] * mul;  flag[fpos + j] = false;
1035.             }
1036.
1037.         size_t offs = step * sref.size();  fpos += bref.size();
1038.         while(shell_pos.size() < offs + sref.size())
1039.             for(size_t j = 0; j < sref.size(); j++)
1040.             {
1042.             }
1043.         for(size_t j = 0; j < sref.size(); j++)
1044.             if(flag[fpos + j] && state.cross(sref[j].move(shell_pos[offs + j])))
1045.             {
1046.                 sum += hitDanger(state, j, step) * mul;  flag[fpos + j] = false;
1047.             }
1048.
1049.         mul *= dmul;
1050.         double min_total = min_danger - (flag[0] ? prm.rot_bonus : 0) - max_bonus;
1051.         if(!(sum + min_total * mul < best))return best;
1052.
1053.         if(index && !(step % 32))for(size_t i = 0; i < *max_act; i++)if(i != index)
1054.             best = samplePhys(state, i, max_act + 1, mul, sum, flag, best, step);
1055.     }
1056. }
1057.
1058. size_t DangerField::samplePhys(const Tank &tank, const double move[][2], const size_t *max_move)
1059. {
1060.     size_t move_count = 1;
1061.     for(const size_t *ptr = max_move; *ptr > 1; ptr++)move_count = max(move_count, *ptr);
1062.
1063.     act.resize(move_count);
1064.     for(size_t i = 0; i < move_count; i++)act[i] = Action(tank, move[i][0], move[i][1]);
1065.
1066.     BonusRef::calcScore(tank, bonus_score);
1067.     tg_angle = tank.angle() + gun_move;
1068.     gun_spd = tank.turret_turn_speed();
1069.
1070.     State state(tank);
1071.     double dng = sampleDanger(state.pos);
1072.     double mul = dmul, sum = dng * (1 - mul);
1073.     vector<bool> flag(bref.size() + sref.size() + 1, true);
1074.     flag[0] = fire_time;
1075.
1076.     double best = numeric_limits<double>::infinity();
1077.     size_t dir = 0, prev = fref[cur].prev_dir;
1078.     if(prev < move_count)
1079.     {
1080.         best = samplePhys(state, prev, max_move + 1, mul, sum, flag, best);
1081.         dir = prev;
1082.     }
1083.     for(size_t i = 0; *max_move > 1; max_move++)
1084.         for(; i < *max_move; i++)if(i != prev)
1085.         {
1086.             double res = samplePhys(state, i, max_move + 1, mul, sum, flag, best);
1087.             if(!(res < best))continue;  best = res;  dir = i;
1088.         }
1089.     //cout << "Best dir: " << dir << ", danger: " << best << endl;
1090.     return fref[cur].prev_dir = dir;
1091. }
1092.
1093.
1094. double DangerField::checkTarget(const Target &tank, double angle, double &best_angle, GunMove &res, double best)
1095. {
1096.     double a = rem(angle - fref[cur].gun_angle - fire_time * fref[cur].ang_spd, 2 * M_PI);
1097.     double left_time = (2 * M_PI - a) / gun_spd_n, right_time = a / gun_spd_p;  int start;
1098.     if(left_time < right_time)
1099.     {
1100.         start = (int)ceil(left_time);  a -= 2 * M_PI;
1101.     }
1102.     else start = (int)ceil(right_time);
1103.     start = max(0, start - fire_time);
1104.
1105.     Vec2D dir = sincos(angle);
1106.     ShellRef shell(fref[cur].pos, dir, fref[cur].gun_len, REGULAR);
1108.     int total = (int)min(1e6, ceil(shellFlyTime(dist, REGULAR)));
1109.     double sc = tank.calcScore(shell, start, total);
1110.     FireType fire = REGULAR_FIRE;
1112.     {
1113.         shell = ShellRef(fref[cur].pos, dir, fref[cur].gun_len, PREMIUM);
1114.         total = (int)min(1e6, ceil(shellFlyTime(dist, PREMIUM)));
1115.         double sc_p = (prm.tg_prem_bonus + 1) * tank.calcScore(shell, start, total) - prm.tg_prem_offs;
1116.         if(sc_p > sc)
1117.         {
1118.             sc = sc_p;  fire = PREMIUM_FIRE;
1119.         }
1120.     }
1121.     if(!(sc > best))return best;
1122.
1123.     if(sc < prm.tg_fire_thr && (cur_tick % 64 || cur_tick / 64 % fref.size() != cur))fire = NONE;
1124.
1125.     res.fire_type = (!fire_time && abs(a) < 1e-3 ? fire : NONE);
1126.     best_angle = angle;  res.gun_move = a - fref[cur].ang_spd;  return sc;
1127. }
1128.
1129.
1130. void Target::generate(const Tank &tank)
1131. {
1132.     delta_min = -tank.engine_rear_power_factor();  delta_max = 1;
1133.
1134.     double damp = tank_info[tank.type()].damp;
1135.     double rot_damp = tank_info[tank.type()].rot_damp;
1136.     double force = 0.5 + tank.crew_health() / (2.0 * tank.crew_max_health());
1137.     force *= tank_info[tank.type()].force;
1138.
1139.     pred.resize(max_pred);  pred[0].pos = Vec2D(tank.x(), tank.y());
1140.     pred[0].delta = Vec2D(0, 0);  pred[0].dir = sincos(tank.angle());
1141.     pred[0].min = delta_min;  pred[0].max = delta_max;
1142.
1143.     Vec2D spd(tank.speed_x(), tank.speed_y()), spd_delta(0, 0);
1144.     double angle(tank.angle()), ang_spd(tank.angular_speed());
1145.     for(int i = 1; i < max_pred; i++)
1146.     {
1147.         spd_delta += force * pred[i - 1].dir - damp * spd_delta;
1148.         spd -= damp * spd;  ang_spd -= rot_damp * ang_spd;
1149.
1150.         pred[i].pos = pred[i - 1].pos + spd;
1151.         pred[i].delta = pred[i - 1].delta + spd_delta;
1152.         pred[i].dir = sincos(angle += ang_spd);
1153.
1154.         double border = half_w / pred[i].delta.len();
1155.         Vec2D inv(1 / pred[i].delta.x, 1 / pred[i].delta.y);
1156.         Vec2D delta = DangerField::size / 2, center = delta - pred[i].pos;
1157.         if(inv.x < 0)delta.x = -delta.x;  if(inv.y < 0)delta.y = -delta.y;
1158.         double cur_min = max(pred[i - 1].min - border, max((center.x - delta.x) * inv.x, (center.y - delta.y) * inv.y));
1159.         double cur_max = min(pred[i - 1].max + border, min((center.x + delta.x) * inv.x, (center.y + delta.y) * inv.y));
1160.         for(size_t j = 0; j < DangerField::block_count; j++)
1162.             {
1163.                 double t_min, t_max;
1165.                 if(t_min < cur_min && t_max > cur_min)cur_min = t_max;
1166.                 if(t_min < cur_max && t_max > cur_max)cur_max = t_min;
1167.             }
1168.         cur_min += border;  cur_max -= border;
1169.         if(cur_min > cur_max)cur_min = cur_max = (cur_min + cur_max) / 2;
1170.         pred[i].min = cur_min;  pred[i].max = cur_max;
1171.     }
1172. }
1173.
1174. void Target::calcRange(ShellRef shell, int step, int total, ScoreRange &range) const
1175. {
1176.     double score = exp(-step / prm.tg_lookahead);
1177.     int end = step + total;  if(end > max_pred)end = max_pred;
1178.     for(; step < end; step++, score *= dmul)
1179.     {
1180.         double t_min, t_max;
1181.         shell.crossRange(Quad(pred[step].pos, pred[step].dir, half_w, half_h), pred[step].delta, t_min, t_max);
1182.         t_min = max(pred[step].min, t_min);  t_max = min(pred[step].max, t_max);
1183.         if(t_min < t_max)
1184.         {
1185.             double score1 = score * sqr(shell.dir * pred[step].dir);
1186.             double score2 = score * sqr(shell.dir % pred[step].dir);
1187.
1188.             Vec2D dr = shell.pos - pred[step].pos;
1189.             if(dr % pred[step].delta < 0)swap(score1, score2);
1190.             Vec2D diag1 = half_w * pred[step].dir + half_h * ~pred[step].dir;
1191.             Vec2D diag2 = half_w * pred[step].dir - half_h * ~pred[step].dir;
1192.             double div1 = (dr % diag1) / (pred[step].delta % diag1);
1193.             double div2 = (dr % diag2) / (pred[step].delta % diag2);
1194.             if(div1 > div2)
1195.             {
1196.                 swap(div1, div2);  swap(score1, score2);
1197.             }
1198.
1199.             int index = 1;
1200.             ScoreElem elem[4] = {ScoreElem(t_min == pred[step].min ? delta_min : t_min, score1)};
1201.             if(div1 > t_min)
1202.             {
1203.                 if(div1 < t_max)
1204.                 {
1205.                     elem[index++] = ScoreElem(div1, score2);
1206.                     if(div2 < t_max)elem[index++] = ScoreElem(div2, score1);
1207.                 }
1208.             }
1209.             else if(div2 > t_min)
1210.             {
1211.                 elem[0].val = score2;
1212.                 if(div2 < t_max)elem[index++] = ScoreElem(div2, score1);
1213.             }
1214.             elem[index++] = ScoreElem(t_max == pred[step].max ? delta_max : t_max, 0);
1215.             range.merge(elem, index);
1216.         }
1218.     }
1219. }
1220.
1221.
1222. inline void printValues(double up, double dn, int flag)
1223. {
1224.     static const char gradient[] =
1225.         "000 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 015";
1226.
1227.     cout << "\x1B[48;5;";
1228.     if(flag & 1)cout << 10;
1229.     else cout.write(gradient + 4 * min(max(0, int(up * 26)), 25), 3);  cout << ";38;5;";
1230.     if(flag & 2)cout << 10;
1231.     else cout.write(gradient + 4 * min(max(0, int(dn * 26)), 25), 3);  cout << "m▄";
1232. }
1233.
1234. void DangerField::print()
1235. {
1236.     static const double offs = 0, scale = 0.5;
1237.
1238.     Vec2D index = (fref[cur].pos - offset) / h;
1239.     size_t k0 = size_t(floor(index.x + 0.5)) + size_t(floor(index.y + 0.5)) * width;
1240.
1241.     cout << "\x1B[" << height << 'A';
1242.     for(size_t j = 0, k = 0; j < height; j += 2, k += width)
1243.     {
1244.         for(size_t i = 0; i < width; i++, k++)
1245.             printValues((danger[k] + offs) * scale, (danger[k + width] + offs) * scale,
1246.                 k == k0 ? 1 : k + width == k0 ? 2 : 0);
1247.         cout << "\x1B[0m" << endl;
1248.     }
1249. }
1250.
1251.
1252. clock_t global_time;
1253.
1254. void MyStrategy::Move(Tank self, World world, model::Move& move)
1255. {
1256.     DangerField field(world, self);
1257.     if(field.cur == size_t(-1))return;
1258.
1259.     move.set_fire_type(field.fire_type);
1260.     move.set_turret_turn(field.gun_move);
1261.
1262.
1263.     static const double moves[][2] =
1264.     {
1265.         {0, 0}, {1, -1}, {-1, 1}, {1, 1}, {-1, -1},
1266.         {1, 0.9}, {0.9, 1}, {-1, -0.9}, {-0.9, -1},
1267.         {1, 0.8}, {0.8, 1}, {-1, -0.8}, {-0.8, -1},
1268.         {1, 0.7}, {0.7, 1}, {-1, -0.7}, {-0.7, -1},
1269.         {1, 0.6}, {0.6, 1}, {-1, -0.6}, {-0.6, -1},
1270.         //{1, 0.5}, {0.5, 1}, {-1, -0.5}, {-0.5, -1},
1271.         {1, 0.4}, {0.4, 1}, {-1, -0.4}, {-0.4, -1},
1272.         //{1, 0.3}, {0.3, 1}, {-1, -0.3}, {-0.3, -1},
1273.         {1, 0.2}, {0.2, 1}, {-1, -0.2}, {-0.2, -1},
1274.         //{1, 0.1}, {0.1, 1}, {-1, -0.1}, {-0.1, -1},
1275.         {1, 0.0}, {0.0, 1}, {-1, -0.0}, {-0.0, -1},
1276.         //{1, -0.1}, {-0.1, 1}, {-1, 0.1}, {0.1, -1},
1277.         {1, -0.2}, {-0.2, 1}, {-1, 0.2}, {0.2, -1},
1278.         //{1, -0.3}, {-0.3, 1}, {-1, 0.3}, {0.3, -1},
1279.         {1, -0.4}, {-0.4, 1}, {-1, 0.4}, {0.4, -1},
1280.         //{1, -0.5}, {-0.5, 1}, {-1, 0.5}, {0.5, -1},
1281.         {1, -0.6}, {-0.6, 1}, {-1, 0.6}, {0.6, -1},
1282.         //{1, -0.7}, {-0.7, 1}, {-1, 0.7}, {0.7, -1},
1283.         {1, -0.8}, {-0.8, 1}, {-1, 0.8}, {0.8, -1},
1284.         //{1, -0.9}, {-0.9, 1}, {-1, 0.9}, {0.9, -1},
1285.     };
1286.
1287.     static const size_t max_move[] = {sizeof(moves) / sizeof(moves[0]), 1};
1288.
1289.     size_t dir = field.samplePhys(self, moves, max_move);
1290.     move.set_left_track_power(moves[dir][0]);
1291.     move.set_right_track_power(moves[dir][1]);
1292.
1293.
1294.     /*if(world.tick() % 100 == 99)
1295.     {
1296.         clock_t old = global_time;  global_time = clock();
1297.         cout << "Time per tick: " << (global_time - old) * (10.0 / CLOCKS_PER_SEC) << "ms" << endl;
1298.     }*/
1299. }
1300.
1301. TankType MyStrategy::SelectTank(int tank_index, int team_size)
1302. {
1303.     global_time = clock();
1304.
1305.     return MEDIUM;
1306. }
RAW Paste Data