gotchi-battler-game-logic 4.0.6 → 4.0.7
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/game-logic/v2.0/index.js +14 -19
- package/package.json +1 -1
- package/scripts/data/cleaver2.json +6895 -0
- package/scripts/rerunBattle.js +1 -1
- package/tests/getModifiedStats.test.js +8 -3
- package/tests/repeatAttack.test.js +89 -0
package/scripts/rerunBattle.js
CHANGED
|
@@ -6,7 +6,7 @@ const { battle } = require('..')
|
|
|
6
6
|
|
|
7
7
|
const main = async () => {
|
|
8
8
|
console.time('Rerun battle')
|
|
9
|
-
const logs = require('./data/
|
|
9
|
+
const logs = require('./data/cleaver2.json')
|
|
10
10
|
const teams = logToInGameTeams(logs)
|
|
11
11
|
const result = await battle(teams[0], teams[1], Number(logs.meta.seed))
|
|
12
12
|
|
|
@@ -22,7 +22,8 @@ describe('getModifiedStats', () => {
|
|
|
22
22
|
it('applies flat stat buffs from statuses', () => {
|
|
23
23
|
const g = makeGotchi({ statuses: ['spd_up', 'atk_up', 'def_up'] })
|
|
24
24
|
const m = getModifiedStats(g)
|
|
25
|
-
|
|
25
|
+
// v2.0 statuses are percent-based; with base speed=10, spd_up (+15%) rounds to +2
|
|
26
|
+
expect(m.speed).to.equal(12)
|
|
26
27
|
expect(m.attack).to.equal(6)
|
|
27
28
|
expect(m.defense).to.equal(4)
|
|
28
29
|
})
|
|
@@ -30,11 +31,15 @@ describe('getModifiedStats', () => {
|
|
|
30
31
|
it('stacks multiple statuses and nets against opposing debuffs', () => {
|
|
31
32
|
const g = makeGotchi({ statuses: ['spd_up', 'spd_up', 'spd_down'] })
|
|
32
33
|
const m = getModifiedStats(g)
|
|
33
|
-
|
|
34
|
+
// Each spd_up: 10 * 0.15 => 1.5 => Math.round => 2
|
|
35
|
+
// spd_down: 10 * -0.15 => -1.5 => Math.round => -1 (JS rounds halves toward +∞)
|
|
36
|
+
// Net: +2 +2 -1 = +3
|
|
37
|
+
expect(m.speed).to.equal(13)
|
|
34
38
|
})
|
|
35
39
|
|
|
36
40
|
it('keeps speed at minimum 1 to avoid zero/negative speed', () => {
|
|
37
|
-
|
|
41
|
+
// Use a base speed where percent debuffs round to at least -1 per stack
|
|
42
|
+
const g = makeGotchi({ speed: 4, statuses: ['spd_down', 'spd_down', 'spd_down'] })
|
|
38
43
|
const m = getModifiedStats(g)
|
|
39
44
|
expect(m.speed).to.equal(1)
|
|
40
45
|
})
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
const { expect } = require('chai')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
|
|
4
|
+
const { attack } = require(path.join('..', 'game-logic', 'v2.0', 'index'))
|
|
5
|
+
|
|
6
|
+
const makeStats = () => ({
|
|
7
|
+
hits: 0,
|
|
8
|
+
crits: 0,
|
|
9
|
+
dmgGiven: 0,
|
|
10
|
+
dmgReceived: 0,
|
|
11
|
+
counters: 0,
|
|
12
|
+
focuses: 0,
|
|
13
|
+
resists: 0,
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
const makeGotchi = (overrides = {}) => ({
|
|
17
|
+
id: 1,
|
|
18
|
+
name: 'Test',
|
|
19
|
+
speed: 10,
|
|
20
|
+
attack: 10,
|
|
21
|
+
defense: 5,
|
|
22
|
+
criticalRate: 0,
|
|
23
|
+
criticalDamage: 15,
|
|
24
|
+
resist: 0,
|
|
25
|
+
focus: 0,
|
|
26
|
+
statuses: [],
|
|
27
|
+
environmentEffects: [],
|
|
28
|
+
health: 1000,
|
|
29
|
+
fullHealth: 1000,
|
|
30
|
+
stats: makeStats(),
|
|
31
|
+
special: { initialCooldown: 0 },
|
|
32
|
+
...overrides,
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const makeTeam = (gotchis) => ({
|
|
36
|
+
leader: gotchis[0]?.id ?? 1,
|
|
37
|
+
formation: {
|
|
38
|
+
front: gotchis.slice(0, 3),
|
|
39
|
+
back: gotchis.slice(3, 5),
|
|
40
|
+
},
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
describe('repeat_attack special effect', () => {
|
|
44
|
+
it('rolls repeat_attack chance once per special use (not once per target)', () => {
|
|
45
|
+
const attacker = makeGotchi({
|
|
46
|
+
id: 100,
|
|
47
|
+
specialExpanded: {
|
|
48
|
+
actionType: 'attack',
|
|
49
|
+
target: 'all_enemies',
|
|
50
|
+
actionMultiplier: 0.5,
|
|
51
|
+
effects: [
|
|
52
|
+
{ effectType: 'repeat_attack', target: 'same_as_attack', chance: 0.5 },
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
const enemies = [1, 2, 3, 4, 5].map((n) =>
|
|
58
|
+
makeGotchi({
|
|
59
|
+
id: 200 + n,
|
|
60
|
+
name: `Enemy ${n}`,
|
|
61
|
+
stats: makeStats(),
|
|
62
|
+
health: 1000,
|
|
63
|
+
fullHealth: 1000,
|
|
64
|
+
environmentEffects: [],
|
|
65
|
+
})
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
const attackingTeam = makeTeam([attacker])
|
|
69
|
+
const defendingTeam = makeTeam(enemies)
|
|
70
|
+
|
|
71
|
+
// RNG sequence:
|
|
72
|
+
// - 1 repeat_attack roll (once per special use): 0.6 (fail for chance=0.5)
|
|
73
|
+
// - 5 crit rolls (one per target): 0.9 (no crit)
|
|
74
|
+
const seq = [
|
|
75
|
+
0.6,
|
|
76
|
+
0.9, 0.9, 0.9, 0.9, 0.9,
|
|
77
|
+
]
|
|
78
|
+
let i = 0
|
|
79
|
+
const rng = () => {
|
|
80
|
+
if (i >= seq.length) return 0.99
|
|
81
|
+
return seq[i++]
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const result = attack(attacker, attackingTeam, defendingTeam, rng, true)
|
|
85
|
+
expect(result.repeatAttack).to.equal(false)
|
|
86
|
+
})
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
|