diff --git a/hwe/compare/turn_command_trace.php b/hwe/compare/turn_command_trace.php index 47bfb574..561db106 100644 --- a/hwe/compare/turn_command_trace.php +++ b/hwe/compare/turn_command_trace.php @@ -98,13 +98,22 @@ function comparisonApplyTurnFixtureSetup(mixed $setup): void throw new \InvalidArgumentException('setup.world must be an object'); } $game = KVStorage::getStorage($db, 'game_env'); - foreach (['year', 'month', 'startyear'] as $key) { - $fixtureKey = $key === 'startyear' ? 'startYear' : $key; + foreach (['year', 'month', 'startyear', 'init_year', 'init_month'] as $key) { + $fixtureKey = match ($key) { + 'startyear' => 'startYear', + 'init_year' => 'initYear', + 'init_month' => 'initMonth', + default => $key, + }; if (!array_key_exists($fixtureKey, $world)) { continue; } $value = $world[$fixtureKey]; - if (!is_int($value) || $value < 1 || ($key === 'month' && $value > 12)) { + if ( + !is_int($value) + || $value < 1 + || (in_array($key, ['month', 'init_month'], true) && $value > 12) + ) { throw new \InvalidArgumentException("setup.world.{$fixtureKey} is invalid"); } $game->setValue($key, $value); @@ -119,11 +128,22 @@ function comparisonApplyTurnFixtureSetup(mixed $setup): void } } - foreach (['nations', 'cities', 'generals', 'diplomacy'] as $collection) { + foreach (['nations', 'cities', 'generals', 'troops', 'diplomacy'] as $collection) { if (isset($setup[$collection]) && !is_array($setup[$collection])) { throw new \InvalidArgumentException("setup.{$collection} must be an array"); } } + if (isset($setup['randomFoundingCandidateCityIds'])) { + $candidateCityIds = comparisonIntegerList( + $setup['randomFoundingCandidateCityIds'], + 'randomFoundingCandidateCityIds', + ); + if ($candidateCityIds === []) { + throw new \InvalidArgumentException('randomFoundingCandidateCityIds must not be empty'); + } + $db->update('city', ['level' => 4], '1 = 1'); + $db->update('city', ['level' => 5], 'city IN %li', $candidateCityIds); + } if (($setup['isolateWorld'] ?? false) === true) { $generalIds = array_values(array_map( @@ -186,6 +206,13 @@ function comparisonApplyTurnFixtureSetup(mixed $setup): void ]; $db->insertUpdate('nation', $data, $data); } + if (($setup['isolateWorld'] ?? false) === true && ($setup['nations'] ?? []) !== []) { + $maxNationId = max(array_map( + static fn(array $row): int => (int)$row['id'], + $setup['nations'], + )); + $db->query('ALTER TABLE nation AUTO_INCREMENT = %i', $maxNationId + 1); + } foreach ($setup['cities'] ?? [] as $row) { if (!is_array($row) || !is_int($row['id'] ?? null) || $row['id'] < 1) { @@ -193,6 +220,7 @@ function comparisonApplyTurnFixtureSetup(mixed $setup): void } $patch = comparisonMappedPatch($row, [ 'nationId' => 'nation', + 'level' => 'level', 'population' => 'pop', 'populationMax' => 'pop_max', 'agriculture' => 'agri', @@ -271,6 +299,26 @@ function comparisonApplyTurnFixtureSetup(mixed $setup): void } } + foreach ($setup['troops'] ?? [] as $row) { + if ( + !is_array($row) + || !is_int($row['id'] ?? null) + || !is_int($row['nationId'] ?? null) + || !is_string($row['name'] ?? null) + || $row['id'] < 1 + || $row['nationId'] < 1 + || $row['name'] === '' + ) { + throw new \InvalidArgumentException('setup.troops requires positive id/nationId and non-empty name'); + } + $data = [ + 'troop_leader' => $row['id'], + 'nation' => $row['nationId'], + 'name' => $row['name'], + ]; + $db->insertUpdate('troop', $data, $data); + } + foreach ($setup['diplomacy'] ?? [] as $row) { if ( !is_array($row) || @@ -361,10 +409,25 @@ function comparisonRunTurnCommand(array $request): array $resultTurnRaw = $resultTurn->toRaw(); $resultTerm = (int)($resultTurnRaw['term'] ?? 0); $preReqTurn = $command->getPreReqTurn(); + $acceptScoutCompleted = ( + $action === 'che_등용수락' + && is_array($args) + && is_int($args['destNationID'] ?? null) + && $general->getNationID() === $args['destNationID'] + ); + $foundNationCompleted = ( + in_array($action, ['che_건국', 'cr_건국', 'che_무작위건국'], true) + && is_array($args) + && is_string($args['nationName'] ?? null) + && DB::db()->queryFirstField( + 'SELECT name FROM nation WHERE nation = %i', + $general->getNationID(), + ) === $args['nationName'] + ); $completed = ( $action === 'che_접경귀환' && $tracingRng->calls !== [] - ) || (($resultTurnRaw['command'] ?? null) === $command->getName() + ) || $acceptScoutCompleted || $foundNationCompleted || (($resultTurnRaw['command'] ?? null) === $command->getName() && ( ($preReqTurn === 0 && $resultTerm === 0) || (