$general */ public static function weight(array $general): float { return pow( (int)$general['leadership'] + (int)$general['strength'] + (int)$general['intel'], 1.5, ); } /** * @param array> $oldPick * @param list $keepIds * @return array{picked: array>, 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> $candidates * @param array $weights * @param iterable $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> $candidates * @param array $weights * @param array> $picked * @param null|callable(int|string): void $onDraw * @return array> */ 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; } }