Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cs and cf with default comparison. A way to add default values in the modifier class. #288

Merged
merged 3 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 0 additions & 15 deletions src/dice/StandardDice.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { RequiredArgumentError } from '../exceptions/index.js';
import { isNumeric, isSafeNumber } from '../utilities/math.js';
import { generator } from '../utilities/NumberGenerator.js';
import ComparePoint from '../ComparePoint.js';
import ExplodeModifier from '../modifiers/ExplodeModifier.js';
import HasDescription from '../traits/HasDescription.js';
import Modifier from '../modifiers/Modifier.js';
import RollResult from '../results/RollResult.js';
import RollResults from '../results/RollResults.js';
import ReRollModifier from '../modifiers/ReRollModifier.js';

const modifiersSymbol = Symbol('modifiers');
const qtySymbol = Symbol('qty');
Expand Down Expand Up @@ -131,18 +128,6 @@ class StandardDice extends HasDescription {
}

this[modifiersSymbol] = modifiers;

// loop through each modifier and ensure that those that require it have compare points
// @todo find a better way of defining compare point on modifiers that don't have them
/* eslint-disable no-param-reassign */
this[modifiersSymbol].forEach((modifier) => {
if ((modifier instanceof ExplodeModifier) && !modifier.comparePoint) {
modifier.comparePoint = new ComparePoint('=', this.max);
} else if ((modifier instanceof ReRollModifier) && !modifier.comparePoint) {
modifier.comparePoint = new ComparePoint('=', this.min);
}
});
/* eslint-enable */
}

/**
Expand Down
30 changes: 30 additions & 0 deletions src/modifiers/ComparisonModifier.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,36 @@ class ComparisonModifier extends Modifier {
return `${this.comparePoint || ''}`;
}

/* eslint-disable class-methods-use-this */
/**
* Empty default compare point definition
*
* @param {StandardDice|RollGroup} _context The object that the modifier is attached to
*
* @returns {null}
*/
defaultComparePoint(_context) {
return {};
}
/* eslint-enable class-methods-use-this */

/**
* Eases processing of simple "compare point only" defaults
*
* @param {StandardDice|RollGroup} _context The object that the modifier is attached to
*
* @returns {object}
*/
defaults(_context) {
const comparePointConfig = this.defaultComparePoint(_context);

if (typeof comparePointConfig === 'object' && comparePointConfig.length === 2) {
return { comparePoint: new ComparePoint(...comparePointConfig) };
}

return {};
}

/**
* Check whether value matches the compare point or not.
*
Expand Down
15 changes: 15 additions & 0 deletions src/modifiers/CriticalFailureModifier.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,19 @@ class CriticalFailureModifier extends ComparisonModifier {
return `cf${super.notation}`;
}

/* eslint-disable class-methods-use-this */
/**
* The default compare point definition
*
* @param {StandardDice|RollGroup} _context The object that the modifier is attached to
*
* @returns {array}
*/
defaultComparePoint(_context) {
return ['=', _context.min];
}
/* eslint-enable class-methods-use-this */

/**
* Run the modifier on the results.
*
Expand All @@ -58,6 +71,8 @@ class CriticalFailureModifier extends ComparisonModifier {
* @returns {RollResults} The modified results
*/
run(results, _context) {
super.run(results, _context);

results.rolls
.forEach((roll) => {
// add the modifier flag
Expand Down
15 changes: 15 additions & 0 deletions src/modifiers/CriticalSuccessModifier.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,19 @@ class CriticalSuccessModifier extends ComparisonModifier {
return `cs${super.notation}`;
}

/* eslint-disable class-methods-use-this */
/**
* The default compare point definition
*
* @param {StandardDice|RollGroup} _context The object that the modifier is attached to
*
* @returns {array}
*/
defaultComparePoint(_context) {
return ['=', _context.max];
}
/* eslint-enable class-methods-use-this */

/**
* Runs the modifier on the rolls.
*
Expand All @@ -58,6 +71,8 @@ class CriticalSuccessModifier extends ComparisonModifier {
* @returns {RollResults}
*/
run(results, _context) {
super.run(results, _context);

// loop through each roll and see if it's a critical success
results.rolls
.forEach((roll) => {
Expand Down
15 changes: 15 additions & 0 deletions src/modifiers/ExplodeModifier.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,19 @@ class ExplodeModifier extends ComparisonModifier {
return this[penetrateSymbol];
}

/* eslint-disable class-methods-use-this */
/**
* The default compare point definition
*
* @param {StandardDice|RollGroup} _context The object that the modifier is attached to
*
* @returns {array}
*/
defaultComparePoint(_context) {
return ['=', _context.max];
}
/* eslint-enable class-methods-use-this */

/**
* Run the modifier on the results.
*
Expand All @@ -83,6 +96,8 @@ class ExplodeModifier extends ComparisonModifier {
* @returns {RollResults} The modified results
*/
run(results, _context) {
super.run(results, _context);

// ensure that the dice can explode without going into an infinite loop
if (_context.min === _context.max) {
throw new DieActionValueError(_context, 'explode');
Expand Down
27 changes: 27 additions & 0 deletions src/modifiers/Modifier.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,34 @@ class Modifier {
get maxIterations() {
return 1000;
}

/**
* No default values present
*
* @param {StandardDice|RollGroup} _context The object that the modifier is attached to
*
* @returns {object}
*/
defaults(_context) {
return {};
}
/* eslint-enable class-methods-use-this */

/**
* Processing default values definitions
*
* @param {StandardDice|RollGroup} _context The object that the modifier is attached to
*
* @returns {void}
*/
useDefaultsIfNeeded(_context) {
Object.entries(this.defaults(_context)).forEach(([field, value]) => {
if (typeof this[field] === 'undefined') {
this[field] = value;
}
});
}

/* eslint-disable class-methods-use-this */
/**
* Run the modifier on the results.
Expand All @@ -62,6 +88,7 @@ class Modifier {
* @returns {RollResults} The modified results
*/
run(results, _context) {
this.useDefaultsIfNeeded(_context);
return results;
}
/* eslint-enable class-methods-use-this */
Expand Down
15 changes: 15 additions & 0 deletions src/modifiers/ReRollModifier.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,19 @@ class ReRollModifier extends ComparisonModifier {
this[onceSymbol] = !!value;
}

/* eslint-disable class-methods-use-this */
/**
* The default compare point definition
*
* @param {StandardDice|RollGroup} _context The object that the modifier is attached to
*
* @returns {array}
*/
defaultComparePoint(_context) {
return ['=', _context.min];
}
/* eslint-enable class-methods-use-this */

/**
* Run the modifier on the results.
*
Expand All @@ -78,6 +91,8 @@ class ReRollModifier extends ComparisonModifier {
* @returns {RollResults} The modified results
*/
run(results, _context) {
super.run(results, _context);

// ensure that the dice can explode without going into an infinite loop
if (_context.min === _context.max) {
throw new DieActionValueError(_context, 're-roll');
Expand Down
4 changes: 2 additions & 2 deletions src/parser/grammars/grammar.pegjs
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,13 @@ UniqueModifier

// Critical success setting
CriticalSuccessModifier
= "cs" comparePoint:ComparePoint {
= "cs" comparePoint:ComparePoint? {
return new Modifiers.CriticalSuccessModifier(comparePoint);
}

// Critical failure setting
CriticalFailureModifier
= "cf" comparePoint:ComparePoint {
= "cf" comparePoint:ComparePoint? {
return new Modifiers.CriticalFailureModifier(comparePoint);
}

Expand Down
33 changes: 30 additions & 3 deletions tests/modifiers/ComparisonModifier.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,13 +154,40 @@ describe('ComparisonModifier', () => {
});

describe('Run', () => {
const results = new RollResults();
const die = new StandardDice(6, 2);
let mod;

beforeEach(() => {
mod = new ComparisonModifier();
});

test('returns RollResults object', () => {
const results = new RollResults();
const die = new StandardDice(6, 2);
const mod = new ComparisonModifier(new ComparePoint('=', 4));
mod.comparePoint = new ComparePoint('=', 4);

expect(mod.run(results, die)).toBe(results);
});

describe('Defaults', () => {
const testOperator = '=';
const testValue = 6;

beforeEach(() => {
mod.defaultComparePoint = () => [testOperator, testValue];
});

test('uses default comparison modifier', () => {
mod.run(results, die);
expect(mod.comparePoint.operator).toEqual(testOperator);
expect(mod.comparePoint.value).toEqual(testValue);
});

test('does not set default comparison modifier if value was provided', () => {
mod.comparePoint = new ComparePoint('=', 4);

expect(mod.run(results, die)).toBe(results);
});
});
});

describe('Readonly properties', () => {
Expand Down
14 changes: 11 additions & 3 deletions tests/modifiers/ExplodeModifier.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -224,12 +224,12 @@ describe('ExplodeModifier', () => {
expect(mod.run(results, die)).toBe(results);
});

test('does not explode without compare point', () => {
test('can explode with default compare point', () => {
const modifiedResults = mod.run(results, die).rolls;

// assert that all the rolls exist
expect(modifiedResults).toBeInstanceOf(Array);
expect(modifiedResults).toHaveLength(6);
expect(modifiedResults).toHaveLength(8);

expect(modifiedResults[0].initialValue).toBe(8);
expect(modifiedResults[0].value).toBe(8);
Expand All @@ -253,7 +253,15 @@ describe('ExplodeModifier', () => {

expect(modifiedResults[5].initialValue).toBe(10);
expect(modifiedResults[5].value).toBe(10);
expect(modifiedResults[5].modifiers).toEqual(new Set());
expect(modifiedResults[5].modifiers).toEqual(new Set(['explode']));

expect(modifiedResults[6].initialValue).toBe(10);
expect(modifiedResults[6].value).toBe(10);
expect(modifiedResults[6].modifiers).toEqual(new Set(['explode']));

expect(modifiedResults[7].initialValue).toBe(2);
expect(modifiedResults[7].value).toBe(2);
expect(modifiedResults[7].modifiers).toEqual(new Set());
});

test('can explode with compare point `>=8`', () => {
Expand Down
22 changes: 22 additions & 0 deletions tests/modifiers/Modifier.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,28 @@ describe('Modifier', () => {
test('returns RollResults object', () => {
expect(mod.run(results, die)).toBe(results);
});

describe('Defaults', () => {
const testKey = 'testKey';
const defaultValue = 'defaultValue';

beforeEach(() => {
mod.defaults = () => ({ testKey: defaultValue });
});

test('uses default if value wasn\'t provided', () => {
mod.run(results, die);
expect(mod[testKey]).toEqual(defaultValue);
});

test('does not set default if value was provided', () => {
const providedValue = 'providedValue';
mod[testKey] = providedValue;

mod.run(results, die);
expect(mod[testKey]).toEqual(providedValue);
});
});
});
});
});
6 changes: 3 additions & 3 deletions tests/modifiers/ReRollModifier.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ describe('ReRollModifier', () => {
expect(mod.run(results, die)).toBe(results);
});

test('does not re-roll without compare point', () => {
test('does re-roll with default compare point', () => {
const modifiedResults = mod.run(results, die).rolls;

expect(modifiedResults).toBeInstanceOf(Array);
Expand All @@ -201,8 +201,8 @@ describe('ReRollModifier', () => {
expect(modifiedResults[2].modifiers).toEqual(new Set());

expect(modifiedResults[3].initialValue).toBe(1);
expect(modifiedResults[3].value).toBe(1);
expect(modifiedResults[3].modifiers).toEqual(new Set());
expect(modifiedResults[3].value).toBe(10);
expect(modifiedResults[3].modifiers).toEqual(new Set(new Set(['re-roll'])));

expect(modifiedResults[4].initialValue).toBe(6);
expect(modifiedResults[4].value).toBe(6);
Expand Down
Loading