@pkmn/engine 0.1.0-dev.c544e10e → 0.1.0-dev.cbdbb719
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 +41 -14
- 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 +3 -2
- package/build/pkg/index.js.map +1 -1
- package/build/pkg/protocol.js +4 -4
- package/build/pkg/protocol.js.map +1 -1
- package/build/test/display.js +8 -3
- package/build/test/display.js.map +1 -1
- package/build/tools/debug.js +2 -3
- package/build/tools/debug.js.map +1 -1
- package/build.zig +208 -81
- package/package.json +32 -21
- package/src/bin/install-pkmn-engine +25 -17
- package/src/lib/common/array.zig +77 -0
- package/src/lib/common/data.zig +4 -4
- package/src/lib/common/debug.zig +2 -2
- package/src/lib/common/js.zig +4 -2
- package/src/lib/common/optional.zig +14 -10
- package/src/lib/common/options.zig +2 -0
- package/src/lib/common/protocol.zig +73 -73
- package/src/lib/common/rational.zig +121 -27
- package/src/lib/common/rng.zig +7 -7
- package/src/lib/common/util.zig +50 -1
- package/src/lib/gen1/calc.zig +511 -131
- package/src/lib/gen1/chance.zig +374 -267
- package/src/lib/gen1/data/species.zig +1 -1
- package/src/lib/gen1/data.zig +15 -14
- package/src/lib/gen1/helpers.zig +96 -536
- package/src/lib/gen1/mechanics.zig +285 -189
- package/src/lib/gen2/calc.zig +34 -16
- package/src/lib/gen2/chance.zig +85 -492
- package/src/lib/gen2/data.zig +8 -7
- package/src/lib/gen2/generated.zig +1 -3
- package/src/lib/gen2/helpers.zig +41 -9
- package/src/lib/gen2/mechanics.zig +178 -121
- package/src/lib/{binding/node.zig → node.zig} +9 -12
- package/src/lib/pkmn.zig +32 -15
- 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 -329
package/src/lib/gen2/chance.zig
CHANGED
|
@@ -11,21 +11,29 @@ const rational = @import("../common/rational.zig");
|
|
|
11
11
|
const rng = @import("../common/rng.zig");
|
|
12
12
|
const util = @import("../common/util.zig");
|
|
13
13
|
|
|
14
|
+
const Array = @import("../common/array.zig").Array;
|
|
14
15
|
const Player = @import("../common/data.zig").Player;
|
|
15
16
|
const Optional = @import("../common/optional.zig").Optional;
|
|
16
17
|
|
|
17
|
-
const data = @import("
|
|
18
|
+
const data = @import("data.zig");
|
|
18
19
|
|
|
19
20
|
const enabled = options.chance;
|
|
20
21
|
const showdown = options.showdown;
|
|
21
22
|
|
|
22
23
|
const Gen12 = rng.Gen12;
|
|
23
24
|
|
|
25
|
+
const PointerType = util.PointerType;
|
|
26
|
+
const isPointerTo = util.isPointerTo;
|
|
27
|
+
|
|
24
28
|
const Move = data.Move;
|
|
25
29
|
const Type = data.Type;
|
|
26
30
|
const Effectiveness = data.Effectiveness;
|
|
27
31
|
const TriAttack = data.TriAttack;
|
|
28
32
|
|
|
33
|
+
const Int = if (@hasField(std.builtin.Type, "int")) .int else .Int;
|
|
34
|
+
const Enum = if (@hasField(std.builtin.Type, "enum")) .@"enum" else .Enum;
|
|
35
|
+
const Struct = if (@hasField(std.builtin.Type, "struct")) .@"struct" else .Struct;
|
|
36
|
+
|
|
29
37
|
/// Actions taken by a hypothetical "chance player" that convey information about which RNG events
|
|
30
38
|
/// were observed during a Generation II battle `update`. This can additionally be provided as input
|
|
31
39
|
/// to the `update` call to override the normal behavior of the RNG in order to force specific
|
|
@@ -37,17 +45,11 @@ pub const Actions = extern struct {
|
|
|
37
45
|
p2: Action = .{},
|
|
38
46
|
|
|
39
47
|
/// Returns the `Action` for the given `player`.
|
|
40
|
-
pub fn get(self: anytype, player: Player)
|
|
41
|
-
assert(
|
|
48
|
+
pub fn get(self: anytype, player: Player) PointerType(@TypeOf(self), Action) {
|
|
49
|
+
assert(isPointerTo(self, Actions));
|
|
42
50
|
return if (player == .P1) &self.p1 else &self.p2;
|
|
43
51
|
}
|
|
44
52
|
|
|
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
53
|
/// Returns true if `a` is equal to `b`.
|
|
52
54
|
pub fn eql(a: Actions, b: Actions) bool {
|
|
53
55
|
return @as(u128, @bitCast(a.p1)) == @as(u128, @bitCast(b.p1)) and
|
|
@@ -58,24 +60,15 @@ pub const Actions = extern struct {
|
|
|
58
60
|
/// same shape if they have the same fields set (though those fields need not necessarily be
|
|
59
61
|
/// set to the same value).
|
|
60
62
|
pub fn matches(a: Actions, b: Actions) bool {
|
|
61
|
-
inline for (@typeInfo(Actions)
|
|
62
|
-
inline for (@typeInfo(Action)
|
|
63
|
+
inline for (@field(@typeInfo(Actions), @tagName(Struct)).fields) |player| {
|
|
64
|
+
inline for (@field(@typeInfo(Action), @tagName(Struct)).fields) |field| {
|
|
63
65
|
const a_val = @field(@field(a, player.name), field.name);
|
|
64
66
|
const b_val = @field(@field(b, player.name), field.name);
|
|
65
67
|
|
|
66
68
|
switch (@typeInfo(@TypeOf(a_val))) {
|
|
67
|
-
|
|
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
|
-
.Enum => if ((@intFromEnum(a_val) > 0) != (@intFromEnum(b_val) > 0))
|
|
69
|
+
Enum => if ((@intFromEnum(a_val) > 0) != (@intFromEnum(b_val) > 0))
|
|
77
70
|
return false,
|
|
78
|
-
|
|
71
|
+
Int => if ((a_val > 0) != (b_val > 0)) return false,
|
|
79
72
|
else => unreachable,
|
|
80
73
|
}
|
|
81
74
|
}
|
|
@@ -98,15 +91,9 @@ pub const Actions = extern struct {
|
|
|
98
91
|
};
|
|
99
92
|
|
|
100
93
|
test Actions {
|
|
101
|
-
const a: Actions = .{ .p1 = .{ .hit = .true, .
|
|
102
|
-
const b: Actions = .{ .p1 = .{ .hit = .false, .
|
|
94
|
+
const a: Actions = .{ .p1 = .{ .hit = .true, .confused = .false, .damages = 245 } };
|
|
95
|
+
const b: Actions = .{ .p1 = .{ .hit = .false, .confused = .true, .damages = 246 } };
|
|
103
96
|
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
97
|
|
|
111
98
|
try expect(a.eql(a));
|
|
112
99
|
try expect(!a.eql(b));
|
|
@@ -119,17 +106,21 @@ test Actions {
|
|
|
119
106
|
try expect(b.matches(a));
|
|
120
107
|
try expect(!a.matches(c));
|
|
121
108
|
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
109
|
}
|
|
127
110
|
|
|
111
|
+
/// Observation made about a duration - whether the duration has started, been continued, or ended.
|
|
112
|
+
pub const Observation = enum { started, continuing, ended };
|
|
113
|
+
|
|
114
|
+
pub const Damages = Array(5, u6);
|
|
115
|
+
pub const Criticals = Array(5, Optional(bool));
|
|
116
|
+
|
|
128
117
|
/// Information about the RNG that was observed during a Generation II battle `update` for a
|
|
129
118
|
/// single player.
|
|
130
119
|
pub const Action = packed struct(u128) {
|
|
131
|
-
///
|
|
132
|
-
|
|
120
|
+
/// TODO
|
|
121
|
+
damages: Damages.T = 0,
|
|
122
|
+
// TODO
|
|
123
|
+
critical_hits: Criticals.T = 0,
|
|
133
124
|
|
|
134
125
|
/// If not None, the Player to be returned by Rolls.speedTie.
|
|
135
126
|
speed_tie: Optional(Player) = .None,
|
|
@@ -137,50 +128,60 @@ pub const Action = packed struct(u128) {
|
|
|
137
128
|
quick_claw: Optional(bool) = .None,
|
|
138
129
|
/// If not None, the value to return for Rolls.hit.
|
|
139
130
|
hit: Optional(bool) = .None,
|
|
140
|
-
/// If not None, the value to be returned by Rolls.criticalHit.
|
|
141
|
-
critical_hit: Optional(bool) = .None,
|
|
142
|
-
|
|
143
131
|
/// If not None, the value to return for Rolls.confused.
|
|
144
132
|
confused: Optional(bool) = .None,
|
|
133
|
+
|
|
145
134
|
/// If not None, the value to return for Rolls.attract.
|
|
146
135
|
attract: Optional(bool) = .None,
|
|
147
136
|
/// If not None, the value to return for Rolls.paralyzed.
|
|
148
137
|
paralyzed: Optional(bool) = .None,
|
|
149
138
|
/// If not None, the value to return for Rolls.defrost.
|
|
150
139
|
defrost: Optional(bool) = .None,
|
|
151
|
-
|
|
152
140
|
/// If not None, the value to be returned for Rolls.secondaryChance.
|
|
153
141
|
secondary_chance: Optional(bool) = .None,
|
|
142
|
+
|
|
154
143
|
/// If not None, the value to be returned for Rolls.item (Focus Band / King's Rock).
|
|
155
144
|
item: Optional(bool) = .None,
|
|
156
145
|
/// If not None, the value to be returned for Rolls.protect.
|
|
157
146
|
protect: Optional(bool) = .None,
|
|
158
147
|
/// If not None, the value to return for Rolls.triAttack.
|
|
159
148
|
tri_attack: Optional(TriAttack) = .None,
|
|
149
|
+
/// If not 0, the value to return for Rolls.tripleKick.
|
|
150
|
+
triple_kick: u2 = 0,
|
|
160
151
|
|
|
161
152
|
/// If not 0, (present - 1) * 40 should be returned as the base power for Rolls.present.
|
|
162
153
|
present: u3 = 0,
|
|
163
154
|
/// If not 0, magnitude + 3 should be returned as the number for Rolls.magnitude.
|
|
164
155
|
magnitude: u3 = 0,
|
|
165
|
-
/// If not 0, the
|
|
166
|
-
triple_kick: u2 = 0,
|
|
167
|
-
|
|
168
|
-
/// If not 0, the amount of PP to deduct for Rolls.spite.
|
|
156
|
+
/// If not 0, the amount of PP to deduct for Rolls.spite.
|
|
169
157
|
spite: u3 = 0,
|
|
170
|
-
/// If not None, the value to return for Rolls.conversion2.
|
|
171
|
-
conversion_2: Optional(Type) = .None,
|
|
172
|
-
|
|
173
158
|
/// If not 0, the move slot (1-4) to return in Rolls.moveSlot. If present as an override,
|
|
174
159
|
/// invalid values (eg. due to empty move slots or 0 PP) will be ignored.
|
|
175
|
-
move_slot:
|
|
160
|
+
move_slot: u3 = 0,
|
|
176
161
|
/// If not 0, the party slot (1-6) to return in Rolls.forceSwitch. If present as an override,
|
|
177
162
|
/// invalid values (eg. due to empty party slots or fainted members) will be ignored.
|
|
178
|
-
force_switch:
|
|
179
|
-
|
|
163
|
+
force_switch: u3 = 0,
|
|
180
164
|
/// If not 0, the value (2-5) to return for Rolls.distribution for multi hit.
|
|
181
|
-
multi_hit:
|
|
165
|
+
multi_hit: u3 = 0,
|
|
166
|
+
|
|
167
|
+
_: u9 = 0,
|
|
168
|
+
|
|
182
169
|
/// If not 0, the value to by one of the Rolls.*Duration rolls.
|
|
183
170
|
duration: u4 = 0,
|
|
171
|
+
sleep: Optional(Observation) = .None,
|
|
172
|
+
/// TODO
|
|
173
|
+
confusion: Optional(Observation) = .None,
|
|
174
|
+
/// TODO
|
|
175
|
+
disable: Optional(Observation) = .None,
|
|
176
|
+
/// TODO
|
|
177
|
+
attacking: Optional(Observation) = .None,
|
|
178
|
+
/// TODO
|
|
179
|
+
binding: Optional(Observation) = .None,
|
|
180
|
+
/// TODO
|
|
181
|
+
encore: Optional(Observation) = .None,
|
|
182
|
+
|
|
183
|
+
/// If not None, the value to return for Rolls.conversion2.
|
|
184
|
+
conversion_2: Optional(Type) = .None,
|
|
184
185
|
|
|
185
186
|
/// If not 0, psywave should be returned as the damage roll for Rolls.psywave.
|
|
186
187
|
psywave: u8 = 0,
|
|
@@ -188,20 +189,8 @@ pub const Action = packed struct(u128) {
|
|
|
188
189
|
/// If not None, the Move to return for Rolls.metronome.
|
|
189
190
|
metronome: Move = .None,
|
|
190
191
|
|
|
191
|
-
_: u16 = 0,
|
|
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;
|
|
197
|
-
|
|
198
192
|
pub const Field = std.meta.FieldEnum(Action);
|
|
199
193
|
|
|
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
194
|
pub fn format(a: Action, comptime f: []const u8, o: std.fmt.FormatOptions, w: anytype) !void {
|
|
206
195
|
_ = .{ f, o };
|
|
207
196
|
try fmt(a, w, false);
|
|
@@ -210,22 +199,10 @@ pub const Action = packed struct(u128) {
|
|
|
210
199
|
pub fn fmt(self: Action, writer: anytype, shape: bool) !void {
|
|
211
200
|
try writer.writeByte('(');
|
|
212
201
|
var printed = false;
|
|
213
|
-
inline for (@typeInfo(Action)
|
|
202
|
+
inline for (@field(@typeInfo(Action), @tagName(Struct)).fields) |field| {
|
|
214
203
|
const val = @field(self, field.name);
|
|
215
204
|
switch (@typeInfo(@TypeOf(val))) {
|
|
216
|
-
|
|
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
|
-
.Enum => if (val != .None) {
|
|
205
|
+
Enum => if (val != .None) {
|
|
229
206
|
if (printed) try writer.writeAll(", ");
|
|
230
207
|
if (shape) {
|
|
231
208
|
try writer.print("{s}:?", .{field.name});
|
|
@@ -239,7 +216,7 @@ pub const Action = packed struct(u128) {
|
|
|
239
216
|
}
|
|
240
217
|
printed = true;
|
|
241
218
|
},
|
|
242
|
-
|
|
219
|
+
Int => if (val != 0) {
|
|
243
220
|
if (printed) try writer.writeAll(", ");
|
|
244
221
|
if (shape) {
|
|
245
222
|
try writer.print("{s}:?", .{field.name});
|
|
@@ -255,36 +232,6 @@ pub const Action = packed struct(u128) {
|
|
|
255
232
|
}
|
|
256
233
|
};
|
|
257
234
|
|
|
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
235
|
/// Tracks chance actions and their associated probability during a Generation II battle update when
|
|
289
236
|
/// `options.chance` is enabled.
|
|
290
237
|
pub fn Chance(comptime Rational: type) type {
|
|
@@ -297,37 +244,15 @@ pub fn Chance(comptime Rational: type) type {
|
|
|
297
244
|
/// RNG events were observed during a battle `update`.
|
|
298
245
|
actions: Actions = .{},
|
|
299
246
|
|
|
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
247
|
/// Possible error returned by operations tracking chance probability.
|
|
309
248
|
pub const Error = Rational.Error;
|
|
310
249
|
|
|
311
250
|
/// Convenience helper to clear fields which typically should be cleared between updates.
|
|
312
251
|
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
252
|
if (!enabled) return;
|
|
320
253
|
|
|
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]);
|
|
254
|
+
self.probability.reset();
|
|
255
|
+
self.actions = .{};
|
|
331
256
|
}
|
|
332
257
|
|
|
333
258
|
pub fn speedTie(self: *Self, p1: bool) Error!void {
|
|
@@ -353,19 +278,21 @@ pub fn Chance(comptime Rational: type) type {
|
|
|
353
278
|
self.actions.get(player).hit = if (ok) .true else .false;
|
|
354
279
|
}
|
|
355
280
|
|
|
356
|
-
pub fn criticalHit(self: *Self, player: Player, crit: bool, rate: u8) Error!void {
|
|
281
|
+
pub fn criticalHit(self: *Self, player: Player, i: u3, crit: bool, rate: u8) Error!void {
|
|
357
282
|
if (!enabled) return;
|
|
358
283
|
|
|
359
284
|
const n = if (crit) rate else @as(u8, @intCast(256 - @as(u9, rate)));
|
|
360
285
|
try self.probability.update(n, 256);
|
|
361
|
-
self.actions.get(player)
|
|
286
|
+
var a = self.actions.get(player);
|
|
287
|
+
a.critical_hits = Criticals.set(a.critical_hits, i, if (crit) .true else .false);
|
|
362
288
|
}
|
|
363
289
|
|
|
364
|
-
pub fn damage(self: *Self, player: Player, roll: u8) Error!void {
|
|
290
|
+
pub fn damage(self: *Self, player: Player, i: u3, roll: u8) Error!void {
|
|
365
291
|
if (!enabled) return;
|
|
366
292
|
|
|
367
293
|
try self.probability.update(1, 39);
|
|
368
|
-
self.actions.get(player)
|
|
294
|
+
var a = self.actions.get(player);
|
|
295
|
+
a.damages = Damages.set(a.damages, i, @intCast(roll - 216));
|
|
369
296
|
}
|
|
370
297
|
|
|
371
298
|
pub fn confused(self: *Self, player: Player, cfz: bool) Error!void {
|
|
@@ -517,122 +444,10 @@ pub fn Chance(comptime Rational: type) type {
|
|
|
517
444
|
self.actions.get(player).multi_hit = n;
|
|
518
445
|
}
|
|
519
446
|
|
|
520
|
-
pub fn duration(
|
|
521
|
-
self: *Self,
|
|
522
|
-
comptime field: Duration.Field,
|
|
523
|
-
player: Player,
|
|
524
|
-
target: Player,
|
|
525
|
-
turns: u4,
|
|
526
|
-
) void {
|
|
527
|
-
if (!enabled) return;
|
|
528
|
-
|
|
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
|
-
self.actions.get(player).duration = if (options.key) 1 else turns;
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
pub fn sleep(self: *Self, player: Player, turns: u4) Error!void {
|
|
447
|
+
pub fn duration(self: *Self, player: Player, turns: u4) void {
|
|
538
448
|
if (!enabled) return;
|
|
539
449
|
|
|
540
|
-
|
|
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
|
-
}
|
|
450
|
+
self.actions.get(player).duration = if (options.key) 2 else turns;
|
|
636
451
|
}
|
|
637
452
|
};
|
|
638
453
|
}
|
|
@@ -684,22 +499,22 @@ test "Chance.hit" {
|
|
|
684
499
|
test "Chance.criticalHit" {
|
|
685
500
|
var chance: Chance(rational.Rational(u64)) = .{ .probability = .{} };
|
|
686
501
|
|
|
687
|
-
try chance.criticalHit(.P1, true, 17);
|
|
688
|
-
try expectValue(Optional(bool).true, chance.actions.p1.
|
|
502
|
+
try chance.criticalHit(.P1, 0, true, 17);
|
|
503
|
+
try expectValue(Optional(bool).true, Criticals.get(chance.actions.p1.critical_hits, 0));
|
|
689
504
|
try expectProbability(&chance.probability, 17, 256);
|
|
690
505
|
|
|
691
506
|
chance.reset();
|
|
692
507
|
|
|
693
|
-
try chance.criticalHit(.P2, false, 5);
|
|
508
|
+
try chance.criticalHit(.P2, 1, false, 5);
|
|
694
509
|
try expectProbability(&chance.probability, 251, 256);
|
|
695
|
-
try expectValue(Optional(bool).false, chance.actions.p2.
|
|
510
|
+
try expectValue(Optional(bool).false, Criticals.get(chance.actions.p2.critical_hits, 1));
|
|
696
511
|
}
|
|
697
512
|
|
|
698
513
|
test "Chance.damage" {
|
|
699
514
|
var chance: Chance(rational.Rational(u64)) = .{ .probability = .{} };
|
|
700
515
|
|
|
701
|
-
try chance.damage(.P1,
|
|
702
|
-
try expectValue(@as(
|
|
516
|
+
try chance.damage(.P1, 0, 219);
|
|
517
|
+
try expectValue(@as(u6, 3), Damages.get(chance.actions.p1.damages, 0));
|
|
703
518
|
try expectProbability(&chance.probability, 1, 39);
|
|
704
519
|
}
|
|
705
520
|
|
|
@@ -915,19 +730,19 @@ test "Chance.moveSlot" {
|
|
|
915
730
|
|
|
916
731
|
try chance.moveSlot(.P2, 2, 2);
|
|
917
732
|
try expectProbability(&chance.probability, 1, 2);
|
|
918
|
-
try expectValue(@as(
|
|
733
|
+
try expectValue(@as(u3, 2), chance.actions.p2.move_slot);
|
|
919
734
|
|
|
920
735
|
chance.reset();
|
|
921
736
|
|
|
922
737
|
try chance.moveSlot(.P1, 1, 3);
|
|
923
738
|
try expectProbability(&chance.probability, 1, 3);
|
|
924
|
-
try expectValue(@as(
|
|
739
|
+
try expectValue(@as(u3, 1), chance.actions.p1.move_slot);
|
|
925
740
|
|
|
926
741
|
chance.reset();
|
|
927
742
|
|
|
928
743
|
try chance.moveSlot(.P1, 4, 1);
|
|
929
744
|
try expectProbability(&chance.probability, 1, 1);
|
|
930
|
-
try expectValue(@as(
|
|
745
|
+
try expectValue(@as(u3, 4), chance.actions.p1.move_slot);
|
|
931
746
|
}
|
|
932
747
|
|
|
933
748
|
test "Chance.forceSwitch" {
|
|
@@ -935,19 +750,19 @@ test "Chance.forceSwitch" {
|
|
|
935
750
|
|
|
936
751
|
try chance.forceSwitch(.P2, 2, 2);
|
|
937
752
|
try expectProbability(&chance.probability, 1, 2);
|
|
938
|
-
try expectValue(@as(
|
|
753
|
+
try expectValue(@as(u3, 2), chance.actions.p2.force_switch);
|
|
939
754
|
|
|
940
755
|
chance.reset();
|
|
941
756
|
|
|
942
757
|
try chance.forceSwitch(.P1, 1, 3);
|
|
943
758
|
try expectProbability(&chance.probability, 1, 3);
|
|
944
|
-
try expectValue(@as(
|
|
759
|
+
try expectValue(@as(u3, 1), chance.actions.p1.force_switch);
|
|
945
760
|
|
|
946
761
|
chance.reset();
|
|
947
762
|
|
|
948
763
|
try chance.forceSwitch(.P1, 4, 1);
|
|
949
764
|
try expectProbability(&chance.probability, 1, 1);
|
|
950
|
-
try expectValue(@as(
|
|
765
|
+
try expectValue(@as(u3, 4), chance.actions.p1.force_switch);
|
|
951
766
|
}
|
|
952
767
|
|
|
953
768
|
test "Chance.multiHit" {
|
|
@@ -955,212 +770,20 @@ test "Chance.multiHit" {
|
|
|
955
770
|
|
|
956
771
|
try chance.multiHit(.P1, 3);
|
|
957
772
|
try expectProbability(&chance.probability, 3, 8);
|
|
958
|
-
try expectValue(@as(
|
|
773
|
+
try expectValue(@as(u3, 3), chance.actions.p1.multi_hit);
|
|
959
774
|
|
|
960
775
|
chance.reset();
|
|
961
776
|
|
|
962
777
|
try chance.multiHit(.P2, 5);
|
|
963
778
|
try expectProbability(&chance.probability, 1, 8);
|
|
964
|
-
try expectValue(@as(
|
|
779
|
+
try expectValue(@as(u3, 5), chance.actions.p2.multi_hit);
|
|
965
780
|
}
|
|
966
781
|
|
|
967
782
|
test "Chance.duration" {
|
|
968
783
|
var chance: Chance(rational.Rational(u64)) = .{ .probability = .{} };
|
|
969
784
|
|
|
970
|
-
chance.duration(.
|
|
785
|
+
chance.duration(.P1, 2);
|
|
971
786
|
try expectValue(@as(u4, 2), chance.actions.p1.duration);
|
|
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
|
-
}
|
|
1164
787
|
}
|
|
1165
788
|
|
|
1166
789
|
pub fn expectProbability(r: anytype, p: u64, q: u64) !void {
|
|
@@ -1202,12 +825,12 @@ const Null = struct {
|
|
|
1202
825
|
_ = .{ self, player, ok, accuracy };
|
|
1203
826
|
}
|
|
1204
827
|
|
|
1205
|
-
pub fn criticalHit(self: Null, player: Player, crit: bool, rate: u8) Error!void {
|
|
1206
|
-
_ = .{ self, player, crit, rate };
|
|
828
|
+
pub fn criticalHit(self: Null, player: Player, i: u3, crit: bool, rate: u8) Error!void {
|
|
829
|
+
_ = .{ self, player, i, crit, rate };
|
|
1207
830
|
}
|
|
1208
831
|
|
|
1209
|
-
pub fn damage(self: Null, player: Player, roll: u8) Error!void {
|
|
1210
|
-
_ = .{ self, player, roll };
|
|
832
|
+
pub fn damage(self: Null, player: Player, i: u3, roll: u8) Error!void {
|
|
833
|
+
_ = .{ self, player, i, roll };
|
|
1211
834
|
}
|
|
1212
835
|
|
|
1213
836
|
pub fn confused(self: Null, player: Player, ok: bool) Error!void {
|
|
@@ -1278,37 +901,7 @@ const Null = struct {
|
|
|
1278
901
|
_ = .{ self, player, move, n };
|
|
1279
902
|
}
|
|
1280
903
|
|
|
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 {
|
|
904
|
+
pub fn duration(self: Null, player: Player, turns: u4) void {
|
|
1312
905
|
_ = .{ self, player, turns };
|
|
1313
906
|
}
|
|
1314
907
|
};
|