@pkmn/engine 0.1.0-dev.b01cb48c → 0.1.0-dev.b14f2221
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 -1
- package/README.md +21 -11
- package/build/pkg/addon/browser.d.ts +3 -0
- package/build/pkg/addon/browser.js +47 -0
- package/build/pkg/addon/browser.js.map +1 -0
- package/build/pkg/addon/node.d.ts +3 -0
- package/build/pkg/addon/node.js +110 -0
- package/build/pkg/addon/node.js.map +1 -0
- package/build/pkg/addon/wasm.d.ts +2 -0
- package/build/pkg/addon/wasm.js +53 -0
- package/build/pkg/addon/wasm.js.map +1 -0
- package/build/pkg/addon.d.ts +26 -4
- package/build/pkg/addon.js +34 -65
- package/build/pkg/addon.js.map +1 -1
- package/build/pkg/data/layout.json +15 -2
- package/build/pkg/data/protocol.json +23 -9
- package/build/pkg/data.d.ts +23 -1
- package/build/pkg/data.js.map +1 -1
- package/build/pkg/gen1.d.ts +15 -18
- package/build/pkg/gen1.js +28 -19
- package/build/pkg/gen1.js.map +1 -1
- package/build/pkg/index.d.ts +40 -90
- package/build/pkg/index.js +23 -70
- package/build/pkg/index.js.map +1 -1
- package/build/pkg/protocol.d.ts +20 -1
- package/build/pkg/protocol.js +105 -103
- package/build/pkg/protocol.js.map +1 -1
- package/build/tools/debug.js +68 -74
- package/build/tools/debug.js.map +1 -1
- package/build/tools/display/debug.jsx +152 -0
- package/build/tools/display/debug.jsx.map +1 -0
- package/build/tools/display/index.js +152 -0
- package/build/tools/display/index.js.map +1 -0
- package/build/tools/display/ui.jsx +359 -0
- package/build/tools/display/ui.jsx.map +1 -0
- package/build/tools/display/util.js +33 -0
- package/build/tools/display/util.js.map +1 -0
- package/build.zig +255 -102
- package/package.json +59 -138
- package/src/bin/install-pkmn-engine +25 -7
- package/src/bin/pkmn-debug +1 -1
- package/src/lib/bindings/c.zig +200 -0
- package/src/lib/bindings/node.zig +117 -0
- package/src/lib/bindings/wasm.zig +50 -0
- package/src/lib/common/array.zig +70 -0
- package/src/lib/common/data.zig +8 -8
- package/src/lib/common/debug.zig +30 -9
- package/src/lib/common/js.zig +3 -7
- package/src/lib/common/optional.zig +11 -17
- package/src/lib/common/options.zig +4 -0
- package/src/lib/common/protocol.zig +195 -159
- package/src/lib/common/rational.zig +303 -310
- package/src/lib/common/rng.zig +5 -7
- package/src/lib/common/util.zig +33 -1
- package/src/lib/gen1/calc.zig +324 -180
- package/src/lib/gen1/chance.zig +536 -140
- 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 +3 -4
- package/src/lib/gen1/data.zig +40 -43
- package/src/lib/gen1/helpers.zig +17 -29
- package/src/lib/gen1/mechanics.zig +240 -187
- package/src/lib/gen2/calc.zig +35 -28
- package/src/lib/gen2/chance.zig +88 -74
- 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 +7 -5
- package/src/lib/gen2/data.zig +33 -35
- package/src/lib/gen2/generated.zig +18 -23
- package/src/lib/gen2/helpers.zig +9 -20
- package/src/lib/gen2/mechanics.zig +98 -98
- package/src/lib/napi.h +2 -0
- package/src/lib/node.zig +4 -121
- package/src/lib/pkmn.zig +103 -22
- package/src/lib/wasm.zig +9 -9
- package/src/tools/display/dom.ts +93 -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/gen2/calc.zig
CHANGED
|
@@ -1,23 +1,20 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
3
|
-
const pkmn = @import("../pkmn.zig");
|
|
4
|
-
|
|
1
|
+
const chance = @import("chance.zig");
|
|
5
2
|
const common = @import("../common/data.zig");
|
|
3
|
+
const Optional = @import("../common/optional.zig").Optional;
|
|
4
|
+
const pkmn = @import("../pkmn.zig");
|
|
5
|
+
const std = @import("std");
|
|
6
6
|
const util = @import("../common/util.zig");
|
|
7
7
|
|
|
8
|
-
const
|
|
9
|
-
|
|
8
|
+
const Action = chance.Action;
|
|
9
|
+
const Actions = chance.Actions;
|
|
10
10
|
const assert = std.debug.assert;
|
|
11
|
-
|
|
11
|
+
const Criticals = chance.Criticals;
|
|
12
|
+
const Damages = chance.Damages;
|
|
12
13
|
const enabled = pkmn.options.calc;
|
|
13
|
-
|
|
14
|
+
const isPointerTo = util.isPointerTo;
|
|
14
15
|
const Player = common.Player;
|
|
15
|
-
|
|
16
16
|
const PointerType = util.PointerType;
|
|
17
17
|
|
|
18
|
-
const Actions = chance.Actions;
|
|
19
|
-
const Action = chance.Action;
|
|
20
|
-
|
|
21
18
|
/// Information relevant to damage calculation that occured during a Generation II battle `update`.
|
|
22
19
|
pub const Summaries = extern struct {
|
|
23
20
|
/// Relevant information for Player 1.
|
|
@@ -31,7 +28,7 @@ pub const Summaries = extern struct {
|
|
|
31
28
|
|
|
32
29
|
/// Returns the `Summary` for the given `player`.
|
|
33
30
|
pub fn get(self: anytype, player: Player) PointerType(@TypeOf(self), Summary) {
|
|
34
|
-
assert(
|
|
31
|
+
assert(isPointerTo(self, Summaries));
|
|
35
32
|
return if (player == .P1) &self.p1 else &self.p2;
|
|
36
33
|
}
|
|
37
34
|
};
|
|
@@ -65,33 +62,34 @@ pub const Summary = extern struct {
|
|
|
65
62
|
}
|
|
66
63
|
};
|
|
67
64
|
|
|
68
|
-
/// TODO
|
|
69
|
-
pub const Overrides = extern struct {
|
|
70
|
-
/// TODO
|
|
71
|
-
actions: Actions = .{},
|
|
72
|
-
};
|
|
73
|
-
|
|
74
65
|
/// Allows for forcing the value of specific RNG events during a Generation II battle `update` via
|
|
75
66
|
/// `overrides` and tracks `summaries` of information relevant to damage calculation.
|
|
76
67
|
pub const Calc = struct {
|
|
77
68
|
/// Overrides the normal behavior of the RNG during an `update` to force specific outcomes.
|
|
78
|
-
overrides:
|
|
69
|
+
overrides: Actions = .{},
|
|
79
70
|
/// Information relevant to damage calculation.
|
|
80
71
|
summaries: Summaries = .{},
|
|
81
72
|
|
|
82
73
|
pub fn overridden(
|
|
83
74
|
self: Calc,
|
|
84
75
|
player: Player,
|
|
76
|
+
hit: u3,
|
|
85
77
|
comptime field: Action.Field,
|
|
86
|
-
)
|
|
78
|
+
) ReturnType(field) {
|
|
87
79
|
if (!enabled) return null;
|
|
88
80
|
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
81
|
+
const val = switch (field) {
|
|
82
|
+
.damages => Damages.get(self.overrides.get(player).damages, hit),
|
|
83
|
+
.critical_hits => Criticals.get(self.overrides.get(player).critical_hits, hit),
|
|
84
|
+
else => val: {
|
|
85
|
+
assert(hit == 0);
|
|
86
|
+
break :val @field(self.overrides.get(player), @tagName(field));
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
|
|
92
90
|
return if (switch (@typeInfo(@TypeOf(val))) {
|
|
93
|
-
|
|
94
|
-
.
|
|
91
|
+
.@"enum" => val != .None,
|
|
92
|
+
.int => val != 0,
|
|
95
93
|
else => unreachable,
|
|
96
94
|
}) val else null;
|
|
97
95
|
}
|
|
@@ -123,9 +121,10 @@ const Null = struct {
|
|
|
123
121
|
pub fn overridden(
|
|
124
122
|
self: Null,
|
|
125
123
|
player: Player,
|
|
124
|
+
hit: u3,
|
|
126
125
|
comptime field: Action.Field,
|
|
127
|
-
)
|
|
128
|
-
_ = .{ self, player };
|
|
126
|
+
) ReturnType(field) {
|
|
127
|
+
_ = .{ self, player, hit };
|
|
129
128
|
return null;
|
|
130
129
|
}
|
|
131
130
|
|
|
@@ -141,3 +140,11 @@ const Null = struct {
|
|
|
141
140
|
_ = .{ self, player };
|
|
142
141
|
}
|
|
143
142
|
};
|
|
143
|
+
|
|
144
|
+
fn ReturnType(comptime field: Action.Field) type {
|
|
145
|
+
return ?(switch (field) {
|
|
146
|
+
.damages => u8,
|
|
147
|
+
.critical_hits => Optional(bool),
|
|
148
|
+
else => @FieldType(Action, @tagName(field)),
|
|
149
|
+
});
|
|
150
|
+
}
|
package/src/lib/gen2/chance.zig
CHANGED
|
@@ -8,9 +8,9 @@ const expectEqual = std.testing.expectEqual;
|
|
|
8
8
|
|
|
9
9
|
const options = @import("../common/options.zig");
|
|
10
10
|
const rational = @import("../common/rational.zig");
|
|
11
|
-
const rng = @import("../common/rng.zig");
|
|
12
11
|
const util = @import("../common/util.zig");
|
|
13
12
|
|
|
13
|
+
const Array = @import("../common/array.zig").Array;
|
|
14
14
|
const Player = @import("../common/data.zig").Player;
|
|
15
15
|
const Optional = @import("../common/optional.zig").Optional;
|
|
16
16
|
|
|
@@ -19,7 +19,8 @@ const data = @import("data.zig");
|
|
|
19
19
|
const enabled = options.chance;
|
|
20
20
|
const showdown = options.showdown;
|
|
21
21
|
|
|
22
|
-
const
|
|
22
|
+
const PointerType = util.PointerType;
|
|
23
|
+
const isPointerTo = util.isPointerTo;
|
|
23
24
|
|
|
24
25
|
const Move = data.Move;
|
|
25
26
|
const Type = data.Type;
|
|
@@ -37,8 +38,8 @@ pub const Actions = extern struct {
|
|
|
37
38
|
p2: Action = .{},
|
|
38
39
|
|
|
39
40
|
/// Returns the `Action` for the given `player`.
|
|
40
|
-
pub fn get(self: anytype, player: Player)
|
|
41
|
-
assert(
|
|
41
|
+
pub fn get(self: anytype, player: Player) PointerType(@TypeOf(self), Action) {
|
|
42
|
+
assert(isPointerTo(self, Actions));
|
|
42
43
|
return if (player == .P1) &self.p1 else &self.p2;
|
|
43
44
|
}
|
|
44
45
|
|
|
@@ -52,15 +53,15 @@ pub const Actions = extern struct {
|
|
|
52
53
|
/// same shape if they have the same fields set (though those fields need not necessarily be
|
|
53
54
|
/// set to the same value).
|
|
54
55
|
pub fn matches(a: Actions, b: Actions) bool {
|
|
55
|
-
inline for (@typeInfo(Actions).
|
|
56
|
-
inline for (@typeInfo(Action).
|
|
56
|
+
inline for (@typeInfo(Actions).@"struct".fields) |player| {
|
|
57
|
+
inline for (@typeInfo(Action).@"struct".fields) |field| {
|
|
57
58
|
const a_val = @field(@field(a, player.name), field.name);
|
|
58
59
|
const b_val = @field(@field(b, player.name), field.name);
|
|
59
60
|
|
|
60
61
|
switch (@typeInfo(@TypeOf(a_val))) {
|
|
61
|
-
|
|
62
|
+
.@"enum" => if ((@intFromEnum(a_val) > 0) != (@intFromEnum(b_val) > 0))
|
|
62
63
|
return false,
|
|
63
|
-
.
|
|
64
|
+
.int => if ((a_val > 0) != (b_val > 0)) return false,
|
|
64
65
|
else => unreachable,
|
|
65
66
|
}
|
|
66
67
|
}
|
|
@@ -68,7 +69,7 @@ pub const Actions = extern struct {
|
|
|
68
69
|
return true;
|
|
69
70
|
}
|
|
70
71
|
|
|
71
|
-
pub fn fmt(self: Actions, writer:
|
|
72
|
+
pub fn fmt(self: Actions, writer: *std.Io.Writer, shape: bool) !void {
|
|
72
73
|
try writer.writeAll("<P1 = ");
|
|
73
74
|
try self.p1.fmt(writer, shape);
|
|
74
75
|
try writer.writeAll(", P2 = ");
|
|
@@ -76,16 +77,14 @@ pub const Actions = extern struct {
|
|
|
76
77
|
try writer.writeAll(">");
|
|
77
78
|
}
|
|
78
79
|
|
|
79
|
-
pub fn format(a: Actions,
|
|
80
|
-
_ = .{ f, o };
|
|
80
|
+
pub fn format(a: Actions, w: *std.Io.Writer) !void {
|
|
81
81
|
try fmt(a, w, false);
|
|
82
82
|
}
|
|
83
83
|
};
|
|
84
84
|
|
|
85
|
-
// TODO: ziglang/zig#19730
|
|
86
85
|
test Actions {
|
|
87
|
-
const a: Actions = .{ .p1 = .{ .hit = .true, .
|
|
88
|
-
const b: Actions = .{ .p1 = .{ .hit = .false, .
|
|
86
|
+
const a: Actions = .{ .p1 = .{ .hit = .true, .confused = .false, .damages = 245 } };
|
|
87
|
+
const b: Actions = .{ .p1 = .{ .hit = .false, .confused = .true, .damages = 246 } };
|
|
89
88
|
const c: Actions = .{ .p1 = .{ .hit = .true } };
|
|
90
89
|
|
|
91
90
|
try expect(a.eql(a));
|
|
@@ -101,11 +100,19 @@ test Actions {
|
|
|
101
100
|
try expect(!c.matches(a));
|
|
102
101
|
}
|
|
103
102
|
|
|
103
|
+
/// Observation made about a duration - whether the duration has started, been continued, or ended.
|
|
104
|
+
pub const Observation = enum { started, continuing, ended };
|
|
105
|
+
|
|
106
|
+
pub const Damages = Array(5, u8);
|
|
107
|
+
pub const Criticals = Array(5, Optional(bool));
|
|
108
|
+
|
|
104
109
|
/// Information about the RNG that was observed during a Generation II battle `update` for a
|
|
105
110
|
/// single player.
|
|
106
111
|
pub const Action = packed struct(u128) {
|
|
107
|
-
///
|
|
108
|
-
|
|
112
|
+
/// TODO
|
|
113
|
+
damages: Damages.T = 0,
|
|
114
|
+
// TODO
|
|
115
|
+
critical_hits: Criticals.T = 0,
|
|
109
116
|
|
|
110
117
|
/// If not None, the Player to be returned by Rolls.speedTie.
|
|
111
118
|
speed_tie: Optional(Player) = .None,
|
|
@@ -113,50 +120,58 @@ pub const Action = packed struct(u128) {
|
|
|
113
120
|
quick_claw: Optional(bool) = .None,
|
|
114
121
|
/// If not None, the value to return for Rolls.hit.
|
|
115
122
|
hit: Optional(bool) = .None,
|
|
116
|
-
/// If not None, the value to be returned by Rolls.criticalHit.
|
|
117
|
-
critical_hit: Optional(bool) = .None,
|
|
118
|
-
|
|
119
123
|
/// If not None, the value to return for Rolls.confused.
|
|
120
124
|
confused: Optional(bool) = .None,
|
|
125
|
+
|
|
121
126
|
/// If not None, the value to return for Rolls.attract.
|
|
122
127
|
attract: Optional(bool) = .None,
|
|
123
128
|
/// If not None, the value to return for Rolls.paralyzed.
|
|
124
129
|
paralyzed: Optional(bool) = .None,
|
|
125
130
|
/// If not None, the value to return for Rolls.defrost.
|
|
126
131
|
defrost: Optional(bool) = .None,
|
|
127
|
-
|
|
128
132
|
/// If not None, the value to be returned for Rolls.secondaryChance.
|
|
129
133
|
secondary_chance: Optional(bool) = .None,
|
|
134
|
+
|
|
130
135
|
/// If not None, the value to be returned for Rolls.item (Focus Band / King's Rock).
|
|
131
136
|
item: Optional(bool) = .None,
|
|
132
137
|
/// If not None, the value to be returned for Rolls.protect.
|
|
133
138
|
protect: Optional(bool) = .None,
|
|
134
139
|
/// If not None, the value to return for Rolls.triAttack.
|
|
135
140
|
tri_attack: Optional(TriAttack) = .None,
|
|
141
|
+
/// If not 0, the value to return for Rolls.tripleKick.
|
|
142
|
+
triple_kick: u2 = 0,
|
|
136
143
|
|
|
137
144
|
/// If not 0, (present - 1) * 40 should be returned as the base power for Rolls.present.
|
|
138
145
|
present: u3 = 0,
|
|
139
146
|
/// If not 0, magnitude + 3 should be returned as the number for Rolls.magnitude.
|
|
140
147
|
magnitude: u3 = 0,
|
|
141
|
-
/// If not 0, the
|
|
142
|
-
triple_kick: u2 = 0,
|
|
143
|
-
|
|
144
|
-
/// If not 0, the amount of PP to deduct for Rolls.spite.
|
|
148
|
+
/// If not 0, the amount of PP to deduct for Rolls.spite.
|
|
145
149
|
spite: u3 = 0,
|
|
146
|
-
/// If not None, the value to return for Rolls.conversion2.
|
|
147
|
-
conversion_2: Optional(Type) = .None,
|
|
148
|
-
|
|
149
150
|
/// If not 0, the move slot (1-4) to return in Rolls.moveSlot. If present as an override,
|
|
150
151
|
/// invalid values (eg. due to empty move slots or 0 PP) will be ignored.
|
|
151
|
-
move_slot:
|
|
152
|
+
move_slot: u3 = 0,
|
|
152
153
|
/// If not 0, the party slot (1-6) to return in Rolls.forceSwitch. If present as an override,
|
|
153
154
|
/// invalid values (eg. due to empty party slots or fainted members) will be ignored.
|
|
154
|
-
force_switch:
|
|
155
|
-
|
|
155
|
+
force_switch: u3 = 0,
|
|
156
156
|
/// If not 0, the value (2-5) to return for Rolls.distribution for multi hit.
|
|
157
|
-
multi_hit:
|
|
157
|
+
multi_hit: u3 = 0,
|
|
158
|
+
|
|
159
|
+
sleep: Optional(Observation) = .None,
|
|
160
|
+
/// TODO
|
|
161
|
+
confusion: Optional(Observation) = .None,
|
|
162
|
+
/// TODO
|
|
163
|
+
disable: Optional(Observation) = .None,
|
|
164
|
+
/// TODO
|
|
165
|
+
attacking: Optional(Observation) = .None,
|
|
166
|
+
/// TODO
|
|
167
|
+
binding: Optional(Observation) = .None,
|
|
168
|
+
/// TODO
|
|
169
|
+
encore: Optional(Observation) = .None,
|
|
170
|
+
|
|
158
171
|
/// If not 0, the value to by one of the Rolls.*Duration rolls.
|
|
159
|
-
duration:
|
|
172
|
+
duration: u3 = 0,
|
|
173
|
+
/// If not None, the value to return for Rolls.conversion2.
|
|
174
|
+
conversion_2: Optional(Type) = .None,
|
|
160
175
|
|
|
161
176
|
/// If not 0, psywave should be returned as the damage roll for Rolls.psywave.
|
|
162
177
|
psywave: u8 = 0,
|
|
@@ -164,22 +179,19 @@ pub const Action = packed struct(u128) {
|
|
|
164
179
|
/// If not None, the Move to return for Rolls.metronome.
|
|
165
180
|
metronome: Move = .None,
|
|
166
181
|
|
|
167
|
-
_: u48 = 0, // TODO
|
|
168
|
-
|
|
169
182
|
pub const Field = std.meta.FieldEnum(Action);
|
|
170
183
|
|
|
171
|
-
pub fn format(a: Action,
|
|
172
|
-
_ = .{ f, o };
|
|
184
|
+
pub fn format(a: Action, w: *std.Io.Writer) !void {
|
|
173
185
|
try fmt(a, w, false);
|
|
174
186
|
}
|
|
175
187
|
|
|
176
|
-
pub fn fmt(self: Action, writer:
|
|
188
|
+
pub fn fmt(self: Action, writer: *std.Io.Writer, shape: bool) !void {
|
|
177
189
|
try writer.writeByte('(');
|
|
178
190
|
var printed = false;
|
|
179
|
-
inline for (@typeInfo(Action).
|
|
191
|
+
inline for (@typeInfo(Action).@"struct".fields) |field| {
|
|
180
192
|
const val = @field(self, field.name);
|
|
181
193
|
switch (@typeInfo(@TypeOf(val))) {
|
|
182
|
-
|
|
194
|
+
.@"enum" => if (val != .None) {
|
|
183
195
|
if (printed) try writer.writeAll(", ");
|
|
184
196
|
if (shape) {
|
|
185
197
|
try writer.print("{s}:?", .{field.name});
|
|
@@ -193,7 +205,7 @@ pub const Action = packed struct(u128) {
|
|
|
193
205
|
}
|
|
194
206
|
printed = true;
|
|
195
207
|
},
|
|
196
|
-
.
|
|
208
|
+
.int => if (val != 0) {
|
|
197
209
|
if (printed) try writer.writeAll(", ");
|
|
198
210
|
if (shape) {
|
|
199
211
|
try writer.print("{s}:?", .{field.name});
|
|
@@ -255,19 +267,21 @@ pub fn Chance(comptime Rational: type) type {
|
|
|
255
267
|
self.actions.get(player).hit = if (ok) .true else .false;
|
|
256
268
|
}
|
|
257
269
|
|
|
258
|
-
pub fn criticalHit(self: *Self, player: Player, crit: bool, rate: u8) Error!void {
|
|
270
|
+
pub fn criticalHit(self: *Self, player: Player, i: u3, crit: bool, rate: u8) Error!void {
|
|
259
271
|
if (!enabled) return;
|
|
260
272
|
|
|
261
273
|
const n = if (crit) rate else @as(u8, @intCast(256 - @as(u9, rate)));
|
|
262
274
|
try self.probability.update(n, 256);
|
|
263
|
-
self.actions.get(player)
|
|
275
|
+
var a = self.actions.get(player);
|
|
276
|
+
a.critical_hits = Criticals.set(a.critical_hits, i, if (crit) .true else .false);
|
|
264
277
|
}
|
|
265
278
|
|
|
266
|
-
pub fn damage(self: *Self, player: Player, roll: u8) Error!void {
|
|
279
|
+
pub fn damage(self: *Self, player: Player, i: u3, roll: u8) Error!void {
|
|
267
280
|
if (!enabled) return;
|
|
268
281
|
|
|
269
282
|
try self.probability.update(1, 39);
|
|
270
|
-
self.actions.get(player)
|
|
283
|
+
var a = self.actions.get(player);
|
|
284
|
+
a.damages = Damages.set(a.damages, i, roll);
|
|
271
285
|
}
|
|
272
286
|
|
|
273
287
|
pub fn confused(self: *Self, player: Player, cfz: bool) Error!void {
|
|
@@ -419,10 +433,10 @@ pub fn Chance(comptime Rational: type) type {
|
|
|
419
433
|
self.actions.get(player).multi_hit = n;
|
|
420
434
|
}
|
|
421
435
|
|
|
422
|
-
pub fn duration(self: *Self, player: Player, turns:
|
|
436
|
+
pub fn duration(self: *Self, player: Player, turns: u3) void {
|
|
423
437
|
if (!enabled) return;
|
|
424
438
|
|
|
425
|
-
self.actions.get(player).duration = if (options.key)
|
|
439
|
+
self.actions.get(player).duration = if (options.key) 2 else turns;
|
|
426
440
|
}
|
|
427
441
|
};
|
|
428
442
|
}
|
|
@@ -474,22 +488,22 @@ test "Chance.hit" {
|
|
|
474
488
|
test "Chance.criticalHit" {
|
|
475
489
|
var chance: Chance(rational.Rational(u64)) = .{ .probability = .{} };
|
|
476
490
|
|
|
477
|
-
try chance.criticalHit(.P1, true, 17);
|
|
478
|
-
try expectValue(Optional(bool).true, chance.actions.p1.
|
|
491
|
+
try chance.criticalHit(.P1, 0, true, 17);
|
|
492
|
+
try expectValue(Optional(bool).true, Criticals.get(chance.actions.p1.critical_hits, 0));
|
|
479
493
|
try expectProbability(&chance.probability, 17, 256);
|
|
480
494
|
|
|
481
495
|
chance.reset();
|
|
482
496
|
|
|
483
|
-
try chance.criticalHit(.P2, false, 5);
|
|
497
|
+
try chance.criticalHit(.P2, 1, false, 5);
|
|
484
498
|
try expectProbability(&chance.probability, 251, 256);
|
|
485
|
-
try expectValue(Optional(bool).false, chance.actions.p2.
|
|
499
|
+
try expectValue(Optional(bool).false, Criticals.get(chance.actions.p2.critical_hits, 1));
|
|
486
500
|
}
|
|
487
501
|
|
|
488
502
|
test "Chance.damage" {
|
|
489
503
|
var chance: Chance(rational.Rational(u64)) = .{ .probability = .{} };
|
|
490
504
|
|
|
491
|
-
try chance.damage(.P1,
|
|
492
|
-
try expectValue(
|
|
505
|
+
try chance.damage(.P1, 0, 219);
|
|
506
|
+
try expectValue(@as(u8, 219), Damages.get(chance.actions.p1.damages, 0));
|
|
493
507
|
try expectProbability(&chance.probability, 1, 39);
|
|
494
508
|
}
|
|
495
509
|
|
|
@@ -614,7 +628,7 @@ test "Chance.present" {
|
|
|
614
628
|
} else {
|
|
615
629
|
try expectProbability(&chance.probability, 25, 256);
|
|
616
630
|
}
|
|
617
|
-
try expectValue(4, chance.actions.p2.present);
|
|
631
|
+
try expectValue(@as(u3, 4), chance.actions.p2.present);
|
|
618
632
|
|
|
619
633
|
chance.reset();
|
|
620
634
|
|
|
@@ -624,7 +638,7 @@ test "Chance.present" {
|
|
|
624
638
|
} else {
|
|
625
639
|
try expectProbability(&chance.probability, 51, 256);
|
|
626
640
|
}
|
|
627
|
-
try expectValue(1, chance.actions.p1.present);
|
|
641
|
+
try expectValue(@as(u3, 1), chance.actions.p1.present);
|
|
628
642
|
}
|
|
629
643
|
|
|
630
644
|
test "Chance.magnitude" {
|
|
@@ -636,7 +650,7 @@ test "Chance.magnitude" {
|
|
|
636
650
|
} else {
|
|
637
651
|
try expectProbability(&chance.probability, 13, 256);
|
|
638
652
|
}
|
|
639
|
-
try expectValue(7, chance.actions.p2.magnitude);
|
|
653
|
+
try expectValue(@as(u3, 7), chance.actions.p2.magnitude);
|
|
640
654
|
|
|
641
655
|
chance.reset();
|
|
642
656
|
|
|
@@ -646,7 +660,7 @@ test "Chance.magnitude" {
|
|
|
646
660
|
} else {
|
|
647
661
|
try expectProbability(&chance.probability, 51, 256);
|
|
648
662
|
}
|
|
649
|
-
try expectValue(5, chance.actions.p1.magnitude);
|
|
663
|
+
try expectValue(@as(u3, 5), chance.actions.p1.magnitude);
|
|
650
664
|
}
|
|
651
665
|
|
|
652
666
|
test "Chance.tripleKick" {
|
|
@@ -654,7 +668,7 @@ test "Chance.tripleKick" {
|
|
|
654
668
|
|
|
655
669
|
try chance.tripleKick(.P1, 2);
|
|
656
670
|
try expectProbability(&chance.probability, 1, 3);
|
|
657
|
-
try expectValue(2, chance.actions.p1.triple_kick);
|
|
671
|
+
try expectValue(@as(u2, 2), chance.actions.p1.triple_kick);
|
|
658
672
|
}
|
|
659
673
|
|
|
660
674
|
test "Chance.spite" {
|
|
@@ -662,7 +676,7 @@ test "Chance.spite" {
|
|
|
662
676
|
|
|
663
677
|
try chance.spite(.P1, 3);
|
|
664
678
|
try expectProbability(&chance.probability, 1, 4);
|
|
665
|
-
try expectValue(3, chance.actions.p1.spite);
|
|
679
|
+
try expectValue(@as(u3, 3), chance.actions.p1.spite);
|
|
666
680
|
}
|
|
667
681
|
|
|
668
682
|
test "Chance.conversion2" {
|
|
@@ -689,7 +703,7 @@ test "Chance.psywave" {
|
|
|
689
703
|
|
|
690
704
|
try chance.psywave(.P2, 100, 150);
|
|
691
705
|
try expectProbability(&chance.probability, 1, 150);
|
|
692
|
-
try expectValue(100, chance.actions.p2.psywave);
|
|
706
|
+
try expectValue(@as(u8, 100), chance.actions.p2.psywave);
|
|
693
707
|
}
|
|
694
708
|
|
|
695
709
|
test "Chance.metronome" {
|
|
@@ -705,19 +719,19 @@ test "Chance.moveSlot" {
|
|
|
705
719
|
|
|
706
720
|
try chance.moveSlot(.P2, 2, 2);
|
|
707
721
|
try expectProbability(&chance.probability, 1, 2);
|
|
708
|
-
try expectValue(2, chance.actions.p2.move_slot);
|
|
722
|
+
try expectValue(@as(u3, 2), chance.actions.p2.move_slot);
|
|
709
723
|
|
|
710
724
|
chance.reset();
|
|
711
725
|
|
|
712
726
|
try chance.moveSlot(.P1, 1, 3);
|
|
713
727
|
try expectProbability(&chance.probability, 1, 3);
|
|
714
|
-
try expectValue(1, chance.actions.p1.move_slot);
|
|
728
|
+
try expectValue(@as(u3, 1), chance.actions.p1.move_slot);
|
|
715
729
|
|
|
716
730
|
chance.reset();
|
|
717
731
|
|
|
718
732
|
try chance.moveSlot(.P1, 4, 1);
|
|
719
733
|
try expectProbability(&chance.probability, 1, 1);
|
|
720
|
-
try expectValue(4, chance.actions.p1.move_slot);
|
|
734
|
+
try expectValue(@as(u3, 4), chance.actions.p1.move_slot);
|
|
721
735
|
}
|
|
722
736
|
|
|
723
737
|
test "Chance.forceSwitch" {
|
|
@@ -725,19 +739,19 @@ test "Chance.forceSwitch" {
|
|
|
725
739
|
|
|
726
740
|
try chance.forceSwitch(.P2, 2, 2);
|
|
727
741
|
try expectProbability(&chance.probability, 1, 2);
|
|
728
|
-
try expectValue(2, chance.actions.p2.force_switch);
|
|
742
|
+
try expectValue(@as(u3, 2), chance.actions.p2.force_switch);
|
|
729
743
|
|
|
730
744
|
chance.reset();
|
|
731
745
|
|
|
732
746
|
try chance.forceSwitch(.P1, 1, 3);
|
|
733
747
|
try expectProbability(&chance.probability, 1, 3);
|
|
734
|
-
try expectValue(1, chance.actions.p1.force_switch);
|
|
748
|
+
try expectValue(@as(u3, 1), chance.actions.p1.force_switch);
|
|
735
749
|
|
|
736
750
|
chance.reset();
|
|
737
751
|
|
|
738
752
|
try chance.forceSwitch(.P1, 4, 1);
|
|
739
753
|
try expectProbability(&chance.probability, 1, 1);
|
|
740
|
-
try expectValue(4, chance.actions.p1.force_switch);
|
|
754
|
+
try expectValue(@as(u3, 4), chance.actions.p1.force_switch);
|
|
741
755
|
}
|
|
742
756
|
|
|
743
757
|
test "Chance.multiHit" {
|
|
@@ -745,20 +759,20 @@ test "Chance.multiHit" {
|
|
|
745
759
|
|
|
746
760
|
try chance.multiHit(.P1, 3);
|
|
747
761
|
try expectProbability(&chance.probability, 3, 8);
|
|
748
|
-
try expectValue(3, chance.actions.p1.multi_hit);
|
|
762
|
+
try expectValue(@as(u3, 3), chance.actions.p1.multi_hit);
|
|
749
763
|
|
|
750
764
|
chance.reset();
|
|
751
765
|
|
|
752
766
|
try chance.multiHit(.P2, 5);
|
|
753
767
|
try expectProbability(&chance.probability, 1, 8);
|
|
754
|
-
try expectValue(5, chance.actions.p2.multi_hit);
|
|
768
|
+
try expectValue(@as(u3, 5), chance.actions.p2.multi_hit);
|
|
755
769
|
}
|
|
756
770
|
|
|
757
771
|
test "Chance.duration" {
|
|
758
772
|
var chance: Chance(rational.Rational(u64)) = .{ .probability = .{} };
|
|
759
773
|
|
|
760
774
|
chance.duration(.P1, 2);
|
|
761
|
-
try expectValue(2, chance.actions.p1.duration);
|
|
775
|
+
try expectValue(@as(u3, 2), chance.actions.p1.duration);
|
|
762
776
|
}
|
|
763
777
|
|
|
764
778
|
pub fn expectProbability(r: anytype, p: u64, q: u64) !void {
|
|
@@ -766,7 +780,7 @@ pub fn expectProbability(r: anytype, p: u64, q: u64) !void {
|
|
|
766
780
|
|
|
767
781
|
r.reduce();
|
|
768
782
|
if (r.p != p or r.q != q) {
|
|
769
|
-
print("expected {d}/{d}, found {}\n", .{ p, q, r });
|
|
783
|
+
print("expected {d}/{d}, found {f}\n", .{ p, q, r });
|
|
770
784
|
return error.TestExpectedEqual;
|
|
771
785
|
}
|
|
772
786
|
}
|
|
@@ -800,12 +814,12 @@ const Null = struct {
|
|
|
800
814
|
_ = .{ self, player, ok, accuracy };
|
|
801
815
|
}
|
|
802
816
|
|
|
803
|
-
pub fn criticalHit(self: Null, player: Player, crit: bool, rate: u8) Error!void {
|
|
804
|
-
_ = .{ self, player, crit, rate };
|
|
817
|
+
pub fn criticalHit(self: Null, player: Player, i: u3, crit: bool, rate: u8) Error!void {
|
|
818
|
+
_ = .{ self, player, i, crit, rate };
|
|
805
819
|
}
|
|
806
820
|
|
|
807
|
-
pub fn damage(self: Null, player: Player, roll: u8) Error!void {
|
|
808
|
-
_ = .{ self, player, roll };
|
|
821
|
+
pub fn damage(self: Null, player: Player, i: u3, roll: u8) Error!void {
|
|
822
|
+
_ = .{ self, player, i, roll };
|
|
809
823
|
}
|
|
810
824
|
|
|
811
825
|
pub fn confused(self: Null, player: Player, ok: bool) Error!void {
|
|
@@ -876,7 +890,7 @@ const Null = struct {
|
|
|
876
890
|
_ = .{ self, player, move, n };
|
|
877
891
|
}
|
|
878
892
|
|
|
879
|
-
pub fn duration(self: Null, player: Player, turns:
|
|
893
|
+
pub fn duration(self: Null, player: Player, turns: u3) void {
|
|
880
894
|
_ = .{ self, player, turns };
|
|
881
895
|
}
|
|
882
896
|
};
|
|
@@ -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 data = @import("../../gen2/data.zig");
|
|
4
|
+
const std = @import("std");
|
|
6
5
|
|
|
7
6
|
const assert = std.debug.assert;
|
|
8
|
-
|
|
9
7
|
const Type = data.Type;
|
|
10
8
|
|
|
11
9
|
/// Representation of a held item in Generation II Pokémon.
|
|
@@ -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 gen2 = @import("../../gen2/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 = gen2.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 gen2 = @import("../../gen2/data.zig");
|
|
4
|
+
const std = @import("std");
|
|
6
5
|
|
|
7
6
|
const assert = std.debug.assert;
|
|
8
|
-
|
|
9
7
|
const Stats = gen2.Stats;
|
|
10
8
|
const Types = gen2.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;
|
|
@@ -173,9 +172,12 @@ pub const Type = enum(u8) {
|
|
|
173
172
|
return CHART[@intFromEnum(t1)][@intFromEnum(t2)];
|
|
174
173
|
}
|
|
175
174
|
|
|
176
|
-
/// The precedence order of Type `
|
|
177
|
-
pub fn precedence(
|
|
178
|
-
return
|
|
175
|
+
/// The precedence order of Type `t1` vs. Type `t2`.
|
|
176
|
+
pub fn precedence(t1: Type, t2: Type) u8 {
|
|
177
|
+
// The Ice vs. Fire matchup is out of order - return a higher
|
|
178
|
+
// number than anything else so that it sorts last correctly
|
|
179
|
+
if (t1 == .Ice and t2 == .Fire) return 18;
|
|
180
|
+
return PRECEDENCE[@intFromEnum(t2)];
|
|
179
181
|
}
|
|
180
182
|
|
|
181
183
|
/// The internal index of this Type used by Present.
|