@pkmn/engine 0.1.0-dev.dc33f678 → 0.1.0-dev.dfd46bbb

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/build.zig CHANGED
@@ -224,30 +224,32 @@ pub fn build(b: *std.Build) !void {
224
224
  var benchmark_config = tools;
225
225
  benchmark_config.general.optimize = .ReleaseFast;
226
226
  benchmark_config.general.strip = true;
227
- const benchmark = tool(b, "src/test/benchmark.zig", benchmark_config);
227
+ const benchmark = try tool(b, "src/test/benchmark.zig", benchmark_config);
228
228
 
229
229
  var fuzz_config = tools;
230
230
  fuzz_config.general.strip = false;
231
231
  fuzz_config.tool.name = "fuzz";
232
- const fuzz = tool(b, "src/test/fuzz.zig", fuzz_config);
232
+ const fuzz = try tool(b, "src/test/fuzz.zig", fuzz_config);
233
233
 
234
- const analyze = tool(b, "src/tools/analyze.zig", tools);
235
- const dump = tool(b, "src/tools/dump.zig", tools);
236
- const transitions = tool(b, "src/tools/transitions.zig", tools);
234
+ const analyze = try tool(b, "src/tools/analyze.zig", tools);
235
+ const dump = try tool(b, "src/tools/dump.zig", tools);
236
+ const transitions = try tool(b, "src/tools/transitions.zig", tools);
237
237
 
238
238
  // FIXME: serde randomly fails to build in some release configurations
239
239
  var hack = tools;
240
240
  if (optimize != .Debug) hack.tool.tests = null;
241
- const serde = tool(b, "src/tools/serde.zig", hack);
241
+ const serde = try tool(b, "src/tools/serde.zig", hack);
242
242
 
243
- b.step("analyze", "Run LLVM analysis tool").dependOn(&analyze.step);
244
- b.step("benchmark", "Run benchmark code").dependOn(&benchmark.step);
245
- b.step("dump", "Run protocol dump tool").dependOn(&dump.step);
246
- b.step("fuzz", "Run fuzz tester").dependOn(&fuzz.step);
247
- b.step("serde", "Run serialization/deserialization tool").dependOn(&serde.step);
243
+ if (analyze) |t| b.step("analyze", "Run LLVM analysis tool").dependOn(&t.step);
244
+ if (benchmark) |t| b.step("benchmark", "Run benchmark code").dependOn(&t.step);
245
+ if (dump) |t| b.step("dump", "Run protocol dump tool").dependOn(&t.step);
246
+ if (fuzz) |t| b.step("fuzz", "Run fuzz tester").dependOn(&t.step);
247
+ if (serde) |t| b.step("serde", "Run serialization/deserialization tool").dependOn(&t.step);
248
248
  b.step("test", "Run all tests").dependOn(&tests.step);
249
249
  b.step("tools", "Install tools").dependOn(&ToolsStep.create(b, &exes).step);
250
- b.step("transitions", "Visualize transitions algorithm search").dependOn(&transitions.step);
250
+ if (transitions) |t| {
251
+ b.step("transitions", "Visualize transitions algorithm search").dependOn(&t.step);
252
+ }
251
253
  }
252
254
 
253
255
  fn maybeStrip(
@@ -326,7 +328,11 @@ const ToolConfig = struct {
326
328
  },
327
329
  };
328
330
 
329
- fn tool(b: *std.Build, path: []const u8, config: ToolConfig) *std.Build.RunStep {
331
+ fn tool(b: *std.Build, path: []const u8, config: ToolConfig) !?*std.Build.RunStep {
332
+ std.fs.cwd().access(path, .{}) catch |err| switch (err) {
333
+ error.FileNotFound => return null,
334
+ else => |e| return e,
335
+ };
330
336
  var name = config.tool.name orelse std.fs.path.basename(path);
331
337
  const index = std.mem.lastIndexOfScalar(u8, name, '.');
332
338
  if (index) |i| name = name[0..i];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pkmn/engine",
3
- "version": "0.1.0-dev.dc33f678",
3
+ "version": "0.1.0-dev.dfd46bbb",
4
4
  "description": "A minimal, complete, Pokémon battle simulation engine optimized for performance",
5
5
  "repository": "github:pkmn/engine",
6
6
  "license": "MIT",
@@ -52,11 +52,14 @@
52
52
  "src/lib/gen1/data/types.zig",
53
53
  "src/lib/gen1/helpers.zig",
54
54
  "src/lib/gen1/mechanics.zig",
55
+ "src/lib/gen2/calc.zig",
56
+ "src/lib/gen2/chance.zig",
55
57
  "src/lib/gen2/data.zig",
56
58
  "src/lib/gen2/data/items.zig",
57
59
  "src/lib/gen2/data/moves.zig",
58
60
  "src/lib/gen2/data/species.zig",
59
61
  "src/lib/gen2/data/types.zig",
62
+ "src/lib/gen2/generated.zig",
60
63
  "src/lib/gen2/helpers.zig",
61
64
  "src/lib/gen2/mechanics.zig",
62
65
  "src/lib/pkmn.zig",
@@ -90,7 +93,7 @@
90
93
  "binaryen": "^114.0.0",
91
94
  "eslint": "^8.51.0",
92
95
  "html-minifier": "^4.0.0",
93
- "json-stringify-pretty-compact": "4.0.0",
96
+ "json-stringify-pretty-compact": "3.0.0",
94
97
  "minimist": "^1.2.8",
95
98
  "mustache": "^4.2.0",
96
99
  "source-map-support": "^0.5.21",
@@ -9,12 +9,12 @@ pub const Player = enum(u1) {
9
9
  P2,
10
10
 
11
11
  /// Returns a player's opponent.
12
- pub inline fn foe(self: Player) Player {
12
+ pub fn foe(self: Player) Player {
13
13
  return @enumFromInt(~@intFromEnum(self));
14
14
  }
15
15
 
16
16
  /// Return's an identifier for the player's Pokémon at the one-indexed `id`.
17
- pub inline fn ident(self: Player, id: u3) ID {
17
+ pub fn ident(self: Player, id: u3) ID {
18
18
  assert(id > 0 and id <= 6);
19
19
  return .{ .id = id, .player = self };
20
20
  }
@@ -35,12 +35,12 @@ pub const ID = packed struct(u8) {
35
35
  _: u4 = 0,
36
36
 
37
37
  /// Converts the identifier into a number.
38
- pub inline fn int(self: ID) u4 {
38
+ pub fn int(self: ID) u4 {
39
39
  return @intCast(@as(u8, @bitCast(self)));
40
40
  }
41
41
 
42
42
  /// Decodes the identifier from a number.
43
- pub inline fn from(id: u4) ID {
43
+ pub fn from(id: u4) ID {
44
44
  return @bitCast(@as(u8, id));
45
45
  }
46
46
  };
@@ -196,7 +196,7 @@ pub const Activate = enum(u8) {
196
196
  Haze,
197
197
  Mist,
198
198
  Struggle,
199
- Substitute,
199
+ Substitute, // FIXME SubstituteDamage
200
200
  Splash,
201
201
 
202
202
  Rage, // TODO
@@ -208,6 +208,9 @@ pub const Activate = enum(u8) {
208
208
  FireSpin,
209
209
  Clamp,
210
210
  Whirlpool,
211
+ SubstituteBlock,
212
+
213
+ DestinyBond,
211
214
 
212
215
  BeatUp, // FIXME of
213
216
  };
@@ -254,6 +257,7 @@ pub const End = enum(u8) {
254
257
  Encore,
255
258
  FutureSight,
256
259
  LeechSeed,
260
+
257
261
  Bind,
258
262
  Wrap,
259
263
  FireSpin,
@@ -269,6 +273,8 @@ pub const End = enum(u8) {
269
273
  LightScreenSilent,
270
274
  ReflectSilent,
271
275
  BideSilent,
276
+
277
+ LeechSeedFrom,
272
278
  };
273
279
 
274
280
  pub const Immune = enum(u8) {
@@ -570,6 +576,7 @@ pub fn Log(comptime Writer: type) type {
570
576
  pub fn activate(self: Self, ident: ID, reason: Activate) Error!void {
571
577
  if (!enabled) return;
572
578
 
579
+ assert(reason != .SubstituteBlock); // TODO
573
580
  try self.writer.writeAll(&.{
574
581
  @intFromEnum(ArgType.Activate),
575
582
  @as(u8, @bitCast(ident)),
@@ -577,6 +584,18 @@ pub fn Log(comptime Writer: type) type {
577
584
  });
578
585
  }
579
586
 
587
+ pub fn activateMove(self: Self, ident: ID, reason: Activate, m: anytype) Error!void {
588
+ if (!enabled) return;
589
+
590
+ assert(reason == .SubstituteBlock); // TODO
591
+ try self.writer.writeAll(&.{
592
+ @intFromEnum(ArgType.Activate),
593
+ @as(u8, @bitCast(ident)),
594
+ @intFromEnum(reason),
595
+ @intFromEnum(m),
596
+ });
597
+ }
598
+
580
599
  pub fn fieldactivate(self: Self) Error!void {
581
600
  if (!enabled) return;
582
601
 
@@ -764,14 +783,13 @@ pub fn Log(comptime Writer: type) type {
764
783
  });
765
784
  }
766
785
 
767
- pub fn spikesend(self: Self, player: Player, m: anytype, source: ID) Error!void {
786
+ pub fn spikesend(self: Self, source: ID) Error!void {
768
787
  if (!enabled) return;
769
788
 
770
789
  try self.writer.writeAll(&.{
771
790
  @intFromEnum(ArgType.SideEnd),
772
- @intFromEnum(player),
791
+ @intFromEnum(source.player),
773
792
  @intFromEnum(Side.Spikes),
774
- @intFromEnum(m),
775
793
  @as(u8, @bitCast(source)),
776
794
  });
777
795
  }
@@ -1789,14 +1807,13 @@ test "|-sideend|" {
1789
1807
  try expectLog2(&.{ N(ArgType.SideEnd), 1, N(Side.LightScreen) }, buf[0..3]);
1790
1808
  stream.reset();
1791
1809
 
1792
- try log.spikesend(.P1, M2.RapidSpin, p1.ident(3));
1810
+ try log.spikesend(p1.ident(3));
1793
1811
  try expectLog2(&.{
1794
1812
  N(ArgType.SideEnd),
1795
1813
  0,
1796
1814
  N(Side.Spikes),
1797
- N(M2.RapidSpin),
1798
1815
  0b0011,
1799
- }, buf[0..5]);
1816
+ }, buf[0..4]);
1800
1817
  stream.reset();
1801
1818
  }
1802
1819
 
@@ -44,7 +44,7 @@ pub fn Rational(comptime T: type) type {
44
44
  /// Both p and q must be >= 1, and if computable at comptime must have no common factors.
45
45
  pub fn update(r: *Self, p: anytype, q: anytype) Error!void {
46
46
  // FIXME
47
- // std.debug.print("({d}/{d}) * ", .{p, q});
47
+ // std.debug.print("({d}/{d}) * ", .{ p, q });
48
48
  assert(p >= 1);
49
49
  assert(q >= 1);
50
50
 
@@ -185,12 +185,12 @@ pub fn Rational(comptime T: type) type {
185
185
  try writer.print("{d}/{d}", .{ self.p, self.q });
186
186
  }
187
187
 
188
- inline fn multiplication(r: *Self, p: anytype, q: anytype) !void {
188
+ fn multiplication(r: *Self, p: anytype, q: anytype) !void {
189
189
  r.p = try std.math.mul(T, r.p, p);
190
190
  r.q = try std.math.mul(T, r.q, q);
191
191
  }
192
192
 
193
- inline fn addition(r: *Self, p: anytype, q: anytype) !void {
193
+ fn addition(r: *Self, p: anytype, q: anytype) !void {
194
194
  // (a/b) + (c/d) = (ad+bc)/(bd)
195
195
  var d = try std.math.mul(T, r.q, q);
196
196
  var n1 = try std.math.mul(T, r.p, q);
@@ -203,7 +203,7 @@ pub fn Rational(comptime T: type) type {
203
203
  }
204
204
 
205
205
  // https://en.wikipedia.org/wiki/Euclidean_algorithm
206
- inline fn gcd(p: anytype, q: anytype) @TypeOf(p, q) {
206
+ fn gcd(p: anytype, q: anytype) @TypeOf(p, q) {
207
207
  assert(p >= 1);
208
208
  assert(q >= 1);
209
209
 
@@ -25,6 +25,11 @@ pub fn PRNG(comptime gen: comptime_int) type {
25
25
  pub fn next(self: *Self) Output(gen) {
26
26
  return self.src.next();
27
27
  }
28
+
29
+ pub fn advance(self: *Self, n: usize) void {
30
+ if (!options.advance) return;
31
+ for (0..n) |_| self.src.advance();
32
+ }
28
33
  };
29
34
  }
30
35
 
@@ -89,6 +94,10 @@ pub const Gen12 = extern struct {
89
94
  self.index = (self.index + 1) % 9;
90
95
  return val;
91
96
  }
97
+
98
+ pub fn advance(self: *Gen12) void {
99
+ _ = self.next();
100
+ }
92
101
  };
93
102
 
94
103
  test Gen12 {
@@ -50,7 +50,7 @@ pub const Summaries = extern struct {
50
50
  }
51
51
 
52
52
  /// Returns the `Summary` for the given `player`.
53
- pub inline fn get(self: anytype, player: Player) PointerType(@TypeOf(self), Summary) {
53
+ pub fn get(self: anytype, player: Player) PointerType(@TypeOf(self), Summary) {
54
54
  assert(@typeInfo(@TypeOf(self)).Pointer.child == Summaries);
55
55
  return if (player == .P1) &self.p1 else &self.p2;
56
56
  }
@@ -387,7 +387,7 @@ pub fn transitions(
387
387
  return stats;
388
388
  }
389
389
 
390
- inline fn matches(actions: Actions, i: usize, frontier: []Actions) bool {
390
+ fn matches(actions: Actions, i: usize, frontier: []Actions) bool {
391
391
  for (frontier, 0..) |f, j| {
392
392
  // TODO: is skipping this redundant check worth it?
393
393
  if (i == j) continue;
@@ -37,19 +37,19 @@ pub const Actions = extern struct {
37
37
  }
38
38
 
39
39
  /// Returns the `Action` for the given `player`.
40
- pub inline fn get(self: anytype, player: Player) util.PointerType(@TypeOf(self), Action) {
40
+ pub fn get(self: anytype, player: Player) util.PointerType(@TypeOf(self), Action) {
41
41
  assert(@typeInfo(@TypeOf(self)).Pointer.child == Actions);
42
42
  return if (player == .P1) &self.p1 else &self.p2;
43
43
  }
44
44
 
45
45
  /// Perform a reset by clearing fields which should not persist across updates.
46
- pub inline fn reset(self: *Actions) void {
46
+ pub fn reset(self: *Actions) void {
47
47
  self.p1.reset();
48
48
  self.p2.reset();
49
49
  }
50
50
 
51
51
  /// Returns true if `a` is equal to `b`.
52
- pub inline fn eql(a: Actions, b: Actions) bool {
52
+ pub fn eql(a: Actions, b: Actions) bool {
53
53
  return @as(u128, @bitCast(a)) == @as(u128, @bitCast(b));
54
54
  }
55
55
 
@@ -159,7 +159,7 @@ pub const Action = packed struct(u64) {
159
159
  pub const Field = std.meta.FieldEnum(Action);
160
160
 
161
161
  /// Perform a reset by clearing fields which should not persist across updates.
162
- pub inline fn reset(self: *Action) void {
162
+ pub fn reset(self: *Action) void {
163
163
  self.* = @bitCast(@as(u64, @bitCast(self.*)) & DURATIONS);
164
164
  }
165
165
 
@@ -1,4 +1,4 @@
1
- //! Code generated by `tools/generate` - manual edits will be overwritten
1
+ //! Code generated by `tools/generate` - manual edits will be overwritten.
2
2
 
3
3
  const std = @import("std");
4
4
 
@@ -1599,43 +1599,43 @@ pub const Move = enum(u8) {
1599
1599
  }
1600
1600
 
1601
1601
  /// Whether this effect activates during the "begin" step of move execution.
1602
- pub inline fn onBegin(effect: Effect) bool {
1602
+ pub fn onBegin(effect: Effect) bool {
1603
1603
  return @intFromEnum(effect) > 0 and @intFromEnum(effect) <= 16;
1604
1604
  }
1605
1605
 
1606
1606
  /// Whether this effect lowers stats.
1607
- pub inline fn isStatDown(effect: Effect) bool {
1607
+ pub fn isStatDown(effect: Effect) bool {
1608
1608
  return @intFromEnum(effect) > 16 and @intFromEnum(effect) <= 21;
1609
1609
  }
1610
1610
 
1611
1611
  /// Whether this effect activates during the "end" step of move execution.
1612
- pub inline fn onEnd(effect: Effect) bool {
1612
+ pub fn onEnd(effect: Effect) bool {
1613
1613
  return @intFromEnum(effect) > 16 and @intFromEnum(effect) <= 31;
1614
1614
  }
1615
1615
 
1616
1616
  /// Whether this effect is considered to "always happen".
1617
- pub inline fn alwaysHappens(effect: Effect) bool {
1617
+ pub fn alwaysHappens(effect: Effect) bool {
1618
1618
  return @intFromEnum(effect) > 31 and @intFromEnum(effect) <= 38;
1619
1619
  }
1620
1620
 
1621
1621
  /// Whether this effect is handled specially by the engine.
1622
- pub inline fn isSpecial(effect: Effect) bool {
1622
+ pub fn isSpecial(effect: Effect) bool {
1623
1623
  // NB: isSpecial includes isMulti up to Twineedle
1624
1624
  return @intFromEnum(effect) > 31 and @intFromEnum(effect) <= 46;
1625
1625
  }
1626
1626
 
1627
1627
  /// Whether this effect is a multi-hit effect.
1628
- pub inline fn isMulti(effect: Effect) bool {
1628
+ pub fn isMulti(effect: Effect) bool {
1629
1629
  return @intFromEnum(effect) > 44 and @intFromEnum(effect) <= 47;
1630
1630
  }
1631
1631
 
1632
1632
  /// Whether this effect is has chance of lowering stats.
1633
- pub inline fn isStatDownChance(effect: Effect) bool {
1633
+ pub fn isStatDownChance(effect: Effect) bool {
1634
1634
  return @intFromEnum(effect) > 47 and @intFromEnum(effect) <= 51;
1635
1635
  }
1636
1636
 
1637
1637
  /// Whether this effect has a secondary chance.
1638
- pub inline fn isSecondaryChance(effect: Effect) bool {
1638
+ pub fn isSecondaryChance(effect: Effect) bool {
1639
1639
  // NB: isSecondaryChance includes isStatDownChance as well as Twineedle
1640
1640
  return (@intFromEnum(effect) > 46 and @intFromEnum(effect) <= 61);
1641
1641
  }
@@ -1853,7 +1853,7 @@ pub const Move = enum(u8) {
1853
1853
  };
1854
1854
 
1855
1855
  /// Returns the `Data` corresponding to the move.
1856
- pub inline fn get(id: Move) Data {
1856
+ pub fn get(id: Move) Data {
1857
1857
  assert(id != .None and id != .SKIP_TURN);
1858
1858
  return DATA[@intFromEnum(id) - 1];
1859
1859
  }
@@ -1,4 +1,4 @@
1
- //! Code generated by `tools/generate` - manual edits will be overwritten
1
+ //! Code generated by `tools/generate` - manual edits will be overwritten.
2
2
 
3
3
  const std = @import("std");
4
4
 
@@ -1092,7 +1092,7 @@ pub const Species = enum(u8) {
1092
1092
  pub const size = 151;
1093
1093
 
1094
1094
  /// The Pokémon's critical hit rate=io out of 256.
1095
- pub inline fn chance(id: Species) u8 {
1095
+ pub fn chance(id: Species) u8 {
1096
1096
  assert(id != .None);
1097
1097
  return CHANCES[@intFromEnum(id) - 1];
1098
1098
  }
@@ -1,4 +1,4 @@
1
- //! Code generated by `tools/generate` - manual edits will be overwritten
1
+ //! Code generated by `tools/generate` - manual edits will be overwritten.
2
2
 
3
3
  const std = @import("std");
4
4
 
@@ -90,12 +90,12 @@ pub const Type = enum(u4) {
90
90
  pub const size = 15;
91
91
 
92
92
  /// Whether or not this type is considered to be special as opposed to physical.
93
- pub inline fn special(self: Type) bool {
93
+ pub fn special(self: Type) bool {
94
94
  return @intFromEnum(self) >= @intFromEnum(Type.Fire);
95
95
  }
96
96
 
97
97
  /// The `Effectiveness` of type `t2` vs. type `t1`.
98
- pub inline fn effectiveness(t1: Type, t2: Type) Effectiveness {
98
+ pub fn effectiveness(t1: Type, t2: Type) Effectiveness {
99
99
  return CHART[@intFromEnum(t1)][@intFromEnum(t2)];
100
100
  }
101
101
 
@@ -120,12 +120,12 @@ pub const Types = packed struct {
120
120
  }
121
121
 
122
122
  /// Whether this typing is immune to type `t`.
123
- pub inline fn immune(self: Types, t: Type) bool {
123
+ pub fn immune(self: Types, t: Type) bool {
124
124
  return t.effectiveness(self.type1) == I or t.effectiveness(self.type2) == I;
125
125
  }
126
126
 
127
127
  /// Whether this typing includes type `t`.
128
- pub inline fn includes(self: Types, t: Type) bool {
128
+ pub fn includes(self: Types, t: Type) bool {
129
129
  return self.type1 == t or self.type2 == t;
130
130
  }
131
131
  };
@@ -70,24 +70,24 @@ pub fn Battle(comptime RNG: anytype) type {
70
70
  rng: RNG,
71
71
 
72
72
  /// Returns the `Side` for the given `player`.
73
- pub inline fn side(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
73
+ pub fn side(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
74
74
  assert(@typeInfo(@TypeOf(self)).Pointer.child == Self);
75
75
  return &self.sides[@intFromEnum(player)];
76
76
  }
77
77
 
78
78
  /// Returns the `Side` of the opponent for the given `player`
79
- pub inline fn foe(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
79
+ pub fn foe(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
80
80
  assert(@typeInfo(@TypeOf(self)).Pointer.child == Self);
81
81
  return &self.sides[@intFromEnum(player.foe())];
82
82
  }
83
83
 
84
84
  /// Returns an identifier for the active Pokémon of `player`.
85
- pub inline fn active(self: *const Self, player: Player) ID {
85
+ pub fn active(self: *const Self, player: Player) ID {
86
86
  return player.ident(@intCast(self.side(player).order[0]));
87
87
  }
88
88
 
89
89
  /// Returns the `MoveDetails` for the given `player`.
90
- pub inline fn lastMove(
90
+ pub fn lastMove(
91
91
  self: anytype,
92
92
  player: Player,
93
93
  ) PointerType(@TypeOf(self), MoveDetails) {
@@ -141,7 +141,7 @@ pub const Side = extern struct {
141
141
  }
142
142
 
143
143
  /// Returns the stored `Pokemon` corresponding to the one-indexed party `slot`.
144
- pub inline fn get(self: anytype, slot: u8) PointerType(@TypeOf(self), Pokemon) {
144
+ pub fn get(self: anytype, slot: u8) PointerType(@TypeOf(self), Pokemon) {
145
145
  assert(@typeInfo(@TypeOf(self)).Pointer.child == Side);
146
146
  assert(slot > 0 and slot <= 6);
147
147
  const id = self.order[slot - 1];
@@ -150,7 +150,7 @@ pub const Side = extern struct {
150
150
  }
151
151
 
152
152
  /// Returns the stored `Pokemon` corresponding to the `active` Pokémon (slot 1).
153
- pub inline fn stored(self: anytype) PointerType(@TypeOf(self), Pokemon) {
153
+ pub fn stored(self: anytype) PointerType(@TypeOf(self), Pokemon) {
154
154
  assert(@typeInfo(@TypeOf(self)).Pointer.child == Side);
155
155
  return self.get(1);
156
156
  }
@@ -176,7 +176,7 @@ pub const ActivePokemon = extern struct {
176
176
  }
177
177
 
178
178
  /// Returns the active Pokémon's current move slot located at the one-indexed `mslot`.
179
- pub inline fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
179
+ pub fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
180
180
  assert(@typeInfo(@TypeOf(self)).Pointer.child == ActivePokemon);
181
181
  assert(mslot > 0 and mslot <= 4);
182
182
  assert(self.moves[mslot - 1].id != .None);
@@ -206,7 +206,7 @@ pub const Pokemon = extern struct {
206
206
  }
207
207
 
208
208
  /// Returns the Pokémon's original move slot located at the one-indexed `mslot`.
209
- pub inline fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
209
+ pub fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
210
210
  assert(@typeInfo(@TypeOf(self)).Pointer.child == Pokemon);
211
211
  assert(mslot > 0 and mslot <= 4);
212
212
  assert(self.moves[mslot - 1].id != .None);
@@ -258,36 +258,36 @@ pub const Status = enum(u8) {
258
258
  const SLP = 0b111;
259
259
 
260
260
  /// Whether or not the status `num` is the same as `status`.
261
- pub inline fn is(num: u8, status: Status) bool {
261
+ pub fn is(num: u8, status: Status) bool {
262
262
  if (status == .SLP) return Status.duration(num) > 0;
263
263
  return ((num >> @intCast(@intFromEnum(status))) & 1) != 0;
264
264
  }
265
265
 
266
266
  /// Initializes a non-sleep `status`. Use `slp` or `slf` to initialize a sleep status.
267
- pub inline fn init(status: Status) u8 {
267
+ pub fn init(status: Status) u8 {
268
268
  assert(status != .SLP and status != .EXT);
269
269
  return @as(u8, 1) << @intCast(@intFromEnum(status));
270
270
  }
271
271
 
272
272
  /// Initializes a non self-inflicted sleep status with duration `dur`.
273
- pub inline fn slp(dur: u3) u8 {
273
+ pub fn slp(dur: u3) u8 {
274
274
  assert(dur > 0);
275
275
  return @as(u8, dur);
276
276
  }
277
277
 
278
278
  /// Initializes a self-inflicted sleep status with duration `dur`.
279
- pub inline fn slf(dur: u3) u8 {
279
+ pub fn slf(dur: u3) u8 {
280
280
  assert(dur > 0);
281
281
  return 0x80 | slp(dur);
282
282
  }
283
283
 
284
284
  /// Returns the duration of a sleep status.
285
- pub inline fn duration(num: u8) u3 {
285
+ pub fn duration(num: u8) u3 {
286
286
  return @intCast(num & SLP);
287
287
  }
288
288
 
289
289
  /// Returns whether `num` reflects any status.
290
- pub inline fn any(num: u8) bool {
290
+ pub fn any(num: u8) bool {
291
291
  return num > 0;
292
292
  }
293
293
 
@@ -266,7 +266,7 @@ pub const Rolls = struct {
266
266
  const PLAYERS = [_]Optional(Player){ .P1, .P2 };
267
267
 
268
268
  /// Returns a slice with the correct range of values for speed ties given the `action` state.
269
- pub inline fn speedTie(action: Action) []const Optional(Player) {
269
+ pub fn speedTie(action: Action) []const Optional(Player) {
270
270
  return if (@field(action, "speed_tie") == .None) &PLAYER_NONE else &PLAYERS;
271
271
  }
272
272
 
@@ -275,14 +275,14 @@ pub const Rolls = struct {
275
275
 
276
276
  /// Returns a slice with the correct range of values for hits given the `action` state
277
277
  /// and the state of the `parent` (whether the player's Pokémon was fully paralyzed).
278
- pub inline fn hit(action: Action, parent: Optional(bool)) []const Optional(bool) {
278
+ pub fn hit(action: Action, parent: Optional(bool)) []const Optional(bool) {
279
279
  if (parent == .true) return &BOOL_NONE;
280
280
  return if (@field(action, "hit") == .None) &BOOL_NONE else &BOOLS;
281
281
  }
282
282
 
283
283
  /// Returns a slice with the correct range of values for critical hits given the `action` state
284
284
  /// and the state of the `parent` (whether the player's Pokémon's move hit).
285
- pub inline fn criticalHit(
285
+ pub fn criticalHit(
286
286
  action: Action,
287
287
  parent: Optional(bool),
288
288
  ) []const Optional(bool) {
@@ -292,7 +292,7 @@ pub const Rolls = struct {
292
292
 
293
293
  /// Returns a slice with the correct range of values for secondary chances hits given the
294
294
  /// `action` state and the state of the `parent` (whether the player's Pokémon's move hit).
295
- pub inline fn secondaryChance(
295
+ pub fn secondaryChance(
296
296
  action: Action,
297
297
  parent: Optional(bool),
298
298
  ) []const Optional(bool) {
@@ -305,7 +305,7 @@ pub const Rolls = struct {
305
305
 
306
306
  /// Returns the range bounding damage rolls given the `action` state and the state of
307
307
  /// the `parent` (whether the player's Pokémon's move hit).
308
- pub inline fn damage(action: Action, parent: Optional(bool)) Range {
308
+ pub fn damage(action: Action, parent: Optional(bool)) Range {
309
309
  return if (parent == .false or @field(action, "damage") == 0)
310
310
  .{ .min = 0, .max = 1 }
311
311
  else
@@ -314,7 +314,7 @@ pub const Rolls = struct {
314
314
 
315
315
  /// Returns the max damage roll which will produce the same damage as `roll`
316
316
  /// given the base damage in `summaries`.
317
- pub inline fn coalesce(player: Player, roll: u8, summaries: *calc.Summaries, cap: bool) !u8 {
317
+ pub fn coalesce(player: Player, roll: u8, summaries: *calc.Summaries, cap: bool) !u8 {
318
318
  if (roll == 0) return roll;
319
319
 
320
320
  const dmg = summaries.get(player.foe()).damage;
@@ -326,13 +326,13 @@ pub const Rolls = struct {
326
326
 
327
327
  /// Returns a slice with the correct range of values for confused given the `action` state
328
328
  /// and the state of the `parent` (the player's Pokémon's remaining confusion turns).
329
- pub inline fn confused(action: Action, parent: u4) []const Optional(bool) {
329
+ pub fn confused(action: Action, parent: u4) []const Optional(bool) {
330
330
  return if (parent == 0 or @field(action, "confused") == .None) &BOOL_NONE else &BOOLS;
331
331
  }
332
332
 
333
333
  /// Returns a slice with the correct range of values for paralysis given the `action` state
334
334
  /// and the state of the `parent` (whether the player's Pokémon was confused).
335
- pub inline fn paralyzed(action: Action, parent: Optional(bool)) []const Optional(bool) {
335
+ pub fn paralyzed(action: Action, parent: Optional(bool)) []const Optional(bool) {
336
336
  if (parent == .true) return &BOOL_NONE;
337
337
  return if (@field(action, "paralyzed") == .None) &BOOL_NONE else &BOOLS;
338
338
  }
@@ -342,7 +342,7 @@ pub const Rolls = struct {
342
342
 
343
343
  /// Returns a slice with a range of values for duration given the `action` state
344
344
  /// and the state of the `parent` (whether the player's Pokémon's move hit).
345
- pub inline fn duration(action: Action, parent: Optional(bool)) []const u1 {
345
+ pub fn duration(action: Action, parent: Optional(bool)) []const u1 {
346
346
  if (parent == .false) return &DURATION_NONE;
347
347
  return if (@field(action, "duration") == 0) &DURATION_NONE else &DURATION;
348
348
  }
@@ -418,7 +418,7 @@ pub const Rolls = struct {
418
418
  /// and the state of the `parent` (whether the player's Pokémon's move hit).
419
419
  ///
420
420
  /// These slots may or **may not be valid** as slots may be unset / have 0 PP.
421
- pub inline fn moveSlot(action: Action, parent: Optional(bool)) []const u4 {
421
+ pub fn moveSlot(action: Action, parent: Optional(bool)) []const u4 {
422
422
  if (parent == .false) return &SLOT_NONE;
423
423
  return if (@field(action, "move_slot") == 0) &SLOT_NONE else &SLOT;
424
424
  }
@@ -428,7 +428,7 @@ pub const Rolls = struct {
428
428
 
429
429
  /// Returns a slice with the correct range of values for multi hit given the `action` state
430
430
  /// and the state of the `parent` (whether the player's Pokémon's move hit).
431
- pub inline fn multiHit(action: Action, parent: Optional(bool)) []const u4 {
431
+ pub fn multiHit(action: Action, parent: Optional(bool)) []const u4 {
432
432
  if (parent == .false) return &MULTI_NONE;
433
433
  return if (@field(action, "multi_hit") == 0) &MULTI_NONE else &MULTI;
434
434
  }
@@ -442,7 +442,7 @@ pub const Rolls = struct {
442
442
 
443
443
  /// Returns a slice with the correct range of values for psywave given the `action` state,
444
444
  /// the `side`, and the state of the `parent` (whether the player's Pokémon's move hit).
445
- pub inline fn psywave(
445
+ pub fn psywave(
446
446
  action: Action,
447
447
  side: *data.Side,
448
448
  parent: Optional(bool),
@@ -457,7 +457,7 @@ pub const Rolls = struct {
457
457
  const MOVE_NONE = [_]Move{.None};
458
458
 
459
459
  /// Returns a slice with the correct range of values for metronome given the `action` state.
460
- pub inline fn metronome(action: Action) []const Move {
460
+ pub fn metronome(action: Action) []const Move {
461
461
  return if (@field(action, "metronome") == .None) &MOVE_NONE else &Move.METRONOME;
462
462
  }
463
463
  };