Advertisement
Guest User

The Accountant [CPC]Karedas

a guest
Oct 18th, 2016
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 17.82 KB | None | 0 0
  1. <?php
  2. /**
  3.  * Shoot enemies before they collect all the incriminating data!
  4.  * The closer you are to an enemy, the more damage you do but don't get too close or you'll get killed.
  5.  **/
  6.  
  7. $Jeu = new Jeu();
  8.  
  9. // game loop
  10. while (TRUE)
  11. {  
  12.     //récup position Wolff
  13.     fscanf(STDIN, "%d %d",
  14.         $x,
  15.         $y
  16.     );
  17.     $Jeu->wolff->setPosition($x, $y);
  18.    
  19.    
  20.     //Init data points
  21.     $Jeu->resetDataPoints();
  22.     fscanf(STDIN, "%d",
  23.         $dataCount
  24.     );
  25.     for ($i = 0; $i < $dataCount; $i++)
  26.     {
  27.         fscanf(STDIN, "%d %d %d",
  28.             $dataId,
  29.             $dataX,
  30.             $dataY
  31.         );
  32.         $Jeu->getDataPoint($dataId)->setPosition($dataX,$dataY);
  33.     }
  34.    
  35.     //init enemies
  36.     $Jeu->resetEnemies();
  37.     $Jeu->resetPredictedEnemies();
  38.     fscanf(STDIN, "%d",
  39.         $enemyCount
  40.     );
  41.     for ($i = 0; $i < $enemyCount; $i++)
  42.     {
  43.         fscanf(STDIN, "%d %d %d %d",
  44.             $enemyId,
  45.             $enemyX,
  46.             $enemyY,
  47.             $enemyLife
  48.         );
  49.         $Jeu->getEnemy($enemyId)->setPosition($enemyX,$enemyY);
  50.         $Jeu->getPredictedEnemy($enemyId)->setPosition($enemyX,$enemyY);
  51.         $Jeu->getEnemy($enemyId)->setLife($enemyLife);    
  52.         $Jeu->getPredictedEnemy($enemyId)->setLife($enemyLife);      
  53.        
  54.     }
  55.    
  56.    
  57.  
  58.  
  59.     // Write an action using echo(). DON'T FORGET THE TRAILING \n
  60.     // To debug (equivalent to var_dump): error_log(var_export($var, true));
  61.     $Jeu->compute();
  62.    
  63.  
  64.     //echo("MOVE 8000 4500\n"); // MOVE x y or SHOOT id
  65. }
  66.  
  67.  
  68.  
  69. class Jeu {
  70.    
  71.     const LARGEUR = 16000;
  72.     const HAUTEUR = 9000;
  73.     const MAXTOENEMY = 2550; //2800
  74.     const MAXTOSHOOT = 4800; //4800
  75.        
  76.     public $wolff = null;
  77.    
  78.     //2550 //4800 //19261
  79.    
  80.    
  81.     protected $enemies = array();
  82.     protected $predicted_enemies = array();    
  83.     protected $datapoints = array();
  84.    
  85.     /**
  86.      * Move Wolff
  87.      */
  88.      /*
  89.     protected $cardinaux  = array(
  90.         'N' => [0,-1000],
  91.         'NE'=> [707,-707],
  92.         'E' => [1000,0],
  93.         'SE'=> [707,707],
  94.         'S' => [0,1000],
  95.         'SW'=> [-707,707],
  96.         'W' => [-1000,0],
  97.         'NW'=> [-707,-707],            
  98.     );
  99.     */
  100.    
  101.     /*
  102.     protected $cardinaux  = array(
  103.         'N' => [0,-1000],
  104.         'NNE' => [500,-867],
  105.         'NE'=> [707,-707],
  106.         'NEE'=> [867,-500],
  107.         'E' => [1000,0],
  108.         'ESE' => [867,500],
  109.         'SE'=> [707,707],
  110.         'SES'=> [500,867],
  111.         'S' => [0,1000],
  112.         'SSW' => [-500,867],
  113.         'SW'=> [-707,707],
  114.         'SWW'=> [-867,500],
  115.         'W' => [-1000,0],
  116.         'WNW' => [-867,-500],
  117.         'NW'=> [-707,-707],  
  118.         'NWB'=> [-500,-867],  
  119.     );
  120.     */
  121.    
  122.     protected $cardinaux  = array(
  123.         '1' => [0,-1000],
  124.         '2' => [317,-950],
  125.         '3' => [448,-895],
  126.         '4' => [548,-837],
  127.         '5' => [633,-775],
  128.         '6' => [708,-708],
  129.         '7' => [775,-633],
  130.         '8' => [837,-548],
  131.         '9' => [895,-448],
  132.         '10' => [950,-317],
  133.         '11' => [1000,0],
  134.         '12' => [950,317],
  135.         '13' => [895,448],
  136.         '14' => [837,548],
  137.         '15' => [775,633],
  138.         '16' => [708,708],
  139.         '17' => [633,775],
  140.         '18' => [548,837],
  141.         '19' => [448,895],
  142.         '20' => [317,950],
  143.         '21' => [0,1000],
  144.         '22' => [-317,950],
  145.         '23' => [-448,895],
  146.         '24' => [-548,837],
  147.         '25' => [-633,775],
  148.         '26' => [-708,708],
  149.         '27' => [-775,633],
  150.         '28' => [-837,548],
  151.         '29' => [-895,448],
  152.         '30' => [-950,317],
  153.         '31' => [-1000,0],
  154.         '32' => [-950,-317],
  155.         '33' => [-895,-448],
  156.         '34' => [-837,-548],
  157.         '35' => [-775,-633],
  158.         '36' => [-708,-708],
  159.         '37' => [-633,-775],
  160.         '38' => [-548,-837],
  161.         '39' => [-448,-895],
  162.         '40' => [-317,-950],
  163.     );
  164.        
  165.    
  166.     public static function log($x) {
  167.         error_log(var_export($x, true));    
  168.     }
  169.        
  170.     /**
  171.      * Constructeur
  172.      */
  173.     public function __construct() {
  174.         $this->wolff = new Wolff();  
  175.         $this->initCardinaux();        
  176.     }
  177.    
  178.     /**
  179.      * Renvoi un DataPoint a partir de son id (l'instancie si besoin)
  180.      */
  181.     public function getDataPoint($id) {
  182.         if(!isset($this->datapoints[$id])) {
  183.             $this->datapoints[$id] = new DataPoint();
  184.             $this->datapoints[$id]->setId($id);
  185.         }
  186.         return $this->datapoints[$id];
  187.     }
  188.    
  189.     /**
  190.      * Renvoi un Enemy a partir de son id (l'instancie si besoin)
  191.      */
  192.     public function getEnemy($id) {
  193.         if(!isset($this->enemies[$id])) {
  194.             $this->enemies[$id] = new Enemy();  
  195.             $this->enemies[$id]->setId($id);
  196.         }
  197.         return $this->enemies[$id];
  198.     }
  199.    
  200.     /**
  201.      * Renvoi un Enemy a partir de son id (l'instancie si besoin)
  202.      */
  203.     public function getPredictedEnemy($id) {
  204.         if(!isset($this->predicted_enemies[$id])) {
  205.             $this->predicted_enemies[$id] = new Enemy();  
  206.             $this->predicted_enemies[$id]->setId($id);
  207.         }
  208.         return $this->predicted_enemies[$id];
  209.     }  
  210.    
  211.     public function resetEnemies() {
  212.         $this->enemies = [];
  213.     }
  214.    
  215.     public function resetPredictedEnemies() {
  216.         $this->predicted_enemies = [];
  217.     }
  218.    
  219.     public function resetDataPoints() {
  220.         $this->datapoints = [];
  221.     }
  222.    
  223.     public function compute() {
  224.         $this->predict();
  225.         if($this->getAway()) return;
  226.         if($this->getCloser()) return;
  227.         $this->shootNearest();        
  228.     }
  229.    
  230.    
  231.    
  232.    
  233.     public function getAway() {
  234.         $idMin = $this->getNearestId($this->wolff->getPosition(), $this->predicted_enemies);
  235.         $distMin = $this->predicted_enemies[$idMin]->getPosition()->getDistanceTo($this->wolff->getPosition());
  236.        
  237.         self::log('DIST MIN '.$distMin);
  238.         self::log('LIFE DIST MIN '.$this->predicted_enemies[$idMin]->getLife());
  239.        
  240.         $maxDist = 0;
  241.         $direction = 'N';
  242.        
  243.        
  244.         self::log('EVA FUITE: '.$distMin.' -> '.self::MAXTOENEMY);
  245.         if($distMin <= self::MAXTOENEMY) {
  246.            
  247.             //si un seul trop proche et tuable, on le tue            
  248.             $nb = $this->getNearestId($this->wolff->getPosition(), $this->predicted_enemies);
  249.             if($nb == 1)  {
  250.                 self::log('TUER LE TROP PROCHE');
  251.                 $degat = 125000/pow($distMin,1.2);
  252.                 $life = $this->predicted_enemies[$idMin]->getLife();
  253.                 if($life < $degat) {
  254.                     echo "SHOOT ".$idMin."\n";
  255.                     return true;
  256.                 }
  257.             }            
  258.            
  259.             //sinon on part au plus loin
  260.             foreach($this->cardinaux as $dir => $vecteur) {
  261.                 //simulation deplacement
  262.                 $newWolff = clone $this->wolff->getPosition();
  263.                 $x = $newWolff->getPosX()+$vecteur[0];
  264.                 $y = $newWolff->getPosY()+$vecteur[1];
  265.                
  266.                 if($x < 0) $x = 0;
  267.                 if($y < 0) $y = 0;
  268.                 if($x > self::LARGEUR) $x = self::LARGEUR;
  269.                 if($y > self::HAUTEUR) $y = self::HAUTEUR;
  270.                
  271.                 $newWolff->setPos($x,$y);
  272.                
  273.                 //recherche plus pres
  274.                 $id = $this->getNearestId($newWolff,$this->predicted_enemies);
  275.                 $dist = $this->predicted_enemies[$id]->getPosition()->getDistanceTo($newWolff);
  276.                
  277.                 self::log($dir.' -> '.$dist);
  278.                 if($dist > $maxDist) {
  279.                     self::log('bip');
  280.                     $maxDist = $dist;
  281.                     $direction = $dir;
  282.                 }                
  283.             }
  284.            
  285.             self::log('fuite -> '.$direction);
  286.             $newWolff = clone $this->wolff->getPosition();
  287.             $x = $newWolff->getPosX()+$this->cardinaux[$direction][0];
  288.             $y = $newWolff->getPosY()+$this->cardinaux[$direction][1];
  289.                
  290.             if($x < 0) $x = 0;
  291.             if($y < 0) $y = 0;
  292.             if($x > self::LARGEUR) $x = self::LARGEUR;
  293.             if($y > self::HAUTEUR) $y = self::HAUTEUR;
  294.            
  295.             echo "MOVE ".$x.' '.$y."\n";
  296.             return true;          
  297.         }    
  298.         return false;
  299.     }
  300.    
  301.    
  302.     public function getCloser() {        
  303.         $idMin = $this->getNearestToMe();
  304.         //$idMin = $this->getNearestToData();
  305.        
  306.         $distMin = $this->predicted_enemies[$idMin]->getPosition()->getDistanceTo($this->wolff->getPosition());
  307.        
  308.        
  309.         if($distMin > self::MAXTOSHOOT) {
  310.             $cible = $this->enemies[$idMin]->getPosition();
  311.             //$cible = $this->predicted_enemies[$idMin]->getPosition();
  312.             //$cible = $this->predicted_enemies[$idMin]->getDestintation();
  313.             //$cible =  $this->wolff->getPosition()->getBary($this->enemies[$idMin]->getPosition());    
  314.             //$cible = Point::getBary([$this->wolff->getPosition(),$this->enemies[$idMin]->getPosition(),$this->predicted_enemies[$idMin]->getDestintation()]);
  315.            
  316.            
  317.             echo "MOVE ".(int)$cible->getPosX().' '.(int)$cible->getPosY()."\n";
  318.             return true;
  319.         } else {
  320.             return false;
  321.         }
  322.     }    
  323.    
  324.     public function shootNearest() {        
  325.         $idMin = $this->getNearestToMe();        
  326.         //$idMin = $this->getNearestToData();
  327.         //$idMin = $this->getNearestToDataAndMe();
  328.        
  329.        
  330.         echo "SHOOT ".$idMin."\n";
  331.         return true;
  332.     }
  333.    
  334.     private function getNearestToMe() {
  335.         return $this->getNearestId($this->wolff->getPosition(), $this->predicted_enemies);
  336.     }
  337.  
  338.    
  339.     private function getNearestToData() {
  340.         $idMin = 0;
  341.         $distMin = 19000;        
  342.         foreach($this->predicted_enemies as $unit) {            
  343.             if($unit->getLife() <= 0) {
  344.                 continue;
  345.             }                    
  346.             if($unit->getPosition() == $unit->getDestintation()) {
  347.                 continue;
  348.             }
  349.             $dist = $unit->getPosition()->getDistanceTo($unit->getDestintation());
  350.            
  351.             /*
  352.             self::log('----------------');
  353.             self::log('id: '.$unit->getId());
  354.             self::log($unit->getDestintation());
  355.             self::log($dist);
  356.             */
  357.            
  358.             if($dist<$distMin) {
  359.                 $distMin = $dist;
  360.                 $idMin = $unit->getId();
  361.             }
  362.         }
  363.         self::log('---->'.$idMin.'<----');
  364.         return $idMin;
  365.     }
  366.  
  367.     private function getNearestToDataAndMe() {
  368.         $idMin = 0;
  369.         $distMin = 19000;        
  370.         foreach($this->predicted_enemies as $unit) {            
  371.             if($unit->getLife() <= 0) {
  372.                 continue;
  373.             }                    
  374.             if($unit->getPosition() == $unit->getDestintation()) {
  375.                 continue;
  376.             }
  377.             $dist = $unit->getPosition()->getDistanceTo($this->wolff->getPosition());
  378.             $dist += $unit->getPosition()->getDistanceTo($unit->getDestintation());
  379.            
  380.             /*
  381.             self::log('----------------');
  382.             self::log('id: '.$unit->getId());
  383.             self::log($unit->getDestintation());
  384.             self::log($dist);
  385.             */
  386.            
  387.             if($dist<$distMin) {
  388.                 $distMin = $dist;
  389.                 $idMin = $unit->getId();
  390.             }
  391.         }
  392.         self::log('---->'.$idMin.'<----');
  393.         return $idMin;
  394.     }
  395.  
  396.  
  397.  
  398.     private function getNearestId($origin, $haystack) {
  399.         $idMin = 0;
  400.         $distMin = 19000;        
  401.         foreach($haystack as $unit) {            
  402.             if($unit->getLife() <= 0) {
  403.                 continue;
  404.             }
  405.             $dist = $unit->getPosition()->getDistanceTo($origin);
  406.             if($dist<$distMin) {
  407.                 $distMin = $dist;
  408.                 $idMin = $unit->getId();
  409.             }
  410.         }
  411.         return $idMin;
  412.     }
  413.    
  414.    
  415.      private function getNbTooShort($origin, $haystack) {
  416.          $cnt = 0;
  417.         foreach($haystack as $unit) {            
  418.             if($unit->getLife() <= 0) {
  419.                 continue;
  420.             }
  421.             $dist = $unit->getPosition()->getDistanceTo($origin);
  422.             if($dist<self::MAXTOENEMY) {
  423.                 $cnt++;
  424.             }
  425.         }
  426.         return $cnt;
  427.     }
  428.    
  429.        
  430.    
  431.     private function predict() {
  432.         foreach($this->enemies as $id => $enemy) {                    
  433.             self::log('PREDICTION '.$id);
  434.             $nearestData = $this->getNearestId($enemy->getPosition(),$this->datapoints);  
  435.             self::log('    nearest data: '.$nearestData);            
  436.             $this->predicted_enemies[$id]->setDestination($this->datapoints[$nearestData]->getPosition());
  437.             $this->predicted_enemies[$id]->predictPosition();    
  438.             self::log('    prev pos: '.$this->predicted_enemies[$id]->getPosition()->toString());
  439.             self::log('    next pos: '.$this->predicted_enemies[$id]->getDestintation()->toString());
  440.         }      
  441.     }
  442.    
  443.    
  444.     private function initCardinaux() {
  445.         $this->cardinaux = [];
  446.         for($angle=0; $angle < 360; $angle+=5) {
  447.             $sin = sin($angle);
  448.             $cos = cos($angle);
  449.             $this->cardinaux[$angle] = [(int)($sin*1000), (int)($cos*1000)];          
  450.         }
  451.     }
  452.      
  453.    
  454. }
  455.  
  456.  
  457. class Unit {
  458.    
  459.     protected $id = null;
  460.     protected $vitesse = 0;  
  461.     protected $position = null;
  462.     protected $life = 1000000000;
  463.    
  464.     public function __construct() {
  465.         $this->position = new Point();  
  466.     }
  467.    
  468.     /**
  469.      * Positione l'unité
  470.      */
  471.     public function setPosition($x, $y) {
  472.         $this->position->setPos($x,$y);  
  473.     }
  474.    
  475.     public function getPosition() {
  476.         return $this->position;  
  477.     }
  478.    
  479.     public function setId($id) {
  480.         $this->id = $id;
  481.     }
  482.    
  483.     public function getId() {
  484.         return $this->id;  
  485.     }
  486.    
  487.     public function setLife($life) {
  488.         $this->life = $life;
  489.     }
  490.    
  491.     public function getLife() {
  492.         return $this->life;  
  493.     }
  494.    
  495. }
  496.  
  497. class Datapoint extends Unit {
  498.    
  499. }
  500.  
  501. class Wolff extends Unit {    
  502.     protected $vitesse = 1000;        
  503.    
  504. }
  505.  
  506. class Enemy extends Unit {    
  507.     protected $vitesse = 500;  
  508.     protected $life = 0;    
  509.     protected $destination = null;
  510.        
  511.    
  512.     public function output() {
  513.         return array(
  514.             'id'    =>$this->id,
  515.             'life'  => $this->life,
  516.             );  
  517.     }
  518.    
  519.     public function getDestintation() {
  520.         return $this->destination;
  521.     }
  522.    
  523.     public function setDestination(Point $p) {
  524.         $this->destination = $p;
  525.     }
  526.        
  527.    
  528.     public function predictPosition() {
  529.         $vecteur = $this->destination->getVector($this->position);
  530.         $this->position->deplace($vecteur,$this->vitesse, $this->destination);    
  531.     }    
  532.        
  533. }
  534.  
  535.  
  536.  
  537.  
  538. /**
  539.  * Class point cartésien
  540.  */
  541. class Point {
  542.     public $x;  //abscisse
  543.     public $y;  //ordonée
  544.    
  545.     /**
  546.      * Construction du point
  547.      * @param type $x abscisse
  548.      * @param type $y ordonnée
  549.      */
  550.     function __construct($x=0, $y=0) {
  551.         $this->x = $x;
  552.         $this->y = $y;
  553.     }
  554.  
  555.     /**
  556.      * MAJ de la position du point
  557.      * @param type $x abscisse
  558.      * @param type $y ordonnée
  559.      */
  560.     function setPos($x, $y) {
  561.         $this->x = $x;
  562.         $this->y = $y;
  563.     }
  564.  
  565.     /**
  566.      * Recup Abscisse
  567.      * @return int abscisse
  568.      */
  569.     function getPosX() {
  570.         return $this->x;
  571.     }
  572.  
  573.     /**
  574.      * Recup Ordonnées
  575.      * @return int ordonnée
  576.      */
  577.     function getPosY() {
  578.         return $this->y;
  579.     }
  580.    
  581.     /**
  582.      * Renvoi la distance à un autre point
  583.      * @return int distance
  584.      */
  585.     function getDistanceTo(Point $p) {
  586.         return sqrt(pow($this->getPosX() - $p->getPosX(), 2) + pow($this->getPosY() - $p->getPosY(), 2));  
  587.     }
  588.    
  589.     /**
  590.      * Renvoi le vecteur entre 2 points
  591.      */
  592.     public function getVector(Point $p) {
  593.         return [
  594.             $this->getPosX()-$p->getPosX(),
  595.             $this->getPosY()-$p->getPosY(),
  596.             ];  
  597.     }
  598.    
  599.     public function deplace($vecteur, $vitesse, $destination) {
  600.         //si on arrive, on se place sur la destination
  601.         if($this->getDistanceTo($destination) < $vitesse) {
  602.             $this->position = $destination;
  603.             return;
  604.         }
  605.        
  606.         //sinon on calcule le deplacement
  607.         $sensX = $vecteur[0]>0 ? 1:-1;
  608.         $sensY = $vecteur[1]>0 ? 1:-1;
  609.         $vitCaree = $vitesse*$vitesse;                
  610.         $ratioX = abs($vecteur[0])/(abs($vecteur[0])+abs($vecteur[1]));        
  611.         $ratioY = abs($vecteur[1])/(abs($vecteur[0])+abs($vecteur[1]));
  612.         $deplaceX = floor(sqrt($vitCaree*$ratioX));
  613.         $deplaceY = floor(sqrt($vitCaree*$ratioY));        
  614.         $x = $this->getPosX()+$deplaceX*$sensX;
  615.         $y = $this->getPosY()+$deplaceY*$sensY;        
  616.        
  617.         $this->setPos($x,$y);    
  618.     }    
  619.    
  620.     public function toString() {
  621.         return 'x: '.$this->x.' / y: '.$this->y;  
  622.     }
  623.    
  624.     public static function getBary($points) {
  625.         $nb = 0;
  626.         $x = 0;
  627.         $y = 0;  
  628.         foreach($points as $p) {
  629.             $nb++;
  630.             $x += $p->getPosX();
  631.             $y += $p->getPosY();
  632.         }
  633.  
  634.  
  635.         $xo = (int)($x/$nb);
  636.         $yo = (int)($y/$nb);
  637.         return new Point($xo,$yo);      
  638.     }
  639.  
  640. }
  641. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement