@pkmn/engine 0.1.0-dev.3de821b9 → 0.1.0-dev.3f3af84c
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 +100 -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 +11 -12
- package/build/pkg/gen1.js.map +1 -1
- package/build/pkg/index.d.ts +40 -90
- package/build/pkg/index.js +6 -63
- 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 +35 -69
- package/build/tools/debug.js.map +1 -1
- package/build/tools/display/debug.jsx +141 -0
- package/build/tools/display/debug.jsx.map +1 -0
- package/build/tools/display/index.js +142 -0
- package/build/tools/display/index.js.map +1 -0
- package/build/tools/display/ui.jsx +349 -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 +53 -134
- 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 +44 -43
- package/src/lib/common/rational.zig +53 -51
- package/src/lib/common/rng.zig +5 -7
- package/src/lib/common/util.zig +50 -1
- package/src/lib/gen1/calc.zig +250 -111
- package/src/lib/gen1/chance.zig +130 -121
- 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 +15 -27
- package/src/lib/gen1/mechanics.zig +118 -95
- package/src/lib/gen2/calc.zig +37 -27
- package/src/lib/gen2/chance.zig +86 -66
- 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 +81 -81
- 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 +96 -0
- package/src/tools/display/ui.css +354 -0
- package/build/test/display.js +0 -405
- package/build/test/display.js.map +0 -1
- package/src/test/display/pkmn.html.tmpl +0 -368
package/src/lib/gen1/chance.zig
CHANGED
|
@@ -1,26 +1,31 @@
|
|
|
1
|
-
const std = @import("std");
|
|
2
|
-
|
|
3
|
-
const assert = std.debug.assert;
|
|
4
|
-
const print = std.debug.print;
|
|
5
|
-
|
|
6
|
-
const expect = std.testing.expect;
|
|
7
|
-
const expectEqual = std.testing.expectEqual;
|
|
8
|
-
|
|
9
1
|
const DEBUG = @import("../common/debug.zig").print;
|
|
2
|
+
|
|
3
|
+
const array = @import("../common/array.zig");
|
|
4
|
+
const common = @import("../common/data.zig");
|
|
5
|
+
const data = @import("data.zig");
|
|
6
|
+
const optional = @import("../common/optional.zig");
|
|
10
7
|
const options = @import("../common/options.zig");
|
|
11
8
|
const rational = @import("../common/rational.zig");
|
|
9
|
+
const std = @import("std");
|
|
12
10
|
const util = @import("../common/util.zig");
|
|
13
11
|
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
const data = @import("data.zig");
|
|
18
|
-
|
|
12
|
+
const Array = array.Array;
|
|
13
|
+
const assert = std.debug.assert;
|
|
19
14
|
const enabled = options.chance;
|
|
20
|
-
const
|
|
21
|
-
|
|
15
|
+
const expect = std.testing.expect;
|
|
16
|
+
const expectEqual = std.testing.expectEqual;
|
|
17
|
+
const isPointerTo = util.isPointerTo;
|
|
22
18
|
const Move = data.Move;
|
|
23
19
|
const MoveSlot = data.MoveSlot;
|
|
20
|
+
const Optional = optional.Optional;
|
|
21
|
+
const Player = common.Player;
|
|
22
|
+
const PointerType = util.PointerType;
|
|
23
|
+
const print = std.debug.print;
|
|
24
|
+
const showdown = options.showdown;
|
|
25
|
+
|
|
26
|
+
const Int = if (@hasField(std.builtin.Type, "int")) .int else .Int;
|
|
27
|
+
const Enum = if (@hasField(std.builtin.Type, "enum")) .@"enum" else .Enum;
|
|
28
|
+
const Struct = if (@hasField(std.builtin.Type, "struct")) .@"struct" else .Struct;
|
|
24
29
|
|
|
25
30
|
/// Actions taken by a hypothetical "chance player" that convey information about which RNG events
|
|
26
31
|
/// were observed during a Generation I battle `update`. This can additionally be provided as input
|
|
@@ -37,8 +42,8 @@ pub const Actions = extern struct {
|
|
|
37
42
|
}
|
|
38
43
|
|
|
39
44
|
/// Returns the `Action` for the given `player`.
|
|
40
|
-
pub fn get(self: anytype, player: Player)
|
|
41
|
-
assert(
|
|
45
|
+
pub fn get(self: anytype, player: Player) PointerType(@TypeOf(self), Action) {
|
|
46
|
+
assert(isPointerTo(self, Actions));
|
|
42
47
|
return if (player == .P1) &self.p1 else &self.p2;
|
|
43
48
|
}
|
|
44
49
|
|
|
@@ -51,15 +56,15 @@ pub const Actions = extern struct {
|
|
|
51
56
|
/// same shape if they have the same fields set (though those fields need not necessarily be
|
|
52
57
|
/// set to the same value).
|
|
53
58
|
pub fn matches(a: Actions, b: Actions) bool {
|
|
54
|
-
inline for (@typeInfo(Actions)
|
|
55
|
-
inline for (@typeInfo(Action)
|
|
59
|
+
inline for (@field(@typeInfo(Actions), @tagName(Struct)).fields) |player| {
|
|
60
|
+
inline for (@field(@typeInfo(Action), @tagName(Struct)).fields) |field| {
|
|
56
61
|
const a_val = @field(@field(a, player.name), field.name);
|
|
57
62
|
const b_val = @field(@field(b, player.name), field.name);
|
|
58
63
|
|
|
59
64
|
switch (@typeInfo(@TypeOf(a_val))) {
|
|
60
|
-
|
|
65
|
+
Enum => if ((@intFromEnum(a_val) > 0) != (@intFromEnum(b_val) > 0))
|
|
61
66
|
return false,
|
|
62
|
-
|
|
67
|
+
Int => if ((a_val > 0) != (b_val > 0)) return false,
|
|
63
68
|
else => unreachable,
|
|
64
69
|
}
|
|
65
70
|
}
|
|
@@ -67,6 +72,25 @@ pub const Actions = extern struct {
|
|
|
67
72
|
return true;
|
|
68
73
|
}
|
|
69
74
|
|
|
75
|
+
/// TODO
|
|
76
|
+
pub fn matchesAny(a: Actions, bs: []Actions, i: usize) bool {
|
|
77
|
+
for (bs, 0..) |b, j| {
|
|
78
|
+
// TODO: is skipping this redundant check worth it?
|
|
79
|
+
if (i == j) continue;
|
|
80
|
+
if (b.matches(a)) return true;
|
|
81
|
+
}
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/// TODO
|
|
86
|
+
pub fn relax(actions: Actions) Actions {
|
|
87
|
+
if (!options.overwrite) return actions;
|
|
88
|
+
var a = actions;
|
|
89
|
+
if (a.p1.confusion == .overwritten) a.p1.confusion = .continuing;
|
|
90
|
+
if (a.p2.confusion == .overwritten) a.p2.confusion = .continuing;
|
|
91
|
+
return a;
|
|
92
|
+
}
|
|
93
|
+
|
|
70
94
|
pub fn fmt(self: Actions, writer: anytype, shape: bool) !void {
|
|
71
95
|
try writer.writeAll("<P1 = ");
|
|
72
96
|
try self.p1.fmt(writer, shape);
|
|
@@ -144,15 +168,15 @@ pub const Action = packed struct(u64) {
|
|
|
144
168
|
/// TODO
|
|
145
169
|
disable: Optional(Observation) = .None,
|
|
146
170
|
/// TODO
|
|
147
|
-
|
|
171
|
+
attacking: Optional(Observation) = .None,
|
|
148
172
|
/// TODO
|
|
149
173
|
binding: Optional(Observation) = .None,
|
|
150
|
-
|
|
151
|
-
|
|
174
|
+
|
|
175
|
+
_: u1 = 0,
|
|
152
176
|
|
|
153
177
|
/// If not 0, the move slot (1-4) to return in Rolls.moveSlot. If present as an override,
|
|
154
178
|
/// invalid values (eg. due to empty move slots or 0 PP) will be ignored.
|
|
155
|
-
move_slot:
|
|
179
|
+
move_slot: u4 = 0,
|
|
156
180
|
|
|
157
181
|
/// TODO
|
|
158
182
|
pp: u4 = 0,
|
|
@@ -175,10 +199,10 @@ pub const Action = packed struct(u64) {
|
|
|
175
199
|
pub fn fmt(self: Action, writer: anytype, shape: bool) !void {
|
|
176
200
|
try writer.writeByte('(');
|
|
177
201
|
var printed = false;
|
|
178
|
-
inline for (@typeInfo(Action)
|
|
202
|
+
inline for (@field(@typeInfo(Action), @tagName(Struct)).fields) |field| {
|
|
179
203
|
const val = @field(self, field.name);
|
|
180
204
|
switch (@typeInfo(@TypeOf(val))) {
|
|
181
|
-
|
|
205
|
+
Enum => if (val != .None) {
|
|
182
206
|
if (printed) try writer.writeAll(", ");
|
|
183
207
|
if (shape) {
|
|
184
208
|
try writer.print("{s}:?", .{field.name});
|
|
@@ -199,7 +223,7 @@ pub const Action = packed struct(u64) {
|
|
|
199
223
|
}
|
|
200
224
|
printed = true;
|
|
201
225
|
},
|
|
202
|
-
|
|
226
|
+
Int => if (val != 0) {
|
|
203
227
|
if (printed) try writer.writeAll(", ");
|
|
204
228
|
if (shape) {
|
|
205
229
|
try writer.print("{s}:?", .{field.name});
|
|
@@ -216,15 +240,19 @@ pub const Action = packed struct(u64) {
|
|
|
216
240
|
};
|
|
217
241
|
|
|
218
242
|
/// TODO
|
|
219
|
-
pub const Durations = struct {
|
|
243
|
+
pub const Durations = extern struct {
|
|
220
244
|
/// TODO
|
|
221
245
|
p1: Duration = .{},
|
|
222
246
|
/// TODO
|
|
223
247
|
p2: Duration = .{},
|
|
224
248
|
|
|
249
|
+
comptime {
|
|
250
|
+
assert(@sizeOf(Durations) == 8);
|
|
251
|
+
}
|
|
252
|
+
|
|
225
253
|
/// TODO
|
|
226
|
-
pub fn get(self: anytype, player: Player)
|
|
227
|
-
assert(
|
|
254
|
+
pub fn get(self: anytype, player: Player) PointerType(@TypeOf(self), Duration) {
|
|
255
|
+
assert(isPointerTo(self, Durations));
|
|
228
256
|
return if (player == .P1) &self.p1 else &self.p2;
|
|
229
257
|
}
|
|
230
258
|
|
|
@@ -239,15 +267,18 @@ pub const Durations = struct {
|
|
|
239
267
|
}
|
|
240
268
|
};
|
|
241
269
|
|
|
270
|
+
pub const Sleeps = Array(6, u3);
|
|
271
|
+
|
|
242
272
|
/// TODO
|
|
243
|
-
pub const Duration = struct {
|
|
244
|
-
sleeps:
|
|
273
|
+
pub const Duration = packed struct(u32) {
|
|
274
|
+
sleeps: Sleeps.T = 0,
|
|
245
275
|
confusion: u3 = 0,
|
|
246
276
|
disable: u4 = 0,
|
|
247
|
-
|
|
248
|
-
thrashing: u3 = 0,
|
|
277
|
+
attacking: u3 = 0,
|
|
249
278
|
binding: u3 = 0,
|
|
250
279
|
|
|
280
|
+
_: u1 = 0,
|
|
281
|
+
|
|
251
282
|
pub fn format(
|
|
252
283
|
self: Duration,
|
|
253
284
|
comptime fmt: []const u8,
|
|
@@ -257,27 +288,22 @@ pub const Duration = struct {
|
|
|
257
288
|
_ = .{ fmt, opts };
|
|
258
289
|
try writer.writeByte('(');
|
|
259
290
|
var printed = false;
|
|
260
|
-
inline for (@typeInfo(Duration)
|
|
291
|
+
inline for (@field(@typeInfo(Duration), @tagName(Struct)).fields) |field| {
|
|
261
292
|
const val = @field(self, field.name);
|
|
262
293
|
switch (@typeInfo(@TypeOf(val))) {
|
|
263
|
-
|
|
294
|
+
Int => if (val != 0) {
|
|
264
295
|
if (printed) try writer.writeAll(", ");
|
|
265
|
-
|
|
266
|
-
printed = true;
|
|
267
|
-
},
|
|
268
|
-
.Array => {
|
|
269
|
-
var total: usize = 0;
|
|
270
|
-
for (val) |v| total += v;
|
|
271
|
-
if (total > 0) {
|
|
272
|
-
if (printed) try writer.writeAll(", ");
|
|
296
|
+
if (comptime std.mem.eql(u8, field.name, "sleeps")) {
|
|
273
297
|
try writer.print("{s}:[", .{field.name});
|
|
274
|
-
for (
|
|
298
|
+
for (0..6) |i| {
|
|
275
299
|
if (i != 0) try writer.writeByte(',');
|
|
276
|
-
try writer.print("{d}", .{
|
|
300
|
+
try writer.print("{d}", .{Sleeps.get(val, i)});
|
|
277
301
|
}
|
|
278
302
|
try writer.writeAll("]");
|
|
279
|
-
|
|
303
|
+
} else {
|
|
304
|
+
try writer.print("{s}:{d}", .{ field.name, val });
|
|
280
305
|
}
|
|
306
|
+
printed = true;
|
|
281
307
|
},
|
|
282
308
|
else => unreachable,
|
|
283
309
|
}
|
|
@@ -365,7 +391,7 @@ pub fn Chance(comptime Rational: type) type {
|
|
|
365
391
|
|
|
366
392
|
// If the move actually lands we can commit any past critical hit / damage rolls. Note
|
|
367
393
|
// we can't rely on the presence or absence of a damage roll to determine whether a
|
|
368
|
-
// "critical hit" was spurious or not as moves that do 1 or less damage don't
|
|
394
|
+
// "critical hit" was spurious or not as moves that do 1 or less damage don't roll for
|
|
369
395
|
// damage but can still crit (instead, whether or not a roll is deemed to be a no-op is
|
|
370
396
|
// passed to the critical hit helper).
|
|
371
397
|
//
|
|
@@ -381,7 +407,7 @@ pub fn Chance(comptime Rational: type) type {
|
|
|
381
407
|
action.critical_hit = if (self.pending.crit) .true else .false;
|
|
382
408
|
} else assert(!self.pending.glitch);
|
|
383
409
|
|
|
384
|
-
if (self.pending.damage_roll > 0) {
|
|
410
|
+
if (self.pending.damage_roll > 0 and (!self.pending.glitch or self.pending.hit)) {
|
|
385
411
|
try self.probability.update(1, 39);
|
|
386
412
|
action.damage = self.pending.damage_roll;
|
|
387
413
|
}
|
|
@@ -408,14 +434,13 @@ pub fn Chance(comptime Rational: type) type {
|
|
|
408
434
|
|
|
409
435
|
var d = self.durations.get(player);
|
|
410
436
|
|
|
411
|
-
const out = d.sleeps
|
|
412
|
-
d.sleeps
|
|
413
|
-
d.sleeps
|
|
437
|
+
const out = Sleeps.get(d.sleeps, 0);
|
|
438
|
+
d.sleeps = Sleeps.set(d.sleeps, 0, Sleeps.get(d.sleeps, slot - 1));
|
|
439
|
+
d.sleeps = Sleeps.set(d.sleeps, slot - 1, out);
|
|
414
440
|
|
|
415
441
|
d.confusion = 0;
|
|
416
442
|
d.disable = 0;
|
|
417
|
-
d.
|
|
418
|
-
d.thrashing = 0;
|
|
443
|
+
d.attacking = 0;
|
|
419
444
|
d.binding = 0;
|
|
420
445
|
|
|
421
446
|
self.durations.get(player.foe()).binding = 0;
|
|
@@ -544,7 +569,8 @@ pub fn Chance(comptime Rational: type) type {
|
|
|
544
569
|
.None => {
|
|
545
570
|
@field(a, @tagName(field)) = .None;
|
|
546
571
|
if (field == .sleep) {
|
|
547
|
-
self.durations.get(player)
|
|
572
|
+
var d = self.durations.get(player);
|
|
573
|
+
d.sleeps = Sleeps.set(d.sleeps, 0, 0);
|
|
548
574
|
} else {
|
|
549
575
|
@field(self.durations.get(player), @tagName(field)) = 0;
|
|
550
576
|
}
|
|
@@ -558,7 +584,8 @@ pub fn Chance(comptime Rational: type) type {
|
|
|
558
584
|
});
|
|
559
585
|
@field(a, @tagName(field)) = .started;
|
|
560
586
|
if (field == .sleep) {
|
|
561
|
-
self.durations.get(player)
|
|
587
|
+
var d = self.durations.get(player);
|
|
588
|
+
d.sleeps = Sleeps.set(d.sleeps, 0, 1);
|
|
562
589
|
} else {
|
|
563
590
|
@field(self.durations.get(player), @tagName(field)) = 1;
|
|
564
591
|
}
|
|
@@ -575,19 +602,19 @@ pub fn Chance(comptime Rational: type) type {
|
|
|
575
602
|
a.sleep = obs;
|
|
576
603
|
|
|
577
604
|
var d = self.durations.get(player);
|
|
578
|
-
const n = d.sleeps
|
|
605
|
+
const n = Sleeps.get(d.sleeps, 0);
|
|
579
606
|
|
|
580
607
|
if (obs == .None) {
|
|
581
|
-
d.sleeps
|
|
608
|
+
d.sleeps = Sleeps.set(d.sleeps, 0, 0);
|
|
582
609
|
} else if (obs == .ended) {
|
|
583
610
|
assert(n >= 1 and n <= 7);
|
|
584
611
|
if (n != 7) try self.probability.update(1, 8 - @as(u4, n));
|
|
585
|
-
d.sleeps
|
|
612
|
+
d.sleeps = Sleeps.set(d.sleeps, 0, 0);
|
|
586
613
|
} else {
|
|
587
614
|
assert(obs == .continuing);
|
|
588
615
|
assert(n >= 1 and n < 7);
|
|
589
616
|
try self.probability.update(8 - @as(u4, n) - 1, 8 - @as(u4, n));
|
|
590
|
-
d.sleeps
|
|
617
|
+
d.sleeps = Sleeps.set(d.sleeps, 0, n + 1);
|
|
591
618
|
}
|
|
592
619
|
}
|
|
593
620
|
|
|
@@ -635,38 +662,25 @@ pub fn Chance(comptime Rational: type) type {
|
|
|
635
662
|
}
|
|
636
663
|
}
|
|
637
664
|
|
|
638
|
-
pub fn
|
|
639
|
-
return self.attacking(.bide, player, obs);
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
pub fn thrashing(self: *Self, player: Player, obs: Optional(Observation)) Error!void {
|
|
643
|
-
return self.attacking(.thrashing, player, obs);
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
fn attacking(
|
|
647
|
-
self: *Self,
|
|
648
|
-
comptime field: Action.Field,
|
|
649
|
-
player: Player,
|
|
650
|
-
obs: Optional(Observation),
|
|
651
|
-
) Error!void {
|
|
665
|
+
pub fn attacking(self: *Self, player: Player, obs: Optional(Observation)) Error!void {
|
|
652
666
|
if (!enabled) return;
|
|
653
667
|
|
|
654
|
-
const f = @tagName(field);
|
|
655
668
|
var a = self.actions.get(player);
|
|
656
|
-
assert(
|
|
657
|
-
|
|
669
|
+
assert(a.attacking == .None or a.attacking == .started);
|
|
670
|
+
a.attacking = obs;
|
|
658
671
|
|
|
659
672
|
var d = self.durations.get(player);
|
|
660
|
-
const n =
|
|
673
|
+
const n = d.attacking;
|
|
661
674
|
if (obs == .ended) {
|
|
675
|
+
// "3-4 turns" includes the turn for the initial attack *plus* the forced attacks
|
|
662
676
|
assert(n >= 2 and n <= 3);
|
|
663
677
|
if (n != 3) try self.probability.update(1, 4 - @as(u4, n));
|
|
664
|
-
|
|
678
|
+
d.attacking = 0;
|
|
665
679
|
} else {
|
|
666
680
|
assert(obs == .continuing);
|
|
667
681
|
assert(n >= 1 and n < 3);
|
|
668
682
|
if (n > 1) try self.probability.update(4 - @as(u4, n) - 1, 4 - @as(u4, n));
|
|
669
|
-
|
|
683
|
+
d.attacking += 1;
|
|
670
684
|
}
|
|
671
685
|
}
|
|
672
686
|
|
|
@@ -685,6 +699,7 @@ pub fn Chance(comptime Rational: type) type {
|
|
|
685
699
|
const q: u4 = if (n < 3) 8 - ((n - 1) * p) else 2;
|
|
686
700
|
|
|
687
701
|
if (obs == .ended) {
|
|
702
|
+
// "2-5 turns" includes the turn for the initial attack *plus* the forced attacks
|
|
688
703
|
assert(n >= 1 and n <= 4);
|
|
689
704
|
if (n != 4) try self.probability.update(p, q);
|
|
690
705
|
d.binding = 0;
|
|
@@ -710,7 +725,7 @@ pub fn Chance(comptime Rational: type) type {
|
|
|
710
725
|
self.actions.get(player).metronome = move;
|
|
711
726
|
}
|
|
712
727
|
|
|
713
|
-
pub fn
|
|
728
|
+
pub fn pp(self: *Self, player: Player, n: u4) bool {
|
|
714
729
|
if (!enabled) return true;
|
|
715
730
|
|
|
716
731
|
var a = self.actions.get(player);
|
|
@@ -818,16 +833,16 @@ test "Chance.damage" {
|
|
|
818
833
|
|
|
819
834
|
try chance.damage(.P1, 217);
|
|
820
835
|
if (showdown) {
|
|
821
|
-
try expectValue(217, chance.actions.p1.damage);
|
|
836
|
+
try expectValue(@as(u8, 217), chance.actions.p1.damage);
|
|
822
837
|
try expectProbability(&chance.probability, 1, 39);
|
|
823
838
|
} else {
|
|
824
839
|
try expectProbability(&chance.probability, 1, 1);
|
|
825
|
-
try expectValue(0, chance.actions.p1.damage);
|
|
840
|
+
try expectValue(@as(u8, 0), chance.actions.p1.damage);
|
|
826
841
|
|
|
827
842
|
try chance.commit(.P1, .hit);
|
|
828
843
|
|
|
829
844
|
try expectProbability(&chance.probability, 1, 39);
|
|
830
|
-
try expectValue(217, chance.actions.p1.damage);
|
|
845
|
+
try expectValue(@as(u8, 217), chance.actions.p1.damage);
|
|
831
846
|
}
|
|
832
847
|
}
|
|
833
848
|
|
|
@@ -879,13 +894,13 @@ test "Chance.moveSlot" {
|
|
|
879
894
|
|
|
880
895
|
try chance.moveSlot(.P2, 2, &ms, 2);
|
|
881
896
|
try expectProbability(&chance.probability, 1, 2);
|
|
882
|
-
try expectValue(2, chance.actions.p2.move_slot);
|
|
897
|
+
try expectValue(@as(u4, 2), chance.actions.p2.move_slot);
|
|
883
898
|
|
|
884
899
|
chance.reset();
|
|
885
900
|
|
|
886
901
|
try chance.moveSlot(.P1, 1, &ms, 0);
|
|
887
902
|
try expectProbability(&chance.probability, 1, 3);
|
|
888
|
-
try expectValue(1, chance.actions.p1.move_slot);
|
|
903
|
+
try expectValue(@as(u4, 1), chance.actions.p1.move_slot);
|
|
889
904
|
}
|
|
890
905
|
|
|
891
906
|
test "Chance.multiHit" {
|
|
@@ -893,43 +908,43 @@ test "Chance.multiHit" {
|
|
|
893
908
|
|
|
894
909
|
try chance.multiHit(.P1, 3);
|
|
895
910
|
try expectProbability(&chance.probability, 3, 8);
|
|
896
|
-
try expectValue(3, chance.actions.p1.multi_hit);
|
|
911
|
+
try expectValue(@as(u4, 3), chance.actions.p1.multi_hit);
|
|
897
912
|
|
|
898
913
|
chance.reset();
|
|
899
914
|
|
|
900
915
|
try chance.multiHit(.P2, 5);
|
|
901
916
|
try expectProbability(&chance.probability, 1, 8);
|
|
902
|
-
try expectValue(5, chance.actions.p2.multi_hit);
|
|
917
|
+
try expectValue(@as(u4, 5), chance.actions.p2.multi_hit);
|
|
903
918
|
}
|
|
904
919
|
|
|
905
920
|
test "Chance.duration" {
|
|
906
921
|
var chance: Chance(rational.Rational(u64)) = .{ .probability = .{} };
|
|
907
922
|
|
|
908
923
|
chance.duration(.P1, 2);
|
|
909
|
-
try expectValue(2, chance.actions.p1.duration);
|
|
924
|
+
try expectValue(@as(u4, 2), chance.actions.p1.duration);
|
|
910
925
|
|
|
911
926
|
chance.reset();
|
|
912
927
|
|
|
913
928
|
chance.duration(.P2, 4);
|
|
914
|
-
try expectValue(4, chance.actions.p2.duration);
|
|
929
|
+
try expectValue(@as(u4, 4), chance.actions.p2.duration);
|
|
915
930
|
}
|
|
916
931
|
|
|
917
932
|
test "Chance.sleep" {
|
|
918
933
|
var chance: Chance(rational.Rational(u64)) = .{ .probability = .{} };
|
|
919
934
|
|
|
920
935
|
for ([_]u8{ 7, 6, 5, 4, 3, 2, 1 }, 1..8) |d, i| {
|
|
921
|
-
chance.durations.p1.sleeps
|
|
936
|
+
chance.durations.p1.sleeps = Sleeps.set(chance.durations.p1.sleeps, 0, @intCast(i));
|
|
922
937
|
try chance.sleep(.P1, .ended);
|
|
923
938
|
try expectProbability(&chance.probability, 1, d);
|
|
924
|
-
try expectValue(0, chance.durations.p1.sleeps
|
|
939
|
+
try expectValue(@as(u3, 0), Sleeps.get(chance.durations.p1.sleeps, 0));
|
|
925
940
|
|
|
926
941
|
chance.reset();
|
|
927
942
|
|
|
928
943
|
if (i < 7) {
|
|
929
|
-
chance.durations.p1.sleeps
|
|
944
|
+
chance.durations.p1.sleeps = Sleeps.set(chance.durations.p1.sleeps, 0, @intCast(i));
|
|
930
945
|
try chance.sleep(.P1, .continuing);
|
|
931
946
|
try expectProbability(&chance.probability, d - 1, d);
|
|
932
|
-
try expectValue(@as(u3, @intCast(i)) + 1, chance.durations.p1.sleeps
|
|
947
|
+
try expectValue(@as(u3, @intCast(i)) + 1, Sleeps.get(chance.durations.p1.sleeps, 0));
|
|
933
948
|
|
|
934
949
|
chance.reset();
|
|
935
950
|
}
|
|
@@ -944,7 +959,7 @@ test "Chance.confusion" {
|
|
|
944
959
|
chance.durations.p2.confusion = @intCast(i);
|
|
945
960
|
try chance.confusion(.P2, .ended);
|
|
946
961
|
try expectProbability(&chance.probability, 1, d);
|
|
947
|
-
try expectValue(0, chance.durations.p2.confusion);
|
|
962
|
+
try expectValue(@as(u3, 0), chance.durations.p2.confusion);
|
|
948
963
|
|
|
949
964
|
chance.reset();
|
|
950
965
|
}
|
|
@@ -967,7 +982,7 @@ test "Chance.disable" {
|
|
|
967
982
|
chance.durations.p1.disable = @intCast(i);
|
|
968
983
|
try chance.disable(.P1, .ended);
|
|
969
984
|
try expectProbability(&chance.probability, 1, d);
|
|
970
|
-
try expectValue(0, chance.durations.p1.disable);
|
|
985
|
+
try expectValue(@as(u4, 0), chance.durations.p1.disable);
|
|
971
986
|
|
|
972
987
|
chance.reset();
|
|
973
988
|
|
|
@@ -985,25 +1000,23 @@ test "Chance.disable" {
|
|
|
985
1000
|
test "Chance.attacking" {
|
|
986
1001
|
var chance: Chance(rational.Rational(u64)) = .{ .probability = .{} };
|
|
987
1002
|
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
try expectValue(0, @field(chance.durations.p2, @tagName(f)));
|
|
1003
|
+
for ([_]u8{ 1, 2, 1 }, 1..4) |d, i| {
|
|
1004
|
+
if (i > 1) {
|
|
1005
|
+
chance.durations.p2.attacking = @intCast(i);
|
|
1006
|
+
try chance.attacking(.P2, .ended);
|
|
1007
|
+
try expectProbability(&chance.probability, 1, d);
|
|
1008
|
+
try expectValue(@as(u3, 0), chance.durations.p2.attacking);
|
|
995
1009
|
|
|
996
|
-
|
|
997
|
-
|
|
1010
|
+
chance.reset();
|
|
1011
|
+
}
|
|
998
1012
|
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1013
|
+
if (i < 3) {
|
|
1014
|
+
chance.durations.p2.attacking = @intCast(i);
|
|
1015
|
+
try chance.attacking(.P2, .continuing);
|
|
1016
|
+
try expectProbability(&chance.probability, if (d > 1) d - 1 else d, d);
|
|
1017
|
+
try expectValue(@as(u3, @intCast(i)) + 1, chance.durations.p2.attacking);
|
|
1004
1018
|
|
|
1005
|
-
|
|
1006
|
-
}
|
|
1019
|
+
chance.reset();
|
|
1007
1020
|
}
|
|
1008
1021
|
}
|
|
1009
1022
|
}
|
|
@@ -1018,7 +1031,7 @@ test "Chance.binding" {
|
|
|
1018
1031
|
chance.durations.p1.binding = @intCast(i);
|
|
1019
1032
|
try chance.binding(.P1, .ended);
|
|
1020
1033
|
try expectProbability(&chance.probability, p, q);
|
|
1021
|
-
try expectValue(0, chance.durations.p1.binding);
|
|
1034
|
+
try expectValue(@as(u3, 0), chance.durations.p1.binding);
|
|
1022
1035
|
|
|
1023
1036
|
chance.reset();
|
|
1024
1037
|
|
|
@@ -1038,7 +1051,7 @@ test "Chance.psywave" {
|
|
|
1038
1051
|
|
|
1039
1052
|
try chance.psywave(.P2, 100, 150);
|
|
1040
1053
|
try expectProbability(&chance.probability, 1, 150);
|
|
1041
|
-
try expectValue(101, chance.actions.p2.psywave);
|
|
1054
|
+
try expectValue(@as(u8, 101), chance.actions.p2.psywave);
|
|
1042
1055
|
}
|
|
1043
1056
|
|
|
1044
1057
|
test "Chance.metronome" {
|
|
@@ -1149,11 +1162,7 @@ const Null = struct {
|
|
|
1149
1162
|
_ = .{ self, player, obs };
|
|
1150
1163
|
}
|
|
1151
1164
|
|
|
1152
|
-
pub fn
|
|
1153
|
-
_ = .{ self, player, obs };
|
|
1154
|
-
}
|
|
1155
|
-
|
|
1156
|
-
pub fn thrashing(self: Null, player: Player, obs: Optional(Observation)) Error!void {
|
|
1165
|
+
pub fn attacking(self: Null, player: Player, obs: Optional(Observation)) Error!void {
|
|
1157
1166
|
_ = .{ self, player, obs };
|
|
1158
1167
|
}
|
|
1159
1168
|
|
|
@@ -1169,7 +1178,7 @@ const Null = struct {
|
|
|
1169
1178
|
_ = .{ self, player, move };
|
|
1170
1179
|
}
|
|
1171
1180
|
|
|
1172
|
-
pub fn
|
|
1181
|
+
pub fn pp(self: Null, player: Player, n: u4) bool {
|
|
1173
1182
|
_ = .{ self, player, n };
|
|
1174
1183
|
return true;
|
|
1175
1184
|
}
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
//! Code generated by `tools/generate` - manual edits will be overwritten.
|
|
2
2
|
|
|
3
|
-
const std = @import("std");
|
|
4
|
-
|
|
5
|
-
const rng = @import("../../common/rng.zig");
|
|
6
3
|
const gen1 = @import("../../gen1/data.zig");
|
|
4
|
+
const rng = @import("../../common/rng.zig");
|
|
5
|
+
const std = @import("std");
|
|
7
6
|
|
|
8
7
|
const assert = std.debug.assert;
|
|
9
|
-
|
|
10
8
|
const percent = rng.Gen12.percent;
|
|
11
9
|
const Type = gen1.Type;
|
|
12
10
|
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
//! Code generated by `tools/generate` - manual edits will be overwritten.
|
|
2
2
|
|
|
3
|
-
const std = @import("std");
|
|
4
|
-
|
|
5
3
|
const gen1 = @import("../../gen1/data.zig");
|
|
4
|
+
const std = @import("std");
|
|
6
5
|
|
|
7
6
|
const assert = std.debug.assert;
|
|
8
|
-
|
|
9
7
|
const Stats = gen1.Stats;
|
|
10
8
|
const Types = gen1.Types;
|
|
11
9
|
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
//! Code generated by `tools/generate` - manual edits will be overwritten.
|
|
2
2
|
|
|
3
|
-
const std = @import("std");
|
|
4
|
-
|
|
5
3
|
const gen1 = @import("../../gen1/data.zig");
|
|
4
|
+
const std = @import("std");
|
|
6
5
|
|
|
7
6
|
const assert = std.debug.assert;
|
|
8
7
|
const Effectiveness = gen1.Effectiveness;
|