Starvation Refactor

Refactor part 3 of the starvation function

+Troops will now die equally, according to the crop consumption of the
village

Database.php:
+Modified two functions to work with unit arrays as a parameters
This commit is contained in:
iopietro
2018-04-12 12:53:24 +02:00
parent a906f673b4
commit 29faeca811
2 changed files with 104 additions and 92 deletions
+81 -82
View File
@@ -4876,37 +4876,35 @@ class Automation {
************************************************/
private function starvation() {
global $database, $village, $autoprefix;
global $database, $autoprefix;
if(file_exists($autoprefix."GameEngine/Prevention/starvation.txt")) {
unlink($autoprefix."GameEngine/Prevention/starvation.txt");
}
//starvation is disabled during Easter/Holidays/Christmas
if(PEACE) return;
$ourFileHandle = fopen($autoprefix."GameEngine/Prevention/starvation.txt", 'w');
fclose($ourFileHandle);
$time = time();
//TODO: Starvation should be updated in every village!
//update starvation
$getvillage = $database->getVillage($village->wid);
$starv = $getvillage['starv'];
if ($getvillage['owner'] != 3 && $starv == 0)
//update starvation in every village
$starvarray = $database->getProfileVillages(0, 7);
foreach($starvarray as $starv)
{
$crop = $database->getCropProdstarv($village->wid);
$unitarrays = $this->getAllUnits($village->wid);
$village_upkeep = $getvillage['pop'] + $this->getUpkeep($unitarrays, 0);
if ($crop < $village_upkeep)
$crop = $database->getCropProdstarv($starv['wref']);
$unitArrays = $this->getAllUnits($starv['wref']);
$villageUpkeep = $starv['pop'] + $this->getUpkeep($unitArrays, 0);
if ($crop < $villageUpkeep)
{
// add starv data
$database->setVillageField($village->wid, 'starv', $village_upkeep);
if($starv==0) $database->setVillageField($village->wid, 'starvupdate', time());
$database->setVillageFields($starv['wref'], ['starv', 'starvupdate'], [$villageUpkeep, time()]);
}
unset($crop,$unitarrays,$getvillage,$village_upkeep);
}
unset($crop, $unitArrays, $villageUpkeep);
}
// load villages with minus prod
@@ -4928,10 +4926,9 @@ class Automation {
{
$unitarrays = $this->getAllUnits($starv['wref']);
$upkeep = $starv['pop'] + $this->getUpkeep($unitarrays, 0, $starv['wref']);
$maxcount = $totalunits = 0;
$upkeep = $starv['pop'] + $this->getUpkeep($unitarrays, 0, $starv['wref']);
$enforceArrays = $prisonerArrays = $unitArrays = $attackArrays = $allTroopsArray = $starvingTroops = [];
$enforceArrays = $prisonerArrays = $unitArrays = $attackArrays = $allTroopsArray = $starvingTroops = $killedUnits = [];
$enforceArrays = [$database->getOasisEnforce($starv['wref'], 2),
$database->getOasisEnforce($starv['wref'], 3),
@@ -4948,54 +4945,30 @@ class Automation {
$allTroopsArray = [$enforceArrays, $prisonerArrays, $unitArrays, $attackArrays];
// find the first not-empty array
for($type = 0; $type < count($allTroopsArray); $type++)
foreach($allTroopsArray as $type => $allTroops)
{
if(!empty($allTroopsArray[$type]))
if(!empty($allTroops))
{
for($subtype = 0; $subtype < count($allTroopsArray[$type]); $subtype++)
foreach($allTroops as $subtype => $troops)
{
if(!empty($allTroopsArray[$type][$subtype]))
if(!empty($troops))
{
$starvingTroops = reset($allTroopsArray[$type][$subtype]);
$starvingTroops = reset($troops);
break 2;
}
}
}
}
// if the player has no troops, then continue to the next value in the foreach
if(empty($starvingTroops)) continue;
$tribe = $database->getUserField($starv['owner'], "tribe", 0);
$start = ($special = in_array($type, [1, 3])) ? 1 : ($tribe - 1) * 10 + 1;
$end = ($special) ? 10 : $tribe * 10 ;
$utype = ($special) ? 't' : 'u';
$heroType = ($special) ? 't11' : 'hero';
for($i = $start ; $i <= $end ; $i++)
{
$units = (isset($starvingTroops[$utype.$i]) ? $starvingTroops[$utype.$i] : 0);
if($units > $maxcount){
$maxcount = $units;
$maxtype = $i;
}
$totalunits += $units;
}
$totalunits += isset($starvingTroops[$heroType]) ? $starvingTroops[$heroType] : 0;
if($totalunits == 1 && $starvingTroops[$heroType] > 0)
{
$maxcount = $starvingTroops[$heroType];
$maxtype = "hero";
$starvingTroops['heroinfo'] = $database->getHero(($type == 2) ? $starv['owner'] : $database->getVillageField($starvingTroops['from'], "owner"))[0];
}
// if the player has no troops, then skip the next instructions
if(empty($starvingTroops)) continue;
// counting
$timedif = $time-$starv['starvupdate'];
$skolko = $database->getCropProdstarv($starv['wref'])-$starv['starv'];
if($skolko < 0)
$cropProd = $database->getCropProdstarv($starv['wref'])-$starv['starv'];
if($cropProd < 0)
{
$starvsec = (abs($skolko)/3600);
$starvsec = (abs($cropProd)/3600);
$difcrop = ($timedif*$starvsec); //crop eat up over time
$newcrop = 0;
$oldcrop = $database->getVillageField($starv['wref'], 'crop');
@@ -5009,64 +4982,90 @@ class Automation {
$database->setVillageField($starv['wref'], 'crop', $newcrop);
}
}
if($difcrop > 0)
{
global ${'u'.$maxtype}, ${'h'.$starvingTroops['heroinfo']['unit'].'_full'};
$tribe = $database->getUserField(($type == 2) ? $starv['owner'] : $database->getVillageField($starvingTroops['from'], "owner"), "tribe", 0);
$start = ($special = in_array($type, [1, 3])) ? 1 : ($tribe - 1) * 10 + 1;
$end = ($special) ? 10 : $tribe * 10 ;
$utype = ($special) ? 't' : 'u';
$heroType = ($special) ? 't11' : 'hero';
$hungry = [];
$hungry = ($maxtype != "hero") ? ${'u'.$maxtype} : ${'h'.$starvingTroops['heroinfo']['unit'].'_full'}[min($starvingTroops['heroinfo']['level'], 60)];
if ($hungry['crop'] > 0 && $oldcrop <= 0) $killunits = ceil($difcrop/$hungry['crop']);
else $killunits = 0;
if($killunits > 0)
$totalUnits = 0;
$counting = true;
while($difcrop > 0)
{
$pskolko = abs($skolko);
if($killunits > $pskolko && $skolko < 0) $killunits = $pskolko;
if($maxtype == "hero" && $totalunits > 0)
// search the highest troop
$maxcount = $maxtype = 0;
for($i = $start ; $i <= $end ; $i++)
{
$database->modifyHero("dead", 1, $starvingTroops['heroinfo']['heroid']);
$database->modifyHero("health", 0, $starvingTroops['heroinfo']['heroid']);
$units = (isset($starvingTroops[$utype.$i]) ? $starvingTroops[$utype.$i] : 0);
if($counting) $totalUnits += $units;
if($units > $maxcount)
{
$maxcount = $units;
$maxtype = $i;
}
}
if($counting) $counting = false;
if($maxtype > 0)
{
$starvingTroops[$utype.$maxtype]--;
$killedUnits[$maxtype]++;
$difcrop -= $GLOBALS['u'.(($special) ? $maxtype + ($tribe - 1) * 10 : $maxtype)]['crop'];
}
else break;
}
$totalKilledUnits = array_sum($killedUnits);
if($starvingTroops[$heroType] > 0 && ($totalUnits == 0 || $totalUnits == $totalKilledUnits))
{
$totalKilledUnits += $starvingTroops[$heroType];
$totalUnits += $starvingTroops[$heroType];
$starvingTroops['heroinfo'] = $database->getHero(($type == 2) ? $starv['owner'] : $database->getVillageField(($type == 3 && $subtype == 1) ? $starvingTroops['to'] : $starvingTroops['from'], "owner"))[0];
$database->modifyHero("dead", 1, $starvingTroops['heroinfo']['heroid']);
$database->modifyHero("health", 0, $starvingTroops['heroinfo']['heroid']);
$newCrop = $GLOBALS['h'.$starvingTroops['heroinfo']['unit'].'_full'][min($starvingTroops['heroinfo']['level'], 60)]['crop'] + $difcrop;
}
else if($maxtype == 0) $newCrop = 0;
else $newCrop = $GLOBALS['u'.$maxtype]['crop'];
if($totalKilledUnits > 0)
{
switch($type)
{
case 0:
if($killunits < $totalunits)
if($totalKilledUnits < $totalUnits)
{
$database->modifyEnforce($starvingTroops['id'], $maxtype, min($killunits, $maxcount), 0);
$database->modifyEnforce($starvingTroops['id'], array_keys($killedUnits), array_values($killedUnits), 0);
}
else $database->deleteReinf($starvingTroops['id']);
break;
case 1:
if($killunits < $totalunits)
if($totalKilledUnits < $totalUnits)
{
$database->modifyPrisoners($starvingTroops['id'], $maxtype, min($killunits, $maxcount), 0);
$database->modifyPrisoners($starvingTroops['id'], array_keys($killedUnits), array_values($killedUnits), 0);
}
else $database->deletePrisoners($starvingTroops['id']);
break;
case 2:
$database->modifyUnit($starv['wref'], [$maxtype], [min($killunits, $maxcount)], [0]);
$database->modifyUnit($starv['wref'], array_keys($killedUnits), array_values($killedUnits), [0]);
break;
case 3:
if($killunits < $totalunits)
if($totalKilledUnits < $totalUnits)
{
$database->modifyAttack($starvingTroops['id'], $maxtype, min($killunits, $maxcount));
$database->modifyAttack2($starvingTroops['id'], array_keys($killedUnits), array_values($killedUnits), 0);
}
else $database->setMovementProc($starvingTroops['moveid'].(($subtype == 1) ? ", ".($starvingTroops['moveid'] + 1) : ""));
break;
}
if($totalunits > 0)
{
$database->modifyResource($starv['wref'], 0, 0, 0, $hungry['crop'], 1);
$database->setVillageField($starv['wref'], ['starv', 'starvupdate'], [$upkeep, $time]);
}
$database->modifyResource($starv['wref'], 0, 0, 0, max(intval($newCrop), 0), 1);
$database->setVillageField($starv['wref'], ['starv', 'starvupdate'], [$upkeep, $time]);
}
}
}
@@ -5075,7 +5074,7 @@ class Automation {
if ($crop > $upkeep) $database->setVillageField($starv['wref'], ['starv', 'starvupdate'], [0, 0]);
unset ($starv, $unitarrays, $enforce, $starvarray, $maxtype, $type, $subtype);
unset ($unitarrays, $type, $subtype);
}
if(file_exists("GameEngine/Prevention/starvation.txt")) {
+23 -10
View File
@@ -1803,6 +1803,10 @@ class MYSQLi_DB implements IDbConnection {
// by loyalty updates required
case 6: $q = "SELECT * FROM " . TB_PREFIX . "vdata WHERE loyalty < 100";
break;
// villages without starvation data, Support, Natars, Taskmaster, Multihunter are all excluded
case 7: $q = "SELECT * FROM " . TB_PREFIX . "vdata WHERE starv = 0 and owner > 5";
break;
}
$result = mysqli_query($this->dblink,$q);
@@ -5614,7 +5618,7 @@ References: User ID/Message ID, Mode
return mysqli_query($this->dblink,$q);
}
function modifyAttack2($aid, $unit, $amt) {
function modifyAttack2($aid, $unit, $amt, $mode = 1) {
list($aid, $unit, $amt) = $this->escape_input((int) $aid, $unit, $amt);
if (!is_array($unit)) {
@@ -5625,7 +5629,7 @@ References: User ID/Message ID, Mode
$pairs = [];
foreach ($unit as $index => $unitValue) {
$unitValue = 't' . $this->escape($unitValue);
$pairs[] = $unitValue . ' = ' . $unitValue . ' + ' . (int) $amt[$index];
$pairs[] = $unitValue . ' = ' . $unitValue . (($mode) ? ' + ' : ' - ') . (int) $amt[$index];
}
$q = "UPDATE " . TB_PREFIX . "attacks SET ".implode(', ', $pairs)." WHERE id = $aid";
@@ -7564,22 +7568,31 @@ References: User ID/Message ID, Mode
/**
* Used to modify prisoners through the inserted id
*
* @param int $id The id where prisoners are in the database
* @param int $id The prisoner id where prisoners are in the database
* @param int $unit The type of the unit
* @param int $amount The amount of the unit you want to sum/subtract
* @param int $mode 0 for subtracting the inserted amount, 1 for adding it
* @return bool Returns false on failure and true on success
*/
function modifyPrisoners($id, $unit, $amount, $mode) {
list($id, $unit, $amount, $mode) = $this->escape_input((int) $id,(int) $unit,(int) $amount,(int) $mode);
function modifyPrisoners($id, $units, $amount, $mode) {
list($id, $units, $amount, $mode) = $this->escape_input((int) $id, $units, $amount,(int) $mode);
$unit = 't'.$unit;
$prisoners = $unit." = ".$unit.(!$mode ? " - " : " + ").$amount;
if (!is_array($units))
{
$units = [$units];
$amount = [$amount];
}
$prisoners = [];
foreach($units as $index => $unit)
{
$unit = 't'.$this->escape($unit);
$prisoners[] = $unit." = ".$unit.(!$mode ? " - " : " + ").(int)$amount[$index];
}
$q = "UPDATE " . TB_PREFIX . "prisoners set $prisoners WHERE id = $id";
$res = mysqli_query($this->dblink,$q);
return $res;
$q = "UPDATE " . TB_PREFIX . "prisoners set ".implode(', ', $prisoners)." WHERE id = $id";
return mysqli_query($this->dblink,$q);
}
function getPrisoners($wid,$mode=0, $use_cache = true) {