refactor: improve rule handling
This commit is contained in:
+24
-35
@@ -1,5 +1,5 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { createRule, type RuleContext, type GameContextLike } from '../../src/core/rule';
|
||||
import { createRule, type RuleContext, type RuleEngineHost } from '../../src/core/rule';
|
||||
import { createGameContext } from '../../src/core/context';
|
||||
import type { Command } from '../../src/utils/command';
|
||||
|
||||
@@ -7,6 +7,10 @@ function isCommand(value: Command | RuleContext<unknown>): value is Command {
|
||||
return 'name' in value;
|
||||
}
|
||||
|
||||
function schema(value: string | { name: string; params: any[]; options: any[]; flags: any[] }) {
|
||||
return { type: 'schema' as const, value };
|
||||
}
|
||||
|
||||
describe('Rule System', () => {
|
||||
function createTestGame() {
|
||||
const game = createGameContext();
|
||||
@@ -34,7 +38,7 @@ describe('Rule System', () => {
|
||||
return cmd.params[0];
|
||||
});
|
||||
|
||||
const gen = rule.create.call(game as unknown as GameContextLike, { name: 'test', params: ['card1'], flags: {}, options: {} });
|
||||
const gen = rule.create.call(game as unknown as RuleEngineHost, { name: 'test', params: ['card1'], flags: {}, options: {} });
|
||||
const result = gen.next();
|
||||
expect(result.done).toBe(true);
|
||||
expect(result.value).toBe('card1');
|
||||
@@ -46,7 +50,7 @@ describe('Rule System', () => {
|
||||
const game = createTestGame();
|
||||
|
||||
game.registerRule('move', createRule('<from> <to>', function*(cmd) {
|
||||
yield { name: '', params: [], options: [], flags: [] };
|
||||
yield schema({ name: '', params: [], options: [], flags: [] });
|
||||
return { moved: cmd.params[0] };
|
||||
}));
|
||||
|
||||
@@ -62,7 +66,7 @@ describe('Rule System', () => {
|
||||
const game = createTestGame();
|
||||
|
||||
game.registerRule('move', createRule('<from> <to>', function*(cmd) {
|
||||
const confirm = yield { name: '', params: [], options: [], flags: [] };
|
||||
const confirm = yield schema({ name: '', params: [], options: [], flags: [] });
|
||||
const confirmCmd = isCommand(confirm) ? confirm : undefined;
|
||||
return { moved: cmd.params[0], confirmed: confirmCmd?.name === 'confirm' };
|
||||
}));
|
||||
@@ -115,7 +119,7 @@ describe('Rule System', () => {
|
||||
const game = createTestGame();
|
||||
|
||||
game.registerRule('move', createRule('<from> <to>', function*(cmd) {
|
||||
yield { name: '', params: [], options: [], flags: [] };
|
||||
yield schema({ name: '', params: [], options: [], flags: [] });
|
||||
return { moved: cmd.params[0] };
|
||||
}));
|
||||
|
||||
@@ -138,7 +142,7 @@ describe('Rule System', () => {
|
||||
const game = createTestGame();
|
||||
|
||||
game.registerRule('move', createRule('<from> <to>', function*(cmd) {
|
||||
const response = yield { name: '', params: [], options: [], flags: [] };
|
||||
const response = yield schema({ name: '', params: [], options: [], flags: [] });
|
||||
const rcmd = isCommand(response) ? response : undefined;
|
||||
return { moved: cmd.params[0], response: rcmd?.name };
|
||||
}));
|
||||
@@ -154,7 +158,7 @@ describe('Rule System', () => {
|
||||
const game = createTestGame();
|
||||
|
||||
game.registerRule('move', createRule('<from> <to>', function*(cmd) {
|
||||
const response = yield '<item>';
|
||||
const response = yield schema('<item>');
|
||||
const rcmd = isCommand(response) ? response : undefined;
|
||||
return { response: rcmd?.params[0] };
|
||||
}));
|
||||
@@ -170,7 +174,7 @@ describe('Rule System', () => {
|
||||
const game = createTestGame();
|
||||
|
||||
game.registerRule('trade', createRule('<from> <to>', function*(cmd) {
|
||||
const response = yield '<item> [amount: number]';
|
||||
const response = yield schema('<item> [amount: number]');
|
||||
const rcmd = isCommand(response) ? response : undefined;
|
||||
return { traded: rcmd?.params[0] };
|
||||
}));
|
||||
@@ -188,12 +192,12 @@ describe('Rule System', () => {
|
||||
const game = createTestGame();
|
||||
|
||||
game.registerRule('parent', createRule('<action>', function*() {
|
||||
yield { name: '', params: [], options: [], flags: [] };
|
||||
yield schema({ name: '', params: [], options: [], flags: [] });
|
||||
return 'parent done';
|
||||
}));
|
||||
|
||||
game.registerRule('child', createRule('<target>', function*() {
|
||||
yield { name: '', params: [], options: [], flags: [] };
|
||||
yield schema({ name: '', params: [], options: [], flags: [] });
|
||||
return 'child done';
|
||||
}));
|
||||
|
||||
@@ -212,7 +216,7 @@ describe('Rule System', () => {
|
||||
const game = createTestGame();
|
||||
|
||||
game.registerRule('parent', createRule('<action>', function*() {
|
||||
yield 'child_cmd';
|
||||
yield schema('child_cmd');
|
||||
return 'parent done';
|
||||
}));
|
||||
|
||||
@@ -236,7 +240,7 @@ describe('Rule System', () => {
|
||||
const game = createTestGame();
|
||||
|
||||
game.registerRule('parent', createRule('<action>', function*() {
|
||||
yield 'child_a | child_b';
|
||||
yield schema('child_a | child_b');
|
||||
return 'parent done';
|
||||
}));
|
||||
|
||||
@@ -270,7 +274,7 @@ describe('Rule System', () => {
|
||||
const game = createTestGame();
|
||||
|
||||
game.registerRule('test', createRule('<arg>', function*() {
|
||||
yield { name: '', params: [], options: [], flags: [] };
|
||||
yield schema({ name: '', params: [], options: [], flags: [] });
|
||||
return 'done';
|
||||
}));
|
||||
|
||||
@@ -281,21 +285,6 @@ describe('Rule System', () => {
|
||||
expect(game.ruleContexts.value.length).toBe(1);
|
||||
expect(game.ruleContexts.value[0].state).toBe('yielded');
|
||||
});
|
||||
|
||||
it('should add context to the context stack', () => {
|
||||
const game = createTestGame();
|
||||
|
||||
game.registerRule('test', createRule('<arg>', function*() {
|
||||
yield { name: '', params: [], options: [], flags: [] };
|
||||
return 'done';
|
||||
}));
|
||||
|
||||
const initialStackLength = game.contexts.value.length;
|
||||
|
||||
game.dispatchCommand('test arg1');
|
||||
|
||||
expect(game.contexts.value.length).toBe(initialStackLength + 1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('error handling', () => {
|
||||
@@ -315,7 +304,7 @@ describe('Rule System', () => {
|
||||
const game = createTestGame();
|
||||
|
||||
game.registerRule('parent', createRule('<action>', function*() {
|
||||
yield 'child';
|
||||
yield schema('child');
|
||||
return 'parent done';
|
||||
}));
|
||||
|
||||
@@ -342,7 +331,7 @@ describe('Rule System', () => {
|
||||
};
|
||||
|
||||
game.registerRule('test', createRule('<arg>', function*() {
|
||||
const cmd = yield customSchema;
|
||||
const cmd = yield schema(customSchema);
|
||||
const rcmd = isCommand(cmd) ? cmd : undefined;
|
||||
return { received: rcmd?.params[0] };
|
||||
}));
|
||||
@@ -358,8 +347,8 @@ describe('Rule System', () => {
|
||||
const game = createTestGame();
|
||||
|
||||
game.registerRule('multi', createRule('<start>', function*() {
|
||||
const a = yield '<value>';
|
||||
const b = yield '<value>';
|
||||
const a = yield schema('<value>');
|
||||
const b = yield schema('<value>');
|
||||
const acmd = isCommand(a) ? a : undefined;
|
||||
const bcmd = isCommand(b) ? b : undefined;
|
||||
return { a: acmd?.params[0], b: bcmd?.params[0] };
|
||||
@@ -380,13 +369,13 @@ describe('Rule System', () => {
|
||||
|
||||
game.registerRule('start', createRule('<player>', function*(cmd) {
|
||||
const player = cmd.params[0];
|
||||
const action = yield { name: '', params: [], options: [], flags: [] };
|
||||
const action = yield schema({ name: '', params: [], options: [], flags: [] });
|
||||
|
||||
if (isCommand(action)) {
|
||||
if (action.name === 'move') {
|
||||
yield '<target>';
|
||||
yield schema('<target>');
|
||||
} else if (action.name === 'attack') {
|
||||
yield '<target> [--power: number]';
|
||||
yield schema('<target> [--power: number]');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user