Skip to content

Instantly share code, notes, and snippets.

@maximov-ru
Created August 3, 2016 08:30
Show Gist options
  • Save maximov-ru/9225f2a448df7e8c27f187a1ffb9e737 to your computer and use it in GitHub Desktop.
Save maximov-ru/9225f2a448df7e8c27f187a1ffb9e737 to your computer and use it in GitHub Desktop.
coding game
<?php
/**
* It's the survival of the biggest!
* Propel your chips across a frictionless table top to avoid getting eaten by bigger foes.
* Aim for smaller oil droplets for an easy size boost.
* Tip: merging your chips will give you a sizeable advantage.
**/
fscanf(STDIN, "%d",
$playerId // your id (0 to 4)
);
class Ship
{
public static $otherShipsMap;
public static $ownShipsMap;
public static $ownShips = [];
public static $playerId = 1;
const XSize = 799;
const YSize = 514;
const XCenter = 399;
const YCenter = 257;
public $id;
public $player;
public $radius;
public $x;
public $y;
public $vx;
public $vy;
public $isLive = true;
//public $ax;
//public $ay;
public $lastTargetId;
public $lastAction;
public static function resetLive()
{
if(self::$ownShipsMap) {
foreach (self::$ownShipsMap as $ship) {
$ship->isLive = false;
}
}
if(self::$otherShipsMap) {
foreach (self::$otherShipsMap as $ship) {
$ship->isLive = false;
}
}
self::$ownShips = [];
}
public static function updateObject($id,$player,$radius,$x,$y,$vx,$vy)
{
if($player == self::$playerId){
if(!isset(self::$ownShipsMap[$id])){
self::$ownShipsMap[$id] = new Ship();
self::$ownShipsMap[$id]->id = $id;
self::$ownShipsMap[$id]->player = $player;
}
self::$ownShips[] = $id;
self::$ownShipsMap[$id]->updateData($radius,$x,$y,$vx,$vy);
}else{
if(!isset(self::$otherShipsMap[$id])) {
self::$otherShipsMap[$id] = new Ship();
self::$otherShipsMap[$id]->id = $id;
self::$otherShipsMap[$id]->player = $player;
}
self::$otherShipsMap[$id]->updateData($radius,$x,$y,$vx,$vy);
}
error_log(var_export("upd:".implode(' ',[$id,$player,$radius,$x,$y,$vx,$vy]), true));
}
public function updateData($radius,$x,$y,$vx,$vy){
//$this->id = $id;
//$this->player = $player;
$this->radius = $radius;
$this->x = $x;
$this->y = $y;
$this->vx = $vx;
$this->vy = $vy;
$this->isLive = true;
}
public static function getDist($x1,$y1,$x2,$y2)
{
$dx = $x1>$x2 ? ($x1 - $x2) : ($x2 - $x1);
$dy = $y1>$y2 ? ($y1 - $y2) : ($y2 - $y1);
return sqrt($dx*$dx + $dy*$dy);
}
public function getNewRadiusAndSpeed()
{
//1520.53
$mass = pi()*$this->radius*$this->radius;
//101.37 p = 101.37*200 = 20274
$sub = $mass/15;
//newMass = 1419.16 v = 20274/1419.16 = 14.29
$newMass = $mass-$sub;
$speed = ($sub*200)/$newMass;
$radius = sqrt($newMass/pi());
return [$radius,$speed];
}
public static function changeCoord(&$x,&$y,&$vx,&$vy,$radius)
{
$x +=$vx;
if($x<0) {
$x = abs($x);
$vx *= -1;
}
if($x > self::XSize){
$x = self::XSize - ($x - self::XSize);
$vx *= -1;
}
$y +=$vy;
if($y<0) {
$y = abs($y);
$vy *= -1;
}
if($y > self::YSize){
$y = self::YSize - ($y - self::YSize);
$vy *= -1;
}
}
public static function getCoord($x,$y,$vx,$vy,$radius)
{
$x +=$vx;
if(($x-$radius)<0) {
$x = abs($x);
$vx *= -1;
}
if(($x+$radius) > self::XSize){
$x = self::XSize - ($x - self::XSize);
$vx *= -1;
}
$y +=$vy;
if(($y-$radius)<0) {
$y = abs($y);
$vy *= -1;
}
if(($y+$radius) > self::YSize){
$y = self::YSize - ($y - self::YSize);
$vy *= -1;
}
return [$x,$y];
}
public function getSpeeds($dt,Ship $obj)
{
list($newRad,$spd) = $this->getNewRadiusAndSpeed();
$coords = self::getCoord($obj->x,$obj->y,$obj->vx*$dt,$obj->vy*$dt,$obj->radius);
$recosh = 0;
if($this->x < self::XCenter && ($this->x < $dt*$spd)){
$recosh = $dt*$spd-$newRad;
}elseif($this->x > self::XCenter && ((self::XSize - $this->x) < $dt*$spd)){
$recosh = $dt*$spd-$newRad;
}
}
public function getPossibleCross($dt,Ship $obj,$step = 1)
{
/**
* x = (Vx1 + dVx)*t+a
* y = (Vy1 + dVy)*t+b
*
* x = Vx2*t+a2
* y = Vy2*t+b2
*
* dV^2 = dVx^2+dVy^2
*
* dVx = √(dV^2 - dVy^2)
*
* t = (x-a2)/Vx2
*
* x = (Vx1 + (sqrt(dV*dV - dVy*dVy)))*((x-a2)/Vx2)+a
*
*
* dVx = -Vx1-a/t-recosh/t+x/t
*/
$x1 = $this->x;
$y1 = $this->y;
$vx1 = $this->vx*$step;
$vy1 = $this->vy*$step;
$dvx1 = 0;
$dvy1 = 0;
$t = 0;
$x2 = $obj->x;
$y2 = $obj->y;
$vx2 = $obj->vx*$step;
$vy2 = $obj->vy*$step;
$dist = self::getDist($x1,$y1,$x2,$y2);
$minRange = $dist;
$xn = $x1;
$yn = $y1;
$vxn = $vx1;
$vyn = $vy1;
$x3 = $xn;
$vx3 = $vxn+10*$step;
$y3 = $yn;
$vy3 = $vyn;
self::changeCoord($x3,$y3,$vx3,$vy3);
$dist3 = self::getDist($x3,$y3,$x2,$y2);
if($dist3<$dist){
$dvx1 = 1;
}elseif($dist3>$dist){
$dvx1 = -1;
}else{
$dvx1 = 0;
}
$x3 = $xn;
$vx3 = $vxn;
$y3 = $yn;
$vy3 = $vyn+10*$step;
self::changeCoord($x3,$y3,$vx3,$vy3);
$dist3 = self::getDist($x3,$y3,$x2,$y2);
if($dist3<$dist){
$dvy1 = 1;
}elseif($dist3>$dist){
$dvy1 = -1;
}else{
$dvy1 = 0;
}
$minT = $t;
for($t=1;$t<=$dt;$t++){
$xn = $x1;
$yn = $y1;
$vxn = $vx1;
$vyn = $vy1;
self::changeCoord($x1,$y1,$vx1,$vy1);
self::changeCoord($x2,$y2,$vx2,$vy2);
$dist = self::getDist($x1,$y1,$x2,$y2);
if($dist<$minRange) {
$minRange = $dist;
$x3 = $xn;
$vx3 = $vxn+10*$step;
$y3 = $yn;
$vy3 = $vyn;
self::changeCoord($x3,$y3,$vx3,$vy3);
$dist3 = self::getDist($x3,$y3,$x2,$y2);
if($dist3<$dist){
$dvx1 = 1;
}elseif($dist3>$dist){
$dvx1 = -1;
}else{
$dvx1 = 0;
}
$x3 = $xn;
$vx3 = $vxn;
$y3 = $yn;
$vy3 = $vyn+10*$step;
self::changeCoord($x3,$y3,$vx3,$vy3);
$dist3 = self::getDist($x3,$y3,$x2,$y2);
if($dist3<$dist){
$dvy1 = 1;
}elseif($dist3>$dist){
$dvy1 = -1;
}else{
$dvy1 = 0;
}
$minT = $t;
}
}
return [$minRange,$minT,$dvx1,$dvy1];
}
public function getAction()
{
$act = 'WAIT';
$dvx = 0;
$dvy = 0;
$canEat = false;
$isDrapaem = false;
$tPrior = 10;
$tPriorEat = 5;
$objId = null;
/*if($this->lastTargetId && self::$otherShipsMap[$this->lastTargetId]->isLive){
$ship = self::$otherShipsMap[$this->lastTargetId];
$crossInfo = $this->getPossibleCross(4, $ship);
error_log(var_export("target id {$this->id}({$this->radius}) njamnjam to {$ship->id}({$ship->radius})", true));
if($this->radius/$ship->radius>1.1) {
$dvx = ($crossInfo[2]);
$dvy = ($crossInfo[3]);
error_log(var_export("target id {$this->id}({$this->radius}) njamnjam to {$ship->id}({$ship->radius}) player: {$ship->player}" . $dvx . ' ' . $dvy, true));
if ($dvx || $dvy) {
$px = $this->x + $dvx;
if ($px < 0) {
$px = 0;
}
if ($px > self::XSize) {
$px = self::XSize;
}
$py = $this->y + $dvy;
if ($py < 0) {
$py = 0;
}
if ($py > self::YSize) {
$py = self::YSize;
}
$act = $px . ' ' . $py;
}
}else{
$act = 'WAIT';
}
return $act;
}*/
if (self::$otherShipsMap) {
$minDistance = 700 * 3;
$maxWeight = 0;
foreach (self::$otherShipsMap as $id => $ship) {
if ($ship->isLive) {
$koef = $this->radius/$ship->radius;
if (self::getDist($this->x, $this->y, $ship->x, $ship->y) < (200 + $this->vx * $this->vx + $this->vy * $this->vy)) {
if (($ship->radius + 1) > $this->radius) {
//drapaem
$crossInfo = $this->getPossibleCross(10, $ship, 0.5);
if ($crossInfo[0] <= ($ship->radius + 1 + $this->radius)) {
if ($crossInfo[1] < $tPrior) {
$k = 6 - $crossInfo[1];
$dvx += (-$crossInfo[2] * $k);
$dvy += (-$crossInfo[3] * $k);
if(!$dvx && !$dvy){
$dvx = $this->x - $ship->x;
$dvy = $this->y - $ship->y;
}
$objId = $id;
$tPrior = $crossInfo[1];
$isDrapaem = true;
error_log(var_export("id {$this->id}({$this->radius}) drapaem X2 from {$ship->id}({$ship->radius}) " . $dvx . ' ' . $dvy . " cross dist:{$crossInfo[0]} t:{$crossInfo[1]}", true));
}
}
error_log(var_export("id {$this->id}({$this->radius}) drapaem from {$ship->id}({$ship->radius}) " . $dvx . ' ' . $dvy . " cross dist:{$crossInfo[0]} t:{$crossInfo[1]}", true));
} elseif (!$isDrapaem && ($koef>1.1) && ($koef<4)) {
//dogonaem
$canEat = true;
$crossInfo = $this->getPossibleCross(4, $ship);
$weight = 0;
if($crossInfo[1] == 1 && ($crossInfo[0]< ($this->radius+$ship->radius))){
$weight = 30000;
}
if($crossInfo[0] == 0){
$obr = 1;
}else{
$obr =$crossInfo[0];
}
$timekMap = [10000,2000,1000,500];
$weight += 10000/$obr + $timekMap[$crossInfo[1]] + 1000/$koef;
//$crossInfo[0] = $crossInfo[0] * $crossInfo[1];
//if ($ship->player == -1)
// $crossInfo[0] = $crossInfo[0] / 2;
if ($maxWeight < $weight) {
$skip = false;
foreach (self::$ownShipsMap as $ownId => $ownShip) {
if ($ownId != $this->id && $ownShip->lastTargetId == $id) {
$skip = true;
break;
}
}
if ($skip)
continue;
$this->lastTargetId = $id;
$minDistance = $crossInfo[0];
error_log(var_export("minDistance:" . $minDistance, true));
$dvx = ($crossInfo[2]);
$dvy = ($crossInfo[3]);
$maxWeight = $weight;
error_log(var_export("id {$this->id}({$this->radius}) njamnjam to {$ship->id}({$ship->radius}) player: {$ship->player}" . $dvx . ' ' . $dvy, true));
}
} else {
error_log(var_export("id {$this->id}({$this->radius}) njamnjam to {$ship->id}({$ship->radius}) very little", true));
}
} else {
error_log(var_export("id {$this->id}({$this->radius}) to {$ship->id}({$ship->radius}) long", true));
}
} else {
error_log(var_export("{$ship->id}({$ship->radius}) die", true));
}
}
if ($dvx || $dvy) {
$px = $this->x + $dvx;
if ($px < 0) {
$px = 0;
}
if ($px > self::XSize) {
$px = self::XSize;
}
$py = $this->y + $dvy;
if ($py < 0) {
$py = 0;
}
if ($py > self::YSize) {
$py = self::YSize;
}
$act = $px . ' ' . $py;
}
}
return $act;
}
}
$tx = 50;
$ty = 50;
$vtx = 1;
$vty = -1;
Ship::$playerId = $playerId;
error_log(var_export("coords: ".implode(' ',[$tx,$ty,$vtx,$vty]), true));
Ship::changeCoord($tx,$ty,$vtx,$vty);
error_log(var_export("coords: ".implode(' ',[$tx,$ty,$vtx,$vty]), true));
error_log(var_export("dist:".Ship::getDist(50,50,$tx,$ty), true));
// game loop
while (TRUE)
{
fscanf(STDIN, "%d",
$playerChipCount // The number of chips under your control
);
fscanf(STDIN, "%d",
$entityCount // The total number of entities on the table, including your chips
);
Ship::resetLive();
for ($i = 0; $i < $entityCount; $i++)
{
fscanf(STDIN, "%d %d %f %f %f %f %f",
$id, // Unique identifier for this entity
$player, // The owner of this entity (-1 for neutral droplets)
$radius, // the radius of this entity
$x, // the X coordinate (0 to 799)
$y, // the Y coordinate (0 to 514)
$vx, // the speed of this entity along the X axis
$vy // the speed of this entity along the Y axis
);
Ship::updateObject($id,$player,$radius,$x,$y,$vx,$vy);
}
for ($i = 0; $i < $playerChipCount; $i++)
{
// Write an action using echo(). DON'T FORGET THE TRAILING \n
// To debug (equivalent to var_dump): error_log(var_export($var, true));
$id = Ship::$ownShips[$i];
$act = Ship::$ownShipsMap[$id]->getAction();
error_log(var_export($act, true));
echo($act."\n"); // One instruction per chip: 2 real numbers (x y) for a propulsion, or 'WAIT'.
}
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment