Advertisement
Guest User

Untitled

a guest
Apr 23rd, 2018
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.80 KB | None | 0 0
  1. <?php
  2. define('DEBUG', true);
  3. function debug() {if (!DEBUG) return; foreach (func_get_args() as $sArgDebug) error_log(var_export($sArgDebug, true));}
  4. class Point
  5. {
  6. public $x;
  7. public $y;
  8.  
  9. public function __construct($x, $y)
  10. {
  11. $this->x = $x;
  12. $this->y = $y;
  13. }
  14. }
  15. class Ship
  16. {
  17. const MAX_HS = 20;
  18. const MAX_VS = 40;
  19.  
  20. public $oMap;
  21.  
  22. public $coord;
  23. public $hs;
  24. public $vs;
  25. public $fuel;
  26. public $rotation;
  27. public $power;
  28.  
  29. public $bIsLanding = false;
  30. public $bIsStarting = true;
  31.  
  32. public $dx;
  33.  
  34. public function initRound($oMap)
  35. {
  36. $this->oMap = $oMap;
  37.  
  38. fscanf(STDIN, "%d %d %d %d %d %d %d",
  39. $X,
  40. $Y,
  41. $HS, // the horizontal speed (in m/s), can be negative.
  42. $VS, // the vertical speed (in m/s), can be negative.
  43. $F, // the quantity of remaining fuel in liters.
  44. $R, // the rotation angle in degrees (-90 to 90).
  45. $P // the thrust power (0 to 4).
  46. );
  47.  
  48. $this->coord = new Point($X, $Y);
  49. $this->hs = $HS;
  50. $this->vs = $VS;
  51. $this->fuel = $F;
  52. $this->rotation = $R;
  53. $this->power = $P;
  54.  
  55. $this->dx = $oMap->target->x - $X;
  56. }
  57.  
  58. public function isRight()
  59. {
  60. return $this->dx > 0;
  61. }
  62.  
  63. public function isAlign()
  64. {
  65. return $this->dx === 0;
  66. }
  67.  
  68. public function move()
  69. {
  70. if ($this->bIsLanding) {
  71. return $this->land();
  72. }
  73.  
  74. $r = 0;
  75. $p = 0;
  76.  
  77. //If the ship has no good HS at start, give a 45° angle to the good direction until the HS is twice the max
  78. //to avoid too hard slowing down.
  79. //todo : This can be optimized by checking there's no obstacle and trying to rotate on more than 45°
  80. if ($this->bIsStarting && abs($this->hs) <= $this->getMaxHsForShip() && !$this->isAlign()) {
  81. $r = ($this->isRight() ? -45 : 45);
  82. } else {
  83. //Otherwise, we have started a landing approach. Calculate angle of slowing down.
  84. $this->bIsStarting = false;
  85. $r = $this->calculateAngle();
  86. }
  87.  
  88. //Update power
  89. $p = ($this->vs > 0 && $this->coord->y > $this->oMap->target->y) ? 0 : $this->getOptimalPower();
  90.  
  91. //Time for landing if HS <= 10 (each step power: 1+2+3+4) and dx <= 10
  92. if (abs($this->hs) <= 10 && abs($this->dx) <= 10) {
  93. $this->bIsLanding = true;
  94. }
  95.  
  96. //Make sure that $r and $p are in the good intervals. We dont want $r < -45 and $r > 45 to avoir bad gravity attraction.
  97. if ($r < -45) {$r = -45;} elseif ($r > 45) {$r = 45;}
  98. if ($p < 0) {$p = 0;} elseif ($p > 4) {$p = 4;}
  99.  
  100. $this->rotation = $r;
  101. $this->power = $p;
  102. return array($r, $p);
  103.  
  104. }
  105.  
  106. public function calculateAngle()
  107. {
  108. //If ship is align to middle of landing place, no rotation.
  109. if ($this->isAlign()) {
  110. return 0;
  111. }
  112.  
  113. //Otherwise, calculus of the angle
  114. //Here is the formula:
  115. //
  116. //V(x)² = V0² + 2*a*(x-x0)
  117. //Where:
  118. // - x is the X value to reach
  119. // - x0 is the X position of the ship
  120. // - V(x) is the speed reached at x
  121. // - V0 is the current speed
  122. // - a is the acceleration (what we're looking for)
  123. //Note:
  124. // - (x-x0) is our property $dx
  125. // - V(x) is wanted to be 0 (no HS when ship is aligned)
  126. // - V0 is our property $hs
  127. //Indeed:
  128. //a = -($hs²) / (2*$dx)
  129. $a = -($this->hs * $this->hs) / (2*$this->dx);
  130.  
  131. //Now, find the good angle. Here is the formula:
  132. //r = arctan(p/a) * 180/PI
  133. $r = round(atan($this->power / $a) * (180 / M_PI));
  134. //If acceleration is negative (ship is angled to mars' ground), turn back half turn
  135. if ($a < 0) {
  136. $r += 180;
  137. }
  138. //If middle of landing ground has been getting over, turn back
  139. if ($this->dx < 0 && $this->hs > 0 || $this->dx > 0 && $this->hs < 0) {
  140. $r = 90 - $r;
  141. }
  142.  
  143. //Adjust the ship for Y axis
  144. $r -= 90;
  145. return $r;
  146. }
  147.  
  148.  
  149. public function getMaxHsForShip()
  150. {
  151. //Optimization: get the max HS depending on the distance between ship and landing place
  152. return 67;
  153.  
  154. }
  155.  
  156. public function getOptimalPower()
  157. {
  158. //Don't take care about gravity and fuel levels for now.
  159. //todo: return better value on calculations.
  160. return 4;
  161. }
  162.  
  163. public function land()
  164. {
  165. $sureMaxVs = Ship::MAX_VS - 10; //10 for each step of power (1+2+3+4)
  166. $p = (abs($this->vs) > $sureMaxVs) ? $this->getOptimalPower() : 0;
  167. //Landing so $r needs to be 0
  168. $r = 0;
  169. return array($r, $p);
  170. }
  171. }
  172. class Map
  173. {
  174. public $aPoints = array();
  175. public $target;
  176. public $xTarget;
  177.  
  178. public function addPoint($x, $y)
  179. {
  180. $oPoint = new Point($x, $y);
  181. $this->aPoints[] = $oPoint;
  182. return $oPoint;
  183. }
  184.  
  185. public function __construct()
  186. {
  187. // the number of points used to draw the surface of Mars.
  188. fscanf(STDIN, "%d", $N);
  189. // X coordinate of a surface point. (0 to 6999)
  190. // Y coordinate of a surface point. By linking all the points together in a sequential fashion, you form the surface of Mars.
  191. fscanf(STDIN, "%d %d", $X, $Y);
  192. $oPreviousPoint = $this->addPoint($X, $Y);
  193. for ($i = 1; $i < $N; ++$i) {
  194. fscanf(STDIN, "%d %d", $X, $Y);
  195. $oPoint = $this->addPoint($X, $Y);
  196. //If same Y value for previous and x has changed for about +1000, this is the landing place
  197. if ($oPreviousPoint->y === $oPoint->y && ($oPoint->x - $oPreviousPoint->x) >= 1000) {
  198. $xTarget = $this->getXTarget($oPreviousPoint->x, $oPoint->x);
  199. $this->target = new Point($xTarget, $oPoint->y);
  200. }
  201. //Landing place is unique so don't need to check if some is already defined.
  202. $oPreviousPoint = $oPoint;
  203. }
  204. }
  205.  
  206. public function getXTarget($a, $b)
  207. {
  208. //Cut the landing space by the half
  209. $halfLanding = round(($b-$a)/2);
  210. //Add half of landing space to left X coord so middle of landing space is the xTarget
  211. return ($a + $halfLanding);
  212. }
  213. }
  214. $oMap = new Map();
  215. $oShip = new Ship();
  216. // game loop
  217. while (TRUE)
  218. {
  219. $oShip->initRound($oMap);
  220. list($r, $p) = $oShip->move();
  221. echo $r . ' ' . $p . "\n";
  222. }
  223. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement