mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-23 00:35:51 +00:00
feat: 计划完成
This commit is contained in:
189
plans/phase-0.md
Normal file
189
plans/phase-0.md
Normal file
@@ -0,0 +1,189 @@
|
||||
# Phase 0: 清除重复 — 委托 @pkmn
|
||||
|
||||
## 目标
|
||||
|
||||
删除所有与 @pkmn 重复的硬编码数据和手写公式,统一委托给 @pkmn 生态。**零新功能,纯重构。**
|
||||
|
||||
## 设计原则
|
||||
|
||||
先清后建。先消除重复代码,再在干净基础上添加新功能。此 Phase 不引入任何新类型或新功能。
|
||||
|
||||
## 改动
|
||||
|
||||
| 文件 | 操作 | 说明 |
|
||||
|------|------|------|
|
||||
| `types.ts` | 删除 `NATURES` 常量(27 行) | `Dex.natures` 已有完整数据 |
|
||||
| `data/nature.ts` | 重写 | `ALL_NATURE_NAMES` → 遍历 `Dex.natures`;`getNatureEffect()` → 查询 `Dex.natures.get()` |
|
||||
| `data/evolution.ts` | 重写 | `EVOLUTION_CHAINS` → `Dex.species.get(id).evos`/`.evoLevel` 动态查询 |
|
||||
| `core/creature.ts` | 重写 `calculateStats()` | 手写公式 → `gen.stats.calc()`(Nature ±10% 自动处理) |
|
||||
| `data/species.ts` | 简化 `buildEvolutionChain()` | 已部分使用 Dex.evos,统一用新 `getNextEvolution()` |
|
||||
| `data/pkmn.ts` | 统一 `gens` 单例 | 导出 `gen` 和 `TO_DEX_STAT` 映射,消除多处重复创建 `Generations` |
|
||||
|
||||
## 使用 @pkmn 包
|
||||
|
||||
- `@pkmn/sim`(Dex.natures, Dex.species)
|
||||
- `@pkmn/data`(stats.calc, Generations)
|
||||
|
||||
## 保留不变
|
||||
|
||||
- `types.ts` 中的 `NatureName`/`NatureStat`/`NatureEffect` 类型定义(Creature 类型约束需要)
|
||||
- `data/species.ts` 的 `SUPPLEMENT`(growthRate/captureRate/flavorText 不在 Dex 中)
|
||||
- `data/names.ts`(i18n 多语言名称)
|
||||
- `data/xpTable.ts`、`data/evMapping.ts`(完全自定义)
|
||||
- `core/` 其他文件、`ui/`、`sprites/`
|
||||
|
||||
## 详细实现
|
||||
|
||||
### 1. types.ts — 删除 NATURES
|
||||
|
||||
删除 `types.ts` 中 `NATURES` 常量(约 27 行手写数据)。保留 `NatureName`、`NatureStat`、`NatureEffect` 类型。
|
||||
|
||||
### 2. data/nature.ts — 委托 Dex.natures
|
||||
|
||||
```typescript
|
||||
import { Dex } from '@pkmn/sim'
|
||||
import type { NatureName, NatureEffect, NatureStat } from '../types'
|
||||
|
||||
export function getAllNatureNames(): NatureName[] {
|
||||
const names: NatureName[] = []
|
||||
for (const nature of Dex.natures) {
|
||||
if (nature.exists) names.push(nature.id as NatureName)
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
export function randomNature(): NatureName {
|
||||
const names = getAllNatureNames()
|
||||
return names[Math.floor(Math.random() * names.length)]!
|
||||
}
|
||||
|
||||
export function getNatureEffect(nature: NatureName): NatureEffect {
|
||||
const n = Dex.natures.get(nature)
|
||||
if (!n?.exists) return { plus: null, minus: null }
|
||||
return {
|
||||
plus: (n.plus as NatureStat | undefined) ?? null,
|
||||
minus: (n.minus as NatureStat | undefined) ?? null,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. data/evolution.ts — 委托 Dex.species
|
||||
|
||||
```typescript
|
||||
import { Dex } from '@pkmn/sim'
|
||||
import type { SpeciesId } from '../types'
|
||||
|
||||
export interface EvolutionChainStep {
|
||||
from: SpeciesId
|
||||
to: SpeciesId
|
||||
trigger: 'level_up' | 'item' | 'trade' | 'friendship'
|
||||
minLevel?: number
|
||||
}
|
||||
|
||||
/** 查找物种的下一个进化(从 Dex 动态获取) */
|
||||
export function getNextEvolution(speciesId: SpeciesId): EvolutionChainStep | undefined {
|
||||
const dex = Dex.species.get(speciesId)
|
||||
if (!dex?.evos?.length) return undefined
|
||||
|
||||
const target = dex.evos[0]!.toLowerCase()
|
||||
const targetDex = Dex.species.get(target)
|
||||
if (!targetDex?.exists) return undefined
|
||||
|
||||
const trigger = dex.evoType === 'trade' ? 'trade'
|
||||
: dex.evoType === 'useItem' ? 'item'
|
||||
: dex.evoType === 'levelFriendship' ? 'friendship'
|
||||
: 'level_up'
|
||||
|
||||
return {
|
||||
from: speciesId,
|
||||
to: target as SpeciesId,
|
||||
trigger,
|
||||
minLevel: targetDex.evoLevel,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. data/pkmn.ts — 统一 gens 单例 + 导出 stat 映射
|
||||
|
||||
```typescript
|
||||
import { Dex } from '@pkmn/sim'
|
||||
import { Generations } from '@pkmn/data'
|
||||
import type { StatName } from '../types'
|
||||
|
||||
// 统一单例(全包唯一入口)
|
||||
const gens = new Generations(Dex as unknown as import('@pkmn/data').Dex)
|
||||
export const gen = gens.get(9)
|
||||
|
||||
// Stat key 映射:@pkmn 缩写 → 我们的 StatName
|
||||
export const FROM_DEX_STAT: Record<string, StatName> = {
|
||||
hp: 'hp', atk: 'attack', def: 'defense',
|
||||
spa: 'spAtk', spd: 'spDef', spe: 'speed',
|
||||
}
|
||||
|
||||
// Stat key 映射:我们的 StatName → @pkmn 缩写
|
||||
export const TO_DEX_STAT: Record<StatName, string> = {
|
||||
hp: 'hp', attack: 'atk', defense: 'def',
|
||||
spAtk: 'spa', spDef: 'spd', speed: 'spe',
|
||||
}
|
||||
|
||||
// ...保留现有 getSpecies, getMove, getAbility, getType, mapBaseStats, mapGenderRatio, getPrimaryAbility ...
|
||||
```
|
||||
|
||||
### 5. core/creature.ts — calculateStats 委托 stats.calc
|
||||
|
||||
```typescript
|
||||
import { gen, TO_DEX_STAT } from '../data/pkmn'
|
||||
import { STAT_NAMES } from '../types'
|
||||
import type { Creature, StatsResult } from '../types'
|
||||
|
||||
export function calculateStats(creature: Creature): StatsResult {
|
||||
const species = gen.species.get(creature.speciesId)
|
||||
if (!species) throw new Error(`Species ${creature.speciesId} not found`)
|
||||
|
||||
const nature = creature.nature ? gen.natures.get(creature.nature) : undefined
|
||||
const result = {} as StatsResult
|
||||
|
||||
for (const stat of STAT_NAMES) {
|
||||
const dexKey = TO_DEX_STAT[stat] as 'hp' | 'atk' | 'def' | 'spa' | 'spd' | 'spe'
|
||||
result[stat] = gen.stats.calc(
|
||||
dexKey,
|
||||
species.baseStats[dexKey],
|
||||
creature.iv[stat],
|
||||
creature.ev[stat],
|
||||
creature.level,
|
||||
nature ?? undefined,
|
||||
)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
```
|
||||
|
||||
**注意**:`gen.stats.calc()` 内部已处理 Nature ±10% 修正。Phase -1 计划中的手写 Nature 修正代码不再需要。
|
||||
|
||||
### 6. data/species.ts — 简化 buildEvolutionChain
|
||||
|
||||
现有的 `buildEvolutionChain()` 已使用 `dex.evos`,只需确保它与新的 `getNextEvolution()` 一致。可简化为:
|
||||
|
||||
```typescript
|
||||
function buildEvolutionChain(speciesId: SpeciesId): SpeciesData['evolutionChain'] {
|
||||
const evo = getNextEvolution(speciesId)
|
||||
if (!evo) return undefined
|
||||
return [{ trigger: evo.trigger, level: evo.minLevel, into: evo.to }]
|
||||
}
|
||||
```
|
||||
|
||||
## 验证
|
||||
|
||||
1. `bun run typecheck` 零错误
|
||||
2. `bun test packages/pokemon/` 全部通过
|
||||
3. `bun run dev` → `/buddy` 所有现有功能正常(pet、dex、egg、switch)
|
||||
4. 性格效果正确:Adamant Charmander Lv50 ATK 应比 Hardy 高 ~10%,SPA 低 ~10%
|
||||
5. 进化判定正确:Charmander Lv16 → Charmeleon,Squirtle Lv16 → Wartortle
|
||||
6. stat 计算结果与旧实现数值一致
|
||||
|
||||
## 代码量
|
||||
|
||||
- 删除:~55 行(NATURES 27 行 + EVOLUTION_CHAINS 12 行 + calculateStats 手写公式 18 行 - 2 行)
|
||||
- 新增:~40 行(委托代码)
|
||||
- 净变化:-15 行
|
||||
Reference in New Issue
Block a user