@pkmn/engine 0.1.0-dev.89cc1c98 → 0.1.0-dev.8b192003
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/LICENSE +1 -3
- package/README.md +44 -19
- package/build/pkg/addon.js +6 -7
- package/build/pkg/addon.js.map +1 -1
- package/build/pkg/data.d.ts +4 -4
- package/build/pkg/data.js.map +1 -1
- package/build/pkg/gen1.js.map +1 -1
- package/build/pkg/index.d.ts +2 -1
- package/build/pkg/index.js.map +1 -1
- package/build/pkg/protocol.js +5 -5
- package/build/pkg/protocol.js.map +1 -1
- package/build/test/display.js +2 -2
- package/build/test/display.js.map +1 -1
- package/build/tools/debug.js +5 -4
- package/build/tools/debug.js.map +1 -1
- package/build.zig +100 -102
- package/package.json +31 -23
- package/src/bin/install-pkmn-engine +26 -18
- package/src/lib/common/data.zig +4 -4
- package/src/lib/common/debug.zig +2 -2
- package/src/lib/common/optional.zig +1 -1
- package/src/lib/common/options.zig +2 -0
- package/src/lib/common/protocol.zig +393 -396
- package/src/lib/common/rational.zig +109 -15
- package/src/lib/common/rng.zig +20 -11
- package/src/lib/gen1/calc.zig +478 -92
- package/src/lib/gen1/chance.zig +195 -428
- package/src/lib/gen1/data/species.zig +1 -1
- package/src/lib/gen1/data.zig +21 -21
- package/src/lib/gen1/helpers.zig +88 -534
- package/src/lib/gen1/mechanics.zig +377 -360
- package/src/lib/gen2/chance.zig +25 -457
- package/src/lib/gen2/data.zig +13 -11
- package/src/lib/gen2/generated.zig +27 -78
- package/src/lib/gen2/helpers.zig +37 -7
- package/src/lib/gen2/mechanics.zig +1022 -456
- package/src/lib/{binding/node.zig → node.zig} +9 -12
- package/src/lib/pkmn.zig +27 -12
- package/src/lib/{binding/wasm.zig → wasm.zig} +2 -1
- package/src/test/display/pkmn.html.tmpl +5 -5
- package/src/lib/gen1/README.md +0 -894
- package/src/lib/gen2/README.md +0 -330
package/src/lib/gen2/chance.zig
CHANGED
|
@@ -14,7 +14,7 @@ const util = @import("../common/util.zig");
|
|
|
14
14
|
const Player = @import("../common/data.zig").Player;
|
|
15
15
|
const Optional = @import("../common/optional.zig").Optional;
|
|
16
16
|
|
|
17
|
-
const data = @import("
|
|
17
|
+
const data = @import("data.zig");
|
|
18
18
|
|
|
19
19
|
const enabled = options.chance;
|
|
20
20
|
const showdown = options.showdown;
|
|
@@ -42,12 +42,6 @@ pub const Actions = extern struct {
|
|
|
42
42
|
return if (player == .P1) &self.p1 else &self.p2;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
/// Perform a reset by clearing fields which should not persist across updates.
|
|
46
|
-
pub fn reset(self: *Actions) void {
|
|
47
|
-
self.p1.reset();
|
|
48
|
-
self.p2.reset();
|
|
49
|
-
}
|
|
50
|
-
|
|
51
45
|
/// Returns true if `a` is equal to `b`.
|
|
52
46
|
pub fn eql(a: Actions, b: Actions) bool {
|
|
53
47
|
return @as(u128, @bitCast(a.p1)) == @as(u128, @bitCast(b.p1)) and
|
|
@@ -64,15 +58,6 @@ pub const Actions = extern struct {
|
|
|
64
58
|
const b_val = @field(@field(b, player.name), field.name);
|
|
65
59
|
|
|
66
60
|
switch (@typeInfo(@TypeOf(a_val))) {
|
|
67
|
-
.Struct => inline for (@typeInfo(@TypeOf(a_val)).Struct.fields) |f| {
|
|
68
|
-
const a_val_f = @field(a_val, f.name);
|
|
69
|
-
const b_val_f = @field(b_val, f.name);
|
|
70
|
-
switch (@typeInfo(@TypeOf(a_val_f))) {
|
|
71
|
-
.Int => if ((a_val_f > 0) != (b_val_f > 0)) return false,
|
|
72
|
-
.Bool => if (a_val_f != b_val_f) return false,
|
|
73
|
-
else => unreachable,
|
|
74
|
-
}
|
|
75
|
-
},
|
|
76
61
|
.Enum => if ((@intFromEnum(a_val) > 0) != (@intFromEnum(b_val) > 0))
|
|
77
62
|
return false,
|
|
78
63
|
.Int => if ((a_val > 0) != (b_val > 0)) return false,
|
|
@@ -97,16 +82,11 @@ pub const Actions = extern struct {
|
|
|
97
82
|
}
|
|
98
83
|
};
|
|
99
84
|
|
|
85
|
+
// TODO: ziglang/zig#19730
|
|
100
86
|
test Actions {
|
|
101
87
|
const a: Actions = .{ .p1 = .{ .hit = .true, .critical_hit = .false, .damage = 245 } };
|
|
102
88
|
const b: Actions = .{ .p1 = .{ .hit = .false, .critical_hit = .true, .damage = 246 } };
|
|
103
89
|
const c: Actions = .{ .p1 = .{ .hit = .true } };
|
|
104
|
-
const d: Actions = .{ .p2 = .{ .hit = .true, .durations = .{ .sleep = 2 } } };
|
|
105
|
-
const e: Actions = .{ .p2 = .{ .hit = .false, .durations = .{ .sleep = 4 } } };
|
|
106
|
-
const f: Actions = .{ .p1 = .{ .hit = .false, .durations = .{ .sleep = 4 } } };
|
|
107
|
-
const g: Actions = .{ .p1 = .{ .hit = .false, .durations = .{ .confusion = 1 } } };
|
|
108
|
-
const h: Actions =
|
|
109
|
-
.{ .p1 = .{ .hit = .false, .durations = .{ .confusion = 1, .thrash = true } } };
|
|
110
90
|
|
|
111
91
|
try expect(a.eql(a));
|
|
112
92
|
try expect(!a.eql(b));
|
|
@@ -119,10 +99,6 @@ test Actions {
|
|
|
119
99
|
try expect(b.matches(a));
|
|
120
100
|
try expect(!a.matches(c));
|
|
121
101
|
try expect(!c.matches(a));
|
|
122
|
-
try expect(d.matches(e));
|
|
123
|
-
try expect(!d.matches(f));
|
|
124
|
-
try expect(!g.matches(h));
|
|
125
|
-
try expect(h.matches(h));
|
|
126
102
|
}
|
|
127
103
|
|
|
128
104
|
/// Information about the RNG that was observed during a Generation II battle `update` for a
|
|
@@ -188,20 +164,10 @@ pub const Action = packed struct(u128) {
|
|
|
188
164
|
/// If not None, the Move to return for Rolls.metronome.
|
|
189
165
|
metronome: Move = .None,
|
|
190
166
|
|
|
191
|
-
_:
|
|
192
|
-
|
|
193
|
-
/// Observed values of various durations. Does not influence future RNG calls. TODO
|
|
194
|
-
durations: Duration = .{},
|
|
195
|
-
|
|
196
|
-
pub const DURATIONS: u128 = 0xFFFFFFFF00000000_0000000000000000;
|
|
167
|
+
_: u48 = 0, // TODO
|
|
197
168
|
|
|
198
169
|
pub const Field = std.meta.FieldEnum(Action);
|
|
199
170
|
|
|
200
|
-
/// Perform a reset by clearing fields which should not persist across updates.
|
|
201
|
-
pub fn reset(self: *Action) void {
|
|
202
|
-
self.* = @bitCast(@as(u128, @bitCast(self.*)) & DURATIONS);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
171
|
pub fn format(a: Action, comptime f: []const u8, o: std.fmt.FormatOptions, w: anytype) !void {
|
|
206
172
|
_ = .{ f, o };
|
|
207
173
|
try fmt(a, w, false);
|
|
@@ -213,18 +179,6 @@ pub const Action = packed struct(u128) {
|
|
|
213
179
|
inline for (@typeInfo(Action).Struct.fields) |field| {
|
|
214
180
|
const val = @field(self, field.name);
|
|
215
181
|
switch (@typeInfo(@TypeOf(val))) {
|
|
216
|
-
.Struct => inline for (@typeInfo(@TypeOf(val)).Struct.fields) |f| {
|
|
217
|
-
const v = @field(val, f.name);
|
|
218
|
-
if (v != 0) {
|
|
219
|
-
if (printed) try writer.writeAll(", ");
|
|
220
|
-
if (shape) {
|
|
221
|
-
try writer.print("{s}:?", .{f.name});
|
|
222
|
-
} else {
|
|
223
|
-
try writer.print("{s}:{d}", .{ f.name, v });
|
|
224
|
-
}
|
|
225
|
-
printed = true;
|
|
226
|
-
}
|
|
227
|
-
},
|
|
228
182
|
.Enum => if (val != .None) {
|
|
229
183
|
if (printed) try writer.writeAll(", ");
|
|
230
184
|
if (shape) {
|
|
@@ -255,36 +209,6 @@ pub const Action = packed struct(u128) {
|
|
|
255
209
|
}
|
|
256
210
|
};
|
|
257
211
|
|
|
258
|
-
test Action {
|
|
259
|
-
var a: Action = .{ .hit = .true, .durations = .{ .sleep = 3 }, .damage = 225 };
|
|
260
|
-
a.reset();
|
|
261
|
-
|
|
262
|
-
try expectEqual(Action{ .hit = .None, .durations = .{ .sleep = 3 }, .damage = 0 }, a);
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/// Observed values for various durations that need to be tracked in order to properly
|
|
266
|
-
/// deduplicate transitions with a primary key. TODO
|
|
267
|
-
pub const Duration = packed struct(u32) {
|
|
268
|
-
/// The number of turns a Pokémon has been observed to be sleeping.
|
|
269
|
-
sleep: u3 = 0,
|
|
270
|
-
/// The number of turns a Pokémon has been observed to be confused.
|
|
271
|
-
confusion: u3 = 0,
|
|
272
|
-
/// TODO
|
|
273
|
-
thrash: bool = false,
|
|
274
|
-
/// The number of turns a Pokémon has been observed to be disabled.
|
|
275
|
-
disable: u4 = 0,
|
|
276
|
-
/// The number of turns a Pokémon has been observed to be attacking.
|
|
277
|
-
attacking: u3 = 0,
|
|
278
|
-
/// The number of turns a Pokémon has been observed to be binding their opponent.
|
|
279
|
-
binding: u3 = 0,
|
|
280
|
-
/// The number of turns a Pokémon has been observed to be encored.
|
|
281
|
-
encore: u3 = 0,
|
|
282
|
-
|
|
283
|
-
_: u12 = 0,
|
|
284
|
-
|
|
285
|
-
pub const Field = std.meta.FieldEnum(Duration);
|
|
286
|
-
};
|
|
287
|
-
|
|
288
212
|
/// Tracks chance actions and their associated probability during a Generation II battle update when
|
|
289
213
|
/// `options.chance` is enabled.
|
|
290
214
|
pub fn Chance(comptime Rational: type) type {
|
|
@@ -297,37 +221,15 @@ pub fn Chance(comptime Rational: type) type {
|
|
|
297
221
|
/// RNG events were observed during a battle `update`.
|
|
298
222
|
actions: Actions = .{},
|
|
299
223
|
|
|
300
|
-
// Tracks the observed sleep durations for the Pokémon in both player's parties. Unlike
|
|
301
|
-
// other durations which are all tied to volatiles, sleep's counter persists through
|
|
302
|
-
// switching and so we must store it here. The indices of these arrays correspond to the
|
|
303
|
-
// `order` field of a Side. This information could be stored in actions but size is a
|
|
304
|
-
// concern so this is tracked separately as actions only purports to track RNG events
|
|
305
|
-
// observed during a single `update` (not across updates).
|
|
306
|
-
sleeps: [2][6]u3 = .{ .{0} ** 6, .{0} ** 6 },
|
|
307
|
-
|
|
308
224
|
/// Possible error returned by operations tracking chance probability.
|
|
309
225
|
pub const Error = Rational.Error;
|
|
310
226
|
|
|
311
227
|
/// Convenience helper to clear fields which typically should be cleared between updates.
|
|
312
228
|
pub fn reset(self: *Self) void {
|
|
313
|
-
self.probability.reset();
|
|
314
|
-
self.actions.reset();
|
|
315
|
-
// TODO: self.pending = .{};
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
pub fn switched(self: *Self, player: Player, in: u8, out: u8) void {
|
|
319
229
|
if (!enabled) return;
|
|
320
230
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
var action = self.actions.get(player);
|
|
325
|
-
|
|
326
|
-
const slp = action.durations.sleep;
|
|
327
|
-
action.durations = .{};
|
|
328
|
-
|
|
329
|
-
self.sleeps[@intFromEnum(player)][out - 1] = slp;
|
|
330
|
-
action.durations.sleep = @intCast(self.sleeps[@intFromEnum(player)][in - 1]);
|
|
231
|
+
self.probability.reset();
|
|
232
|
+
self.actions = .{};
|
|
331
233
|
}
|
|
332
234
|
|
|
333
235
|
pub fn speedTie(self: *Self, p1: bool) Error!void {
|
|
@@ -517,123 +419,11 @@ pub fn Chance(comptime Rational: type) type {
|
|
|
517
419
|
self.actions.get(player).multi_hit = n;
|
|
518
420
|
}
|
|
519
421
|
|
|
520
|
-
pub fn duration(
|
|
521
|
-
self: *Self,
|
|
522
|
-
comptime field: Duration.Field,
|
|
523
|
-
player: Player,
|
|
524
|
-
target: Player,
|
|
525
|
-
turns: u4,
|
|
526
|
-
) void {
|
|
422
|
+
pub fn duration(self: *Self, player: Player, turns: u4) void {
|
|
527
423
|
if (!enabled) return;
|
|
528
424
|
|
|
529
|
-
var durations = &self.actions.get(target).durations;
|
|
530
|
-
assert(@field(durations, @tagName(field)) == 0 or
|
|
531
|
-
(field == .confusion and player == target));
|
|
532
|
-
@field(durations, @tagName(field)) = 1;
|
|
533
|
-
if (field == .confusion) durations.thrash = player == target;
|
|
534
425
|
self.actions.get(player).duration = if (options.key) 1 else turns;
|
|
535
426
|
}
|
|
536
|
-
|
|
537
|
-
pub fn sleep(self: *Self, player: Player, turns: u4) Error!void {
|
|
538
|
-
if (!enabled) return;
|
|
539
|
-
|
|
540
|
-
var durations = &self.actions.get(player).durations;
|
|
541
|
-
const n = durations.sleep;
|
|
542
|
-
if (turns == 0) {
|
|
543
|
-
assert(n >= 1 and n <= 6);
|
|
544
|
-
if (n != 6) try self.probability.update(1, 7 - @as(u4, n));
|
|
545
|
-
durations.sleep = 0;
|
|
546
|
-
} else {
|
|
547
|
-
assert(n >= 1 and n < 6);
|
|
548
|
-
try self.probability.update(7 - @as(u4, n) - 1, 7 - @as(u4, n));
|
|
549
|
-
durations.sleep += 1;
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
pub fn confusion(self: *Self, player: Player, turns: u4) Error!void {
|
|
554
|
-
if (!enabled) return;
|
|
555
|
-
|
|
556
|
-
var durations = &self.actions.get(player).durations;
|
|
557
|
-
const n = durations.confusion;
|
|
558
|
-
const hi: u8 = if (durations.thrash) 3 else 5;
|
|
559
|
-
const p = hi + 1;
|
|
560
|
-
if (turns == 0) {
|
|
561
|
-
assert(n >= 2 and n <= hi);
|
|
562
|
-
if (n != hi) try self.probability.update(1, p - @as(u4, n));
|
|
563
|
-
durations.confusion = 0;
|
|
564
|
-
} else {
|
|
565
|
-
assert(n >= 1 and n < hi);
|
|
566
|
-
if (n > 1) try self.probability.update(p - @as(u4, n) - 1, p - @as(u4, n));
|
|
567
|
-
durations.confusion += 1;
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
pub fn disable(self: *Self, player: Player, turns: u4) Error!void {
|
|
572
|
-
if (!enabled) return;
|
|
573
|
-
|
|
574
|
-
var durations = &self.actions.get(player).durations;
|
|
575
|
-
const n = durations.disable;
|
|
576
|
-
const hi = if (showdown) 5 else 8;
|
|
577
|
-
const p = hi + 1;
|
|
578
|
-
if (turns == 0) {
|
|
579
|
-
assert(n >= 2 and n <= hi);
|
|
580
|
-
if (n != hi) try self.probability.update(1, p - n);
|
|
581
|
-
durations.disable = 0;
|
|
582
|
-
} else {
|
|
583
|
-
assert(n >= 1 and n < hi);
|
|
584
|
-
if (n > 1) try self.probability.update(p - n - 1, p - n);
|
|
585
|
-
durations.disable += 1;
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
pub fn attacking(self: *Self, player: Player, turns: u4) Error!void {
|
|
590
|
-
if (!enabled) return;
|
|
591
|
-
|
|
592
|
-
var durations = &self.actions.get(player).durations;
|
|
593
|
-
const n = durations.attacking;
|
|
594
|
-
if (turns == 0) {
|
|
595
|
-
assert(n >= 2 and n <= 3);
|
|
596
|
-
if (n != 3) try self.probability.update(1, 4 - @as(u4, n));
|
|
597
|
-
durations.attacking = 0;
|
|
598
|
-
} else {
|
|
599
|
-
assert(n >= 1 and n < 3);
|
|
600
|
-
if (n > 1) try self.probability.update(4 - @as(u4, n) - 1, 4 - @as(u4, n));
|
|
601
|
-
durations.attacking += 1;
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
pub fn binding(self: *Self, player: Player, turns: u4) Error!void {
|
|
606
|
-
if (!enabled) return;
|
|
607
|
-
|
|
608
|
-
var durations = &self.actions.get(player).durations;
|
|
609
|
-
const n = durations.binding;
|
|
610
|
-
if (turns == 0) {
|
|
611
|
-
assert(n >= 2 and n <= 5);
|
|
612
|
-
if (n != 5) try self.probability.update(1, 6 - @as(u4, n));
|
|
613
|
-
durations.binding = 0;
|
|
614
|
-
} else {
|
|
615
|
-
assert(n >= 1 and n < 5);
|
|
616
|
-
if (n > 1) try self.probability.update(6 - @as(u4, n) - 1, 6 - @as(u4, n));
|
|
617
|
-
durations.binding += 1;
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
// TODO: consider sharing implementation with binding
|
|
622
|
-
pub fn encore(self: *Self, player: Player, turns: u4) Error!void {
|
|
623
|
-
if (!enabled) return;
|
|
624
|
-
|
|
625
|
-
var durations = &self.actions.get(player).durations;
|
|
626
|
-
const n = durations.encore;
|
|
627
|
-
if (turns == 0) {
|
|
628
|
-
assert(n >= 2 and n <= 5);
|
|
629
|
-
if (n != 5) try self.probability.update(1, 6 - @as(u4, n));
|
|
630
|
-
durations.encore = 0;
|
|
631
|
-
} else {
|
|
632
|
-
assert(n >= 1 and n < 5);
|
|
633
|
-
if (n > 1) try self.probability.update(6 - @as(u4, n) - 1, 6 - @as(u4, n));
|
|
634
|
-
durations.encore += 1;
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
427
|
};
|
|
638
428
|
}
|
|
639
429
|
|
|
@@ -699,7 +489,7 @@ test "Chance.damage" {
|
|
|
699
489
|
var chance: Chance(rational.Rational(u64)) = .{ .probability = .{} };
|
|
700
490
|
|
|
701
491
|
try chance.damage(.P1, 217);
|
|
702
|
-
try expectValue(
|
|
492
|
+
try expectValue(217, chance.actions.p1.damage);
|
|
703
493
|
try expectProbability(&chance.probability, 1, 39);
|
|
704
494
|
}
|
|
705
495
|
|
|
@@ -824,7 +614,7 @@ test "Chance.present" {
|
|
|
824
614
|
} else {
|
|
825
615
|
try expectProbability(&chance.probability, 25, 256);
|
|
826
616
|
}
|
|
827
|
-
try expectValue(
|
|
617
|
+
try expectValue(4, chance.actions.p2.present);
|
|
828
618
|
|
|
829
619
|
chance.reset();
|
|
830
620
|
|
|
@@ -834,7 +624,7 @@ test "Chance.present" {
|
|
|
834
624
|
} else {
|
|
835
625
|
try expectProbability(&chance.probability, 51, 256);
|
|
836
626
|
}
|
|
837
|
-
try expectValue(
|
|
627
|
+
try expectValue(1, chance.actions.p1.present);
|
|
838
628
|
}
|
|
839
629
|
|
|
840
630
|
test "Chance.magnitude" {
|
|
@@ -846,7 +636,7 @@ test "Chance.magnitude" {
|
|
|
846
636
|
} else {
|
|
847
637
|
try expectProbability(&chance.probability, 13, 256);
|
|
848
638
|
}
|
|
849
|
-
try expectValue(
|
|
639
|
+
try expectValue(7, chance.actions.p2.magnitude);
|
|
850
640
|
|
|
851
641
|
chance.reset();
|
|
852
642
|
|
|
@@ -856,7 +646,7 @@ test "Chance.magnitude" {
|
|
|
856
646
|
} else {
|
|
857
647
|
try expectProbability(&chance.probability, 51, 256);
|
|
858
648
|
}
|
|
859
|
-
try expectValue(
|
|
649
|
+
try expectValue(5, chance.actions.p1.magnitude);
|
|
860
650
|
}
|
|
861
651
|
|
|
862
652
|
test "Chance.tripleKick" {
|
|
@@ -864,7 +654,7 @@ test "Chance.tripleKick" {
|
|
|
864
654
|
|
|
865
655
|
try chance.tripleKick(.P1, 2);
|
|
866
656
|
try expectProbability(&chance.probability, 1, 3);
|
|
867
|
-
try expectValue(
|
|
657
|
+
try expectValue(2, chance.actions.p1.triple_kick);
|
|
868
658
|
}
|
|
869
659
|
|
|
870
660
|
test "Chance.spite" {
|
|
@@ -872,7 +662,7 @@ test "Chance.spite" {
|
|
|
872
662
|
|
|
873
663
|
try chance.spite(.P1, 3);
|
|
874
664
|
try expectProbability(&chance.probability, 1, 4);
|
|
875
|
-
try expectValue(
|
|
665
|
+
try expectValue(3, chance.actions.p1.spite);
|
|
876
666
|
}
|
|
877
667
|
|
|
878
668
|
test "Chance.conversion2" {
|
|
@@ -899,7 +689,7 @@ test "Chance.psywave" {
|
|
|
899
689
|
|
|
900
690
|
try chance.psywave(.P2, 100, 150);
|
|
901
691
|
try expectProbability(&chance.probability, 1, 150);
|
|
902
|
-
try expectValue(
|
|
692
|
+
try expectValue(100, chance.actions.p2.psywave);
|
|
903
693
|
}
|
|
904
694
|
|
|
905
695
|
test "Chance.metronome" {
|
|
@@ -915,19 +705,19 @@ test "Chance.moveSlot" {
|
|
|
915
705
|
|
|
916
706
|
try chance.moveSlot(.P2, 2, 2);
|
|
917
707
|
try expectProbability(&chance.probability, 1, 2);
|
|
918
|
-
try expectValue(
|
|
708
|
+
try expectValue(2, chance.actions.p2.move_slot);
|
|
919
709
|
|
|
920
710
|
chance.reset();
|
|
921
711
|
|
|
922
712
|
try chance.moveSlot(.P1, 1, 3);
|
|
923
713
|
try expectProbability(&chance.probability, 1, 3);
|
|
924
|
-
try expectValue(
|
|
714
|
+
try expectValue(1, chance.actions.p1.move_slot);
|
|
925
715
|
|
|
926
716
|
chance.reset();
|
|
927
717
|
|
|
928
718
|
try chance.moveSlot(.P1, 4, 1);
|
|
929
719
|
try expectProbability(&chance.probability, 1, 1);
|
|
930
|
-
try expectValue(
|
|
720
|
+
try expectValue(4, chance.actions.p1.move_slot);
|
|
931
721
|
}
|
|
932
722
|
|
|
933
723
|
test "Chance.forceSwitch" {
|
|
@@ -935,19 +725,19 @@ test "Chance.forceSwitch" {
|
|
|
935
725
|
|
|
936
726
|
try chance.forceSwitch(.P2, 2, 2);
|
|
937
727
|
try expectProbability(&chance.probability, 1, 2);
|
|
938
|
-
try expectValue(
|
|
728
|
+
try expectValue(2, chance.actions.p2.force_switch);
|
|
939
729
|
|
|
940
730
|
chance.reset();
|
|
941
731
|
|
|
942
732
|
try chance.forceSwitch(.P1, 1, 3);
|
|
943
733
|
try expectProbability(&chance.probability, 1, 3);
|
|
944
|
-
try expectValue(
|
|
734
|
+
try expectValue(1, chance.actions.p1.force_switch);
|
|
945
735
|
|
|
946
736
|
chance.reset();
|
|
947
737
|
|
|
948
738
|
try chance.forceSwitch(.P1, 4, 1);
|
|
949
739
|
try expectProbability(&chance.probability, 1, 1);
|
|
950
|
-
try expectValue(
|
|
740
|
+
try expectValue(4, chance.actions.p1.force_switch);
|
|
951
741
|
}
|
|
952
742
|
|
|
953
743
|
test "Chance.multiHit" {
|
|
@@ -955,212 +745,20 @@ test "Chance.multiHit" {
|
|
|
955
745
|
|
|
956
746
|
try chance.multiHit(.P1, 3);
|
|
957
747
|
try expectProbability(&chance.probability, 3, 8);
|
|
958
|
-
try expectValue(
|
|
748
|
+
try expectValue(3, chance.actions.p1.multi_hit);
|
|
959
749
|
|
|
960
750
|
chance.reset();
|
|
961
751
|
|
|
962
752
|
try chance.multiHit(.P2, 5);
|
|
963
753
|
try expectProbability(&chance.probability, 1, 8);
|
|
964
|
-
try expectValue(
|
|
754
|
+
try expectValue(5, chance.actions.p2.multi_hit);
|
|
965
755
|
}
|
|
966
756
|
|
|
967
757
|
test "Chance.duration" {
|
|
968
758
|
var chance: Chance(rational.Rational(u64)) = .{ .probability = .{} };
|
|
969
759
|
|
|
970
|
-
chance.duration(.
|
|
971
|
-
try expectValue(
|
|
972
|
-
try expectValue(@as(u3, 1), chance.actions.p2.durations.sleep);
|
|
973
|
-
}
|
|
974
|
-
|
|
975
|
-
test "Chance.sleep" {
|
|
976
|
-
var chance: Chance(rational.Rational(u64)) = .{ .probability = .{} };
|
|
977
|
-
|
|
978
|
-
for ([_]u8{ 6, 5, 4, 3, 2, 1 }, 1..7) |d, i| {
|
|
979
|
-
chance.actions.p1.durations.sleep = @intCast(i);
|
|
980
|
-
try chance.sleep(.P1, 0);
|
|
981
|
-
try expectProbability(&chance.probability, 1, d);
|
|
982
|
-
try expectValue(@as(u3, 0), chance.actions.p1.durations.sleep);
|
|
983
|
-
|
|
984
|
-
chance.reset();
|
|
985
|
-
|
|
986
|
-
if (i < 6) {
|
|
987
|
-
chance.actions.p1.durations.sleep = @intCast(i);
|
|
988
|
-
try chance.sleep(.P1, 1);
|
|
989
|
-
try expectProbability(&chance.probability, d - 1, d);
|
|
990
|
-
try expectValue(@as(u3, @intCast(i)) + 1, chance.actions.p1.durations.sleep);
|
|
991
|
-
|
|
992
|
-
chance.reset();
|
|
993
|
-
}
|
|
994
|
-
}
|
|
995
|
-
}
|
|
996
|
-
|
|
997
|
-
test "Chance.confusion" {
|
|
998
|
-
var chance: Chance(rational.Rational(u64)) = .{ .probability = .{} };
|
|
999
|
-
|
|
1000
|
-
chance.actions.p2.durations.thrash = false;
|
|
1001
|
-
for ([_]u8{ 1, 4, 3, 2, 1 }, 1..6) |d, i| {
|
|
1002
|
-
if (i > 1) {
|
|
1003
|
-
chance.actions.p2.durations.confusion = @intCast(i);
|
|
1004
|
-
try chance.confusion(.P2, 0);
|
|
1005
|
-
try expectProbability(&chance.probability, 1, d);
|
|
1006
|
-
try expectValue(@as(u3, 0), chance.actions.p2.durations.confusion);
|
|
1007
|
-
try expectValue(false, chance.actions.p2.durations.thrash);
|
|
1008
|
-
|
|
1009
|
-
chance.reset();
|
|
1010
|
-
}
|
|
1011
|
-
|
|
1012
|
-
if (i < 5) {
|
|
1013
|
-
chance.actions.p2.durations.confusion = @intCast(i);
|
|
1014
|
-
try chance.confusion(.P2, 1);
|
|
1015
|
-
try expectProbability(&chance.probability, if (d > 1) d - 1 else d, d);
|
|
1016
|
-
try expectValue(@as(u3, @intCast(i)) + 1, chance.actions.p2.durations.confusion);
|
|
1017
|
-
try expectValue(false, chance.actions.p2.durations.thrash);
|
|
1018
|
-
|
|
1019
|
-
chance.reset();
|
|
1020
|
-
}
|
|
1021
|
-
}
|
|
1022
|
-
|
|
1023
|
-
chance.reset();
|
|
1024
|
-
|
|
1025
|
-
chance.actions.p2.durations.thrash = true;
|
|
1026
|
-
for ([_]u8{ 1, 2, 1 }, 1..4) |d, i| {
|
|
1027
|
-
if (i > 1) {
|
|
1028
|
-
chance.actions.p2.durations.confusion = @intCast(i);
|
|
1029
|
-
try chance.confusion(.P2, 0);
|
|
1030
|
-
try expectProbability(&chance.probability, 1, d);
|
|
1031
|
-
try expectValue(@as(u3, 0), chance.actions.p2.durations.confusion);
|
|
1032
|
-
try expectValue(true, chance.actions.p2.durations.thrash);
|
|
1033
|
-
|
|
1034
|
-
chance.reset();
|
|
1035
|
-
}
|
|
1036
|
-
|
|
1037
|
-
if (i < 3) {
|
|
1038
|
-
chance.actions.p2.durations.confusion = @intCast(i);
|
|
1039
|
-
try chance.confusion(.P2, 1);
|
|
1040
|
-
try expectProbability(&chance.probability, if (d > 1) d - 1 else d, d);
|
|
1041
|
-
try expectValue(@as(u3, @intCast(i)) + 1, chance.actions.p2.durations.confusion);
|
|
1042
|
-
try expectValue(true, chance.actions.p2.durations.thrash);
|
|
1043
|
-
|
|
1044
|
-
chance.reset();
|
|
1045
|
-
}
|
|
1046
|
-
}
|
|
1047
|
-
}
|
|
1048
|
-
|
|
1049
|
-
test "Chance.disable" {
|
|
1050
|
-
var chance: Chance(rational.Rational(u64)) = .{ .probability = .{} };
|
|
1051
|
-
if (showdown) {
|
|
1052
|
-
for ([_]u8{ 1, 4, 3, 2, 1 }, 1..6) |d, i| {
|
|
1053
|
-
if (i > 1) {
|
|
1054
|
-
chance.actions.p2.durations.disable = @intCast(i);
|
|
1055
|
-
try chance.disable(.P2, 0);
|
|
1056
|
-
try expectProbability(&chance.probability, 1, d);
|
|
1057
|
-
try expectValue(@as(u4, 0), chance.actions.p2.durations.disable);
|
|
1058
|
-
|
|
1059
|
-
chance.reset();
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
|
-
if (i < 5) {
|
|
1063
|
-
chance.actions.p2.durations.disable = @intCast(i);
|
|
1064
|
-
try chance.disable(.P2, 1);
|
|
1065
|
-
try expectProbability(&chance.probability, if (d > 1) d - 1 else d, d);
|
|
1066
|
-
try expectValue(@as(u4, @intCast(i)) + 1, chance.actions.p2.durations.disable);
|
|
1067
|
-
|
|
1068
|
-
chance.reset();
|
|
1069
|
-
}
|
|
1070
|
-
}
|
|
1071
|
-
} else {
|
|
1072
|
-
for ([_]u8{ 1, 7, 6, 5, 4, 3, 2, 1 }, 1..9) |d, i| {
|
|
1073
|
-
if (i > 1) {
|
|
1074
|
-
chance.actions.p2.durations.disable = @intCast(i);
|
|
1075
|
-
try chance.disable(.P2, 0);
|
|
1076
|
-
try expectProbability(&chance.probability, 1, d);
|
|
1077
|
-
try expectValue(@as(u4, 0), chance.actions.p2.durations.disable);
|
|
1078
|
-
|
|
1079
|
-
chance.reset();
|
|
1080
|
-
}
|
|
1081
|
-
|
|
1082
|
-
if (i < 8) {
|
|
1083
|
-
chance.actions.p2.durations.disable = @intCast(i);
|
|
1084
|
-
try chance.disable(.P2, 1);
|
|
1085
|
-
try expectProbability(&chance.probability, if (d > 1) d - 1 else d, d);
|
|
1086
|
-
try expectValue(@as(u4, @intCast(i)) + 1, chance.actions.p2.durations.disable);
|
|
1087
|
-
|
|
1088
|
-
chance.reset();
|
|
1089
|
-
}
|
|
1090
|
-
}
|
|
1091
|
-
}
|
|
1092
|
-
}
|
|
1093
|
-
|
|
1094
|
-
test "Chance.attacking" {
|
|
1095
|
-
var chance: Chance(rational.Rational(u64)) = .{ .probability = .{} };
|
|
1096
|
-
|
|
1097
|
-
for ([_]u8{ 1, 2, 1 }, 1..4) |d, i| {
|
|
1098
|
-
if (i > 1) {
|
|
1099
|
-
chance.actions.p2.durations.attacking = @intCast(i);
|
|
1100
|
-
try chance.attacking(.P2, 0);
|
|
1101
|
-
try expectProbability(&chance.probability, 1, d);
|
|
1102
|
-
try expectValue(@as(u3, 0), chance.actions.p2.durations.attacking);
|
|
1103
|
-
|
|
1104
|
-
chance.reset();
|
|
1105
|
-
}
|
|
1106
|
-
|
|
1107
|
-
if (i < 3) {
|
|
1108
|
-
chance.actions.p2.durations.attacking = @intCast(i);
|
|
1109
|
-
try chance.attacking(.P2, 1);
|
|
1110
|
-
try expectProbability(&chance.probability, if (d > 1) d - 1 else d, d);
|
|
1111
|
-
try expectValue(@as(u3, @intCast(i)) + 1, chance.actions.p2.durations.attacking);
|
|
1112
|
-
|
|
1113
|
-
chance.reset();
|
|
1114
|
-
}
|
|
1115
|
-
}
|
|
1116
|
-
}
|
|
1117
|
-
|
|
1118
|
-
test "Chance.binding" {
|
|
1119
|
-
var chance: Chance(rational.Rational(u64)) = .{ .probability = .{} };
|
|
1120
|
-
|
|
1121
|
-
for ([_]u8{ 1, 4, 3, 2, 1 }, 1..6) |d, i| {
|
|
1122
|
-
if (i > 1) {
|
|
1123
|
-
chance.actions.p2.durations.binding = @intCast(i);
|
|
1124
|
-
try chance.binding(.P2, 0);
|
|
1125
|
-
try expectProbability(&chance.probability, 1, d);
|
|
1126
|
-
try expectValue(@as(u3, 0), chance.actions.p2.durations.binding);
|
|
1127
|
-
|
|
1128
|
-
chance.reset();
|
|
1129
|
-
}
|
|
1130
|
-
|
|
1131
|
-
if (i < 5) {
|
|
1132
|
-
chance.actions.p2.durations.binding = @intCast(i);
|
|
1133
|
-
try chance.binding(.P2, 1);
|
|
1134
|
-
try expectProbability(&chance.probability, if (d > 1) d - 1 else d, d);
|
|
1135
|
-
try expectValue(@as(u3, @intCast(i)) + 1, chance.actions.p2.durations.binding);
|
|
1136
|
-
|
|
1137
|
-
chance.reset();
|
|
1138
|
-
}
|
|
1139
|
-
}
|
|
1140
|
-
}
|
|
1141
|
-
|
|
1142
|
-
test "Chance.encore" {
|
|
1143
|
-
var chance: Chance(rational.Rational(u64)) = .{ .probability = .{} };
|
|
1144
|
-
|
|
1145
|
-
for ([_]u8{ 1, 4, 3, 2, 1 }, 1..6) |d, i| {
|
|
1146
|
-
if (i > 1) {
|
|
1147
|
-
chance.actions.p2.durations.encore = @intCast(i);
|
|
1148
|
-
try chance.encore(.P2, 0);
|
|
1149
|
-
try expectProbability(&chance.probability, 1, d);
|
|
1150
|
-
try expectValue(@as(u3, 0), chance.actions.p2.durations.encore);
|
|
1151
|
-
|
|
1152
|
-
chance.reset();
|
|
1153
|
-
}
|
|
1154
|
-
|
|
1155
|
-
if (i < 5) {
|
|
1156
|
-
chance.actions.p2.durations.encore = @intCast(i);
|
|
1157
|
-
try chance.encore(.P2, 1);
|
|
1158
|
-
try expectProbability(&chance.probability, if (d > 1) d - 1 else d, d);
|
|
1159
|
-
try expectValue(@as(u3, @intCast(i)) + 1, chance.actions.p2.durations.encore);
|
|
1160
|
-
|
|
1161
|
-
chance.reset();
|
|
1162
|
-
}
|
|
1163
|
-
}
|
|
760
|
+
chance.duration(.P1, 2);
|
|
761
|
+
try expectValue(2, chance.actions.p1.duration);
|
|
1164
762
|
}
|
|
1165
763
|
|
|
1166
764
|
pub fn expectProbability(r: anytype, p: u64, q: u64) !void {
|
|
@@ -1278,37 +876,7 @@ const Null = struct {
|
|
|
1278
876
|
_ = .{ self, player, move, n };
|
|
1279
877
|
}
|
|
1280
878
|
|
|
1281
|
-
pub fn duration(
|
|
1282
|
-
self: Null,
|
|
1283
|
-
comptime field: Duration.Field,
|
|
1284
|
-
player: Player,
|
|
1285
|
-
target: Player,
|
|
1286
|
-
turns: u4,
|
|
1287
|
-
) void {
|
|
1288
|
-
_ = .{ self, field, player, target, turns };
|
|
1289
|
-
}
|
|
1290
|
-
|
|
1291
|
-
pub fn sleep(self: Null, player: Player, turns: u4) Error!void {
|
|
1292
|
-
_ = .{ self, player, turns };
|
|
1293
|
-
}
|
|
1294
|
-
|
|
1295
|
-
pub fn confusion(self: Null, player: Player, turns: u4) Error!void {
|
|
1296
|
-
_ = .{ self, player, turns };
|
|
1297
|
-
}
|
|
1298
|
-
|
|
1299
|
-
pub fn disable(self: Null, player: Player, turns: u4) Error!void {
|
|
1300
|
-
_ = .{ self, player, turns };
|
|
1301
|
-
}
|
|
1302
|
-
|
|
1303
|
-
pub fn attacking(self: Null, player: Player, turns: u4) Error!void {
|
|
1304
|
-
_ = .{ self, player, turns };
|
|
1305
|
-
}
|
|
1306
|
-
|
|
1307
|
-
pub fn binding(self: Null, player: Player, turns: u4) Error!void {
|
|
1308
|
-
_ = .{ self, player, turns };
|
|
1309
|
-
}
|
|
1310
|
-
|
|
1311
|
-
pub fn encore(self: Null, player: Player, turns: u4) Error!void {
|
|
879
|
+
pub fn duration(self: Null, player: Player, turns: u4) void {
|
|
1312
880
|
_ = .{ self, player, turns };
|
|
1313
881
|
}
|
|
1314
882
|
};
|