From 8ec95cbf8146ca87d181e67fa8da12d139c271dd Mon Sep 17 00:00:00 2001 From: hypercross Date: Thu, 23 Apr 2026 00:35:28 +0800 Subject: [PATCH] refactor: rename 'user' target to 'source' in slay-the-spire-like Updates the card effect and intent target types from 'user' to 'source' within the desert data files and combat effect system to maintain consistency. Also reformat command tests to use 2-space indentation. --- .../data/desert/cardEffect.csv | 50 ++-- .../data/desert/cardEffect.csv.d.ts | 2 +- .../data/desert/intent.csv | 48 +-- .../data/desert/intent.csv.d.ts | 2 +- .../system/combat/effects.ts | 2 +- tests/utils/command.test.ts | 280 +++++++++--------- 6 files changed, 193 insertions(+), 191 deletions(-) diff --git a/src/samples/slay-the-spire-like/data/desert/cardEffect.csv b/src/samples/slay-the-spire-like/data/desert/cardEffect.csv index b8cad23..a5193d4 100644 --- a/src/samples/slay-the-spire-like/data/desert/cardEffect.csv +++ b/src/samples/slay-the-spire-like/data/desert/cardEffect.csv @@ -1,5 +1,5 @@ # type CardEffectTrigger = 'onPlay' | 'onDraw' | 'onDiscard' -# type CardEffectTarget = 'user' | 'eachTarget' | 'eachEnemy' | 'randomEnemy' | 'player' +# type CardEffectTarget = 'source' | 'eachTarget' | 'eachEnemy' | 'randomEnemy' | 'player' # type CardEffectList = [effect: @effect; stacks: number][] id,card,trigger,target,effects @@ -9,28 +9,28 @@ greataxe,greataxe,onPlay,eachTarget,[attack;5] spear,spear,onPlay,eachTarget,[attack;2];[attack;2];[attack;2] dagger,dagger,onPlay,eachTarget,[attack;3];[attack;3] dart,dart,onPlay,eachTarget,[attack;1] -dart-draw,dart,onPlay,user,[draw;1] +dart-draw,dart,onPlay,source,[draw;1] crossbow,crossbow,onPlay,eachTarget,[attack;6] -crossbow-combo,crossbow,onPlay,user,[crossbow;0] -shield,shield,onPlay,user,[defend;3] -hat,hat,onPlay,user,[defend;8] -cape,cape,onPlay,user,[defend;2];[defendNext;2] -bracer,bracer,onPlay,user,[defend;1];[draw;1] -greatshield,greatshield,onPlay,user,[defend;5] -chainmail,chainmail,onPlay,user,[damageReduce;3] -bandage,bandage,onPlay,user,[removeWound;1] -poisonPotion,poisonPotion,onPlay,user,[attackBuff;2] -fortifyPotion,fortifyPotion,onPlay,user,[defendBuff;2] -vitalityPotion,vitalityPotion,onPlay,user,[gainEnergy;1] -focusPotion,focusPotion,onPlay,user,[draw;2] -healingPotion,healingPotion,onPlay,user,[removeWound;3] -waterBag,waterBag,onPlay,user,[energyNext;1];[drawNext;2] -rope,rope,onPlay,user,[defendBuffUntilPlay;2] -belt,belt,onPlay,user,[drawChoice;1] -torch,torch,onPlay,user,[burnForEnergy;1] -whetstone,whetstone,onPlay,user,[attackBuffUntilPlay;3] -blacksmithHammer,blacksmithHammer,onPlay,user,[transformRandom;1] -venom,venom,onDiscard,user,[attack;3] -curse,curse,onDraw,user,[curse;1] -static,static,onDraw,user,[static;1] -vultureEye,vultureEye,onDraw,user,[expose;3] +crossbow-combo,crossbow,onPlay,source,[crossbow;0] +shield,shield,onPlay,source,[defend;3] +hat,hat,onPlay,source,[defend;8] +cape,cape,onPlay,source,[defend;2];[defendNext;2] +bracer,bracer,onPlay,source,[defend;1];[draw;1] +greatshield,greatshield,onPlay,source,[defend;5] +chainmail,chainmail,onPlay,source,[damageReduce;3] +bandage,bandage,onPlay,source,[removeWound;1] +poisonPotion,poisonPotion,onPlay,source,[attackBuff;2] +fortifyPotion,fortifyPotion,onPlay,source,[defendBuff;2] +vitalityPotion,vitalityPotion,onPlay,source,[gainEnergy;1] +focusPotion,focusPotion,onPlay,source,[draw;2] +healingPotion,healingPotion,onPlay,source,[removeWound;3] +waterBag,waterBag,onPlay,source,[energyNext;1];[drawNext;2] +rope,rope,onPlay,source,[defendBuffUntilPlay;2] +belt,belt,onPlay,source,[drawChoice;1] +torch,torch,onPlay,source,[burnForEnergy;1] +whetstone,whetstone,onPlay,source,[attackBuffUntilPlay;3] +blacksmithHammer,blacksmithHammer,onPlay,source,[transformRandom;1] +venom,venom,onDiscard,source,[attack;3] +curse,curse,onDraw,source,[curse;1] +static,static,onDraw,source,[static;1] +vultureEye,vultureEye,onDraw,source,[expose;3] diff --git a/src/samples/slay-the-spire-like/data/desert/cardEffect.csv.d.ts b/src/samples/slay-the-spire-like/data/desert/cardEffect.csv.d.ts index 72f7e92..19a7794 100644 --- a/src/samples/slay-the-spire-like/data/desert/cardEffect.csv.d.ts +++ b/src/samples/slay-the-spire-like/data/desert/cardEffect.csv.d.ts @@ -2,7 +2,7 @@ import type { Card } from './card.csv'; import type { Effect } from './effect.csv'; export type CardEffectTrigger = 'onPlay' | 'onDraw' | 'onDiscard'; -export type CardEffectTarget = 'user' | 'eachTarget' | 'eachEnemy' | 'randomEnemy' | 'player'; +export type CardEffectTarget = 'source' | 'eachTarget' | 'eachEnemy' | 'randomEnemy' | 'player'; export type CardEffectList = [effect: Effect, stacks: number][]; type CardEffectTable = readonly { diff --git a/src/samples/slay-the-spire-like/data/desert/intent.csv b/src/samples/slay-the-spire-like/data/desert/intent.csv index 422ac3c..f3bd4ec 100644 --- a/src/samples/slay-the-spire-like/data/desert/intent.csv +++ b/src/samples/slay-the-spire-like/data/desert/intent.csv @@ -6,50 +6,50 @@ # initBuffs: initial buffs for this intent (applied when intent becomes active) # effects: effects executed when this intent is active -# type IntentEffectTarget = 'user' | 'eachEnemy' | 'randomEnemy' | 'player' +# type IntentEffectTarget = 'source' | 'eachEnemy' | 'randomEnemy' | 'player' # type IntentEffect = [IntentEffectTarget;@effect;number] # type IntentEffectList = IntentEffect[] id,enemy,initialIntent,nextIntents,brokenIntent,effects string,@enemy,boolean,@intent[],@intent[],IntentEffectList -仙人掌怪-boost,仙人掌怪,true,仙人掌怪-boost;仙人掌怪-defend,,[user;spike;1];[user;defend;4] -仙人掌怪-defend,仙人掌怪,false,仙人掌怪-attack,,[user;defend;8] +仙人掌怪-boost,仙人掌怪,true,仙人掌怪-boost;仙人掌怪-defend,,[source;spike;1];[source;defend;4] +仙人掌怪-defend,仙人掌怪,false,仙人掌怪-attack,,[source;defend;8] 仙人掌怪-attack,仙人掌怪,false,仙人掌怪-boost,,[player;attack;5] 蛇-poison,蛇,true,蛇-attack;蛇-attack,,[player;venom;1];[player;attack;4] 蛇-attack,蛇,false,蛇-poison;蛇-boost,,[player;attack;6] -蛇-boost,蛇,false,蛇-poison;蛇-attack,,[user;defend;3];[player;venom;1] +蛇-boost,蛇,false,蛇-poison;蛇-attack,,[source;defend;3];[player;venom;1] 木乃伊-attack,木乃伊,true,木乃伊-defend;木乃伊-curse,,[player;attack;6] -木乃伊-defend,木乃伊,false,木乃伊-attack,,[user;defend;6] +木乃伊-defend,木乃伊,false,木乃伊-attack,,[source;defend;6] 木乃伊-curse,木乃伊,false,木乃伊-defend;木乃伊-attack,木乃伊-attack,[player;curse;1] -枪手-aim,枪手,true,枪手-attack,,[user;aim;2] +枪手-aim,枪手,true,枪手-attack,,[source;aim;2] 枪手-attack,枪手,false,枪手-aim;枪手-defend,枪手-aim,[player;attack;8] -枪手-defend,枪手,false,枪手-aim,枪手-aim,[user;defend;5] -风卷草-boost,风卷草,true,风卷草-defend;风卷草-defend;风卷草-boost,,[user;roll;5];[user;defend;4] -风卷草-defend,风卷草,false,风卷草-boost;风卷草-attack,,[user;defend;8] +枪手-defend,枪手,false,枪手-aim,枪手-aim,[source;defend;5] +风卷草-boost,风卷草,true,风卷草-defend;风卷草-defend;风卷草-boost,,[source;roll;5];[source;defend;4] +风卷草-defend,风卷草,false,风卷草-boost;风卷草-attack,,[source;defend;8] 风卷草-attack,风卷草,false,风卷草-boost,,[player;rollDamage;0] 秃鹫-attack,秃鹫,true,秃鹫-defend;秃鹫-defend,,[player;attack;6];[player;vultureEye;1] -秃鹫-defend,秃鹫,false,秃鹫-attack;秃鹫-attack,,[user;defend;5] -沙蝎-boost,沙蝎,true,沙蝎-attack;沙蝎-attack,,[user;tailSting;2] +秃鹫-defend,秃鹫,false,秃鹫-attack;秃鹫-attack,,[source;defend;5] +沙蝎-boost,沙蝎,true,沙蝎-attack;沙蝎-attack,,[source;tailSting;2] 沙蝎-attack,沙蝎,false,沙蝎-boost;沙蝎-attack,,[player;attack;6] -幼沙虫-defend,幼沙虫,true,幼沙虫-defend;幼沙虫-boost,,[user;defend;6] -幼沙虫-boost,幼沙虫,false,幼沙虫-attack;幼沙虫-defend,,[user;energyDrain;1];[user;defend;4] +幼沙虫-defend,幼沙虫,true,幼沙虫-defend;幼沙虫-boost,,[source;defend;6] +幼沙虫-boost,幼沙虫,false,幼沙虫-attack;幼沙虫-defend,,[source;energyDrain;1];[source;defend;4] 幼沙虫-attack,幼沙虫,false,幼沙虫-defend;幼沙虫-defend,,[player;attack;5] 蜥蜴-attack,蜥蜴,true,蜥蜴-defend;蜥蜴-molt,,[player;attack;5] -蜥蜴-defend,蜥蜴,false,蜥蜴-attack;蜥蜴-attack,,[user;defend;6] -蜥蜴-molt,蜥蜴,false,蜥蜴-defend;蜥蜴-attack,,[user;molt;3] +蜥蜴-defend,蜥蜴,false,蜥蜴-attack;蜥蜴-attack,,[source;defend;6] +蜥蜴-molt,蜥蜴,false,蜥蜴-defend;蜥蜴-attack,,[source;molt;3] 沙匪-attack,沙匪,true,沙匪-attack;沙匪-heavyAttack,,[player;attack;6] 沙匪-heavyAttack,沙匪,false,沙匪-attack;沙匪-attack;沙匪-debuff,,[player;attack;10] 沙匪-debuff,沙匪,false,沙匪-attack;沙匪-attack,,[player;discard;1] -风暴之灵-storm,风暴之灵,true,风暴之灵-attack;风暴之灵-storm,,[user;storm;2];[user;defend;3] +风暴之灵-storm,风暴之灵,true,风暴之灵-attack;风暴之灵-storm,,[source;storm;2];[source;defend;3] 风暴之灵-attack,风暴之灵,false,风暴之灵-storm;风暴之灵-defend,,[player;attack;8];[player;static;1] -风暴之灵-defend,风暴之灵,false,风暴之灵-storm;风暴之灵-attack,,[user;defend;8] -骑马枪手-charge,骑马枪手,true,骑马枪手-attack,,[user;charge;2] +风暴之灵-defend,风暴之灵,false,风暴之灵-storm;风暴之灵-attack,,[source;defend;8] +骑马枪手-charge,骑马枪手,true,骑马枪手-attack,,[source;charge;2] 骑马枪手-attack,骑马枪手,false,骑马枪手-charge;骑马枪手-defend,骑马枪手-charge,[player;attack;6] -骑马枪手-defend,骑马枪手,false,骑马枪手-charge;骑马枪手-attack,骑马枪手-charge,[user;defend;5] -沙虫王-summon,沙虫王,true,沙虫王-attack;沙虫王-defend,,[user;summonSandwormLarva;18] +骑马枪手-defend,骑马枪手,false,骑马枪手-charge;骑马枪手-attack,骑马枪手-charge,[source;defend;5] +沙虫王-summon,沙虫王,true,沙虫王-attack;沙虫王-defend,,[source;summonSandwormLarva;18] 沙虫王-attack,沙虫王,false,沙虫王-summon;沙虫王-defend,,[player;attack;9] -沙虫王-defend,沙虫王,false,沙虫王-attack;沙虫王-summon,,[user;defend;6] -沙漠守卫-summon,沙漠守卫,true,沙漠守卫-attack;沙漠守卫-defend,,[user;summonMummy;14] +沙虫王-defend,沙虫王,false,沙虫王-attack;沙虫王-summon,,[source;defend;6] +沙漠守卫-summon,沙漠守卫,true,沙漠守卫-attack;沙漠守卫-defend,,[source;summonMummy;14] 沙漠守卫-attack,沙漠守卫,false,沙漠守卫-defend;沙漠守卫-summon,,[player;attack;8] -沙漠守卫-defend,沙漠守卫,false,沙漠守卫-attack;沙漠守卫-revive,,[user;defend;8] -沙漠守卫-revive,沙漠守卫,false,沙漠守卫-attack;沙漠守卫-summon,,[user;reviveMummy;1] +沙漠守卫-defend,沙漠守卫,false,沙漠守卫-attack;沙漠守卫-revive,,[source;defend;8] +沙漠守卫-revive,沙漠守卫,false,沙漠守卫-attack;沙漠守卫-summon,,[source;reviveMummy;1] diff --git a/src/samples/slay-the-spire-like/data/desert/intent.csv.d.ts b/src/samples/slay-the-spire-like/data/desert/intent.csv.d.ts index 52143e0..a0b4c77 100644 --- a/src/samples/slay-the-spire-like/data/desert/intent.csv.d.ts +++ b/src/samples/slay-the-spire-like/data/desert/intent.csv.d.ts @@ -1,7 +1,7 @@ import type { Enemy } from './enemy.csv'; import type { Effect } from './effect.csv'; -export type IntentEffectTarget = 'user' | 'eachEnemy' | 'randomEnemy' | 'player'; +export type IntentEffectTarget = 'source' | 'eachEnemy' | 'randomEnemy' | 'player'; export type IntentEffect = [IntentEffectTarget, Effect, number]; export type IntentEffectList = IntentEffect[]; diff --git a/src/samples/slay-the-spire-like/system/combat/effects.ts b/src/samples/slay-the-spire-like/system/combat/effects.ts index dc98a8d..574cc60 100644 --- a/src/samples/slay-the-spire-like/system/combat/effects.ts +++ b/src/samples/slay-the-spire-like/system/combat/effects.ts @@ -112,7 +112,7 @@ export function* getEffectTargets( for (const enemy of getAliveEnemies(game.value)) { yield enemy; } - } else if (target === "user") { + } else if (target === "source") { const entity = getCombatEntity(game.value, sourceEntityKey); if (entity) yield entity; } else if (target === "player") { diff --git a/tests/utils/command.test.ts b/tests/utils/command.test.ts index 9037e2d..3ef1ea2 100644 --- a/tests/utils/command.test.ts +++ b/tests/utils/command.test.ts @@ -1,174 +1,176 @@ -import { describe, it, expect } from 'vitest'; -import { parseCommand, type Command } from '@/utils/command'; +import { describe, it, expect } from "vitest"; +import { parseCommand, type Command } from "@/utils/command"; -describe('parseCommand', () => { - it('should parse empty string', () => { - const result = parseCommand(''); - expect(result).toEqual({ - name: '', - flags: {}, - options: {}, - params: [] - }); +describe("parseCommand", () => { + it("should parse empty string", () => { + const result = parseCommand(""); + expect(result).toEqual({ + name: "", + flags: {}, + options: {}, + params: [], }); + }); - it('should parse command name only', () => { - const result = parseCommand('move'); - expect(result).toEqual({ - name: 'move', - flags: {}, - options: {}, - params: [] - }); + it("should parse command name only", () => { + const result = parseCommand("move"); + expect(result).toEqual({ + name: "move", + flags: {}, + options: {}, + params: [], }); + }); - it('should parse command with params', () => { - const result = parseCommand('move meeple1 region1'); - expect(result).toEqual({ - name: 'move', - flags: {}, - options: {}, - params: ['meeple1', 'region1'] - }); + it("should parse command with params", () => { + const result = parseCommand("move meeple1 region1"); + expect(result).toEqual({ + name: "move", + flags: {}, + options: {}, + params: ["meeple1", "region1"], }); + }); - it('should parse command with long flags', () => { - const result = parseCommand('move meeple1 --force --quiet'); - expect(result).toEqual({ - name: 'move', - flags: { force: true, quiet: true }, - options: {}, - params: ['meeple1'] - }); + it("should parse command with long flags", () => { + const result = parseCommand("move meeple1 --force --quiet"); + expect(result).toEqual({ + name: "move", + flags: { force: true, quiet: true }, + options: {}, + params: ["meeple1"], }); + }); - it('should parse command with short flags', () => { - const result = parseCommand('move meeple1 -f -q'); - expect(result).toEqual({ - name: 'move', - flags: { f: true, q: true }, - options: {}, - params: ['meeple1'] - }); + it("should parse command with short flags", () => { + const result = parseCommand("move meeple1 -f -q"); + expect(result).toEqual({ + name: "move", + flags: { f: true, q: true }, + options: {}, + params: ["meeple1"], }); + }); - it('should parse command with long options', () => { - const result = parseCommand('move meeple1 --x 10 --y 20'); - expect(result).toEqual({ - name: 'move', - flags: {}, - options: { x: '10', y: '20' }, - params: ['meeple1'] - }); + it("should parse command with long options", () => { + const result = parseCommand("move meeple1 --x 10 --y 20"); + expect(result).toEqual({ + name: "move", + flags: {}, + options: { x: "10", y: "20" }, + params: ["meeple1"], }); + }); - it('should parse command with short options', () => { - const result = parseCommand('move meeple1 -x 10 -y 20'); - expect(result).toEqual({ - name: 'move', - flags: {}, - options: { x: '10', y: '20' }, - params: ['meeple1'] - }); + it("should parse command with short options", () => { + const result = parseCommand("move meeple1 -x 10 -y 20"); + expect(result).toEqual({ + name: "move", + flags: {}, + options: { x: "10", y: "20" }, + params: ["meeple1"], }); + }); - it('should parse command with mixed flags和选项', () => { - const result = parseCommand('move meeple1 region1 --force -x 10 -q'); - expect(result).toEqual({ - name: 'move', - flags: { force: true, q: true }, - options: { x: '10' }, - params: ['meeple1', 'region1'] - }); + it("should parse command with mixed flags和选项", () => { + const result = parseCommand("move meeple1 region1 --force -x 10 -q"); + expect(result).toEqual({ + name: "move", + flags: { force: true, q: true }, + options: { x: "10" }, + params: ["meeple1", "region1"], }); + }); - it('should handle extra whitespace', () => { - const result = parseCommand(' move meeple1 --force '); - expect(result).toEqual({ - name: 'move', - flags: { force: true }, - options: {}, - params: ['meeple1'] - }); + it("should handle extra whitespace", () => { + const result = parseCommand(" move meeple1 --force "); + expect(result).toEqual({ + name: "move", + flags: { force: true }, + options: {}, + params: ["meeple1"], }); + }); - it('should parse complex command', () => { - const result = parseCommand('place meeple1 board --x 5 --y 3 --rotate 90 --force'); - expect(result).toEqual({ - name: 'place', - flags: { force: true }, - options: { x: '5', y: '3', rotate: '90' }, - params: ['meeple1', 'board'] - }); + it("should parse complex command", () => { + const result = parseCommand( + "place meeple1 board --x 5 --y 3 --rotate 90 --force", + ); + expect(result).toEqual({ + name: "place", + flags: { force: true }, + options: { x: "5", y: "3", rotate: "90" }, + params: ["meeple1", "board"], }); + }); - it('should treat negative number as option value', () => { - const result = parseCommand('set --value -10'); - expect(result).toEqual({ - name: 'set', - flags: {}, - options: { value: '-10' }, - params: [] - }); + it("should treat negative number as option value", () => { + const result = parseCommand("set --value -10"); + expect(result).toEqual({ + name: "set", + flags: {}, + options: { value: "-10" }, + params: [], }); + }); - it('should parse quoted string with double quotes', () => { - const result = parseCommand('place tile "large castle" --x 5'); - expect(result).toEqual({ - name: 'place', - flags: {}, - options: { x: '5' }, - params: ['tile', 'large castle'] - }); + it("should parse quoted string with double quotes", () => { + const result = parseCommand('place tile "large castle" --x 5'); + expect(result).toEqual({ + name: "place", + flags: {}, + options: { x: "5" }, + params: ["tile", "large castle"], }); + }); - it('should parse quoted string with single quotes', () => { - const result = parseCommand("place tile 'large castle' --x 5"); - expect(result).toEqual({ - name: 'place', - flags: {}, - options: { x: '5' }, - params: ['tile', 'large castle'] - }); + it("should parse quoted string with single quotes", () => { + const result = parseCommand("place tile 'large castle' --x 5"); + expect(result).toEqual({ + name: "place", + flags: {}, + options: { x: "5" }, + params: ["tile", "large castle"], }); + }); - it('should handle escaped quotes', () => { - const result = parseCommand('say "hello \\"world\\""'); - expect(result).toEqual({ - name: 'say', - flags: {}, - options: {}, - params: ['hello "world"'] - }); + it("should handle escaped quotes", () => { + const result = parseCommand('say "hello \\"world\\""'); + expect(result).toEqual({ + name: "say", + flags: {}, + options: {}, + params: ['hello "world"'], }); + }); - it('should handle escaped backslash', () => { - const result = parseCommand('set path "C:\\\\Users"'); - expect(result).toEqual({ - name: 'set', - flags: {}, - options: {}, - params: ['path', 'C:\\Users'] - }); + it("should handle escaped backslash", () => { + const result = parseCommand('set path "C:\\\\Users"'); + expect(result).toEqual({ + name: "set", + flags: {}, + options: {}, + params: ["path", "C:\\Users"], }); + }); - it('should handle mixed quotes', () => { - const result = parseCommand('cmd "hello world" \'foo bar\' --flag'); - expect(result).toEqual({ - name: 'cmd', - flags: { flag: true }, - options: {}, - params: ['hello world', 'foo bar'] - }); + it("should handle mixed quotes", () => { + const result = parseCommand("cmd \"hello world\" 'foo bar' --flag"); + expect(result).toEqual({ + name: "cmd", + flags: { flag: true }, + options: {}, + params: ["hello world", "foo bar"], }); + }); - it('should handle quote in middle of argument', () => { - const result = parseCommand('cmd "hello\'s world"'); - expect(result).toEqual({ - name: 'cmd', - flags: {}, - options: {}, - params: ["hello's world"] - }); + it("should handle quote in middle of argument", () => { + const result = parseCommand('cmd "hello\'s world"'); + expect(result).toEqual({ + name: "cmd", + flags: {}, + options: {}, + params: ["hello's world"], }); + }); });