Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- /**
- * Shoot enemies before they collect all the incriminating data!
- * The closer you are to an enemy, the more damage you do but don't get too close or you'll get killed.
- **/
- $Jeu = new Jeu();
- // game loop
- while (TRUE)
- {
- //récup position Wolff
- fscanf(STDIN, "%d %d",
- $x,
- $y
- );
- $Jeu->wolff->setPosition($x, $y);
- //Init data points
- $Jeu->resetDataPoints();
- fscanf(STDIN, "%d",
- $dataCount
- );
- for ($i = 0; $i < $dataCount; $i++)
- {
- fscanf(STDIN, "%d %d %d",
- $dataId,
- $dataX,
- $dataY
- );
- $Jeu->getDataPoint($dataId)->setPosition($dataX,$dataY);
- }
- //init enemies
- $Jeu->resetEnemies();
- $Jeu->resetPredictedEnemies();
- fscanf(STDIN, "%d",
- $enemyCount
- );
- for ($i = 0; $i < $enemyCount; $i++)
- {
- fscanf(STDIN, "%d %d %d %d",
- $enemyId,
- $enemyX,
- $enemyY,
- $enemyLife
- );
- $Jeu->getEnemy($enemyId)->setPosition($enemyX,$enemyY);
- $Jeu->getPredictedEnemy($enemyId)->setPosition($enemyX,$enemyY);
- $Jeu->getEnemy($enemyId)->setLife($enemyLife);
- $Jeu->getPredictedEnemy($enemyId)->setLife($enemyLife);
- }
- // Write an action using echo(). DON'T FORGET THE TRAILING \n
- // To debug (equivalent to var_dump): error_log(var_export($var, true));
- $Jeu->compute();
- //echo("MOVE 8000 4500\n"); // MOVE x y or SHOOT id
- }
- class Jeu {
- const LARGEUR = 16000;
- const HAUTEUR = 9000;
- const MAXTOENEMY = 2550; //2800
- const MAXTOSHOOT = 4800; //4800
- public $wolff = null;
- //2550 //4800 //19261
- protected $enemies = array();
- protected $predicted_enemies = array();
- protected $datapoints = array();
- /**
- * Move Wolff
- */
- /*
- protected $cardinaux = array(
- 'N' => [0,-1000],
- 'NE'=> [707,-707],
- 'E' => [1000,0],
- 'SE'=> [707,707],
- 'S' => [0,1000],
- 'SW'=> [-707,707],
- 'W' => [-1000,0],
- 'NW'=> [-707,-707],
- );
- */
- /*
- protected $cardinaux = array(
- 'N' => [0,-1000],
- 'NNE' => [500,-867],
- 'NE'=> [707,-707],
- 'NEE'=> [867,-500],
- 'E' => [1000,0],
- 'ESE' => [867,500],
- 'SE'=> [707,707],
- 'SES'=> [500,867],
- 'S' => [0,1000],
- 'SSW' => [-500,867],
- 'SW'=> [-707,707],
- 'SWW'=> [-867,500],
- 'W' => [-1000,0],
- 'WNW' => [-867,-500],
- 'NW'=> [-707,-707],
- 'NWB'=> [-500,-867],
- );
- */
- protected $cardinaux = array(
- '1' => [0,-1000],
- '2' => [317,-950],
- '3' => [448,-895],
- '4' => [548,-837],
- '5' => [633,-775],
- '6' => [708,-708],
- '7' => [775,-633],
- '8' => [837,-548],
- '9' => [895,-448],
- '10' => [950,-317],
- '11' => [1000,0],
- '12' => [950,317],
- '13' => [895,448],
- '14' => [837,548],
- '15' => [775,633],
- '16' => [708,708],
- '17' => [633,775],
- '18' => [548,837],
- '19' => [448,895],
- '20' => [317,950],
- '21' => [0,1000],
- '22' => [-317,950],
- '23' => [-448,895],
- '24' => [-548,837],
- '25' => [-633,775],
- '26' => [-708,708],
- '27' => [-775,633],
- '28' => [-837,548],
- '29' => [-895,448],
- '30' => [-950,317],
- '31' => [-1000,0],
- '32' => [-950,-317],
- '33' => [-895,-448],
- '34' => [-837,-548],
- '35' => [-775,-633],
- '36' => [-708,-708],
- '37' => [-633,-775],
- '38' => [-548,-837],
- '39' => [-448,-895],
- '40' => [-317,-950],
- );
- public static function log($x) {
- error_log(var_export($x, true));
- }
- /**
- * Constructeur
- */
- public function __construct() {
- $this->wolff = new Wolff();
- $this->initCardinaux();
- }
- /**
- * Renvoi un DataPoint a partir de son id (l'instancie si besoin)
- */
- public function getDataPoint($id) {
- if(!isset($this->datapoints[$id])) {
- $this->datapoints[$id] = new DataPoint();
- $this->datapoints[$id]->setId($id);
- }
- return $this->datapoints[$id];
- }
- /**
- * Renvoi un Enemy a partir de son id (l'instancie si besoin)
- */
- public function getEnemy($id) {
- if(!isset($this->enemies[$id])) {
- $this->enemies[$id] = new Enemy();
- $this->enemies[$id]->setId($id);
- }
- return $this->enemies[$id];
- }
- /**
- * Renvoi un Enemy a partir de son id (l'instancie si besoin)
- */
- public function getPredictedEnemy($id) {
- if(!isset($this->predicted_enemies[$id])) {
- $this->predicted_enemies[$id] = new Enemy();
- $this->predicted_enemies[$id]->setId($id);
- }
- return $this->predicted_enemies[$id];
- }
- public function resetEnemies() {
- $this->enemies = [];
- }
- public function resetPredictedEnemies() {
- $this->predicted_enemies = [];
- }
- public function resetDataPoints() {
- $this->datapoints = [];
- }
- public function compute() {
- $this->predict();
- if($this->getAway()) return;
- if($this->getCloser()) return;
- $this->shootNearest();
- }
- public function getAway() {
- $idMin = $this->getNearestId($this->wolff->getPosition(), $this->predicted_enemies);
- $distMin = $this->predicted_enemies[$idMin]->getPosition()->getDistanceTo($this->wolff->getPosition());
- self::log('DIST MIN '.$distMin);
- self::log('LIFE DIST MIN '.$this->predicted_enemies[$idMin]->getLife());
- $maxDist = 0;
- $direction = 'N';
- self::log('EVA FUITE: '.$distMin.' -> '.self::MAXTOENEMY);
- if($distMin <= self::MAXTOENEMY) {
- //si un seul trop proche et tuable, on le tue
- $nb = $this->getNearestId($this->wolff->getPosition(), $this->predicted_enemies);
- if($nb == 1) {
- self::log('TUER LE TROP PROCHE');
- $degat = 125000/pow($distMin,1.2);
- $life = $this->predicted_enemies[$idMin]->getLife();
- if($life < $degat) {
- echo "SHOOT ".$idMin."\n";
- return true;
- }
- }
- //sinon on part au plus loin
- foreach($this->cardinaux as $dir => $vecteur) {
- //simulation deplacement
- $newWolff = clone $this->wolff->getPosition();
- $x = $newWolff->getPosX()+$vecteur[0];
- $y = $newWolff->getPosY()+$vecteur[1];
- if($x < 0) $x = 0;
- if($y < 0) $y = 0;
- if($x > self::LARGEUR) $x = self::LARGEUR;
- if($y > self::HAUTEUR) $y = self::HAUTEUR;
- $newWolff->setPos($x,$y);
- //recherche plus pres
- $id = $this->getNearestId($newWolff,$this->predicted_enemies);
- $dist = $this->predicted_enemies[$id]->getPosition()->getDistanceTo($newWolff);
- self::log($dir.' -> '.$dist);
- if($dist > $maxDist) {
- self::log('bip');
- $maxDist = $dist;
- $direction = $dir;
- }
- }
- self::log('fuite -> '.$direction);
- $newWolff = clone $this->wolff->getPosition();
- $x = $newWolff->getPosX()+$this->cardinaux[$direction][0];
- $y = $newWolff->getPosY()+$this->cardinaux[$direction][1];
- if($x < 0) $x = 0;
- if($y < 0) $y = 0;
- if($x > self::LARGEUR) $x = self::LARGEUR;
- if($y > self::HAUTEUR) $y = self::HAUTEUR;
- echo "MOVE ".$x.' '.$y."\n";
- return true;
- }
- return false;
- }
- public function getCloser() {
- $idMin = $this->getNearestToMe();
- //$idMin = $this->getNearestToData();
- $distMin = $this->predicted_enemies[$idMin]->getPosition()->getDistanceTo($this->wolff->getPosition());
- if($distMin > self::MAXTOSHOOT) {
- $cible = $this->enemies[$idMin]->getPosition();
- //$cible = $this->predicted_enemies[$idMin]->getPosition();
- //$cible = $this->predicted_enemies[$idMin]->getDestintation();
- //$cible = $this->wolff->getPosition()->getBary($this->enemies[$idMin]->getPosition());
- //$cible = Point::getBary([$this->wolff->getPosition(),$this->enemies[$idMin]->getPosition(),$this->predicted_enemies[$idMin]->getDestintation()]);
- echo "MOVE ".(int)$cible->getPosX().' '.(int)$cible->getPosY()."\n";
- return true;
- } else {
- return false;
- }
- }
- public function shootNearest() {
- $idMin = $this->getNearestToMe();
- //$idMin = $this->getNearestToData();
- //$idMin = $this->getNearestToDataAndMe();
- echo "SHOOT ".$idMin."\n";
- return true;
- }
- private function getNearestToMe() {
- return $this->getNearestId($this->wolff->getPosition(), $this->predicted_enemies);
- }
- private function getNearestToData() {
- $idMin = 0;
- $distMin = 19000;
- foreach($this->predicted_enemies as $unit) {
- if($unit->getLife() <= 0) {
- continue;
- }
- if($unit->getPosition() == $unit->getDestintation()) {
- continue;
- }
- $dist = $unit->getPosition()->getDistanceTo($unit->getDestintation());
- /*
- self::log('----------------');
- self::log('id: '.$unit->getId());
- self::log($unit->getDestintation());
- self::log($dist);
- */
- if($dist<$distMin) {
- $distMin = $dist;
- $idMin = $unit->getId();
- }
- }
- self::log('---->'.$idMin.'<----');
- return $idMin;
- }
- private function getNearestToDataAndMe() {
- $idMin = 0;
- $distMin = 19000;
- foreach($this->predicted_enemies as $unit) {
- if($unit->getLife() <= 0) {
- continue;
- }
- if($unit->getPosition() == $unit->getDestintation()) {
- continue;
- }
- $dist = $unit->getPosition()->getDistanceTo($this->wolff->getPosition());
- $dist += $unit->getPosition()->getDistanceTo($unit->getDestintation());
- /*
- self::log('----------------');
- self::log('id: '.$unit->getId());
- self::log($unit->getDestintation());
- self::log($dist);
- */
- if($dist<$distMin) {
- $distMin = $dist;
- $idMin = $unit->getId();
- }
- }
- self::log('---->'.$idMin.'<----');
- return $idMin;
- }
- private function getNearestId($origin, $haystack) {
- $idMin = 0;
- $distMin = 19000;
- foreach($haystack as $unit) {
- if($unit->getLife() <= 0) {
- continue;
- }
- $dist = $unit->getPosition()->getDistanceTo($origin);
- if($dist<$distMin) {
- $distMin = $dist;
- $idMin = $unit->getId();
- }
- }
- return $idMin;
- }
- private function getNbTooShort($origin, $haystack) {
- $cnt = 0;
- foreach($haystack as $unit) {
- if($unit->getLife() <= 0) {
- continue;
- }
- $dist = $unit->getPosition()->getDistanceTo($origin);
- if($dist<self::MAXTOENEMY) {
- $cnt++;
- }
- }
- return $cnt;
- }
- private function predict() {
- foreach($this->enemies as $id => $enemy) {
- self::log('PREDICTION '.$id);
- $nearestData = $this->getNearestId($enemy->getPosition(),$this->datapoints);
- self::log(' nearest data: '.$nearestData);
- $this->predicted_enemies[$id]->setDestination($this->datapoints[$nearestData]->getPosition());
- $this->predicted_enemies[$id]->predictPosition();
- self::log(' prev pos: '.$this->predicted_enemies[$id]->getPosition()->toString());
- self::log(' next pos: '.$this->predicted_enemies[$id]->getDestintation()->toString());
- }
- }
- private function initCardinaux() {
- $this->cardinaux = [];
- for($angle=0; $angle < 360; $angle+=5) {
- $sin = sin($angle);
- $cos = cos($angle);
- $this->cardinaux[$angle] = [(int)($sin*1000), (int)($cos*1000)];
- }
- }
- }
- class Unit {
- protected $id = null;
- protected $vitesse = 0;
- protected $position = null;
- protected $life = 1000000000;
- public function __construct() {
- $this->position = new Point();
- }
- /**
- * Positione l'unité
- */
- public function setPosition($x, $y) {
- $this->position->setPos($x,$y);
- }
- public function getPosition() {
- return $this->position;
- }
- public function setId($id) {
- $this->id = $id;
- }
- public function getId() {
- return $this->id;
- }
- public function setLife($life) {
- $this->life = $life;
- }
- public function getLife() {
- return $this->life;
- }
- }
- class Datapoint extends Unit {
- }
- class Wolff extends Unit {
- protected $vitesse = 1000;
- }
- class Enemy extends Unit {
- protected $vitesse = 500;
- protected $life = 0;
- protected $destination = null;
- public function output() {
- return array(
- 'id' =>$this->id,
- 'life' => $this->life,
- );
- }
- public function getDestintation() {
- return $this->destination;
- }
- public function setDestination(Point $p) {
- $this->destination = $p;
- }
- public function predictPosition() {
- $vecteur = $this->destination->getVector($this->position);
- $this->position->deplace($vecteur,$this->vitesse, $this->destination);
- }
- }
- /**
- * Class point cartésien
- */
- class Point {
- public $x; //abscisse
- public $y; //ordonée
- /**
- * Construction du point
- * @param type $x abscisse
- * @param type $y ordonnée
- */
- function __construct($x=0, $y=0) {
- $this->x = $x;
- $this->y = $y;
- }
- /**
- * MAJ de la position du point
- * @param type $x abscisse
- * @param type $y ordonnée
- */
- function setPos($x, $y) {
- $this->x = $x;
- $this->y = $y;
- }
- /**
- * Recup Abscisse
- * @return int abscisse
- */
- function getPosX() {
- return $this->x;
- }
- /**
- * Recup Ordonnées
- * @return int ordonnée
- */
- function getPosY() {
- return $this->y;
- }
- /**
- * Renvoi la distance à un autre point
- * @return int distance
- */
- function getDistanceTo(Point $p) {
- return sqrt(pow($this->getPosX() - $p->getPosX(), 2) + pow($this->getPosY() - $p->getPosY(), 2));
- }
- /**
- * Renvoi le vecteur entre 2 points
- */
- public function getVector(Point $p) {
- return [
- $this->getPosX()-$p->getPosX(),
- $this->getPosY()-$p->getPosY(),
- ];
- }
- public function deplace($vecteur, $vitesse, $destination) {
- //si on arrive, on se place sur la destination
- if($this->getDistanceTo($destination) < $vitesse) {
- $this->position = $destination;
- return;
- }
- //sinon on calcule le deplacement
- $sensX = $vecteur[0]>0 ? 1:-1;
- $sensY = $vecteur[1]>0 ? 1:-1;
- $vitCaree = $vitesse*$vitesse;
- $ratioX = abs($vecteur[0])/(abs($vecteur[0])+abs($vecteur[1]));
- $ratioY = abs($vecteur[1])/(abs($vecteur[0])+abs($vecteur[1]));
- $deplaceX = floor(sqrt($vitCaree*$ratioX));
- $deplaceY = floor(sqrt($vitCaree*$ratioY));
- $x = $this->getPosX()+$deplaceX*$sensX;
- $y = $this->getPosY()+$deplaceY*$sensY;
- $this->setPos($x,$y);
- }
- public function toString() {
- return 'x: '.$this->x.' / y: '.$this->y;
- }
- public static function getBary($points) {
- $nb = 0;
- $x = 0;
- $y = 0;
- foreach($points as $p) {
- $nb++;
- $x += $p->getPosX();
- $y += $p->getPosY();
- }
- $xo = (int)($x/$nb);
- $yo = (int)($y/$nb);
- return new Point($xo,$yo);
- }
- }
- ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement