58 lines
2 KiB
TypeScript
58 lines
2 KiB
TypeScript
|
export function assignSubChecksToDice(
|
||
|
dice: number[],
|
||
|
checkTargetNumber: number,
|
||
|
{
|
||
|
maximumCoupResult = 1,
|
||
|
}: {
|
||
|
maximumCoupResult?: number;
|
||
|
} = {},
|
||
|
): { result: number; checkTargetNumber: number }[] {
|
||
|
const requiredNumberOfDice = Math.ceil(checkTargetNumber / 20);
|
||
|
if (dice.length !== requiredNumberOfDice || requiredNumberOfDice < 1) {
|
||
|
throw new Error(game.i18n.localize("DS4.ErrorInvalidNumberOfDice")); // TODO: add i18n
|
||
|
}
|
||
|
|
||
|
const checkTargetNumberForLastSubCheck = checkTargetNumber - 20 * (requiredNumberOfDice - 1);
|
||
|
|
||
|
const indexOfSmallestNonCoup = findIndexOfSmallestNonCoup(dice, maximumCoupResult);
|
||
|
const indexOfFirstCoup = dice.findIndex((die) => die <= maximumCoupResult);
|
||
|
const indexForLastSubCheck = shouldUseCoupForLastSubCheck(
|
||
|
indexOfSmallestNonCoup,
|
||
|
indexOfFirstCoup,
|
||
|
dice,
|
||
|
checkTargetNumberForLastSubCheck,
|
||
|
)
|
||
|
? indexOfFirstCoup
|
||
|
: indexOfSmallestNonCoup;
|
||
|
|
||
|
return dice.map((die, index) => ({
|
||
|
result: die,
|
||
|
checkTargetNumber: index === indexForLastSubCheck ? checkTargetNumberForLastSubCheck : 20,
|
||
|
}));
|
||
|
}
|
||
|
|
||
|
function findIndexOfSmallestNonCoup(dice: number[], maximumCoupResult: number): number {
|
||
|
return dice
|
||
|
.map((die, index) => [die, index])
|
||
|
.filter((indexedDie) => indexedDie[0] > maximumCoupResult)
|
||
|
.reduce(
|
||
|
(smallestIndexedDie, indexedDie) =>
|
||
|
indexedDie[0] < smallestIndexedDie[0] ? indexedDie : smallestIndexedDie,
|
||
|
[Infinity, -1],
|
||
|
)[1];
|
||
|
}
|
||
|
|
||
|
function shouldUseCoupForLastSubCheck(
|
||
|
indexOfSmallestNonCoup: number,
|
||
|
indexOfFirstCoup: number,
|
||
|
dice: number[],
|
||
|
checkTargetNumberForLastSubCheck: number,
|
||
|
) {
|
||
|
return (
|
||
|
indexOfFirstCoup !== -1 &&
|
||
|
(indexOfSmallestNonCoup === -1 ||
|
||
|
(dice[indexOfSmallestNonCoup] > checkTargetNumberForLastSubCheck &&
|
||
|
dice[indexOfSmallestNonCoup] + checkTargetNumberForLastSubCheck > 20))
|
||
|
);
|
||
|
}
|