Added full source code
This commit is contained in:
commit
33f8586698
1377 changed files with 123808 additions and 0 deletions
scripts/game/beta5/ticks
battle
cash
day
hour
move
punishment
quit
sales
universe
521
scripts/game/beta5/ticks/battle/library.inc
Normal file
521
scripts/game/beta5/ticks/battle/library.inc
Normal file
|
@ -0,0 +1,521 @@
|
|||
<?php
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// "Battle tick": computes battle outcomes
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
class beta5_ticks_battle_library {
|
||||
|
||||
function beta5_ticks_battle_library($lib) {
|
||||
$this->lib = $lib;
|
||||
$this->db = $lib->game->db;
|
||||
$this->fleets = $lib->game->getLib('beta5/fleet');
|
||||
$this->msgs = $lib->game->getLib('beta5/msg');
|
||||
$this->planets = $lib->game->getLib('beta5/planet');
|
||||
$this->players = $lib->game->getLib('beta5/player');
|
||||
$this->rules = $lib->game->getLib('beta5/rules');
|
||||
$this->sales = $lib->game->getLib('beta5/sale');
|
||||
$this->rankings = $lib->game->getLib('main/rankings');
|
||||
}
|
||||
|
||||
|
||||
function runTick() {
|
||||
$this->idrInc = array();
|
||||
$toThrow = null;
|
||||
try {
|
||||
$locations = $this->db->safeTransaction(array($this, 'getBattleLocations'));
|
||||
foreach ($locations as $lId) {
|
||||
$this->db->safeTransaction(array($this, 'battleAt'), array($lId), 5);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$toThrow = $e;
|
||||
}
|
||||
|
||||
$this->db->safeTransaction(array($this, 'updateStatus'));
|
||||
if (!is_null($toThrow)) {
|
||||
throw $toThrow;
|
||||
}
|
||||
|
||||
$this->db->safeTransaction(array($this, 'updateRankings'));
|
||||
}
|
||||
|
||||
|
||||
public function getBattleLocations() {
|
||||
$q = $this->btQuery(
|
||||
"SELECT DISTINCT location FROM fleet WHERE location IS NOT NULL AND attacking"
|
||||
);
|
||||
$locations = array();
|
||||
while ($r = dbFetchArray($q)) {
|
||||
array_push($locations, $r[0]);
|
||||
}
|
||||
return $locations;
|
||||
}
|
||||
|
||||
|
||||
public function updateStatus() {
|
||||
// Mark fleets that were in battle as available and commit
|
||||
$this->btQuery("UPDATE fleet SET can_move='Y' WHERE can_move='B'");
|
||||
}
|
||||
|
||||
public function updateRankings() {
|
||||
// Increase inflicted damage points
|
||||
$rt = $this->rankings->call('getType', 'p_idr');
|
||||
$rl = $this->rankings->call('getAll', $rt);
|
||||
$idr = array();
|
||||
foreach ($rl as $r) {
|
||||
$idr[$r['id']] = $r['points'];
|
||||
}
|
||||
foreach ($this->idrInc as $n => $inc) {
|
||||
$idr[$n] += $inc;
|
||||
}
|
||||
$idrR = array();
|
||||
foreach ($idr as $n => $p) {
|
||||
if (!is_array($idrR[$p])) {
|
||||
$idrR[$p] = array();
|
||||
}
|
||||
array_push($idrR[$p], $n);
|
||||
}
|
||||
$this->rankings->call('update', $rt, $idrR);
|
||||
}
|
||||
|
||||
|
||||
public function battleAt($lId) {
|
||||
// Execute computations
|
||||
$idrInc = $this->battleComputation($lId);
|
||||
|
||||
// Increase stored IDR
|
||||
foreach ($idrInc as $n => $ii) {
|
||||
if (is_null($this->idrInc[$n])) {
|
||||
$this->idrInc[$n] = $ii;
|
||||
} else {
|
||||
$this->idrInc[$n] += $ii;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function battleComputation($lId) {
|
||||
static $rnames = array('turret', 'gaship', 'fighter', 'cruiser', 'bcruiser');
|
||||
static $addLosses = array(.5, .25, 1, .25, .125);
|
||||
|
||||
// Get the ID of the planet's owner and the amount of turrets
|
||||
$q = $this->btQuery("SELECT name,owner,turrets,vacation FROM planet WHERE id=$lId "
|
||||
. "FOR UPDATE");
|
||||
list($pName,$pOwner,$pTurrets,$vacation) = dbFetchArray($q);
|
||||
$poFake = is_null($pOwner) ? 0 : $pOwner;
|
||||
|
||||
// Compute the power of the planet's turrets
|
||||
if ($vacation == 'YES ') {
|
||||
$defPower = 0;
|
||||
$pTurrets = 0;
|
||||
} else {
|
||||
$defPower = $this->planets->call('getPower', $lId);
|
||||
}
|
||||
$turretPower = $defPower;
|
||||
|
||||
// Get all fleets at that location
|
||||
$q = $this->btQuery("SELECT * FROM fleet WHERE location=$lId FOR UPDATE");
|
||||
$attFleets = array(0,0,0,0,0,0,0,0);
|
||||
$defFleets = array(0,0,0,0,0,0,0,0);
|
||||
$attPlayers = $defPlayers = 0;
|
||||
$fleets = array();
|
||||
$players = array(
|
||||
$poFake => array(false, $turretPower, $pTurrets, 0, 0, 0, 0, array())
|
||||
);
|
||||
$attPower = 0;
|
||||
$cSales = null;
|
||||
|
||||
// Extract fleet data
|
||||
while ($r = dbFetchHash($q)) {
|
||||
if ( ($r['owner'] == $pOwner && $vacation == 'YES ')
|
||||
|| ($r['attacking'] == 't' && $r['time_spent'] < 15) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$r['power'] = $this->fleets->call('getPower', $r['owner'], $r['gaships'],
|
||||
$r['fighters'], $r['cruisers'], $r['bcruisers']);
|
||||
if ($r['attacking'] == 't') {
|
||||
$attFleets[0] += $r['gaships'];
|
||||
$attFleets[1] += $r['fighters'];
|
||||
$attFleets[2] += $r['cruisers'];
|
||||
$attFleets[3] += $r['bcruisers'];
|
||||
$attPower += $r['power'];
|
||||
} else {
|
||||
$defFleets[0] += $r['gaships'];
|
||||
$defFleets[1] += $r['fighters'];
|
||||
$defFleets[2] += $r['cruisers'];
|
||||
$defFleets[3] += $r['bcruisers'];
|
||||
$defPower += $r['power'];
|
||||
}
|
||||
|
||||
if (is_null($players[$r['owner']])) {
|
||||
$players[$r['owner']] = array(
|
||||
$r['attacking'] == 't', $r['power'], 0, $r['gaships'],
|
||||
$r['fighters'], $r['cruisers'], $r['bcruisers'], array()
|
||||
);
|
||||
if ($r['attacking'] == 't') {
|
||||
$attPlayers ++;
|
||||
} else {
|
||||
$defPlayers ++;
|
||||
}
|
||||
} else {
|
||||
$players[$r['owner']][1] += $r['power'];
|
||||
$players[$r['owner']][3] += $r['gaships'];
|
||||
$players[$r['owner']][4] += $r['fighters'];
|
||||
$players[$r['owner']][5] += $r['cruisers'];
|
||||
$players[$r['owner']][6] += $r['bcruisers'];
|
||||
}
|
||||
|
||||
array_push($players[$r['owner']][7], $r['id']);
|
||||
$fleets[$r['id']] = $r;
|
||||
}
|
||||
|
||||
// If there is no defense at all, forget it
|
||||
// (that can also mean that the local defense fleet is on vacation)
|
||||
// Also skip if there are no attack fleets (could happen because of separate transactions)
|
||||
if ($defPower == 0 || $attPower == 0) {
|
||||
l::debug("Skipped battle on $pName, no fleets");
|
||||
return array();
|
||||
}
|
||||
l::debug("Starting battle on $pName (owner: $poFake); $pTurrets turrets, vacation=$vacation");
|
||||
|
||||
// Compute the damage index, which is the proportion of damage inflicted by the biggest fleet
|
||||
$dRandom = $defPower;
|
||||
while ($dRandom > 1000) {
|
||||
$dRandom = $dRandom / 10;
|
||||
}
|
||||
$rdPower = $defPower + rand(0, round($dRandom * 0.05));
|
||||
l::debug("Defense: power= $defPower ; random= $dRandom; rPower= $rdPower");
|
||||
|
||||
$aRandom = $attPower;
|
||||
while ($aRandom > 1000) {
|
||||
$aRandom = $aRandom / 10;
|
||||
}
|
||||
$raPower = $attPower + rand(0, round($aRandom * 0.05));
|
||||
l::debug("Attack: power= $attPower ; random= $aRandom; rPower= $raPower");
|
||||
|
||||
$bigDef = ($rdPower > $raPower);
|
||||
$bigPower = $bigDef ? $rdPower : $raPower;
|
||||
$smallPower = $bigDef ? $raPower : $rdPower;
|
||||
$ratio = $bigPower / $smallPower;
|
||||
$damageIndex = ($ratio > 10 ? 1 : ((exp($ratio - 1) / (exp($ratio - 1) + 1))));
|
||||
$attDamage = round(($bigDef ? $damageIndex : (1 - $damageIndex)) * $attPower);
|
||||
$defDamage = round(($bigDef ? (1-$damageIndex) : $damageIndex) * $defPower);
|
||||
l::debug("Damage index: $damageIndex (attDamage: $attDamage ; defDamage: $defDamage)");
|
||||
|
||||
// Handle heroic defense
|
||||
if (! $bigDef && $ratio >= 5 && rand(0, 10000) <= 200) {
|
||||
$heroicDefense = true;
|
||||
$addDamage = ceil($smallPower * rand(300, 400) / 100);
|
||||
if ($addDamage > $bigPower / 5) {
|
||||
$addDamage = ceil($bigPower / 5);
|
||||
}
|
||||
$attDamage += $addDamage;
|
||||
l::debug("Heroic defense! Damage increased by $addDamage (-> $attDamage)");
|
||||
} else {
|
||||
$heroicDefense = false;
|
||||
}
|
||||
|
||||
// Compute the amount of damage to each player
|
||||
$defLosses = $attLosses = 0;
|
||||
$plist = array_keys($players);
|
||||
$turretLoss = $tPowerLoss = 0;
|
||||
foreach ($plist as $id) {
|
||||
l::debug(" -> Player $id");
|
||||
if ($players[$id][0])
|
||||
$losses = ($players[$id][1] / $attPower) * $attDamage;
|
||||
else
|
||||
$losses = ($players[$id][1] / $defPower) * $defDamage;
|
||||
l::debug(" * losses = $losses");
|
||||
|
||||
$rules = $this->rules->call('get', ($id == 0) ? null : $id);
|
||||
if ($damageIndex < 1 || ($players[$id][0] && !$bigDef || !$players[$id][0] && $bigDef)) {
|
||||
$losses = ($losses / 100) * $rules['battle_losses'];
|
||||
l::debug(" * losses = $losses after adjustment ({$rules['battle_losses']}%)");
|
||||
} else {
|
||||
l::debug(" * losses not adjusted");
|
||||
}
|
||||
|
||||
// Compute damage for each type of ship
|
||||
$probLoss = array(0, 0, 0, 0, 0); $oriFleet = array();
|
||||
if ($players[$id][1] > 0) {
|
||||
$sPowers = array(); $power = array();
|
||||
$tLoss = 0;
|
||||
$lossRatio = $losses / $players[$id][1];
|
||||
for ($i=0;$i<5;$i++) {
|
||||
$sPowers[$i] = ($rules[$rnames[$i] . "_power"] / 100)
|
||||
* $rules['effective_fleet_power'];
|
||||
$oriFleet[$i] = $players[$id][$i+2];
|
||||
$power[$i] = $sPowers[$i] * $players[$id][$i+2];
|
||||
$shipRatio = $power[$i] / $players[$id][1];
|
||||
$pLoss = $shipRatio * $losses;
|
||||
$probLoss[$i] = min($players[$id][$i+2], round($pLoss / $sPowers[$i]));
|
||||
$tLoss += $probLoss[$i] * $sPowers[$i];
|
||||
}
|
||||
|
||||
$i = $n = 0;
|
||||
while ($tLoss < $losses && $n < 5) {
|
||||
if ($probLoss[$i] < $players[$id][$i+2]) {
|
||||
$probLoss[$i] ++;
|
||||
$tLoss += $sPowers[$i];
|
||||
$n = 0;
|
||||
} else {
|
||||
$n++;
|
||||
}
|
||||
$i = ($i + 1) % 5;
|
||||
}
|
||||
}
|
||||
l::debug(" * ship losses (T/G/F/C/B) = " . join(', ', $probLoss)
|
||||
. " out of " . join(', ', $oriFleet));
|
||||
|
||||
// If there are turret losses, remove turrets
|
||||
if ($probLoss[0] > 0) {
|
||||
$turretLoss = $probLoss[0];
|
||||
$tPowerLoss = $this->planets->call('getPower', $pOwner, $turretLoss);
|
||||
$this->btQuery("UPDATE planet SET turrets=turrets-$turretLoss WHERE id=$lId");
|
||||
$tm = time();
|
||||
$this->btQuery("DELETE FROM turhist WHERE $tm-moment>86400");
|
||||
$this->btQuery("INSERT INTO turhist VALUES ($lId,$tm,-$turretLoss)");
|
||||
|
||||
// Mark the planet's sale to be cancelled if that applies
|
||||
$q = $this->btQuery("SELECT id,player,finalized,sold_to FROM sale WHERE planet=$lId");
|
||||
if (($r = dbFetchArray($q)) && is_null($cSales)) {
|
||||
$cSales = $r;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply losses to the player's individual fleets
|
||||
$removed = array(0, 0, 0, 0);
|
||||
foreach ($players[$id][7] as $fid) {
|
||||
$rff = $tif = 0;
|
||||
$rem = array();
|
||||
for ($i=0;$i<4;$i++) {
|
||||
// Ships that must be destroyed
|
||||
$toRemove = $probLoss[$i+1] - $removed[$i];
|
||||
|
||||
// Ships in the fleet
|
||||
$inFleet = $fleets[$fid][$rnames[$i+1]."s"];
|
||||
$tif += $inFleet;
|
||||
|
||||
// Remove ships
|
||||
$fromFleet = min($toRemove, $inFleet);
|
||||
$removed[$i] += $fromFleet;
|
||||
$rff += $fromFleet;
|
||||
$rem[$i] = $fromFleet;
|
||||
}
|
||||
l::debug(" * fleet $fid losses (G/F/C/B) = " . join(', ', $rem));
|
||||
|
||||
// Mark the fleet's sale to be cancelled if that applies
|
||||
if ($rff) {
|
||||
$q = $this->btQuery("SELECT id,player,finalized,sold_to FROM sale WHERE fleet=$fid");
|
||||
if ($r = dbFetchArray($q)) {
|
||||
if (is_null($r[2])) {
|
||||
$ga = 'cancel';
|
||||
} else {
|
||||
$ga = 'cancelTransfer';
|
||||
}
|
||||
$this->sales->call($ga, $r[1], $r[0]);
|
||||
|
||||
// FIXME: send messages
|
||||
if (!is_null($cSales) && $cSales == $r[0]) {
|
||||
$cSales = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($rff == $tif) {
|
||||
// The whole fleet has been lost
|
||||
$this->btQuery("DELETE FROM fleet WHERE id=$fid");
|
||||
} elseif ($rff) {
|
||||
// Fleet has suffered some losses
|
||||
$qs = "UPDATE fleet SET ";
|
||||
$qsi = false;
|
||||
for ($i=0;$i<4;$i++) {
|
||||
if ($rem[$i] == 0) {
|
||||
continue;
|
||||
}
|
||||
if ($qsi) {
|
||||
$qs .= ",";
|
||||
} else {
|
||||
$qsi = true;
|
||||
}
|
||||
$qs .= $rnames[$i+1]."s=".$rnames[$i+1]."s-".$rem[$i];
|
||||
}
|
||||
$qs .= " WHERE id=$fid";
|
||||
$this->btQuery($qs);
|
||||
} else {
|
||||
// No losses, we're done
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add losses to the correct array
|
||||
if ($players[$id][0]) {
|
||||
for ($i=0;$i<4;$i++) {
|
||||
$attFleets[$i+4] += $probLoss[$i+1];
|
||||
}
|
||||
} else {
|
||||
for ($i=0;$i<4;$i++) {
|
||||
$defFleets[$i+4] += $probLoss[$i+1];
|
||||
}
|
||||
}
|
||||
|
||||
// Store the player's losses
|
||||
$lostPower = $this->fleets->call('getPower', ($id==0 ? null : $id), $probLoss[1], $probLoss[2], $probLoss[3], $probLoss[4]);
|
||||
$lostPower += $this->planets->call('getPower', ($id==0 ? null : $id), $probLoss[0]);
|
||||
array_shift($probLoss);
|
||||
$players[$id][8] = $probLoss;
|
||||
$players[$id][9] = $lostPower;
|
||||
if ($players[$id][0]) {
|
||||
$attLosses += $lostPower;
|
||||
} else {
|
||||
$defLosses += $lostPower;
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel the planet's sale if it suffered damage
|
||||
if (!is_null($cSales)) {
|
||||
if (is_null($cSales[2])) {
|
||||
$ga = 'cancel';
|
||||
} else {
|
||||
$ga = 'cancelTransfer';
|
||||
}
|
||||
$this->sales->call($ga, $cSales[1], $cSales[0]);
|
||||
// FIXME: send messages
|
||||
}
|
||||
|
||||
// Give the players "inflicted damage" points
|
||||
$idrInc = array();
|
||||
foreach ($plist as $id) {
|
||||
if ($id == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$q = $this->btQuery("SELECT hidden FROM player WHERE id = $id");
|
||||
list($hidden) = dbFetchArray($q);
|
||||
if ($hidden == 't') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($players[$id][0]) {
|
||||
$tPower = $attPower;
|
||||
$eLoss = $defLosses;
|
||||
} else {
|
||||
$tPower = $defPower;
|
||||
$eLoss = $attLosses;
|
||||
}
|
||||
$ii = round(($players[$id][1] / $tPower) * $eLoss);
|
||||
$n = $this->players->call('getName', $id);
|
||||
if (is_null($idrInc[$n])) {
|
||||
$idrInc[$n] = $ii;
|
||||
} else {
|
||||
$idrInc[$n] += $ii;
|
||||
}
|
||||
}
|
||||
|
||||
// Send battle reports
|
||||
$tm = time();
|
||||
foreach ($plist as $id) {
|
||||
// Avoid the fake "neutral" player
|
||||
if ($id == 0) {
|
||||
continue;
|
||||
}
|
||||
$p = $players[$id];
|
||||
|
||||
// Get friendly/hostile data
|
||||
if ($players[$id][0]) {
|
||||
$fPower = $attPower;
|
||||
$ePower = $defPower;
|
||||
$fLosses = $attLosses;
|
||||
$eLosses = $defLosses;
|
||||
$fFleets = $attFleets;
|
||||
$eFleets = $defFleets;
|
||||
$tMode = ($pTurrets != 0 ? 3 : 0);
|
||||
} else {
|
||||
$fPower = $defPower;
|
||||
$ePower = $attPower;
|
||||
$fLosses = $defLosses;
|
||||
$eLosses = $attLosses;
|
||||
$fFleets = $defFleets;
|
||||
$eFleets = $attFleets;
|
||||
$tMode = ($pTurrets != 0 ? ($pOwner == $id ? 1 : 2) : 0);
|
||||
}
|
||||
|
||||
// Remove the player's own statistics from the list of friendlies
|
||||
$fPower -= $p[1]; $fLosses -= $p[9];
|
||||
for ($i=0;$i<4;$i++) {
|
||||
$fFleets[$i] -= $p[$i+3];
|
||||
$fFleets[$i+4] -= $p[8][$i];
|
||||
}
|
||||
|
||||
// Send battle report
|
||||
$this->msgs->call('send', $id, "battle", array(
|
||||
"planet_id" => $lId,
|
||||
"planet" => $pName,
|
||||
"o_gaships" => $p[3],
|
||||
"o_fighters" => $p[4],
|
||||
"o_cruisers" => $p[5],
|
||||
"o_bcruisers" => $p[6],
|
||||
"o_power" => $p[1],
|
||||
"ol_gaships" => $p[8][0],
|
||||
"ol_fighters" => $p[8][1],
|
||||
"ol_cruisers" => $p[8][2],
|
||||
"ol_bcruisers" => $p[8][3],
|
||||
"ol_power" => $p[9],
|
||||
"a_gaships" => $fFleets[0],
|
||||
"a_fighters" => $fFleets[1],
|
||||
"a_cruisers" => $fFleets[2],
|
||||
"a_bcruisers" => $fFleets[3],
|
||||
"a_power" => $fPower,
|
||||
"al_gaships" => $fFleets[4],
|
||||
"al_fighters" => $fFleets[5],
|
||||
"al_cruisers" => $fFleets[6],
|
||||
"al_bcruisers" => $fFleets[7],
|
||||
"al_power" => $fLosses,
|
||||
"e_gaships" => $eFleets[0],
|
||||
"e_fighters" => $eFleets[1],
|
||||
"e_cruisers" => $eFleets[2],
|
||||
"e_bcruisers" => $eFleets[3],
|
||||
"e_power" => $ePower,
|
||||
"el_gaships" => $eFleets[4],
|
||||
"el_fighters" => $eFleets[5],
|
||||
"el_cruisers" => $eFleets[6],
|
||||
"el_bcruisers" => $eFleets[7],
|
||||
"el_power" => $eLosses,
|
||||
"turrets" => $pTurrets,
|
||||
"tpower " => $turretPower,
|
||||
"l_turrets" => $turretLoss,
|
||||
"l_tpower" => $tPowerLoss,
|
||||
"tmode" => $tMode,
|
||||
"heroic_def" => $heroicDefense ? ($players[$id][0] ? -1 : 1) : 0
|
||||
));
|
||||
}
|
||||
|
||||
// Update happiness and attack status
|
||||
$this->planets->call('updateHappiness', $lId);
|
||||
$this->planets->call('updateMilStatus', $lId);
|
||||
|
||||
// If the planet was pending entrance in vacation mode and all enemy
|
||||
// fleet is dead, set it to vacation mode.
|
||||
if ($vacation == 'PEND') {
|
||||
$q = $this->btQuery("SELECT COUNT(*) FROM fleet WHERE location=$lId AND attacking");
|
||||
if ($q && dbCount($q) == 1) {
|
||||
list($c) = dbFetchArray($q);
|
||||
if ($c == 0) {
|
||||
$this->btQuery("UPDATE planet SET vacation='YES' WHERE id=$lId");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $idrInc;
|
||||
}
|
||||
|
||||
|
||||
function btQuery($q) {
|
||||
$r = $this->db->query($q);
|
||||
l::trace("Result '$r' for query: $q");
|
||||
return $r;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
250
scripts/game/beta5/ticks/cash/library.inc
Normal file
250
scripts/game/beta5/ticks/cash/library.inc
Normal file
|
@ -0,0 +1,250 @@
|
|||
<?php
|
||||
|
||||
//------------------------------------------------------
|
||||
// "Cash tick": Income computations & fleet destruction
|
||||
//------------------------------------------------------
|
||||
|
||||
class beta5_ticks_cash_library {
|
||||
|
||||
public function __construct($lib) {
|
||||
$this->lib = $lib;
|
||||
$this->game = $this->lib->game;
|
||||
$this->db = $this->game->db;
|
||||
$this->fleets = $this->game->getLib('beta5/fleet');
|
||||
$this->msgs = $this->game->getLib('beta5/msg');
|
||||
$this->planets = $this->game->getLib('beta5/planet');
|
||||
$this->players = $this->game->getLib('beta5/player');
|
||||
$this->rules = $this->game->getLib('beta5/rules');
|
||||
}
|
||||
|
||||
|
||||
public function runTick() {
|
||||
// Update time required to abandon planets
|
||||
$this->db->safeTransaction(array($this, "handleAbandon"));
|
||||
|
||||
// Handle the players' income
|
||||
$players = $this->db->safeTransaction(array($this, "getPlayers"));
|
||||
foreach ($players as $player) {
|
||||
$this->db->safeTransaction(array($this, "playerIncome"), $player);
|
||||
}
|
||||
|
||||
// Handle CTF victory
|
||||
$this->db->safeTransaction(array($this, "checkCTF"));
|
||||
}
|
||||
|
||||
|
||||
public function checkCTF() {
|
||||
// Check victory status on CTF games
|
||||
if ($this->game->params['victory'] == 2 && ! $this->game->getLib()->call('isFinished')) {
|
||||
$this->game->getLib('beta5/ctf')->call('checkTargets');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function getPlayers() {
|
||||
$q = $this->db->query(
|
||||
"SELECT id FROM player "
|
||||
. "WHERE quit IS NULL "
|
||||
. "OR UNIX_TIMESTAMP(NOW()) - quit < 86400"
|
||||
);
|
||||
|
||||
$players = array();
|
||||
while ($r = dbFetchArray($q)) {
|
||||
array_push($players, $r[0]);
|
||||
}
|
||||
|
||||
return $players;
|
||||
}
|
||||
|
||||
|
||||
public function playerIncome($id) {
|
||||
$q = $this->db->query(
|
||||
"SELECT p.cash, (a.status = 'VAC') FROM player p,account a "
|
||||
. "WHERE p.id = $id AND a.id = p.userid "
|
||||
. "FOR UPDATE OF p"
|
||||
);
|
||||
list($cash, $vac) = dbFetchArray($q);
|
||||
|
||||
$protected = $this->players->call('getProtectionLevel', $id);
|
||||
|
||||
$div = ($vac == 't' ? 4 : 1);
|
||||
$mult = ($protected ? 1.15 : 1);
|
||||
$income = round($this->computeIncome($id) * $mult / $div);
|
||||
$upkeep = round($this->computeUpkeep($id) / $div);
|
||||
$profit = ceil($income - $upkeep) / 2;
|
||||
|
||||
$cash += $profit;
|
||||
if ($cash < 0) {
|
||||
$this->debt($id, $income, $upkeep, $cash);
|
||||
$cash = 0;
|
||||
}
|
||||
$this->db->query("UPDATE player SET cash=$cash WHERE id=$id");
|
||||
}
|
||||
|
||||
|
||||
private function computeIncome($player) {
|
||||
$income = 0;
|
||||
$ppl = $this->players->call('getPlanets', $player);
|
||||
|
||||
foreach ($ppl as $id => $name) {
|
||||
$info = $this->planets->call('byId', $id);
|
||||
$m = $this->planets->call('getIncome', $player, $info['pop'], $info['happiness'],
|
||||
$info['ifact'], $info['mfact'], $info['turrets'], $info['corruption']);
|
||||
$income += $m[0];
|
||||
}
|
||||
|
||||
return $income;
|
||||
}
|
||||
|
||||
|
||||
private function computeUpkeep($player) {
|
||||
$pfl = $this->players->call('getFleets', $player);
|
||||
$upkeep = 0;
|
||||
|
||||
foreach ($pfl as $id => $name) {
|
||||
$info = $this->fleets->call('get', $id);
|
||||
$u = $this->fleets->call('getUpkeep', $player, $info['gaships'], $info['fighters'],
|
||||
$info['cruisers'], $info['bcruisers']);
|
||||
$upkeep += $u;
|
||||
}
|
||||
|
||||
return $upkeep;
|
||||
}
|
||||
|
||||
|
||||
private function killFleets($id, $ratio) {
|
||||
$fl = array_keys($this->players->call('getFleets', $id));
|
||||
$rules = $this->rules->call('get', $id);
|
||||
|
||||
$kills = array(0, 0, 0, 0);
|
||||
foreach ($fl as $fid) {
|
||||
$f = $this->fleets->call('get', $fid);
|
||||
|
||||
if (is_null($f['waiting']) && (is_null($f['moving'])
|
||||
|| !is_null($f['moving']) && $f['move']['hyperspace'] == 'f')) {
|
||||
|
||||
// Fleet is idle or not in HyperSpace
|
||||
$kg = ceil($ratio * $f['gaships']);
|
||||
$kf = ceil($ratio * $f['fighters']);
|
||||
$kc = ceil($ratio * $f['cruisers']);
|
||||
$kb = ceil($ratio * $f['bcruisers']);
|
||||
} else {
|
||||
// Fleet is in Hyperspace
|
||||
$kc = ceil($f['cruisers'] * $ratio);
|
||||
$kb = ceil($f['bcruisers'] * $ratio);
|
||||
|
||||
// Compute the amount of transported ships to be destroyed
|
||||
// FIXME: computeHyperspaceDamage() ?
|
||||
$gaSpace = $f['gaships'] * $rules['gaship_space'];
|
||||
$fSpace = $f['fighters'] * $rules['fighter_space'];
|
||||
$tSpace = $gaSpace + $fSpace;
|
||||
if ($tSpace > 0) {
|
||||
$haul = $f['cruisers'] * $rules['cruiser_haul']
|
||||
+ $f['bcruisers'] * $rules['bcruiser_haul'];
|
||||
$haulUsed = $tSpace / $haul;
|
||||
$lHaul = $kc * $rules['cruiser_haul'] + $kb * $rules['bcruiser_haul'];
|
||||
$lSpace = $haulUsed * $lHaul;
|
||||
$gaLSpace = ($lSpace / $tSpace) * $gaSpace;
|
||||
$fLSpace = ($lSpace / $tSpace) * $fSpace;
|
||||
$kg = min($f['gaships'], ceil($gaLSpace / $rules['gaship_space']));
|
||||
$kf = min($f['fighters'], ceil($fLSpace / $rules['fighter_space']));
|
||||
} else {
|
||||
$kg = $kf = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ($kc == $f['cruisers'] && $kb == $f['bcruisers'] && $kf == $f['fighters']
|
||||
&& $kg == $f['gaships']) {
|
||||
|
||||
$this->fleets->call('disband', $fid, true);
|
||||
} elseif ($kc + $kb + $kf + $kg > 0) {
|
||||
$this->db->query(
|
||||
"UPDATE fleet SET gaships=gaships - $kg, fighters = fighters - $kf, "
|
||||
. "cruisers=cruisers - $kc,bcruisers = bcruisers - $kb "
|
||||
. "WHERE id=$fid"
|
||||
);
|
||||
$this->fleets->call('invCache', $fid);
|
||||
}
|
||||
$kills[0] += $kg; $kills[1] += $kf; $kills[2] += $kc; $kills[3] += $kb;
|
||||
}
|
||||
|
||||
// No kills?
|
||||
if ($kills[0] + $kills[1] + $kills[2] + $kills[3] == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Send the message
|
||||
$this->msgs->call('send', $id, 'kfleet', array(
|
||||
"gaships" => $kills[0],
|
||||
"fighters" => $kills[1],
|
||||
"cruisers" => $kills[2],
|
||||
"bcruisers" => $kills[3],
|
||||
));
|
||||
|
||||
$this->players->call('updateHappiness', $id);
|
||||
}
|
||||
|
||||
|
||||
private function debt($id, $income, $upkeep, $cash) {
|
||||
if ($upkeep > 0) {
|
||||
$ratio = min(-$cash * 2 / $upkeep, 1) / 5;
|
||||
$this->killFleets($id, $ratio);
|
||||
return;
|
||||
}
|
||||
|
||||
$rules = $this->rules->call('get', $id);
|
||||
$ppl = $this->players->call('getPlanets', $id);
|
||||
$pinf = array();
|
||||
foreach ($ppl as $pid => $name) {
|
||||
$info = $this->planets->call('byId', $pid);
|
||||
$ic = $this->planets->call('getIncome', $id, $info['pop'], $info['ifact'],
|
||||
$info['mfact'], $info['turrets'], $info['corruption']);
|
||||
$info['income'] = $ic[0];
|
||||
if ($info['income'] >= 0) {
|
||||
$income -= $info['income'];
|
||||
continue;
|
||||
} else {
|
||||
$income -= $ic[1] + $ic[2];
|
||||
$info['income'] -= $ic[1] + $ic[2];
|
||||
}
|
||||
$pinf[$pid] = $info;
|
||||
}
|
||||
|
||||
$kill = array(0, 0);
|
||||
foreach ($pinf as $pid => $p) {
|
||||
$ratio = $p['income'] / $income;
|
||||
$tCost = $p['turrets'] * $rules['turret_cost'];
|
||||
$mCost = $p['mfact'] * $rules['factory_cost'];
|
||||
$tRatio = (rand(10,20)/100) * $ratio * $tCost / (-$p['income']);
|
||||
$mRatio = (rand(10,20)/100) * $ratio * $mCost / (-$p['income']);
|
||||
|
||||
$tLoss = ceil($p['turrets'] * $tRatio);
|
||||
$mLoss = ceil($p['mfact'] * $mRatio);
|
||||
if ($tLoss + $mLoss == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->db->query("UPDATE planet SET turrets=turrets-$tLoss,mfact=mfact-$mLoss WHERE id=$pid");
|
||||
$kill[0] += $tLoss; $kill[1] += $mLoss;
|
||||
$this->planets->call('updateHappiness', $pid);
|
||||
}
|
||||
|
||||
if ($kill[0] + $kill[1] == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->msgs->call('send', $id, 'kimpr', array("turrets" => $kill[0], "factories" => $kill[1]));
|
||||
}
|
||||
|
||||
|
||||
public function handleAbandon() {
|
||||
$this->db->query(
|
||||
"UPDATE planet_abandon_time "
|
||||
. "SET time_required = time_required + 1 "
|
||||
. "WHERE time_required < 24"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
479
scripts/game/beta5/ticks/day/library.inc
Normal file
479
scripts/game/beta5/ticks/day/library.inc
Normal file
|
@ -0,0 +1,479 @@
|
|||
<?php
|
||||
|
||||
//------------------------------------------------------
|
||||
// "Day tick": Research, population increase, rankings,
|
||||
// protection levels
|
||||
//------------------------------------------------------
|
||||
|
||||
class beta5_ticks_day_library {
|
||||
|
||||
public function __construct($lib) {
|
||||
$this->lib = $lib;
|
||||
$this->game = $this->lib->game;
|
||||
$this->db = $this->game->db;
|
||||
$this->main = $this->game->getLib();
|
||||
$this->planets = $this->game->getLib('beta5/planet');
|
||||
$this->players = $this->game->getLib('beta5/player');
|
||||
$this->msgs = $this->game->getLib('beta5/msgs');
|
||||
$this->fleets = $this->game->getLib('beta5/fleet');
|
||||
$this->rankings = $this->game->getLib('main/rankings');
|
||||
$this->rules = $this->game->getLib('beta5/rules');
|
||||
$this->tech = $this->game->getLib('beta5/tech');
|
||||
}
|
||||
|
||||
|
||||
public function runTick() {
|
||||
// Cache the whole research tree, we'll need that later
|
||||
$this->tech->call('getTree');
|
||||
|
||||
// Increase neutral population
|
||||
l::debug("Increasing neutral population");
|
||||
$this->db->safeTransaction(array($this, 'increasePopulation'), array(null, false));
|
||||
|
||||
// Increase population and research
|
||||
$players = $this->db->safeTransaction(array($this, 'getPlayers'));
|
||||
$this->playerPopulation($players);
|
||||
$this->playerResearch($players);
|
||||
|
||||
// Mass-update status and timers
|
||||
$this->db->safeTransaction(array($this, 'statusUpdates'));
|
||||
|
||||
// Dry run of the rankings computation
|
||||
list($players, $playersById) = $this->db->safeTransaction(
|
||||
array($this->main, 'call'), array('updateRankings', true)
|
||||
);
|
||||
|
||||
// Restore neutral planets and decrease protection levels
|
||||
if ((int) $this->game->params['victory'] == 0) {
|
||||
$this->db->safeTransaction(array($this, 'restoreNeutrals'));
|
||||
$this->db->safeTransaction(array($this, 'decreaseProtection'));
|
||||
}
|
||||
|
||||
// Update the data warehouse
|
||||
$this->db->safeTransaction(array($this, 'updateWarehouse'), array($players, $playersById));
|
||||
}
|
||||
|
||||
|
||||
public function restoreNeutrals() {
|
||||
$q = $this->db->query("SELECT p.id FROM planet p, system s "
|
||||
. "WHERE p.owner IS NULL AND p.status = 0 AND s.id = p.system "
|
||||
. "AND s.nebula = 0"
|
||||
);
|
||||
|
||||
while ($r = dbFetchArray($q)) {
|
||||
$this->planets->call('restoreNeutral', $r[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function decreaseProtection() {
|
||||
$q = $this->db->query(
|
||||
"SELECT s.id, s.prot, y.id FROM system s, player y "
|
||||
. "WHERE s.prot > 0 AND s.nebula = 0 "
|
||||
. "AND y.id = (SELECT DISTINCT p.owner FROM planet p "
|
||||
. "WHERE p.system = s.id AND owner IS NOT NULL) "
|
||||
. "FOR UPDATE OF s, y");
|
||||
$removeProtection = array();
|
||||
while ($r = dbFetchArray($q)) {
|
||||
if ($r[1] == 1) {
|
||||
$removeProtection[$r[0]] = $r[2];
|
||||
}
|
||||
}
|
||||
|
||||
$this->db->query("UPDATE system SET prot = prot - 1 WHERE prot > 1 AND nebula = 0");
|
||||
foreach ($removeProtection as $system => $player) {
|
||||
$this->players->call('breakProtection', $player, 'EXP');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function getPlayers() {
|
||||
$q = $this->db->query(
|
||||
"SELECT p.id, (a.status <> 'STD') FROM player p, account a "
|
||||
. "WHERE (p.quit IS NULL OR UNIX_TIMESTAMP(NOW()) - p.quit < 86400) "
|
||||
. "AND a.id = p.userid"
|
||||
);
|
||||
|
||||
$players = array();
|
||||
while ($r = dbFetchArray($q)) {
|
||||
$players[$r[0]] = ($r[1] == 't');
|
||||
}
|
||||
|
||||
return $players;
|
||||
}
|
||||
|
||||
|
||||
private function playerResearch($players) {
|
||||
l::debug("Increasing player research");
|
||||
foreach ($players as $playerID => $vacation) {
|
||||
$this->db->safeTransaction(array($this, 'research'), array($playerID, $vacation));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function playerPopulation($players) {
|
||||
l::debug("Increasing player population");
|
||||
foreach ($players as $playerID => $vacation) {
|
||||
l::trace("Increasing population for player #$playerID");
|
||||
$this->db->safeTransaction(array($this, 'increasePopulation'), array($playerID, $vacation));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function statusUpdates() {
|
||||
// Laws: reduce delays to enact/revoke laws
|
||||
$this->db->query("UPDATE research_player SET in_effect=in_effect-1 WHERE in_effect>1");
|
||||
$this->db->query("UPDATE research_player SET in_effect=in_effect+1 WHERE in_effect<0");
|
||||
|
||||
// Remove research assistance
|
||||
$this->db->query("UPDATE player SET res_assistance=NULL WHERE res_assistance IS NOT NULL");
|
||||
|
||||
// Restrictions on new players
|
||||
$this->db->query("UPDATE player SET restrain=restrain-1 WHERE restrain >= 1");
|
||||
|
||||
// Decrease unhappiness because of Wormhole Super Novas and sales
|
||||
$this->db->query("UPDATE player SET bh_unhappiness=bh_unhappiness-1 WHERE bh_unhappiness>0");
|
||||
$this->db->query("UPDATE planet SET bh_unhappiness=bh_unhappiness-1 WHERE bh_unhappiness>0 AND status=0");
|
||||
|
||||
// Probe building
|
||||
$this->db->query("UPDATE planet SET built_probe=FALSE WHERE built_probe");
|
||||
}
|
||||
|
||||
|
||||
// Advance a player's research status.
|
||||
public function research($id, $onVacation) {
|
||||
$q = $this->db->query("SELECT COUNT(*) FROM research_player WHERE player=$id");
|
||||
list($c) = dbFetchArray($q);
|
||||
if (!$c) {
|
||||
if ($this->lib->game->params['partialtechs'] == 1) {
|
||||
$this->tech->call('createTree', $id);
|
||||
} else {
|
||||
$q = $this->db->query("SELECT id FROM research");
|
||||
while ($r = dbFetchArray($q)) {
|
||||
$this->db->query("INSERT INTO research_player(player,research,possible) "
|
||||
. "VALUES($id,{$r[0]},TRUE)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the whole tech tree and the player's research points
|
||||
$rp = $this->tech->call('getPoints',$id);
|
||||
list($res, $rLeaf) = $this->tech->call('getTree', $id);
|
||||
|
||||
// Reduce by half if we're giving assistance
|
||||
$q = $this->db->query("SELECT id FROM player WHERE res_assistance=$id");
|
||||
if (dbCount($q)) {
|
||||
$rp = round($rp / 2);
|
||||
}
|
||||
|
||||
// Are we receiving assistance?
|
||||
$q = $this->db->query("SELECT research,res_assistance FROM player WHERE id=$id");
|
||||
list($rb, $ra) = dbFetchArray($q);
|
||||
if (!is_null($ra)) {
|
||||
$rp += round(min($this->tech->call('getPoints', $ra), $rp) / 2);
|
||||
}
|
||||
|
||||
// If the player's on vacation, he gets a fourth of the RPs
|
||||
if ($onVacation) {
|
||||
$rp = round($rp / 4);
|
||||
}
|
||||
|
||||
// If the player is under protection, he gets a +25% bonus
|
||||
if ($this->players->call('getProtectionLevel', $id)) {
|
||||
$rp = round($rp * 1.25);
|
||||
}
|
||||
|
||||
// Divide research points between categories
|
||||
$rbl = explode('!',$rb);
|
||||
$rbp = array();
|
||||
for ($i=$s=0;$i<3;$i++) {
|
||||
$rbp[$i] = floor($rbl[$i] * $rp / 100);
|
||||
$s += $rbp[$i];
|
||||
}
|
||||
for ($i=0;$s<$rb;$i=($i+1)%3) {
|
||||
$rbp[$i] ++; $s ++;
|
||||
}
|
||||
$possible = array(array(), array(), array());
|
||||
|
||||
// Get current research topics
|
||||
$q = $this->db->query("SELECT p.research,p.points FROM research_player p,research r "
|
||||
. "WHERE p.research=r.id AND p.points>0 AND p.points<r.points AND p.player=$id");
|
||||
$npc = array(0, 0, 0);
|
||||
while ($r = dbFetchArray($q)) {
|
||||
$rp = array(
|
||||
'id' => $r[0],
|
||||
'pts' => $r[1],
|
||||
'max' => $res[$r[0]]['points']
|
||||
);
|
||||
$cat = $res[$r[0]]['category'];
|
||||
array_push($possible[$cat], $rp);
|
||||
$npc[$cat] ++;
|
||||
}
|
||||
|
||||
// Get pending research topics
|
||||
$q = $this->db->query("SELECT research FROM research_player WHERE player=$id AND points=0 AND possible");
|
||||
$pending = array(array(),array(),array());
|
||||
while ($r = dbFetchArray($q)) {
|
||||
array_push($pending[$res[$r[0]]['category']], $r[0]);
|
||||
}
|
||||
|
||||
// Get completed research
|
||||
$q = $this->db->query("SELECT p.research FROM research_player p,research r "
|
||||
. "WHERE p.research=r.id AND p.points=r.points AND (r.is_law OR p.in_effect <> 0) AND p.player=$id");
|
||||
$pRes = array();
|
||||
while ($r = dbFetchArray($q)) {
|
||||
$pRes[$r[0]] = 1;
|
||||
}
|
||||
|
||||
// Find topics which have their dependencies satisfied
|
||||
for ($i=0;$i<3;$i++) {
|
||||
foreach ($pending[$i] as $p) {
|
||||
$ok = true;
|
||||
foreach ($res[$p]['depends_on'] as $dep) {
|
||||
$ok = $ok && $pRes[$dep];
|
||||
}
|
||||
if ($ok) {
|
||||
array_push($possible[$i], array(
|
||||
'id' => $p,
|
||||
'pts' => 0,
|
||||
'max' => $res[$p]['points']
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find points left for each category
|
||||
$left = array(); $nrec = 0; $points = 0;
|
||||
for ($i=0;$i<3;$i++) {
|
||||
$max = 0;
|
||||
foreach ($possible[$i] as $rt) {
|
||||
$max += $rt['max'] - $rt['pts'];
|
||||
}
|
||||
$left[$i] = max(0, $rbp[$i] - $max);
|
||||
if ($left[$i] == 0) {
|
||||
$nrec ++;
|
||||
} else {
|
||||
$points += $left[$i];
|
||||
$rbp[$i] -= $left[$i];
|
||||
}
|
||||
}
|
||||
|
||||
// Reassign extra points if possible
|
||||
if ($points) {
|
||||
for ($i=0;$i<3;$i++) {
|
||||
if ($left[$i] == 0) {
|
||||
$rbp[$i] += floor($points / $nrec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Increment research points for existing research
|
||||
for ($i=0;$i<3;$i++) {
|
||||
while ($possible[$i][0]['pts'] && $npc[$i]) {
|
||||
$inc = min(floor($rbp[$i] / $npc[$i]), $possible[$i][0]['max'] - $possible[$i][0]['pts']);
|
||||
l::trace("Adding $inc points to research #{$possible[$i][0]['id']} for player #$id");
|
||||
$this->db->query(
|
||||
"UPDATE research_player SET points = points + $inc "
|
||||
. "WHERE research = {$possible[$i][0]['id']} AND player = $id"
|
||||
);
|
||||
array_shift($possible[$i]);
|
||||
$rbp[$i] -= $inc;
|
||||
$npc[$i] --;
|
||||
}
|
||||
}
|
||||
|
||||
// Generate probabilities for new research: the lower a tech's required points,
|
||||
// the higher its probabillity
|
||||
$probabilities = array(array(), array(), array());
|
||||
for ($i=0;$i<3;$i++) {
|
||||
if ($rbp[$i] == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$sum = 0;
|
||||
foreach ($possible[$i] as $idx => $t) {
|
||||
$sum += $t['max'];
|
||||
}
|
||||
|
||||
foreach ($possible[$i] as $idx => $t) {
|
||||
$raw = $sum / $t['max'];
|
||||
$n = ceil($raw * $raw);
|
||||
for ($j=0;$j<$n;$j++) {
|
||||
array_push($probabilities[$i], $idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Start new research
|
||||
$doneSomething = true;
|
||||
$addedTechs = array(array(), array(), array());
|
||||
for ($i=0;$i%3||$doneSomething;$i=($i+1)%3) {
|
||||
if ($i%3==0) {
|
||||
$doneSomething = false;
|
||||
}
|
||||
if (!$rbp[$i] || count($possible[$i]) == count($addedTechs[$i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$doneSomething = true;
|
||||
do {
|
||||
$ridx = $probabilities[$i][rand(0, count($probabilities[$i]) - 1)];
|
||||
} while (in_array($ridx, $addedTechs[$i]));
|
||||
array_push($addedTechs[$i], $ridx);
|
||||
|
||||
$r = $possible[$i][$ridx];
|
||||
$inc = min($rbp[$i], $r['max']);
|
||||
$this->db->query(
|
||||
"UPDATE research_player SET points = points + $inc "
|
||||
. "WHERE research = {$r['id']} AND player = $id"
|
||||
);
|
||||
l::trace("Starting research {$r['id']} with $inc points for player $id");
|
||||
$rbp[$i] -= $inc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function increasePopulation($id, $onVacation = false) {
|
||||
$rules = $this->rules->call('get', $id);
|
||||
if (!is_null($id) && $this->players->call('getProtectionLevel', $id)) {
|
||||
$rules['pop_growth_factor'] = min($rules['pop_growth_factor'] + 1, 5);
|
||||
}
|
||||
$pow = 1.45 - (0.05 * $rules['pop_growth_factor']);
|
||||
$vacFact = $onVacation ? 4 : 1;
|
||||
|
||||
$q = $this->db->query("SELECT id,pop,max_pop,happiness,corruption,mfact+ifact FROM planet "
|
||||
. "WHERE owner" . (is_null($id) ? " IS NULL AND status=0" : "=$id") . " FOR UPDATE");
|
||||
while ($r = dbFetchArray($q)) {
|
||||
$hapVal = ($r[3] - 50) / 12;
|
||||
$hapFct = exp($hapVal) / ((exp($hapVal)+1)*9);
|
||||
|
||||
// Population growth for players that are on vacation is 1/4th of normal
|
||||
$p = round($r[1] + pow($hapFct, $pow) * $r[1] * ($r[2] - $r[1]) / ($vacFact * $r[2]));
|
||||
$growthRatio = $r[1] / $p;
|
||||
|
||||
// Increase corruption
|
||||
$cDec = 5 + 3 * $r[3] / 10;
|
||||
if (!is_null($id)) {
|
||||
$ncor = max(0, $r[4] - $cDec);
|
||||
$x = ($r[1] - 2000) / 48000;
|
||||
$optFact = ($r[1] / 30) - 754 * $x * $x;
|
||||
$mCorInc = $r[5] / 3;
|
||||
$nf = ($r[5] > $optFact * 3) ? ($optFact * 3) : $r[5];
|
||||
$x = abs($nf / $optFact - 1);
|
||||
$v = 10 + $x * $x * $x * 50;
|
||||
|
||||
$ncor = min(32000, $ncor + $v);
|
||||
} else {
|
||||
$ncor = max(0, $r[4] - $cDec * 3);
|
||||
}
|
||||
$ncor = round($ncor * $growthRatio * $growthRatio * $growthRatio);
|
||||
|
||||
$this->db->query("UPDATE planet SET pop=$p,corruption=$ncor WHERE id={$r[0]}");
|
||||
$this->planets->call('updateHappiness', $r[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function updateWarehouse(&$players, &$playersById) {
|
||||
// Get missing data for the warehouse:
|
||||
$this->at = time();
|
||||
|
||||
// -> IDR:
|
||||
$o = $this->rankings->call('getAll', $this->rankings->call('getType', 'p_idr'));
|
||||
foreach ($o as $r) {
|
||||
$players[$r['id']]['d_rank'] = $r['points'];
|
||||
}
|
||||
|
||||
// -> Alliance tag:
|
||||
$q = $this->db->query("SELECT p.id,a.tag FROM alliance a,player p "
|
||||
. "WHERE (p.quit IS NULL OR UNIX_TIMESTAMP(NOW())-p.quit<86400)"
|
||||
. " AND p.a_status='IN' AND p.alliance IS NOT NULL AND NOT p.hidden"
|
||||
. " AND a.id=p.alliance");
|
||||
while ($r = dbFetchArray($q)) {
|
||||
$players[$playersById[$r[0]]]['a_tag'] = $r[1];
|
||||
}
|
||||
|
||||
// -> Tech lists
|
||||
$lsts = array();
|
||||
$q = $this->db->query("SELECT p.id,r.id FROM research r,research_player j,player p "
|
||||
. "WHERE (p.quit IS NULL OR UNIX_TIMESTAMP(NOW())-p.quit<86400) AND NOT p.hidden"
|
||||
. " AND j.player=p.id AND j.research=r.id AND j.points=r.points");
|
||||
while ($r = dbFetchArray($q)) {
|
||||
if (!is_array($lsts[$r[0]])) {
|
||||
$lsts[$r[0]] = array();
|
||||
}
|
||||
array_push($lsts[$r[0]], $r[1]);
|
||||
}
|
||||
foreach ($lsts as $pid => $tl) {
|
||||
$players[$playersById[$pid]]['tech_list'] = join(',', $tl);
|
||||
}
|
||||
|
||||
// -> Planet lists and details
|
||||
$q = $this->db->query("SELECT p.id,r.id,r.name,r.pop,r.max_pop,r.ifact,r.mfact,r.turrets,"
|
||||
. "r.happiness,r.beacon,r.abandon,r.corruption "
|
||||
. "FROM planet r,player p "
|
||||
. "WHERE (p.quit IS NULL OR UNIX_TIMESTAMP(NOW())-p.quit<86400) AND NOT p.hidden"
|
||||
. " AND r.owner=p.id");
|
||||
$plPlanets = array();
|
||||
while ($r = dbFetchArray($q)) {
|
||||
if (!is_array($plPlanets[$r[0]])) {
|
||||
$plPlanets[$r[0]] = array();
|
||||
}
|
||||
array_push($plPlanets[$r[0]], array(
|
||||
"planet" => $r[1],
|
||||
"name" => $r[2],
|
||||
"pop" => $r[3],
|
||||
"max_pop" => $r[4],
|
||||
"ifact" => $r[5],
|
||||
"mfact" => $r[6],
|
||||
"turrets" => $r[7],
|
||||
"happiness" => $r[8],
|
||||
"beacon" => $r[9],
|
||||
"abandon" => $r[10],
|
||||
"corruption" => $r[11]
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
// Update the warehouse
|
||||
foreach ($players as $name => $data) {
|
||||
$pid = $data['player'];
|
||||
if (is_null($pid)) {
|
||||
l::warn("****** BUG: null player ID in the warehouse update loop");
|
||||
continue;
|
||||
}
|
||||
foreach ($data as $k => $v) {
|
||||
$data[$k] = "'" . addslashes($v) . "'";
|
||||
}
|
||||
if (is_null( $data['tech_list'] )) {
|
||||
$data['tech_list'] = "''";
|
||||
}
|
||||
|
||||
$qs = "INSERT INTO warehouse(" . join(',', array_keys($data))
|
||||
. ") VALUES (" . join(',', array_values($data)) . ")";
|
||||
$this->db->query($qs);
|
||||
|
||||
$q = $this->db->query("SELECT id FROM warehouse WHERE tick_at={$this->at} AND player=$pid");
|
||||
list($id) = dbFetchArray($q);
|
||||
if (!$id || is_null($plPlanets[$pid])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($plPlanets[$pid] as $pdata) {
|
||||
$pdata['id'] = $id;
|
||||
|
||||
foreach ($pdata as $k => $v) {
|
||||
$pdata[$k] = "'" . addslashes($v == '' ? '0' : $v) . "'";
|
||||
}
|
||||
|
||||
$qs = "INSERT INTO wh_planet(" . join(',', array_keys($pdata))
|
||||
. ") VALUES (" . join(',', array_values($pdata)) . ")";
|
||||
$this->db->query($qs);
|
||||
}
|
||||
}
|
||||
$this->db->query("DELETE FROM warehouse WHERE UNIX_TIMESTAMP(NOW())-tick_at>86400*60");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
911
scripts/game/beta5/ticks/hour/library.inc
Normal file
911
scripts/game/beta5/ticks/hour/library.inc
Normal file
|
@ -0,0 +1,911 @@
|
|||
<?php
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// "Hour tick": owner change, production, stuck fleets, HS stand-by,
|
||||
// revolts, wormholes, sales
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
class beta5_ticks_hour_library {
|
||||
|
||||
var $idrInc = array();
|
||||
var $oChange = array();
|
||||
|
||||
public function __construct($lib) {
|
||||
$this->lib = $lib;
|
||||
$this->game = $this->lib->game;
|
||||
$this->db = $this->game->db;
|
||||
$this->main = $this->game->getLib();
|
||||
$this->bq = $this->game->getLib('beta5/bq');
|
||||
$this->fleets = $this->game->getLib('beta5/fleet');
|
||||
$this->msg = $this->game->getLib('beta5/msg');
|
||||
$this->planets = $this->game->getLib('beta5/planet');
|
||||
$this->players = $this->game->getLib('beta5/player');
|
||||
$this->rankings = $this->game->getLib('main/rankings');
|
||||
$this->rules = $this->game->getLib('beta5/rules');
|
||||
$this->sales = $this->game->getLib('beta5/sale');
|
||||
$this->standby = $this->game->getLib('beta5/standby');
|
||||
}
|
||||
|
||||
|
||||
public function runTick() {
|
||||
// Planetary events
|
||||
l::debug("Handling planetary events");
|
||||
$handledSystems = 0;
|
||||
do {
|
||||
$increase = $this->db->safeTransaction(
|
||||
array($this, 'handleSystemGroup'), $handledSystems
|
||||
);
|
||||
$handledSystems += $increase;
|
||||
} while ($increase > 0);
|
||||
|
||||
// Abandon planets
|
||||
$this->db->safeTransaction(array($this, "handleAbandon"));
|
||||
|
||||
// Stuck fleets
|
||||
$this->db->safeTransaction(array($this, 'unstickFleets'));
|
||||
|
||||
// Fleets waiting in hyperspace
|
||||
$this->db->safeTransaction(array($this, 'hyperspaceStandby'));
|
||||
|
||||
// Fleet sales
|
||||
$this->db->safeTransaction(array($this, 'fleetSales'));
|
||||
|
||||
// Update happiness
|
||||
$this->db->safeTransaction(array($this, 'updateHappiness'));
|
||||
|
||||
// Increase inflicted damage points for WHSN'd fleets
|
||||
if (count($this->idrInc)) {
|
||||
$this->db->safeTransaction(array($this, 'updateIDR'));
|
||||
}
|
||||
|
||||
// Check victory status on CTF games
|
||||
if ($this->game->params['victory'] == 2) {
|
||||
$this->db->safeTransaction(array($this, 'updateCTF'));
|
||||
}
|
||||
|
||||
// Update rankings
|
||||
$this->db->safeTransaction(array($this->main, 'call'), 'updateRankings');
|
||||
}
|
||||
|
||||
|
||||
public function handleSystemGroup($startAt) {
|
||||
$q = $this->db->query("SELECT id,nebula FROM system ORDER BY id ASC LIMIT 5 OFFSET $startAt");
|
||||
$n = dbCount($q);
|
||||
while ($r = dbFetchArray($q)) {
|
||||
$this->handleSystem($r[0], $r[1]);
|
||||
}
|
||||
return $n;
|
||||
}
|
||||
|
||||
public function unstickFleets() {
|
||||
l::debug("Unsticking fleets");
|
||||
$this->db->query("UPDATE fleet SET can_move = 'Y' WHERE can_move = 'H'");
|
||||
}
|
||||
|
||||
public function hyperspaceStandby() {
|
||||
$q = $this->db->query("SELECT id,owner,waiting FROM fleet WHERE waiting IS NOT NULL");
|
||||
$fWait = array();
|
||||
while ($r = dbFetchArray($q)) {
|
||||
$fWait[$r[2]] = array($r[0],$r[1]);
|
||||
}
|
||||
if (!count($fWait)) {
|
||||
return;
|
||||
}
|
||||
|
||||
l::debug("Handling hyperspace stand-by");
|
||||
$q = $this->db->query(
|
||||
"SELECT * FROM hs_wait WHERE id IN (" . join(',', array_keys($fWait)) . ")"
|
||||
);
|
||||
while ($r = dbFetchHash($q)) {
|
||||
$r['fleet'] = $fWait[$r['id']][0];
|
||||
$r['player'] = $fWait[$r['id']][1];
|
||||
$fWait[$r['id']] = $r;
|
||||
}
|
||||
|
||||
$losses = array();
|
||||
$planets = array();
|
||||
foreach ($fWait as $fw) {
|
||||
if ($this->handleWait($fw, &$losses)) {
|
||||
array_push($planets, $fw['drop_point']);
|
||||
}
|
||||
}
|
||||
foreach ($planets as $planetID) {
|
||||
$this->planets->call('detectFleets', $planetID);
|
||||
}
|
||||
|
||||
$tm = time();
|
||||
foreach ($losses as $pid => $locs) {
|
||||
foreach ($locs as $plid => $fl) {
|
||||
$pinf = $this->planets->call('byId', $plid);
|
||||
|
||||
$hsLosses = array();
|
||||
foreach ($fl as $f) {
|
||||
array_push($hsLosses, array(
|
||||
"p_id" => $plid,
|
||||
"p_name" => $pinf['name'],
|
||||
"f_name" => $f[0],
|
||||
"gaships" => $f[1],
|
||||
"fighters" => $f[2],
|
||||
"cruisers" => $f[3],
|
||||
"bcruisers" => $f[4],
|
||||
"power" => $f[5]
|
||||
));
|
||||
}
|
||||
$this->msg->call('send', $pid, 'hsloss', $hsLosses);
|
||||
}
|
||||
}
|
||||
|
||||
$this->fleets->call('sendMoveMessages');
|
||||
}
|
||||
|
||||
|
||||
public function fleetSales() {
|
||||
$q = $this->db->query("SELECT id FROM fleet WHERE sale IS NOT NULL");
|
||||
if (! dbCount($q)) {
|
||||
return;
|
||||
}
|
||||
|
||||
l::debug("Handling fleet sales");
|
||||
while ($r = dbFetchArray($q)) {
|
||||
$f = $this->fleets->call('get', $r[0]);
|
||||
l::trace("FSALE: found fleet {$r[0]}");
|
||||
if (!is_null($f['sale_info']['sale']['planet'])) {
|
||||
l::trace("FSALE({$r[0]}): fleet is bundled with a planet, skipping");
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($f['sale'] > 0) {
|
||||
l::debug("FSALE({$f['id']}): fleet isn't ready yet ({$f['sale']}h remaining)");
|
||||
$this->db->query("UPDATE fleet SET sale=sale-1 WHERE id={$f['id']}");
|
||||
continue;
|
||||
}
|
||||
|
||||
$q2 = $this->db->query(
|
||||
"SELECT id,sold_to FROM sale WHERE player={$f['owner']} AND fleet={$f['id']}"
|
||||
. " AND finalized IS NOT NULL ORDER BY finalized DESC LIMIT 1"
|
||||
);
|
||||
list($oid,$to) = dbFetchArray($q2);
|
||||
l::trace("FSALE({$f['id']}): offer #$oid, buyer #$to");
|
||||
|
||||
// Read data required to send the messages
|
||||
$fps = $this->fleets->call('getPower', $f['owner'], $f['gaships'], $f['fighters'],
|
||||
$f['cruisers'], $f['bcruisers']);
|
||||
$fpb = $this->fleets->call('getPower', $to, $f['gaships'], $f['fighters'], $f['cruisers'],
|
||||
$f['bcruisers']);
|
||||
l::trace("FSALE({$f['id']}): fps= $fps, fpb= $fpb");
|
||||
|
||||
// Send messages
|
||||
$this->msg->call('send', $f['owner'], 'sale', array(
|
||||
'f_name' => $f['name'],
|
||||
'f_power' => $fps,
|
||||
'pl_id' => $to,
|
||||
'pl_name' => $this->players->call('getName', $to),
|
||||
'is_sale' => 'TRUE'
|
||||
));
|
||||
$this->msg->call('send', $to, 'sale', array(
|
||||
'f_name' => $f['name'],
|
||||
'f_power' => $fpb,
|
||||
'pl_id' => $f['owner'],
|
||||
'pl_name' => $this->players->call('getName', $f['owner']),
|
||||
'is_sale' => 'FALSE'
|
||||
));
|
||||
l::trace("FSALE({$f['id']}): messages sent");
|
||||
|
||||
// Transfer control
|
||||
$this->db->query("UPDATE fleet SET sale=NULL,owner=$to WHERE id={$f['id']}");
|
||||
$this->fleets->call('invCache', $f['id']);
|
||||
// FIXME: add history
|
||||
$this->db->query("DELETE FROM sale WHERE id=$oid");
|
||||
l::debug("FSALE({$f['id']}): control transfered");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function updateIDR() {
|
||||
l::debug("Updating IDR");
|
||||
$rt = $this->rankings->call('getType', 'p_idr');
|
||||
$rl = $this->rankings->call('getAll', $rt);
|
||||
$idr = array();
|
||||
foreach ($rl as $r) {
|
||||
$idr[$r['id']] = $r['points'];
|
||||
}
|
||||
foreach ($this->idrInc as $n => $inc) {
|
||||
$idr[$n] += $inc;
|
||||
}
|
||||
$idrR = array();
|
||||
foreach ($idr as $n => $p) {
|
||||
if (!is_array($idrR[$p])) {
|
||||
$idrR[$p] = array();
|
||||
}
|
||||
array_push($idrR[$p], $n);
|
||||
}
|
||||
$this->rankings->call('update', $rt, $idrR);
|
||||
}
|
||||
|
||||
public function updateCTF() {
|
||||
if (! $this->game->getLib()->call('isFinished')) {
|
||||
$this->game->getLib('beta5/ctf')->call('checkTargets');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function updateHappiness() {
|
||||
l::debug("Updating planetary happiness");
|
||||
|
||||
$q = $this->db->query("SELECT id,owner FROM planet WHERE status=0");
|
||||
$destroy = array();
|
||||
while ($r = dbFetchArray($q)) {
|
||||
$nHap = $this->planets->call('updateHappiness', $r[0]);
|
||||
|
||||
// Handle revolts
|
||||
if ($nHap < 20 && !in_array($r[0], $this->oChange)) {
|
||||
if (!is_null($r[1]) && is_null($destroy[$r[1]])) {
|
||||
$destroy[$r[1]] = array();
|
||||
}
|
||||
$pDestr = $this->planetRevolt($r[0], $nHap);
|
||||
if (!is_null($r[1])) {
|
||||
array_push($destroy[$r[1]], $pDestr);
|
||||
}
|
||||
$this->planets->call('updateHappiness', $r[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// Send damage reports for revolts
|
||||
$tm = time() + 1;
|
||||
foreach ($destroy as $player => $plist) {
|
||||
$report = array();
|
||||
foreach ($plist as $data) {
|
||||
array_push($report, array(
|
||||
"planet" => $data[0],
|
||||
"pname" => $data[1],
|
||||
"ifact" => $data[2],
|
||||
"mfact" => $data[3],
|
||||
"turrets" => $data[4]
|
||||
));
|
||||
}
|
||||
$this->msg->call('send', $player, 'revdmg', $report);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private function buildFleets($plId, $ownId, $g, $f, $c, $b) {
|
||||
if ($g + $f + $c + $b == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$q = $this->db->query("SELECT id FROM fleet WHERE can_move='Y' AND LOWER(name)='no name' AND location=$plId AND owner=$ownId AND sale IS NULL LIMIT 1");
|
||||
if (dbCount($q)) {
|
||||
list($id) = dbFetchArray($q);
|
||||
$this->db->query("UPDATE fleet SET gaships=gaships+$g,fighters=fighters+$f,cruisers=cruisers+$c,bcruisers=bcruisers+$b WHERE id=$id");
|
||||
} else {
|
||||
$qs = "INSERT INTO fleet(owner,location,gaships,fighters,cruisers,bcruisers)VALUES($ownId,$plId,$g,$f,$c,$b)";
|
||||
$this->db->query($qs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function planetBuildQueue($planet, $rules) {
|
||||
static $types = array('turret', 'gaship', 'fighter', 'cruiser', 'bcruiser');
|
||||
|
||||
$units = $rules['mf_productivity'] * $rules['mf_productivity_factor'] * $planet['mfact'];
|
||||
$cl = $planet['corruption'] / 32000;
|
||||
if ($cl > .1) {
|
||||
$units = $units * (1.1 - $cl);
|
||||
}
|
||||
|
||||
$vac = $this->players->call('isOnVacation', $planet['owner']);
|
||||
if ($vac) {
|
||||
$units = $units / 4;
|
||||
}
|
||||
|
||||
$prot = $this->players->call('getProtectionLevel', $planet['owner']);
|
||||
if ($prot) {
|
||||
$units = $units * 1.15;
|
||||
}
|
||||
|
||||
$units = round($units);
|
||||
|
||||
$bq = $this->bq->call('get', $planet['id']);
|
||||
$prod = array(0, 0, 0, 0, 0);
|
||||
$move = 0;
|
||||
while (count($bq) && $units > 0) {
|
||||
if ($bq[0]['units'] <= $units) {
|
||||
$units -= $bq[0]['units'];
|
||||
$prod[$bq[0]['type']] += $bq[0]['quantity'];
|
||||
$this->db->query("DELETE FROM buildqueue WHERE planet=".$planet['id']." AND bq_order=$move");
|
||||
$move ++;
|
||||
array_shift($bq);
|
||||
} else {
|
||||
$units += $bq[0]['workunits'];
|
||||
$wuCost = $rules['workunits_'.$types[$bq[0]['type']]];
|
||||
$mod = $units % $wuCost;
|
||||
$nBuild = ($units - $mod) / $wuCost;
|
||||
$prod[$bq[0]['type']] += $nBuild;
|
||||
$nQt = $bq[0]['quantity'] - $nBuild;
|
||||
$this->db->query("UPDATE buildqueue SET quantity=$nQt,workunits=$mod WHERE planet=".$planet['id']." AND bq_order=$move");
|
||||
$units = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ($move) {
|
||||
$this->bq->call('reorder', $planet['id']);
|
||||
}
|
||||
|
||||
if ($prod[0] > 0) {
|
||||
$this->db->query("UPDATE planet SET turrets=turrets+".$prod[0]." WHERE id=".$planet['id']);
|
||||
$tm = time();
|
||||
$this->db->query("DELETE FROM turhist WHERE $tm-moment>86400");
|
||||
$this->db->query("INSERT INTO turhist VALUES({$planet['id']},$tm,$prod[0])");
|
||||
}
|
||||
|
||||
$this->buildFleets($planet['id'], $planet['owner'], $prod[1], $prod[2], $prod[3], $prod[4]);
|
||||
$this->planets->call('updateMilStatus', $planet['id']);
|
||||
}
|
||||
|
||||
private function planetSale(&$planet) {
|
||||
l::trace("SALE: handling planet {$planet['id']}");
|
||||
if ($planet['sale'] > 0) {
|
||||
l::debug("SALE({$planet['id']}): not ready for sale yet ({$planet['sale']}h remaining)");
|
||||
$this->db->query("UPDATE planet SET sale=sale-1 WHERE id=".$planet['id']);
|
||||
$q = $this->db->query(
|
||||
"SELECT fleet FROM sale WHERE player=".$planet['owner']." AND planet=".$planet['id']
|
||||
. " AND finalized IS NOT NULL ORDER BY finalized DESC LIMIT 1"
|
||||
);
|
||||
list($fleet) = dbFetchArray($q);
|
||||
if (!is_null($fleet)) {
|
||||
l::trace("SALE({$planet['id']}): fleet $fleet bundled");
|
||||
$this->db->query("UPDATE fleet SET sale=sale-1 WHERE id=$fleet");
|
||||
}
|
||||
} else {
|
||||
l::trace("SALE({$planet['id']}): running sale code");
|
||||
$q = $this->db->query(
|
||||
"SELECT id,sold_to,fleet FROM sale WHERE player=".$planet['owner']." AND planet=".$planet['id']
|
||||
. " AND finalized IS NOT NULL ORDER BY finalized DESC LIMIT 1"
|
||||
);
|
||||
if (!dbCount($q)) {
|
||||
l::warn("***** BUG: planet {$planet['id']} has sale field set to 0, but no "
|
||||
. "sales were found");
|
||||
$this->db->query("UPDATE planet SET sale=NULL WHERE id={$planet['id']}");
|
||||
return;
|
||||
}
|
||||
list($oid,$to,$fleet) = dbFetchArray($q);
|
||||
l::trace("SALE({$planet['id']}): offer #$oid, sold to player #$to (bundled fleet: "
|
||||
. (is_null($fleet) ? "none" : "#$fleet") . ")");
|
||||
|
||||
// Read data required to send the messages
|
||||
$tn = addslashes($this->players->call('getName', $to));
|
||||
$fn = addslashes($this->players->call('getName', $planet['owner']));
|
||||
l::trace("SALE({$planet['id']}): original owner '$tn', new owner '$fn'");
|
||||
if (is_null($fleet)) {
|
||||
$fqs = $fqb = "NULL,NULL";
|
||||
} else {
|
||||
$q = $this->db->query("SELECT * FROM fleet WHERE id=$fleet");
|
||||
$fd = dbFetchHash($q);
|
||||
$fps = $this->fleets->call('getPower', $fd['owner'], $fd['gaships'], $fd['fighters'], $fd['cruisers'], $fd['bcruisers']);
|
||||
$fpb = $this->fleets->call('getPower', $to, $fd['gaships'], $fd['fighters'], $fd['cruisers'], $fd['bcruisers']);
|
||||
$fqs = "'" . addslashes($fd['name']) . "',$fps";
|
||||
$fqb = "'" . addslashes($fd['name']) . "',$fpb";
|
||||
}
|
||||
l::trace("SALE({$planet['id']}): fqs: $fqs");
|
||||
l::trace("SALE({$planet['id']}): fqb: $fqb");
|
||||
|
||||
// Send messages
|
||||
// FIXME: message API
|
||||
$tm = time();
|
||||
$this->db->query("INSERT INTO message(player,sent_on,mtype,ftype,is_new) VALUES({$planet['owner']},$tm,'sale','INT',TRUE)");
|
||||
$q = $this->db->query("SELECT id FROM message WHERE player={$planet['owner']} AND sent_on=$tm AND mtype='sale' ORDER BY id DESC LIMIT 1");
|
||||
list($mid) = dbFetchArray($q);
|
||||
$this->db->query("INSERT INTO msg_sale VALUES($mid,{$planet['id']},'".addslashes($planet['name'])."',$fqs,$to,'$tn',TRUE)");
|
||||
$this->db->query("INSERT INTO message(player,sent_on,mtype,ftype,is_new) VALUES($to,$tm,'sale','INT',TRUE)");
|
||||
$q = $this->db->query("SELECT id FROM message WHERE player=$to AND sent_on=$tm AND mtype='sale' ORDER BY id DESC LIMIT 1");
|
||||
list($mid) = dbFetchArray($q);
|
||||
$this->db->query("INSERT INTO msg_sale VALUES($mid,{$planet['id']},'".addslashes($planet['name'])."',$fqb,{$planet['owner']},'$fn',FALSE)");
|
||||
l::trace("SALE({$planet['id']}): messages sent");
|
||||
|
||||
// Check for vacation mode
|
||||
$vac = $this->players->call('isOnVacation', $to);
|
||||
if ($vac) {
|
||||
$q = $this->db->query("SELECT COUNT(*) FROM fleet WHERE location={$planet['id']} AND attacking");
|
||||
list($c) = dbFetchArray();
|
||||
if ($c) {
|
||||
$vm = 'PEND';
|
||||
} else {
|
||||
$vm = 'YES';
|
||||
}
|
||||
} else {
|
||||
$vm = 'NO';
|
||||
}
|
||||
l::trace("SALE({$planet['id']}): vacation mode for target player: $vm");
|
||||
|
||||
// Sell the planet
|
||||
$this->players->call('losePlanet', $planet['owner'], $planet['id']);
|
||||
$this->players->call('takePlanet', $to, $planet['id']);
|
||||
$nVal = $this->planets->call('ownerChange', $planet['id'], $to, $vm);
|
||||
if ($nVal > 0) {
|
||||
$planet['max_pop'] = $nVal;
|
||||
}
|
||||
$this->db->query("UPDATE player SET bh_unhappiness=bh_unhappiness+1 WHERE id={$planet['owner']} AND bh_unhappiness<15");
|
||||
if (!is_null($fleet)) {
|
||||
$this->db->query("UPDATE fleet SET sale=NULL,owner=$to WHERE id=$fleet");
|
||||
}
|
||||
$planet['owner'] = $to;
|
||||
// FIXME: add history
|
||||
$this->db->query("DELETE FROM sale WHERE id=$oid");
|
||||
|
||||
l::debug("SALE({$planet['id']}) completed");
|
||||
}
|
||||
}
|
||||
|
||||
private function whsnPreparation(&$planet) {
|
||||
if ($planet['bh_prep'] > 0) {
|
||||
// WHSN is not ready yet
|
||||
$this->db->query("UPDATE planet SET bh_prep=bh_prep-1 WHERE id=".$planet['id']);
|
||||
$this->db->query("UPDATE player SET bh_unhappiness=bh_unhappiness+1 WHERE id={$planet['owner']} AND bh_unhappiness<15");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get fleet statistics to send messages
|
||||
$players = array(
|
||||
$planet['owner'] => array(
|
||||
"was_owner" => dbBool(true),
|
||||
"attacking" => false,
|
||||
"power" => 0,
|
||||
"fleets" => array(),
|
||||
)
|
||||
);
|
||||
$q = $this->db->query("SELECT * FROM fleet WHERE location=".$planet['id']);
|
||||
$aPower = $dPower = 0;
|
||||
while ($r = dbFetchHash($q)) {
|
||||
if (is_null($players[$r['owner']])) {
|
||||
$players[$r['owner']] = array(
|
||||
"was_owner" => dbBool(false),
|
||||
"attacking" => ($r['attacking'] == 't'),
|
||||
"power" => 0,
|
||||
"fleets" => array(),
|
||||
);
|
||||
}
|
||||
$f = array(
|
||||
"name" => $r['name'],
|
||||
"gaships" => $r['gaships'],
|
||||
"fighters" => $r['fighters'],
|
||||
"cruisers" => $r['cruisers'],
|
||||
"bcruisers" => $r['bcruisers'],
|
||||
);
|
||||
$power = $this->fleets->call('getPower', $r['owner'], $r['gaships'], $r['fighters'], $r['cruisers'], $r['bcruisers']);
|
||||
$players[$r['owner']]["power"] += ($f['power'] = $power);
|
||||
array_push($players[$r['owner']]['fleets'], $f);
|
||||
if ($players[$r['owner']]['attacking']) {
|
||||
$aPower += $power;
|
||||
} else {
|
||||
$dPower += $power;
|
||||
}
|
||||
|
||||
// Cancel fleet sales
|
||||
$qfs = $this->db->query("SELECT id,player,finalized FROM sale WHERE fleet={$r['id']}");
|
||||
if (dbCount($qfs)) {
|
||||
list($saleId, $seller, $saleFin) = dbFetchArray($qfs);
|
||||
if (is_null($saleFin)) {
|
||||
$ga = "cancel";
|
||||
} else {
|
||||
$ga = "cancelTransfer";
|
||||
}
|
||||
$this->sales->call($ga, $seller, $saleId);
|
||||
}
|
||||
}
|
||||
|
||||
// Send the messages
|
||||
// FIXME: message API
|
||||
$tm = time();
|
||||
foreach ($players as $pId => $data) {
|
||||
$this->db->query("INSERT INTO message(player,sent_on,mtype,ftype,is_new) VALUES($pId,$tm,'whsn','INT',TRUE)");
|
||||
$q = $this->db->query("SELECT id FROM message WHERE player=$pId AND sent_on=$tm AND mtype='whsn' ORDER BY id DESC LIMIT 1");
|
||||
list($mid) = dbFetchArray($q);
|
||||
|
||||
if ($data['attacking']) {
|
||||
$pow = $aPower - $data['power'];
|
||||
$fPower = $pow; $ePower = $dPower;
|
||||
} else {
|
||||
$pow = $dPower - $data['power'];
|
||||
$fPower = $pow; $ePower = $aPower;
|
||||
}
|
||||
|
||||
$this->db->query("INSERT INTO msg_whsn VALUES($mid,{$planet['id']},'"
|
||||
. addslashes($planet['name']) . "'," . $data['was_owner']
|
||||
. ",$fPower,$ePower)");
|
||||
foreach ($data['fleets'] as $f)
|
||||
$this->db->query("INSERT INTO whsn_fleet VALUES($mid,'" . addslashes($f['name'])
|
||||
. "',{$f['gaships']},{$f['fighters']},{$f['cruisers']},"
|
||||
. "{$f['bcruisers']},{$f['power']})");
|
||||
}
|
||||
|
||||
// Check for IDR points
|
||||
$pow = $aPower - $dPower;
|
||||
if ($pow > 0) {
|
||||
$pn = $this->players->call('getName', $planet['owner']);
|
||||
if (is_null($this->idrInc[$pn])) {
|
||||
$this->idrInc[$pn] = $pow;
|
||||
} else {
|
||||
$this->idrInc[$pn] += $pow;
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy the planet and anything around it
|
||||
$this->players->call('losePlanet', $planet['owner'], $planet['id']);
|
||||
$this->bq->call('flush', $planet['id']);
|
||||
$this->db->query("DELETE FROM fleet WHERE location=".$planet['id']);
|
||||
do {
|
||||
$rn = strtoupper(substr(md5(uniqid(rand())), 0, 10));
|
||||
$q = $this->db->query("SELECT id FROM planet WHERE name='PR-[$rn]'");
|
||||
} while(dbCount($q));
|
||||
$this->db->query(
|
||||
"UPDATE planet "
|
||||
. "SET pop = 0, max_pop = 0, happiness = 0, mfact = 0, ifact = 0, beacon = 0, "
|
||||
. "built_probe = FALSE, probe_policy = NULL, bh_prep = NULL, owner = NULL, "
|
||||
. "sale = NULL, status = 1, bh_unhappiness = 0, vacation = 'NO', "
|
||||
. "name = 'PR-[$rn]', abandon = NULL "
|
||||
. "WHERE id = {$planet['id']}"
|
||||
);
|
||||
$this->db->query(
|
||||
"UPDATE planet "
|
||||
. "SET bh_unhappiness = bh_unhappiness + 4 "
|
||||
. "WHERE system={$planet['system']} AND id <> {$planet['id']} "
|
||||
. "AND status = 0 AND bh_unhappiness < 12"
|
||||
);
|
||||
$this->db->query("DELETE FROM planet_abandon_time WHERE id = {$planet['id']}");
|
||||
|
||||
// Raise the empire-wide unhappiness for the planet's owner
|
||||
$q = $this->db->query("SELECT bh_unhappiness FROM player WHERE id={$planet['owner']}");
|
||||
list($bhu) = dbFetchArray($q);
|
||||
$nuh = max($bhu + 4, 15);
|
||||
$this->db->query("UPDATE player SET bh_unhappiness=$nuh WHERE id={$planet['owner']}");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private function planetTaken(&$planet) {
|
||||
if ($planet['turrets'] > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the planet was in vacation mode before the attacking ships arrived
|
||||
// If it was, it can't be taken
|
||||
if ($planet['vacation'] == 'YES ') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// List fleets at location
|
||||
$q = $this->db->query("SELECT owner,gaships,attacking,time_spent FROM fleet WHERE location={$planet['id']}");
|
||||
$players = array();
|
||||
while ($r = dbFetchArray($q)) {
|
||||
// If there are defending fleets, forget it
|
||||
if ($r[2] == 'f') {
|
||||
if ($r[3] > 5) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
} elseif ($r[3] < 15) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Count GA Ships per player
|
||||
$players[$r[0]] += $r[1];
|
||||
}
|
||||
|
||||
// Get the highest GA efficiency
|
||||
$maxGAPower = $maxGAPlayer = -1;
|
||||
foreach ($players as $id => $gas) {
|
||||
$rules = $this->rules->call('get', $id);
|
||||
$gaPower = $gas * $rules['gaship_pop'];
|
||||
if ($gaPower > $maxGAPower) {
|
||||
$maxGAPower = $gaPower;
|
||||
$maxGAPlayer = $id;
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether the player can actually take the planet
|
||||
if ($maxGAPlayer == -1 || $maxGAPower < $planet['pop']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// A player has taken control on the planet
|
||||
if (!is_null($planet['owner'])) {
|
||||
// If the planet had an owner, flush build queue and cancel sales
|
||||
$this->bq->call('flush', $planet['id']);
|
||||
$q = $this->db->query("SELECT id,finalized,sold_to FROM sale WHERE planet={$planet['id']}");
|
||||
if (dbCount($q)) {
|
||||
// Cancel sale
|
||||
list($sId,$fin,$to) = dbFetchArray($q);
|
||||
if (is_null($fin)) {
|
||||
$ga = 'cancel';
|
||||
} else {
|
||||
$ga = 'cancelTransfer';
|
||||
|
||||
// Send message
|
||||
// FIXME ...
|
||||
$tm = time();
|
||||
$this->db->query("INSERT INTO message(player,sent_on,mtype,ftype,is_new) VALUES($to,$tm,'plsc','INT',TRUE)");
|
||||
$q = $this->db->query("SELECT id FROM message WHERE player=$to AND sent_on=$tm AND mtype='plsc' ORDER BY id DESC LIMIT 1");
|
||||
list($mid) = dbFetchArray($q);
|
||||
$this->db->query("INSERT INTO msg_plsc VALUES($mid,{$planet['owner']},$maxGAPlayer,{$planet['id']},'"
|
||||
. addslashes($planet['name']) . "')");
|
||||
}
|
||||
$this->sales->call($ga, $planet['owner'], $sId);
|
||||
}
|
||||
|
||||
$rqs = ",renamed=".time();
|
||||
} else {
|
||||
$rqs = "";
|
||||
}
|
||||
|
||||
// Check for vacation mode
|
||||
$vm = $this->players->call('isOnVacation', $maxGAPlayer) ? 'YES' : 'NO';
|
||||
|
||||
// Transfer control
|
||||
$this->players->call('losePlanet', $planet['owner'], $planet['id']);
|
||||
$this->players->call('takePlanet', $maxGAPlayer, $planet['id']);
|
||||
$nVal = $this->planets->call('ownerChange', $planet['id'], $maxGAPlayer, $vm);
|
||||
if ($nVal > 0) {
|
||||
$planet['max_pop'] = $nVal;
|
||||
}
|
||||
|
||||
// Update a potential abandon log entry
|
||||
$tm = time();
|
||||
$this->db->query("UPDATE abandon_log SET retake_owner=$maxGAPlayer,retake_time=$tm WHERE planet={$planet['id']} AND retake_time IS NULL");
|
||||
|
||||
// Get the list of the new owner's enemies
|
||||
$q = $this->db->query("SELECT enemy FROM enemy_player WHERE player=$maxGAPlayer");
|
||||
$enemies = array();
|
||||
while ($r = dbFetchArray($q)) {
|
||||
array_push($enemies, $r[0]);
|
||||
}
|
||||
$q = $this->db->query("SELECT p.id FROM player p,enemy_alliance e WHERE p.alliance=e.alliance AND p.a_status='IN' AND e.player=$maxGAPlayer");
|
||||
while ($r = dbFetchArray($q)) {
|
||||
array_push($enemies, $r[0]);
|
||||
}
|
||||
$enemies = array_unique($enemies);
|
||||
|
||||
// Switch attacking fleets to defense unless they belong to an enemy
|
||||
$qs = "UPDATE fleet SET attacking=FALSE,can_move='Y' WHERE location={$planet['id']}";
|
||||
if (count($enemies)) {
|
||||
$qs .= " AND owner NOT IN (".join(',',$enemies).")";
|
||||
}
|
||||
$this->db->query($qs);
|
||||
|
||||
// Send messages to the former owner and the new owner
|
||||
$pn = addslashes($planet['name']);
|
||||
$noMsg = array($maxGAPlayer);
|
||||
$mData = array(
|
||||
'p_id' => $planet['id'],
|
||||
'p_name' => $planet['name'],
|
||||
'owner' => $planet['owner'],
|
||||
'status' => 'TAKE'
|
||||
);
|
||||
$this->msg->call('send', $maxGAPlayer, 'ownerch', $mData);
|
||||
|
||||
$mData['owner'] = $maxGAPlayer;
|
||||
if (!is_null($planet['owner'])) {
|
||||
$mData['status'] = 'LOSE';
|
||||
array_push($noMsg, $pid = $planet['owner']);
|
||||
$this->msg->call('send', $pid, 'ownerch', $mData);
|
||||
}
|
||||
|
||||
// Get the list of other players and send them a message as well
|
||||
$q2 = $this->db->query("SELECT DISTINCT owner FROM fleet WHERE location={$planet['id']} AND owner NOT IN (" . join(',', $noMsg) . ")");
|
||||
$mData['status'] = 'VIEW';
|
||||
while ($r = dbFetchArray($q2)) {
|
||||
$this->msg->call('send', $r[0], 'ownerch', $mData);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private function handlePlanet($planet) {
|
||||
// WHSN preparation
|
||||
if (!is_null($planet['bh_prep']) && $this->whsnPreparation($planet)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for owner change
|
||||
if ($this->planetTaken($planet)) {
|
||||
$this->planets->call('updateMilStatus', $planet['id']);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Planet sale
|
||||
if (!is_null($planet['sale'])) {
|
||||
$this->planetSale($planet);
|
||||
}
|
||||
|
||||
// No build queues or revolts on neutral planets
|
||||
if (is_null($planet['owner'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load owner rules
|
||||
$rules = $this->rules->call('get', $planet['owner']);
|
||||
|
||||
// Build queue
|
||||
$this->planetBuildQueue($planet, $rules);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private function handleSystem($sid, $neb) {
|
||||
if ($neb) {
|
||||
return;
|
||||
}
|
||||
|
||||
l::trace("Handling system #$sid");
|
||||
$q = $this->db->query("SELECT * FROM planet WHERE system=$sid");
|
||||
while ($planet = dbFetchHash($q)) {
|
||||
if ($neb || $planet['status'] == 1) {
|
||||
continue;
|
||||
}
|
||||
if ($this->handlePlanet($planet)) {
|
||||
array_push($this->oChange, $planet['id']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function handleWait($fw, &$losses) {
|
||||
$canDestroy = $this->standby->call('canDestroy', $fw['drop_point'], $fw['player']);
|
||||
|
||||
// If we can destroy fleets, find out whether we must do so
|
||||
if ($canDestroy) {
|
||||
$prob = $this->standby->call('getLossProb', $fw['time_spent']);
|
||||
l::debug("HSSB({$fw['fleet']}): at planet #{$fw['drop_point']}, loss probability = "
|
||||
. "$prob (time spent: {$fw['time_spent']}h)");
|
||||
if (rand(1,100) <= $prob) {
|
||||
l::debug("HSSB({$fw['fleet']}): applying fleet losses");
|
||||
|
||||
// Destroy a part of the fleet
|
||||
$amount = rand(5,round(10+$prob/10));
|
||||
$fleet = $this->fleets->call('get', $fw['fleet']);
|
||||
$rules = $this->rules->call('get', $fw['player']);
|
||||
$fcLoss = ceil(($fleet['cruisers'] / 100) * $amount);
|
||||
$fbLoss = ceil(($fleet['bcruisers'] / 100) * $amount);
|
||||
l::trace("HSSB({$fw['fleet']}): cruisers lost: $fcLoss; battle cruisers lost: $fbLoss");
|
||||
|
||||
// Compute the amount of transported ships to be destroyed
|
||||
$gaSpace = $fleet['gaships'] * $rules['gaship_space'];
|
||||
$fSpace = $fleet['fighters'] * $rules['fighter_space'];
|
||||
$tSpace = $gaSpace + $fSpace;
|
||||
if ($tSpace > 0) {
|
||||
$haul = $fleet['cruisers'] * $rules['cruiser_haul']
|
||||
+ $fleet['bcruisers'] * $rules['bcruiser_haul'];
|
||||
$haulUsed = $tSpace / $haul;
|
||||
$lHaul = $fcLoss * $rules['cruiser_haul'] + $fbLoss * $rules['bcruiser_haul'];
|
||||
$lSpace = $haulUsed * $lHaul;
|
||||
$gaLSpace = ($lSpace / $tSpace) * $gaSpace;
|
||||
$fLSpace = ($lSpace / $tSpace) * $fSpace;
|
||||
$fgLoss = min($fleet['gaships'], ceil($gaLSpace / $rules['gaship_space']));
|
||||
$ffLoss = min($fleet['fighters'], ceil($fLSpace / $rules['fighter_space']));
|
||||
} else {
|
||||
$fgLoss = $ffLoss = 0;
|
||||
}
|
||||
l::trace("HSSB({$fw['fleet']}): fighters lost: $ffLoss; GA ships lost: $fgLoss");
|
||||
|
||||
// Add details to the $losses array
|
||||
if (!is_array($losses[$fleet['owner']])) {
|
||||
$losses[$fleet['owner']] = array();
|
||||
}
|
||||
if (!is_array($losses[$fleet['owner']][$fw['drop_point']])) {
|
||||
$losses[$fleet['owner']][$fw['drop_point']] = array();
|
||||
}
|
||||
array_push($losses[$fleet['owner']][$fw['drop_point']], array(
|
||||
addslashes($fleet['name']), $fgLoss, $ffLoss, $fcLoss, $fbLoss,
|
||||
$this->fleets->call('getPower', $fleet['owner'], $fgLoss, $ffLoss,
|
||||
$fcLoss, $fbLoss)
|
||||
));
|
||||
|
||||
if ($fcLoss == $fleet['cruisers'] && $fbLoss == $fleet['bcruisers']
|
||||
&& $ffLoss == $fleet['fighters'] && $fgLoss == $fleet['gaships']) {
|
||||
$this->fleets->call('disband',$fw['fleet'],true);
|
||||
l::trace("HSSB({$fw['fleet']}): fleet disbanded");
|
||||
} elseif ($fcLoss + $fbLoss + $ffLoss + $fgLoss > 0) {
|
||||
$this->db->query(
|
||||
"UPDATE fleet SET gaships = gaships - $fgLoss, "
|
||||
. "fighters = fighters - $ffLoss, "
|
||||
. "cruisers = cruisers - $fcLoss, "
|
||||
. "bcruisers = bcruisers - $fbLoss "
|
||||
. "WHERE id = {$fw['fleet']}"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($fw['time_left'] == 1) {
|
||||
// Fleet arrival
|
||||
$this->fleets->call('arrival', $fw['fleet'], $fw['drop_point'], $fw['origin']);
|
||||
// Destroy wait entry
|
||||
$this->db->query("DELETE FROM hs_wait WHERE id={$fw['id']}");
|
||||
} else {
|
||||
// Update wait entry
|
||||
$this->db->query(
|
||||
"UPDATE hs_wait SET time_left = time_left - 1, time_spent = time_spent + 1 "
|
||||
. "WHERE id={$fw['id']}"
|
||||
);
|
||||
}
|
||||
|
||||
return !($fw['time_left'] == 1);
|
||||
}
|
||||
|
||||
|
||||
private function planetRevolt($id, $hap) {
|
||||
$q = $this->db->query("SELECT name,ifact,mfact,turrets FROM planet WHERE id=$id");
|
||||
list($n, $if, $mf, $tr) = dbFetchArray($q);
|
||||
|
||||
$pdestr = 30 - $hap;
|
||||
$pdestr += rand(-floor($pdestr/2),floor($pdestr/2));
|
||||
$pdestr /= 150;
|
||||
$dInd = round($if * $pdestr);
|
||||
$dMil = round($mf * $pdestr);
|
||||
$dTur = round($tr * $pdestr);
|
||||
|
||||
if ($dInd + $dMil + $dTur != 0) {
|
||||
$this->db->query(
|
||||
"UPDATE planet SET ifact = ifact - $dInd, mfact = mfact - $dMil, "
|
||||
. "turrets = turrets - $dTur "
|
||||
. "WHERE id = $id"
|
||||
);
|
||||
}
|
||||
|
||||
return array($id, $n, $dInd, $dMil, $dTur);
|
||||
}
|
||||
|
||||
|
||||
public function handleAbandon() {
|
||||
l::debug("Handling planets being abandonned");
|
||||
|
||||
// Decrease time to abandon
|
||||
$this->db->query("UPDATE planet SET abandon = abandon - 1 WHERE abandon IS NOT NULL");
|
||||
|
||||
// Get the list of planets to abandon at this tick
|
||||
$q = $this->db->query("SELECT id, owner FROM planet WHERE abandon = 0");
|
||||
$oList = array();
|
||||
while ($r = dbFetchArray($q)) {
|
||||
if (is_null($r[1])) {
|
||||
l::warn("****** BUG: planet {$r[0]} is being abandoned and has no owner");
|
||||
continue;
|
||||
}
|
||||
$this->abandonPlanet($r[0], $r[1]);
|
||||
if (!is_array($oList[$r[1]])) {
|
||||
$oList[$r[1]] = array();
|
||||
}
|
||||
array_push($oList[$r[1]], $r[0]);
|
||||
}
|
||||
|
||||
foreach ($oList as $pid => $aPl) {
|
||||
// Send the message
|
||||
$message = array();
|
||||
foreach ($aPl as $plId) {
|
||||
$planet = $this->planets->call('byId', $plId);
|
||||
array_push($message, array("p_id" => $plId, "p_name" => $planet['name']));
|
||||
}
|
||||
$this->msg->call('send', $pid, 'abandon', $message);
|
||||
|
||||
// Update other planets' happiness
|
||||
$this->players->call('updateHappiness', $pid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function abandonPlanet($pid, $oid) {
|
||||
// Insert log entry
|
||||
$this->db->query(
|
||||
"INSERT INTO abandon_log(planet,abandon_time,former_owner) "
|
||||
. "VALUES ($pid," . time() . ",$oid)"
|
||||
);
|
||||
|
||||
// Make the planet neutral
|
||||
$this->planets->call('ownerChange', $pid);
|
||||
$this->players->call('losePlanet', $oid, $pid);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
121
scripts/game/beta5/ticks/move/library.inc
Normal file
121
scripts/game/beta5/ticks/move/library.inc
Normal file
|
@ -0,0 +1,121 @@
|
|||
<?php
|
||||
|
||||
//-------------------------------------
|
||||
// "Move tick": handles moving objects
|
||||
//-------------------------------------
|
||||
|
||||
class beta5_ticks_move_library {
|
||||
|
||||
private $arrivals = array();
|
||||
|
||||
public function __construct($lib) {
|
||||
$this->lib = $lib;
|
||||
$this->db = $lib->game->db;
|
||||
$this->fleets = $lib->game->getLib('beta5/fleet');
|
||||
$this->planets = $lib->game->getLib('beta5/planet');
|
||||
}
|
||||
|
||||
|
||||
public function runTick() {
|
||||
// Increase time spent for fleets
|
||||
$this->db->safeTransaction(array($this, 'increaseTimeSpent'));
|
||||
|
||||
// Advance moving objects and get the list of arrivals
|
||||
$this->db->safeTransaction(array($this, 'advanceMovingObjects'));
|
||||
|
||||
// Fleet arrivals
|
||||
if (count($this->arrivals)) {
|
||||
$this->db->safeTransaction(array($this, 'fleetArrivals'));
|
||||
$this->db->safeTransaction(array($this, 'fleetArrivalUpdates'));
|
||||
}
|
||||
|
||||
// Remove completed trajectories
|
||||
$this->db->safeTransaction(array($this, 'deleteOldTrajectories'));
|
||||
}
|
||||
|
||||
|
||||
public function deleteOldTrajectories() {
|
||||
$this->db->query("DELETE FROM moving_object WHERE time_left = 0");
|
||||
}
|
||||
|
||||
|
||||
public function increaseTimeSpent() {
|
||||
// Increase time spent on planets for fleets that are not moving
|
||||
$this->db->query("UPDATE fleet SET time_spent = time_spent + 1 WHERE location IS NOT NULL");
|
||||
}
|
||||
|
||||
|
||||
public function advanceMovingObjects() {
|
||||
// Advances all moving objects that don't suffer a destination change penalty
|
||||
$this->db->query("UPDATE moving_object SET time_left = time_left - 1 WHERE changed=0 AND time_left > 0");
|
||||
|
||||
// Decreases penalty
|
||||
$this->db->query("UPDATE moving_object SET changed = 61 WHERE changed > 60");
|
||||
$this->db->query("UPDATE moving_object SET changed = changed - 1 WHERE changed > 0");
|
||||
|
||||
// Get all moving objects arriving at destination
|
||||
$q = $this->db->query("SELECT id, m_to, m_from, wait_order FROM moving_object WHERE time_left = 0");
|
||||
if (!dbCount($q)) {
|
||||
return;
|
||||
}
|
||||
$mobjs = array();
|
||||
while ($r = dbFetchArray($q)) {
|
||||
$mobjs[$r[0]] = array($r[1], $r[2], $r[3]);
|
||||
}
|
||||
|
||||
$this->arrivals = $mobjs;
|
||||
}
|
||||
|
||||
|
||||
function fleetArrivals() {
|
||||
// Find moving fleets
|
||||
$q = $this->db->query(
|
||||
"SELECT id, moving FROM fleet WHERE moving IN (" . join(',', array_keys($this->arrivals)) . ")"
|
||||
);
|
||||
$planets = array(); $plDetect = array();
|
||||
while ($r = dbFetchArray($q)) {
|
||||
list($fId,$mId) = $r;
|
||||
|
||||
// Does it have an HS stand-by order?
|
||||
if (!is_null($this->arrivals[$mId][2])) {
|
||||
$this->db->query(
|
||||
"UPDATE hs_wait SET origin={$this->arrivals[$mId][1]}, "
|
||||
. "drop_point={$this->arrivals[$mId][0]}"
|
||||
. " WHERE id={$this->arrivals[$mId][2]}");
|
||||
$this->db->query("UPDATE fleet SET moving=NULL,waiting="
|
||||
. $this->arrivals[$mId][2] . " WHERE id=$fId");
|
||||
|
||||
// Add the planet to the list of planets where detection is to be run
|
||||
if (!in_array($this->arrivals[$mId][0], $plDetect)) {
|
||||
array_push($plDetect, $this->arrivals[$mId][0]);
|
||||
}
|
||||
} else {
|
||||
// If there is no HS stand-by order, the fleet has arrived.
|
||||
$this->fleets->call('arrival', $fId, $this->arrivals[$mId][0], $this->arrivals[$mId][1]);
|
||||
|
||||
// Add the planet to the list of planets to be updated
|
||||
if (!in_array($this->arrivals[$mId][0], $planets)) {
|
||||
array_push($planets, $this->arrivals[$mId][0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->plDetect = $plDetect;
|
||||
$this->plUpdate = $planets;
|
||||
}
|
||||
|
||||
public function fleetArrivalUpdates() {
|
||||
// Update planet status
|
||||
foreach ($this->plDetect as $pid) {
|
||||
$this->planets->call('detectFleets', $pid);
|
||||
}
|
||||
foreach ($this->plUpdate as $pid) {
|
||||
$this->planets->call('updateHappiness', $pid);
|
||||
$this->planets->call('updateMilStatus', $pid);
|
||||
}
|
||||
$this->fleets->call('sendMoveMessages');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
48
scripts/game/beta5/ticks/punishment/library.inc
Normal file
48
scripts/game/beta5/ticks/punishment/library.inc
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// "Punishment tick": contains the code to reset planets if
|
||||
// they are not renamed in time.
|
||||
//-------------------------------------------------------------
|
||||
|
||||
|
||||
class beta5_ticks_punishment_library {
|
||||
|
||||
public function __construct($lib) {
|
||||
$this->lib = $lib;
|
||||
$this->db = $lib->game->db;
|
||||
$this->b5adm = $lib->game->getLib('admin/beta5');
|
||||
}
|
||||
|
||||
|
||||
public function runTick() {
|
||||
$this->db->safeTransaction(array($this, 'punish'));
|
||||
}
|
||||
|
||||
|
||||
public function punish() {
|
||||
// Neutralize planets with funky names
|
||||
$q = $this->db->query(
|
||||
"SELECT id, name FROM planet "
|
||||
. "WHERE mod_check AND force_rename IS NOT NULL "
|
||||
. "AND UNIX_TIMESTAMP(NOW())-force_rename >= 86400"
|
||||
);
|
||||
|
||||
while ($r = dbFetchArray($q)) {
|
||||
$q2 = $this->db->query(
|
||||
"SELECT moderator FROM msg_warnname "
|
||||
. "WHERE planet={$r[0]} AND event='WARN' "
|
||||
. "ORDER BY id DESC LIMIT 1"
|
||||
);
|
||||
list($mod) = dbFetchArray($q2);
|
||||
if (is_null($mod)) {
|
||||
l::error("****** BUG: moderator ID not found for planet {$r[0]}");
|
||||
continue;
|
||||
}
|
||||
l::notice("resetting planet '{$r[1]}' (id: $r[0]) due to funky name");
|
||||
$this->b5adm->call('resetPlanet', $r[0], $mod, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
33
scripts/game/beta5/ticks/quit/library.inc
Normal file
33
scripts/game/beta5/ticks/quit/library.inc
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
//--------------------------------------------
|
||||
// "Quit tick": account deletion for quitters
|
||||
//--------------------------------------------
|
||||
|
||||
class beta5_ticks_quit_library {
|
||||
|
||||
public function __construct($lib) {
|
||||
$this->lib = $lib;
|
||||
$this->db = $lib->game->db;
|
||||
$this->main = $lib->game->getLib();
|
||||
}
|
||||
|
||||
|
||||
public function runTick() {
|
||||
$this->db->safeTransaction(array($this, 'quit'));
|
||||
}
|
||||
|
||||
public function quit() {
|
||||
$q = $this->db->query(
|
||||
"SELECT id FROM player "
|
||||
. "WHERE quit IS NOT NULL AND (UNIX_TIMESTAMP(NOW()) - quit) < 86400 "
|
||||
. "AND (UNIX_TIMESTAMP(NOW()) - quit) > 86339"
|
||||
);
|
||||
while ($r = dbFetchArray($q)) {
|
||||
$this->main->call('leaveGame', $r[0], 'QUIT');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
127
scripts/game/beta5/ticks/sales/library.inc
Normal file
127
scripts/game/beta5/ticks/sales/library.inc
Normal file
|
@ -0,0 +1,127 @@
|
|||
<?php
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// "Sales tick": makes sales expire and finalize auction sales
|
||||
//-------------------------------------------------------------
|
||||
|
||||
|
||||
class beta5_ticks_sales_library {
|
||||
|
||||
public function __construct($lib) {
|
||||
$this->lib = $lib;
|
||||
$this->game = $this->lib->game;
|
||||
$this->db = $this->game->db;
|
||||
}
|
||||
|
||||
|
||||
public function runTick() {
|
||||
// Update sales
|
||||
$this->db->safeTransaction(array($this, 'expireSales'));
|
||||
|
||||
// Check CTF victory
|
||||
if ($this->game->params['victory'] == 0) {
|
||||
$this->db->safeTransaction(array($this, 'checkProtection'));
|
||||
} elseif ($this->game->params['victory'] == 2) {
|
||||
$this->db->safeTransaction(array($this, 'checkCTFVictory'));
|
||||
}
|
||||
}
|
||||
|
||||
public function expireSales() {
|
||||
$q = $this->db->query("SELECT * FROM sale WHERE expires<UNIX_TIMESTAMP(NOW()) AND finalized IS NULL");
|
||||
while ($r = dbFetchHash($q)) {
|
||||
// Public offers
|
||||
$q2 = $this->db->query("SELECT auction FROM public_offer WHERE offer=".$r['id']);
|
||||
if ($q2 && dbCount($q2)) {
|
||||
list($auction) = dbFetchArray($q2);
|
||||
$this->expirePublicOffer($r, $auction == 't');
|
||||
continue;
|
||||
}
|
||||
|
||||
// Private offers
|
||||
// FIXME
|
||||
}
|
||||
$this->db->query(
|
||||
"DELETE FROM sale_history WHERE end_mode IS NOT NULL AND UNIX_TIMESTAMP(NOW()) - ended > 5184000"
|
||||
);
|
||||
}
|
||||
|
||||
public function checkCTFVictory() {
|
||||
// Check victory status on CTF games
|
||||
if (! $this->game->getLib()->call('isFinished')) {
|
||||
$this->game->getLib('beta5/ctf')->call('checkTargets');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function checkProtection() {
|
||||
$q = $this->db->query(
|
||||
"SELECT p.id, s.id FROM planet p, system s WHERE s.id = p.system AND s.prot > 0"
|
||||
);
|
||||
|
||||
$checked = array();
|
||||
$pLib = $this->game->getLib('beta5/prot');
|
||||
|
||||
while ($r = dbFetchArray($q)) {
|
||||
if (! in_array($r[1], $checked)) {
|
||||
array_push($checked, $r[1]);
|
||||
$pLib->call('checkSystem', $r[0]);
|
||||
}
|
||||
}
|
||||
|
||||
$pLib->call('flushStatus');
|
||||
}
|
||||
|
||||
|
||||
private function expirePublicOffer($offer, $isAuction) {
|
||||
$tm = time();
|
||||
|
||||
// If it isn't an auction sale, just delete it
|
||||
if (!$isAuction) {
|
||||
// Insert entry in player's history
|
||||
$this->db->query("UPDATE sale_history SET ended=$tm,end_mode=3,sell_price=NULL WHERE offer=".$offer['id']);
|
||||
// FIXME: send message
|
||||
$this->db->query("DELETE FROM sale WHERE id=".$offer['id']);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for a buyer
|
||||
$q = $this->db->query("SELECT player,price FROM auction WHERE offer=".$offer['id']." ORDER BY price DESC LIMIT 1");
|
||||
if (!($q && dbCount($q))) {
|
||||
// Insert entry in player's history
|
||||
$this->db->query("UPDATE sale_history SET ended=$tm,end_mode=3,sell_price=NULL WHERE offer=".$offer['id']);
|
||||
// FIXME: send message
|
||||
$this->db->query("DELETE FROM sale WHERE id=".$offer['id']);
|
||||
return;
|
||||
}
|
||||
list($buyer,$price) = dbFetchArray($q);
|
||||
|
||||
// Refund players who have failed to buy the item
|
||||
$q = $this->db->query("SELECT player,MAX(price) FROM auction WHERE offer=".$offer['id']." AND player<>$buyer GROUP BY player");
|
||||
while ($r = dbFetchArray($q)) {
|
||||
// FIXME: send message
|
||||
$this->db->query("UPDATE player SET cash=cash+".$r[1]." WHERE id=".$r[0]);
|
||||
}
|
||||
|
||||
// Mark the transaction as finalized
|
||||
$this->db->query("UPDATE sale SET finalized=$tm,sold_to=$buyer WHERE id=".$offer['id']);
|
||||
$this->db->query("UPDATE public_offer SET price=$price WHERE offer=".$offer['id']);
|
||||
$this->db->query("DELETE FROM auction WHERE offer=".$offer['id']);
|
||||
$this->db->query("UPDATE player SET cash=cash+$price WHERE id=".$offer['player']);
|
||||
|
||||
// Inform both the current owner and the buyer
|
||||
// FIXME
|
||||
|
||||
// Insert history entry
|
||||
$this->db->query("UPDATE sale_history SET ended=$tm,end_mode=2,sell_price=$price,to_player=$buyer WHERE offer=".$offer['id']);
|
||||
|
||||
// Mark the items for sale
|
||||
if (!is_null($offer['planet'])) {
|
||||
$this->db->query("UPDATE planet SET sale=3 WHERE id=".$offer['planet']);
|
||||
}
|
||||
if (!is_null($offer['fleet'])) {
|
||||
$this->db->query("UPDATE fleet SET sale=3 WHERE id=".$offer['fleet']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
483
scripts/game/beta5/ticks/universe/library.inc
Normal file
483
scripts/game/beta5/ticks/universe/library.inc
Normal file
|
@ -0,0 +1,483 @@
|
|||
<?php
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// "Universe tick": generates sections of the universe
|
||||
// Executed once every 5 minutes, starting from 7:02:00 ST
|
||||
//---------------------------------------------------------------
|
||||
|
||||
|
||||
class beta5_ticks_universe_library {
|
||||
|
||||
public function __construct($lib) {
|
||||
$this->lib = $lib;
|
||||
$this->game = $this->lib->game;
|
||||
$this->db = $this->game->db;
|
||||
$this->main = $this->game->getLib('main');
|
||||
$this->planets = $this->game->getLib('beta5/planet');
|
||||
}
|
||||
|
||||
public function runTick() {
|
||||
$this->db->safeTransaction(array($this, 'genUniverse'));
|
||||
}
|
||||
|
||||
public function genUniverse() {
|
||||
// Run a special version of the tick if we are using a CTF map
|
||||
$map = (int) $this->game->params['usemap'];
|
||||
if ($map > 0) {
|
||||
$this->handleCTFMap($map);
|
||||
return;
|
||||
}
|
||||
|
||||
// Read the game's parameters
|
||||
$np = $this->game->params['nebulaprob'];
|
||||
$this->nebulaProb = ($np > -1 && $np < 21) ? $np : 2;
|
||||
$this->minSystems = $this->game->params['minsystems'];
|
||||
$this->maxSystems = $this->game->params['maxsystems'];
|
||||
$zs = $this->game->params['zonesize'];
|
||||
$this->zoneSize = ($zs <= 0 || $zs > 10) ? 2 : $zs;
|
||||
|
||||
// If there is a maximum value, check it
|
||||
if ($this->maxSystems) {
|
||||
$ns = $this->getAllSystems();
|
||||
if ($ns >= $this->maxSystems) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the amount of free systems
|
||||
$this->reassignEmpty();
|
||||
$ns = $this->getFreeSystems();
|
||||
if ($ns >= $this->minSystems) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the latest system ID
|
||||
$q = $this->db->query("SELECT MAX(id) FROM system");
|
||||
list($id1) = dbFetchArray($q);
|
||||
|
||||
// Read the universe generator's parameters
|
||||
list($dir, $size) = $this->getSystemGenParm();
|
||||
$ldir = $dir; $lsize = $lsize;
|
||||
|
||||
// Generate zones
|
||||
while ($ns < $this->minSystems) {
|
||||
list($x1, $y1, $x2, $y2) = $this->getNextRectangle($dir, $size);
|
||||
$this->makeZone($x1, $y1, $x2, $y2);
|
||||
$ns = $this->getFreeSystems();
|
||||
}
|
||||
|
||||
if ($ldir != $dir || $lsize != $size) {
|
||||
// Update the universe generator's parameters
|
||||
if ($ldir != $dir) {
|
||||
$this->db->query("UPDATE gdata SET value='$dir' WHERE id='sg_dir'");
|
||||
}
|
||||
if ($lsize != $size) {
|
||||
$this->db->query("UPDATE gdata SET value='$size' WHERE id='sg_len'");
|
||||
}
|
||||
|
||||
// Make sure we have a first ID
|
||||
if (is_null($id1)) {
|
||||
$q = $this->db->query("SELECT MIN(id) FROM system");
|
||||
list($id1) = dbFetchArray($q);
|
||||
} else {
|
||||
$id1++;
|
||||
}
|
||||
|
||||
// Read the last ID
|
||||
$q = $this->db->query("SELECT MAX(id) FROM system");
|
||||
list($id2) = dbFetchArray($q);
|
||||
|
||||
// Generate the systems' planets
|
||||
for ($i=$id1;$i<=$id2;$i++) {
|
||||
$this->genSystem($i);
|
||||
}
|
||||
|
||||
// Get the size of the next area
|
||||
list($x1,$y1,$x2,$y2) = $this->getNextRectangle($dir, $size);
|
||||
$w = abs($x2 - $x1) + 1;
|
||||
$h = abs($y2 - $y1) + 1;
|
||||
|
||||
$q = $this->db->query("SELECT MAX(id) FROM planet");
|
||||
list($idp) = dbFetchArray($q);
|
||||
|
||||
// Generate new planets
|
||||
$this->main->call('requestGenPlanets', $idp + 1, ($w + 5) * $h * 6);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function handleCTFMap($mapID) {
|
||||
// Check if there are systems
|
||||
$q = $this->db->query("SELECT COUNT(*) FROM system");
|
||||
if (!($q && dbCount($q))) {
|
||||
return;
|
||||
}
|
||||
list($nSys) = dbFetchArray($q);
|
||||
if ($nSys > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// No systems -> we must generate the map
|
||||
// Start by loading the template's definition
|
||||
$q = $this->db->query("SELECT width,height FROM ctf_map_def WHERE id=$mapID");
|
||||
if (!($q && dbCount($q))) {
|
||||
logText("Could not load map definition #$mapID", LOG_ERR);
|
||||
return;
|
||||
}
|
||||
list($width, $height) = dbFetchArray($q);
|
||||
|
||||
// Load the template's layout
|
||||
$q = $this->db->query("SELECT * FROM ctf_map_layout WHERE map=$mapID");
|
||||
if (!($q && dbCount($q) == $width * $height)) {
|
||||
logText("Could not load map layout for template #$mapID", LOG_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create systems and generate CTF-specific data along the way
|
||||
$ids = array();
|
||||
$targets = array();
|
||||
while ($row = dbFetchHash($q)) {
|
||||
// Insert the map system
|
||||
$qStr = "INSERT INTO system(x,y,prot,assigned,nebula) VALUES ("
|
||||
. "{$row['sys_x']},{$row['sys_y']},0,FALSE,"
|
||||
. (($row['sys_type'] == 'S') ? "0" : $row['sys_type']) . ")";
|
||||
$sys = $this->db->query($qStr);
|
||||
|
||||
if (!$sys) {
|
||||
logText("Error inserting system at ({$row['sys_x']},{$row['sys_y']})", LOG_ERR);
|
||||
return;
|
||||
}
|
||||
array_push($ids, $sys);
|
||||
|
||||
if ($row['sys_type'] != 'S') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($row['alloc_for'] == 0) {
|
||||
// Insert a target record
|
||||
$this->db->query("INSERT INTO ctf_target(system) VALUES ($sys)");
|
||||
array_push($targets, $sys);
|
||||
} else {
|
||||
// Insert an alliance area record
|
||||
$this->db->query("INSERT INTO ctf_alloc(system,alliance,spawn_point) VALUES ("
|
||||
. "$sys,{$row['alloc_for']},'{$row['spawn_here']}')");
|
||||
}
|
||||
}
|
||||
|
||||
// Generate system contents
|
||||
foreach ($ids as $sys) {
|
||||
$this->genSystem($sys);
|
||||
}
|
||||
|
||||
// Upgrade target planets
|
||||
$q = $this->db->query("SELECT id FROM planet WHERE system IN (" . join(',', $targets) . ")");
|
||||
while ($r = dbFetchArray($q)) {
|
||||
$q = $this->db->query("UPDATE planet SET ifact=33, mfact=33, turrets=90 WHERE id = {$r[0]}");
|
||||
$this->planets->call('updateHappiness', $r[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function reassignEmpty() {
|
||||
$q = $this->db->query("SELECT s.id,COUNT(p.*) AS cnt FROM system s,planet p "
|
||||
. "WHERE s.assigned AND s.nebula=0 AND p.owner IS NULL AND p.status=0 AND p.system=s.id "
|
||||
. "GROUP BY s.id HAVING COUNT(p.*)=6");
|
||||
if (!($q && dbCount($q))) {
|
||||
return;
|
||||
}
|
||||
|
||||
$sids = array();
|
||||
while ($r = dbFetchArray($q)) {
|
||||
$allocate = true;
|
||||
|
||||
$q2 = $this->db->query("SELECT id FROM planet WHERE system = {$r[0]}");
|
||||
while ($allocate && $r2 = dbFetchArray($q2)) {
|
||||
$allocate = $this->planets->call('canAllocate', $r2[0]);
|
||||
}
|
||||
|
||||
if ($allocate) {
|
||||
array_push($sids, $r[0]);
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($sids)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$q = $this->db->query("SELECT DISTINCT p.system FROM fleet f,planet p "
|
||||
. "WHERE f.location IS NOT NULL AND f.location=p.id AND p.system IN (" . join(',', $sids) . ")");
|
||||
if (!$q) {
|
||||
return;
|
||||
}
|
||||
|
||||
$flids = array();
|
||||
while ($r = dbFetchArray($q)) {
|
||||
array_push($flids, $r[0]);
|
||||
}
|
||||
|
||||
$rsids = array();
|
||||
foreach ($sids as $sid) {
|
||||
if (!in_array($sid, $flids)) {
|
||||
array_push($rsids, $sid);
|
||||
logText("beta5/universe: system $sid will be reassigned");
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($rsids)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->db->query("UPDATE system SET assigned=FALSE WHERE id IN (" . join(',', $rsids) . ")");
|
||||
}
|
||||
|
||||
|
||||
private function getAllSystems() {
|
||||
$q = $this->db->query("SELECT COUNT(*) FROM system WHERE nebula = 0");
|
||||
list($n) = dbFetchArray($q);
|
||||
return $n;
|
||||
}
|
||||
|
||||
|
||||
private function getFreeSystems() {
|
||||
$q = $this->db->query("SELECT COUNT(*) FROM system WHERE NOT assigned AND nebula = 0");
|
||||
list($n) = dbFetchArray($q);
|
||||
return $n;
|
||||
}
|
||||
|
||||
|
||||
private function getSystemGenParm() {
|
||||
$q = $this->db->query("SELECT id,value FROM gdata WHERE id IN ('sg_dir','sg_len')");
|
||||
$rs = array();
|
||||
while ($r = dbFetchArray($q)) {
|
||||
$rs[$r[0] == "sg_dir" ? 0 : 1] = $r[1];
|
||||
}
|
||||
return $rs;
|
||||
}
|
||||
|
||||
|
||||
private function getNextRectangle(&$dir, &$size) {
|
||||
$zs = $this->zoneSize;
|
||||
$zsT = 1 + 2*$zs;
|
||||
$zsI = $zsT - 1;
|
||||
|
||||
if ($dir < 2) {
|
||||
//$x1 = -2 - 5*$size/2;
|
||||
$x1 = -$zs - $zsT * $size / 2;
|
||||
// $y1 = ($dir == 0) ? (-2 - 5*$size/2) : (3 + 5*$size/2);
|
||||
$y1 = ($dir == 0) ? (-$zs - $zsT * $size / 2) : ($zs + 1 + $zsT * $size / 2);
|
||||
//$x2 = $x1 + 4 + (($dir == 1) ? $size * 5 : 0);
|
||||
$x2 = $x1 + $zs * 2 + (($dir == 1) ? $size * $zsT : 0);
|
||||
//$y2 = $y1 + 4 + (($dir == 0) ? $size * 5 : 0);
|
||||
$y2 = $y1 + $zs * 2 + (($dir == 0) ? $size * $zsT : 0);
|
||||
} else {
|
||||
$m = $size % 2;
|
||||
//$x2 = 7 + 5*($size-$m)/2;
|
||||
$x2 = $zsT + $zs + $zsT * ($size-$m) / 2;
|
||||
//$y2 = ($dir == 2) ? (7 + 5*($size-$m)/2) : (-3 - 5*($size-$m)/2);
|
||||
$y2 = ($dir == 2) ? ($zsT + $zs + $zsT * ($size - $m) / 2) : (- $zs - 1 - $zsT * ($size - $m) /2);
|
||||
//$x1 = $x2 - 4 - (($dir == 3) ? $size * 5 : 0);
|
||||
$x1 = $x2 - $zsT + 1 - (($dir == 3) ? $size * $zsT : 0);
|
||||
//$y1 = $y2 - 4 - (($dir == 2) ? $size * 5 : 0);
|
||||
$y1 = $y2 - $zsT + 1 - (($dir == 2) ? $size * $zsT : 0);
|
||||
}
|
||||
|
||||
$dir = ($dir + 1) % 4;
|
||||
if ($dir % 2 == 0) {
|
||||
$size ++;
|
||||
}
|
||||
return array($x1,$y1,$x2,$y2);
|
||||
}
|
||||
|
||||
|
||||
private function findBorderNebulas($x1, $y1, $x2, $y2) {
|
||||
$x1--;$y1--;$x2++;$y2--;
|
||||
|
||||
$q = $this->db->query(
|
||||
"SELECT COUNT(*) FROM system WHERE nebula > 0 AND ("
|
||||
. "((x=$x1 OR x=$x2) AND y>=$y1 AND y<=$y2) OR ((y=$y1 OR y=$y2) AND x>$x1 AND x<$y2))"
|
||||
);
|
||||
list($c) = dbFetchArray($q);
|
||||
return $c;
|
||||
}
|
||||
|
||||
|
||||
private function getAdjacentNebula($x, $y) {
|
||||
list($x1,$x2,$y1,$y2) = array($x+1, $x-1, $y+1, $y-1);
|
||||
$q = $this->db->query(
|
||||
"SELECT SUM(nebula) FROM system "
|
||||
. "WHERE (x=$x AND y=$y1) OR (x=$x AND y=$y2) OR (x=$x1 AND y=$y) OR (x=$x2 AND y=$y)"
|
||||
);
|
||||
list($r) = dbFetchArray($q);
|
||||
return min((int)$r, 4);
|
||||
}
|
||||
|
||||
|
||||
private function nebulaPass($x1, $y1) {
|
||||
$ds = array(0,1,1,1,2,2,2,2,2,3);
|
||||
$c = 0;
|
||||
|
||||
$zsT = $this->zoneSize * 2 + 1;
|
||||
for ($x = $x1; $x < $x1 + $zsT; $x++) {
|
||||
for ($y = $y1; $y < $y1 + $zsT; $y++) {
|
||||
$q = $this->db->query("SELECT assigned,nebula FROM system WHERE x=$x AND y=$y");
|
||||
list($as,$nb) = dbFetchArray($q);
|
||||
if ($as == 'f' || $nb > 0)
|
||||
continue;
|
||||
|
||||
$ap = $this->getAdjacentNebula($x,$y);
|
||||
if ($ap == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ap -= $ds[rand(0,9)];
|
||||
if ($ap <= 0) {
|
||||
$this->db->query("UPDATE system SET assigned=FALSE,nebula=0 WHERE x=$x AND y=$y");
|
||||
} else {
|
||||
$this->db->query("UPDATE system SET nebula=$ap WHERE x=$x AND y=$y");
|
||||
}
|
||||
$c = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
|
||||
private function makeNebulas($x1,$y1) {
|
||||
do {
|
||||
$c = $this->nebulaPass($x1,$y1);
|
||||
} while ($c);
|
||||
}
|
||||
|
||||
|
||||
private function makeCluster($x1,$y1) {
|
||||
$np = array(1,1,1,1,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,4);
|
||||
|
||||
$zs = $this->zoneSize * 2;
|
||||
$x = $x1 + $zs; $y = $y1 + $zs;
|
||||
$nl = $this->findBorderNebulas($x1,$y1,$x,$y);
|
||||
|
||||
$zsT = $zs + 1;
|
||||
for ($x = $x1; $x < $x1 + $zsT; $x++) {
|
||||
for ($y = $y1; $y < $y1 + $zsT; $y++) {
|
||||
if (rand(0,99) <= $this->nebulaProb && $nl == 0) {
|
||||
$v = $np[rand(0,19)];
|
||||
$nl ++;
|
||||
} else {
|
||||
$v = 0;
|
||||
}
|
||||
$this->db->query("INSERT INTO system(x,y,prot,assigned,nebula) VALUES($x,$y,0,TRUE,$v)");
|
||||
}
|
||||
}
|
||||
|
||||
if ($nl > 0) {
|
||||
$this->makeNebulas($x1,$y1);
|
||||
}
|
||||
$this->db->query("UPDATE system SET assigned=FALSE WHERE x>=$x1 AND y>=$y1 AND x<$x AND y<$y AND nebula=0");
|
||||
}
|
||||
|
||||
|
||||
private function makeZone($x1,$y1,$x2,$y2) {
|
||||
$zsT = $this->zoneSize * 2 + 1;
|
||||
for ($x=$x1;$x<$x2;$x+=$zsT) {
|
||||
for ($y=$y1;$y<$y2;$y+=$zsT) {
|
||||
$this->makeCluster($x,$y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function genPlanets($system) {
|
||||
$npl = 6;
|
||||
|
||||
// Generate the turrets
|
||||
$ttn = 17;
|
||||
$i = -1;
|
||||
$tna = array();
|
||||
for ($i=0;$i<$npl;$i++) {
|
||||
$tna[$i] = 3;
|
||||
}
|
||||
while ($ttn) {
|
||||
$i = ($i + 1) % $npl;
|
||||
if ($tna[$i] == 8) {
|
||||
continue;
|
||||
}
|
||||
$a = rand(0,1);
|
||||
$ttn -= $a; $tna[$i] += $a;
|
||||
}
|
||||
|
||||
// Generate the planets' maximum populations for each tech level
|
||||
$mpa = array();
|
||||
$levels = 4;
|
||||
for ($tl=0;$tl<$levels;$tl++) {
|
||||
$minPPop = 8500 + $tl * 10000;
|
||||
$maxPPop = 11500 + $tl * 10000;
|
||||
$ttp = rand(8800,9200);
|
||||
$mpa[$tl] = array();
|
||||
|
||||
for ($i=0;$i<$npl;$i++) {
|
||||
$mpa[$tl][$i] = $minPPop;
|
||||
}
|
||||
while ($ttp) {
|
||||
$i = ($i + 1) % $npl;
|
||||
if ($mpa[$tl][$i] >= $maxPPop) {
|
||||
continue;
|
||||
}
|
||||
$a = rand(1, min($maxPPop - $mpa[$tl][$i], $ttp));
|
||||
$ttp -= $a;
|
||||
$mpa[$tl][$i] += $a;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the planets
|
||||
for ($i=0;$i<$npl;$i++) {
|
||||
$qs = "INSERT INTO planet(system,orbit,name,turrets,max_pop) VALUES($system,$i,";
|
||||
do {
|
||||
$rn = strtoupper(substr(md5(uniqid(rand())), 0, 7));
|
||||
$q = $this->db->query("SELECT id FROM planet WHERE name='P-[$rn]'");
|
||||
} while(dbCount($q));
|
||||
$qs .= "'P-[$rn]',{$tna[$i]},{$mpa[0][$i]})";
|
||||
$this->db->query($qs);
|
||||
}
|
||||
|
||||
// Compute the new planets' happiness and store their maximal populations
|
||||
$q = $this->db->query("SELECT id FROM planet WHERE system=$system");
|
||||
$np = 0;
|
||||
while ($r = dbFetchArray($q)) {
|
||||
for ($i=0;$i<$levels;$i++) {
|
||||
$this->db->query("INSERT INTO planet_max_pop(planet,tech_level,max_pop) VALUES ({$r[0]},$i,{$mpa[$i][$np]})");
|
||||
}
|
||||
$this->planets->call('updateHappiness', $r[0]);
|
||||
$np ++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function genNebulaOrbit($system, $n) {
|
||||
$npl = 6;
|
||||
for ($i=0;$i<$npl;$i++) {
|
||||
$qs = "INSERT INTO planet(system,orbit,name,status,pop,max_pop,ifact,mfact,turrets,happiness) VALUES($system,$i,";
|
||||
do {
|
||||
$rn = strtoupper(substr(md5(uniqid(rand())), 0, 10));
|
||||
$q = $this->db->query("SELECT id FROM planet WHERE name='NB-[$rn]'");
|
||||
} while(dbCount($q));
|
||||
$md = min(4, max($n + rand(0,2) - 1, 1)) + 1;
|
||||
$qs .= "'NB-[$rn]',$md,0,0,0,0,0,0)";
|
||||
$this->db->query($qs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function genSystem($i) {
|
||||
$q = $this->db->query("SELECT nebula FROM system WHERE id=$i");
|
||||
list($n) = dbFetchArray($q);
|
||||
if ($n == 0) {
|
||||
$this->genPlanets($i);
|
||||
} else {
|
||||
$this->genNebulaOrbit($i, $n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
Reference in a new issue