@codehawks/agent-battle-arena-mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +112 -0
- package/dist/data/creatures.d.ts +6 -0
- package/dist/data/creatures.d.ts.map +1 -0
- package/dist/data/creatures.js +524 -0
- package/dist/data/creatures.js.map +1 -0
- package/dist/data/moves.d.ts +5 -0
- package/dist/data/moves.d.ts.map +1 -0
- package/dist/data/moves.js +1034 -0
- package/dist/data/moves.js.map +1 -0
- package/dist/data/sprites.d.ts +6 -0
- package/dist/data/sprites.d.ts.map +1 -0
- package/dist/data/sprites.js +5 -0
- package/dist/data/sprites.js.map +1 -0
- package/dist/data/types.d.ts +115 -0
- package/dist/data/types.d.ts.map +1 -0
- package/dist/data/types.js +29 -0
- package/dist/data/types.js.map +1 -0
- package/dist/engine/ai.d.ts +4 -0
- package/dist/engine/ai.d.ts.map +1 -0
- package/dist/engine/ai.js +138 -0
- package/dist/engine/ai.js.map +1 -0
- package/dist/engine/battle.d.ts +12 -0
- package/dist/engine/battle.d.ts.map +1 -0
- package/dist/engine/battle.js +313 -0
- package/dist/engine/battle.js.map +1 -0
- package/dist/engine/damage.d.ts +14 -0
- package/dist/engine/damage.d.ts.map +1 -0
- package/dist/engine/damage.js +51 -0
- package/dist/engine/damage.js.map +1 -0
- package/dist/engine/effects.d.ts +9 -0
- package/dist/engine/effects.d.ts.map +1 -0
- package/dist/engine/effects.js +99 -0
- package/dist/engine/effects.js.map +1 -0
- package/dist/engine/typeChart.d.ts +7 -0
- package/dist/engine/typeChart.d.ts.map +1 -0
- package/dist/engine/typeChart.js +73 -0
- package/dist/engine/typeChart.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +97 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/getMoveInfo.d.ts +4 -0
- package/dist/tools/getMoveInfo.d.ts.map +1 -0
- package/dist/tools/getMoveInfo.js +33 -0
- package/dist/tools/getMoveInfo.js.map +1 -0
- package/dist/tools/getSprites.d.ts +2 -0
- package/dist/tools/getSprites.d.ts.map +1 -0
- package/dist/tools/getSprites.js +15 -0
- package/dist/tools/getSprites.js.map +1 -0
- package/dist/tools/getState.d.ts +2 -0
- package/dist/tools/getState.d.ts.map +1 -0
- package/dist/tools/getState.js +18 -0
- package/dist/tools/getState.js.map +1 -0
- package/dist/tools/listCreatures.d.ts +4 -0
- package/dist/tools/listCreatures.d.ts.map +1 -0
- package/dist/tools/listCreatures.js +36 -0
- package/dist/tools/listCreatures.js.map +1 -0
- package/dist/tools/makeMove.d.ts +4 -0
- package/dist/tools/makeMove.d.ts.map +1 -0
- package/dist/tools/makeMove.js +21 -0
- package/dist/tools/makeMove.js.map +1 -0
- package/dist/tools/startBattle.d.ts +6 -0
- package/dist/tools/startBattle.d.ts.map +1 -0
- package/dist/tools/startBattle.js +22 -0
- package/dist/tools/startBattle.js.map +1 -0
- package/dist/utils/rng.d.ts +11 -0
- package/dist/utils/rng.d.ts.map +1 -0
- package/dist/utils/rng.js +26 -0
- package/dist/utils/rng.js.map +1 -0
- package/package.json +45 -0
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
import { ALL_CREATURES } from '../data/creatures.js';
|
|
2
|
+
import { ALL_MOVES, getMove } from '../data/moves.js';
|
|
3
|
+
import { getMatchupChart } from './typeChart.js';
|
|
4
|
+
import { calculateDamage, applyDamage, getEffectiveSpeed } from './damage.js';
|
|
5
|
+
import { applyMoveEffect, processStatusEffects, consumePP } from './effects.js';
|
|
6
|
+
import { chooseOpponentMove } from './ai.js';
|
|
7
|
+
import { SeededRNG } from '../utils/rng.js';
|
|
8
|
+
let battleCounter = 0;
|
|
9
|
+
function generateBattleId() {
|
|
10
|
+
battleCounter++;
|
|
11
|
+
return `b_${Date.now().toString(36)}_${battleCounter}`;
|
|
12
|
+
}
|
|
13
|
+
function createBattleCreature(name) {
|
|
14
|
+
const def = ALL_CREATURES[name];
|
|
15
|
+
if (!def)
|
|
16
|
+
throw new Error(`Unknown creature: ${name}`);
|
|
17
|
+
const moves = def.moves.map(moveName => {
|
|
18
|
+
const moveDef = ALL_MOVES[moveName];
|
|
19
|
+
if (!moveDef)
|
|
20
|
+
throw new Error(`Unknown move: ${moveName}`);
|
|
21
|
+
return {
|
|
22
|
+
name: moveDef.name,
|
|
23
|
+
type: moveDef.type,
|
|
24
|
+
power: moveDef.power,
|
|
25
|
+
accuracy: moveDef.accuracy,
|
|
26
|
+
pp: moveDef.pp,
|
|
27
|
+
ppLeft: moveDef.pp,
|
|
28
|
+
effect: moveDef.effect
|
|
29
|
+
? formatEffectDescription(moveDef)
|
|
30
|
+
: null,
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
return {
|
|
34
|
+
name: def.name,
|
|
35
|
+
type: def.type,
|
|
36
|
+
hp: def.hp,
|
|
37
|
+
maxHp: def.hp,
|
|
38
|
+
attack: def.attack,
|
|
39
|
+
defense: def.defense,
|
|
40
|
+
speed: def.speed,
|
|
41
|
+
moves,
|
|
42
|
+
statusEffects: [],
|
|
43
|
+
statModifiers: { attack: 0, defense: 0, speed: 0 },
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function formatEffectDescription(moveDef) {
|
|
47
|
+
const e = moveDef.effect;
|
|
48
|
+
if (!e)
|
|
49
|
+
return '';
|
|
50
|
+
switch (e.type) {
|
|
51
|
+
case 'stat_boost': return `Raises ${e.target === 'self' ? 'user' : 'target'}'s ${e.stat} by ${e.stages ?? 1} stage(s)`;
|
|
52
|
+
case 'stat_lower': return `Lowers ${e.target === 'self' ? 'user' : 'target'}'s ${e.stat} by ${e.stages ?? 1} stage(s)`;
|
|
53
|
+
case 'heal': return `Heals ${e.healPercent}% of max HP`;
|
|
54
|
+
case 'recoil': return `Recoil: ${e.recoilPercent}% of damage dealt`;
|
|
55
|
+
case 'status': return `${e.chance === 100 ? '' : `${e.chance}% chance to `}${e.status === 'burned' ? 'burn' : e.status === 'frozen' ? 'freeze' : e.status === 'poisoned' ? 'poison' : 'paralyze'} the target`;
|
|
56
|
+
case 'high_crit': return `High critical hit chance (+${e.critBonus}%)`;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export class BattleManager {
|
|
60
|
+
battles = new Map();
|
|
61
|
+
startBattle(playerCreature, difficulty = 'normal', mode = 'single') {
|
|
62
|
+
const rng = new SeededRNG();
|
|
63
|
+
const creatureNames = Object.keys(ALL_CREATURES);
|
|
64
|
+
const playerName = playerCreature && ALL_CREATURES[playerCreature]
|
|
65
|
+
? playerCreature
|
|
66
|
+
: rng.pick(creatureNames);
|
|
67
|
+
let opponentName = rng.pick(creatureNames);
|
|
68
|
+
while (opponentName === playerName) {
|
|
69
|
+
opponentName = rng.pick(creatureNames);
|
|
70
|
+
}
|
|
71
|
+
const player = createBattleCreature(playerName);
|
|
72
|
+
const opponent = createBattleCreature(opponentName);
|
|
73
|
+
const battleId = generateBattleId();
|
|
74
|
+
const session = {
|
|
75
|
+
gameState: {
|
|
76
|
+
battleId,
|
|
77
|
+
status: 'active',
|
|
78
|
+
turn: 0,
|
|
79
|
+
difficulty,
|
|
80
|
+
mode,
|
|
81
|
+
player: { creature: player },
|
|
82
|
+
opponent: { creature: opponent },
|
|
83
|
+
lastRound: null,
|
|
84
|
+
battleLog: [],
|
|
85
|
+
typeChart: getMatchupChart(player.type, opponent.type),
|
|
86
|
+
...(mode === 'best_of_3' ? { seriesScore: { player: 0, opponent: 0, round: 1 } } : {}),
|
|
87
|
+
},
|
|
88
|
+
rng,
|
|
89
|
+
playerMoveHistory: [],
|
|
90
|
+
};
|
|
91
|
+
this.battles.set(battleId, session);
|
|
92
|
+
return session.gameState;
|
|
93
|
+
}
|
|
94
|
+
getState(battleId) {
|
|
95
|
+
if (battleId) {
|
|
96
|
+
return this.battles.get(battleId)?.gameState ?? null;
|
|
97
|
+
}
|
|
98
|
+
// Return most recent battle
|
|
99
|
+
const entries = Array.from(this.battles.entries());
|
|
100
|
+
if (entries.length === 0)
|
|
101
|
+
return null;
|
|
102
|
+
return entries[entries.length - 1][1].gameState;
|
|
103
|
+
}
|
|
104
|
+
makeMove(moveName, battleId) {
|
|
105
|
+
const session = battleId
|
|
106
|
+
? this.battles.get(battleId)
|
|
107
|
+
: Array.from(this.battles.values()).pop();
|
|
108
|
+
if (!session)
|
|
109
|
+
throw new Error('No active battle. Use start_battle first.');
|
|
110
|
+
const { gameState, rng } = session;
|
|
111
|
+
if (gameState.status !== 'active') {
|
|
112
|
+
throw new Error(`Battle is over. Status: ${gameState.status}. Start a new battle.`);
|
|
113
|
+
}
|
|
114
|
+
const playerCreature = gameState.player.creature;
|
|
115
|
+
const opponentCreature = gameState.opponent.creature;
|
|
116
|
+
// Validate move
|
|
117
|
+
const playerMove = playerCreature.moves.find(m => m.name.toLowerCase() === moveName.toLowerCase());
|
|
118
|
+
if (!playerMove) {
|
|
119
|
+
const available = playerCreature.moves.map(m => m.name).join(', ');
|
|
120
|
+
throw new Error(`Unknown move: "${moveName}". Available: ${available}`);
|
|
121
|
+
}
|
|
122
|
+
if (playerMove.ppLeft <= 0) {
|
|
123
|
+
throw new Error(`${playerMove.name} has no PP left! Choose a different move.`);
|
|
124
|
+
}
|
|
125
|
+
gameState.turn++;
|
|
126
|
+
// Opponent chooses move
|
|
127
|
+
const opponentMoveName = chooseOpponentMove(opponentCreature, playerCreature, gameState.difficulty, session.playerMoveHistory, rng);
|
|
128
|
+
session.playerMoveHistory.push(moveName);
|
|
129
|
+
// Determine turn order by speed
|
|
130
|
+
const playerSpeed = getEffectiveSpeed(playerCreature);
|
|
131
|
+
const opponentSpeed = getEffectiveSpeed(opponentCreature);
|
|
132
|
+
const playerFirst = playerSpeed >= opponentSpeed;
|
|
133
|
+
const [first, second, firstName, secondName, firstMoveName, secondMoveName] = playerFirst
|
|
134
|
+
? [playerCreature, opponentCreature, 'player', 'opponent', moveName, opponentMoveName]
|
|
135
|
+
: [opponentCreature, playerCreature, 'opponent', 'player', opponentMoveName, moveName];
|
|
136
|
+
const narrativeParts = [];
|
|
137
|
+
// === First attacker's turn ===
|
|
138
|
+
const firstAction = this.executeTurn(first, second, firstMoveName, rng, narrativeParts);
|
|
139
|
+
// === Check if second attacker fainted ===
|
|
140
|
+
let secondAction;
|
|
141
|
+
if (second.hp <= 0) {
|
|
142
|
+
secondAction = { move: secondMoveName, damage: 0, effectiveness: 'neutral', critical: false, missed: false };
|
|
143
|
+
narrativeParts.push(`${second.name} fainted!`);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
// === Second attacker's turn ===
|
|
147
|
+
secondAction = this.executeTurn(second, first, secondMoveName, rng, narrativeParts);
|
|
148
|
+
if (first.hp <= 0) {
|
|
149
|
+
narrativeParts.push(`${first.name} fainted!`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// Assign results to player/opponent
|
|
153
|
+
const [playerAction, opponentAction] = playerFirst
|
|
154
|
+
? [firstAction, secondAction]
|
|
155
|
+
: [secondAction, firstAction];
|
|
156
|
+
const round = {
|
|
157
|
+
playerAction,
|
|
158
|
+
opponentAction,
|
|
159
|
+
turnOrder: playerFirst ? 'player_first' : 'opponent_first',
|
|
160
|
+
narrative: narrativeParts.join(' '),
|
|
161
|
+
};
|
|
162
|
+
gameState.lastRound = round;
|
|
163
|
+
// Build log entry
|
|
164
|
+
const logParts = [];
|
|
165
|
+
if (playerAction.missed) {
|
|
166
|
+
logParts.push(`${playerCreature.name}'s ${playerAction.move} missed!`);
|
|
167
|
+
}
|
|
168
|
+
else if (playerAction.damage > 0) {
|
|
169
|
+
const seTag = playerAction.effectiveness === 'super_effective' ? ' SE!' : playerAction.effectiveness === 'not_very_effective' ? ' NVE' : '';
|
|
170
|
+
const critTag = playerAction.critical ? ' CRIT!' : '';
|
|
171
|
+
logParts.push(`${playerCreature.name}: ${playerAction.move} (${playerAction.damage} dmg${seTag}${critTag})`);
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
logParts.push(`${playerCreature.name}: ${playerAction.move}${playerAction.effectApplied ? ` - ${playerAction.effectApplied}` : ''}`);
|
|
175
|
+
}
|
|
176
|
+
if (opponentAction.missed) {
|
|
177
|
+
logParts.push(`${opponentCreature.name}'s ${opponentAction.move} missed!`);
|
|
178
|
+
}
|
|
179
|
+
else if (opponentAction.damage > 0) {
|
|
180
|
+
const seTag = opponentAction.effectiveness === 'super_effective' ? ' SE!' : opponentAction.effectiveness === 'not_very_effective' ? ' NVE' : '';
|
|
181
|
+
const critTag = opponentAction.critical ? ' CRIT!' : '';
|
|
182
|
+
logParts.push(`${opponentCreature.name}: ${opponentAction.move} (${opponentAction.damage} dmg${seTag}${critTag})`);
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
logParts.push(`${opponentCreature.name}: ${opponentAction.move}${opponentAction.effectApplied ? ` - ${opponentAction.effectApplied}` : ''}`);
|
|
186
|
+
}
|
|
187
|
+
gameState.battleLog.push({
|
|
188
|
+
turn: gameState.turn,
|
|
189
|
+
summary: logParts.join(' / '),
|
|
190
|
+
});
|
|
191
|
+
// Check win condition
|
|
192
|
+
if (playerCreature.hp <= 0) {
|
|
193
|
+
gameState.status = 'opponent_won';
|
|
194
|
+
if (gameState.seriesScore) {
|
|
195
|
+
gameState.seriesScore.opponent++;
|
|
196
|
+
this.maybeAdvanceSeries(session);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
else if (opponentCreature.hp <= 0) {
|
|
200
|
+
gameState.status = 'player_won';
|
|
201
|
+
if (gameState.seriesScore) {
|
|
202
|
+
gameState.seriesScore.player++;
|
|
203
|
+
this.maybeAdvanceSeries(session);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return gameState;
|
|
207
|
+
}
|
|
208
|
+
executeTurn(attacker, defender, moveName, rng, narrative) {
|
|
209
|
+
// Process status effects first
|
|
210
|
+
const statusResult = processStatusEffects(attacker, rng);
|
|
211
|
+
narrative.push(...statusResult.messages);
|
|
212
|
+
if (statusResult.skipTurn) {
|
|
213
|
+
return {
|
|
214
|
+
move: moveName,
|
|
215
|
+
damage: 0,
|
|
216
|
+
effectiveness: 'neutral',
|
|
217
|
+
critical: false,
|
|
218
|
+
missed: false,
|
|
219
|
+
effectApplied: 'Skipped turn',
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
// Check if attacker fainted from status damage
|
|
223
|
+
if (attacker.hp <= 0) {
|
|
224
|
+
return {
|
|
225
|
+
move: moveName,
|
|
226
|
+
damage: 0,
|
|
227
|
+
effectiveness: 'neutral',
|
|
228
|
+
critical: false,
|
|
229
|
+
missed: false,
|
|
230
|
+
effectApplied: `${attacker.name} fainted from status damage`,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
const moveDef = getMove(moveName);
|
|
234
|
+
if (!moveDef) {
|
|
235
|
+
return {
|
|
236
|
+
move: moveName,
|
|
237
|
+
damage: 0,
|
|
238
|
+
effectiveness: 'neutral',
|
|
239
|
+
critical: false,
|
|
240
|
+
missed: true,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
// Consume PP
|
|
244
|
+
consumePP(attacker, moveName);
|
|
245
|
+
// Calculate and apply damage
|
|
246
|
+
const damageResult = calculateDamage(attacker, defender, moveDef, rng);
|
|
247
|
+
if (damageResult.missed) {
|
|
248
|
+
narrative.push(`${attacker.name} used ${moveName}, but it missed!`);
|
|
249
|
+
return {
|
|
250
|
+
move: moveName,
|
|
251
|
+
damage: 0,
|
|
252
|
+
effectiveness: damageResult.effectiveness,
|
|
253
|
+
critical: false,
|
|
254
|
+
missed: true,
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
if (damageResult.damage > 0) {
|
|
258
|
+
applyDamage(defender, damageResult.damage);
|
|
259
|
+
let desc = `${attacker.name} used ${moveName}`;
|
|
260
|
+
if (damageResult.effectiveness === 'super_effective') {
|
|
261
|
+
desc += ` — it's super effective! ${damageResult.damage} damage!`;
|
|
262
|
+
}
|
|
263
|
+
else if (damageResult.effectiveness === 'not_very_effective') {
|
|
264
|
+
desc += ` — not very effective. ${damageResult.damage} damage.`;
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
desc += ` for ${damageResult.damage} damage.`;
|
|
268
|
+
}
|
|
269
|
+
if (damageResult.critical) {
|
|
270
|
+
desc += ' Critical hit!';
|
|
271
|
+
}
|
|
272
|
+
narrative.push(desc);
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
narrative.push(`${attacker.name} used ${moveName}!`);
|
|
276
|
+
}
|
|
277
|
+
// Apply move effect
|
|
278
|
+
const effectMessage = applyMoveEffect(moveDef, attacker, defender, damageResult.damage, rng);
|
|
279
|
+
if (effectMessage) {
|
|
280
|
+
narrative.push(effectMessage);
|
|
281
|
+
}
|
|
282
|
+
return {
|
|
283
|
+
move: moveName,
|
|
284
|
+
damage: damageResult.damage,
|
|
285
|
+
effectiveness: damageResult.effectiveness,
|
|
286
|
+
critical: damageResult.critical,
|
|
287
|
+
missed: false,
|
|
288
|
+
effectApplied: effectMessage,
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
maybeAdvanceSeries(session) {
|
|
292
|
+
const score = session.gameState.seriesScore;
|
|
293
|
+
if (!score)
|
|
294
|
+
return;
|
|
295
|
+
// Best of 3: need 2 wins
|
|
296
|
+
if (score.player >= 2 || score.opponent >= 2) {
|
|
297
|
+
// Series is over, status already set from last round
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
// If both haven't reached 2, series continues
|
|
301
|
+
// The next start_battle_round call will create the next round
|
|
302
|
+
// For now, just track it
|
|
303
|
+
score.round++;
|
|
304
|
+
}
|
|
305
|
+
getActiveBattleIds() {
|
|
306
|
+
return Array.from(this.battles.entries())
|
|
307
|
+
.filter(([_, s]) => s.gameState.status === 'active')
|
|
308
|
+
.map(([id]) => id);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
// Singleton
|
|
312
|
+
export const battleManager = new BattleManager();
|
|
313
|
+
//# sourceMappingURL=battle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"battle.js","sourceRoot":"","sources":["../../src/engine/battle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BattleCreature, MoveDefinition, Effectiveness } from '../data/types.js';
|
|
2
|
+
import { SeededRNG } from '../utils/rng.js';
|
|
3
|
+
export declare function getEffectiveAttack(creature: BattleCreature): number;
|
|
4
|
+
export declare function getEffectiveDefense(creature: BattleCreature): number;
|
|
5
|
+
export declare function getEffectiveSpeed(creature: BattleCreature): number;
|
|
6
|
+
export interface DamageResult {
|
|
7
|
+
damage: number;
|
|
8
|
+
effectiveness: Effectiveness;
|
|
9
|
+
critical: boolean;
|
|
10
|
+
missed: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare function calculateDamage(attacker: BattleCreature, defender: BattleCreature, move: MoveDefinition, rng: SeededRNG): DamageResult;
|
|
13
|
+
export declare function applyDamage(creature: BattleCreature, damage: number): void;
|
|
14
|
+
//# sourceMappingURL=damage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"damage.d.ts","sourceRoot":"","sources":["../../src/engine/damage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAgB,MAAM,kBAAkB,CAAC;AAE/F,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAM5C,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CAOnE;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CAEpE;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CAMlE;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,aAAa,CAAC;IAC7B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,cAAc,EACxB,IAAI,EAAE,cAAc,EACpB,GAAG,EAAE,SAAS,GACb,YAAY,CAiCd;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAE1E"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { getEffectiveness, getTypeMultiplier } from './typeChart.js';
|
|
2
|
+
function getStatMultiplier(stage) {
|
|
3
|
+
return 1 + stage * 0.25;
|
|
4
|
+
}
|
|
5
|
+
export function getEffectiveAttack(creature) {
|
|
6
|
+
const base = creature.attack;
|
|
7
|
+
let mult = getStatMultiplier(creature.statModifiers.attack);
|
|
8
|
+
if (creature.statusEffects.includes('burned')) {
|
|
9
|
+
mult *= 0.75;
|
|
10
|
+
}
|
|
11
|
+
return Math.round(base * mult);
|
|
12
|
+
}
|
|
13
|
+
export function getEffectiveDefense(creature) {
|
|
14
|
+
return Math.round(creature.defense * getStatMultiplier(creature.statModifiers.defense));
|
|
15
|
+
}
|
|
16
|
+
export function getEffectiveSpeed(creature) {
|
|
17
|
+
let mult = getStatMultiplier(creature.statModifiers.speed);
|
|
18
|
+
if (creature.statusEffects.includes('frozen') || creature.statusEffects.includes('paralyzed')) {
|
|
19
|
+
mult *= 0.5;
|
|
20
|
+
}
|
|
21
|
+
return Math.round(creature.speed * mult);
|
|
22
|
+
}
|
|
23
|
+
export function calculateDamage(attacker, defender, move, rng) {
|
|
24
|
+
// Status moves deal no damage
|
|
25
|
+
if (move.power === 0) {
|
|
26
|
+
return { damage: 0, effectiveness: 'neutral', critical: false, missed: false };
|
|
27
|
+
}
|
|
28
|
+
// Accuracy check
|
|
29
|
+
const accuracyRoll = rng.next() * 100;
|
|
30
|
+
if (accuracyRoll >= move.accuracy) {
|
|
31
|
+
return { damage: 0, effectiveness: 'neutral', critical: false, missed: true };
|
|
32
|
+
}
|
|
33
|
+
const effectiveness = getEffectiveness(move.type, defender.type);
|
|
34
|
+
const typeMultiplier = getTypeMultiplier(effectiveness);
|
|
35
|
+
// Crit check
|
|
36
|
+
let critChance = 10;
|
|
37
|
+
if (move.effect?.type === 'high_crit' && move.effect.critBonus) {
|
|
38
|
+
critChance += move.effect.critBonus;
|
|
39
|
+
}
|
|
40
|
+
const critical = rng.chance(critChance);
|
|
41
|
+
const critMultiplier = critical ? 1.5 : 1.0;
|
|
42
|
+
const atk = getEffectiveAttack(attacker);
|
|
43
|
+
const def = getEffectiveDefense(defender);
|
|
44
|
+
const baseDamage = ((2 * move.power * (atk / Math.max(def, 1))) / 10 + 2);
|
|
45
|
+
const finalDamage = Math.max(1, Math.round(baseDamage * typeMultiplier * critMultiplier * rng.variance()));
|
|
46
|
+
return { damage: finalDamage, effectiveness, critical, missed: false };
|
|
47
|
+
}
|
|
48
|
+
export function applyDamage(creature, damage) {
|
|
49
|
+
creature.hp = Math.max(0, creature.hp - damage);
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=damage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"damage.js","sourceRoot":"","sources":["../../src/engine/damage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { BattleCreature, MoveDefinition } from '../data/types.js';
|
|
2
|
+
import { SeededRNG } from '../utils/rng.js';
|
|
3
|
+
export declare function applyMoveEffect(move: MoveDefinition, user: BattleCreature, target: BattleCreature, damageDone: number, rng: SeededRNG): string | undefined;
|
|
4
|
+
export declare function processStatusEffects(creature: BattleCreature, rng: SeededRNG): {
|
|
5
|
+
skipTurn: boolean;
|
|
6
|
+
messages: string[];
|
|
7
|
+
};
|
|
8
|
+
export declare function consumePP(creature: BattleCreature, moveName: string): boolean;
|
|
9
|
+
//# sourceMappingURL=effects.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"effects.d.ts","sourceRoot":"","sources":["../../src/engine/effects.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAgB,MAAM,kBAAkB,CAAC;AAChF,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,wBAAgB,eAAe,CAC7B,IAAI,EAAE,cAAc,EACpB,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,cAAc,EACtB,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,SAAS,GACb,MAAM,GAAG,SAAS,CAuDpB;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,SAAS,GAAG;IAC9E,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CA2CA;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAK7E"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
export function applyMoveEffect(move, user, target, damageDone, rng) {
|
|
2
|
+
const effect = move.effect;
|
|
3
|
+
if (!effect)
|
|
4
|
+
return undefined;
|
|
5
|
+
const effectTarget = effect.target === 'self' ? user : target;
|
|
6
|
+
switch (effect.type) {
|
|
7
|
+
case 'stat_boost': {
|
|
8
|
+
const stat = effect.stat;
|
|
9
|
+
const stages = effect.stages ?? 1;
|
|
10
|
+
const oldVal = effectTarget.statModifiers[stat];
|
|
11
|
+
effectTarget.statModifiers[stat] = Math.min(4, oldVal + stages);
|
|
12
|
+
const word = stages > 1 ? 'sharply rose' : 'rose';
|
|
13
|
+
return `${effectTarget.name}'s ${stat} ${word}!`;
|
|
14
|
+
}
|
|
15
|
+
case 'stat_lower': {
|
|
16
|
+
const stat = effect.stat;
|
|
17
|
+
const stages = effect.stages ?? 1;
|
|
18
|
+
const oldVal = effectTarget.statModifiers[stat];
|
|
19
|
+
effectTarget.statModifiers[stat] = Math.max(-4, oldVal - stages);
|
|
20
|
+
const word = stages > 1 ? 'sharply fell' : 'fell';
|
|
21
|
+
return `${effectTarget.name}'s ${stat} ${word}!`;
|
|
22
|
+
}
|
|
23
|
+
case 'heal': {
|
|
24
|
+
const healAmount = Math.round(user.maxHp * (effect.healPercent / 100));
|
|
25
|
+
user.hp = Math.min(user.maxHp, user.hp + healAmount);
|
|
26
|
+
return `${user.name} restored ${healAmount} HP!`;
|
|
27
|
+
}
|
|
28
|
+
case 'recoil': {
|
|
29
|
+
const recoilDamage = Math.max(1, Math.round(damageDone * (effect.recoilPercent / 100)));
|
|
30
|
+
user.hp = Math.max(0, user.hp - recoilDamage);
|
|
31
|
+
return `${user.name} took ${recoilDamage} recoil damage!`;
|
|
32
|
+
}
|
|
33
|
+
case 'status': {
|
|
34
|
+
const chance = effect.chance ?? 100;
|
|
35
|
+
if (!rng.chance(chance))
|
|
36
|
+
return undefined;
|
|
37
|
+
const status = effect.status;
|
|
38
|
+
if (effectTarget.statusEffects.includes(status)) {
|
|
39
|
+
return `${effectTarget.name} is already ${status}!`;
|
|
40
|
+
}
|
|
41
|
+
effectTarget.statusEffects.push(status);
|
|
42
|
+
return `${effectTarget.name} was ${status}!`;
|
|
43
|
+
}
|
|
44
|
+
case 'high_crit': {
|
|
45
|
+
// Handled in damage calculation, no additional effect
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
export function processStatusEffects(creature, rng) {
|
|
52
|
+
const messages = [];
|
|
53
|
+
let skipTurn = false;
|
|
54
|
+
for (const status of creature.statusEffects) {
|
|
55
|
+
switch (status) {
|
|
56
|
+
case 'burned':
|
|
57
|
+
{
|
|
58
|
+
const burnDamage = Math.max(1, Math.round(creature.maxHp * 0.1));
|
|
59
|
+
creature.hp = Math.max(0, creature.hp - burnDamage);
|
|
60
|
+
messages.push(`${creature.name} is hurt by its burn! (-${burnDamage} HP)`);
|
|
61
|
+
}
|
|
62
|
+
break;
|
|
63
|
+
case 'poisoned':
|
|
64
|
+
{
|
|
65
|
+
const poisonDamage = Math.max(1, Math.round(creature.maxHp * 0.08));
|
|
66
|
+
creature.hp = Math.max(0, creature.hp - poisonDamage);
|
|
67
|
+
messages.push(`${creature.name} is hurt by poison! (-${poisonDamage} HP)`);
|
|
68
|
+
}
|
|
69
|
+
break;
|
|
70
|
+
case 'frozen':
|
|
71
|
+
if (rng.chance(25)) {
|
|
72
|
+
skipTurn = true;
|
|
73
|
+
messages.push(`${creature.name} is frozen solid and can't move!`);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
messages.push(`${creature.name} struggles against the ice!`);
|
|
77
|
+
}
|
|
78
|
+
break;
|
|
79
|
+
case 'paralyzed':
|
|
80
|
+
if (rng.chance(25)) {
|
|
81
|
+
skipTurn = true;
|
|
82
|
+
messages.push(`${creature.name} is paralyzed and can't move!`);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
messages.push(`${creature.name} fought through the paralysis!`);
|
|
86
|
+
}
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return { skipTurn, messages };
|
|
91
|
+
}
|
|
92
|
+
export function consumePP(creature, moveName) {
|
|
93
|
+
const move = creature.moves.find(m => m.name === moveName);
|
|
94
|
+
if (!move || move.ppLeft <= 0)
|
|
95
|
+
return false;
|
|
96
|
+
move.ppLeft -= 1;
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=effects.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"effects.js","sourceRoot":"","sources":["../../src/engine/effects.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { CreatureType, MoveType, Effectiveness, TypeInfo } from '../data/types.js';
|
|
2
|
+
export declare function getEffectiveness(moveType: MoveType, defenderType: CreatureType): Effectiveness;
|
|
3
|
+
export declare function getTypeMultiplier(effectiveness: Effectiveness): number;
|
|
4
|
+
export declare function getTypeInfo(type: CreatureType): TypeInfo;
|
|
5
|
+
export declare function getMatchupChart(playerType: CreatureType, opponentType: CreatureType): Record<string, TypeInfo>;
|
|
6
|
+
export declare function getAllTypes(): CreatureType[];
|
|
7
|
+
//# sourceMappingURL=typeChart.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typeChart.d.ts","sourceRoot":"","sources":["../../src/engine/typeChart.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAgCnF,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,GAAG,aAAa,CAU9F;AAED,wBAAgB,iBAAiB,CAAC,aAAa,EAAE,aAAa,GAAG,MAAM,CAMtE;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,QAAQ,CAoBxD;AAED,wBAAgB,eAAe,CAAC,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAK9G;AAED,wBAAgB,WAAW,IAAI,YAAY,EAAE,CAE5C"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
const SUPER_EFFECTIVE = {
|
|
2
|
+
electric: ['water', 'air'],
|
|
3
|
+
earth: ['electric', 'fire', 'metal'],
|
|
4
|
+
water: ['fire', 'earth'],
|
|
5
|
+
fire: ['plant', 'ice', 'metal'],
|
|
6
|
+
air: ['plant', 'poison'],
|
|
7
|
+
plant: ['water', 'earth'],
|
|
8
|
+
light: ['shadow', 'poison'],
|
|
9
|
+
shadow: ['light', 'plasma'],
|
|
10
|
+
metal: ['ice', 'air'],
|
|
11
|
+
ice: ['plant', 'air', 'plasma'],
|
|
12
|
+
poison: ['plant', 'light'],
|
|
13
|
+
plasma: ['metal', 'water'],
|
|
14
|
+
};
|
|
15
|
+
const NOT_VERY_EFFECTIVE = {
|
|
16
|
+
electric: ['earth', 'plant', 'electric'],
|
|
17
|
+
earth: ['air', 'plant'],
|
|
18
|
+
water: ['water', 'plant'],
|
|
19
|
+
fire: ['fire', 'water', 'plasma'],
|
|
20
|
+
air: ['metal', 'electric'],
|
|
21
|
+
plant: ['fire', 'poison', 'metal'],
|
|
22
|
+
light: ['light', 'metal'],
|
|
23
|
+
shadow: ['shadow'],
|
|
24
|
+
metal: ['fire', 'metal', 'earth'],
|
|
25
|
+
ice: ['fire', 'water', 'ice', 'metal'],
|
|
26
|
+
poison: ['metal', 'poison', 'earth'],
|
|
27
|
+
plasma: ['plasma', 'shadow'],
|
|
28
|
+
};
|
|
29
|
+
export function getEffectiveness(moveType, defenderType) {
|
|
30
|
+
if (moveType === 'normal')
|
|
31
|
+
return 'neutral';
|
|
32
|
+
const seList = SUPER_EFFECTIVE[moveType];
|
|
33
|
+
if (seList && seList.includes(defenderType))
|
|
34
|
+
return 'super_effective';
|
|
35
|
+
const nveList = NOT_VERY_EFFECTIVE[moveType];
|
|
36
|
+
if (nveList && nveList.includes(defenderType))
|
|
37
|
+
return 'not_very_effective';
|
|
38
|
+
return 'neutral';
|
|
39
|
+
}
|
|
40
|
+
export function getTypeMultiplier(effectiveness) {
|
|
41
|
+
switch (effectiveness) {
|
|
42
|
+
case 'super_effective': return 1.5;
|
|
43
|
+
case 'not_very_effective': return 0.67;
|
|
44
|
+
case 'neutral': return 1.0;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export function getTypeInfo(type) {
|
|
48
|
+
const strong_against = SUPER_EFFECTIVE[type] || [];
|
|
49
|
+
const weak_against = NOT_VERY_EFFECTIVE[type] || [];
|
|
50
|
+
const weak_to = [];
|
|
51
|
+
const resists = [];
|
|
52
|
+
for (const [attackType, targets] of Object.entries(SUPER_EFFECTIVE)) {
|
|
53
|
+
if (targets.includes(type)) {
|
|
54
|
+
weak_to.push(attackType);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
for (const [attackType, targets] of Object.entries(NOT_VERY_EFFECTIVE)) {
|
|
58
|
+
if (targets.includes(type)) {
|
|
59
|
+
resists.push(attackType);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return { strong_against, weak_against, resists, weak_to };
|
|
63
|
+
}
|
|
64
|
+
export function getMatchupChart(playerType, opponentType) {
|
|
65
|
+
return {
|
|
66
|
+
[playerType]: getTypeInfo(playerType),
|
|
67
|
+
[opponentType]: getTypeInfo(opponentType),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
export function getAllTypes() {
|
|
71
|
+
return Object.keys(SUPER_EFFECTIVE);
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=typeChart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typeChart.js","sourceRoot":"","sources":["../../src/engine/typeChart.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|