Advertisement
Guest User

Untitled

a guest
May 24th, 2016
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 31.64 KB | None | 0 0
  1. #include <iostream>
  2. #include <sstream>
  3. #include <string>
  4. #include <vector>
  5. #include <algorithm>
  6. #include <array>
  7. #include <sys/time.h>
  8.  
  9. using namespace std;
  10. #define my_delete(x) \
  11.     {                \
  12.         delete x;    \
  13.         x = NULL;    \
  14.     }
  15.  
  16. // *** DECLARATION ***
  17. class Vector2D;
  18. class Checkpoint;
  19. class Command;
  20. class Drone;
  21. void cheapPlay(Command* cmd, Drone* drone);
  22.  
  23. // *** CONSTANTS ***
  24. const int SIM_DEPTH = 5;
  25. const int GEN_POP_SIZE = 256;
  26. const int SHIELD_TIMER = 3;
  27. const int CP_RADIUS = 550;
  28. const int DRONE_RADIUS = 400;
  29. const double FRICTION = 0.85f;
  30. const float PI = 3.1415926535897932384626434;
  31.  
  32. // *** GLOBAL ***
  33. struct timeval timestart, timeend;
  34. int laps, checkpointCount, turn, totalCp;
  35. vector<Checkpoint*> checkPoints;
  36. vector<Drone*> drones;
  37. vector<Drone*> dronePositions;
  38. int MYRUNNER, MYSUPPORT, HISRUNNER, HISSUPPORT;
  39. int MYTIMEOUT = 100, HISTIMEOUT = 100;
  40. int STRATEGY;
  41. double COS[2 * 360];
  42. double SIN[2 * 360];
  43.  
  44. // *** DEBUG ***
  45. int BOUNCE_CALL = 0;
  46. int MOVDUR_CALL = 0;
  47. int SIM_BRAN = 0;
  48. int cpt = 0;
  49.  
  50. // ***********************************************************
  51.  
  52. float elapsedMS()
  53. {
  54.     gettimeofday(&timeend, NULL);
  55.     return ((timeend.tv_sec - timestart.tv_sec) * 1000 + (timeend.tv_usec - timestart.tv_usec) / 1000.0) + 0.5;
  56. }
  57.  
  58. float degToRad(float x)
  59. {
  60.     return x / 180 * PI;
  61. }
  62.  
  63. float radToDeg(float x)
  64. {
  65.     return x / PI * 180;
  66. }
  67.  
  68. int randInt(int a, int b)
  69. {
  70.     return rand() % (b - a) + a;
  71. }
  72.  
  73. double randDouble(double a, double b)
  74. {
  75.     return (rand() / (double)RAND_MAX) * (b - a) + a;
  76. }
  77.  
  78. double precos(int angle)
  79. {
  80.     while (angle < 0) {
  81.         angle += 360;
  82.     }
  83.     while (angle > 360) {
  84.         angle -= 360;
  85.     }
  86.     return COS[angle];
  87. }
  88.  
  89. double presin(int angle)
  90. {
  91.     while (angle < 0) {
  92.         angle += 360;
  93.     }
  94.     while (angle > 360) {
  95.         angle -= 360;
  96.     }
  97.     return SIN[angle];
  98. }
  99.  
  100. void precalculateCosSin()
  101. {
  102.     int idx = 0;
  103.     for (int i = -359; i <= 360; i++) {
  104.         double rad = degToRad((float)i);
  105.         COS[idx] = cos(rad);
  106.         SIN[idx] = sin(rad);
  107.         idx++;
  108.     }
  109. }
  110.  
  111. // ***********************************************************
  112.  
  113. class Checkpoint {
  114. public:
  115.     int x, y;
  116.  
  117.     Checkpoint(int x, int y)
  118.     {
  119.         this->x = x;
  120.         this->y = y;
  121.     }
  122. };
  123.  
  124. // ***********************************************************
  125.  
  126. class Vector2D {
  127. public:
  128.     double dX, dY;
  129.  
  130.     Vector2D()
  131.     {
  132.         this->dX = 0.0;
  133.         this->dY = 0.0;
  134.     }
  135.  
  136.     Vector2D(Vector2D* from)
  137.     {
  138.         this->dX = from->dX;
  139.         this->dY = from->dY;
  140.     }
  141.  
  142.     Vector2D(double dX, double dY)
  143.     {
  144.         this->dX = dX;
  145.         this->dY = dY;
  146.     }
  147.  
  148.     void copy(Vector2D* v)
  149.     {
  150.         this->dX = v->dX;
  151.         this->dY = v->dY;
  152.     }
  153.  
  154.     double sqrLength()
  155.     {
  156.         return this->dX * this->dX + this->dY * this->dY;
  157.     }
  158.  
  159.     double length()
  160.     {
  161.         return sqrt(this->dX * this->dX + this->dY * this->dY);
  162.     }
  163.  
  164.     void add(Vector2D* v1)
  165.     {
  166.         this->dX += v1->dX;
  167.         this->dY += v1->dY;
  168.     }
  169.  
  170.     void add(Vector2D* v1, double factor)
  171.     {
  172.         this->dX += v1->dX * factor;
  173.         this->dY += v1->dY * factor;
  174.     }
  175.  
  176.     void sub(Vector2D* v1)
  177.     {
  178.         this->dX -= v1->dX;
  179.         this->dY -= v1->dY;
  180.     }
  181.  
  182.     void sub(Vector2D* v1, double factor)
  183.     {
  184.         this->dX -= v1->dX * factor;
  185.         this->dY -= v1->dY * factor;
  186.     }
  187.  
  188.     void scale(double scaleFactor)
  189.     {
  190.         this->dX *= scaleFactor;
  191.         this->dY *= scaleFactor;
  192.     }
  193.  
  194.     void normalize()
  195.     {
  196.         double length = sqrt(this->dX * this->dX + this->dY * this->dY);
  197.         if (length != 0) {
  198.             this->dX /= length;
  199.             this->dY /= length;
  200.         }
  201.     }
  202.  
  203.     double dotProduct(Vector2D& v1)
  204.     {
  205.         return this->dX * v1.dX + this->dY * v1.dY;
  206.     }
  207. };
  208.  
  209. // ***********************************************************
  210.  
  211. class Command {
  212. public:
  213.     int angle, th;
  214.     bool shield;
  215.  
  216.     Command(int angle, int th, bool shield)
  217.     {
  218.         this->angle = angle;
  219.         this->th = th;
  220.         this->shield = shield;
  221.     }
  222.  
  223.     void copy(Command* from)
  224.     {
  225.         this->th = from->th;
  226.         this->angle = from->angle;
  227.         this->shield = from->shield;
  228.     }
  229.  
  230.     void randomize(bool allowShield)
  231.     {
  232.         angle = randInt(0, 37) - 18;
  233.         if (angle > 18)
  234.             angle = 18;
  235.         if (angle < -18)
  236.             angle = -18;
  237.         if (allowShield && randInt(0, 101) > 80) {
  238.             shield = true;
  239.             th = -1;
  240.         }
  241.         else {
  242.             shield = false;
  243.             th = randInt(0, 101);
  244.         }
  245.     }
  246.  
  247.     void smallMutation(bool allowShield)
  248.     {
  249.         if (randInt(0, 101) > 50) {
  250.             angle += randInt(0, 7) - 3;
  251.             if (angle > 18)
  252.                 angle = 18;
  253.             if (angle < -18)
  254.                 angle = -18;
  255.         }
  256.         else {
  257.             if (allowShield && randInt(0, 101) > 90) {
  258.                 shield = true;
  259.                 th = -1;
  260.             }
  261.             else {
  262.                 shield = false;
  263.                 th += randInt(0, 15) - 5;
  264.                 if (th > 100)
  265.                     th = 100;
  266.                 if (th < 0)
  267.                     th = 0;
  268.             }
  269.         }
  270.     }
  271. };
  272.  
  273. // ***********************************************************
  274.  
  275. class Drone {
  276. public:
  277.     int id, cpTodo, rotation, shieldTimer, nextCp, nextNextCp;
  278.     bool mine;
  279.     double x, y;
  280.     Vector2D* speed;
  281.  
  282.     ~Drone()
  283.     {
  284.         my_delete(this->speed);
  285.     }
  286.  
  287.     Drone(int id)
  288.     {
  289.         this->nextCp = -1;
  290.         this->nextNextCp = -1;
  291.         this->id = id;
  292.         this->mine = id < 2;
  293.         this->speed = new Vector2D();
  294.     }
  295.  
  296.     void copy(Drone* from)
  297.     {
  298.         this->shieldTimer = from->shieldTimer;
  299.         this->id = from->id;
  300.         this->mine = from->mine;
  301.         this->rotation = from->rotation;
  302.         this->x = from->x;
  303.         this->y = from->y;
  304.         this->speed->copy(from->speed);
  305.         this->cpTodo = from->cpTodo;
  306.         this->nextCp = from->nextCp;
  307.         this->nextNextCp = from->nextNextCp;
  308.     }
  309.  
  310.     void setCheapRaceCmd(Command* cmd)
  311.     {
  312.         if (nextCp == -1) {
  313.             cmd->th = 0;
  314.             cmd->angle = 0;
  315.             cmd->shield = false;
  316.             return;
  317.         }
  318.         Checkpoint* cp = checkPoints[nextCp];
  319.         int degAngle = angleWithPoint(cp->x, cp->y);
  320.         int th = 100;
  321.         int sqrCpD = getNextCpSquaredD();
  322.        
  323.         if (abs(degAngle) > 90) {
  324.             th=20;
  325.         } else if(sqrCpD < 1000000) {
  326.             th=55;
  327.         } else if (sqrCpD < 250000) {
  328.             th=40;
  329.         } else {
  330.             th=100;
  331.         }
  332.        
  333.         if (degAngle < -18) {
  334.             degAngle = -18;
  335.         }
  336.         if (degAngle > 18) {
  337.             degAngle = 18;
  338.         }
  339.            
  340.         cmd->th = th;
  341.         cmd->angle = degAngle;
  342.         cmd->shield = false;
  343.     }
  344.    
  345.     void setCheapSupportCmd(Command* cmd, Drone* target)
  346.     {
  347.         int degAngle = angleWithPoint(target->x, target->y);
  348.         int th = 100;
  349.        
  350.         if (abs(degAngle) > 90) {
  351.             th=20;
  352.         }
  353.        
  354.         if (degAngle < -18) {
  355.             degAngle = -18;
  356.         }
  357.         if (degAngle > 18) {
  358.             degAngle = 18;
  359.         }
  360.        
  361.         cmd->th = th;
  362.         cmd->angle = degAngle;
  363.         cmd->shield = false;
  364.     }
  365.  
  366.     void setCPCmd(Command* cmd, Checkpoint* cp, int th)
  367.     {
  368.         if (cp == NULL) {
  369.             cmd->th = 0;
  370.             cmd->angle = 0;
  371.             cmd->shield = false;
  372.             return;
  373.         }
  374.         int degAngle = angleWithPoint(cp->x, cp->y);
  375.         if (turn > 0) {
  376.             if (degAngle < -18) {
  377.                 degAngle = -18;
  378.             }
  379.             if (degAngle > 18) {
  380.                 degAngle = 18;
  381.             }
  382.         }
  383.         cmd->th = th;
  384.         cmd->angle = degAngle;
  385.         cmd->shield = false;
  386.     }
  387.  
  388.     void setNextCPCmd(Command* cmd, int th)
  389.     {
  390.         if (nextCp == -1) {
  391.             cmd->th = 0;
  392.             cmd->angle = 0;
  393.             cmd->shield = false;
  394.             return;
  395.         }
  396.         setCPCmd(cmd, checkPoints[nextCp], th);
  397.     }
  398.  
  399.     void updateCpState()
  400.     {
  401.         int squaredDistance = getNextCpSquaredD();
  402.         if (nextCp != -1 && squaredDistance <= CP_RADIUS * CP_RADIUS) {
  403.             cpTodo--;
  404.             nextCp = nextNextCp;
  405.             if (nextCp != -1) {
  406.                 nextNextCp = (nextCp + 1) % checkpointCount;
  407.             }
  408.             else {
  409.                 nextNextCp = -1;
  410.             }
  411.         }
  412.     }
  413.  
  414.     void moveDuring(double t)
  415.     {
  416.         MOVDUR_CALL++;
  417.         x += speed->dX * t;
  418.         y += speed->dY * t;
  419.     }
  420.  
  421.     double collisionTime(Drone* drone)
  422.     {
  423.         double a, b, c, d;
  424.  
  425.         a = (speed->dX - drone->speed->dX) * (speed->dX - drone->speed->dX) + (speed->dY - drone->speed->dY) * (speed->dY - drone->speed->dY);
  426.         b = 2 * (x * speed->dX - drone->x * speed->dX - x * drone->speed->dX + drone->x * drone->speed->dX + y * speed->dY - drone->y * speed->dY - y * drone->speed->dY + drone->y * drone->speed->dY);
  427.         c = (drone->x - x) * (drone->x - x) + (drone->y - y) * (drone->y - y) - (DRONE_RADIUS + DRONE_RADIUS) * (DRONE_RADIUS + DRONE_RADIUS);
  428.         d = b * b - 4 * a * c;
  429.  
  430.         if (a == 0 || d < 0) {
  431.             return 999999;
  432.         }
  433.         else {
  434.             double t = (-b - sqrt(d)) / (2 * a);
  435.             return t > 0 ? t : 999999;
  436.         }
  437.     }
  438.  
  439.     int angleWithPoint(int tx, int ty)
  440.     {
  441.         double radAngle = atan2(ty - y, tx - x) - atan2(presin(rotation), precos(rotation));
  442.         int result = radToDeg(radAngle);
  443.         result += (result > 180) ? -360 : (result < -180) ? 360 : 0;
  444.         return result;
  445.     }
  446.  
  447.     int getPointSquaredD(int tx, int ty)
  448.     {
  449.         return (x - tx) * (x - tx) + (y - ty) * (y - ty);
  450.     }
  451.  
  452.     int getNextCpSquaredD()
  453.     {
  454.         if (nextCp == -1) {
  455.             return 0;
  456.         }
  457.         else {
  458.             return getPointSquaredD(checkPoints[nextCp]->x, checkPoints[nextCp]->y);
  459.         }
  460.     }
  461. };
  462. // ***********************************************************
  463.  
  464. class Chromosome {
  465. public:
  466.     Command* commands[SIM_DEPTH * 4]; // Les commandes des drones [turn*4 + droneId]
  467.     double score;
  468.  
  469.     ~Chromosome()
  470.     {
  471.         for (int i = 0; i < SIM_DEPTH * 4; i++) {
  472.             delete commands[i];
  473.         }
  474.     }
  475.  
  476.     Chromosome()
  477.     {
  478.         for (int i = 0; i < SIM_DEPTH * 4; i++) {
  479.             commands[i] = new Command(0, 0, false);
  480.         }
  481.     }
  482.  
  483.     void copy(Chromosome* ch)
  484.     {
  485.         for (int turn = 0; turn < SIM_DEPTH; turn++) {
  486.             for (int did = 0; did < 2; did++) {
  487.                 this->commands[turn * 4 + did]->copy(ch->commands[turn * 4 + did]);
  488.             }
  489.             // for (int did = 2; did < 4; did++) {
  490.             //     this->commands[turn * 4 + did] = NULL;
  491.             // }
  492.         }
  493.     }
  494.  
  495.     bool shieldUser()
  496.     {
  497.         return commands[0]->shield || commands[1]->shield;
  498.     }
  499. };
  500.  
  501. // ***********************************************************
  502.  
  503. class Simulator {
  504. public:
  505.     Drone* testedDrones[4]; // Les drones à utiliser pour la simulation
  506.     Chromosome* chromosome;
  507.  
  508.     ~Simulator()
  509.     {
  510.         for (int i = 0; i < 4; i++) {
  511.             delete testedDrones[i];
  512.         }
  513.     }
  514.  
  515.     Simulator(Chromosome* chromosome)
  516.     {
  517.         for (int i = 0; i < 4; i++) {
  518.             testedDrones[i] = new Drone(i);
  519.             testedDrones[i]->copy(drones[i]);
  520.         }
  521.         this->chromosome = chromosome;
  522.     }
  523.  
  524.     /**
  525.      * 1    YOLO        Tout faire pour empecher le runner ennemi de traverser son prochain CP
  526.      * .                Maximiser distance entre lui et son CP. Puis minimiser distance entre mon runner et lui, et entre mon chaser et son CP.
  527.      * <p>
  528.      * 2    CLASSIC1    Priorité au score de mon runner. Maximiser distance entre runner adverse et son CP. Puis minimiser distance entre mon chaser et le runner adverse.
  529.      * <p>
  530.      * 3    CLASSIC1    Priorité au score de mon runner. Maximiser distance entre runner adverse et son CP. Puis minimiser distance entre mon chaser et le prochain CP du runner adverse.
  531.      * .
  532.      * 4    FINISH1     I'm ahead and I have 1 CP left. Rammener mon chaser en support.
  533.      */
  534.     double evaluate()
  535.     {
  536.         double score = 0;
  537.  
  538.         Drone* tMyRunner = testedDrones[MYRUNNER];
  539.         Drone* tMySupport = testedDrones[MYSUPPORT];
  540.         Drone* tHisRunner = testedDrones[HISRUNNER];
  541.         Drone* tHisSupport = testedDrones[HISSUPPORT];
  542.  
  543.         /**
  544.          * Je suis plus pret de son NCP que lui -> TARGET HIM
  545.          * Il est plus pret de son NCP que moi -> TARGET NNCP
  546.          */
  547.  
  548.         switch (STRATEGY) {
  549.         case 1: {
  550.             score += 1 * getDistanceScore(testedDrones[MYSUPPORT], (int)testedDrones[HISRUNNER]->x, (int)testedDrones[HISRUNNER]->y);
  551.             score += 1 * getDistanceScore(testedDrones[MYRUNNER], (int)testedDrones[HISRUNNER]->x, (int)testedDrones[HISRUNNER]->y);
  552.             score -= 8 * getRaceScore(testedDrones[HISRUNNER]);
  553.             break;
  554.         }
  555.         case 2: {
  556.             score += 6 * getRaceScore(testedDrones[MYRUNNER]);
  557.             score -= 3 * getRaceScore(testedDrones[HISRUNNER]);
  558.             score += 0.5 * getDistanceScore(testedDrones[MYSUPPORT], (int)testedDrones[HISRUNNER]->x, (int)testedDrones[HISRUNNER]->y);
  559.             break;
  560.         }
  561.         case 3: {
  562.             score += 6 * getRaceScore(testedDrones[MYRUNNER]);
  563.             score -= 3 * getRaceScore(testedDrones[HISRUNNER]);
  564.             if (testedDrones[HISRUNNER]->nextCp != -1) {
  565.                 score += 0.5 * getDistanceScore(testedDrones[MYSUPPORT], checkPoints[testedDrones[HISRUNNER]->nextCp]->x, checkPoints[testedDrones[HISRUNNER]->nextCp]->y);
  566.             }
  567.             else {
  568.                 score += 0.5 * getDistanceScore(testedDrones[MYSUPPORT], (int)testedDrones[HISRUNNER]->x, (int)testedDrones[HISRUNNER]->y);
  569.             }
  570.             int angle = abs(testedDrones[MYSUPPORT]->angleWithPoint((int)testedDrones[HISRUNNER]->x, (int)testedDrones[HISRUNNER]->y));
  571.             score -= (((double)10) * angle) / 180;
  572.             break;
  573.         }
  574.         case 4: {
  575.             score += getRaceScore(tMyRunner);
  576.             score += getRaceScore(tMySupport);
  577.             break;
  578.         }
  579.         }
  580.  
  581.         return score;
  582.     }
  583.  
  584.     double getRaceScore(Drone* drone)
  585.     {
  586.         double maxv = 3 * 337000000;
  587.         double score = 0;
  588.         score += (drones[drone->id]->cpTodo - drone->cpTodo) * 337000000;
  589.         score += max(337000000 - drone->getNextCpSquaredD(), 0);
  590.         score = (100 * score) / maxv;
  591.         return score;
  592.     }
  593.  
  594.     // The higher score the closer to the target
  595.     double getDistanceScore(Drone* drone, int tx, int ty)
  596.     {
  597.         double score = 0;
  598.         score += max(337000000 - drone->getPointSquaredD(tx, ty), 0);
  599.         score = (100 * score) / 337000000;
  600.         return score;
  601.     }
  602.  
  603.     void launchSimulation()
  604.     {
  605.         for (int turn = 0; turn < SIM_DEPTH; turn++) {
  606.             double turnTime = 0;
  607.  
  608.             // Application des nouvelles vitesses en fonction des commandes
  609.             preTurnUpdates(turn);
  610.  
  611.             while (turnTime < 1) {
  612.                 double nextColT = 999;
  613.                 int cold1 = -1, cold2 = -1;
  614.                 for (int did1 = 0; did1 < 4; did1++) {
  615.                     for (int did2 = did1 + 1; did2 < 4; did2++) {
  616.                         if (did1 != did2) {
  617.                             double colTime = testedDrones[did1]->collisionTime(testedDrones[did2]);
  618.  
  619.                             // Collision occuring before the end of the turn
  620.                             if (turnTime + colTime < 1 && colTime < nextColT) {
  621.                                 nextColT = colTime;
  622.                                 cold1 = did1;
  623.                                 cold2 = did2;
  624.                             }
  625.                         }
  626.                     }
  627.                 }
  628.  
  629.                 // Collision occured
  630.                 if (cold1 != -1 && cold2 != -1) {
  631.                     // Drones are moved until the collision time
  632.                     for (int did = 0; did < 4; did++) {
  633.                         testedDrones[did]->moveDuring(nextColT);
  634.                     }
  635.                     // Bounce is computed and speeds are updated
  636.                     computeBounce(cold1, cold2);
  637.  
  638.                     turnTime += nextColT;
  639.                 }
  640.                 else {
  641.                     break;
  642.                 }
  643.             }
  644.  
  645.             // Drones are moved until the end of the turn
  646.             for (int did = 0; did < 4; did++) {
  647.                 testedDrones[did]->moveDuring(1 - turnTime);
  648.             }
  649.  
  650.             // Trunc/round des vitesses et positions, application de la friction, update de la rotation
  651.             postTurnUpdates(turn);
  652.         }
  653.     }
  654.  
  655.     /**
  656.      * Ajuste les vitesses des drones suite à la collision en cours entre eux deux
  657.      */
  658.     void computeBounce(int did1, int did2)
  659.     {
  660.         BOUNCE_CALL++;
  661.         Drone* d1 = testedDrones[did1];
  662.         Drone* d2 = testedDrones[did2];
  663.  
  664.         double d1mass = d1->shieldTimer == SHIELD_TIMER ? 10 : 1;
  665.         double d2mass = d2->shieldTimer == SHIELD_TIMER ? 10 : 1;
  666.  
  667.         Vector2D normalVector(d1->x - d2->x, d1->y - d2->y);
  668.         normalVector.normalize();
  669.         Vector2D relativeVelocity(d1->speed->dX - d2->speed->dX, d1->speed->dY - d2->speed->dY);
  670.         double dp = normalVector.dotProduct(relativeVelocity);
  671.         normalVector.scale(dp / ((1 / d1mass) + (1 / d2mass)));
  672.  
  673.         d1->speed->dX -= normalVector.dX * (1 / d1mass);
  674.         d1->speed->dY -= normalVector.dY * (1 / d1mass);
  675.         d2->speed->dX += normalVector.dX * (1 / d2mass);
  676.         d2->speed->dY += normalVector.dY * (1 / d2mass);
  677.  
  678.         normalVector.scale(max(120 / normalVector.length(), double(1)));
  679.  
  680.         d1->speed->dX -= normalVector.dX * (1 / d1mass);
  681.         d1->speed->dY -= normalVector.dY * (1 / d1mass);
  682.         d2->speed->dX += normalVector.dX * (1 / d2mass);
  683.         d2->speed->dY += normalVector.dY * (1 / d2mass);
  684.     }
  685.  
  686.     /**
  687.      * Applique les nouvelles vitesses sans changer les positions
  688.      */
  689.     void preTurnUpdates(int depth)
  690.     {
  691.         for (int did = 0; did < 4; did++) {
  692.             Command* cmd = chromosome->commands[depth * 4 + did];
  693.             Drone* drone = testedDrones[did];
  694.  
  695.             // Ennemy command
  696.             if (did > 1) {
  697.                 if (did == HISRUNNER) {
  698.                     drone->setCheapRaceCmd(cmd);
  699.                 } else {
  700.                     drone->setCheapSupportCmd(cmd, testedDrones[MYRUNNER]);
  701.                 }
  702.                 //cheapPlay(cmd, drone);
  703.             }
  704.  
  705.             if (cmd->shield) {
  706.                 drone->shieldTimer = SHIELD_TIMER;
  707.             }
  708.             else {
  709.                 if (drone->shieldTimer > 0) {
  710.                     drone->shieldTimer--;
  711.                 }
  712.             }
  713.  
  714.             if (drone->shieldTimer == 0) {
  715.                 drone->speed->dX += precos(drone->rotation + cmd->angle) * cmd->th;
  716.                 drone->speed->dY += presin(drone->rotation + cmd->angle) * cmd->th;
  717.             }
  718.         }
  719.     }
  720.  
  721.     void postTurnUpdates(int depth)
  722.     {
  723.         for (int did = 0; did < 4; did++) {
  724.             Command* cmd = chromosome->commands[depth * 4 + did];
  725.             Drone* drone = testedDrones[did];
  726.  
  727.             drone->speed->dX *= FRICTION;
  728.             drone->speed->dY *= FRICTION;
  729.  
  730.             drone->speed->dX = floor(drone->speed->dX);
  731.             if (drone->speed->dX < 0) {
  732.                 drone->speed->dX++;
  733.             }
  734.             drone->speed->dY = floor(drone->speed->dY);
  735.             if (drone->speed->dY < 0) {
  736.                 drone->speed->dY++;
  737.             }
  738.  
  739.             drone->x = (int)round(drone->x);
  740.             drone->y = (int)round(drone->y);
  741.             drone->rotation += cmd->angle;
  742.  
  743.             if (drone->shieldTimer > 0)
  744.                 drone->shieldTimer--;
  745.  
  746.             drone->updateCpState();
  747.         }
  748.     }
  749. };
  750.  
  751. // ***********************************************************
  752.  
  753. bool dronePositionsPredicate(Drone* a, Drone* b)
  754. {
  755.     if (a->cpTodo != b->cpTodo) {
  756.         return a->cpTodo < b->cpTodo;
  757.     }
  758.     else {
  759.         return a->getNextCpSquaredD() < b->getNextCpSquaredD();
  760.     }
  761. }
  762.  
  763. void setDroneRoles()
  764. {
  765.     MYRUNNER = -1;
  766.     MYSUPPORT = -1;
  767.     HISRUNNER = -1;
  768.     HISSUPPORT = -1;
  769.  
  770.     sort(dronePositions.begin(), dronePositions.end(), dronePositionsPredicate);
  771.  
  772.     for (int i = 0; i < dronePositions.size(); i++) {
  773.         if (dronePositions[i]->mine) {
  774.             if (MYRUNNER == -1) {
  775.                 MYRUNNER = dronePositions[i]->id;
  776.             }
  777.             else {
  778.                 MYSUPPORT = dronePositions[i]->id;
  779.             }
  780.         }
  781.         else {
  782.             if (HISRUNNER == -1) {
  783.                 HISRUNNER = dronePositions[i]->id;
  784.             }
  785.             else {
  786.                 HISSUPPORT = dronePositions[i]->id;
  787.             }
  788.         }
  789.     }
  790.  
  791.     cerr << "MYRUN:" << MYRUNNER << " MYSUP:" << MYSUPPORT << " HISRUN:" << HISRUNNER << " HISSUP:" << HISSUPPORT << " // MYT:" << MYTIMEOUT << " HIST:" << HISTIMEOUT << endl;
  792. }
  793.  
  794. void cheapPlay(Command* cmd, Drone* drone)
  795. {
  796.     Checkpoint* cp;
  797.     if (drone->nextCp != -1) {
  798.         cp = checkPoints[drone->nextCp];
  799.     }
  800.     else {
  801.         cp = checkPoints[0];
  802.     }
  803.     double ncpd = drone->getNextCpSquaredD();
  804.     double speed = drone->speed->length();
  805.     if (ncpd < 1500 * 1500 && speed > 250 && drone->nextNextCp != -1) {
  806.         drone->setCPCmd(cmd, checkPoints[drone->nextNextCp], 25);
  807.     }
  808.     else if (ncpd > 4000 * 4000) {
  809.         drone->setCPCmd(cmd, cp, 100);
  810.     }
  811.     else {
  812.         drone->setCPCmd(cmd, cp, 40);
  813.     }
  814. }
  815.  
  816. void initGeneticPopulation(array<Chromosome*, GEN_POP_SIZE> population)
  817. {
  818.     Command* dummy0 = new Command(0, 0, false);
  819.     cheapPlay(dummy0, drones[0]);
  820.     Command* dummy1 = new Command(0, 0, false);
  821.     cheapPlay(dummy1, drones[1]);
  822.  
  823.     // 3/4, des petites mutations sur les commandes dummy
  824.     for (int chromId = 0; chromId < (3 * GEN_POP_SIZE) / 4; chromId++) {
  825.         Chromosome* ch = population[chromId];
  826.         ch->score = 0;
  827.         for (int level = 0; level < SIM_DEPTH; level++) {
  828.             ch->commands[level * 4]->copy(dummy0);
  829.             ch->commands[level * 4 + 1]->copy(dummy1);
  830.             if (level < 3) { // On ne mute que les premiers tours
  831.                 ch->commands[level * 4]->smallMutation(level == 0);
  832.                 ch->commands[level * 4 + 1]->smallMutation(level == 0);
  833.             }
  834.             else {
  835.                 ch->commands[level * 4]->randomize(level == 0);
  836.                 ch->commands[level * 4 + 1]->randomize(level == 0);
  837.             }
  838.         }
  839.     }
  840.  
  841.     // 1/4, full random
  842.     for (int chromId = (3 * GEN_POP_SIZE) / 4; chromId < GEN_POP_SIZE; chromId++) {
  843.         Chromosome* ch = population[chromId];
  844.         ch->score = 0;
  845.         for (int level = 0; level < SIM_DEPTH; level++) {
  846.             ch->commands[level * 4]->randomize(level == 0);
  847.             ch->commands[level * 4 + 1]->randomize(level == 0);
  848.             // ch->commands[level * 4 + 2] = NULL;
  849.             // ch->commands[level * 4 + 3] = NULL;
  850.         }
  851.     }
  852.  
  853.     my_delete(dummy0);
  854.     my_delete(dummy1);
  855. }
  856.  
  857. bool chromScorePredicate(Chromosome* c1, Chromosome* c2)
  858. {
  859.     return c1->score > c2->score;
  860. }
  861.  
  862. void getNextGeneticPopulation(array<Chromosome*, GEN_POP_SIZE> oldPopulation, array<Chromosome*, GEN_POP_SIZE> newPopulation)
  863. {
  864.     // Tri de la population, les premiers sont les meilleurs
  865.     sort(oldPopulation.begin(), oldPopulation.end(), chromScorePredicate);
  866.  
  867.     /**
  868.      * Croisement entre deux chromosomes = 1 swap de commande
  869.      * Mutation d'un chromosome = 1 mutation légère sur une commande choisie aléatoirement
  870.      *
  871.      * 1/2 : croisements entre paire de chromosomes issue du top 50%
  872.      * 3/8 : mutations aléatoires sur chromosomes issus du top 50%
  873.      * 1/8 : full random
  874.      */
  875.  
  876.     // Ajoute des paires de chromosomes dans la liste
  877.     for (int i = 0; i < GEN_POP_SIZE / 2; i += 2) {
  878.         Chromosome* ch1 = oldPopulation[randInt(0, GEN_POP_SIZE / 2)];
  879.         Chromosome* ch2 = oldPopulation[randInt(0, GEN_POP_SIZE / 2)];
  880.         Chromosome* nch1 = newPopulation[i];
  881.         nch1->copy(ch1);
  882.         nch1->score = 0;
  883.         Chromosome* nch2 = newPopulation[i + 1];
  884.         nch2->copy(ch2);
  885.         nch2->score = 0;
  886.  
  887.         int crossLevel = randInt(0, SIM_DEPTH);
  888.         int crossDid = randInt(0, 2);
  889.         Command* tmp = nch1->commands[crossLevel * 4 + crossDid];
  890.         nch1->commands[crossLevel * 4 + crossDid] = nch2->commands[crossLevel * 4 + crossDid];
  891.         nch2->commands[crossLevel * 4 + crossDid] = tmp;
  892.  
  893.         crossLevel = randInt(0, SIM_DEPTH);
  894.         crossDid = randInt(0, 2);
  895.         tmp = nch1->commands[crossLevel * 4 + crossDid];
  896.         nch1->commands[crossLevel * 4 + crossDid] = nch2->commands[crossLevel * 4 + crossDid];
  897.         nch2->commands[crossLevel * 4 + crossDid] = tmp;
  898.     }
  899.  
  900.     for (int i = GEN_POP_SIZE / 2; i < ((15 * GEN_POP_SIZE) / 16); i++) {
  901.         Chromosome* ch = oldPopulation[randInt(0, GEN_POP_SIZE / 2)];
  902.         Chromosome* nch = newPopulation[i];
  903.         nch->copy(ch);
  904.         nch->score = 0;
  905.         int crossLevel = randInt(0, SIM_DEPTH);
  906.         int crossDid = randInt(0, 2);
  907.         nch->commands[crossLevel * 4 + crossDid]->smallMutation(crossLevel == 0);
  908.  
  909.         crossLevel = randInt(0, SIM_DEPTH);
  910.         crossDid = randInt(0, 2);
  911.         nch->commands[crossLevel * 4 + crossDid]->smallMutation(crossLevel == 0);
  912.     }
  913.  
  914.     for (int i = ((15 * GEN_POP_SIZE) / 16); i < GEN_POP_SIZE; i++) {
  915.         Chromosome* ch = newPopulation[i];
  916.         ch->score = 0;
  917.         for (int level = 0; level < SIM_DEPTH; level++) {
  918.             ch->commands[level * 4]->randomize(level == 0);
  919.             ch->commands[level * 4 + 1]->randomize(level == 0);
  920.             // ch->commands[level * 4 + 2] = NULL;
  921.             // ch->commands[level * 4 + 3] = NULL;
  922.         }
  923.     }
  924. }
  925.  
  926. void play(Command* cmd0, Command* cmd1)
  927. {
  928.     int geneticBatch = 0;
  929.     double bestScore = -9999999;
  930.     int bestScoreBatchN = 0;
  931.  
  932.     array<Chromosome*, GEN_POP_SIZE> pop;
  933.     array<Chromosome*, GEN_POP_SIZE> oldPop;
  934.     for (int i = 0; i < GEN_POP_SIZE; i++) {
  935.         pop[i] = new Chromosome();
  936.         oldPop[i] = new Chromosome();
  937.     }
  938.     bool popInit = false;
  939.  
  940.     // SIM_BRAN < 20 * populationSize ||
  941.     while (elapsedMS() < 145) { // TODO : augmenter ?
  942.         if (!popInit) {
  943.             initGeneticPopulation(pop);
  944.             popInit = true;
  945.         }
  946.         else {
  947.             getNextGeneticPopulation(oldPop, pop);
  948.         }
  949.  
  950.         for (int chromId = 0; chromId < GEN_POP_SIZE; chromId++) {
  951.             Chromosome* chromosome = pop[chromId];
  952.             Simulator sim(chromosome);
  953.             sim.launchSimulation();
  954.             double score = sim.evaluate();
  955.             if (chromosome->shieldUser()) {
  956.                 score -= 2;
  957.             }
  958.             chromosome->score = score;
  959.  
  960.             if (score > bestScore) {
  961.                 bestScore = score;
  962.                 bestScoreBatchN = geneticBatch;
  963.                 cmd0->copy(chromosome->commands[0]);
  964.                 cmd1->copy(chromosome->commands[1]);
  965.             }
  966.  
  967.             SIM_BRAN++;
  968.         }
  969.         swap(pop, oldPop); // TODO swap toute la liste et pas tous les pointeurs un par un
  970.         geneticBatch++;
  971.     }
  972.  
  973.     for (int i = 0; i < GEN_POP_SIZE; i++) {
  974.         delete pop[i];
  975.         delete oldPop[i];
  976.     }
  977.  
  978.     cerr << "Best score = " << bestScore << " from batch n." << bestScoreBatchN << "/" << (geneticBatch - 1) << endl;
  979. }
  980.  
  981. void choseStrategy()
  982. {
  983.     if (MYTIMEOUT < 30) {
  984.         STRATEGY = 4;
  985.     }
  986.     else if (!dronePositions[0]->mine && drones[MYRUNNER]->cpTodo - drones[HISRUNNER]->cpTodo > 4 && MYTIMEOUT > HISTIMEOUT) {
  987.         // Je suis deuxieme, j'ai au moins 4 CP de retard sur le premier et j'ai un timeout plus grand que lui ..
  988.         STRATEGY = 1; // YOLO
  989.     }
  990.     else {
  991.         Vector2D v(drones[MYSUPPORT]->speed);
  992.         v.add(drones[HISRUNNER]->speed);
  993.  
  994.         if (v.length() > drones[HISRUNNER]->speed->length()) {
  995.             STRATEGY = 3;
  996.         }
  997.         else {
  998.             STRATEGY = 2;
  999.         }
  1000.     }
  1001. }
  1002.  
  1003. void outputInstruction(Command* cmd, Drone* drone)
  1004. {
  1005.     int tx = (int)(drone->x + precos(drone->rotation + cmd->angle) * 400);
  1006.     int ty = (int)(drone->y + presin(drone->rotation + cmd->angle) * 400);
  1007.     cout << tx << " " << ty << " " << (cmd->shield ? "SHIELD" : cmd->th == 650 ? "BOOST" : to_string(cmd->th)) << endl;
  1008. }
  1009.  
  1010. int main()
  1011. {
  1012.     cin >> laps;
  1013.     cin.ignore();
  1014.     cin >> checkpointCount;
  1015.     cin.ignore();
  1016.  
  1017.     totalCp = laps * checkpointCount;
  1018.     for (int i = 0; i < 4; i++) {
  1019.         drones.push_back(new Drone(i));
  1020.         drones[i]->cpTodo = laps * checkpointCount;
  1021.         dronePositions.push_back(drones[i]);
  1022.     }
  1023.  
  1024.     for (int i = 0; i < checkpointCount; i++) {
  1025.         int checkpointX;
  1026.         int checkpointY;
  1027.         cin >> checkpointX >> checkpointY;
  1028.         checkPoints.push_back(new Checkpoint(checkpointX, checkpointY));
  1029.         cin.ignore();
  1030.     }
  1031.     precalculateCosSin();
  1032.  
  1033.     // game loop
  1034.     while (1) {
  1035.         cpt = 0;
  1036.         BOUNCE_CALL = 0;
  1037.         MOVDUR_CALL = 0;
  1038.         SIM_BRAN = 0;
  1039.         for (int i = 0; i < 4; i++) {
  1040.             int x;
  1041.             int y;
  1042.             int vx;
  1043.             int vy;
  1044.             int angle;
  1045.             int nextCheckPointId;
  1046.             cin >> x >> y >> vx >> vy >> angle >> nextCheckPointId;
  1047.             cin.ignore();
  1048.  
  1049.             Drone* drone = drones[i];
  1050.             drone->x = x;
  1051.             drone->y = y;
  1052.             drone->speed->dX = vx;
  1053.             drone->speed->dY = vy;
  1054.             drone->rotation = angle;
  1055.             int oldncp = drone->nextCp;
  1056.             drone->nextCp = nextCheckPointId;
  1057.             if (oldncp != -1 && drone->nextCp != oldncp) {
  1058.                 drone->cpTodo--;
  1059.                 if (drone->mine) {
  1060.                     MYTIMEOUT = 100;
  1061.                 }
  1062.                 else {
  1063.                     HISTIMEOUT = 100;
  1064.                 }
  1065.             }
  1066.             drone->nextNextCp = drone->cpTodo == 1 ? -1 : (drone->nextCp + 1) % checkpointCount;
  1067.             if (drone->shieldTimer > 0) {
  1068.                 drone->shieldTimer--;
  1069.             }
  1070.         }
  1071.  
  1072.         MYTIMEOUT--;
  1073.         HISTIMEOUT--;
  1074.  
  1075.         gettimeofday(&timestart, NULL);
  1076.         setDroneRoles();
  1077.         choseStrategy();
  1078.  
  1079.         Command* cmd0 = new Command(0, 0, false);
  1080.         Command* cmd1 = new Command(0, 0, false);
  1081.         if (turn == 0) {
  1082.             drones[0]->setNextCPCmd(cmd0, 650);
  1083.             drones[1]->setNextCPCmd(cmd1, 650);
  1084.         }
  1085.         else {
  1086.             play(cmd0, cmd1);
  1087.         }
  1088.  
  1089.         float elapsed = elapsedMS();
  1090.         cerr << "turn in " << elapsed << " ms. Strategy " << STRATEGY << endl;
  1091.         cerr << SIM_BRAN << " simulated branches with BOUNCE_CALL:" << BOUNCE_CALL << " MOVDUR_CALL:" << MOVDUR_CALL << endl;
  1092.  
  1093.         if (cmd0->shield) {
  1094.             drones[0]->shieldTimer = SHIELD_TIMER + 1;
  1095.         }
  1096.         if (cmd1->shield) {
  1097.             drones[1]->shieldTimer = SHIELD_TIMER + 1;
  1098.         }
  1099.         outputInstruction(cmd0, drones[0]);
  1100.         outputInstruction(cmd1, drones[1]);
  1101.         my_delete(cmd0);
  1102.         my_delete(cmd1);
  1103.         turn++;
  1104.     }
  1105. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement