@pkmn/engine 0.1.0-dev.b01cb48c → 0.1.0-dev.b3197aa3
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 +54 -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 +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 +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 +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 +52 -76
- 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 +331 -85
- package/package.json +56 -136
- 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 +117 -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 -6
- package/src/lib/common/napi.zig +4 -0
- 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 +317 -304
- package/src/lib/common/rng.zig +5 -7
- package/src/lib/common/util.zig +65 -1
- package/src/lib/gen1/calc.zig +266 -135
- package/src/lib/gen1/chance.zig +469 -110
- 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 +2 -3
- package/src/lib/gen1/data.zig +35 -38
- package/src/lib/gen1/helpers.zig +17 -27
- package/src/lib/gen1/mechanics.zig +213 -160
- package/src/lib/gen2/calc.zig +37 -27
- package/src/lib/gen2/chance.zig +87 -67
- 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 +28 -30
- package/src/lib/gen2/generated.zig +18 -23
- package/src/lib/gen2/helpers.zig +9 -18
- package/src/lib/gen2/mechanics.zig +82 -82
- package/src/lib/node.zig +4 -121
- package/src/lib/pkmn.zig +14 -7
- package/src/lib/wasm.zig +13 -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,22 +1,22 @@
|
|
|
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
|
|
19
|
-
const
|
|
18
|
+
const Int = if (@hasField(std.builtin.Type, "int")) .int else .Int;
|
|
19
|
+
const Enum = if (@hasField(std.builtin.Type, "enum")) .@"enum" else .Enum;
|
|
20
20
|
|
|
21
21
|
/// Information relevant to damage calculation that occured during a Generation II battle `update`.
|
|
22
22
|
pub const Summaries = extern struct {
|
|
@@ -31,7 +31,7 @@ pub const Summaries = extern struct {
|
|
|
31
31
|
|
|
32
32
|
/// Returns the `Summary` for the given `player`.
|
|
33
33
|
pub fn get(self: anytype, player: Player) PointerType(@TypeOf(self), Summary) {
|
|
34
|
-
assert(
|
|
34
|
+
assert(isPointerTo(self, Summaries));
|
|
35
35
|
return if (player == .P1) &self.p1 else &self.p2;
|
|
36
36
|
}
|
|
37
37
|
};
|
|
@@ -65,33 +65,34 @@ pub const Summary = extern struct {
|
|
|
65
65
|
}
|
|
66
66
|
};
|
|
67
67
|
|
|
68
|
-
/// TODO
|
|
69
|
-
pub const Overrides = extern struct {
|
|
70
|
-
/// TODO
|
|
71
|
-
actions: Actions = .{},
|
|
72
|
-
};
|
|
73
|
-
|
|
74
68
|
/// Allows for forcing the value of specific RNG events during a Generation II battle `update` via
|
|
75
69
|
/// `overrides` and tracks `summaries` of information relevant to damage calculation.
|
|
76
70
|
pub const Calc = struct {
|
|
77
71
|
/// Overrides the normal behavior of the RNG during an `update` to force specific outcomes.
|
|
78
|
-
overrides:
|
|
72
|
+
overrides: Actions = .{},
|
|
79
73
|
/// Information relevant to damage calculation.
|
|
80
74
|
summaries: Summaries = .{},
|
|
81
75
|
|
|
82
76
|
pub fn overridden(
|
|
83
77
|
self: Calc,
|
|
84
78
|
player: Player,
|
|
79
|
+
hit: u3,
|
|
85
80
|
comptime field: Action.Field,
|
|
86
|
-
)
|
|
81
|
+
) ReturnType(field) {
|
|
87
82
|
if (!enabled) return null;
|
|
88
83
|
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
84
|
+
const val = switch (field) {
|
|
85
|
+
.damages => Damages.get(self.overrides.get(player).damages, hit),
|
|
86
|
+
.critical_hits => Criticals.get(self.overrides.get(player).critical_hits, hit),
|
|
87
|
+
else => val: {
|
|
88
|
+
assert(hit == 0);
|
|
89
|
+
break :val @field(self.overrides.get(player), @tagName(field));
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
|
|
92
93
|
return if (switch (@typeInfo(@TypeOf(val))) {
|
|
93
|
-
|
|
94
|
-
|
|
94
|
+
Enum => val != .None,
|
|
95
|
+
Int => val != 0,
|
|
95
96
|
else => unreachable,
|
|
96
97
|
}) val else null;
|
|
97
98
|
}
|
|
@@ -123,9 +124,10 @@ const Null = struct {
|
|
|
123
124
|
pub fn overridden(
|
|
124
125
|
self: Null,
|
|
125
126
|
player: Player,
|
|
127
|
+
hit: u3,
|
|
126
128
|
comptime field: Action.Field,
|
|
127
|
-
)
|
|
128
|
-
_ = .{ self, player };
|
|
129
|
+
) ReturnType(field) {
|
|
130
|
+
_ = .{ self, player, hit };
|
|
129
131
|
return null;
|
|
130
132
|
}
|
|
131
133
|
|
|
@@ -141,3 +143,11 @@ const Null = struct {
|
|
|
141
143
|
_ = .{ self, player };
|
|
142
144
|
}
|
|
143
145
|
};
|
|
146
|
+
|
|
147
|
+
fn ReturnType(comptime field: Action.Field) type {
|
|
148
|
+
return ?(switch (field) {
|
|
149
|
+
.damages => u8,
|
|
150
|
+
.critical_hits => Optional(bool),
|
|
151
|
+
else => util.FieldType(Action, field),
|
|
152
|
+
});
|
|
153
|
+
}
|
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,13 +19,18 @@ 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;
|
|
26
27
|
const Effectiveness = data.Effectiveness;
|
|
27
28
|
const TriAttack = data.TriAttack;
|
|
28
29
|
|
|
30
|
+
const Int = if (@hasField(std.builtin.Type, "int")) .int else .Int;
|
|
31
|
+
const Enum = if (@hasField(std.builtin.Type, "enum")) .@"enum" else .Enum;
|
|
32
|
+
const Struct = if (@hasField(std.builtin.Type, "struct")) .@"struct" else .Struct;
|
|
33
|
+
|
|
29
34
|
/// Actions taken by a hypothetical "chance player" that convey information about which RNG events
|
|
30
35
|
/// were observed during a Generation II battle `update`. This can additionally be provided as input
|
|
31
36
|
/// to the `update` call to override the normal behavior of the RNG in order to force specific
|
|
@@ -37,8 +42,8 @@ pub const Actions = extern struct {
|
|
|
37
42
|
p2: Action = .{},
|
|
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
|
|
|
@@ -52,15 +57,15 @@ pub const Actions = extern struct {
|
|
|
52
57
|
/// same shape if they have the same fields set (though those fields need not necessarily be
|
|
53
58
|
/// set to the same value).
|
|
54
59
|
pub fn matches(a: Actions, b: Actions) bool {
|
|
55
|
-
inline for (@typeInfo(Actions)
|
|
56
|
-
inline for (@typeInfo(Action)
|
|
60
|
+
inline for (@field(@typeInfo(Actions), @tagName(Struct)).fields) |player| {
|
|
61
|
+
inline for (@field(@typeInfo(Action), @tagName(Struct)).fields) |field| {
|
|
57
62
|
const a_val = @field(@field(a, player.name), field.name);
|
|
58
63
|
const b_val = @field(@field(b, player.name), field.name);
|
|
59
64
|
|
|
60
65
|
switch (@typeInfo(@TypeOf(a_val))) {
|
|
61
|
-
|
|
66
|
+
Enum => if ((@intFromEnum(a_val) > 0) != (@intFromEnum(b_val) > 0))
|
|
62
67
|
return false,
|
|
63
|
-
|
|
68
|
+
Int => if ((a_val > 0) != (b_val > 0)) return false,
|
|
64
69
|
else => unreachable,
|
|
65
70
|
}
|
|
66
71
|
}
|
|
@@ -82,10 +87,9 @@ pub const Actions = extern struct {
|
|
|
82
87
|
}
|
|
83
88
|
};
|
|
84
89
|
|
|
85
|
-
// TODO: ziglang/zig#19730
|
|
86
90
|
test Actions {
|
|
87
|
-
const a: Actions = .{ .p1 = .{ .hit = .true, .
|
|
88
|
-
const b: Actions = .{ .p1 = .{ .hit = .false, .
|
|
91
|
+
const a: Actions = .{ .p1 = .{ .hit = .true, .confused = .false, .damages = 245 } };
|
|
92
|
+
const b: Actions = .{ .p1 = .{ .hit = .false, .confused = .true, .damages = 246 } };
|
|
89
93
|
const c: Actions = .{ .p1 = .{ .hit = .true } };
|
|
90
94
|
|
|
91
95
|
try expect(a.eql(a));
|
|
@@ -101,11 +105,19 @@ test Actions {
|
|
|
101
105
|
try expect(!c.matches(a));
|
|
102
106
|
}
|
|
103
107
|
|
|
108
|
+
/// Observation made about a duration - whether the duration has started, been continued, or ended.
|
|
109
|
+
pub const Observation = enum { started, continuing, ended };
|
|
110
|
+
|
|
111
|
+
pub const Damages = Array(5, u8);
|
|
112
|
+
pub const Criticals = Array(5, Optional(bool));
|
|
113
|
+
|
|
104
114
|
/// Information about the RNG that was observed during a Generation II battle `update` for a
|
|
105
115
|
/// single player.
|
|
106
116
|
pub const Action = packed struct(u128) {
|
|
107
|
-
///
|
|
108
|
-
|
|
117
|
+
/// TODO
|
|
118
|
+
damages: Damages.T = 0,
|
|
119
|
+
// TODO
|
|
120
|
+
critical_hits: Criticals.T = 0,
|
|
109
121
|
|
|
110
122
|
/// If not None, the Player to be returned by Rolls.speedTie.
|
|
111
123
|
speed_tie: Optional(Player) = .None,
|
|
@@ -113,50 +125,58 @@ pub const Action = packed struct(u128) {
|
|
|
113
125
|
quick_claw: Optional(bool) = .None,
|
|
114
126
|
/// If not None, the value to return for Rolls.hit.
|
|
115
127
|
hit: Optional(bool) = .None,
|
|
116
|
-
/// If not None, the value to be returned by Rolls.criticalHit.
|
|
117
|
-
critical_hit: Optional(bool) = .None,
|
|
118
|
-
|
|
119
128
|
/// If not None, the value to return for Rolls.confused.
|
|
120
129
|
confused: Optional(bool) = .None,
|
|
130
|
+
|
|
121
131
|
/// If not None, the value to return for Rolls.attract.
|
|
122
132
|
attract: Optional(bool) = .None,
|
|
123
133
|
/// If not None, the value to return for Rolls.paralyzed.
|
|
124
134
|
paralyzed: Optional(bool) = .None,
|
|
125
135
|
/// If not None, the value to return for Rolls.defrost.
|
|
126
136
|
defrost: Optional(bool) = .None,
|
|
127
|
-
|
|
128
137
|
/// If not None, the value to be returned for Rolls.secondaryChance.
|
|
129
138
|
secondary_chance: Optional(bool) = .None,
|
|
139
|
+
|
|
130
140
|
/// If not None, the value to be returned for Rolls.item (Focus Band / King's Rock).
|
|
131
141
|
item: Optional(bool) = .None,
|
|
132
142
|
/// If not None, the value to be returned for Rolls.protect.
|
|
133
143
|
protect: Optional(bool) = .None,
|
|
134
144
|
/// If not None, the value to return for Rolls.triAttack.
|
|
135
145
|
tri_attack: Optional(TriAttack) = .None,
|
|
146
|
+
/// If not 0, the value to return for Rolls.tripleKick.
|
|
147
|
+
triple_kick: u2 = 0,
|
|
136
148
|
|
|
137
149
|
/// If not 0, (present - 1) * 40 should be returned as the base power for Rolls.present.
|
|
138
150
|
present: u3 = 0,
|
|
139
151
|
/// If not 0, magnitude + 3 should be returned as the number for Rolls.magnitude.
|
|
140
152
|
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.
|
|
153
|
+
/// If not 0, the amount of PP to deduct for Rolls.spite.
|
|
145
154
|
spite: u3 = 0,
|
|
146
|
-
/// If not None, the value to return for Rolls.conversion2.
|
|
147
|
-
conversion_2: Optional(Type) = .None,
|
|
148
|
-
|
|
149
155
|
/// If not 0, the move slot (1-4) to return in Rolls.moveSlot. If present as an override,
|
|
150
156
|
/// invalid values (eg. due to empty move slots or 0 PP) will be ignored.
|
|
151
|
-
move_slot:
|
|
157
|
+
move_slot: u3 = 0,
|
|
152
158
|
/// If not 0, the party slot (1-6) to return in Rolls.forceSwitch. If present as an override,
|
|
153
159
|
/// invalid values (eg. due to empty party slots or fainted members) will be ignored.
|
|
154
|
-
force_switch:
|
|
155
|
-
|
|
160
|
+
force_switch: u3 = 0,
|
|
156
161
|
/// If not 0, the value (2-5) to return for Rolls.distribution for multi hit.
|
|
157
|
-
multi_hit:
|
|
162
|
+
multi_hit: u3 = 0,
|
|
163
|
+
|
|
164
|
+
sleep: Optional(Observation) = .None,
|
|
165
|
+
/// TODO
|
|
166
|
+
confusion: Optional(Observation) = .None,
|
|
167
|
+
/// TODO
|
|
168
|
+
disable: Optional(Observation) = .None,
|
|
169
|
+
/// TODO
|
|
170
|
+
attacking: Optional(Observation) = .None,
|
|
171
|
+
/// TODO
|
|
172
|
+
binding: Optional(Observation) = .None,
|
|
173
|
+
/// TODO
|
|
174
|
+
encore: Optional(Observation) = .None,
|
|
175
|
+
|
|
158
176
|
/// If not 0, the value to by one of the Rolls.*Duration rolls.
|
|
159
|
-
duration:
|
|
177
|
+
duration: u3 = 0,
|
|
178
|
+
/// If not None, the value to return for Rolls.conversion2.
|
|
179
|
+
conversion_2: Optional(Type) = .None,
|
|
160
180
|
|
|
161
181
|
/// If not 0, psywave should be returned as the damage roll for Rolls.psywave.
|
|
162
182
|
psywave: u8 = 0,
|
|
@@ -164,8 +184,6 @@ pub const Action = packed struct(u128) {
|
|
|
164
184
|
/// If not None, the Move to return for Rolls.metronome.
|
|
165
185
|
metronome: Move = .None,
|
|
166
186
|
|
|
167
|
-
_: u48 = 0, // TODO
|
|
168
|
-
|
|
169
187
|
pub const Field = std.meta.FieldEnum(Action);
|
|
170
188
|
|
|
171
189
|
pub fn format(a: Action, comptime f: []const u8, o: std.fmt.FormatOptions, w: anytype) !void {
|
|
@@ -176,10 +194,10 @@ pub const Action = packed struct(u128) {
|
|
|
176
194
|
pub fn fmt(self: Action, writer: anytype, shape: bool) !void {
|
|
177
195
|
try writer.writeByte('(');
|
|
178
196
|
var printed = false;
|
|
179
|
-
inline for (@typeInfo(Action)
|
|
197
|
+
inline for (@field(@typeInfo(Action), @tagName(Struct)).fields) |field| {
|
|
180
198
|
const val = @field(self, field.name);
|
|
181
199
|
switch (@typeInfo(@TypeOf(val))) {
|
|
182
|
-
|
|
200
|
+
Enum => if (val != .None) {
|
|
183
201
|
if (printed) try writer.writeAll(", ");
|
|
184
202
|
if (shape) {
|
|
185
203
|
try writer.print("{s}:?", .{field.name});
|
|
@@ -193,7 +211,7 @@ pub const Action = packed struct(u128) {
|
|
|
193
211
|
}
|
|
194
212
|
printed = true;
|
|
195
213
|
},
|
|
196
|
-
|
|
214
|
+
Int => if (val != 0) {
|
|
197
215
|
if (printed) try writer.writeAll(", ");
|
|
198
216
|
if (shape) {
|
|
199
217
|
try writer.print("{s}:?", .{field.name});
|
|
@@ -255,19 +273,21 @@ pub fn Chance(comptime Rational: type) type {
|
|
|
255
273
|
self.actions.get(player).hit = if (ok) .true else .false;
|
|
256
274
|
}
|
|
257
275
|
|
|
258
|
-
pub fn criticalHit(self: *Self, player: Player, crit: bool, rate: u8) Error!void {
|
|
276
|
+
pub fn criticalHit(self: *Self, player: Player, i: u3, crit: bool, rate: u8) Error!void {
|
|
259
277
|
if (!enabled) return;
|
|
260
278
|
|
|
261
279
|
const n = if (crit) rate else @as(u8, @intCast(256 - @as(u9, rate)));
|
|
262
280
|
try self.probability.update(n, 256);
|
|
263
|
-
self.actions.get(player)
|
|
281
|
+
var a = self.actions.get(player);
|
|
282
|
+
a.critical_hits = Criticals.set(a.critical_hits, i, if (crit) .true else .false);
|
|
264
283
|
}
|
|
265
284
|
|
|
266
|
-
pub fn damage(self: *Self, player: Player, roll: u8) Error!void {
|
|
285
|
+
pub fn damage(self: *Self, player: Player, i: u3, roll: u8) Error!void {
|
|
267
286
|
if (!enabled) return;
|
|
268
287
|
|
|
269
288
|
try self.probability.update(1, 39);
|
|
270
|
-
self.actions.get(player)
|
|
289
|
+
var a = self.actions.get(player);
|
|
290
|
+
a.damages = Damages.set(a.damages, i, roll);
|
|
271
291
|
}
|
|
272
292
|
|
|
273
293
|
pub fn confused(self: *Self, player: Player, cfz: bool) Error!void {
|
|
@@ -419,10 +439,10 @@ pub fn Chance(comptime Rational: type) type {
|
|
|
419
439
|
self.actions.get(player).multi_hit = n;
|
|
420
440
|
}
|
|
421
441
|
|
|
422
|
-
pub fn duration(self: *Self, player: Player, turns:
|
|
442
|
+
pub fn duration(self: *Self, player: Player, turns: u3) void {
|
|
423
443
|
if (!enabled) return;
|
|
424
444
|
|
|
425
|
-
self.actions.get(player).duration = if (options.key)
|
|
445
|
+
self.actions.get(player).duration = if (options.key) 2 else turns;
|
|
426
446
|
}
|
|
427
447
|
};
|
|
428
448
|
}
|
|
@@ -474,22 +494,22 @@ test "Chance.hit" {
|
|
|
474
494
|
test "Chance.criticalHit" {
|
|
475
495
|
var chance: Chance(rational.Rational(u64)) = .{ .probability = .{} };
|
|
476
496
|
|
|
477
|
-
try chance.criticalHit(.P1, true, 17);
|
|
478
|
-
try expectValue(Optional(bool).true, chance.actions.p1.
|
|
497
|
+
try chance.criticalHit(.P1, 0, true, 17);
|
|
498
|
+
try expectValue(Optional(bool).true, Criticals.get(chance.actions.p1.critical_hits, 0));
|
|
479
499
|
try expectProbability(&chance.probability, 17, 256);
|
|
480
500
|
|
|
481
501
|
chance.reset();
|
|
482
502
|
|
|
483
|
-
try chance.criticalHit(.P2, false, 5);
|
|
503
|
+
try chance.criticalHit(.P2, 1, false, 5);
|
|
484
504
|
try expectProbability(&chance.probability, 251, 256);
|
|
485
|
-
try expectValue(Optional(bool).false, chance.actions.p2.
|
|
505
|
+
try expectValue(Optional(bool).false, Criticals.get(chance.actions.p2.critical_hits, 1));
|
|
486
506
|
}
|
|
487
507
|
|
|
488
508
|
test "Chance.damage" {
|
|
489
509
|
var chance: Chance(rational.Rational(u64)) = .{ .probability = .{} };
|
|
490
510
|
|
|
491
|
-
try chance.damage(.P1,
|
|
492
|
-
try expectValue(
|
|
511
|
+
try chance.damage(.P1, 0, 219);
|
|
512
|
+
try expectValue(@as(u8, 219), Damages.get(chance.actions.p1.damages, 0));
|
|
493
513
|
try expectProbability(&chance.probability, 1, 39);
|
|
494
514
|
}
|
|
495
515
|
|
|
@@ -614,7 +634,7 @@ test "Chance.present" {
|
|
|
614
634
|
} else {
|
|
615
635
|
try expectProbability(&chance.probability, 25, 256);
|
|
616
636
|
}
|
|
617
|
-
try expectValue(4, chance.actions.p2.present);
|
|
637
|
+
try expectValue(@as(u3, 4), chance.actions.p2.present);
|
|
618
638
|
|
|
619
639
|
chance.reset();
|
|
620
640
|
|
|
@@ -624,7 +644,7 @@ test "Chance.present" {
|
|
|
624
644
|
} else {
|
|
625
645
|
try expectProbability(&chance.probability, 51, 256);
|
|
626
646
|
}
|
|
627
|
-
try expectValue(1, chance.actions.p1.present);
|
|
647
|
+
try expectValue(@as(u3, 1), chance.actions.p1.present);
|
|
628
648
|
}
|
|
629
649
|
|
|
630
650
|
test "Chance.magnitude" {
|
|
@@ -636,7 +656,7 @@ test "Chance.magnitude" {
|
|
|
636
656
|
} else {
|
|
637
657
|
try expectProbability(&chance.probability, 13, 256);
|
|
638
658
|
}
|
|
639
|
-
try expectValue(7, chance.actions.p2.magnitude);
|
|
659
|
+
try expectValue(@as(u3, 7), chance.actions.p2.magnitude);
|
|
640
660
|
|
|
641
661
|
chance.reset();
|
|
642
662
|
|
|
@@ -646,7 +666,7 @@ test "Chance.magnitude" {
|
|
|
646
666
|
} else {
|
|
647
667
|
try expectProbability(&chance.probability, 51, 256);
|
|
648
668
|
}
|
|
649
|
-
try expectValue(5, chance.actions.p1.magnitude);
|
|
669
|
+
try expectValue(@as(u3, 5), chance.actions.p1.magnitude);
|
|
650
670
|
}
|
|
651
671
|
|
|
652
672
|
test "Chance.tripleKick" {
|
|
@@ -654,7 +674,7 @@ test "Chance.tripleKick" {
|
|
|
654
674
|
|
|
655
675
|
try chance.tripleKick(.P1, 2);
|
|
656
676
|
try expectProbability(&chance.probability, 1, 3);
|
|
657
|
-
try expectValue(2, chance.actions.p1.triple_kick);
|
|
677
|
+
try expectValue(@as(u2, 2), chance.actions.p1.triple_kick);
|
|
658
678
|
}
|
|
659
679
|
|
|
660
680
|
test "Chance.spite" {
|
|
@@ -662,7 +682,7 @@ test "Chance.spite" {
|
|
|
662
682
|
|
|
663
683
|
try chance.spite(.P1, 3);
|
|
664
684
|
try expectProbability(&chance.probability, 1, 4);
|
|
665
|
-
try expectValue(3, chance.actions.p1.spite);
|
|
685
|
+
try expectValue(@as(u3, 3), chance.actions.p1.spite);
|
|
666
686
|
}
|
|
667
687
|
|
|
668
688
|
test "Chance.conversion2" {
|
|
@@ -689,7 +709,7 @@ test "Chance.psywave" {
|
|
|
689
709
|
|
|
690
710
|
try chance.psywave(.P2, 100, 150);
|
|
691
711
|
try expectProbability(&chance.probability, 1, 150);
|
|
692
|
-
try expectValue(100, chance.actions.p2.psywave);
|
|
712
|
+
try expectValue(@as(u8, 100), chance.actions.p2.psywave);
|
|
693
713
|
}
|
|
694
714
|
|
|
695
715
|
test "Chance.metronome" {
|
|
@@ -705,19 +725,19 @@ test "Chance.moveSlot" {
|
|
|
705
725
|
|
|
706
726
|
try chance.moveSlot(.P2, 2, 2);
|
|
707
727
|
try expectProbability(&chance.probability, 1, 2);
|
|
708
|
-
try expectValue(2, chance.actions.p2.move_slot);
|
|
728
|
+
try expectValue(@as(u3, 2), chance.actions.p2.move_slot);
|
|
709
729
|
|
|
710
730
|
chance.reset();
|
|
711
731
|
|
|
712
732
|
try chance.moveSlot(.P1, 1, 3);
|
|
713
733
|
try expectProbability(&chance.probability, 1, 3);
|
|
714
|
-
try expectValue(1, chance.actions.p1.move_slot);
|
|
734
|
+
try expectValue(@as(u3, 1), chance.actions.p1.move_slot);
|
|
715
735
|
|
|
716
736
|
chance.reset();
|
|
717
737
|
|
|
718
738
|
try chance.moveSlot(.P1, 4, 1);
|
|
719
739
|
try expectProbability(&chance.probability, 1, 1);
|
|
720
|
-
try expectValue(4, chance.actions.p1.move_slot);
|
|
740
|
+
try expectValue(@as(u3, 4), chance.actions.p1.move_slot);
|
|
721
741
|
}
|
|
722
742
|
|
|
723
743
|
test "Chance.forceSwitch" {
|
|
@@ -725,19 +745,19 @@ test "Chance.forceSwitch" {
|
|
|
725
745
|
|
|
726
746
|
try chance.forceSwitch(.P2, 2, 2);
|
|
727
747
|
try expectProbability(&chance.probability, 1, 2);
|
|
728
|
-
try expectValue(2, chance.actions.p2.force_switch);
|
|
748
|
+
try expectValue(@as(u3, 2), chance.actions.p2.force_switch);
|
|
729
749
|
|
|
730
750
|
chance.reset();
|
|
731
751
|
|
|
732
752
|
try chance.forceSwitch(.P1, 1, 3);
|
|
733
753
|
try expectProbability(&chance.probability, 1, 3);
|
|
734
|
-
try expectValue(1, chance.actions.p1.force_switch);
|
|
754
|
+
try expectValue(@as(u3, 1), chance.actions.p1.force_switch);
|
|
735
755
|
|
|
736
756
|
chance.reset();
|
|
737
757
|
|
|
738
758
|
try chance.forceSwitch(.P1, 4, 1);
|
|
739
759
|
try expectProbability(&chance.probability, 1, 1);
|
|
740
|
-
try expectValue(4, chance.actions.p1.force_switch);
|
|
760
|
+
try expectValue(@as(u3, 4), chance.actions.p1.force_switch);
|
|
741
761
|
}
|
|
742
762
|
|
|
743
763
|
test "Chance.multiHit" {
|
|
@@ -745,20 +765,20 @@ test "Chance.multiHit" {
|
|
|
745
765
|
|
|
746
766
|
try chance.multiHit(.P1, 3);
|
|
747
767
|
try expectProbability(&chance.probability, 3, 8);
|
|
748
|
-
try expectValue(3, chance.actions.p1.multi_hit);
|
|
768
|
+
try expectValue(@as(u3, 3), chance.actions.p1.multi_hit);
|
|
749
769
|
|
|
750
770
|
chance.reset();
|
|
751
771
|
|
|
752
772
|
try chance.multiHit(.P2, 5);
|
|
753
773
|
try expectProbability(&chance.probability, 1, 8);
|
|
754
|
-
try expectValue(5, chance.actions.p2.multi_hit);
|
|
774
|
+
try expectValue(@as(u3, 5), chance.actions.p2.multi_hit);
|
|
755
775
|
}
|
|
756
776
|
|
|
757
777
|
test "Chance.duration" {
|
|
758
778
|
var chance: Chance(rational.Rational(u64)) = .{ .probability = .{} };
|
|
759
779
|
|
|
760
780
|
chance.duration(.P1, 2);
|
|
761
|
-
try expectValue(2, chance.actions.p1.duration);
|
|
781
|
+
try expectValue(@as(u3, 2), chance.actions.p1.duration);
|
|
762
782
|
}
|
|
763
783
|
|
|
764
784
|
pub fn expectProbability(r: anytype, p: u64, q: u64) !void {
|
|
@@ -800,12 +820,12 @@ const Null = struct {
|
|
|
800
820
|
_ = .{ self, player, ok, accuracy };
|
|
801
821
|
}
|
|
802
822
|
|
|
803
|
-
pub fn criticalHit(self: Null, player: Player, crit: bool, rate: u8) Error!void {
|
|
804
|
-
_ = .{ self, player, crit, rate };
|
|
823
|
+
pub fn criticalHit(self: Null, player: Player, i: u3, crit: bool, rate: u8) Error!void {
|
|
824
|
+
_ = .{ self, player, i, crit, rate };
|
|
805
825
|
}
|
|
806
826
|
|
|
807
|
-
pub fn damage(self: Null, player: Player, roll: u8) Error!void {
|
|
808
|
-
_ = .{ self, player, roll };
|
|
827
|
+
pub fn damage(self: Null, player: Player, i: u3, roll: u8) Error!void {
|
|
828
|
+
_ = .{ self, player, i, roll };
|
|
809
829
|
}
|
|
810
830
|
|
|
811
831
|
pub fn confused(self: Null, player: Player, ok: bool) Error!void {
|
|
@@ -876,7 +896,7 @@ const Null = struct {
|
|
|
876
896
|
_ = .{ self, player, move, n };
|
|
877
897
|
}
|
|
878
898
|
|
|
879
|
-
pub fn duration(self: Null, player: Player, turns:
|
|
899
|
+
pub fn duration(self: Null, player: Player, turns: u3) void {
|
|
880
900
|
_ = .{ self, player, turns };
|
|
881
901
|
}
|
|
882
902
|
};
|
|
@@ -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.
|