@pkmn/engine 0.1.0-dev.3a62fd35 → 0.1.0-dev.3de821b9
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 +13 -11
- package/build/pkg/addon.js +6 -7
- package/build/pkg/addon.js.map +1 -1
- package/build/pkg/data.d.ts +2 -3
- 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 +32 -50
- package/package.json +24 -17
- package/src/bin/install-pkmn-engine +13 -5
- package/src/lib/common/debug.zig +2 -2
- package/src/lib/common/options.zig +2 -0
- package/src/lib/common/protocol.zig +11 -9
- package/src/lib/common/rational.zig +102 -12
- package/src/lib/common/rng.zig +6 -6
- package/src/lib/gen1/calc.zig +480 -92
- package/src/lib/gen1/chance.zig +384 -268
- package/src/lib/gen1/data/species.zig +1 -1
- package/src/lib/gen1/data.zig +3 -3
- package/src/lib/gen1/helpers.zig +90 -534
- package/src/lib/gen1/mechanics.zig +266 -158
- package/src/lib/gen2/chance.zig +8 -440
- package/src/lib/gen2/helpers.zig +37 -7
- package/src/lib/gen2/mechanics.zig +119 -61
- package/src/lib/pkmn.zig +4 -12
- 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/build.zig
CHANGED
|
@@ -1,26 +1,6 @@
|
|
|
1
1
|
const std = @import("std");
|
|
2
2
|
const builtin = @import("builtin");
|
|
3
3
|
|
|
4
|
-
pub const Options = struct {
|
|
5
|
-
showdown: ?bool = null,
|
|
6
|
-
log: ?bool = null,
|
|
7
|
-
chance: ?bool = null,
|
|
8
|
-
calc: ?bool = null,
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
pub fn module(b: *std.Build, options: Options) *std.Build.Module {
|
|
12
|
-
const dirname = comptime std.fs.path.dirname(@src().file) orelse ".";
|
|
13
|
-
const build_options = b.addOptions();
|
|
14
|
-
build_options.addOption(?bool, "showdown", options.showdown);
|
|
15
|
-
build_options.addOption(?bool, "log", options.log);
|
|
16
|
-
build_options.addOption(?bool, "chance", options.chance);
|
|
17
|
-
build_options.addOption(?bool, "calc", options.calc);
|
|
18
|
-
return b.createModule(.{
|
|
19
|
-
.root_source_file = .{ .path = dirname ++ "/src/lib/pkmn.zig" },
|
|
20
|
-
.imports = &.{.{ .name = "build_options", .module = build_options.createModule() }},
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
|
|
24
4
|
pub fn build(b: *std.Build) !void {
|
|
25
5
|
const target = b.standardTargetOptions(.{});
|
|
26
6
|
const optimize = b.standardOptimizeOption(.{});
|
|
@@ -44,7 +24,7 @@ pub fn build(b: *std.Build) !void {
|
|
|
44
24
|
defer parsed.deinit();
|
|
45
25
|
const version = parsed.value.object.get("version").?.string;
|
|
46
26
|
const description = parsed.value.object.get("description").?.string;
|
|
47
|
-
var repository = std.mem.
|
|
27
|
+
var repository = std.mem.splitSequence(u8, parsed.value.object.get("repository").?.string, ":");
|
|
48
28
|
std.debug.assert(std.mem.eql(u8, repository.first(), "github"));
|
|
49
29
|
|
|
50
30
|
const showdown =
|
|
@@ -61,22 +41,29 @@ pub fn build(b: *std.Build) !void {
|
|
|
61
41
|
|
|
62
42
|
const name = if (showdown) "pkmn-showdown" else "pkmn";
|
|
63
43
|
|
|
44
|
+
const module = b.addModule("pkmn", .{
|
|
45
|
+
.root_source_file = b.path("src/lib/pkmn.zig"),
|
|
46
|
+
.optimize = optimize,
|
|
47
|
+
.target = target,
|
|
48
|
+
.imports = &.{.{ .name = "build_options", .module = options.createModule() }},
|
|
49
|
+
});
|
|
50
|
+
|
|
64
51
|
var c = false;
|
|
65
52
|
if (node_headers) |headers| {
|
|
66
53
|
const addon = b.fmt("{s}.node", .{name});
|
|
67
54
|
const lib = b.addSharedLibrary(.{
|
|
68
55
|
.name = addon,
|
|
69
|
-
.root_source_file = .
|
|
56
|
+
.root_source_file = b.path("src/lib/node.zig"),
|
|
70
57
|
.optimize = optimize,
|
|
71
58
|
.target = target,
|
|
72
59
|
.strip = strip,
|
|
73
60
|
.pic = pic,
|
|
74
61
|
});
|
|
75
62
|
lib.root_module.addOptions("build_options", options);
|
|
76
|
-
lib.addSystemIncludePath(.
|
|
63
|
+
lib.addSystemIncludePath(b.path(headers));
|
|
77
64
|
lib.linkLibC();
|
|
78
65
|
if (node_import_lib) |il| {
|
|
79
|
-
lib.addObjectFile(.
|
|
66
|
+
lib.addObjectFile(b.path(il));
|
|
80
67
|
} else if (target.result.os.tag == .windows) {
|
|
81
68
|
try std.io.getStdErr().writeAll("Must provide --node-import-library path on Windows\n");
|
|
82
69
|
std.process.exit(1);
|
|
@@ -84,7 +71,7 @@ pub fn build(b: *std.Build) !void {
|
|
|
84
71
|
lib.linker_allow_shlib_undefined = true;
|
|
85
72
|
maybeStrip(b, lib, b.getInstallStep(), strip, cmd);
|
|
86
73
|
// Always emit to build/lib because this is where the driver code expects to find it
|
|
87
|
-
// TODO
|
|
74
|
+
// TODO: ziglang/zig#2231 - using the following used to work (though was hacky):
|
|
88
75
|
//
|
|
89
76
|
// lib.emit_bin = .{ .emit_to = b.fmt("build/lib/{s}", .{addon}) };
|
|
90
77
|
// b.getInstallStep().dependOn(&lib.step);
|
|
@@ -95,7 +82,7 @@ pub fn build(b: *std.Build) !void {
|
|
|
95
82
|
} else if (wasm) {
|
|
96
83
|
const exe = b.addExecutable(.{
|
|
97
84
|
.name = name,
|
|
98
|
-
.root_source_file = .
|
|
85
|
+
.root_source_file = b.path("src/lib/wasm.zig"),
|
|
99
86
|
.optimize = switch (optimize) {
|
|
100
87
|
.ReleaseFast, .ReleaseSafe => .ReleaseSmall,
|
|
101
88
|
else => optimize,
|
|
@@ -121,7 +108,7 @@ pub fn build(b: *std.Build) !void {
|
|
|
121
108
|
const sh = b.addSystemCommand(&.{ opt.?, "-O4" });
|
|
122
109
|
sh.addArtifactArg(exe);
|
|
123
110
|
sh.addArg("-o");
|
|
124
|
-
sh.addFileArg(.
|
|
111
|
+
sh.addFileArg(b.path(out));
|
|
125
112
|
b.getInstallStep().dependOn(&sh.step);
|
|
126
113
|
} else {
|
|
127
114
|
b.getInstallStep().dependOn(&b.addInstallArtifact(exe, .{
|
|
@@ -131,7 +118,7 @@ pub fn build(b: *std.Build) !void {
|
|
|
131
118
|
} else if (dynamic) {
|
|
132
119
|
const lib = b.addSharedLibrary(.{
|
|
133
120
|
.name = name,
|
|
134
|
-
.root_source_file = .
|
|
121
|
+
.root_source_file = b.path("src/lib/c.zig"),
|
|
135
122
|
.version = try std.SemanticVersion.parse(version),
|
|
136
123
|
.optimize = optimize,
|
|
137
124
|
.target = target,
|
|
@@ -139,21 +126,21 @@ pub fn build(b: *std.Build) !void {
|
|
|
139
126
|
.pic = pic,
|
|
140
127
|
});
|
|
141
128
|
lib.root_module.addOptions("build_options", options);
|
|
142
|
-
lib.addIncludePath(.
|
|
129
|
+
lib.addIncludePath(b.path("src/include"));
|
|
143
130
|
maybeStrip(b, lib, b.getInstallStep(), strip, cmd);
|
|
144
131
|
b.installArtifact(lib);
|
|
145
132
|
c = true;
|
|
146
133
|
} else {
|
|
147
134
|
const lib = b.addStaticLibrary(.{
|
|
148
135
|
.name = name,
|
|
149
|
-
.root_source_file = .
|
|
136
|
+
.root_source_file = b.path("src/lib/c.zig"),
|
|
150
137
|
.optimize = optimize,
|
|
151
138
|
.target = target,
|
|
152
139
|
.strip = strip,
|
|
153
140
|
.pic = pic,
|
|
154
141
|
});
|
|
155
142
|
lib.root_module.addOptions("build_options", options);
|
|
156
|
-
lib.addIncludePath(.
|
|
143
|
+
lib.addIncludePath(b.path("src/include"));
|
|
157
144
|
lib.bundle_compiler_rt = true;
|
|
158
145
|
maybeStrip(b, lib, b.getInstallStep(), strip, cmd);
|
|
159
146
|
if (emit_asm) {
|
|
@@ -176,14 +163,18 @@ pub fn build(b: *std.Build) !void {
|
|
|
176
163
|
|
|
177
164
|
if (c) {
|
|
178
165
|
const header = b.addInstallFileWithDir(
|
|
179
|
-
.
|
|
166
|
+
b.path("src/include/pkmn.h"),
|
|
180
167
|
.header,
|
|
181
168
|
"pkmn.h",
|
|
182
169
|
);
|
|
183
170
|
b.getInstallStep().dependOn(&header.step);
|
|
184
171
|
|
|
185
172
|
const pc = b.fmt("lib{s}.pc", .{name});
|
|
186
|
-
const file = try
|
|
173
|
+
const file = try std.fs.path.relative(
|
|
174
|
+
b.allocator,
|
|
175
|
+
try std.process.getCwdAlloc(b.allocator),
|
|
176
|
+
try b.cache_root.join(b.allocator, &.{pc}),
|
|
177
|
+
);
|
|
187
178
|
const pkgconfig_file = try std.fs.cwd().createFile(file, .{});
|
|
188
179
|
|
|
189
180
|
const dirname = comptime std.fs.path.dirname(@src().file) orelse ".";
|
|
@@ -218,12 +209,8 @@ pub fn build(b: *std.Build) !void {
|
|
|
218
209
|
|
|
219
210
|
var exes = std.ArrayList(*std.Build.Step.Compile).init(b.allocator);
|
|
220
211
|
const tools: ToolConfig = .{
|
|
221
|
-
.
|
|
222
|
-
|
|
223
|
-
.log = log,
|
|
224
|
-
.chance = chance,
|
|
225
|
-
.calc = calc,
|
|
226
|
-
},
|
|
212
|
+
.showdown = showdown,
|
|
213
|
+
.module = module,
|
|
227
214
|
.general = config,
|
|
228
215
|
.tool = .{
|
|
229
216
|
.tests = if (tests.build) tests else null,
|
|
@@ -294,7 +281,6 @@ const TestStep = struct {
|
|
|
294
281
|
|
|
295
282
|
pub fn create(b: *std.Build, options: *std.Build.Step.Options, config: Config) *TestStep {
|
|
296
283
|
const coverage = b.option([]const u8, "test-coverage", "Generate test coverage");
|
|
297
|
-
const test_file = b.option([]const u8, "test-file", "Input file for test");
|
|
298
284
|
const test_filter =
|
|
299
285
|
b.option([]const u8, "test-filter", "Skip tests that do not match filter");
|
|
300
286
|
|
|
@@ -302,13 +288,8 @@ const TestStep = struct {
|
|
|
302
288
|
const step = std.Build.Step.init(.{ .id = .custom, .name = "Run all tests", .owner = b });
|
|
303
289
|
self.* = .{ .step = step, .build = test_filter == null };
|
|
304
290
|
|
|
305
|
-
const path = test_file orelse "src/lib/test.zig";
|
|
306
291
|
const tests = b.addTest(.{
|
|
307
|
-
.
|
|
308
|
-
std.fs.path.basename(std.fs.path.dirname(path).?),
|
|
309
|
-
std.fs.path.stem(std.fs.path.basename(path)),
|
|
310
|
-
}),
|
|
311
|
-
.root_source_file = .{ .path = path },
|
|
292
|
+
.root_source_file = b.path("src/lib/test.zig"),
|
|
312
293
|
.optimize = config.optimize,
|
|
313
294
|
.target = config.target,
|
|
314
295
|
.filter = test_filter,
|
|
@@ -328,7 +309,8 @@ const TestStep = struct {
|
|
|
328
309
|
};
|
|
329
310
|
|
|
330
311
|
const ToolConfig = struct {
|
|
331
|
-
|
|
312
|
+
showdown: ?bool,
|
|
313
|
+
module: *std.Build.Module,
|
|
332
314
|
general: Config,
|
|
333
315
|
tool: struct {
|
|
334
316
|
tests: ?*TestStep,
|
|
@@ -345,18 +327,18 @@ fn tool(b: *std.Build, path: []const u8, config: ToolConfig) !?*std.Build.Step.R
|
|
|
345
327
|
var name = config.tool.name orelse std.fs.path.basename(path);
|
|
346
328
|
const index = std.mem.lastIndexOfScalar(u8, name, '.');
|
|
347
329
|
if (index) |i| name = name[0..i];
|
|
348
|
-
if (config.
|
|
330
|
+
if (config.showdown orelse false) name = b.fmt("{s}-showdown", .{name});
|
|
349
331
|
|
|
350
332
|
const exe = b.addExecutable(.{
|
|
351
333
|
.name = name,
|
|
352
|
-
.root_source_file = .
|
|
334
|
+
.root_source_file = b.path(path),
|
|
353
335
|
.target = config.general.target,
|
|
354
336
|
.optimize = config.general.optimize,
|
|
355
337
|
.single_threaded = true,
|
|
356
338
|
.strip = config.general.strip,
|
|
357
339
|
.pic = config.general.pic,
|
|
358
340
|
});
|
|
359
|
-
exe.root_module.addImport("pkmn",
|
|
341
|
+
exe.root_module.addImport("pkmn", config.module);
|
|
360
342
|
|
|
361
343
|
if (config.tool.tests) |ts| ts.step.dependOn(&exe.step);
|
|
362
344
|
config.tool.exes.append(exe) catch @panic("OOM");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pkmn/engine",
|
|
3
|
-
"version": "0.1.0-dev.
|
|
3
|
+
"version": "0.1.0-dev.3de821b9",
|
|
4
4
|
"description": "A minimal, complete, Pokémon battle simulation engine optimized for performance",
|
|
5
5
|
"repository": "github:pkmn/engine",
|
|
6
6
|
"license": "MIT",
|
|
@@ -31,7 +31,6 @@
|
|
|
31
31
|
"build/test/display.js",
|
|
32
32
|
"build/tools/debug.js.map",
|
|
33
33
|
"build/tools/debug.js",
|
|
34
|
-
"src/bin/install-pkmn-engine",
|
|
35
34
|
"src/lib/common/battle.zig",
|
|
36
35
|
"src/lib/common/data.zig",
|
|
37
36
|
"src/lib/common/debug.zig",
|
|
@@ -76,31 +75,31 @@
|
|
|
76
75
|
"access": "public"
|
|
77
76
|
},
|
|
78
77
|
"dependencies": {
|
|
79
|
-
"@pkmn/data": "^0.
|
|
80
|
-
"@pkmn/protocol": "^0.6.
|
|
78
|
+
"@pkmn/data": "^0.9.11",
|
|
79
|
+
"@pkmn/protocol": "^0.6.25"
|
|
81
80
|
},
|
|
82
81
|
"devDependencies": {
|
|
83
|
-
"@pkmn/eslint-config": "^
|
|
84
|
-
"@pkmn/img": "^0.2.
|
|
85
|
-
"@pkmn/sets": "^5.1.
|
|
86
|
-
"@pkmn/sim": "0.
|
|
82
|
+
"@pkmn/eslint-config": "^8.1.0",
|
|
83
|
+
"@pkmn/img": "^0.2.31",
|
|
84
|
+
"@pkmn/sets": "^5.1.2",
|
|
85
|
+
"@pkmn/sim": "0.9.11",
|
|
87
86
|
"@types/html-minifier": "^4.0.5",
|
|
88
|
-
"@types/jest": "^29.5.
|
|
87
|
+
"@types/jest": "^29.5.12",
|
|
89
88
|
"@types/minimist": "^1.2.5",
|
|
90
89
|
"@types/mustache": "^4.2.5",
|
|
91
|
-
"@types/node": "^
|
|
92
|
-
"@vitest/coverage-v8": "^
|
|
93
|
-
"binaryen": "^
|
|
94
|
-
"eslint": "
|
|
90
|
+
"@types/node": "^22.0.2",
|
|
91
|
+
"@vitest/coverage-v8": "^2.0.5",
|
|
92
|
+
"binaryen": "^118.0.0",
|
|
93
|
+
"eslint": "<=8",
|
|
95
94
|
"html-minifier": "^4.0.0",
|
|
96
|
-
"json-stringify-pretty-compact": "
|
|
95
|
+
"json-stringify-pretty-compact": "4.0.0",
|
|
97
96
|
"minimist": "^1.2.8",
|
|
98
97
|
"mustache": "^4.2.0",
|
|
99
98
|
"source-map-support": "^0.5.21",
|
|
100
|
-
"table": "^6.8.
|
|
99
|
+
"table": "^6.8.2",
|
|
101
100
|
"trakr": "^0.2.0",
|
|
102
|
-
"typescript": "^5.
|
|
103
|
-
"vitest": "^
|
|
101
|
+
"typescript": "^5.5.4",
|
|
102
|
+
"vitest": "^2.0.5"
|
|
104
103
|
},
|
|
105
104
|
"scripts": {
|
|
106
105
|
"lint": "eslint --cache src --ext ts,js && eslint src/bin/*",
|
|
@@ -142,6 +141,14 @@
|
|
|
142
141
|
]
|
|
143
142
|
}
|
|
144
143
|
},
|
|
144
|
+
{
|
|
145
|
+
"files": [
|
|
146
|
+
"src/test/display.ts"
|
|
147
|
+
],
|
|
148
|
+
"rules": {
|
|
149
|
+
"@typescript-eslint/no-unnecessary-type-assertion": "off"
|
|
150
|
+
}
|
|
151
|
+
},
|
|
145
152
|
{
|
|
146
153
|
"files": [
|
|
147
154
|
"src/pkg/index.ts",
|
|
@@ -10,7 +10,7 @@ const path = require('path');
|
|
|
10
10
|
const {pipeline} = require('stream/promises');
|
|
11
11
|
const tty = require('tty');
|
|
12
12
|
|
|
13
|
-
const ZIG_VERSION = {major: 0, minor:
|
|
13
|
+
const ZIG_VERSION = {major: 0, minor: 13, patch: 0};
|
|
14
14
|
const DEV = ZIG_VERSION.dev ? `-dev.${ZIG_VERSION.dev}` : '';
|
|
15
15
|
const VERSION = `${ZIG_VERSION.major}.${ZIG_VERSION.minor}.${ZIG_VERSION.patch}${DEV}`;
|
|
16
16
|
const INDEX = 'https://ziglang.org/download/index.json';
|
|
@@ -370,8 +370,10 @@ const downloadImportLib = async () => {
|
|
|
370
370
|
const args = ['build', '-p', 'build', ...opts];
|
|
371
371
|
if (!process.env.DEBUG_PKMN_ENGINE) args.push('-Doptimize=ReleaseFast', '-Dstrip');
|
|
372
372
|
if (config.type === 'node') {
|
|
373
|
-
args.push(`-Dnode-headers=${headers}`);
|
|
374
|
-
if (process.platform === 'win32')
|
|
373
|
+
args.push(`-Dnode-headers=${path.relative(ROOT, headers)}`);
|
|
374
|
+
if (process.platform === 'win32') {
|
|
375
|
+
args.push(`-Dnode-import-library=${path.relative(ROOT, lib)}`);
|
|
376
|
+
}
|
|
375
377
|
} else {
|
|
376
378
|
args.push('-Dwasm');
|
|
377
379
|
}
|
|
@@ -386,8 +388,14 @@ const downloadImportLib = async () => {
|
|
|
386
388
|
const prefix = process.platform === 'win32' ? '' : 'lib';
|
|
387
389
|
const ext = process.platform === 'darwin'
|
|
388
390
|
? 'dylib' : process.platform === 'win32' ? 'dll' : 'so';
|
|
389
|
-
|
|
390
|
-
|
|
391
|
+
try {
|
|
392
|
+
const actual = path.join('build', 'lib', `${prefix}pkmn${suffix}.node.${ext}`);
|
|
393
|
+
fs.renameSync(actual, artifact);
|
|
394
|
+
} catch (err) {
|
|
395
|
+
// ziglang/zig#19743 changed this path
|
|
396
|
+
const actual = path.join('build', 'bin', `${prefix}pkmn${suffix}.node.${ext}`);
|
|
397
|
+
fs.renameSync(actual, artifact);
|
|
398
|
+
}
|
|
391
399
|
}
|
|
392
400
|
}
|
|
393
401
|
})().catch(e => {
|
package/src/lib/common/debug.zig
CHANGED
|
@@ -4,8 +4,8 @@ const debug = std.debug;
|
|
|
4
4
|
const io = std.io;
|
|
5
5
|
|
|
6
6
|
pub fn print(value: anytype) void {
|
|
7
|
-
debug.
|
|
8
|
-
defer debug.
|
|
7
|
+
debug.lockStdErr();
|
|
8
|
+
defer debug.unlockStdErr();
|
|
9
9
|
const stderr = io.getStdErr().writer();
|
|
10
10
|
|
|
11
11
|
nosuspend {
|
|
@@ -10,6 +10,7 @@ pub const Options = struct {
|
|
|
10
10
|
advance: ?bool = null,
|
|
11
11
|
ebc: ?bool = null,
|
|
12
12
|
key: ?bool = null,
|
|
13
|
+
miss: ?bool = null,
|
|
13
14
|
internal: ?bool = null,
|
|
14
15
|
};
|
|
15
16
|
|
|
@@ -25,6 +26,7 @@ pub const calc = get("calc", false);
|
|
|
25
26
|
pub const advance = get("advance", true);
|
|
26
27
|
pub const ebc = get("ebc", true);
|
|
27
28
|
pub const key = get("key", false);
|
|
29
|
+
pub const miss = get("miss", true);
|
|
28
30
|
pub const internal = get("internal", false);
|
|
29
31
|
|
|
30
32
|
fn get(comptime name: []const u8, default: bool) bool {
|
|
@@ -220,6 +220,7 @@ pub const Activate = enum(u8) {
|
|
|
220
220
|
BeatUp, // FIXME of
|
|
221
221
|
|
|
222
222
|
Magnitude,
|
|
223
|
+
Spite,
|
|
223
224
|
};
|
|
224
225
|
|
|
225
226
|
pub const Start = enum(u8) {
|
|
@@ -544,6 +545,7 @@ pub fn Log(comptime Writer: type) type {
|
|
|
544
545
|
// ident: ID, reason: Activate
|
|
545
546
|
// ident: ID, reason: .SubstituteBlock, m: <Move>
|
|
546
547
|
// ident: ID, reason: .Magnitude, num: u8
|
|
548
|
+
// ident: ID, reason: .Spite, m: <Move>, num: u8
|
|
547
549
|
pub fn activate(self: Self, args: anytype) Error!void {
|
|
548
550
|
if (!enabled) return;
|
|
549
551
|
|
|
@@ -561,6 +563,9 @@ pub fn Log(comptime Writer: type) type {
|
|
|
561
563
|
assert(reason == .Magnitude);
|
|
562
564
|
try self.writer.writeByte(args[2]);
|
|
563
565
|
}
|
|
566
|
+
} else if (args.len == 4) {
|
|
567
|
+
assert(reason == .Spite);
|
|
568
|
+
try self.writer.writeAll(&.{ @intFromEnum(args[2]), args[3] });
|
|
564
569
|
}
|
|
565
570
|
}
|
|
566
571
|
|
|
@@ -859,7 +864,7 @@ pub const ByteStream = struct {
|
|
|
859
864
|
pub const Kind = enum { Move, Species, Type, Status, Item, Weather };
|
|
860
865
|
|
|
861
866
|
pub fn format(
|
|
862
|
-
|
|
867
|
+
gen: anytype,
|
|
863
868
|
a: []const u8,
|
|
864
869
|
b: ?[]const u8,
|
|
865
870
|
color: bool,
|
|
@@ -1202,14 +1207,11 @@ pub fn expectLog(
|
|
|
1202
1207
|
) !void {
|
|
1203
1208
|
if (!enabled) return;
|
|
1204
1209
|
|
|
1205
|
-
const color =
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
} else {
|
|
1211
|
-
break :color std.io.getStdErr().supportsAnsiEscapeCodes();
|
|
1212
|
-
}
|
|
1210
|
+
const color = if (std.process.hasEnvVarConstant("ZIG_DEBUG_COLOR"))
|
|
1211
|
+
true
|
|
1212
|
+
else switch (std.io.tty.detectConfig(std.io.getStdErr())) {
|
|
1213
|
+
.escape_codes => true,
|
|
1214
|
+
else => false,
|
|
1213
1215
|
};
|
|
1214
1216
|
|
|
1215
1217
|
expectEqualBytes(expected, actual, offset) catch |err| switch (err) {
|
|
@@ -43,8 +43,7 @@ pub fn Rational(comptime T: type) type {
|
|
|
43
43
|
/// Update the rational by multiplying its numerator by p and its denominator by q.
|
|
44
44
|
/// Both p and q must be >= 1, and if computable at comptime must have no common factors.
|
|
45
45
|
pub fn update(r: *Self, p: anytype, q: anytype) Error!void {
|
|
46
|
-
//
|
|
47
|
-
// std.debug.print("({d}/{d}) * ", .{ p, q });
|
|
46
|
+
// std.debug.print("({d}/{d}) * ", .{ p, q }); // DEBUG
|
|
48
47
|
assert(p >= 1);
|
|
49
48
|
assert(q >= 1);
|
|
50
49
|
|
|
@@ -202,23 +201,81 @@ pub fn Rational(comptime T: type) type {
|
|
|
202
201
|
};
|
|
203
202
|
}
|
|
204
203
|
|
|
205
|
-
// https://
|
|
204
|
+
// https://lemire.me/blog/greatest-common-divisor-the-extended-euclidean-algorithm-and-speed/
|
|
206
205
|
fn gcd(p: anytype, q: anytype) @TypeOf(p, q) {
|
|
207
206
|
assert(p >= 1);
|
|
208
207
|
assert(q >= 1);
|
|
209
208
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
209
|
+
const T = @TypeOf(p, q);
|
|
210
|
+
switch (@typeInfo(T)) {
|
|
211
|
+
.Int => {
|
|
212
|
+
var u: T = undefined;
|
|
213
|
+
var v: T = undefined;
|
|
214
|
+
if (p < q) {
|
|
215
|
+
u = q;
|
|
216
|
+
v = p;
|
|
217
|
+
} else {
|
|
218
|
+
u = p;
|
|
219
|
+
v = q;
|
|
220
|
+
}
|
|
221
|
+
assert(v <= u);
|
|
222
|
+
u %= v;
|
|
223
|
+
if (u == 0) return v;
|
|
224
|
+
|
|
225
|
+
const zu = @ctz(u);
|
|
226
|
+
const zv = @ctz(v);
|
|
227
|
+
const shift = @min(zu, zv);
|
|
228
|
+
u >>= @intCast(zu);
|
|
229
|
+
v >>= @intCast(zv);
|
|
230
|
+
|
|
231
|
+
while (true) {
|
|
232
|
+
const diff = u -% v;
|
|
233
|
+
if (u > v) {
|
|
234
|
+
u = v;
|
|
235
|
+
v = diff;
|
|
236
|
+
} else {
|
|
237
|
+
v -= u;
|
|
238
|
+
}
|
|
239
|
+
if (diff != 0) v >>= @intCast(@ctz(diff));
|
|
240
|
+
if (v == 0) break;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const result = u << @intCast(shift);
|
|
244
|
+
assert(result > 0);
|
|
245
|
+
return result;
|
|
246
|
+
},
|
|
247
|
+
else => {
|
|
248
|
+
var a = p;
|
|
249
|
+
var b = q;
|
|
250
|
+
var c: T = undefined;
|
|
251
|
+
|
|
252
|
+
while (b != 0) {
|
|
253
|
+
c = b;
|
|
254
|
+
b = @mod(a, b);
|
|
255
|
+
a = c;
|
|
256
|
+
}
|
|
213
257
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
a = c;
|
|
258
|
+
assert(a > 0);
|
|
259
|
+
return a;
|
|
260
|
+
},
|
|
218
261
|
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
test gcd {
|
|
265
|
+
const seed = if (@hasDecl(std.testing, "random_seed")) std.testing.random_seed else 0x12345678;
|
|
266
|
+
var prng = std.Random.DefaultPrng.init(seed);
|
|
267
|
+
var random = prng.random();
|
|
219
268
|
|
|
220
|
-
|
|
221
|
-
|
|
269
|
+
for (0..1000) |_| {
|
|
270
|
+
const a = random.int(u32);
|
|
271
|
+
const b = random.int(u32);
|
|
272
|
+
if (a == 0 or b == 0) continue;
|
|
273
|
+
|
|
274
|
+
try expectEqual(
|
|
275
|
+
gcd(a, b),
|
|
276
|
+
@as(u32, @intFromFloat(gcd(@as(f64, @floatFromInt(a)), @as(f64, @floatFromInt(b))))),
|
|
277
|
+
);
|
|
278
|
+
}
|
|
222
279
|
}
|
|
223
280
|
|
|
224
281
|
fn doTurn(r: anytype) !void {
|
|
@@ -355,3 +412,36 @@ test BigRational {
|
|
|
355
412
|
try s.setRatio(71, 78);
|
|
356
413
|
try expect((try s.order(r.val)) == .eq);
|
|
357
414
|
}
|
|
415
|
+
|
|
416
|
+
test "minimum" {
|
|
417
|
+
// TODO: ziglang/zig#21069
|
|
418
|
+
if (builtin.mode == .ReleaseFast or builtin.mode == .ReleaseSmall) {
|
|
419
|
+
return error.SkipZigTest;
|
|
420
|
+
}
|
|
421
|
+
var r = try BigRational.init(std.testing.allocator);
|
|
422
|
+
defer r.deinit();
|
|
423
|
+
var s = try std.math.big.Rational.init(std.testing.allocator);
|
|
424
|
+
defer s.deinit();
|
|
425
|
+
|
|
426
|
+
try r.reset();
|
|
427
|
+
|
|
428
|
+
try r.update(1, 2); // Speed Tie
|
|
429
|
+
for (0..2) |_| {
|
|
430
|
+
try r.update(1, 2); // Confusion
|
|
431
|
+
try r.update(1, 2); // Infatuation
|
|
432
|
+
try r.update(3, 4); // Paralysis
|
|
433
|
+
// Population Bomb
|
|
434
|
+
for (0..10) |_| {
|
|
435
|
+
try r.update(9, 10); // Accuracy
|
|
436
|
+
try r.update(1, 15); // Damage roll
|
|
437
|
+
try r.update(1, 24); // Critical Hit
|
|
438
|
+
try r.update(9, 10); // King's Rock non-proc
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
const ZEROS = std.math.pow(u310, 10, 31);
|
|
443
|
+
const n = 36472996377170786403;
|
|
444
|
+
const d: u310 = 146267071761884981524886149560653378220687632500762654519853056 * ZEROS;
|
|
445
|
+
try s.setRatio(n, d);
|
|
446
|
+
try expect((try s.order(r.val)) == .eq);
|
|
447
|
+
}
|
package/src/lib/common/rng.zig
CHANGED
|
@@ -66,6 +66,10 @@ pub const PSRNG = extern struct {
|
|
|
66
66
|
(@as(u64, self.range(u16, 0, 0x10000)) << 16) |
|
|
67
67
|
(@as(u64, self.range(u16, 0, 0x10000)));
|
|
68
68
|
}
|
|
69
|
+
|
|
70
|
+
pub fn Bound(comptime T: type) type {
|
|
71
|
+
return std.math.IntFittingRange(0, std.math.maxInt(T) + 1);
|
|
72
|
+
}
|
|
69
73
|
};
|
|
70
74
|
|
|
71
75
|
test PSRNG {
|
|
@@ -197,7 +201,7 @@ pub fn FixedRNG(comptime gen: comptime_int, comptime len: usize) type {
|
|
|
197
201
|
for (0..n) |_| _ = self.next();
|
|
198
202
|
}
|
|
199
203
|
|
|
200
|
-
pub fn range(self: *Self, comptime T: type, from: T, to: Bound(T)) T {
|
|
204
|
+
pub fn range(self: *Self, comptime T: type, from: T, to: PSRNG.Bound(T)) T {
|
|
201
205
|
assert(showdown);
|
|
202
206
|
return @intCast(@as(u64, self.next()) * (to - from) / divisor + from);
|
|
203
207
|
}
|
|
@@ -206,7 +210,7 @@ pub fn FixedRNG(comptime gen: comptime_int, comptime len: usize) type {
|
|
|
206
210
|
self: *Self,
|
|
207
211
|
comptime T: type,
|
|
208
212
|
numerator: T,
|
|
209
|
-
denominator: Bound(T),
|
|
213
|
+
denominator: PSRNG.Bound(T),
|
|
210
214
|
) bool {
|
|
211
215
|
assert(showdown);
|
|
212
216
|
assert(denominator > 0);
|
|
@@ -237,7 +241,3 @@ fn Output(comptime gen: comptime_int) type {
|
|
|
237
241
|
else => unreachable,
|
|
238
242
|
};
|
|
239
243
|
}
|
|
240
|
-
|
|
241
|
-
fn Bound(comptime T: type) type {
|
|
242
|
-
return std.math.IntFittingRange(0, std.math.maxInt(T) + 1);
|
|
243
|
-
}
|