Add slaying dice behaviour.

This commit is contained in:
Oliver Rümpelein 2021-01-02 16:40:30 +01:00
parent 55beeb92c9
commit aaa10d7469
2 changed files with 33 additions and 23 deletions

View file

@ -314,13 +314,12 @@ describe("DS4 Rolls with multiple and slaying dice, first throw", () => {
}); });
}); });
// TODO: Implement & reactivate describe("DS4 Rolls with multiple and slaying dice, recurrent throw", () => {
xdescribe("DS4 Rolls with multiple and slaying dice, recurrent throw", () => {
it("Should regularly succeed with the first roll being a `20`", () => { it("Should regularly succeed with the first roll being a `20`", () => {
const rollProvider = mockMultipleThrows([20, 2, 19]); const rollProvider = mockMultipleThrows([20, 2, 19]);
expect(rollCheckMultipleDice(48, {}, rollProvider)).toEqual( expect(rollCheckMultipleDice(48, { useSlayingDice: true, slayingDiceRepetition: true }, rollProvider)).toEqual(
new RollResult(40, RollResultStatus.CRITICAL_FAILURE, [20, 2, 19]), new RollResult(41, RollResultStatus.SUCCESS, [20, 19, 2]),
); );
}); });
}); });

View file

@ -33,24 +33,7 @@ export function rollCheckSingleDie(
} }
} }
export function rollCheckMultipleDice( function separateCriticalHits(dice: Array<number>, usedOptions: RollOptions): [Array<number>, Array<number>] {
testValue: number,
rollOptions: Partial<RollOptions>,
provider: RollProvider = new DS4RollProvider(),
): RollResult {
const usedOptions = new DefaultRollOptions().mergeWith(rollOptions);
const finalCheck = testValue % 20;
const numberOfDice = Math.ceil(testValue / 20);
const dice = provider.getNextRolls(numberOfDice);
const firstResult = dice[0];
// Slaying Dice require a different handling.
if (firstResult >= usedOptions.minCritFail && !isSlayingDiceRepetition(usedOptions)) {
return new RollResult(0, RollResultStatus.CRITICAL_FAILURE, dice);
}
const partitionCallback = (prev: [Array<number>, Array<number>], cur: number) => { const partitionCallback = (prev: [Array<number>, Array<number>], cur: number) => {
if (cur <= usedOptions.maxCritSucc) { if (cur <= usedOptions.maxCritSucc) {
prev[0].push(cur); prev[0].push(cur);
@ -64,6 +47,30 @@ export function rollCheckMultipleDice(
.reduce(partitionCallback, [[], []]) .reduce(partitionCallback, [[], []])
.map((a) => a.sort((r1, r2) => r2 - r1)); .map((a) => a.sort((r1, r2) => r2 - r1));
return [critSuccesses, otherRolls];
}
export function rollCheckMultipleDice(
testValue: number,
rollOptions: Partial<RollOptions>,
provider: RollProvider = new DS4RollProvider(),
): RollResult {
const usedOptions = new DefaultRollOptions().mergeWith(rollOptions);
const finalCheck = testValue % 20;
const numberOfDice = Math.ceil(testValue / 20);
const dice = provider.getNextRolls(numberOfDice);
const firstResult = dice[0];
const slayingDiceRepetition = isSlayingDiceRepetition(usedOptions);
// Slaying Dice require a different handling.
if (firstResult >= usedOptions.minCritFail && !slayingDiceRepetition) {
return new RollResult(0, RollResultStatus.CRITICAL_FAILURE, dice);
}
const [critSuccesses, otherRolls] = separateCriticalHits(dice, usedOptions);
const swapLastWithCrit: boolean = isDiceSwapNecessary(critSuccesses, otherRolls, finalCheck); const swapLastWithCrit: boolean = isDiceSwapNecessary(critSuccesses, otherRolls, finalCheck);
let sortedRollResults: Array<number>; let sortedRollResults: Array<number>;
@ -96,5 +103,9 @@ export function rollCheckMultipleDice(
}) })
.reduce((a, b) => a + b); .reduce((a, b) => a + b);
return new RollResult(evaluationResult, RollResultStatus.SUCCESS, sortedRollResults); if (usedOptions.useSlayingDice && firstResult <= usedOptions.maxCritSucc) {
return new RollResult(evaluationResult, RollResultStatus.CRITICAL_SUCCESS, sortedRollResults);
} else {
return new RollResult(evaluationResult, RollResultStatus.SUCCESS, sortedRollResults);
}
} }