@pkmn/engine 0.1.0-dev.f3aaee39 → 0.1.0-dev.fc150752
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/package.json +11 -11
- package/src/lib/common/data.zig +3 -15
- package/src/lib/common/protocol.zig +79 -25
- package/src/lib/common/rng.zig +1 -1
- package/src/lib/gen1/README.md +3 -1
- package/src/lib/gen1/calc.zig +0 -1
- package/src/lib/gen1/chance.zig +2 -10
- package/src/lib/gen1/data/moves.zig +168 -170
- package/src/lib/gen1/data.zig +6 -18
- package/src/lib/gen1/mechanics.zig +19 -23
- package/src/lib/gen2/README.md +75 -0
- package/src/lib/gen2/data/moves.zig +634 -562
- package/src/lib/gen2/data.zig +67 -48
- package/src/lib/gen2/helpers.zig +8 -12
- package/src/lib/gen2/mechanics.zig +911 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pkmn/engine",
|
|
3
|
-
"version": "0.1.0-dev.
|
|
3
|
+
"version": "0.1.0-dev.fc150752",
|
|
4
4
|
"description": "A minimal, complete, Pokémon battle simulation engine optimized for performance",
|
|
5
5
|
"repository": "github:pkmn/engine",
|
|
6
6
|
"license": "MIT",
|
|
@@ -73,30 +73,30 @@
|
|
|
73
73
|
"access": "public"
|
|
74
74
|
},
|
|
75
75
|
"dependencies": {
|
|
76
|
-
"@pkmn/data": "^0.7.
|
|
77
|
-
"@pkmn/protocol": "^0.6.
|
|
76
|
+
"@pkmn/data": "^0.7.50",
|
|
77
|
+
"@pkmn/protocol": "^0.6.13"
|
|
78
78
|
},
|
|
79
79
|
"devDependencies": {
|
|
80
|
-
"@pkmn/eslint-config": "^5.
|
|
81
|
-
"@pkmn/img": "^0.2.
|
|
80
|
+
"@pkmn/eslint-config": "^5.2.0",
|
|
81
|
+
"@pkmn/img": "^0.2.15",
|
|
82
82
|
"@pkmn/sets": "^5.0.4",
|
|
83
|
-
"@pkmn/sim": "0.7.
|
|
83
|
+
"@pkmn/sim": "0.7.50",
|
|
84
84
|
"@types/html-minifier": "^4.0.2",
|
|
85
|
-
"@types/jest": "^29.5.
|
|
85
|
+
"@types/jest": "^29.5.4",
|
|
86
86
|
"@types/minimist": "^1.2.2",
|
|
87
87
|
"@types/mustache": "^4.2.2",
|
|
88
|
-
"@types/node": "^20.
|
|
88
|
+
"@types/node": "^20.5.9",
|
|
89
89
|
"@vitest/coverage-c8": "^0.33.0",
|
|
90
90
|
"binaryen": "^114.0.0",
|
|
91
|
-
"eslint": "^8.
|
|
91
|
+
"eslint": "^8.48.0",
|
|
92
92
|
"html-minifier": "^4.0.0",
|
|
93
93
|
"json-stringify-pretty-compact": "3.0.0",
|
|
94
94
|
"minimist": "^1.2.8",
|
|
95
95
|
"mustache": "^4.2.0",
|
|
96
96
|
"source-map-support": "^0.5.21",
|
|
97
97
|
"trakr": "^0.2.0",
|
|
98
|
-
"typescript": "^5.
|
|
99
|
-
"vitest": "^0.
|
|
98
|
+
"typescript": "^5.2.2",
|
|
99
|
+
"vitest": "^0.34.4"
|
|
100
100
|
},
|
|
101
101
|
"scripts": {
|
|
102
102
|
"lint": "eslint --cache src --ext ts,js && eslint src/bin/*",
|
package/src/lib/common/data.zig
CHANGED
|
@@ -27,17 +27,13 @@ test Player {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
/// An identifier for a specific Pokémon in battle.
|
|
30
|
-
pub const ID = packed struct {
|
|
30
|
+
pub const ID = packed struct(u8) {
|
|
31
31
|
/// The one-indexed team slot of the Pokémon
|
|
32
32
|
id: u3 = 0,
|
|
33
33
|
/// The Pokémon's trainer.
|
|
34
34
|
player: Player = .P1,
|
|
35
35
|
_: u4 = 0,
|
|
36
36
|
|
|
37
|
-
comptime {
|
|
38
|
-
assert(@sizeOf(ID) == 1);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
37
|
/// Converts the identifier into a number.
|
|
42
38
|
pub inline fn int(self: ID) u4 {
|
|
43
39
|
return @intCast(@as(u8, @bitCast(self)));
|
|
@@ -57,7 +53,7 @@ test ID {
|
|
|
57
53
|
}
|
|
58
54
|
|
|
59
55
|
/// A choice made by a player during battle.
|
|
60
|
-
pub const Choice = packed struct {
|
|
56
|
+
pub const Choice = packed struct(u8) {
|
|
61
57
|
/// The choice type.
|
|
62
58
|
type: Choice.Type = .Pass,
|
|
63
59
|
/// The choice data:
|
|
@@ -73,10 +69,6 @@ pub const Choice = packed struct {
|
|
|
73
69
|
Move,
|
|
74
70
|
Switch,
|
|
75
71
|
};
|
|
76
|
-
|
|
77
|
-
comptime {
|
|
78
|
-
assert(@sizeOf(Choice) == 1);
|
|
79
|
-
}
|
|
80
72
|
};
|
|
81
73
|
|
|
82
74
|
test Choice {
|
|
@@ -89,7 +81,7 @@ test Choice {
|
|
|
89
81
|
}
|
|
90
82
|
|
|
91
83
|
/// The result of the battle - all results other than 'None' should be considered terminal.
|
|
92
|
-
pub const Result = packed struct {
|
|
84
|
+
pub const Result = packed struct(u8) {
|
|
93
85
|
/// The type of result from the perspective of Player 1.
|
|
94
86
|
/// `Error` is not possible when in Pokémon Showdown compatibility mode.
|
|
95
87
|
type: Result.Type = .None,
|
|
@@ -117,10 +109,6 @@ pub const Result = packed struct {
|
|
|
117
109
|
pub const Error: Result = .{ .type = .Error };
|
|
118
110
|
/// The default result.
|
|
119
111
|
pub const Default: Result = .{ .p1 = .Move, .p2 = .Move };
|
|
120
|
-
|
|
121
|
-
comptime {
|
|
122
|
-
assert(@sizeOf(Result) == 1);
|
|
123
|
-
}
|
|
124
112
|
};
|
|
125
113
|
|
|
126
114
|
test Result {
|
|
@@ -136,6 +136,8 @@ pub const Damage = enum(u8) {
|
|
|
136
136
|
Confusion,
|
|
137
137
|
LeechSeed,
|
|
138
138
|
RecoilOf,
|
|
139
|
+
|
|
140
|
+
Spikes,
|
|
139
141
|
};
|
|
140
142
|
|
|
141
143
|
pub const Status = enum(u8) {
|
|
@@ -264,7 +266,15 @@ pub fn Log(comptime Writer: type) type {
|
|
|
264
266
|
if (!enabled) return;
|
|
265
267
|
|
|
266
268
|
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Switch), @as(u8, @bitCast(ident)) });
|
|
267
|
-
|
|
269
|
+
if (@hasField(@TypeOf(pokemon.*), "dvs")) {
|
|
270
|
+
try self.writer.writeAll(&.{
|
|
271
|
+
@intFromEnum(pokemon.species),
|
|
272
|
+
@intFromEnum(pokemon.dvs.gender),
|
|
273
|
+
pokemon.level,
|
|
274
|
+
});
|
|
275
|
+
} else {
|
|
276
|
+
try self.writer.writeAll(&.{ @intFromEnum(pokemon.species), pokemon.level });
|
|
277
|
+
}
|
|
268
278
|
try self.writer.writeIntNative(u16, pokemon.hp);
|
|
269
279
|
try self.writer.writeIntNative(u16, pokemon.stats.hp);
|
|
270
280
|
try self.writer.writeAll(&.{pokemon.status});
|
|
@@ -646,9 +656,13 @@ pub const ByteStream = struct {
|
|
|
646
656
|
};
|
|
647
657
|
|
|
648
658
|
pub const Kind = enum { Move, Species, Type, Status };
|
|
649
|
-
pub const Formatter = fn (Kind, u8) []const u8;
|
|
650
659
|
|
|
651
|
-
pub fn format(
|
|
660
|
+
pub fn format(
|
|
661
|
+
comptime gen: anytype,
|
|
662
|
+
a: []const u8,
|
|
663
|
+
b: ?[]const u8,
|
|
664
|
+
color: bool,
|
|
665
|
+
) void {
|
|
652
666
|
print("\n", .{});
|
|
653
667
|
|
|
654
668
|
var i: usize = 0;
|
|
@@ -701,17 +715,27 @@ pub fn format(comptime formatter: Formatter, a: []const u8, b: ?[]const u8, colo
|
|
|
701
715
|
.Move => {
|
|
702
716
|
const source = ID.from(@intCast(a[i]));
|
|
703
717
|
printc(" {s}({d})", .{ @tagName(source.player), source.id }, a, b, &i, 1, color);
|
|
704
|
-
printc(" {s}", .{formatter(.Move, a[i])}, a, b, &i, 1, color);
|
|
718
|
+
printc(" {s}", .{formatter(gen, .Move, a[i])}, a, b, &i, 1, color);
|
|
705
719
|
const target = ID.from(@intCast(a[i]));
|
|
706
720
|
printc(" {s}({d})", .{ @tagName(target.player), target.id }, a, b, &i, 1, color);
|
|
707
721
|
const reason: Move = @enumFromInt(a[i]);
|
|
708
722
|
printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
|
|
709
|
-
if (reason == .From)
|
|
723
|
+
if (reason == .From) {
|
|
724
|
+
printc(" {s}", .{formatter(gen, .Move, a[i])}, a, b, &i, 1, color);
|
|
725
|
+
}
|
|
710
726
|
},
|
|
711
727
|
.Switch => {
|
|
712
728
|
const id = ID.from(@intCast(a[i]));
|
|
713
729
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
714
|
-
printc(" {s}", .{formatter(.Species, a[i])}, a, b, &i, 1, color);
|
|
730
|
+
printc(" {s}", .{formatter(gen, .Species, a[i])}, a, b, &i, 1, color);
|
|
731
|
+
if (@hasDecl(gen, "Gender")) {
|
|
732
|
+
if (a[i] == N(gen.Gender.Unknown)) {
|
|
733
|
+
i += 1;
|
|
734
|
+
} else {
|
|
735
|
+
var gender = if (a[i] == N(gen.Gender.Male)) "M" else "F";
|
|
736
|
+
printc(", {s}", .{gender}, a, b, &i, 1, color);
|
|
737
|
+
}
|
|
738
|
+
}
|
|
715
739
|
printc(" L{d}", .{a[i]}, a, b, &i, 1, color);
|
|
716
740
|
switch (endian) {
|
|
717
741
|
.Big => {
|
|
@@ -727,7 +751,7 @@ pub fn format(comptime formatter: Formatter, a: []const u8, b: ?[]const u8, colo
|
|
|
727
751
|
printc("/{d}", .{hp}, a, b, &i, 2, color);
|
|
728
752
|
},
|
|
729
753
|
}
|
|
730
|
-
printc(" {s}", .{formatter(.Status, a[i])}, a, b, &i, 1, color);
|
|
754
|
+
printc(" {s}", .{formatter(gen, .Status, a[i])}, a, b, &i, 1, color);
|
|
731
755
|
},
|
|
732
756
|
.Cant => {
|
|
733
757
|
const id = ID.from(@intCast(a[i]));
|
|
@@ -735,7 +759,7 @@ pub fn format(comptime formatter: Formatter, a: []const u8, b: ?[]const u8, colo
|
|
|
735
759
|
const reason: Cant = @enumFromInt(a[i]);
|
|
736
760
|
printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
|
|
737
761
|
if (reason == .Disable) {
|
|
738
|
-
printc(" {s}", .{formatter(.Move, a[i])}, a, b, &i, 1, color);
|
|
762
|
+
printc(" {s}", .{formatter(gen, .Move, a[i])}, a, b, &i, 1, color);
|
|
739
763
|
}
|
|
740
764
|
},
|
|
741
765
|
.Faint,
|
|
@@ -775,7 +799,7 @@ pub fn format(comptime formatter: Formatter, a: []const u8, b: ?[]const u8, colo
|
|
|
775
799
|
printc("/{d}", .{hp}, a, b, &i, 2, color);
|
|
776
800
|
},
|
|
777
801
|
}
|
|
778
|
-
printc(" {s}", .{formatter(.Status, a[i])}, a, b, &i, 1, color);
|
|
802
|
+
printc(" {s}", .{formatter(gen, .Status, a[i])}, a, b, &i, 1, color);
|
|
779
803
|
if (arg == .Damage) {
|
|
780
804
|
const reason: Damage = @enumFromInt(a[i]);
|
|
781
805
|
printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
|
|
@@ -795,15 +819,17 @@ pub fn format(comptime formatter: Formatter, a: []const u8, b: ?[]const u8, colo
|
|
|
795
819
|
.Status => {
|
|
796
820
|
const id = ID.from(@intCast(a[i]));
|
|
797
821
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
798
|
-
printc(" {s}", .{formatter(.Status, a[i])}, a, b, &i, 1, color);
|
|
822
|
+
printc(" {s}", .{formatter(gen, .Status, a[i])}, a, b, &i, 1, color);
|
|
799
823
|
const reason: Status = @enumFromInt(a[i]);
|
|
800
824
|
printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
|
|
801
|
-
if (reason == .From)
|
|
825
|
+
if (reason == .From) {
|
|
826
|
+
printc(" {s}", .{formatter(gen, .Move, a[i])}, a, b, &i, 1, color);
|
|
827
|
+
}
|
|
802
828
|
},
|
|
803
829
|
.CureStatus => {
|
|
804
830
|
const id = ID.from(@intCast(a[i]));
|
|
805
831
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
806
|
-
printc(" {s}", .{formatter(.Status, a[i])}, a, b, &i, 1, color);
|
|
832
|
+
printc(" {s}", .{formatter(gen, .Status, a[i])}, a, b, &i, 1, color);
|
|
807
833
|
const reason: CureStatus = @enumFromInt(a[i]);
|
|
808
834
|
printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
|
|
809
835
|
},
|
|
@@ -826,7 +852,7 @@ pub fn format(comptime formatter: Formatter, a: []const u8, b: ?[]const u8, colo
|
|
|
826
852
|
.Prepare => {
|
|
827
853
|
const id = ID.from(@intCast(a[i]));
|
|
828
854
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
829
|
-
printc(" {s}", .{formatter(.Move, a[i])}, a, b, &i, 1, color);
|
|
855
|
+
printc(" {s}", .{formatter(gen, .Move, a[i])}, a, b, &i, 1, color);
|
|
830
856
|
},
|
|
831
857
|
.Activate => {
|
|
832
858
|
const id = ID.from(@intCast(a[i]));
|
|
@@ -841,12 +867,12 @@ pub fn format(comptime formatter: Formatter, a: []const u8, b: ?[]const u8, colo
|
|
|
841
867
|
if (@as(Start, @enumFromInt(reason)) == .TypeChange) {
|
|
842
868
|
const types = @as(gen1.Types, @bitCast(a[i]));
|
|
843
869
|
const args = .{
|
|
844
|
-
formatter(.Type, @intFromEnum(types.type1)),
|
|
845
|
-
formatter(.Type, @intFromEnum(types.type2)),
|
|
870
|
+
formatter(gen, .Type, @intFromEnum(types.type1)),
|
|
871
|
+
formatter(gen, .Type, @intFromEnum(types.type2)),
|
|
846
872
|
};
|
|
847
873
|
printc(" {s}/{s}", args, a, b, &i, 1, color);
|
|
848
874
|
} else if (reason >= @intFromEnum(Start.Disable)) {
|
|
849
|
-
printc(" {s}", .{formatter(.Move, a[i])}, a, b, &i, 1, color);
|
|
875
|
+
printc(" {s}", .{formatter(gen, .Move, a[i])}, a, b, &i, 1, color);
|
|
850
876
|
}
|
|
851
877
|
},
|
|
852
878
|
.End => {
|
|
@@ -896,7 +922,7 @@ fn printc(
|
|
|
896
922
|
}
|
|
897
923
|
|
|
898
924
|
pub fn expectLog(
|
|
899
|
-
comptime
|
|
925
|
+
comptime gen: anytype,
|
|
900
926
|
expected: []const u8,
|
|
901
927
|
actual: []const u8,
|
|
902
928
|
offset: usize,
|
|
@@ -915,8 +941,8 @@ pub fn expectLog(
|
|
|
915
941
|
|
|
916
942
|
expectEqualBytes(expected, actual, offset) catch |err| switch (err) {
|
|
917
943
|
error.TestExpectedEqual => {
|
|
918
|
-
format(
|
|
919
|
-
format(
|
|
944
|
+
format(gen, expected, null, color);
|
|
945
|
+
format(gen, actual, expected, color);
|
|
920
946
|
return err;
|
|
921
947
|
},
|
|
922
948
|
else => return err,
|
|
@@ -956,6 +982,11 @@ const gen1 = struct {
|
|
|
956
982
|
pub const helpers = @import("../gen1/helpers.zig");
|
|
957
983
|
};
|
|
958
984
|
|
|
985
|
+
const gen2 = struct {
|
|
986
|
+
pub usingnamespace @import("../gen2/data.zig");
|
|
987
|
+
pub const helpers = @import("../gen2/helpers.zig");
|
|
988
|
+
};
|
|
989
|
+
|
|
959
990
|
var buf: [gen1.LOGS_SIZE]u8 = undefined;
|
|
960
991
|
var stream = ByteStream{ .buffer = &buf };
|
|
961
992
|
var log: FixedLog = .{ .writer = stream.writer() };
|
|
@@ -964,15 +995,19 @@ const M = gen1.Move;
|
|
|
964
995
|
const S = gen1.Species;
|
|
965
996
|
|
|
966
997
|
fn expectLog1(expected: []const u8, actual: []const u8) !void {
|
|
967
|
-
return expectLog(
|
|
998
|
+
return expectLog(gen1, expected, actual, 0);
|
|
968
999
|
}
|
|
969
1000
|
|
|
970
|
-
fn
|
|
1001
|
+
fn expectLog2(expected: []const u8, actual: []const u8) !void {
|
|
1002
|
+
return expectLog(gen2, expected, actual, 0);
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
fn formatter(comptime gen: anytype, kind: Kind, byte: u8) []const u8 {
|
|
971
1006
|
return switch (kind) {
|
|
972
|
-
.Move => @tagName(@as(
|
|
973
|
-
.Species => @tagName(@as(
|
|
974
|
-
.Type => @tagName(@as(
|
|
975
|
-
.Status =>
|
|
1007
|
+
.Move => @tagName(@as(gen.Move, @enumFromInt(byte))),
|
|
1008
|
+
.Species => @tagName(@as(gen.Species, @enumFromInt(byte))),
|
|
1009
|
+
.Type => @tagName(@as(gen.Type, @enumFromInt(byte))),
|
|
1010
|
+
.Status => gen.Status.name(byte),
|
|
976
1011
|
};
|
|
977
1012
|
}
|
|
978
1013
|
|
|
@@ -1057,6 +1092,25 @@ test "|switch|" {
|
|
|
1057
1092
|
};
|
|
1058
1093
|
try expectLog1(expected, buf[0..9]);
|
|
1059
1094
|
stream.reset();
|
|
1095
|
+
|
|
1096
|
+
var blissey = gen2.helpers.Pokemon.init(.{ .species = .Blissey, .moves = &.{.Splash} });
|
|
1097
|
+
blissey.level = 91;
|
|
1098
|
+
blissey.hp = 200;
|
|
1099
|
+
blissey.stats.hp = 400;
|
|
1100
|
+
blissey.status = gen2.Status.init(.PAR);
|
|
1101
|
+
try log.switched(p2.ident(3), &blissey);
|
|
1102
|
+
expected = &(.{
|
|
1103
|
+
N(ArgType.Switch),
|
|
1104
|
+
0b1011,
|
|
1105
|
+
N(gen2.Species.Blissey),
|
|
1106
|
+
N(gen2.Gender.Female),
|
|
1107
|
+
91,
|
|
1108
|
+
} ++ switch (endian) {
|
|
1109
|
+
.Big => .{ 0, 200, 1, 144, par },
|
|
1110
|
+
.Little => .{ 200, 0, 144, 1, par },
|
|
1111
|
+
});
|
|
1112
|
+
try expectLog2(expected, buf[0..10]);
|
|
1113
|
+
stream.reset();
|
|
1060
1114
|
}
|
|
1061
1115
|
|
|
1062
1116
|
test "|cant|" {
|
package/src/lib/common/rng.zig
CHANGED
package/src/lib/gen1/README.md
CHANGED
|
@@ -612,7 +612,8 @@ engine, but the following moves have their broken behavior preserved in `-Dshowd
|
|
|
612
612
|
- **Roar** / **Whirlwind**: these moves can miss on Pokémon Showdown (and advance the RNG when
|
|
613
613
|
checking) which is incorrect (these moves should always fail, but don't check accuracy or advance
|
|
614
614
|
the RNG). More importantly, these moves should *not* cause the tracked last battle damage to be
|
|
615
|
-
zeroed, but on Pokémon Showdown they do.
|
|
615
|
+
zeroed, but on Pokémon Showdown they do. These should also `|-fail|...|[still]` instead of doing
|
|
616
|
+
nothing.
|
|
616
617
|
- **Substitute**: in addition to the [Substitute + Confusion
|
|
617
618
|
glitch](https://pkmn.cc/bulba-glitch-1#Substitute_.2B_Confusion_glitch) not being implemented
|
|
618
619
|
correctly (covered earlier), the [Substitute 1/4
|
|
@@ -634,6 +635,7 @@ only pedantic UI correctness):
|
|
|
634
635
|
|
|
635
636
|
- **Rage**: Rage should report the `|-boost|` before the Disable `|-miss|`, not after.
|
|
636
637
|
- **Haze**: Haze clears the status/volatiles in an incorrect order.
|
|
638
|
+
- **Teleport**: Teleport should `|-fail|...|[still]` instead of doing nothing.
|
|
637
639
|
- **Twineedle**: the `|-hitcount|` ("Hit 2 times") should come before the `|-status|` message, not
|
|
638
640
|
after.
|
|
639
641
|
- **Thrash** / **Petal Dance**: confusion should silently get applied before the `|move|` message,
|
package/src/lib/gen1/calc.zig
CHANGED
package/src/lib/gen1/chance.zig
CHANGED
|
@@ -115,7 +115,7 @@ test Actions {
|
|
|
115
115
|
|
|
116
116
|
/// Information about the RNG that was observed during a Generation I battle `update` for a
|
|
117
117
|
/// single player.
|
|
118
|
-
pub const Action = packed struct {
|
|
118
|
+
pub const Action = packed struct(u64) {
|
|
119
119
|
/// If not 0, the roll to be returned Rolls.damage.
|
|
120
120
|
damage: u8 = 0,
|
|
121
121
|
|
|
@@ -156,10 +156,6 @@ pub const Action = packed struct {
|
|
|
156
156
|
|
|
157
157
|
pub const Field = std.meta.FieldEnum(Action);
|
|
158
158
|
|
|
159
|
-
comptime {
|
|
160
|
-
assert(@sizeOf(Action) == 8);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
159
|
/// Perform a reset by clearing fields which should not persist across updates.
|
|
164
160
|
pub inline fn reset(self: *Action) void {
|
|
165
161
|
self.* = @bitCast(@as(u64, @bitCast(self.*)) & DURATIONS);
|
|
@@ -239,7 +235,7 @@ pub const Durations = extern struct {
|
|
|
239
235
|
|
|
240
236
|
/// Observed values for various durations that need to be tracked in order to properly
|
|
241
237
|
/// deduplicate transitions with a primary key. TODO
|
|
242
|
-
pub const Duration = packed struct {
|
|
238
|
+
pub const Duration = packed struct(u16) {
|
|
243
239
|
/// The number of turns a Pokémon has been observed to be sleeping.
|
|
244
240
|
sleep: u3 = 0,
|
|
245
241
|
/// The number of turns a Pokémon has been observed to be confused.
|
|
@@ -252,10 +248,6 @@ pub const Duration = packed struct {
|
|
|
252
248
|
binding: u3 = 0,
|
|
253
249
|
|
|
254
250
|
pub const Field = std.meta.FieldEnum(Duration);
|
|
255
|
-
|
|
256
|
-
comptime {
|
|
257
|
-
assert(@sizeOf(Duration) == 2);
|
|
258
|
-
}
|
|
259
251
|
};
|
|
260
252
|
|
|
261
253
|
pub const Commit = enum { hit, miss, binding };
|