Implement swapping edge case, restructure sources.

This commit is contained in:
Oliver Rümpelein 2021-01-02 16:12:16 +01:00
parent 3f6f9f795f
commit 55beeb92c9
5 changed files with 173 additions and 76 deletions

View file

@ -0,0 +1,28 @@
export interface RollOptions {
maxCritSucc: number;
minCritFail: number;
useSlayingDice: boolean;
slayingDiceRepetition: boolean;
}
export class DefaultRollOptions implements RollOptions {
public maxCritSucc = 1;
public minCritFail = 20;
public useSlayingDice = false;
public slayingDiceRepetition = false;
mergeWith(other: Partial<RollOptions>): RollOptions {
return { ...this, ...other } as RollOptions;
}
}
export class RollResult {
constructor(public value: number, public status: RollResultStatus, public dice: Array<number>) {}
}
export enum RollResultStatus {
FAILURE,
SUCCESS,
CRITICAL_FAILURE,
CRITICAL_SUCCESS,
}

View file

@ -1,4 +1,6 @@
import { DefaultRollOptions, RollOptions, RollResult, RollResultStatus } from "./roll-data";
import { DS4RollProvider, RollProvider } from "./roll-provider";
import { isDiceSwapNecessary, isSlayingDiceRepetition } from "./roll-utils";
export function ds4test(testValue: number, rollOptions: Partial<RollOptions> = {}): RollResult {
const finalRollValue = testValue;
@ -20,7 +22,7 @@ export function rollCheckSingleDie(
if (roll <= usedOptions.maxCritSucc) {
return new RollResult(testValue, RollResultStatus.CRITICAL_SUCCESS, dice);
} else if (roll >= usedOptions.minCritFail) {
} else if (roll >= usedOptions.minCritFail && !isSlayingDiceRepetition(usedOptions)) {
return new RollResult(0, RollResultStatus.CRITICAL_FAILURE, dice);
} else {
if (roll <= testValue) {
@ -44,7 +46,8 @@ export function rollCheckMultipleDice(
const firstResult = dice[0];
if (firstResult >= usedOptions.minCritFail) {
// Slaying Dice require a different handling.
if (firstResult >= usedOptions.minCritFail && !isSlayingDiceRepetition(usedOptions)) {
return new RollResult(0, RollResultStatus.CRITICAL_FAILURE, dice);
}
@ -61,13 +64,22 @@ export function rollCheckMultipleDice(
.reduce(partitionCallback, [[], []])
.map((a) => a.sort((r1, r2) => r2 - r1));
const sortedRollResults: Array<number> = critSuccesses.concat(otherRolls);
const swapLastWithCrit: boolean = isDiceSwapNecessary(critSuccesses, otherRolls, finalCheck);
let sortedRollResults: Array<number>;
if (swapLastWithCrit) {
const diceToMove = critSuccesses[0];
const remainingSuccesses = critSuccesses.slice(1);
sortedRollResults = remainingSuccesses.concat(otherRolls).concat([diceToMove]);
} else {
sortedRollResults = critSuccesses.concat(otherRolls);
}
const evaluationResult = sortedRollResults
.map((value, index) => {
if (index == numberOfDice - 1) {
console.log(`Last dice: ${value}, checking against ${finalCheck}`);
if (value == 1) {
if (value <= usedOptions.maxCritSucc) {
return finalCheck;
} else if (value <= finalCheck) {
return value;
@ -86,32 +98,3 @@ export function rollCheckMultipleDice(
return new RollResult(evaluationResult, RollResultStatus.SUCCESS, sortedRollResults);
}
export interface RollOptions {
maxCritSucc: number;
minCritFail: number;
useSlayingDice: boolean;
slayingDiceRepetition: boolean;
}
class DefaultRollOptions implements RollOptions {
public maxCritSucc = 1;
public minCritFail = 20;
public useSlayingDice = false;
public slayingDiceRepetition = false;
mergeWith(other: Partial<RollOptions>): RollOptions {
return { ...this, ...other } as RollOptions;
}
}
export class RollResult {
constructor(public value: number, public status: RollResultStatus, public dice: Array<number>) {}
}
export enum RollResultStatus {
FAILURE,
SUCCESS,
CRITICAL_FAILURE,
CRITICAL_SUCCESS,
}

View file

@ -0,0 +1,22 @@
import { RollOptions } from "./roll-data";
export function isDiceSwapNecessary(
critSuccesses: Array<number>,
otherRolls: Array<number>,
finalRollValue: number,
): boolean {
if (critSuccesses.length == 0 || otherRolls.length == 0) {
return false;
}
const amountOfOtherRolls = otherRolls.length;
const lastDice = otherRolls[amountOfOtherRolls - 1];
if (lastDice <= finalRollValue) {
return false;
}
return lastDice + finalRollValue > 20;
}
export function isSlayingDiceRepetition(opts: RollOptions): boolean {
return opts.useSlayingDice && opts.slayingDiceRepetition;
}