@pkmn/engine 0.1.0-dev.deda8593 → 0.1.0-dev.e0a786f8
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 +9 -6
- package/build/pkg/addon/browser.d.ts +3 -0
- package/build/pkg/addon/browser.js +47 -0
- package/build/pkg/addon/browser.js.map +1 -0
- package/build/pkg/addon/node.d.ts +3 -0
- package/build/pkg/addon/node.js +110 -0
- package/build/pkg/addon/node.js.map +1 -0
- package/build/pkg/addon/wasm.d.ts +2 -0
- package/build/pkg/addon/wasm.js +53 -0
- package/build/pkg/addon/wasm.js.map +1 -0
- package/build/pkg/addon.d.ts +25 -3
- package/build/pkg/addon.js +34 -65
- package/build/pkg/addon.js.map +1 -1
- package/build/pkg/data/layout.json +15 -2
- package/build/pkg/data/protocol.json +23 -9
- package/build/pkg/data.d.ts +23 -1
- package/build/pkg/data.js.map +1 -1
- package/build/pkg/gen1.d.ts +15 -18
- package/build/pkg/gen1.js +28 -19
- package/build/pkg/gen1.js.map +1 -1
- package/build/pkg/index.d.ts +40 -90
- package/build/pkg/index.js +23 -70
- package/build/pkg/index.js.map +1 -1
- package/build/pkg/protocol.d.ts +20 -1
- package/build/pkg/protocol.js +105 -103
- package/build/pkg/protocol.js.map +1 -1
- package/build/tools/debug.js +52 -76
- package/build/tools/debug.js.map +1 -1
- package/build/tools/display/debug.jsx +152 -0
- package/build/tools/display/debug.jsx.map +1 -0
- package/build/tools/display/index.js +152 -0
- package/build/tools/display/index.js.map +1 -0
- package/build/tools/display/ui.jsx +359 -0
- package/build/tools/display/ui.jsx.map +1 -0
- package/build/tools/display/util.js +33 -0
- package/build/tools/display/util.js.map +1 -0
- package/build.zig +330 -85
- package/package.json +54 -135
- package/src/bin/install-pkmn-engine +10 -7
- package/src/bin/pkmn-debug +1 -1
- package/src/lib/bindings/c.zig +255 -0
- package/src/lib/bindings/node.zig +121 -0
- package/src/lib/bindings/wasm.zig +59 -0
- package/src/lib/common/array.zig +77 -0
- package/src/lib/common/data.zig +8 -8
- package/src/lib/common/debug.zig +39 -8
- package/src/lib/common/js.zig +4 -2
- package/src/lib/common/optional.zig +13 -9
- package/src/lib/common/options.zig +4 -0
- package/src/lib/common/protocol.zig +45 -44
- package/src/lib/common/rational.zig +323 -157
- package/src/lib/common/rng.zig +5 -7
- package/src/lib/common/util.zig +60 -1
- package/src/lib/gen1/calc.zig +527 -161
- package/src/lib/gen1/chance.zig +366 -240
- package/src/lib/gen1/data/moves.zig +2 -4
- package/src/lib/gen1/data/species.zig +1 -3
- package/src/lib/gen1/data/types.zig +1 -2
- package/src/lib/gen1/data.zig +35 -38
- package/src/lib/gen1/helpers.zig +17 -554
- package/src/lib/gen1/mechanics.zig +280 -193
- package/src/lib/gen2/calc.zig +37 -27
- package/src/lib/gen2/chance.zig +90 -503
- package/src/lib/gen2/data/items.zig +1 -3
- package/src/lib/gen2/data/moves.zig +2 -4
- package/src/lib/gen2/data/species.zig +1 -3
- package/src/lib/gen2/data/types.zig +1 -2
- package/src/lib/gen2/data.zig +26 -29
- package/src/lib/gen2/generated.zig +18 -23
- package/src/lib/gen2/helpers.zig +9 -18
- package/src/lib/gen2/mechanics.zig +88 -115
- package/src/lib/node.zig +3 -116
- package/src/lib/pkmn.zig +14 -7
- package/src/lib/wasm.zig +13 -9
- package/src/tools/display/dom.ts +93 -0
- package/src/tools/display/ui.css +354 -0
- package/build/test/display.js +0 -400
- package/build/test/display.js.map +0 -1
- package/src/test/display/pkmn.html.tmpl +0 -368
|
@@ -1,50 +1,37 @@
|
|
|
1
|
-
const std = @import("std");
|
|
2
|
-
|
|
3
|
-
const pkmn = @import("../pkmn.zig");
|
|
4
|
-
|
|
5
|
-
const common = @import("../common/data.zig");
|
|
6
1
|
const DEBUG = @import("../common/debug.zig").print;
|
|
7
|
-
const protocol = @import("../common/protocol.zig");
|
|
8
|
-
const rng = @import("../common/rng.zig");
|
|
9
|
-
const util = @import("../common/util.zig");
|
|
10
2
|
|
|
3
|
+
const builtin = @import("builtin");
|
|
4
|
+
const common = @import("../common/data.zig");
|
|
11
5
|
const data = @import("data.zig");
|
|
12
6
|
const generated = @import("generated.zig");
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
const expectEqualSlices = std.testing.expectEqualSlices;
|
|
18
|
-
const expectEqualStrings = std.testing.expectEqualStrings;
|
|
19
|
-
|
|
20
|
-
const showdown = pkmn.options.showdown;
|
|
21
|
-
|
|
22
|
-
const Choice = common.Choice;
|
|
23
|
-
const ID = common.ID;
|
|
24
|
-
const Player = common.Player;
|
|
25
|
-
const Result = common.Result;
|
|
7
|
+
const pkmn = @import("../pkmn.zig");
|
|
8
|
+
const protocol = @import("../common/protocol.zig");
|
|
9
|
+
const rng = @import("../common/rng.zig");
|
|
10
|
+
const std = @import("std");
|
|
26
11
|
|
|
27
12
|
const Activate = protocol.Activate;
|
|
13
|
+
const ActivePokemon = data.ActivePokemon;
|
|
14
|
+
const assert = std.debug.assert;
|
|
28
15
|
const Boost = protocol.Boost;
|
|
16
|
+
const Boosts = data.Boosts;
|
|
17
|
+
const Choice = common.Choice;
|
|
29
18
|
const Damage = protocol.Damage;
|
|
19
|
+
const Effectiveness = data.Effectiveness;
|
|
30
20
|
const End = protocol.End;
|
|
21
|
+
const expectEqual = std.testing.expectEqual;
|
|
22
|
+
const expectEqualSlices = std.testing.expectEqualSlices;
|
|
23
|
+
const expectEqualStrings = std.testing.expectEqualStrings;
|
|
31
24
|
const Fail = protocol.Fail;
|
|
32
|
-
const Heal = protocol.Heal;
|
|
33
|
-
const Start = protocol.Start;
|
|
34
|
-
|
|
35
25
|
const Gen12 = rng.Gen12;
|
|
36
|
-
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
const ActivePokemon = data.ActivePokemon;
|
|
40
|
-
const Boosts = data.Boosts;
|
|
41
|
-
const Effectiveness = data.Effectiveness;
|
|
26
|
+
const Heal = protocol.Heal;
|
|
27
|
+
const ID = common.ID;
|
|
42
28
|
const Item = data.Item;
|
|
43
29
|
const Move = data.Move;
|
|
44
|
-
const
|
|
45
|
-
const
|
|
30
|
+
const Player = common.Player;
|
|
31
|
+
const Result = common.Result;
|
|
32
|
+
const showdown = pkmn.options.showdown;
|
|
46
33
|
const Side = data.Side;
|
|
47
|
-
const
|
|
34
|
+
const Start = protocol.Start;
|
|
48
35
|
const Stats = data.Stats;
|
|
49
36
|
const Status = data.Status;
|
|
50
37
|
const TriAttack = data.TriAttack;
|
|
@@ -106,6 +93,7 @@ pub const State = struct {
|
|
|
106
93
|
type: Type, // BATTLE_VARS_MOVE_TYPE
|
|
107
94
|
accuracy: u8, // wEnemyMoveStruct + MOVE_ACC
|
|
108
95
|
move: Move, // wCurPlayerMove
|
|
96
|
+
hit: u3 = 0,
|
|
109
97
|
from: Move = .None,
|
|
110
98
|
mslot: u4, // wCurMoveNum
|
|
111
99
|
first: bool, // wEnemyGoesFirst
|
|
@@ -256,7 +244,6 @@ fn switchIn(battle: anytype, player: Player, slot: u8, kind: SwitchIn, options:
|
|
|
256
244
|
} else {
|
|
257
245
|
try options.log.switched(.{ battle.active(player), incoming });
|
|
258
246
|
}
|
|
259
|
-
options.chance.switched(player, side.pokemon[0].position, out);
|
|
260
247
|
|
|
261
248
|
if (side.conditions.Spikes and !active.types.includes(.Flying)) {
|
|
262
249
|
incoming.hp -|= @max(incoming.stats.hp / 8, 1);
|
|
@@ -442,18 +429,9 @@ fn beforeMove(battle: anytype, player: Player, move: Move, options: anytype) !bo
|
|
|
442
429
|
if (Status.is(stored.status, .SLP)) slp: {
|
|
443
430
|
const before = stored.status;
|
|
444
431
|
// Even if the EXT bit is set this will still correctly modify the sleep duration
|
|
445
|
-
// if (options.calc.modify(player, .sleep)) |extend| {
|
|
446
|
-
// if (!extend) stored.status = 0;
|
|
447
|
-
// } else {
|
|
448
432
|
stored.status -= 1;
|
|
449
|
-
// }
|
|
450
433
|
|
|
451
|
-
|
|
452
|
-
if (!Status.is(stored.status, .EXT)) {
|
|
453
|
-
try options.chance.sleep(player, duration);
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
if (duration == 0) {
|
|
434
|
+
if (Status.duration(stored.status) == 0) {
|
|
457
435
|
try log.curestatus(.{ ident, before, .Message });
|
|
458
436
|
stored.status = 0; // clears EXT if present
|
|
459
437
|
resetCant(volatiles);
|
|
@@ -483,12 +461,7 @@ fn beforeMove(battle: anytype, player: Player, move: Move, options: anytype) !bo
|
|
|
483
461
|
}
|
|
484
462
|
|
|
485
463
|
if (volatiles.disable.duration > 0) {
|
|
486
|
-
// if (options.calc.modify(player, .disable)) |extend| {
|
|
487
|
-
// if (!extend) volatiles.disable.duration = 0;
|
|
488
|
-
// } else {
|
|
489
464
|
volatiles.disable.duration -= 1;
|
|
490
|
-
// }
|
|
491
|
-
try options.chance.disable(player, volatiles.disable.duration);
|
|
492
465
|
|
|
493
466
|
if (volatiles.disable.duration == 0) {
|
|
494
467
|
volatiles.disable.move = 0;
|
|
@@ -498,13 +471,7 @@ fn beforeMove(battle: anytype, player: Player, move: Move, options: anytype) !bo
|
|
|
498
471
|
|
|
499
472
|
if (volatiles.Confusion) {
|
|
500
473
|
assert(volatiles.confusion > 0);
|
|
501
|
-
|
|
502
|
-
// if (options.calc.modify(player, .confusion)) |extend| {
|
|
503
|
-
// if (!extend) volatiles.confusion = 0;
|
|
504
|
-
// } else {
|
|
505
474
|
volatiles.confusion -= 1;
|
|
506
|
-
// }
|
|
507
|
-
try options.chance.confusion(player, volatiles.confusion);
|
|
508
475
|
|
|
509
476
|
if (volatiles.confusion == 0) {
|
|
510
477
|
volatiles.Confusion = false;
|
|
@@ -665,7 +632,7 @@ pub fn checkCriticalHit(battle: anytype, player: Player, state: *State, options:
|
|
|
665
632
|
}
|
|
666
633
|
assert(stage <= 4);
|
|
667
634
|
|
|
668
|
-
state.crit = try Rolls.criticalHit(battle, player, CRITICAL_HITS[stage], options);
|
|
635
|
+
state.crit = try Rolls.criticalHit(battle, player, state.hit, CRITICAL_HITS[stage], options);
|
|
669
636
|
}
|
|
670
637
|
|
|
671
638
|
pub fn calcDamage(
|
|
@@ -733,7 +700,7 @@ pub fn adjustDamage(battle: anytype, player: Player, state: *State, _: anytype)
|
|
|
733
700
|
|
|
734
701
|
pub fn randomizeDamage(battle: anytype, player: Player, state: *State, options: anytype) !void {
|
|
735
702
|
if (state.damage <= 1) return;
|
|
736
|
-
const random = try Rolls.damage(battle, player, options);
|
|
703
|
+
const random = try Rolls.damage(battle, player, state.hit, options);
|
|
737
704
|
options.calc.base(player.foe(), state.damage);
|
|
738
705
|
state.damage = @intCast(@as(u32, state.damage) *% random / 255);
|
|
739
706
|
options.calc.final(player.foe(), state.damage);
|
|
@@ -1226,7 +1193,7 @@ fn updateSideCondition(
|
|
|
1226
1193
|
fn endTurn(battle: anytype, options: anytype) @TypeOf(options.log).Error!Result {
|
|
1227
1194
|
battle.turn += 1;
|
|
1228
1195
|
|
|
1229
|
-
if (
|
|
1196
|
+
if (pkmn.options.mod and battle.turn >= 1000) {
|
|
1230
1197
|
try options.log.tie(.{});
|
|
1231
1198
|
return Result.Tie;
|
|
1232
1199
|
} else if (battle.turn >= 65535) {
|
|
@@ -1341,13 +1308,7 @@ pub const Effects = struct {
|
|
|
1341
1308
|
|
|
1342
1309
|
if (!volatiles.Bide) return;
|
|
1343
1310
|
|
|
1344
|
-
// if (options.calc.modify(player, .attacking)) |extend| {
|
|
1345
|
-
// if (!extend) volatiles.attacks = 0;
|
|
1346
|
-
// } else {
|
|
1347
1311
|
volatiles.attacks -= 1;
|
|
1348
|
-
// }
|
|
1349
|
-
try options.chance.attacking(player, volatiles.attacks);
|
|
1350
|
-
|
|
1351
1312
|
if (volatiles.attacks != 0) return options.log.activate(.{ ident, .Bide });
|
|
1352
1313
|
|
|
1353
1314
|
volatiles.Bide = false;
|
|
@@ -1466,7 +1427,8 @@ pub const Effects = struct {
|
|
|
1466
1427
|
if (move.type.special() != (last == .MirrorCoat)) return;
|
|
1467
1428
|
if (state.damage == 0) return;
|
|
1468
1429
|
|
|
1469
|
-
|
|
1430
|
+
// NOTE: llvm/llvm-project#58557
|
|
1431
|
+
state.damage = smul(state.damage, 2);
|
|
1470
1432
|
state.miss = false;
|
|
1471
1433
|
}
|
|
1472
1434
|
|
|
@@ -1561,15 +1523,18 @@ pub const Effects = struct {
|
|
|
1561
1523
|
|
|
1562
1524
|
pub const double = struct {
|
|
1563
1525
|
pub fn flying(battle: anytype, player: Player, state: *State, _: anytype) !void {
|
|
1564
|
-
if (battle.foe(player).active.volatiles.Flying)
|
|
1526
|
+
if (!battle.foe(player).active.volatiles.Flying) return;
|
|
1527
|
+
state.damage = smul(state.damage, 2);
|
|
1565
1528
|
}
|
|
1566
1529
|
|
|
1567
1530
|
pub fn underground(battle: anytype, player: Player, state: *State, _: anytype) !void {
|
|
1568
|
-
if (battle.foe(player).active.volatiles.Underground)
|
|
1531
|
+
if (!battle.foe(player).active.volatiles.Underground) return;
|
|
1532
|
+
state.damage = smul(state.damage, 2);
|
|
1569
1533
|
}
|
|
1570
1534
|
|
|
1571
1535
|
pub fn minimize(battle: anytype, player: Player, state: *State, _: anytype) !void {
|
|
1572
|
-
if (battle.foe(player).active.volatiles.minimized)
|
|
1536
|
+
if (!battle.foe(player).active.volatiles.minimized) return;
|
|
1537
|
+
state.damage = smul(state.damage, 2);
|
|
1573
1538
|
}
|
|
1574
1539
|
};
|
|
1575
1540
|
|
|
@@ -1738,7 +1703,7 @@ pub const Effects = struct {
|
|
|
1738
1703
|
if (!state.proc) return;
|
|
1739
1704
|
if (foe.conditions.Safeguard) return;
|
|
1740
1705
|
// Freeze Clause Mod
|
|
1741
|
-
if (
|
|
1706
|
+
if (pkmn.options.mod) for (foe.pokemon) |p| if (Status.is(p.status, .FRZ)) return;
|
|
1742
1707
|
|
|
1743
1708
|
foe_stored.status = Status.init(.FRZ);
|
|
1744
1709
|
try options.log.status(.{ foe_ident, foe_stored.status, .None });
|
|
@@ -1767,7 +1732,7 @@ pub const Effects = struct {
|
|
|
1767
1732
|
state.bp *= 2;
|
|
1768
1733
|
assert(state.bp <= 160);
|
|
1769
1734
|
} else {
|
|
1770
|
-
state.damage
|
|
1735
|
+
state.damage = smul(state.damage, 2);
|
|
1771
1736
|
}
|
|
1772
1737
|
}
|
|
1773
1738
|
|
|
@@ -2238,7 +2203,7 @@ pub const Effects = struct {
|
|
|
2238
2203
|
|
|
2239
2204
|
pub fn pursuit(battle: anytype, player: Player, state: *State, _: anytype) !void {
|
|
2240
2205
|
// TODO: remove switching variable and just look at Choice saved in Battle struct?
|
|
2241
|
-
if (battle.foe(player).active.volatiles.switching) state.damage
|
|
2206
|
+
if (battle.foe(player).active.volatiles.switching) state.damage = smul(state.damage, 2);
|
|
2242
2207
|
}
|
|
2243
2208
|
|
|
2244
2209
|
pub const rage = struct {
|
|
@@ -2251,7 +2216,7 @@ pub const Effects = struct {
|
|
|
2251
2216
|
const side = battle.side(player);
|
|
2252
2217
|
|
|
2253
2218
|
assert(side.active.volatiles.Rage);
|
|
2254
|
-
state.damage
|
|
2219
|
+
state.damage = smul(state.damage, (side.active.volatiles.rage +| 1)); // TODO: |+
|
|
2255
2220
|
}
|
|
2256
2221
|
};
|
|
2257
2222
|
|
|
@@ -2346,7 +2311,7 @@ pub const Effects = struct {
|
|
|
2346
2311
|
side.active.volatiles.attacks += 1;
|
|
2347
2312
|
side.active.volatiles.Rollout = side.active.volatiles.attacks != 5;
|
|
2348
2313
|
|
|
2349
|
-
if (side.active.volatiles.DefenseCurl) state.damage
|
|
2314
|
+
if (side.active.volatiles.DefenseCurl) state.damage = smul(state.damage, 2);
|
|
2350
2315
|
}
|
|
2351
2316
|
};
|
|
2352
2317
|
|
|
@@ -2416,7 +2381,7 @@ pub const Effects = struct {
|
|
|
2416
2381
|
}
|
|
2417
2382
|
|
|
2418
2383
|
// Sleep Clause Mod
|
|
2419
|
-
if (
|
|
2384
|
+
if (pkmn.options.mod) {
|
|
2420
2385
|
for (foe.pokemon) |p| {
|
|
2421
2386
|
if (Status.is(p.status, .SLP) and !Status.is(p.status, .EXT)) return;
|
|
2422
2387
|
}
|
|
@@ -2874,9 +2839,15 @@ fn convertible(active: ActivePokemon, m: Move) bool {
|
|
|
2874
2839
|
return t != .@"???" and !active.types.includes(t);
|
|
2875
2840
|
}
|
|
2876
2841
|
|
|
2842
|
+
// NOTE: llvm/llvm-project#58557
|
|
2843
|
+
fn smul(a: anytype, b: @TypeOf(a)) @TypeOf(a) {
|
|
2844
|
+
if (!comptime builtin.target.isWasm()) return a *| b;
|
|
2845
|
+
return @max(a *% b, std.math.maxInt(@TypeOf(a)));
|
|
2846
|
+
}
|
|
2847
|
+
|
|
2877
2848
|
pub const Rolls = struct {
|
|
2878
2849
|
fn speedTie(battle: anytype, options: anytype) !bool {
|
|
2879
|
-
const p1 = if (options.calc.overridden(.P1, .speed_tie)) |player|
|
|
2850
|
+
const p1 = if (options.calc.overridden(.P1, 0, .speed_tie)) |player|
|
|
2880
2851
|
player == .P1
|
|
2881
2852
|
else if (showdown)
|
|
2882
2853
|
battle.rng.range(u8, 0, 2) == 0
|
|
@@ -2888,7 +2859,7 @@ pub const Rolls = struct {
|
|
|
2888
2859
|
}
|
|
2889
2860
|
|
|
2890
2861
|
fn quickClaw(battle: anytype, player: Player, options: anytype) !bool {
|
|
2891
|
-
const qkc = if (options.calc.overridden(player, .quick_claw)) |val|
|
|
2862
|
+
const qkc = if (options.calc.overridden(player, 0, .quick_claw)) |val|
|
|
2892
2863
|
val == .true
|
|
2893
2864
|
else if (showdown)
|
|
2894
2865
|
battle.rng.chance(u8, 60, 256)
|
|
@@ -2900,7 +2871,7 @@ pub const Rolls = struct {
|
|
|
2900
2871
|
}
|
|
2901
2872
|
|
|
2902
2873
|
fn hit(battle: anytype, player: Player, accuracy: u8, options: anytype) !bool {
|
|
2903
|
-
const ok = if (options.calc.overridden(player, .hit)) |val|
|
|
2874
|
+
const ok = if (options.calc.overridden(player, 0, .hit)) |val|
|
|
2904
2875
|
val == .true
|
|
2905
2876
|
else if (showdown)
|
|
2906
2877
|
battle.rng.chance(u8, accuracy, 256)
|
|
@@ -2911,20 +2882,22 @@ pub const Rolls = struct {
|
|
|
2911
2882
|
return ok;
|
|
2912
2883
|
}
|
|
2913
2884
|
|
|
2914
|
-
fn criticalHit(battle: anytype, player: Player, rate: u8, options: anytype) !bool {
|
|
2915
|
-
|
|
2885
|
+
fn criticalHit(battle: anytype, player: Player, i: u3, rate: u8, options: anytype) !bool {
|
|
2886
|
+
_ = .{ player, options };
|
|
2887
|
+
const crit = if (options.calc.overridden(player, i, .critical_hits)) |val|
|
|
2916
2888
|
val == .true
|
|
2917
2889
|
else if (showdown)
|
|
2918
2890
|
battle.rng.chance(u8, rate, 256)
|
|
2919
2891
|
else
|
|
2920
2892
|
battle.rng.next() < rate;
|
|
2921
2893
|
|
|
2922
|
-
try options.chance.criticalHit(player, crit, rate);
|
|
2894
|
+
try options.chance.criticalHit(player, i, crit, rate);
|
|
2923
2895
|
return crit;
|
|
2924
2896
|
}
|
|
2925
2897
|
|
|
2926
|
-
fn damage(battle: anytype, player: Player, options: anytype) !u8 {
|
|
2927
|
-
|
|
2898
|
+
fn damage(battle: anytype, player: Player, i: u3, options: anytype) !u8 {
|
|
2899
|
+
_ = .{ player, options };
|
|
2900
|
+
const roll = if (options.calc.overridden(player, i, .damages)) |val|
|
|
2928
2901
|
val
|
|
2929
2902
|
else roll: {
|
|
2930
2903
|
if (showdown) break :roll battle.rng.range(u8, 217, 256);
|
|
@@ -2935,12 +2908,12 @@ pub const Rolls = struct {
|
|
|
2935
2908
|
};
|
|
2936
2909
|
|
|
2937
2910
|
assert(roll >= 217 and roll <= 255);
|
|
2938
|
-
try options.chance.damage(player, roll);
|
|
2911
|
+
try options.chance.damage(player, i, roll);
|
|
2939
2912
|
return roll;
|
|
2940
2913
|
}
|
|
2941
2914
|
|
|
2942
2915
|
fn confused(battle: anytype, player: Player, options: anytype) !bool {
|
|
2943
|
-
const cfz = if (options.calc.overridden(player, .confused)) |val|
|
|
2916
|
+
const cfz = if (options.calc.overridden(player, 0, .confused)) |val|
|
|
2944
2917
|
val == .true
|
|
2945
2918
|
else if (showdown)
|
|
2946
2919
|
!battle.rng.chance(u8, 128, 256)
|
|
@@ -2952,7 +2925,7 @@ pub const Rolls = struct {
|
|
|
2952
2925
|
}
|
|
2953
2926
|
|
|
2954
2927
|
fn attract(battle: anytype, player: Player, options: anytype) !bool {
|
|
2955
|
-
const cant = if (options.calc.overridden(player, .attract)) |val|
|
|
2928
|
+
const cant = if (options.calc.overridden(player, 0, .attract)) |val|
|
|
2956
2929
|
val == .true
|
|
2957
2930
|
else if (showdown)
|
|
2958
2931
|
battle.rng.chance(u8, 1, 2)
|
|
@@ -2964,7 +2937,7 @@ pub const Rolls = struct {
|
|
|
2964
2937
|
}
|
|
2965
2938
|
|
|
2966
2939
|
fn paralyzed(battle: anytype, player: Player, options: anytype) !bool {
|
|
2967
|
-
const par = if (options.calc.overridden(player, .paralyzed)) |val|
|
|
2940
|
+
const par = if (options.calc.overridden(player, 0, .paralyzed)) |val|
|
|
2968
2941
|
val == .true
|
|
2969
2942
|
else if (showdown)
|
|
2970
2943
|
battle.rng.chance(u8, 63, 256)
|
|
@@ -2976,7 +2949,7 @@ pub const Rolls = struct {
|
|
|
2976
2949
|
}
|
|
2977
2950
|
|
|
2978
2951
|
fn defrost(battle: anytype, player: Player, options: anytype) !bool {
|
|
2979
|
-
const thaw = if (options.calc.overridden(player, .defrost)) |val|
|
|
2952
|
+
const thaw = if (options.calc.overridden(player, 0, .defrost)) |val|
|
|
2980
2953
|
val == .true
|
|
2981
2954
|
else if (showdown)
|
|
2982
2955
|
battle.rng.chance(u8, 25, 256)
|
|
@@ -2989,7 +2962,7 @@ pub const Rolls = struct {
|
|
|
2989
2962
|
|
|
2990
2963
|
fn secondaryChance(battle: anytype, player: Player, rate: u8, options: anytype) !bool {
|
|
2991
2964
|
// GLITCH: 100% secondary chance will still fail 1/256 of the time
|
|
2992
|
-
const proc = if (options.calc.overridden(player, .secondary_chance)) |val|
|
|
2965
|
+
const proc = if (options.calc.overridden(player, 0, .secondary_chance)) |val|
|
|
2993
2966
|
val == .true
|
|
2994
2967
|
else if (showdown)
|
|
2995
2968
|
battle.rng.chance(u8, rate, 256)
|
|
@@ -3001,7 +2974,7 @@ pub const Rolls = struct {
|
|
|
3001
2974
|
}
|
|
3002
2975
|
|
|
3003
2976
|
fn item(battle: anytype, player: Player, options: anytype) !bool {
|
|
3004
|
-
const proc = if (options.calc.overridden(player, .item)) |val|
|
|
2977
|
+
const proc = if (options.calc.overridden(player, 0, .item)) |val|
|
|
3005
2978
|
val == .true
|
|
3006
2979
|
else if (showdown)
|
|
3007
2980
|
battle.rng.chance(u8, 30, 256)
|
|
@@ -3013,7 +2986,7 @@ pub const Rolls = struct {
|
|
|
3013
2986
|
}
|
|
3014
2987
|
|
|
3015
2988
|
fn triAttack(battle: anytype, player: Player, options: anytype) !TriAttack {
|
|
3016
|
-
const status: TriAttack = if (options.calc.overridden(player, .tri_attack)) |val|
|
|
2989
|
+
const status: TriAttack = if (options.calc.overridden(player, 0, .tri_attack)) |val|
|
|
3017
2990
|
@enumFromInt(@intFromEnum(val) - 1)
|
|
3018
2991
|
else if (showdown)
|
|
3019
2992
|
@enumFromInt(battle.rng.range(u2, 0, 2))
|
|
@@ -3029,7 +3002,7 @@ pub const Rolls = struct {
|
|
|
3029
3002
|
}
|
|
3030
3003
|
|
|
3031
3004
|
fn present(battle: anytype, player: Player, options: anytype) !u8 {
|
|
3032
|
-
const power = if (options.calc.overridden(player, .present)) |val|
|
|
3005
|
+
const power = if (options.calc.overridden(player, 0, .present)) |val|
|
|
3033
3006
|
(val - 1) * 40
|
|
3034
3007
|
else if (showdown) power: {
|
|
3035
3008
|
const r = battle.rng.range(u8, 0, 10);
|
|
@@ -3051,7 +3024,7 @@ pub const Rolls = struct {
|
|
|
3051
3024
|
}
|
|
3052
3025
|
|
|
3053
3026
|
fn magnitude(battle: anytype, player: Player, options: anytype) !u8 {
|
|
3054
|
-
const num: u8 = if (options.calc.overridden(player, .magnitude)) |val|
|
|
3027
|
+
const num: u8 = if (options.calc.overridden(player, 0, .magnitude)) |val|
|
|
3055
3028
|
val + 3
|
|
3056
3029
|
else if (showdown) num: {
|
|
3057
3030
|
const r = battle.rng.range(u8, 0, 100);
|
|
@@ -3079,7 +3052,7 @@ pub const Rolls = struct {
|
|
|
3079
3052
|
}
|
|
3080
3053
|
|
|
3081
3054
|
fn tripleKick(battle: anytype, player: Player, options: anytype) !u2 {
|
|
3082
|
-
const hits = if (options.calc.overridden(player, .triple_kick)) |val|
|
|
3055
|
+
const hits = if (options.calc.overridden(player, 0, .triple_kick)) |val|
|
|
3083
3056
|
val
|
|
3084
3057
|
else if (showdown)
|
|
3085
3058
|
battle.rng.range(u2, 1, 4)
|
|
@@ -3097,7 +3070,7 @@ pub const Rolls = struct {
|
|
|
3097
3070
|
|
|
3098
3071
|
fn spite(battle: anytype, player: Player, options: anytype) !u3 {
|
|
3099
3072
|
assert(!showdown);
|
|
3100
|
-
const pp: u3 = if (options.calc.overridden(player, .spite)) |val|
|
|
3073
|
+
const pp: u3 = if (options.calc.overridden(player, 0, .spite)) |val|
|
|
3101
3074
|
val + 1
|
|
3102
3075
|
else
|
|
3103
3076
|
@intCast((battle.rng.next() & 3) + 2);
|
|
@@ -3114,7 +3087,7 @@ pub const Rolls = struct {
|
|
|
3114
3087
|
var i: u8 = 0;
|
|
3115
3088
|
const neutral = @intFromEnum(Effectiveness.Neutral);
|
|
3116
3089
|
assert(mtype != .@"???");
|
|
3117
|
-
const ty: Type = if (options.calc.overridden(player, .conversion_2)) |val|
|
|
3090
|
+
const ty: Type = if (options.calc.overridden(player, 0, .conversion_2)) |val|
|
|
3118
3091
|
@enumFromInt(@intFromEnum(val) - 1)
|
|
3119
3092
|
else if (showdown) ty: {
|
|
3120
3093
|
for (Type.SHOWDOWN) |t| {
|
|
@@ -3148,7 +3121,7 @@ pub const Rolls = struct {
|
|
|
3148
3121
|
assert(count <= 8);
|
|
3149
3122
|
const num = if (count == 8) 0 else @as(u8, 255) >> @intCast(count);
|
|
3150
3123
|
|
|
3151
|
-
const ok = if (options.calc.overridden(player, .protect)) |val|
|
|
3124
|
+
const ok = if (options.calc.overridden(player, 0, .protect)) |val|
|
|
3152
3125
|
val == .true
|
|
3153
3126
|
else if (showdown)
|
|
3154
3127
|
battle.rng.chance(u8, num, 255)
|
|
@@ -3170,7 +3143,7 @@ pub const Rolls = struct {
|
|
|
3170
3143
|
const moves = active.moves;
|
|
3171
3144
|
|
|
3172
3145
|
// TODO: consider throwing error instead of rerolling?
|
|
3173
|
-
const overridden = if (options.calc.overridden(player, .move_slot)) |val|
|
|
3146
|
+
const overridden = if (options.calc.overridden(player, 0, .move_slot)) |val|
|
|
3174
3147
|
if (convertible(active, moves[val - 1].id)) val else null
|
|
3175
3148
|
else
|
|
3176
3149
|
null;
|
|
@@ -3207,7 +3180,7 @@ pub const Rolls = struct {
|
|
|
3207
3180
|
const moves = active.moves;
|
|
3208
3181
|
|
|
3209
3182
|
// TODO: consider throwing error instead of rerolling?
|
|
3210
|
-
const overridden = if (options.calc.overridden(player, .move_slot)) |val|
|
|
3183
|
+
const overridden = if (options.calc.overridden(player, 0, .move_slot)) |val|
|
|
3211
3184
|
if (val != mslot and Move.get(moves[val - 1].id).extra.sleep_talk) val else null
|
|
3212
3185
|
else
|
|
3213
3186
|
null;
|
|
@@ -3251,7 +3224,7 @@ pub const Rolls = struct {
|
|
|
3251
3224
|
assert(n > 0 and n <= 6);
|
|
3252
3225
|
|
|
3253
3226
|
// TODO: consider throwing error instead of rerolling?
|
|
3254
|
-
const overridden = if (options.calc.overridden(player, .force_switch)) |val| val: {
|
|
3227
|
+
const overridden = if (options.calc.overridden(player, 0, .force_switch)) |val| val: {
|
|
3255
3228
|
for (slots) |slot| if (slot == val) break :val if (foe.get(slot).hp > 0) val else null;
|
|
3256
3229
|
break :val null;
|
|
3257
3230
|
} else null;
|
|
@@ -3277,7 +3250,7 @@ pub const Rolls = struct {
|
|
|
3277
3250
|
const DISTRIBUTION = [_]u3{ 2, 2, 2, 3, 3, 3, 4, 5 };
|
|
3278
3251
|
|
|
3279
3252
|
fn multiHit(battle: anytype, player: Player, options: anytype) !u3 {
|
|
3280
|
-
const n: u3 = if (options.calc.overridden(player, .multi_hit)) |val|
|
|
3253
|
+
const n: u3 = if (options.calc.overridden(player, 0, .multi_hit)) |val|
|
|
3281
3254
|
@intCast(val)
|
|
3282
3255
|
else if (showdown)
|
|
3283
3256
|
DISTRIBUTION[battle.rng.range(u3, 0, DISTRIBUTION.len)]
|
|
@@ -3292,7 +3265,7 @@ pub const Rolls = struct {
|
|
|
3292
3265
|
}
|
|
3293
3266
|
|
|
3294
3267
|
fn psywave(battle: anytype, player: Player, max: u8, options: anytype) !u8 {
|
|
3295
|
-
const power = if (options.calc.overridden(player, .psywave)) |val|
|
|
3268
|
+
const power = if (options.calc.overridden(player, 0, .psywave)) |val|
|
|
3296
3269
|
val
|
|
3297
3270
|
else if (showdown)
|
|
3298
3271
|
battle.rng.range(u8, 1, max)
|
|
@@ -3318,7 +3291,7 @@ pub const Rolls = struct {
|
|
|
3318
3291
|
}
|
|
3319
3292
|
|
|
3320
3293
|
// TODO: consider throwing error instead of rerolling?
|
|
3321
|
-
const overridden = if (options.calc.overridden(player, .metronome)) |val| val: {
|
|
3294
|
+
const overridden = if (options.calc.overridden(player, 0, .metronome)) |val| val: {
|
|
3322
3295
|
for (moves) |m| if (m.id == val) break :val null;
|
|
3323
3296
|
break :val val;
|
|
3324
3297
|
} else null;
|
|
@@ -3350,7 +3323,7 @@ pub const Rolls = struct {
|
|
|
3350
3323
|
}
|
|
3351
3324
|
|
|
3352
3325
|
fn sleepDuration(battle: anytype, player: Player, options: anytype) u3 {
|
|
3353
|
-
const duration: u3 = if (options.calc.overridden(player, .duration)) |val|
|
|
3326
|
+
const duration: u3 = if (options.calc.overridden(player, 0, .duration)) |val|
|
|
3354
3327
|
@intCast(val)
|
|
3355
3328
|
else if (showdown)
|
|
3356
3329
|
battle.rng.range(u3, 1, 7)
|
|
@@ -3362,12 +3335,12 @@ pub const Rolls = struct {
|
|
|
3362
3335
|
};
|
|
3363
3336
|
|
|
3364
3337
|
assert(duration >= 1 and duration <= 6);
|
|
3365
|
-
options.chance.duration(
|
|
3338
|
+
options.chance.duration(player, duration);
|
|
3366
3339
|
return duration + 1;
|
|
3367
3340
|
}
|
|
3368
3341
|
|
|
3369
3342
|
fn confusionDuration(battle: anytype, player: Player, self: bool, options: anytype) u3 {
|
|
3370
|
-
const duration: u3 = if (options.calc.overridden(player, .duration)) |val|
|
|
3343
|
+
const duration: u3 = if (options.calc.overridden(player, 0, .duration)) |val|
|
|
3371
3344
|
@intCast(val)
|
|
3372
3345
|
else if (showdown)
|
|
3373
3346
|
// Pokémon Showdown incorrectly uses the same duration for self-confusion
|
|
@@ -3376,16 +3349,16 @@ pub const Rolls = struct {
|
|
|
3376
3349
|
@intCast((battle.rng.next() & if (self) 1 else 3) + 2);
|
|
3377
3350
|
|
|
3378
3351
|
assert(duration >= 2 and duration <= if (!showdown and self) 3 else 5);
|
|
3379
|
-
options.chance.duration(
|
|
3352
|
+
options.chance.duration(player, duration);
|
|
3380
3353
|
return duration;
|
|
3381
3354
|
}
|
|
3382
3355
|
|
|
3383
3356
|
fn disableDuration(battle: anytype, player: Player, options: anytype) u4 {
|
|
3384
|
-
const duration:
|
|
3357
|
+
const duration: u3 = if (options.calc.overridden(player, 0, .duration)) |val|
|
|
3385
3358
|
@intCast(val)
|
|
3386
3359
|
else if (showdown)
|
|
3387
3360
|
// Pokémon Showdown incorrectly inherits Generation III's Disable duration
|
|
3388
|
-
battle.rng.range(
|
|
3361
|
+
battle.rng.range(u3, 2, 6)
|
|
3389
3362
|
else duration: {
|
|
3390
3363
|
while (true) {
|
|
3391
3364
|
const r = battle.rng.next() & 7;
|
|
@@ -3394,12 +3367,12 @@ pub const Rolls = struct {
|
|
|
3394
3367
|
};
|
|
3395
3368
|
|
|
3396
3369
|
assert(duration >= 2 and duration <= (if (showdown) 5 else 7));
|
|
3397
|
-
options.chance.duration(
|
|
3370
|
+
options.chance.duration(player, duration);
|
|
3398
3371
|
return duration;
|
|
3399
3372
|
}
|
|
3400
3373
|
|
|
3401
3374
|
fn attackingDuration(battle: anytype, player: Player, options: anytype) u3 {
|
|
3402
|
-
const duration: u3 = if (options.calc.overridden(player, .duration)) |val|
|
|
3375
|
+
const duration: u3 = if (options.calc.overridden(player, 0, .duration)) |val|
|
|
3403
3376
|
@intCast(val)
|
|
3404
3377
|
else if (showdown)
|
|
3405
3378
|
battle.rng.range(u3, 2, 4)
|
|
@@ -3407,12 +3380,12 @@ pub const Rolls = struct {
|
|
|
3407
3380
|
@intCast((battle.rng.next() & 1) + 2); // BUG: thrash is + 1 not +2
|
|
3408
3381
|
|
|
3409
3382
|
assert(duration >= 2 and duration <= 3);
|
|
3410
|
-
options.chance.duration(
|
|
3383
|
+
options.chance.duration(player, duration);
|
|
3411
3384
|
return duration;
|
|
3412
3385
|
}
|
|
3413
3386
|
|
|
3414
3387
|
fn bindingDuration(battle: anytype, player: Player, options: anytype) u3 {
|
|
3415
|
-
const duration: u3 = (if (options.calc.overridden(player, .duration)) |val|
|
|
3388
|
+
const duration: u3 = (if (options.calc.overridden(player, 0, .duration)) |val|
|
|
3416
3389
|
@intCast(val)
|
|
3417
3390
|
else if (showdown)
|
|
3418
3391
|
// TODO: PS does range(3, 6) here which after subtracting 1 is actually 2-4 not 2-5!
|
|
@@ -3421,13 +3394,13 @@ pub const Rolls = struct {
|
|
|
3421
3394
|
@intCast(battle.rng.next() & 3 + 2));
|
|
3422
3395
|
|
|
3423
3396
|
assert(duration >= 2 and duration <= 5);
|
|
3424
|
-
options.chance.duration(
|
|
3397
|
+
options.chance.duration(player, duration);
|
|
3425
3398
|
return duration + 1;
|
|
3426
3399
|
}
|
|
3427
3400
|
|
|
3428
3401
|
// TODO: consider sharing implementation with bindingDuration
|
|
3429
3402
|
fn encoreDuration(battle: anytype, player: Player, options: anytype) u3 {
|
|
3430
|
-
const duration: u3 = (if (options.calc.overridden(player, .duration)) |val|
|
|
3403
|
+
const duration: u3 = (if (options.calc.overridden(player, 0, .duration)) |val|
|
|
3431
3404
|
@intCast(val)
|
|
3432
3405
|
else if (showdown)
|
|
3433
3406
|
battle.rng.range(u3, 2, 6)
|
|
@@ -3435,7 +3408,7 @@ pub const Rolls = struct {
|
|
|
3435
3408
|
@intCast(battle.rng.next() & 3 + 2));
|
|
3436
3409
|
|
|
3437
3410
|
assert(duration >= 2 and duration <= 5);
|
|
3438
|
-
options.chance.duration(
|
|
3411
|
+
options.chance.duration(player, duration);
|
|
3439
3412
|
return duration + 1;
|
|
3440
3413
|
}
|
|
3441
3414
|
};
|