test(compare): trace NPC possession selection
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace sammo;
|
||||
|
||||
final class NpcPossessionSelector
|
||||
{
|
||||
public static function buildSeed(string|int $hiddenSeed, int $owner, string $now): string
|
||||
{
|
||||
return Util::simpleSerialize($hiddenSeed, 'SelectNPCToken', $owner, $now);
|
||||
}
|
||||
|
||||
/** @param array<string, mixed> $general */
|
||||
public static function weight(array $general): float
|
||||
{
|
||||
return pow(
|
||||
(int)$general['leadership'] + (int)$general['strength'] + (int)$general['intel'],
|
||||
1.5,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int|string, array<string, mixed>> $oldPick
|
||||
* @param list<int> $keepIds
|
||||
* @return array{picked: array<int|string, array<string, mixed>>, cancelled: bool}
|
||||
*/
|
||||
public static function applyKeep(array $oldPick, array $keepIds): array
|
||||
{
|
||||
$picked = [];
|
||||
foreach ($keepIds as $keepId) {
|
||||
if (array_key_exists($keepId, $oldPick) && (int)$oldPick[$keepId]['keepCnt'] > 0) {
|
||||
$picked[$keepId] = $oldPick[$keepId];
|
||||
$picked[$keepId]['keepCnt'] = (int)$picked[$keepId]['keepCnt'] - 1;
|
||||
}
|
||||
}
|
||||
return [
|
||||
'picked' => $picked,
|
||||
'cancelled' => count($picked) === count($oldPick),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int|string, array<string, mixed>> $candidates
|
||||
* @param array<int|string, float> $weights
|
||||
* @param iterable<string> $reservedPayloads
|
||||
*/
|
||||
public static function removeReserved(array &$candidates, array &$weights, iterable $reservedPayloads): void
|
||||
{
|
||||
foreach ($reservedPayloads as $reservedPayload) {
|
||||
$reserved = Json::decode($reservedPayload);
|
||||
foreach (array_keys($reserved) as $reservedNpc) {
|
||||
if (array_key_exists($reservedNpc, $weights)) {
|
||||
unset($candidates[$reservedNpc], $weights[$reservedNpc]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int|string, array<string, mixed>> $candidates
|
||||
* @param array<int|string, float> $weights
|
||||
* @param array<int|string, array<string, mixed>> $picked
|
||||
* @param null|callable(int|string): void $onDraw
|
||||
* @return array<int|string, array<string, mixed>>
|
||||
*/
|
||||
public static function select(
|
||||
array $candidates,
|
||||
array $weights,
|
||||
array $picked,
|
||||
RandUtil $rng,
|
||||
?callable $onDraw = null,
|
||||
): array {
|
||||
$pickLimit = min(count($candidates), 5);
|
||||
while (count($picked) < $pickLimit) {
|
||||
$generalId = $rng->choiceUsingWeight($weights);
|
||||
if ($onDraw !== null) {
|
||||
$onDraw($generalId);
|
||||
}
|
||||
if (!array_key_exists($generalId, $picked)) {
|
||||
$picked[$generalId] = $candidates[$generalId];
|
||||
}
|
||||
}
|
||||
return $picked;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user