This repository has been archived on 2024-07-18. You can view files and clone it, but cannot push or open issues or pull requests.
lwb5/scripts/game/beta5/moving/library/computeTrajectory.inc

183 lines
5.8 KiB
PHP

<?php
class beta5_moving_computeTrajectory {
var $trajCache = null;
function beta5_moving_computeTrajectory($lib) {
$this->lib = $lib;
$this->db = $this->lib->game->db;
$this->planets = $this->lib->game->getLib('beta5/planet');
}
// Get a fleet's trajectory (using the trajectory cache)
function run($srcId, $dstId, $speed, $cruisers) {
$s = "$srcId:$dstId:$speed:".($cruisers?1:0);
if (is_null($this->trajCache[$s])) {
$this->trajCache[$s] = $this->computeTrajectory($srcId, $dstId, $speed, $cruisers);
}
return $this->trajCache[$s];
}
// Computes a fleet's trajectory
function computeTrajectory($srcId, $dstId, $speed, $cruisers) {
$src = $this->planets->call('byId', $srcId);
$dst = $this->planets->call('byId', $dstId);
// Get planet list and base travel time
$pList = array();
if ($src['x'] == $dst['x'] && $src['y'] == $dst['y']) {
// Planets are in the same system
$minId = min($srcId,$dstId); $maxId = max($srcId,$dstId);
logText("min/max id = $minId / $maxId");
$q = $this->db->query("SELECT id,status,system FROM planet WHERE id>=$minId AND id<=$maxId ORDER BY id "
. ($srcId==$minId ? 'ASC' : 'DESC'));
$bTTime = 0;
while ($r = dbFetchArray($q)) {
array_push($pList, array($r[0], $r[1], $r[2]));
$bTTime += ($r[0] == $minId || $r[0] == $maxId) ? 6 : 12;
}
} else {
// Planets are in different systems
if ($src['x'] != $dst['x']) {
// Trajectory looks like y = ax + b
$slope = ($dst['y'] - $src['y']) / ($dst['x'] - $src['x']);
$displ = $src['y'] - $src['x'] * $slope;
$vert = false;
$minX = min($dst['x'],$src['x']); $maxX = max($dst['x'],$src['x']);
$minY = min($dst['y'],$src['y']); $maxY = max($dst['y'],$src['y']);
$qs = "SELECT id,x,y FROM system WHERE x>=$minX AND x<=$maxX AND y>=$minY AND y<=$maxY AND ";
if ($slope > 0)
$qs .= "y+0.5>$slope*(x-0.5)+$displ AND y-0.5<$slope*(x+0.5)+$displ";
else
$qs .= "y+0.5>$slope*(x+0.5)+$displ AND y-0.5<$slope*(x-0.5)+$displ";
$qs .= " ORDER BY x " .($minX == $dst['x'] ? 'DESC' : 'ASC') . ", y " . ($src['y'] < $dst['y'] ? "ASC" : "DESC");
} else {
// Trajectory looks like x = c
$vert = true;
$minY = min($dst['y'],$src['y']); $maxY = max($dst['y'],$src['y']);
$qs = "SELECT id,x,y FROM system WHERE y>=$minY AND y<=$maxY AND x=".$src['x'];
$qs .= " ORDER BY y " .($minY == $dst['y'] ? 'DESC' : 'ASC');
}
$dX = $src['x'] - $dst['x']; $dY = $src['y'] - $dst['y'];
$distance = sqrt($dX*$dX+$dY*$dY);
$bTTime = round($distance * (70 - $speed * 10) * ($cruisers ? 2 : 1));
// List orbits
$q = $this->db->query($qs);
while ($r = dbFetchArray($q)) {
$dir = "DESC";
// If we are in source or destination system, get all planets with orbits >= source/dest planet
if ($r[1] == $src['x'] && $r[2] == $src['y']) {
$dir = "ASC";
$minOrbit = $src['orbit'];
} elseif ($r[1] == $dst['x'] && $r[2] == $dst['y']) {
$minOrbit = $dst['orbit'];
} elseif ($vert) {
// Vertical trajectories: 4 orbits out of 6 get intersected (1 / sqrt(2))
$minOrbit = 2;
} else {
// If we are intersecting another system, 6 different cases:
// (1) passing through x = xs - 0.5 and y = ys - 0.5
// (2) passing through x = xs - 0.5 and y = ys + 0.5
// (3) passing through x = xs - 0.5 and x = xs + 0.5
// (4) passing through x = xs + 0.5 and y = ys - 0.5
// (5) passing through x = xs + 0.5 and y = ys + 0.5
// (6) passing through y = ys - 0.5 and y = ys + 0.5
$y1 = ($r[1] - 0.5) * $slope + $displ;
if ($y1 < $r[2] - 0.5 || $y1 > $r[2] + 0.5) {
// Case (4), (5) or (6)
$y1 = ($r[1] + 0.5) * $slope + $displ;
if ($y1 < $r[2] - 0.5 || $y1 > $r[2] + 0.5) {
// Case (6)
$y1 = $r[2] - 0.5;
$x1 = ($y1 - $displ) / $slope;
$y2 = $r[2] + 0.5;
$x2 = ($y2 - $displ) / $slope;
} else {
// Case (4) or (5)
$x1 = $r[1] + 0.5;
$x2 = ($r[2] - 0.5 - $displ) / $slope;
if ($x2 < $r[1] - 0.5 || $x2 > $r[1] + 0.5) {
// Case (5)
$y2 = $r[2] + 0.5;
$x2 = ($y2 - $displ) / $slope;
} else {
// Case (4)
$y2 = $r[2] - 0.5;
}
}
} else {
// Case (1), (2) or (3)
$x1 = $r[1] - 0.5;
$y2 = ($r[1] + 0.5) * $slope + $displ;
if ($y2 < $r[2] - 0.5 || $y2 > $r[2] + 0.5) {
// Case (1) or (2)
$x2 = ($r[2] - 0.5 - $displ) / $slope;
if ($x2 < $r[1] - 0.5 || $x2 > $r[1] + 0.5) {
// Case (2)
$y2 = $r[2] + 0.5;
$x2 = ($y2 - $displ) / $slope;
} else {
// Case (1)
$y2 = $r[2] + 0.5;
}
} else {
// Case (3)
$x2 = $r[1] + 0.5;
}
}
$dX = $x1 - $x2; $dY = $y1 - $y2; $d = sqrt($dX*$dX+$dY*$dY);
$no = round(1 + 5 * $d / sqrt(2));
$minOrbit = 6 - $no;
}
// List orbits for this system
$q2 = $this->db->query("SELECT id,status FROM planet WHERE system=".$r[0]." AND orbit>=$minOrbit ORDER BY orbit $dir");
while ($r2 = dbFetchArray($q2)) {
array_push($pList, array($r2[0], $r2[1], $r[0]));
}
}
}
// Generate trajectory
$trajectory = array(
"hs" => ($src['x'] != $dst['x'] || $src['y'] != $dst['y']),
"list" => array()
);
$opDelay = array(0,26,26,38,56,80);
$tTime = $bTTime;
$nPlanets = count($pList);
$perPlanet = floor($bTTime / ($nPlanets - 1));
$perEndpoint = ($bTTime - ($perPlanet * ($nPlanets - 2))) / 2;
for ($i=0;$i<$nPlanets;$i++) {
$otime = $opDelay[$pList[$i][1]];
if ($i == 0) {
$trtime = floor($perEndpoint);
$otime /= 2;
} elseif ($i == $nPlanets - 1) {
$trtime = ceil($perEndpoint);
$otime /= 2;
} else {
$trtime = $perPlanet;
}
$tTime += $otime;
array_push($trajectory['list'], array(
"pid" => $pList[$i][0],
"time" => $trtime + $otime
));
}
$trajectory['time'] = $tTime;
return $trajectory;
}
}
?>