merge: trace scenario 2400 speciality parity
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace sammo;
|
||||
|
||||
if (PHP_SAPI !== 'cli' || getenv('REF_DETERMINISTIC_INSTALL_ENABLED') !== '1') {
|
||||
http_response_code(404);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
chdir(dirname(__DIR__));
|
||||
require_once 'lib.php';
|
||||
|
||||
$rows = DB::db()->query(
|
||||
'SELECT general_id, log_type, year, month, text
|
||||
FROM general_record
|
||||
WHERE log_type IN ("battle_brief", "battle")
|
||||
ORDER BY id'
|
||||
);
|
||||
|
||||
echo json_encode([
|
||||
'schemaVersion' => 1,
|
||||
'engine' => 'ref',
|
||||
'logs' => array_map(static fn(array $row): array => [
|
||||
'generalId' => (int)$row['general_id'],
|
||||
'category' => $row['log_type'] === 'battle_brief' ? 'BATTLE_BRIEF' : 'BATTLE_DETAIL',
|
||||
'year' => (int)$row['year'],
|
||||
'month' => (int)$row['month'],
|
||||
'text' => (string)$row['text'],
|
||||
], $rows),
|
||||
], JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
|
||||
@@ -75,7 +75,11 @@ foreach ($db->query('SELECT * FROM general ORDER BY no') as $row) {
|
||||
'dex4', 'dex5', 'killTurn', 'affinity', 'birthYear', 'deathYear', 'specAge', 'specAge2'] as $key) {
|
||||
$general[$key] = (int)$general[$key];
|
||||
}
|
||||
$general['turnTime'] = $clock->formatTick(Util::toInt($general['turnTime']), true);
|
||||
$general['turnTick'] = Util::toInt($general['turnTime']);
|
||||
$general['turnTime'] = $clock->formatTick($general['turnTick'], true);
|
||||
$general['recentWarTick'] = $general['recentWarTime'] === null
|
||||
? null
|
||||
: Util::toInt($general['recentWarTime']);
|
||||
$general['recentWarTime'] = $general['recentWarTime'] === null
|
||||
? null
|
||||
: $clock->formatTick(Util::toInt($general['recentWarTime']), true);
|
||||
@@ -102,7 +106,9 @@ foreach ($db->query('SELECT * FROM city ORDER BY city') as $row) {
|
||||
}
|
||||
|
||||
$nations = [];
|
||||
foreach ($db->query('SELECT * FROM nation ORDER BY nation') as $row) {
|
||||
$lastAttackableByNation = KVStorage::getValuesFromInterNamespace($db, 'nation_env', 'last_attackable');
|
||||
$lastCapitalMoveTrialByNation = KVStorage::getValuesFromInterNamespace($db, 'nation_env', 'last천도Trial');
|
||||
foreach ($db->query('SELECT *, CAST(tech AS DOUBLE) AS tech_raw FROM nation ORDER BY nation') as $row) {
|
||||
$nation = monthlySnapshotPick($row, [
|
||||
'id' => 'nation', 'name' => 'name', 'color' => 'color', 'capitalCityId' => 'capital',
|
||||
'gold' => 'gold', 'rice' => 'rice', 'tech' => 'tech', 'level' => 'level',
|
||||
@@ -117,6 +123,12 @@ foreach ($db->query('SELECT * FROM nation ORDER BY nation') as $row) {
|
||||
$nation[$key] = (int)$nation[$key];
|
||||
}
|
||||
$nation['tech'] = (float)$nation['tech'];
|
||||
$nation['techRaw'] = (float)$row['tech_raw'];
|
||||
$nation['lastAttackable'] = (int)($lastAttackableByNation[$nation['id']] ?? 0);
|
||||
$lastCapitalMoveTrial = $lastCapitalMoveTrialByNation[$nation['id']] ?? null;
|
||||
$nation['lastCapitalMoveTrial'] = is_array($lastCapitalMoveTrial)
|
||||
? [(int)($lastCapitalMoveTrial[0] ?? 0), (int)($lastCapitalMoveTrial[1] ?? 0)]
|
||||
: null;
|
||||
$nations[] = $nation;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1734,7 +1734,7 @@ function deleteNation(General $lord, bool $applyDB): array
|
||||
|
||||
$nationGeneralList = General::createObjListFromDB(
|
||||
$db->queryFirstColumn(
|
||||
'SELECT `no` FROM general WHERE nation=%i AND no != %i',
|
||||
'SELECT `no` FROM general WHERE nation=%i AND no != %i ORDER BY no ASC',
|
||||
$nationID,
|
||||
$lordID
|
||||
),
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ function processWar(string $warSeed, General $attackerGeneral, array $rawAttacke
|
||||
|
||||
$city = new WarUnitCity($rng, $rawDefenderCity, $rawDefenderNation, $year, $month, $startYear);
|
||||
|
||||
$defenderCityGeneralIDList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND city=%i AND nation!=0', $city->getVar('nation'), $city->getVar('city'));
|
||||
$defenderCityGeneralIDList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND city=%i AND nation!=0 ORDER BY no', $city->getVar('nation'), $city->getVar('city'));
|
||||
$defenderCityGeneralList = General::createObjListFromDB($defenderCityGeneralIDList, null);
|
||||
|
||||
$captureBattleFixture =
|
||||
|
||||
@@ -37,7 +37,7 @@ class AssignGeneralSpeciality extends \sammo\Event\Action
|
||||
$month,
|
||||
)));
|
||||
|
||||
foreach ($db->query('SELECT no,name,nation,leadership,strength,intel,aux from general where specage<=age and special=%s', GameConst::$defaultSpecialDomestic) as $general) {
|
||||
foreach ($db->query('SELECT no,name,nation,leadership,strength,intel,aux from general where specage<=age and special=%s ORDER BY no ASC', GameConst::$defaultSpecialDomestic) as $general) {
|
||||
$generalID = $general['no'];
|
||||
$special = SpecialityHelper::pickSpecialDomestic(
|
||||
$rng,
|
||||
@@ -57,7 +57,7 @@ class AssignGeneralSpeciality extends \sammo\Event\Action
|
||||
$logger->pushGeneralHistoryLog("특기 【<b><C>{$specialText}</></b>】{$josaUl} 습득");
|
||||
}
|
||||
|
||||
foreach ($db->query('SELECT no,name,nation,leadership,strength,intel,npc,dex1,dex2,dex3,dex4,dex5,aux from general where specage2<=age and special2=%s', GameConst::$defaultSpecialWar) as $general) {
|
||||
foreach ($db->query('SELECT no,name,nation,leadership,strength,intel,npc,dex1,dex2,dex3,dex4,dex5,aux from general where specage2<=age and special2=%s ORDER BY no ASC', GameConst::$defaultSpecialWar) as $general) {
|
||||
$generalID = $general['no'];
|
||||
$generalAux = Json::decode($general['aux']);
|
||||
|
||||
|
||||
+52
-28
@@ -2916,22 +2916,40 @@ class GeneralAI
|
||||
}
|
||||
|
||||
|
||||
protected function do출병(): ?GeneralCommand
|
||||
{
|
||||
if (!$this->attackable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($this->dipState !== self::d전쟁) {
|
||||
return null;
|
||||
protected function do출병(): ?GeneralCommand
|
||||
{
|
||||
$traceEnabled = in_array((string)$this->general->getID(), array_filter(explode(',', (string)getenv('REF_AI_TRACE_GENERAL_IDS')), 'strlen'), true);
|
||||
$trace = static function (string $stage, array $values = []) use ($traceEnabled): void {
|
||||
if ($traceEnabled) {
|
||||
fwrite(STDOUT, 'AI_WAR_TRACE ' . Json::encode(['engine' => 'ref', 'stage' => $stage] + $values) . "\n");
|
||||
}
|
||||
};
|
||||
$trace('start', [
|
||||
'generalId' => $this->general->getID(), 'attackable' => $this->attackable,
|
||||
'dipState' => $this->dipState, 'nationRice' => $this->nation['rice'],
|
||||
'baseRice' => GameConst::$baserice, 'train' => $this->general->getVar('train'),
|
||||
'atmos' => $this->general->getVar('atmos'), 'crew' => $this->general->getVar('crew'),
|
||||
'fullLeadership' => $this->fullLeadership, 'minWarCrew' => $this->nationPolicy->minWarCrew,
|
||||
'cityID' => $this->city['city'], 'front' => $this->city['front'],
|
||||
'warTargetNation' => $this->warTargetNation,
|
||||
]);
|
||||
if (!$this->attackable) {
|
||||
$trace('not-attackable');
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($this->dipState !== self::d전쟁) {
|
||||
$trace('not-at-war');
|
||||
return null;
|
||||
}
|
||||
|
||||
$general = $this->getGeneralObj();
|
||||
$city = $this->city;
|
||||
$nation = $this->nation;
|
||||
|
||||
if (($nation['rice'] < GameConst::$baserice) && $general->getNPCType() >= 2 && $this->rng->nextBool(0.7)) {
|
||||
return null;
|
||||
if (($nation['rice'] < GameConst::$baserice) && $general->getNPCType() >= 2 && $this->rng->nextBool(0.7)) {
|
||||
$trace('low-nation-rice');
|
||||
return null;
|
||||
}
|
||||
|
||||
$cityID = $city['city'];
|
||||
@@ -2939,22 +2957,27 @@ class GeneralAI
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
if ($general->getVar('train') < min(100, $this->nationPolicy->properWarTrainAtmos)) {
|
||||
return null;
|
||||
}
|
||||
if ($general->getVar('atmos') < min(100, $this->nationPolicy->properWarTrainAtmos)) {
|
||||
return null;
|
||||
}
|
||||
if ($general->getVar('crew') < min(($this->fullLeadership - 2) * 100, $this->nationPolicy->minWarCrew)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($city['front'] === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($city['front'] === 1) {
|
||||
return null;
|
||||
if ($general->getVar('train') < min(100, $this->nationPolicy->properWarTrainAtmos)) {
|
||||
$trace('low-train');
|
||||
return null;
|
||||
}
|
||||
if ($general->getVar('atmos') < min(100, $this->nationPolicy->properWarTrainAtmos)) {
|
||||
$trace('low-atmos');
|
||||
return null;
|
||||
}
|
||||
if ($general->getVar('crew') < min(($this->fullLeadership - 2) * 100, $this->nationPolicy->minWarCrew)) {
|
||||
$trace('low-crew');
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($city['front'] === 0) {
|
||||
$trace('front-zero');
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($city['front'] === 1) {
|
||||
$trace('front-one');
|
||||
return null;
|
||||
}
|
||||
|
||||
$attackableNations = [];
|
||||
@@ -2969,11 +2992,12 @@ class GeneralAI
|
||||
}
|
||||
$nearCities = array_keys(CityConst::byID($cityID)->path);
|
||||
|
||||
$attackableCities = $db->queryFirstColumn(
|
||||
$attackableCities = $db->queryFirstColumn(
|
||||
'SELECT city, nation FROM city WHERE nation IN %li AND city IN %li',
|
||||
$attackableNations,
|
||||
$nearCities
|
||||
);
|
||||
);
|
||||
$trace('destinations', ['attackableNations' => $attackableNations, 'nearCities' => $nearCities, 'attackableCities' => $attackableCities]);
|
||||
|
||||
if (count($attackableCities) == 0) {
|
||||
throw new \RuntimeException('출병 불가' . $cityID . var_export($attackableNations, true) . var_export($nearCities, true));
|
||||
|
||||
Reference in New Issue
Block a user